From 9abf567d95a4e840df868ca993219175fbef8c22 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Mon, 23 Jul 2012 21:37:04 +0000 Subject: [PATCH 0001/2270] s390: Fix error handling and condition code of service call Invalid sccb addresses will cause specification or addressing exception. Lets add those checks. Furthermore, the good case (cc=0) was incorrect for KVM, we did not set the CC at all. We now use return codes < 0 as program checks and return codes > 0 as condition code values. Signed-off-by: Christian Borntraeger Signed-off-by: Alexander Graf --- target-s390x/kvm.c | 5 +++-- target-s390x/op_helper.c | 27 ++++++++++++++++++--------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 47008c24f2..07edf93690 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -273,9 +273,10 @@ static int kvm_sclp_service_call(CPUS390XState *env, struct kvm_run *run, code = env->regs[(ipbh0 & 0xf0) >> 4]; r = sclp_service_call(env, sccb, code); - if (r) { - setcc(env, 3); + if (r < 0) { + enter_pgmcheck(env, -r); } + setcc(env, r); return 0; } diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c index 7b7247316e..91dd8dc3fb 100644 --- a/target-s390x/op_helper.c +++ b/target-s390x/op_helper.c @@ -19,6 +19,8 @@ */ #include "cpu.h" +#include "memory.h" +#include "cputlb.h" #include "dyngen-exec.h" #include "host-utils.h" #include "helper.h" @@ -2366,6 +2368,9 @@ static void ext_interrupt(CPUS390XState *env, int type, uint32_t param, cpu_inject_ext(env, type, param, param64); } +/* + * ret < 0 indicates program check, ret = 0,1,2,3 -> cc + */ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code) { int r = 0; @@ -2375,10 +2380,12 @@ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code) printf("sclp(0x%x, 0x%" PRIx64 ")\n", sccb, code); #endif + /* basic checks */ + if (!memory_region_is_ram(phys_page_find(sccb >> TARGET_PAGE_BITS)->mr)) { + return -PGM_ADDRESSING; + } if (sccb & ~0x7ffffff8ul) { - fprintf(stderr, "KVM: invalid sccb address 0x%x\n", sccb); - r = -1; - goto out; + return -PGM_SPECIFICATION; } switch(code) { @@ -2405,22 +2412,24 @@ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code) #ifdef DEBUG_HELPER printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code); #endif - r = -1; + r = 3; break; } -out: return r; } /* SCLP service call */ uint32_t HELPER(servc)(uint32_t r1, uint64_t r2) { - if (sclp_service_call(env, r1, r2)) { - return 3; - } + int r; - return 0; + r = sclp_service_call(env, r1, r2); + if (r < 0) { + program_interrupt(env, -r, 4); + return 0; + } + return r; } /* DIAG */ From 000a1a3800b532f97b939ebb777d5a14418f44a6 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Mon, 23 Jul 2012 21:37:05 +0000 Subject: [PATCH 0002/2270] s390: provide interface for service interrupt/introduce interrupt.c This patch creates interrupt.c. The first user is a callback for hw/* code to trigger an service interrupt for a given sccb value. Several interrupt types for s390 are floating (can be delivered to all CPUs). so this code does not belong to a specific CPU. Other interrupts (like the virtio one) are also floating and can be moved here later on. Signed-off-by: Christian Borntraeger Signed-off-by: Alexander Graf --- target-s390x/Makefile.objs | 2 +- target-s390x/cpu.h | 3 +++ target-s390x/interrupt.c | 29 +++++++++++++++++++++++++++++ target-s390x/op_helper.c | 16 +--------------- 4 files changed, 34 insertions(+), 16 deletions(-) create mode 100644 target-s390x/interrupt.c diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs index 262747f8a6..80be3bbdb2 100644 --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -1,4 +1,4 @@ -obj-y += translate.o op_helper.o helper.o cpu.o +obj-y += translate.o op_helper.o helper.o cpu.o interrupt.o obj-$(CONFIG_SOFTMMU) += machine.o obj-$(CONFIG_KVM) += kvm.o diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index c30ac3a0e1..18ac6e3938 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -320,6 +320,9 @@ S390CPU *s390_cpu_addr2state(uint16_t cpu_addr); void s390_add_running_cpu(CPUS390XState *env); unsigned s390_del_running_cpu(CPUS390XState *env); +/* service interrupts are floating therefore we must not pass an cpustate */ +void s390_sclp_extint(uint32_t parm); + /* from s390-virtio-bus */ extern const target_phys_addr_t virtio_size; diff --git a/target-s390x/interrupt.c b/target-s390x/interrupt.c new file mode 100644 index 0000000000..c1b034f775 --- /dev/null +++ b/target-s390x/interrupt.c @@ -0,0 +1,29 @@ +/* + * QEMU S/390 Interrupt support + * + * Copyright IBM, Corp. 2012 + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. + */ + +#include "cpu.h" +#include "kvm.h" + +#if !defined(CONFIG_USER_ONLY) +/* service interrupts are floating therefore we must not pass an cpustate */ +void s390_sclp_extint(uint32_t parm) +{ + S390CPU *dummy_cpu = s390_cpu_addr2state(0); + CPUS390XState *env = &dummy_cpu->env; + + if (kvm_enabled()) { +#ifdef CONFIG_KVM + kvm_s390_interrupt_internal(env, KVM_S390_INT_SERVICE, parm, 0, 1); +#endif + } else { + env->psw.addr += 4; + cpu_inject_ext(env, EXT_SERVICE, parm, 0); + } +} +#endif diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c index 91dd8dc3fb..abc35ddd7b 100644 --- a/target-s390x/op_helper.c +++ b/target-s390x/op_helper.c @@ -2362,12 +2362,6 @@ static void program_interrupt(CPUS390XState *env, uint32_t code, int ilc) } } -static void ext_interrupt(CPUS390XState *env, int type, uint32_t param, - uint64_t param64) -{ - cpu_inject_ext(env, type, param, param64); -} - /* * ret < 0 indicates program check, ret = 0,1,2,3 -> cc */ @@ -2398,15 +2392,7 @@ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code) stb_phys(sccb + SCP_INCREMENT, 1 << shift); stw_phys(sccb + SCP_RESPONSE_CODE, 0x10); - if (kvm_enabled()) { -#ifdef CONFIG_KVM - kvm_s390_interrupt_internal(env, KVM_S390_INT_SERVICE, - sccb & ~3, 0, 1); -#endif - } else { - env->psw.addr += 4; - ext_interrupt(env, EXT_SERVICE, sccb & ~3, 0); - } + s390_sclp_extint(sccb & ~3); break; default: #ifdef DEBUG_HELPER From 231903bf27c18ba6d4d905601eab368f324159eb Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Wed, 13 Jun 2012 18:38:50 +0000 Subject: [PATCH 0003/2270] pseries pci: removed redundant busdev The PCIHostState struct already contains SysBusDevice so the one in sPAPRPHBState has to go. Signed-off-by: Alexey Kardashevskiy Signed-off-by: Alexander Graf --- hw/spapr_pci.c | 4 ++-- hw/spapr_pci.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index b2e4f785ea..5bee180989 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -276,7 +276,7 @@ static DMAContext *spapr_pci_dma_context_fn(PCIBus *bus, void *opaque, static int spapr_phb_init(SysBusDevice *s) { - sPAPRPHBState *phb = FROM_SYSBUS(sPAPRPHBState, s); + sPAPRPHBState *phb = DO_UPCAST(sPAPRPHBState, host_state.busdev, s); char *namebuf; int i; PCIBus *bus; @@ -314,7 +314,7 @@ static int spapr_phb_init(SysBusDevice *s) memory_region_add_subregion(get_system_memory(), phb->io_win_addr, &phb->iowindow); - bus = pci_register_bus(&phb->busdev.qdev, + bus = pci_register_bus(&phb->host_state.busdev.qdev, phb->busname ? phb->busname : phb->dtbusname, pci_spapr_set_irq, pci_spapr_map_irq, phb, &phb->memspace, &phb->iospace, diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index d9e46e22e3..a141764a6a 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -28,7 +28,6 @@ #include "hw/xics.h" typedef struct sPAPRPHBState { - SysBusDevice busdev; PCIHostState host_state; uint64_t buid; From e0fdbd7c1b45c1af034d4070a65067f6635f77b0 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Wed, 13 Jun 2012 18:40:06 +0000 Subject: [PATCH 0004/2270] pseries pci: spapr_populate_pci_devices renamed to spapr_populate_pci_dt spapr_populate_pci_devices() populates the device tree only with bus properties and has nothing to do with the devices on it as PCI BAR allocation is done by the system firmware (SLOF). New name - spapr_populate_pci_dt() - describes the functionality better. Signed-off-by: Alexey Kardashevskiy Signed-off-by: Alexander Graf --- hw/spapr.c | 2 +- hw/spapr_pci.c | 6 +++--- hw/spapr_pci.h | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 81c9343ca5..ab5a0c2ed7 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -481,7 +481,7 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr, } QLIST_FOREACH(phb, &spapr->phbs, list) { - ret = spapr_populate_pci_devices(phb, PHANDLE_XICP, fdt); + ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt); } if (ret < 0) { diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 5bee180989..291354094d 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -406,9 +406,9 @@ void spapr_create_phb(sPAPREnvironment *spapr, #define b_fff(x) b_x((x), 8, 3) /* function number */ #define b_rrrrrrrr(x) b_x((x), 0, 8) /* register number */ -int spapr_populate_pci_devices(sPAPRPHBState *phb, - uint32_t xics_phandle, - void *fdt) +int spapr_populate_pci_dt(sPAPRPHBState *phb, + uint32_t xics_phandle, + void *fdt) { int bus_off, i, j; char nodename[256]; diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index a141764a6a..dd66f4b386 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -55,8 +55,8 @@ void spapr_create_phb(sPAPREnvironment *spapr, uint64_t mem_win_addr, uint64_t mem_win_size, uint64_t io_win_addr); -int spapr_populate_pci_devices(sPAPRPHBState *phb, - uint32_t xics_phandle, - void *fdt); +int spapr_populate_pci_dt(sPAPRPHBState *phb, + uint32_t xics_phandle, + void *fdt); #endif /* __HW_SPAPR_PCI_H__ */ From 4a18e7c92a3c23ee742eda1e4442299b56198517 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 2 Jul 2012 13:03:18 +0000 Subject: [PATCH 0005/2270] PPC: e500: rename mpc8544ds into generic file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the file (with no changes other than fixing up the header paths) in preparation for refactoring into a generic e500 platform. Also move it into the newly created ppc/ directory. Signed-off-by: Scott Wood Reviewed-by: Andreas Färber [agraf: conditionalize on CONFIG_FDT] Signed-off-by: Alexander Graf --- hw/ppc/Makefile.objs | 4 +++- hw/{ppce500_mpc8544ds.c => ppc/e500.c} | 16 ++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) rename hw/{ppce500_mpc8544ds.c => ppc/e500.c} (99%) diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index aa4bbeb664..e86c5244b1 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -15,7 +15,7 @@ obj-$(CONFIG_PSERIES) += spapr_pci.o pci-hotplug.o spapr_iommu.o obj-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o obj-y += ppc440_bamboo.o # PowerPC E500 boards -obj-$(CONFIG_FDT) += ppce500_mpc8544ds.o mpc8544_guts.o ppce500_spin.o +obj-$(CONFIG_FDT) += mpc8544_guts.o ppce500_spin.o # PowerPC 440 Xilinx ML507 reference board. obj-y += virtex_ml507.o # PowerPC OpenPIC @@ -26,3 +26,5 @@ obj-$(CONFIG_FDT) += ../device_tree.o obj-y += xilinx_ethlite.o obj-y := $(addprefix ../,$(obj-y)) + +obj-$(CONFIG_FDT) += e500.o diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppc/e500.c similarity index 99% rename from hw/ppce500_mpc8544ds.c rename to hw/ppc/e500.c index 8b9fd83ce1..0b383e6288 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppc/e500.c @@ -17,19 +17,19 @@ #include "config.h" #include "qemu-common.h" #include "net.h" -#include "hw.h" -#include "pc.h" -#include "pci.h" -#include "boards.h" +#include "hw/hw.h" +#include "hw/pc.h" +#include "hw/pci.h" +#include "hw/boards.h" #include "sysemu.h" #include "kvm.h" #include "kvm_ppc.h" #include "device_tree.h" -#include "openpic.h" -#include "ppc.h" -#include "loader.h" +#include "hw/openpic.h" +#include "hw/ppc.h" +#include "hw/loader.h" #include "elf.h" -#include "sysbus.h" +#include "hw/sysbus.h" #include "exec-memory.h" #include "host-utils.h" From b330598137cad915f65562a524b30e32498e44be Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 2 Jul 2012 13:03:19 +0000 Subject: [PATCH 0006/2270] PPC: e500: change internal references away from mpc8544ds No functional changes -- machine is still outwardly mpc8544ds. The references that are not changed contain mpc8544 hardware details that need to be parameterized if/when a different e500 platform wants to change them. Signed-off-by: Scott Wood Signed-off-by: Alexander Graf --- hw/ppc/e500.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 0b383e6288..db5ca6e693 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -1,5 +1,5 @@ /* - * QEMU PowerPC MPC8544DS board emulation + * QEMU PowerPC e500-based platforms * * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved. * @@ -42,6 +42,7 @@ #define RAM_SIZES_ALIGN (64UL << 20) +/* TODO: parameterize */ #define MPC8544_CCSRBAR_BASE 0xE0000000ULL #define MPC8544_CCSRBAR_SIZE 0x00100000ULL #define MPC8544_MPIC_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x40000ULL) @@ -104,7 +105,7 @@ static void dt_serial_create(void *fdt, unsigned long long offset, } } -static int mpc8544_load_device_tree(CPUPPCState *env, +static int ppce500_load_device_tree(CPUPPCState *env, target_phys_addr_t addr, target_phys_addr_t ramsize, target_phys_addr_t initrd_base, @@ -388,7 +389,7 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env) env->tlb_dirty = true; } -static void mpc8544ds_cpu_reset_sec(void *opaque) +static void ppce500_cpu_reset_sec(void *opaque) { PowerPCCPU *cpu = opaque; CPUPPCState *env = &cpu->env; @@ -401,7 +402,7 @@ static void mpc8544ds_cpu_reset_sec(void *opaque) env->exception_index = EXCP_HLT; } -static void mpc8544ds_cpu_reset(void *opaque) +static void ppce500_cpu_reset(void *opaque) { PowerPCCPU *cpu = opaque; CPUPPCState *env = &cpu->env; @@ -417,7 +418,7 @@ static void mpc8544ds_cpu_reset(void *opaque) mmubooke_create_initial_mapping(env); } -static void mpc8544ds_init(ram_addr_t ram_size, +static void ppce500_init(ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, @@ -478,11 +479,11 @@ static void mpc8544ds_init(ram_addr_t ram_size, /* Primary CPU */ struct boot_info *boot_info; boot_info = g_malloc0(sizeof(struct boot_info)); - qemu_register_reset(mpc8544ds_cpu_reset, cpu); + qemu_register_reset(ppce500_cpu_reset, cpu); env->load_info = boot_info; } else { /* Secondary CPUs */ - qemu_register_reset(mpc8544ds_cpu_reset_sec, cpu); + qemu_register_reset(ppce500_cpu_reset_sec, cpu); } } @@ -577,7 +578,7 @@ static void mpc8544ds_init(ram_addr_t ram_size, int dt_size; dt_base = (loadaddr + kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; - dt_size = mpc8544_load_device_tree(env, dt_base, ram_size, initrd_base, + dt_size = ppce500_load_device_tree(env, dt_base, ram_size, initrd_base, initrd_size, kernel_cmdline); if (dt_size < 0) { fprintf(stderr, "couldn't load device tree\n"); @@ -595,16 +596,16 @@ static void mpc8544ds_init(ram_addr_t ram_size, } } -static QEMUMachine mpc8544ds_machine = { +static QEMUMachine ppce500_machine = { .name = "mpc8544ds", .desc = "mpc8544ds", - .init = mpc8544ds_init, + .init = ppce500_init, .max_cpus = 15, }; -static void mpc8544ds_machine_init(void) +static void ppce500_machine_init(void) { - qemu_register_machine(&mpc8544ds_machine); + qemu_register_machine(&ppce500_machine); } -machine_init(mpc8544ds_machine_init); +machine_init(ppce500_machine_init); From e6eaabeb8dfb026da51d178974bddf56f1f06ffe Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 2 Jul 2012 13:03:20 +0000 Subject: [PATCH 0007/2270] PPC: e500: split mpc8544ds machine from generic e500 code Currently the only mpc8544ds-ism that is factored out is toplevel compatible and model. In the future the generic e500 code is expected to become more generic. Signed-off-by: Scott Wood [agraf: conditionalize on CONFIG_FDT] Signed-off-by: Alexander Graf --- hw/ppc/Makefile.objs | 2 +- hw/ppc/e500.c | 81 +++++++++++++++++--------------------------- hw/ppc/e500.h | 21 ++++++++++++ hw/ppc/mpc8544ds.c | 61 +++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 51 deletions(-) create mode 100644 hw/ppc/e500.h create mode 100644 hw/ppc/mpc8544ds.c diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index e86c5244b1..99fe837125 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -27,4 +27,4 @@ obj-y += xilinx_ethlite.o obj-y := $(addprefix ../,$(obj-y)) -obj-$(CONFIG_FDT) += e500.o +obj-$(CONFIG_FDT) += e500.o mpc8544ds.o diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index db5ca6e693..f07be08f6e 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -16,6 +16,7 @@ #include "config.h" #include "qemu-common.h" +#include "e500.h" #include "net.h" #include "hw/hw.h" #include "hw/pc.h" @@ -106,24 +107,21 @@ static void dt_serial_create(void *fdt, unsigned long long offset, } static int ppce500_load_device_tree(CPUPPCState *env, + PPCE500Params *params, target_phys_addr_t addr, - target_phys_addr_t ramsize, target_phys_addr_t initrd_base, - target_phys_addr_t initrd_size, - const char *kernel_cmdline) + target_phys_addr_t initrd_size) { int ret = -1; - uint64_t mem_reg_property[] = { 0, cpu_to_be64(ramsize) }; + uint64_t mem_reg_property[] = { 0, cpu_to_be64(params->ram_size) }; int fdt_size; void *fdt; uint8_t hypercall[16]; uint32_t clock_freq = 400000000; uint32_t tb_freq = 400000000; int i; - const char *compatible = "MPC8544DS\0MPC85xxDS"; - int compatible_len = sizeof("MPC8544DS\0MPC85xxDS"); + const char *toplevel_compat = NULL; /* user override */ char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus"; - char model[] = "MPC8544DS"; char soc[128]; char mpic[128]; uint32_t mpic_ph; @@ -146,14 +144,9 @@ static int ppce500_load_device_tree(CPUPPCState *env, machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); if (machine_opts) { - const char *tmp; dumpdtb = qemu_opt_get(machine_opts, "dumpdtb"); dtb_file = qemu_opt_get(machine_opts, "dtb"); - tmp = qemu_opt_get(machine_opts, "dt_compatible"); - if (tmp) { - compatible = tmp; - compatible_len = strlen(compatible) + 1; - } + toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); } if (dtb_file) { @@ -176,8 +169,6 @@ static int ppce500_load_device_tree(CPUPPCState *env, } /* Manipulate device tree in memory. */ - qemu_devtree_setprop_string(fdt, "/", "model", model); - qemu_devtree_setprop(fdt, "/", "compatible", compatible, compatible_len); qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2); qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2); @@ -202,7 +193,7 @@ static int ppce500_load_device_tree(CPUPPCState *env, } ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", - kernel_cmdline); + params->kernel_cmdline); if (ret < 0) fprintf(stderr, "couldn't set /chosen/bootargs\n"); @@ -338,6 +329,13 @@ static int ppce500_load_device_tree(CPUPPCState *env, qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3); qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci); + params->fixup_devtree(params, fdt); + + if (toplevel_compat) { + qemu_devtree_setprop(fdt, "/", "compatible", toplevel_compat, + strlen(toplevel_compat) + 1); + } + done: if (dumpdtb) { /* Dump the dtb to a file and quit */ @@ -418,12 +416,7 @@ static void ppce500_cpu_reset(void *opaque) mmubooke_create_initial_mapping(env); } -static void ppce500_init(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 ppce500_init(PPCE500Params *params) { MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); @@ -444,8 +437,8 @@ static void ppce500_init(ram_addr_t ram_size, CPUPPCState *firstenv = NULL; /* Setup CPUs */ - if (cpu_model == NULL) { - cpu_model = "e500v2_v30"; + if (params->cpu_model == NULL) { + params->cpu_model = "e500v2_v30"; } irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); @@ -454,7 +447,7 @@ static void ppce500_init(ram_addr_t ram_size, PowerPCCPU *cpu; qemu_irq *input; - cpu = cpu_ppc_init(cpu_model); + cpu = cpu_ppc_init(params->cpu_model); if (cpu == NULL) { fprintf(stderr, "Unable to initialize CPU!\n"); exit(1); @@ -543,43 +536,45 @@ static void ppce500_init(ram_addr_t ram_size, sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL); /* Load kernel. */ - if (kernel_filename) { - kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL); + if (params->kernel_filename) { + kernel_size = load_uimage(params->kernel_filename, &entry, + &loadaddr, NULL); if (kernel_size < 0) { - kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry, - &elf_lowaddr, NULL, 1, ELF_MACHINE, 0); + kernel_size = load_elf(params->kernel_filename, NULL, NULL, + &elf_entry, &elf_lowaddr, NULL, 1, + ELF_MACHINE, 0); entry = elf_entry; loadaddr = elf_lowaddr; } /* XXX try again as binary */ if (kernel_size < 0) { fprintf(stderr, "qemu: could not load kernel '%s'\n", - kernel_filename); + params->kernel_filename); exit(1); } } /* Load initrd. */ - if (initrd_filename) { + if (params->initrd_filename) { initrd_base = (kernel_size + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK; - initrd_size = load_image_targphys(initrd_filename, initrd_base, + initrd_size = load_image_targphys(params->initrd_filename, initrd_base, ram_size - initrd_base); if (initrd_size < 0) { fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", - initrd_filename); + params->initrd_filename); exit(1); } } /* If we're loading a kernel directly, we must load the device tree too. */ - if (kernel_filename) { + if (params->kernel_filename) { struct boot_info *boot_info; int dt_size; dt_base = (loadaddr + kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; - dt_size = ppce500_load_device_tree(env, dt_base, ram_size, initrd_base, - initrd_size, kernel_cmdline); + dt_size = ppce500_load_device_tree(env, params, dt_base, initrd_base, + initrd_size); if (dt_size < 0) { fprintf(stderr, "couldn't load device tree\n"); exit(1); @@ -595,17 +590,3 @@ static void ppce500_init(ram_addr_t ram_size, kvmppc_init(); } } - -static QEMUMachine ppce500_machine = { - .name = "mpc8544ds", - .desc = "mpc8544ds", - .init = ppce500_init, - .max_cpus = 15, -}; - -static void ppce500_machine_init(void) -{ - qemu_register_machine(&ppce500_machine); -} - -machine_init(ppce500_machine_init); diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h new file mode 100644 index 0000000000..7ae87f4e21 --- /dev/null +++ b/hw/ppc/e500.h @@ -0,0 +1,21 @@ +#ifndef PPCE500_H +#define PPCE500_H + +typedef struct PPCE500Params { + /* Standard QEMU machine init params */ + 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; + + /* e500-specific params */ + + /* required -- must at least add toplevel board compatible */ + void (*fixup_devtree)(struct PPCE500Params *params, void *fdt); +} PPCE500Params; + +void ppce500_init(PPCE500Params *params); + +#endif diff --git a/hw/ppc/mpc8544ds.c b/hw/ppc/mpc8544ds.c new file mode 100644 index 0000000000..984d21cbf5 --- /dev/null +++ b/hw/ppc/mpc8544ds.c @@ -0,0 +1,61 @@ +/* + * Support for the PPC e500-based mpc8544ds board + * + * Copyright 2012 Freescale Semiconductor, Inc. + * + * This 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. + */ + +#include "config.h" +#include "qemu-common.h" +#include "e500.h" +#include "../boards.h" +#include "device_tree.h" + +static void mpc8544ds_fixup_devtree(PPCE500Params *params, void *fdt) +{ + const char model[] = "MPC8544DS"; + const char compatible[] = "MPC8544DS\0MPC85xxDS"; + + qemu_devtree_setprop(fdt, "/", "model", model, sizeof(model)); + qemu_devtree_setprop(fdt, "/", "compatible", compatible, + sizeof(compatible)); +} + +static void mpc8544ds_init(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) +{ + PPCE500Params params = { + .ram_size = ram_size, + .boot_device = boot_device, + .kernel_filename = kernel_filename, + .kernel_cmdline = kernel_cmdline, + .initrd_filename = initrd_filename, + .cpu_model = cpu_model, + .fixup_devtree = mpc8544ds_fixup_devtree, + }; + + ppce500_init(¶ms); +} + + +static QEMUMachine ppce500_machine = { + .name = "mpc8544ds", + .desc = "mpc8544ds", + .init = mpc8544ds_init, + .max_cpus = 15, +}; + +static void ppce500_machine_init(void) +{ + qemu_register_machine(&ppce500_machine); +} + +machine_init(ppce500_machine_init); From 4d5c29ca455ed6adb1fb9f8394e4d7badfd0c532 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 2 Jul 2012 13:03:21 +0000 Subject: [PATCH 0008/2270] PPC: e500: add generic e500 platform This gives the kernel a paravirtualized machine to target, without requiring both sides to pretend to be targeting a specific board that likely has little to do with the host in KVM scenarios. This avoids the need to add new boards to QEMU, just to be able to run KVM on new CPUs. Signed-off-by: Scott Wood [agraf: conditionalize on CONFIG_FDT] Signed-off-by: Alexander Graf --- hw/ppc/Makefile.objs | 2 +- hw/ppc/e500plat.c | 60 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 hw/ppc/e500plat.c diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index 99fe837125..951e407f14 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -27,4 +27,4 @@ obj-y += xilinx_ethlite.o obj-y := $(addprefix ../,$(obj-y)) -obj-$(CONFIG_FDT) += e500.o mpc8544ds.o +obj-$(CONFIG_FDT) += e500.o mpc8544ds.o e500plat.o diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c new file mode 100644 index 0000000000..60a5cb3bd0 --- /dev/null +++ b/hw/ppc/e500plat.c @@ -0,0 +1,60 @@ +/* + * Generic device-tree-driven paravirt PPC e500 platform + * + * Copyright 2012 Freescale Semiconductor, Inc. + * + * This 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. + */ + +#include "config.h" +#include "qemu-common.h" +#include "e500.h" +#include "../boards.h" +#include "device_tree.h" + +static void e500plat_fixup_devtree(PPCE500Params *params, void *fdt) +{ + const char model[] = "QEMU ppce500"; + const char compatible[] = "fsl,qemu-e500"; + + qemu_devtree_setprop(fdt, "/", "model", model, sizeof(model)); + qemu_devtree_setprop(fdt, "/", "compatible", compatible, + sizeof(compatible)); +} + +static void e500plat_init(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) +{ + PPCE500Params params = { + .ram_size = ram_size, + .boot_device = boot_device, + .kernel_filename = kernel_filename, + .kernel_cmdline = kernel_cmdline, + .initrd_filename = initrd_filename, + .cpu_model = cpu_model, + .fixup_devtree = e500plat_fixup_devtree, + }; + + ppce500_init(¶ms); +} + +static QEMUMachine e500plat_machine = { + .name = "ppce500", + .desc = "generic paravirt e500 platform", + .init = e500plat_init, + .max_cpus = 15, +}; + +static void e500plat_machine_init(void) +{ + qemu_register_machine(&e500plat_machine); +} + +machine_init(e500plat_machine_init); From 78e8fde26c032931ca2ae13bfc7c59e38afd17ee Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 6 Aug 2012 18:44:45 +0000 Subject: [PATCH 0009/2270] ppc: Fix bug in handling of PAPR hypercall exits Currently for powerpc, kvm_arch_handle_exit() always returns 1, meaning that its caller - kvm_cpu_exec() - will always exit immediately afterwards to the loop in qemu_kvm_cpu_thread_fn(). There's no need to do this. Once we've handled the hypercall there's no reason we can't go straight around and KVM_RUN again, which is what ret = 0 will signal. The only exception might be for hypercalls which affect the state of cpu_can_run(), however the only one that might do this is H_CEDE and for kvm that is always handled in the kernel, not qemu. Furtherm setting ret = 0 means that when exit_requested is set from a hypercall, we will enter KVM_RUN once more with a signal which lets the the kernel do its internal logic to complete the hypercall with out actually executing any more guest code. This is important if our hypercall also triggered a reset, which previously would re-initialize everything without completing the hypercall. This caused the kernel to get confused because it thought the guest was still in the middle of a hypercall when it has actually been reset. This patch therefore changes to ret = 0, which is both a bugfix and a small optimization. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- target-ppc/kvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 829e180f8b..a31d278a5f 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -766,7 +766,7 @@ int kvm_arch_handle_exit(CPUPPCState *env, struct kvm_run *run) dprintf("handle PAPR hypercall\n"); run->papr_hcall.ret = spapr_hypercall(env, run->papr_hcall.nr, run->papr_hcall.args); - ret = 1; + ret = 0; break; #endif default: From 7e99826c350f21cb7d162e802efaa5d1b8689ad0 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 9 Aug 2012 22:57:14 +0200 Subject: [PATCH 0010/2270] Revert "PPC: e500: Use new MPIC dt format" This reverts commit 518c7fb44f2182cde943dc64f88cb2fd4e4ff6b5. It breaks new Linux guests with SMP, because IPIs get mapped to large vectors which our MPIC emulation does not implement. Conflicts: hw/ppc/e500.c --- hw/ppc/e500.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index f07be08f6e..6f0de6d959 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -68,18 +68,18 @@ static void pci_map_create(void *fdt, uint32_t *pci_map, uint32_t mpic) int i; const uint32_t tmp[] = { /* IDSEL 0x11 J17 Slot 1 */ - 0x8800, 0x0, 0x0, 0x1, mpic, 0x2, 0x1, 0x0, 0x0, - 0x8800, 0x0, 0x0, 0x2, mpic, 0x3, 0x1, 0x0, 0x0, - 0x8800, 0x0, 0x0, 0x3, mpic, 0x4, 0x1, 0x0, 0x0, - 0x8800, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, 0x0, 0x0, + 0x8800, 0x0, 0x0, 0x1, mpic, 0x2, 0x1, + 0x8800, 0x0, 0x0, 0x2, mpic, 0x3, 0x1, + 0x8800, 0x0, 0x0, 0x3, mpic, 0x4, 0x1, + 0x8800, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, /* IDSEL 0x12 J16 Slot 2 */ - 0x9000, 0x0, 0x0, 0x1, mpic, 0x3, 0x1, 0x0, 0x0, - 0x9000, 0x0, 0x0, 0x2, mpic, 0x4, 0x1, 0x0, 0x0, - 0x9000, 0x0, 0x0, 0x3, mpic, 0x2, 0x1, 0x0, 0x0, - 0x9000, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, 0x0, 0x0, + 0x9000, 0x0, 0x0, 0x1, mpic, 0x3, 0x1, + 0x9000, 0x0, 0x0, 0x2, mpic, 0x4, 0x1, + 0x9000, 0x0, 0x0, 0x3, mpic, 0x2, 0x1, + 0x9000, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, }; - for (i = 0; i < ARRAY_SIZE(tmp); i++) { + for (i = 0; i < (7 * 8); i++) { pci_map[i] = cpu_to_be32(tmp[i]); } } @@ -97,7 +97,7 @@ static void dt_serial_create(void *fdt, unsigned long long offset, qemu_devtree_setprop_cells(fdt, ser, "reg", offset, 0x100); qemu_devtree_setprop_cell(fdt, ser, "cell-index", idx); qemu_devtree_setprop_cell(fdt, ser, "clock-frequency", 0); - qemu_devtree_setprop_cells(fdt, ser, "interrupts", 42, 2, 0, 0); + qemu_devtree_setprop_cells(fdt, ser, "interrupts", 42, 2); qemu_devtree_setprop_phandle(fdt, ser, "interrupt-parent", mpic); qemu_devtree_setprop_string(fdt, "/aliases", alias, ser); @@ -127,7 +127,7 @@ static int ppce500_load_device_tree(CPUPPCState *env, uint32_t mpic_ph; char gutil[128]; char pci[128]; - uint32_t pci_map[9 * 8]; + uint32_t pci_map[7 * 8]; uint32_t pci_ranges[14] = { 0x2000000, 0x0, 0xc0000000, @@ -274,18 +274,15 @@ static int ppce500_load_device_tree(CPUPPCState *env, MPC8544_MPIC_REGS_BASE - MPC8544_CCSRBAR_BASE); qemu_devtree_add_subnode(fdt, mpic); qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic"); - qemu_devtree_setprop_string(fdt, mpic, "compatible", "fsl,mpic"); + qemu_devtree_setprop_string(fdt, mpic, "compatible", "chrp,open-pic"); qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_BASE - MPC8544_CCSRBAR_BASE, 0x40000); qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0); - qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 4); + qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2); mpic_ph = qemu_devtree_alloc_phandle(fdt); qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph); qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph); qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0); - qemu_devtree_setprop(fdt, mpic, "big-endian", NULL, 0); - qemu_devtree_setprop(fdt, mpic, "single-cpu-affinity", NULL, 0); - qemu_devtree_setprop_cell(fdt, mpic, "last-interrupt-source", 255); /* * We have to generate ser1 first, because Linux takes the first @@ -315,7 +312,7 @@ static int ppce500_load_device_tree(CPUPPCState *env, pci_map_create(fdt, pci_map, qemu_devtree_get_phandle(fdt, mpic)); qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, sizeof(pci_map)); qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic); - qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2, 0, 0); + qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2); qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255); for (i = 0; i < 14; i++) { pci_ranges[i] = cpu_to_be32(pci_ranges[i]); From c1195d1677a41f42be712620674d42b39d83bdfe Mon Sep 17 00:00:00 2001 From: "zhlcindy@gmail.com" Date: Mon, 6 Aug 2012 16:41:59 +0000 Subject: [PATCH 0011/2270] Add one new file vga-pci.h and cleanup on all platforms Functions pci_vga_init() and pci_cirrus_vga_init() are declared in pc.h. That prevents other platforms (e.g. sPAPR) to use them. This patch is to create one new file vga-pci.h and move the declarations to vga-pci.h, so that they can be shared by all platforms. This patch also cleans up on all platforms. Signed-off-by: Li Zhang Signed-off-by: Alexander Graf --- hw/alpha_pci.c | 1 + hw/cirrus_vga.c | 2 +- hw/mips_malta.c | 1 + hw/pc.c | 1 + hw/pc.h | 4 ---- hw/ppc_newworld.c | 2 +- hw/ppc_oldworld.c | 2 +- hw/ppc_prep.c | 1 + hw/sun4u.c | 1 + hw/vga-pci.c | 2 +- hw/vga-pci.h | 12 ++++++++++++ 11 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 hw/vga-pci.h diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c index 673557781e..ea546f83f1 100644 --- a/hw/alpha_pci.c +++ b/hw/alpha_pci.c @@ -11,6 +11,7 @@ #include "qemu-log.h" #include "sysemu.h" #include "vmware_vga.h" +#include "vga-pci.h" /* PCI IO reads/writes, to byte-word addressable memory. */ diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index 623dd688d9..e8dcc6b883 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -27,8 +27,8 @@ * available at http://home.worldonline.dk/~finth/ */ #include "hw.h" -#include "pc.h" #include "pci.h" +#include "vga-pci.h" #include "console.h" #include "vga_int.h" #include "loader.h" diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 351c88ebca..ad23f26e59 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -48,6 +48,7 @@ #include "blockdev.h" #include "exec-memory.h" #include "sysbus.h" /* SysBusDevice */ +#include "vga-pci.h" //#define DEBUG_BOARD_INIT diff --git a/hw/pc.c b/hw/pc.c index e8bcfc0b4b..3ed1a3caa2 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -51,6 +51,7 @@ #include "exec-memory.h" #include "arch_init.h" #include "bitmap.h" +#include "vga-pci.h" /* output Bochs bios info messages */ //#define DEBUG_BIOS diff --git a/hw/pc.h b/hw/pc.h index 31ccb6f495..e4db0715b8 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -189,14 +189,10 @@ static inline DeviceState *isa_vga_init(ISABus *bus) return &dev->qdev; } -DeviceState *pci_vga_init(PCIBus *bus); int isa_vga_mm_init(target_phys_addr_t vram_base, target_phys_addr_t ctrl_base, int it_shift, MemoryRegion *address_space); -/* cirrus_vga.c */ -DeviceState *pci_cirrus_vga_init(PCIBus *bus); - /* ne2000.c */ static inline bool isa_ne2000_init(ISABus *bus, int base, int irq, NICInfo *nd) { diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index 4e2a6e691b..e95cfe831e 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -52,7 +52,6 @@ #include "adb.h" #include "mac_dbdma.h" #include "nvram.h" -#include "pc.h" #include "pci.h" #include "net.h" #include "sysemu.h" @@ -68,6 +67,7 @@ #include "hw/usb.h" #include "blockdev.h" #include "exec-memory.h" +#include "vga-pci.h" #define MAX_IDE_BUS 2 #define CFG_ADDR 0xf0000510 diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index f2c6908534..1dcd8a6c36 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -29,7 +29,6 @@ #include "adb.h" #include "mac_dbdma.h" #include "nvram.h" -#include "pc.h" #include "sysemu.h" #include "net.h" #include "isa.h" @@ -44,6 +43,7 @@ #include "kvm_ppc.h" #include "blockdev.h" #include "exec-memory.h" +#include "vga-pci.h" #define MAX_IDE_BUS 2 #define CFG_ADDR 0xf0000510 diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index be2b26830d..7a876164c9 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -39,6 +39,7 @@ #include "blockdev.h" #include "arch_init.h" #include "exec-memory.h" +#include "vga-pci.h" //#define HARD_DEBUG_PPC_IO //#define DEBUG_PPC_IO diff --git a/hw/sun4u.c b/hw/sun4u.c index 137a7c6666..07cd04273a 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -39,6 +39,7 @@ #include "elf.h" #include "blockdev.h" #include "exec-memory.h" +#include "vga-pci.h" //#define DEBUG_IRQ //#define DEBUG_EBUS diff --git a/hw/vga-pci.c b/hw/vga-pci.c index 37dc019a61..9abbada8f1 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -23,8 +23,8 @@ */ #include "hw.h" #include "console.h" -#include "pc.h" #include "pci.h" +#include "vga-pci.h" #include "vga_int.h" #include "pixel_ops.h" #include "qemu-timer.h" diff --git a/hw/vga-pci.h b/hw/vga-pci.h new file mode 100644 index 0000000000..49abf1309d --- /dev/null +++ b/hw/vga-pci.h @@ -0,0 +1,12 @@ +#ifndef VGA_PCI_H +#define VGA_PCI_H + +#include "qemu-common.h" + +/* vga-pci.c */ +DeviceState *pci_vga_init(PCIBus *bus); + +/* cirrus_vga.c */ +DeviceState *pci_cirrus_vga_init(PCIBus *bus); + +#endif From f28359d8e8fc64192450a72164b89d06cc3f781d Mon Sep 17 00:00:00 2001 From: "zhlcindy@gmail.com" Date: Mon, 6 Aug 2012 16:42:00 +0000 Subject: [PATCH 0012/2270] spapr: Add support for -vga option Also instanciate the USB keyboard and mouse when that option is used (you can still use -device to create individual devices without all the defaults) Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Li Zhang [agraf: remove USB bits] Signed-off-by: Alexander Graf --- hw/spapr.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/hw/spapr.c b/hw/spapr.c index ab5a0c2ed7..494c412dba 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -45,6 +45,7 @@ #include "kvm.h" #include "kvm_ppc.h" #include "pci.h" +#include "vga-pci.h" #include "exec-memory.h" @@ -82,6 +83,7 @@ #define PHANDLE_XICP 0x00001111 sPAPREnvironment *spapr; +bool spapr_has_graphics; qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num, enum xics_irq_type type) @@ -257,6 +259,9 @@ static void *spapr_create_fdt_skel(const char *cpu_model, _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop)))); } _FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device))); + _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width))); + _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height))); + _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth))); _FDT((fdt_end_node(fdt))); @@ -503,7 +508,9 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr, } } - spapr_populate_chosen_stdout(fdt, spapr->vio_bus); + if (!spapr_has_graphics) { + spapr_populate_chosen_stdout(fdt, spapr->vio_bus); + } _FDT((fdt_pack(fdt))); @@ -556,6 +563,18 @@ static void spapr_cpu_reset(void *opaque) cpu_reset(CPU(cpu)); } +static int spapr_vga_init(PCIBus *pci_bus) +{ + if (std_vga_enabled) { + pci_vga_init(pci_bus); + } else { + fprintf(stderr, "This vga model is not supported," + "currently it only supports -vga std\n"); + return 0; + } + return 1; +} + /* pSeries LPAR / sPAPR hardware init */ static void ppc_spapr_init(ram_addr_t ram_size, const char *boot_device, @@ -710,6 +729,11 @@ static void ppc_spapr_init(ram_addr_t ram_size, spapr_vscsi_create(spapr->vio_bus); } + /* Graphics */ + if (spapr_vga_init(QLIST_FIRST(&spapr->phbs)->host_state.bus)) { + spapr_has_graphics = true; + } + if (rma_size < (MIN_RMA_SLOF << 20)) { fprintf(stderr, "qemu: pSeries SLOF firmware requires >= " "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF); From a5b71725c7067f6805eb30ff8e03dce3b6bf7a53 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 14 Aug 2012 12:53:18 +0200 Subject: [PATCH 0013/2270] xbzrle: fix compilation on ppc32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compiling the xbzrle code on my ppc32 user space, I hit the following gcc compiler warning (treated as an error): cc1: warnings being treated as errors savevm.c: In function ‘xbzrle_encode_buffer’: savevm.c:2476: error: overflow in implicit constant conversion Fix this by making the cast explicit, rather than implicit. Signed-off-by: Alexander Graf --- savevm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/savevm.c b/savevm.c index 0ea10c9b66..9ab4d83da4 100644 --- a/savevm.c +++ b/savevm.c @@ -2473,7 +2473,7 @@ int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen, /* word at a time for speed, use of 32-bit long okay */ if (!res) { /* truncation to 32-bit long okay */ - long mask = 0x0101010101010101ULL; + long mask = (long)0x0101010101010101ULL; while (i < slen) { xor = *(long *)(old_buf + i) ^ *(long *)(new_buf + i); if ((xor - mask) & ~xor & (mask << 7)) { From 8c57b867b5d18b0d916797dfbac465b8aaa5bf5a Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 14 Aug 2012 13:11:49 +0200 Subject: [PATCH 0014/2270] PPC: spapr: Rework VGA select logic When selecting our VGA adapter, we want to: * fail completely when we can't satisfy the user's request * support -nographic where no VGA adapter should be spawned This patch reworks the logic so we fulfill the two conditions above. Signed-off-by: Alexander Graf --- hw/spapr.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 494c412dba..709673e767 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -563,16 +563,21 @@ static void spapr_cpu_reset(void *opaque) cpu_reset(CPU(cpu)); } +/* Returns whether we want to use VGA or not */ static int spapr_vga_init(PCIBus *pci_bus) { - if (std_vga_enabled) { + switch (vga_interface_type) { + case VGA_STD: pci_vga_init(pci_bus); - } else { + return 1; + case VGA_NONE: + return 0; + default: fprintf(stderr, "This vga model is not supported," "currently it only supports -vga std\n"); - return 0; + exit(0); + break; } - return 1; } /* pSeries LPAR / sPAPR hardware init */ From 3fc5acdeedfcea7c7d86040fa427ae785920b399 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 14 Aug 2012 13:22:13 +0200 Subject: [PATCH 0015/2270] PPC: spapr: Remove global variable Global variables are bad. Let's move spapr_has_graphics into the machine state struct. Signed-off-by: Alexander Graf --- hw/spapr.c | 5 ++--- hw/spapr.h | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 709673e767..aa39d2d2c3 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -83,7 +83,6 @@ #define PHANDLE_XICP 0x00001111 sPAPREnvironment *spapr; -bool spapr_has_graphics; qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num, enum xics_irq_type type) @@ -508,7 +507,7 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr, } } - if (!spapr_has_graphics) { + if (!spapr->has_graphics) { spapr_populate_chosen_stdout(fdt, spapr->vio_bus); } @@ -736,7 +735,7 @@ static void ppc_spapr_init(ram_addr_t ram_size, /* Graphics */ if (spapr_vga_init(QLIST_FIRST(&spapr->phbs)->host_state.bus)) { - spapr_has_graphics = true; + spapr->has_graphics = true; } if (rma_size < (MIN_RMA_SLOF << 20)) { diff --git a/hw/spapr.h b/hw/spapr.h index 9153f29a60..fe40e7d005 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -23,6 +23,7 @@ typedef struct sPAPREnvironment { int next_irq; int rtc_offset; char *cpu_model; + bool has_graphics; } sPAPREnvironment; #define H_SUCCESS 0 From 03332579b81ef7f2b0fcb41e45f7764a5bfc1ea4 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 30 Jul 2012 20:09:01 +0000 Subject: [PATCH 0016/2270] pseries: Update SLOF This patch updates the SLOF version, introducing a number of fixes: * add proper graphics support * fix bugs with graphical terminal under grub2 * fix bugs in handling of 64-bit unit addresses * fix VSCSI representation to be closer to PowerVM * fix bugs which caused grub2 to crash Signed-off-by: Benjamin Herrenschmidt Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- pc-bios/README | 2 +- pc-bios/slof.bin | Bin 880496 -> 878088 bytes roms/SLOF | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pc-bios/README b/pc-bios/README index e56e9e5f04..e71bcd0f36 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -17,7 +17,7 @@ - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at https://github.com/dgibson/SLOF, and the image currently in qemu is - built from git tag qemu-slof-20120217. + built from git tag qemu-slof-20120719. - sgabios (the Serial Graphics Adapter option ROM) provides a means for legacy x86 software to communicate with an attached serial console as diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin index 449a7bb2afaf604f6c089612e99086df0800d7dc..320b8f001cf9962318812a5b9109242e210fe499 100644 GIT binary patch delta 149136 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
uB7(Tl{Z_zPG%GKwI);XZL=yYnr`vG4{ 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

UmOEx7=;6L^YR1nVIk6 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 delta 156060 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 diff --git a/roms/SLOF b/roms/SLOF index d153364253..7279655af2 160000 --- a/roms/SLOF +++ b/roms/SLOF @@ -1 +1 @@ -Subproject commit d153364253548d6cd91403711f84996e6a7dab31 +Subproject commit 7279655af2eba855bd2df61303d25abd1eeb2300 From c9f709d2e7d9dcc6e6ecbee8d499b4b14b11320b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 7 Aug 2012 16:10:31 +0000 Subject: [PATCH 0017/2270] pseries: Remove extraneous prints The pseries machine prints several messages to stderr whenever it starts up and another whenever the vm is reset. It's not normal for qemu machines to do this though, so this patch removes them. We can put them back conditional on a DEBUG symbol if we really need them in future. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index aa39d2d2c3..032d259e83 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -538,8 +538,6 @@ static void spapr_reset(void *opaque) { sPAPREnvironment *spapr = (sPAPREnvironment *)opaque; - fprintf(stderr, "sPAPR reset\n"); - /* flush out the hash table */ memset(spapr->htab, 0, spapr->htab_size); @@ -744,14 +742,6 @@ static void ppc_spapr_init(ram_addr_t ram_size, exit(1); } - fprintf(stderr, "sPAPR memory map:\n"); - fprintf(stderr, "RTAS : 0x%08lx..%08lx\n", - (unsigned long)spapr->rtas_addr, - (unsigned long)(spapr->rtas_addr + spapr->rtas_size - 1)); - fprintf(stderr, "FDT : 0x%08lx..%08lx\n", - (unsigned long)spapr->fdt_addr, - (unsigned long)(spapr->fdt_addr + FDT_MAX_SIZE - 1)); - if (kernel_filename) { uint64_t lowaddr = 0; @@ -767,8 +757,6 @@ static void ppc_spapr_init(ram_addr_t ram_size, kernel_filename); exit(1); } - fprintf(stderr, "Kernel : 0x%08x..%08lx\n", - KERNEL_LOAD_ADDR, KERNEL_LOAD_ADDR + kernel_size - 1); /* load initrd */ if (initrd_filename) { @@ -783,8 +771,6 @@ static void ppc_spapr_init(ram_addr_t ram_size, initrd_filename); exit(1); } - fprintf(stderr, "Ramdisk : 0x%08lx..%08lx\n", - (long)initrd_base, (long)(initrd_base + initrd_size - 1)); } else { initrd_base = 0; initrd_size = 0; @@ -798,10 +784,6 @@ static void ppc_spapr_init(ram_addr_t ram_size, exit(1); } g_free(filename); - fprintf(stderr, "Firmware load : 0x%08x..%08lx\n", - 0, fw_size); - fprintf(stderr, "Firmware runtime : 0x%08lx..%08lx\n", - load_limit, (unsigned long)spapr->fdt_addr); spapr->entry_point = 0x100; From a307d59434ba78b97544b42b8cfd24a1b62e39a6 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 7 Aug 2012 16:10:32 +0000 Subject: [PATCH 0018/2270] pseries: Rework irq assignment to avoid carrying qemu_irqs around Currently, the interfaces in the pseries machine code for assignment and setup of interrupts pass around qemu_irq objects. That was done in an attempt not to be too closely linked to the specific XICS interrupt controller. However interactions with the device tree setup made that attempt rather futile, and XICS is part of the PAPR spec anyway, so this really just meant we had to carry both the qemu_irq pointers and the XICS irq numbers around. This mess will just get worse when we add upcoming PCI MSI support, since that will require tracking a bunch more interrupt. Therefore, this patch reworks the spapr code to just use XICS irq numbers (roughly equivalent to GSIs on x86) and only retrieve the qemu_irq pointers from the XICS code when we need them (a trivial lookup). This is a reworked and generalized version of an earlier spapr_pci specific patch from Alexey Kardashevskiy. Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson [agraf: fix checkpath warning] Signed-off-by: Alexander Graf --- hw/spapr.c | 18 +++++++----------- hw/spapr.h | 11 +++++------ hw/spapr_llan.c | 2 +- hw/spapr_pci.c | 14 ++++++-------- hw/spapr_pci.h | 8 ++++++-- hw/spapr_vio.c | 12 ++++++------ hw/spapr_vio.h | 8 ++++++-- hw/spapr_vty.c | 2 +- hw/xics.c | 12 +++++++++--- hw/xics.h | 5 +++-- 10 files changed, 50 insertions(+), 42 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 032d259e83..40bb6d300d 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -84,11 +84,9 @@ sPAPREnvironment *spapr; -qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num, - enum xics_irq_type type) +int spapr_allocate_irq(int hint, enum xics_irq_type type) { - uint32_t irq; - qemu_irq qirq; + int irq; if (hint) { irq = hint; @@ -97,16 +95,14 @@ qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num, irq = spapr->next_irq++; } - qirq = xics_assign_irq(spapr->icp, irq, type); - if (!qirq) { - return NULL; + /* Configure irq type */ + if (!xics_get_qirq(spapr->icp, irq)) { + return 0; } - if (irq_num) { - *irq_num = irq; - } + xics_set_irq_type(spapr->icp, irq, type); - return qirq; + return irq; } static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr) diff --git a/hw/spapr.h b/hw/spapr.h index fe40e7d005..b5cf6afca5 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -289,17 +289,16 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn); target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode, target_ulong *args); -qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num, - enum xics_irq_type type); +int spapr_allocate_irq(int hint, enum xics_irq_type type); -static inline qemu_irq spapr_allocate_msi(uint32_t hint, uint32_t *irq_num) +static inline int spapr_allocate_msi(int hint) { - return spapr_allocate_irq(hint, irq_num, XICS_MSI); + return spapr_allocate_irq(hint, XICS_MSI); } -static inline qemu_irq spapr_allocate_lsi(uint32_t hint, uint32_t *irq_num) +static inline int spapr_allocate_lsi(int hint) { - return spapr_allocate_irq(hint, irq_num, XICS_LSI); + return spapr_allocate_irq(hint, XICS_LSI); } static inline uint32_t rtas_ld(target_ulong phys, int n) diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c index 01e54f3675..bd3f131d7e 100644 --- a/hw/spapr_llan.c +++ b/hw/spapr_llan.c @@ -169,7 +169,7 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf, } if (sdev->signal_state & 1) { - qemu_irq_pulse(sdev->qirq); + qemu_irq_pulse(spapr_vio_qirq(sdev)); } return size; diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 291354094d..65ae8c4801 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -223,7 +223,7 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level) */ sPAPRPHBState *phb = opaque; - qemu_set_irq(phb->lsi_table[irq_num].qirq, level); + qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level); } static uint64_t spapr_io_read(void *opaque, target_phys_addr_t addr, @@ -329,16 +329,14 @@ static int spapr_phb_init(SysBusDevice *s) /* Initialize the LSI table */ for (i = 0; i < PCI_NUM_PINS; i++) { - qemu_irq qirq; - uint32_t num; + uint32_t irq; - qirq = spapr_allocate_lsi(0, &num); - if (!qirq) { + irq = spapr_allocate_lsi(0); + if (!irq) { return -1; } - phb->lsi_table[i].dt_irq = num; - phb->lsi_table[i].qirq = qirq; + phb->lsi_table[i].irq = irq; } return 0; @@ -477,7 +475,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, irqmap[2] = 0; irqmap[3] = cpu_to_be32(j+1); irqmap[4] = cpu_to_be32(xics_phandle); - irqmap[5] = cpu_to_be32(phb->lsi_table[lsi_num].dt_irq); + irqmap[5] = cpu_to_be32(phb->lsi_table[lsi_num].irq); irqmap[6] = cpu_to_be32(0x8); } } diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index dd66f4b386..6bba885600 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -40,13 +40,17 @@ typedef struct sPAPRPHBState { DMAContext *dma; struct { - uint32_t dt_irq; - qemu_irq qirq; + uint32_t irq; } lsi_table[PCI_NUM_PINS]; QLIST_ENTRY(sPAPRPHBState) list; } sPAPRPHBState; +static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin) +{ + return xics_get_qirq(spapr->icp, phb->lsi_table[pin].irq); +} + #define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL #define SPAPR_PCI_IO_WIN_SIZE 0x10000 diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index 05b55032a9..3abe853f3d 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -49,7 +49,7 @@ #endif static Property spapr_vio_props[] = { - DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, vio_irq_num, 0), \ + DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, irq, 0), \ DEFINE_PROP_END_OF_LIST(), }; @@ -132,8 +132,8 @@ static int vio_make_devnode(VIOsPAPRDevice *dev, } } - if (dev->qirq) { - uint32_t ints_prop[] = {cpu_to_be32(dev->vio_irq_num), 0}; + if (dev->irq) { + uint32_t ints_prop[] = {cpu_to_be32(dev->irq), 0}; ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop, sizeof(ints_prop)); @@ -306,7 +306,7 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq) dev->crq.qnext = (dev->crq.qnext + 16) % dev->crq.qsize; if (dev->signal_state & 1) { - qemu_irq_pulse(dev->qirq); + qemu_irq_pulse(spapr_vio_qirq(dev)); } return 0; @@ -459,8 +459,8 @@ static int spapr_vio_busdev_init(DeviceState *qdev) dev->qdev.id = id; } - dev->qirq = spapr_allocate_msi(dev->vio_irq_num, &dev->vio_irq_num); - if (!dev->qirq) { + dev->irq = spapr_allocate_msi(dev->irq); + if (!dev->irq) { return -1; } diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h index 6f9a498ccd..ea6aa43e26 100644 --- a/hw/spapr_vio.h +++ b/hw/spapr_vio.h @@ -61,8 +61,7 @@ struct VIOsPAPRDevice { DeviceState qdev; uint32_t reg; uint32_t flags; - qemu_irq qirq; - uint32_t vio_irq_num; + uint32_t irq; target_ulong signal_state; VIOsPAPR_CRQ crq; DMAContext *dma; @@ -85,6 +84,11 @@ extern int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus); extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode); +static inline qemu_irq spapr_vio_qirq(VIOsPAPRDevice *dev) +{ + return xics_get_qirq(spapr->icp, dev->irq); +} + static inline bool spapr_vio_dma_valid(VIOsPAPRDevice *dev, uint64_t taddr, uint32_t size, DMADirection dir) { diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c index 99e52cc6b7..5da17a3ff4 100644 --- a/hw/spapr_vty.c +++ b/hw/spapr_vty.c @@ -26,7 +26,7 @@ static void vty_receive(void *opaque, const uint8_t *buf, int size) if ((dev->in == dev->out) && size) { /* toggle line to simulate edge interrupt */ - qemu_irq_pulse(dev->sdev.qirq); + qemu_irq_pulse(spapr_vio_qirq(&dev->sdev)); } for (i = 0; i < size; i++) { assert((dev->in - dev->out) < VTERM_BUFSIZE); diff --git a/hw/xics.c b/hw/xics.c index 668a0d6484..b674771dc4 100644 --- a/hw/xics.c +++ b/hw/xics.c @@ -315,18 +315,24 @@ static void ics_eoi(struct ics_state *ics, int nr) * Exported functions */ -qemu_irq xics_assign_irq(struct icp_state *icp, int irq, - enum xics_irq_type type) +qemu_irq xics_get_qirq(struct icp_state *icp, int irq) { if ((irq < icp->ics->offset) || (irq >= (icp->ics->offset + icp->ics->nr_irqs))) { return NULL; } + return icp->ics->qirqs[irq - icp->ics->offset]; +} + +void xics_set_irq_type(struct icp_state *icp, int irq, + enum xics_irq_type type) +{ + assert((irq >= icp->ics->offset) + && (irq < (icp->ics->offset + icp->ics->nr_irqs))); assert((type == XICS_MSI) || (type == XICS_LSI)); icp->ics->irqs[irq - icp->ics->offset].type = type; - return icp->ics->qirqs[irq - icp->ics->offset]; } static target_ulong h_cppr(CPUPPCState *env, sPAPREnvironment *spapr, diff --git a/hw/xics.h b/hw/xics.h index 208015939c..99b96ac85a 100644 --- a/hw/xics.h +++ b/hw/xics.h @@ -36,8 +36,9 @@ enum xics_irq_type { XICS_LSI, /* Level-signalled interrupt */ }; -qemu_irq xics_assign_irq(struct icp_state *icp, int irq, - enum xics_irq_type type); +qemu_irq xics_get_qirq(struct icp_state *icp, int irq); +void xics_set_irq_type(struct icp_state *icp, int irq, + enum xics_irq_type type); struct icp_state *xics_system_init(int nr_irqs); From fa28f71b4a88cdb796f1e0a308205c6be604d3f3 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 7 Aug 2012 16:10:33 +0000 Subject: [PATCH 0019/2270] pseries: Separate PCI RTAS setup from common from emulation specific PCI setup Currently the RTAS functions for handling PCI are registered from the class init code for the PCI host bridge. That sort of makes sense now, but will break in the future when vfio gives us multiple types of host bridge for pseries (emulated and pass-through, at least). The RTAS functions will be common across all host bridge types (and will call out to different places internally depending on the type). So, this patch moves the RTAS registration into its own function called direct from the machine setup code. Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.c | 2 ++ hw/spapr_pci.c | 13 ++++++++----- hw/spapr_pci.h | 2 ++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 40bb6d300d..8153c05636 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -704,6 +704,8 @@ static void ppc_spapr_init(ram_addr_t ram_size, } /* Set up PCI */ + spapr_pci_rtas_init(); + spapr_create_phb(spapr, "pci", SPAPR_PCI_BUID, SPAPR_PCI_MEM_WIN_ADDR, SPAPR_PCI_MEM_WIN_SIZE, diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 65ae8c4801..fcc358e4c6 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -359,11 +359,6 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data) sdc->init = spapr_phb_init; dc->props = spapr_phb_properties; - - spapr_rtas_register("read-pci-config", rtas_read_pci_config); - spapr_rtas_register("write-pci-config", rtas_write_pci_config); - spapr_rtas_register("ibm,read-pci-config", rtas_ibm_read_pci_config); - spapr_rtas_register("ibm,write-pci-config", rtas_ibm_write_pci_config); } static TypeInfo spapr_phb_info = { @@ -488,6 +483,14 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, return 0; } +void spapr_pci_rtas_init(void) +{ + spapr_rtas_register("read-pci-config", rtas_read_pci_config); + spapr_rtas_register("write-pci-config", rtas_write_pci_config); + spapr_rtas_register("ibm,read-pci-config", rtas_ibm_read_pci_config); + spapr_rtas_register("ibm,write-pci-config", rtas_ibm_write_pci_config); +} + static void register_types(void) { type_register_static(&spapr_phb_info); diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index 6bba885600..2aee67fd4c 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -63,4 +63,6 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t xics_phandle, void *fdt); +void spapr_pci_rtas_init(void); + #endif /* __HW_SPAPR_PCI_H__ */ From f4b9523ba6388f6f951933de3f9a76e2e9ea2ede Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 7 Aug 2012 16:10:34 +0000 Subject: [PATCH 0020/2270] pseries: added allocator for a block of IRQs The patch adds a simple helper which allocates a consecutive sequence of IRQs calling spapr_allocate_irq for each and checks that allocated IRQs go consequently. The patch is required for upcoming support of MSI/MSIX on POWER. Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.c | 26 ++++++++++++++++++++++++++ hw/spapr.h | 1 + 2 files changed, 27 insertions(+) diff --git a/hw/spapr.c b/hw/spapr.c index 8153c05636..afbdbc586e 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -105,6 +105,32 @@ int spapr_allocate_irq(int hint, enum xics_irq_type type) return irq; } +/* Allocate block of consequtive IRQs, returns a number of the first */ +int spapr_allocate_irq_block(int num, enum xics_irq_type type) +{ + int first = -1; + int i; + + for (i = 0; i < num; ++i) { + int irq; + + irq = spapr_allocate_irq(0, type); + if (!irq) { + return -1; + } + + if (0 == i) { + first = irq; + } + + /* If the above doesn't create a consecutive block then that's + * an internal bug */ + assert(irq == (first + i)); + } + + return first; +} + static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr) { int ret = 0, offset; diff --git a/hw/spapr.h b/hw/spapr.h index b5cf6afca5..6229769ce0 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -290,6 +290,7 @@ target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode, target_ulong *args); int spapr_allocate_irq(int hint, enum xics_irq_type type); +int spapr_allocate_irq_block(int num, enum xics_irq_type type); static inline int spapr_allocate_msi(int hint) { From 9894c5d4b467d24e281c22f2f5e24822c9b55fb3 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 7 Aug 2012 16:10:35 +0000 Subject: [PATCH 0021/2270] pseries: Export find_phb() utility function for PCI code The pseries PCI code makes use of an internal find_dev() function which locates a PCIDevice * given a (platform specific) bus ID and device address. Internally this needs to first locate the host bridge on which the device resides based on the bus ID. This patch exposes that host bridge lookup as a separate function, which we will need later in the MSI and VFIO code. Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson [agraf: drop trace.h inclusion] Signed-off-by: Alexander Graf --- hw/spapr_pci.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index fcc358e4c6..2e38fee017 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -32,24 +32,35 @@ #include "hw/pci_internals.h" -static PCIDevice *find_dev(sPAPREnvironment *spapr, - uint64_t buid, uint32_t config_addr) +static sPAPRPHBState *find_phb(sPAPREnvironment *spapr, uint64_t buid) { - int devfn = (config_addr >> 8) & 0xFF; sPAPRPHBState *phb; QLIST_FOREACH(phb, &spapr->phbs, list) { - BusChild *kid; - if (phb->buid != buid) { continue; } + return phb; + } - QTAILQ_FOREACH(kid, &phb->host_state.bus->qbus.children, sibling) { - PCIDevice *dev = (PCIDevice *)kid->child; - if (dev->devfn == devfn) { - return dev; - } + return NULL; +} + +static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid, + uint32_t config_addr) +{ + sPAPRPHBState *phb = find_phb(spapr, buid); + BusChild *kid; + int devfn = (config_addr >> 8) & 0xFF; + + if (!phb) { + return NULL; + } + + QTAILQ_FOREACH(kid, &phb->host_state.bus->qbus.children, sibling) { + PCIDevice *dev = (PCIDevice *)kid->child; + if (dev->devfn == devfn) { + return dev; } } From a2950fb6e795e3e10fed35d347a7aa28a44be2ff Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 7 Aug 2012 16:10:36 +0000 Subject: [PATCH 0022/2270] pseries: Add trace event for PCI irqs This adds a trace event in the pseries PCI specific set_irq() function to assist in debugging. Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson [agraf: add trace.h include] Signed-off-by: Alexander Graf --- hw/spapr_pci.c | 2 ++ trace-events | 3 +++ 2 files changed, 5 insertions(+) diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 2e38fee017..1eb1a7edc9 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -29,6 +29,7 @@ #include "hw/spapr_pci.h" #include "exec-memory.h" #include +#include "trace.h" #include "hw/pci_internals.h" @@ -234,6 +235,7 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level) */ sPAPRPHBState *phb = opaque; + trace_spapr_pci_lsi_set(phb->busname, irq_num, phb->lsi_table[irq_num].irq); qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level); } diff --git a/trace-events b/trace-events index 6b12f83de0..191b39ebdf 100644 --- a/trace-events +++ b/trace-events @@ -970,3 +970,6 @@ qxl_render_blit_guest_primary_initialized(void) "" qxl_render_blit(int32_t stride, int32_t left, int32_t right, int32_t top, int32_t bottom) "stride=%d [%d, %d, %d, %d]" qxl_render_guest_primary_resized(int32_t width, int32_t height, int32_t stride, int32_t bytes_pp, int32_t bits_pp) "%dx%d, stride %d, bpp %d, depth %d" qxl_render_update_area_done(void *cookie) "%p" + +# hw/spapr_pci.c +spapr_pci_lsi_set(const char *busname, int pin, uint32_t irq) "%s PIN%d IRQ %u" From 0ee2c058a3fe485b8901186179102e251a33d082 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 7 Aug 2012 16:10:37 +0000 Subject: [PATCH 0023/2270] pseries: Add PCI MSI/MSI-X support This patch implements MSI and MSI-X support for the pseries PCI host bridge. To do this it adds: * A "config_space_address to msi_table" map, since the MSI RTAS calls take a PCI config space address as an identifier. * A MSIX memory region to catch msi_notify()/msix_notiry() from virtio-pci and pass them to the guest via qemu_irq_pulse(). * RTAS call "ibm,change-msi" which sets up MSI vectors for a device. Note that this call may configure and return lesser number of vectors than requested. * RTAS call "ibm,query-interrupt-source-number" which translates MSI vector to interrupt controller (XICS) IRQ number. Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson [agraf: fix error case ndev < 0] Signed-off-by: Alexander Graf --- hw/spapr.c | 7 +- hw/spapr_pci.c | 245 ++++++++++++++++++++++++++++++++++++++++++++++++- hw/spapr_pci.h | 15 ++- trace-events | 5 + 4 files changed, 268 insertions(+), 4 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index afbdbc586e..5178721d49 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -41,6 +41,7 @@ #include "hw/spapr_vio.h" #include "hw/spapr_pci.h" #include "hw/xics.h" +#include "hw/msi.h" #include "kvm.h" #include "kvm_ppc.h" @@ -79,6 +80,7 @@ #define SPAPR_PCI_MEM_WIN_ADDR (0x10000000000ULL + 0xA0000000) #define SPAPR_PCI_MEM_WIN_SIZE 0x20000000 #define SPAPR_PCI_IO_WIN_ADDR (0x10000000000ULL + 0x80000000) +#define SPAPR_PCI_MSI_WIN_ADDR (0x10000000000ULL + 0x90000000) #define PHANDLE_XICP 0x00001111 @@ -619,6 +621,8 @@ static void ppc_spapr_init(ram_addr_t ram_size, long pteg_shift = 17; char *filename; + msi_supported = true; + spapr = g_malloc0(sizeof(*spapr)); QLIST_INIT(&spapr->phbs); @@ -735,7 +739,8 @@ static void ppc_spapr_init(ram_addr_t ram_size, spapr_create_phb(spapr, "pci", SPAPR_PCI_BUID, SPAPR_PCI_MEM_WIN_ADDR, SPAPR_PCI_MEM_WIN_SIZE, - SPAPR_PCI_IO_WIN_ADDR); + SPAPR_PCI_IO_WIN_ADDR, + SPAPR_PCI_MSI_WIN_ADDR); for (i = 0; i < nb_nics; i++) { NICInfo *nd = &nd_table[i]; diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 1eb1a7edc9..780a4d6f16 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -24,6 +24,8 @@ */ #include "hw.h" #include "pci.h" +#include "msi.h" +#include "msix.h" #include "pci_host.h" #include "hw/spapr.h" #include "hw/spapr_pci.h" @@ -33,6 +35,17 @@ #include "hw/pci_internals.h" +/* Copied from the kernel arch/powerpc/platforms/pseries/msi.c */ +#define RTAS_QUERY_FN 0 +#define RTAS_CHANGE_FN 1 +#define RTAS_RESET_FN 2 +#define RTAS_CHANGE_MSI_FN 3 +#define RTAS_CHANGE_MSIX_FN 4 + +/* Interrupt types to return on RTAS_CHANGE_* */ +#define RTAS_TYPE_MSI 1 +#define RTAS_TYPE_MSIX 2 + static sPAPRPHBState *find_phb(sPAPREnvironment *spapr, uint64_t buid) { sPAPRPHBState *phb; @@ -211,6 +224,191 @@ static void rtas_write_pci_config(sPAPREnvironment *spapr, finish_write_pci_config(spapr, 0, addr, size, val, rets); } +/* + * Find an entry with config_addr or returns the empty one if not found AND + * alloc_new is set. + * At the moment the msi_table entries are never released so there is + * no point to look till the end of the list if we need to find the free entry. + */ +static int spapr_msicfg_find(sPAPRPHBState *phb, uint32_t config_addr, + bool alloc_new) +{ + int i; + + for (i = 0; i < SPAPR_MSIX_MAX_DEVS; ++i) { + if (!phb->msi_table[i].nvec) { + break; + } + if (phb->msi_table[i].config_addr == config_addr) { + return i; + } + } + if ((i < SPAPR_MSIX_MAX_DEVS) && alloc_new) { + trace_spapr_pci_msi("Allocating new MSI config", i, config_addr); + return i; + } + + return -1; +} + +/* + * Set MSI/MSIX message data. + * This is required for msi_notify()/msix_notify() which + * will write at the addresses via spapr_msi_write(). + */ +static void spapr_msi_setmsg(PCIDevice *pdev, target_phys_addr_t addr, + bool msix, unsigned req_num) +{ + unsigned i; + MSIMessage msg = { .address = addr, .data = 0 }; + + if (!msix) { + msi_set_message(pdev, msg); + trace_spapr_pci_msi_setup(pdev->name, 0, msg.address); + return; + } + + for (i = 0; i < req_num; ++i) { + msg.address = addr | (i << 2); + msix_set_message(pdev, i, msg); + trace_spapr_pci_msi_setup(pdev->name, i, msg.address); + } +} + +static void rtas_ibm_change_msi(sPAPREnvironment *spapr, + uint32_t token, uint32_t nargs, + target_ulong args, uint32_t nret, + target_ulong rets) +{ + uint32_t config_addr = rtas_ld(args, 0); + uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + unsigned int func = rtas_ld(args, 3); + unsigned int req_num = rtas_ld(args, 4); /* 0 == remove all */ + unsigned int seq_num = rtas_ld(args, 5); + unsigned int ret_intr_type; + int ndev, irq; + sPAPRPHBState *phb = NULL; + PCIDevice *pdev = NULL; + + switch (func) { + case RTAS_CHANGE_MSI_FN: + case RTAS_CHANGE_FN: + ret_intr_type = RTAS_TYPE_MSI; + break; + case RTAS_CHANGE_MSIX_FN: + ret_intr_type = RTAS_TYPE_MSIX; + break; + default: + fprintf(stderr, "rtas_ibm_change_msi(%u) is not implemented\n", func); + rtas_st(rets, 0, -3); /* Parameter error */ + return; + } + + /* Fins sPAPRPHBState */ + phb = find_phb(spapr, buid); + if (phb) { + pdev = find_dev(spapr, buid, config_addr); + } + if (!phb || !pdev) { + rtas_st(rets, 0, -3); /* Parameter error */ + return; + } + + /* Releasing MSIs */ + if (!req_num) { + ndev = spapr_msicfg_find(phb, config_addr, false); + if (ndev < 0) { + trace_spapr_pci_msi("MSI has not been enabled", -1, config_addr); + rtas_st(rets, 0, -1); /* Hardware error */ + return; + } + trace_spapr_pci_msi("Released MSIs", ndev, config_addr); + rtas_st(rets, 0, 0); + rtas_st(rets, 1, 0); + return; + } + + /* Enabling MSI */ + + /* Find a device number in the map to add or reuse the existing one */ + ndev = spapr_msicfg_find(phb, config_addr, true); + if (ndev >= SPAPR_MSIX_MAX_DEVS || ndev < 0) { + fprintf(stderr, "No free entry for a new MSI device\n"); + rtas_st(rets, 0, -1); /* Hardware error */ + return; + } + trace_spapr_pci_msi("Configuring MSI", ndev, config_addr); + + /* Check if there is an old config and MSI number has not changed */ + if (phb->msi_table[ndev].nvec && (req_num != phb->msi_table[ndev].nvec)) { + /* Unexpected behaviour */ + fprintf(stderr, "Cannot reuse MSI config for device#%d", ndev); + rtas_st(rets, 0, -1); /* Hardware error */ + return; + } + + /* There is no cached config, allocate MSIs */ + if (!phb->msi_table[ndev].nvec) { + irq = spapr_allocate_irq_block(req_num, XICS_MSI); + if (irq < 0) { + fprintf(stderr, "Cannot allocate MSIs for device#%d", ndev); + rtas_st(rets, 0, -1); /* Hardware error */ + return; + } + phb->msi_table[ndev].irq = irq; + phb->msi_table[ndev].nvec = req_num; + phb->msi_table[ndev].config_addr = config_addr; + } + + /* Setup MSI/MSIX vectors in the device (via cfgspace or MSIX BAR) */ + spapr_msi_setmsg(pdev, phb->msi_win_addr | (ndev << 16), + ret_intr_type == RTAS_TYPE_MSIX, req_num); + + rtas_st(rets, 0, 0); + rtas_st(rets, 1, req_num); + rtas_st(rets, 2, ++seq_num); + rtas_st(rets, 3, ret_intr_type); + + trace_spapr_pci_rtas_ibm_change_msi(func, req_num); +} + +static void rtas_ibm_query_interrupt_source_number(sPAPREnvironment *spapr, + uint32_t token, + uint32_t nargs, + target_ulong args, + uint32_t nret, + target_ulong rets) +{ + uint32_t config_addr = rtas_ld(args, 0); + uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + unsigned int intr_src_num = -1, ioa_intr_num = rtas_ld(args, 3); + int ndev; + sPAPRPHBState *phb = NULL; + + /* Fins sPAPRPHBState */ + phb = find_phb(spapr, buid); + if (!phb) { + rtas_st(rets, 0, -3); /* Parameter error */ + return; + } + + /* Find device descriptor and start IRQ */ + ndev = spapr_msicfg_find(phb, config_addr, false); + if (ndev < 0) { + trace_spapr_pci_msi("MSI has not been enabled", -1, config_addr); + rtas_st(rets, 0, -1); /* Hardware error */ + return; + } + + intr_src_num = phb->msi_table[ndev].irq + ioa_intr_num; + trace_spapr_pci_rtas_ibm_query_interrupt_source_number(ioa_intr_num, + intr_src_num); + + rtas_st(rets, 0, 0); + rtas_st(rets, 1, intr_src_num); + rtas_st(rets, 2, 1);/* 0 == level; 1 == edge */ +} + static int pci_spapr_swizzle(int slot, int pin) { return (slot + pin) % PCI_NUM_PINS; @@ -276,6 +474,33 @@ static const MemoryRegionOps spapr_io_ops = { .write = spapr_io_write }; +/* + * MSI/MSIX memory region implementation. + * The handler handles both MSI and MSIX. + * For MSI-X, the vector number is encoded as a part of the address, + * data is set to 0. + * For MSI, the vector number is encoded in least bits in data. + */ +static void spapr_msi_write(void *opaque, target_phys_addr_t addr, + uint64_t data, unsigned size) +{ + sPAPRPHBState *phb = opaque; + int ndev = addr >> 16; + int vec = ((addr & 0xFFFF) >> 2) | data; + uint32_t irq = phb->msi_table[ndev].irq + vec; + + trace_spapr_pci_msi_write(addr, data, irq); + + qemu_irq_pulse(xics_get_qirq(spapr->icp, irq)); +} + +static const MemoryRegionOps spapr_msi_ops = { + /* There is no .read as the read result is undefined by PCI spec */ + .read = NULL, + .write = spapr_msi_write, + .endianness = DEVICE_LITTLE_ENDIAN +}; + /* * PHB PCI device */ @@ -327,6 +552,17 @@ static int spapr_phb_init(SysBusDevice *s) memory_region_add_subregion(get_system_memory(), phb->io_win_addr, &phb->iowindow); + /* As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors, + * we need to allocate some memory to catch those writes coming + * from msi_notify()/msix_notify() */ + if (msi_supported) { + sprintf(namebuf, "%s.msi", phb->dtbusname); + memory_region_init_io(&phb->msiwindow, &spapr_msi_ops, phb, + namebuf, SPAPR_MSIX_MAX_DEVS * 0x10000); + memory_region_add_subregion(get_system_memory(), phb->msi_win_addr, + &phb->msiwindow); + } + bus = pci_register_bus(&phb->host_state.busdev.qdev, phb->busname ? phb->busname : phb->dtbusname, pci_spapr_set_irq, pci_spapr_map_irq, phb, @@ -362,6 +598,7 @@ static Property spapr_phb_properties[] = { DEFINE_PROP_HEX64("mem_win_size", sPAPRPHBState, mem_win_size, 0x20000000), DEFINE_PROP_HEX64("io_win_addr", sPAPRPHBState, io_win_addr, 0), DEFINE_PROP_HEX64("io_win_size", sPAPRPHBState, io_win_size, 0x10000), + DEFINE_PROP_HEX64("msi_win_addr", sPAPRPHBState, msi_win_addr, 0), DEFINE_PROP_END_OF_LIST(), }; @@ -384,7 +621,7 @@ static TypeInfo spapr_phb_info = { void spapr_create_phb(sPAPREnvironment *spapr, const char *busname, uint64_t buid, uint64_t mem_win_addr, uint64_t mem_win_size, - uint64_t io_win_addr) + uint64_t io_win_addr, uint64_t msi_win_addr) { DeviceState *dev; @@ -397,6 +634,7 @@ void spapr_create_phb(sPAPREnvironment *spapr, qdev_prop_set_uint64(dev, "mem_win_addr", mem_win_addr); qdev_prop_set_uint64(dev, "mem_win_size", mem_win_size); qdev_prop_set_uint64(dev, "io_win_addr", io_win_addr); + qdev_prop_set_uint64(dev, "msi_win_addr", msi_win_addr); qdev_init_nofail(dev); } @@ -502,6 +740,11 @@ void spapr_pci_rtas_init(void) spapr_rtas_register("write-pci-config", rtas_write_pci_config); spapr_rtas_register("ibm,read-pci-config", rtas_ibm_read_pci_config); spapr_rtas_register("ibm,write-pci-config", rtas_ibm_write_pci_config); + if (msi_supported) { + spapr_rtas_register("ibm,query-interrupt-source-number", + rtas_ibm_query_interrupt_source_number); + spapr_rtas_register("ibm,change-msi", rtas_ibm_change_msi); + } } static void register_types(void) diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index 2aee67fd4c..6892e4fae5 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -27,6 +27,8 @@ #include "hw/pci_host.h" #include "hw/xics.h" +#define SPAPR_MSIX_MAX_DEVS 32 + typedef struct sPAPRPHBState { PCIHostState host_state; @@ -36,13 +38,22 @@ typedef struct sPAPRPHBState { MemoryRegion memspace, iospace; target_phys_addr_t mem_win_addr, mem_win_size, io_win_addr, io_win_size; - MemoryRegion memwindow, iowindow; + target_phys_addr_t msi_win_addr; + MemoryRegion memwindow, iowindow, msiwindow; + + DMAContext *dma; struct { uint32_t irq; } lsi_table[PCI_NUM_PINS]; + struct { + uint32_t config_addr; + uint32_t irq; + int nvec; + } msi_table[SPAPR_MSIX_MAX_DEVS]; + QLIST_ENTRY(sPAPRPHBState) list; } sPAPRPHBState; @@ -57,7 +68,7 @@ static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin) void spapr_create_phb(sPAPREnvironment *spapr, const char *busname, uint64_t buid, uint64_t mem_win_addr, uint64_t mem_win_size, - uint64_t io_win_addr); + uint64_t io_win_addr, uint64_t msi_win_addr); int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t xics_phandle, diff --git a/trace-events b/trace-events index 191b39ebdf..04b0723927 100644 --- a/trace-events +++ b/trace-events @@ -972,4 +972,9 @@ qxl_render_guest_primary_resized(int32_t width, int32_t height, int32_t stride, qxl_render_update_area_done(void *cookie) "%p" # hw/spapr_pci.c +spapr_pci_msi(const char *msg, uint32_t n, uint32_t ca) "%s (device#%d, cfg=%x)" +spapr_pci_msi_setup(const char *name, unsigned vector, uint64_t addr) "dev\"%s\" vector %u, addr=%"PRIx64 +spapr_pci_rtas_ibm_change_msi(unsigned func, unsigned req) "func %u, requested %u" +spapr_pci_rtas_ibm_query_interrupt_source_number(unsigned ioa, unsigned intr) "queries for #%u, IRQ%u" +spapr_pci_msi_write(uint64_t addr, uint64_t data, uint32_t dt_irq) "@%"PRIx64"<=%"PRIx64" IRQ %u" spapr_pci_lsi_set(const char *busname, int pin, uint32_t irq) "%s PIN%d IRQ %u" From 5c4cbcf26ca9465a36fc0661b4103d55897e1a19 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 7 Aug 2012 16:10:38 +0000 Subject: [PATCH 0024/2270] pseries dma: DMA window params added to PHB and DT population changed Previously the only PCI bus supported was the emulated PCI bus with fixed DMA window with start at 0 and size 1GB. As we are going to support PCI pass through which DMA window properties are set by the host kernel, we have to support DMA windows with parameters other than default. This patch adds: 1. DMA window properties to sPAPRPHBState: LIOBN (bus id), start, size of the window. 2. An additional function spapr_dma_dt() to populate DMA window properties in the device tree which simply accepts all the parameters and does not try to guess what kind of IOMMU is given to it. The original spapr_dma_dt() is renamed to spapr_tcet_dma_dt(). Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.h | 4 +++- hw/spapr_iommu.c | 56 +++++++++++++++++++++++++++++++----------------- hw/spapr_pci.c | 11 ++++++---- hw/spapr_pci.h | 4 +++- hw/spapr_vio.c | 2 +- 5 files changed, 50 insertions(+), 27 deletions(-) diff --git a/hw/spapr.h b/hw/spapr.h index 6229769ce0..ac34a171e3 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -337,6 +337,8 @@ void spapr_iommu_init(void); DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size); void spapr_tce_free(DMAContext *dma); int spapr_dma_dt(void *fdt, int node_off, const char *propname, - DMAContext *dma); + uint32_t liobn, uint64_t window, uint32_t size); +int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname, + DMAContext *dma); #endif /* !defined (__HW_SPAPR_H__) */ diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c index 388ffa4b22..53b731773a 100644 --- a/hw/spapr_iommu.c +++ b/hw/spapr_iommu.c @@ -216,31 +216,47 @@ void spapr_iommu_init(void) } int spapr_dma_dt(void *fdt, int node_off, const char *propname, - DMAContext *dma) + uint32_t liobn, uint64_t window, uint32_t size) { - if (dma) { - sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma); - uint32_t dma_prop[] = {cpu_to_be32(tcet->liobn), - 0, 0, - 0, cpu_to_be32(tcet->window_size)}; - int ret; + uint32_t dma_prop[5]; + int ret; - ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-address-cells", 2); - if (ret < 0) { - return ret; - } + dma_prop[0] = cpu_to_be32(liobn); + dma_prop[1] = cpu_to_be32(window >> 32); + dma_prop[2] = cpu_to_be32(window & 0xFFFFFFFF); + dma_prop[3] = 0; /* window size is 32 bits */ + dma_prop[4] = cpu_to_be32(size); - ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-size-cells", 2); - if (ret < 0) { - return ret; - } + ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-address-cells", 2); + if (ret < 0) { + return ret; + } - ret = fdt_setprop(fdt, node_off, propname, dma_prop, - sizeof(dma_prop)); - if (ret < 0) { - return ret; - } + ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-size-cells", 2); + if (ret < 0) { + return ret; + } + + ret = fdt_setprop(fdt, node_off, propname, dma_prop, sizeof(dma_prop)); + if (ret < 0) { + return ret; } return 0; } + +int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname, + DMAContext *iommu) +{ + if (!iommu) { + return 0; + } + + if (iommu->translate == spapr_tce_translate) { + sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, iommu); + return spapr_dma_dt(fdt, node_off, propname, + tcet->liobn, 0, tcet->window_size); + } + + return -1; +} diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 780a4d6f16..b92583a991 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -518,7 +518,6 @@ static int spapr_phb_init(SysBusDevice *s) char *namebuf; int i; PCIBus *bus; - uint32_t liobn; phb->dtbusname = g_strdup_printf("pci@%" PRIx64, phb->buid); namebuf = alloca(strlen(phb->dtbusname) + 32); @@ -570,8 +569,10 @@ static int spapr_phb_init(SysBusDevice *s) PCI_DEVFN(0, 0), PCI_NUM_PINS); phb->host_state.bus = bus; - liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16); - phb->dma = spapr_tce_new_dma_context(liobn, 0x40000000); + phb->dma_liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16); + phb->dma_window_start = 0; + phb->dma_window_size = 0x40000000; + phb->dma = spapr_tce_new_dma_context(phb->dma_liobn, phb->dma_window_size); pci_setup_iommu(bus, spapr_pci_dma_context_fn, phb); QLIST_INSERT_HEAD(&spapr->phbs, phb, list); @@ -729,7 +730,9 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, _FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map, sizeof(interrupt_map))); - spapr_dma_dt(fdt, bus_off, "ibm,dma-window", phb->dma); + spapr_dma_dt(fdt, bus_off, "ibm,dma-window", + phb->dma_liobn, phb->dma_window_start, + phb->dma_window_size); return 0; } diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index 6892e4fae5..7518899b85 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -41,7 +41,9 @@ typedef struct sPAPRPHBState { target_phys_addr_t msi_win_addr; MemoryRegion memwindow, iowindow, msiwindow; - + uint32_t dma_liobn; + uint64_t dma_window_start; + uint64_t dma_window_size; DMAContext *dma; struct { diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index 3abe853f3d..7ca445216d 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -142,7 +142,7 @@ static int vio_make_devnode(VIOsPAPRDevice *dev, } } - ret = spapr_dma_dt(fdt, node_off, "ibm,my-dma-window", dev->dma); + ret = spapr_tcet_dma_dt(fdt, node_off, "ibm,my-dma-window", dev->dma); if (ret < 0) { return ret; } From 4504068723bcf9a3b37f6683d87711b6c5e4c0c3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 7 Aug 2012 16:10:39 +0000 Subject: [PATCH 0025/2270] pseries: Update SLOF firmware image This updates SLOF to handle the necessary device tree properties for MSI and MSI-X. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- pc-bios/README | 2 +- pc-bios/slof.bin | Bin 878088 -> 878640 bytes roms/SLOF | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pc-bios/README b/pc-bios/README index e71bcd0f36..f4b37d66dc 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -17,7 +17,7 @@ - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at https://github.com/dgibson/SLOF, and the image currently in qemu is - built from git tag qemu-slof-20120719. + built from git tag qemu-slof-20120731. - sgabios (the Serial Graphics Adapter option ROM) provides a means for legacy x86 software to communicate with an attached serial console as diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin index 320b8f001cf9962318812a5b9109242e210fe499..84ba6b83f3c7fe523cb0b0e73ae8522872d1feef 100644 GIT binary patch delta 970 zcmb7?&rj1}7{}MHWur`EB4Q#5J^>FyEv#cd%oLfCAtXX(Fu02e-P%GE=tfsyBt|@F zSYk|ANO(yQ4szk32}Vh8WXBzdfeU&tWdDHH$iSQUc5D-a9()HPU+b3bFB=G=@<4Cs8-k&`RR8>J6<_>do|MQf3osJONJN z1wjRtg=WSJiI~jB_yjA-iU5^x0zNCsnwbt^JOMpjjQa|x8lPliaYd4c*vTMPJHfQY zCz=``!G0X5$zfU2zz=-c??^LU5(U}<92T0MKDc4}a*&+l6EJdAXnIbFF)gkpo3Kt) zVsSxaWkrKVkfWnlRdK8d|FaRyUPM)!VnTQOLrhB}^e7Yjh%7*Fe^1!~l=0E1sN&L= zX^5%J{q9iT(c?N3D7KERQYW!++~2wU7nam9E`G@={U%bvTm(~51vpp0g*!&K=IFDX ze^Mx4!M|v*sbf4UO`;c{sTTC%BW1f-zWgG0^U5oIGXmy_h%eMR{qiG5eX56edMZQO z2T}Gr{g|u{qu?H1@3>IbTq8jgEYMwKID!VZ?e%D-K-ZHG*HE@V`xqlm!wFG(YXf=jkK(pZ>@EZK0{aaQAGaMtLNCCBR= JwSK90?HATCK#BkW delta 440 zcmdmR!L;Ly=>#*TG>(ZDrp(G>1``WJSlV;HR7_ux!Yekpp4VaHy+!r{=0@h0W~Qcz zX-26@i58}&nYUZfNSOo1`uGISup(uGov5VJB{fYER1GMZx(D%U}3yBkLzs$NS;sRZNhes#fd1jNkS<@8x9)=r;&k41HQ*Bus~_V@Q#w!go}`dyTX&0_kCFRXP; z>>ATEz5;1ij_EHzbeP2SjBl)NOnwH_H+*9?V~XyW{sKsIyM&)^S0$$#er1)Ke(F1`4Aa{k(_egNwPX5}F1XurV3w*3MV`?NVyZv%kVumZ6f o*t+H`6(Abu>w@-%`RqW<0mPg@%mu{U+Z*QdtU1B*d19Rx0DW1U^8f$< diff --git a/roms/SLOF b/roms/SLOF index 7279655af2..f21f7a3f46 160000 --- a/roms/SLOF +++ b/roms/SLOF @@ -1 +1 @@ -Subproject commit 7279655af2eba855bd2df61303d25abd1eeb2300 +Subproject commit f21f7a3f46b557eb5923f899ce8b4401b3cc6d91 From 3e77223293bcb9277f7b760b88f694f097f29c33 Mon Sep 17 00:00:00 2001 From: Bharat Bhushan Date: Tue, 14 Aug 2012 04:30:55 +0000 Subject: [PATCH 0026/2270] openpic: Added BRR1 register Linux mpic driver uses (changes may be in pipeline to get upstreamed soon) BRR1. This patch adds the support to emulate readonly FSL BRR1 register. Currently QEMU does not fully emulate any version on MPIC, so the MPIC Major number and Minor number are set to 0. Signed-off-by: Bharat Bhushan Signed-off-by: Alexander Graf --- hw/openpic.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/hw/openpic.c b/hw/openpic.c index 58ef871f68..b9d856830a 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -130,6 +130,17 @@ enum { #define MPIC_CPU_REG_START 0x20000 #define MPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000) +/* + * Block Revision Register1 (BRR1): QEMU does not fully emulate + * any version on MPIC. So to start with, set the IP version to 0. + * + * NOTE: This is Freescale MPIC specific register. Keep it here till + * this code is refactored for different variants of OPENPIC and MPIC. + */ +#define FSL_BRR1_IPID (0x0040 << 16) /* 16 bit IP-block ID */ +#define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */ +#define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */ + enum mpic_ide_bits { IDR_EP = 31, IDR_CI0 = 30, @@ -595,6 +606,8 @@ static void openpic_gbl_write (void *opaque, target_phys_addr_t addr, uint32_t v if (addr & 0xF) return; switch (addr) { + case 0x00: /* Block Revision Register1 (BRR1) is Readonly */ + break; case 0x40: case 0x50: case 0x60: @@ -671,6 +684,7 @@ static uint32_t openpic_gbl_read (void *opaque, target_phys_addr_t addr) case 0x1090: /* PINT */ retval = 0x00000000; break; + case 0x00: /* Block Revision Register1 (BRR1) */ case 0x40: case 0x50: case 0x60: @@ -893,6 +907,9 @@ static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr, dst = &opp->dst[idx]; addr &= 0xFF0; switch (addr) { + case 0x00: /* Block Revision Register1 (BRR1) */ + retval = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN; + break; case 0x80: /* PCTP */ retval = dst->pctp; break; From c19537a1143d493897850576394f082914f39ef1 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 9 Aug 2012 10:57:32 +0200 Subject: [PATCH 0027/2270] usb: async control xfer fixup Need to clear p->result after copying setup data using usb_packet_copy() because we'll reuse the USBPacket for the data transfer. Signed-off-by: Gerd Hoffmann --- hw/usb/core.c | 1 + hw/usb/host-linux.c | 1 + 2 files changed, 2 insertions(+) diff --git a/hw/usb/core.c b/hw/usb/core.c index 01a7622837..c7e5bc047f 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -107,6 +107,7 @@ static int do_token_setup(USBDevice *s, USBPacket *p) } usb_packet_copy(p, s->setup_buf, p->iov.size); + p->result = 0; s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6]; s->setup_index = 0; diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c index d55be878ad..8df92074d3 100644 --- a/hw/usb/host-linux.c +++ b/hw/usb/host-linux.c @@ -1045,6 +1045,7 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p, /* Note request is (bRequestType << 8) | bRequest */ trace_usb_host_req_control(s->bus_num, s->addr, p, request, value, index); + assert(p->result == 0); switch (request) { case DeviceOutRequest | USB_REQ_SET_ADDRESS: From 0daf53047da0b817e40c4931580e59e73b420f41 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 10 Aug 2012 13:06:05 +0200 Subject: [PATCH 0028/2270] usb: update uas product id Pick other product id to fix clash with audio. Current usage list (after applying this patch): 46f4:0001 -- usb-storage 46f4:0002 -- usb-audio 46f4:0003 -- usb-uas Signed-off-by: Gerd Hoffmann --- hw/usb/dev-uas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index 9b02ff48fa..b13eeba565 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -223,7 +223,7 @@ static const USBDescDevice desc_device_high = { static const USBDesc desc = { .id = { .idVendor = 0x46f4, /* CRC16() of "QEMU" */ - .idProduct = 0x0002, + .idProduct = 0x0003, .bcdDevice = 0, .iManufacturer = STR_MANUFACTURER, .iProduct = STR_PRODUCT, From 6d3b6d3d2deaf682def95e3e512ad0e17f02274f Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 15 Aug 2012 13:55:40 +0200 Subject: [PATCH 0029/2270] ehci: fix Interrupt Threshold Control implementation First, not all interrupts are subject to Interrupt Threshold Control, some of them must be delivered without delay. Second, Interrupt Threshold Control state must be part of vmstate, otherwise we might loose IRQs on migration. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 104c21d315..e4895095cf 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -575,7 +575,12 @@ static inline void ehci_update_irq(EHCIState *s) /* flag interrupt condition */ static inline void ehci_raise_irq(EHCIState *s, int intr) { - s->usbsts_pending |= intr; + if (intr & (USBSTS_PCD | USBSTS_FLR | USBSTS_HSE)) { + s->usbsts |= intr; + ehci_update_irq(s); + } else { + s->usbsts_pending |= intr; + } } /* @@ -2466,13 +2471,16 @@ static int usb_ehci_post_load(void *opaque, int version_id) static const VMStateDescription vmstate_ehci = { .name = "ehci", - .version_id = 1, + .version_id = 2, + .minimum_version_id = 1, .post_load = usb_ehci_post_load, .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(dev, EHCIState), /* mmio registers */ VMSTATE_UINT32(usbcmd, EHCIState), VMSTATE_UINT32(usbsts, EHCIState), + VMSTATE_UINT32_V(usbsts_pending, EHCIState, 2), + VMSTATE_UINT32_V(usbsts_frindex, EHCIState, 2), VMSTATE_UINT32(usbintr, EHCIState), VMSTATE_UINT32(frindex, EHCIState), VMSTATE_UINT32(ctrldssegment, EHCIState), From 47d073cc3b8ad4a3ef1dba7055b35a87fa4091ff Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 15 Aug 2012 17:08:54 +0200 Subject: [PATCH 0030/2270] ehci: Fix setting of halt bit from usbcmd register updates This fixes linux guests started without any USB devices not seeing newly plugged devices until "lsusb" is done inside the guest. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index e4895095cf..8b94b17723 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1187,22 +1187,23 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) break; } - if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) != - ((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) { - if (s->pstate == EST_INACTIVE) { - SET_LAST_RUN_CLOCK(s); - } - ehci_update_halt(s); - s->async_stepdown = 0; - qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock)); - } - /* not supporting dynamic frame list size at the moment */ if ((val & USBCMD_FLS) && !(s->usbcmd & USBCMD_FLS)) { fprintf(stderr, "attempt to set frame list size -- value %d\n", val & USBCMD_FLS); val &= ~USBCMD_FLS; } + + if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) != + ((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) { + if (s->pstate == EST_INACTIVE) { + SET_LAST_RUN_CLOCK(s); + } + s->usbcmd = val; /* Set usbcmd for ehci_update_halt() */ + ehci_update_halt(s); + s->async_stepdown = 0; + qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock)); + } break; case USBSTS: From 5a4d701acde890a5ca134236424ece45545f70c7 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 16 Aug 2012 11:01:11 +0200 Subject: [PATCH 0031/2270] audio: Make pcspk card selectable again [ The following text is in the "ISO-8859-1" character set. ] [ Your display is set for the "KOI8-R" character set. ] [ Some special characters may be displayed incorrectly. ] Since we moved pcspk into hwlib, CONFIG_PCSPK is no longer defined per target. Therefore, statically built soundhw array in arch_init.c stopped including this card. Work around this by re-adding this define to config-target.mak. Long-term, a dynamic creation of this soundhw list will be necessary. Signed-off-by: Jan Kiszka Signed-off-by: malc --- configure | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure b/configure index edf9da44b5..cc774b5fd9 100755 --- a/configure +++ b/configure @@ -3881,6 +3881,11 @@ if test "$target_bsd_user" = "yes" ; then echo "CONFIG_BSD_USER=y" >> $config_target_mak fi +# the static way of configuring available audio cards requires this workaround +if test "$target_user_only" != "yes" && grep -q CONFIG_PCSPK $source_path/default-configs/$target.mak; then + echo "CONFIG_PCSPK=y" >> $config_target_mak +fi + # generate QEMU_CFLAGS/LDFLAGS for targets cflags="" From a86a4c2f7b7f0b72816ea1c219d8140699b6665b Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Wed, 15 Aug 2012 13:45:42 -0500 Subject: [PATCH 0032/2270] qlist: add qlist_size() Signed-off-by: Michael Roth Reviewed-by: Eric Blake Signed-off-by: Michael Roth Signed-off-by: Anthony Liguori --- qlist.c | 13 +++++++++++++ qlist.h | 1 + 2 files changed, 14 insertions(+) diff --git a/qlist.c b/qlist.c index 88498b157f..b48ec5b914 100644 --- a/qlist.c +++ b/qlist.c @@ -124,6 +124,19 @@ int qlist_empty(const QList *qlist) return QTAILQ_EMPTY(&qlist->head); } +static void qlist_size_iter(QObject *obj, void *opaque) +{ + size_t *count = opaque; + (*count)++; +} + +size_t qlist_size(const QList *qlist) +{ + size_t count = 0; + qlist_iter(qlist, qlist_size_iter, &count); + return count; +} + /** * qobject_to_qlist(): Convert a QObject into a QList */ diff --git a/qlist.h b/qlist.h index d426bd4a4b..ae776f99c3 100644 --- a/qlist.h +++ b/qlist.h @@ -49,6 +49,7 @@ void qlist_iter(const QList *qlist, QObject *qlist_pop(QList *qlist); QObject *qlist_peek(QList *qlist); int qlist_empty(const QList *qlist); +size_t qlist_size(const QList *qlist); QList *qobject_to_qlist(const QObject *obj); static inline const QListEntry *qlist_first(const QList *qlist) From 65c0f1e9558c7c762cdb333406243fff1d687117 Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Wed, 15 Aug 2012 13:45:43 -0500 Subject: [PATCH 0033/2270] json-parser: don't replicate tokens at each level of recursion Currently, when parsing a stream of tokens we make a copy of the token list at the beginning of each level of recursion so that we do not modify the original list in cases where we need to fall back to an earlier state. In the worst case, we will only read 1 or 2 tokens off the list before recursing again, which means an upper bound of roughly N^2 token allocations. For a "reasonably" sized QMP request (in this a QMP representation of cirrus_vga's device state, generated via QIDL, being passed in via qom-set), this caused my 16GB's of memory to be exhausted before any noticeable progress was made by the parser. This patch works around the issue by using single copy of the token list in the form of an indexable array so that we can save/restore state by manipulating indices. A subsequent commit adds a "large_dict" test case which exhibits the same behavior as above. With this patch applied the test case successfully completes in under a second. Tested with valgrind, make check, and QMP. Reviewed-by: Eric Blake Signed-off-by: Michael Roth Signed-off-by: Anthony Liguori --- json-parser.c | 230 +++++++++++++++++++++++++++++++------------------- 1 file changed, 142 insertions(+), 88 deletions(-) diff --git a/json-parser.c b/json-parser.c index 849e2156da..457291b161 100644 --- a/json-parser.c +++ b/json-parser.c @@ -27,6 +27,11 @@ typedef struct JSONParserContext { Error *err; + struct { + QObject **buf; + size_t pos; + size_t count; + } tokens; } JSONParserContext; #define BUG_ON(cond) assert(!(cond)) @@ -40,7 +45,7 @@ typedef struct JSONParserContext * 4) deal with premature EOI */ -static QObject *parse_value(JSONParserContext *ctxt, QList **tokens, va_list *ap); +static QObject *parse_value(JSONParserContext *ctxt, va_list *ap); /** * Token manipulators @@ -270,27 +275,111 @@ out: return NULL; } +static QObject *parser_context_pop_token(JSONParserContext *ctxt) +{ + QObject *token; + g_assert(ctxt->tokens.pos < ctxt->tokens.count); + token = ctxt->tokens.buf[ctxt->tokens.pos]; + ctxt->tokens.pos++; + return token; +} + +/* Note: parser_context_{peek|pop}_token do not increment the + * token object's refcount. In both cases the references will continue + * to be tracked and cleaned up in parser_context_free(), so do not + * attempt to free the token object. + */ +static QObject *parser_context_peek_token(JSONParserContext *ctxt) +{ + QObject *token; + g_assert(ctxt->tokens.pos < ctxt->tokens.count); + token = ctxt->tokens.buf[ctxt->tokens.pos]; + return token; +} + +static JSONParserContext parser_context_save(JSONParserContext *ctxt) +{ + JSONParserContext saved_ctxt = {0}; + saved_ctxt.tokens.pos = ctxt->tokens.pos; + saved_ctxt.tokens.count = ctxt->tokens.count; + saved_ctxt.tokens.buf = ctxt->tokens.buf; + return saved_ctxt; +} + +static void parser_context_restore(JSONParserContext *ctxt, + JSONParserContext saved_ctxt) +{ + ctxt->tokens.pos = saved_ctxt.tokens.pos; + ctxt->tokens.count = saved_ctxt.tokens.count; + ctxt->tokens.buf = saved_ctxt.tokens.buf; +} + +static void tokens_append_from_iter(QObject *obj, void *opaque) +{ + JSONParserContext *ctxt = opaque; + g_assert(ctxt->tokens.pos < ctxt->tokens.count); + ctxt->tokens.buf[ctxt->tokens.pos++] = obj; + qobject_incref(obj); +} + +static JSONParserContext *parser_context_new(QList *tokens) +{ + JSONParserContext *ctxt; + size_t count; + + if (!tokens) { + return NULL; + } + + count = qlist_size(tokens); + if (count == 0) { + return NULL; + } + + ctxt = g_malloc0(sizeof(JSONParserContext)); + ctxt->tokens.pos = 0; + ctxt->tokens.count = count; + ctxt->tokens.buf = g_malloc(count * sizeof(QObject *)); + qlist_iter(tokens, tokens_append_from_iter, ctxt); + ctxt->tokens.pos = 0; + + return ctxt; +} + +/* to support error propagation, ctxt->err must be freed separately */ +static void parser_context_free(JSONParserContext *ctxt) +{ + int i; + if (ctxt) { + for (i = 0; i < ctxt->tokens.count; i++) { + qobject_decref(ctxt->tokens.buf[i]); + } + g_free(ctxt->tokens.buf); + g_free(ctxt); + } +} + /** * Parsing rules */ -static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_list *ap) +static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap) { QObject *key = NULL, *token = NULL, *value, *peek; - QList *working = qlist_copy(*tokens); + JSONParserContext saved_ctxt = parser_context_save(ctxt); - peek = qlist_peek(working); + peek = parser_context_peek_token(ctxt); if (peek == NULL) { parse_error(ctxt, NULL, "premature EOI"); goto out; } - key = parse_value(ctxt, &working, ap); + key = parse_value(ctxt, ap); if (!key || qobject_type(key) != QTYPE_QSTRING) { parse_error(ctxt, peek, "key is not a string in object"); goto out; } - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { parse_error(ctxt, NULL, "premature EOI"); goto out; @@ -301,7 +390,7 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_l goto out; } - value = parse_value(ctxt, &working, ap); + value = parse_value(ctxt, ap); if (value == NULL) { parse_error(ctxt, token, "Missing value in dict"); goto out; @@ -309,28 +398,24 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_l qdict_put_obj(dict, qstring_get_str(qobject_to_qstring(key)), value); - qobject_decref(token); qobject_decref(key); - QDECREF(*tokens); - *tokens = working; return 0; out: - qobject_decref(token); + parser_context_restore(ctxt, saved_ctxt); qobject_decref(key); - QDECREF(working); return -1; } -static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *ap) +static QObject *parse_object(JSONParserContext *ctxt, va_list *ap) { QDict *dict = NULL; QObject *token, *peek; - QList *working = qlist_copy(*tokens); + JSONParserContext saved_ctxt = parser_context_save(ctxt); - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { goto out; } @@ -338,23 +423,22 @@ static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *a if (!token_is_operator(token, '{')) { goto out; } - qobject_decref(token); token = NULL; dict = qdict_new(); - peek = qlist_peek(working); + peek = parser_context_peek_token(ctxt); if (peek == NULL) { parse_error(ctxt, NULL, "premature EOI"); goto out; } if (!token_is_operator(peek, '}')) { - if (parse_pair(ctxt, dict, &working, ap) == -1) { + if (parse_pair(ctxt, dict, ap) == -1) { goto out; } - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { parse_error(ctxt, NULL, "premature EOI"); goto out; @@ -365,59 +449,52 @@ static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *a parse_error(ctxt, token, "expected separator in dict"); goto out; } - qobject_decref(token); token = NULL; - if (parse_pair(ctxt, dict, &working, ap) == -1) { + if (parse_pair(ctxt, dict, ap) == -1) { goto out; } - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { parse_error(ctxt, NULL, "premature EOI"); goto out; } } - qobject_decref(token); token = NULL; } else { - token = qlist_pop(working); - qobject_decref(token); + token = parser_context_pop_token(ctxt); token = NULL; } - QDECREF(*tokens); - *tokens = working; - return QOBJECT(dict); out: - qobject_decref(token); - QDECREF(working); + parser_context_restore(ctxt, saved_ctxt); QDECREF(dict); return NULL; } -static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap) +static QObject *parse_array(JSONParserContext *ctxt, va_list *ap) { QList *list = NULL; QObject *token, *peek; - QList *working = qlist_copy(*tokens); + JSONParserContext saved_ctxt = parser_context_save(ctxt); - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { goto out; } if (!token_is_operator(token, '[')) { + token = NULL; goto out; } - qobject_decref(token); token = NULL; list = qlist_new(); - peek = qlist_peek(working); + peek = parser_context_peek_token(ctxt); if (peek == NULL) { parse_error(ctxt, NULL, "premature EOI"); goto out; @@ -426,7 +503,7 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap if (!token_is_operator(peek, ']')) { QObject *obj; - obj = parse_value(ctxt, &working, ap); + obj = parse_value(ctxt, ap); if (obj == NULL) { parse_error(ctxt, token, "expecting value"); goto out; @@ -434,7 +511,7 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap qlist_append_obj(list, obj); - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { parse_error(ctxt, NULL, "premature EOI"); goto out; @@ -446,10 +523,9 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap goto out; } - qobject_decref(token); token = NULL; - obj = parse_value(ctxt, &working, ap); + obj = parse_value(ctxt, ap); if (obj == NULL) { parse_error(ctxt, token, "expecting value"); goto out; @@ -457,39 +533,33 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap qlist_append_obj(list, obj); - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { parse_error(ctxt, NULL, "premature EOI"); goto out; } } - qobject_decref(token); token = NULL; } else { - token = qlist_pop(working); - qobject_decref(token); + token = parser_context_pop_token(ctxt); token = NULL; } - QDECREF(*tokens); - *tokens = working; - return QOBJECT(list); out: - qobject_decref(token); - QDECREF(working); + parser_context_restore(ctxt, saved_ctxt); QDECREF(list); return NULL; } -static QObject *parse_keyword(JSONParserContext *ctxt, QList **tokens) +static QObject *parse_keyword(JSONParserContext *ctxt) { QObject *token, *ret; - QList *working = qlist_copy(*tokens); + JSONParserContext saved_ctxt = parser_context_save(ctxt); - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { goto out; } @@ -507,29 +577,24 @@ static QObject *parse_keyword(JSONParserContext *ctxt, QList **tokens) goto out; } - qobject_decref(token); - QDECREF(*tokens); - *tokens = working; - return ret; out: - qobject_decref(token); - QDECREF(working); + parser_context_restore(ctxt, saved_ctxt); return NULL; } -static QObject *parse_escape(JSONParserContext *ctxt, QList **tokens, va_list *ap) +static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap) { QObject *token = NULL, *obj; - QList *working = qlist_copy(*tokens); + JSONParserContext saved_ctxt = parser_context_save(ctxt); if (ap == NULL) { goto out; } - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { goto out; } @@ -553,25 +618,20 @@ static QObject *parse_escape(JSONParserContext *ctxt, QList **tokens, va_list *a goto out; } - qobject_decref(token); - QDECREF(*tokens); - *tokens = working; - return obj; out: - qobject_decref(token); - QDECREF(working); + parser_context_restore(ctxt, saved_ctxt); return NULL; } -static QObject *parse_literal(JSONParserContext *ctxt, QList **tokens) +static QObject *parse_literal(JSONParserContext *ctxt) { QObject *token, *obj; - QList *working = qlist_copy(*tokens); + JSONParserContext saved_ctxt = parser_context_save(ctxt); - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { goto out; } @@ -591,35 +651,30 @@ static QObject *parse_literal(JSONParserContext *ctxt, QList **tokens) goto out; } - qobject_decref(token); - QDECREF(*tokens); - *tokens = working; - return obj; out: - qobject_decref(token); - QDECREF(working); + parser_context_restore(ctxt, saved_ctxt); return NULL; } -static QObject *parse_value(JSONParserContext *ctxt, QList **tokens, va_list *ap) +static QObject *parse_value(JSONParserContext *ctxt, va_list *ap) { QObject *obj; - obj = parse_object(ctxt, tokens, ap); + obj = parse_object(ctxt, ap); if (obj == NULL) { - obj = parse_array(ctxt, tokens, ap); + obj = parse_array(ctxt, ap); } if (obj == NULL) { - obj = parse_escape(ctxt, tokens, ap); + obj = parse_escape(ctxt, ap); } if (obj == NULL) { - obj = parse_keyword(ctxt, tokens); + obj = parse_keyword(ctxt); } if (obj == NULL) { - obj = parse_literal(ctxt, tokens); + obj = parse_literal(ctxt); } return obj; @@ -632,19 +687,18 @@ QObject *json_parser_parse(QList *tokens, va_list *ap) QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp) { - JSONParserContext ctxt = {}; - QList *working; + JSONParserContext *ctxt = parser_context_new(tokens); QObject *result; - if (!tokens) { + if (!ctxt) { return NULL; } - working = qlist_copy(tokens); - result = parse_value(&ctxt, &working, ap); - QDECREF(working); + result = parse_value(ctxt, ap); - error_propagate(errp, ctxt.err); + error_propagate(errp, ctxt->err); + + parser_context_free(ctxt); return result; } From 7109edfeb69c1d3c2164175837784dfcd210fed0 Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Wed, 15 Aug 2012 13:45:44 -0500 Subject: [PATCH 0034/2270] check-qjson: add test for large JSON objects Signed-off-by: Michael Roth Signed-off-by: Anthony Liguori --- tests/check-qjson.c | 53 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/tests/check-qjson.c b/tests/check-qjson.c index 526e25ef6d..3b896f5f9c 100644 --- a/tests/check-qjson.c +++ b/tests/check-qjson.c @@ -466,6 +466,58 @@ static void simple_dict(void) } } +/* + * this generates json of the form: + * a(0,m) = [0, 1, ..., m-1] + * a(n,m) = { + * 'key0': a(0,m), + * 'key1': a(1,m), + * ... + * 'key(n-1)': a(n-1,m) + * } + */ +static void gen_test_json(GString *gstr, int nest_level_max, + int elem_count) +{ + int i; + + g_assert(gstr); + if (nest_level_max == 0) { + g_string_append(gstr, "["); + for (i = 0; i < elem_count; i++) { + g_string_append_printf(gstr, "%d", i); + if (i < elem_count - 1) { + g_string_append_printf(gstr, ", "); + } + } + g_string_append(gstr, "]"); + return; + } + + g_string_append(gstr, "{"); + for (i = 0; i < nest_level_max; i++) { + g_string_append_printf(gstr, "'key%d': ", i); + gen_test_json(gstr, i, elem_count); + if (i < nest_level_max - 1) { + g_string_append(gstr, ","); + } + } + g_string_append(gstr, "}"); +} + +static void large_dict(void) +{ + GString *gstr = g_string_new(""); + QObject *obj; + + gen_test_json(gstr, 10, 100); + obj = qobject_from_json(gstr->str); + g_assert(obj != NULL); + + qobject_decref(obj); + g_string_free(gstr, true); +} + static void simple_list(void) { int i; @@ -706,6 +758,7 @@ int main(int argc, char **argv) g_test_add_func("/literals/keyword", keyword_literal); g_test_add_func("/dicts/simple_dict", simple_dict); + g_test_add_func("/dicts/large_dict", large_dict); g_test_add_func("/lists/simple_list", simple_list); g_test_add_func("/whitespace/simple_whitespace", simple_whitespace); From bbea4050802a2e7e0296a21823c0925782c02b93 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 14 Aug 2012 15:35:34 +0100 Subject: [PATCH 0035/2270] configure: Don't override user's --cpu on MacOS and Solaris Both MacOS and Solaris have special case handling for the CPU type, because the check_define probes will return i386 even if the hardware is 64 bit and x86_64 would be preferable. Move these checks earlier in the configure probing so that we can do them only if the user didn't specify a CPU with --cpu. This fixes a bug where the user's command line argument was being ignored. Reviewed-by: Andreas F=E4rber Signed-off-by: Peter Maydell Signed-off-by: Anthony Liguori --- configure | 60 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/configure b/configure index cc774b5fd9..d08c0ce028 100755 --- a/configure +++ b/configure @@ -298,6 +298,41 @@ EOF compile_object } +if check_define __linux__ ; then + targetos="Linux" +elif check_define _WIN32 ; then + targetos='MINGW32' +elif check_define __OpenBSD__ ; then + targetos='OpenBSD' +elif check_define __sun__ ; then + targetos='SunOS' +elif check_define __HAIKU__ ; then + targetos='Haiku' +else + targetos=`uname -s` +fi + +# Some host OSes need non-standard checks for which CPU to use. +# Note that these checks are broken for cross-compilation: if you're +# cross-compiling to one of these OSes then you'll need to specify +# the correct CPU with the --cpu option. +case $targetos in +Darwin) + # on Leopard most of the system is 32-bit, so we have to ask the kernel if we can + # run 64-bit userspace code. + # If the user didn't specify a CPU explicitly and the kernel says this is + # 64 bit hw, then assume x86_64. Otherwise fall through to the usual detection code. + if test -z "$cpu" && test "$(sysctl -n hw.optional.x86_64)" = "1"; then + cpu="x86_64" + fi + ;; +SunOS) + # `uname -m` returns i86pc even on an x86_64 box, so default based on isainfo + if test -z "$cpu" && test "$(isainfo -k)" = "amd64"; then + cpu="x86_64" + fi +esac + if test ! -z "$cpu" ; then # command line argument : @@ -372,19 +407,6 @@ if test -z "$ARCH"; then fi # OS specific -if check_define __linux__ ; then - targetos="Linux" -elif check_define _WIN32 ; then - targetos='MINGW32' -elif check_define __OpenBSD__ ; then - targetos='OpenBSD' -elif check_define __sun__ ; then - targetos='SunOS' -elif check_define __HAIKU__ ; then - targetos='Haiku' -else - targetos=`uname -s` -fi case $targetos in CYGWIN*) @@ -434,12 +456,6 @@ OpenBSD) Darwin) bsd="yes" darwin="yes" - # on Leopard most of the system is 32-bit, so we have to ask the kernel it if we can - # run 64-bit userspace code - if [ "$cpu" = "i386" ] ; then - is_x86_64=`sysctl -n hw.optional.x86_64` - [ "$is_x86_64" = "1" ] && cpu=x86_64 - fi if [ "$cpu" = "x86_64" ] ; then QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS" LDFLAGS="-arch x86_64 $LDFLAGS" @@ -460,12 +476,6 @@ SunOS) smbd="${SMBD-/usr/sfw/sbin/smbd}" needs_libsunmath="no" solarisrev=`uname -r | cut -f2 -d.` - # have to select again, because `uname -m` returns i86pc - # even on an x86_64 box. - solariscpu=`isainfo -k` - if test "${solariscpu}" = "amd64" ; then - cpu="x86_64" - fi if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then if test "$solarisrev" -le 9 ; then if test -f /opt/SUNWspro/prod/lib/libsunmath.so.1; then From a0b7cf6b6ecc91e730de5ac6a6f7f927d16f89ca Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sat, 11 Aug 2012 22:34:39 +0100 Subject: [PATCH 0036/2270] configure: Define OS_OBJECT_USE_OBJC=0 for MacOSX builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MacOSX 10.8 ("Mountain Lion") defaults to trying to use automated reference counting on certain objects. This means that the system header files will use some Objective C syntax constructs even when compiling pure C, which confuses mainline gcc. Suppress this by setting OS_OBJECT_USE_OBJC=0. This avoids a compile error like this: In file included from /System/Library/Frameworks/Foundation.framework/Headers/NSObject.h:5:0, from /usr/include/os/object.h:74, from /usr/include/dispatch/dispatch.h:48, from /System/Library/Frameworks/IOKit.framework/Headers/IOKitLib.h:56, from block/raw-posix.c:35: /System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:409:1: error: stray ‘@’ in program [with a large number of further run-on errors] Signed-off-by: Peter Maydell Signed-off-by: Anthony Liguori --- configure | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure b/configure index d08c0ce028..6f6f8e03f0 100755 --- a/configure +++ b/configure @@ -467,6 +467,9 @@ Darwin) audio_possible_drivers="coreaudio sdl fmod" LDFLAGS="-framework CoreFoundation -framework IOKit $LDFLAGS" libs_softmmu="-F/System/Library/Frameworks -framework Cocoa -framework IOKit $libs_softmmu" + # Disable attempts to use ObjectiveC features in os/object.h since they + # won't work when we're compiling with gcc as a C compiler. + QEMU_CFLAGS="-DOS_OBJECT_USE_OBJC=0 $QEMU_CFLAGS" ;; SunOS) solaris="yes" From 3c4a4d0dcbf4269e125f92df06816db1c1e86d20 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sat, 11 Aug 2012 22:34:40 +0100 Subject: [PATCH 0037/2270] Support using a different compiler for Objective-C files MacOSX 10.8 ("Mountain Lion") requires us to compile our one Objective-C source file with clang even if the rest of QEMU requires a real gcc, because the system headers we use make use of Apple's "Blocks" extension to C/ObjC, and mainline gcc doesn't support that. Since we only need to use a true gcc for the parts of QEMU that use the fixed-register env variable, we can simply use clang to build the ObjC file: it will link to the gcc-built objects with no problems. Add the necessary support for an OBJCC variable in the makefile and configure machinery; we default to clang if we have it, otherwise whatever CC is (since gcc might be the Apple gcc which does support Blocks). Signed-off-by: Peter Maydell Signed-off-by: Anthony Liguori --- configure | 12 ++++++++++++ rules.mak | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 6f6f8e03f0..f54326d432 100755 --- a/configure +++ b/configure @@ -543,6 +543,13 @@ fi : ${python=${PYTHON-python}} : ${smbd=${SMBD-/usr/sbin/smbd}} +# Default objcc to clang if available, otherwise use CC +if has clang; then + objcc=clang +else + objcc="$cc" +fi + if test "$mingw32" = "yes" ; then EXESUF=".exe" QEMU_CFLAGS="-DWIN32_LEAN_AND_MEAN -DWINVER=0x501 $QEMU_CFLAGS" @@ -586,6 +593,8 @@ for opt do ;; --host-cc=*) host_cc="$optarg" ;; + --objcc=*) objcc="$optarg" + ;; --make=*) make="$optarg" ;; --install=*) install="$optarg" @@ -1028,6 +1037,7 @@ echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]" echo " --cc=CC use C compiler CC [$cc]" echo " --host-cc=CC use C compiler CC [$host_cc] for code run at" echo " build time" +echo " --objcc=OBJCC use Objective-C compiler OBJCC [$objcc]" echo " --extra-cflags=CFLAGS append extra C compiler flags QEMU_CFLAGS" echo " --extra-ldflags=LDFLAGS append extra linker flags LDFLAGS" echo " --make=MAKE use specified make [$make]" @@ -3058,6 +3068,7 @@ fi echo "Source path $source_path" echo "C compiler $cc" echo "Host C compiler $host_cc" +echo "Objective-C compiler $objcc" echo "CFLAGS $CFLAGS" echo "QEMU_CFLAGS $QEMU_CFLAGS" echo "LDFLAGS $LDFLAGS" @@ -3521,6 +3532,7 @@ echo "PYTHON=$python" >> $config_host_mak echo "CC=$cc" >> $config_host_mak echo "CC_I386=$cc_i386" >> $config_host_mak echo "HOST_CC=$host_cc" >> $config_host_mak +echo "OBJCC=$objcc" >> $config_host_mak echo "AR=$ar" >> $config_host_mak echo "OBJCOPY=$objcopy" >> $config_host_mak echo "LD=$ld" >> $config_host_mak diff --git a/rules.mak b/rules.mak index a28494679a..1b173aa981 100644 --- a/rules.mak +++ b/rules.mak @@ -29,7 +29,7 @@ endif $(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," AS $(TARGET_DIR)$@") %.o: %.m - $(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," OBJC $(TARGET_DIR)$@") + $(call quiet-command,$(OBJCC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," OBJC $(TARGET_DIR)$@") LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(sort $(1)) $(LIBS)," LINK $(TARGET_DIR)$@") From ddb97f1debbb6be8d871f3b565f7b8befebf0f4f Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Thu, 2 Aug 2012 15:44:16 -0400 Subject: [PATCH 0038/2270] memory: add -machine dump-guest-core=on|off Add a new '[,dump-guest-core=on|off]' option to the '-machine' option. When 'dump-guest-core=off' is specified, guest memory is omitted from the core dump. The default behavior continues to be to include guest memory when a core dump is triggered. In my testing, this brought the core dump size down from 384MB to 6MB on a 2GB guest. Is anything additional required to preserve this setting for migration or savevm? I don't believe so. Changelog: v3: Eliminate globals as per Anthony's suggestion set no dump from qemu_ram_remap() as well v2: move the option from -m to -machine, rename option dump -> dump-guest-core Signed-off-by: Jason Baron Signed-off-by: Anthony Liguori --- exec.c | 21 +++++++++++++++++++++ osdep.h | 7 +++++++ qemu-config.c | 4 ++++ qemu-options.hx | 5 ++++- 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/exec.c b/exec.c index 929db5cf0a..58347664b2 100644 --- a/exec.c +++ b/exec.c @@ -2475,6 +2475,24 @@ static ram_addr_t last_ram_offset(void) return last; } +static void qemu_ram_setup_dump(void *addr, ram_addr_t size) +{ + int ret; + QemuOpts *machine_opts; + + /* Use MADV_DONTDUMP, if user doesn't want the guest memory in the core */ + machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); + if (machine_opts && + !qemu_opt_get_bool(machine_opts, "dump-guest-core", true)) { + ret = qemu_madvise(addr, size, QEMU_MADV_DONTDUMP); + if (ret) { + perror("qemu_madvise"); + fprintf(stderr, "madvise doesn't support MADV_DONTDUMP, " + "but dump_guest_core=off specified\n"); + } + } +} + void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) { RAMBlock *new_block, *block; @@ -2554,6 +2572,8 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, 0, size >> TARGET_PAGE_BITS); cpu_physical_memory_set_dirty_range(new_block->offset, size, 0xff); + qemu_ram_setup_dump(new_block->host, size); + if (kvm_enabled()) kvm_setup_guest_memory(new_block->host, size); @@ -2670,6 +2690,7 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) exit(1); } qemu_madvise(vaddr, length, QEMU_MADV_MERGEABLE); + qemu_ram_setup_dump(vaddr, length); } return; } diff --git a/osdep.h b/osdep.h index d4b887d542..cb213e0295 100644 --- a/osdep.h +++ b/osdep.h @@ -103,6 +103,11 @@ void qemu_vfree(void *ptr); #else #define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID #endif +#ifdef MADV_DONTDUMP +#define QEMU_MADV_DONTDUMP MADV_DONTDUMP +#else +#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID +#endif #elif defined(CONFIG_POSIX_MADVISE) @@ -110,6 +115,7 @@ void qemu_vfree(void *ptr); #define QEMU_MADV_DONTNEED POSIX_MADV_DONTNEED #define QEMU_MADV_DONTFORK QEMU_MADV_INVALID #define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID +#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID #else /* no-op */ @@ -117,6 +123,7 @@ void qemu_vfree(void *ptr); #define QEMU_MADV_DONTNEED QEMU_MADV_INVALID #define QEMU_MADV_DONTFORK QEMU_MADV_INVALID #define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID +#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID #endif diff --git a/qemu-config.c b/qemu-config.c index 5c3296b8c6..6700de0c71 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -595,6 +595,10 @@ static QemuOptsList qemu_machine_opts = { .name = "dt_compatible", .type = QEMU_OPT_STRING, .help = "Overrides the \"compatible\" property of the dt root node", + }, { + .name = "dump-guest-core", + .type = QEMU_OPT_BOOL, + .help = "Include guest memory in a core dump", }, { /* End of list */ } }, diff --git a/qemu-options.hx b/qemu-options.hx index 47cb5bd311..6aeef6a845 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -37,7 +37,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \ " property accel=accel1[:accel2[:...]] selects accelerator\n" " supported accelerators are kvm, xen, tcg (default: tcg)\n" " kernel_irqchip=on|off controls accelerated irqchip support\n" - " kvm_shadow_mem=size of KVM shadow MMU\n", + " kvm_shadow_mem=size of KVM shadow MMU\n" + " dump-guest-core=on|off include guest memory in a core dump (default=on)\n", QEMU_ARCH_ALL) STEXI @item -machine [type=]@var{name}[,prop=@var{value}[,...]] @@ -54,6 +55,8 @@ to initialize. Enables in-kernel irqchip support for the chosen accelerator when available. @item kvm_shadow_mem=size Defines the size of the KVM shadow MMU. +@item dump-guest-core=on|off +Include guest memory in a core dump. The default is on. @end table ETEXI From bc9b78debf63c9be051abe51403736d386092d09 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 14 Aug 2012 17:41:47 +1000 Subject: [PATCH 0039/2270] dma: Fix stupid typo/thinko Hi hard a brain fart when coding that function, it will fail to "set" the memory beyond the first 512 bytes. This is in turn causing guest crashes in ibmveth (spapr_llan.c on the qemu side) due to the receive queue not being properly initialized. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Anthony Liguori --- dma-helpers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dma-helpers.c b/dma-helpers.c index 13593d1b42..433d8b21b3 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -24,8 +24,8 @@ static void do_dma_memory_set(dma_addr_t addr, uint8_t c, dma_addr_t len) while (len > 0) { l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE; cpu_physical_memory_rw(addr, fillbuf, l, true); - len -= len; - addr += len; + len -= l; + addr += l; } } From f794573eab564548fa7aa463b5908b0042c0e6a4 Mon Sep 17 00:00:00 2001 From: Eduardo Otubo Date: Tue, 14 Aug 2012 18:44:05 -0300 Subject: [PATCH 0040/2270] Adding support for libseccomp in configure and Makefile (v8) Adding basic options to the configure script to use libseccomp or not. The default is set to 'no'. If the flag --enable-libseccomp is used, the script will check for its existence using pkg-config. Signed-off-by: Eduardo Otubo Signed-off-by: Anthony Liguori --- v1 -> v2: - As I removed all the code related to seccomp from vl.c, I created qemu-seccomp.[ch]. - Also making the configure script to add the specific line to Makefile.obj in order to compile with appropriate support to seccomp. v2 -> v3: - Removing the line from Makefile.obj and adding it to Makefile.objs. - Marking libseccomp default option to 'yes' in the configure script. v3 -> v8: - fix configure probe if libseccomp isn't available (aliguori) --- Makefile.objs | 6 ++++++ configure | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/Makefile.objs b/Makefile.objs index 309d066286..4412757309 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -96,6 +96,12 @@ common-obj-y += qemu-timer.o qemu-timer-common.o common-obj-$(CONFIG_SLIRP) += slirp/ +###################################################################### +# libseccomp +ifeq ($(CONFIG_SECCOMP),y) +common-obj-y += qemu-seccomp.o +endif + ###################################################################### # libuser diff --git a/configure b/configure index f54326d432..60d266fcca 100755 --- a/configure +++ b/configure @@ -218,6 +218,7 @@ zlib="yes" guest_agent="yes" libiscsi="" coroutine="" +seccomp="" # parse CC options first for opt do @@ -864,6 +865,10 @@ for opt do ;; --disable-guest-agent) guest_agent="no" ;; + --enable-seccomp) seccomp="yes" + ;; + --disable-seccomp) seccomp="no" + ;; *) echo "ERROR: unknown option $opt"; show_help="yes" ;; esac @@ -1152,6 +1157,8 @@ echo " --disable-usb-redir disable usb network redirection support" echo " --enable-usb-redir enable usb network redirection support" echo " --disable-guest-agent disable building of the QEMU Guest Agent" echo " --enable-guest-agent enable building of the QEMU Guest Agent" +echo " --disable-seccomp disable seccomp support" +echo " --enable-seccomp enables seccomp support" echo " --with-coroutine=BACKEND coroutine backend. Supported options:" echo " gthread, ucontext, sigaltstack, windows" echo "" @@ -1413,6 +1420,20 @@ EOF fi fi +########################################## +# libseccomp check + +if test "$seccomp" != "no" ; then + if $pkg_config libseccomp --modversion >/dev/null 2>&1; then + LIBS=`$pkg_config --libs libseccomp` + seccomp="yes" + else + seccomp="no" + if test "$seccomp" = "yes"; then + feature_not_found "libseccomp" + fi + fi +fi ########################################## # xen probe @@ -3143,6 +3164,7 @@ echo "usb net redir $usb_redir" echo "OpenGL support $opengl" echo "libiscsi support $libiscsi" echo "build guest agent $guest_agent" +echo "seccomp support $seccomp" echo "coroutine backend $coroutine_backend" if test "$sdl_too_old" = "yes"; then @@ -3438,6 +3460,10 @@ if test "$libiscsi" = "yes" ; then echo "CONFIG_LIBISCSI=y" >> $config_host_mak fi +if test "$seccomp" = "yes"; then + echo "CONFIG_SECCOMP=y" >> $config_host_mak +fi + # XXX: suppress that if [ "$bsd" = "yes" ] ; then echo "CONFIG_BSD=y" >> $config_host_mak From 2f668be77501c0232a84aafb6a066c9915987f0e Mon Sep 17 00:00:00 2001 From: Eduardo Otubo Date: Tue, 14 Aug 2012 18:44:06 -0300 Subject: [PATCH 0041/2270] Adding qemu-seccomp.[ch] (v8) Signed-off-by: Eduardo Otubo Signed-off-by: Anthony Liguori --- v1: - I added a syscall struct using priority levels as described in the libseccomp man page. The priority numbers are based to the frequency they appear in a sample strace from a regular qemu guest run under libvirt. Libseccomp generates linear BPF code to filter system calls, those rules are read one after another. The priority system places the most common rules first in order to reduce the overhead when processing them. v1 -> v2: - Fixed some style issues - Removed code from vl.c and created qemu-seccomp.[ch] - Now using ARRAY_SIZE macro - Added more syscalls without priority/frequency set yet v2 -> v3: - Adding copyright and license information - Replacing seccomp_whitelist_count just by ARRAY_SIZE - Adding header protection to qemu-seccomp.h - Moving QemuSeccompSyscall definition to qemu-seccomp.c - Negative return from seccomp_start is fatal now. - Adding open() and execve() to the whitelis v3 -> v4: - Tests revealed a bigger set of syscalls. - seccomp_start() now has an argument to set the mode according to the configure option trap or kill. v4 -> v5: - Tests on x86_64 required a new specific set of system calls. - libseccomp release 1.0.0: part of the API have changed in this last release, had to adapt to the new function signatures. --- qemu-seccomp.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++ qemu-seccomp.h | 22 ++++++++ 2 files changed, 163 insertions(+) create mode 100644 qemu-seccomp.c create mode 100644 qemu-seccomp.h diff --git a/qemu-seccomp.c b/qemu-seccomp.c new file mode 100644 index 0000000000..64329a3c09 --- /dev/null +++ b/qemu-seccomp.c @@ -0,0 +1,141 @@ +/* + * QEMU seccomp mode 2 support with libseccomp + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Eduardo Otubo + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ +#include +#include +#include "qemu-seccomp.h" + +struct QemuSeccompSyscall { + int32_t num; + uint8_t priority; +}; + +static const struct QemuSeccompSyscall seccomp_whitelist[] = { + { SCMP_SYS(timer_settime), 255 }, + { SCMP_SYS(timer_gettime), 254 }, + { SCMP_SYS(futex), 253 }, + { SCMP_SYS(select), 252 }, + { SCMP_SYS(recvfrom), 251 }, + { SCMP_SYS(sendto), 250 }, + { SCMP_SYS(read), 249 }, + { SCMP_SYS(brk), 248 }, + { SCMP_SYS(clone), 247 }, + { SCMP_SYS(mmap), 247 }, + { SCMP_SYS(mprotect), 246 }, + { SCMP_SYS(execve), 245 }, + { SCMP_SYS(open), 245 }, + { SCMP_SYS(ioctl), 245 }, + { SCMP_SYS(recvmsg), 245 }, + { SCMP_SYS(sendmsg), 245 }, + { SCMP_SYS(accept), 245 }, + { SCMP_SYS(connect), 245 }, + { SCMP_SYS(gettimeofday), 245 }, + { SCMP_SYS(readlink), 245 }, + { SCMP_SYS(access), 245 }, + { SCMP_SYS(prctl), 245 }, + { SCMP_SYS(signalfd), 245 }, +#if defined(__i386__) + { SCMP_SYS(fcntl64), 245 }, + { SCMP_SYS(fstat64), 245 }, + { SCMP_SYS(stat64), 245 }, + { SCMP_SYS(getgid32), 245 }, + { SCMP_SYS(getegid32), 245 }, + { SCMP_SYS(getuid32), 245 }, + { SCMP_SYS(geteuid32), 245 }, + { SCMP_SYS(sigreturn), 245 }, + { SCMP_SYS(_newselect), 245 }, + { SCMP_SYS(_llseek), 245 }, + { SCMP_SYS(mmap2), 245}, + { SCMP_SYS(sigprocmask), 245 }, +#elif defined(__x86_64__) + { SCMP_SYS(sched_getparam), 245}, + { SCMP_SYS(sched_getscheduler), 245}, + { SCMP_SYS(fstat), 245}, + { SCMP_SYS(clock_getres), 245}, + { SCMP_SYS(sched_get_priority_min), 245}, + { SCMP_SYS(sched_get_priority_max), 245}, + { SCMP_SYS(stat), 245}, + { SCMP_SYS(socket), 245}, + { SCMP_SYS(setsockopt), 245}, + { SCMP_SYS(uname), 245}, + { SCMP_SYS(semget), 245}, +#endif + { SCMP_SYS(eventfd2), 245 }, + { SCMP_SYS(dup), 245 }, + { SCMP_SYS(gettid), 245 }, + { SCMP_SYS(timer_create), 245 }, + { SCMP_SYS(exit), 245 }, + { SCMP_SYS(clock_gettime), 245 }, + { SCMP_SYS(time), 245 }, + { SCMP_SYS(restart_syscall), 245 }, + { SCMP_SYS(pwrite64), 245 }, + { SCMP_SYS(chown), 245 }, + { SCMP_SYS(openat), 245 }, + { SCMP_SYS(getdents), 245 }, + { SCMP_SYS(timer_delete), 245 }, + { SCMP_SYS(exit_group), 245 }, + { SCMP_SYS(rt_sigreturn), 245 }, + { SCMP_SYS(sync), 245 }, + { SCMP_SYS(pread64), 245 }, + { SCMP_SYS(madvise), 245 }, + { SCMP_SYS(set_robust_list), 245 }, + { SCMP_SYS(lseek), 245 }, + { SCMP_SYS(pselect6), 245 }, + { SCMP_SYS(fork), 245 }, + { SCMP_SYS(bind), 245 }, + { SCMP_SYS(listen), 245 }, + { SCMP_SYS(eventfd), 245 }, + { SCMP_SYS(rt_sigprocmask), 245 }, + { SCMP_SYS(write), 244 }, + { SCMP_SYS(fcntl), 243 }, + { SCMP_SYS(tgkill), 242 }, + { SCMP_SYS(rt_sigaction), 242 }, + { SCMP_SYS(pipe2), 242 }, + { SCMP_SYS(munmap), 242 }, + { SCMP_SYS(mremap), 242 }, + { SCMP_SYS(getsockname), 242 }, + { SCMP_SYS(getpeername), 242 }, + { SCMP_SYS(fdatasync), 242 }, + { SCMP_SYS(close), 242 } +}; + +int seccomp_start(void) +{ + int rc = 0; + unsigned int i = 0; + scmp_filter_ctx ctx; + + ctx = seccomp_init(SCMP_ACT_KILL); + if (ctx == NULL) { + goto seccomp_return; + } + + for (i = 0; i < ARRAY_SIZE(seccomp_whitelist); i++) { + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, seccomp_whitelist[i].num, 0); + if (rc < 0) { + goto seccomp_return; + } + rc = seccomp_syscall_priority(ctx, seccomp_whitelist[i].num, + seccomp_whitelist[i].priority); + if (rc < 0) { + goto seccomp_return; + } + } + + rc = seccomp_load(ctx); + + seccomp_return: + seccomp_release(ctx); + return rc; +} diff --git a/qemu-seccomp.h b/qemu-seccomp.h new file mode 100644 index 0000000000..b2fc3f8c3c --- /dev/null +++ b/qemu-seccomp.h @@ -0,0 +1,22 @@ +/* + * QEMU seccomp mode 2 support with libseccomp + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Eduardo Otubo + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ +#ifndef QEMU_SECCOMP_H +#define QEMU_SECCOMP_H + +#include +#include "osdep.h" + +int seccomp_start(void); +#endif From 452dfbef600837c0e430564ea9e35138ef48f24c Mon Sep 17 00:00:00 2001 From: Eduardo Otubo Date: Tue, 14 Aug 2012 18:44:07 -0300 Subject: [PATCH 0042/2270] Adding seccomp calls to vl.c (v8) Signed-off-by: Eduardo Otubo Signed-off-by: Anthony Liguori --- v1: - Full seccomp calls and data included in vl.c v1 -> v2: - Full seccomp calls and data removed from vl.c and put into separate qemu-seccomp.[ch] file. --- vl.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/vl.c b/vl.c index d01256a6a3..1010248dcd 100644 --- a/vl.c +++ b/vl.c @@ -63,6 +63,11 @@ #include #include #endif + +#ifdef CONFIG_SECCOMP +#include "qemu-seccomp.h" +#endif + #ifdef __sun__ #include #include @@ -2344,6 +2349,14 @@ int main(int argc, char **argv, char **envp) const char *trace_events = NULL; const char *trace_file = NULL; +#ifdef CONFIG_SECCOMP + if (seccomp_start() < 0) { + fprintf(stderr, + "seccomp: failed to install syscall filter in the kernel\n"); + exit(1); + } +#endif + atexit(qemu_run_exit_notifiers); error_set_progname(argv[0]); From 7d76ad4fa4405bb20c35fd24c3c848d2bc48f694 Mon Sep 17 00:00:00 2001 From: Eduardo Otubo Date: Tue, 14 Aug 2012 18:44:08 -0300 Subject: [PATCH 0043/2270] Command line support for seccomp with -sandbox (v8) Signed-off-by: Eduardo Otubo Signed-off-by: Anthony Liguori --- v7 -> v8 - Parse options correctly (aliguori) --- qemu-config.c | 14 ++++++++++++++ qemu-config.h | 1 + qemu-options.hx | 10 ++++++++++ vl.c | 38 ++++++++++++++++++++++++++++++-------- 4 files changed, 55 insertions(+), 8 deletions(-) diff --git a/qemu-config.c b/qemu-config.c index 6700de0c71..c05ffbc444 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -362,6 +362,19 @@ static QemuOptsList qemu_global_opts = { }, }; +QemuOptsList qemu_sandbox_opts = { + .name = "sandbox", + .implied_opt_name = "enable", + .head = QTAILQ_HEAD_INITIALIZER(qemu_sandbox_opts.head), + .desc = { + { + .name = "enable", + .type = QEMU_OPT_BOOL, + }, + { /* end of list */ } + }, +}; + static QemuOptsList qemu_mon_opts = { .name = "mon", .implied_opt_name = "chardev", @@ -645,6 +658,7 @@ static QemuOptsList *vm_config_groups[32] = { &qemu_machine_opts, &qemu_boot_opts, &qemu_iscsi_opts, + &qemu_sandbox_opts, NULL, }; diff --git a/qemu-config.h b/qemu-config.h index 12ddf3ed97..5557562c33 100644 --- a/qemu-config.h +++ b/qemu-config.h @@ -6,6 +6,7 @@ extern QemuOptsList qemu_fsdev_opts; extern QemuOptsList qemu_virtfs_opts; extern QemuOptsList qemu_spice_opts; +extern QemuOptsList qemu_sandbox_opts; QemuOptsList *qemu_find_opts(const char *group); QemuOptsList *qemu_find_opts_err(const char *group, Error **errp); diff --git a/qemu-options.hx b/qemu-options.hx index 6aeef6a845..3c411c427e 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2723,6 +2723,16 @@ STEXI Old param mode (ARM only). ETEXI +DEF("sandbox", HAS_ARG, QEMU_OPTION_sandbox, \ + "-sandbox Enable seccomp mode 2 system call filter (default 'off').\n", + QEMU_ARCH_ALL) +STEXI +@item -sandbox +@findex -sandbox +Enable Seccomp mode 2 system call filter. 'on' will enable syscall filtering and 'off' will +disable it. The default is 'off'. +ETEXI + DEF("readconfig", HAS_ARG, QEMU_OPTION_readconfig, "-readconfig \n", QEMU_ARCH_ALL) STEXI diff --git a/vl.c b/vl.c index 1010248dcd..124d30d3e7 100644 --- a/vl.c +++ b/vl.c @@ -770,6 +770,26 @@ static int bt_parse(const char *opt) return 1; } +static int parse_sandbox(QemuOpts *opts, void *opaque) +{ + /* FIXME: change this to true for 1.3 */ + if (qemu_opt_get_bool(opts, "enable", false)) { +#ifdef CONFIG_SECCOMP + if (seccomp_start() < 0) { + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "failed to install seccomp syscall filter in the kernel"); + return -1; + } +#else + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "sandboxing request but seccomp is not compiled into this build"); + return -1; +#endif + } + + return 0; +} + /***********************************************************/ /* QEMU Block devices */ @@ -2349,14 +2369,6 @@ int main(int argc, char **argv, char **envp) const char *trace_events = NULL; const char *trace_file = NULL; -#ifdef CONFIG_SECCOMP - if (seccomp_start() < 0) { - fprintf(stderr, - "seccomp: failed to install syscall filter in the kernel\n"); - exit(1); - } -#endif - atexit(qemu_run_exit_notifiers); error_set_progname(argv[0]); @@ -3260,6 +3272,12 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_qtest_log: qtest_log = optarg; break; + case QEMU_OPTION_sandbox: + opts = qemu_opts_parse(qemu_find_opts("sandbox"), optarg, 1); + if (!opts) { + exit(0); + } + break; default: os_parse_cmd_args(popt->index, optarg); } @@ -3267,6 +3285,10 @@ int main(int argc, char **argv, char **envp) } loc_set_none(); + if (qemu_opts_foreach(qemu_find_opts("sandbox"), parse_sandbox, NULL, 0)) { + exit(1); + } + if (machine == NULL) { fprintf(stderr, "No machine found.\n"); exit(1); From d973ba18ced6e9440131c55b0f07e97bdbbc6703 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 16 Aug 2012 12:15:18 +0100 Subject: [PATCH 0044/2270] osdep: Fix compilation failure on BSD systems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix compilation failure on BSD systems (which don't have O_DIRECT or O_NOATIME: osdep.c:116: error: ‘O_DIRECT’ undeclared (first use in this function) osdep.c:116: error: (Each undeclared identifier is reported only once osdep.c:116: error: for each function it appears in.) osdep.c:116: error: ‘O_NOATIME’ undeclared (first use in this function) Reviewed-by: Stefan Weil Signed-off-by: Peter Maydell Signed-off-by: Anthony Liguori --- osdep.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osdep.c b/osdep.c index 5b78ceebef..3b25297a25 100644 --- a/osdep.c +++ b/osdep.c @@ -113,7 +113,13 @@ static int qemu_dup_flags(int fd, int flags) } /* Set/unset flags that we can with fcntl */ - setfl_flags = O_APPEND | O_ASYNC | O_DIRECT | O_NOATIME | O_NONBLOCK; + setfl_flags = O_APPEND | O_ASYNC | O_NONBLOCK; +#ifdef O_NOATIME + setfl_flags |= O_NOATIME; +#endif +#ifdef O_DIRECT + setfl_flags |= O_DIRECT; +#endif dup_flags &= ~setfl_flags; dup_flags |= (flags & setfl_flags); if (fcntl(ret, F_SETFL, dup_flags) == -1) { From 35139a590c4e2f3086d069028bda77f1de1d46b0 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 16 Aug 2012 12:03:56 +1000 Subject: [PATCH 0045/2270] pseries: Instantiate USB interface when required The pseries machine already supports the -vga std option, creating a graphics adapter. However, this is not very useful without being able to add a keyboard and mouse as well. This patch addresses this by adding a USB interface when requested, and automatically adding a USB keyboard and mouse when VGA is enabled. This is a stop gap measure to get usable graphics mode on pseries while waiting for Li Zhang's rework of USB options to go in after 1.2. Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- hw/spapr.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hw/spapr.c b/hw/spapr.c index 5178721d49..be533ee934 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -49,6 +49,7 @@ #include "vga-pci.h" #include "exec-memory.h" +#include "hw/usb.h" #include @@ -765,6 +766,15 @@ static void ppc_spapr_init(ram_addr_t ram_size, spapr->has_graphics = true; } + if (usb_enabled) { + pci_create_simple(QLIST_FIRST(&spapr->phbs)->host_state.bus, + -1, "pci-ohci"); + if (spapr->has_graphics) { + usbdevice_create("keyboard"); + usbdevice_create("mouse"); + } + } + if (rma_size < (MIN_RMA_SLOF << 20)) { fprintf(stderr, "qemu: pSeries SLOF firmware requires >= " "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF); From be52202902d166e914d426c8e3d8976b25121b4d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 7 Aug 2012 16:41:51 +1000 Subject: [PATCH 0046/2270] Allow QEMUMachine to override reset sequencing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qemu_system_reset() function always performs the same basic actions on all machines. This includes running all the reset handler hooks, however the order in which these will run is not always easily predictable. This patch splits the core of qemu_system_reset() - the invocation of the reset handlers - out into a new qemu_devices_reset() function. qemu_system_reset() will usually call qemu_devices_reset(), but that can be now overriden by a new reset method in the QEMUMachine structure. Individual machines can use this reset method, if necessary, to perform any extra, machine specific initializations which have to occur before or after the bulk of the reset handlers. It's expected that the method will call qemu_devices_reset() at some point, but if the machine has really strange ordering requirements between devices resets it could even override that with it's own reset sequence (with great care, obviously). For a specific example of when this might be needed: a number of machines (but not PC) load images specified with -kernel or -initrd directly into the machine RAM before booting the guest. This mostly works at the moment, but to make this actually safe requires that this load occurs after peripheral devices are reset - otherwise they could have active DMAs in progress which would clobber the in memory images. Some machines (notably pseries) also have other entry conditions which need to be set up as the last thing before executing in guest space - some of this could be considered "emulated firmware" in the sense that the actions of the firmware are emulated directly by qemu rather than by executing a firmware image within the guest. When the platform's firmware to OS interface is sufficiently well specified, this saves time both in implementing the "firmware" and executing it. aliguori: don't unconditionally dereference current_machine Reviewed-by: Andreas Färber Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- hw/boards.h | 3 +++ sysemu.h | 1 + vl.c | 11 ++++++++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/hw/boards.h b/hw/boards.h index 59c01d0367..a2e0a54497 100644 --- a/hw/boards.h +++ b/hw/boards.h @@ -12,11 +12,14 @@ typedef void QEMUMachineInitFunc(ram_addr_t ram_size, const char *initrd_filename, const char *cpu_model); +typedef void QEMUMachineResetFunc(void); + typedef struct QEMUMachine { const char *name; const char *alias; const char *desc; QEMUMachineInitFunc *init; + QEMUMachineResetFunc *reset; int use_scsi; int max_cpus; unsigned int no_serial:1, diff --git a/sysemu.h b/sysemu.h index 4669348a12..65552acee5 100644 --- a/sysemu.h +++ b/sysemu.h @@ -62,6 +62,7 @@ int qemu_powerdown_requested(void); void qemu_system_killed(int signal, pid_t pid); void qemu_kill_report(void); extern qemu_irq qemu_system_powerdown; +void qemu_devices_reset(void); void qemu_system_reset(bool report); void qemu_add_exit_notifier(Notifier *notify); diff --git a/vl.c b/vl.c index 124d30d3e7..67f5813e75 100644 --- a/vl.c +++ b/vl.c @@ -1464,7 +1464,7 @@ void qemu_unregister_reset(QEMUResetHandler *func, void *opaque) } } -void qemu_system_reset(bool report) +void qemu_devices_reset(void) { QEMUResetEntry *re, *nre; @@ -1472,6 +1472,15 @@ void qemu_system_reset(bool report) QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) { re->func(re->opaque); } +} + +void qemu_system_reset(bool report) +{ + if (current_machine && current_machine->reset) { + current_machine->reset(); + } else { + qemu_devices_reset(); + } if (report) { monitor_protocol_event(QEVENT_RESET, NULL); } From c3767ed0eb5d0bb25fe409ae5dec06e3411ff1b6 Mon Sep 17 00:00:00 2001 From: Lei Li Date: Thu, 19 Jul 2012 22:09:22 +0800 Subject: [PATCH 0047/2270] qemu-char: (Re-)connect for tcp_chr_write() unconnected writing tcp_chr_write() did not deal with writing to an unconnected connection and return the original length of the data, it's not right and would cause false writing. So (re-)connect it and return 0 for this situation. Reviewed-by: Anthony Liguori Signed-off-by: Lei Li Signed-off-by: Anthony Liguori --- qemu-char.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 10d1504948..398baf1e04 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2141,14 +2141,17 @@ typedef struct { static void tcp_chr_accept(void *opaque); +static void tcp_chr_connect(void *opaque); + static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) { TCPCharDriver *s = chr->opaque; if (s->connected) { return send_all(s->fd, buf, len); } else { - /* XXX: indicate an error ? */ - return len; + /* (Re-)connect for unconnected writing */ + tcp_chr_connect(chr); + return 0; } } From 731dc9ecd4f2c3041538f7eb2d10eee0cb82da1b Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Thu, 16 Aug 2012 13:56:34 -0500 Subject: [PATCH 0048/2270] Update version to 1.2.0-rc0 Signed-off-by: Anthony Liguori --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index da44c7f348..69658cdda2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.50 +1.1.90 From 7a736bfa4e0a58087054cad68a1d4b3804bbb708 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 16 Aug 2012 10:34:10 +0200 Subject: [PATCH 0049/2270] vmdk: Fix header structure Commit bb45ded9 swapped gd_offset and rgd_offset. This is wrong. Signed-off-by: Kevin Wolf --- block/vmdk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/vmdk.c b/block/vmdk.c index daee4268be..9648398822 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -57,8 +57,8 @@ typedef struct { int64_t desc_offset; int64_t desc_size; int32_t num_gtes_per_gte; - int64_t gd_offset; int64_t rgd_offset; + int64_t gd_offset; int64_t grain_offset; char filler[1]; char check_bytes[4]; From 65bd155c7356d448ffee7f89149c4d473076b0ba Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 16 Aug 2012 10:39:33 +0200 Subject: [PATCH 0050/2270] vmdk: Read footer for streamOptimized images The footer takes precedence over the header when it exists. It contains the real grain directory offset that is missing in the header. Without this patch, streamOptimized images with a footer cannot be read. Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi Reviewed-by: Jeff Cody --- block/vmdk.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/block/vmdk.c b/block/vmdk.c index 9648398822..bba4c61a74 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -35,6 +35,7 @@ #define VMDK4_FLAG_RGD (1 << 1) #define VMDK4_FLAG_COMPRESS (1 << 16) #define VMDK4_FLAG_MARKER (1 << 17) +#define VMDK4_GD_AT_END 0xffffffffffffffffULL typedef struct { uint32_t version; @@ -115,6 +116,13 @@ typedef struct VmdkGrainMarker { uint8_t data[0]; } VmdkGrainMarker; +enum { + MARKER_END_OF_STREAM = 0, + MARKER_GRAIN_TABLE = 1, + MARKER_GRAIN_DIRECTORY = 2, + MARKER_FOOTER = 3, +}; + static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename) { uint32_t magic; @@ -451,6 +459,54 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, if (header.capacity == 0 && header.desc_offset) { return vmdk_open_desc_file(bs, flags, header.desc_offset << 9); } + + if (le64_to_cpu(header.gd_offset) == VMDK4_GD_AT_END) { + /* + * The footer takes precedence over the header, so read it in. The + * footer starts at offset -1024 from the end: One sector for the + * footer, and another one for the end-of-stream marker. + */ + struct { + struct { + uint64_t val; + uint32_t size; + uint32_t type; + uint8_t pad[512 - 16]; + } QEMU_PACKED footer_marker; + + uint32_t magic; + VMDK4Header header; + uint8_t pad[512 - 4 - sizeof(VMDK4Header)]; + + struct { + uint64_t val; + uint32_t size; + uint32_t type; + uint8_t pad[512 - 16]; + } QEMU_PACKED eos_marker; + } QEMU_PACKED footer; + + ret = bdrv_pread(file, + bs->file->total_sectors * 512 - 1536, + &footer, sizeof(footer)); + if (ret < 0) { + return ret; + } + + /* Some sanity checks for the footer */ + if (be32_to_cpu(footer.magic) != VMDK4_MAGIC || + le32_to_cpu(footer.footer_marker.size) != 0 || + le32_to_cpu(footer.footer_marker.type) != MARKER_FOOTER || + le64_to_cpu(footer.eos_marker.val) != 0 || + le32_to_cpu(footer.eos_marker.size) != 0 || + le32_to_cpu(footer.eos_marker.type) != MARKER_END_OF_STREAM) + { + return -EINVAL; + } + + header = footer.header; + } + l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte) * le64_to_cpu(header.granularity); if (l1_entry_sectors == 0) { From 48467328c6dccc9c7be6628ed0ef0810f83be2a9 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 16 Aug 2012 10:56:35 +0200 Subject: [PATCH 0051/2270] Documentation: Warn against qemu-img on active image People have repeatedly expected that you can do things like snapshotting an image with qemu-img while a qemu instance is running. Maybe we need to consider locking the files while they are in use, but having a warning in the qemu-img manpage is doable for 1.2 and can't hurt anyway. Signed-off-by: Kevin Wolf --- qemu-img.texi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/qemu-img.texi b/qemu-img.texi index 77c6d0b6b0..6b42e35fe7 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -4,6 +4,16 @@ usage: qemu-img command [command options] @c man end @end example +@c man begin DESCRIPTION +qemu-img allows you to create, convert and modify images offline. It can handle +all image formats supported by QEMU. + +@b{Warning:} Never use qemu-img to modify images in use by a running virtual +machine or any other process; this may destroy the image. Also, be aware that +querying an image that is being modified by another process may encounter +inconsistent state. +@c man end + @c man begin OPTIONS The following commands are supported: From eec7f96c2cac88f59fd8c79b78a6e027df4abfb2 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 16 Aug 2012 09:57:49 +0100 Subject: [PATCH 0052/2270] virtio-blk: hide VIRTIO_BLK_F_CONFIG_WCE from old machine types QEMU has a policy of keeping a stable guest device ABI. When new guest device features are introduced they must not change hardware info seen by existing guests. This is important because operating systems or applications may "fingerprint" the hardware and refuse to run when the hardware changes. To always get the latest guest device ABI, run with x86 machine type "pc". This patch hides the new VIRTIO_BLK_F_CONFIG_WCE virtio feature bit from existing machine types. Only pc-1.2 and later will expose this feature by default. For more info on the VIRTIO_BLK_F_CONFIG_WCE feature bit, see: commit 13e3dce068773c971ff2f19d986378c55897c4a3 Author: Paolo Bonzini Date: Thu Aug 9 16:07:19 2012 +0200 virtio-blk: support VIRTIO_BLK_F_CONFIG_WCE Also rename VIRTIO_BLK_F_WCACHE to VIRTIO_BLK_F_WCE for consistency with the spec. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf Anthony Liguori reported: This broke qemu-test because it changed the pc-1.0 machine type: Setting guest RANDOM seed to 47167 *** Running tests *** Running test /tests/finger-print.sh... OK --- fingerprints/pc-1.0.x86_64 2011-12-18 13:08:40.000000000 -0600 +++ fingerprint.txt 2012-08-12 13:30:48.000000000 -0500 @@ -55,7 +55,7 @@ /sys/bus/pci/devices/0000:00:06.0/subsystem_device=0x0002 /sys/bus/pci/devices/0000:00:06.0/class=0x010000 /sys/bus/pci/devices/0000:00:06.0/revision=0x00 -/sys/bus/pci/devices/0000:00:06.0/virtio/host-features=0x710006d4 +/sys/bus/pci/devices/0000:00:06.0/virtio/host-features=0x71000ed4 /sys/class/dmi/id/bios_vendor=Bochs /sys/class/dmi/id/bios_date=01/01/2007 /sys/class/dmi/id/bios_version=Bochs Guest fingerprint changed for pc-1.0! Reported-by: Anthony Liguori Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/pc_piix.c | 4 ++++ hw/virtio-blk.c | 4 +++- hw/virtio-blk.h | 1 + hw/virtio-pci.c | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 0c0096fd7e..d68dbb2320 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -375,6 +375,10 @@ static QEMUMachine pc_machine_v1_2 = { .driver = "qxl",\ .property = "vgamem_mb",\ .value = stringify(8),\ + },{\ + .driver = "virtio-blk-pci",\ + .property = "config-wce",\ + .value = "off",\ } static QEMUMachine pc_machine_v1_1 = { diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index fd8fa90792..0bc2b5e7c5 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -533,7 +533,9 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features) features |= (1 << VIRTIO_BLK_F_BLK_SIZE); features |= (1 << VIRTIO_BLK_F_SCSI); - features |= (1 << VIRTIO_BLK_F_CONFIG_WCE); + if (s->blk->config_wce) { + features |= (1 << VIRTIO_BLK_F_CONFIG_WCE); + } if (bdrv_enable_write_cache(s->bs)) features |= (1 << VIRTIO_BLK_F_WCE); diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h index 35834cf493..454f445d61 100644 --- a/hw/virtio-blk.h +++ b/hw/virtio-blk.h @@ -104,6 +104,7 @@ struct VirtIOBlkConf BlockConf conf; char *serial; uint32_t scsi; + uint32_t config_wce; }; #define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \ diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 5e6e09efb7..2a3d86f176 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -886,6 +886,7 @@ static Property virtio_blk_properties[] = { #ifdef __linux__ DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true), #endif + DEFINE_PROP_BIT("config-wce", VirtIOPCIProxy, blk.config_wce, 0, true), DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features), From 5f893b4e9c207c5a38cf7b141d2c54fa30046afd Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 13 Aug 2012 13:05:43 +0200 Subject: [PATCH 0053/2270] Avoid asprintf() which is not available on mingw Use g_strdup_printf() instead. Signed-off-by: Gerd Hoffmann Reviewed-by: Stefan Weil Signed-off-by: Blue Swirl --- hw/msix.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/hw/msix.c b/hw/msix.c index 800fc32f0b..aea340b7c7 100644 --- a/hw/msix.c +++ b/hw/msix.c @@ -307,13 +307,9 @@ int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries, return -EINVAL; } - if (asprintf(&name, "%s-msix", dev->name) == -1) { - return -ENOMEM; - } - + name = g_strdup_printf("%s-msix", dev->name); memory_region_init(&dev->msix_exclusive_bar, name, MSIX_EXCLUSIVE_BAR_SIZE); - - free(name); + g_free(name); ret = msix_init(dev, nentries, &dev->msix_exclusive_bar, bar_nr, MSIX_EXCLUSIVE_BAR_TABLE_OFFSET, &dev->msix_exclusive_bar, From d83c951cce14dd3c7600c386d3791c4993744622 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 13 Aug 2012 13:05:44 +0200 Subject: [PATCH 0054/2270] scsi: fix warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hw/scsi-bus.c:758: warning: ‘xfer’ may be used uninitialized in this function Isn't true, but older gcc versions (for example 4.1 as shipped in rhel5) are not clever enougth to figure, so sprinkle in a default: line to make them happy. Signed-off-by: Gerd Hoffmann Signed-off-by: Blue Swirl --- hw/scsi-bus.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index b8a857d145..4981a02436 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -761,6 +761,7 @@ static int ata_passthrough_12_xfer_size(SCSIDevice *dev, uint8_t *buf) switch (length) { case 0: case 3: /* USB-specific. */ + default: xfer = 0; break; case 1: @@ -784,6 +785,7 @@ static int ata_passthrough_16_xfer_size(SCSIDevice *dev, uint8_t *buf) switch (length) { case 0: case 3: /* USB-specific. */ + default: xfer = 0; break; case 1: From ff961015529437f4b83fca0a92069aebcf533c9c Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 15 Aug 2012 13:12:19 +0200 Subject: [PATCH 0055/2270] vl: Round argument of -m up to multiple of 8KiB Partial pages make little sense and don't work. Ensure the RAM size is a multiple of any possible target's page size. Fixes $ qemu-system-x86_64 -nodefaults -S -vnc :0 -m 0.8 qemu-system-x86_64: /work/armbru/qemu/exec.c:2255: register_subpage: Assertion `existing->mr->subpage || existing->mr == &io_mem_unassigned' failed. Signed-off-by: Markus Armbruster Signed-off-by: Blue Swirl --- vl.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/vl.c b/vl.c index 67f5813e75..7c577fa544 100644 --- a/vl.c +++ b/vl.c @@ -2735,6 +2735,7 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_m: { int64_t value; + uint64_t sz; char *end; value = strtosz(optarg, &end); @@ -2742,12 +2743,12 @@ int main(int argc, char **argv, char **envp) fprintf(stderr, "qemu: invalid ram size: %s\n", optarg); exit(1); } - - if (value != (uint64_t)(ram_addr_t)value) { + sz = QEMU_ALIGN_UP((uint64_t)value, 8192); + ram_size = sz; + if (ram_size != sz) { fprintf(stderr, "qemu: ram size too large\n"); exit(1); } - ram_size = value; break; } case QEMU_OPTION_mempath: From e89001f72edde37fb36fa7c964daa1bbeb2eca26 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 15 Aug 2012 13:12:20 +0200 Subject: [PATCH 0056/2270] pc: Fix RTC CMOS info on RAM for ram_size < 1MiB pc_cmos_init() always claims 640KiB base memory, and ram_size - 1MiB extended memory. The latter can underflow to "lots of extended memory". Fix both, and clean up some. Note: SeaBIOS currently requires 1MiB of RAM, and doesn't check whether it got enough. Signed-off-by: Markus Armbruster Signed-off-by: Blue Swirl --- hw/pc.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/hw/pc.c b/hw/pc.c index 3ed1a3caa2..112739a278 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -338,32 +338,37 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, /* various important CMOS locations needed by PC/Bochs bios */ /* memory size */ - val = 640; /* base memory in K */ + /* base memory (first MiB) */ + val = MIN(ram_size / 1024, 640); rtc_set_memory(s, 0x15, val); rtc_set_memory(s, 0x16, val >> 8); - - val = (ram_size / 1024) - 1024; + /* extended memory (next 64MiB) */ + if (ram_size > 1024 * 1024) { + val = (ram_size - 1024 * 1024) / 1024; + } else { + val = 0; + } if (val > 65535) val = 65535; rtc_set_memory(s, 0x17, val); rtc_set_memory(s, 0x18, val >> 8); rtc_set_memory(s, 0x30, val); rtc_set_memory(s, 0x31, val >> 8); - - if (above_4g_mem_size) { - rtc_set_memory(s, 0x5b, (unsigned int)above_4g_mem_size >> 16); - rtc_set_memory(s, 0x5c, (unsigned int)above_4g_mem_size >> 24); - rtc_set_memory(s, 0x5d, (uint64_t)above_4g_mem_size >> 32); - } - - if (ram_size > (16 * 1024 * 1024)) - val = (ram_size / 65536) - ((16 * 1024 * 1024) / 65536); - else + /* memory between 16MiB and 4GiB */ + if (ram_size > 16 * 1024 * 1024) { + val = (ram_size - 16 * 1024 * 1024) / 65536; + } else { val = 0; + } if (val > 65535) val = 65535; rtc_set_memory(s, 0x34, val); rtc_set_memory(s, 0x35, val >> 8); + /* memory above 4GiB */ + val = above_4g_mem_size / 65536; + rtc_set_memory(s, 0x5b, val); + rtc_set_memory(s, 0x5c, val >> 8); + rtc_set_memory(s, 0x5d, val >> 16); /* set the number of CPU */ rtc_set_memory(s, 0x5f, smp_cpus - 1); From 682527c00409d676c0d3b9fac99ca3b2fdfd6d2c Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 19 Aug 2012 13:39:31 +0000 Subject: [PATCH 0057/2270] Update OpenBIOS images Update OpenBIOS images to SVN r1062. Build with GCC 4.6.0 in order to avoid boot problems introduced by GCC 4.7.[01]. Signed-off-by: Blue Swirl --- pc-bios/README | 2 +- pc-bios/openbios-ppc | Bin 729876 -> 729876 bytes pc-bios/openbios-sparc32 | Bin 381764 -> 381764 bytes pc-bios/openbios-sparc64 | Bin 1598648 -> 1598648 bytes 4 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pc-bios/README b/pc-bios/README index f4b37d66dc..fc07ebc21c 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -12,7 +12,7 @@ 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 - 1060. + 1062. - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc index aeae265880dd5744b1e883a0ffd57140223768f9..1c3753d3eba13f39b2ebe4b4fbef373424bc5eb0 100644 GIT binary patch delta 22903 zcmbundwh(?9zXufvsNAHwdzQ(?cXmZ_jjIL{4yca)nQBCBWKk5CD+LW^;~fp*{239eUq$J%a`^D zIqPoG(f2JqeTr5^Yc-`ri8GNiKwH|A98z_!^(5=n^w)9{o>DI;idk#9nr+kSvn!MU z6Zv9>MN!_*SCnLnLgF$fbJ&?)YWZsiG32DzUm&y95sKKPv~g(hY69oo&8o>w&iY7VE(Gb1Jk(3_QWO|4JVMH)4rdILSY_*QR7OJ6d^oYFjH8WXM&o%gs~R=?&7KLD&@$QCr2*vnVVIe6 znCziW(uE-1q?W$<$b{S65*}#8dhdM``EGbljn>RHX4I0W!v+>Qd(A~JjB7mXq+VlE zvNp*w#^0!5g2t`VF21W!do7P8O={lq?qt7Ov^*wDbnV@ytKLbr*ii7xVRUuLpb4Z( zP$!bqw@vCvL8@taH(KkdM!hwb)^=Bm-g($S9qcLwUjvaoXzU{Qd10=85g^md=H+A(IW=`y!g zykWKNBP8RsZ>X!@PP1;!!5}8(^R*IMKLS|GoEQgD77`PT6x6mFimwI&HiI+bWH`@6 z0wqPx=wc<$P;fOCOpXTL0Lfh7tcrt5=|dm7+8=FQ(dJ2Z{lbF*w{cU~36c`j(*1aiL=P(bX5#ReziEd0i=J?OPA zYF%mK#4GTgjMW?&ovNUuCeD^||FxcyK*oH)4?Se7&teYeIOz8jBEfOAALTG(`BgB| z$LTI$ZSIN~di8)>wj#2Rn4r@puY$$&8|Zb;Il^5hi+uq8n{OfwQfb2m799T zXA*@oo4%fRL-$(1w>rD#a4+K?hW3R{5_R0=os2H#FfM09LCZnlOhEs7=kU{8{ zz}fdU`XY2@3^k}rR|fXEHU{Ms?)PTx&bLmS7U{tmon)OT&=UlZAziWHN{xDa<qny2=(4i_G^K}p7B8hJP}YPFTd^R?Tc zmD0=vg$z`*NzNWGo3+Nh+@*LOxXp%wYh}jsTmY#JyuZNPKy;u{At#g8VEtb+j3-r2 zU;{yHzlM05c2?qANdT7^0LSDYwUt1wbP@`ZfhFxDYin~6_dLXHc#ki4du6}@(!}u~ zZ7|Z|xN*N=L{4u#33W0sn_IS^x1NL>%dhPP91Bv~1YyF*?i$vUc{*@-f`sWGM znX*X&t_J~eA>v@Os23+sHx!eZQnD!v!5D(F_iSjRV88|?AiE02cBFP6OvKk&-pdWp z@1|c*6w%t%%W&-?98`uFu z@$xdjE@HjgZX!nt)j?%FXkCF?Sk{MLH>+F9lB^9}h!$(-B13Vi2*iehx><%|cg3V6 zo=w`Q%)$zG2m;lah}UY%g3j{?yi4*?ht|E8S{9*SzM@BYzMzq>c%wYaVi9m3lqXvc zH5T!eP|mn+fpyw{i>$BxugLnrbp#M~?Ao9{bzhma8-j66#Eh`%XL+S_kq`vgoq$1| z<(<)Bw$bo!g&2zKuBjDkdwA9rn8=o3wR&y$ggZ$~G>r=%Di61AMp&$%ShxQ^%ep@- z$f||$G_l%5KD?+#y^};5)x39N$skr0PfTk%5_h%gokz&}o$l)rNzCU&W|ggz`J~KR z>jdj19xR@_D-(y$i`3EOKZM+%X6;&v0Xi@#Jx`!1%0xc1se{({54nNCuKwt3nlF2O zmaLYo9~p8Z9!>L{O@Xqh>gdW1N4Q3gZiwu0eUzcNPq;~m|Iw^9Z{;(#Oylagku6Ol zDOe75aE}_WF|Bt4=autmQnVCKPRi|Ip)2=-f)tKpQtsbT3pXZpI?SUKPh zTJ~G=I~S?-Uk9;@J|s@9-`JTXsJ<0h^u`|5RMDMWPzx&}LvFUW{@e_K{LE*Iu9}A2 zCtlrL@uL6DY?IQ>>8>~P)VNKF^ybs*=uLfzVdwHq9ZBGDJ|gGb5_$I@CbBO;-Sut~ z`BuI3?vml-`Hq3}dvLPi>oOMbj97QG1ZqpMxhd|*78Iy9pBqvRw}XP4Ym8Nj4()-) z8bvV{AXO{BxnAA%-gBfv4c|PH-YiiIH;09|@LIe62CriCbJktX{YpI_-9+|Aa7jv2 zy}3_X!B3eb8x@@s_MKV#Nw^(gdT?+V^-d*S6mKVY0m4FyZ~k4x8qQ_$&3`!iHkq}H zH-PK&5I0O9>~4d+S0dl?Q7bA#M&A6hrby6PZQF>r21ytSZl$2U6!joyeF*CFco{IP zHn*NceHvGoiR{5n?EOUVTQ4AMgGaxwS99O*Pj3~ew)eY}q3V|Rt)z@wz%X_02Vao8 zYW9{`GIMACmUe`UR|~g3N*1bnw&sw2YSY#%x{Ijke;-G3)#ZOz$>yC=A9@kur^avl ziVWC!d)rr(%u}mA?#q!s?nD3Kp(bzdOHQcMw~wVCd8k#}JCnoex$QkkZ&kM=hZL)( z9cg5*YC(Cvx)1+msx3SE&}|sxlfLAbIurk{P&eaW>?!eYv>LSYdooMF zORaoQu%+pDxFgg{yK_jO8u!mf_*C)lGIiTOjhxMYzK;18+PjlPm|L;v*znWUC)4WsYwP>WHSte*VW5E^(^ z4d2(O|4drWrtNCz{i)ig$!$3W6qDa?B$w3M{T~FT|F&)8 zYPI4(4_cw9#}6dZTkohX2j-B`YT>~cdh4LN>fm$ap4xKor}p(DjM|XWtkd;5S-;*o zXbi1?RIRU?Nb85G!#*3^tv(H|BhtYB`8?aIf2@Bl-e0{o z(0b#_&!>2|L}UfjKc1CRpSE-6=RF9mAElQ4`xRP0O$|Eq60M)9Ebv?G;j>5(ph;ca)eCcv^k*l-^dWPh`=C>8kJ7uhNEj zYU$TG*tu7KJ&`uNq4xSF%)8+oL$TPKS|p81b^15xuuI+i%_9-RrQ>O9rQ>O0v6QRZ z+ean-K{dR36!}gqtbQ_hgxE1)NrOp*iyg!Hh6`#tleF`e^hM>?s6ryir1SE>6> z^$niQWmwk5P2+Px?m5XsUOJ)bPWOm(#PQvWS!nrMXTZeiSc#}MiuGV z%Xd`Mf1d5(;Aa~Y)umu3TlQAs`YBja(A!qx@O8FNQ_uXT=kQFYbi<7+-4)BCdqLJ> zY`)2y-ZE2HdhuQhFD*dU#o2pV@5GPdxQnK)66qC`dCUK3R)Aw{){8pD$|{rrha5eL5^hjxrcY7hq2tz zWZdtlRcHSEB)O^{{kaR4#oC`^v5FLy#Hq(slSGkN@YKmr z(74yEZP+iIpYNZ^OFDH|ZCa-vEW3LaSx%=x7w0!|vo_Z7+;F^p<<%T=ZD;P)M3Q=Y zVb;joOHB${-Y-h-+ic6C$_xd!;X37F+ijhStpVJ|a8AvvLNN&QNsR7;W2exJ#x?R!gsU49;}6 zxVLG^Q1@LQM{cM=b=@;gN}=5@H*4!6IFGhvIi{pyp=GB)Z-0O`!tpFdA87pcPPMQu zG3551{x+>S^VaS2{cE)5tbjZEtdu*w)LnItAe=YV#dez9hH0_OvJU#5cfY2l-^d|P zsdI0{(8f@;?8amCPO^IG#+UTYBkJ~>qXwi{W^^uE7;7#P{A`81aAsyAg`J%BRjA{{ zxKN+88pe*?6&4u;nERs24!R1$QdU+8GbqVkM5( zM;B9^?AZQQDnWz~r8^;FnmG_Zp#LzG3DzV@;se!V1voxGNlhx%K*F1@&6msvZx8bM;Mz!6skSi4M(iS(DZ)uP7l zNzu+>w;92$#-%$ild0;YU%Js>%GKguQrrK6EqBg%v-Yi@TmheJQIG!eNysl>o3+1P zUc6Y*agG<-7GrUIE?h1B_3!jo_np~IS%m)TuNK{XHsseq|5}WlRkRX?q@m(b5D}5j&J@DnWlToDDu5Jz9lJesM-oYmEH~6ObJ)Z zTAtxKI52GLu=_7`&5%cTug~Vx<#L*TyG;~A(90jQv*tcl#an7iYj?6rjnn>uw6#=g zB+09b$(v-mJ%ErW2${t4Dfy7>VZLr;0ZC`M|0SWU!i_vbj;?VhOCkofAzRNawsb~v zI)B5DSF;Lt@KH!_ z#lBzc^xzgS!m8bpxuzVHx5_d%!YZEYK+xlMt??o+B57uGy~sq`w31bOkx^tbOYTR5 zm_bK62T#Uv$@~GYDrHNoicSXJLBrW}9qAG=yq6oo%&SWNIs`VjuXh`i6t-DMx(5!$ zM0NaFLk8!;!R#D*k}B4sBR$Dv7Oy8S^q#P|pWND8^bIma6H$6hP+LXFgl6qJ_Z#8Yp3TQfzm4Y07Wc>*HQ6F-PlBd`nfAR*+ z_F#kBktDK-&22|sASvupJJ?uPRvG}yTg$=&$zRA@tR#^1Z{M`HRG%DY)^;DpkohJu zY&$y>NUjr1tvykD54Eg|<@rc9Br0xgOeAX>S1mu2;sH{eLygA?BzbHAEABupfbi5H z@Q_JZeGtqzkL3lECDGy>$f^IIWLCO+IJSV!Q-P+N>~=8eMz0jJ@DLJ9nptiLxk(@O zV96b!ciZnJY$8KWv3%b2n;ods%aBS|%A2D8q}M!F)saNfyWLq0-iZytX6@r+uv4*m z8Vc_A#7Vw8V7s{nFv>Q`^W8KPN&JZQ3MJk9UF3^|oI>kjI7ggwfipQ#pD}AYjtMv{ z5t)<7LP2^eNDO7Ap-_x3s|qDkV(vzmwNL!`M%dXk23_x??k?-T`D{=pxWwJnY)>ah z=k5orM!a`0T^Jd{>v>@$#Ix=>6G_>@W`>czh#s56h#L5mNjZDML^{sL0b+(pS?Q}JqmBFPN3yC2(%J8nIC6xYm`L(5RvSUA{dR~`DI3-Z zBuqGc1kb%US>`C|W9OV*#PfMR=h7}pxS_x|A55)(D2KZd_RW#xc|z~*um?nuPk4bH ziY76h^&?HB*I`x{O%k~@!edC9HT#chH-5`?h9j_Wad32iZ$-^kie^y`M@KiLN6!D{`s6#|*_?p~y``jT7(v*SO$bgZ*4L zcoCVlCZ1RW}JEz&JlgKxOMA<7+AS-f|wWMPC zKCEsp3svjNz1d&W$PQA$qSDEM#O8@ep4}G~Jy}$`ObIY%HfNV^g$gG&4=g>Vgc=t# z4=uf_;O4aX3FH3z)b5)>#t~w&PwhkgM#&*|+dy8lwnUgn^kAg=rtAu>abY(zu31{b zEM9K#sOa8+Cnvq>OsgSmT+PViQcY3lxP4a`g?*&B^VH!CcgR2)cNCrM)8$pM1<7RC|C(&NqT+fR7lb)Sw#I^J$MK}6L zK$cm1`v#_%Y$8!Qwy!_w9?@dfN^o-ic31cp&xj1%mv|;&B7PBTa!AKc;i8gDCSIaW)|5o4} zLQ%$Z0*hXIj}z#)=z|Y&goEqu$x5h+1W#kb29vPo1&zsVX!L7C11f)YFc%l!=@^Pz zK3TN%J*-_Ni`&4u@$3Y!S#4m+iw3J4HlYnHn^g}ciK#7*0xncw+e8bUbcX@v0Uzlv z*T(u|yq~;EY8l6phajl5OlEoFJ&P5J_baSayqB}>;{6V*9)k3(WeaN=LSkskJ{I*T zY_sJU%YKxkhVgmYCdj!pTrg`^*Y4~vD|wXkknO>;{VMiAiyB;VV8RuxM{amOh!s8#A>5B)%O5A*5(C`ZL~Waiw3`j$#rQmHHiWY@Td7hw>ww{y z@O}oXL7&L`0}OBuFyhYP5X>?$JtQ%}nZV+nKt|9qjE#PR#8~go{vB>7*t|{L+mUt# z@jV=0xjw_uqx0?xH1UPPwK6E=6u+Vsxw_JFhmRp|Pw|lo_c)xjn6-uCOkdLTzr^2< z+i*+gJP9pjH=ZCP$N2HSTu|W8VyL{o47}^*>bS6-+3h^C(vwG%MMK&05%A)t*zpk%#Ql$0%LvjXcn6;g zZaDln?}%WbC@*8lBS~y9fgS^JTiwN|DI|A;2HUrsuumUJ9wYSrmu%N4vIG&%Fq%Bq z={qc2KX5Y?SHuPPZ%8SmR@(QBhD-SA&KQbwbGZo3+8p)`GE{bVENSmoi<4@uEr1I@ z;wvXh9!J_){Ww$7s(tN7EjQP!y&ydTmxlaP4WLgJ%H>QWcp``rv-Z;ZHn4ggSOF78 zz*7e?!Qv}5PR09jBf-Pph#vDUi}5z%jJLq5b6^1eK^tP3XWMOjJ?bMQzc0^lS%#s& z0}0$;_hNA8mlL_Um>2)n1&qGH;f+#@E=K1Gt8v1djLzd96d)RVmaJm^#*Q=wjSo%WqiYF!7J%bv-|>m-%%TT*j>WYZ^rl%JE72$D`xJ`YLF zxnbWnfxO`}M9+`=)6LoxM1Wgcv7HKcT}LC2_5pmBQ}$7~Y{Eg(l&63vBDbOVN;KD( zS(|>0S*DR^2kJx7Ki;fOmHH~U`8}fu;Ya!Eqa+acRzrz&21H*4;hN}qnwTs1+@7rYBqWHv6f*RhPiU5 zfzM7N5Aj>h!r}1o#-tf$t@GJG(rbCtNe{|=@))b0O*&d#z9_DP)WwQU70KI^Yb~8W z4N{#$f!zE*A$PwGxfx<>K)9WB7T>rb@oYPl0w*p4#Ww-&a+#`$eJ>4|~ZR@+Emz zZ!v2V?(op>8APmkmYa@qqx$%fCW5Crr+&0YGc)gIPi0ZCbF@AO% zm@`(4$EnUdMETzKnt9}BLiO|6(U-}P_9ec;&Xytt5_b0FNA{>9zM(s1H_Rt)lzhvw z7vR*OB#up8KvJ!G8|LF{QZDGTtH95Zk~r9^8>fLe`x=f6Yy+B07j=eWVEJQXt>RRilIWD#|-tXh|@b_mn+*A?f2rzZ}Nq+Q@1C z9=4bqv<`T<8h9go4O)T0T&sbFuX1uV7|h|nTMf)7+Q6I|Hb0QG%R&s5-jgv|53^>D z&Q=tXujD_-fvo?tB1ur9u#tGMz6m!qYmeQ5Z*+pY>YP3TDSKc2jXw!c;6slg zrh1DHn&3yF51DhhxEY63-fuZ+$o5Aikw+og_8@TIY4Z(+;zfmq0`G2+h;wi4-N&pw zGVeFiDexWx31Q$t^H|;zqFNImOl)CD5!ZAM7ufsw^30~-%U17+(2&kp{^c-!#AH%V zuf>XE>+ibF0ZY&rSCU@i8xiHq^K%U*Vs?@%|>|=rlerxoCMmB|_dN&ce`4 z)!H5>Pd3fLC0`Pm523zV%jOot-&U~lVkD{F&$2zmBzABENSQF(^~UqwGlZCUgfE6? zz_a;jhFLSMeF#VJJZU@y1t!i?*A! zfxGSbOZoB5IeYPIWC_Jvw~RdQMZem{#+Q8i)~;-t%JYkFll}g?+I&Hepj3=%x_$!(g&$0L#E~@aBKX9uL%uJvcIOk@w4YsCN&1JiL~veA$`=c{IheJy`Pgs9@hc)$<3)m4 zo=UtTcEIEmSabmQZIiNVD-Sf>D$K17d)ZtS3HFa{n~H<8kJvetgjw-j^7-85W-aw2 zJ`;W*4zG6ub(w^0kUx+?-6_g@8;ljX$S+bCikWW^$!!?gmpbc6Mz1vGRB70prOhrl zpQ~_(;HJVq8FV_tLFl{L;VaZu?TmD2f2gn$AkX84KQO*vu4;0n)1RPzsKNo@;G-AktZ77-vANe z#vtwib829q_!8Bq-P-{D@OvBXieNNlF*>_q<#I#ai>L90nmKc}$x!ja{{ zEUS@R^}Wx^SL34Q1lzY7T3F3)uZDZhV&Q90%V49|U?Kl%7b{vrV*NTvtK!`aXW5oD zB+}ET9V`^7&l)n;`&yZ0Lo6)AFoyMFBqq$K9SpyXR=Hwq zP(r0@lLMWq!Xfn)kWD7i!4oe!;mB#PK&44ng>a|KlT!B~JSPDhs?88NMz#W*Lr|CPLd86H zb8dPv5;$Sm<_hi^zh9v^t%aN>$FuS;RAl0lenWDlr+>gN3dmUAl^o zrbG%_0d>O0;i*xEN}s9RYfZ|*5$0A$Z#HQii4E-3#ws|<^Q?3o>6!7PB%Ze4rFdx+ zK84VOm&~_P#Mkx@6|W4 z3PigC?%E^{<1WOfa~lDEiY4qG|I|Q-h!^~uqyZN>IA(Jt;Yh4gJfb4;3Fk8cx&F5q zhD3I40Dzo)mS-cz^GY0#HDa*V`V)ULfY@+w14bV#5vl!HQ#tw6+s7tsu=VOD`@Z!g zjac^!Er`zwc)*Q6oRbfa!DGOQfpLM)2huy^KjK$SX05vjNoeB%7Ty`ZTIk_Hmf^FR ztIeeRYchXh>=Z6AtfS(jK`J0|2b_y=c)nsyR=6a&q=Y1u0EOEaXIx4$QO^;jHX1JQ zMH+3$<$5>pfd%nOm{%n<0k3vx4ej4LC&5n>;7r|x(}|rVx2s|wBk+m2gLY4tN}Gle z|EwVI5PzR-IK}am-23daZ`nk?qy9dhW0kH3XYh#FernXxaJG3fF4%oeuc;(v{YCE3 z=GF_?Pgat&h#zHs9s8q6SvQOS9v~OT`XYaBy|B!_xsvQ85l!$4e#g#(4KZ9++%px$ zTMp230Gs;(c}AZp&L!W)3Y-5ER@nLv$bWIeetZkY^-X61pOB6$XDdmgzEAK#SlYwnx}i?<8-;_*L?iwNxKf4&$T{ zTfA+fTdBw~ibZ18 zYq0-!YY9zSyc^r+P@t??-#sgKGrUt^}2`+X}d?*=!@j1uy#{_uYz$)Oufvl z@9t-LKjB-)8TLaz;k1|wFz+(X(AzDSA}hU29;59x*w0-i|Da**wzi?-fzd)yZ#3xJ zeabf1;x?xfyIo7N{MX&*M$4Hox2|ho*;mOL=^3|$;kN#Gnblk+-Sr+~6>hx%FyV#ti6n( z?e5z1>X5?g_e$?#JM5MlP&(3;rkkXTez@?m)*ptms9T`k%EsR!L;M4<)KnAj2_dhZ z%(mSkojc)oUXzA$*~1Te;f7jl0}aIi#9ng?H_A?D+Ebd?l zOK!y8I>3$D8p+R|0siLJl?`m>Z8Da(9lDLr2TlxQzIV`PnYf8cevjzvd3Q(*I!|Z0 zzrt%vej)!v#f}Q>cDB8|iFBcUyQI+|n(7Jet?!Y(e*DWM*ck^=h50r^$;kehhrh770rWY1b#pF&K1uG_4T01f zp_xbFCTVNCvGZ+DyX#j=TeC+qTYEZ^`q+YR)gYptxVU6zKrkKY@O&>+Tkm9rV~xVmq)rV zdL=kr{$Q+*JBXXcC z9JAs~A%1AquN|(yWpM-x*PYnzE-QEHSh*i2%1jtY!kyvFdQ*!S*6@ z>Zi##F$LOP}xL;J-UeY7$ngc*^iC#Flu9W5!vmDuIf%s|RM) zV9)MBpQC}xU}qpaez7Duem>jPi}utHcUA|p+Fo>}P~QOYn>usrJN;I^g$caIw)Cbi za0Mp9APzHAB8^OiqAGBJ%bzMdHC$n#W3pC3VGrW&rJAhWh`Xn6d1d{IxLcM;bBKP7 zOj*VZx7Q@WAaQjyJ_R0kS!8pq>@q7!!6?WDQs^iW&3seo$E1esONE1-W#>|LqJSBF5ts};;Gih{GAdzCoyDOXX5G&Hb z*9vAyrw1eOe?Q=pIzi}(!%jltdp~pQ6W}z1j)R+T&!Bw+yZ){f>qiFtl|-=mKGf{j z;IupleE4O%sW08ACnH#GE*(Pg?O5^v7|q=XW*UH?GM}v)fN+$+>IYzs16aU7I<`m9 zCcdKJ5CvIp>j38}6E8(qoPf3f+eU0JTT4!{(t)%;4H&_y2g1r`v8I9aY3dur#y_K_-rW*&ij}`;jSB<7qC=KprZyHOR zJxHMa_9RMaNMkrommtjer;IfsPK26UyAkI53|$%4IMm$QeXnGrF$3j~q}_DIvi=O+ zpIUH~Qm7|LpF$?hW8q+(KjFE(I|g{x1!a5P>W}mX1`cKZ|JQ}&ufmRrCR;T zAiR%(dWF`YFGTqq-Uhr+Y7O2eHOF0@YzrPH+k)c-<%VEIP;Ll11Dpu0A@CC3F=SB{eL_kAdq!*McwF}F=&o5gTMZ%0W#2a6~WJFWe#thJ!giKzO|D9}TAN4F`UO=D1RfcRf_6;N7G(`eCARrB>N7 z)+T2Wr;`L@L7*8AA1uCB4%P#5+wt&_I zJX5rWlzn*5(i+mT@h(E$$_IK~Ye4-mj>|lS;z-T05Mklr zAD1V{Tt(ZHXu~ge9{y3;)}%%ge82M&^>A}&?L;MNo~Xp|iq1ozX{juEF+ST5c#(Qi zZGb?_ol9dQp5_EK$0GiM{XVe=B3vei)m{{6HqoU-l%2zriHdWW4|v5jj9s+Ui!NV^ zvK+BSl*NcGVkkbEV^NW->>N=}CSX38RODPLig>xJ=w9;@GHRtCFY82yM&&U%hUhR( zlx2t6Z8`|nT^-nihDZhObN?UUqRGVte>(~9Z9{mEC}Zy6PO`ggX4~#U z+>OdN0xka)-sMML)`{5Os9X~brSqs4evHoHdh~|L=|lw!1+VlJNSKM2eh??FITpLK z?L{;(%M-b*`~z&Xt1Nl;{MJ?19Ipns%EC+<@k3+`#?8bt(ksK&2E5I#vO5YGx=`>T zXMvyB@J^f$@}?+q4OqQ|JMn&+V@bNJzvRJdg{zLXL$0#q!E3Lpt~rY1TxB;Dv_`K+ zR~>D|uCkM-N>^RH)kNYYc+&6Vb>N@lvPr_vg}6K=ALNSQ7nbBj8bnd3k5W;F<$59` z5M^O6G(nVwfl*@{_^3AU>AdWuPhS=d^_>1|0v^D5X{5q6)-2@ow+J|of`ET2@NL{s z=`m5}gGJKQXuHYh(e_Wyf&MD+xHqsV3uuVco-PY9CY)nyj-?MQKuXFjN(?Er=awnD z3mbG3elkqjpj$rg&Hq5*k}N3-k2|3Jf~(%PP1>m2;T=@36S(fs;1JxETCkJ$5jb+v?y&+cwB_Dkl)1K8%tD&Vs$Qm^ zxEEL)?Gx5eo9?B=ALF4`~1hP~nEcf*C23 zpH1(TlAN5P{Jv5!bMl-yy^>RsQw+~yQen3PINz9@hnX#3NC&aeU^LQW901RV2FJqj z{O$Tfh@H#Vv1EgDh~&0Ih>CNF)MWgjTR@#nu6K7SoO_ZxNlCion{dll#^gy1n==(qIJI>@1vT^Gc6T_RQ z8kbnLji!cq;xOR1f719oQ`gML9?kPHmj4pA)Kgf%JQ@<_`O0r`6-7Fj=Sr6M3P=At zOP))6g=5SI5!ltkN%wP3m(gO{o;$Hur#r58*Si%3L_u#CC9lq|7S~%+@=6dKdKo!~ zA=GQQV3B$~^PuBwR|nVI*>M5y80Phdxk$J0TEglroZylNgqFJqxZX}en@TFyq7!AgrTYn@2++Tuxh>z;D)rkmcjm6s)NI*XWuZk1%QZYgc= zt@{L={1c8fNW_ou*IG>j~$K7|0k_s+9A2M7=!e=sab0nQv#;`-#k2C)NI}<0< zbCJXI-Q(N}xlNgS)PDSRN(Xl1!1-koIKM(}p5`Ng=kNvC1n@o0f+kjSiRSZ2iuo^w zGI;BvdfB=NRwe2!u&|f32J0Zaty+VvgcW~Df3W(Dl1f~Otp?u_t;BwiO`B6tpgdw4nb&LD96l)8b#l8`nJ@cR!h$(xo3Z=C7P{fxU2^;Po)7ZUg~DhcCg2?}C-GjB{q|RM3Yij+Eh#q?Ny;}%CFPsBlJbpON%=;Q zq>PQdpnM&Bw}25^!)?wz2Dpa(3?Ja?CBP@)ZIc6C&9m=0fuj;@hp)vzj<9WFAV(+& zVhWCq)nXt=NU<2m5r~Z=w#klQIR!^>p%}=~`HUFI(VlOo6EsJA%m@QH0_(*}%S<^)7YrKYr8&Y||lcuwN^0Z$E{pYhb;ao}mf(+cl!M>N)O!K@+rg$HPj!Bg?TZTuto!@{F|z9GBt R6HuRSbhqt;pco(We*on`sDJ*q8^R{85prUQvT4;F93PmeR3-c1@#tn+8W#^zv z9V}E#DJ?zOQP0+nD4N&OveJ&7%&@$Gim*Ww1X;iD%q$e^ynp=Om(OQ8Yo2-LnP;Bc zJTtSlYmWC^bG+xSA9Bdu-RE-NBqU88xnv7Dt5z+!Nk*#|b9<9Ls?XAQ$ttyAY4?B& z4K@S)$kwA}=9+M=G><5qEaU>vmi8bARKwdn$Xd0}+lk%As=q3VRck0u$kwV73Kbs< zIWfhiC?BOMO0-QOo#Li&*o97N!P|#0A`u-oDX!?8Xi)|_vu%p2MH%p&4mSWk z0`Q;o0mh+iuioZ~wn=C!w%G@Nlvt?MVBm@7;%hIeVJiaM@7_i8Y&Bs;cX};LeVG?4 z)HS?VtCsL$vwDjcJJrB2a70k2&9 z4k&Rz8L6WT)lpn6#Q%X+d+-a|QtVr9^6uSqey^a98{nyWA734Q$D)`k^m$AGqYc2j zE8DJnsHN|;Ath?AmKHA&hH2rc?K^DDj)+ zJI3FnV1nlD(k{NwS9`APNFvmfm0ihRHFIT$c+s_2v#v&+Y_2K&?p<`%WpF(Lq?V&j zB&qMJ)N_JV?aD6ndOtPny>ayVcs29AH^&;eq)j=B!BnWYnhO=hLRz7ddF{RnWUpiXRA!I^-C0p<=^mYV#xenHolTD97%+*(n> zYC#rqhSa`L*Zi%weRCoPu_#AYNoZvbuvX|8m3S8t6O5#nMVfNU1_3sMGomw`Vj;f% z0-rOQqokP9%bo#~slXc~ne&}qcu2{6`Q)!W%QpXX_xz}X?ek&+W|64hja#JH(+j)PSU@x4v$s~^Mc&V6F~4qwIr`QEq_|Q zl@~eb8oa0PT8@lPB~Vf=XUkk%{;VX>cLCr>AFAz`aOq8(17-n9A+*k2P6G- zcL8g2S9PFex7GYrq5Z@Jb(<^)i+w84>!LnFozCJ*fS(udo0L)>chp;}g6!PX`yQ4k zoY_7bcsF#1jQeiayS~o7jC&Z`vvd--xXbH|=5QF7vnjp45;zmlze*o|x=tet@IiXt zJLrqh*>|`}UAo%0U-?qJ$8f*5YIncWaiAB$TU%Kt3iJd4^p&p2BgpC1&vz+bW!3KV z&Hhz!P2lRzR+3CbldMwytr-( z8LViNb!I=dYBl@0OYu5z>oNFA^Cd2TSSRl<@HP?yXq=Uk>Fu=tUJv7ml@r)V5ZlWU zZ+pwQztK*7xWoWBB?q~F9>_&HAwL;ddhfJ1)@O3hL)?bI}^0maW4=U@ql=V?pXYQCPLQV2ziZFGRfuNh^;H*Ks=m4~tOmZiz{H zjGiRC;!YwaZ&70EOdCjqeaH`)=7n4Xy@}|TUaosm%ui_VDcTFTA;w-tJ=&iBb7o=~ z@2?9ay}Yy8B@W(USlf}@ReP>oXnz94jX+M-8S>XB-oipW&RDhTooJh2@Ax&O8lzkB zjV=}?`aIy1WuKVKl9?M(fENRv#u)*=F60|=fENKiO~?OS;v;fzc!fZnF`IP)$w16P z9IO}h+~}80xn!o4Y)lpyLs0gZ0d1rY+Nk&>l)%`IU%v$t@zmeTxdGZv^v*OD-54bd z5k?6AsJD=#ZPmPW0ReEAY$4Egd5YG=C9K2L8wWu0 zsnw;OA-c;3${C@PtLUmhyl%1zx^)`EOrYSd81Y%SA%?+kpSH+@4{uH%InS~YX zC2qcxd)C6qJ1 z`Kf*S&zbhOf6ugkd=mjg9k<@E-_3ffRv{S2L>3}!dfDCz&J=XaBjwFGVL=elmHpEped4C95yW91HNYdeOoy;m5r|?NxwZ@6|D?C`d zR3{UMBN=LH!G8m8#agu+F(&B1qVza}rZ5XRoT(;n7#MIX*{YTQqBkv&y$(mH`5VRr z+?s%Pz418L$jObN-ES;0<@O7)C=tI{wfgOR#3Q=eE$ge^|%?gSzL#C~``@^5K$E zDSXGk`8_m6@oX{{@Qheju@7pC$#zj(ku4}tZ5lVEL~aM^701mbiUIAu=2As5rz2G> zs5qnU+42&}S3|arp%weojIBWdO?Zu+AHyr$`jUNzzF(>0qg%*+e=bRBsuj1S75o;r ze3N33u-nwC{U+QFFrz8`wm<4^m$z3ubnbkFh2~cLSHv35Wp2eKy>En7yIcX>mXC0Q z1OiV7J@t;|IGk=j&*SfaVYRvaF6z^{ z!YpLpfgZU^$T~{>)$ot}J#KG8_6E=Xh^R>)4WzfXso5WOC4cKX zr<$;>Bbl~4ZCfisQq+v?Pm+1+zU_&muUfl3p6;$w`+PE)f61`i1N6Lg+52j?mo6r3x# zNb~G`Z?H|6&!f?{4Og%1O(aIO)4zuBsp8)pb;rNVoXvkN!+bLwT}e+h-!YyHP^%oh zNuk>&hInHY_jx$I92^ z@7=C62UfnRR+UVml{R(c;c;Cm)8RrQ9UPd(v#!dw1}5?Cd2L+$oF{$avlS9Qrhb%q z@^C*|`ReK;Q$6ZO#rsq)ijS#G-#zn4cS0+dsQF*MMJv~;en;oi$^v!e(Mz=QAL`6w z-Dzd9ntyB)87bBZHT!rgvO&!|-rm=b&z;YPpGjBo>O!lAsy<)!@Lm2mIrXwS@~dU!7E8NL{M40SJ)zcr)yFsQairB1 zYSP#J`R@5^&>pRB`#P3Zy`Wy?#q+AqX=Efz)P&OmY1ON$?Q}2>Zt_oepjGqK1E&Ym zs>Q3%JmbHXM{^#@VFzL241lakRWnWn(5gH&`^;ePyWd;2{Tq0zh2-5*&z^~=Rr#vt zH;ZXik(&2SBB@f(elv+yeWCXJHprvuD^sr6quL~m^XkjrqQez+>$gMN4V8|kt(T6c ziA7Vca(^q4_?2qN*=GnLd4GDlCzasdNvp*91UmtyLp=noWZK; zyA!12>hJ$W->p^meLsZs*xm4bFoC=S&-HFMtx2mQC>JUord(%|begx$s4t(3jlHq3 z_^@k!9&x>5)$U&wXq)+|fYWN#>eeo~tQhz{8atbn_Nz!8$bxq2>2q6%ubOdw1if-p zJ#fCi{|qj}{Pr#yp9^x($rdvIm}>a3d#E#&?_#W)b7D?nbOaCO=1Widj1BXNH>EqD zS5tmm?BSe`(2c|^bE10j$Dl4weh7ekE3>cIf^4Ld1y5K`!PCoVLqeR{Rt@=22M^~w zRFS5=S)p3~^I~_W2~~<}7T8IUy_HS_6f7<1oxR+dptnD#UieRsQ8Bu7L(HpP72Bfw ze)e2!!pWS@GGkYI@?Ke279#uN?7c~J{4kEYXxazBeWPwsIxpuwr>0zJV?U!~1PW@M zuzw(L9OL^4EbOP7%_0vJu~yCB&>Vl!(cK(>?V>MtbNqs4`0FJH^Jj5g1YbL z@uYCK&&BqH%v7U)d4crYo%hQe;(Oq67qw$q`!$MW?@s=8nL9bHp1%4jRyWhN?jF^B z%>~sF=Hlu=b>_8a$z}EAwf0yR%dU0ADw46hlNx>f@4kD%lq*l~WJ*xIUOjs~lveLj ztFE`l8sSqG5K#TCRofJ2PLoL)-vC0knQB7WkiOHivl5f}RP4uaG)bPlYF|>tlSPqW z@D$3FUR`e0HWmx#=lf_fUs3mz^=|87+uI}4_G548;?ibr*5*>4BTgWz%M(e^?xgZa z5?iw~eoW0?i$Yco2$TD_>=j}8rt})PPJ!5d+oxfR0Jkw+)HJ}Ssf9OsclOPGD=|6y z5b|5JTFAsz+3oQz_S;RFPt6*&_C`7~g2^}A`#%>KpO~CCLosk;%-)4VUNUu}ns>8} ze~jMZ+N`CQdf?`Ga#i)a)wQpy6k5$`tM)-V&SUn9L`zhz(6TPjn*X4Ua6Fs2B{W|1 zyP9z;GN7hxV768tS9!;KV5wFg?{ga*F;Fg`E zbmH~YT#6IEJ9TPdWt+ZUR_#AOW#hCH=Y9H-+TBRNj>(>PpTYZnGc?RM&fI1!WSp0J zt1_{3svbbkO3WIML*a@a0%#xf&?z}n)s(7udUu+-vMQ9`U99e?dV&0+dOD*A>E_X({J5w!WCelgg z9I{4@uKqPHC=m*>YCmj{WU!;x5>rrrkJqIaS0S{YTZ)JFKJ^lr#zs-K$Q z@B+`lfsv_>eDHebUh)WU*=$Z-E~ja?nnfW5y|hugOCMlWY_B#nb|ov-PTH$TTl2IU z5`jI0-`ae{_iYXzLY^ihm8DVgDcQw5UC2VxlVwaIfvnJlyg*9UxsoOA5}J{&;#QkC zBf1YS;mhx_LRWIaznPUB373j-rZSrwS=8^|^X5tSrkNMsdj*!em2+zsE5)#;^(C5b zfU@mau@E9`8$0+}$dmh7v^(k8>#)9Hg!~Vb1t1q8$cd;jbS=wvCv8X!%XcSHaWKS^ zQ~YEUX8_$KL)-yM_R9Bruj75Y4u><8@O%ft9=~H<3-SgMXEwJ5nMCg$VP{*AXGj6t zl|}qnoPh-SPsGv5fCXeY^#BE z^&NzX8u$^14A4Wp*hTat`&fg4^dJ*igps`7Yjn;4xy`p3oia@mk$S9Wb4AFcCUpio zY9t-oUi@o0r$R*`%&?XtGstH-sj%!_!#8rV=8kTCtH$AO2)E% z-sBx>e!!AjktnjB&22?qC*9bURA8f5#RBhN_^AW?CHVN5u z4Yg{Yor0Z;71Weo`z%iNT>;z6H30mr(oSpBEhMst^$a9k2mHjRBB#)p1Lx?ZFLD+g z_3u{g^HTy2OGNf0GEtCT0}_K+ULX|X%1Q#s)DE?ytlB@l_-0t|ItE=Ipsuf_Ep05h zEnK4Z7~9tt(y9FqD;4EsW(Xp~cs(VE1i0U1780|a%?u*_i4WTvL{#6g7Uid77Sd)m z4ikG>l$CDG5)9?Iv4{}zENn72ggg^7cFFI2vOCuDtecyoRr^PdocN%#P2%Q49FW8V z&Y;fB(2ji2E^JMB{Vop9%2v7*Uv~AxLWavL*Hm+HgM8EUaSS%P z`tfP)c&oOx7s5k`T;OVd!NRsjCMNvt$Uj#btYz#%xs-WzkoX21AgeAZBIOHQC=^X(l*tylby*JTK6#v z=|b#-+{|z{KL7Y1>(0e%xcLpNyKdEbLT zo#e7l*k5g;_dK?*JNaNh#+vX4XZbjX2=(FH$2>y&m@ic>=7I-jbzJ*0!gcIs#t|q# z?AGgTSzZtFc4Tm!FdA_~Hqn<`1gt?nT;~?Cv6*MUB9eQOZ-gQEMUoe}@@Y&e@M)5ogi^TZrJAGJd$KK*_q{AVZY6ouINoa1a1`IeAC zM_~+PMM_vhESB$L7B(J^2 zR+H7miaVG35w;dCaH()yf0F2^clF#F(#AcFJUbQdm5Za6i8jB4QY5G8ZU;@*8~DYn zC$F2XS1#r>^N^wFycAa+iC2OMYcTFnQO z?+6Le@g!jI{c@WJm{*i(4+r^QV{kefu>&jRj7mC9Ota@-SOPh7#UZxTo#^_R|6l4jJpOs*BHcEVX}&_glh*85tuymFQ{35&9EAerLby3DGrlJ_*Z^-qtb@OxQ+7g|W@N=MHmBtj&GO&COQg3R&vQq4mjpske~8ZkW6uw;x`IO{M_m&(;hki)j6C4!rNg*^%5tgmAUPmE-NwN?_Dd;hlbuQ0lQmT6zp^A%AUaFtQ8_sU$%x zZ8!{|7dtx~H6KUG2r`)TYlzP#G}~077+}{S(CvHBXUHRiD0?-&lz+|Ron_Vjm>D;P zp0$wHsSeXf@(H2!1K5>O$POElS;kWkLcQFwh7JwMqD`@f>|M^hcpH_D_EzekrUM0SnAWHgS}z%pK#m4 z=Cj2u9%&UVzK-K-*I^t$V!h%522FggP<|2$InOU_MYgUqRPZt6U8+_qJPs!=RxRrk z_bo}!`(Xg!G_seFux$3=X)HVccWY%vxG4VAxi#_p#3x#GH7>e z>c@FN-*ad?$mfkVFIJF((6fLYO+oTEh&7~;)$Tl+EE>($jD{CaXXi$f$bJpKScqYJ zLWx!lK?ItPzgA@`Rk&pvz%+pt_wz~O0>qzB3b8E^@2i+;4C&}^go1r=sombJDI{s5 zHqxru&O0*3kP(D7+-C=#Axp?FEGd<|)RvlyA9!%_iJRo~2krQQlvRt}=_pBsuXwk( zW6DhuXTnx(&Rupki1@e9*6JTdOEj9&4X!xW=1N6|m9dvEv0d%{oIPpyEq^d;Nl8}i zbr~FR%gDd&0O|~(f6hJvECMa2HNU7CEQ|+Vz*cb>&o9JObFcg8w&BU`2oEn2VCGeb z@iyTwINjagjRB18^mx*Kw79gFytpp2YOfszJ^hOcu%F8lM$XUc99|=J*2K@e2hCtQ zKl932!UWPGl-t^yz4+cfu3J(Pw}tFe;xx)&Dl!B!+XUon57-WgYA(LcFIqccI(y}< zJwL7G8k{$S-I_o;hOd_vTeCsTR^0v@!XH`e+yyLpq8JsV_-!~R74tZ$xmQ`nM3C~= zNy!CDlIr@1)SSDHJrl`0Er%I;f({O=roLy@Dz{@N71DGojTG7p_&i;rVW{^&eLC<& z$TsC(8_l&~)n5LN+3x81B026JX?TjCv&D}|T@ybiwJd&3YDxUwv3=scF<8xkOYg+rgZk5m&78(f zqs;?H*eueD7h1=|6)e`Zc^pJ_!i{jDKN+Dp`0`)r)xW9JgEF7}&ZPJ>g>FwVonhD#uLeO#qsEYwyX zA9LMjV3JnT{y8PZJc+&i2695Kz&9RKAgDx01*Y)?6SAGWc~Pf#GwntEOzT-F@C~98 zFGt=S@)dc}kZ;u{KHza&Dtq*3Zix^WZd9*LLcE)6)y9nF0^~7U#)I8wO+;#W?bz{kpzh_{_I{yL?++V z{o+VkKwK#Ki6t+@$-%NzHgh3~ZEYyPd^|16uSP5d*fjvYYatZj&%svh84^=rl*9iN@U7>Y!E|L>A4<8&7)(XR zEX>Kxs#y_L7L#Cm)0!ll(5j7i0LyO+XEf*@00DY9AM*fdL&9-E3LY{7=UN`(nh+ba zz(;H}Ij|K68XjwP8qM0_z=Z>q*5JiWH)N+NchSq3`(Vsn&pwSfsv45@m>klLvmpx% zoSelbEP;c>uv<$=P=Ikh)MzjloU$Phd~ z5eNuYZTKLSAB<&d)m%!;L(>p97MC(xF7`g_k&ztbR1;yv_=s}5Fpg{mAI2JS0+mZT z4y{A81wtq?UotKgljl)67gh}?X1mtg7s8{B^ZD;MlY*aG{|A2>{!kA&Ino%!`{f-s-)MM^*9g0XhA z0k%`x`Hh8EZJ?L!&8Aq?w^u^iQ%%8$e=J;N9l zxSDkLHg45D-2l9aEM+z6;%(g14Azw=8~MY`rXv5n%J!%v%Dy)d@qrt5B37!T zgGvVH6Q&|REWVVq5*evT7x*bQe785~6^prSl)rF6T^DHGH|D}5WCpQI^>&_YjzIf+ zdL7B(^$5_e0&GG0r6eVx(5}^R0rQXk5S_VA{%qg)n;#hWQCB1tSd`;@#YV(hLu45* zRu5}qt+Wc^$;KZ%qB)uMC)gtSx zjd#A&SBianwlH`u;0@+W9ZC?JCZa)n z>n!()eJ)FQ13u#IH;8xO1Bs(!5Hw$ENJigc4u^#qWR&jn3(H)ONZ{otSWhAe^>~w= zexJm4_^KB9IRAkUwt=Saz;rbFekbX3%k6`7-~(L$O=L+QkN|IwY_3_0a%i-*vAQpt z_5tbW8{SOeVbIsxEdK-2qwiHotoN}do$C5t2@$uD$x_VWW?c~hJltKz{YAWUI1XD((2ODbr-^pF2Fq7T&?sehFmNx{5%AHbhY# zRUOHoJePf!%X;c1FJTH!L~ljn&k-+XXG z;e3n9X^}GD7J_iL;_ETmkaqQ|;{yxgMKGKq_&i**Nk3@+NuLDv_S_@73eOQ6Juqg< z^%xI)Vr6$X5nt*t%V8)a?-Os2lgLx_Pn10_ICgC&-&1doOIU@^f*pj6jzd}ARx+P@ zR5L>nu^P*{A6grK#Rjj4^lo=m=C~d4Ir9hj9!t}(mdUu<`0Faijv}&~kO-FcF&4n# z%=R&ETL-a=ACr5yy*;-LSLiKMSoC%>g0_5>mwt}C?PM{bEpvD+z|s9v(v2rAsXItD zr7a7YuZ)#iW3~K z+h8^%ClPiCXYR4WJ#kPmK1B=z^G0t2A8Wq1cc-Qa#f|VzW_>PWPw4#un|zu4M!mCH z(r?%^9%B=JBXh`X$LZgoBre$rS8;Cby-mt8|0*oW`wPdFs}OsT_c096q+>S_57Y4Vg zj}`tiA^rgik6OfZU6~dKQ`DukieDLZa!j~OI)Gv>v;9H7Lg}#F!Rv9*@8r(Qdx z%^|27m0EW8KI!jO_6S63nO{BB{|;dZ_2hlpY9q@w&;WM3o~)#;ZZlg0=kjX~Y{PzU zAm>N`+xGwmT|Opu;Q`uwo_9nv5_cEsvy?>>+J*XTXA=nh8}&KI$_V{}`qZ&#SL)~3 zN9lY*eLM5oXP{E*O5dTr7RO9CIt;hOb!?A2ZFKit4(qY70$19B{kH`Tmx!S($UsL1 z`Tm=mR$+VUgNu6?>|=Gi_N{h+zaT=-BsmIiaoVy&&nsCMvC$F`Ey4iNvuhKJ;1gz>$RDjj+ulbgdNm-YjmQETc7T zW!xYw)X|MCZ%xNgk002@*3?SwIwGE+UGOpdVwU1ZhmaL)jUVkug4sSl+8*cc7yRg} z`09O0$4qfflMU@2Z@q=3`qK`y^(QRTpLVCMKWAJ0L9?~PQR`2a(7uQ9F@meLai;wJ zfHExUVfwrozgxoL3fM#XyyrXc#Bcwqtc|uuELZfgS z04_@%U*#XX<% zDwgK-%ACY7M1v$A4I+le-+RKv9OzwZjza{P)XJX~hEj*|s`Sn2zc|v`(;tY}AYFP8 z)wTgFDV%mC=h@5QG#$5|r^BJW(fG84t_%Hr>tjxNRdIz=ddL~<>dXo|&?w_9Db}e_ zcn7E-S1}#v7eP<-;06riC0M(g9kM*pot^DSzoJj{Vg;RO7xyQ6TN|eqv6G!>D1Blw zE9(SSyqHgC`VIZPmX&r!#C>9_wQc;cK$Gem$=&Ho z)OQvCHqhEQVTBxLLJm97llCx<)vKdeRZqHFD0C1%8uzm{zCU#Jdziw9Y*#P(I#+2V zOyUeniNwSzb67?sZPV7}QJlWwgScHA|Ksic@%Ip?3nM9h0Q8*TsB!FAM_Cjs5SL47 zF|@0(LL_{Rtb*mmfGDzw82SvpZu5(!pN0GUA3~?DrA?RFl~}5hB9_^k_9wI0uHImT zhkhOpbe9-CUF`fCM?c3(d(&rpjdJ#*#ix4K#uP-6KHzUX%k4uCwX1{t5}*zrYva>r zbVA~zJ=DQ*UpgMnzppRt@7wE7tpnEeqxVQ>R@;wSz3RAWffU3%s=|@dpKdb3TdI=i zups``izd#*VLWTNYjXZfxwWHM${<9Z99A$0aVv(^4uY)?XMuy^s81BLjKMV6D+bK_ zWN(7&H!lB$|`=s0)dYlN(a;0F)VK=h!wMaL+KK)&Rl2XHGHYiIPk8+GK_i? zk84v*xx-dk8?)!Jv?u9t{DOl;Sm@il+-0GQco{t$3kS-Q;q;5xCyq)RN+^ds9{#^1 z(!KrkH89}}Z{x{ETsQRFF@p9(f5(*(^tuZS{`6C{k<&ZtV@7 z^>n=NmDb-GEBp&|A4{4;J?M=ZW=jJrH)`1)Q8uz$X)v@FtkV=~##ec1Qy?pR3p#~{ zxA0IDt@>s+wrdJj&zt>N;Zy((0yu2lR1O=)QaB7V1)`{MAlkwV*`5M8hW7&S1potC z=~U`XZ@$8+1Z+MFOy_O6EGeCKu;0qis&BokRlT2#QblRes>`$RzDKLt&f>m!M>au_jF<#q)vI?qG zP}XWSo|tH-JRAx_KF*HWau%Hol3+&=xIaM-7EvY#>khecCcF2PeY!Qs!MgF8gV{(h z!w2h@A_wbMC+Pk27BDn43`M-TB-KloXz&e#TA()4J~F)0ze zGZ5P}Lo5g4Kbw$vsW~6wb!din4|pg3gqOy`7SWz|t@^=4w7@ztpw!0s`g@gD3HU8)pM?BHOc}Bp9>4b7bp1Bs^@LRyHmc; z&&4PF&&&5WEqI@U_t8Mg^h5E?HqJpJ? zSDqC}g_+ddLz&B|YSr0&*se?(8Sgfl*ZCh{_<5E56XK|GyU|qFs&kT?-i4vmD7k_r zrr{py{!~*N@Xj^8yW$077YatiG-{Mx4;i7#zr{P0*un1p_ohx-_2Oww?~)1kPnzmz zyVLY8nQ;HUsjgKoNo{&}!HZVY0t=h`L))IFcb%#8O?6SKkyu!zbZ&8gR-Nl9q(kvL zo`=>^L)r+AeHK6o_>UR53G(Sv5-Z-J#1{AsBL{O@6u;c&?|g!kyxI)Dq!~P)ze{VX zAs>qdN&jD>!H08GLxh8@%i=^Y2za!F-w++L1w(b>osSku-L)DT%4gF2Pl}Uv6?hn= z1%CFf&!I)TXV7CL$Hv@qn|euM(G-p*J+g+*5PgIpQsFHlr6JP1re0e0Qop8m9$`Qk zX`}pW-X;x|e%`!|rDf6{&<-T34Ic^A)W-p!TAOBR+vBUsfU>K^2( zuLDc5*r()kY$+Dk9n8m0Ux`J)sc}7l$XA6XZus0WuI7G?hA`FC+)}d7hlJ`U|S z-uzF_r$xM+Pm8BmUMA+z6K}X zA|}lh9((I;*kFsF0Yg%&!~B-fD0?bw9(n6HWa|cas$s~Vo^ZXs`cLpb>AX2pv(qS|8Gn``_~!&|DB1>^ju`5e4{ou zUot(n#8I%E(!pIga6z5~F36Yrlm!J6dErS3Us#131ezAj^{Y8^pbXw?QJHLAgbZEO z?`Snf>{#pxC_m7g+1V`hYx-Zi$LmswtC6wu&ByAw690V!A-*|zKTwXk0TGyQXx1N? zJ|{h08Dbfe(sTM8J}BBd$(>cv1lf0Mt?avXo9z4H4%D&J+7gWt+qo@#n%H4&&D7e| zv`oOuNFWYH873#OrOI*iG@VMOwwfR*J2NEZ+sh^8+eqhI+B9cHsia)tDJfUHEGgeK zXf>^7Y0f*Gdkk>HRSr;o5%5gSS)M5eDz`Y6e}jVwd+Qrwpz5HlVxa0kP7qIAFi^E`nHZ?rcb``Cgohj>JXekp zCQYZ2 zj*(_m9bE-{Fdv;SnU7AAbfYpPy{MCtUN0~L=~VZ!NTz#9@mKe(a(G^&SuVb#rYs2S z9UT@M9TOWC(=WbnU&s69w9Me{%+{)%OB~CqagI;#40Eihp;4{bw{9*S91U(RDJ~-Q zseXI8BgN>_vyGZZuQ+UBE=OPdE5T)>m$~3^#p8y@9Zw5920TW`=w%*#*S})e22b6A z2cB)%g9oBC6yrI9=L8-^E5o;V&f&R$2Rb%j88uwNa{~`N!0-p223S7DW5DB$#}5zw xk1JysqOXR7X1ElQ?kV`#uR}}n{{hVCY3Tp} diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32 index d90c4e59a02b86d1aad2aed386e845fb27385723..6bd8e45d86e00919fcf3d4de697f1946ea2a3905 100644 GIT binary patch delta 76522 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 Y_+PTJ%k{pGM`kP6xwhy$HCt)^3s5(kH~;_u diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64 index 457d264228433a139d9e3e8e5f9708cc44611c79..7c06fcc5aaa2274b01d65b26ec5339d190036e44 100644 GIT binary patch delta 18620 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 DK?R-A From b20909195745c34a819aed14ae996b60ab0f591f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sun, 19 Aug 2012 00:12:39 +0200 Subject: [PATCH 0058/2270] Revert "iscsi: Fix NULL dereferences / races between task completion and abort" This reverts commit 64e69e80920d82df3fa679bc41b13770d2f99360. The commit returned immediately from iscsi_aio_cancel, risking corruption in case the following happens: guest qemu target ========================================================================= send write 1 --------> send write 1 --------> cancel write 1 ------> cancel write 1 ------> <------------------ cancellation processed send write 2 --------> send write 2 --------> <---------------- completed write 2 <------------------ completed write 2 <---------------- completed write 1 <---------------- cancellation not done Here, the guest would see write 2 superseding write 1, when in fact the outcome could have been the opposite. The right behavior is to return only after the target says whether the cancellation was done or not, and it will be implemented by the next three patches. Signed-off-by: Paolo Bonzini --- block/iscsi.c | 55 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/block/iscsi.c b/block/iscsi.c index bb9cf82459..219f927823 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -76,10 +76,6 @@ static void iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data) { - IscsiAIOCB *acb = (IscsiAIOCB *)private_data; - - scsi_free_scsi_task(acb->task); - acb->task = NULL; } static void @@ -88,15 +84,15 @@ iscsi_aio_cancel(BlockDriverAIOCB *blockacb) IscsiAIOCB *acb = (IscsiAIOCB *)blockacb; IscsiLun *iscsilun = acb->iscsilun; + acb->common.cb(acb->common.opaque, -ECANCELED); acb->canceled = 1; - acb->common.cb(acb->common.opaque, -ECANCELED); - - /* send a task mgmt call to the target to cancel the task on the target - * this also cancels the task in libiscsi - */ + /* send a task mgmt call to the target to cancel the task on the target */ iscsi_task_mgmt_abort_task_async(iscsilun->iscsi, acb->task, - iscsi_abort_task_cb, &acb); + iscsi_abort_task_cb, NULL); + + /* then also cancel the task locally in libiscsi */ + iscsi_scsi_task_cancel(iscsilun->iscsi, acb->task); } static AIOPool iscsi_aio_pool = { @@ -183,18 +179,11 @@ iscsi_readv_writev_bh_cb(void *p) qemu_bh_delete(acb->bh); - if (!acb->canceled) { + if (acb->canceled == 0) { acb->common.cb(acb->common.opaque, acb->status); } qemu_aio_release(acb); - - if (acb->canceled) { - return; - } - - scsi_free_scsi_task(acb->task); - acb->task = NULL; } @@ -208,8 +197,10 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status, g_free(acb->buf); - if (acb->canceled) { + if (acb->canceled != 0) { qemu_aio_release(acb); + scsi_free_scsi_task(acb->task); + acb->task = NULL; return; } @@ -221,6 +212,8 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status, } iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); + scsi_free_scsi_task(acb->task); + acb->task = NULL; } static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun) @@ -305,8 +298,10 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status, trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled); - if (acb->canceled) { + if (acb->canceled != 0) { qemu_aio_release(acb); + scsi_free_scsi_task(acb->task); + acb->task = NULL; return; } @@ -318,6 +313,8 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status, } iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); + scsi_free_scsi_task(acb->task); + acb->task = NULL; } static BlockDriverAIOCB * @@ -417,8 +414,10 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status, { IscsiAIOCB *acb = opaque; - if (acb->canceled) { + if (acb->canceled != 0) { qemu_aio_release(acb); + scsi_free_scsi_task(acb->task); + acb->task = NULL; return; } @@ -430,6 +429,8 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status, } iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); + scsi_free_scsi_task(acb->task); + acb->task = NULL; } static BlockDriverAIOCB * @@ -467,8 +468,10 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status, { IscsiAIOCB *acb = opaque; - if (acb->canceled) { + if (acb->canceled != 0) { qemu_aio_release(acb); + scsi_free_scsi_task(acb->task); + acb->task = NULL; return; } @@ -480,6 +483,8 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status, } iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); + scsi_free_scsi_task(acb->task); + acb->task = NULL; } static BlockDriverAIOCB * @@ -523,8 +528,10 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status, { IscsiAIOCB *acb = opaque; - if (acb->canceled) { + if (acb->canceled != 0) { qemu_aio_release(acb); + scsi_free_scsi_task(acb->task); + acb->task = NULL; return; } @@ -553,6 +560,8 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status, } iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); + scsi_free_scsi_task(acb->task); + acb->task = NULL; } static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs, From 27cbd828c617944c0f9603763fdf4fa87e7ad923 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 18 Aug 2012 23:37:31 +0200 Subject: [PATCH 0059/2270] iscsi: move iscsi_schedule_bh and iscsi_readv_writev_bh_cb Put these functions at the beginning, to avoid forward references in the next patches. Signed-off-by: Paolo Bonzini --- block/iscsi.c | 56 +++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/block/iscsi.c b/block/iscsi.c index 219f927823..600e334e13 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -72,6 +72,34 @@ struct IscsiTask { int complete; }; +static void +iscsi_readv_writev_bh_cb(void *p) +{ + IscsiAIOCB *acb = p; + + qemu_bh_delete(acb->bh); + + if (acb->canceled == 0) { + acb->common.cb(acb->common.opaque, acb->status); + } + + qemu_aio_release(acb); +} + +static int +iscsi_schedule_bh(QEMUBHFunc *cb, IscsiAIOCB *acb) +{ + acb->bh = qemu_bh_new(cb, acb); + if (!acb->bh) { + error_report("oom: could not create iscsi bh"); + return -EIO; + } + + qemu_bh_schedule(acb->bh); + return 0; +} + + static void iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data) @@ -159,34 +187,6 @@ iscsi_process_write(void *arg) } -static int -iscsi_schedule_bh(QEMUBHFunc *cb, IscsiAIOCB *acb) -{ - acb->bh = qemu_bh_new(cb, acb); - if (!acb->bh) { - error_report("oom: could not create iscsi bh"); - return -EIO; - } - - qemu_bh_schedule(acb->bh); - return 0; -} - -static void -iscsi_readv_writev_bh_cb(void *p) -{ - IscsiAIOCB *acb = p; - - qemu_bh_delete(acb->bh); - - if (acb->canceled == 0) { - acb->common.cb(acb->common.opaque, acb->status); - } - - qemu_aio_release(acb); -} - - static void iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status, void *command_data, void *opaque) From cfb3f5064af2d2e29c976e292c9472dfe9d61e31 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 18 Aug 2012 23:38:03 +0200 Subject: [PATCH 0060/2270] iscsi: simplify iscsi_schedule_bh It is always used with the same callback, remove the argument. And its return value is never used, assume allocation succeeds. Signed-off-by: Paolo Bonzini --- block/iscsi.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/block/iscsi.c b/block/iscsi.c index 600e334e13..7b09795720 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -73,7 +73,7 @@ struct IscsiTask { }; static void -iscsi_readv_writev_bh_cb(void *p) +iscsi_bh_cb(void *p) { IscsiAIOCB *acb = p; @@ -86,17 +86,11 @@ iscsi_readv_writev_bh_cb(void *p) qemu_aio_release(acb); } -static int -iscsi_schedule_bh(QEMUBHFunc *cb, IscsiAIOCB *acb) +static void +iscsi_schedule_bh(IscsiAIOCB *acb) { - acb->bh = qemu_bh_new(cb, acb); - if (!acb->bh) { - error_report("oom: could not create iscsi bh"); - return -EIO; - } - + acb->bh = qemu_bh_new(iscsi_bh_cb, acb); qemu_bh_schedule(acb->bh); - return 0; } @@ -211,7 +205,7 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status, acb->status = -EIO; } - iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); + iscsi_schedule_bh(acb); scsi_free_scsi_task(acb->task); acb->task = NULL; } @@ -312,7 +306,7 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status, acb->status = -EIO; } - iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); + iscsi_schedule_bh(acb); scsi_free_scsi_task(acb->task); acb->task = NULL; } @@ -428,7 +422,7 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status, acb->status = -EIO; } - iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); + iscsi_schedule_bh(acb); scsi_free_scsi_task(acb->task); acb->task = NULL; } @@ -482,7 +476,7 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status, acb->status = -EIO; } - iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); + iscsi_schedule_bh(acb); scsi_free_scsi_task(acb->task); acb->task = NULL; } @@ -559,7 +553,7 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status, memcpy(acb->ioh->sbp, &acb->task->datain.data[2], ss); } - iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); + iscsi_schedule_bh(acb); scsi_free_scsi_task(acb->task); acb->task = NULL; } From 1bd075f29ea6d11853475c7c42734595720c3ac6 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 18 Aug 2012 23:35:49 +0200 Subject: [PATCH 0061/2270] iscsi: fix races between task completion and abort This patch fixes two main issues with block/iscsi.c: 1) iscsi_task_mgmt_abort_task_async calls iscsi_scsi_task_cancel which was also directly called in iscsi_aio_cancel 2) a race between task completion and task abortion could happen cause the scsi_free_scsi_task were done before iscsi_schedule_bh has finished. To fix this, all the freeing of IscsiTasks and releasing of the AIOCBs is centralized in iscsi_bh_cb, independent of whether the SCSI command has completed or was cancelled. 3) iscsi_aio_cancel was not synchronously waiting for the end of the command. Signed-off-by: Paolo Bonzini --- block/iscsi.c | 59 ++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/block/iscsi.c b/block/iscsi.c index 7b09795720..4828b83927 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -83,12 +83,20 @@ iscsi_bh_cb(void *p) acb->common.cb(acb->common.opaque, acb->status); } + if (acb->task != NULL) { + scsi_free_scsi_task(acb->task); + acb->task = NULL; + } + qemu_aio_release(acb); } static void iscsi_schedule_bh(IscsiAIOCB *acb) { + if (acb->bh) { + return; + } acb->bh = qemu_bh_new(iscsi_bh_cb, acb); qemu_bh_schedule(acb->bh); } @@ -98,6 +106,10 @@ static void iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data) { + IscsiAIOCB *acb = private_data; + + acb->status = -ECANCELED; + iscsi_schedule_bh(acb); } static void @@ -106,15 +118,19 @@ iscsi_aio_cancel(BlockDriverAIOCB *blockacb) IscsiAIOCB *acb = (IscsiAIOCB *)blockacb; IscsiLun *iscsilun = acb->iscsilun; - acb->common.cb(acb->common.opaque, -ECANCELED); + if (acb->status != -EINPROGRESS) { + return; + } + acb->canceled = 1; /* send a task mgmt call to the target to cancel the task on the target */ iscsi_task_mgmt_abort_task_async(iscsilun->iscsi, acb->task, - iscsi_abort_task_cb, NULL); + iscsi_abort_task_cb, acb); - /* then also cancel the task locally in libiscsi */ - iscsi_scsi_task_cancel(iscsilun->iscsi, acb->task); + while (acb->status == -EINPROGRESS) { + qemu_aio_wait(); + } } static AIOPool iscsi_aio_pool = { @@ -192,9 +208,6 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status, g_free(acb->buf); if (acb->canceled != 0) { - qemu_aio_release(acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; return; } @@ -206,8 +219,6 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status, } iscsi_schedule_bh(acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; } static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun) @@ -236,6 +247,8 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num, acb->qiov = qiov; acb->canceled = 0; + acb->bh = NULL; + acb->status = -EINPROGRESS; /* XXX we should pass the iovec to write16 to avoid the extra copy */ /* this will allow us to get rid of 'buf' completely */ @@ -293,9 +306,6 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status, trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled); if (acb->canceled != 0) { - qemu_aio_release(acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; return; } @@ -307,8 +317,6 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status, } iscsi_schedule_bh(acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; } static BlockDriverAIOCB * @@ -334,6 +342,8 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num, acb->qiov = qiov; acb->canceled = 0; + acb->bh = NULL; + acb->status = -EINPROGRESS; acb->read_size = qemu_read_size; acb->buf = NULL; @@ -409,9 +419,6 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status, IscsiAIOCB *acb = opaque; if (acb->canceled != 0) { - qemu_aio_release(acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; return; } @@ -423,8 +430,6 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status, } iscsi_schedule_bh(acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; } static BlockDriverAIOCB * @@ -439,6 +444,8 @@ iscsi_aio_flush(BlockDriverState *bs, acb->iscsilun = iscsilun; acb->canceled = 0; + acb->bh = NULL; + acb->status = -EINPROGRESS; acb->task = iscsi_synchronizecache10_task(iscsi, iscsilun->lun, 0, 0, 0, 0, @@ -463,9 +470,6 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status, IscsiAIOCB *acb = opaque; if (acb->canceled != 0) { - qemu_aio_release(acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; return; } @@ -477,8 +481,6 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status, } iscsi_schedule_bh(acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; } static BlockDriverAIOCB * @@ -495,6 +497,8 @@ iscsi_aio_discard(BlockDriverState *bs, acb->iscsilun = iscsilun; acb->canceled = 0; + acb->bh = NULL; + acb->status = -EINPROGRESS; list[0].lba = sector_qemu2lun(sector_num, iscsilun); list[0].num = nb_sectors * BDRV_SECTOR_SIZE / iscsilun->block_size; @@ -523,9 +527,6 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status, IscsiAIOCB *acb = opaque; if (acb->canceled != 0) { - qemu_aio_release(acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; return; } @@ -554,8 +555,6 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status, } iscsi_schedule_bh(acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; } static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs, @@ -573,6 +572,8 @@ static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs, acb->iscsilun = iscsilun; acb->canceled = 0; + acb->bh = NULL; + acb->status = -EINPROGRESS; acb->buf = NULL; acb->ioh = buf; From 07a5298c3067ed63f7d82d8c1a6f479146447289 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 20 Aug 2012 15:23:28 +0200 Subject: [PATCH 0062/2270] virtio-scsi: add backwards-compatibility properties for 1.1 and earlier machines Hotplug and parameter change are new in 1.2, disable them via compat properties for pc-1.1 and earlier. Signed-off-by: Paolo Bonzini --- hw/pc_piix.c | 8 ++++++++ hw/virtio-scsi.c | 7 ------- hw/virtio-scsi.h | 9 ++++++++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 0c0096fd7e..a960710af8 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -360,6 +360,14 @@ static QEMUMachine pc_machine_v1_2 = { #define PC_COMPAT_1_1 \ {\ + .driver = "virtio-scsi-pci",\ + .property = "hotplug",\ + .value = "off",\ + },{\ + .driver = "virtio-scsi-pci",\ + .property = "param_change",\ + .value = "off",\ + },{\ .driver = "VGA",\ .property = "vgamem_mb",\ .value = stringify(8),\ diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c index 5f737acd97..c1b47a8f4d 100644 --- a/hw/virtio-scsi.c +++ b/hw/virtio-scsi.c @@ -24,11 +24,6 @@ #define VIRTIO_SCSI_MAX_TARGET 255 #define VIRTIO_SCSI_MAX_LUN 16383 -/* Feature Bits */ -#define VIRTIO_SCSI_F_INOUT 0 -#define VIRTIO_SCSI_F_HOTPLUG 1 -#define VIRTIO_SCSI_F_CHANGE 2 - /* Response codes */ #define VIRTIO_SCSI_S_OK 0 #define VIRTIO_SCSI_S_OVERRUN 1 @@ -561,8 +556,6 @@ static void virtio_scsi_set_config(VirtIODevice *vdev, static uint32_t virtio_scsi_get_features(VirtIODevice *vdev, uint32_t requested_features) { - requested_features |= (1UL << VIRTIO_SCSI_F_HOTPLUG); - requested_features |= (1UL << VIRTIO_SCSI_F_CHANGE); return requested_features; } diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h index 4bc889de02..91924f6dfc 100644 --- a/hw/virtio-scsi.h +++ b/hw/virtio-scsi.h @@ -21,6 +21,11 @@ /* The ID for virtio_scsi */ #define VIRTIO_ID_SCSI 8 +/* Feature Bits */ +#define VIRTIO_SCSI_F_INOUT 0 +#define VIRTIO_SCSI_F_HOTPLUG 1 +#define VIRTIO_SCSI_F_CHANGE 2 + struct VirtIOSCSIConf { uint32_t num_queues; uint32_t max_sectors; @@ -31,6 +36,8 @@ struct VirtIOSCSIConf { DEFINE_VIRTIO_COMMON_FEATURES(_state, _features_field), \ DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \ DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF), \ - DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128) + DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128), \ + DEFINE_PROP_BIT("hotplug", _state, _features_field, VIRTIO_SCSI_F_HOTPLUG, true), \ + DEFINE_PROP_BIT("param_change", _state, _features_field, VIRTIO_SCSI_F_CHANGE, true) #endif /* _QEMU_VIRTIO_SCSI_H */ From e36c87667aa2204a3f19efe7bbcb6eb41f098e40 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 18 Aug 2012 22:51:29 +0200 Subject: [PATCH 0063/2270] qapi: Fix memory leak valgrind report: ==24534== 232 bytes in 2 blocks are definitely lost in loss record 1,245 of 1,601 ==24534== at 0x4824F20: malloc (vg_replace_malloc.c:236) ==24534== by 0x293C88: malloc_and_trace (vl.c:2281) ==24534== by 0x489AD99: ??? (in /lib/libglib-2.0.so.0.2400.1) ==24534== by 0x489B23B: g_malloc0 (in /lib/libglib-2.0.so.0.2400.1) ==24534== by 0x2B4EFC: opts_visitor_new (opts-visitor.c:376) ==24534== by 0x29DEA5: net_client_init (net.c:708) ==24534== by 0x29E6C7: net_init_client (net.c:966) ==24534== by 0x2C2179: qemu_opts_foreach (qemu-option.c:1114) ==24534== by 0x29E85B: net_init_clients (net.c:1008) ==24534== by 0x296F40: main (vl.c:3463) Signed-off-by: Stefan Weil Reviewed-by: Laszlo Ersek Signed-off-by: Luiz Capitulino --- qapi/opts-visitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index a59d306e46..e048b6c863 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -416,7 +416,7 @@ opts_visitor_cleanup(OptsVisitor *ov) g_hash_table_destroy(ov->unprocessed_opts); } g_free(ov->fake_id_opt); - memset(ov, '\0', sizeof *ov); + g_free(ov); } From b2dc64c391843f6499069f0ba77ad0a8c9560c86 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sat, 18 Aug 2012 20:14:54 +0000 Subject: [PATCH 0064/2270] monitor: avoid declaring unused variables Some variables are only used on !win32, declare them only when used. This avoids a warning in mingw32 build: CC i386-softmmu/monitor.o /src/qemu/monitor.c: In function 'monitor_fdset_get_fd': /src/qemu/monitor.c:2575: warning: unused variable 'mon_fd_flags' /src/qemu/monitor.c:2574: warning: unused variable 'mon_fdset_fd' /src/qemu/monitor.c:2573: warning: unused variable 'mon_fdset' Signed-off-by: Blue Swirl Reviewed-by: Stefan Weil Signed-off-by: Luiz Capitulino --- monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monitor.c b/monitor.c index ce42466a63..480f583f70 100644 --- a/monitor.c +++ b/monitor.c @@ -2570,11 +2570,11 @@ FdsetInfoList *qmp_query_fdsets(Error **errp) int monitor_fdset_get_fd(int64_t fdset_id, int flags) { +#ifndef _WIN32 MonFdset *mon_fdset; MonFdsetFd *mon_fdset_fd; int mon_fd_flags; -#ifndef _WIN32 QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { if (mon_fdset->id != fdset_id) { continue; From 7aa939af39e20eeca98fced59708a87c64267f54 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Sat, 18 Aug 2012 13:17:10 +0200 Subject: [PATCH 0065/2270] migration: move total_time from ram stats to migration info Signed-off-by: Juan Quintela Signed-off-by: Luiz Capitulino --- hmp.c | 4 ++-- migration.c | 7 ++++--- qapi-schema.json | 14 +++++++------- qmp-commands.hx | 6 +++--- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/hmp.c b/hmp.c index a9d5675fc8..81c8acb67a 100644 --- a/hmp.c +++ b/hmp.c @@ -149,6 +149,8 @@ void hmp_info_migrate(Monitor *mon) if (info->has_status) { monitor_printf(mon, "Migration status: %s\n", info->status); + monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n", + info->total_time); } if (info->has_ram) { @@ -158,8 +160,6 @@ void hmp_info_migrate(Monitor *mon) info->ram->remaining >> 10); monitor_printf(mon, "total ram: %" PRIu64 " kbytes\n", info->ram->total >> 10); - monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n", - info->ram->total_time); monitor_printf(mon, "duplicate: %" PRIu64 " pages\n", info->ram->duplicate); monitor_printf(mon, "normal: %" PRIu64 " pages\n", diff --git a/migration.c b/migration.c index 653a3c1a88..1edeec5ddd 100644 --- a/migration.c +++ b/migration.c @@ -166,14 +166,15 @@ MigrationInfo *qmp_query_migrate(Error **errp) case MIG_STATE_ACTIVE: info->has_status = true; info->status = g_strdup("active"); + info->has_total_time = true; + info->total_time = qemu_get_clock_ms(rt_clock) + - s->total_time; info->has_ram = true; info->ram = g_malloc0(sizeof(*info->ram)); info->ram->transferred = ram_bytes_transferred(); info->ram->remaining = ram_bytes_remaining(); info->ram->total = ram_bytes_total(); - info->ram->total_time = qemu_get_clock_ms(rt_clock) - - s->total_time; info->ram->duplicate = dup_mig_pages_transferred(); info->ram->normal = norm_mig_pages_transferred(); info->ram->normal_bytes = norm_mig_bytes_transferred(); @@ -193,13 +194,13 @@ MigrationInfo *qmp_query_migrate(Error **errp) info->has_status = true; info->status = g_strdup("completed"); + info->total_time = s->total_time; info->has_ram = true; info->ram = g_malloc0(sizeof(*info->ram)); info->ram->transferred = ram_bytes_transferred(); info->ram->remaining = 0; info->ram->total = ram_bytes_total(); - info->ram->total_time = s->total_time; info->ram->duplicate = dup_mig_pages_transferred(); info->ram->normal = norm_mig_pages_transferred(); info->ram->normal_bytes = norm_mig_bytes_transferred(); diff --git a/qapi-schema.json b/qapi-schema.json index 3d2b2d175a..37f47e1717 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -290,10 +290,6 @@ # # @total: total amount of bytes involved in the migration process # -# @total-time: total amount of ms since migration started. If -# migration has ended, it returns the total migration -# time. (since 1.2) -# # @duplicate: number of duplicate pages (since 1.2) # # @normal : number of normal pages (since 1.2) @@ -304,8 +300,7 @@ ## { 'type': 'MigrationStats', 'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' , - 'total-time': 'int', 'duplicate': 'int', 'normal': 'int', - 'normal-bytes': 'int' } } + 'duplicate': 'int', 'normal': 'int', 'normal-bytes': 'int' } } ## # @XBZRLECacheStats @@ -350,12 +345,17 @@ # migration statistics, only returned if XBZRLE feature is on and # status is 'active' or 'completed' (since 1.2) # +# @total-time: #optional total amount of milliseconds since migration started. +# If migration has ended, it returns the total migration +# time. (since 1.2) +# # Since: 0.14.0 ## { 'type': 'MigrationInfo', 'data': {'*status': 'str', '*ram': 'MigrationStats', '*disk': 'MigrationStats', - '*xbzrle-cache': 'XBZRLECacheStats'} } + '*xbzrle-cache': 'XBZRLECacheStats', + '*total-time': 'int'} } ## # @query-migrate diff --git a/qmp-commands.hx b/qmp-commands.hx index 2ce4ce6556..8671bf33a8 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -2239,14 +2239,14 @@ The main json-object contains the following: - "status": migration status (json-string) - Possible values: "active", "completed", "failed", "cancelled" +- "total-time": total amount of ms since migration started. If + migration has ended, it returns the total migration + time (json-int) - "ram": only present if "status" is "active", it is a json-object with the following RAM information (in bytes): - "transferred": amount transferred (json-int) - "remaining": amount remaining (json-int) - "total": total (json-int) - - "total-time": total amount of ms since migration started. If - migration has ended, it returns the total migration time - (json-int) - "duplicate": number of duplicated pages (json-int) - "normal" : number of normal pages transferred (json-int) - "normal-bytes" : number of normal bytes transferred (json-int) From 55ce75faf253d4369670f60409c608e665e8dde9 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Wed, 18 Jul 2012 22:52:04 +1000 Subject: [PATCH 0066/2270] eventfd: making it thread safe QEMU uses IO handlers to run select() in the main loop. The handlers list is managed by qemu_set_fd_handler() helper which works fine when called from the main thread as it is called when select() is not waiting. However IO handlers list can be changed in the thread other than the main one doing os_host_main_loop_wait(), for example, as a result of a hypercall which changes PCI config space (VFIO on POWER is the case) and enables/disabled MSI/MSIX which closes/creates eventfd handles. As the main loop should be waiting on the newly created eventfds, it has to be restarted. The patch adds the qemu_notify_event() call to interrupt select() to make main_loop() restart select() with the updated IO handlers list. Signed-off-by: Alexey Kardashevskiy Reviewed-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- iohandler.c | 1 + 1 file changed, 1 insertion(+) diff --git a/iohandler.c b/iohandler.c index 3c74de612b..dea43552d2 100644 --- a/iohandler.c +++ b/iohandler.c @@ -77,6 +77,7 @@ int qemu_set_fd_handler2(int fd, ioh->fd_write = fd_write; ioh->opaque = opaque; ioh->deleted = 0; + qemu_notify_event(); } return 0; } From 0ec64507a5e6366e6d8070a82c866b935f687ed9 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 17 Aug 2012 12:56:44 +0200 Subject: [PATCH 0067/2270] i82378: Remove bogus MMIO coalescing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This MMIO area is an entry gate to legacy PC ISA devices, addressed via PIO over there. Quite a few of the PIO ports have side effects on access like starting/stopping timers that must be executed properly ordered /wrt the CPU. So we have to remove the coalescing mark. Acked-by: Hervé Poussineau Acked-by: Andreas Färber Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- hw/i82378.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/i82378.c b/hw/i82378.c index 9b11d907eb..2123c142aa 100644 --- a/hw/i82378.c +++ b/hw/i82378.c @@ -225,7 +225,6 @@ static int pci_i82378_init(PCIDevice *dev) pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io); memory_region_init_io(&s->mem, &i82378_mem_ops, s, "i82378-mem", 0x01000000); - memory_region_set_coalescing(&s->mem); pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); /* Make I/O address read only */ From 27b7652ef515bb4c694f79d657d2052c72b19536 Mon Sep 17 00:00:00 2001 From: Frediano Ziglio Date: Wed, 22 Aug 2012 10:17:04 +0000 Subject: [PATCH 0068/2270] Fix invalidate if memory requested was not bucket aligned When memory is mapped in qemu_map_cache with lock != 0 a reverse mapping is created pointing to the virtual address of location requested. The cached mapped entry is saved in last_address_vaddr with the memory location of the base virtual address (without bucket offset). However when this entry is invalidated the virtual address saved in the reverse mapping is used. This cause that the mapping is freed but the last_address_vaddr is not reset. Signed-off-by: Frediano Ziglio Signed-off-by: Stefano Stabellini --- xen-mapcache.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/xen-mapcache.c b/xen-mapcache.c index 59ba085b62..9cd6db3d7b 100644 --- a/xen-mapcache.c +++ b/xen-mapcache.c @@ -320,10 +320,6 @@ void xen_invalidate_map_cache_entry(uint8_t *buffer) target_phys_addr_t size; int found = 0; - if (mapcache->last_address_vaddr == buffer) { - mapcache->last_address_index = -1; - } - QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) { if (reventry->vaddr_req == buffer) { paddr_index = reventry->paddr_index; @@ -342,6 +338,11 @@ void xen_invalidate_map_cache_entry(uint8_t *buffer) QTAILQ_REMOVE(&mapcache->locked_entries, reventry, next); g_free(reventry); + if (mapcache->last_address_index == paddr_index) { + mapcache->last_address_index = -1; + mapcache->last_address_vaddr = NULL; + } + entry = &mapcache->entry[paddr_index % mapcache->nr_buckets]; while (entry && (entry->paddr_index != paddr_index || entry->size != size)) { pentry = entry; From 14d40183725361e6350166099556c7661063921b Mon Sep 17 00:00:00 2001 From: Dongxiao Xu Date: Wed, 22 Aug 2012 10:17:43 +0000 Subject: [PATCH 0069/2270] xen-all.c: fix multiply issue for int and uint types If the two multiply operands are int and uint types separately, the int type will be transformed to uint firstly, which is not the intent in our code piece. The fix is to add (int64_t) transform for the uint type before the multiply. Signed-off-by: Dongxiao Xu Signed-off-by: Stefano Stabellini --- xen-all.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/xen-all.c b/xen-all.c index 61def2ec8f..f76b051eee 100644 --- a/xen-all.c +++ b/xen-all.c @@ -712,7 +712,8 @@ static void cpu_ioreq_pio(ioreq_t *req) for (i = 0; i < req->count; i++) { tmp = do_inp(req->addr, req->size); - cpu_physical_memory_write(req->data + (sign * i * req->size), + cpu_physical_memory_write( + req->data + (sign * i * (int64_t)req->size), (uint8_t *) &tmp, req->size); } } @@ -723,7 +724,8 @@ static void cpu_ioreq_pio(ioreq_t *req) for (i = 0; i < req->count; i++) { uint32_t tmp = 0; - cpu_physical_memory_read(req->data + (sign * i * req->size), + cpu_physical_memory_read( + req->data + (sign * i * (int64_t)req->size), (uint8_t*) &tmp, req->size); do_outp(req->addr, req->size, tmp); } @@ -740,12 +742,14 @@ static void cpu_ioreq_move(ioreq_t *req) if (!req->data_is_ptr) { if (req->dir == IOREQ_READ) { for (i = 0; i < req->count; i++) { - cpu_physical_memory_read(req->addr + (sign * i * req->size), + cpu_physical_memory_read( + req->addr + (sign * i * (int64_t)req->size), (uint8_t *) &req->data, req->size); } } else if (req->dir == IOREQ_WRITE) { for (i = 0; i < req->count; i++) { - cpu_physical_memory_write(req->addr + (sign * i * req->size), + cpu_physical_memory_write( + req->addr + (sign * i * (int64_t)req->size), (uint8_t *) &req->data, req->size); } } @@ -754,16 +758,20 @@ static void cpu_ioreq_move(ioreq_t *req) if (req->dir == IOREQ_READ) { for (i = 0; i < req->count; i++) { - cpu_physical_memory_read(req->addr + (sign * i * req->size), + cpu_physical_memory_read( + req->addr + (sign * i * (int64_t)req->size), (uint8_t*) &tmp, req->size); - cpu_physical_memory_write(req->data + (sign * i * req->size), + cpu_physical_memory_write( + req->data + (sign * i * (int64_t)req->size), (uint8_t*) &tmp, req->size); } } else if (req->dir == IOREQ_WRITE) { for (i = 0; i < req->count; i++) { - cpu_physical_memory_read(req->data + (sign * i * req->size), + cpu_physical_memory_read( + req->data + (sign * i * (int64_t)req->size), (uint8_t*) &tmp, req->size); - cpu_physical_memory_write(req->addr + (sign * i * req->size), + cpu_physical_memory_write( + req->addr + (sign * i * (int64_t)req->size), (uint8_t*) &tmp, req->size); } } From 4144f122b477164cf466ca69be24cf4ef5c218d3 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Wed, 22 Aug 2012 13:55:52 +0200 Subject: [PATCH 0070/2270] qemu-ga: don't leak a file descriptor upon failed lockf Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- qemu-ga.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/qemu-ga.c b/qemu-ga.c index 8f87621ae4..26671fee3f 100644 --- a/qemu-ga.c +++ b/qemu-ga.c @@ -247,6 +247,9 @@ static bool ga_open_pidfile(const char *pidfile) pidfd = open(pidfile, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR); if (pidfd == -1 || lockf(pidfd, F_TLOCK, 0)) { g_critical("Cannot lock pid file, %s", strerror(errno)); + if (pidfd != -1) { + close(pidfd); + } return false; } From 0d07fe47d4986271a21ed4ff5237275ff55dd93f Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Wed, 22 Aug 2012 13:55:53 +0200 Subject: [PATCH 0071/2270] linux-user: do_msgrcv: don't leak host_mb upon TARGET_EFAULT failure Also, use g_malloc to avoid NULL-deref upon OOM. Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- linux-user/syscall.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 41c869bfe0..11743065e9 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -2848,7 +2848,7 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp, if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0)) return -TARGET_EFAULT; - host_mb = malloc(msgsz+sizeof(long)); + host_mb = g_malloc(msgsz+sizeof(long)); ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapal(msgtyp), msgflg)); if (ret > 0) { @@ -2863,11 +2863,11 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp, } target_mb->mtype = tswapal(host_mb->mtype); - free(host_mb); end: if (target_mb) unlock_user_struct(target_mb, msgp, 1); + g_free(host_mb); return ret; } From a7e47d4bfcbf256fae06891a8599950ff8e1b61b Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Wed, 22 Aug 2012 13:55:54 +0200 Subject: [PATCH 0072/2270] sheepdog: don't leak socket file descriptor upon connection failure Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- block/sheepdog.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block/sheepdog.c b/block/sheepdog.c index a04ad99ead..df4f44107b 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -485,6 +485,7 @@ static int connect_to_sdog(const char *addr, const char *port) if (errno == EINTR) { goto reconnect; } + close(fd); break; } From 396bef4b3846bf4e80a2bee38e9a2d8554d0f251 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Wed, 22 Aug 2012 13:55:55 +0200 Subject: [PATCH 0073/2270] arm-semi: don't leak 1KB user string lock buffer upon TARGET_SYS_OPEN Always call unlock_user before returning. Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- target-arm/arm-semi.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/target-arm/arm-semi.c b/target-arm/arm-semi.c index 24952061cf..73bde584ab 100644 --- a/target-arm/arm-semi.c +++ b/target-arm/arm-semi.c @@ -194,18 +194,19 @@ uint32_t do_arm_semihosting(CPUARMState *env) if (!(s = lock_user_string(ARG(0)))) /* FIXME - should this error code be -TARGET_EFAULT ? */ return (uint32_t)-1; - if (ARG(1) >= 12) + if (ARG(1) >= 12) { + unlock_user(s, ARG(0), 0); return (uint32_t)-1; + } if (strcmp(s, ":tt") == 0) { - if (ARG(1) < 4) - return STDIN_FILENO; - else - return STDOUT_FILENO; + int result_fileno = ARG(1) < 4 ? STDIN_FILENO : STDOUT_FILENO; + unlock_user(s, ARG(0), 0); + return result_fileno; } if (use_gdb_syscalls()) { gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0), (int)ARG(2)+1, gdb_open_modeflags[ARG(1)]); - return env->regs[0]; + ret = env->regs[0]; } else { ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644)); } From 15d9e3bc6af8a56af8c61911aab8453a54795db1 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Wed, 22 Aug 2012 13:55:56 +0200 Subject: [PATCH 0074/2270] softmmu-semi: fix lock_user* functions not to deref NULL upon OOM Return NULL upon malloc failure. Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- softmmu-semi.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/softmmu-semi.h b/softmmu-semi.h index 648cb959d8..bcb979a5b0 100644 --- a/softmmu-semi.h +++ b/softmmu-semi.h @@ -40,7 +40,7 @@ static void *softmmu_lock_user(CPUArchState *env, uint32_t addr, uint32_t len, uint8_t *p; /* TODO: Make this something that isn't fixed size. */ p = malloc(len); - if (copy) + if (p && copy) cpu_memory_rw_debug(env, addr, p, len, 0); return p; } @@ -52,6 +52,9 @@ static char *softmmu_lock_user_string(CPUArchState *env, uint32_t addr) uint8_t c; /* TODO: Make this something that isn't fixed size. */ s = p = malloc(1024); + if (!s) { + return NULL; + } do { cpu_memory_rw_debug(env, addr, &c, 1, 0); addr++; From ea776abca628d855e03c4929da3864985afd8aae Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 21 Aug 2012 14:40:49 +0100 Subject: [PATCH 0075/2270] virtio-blk: hide VIRTIO_BLK_F_CONFIG_WCE from old machine types QEMU has a policy of keeping a stable guest device ABI. When new guest device features are introduced they must not change hardware info seen by existing guests. This is important because operating systems or applications may "fingerprint" the hardware and refuse to run when the hardware changes. To always get the latest guest device ABI, run with x86 machine type "pc". This patch hides the new VIRTIO_BLK_F_CONFIG_WCE virtio feature bit from existing machine types. Only pc-1.2 and later will expose this feature by default. For more info on the VIRTIO_BLK_F_CONFIG_WCE feature bit, see: commit 13e3dce068773c971ff2f19d986378c55897c4a3 Author: Paolo Bonzini Date: Thu Aug 9 16:07:19 2012 +0200 virtio-blk: support VIRTIO_BLK_F_CONFIG_WCE Also rename VIRTIO_BLK_F_WCACHE to VIRTIO_BLK_F_WCE for consistency with the spec. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf Anthony Liguori reported: This broke qemu-test because it changed the pc-1.0 machine type: Setting guest RANDOM seed to 47167 *** Running tests *** Running test /tests/finger-print.sh... OK --- fingerprints/pc-1.0.x86_64 2011-12-18 13:08:40.000000000 -0600 +++ fingerprint.txt 2012-08-12 13:30:48.000000000 -0500 @@ -55,7 +55,7 @@ /sys/bus/pci/devices/0000:00:06.0/subsystem_device=0x0002 /sys/bus/pci/devices/0000:00:06.0/class=0x010000 /sys/bus/pci/devices/0000:00:06.0/revision=0x00 -/sys/bus/pci/devices/0000:00:06.0/virtio/host-features=0x710006d4 +/sys/bus/pci/devices/0000:00:06.0/virtio/host-features=0x71000ed4 /sys/class/dmi/id/bios_vendor=Bochs /sys/class/dmi/id/bios_date=01/01/2007 /sys/class/dmi/id/bios_version=Bochs Guest fingerprint changed for pc-1.0! Reported-by: Anthony Liguori Signed-off-by: Stefan Hajnoczi Signed-off-by: Anthony Liguori --- hw/pc_piix.c | 4 ++++ hw/virtio-blk.c | 1 - hw/virtio-blk.h | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 0c0096fd7e..d68dbb2320 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -375,6 +375,10 @@ static QEMUMachine pc_machine_v1_2 = { .driver = "qxl",\ .property = "vgamem_mb",\ .value = stringify(8),\ + },{\ + .driver = "virtio-blk-pci",\ + .property = "config-wce",\ + .value = "off",\ } static QEMUMachine pc_machine_v1_1 = { diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index fd8fa90792..6f6d172fd0 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -533,7 +533,6 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features) features |= (1 << VIRTIO_BLK_F_BLK_SIZE); features |= (1 << VIRTIO_BLK_F_SCSI); - features |= (1 << VIRTIO_BLK_F_CONFIG_WCE); if (bdrv_enable_write_cache(s->bs)) features |= (1 << VIRTIO_BLK_F_WCE); diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h index 35834cf493..651a000b9f 100644 --- a/hw/virtio-blk.h +++ b/hw/virtio-blk.h @@ -107,6 +107,7 @@ struct VirtIOBlkConf }; #define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \ - DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) + DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \ + DEFINE_PROP_BIT("config-wce", _state, _field, VIRTIO_BLK_F_CONFIG_WCE, true) #endif From 4240abff5a6fb5d88867b51f46c0235518dac564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 20 Aug 2012 19:07:56 +0200 Subject: [PATCH 0076/2270] pci: Make host bridge TypeInfos const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During the QOM migration they were amended with further info but this is no longer the case. All static TypeInfos can be const these days. Signed-off-by: Andreas Färber Acked-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- hw/alpha_typhoon.c | 2 +- hw/bonito.c | 4 ++-- hw/dec_pci.c | 6 +++--- hw/grackle_pci.c | 4 ++-- hw/gt64xxx.c | 4 ++-- hw/piix_pci.c | 8 ++++---- hw/ppc4xx_pci.c | 4 ++-- hw/ppce500_pci.c | 4 ++-- hw/prep_pci.c | 4 ++-- hw/spapr_pci.c | 2 +- hw/unin_pci.c | 16 ++++++++-------- 11 files changed, 29 insertions(+), 29 deletions(-) diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c index 872e1122e8..cc637375c8 100644 --- a/hw/alpha_typhoon.c +++ b/hw/alpha_typhoon.c @@ -817,7 +817,7 @@ static void typhoon_pcihost_class_init(ObjectClass *klass, void *data) dc->no_user = 1; } -static TypeInfo typhoon_pcihost_info = { +static const TypeInfo typhoon_pcihost_info = { .name = "typhoon-pcihost", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(TyphoonState), diff --git a/hw/bonito.c b/hw/bonito.c index 77786f8883..b990875cf0 100644 --- a/hw/bonito.c +++ b/hw/bonito.c @@ -781,7 +781,7 @@ static void bonito_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_bonito; } -static TypeInfo bonito_info = { +static const TypeInfo bonito_info = { .name = "Bonito", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIBonitoState), @@ -797,7 +797,7 @@ static void bonito_pcihost_class_init(ObjectClass *klass, void *data) dc->no_user = 1; } -static TypeInfo bonito_pcihost_info = { +static const TypeInfo bonito_pcihost_info = { .name = "Bonito-pcihost", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(BonitoState), diff --git a/hw/dec_pci.c b/hw/dec_pci.c index 37337bf4b6..5194a9fc7d 100644 --- a/hw/dec_pci.c +++ b/hw/dec_pci.c @@ -66,7 +66,7 @@ static void dec_21154_pci_bridge_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_pci_device; } -static TypeInfo dec_21154_pci_bridge_info = { +static const TypeInfo dec_21154_pci_bridge_info = { .name = "dec-21154-p2p-bridge", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIBridge), @@ -119,7 +119,7 @@ static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data) k->is_bridge = 1; } -static TypeInfo dec_21154_pci_host_info = { +static const TypeInfo dec_21154_pci_host_info = { .name = "dec-21154", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIDevice), @@ -133,7 +133,7 @@ static void pci_dec_21154_device_class_init(ObjectClass *klass, void *data) sdc->init = pci_dec_21154_device_init; } -static TypeInfo pci_dec_21154_device_info = { +static const TypeInfo pci_dec_21154_device_info = { .name = "dec-21154-sysbus", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(DECState), diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c index 81ff3a339a..35667ade0b 100644 --- a/hw/grackle_pci.c +++ b/hw/grackle_pci.c @@ -134,7 +134,7 @@ static void grackle_pci_class_init(ObjectClass *klass, void *data) dc->no_user = 1; } -static TypeInfo grackle_pci_info = { +static const TypeInfo grackle_pci_info = { .name = "grackle", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIDevice), @@ -150,7 +150,7 @@ static void pci_grackle_class_init(ObjectClass *klass, void *data) dc->no_user = 1; } -static TypeInfo grackle_pci_host_info = { +static const TypeInfo grackle_pci_host_info = { .name = "grackle-pcihost", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(GrackleState), diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c index a2d0e5a2c3..04831bb07f 100644 --- a/hw/gt64xxx.c +++ b/hw/gt64xxx.c @@ -1147,7 +1147,7 @@ static void gt64120_pci_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_BRIDGE_HOST; } -static TypeInfo gt64120_pci_info = { +static const TypeInfo gt64120_pci_info = { .name = "gt64120_pci", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIDevice), @@ -1161,7 +1161,7 @@ static void gt64120_class_init(ObjectClass *klass, void *data) sdc->init = gt64120_init; } -static TypeInfo gt64120_info = { +static const TypeInfo gt64120_info = { .name = "gt64120", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(GT64120State), diff --git a/hw/piix_pci.c b/hw/piix_pci.c index c497a014af..0b06a75a8d 100644 --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@ -537,7 +537,7 @@ static void piix3_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_BRIDGE_ISA; } -static TypeInfo piix3_info = { +static const TypeInfo piix3_info = { .name = "PIIX3", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PIIX3State), @@ -560,7 +560,7 @@ static void piix3_xen_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_BRIDGE_ISA; }; -static TypeInfo piix3_xen_info = { +static const TypeInfo piix3_xen_info = { .name = "PIIX3-xen", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PIIX3State), @@ -584,7 +584,7 @@ static void i440fx_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_i440fx; } -static TypeInfo i440fx_info = { +static const TypeInfo i440fx_info = { .name = "i440FX", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCII440FXState), @@ -601,7 +601,7 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data) dc->no_user = 1; } -static TypeInfo i440fx_pcihost_info = { +static const TypeInfo i440fx_pcihost_info = { .name = "i440FX-pcihost", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(I440FXState), diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c index 203c3cdc47..104ed98cb3 100644 --- a/hw/ppc4xx_pci.c +++ b/hw/ppc4xx_pci.c @@ -377,7 +377,7 @@ static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_BRIDGE_OTHER; } -static TypeInfo ppc4xx_host_bridge_info = { +static const TypeInfo ppc4xx_host_bridge_info = { .name = "ppc4xx-host-bridge", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIDevice), @@ -393,7 +393,7 @@ static void ppc4xx_pcihost_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_ppc4xx_pci; } -static TypeInfo ppc4xx_pcihost_info = { +static const TypeInfo ppc4xx_pcihost_info = { .name = "ppc4xx-pcihost", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(PPC4xxPCIState), diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 0f60b24134..99748b311f 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -350,7 +350,7 @@ static void e500_host_bridge_class_init(ObjectClass *klass, void *data) dc->desc = "Host bridge"; } -static TypeInfo e500_host_bridge_info = { +static const TypeInfo e500_host_bridge_info = { .name = "e500-host-bridge", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIDevice), @@ -366,7 +366,7 @@ static void e500_pcihost_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_ppce500_pci; } -static TypeInfo e500_pcihost_info = { +static const TypeInfo e500_pcihost_info = { .name = "e500-pcihost", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(PPCE500PCIState), diff --git a/hw/prep_pci.c b/hw/prep_pci.c index 38dbff44a1..a8cdc21bb4 100644 --- a/hw/prep_pci.c +++ b/hw/prep_pci.c @@ -166,7 +166,7 @@ static void raven_class_init(ObjectClass *klass, void *data) dc->no_user = 1; } -static TypeInfo raven_info = { +static const TypeInfo raven_info = { .name = "raven", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(RavenPCIState), @@ -183,7 +183,7 @@ static void raven_pcihost_class_init(ObjectClass *klass, void *data) dc->no_user = 1; } -static TypeInfo raven_pcihost_info = { +static const TypeInfo raven_pcihost_info = { .name = "raven-pcihost", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(PREPPCIState), diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index b92583a991..c57ab1ee2b 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -612,7 +612,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data) dc->props = spapr_phb_properties; } -static TypeInfo spapr_phb_info = { +static const TypeInfo spapr_phb_info = { .name = "spapr-pci-host-bridge", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(sPAPRPHBState), diff --git a/hw/unin_pci.c b/hw/unin_pci.c index 409bcd4cc6..2b309dfe82 100644 --- a/hw/unin_pci.c +++ b/hw/unin_pci.c @@ -350,7 +350,7 @@ static void unin_main_pci_host_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_BRIDGE_HOST; } -static TypeInfo unin_main_pci_host_info = { +static const TypeInfo unin_main_pci_host_info = { .name = "uni-north-pci", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIDevice), @@ -368,7 +368,7 @@ static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_BRIDGE_HOST; } -static TypeInfo u3_agp_pci_host_info = { +static const TypeInfo u3_agp_pci_host_info = { .name = "u3-agp", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIDevice), @@ -386,7 +386,7 @@ static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_BRIDGE_HOST; } -static TypeInfo unin_agp_pci_host_info = { +static const TypeInfo unin_agp_pci_host_info = { .name = "uni-north-agp", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIDevice), @@ -404,7 +404,7 @@ static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_BRIDGE_HOST; } -static TypeInfo unin_internal_pci_host_info = { +static const TypeInfo unin_internal_pci_host_info = { .name = "uni-north-internal-pci", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIDevice), @@ -418,7 +418,7 @@ static void pci_unin_main_class_init(ObjectClass *klass, void *data) sbc->init = pci_unin_main_init_device; } -static TypeInfo pci_unin_main_info = { +static const TypeInfo pci_unin_main_info = { .name = "uni-north-pci-pcihost", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(UNINState), @@ -432,7 +432,7 @@ static void pci_u3_agp_class_init(ObjectClass *klass, void *data) sbc->init = pci_u3_agp_init_device; } -static TypeInfo pci_u3_agp_info = { +static const TypeInfo pci_u3_agp_info = { .name = "u3-agp-pcihost", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(UNINState), @@ -446,7 +446,7 @@ static void pci_unin_agp_class_init(ObjectClass *klass, void *data) sbc->init = pci_unin_agp_init_device; } -static TypeInfo pci_unin_agp_info = { +static const TypeInfo pci_unin_agp_info = { .name = "uni-north-agp-pcihost", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(UNINState), @@ -460,7 +460,7 @@ static void pci_unin_internal_class_init(ObjectClass *klass, void *data) sbc->init = pci_unin_internal_init_device; } -static TypeInfo pci_unin_internal_info = { +static const TypeInfo pci_unin_internal_info = { .name = "uni-north-internal-pci-pcihost", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(UNINState), From 94dd91d651fe821971411280f8c64a6b72e8ca64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 20 Aug 2012 19:07:57 +0200 Subject: [PATCH 0077/2270] alpha_typhoon: QOM'ify Typhoon PCI host bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce type constant and cast macro. Don't access DeviceState or PCIHostState indirectly through parent fields. Signed-off-by: Andreas Färber Acked-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- hw/alpha_typhoon.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c index cc637375c8..10e588af9d 100644 --- a/hw/alpha_typhoon.c +++ b/hw/alpha_typhoon.c @@ -15,6 +15,8 @@ #include "exec-memory.h" +#define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost" + typedef struct TyphoonCchip { MemoryRegion region; uint64_t misc; @@ -40,8 +42,12 @@ typedef struct TyphoonPchip { TyphoonWindow win[4]; } TyphoonPchip; +#define TYPHOON_PCI_HOST_BRIDGE(obj) \ + OBJECT_CHECK(TyphoonState, (obj), TYPE_TYPHOON_PCI_HOST_BRIDGE) + typedef struct TyphoonState { PCIHostState host; + TyphoonCchip cchip; TyphoonPchip pchip; MemoryRegion dchip_region; @@ -700,16 +706,16 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, MemoryRegion *addr_space = get_system_memory(); MemoryRegion *addr_space_io = get_system_io(); DeviceState *dev; - PCIHostState *p; TyphoonState *s; + PCIHostState *phb; PCIBus *b; int i; - dev = qdev_create(NULL, "typhoon-pcihost"); + dev = qdev_create(NULL, TYPE_TYPHOON_PCI_HOST_BRIDGE); qdev_init_nofail(dev); - p = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev)); - s = container_of(p, TyphoonState, host); + s = TYPHOON_PCI_HOST_BRIDGE(dev); + phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(dev)); /* Remember the CPUs so that we can deliver interrupts to them. */ for (i = 0; i < 4; i++) { @@ -763,10 +769,10 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, memory_region_add_subregion(addr_space, 0x801fc000000ULL, &s->pchip.reg_io); - b = pci_register_bus(&s->host.busdev.qdev, "pci", + b = pci_register_bus(dev, "pci", typhoon_set_irq, sys_map_irq, s, &s->pchip.reg_mem, addr_space_io, 0, 64); - s->host.bus = b; + phb->bus = b; /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB. */ memory_region_init_io(&s->pchip.reg_iack, &alpha_pci_iack_ops, b, @@ -818,7 +824,7 @@ static void typhoon_pcihost_class_init(ObjectClass *klass, void *data) } static const TypeInfo typhoon_pcihost_info = { - .name = "typhoon-pcihost", + .name = TYPE_TYPHOON_PCI_HOST_BRIDGE, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(TyphoonState), .class_init = typhoon_pcihost_class_init, From c5589ee9745319944886231935680fb8d110e6cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 20 Aug 2012 19:07:58 +0200 Subject: [PATCH 0078/2270] bonito: QOM'ify Bonito PCI host bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce type constant. Avoid accessing DeviceState or SysBusDevice indirectly through PCIHostState field. Drop global state by passing BonitoState as opaque and adding the IRQs and a pointer to PCIBonitoState to its state. Signed-off-by: Andreas Färber Acked-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- hw/bonito.c | 146 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 90 insertions(+), 56 deletions(-) diff --git a/hw/bonito.c b/hw/bonito.c index b990875cf0..062c701161 100644 --- a/hw/bonito.c +++ b/hw/bonito.c @@ -180,11 +180,14 @@ #define PCI_ADDR(busno,devno,funno,regno) \ ((((busno)<<16)&0xff0000) + (((devno)<<11)&0xf800) + (((funno)<<8)&0x700) + (regno)) -typedef PCIHostState BonitoState; +#define TYPE_BONITO_PCI_HOST_BRIDGE "Bonito-pcihost" + +typedef struct BonitoState BonitoState; typedef struct PCIBonitoState { PCIDevice dev; + BonitoState *pcihost; uint32_t regs[BONITO_REGS]; @@ -218,7 +221,16 @@ typedef struct PCIBonitoState } PCIBonitoState; -PCIBonitoState * bonito_state; +#define BONITO_PCI_HOST_BRIDGE(obj) \ + OBJECT_CHECK(BonitoState, (obj), TYPE_BONITO_PCI_HOST_BRIDGE) + +struct BonitoState { + PCIHostState parent_obj; + + qemu_irq *pic; + + PCIBonitoState *pci_dev; +}; static void bonito_writel(void *opaque, target_phys_addr_t addr, uint64_t val, unsigned size) @@ -314,9 +326,10 @@ static void bonito_pciconf_writel(void *opaque, target_phys_addr_t addr, uint64_t val, unsigned size) { PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); DPRINTF("bonito_pciconf_writel "TARGET_FMT_plx" val %x\n", addr, val); - s->dev.config_write(&s->dev, addr, val, 4); + d->config_write(d, addr, val, 4); } static uint64_t bonito_pciconf_readl(void *opaque, target_phys_addr_t addr, @@ -324,9 +337,10 @@ static uint64_t bonito_pciconf_readl(void *opaque, target_phys_addr_t addr, { PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); DPRINTF("bonito_pciconf_readl "TARGET_FMT_plx"\n", addr); - return s->dev.config_read(&s->dev, addr, 4); + return d->config_read(d, addr, 4); } /* north bridge PCI configure space. 0x1fe0 0000 - 0x1fe0 00ff */ @@ -402,6 +416,7 @@ static const MemoryRegionOps bonito_cop_ops = { static uint32_t bonito_sbridge_pciaddr(void *opaque, target_phys_addr_t addr) { PCIBonitoState *s = opaque; + PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); uint32_t cfgaddr; uint32_t idsel; uint32_t devno; @@ -423,13 +438,13 @@ static uint32_t bonito_sbridge_pciaddr(void *opaque, target_phys_addr_t addr) regno = (cfgaddr & BONITO_PCICONF_REG_MASK) >> BONITO_PCICONF_REG_OFFSET; if (idsel == 0) { - fprintf(stderr, "error in bonito pci config address" TARGET_FMT_plx + fprintf(stderr, "error in bonito pci config address " TARGET_FMT_plx ",pcimap_cfg=%x\n", addr, s->regs[BONITO_PCIMAP_CFG]); exit(1); } - pciaddr = PCI_ADDR(pci_bus_num(s->pcihost->bus), devno, funno, regno); + pciaddr = PCI_ADDR(pci_bus_num(phb->bus), devno, funno, regno); DPRINTF("cfgaddr %x pciaddr %x busno %x devno %d funno %d regno %d\n", - cfgaddr, pciaddr, pci_bus_num(s->pcihost->bus), devno, funno, regno); + cfgaddr, pciaddr, pci_bus_num(phb->bus), devno, funno, regno); return pciaddr; } @@ -438,6 +453,8 @@ static void bonito_spciconf_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) { PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); + PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); uint32_t pciaddr; uint16_t status; @@ -449,24 +466,26 @@ static void bonito_spciconf_writeb(void *opaque, target_phys_addr_t addr, } /* set the pci address in s->config_reg */ - s->pcihost->config_reg = (pciaddr) | (1u << 31); - pci_data_write(s->pcihost->bus, s->pcihost->config_reg, val & 0xff, 1); + phb->config_reg = (pciaddr) | (1u << 31); + pci_data_write(phb->bus, phb->config_reg, val & 0xff, 1); /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(s->dev.config + PCI_STATUS); + status = pci_get_word(d->config + PCI_STATUS); status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(s->dev.config + PCI_STATUS, status); + pci_set_word(d->config + PCI_STATUS, status); } static void bonito_spciconf_writew(void *opaque, target_phys_addr_t addr, uint32_t val) { PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); + PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); uint32_t pciaddr; uint16_t status; DPRINTF("bonito_spciconf_writew "TARGET_FMT_plx" val %x\n", addr, val); - assert((addr&0x1)==0); + assert((addr & 0x1) == 0); pciaddr = bonito_sbridge_pciaddr(s, addr); @@ -475,24 +494,26 @@ static void bonito_spciconf_writew(void *opaque, target_phys_addr_t addr, } /* set the pci address in s->config_reg */ - s->pcihost->config_reg = (pciaddr) | (1u << 31); - pci_data_write(s->pcihost->bus, s->pcihost->config_reg, val, 2); + phb->config_reg = (pciaddr) | (1u << 31); + pci_data_write(phb->bus, phb->config_reg, val, 2); /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(s->dev.config + PCI_STATUS); + status = pci_get_word(d->config + PCI_STATUS); status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(s->dev.config + PCI_STATUS, status); + pci_set_word(d->config + PCI_STATUS, status); } static void bonito_spciconf_writel(void *opaque, target_phys_addr_t addr, uint32_t val) { PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); + PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); uint32_t pciaddr; uint16_t status; DPRINTF("bonito_spciconf_writel "TARGET_FMT_plx" val %x\n", addr, val); - assert((addr&0x3)==0); + assert((addr & 0x3) == 0); pciaddr = bonito_sbridge_pciaddr(s, addr); @@ -501,18 +522,20 @@ static void bonito_spciconf_writel(void *opaque, target_phys_addr_t addr, } /* set the pci address in s->config_reg */ - s->pcihost->config_reg = (pciaddr) | (1u << 31); - pci_data_write(s->pcihost->bus, s->pcihost->config_reg, val, 4); + phb->config_reg = (pciaddr) | (1u << 31); + pci_data_write(phb->bus, phb->config_reg, val, 4); /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(s->dev.config + PCI_STATUS); + status = pci_get_word(d->config + PCI_STATUS); status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(s->dev.config + PCI_STATUS, status); + pci_set_word(d->config + PCI_STATUS, status); } static uint32_t bonito_spciconf_readb(void *opaque, target_phys_addr_t addr) { PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); + PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); uint32_t pciaddr; uint16_t status; @@ -524,24 +547,26 @@ static uint32_t bonito_spciconf_readb(void *opaque, target_phys_addr_t addr) } /* set the pci address in s->config_reg */ - s->pcihost->config_reg = (pciaddr) | (1u << 31); + phb->config_reg = (pciaddr) | (1u << 31); /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(s->dev.config + PCI_STATUS); + status = pci_get_word(d->config + PCI_STATUS); status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(s->dev.config + PCI_STATUS, status); + pci_set_word(d->config + PCI_STATUS, status); - return pci_data_read(s->pcihost->bus, s->pcihost->config_reg, 1); + return pci_data_read(phb->bus, phb->config_reg, 1); } static uint32_t bonito_spciconf_readw(void *opaque, target_phys_addr_t addr) { PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); + PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); uint32_t pciaddr; uint16_t status; DPRINTF("bonito_spciconf_readw "TARGET_FMT_plx"\n", addr); - assert((addr&0x1)==0); + assert((addr & 0x1) == 0); pciaddr = bonito_sbridge_pciaddr(s, addr); @@ -550,24 +575,26 @@ static uint32_t bonito_spciconf_readw(void *opaque, target_phys_addr_t addr) } /* set the pci address in s->config_reg */ - s->pcihost->config_reg = (pciaddr) | (1u << 31); + phb->config_reg = (pciaddr) | (1u << 31); /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(s->dev.config + PCI_STATUS); + status = pci_get_word(d->config + PCI_STATUS); status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(s->dev.config + PCI_STATUS, status); + pci_set_word(d->config + PCI_STATUS, status); - return pci_data_read(s->pcihost->bus, s->pcihost->config_reg, 2); + return pci_data_read(phb->bus, phb->config_reg, 2); } static uint32_t bonito_spciconf_readl(void *opaque, target_phys_addr_t addr) { PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); + PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); uint32_t pciaddr; uint16_t status; DPRINTF("bonito_spciconf_readl "TARGET_FMT_plx"\n", addr); - assert((addr&0x3) == 0); + assert((addr & 0x3) == 0); pciaddr = bonito_sbridge_pciaddr(s, addr); @@ -576,14 +603,14 @@ static uint32_t bonito_spciconf_readl(void *opaque, target_phys_addr_t addr) } /* set the pci address in s->config_reg */ - s->pcihost->config_reg = (pciaddr) | (1u << 31); + phb->config_reg = (pciaddr) | (1u << 31); /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(s->dev.config + PCI_STATUS); + status = pci_get_word(d->config + PCI_STATUS); status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(s->dev.config + PCI_STATUS, status); + pci_set_word(d->config + PCI_STATUS, status); - return pci_data_read(s->pcihost->bus, s->pcihost->config_reg, 4); + return pci_data_read(phb->bus, phb->config_reg, 4); } /* south bridge PCI configure space. 0x1fe8 0000 - 0x1fef ffff */ @@ -607,13 +634,15 @@ static const MemoryRegionOps bonito_spciconf_ops = { static void pci_bonito_set_irq(void *opaque, int irq_num, int level) { - qemu_irq *pic = opaque; + BonitoState *s = opaque; + qemu_irq *pic = s->pic; + PCIBonitoState *bonito_state = s->pci_dev; int internal_irq = irq_num - BONITO_IRQ_BASE; - if (bonito_state->regs[BONITO_INTEDGE] & (1<regs[BONITO_INTEDGE] & (1 << internal_irq)) { qemu_irq_pulse(*pic); } else { /* level triggered */ - if (bonito_state->regs[BONITO_INTPOL] & (1<regs[BONITO_INTPOL] & (1 << internal_irq)) { qemu_irq_raise(*pic); } else { qemu_irq_lower(*pic); @@ -673,13 +702,21 @@ static const VMStateDescription vmstate_bonito = { static int bonito_pcihost_initfn(SysBusDevice *dev) { + PCIHostState *phb = FROM_SYSBUS(PCIHostState, dev); + + phb->bus = pci_register_bus(DEVICE(dev), "pci", + pci_bonito_set_irq, pci_bonito_map_irq, dev, + get_system_memory(), get_system_io(), + 0x28, 32); + return 0; } static int bonito_initfn(PCIDevice *dev) { PCIBonitoState *s = DO_UPCAST(PCIBonitoState, dev, dev); - SysBusDevice *sysbus = &s->pcihost->busdev; + SysBusDevice *sysbus = SYS_BUS_DEVICE(s->pcihost); + PCIHostState *phb = FROM_SYSBUS(PCIHostState, sysbus); /* Bonito North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined" */ pci_config_set_prog_interface(dev->config, 0x00); @@ -691,15 +728,15 @@ static int bonito_initfn(PCIDevice *dev) sysbus_mmio_map(sysbus, 0, BONITO_INTERNAL_REG_BASE); /* set the north bridge pci configure mapping */ - memory_region_init_io(&s->pcihost->conf_mem, &bonito_pciconf_ops, s, + memory_region_init_io(&phb->conf_mem, &bonito_pciconf_ops, s, "north-bridge-pci-config", BONITO_PCICONFIG_SIZE); - sysbus_init_mmio(sysbus, &s->pcihost->conf_mem); + sysbus_init_mmio(sysbus, &phb->conf_mem); sysbus_mmio_map(sysbus, 1, BONITO_PCICONFIG_BASE); /* set the south bridge pci configure mapping */ - memory_region_init_io(&s->pcihost->data_mem, &bonito_spciconf_ops, s, + memory_region_init_io(&phb->data_mem, &bonito_spciconf_ops, s, "south-bridge-pci-config", BONITO_SPCICONFIG_SIZE); - sysbus_init_mmio(sysbus, &s->pcihost->data_mem); + sysbus_init_mmio(sysbus, &phb->data_mem); sysbus_mmio_map(sysbus, 2, BONITO_SPCICONFIG_BASE); memory_region_init_io(&s->iomem_ldma, &bonito_ldma_ops, s, @@ -742,28 +779,25 @@ static int bonito_initfn(PCIDevice *dev) PCIBus *bonito_init(qemu_irq *pic) { DeviceState *dev; - PCIBus *b; BonitoState *pcihost; + PCIHostState *phb; PCIBonitoState *s; PCIDevice *d; - dev = qdev_create(NULL, "Bonito-pcihost"); - pcihost = FROM_SYSBUS(BonitoState, sysbus_from_qdev(dev)); - b = pci_register_bus(&pcihost->busdev.qdev, "pci", pci_bonito_set_irq, - pci_bonito_map_irq, pic, get_system_memory(), - get_system_io(), - 0x28, 32); - pcihost->bus = b; + dev = qdev_create(NULL, TYPE_BONITO_PCI_HOST_BRIDGE); + phb = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev)); + pcihost = BONITO_PCI_HOST_BRIDGE(dev); + pcihost->pic = pic; qdev_init_nofail(dev); /* set the pcihost pointer before bonito_initfn is called */ - d = pci_create(b, PCI_DEVFN(0, 0), "Bonito"); + d = pci_create(phb->bus, PCI_DEVFN(0, 0), "Bonito"); s = DO_UPCAST(PCIBonitoState, dev, d); s->pcihost = pcihost; - bonito_state = s; - qdev_init_nofail(&d->qdev); + pcihost->pci_dev = s; + qdev_init_nofail(DEVICE(d)); - return b; + return phb->bus; } static void bonito_class_init(ObjectClass *klass, void *data) @@ -798,7 +832,7 @@ static void bonito_pcihost_class_init(ObjectClass *klass, void *data) } static const TypeInfo bonito_pcihost_info = { - .name = "Bonito-pcihost", + .name = TYPE_BONITO_PCI_HOST_BRIDGE, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(BonitoState), .class_init = bonito_pcihost_class_init, From ab6153673727cc1b88258675fa02113cf3271aa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 20 Aug 2012 19:07:59 +0200 Subject: [PATCH 0079/2270] dec_pci: QOM'ify DEC 21154 PCI-PCI bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce type constant. Introduce cast macro and drop dummy busdev field used with FROM_SYSBUS() that would've broken SYS_BUS_DEVICE(). Avoid accessing parent fields directly. Signed-off-by: Andreas Färber Acked-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- hw/dec_pci.c | 21 +++++++++++---------- hw/dec_pci.h | 2 ++ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/hw/dec_pci.c b/hw/dec_pci.c index 5194a9fc7d..19aed1b545 100644 --- a/hw/dec_pci.c +++ b/hw/dec_pci.c @@ -40,8 +40,9 @@ #define DEC_DPRINTF(fmt, ...) #endif +#define DEC_21154(obj) OBJECT_CHECK(DECState, (obj), TYPE_DEC_21154) + typedef struct DECState { - SysBusDevice busdev; PCIHostState host_state; } DECState; @@ -88,16 +89,16 @@ PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn) static int pci_dec_21154_device_init(SysBusDevice *dev) { - DECState *s; + PCIHostState *phb; - s = FROM_SYSBUS(DECState, dev); + phb = FROM_SYSBUS(PCIHostState, dev); - memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops, - &s->host_state, "pci-conf-idx", 0x1000); - memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops, - &s->host_state, "pci-data-idx", 0x1000); - sysbus_init_mmio(dev, &s->host_state.conf_mem); - sysbus_init_mmio(dev, &s->host_state.data_mem); + memory_region_init_io(&phb->conf_mem, &pci_host_conf_le_ops, + dev, "pci-conf-idx", 0x1000); + memory_region_init_io(&phb->data_mem, &pci_host_data_le_ops, + dev, "pci-data-idx", 0x1000); + sysbus_init_mmio(dev, &phb->conf_mem); + sysbus_init_mmio(dev, &phb->data_mem); return 0; } @@ -134,7 +135,7 @@ static void pci_dec_21154_device_class_init(ObjectClass *klass, void *data) } static const TypeInfo pci_dec_21154_device_info = { - .name = "dec-21154-sysbus", + .name = TYPE_DEC_21154, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(DECState), .class_init = pci_dec_21154_device_class_init, diff --git a/hw/dec_pci.h b/hw/dec_pci.h index 79264bac84..17dc0c2b0a 100644 --- a/hw/dec_pci.h +++ b/hw/dec_pci.h @@ -3,6 +3,8 @@ #include "qemu-common.h" +#define TYPE_DEC_21154 "dec-21154-sysbus" + PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn); #endif From 0e655047c5b394b54ffec6dddf37641b2aa5df55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 20 Aug 2012 19:08:00 +0200 Subject: [PATCH 0080/2270] grackle_pci: QOM'ify Grackle PCI host bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce type constant. Introduce cast macro to drop dummy busdev field used with FROM_SYSBUS() that would've broken SYS_BUS_DEVICE(). Avoid accessing parent fields directly. Drop no-op reset function. Signed-off-by: Andreas Färber Acked-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- hw/grackle_pci.c | 57 ++++++++++++++++++++++++------------------------ hw/ppc_mac.h | 1 + 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c index 35667ade0b..d8142708a1 100644 --- a/hw/grackle_pci.c +++ b/hw/grackle_pci.c @@ -23,10 +23,9 @@ * THE SOFTWARE. */ -#include "sysbus.h" +#include "pci_host.h" #include "ppc_mac.h" #include "pci.h" -#include "pci_host.h" /* debug Grackle */ //#define DEBUG_GRACKLE @@ -38,9 +37,12 @@ #define GRACKLE_DPRINTF(fmt, ...) #endif +#define GRACKLE_PCI_HOST_BRIDGE(obj) \ + OBJECT_CHECK(GrackleState, (obj), TYPE_GRACKLE_PCI_HOST_BRIDGE) + typedef struct GrackleState { - SysBusDevice busdev; PCIHostState host_state; + MemoryRegion pci_mmio; MemoryRegion pci_hole; } GrackleState; @@ -59,22 +61,20 @@ static void pci_grackle_set_irq(void *opaque, int irq_num, int level) qemu_set_irq(pic[irq_num + 0x15], level); } -static void pci_grackle_reset(void *opaque) -{ -} - PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic, MemoryRegion *address_space_mem, MemoryRegion *address_space_io) { DeviceState *dev; SysBusDevice *s; + PCIHostState *phb; GrackleState *d; - dev = qdev_create(NULL, "grackle-pcihost"); + dev = qdev_create(NULL, TYPE_GRACKLE_PCI_HOST_BRIDGE); qdev_init_nofail(dev); - s = sysbus_from_qdev(dev); - d = FROM_SYSBUS(GrackleState, s); + s = SYS_BUS_DEVICE(dev); + phb = FROM_SYSBUS(PCIHostState, s); + d = GRACKLE_PCI_HOST_BRIDGE(dev); memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL); memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio, @@ -82,36 +82,35 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic, memory_region_add_subregion(address_space_mem, 0x80000000ULL, &d->pci_hole); - d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci", - pci_grackle_set_irq, - pci_grackle_map_irq, - pic, - &d->pci_mmio, - address_space_io, - 0, 4); + phb->bus = pci_register_bus(dev, "pci", + pci_grackle_set_irq, + pci_grackle_map_irq, + pic, + &d->pci_mmio, + address_space_io, + 0, 4); - pci_create_simple(d->host_state.bus, 0, "grackle"); + pci_create_simple(phb->bus, 0, "grackle"); sysbus_mmio_map(s, 0, base); sysbus_mmio_map(s, 1, base + 0x00200000); - return d->host_state.bus; + return phb->bus; } static int pci_grackle_init_device(SysBusDevice *dev) { - GrackleState *s; + PCIHostState *phb; - s = FROM_SYSBUS(GrackleState, dev); + phb = FROM_SYSBUS(PCIHostState, dev); - memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops, - &s->host_state, "pci-conf-idx", 0x1000); - memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops, - &s->host_state, "pci-data-idx", 0x1000); - sysbus_init_mmio(dev, &s->host_state.conf_mem); - sysbus_init_mmio(dev, &s->host_state.data_mem); + memory_region_init_io(&phb->conf_mem, &pci_host_conf_le_ops, + dev, "pci-conf-idx", 0x1000); + memory_region_init_io(&phb->data_mem, &pci_host_data_le_ops, + dev, "pci-data-idx", 0x1000); + sysbus_init_mmio(dev, &phb->conf_mem); + sysbus_init_mmio(dev, &phb->data_mem); - qemu_register_reset(pci_grackle_reset, &s->host_state); return 0; } @@ -151,7 +150,7 @@ static void pci_grackle_class_init(ObjectClass *klass, void *data) } static const TypeInfo grackle_pci_host_info = { - .name = "grackle-pcihost", + .name = TYPE_GRACKLE_PCI_HOST_BRIDGE, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(GrackleState), .class_init = pci_grackle_class_init, diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h index af75e45cc2..7d084184fc 100644 --- a/hw/ppc_mac.h +++ b/hw/ppc_mac.h @@ -55,6 +55,7 @@ qemu_irq *heathrow_pic_init(MemoryRegion **pmem, int nb_cpus, qemu_irq **irqs); /* Grackle PCI */ +#define TYPE_GRACKLE_PCI_HOST_BRIDGE "grackle-pcihost" PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic, MemoryRegion *address_space_mem, MemoryRegion *address_space_io); From 8d43d7e591c2078cc64534b867365d46ad394d04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 20 Aug 2012 19:08:01 +0200 Subject: [PATCH 0081/2270] gt64xxx: QOM'ify GT64120 PCI host bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce type constant. Introduce cast macro to drop dummy busdev field used with FROM_SYSBUS() macro that would've broken SYS_BUS_DEVICE(). Avoid accessing DeviceState indirectly through PCIHostState. Signed-off-by: Andreas Färber Acked-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- hw/gt64xxx.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c index 04831bb07f..067729946e 100644 --- a/hw/gt64xxx.c +++ b/hw/gt64xxx.c @@ -229,9 +229,14 @@ target_phys_addr_t regname ##_length; \ MemoryRegion regname ##_mem +#define TYPE_GT64120_PCI_HOST_BRIDGE "gt64120" + +#define GT64120_PCI_HOST_BRIDGE(obj) \ + OBJECT_CHECK(GT64120State, (obj), TYPE_GT64120_PCI_HOST_BRIDGE) + typedef struct GT64120State { - SysBusDevice busdev; PCIHostState pci; + uint32_t regs[GT_REGS]; PCI_MAPPING_ENTRY(PCI0IO); PCI_MAPPING_ENTRY(ISD); @@ -1083,31 +1088,31 @@ static void gt64120_reset(void *opaque) PCIBus *gt64120_register(qemu_irq *pic) { - SysBusDevice *s; GT64120State *d; + PCIHostState *phb; DeviceState *dev; - dev = qdev_create(NULL, "gt64120"); + dev = qdev_create(NULL, TYPE_GT64120_PCI_HOST_BRIDGE); qdev_init_nofail(dev); - s = sysbus_from_qdev(dev); - d = FROM_SYSBUS(GT64120State, s); - d->pci.bus = pci_register_bus(&d->busdev.qdev, "pci", - gt64120_pci_set_irq, gt64120_pci_map_irq, - pic, - get_system_memory(), - get_system_io(), - PCI_DEVFN(18, 0), 4); + d = GT64120_PCI_HOST_BRIDGE(dev); + phb = &d->pci; + phb->bus = pci_register_bus(dev, "pci", + gt64120_pci_set_irq, gt64120_pci_map_irq, + pic, + get_system_memory(), + get_system_io(), + PCI_DEVFN(18, 0), 4); memory_region_init_io(&d->ISD_mem, &isd_mem_ops, d, "isd-mem", 0x1000); - pci_create_simple(d->pci.bus, PCI_DEVFN(0, 0), "gt64120_pci"); - return d->pci.bus; + pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "gt64120_pci"); + return phb->bus; } static int gt64120_init(SysBusDevice *dev) { GT64120State *s; - s = FROM_SYSBUS(GT64120State, dev); + s = GT64120_PCI_HOST_BRIDGE(dev); /* FIXME: This value is computed from registers during reset, but some devices (e.g. VGA card) need to know it when they are registered. @@ -1162,7 +1167,7 @@ static void gt64120_class_init(ObjectClass *klass, void *data) } static const TypeInfo gt64120_info = { - .name = "gt64120", + .name = TYPE_GT64120_PCI_HOST_BRIDGE, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(GT64120State), .class_init = gt64120_class_init, From 42c281a2832a67ee1d0cc08744c5b9ebb4f6b802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 20 Aug 2012 19:08:02 +0200 Subject: [PATCH 0082/2270] ppc4xx_pci: QOM'ify ppc4xx PCI host bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce type constant and cast macro. Avoid accessing its parent field directly. Signed-off-by: Andreas Färber Acked-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- hw/ppc440_bamboo.c | 3 ++- hw/ppc4xx.h | 2 ++ hw/ppc4xx_pci.c | 13 ++++++++----- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c index 0dd4dab318..c198071170 100644 --- a/hw/ppc440_bamboo.c +++ b/hw/ppc440_bamboo.c @@ -216,7 +216,8 @@ static void bamboo_init(ram_addr_t ram_size, ram_bases, ram_sizes, 1); /* PCI */ - dev = sysbus_create_varargs("ppc4xx-pcihost", PPC440EP_PCI_CONFIG, + dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE, + PPC440EP_PCI_CONFIG, pic[pci_irq_nrs[0]], pic[pci_irq_nrs[1]], pic[pci_irq_nrs[2]], pic[pci_irq_nrs[3]], NULL); diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h index b511020aeb..5cd78b6291 100644 --- a/hw/ppc4xx.h +++ b/hw/ppc4xx.h @@ -53,6 +53,8 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks, target_phys_addr_t *ram_sizes, int do_init); +#define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost" + PCIBus *ppc4xx_pci_init(CPUPPCState *env, qemu_irq pci_irqs[4], target_phys_addr_t config_space, target_phys_addr_t int_ack, diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c index 104ed98cb3..599a75a05b 100644 --- a/hw/ppc4xx_pci.c +++ b/hw/ppc4xx_pci.c @@ -45,6 +45,9 @@ struct PCITargetMap { uint32_t la; }; +#define PPC4xx_PCI_HOST_BRIDGE(obj) \ + OBJECT_CHECK(PPC4xxPCIState, (obj), TYPE_PPC4xx_PCI_HOST_BRIDGE) + #define PPC4xx_PCI_NR_PMMS 3 #define PPC4xx_PCI_NR_PTMS 2 @@ -335,17 +338,17 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev) PCIBus *b; int i; - h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev)); - s = DO_UPCAST(PPC4xxPCIState, pci_state, h); + h = FROM_SYSBUS(PCIHostState, dev); + s = PPC4xx_PCI_HOST_BRIDGE(dev); for (i = 0; i < ARRAY_SIZE(s->irq); i++) { sysbus_init_irq(dev, &s->irq[i]); } - b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, ppc4xx_pci_set_irq, + b = pci_register_bus(DEVICE(dev), NULL, ppc4xx_pci_set_irq, ppc4xx_pci_map_irq, s->irq, get_system_memory(), get_system_io(), 0, 4); - s->pci_state.bus = b; + h->bus = b; pci_create_simple(b, 0, "ppc4xx-host-bridge"); @@ -394,7 +397,7 @@ static void ppc4xx_pcihost_class_init(ObjectClass *klass, void *data) } static const TypeInfo ppc4xx_pcihost_info = { - .name = "ppc4xx-pcihost", + .name = TYPE_PPC4xx_PCI_HOST_BRIDGE, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(PPC4xxPCIState), .class_init = ppc4xx_pcihost_class_init, From 9c1a61f0e583a0ae3f601465ffa22da5954c9bfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 20 Aug 2012 19:08:03 +0200 Subject: [PATCH 0083/2270] ppce500_pci: QOM'ify e500 PCI host bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce type constant and cast macro. Avoid accessing parent fields directly. Signed-off-by: Andreas Färber Acked-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- hw/ppce500_pci.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 99748b311f..e4f065a496 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -72,8 +72,14 @@ struct pci_inbound { uint32_t piwar; }; +#define TYPE_PPC_E500_PCI_HOST_BRIDGE "e500-pcihost" + +#define PPC_E500_PCI_HOST_BRIDGE(obj) \ + OBJECT_CHECK(PPCE500PCIState, (obj), TYPE_PPC_E500_PCI_HOST_BRIDGE) + struct PPCE500PCIState { PCIHostState pci_state; + struct pci_outbound pob[PPCE500_PCI_NR_POBS]; struct pci_inbound pib[PPCE500_PCI_NR_PIBS]; uint32_t gasket_time; @@ -310,17 +316,17 @@ static int e500_pcihost_initfn(SysBusDevice *dev) MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *address_space_io = get_system_io(); - h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev)); - s = DO_UPCAST(PPCE500PCIState, pci_state, h); + h = FROM_SYSBUS(PCIHostState, dev); + s = PPC_E500_PCI_HOST_BRIDGE(dev); for (i = 0; i < ARRAY_SIZE(s->irq); i++) { sysbus_init_irq(dev, &s->irq[i]); } - b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq, + b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq, mpc85xx_pci_map_irq, s->irq, address_space_mem, address_space_io, PCI_DEVFN(0x11, 0), 4); - s->pci_state.bus = b; + h->bus = b; pci_create_simple(b, 0, "e500-host-bridge"); @@ -367,7 +373,7 @@ static void e500_pcihost_class_init(ObjectClass *klass, void *data) } static const TypeInfo e500_pcihost_info = { - .name = "e500-pcihost", + .name = TYPE_PPC_E500_PCI_HOST_BRIDGE, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(PPCE500PCIState), .class_init = e500_pcihost_class_init, From 03a6b667702b0af0e7b36754489aed6aa82d30a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 20 Aug 2012 19:08:04 +0200 Subject: [PATCH 0084/2270] prep_pci: QOM'ify Raven PCI host bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce type constant and cast macro. Avoid accessing parent fields directly. Also add missing space and braces. Signed-off-by: Andreas Färber Acked-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- hw/prep_pci.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/hw/prep_pci.c b/hw/prep_pci.c index a8cdc21bb4..69c19dfded 100644 --- a/hw/prep_pci.c +++ b/hw/prep_pci.c @@ -28,8 +28,14 @@ #include "pc.h" #include "exec-memory.h" +#define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost" + +#define RAVEN_PCI_HOST_BRIDGE(obj) \ + OBJECT_CHECK(PREPPCIState, (obj), TYPE_RAVEN_PCI_HOST_BRIDGE) + typedef struct PRePPCIState { PCIHostState host_state; + MemoryRegion intack; qemu_irq irq[4]; } PREPPCIState; @@ -42,9 +48,10 @@ static inline uint32_t PPC_PCIIO_config(target_phys_addr_t addr) { int i; - for(i = 0; i < 11; i++) { - if ((addr & (1 << (11 + i))) != 0) + for (i = 0; i < 11; i++) { + if ((addr & (1 << (11 + i))) != 0) { break; + } } return (addr & 0x7ff) | (i << 11); } @@ -97,7 +104,7 @@ static void prep_set_irq(void *opaque, int irq_num, int level) static int raven_pcihost_init(SysBusDevice *dev) { PCIHostState *h = FROM_SYSBUS(PCIHostState, dev); - PREPPCIState *s = DO_UPCAST(PREPPCIState, host_state, h); + PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(dev); MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *address_space_io = get_system_io(); PCIBus *bus; @@ -107,7 +114,7 @@ static int raven_pcihost_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq[i]); } - bus = pci_register_bus(&h->busdev.qdev, NULL, + bus = pci_register_bus(DEVICE(dev), NULL, prep_set_irq, prep_map_irq, s->irq, address_space_mem, address_space_io, 0, 4); h->bus = bus; @@ -184,7 +191,7 @@ static void raven_pcihost_class_init(ObjectClass *klass, void *data) } static const TypeInfo raven_pcihost_info = { - .name = "raven-pcihost", + .name = TYPE_RAVEN_PCI_HOST_BRIDGE, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(PREPPCIState), .class_init = raven_pcihost_class_init, From 8c9f64df3dd76c253e4961c5d2f075bffcc29e1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 20 Aug 2012 19:08:05 +0200 Subject: [PATCH 0085/2270] spapr_pci: QOM'ify sPAPR PCI host bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce type constant. Introduce cast macro to drop bogus busdev field that would've broken SYS_BUS_DEVICE(). Avoid accessing parent fields directly. Free the identifier phb as acronym for PCI_HOST_BRIDGE. Updated against conflicting merge from branch 'agraf/ppc-for-upstream' (0d16fdd732d1b211842fa96b7c90ddf9e6bde0e4), which removed busdev field differently, moved some code around and added new occurrences of 'phb'. Signed-off-by: Andreas Färber Signed-off-by: Anthony Liguori --- hw/spapr.c | 7 ++-- hw/spapr_pci.c | 90 ++++++++++++++++++++++++++------------------------ hw/spapr_pci.h | 5 +++ 3 files changed, 56 insertions(+), 46 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index be533ee934..f8b53e9c1e 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -612,6 +612,7 @@ static void ppc_spapr_init(ram_addr_t ram_size, { PowerPCCPU *cpu; CPUPPCState *env; + PCIHostState *phb; int i; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); @@ -742,6 +743,7 @@ static void ppc_spapr_init(ram_addr_t ram_size, SPAPR_PCI_MEM_WIN_SIZE, SPAPR_PCI_IO_WIN_ADDR, SPAPR_PCI_MSI_WIN_ADDR); + phb = &QLIST_FIRST(&spapr->phbs)->host_state; for (i = 0; i < nb_nics; i++) { NICInfo *nd = &nd_table[i]; @@ -762,13 +764,12 @@ static void ppc_spapr_init(ram_addr_t ram_size, } /* Graphics */ - if (spapr_vga_init(QLIST_FIRST(&spapr->phbs)->host_state.bus)) { + if (spapr_vga_init(phb->bus)) { spapr->has_graphics = true; } if (usb_enabled) { - pci_create_simple(QLIST_FIRST(&spapr->phbs)->host_state.bus, - -1, "pci-ohci"); + pci_create_simple(phb->bus, -1, "pci-ohci"); if (spapr->has_graphics) { usbdevice_create("keyboard"); usbdevice_create("mouse"); diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index c57ab1ee2b..f9dd2a8203 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -48,13 +48,13 @@ static sPAPRPHBState *find_phb(sPAPREnvironment *spapr, uint64_t buid) { - sPAPRPHBState *phb; + sPAPRPHBState *sphb; - QLIST_FOREACH(phb, &spapr->phbs, list) { - if (phb->buid != buid) { + QLIST_FOREACH(sphb, &spapr->phbs, list) { + if (sphb->buid != buid) { continue; } - return phb; + return sphb; } return NULL; @@ -63,7 +63,9 @@ static sPAPRPHBState *find_phb(sPAPREnvironment *spapr, uint64_t buid) static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid, uint32_t config_addr) { - sPAPRPHBState *phb = find_phb(spapr, buid); + sPAPRPHBState *sphb = find_phb(spapr, buid); + PCIHostState *phb = &sphb->host_state; + BusState *bus = BUS(phb->bus); BusChild *kid; int devfn = (config_addr >> 8) & 0xFF; @@ -71,7 +73,7 @@ static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid, return NULL; } - QTAILQ_FOREACH(kid, &phb->host_state.bus->qbus.children, sibling) { + QTAILQ_FOREACH(kid, &bus->children, sibling) { PCIDevice *dev = (PCIDevice *)kid->child; if (dev->devfn == devfn) { return dev; @@ -514,23 +516,24 @@ static DMAContext *spapr_pci_dma_context_fn(PCIBus *bus, void *opaque, static int spapr_phb_init(SysBusDevice *s) { - sPAPRPHBState *phb = DO_UPCAST(sPAPRPHBState, host_state.busdev, s); + sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s); + PCIHostState *phb = FROM_SYSBUS(PCIHostState, s); char *namebuf; int i; PCIBus *bus; - phb->dtbusname = g_strdup_printf("pci@%" PRIx64, phb->buid); - namebuf = alloca(strlen(phb->dtbusname) + 32); + sphb->dtbusname = g_strdup_printf("pci@%" PRIx64, sphb->buid); + namebuf = alloca(strlen(sphb->dtbusname) + 32); /* Initialize memory regions */ - sprintf(namebuf, "%s.mmio", phb->dtbusname); - memory_region_init(&phb->memspace, namebuf, INT64_MAX); + sprintf(namebuf, "%s.mmio", sphb->dtbusname); + memory_region_init(&sphb->memspace, namebuf, INT64_MAX); - sprintf(namebuf, "%s.mmio-alias", phb->dtbusname); - memory_region_init_alias(&phb->memwindow, namebuf, &phb->memspace, - SPAPR_PCI_MEM_WIN_BUS_OFFSET, phb->mem_win_size); - memory_region_add_subregion(get_system_memory(), phb->mem_win_addr, - &phb->memwindow); + sprintf(namebuf, "%s.mmio-alias", sphb->dtbusname); + memory_region_init_alias(&sphb->memwindow, namebuf, &sphb->memspace, + SPAPR_PCI_MEM_WIN_BUS_OFFSET, sphb->mem_win_size); + memory_region_add_subregion(get_system_memory(), sphb->mem_win_addr, + &sphb->memwindow); /* On ppc, we only have MMIO no specific IO space from the CPU * perspective. In theory we ought to be able to embed the PCI IO @@ -540,42 +543,42 @@ static int spapr_phb_init(SysBusDevice *s) * system io address space. This hack to bounce things via * system_io works around the problem until all the users of * old_portion are updated */ - sprintf(namebuf, "%s.io", phb->dtbusname); - memory_region_init(&phb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE); + sprintf(namebuf, "%s.io", sphb->dtbusname); + memory_region_init(&sphb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE); /* FIXME: fix to support multiple PHBs */ - memory_region_add_subregion(get_system_io(), 0, &phb->iospace); + memory_region_add_subregion(get_system_io(), 0, &sphb->iospace); - sprintf(namebuf, "%s.io-alias", phb->dtbusname); - memory_region_init_io(&phb->iowindow, &spapr_io_ops, phb, + sprintf(namebuf, "%s.io-alias", sphb->dtbusname); + memory_region_init_io(&sphb->iowindow, &spapr_io_ops, sphb, namebuf, SPAPR_PCI_IO_WIN_SIZE); - memory_region_add_subregion(get_system_memory(), phb->io_win_addr, - &phb->iowindow); + memory_region_add_subregion(get_system_memory(), sphb->io_win_addr, + &sphb->iowindow); /* As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors, * we need to allocate some memory to catch those writes coming * from msi_notify()/msix_notify() */ if (msi_supported) { - sprintf(namebuf, "%s.msi", phb->dtbusname); - memory_region_init_io(&phb->msiwindow, &spapr_msi_ops, phb, + sprintf(namebuf, "%s.msi", sphb->dtbusname); + memory_region_init_io(&sphb->msiwindow, &spapr_msi_ops, sphb, namebuf, SPAPR_MSIX_MAX_DEVS * 0x10000); - memory_region_add_subregion(get_system_memory(), phb->msi_win_addr, - &phb->msiwindow); + memory_region_add_subregion(get_system_memory(), sphb->msi_win_addr, + &sphb->msiwindow); } - bus = pci_register_bus(&phb->host_state.busdev.qdev, - phb->busname ? phb->busname : phb->dtbusname, - pci_spapr_set_irq, pci_spapr_map_irq, phb, - &phb->memspace, &phb->iospace, + bus = pci_register_bus(DEVICE(s), + sphb->busname ? sphb->busname : sphb->dtbusname, + pci_spapr_set_irq, pci_spapr_map_irq, sphb, + &sphb->memspace, &sphb->iospace, PCI_DEVFN(0, 0), PCI_NUM_PINS); - phb->host_state.bus = bus; + phb->bus = bus; - phb->dma_liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16); - phb->dma_window_start = 0; - phb->dma_window_size = 0x40000000; - phb->dma = spapr_tce_new_dma_context(phb->dma_liobn, phb->dma_window_size); - pci_setup_iommu(bus, spapr_pci_dma_context_fn, phb); + sphb->dma_liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16); + sphb->dma_window_start = 0; + sphb->dma_window_size = 0x40000000; + sphb->dma = spapr_tce_new_dma_context(sphb->dma_liobn, sphb->dma_window_size); + pci_setup_iommu(bus, spapr_pci_dma_context_fn, sphb); - QLIST_INSERT_HEAD(&spapr->phbs, phb, list); + QLIST_INSERT_HEAD(&spapr->phbs, sphb, list); /* Initialize the LSI table */ for (i = 0; i < PCI_NUM_PINS; i++) { @@ -586,7 +589,7 @@ static int spapr_phb_init(SysBusDevice *s) return -1; } - phb->lsi_table[i].irq = irq; + sphb->lsi_table[i].irq = irq; } return 0; @@ -613,7 +616,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data) } static const TypeInfo spapr_phb_info = { - .name = "spapr-pci-host-bridge", + .name = TYPE_SPAPR_PCI_HOST_BRIDGE, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(sPAPRPHBState), .class_init = spapr_phb_class_init, @@ -626,7 +629,7 @@ void spapr_create_phb(sPAPREnvironment *spapr, { DeviceState *dev; - dev = qdev_create(NULL, spapr_phb_info.name); + dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE); if (busname) { qdev_prop_set_string(dev, "busname", g_strdup(busname)); @@ -750,8 +753,9 @@ void spapr_pci_rtas_init(void) } } -static void register_types(void) +static void spapr_pci_register_types(void) { type_register_static(&spapr_phb_info); } -type_init(register_types) + +type_init(spapr_pci_register_types) diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index 7518899b85..4140ee67af 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -29,6 +29,11 @@ #define SPAPR_MSIX_MAX_DEVS 32 +#define TYPE_SPAPR_PCI_HOST_BRIDGE "spapr-pci-host-bridge" + +#define SPAPR_PCI_HOST_BRIDGE(obj) \ + OBJECT_CHECK(sPAPRPHBState, (obj), TYPE_SPAPR_PCI_HOST_BRIDGE) + typedef struct sPAPRPHBState { PCIHostState host_state; From 57fd7b7fce9098cdac58a8442033cb91412400b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 20 Aug 2012 19:08:06 +0200 Subject: [PATCH 0086/2270] unin_pci: QOM'ify UniNorth PCI host bridges MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce type constants and cast macros. Avoid accessing parent fields directly. Signed-off-by: Andreas Färber Acked-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- hw/unin_pci.c | 133 ++++++++++++++++++++++++++------------------------ 1 file changed, 70 insertions(+), 63 deletions(-) diff --git a/hw/unin_pci.c b/hw/unin_pci.c index 2b309dfe82..1fc8920ab0 100644 --- a/hw/unin_pci.c +++ b/hw/unin_pci.c @@ -38,8 +38,23 @@ static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e }; +#define TYPE_UNI_NORTH_PCI_HOST_BRIDGE "uni-north-pci-pcihost" +#define TYPE_UNI_NORTH_AGP_HOST_BRIDGE "uni-north-agp-pcihost" +#define TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE "uni-north-internal-pci-pcihost" +#define TYPE_U3_AGP_HOST_BRIDGE "u3-agp-pcihost" + +#define UNI_NORTH_PCI_HOST_BRIDGE(obj) \ + OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_PCI_HOST_BRIDGE) +#define UNI_NORTH_AGP_HOST_BRIDGE(obj) \ + OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_AGP_HOST_BRIDGE) +#define UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(obj) \ + OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE) +#define U3_AGP_HOST_BRIDGE(obj) \ + OBJECT_CHECK(UNINState, (obj), TYPE_U3_AGP_HOST_BRIDGE) + typedef struct UNINState { PCIHostState host_state; + MemoryRegion pci_mmio; MemoryRegion pci_hole; } UNINState; @@ -130,19 +145,17 @@ static const MemoryRegionOps unin_data_ops = { static int pci_unin_main_init_device(SysBusDevice *dev) { PCIHostState *h; - UNINState *s; /* Use values found on a real PowerMac */ /* Uninorth main bus */ h = FROM_SYSBUS(PCIHostState, dev); - s = DO_UPCAST(UNINState, host_state, h); - memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops, - &s->host_state, "pci-conf-idx", 0x1000); - memory_region_init_io(&s->host_state.data_mem, &unin_data_ops, s, + memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, + dev, "pci-conf-idx", 0x1000); + memory_region_init_io(&h->data_mem, &unin_data_ops, dev, "pci-conf-data", 0x1000); - sysbus_init_mmio(dev, &s->host_state.conf_mem); - sysbus_init_mmio(dev, &s->host_state.data_mem); + sysbus_init_mmio(dev, &h->conf_mem); + sysbus_init_mmio(dev, &h->data_mem); return 0; } @@ -151,18 +164,16 @@ static int pci_unin_main_init_device(SysBusDevice *dev) static int pci_u3_agp_init_device(SysBusDevice *dev) { PCIHostState *h; - UNINState *s; /* Uninorth U3 AGP bus */ h = FROM_SYSBUS(PCIHostState, dev); - s = DO_UPCAST(UNINState, host_state, h); - memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops, - &s->host_state, "pci-conf-idx", 0x1000); - memory_region_init_io(&s->host_state.data_mem, &unin_data_ops, s, + memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, + dev, "pci-conf-idx", 0x1000); + memory_region_init_io(&h->data_mem, &unin_data_ops, dev, "pci-conf-data", 0x1000); - sysbus_init_mmio(dev, &s->host_state.conf_mem); - sysbus_init_mmio(dev, &s->host_state.data_mem); + sysbus_init_mmio(dev, &h->conf_mem); + sysbus_init_mmio(dev, &h->data_mem); return 0; } @@ -170,36 +181,32 @@ static int pci_u3_agp_init_device(SysBusDevice *dev) static int pci_unin_agp_init_device(SysBusDevice *dev) { PCIHostState *h; - UNINState *s; /* Uninorth AGP bus */ h = FROM_SYSBUS(PCIHostState, dev); - s = DO_UPCAST(UNINState, host_state, h); - memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops, - &s->host_state, "pci-conf-idx", 0x1000); - memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops, - &s->host_state, "pci-conf-data", 0x1000); - sysbus_init_mmio(dev, &s->host_state.conf_mem); - sysbus_init_mmio(dev, &s->host_state.data_mem); + memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, + dev, "pci-conf-idx", 0x1000); + memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, + dev, "pci-conf-data", 0x1000); + sysbus_init_mmio(dev, &h->conf_mem); + sysbus_init_mmio(dev, &h->data_mem); return 0; } static int pci_unin_internal_init_device(SysBusDevice *dev) { PCIHostState *h; - UNINState *s; /* Uninorth internal bus */ h = FROM_SYSBUS(PCIHostState, dev); - s = DO_UPCAST(UNINState, host_state, h); - memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops, - &s->host_state, "pci-conf-idx", 0x1000); - memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops, - &s->host_state, "pci-conf-data", 0x1000); - sysbus_init_mmio(dev, &s->host_state.conf_mem); - sysbus_init_mmio(dev, &s->host_state.data_mem); + memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, + dev, "pci-conf-idx", 0x1000); + memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, + dev, "pci-conf-data", 0x1000); + sysbus_init_mmio(dev, &h->conf_mem); + sysbus_init_mmio(dev, &h->data_mem); return 0; } @@ -214,26 +221,26 @@ PCIBus *pci_pmac_init(qemu_irq *pic, /* Use values found on a real PowerMac */ /* Uninorth main bus */ - dev = qdev_create(NULL, "uni-north-pci-pcihost"); + dev = qdev_create(NULL, TYPE_UNI_NORTH_PCI_HOST_BRIDGE); qdev_init_nofail(dev); - s = sysbus_from_qdev(dev); + s = SYS_BUS_DEVICE(dev); h = FROM_SYSBUS(PCIHostState, s); - d = DO_UPCAST(UNINState, host_state, h); + d = UNI_NORTH_PCI_HOST_BRIDGE(dev); memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL); memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio, 0x80000000ULL, 0x70000000ULL); memory_region_add_subregion(address_space_mem, 0x80000000ULL, &d->pci_hole); - d->host_state.bus = pci_register_bus(dev, "pci", - pci_unin_set_irq, pci_unin_map_irq, - pic, - &d->pci_mmio, - address_space_io, - PCI_DEVFN(11, 0), 4); + h->bus = pci_register_bus(dev, "pci", + pci_unin_set_irq, pci_unin_map_irq, + pic, + &d->pci_mmio, + address_space_io, + PCI_DEVFN(11, 0), 4); #if 0 - pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north"); + pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north"); #endif sysbus_mmio_map(s, 0, 0xf2800000); @@ -242,30 +249,30 @@ PCIBus *pci_pmac_init(qemu_irq *pic, /* DEC 21154 bridge */ #if 0 /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */ - pci_create_simple(d->host_state.bus, PCI_DEVFN(12, 0), "dec-21154"); + pci_create_simple(h->bus, PCI_DEVFN(12, 0), "dec-21154"); #endif /* Uninorth AGP bus */ - pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north-agp"); - dev = qdev_create(NULL, "uni-north-agp-pcihost"); + pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-agp"); + dev = qdev_create(NULL, TYPE_UNI_NORTH_AGP_HOST_BRIDGE); qdev_init_nofail(dev); - s = sysbus_from_qdev(dev); + s = SYS_BUS_DEVICE(dev); sysbus_mmio_map(s, 0, 0xf0800000); sysbus_mmio_map(s, 1, 0xf0c00000); /* Uninorth internal bus */ #if 0 /* XXX: not needed for now */ - pci_create_simple(d->host_state.bus, PCI_DEVFN(14, 0), + pci_create_simple(h->bus, PCI_DEVFN(14, 0), "uni-north-internal-pci"); - dev = qdev_create(NULL, "uni-north-internal-pci-pcihost"); + dev = qdev_create(NULL, TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE); qdev_init_nofail(dev); - s = sysbus_from_qdev(dev); + s = SYS_BUS_DEVICE(dev); sysbus_mmio_map(s, 0, 0xf4800000); sysbus_mmio_map(s, 1, 0xf4c00000); #endif - return d->host_state.bus; + return h->bus; } PCIBus *pci_pmac_u3_init(qemu_irq *pic, @@ -279,11 +286,11 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic, /* Uninorth AGP bus */ - dev = qdev_create(NULL, "u3-agp-pcihost"); + dev = qdev_create(NULL, TYPE_U3_AGP_HOST_BRIDGE); qdev_init_nofail(dev); - s = sysbus_from_qdev(dev); + s = SYS_BUS_DEVICE(dev); h = FROM_SYSBUS(PCIHostState, s); - d = DO_UPCAST(UNINState, host_state, h); + d = U3_AGP_HOST_BRIDGE(dev); memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL); memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio, @@ -291,19 +298,19 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic, memory_region_add_subregion(address_space_mem, 0x80000000ULL, &d->pci_hole); - d->host_state.bus = pci_register_bus(dev, "pci", - pci_unin_set_irq, pci_unin_map_irq, - pic, - &d->pci_mmio, - address_space_io, - PCI_DEVFN(11, 0), 4); + h->bus = pci_register_bus(dev, "pci", + pci_unin_set_irq, pci_unin_map_irq, + pic, + &d->pci_mmio, + address_space_io, + PCI_DEVFN(11, 0), 4); sysbus_mmio_map(s, 0, 0xf0800000); sysbus_mmio_map(s, 1, 0xf0c00000); - pci_create_simple(d->host_state.bus, 11 << 3, "u3-agp"); + pci_create_simple(h->bus, 11 << 3, "u3-agp"); - return d->host_state.bus; + return h->bus; } static int unin_main_pci_host_init(PCIDevice *d) @@ -419,7 +426,7 @@ static void pci_unin_main_class_init(ObjectClass *klass, void *data) } static const TypeInfo pci_unin_main_info = { - .name = "uni-north-pci-pcihost", + .name = TYPE_UNI_NORTH_PCI_HOST_BRIDGE, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(UNINState), .class_init = pci_unin_main_class_init, @@ -433,7 +440,7 @@ static void pci_u3_agp_class_init(ObjectClass *klass, void *data) } static const TypeInfo pci_u3_agp_info = { - .name = "u3-agp-pcihost", + .name = TYPE_U3_AGP_HOST_BRIDGE, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(UNINState), .class_init = pci_u3_agp_class_init, @@ -447,7 +454,7 @@ static void pci_unin_agp_class_init(ObjectClass *klass, void *data) } static const TypeInfo pci_unin_agp_info = { - .name = "uni-north-agp-pcihost", + .name = TYPE_UNI_NORTH_AGP_HOST_BRIDGE, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(UNINState), .class_init = pci_unin_agp_class_init, @@ -461,7 +468,7 @@ static void pci_unin_internal_class_init(ObjectClass *klass, void *data) } static const TypeInfo pci_unin_internal_info = { - .name = "uni-north-internal-pci-pcihost", + .name = TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(UNINState), .class_init = pci_unin_internal_class_init, From b44ff9d430c5f2b51872f542d9562a15f0061a82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 20 Aug 2012 19:08:07 +0200 Subject: [PATCH 0087/2270] pci_host: Turn into SysBus-derived QOM type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The preceding commits fixed misuses of FROM_SYSBUS() that led people to add a bogus busdev field. For qdev the field order was less relevant but for QOM the PCIHostState field (including the SysBusDevice actually initialized with a value) must be placed first within the state struct. To facilitate accessing the PCIHostState fields, derive all PCI host bridges from TYPE_PCI_HOST_BRIDGE rather than TYPE_SYS_BUS_DEVICE. We can now access PCIHostState QOM-style, with PCI_HOST_BRIDGE() macro. Signed-off-by: Anthony Liguori Signed-off-by: Wanpeng Li Signed-off-by: Andreas Färber Signed-off-by: Andreas Färber Acked-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- hw/pci_host.c | 12 ++++++++++++ hw/pci_host.h | 5 +++++ 2 files changed, 17 insertions(+) diff --git a/hw/pci_host.c b/hw/pci_host.c index 804177891a..3950e943c0 100644 --- a/hw/pci_host.c +++ b/hw/pci_host.c @@ -165,4 +165,16 @@ const MemoryRegionOps pci_host_data_be_ops = { .endianness = DEVICE_BIG_ENDIAN, }; +static const TypeInfo pci_host_type_info = { + .name = TYPE_PCI_HOST_BRIDGE, + .parent = TYPE_SYS_BUS_DEVICE, + .abstract = true, + .instance_size = sizeof(PCIHostState), +}; +static void pci_host_register_types(void) +{ + type_register_static(&pci_host_type_info); +} + +type_init(pci_host_register_types) diff --git a/hw/pci_host.h b/hw/pci_host.h index 359e38f63b..4b9c300fcf 100644 --- a/hw/pci_host.h +++ b/hw/pci_host.h @@ -30,8 +30,13 @@ #include "sysbus.h" +#define TYPE_PCI_HOST_BRIDGE "pci-host-bridge" +#define PCI_HOST_BRIDGE(obj) \ + OBJECT_CHECK(PCIHostState, (obj), TYPE_PCI_HOST_BRIDGE) + struct PCIHostState { SysBusDevice busdev; + MemoryRegion conf_mem; MemoryRegion data_mem; MemoryRegion mmcfg; From 8558d942b665a9ff0847851615e107308f6386a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 20 Aug 2012 19:08:08 +0200 Subject: [PATCH 0088/2270] pci: Derive PCI host bridges from TYPE_PCI_HOST_BRIDGE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use PCIHostState and PCI_HOST_BRIDGE() where appropriate. Signed-off-by: Andreas Färber Signed-off-by: Anthony Liguori --- hw/alpha_typhoon.c | 4 ++-- hw/bonito.c | 22 +++++++++++----------- hw/dec_pci.c | 4 ++-- hw/grackle_pci.c | 6 +++--- hw/gt64xxx.c | 4 ++-- hw/piix_pci.c | 8 ++++---- hw/ppc4xx_pci.c | 4 ++-- hw/ppc_prep.c | 4 +--- hw/ppce500_pci.c | 4 ++-- hw/prep_pci.c | 4 ++-- hw/spapr.c | 2 +- hw/spapr_pci.c | 6 +++--- hw/unin_pci.c | 20 ++++++++++---------- 13 files changed, 45 insertions(+), 47 deletions(-) diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c index 10e588af9d..7667412adb 100644 --- a/hw/alpha_typhoon.c +++ b/hw/alpha_typhoon.c @@ -715,7 +715,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, qdev_init_nofail(dev); s = TYPHOON_PCI_HOST_BRIDGE(dev); - phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(dev)); + phb = PCI_HOST_BRIDGE(dev); /* Remember the CPUs so that we can deliver interrupts to them. */ for (i = 0; i < 4; i++) { @@ -825,7 +825,7 @@ static void typhoon_pcihost_class_init(ObjectClass *klass, void *data) static const TypeInfo typhoon_pcihost_info = { .name = TYPE_TYPHOON_PCI_HOST_BRIDGE, - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(TyphoonState), .class_init = typhoon_pcihost_class_init, }; diff --git a/hw/bonito.c b/hw/bonito.c index 062c701161..6084ac48fa 100644 --- a/hw/bonito.c +++ b/hw/bonito.c @@ -416,7 +416,7 @@ static const MemoryRegionOps bonito_cop_ops = { static uint32_t bonito_sbridge_pciaddr(void *opaque, target_phys_addr_t addr) { PCIBonitoState *s = opaque; - PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); + PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); uint32_t cfgaddr; uint32_t idsel; uint32_t devno; @@ -454,7 +454,7 @@ static void bonito_spciconf_writeb(void *opaque, target_phys_addr_t addr, { PCIBonitoState *s = opaque; PCIDevice *d = PCI_DEVICE(s); - PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); + PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); uint32_t pciaddr; uint16_t status; @@ -480,7 +480,7 @@ static void bonito_spciconf_writew(void *opaque, target_phys_addr_t addr, { PCIBonitoState *s = opaque; PCIDevice *d = PCI_DEVICE(s); - PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); + PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); uint32_t pciaddr; uint16_t status; @@ -508,7 +508,7 @@ static void bonito_spciconf_writel(void *opaque, target_phys_addr_t addr, { PCIBonitoState *s = opaque; PCIDevice *d = PCI_DEVICE(s); - PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); + PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); uint32_t pciaddr; uint16_t status; @@ -535,7 +535,7 @@ static uint32_t bonito_spciconf_readb(void *opaque, target_phys_addr_t addr) { PCIBonitoState *s = opaque; PCIDevice *d = PCI_DEVICE(s); - PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); + PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); uint32_t pciaddr; uint16_t status; @@ -561,7 +561,7 @@ static uint32_t bonito_spciconf_readw(void *opaque, target_phys_addr_t addr) { PCIBonitoState *s = opaque; PCIDevice *d = PCI_DEVICE(s); - PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); + PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); uint32_t pciaddr; uint16_t status; @@ -589,7 +589,7 @@ static uint32_t bonito_spciconf_readl(void *opaque, target_phys_addr_t addr) { PCIBonitoState *s = opaque; PCIDevice *d = PCI_DEVICE(s); - PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); + PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); uint32_t pciaddr; uint16_t status; @@ -702,7 +702,7 @@ static const VMStateDescription vmstate_bonito = { static int bonito_pcihost_initfn(SysBusDevice *dev) { - PCIHostState *phb = FROM_SYSBUS(PCIHostState, dev); + PCIHostState *phb = PCI_HOST_BRIDGE(dev); phb->bus = pci_register_bus(DEVICE(dev), "pci", pci_bonito_set_irq, pci_bonito_map_irq, dev, @@ -716,7 +716,7 @@ static int bonito_initfn(PCIDevice *dev) { PCIBonitoState *s = DO_UPCAST(PCIBonitoState, dev, dev); SysBusDevice *sysbus = SYS_BUS_DEVICE(s->pcihost); - PCIHostState *phb = FROM_SYSBUS(PCIHostState, sysbus); + PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); /* Bonito North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined" */ pci_config_set_prog_interface(dev->config, 0x00); @@ -785,7 +785,7 @@ PCIBus *bonito_init(qemu_irq *pic) PCIDevice *d; dev = qdev_create(NULL, TYPE_BONITO_PCI_HOST_BRIDGE); - phb = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev)); + phb = PCI_HOST_BRIDGE(dev); pcihost = BONITO_PCI_HOST_BRIDGE(dev); pcihost->pic = pic; qdev_init_nofail(dev); @@ -833,7 +833,7 @@ static void bonito_pcihost_class_init(ObjectClass *klass, void *data) static const TypeInfo bonito_pcihost_info = { .name = TYPE_BONITO_PCI_HOST_BRIDGE, - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(BonitoState), .class_init = bonito_pcihost_class_init, }; diff --git a/hw/dec_pci.c b/hw/dec_pci.c index 19aed1b545..de16361705 100644 --- a/hw/dec_pci.c +++ b/hw/dec_pci.c @@ -91,7 +91,7 @@ static int pci_dec_21154_device_init(SysBusDevice *dev) { PCIHostState *phb; - phb = FROM_SYSBUS(PCIHostState, dev); + phb = PCI_HOST_BRIDGE(dev); memory_region_init_io(&phb->conf_mem, &pci_host_conf_le_ops, dev, "pci-conf-idx", 0x1000); @@ -136,7 +136,7 @@ static void pci_dec_21154_device_class_init(ObjectClass *klass, void *data) static const TypeInfo pci_dec_21154_device_info = { .name = TYPE_DEC_21154, - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(DECState), .class_init = pci_dec_21154_device_class_init, }; diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c index d8142708a1..066f6e1900 100644 --- a/hw/grackle_pci.c +++ b/hw/grackle_pci.c @@ -73,7 +73,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic, dev = qdev_create(NULL, TYPE_GRACKLE_PCI_HOST_BRIDGE); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); - phb = FROM_SYSBUS(PCIHostState, s); + phb = PCI_HOST_BRIDGE(dev); d = GRACKLE_PCI_HOST_BRIDGE(dev); memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL); @@ -102,7 +102,7 @@ static int pci_grackle_init_device(SysBusDevice *dev) { PCIHostState *phb; - phb = FROM_SYSBUS(PCIHostState, dev); + phb = PCI_HOST_BRIDGE(dev); memory_region_init_io(&phb->conf_mem, &pci_host_conf_le_ops, dev, "pci-conf-idx", 0x1000); @@ -151,7 +151,7 @@ static void pci_grackle_class_init(ObjectClass *klass, void *data) static const TypeInfo grackle_pci_host_info = { .name = TYPE_GRACKLE_PCI_HOST_BRIDGE, - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(GrackleState), .class_init = pci_grackle_class_init, }; diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c index 067729946e..857758e23b 100644 --- a/hw/gt64xxx.c +++ b/hw/gt64xxx.c @@ -1095,7 +1095,7 @@ PCIBus *gt64120_register(qemu_irq *pic) dev = qdev_create(NULL, TYPE_GT64120_PCI_HOST_BRIDGE); qdev_init_nofail(dev); d = GT64120_PCI_HOST_BRIDGE(dev); - phb = &d->pci; + phb = PCI_HOST_BRIDGE(dev); phb->bus = pci_register_bus(dev, "pci", gt64120_pci_set_irq, gt64120_pci_map_irq, pic, @@ -1168,7 +1168,7 @@ static void gt64120_class_init(ObjectClass *klass, void *data) static const TypeInfo gt64120_info = { .name = TYPE_GT64120_PCI_HOST_BRIDGE, - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(GT64120State), .class_init = gt64120_class_init, }; diff --git a/hw/piix_pci.c b/hw/piix_pci.c index 0b06a75a8d..04ceccf46d 100644 --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@ -225,7 +225,7 @@ static const VMStateDescription vmstate_i440fx = { static int i440fx_pcihost_initfn(SysBusDevice *dev) { - I440FXState *s = FROM_SYSBUS(I440FXState, dev); + PCIHostState *s = PCI_HOST_BRIDGE(dev); memory_region_init_io(&s->conf_mem, &pci_host_conf_le_ops, s, "pci-conf-idx", 4); @@ -267,12 +267,12 @@ static PCIBus *i440fx_common_init(const char *device_name, DeviceState *dev; PCIBus *b; PCIDevice *d; - I440FXState *s; + PCIHostState *s; PIIX3State *piix3; PCII440FXState *f; dev = qdev_create(NULL, "i440FX-pcihost"); - s = FROM_SYSBUS(I440FXState, sysbus_from_qdev(dev)); + s = PCI_HOST_BRIDGE(dev); s->address_space = address_space_mem; b = pci_bus_new(&s->busdev.qdev, NULL, pci_address_space, address_space_io, 0); @@ -603,7 +603,7 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data) static const TypeInfo i440fx_pcihost_info = { .name = "i440FX-pcihost", - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(I440FXState), .class_init = i440fx_pcihost_class_init, }; diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c index 599a75a05b..55833213e1 100644 --- a/hw/ppc4xx_pci.c +++ b/hw/ppc4xx_pci.c @@ -338,7 +338,7 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev) PCIBus *b; int i; - h = FROM_SYSBUS(PCIHostState, dev); + h = PCI_HOST_BRIDGE(dev); s = PPC4xx_PCI_HOST_BRIDGE(dev); for (i = 0; i < ARRAY_SIZE(s->irq); i++) { @@ -398,7 +398,7 @@ static void ppc4xx_pcihost_class_init(ObjectClass *klass, void *data) static const TypeInfo ppc4xx_pcihost_info = { .name = TYPE_PPC4xx_PCI_HOST_BRIDGE, - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(PPC4xxPCIState), .class_init = ppc4xx_pcihost_class_init, }; diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index 7a876164c9..592b7b255f 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -471,7 +471,6 @@ static void ppc_prep_init (ram_addr_t ram_size, uint32_t kernel_base, initrd_base; long kernel_size, initrd_size; DeviceState *dev; - SysBusDevice *sys; PCIHostState *pcihost; PCIBus *pci_bus; PCIDevice *pci; @@ -584,8 +583,7 @@ static void ppc_prep_init (ram_addr_t ram_size, } dev = qdev_create(NULL, "raven-pcihost"); - sys = sysbus_from_qdev(dev); - pcihost = DO_UPCAST(PCIHostState, busdev, sys); + pcihost = PCI_HOST_BRIDGE(dev); pcihost->address_space = get_system_memory(); object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev), NULL); qdev_init_nofail(dev); diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index e4f065a496..3333967746 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -316,7 +316,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev) MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *address_space_io = get_system_io(); - h = FROM_SYSBUS(PCIHostState, dev); + h = PCI_HOST_BRIDGE(dev); s = PPC_E500_PCI_HOST_BRIDGE(dev); for (i = 0; i < ARRAY_SIZE(s->irq); i++) { @@ -374,7 +374,7 @@ static void e500_pcihost_class_init(ObjectClass *klass, void *data) static const TypeInfo e500_pcihost_info = { .name = TYPE_PPC_E500_PCI_HOST_BRIDGE, - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(PPCE500PCIState), .class_init = e500_pcihost_class_init, }; diff --git a/hw/prep_pci.c b/hw/prep_pci.c index 69c19dfded..35cb9b297c 100644 --- a/hw/prep_pci.c +++ b/hw/prep_pci.c @@ -103,7 +103,7 @@ static void prep_set_irq(void *opaque, int irq_num, int level) static int raven_pcihost_init(SysBusDevice *dev) { - PCIHostState *h = FROM_SYSBUS(PCIHostState, dev); + PCIHostState *h = PCI_HOST_BRIDGE(dev); PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(dev); MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *address_space_io = get_system_io(); @@ -192,7 +192,7 @@ static void raven_pcihost_class_init(ObjectClass *klass, void *data) static const TypeInfo raven_pcihost_info = { .name = TYPE_RAVEN_PCI_HOST_BRIDGE, - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(PREPPCIState), .class_init = raven_pcihost_class_init, }; diff --git a/hw/spapr.c b/hw/spapr.c index f8b53e9c1e..c34b767c6e 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -743,7 +743,7 @@ static void ppc_spapr_init(ram_addr_t ram_size, SPAPR_PCI_MEM_WIN_SIZE, SPAPR_PCI_IO_WIN_ADDR, SPAPR_PCI_MSI_WIN_ADDR); - phb = &QLIST_FIRST(&spapr->phbs)->host_state; + phb = PCI_HOST_BRIDGE(QLIST_FIRST(&spapr->phbs)); for (i = 0; i < nb_nics; i++) { NICInfo *nd = &nd_table[i]; diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index f9dd2a8203..661c05bc30 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -64,7 +64,7 @@ static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid, uint32_t config_addr) { sPAPRPHBState *sphb = find_phb(spapr, buid); - PCIHostState *phb = &sphb->host_state; + PCIHostState *phb = PCI_HOST_BRIDGE(sphb); BusState *bus = BUS(phb->bus); BusChild *kid; int devfn = (config_addr >> 8) & 0xFF; @@ -517,7 +517,7 @@ static DMAContext *spapr_pci_dma_context_fn(PCIBus *bus, void *opaque, static int spapr_phb_init(SysBusDevice *s) { sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s); - PCIHostState *phb = FROM_SYSBUS(PCIHostState, s); + PCIHostState *phb = PCI_HOST_BRIDGE(s); char *namebuf; int i; PCIBus *bus; @@ -617,7 +617,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data) static const TypeInfo spapr_phb_info = { .name = TYPE_SPAPR_PCI_HOST_BRIDGE, - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(sPAPRPHBState), .class_init = spapr_phb_class_init, }; diff --git a/hw/unin_pci.c b/hw/unin_pci.c index 1fc8920ab0..0db7c1f52b 100644 --- a/hw/unin_pci.c +++ b/hw/unin_pci.c @@ -148,7 +148,7 @@ static int pci_unin_main_init_device(SysBusDevice *dev) /* Use values found on a real PowerMac */ /* Uninorth main bus */ - h = FROM_SYSBUS(PCIHostState, dev); + h = PCI_HOST_BRIDGE(dev); memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, dev, "pci-conf-idx", 0x1000); @@ -166,7 +166,7 @@ static int pci_u3_agp_init_device(SysBusDevice *dev) PCIHostState *h; /* Uninorth U3 AGP bus */ - h = FROM_SYSBUS(PCIHostState, dev); + h = PCI_HOST_BRIDGE(dev); memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, dev, "pci-conf-idx", 0x1000); @@ -183,7 +183,7 @@ static int pci_unin_agp_init_device(SysBusDevice *dev) PCIHostState *h; /* Uninorth AGP bus */ - h = FROM_SYSBUS(PCIHostState, dev); + h = PCI_HOST_BRIDGE(dev); memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, dev, "pci-conf-idx", 0x1000); @@ -199,7 +199,7 @@ static int pci_unin_internal_init_device(SysBusDevice *dev) PCIHostState *h; /* Uninorth internal bus */ - h = FROM_SYSBUS(PCIHostState, dev); + h = PCI_HOST_BRIDGE(dev); memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, dev, "pci-conf-idx", 0x1000); @@ -224,7 +224,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic, dev = qdev_create(NULL, TYPE_UNI_NORTH_PCI_HOST_BRIDGE); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); - h = FROM_SYSBUS(PCIHostState, s); + h = PCI_HOST_BRIDGE(s); d = UNI_NORTH_PCI_HOST_BRIDGE(dev); memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL); memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio, @@ -289,7 +289,7 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic, dev = qdev_create(NULL, TYPE_U3_AGP_HOST_BRIDGE); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); - h = FROM_SYSBUS(PCIHostState, s); + h = PCI_HOST_BRIDGE(dev); d = U3_AGP_HOST_BRIDGE(dev); memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL); @@ -427,7 +427,7 @@ static void pci_unin_main_class_init(ObjectClass *klass, void *data) static const TypeInfo pci_unin_main_info = { .name = TYPE_UNI_NORTH_PCI_HOST_BRIDGE, - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(UNINState), .class_init = pci_unin_main_class_init, }; @@ -441,7 +441,7 @@ static void pci_u3_agp_class_init(ObjectClass *klass, void *data) static const TypeInfo pci_u3_agp_info = { .name = TYPE_U3_AGP_HOST_BRIDGE, - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(UNINState), .class_init = pci_u3_agp_class_init, }; @@ -455,7 +455,7 @@ static void pci_unin_agp_class_init(ObjectClass *klass, void *data) static const TypeInfo pci_unin_agp_info = { .name = TYPE_UNI_NORTH_AGP_HOST_BRIDGE, - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(UNINState), .class_init = pci_unin_agp_class_init, }; @@ -469,7 +469,7 @@ static void pci_unin_internal_class_init(ObjectClass *klass, void *data) static const TypeInfo pci_unin_internal_info = { .name = TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE, - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(UNINState), .class_init = pci_unin_internal_class_init, }; From 67c332fd12326a6ef572f07b9d71370ada6a287f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 20 Aug 2012 19:08:09 +0200 Subject: [PATCH 0089/2270] pci: Tidy up PCI host bridges MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adopt the QOM parent field name and enforce QOM-style access via casts. Don't just typedef PCIHostState, either use it directly or embed it. Signed-off-by: Andreas Färber Signed-off-by: Anthony Liguori --- hw/alpha_typhoon.c | 2 +- hw/dec_pci.c | 2 +- hw/grackle_pci.c | 2 +- hw/gt64xxx.c | 26 ++++++++++++++++---------- hw/piix_pci.c | 6 ++++-- hw/ppc4xx_pci.c | 8 +++++--- hw/ppce500_pci.c | 2 +- hw/prep_pci.c | 8 +++++--- hw/spapr_pci.h | 2 +- hw/unin_pci.c | 12 +++++++----- 10 files changed, 42 insertions(+), 28 deletions(-) diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c index 7667412adb..b7cf4e2900 100644 --- a/hw/alpha_typhoon.c +++ b/hw/alpha_typhoon.c @@ -46,7 +46,7 @@ typedef struct TyphoonPchip { OBJECT_CHECK(TyphoonState, (obj), TYPE_TYPHOON_PCI_HOST_BRIDGE) typedef struct TyphoonState { - PCIHostState host; + PCIHostState parent_obj; TyphoonCchip cchip; TyphoonPchip pchip; diff --git a/hw/dec_pci.c b/hw/dec_pci.c index de16361705..c30ade38bd 100644 --- a/hw/dec_pci.c +++ b/hw/dec_pci.c @@ -43,7 +43,7 @@ #define DEC_21154(obj) OBJECT_CHECK(DECState, (obj), TYPE_DEC_21154) typedef struct DECState { - PCIHostState host_state; + PCIHostState parent_obj; } DECState; static int dec_map_irq(PCIDevice *pci_dev, int irq_num) diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c index 066f6e1900..67da307284 100644 --- a/hw/grackle_pci.c +++ b/hw/grackle_pci.c @@ -41,7 +41,7 @@ OBJECT_CHECK(GrackleState, (obj), TYPE_GRACKLE_PCI_HOST_BRIDGE) typedef struct GrackleState { - PCIHostState host_state; + PCIHostState parent_obj; MemoryRegion pci_mmio; MemoryRegion pci_hole; diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c index 857758e23b..e95e664833 100644 --- a/hw/gt64xxx.c +++ b/hw/gt64xxx.c @@ -235,7 +235,7 @@ OBJECT_CHECK(GT64120State, (obj), TYPE_GT64120_PCI_HOST_BRIDGE) typedef struct GT64120State { - PCIHostState pci; + PCIHostState parent_obj; uint32_t regs[GT_REGS]; PCI_MAPPING_ENTRY(PCI0IO); @@ -315,6 +315,7 @@ static void gt64120_writel (void *opaque, target_phys_addr_t addr, uint64_t val, unsigned size) { GT64120State *s = opaque; + PCIHostState *phb = PCI_HOST_BRIDGE(s); uint32_t saddr; if (!(s->regs[GT_CPU] & 0x00001000)) @@ -535,13 +536,15 @@ static void gt64120_writel (void *opaque, target_phys_addr_t addr, /* not implemented */ break; case GT_PCI0_CFGADDR: - s->pci.config_reg = val & 0x80fffffc; + phb->config_reg = val & 0x80fffffc; break; case GT_PCI0_CFGDATA: - if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci.config_reg & 0x00fff800)) + if (!(s->regs[GT_PCI0_CMD] & 1) && (phb->config_reg & 0x00fff800)) { val = bswap32(val); - if (s->pci.config_reg & (1u << 31)) - pci_data_write(s->pci.bus, s->pci.config_reg, val, 4); + } + if (phb->config_reg & (1u << 31)) { + pci_data_write(phb->bus, phb->config_reg, val, 4); + } break; /* Interrupts */ @@ -594,6 +597,7 @@ static uint64_t gt64120_readl (void *opaque, target_phys_addr_t addr, unsigned size) { GT64120State *s = opaque; + PCIHostState *phb = PCI_HOST_BRIDGE(s); uint32_t val; uint32_t saddr; @@ -775,15 +779,17 @@ static uint64_t gt64120_readl (void *opaque, /* PCI Internal */ case GT_PCI0_CFGADDR: - val = s->pci.config_reg; + val = phb->config_reg; break; case GT_PCI0_CFGDATA: - if (!(s->pci.config_reg & (1 << 31))) + if (!(phb->config_reg & (1 << 31))) { val = 0xffffffff; - else - val = pci_data_read(s->pci.bus, s->pci.config_reg, 4); - if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci.config_reg & 0x00fff800)) + } else { + val = pci_data_read(phb->bus, phb->config_reg, 4); + } + if (!(s->regs[GT_PCI0_CMD] & 1) && (phb->config_reg & 0x00fff800)) { val = bswap32(val); + } break; case GT_PCI0_CMD: diff --git a/hw/piix_pci.c b/hw/piix_pci.c index 04ceccf46d..537fc1973c 100644 --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@ -36,7 +36,9 @@ * http://download.intel.com/design/chipsets/datashts/29054901.pdf */ -typedef PCIHostState I440FXState; +typedef struct I440FXState { + PCIHostState parent_obj; +} I440FXState; #define PIIX_NUM_PIC_IRQS 16 /* i8259 * 2 */ #define PIIX_NUM_PIRQS 4ULL /* PIRQ[A-D] */ @@ -274,7 +276,7 @@ static PCIBus *i440fx_common_init(const char *device_name, dev = qdev_create(NULL, "i440FX-pcihost"); s = PCI_HOST_BRIDGE(dev); s->address_space = address_space_mem; - b = pci_bus_new(&s->busdev.qdev, NULL, pci_address_space, + b = pci_bus_new(dev, NULL, pci_address_space, address_space_io, 0); s->bus = b; object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL); diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c index 55833213e1..a14fd426c1 100644 --- a/hw/ppc4xx_pci.c +++ b/hw/ppc4xx_pci.c @@ -52,7 +52,7 @@ struct PCITargetMap { #define PPC4xx_PCI_NR_PTMS 2 struct PPC4xxPCIState { - PCIHostState pci_state; + PCIHostState parent_obj; struct PCIMasterMap pmm[PPC4xx_PCI_NR_PMMS]; struct PCITargetMap ptm[PPC4xx_PCI_NR_PTMS]; @@ -96,16 +96,18 @@ static uint64_t pci4xx_cfgaddr_read(void *opaque, target_phys_addr_t addr, unsigned size) { PPC4xxPCIState *ppc4xx_pci = opaque; + PCIHostState *phb = PCI_HOST_BRIDGE(ppc4xx_pci); - return ppc4xx_pci->pci_state.config_reg; + return phb->config_reg; } static void pci4xx_cfgaddr_write(void *opaque, target_phys_addr_t addr, uint64_t value, unsigned size) { PPC4xxPCIState *ppc4xx_pci = opaque; + PCIHostState *phb = PCI_HOST_BRIDGE(ppc4xx_pci); - ppc4xx_pci->pci_state.config_reg = value & ~0x3; + phb->config_reg = value & ~0x3; } static const MemoryRegionOps pci4xx_cfgaddr_ops = { diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 3333967746..92b1dc0534 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -78,7 +78,7 @@ struct pci_inbound { OBJECT_CHECK(PPCE500PCIState, (obj), TYPE_PPC_E500_PCI_HOST_BRIDGE) struct PPCE500PCIState { - PCIHostState pci_state; + PCIHostState parent_obj; struct pci_outbound pob[PPCE500_PCI_NR_POBS]; struct pci_inbound pib[PPCE500_PCI_NR_PIBS]; diff --git a/hw/prep_pci.c b/hw/prep_pci.c index 35cb9b297c..cc44e61987 100644 --- a/hw/prep_pci.c +++ b/hw/prep_pci.c @@ -34,7 +34,7 @@ OBJECT_CHECK(PREPPCIState, (obj), TYPE_RAVEN_PCI_HOST_BRIDGE) typedef struct PRePPCIState { - PCIHostState host_state; + PCIHostState parent_obj; MemoryRegion intack; qemu_irq irq[4]; @@ -60,14 +60,16 @@ static void ppc_pci_io_write(void *opaque, target_phys_addr_t addr, uint64_t val, unsigned int size) { PREPPCIState *s = opaque; - pci_data_write(s->host_state.bus, PPC_PCIIO_config(addr), val, size); + PCIHostState *phb = PCI_HOST_BRIDGE(s); + pci_data_write(phb->bus, PPC_PCIIO_config(addr), val, size); } static uint64_t ppc_pci_io_read(void *opaque, target_phys_addr_t addr, unsigned int size) { PREPPCIState *s = opaque; - return pci_data_read(s->host_state.bus, PPC_PCIIO_config(addr), size); + PCIHostState *phb = PCI_HOST_BRIDGE(s); + return pci_data_read(phb->bus, PPC_PCIIO_config(addr), size); } static const MemoryRegionOps PPC_PCIIO_ops = { diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index 4140ee67af..670dc62a19 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -35,7 +35,7 @@ OBJECT_CHECK(sPAPRPHBState, (obj), TYPE_SPAPR_PCI_HOST_BRIDGE) typedef struct sPAPRPHBState { - PCIHostState host_state; + PCIHostState parent_obj; uint64_t buid; char *busname; diff --git a/hw/unin_pci.c b/hw/unin_pci.c index 0db7c1f52b..d1cc68062b 100644 --- a/hw/unin_pci.c +++ b/hw/unin_pci.c @@ -53,7 +53,7 @@ static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e }; OBJECT_CHECK(UNINState, (obj), TYPE_U3_AGP_HOST_BRIDGE) typedef struct UNINState { - PCIHostState host_state; + PCIHostState parent_obj; MemoryRegion pci_mmio; MemoryRegion pci_hole; @@ -115,10 +115,11 @@ static void unin_data_write(void *opaque, target_phys_addr_t addr, uint64_t val, unsigned len) { UNINState *s = opaque; + PCIHostState *phb = PCI_HOST_BRIDGE(s); UNIN_DPRINTF("write addr %" TARGET_FMT_plx " len %d val %"PRIx64"\n", addr, len, val); - pci_data_write(s->host_state.bus, - unin_get_config_reg(s->host_state.config_reg, addr), + pci_data_write(phb->bus, + unin_get_config_reg(phb->config_reg, addr), val, len); } @@ -126,10 +127,11 @@ static uint64_t unin_data_read(void *opaque, target_phys_addr_t addr, unsigned len) { UNINState *s = opaque; + PCIHostState *phb = PCI_HOST_BRIDGE(s); uint32_t val; - val = pci_data_read(s->host_state.bus, - unin_get_config_reg(s->host_state.config_reg, addr), + val = pci_data_read(phb->bus, + unin_get_config_reg(phb->config_reg, addr), len); UNIN_DPRINTF("read addr %" TARGET_FMT_plx " len %d val %x\n", addr, len, val); From 99afc91d6ccdbe45258cff66fd0ce0142820c366 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Mon, 20 Aug 2012 15:31:38 +0100 Subject: [PATCH 0090/2270] qapi: add 'query-target' command to return target arch Add a 'query-target' QAPI command to allow management applications to determine what target architecture a QEMU binary is emulating without having to parse the binary name or -help output $ qmp-shell -p /tmp/qemu (QEMU) query-target { u'return': { u'arch': u'x86_64' }} Signed-off-by: Daniel P. Berrange Signed-off-by: Anthony Liguori --- arch_init.c | 11 +++++++++++ configure | 7 ++++++- qapi-schema.json | 39 +++++++++++++++++++++++++++++++++++++++ qmp-commands.hx | 5 +++++ 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/arch_init.c b/arch_init.c index 9b46bfcaa5..5a1173e29a 100644 --- a/arch_init.c +++ b/arch_init.c @@ -44,6 +44,7 @@ #include "exec-memory.h" #include "hw/pcspk.h" #include "qemu/page_cache.h" +#include "qmp-commands.h" #ifdef DEBUG_ARCH_INIT #define DPRINTF(fmt, ...) \ @@ -1080,3 +1081,13 @@ int xen_available(void) return 0; #endif } + + +TargetInfo *qmp_query_target(Error **errp) +{ + TargetInfo *info = g_malloc0(sizeof(*info)); + + info->arch = TARGET_TYPE; + + return info; +} diff --git a/configure b/configure index 60d266fcca..d97fd81709 100755 --- a/configure +++ b/configure @@ -3834,14 +3834,19 @@ case "$target_arch2" in ;; esac +upper() { + echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]' +} + echo "TARGET_SHORT_ALIGNMENT=$target_short_alignment" >> $config_target_mak echo "TARGET_INT_ALIGNMENT=$target_int_alignment" >> $config_target_mak echo "TARGET_LONG_ALIGNMENT=$target_long_alignment" >> $config_target_mak echo "TARGET_LLONG_ALIGNMENT=$target_llong_alignment" >> $config_target_mak echo "TARGET_ARCH=$TARGET_ARCH" >> $config_target_mak -target_arch_name="`echo $TARGET_ARCH | LC_ALL=C tr '[a-z]' '[A-Z]'`" +target_arch_name="`upper $TARGET_ARCH`" echo "TARGET_$target_arch_name=y" >> $config_target_mak echo "TARGET_ARCH2=$target_arch2" >> $config_target_mak +echo "TARGET_TYPE=TARGET_TYPE_`upper $target_arch2`" >> $config_target_mak echo "TARGET_BASE_ARCH=$TARGET_BASE_ARCH" >> $config_target_mak if [ "$TARGET_ABI_DIR" = "" ]; then TARGET_ABI_DIR=$TARGET_ARCH diff --git a/qapi-schema.json b/qapi-schema.json index 3d2b2d175a..72b3c4d5bd 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2454,3 +2454,42 @@ # ## { 'command': 'query-fdsets', 'returns': ['FdsetInfo'] } + +## +# @TargetType +# +# Target CPU emulation type +# +# These parameters correspond to the softmmu binary CPU name that is currently +# running. +# +# Since: 1.2.0 +## +{ 'enum': 'TargetType', + 'data': [ 'alpha', 'arm', 'cris', 'i386', 'lm32', 'm68k', 'microblazeel', + 'microblaze', 'mips64el', 'mips64', 'mipsel', 'mips', 'or32', + 'ppc64', 'ppcemb', 'ppc', 's390x', 'sh4eb', 'sh4', 'sparc64', + 'sparc', 'unicore32', 'x86_64', 'xtensaeb', 'xtensa' ] } + +## +# @TargetInfo: +# +# Information describing the QEMU target. +# +# @arch: the target architecture (eg "x86_64", "i386", etc) +# +# Since: 1.2.0 +## +{ 'type': 'TargetInfo', + 'data': { 'arch': 'TargetType' } } + +## +# @query-target: +# +# Return information about the target for this QEMU +# +# Returns: TargetInfo +# +# Since: 1.2.0 +## +{ 'command': 'query-target', 'returns': 'TargetInfo' } diff --git a/qmp-commands.hx b/qmp-commands.hx index 2ce4ce6556..00d798fe55 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -2509,3 +2509,8 @@ EQMP .mhandler.cmd_new = qmp_marshal_input_query_cpu_definitions, }, + { + .name = "query-target", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_target, + }, From af506c7036003a4a860e23e694034b9a914d1d2f Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Wed, 22 Aug 2012 15:44:38 -0500 Subject: [PATCH 0091/2270] Update version for 1.2.0-rc1 release Signed-off-by: Anthony Liguori --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 69658cdda2..069199b82a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.90 +1.1.91 From b4a738bf93c3137b92d532e59d60edccc4e1ea96 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Wed, 22 Aug 2012 15:22:05 -0500 Subject: [PATCH 0092/2270] boards: add a 'none' machine type to all platforms This allows any QEMU binary to be executed with: $QEMU_BINARY -M none -qmp stdio Without errors from missing options that are required by various boards. This also provides a mode that we can use in the future to construct machines entirely through QMP commands. Cc: Daniel Berrange Cc: Markus Armbruster Signed-off-by: Anthony Liguori --- hw/Makefile.objs | 2 ++ hw/null-machine.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 hw/null-machine.c diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 7f57ed58e2..6dfebd2978 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -134,6 +134,8 @@ hw-obj-$(CONFIG_DP8393X) += dp8393x.o hw-obj-$(CONFIG_DS1225Y) += ds1225y.o hw-obj-$(CONFIG_MIPSNET) += mipsnet.o +hw-obj-y += null-machine.o + # Sound sound-obj-y = sound-obj-$(CONFIG_SB16) += sb16.o diff --git a/hw/null-machine.c b/hw/null-machine.c new file mode 100644 index 0000000000..69910d399c --- /dev/null +++ b/hw/null-machine.c @@ -0,0 +1,40 @@ +/* + * Empty machine + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu-common.h" +#include "hw/hw.h" +#include "hw/boards.h" + +static void machine_none_init(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) +{ +} + +static QEMUMachine machine_none = { + .name = "none", + .desc = "empty machine", + .init = machine_none_init, + .max_cpus = 0, +}; + +static void register_machines(void) +{ + qemu_register_machine(&machine_none); +} + +machine_init(register_machines); + From 58617a795c8067b2f9800cffce60f38707d3aa31 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Thu, 23 Aug 2012 08:03:21 -0500 Subject: [PATCH 0093/2270] monitor: move json init from OPEN event to init At some point in the past, the OPEN event was changed to be issued from a bottom half. This creates a small window whereas a data callback registered in init may be invoked before the OPEN event has been issued. This is reproducible with: echo "{'execute': 'qmp_capabilities'}" | qemu-system-x86_64 -M none -qmp stdio We can fix this for the monitor by moving the parser initialization to init. The remaining state that is set in OPEN appears harmless. Reported-by: Daniel Berrange Signed-off-by: Anthony Liguori --- monitor.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/monitor.c b/monitor.c index 480f583f70..b188582057 100644 --- a/monitor.c +++ b/monitor.c @@ -4832,7 +4832,6 @@ static void monitor_control_event(void *opaque, int event) switch (event) { case CHR_EVENT_OPENED: mon->mc->command_mode = 0; - json_message_parser_init(&mon->mc->parser, handle_qmp_command); data = get_qmp_greeting(); monitor_json_emitter(mon, data); qobject_decref(data); @@ -4840,6 +4839,7 @@ static void monitor_control_event(void *opaque, int event) break; case CHR_EVENT_CLOSED: json_message_parser_destroy(&mon->mc->parser); + json_message_parser_init(&mon->mc->parser, handle_qmp_command); mon_refcount--; monitor_fdsets_cleanup(); break; @@ -4951,6 +4951,8 @@ void monitor_init(CharDriverState *chr, int flags) monitor_event, mon); } + json_message_parser_init(&mon->mc->parser, handle_qmp_command); + QLIST_INSERT_HEAD(&mon_list, mon, entry); if (!default_mon || (flags & MONITOR_IS_DEFAULT)) default_mon = mon; From 94159135cb59684853dcd45ff70d6dbc54a29209 Mon Sep 17 00:00:00 2001 From: Meador Inge Date: Tue, 21 Aug 2012 12:31:37 -0500 Subject: [PATCH 0094/2270] target-mips: Enable access to required RDHWR hardware registers While running in the usermode emulator all of the required* MIPS32r2 RDHWR hardware registers should be accessible (the Linux kernel enables access to these same registers). Note that these registers are still enabled when the MIPS ISA is not release 2. This is OK since the Linux kernel emulates access to them when they are not available in hardware. * There is also the ULR register which is only recommended for full release 2 compliance. Incidentally, accessing this register in the current implementation works fine without flipping its access bit. Signed-off-by: Meador Inge Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 47daf8574f..d643676e58 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -12768,8 +12768,9 @@ void cpu_state_reset(CPUMIPSState *env) #if defined(CONFIG_USER_ONLY) env->hflags = MIPS_HFLAG_UM; - /* Enable access to the SYNCI_Step register. */ - env->CP0_HWREna |= (1 << 1); + /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR + hardware registers. */ + env->CP0_HWREna |= 0x0000000F; if (env->CP0_Config1 & (1 << CP0C1_FP)) { env->hflags |= MIPS_HFLAG_FPU; } From 6fc97fafce05eee76479ca6d289241772d21b370 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sun, 4 Mar 2012 08:21:39 +0100 Subject: [PATCH 0095/2270] target-mips: Fix some helper functions (VR54xx multiplication) Commits b5dc7732e1cc2fb549e48b7b5d664f2c79628e2e and be24bb4f3007c3e07cbf1934f7e781493d876ab7 optimized the code and removed the correct setting of t0. Fix this. gcc-4.7 detected this bug because parameter arg1 was unused but set in set_HIT0_LO and set_HI_LOT0. Cc: Aurelien Jarno Signed-off-by: Stefan Weil Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 75 ++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 46 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 66037acec5..e5bc93e226 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -192,115 +192,98 @@ static inline uint64_t get_HILO (void) return ((uint64_t)(env->active_tc.HI[0]) << 32) | (uint32_t)env->active_tc.LO[0]; } -static inline void set_HIT0_LO (target_ulong arg1, uint64_t HILO) +static inline target_ulong set_HIT0_LO(uint64_t HILO) { + target_ulong tmp; env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF); - arg1 = env->active_tc.HI[0] = (int32_t)(HILO >> 32); + tmp = env->active_tc.HI[0] = (int32_t)(HILO >> 32); + return tmp; } -static inline void set_HI_LOT0 (target_ulong arg1, uint64_t HILO) +static inline target_ulong set_HI_LOT0(uint64_t HILO) { - arg1 = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF); + target_ulong tmp = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF); env->active_tc.HI[0] = (int32_t)(HILO >> 32); + return tmp; } /* Multiplication variants of the vr54xx. */ target_ulong helper_muls (target_ulong arg1, target_ulong arg2) { - set_HI_LOT0(arg1, 0 - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2)); - - return arg1; + return set_HI_LOT0(0 - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2)); } target_ulong helper_mulsu (target_ulong arg1, target_ulong arg2) { - set_HI_LOT0(arg1, 0 - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2)); - - return arg1; + return set_HI_LOT0(0 - (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); } target_ulong helper_macc (target_ulong arg1, target_ulong arg2) { - set_HI_LOT0(arg1, ((int64_t)get_HILO()) + ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2)); - - return arg1; + return set_HI_LOT0((int64_t)get_HILO() + (int64_t)(int32_t)arg1 * + (int64_t)(int32_t)arg2); } target_ulong helper_macchi (target_ulong arg1, target_ulong arg2) { - set_HIT0_LO(arg1, ((int64_t)get_HILO()) + ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2)); - - return arg1; + return set_HIT0_LO((int64_t)get_HILO() + (int64_t)(int32_t)arg1 * + (int64_t)(int32_t)arg2); } target_ulong helper_maccu (target_ulong arg1, target_ulong arg2) { - set_HI_LOT0(arg1, ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2)); - - return arg1; + return set_HI_LOT0((uint64_t)get_HILO() + (uint64_t)(uint32_t)arg1 * + (uint64_t)(uint32_t)arg2); } target_ulong helper_macchiu (target_ulong arg1, target_ulong arg2) { - set_HIT0_LO(arg1, ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2)); - - return arg1; + return set_HIT0_LO((uint64_t)get_HILO() + (uint64_t)(uint32_t)arg1 * + (uint64_t)(uint32_t)arg2); } target_ulong helper_msac (target_ulong arg1, target_ulong arg2) { - set_HI_LOT0(arg1, ((int64_t)get_HILO()) - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2)); - - return arg1; + return set_HI_LOT0((int64_t)get_HILO() - (int64_t)(int32_t)arg1 * + (int64_t)(int32_t)arg2); } target_ulong helper_msachi (target_ulong arg1, target_ulong arg2) { - set_HIT0_LO(arg1, ((int64_t)get_HILO()) - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2)); - - return arg1; + return set_HIT0_LO((int64_t)get_HILO() - (int64_t)(int32_t)arg1 * + (int64_t)(int32_t)arg2); } target_ulong helper_msacu (target_ulong arg1, target_ulong arg2) { - set_HI_LOT0(arg1, ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2)); - - return arg1; + return set_HI_LOT0((uint64_t)get_HILO() - (uint64_t)(uint32_t)arg1 * + (uint64_t)(uint32_t)arg2); } target_ulong helper_msachiu (target_ulong arg1, target_ulong arg2) { - set_HIT0_LO(arg1, ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2)); - - return arg1; + return set_HIT0_LO((uint64_t)get_HILO() - (uint64_t)(uint32_t)arg1 * + (uint64_t)(uint32_t)arg2); } target_ulong helper_mulhi (target_ulong arg1, target_ulong arg2) { - set_HIT0_LO(arg1, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2); - - return arg1; + return set_HIT0_LO((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2); } target_ulong helper_mulhiu (target_ulong arg1, target_ulong arg2) { - set_HIT0_LO(arg1, (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); - - return arg1; + return set_HIT0_LO((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); } target_ulong helper_mulshi (target_ulong arg1, target_ulong arg2) { - set_HIT0_LO(arg1, 0 - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2)); - - return arg1; + return set_HIT0_LO(0 - (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2); } target_ulong helper_mulshiu (target_ulong arg1, target_ulong arg2) { - set_HIT0_LO(arg1, 0 - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2)); - - return arg1; + return set_HIT0_LO(0 - (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); } #ifdef TARGET_MIPS64 From 26efaca377e004b79ff50a6e936d029a0c095b8b Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Thu, 23 Aug 2012 13:49:02 -0500 Subject: [PATCH 0096/2270] monitor: don't try to initialize json parser when monitor is HMP Reported-by: Michael Roth Signed-off-by: Anthony Liguori --- monitor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monitor.c b/monitor.c index b188582057..b17b1bb849 100644 --- a/monitor.c +++ b/monitor.c @@ -4946,13 +4946,13 @@ void monitor_init(CharDriverState *chr, int flags) qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read, monitor_control_event, mon); qemu_chr_fe_set_echo(chr, true); + + json_message_parser_init(&mon->mc->parser, handle_qmp_command); } else { qemu_chr_add_handlers(chr, monitor_can_read, monitor_read, monitor_event, mon); } - json_message_parser_init(&mon->mc->parser, handle_qmp_command); - QLIST_INSERT_HEAD(&mon_list, mon, entry); if (!default_mon || (flags & MONITOR_IS_DEFAULT)) default_mon = mon; From da5a44e8b0b727681fc33e8d94832d1cae48a788 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 22 Aug 2012 23:09:46 +0200 Subject: [PATCH 0097/2270] qom: object_delete should unparent the object first object_deinit is only called when the reference count goes to zero, and yet tries to do an object_unparent. Now, object_unparent either does nothing or it will decrease the reference count. Because we know the reference count is zero, the object_unparent call in object_deinit is useless. Instead, we need to disconnect the object from its parent just before we remove the last reference apart from the parent's. This happens in object_delete. Once we do this, all calls to object_unparent peppered through QEMU can go away. Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- hw/acpi_piix4.c | 1 - hw/qdev.c | 2 -- hw/shpc.c | 1 - hw/xen_platform.c | 3 --- qom/object.c | 5 ++--- 5 files changed, 2 insertions(+), 10 deletions(-) diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 0aace60f24..72d6e5c904 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -305,7 +305,6 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots) if (pc->no_hotplug) { slot_free = false; } else { - object_unparent(OBJECT(dev)); qdev_free(qdev); } } diff --git a/hw/qdev.c b/hw/qdev.c index b5b74b9135..b5a52ac503 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -159,7 +159,6 @@ int qdev_init(DeviceState *dev) rc = dc->init(dev); if (rc < 0) { - object_unparent(OBJECT(dev)); qdev_free(dev); return rc; } @@ -243,7 +242,6 @@ void qbus_reset_all_fn(void *opaque) int qdev_simple_unplug_cb(DeviceState *dev) { /* just zap it */ - object_unparent(OBJECT(dev)); qdev_free(dev); return 0; } diff --git a/hw/shpc.c b/hw/shpc.c index 6b9884d544..a5baf246f1 100644 --- a/hw/shpc.c +++ b/hw/shpc.c @@ -253,7 +253,6 @@ static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot) ++devfn) { PCIDevice *affected_dev = shpc->sec_bus->devices[devfn]; if (affected_dev) { - object_unparent(OBJECT(affected_dev)); qdev_free(&affected_dev->qdev); } } diff --git a/hw/xen_platform.c b/hw/xen_platform.c index c1fe984f07..0d6c2ff8c3 100644 --- a/hw/xen_platform.c +++ b/hw/xen_platform.c @@ -87,9 +87,6 @@ static void unplug_nic(PCIBus *b, PCIDevice *d, void *o) { if (pci_get_word(d->config + PCI_CLASS_DEVICE) == PCI_CLASS_NETWORK_ETHERNET) { - /* Until qdev_free includes a call to object_unparent, we call it here - */ - object_unparent(&d->qdev.parent_obj); qdev_free(&d->qdev); } } diff --git a/qom/object.c b/qom/object.c index a552be258e..e3e9242638 100644 --- a/qom/object.c +++ b/qom/object.c @@ -373,8 +373,6 @@ static void object_deinit(Object *obj, TypeImpl *type) if (type_has_parent(type)) { object_deinit(obj, type_get_parent(type)); } - - object_unparent(obj); } void object_finalize(void *data) @@ -411,8 +409,9 @@ Object *object_new(const char *typename) void object_delete(Object *obj) { + object_unparent(obj); + g_assert(obj->ref == 1); object_unref(obj); - g_assert(obj->ref == 0); g_free(obj); } From 98609cd8fcf755c0ba7049d751353b8b2e243b65 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 22 Aug 2012 23:09:47 +0200 Subject: [PATCH 0098/2270] ivshmem: fix memory_region_del_eventfd assertion failure We do not register ioeventfds unless the IVSHMEM_IOEVENTFD feature is set. The same feature must be checked before releasing the eventfds. Regression introduced by commit 563027c (ivshmem: use EventNotifier and memory API, 2012-07-05). Reported-by: Cam Macdonnell Tested-by: Cam Macdonnell Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- hw/ivshmem.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/ivshmem.c b/hw/ivshmem.c index b4d65a6db5..47f2a16833 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -366,6 +366,10 @@ static void close_guest_eventfds(IVShmemState *s, int posn) { int i, guest_curr_max; + if (!ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) { + return; + } + guest_curr_max = s->peers[posn].nb_eventfds; memory_region_transaction_begin(); From 145c7c880ff520a9348cc2401ba291330b9606fe Mon Sep 17 00:00:00 2001 From: Matthew Ogilvie Date: Thu, 23 Aug 2012 00:24:38 -0600 Subject: [PATCH 0099/2270] fix some debug printf format strings These are normally ifdefed out and don't matter. But if you enable them, they ought to be correct. Signed-off-by: Matthew Ogilvie Signed-off-by: malc --- hw/cirrus_vga.c | 4 ++-- hw/i8259.c | 3 ++- hw/ide/cmd646.c | 5 +++-- hw/ide/via.c | 5 +++-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index e8dcc6b883..909899dd54 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -2055,8 +2055,8 @@ static void cirrus_vga_mem_write(void *opaque, } } else { #ifdef DEBUG_CIRRUS - printf("cirrus: mem_writeb " TARGET_FMT_plx " value %02x\n", addr, - mem_value); + printf("cirrus: mem_writeb " TARGET_FMT_plx " value %" PRIx64 "\n", + addr, mem_value); #endif } } diff --git a/hw/i8259.c b/hw/i8259.c index 53daf78652..65876662a1 100644 --- a/hw/i8259.c +++ b/hw/i8259.c @@ -355,7 +355,8 @@ static uint64_t pic_ioport_read(void *opaque, target_phys_addr_t addr, ret = s->imr; } } - DPRINTF("read: addr=0x%02x val=0x%02x\n", addr, ret); + DPRINTF("read: addr=0x%02" TARGET_PRIxPHYS " val=0x%02x\n", + addr, ret); return ret; } diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index e0b9443496..dd2855e19d 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -154,7 +154,7 @@ static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr, break; } #ifdef DEBUG_IDE - printf("bmdma: readb 0x%02x : 0x%02x\n", addr, val); + printf("bmdma: readb 0x%02" TARGET_PRIxPHYS " : 0x%02x\n", addr, val); #endif return val; } @@ -170,7 +170,8 @@ static void bmdma_write(void *opaque, target_phys_addr_t addr, } #ifdef DEBUG_IDE - printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val); + printf("bmdma: writeb 0x%02" TARGET_PRIxPHYS " : 0x%02" PRIx64 "\n", + addr, val); #endif switch(addr & 3) { case 0: diff --git a/hw/ide/via.c b/hw/ide/via.c index b20e4f094e..948a46938a 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -55,7 +55,7 @@ static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr, break; } #ifdef DEBUG_IDE - printf("bmdma: readb 0x%02x : 0x%02x\n", addr, val); + printf("bmdma: readb 0x%02" TARGET_PRIxPHYS " : 0x%02x\n", addr, val); #endif return val; } @@ -70,7 +70,8 @@ static void bmdma_write(void *opaque, target_phys_addr_t addr, } #ifdef DEBUG_IDE - printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val); + printf("bmdma: writeb 0x%02" TARGET_PRIxPHYS " : 0x%02" PRIx64 "\n", + addr, val); #endif switch (addr & 3) { case 0: From 5c73b757e3aa80dc84352b2ede0d8bdea5419f6d Mon Sep 17 00:00:00 2001 From: Matthew Ogilvie Date: Thu, 23 Aug 2012 00:24:39 -0600 Subject: [PATCH 0100/2270] target-i386/translate.c: mov to/from crN/drN: ignore mod bits > This instruction is always treated as a register-to-register (MOD = 11) > instruction, regardless of the encoding of the MOD field in the MODR/M > byte. Also, Microport UNIX System V/386 v 2.1 (ca 1987) runs fine on real Intel 386 and 486 CPU's (at least), but does not run in qemu without this patch. Signed-off-by: Matthew Ogilvie Signed-off-by: malc --- target-i386/translate.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/target-i386/translate.c b/target-i386/translate.c index 7ab2ccb190..eb0cabcf19 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -7551,8 +7551,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { modrm = cpu_ldub_code(cpu_single_env, s->pc++); - if ((modrm & 0xc0) != 0xc0) - goto illegal_op; + /* Ignore the mod bits (assume (modrm&0xc0)==0xc0). + * AMD documentation (24594.pdf) and testing of + * intel 386 and 486 processors all show that the mod bits + * are assumed to be 1's, regardless of actual values. + */ rm = (modrm & 7) | REX_B(s); reg = ((modrm >> 3) & 7) | rex_r; if (CODE64(s)) @@ -7594,8 +7597,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { modrm = cpu_ldub_code(cpu_single_env, s->pc++); - if ((modrm & 0xc0) != 0xc0) - goto illegal_op; + /* Ignore the mod bits (assume (modrm&0xc0)==0xc0). + * AMD documentation (24594.pdf) and testing of + * intel 386 and 486 processors all show that the mod bits + * are assumed to be 1's, regardless of actual values. + */ rm = (modrm & 7) | REX_B(s); reg = ((modrm >> 3) & 7) | rex_r; if (CODE64(s)) From 7764ae9671f1cd74227cf4404431dd5213799ef0 Mon Sep 17 00:00:00 2001 From: Matthew Ogilvie Date: Thu, 23 Aug 2012 00:24:40 -0600 Subject: [PATCH 0101/2270] vl: fix -hdachs/-hda argument order parsing issues Without this patch, the -hdachs argument had to occur either BEFORE the corresponding "-hda" option, or AFTER the plain disk image name (if neither -hda nor -drive is used). Otherwise it would effectively be ignored. Option -hdachs still has no effect on -drive, but that seems best. Signed-off-by: Matthew Ogilvie Signed-off-by: malc --- vl.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/vl.c b/vl.c index 7c577fa544..febfd62c37 100644 --- a/vl.c +++ b/vl.c @@ -2352,8 +2352,9 @@ int main(int argc, char **argv, char **envp) char boot_devices[33] = "cad"; /* default to HD->floppy->CD-ROM */ DisplayState *ds; DisplayChangeListener *dcl; - int cyls, heads, secs, translation; - QemuOpts *hda_opts = NULL, *opts, *machine_opts; + char hdachs_params[512]; /* save -hdachs to apply to later -hda */ + QemuOpts *hda_opts = NULL; /* save -hda to be modified by later -hdachs */ + QemuOpts *opts, *machine_opts; QemuOptsList *olist; int optind; const char *optarg; @@ -2408,8 +2409,7 @@ int main(int argc, char **argv, char **envp) cpu_model = NULL; ram_size = 0; snapshot = 0; - cyls = heads = secs = 0; - translation = BIOS_ATA_TRANSLATION_AUTO; + snprintf(hdachs_params, sizeof(hdachs_params), "%s", HD_OPTS); for (i = 0; i < MAX_NODES; i++) { node_mem[i] = 0; @@ -2457,7 +2457,7 @@ int main(int argc, char **argv, char **envp) if (optind >= argc) break; if (argv[optind][0] != '-') { - hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS); + hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++], hdachs_params); } else { const QEMUOption *popt; @@ -2475,21 +2475,8 @@ int main(int argc, char **argv, char **envp) cpu_model = optarg; break; case QEMU_OPTION_hda: - { - char buf[256]; - if (cyls == 0) - snprintf(buf, sizeof(buf), "%s", HD_OPTS); - else - snprintf(buf, sizeof(buf), - "%s,cyls=%d,heads=%d,secs=%d%s", - HD_OPTS , cyls, heads, secs, - translation == BIOS_ATA_TRANSLATION_LBA ? - ",trans=lba" : - translation == BIOS_ATA_TRANSLATION_NONE ? - ",trans=none" : ""); - drive_add(IF_DEFAULT, 0, optarg, buf); - break; - } + hda_opts = drive_add(IF_DEFAULT, 0, optarg, hdachs_params); + break; case QEMU_OPTION_hdb: case QEMU_OPTION_hdc: case QEMU_OPTION_hdd: @@ -2523,7 +2510,10 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_hdachs: { + int cyls, heads, secs, translation; const char *p; + cyls = heads = secs = 0; + translation = BIOS_ATA_TRANSLATION_AUTO; p = optarg; cyls = strtol(p, (char **)&p, 0); if (cyls < 1 || cyls > 16383) @@ -2555,7 +2545,14 @@ int main(int argc, char **argv, char **envp) fprintf(stderr, "qemu: invalid physical CHS format\n"); exit(1); } - if (hda_opts != NULL) { + snprintf(hdachs_params, sizeof(hdachs_params), + "%s,cyls=%d,heads=%d,secs=%d%s", + HD_OPTS , cyls, heads, secs, + translation == BIOS_ATA_TRANSLATION_LBA ? + ",trans=lba" : + translation == BIOS_ATA_TRANSLATION_NONE ? + ",trans=none" : ""); + if (hda_opts != NULL) { char num[16]; snprintf(num, sizeof(num), "%d", cyls); qemu_opt_set(hda_opts, "cyls", num); From 39dda260628e5f2a3fd2ce2ec8a71f3d5ca309a9 Mon Sep 17 00:00:00 2001 From: Matthew Ogilvie Date: Thu, 23 Aug 2012 00:24:41 -0600 Subject: [PATCH 0102/2270] qemu-options.hx: mention retrace= VGA option The feature was added in commit cb5a7aa8c32141bb Sep 2008. My description is based on "Better VGA retrace emulation (needed for some DOS games/demos)" from http://www.boblycat.org/~malc/code/patches/qemu/index.html Signed-off-by: Matthew Ogilvie Signed-off-by: malc --- qemu-options.hx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/qemu-options.hx b/qemu-options.hx index 3c411c427e..3e8085d463 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -945,7 +945,7 @@ DEF("vga", HAS_ARG, QEMU_OPTION_vga, "-vga [std|cirrus|vmware|qxl|xenfb|none]\n" " select video card type\n", QEMU_ARCH_ALL) STEXI -@item -vga @var{type} +@item -vga @var{type}[,@var{prop}=@var{value}[,...]] @findex -vga Select type of VGA card to emulate. Valid values for @var{type} are @table @option @@ -970,6 +970,12 @@ Recommended choice when using the spice protocol. @item none Disable VGA card. @end table +Valid optional properties are +@table @option +@item retrace=dumb|precise +Select dumb (default) or precise VGA retrace logic, useful for some +DOS games/demos. +@end table ETEXI DEF("full-screen", 0, QEMU_OPTION_full_screen, From 482f7bf86b43af9f6903c52726fedf82b28bf953 Mon Sep 17 00:00:00 2001 From: Matthew Ogilvie Date: Thu, 23 Aug 2012 00:24:42 -0600 Subject: [PATCH 0103/2270] vga: add some optional CGA compatibility hacks This patch adds some optional compatibility hacks (default disabled) to allow Microport UNIX to function under qemu. I've tried to structure it to be easy to add more hacks for other old CGA programs, if anyone ever needs them. Microport UNIX System V/386 v 2.1 (ca 1987) tries to program the CGA registers directly with neither the assistance of BIOS, nor with proper handling of EGA/VGA-only registers. Note that it didn't work on real VGA hardware, either (although in that case, the most obvious problems seemed to be out-of-range hsync and/or vsync signalling, rather than the issues in this patch). Eventually real MDA and/or CGA support might provide an alternative to this patch, although a hybrid approach like this patch might still be useful in marginal cases. Signed-off-by: Matthew Ogilvie Signed-off-by: malc --- hw/pc.h | 4 ++++ hw/vga.c | 36 ++++++++++++++++++++++++++++-------- qemu-options.hx | 19 +++++++++++++++++++ vl.c | 23 +++++++++++++++++++++++ 4 files changed, 74 insertions(+), 8 deletions(-) diff --git a/hw/pc.h b/hw/pc.h index e4db0715b8..37e2f87583 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -176,6 +176,10 @@ enum vga_retrace_method { extern enum vga_retrace_method vga_retrace_method; +#define VGA_CGA_HACK_PALETTE_BLANKING (1<<0) +#define VGA_CGA_HACK_FONT_HEIGHT (1<<1) +extern int vga_cga_hacks; + static inline DeviceState *isa_vga_init(ISABus *bus) { ISADevice *dev; diff --git a/hw/vga.c b/hw/vga.c index f82ced8e66..a65fc26ab7 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -547,14 +547,31 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) printf("vga: write CR%x = 0x%02x\n", s->cr_index, val); #endif /* handle CR0-7 protection */ - if ((s->cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) && - s->cr_index <= VGA_CRTC_OVERFLOW) { - /* can always write bit 4 of CR7 */ - if (s->cr_index == VGA_CRTC_OVERFLOW) { - s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) | - (val & 0x10); + if (s->cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) { + if (s->cr_index <= VGA_CRTC_OVERFLOW) { + /* can always write bit 4 of CR7 */ + if (s->cr_index == VGA_CRTC_OVERFLOW) { + s->cr[VGA_CRTC_OVERFLOW] = + (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) | (val & 0x10); + } + return; + } else if ((vga_cga_hacks & VGA_CGA_HACK_FONT_HEIGHT) && + !(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) { + /* extra CGA compatibility hacks (not in standard VGA) */ + if (s->cr_index == VGA_CRTC_MAX_SCAN && + val == 7 && + (s->cr[VGA_CRTC_MAX_SCAN] & 0xf) == 0xf) { + return; + } else if (s->cr_index == VGA_CRTC_CURSOR_START && + val == 6 && + (s->cr[VGA_CRTC_MAX_SCAN] & 0xf) == 0xf) { + val = 0xd; + } else if (s->cr_index == VGA_CRTC_CURSOR_END && + val == 7 && + (s->cr[VGA_CRTC_MAX_SCAN] & 0xf) == 0xf) { + val = 0xe; + } } - return; } s->cr[s->cr_index] = val; @@ -1886,7 +1903,10 @@ static void vga_update_display(void *opaque) /* nothing to do */ } else { full_update = 0; - if (!(s->ar_index & 0x20)) { + if (!(s->ar_index & 0x20) && + /* extra CGA compatibility hacks (not in standard VGA */ + (!(vga_cga_hacks & VGA_CGA_HACK_PALETTE_BLANKING) || + (s->ar_index != 0 && s->ar_flip_flop))) { graphic_mode = GMODE_BLANK; } else { graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE; diff --git a/qemu-options.hx b/qemu-options.hx index 3e8085d463..0682338e9f 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -975,6 +975,25 @@ Valid optional properties are @item retrace=dumb|precise Select dumb (default) or precise VGA retrace logic, useful for some DOS games/demos. +@item cga_hacks=@var{hack1}[+@var{hack2},[...]] +Enable various extra CGA compatibility hacks for programs that are +trying to directly set CGA modes without BIOS assistance nor +real knowledge of EGA/VGA. These might only work with -vga std. +Valid hacks are +@table @option +@item palette_blanking +Wait to blank the screen until palette registers seem to actually be +modified, instead of blanking it as soon as the palette address bit (0x10) +of the attribute address register (0x3c0) is cleared. +@item font_height +Ignore attempts to change the VGA font height (index 9), +cursor start (index 10), and cursor end (index 11) of the CRTC control +registers (0x3d5) if trying to set them to the default for CGA fonts +instead of VGA fonts. +@item all +Enable all CGA hacks. More CGA hacks may be added in future versions +of qemu. +@end table @end table ETEXI diff --git a/vl.c b/vl.c index febfd62c37..16d04a2ee2 100644 --- a/vl.c +++ b/vl.c @@ -179,6 +179,7 @@ int main(int argc, char **argv) static const char *data_dir; const char *bios_name = NULL; enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; +int vga_cga_hacks = 0; DisplayType display_type = DT_DEFAULT; int display_remote = 0; const char* keyboard_layout = NULL; @@ -1748,6 +1749,28 @@ static void select_vgahw (const char *p) else if (strstart(opts, "precise", &nextopt)) vga_retrace_method = VGA_RETRACE_PRECISE; else goto invalid_vga; + } else if (strstart(opts, ",cga_hacks=", &nextopt)) { + opts = nextopt; + while (*opts) { + if (strstart(opts, "all", &nextopt)) { + opts = nextopt; + vga_cga_hacks |= ~0; + } else if (strstart(opts, "palette_blanking", &nextopt)) { + opts = nextopt; + vga_cga_hacks |= VGA_CGA_HACK_PALETTE_BLANKING; + } else if (strstart(opts, "font_height", &nextopt)) { + opts = nextopt; + vga_cga_hacks |= VGA_CGA_HACK_FONT_HEIGHT; + } else { + break; + } + + if (*opts == '+') { + opts++; + } else { + break; + } + } } else goto invalid_vga; opts = nextopt; } From f278d4947fff814dcde2ef2acad36d172ff8be35 Mon Sep 17 00:00:00 2001 From: Matthew Ogilvie Date: Thu, 23 Aug 2012 00:24:43 -0600 Subject: [PATCH 0104/2270] i8259: add -no-spurious-interrupt-hack option This patch provides a way to optionally suppress spurious interrupts, as a workaround for systems described below: Some old operating systems do not handle spurious interrupts well, and qemu tends to generate them significantly more often than real hardware. Examples: - Microport UNIX System V/386 v 2.1 (ca 1987) (The main problem I'm fixing: Without this patch, it panics sporadically when accessing the hard disk.) - AT&T UNIX System V/386 Release 4.0 Version 2.1a (ca 1991) See screenshot in "QEMU Official OS Support List": http://www.claunia.com/qemu/objectManager.php?sClass=application&iId=9 (I don't have this system to test.) - A report about OS/2 boot lockup from 2004 by Hampa Hug: http://lists.nongnu.org/archive/html/qemu-devel/2004-09/msg00367.html (My patch was partially inspired by his.) Also: http://lists.nongnu.org/archive/html/qemu-devel/2005-06/msg00243.html (I don't have this system to test.) Signed-off-by: Matthew Ogilvie Signed-off-by: malc --- cpu-exec.c | 14 +++++++++----- hw/i8259.c | 18 ++++++++++++++++++ qemu-options.hx | 12 ++++++++++++ sysemu.h | 1 + vl.c | 4 ++++ 5 files changed, 44 insertions(+), 5 deletions(-) diff --git a/cpu-exec.c b/cpu-exec.c index 134b3c4fcf..625fbb0e0f 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -329,11 +329,15 @@ int cpu_exec(CPUArchState *env) 0); env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ); intno = cpu_get_pic_interrupt(env); - qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno); - do_interrupt_x86_hardirq(env, intno, 1); - /* ensure that no TB jump will be modified as - the program flow was changed */ - next_tb = 0; + if (intno >= 0) { + qemu_log_mask(CPU_LOG_TB_IN_ASM, + "Servicing hardware INT=0x%02x\n", + intno); + do_interrupt_x86_hardirq(env, intno, 1); + /* ensure that no TB jump will be modified as + the program flow was changed */ + next_tb = 0; + } #if !defined(CONFIG_USER_ONLY) } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) && (env->eflags & IF_MASK) && diff --git a/hw/i8259.c b/hw/i8259.c index 65876662a1..7ecb7e1de6 100644 --- a/hw/i8259.c +++ b/hw/i8259.c @@ -26,6 +26,7 @@ #include "isa.h" #include "monitor.h" #include "qemu-timer.h" +#include "sysemu.h" #include "i8259_internal.h" /* debug PIC */ @@ -193,6 +194,20 @@ int pic_read_irq(DeviceState *d) pic_intack(slave_pic, irq2); } else { /* spurious IRQ on slave controller */ + if (no_spurious_interrupt_hack) { + /* Pretend it was delivered and acknowledged. If + * it was spurious due to slave_pic->imr, then + * as soon as the mask is cleared, the slave will + * re-trigger IRQ2 on the master. If it is spurious for + * some other reason, make sure we don't keep trying + * to half-process the same spurious interrupt over + * and over again. + */ + s->irr &= ~(1<last_irr &= ~(1<isr &= ~(1<irq_base + irq2; @@ -202,6 +217,9 @@ int pic_read_irq(DeviceState *d) pic_intack(s, irq); } else { /* spurious IRQ on host controller */ + if (no_spurious_interrupt_hack) { + return -1; + } irq = 7; intno = s->irq_base + irq; } diff --git a/qemu-options.hx b/qemu-options.hx index 0682338e9f..2a6d829551 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1189,6 +1189,18 @@ Windows 2000 is installed, you no longer need this option (this option slows down the IDE transfers). ETEXI +DEF("no-spurious-interrupt-hack", 0, QEMU_OPTION_no_spurious_interrupt_hack, + "-no-spurious-interrupt-hack disable delivery of spurious interrupts\n", + QEMU_ARCH_I386) +STEXI +@item -no-spurious-interrupt-hack +@findex -no-spurious-interrupt-hack +Use it as a workaround for operating systems that drive PICs in a way that +can generate spurious interrupts, but the OS doesn't handle spurious +interrupts gracefully. (e.g. late 80s/early 90s versions of ATT UNIX +and derivatives) +ETEXI + HXCOMM Deprecated by -rtc DEF("rtc-td-hack", 0, QEMU_OPTION_rtc_td_hack, "", QEMU_ARCH_I386) diff --git a/sysemu.h b/sysemu.h index 65552acee5..0170109e12 100644 --- a/sysemu.h +++ b/sysemu.h @@ -117,6 +117,7 @@ extern int graphic_depth; extern DisplayType display_type; extern const char *keyboard_layout; extern int win2k_install_hack; +extern int no_spurious_interrupt_hack; extern int alt_grab; extern int ctrl_grab; extern int usb_enabled; diff --git a/vl.c b/vl.c index 16d04a2ee2..6de41c124d 100644 --- a/vl.c +++ b/vl.c @@ -204,6 +204,7 @@ CharDriverState *serial_hds[MAX_SERIAL_PORTS]; CharDriverState *parallel_hds[MAX_PARALLEL_PORTS]; CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES]; int win2k_install_hack = 0; +int no_spurious_interrupt_hack = 0; int usb_enabled = 0; int singlestep = 0; int smp_cpus = 1; @@ -3046,6 +3047,9 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_win2k_hack: win2k_install_hack = 1; break; + case QEMU_OPTION_no_spurious_interrupt_hack: + no_spurious_interrupt_hack = 1; + break; case QEMU_OPTION_rtc_td_hack: { static GlobalProperty slew_lost_ticks[] = { { From 9716ef3b1b48ebbb4b6515fb4685a5db96ce41d9 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 26 Aug 2012 14:40:02 +0100 Subject: [PATCH 0105/2270] tcg/arm: Fix broken CONFIG_TCG_PASS_AREG0 code The CONFIG_TCG_PASS_AREG0 code for calling ld/st helpers was broken in that it did not respect the ABI requirement that 64 bit values were passed in even-odd register pairs. The simplest way to fix this is to implement some new utility functions for marshalling function arguments into the correct registers and stack, so that the code which sets up the address and data arguments does not need to care whether there has been a preceding env argument. Signed-off-by: Peter Maydell Signed-off-by: Blue Swirl --- tcg/arm/tcg-target.c | 255 ++++++++++++++++++++++++++----------------- 1 file changed, 153 insertions(+), 102 deletions(-) diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index 4d59a63855..cf0ca3d0b3 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -176,6 +176,13 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) so don't use these. */ tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0); tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1); +#if defined(CONFIG_TCG_PASS_AREG0) && (TARGET_LONG_BITS == 64) + /* If we're passing env to the helper as r0 and need a regpair + * for the address then r2 will be overwritten as we're setting + * up the args to the helper. + */ + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2); +#endif #endif break; case 'L': @@ -197,6 +204,12 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) use these. */ tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0); tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1); +#if defined(CONFIG_SOFTMMU) && \ + defined(CONFIG_TCG_PASS_AREG0) && (TARGET_LONG_BITS == 64) + /* Avoid clashes with registers being used for helper args */ + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2); + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3); +#endif break; /* qemu_st64 data_reg2 */ case 'S': @@ -210,6 +223,10 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) #ifdef CONFIG_SOFTMMU /* r2 is still needed to load data_reg, so don't use it. */ tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2); +#if defined(CONFIG_TCG_PASS_AREG0) && (TARGET_LONG_BITS == 64) + /* Avoid clashes with registers being used for helper args */ + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3); +#endif #endif break; @@ -388,6 +405,14 @@ static inline void tcg_out_dat_reg(TCGContext *s, (rn << 16) | (rd << 12) | shift | rm); } +static inline void tcg_out_mov_reg(TCGContext *s, int cond, int rd, int rm) +{ + /* Simple reg-reg move, optimising out the 'do nothing' case */ + if (rd != rm) { + tcg_out_dat_reg(s, cond, ARITH_MOV, rd, 0, rm, SHIFT_IMM_LSL(0)); + } +} + static inline void tcg_out_dat_reg2(TCGContext *s, int cond, int opc0, int opc1, int rd0, int rd1, int rn0, int rn1, int rm0, int rm1, int shift) @@ -966,6 +991,90 @@ static void *qemu_st_helpers[4] = { __stq_mmu, }; #endif + +/* Helper routines for marshalling helper function arguments into + * the correct registers and stack. + * argreg is where we want to put this argument, arg is the argument itself. + * Return value is the updated argreg ready for the next call. + * Note that argreg 0..3 is real registers, 4+ on stack. + * When we reach the first stacked argument, we allocate space for it + * and the following stacked arguments using "str r8, [sp, #-0x10]!". + * Following arguments are filled in with "str r8, [sp, #0xNN]". + * For more than 4 stacked arguments we'd need to know how much + * space to allocate when we pushed the first stacked argument. + * We don't need this, so don't implement it (and will assert if you try it.) + * + * We provide routines for arguments which are: immediate, 32 bit + * value in register, 16 and 8 bit values in register (which must be zero + * extended before use) and 64 bit value in a lo:hi register pair. + */ +#define DEFINE_TCG_OUT_ARG(NAME, ARGPARAM) \ + static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGPARAM) \ + { \ + if (argreg < 4) { \ + TCG_OUT_ARG_GET_ARG(argreg); \ + } else if (argreg == 4) { \ + TCG_OUT_ARG_GET_ARG(TCG_REG_R8); \ + tcg_out32(s, (COND_AL << 28) | 0x052d8010); \ + } else { \ + assert(argreg < 8); \ + TCG_OUT_ARG_GET_ARG(TCG_REG_R8); \ + tcg_out32(s, (COND_AL << 28) | 0x058d8000 | (argreg - 4) * 4); \ + } \ + return argreg + 1; \ + } + +#define TCG_OUT_ARG_GET_ARG(A) tcg_out_dat_imm(s, COND_AL, ARITH_MOV, A, 0, arg) +DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32, uint32_t arg) +#undef TCG_OUT_ARG_GET_ARG +#define TCG_OUT_ARG_GET_ARG(A) tcg_out_ext8u(s, COND_AL, A, arg) +DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8, TCGReg arg) +#undef TCG_OUT_ARG_GET_ARG +#define TCG_OUT_ARG_GET_ARG(A) tcg_out_ext16u(s, COND_AL, A, arg) +DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16, TCGReg arg) +#undef TCG_OUT_ARG_GET_ARG + +/* We don't use the macro for this one to avoid an unnecessary reg-reg + * move when storing to the stack. + */ +static TCGReg tcg_out_arg_reg32(TCGContext *s, TCGReg argreg, TCGReg arg) +{ + if (argreg < 4) { + tcg_out_mov_reg(s, COND_AL, argreg, arg); + } else if (argreg == 4) { + /* str arg, [sp, #-0x10]! */ + tcg_out32(s, (COND_AL << 28) | 0x052d0010 | (arg << 12)); + } else { + assert(argreg < 8); + /* str arg, [sp, #0xNN] */ + tcg_out32(s, (COND_AL << 28) | 0x058d0000 | + (arg << 12) | (argreg - 4) * 4); + } + return argreg + 1; +} + +static inline TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg, + TCGReg arglo, TCGReg arghi) +{ + /* 64 bit arguments must go in even/odd register pairs + * and in 8-aligned stack slots. + */ + if (argreg & 1) { + argreg++; + } + argreg = tcg_out_arg_reg32(s, argreg, arglo); + argreg = tcg_out_arg_reg32(s, argreg, arghi); + return argreg; +} + +static inline void tcg_out_arg_stacktidy(TCGContext *s, TCGReg argreg) +{ + /* Output any necessary post-call cleanup of the stack */ + if (argreg > 4) { + tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10); + } +} + #endif #define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS) @@ -975,6 +1084,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) int addr_reg, data_reg, data_reg2, bswap; #ifdef CONFIG_SOFTMMU int mem_index, s_bits; + TCGReg argreg; # if TARGET_LONG_BITS == 64 int addr_reg2; # endif @@ -1088,31 +1198,22 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) tcg_out_b_noaddr(s, COND_EQ); /* TODO: move this code to where the constants pool will be */ - if (addr_reg != TCG_REG_R0) { - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0)); - } -# if TARGET_LONG_BITS == 32 - tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R1, 0, mem_index); -# else - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0)); - tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index); -# endif + /* Note that this code relies on the constraints we set in arm_op_defs[] + * to ensure that later arguments are not passed to us in registers we + * trash by moving the earlier arguments into them. + */ + argreg = TCG_REG_R0; #ifdef CONFIG_TCG_PASS_AREG0 - /* XXX/FIXME: suboptimal and incorrect for 64 bit */ - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - tcg_target_call_iarg_regs[2], 0, - tcg_target_call_iarg_regs[1], SHIFT_IMM_LSL(0)); - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - tcg_target_call_iarg_regs[1], 0, - tcg_target_call_iarg_regs[0], SHIFT_IMM_LSL(0)); - - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - tcg_target_call_iarg_regs[0], 0, TCG_AREG0, - SHIFT_IMM_LSL(0)); + argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0); #endif +#if TARGET_LONG_BITS == 64 + argreg = tcg_out_arg_reg64(s, argreg, addr_reg, addr_reg2); +#else + argreg = tcg_out_arg_reg32(s, argreg, addr_reg); +#endif + argreg = tcg_out_arg_imm32(s, argreg, mem_index); tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[s_bits]); + tcg_out_arg_stacktidy(s, argreg); switch (opc) { case 0 | 4: @@ -1211,6 +1312,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) int addr_reg, data_reg, data_reg2, bswap; #ifdef CONFIG_SOFTMMU int mem_index, s_bits; + TCGReg argreg; # if TARGET_LONG_BITS == 64 int addr_reg2; # endif @@ -1314,89 +1416,38 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) tcg_out_b_noaddr(s, COND_EQ); /* TODO: move this code to where the constants pool will be */ - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0)); -# if TARGET_LONG_BITS == 32 - switch (opc) { - case 0: - tcg_out_ext8u(s, COND_AL, TCG_REG_R1, data_reg); - tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index); - break; - case 1: - tcg_out_ext16u(s, COND_AL, TCG_REG_R1, data_reg); - tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index); - break; - case 2: - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(0)); - tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index); - break; - case 3: - tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R8, 0, mem_index); - tcg_out32(s, (COND_AL << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */ - if (data_reg != TCG_REG_R2) { - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0)); - } - if (data_reg2 != TCG_REG_R3) { - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - TCG_REG_R3, 0, data_reg2, SHIFT_IMM_LSL(0)); - } - break; - } -# else - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0)); - switch (opc) { - case 0: - tcg_out_ext8u(s, COND_AL, TCG_REG_R2, data_reg); - tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index); - break; - case 1: - tcg_out_ext16u(s, COND_AL, TCG_REG_R2, data_reg); - tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index); - break; - case 2: - if (data_reg != TCG_REG_R2) { - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0)); - } - tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index); - break; - case 3: - tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R8, 0, mem_index); - tcg_out32(s, (COND_AL << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */ - if (data_reg != TCG_REG_R2) { - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0)); - } - if (data_reg2 != TCG_REG_R3) { - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - TCG_REG_R3, 0, data_reg2, SHIFT_IMM_LSL(0)); - } - break; - } -# endif - + /* Note that this code relies on the constraints we set in arm_op_defs[] + * to ensure that later arguments are not passed to us in registers we + * trash by moving the earlier arguments into them. + */ + argreg = TCG_REG_R0; #ifdef CONFIG_TCG_PASS_AREG0 - /* XXX/FIXME: suboptimal and incorrect for 64 bit */ - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - tcg_target_call_iarg_regs[3], 0, - tcg_target_call_iarg_regs[2], SHIFT_IMM_LSL(0)); - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - tcg_target_call_iarg_regs[2], 0, - tcg_target_call_iarg_regs[1], SHIFT_IMM_LSL(0)); - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - tcg_target_call_iarg_regs[1], 0, - tcg_target_call_iarg_regs[0], SHIFT_IMM_LSL(0)); - - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - tcg_target_call_iarg_regs[0], 0, TCG_AREG0, - SHIFT_IMM_LSL(0)); + argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0); #endif +#if TARGET_LONG_BITS == 64 + argreg = tcg_out_arg_reg64(s, argreg, addr_reg, addr_reg2); +#else + argreg = tcg_out_arg_reg32(s, argreg, addr_reg); +#endif + + switch (opc) { + case 0: + argreg = tcg_out_arg_reg8(s, argreg, data_reg); + break; + case 1: + argreg = tcg_out_arg_reg16(s, argreg, data_reg); + break; + case 2: + argreg = tcg_out_arg_reg32(s, argreg, data_reg); + break; + case 3: + argreg = tcg_out_arg_reg64(s, argreg, data_reg, data_reg2); + break; + } + + argreg = tcg_out_arg_imm32(s, argreg, mem_index); tcg_out_call(s, (tcg_target_long) qemu_st_helpers[s_bits]); - if (opc == 3) - tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10); + tcg_out_arg_stacktidy(s, argreg); reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr); #else /* !CONFIG_SOFTMMU */ From 18d445b443a5fa06a7c2819a170623b970afb3fb Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 25 Aug 2012 23:59:58 +0200 Subject: [PATCH 0106/2270] tcg/ia64: fix prologue/epilogue Prologue and epilogue code has been broken in cea5f9a28. Signed-off-by: Aurelien Jarno --- tcg/ia64/tcg-target.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index e02dacc84f..b3c7db0f98 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -107,7 +107,7 @@ enum { }; static const int tcg_target_reg_alloc_order[] = { - TCG_REG_R34, + TCG_REG_R33, TCG_REG_R35, TCG_REG_R36, TCG_REG_R37, @@ -2314,13 +2314,13 @@ static void tcg_target_qemu_prologue(TCGContext *s) s->code_ptr += 16; /* skip GP */ /* prologue */ - tcg_out_bundle(s, mII, + tcg_out_bundle(s, miI, tcg_opc_m34(TCG_REG_P0, OPC_ALLOC_M34, - TCG_REG_R33, 32, 24, 0), + TCG_REG_R34, 32, 24, 0), + tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4, + TCG_AREG0, 0, TCG_REG_R32), tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21, - TCG_REG_B6, TCG_REG_R33, 0), - tcg_opc_i22(TCG_REG_P0, OPC_MOV_I22, - TCG_REG_R32, TCG_REG_B0)); + TCG_REG_B6, TCG_REG_R33, 0)); /* ??? If GUEST_BASE < 0x200000, we could load the register via an ADDL in the M slot of the next bundle. */ @@ -2334,10 +2334,10 @@ static void tcg_target_qemu_prologue(TCGContext *s) } tcg_out_bundle(s, miB, - tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4, - TCG_AREG0, 0, TCG_REG_R32), tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4, TCG_REG_R12, -frame_size, TCG_REG_R12), + tcg_opc_i22(TCG_REG_P0, OPC_MOV_I22, + TCG_REG_R32, TCG_REG_B0), tcg_opc_b4 (TCG_REG_P0, OPC_BR_SPTK_MANY_B4, TCG_REG_B6)); /* epilogue */ @@ -2351,7 +2351,7 @@ static void tcg_target_qemu_prologue(TCGContext *s) tcg_out_bundle(s, miB, tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), tcg_opc_i26(TCG_REG_P0, OPC_MOV_I_I26, - TCG_REG_PFS, TCG_REG_R33), + TCG_REG_PFS, TCG_REG_R34), tcg_opc_b4 (TCG_REG_P0, OPC_BR_RET_SPTK_MANY_B4, TCG_REG_B0)); } @@ -2403,7 +2403,7 @@ static void tcg_target_init(TCGContext *s) tcg_regset_set_reg(s->reserved_regs, TCG_REG_R12); /* stack pointer */ tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13); /* thread pointer */ tcg_regset_set_reg(s->reserved_regs, TCG_REG_R32); /* return address */ - tcg_regset_set_reg(s->reserved_regs, TCG_REG_R33); /* PFS */ + tcg_regset_set_reg(s->reserved_regs, TCG_REG_R34); /* PFS */ /* The following 3 are not in use, are call-saved, but *not* saved by the prologue. Therefore we cannot use them without modifying From d03c98d80ffb7c561d9e6874580f52fe7ecc8c6c Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 Aug 2012 00:45:27 +0200 Subject: [PATCH 0107/2270] tcg/ia64: fix and optimize ld/st slow path Store slow path has been broken in e141ab52d: - the arguments are shifted before the last one (mem_index) is written. - the shift is done for both slow and fast paths. Fix that. Also optimize a bit by bundling the move together. This still can be optimized, but it's better to wait for a decision to be taken on the arguments order. Signed-off-by: Aurelien Jarno --- tcg/ia64/tcg-target.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index b3c7db0f98..dc588dbea5 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1532,12 +1532,13 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) } #ifdef CONFIG_TCG_PASS_AREG0 /* XXX/FIXME: suboptimal */ - tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], - tcg_target_call_iarg_regs[1]); - tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1], - tcg_target_call_iarg_regs[0]); - tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], - TCG_AREG0); + tcg_out_bundle(s, mII, + tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R58, + mem_index, TCG_REG_R0), + tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, + TCG_REG_R57, 0, TCG_REG_R56), + tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, + TCG_REG_R56, 0, TCG_AREG0)); #endif if (!bswap || s_bits == 0) { tcg_out_bundle(s, miB, @@ -1659,15 +1660,21 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) #ifdef CONFIG_TCG_PASS_AREG0 /* XXX/FIXME: suboptimal */ - tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3], - tcg_target_call_iarg_regs[2]); - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], - tcg_target_call_iarg_regs[1]); - tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1], - tcg_target_call_iarg_regs[0]); - tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], - TCG_AREG0); -#endif + tcg_out_bundle(s, mII, + tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R59, + mem_index, TCG_REG_R0), + tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, + TCG_REG_R58, 0, TCG_REG_R57), + tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, + TCG_REG_R57, 0, TCG_REG_R56)); + tcg_out_bundle(s, miB, + tcg_opc_m4 (TCG_REG_P6, opc_st_m4[opc], + data_reg, TCG_REG_R3), + tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, + TCG_REG_R56, 0, TCG_AREG0), + tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, + TCG_REG_B0, TCG_REG_B6)); +#else tcg_out_bundle(s, miB, tcg_opc_m4 (TCG_REG_P6, opc_st_m4[opc], data_reg, TCG_REG_R3), @@ -1675,6 +1682,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) mem_index, TCG_REG_R0), tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, TCG_REG_B0, TCG_REG_B6)); +#endif } #else /* !CONFIG_SOFTMMU */ From 42644cee08f85202f5d3e8babf6503487849353a Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Mon, 21 May 2012 21:56:19 +0200 Subject: [PATCH 0108/2270] linux-user: arg_table need not have global scope Declare arg_table to be "static const", and adjust the two users to also be const. Signed-off-by: Jim Meyering Signed-off-by: Riku Voipio --- linux-user/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 7dea084873..b1c228a249 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3222,7 +3222,7 @@ struct qemu_argument { const char *help; }; -struct qemu_argument arg_table[] = { +static const struct qemu_argument arg_table[] = { {"h", "", false, handle_arg_help, "", "print this help"}, {"g", "QEMU_GDB", true, handle_arg_gdb, @@ -3264,7 +3264,7 @@ struct qemu_argument arg_table[] = { static void usage(void) { - struct qemu_argument *arginfo; + const struct qemu_argument *arginfo; int maxarglen; int maxenvlen; @@ -3330,7 +3330,7 @@ static int parse_args(int argc, char **argv) { const char *r; int optind; - struct qemu_argument *arginfo; + const struct qemu_argument *arginfo; for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { if (arginfo->env == NULL) { From 333858b77c2b4f7636257808a77822c58bdd80fe Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Tue, 21 Aug 2012 02:13:12 +0400 Subject: [PATCH 0109/2270] linux-user: fix emulation of getdents In case when TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64, the last byte of the target dirent structure (aka d_type byte) was never copied from the host dirent structure, thus breaking everything that relies on valid d_type value, e.g. glob(3). Reviewed-by: Peter Maydell Signed-off-by: Dmitry V. Levin Signed-off-by: Riku Voipio --- linux-user/syscall.c | 11 +++++------ linux-user/syscall_defs.h | 8 ++++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 11743065e9..6257a04d0a 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7025,15 +7025,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, tde = target_dirp; while (len > 0) { reclen = de->d_reclen; - treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long))); + tnamelen = reclen - offsetof(struct linux_dirent, d_name); + assert(tnamelen >= 0); + treclen = tnamelen + offsetof(struct target_dirent, d_name); + assert(count1 + treclen <= count); tde->d_reclen = tswap16(treclen); tde->d_ino = tswapal(de->d_ino); tde->d_off = tswapal(de->d_off); - tnamelen = treclen - (2 * sizeof(abi_long) + 2); - if (tnamelen > 256) - tnamelen = 256; - /* XXX: may not be correct */ - pstrcpy(tde->d_name, tnamelen, de->d_name); + memcpy(tde->d_name, de->d_name, tnamelen); de = (struct linux_dirent *)((char *)de + reclen); len -= reclen; tde = (struct target_dirent *)((char *)tde + treclen); diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 2cfda5afd5..a98cbf7b80 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -255,10 +255,10 @@ struct kernel_statfs { }; struct target_dirent { - abi_long d_ino; - abi_long d_off; - unsigned short d_reclen; - char d_name[256]; /* We must not include limits.h! */ + abi_long d_ino; + abi_long d_off; + unsigned short d_reclen; + char d_name[]; }; struct target_dirent64 { From 097b8cb840a31ec526cc58778bd8cbab0d2beaaa Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 20 Aug 2012 11:36:32 +0100 Subject: [PATCH 0110/2270] linux-user: Clarify "Unable to reserve guest address space" error Now that we default to reserving nearly 4GB of RAM for the guest address space when running a 32 bit linux-user guest on 64 bit hosts, users are much more likely to run into it. Reword the message to be more informative about what failed and provide suggestions for how to fix things. Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/linux-user/main.c b/linux-user/main.c index b1c228a249..1a1c661ee4 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3519,7 +3519,10 @@ int main(int argc, char **argv, char **envp) guest_base = init_guest_space(guest_base, reserved_va, 0, have_guest_base); if (guest_base == (unsigned long)-1) { - fprintf(stderr, "Unable to reserve guest address space\n"); + fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address " + "space for use as guest address space (check your virtual " + "memory ulimit setting or reserve less using -R option)\n", + reserved_va); exit(1); } From d22d7289877ecd3ef86570f6f6d0574da40711dc Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Mon, 27 Aug 2012 09:50:38 +0100 Subject: [PATCH 0111/2270] Fix operands of RECIP2.S and RECIP2.PS Read the second input operand of RECIP2.S and RECIP2.PS from FT rather than FD. RECIP2.D is already correct. Signed-off-by: Richard Sandiford Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index d643676e58..2589f63b35 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -6805,7 +6805,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i32 fp1 = tcg_temp_new_i32(); gen_load_fpr32(fp0, fs); - gen_load_fpr32(fp1, fd); + gen_load_fpr32(fp1, ft); gen_helper_float_recip2_s(fp0, fp0, fp1); tcg_temp_free_i32(fp1); gen_store_fpr32(fp0, fd); @@ -7543,7 +7543,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp1 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_load_fpr64(ctx, fp1, fd); + gen_load_fpr64(ctx, fp1, ft); gen_helper_float_recip2_ps(fp0, fp0, fp1); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp0, fd); From 13d24f49720a3e7b35a21222ef182c8513f139db Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Mon, 27 Aug 2012 09:53:29 +0100 Subject: [PATCH 0112/2270] Fix order of CVT.PS.S operands The FS input to CVT.PS.S is the high half and FT is the low half. tcg_gen_concat_i32_i64 takes the low half first, so the operands were in the wrong order. Signed-off-by: Richard Sandiford Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 2589f63b35..d8129864ed 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -6900,7 +6900,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr32(fp32_0, fs); gen_load_fpr32(fp32_1, ft); - tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1); + tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0); tcg_temp_free_i32(fp32_1); tcg_temp_free_i32(fp32_0); gen_store_fpr64(ctx, fp64, fd); From 05168674505153a641c7bfddb691d2eda11d13d1 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 30 Mar 2012 13:16:36 -0400 Subject: [PATCH 0113/2270] target-mips: Streamline indexed cp1 memory addressing. We've already eliminated both base and index being zero. Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index d8129864ed..f740a08320 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -7742,8 +7742,7 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, } else if (index == 0) { gen_load_gpr(t0, base); } else { - gen_load_gpr(t0, index); - gen_op_addr_add(ctx, t0, cpu_gpr[base], t0); + gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]); } /* Don't do NOP if destination is zero: we must perform the actual memory access. */ From b3167288367f79754b74ad933146e37938ebff13 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 30 Mar 2012 13:16:37 -0400 Subject: [PATCH 0114/2270] mips-linux-user: Always support rdhwr. The kernel will emulate this instruction if it's not supported natively. This insn is used for TLS, among other things, and so is required by modern glibc. Signed-off-by: Richard Henderson Cc: Riku Voipio Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target-mips/translate.c b/target-mips/translate.c index f740a08320..35624e9da1 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -8111,7 +8111,11 @@ gen_rdhwr (CPUMIPSState *env, DisasContext *ctx, int rt, int rd) { TCGv t0; +#if !defined(CONFIG_USER_ONLY) + /* The Linux kernel will emulate rdhwr if it's not supported natively. + Therefore only check the ISA in system mode. */ check_insn(env, ctx, ISA_MIPS32R2); +#endif t0 = tcg_temp_new(); switch (rd) { From 4f213879f3cc695644cfd8bf603495e7316c78f6 Mon Sep 17 00:00:00 2001 From: malc Date: Mon, 27 Aug 2012 18:33:12 +0400 Subject: [PATCH 0115/2270] Revert "i8259: add -no-spurious-interrupt-hack option" This reverts commit f278d4947fff814dcde2ef2acad36d172ff8be35. Signed-off-by: malc --- cpu-exec.c | 14 +++++--------- hw/i8259.c | 18 ------------------ qemu-options.hx | 12 ------------ sysemu.h | 1 - vl.c | 4 ---- 5 files changed, 5 insertions(+), 44 deletions(-) diff --git a/cpu-exec.c b/cpu-exec.c index 625fbb0e0f..134b3c4fcf 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -329,15 +329,11 @@ int cpu_exec(CPUArchState *env) 0); env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ); intno = cpu_get_pic_interrupt(env); - if (intno >= 0) { - qemu_log_mask(CPU_LOG_TB_IN_ASM, - "Servicing hardware INT=0x%02x\n", - intno); - do_interrupt_x86_hardirq(env, intno, 1); - /* ensure that no TB jump will be modified as - the program flow was changed */ - next_tb = 0; - } + qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno); + do_interrupt_x86_hardirq(env, intno, 1); + /* ensure that no TB jump will be modified as + the program flow was changed */ + next_tb = 0; #if !defined(CONFIG_USER_ONLY) } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) && (env->eflags & IF_MASK) && diff --git a/hw/i8259.c b/hw/i8259.c index 7ecb7e1de6..65876662a1 100644 --- a/hw/i8259.c +++ b/hw/i8259.c @@ -26,7 +26,6 @@ #include "isa.h" #include "monitor.h" #include "qemu-timer.h" -#include "sysemu.h" #include "i8259_internal.h" /* debug PIC */ @@ -194,20 +193,6 @@ int pic_read_irq(DeviceState *d) pic_intack(slave_pic, irq2); } else { /* spurious IRQ on slave controller */ - if (no_spurious_interrupt_hack) { - /* Pretend it was delivered and acknowledged. If - * it was spurious due to slave_pic->imr, then - * as soon as the mask is cleared, the slave will - * re-trigger IRQ2 on the master. If it is spurious for - * some other reason, make sure we don't keep trying - * to half-process the same spurious interrupt over - * and over again. - */ - s->irr &= ~(1<last_irr &= ~(1<isr &= ~(1<irq_base + irq2; @@ -217,9 +202,6 @@ int pic_read_irq(DeviceState *d) pic_intack(s, irq); } else { /* spurious IRQ on host controller */ - if (no_spurious_interrupt_hack) { - return -1; - } irq = 7; intno = s->irq_base + irq; } diff --git a/qemu-options.hx b/qemu-options.hx index 2a6d829551..0682338e9f 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1189,18 +1189,6 @@ Windows 2000 is installed, you no longer need this option (this option slows down the IDE transfers). ETEXI -DEF("no-spurious-interrupt-hack", 0, QEMU_OPTION_no_spurious_interrupt_hack, - "-no-spurious-interrupt-hack disable delivery of spurious interrupts\n", - QEMU_ARCH_I386) -STEXI -@item -no-spurious-interrupt-hack -@findex -no-spurious-interrupt-hack -Use it as a workaround for operating systems that drive PICs in a way that -can generate spurious interrupts, but the OS doesn't handle spurious -interrupts gracefully. (e.g. late 80s/early 90s versions of ATT UNIX -and derivatives) -ETEXI - HXCOMM Deprecated by -rtc DEF("rtc-td-hack", 0, QEMU_OPTION_rtc_td_hack, "", QEMU_ARCH_I386) diff --git a/sysemu.h b/sysemu.h index 0170109e12..65552acee5 100644 --- a/sysemu.h +++ b/sysemu.h @@ -117,7 +117,6 @@ extern int graphic_depth; extern DisplayType display_type; extern const char *keyboard_layout; extern int win2k_install_hack; -extern int no_spurious_interrupt_hack; extern int alt_grab; extern int ctrl_grab; extern int usb_enabled; diff --git a/vl.c b/vl.c index 6de41c124d..16d04a2ee2 100644 --- a/vl.c +++ b/vl.c @@ -204,7 +204,6 @@ CharDriverState *serial_hds[MAX_SERIAL_PORTS]; CharDriverState *parallel_hds[MAX_PARALLEL_PORTS]; CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES]; int win2k_install_hack = 0; -int no_spurious_interrupt_hack = 0; int usb_enabled = 0; int singlestep = 0; int smp_cpus = 1; @@ -3047,9 +3046,6 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_win2k_hack: win2k_install_hack = 1; break; - case QEMU_OPTION_no_spurious_interrupt_hack: - no_spurious_interrupt_hack = 1; - break; case QEMU_OPTION_rtc_td_hack: { static GlobalProperty slew_lost_ticks[] = { { From df8002103c3e262dc40d7b5e0eb2171ba28b1d63 Mon Sep 17 00:00:00 2001 From: malc Date: Mon, 27 Aug 2012 18:33:20 +0400 Subject: [PATCH 0116/2270] Revert "vga: add some optional CGA compatibility hacks" This reverts commit 482f7bf86b43af9f6903c52726fedf82b28bf953. Signed-off-by: malc --- hw/pc.h | 4 ---- hw/vga.c | 36 ++++++++---------------------------- qemu-options.hx | 19 ------------------- vl.c | 23 ----------------------- 4 files changed, 8 insertions(+), 74 deletions(-) diff --git a/hw/pc.h b/hw/pc.h index 37e2f87583..e4db0715b8 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -176,10 +176,6 @@ enum vga_retrace_method { extern enum vga_retrace_method vga_retrace_method; -#define VGA_CGA_HACK_PALETTE_BLANKING (1<<0) -#define VGA_CGA_HACK_FONT_HEIGHT (1<<1) -extern int vga_cga_hacks; - static inline DeviceState *isa_vga_init(ISABus *bus) { ISADevice *dev; diff --git a/hw/vga.c b/hw/vga.c index a65fc26ab7..f82ced8e66 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -547,31 +547,14 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) printf("vga: write CR%x = 0x%02x\n", s->cr_index, val); #endif /* handle CR0-7 protection */ - if (s->cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) { - if (s->cr_index <= VGA_CRTC_OVERFLOW) { - /* can always write bit 4 of CR7 */ - if (s->cr_index == VGA_CRTC_OVERFLOW) { - s->cr[VGA_CRTC_OVERFLOW] = - (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) | (val & 0x10); - } - return; - } else if ((vga_cga_hacks & VGA_CGA_HACK_FONT_HEIGHT) && - !(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) { - /* extra CGA compatibility hacks (not in standard VGA) */ - if (s->cr_index == VGA_CRTC_MAX_SCAN && - val == 7 && - (s->cr[VGA_CRTC_MAX_SCAN] & 0xf) == 0xf) { - return; - } else if (s->cr_index == VGA_CRTC_CURSOR_START && - val == 6 && - (s->cr[VGA_CRTC_MAX_SCAN] & 0xf) == 0xf) { - val = 0xd; - } else if (s->cr_index == VGA_CRTC_CURSOR_END && - val == 7 && - (s->cr[VGA_CRTC_MAX_SCAN] & 0xf) == 0xf) { - val = 0xe; - } + if ((s->cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) && + s->cr_index <= VGA_CRTC_OVERFLOW) { + /* can always write bit 4 of CR7 */ + if (s->cr_index == VGA_CRTC_OVERFLOW) { + s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) | + (val & 0x10); } + return; } s->cr[s->cr_index] = val; @@ -1903,10 +1886,7 @@ static void vga_update_display(void *opaque) /* nothing to do */ } else { full_update = 0; - if (!(s->ar_index & 0x20) && - /* extra CGA compatibility hacks (not in standard VGA */ - (!(vga_cga_hacks & VGA_CGA_HACK_PALETTE_BLANKING) || - (s->ar_index != 0 && s->ar_flip_flop))) { + if (!(s->ar_index & 0x20)) { graphic_mode = GMODE_BLANK; } else { graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE; diff --git a/qemu-options.hx b/qemu-options.hx index 0682338e9f..3e8085d463 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -975,25 +975,6 @@ Valid optional properties are @item retrace=dumb|precise Select dumb (default) or precise VGA retrace logic, useful for some DOS games/demos. -@item cga_hacks=@var{hack1}[+@var{hack2},[...]] -Enable various extra CGA compatibility hacks for programs that are -trying to directly set CGA modes without BIOS assistance nor -real knowledge of EGA/VGA. These might only work with -vga std. -Valid hacks are -@table @option -@item palette_blanking -Wait to blank the screen until palette registers seem to actually be -modified, instead of blanking it as soon as the palette address bit (0x10) -of the attribute address register (0x3c0) is cleared. -@item font_height -Ignore attempts to change the VGA font height (index 9), -cursor start (index 10), and cursor end (index 11) of the CRTC control -registers (0x3d5) if trying to set them to the default for CGA fonts -instead of VGA fonts. -@item all -Enable all CGA hacks. More CGA hacks may be added in future versions -of qemu. -@end table @end table ETEXI diff --git a/vl.c b/vl.c index 16d04a2ee2..febfd62c37 100644 --- a/vl.c +++ b/vl.c @@ -179,7 +179,6 @@ int main(int argc, char **argv) static const char *data_dir; const char *bios_name = NULL; enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; -int vga_cga_hacks = 0; DisplayType display_type = DT_DEFAULT; int display_remote = 0; const char* keyboard_layout = NULL; @@ -1749,28 +1748,6 @@ static void select_vgahw (const char *p) else if (strstart(opts, "precise", &nextopt)) vga_retrace_method = VGA_RETRACE_PRECISE; else goto invalid_vga; - } else if (strstart(opts, ",cga_hacks=", &nextopt)) { - opts = nextopt; - while (*opts) { - if (strstart(opts, "all", &nextopt)) { - opts = nextopt; - vga_cga_hacks |= ~0; - } else if (strstart(opts, "palette_blanking", &nextopt)) { - opts = nextopt; - vga_cga_hacks |= VGA_CGA_HACK_PALETTE_BLANKING; - } else if (strstart(opts, "font_height", &nextopt)) { - opts = nextopt; - vga_cga_hacks |= VGA_CGA_HACK_FONT_HEIGHT; - } else { - break; - } - - if (*opts == '+') { - opts++; - } else { - break; - } - } } else goto invalid_vga; opts = nextopt; } From e4558dcae8b9fcb2bcc312f1d04071b34adf0781 Mon Sep 17 00:00:00 2001 From: malc Date: Mon, 27 Aug 2012 18:33:21 +0400 Subject: [PATCH 0117/2270] Revert "qemu-options.hx: mention retrace= VGA option" This reverts commit 39dda260628e5f2a3fd2ce2ec8a71f3d5ca309a9. Signed-off-by: malc --- qemu-options.hx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index 3e8085d463..3c411c427e 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -945,7 +945,7 @@ DEF("vga", HAS_ARG, QEMU_OPTION_vga, "-vga [std|cirrus|vmware|qxl|xenfb|none]\n" " select video card type\n", QEMU_ARCH_ALL) STEXI -@item -vga @var{type}[,@var{prop}=@var{value}[,...]] +@item -vga @var{type} @findex -vga Select type of VGA card to emulate. Valid values for @var{type} are @table @option @@ -970,12 +970,6 @@ Recommended choice when using the spice protocol. @item none Disable VGA card. @end table -Valid optional properties are -@table @option -@item retrace=dumb|precise -Select dumb (default) or precise VGA retrace logic, useful for some -DOS games/demos. -@end table ETEXI DEF("full-screen", 0, QEMU_OPTION_full_screen, From 9f227bc3583ea082be7a79c14a5ffdade5844753 Mon Sep 17 00:00:00 2001 From: malc Date: Mon, 27 Aug 2012 18:33:22 +0400 Subject: [PATCH 0118/2270] Revert "vl: fix -hdachs/-hda argument order parsing issues" This reverts commit 7764ae9671f1cd74227cf4404431dd5213799ef0. Signed-off-by: malc --- vl.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/vl.c b/vl.c index febfd62c37..7c577fa544 100644 --- a/vl.c +++ b/vl.c @@ -2352,9 +2352,8 @@ int main(int argc, char **argv, char **envp) char boot_devices[33] = "cad"; /* default to HD->floppy->CD-ROM */ DisplayState *ds; DisplayChangeListener *dcl; - char hdachs_params[512]; /* save -hdachs to apply to later -hda */ - QemuOpts *hda_opts = NULL; /* save -hda to be modified by later -hdachs */ - QemuOpts *opts, *machine_opts; + int cyls, heads, secs, translation; + QemuOpts *hda_opts = NULL, *opts, *machine_opts; QemuOptsList *olist; int optind; const char *optarg; @@ -2409,7 +2408,8 @@ int main(int argc, char **argv, char **envp) cpu_model = NULL; ram_size = 0; snapshot = 0; - snprintf(hdachs_params, sizeof(hdachs_params), "%s", HD_OPTS); + cyls = heads = secs = 0; + translation = BIOS_ATA_TRANSLATION_AUTO; for (i = 0; i < MAX_NODES; i++) { node_mem[i] = 0; @@ -2457,7 +2457,7 @@ int main(int argc, char **argv, char **envp) if (optind >= argc) break; if (argv[optind][0] != '-') { - hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++], hdachs_params); + hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS); } else { const QEMUOption *popt; @@ -2475,8 +2475,21 @@ int main(int argc, char **argv, char **envp) cpu_model = optarg; break; case QEMU_OPTION_hda: - hda_opts = drive_add(IF_DEFAULT, 0, optarg, hdachs_params); - break; + { + char buf[256]; + if (cyls == 0) + snprintf(buf, sizeof(buf), "%s", HD_OPTS); + else + snprintf(buf, sizeof(buf), + "%s,cyls=%d,heads=%d,secs=%d%s", + HD_OPTS , cyls, heads, secs, + translation == BIOS_ATA_TRANSLATION_LBA ? + ",trans=lba" : + translation == BIOS_ATA_TRANSLATION_NONE ? + ",trans=none" : ""); + drive_add(IF_DEFAULT, 0, optarg, buf); + break; + } case QEMU_OPTION_hdb: case QEMU_OPTION_hdc: case QEMU_OPTION_hdd: @@ -2510,10 +2523,7 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_hdachs: { - int cyls, heads, secs, translation; const char *p; - cyls = heads = secs = 0; - translation = BIOS_ATA_TRANSLATION_AUTO; p = optarg; cyls = strtol(p, (char **)&p, 0); if (cyls < 1 || cyls > 16383) @@ -2545,14 +2555,7 @@ int main(int argc, char **argv, char **envp) fprintf(stderr, "qemu: invalid physical CHS format\n"); exit(1); } - snprintf(hdachs_params, sizeof(hdachs_params), - "%s,cyls=%d,heads=%d,secs=%d%s", - HD_OPTS , cyls, heads, secs, - translation == BIOS_ATA_TRANSLATION_LBA ? - ",trans=lba" : - translation == BIOS_ATA_TRANSLATION_NONE ? - ",trans=none" : ""); - if (hda_opts != NULL) { + if (hda_opts != NULL) { char num[16]; snprintf(num, sizeof(num), "%d", cyls); qemu_opt_set(hda_opts, "cyls", num); From 08406b035edc35fff4e3e14af3ec6f8f3a17a587 Mon Sep 17 00:00:00 2001 From: malc Date: Mon, 27 Aug 2012 18:33:24 +0400 Subject: [PATCH 0119/2270] Revert "fix some debug printf format strings" This reverts commit 145c7c880ff520a9348cc2401ba291330b9606fe. Signed-off-by: malc --- hw/cirrus_vga.c | 4 ++-- hw/i8259.c | 3 +-- hw/ide/cmd646.c | 5 ++--- hw/ide/via.c | 5 ++--- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index 909899dd54..e8dcc6b883 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -2055,8 +2055,8 @@ static void cirrus_vga_mem_write(void *opaque, } } else { #ifdef DEBUG_CIRRUS - printf("cirrus: mem_writeb " TARGET_FMT_plx " value %" PRIx64 "\n", - addr, mem_value); + printf("cirrus: mem_writeb " TARGET_FMT_plx " value %02x\n", addr, + mem_value); #endif } } diff --git a/hw/i8259.c b/hw/i8259.c index 65876662a1..53daf78652 100644 --- a/hw/i8259.c +++ b/hw/i8259.c @@ -355,8 +355,7 @@ static uint64_t pic_ioport_read(void *opaque, target_phys_addr_t addr, ret = s->imr; } } - DPRINTF("read: addr=0x%02" TARGET_PRIxPHYS " val=0x%02x\n", - addr, ret); + DPRINTF("read: addr=0x%02x val=0x%02x\n", addr, ret); return ret; } diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index dd2855e19d..e0b9443496 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -154,7 +154,7 @@ static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr, break; } #ifdef DEBUG_IDE - printf("bmdma: readb 0x%02" TARGET_PRIxPHYS " : 0x%02x\n", addr, val); + printf("bmdma: readb 0x%02x : 0x%02x\n", addr, val); #endif return val; } @@ -170,8 +170,7 @@ static void bmdma_write(void *opaque, target_phys_addr_t addr, } #ifdef DEBUG_IDE - printf("bmdma: writeb 0x%02" TARGET_PRIxPHYS " : 0x%02" PRIx64 "\n", - addr, val); + printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val); #endif switch(addr & 3) { case 0: diff --git a/hw/ide/via.c b/hw/ide/via.c index 948a46938a..b20e4f094e 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -55,7 +55,7 @@ static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr, break; } #ifdef DEBUG_IDE - printf("bmdma: readb 0x%02" TARGET_PRIxPHYS " : 0x%02x\n", addr, val); + printf("bmdma: readb 0x%02x : 0x%02x\n", addr, val); #endif return val; } @@ -70,8 +70,7 @@ static void bmdma_write(void *opaque, target_phys_addr_t addr, } #ifdef DEBUG_IDE - printf("bmdma: writeb 0x%02" TARGET_PRIxPHYS " : 0x%02" PRIx64 "\n", - addr, val); + printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val); #endif switch (addr & 3) { case 0: From 2e15497c5b8d0d172dece0cf56e2d2e977a6b679 Mon Sep 17 00:00:00 2001 From: Eric Johnson Date: Sat, 17 Sep 2011 17:05:32 -0700 Subject: [PATCH 0120/2270] target-mips: add privilege level check to several Cop0 instructions The MIPS Architecture Verification Programs (AVPs) check privileged instructions for the required privilege level. These changes are needed to pass the AVP suite. Signed-off-by: Eric Johnson Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/target-mips/translate.c b/target-mips/translate.c index 35624e9da1..0cff905db7 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -5933,6 +5933,7 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, { const char *opn = "ldst"; + check_cp0_enabled(ctx); switch (opc) { case OPC_MFC0: if (rt == 0) { @@ -10121,6 +10122,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs, #ifndef CONFIG_USER_ONLY case MFC0: case MFC0 + 32: + check_cp0_enabled(ctx); if (rt == 0) { /* Treat as NOP. */ break; @@ -10129,6 +10131,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs, break; case MTC0: case MTC0 + 32: + check_cp0_enabled(ctx); { TCGv t0 = tcg_temp_new(); @@ -10225,10 +10228,12 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs, case 0x05: switch (minor) { case RDPGPR: + check_cp0_enabled(ctx); check_insn(env, ctx, ISA_MIPS32R2); gen_load_srsgpr(rt, rs); break; case WRPGPR: + check_cp0_enabled(ctx); check_insn(env, ctx, ISA_MIPS32R2); gen_store_srsgpr(rt, rs); break; @@ -10269,6 +10274,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs, case 0x1d: switch (minor) { case DI: + check_cp0_enabled(ctx); { TCGv t0 = tcg_temp_new(); @@ -10281,6 +10287,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs, } break; case EI: + check_cp0_enabled(ctx); { TCGv t0 = tcg_temp_new(); @@ -10761,6 +10768,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, minor = (ctx->opcode >> 12) & 0xf; switch (minor) { case CACHE: + check_cp0_enabled(ctx); /* Treat as no-op. */ break; case LWC2: @@ -12211,6 +12219,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) gen_st_cond(ctx, op, rt, rs, imm); break; case OPC_CACHE: + check_cp0_enabled(ctx); check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32); /* Treat as NOP. */ break; From 36c6711bbe79642b0102416a9dd4243505e874a6 Mon Sep 17 00:00:00 2001 From: Eric Johnson Date: Sat, 17 Sep 2011 17:28:16 -0700 Subject: [PATCH 0121/2270] target-mips: allow microMIPS SWP and SDP to have RD equal to BASE The microMIPS SWP and SDP instructions do not modify GPRs. So their behavior is well defined when RD equals BASE. The MIPS Architecture Verification Programs (AVPs) check that they work as expected. This is required for AVPs to pass. Signed-off-by: Eric Johnson Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 0cff905db7..b293419536 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -10031,7 +10031,7 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, const char *opn = "ldst_pair"; TCGv t0, t1; - if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) { + if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) { generate_exception(ctx, EXCP_RI); return; } @@ -10043,6 +10043,10 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, switch (opc) { case LWP: + if (rd == base) { + generate_exception(ctx, EXCP_RI); + return; + } save_cpu_state(ctx, 0); op_ld_lw(t1, t0, ctx); gen_store_gpr(t1, rd); @@ -10064,6 +10068,10 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, break; #ifdef TARGET_MIPS64 case LDP: + if (rd == base) { + generate_exception(ctx, EXCP_RI); + return; + } save_cpu_state(ctx, 0); op_ld_ld(t1, t0, ctx); gen_store_gpr(t1, rd); From fb6541571e0dc74655f0bfb0534c95d759a7bdb4 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 24 Aug 2012 12:36:41 +0200 Subject: [PATCH 0122/2270] megasas: Add 'hba_serial' property Add a 'hba_serial' property to the megasas driver. Originally it would be using a pointer value which would break migration. Reported-by: Stefan Weil Cc: Paolo Bonzini Signed-off-by: Hannes Reinecke Signed-off-by: Paolo Bonzini --- hw/megasas.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/hw/megasas.c b/hw/megasas.c index c35a15db4f..c728aea699 100644 --- a/hw/megasas.c +++ b/hw/megasas.c @@ -38,6 +38,7 @@ #define MEGASAS_MAX_SECTORS 0xFFFF /* No real limit */ #define MEGASAS_MAX_ARRAYS 128 +#define MEGASAS_HBA_SERIAL "QEMU123456" #define NAA_LOCALLY_ASSIGNED_ID 0x3ULL #define IEEE_COMPANY_LOCALLY_ASSIGNED 0x525400 @@ -93,6 +94,7 @@ typedef struct MegasasState { int boot_event; uint64_t sas_addr; + char *hba_serial; uint64_t reply_queue_pa; void *reply_queue; @@ -698,8 +700,7 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) } memcpy(info.product_name, "MegaRAID SAS 8708EM2", 20); - snprintf(info.serial_number, 32, "QEMU%08lx", - (unsigned long)s & 0xFFFFFFFF); + snprintf(info.serial_number, 32, "%s", s->hba_serial); snprintf(info.package_version, 0x60, "%s-QEMU", QEMU_VERSION); memcpy(info.image_component[0].name, "APP", 3); memcpy(info.image_component[0].version, MEGASAS_VERSION "-QEMU", 9); @@ -2132,6 +2133,9 @@ static int megasas_scsi_init(PCIDevice *dev) s->sas_addr |= (PCI_SLOT(dev->devfn) << 8); s->sas_addr |= PCI_FUNC(dev->devfn); } + if (!s->hba_serial) { + s->hba_serial = g_strdup(MEGASAS_HBA_SERIAL); + } if (s->fw_sge >= MEGASAS_MAX_SGE - MFI_PASS_FRAME_SIZE) { s->fw_sge = MEGASAS_MAX_SGE - MFI_PASS_FRAME_SIZE; } else if (s->fw_sge >= 128 - MFI_PASS_FRAME_SIZE) { @@ -2166,6 +2170,7 @@ static Property megasas_properties[] = { MEGASAS_DEFAULT_SGE), DEFINE_PROP_UINT32("max_cmds", MegasasState, fw_cmds, MEGASAS_DEFAULT_FRAMES), + DEFINE_PROP_STRING("hba_serial", MegasasState, hba_serial), DEFINE_PROP_HEX64("sas_address", MegasasState, sas_addr, 0), #ifdef USE_MSIX DEFINE_PROP_BIT("use_msix", MegasasState, flags, From 9ea73f8b10531de4b1173835c819b7c35b7160c6 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 2 Aug 2012 15:43:39 +0200 Subject: [PATCH 0123/2270] esp: support 24-bit DMA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SeaBIOS will issue requests for more than 64k when loading a CD-ROM image into memory. Support the TCHI register from the AMD PCscsi spec. Acked-by: Hervé Poussineau Signed-off-by: Paolo Bonzini --- hw/esp.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/hw/esp.c b/hw/esp.c index 52c46e615f..84a4e74e25 100644 --- a/hw/esp.c +++ b/hw/esp.c @@ -87,7 +87,9 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf) target = s->wregs[ESP_WBUSID] & BUSID_DID; if (s->dma) { - dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8); + dmalen = s->rregs[ESP_TCLO]; + dmalen |= s->rregs[ESP_TCMID] << 8; + dmalen |= s->rregs[ESP_TCHI] << 16; s->dma_memory_read(s->dma_opaque, buf, dmalen); } else { dmalen = s->ti_size; @@ -226,6 +228,7 @@ static void esp_dma_done(ESPState *s) s->rregs[ESP_RFLAGS] = 0; s->rregs[ESP_TCLO] = 0; s->rregs[ESP_TCMID] = 0; + s->rregs[ESP_TCHI] = 0; esp_raise_irq(s); } @@ -328,7 +331,9 @@ static void handle_ti(ESPState *s) return; } - dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8); + dmalen = s->rregs[ESP_TCLO]; + dmalen |= s->rregs[ESP_TCMID] << 8; + dmalen |= s->rregs[ESP_TCHI] << 16; if (dmalen==0) { dmalen=0x10000; } @@ -429,6 +434,7 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val) switch (saddr) { case ESP_TCLO: case ESP_TCMID: + case ESP_TCHI: s->rregs[ESP_RSTAT] &= ~STAT_TC; break; case ESP_FIFO: @@ -448,6 +454,7 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val) /* Reload DMA counter. */ s->rregs[ESP_TCLO] = s->wregs[ESP_TCLO]; s->rregs[ESP_TCMID] = s->wregs[ESP_TCMID]; + s->rregs[ESP_TCHI] = s->wregs[ESP_TCHI]; } else { s->dma = 0; } @@ -530,13 +537,12 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val) case ESP_WBUSID ... ESP_WSYNO: break; case ESP_CFG1: + case ESP_CFG2: case ESP_CFG3: + case ESP_RES3: case ESP_RES4: s->rregs[saddr] = val; break; case ESP_WCCF ... ESP_WTEST: break; - case ESP_CFG2 ... ESP_RES4: - s->rregs[saddr] = val; - break; default: trace_esp_error_invalid_write(val, saddr); return; From 0f1da449ec65403bc5c028eb9618d0ee598a3615 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 28 Aug 2012 12:46:18 +0200 Subject: [PATCH 0124/2270] scsi: more fixes to properties for passthrough devices Commit 0384783 (scsi-block: remove properties that are not relevant for passthrough, 2012-07-09) removed one property that should have been left there, "bootindex". It also did not touch scsi-generic, while it should have. Fix both problems. Reported-by: Alexandre DERUMIER Signed-off-by: Paolo Bonzini --- hw/scsi-disk.c | 1 + hw/scsi-generic.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 409f760ef7..21b862dadb 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -2421,6 +2421,7 @@ static TypeInfo scsi_cd_info = { #ifdef __linux__ static Property scsi_block_properties[] = { DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.bs), + DEFINE_PROP_INT32("bootindex", SCSIDiskState, qdev.conf.bootindex, -1), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index 8d5106061e..a5eb663ecf 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -479,7 +479,8 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun, } static Property scsi_generic_properties[] = { - DEFINE_BLOCK_PROPERTIES(SCSIDevice, conf), + DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.bs), + DEFINE_PROP_INT32("bootindex", SCSIDevice, conf.bootindex, -1), DEFINE_PROP_END_OF_LIST(), }; From 135b9088780d7d8e5eae027b4fba6b33562f7006 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Fri, 17 Aug 2012 12:36:20 +1000 Subject: [PATCH 0125/2270] iscsi: Set number of blocks to 0 for blank CDROM devices The number of blocks of the device is used to compute the device size in bdrv_getlength()/iscsi_getlength(). For MMC devices, the ReturnedLogicalBlockAddress in the READCAPACITY10 has a special meaning when it is 0. In this case it does not mean that LBA 0 is the last accessible LBA, and thus the device has 1 readable block, but instead it means that the disc is blank and there are no readable blocks. This change ensures that when the iSCSI LUN is loaded with a blank DVD-R disk or similar that bdrv_getlength() will return the correct size of the device as 0 bytes. Signed-off-by: Ronnie Sahlberg --- block/iscsi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/block/iscsi.c b/block/iscsi.c index 4828b83927..0b96165ec2 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -721,7 +721,12 @@ iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status, } itask->iscsilun->block_size = rc10->block_size; - itask->iscsilun->num_blocks = rc10->lba + 1; + if (rc10->lba == 0) { + /* blank disk loaded */ + itask->iscsilun->num_blocks = 0; + } else { + itask->iscsilun->num_blocks = rc10->lba + 1; + } itask->bs->total_sectors = itask->iscsilun->num_blocks * itask->iscsilun->block_size / BDRV_SECTOR_SIZE ; From 13ef70f64e9e4d7583fbd9918d8ea76194023d37 Mon Sep 17 00:00:00 2001 From: "munkyu.im" Date: Tue, 28 Aug 2012 16:42:06 +0900 Subject: [PATCH 0126/2270] audio/winwave: previous audio buffer should be flushed Winwave audio backend has problem with pausing and restart audio out. Unlike other backends, Winwave pausing API does not flush audio buffer. As a result, the previous audio data are played in front of user expected sound when user restart audio. So changes it to waveOutReset() Signed-off-by: Munkyu Im Signed-off-by: malc --- audio/winwaveaudio.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/audio/winwaveaudio.c b/audio/winwaveaudio.c index 663abb9b50..72babbf184 100644 --- a/audio/winwaveaudio.c +++ b/audio/winwaveaudio.c @@ -349,21 +349,15 @@ static int winwave_ctl_out (HWVoiceOut *hw, int cmd, ...) else { hw->poll_mode = 0; } - if (wave->paused) { - mr = waveOutRestart (wave->hwo); - if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveOutRestart"); - } - wave->paused = 0; - } + wave->paused = 0; } return 0; case VOICE_DISABLE: if (!wave->paused) { - mr = waveOutPause (wave->hwo); + mr = waveOutReset (wave->hwo); if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveOutPause"); + winwave_logerr (mr, "waveOutReset"); } else { wave->paused = 1; From 54cddd21b04013d5741a92d6828dea3bdb821482 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 Aug 2012 16:12:03 +0200 Subject: [PATCH 0127/2270] target-ppc: fix altivec instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Altivec instructions are not working anymore in PowerPC emulation, following commit d15f74fb, which inverted two registers in the call to helper. Fix that. Reviewed-by: Peter Maydell Reviewed-by: Andreas Färber Acked-by: Blue Swirl Signed-off-by: Aurelien Jarno --- target-ppc/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 91eb7a062c..ac915ccade 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -6530,7 +6530,7 @@ static void glue(gen_, name)(DisasContext *ctx) \ ra = gen_avr_ptr(rA(ctx->opcode)); \ rb = gen_avr_ptr(rB(ctx->opcode)); \ rd = gen_avr_ptr(rD(ctx->opcode)); \ - gen_helper_##name(rd, cpu_env, ra, rb); \ + gen_helper_##name(cpu_env, rd, ra, rb); \ tcg_temp_free_ptr(ra); \ tcg_temp_free_ptr(rb); \ tcg_temp_free_ptr(rd); \ From ce6760404851f410d63519084329d54dc216ff93 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 28 Aug 2012 14:47:51 +0200 Subject: [PATCH 0128/2270] Update OpenBIOS PPC image Update OpenBIOS PPC image to SVN r1063 to fix issues introduced by commit 9e56edcf. The code change in this revision only affects PPC, so OpenBIOS SPARC images are not updated. Signed-off-by: Aurelien Jarno --- pc-bios/README | 2 +- pc-bios/openbios-ppc | Bin 729876 -> 729908 bytes roms/openbios | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pc-bios/README b/pc-bios/README index fc07ebc21c..303713099e 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -12,7 +12,7 @@ 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 - 1062. + 1063. - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc index 1c3753d3eba13f39b2ebe4b4fbef373424bc5eb0..5311eca691f37222e8dc3453c4b6307e4f285306 100644 GIT binary patch delta 73273 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 Mzf7#Muh5(M4=0xno&W#< delta 73604 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%0A*s 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 Date: Mon, 27 Aug 2012 22:13:27 +0200 Subject: [PATCH 0129/2270] tcg/mips: fix broken CONFIG_TCG_PASS_AREG0 code The CONFIG_TCG_PASS_AREG0 code for calling ld/st helpers was broken in that it did not respect the ABI requirement that 64 bit values were passed in even-odd register pairs. The simplest way to fix this is to implement some new utility functions for marshalling function arguments into the correct registers and stack, so that the code which sets up the address and data arguments does not need to care whether there has been a preceding env argument. Based on commit 9716ef3b for ARM by Peter Maydell. Signed-off-by: Aurelien Jarno Reviewed-by: Peter Maydell --- tcg/mips/tcg-target.c | 160 ++++++++++++++++++++++++++---------------- 1 file changed, 100 insertions(+), 60 deletions(-) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index 393ba07f25..1006e28000 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -217,6 +217,9 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_set(ct->u.regs, 0xffffffff); #if defined(CONFIG_SOFTMMU) tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0); +# if defined(CONFIG_TCG_PASS_AREG0) && (TARGET_LONG_BITS == 64) + tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2); +# endif #endif break; case 'S': /* qemu_st constraint */ @@ -224,10 +227,14 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_set(ct->u.regs, 0xffffffff); tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0); #if defined(CONFIG_SOFTMMU) -# if TARGET_LONG_BITS == 64 +# if (defined(CONFIG_TCG_PASS_AREG0) && TARGET_LONG_BITS == 32) || \ + (!defined(CONFIG_TCG_PASS_AREG0) && TARGET_LONG_BITS == 64) tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1); # endif tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2); +# if defined(CONFIG_TCG_PASS_AREG0) && TARGET_LONG_BITS == 64 + tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3); +# endif #endif break; case 'I': @@ -382,7 +389,10 @@ static inline void tcg_out_nop(TCGContext *s) static inline void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) { - tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO); + /* Simple reg-reg move, optimising out the 'do nothing' case */ + if (ret != arg) { + tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO); + } } static inline void tcg_out_movi(TCGContext *s, TCGType type, @@ -503,6 +513,67 @@ static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) } } +/* Helper routines for marshalling helper function arguments into + * the correct registers and stack. + * arg_num is where we want to put this argument, and is updated to be ready + * for the next call. arg is the argument itself. Note that arg_num 0..3 is + * real registers, 4+ on stack. + * + * We provide routines for arguments which are: immediate, 32 bit + * value in register, 16 and 8 bit values in register (which must be zero + * extended before use) and 64 bit value in a lo:hi register pair. + */ +#define DEFINE_TCG_OUT_CALL_IARG(NAME, ARGPARAM) \ + static inline void NAME(TCGContext *s, int *arg_num, ARGPARAM) \ + { \ + if (*arg_num < 4) { \ + DEFINE_TCG_OUT_CALL_IARG_GET_ARG(tcg_target_call_iarg_regs[*arg_num]); \ + } else { \ + DEFINE_TCG_OUT_CALL_IARG_GET_ARG(TCG_REG_AT); \ + tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 4 * (*arg_num)); \ + } \ + (*arg_num)++; \ +} +#define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \ + tcg_out_opc_imm(s, OPC_ANDI, A, arg, 0xff); +DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_reg8, TCGReg arg) +#undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG +#define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \ + tcg_out_opc_imm(s, OPC_ANDI, A, arg, 0xffff); +DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_reg16, TCGReg arg) +#undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG +#define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \ + tcg_out_movi(s, TCG_TYPE_I32, A, arg); +DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_imm32, uint32_t arg) +#undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG + +/* We don't use the macro for this one to avoid an unnecessary reg-reg + move when storing to the stack. */ +static inline void tcg_out_call_iarg_reg32(TCGContext *s, int *arg_num, + TCGReg arg) +{ + if (*arg_num < 4) { + tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[*arg_num], arg); + } else { + tcg_out_st(s, TCG_TYPE_I32, arg, TCG_REG_SP, 4 * (*arg_num)); + } + (*arg_num)++; +} + +static inline void tcg_out_call_iarg_reg64(TCGContext *s, int *arg_num, + TCGReg arg_low, TCGReg arg_high) +{ + (*arg_num) = (*arg_num + 1) & ~1; + +#if defined(TCG_TARGET_WORDS_BIGENDIAN) + tcg_out_call_iarg_reg32(s, arg_num, arg_high); + tcg_out_call_iarg_reg32(s, arg_num, arg_low); +#else + tcg_out_call_iarg_reg32(s, arg_num, arg_low); + tcg_out_call_iarg_reg32(s, arg_num, arg_high); +#endif +} + static void tcg_out_brcond(TCGContext *s, TCGCond cond, int arg1, int arg2, int label_index) { @@ -792,18 +863,18 @@ static void *qemu_st_helpers[4] = { static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) { - int addr_regl, addr_reg1, addr_meml; + int addr_regl, addr_meml; int data_regl, data_regh, data_reg1, data_reg2; int mem_index, s_bits; #if defined(CONFIG_SOFTMMU) void *label1_ptr, *label2_ptr; - int sp_args; + int arg_num; #endif #if TARGET_LONG_BITS == 64 # if defined(CONFIG_SOFTMMU) uint8_t *label3_ptr; # endif - int addr_regh, addr_reg2, addr_memh; + int addr_regh, addr_memh; #endif data_regl = *args++; if (opc == 3) @@ -831,18 +902,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, } #if TARGET_LONG_BITS == 64 # if defined(TCG_TARGET_WORDS_BIGENDIAN) - addr_reg1 = addr_regh; - addr_reg2 = addr_regl; addr_memh = 0; addr_meml = 4; # else - addr_reg1 = addr_regl; - addr_reg2 = addr_regh; addr_memh = 4; addr_meml = 0; # endif #else - addr_reg1 = addr_regl; addr_meml = 0; #endif @@ -875,22 +941,17 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, # endif /* slow path */ - sp_args = TCG_REG_A0; - tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1); -# if TARGET_LONG_BITS == 64 - tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2); + arg_num = 0; +# ifdef CONFIG_TCG_PASS_AREG0 + tcg_out_call_iarg_reg32(s, &arg_num, TCG_AREG0); # endif - tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index); +# if TARGET_LONG_BITS == 64 + tcg_out_call_iarg_reg64(s, &arg_num, addr_regl, addr_regh); +# else + tcg_out_call_iarg_reg32(s, &arg_num, addr_regl); +# endif + tcg_out_call_iarg_imm32(s, &arg_num, mem_index); tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]); -#ifdef CONFIG_TCG_PASS_AREG0 - /* XXX/FIXME: suboptimal and incorrect for 64 on 32 bit */ - tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], - tcg_target_call_iarg_regs[1]); - tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1], - tcg_target_call_iarg_regs[0]); - tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], - TCG_AREG0); -#endif tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0); tcg_out_nop(s); @@ -991,18 +1052,18 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) { - int addr_regl, addr_reg1, addr_meml; + int addr_regl, addr_meml; int data_regl, data_regh, data_reg1, data_reg2; int mem_index, s_bits; #if defined(CONFIG_SOFTMMU) uint8_t *label1_ptr, *label2_ptr; - int sp_args; + int arg_num; #endif #if TARGET_LONG_BITS == 64 # if defined(CONFIG_SOFTMMU) uint8_t *label3_ptr; # endif - int addr_regh, addr_reg2, addr_memh; + int addr_regh, addr_memh; #endif data_regl = *args++; @@ -1024,18 +1085,13 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, #if TARGET_LONG_BITS == 64 addr_regh = *args++; # if defined(TCG_TARGET_WORDS_BIGENDIAN) - addr_reg1 = addr_regh; - addr_reg2 = addr_regl; addr_memh = 0; addr_meml = 4; # else - addr_reg1 = addr_regl; - addr_reg2 = addr_regh; addr_memh = 4; addr_meml = 0; # endif #else - addr_reg1 = addr_regl; addr_meml = 0; #endif mem_index = *args; @@ -1070,49 +1126,33 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, # endif /* slow path */ - sp_args = TCG_REG_A0; - tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1); + arg_num = 0; +# ifdef CONFIG_TCG_PASS_AREG0 + tcg_out_call_iarg_reg32(s, &arg_num, TCG_AREG0); +# endif # if TARGET_LONG_BITS == 64 - tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2); + tcg_out_call_iarg_reg64(s, &arg_num, addr_regl, addr_regh); +# else + tcg_out_call_iarg_reg32(s, &arg_num, addr_regl); # endif switch(opc) { case 0: - tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff); + tcg_out_call_iarg_reg8(s, &arg_num, data_regl); break; case 1: - tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff); + tcg_out_call_iarg_reg16(s, &arg_num, data_regl); break; case 2: - tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1); + tcg_out_call_iarg_reg32(s, &arg_num, data_regl); break; case 3: - sp_args = (sp_args + 1) & ~1; - tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1); - tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg2); + tcg_out_call_iarg_reg64(s, &arg_num, data_regl, data_regh); break; default: tcg_abort(); } - if (sp_args > TCG_REG_A3) { - /* Push mem_index on the stack */ - tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index); - tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16); - } else { - tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index); - } - + tcg_out_call_iarg_imm32(s, &arg_num, mem_index); tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]); -#ifdef CONFIG_TCG_PASS_AREG0 - /* XXX/FIXME: suboptimal and incorrect for 64 on 32 bit */ - tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3], - tcg_target_call_iarg_regs[2]); - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], - tcg_target_call_iarg_regs[1]); - tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1], - tcg_target_call_iarg_regs[0]); - tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], - TCG_AREG0); -#endif tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0); tcg_out_nop(s); From ef72f76e58107bd4096018c3db2912d28249308e Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 28 Aug 2012 14:04:27 +0100 Subject: [PATCH 0130/2270] qed: refuse unaligned zero writes with a backing file Zero writes have cluster granularity in QED. Therefore they can only be used to zero entire clusters. If the zero write request leaves sectors untouched, zeroing the entire cluster would obscure the backing file. Instead return -ENOTSUP, which is handled by block.c:bdrv_co_do_write_zeroes() and falls back to a regular write. The qemu-iotests 034 test cases covers this scenario. Signed-off-by: Stefan Hajnoczi Reviewed-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- block/qed.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/block/qed.c b/block/qed.c index a02dbfd72d..21cb239870 100644 --- a/block/qed.c +++ b/block/qed.c @@ -1363,10 +1363,21 @@ static int coroutine_fn bdrv_qed_co_write_zeroes(BlockDriverState *bs, int nb_sectors) { BlockDriverAIOCB *blockacb; + BDRVQEDState *s = bs->opaque; QEDWriteZeroesCB cb = { .done = false }; QEMUIOVector qiov; struct iovec iov; + /* Refuse if there are untouched backing file sectors */ + if (bs->backing_hd) { + if (qed_offset_into_cluster(s, sector_num * BDRV_SECTOR_SIZE) != 0) { + return -ENOTSUP; + } + if (qed_offset_into_cluster(s, nb_sectors * BDRV_SECTOR_SIZE) != 0) { + return -ENOTSUP; + } + } + /* Zero writes start without an I/O buffer. If a buffer becomes necessary * then it will be allocated during request processing. */ From 571cd9dcc7f2fee59e47913365ced7781f33c2d3 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 28 Aug 2012 15:26:48 +0100 Subject: [PATCH 0131/2270] stream: complete early if end of backing file is reached It is possible to create an image that is larger than its backing file. Reading beyond the end of the backing file produces zeroes if no writes have been made to those sectors in the image file. This patch finishes streaming early when the end of the backing file is reached. Without this patch the block job hangs and continually tries to stream the first sectors beyond the end of the backing file. To reproduce the hung block job bug: $ qemu-img create -f qcow2 backing.qcow2 128M $ qemu-img create -f qcow2 -o backing_file=backing.qcow2 image.qcow2 6G $ qemu -drive if=virtio,cache=none,file=image.qcow2 (qemu) block_stream virtio0 (qemu) info block-jobs The qemu-iotests 030 streaming test still passes. Signed-off-by: Stefan Hajnoczi Reviewed-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- block/stream.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/block/stream.c b/block/stream.c index 37c46525d2..c4f87dd5b6 100644 --- a/block/stream.c +++ b/block/stream.c @@ -122,6 +122,12 @@ wait: * known-unallocated area [sector_num, sector_num+n). */ ret = bdrv_co_is_allocated_above(bs->backing_hd, base, sector_num, n, &n); + + /* Finish early if end of backing file has been reached */ + if (ret == 0 && n == 0) { + n = end - sector_num; + } + copy = (ret == 1); } trace_stream_one_iteration(s, sector_num, n, ret); From 774a8850d708aeb6dd6de493c28b374098c1a4c3 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 28 Aug 2012 15:26:49 +0100 Subject: [PATCH 0132/2270] qemu-iotests: add backing file smaller than image test case This new test case checks that streaming completes successfully when the backing file is smaller than the image file. Signed-off-by: Stefan Hajnoczi Reviewed-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- tests/qemu-iotests/030 | 33 +++++++++++++++++++++++++++++++++ tests/qemu-iotests/030.out | 4 ++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030 index f71ab8dd10..55b16f81dd 100755 --- a/tests/qemu-iotests/030 +++ b/tests/qemu-iotests/030 @@ -125,6 +125,39 @@ class TestSingleDrive(ImageStreamingTestCase): result = self.vm.qmp('block-stream', device='nonexistent') self.assert_qmp(result, 'error/class', 'DeviceNotFound') + +class TestSmallerBackingFile(ImageStreamingTestCase): + backing_len = 1 * 1024 * 1024 # MB + image_len = 2 * backing_len + + def setUp(self): + self.create_image(backing_img, self.backing_len) + qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img, str(self.image_len)) + self.vm = iotests.VM().add_drive(test_img) + self.vm.launch() + + # If this hangs, then you are missing a fix to complete streaming when the + # end of the backing file is reached. + def test_stream(self): + self.assert_no_active_streams() + + result = self.vm.qmp('block-stream', device='drive0') + self.assert_qmp(result, 'return', {}) + + completed = False + while not completed: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_COMPLETED': + self.assert_qmp(event, 'data/type', 'stream') + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/offset', self.image_len) + self.assert_qmp(event, 'data/len', self.image_len) + completed = True + + self.assert_no_active_streams() + self.vm.shutdown() + + class TestStreamStop(ImageStreamingTestCase): image_len = 8 * 1024 * 1024 * 1024 # GB diff --git a/tests/qemu-iotests/030.out b/tests/qemu-iotests/030.out index 3f8a935a08..2f7d3902f2 100644 --- a/tests/qemu-iotests/030.out +++ b/tests/qemu-iotests/030.out @@ -1,5 +1,5 @@ -...... +....... ---------------------------------------------------------------------- -Ran 6 tests +Ran 7 tests OK From 998a74bcda7f3297813732ddc2f28ffe5a12e37a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 29 Aug 2012 08:52:37 +0100 Subject: [PATCH 0133/2270] hw/arm_gic.c: Define .class_size in arm_gic_info TypeInfo Add the missing .class_size definition to the arm_gic_info TypeInfo. This fixes the memory corruption and possible segfault that otherwise results when the class struct is allocated at too small a size and the class init function writes off the end of it. Reported-by: Adam Lackorzynski Signed-off-by: Peter Maydell Signed-off-by: Anthony Liguori --- hw/arm_gic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/arm_gic.c b/hw/arm_gic.c index 186ac66f00..55871fad19 100644 --- a/hw/arm_gic.c +++ b/hw/arm_gic.c @@ -703,6 +703,7 @@ static TypeInfo arm_gic_info = { .parent = TYPE_ARM_GIC_COMMON, .instance_size = sizeof(gic_state), .class_init = arm_gic_class_init, + .class_size = sizeof(ARMGICClass), }; static void arm_gic_register_types(void) From 7e7de876ae9bdb1b994dee148c6dc009ce94c48e Mon Sep 17 00:00:00 2001 From: Cam Macdonell Date: Mon, 27 Aug 2012 12:12:19 -0600 Subject: [PATCH 0134/2270] ivshmem: remove redundant ioeventfd configuration setup_ioeventfds() is unnecessary and actually causes a segfault when used ioeventfd=on is used on the command-line. Since ioeventfds are handled within the memory API, it can be removed. Signed-off-by: Cam Macdonell Signed-off-by: Anthony Liguori --- hw/ivshmem.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/hw/ivshmem.c b/hw/ivshmem.c index 47f2a16833..62fe53ae2b 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -385,17 +385,6 @@ static void close_guest_eventfds(IVShmemState *s, int posn) s->peers[posn].nb_eventfds = 0; } -static void setup_ioeventfds(IVShmemState *s) { - - int i, j; - - for (i = 0; i <= s->max_peer; i++) { - for (j = 0; j < s->peers[i].nb_eventfds; j++) { - ivshmem_add_eventfd(s, i, j); - } - } -} - /* this function increase the dynamic storage need to store data about other * guests */ static void increase_dynamic_storage(IVShmemState *s, int new_min_size) { @@ -696,10 +685,6 @@ static int pci_ivshmem_init(PCIDevice *dev) memory_region_init_io(&s->ivshmem_mmio, &ivshmem_mmio_ops, s, "ivshmem-mmio", IVSHMEM_REG_BAR_SIZE); - if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) { - setup_ioeventfds(s); - } - /* region for registers*/ pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ivshmem_mmio); From 7e2a62d82a3f1397acd67685c3008046eba8344b Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sun, 26 Aug 2012 10:12:47 +0200 Subject: [PATCH 0135/2270] memory: Fix copy&paste mistake in memory_region_iorange_write The last argument of find_portio is "write", so this must be true here. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/memory.c b/memory.c index 643871bafa..d528d1f7f3 100644 --- a/memory.c +++ b/memory.c @@ -426,7 +426,7 @@ static void memory_region_iorange_write(IORange *iorange, if (mrp) { mrp->write(mr->opaque, offset, data); } else if (width == 2) { - mrp = find_portio(mr, offset - mrio->offset, 1, false); + mrp = find_portio(mr, offset - mrio->offset, 1, true); assert(mrp); mrp->write(mr->opaque, offset, data & 0xff); mrp->write(mr->opaque, offset + 1, data >> 8); From 4bdb1a3059d7d3a931de0748a2eec39a0ab41b4e Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 24 Aug 2012 07:03:03 +0200 Subject: [PATCH 0136/2270] qemu-ga: Fix null pointer passed to unlink in failure branch Clang reports this warning: Null pointer passed as an argument to a 'nonnull' parameter Reviewed-by: Luiz Capitulino Signed-off-by: Stefan Weil Signed-off-by: Anthony Liguori --- qemu-ga.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qemu-ga.c b/qemu-ga.c index 26671fee3f..7623079887 100644 --- a/qemu-ga.c +++ b/qemu-ga.c @@ -438,7 +438,9 @@ static void become_daemon(const char *pidfile) return; fail: - unlink(pidfile); + if (pidfile) { + unlink(pidfile); + } g_critical("failed to daemonize"); exit(EXIT_FAILURE); #endif From 4d09d37c6aa9a02b44b1fdb6268820fab92499bd Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Tue, 7 Aug 2012 15:52:03 +0300 Subject: [PATCH 0137/2270] reset PMBA and PMREGMISC PIIX4 registers. The bug causes Windows + OVMF hang after reboot since OVMF checks PMREGMISC to see if IO space is enabled and skip configuration if it is. Reviewed-by: Laszlo Ersek Signed-off-by: Gleb Natapov Signed-off-by: Anthony Liguori --- hw/acpi_piix4.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 72d6e5c904..c56220b368 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -352,6 +352,9 @@ static void piix4_reset(void *opaque) pci_conf[0x5a] = 0; pci_conf[0x5b] = 0; + pci_conf[0x40] = 0x01; /* PM io base read only bit */ + pci_conf[0x80] = 0; + if (s->kvm_enabled) { /* Mark SMM as already inited (until KVM supports SMM). */ pci_conf[0x5B] = 0x02; @@ -391,8 +394,6 @@ static int piix4_pm_initfn(PCIDevice *dev) pci_conf[0x09] = 0x00; pci_conf[0x3d] = 0x01; // interrupt pin 1 - pci_conf[0x40] = 0x01; /* PM io base read only bit */ - /* APM */ apm_init(&s->apm, apm_ctrl_changed, s); From ef8621b1a3b199c348606c0a11a77d8e8bf135f1 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Wed, 29 Aug 2012 09:32:41 -0500 Subject: [PATCH 0138/2270] target-i386: disable pv eoi to fix migration across QEMU versions We have a problem with how we handle migration with KVM paravirt features. We unconditionally enable paravirt features regardless of whether we know how to migrate them. We also don't tie paravirt features to specific machine types so an old QEMU on a new kernel would expose features that never existed. The 1.2 cycle is over and as things stand, migration is broken. Michael has another series that adds support for migrating PV EOI and attempts to make it work correctly for different machine types. After speaking with Michael on IRC, we agreed to take this patch plus 1 & 4 from his series. This makes sure QEMU can migrate PV EOI if it's enabled, but does not enable it by default. This also means that we won't unconditionally enable new features for guests future proofing us from this happening again in the future. Signed-off-by: Anthony Liguori --- target-i386/cpu.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 120a2e3d3e..f3cac49fd3 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -33,6 +33,7 @@ #include "hyperv.h" #include "hw/hw.h" +#include /* feature flags taken from "Intel Processor Identification and the CPUID * Instruction" and AMD's "CPUID Specification". In cases of disagreement @@ -887,7 +888,17 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) memcpy(x86_cpu_def, def, sizeof(*def)); } - plus_kvm_features = ~0; /* not supported bits will be filtered out later */ +#if defined(CONFIG_KVM) + plus_kvm_features = (1 << KVM_FEATURE_CLOCKSOURCE) | + (1 << KVM_FEATURE_NOP_IO_DELAY) | + (1 << KVM_FEATURE_MMU_OP) | + (1 << KVM_FEATURE_CLOCKSOURCE2) | + (1 << KVM_FEATURE_ASYNC_PF) | + (1 << KVM_FEATURE_STEAL_TIME) | + (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT); +#else + plus_kvm_features = 0; +#endif add_flagname_to_bitmaps("hypervisor", &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features, From 651682dcf54c4f2e07904bd822a97895900f6d8a Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 28 Aug 2012 20:43:42 +0300 Subject: [PATCH 0139/2270] linux-headers: update to 3.6-rc3 Update linux-headers to version present in Linux 3.6-rc3. Header asm-x96_64/kvm_para.h update is needed for the new PV EOI feature. Signed-off-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- linux-headers/asm-s390/kvm.h | 2 +- linux-headers/asm-s390/kvm_para.h | 2 +- linux-headers/asm-x86/kvm.h | 1 + linux-headers/asm-x86/kvm_para.h | 7 +++++++ linux-headers/linux/kvm.h | 3 +++ 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h index bdcbe0f8dd..d25da598ec 100644 --- a/linux-headers/asm-s390/kvm.h +++ b/linux-headers/asm-s390/kvm.h @@ -1,7 +1,7 @@ #ifndef __LINUX_KVM_S390_H #define __LINUX_KVM_S390_H /* - * asm-s390/kvm.h - KVM s390 specific structures and definitions + * KVM s390 specific structures and definitions * * Copyright IBM Corp. 2008 * diff --git a/linux-headers/asm-s390/kvm_para.h b/linux-headers/asm-s390/kvm_para.h index 8e2dd6706b..870051f645 100644 --- a/linux-headers/asm-s390/kvm_para.h +++ b/linux-headers/asm-s390/kvm_para.h @@ -1,5 +1,5 @@ /* - * asm-s390/kvm_para.h - definition for paravirtual devices on s390 + * definition for paravirtual devices on s390 * * Copyright IBM Corp. 2008 * diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h index e7d1c194d2..246617efd6 100644 --- a/linux-headers/asm-x86/kvm.h +++ b/linux-headers/asm-x86/kvm.h @@ -12,6 +12,7 @@ /* Select x86 specific features in */ #define __KVM_HAVE_PIT #define __KVM_HAVE_IOAPIC +#define __KVM_HAVE_IRQ_LINE #define __KVM_HAVE_DEVICE_ASSIGNMENT #define __KVM_HAVE_MSI #define __KVM_HAVE_USER_NMI diff --git a/linux-headers/asm-x86/kvm_para.h b/linux-headers/asm-x86/kvm_para.h index f2ac46a2a2..a1c3d72acd 100644 --- a/linux-headers/asm-x86/kvm_para.h +++ b/linux-headers/asm-x86/kvm_para.h @@ -22,6 +22,7 @@ #define KVM_FEATURE_CLOCKSOURCE2 3 #define KVM_FEATURE_ASYNC_PF 4 #define KVM_FEATURE_STEAL_TIME 5 +#define KVM_FEATURE_PV_EOI 6 /* The last 8 bits are used to indicate how to interpret the flags field * in pvclock structure. If no bits are set, all flags are ignored. @@ -37,6 +38,7 @@ #define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01 #define MSR_KVM_ASYNC_PF_EN 0x4b564d02 #define MSR_KVM_STEAL_TIME 0x4b564d03 +#define MSR_KVM_PV_EOI_EN 0x4b564d04 struct kvm_steal_time { __u64 steal; @@ -89,5 +91,10 @@ struct kvm_vcpu_pv_apf_data { __u32 enabled; }; +#define KVM_PV_EOI_BIT 0 +#define KVM_PV_EOI_MASK (0x1 << KVM_PV_EOI_BIT) +#define KVM_PV_EOI_ENABLED KVM_PV_EOI_MASK +#define KVM_PV_EOI_DISABLED 0x0 + #endif /* _ASM_X86_KVM_PARA_H */ diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 5a9d4e350d..4b9e575dd0 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -617,6 +617,7 @@ struct kvm_ppc_smmu_info { #define KVM_CAP_SIGNAL_MSI 77 #define KVM_CAP_PPC_GET_SMMU_INFO 78 #define KVM_CAP_S390_COW 79 +#define KVM_CAP_PPC_ALLOC_HTAB 80 #ifdef KVM_CAP_IRQ_ROUTING @@ -828,6 +829,8 @@ struct kvm_s390_ucas_mapping { #define KVM_SIGNAL_MSI _IOW(KVMIO, 0xa5, struct kvm_msi) /* Available with KVM_CAP_PPC_GET_SMMU_INFO */ #define KVM_PPC_GET_SMMU_INFO _IOR(KVMIO, 0xa6, struct kvm_ppc_smmu_info) +/* Available with KVM_CAP_PPC_ALLOC_HTAB */ +#define KVM_PPC_ALLOCATE_HTAB _IOWR(KVMIO, 0xa7, __u32) /* * ioctls for vcpu fds From bc9a839d569d4d8532c5c097bf1f4583226e3aa0 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 28 Aug 2012 20:43:56 +0300 Subject: [PATCH 0140/2270] kvm: get/set PV EOI MSR Support get/set of new PV EOI MSR, for migration. Add an optional section for MSR value - send it out in case MSR was changed from the default value (0). Signed-off-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- target-i386/cpu.h | 1 + target-i386/kvm.c | 13 +++++++++++++ target-i386/machine.c | 21 +++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 60f9e972bd..0677502dcc 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -699,6 +699,7 @@ typedef struct CPUX86State { uint64_t system_time_msr; uint64_t wall_clock_msr; uint64_t async_pf_en_msr; + uint64_t pv_eoi_en_msr; uint64_t tsc; uint64_t tsc_deadline; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 696b14a04a..ffc294ec39 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -63,6 +63,7 @@ static bool has_msr_star; static bool has_msr_hsave_pa; static bool has_msr_tsc_deadline; static bool has_msr_async_pf_en; +static bool has_msr_pv_eoi_en; static bool has_msr_misc_enable; static int lm_capable_kernel; @@ -455,6 +456,8 @@ int kvm_arch_init_vcpu(CPUX86State *env) has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF); + has_msr_pv_eoi_en = c->eax & (1 << KVM_FEATURE_PV_EOI); + cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused); for (i = 0; i <= limit; i++) { @@ -1017,6 +1020,10 @@ static int kvm_put_msrs(CPUX86State *env, int level) kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN, env->async_pf_en_msr); } + if (has_msr_pv_eoi_en) { + kvm_msr_entry_set(&msrs[n++], MSR_KVM_PV_EOI_EN, + env->pv_eoi_en_msr); + } if (hyperv_hypercall_available()) { kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, 0); kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, 0); @@ -1259,6 +1266,9 @@ static int kvm_get_msrs(CPUX86State *env) if (has_msr_async_pf_en) { msrs[n++].index = MSR_KVM_ASYNC_PF_EN; } + if (has_msr_pv_eoi_en) { + msrs[n++].index = MSR_KVM_PV_EOI_EN; + } if (env->mcg_cap) { msrs[n++].index = MSR_MCG_STATUS; @@ -1338,6 +1348,9 @@ static int kvm_get_msrs(CPUX86State *env) case MSR_KVM_ASYNC_PF_EN: env->async_pf_en_msr = msrs[i].data; break; + case MSR_KVM_PV_EOI_EN: + env->pv_eoi_en_msr = msrs[i].data; + break; } } diff --git a/target-i386/machine.c b/target-i386/machine.c index a8be058d2d..477150887b 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -279,6 +279,13 @@ static bool async_pf_msr_needed(void *opaque) return cpu->async_pf_en_msr != 0; } +static bool pv_eoi_msr_needed(void *opaque) +{ + CPUX86State *cpu = opaque; + + return cpu->pv_eoi_en_msr != 0; +} + static const VMStateDescription vmstate_async_pf_msr = { .name = "cpu/async_pf_msr", .version_id = 1, @@ -290,6 +297,17 @@ static const VMStateDescription vmstate_async_pf_msr = { } }; +static const VMStateDescription vmstate_pv_eoi_msr = { + .name = "cpu/async_pv_eoi_msr", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { + VMSTATE_UINT64(pv_eoi_en_msr, CPUX86State), + VMSTATE_END_OF_LIST() + } +}; + static bool fpop_ip_dp_needed(void *opaque) { CPUX86State *env = opaque; @@ -453,6 +471,9 @@ static const VMStateDescription vmstate_cpu = { { .vmsd = &vmstate_async_pf_msr, .needed = async_pf_msr_needed, + } , { + .vmsd = &vmstate_pv_eoi_msr, + .needed = pv_eoi_msr_needed, } , { .vmsd = &vmstate_fpop_ip_dp, .needed = fpop_ip_dp_needed, From 3cac001e5ae3c0ceb33e0a1978a48cb5e2482ab2 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 29 Aug 2012 19:40:56 +0300 Subject: [PATCH 0141/2270] msix: make [un]use vectors on reset/load optional The facility to use/unuse vectors dynamically is helpful for virtio but little else: everyone just seems to use vectors in their init function. Avoid clearing msix vector use info on reset and load. For virtio, clear it explicitly. This should fix regressions reported with ivshmem - though I didn't test this, I verified that virtio keeps working like it did. Tested-by: Cam Macdonell Signed-off-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- hw/msix.c | 13 +++++++++++-- hw/virtio-pci.c | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/hw/msix.c b/hw/msix.c index aea340b7c7..d812094139 100644 --- a/hw/msix.c +++ b/hw/msix.c @@ -336,6 +336,15 @@ static void msix_free_irq_entries(PCIDevice *dev) } } +static void msix_clear_all_vectors(PCIDevice *dev) +{ + int vector; + + for (vector = 0; vector < dev->msix_entries_nr; ++vector) { + msix_clr_pending(dev, vector); + } +} + /* Clean up resources for the device. */ void msix_uninit(PCIDevice *dev, MemoryRegion *table_bar, MemoryRegion *pba_bar) { @@ -390,7 +399,7 @@ void msix_load(PCIDevice *dev, QEMUFile *f) return; } - msix_free_irq_entries(dev); + msix_clear_all_vectors(dev); qemu_get_buffer(f, dev->msix_table, n * PCI_MSIX_ENTRY_SIZE); qemu_get_buffer(f, dev->msix_pba, (n + 7) / 8); msix_update_function_masked(dev); @@ -436,7 +445,7 @@ void msix_reset(PCIDevice *dev) if (!msix_present(dev)) { return; } - msix_free_irq_entries(dev); + msix_clear_all_vectors(dev); dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &= ~dev->wmask[dev->msix_cap + MSIX_CONTROL_OFFSET]; memset(dev->msix_table, 0, dev->msix_entries_nr * PCI_MSIX_ENTRY_SIZE); diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 2a3d86f176..b3f0710f39 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -131,6 +131,7 @@ static int virtio_pci_load_config(void * opaque, QEMUFile *f) if (ret) { return ret; } + msix_unuse_all_vectors(&proxy->pci_dev); msix_load(&proxy->pci_dev, f); if (msix_present(&proxy->pci_dev)) { qemu_get_be16s(f, &proxy->vdev->config_vector); @@ -246,6 +247,7 @@ void virtio_pci_reset(DeviceState *d) VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev); virtio_pci_stop_ioeventfd(proxy); virtio_reset(proxy->vdev); + msix_unuse_all_vectors(&proxy->pci_dev); proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG; } From 5bb0b62e750c24886e90d1399eb9f03c68404001 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 29 Aug 2012 20:39:25 +0200 Subject: [PATCH 0142/2270] scsi-disk: Fix typo (uint32 -> uint32_t) Cc: Paolo Bonzini Signed-off-by: Stefan Weil Signed-off-by: Anthony Liguori --- hw/scsi-disk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 21b862dadb..1585683bce 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -1461,7 +1461,7 @@ static void scsi_unmap_complete(void *opaque, int ret) SCSIDiskReq *r = data->r; SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); uint64_t sector_num; - uint32 nb_sectors; + uint32_t nb_sectors; r->req.aiocb = NULL; if (ret < 0) { From c9a238e7005bc6c94c7367b2976402ee5adec0de Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Thu, 30 Aug 2012 07:45:28 -0500 Subject: [PATCH 0143/2270] Update version for 1.2.0-rc2 Signed-off-by: Anthony Liguori --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 069199b82a..99f6a00b10 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.91 +1.1.92 From b834b5081d6266cc0789454905f3b7d622d4d096 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 30 Aug 2012 22:28:31 +0200 Subject: [PATCH 0144/2270] w32: Fix broken build Commit ef8621b1a3b199c348606c0a11a77d8e8bf135f1 added an include file which is not available for MinGW compilations. Signed-off-by: Stefan Weil Signed-off-by: Anthony Liguori --- target-i386/cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index f3cac49fd3..423e00905d 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -33,7 +33,9 @@ #include "hyperv.h" #include "hw/hw.h" +#if defined(CONFIG_KVM) #include +#endif /* feature flags taken from "Intel Processor Identification and the CPUID * Instruction" and AMD's "CPUID Specification". In cases of disagreement From da9fbe76a0639c529f9678aabcc052dfe4cd9cc4 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 11 Jul 2012 12:21:23 +0200 Subject: [PATCH 0145/2270] fix info qtree indention Without the patch bus properties are are not in line with the other properties: [ ... ] dev: fw_cfg, id "" ctl_iobase = 0x510 data_iobase = 0x511 irq 0 mmio ffffffffffffffff/0000000000000002 mmio ffffffffffffffff/0000000000000001 [ ... ] With the patch applied everything is lined up properly: [ ... ] dev: fw_cfg, id "" ctl_iobase = 0x510 data_iobase = 0x511 irq 0 mmio ffffffffffffffff/0000000000000002 mmio ffffffffffffffff/0000000000000001 [ ... ] Needed to make the autotest qtree parser happy. Signed-off-by: Gerd Hoffmann --- hw/qdev-monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c index 018b386782..33b7f79a94 100644 --- a/hw/qdev-monitor.c +++ b/hw/qdev-monitor.c @@ -543,7 +543,7 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent) qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent); class = object_class_get_parent(class); } while (class != object_class_by_name(TYPE_DEVICE)); - bus_print_dev(dev->parent_bus, mon, dev, indent + 2); + bus_print_dev(dev->parent_bus, mon, dev, indent); QLIST_FOREACH(child, &dev->child_bus, sibling) { qbus_print(mon, child, indent); } From 0132b4b6595423c92f54d7e0b172b5d73aaa8375 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 17 Aug 2012 15:24:49 +0200 Subject: [PATCH 0146/2270] usb: Halt ep queue en cancel pending packets on a packet error For controllers which queue up more then 1 packet at a time, we must halt the ep queue, and inside the controller code cancel all pending packets on an error. There are multiple reasons for this: 1) Guests expect the controllers to halt ep queues on error, so that they get the opportunity to cancel transfers which the scheduled after the failing one, before processing continues 2) Not cancelling queued up packets after a failed transfer also messes up the controller state machine, in the case of EHCI causing the following assert to trigger: "assert(p->qtdaddr == q->qtdaddr)" at hcd-ehci.c:2075 3) For bulk endpoints with pipelining enabled (redirection to a real USB device), we must cancel all the transfers after this a failed one so that: a) If they've completed already, they are not processed further causing more stalls to be reported, originating from the same failed transfer b) If still in flight, they are cancelled before the guest does a clear stall, otherwise the guest and device can loose sync! Note this patch only touches the ehci and uhci controller changes, since AFAIK no other controllers actually queue up multiple transfer. If I'm wrong on this other controllers need to be updated too! Also note that this patch was heavily tested with the ehci code, where I had a reproducer for a device causing a transfer to fail. The uhci code is not tested with actually failing transfers and could do with a thorough review! Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb.h | 1 + hw/usb/core.c | 35 ++++++++++++++++++++++++++++------- hw/usb/hcd-ehci.c | 13 +++++++++++++ hw/usb/hcd-uhci.c | 16 ++++++++++++++++ 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/hw/usb.h b/hw/usb.h index 432ccae57f..e5744773bd 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -179,6 +179,7 @@ struct USBEndpoint { uint8_t ifnum; int max_packet_size; bool pipeline; + bool halted; USBDevice *dev; QTAILQ_HEAD(, USBPacket) queue; }; diff --git a/hw/usb/core.c b/hw/usb/core.c index c7e5bc047f..28b840e52d 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -382,12 +382,23 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) usb_packet_check_state(p, USB_PACKET_SETUP); assert(p->ep != NULL); + /* Submitting a new packet clears halt */ + if (p->ep->halted) { + assert(QTAILQ_EMPTY(&p->ep->queue)); + p->ep->halted = false; + } + if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) { ret = usb_process_one(p); if (ret == USB_RET_ASYNC) { usb_packet_set_state(p, USB_PACKET_ASYNC); QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue); } else { + /* + * When pipelining is enabled usb-devices must always return async, + * otherwise packets can complete out of order! + */ + assert(!p->ep->pipeline); p->result = ret; usb_packet_set_state(p, USB_PACKET_COMPLETE); } @@ -399,6 +410,20 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) return ret; } +static void __usb_packet_complete(USBDevice *dev, USBPacket *p) +{ + USBEndpoint *ep = p->ep; + + assert(p->result != USB_RET_ASYNC && p->result != USB_RET_NAK); + + if (p->result < 0) { + ep->halted = true; + } + usb_packet_set_state(p, USB_PACKET_COMPLETE); + QTAILQ_REMOVE(&ep->queue, p, queue); + dev->port->ops->complete(dev->port, p); +} + /* Notify the controller that an async packet is complete. This should only be called for packets previously deferred by returning USB_RET_ASYNC from handle_packet. */ @@ -409,11 +434,9 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p) usb_packet_check_state(p, USB_PACKET_ASYNC); assert(QTAILQ_FIRST(&ep->queue) == p); - usb_packet_set_state(p, USB_PACKET_COMPLETE); - QTAILQ_REMOVE(&ep->queue, p, queue); - dev->port->ops->complete(dev->port, p); + __usb_packet_complete(dev, p); - while (!QTAILQ_EMPTY(&ep->queue)) { + while (!ep->halted && !QTAILQ_EMPTY(&ep->queue)) { p = QTAILQ_FIRST(&ep->queue); if (p->state == USB_PACKET_ASYNC) { break; @@ -425,9 +448,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p) break; } p->result = ret; - usb_packet_set_state(p, USB_PACKET_COMPLETE); - QTAILQ_REMOVE(&ep->queue, p, queue); - dev->port->ops->complete(dev->port, p); + __usb_packet_complete(ep->dev, p); } } diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 8b94b17723..8504a6a6b0 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -2138,6 +2138,19 @@ static int ehci_state_writeback(EHCIQueue *q) * bit is clear. */ if (q->qh.token & QTD_TOKEN_HALT) { + /* + * We should not do any further processing on a halted queue! + * This is esp. important for bulk endpoints with pipelining enabled + * (redirection to a real USB device), where we must cancel all the + * transfers after this one so that: + * 1) If they've completed already, they are not processed further + * causing more stalls, originating from the same failed transfer + * 2) If still in flight, they are cancelled before the guest does + * a clear stall, otherwise the guest and device can loose sync! + */ + while ((p = QTAILQ_FIRST(&q->packets)) != NULL) { + ehci_free_packet(p); + } ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); again = 1; } else { diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 1ace2a41da..898773414e 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -748,6 +748,22 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_ return TD_RESULT_COMPLETE; out: + /* + * We should not do any further processing on a queue with errors! + * This is esp. important for bulk endpoints with pipelining enabled + * (redirection to a real USB device), where we must cancel all the + * transfers after this one so that: + * 1) If they've completed already, they are not processed further + * causing more stalls, originating from the same failed transfer + * 2) If still in flight, they are cancelled before the guest does + * a clear stall, otherwise the guest and device can loose sync! + */ + while (!QTAILQ_EMPTY(&async->queue->asyncs)) { + UHCIAsync *as = QTAILQ_FIRST(&async->queue->asyncs); + uhci_async_unlink(as); + uhci_async_cancel(as); + } + switch(ret) { case USB_RET_STALL: td->ctrl |= TD_CTRL_STALL; From e983395d30d1d5bfa0ed3ae9c028c130f7c498cc Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 23 Aug 2012 13:30:13 +0200 Subject: [PATCH 0147/2270] usb: unique packet ids This patch adds IDs to usb packets. Those IDs are (a) supposed to be unique for the lifecycle of a packet (from packet setup until the packet is either completed or canceled) and (b) stable across migration. uhci, ohci, ehci and xhci use the guest physical address of the transfer descriptor for this. musb needs a different approach because there is no transfer descriptor. But musb also doesn't support pipelining, so we have never more than one packet per endpoint in flight. So we go create an ID based on endpoint and device address. Signed-off-by: Gerd Hoffmann --- hw/usb.h | 3 ++- hw/usb/core.c | 3 ++- hw/usb/hcd-ehci.c | 9 +++++---- hw/usb/hcd-musb.c | 3 ++- hw/usb/hcd-ohci.c | 4 ++-- hw/usb/hcd-uhci.c | 4 ++-- hw/usb/hcd-xhci.c | 2 +- 7 files changed, 16 insertions(+), 12 deletions(-) diff --git a/hw/usb.h b/hw/usb.h index e5744773bd..b8fceec895 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -332,6 +332,7 @@ typedef enum USBPacketState { struct USBPacket { /* Data fields for use by the driver. */ int pid; + uint64_t id; USBEndpoint *ep; QEMUIOVector iov; uint64_t parameter; /* control transfers */ @@ -344,7 +345,7 @@ struct USBPacket { void usb_packet_init(USBPacket *p); void usb_packet_set_state(USBPacket *p, USBPacketState state); void usb_packet_check_state(USBPacket *p, USBPacketState expected); -void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep); +void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id); void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len); int usb_packet_map(USBPacket *p, QEMUSGList *sgl); void usb_packet_unmap(USBPacket *p, QEMUSGList *sgl); diff --git a/hw/usb/core.c b/hw/usb/core.c index 28b840e52d..2da38e7fd0 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -520,10 +520,11 @@ void usb_packet_set_state(USBPacket *p, USBPacketState state) p->state = state; } -void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep) +void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id) { assert(!usb_packet_is_inflight(p)); assert(p->iov.iov != NULL); + p->id = id; p->pid = pid; p->ep = ep; p->result = 0; diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 8504a6a6b0..f43d690eb5 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1530,7 +1530,7 @@ static int ehci_execute(EHCIPacket *p, const char *action) endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP); ep = usb_ep_get(p->queue->dev, p->pid, endp); - usb_packet_setup(&p->packet, p->pid, ep); + usb_packet_setup(&p->packet, p->pid, ep, p->qtdaddr); usb_packet_map(&p->packet, &p->sgl); trace_usb_ehci_packet_action(p->queue, p, action); @@ -1552,7 +1552,8 @@ static int ehci_execute(EHCIPacket *p, const char *action) */ static int ehci_process_itd(EHCIState *ehci, - EHCIitd *itd) + EHCIitd *itd, + uint32_t addr) { USBDevice *dev; USBEndpoint *ep; @@ -1598,7 +1599,7 @@ static int ehci_process_itd(EHCIState *ehci, dev = ehci_find_device(ehci, devaddr); ep = usb_ep_get(dev, pid, endp); if (ep->type == USB_ENDPOINT_XFER_ISOC) { - usb_packet_setup(&ehci->ipacket, pid, ep); + usb_packet_setup(&ehci->ipacket, pid, ep, addr); usb_packet_map(&ehci->ipacket, &ehci->isgl); ret = usb_handle_packet(dev, &ehci->ipacket); assert(ret != USB_RET_ASYNC); @@ -1862,7 +1863,7 @@ static int ehci_state_fetchitd(EHCIState *ehci, int async) sizeof(EHCIitd) >> 2); ehci_trace_itd(ehci, entry, &itd); - if (ehci_process_itd(ehci, &itd) != 0) { + if (ehci_process_itd(ehci, &itd, entry) != 0) { return -1; } diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c index fa9385ee49..0bb5c7b19e 100644 --- a/hw/usb/hcd-musb.c +++ b/hw/usb/hcd-musb.c @@ -626,7 +626,8 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep, /* A wild guess on the FADDR semantics... */ dev = usb_find_device(&s->port, ep->faddr[idx]); uep = usb_ep_get(dev, pid, ep->type[idx] & 0xf); - usb_packet_setup(&ep->packey[dir].p, pid, uep); + usb_packet_setup(&ep->packey[dir].p, pid, uep, + (dev->addr << 16) | (uep->nr << 8) | pid); usb_packet_addbuf(&ep->packey[dir].p, ep->buf[idx], len); ep->packey[dir].ep = ep; ep->packey[dir].dir = dir; diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 844e7ed166..c36184ae4f 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -812,7 +812,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, } else { dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); - usb_packet_setup(&ohci->usb_packet, pid, ep); + usb_packet_setup(&ohci->usb_packet, pid, ep, addr); usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len); ret = usb_handle_packet(dev, &ohci->usb_packet); if (ret == USB_RET_ASYNC) { @@ -1011,7 +1011,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) } dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); - usb_packet_setup(&ohci->usb_packet, pid, ep); + usb_packet_setup(&ohci->usb_packet, pid, ep, addr); usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen); ret = usb_handle_packet(dev, &ohci->usb_packet); #ifdef DEBUG_PACKET diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 898773414e..b0db92145a 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -859,14 +859,14 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, * for initial isochronous requests */ async->queue->valid = 32; - async->isoc = td->ctrl & TD_CTRL_IOS; + async->isoc = td->ctrl & TD_CTRL_IOS; max_len = ((td->token >> 21) + 1) & 0x7ff; pid = td->token & 0xff; dev = uhci_find_device(s, (td->token >> 8) & 0x7f); ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf); - usb_packet_setup(&async->packet, pid, ep); + usb_packet_setup(&async->packet, pid, ep, addr); qemu_sglist_add(&async->sgl, td->buffer, max_len); usb_packet_map(&async->packet, &async->sgl); diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 6c2ff024e0..3eb27fadb8 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1392,7 +1392,7 @@ static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev) dir = xfer->in_xfer ? USB_TOKEN_IN : USB_TOKEN_OUT; ep = usb_ep_get(dev, dir, xfer->epid >> 1); - usb_packet_setup(&xfer->packet, dir, ep); + usb_packet_setup(&xfer->packet, dir, ep, xfer->trbs[0].addr); usb_packet_addbuf(&xfer->packet, xfer->data, xfer->data_length); DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n", xfer->packet.pid, dev->addr, ep->nr); From 7ce86aa1aafaa65e7d3e572873bdf37bdb896f49 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 28 Aug 2012 11:50:26 +0200 Subject: [PATCH 0148/2270] ehci: Fix NULL ptr deref when unplugging an USB dev with an iso stream active Signed-off-by: Hans de Goede --- hw/usb/hcd-ehci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index f43d690eb5..a3aea6debe 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1598,7 +1598,7 @@ static int ehci_process_itd(EHCIState *ehci, dev = ehci_find_device(ehci, devaddr); ep = usb_ep_get(dev, pid, endp); - if (ep->type == USB_ENDPOINT_XFER_ISOC) { + if (ep && ep->type == USB_ENDPOINT_XFER_ISOC) { usb_packet_setup(&ehci->ipacket, pid, ep, addr); usb_packet_map(&ehci->ipacket, &ehci->isgl); ret = usb_handle_packet(dev, &ehci->ipacket); From a1c3e4b839f8e7ec7f1792b8a11c63ca845aa021 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 30 Aug 2012 09:55:19 +0200 Subject: [PATCH 0149/2270] ehci: Schedule async-bh when IAAD bit gets set After the "ehci: Print a warning when a queue unexpectedly contains packets on cancel" commit. Under certain reproducable conditions I was getting the following message: "EHCI: Warning queue not empty on queue reset". After aprox. 8 hours of debugging I've finally found the cause. The Linux EHCI driver has an IAAD watchdog, to work around certain EHCI hardware sometimes not acknowledging the doorbell at all. This watchdog has a timeout of 10 ms, which is less then the time between 2 runs through the async schedule when async_stepdown is at its highest value. Thus the watchdog can trigger, after which Linux clears the IAAD bit and re-uses the QH. IOW we were not properly detecting the unlink of the qh, due to us missing (ignoring for more then 10 ms) the IAAD command, which triggered the warning. Signed-off-by: Hans de Goede --- hw/usb/hcd-ehci.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index a3aea6debe..3e10977492 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1194,6 +1194,15 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) val &= ~USBCMD_FLS; } + if (val & USBCMD_IAAD) { + /* + * Process IAAD immediately, otherwise the Linux IAAD watchdog may + * trigger and re-use a qh without us seeing the unlink. + */ + s->async_stepdown = 0; + qemu_bh_schedule(s->async_bh); + } + if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) != ((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) { if (s->pstate == EST_INACTIVE) { From 53dd6f7032ec4898ca8f95356df795a92cd27e09 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 16 Aug 2012 15:47:29 +0200 Subject: [PATCH 0150/2270] ehci: Remove unnecessary ehci_flush_qh call ehci_qh_do_overlay() already calls ehci_flush_qh() before it returns, calling it twice is useless. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 3e10977492..923a949ea5 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1966,7 +1966,6 @@ static int ehci_state_fetchqtd(EHCIQueue *q) } if (p != NULL) { ehci_qh_do_overlay(q); - ehci_flush_qh(q); if (p->async == EHCI_ASYNC_INFLIGHT) { ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); } else { From 574ef17191f5ec5a3cc4782c1f59dc5eb8279654 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 17 Aug 2012 11:39:17 +0200 Subject: [PATCH 0151/2270] ehci: simplify ehci_state_executing ehci_state_executing does not need to check for p->usb_status == USB_RET_ASYNC or USB_RET_PROCERR, since ehci_execute_complete already does a similar check and will trigger an assert if either value is encountered. USB_RET_ASYNC should never be the packet status when execute_complete runs for obvious reasons, and USB_RET_PROCERR is only used by ehci_state_execute / ehci_execute not by ehci_state_executing / ehci_execute_complete. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 923a949ea5..b6169ce968 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -2084,19 +2084,11 @@ out: static int ehci_state_executing(EHCIQueue *q) { EHCIPacket *p = QTAILQ_FIRST(&q->packets); - int again = 0; assert(p != NULL); assert(p->qtdaddr == q->qtdaddr); ehci_execute_complete(q); - if (p->usb_status == USB_RET_ASYNC) { - goto out; - } - if (p->usb_status == USB_RET_PROCERR) { - again = -1; - goto out; - } // 4.10.3 if (!q->async) { @@ -2114,11 +2106,8 @@ static int ehci_state_executing(EHCIQueue *q) ehci_set_state(q->ehci, q->async, EST_WRITEBACK); } - again = 1; - -out: ehci_flush_qh(q); - return again; + return 1; } From c7cdca3b853eed0dd521c43098b6d07bcce24fd1 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 21 Aug 2012 13:58:40 +0200 Subject: [PATCH 0152/2270] ehci: add ehci_cancel_queue() Factor out function to cancel all packets of a queue. No behavior change. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index b6169ce968..30e5e8fa98 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -766,15 +766,27 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint32_t addr, int async) return q; } +static void ehci_cancel_queue(EHCIQueue *q) +{ + EHCIPacket *p; + + p = QTAILQ_FIRST(&q->packets); + if (p == NULL) { + return; + } + + trace_usb_ehci_queue_action(q, "cancel"); + do { + ehci_free_packet(p); + } while ((p = QTAILQ_FIRST(&q->packets)) != NULL); +} + static void ehci_free_queue(EHCIQueue *q) { EHCIQueueHead *head = q->async ? &q->ehci->aqueues : &q->ehci->pqueues; - EHCIPacket *p; trace_usb_ehci_queue_action(q, "free"); - while ((p = QTAILQ_FIRST(&q->packets)) != NULL) { - ehci_free_packet(p); - } + ehci_cancel_queue(q); QTAILQ_REMOVE(head, q, next); g_free(q); } @@ -1796,9 +1808,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) if (q->dev != NULL && q->dev->addr != devaddr) { if (!QTAILQ_EMPTY(&q->packets)) { /* should not happen (guest bug) */ - while ((p = QTAILQ_FIRST(&q->packets)) != NULL) { - ehci_free_packet(p); - } + ehci_cancel_queue(q); } q->dev = NULL; } @@ -1959,10 +1969,10 @@ static int ehci_state_fetchqtd(EHCIQueue *q) ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &qtd); p = QTAILQ_FIRST(&q->packets); - while (p != NULL && p->qtdaddr != q->qtdaddr) { + if (p != NULL && p->qtdaddr != q->qtdaddr) { /* should not happen (guest bug) */ - ehci_free_packet(p); - p = QTAILQ_FIRST(&q->packets); + ehci_cancel_queue(q); + p = NULL; } if (p != NULL) { ehci_qh_do_overlay(q); From 287fd3f1dd0b2abbd69e58b402e5364b334e95bd Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 21 Aug 2012 14:03:09 +0200 Subject: [PATCH 0153/2270] ehci: handle TD deactivation of inflight packets Check the TDs of inflight packets, cancel packets in case the guest clears the active bit. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 30e5e8fa98..eca1431bff 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1816,11 +1816,6 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) q->dev = ehci_find_device(q->ehci, devaddr); } - if (p && p->async == EHCI_ASYNC_INFLIGHT) { - /* I/O still in progress -- skip queue */ - ehci_set_state(ehci, async, EST_HORIZONTALQH); - goto out; - } if (p && p->async == EHCI_ASYNC_FINISHED) { /* I/O finished -- continue processing queue */ trace_usb_ehci_packet_action(p->queue, p, "complete"); @@ -1969,28 +1964,41 @@ static int ehci_state_fetchqtd(EHCIQueue *q) ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &qtd); p = QTAILQ_FIRST(&q->packets); - if (p != NULL && p->qtdaddr != q->qtdaddr) { - /* should not happen (guest bug) */ - ehci_cancel_queue(q); - p = NULL; - } if (p != NULL) { - ehci_qh_do_overlay(q); + if (p->qtdaddr != q->qtdaddr || + (!NLPTR_TBIT(p->qtd.next) && (p->qtd.next != qtd.next)) || + (!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd.altnext)) || + p->qtd.bufptr[0] != qtd.bufptr[0]) { + /* guest bug: guest updated active QH or qTD underneath us */ + ehci_cancel_queue(q); + p = NULL; + } else { + p->qtd = qtd; + ehci_qh_do_overlay(q); + } + } + + if (!(qtd.token & QTD_TOKEN_ACTIVE)) { + if (p != NULL) { + /* transfer canceled by guest (clear active) */ + ehci_cancel_queue(q); + p = NULL; + } + ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); + again = 1; + } else if (p != NULL) { if (p->async == EHCI_ASYNC_INFLIGHT) { ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); } else { ehci_set_state(q->ehci, q->async, EST_EXECUTING); } again = 1; - } else if (qtd.token & QTD_TOKEN_ACTIVE) { + } else { p = ehci_alloc_packet(q); p->qtdaddr = q->qtdaddr; p->qtd = qtd; ehci_set_state(q->ehci, q->async, EST_EXECUTE); again = 1; - } else { - ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); - again = 1; } return again; From adf478342b11cf9f540baf1f387b669210d3bea1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 30 Aug 2012 11:20:51 +0200 Subject: [PATCH 0154/2270] ehci: Fix interrupt endpoints no longer working One of the recent changes (likely the addition of queuing support) has broken interrupt endpoints, this patch fixes this. Signed-off-by: Hans de Goede --- hw/usb/hcd-ehci.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index eca1431bff..017342b56a 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1987,10 +1987,19 @@ static int ehci_state_fetchqtd(EHCIQueue *q) ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); again = 1; } else if (p != NULL) { - if (p->async == EHCI_ASYNC_INFLIGHT) { + switch (p->async) { + case EHCI_ASYNC_NONE: + /* Previously nacked packet (likely interrupt ep) */ + ehci_set_state(q->ehci, q->async, EST_EXECUTE); + break; + case EHCI_ASYNC_INFLIGHT: + /* Unfinyshed async handled packet, go horizontal */ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); - } else { + break; + case EHCI_ASYNC_FINISHED: + /* Should never happen, as this case is caught by fetchqh */ ehci_set_state(q->ehci, q->async, EST_EXECUTING); + break; } again = 1; } else { From 347e40ffe61b7cc8d4565be476c20acd00611669 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 31 Aug 2012 14:34:19 +0200 Subject: [PATCH 0155/2270] uas: move transfer kickoff Kick next scsi transfer from request release callback instead of command completion callback, otherwise we might get stuck in case scsi_req_unref() doesn't release the request instantly due to someone else holding a reference too. Signed-off-by: Gerd Hoffmann --- hw/usb/dev-uas.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index b13eeba565..5a0057a36b 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -424,6 +424,7 @@ static void usb_uas_scsi_free_request(SCSIBus *bus, void *priv) } QTAILQ_REMOVE(&uas->requests, req, next); g_free(req); + usb_uas_start_next_transfer(uas); } static UASRequest *usb_uas_find_request(UASDevice *uas, uint16_t tag) @@ -456,7 +457,6 @@ static void usb_uas_scsi_command_complete(SCSIRequest *r, uint32_t status, size_t resid) { UASRequest *req = r->hba_private; - UASDevice *uas = req->uas; trace_usb_uas_scsi_complete(req->uas->dev.addr, req->tag, status, resid); req->complete = true; @@ -465,7 +465,6 @@ static void usb_uas_scsi_command_complete(SCSIRequest *r, } usb_uas_queue_sense(req, status); scsi_req_unref(req->req); - usb_uas_start_next_transfer(uas); } static void usb_uas_scsi_request_cancelled(SCSIRequest *r) From 8bd6b06d7b718b3e595aab279699ef3651ce2e48 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 17 Aug 2012 15:50:44 +0200 Subject: [PATCH 0156/2270] console: Fix warning from clang (and potential crash) ccc-analyzer reports this warning: console.c:1090:29: warning: Dereference of null pointer if (active_console->cursor_timer) { ^ Function console_select allows active_console to be NULL, but would crash when accessing cursor_timer. Fix this. Reviewed-by: Jan Kiszka Signed-off-by: Stefan Weil Signed-off-by: Anthony Liguori --- console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/console.c b/console.c index 4525cc70b8..f5e8814792 100644 --- a/console.c +++ b/console.c @@ -1087,7 +1087,7 @@ void console_select(unsigned int index) if (s) { DisplayState *ds = s->ds; - if (active_console->cursor_timer) { + if (active_console && active_console->cursor_timer) { qemu_del_timer(active_console->cursor_timer); } active_console = s; From 0232cd355d37e1ef938c3636a0e934da87f3bcc8 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Fri, 31 Aug 2012 10:50:46 -0500 Subject: [PATCH 0157/2270] Update version to 1.2.0-rc3 Signed-off-by: Anthony Liguori --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 99f6a00b10..9a03ea6377 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.92 +1.1.93 From e7eee62a90c671d22d50964b7de05e3f4fd96f5f Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 22 Aug 2012 22:03:35 +0400 Subject: [PATCH 0158/2270] target-xtensa: return ENOSYS for unimplemented simcalls This prevents guest from proceeding with uninitialised garbage returned from unimplemented simcalls. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl --- target-xtensa/xtensa-semi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target-xtensa/xtensa-semi.c b/target-xtensa/xtensa-semi.c index 1c8a19ed56..6d001c2c1a 100644 --- a/target-xtensa/xtensa-semi.c +++ b/target-xtensa/xtensa-semi.c @@ -218,6 +218,8 @@ void HELPER(simcall)(CPUXtensaState *env) default: qemu_log("%s(%d): not implemented\n", __func__, regs[2]); + regs[2] = -1; + regs[3] = ENOSYS; break; } } From de188751da8db3c77a681bf903035a0e5218c463 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 3 Sep 2012 17:34:32 +0200 Subject: [PATCH 0159/2270] qemu-timer: properly arm alarm timer for timers set by device initialization QEMU will hang when fed the following command-line qemu-system-mips -kernel vmlinux-2.6.32-5-4kc-malta -append "console=ttyS0" -nographic -net none The -net none is important otherwise it seems some events are generated causing the things to work. When it doesn't work, the guest hangs when measuring the CPU frequency, after the following line: [ 0.000000] NR_IRQS:256 Pressing a key on the serial port unblocks it, hinting that the problem is due to the recent elimination of the 1 second timeout in the main loop. The problem is that because init_timer_alarm sets the timer's pending flag to true, the alarm timer is never armed until after the first time through the main loop. Thus the bug started when QEMU started testing the pending flag in qemu_mod_timer (commit 1828be3, more alarm timer cleanup, 2010-03-10). But actually, it isn't true at all that a timer is pending when the alarm timer is created, and the real bug has been latent forever: the fix is to remove the bogus setting of pending flag. Reported-by: Aurelien Jarno Signed-off-by: Paolo Bonzini Reviewed-by: Jan Kiszka Tested-by: Aurelien Jarno Tested-by: Michael Tokarev Signed-off-by: Aurelien Jarno --- qemu-timer.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/qemu-timer.c b/qemu-timer.c index 5aea94e8e0..c7a1551a36 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -759,11 +759,8 @@ int init_timer_alarm(void) goto fail; } - /* first event is at time 0 */ atexit(quit_timers); - t->pending = true; alarm_timer = t; - return 0; fail: From 3eea5498ca501922520b3447ba94815bfc109743 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Tue, 4 Sep 2012 10:26:09 -0500 Subject: [PATCH 0160/2270] console: bounds check whenever changing the cursor due to an escape code This is XSA-17 / CVE-2012-3515 Signed-off-by: Ian Campbell Signed-off-by: Anthony Liguori --- console.c | 57 +++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/console.c b/console.c index f5e8814792..3b5cabba3a 100644 --- a/console.c +++ b/console.c @@ -850,6 +850,26 @@ static void console_clear_xy(TextConsole *s, int x, int y) update_xy(s, x, y); } +/* set cursor, checking bounds */ +static void set_cursor(TextConsole *s, int x, int y) +{ + if (x < 0) { + x = 0; + } + if (y < 0) { + y = 0; + } + if (y >= s->height) { + y = s->height - 1; + } + if (x >= s->width) { + x = s->width - 1; + } + + s->x = x; + s->y = y; +} + static void console_putchar(TextConsole *s, int ch) { TextCell *c; @@ -921,7 +941,8 @@ static void console_putchar(TextConsole *s, int ch) s->esc_params[s->nb_esc_params] * 10 + ch - '0'; } } else { - s->nb_esc_params++; + if (s->nb_esc_params < MAX_ESC_PARAMS) + s->nb_esc_params++; if (ch == ';') break; #ifdef DEBUG_CONSOLE @@ -935,59 +956,37 @@ static void console_putchar(TextConsole *s, int ch) if (s->esc_params[0] == 0) { s->esc_params[0] = 1; } - s->y -= s->esc_params[0]; - if (s->y < 0) { - s->y = 0; - } + set_cursor(s, s->x, s->y - s->esc_params[0]); break; case 'B': /* move cursor down */ if (s->esc_params[0] == 0) { s->esc_params[0] = 1; } - s->y += s->esc_params[0]; - if (s->y >= s->height) { - s->y = s->height - 1; - } + set_cursor(s, s->x, s->y + s->esc_params[0]); break; case 'C': /* move cursor right */ if (s->esc_params[0] == 0) { s->esc_params[0] = 1; } - s->x += s->esc_params[0]; - if (s->x >= s->width) { - s->x = s->width - 1; - } + set_cursor(s, s->x + s->esc_params[0], s->y); break; case 'D': /* move cursor left */ if (s->esc_params[0] == 0) { s->esc_params[0] = 1; } - s->x -= s->esc_params[0]; - if (s->x < 0) { - s->x = 0; - } + set_cursor(s, s->x - s->esc_params[0], s->y); break; case 'G': /* move cursor to column */ - s->x = s->esc_params[0] - 1; - if (s->x < 0) { - s->x = 0; - } + set_cursor(s, s->esc_params[0] - 1, s->y); break; case 'f': case 'H': /* move cursor to row, column */ - s->x = s->esc_params[1] - 1; - if (s->x < 0) { - s->x = 0; - } - s->y = s->esc_params[0] - 1; - if (s->y < 0) { - s->y = 0; - } + set_cursor(s, s->esc_params[1] - 1, s->esc_params[0] - 1); break; case 'J': switch (s->esc_params[0]) { From 8db972cfa469b4e4afd9c65e54e796b83b5ce3a2 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Wed, 5 Sep 2012 07:50:01 -0500 Subject: [PATCH 0161/2270] Update version for 1.2.0 Signed-off-by: Anthony Liguori --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 9a03ea6377..26aaba0e86 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.93 +1.2.0 From 835cab85ad83ed8dfe1c13243aeda5959b153e3e Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Mon, 13 Aug 2012 10:32:32 +0200 Subject: [PATCH 0162/2270] spice: abort on invalid streaming cmdline params When parsing its command line parameters, spice aborts when it finds unexpected values, except for the 'streaming-video' option. This happens because the parsing of the parameters for this option is done using the 'name2enum' helper, which does not error out on unknown values. Using the 'parse_name' helper makes sure we error out in this case. Looking at git history, the use of 'name2enum' instead of 'parse_name' seems to have been an oversight, so let's change to that now. Fixes rhbz#831708 Signed-off-by: Gerd Hoffmann --- ui/spice-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/spice-core.c b/ui/spice-core.c index 4fc48f8902..bb4f58584a 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -344,7 +344,8 @@ static const char *stream_video_names[] = { [ SPICE_STREAM_VIDEO_FILTER ] = "filter", }; #define parse_stream_video(_name) \ - name2enum(_name, stream_video_names, ARRAY_SIZE(stream_video_names)) + parse_name(_name, "stream video control", \ + stream_video_names, ARRAY_SIZE(stream_video_names)) static const char *compression_names[] = { [ SPICE_IMAGE_COMPRESS_OFF ] = "off", From f5bb039c6d97ef3e664094eab3c9a4dc1824ed73 Mon Sep 17 00:00:00 2001 From: Yonit Halperin Date: Tue, 21 Aug 2012 11:51:55 +0300 Subject: [PATCH 0163/2270] spice: notify spice server on vm start/stop Spice server needs to know about the vm state in order to prevent attempts to write to devices when they are stopped, mainly during the non-live stage of migration. Instead, spice will take care of restoring this writes, on the migration target side, after migration completes. Signed-off-by: Yonit Halperin Signed-off-by: Gerd Hoffmann --- ui/spice-core.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ui/spice-core.c b/ui/spice-core.c index bb4f58584a..a515c946ca 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -546,6 +546,18 @@ static int add_channel(const char *name, const char *value, void *opaque) return 0; } +static void vm_change_state_handler(void *opaque, int running, + RunState state) +{ +#if SPICE_SERVER_VERSION >= 0x000b02 /* 0.11.2 */ + if (running) { + spice_server_vm_start(spice_server); + } else { + spice_server_vm_stop(spice_server); + } +#endif +} + void qemu_spice_init(void) { QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head); @@ -719,6 +731,8 @@ void qemu_spice_init(void) qemu_spice_input_init(); qemu_spice_audio_init(); + qemu_add_vm_change_state_handler(vm_change_state_handler, &spice_server); + g_free(x509_key_file); g_free(x509_cert_file); g_free(x509_cacert_file); From 71d388d420e68ac77cd42f15f7e68cf5a6fb01b2 Mon Sep 17 00:00:00 2001 From: Yonit Halperin Date: Tue, 21 Aug 2012 11:51:56 +0300 Subject: [PATCH 0164/2270] spice: notify on vm state change only via spice_server_vm_start/stop QXLWorker->start/stop are deprecated since spice-server 0.11.2 Signed-off-by: Yonit Halperin Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 7 ++++--- ui/spice-core.c | 4 ++++ ui/spice-display.c | 32 ++++++++++++++++++++++++++++++-- ui/spice-display.h | 9 +++++++-- 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index c2dd3b471b..95bbc031c0 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -958,9 +958,10 @@ static void qxl_update_irq(PCIQXLDevice *d) static void qxl_check_state(PCIQXLDevice *d) { QXLRam *ram = d->ram; + int spice_display_running = qemu_spice_display_is_running(&d->ssd); - assert(!d->ssd.running || SPICE_RING_IS_EMPTY(&ram->cmd_ring)); - assert(!d->ssd.running || SPICE_RING_IS_EMPTY(&ram->cursor_ring)); + assert(!spice_display_running || SPICE_RING_IS_EMPTY(&ram->cmd_ring)); + assert(!spice_display_running || SPICE_RING_IS_EMPTY(&ram->cursor_ring)); } static void qxl_reset_state(PCIQXLDevice *d) @@ -1538,7 +1539,7 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events) uint32_t old_pending; uint32_t le_events = cpu_to_le32(events); - assert(d->ssd.running); + assert(qemu_spice_display_is_running(&d->ssd)); old_pending = __sync_fetch_and_or(&d->ram->int_pending, le_events); if ((old_pending & le_events) == le_events) { return; diff --git a/ui/spice-core.c b/ui/spice-core.c index a515c946ca..1a7a773457 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -37,6 +37,7 @@ #include "migration.h" #include "monitor.h" #include "hw/hw.h" +#include "spice-display.h" /* core bits */ @@ -551,9 +552,11 @@ static void vm_change_state_handler(void *opaque, int running, { #if SPICE_SERVER_VERSION >= 0x000b02 /* 0.11.2 */ if (running) { + qemu_spice_display_start(); spice_server_vm_start(spice_server); } else { spice_server_vm_stop(spice_server); + qemu_spice_display_stop(); } #endif } @@ -755,6 +758,7 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin) spice_server = spice_server_new(); spice_server_init(spice_server, &core_interface); } + return spice_server_add_interface(spice_server, sin); } diff --git a/ui/spice-display.c b/ui/spice-display.c index 3e8f0b3ad5..1c31418a4c 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -126,18 +126,44 @@ void qemu_spice_wakeup(SimpleSpiceDisplay *ssd) ssd->worker->wakeup(ssd->worker); } -void qemu_spice_start(SimpleSpiceDisplay *ssd) +#if SPICE_SERVER_VERSION < 0x000b02 /* before 0.11.2 */ +static void qemu_spice_start(SimpleSpiceDisplay *ssd) { trace_qemu_spice_start(ssd->qxl.id); ssd->worker->start(ssd->worker); } -void qemu_spice_stop(SimpleSpiceDisplay *ssd) +static void qemu_spice_stop(SimpleSpiceDisplay *ssd) { trace_qemu_spice_stop(ssd->qxl.id); ssd->worker->stop(ssd->worker); } +#else + +static int spice_display_is_running; + +void qemu_spice_display_start(void) +{ + spice_display_is_running = true; +} + +void qemu_spice_display_stop(void) +{ + spice_display_is_running = false; +} + +#endif + +int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd) +{ +#if SPICE_SERVER_VERSION < 0x000b02 /* before 0.11.2 */ + return ssd->running; +#else + return spice_display_is_running; +#endif +} + static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) { SimpleSpiceUpdate *update; @@ -272,6 +298,7 @@ void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd) void qemu_spice_vm_change_state_handler(void *opaque, int running, RunState state) { +#if SPICE_SERVER_VERSION < 0x000b02 /* before 0.11.2 */ SimpleSpiceDisplay *ssd = opaque; if (running) { @@ -281,6 +308,7 @@ void qemu_spice_vm_change_state_handler(void *opaque, int running, qemu_spice_stop(ssd); ssd->running = false; } +#endif } void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds) diff --git a/ui/spice-display.h b/ui/spice-display.h index 12e50b6efc..672d65ec32 100644 --- a/ui/spice-display.h +++ b/ui/spice-display.h @@ -82,7 +82,9 @@ struct SimpleSpiceDisplay { QXLRect dirty; int notify; +#if SPICE_SERVER_VERSION < 0x000b02 /* before 0.11.2 */ int running; +#endif /* * All struct members below this comment can be accessed from @@ -129,5 +131,8 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id, void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id, qxl_async_io async); void qemu_spice_wakeup(SimpleSpiceDisplay *ssd); -void qemu_spice_start(SimpleSpiceDisplay *ssd); -void qemu_spice_stop(SimpleSpiceDisplay *ssd); +#if SPICE_SERVER_VERSION >= 0x000b02 /* before 0.11.2 */ +void qemu_spice_display_start(void); +void qemu_spice_display_stop(void); +#endif +int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd); From 2fdd16e239c2a2763aa3266e637718123328688c Mon Sep 17 00:00:00 2001 From: Yonit Halperin Date: Tue, 21 Aug 2012 11:51:57 +0300 Subject: [PATCH 0165/2270] spice migration: add QEVENT_SPICE_MIGRATE_COMPLETED When migrating, libvirt queries the migration status, and upon migration completions, it closes the migration src. On the other hand, when migration is completed, spice transfers data from the src to destination via the client. This data is required for keeping the spice session after migration, without suffering from data loss and inconsistencies. In order to allow this data transfer, we add QEVENT for signaling libvirt that spice migration has completed, and libvirt needs to wait for this event before quitting the src process. Signed-off-by: Yonit Halperin Signed-off-by: Gerd Hoffmann --- monitor.c | 1 + monitor.h | 1 + ui/spice-core.c | 9 ++++++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/monitor.c b/monitor.c index b17b1bb849..413edf4b3e 100644 --- a/monitor.c +++ b/monitor.c @@ -455,6 +455,7 @@ static const char *monitor_event_names[] = { [QEVENT_SUSPEND_DISK] = "SUSPEND_DISK", [QEVENT_WAKEUP] = "WAKEUP", [QEVENT_BALLOON_CHANGE] = "BALLOON_CHANGE", + [QEVENT_SPICE_MIGRATE_COMPLETED] = "SPICE_MIGRATE_COMPLETED", }; QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX) diff --git a/monitor.h b/monitor.h index 47d556b9d1..5fc2983b94 100644 --- a/monitor.h +++ b/monitor.h @@ -43,6 +43,7 @@ typedef enum MonitorEvent { QEVENT_SUSPEND_DISK, QEVENT_WAKEUP, QEVENT_BALLOON_CHANGE, + QEVENT_SPICE_MIGRATE_COMPLETED, /* Add to 'monitor_event_names' array in monitor.c when * defining new events here */ diff --git a/ui/spice-core.c b/ui/spice-core.c index 1a7a773457..851e869ec6 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -285,6 +285,7 @@ typedef struct SpiceMigration { } SpiceMigration; static void migrate_connect_complete_cb(SpiceMigrateInstance *sin); +static void migrate_end_complete_cb(SpiceMigrateInstance *sin); static const SpiceMigrateInterface migrate_interface = { .base.type = SPICE_INTERFACE_MIGRATION, @@ -292,7 +293,7 @@ static const SpiceMigrateInterface migrate_interface = { .base.major_version = SPICE_INTERFACE_MIGRATION_MAJOR, .base.minor_version = SPICE_INTERFACE_MIGRATION_MINOR, .migrate_connect_complete = migrate_connect_complete_cb, - .migrate_end_complete = NULL, + .migrate_end_complete = migrate_end_complete_cb, }; static SpiceMigration spice_migrate; @@ -305,6 +306,11 @@ static void migrate_connect_complete_cb(SpiceMigrateInstance *sin) } sm->connect_complete.cb = NULL; } + +static void migrate_end_complete_cb(SpiceMigrateInstance *sin) +{ + monitor_protocol_event(QEVENT_SPICE_MIGRATE_COMPLETED, NULL); +} #endif /* config string parsing */ @@ -489,6 +495,7 @@ static void migration_state_notifier(Notifier *notifier, void *data) } else if (migration_has_finished(s)) { #ifndef SPICE_INTERFACE_MIGRATION spice_server_migrate_switch(spice_server); + monitor_protocol_event(QEVENT_SPICE_MIGRATE_COMPLETED, NULL); #else spice_server_migrate_end(spice_server, true); } else if (migration_has_failed(s)) { From 61c4efe2cb85b0a9c6bc68f6a2dd107c8d7ec080 Mon Sep 17 00:00:00 2001 From: Yonit Halperin Date: Tue, 21 Aug 2012 11:51:58 +0300 Subject: [PATCH 0166/2270] spice: add 'migrated' flag to spice info The flag is 'true' when spice migration has completed on the src side. It is needed for a case where libvirt dies before migration completes and it misses the event QEVENT_SPICE_MIGRATE_COMPLETED. When libvirt is restored and queries the migration status, it also needs to query spice and check if its migration has completed. Signed-off-by: Yonit Halperin Signed-off-by: Gerd Hoffmann --- hmp.c | 2 ++ qapi-schema.json | 5 ++++- ui/spice-core.c | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/hmp.c b/hmp.c index 81c8acb67a..ec4274b3da 100644 --- a/hmp.c +++ b/hmp.c @@ -413,6 +413,8 @@ void hmp_info_spice(Monitor *mon) monitor_printf(mon, " address: %s:%" PRId64 " [tls]\n", info->host, info->tls_port); } + monitor_printf(mon, " migrated: %s\n", + info->migrated ? "true" : "false"); monitor_printf(mon, " auth: %s\n", info->auth); monitor_printf(mon, " compiled: %s\n", info->compiled_version); monitor_printf(mon, " mouse-mode: %s\n", diff --git a/qapi-schema.json b/qapi-schema.json index bd8ad74495..8ddde1298c 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -808,6 +808,9 @@ # # @enabled: true if the SPICE server is enabled, false otherwise # +# @migrated: true if the last guest migration completed and spice +# migration had completed as well. false otherwise. +# # @host: #optional The hostname the SPICE server is bound to. This depends on # the name resolution on the host and may be an IP address. # @@ -833,7 +836,7 @@ # Since: 0.14.0 ## { 'type': 'SpiceInfo', - 'data': {'enabled': 'bool', '*host': 'str', '*port': 'int', + 'data': {'enabled': 'bool', 'migrated': 'bool', '*host': 'str', '*port': 'int', '*tls-port': 'int', '*auth': 'str', '*compiled-version': 'str', 'mouse-mode': 'SpiceQueryMouseMode', '*channels': ['SpiceChannel']} } diff --git a/ui/spice-core.c b/ui/spice-core.c index 851e869ec6..ab069c5b69 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -46,6 +46,7 @@ static Notifier migration_state; static const char *auth = "spice"; static char *auth_passwd; static time_t auth_expires = TIME_MAX; +static int spice_migration_completed; int using_spice = 0; static QemuThread me; @@ -310,6 +311,7 @@ static void migrate_connect_complete_cb(SpiceMigrateInstance *sin) static void migrate_end_complete_cb(SpiceMigrateInstance *sin) { monitor_protocol_event(QEVENT_SPICE_MIGRATE_COMPLETED, NULL); + spice_migration_completed = true; } #endif @@ -443,6 +445,7 @@ SpiceInfo *qmp_query_spice(Error **errp) } info->enabled = true; + info->migrated = spice_migration_completed; addr = qemu_opt_get(opts, "addr"); port = qemu_opt_get_number(opts, "port", 0); @@ -496,6 +499,7 @@ static void migration_state_notifier(Notifier *notifier, void *data) #ifndef SPICE_INTERFACE_MIGRATION spice_server_migrate_switch(spice_server); monitor_protocol_event(QEVENT_SPICE_MIGRATE_COMPLETED, NULL); + spice_migration_completed = true; #else spice_server_migrate_end(spice_server, true); } else if (migration_has_failed(s)) { From 8c9570530c819821b9b5cc3113d2b2966afe7621 Mon Sep 17 00:00:00 2001 From: Yonit Halperin Date: Tue, 21 Aug 2012 11:51:59 +0300 Subject: [PATCH 0167/2270] spice: adding seamless-migration option to the command line The seamless-migration flag is required in order to identify whether libvirt supports the new QEVENT_SPICE_MIGRATE_COMPLETED or not (by default the flag is off). New libvirt versions that wait for QEVENT_SPICE_MIGRATE_COMPLETED should turn on this flag. When this flag is off, spice fallbacks to its old migration method, which can result in data loss. Signed-off-by: Yonit Halperin Signed-off-by: Gerd Hoffmann --- qemu-config.c | 3 +++ qemu-options.hx | 3 +++ ui/spice-core.c | 7 +++++++ 3 files changed, 13 insertions(+) diff --git a/qemu-config.c b/qemu-config.c index c05ffbc444..eba977ebca 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -537,6 +537,9 @@ QemuOptsList qemu_spice_opts = { },{ .name = "playback-compression", .type = QEMU_OPT_BOOL, + }, { + .name = "seamless-migration", + .type = QEMU_OPT_BOOL, }, { /* end of list */ } }, diff --git a/qemu-options.hx b/qemu-options.hx index 3c411c427e..96a7bb192e 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -920,6 +920,9 @@ Enable/disable passing mouse events via vdagent. Default is on. @item playback-compression=[on|off] Enable/disable audio stream compression (using celt 0.5.1). Default is on. +@item seamless-migration=[on|off] +Enable/disable spice seamless migration. Default is off. + @end table ETEXI diff --git a/ui/spice-core.c b/ui/spice-core.c index ab069c5b69..ba0d0bdbc2 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -585,6 +585,9 @@ void qemu_spice_init(void) int port, tls_port, len, addr_flags; spice_image_compression_t compression; spice_wan_compression_t wan_compr; +#if SPICE_SERVER_VERSION >= 0x000b02 /* 0.11.2 */ + bool seamless_migration; +#endif qemu_thread_get_self(&me); @@ -728,6 +731,10 @@ void qemu_spice_init(void) spice_server_set_uuid(spice_server, qemu_uuid); #endif +#if SPICE_SERVER_VERSION >= 0x000b02 /* 0.11.2 */ + seamless_migration = qemu_opt_get_bool(opts, "seamless-migration", 0); + spice_server_set_seamless_migration(spice_server, seamless_migration); +#endif if (0 != spice_server_init(spice_server, &core_interface)) { error_report("failed to initialize spice server"); exit(1); From 27af778828db9aa893fa1de928744141e5de20e5 Mon Sep 17 00:00:00 2001 From: Yonit Halperin Date: Tue, 21 Aug 2012 13:54:20 +0300 Subject: [PATCH 0168/2270] spice: increase the verbosity of spice section in "qemu --help" Added all spice options to the help string. This can be used by libvirt to determine which spice related features are supported by qemu. Signed-off-by: Yonit Halperin Signed-off-by: Gerd Hoffmann --- qemu-options.hx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/qemu-options.hx b/qemu-options.hx index 96a7bb192e..804a2d1739 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -838,7 +838,23 @@ Enable SDL. ETEXI DEF("spice", HAS_ARG, QEMU_OPTION_spice, - "-spice enable spice\n", QEMU_ARCH_ALL) + "-spice [port=port][,tls-port=secured-port][,x509-dir=

]\n" + " [,x509-key-file=][,x509-key-password=]\n" + " [,x509-cert-file=][,x509-cacert-file=]\n" + " [,x509-dh-key-file=][,addr=addr][,ipv4|ipv6]\n" + " [,tls-ciphers=]\n" + " [,tls-channel=[main|display|cursor|inputs|record|playback]]\n" + " [,plaintext-channel=[main|display|cursor|inputs|record|playback]]\n" + " [,sasl][,password=][,disable-ticketing]\n" + " [,image-compression=[auto_glz|auto_lz|quic|glz|lz|off]]\n" + " [,jpeg-wan-compression=[auto|never|always]]\n" + " [,zlib-glz-wan-compression=[auto|never|always]]\n" + " [,streaming-video=[off|all|filter]][,disable-copy-paste]\n" + " [,agent-mouse=[on|off]][,playback-compression=[on|off]]\n" + " [,seamless-migration=[on|off]]\n" + " enable spice\n" + " at least one of {port, tls-port} is mandatory\n", + QEMU_ARCH_ALL) STEXI @item -spice @var{option}[,@var{option}[,...]] @findex -spice From 511b13e2c9b426b3c56060909693de5097f0b496 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Tue, 21 Aug 2012 13:51:31 +0300 Subject: [PATCH 0169/2270] qxl/update_area_io: guest_bug on invalid parameters Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hw/qxl.c b/hw/qxl.c index 95bbc031c0..baf9bb4dfb 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1386,6 +1386,18 @@ async_common: QXLCookie *cookie = NULL; QXLRect update = d->ram->update_area; + if (d->ram->update_surface > NUM_SURFACES) { + qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: invalid surface id %d\n", + d->ram->update_surface); + return; + } + if (update.left >= update.right || update.top >= update.bottom) { + qxl_set_guest_bug(d, + "QXL_IO_UPDATE_AREA: invalid area (%ux%u)x(%ux%u)\n", + update.left, update.top, update.right, update.bottom); + return; + } + if (async == QXL_ASYNC) { cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO, QXL_IO_UPDATE_AREA_ASYNC); From 36839d355e4ffc77d8f937caa6bb4c5530b9237e Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Tue, 21 Aug 2012 13:51:32 +0300 Subject: [PATCH 0170/2270] qxl: disallow unknown revisions Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/qxl.c b/hw/qxl.c index baf9bb4dfb..d134a701de 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1798,10 +1798,13 @@ static int qxl_init_common(PCIQXLDevice *qxl) io_size = 16; break; case 3: /* qxl-3 */ - default: pci_device_rev = QXL_DEFAULT_REVISION; io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1); break; + default: + error_report("Invalid revision %d for qxl device (max %d)", + qxl->revision, QXL_DEFAULT_REVISION); + return -1; } pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev); From 020af1c45fec664d5d4cf3b8e5117f8bc1d691f2 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Wed, 22 Aug 2012 11:16:25 +0300 Subject: [PATCH 0171/2270] qxl: add QXL_IO_MONITORS_CONFIG_ASYNC Revision bumped to 4 for new IO support, enabled for spice-server >= 0.11.1. New io enabled if revision is 4. Revision can be set to 4. [ kraxel: 3 continues to be the default revision. Once we have a new stable spice-server release and the qemu patches to enable the new bits merged we'll go flip the switch and make rev4 the default ] This io calls the corresponding new spice api spice_qxl_monitors_config_async to let spice-server read a new guest set monitors config and notify the client. On migration reissue spice_qxl_monitors_config_async. RHBZ: 770842 Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann fixup Signed-off-by: Gerd Hoffmann --- configure | 7 ++++ hw/qxl.c | 97 ++++++++++++++++++++++++++++++++++++++++++++-- hw/qxl.h | 7 ++++ trace-events | 1 + ui/spice-display.h | 1 + 5 files changed, 109 insertions(+), 4 deletions(-) diff --git a/configure b/configure index d97fd81709..59521ea69c 100755 --- a/configure +++ b/configure @@ -2701,6 +2701,9 @@ EOF spice="yes" libs_softmmu="$libs_softmmu $spice_libs" QEMU_CFLAGS="$QEMU_CFLAGS $spice_cflags" + if $pkg_config --atleast-version=0.12.0 spice-protocol >/dev/null 2>&1; then + spice_qxl_io_monitors_config_async="yes" + fi else if test "$spice" = "yes" ; then feature_not_found "spice" @@ -3438,6 +3441,10 @@ if test "$spice" = "yes" ; then echo "CONFIG_SPICE=y" >> $config_host_mak fi +if test "$spice_qxl_io_monitors_config_async" = "yes" ; then + echo "CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC=y" >> $config_host_mak +fi + if test "$smartcard" = "yes" ; then echo "CONFIG_SMARTCARD=y" >> $config_host_mak fi diff --git a/hw/qxl.c b/hw/qxl.c index d134a701de..adf17fd79b 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -27,6 +27,11 @@ #include "qxl.h" +#ifndef CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC +/* spice-protocol is too old, add missing definitions */ +#define QXL_IO_MONITORS_CONFIG_ASYNC (QXL_IO_FLUSH_RELEASE + 1) +#endif + /* * NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as * such can be changed by the guest, so to avoid a guest trigerrable @@ -249,6 +254,39 @@ static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async) } } +static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay) +{ + trace_qxl_spice_monitors_config(qxl->id); +/* 0x000b01 == 0.11.1 */ +#if SPICE_SERVER_VERSION >= 0x000b01 && \ + defined(CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC) + if (replay) { + /* + * don't use QXL_COOKIE_TYPE_IO: + * - we are not running yet (post_load), we will assert + * in send_events + * - this is not a guest io, but a reply, so async_io isn't set. + */ + spice_qxl_monitors_config_async(&qxl->ssd.qxl, + qxl->guest_monitors_config, + MEMSLOT_GROUP_GUEST, + (uintptr_t)qxl_cookie_new( + QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG, + 0)); + } else { + qxl->guest_monitors_config = qxl->ram->monitors_config; + spice_qxl_monitors_config_async(&qxl->ssd.qxl, + qxl->ram->monitors_config, + MEMSLOT_GROUP_GUEST, + (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO, + QXL_IO_MONITORS_CONFIG_ASYNC)); + } +#else + fprintf(stderr, "qxl: too old spice-protocol/spice-server for " + "QXL_IO_MONITORS_CONFIG_ASYNC\n"); +#endif +} + void qxl_spice_reset_image_cache(PCIQXLDevice *qxl) { trace_qxl_spice_reset_image_cache(qxl->id); @@ -538,6 +576,7 @@ static const char *io_port_to_string(uint32_t io_port) = "QXL_IO_DESTROY_ALL_SURFACES_ASYNC", [QXL_IO_FLUSH_SURFACES_ASYNC] = "QXL_IO_FLUSH_SURFACES_ASYNC", [QXL_IO_FLUSH_RELEASE] = "QXL_IO_FLUSH_RELEASE", + [QXL_IO_MONITORS_CONFIG_ASYNC] = "QXL_IO_MONITORS_CONFIG_ASYNC", }; return io_port_to_string[io_port]; } @@ -819,6 +858,7 @@ static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie) case QXL_IO_DESTROY_PRIMARY_ASYNC: case QXL_IO_UPDATE_AREA_ASYNC: case QXL_IO_FLUSH_SURFACES_ASYNC: + case QXL_IO_MONITORS_CONFIG_ASYNC: break; case QXL_IO_CREATE_PRIMARY_ASYNC: qxl_create_guest_primary_complete(qxl); @@ -894,6 +934,8 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token) case QXL_COOKIE_TYPE_RENDER_UPDATE_AREA: qxl_render_update_area_done(qxl, cookie); break; + case QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG: + break; default: fprintf(stderr, "qxl: %s: unexpected cookie type %d\n", __func__, cookie->type); @@ -1315,6 +1357,13 @@ static void ioport_write(void *opaque, target_phys_addr_t addr, return; } + if (d->revision <= QXL_REVISION_STABLE_V10 && + io_port >= QXL_IO_FLUSH_SURFACES_ASYNC) { + qxl_set_guest_bug(d, "unsupported io %d for revision %d\n", + io_port, d->revision); + return; + } + switch (io_port) { case QXL_IO_RESET: case QXL_IO_SET_MODE: @@ -1334,7 +1383,7 @@ static void ioport_write(void *opaque, target_phys_addr_t addr, io_port, io_port_to_string(io_port)); /* be nice to buggy guest drivers */ if (io_port >= QXL_IO_UPDATE_AREA_ASYNC && - io_port <= QXL_IO_DESTROY_ALL_SURFACES_ASYNC) { + io_port < QXL_IO_RANGE_SIZE) { qxl_send_events(d, QXL_INTERRUPT_IO_CMD); } return; @@ -1362,6 +1411,7 @@ static void ioport_write(void *opaque, target_phys_addr_t addr, io_port = QXL_IO_DESTROY_ALL_SURFACES; goto async_common; case QXL_IO_FLUSH_SURFACES_ASYNC: + case QXL_IO_MONITORS_CONFIG_ASYNC: async_common: async = QXL_ASYNC; qemu_mutex_lock(&d->async_lock); @@ -1503,6 +1553,9 @@ async_common: d->mode = QXL_MODE_UNDEFINED; qxl_spice_destroy_surfaces(d, async); break; + case QXL_IO_MONITORS_CONFIG_ASYNC: + qxl_spice_monitors_config_async(d, 0); + break; default: qxl_set_guest_bug(d, "%s: unexpected ioport=0x%x\n", __func__, io_port); } @@ -1798,9 +1851,17 @@ static int qxl_init_common(PCIQXLDevice *qxl) io_size = 16; break; case 3: /* qxl-3 */ - pci_device_rev = QXL_DEFAULT_REVISION; + pci_device_rev = QXL_REVISION_STABLE_V10; + io_size = 32; /* PCI region size must be pow2 */ + break; +/* 0x000b01 == 0.11.1 */ +#if SPICE_SERVER_VERSION >= 0x000b01 && \ + defined(CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC) + case 4: /* qxl-4 */ + pci_device_rev = QXL_REVISION_STABLE_V12; io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1); break; +#endif default: error_report("Invalid revision %d for qxl device (max %d)", qxl->revision, QXL_DEFAULT_REVISION); @@ -1999,7 +2060,9 @@ static int qxl_post_load(void *opaque, int version) } qxl_spice_loadvm_commands(d, cmds, out); g_free(cmds); - + if (d->guest_monitors_config) { + qxl_spice_monitors_config_async(d, 1); + } break; case QXL_MODE_COMPAT: /* note: no need to call qxl_create_memslots, qxl_set_mode @@ -2012,6 +2075,14 @@ static int qxl_post_load(void *opaque, int version) #define QXL_SAVE_VERSION 21 +static bool qxl_monitors_config_needed(void *opaque) +{ + PCIQXLDevice *qxl = opaque; + + return qxl->guest_monitors_config != 0; +} + + static VMStateDescription qxl_memslot = { .name = "qxl-memslot", .version_id = QXL_SAVE_VERSION, @@ -2042,6 +2113,16 @@ static VMStateDescription qxl_surface = { } }; +static VMStateDescription qxl_vmstate_monitors_config = { + .name = "qxl/monitors-config", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT64(guest_monitors_config, PCIQXLDevice), + VMSTATE_END_OF_LIST() + }, +}; + static VMStateDescription qxl_vmstate = { .name = "qxl", .version_id = QXL_SAVE_VERSION, @@ -2049,7 +2130,7 @@ static VMStateDescription qxl_vmstate = { .pre_save = qxl_pre_save, .pre_load = qxl_pre_load, .post_load = qxl_post_load, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(pci, PCIQXLDevice), VMSTATE_STRUCT(vga, PCIQXLDevice, 0, vmstate_vga_common, VGACommonState), VMSTATE_UINT32(shadow_rom.mode, PCIQXLDevice), @@ -2068,6 +2149,14 @@ static VMStateDescription qxl_vmstate = { VMSTATE_UINT64(guest_cursor, PCIQXLDevice), VMSTATE_END_OF_LIST() }, + .subsections = (VMStateSubsection[]) { + { + .vmsd = &qxl_vmstate_monitors_config, + .needed = qxl_monitors_config_needed, + }, { + /* empty */ + } + } }; static Property qxl_properties[] = { diff --git a/hw/qxl.h b/hw/qxl.h index 172baf6cc2..9cfedb72d1 100644 --- a/hw/qxl.h +++ b/hw/qxl.h @@ -71,6 +71,8 @@ typedef struct PCIQXLDevice { } guest_surfaces; QXLPHYSICAL guest_cursor; + QXLPHYSICAL guest_monitors_config; + QemuMutex track_lock; /* thread signaling */ @@ -128,7 +130,12 @@ typedef struct PCIQXLDevice { } \ } while (0) +#if 0 +/* spice-server 0.12 is still in development */ +#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V12 +#else #define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V10 +#endif /* qxl.c */ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id); diff --git a/trace-events b/trace-events index 04b0723927..8fcbc50f92 100644 --- a/trace-events +++ b/trace-events @@ -956,6 +956,7 @@ qxl_spice_destroy_surfaces(int qid, int async) "%d async=%d" qxl_spice_destroy_surface_wait_complete(int qid, uint32_t id) "%d sid=%d" qxl_spice_destroy_surface_wait(int qid, uint32_t id, int async) "%d sid=%d async=%d" qxl_spice_flush_surfaces_async(int qid, uint32_t surface_count, uint32_t num_free_res) "%d s#=%d, res#=%d" +qxl_spice_monitors_config(int id) "%d" qxl_spice_loadvm_commands(int qid, void *ext, uint32_t count) "%d ext=%p count=%d" qxl_spice_oom(int qid) "%d" qxl_spice_reset_cursor(int qid) "%d" diff --git a/ui/spice-display.h b/ui/spice-display.h index 672d65ec32..bcff1147bf 100644 --- a/ui/spice-display.h +++ b/ui/spice-display.h @@ -51,6 +51,7 @@ typedef enum qxl_async_io { enum { QXL_COOKIE_TYPE_IO, QXL_COOKIE_TYPE_RENDER_UPDATE_AREA, + QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG, }; typedef struct QXLCookie { From 2e0e3c399aa8067148055b9ea0edb822c5b584d2 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Wed, 22 Aug 2012 11:16:26 +0300 Subject: [PATCH 0172/2270] configure: print spice-protocol and spice-server versions Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- configure | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 59521ea69c..9592095d6a 100755 --- a/configure +++ b/configure @@ -2701,6 +2701,8 @@ EOF spice="yes" libs_softmmu="$libs_softmmu $spice_libs" QEMU_CFLAGS="$QEMU_CFLAGS $spice_cflags" + spice_protocol_version=$($pkg_config --modversion spice-protocol) + spice_server_version=$($pkg_config --modversion spice-server) if $pkg_config --atleast-version=0.12.0 spice-protocol >/dev/null 2>&1; then spice_qxl_io_monitors_config_async="yes" fi @@ -3159,7 +3161,7 @@ echo "libcap-ng support $cap_ng" echo "vhost-net support $vhost_net" echo "Trace backend $trace_backend" echo "Trace output file $trace_file-" -echo "spice support $spice" +echo "spice support $spice ($spice_protocol_version/$spice_server_version)" echo "rbd support $rbd" echo "xfsctl support $xfs" echo "nss used $smartcard_nss" From ddd8fdc78ee30fc445e3d1f5bd2056acfcdefe47 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 4 Sep 2012 11:39:41 +0200 Subject: [PATCH 0173/2270] spice: make number of surfaces runtime-configurable. Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 31 +++++++++++++++++-------------- hw/qxl.h | 3 +-- ui/spice-display.c | 5 ++++- ui/spice-display.h | 3 +-- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index adf17fd79b..8725f67d4b 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -236,7 +236,8 @@ static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl) { trace_qxl_spice_destroy_surfaces_complete(qxl->id); qemu_mutex_lock(&qxl->track_lock); - memset(&qxl->guest_surfaces.cmds, 0, sizeof(qxl->guest_surfaces.cmds)); + memset(qxl->guest_surfaces.cmds, 0, + sizeof(qxl->guest_surfaces.cmds) * qxl->ssd.num_surfaces); qxl->guest_surfaces.count = 0; qemu_mutex_unlock(&qxl->track_lock); } @@ -345,7 +346,7 @@ static void init_qxl_rom(PCIQXLDevice *d) rom->slot_id_bits = MEMSLOT_SLOT_BITS; rom->slots_start = 1; rom->slots_end = NUM_MEMSLOTS - 1; - rom->n_surfaces = cpu_to_le32(NUM_SURFACES); + rom->n_surfaces = cpu_to_le32(d->ssd.num_surfaces); for (i = 0, n = 0; i < ARRAY_SIZE(qxl_modes); i++) { fb = qxl_modes[i].y_res * qxl_modes[i].stride; @@ -449,9 +450,9 @@ static int qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext) } uint32_t id = le32_to_cpu(cmd->surface_id); - if (id >= NUM_SURFACES) { + if (id >= qxl->ssd.num_surfaces) { qxl_set_guest_bug(qxl, "QXL_CMD_SURFACE id %d >= %d", id, - NUM_SURFACES); + qxl->ssd.num_surfaces); return 1; } qemu_mutex_lock(&qxl->track_lock); @@ -527,7 +528,7 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info) info->num_memslots_groups = NUM_MEMSLOTS_GROUPS; info->internal_groupslot_id = 0; info->qxl_ram_size = le32_to_cpu(qxl->shadow_rom.num_pages) << TARGET_PAGE_BITS; - info->n_surfaces = NUM_SURFACES; + info->n_surfaces = qxl->ssd.num_surfaces; } static const char *qxl_mode_to_string(int mode) @@ -1436,7 +1437,7 @@ async_common: QXLCookie *cookie = NULL; QXLRect update = d->ram->update_area; - if (d->ram->update_surface > NUM_SURFACES) { + if (d->ram->update_surface > d->ssd.num_surfaces) { qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: invalid surface id %d\n", d->ram->update_surface); return; @@ -1529,7 +1530,7 @@ async_common: } break; case QXL_IO_DESTROY_SURFACE_WAIT: - if (val >= NUM_SURFACES) { + if (val >= d->ssd.num_surfaces) { qxl_set_guest_bug(d, "QXL_IO_DESTROY_SURFACE (async=%d):" "%" PRIu64 " >= NUM_SURFACES", async, val); goto cancel_async; @@ -1707,7 +1708,7 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl) vram_start = (intptr_t)memory_region_get_ram_ptr(&qxl->vram_bar); /* dirty the off-screen surfaces */ - for (i = 0; i < NUM_SURFACES; i++) { + for (i = 0; i < qxl->ssd.num_surfaces; i++) { QXLSurfaceCmd *cmd; intptr_t surface_offset; int surface_size; @@ -1835,7 +1836,6 @@ static int qxl_init_common(PCIQXLDevice *qxl) qxl->mode = QXL_MODE_UNDEFINED; qxl->generation = 1; qxl->num_memslots = NUM_MEMSLOTS; - qxl->num_surfaces = NUM_SURFACES; qemu_mutex_init(&qxl->track_lock); qemu_mutex_init(&qxl->async_lock); qxl->current_async = QXL_UNDEFINED_IO; @@ -1877,6 +1877,7 @@ static int qxl_init_common(PCIQXLDevice *qxl) init_qxl_rom(qxl); init_qxl_ram(qxl); + qxl->guest_surfaces.cmds = g_new0(QXLPHYSICAL, qxl->ssd.num_surfaces); memory_region_init_ram(&qxl->vram_bar, "qxl.vram", qxl->vram_size); vmstate_register_ram(&qxl->vram_bar, &qxl->pci.qdev); memory_region_init_alias(&qxl->vram32_bar, "qxl.vram32", &qxl->vram_bar, @@ -2042,8 +2043,8 @@ static int qxl_post_load(void *opaque, int version) qxl_create_guest_primary(d, 1, QXL_SYNC); /* replay surface-create and cursor-set commands */ - cmds = g_malloc0(sizeof(QXLCommandExt) * (NUM_SURFACES + 1)); - for (in = 0, out = 0; in < NUM_SURFACES; in++) { + cmds = g_malloc0(sizeof(QXLCommandExt) * (d->ssd.num_surfaces + 1)); + for (in = 0, out = 0; in < d->ssd.num_surfaces; in++) { if (d->guest_surfaces.cmds[in] == 0) { continue; } @@ -2143,9 +2144,10 @@ static VMStateDescription qxl_vmstate = { qxl_memslot, struct guest_slots), VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, 0, qxl_surface, QXLSurfaceCreate), - VMSTATE_INT32_EQUAL(num_surfaces, PCIQXLDevice), - VMSTATE_ARRAY(guest_surfaces.cmds, PCIQXLDevice, NUM_SURFACES, 0, - vmstate_info_uint64, uint64_t), + VMSTATE_INT32_EQUAL(ssd.num_surfaces, PCIQXLDevice), + VMSTATE_VARRAY_INT32(guest_surfaces.cmds, PCIQXLDevice, + ssd.num_surfaces, 0, + vmstate_info_uint64, uint64_t), VMSTATE_UINT64(guest_cursor, PCIQXLDevice), VMSTATE_END_OF_LIST() }, @@ -2173,6 +2175,7 @@ static Property qxl_properties[] = { DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram32_size_mb, -1), DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, -1), DEFINE_PROP_UINT32("vgamem_mb", PCIQXLDevice, vgamem_size_mb, 16), + DEFINE_PROP_INT32("surfaces", PCIQXLDevice, ssd.num_surfaces, 1024), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/qxl.h b/hw/qxl.h index 9cfedb72d1..5553824bee 100644 --- a/hw/qxl.h +++ b/hw/qxl.h @@ -40,7 +40,6 @@ typedef struct PCIQXLDevice { uint32_t revision; int32_t num_memslots; - int32_t num_surfaces; uint32_t current_async; QemuMutex async_lock; @@ -65,7 +64,7 @@ typedef struct PCIQXLDevice { } guest_primary; struct surfaces { - QXLPHYSICAL cmds[NUM_SURFACES]; + QXLPHYSICAL *cmds; uint32_t count; uint32_t max; } guest_surfaces; diff --git a/ui/spice-display.c b/ui/spice-display.c index 1c31418a4c..99bc665bc7 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -317,6 +317,9 @@ void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds) qemu_mutex_init(&ssd->lock); ssd->mouse_x = -1; ssd->mouse_y = -1; + if (ssd->num_surfaces == 0) { + ssd->num_surfaces = 1024; + } ssd->bufsize = (16 * 1024 * 1024); ssd->buf = g_malloc(ssd->bufsize); } @@ -427,7 +430,7 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info) info->num_memslots_groups = NUM_MEMSLOTS_GROUPS; info->internal_groupslot_id = 0; info->qxl_ram_size = ssd->bufsize; - info->n_surfaces = NUM_SURFACES; + info->n_surfaces = ssd->num_surfaces; } static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) diff --git a/ui/spice-display.h b/ui/spice-display.h index bcff1147bf..512ab7831b 100644 --- a/ui/spice-display.h +++ b/ui/spice-display.h @@ -32,8 +32,6 @@ #define MEMSLOT_GROUP_GUEST 1 #define NUM_MEMSLOTS_GROUPS 2 -#define NUM_SURFACES 1024 - /* * Internal enum to differenciate between options for * io calls that have a sync (old) version and an _async (new) @@ -80,6 +78,7 @@ struct SimpleSpiceDisplay { QXLInstance qxl; uint32_t unique; QemuPfConv *conv; + int32_t num_surfaces; QXLRect dirty; int notify; From c10018d6c77c94a8c703b9e4f026da74cad73d9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Sandmann=20Pedersen?= Date: Tue, 4 Sep 2012 10:14:48 -0400 Subject: [PATCH 0174/2270] qxl: Add set_client_capabilities() interface to QXLInterface This new interface lets spice server inform the guest whether (a) a client is connected (b) what capabilities the client has There is a fixed number (464) of bits reserved for capabilities, and when the capabilities bits change, the QXL_INTERRUPT_CLIENT interrupt is generated. Signed-off-by: Soren Sandmann Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/hw/qxl.c b/hw/qxl.c index 8725f67d4b..2aa58485c2 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -944,6 +944,26 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token) } } +#if SPICE_SERVER_VERSION >= 0x000b04 + +/* called from spice server thread context only */ +static void interface_set_client_capabilities(QXLInstance *sin, + uint8_t client_present, + uint8_t caps[58]) +{ + PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); + + qxl->shadow_rom.client_present = client_present; + memcpy(qxl->shadow_rom.client_capabilities, caps, sizeof(caps)); + qxl->rom->client_present = client_present; + memcpy(qxl->rom->client_capabilities, caps, sizeof(caps)); + qxl_rom_set_dirty(qxl); + + qxl_send_events(qxl, QXL_INTERRUPT_CLIENT); +} + +#endif + static const QXLInterface qxl_interface = { .base.type = SPICE_INTERFACE_QXL, .base.description = "qxl gpu", @@ -965,6 +985,9 @@ static const QXLInterface qxl_interface = { .flush_resources = interface_flush_resources, .async_complete = interface_async_complete, .update_area_complete = interface_update_area_complete, +#if SPICE_SERVER_VERSION >= 0x000b04 + .set_client_capabilities = interface_set_client_capabilities, +#endif }; static void qxl_enter_vga_mode(PCIQXLDevice *d) From 265db734901df7d8f24796ad7c43923249651289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Sandmann=20Pedersen?= Date: Tue, 4 Sep 2012 10:14:49 -0400 Subject: [PATCH 0175/2270] Remove #ifdef QXL_COMMAND_FLAG_COMPAT_16BPP We require spice >= 0.8 now, so this flag is always present. Signed-off-by: Soren Sandmann Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 2aa58485c2..b726c194b4 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1359,11 +1359,9 @@ static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm) d->mode = QXL_MODE_COMPAT; d->cmdflags = QXL_COMMAND_FLAG_COMPAT; -#ifdef QXL_COMMAND_FLAG_COMPAT_16BPP /* new in spice 0.6.1 */ if (mode->bits == 16) { d->cmdflags |= QXL_COMMAND_FLAG_COMPAT_16BPP; } -#endif d->shadow_rom.mode = cpu_to_le32(modenr); d->rom->mode = cpu_to_le32(modenr); qxl_rom_set_dirty(d); From f45ddd14209a4d1b95a4096d50a561b7f6270118 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Wed, 5 Sep 2012 11:44:53 -0500 Subject: [PATCH 0176/2270] Open up 1.3 development tree Signed-off-by: Anthony Liguori --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 26aaba0e86..99188f0c6f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.0 +1.2.50 From fa779b65fa77d5632df1f8b2df33e9023dbc4cc8 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 15 Aug 2012 11:33:47 +0100 Subject: [PATCH 0177/2270] Add support for pretty-printing response in qmp-shell Add a '-p' arg to the QMP/qmp-shell test program, which uses the python pprint module to pretty-print the dictionary returned from a command $ qmp-shell -p /tmp/qemu Welcome to the QMP low-level shell! Connected to QEMU 1.1.50 (QEMU) query-cpus { u'return': [ { u'CPU': 0, u'current': True, u'halted': True, u'pc': 1048556, u'thread_id': 7108}]} Signed-off-by: Daniel P. Berrange Signed-off-by: Luiz Capitulino --- QMP/qmp-shell | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/QMP/qmp-shell b/QMP/qmp-shell index 42dabc8c6d..24b665c8c0 100755 --- a/QMP/qmp-shell +++ b/QMP/qmp-shell @@ -33,6 +33,7 @@ import qmp import readline import sys +import pprint class QMPCompleter(list): def complete(self, text, state): @@ -52,10 +53,11 @@ class QMPShellBadPort(QMPShellError): # TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and # _execute_cmd()). Let's design a better one. class QMPShell(qmp.QEMUMonitorProtocol): - def __init__(self, address): + def __init__(self, address, pp=None): qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address)) self._greeting = None self._completer = None + self._pp = pp def __get_address(self, arg): """ @@ -114,7 +116,11 @@ class QMPShell(qmp.QEMUMonitorProtocol): if resp is None: print 'Disconnected' return False - print resp + + if self._pp is not None: + self._pp.pprint(resp) + else: + print resp return True def connect(self): @@ -222,22 +228,36 @@ def die(msg): def fail_cmdline(option=None): if option: sys.stderr.write('ERROR: bad command-line option \'%s\'\n' % option) - sys.stderr.write('qemu-shell [ -H ] < UNIX socket path> | < TCP address:port >\n') + sys.stderr.write('qemu-shell [ -p ] [ -H ] < UNIX socket path> | < TCP address:port >\n') sys.exit(1) def main(): addr = '' + qemu = None + hmp = False + pp = None + try: - if len(sys.argv) == 2: - qemu = QMPShell(sys.argv[1]) - addr = sys.argv[1] - elif len(sys.argv) == 3: - if sys.argv[1] != '-H': - fail_cmdline(sys.argv[1]) - qemu = HMPShell(sys.argv[2]) - addr = sys.argv[2] - else: - fail_cmdline() + for arg in sys.argv[1:]: + if arg == "-H": + if qemu is not None: + fail_cmdline(arg) + hmp = True + elif arg == "-p": + if pp is not None: + fail_cmdline(arg) + pp = pprint.PrettyPrinter(indent=4) + else: + if qemu is not None: + fail_cmdline(arg) + if hmp: + qemu = HMPShell(arg) + else: + qemu = QMPShell(arg, pp) + addr = arg + + if qemu is None: + fail_cmdline() except QMPShellBadPort: die('bad port number in command-line') From 886cc706ce5d4d3d1c296f028ddc2991cfbe3bbe Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Fri, 31 Aug 2012 10:56:20 +0800 Subject: [PATCH 0178/2270] fix doc of using raw values with sendkey (qemu) sendkey a (qemu) sendkey 0x1e (qemu) sendkey #0x1e unknown key: '#0x1e' The last command doesn't work, '#' is not requested before raw values, and the raw value in decimal format is not supported. Signed-off-by: Amos Kong Signed-off-by: Luiz Capitulino --- hmp-commands.hx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index f6104b099f..6a70a9c598 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -512,9 +512,9 @@ STEXI @item sendkey @var{keys} @findex sendkey -Send @var{keys} to the emulator. @var{keys} could be the name of the -key or @code{#} followed by the raw value in either decimal or hexadecimal -format. Use @code{-} to press several keys simultaneously. Example: +Send @var{keys} to the guest. @var{keys} could be the name of the +key or the raw value in hexadecimal format. Use @code{-} to press +several keys simultaneously. Example: @example sendkey ctrl-alt-f1 @end example From cd383492bfb5ea805d518e129d7a5402c7b99ef2 Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Fri, 31 Aug 2012 10:56:21 +0800 Subject: [PATCH 0179/2270] monitor: rename keyname '<' to 'less' There are many maps of keycode 0x56 in pc-bios/keymaps/* pc-bios/keymaps/common:less 0x56 pc-bios/keymaps/common:greater 0x56 shift pc-bios/keymaps/common:bar 0x56 altgr pc-bios/keymaps/common:brokenbar 0x56 shift altgr This patch just renamed '<' to 'less', QAPI might add new variable by adding a prefix to keyname, '$PREFIX_<' is not available, '$PREFIX_less' is ok. For compatibility, convert user inputted '<' to 'less'. Signed-off-by: Amos Kong Signed-off-by: Luiz Capitulino --- monitor.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/monitor.c b/monitor.c index b17b1bb849..c97c120062 100644 --- a/monitor.c +++ b/monitor.c @@ -1400,7 +1400,7 @@ static const KeyDef key_defs[] = { { 0x48, "kp_8" }, { 0x49, "kp_9" }, - { 0x56, "<" }, + { 0x56, "less" }, { 0x57, "f11" }, { 0x58, "f12" }, @@ -1504,6 +1504,13 @@ static void do_sendkey(Monitor *mon, const QDict *qdict) monitor_printf(mon, "too many keys\n"); return; } + + /* Be compatible with old interface, convert user inputted "<" */ + if (!strncmp(keyname_buf, "<", 1) && keyname_len == 1) { + pstrcpy(keyname_buf, sizeof(keyname_buf), "less"); + keyname_len = 4; + } + keyname_buf[keyname_len] = 0; keycode = get_keycode(keyname_buf); if (keycode < 0) { From 2ef20c15b4736c9b0afc7ef2b14239182fbcd3e1 Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Fri, 31 Aug 2012 10:56:22 +0800 Subject: [PATCH 0180/2270] hmp: rename arguments Rename 'string' to 'keys', rename 'hold_time' to 'hold-time'. Signed-off-by: Amos Kong Signed-off-by: Luiz Capitulino --- hmp-commands.hx | 2 +- monitor.c | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index 6a70a9c598..bd0c6c9191 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -502,7 +502,7 @@ ETEXI { .name = "sendkey", - .args_type = "string:s,hold_time:i?", + .args_type = "keys:s,hold-time:i?", .params = "keys [hold_ms]", .help = "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)", .mhandler.cmd = do_sendkey, diff --git a/monitor.c b/monitor.c index c97c120062..84176eb8f6 100644 --- a/monitor.c +++ b/monitor.c @@ -1480,9 +1480,9 @@ static void do_sendkey(Monitor *mon, const QDict *qdict) char keyname_buf[16]; char *separator; int keyname_len, keycode, i; - const char *string = qdict_get_str(qdict, "string"); - int has_hold_time = qdict_haskey(qdict, "hold_time"); - int hold_time = qdict_get_try_int(qdict, "hold_time", -1); + const char *keys = qdict_get_str(qdict, "keys"); + int has_hold_time = qdict_haskey(qdict, "hold-time"); + int hold_time = qdict_get_try_int(qdict, "hold-time", -1); if (nb_pending_keycodes > 0) { qemu_del_timer(key_timer); @@ -1492,10 +1492,10 @@ static void do_sendkey(Monitor *mon, const QDict *qdict) hold_time = 100; i = 0; while (1) { - separator = strchr(string, '-'); - keyname_len = separator ? separator - string : strlen(string); + separator = strchr(keys, '-'); + keyname_len = separator ? separator - keys : strlen(keys); if (keyname_len > 0) { - pstrcpy(keyname_buf, sizeof(keyname_buf), string); + pstrcpy(keyname_buf, sizeof(keyname_buf), keys); if (keyname_len > sizeof(keyname_buf) - 1) { monitor_printf(mon, "invalid key: '%s...'\n", keyname_buf); return; @@ -1521,7 +1521,7 @@ static void do_sendkey(Monitor *mon, const QDict *qdict) } if (!separator) break; - string = separator + 1; + keys = separator + 1; } nb_pending_keycodes = i; /* key down events */ From b9c4b48d50057b6aee7c70879b240ff76f39c85b Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Fri, 31 Aug 2012 10:56:23 +0800 Subject: [PATCH 0181/2270] qapi: generate list struct and visit_list for enum Currently, if we define an 'enum' and use it in one command's data, list struct for enum could not be generated, but it's used in qmp function. For example: KeyCodesList could not be generated. >>> qapi-schema.json: { 'enum': 'KeyCodes', 'data': [ 'shift', 'alt' ... ] } { 'command': 'sendkey', 'data': { 'keys': ['KeyCodes'], '*hold-time': 'int' } } >>> qmp-command.h: void qmp_sendkey(KeyCodesList * keys, bool has_hold_time, int64_t hold_time, Error **errp); This patch lets qapi generate list struct and visit_list for enum. Signed-off-by: Amos Kong Signed-off-by: Luiz Capitulino --- scripts/qapi-types.py | 16 +++++++++++++++- scripts/qapi-visit.py | 14 +++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index cf601ae2d2..49ef569a2f 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -28,6 +28,16 @@ typedef struct %(name)sList ''', name=name) +def generate_fwd_enum_struct(name, members): + return mcgen(''' +typedef struct %(name)sList +{ + %(name)s value; + struct %(name)sList *next; +} %(name)sList; +''', + name=name) + def generate_struct(structname, fieldname, members): ret = mcgen(''' struct %(name)s @@ -276,7 +286,8 @@ for expr in exprs: if expr.has_key('type'): ret += generate_fwd_struct(expr['type'], expr['data']) elif expr.has_key('enum'): - ret += generate_enum(expr['enum'], expr['data']) + ret += generate_enum(expr['enum'], expr['data']) + "\n" + ret += generate_fwd_enum_struct(expr['enum'], expr['data']) fdef.write(generate_enum_lookup(expr['enum'], expr['data'])) elif expr.has_key('union'): ret += generate_fwd_struct(expr['union'], expr['data']) + "\n" @@ -300,6 +311,9 @@ for expr in exprs: fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n") ret += generate_type_cleanup_decl(expr['union']) fdef.write(generate_type_cleanup(expr['union']) + "\n") + elif expr.has_key('enum'): + ret += generate_type_cleanup_decl(expr['enum'] + "List") + fdef.write(generate_type_cleanup(expr['enum'] + "List") + "\n") else: continue fdecl.write(ret) diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index 04ef7c41ab..cbec24da16 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -217,6 +217,16 @@ void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, return ret +def generate_enum_declaration(name, members, genlist=True): + ret = "" + if genlist: + ret += mcgen(''' +void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp); +''', + name=name) + + return ret + def generate_decl_enum(name, members, genlist=True): return mcgen(''' @@ -335,10 +345,12 @@ for expr in exprs: ret += generate_declaration(expr['union'], expr['data']) fdecl.write(ret) elif expr.has_key('enum'): - ret = generate_visit_enum(expr['enum'], expr['data']) + ret = generate_visit_list(expr['enum'], expr['data']) + ret += generate_visit_enum(expr['enum'], expr['data']) fdef.write(ret) ret = generate_decl_enum(expr['enum'], expr['data']) + ret += generate_enum_declaration(expr['enum'], expr['data']) fdecl.write(ret) fdecl.write(''' From 411656f48d71131d6d1cb5b6db792fc7b451e72e Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Fri, 31 Aug 2012 10:56:24 +0800 Subject: [PATCH 0182/2270] qapi: add the QKeyCode enum key_defs[] in monitor.c is a mapping table of keys and keycodes, this patch added a QKeyCode enum. Key's index in the enmu is same as keycode's index in key_defs[]. Signed-off-by: Amos Kong Signed-off-by: Luiz Capitulino --- qapi-schema.json | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/qapi-schema.json b/qapi-schema.json index bd8ad74495..856e11a729 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2493,3 +2493,29 @@ # Since: 1.2.0 ## { 'command': 'query-target', 'returns': 'TargetInfo' } + +## +# @QKeyCode: +# +# An enumeration of key name. +# +# This is used by the send-key command. +# +# Since: 1.3.0 +## +{ 'enum': 'QKeyCode', + 'data': [ 'shift', 'shift_r', 'alt', 'alt_r', 'altgr', 'altgr_r', 'ctrl', + 'ctrl_r', 'menu', 'esc', '1', '2', '3', '4', '5', '6', '7', '8', + '9', '0', 'minus', 'equal', 'backspace', 'tab', 'q', 'w', 'e', + 'r', 't', 'y', 'u', 'i', 'o', 'p', 'bracket_left', 'bracket_right', + 'ret', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'semicolon', + 'apostrophe', 'grave_accent', 'backslash', 'z', 'x', 'c', 'v', 'b', + 'n', 'm', 'comma', 'dot', 'slash', 'asterisk', 'spc', 'caps_lock', + 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10', + 'num_lock', 'scroll_lock', 'kp_divide', 'kp_multiply', + 'kp_subtract', 'kp_add', 'kp_enter', 'kp_decimal', 'sysrq', 'kp_0', + 'kp_1', 'kp_2', 'kp_3', 'kp_4', 'kp_5', 'kp_6', 'kp_7', 'kp_8', + 'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup', 'pgdn', 'end', + 'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again', + 'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut', + 'lf', 'help', 'meta_l', 'meta_r', 'compose' ] } From 1048c88f03545fa42bdebb077871a743a614d2ab Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Fri, 31 Aug 2012 10:56:25 +0800 Subject: [PATCH 0183/2270] monitor: move key_defs[] table and introduce two help functions This patch added two help functions to convert key/code to index of mapping table, those functions will return Q_KEY_CODE_MAX if the code/key is invalid. Patch also moved key_defs[] to input.c, and removed useless KeyDef struct. Key's index in QKeyCode enmu is same as keycode's index in new key_defs[]. Monitor functions were changed to access key_defs[] directly. key_defs[] is used in do_send_key(), so export key_defs[]. It will be changed to static in next patch. Signed-off-by: Amos Kong Signed-off-by: Luiz Capitulino --- console.h | 6 ++ input.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ monitor.c | 183 ++++------------------------------------------------- 3 files changed, 203 insertions(+), 172 deletions(-) diff --git a/console.h b/console.h index 4334db5ca5..7934b11894 100644 --- a/console.h +++ b/console.h @@ -6,6 +6,7 @@ #include "notify.h" #include "monitor.h" #include "trace.h" +#include "qapi-types.h" /* keyboard/mouse support */ @@ -397,4 +398,9 @@ static inline int vnc_display_pw_expire(DisplayState *ds, time_t expires) /* curses.c */ void curses_display_init(DisplayState *ds, int full_screen); +/* input.c */ +extern const int key_defs[]; +int index_from_key(const char *key); +int index_from_keycode(int code); + #endif diff --git a/input.c b/input.c index 6968b31781..5630cb19d1 100644 --- a/input.c +++ b/input.c @@ -37,6 +37,192 @@ static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers = static NotifierList mouse_mode_notifiers = NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers); +const int key_defs[] = { + [Q_KEY_CODE_SHIFT] = 0x2a, + [Q_KEY_CODE_SHIFT_R] = 0x36, + + [Q_KEY_CODE_ALT] = 0x38, + [Q_KEY_CODE_ALT_R] = 0xb8, + [Q_KEY_CODE_ALTGR] = 0x64, + [Q_KEY_CODE_ALTGR_R] = 0xe4, + [Q_KEY_CODE_CTRL] = 0x1d, + [Q_KEY_CODE_CTRL_R] = 0x9d, + + [Q_KEY_CODE_MENU] = 0xdd, + + [Q_KEY_CODE_ESC] = 0x01, + + [Q_KEY_CODE_1] = 0x02, + [Q_KEY_CODE_2] = 0x03, + [Q_KEY_CODE_3] = 0x04, + [Q_KEY_CODE_4] = 0x05, + [Q_KEY_CODE_5] = 0x06, + [Q_KEY_CODE_6] = 0x07, + [Q_KEY_CODE_7] = 0x08, + [Q_KEY_CODE_8] = 0x09, + [Q_KEY_CODE_9] = 0x0a, + [Q_KEY_CODE_0] = 0x0b, + [Q_KEY_CODE_MINUS] = 0x0c, + [Q_KEY_CODE_EQUAL] = 0x0d, + [Q_KEY_CODE_BACKSPACE] = 0x0e, + + [Q_KEY_CODE_TAB] = 0x0f, + [Q_KEY_CODE_Q] = 0x10, + [Q_KEY_CODE_W] = 0x11, + [Q_KEY_CODE_E] = 0x12, + [Q_KEY_CODE_R] = 0x13, + [Q_KEY_CODE_T] = 0x14, + [Q_KEY_CODE_Y] = 0x15, + [Q_KEY_CODE_U] = 0x16, + [Q_KEY_CODE_I] = 0x17, + [Q_KEY_CODE_O] = 0x18, + [Q_KEY_CODE_P] = 0x19, + [Q_KEY_CODE_BRACKET_LEFT] = 0x1a, + [Q_KEY_CODE_BRACKET_RIGHT] = 0x1b, + [Q_KEY_CODE_RET] = 0x1c, + + [Q_KEY_CODE_A] = 0x1e, + [Q_KEY_CODE_S] = 0x1f, + [Q_KEY_CODE_D] = 0x20, + [Q_KEY_CODE_F] = 0x21, + [Q_KEY_CODE_G] = 0x22, + [Q_KEY_CODE_H] = 0x23, + [Q_KEY_CODE_J] = 0x24, + [Q_KEY_CODE_K] = 0x25, + [Q_KEY_CODE_L] = 0x26, + [Q_KEY_CODE_SEMICOLON] = 0x27, + [Q_KEY_CODE_APOSTROPHE] = 0x28, + [Q_KEY_CODE_GRAVE_ACCENT] = 0x29, + + [Q_KEY_CODE_BACKSLASH] = 0x2b, + [Q_KEY_CODE_Z] = 0x2c, + [Q_KEY_CODE_X] = 0x2d, + [Q_KEY_CODE_C] = 0x2e, + [Q_KEY_CODE_V] = 0x2f, + [Q_KEY_CODE_B] = 0x30, + [Q_KEY_CODE_N] = 0x31, + [Q_KEY_CODE_M] = 0x32, + [Q_KEY_CODE_COMMA] = 0x33, + [Q_KEY_CODE_DOT] = 0x34, + [Q_KEY_CODE_SLASH] = 0x35, + + [Q_KEY_CODE_ASTERISK] = 0x37, + + [Q_KEY_CODE_SPC] = 0x39, + [Q_KEY_CODE_CAPS_LOCK] = 0x3a, + [Q_KEY_CODE_F1] = 0x3b, + [Q_KEY_CODE_F2] = 0x3c, + [Q_KEY_CODE_F3] = 0x3d, + [Q_KEY_CODE_F4] = 0x3e, + [Q_KEY_CODE_F5] = 0x3f, + [Q_KEY_CODE_F6] = 0x40, + [Q_KEY_CODE_F7] = 0x41, + [Q_KEY_CODE_F8] = 0x42, + [Q_KEY_CODE_F9] = 0x43, + [Q_KEY_CODE_F10] = 0x44, + [Q_KEY_CODE_NUM_LOCK] = 0x45, + [Q_KEY_CODE_SCROLL_LOCK] = 0x46, + + [Q_KEY_CODE_KP_DIVIDE] = 0xb5, + [Q_KEY_CODE_KP_MULTIPLY] = 0x37, + [Q_KEY_CODE_KP_SUBTRACT] = 0x4a, + [Q_KEY_CODE_KP_ADD] = 0x4e, + [Q_KEY_CODE_KP_ENTER] = 0x9c, + [Q_KEY_CODE_KP_DECIMAL] = 0x53, + [Q_KEY_CODE_SYSRQ] = 0x54, + + [Q_KEY_CODE_KP_0] = 0x52, + [Q_KEY_CODE_KP_1] = 0x4f, + [Q_KEY_CODE_KP_2] = 0x50, + [Q_KEY_CODE_KP_3] = 0x51, + [Q_KEY_CODE_KP_4] = 0x4b, + [Q_KEY_CODE_KP_5] = 0x4c, + [Q_KEY_CODE_KP_6] = 0x4d, + [Q_KEY_CODE_KP_7] = 0x47, + [Q_KEY_CODE_KP_8] = 0x48, + [Q_KEY_CODE_KP_9] = 0x49, + + [Q_KEY_CODE_LESS] = 0x56, + + [Q_KEY_CODE_F11] = 0x57, + [Q_KEY_CODE_F12] = 0x58, + + [Q_KEY_CODE_PRINT] = 0xb7, + + [Q_KEY_CODE_HOME] = 0xc7, + [Q_KEY_CODE_PGUP] = 0xc9, + [Q_KEY_CODE_PGDN] = 0xd1, + [Q_KEY_CODE_END] = 0xcf, + + [Q_KEY_CODE_LEFT] = 0xcb, + [Q_KEY_CODE_UP] = 0xc8, + [Q_KEY_CODE_DOWN] = 0xd0, + [Q_KEY_CODE_RIGHT] = 0xcd, + + [Q_KEY_CODE_INSERT] = 0xd2, + [Q_KEY_CODE_DELETE] = 0xd3, +#ifdef NEED_CPU_H +#if defined(TARGET_SPARC) && !defined(TARGET_SPARC64) + [Q_KEY_CODE_STOP] = 0xf0, + [Q_KEY_CODE_AGAIN] = 0xf1, + [Q_KEY_CODE_PROPS] = 0xf2, + [Q_KEY_CODE_UNDO] = 0xf3, + [Q_KEY_CODE_FRONT] = 0xf4, + [Q_KEY_CODE_COPY] = 0xf5, + [Q_KEY_CODE_OPEN] = 0xf6, + [Q_KEY_CODE_PASTE] = 0xf7, + [Q_KEY_CODE_FIND] = 0xf8, + [Q_KEY_CODE_CUT] = 0xf9, + [Q_KEY_CODE_LF] = 0xfa, + [Q_KEY_CODE_HELP] = 0xfb, + [Q_KEY_CODE_META_L] = 0xfc, + [Q_KEY_CODE_META_R] = 0xfd, + [Q_KEY_CODE_COMPOSE] = 0xfe, +#endif +#endif + [Q_KEY_CODE_MAX] = 0, +}; + +int index_from_key(const char *key) +{ + int i, keycode; + char *endp; + + for (i = 0; QKeyCode_lookup[i] != NULL; i++) { + if (!strcmp(key, QKeyCode_lookup[i])) { + break; + } + } + + if (strstart(key, "0x", NULL)) { + keycode = strtoul(key, &endp, 0); + if (*endp == '\0' && keycode >= 0x01 && keycode <= 0xff) { + for (i = 0; i < Q_KEY_CODE_MAX; i++) { + if (keycode == key_defs[i]) { + break; + } + } + } + } + + /* Return Q_KEY_CODE_MAX if the key is invalid */ + return i; +} + +int index_from_keycode(int code) +{ + int i; + + for (i = 0; i < Q_KEY_CODE_MAX; i++) { + if (key_defs[i] == code) { + break; + } + } + + /* Return Q_KEY_CODE_MAX if the code is invalid */ + return i; +} + void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) { qemu_put_kbd_event_opaque = opaque; diff --git a/monitor.c b/monitor.c index 84176eb8f6..0c4f86f639 100644 --- a/monitor.c +++ b/monitor.c @@ -1290,173 +1290,6 @@ static void do_sum(Monitor *mon, const QDict *qdict) monitor_printf(mon, "%05d\n", sum); } -typedef struct { - int keycode; - const char *name; -} KeyDef; - -static const KeyDef key_defs[] = { - { 0x2a, "shift" }, - { 0x36, "shift_r" }, - - { 0x38, "alt" }, - { 0xb8, "alt_r" }, - { 0x64, "altgr" }, - { 0xe4, "altgr_r" }, - { 0x1d, "ctrl" }, - { 0x9d, "ctrl_r" }, - - { 0xdd, "menu" }, - - { 0x01, "esc" }, - - { 0x02, "1" }, - { 0x03, "2" }, - { 0x04, "3" }, - { 0x05, "4" }, - { 0x06, "5" }, - { 0x07, "6" }, - { 0x08, "7" }, - { 0x09, "8" }, - { 0x0a, "9" }, - { 0x0b, "0" }, - { 0x0c, "minus" }, - { 0x0d, "equal" }, - { 0x0e, "backspace" }, - - { 0x0f, "tab" }, - { 0x10, "q" }, - { 0x11, "w" }, - { 0x12, "e" }, - { 0x13, "r" }, - { 0x14, "t" }, - { 0x15, "y" }, - { 0x16, "u" }, - { 0x17, "i" }, - { 0x18, "o" }, - { 0x19, "p" }, - { 0x1a, "bracket_left" }, - { 0x1b, "bracket_right" }, - { 0x1c, "ret" }, - - { 0x1e, "a" }, - { 0x1f, "s" }, - { 0x20, "d" }, - { 0x21, "f" }, - { 0x22, "g" }, - { 0x23, "h" }, - { 0x24, "j" }, - { 0x25, "k" }, - { 0x26, "l" }, - { 0x27, "semicolon" }, - { 0x28, "apostrophe" }, - { 0x29, "grave_accent" }, - - { 0x2b, "backslash" }, - { 0x2c, "z" }, - { 0x2d, "x" }, - { 0x2e, "c" }, - { 0x2f, "v" }, - { 0x30, "b" }, - { 0x31, "n" }, - { 0x32, "m" }, - { 0x33, "comma" }, - { 0x34, "dot" }, - { 0x35, "slash" }, - - { 0x37, "asterisk" }, - - { 0x39, "spc" }, - { 0x3a, "caps_lock" }, - { 0x3b, "f1" }, - { 0x3c, "f2" }, - { 0x3d, "f3" }, - { 0x3e, "f4" }, - { 0x3f, "f5" }, - { 0x40, "f6" }, - { 0x41, "f7" }, - { 0x42, "f8" }, - { 0x43, "f9" }, - { 0x44, "f10" }, - { 0x45, "num_lock" }, - { 0x46, "scroll_lock" }, - - { 0xb5, "kp_divide" }, - { 0x37, "kp_multiply" }, - { 0x4a, "kp_subtract" }, - { 0x4e, "kp_add" }, - { 0x9c, "kp_enter" }, - { 0x53, "kp_decimal" }, - { 0x54, "sysrq" }, - - { 0x52, "kp_0" }, - { 0x4f, "kp_1" }, - { 0x50, "kp_2" }, - { 0x51, "kp_3" }, - { 0x4b, "kp_4" }, - { 0x4c, "kp_5" }, - { 0x4d, "kp_6" }, - { 0x47, "kp_7" }, - { 0x48, "kp_8" }, - { 0x49, "kp_9" }, - - { 0x56, "less" }, - - { 0x57, "f11" }, - { 0x58, "f12" }, - - { 0xb7, "print" }, - - { 0xc7, "home" }, - { 0xc9, "pgup" }, - { 0xd1, "pgdn" }, - { 0xcf, "end" }, - - { 0xcb, "left" }, - { 0xc8, "up" }, - { 0xd0, "down" }, - { 0xcd, "right" }, - - { 0xd2, "insert" }, - { 0xd3, "delete" }, -#if defined(TARGET_SPARC) && !defined(TARGET_SPARC64) - { 0xf0, "stop" }, - { 0xf1, "again" }, - { 0xf2, "props" }, - { 0xf3, "undo" }, - { 0xf4, "front" }, - { 0xf5, "copy" }, - { 0xf6, "open" }, - { 0xf7, "paste" }, - { 0xf8, "find" }, - { 0xf9, "cut" }, - { 0xfa, "lf" }, - { 0xfb, "help" }, - { 0xfc, "meta_l" }, - { 0xfd, "meta_r" }, - { 0xfe, "compose" }, -#endif - { 0, NULL }, -}; - -static int get_keycode(const char *key) -{ - const KeyDef *p; - char *endp; - int ret; - - for(p = key_defs; p->name != NULL; p++) { - if (!strcmp(key, p->name)) - return p->keycode; - } - if (strstart(key, "0x", NULL)) { - ret = strtoul(key, &endp, 0); - if (*endp == '\0' && ret >= 0x01 && ret <= 0xff) - return ret; - } - return -1; -} - #define MAX_KEYCODES 16 static uint8_t keycodes[MAX_KEYCODES]; static int nb_pending_keycodes; @@ -1479,7 +1312,7 @@ static void do_sendkey(Monitor *mon, const QDict *qdict) { char keyname_buf[16]; char *separator; - int keyname_len, keycode, i; + int keyname_len, keycode, i, idx; const char *keys = qdict_get_str(qdict, "keys"); int has_hold_time = qdict_haskey(qdict, "hold-time"); int hold_time = qdict_get_try_int(qdict, "hold-time", -1); @@ -1512,7 +1345,14 @@ static void do_sendkey(Monitor *mon, const QDict *qdict) } keyname_buf[keyname_len] = 0; - keycode = get_keycode(keyname_buf); + + idx = index_from_key(keyname_buf); + if (idx == Q_KEY_CODE_MAX) { + monitor_printf(mon, "invalid parameter: %s\n", keyname_buf); + return; + } + + keycode = key_defs[idx]; if (keycode < 0) { monitor_printf(mon, "unknown key: '%s'\n", keyname_buf); return; @@ -4322,7 +4162,6 @@ static void monitor_find_completion(const char *cmdline) int nb_args, i, len; const char *ptype, *str; const mon_cmd_t *cmd; - const KeyDef *key; parse_cmdline(cmdline, &nb_args, args); #ifdef DEBUG_COMPLETION @@ -4396,8 +4235,8 @@ static void monitor_find_completion(const char *cmdline) if (sep) str = sep + 1; readline_set_completion_index(cur_mon->rs, strlen(str)); - for(key = key_defs; key->name != NULL; key++) { - cmd_completion(str, key->name); + for (i = 0; i < Q_KEY_CODE_MAX; i++) { + cmd_completion(str, QKeyCode_lookup[i]); } } else if (!strcmp(cmd->name, "help|?")) { readline_set_completion_index(cur_mon->rs, strlen(str)); From e4c8f004c55d9da3eae3e14df740238bf805b5d6 Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Fri, 31 Aug 2012 10:56:26 +0800 Subject: [PATCH 0184/2270] qapi: convert sendkey Convert 'sendkey' to use QAPI. QAPI passes key's index of mapping table to qmp_send_key(), not keycode. So we use help functions to convert key/code to index of key_defs, and 'index' will be converted to 'keycode' inside qmp_send_key(). For qmp, QAPI would check invalid key and raise error. For hmp, invalid key is checked in hmp_send_key(). 'send-key' of QMP doesn't support key in hexadecimal format. Signed-off-by: Amos Kong Signed-off-by: Luiz Capitulino --- console.h | 1 - hmp-commands.hx | 2 +- hmp.c | 55 ++++++++++++++++++++++++++++++ hmp.h | 1 + input.c | 67 ++++++++++++++++++++++++++++++++++++- monitor.c | 87 ------------------------------------------------ qapi-schema.json | 20 +++++++++++ qmp-commands.hx | 28 ++++++++++++++++ 8 files changed, 171 insertions(+), 90 deletions(-) diff --git a/console.h b/console.h index 7934b11894..c702b23721 100644 --- a/console.h +++ b/console.h @@ -399,7 +399,6 @@ static inline int vnc_display_pw_expire(DisplayState *ds, time_t expires) void curses_display_init(DisplayState *ds, int full_screen); /* input.c */ -extern const int key_defs[]; int index_from_key(const char *key); int index_from_keycode(int code); diff --git a/hmp-commands.hx b/hmp-commands.hx index bd0c6c9191..5cee1310cc 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -505,7 +505,7 @@ ETEXI .args_type = "keys:s,hold-time:i?", .params = "keys [hold_ms]", .help = "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)", - .mhandler.cmd = do_sendkey, + .mhandler.cmd = hmp_send_key, }, STEXI diff --git a/hmp.c b/hmp.c index 81c8acb67a..ba99b2fb30 100644 --- a/hmp.c +++ b/hmp.c @@ -19,6 +19,7 @@ #include "qemu-timer.h" #include "qmp-commands.h" #include "monitor.h" +#include "console.h" static void hmp_handle_error(Monitor *mon, Error **errp) { @@ -1102,3 +1103,57 @@ void hmp_closefd(Monitor *mon, const QDict *qdict) qmp_closefd(fdname, &errp); hmp_handle_error(mon, &errp); } + +void hmp_send_key(Monitor *mon, const QDict *qdict) +{ + const char *keys = qdict_get_str(qdict, "keys"); + QKeyCodeList *keylist, *head = NULL, *tmp = NULL; + int has_hold_time = qdict_haskey(qdict, "hold-time"); + int hold_time = qdict_get_try_int(qdict, "hold-time", -1); + Error *err = NULL; + char keyname_buf[16]; + char *separator; + int keyname_len, idx; + + while (1) { + separator = strchr(keys, '-'); + keyname_len = separator ? separator - keys : strlen(keys); + pstrcpy(keyname_buf, sizeof(keyname_buf), keys); + + /* Be compatible with old interface, convert user inputted "<" */ + if (!strncmp(keyname_buf, "<", 1) && keyname_len == 1) { + pstrcpy(keyname_buf, sizeof(keyname_buf), "less"); + keyname_len = 4; + } + keyname_buf[keyname_len] = 0; + + idx = index_from_key(keyname_buf); + if (idx == Q_KEY_CODE_MAX) { + monitor_printf(mon, "invalid parameter: %s\n", keyname_buf); + break; + } + + keylist = g_malloc0(sizeof(*keylist)); + keylist->value = idx; + keylist->next = NULL; + + if (!head) { + head = keylist; + } + if (tmp) { + tmp->next = keylist; + } + tmp = keylist; + + if (!separator) { + break; + } + keys = separator + 1; + } + + if (idx != Q_KEY_CODE_MAX) { + qmp_send_key(head, has_hold_time, hold_time, &err); + } + hmp_handle_error(mon, &err); + qapi_free_QKeyCodeList(head); +} diff --git a/hmp.h b/hmp.h index 7dd93bf0f4..8e7838ce5d 100644 --- a/hmp.h +++ b/hmp.h @@ -71,5 +71,6 @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict); void hmp_netdev_del(Monitor *mon, const QDict *qdict); void hmp_getfd(Monitor *mon, const QDict *qdict); void hmp_closefd(Monitor *mon, const QDict *qdict); +void hmp_send_key(Monitor *mon, const QDict *qdict); #endif diff --git a/input.c b/input.c index 5630cb19d1..c4b0619a74 100644 --- a/input.c +++ b/input.c @@ -28,6 +28,7 @@ #include "console.h" #include "error.h" #include "qmp-commands.h" +#include "qapi-types.h" static QEMUPutKBDEvent *qemu_put_kbd_event; static void *qemu_put_kbd_event_opaque; @@ -37,7 +38,7 @@ static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers = static NotifierList mouse_mode_notifiers = NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers); -const int key_defs[] = { +static const int key_defs[] = { [Q_KEY_CODE_SHIFT] = 0x2a, [Q_KEY_CODE_SHIFT_R] = 0x36, @@ -223,6 +224,70 @@ int index_from_keycode(int code) return i; } +static QKeyCodeList *keycodes; +static QEMUTimer *key_timer; + +static void release_keys(void *opaque) +{ + int keycode; + QKeyCodeList *p; + + for (p = keycodes; p != NULL; p = p->next) { + keycode = key_defs[p->value]; + if (keycode & 0x80) { + kbd_put_keycode(0xe0); + } + kbd_put_keycode(keycode | 0x80); + } + qapi_free_QKeyCodeList(keycodes); + keycodes = NULL; +} + +void qmp_send_key(QKeyCodeList *keys, bool has_hold_time, int64_t hold_time, + Error **errp) +{ + int keycode; + QKeyCodeList *p, *keylist, *head = NULL, *tmp = NULL; + + if (!key_timer) { + key_timer = qemu_new_timer_ns(vm_clock, release_keys, NULL); + } + + if (keycodes != NULL) { + qemu_del_timer(key_timer); + release_keys(NULL); + } + if (!has_hold_time) { + hold_time = 100; + } + + for (p = keys; p != NULL; p = p->next) { + keylist = g_malloc0(sizeof(*keylist)); + keylist->value = p->value; + keylist->next = NULL; + + if (!head) { + head = keylist; + } + if (tmp) { + tmp->next = keylist; + } + tmp = keylist; + + /* key down events */ + keycode = key_defs[p->value]; + if (keycode & 0x80) { + kbd_put_keycode(0xe0); + } + kbd_put_keycode(keycode & 0x7f); + } + keycodes = head; + + /* delayed key up events */ + qemu_mod_timer(key_timer, qemu_get_clock_ns(vm_clock) + + muldiv64(get_ticks_per_sec(), hold_time, 1000)); +} + void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) { qemu_put_kbd_event_opaque = opaque; diff --git a/monitor.c b/monitor.c index 0c4f86f639..d73bad8316 100644 --- a/monitor.c +++ b/monitor.c @@ -1290,92 +1290,6 @@ static void do_sum(Monitor *mon, const QDict *qdict) monitor_printf(mon, "%05d\n", sum); } -#define MAX_KEYCODES 16 -static uint8_t keycodes[MAX_KEYCODES]; -static int nb_pending_keycodes; -static QEMUTimer *key_timer; - -static void release_keys(void *opaque) -{ - int keycode; - - while (nb_pending_keycodes > 0) { - nb_pending_keycodes--; - keycode = keycodes[nb_pending_keycodes]; - if (keycode & 0x80) - kbd_put_keycode(0xe0); - kbd_put_keycode(keycode | 0x80); - } -} - -static void do_sendkey(Monitor *mon, const QDict *qdict) -{ - char keyname_buf[16]; - char *separator; - int keyname_len, keycode, i, idx; - const char *keys = qdict_get_str(qdict, "keys"); - int has_hold_time = qdict_haskey(qdict, "hold-time"); - int hold_time = qdict_get_try_int(qdict, "hold-time", -1); - - if (nb_pending_keycodes > 0) { - qemu_del_timer(key_timer); - release_keys(NULL); - } - if (!has_hold_time) - hold_time = 100; - i = 0; - while (1) { - separator = strchr(keys, '-'); - keyname_len = separator ? separator - keys : strlen(keys); - if (keyname_len > 0) { - pstrcpy(keyname_buf, sizeof(keyname_buf), keys); - if (keyname_len > sizeof(keyname_buf) - 1) { - monitor_printf(mon, "invalid key: '%s...'\n", keyname_buf); - return; - } - if (i == MAX_KEYCODES) { - monitor_printf(mon, "too many keys\n"); - return; - } - - /* Be compatible with old interface, convert user inputted "<" */ - if (!strncmp(keyname_buf, "<", 1) && keyname_len == 1) { - pstrcpy(keyname_buf, sizeof(keyname_buf), "less"); - keyname_len = 4; - } - - keyname_buf[keyname_len] = 0; - - idx = index_from_key(keyname_buf); - if (idx == Q_KEY_CODE_MAX) { - monitor_printf(mon, "invalid parameter: %s\n", keyname_buf); - return; - } - - keycode = key_defs[idx]; - if (keycode < 0) { - monitor_printf(mon, "unknown key: '%s'\n", keyname_buf); - return; - } - keycodes[i++] = keycode; - } - if (!separator) - break; - keys = separator + 1; - } - nb_pending_keycodes = i; - /* key down events */ - for (i = 0; i < nb_pending_keycodes; i++) { - keycode = keycodes[i]; - if (keycode & 0x80) - kbd_put_keycode(0xe0); - kbd_put_keycode(keycode & 0x7f); - } - /* delayed key up events */ - qemu_mod_timer(key_timer, qemu_get_clock_ns(vm_clock) + - muldiv64(get_ticks_per_sec(), hold_time, 1000)); -} - static int mouse_button_state; static void do_mouse_move(Monitor *mon, const QDict *qdict) @@ -4772,7 +4686,6 @@ void monitor_init(CharDriverState *chr, int flags) Monitor *mon; if (is_first_init) { - key_timer = qemu_new_timer_ns(vm_clock, release_keys, NULL); monitor_protocol_event_init(); is_first_init = 0; } diff --git a/qapi-schema.json b/qapi-schema.json index 856e11a729..5421382991 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2519,3 +2519,23 @@ 'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again', 'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut', 'lf', 'help', 'meta_l', 'meta_r', 'compose' ] } + +## +# @send-key: +# +# Send keys to guest. +# +# @keys: key sequence. 'keys' is the name of the key. Use a JSON array to +# press several keys simultaneously. +# +# @hold-time: #optional time to delay key up events, milliseconds. Defaults +# to 100 +# +# Returns: Nothing on success +# If key is unknown or redundant, InvalidParameter +# +# Since: 1.3.0 +# +## +{ 'command': 'send-key', + 'data': { 'keys': ['QKeyCode'], '*hold-time': 'int' } } diff --git a/qmp-commands.hx b/qmp-commands.hx index 3745a21199..470f08ed99 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -332,6 +332,34 @@ Example: -> { "execute": "device_del", "arguments": { "id": "net1" } } <- { "return": {} } +EQMP + + { + .name = "send-key", + .args_type = "keys:O,hold-time:i?", + .mhandler.cmd_new = qmp_marshal_input_send_key, + }, + +SQMP +send-key +---------- + +Send keys to VM. + +Arguments: + +keys array: + - "key": key sequence (a json-array of key enum values) + +- hold-time: time to delay key up events, milliseconds. Defaults to 100 + (json-int, optional) + +Example: + +-> { "execute": "send-key", + "arguments": { 'keys': [ 'ctrl', 'alt', 'delete' ] } } +<- { "return": {} } + EQMP { From 227ccf6bff234c29974c2c18ecd3a29e6b965e3d Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 1 Sep 2012 09:30:39 +0200 Subject: [PATCH 0185/2270] qapi: Fix potential NULL pointer segfault Report from smatch: qapi-visit.c:1640 visit_type_BlockdevAction(8) error: we previously assumed 'obj' could be null (see line 1639) qapi-visit.c:2432 visit_type_NetClientOptions(8) error: we previously assumed 'obj' could be null (see line 2431) Signed-off-by: Stefan Weil Reviewed-by: Paolo Bonzini Signed-off-by: Luiz Capitulino --- scripts/qapi-visit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index cbec24da16..e2093e8947 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -157,7 +157,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** if (!error_is_set(errp)) { visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); if (!err) { - if (!obj || *obj) { + if (obj && *obj) { visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err); if (!err) { switch ((*obj)->kind) { From 149474c93490e1c66f838391bd491db83136d91d Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Mon, 3 Sep 2012 21:19:11 +0200 Subject: [PATCH 0186/2270] json-parser: Fix potential NULL pointer segfault Report from smatch: json-parser.c:474 parse_object(62) error: potential null derefence 'dict'. json-parser.c:553 parse_array(75) error: potential null derefence 'list'. Label 'out' in json-parser.c can be called with list == NULL which is passed to QDECREF. Modify QDECREF to handle a NULL argument (inline function qobject_decref already handles them, too). Signed-off-by: Stefan Weil Signed-off-by: Luiz Capitulino --- qobject.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qobject.h b/qobject.h index d42386dde1..9124649ed2 100644 --- a/qobject.h +++ b/qobject.h @@ -71,7 +71,7 @@ typedef struct QObject { /* High-level interface for qobject_decref() */ #define QDECREF(obj) \ - qobject_decref(QOBJECT(obj)) + qobject_decref(obj ? QOBJECT(obj) : NULL) /* Initialize an object to default values */ #define QOBJECT_INIT(obj, qtype_type) \ From 75d789f8d38be693bbee3e77b558e59012e33997 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 29 Aug 2012 11:20:57 -0300 Subject: [PATCH 0187/2270] error: add error_setg() Signed-off-by: Luiz Capitulino --- error.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/error.h b/error.h index 96fc20328f..da7fed399e 100644 --- a/error.h +++ b/error.h @@ -29,6 +29,12 @@ typedef struct Error Error; */ void error_set(Error **err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(3, 4); +/** + * Same as error_set(), but sets a generic error + */ +#define error_setg(err, fmt, ...) \ + error_set(err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__) + /** * Returns true if an indirect pointer to an error is pointing to a valid * error object. From d7098135d4baac8141b2e76f2daa8a7f61599c72 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Mon, 21 May 2012 16:41:37 -0300 Subject: [PATCH 0188/2270] console: vga_hw_screen_dump_ptr: take Error argument All devices that register a screen dump callback via graphic_console_init() are updated. The new argument is not used in this commit. Error handling will be added to each device individually later. This change is a preparation to convert the screendump command to the QAPI. Signed-off-by: Luiz Capitulino --- console.c | 2 +- console.h | 4 +++- hw/blizzard.c | 2 +- hw/g364fb.c | 3 ++- hw/omap_lcdc.c | 3 ++- hw/qxl.c | 5 +++-- hw/tcx.c | 12 ++++++++---- hw/vga.c | 6 ++++-- hw/vmware_vga.c | 5 +++-- 9 files changed, 27 insertions(+), 15 deletions(-) diff --git a/console.c b/console.c index 3b5cabba3a..8228773ddc 100644 --- a/console.c +++ b/console.c @@ -190,7 +190,7 @@ void vga_hw_screen_dump(const char *filename) console_select(0); } if (consoles[0] && consoles[0]->hw_screen_dump) { - consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch); + consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch, NULL); } else { error_report("screen dump not implemented"); } diff --git a/console.h b/console.h index c702b23721..fd68ecca75 100644 --- a/console.h +++ b/console.h @@ -7,6 +7,7 @@ #include "monitor.h" #include "trace.h" #include "qapi-types.h" +#include "error.h" /* keyboard/mouse support */ @@ -344,7 +345,8 @@ static inline void console_write_ch(console_ch_t *dest, uint32_t ch) typedef void (*vga_hw_update_ptr)(void *); typedef void (*vga_hw_invalidate_ptr)(void *); -typedef void (*vga_hw_screen_dump_ptr)(void *, const char *, bool cswitch); +typedef void (*vga_hw_screen_dump_ptr)(void *, const char *, bool cswitch, + Error **errp); typedef void (*vga_hw_text_update_ptr)(void *, console_ch_t *); DisplayState *graphic_console_init(vga_hw_update_ptr update, diff --git a/hw/blizzard.c b/hw/blizzard.c index 29074c4fa7..a2b90537c9 100644 --- a/hw/blizzard.c +++ b/hw/blizzard.c @@ -933,7 +933,7 @@ static void blizzard_update_display(void *opaque) } static void blizzard_screen_dump(void *opaque, const char *filename, - bool cswitch) + bool cswitch, Error **errp) { BlizzardState *s = (BlizzardState *) opaque; diff --git a/hw/g364fb.c b/hw/g364fb.c index 3a0b68fbae..498154be28 100644 --- a/hw/g364fb.c +++ b/hw/g364fb.c @@ -289,7 +289,8 @@ static void g364fb_reset(G364State *s) g364fb_invalidate_display(s); } -static void g364fb_screen_dump(void *opaque, const char *filename, bool cswitch) +static void g364fb_screen_dump(void *opaque, const char *filename, bool cswitch, + Error **errp) { G364State *s = opaque; int y, x; diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c index 4a08e9d002..39b78cd6d5 100644 --- a/hw/omap_lcdc.c +++ b/hw/omap_lcdc.c @@ -264,7 +264,8 @@ static int ppm_save(const char *filename, uint8_t *data, return 0; } -static void omap_screen_dump(void *opaque, const char *filename, bool cswitch) +static void omap_screen_dump(void *opaque, const char *filename, bool cswitch, + Error **errp) { struct omap_lcd_panel_s *omap_lcd = opaque; diff --git a/hw/qxl.c b/hw/qxl.c index c2dd3b471b..46a929dc35 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1595,7 +1595,8 @@ static void qxl_hw_invalidate(void *opaque) vga->invalidate(vga); } -static void qxl_hw_screen_dump(void *opaque, const char *filename, bool cswitch) +static void qxl_hw_screen_dump(void *opaque, const char *filename, bool cswitch, + Error **errp) { PCIQXLDevice *qxl = opaque; VGACommonState *vga = &qxl->vga; @@ -1607,7 +1608,7 @@ static void qxl_hw_screen_dump(void *opaque, const char *filename, bool cswitch) ppm_save(filename, qxl->ssd.ds->surface); break; case QXL_MODE_VGA: - vga->screen_dump(vga, filename, cswitch); + vga->screen_dump(vga, filename, cswitch, errp); break; default: break; diff --git a/hw/tcx.c b/hw/tcx.c index ac7dcb428c..74a7085422 100644 --- a/hw/tcx.c +++ b/hw/tcx.c @@ -56,8 +56,10 @@ typedef struct TCXState { uint8_t dac_index, dac_state; } TCXState; -static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch); -static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch); +static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch, + Error **errp); +static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch, + Error **errp); static void tcx_set_dirty(TCXState *s) { @@ -574,7 +576,8 @@ static int tcx_init1(SysBusDevice *dev) return 0; } -static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch) +static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch, + Error **errp) { TCXState *s = opaque; FILE *f; @@ -601,7 +604,8 @@ static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch) return; } -static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch) +static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch, + Error **errp) { TCXState *s = opaque; FILE *f; diff --git a/hw/vga.c b/hw/vga.c index f82ced8e66..dd703cf41c 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -166,7 +166,8 @@ static uint32_t expand4[256]; static uint16_t expand2[256]; static uint8_t expand4to8[16]; -static void vga_screen_dump(void *opaque, const char *filename, bool cswitch); +static void vga_screen_dump(void *opaque, const char *filename, bool cswitch, + Error **errp); static void vga_update_memory_access(VGACommonState *s) { @@ -2435,7 +2436,8 @@ int ppm_save(const char *filename, struct DisplaySurface *ds) /* save the vga display in a PPM image even if no display is available */ -static void vga_screen_dump(void *opaque, const char *filename, bool cswitch) +static void vga_screen_dump(void *opaque, const char *filename, bool cswitch, + Error **errp) { VGACommonState *s = opaque; diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index f5e4f440d5..29750e1b0d 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -1003,11 +1003,12 @@ static void vmsvga_invalidate_display(void *opaque) /* save the vga display in a PPM image even if no display is available */ -static void vmsvga_screen_dump(void *opaque, const char *filename, bool cswitch) +static void vmsvga_screen_dump(void *opaque, const char *filename, bool cswitch, + Error **errp) { struct vmsvga_state_s *s = opaque; if (!s->enable) { - s->vga.screen_dump(&s->vga, filename, cswitch); + s->vga.screen_dump(&s->vga, filename, cswitch, errp); return; } From ad39cf6d150e951e4c67c8120d495ae7e78054a6 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 24 May 2012 13:48:23 -0300 Subject: [PATCH 0189/2270] qapi: convert screendump Next commits will update devices to propagate errors. Signed-off-by: Luiz Capitulino --- console.c | 7 ++++--- console.h | 1 - hmp-commands.hx | 3 +-- hmp.c | 9 +++++++++ hmp.h | 1 + monitor.c | 6 ------ qapi-schema.json | 13 +++++++++++++ qmp-commands.hx | 5 +---- 8 files changed, 29 insertions(+), 16 deletions(-) diff --git a/console.c b/console.c index 8228773ddc..c1ed5e09e0 100644 --- a/console.c +++ b/console.c @@ -24,6 +24,7 @@ #include "qemu-common.h" #include "console.h" #include "qemu-timer.h" +#include "qmp-commands.h" //#define DEBUG_CONSOLE #define DEFAULT_BACKSCROLL 512 @@ -176,7 +177,7 @@ void vga_hw_invalidate(void) active_console->hw_invalidate(active_console->hw); } -void vga_hw_screen_dump(const char *filename) +void qmp_screendump(const char *filename, Error **errp) { TextConsole *previous_active_console; bool cswitch; @@ -190,9 +191,9 @@ void vga_hw_screen_dump(const char *filename) console_select(0); } if (consoles[0] && consoles[0]->hw_screen_dump) { - consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch, NULL); + consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch, errp); } else { - error_report("screen dump not implemented"); + error_setg(errp, "device doesn't support screendump\n"); } if (cswitch) { diff --git a/console.h b/console.h index fd68ecca75..f990684ef4 100644 --- a/console.h +++ b/console.h @@ -357,7 +357,6 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update, void vga_hw_update(void); void vga_hw_invalidate(void); -void vga_hw_screen_dump(const char *filename); void vga_hw_text_update(console_ch_t *chardata); int is_graphic_console(void); diff --git a/hmp-commands.hx b/hmp-commands.hx index 5cee1310cc..ed67e997fd 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -194,8 +194,7 @@ ETEXI .args_type = "filename:F", .params = "filename", .help = "save screen into PPM image 'filename'", - .user_print = monitor_user_noop, - .mhandler.cmd_new = do_screen_dump, + .mhandler.cmd = hmp_screen_dump, }, STEXI diff --git a/hmp.c b/hmp.c index ba99b2fb30..1bdab22778 100644 --- a/hmp.c +++ b/hmp.c @@ -1157,3 +1157,12 @@ void hmp_send_key(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, &err); qapi_free_QKeyCodeList(head); } + +void hmp_screen_dump(Monitor *mon, const QDict *qdict) +{ + const char *filename = qdict_get_str(qdict, "filename"); + Error *err = NULL; + + qmp_screendump(filename, &err); + hmp_handle_error(mon, &err); +} diff --git a/hmp.h b/hmp.h index 8e7838ce5d..48b9c59f8a 100644 --- a/hmp.h +++ b/hmp.h @@ -72,5 +72,6 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict); void hmp_getfd(Monitor *mon, const QDict *qdict); void hmp_closefd(Monitor *mon, const QDict *qdict); void hmp_send_key(Monitor *mon, const QDict *qdict); +void hmp_screen_dump(Monitor *mon, const QDict *qdict); #endif diff --git a/monitor.c b/monitor.c index d73bad8316..e315b270ee 100644 --- a/monitor.c +++ b/monitor.c @@ -1016,12 +1016,6 @@ static int client_migrate_info(Monitor *mon, const QDict *qdict, return -1; } -static int do_screen_dump(Monitor *mon, const QDict *qdict, QObject **ret_data) -{ - vga_hw_screen_dump(qdict_get_str(qdict, "filename")); - return 0; -} - static void do_logfile(Monitor *mon, const QDict *qdict) { cpu_set_log_filename(qdict_get_str(qdict, "filename")); diff --git a/qapi-schema.json b/qapi-schema.json index 5421382991..df47fcee2f 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2539,3 +2539,16 @@ ## { 'command': 'send-key', 'data': { 'keys': ['QKeyCode'], '*hold-time': 'int' } } + +## +# @screendump: +# +# Write a PPM of the VGA screen to a file. +# +# @filename: the path of a new PPM file to store the image +# +# Returns: Nothing on success +# +# Since: 0.14.0 +## +{ 'command': 'screendump', 'data': {'filename': 'str'} } diff --git a/qmp-commands.hx b/qmp-commands.hx index 470f08ed99..6e21ddba61 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -146,10 +146,7 @@ EQMP { .name = "screendump", .args_type = "filename:F", - .params = "filename", - .help = "save screen into PPM image 'filename'", - .user_print = monitor_user_noop, - .mhandler.cmd_new = do_screen_dump, + .mhandler.cmd_new = qmp_marshal_input_screendump, }, SQMP From d663174dcd9623c44f3af2a46de2a55d16f15c19 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 24 May 2012 10:42:25 -0300 Subject: [PATCH 0190/2270] vga: ppm_save(): add error handling Signed-off-by: Luiz Capitulino --- hw/blizzard.c | 2 +- hw/qxl.c | 2 +- hw/vga.c | 32 +++++++++++++++++++++++++------- hw/vga_int.h | 3 ++- hw/vmware_vga.c | 2 +- 5 files changed, 30 insertions(+), 11 deletions(-) diff --git a/hw/blizzard.c b/hw/blizzard.c index a2b90537c9..d1c9d81510 100644 --- a/hw/blizzard.c +++ b/hw/blizzard.c @@ -939,7 +939,7 @@ static void blizzard_screen_dump(void *opaque, const char *filename, blizzard_update_display(opaque); if (s && ds_get_data(s->state)) - ppm_save(filename, s->state->surface); + ppm_save(filename, s->state->surface, errp); } #define DEPTH 8 diff --git a/hw/qxl.c b/hw/qxl.c index 46a929dc35..bae5758195 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1605,7 +1605,7 @@ static void qxl_hw_screen_dump(void *opaque, const char *filename, bool cswitch, case QXL_MODE_COMPAT: case QXL_MODE_NATIVE: qxl_render_update(qxl); - ppm_save(filename, qxl->ssd.ds->surface); + ppm_save(filename, qxl->ssd.ds->surface, errp); break; case QXL_MODE_VGA: vga->screen_dump(vga, filename, cswitch, errp); diff --git a/hw/vga.c b/hw/vga.c index dd703cf41c..80299ea1d4 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -2390,7 +2390,7 @@ void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory) /********************************************************/ /* vga screen dump */ -int ppm_save(const char *filename, struct DisplaySurface *ds) +void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp) { FILE *f; uint8_t *d, *d1; @@ -2402,10 +2402,16 @@ int ppm_save(const char *filename, struct DisplaySurface *ds) trace_ppm_save(filename, ds); f = fopen(filename, "wb"); - if (!f) - return -1; - fprintf(f, "P6\n%d %d\n%d\n", - ds->width, ds->height, 255); + if (!f) { + error_setg(errp, "failed to open file '%s': %s", filename, + strerror(errno)); + return; + } + ret = fprintf(f, "P6\n%d %d\n%d\n", ds->width, ds->height, 255); + if (ret < 0) { + linebuf = NULL; + goto write_err; + } linebuf = g_malloc(ds->width * 3); d1 = ds->data; for(y = 0; y < ds->height; y++) { @@ -2426,12 +2432,24 @@ int ppm_save(const char *filename, struct DisplaySurface *ds) d += ds->pf.bytes_per_pixel; } d1 += ds->linesize; + clearerr(f); ret = fwrite(linebuf, 1, pbuf - linebuf, f); (void)ret; + if (ferror(f)) { + goto write_err; + } } + +out: g_free(linebuf); fclose(f); - return 0; + return; + +write_err: + error_setg(errp, "failed to write to file '%s': %s", filename, + strerror(errno)); + unlink(filename); + goto out; } /* save the vga display in a PPM image even if no display is @@ -2445,5 +2463,5 @@ static void vga_screen_dump(void *opaque, const char *filename, bool cswitch, vga_invalidate_display(s); } vga_hw_update(); - ppm_save(filename, s->ds->surface); + ppm_save(filename, s->ds->surface, errp); } diff --git a/hw/vga_int.h b/hw/vga_int.h index 8938093682..330a32f77d 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -23,6 +23,7 @@ */ #include +#include "error.h" #include "memory.h" #define ST01_V_RETRACE 0x08 @@ -204,7 +205,7 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val); uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr); void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val); void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2); -int ppm_save(const char *filename, struct DisplaySurface *ds); +void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp); int vga_ioport_invalid(VGACommonState *s, uint32_t addr); void vga_init_vbe(VGACommonState *s, MemoryRegion *address_space); diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 29750e1b0d..b68e88367f 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -1015,7 +1015,7 @@ static void vmsvga_screen_dump(void *opaque, const char *filename, bool cswitch, if (s->depth == 32) { DisplaySurface *ds = qemu_create_displaysurface_from(s->width, s->height, 32, ds_get_linesize(s->vga.ds), s->vga.vram_ptr); - ppm_save(filename, ds); + ppm_save(filename, ds, errp); g_free(ds); } } From 8dc4cc7bb57d3f0d6a1d8ba372d9eda1494bcc64 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Mon, 21 May 2012 15:18:58 -0300 Subject: [PATCH 0191/2270] omap_lcdc: rename ppm_save() to omap_ppm_save() Avoids confusion with the global ppm_save() defined in hw/vga.c. Signed-off-by: Luiz Capitulino Reviewed-by: Peter Maydell --- hw/omap_lcdc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c index 39b78cd6d5..3d6328febc 100644 --- a/hw/omap_lcdc.c +++ b/hw/omap_lcdc.c @@ -224,8 +224,8 @@ static void omap_update_display(void *opaque) omap_lcd->invalidate = 0; } -static int ppm_save(const char *filename, uint8_t *data, - int w, int h, int linesize) +static int omap_ppm_save(const char *filename, uint8_t *data, + int w, int h, int linesize) { FILE *f; uint8_t *d, *d1; @@ -271,9 +271,9 @@ static void omap_screen_dump(void *opaque, const char *filename, bool cswitch, omap_update_display(opaque); if (omap_lcd && ds_get_data(omap_lcd->state)) - ppm_save(filename, ds_get_data(omap_lcd->state), - omap_lcd->width, omap_lcd->height, - ds_get_linesize(omap_lcd->state)); + omap_ppm_save(filename, ds_get_data(omap_lcd->state), + omap_lcd->width, omap_lcd->height, + ds_get_linesize(omap_lcd->state)); } static void omap_invalidate_display(void *opaque) { From d9c7ebb10042a7d29d50b47c110e5cb754293d89 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 24 May 2012 11:24:34 -0300 Subject: [PATCH 0192/2270] omap_lcdc: omap_ppm_save(): add error handling Signed-off-by: Luiz Capitulino --- hw/omap_lcdc.c | 59 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c index 3d6328febc..e2ba10834e 100644 --- a/hw/omap_lcdc.c +++ b/hw/omap_lcdc.c @@ -224,18 +224,24 @@ static void omap_update_display(void *opaque) omap_lcd->invalidate = 0; } -static int omap_ppm_save(const char *filename, uint8_t *data, - int w, int h, int linesize) +static void omap_ppm_save(const char *filename, uint8_t *data, + int w, int h, int linesize, Error **errp) { FILE *f; uint8_t *d, *d1; unsigned int v; - int y, x, bpp; + int ret, y, x, bpp; f = fopen(filename, "wb"); - if (!f) - return -1; - fprintf(f, "P6\n%d %d\n%d\n", w, h, 255); + if (!f) { + error_setg(errp, "failed to open file '%s': %s", filename, + strerror(errno)); + return; + } + ret = fprintf(f, "P6\n%d %d\n%d\n", w, h, 255); + if (ret < 0) { + goto write_err; + } d1 = data; bpp = linesize / w; for (y = 0; y < h; y ++) { @@ -244,24 +250,49 @@ static int omap_ppm_save(const char *filename, uint8_t *data, v = *(uint32_t *) d; switch (bpp) { case 2: - fputc((v >> 8) & 0xf8, f); - fputc((v >> 3) & 0xfc, f); - fputc((v << 3) & 0xf8, f); + ret = fputc((v >> 8) & 0xf8, f); + if (ret == EOF) { + goto write_err; + } + ret = fputc((v >> 3) & 0xfc, f); + if (ret == EOF) { + goto write_err; + } + ret = fputc((v << 3) & 0xf8, f); + if (ret == EOF) { + goto write_err; + } break; case 3: case 4: default: - fputc((v >> 16) & 0xff, f); - fputc((v >> 8) & 0xff, f); - fputc((v) & 0xff, f); + ret = fputc((v >> 16) & 0xff, f); + if (ret == EOF) { + goto write_err; + } + ret = fputc((v >> 8) & 0xff, f); + if (ret == EOF) { + goto write_err; + } + ret = fputc((v) & 0xff, f); + if (ret == EOF) { + goto write_err; + } break; } d += bpp; } d1 += linesize; } +out: fclose(f); - return 0; + return; + +write_err: + error_setg(errp, "failed to write to file '%s': %s", filename, + strerror(errno)); + unlink(filename); + goto out; } static void omap_screen_dump(void *opaque, const char *filename, bool cswitch, @@ -273,7 +304,7 @@ static void omap_screen_dump(void *opaque, const char *filename, bool cswitch, if (omap_lcd && ds_get_data(omap_lcd->state)) omap_ppm_save(filename, ds_get_data(omap_lcd->state), omap_lcd->width, omap_lcd->height, - ds_get_linesize(omap_lcd->state)); + ds_get_linesize(omap_lcd->state), errp); } static void omap_invalidate_display(void *opaque) { From 61a3f955c1caca775729fc59e97fb9c97808ffca Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 24 May 2012 11:28:17 -0300 Subject: [PATCH 0193/2270] g364fb: g364fb_screen_dump(): add error handling Signed-off-by: Luiz Capitulino --- hw/g364fb.c | 52 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/hw/g364fb.c b/hw/g364fb.c index 498154be28..059e6220e0 100644 --- a/hw/g364fb.c +++ b/hw/g364fb.c @@ -293,7 +293,7 @@ static void g364fb_screen_dump(void *opaque, const char *filename, bool cswitch, Error **errp) { G364State *s = opaque; - int y, x; + int ret, y, x; uint8_t index; uint8_t *data_buffer; FILE *f; @@ -301,35 +301,63 @@ static void g364fb_screen_dump(void *opaque, const char *filename, bool cswitch, qemu_flush_coalesced_mmio_buffer(); if (s->depth != 8) { - error_report("g364: unknown guest depth %d", s->depth); + error_setg(errp, "g364: unknown guest depth %d", s->depth); return; } f = fopen(filename, "wb"); - if (!f) + if (!f) { + error_setg(errp, "failed to open file '%s': %s", filename, + strerror(errno)); return; + } if (s->ctla & CTLA_FORCE_BLANK) { /* blank screen */ - fprintf(f, "P4\n%d %d\n", - s->width, s->height); + ret = fprintf(f, "P4\n%d %d\n", s->width, s->height); + if (ret < 0) { + goto write_err; + } for (y = 0; y < s->height; y++) - for (x = 0; x < s->width; x++) - fputc(0, f); + for (x = 0; x < s->width; x++) { + ret = fputc(0, f); + if (ret == EOF) { + goto write_err; + } + } } else { data_buffer = s->vram + s->top_of_screen; - fprintf(f, "P6\n%d %d\n%d\n", - s->width, s->height, 255); + ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255); + if (ret < 0) { + goto write_err; + } for (y = 0; y < s->height; y++) for (x = 0; x < s->width; x++, data_buffer++) { index = *data_buffer; - fputc(s->color_palette[index][0], f); - fputc(s->color_palette[index][1], f); - fputc(s->color_palette[index][2], f); + ret = fputc(s->color_palette[index][0], f); + if (ret == EOF) { + goto write_err; + } + ret = fputc(s->color_palette[index][1], f); + if (ret == EOF) { + goto write_err; + } + ret = fputc(s->color_palette[index][2], f); + if (ret == EOF) { + goto write_err; + } } } +out: fclose(f); + return; + +write_err: + error_setg(errp, "failed to write to file '%s': %s", filename, + strerror(errno)); + unlink(filename); + goto out; } /* called for accesses to io ports */ From 537f2d2b0d4c27e21b3e610e57d6511e315d76cc Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 24 May 2012 11:30:40 -0300 Subject: [PATCH 0194/2270] tcx: tcx24_screen_dump(): add error handling Signed-off-by: Luiz Capitulino --- hw/tcx.c | 50 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/hw/tcx.c b/hw/tcx.c index 74a7085422..428649e665 100644 --- a/hw/tcx.c +++ b/hw/tcx.c @@ -611,12 +611,18 @@ static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch, FILE *f; uint8_t *d, *d1, v; uint32_t *s24, *cptr, dval; - int y, x; + int ret, y, x; f = fopen(filename, "wb"); - if (!f) + if (!f) { + error_setg(errp, "failed to open file '%s': %s", filename, + strerror(errno)); return; - fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255); + } + ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255); + if (ret < 0) { + goto write_err; + } d1 = s->vram; s24 = s->vram24; cptr = s->cplane; @@ -625,20 +631,46 @@ static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch, for(x = 0; x < s->width; x++, d++, s24++) { if ((*cptr++ & 0xff000000) == 0x03000000) { // 24-bit direct dval = *s24 & 0x00ffffff; - fputc((dval >> 16) & 0xff, f); - fputc((dval >> 8) & 0xff, f); - fputc(dval & 0xff, f); + ret = fputc((dval >> 16) & 0xff, f); + if (ret == EOF) { + goto write_err; + } + ret = fputc((dval >> 8) & 0xff, f); + if (ret == EOF) { + goto write_err; + } + ret = fputc(dval & 0xff, f); + if (ret == EOF) { + goto write_err; + } } else { v = *d; - fputc(s->r[v], f); - fputc(s->g[v], f); - fputc(s->b[v], f); + ret = fputc(s->r[v], f); + if (ret == EOF) { + goto write_err; + } + ret = fputc(s->g[v], f); + if (ret == EOF) { + goto write_err; + } + ret = fputc(s->b[v], f); + if (ret == EOF) { + goto write_err; + } } } d1 += MAXX; } + +out: fclose(f); return; + +write_err: + error_setg(errp, "failed to write to file '%s': %s", filename, + strerror(errno)); + unlink(filename); + goto out; } static Property tcx_properties[] = { From 0ab6b63655ba59d7c05089017acb721a44979526 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 24 May 2012 11:33:25 -0300 Subject: [PATCH 0195/2270] tcx: tcx_screen_dump(): add error handling Signed-off-by: Luiz Capitulino --- hw/tcx.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/hw/tcx.c b/hw/tcx.c index 428649e665..93994d6440 100644 --- a/hw/tcx.c +++ b/hw/tcx.c @@ -582,26 +582,49 @@ static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch, TCXState *s = opaque; FILE *f; uint8_t *d, *d1, v; - int y, x; + int ret, y, x; f = fopen(filename, "wb"); - if (!f) + if (!f) { + error_setg(errp, "failed to open file '%s': %s", filename, + strerror(errno)); return; - fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255); + } + ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255); + if (ret < 0) { + goto write_err; + } d1 = s->vram; for(y = 0; y < s->height; y++) { d = d1; for(x = 0; x < s->width; x++) { v = *d; - fputc(s->r[v], f); - fputc(s->g[v], f); - fputc(s->b[v], f); + ret = fputc(s->r[v], f); + if (ret == EOF) { + goto write_err; + } + ret = fputc(s->g[v], f); + if (ret == EOF) { + goto write_err; + } + ret = fputc(s->b[v], f); + if (ret == EOF) { + goto write_err; + } d++; } d1 += MAXX; } + +out: fclose(f); return; + +write_err: + error_setg(errp, "failed to write to file '%s': %s", filename, + strerror(errno)); + unlink(filename); + goto out; } static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch, From a99ac041e9f30dafb0afa326ddbeb8a481ba3f81 Mon Sep 17 00:00:00 2001 From: Don Slutz Date: Sun, 2 Sep 2012 19:22:35 -0400 Subject: [PATCH 0196/2270] CHECKPATCH: Add --debug adv_dcs Add debug options to find this issue. They were not listed in the help because the are not simple to understand the output of. Signed-off-by: Don Slutz Signed-off-by: Blue Swirl --- scripts/checkpatch.pl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index b98dc6cad1..0b0f3f379b 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -97,6 +97,7 @@ my $dbg_values = 0; my $dbg_possible = 0; my $dbg_type = 0; my $dbg_attr = 0; +my $dbg_adv_dcs = 0; for my $key (keys %debug) { ## no critic eval "\${dbg_$key} = '$debug{$key}';"; @@ -2575,6 +2576,8 @@ sub process { $allowed = 1; } } + print "DCS: level=$level block<$block> allowed=$allowed\n" + if $dbg_adv_dcs; if ($level == 0 && $block !~ /^\s*\{/ && !$allowed) { my $herectx = $here . "\n";; my $cnt = statement_rawlines($block); From 5424302e56ca587b665e3f409c4daa1bc2ff1cf7 Mon Sep 17 00:00:00 2001 From: Don Slutz Date: Sun, 2 Sep 2012 19:22:36 -0400 Subject: [PATCH 0197/2270] CHECKPATCH: Add --debug adv_checking Add debug options to find this issue. They were not listed in the help because the are not simple to understand the output of. Signed-off-by: Don Slutz Signed-off-by: Blue Swirl --- scripts/checkpatch.pl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 0b0f3f379b..8c83b56c6a 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -98,6 +98,7 @@ my $dbg_possible = 0; my $dbg_type = 0; my $dbg_attr = 0; my $dbg_adv_dcs = 0; +my $dbg_adv_checking = 0; for my $key (keys %debug) { ## no critic eval "\${dbg_$key} = '$debug{$key}';"; @@ -2549,7 +2550,8 @@ sub process { # Check the condition. my ($cond, $block) = @{$chunks[0]}; - #print "CHECKING<$linenr> cond<$cond> block<$block>\n"; + print "CHECKING<$linenr> cond<$cond> block<$block>\n" + if $dbg_adv_checking; if (defined $cond) { substr($block, 0, length($cond), ''); } From 69402a6944f506f51efee13c9db94bd1605eb478 Mon Sep 17 00:00:00 2001 From: Don Slutz Date: Sun, 2 Sep 2012 19:22:37 -0400 Subject: [PATCH 0198/2270] CHECKPATCH: Add --debug adv_apw Add debug options to find this issue. They were not listed in the help because the are not simple to understand the output of. Signed-off-by: Don Slutz Signed-off-by: Blue Swirl --- scripts/checkpatch.pl | 51 +++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 8c83b56c6a..7ec8846ac9 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -99,6 +99,7 @@ my $dbg_type = 0; my $dbg_attr = 0; my $dbg_adv_dcs = 0; my $dbg_adv_checking = 0; +my $dbg_adv_apw = 0; for my $key (keys %debug) { ## no critic eval "\${dbg_$key} = '$debug{$key}';"; @@ -2488,8 +2489,11 @@ sub process { if ($line =~ /(^.*)\bif\b/ && $line !~ /\#\s*if/) { my ($level, $endln, @chunks) = ctx_statement_full($linenr, $realcnt, 1); - #print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n"; - #print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n"; + if ($dbg_adv_apw) { + print "APW: chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n"; + print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n" + if $#chunks >= 1; + } if ($#chunks >= 0 && $level == 0) { my $allowed = 0; my $seen = 0; @@ -2514,18 +2518,22 @@ sub process { $seen++ if ($block =~ /^\s*{/); - #print "cond<$cond> block<$block> allowed<$allowed>\n"; + print "APW: cond<$cond> block<$block> allowed<$allowed>\n" + if $dbg_adv_apw; if (statement_lines($cond) > 1) { - #print "APW: ALLOWED: cond<$cond>\n"; - $allowed = 1; + print "APW: ALLOWED: cond<$cond>\n" + if $dbg_adv_apw; + $allowed = 1; } if ($block =~/\b(?:if|for|while)\b/) { - #print "APW: ALLOWED: block<$block>\n"; - $allowed = 1; + print "APW: ALLOWED: block<$block>\n" + if $dbg_adv_apw; + $allowed = 1; } if (statement_block_size($block) > 1) { - #print "APW: ALLOWED: lines block<$block>\n"; - $allowed = 1; + print "APW: ALLOWED: lines block<$block>\n" + if $dbg_adv_apw; + $allowed = 1; } } if ($seen != ($#chunks + 1)) { @@ -2541,8 +2549,9 @@ sub process { # Check the pre-context. if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) { - #print "APW: ALLOWED: pre<$1>\n"; - $allowed = 1; + print "APW: ALLOWED: pre<$pre> line<$line>\n" + if $dbg_adv_apw; + $allowed = 1; } my ($level, $endln, @chunks) = @@ -2556,16 +2565,19 @@ sub process { substr($block, 0, length($cond), ''); } if (statement_lines($cond) > 1) { - #print "APW: ALLOWED: cond<$cond>\n"; - $allowed = 1; + print "APW: ALLOWED: cond<$cond>\n" + if $dbg_adv_apw; + $allowed = 1; } if ($block =~/\b(?:if|for|while)\b/) { - #print "APW: ALLOWED: block<$block>\n"; - $allowed = 1; + print "APW: ALLOWED: block<$block>\n" + if $dbg_adv_apw; + $allowed = 1; } if (statement_block_size($block) > 1) { - #print "APW: ALLOWED: lines block<$block>\n"; - $allowed = 1; + print "APW: ALLOWED: lines block<$block>\n" + if $dbg_adv_apw; + $allowed = 1; } # Check the post-context. if (defined $chunks[1]) { @@ -2574,8 +2586,9 @@ sub process { substr($block, 0, length($cond), ''); } if ($block =~ /^\s*\{/) { - #print "APW: ALLOWED: chunk-1 block<$block>\n"; - $allowed = 1; + print "APW: ALLOWED: chunk-1 block<$block>\n" + if $dbg_adv_apw; + $allowed = 1; } } print "DCS: level=$level block<$block> allowed=$allowed\n" From dfe7053a34353079503bf350f83cb8b6101a450d Mon Sep 17 00:00:00 2001 From: Don Slutz Date: Sun, 2 Sep 2012 19:22:38 -0400 Subject: [PATCH 0199/2270] CHECKPATCH: Add warning for single else statement. For an example: WARNING: braces {} are necessary even for single statement blocks + } else + return env->regs[R_EAX]; total: 0 errors, 1 warnings, 41 lines checked Signed-off-by: Don Slutz Signed-off-by: Blue Swirl --- scripts/checkpatch.pl | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 7ec8846ac9..ec0aa4cd93 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2547,12 +2547,16 @@ sub process { $line !~ /\#\s*else/) { my $allowed = 0; - # Check the pre-context. - if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) { - print "APW: ALLOWED: pre<$pre> line<$line>\n" - if $dbg_adv_apw; - $allowed = 1; - } + # Check the pre-context. + if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) { + my $pre = $1; + + if ($line !~ /else/) { + print "APW: ALLOWED: pre<$pre> line<$line>\n" + if $dbg_adv_apw; + $allowed = 1; + } + } my ($level, $endln, @chunks) = ctx_statement_full($linenr, $realcnt, $-[0]); From d6ce52c1f183add6f60509bc3344a61104489613 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 29 Aug 2012 23:54:25 +0400 Subject: [PATCH 0200/2270] target-xtensa: convert host errno values to guest Guest errno values are taken from the newlib. Convert only those errno values that can be returned from used system calls. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl --- target-xtensa/xtensa-semi.c | 106 +++++++++++++++++++++++++++++++++--- 1 file changed, 98 insertions(+), 8 deletions(-) diff --git a/target-xtensa/xtensa-semi.c b/target-xtensa/xtensa-semi.c index 6d001c2c1a..e745bef0ee 100644 --- a/target-xtensa/xtensa-semi.c +++ b/target-xtensa/xtensa-semi.c @@ -54,6 +54,96 @@ enum { SELECT_ONE_EXCEPT = 3, }; +enum { + TARGET_EPERM = 1, + TARGET_ENOENT = 2, + TARGET_ESRCH = 3, + TARGET_EINTR = 4, + TARGET_EIO = 5, + TARGET_ENXIO = 6, + TARGET_E2BIG = 7, + TARGET_ENOEXEC = 8, + TARGET_EBADF = 9, + TARGET_ECHILD = 10, + TARGET_EAGAIN = 11, + TARGET_ENOMEM = 12, + TARGET_EACCES = 13, + TARGET_EFAULT = 14, + TARGET_ENOTBLK = 15, + TARGET_EBUSY = 16, + TARGET_EEXIST = 17, + TARGET_EXDEV = 18, + TARGET_ENODEV = 19, + TARGET_ENOTDIR = 20, + TARGET_EISDIR = 21, + TARGET_EINVAL = 22, + TARGET_ENFILE = 23, + TARGET_EMFILE = 24, + TARGET_ENOTTY = 25, + TARGET_ETXTBSY = 26, + TARGET_EFBIG = 27, + TARGET_ENOSPC = 28, + TARGET_ESPIPE = 29, + TARGET_EROFS = 30, + TARGET_EMLINK = 31, + TARGET_EPIPE = 32, + TARGET_EDOM = 33, + TARGET_ERANGE = 34, + TARGET_ENOSYS = 88, + TARGET_ELOOP = 92, +}; + +static uint32_t errno_h2g(int host_errno) +{ + static const uint32_t guest_errno[] = { + [EPERM] = TARGET_EPERM, + [ENOENT] = TARGET_ENOENT, + [ESRCH] = TARGET_ESRCH, + [EINTR] = TARGET_EINTR, + [EIO] = TARGET_EIO, + [ENXIO] = TARGET_ENXIO, + [E2BIG] = TARGET_E2BIG, + [ENOEXEC] = TARGET_ENOEXEC, + [EBADF] = TARGET_EBADF, + [ECHILD] = TARGET_ECHILD, + [EAGAIN] = TARGET_EAGAIN, + [ENOMEM] = TARGET_ENOMEM, + [EACCES] = TARGET_EACCES, + [EFAULT] = TARGET_EFAULT, + [ENOTBLK] = TARGET_ENOTBLK, + [EBUSY] = TARGET_EBUSY, + [EEXIST] = TARGET_EEXIST, + [EXDEV] = TARGET_EXDEV, + [ENODEV] = TARGET_ENODEV, + [ENOTDIR] = TARGET_ENOTDIR, + [EISDIR] = TARGET_EISDIR, + [EINVAL] = TARGET_EINVAL, + [ENFILE] = TARGET_ENFILE, + [EMFILE] = TARGET_EMFILE, + [ENOTTY] = TARGET_ENOTTY, + [ETXTBSY] = TARGET_ETXTBSY, + [EFBIG] = TARGET_EFBIG, + [ENOSPC] = TARGET_ENOSPC, + [ESPIPE] = TARGET_ESPIPE, + [EROFS] = TARGET_EROFS, + [EMLINK] = TARGET_EMLINK, + [EPIPE] = TARGET_EPIPE, + [EDOM] = TARGET_EDOM, + [ERANGE] = TARGET_ERANGE, + [ENOSYS] = TARGET_ENOSYS, + [ELOOP] = TARGET_ELOOP, + }; + + if (host_errno == 0) { + return 0; + } else if (host_errno > 0 && host_errno < ARRAY_SIZE(guest_errno) && + guest_errno[host_errno]) { + return guest_errno[host_errno]; + } else { + return TARGET_EINVAL; + } +} + void HELPER(simcall)(CPUXtensaState *env) { uint32_t *regs = env->regs; @@ -87,14 +177,14 @@ void HELPER(simcall)(CPUXtensaState *env) regs[2] = is_write ? write(fd, buf, io_sz) : read(fd, buf, io_sz); - regs[3] = errno; + regs[3] = errno_h2g(errno); cpu_physical_memory_unmap(buf, sz, is_write, sz); if (regs[2] == -1) { break; } } else { regs[2] = -1; - regs[3] = EINVAL; + regs[3] = TARGET_EINVAL; break; } } @@ -117,10 +207,10 @@ void HELPER(simcall)(CPUXtensaState *env) if (rc == 0 && i < ARRAY_SIZE(name)) { regs[2] = open(name, regs[4], regs[5]); - regs[3] = errno; + regs[3] = errno_h2g(errno); } else { regs[2] = -1; - regs[3] = EINVAL; + regs[3] = TARGET_EINVAL; } } break; @@ -130,13 +220,13 @@ void HELPER(simcall)(CPUXtensaState *env) regs[2] = regs[3] = 0; } else { regs[2] = close(regs[3]); - regs[3] = errno; + regs[3] = errno_h2g(errno); } break; case TARGET_SYS_lseek: regs[2] = lseek(regs[3], (off_t)(int32_t)regs[4], regs[5]); - regs[3] = errno; + regs[3] = errno_h2g(errno); break; case TARGET_SYS_select_one: @@ -163,7 +253,7 @@ void HELPER(simcall)(CPUXtensaState *env) rq == SELECT_ONE_WRITE ? &fdset : NULL, rq == SELECT_ONE_EXCEPT ? &fdset : NULL, target_tv ? &tv : NULL); - regs[3] = errno; + regs[3] = errno_h2g(errno); } break; @@ -219,7 +309,7 @@ void HELPER(simcall)(CPUXtensaState *env) default: qemu_log("%s(%d): not implemented\n", __func__, regs[2]); regs[2] = -1; - regs[3] = ENOSYS; + regs[3] = TARGET_ENOSYS; break; } } From 6e4c0d1f03d6ab407509c32fab7cb4b8230f57ff Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 27 Aug 2012 12:32:36 +0100 Subject: [PATCH 0201/2270] hw/pl110: Fix spelling of 'palette' Fix the spelling of 'palette' used in various local variables, structure members and comments. Signed-off-by: Peter Maydell Reviewed-by: Stefan Weil Signed-off-by: Aurelien Jarno --- hw/pl110.c | 30 +++++++++++++++--------------- hw/pl110_template.h | 22 +++++++++++----------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/hw/pl110.c b/hw/pl110.c index f94608cb62..a5826407ab 100644 --- a/hw/pl110.c +++ b/hw/pl110.c @@ -55,8 +55,8 @@ typedef struct { enum pl110_bppmode bpp; int invalidate; uint32_t mux_ctrl; - uint32_t pallette[256]; - uint32_t raw_pallette[128]; + uint32_t palette[256]; + uint32_t raw_palette[128]; qemu_irq irq; } pl110_state; @@ -79,8 +79,8 @@ static const VMStateDescription vmstate_pl110 = { VMSTATE_INT32(rows, pl110_state), VMSTATE_UINT32(bpp, pl110_state), VMSTATE_INT32(invalidate, pl110_state), - VMSTATE_UINT32_ARRAY(pallette, pl110_state, 256), - VMSTATE_UINT32_ARRAY(raw_pallette, pl110_state, 128), + VMSTATE_UINT32_ARRAY(palette, pl110_state, 256), + VMSTATE_UINT32_ARRAY(raw_palette, pl110_state, 128), VMSTATE_UINT32_V(mux_ctrl, pl110_state, 2), VMSTATE_END_OF_LIST() } @@ -236,7 +236,7 @@ static void pl110_update_display(void *opaque) s->upbase, s->cols, s->rows, src_width, dest_width, 0, s->invalidate, - fn, s->pallette, + fn, s->palette, &first, &last); if (first >= 0) { dpy_update(s->ds, 0, first, s->cols, last - first + 1); @@ -253,13 +253,13 @@ static void pl110_invalidate_display(void * opaque) } } -static void pl110_update_pallette(pl110_state *s, int n) +static void pl110_update_palette(pl110_state *s, int n) { int i; uint32_t raw; unsigned int r, g, b; - raw = s->raw_pallette[n]; + raw = s->raw_palette[n]; n <<= 1; for (i = 0; i < 2; i++) { r = (raw & 0x1f) << 3; @@ -271,17 +271,17 @@ static void pl110_update_pallette(pl110_state *s, int n) raw >>= 6; switch (ds_get_bits_per_pixel(s->ds)) { case 8: - s->pallette[n] = rgb_to_pixel8(r, g, b); + s->palette[n] = rgb_to_pixel8(r, g, b); break; case 15: - s->pallette[n] = rgb_to_pixel15(r, g, b); + s->palette[n] = rgb_to_pixel15(r, g, b); break; case 16: - s->pallette[n] = rgb_to_pixel16(r, g, b); + s->palette[n] = rgb_to_pixel16(r, g, b); break; case 24: case 32: - s->pallette[n] = rgb_to_pixel32(r, g, b); + s->palette[n] = rgb_to_pixel32(r, g, b); break; } n++; @@ -314,7 +314,7 @@ static uint64_t pl110_read(void *opaque, target_phys_addr_t offset, return idregs[s->version][(offset - 0xfe0) >> 2]; } if (offset >= 0x200 && offset < 0x400) { - return s->raw_pallette[(offset - 0x200) >> 2]; + return s->raw_palette[(offset - 0x200) >> 2]; } switch (offset >> 2) { case 0: /* LCDTiming0 */ @@ -364,10 +364,10 @@ static void pl110_write(void *opaque, target_phys_addr_t offset, is written to. */ s->invalidate = 1; if (offset >= 0x200 && offset < 0x400) { - /* Pallette. */ + /* Palette. */ n = (offset - 0x200) >> 2; - s->raw_pallette[(offset - 0x200) >> 2] = val; - pl110_update_pallette(s, n); + s->raw_palette[(offset - 0x200) >> 2] = val; + pl110_update_palette(s, n); return; } switch (offset >> 2) { diff --git a/hw/pl110_template.h b/hw/pl110_template.h index 1dce32a0c3..e738e4a241 100644 --- a/hw/pl110_template.h +++ b/hw/pl110_template.h @@ -129,14 +129,14 @@ static drawfn glue(pl110_draw_fn_,BITS)[48] = static void glue(pl110_draw_line1_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) { - uint32_t *pallette = opaque; + uint32_t *palette = opaque; uint32_t data; while (width > 0) { data = *(uint32_t *)src; #ifdef SWAP_PIXELS -#define FN(x, y) COPY_PIXEL(d, pallette[(data >> (y + 7 - (x))) & 1]); +#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 7 - (x))) & 1]); #else -#define FN(x, y) COPY_PIXEL(d, pallette[(data >> ((x) + y)) & 1]); +#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x) + y)) & 1]); #endif #ifdef SWAP_WORDS FN_8(24) @@ -157,14 +157,14 @@ static void glue(pl110_draw_line1_,NAME)(void *opaque, uint8_t *d, const uint8_t static void glue(pl110_draw_line2_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) { - uint32_t *pallette = opaque; + uint32_t *palette = opaque; uint32_t data; while (width > 0) { data = *(uint32_t *)src; #ifdef SWAP_PIXELS -#define FN(x, y) COPY_PIXEL(d, pallette[(data >> (y + 6 - (x)*2)) & 3]); +#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 6 - (x)*2)) & 3]); #else -#define FN(x, y) COPY_PIXEL(d, pallette[(data >> ((x)*2 + y)) & 3]); +#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x)*2 + y)) & 3]); #endif #ifdef SWAP_WORDS FN_4(0, 24) @@ -185,14 +185,14 @@ static void glue(pl110_draw_line2_,NAME)(void *opaque, uint8_t *d, const uint8_t static void glue(pl110_draw_line4_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) { - uint32_t *pallette = opaque; + uint32_t *palette = opaque; uint32_t data; while (width > 0) { data = *(uint32_t *)src; #ifdef SWAP_PIXELS -#define FN(x, y) COPY_PIXEL(d, pallette[(data >> (y + 4 - (x)*4)) & 0xf]); +#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 4 - (x)*4)) & 0xf]); #else -#define FN(x, y) COPY_PIXEL(d, pallette[(data >> ((x)*4 + y)) & 0xf]); +#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x)*4 + y)) & 0xf]); #endif #ifdef SWAP_WORDS FN_2(0, 24) @@ -213,11 +213,11 @@ static void glue(pl110_draw_line4_,NAME)(void *opaque, uint8_t *d, const uint8_t static void glue(pl110_draw_line8_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) { - uint32_t *pallette = opaque; + uint32_t *palette = opaque; uint32_t data; while (width > 0) { data = *(uint32_t *)src; -#define FN(x) COPY_PIXEL(d, pallette[(data >> (x)) & 0xff]); +#define FN(x) COPY_PIXEL(d, palette[(data >> (x)) & 0xff]); #ifdef SWAP_WORDS FN(24) FN(16) From 692e587fc61fd32d755234d187b4f082e28c3993 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 19 Jul 2012 17:26:10 +0300 Subject: [PATCH 0202/2270] qemu: add .exrc I've been using this to get correct indenting with vim in qemu for a while, but it's a bit easier if we put the settings in the central place. Note that 1. you still need to enable 'exrc' and 'secure' options in your vimrc for these settings to take effect. 2. you can create a .vimrc file if 'exrc' is on but there's need to bypass this configuration. Signed-off-by: Michael S. Tsirkin --- .exrc | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .exrc diff --git a/.exrc b/.exrc new file mode 100644 index 0000000000..37755ede83 --- /dev/null +++ b/.exrc @@ -0,0 +1,7 @@ +"VIM settings to match QEMU coding style. They are activated by adding the +"following settings (without the " symbol) as last two lines in $HOME/.vimrc: +"set secure +"set exrc +set expandtab +set shiftwidth=4 +set smarttab From 1de53459272d89c52bb21b45d5d970de40fbb642 Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Wed, 8 Aug 2012 14:29:12 -0400 Subject: [PATCH 0203/2270] pcie: drop version_id field for live migration While testing q35 live migration, I found that the migration would abort with the following error: "Unknown savevm section type 76". The error is due to this check failing in 'vmstate_load_state()': while(field->name) { if ((field->field_exists && field->field_exists(opaque, version_id)) || (!field->field_exists && field->version_id <= version_id)) { The VMSTATE_PCIE_DEVICE() currently has a 'version_id' set to 2. However, 'version_id' in the above check is 1. And thus we fail to load the pcie device field. Further the code returns to 'qemu_loadvm_state()' which produces the error that I saw. I'm proposing to fix this by simply dropping the 'version_id' field from VMSTATE_PCIE_DEVICE(). VMSTATE_PCI_DEVICE() defines no such field and further the vmstate_pcie_device that VMSTATE_PCI_DEVICE() refers to is already versioned. Thus, any versioning issues could be detected at the vmsd level. Taking a step back, I think that the 'field->version_id' should be compared against a saved version number for the field not the 'version_id'. Futhermore, once vmstate_load_state() is called recursively on another vmsd, the check of: if (version_id > vmsd->version_id) { return -EINVAL; } Will never fail since version_id is always equal to vmsd->version_id. So I'm wondering why we aren't storing the vmsd version id of the source in the migration stream? This patch also renames the 'name' field of vmstate_pcie_device from: PCIDevice -> PCIEDevice to differentiate it from vmstate_pci_device. Signed-off-by: Jason Baron Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 2 +- hw/pcie.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index 4d95984807..f855cf3f39 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -439,7 +439,7 @@ const VMStateDescription vmstate_pci_device = { }; const VMStateDescription vmstate_pcie_device = { - .name = "PCIDevice", + .name = "PCIEDevice", .version_id = 2, .minimum_version_id = 1, .minimum_version_id_old = 1, diff --git a/hw/pcie.h b/hw/pcie.h index b8ab0c7b4f..4889194ae6 100644 --- a/hw/pcie.h +++ b/hw/pcie.h @@ -133,7 +133,6 @@ extern const VMStateDescription vmstate_pcie_device; #define VMSTATE_PCIE_DEVICE(_field, _state) { \ .name = (stringify(_field)), \ - .version_id = 2, \ .size = sizeof(PCIDevice), \ .vmsd = &vmstate_pcie_device, \ .flags = VMS_STRUCT, \ From 0e180d9c8a7429c55d23d2e7855f1e490a063aaa Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Tue, 4 Sep 2012 16:22:46 -0400 Subject: [PATCH 0204/2270] pcie_aer: clear cmask for Advanced Error Interrupt Message Number The Advanced Error Interrupt Message Number (bits 31:27 of the Root Error Status Register) is updated when the number of msi messages assigned to a device changes. Migration of windows 7 on q35 chipset failed because the check in get_pci_config_device() fails due to cmask being set on these bits. Its valid to update these bits and we must restore this state across migration. Signed-off-by: Jason Baron Signed-off-by: Michael S. Tsirkin --- hw/pcie_aer.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c index 3b6981c7b7..b04c164e22 100644 --- a/hw/pcie_aer.c +++ b/hw/pcie_aer.c @@ -738,6 +738,11 @@ void pcie_aer_root_init(PCIDevice *dev) PCI_ERR_ROOT_CMD_EN_MASK); pci_set_long(dev->w1cmask + pos + PCI_ERR_ROOT_STATUS, PCI_ERR_ROOT_STATUS_REPORT_MASK); + /* PCI_ERR_ROOT_IRQ is RO but devices change it using a + * device-specific method. + */ + pci_set_long(dev->cmask + pos + PCI_ERR_ROOT_STATUS, + ~PCI_ERR_ROOT_IRQ); } void pcie_aer_root_reset(PCIDevice *dev) From a96ed02fc73e23748c8b3e38880eeac91f83ab9f Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 21 Aug 2012 20:52:07 +0000 Subject: [PATCH 0205/2270] monitor: Rename+move net_handle_fd_param -> monitor_handle_fd_param This patch renames+moves the net_handle_fd_param() caller used to obtain a file descriptor from either qemu_parse_fd() (the normal case) or from monitor_get_fd() (migration case) into a generically prefixed monitor_handle_fd_param() to be used by vhost-scsi code. Also update net/[socket,tap].c consumers to use the new prefix. Reported-by: Michael S. Tsirkin Cc: Michael S. Tsirkin Cc: Stefan Hajnoczi Cc: Paolo Bonzini Cc: Anthony Liguori Signed-off-by: Nicholas Bellinger Signed-off-by: Michael S. Tsirkin --- monitor.c | 18 ++++++++++++++++++ monitor.h | 1 + net.c | 18 ------------------ net.h | 2 -- net/socket.c | 2 +- net/tap.c | 4 ++-- 6 files changed, 22 insertions(+), 23 deletions(-) diff --git a/monitor.c b/monitor.c index b17b1bb849..6b70b20b9f 100644 --- a/monitor.c +++ b/monitor.c @@ -2651,6 +2651,24 @@ int monitor_fdset_dup_fd_remove(int dup_fd) return monitor_fdset_dup_fd_find_remove(dup_fd, true); } +int monitor_handle_fd_param(Monitor *mon, const char *fdname) +{ + int fd; + + if (!qemu_isdigit(fdname[0]) && mon) { + + fd = monitor_get_fd(mon, fdname); + if (fd == -1) { + error_report("No file descriptor named %s found", fdname); + return -1; + } + } else { + fd = qemu_parse_fd(fdname); + } + + return fd; +} + /* mon_cmds and info_cmds would be sorted at runtime */ static mon_cmd_t mon_cmds[] = { #include "hmp-commands.h" diff --git a/monitor.h b/monitor.h index 47d556b9d1..714b9ea5bc 100644 --- a/monitor.h +++ b/monitor.h @@ -66,6 +66,7 @@ int monitor_read_block_device_key(Monitor *mon, const char *device, void *opaque); int monitor_get_fd(Monitor *mon, const char *fdname); +int monitor_handle_fd_param(Monitor *mon, const char *fdname); void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) GCC_FMT_ATTR(2, 0); diff --git a/net.c b/net.c index 60043ddec6..e5d25d4b6d 100644 --- a/net.c +++ b/net.c @@ -522,24 +522,6 @@ int qemu_find_nic_model(NICInfo *nd, const char * const *models, return -1; } -int net_handle_fd_param(Monitor *mon, const char *param) -{ - int fd; - - if (!qemu_isdigit(param[0]) && mon) { - - fd = monitor_get_fd(mon, param); - if (fd == -1) { - error_report("No file descriptor named %s found", param); - return -1; - } - } else { - fd = qemu_parse_fd(param); - } - - return fd; -} - static int net_init_nic(const NetClientOptions *opts, const char *name, NetClientState *peer) { diff --git a/net.h b/net.h index 29750567ed..04fda1d6c8 100644 --- a/net.h +++ b/net.h @@ -168,8 +168,6 @@ int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret); void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd); -int net_handle_fd_param(Monitor *mon, const char *param); - #define POLYNOMIAL 0x04c11db6 unsigned compute_mcast_idx(const uint8_t *ep); diff --git a/net/socket.c b/net/socket.c index c172c249be..7c602e4c3a 100644 --- a/net/socket.c +++ b/net/socket.c @@ -629,7 +629,7 @@ int net_init_socket(const NetClientOptions *opts, const char *name, if (sock->has_fd) { int fd; - fd = net_handle_fd_param(cur_mon, sock->fd); + fd = monitor_handle_fd_param(cur_mon, sock->fd); if (fd == -1 || !net_socket_fd_init(peer, "socket", name, fd, 1)) { return -1; } diff --git a/net/tap.c b/net/tap.c index 1971525794..a88ae8f61a 100644 --- a/net/tap.c +++ b/net/tap.c @@ -610,7 +610,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name, return -1; } - fd = net_handle_fd_param(cur_mon, tap->fd); + fd = monitor_handle_fd_param(cur_mon, tap->fd); if (fd == -1) { return -1; } @@ -686,7 +686,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name, int vhostfd; if (tap->has_vhostfd) { - vhostfd = net_handle_fd_param(cur_mon, tap->vhostfd); + vhostfd = monitor_handle_fd_param(cur_mon, tap->vhostfd); if (vhostfd == -1) { return -1; } From 1241ed94c331ddd8fc8297b02b4508ead59467de Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 21 Aug 2012 20:52:08 +0000 Subject: [PATCH 0206/2270] vhost: Pass device path to vhost_dev_init() The path to /dev/vhost-net is currently hardcoded in vhost_dev_init(). This needs to be changed so that /dev/vhost-scsi can be used. Pass in the device path instead of hardcoding it. Signed-off-by: Stefan Hajnoczi Cc: Paolo Bonzini Cc: Michael S. Tsirkin Signed-off-by: Nicholas Bellinger Signed-off-by: Michael S. Tsirkin --- hw/vhost.c | 5 +++-- hw/vhost.h | 3 ++- hw/vhost_net.c | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/hw/vhost.c b/hw/vhost.c index 0fd8da84e2..d0ce5aad9b 100644 --- a/hw/vhost.c +++ b/hw/vhost.c @@ -747,14 +747,15 @@ static void vhost_eventfd_del(MemoryListener *listener, { } -int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force) +int vhost_dev_init(struct vhost_dev *hdev, int devfd, const char *devpath, + bool force) { uint64_t features; int r; if (devfd >= 0) { hdev->control = devfd; } else { - hdev->control = open("/dev/vhost-net", O_RDWR); + hdev->control = open(devpath, O_RDWR); if (hdev->control < 0) { return -errno; } diff --git a/hw/vhost.h b/hw/vhost.h index 80e64df860..0c47229f91 100644 --- a/hw/vhost.h +++ b/hw/vhost.h @@ -44,7 +44,8 @@ struct vhost_dev { bool force; }; -int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force); +int vhost_dev_init(struct vhost_dev *hdev, int devfd, const char *devpath, + bool force); void vhost_dev_cleanup(struct vhost_dev *hdev); bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev); int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); diff --git a/hw/vhost_net.c b/hw/vhost_net.c index ecaa22dfb4..df2c4a30a2 100644 --- a/hw/vhost_net.c +++ b/hw/vhost_net.c @@ -109,7 +109,7 @@ struct vhost_net *vhost_net_init(NetClientState *backend, int devfd, (1 << VHOST_NET_F_VIRTIO_NET_HDR); net->backend = r; - r = vhost_dev_init(&net->dev, devfd, force); + r = vhost_dev_init(&net->dev, devfd, "/dev/vhost-net", force); if (r < 0) { goto fail; } From 7e9c7ffe9fd9dfc3d0168dd584936db8144b230b Mon Sep 17 00:00:00 2001 From: Henning Schild Date: Wed, 5 Sep 2012 14:56:39 +0200 Subject: [PATCH 0207/2270] fix entry pointer for ELF kernels loaded with -kernel option Find a hopefully proper patch attached. Take it or leave it. Reviewed-by: Kevin Wolf Signed-off-by: Henning Schild Signed-off-by: Aurelien Jarno --- hw/elf_ops.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/hw/elf_ops.h b/hw/elf_ops.h index fa65ce2f93..731a983854 100644 --- a/hw/elf_ops.h +++ b/hw/elf_ops.h @@ -269,6 +269,17 @@ static int glue(load_elf, SZ)(const char *name, int fd, addr = ph->p_paddr; } + /* the entry pointer in the ELF header is a virtual + * address, if the text segments paddr and vaddr differ + * we need to adjust the entry */ + if (pentry && !translate_fn && + ph->p_vaddr != ph->p_paddr && + ehdr.e_entry >= ph->p_vaddr && + ehdr.e_entry < ph->p_vaddr + ph->p_filesz && + ph->p_flags & PF_X) { + *pentry = ehdr.e_entry - ph->p_vaddr + ph->p_paddr; + } + snprintf(label, sizeof(label), "phdr #%d: %s", i, name); rom_add_blob_fixed(label, data, mem_size, addr); From 449bc90e1f2e2fbafb64eb0c76d16c9352b0d2df Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 10 Jun 2012 23:18:44 +0200 Subject: [PATCH 0208/2270] lan9118: fix multicast filtering The lan9118 emulation tries to compute the multicast index by calling directly the crc32() function from zlib, but fails to get the correct result. Use the common compute_mcast_idx() function instead, which gives the correct result. This fixes IPv6 support. Reviewed-by: Peter Maydell Signed-off-by: Aurelien Jarno --- hw/lan9118.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/lan9118.c b/hw/lan9118.c index ff0a50be19..ceaf96fc3e 100644 --- a/hw/lan9118.c +++ b/hw/lan9118.c @@ -500,7 +500,7 @@ static int lan9118_filter(lan9118_state *s, const uint8_t *addr) } } else { /* Hash matching */ - hash = (crc32(~0, addr, 6) >> 26); + hash = compute_mcast_idx(addr); if (hash & 0x20) { return (s->mac_hashh >> (hash & 0x1f)) & 1; } else { From 03e6e5017757645f00b2f3b4f3a257973985e455 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 8 Jun 2012 02:04:40 +0100 Subject: [PATCH 0209/2270] MIPS/user: Fix reset CPU state initialization This change updates the CPU reset sequence to use a common piece of code that figures out CPU state flags, fixing the problem with MIPS_HFLAG_COP1X not being set where applicable that causes floating-point MADD family instructions (and other instructions from the MIPS IV FP subset) to trap. As compute_hflags is now shared between op_helper.c and translate.c, the function is now moved to a common header. There are no changes to this function. The problem was seen with the 24Kf MIPS32r2 processor in user emulation. The new approach prevents system and user emulation from diverging -- all the hflags state is initialized in one place now. Signed-off-by: Maciej W. Rozycki Signed-off-by: Aurelien Jarno --- target-mips/cpu.h | 49 +++++++++++++++++++++++++++++++++++++++++ target-mips/op_helper.c | 49 ----------------------------------------- target-mips/translate.c | 16 +++----------- 3 files changed, 52 insertions(+), 62 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index ce3467f140..88d92f1182 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -742,4 +742,53 @@ static inline void cpu_pc_from_tb(CPUMIPSState *env, TranslationBlock *tb) env->hflags |= tb->flags & MIPS_HFLAG_BMASK; } +static inline void compute_hflags(CPUMIPSState *env) +{ + env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | + MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU | + MIPS_HFLAG_UX); + if (!(env->CP0_Status & (1 << CP0St_EXL)) && + !(env->CP0_Status & (1 << CP0St_ERL)) && + !(env->hflags & MIPS_HFLAG_DM)) { + env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU; + } +#if defined(TARGET_MIPS64) + if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) || + (env->CP0_Status & (1 << CP0St_PX)) || + (env->CP0_Status & (1 << CP0St_UX))) { + env->hflags |= MIPS_HFLAG_64; + } + if (env->CP0_Status & (1 << CP0St_UX)) { + env->hflags |= MIPS_HFLAG_UX; + } +#endif + if ((env->CP0_Status & (1 << CP0St_CU0)) || + !(env->hflags & MIPS_HFLAG_KSU)) { + env->hflags |= MIPS_HFLAG_CP0; + } + if (env->CP0_Status & (1 << CP0St_CU1)) { + env->hflags |= MIPS_HFLAG_FPU; + } + if (env->CP0_Status & (1 << CP0St_FR)) { + env->hflags |= MIPS_HFLAG_F64; + } + if (env->insn_flags & ISA_MIPS32R2) { + if (env->active_fpu.fcr0 & (1 << FCR0_F64)) { + env->hflags |= MIPS_HFLAG_COP1X; + } + } else if (env->insn_flags & ISA_MIPS32) { + if (env->hflags & MIPS_HFLAG_64) { + env->hflags |= MIPS_HFLAG_COP1X; + } + } else if (env->insn_flags & ISA_MIPS4) { + /* All supported MIPS IV CPUs use the XX (CU3) to enable + and disable the MIPS IV extensions to the MIPS III ISA. + Some other MIPS IV CPUs ignore the bit, so the check here + would be too restrictive for them. */ + if (env->CP0_Status & (1 << CP0St_CU3)) { + env->hflags |= MIPS_HFLAG_COP1X; + } + } +} + #endif /* !defined (__MIPS_CPU_H__) */ diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index e5bc93e226..3d242aafda 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -32,55 +32,6 @@ static inline void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global); #endif -static inline void compute_hflags(CPUMIPSState *env) -{ - env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | - MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU | - MIPS_HFLAG_UX); - if (!(env->CP0_Status & (1 << CP0St_EXL)) && - !(env->CP0_Status & (1 << CP0St_ERL)) && - !(env->hflags & MIPS_HFLAG_DM)) { - env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU; - } -#if defined(TARGET_MIPS64) - if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) || - (env->CP0_Status & (1 << CP0St_PX)) || - (env->CP0_Status & (1 << CP0St_UX))) { - env->hflags |= MIPS_HFLAG_64; - } - if (env->CP0_Status & (1 << CP0St_UX)) { - env->hflags |= MIPS_HFLAG_UX; - } -#endif - if ((env->CP0_Status & (1 << CP0St_CU0)) || - !(env->hflags & MIPS_HFLAG_KSU)) { - env->hflags |= MIPS_HFLAG_CP0; - } - if (env->CP0_Status & (1 << CP0St_CU1)) { - env->hflags |= MIPS_HFLAG_FPU; - } - if (env->CP0_Status & (1 << CP0St_FR)) { - env->hflags |= MIPS_HFLAG_F64; - } - if (env->insn_flags & ISA_MIPS32R2) { - if (env->active_fpu.fcr0 & (1 << FCR0_F64)) { - env->hflags |= MIPS_HFLAG_COP1X; - } - } else if (env->insn_flags & ISA_MIPS32) { - if (env->hflags & MIPS_HFLAG_64) { - env->hflags |= MIPS_HFLAG_COP1X; - } - } else if (env->insn_flags & ISA_MIPS4) { - /* All supported MIPS IV CPUs use the XX (CU3) to enable - and disable the MIPS IV extensions to the MIPS III ISA. - Some other MIPS IV CPUs ignore the bit, so the check here - would be too restrictive for them. */ - if (env->CP0_Status & (1 << CP0St_CU3)) { - env->hflags |= MIPS_HFLAG_COP1X; - } - } -} - /*****************************************************************************/ /* Exceptions processing helpers */ diff --git a/target-mips/translate.c b/target-mips/translate.c index b293419536..a884f751bc 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -12787,18 +12787,13 @@ void cpu_state_reset(CPUMIPSState *env) env->insn_flags = env->cpu_model->insn_flags; #if defined(CONFIG_USER_ONLY) - env->hflags = MIPS_HFLAG_UM; + env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU); /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR hardware registers. */ env->CP0_HWREna |= 0x0000000F; if (env->CP0_Config1 & (1 << CP0C1_FP)) { - env->hflags |= MIPS_HFLAG_FPU; + env->CP0_Status |= (1 << CP0St_CU1); } -#ifdef TARGET_MIPS64 - if (env->active_fpu.fcr0 & (1 << FCR0_F64)) { - env->hflags |= MIPS_HFLAG_F64; - } -#endif #else if (env->hflags & MIPS_HFLAG_BMASK) { /* If the exception was raised from a delay slot, @@ -12828,7 +12823,6 @@ void cpu_state_reset(CPUMIPSState *env) } /* Count register increments in debug mode, EJTAG version 1 */ env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER); - env->hflags = MIPS_HFLAG_CP0; if (env->CP0_Config3 & (1 << CP0C3_MT)) { int i; @@ -12856,11 +12850,7 @@ void cpu_state_reset(CPUMIPSState *env) } } #endif -#if defined(TARGET_MIPS64) - if (env->cpu_model->insn_flags & ISA_MIPS3) { - env->hflags |= MIPS_HFLAG_64; - } -#endif + compute_hflags(env); env->exception_index = EXCP_NONE; } From c001ed15f7bfeaa3cabde5c9cc79c4dfdb674769 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 7 Sep 2012 22:36:08 +0200 Subject: [PATCH 0210/2270] target-cris: Fix buffer overflow Report from smatch: target-cris/translate.c:3464 cpu_dump_state(32) error: buffer overflow 'env->sregs' 4 <= 255 sregs is declared 'uint32_t sregs[4][16]', so the first index must be less than 4 or ARRAY_SIZE(env->sregs). Signed-off-by: Stefan Weil --- target-cris/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-cris/translate.c b/target-cris/translate.c index 1ad9ec788e..ad3187773e 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -3458,7 +3458,7 @@ void cpu_dump_state (CPUCRISState *env, FILE *f, fprintf_function cpu_fprintf, } srs = env->pregs[PR_SRS]; cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs); - if (srs < 256) { + if (srs < ARRAY_SIZE(env->sregs)) { for (i = 0; i < 16; i++) { cpu_fprintf(f, "s%2.2d=%8.8x ", i, env->sregs[srs][i]); From c29b1bee4b025f51f02cc9f521ca19cb5f3eb432 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 6 Sep 2012 04:36:46 +0400 Subject: [PATCH 0211/2270] target-xtensa: fix missing errno codes for mingw32 Put the following errno value mappings under #ifdef: xtensa-semi.c: In function 'errno_h2g': xtensa-semi.c:113: error: 'ENOTBLK' undeclared (first use in this function) xtensa-semi.c:113: error: (Each undeclared identifier is reported only once xtensa-semi.c:113: error: for each function it appears in.) xtensa-semi.c:113: error: array index in initializer not of integer type xtensa-semi.c:113: error: (near initialization for 'guest_errno') xtensa-semi.c:124: error: 'ETXTBSY' undeclared (first use in this function) xtensa-semi.c:124: error: array index in initializer not of integer type xtensa-semi.c:124: error: (near initialization for 'guest_errno') xtensa-semi.c:134: error: 'ELOOP' undeclared (first use in this function) xtensa-semi.c:134: error: array index in initializer not of integer type xtensa-semi.c:134: error: (near initialization for 'guest_errno') Signed-off-by: Max Filippov Signed-off-by: Blue Swirl --- target-xtensa/xtensa-semi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target-xtensa/xtensa-semi.c b/target-xtensa/xtensa-semi.c index e745bef0ee..52be07a368 100644 --- a/target-xtensa/xtensa-semi.c +++ b/target-xtensa/xtensa-semi.c @@ -110,7 +110,9 @@ static uint32_t errno_h2g(int host_errno) [ENOMEM] = TARGET_ENOMEM, [EACCES] = TARGET_EACCES, [EFAULT] = TARGET_EFAULT, +#ifdef ENOTBLK [ENOTBLK] = TARGET_ENOTBLK, +#endif [EBUSY] = TARGET_EBUSY, [EEXIST] = TARGET_EEXIST, [EXDEV] = TARGET_EXDEV, @@ -121,7 +123,9 @@ static uint32_t errno_h2g(int host_errno) [ENFILE] = TARGET_ENFILE, [EMFILE] = TARGET_EMFILE, [ENOTTY] = TARGET_ENOTTY, +#ifdef ETXTBSY [ETXTBSY] = TARGET_ETXTBSY, +#endif [EFBIG] = TARGET_EFBIG, [ENOSPC] = TARGET_ENOSPC, [ESPIPE] = TARGET_ESPIPE, @@ -131,7 +135,9 @@ static uint32_t errno_h2g(int host_errno) [EDOM] = TARGET_EDOM, [ERANGE] = TARGET_ERANGE, [ENOSYS] = TARGET_ENOSYS, +#ifdef ELOOP [ELOOP] = TARGET_ELOOP, +#endif }; if (host_errno == 0) { From 5acfc8320fdd455c3ee5c21fe7d3403dbc755372 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 7 Sep 2012 17:13:28 +0200 Subject: [PATCH 0212/2270] target-sparc: fix fcmp{s,d,q} instructions wrt exception fcmp{s,d,q} instructions are supposed to ignore quiet NaN (contrary to the fcmpe{s,d,q} instructions), but the current code is wrongly setting the NV exception in that case. Moreover the current code is duplicated: first the arguments are checked for NaN to generate an exception, and later in case the comparison is unordered (which can only happens if one of the argument is a NaN), the same check is done to generate an exception. Fix that by calling clear_float_exceptions() followed by check_ieee_exceptions() as for the other floating point instructions. Use the _compare_quiet functions for fcmp{s,d,q} and the _compare ones for fcmpe{s,d,q}. Simplify the flag setting by not clearing a flag that is set the line just below. This fix allows the math glibc testsuite to pass. Cc: Blue Swirl Signed-off-by: Aurelien Jarno Signed-off-by: Blue Swirl --- target-sparc/fop_helper.c | 67 ++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 40 deletions(-) diff --git a/target-sparc/fop_helper.c b/target-sparc/fop_helper.c index 9c64ef89fe..f4b62a5ba2 100644 --- a/target-sparc/fop_helper.c +++ b/target-sparc/fop_helper.c @@ -334,34 +334,28 @@ void helper_fsqrtq(CPUSPARCState *env) } #define GEN_FCMP(name, size, reg1, reg2, FS, E) \ - void glue(helper_, name) (CPUSPARCState *env) \ + void glue(helper_, name) (CPUSPARCState *env) \ { \ - env->fsr &= FSR_FTT_NMASK; \ - if (E && (glue(size, _is_any_nan)(reg1) || \ - glue(size, _is_any_nan)(reg2)) && \ - (env->fsr & FSR_NVM)) { \ - env->fsr |= FSR_NVC; \ - env->fsr |= FSR_FTT_IEEE_EXCP; \ - helper_raise_exception(env, TT_FP_EXCP); \ + int ret; \ + clear_float_exceptions(env); \ + if (E) { \ + ret = glue(size, _compare)(reg1, reg2, &env->fp_status); \ + } else { \ + ret = glue(size, _compare_quiet)(reg1, reg2, \ + &env->fp_status); \ } \ - switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \ + check_ieee_exceptions(env); \ + switch (ret) { \ case float_relation_unordered: \ - if ((env->fsr & FSR_NVM)) { \ - env->fsr |= FSR_NVC; \ - env->fsr |= FSR_FTT_IEEE_EXCP; \ - helper_raise_exception(env, TT_FP_EXCP); \ - } else { \ - env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ - env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \ - env->fsr |= FSR_NVA; \ - } \ + env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \ + env->fsr |= FSR_NVA; \ break; \ case float_relation_less: \ - env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ + env->fsr &= ~(FSR_FCC1) << FS; \ env->fsr |= FSR_FCC0 << FS; \ break; \ case float_relation_greater: \ - env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ + env->fsr &= ~(FSR_FCC0) << FS; \ env->fsr |= FSR_FCC1 << FS; \ break; \ default: \ @@ -370,34 +364,27 @@ void helper_fsqrtq(CPUSPARCState *env) } \ } #define GEN_FCMP_T(name, size, FS, E) \ - void glue(helper_, name)(CPUSPARCState *env, size src1, size src2) \ + void glue(helper_, name)(CPUSPARCState *env, size src1, size src2) \ { \ - env->fsr &= FSR_FTT_NMASK; \ - if (E && (glue(size, _is_any_nan)(src1) || \ - glue(size, _is_any_nan)(src2)) && \ - (env->fsr & FSR_NVM)) { \ - env->fsr |= FSR_NVC; \ - env->fsr |= FSR_FTT_IEEE_EXCP; \ - helper_raise_exception(env, TT_FP_EXCP); \ + int ret; \ + clear_float_exceptions(env); \ + if (E) { \ + ret = glue(size, _compare)(src1, src2, &env->fp_status); \ + } else { \ + ret = glue(size, _compare_quiet)(src1, src2, \ + &env->fp_status); \ } \ - switch (glue(size, _compare) (src1, src2, &env->fp_status)) { \ + check_ieee_exceptions(env); \ + switch (ret) { \ case float_relation_unordered: \ - if ((env->fsr & FSR_NVM)) { \ - env->fsr |= FSR_NVC; \ - env->fsr |= FSR_FTT_IEEE_EXCP; \ - helper_raise_exception(env, TT_FP_EXCP); \ - } else { \ - env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ - env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \ - env->fsr |= FSR_NVA; \ - } \ + env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \ break; \ case float_relation_less: \ - env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ + env->fsr &= ~(FSR_FCC1 << FS); \ env->fsr |= FSR_FCC0 << FS; \ break; \ case float_relation_greater: \ - env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ + env->fsr &= ~(FSR_FCC0 << FS); \ env->fsr |= FSR_FCC1 << FS; \ break; \ default: \ From ce6c760c37b9a88db87c5b9b9bf39ca866e570f6 Mon Sep 17 00:00:00 2001 From: Fabien Chouteau Date: Tue, 22 May 2012 10:14:28 +0200 Subject: [PATCH 0213/2270] Add MAINTAINERS entry for leon3 Signed-off-by: Fabien Chouteau Signed-off-by: Blue Swirl --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 6d864c1ceb..61f8b45cb5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -398,6 +398,12 @@ M: Blue Swirl S: Maintained F: hw/sun4u.c +Leon3 +M: Fabien Chouteau +S: Maintained +F: hw/leon3.c +F: hw/grlib* + S390 Machines ------------- S390 Virtio From 0c267217ca9985e6d118ec8368bebd382db7a099 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 8 Sep 2012 11:52:39 +0200 Subject: [PATCH 0214/2270] musicpal: Fix flash mapping The old arithmetic assumed 32 physical address bits which is no longer true for ARM since 3cc0cd61f4. Signed-off-by: Jan Kiszka Signed-off-by: Blue Swirl --- hw/musicpal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/musicpal.c b/hw/musicpal.c index ad725b5599..f305e21038 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -1583,7 +1583,7 @@ static void musicpal_init(ram_addr_t ram_size, * image is smaller than 32 MB. */ #ifdef TARGET_WORDS_BIGENDIAN - pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, NULL, + pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL, "musicpal.flash", flash_size, dinfo->bdrv, 0x10000, (flash_size + 0xffff) >> 16, @@ -1591,7 +1591,7 @@ static void musicpal_init(ram_addr_t ram_size, 2, 0x00BF, 0x236D, 0x0000, 0x0000, 0x5555, 0x2AAA, 1); #else - pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, NULL, + pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL, "musicpal.flash", flash_size, dinfo->bdrv, 0x10000, (flash_size + 0xffff) >> 16, From 62fe83318d2fc5b31f473d66326910d94c1c4907 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Fri, 10 Aug 2012 15:11:45 +0200 Subject: [PATCH 0215/2270] qemu: Use valgrind annotations to mark kvm guest memory as defined valgrind with kvm produces a big amount of false positives regarding "Conditional jump or move depends on uninitialised value(s)". This happens because the guest memory is allocated with qemu_vmalloc which boils down posix_memalign etc. This function is (correctly) considered by valgrind as returning undefined memory. Since valgrind is based on jitting code, it will not be able to see changes made by the guest to guest memory if this is done by KVM_RUN, thus keeping most of the guest memory undefined. Now lots of places in qemu will then use guest memory to change behaviour. To avoid the flood of these messages, lets declare the whole guest memory as defined. This will reduce the noise and allows us to see real problems. In the future we might want to make this conditional, since there is actually something that we can use those false positives for: These messages will point to code that depends on guest memory, so we can use these backtraces to actually make an audit that is focussed only at those code places. For normal development we dont want to see those messages, though. Signed-off-by: Christian Borntraeger Signed-off-by: Avi Kivity --- configure | 3 ++- kvm-all.c | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/configure b/configure index d97fd81709..056b3561b9 100755 --- a/configure +++ b/configure @@ -2963,11 +2963,12 @@ if compile_prog "-Werror" "" ; then fi ######################################## -# check if we have valgrind/valgrind.h +# check if we have valgrind/valgrind.h and valgrind/memcheck.h valgrind_h=no cat > $TMPC << EOF #include +#include int main(void) { return 0; } diff --git a/kvm-all.c b/kvm-all.c index 34b02c1fba..e0244b6d1e 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -39,6 +39,10 @@ #include #endif +#ifdef CONFIG_VALGRIND_H +#include +#endif + /* KVM uses PAGE_SIZE in its definition of COALESCED_MMIO_MAX */ #define PAGE_SIZE TARGET_PAGE_SIZE @@ -1719,6 +1723,9 @@ void *kvm_vmalloc(ram_addr_t size) void kvm_setup_guest_memory(void *start, size_t size) { +#ifdef CONFIG_VALGRIND_H + VALGRIND_MAKE_MEM_DEFINED(start, size); +#endif if (!kvm_has_sync_mmu()) { int ret = qemu_madvise(start, size, QEMU_MADV_DONTFORK); From b131c74a0e485b084ddaffc8214c8a19af492be7 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 20 Aug 2012 10:55:56 +0200 Subject: [PATCH 0216/2270] kvm: Clean up irqfd API No need to expose the fd-based interface, everyone will already be fine with the more handy EventNotifier variant. Rename the latter to clarify that we are still talking about irqfds here. Signed-off-by: Jan Kiszka Acked-by: Alex Williamson Signed-off-by: Avi Kivity --- hw/virtio-pci.c | 4 ++-- kvm-all.c | 18 ++++-------------- kvm-stub.c | 14 ++------------ kvm.h | 6 ++---- 4 files changed, 10 insertions(+), 32 deletions(-) diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index b3f0710f39..400f3c26b6 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -517,7 +517,7 @@ static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy, } irqfd->users++; - ret = kvm_irqchip_add_irq_notifier(kvm_state, n, irqfd->virq); + ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, irqfd->virq); if (ret < 0) { if (--irqfd->users == 0) { kvm_irqchip_release_virq(kvm_state, irqfd->virq); @@ -538,7 +538,7 @@ static void kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy, VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; int ret; - ret = kvm_irqchip_remove_irq_notifier(kvm_state, n, irqfd->virq); + ret = kvm_irqchip_remove_irqfd_notifier(kvm_state, n, irqfd->virq); assert(ret == 0); if (--irqfd->users == 0) { diff --git a/kvm-all.c b/kvm-all.c index e0244b6d1e..f96be21034 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1166,24 +1166,14 @@ static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign) } #endif /* !KVM_CAP_IRQ_ROUTING */ -int kvm_irqchip_add_irqfd(KVMState *s, int fd, int virq) +int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq) { - return kvm_irqchip_assign_irqfd(s, fd, virq, true); + return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n), virq, true); } -int kvm_irqchip_add_irq_notifier(KVMState *s, EventNotifier *n, int virq) +int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq) { - return kvm_irqchip_add_irqfd(s, event_notifier_get_fd(n), virq); -} - -int kvm_irqchip_remove_irqfd(KVMState *s, int fd, int virq) -{ - return kvm_irqchip_assign_irqfd(s, fd, virq, false); -} - -int kvm_irqchip_remove_irq_notifier(KVMState *s, EventNotifier *n, int virq) -{ - return kvm_irqchip_remove_irqfd(s, event_notifier_get_fd(n), virq); + return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n), virq, false); } static int kvm_irqchip_create(KVMState *s) diff --git a/kvm-stub.c b/kvm-stub.c index 94c9ea15b0..3c52eb5bc6 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -141,22 +141,12 @@ void kvm_irqchip_release_virq(KVMState *s, int virq) { } -int kvm_irqchip_add_irqfd(KVMState *s, int fd, int virq) +int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq) { return -ENOSYS; } -int kvm_irqchip_add_irq_notifier(KVMState *s, EventNotifier *n, int virq) -{ - return -ENOSYS; -} - -int kvm_irqchip_remove_irqfd(KVMState *s, int fd, int virq) -{ - return -ENOSYS; -} - -int kvm_irqchip_remove_irq_notifier(KVMState *s, EventNotifier *n, int virq) +int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq) { return -ENOSYS; } diff --git a/kvm.h b/kvm.h index 5b8f588813..37d1f8166a 100644 --- a/kvm.h +++ b/kvm.h @@ -272,8 +272,6 @@ int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign); int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg); void kvm_irqchip_release_virq(KVMState *s, int virq); -int kvm_irqchip_add_irqfd(KVMState *s, int fd, int virq); -int kvm_irqchip_remove_irqfd(KVMState *s, int fd, int virq); -int kvm_irqchip_add_irq_notifier(KVMState *s, EventNotifier *n, int virq); -int kvm_irqchip_remove_irq_notifier(KVMState *s, EventNotifier *n, int virq); +int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq); +int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq); #endif From 71e470886fb6092504503a5fe41092ace71c096c Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 07:33:30 +0000 Subject: [PATCH 0217/2270] target-s390x: fix style Before splitting op_helper.c and helper.c in the next patches, fix style issues. No functional changes. Replace also GCC specific __FUNCTION__ with standard __func__. Don't init static variable (cpu_s390x_init:inited) with 0. Signed-off-by: Blue Swirl Signed-off-by: Alexander Graf --- target-s390x/helper.c | 96 ++++----- target-s390x/op_helper.c | 432 ++++++++++++++++++++++----------------- 2 files changed, 294 insertions(+), 234 deletions(-) diff --git a/target-s390x/helper.c b/target-s390x/helper.c index d0a1180a83..d98e6d9dcc 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -74,7 +74,7 @@ S390CPU *cpu_s390x_init(const char *cpu_model) { S390CPU *cpu; CPUS390XState *env; - static int inited = 0; + static int inited; cpu = S390_CPU(object_new(TYPE_S390_CPU)); env = &cpu->env; @@ -91,25 +91,27 @@ S390CPU *cpu_s390x_init(const char *cpu_model) #if defined(CONFIG_USER_ONLY) -void do_interrupt (CPUS390XState *env) +void do_interrupt(CPUS390XState *env) { env->exception_index = -1; } -int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, int rw, - int mmu_idx) +int cpu_s390x_handle_mmu_fault(CPUS390XState *env, target_ulong address, + int rw, int mmu_idx) { - /* fprintf(stderr,"%s: address 0x%lx rw %d mmu_idx %d\n", - __FUNCTION__, address, rw, mmu_idx); */ + /* fprintf(stderr, "%s: address 0x%lx rw %d mmu_idx %d\n", + __func__, address, rw, mmu_idx); */ env->exception_index = EXCP_ADDR; - env->__excp_addr = address; /* FIXME: find out how this works on a real machine */ + /* FIXME: find out how this works on a real machine */ + env->__excp_addr = address; return 1; } #else /* !CONFIG_USER_ONLY */ /* Ensure to exit the TB after this call! */ -static void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilc) +static void trigger_pgm_exception(CPUS390XState *env, uint32_t code, + uint32_t ilc) { env->exception_index = EXCP_PGM; env->int_pgm_code = code; @@ -138,19 +140,20 @@ static int trans_bits(CPUS390XState *env, uint64_t mode) return bits; } -static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr, uint64_t mode) +static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr, + uint64_t mode) { int ilc = ILC_LATER_INC_2; int bits = trans_bits(env, mode) | 4; - DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __FUNCTION__, vaddr, bits); + DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits); stq_phys(env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits); trigger_pgm_exception(env, PGM_PROTECTION, ilc); } -static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr, uint32_t type, - uint64_t asc, int rw) +static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr, + uint32_t type, uint64_t asc, int rw) { int ilc = ILC_LATER; int bits = trans_bits(env, asc); @@ -160,26 +163,26 @@ static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr, uint32_t ilc = 2; } - DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __FUNCTION__, vaddr, bits); + DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits); stq_phys(env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits); trigger_pgm_exception(env, type, ilc); } -static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr, uint64_t asc, - uint64_t asce, int level, target_ulong *raddr, - int *flags, int rw) +static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr, + uint64_t asc, uint64_t asce, int level, + target_ulong *raddr, int *flags, int rw) { uint64_t offs = 0; uint64_t origin; uint64_t new_asce; - PTE_DPRINTF("%s: 0x%" PRIx64 "\n", __FUNCTION__, asce); + PTE_DPRINTF("%s: 0x%" PRIx64 "\n", __func__, asce); if (((level != _ASCE_TYPE_SEGMENT) && (asce & _REGION_ENTRY_INV)) || ((level == _ASCE_TYPE_SEGMENT) && (asce & _SEGMENT_ENTRY_INV))) { /* XXX different regions have different faults */ - DPRINTF("%s: invalid region\n", __FUNCTION__); + DPRINTF("%s: invalid region\n", __func__); trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw); return -1; } @@ -222,7 +225,7 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr, uint64_t a new_asce = ldq_phys(origin + offs); PTE_DPRINTF("%s: 0x%" PRIx64 " + 0x%" PRIx64 " => 0x%016" PRIx64 "\n", - __FUNCTION__, origin, offs, new_asce); + __func__, origin, offs, new_asce); if (level != _ASCE_TYPE_SEGMENT) { /* yet another region */ @@ -232,7 +235,7 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr, uint64_t a /* PTE */ if (new_asce & _PAGE_INVALID) { - DPRINTF("%s: PTE=0x%" PRIx64 " invalid\n", __FUNCTION__, new_asce); + DPRINTF("%s: PTE=0x%" PRIx64 " invalid\n", __func__, new_asce); trigger_page_fault(env, vaddr, PGM_PAGE_TRANS, asc, rw); return -1; } @@ -243,13 +246,14 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr, uint64_t a *raddr = new_asce & _ASCE_ORIGIN; - PTE_DPRINTF("%s: PTE=0x%" PRIx64 "\n", __FUNCTION__, new_asce); + PTE_DPRINTF("%s: PTE=0x%" PRIx64 "\n", __func__, new_asce); return 0; } -static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr, uint64_t asc, - target_ulong *raddr, int *flags, int rw) +static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr, + uint64_t asc, target_ulong *raddr, int *flags, + int rw) { uint64_t asce = 0; int level, new_level; @@ -257,15 +261,15 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr, uint64_t as switch (asc) { case PSW_ASC_PRIMARY: - PTE_DPRINTF("%s: asc=primary\n", __FUNCTION__); + PTE_DPRINTF("%s: asc=primary\n", __func__); asce = env->cregs[1]; break; case PSW_ASC_SECONDARY: - PTE_DPRINTF("%s: asc=secondary\n", __FUNCTION__); + PTE_DPRINTF("%s: asc=secondary\n", __func__); asce = env->cregs[7]; break; case PSW_ASC_HOME: - PTE_DPRINTF("%s: asc=home\n", __FUNCTION__); + PTE_DPRINTF("%s: asc=home\n", __func__); asce = env->cregs[13]; break; } @@ -276,8 +280,7 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr, uint64_t as case _ASCE_TYPE_REGION2: if (vaddr & 0xffe0000000000000ULL) { DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64 - " 0xffe0000000000000ULL\n", __FUNCTION__, - vaddr); + " 0xffe0000000000000ULL\n", __func__, vaddr); trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw); return -1; } @@ -285,8 +288,7 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr, uint64_t as case _ASCE_TYPE_REGION3: if (vaddr & 0xfffffc0000000000ULL) { DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64 - " 0xfffffc0000000000ULL\n", __FUNCTION__, - vaddr); + " 0xfffffc0000000000ULL\n", __func__, vaddr); trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw); return -1; } @@ -294,8 +296,7 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr, uint64_t as case _ASCE_TYPE_SEGMENT: if (vaddr & 0xffffffff80000000ULL) { DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64 - " 0xffffffff80000000ULL\n", __FUNCTION__, - vaddr); + " 0xffffffff80000000ULL\n", __func__, vaddr); trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw); return -1; } @@ -358,7 +359,7 @@ int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc, break; } -out: + out: /* Convert real address -> absolute address */ if (*raddr < 0x2000) { *raddr = *raddr + env->psa; @@ -378,18 +379,18 @@ out: return r; } -int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong _vaddr, int rw, - int mmu_idx) +int cpu_s390x_handle_mmu_fault(CPUS390XState *env, target_ulong orig_vaddr, + int rw, int mmu_idx) { uint64_t asc = env->psw.mask & PSW_MASK_ASC; target_ulong vaddr, raddr; int prot; DPRINTF("%s: address 0x%" PRIx64 " rw %d mmu_idx %d\n", - __FUNCTION__, _vaddr, rw, mmu_idx); + __func__, _vaddr, rw, mmu_idx); - _vaddr &= TARGET_PAGE_MASK; - vaddr = _vaddr; + orig_vaddr &= TARGET_PAGE_MASK; + vaddr = orig_vaddr; /* 31-Bit mode */ if (!(env->psw.mask & PSW_MASK_64)) { @@ -403,22 +404,23 @@ int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong _vaddr, int rw, /* check out of RAM access */ if (raddr > (ram_size + virtio_size)) { - DPRINTF("%s: aaddr %" PRIx64 " > ram_size %" PRIx64 "\n", __FUNCTION__, + DPRINTF("%s: aaddr %" PRIx64 " > ram_size %" PRIx64 "\n", __func__, (uint64_t)aaddr, (uint64_t)ram_size); trigger_pgm_exception(env, PGM_ADDRESSING, ILC_LATER); return 1; } - DPRINTF("%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x)\n", __FUNCTION__, + DPRINTF("%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x)\n", __func__, (uint64_t)vaddr, (uint64_t)raddr, prot); - tlb_set_page(env, _vaddr, raddr, prot, + tlb_set_page(env, orig_vaddr, raddr, prot, mmu_idx, TARGET_PAGE_SIZE); return 0; } -target_phys_addr_t cpu_get_phys_page_debug(CPUS390XState *env, target_ulong vaddr) +target_phys_addr_t cpu_get_phys_page_debug(CPUS390XState *env, + target_ulong vaddr) { target_ulong raddr; int prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; @@ -509,7 +511,7 @@ static void do_program_interrupt(CPUS390XState *env) break; } - qemu_log("%s: code=0x%x ilc=%d\n", __FUNCTION__, env->int_pgm_code, ilc); + qemu_log("%s: code=0x%x ilc=%d\n", __func__, env->int_pgm_code, ilc); lowcore = cpu_physical_memory_map(env->psa, &len, 1); @@ -522,7 +524,7 @@ static void do_program_interrupt(CPUS390XState *env) cpu_physical_memory_unmap(lowcore, len, 1, len); - DPRINTF("%s: %x %x %" PRIx64 " %" PRIx64 "\n", __FUNCTION__, + DPRINTF("%s: %x %x %" PRIx64 " %" PRIx64 "\n", __func__, env->int_pgm_code, ilc, env->psw.mask, env->psw.addr); @@ -565,15 +567,15 @@ static void do_ext_interrupt(CPUS390XState *env) env->pending_int &= ~INTERRUPT_EXT; } - DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __FUNCTION__, + DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__, env->psw.mask, env->psw.addr); load_psw(env, mask, addr); } -void do_interrupt (CPUS390XState *env) +void do_interrupt(CPUS390XState *env) { - qemu_log("%s: %d at pc=%" PRIx64 "\n", __FUNCTION__, env->exception_index, + qemu_log("%s: %d at pc=%" PRIx64 "\n", __func__, env->exception_index, env->psw.addr); s390_add_running_cpu(env); diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c index abc35ddd7b..195e93ed5e 100644 --- a/target-s390x/op_helper.c +++ b/target-s390x/op_helper.c @@ -31,13 +31,13 @@ #include #endif -#if !defined (CONFIG_USER_ONLY) +#if !defined(CONFIG_USER_ONLY) #include "sysemu.h" #endif /*****************************************************************************/ /* Softmmu support */ -#if !defined (CONFIG_USER_ONLY) +#if !defined(CONFIG_USER_ONLY) #include "softmmu_exec.h" #define MMUSUFFIX _mmu @@ -95,7 +95,7 @@ void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx, /* raise an exception */ void HELPER(exception)(uint32_t excp) { - HELPER_LOG("%s: exception %d\n", __FUNCTION__, excp); + HELPER_LOG("%s: exception %d\n", __func__, excp); env->exception_index = excp; cpu_loop_exit(env); } @@ -164,7 +164,7 @@ uint32_t HELPER(nc)(uint32_t l, uint64_t dest, uint64_t src) uint32_t cc = 0; HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", - __FUNCTION__, l, dest, src); + __func__, l, dest, src); for (i = 0; i <= l; i++) { x = ldub(dest + i) & ldub(src + i); if (x) { @@ -183,7 +183,7 @@ uint32_t HELPER(xc)(uint32_t l, uint64_t dest, uint64_t src) uint32_t cc = 0; HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", - __FUNCTION__, l, dest, src); + __func__, l, dest, src); #ifndef CONFIG_USER_ONLY /* xor with itself is the same as memset(0) */ @@ -217,7 +217,7 @@ uint32_t HELPER(oc)(uint32_t l, uint64_t dest, uint64_t src) uint32_t cc = 0; HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", - __FUNCTION__, l, dest, src); + __func__, l, dest, src); for (i = 0; i <= l; i++) { x = ldub(dest + i) | ldub(src + i); if (x) { @@ -236,7 +236,7 @@ void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src) uint32_t l_64 = (l + 1) / 8; HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", - __FUNCTION__, l, dest, src); + __func__, l, dest, src); #ifndef CONFIG_USER_ONLY if ((l > 32) && @@ -278,10 +278,11 @@ void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src) uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2) { int i; - unsigned char x,y; + unsigned char x, y; uint32_t cc; + HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n", - __FUNCTION__, l, s1, s2); + __func__, l, s1, s2); for (i = 0; i <= l; i++) { x = ldub(s1 + i); y = ldub(s2 + i); @@ -295,7 +296,7 @@ uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2) } } cc = 0; -done: + done: HELPER_LOG("\n"); return cc; } @@ -303,9 +304,10 @@ done: /* compare logical under mask */ uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr) { - uint8_t r,d; + uint8_t r, d; uint32_t cc; - HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __FUNCTION__, r1, + + HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __func__, r1, mask, addr); cc = 0; while (mask) { @@ -313,7 +315,7 @@ uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr) d = ldub(addr); r = (r1 & 0xff000000UL) >> 24; HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d, - addr); + addr); if (r < d) { cc = 1; break; @@ -334,7 +336,8 @@ uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr) void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr) { uint8_t r; - HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%lx\n", __FUNCTION__, r1, mask, + + HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%lx\n", __func__, r1, mask, addr); while (mask) { if (mask & 8) { @@ -355,6 +358,7 @@ void HELPER(mlg)(uint32_t r1, uint64_t v2) #if HOST_LONG_BITS == 64 && defined(__GNUC__) /* assuming 64-bit hosts have __uint128_t */ __uint128_t res = (__uint128_t)env->regs[r1 + 1]; + res *= (__uint128_t)v2; env->regs[r1] = (uint64_t)(res >> 64); env->regs[r1 + 1] = (uint64_t)res; @@ -370,18 +374,18 @@ void HELPER(dlg)(uint32_t r1, uint64_t v2) if (!env->regs[r1]) { /* 64 -> 64/64 case */ - env->regs[r1] = env->regs[r1+1] % divisor; - env->regs[r1+1] = env->regs[r1+1] / divisor; + env->regs[r1] = env->regs[r1 + 1] % divisor; + env->regs[r1 + 1] = env->regs[r1 + 1] / divisor; return; } else { - #if HOST_LONG_BITS == 64 && defined(__GNUC__) /* assuming 64-bit hosts have __uint128_t */ __uint128_t dividend = (((__uint128_t)env->regs[r1]) << 64) | - (env->regs[r1+1]); + (env->regs[r1 + 1]); __uint128_t quotient = dividend / divisor; - env->regs[r1+1] = quotient; __uint128_t remainder = dividend % divisor; + + env->regs[r1 + 1] = quotient; env->regs[r1] = remainder; #else /* 32-bit hosts would need special wrapper functionality - just abort if @@ -431,7 +435,7 @@ uint32_t HELPER(srst)(uint32_t c, uint32_t r1, uint32_t r2) uint64_t str = get_address_31fix(r2); uint64_t end = get_address_31fix(r1); - HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __FUNCTION__, + HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __func__, c, env->regs[r1], env->regs[r2]); for (i = str; i != end; i++) { @@ -452,11 +456,12 @@ uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2) uint64_t s2 = get_address_31fix(r2); uint8_t v1, v2; uint32_t cc; + c = c & 0xff; #ifdef CONFIG_USER_ONLY if (!c) { HELPER_LOG("%s: comparing '%s' and '%s'\n", - __FUNCTION__, (char*)g2h(s1), (char*)g2h(s2)); + __func__, (char *)g2h(s1), (char *)g2h(s2)); } #endif for (;;) { @@ -501,10 +506,11 @@ void HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2) uint64_t dest = get_address_31fix(r1); uint64_t src = get_address_31fix(r2); uint8_t v; + c = c & 0xff; #ifdef CONFIG_USER_ONLY if (!c) { - HELPER_LOG("%s: copy '%s' to 0x%lx\n", __FUNCTION__, (char*)g2h(src), + HELPER_LOG("%s: copy '%s' to 0x%lx\n", __func__, (char *)g2h(src), dest); } #endif @@ -526,6 +532,7 @@ uint32_t HELPER(csg)(uint32_t r1, uint64_t a2, uint32_t r3) /* FIXME: locking? */ uint32_t cc; uint64_t v2 = ldq(a2); + if (env->regs[r1] == v2) { cc = 0; stq(a2, env->regs[r3]); @@ -564,8 +571,9 @@ uint32_t HELPER(cs)(uint32_t r1, uint64_t a2, uint32_t r3) { /* FIXME: locking? */ uint32_t cc; - HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __FUNCTION__, r1, a2, r3); uint32_t v2 = ldl(a2); + + HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __func__, r1, a2, r3); if (((uint32_t)env->regs[r1]) == v2) { cc = 0; stl(a2, (uint32_t)env->regs[r3]); @@ -612,14 +620,16 @@ static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask) it does not change the program counter in other words: tricky... currently implemented by interpreting the cases it is most commonly used in - */ +*/ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret) { uint16_t insn = lduw_code(addr); - HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __FUNCTION__, v1, addr, - insn); + + HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __func__, v1, addr, + insn); if ((insn & 0xf0ff) == 0xd000) { uint32_t l, insn2, b1, b2, d1, d2; + l = v1 & 0xff; insn2 = ldl_code(addr + 2); b1 = (insn2 >> 28) & 0xf; @@ -645,13 +655,14 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret) } } else if ((insn & 0xff00) == 0x0a00) { /* supervisor call */ - HELPER_LOG("%s: svc %ld via execute\n", __FUNCTION__, (insn|v1) & 0xff); + HELPER_LOG("%s: svc %ld via execute\n", __func__, (insn | v1) & 0xff); env->psw.addr = ret - 4; - env->int_svc_code = (insn|v1) & 0xff; + env->int_svc_code = (insn | v1) & 0xff; env->int_svc_ilc = 4; helper_exception(EXCP_SVC); } else if ((insn & 0xff00) == 0xbf00) { uint32_t insn2, r1, r3, b2, d2; + insn2 = ldl_code(addr + 2); r1 = (insn2 >> 20) & 0xf; r3 = (insn2 >> 16) & 0xf; @@ -659,7 +670,7 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret) d2 = insn2 & 0xfff; cc = helper_icm(r1, get_address(0, b2, d2), r3); } else { -abort: + abort: cpu_abort(env, "EXECUTE on instruction prefix 0x%x not implemented\n", insn); } @@ -689,7 +700,7 @@ int32_t HELPER(nabs_i32)(int32_t val) /* absolute value 64-bit */ uint64_t HELPER(abs_i64)(int64_t val) { - HELPER_LOG("%s: val 0x%" PRIx64 "\n", __FUNCTION__, val); + HELPER_LOG("%s: val 0x%" PRIx64 "\n", __func__, val); if (val < 0) { return -val; @@ -774,9 +785,9 @@ void HELPER(ipm)(uint32_t cc, uint32_t r1) uint64_t r = env->regs[r1]; r &= 0xffffffff00ffffffULL; - r |= (cc << 28) | ( (env->psw.mask >> 40) & 0xf ); + r |= (cc << 28) | ((env->psw.mask >> 40) & 0xf); env->regs[r1] = r; - HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __FUNCTION__, + HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __func__, cc, env->psw.mask, r); } @@ -908,7 +919,7 @@ uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3) uint64_t srclen = env->regs[r3 + 1]; uint64_t src = get_address_31fix(r3); uint8_t pad = a2 & 0xff; - uint8_t v1 = 0,v2 = 0; + uint8_t v1 = 0, v2 = 0; uint32_t cc = 0; if (!(destlen || srclen)) { @@ -1036,7 +1047,7 @@ static uint32_t set_cc_nz_f128(float128 v) /* convert 32-bit int to 64-bit float */ void HELPER(cdfbr)(uint32_t f1, int32_t v2) { - HELPER_LOG("%s: converting %d to f%d\n", __FUNCTION__, v2, f1); + HELPER_LOG("%s: converting %d to f%d\n", __func__, v2, f1); env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status); } @@ -1044,6 +1055,7 @@ void HELPER(cdfbr)(uint32_t f1, int32_t v2) void HELPER(cxfbr)(uint32_t f1, int32_t v2) { CPU_QuadU v1; + v1.q = int32_to_float128(v2, &env->fpu_status); env->fregs[f1].ll = v1.ll.upper; env->fregs[f1 + 2].ll = v1.ll.lower; @@ -1052,14 +1064,14 @@ void HELPER(cxfbr)(uint32_t f1, int32_t v2) /* convert 64-bit int to 32-bit float */ void HELPER(cegbr)(uint32_t f1, int64_t v2) { - HELPER_LOG("%s: converting %ld to f%d\n", __FUNCTION__, v2, f1); + HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1); env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status); } /* convert 64-bit int to 64-bit float */ void HELPER(cdgbr)(uint32_t f1, int64_t v2) { - HELPER_LOG("%s: converting %ld to f%d\n", __FUNCTION__, v2, f1); + HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1); env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status); } @@ -1067,8 +1079,9 @@ void HELPER(cdgbr)(uint32_t f1, int64_t v2) void HELPER(cxgbr)(uint32_t f1, int64_t v2) { CPU_QuadU x1; + x1.q = int64_to_float128(v2, &env->fpu_status); - HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __FUNCTION__, v2, + HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __func__, v2, x1.ll.upper, x1.ll.lower); env->fregs[f1].ll = x1.ll.upper; env->fregs[f1 + 2].ll = x1.ll.lower; @@ -1078,7 +1091,7 @@ void HELPER(cxgbr)(uint32_t f1, int64_t v2) void HELPER(cefbr)(uint32_t f1, int32_t v2) { env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status); - HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __FUNCTION__, v2, + HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __func__, v2, env->fregs[f1].l.upper, f1); } @@ -1088,7 +1101,7 @@ uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2) env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper, env->fregs[f2].l.upper, &env->fpu_status); - HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __FUNCTION__, + HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__, env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1); return set_cc_nz_f32(env->fregs[f1].l.upper); @@ -1099,7 +1112,7 @@ uint32_t HELPER(adbr)(uint32_t f1, uint32_t f2) { env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d, &env->fpu_status); - HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __FUNCTION__, + HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __func__, env->fregs[f2].d, env->fregs[f1].d, f1); return set_cc_nz_f64(env->fregs[f1].d); @@ -1111,7 +1124,7 @@ uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2) env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper, env->fregs[f2].l.upper, &env->fpu_status); - HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __FUNCTION__, + HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__, env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1); return set_cc_nz_f32(env->fregs[f1].l.upper); @@ -1123,7 +1136,7 @@ uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2) env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d, &env->fpu_status); HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n", - __FUNCTION__, env->fregs[f2].d, env->fregs[f1].d, f1); + __func__, env->fregs[f2].d, env->fregs[f1].d, f1); return set_cc_nz_f64(env->fregs[f1].d); } @@ -1140,12 +1153,13 @@ void HELPER(debr)(uint32_t f1, uint32_t f2) void HELPER(dxbr)(uint32_t f1, uint32_t f2) { CPU_QuadU v1; + CPU_QuadU v2; + CPU_QuadU res; + v1.ll.upper = env->fregs[f1].ll; v1.ll.lower = env->fregs[f1 + 2].ll; - CPU_QuadU v2; v2.ll.upper = env->fregs[f2].ll; v2.ll.lower = env->fregs[f2 + 2].ll; - CPU_QuadU res; res.q = float128_div(v1.q, v2.q, &env->fpu_status); env->fregs[f1].ll = res.ll.upper; env->fregs[f1 + 2].ll = res.ll.lower; @@ -1162,12 +1176,13 @@ void HELPER(mdbr)(uint32_t f1, uint32_t f2) void HELPER(mxbr)(uint32_t f1, uint32_t f2) { CPU_QuadU v1; + CPU_QuadU v2; + CPU_QuadU res; + v1.ll.upper = env->fregs[f1].ll; v1.ll.lower = env->fregs[f1 + 2].ll; - CPU_QuadU v2; v2.ll.upper = env->fregs[f2].ll; v2.ll.lower = env->fregs[f2 + 2].ll; - CPU_QuadU res; res.q = float128_mul(v1.q, v2.q, &env->fpu_status); env->fregs[f1].ll = res.ll.upper; env->fregs[f1 + 2].ll = res.ll.lower; @@ -1184,16 +1199,18 @@ void HELPER(ldebr)(uint32_t r1, uint32_t r2) void HELPER(ldxbr)(uint32_t f1, uint32_t f2) { CPU_QuadU x2; + x2.ll.upper = env->fregs[f2].ll; x2.ll.lower = env->fregs[f2 + 2].ll; env->fregs[f1].d = float128_to_float64(x2.q, &env->fpu_status); - HELPER_LOG("%s: to 0x%ld\n", __FUNCTION__, env->fregs[f1].d); + HELPER_LOG("%s: to 0x%ld\n", __func__, env->fregs[f1].d); } /* convert 64-bit float to 128-bit float */ void HELPER(lxdbr)(uint32_t f1, uint32_t f2) { CPU_QuadU res; + res.q = float64_to_float128(env->fregs[f2].d, &env->fpu_status); env->fregs[f1].ll = res.ll.upper; env->fregs[f1 + 2].ll = res.ll.lower; @@ -1203,6 +1220,7 @@ void HELPER(lxdbr)(uint32_t f1, uint32_t f2) void HELPER(ledbr)(uint32_t f1, uint32_t f2) { float64 d2 = env->fregs[f2].d; + env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status); } @@ -1210,10 +1228,11 @@ void HELPER(ledbr)(uint32_t f1, uint32_t f2) void HELPER(lexbr)(uint32_t f1, uint32_t f2) { CPU_QuadU x2; + x2.ll.upper = env->fregs[f2].ll; x2.ll.lower = env->fregs[f2 + 2].ll; env->fregs[f1].l.upper = float128_to_float32(x2.q, &env->fpu_status); - HELPER_LOG("%s: to 0x%d\n", __FUNCTION__, env->fregs[f1].l.upper); + HELPER_LOG("%s: to 0x%d\n", __func__, env->fregs[f1].l.upper); } /* absolute value of 32-bit float */ @@ -1221,6 +1240,7 @@ uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2) { float32 v1; float32 v2 = env->fregs[f2].d; + v1 = float32_abs(v2); env->fregs[f1].d = v1; return set_cc_nz_f32(v1); @@ -1231,6 +1251,7 @@ uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2) { float64 v1; float64 v2 = env->fregs[f2].d; + v1 = float64_abs(v2); env->fregs[f1].d = v1; return set_cc_nz_f64(v1); @@ -1241,6 +1262,7 @@ uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2) { CPU_QuadU v1; CPU_QuadU v2; + v2.ll.upper = env->fregs[f2].ll; v2.ll.lower = env->fregs[f2 + 2].ll; v1.q = float128_abs(v2.q); @@ -1267,6 +1289,7 @@ uint32_t HELPER(ltebr)(uint32_t f1, uint32_t f2) uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2) { CPU_QuadU x; + x.ll.upper = env->fregs[f2].ll; x.ll.lower = env->fregs[f2 + 2].ll; env->fregs[f1].ll = x.ll.upper; @@ -1294,6 +1317,7 @@ uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2) uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2) { CPU_QuadU x1, x2; + x2.ll.upper = env->fregs[f2].ll; x2.ll.lower = env->fregs[f2 + 2].ll; x1.q = float128_chs(x2.q); @@ -1307,8 +1331,9 @@ void HELPER(aeb)(uint32_t f1, uint32_t val) { float32 v1 = env->fregs[f1].l.upper; CPU_FloatU v2; + v2.l = val; - HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __FUNCTION__, + HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __func__, v1, f1, v2.f); env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status); } @@ -1318,8 +1343,9 @@ void HELPER(deb)(uint32_t f1, uint32_t val) { float32 v1 = env->fregs[f1].l.upper; CPU_FloatU v2; + v2.l = val; - HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __FUNCTION__, + HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __func__, v1, f1, v2.f); env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status); } @@ -1329,8 +1355,9 @@ void HELPER(meeb)(uint32_t f1, uint32_t val) { float32 v1 = env->fregs[f1].l.upper; CPU_FloatU v2; + v2.l = val; - HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __FUNCTION__, + HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __func__, v1, f1, v2.f); env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status); } @@ -1340,7 +1367,8 @@ uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2) { float32 v1 = env->fregs[f1].l.upper; float32 v2 = env->fregs[f2].l.upper; - HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __FUNCTION__, + + HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __func__, v1, f1, v2); return set_cc_f32(v1, v2); } @@ -1350,7 +1378,8 @@ uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2) { float64 v1 = env->fregs[f1].d; float64 v2 = env->fregs[f2].d; - HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __FUNCTION__, + + HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __func__, v1, f1, v2); return set_cc_f64(v1, v2); } @@ -1359,14 +1388,15 @@ uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2) uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2) { CPU_QuadU v1; + CPU_QuadU v2; + v1.ll.upper = env->fregs[f1].ll; v1.ll.lower = env->fregs[f1 + 2].ll; - CPU_QuadU v2; v2.ll.upper = env->fregs[f2].ll; v2.ll.lower = env->fregs[f2 + 2].ll; return float_comp_to_cc(float128_compare_quiet(v1.q, v2.q, - &env->fpu_status)); + &env->fpu_status)); } /* 64-bit FP compare RM */ @@ -1374,8 +1404,9 @@ uint32_t HELPER(cdb)(uint32_t f1, uint64_t a2) { float64 v1 = env->fregs[f1].d; CPU_DoubleU v2; + v2.ll = ldq(a2); - HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __FUNCTION__, v1, + HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__, v1, f1, v2.d); return set_cc_f64(v1, v2.d); } @@ -1385,8 +1416,9 @@ uint32_t HELPER(adb)(uint32_t f1, uint64_t a2) { float64 v1 = env->fregs[f1].d; CPU_DoubleU v2; + v2.ll = ldq(a2); - HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __FUNCTION__, + HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __func__, v1, f1, v2.d); env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status); return set_cc_nz_f64(v1); @@ -1397,6 +1429,7 @@ void HELPER(seb)(uint32_t f1, uint32_t val) { float32 v1 = env->fregs[f1].l.upper; CPU_FloatU v2; + v2.l = val; env->fregs[f1].l.upper = float32_sub(v1, v2.f, &env->fpu_status); } @@ -1406,6 +1439,7 @@ uint32_t HELPER(sdb)(uint32_t f1, uint64_t a2) { float64 v1 = env->fregs[f1].d; CPU_DoubleU v2; + v2.ll = ldq(a2); env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status); return set_cc_nz_f64(v1); @@ -1416,8 +1450,9 @@ void HELPER(mdb)(uint32_t f1, uint64_t a2) { float64 v1 = env->fregs[f1].d; CPU_DoubleU v2; + v2.ll = ldq(a2); - HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __FUNCTION__, + HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __func__, v1, f1, v2.d); env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status); } @@ -1427,8 +1462,9 @@ void HELPER(ddb)(uint32_t f1, uint64_t a2) { float64 v1 = env->fregs[f1].d; CPU_DoubleU v2; + v2.ll = ldq(a2); - HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __FUNCTION__, + HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __func__, v1, f1, v2.d); env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status); } @@ -1464,6 +1500,7 @@ static void set_round_mode(int m3) uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3) { float32 v2 = env->fregs[f2].l.upper; + set_round_mode(m3); env->regs[r1] = float32_to_int64(v2, &env->fpu_status); return set_cc_nz_f32(v2); @@ -1473,6 +1510,7 @@ uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3) uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3) { float64 v2 = env->fregs[f2].d; + set_round_mode(m3); env->regs[r1] = float64_to_int64(v2, &env->fpu_status); return set_cc_nz_f64(v2); @@ -1482,6 +1520,7 @@ uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3) uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3) { CPU_QuadU v2; + v2.ll.upper = env->fregs[f2].ll; v2.ll.lower = env->fregs[f2 + 2].ll; set_round_mode(m3); @@ -1501,9 +1540,10 @@ uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3) uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3) { float32 v2 = env->fregs[f2].l.upper; + set_round_mode(m3); env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | - float32_to_int32(v2, &env->fpu_status); + float32_to_int32(v2, &env->fpu_status); return set_cc_nz_f32(v2); } @@ -1511,9 +1551,10 @@ uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3) uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3) { float64 v2 = env->fregs[f2].d; + set_round_mode(m3); env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | - float64_to_int32(v2, &env->fpu_status); + float64_to_int32(v2, &env->fpu_status); return set_cc_nz_f64(v2); } @@ -1521,10 +1562,11 @@ uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3) uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3) { CPU_QuadU v2; + v2.ll.upper = env->fregs[f2].ll; v2.ll.lower = env->fregs[f2 + 2].ll; env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | - float128_to_int32(v2.q, &env->fpu_status); + float128_to_int32(v2.q, &env->fpu_status); return set_cc_nz_f128(v2.q); } @@ -1544,6 +1586,7 @@ void HELPER(lzdr)(uint32_t f1) void HELPER(lzxr)(uint32_t f1) { CPU_QuadU x; + x.q = float64_to_float128(float64_zero, &env->fpu_status); env->fregs[f1].ll = x.ll.upper; env->fregs[f1 + 1].ll = x.ll.lower; @@ -1553,12 +1596,13 @@ void HELPER(lzxr)(uint32_t f1) uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2) { CPU_QuadU v1; + CPU_QuadU v2; + CPU_QuadU res; + v1.ll.upper = env->fregs[f1].ll; v1.ll.lower = env->fregs[f1 + 2].ll; - CPU_QuadU v2; v2.ll.upper = env->fregs[f2].ll; v2.ll.lower = env->fregs[f2 + 2].ll; - CPU_QuadU res; res.q = float128_sub(v1.q, v2.q, &env->fpu_status); env->fregs[f1].ll = res.ll.upper; env->fregs[f1 + 2].ll = res.ll.lower; @@ -1569,12 +1613,13 @@ uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2) uint32_t HELPER(axbr)(uint32_t f1, uint32_t f2) { CPU_QuadU v1; + CPU_QuadU v2; + CPU_QuadU res; + v1.ll.upper = env->fregs[f1].ll; v1.ll.lower = env->fregs[f1 + 2].ll; - CPU_QuadU v2; v2.ll.upper = env->fregs[f2].ll; v2.ll.lower = env->fregs[f2 + 2].ll; - CPU_QuadU res; res.q = float128_add(v1.q, v2.q, &env->fpu_status); env->fregs[f1].ll = res.ll.upper; env->fregs[f1 + 2].ll = res.ll.lower; @@ -1599,8 +1644,9 @@ void HELPER(ddbr)(uint32_t f1, uint32_t f2) /* 64-bit FP multiply and add RM */ void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3) { - HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __FUNCTION__, f1, a2, f3); CPU_DoubleU v2; + + HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __func__, f1, a2, f3); v2.ll = ldq(a2); env->fregs[f1].d = float64_add(env->fregs[f1].d, float64_mul(v2.d, env->fregs[f3].d, @@ -1611,7 +1657,7 @@ void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3) /* 64-bit FP multiply and add RR */ void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2) { - HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __FUNCTION__, f1, f2, f3); + HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3); env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d, env->fregs[f3].d, &env->fpu_status), @@ -1621,7 +1667,7 @@ void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2) /* 64-bit FP multiply and subtract RR */ void HELPER(msdbr)(uint32_t f1, uint32_t f3, uint32_t f2) { - HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __FUNCTION__, f1, f2, f3); + HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3); env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d, env->fregs[f3].d, &env->fpu_status), @@ -1642,6 +1688,7 @@ void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2) void HELPER(ldeb)(uint32_t f1, uint64_t a2) { uint32_t v2; + v2 = ldl(a2); env->fregs[f1].d = float32_to_float64(v2, &env->fpu_status); @@ -1651,8 +1698,9 @@ void HELPER(ldeb)(uint32_t f1, uint64_t a2) void HELPER(lxdb)(uint32_t f1, uint64_t a2) { CPU_DoubleU v2; - v2.ll = ldq(a2); CPU_QuadU v1; + + v2.ll = ldq(a2); v1.q = float64_to_float128(v2.d, &env->fpu_status); env->fregs[f1].ll = v1.ll.upper; env->fregs[f1 + 2].ll = v1.ll.lower; @@ -1665,7 +1713,7 @@ uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2) int neg = float32_is_neg(v1); uint32_t cc = 0; - HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __FUNCTION__, (long)v1, m2, neg); + HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, (long)v1, m2, neg); if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) || (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) || (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || @@ -1687,7 +1735,7 @@ uint32_t HELPER(tcdb)(uint32_t f1, uint64_t m2) int neg = float64_is_neg(v1); uint32_t cc = 0; - HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __FUNCTION__, v1, m2, neg); + HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, v1, m2, neg); if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) || (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) || (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || @@ -1706,10 +1754,12 @@ uint32_t HELPER(tcxb)(uint32_t f1, uint64_t m2) { CPU_QuadU v1; uint32_t cc = 0; + int neg; + v1.ll.upper = env->fregs[f1].ll; v1.ll.lower = env->fregs[f1 + 2].ll; - int neg = float128_is_neg(v1.q); + neg = float128_is_neg(v1.q); if ((float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) || (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) || (float128_is_any_nan(v1.q) && (m2 & (1 << (3-neg)))) || @@ -1787,7 +1837,7 @@ void HELPER(cksm)(uint32_t r1, uint32_t r2) /* store result */ env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | - ((uint32_t)cksm + (cksm >> 32)); + ((uint32_t)cksm + (cksm >> 32)); } static inline uint32_t cc_calc_ltgt_32(CPUS390XState *env, int32_t src, @@ -1848,10 +1898,12 @@ static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src, } } -static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, uint32_t mask) +static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, + uint32_t mask) { - HELPER_LOG("%s: val 0x%x mask 0x%x\n", __FUNCTION__, val, mask); uint16_t r = val & mask; + + HELPER_LOG("%s: val 0x%x mask 0x%x\n", __func__, val, mask); if (r == 0 || mask == 0) { return 0; } else if (r == mask) { @@ -1862,10 +1914,12 @@ static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, uint32_t } /* set condition code for test under mask */ -static inline uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val, uint32_t mask) +static inline uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val, + uint32_t mask) { uint16_t r = val & mask; - HELPER_LOG("%s: val 0x%lx mask 0x%x r 0x%x\n", __FUNCTION__, val, mask, r); + + HELPER_LOG("%s: val 0x%lx mask 0x%x r 0x%x\n", __func__, val, mask, r); if (r == 0 || mask == 0) { return 0; } else if (r == mask) { @@ -1888,8 +1942,8 @@ static inline uint32_t cc_calc_nz(CPUS390XState *env, uint64_t dst) return !!dst; } -static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1, int64_t a2, - int64_t ar) +static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1, + int64_t a2, int64_t ar) { if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) { return 3; /* overflow */ @@ -1904,8 +1958,8 @@ static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1, int64_t a2 } } -static inline uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1, uint64_t a2, - uint64_t ar) +static inline uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1, + uint64_t a2, uint64_t ar) { if (ar == 0) { if (a1) { @@ -1915,15 +1969,15 @@ static inline uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1, uint64_t } } else { if (ar < a1 || ar < a2) { - return 3; + return 3; } else { - return 1; + return 1; } } } -static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1, int64_t a2, - int64_t ar) +static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1, + int64_t a2, int64_t ar) { if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) { return 3; /* overflow */ @@ -1938,8 +1992,8 @@ static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1, int64_t a2 } } -static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1, uint64_t a2, - uint64_t ar) +static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1, + uint64_t a2, uint64_t ar) { if (ar == 0) { return 2; @@ -1982,8 +2036,8 @@ static inline uint32_t cc_calc_comp_64(CPUS390XState *env, int64_t dst) } -static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1, int32_t a2, - int32_t ar) +static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1, + int32_t a2, int32_t ar) { if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) { return 3; /* overflow */ @@ -1998,26 +2052,26 @@ static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1, int32_t a2 } } -static inline uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1, uint32_t a2, - uint32_t ar) +static inline uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1, + uint32_t a2, uint32_t ar) { if (ar == 0) { if (a1) { - return 2; + return 2; } else { - return 0; + return 0; } } else { if (ar < a1 || ar < a2) { - return 3; + return 3; } else { - return 1; + return 1; } } } -static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1, int32_t a2, - int32_t ar) +static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1, + int32_t a2, int32_t ar) { if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) { return 3; /* overflow */ @@ -2032,8 +2086,8 @@ static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1, int32_t a2 } } -static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1, uint32_t a2, - uint32_t ar) +static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1, + uint32_t a2, uint32_t ar) { if (ar == 0) { return 2; @@ -2076,11 +2130,12 @@ static inline uint32_t cc_calc_comp_32(CPUS390XState *env, int32_t dst) } /* calculate condition code for insert character under mask insn */ -static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask, uint32_t val) +static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask, + uint32_t val) { - HELPER_LOG("%s: mask 0x%x val %d\n", __FUNCTION__, mask, val); uint32_t cc; + HELPER_LOG("%s: mask 0x%x val %d\n", __func__, mask, val); if (mask == 0xf) { if (!val) { return 0; @@ -2107,7 +2162,8 @@ static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask, uint32_ return cc; } -static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src, uint64_t shift) +static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src, + uint64_t shift) { uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift); uint64_t match, r; @@ -2136,8 +2192,8 @@ static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src, uint64_t s } -static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, - uint64_t dst, uint64_t vr) +static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, + uint64_t src, uint64_t dst, uint64_t vr) { uint32_t r = 0; @@ -2244,7 +2300,7 @@ static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t s cpu_abort(env, "Unknown CC operation: %s\n", cc_name(cc_op)); } - HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __FUNCTION__, + HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __func__, cc_name(cc_op), src, dst, vr, r); return r; } @@ -2334,6 +2390,7 @@ void HELPER(tr)(uint32_t len, uint64_t array, uint64_t trans) for (i = 0; i <= len; i++) { uint8_t byte = ldub(array + i); uint8_t new_byte = ldub(trans + byte); + stb(array + i, new_byte); } } @@ -2363,7 +2420,7 @@ static void program_interrupt(CPUS390XState *env, uint32_t code, int ilc) } /* - * ret < 0 indicates program check, ret = 0,1,2,3 -> cc + * ret < 0 indicates program check, ret = 0, 1, 2, 3 -> cc */ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code) { @@ -2382,24 +2439,24 @@ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code) return -PGM_SPECIFICATION; } - switch(code) { - case SCLP_CMDW_READ_SCP_INFO: - case SCLP_CMDW_READ_SCP_INFO_FORCED: - while ((ram_size >> (20 + shift)) > 65535) { - shift++; - } - stw_phys(sccb + SCP_MEM_CODE, ram_size >> (20 + shift)); - stb_phys(sccb + SCP_INCREMENT, 1 << shift); - stw_phys(sccb + SCP_RESPONSE_CODE, 0x10); + switch (code) { + case SCLP_CMDW_READ_SCP_INFO: + case SCLP_CMDW_READ_SCP_INFO_FORCED: + while ((ram_size >> (20 + shift)) > 65535) { + shift++; + } + stw_phys(sccb + SCP_MEM_CODE, ram_size >> (20 + shift)); + stb_phys(sccb + SCP_INCREMENT, 1 << shift); + stw_phys(sccb + SCP_RESPONSE_CODE, 0x10); - s390_sclp_extint(sccb & ~3); - break; - default: + s390_sclp_extint(sccb & ~3); + break; + default: #ifdef DEBUG_HELPER - printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code); + printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code); #endif - r = 3; - break; + r = 3; + break; } return r; @@ -2479,7 +2536,7 @@ static inline uint64_t clock_value(CPUS390XState *env) uint64_t time; time = env->tod_offset + - time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime); + time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime); return time; } @@ -2503,7 +2560,6 @@ uint32_t HELPER(stcke)(uint64_t a1) /* XXX programmable fields */ stw(a1 + 17, 0); - return 0; } @@ -2584,7 +2640,7 @@ uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1) ebcdic_put(sysib.model, "QEMU ", 16); ebcdic_put(sysib.sequence, "QEMU ", 16); ebcdic_put(sysib.plant, "QEMU", 4); - cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1); + cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); } else if ((sel1 == 2) && (sel2 == 1)) { /* Basic Machine CPU */ struct sysib_121 sysib; @@ -2594,7 +2650,7 @@ uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1) ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16); ebcdic_put(sysib.plant, "QEMU", 4); stw_p(&sysib.cpu_addr, env->cpu_num); - cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1); + cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); } else if ((sel1 == 2) && (sel2 == 2)) { /* Basic Machine CPUs */ struct sysib_122 sysib; @@ -2606,68 +2662,68 @@ uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1) stw_p(&sysib.active_cpus, 1); stw_p(&sysib.standby_cpus, 0); stw_p(&sysib.reserved_cpus, 0); - cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1); + cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); } else { cc = 3; } break; case STSI_LEVEL_2: - { - if ((sel1 == 2) && (sel2 == 1)) { - /* LPAR CPU */ - struct sysib_221 sysib; + { + if ((sel1 == 2) && (sel2 == 1)) { + /* LPAR CPU */ + struct sysib_221 sysib; - memset(&sysib, 0, sizeof(sysib)); - /* XXX make different for different CPUs? */ - ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16); - ebcdic_put(sysib.plant, "QEMU", 4); - stw_p(&sysib.cpu_addr, env->cpu_num); - stw_p(&sysib.cpu_id, 0); - cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1); - } else if ((sel1 == 2) && (sel2 == 2)) { - /* LPAR CPUs */ - struct sysib_222 sysib; + memset(&sysib, 0, sizeof(sysib)); + /* XXX make different for different CPUs? */ + ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16); + ebcdic_put(sysib.plant, "QEMU", 4); + stw_p(&sysib.cpu_addr, env->cpu_num); + stw_p(&sysib.cpu_id, 0); + cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); + } else if ((sel1 == 2) && (sel2 == 2)) { + /* LPAR CPUs */ + struct sysib_222 sysib; - memset(&sysib, 0, sizeof(sysib)); - stw_p(&sysib.lpar_num, 0); - sysib.lcpuc = 0; - /* XXX change when SMP comes */ - stw_p(&sysib.total_cpus, 1); - stw_p(&sysib.conf_cpus, 1); - stw_p(&sysib.standby_cpus, 0); - stw_p(&sysib.reserved_cpus, 0); - ebcdic_put(sysib.name, "QEMU ", 8); - stl_p(&sysib.caf, 1000); - stw_p(&sysib.dedicated_cpus, 0); - stw_p(&sysib.shared_cpus, 0); - cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1); - } else { - cc = 3; + memset(&sysib, 0, sizeof(sysib)); + stw_p(&sysib.lpar_num, 0); + sysib.lcpuc = 0; + /* XXX change when SMP comes */ + stw_p(&sysib.total_cpus, 1); + stw_p(&sysib.conf_cpus, 1); + stw_p(&sysib.standby_cpus, 0); + stw_p(&sysib.reserved_cpus, 0); + ebcdic_put(sysib.name, "QEMU ", 8); + stl_p(&sysib.caf, 1000); + stw_p(&sysib.dedicated_cpus, 0); + stw_p(&sysib.shared_cpus, 0); + cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); + } else { + cc = 3; + } + break; } - break; - } case STSI_LEVEL_3: - { - if ((sel1 == 2) && (sel2 == 2)) { - /* VM CPUs */ - struct sysib_322 sysib; + { + if ((sel1 == 2) && (sel2 == 2)) { + /* VM CPUs */ + struct sysib_322 sysib; - memset(&sysib, 0, sizeof(sysib)); - sysib.count = 1; - /* XXX change when SMP comes */ - stw_p(&sysib.vm[0].total_cpus, 1); - stw_p(&sysib.vm[0].conf_cpus, 1); - stw_p(&sysib.vm[0].standby_cpus, 0); - stw_p(&sysib.vm[0].reserved_cpus, 0); - ebcdic_put(sysib.vm[0].name, "KVMguest", 8); - stl_p(&sysib.vm[0].caf, 1000); - ebcdic_put(sysib.vm[0].cpi, "KVM/Linux ", 16); - cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1); - } else { - cc = 3; + memset(&sysib, 0, sizeof(sysib)); + sysib.count = 1; + /* XXX change when SMP comes */ + stw_p(&sysib.vm[0].total_cpus, 1); + stw_p(&sysib.vm[0].conf_cpus, 1); + stw_p(&sysib.vm[0].standby_cpus, 0); + stw_p(&sysib.vm[0].reserved_cpus, 0); + ebcdic_put(sysib.vm[0].name, "KVMguest", 8); + stl_p(&sysib.vm[0].caf, 1000); + ebcdic_put(sysib.vm[0].cpi, "KVM/Linux ", 16); + cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); + } else { + cc = 3; + } + break; } - break; - } case STSI_LEVEL_CURRENT: env->regs[0] = STSI_LEVEL_3; break; @@ -2781,6 +2837,7 @@ uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2) { uint8_t re; uint8_t key; + if (r2 > ram_size) { return 0; } @@ -2865,7 +2922,7 @@ static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2, uint32_t HELPER(mvcs)(uint64_t l, uint64_t a1, uint64_t a2) { HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n", - __FUNCTION__, l, a1, a2); + __func__, l, a1, a2); return mvc_asc(l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY); } @@ -2873,7 +2930,7 @@ uint32_t HELPER(mvcs)(uint64_t l, uint64_t a1, uint64_t a2) uint32_t HELPER(mvcp)(uint64_t l, uint64_t a1, uint64_t a2) { HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n", - __FUNCTION__, l, a1, a2); + __func__, l, a1, a2); return mvc_asc(l, a1, PSW_ASC_PRIMARY, a2, PSW_ASC_SECONDARY); } @@ -2883,9 +2940,9 @@ uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr) int cc = 0; HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n", - __FUNCTION__, order_code, r1, cpu_addr); + __func__, order_code, r1, cpu_addr); - /* Remember: Use "R1 or R1+1, whichever is the odd-numbered register" + /* Remember: Use "R1 or R1 + 1, whichever is the odd-numbered register" as parameter (input). Status (output) is always R1. */ switch (order_code) { @@ -2901,7 +2958,7 @@ uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr) env->regs[r1] &= 0xffffffff00000000ULL; cc = 1; break; -#if !defined (CONFIG_USER_ONLY) +#if !defined(CONFIG_USER_ONLY) case SIGP_RESTART: qemu_system_reset_request(); cpu_loop_exit(env); @@ -2922,7 +2979,7 @@ uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr) void HELPER(sacf)(uint64_t a1) { - HELPER_LOG("%s: %16" PRIx64 "\n", __FUNCTION__, a1); + HELPER_LOG("%s: %16" PRIx64 "\n", __func__, a1); switch (a1 & 0xf00) { case 0x000: @@ -2953,13 +3010,13 @@ void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr) /* XXX broadcast to other CPUs */ /* XXX Linux is nice enough to give us the exact pte address. - According to spec we'd have to find it out ourselves */ + According to spec we'd have to find it out ourselves */ /* XXX Linux is fine with overwriting the pte, the spec requires - us to only set the invalid bit */ + us to only set the invalid bit */ stq_phys(pte_addr, pte | _PAGE_INVALID); /* XXX we exploit the fact that Linux passes the exact virtual - address here - it's not obliged to! */ + address here - it's not obliged to! */ tlb_flush_page(env, page); /* XXX 31-bit hack */ @@ -3008,7 +3065,8 @@ uint32_t HELPER(lra)(uint64_t addr, uint32_t r1) env->exception_index = old_exc; if (!(env->psw.mask & PSW_MASK_64)) { - env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | (ret & 0xffffffffULL); + env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | + (ret & 0xffffffffULL); } else { env->regs[r1] = ret; } From e72ca652aa08e3d07c59349f239ba596f27c97af Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 07:33:31 +0000 Subject: [PATCH 0218/2270] target-s390x: split FPU ops Move floating point instructions to fpu_helper.c. While exporting some condition code helpers, avoid duplicate identifier conflict with translate.c. Remove unused set_cc_nz_f64() in translate.c. Signed-off-by: Blue Swirl Signed-off-by: Alexander Graf --- target-s390x/Makefile.objs | 2 + target-s390x/cpu.h | 6 + target-s390x/fpu_helper.c | 836 +++++++++++++++++++++++++++++++++++++ target-s390x/op_helper.c | 802 ----------------------------------- target-s390x/translate.c | 11 +- 5 files changed, 847 insertions(+), 810 deletions(-) create mode 100644 target-s390x/fpu_helper.c diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs index 80be3bbdb2..23b3bd9989 100644 --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -1,5 +1,7 @@ obj-y += translate.o op_helper.o helper.o cpu.o interrupt.o +obj-y += fpu_helper.o obj-$(CONFIG_SOFTMMU) += machine.o obj-$(CONFIG_KVM) += kvm.o $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) +$(obj)/fpu_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 18ac6e3938..b4620c502d 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -999,4 +999,10 @@ static inline void cpu_pc_from_tb(CPUS390XState *env, TranslationBlock* tb) env->psw.addr = tb->pc; } +/* fpu_helper.c */ +uint32_t set_cc_f32(float32 v1, float32 v2); +uint32_t set_cc_f64(float64 v1, float64 v2); +uint32_t set_cc_nz_f32(float32 v); +uint32_t set_cc_nz_f64(float64 v); + #endif diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c new file mode 100644 index 0000000000..1389052f5c --- /dev/null +++ b/target-s390x/fpu_helper.c @@ -0,0 +1,836 @@ +/* + * S/390 FPU helper routines + * + * Copyright (c) 2009 Ulrich Hecht + * Copyright (c) 2009 Alexander Graf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "cpu.h" +#include "dyngen-exec.h" +#include "helper.h" + +#if !defined(CONFIG_USER_ONLY) +#include "softmmu_exec.h" +#endif + +/* #define DEBUG_HELPER */ +#ifdef DEBUG_HELPER +#define HELPER_LOG(x...) qemu_log(x) +#else +#define HELPER_LOG(x...) +#endif + +static inline int float_comp_to_cc(int float_compare) +{ + switch (float_compare) { + case float_relation_equal: + return 0; + case float_relation_less: + return 1; + case float_relation_greater: + return 2; + case float_relation_unordered: + return 3; + default: + cpu_abort(env, "unknown return value for float compare\n"); + } +} + +/* condition codes for binary FP ops */ +uint32_t set_cc_f32(float32 v1, float32 v2) +{ + return float_comp_to_cc(float32_compare_quiet(v1, v2, &env->fpu_status)); +} + +uint32_t set_cc_f64(float64 v1, float64 v2) +{ + return float_comp_to_cc(float64_compare_quiet(v1, v2, &env->fpu_status)); +} + +/* condition codes for unary FP ops */ +uint32_t set_cc_nz_f32(float32 v) +{ + if (float32_is_any_nan(v)) { + return 3; + } else if (float32_is_zero(v)) { + return 0; + } else if (float32_is_neg(v)) { + return 1; + } else { + return 2; + } +} + +uint32_t set_cc_nz_f64(float64 v) +{ + if (float64_is_any_nan(v)) { + return 3; + } else if (float64_is_zero(v)) { + return 0; + } else if (float64_is_neg(v)) { + return 1; + } else { + return 2; + } +} + +static uint32_t set_cc_nz_f128(float128 v) +{ + if (float128_is_any_nan(v)) { + return 3; + } else if (float128_is_zero(v)) { + return 0; + } else if (float128_is_neg(v)) { + return 1; + } else { + return 2; + } +} + +/* convert 32-bit int to 64-bit float */ +void HELPER(cdfbr)(uint32_t f1, int32_t v2) +{ + HELPER_LOG("%s: converting %d to f%d\n", __func__, v2, f1); + env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status); +} + +/* convert 32-bit int to 128-bit float */ +void HELPER(cxfbr)(uint32_t f1, int32_t v2) +{ + CPU_QuadU v1; + + v1.q = int32_to_float128(v2, &env->fpu_status); + env->fregs[f1].ll = v1.ll.upper; + env->fregs[f1 + 2].ll = v1.ll.lower; +} + +/* convert 64-bit int to 32-bit float */ +void HELPER(cegbr)(uint32_t f1, int64_t v2) +{ + HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1); + env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status); +} + +/* convert 64-bit int to 64-bit float */ +void HELPER(cdgbr)(uint32_t f1, int64_t v2) +{ + HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1); + env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status); +} + +/* convert 64-bit int to 128-bit float */ +void HELPER(cxgbr)(uint32_t f1, int64_t v2) +{ + CPU_QuadU x1; + + x1.q = int64_to_float128(v2, &env->fpu_status); + HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __func__, v2, + x1.ll.upper, x1.ll.lower); + env->fregs[f1].ll = x1.ll.upper; + env->fregs[f1 + 2].ll = x1.ll.lower; +} + +/* convert 32-bit int to 32-bit float */ +void HELPER(cefbr)(uint32_t f1, int32_t v2) +{ + env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status); + HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __func__, v2, + env->fregs[f1].l.upper, f1); +} + +/* 32-bit FP addition RR */ +uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2) +{ + env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper, + env->fregs[f2].l.upper, + &env->fpu_status); + HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__, + env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1); + + return set_cc_nz_f32(env->fregs[f1].l.upper); +} + +/* 64-bit FP addition RR */ +uint32_t HELPER(adbr)(uint32_t f1, uint32_t f2) +{ + env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d, + &env->fpu_status); + HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __func__, + env->fregs[f2].d, env->fregs[f1].d, f1); + + return set_cc_nz_f64(env->fregs[f1].d); +} + +/* 32-bit FP subtraction RR */ +uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2) +{ + env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper, + env->fregs[f2].l.upper, + &env->fpu_status); + HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__, + env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1); + + return set_cc_nz_f32(env->fregs[f1].l.upper); +} + +/* 64-bit FP subtraction RR */ +uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2) +{ + env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d, + &env->fpu_status); + HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n", + __func__, env->fregs[f2].d, env->fregs[f1].d, f1); + + return set_cc_nz_f64(env->fregs[f1].d); +} + +/* 32-bit FP division RR */ +void HELPER(debr)(uint32_t f1, uint32_t f2) +{ + env->fregs[f1].l.upper = float32_div(env->fregs[f1].l.upper, + env->fregs[f2].l.upper, + &env->fpu_status); +} + +/* 128-bit FP division RR */ +void HELPER(dxbr)(uint32_t f1, uint32_t f2) +{ + CPU_QuadU v1; + CPU_QuadU v2; + CPU_QuadU res; + + v1.ll.upper = env->fregs[f1].ll; + v1.ll.lower = env->fregs[f1 + 2].ll; + v2.ll.upper = env->fregs[f2].ll; + v2.ll.lower = env->fregs[f2 + 2].ll; + res.q = float128_div(v1.q, v2.q, &env->fpu_status); + env->fregs[f1].ll = res.ll.upper; + env->fregs[f1 + 2].ll = res.ll.lower; +} + +/* 64-bit FP multiplication RR */ +void HELPER(mdbr)(uint32_t f1, uint32_t f2) +{ + env->fregs[f1].d = float64_mul(env->fregs[f1].d, env->fregs[f2].d, + &env->fpu_status); +} + +/* 128-bit FP multiplication RR */ +void HELPER(mxbr)(uint32_t f1, uint32_t f2) +{ + CPU_QuadU v1; + CPU_QuadU v2; + CPU_QuadU res; + + v1.ll.upper = env->fregs[f1].ll; + v1.ll.lower = env->fregs[f1 + 2].ll; + v2.ll.upper = env->fregs[f2].ll; + v2.ll.lower = env->fregs[f2 + 2].ll; + res.q = float128_mul(v1.q, v2.q, &env->fpu_status); + env->fregs[f1].ll = res.ll.upper; + env->fregs[f1 + 2].ll = res.ll.lower; +} + +/* convert 32-bit float to 64-bit float */ +void HELPER(ldebr)(uint32_t r1, uint32_t r2) +{ + env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper, + &env->fpu_status); +} + +/* convert 128-bit float to 64-bit float */ +void HELPER(ldxbr)(uint32_t f1, uint32_t f2) +{ + CPU_QuadU x2; + + x2.ll.upper = env->fregs[f2].ll; + x2.ll.lower = env->fregs[f2 + 2].ll; + env->fregs[f1].d = float128_to_float64(x2.q, &env->fpu_status); + HELPER_LOG("%s: to 0x%ld\n", __func__, env->fregs[f1].d); +} + +/* convert 64-bit float to 128-bit float */ +void HELPER(lxdbr)(uint32_t f1, uint32_t f2) +{ + CPU_QuadU res; + + res.q = float64_to_float128(env->fregs[f2].d, &env->fpu_status); + env->fregs[f1].ll = res.ll.upper; + env->fregs[f1 + 2].ll = res.ll.lower; +} + +/* convert 64-bit float to 32-bit float */ +void HELPER(ledbr)(uint32_t f1, uint32_t f2) +{ + float64 d2 = env->fregs[f2].d; + + env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status); +} + +/* convert 128-bit float to 32-bit float */ +void HELPER(lexbr)(uint32_t f1, uint32_t f2) +{ + CPU_QuadU x2; + + x2.ll.upper = env->fregs[f2].ll; + x2.ll.lower = env->fregs[f2 + 2].ll; + env->fregs[f1].l.upper = float128_to_float32(x2.q, &env->fpu_status); + HELPER_LOG("%s: to 0x%d\n", __func__, env->fregs[f1].l.upper); +} + +/* absolute value of 32-bit float */ +uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2) +{ + float32 v1; + float32 v2 = env->fregs[f2].d; + + v1 = float32_abs(v2); + env->fregs[f1].d = v1; + return set_cc_nz_f32(v1); +} + +/* absolute value of 64-bit float */ +uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2) +{ + float64 v1; + float64 v2 = env->fregs[f2].d; + + v1 = float64_abs(v2); + env->fregs[f1].d = v1; + return set_cc_nz_f64(v1); +} + +/* absolute value of 128-bit float */ +uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2) +{ + CPU_QuadU v1; + CPU_QuadU v2; + + v2.ll.upper = env->fregs[f2].ll; + v2.ll.lower = env->fregs[f2 + 2].ll; + v1.q = float128_abs(v2.q); + env->fregs[f1].ll = v1.ll.upper; + env->fregs[f1 + 2].ll = v1.ll.lower; + return set_cc_nz_f128(v1.q); +} + +/* load and test 64-bit float */ +uint32_t HELPER(ltdbr)(uint32_t f1, uint32_t f2) +{ + env->fregs[f1].d = env->fregs[f2].d; + return set_cc_nz_f64(env->fregs[f1].d); +} + +/* load and test 32-bit float */ +uint32_t HELPER(ltebr)(uint32_t f1, uint32_t f2) +{ + env->fregs[f1].l.upper = env->fregs[f2].l.upper; + return set_cc_nz_f32(env->fregs[f1].l.upper); +} + +/* load and test 128-bit float */ +uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2) +{ + CPU_QuadU x; + + x.ll.upper = env->fregs[f2].ll; + x.ll.lower = env->fregs[f2 + 2].ll; + env->fregs[f1].ll = x.ll.upper; + env->fregs[f1 + 2].ll = x.ll.lower; + return set_cc_nz_f128(x.q); +} + +/* load complement of 32-bit float */ +uint32_t HELPER(lcebr)(uint32_t f1, uint32_t f2) +{ + env->fregs[f1].l.upper = float32_chs(env->fregs[f2].l.upper); + + return set_cc_nz_f32(env->fregs[f1].l.upper); +} + +/* load complement of 64-bit float */ +uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2) +{ + env->fregs[f1].d = float64_chs(env->fregs[f2].d); + + return set_cc_nz_f64(env->fregs[f1].d); +} + +/* load complement of 128-bit float */ +uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2) +{ + CPU_QuadU x1, x2; + + x2.ll.upper = env->fregs[f2].ll; + x2.ll.lower = env->fregs[f2 + 2].ll; + x1.q = float128_chs(x2.q); + env->fregs[f1].ll = x1.ll.upper; + env->fregs[f1 + 2].ll = x1.ll.lower; + return set_cc_nz_f128(x1.q); +} + +/* 32-bit FP addition RM */ +void HELPER(aeb)(uint32_t f1, uint32_t val) +{ + float32 v1 = env->fregs[f1].l.upper; + CPU_FloatU v2; + + v2.l = val; + HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __func__, + v1, f1, v2.f); + env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status); +} + +/* 32-bit FP division RM */ +void HELPER(deb)(uint32_t f1, uint32_t val) +{ + float32 v1 = env->fregs[f1].l.upper; + CPU_FloatU v2; + + v2.l = val; + HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __func__, + v1, f1, v2.f); + env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status); +} + +/* 32-bit FP multiplication RM */ +void HELPER(meeb)(uint32_t f1, uint32_t val) +{ + float32 v1 = env->fregs[f1].l.upper; + CPU_FloatU v2; + + v2.l = val; + HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __func__, + v1, f1, v2.f); + env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status); +} + +/* 32-bit FP compare RR */ +uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2) +{ + float32 v1 = env->fregs[f1].l.upper; + float32 v2 = env->fregs[f2].l.upper; + + HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __func__, + v1, f1, v2); + return set_cc_f32(v1, v2); +} + +/* 64-bit FP compare RR */ +uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2) +{ + float64 v1 = env->fregs[f1].d; + float64 v2 = env->fregs[f2].d; + + HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __func__, + v1, f1, v2); + return set_cc_f64(v1, v2); +} + +/* 128-bit FP compare RR */ +uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2) +{ + CPU_QuadU v1; + CPU_QuadU v2; + + v1.ll.upper = env->fregs[f1].ll; + v1.ll.lower = env->fregs[f1 + 2].ll; + v2.ll.upper = env->fregs[f2].ll; + v2.ll.lower = env->fregs[f2 + 2].ll; + + return float_comp_to_cc(float128_compare_quiet(v1.q, v2.q, + &env->fpu_status)); +} + +/* 64-bit FP compare RM */ +uint32_t HELPER(cdb)(uint32_t f1, uint64_t a2) +{ + float64 v1 = env->fregs[f1].d; + CPU_DoubleU v2; + + v2.ll = ldq(a2); + HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__, v1, + f1, v2.d); + return set_cc_f64(v1, v2.d); +} + +/* 64-bit FP addition RM */ +uint32_t HELPER(adb)(uint32_t f1, uint64_t a2) +{ + float64 v1 = env->fregs[f1].d; + CPU_DoubleU v2; + + v2.ll = ldq(a2); + HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __func__, + v1, f1, v2.d); + env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status); + return set_cc_nz_f64(v1); +} + +/* 32-bit FP subtraction RM */ +void HELPER(seb)(uint32_t f1, uint32_t val) +{ + float32 v1 = env->fregs[f1].l.upper; + CPU_FloatU v2; + + v2.l = val; + env->fregs[f1].l.upper = float32_sub(v1, v2.f, &env->fpu_status); +} + +/* 64-bit FP subtraction RM */ +uint32_t HELPER(sdb)(uint32_t f1, uint64_t a2) +{ + float64 v1 = env->fregs[f1].d; + CPU_DoubleU v2; + + v2.ll = ldq(a2); + env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status); + return set_cc_nz_f64(v1); +} + +/* 64-bit FP multiplication RM */ +void HELPER(mdb)(uint32_t f1, uint64_t a2) +{ + float64 v1 = env->fregs[f1].d; + CPU_DoubleU v2; + + v2.ll = ldq(a2); + HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __func__, + v1, f1, v2.d); + env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status); +} + +/* 64-bit FP division RM */ +void HELPER(ddb)(uint32_t f1, uint64_t a2) +{ + float64 v1 = env->fregs[f1].d; + CPU_DoubleU v2; + + v2.ll = ldq(a2); + HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __func__, + v1, f1, v2.d); + env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status); +} + +static void set_round_mode(int m3) +{ + switch (m3) { + case 0: + /* current mode */ + break; + case 1: + /* biased round no nearest */ + case 4: + /* round to nearest */ + set_float_rounding_mode(float_round_nearest_even, &env->fpu_status); + break; + case 5: + /* round to zero */ + set_float_rounding_mode(float_round_to_zero, &env->fpu_status); + break; + case 6: + /* round to +inf */ + set_float_rounding_mode(float_round_up, &env->fpu_status); + break; + case 7: + /* round to -inf */ + set_float_rounding_mode(float_round_down, &env->fpu_status); + break; + } +} + +/* convert 32-bit float to 64-bit int */ +uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3) +{ + float32 v2 = env->fregs[f2].l.upper; + + set_round_mode(m3); + env->regs[r1] = float32_to_int64(v2, &env->fpu_status); + return set_cc_nz_f32(v2); +} + +/* convert 64-bit float to 64-bit int */ +uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3) +{ + float64 v2 = env->fregs[f2].d; + + set_round_mode(m3); + env->regs[r1] = float64_to_int64(v2, &env->fpu_status); + return set_cc_nz_f64(v2); +} + +/* convert 128-bit float to 64-bit int */ +uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3) +{ + CPU_QuadU v2; + + v2.ll.upper = env->fregs[f2].ll; + v2.ll.lower = env->fregs[f2 + 2].ll; + set_round_mode(m3); + env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status); + if (float128_is_any_nan(v2.q)) { + return 3; + } else if (float128_is_zero(v2.q)) { + return 0; + } else if (float128_is_neg(v2.q)) { + return 1; + } else { + return 2; + } +} + +/* convert 32-bit float to 32-bit int */ +uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3) +{ + float32 v2 = env->fregs[f2].l.upper; + + set_round_mode(m3); + env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | + float32_to_int32(v2, &env->fpu_status); + return set_cc_nz_f32(v2); +} + +/* convert 64-bit float to 32-bit int */ +uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3) +{ + float64 v2 = env->fregs[f2].d; + + set_round_mode(m3); + env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | + float64_to_int32(v2, &env->fpu_status); + return set_cc_nz_f64(v2); +} + +/* convert 128-bit float to 32-bit int */ +uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3) +{ + CPU_QuadU v2; + + v2.ll.upper = env->fregs[f2].ll; + v2.ll.lower = env->fregs[f2 + 2].ll; + env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | + float128_to_int32(v2.q, &env->fpu_status); + return set_cc_nz_f128(v2.q); +} + +/* load 32-bit FP zero */ +void HELPER(lzer)(uint32_t f1) +{ + env->fregs[f1].l.upper = float32_zero; +} + +/* load 64-bit FP zero */ +void HELPER(lzdr)(uint32_t f1) +{ + env->fregs[f1].d = float64_zero; +} + +/* load 128-bit FP zero */ +void HELPER(lzxr)(uint32_t f1) +{ + CPU_QuadU x; + + x.q = float64_to_float128(float64_zero, &env->fpu_status); + env->fregs[f1].ll = x.ll.upper; + env->fregs[f1 + 1].ll = x.ll.lower; +} + +/* 128-bit FP subtraction RR */ +uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2) +{ + CPU_QuadU v1; + CPU_QuadU v2; + CPU_QuadU res; + + v1.ll.upper = env->fregs[f1].ll; + v1.ll.lower = env->fregs[f1 + 2].ll; + v2.ll.upper = env->fregs[f2].ll; + v2.ll.lower = env->fregs[f2 + 2].ll; + res.q = float128_sub(v1.q, v2.q, &env->fpu_status); + env->fregs[f1].ll = res.ll.upper; + env->fregs[f1 + 2].ll = res.ll.lower; + return set_cc_nz_f128(res.q); +} + +/* 128-bit FP addition RR */ +uint32_t HELPER(axbr)(uint32_t f1, uint32_t f2) +{ + CPU_QuadU v1; + CPU_QuadU v2; + CPU_QuadU res; + + v1.ll.upper = env->fregs[f1].ll; + v1.ll.lower = env->fregs[f1 + 2].ll; + v2.ll.upper = env->fregs[f2].ll; + v2.ll.lower = env->fregs[f2 + 2].ll; + res.q = float128_add(v1.q, v2.q, &env->fpu_status); + env->fregs[f1].ll = res.ll.upper; + env->fregs[f1 + 2].ll = res.ll.lower; + return set_cc_nz_f128(res.q); +} + +/* 32-bit FP multiplication RR */ +void HELPER(meebr)(uint32_t f1, uint32_t f2) +{ + env->fregs[f1].l.upper = float32_mul(env->fregs[f1].l.upper, + env->fregs[f2].l.upper, + &env->fpu_status); +} + +/* 64-bit FP division RR */ +void HELPER(ddbr)(uint32_t f1, uint32_t f2) +{ + env->fregs[f1].d = float64_div(env->fregs[f1].d, env->fregs[f2].d, + &env->fpu_status); +} + +/* 64-bit FP multiply and add RM */ +void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3) +{ + CPU_DoubleU v2; + + HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __func__, f1, a2, f3); + v2.ll = ldq(a2); + env->fregs[f1].d = float64_add(env->fregs[f1].d, + float64_mul(v2.d, env->fregs[f3].d, + &env->fpu_status), + &env->fpu_status); +} + +/* 64-bit FP multiply and add RR */ +void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2) +{ + HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3); + env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d, + env->fregs[f3].d, + &env->fpu_status), + env->fregs[f1].d, &env->fpu_status); +} + +/* 64-bit FP multiply and subtract RR */ +void HELPER(msdbr)(uint32_t f1, uint32_t f3, uint32_t f2) +{ + HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3); + env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d, + env->fregs[f3].d, + &env->fpu_status), + env->fregs[f1].d, &env->fpu_status); +} + +/* 32-bit FP multiply and add RR */ +void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2) +{ + env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper, + float32_mul(env->fregs[f2].l.upper, + env->fregs[f3].l.upper, + &env->fpu_status), + &env->fpu_status); +} + +/* convert 32-bit float to 64-bit float */ +void HELPER(ldeb)(uint32_t f1, uint64_t a2) +{ + uint32_t v2; + + v2 = ldl(a2); + env->fregs[f1].d = float32_to_float64(v2, + &env->fpu_status); +} + +/* convert 64-bit float to 128-bit float */ +void HELPER(lxdb)(uint32_t f1, uint64_t a2) +{ + CPU_DoubleU v2; + CPU_QuadU v1; + + v2.ll = ldq(a2); + v1.q = float64_to_float128(v2.d, &env->fpu_status); + env->fregs[f1].ll = v1.ll.upper; + env->fregs[f1 + 2].ll = v1.ll.lower; +} + +/* test data class 32-bit */ +uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2) +{ + float32 v1 = env->fregs[f1].l.upper; + int neg = float32_is_neg(v1); + uint32_t cc = 0; + + HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, (long)v1, m2, neg); + if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) || + (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) || + (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || + (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { + cc = 1; + } else if (m2 & (1 << (9-neg))) { + /* assume normalized number */ + cc = 1; + } + + /* FIXME: denormalized? */ + return cc; +} + +/* test data class 64-bit */ +uint32_t HELPER(tcdb)(uint32_t f1, uint64_t m2) +{ + float64 v1 = env->fregs[f1].d; + int neg = float64_is_neg(v1); + uint32_t cc = 0; + + HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, v1, m2, neg); + if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) || + (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) || + (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || + (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { + cc = 1; + } else if (m2 & (1 << (9-neg))) { + /* assume normalized number */ + cc = 1; + } + /* FIXME: denormalized? */ + return cc; +} + +/* test data class 128-bit */ +uint32_t HELPER(tcxb)(uint32_t f1, uint64_t m2) +{ + CPU_QuadU v1; + uint32_t cc = 0; + int neg; + + v1.ll.upper = env->fregs[f1].ll; + v1.ll.lower = env->fregs[f1 + 2].ll; + + neg = float128_is_neg(v1.q); + if ((float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) || + (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) || + (float128_is_any_nan(v1.q) && (m2 & (1 << (3-neg)))) || + (float128_is_signaling_nan(v1.q) && (m2 & (1 << (1-neg))))) { + cc = 1; + } else if (m2 & (1 << (9-neg))) { + /* assume normalized number */ + cc = 1; + } + /* FIXME: denormalized? */ + return cc; +} + +/* square root 64-bit RR */ +void HELPER(sqdbr)(uint32_t f1, uint32_t f2) +{ + env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status); +} diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c index 195e93ed5e..270bf14f0b 100644 --- a/target-s390x/op_helper.c +++ b/target-s390x/op_helper.c @@ -977,802 +977,6 @@ uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2) } } -static inline int float_comp_to_cc(int float_compare) -{ - switch (float_compare) { - case float_relation_equal: - return 0; - case float_relation_less: - return 1; - case float_relation_greater: - return 2; - case float_relation_unordered: - return 3; - default: - cpu_abort(env, "unknown return value for float compare\n"); - } -} - -/* condition codes for binary FP ops */ -static uint32_t set_cc_f32(float32 v1, float32 v2) -{ - return float_comp_to_cc(float32_compare_quiet(v1, v2, &env->fpu_status)); -} - -static uint32_t set_cc_f64(float64 v1, float64 v2) -{ - return float_comp_to_cc(float64_compare_quiet(v1, v2, &env->fpu_status)); -} - -/* condition codes for unary FP ops */ -static uint32_t set_cc_nz_f32(float32 v) -{ - if (float32_is_any_nan(v)) { - return 3; - } else if (float32_is_zero(v)) { - return 0; - } else if (float32_is_neg(v)) { - return 1; - } else { - return 2; - } -} - -static uint32_t set_cc_nz_f64(float64 v) -{ - if (float64_is_any_nan(v)) { - return 3; - } else if (float64_is_zero(v)) { - return 0; - } else if (float64_is_neg(v)) { - return 1; - } else { - return 2; - } -} - -static uint32_t set_cc_nz_f128(float128 v) -{ - if (float128_is_any_nan(v)) { - return 3; - } else if (float128_is_zero(v)) { - return 0; - } else if (float128_is_neg(v)) { - return 1; - } else { - return 2; - } -} - -/* convert 32-bit int to 64-bit float */ -void HELPER(cdfbr)(uint32_t f1, int32_t v2) -{ - HELPER_LOG("%s: converting %d to f%d\n", __func__, v2, f1); - env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status); -} - -/* convert 32-bit int to 128-bit float */ -void HELPER(cxfbr)(uint32_t f1, int32_t v2) -{ - CPU_QuadU v1; - - v1.q = int32_to_float128(v2, &env->fpu_status); - env->fregs[f1].ll = v1.ll.upper; - env->fregs[f1 + 2].ll = v1.ll.lower; -} - -/* convert 64-bit int to 32-bit float */ -void HELPER(cegbr)(uint32_t f1, int64_t v2) -{ - HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1); - env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status); -} - -/* convert 64-bit int to 64-bit float */ -void HELPER(cdgbr)(uint32_t f1, int64_t v2) -{ - HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1); - env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status); -} - -/* convert 64-bit int to 128-bit float */ -void HELPER(cxgbr)(uint32_t f1, int64_t v2) -{ - CPU_QuadU x1; - - x1.q = int64_to_float128(v2, &env->fpu_status); - HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __func__, v2, - x1.ll.upper, x1.ll.lower); - env->fregs[f1].ll = x1.ll.upper; - env->fregs[f1 + 2].ll = x1.ll.lower; -} - -/* convert 32-bit int to 32-bit float */ -void HELPER(cefbr)(uint32_t f1, int32_t v2) -{ - env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status); - HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __func__, v2, - env->fregs[f1].l.upper, f1); -} - -/* 32-bit FP addition RR */ -uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2) -{ - env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper, - env->fregs[f2].l.upper, - &env->fpu_status); - HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__, - env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1); - - return set_cc_nz_f32(env->fregs[f1].l.upper); -} - -/* 64-bit FP addition RR */ -uint32_t HELPER(adbr)(uint32_t f1, uint32_t f2) -{ - env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d, - &env->fpu_status); - HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __func__, - env->fregs[f2].d, env->fregs[f1].d, f1); - - return set_cc_nz_f64(env->fregs[f1].d); -} - -/* 32-bit FP subtraction RR */ -uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2) -{ - env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper, - env->fregs[f2].l.upper, - &env->fpu_status); - HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__, - env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1); - - return set_cc_nz_f32(env->fregs[f1].l.upper); -} - -/* 64-bit FP subtraction RR */ -uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2) -{ - env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d, - &env->fpu_status); - HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n", - __func__, env->fregs[f2].d, env->fregs[f1].d, f1); - - return set_cc_nz_f64(env->fregs[f1].d); -} - -/* 32-bit FP division RR */ -void HELPER(debr)(uint32_t f1, uint32_t f2) -{ - env->fregs[f1].l.upper = float32_div(env->fregs[f1].l.upper, - env->fregs[f2].l.upper, - &env->fpu_status); -} - -/* 128-bit FP division RR */ -void HELPER(dxbr)(uint32_t f1, uint32_t f2) -{ - CPU_QuadU v1; - CPU_QuadU v2; - CPU_QuadU res; - - v1.ll.upper = env->fregs[f1].ll; - v1.ll.lower = env->fregs[f1 + 2].ll; - v2.ll.upper = env->fregs[f2].ll; - v2.ll.lower = env->fregs[f2 + 2].ll; - res.q = float128_div(v1.q, v2.q, &env->fpu_status); - env->fregs[f1].ll = res.ll.upper; - env->fregs[f1 + 2].ll = res.ll.lower; -} - -/* 64-bit FP multiplication RR */ -void HELPER(mdbr)(uint32_t f1, uint32_t f2) -{ - env->fregs[f1].d = float64_mul(env->fregs[f1].d, env->fregs[f2].d, - &env->fpu_status); -} - -/* 128-bit FP multiplication RR */ -void HELPER(mxbr)(uint32_t f1, uint32_t f2) -{ - CPU_QuadU v1; - CPU_QuadU v2; - CPU_QuadU res; - - v1.ll.upper = env->fregs[f1].ll; - v1.ll.lower = env->fregs[f1 + 2].ll; - v2.ll.upper = env->fregs[f2].ll; - v2.ll.lower = env->fregs[f2 + 2].ll; - res.q = float128_mul(v1.q, v2.q, &env->fpu_status); - env->fregs[f1].ll = res.ll.upper; - env->fregs[f1 + 2].ll = res.ll.lower; -} - -/* convert 32-bit float to 64-bit float */ -void HELPER(ldebr)(uint32_t r1, uint32_t r2) -{ - env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper, - &env->fpu_status); -} - -/* convert 128-bit float to 64-bit float */ -void HELPER(ldxbr)(uint32_t f1, uint32_t f2) -{ - CPU_QuadU x2; - - x2.ll.upper = env->fregs[f2].ll; - x2.ll.lower = env->fregs[f2 + 2].ll; - env->fregs[f1].d = float128_to_float64(x2.q, &env->fpu_status); - HELPER_LOG("%s: to 0x%ld\n", __func__, env->fregs[f1].d); -} - -/* convert 64-bit float to 128-bit float */ -void HELPER(lxdbr)(uint32_t f1, uint32_t f2) -{ - CPU_QuadU res; - - res.q = float64_to_float128(env->fregs[f2].d, &env->fpu_status); - env->fregs[f1].ll = res.ll.upper; - env->fregs[f1 + 2].ll = res.ll.lower; -} - -/* convert 64-bit float to 32-bit float */ -void HELPER(ledbr)(uint32_t f1, uint32_t f2) -{ - float64 d2 = env->fregs[f2].d; - - env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status); -} - -/* convert 128-bit float to 32-bit float */ -void HELPER(lexbr)(uint32_t f1, uint32_t f2) -{ - CPU_QuadU x2; - - x2.ll.upper = env->fregs[f2].ll; - x2.ll.lower = env->fregs[f2 + 2].ll; - env->fregs[f1].l.upper = float128_to_float32(x2.q, &env->fpu_status); - HELPER_LOG("%s: to 0x%d\n", __func__, env->fregs[f1].l.upper); -} - -/* absolute value of 32-bit float */ -uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2) -{ - float32 v1; - float32 v2 = env->fregs[f2].d; - - v1 = float32_abs(v2); - env->fregs[f1].d = v1; - return set_cc_nz_f32(v1); -} - -/* absolute value of 64-bit float */ -uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2) -{ - float64 v1; - float64 v2 = env->fregs[f2].d; - - v1 = float64_abs(v2); - env->fregs[f1].d = v1; - return set_cc_nz_f64(v1); -} - -/* absolute value of 128-bit float */ -uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2) -{ - CPU_QuadU v1; - CPU_QuadU v2; - - v2.ll.upper = env->fregs[f2].ll; - v2.ll.lower = env->fregs[f2 + 2].ll; - v1.q = float128_abs(v2.q); - env->fregs[f1].ll = v1.ll.upper; - env->fregs[f1 + 2].ll = v1.ll.lower; - return set_cc_nz_f128(v1.q); -} - -/* load and test 64-bit float */ -uint32_t HELPER(ltdbr)(uint32_t f1, uint32_t f2) -{ - env->fregs[f1].d = env->fregs[f2].d; - return set_cc_nz_f64(env->fregs[f1].d); -} - -/* load and test 32-bit float */ -uint32_t HELPER(ltebr)(uint32_t f1, uint32_t f2) -{ - env->fregs[f1].l.upper = env->fregs[f2].l.upper; - return set_cc_nz_f32(env->fregs[f1].l.upper); -} - -/* load and test 128-bit float */ -uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2) -{ - CPU_QuadU x; - - x.ll.upper = env->fregs[f2].ll; - x.ll.lower = env->fregs[f2 + 2].ll; - env->fregs[f1].ll = x.ll.upper; - env->fregs[f1 + 2].ll = x.ll.lower; - return set_cc_nz_f128(x.q); -} - -/* load complement of 32-bit float */ -uint32_t HELPER(lcebr)(uint32_t f1, uint32_t f2) -{ - env->fregs[f1].l.upper = float32_chs(env->fregs[f2].l.upper); - - return set_cc_nz_f32(env->fregs[f1].l.upper); -} - -/* load complement of 64-bit float */ -uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2) -{ - env->fregs[f1].d = float64_chs(env->fregs[f2].d); - - return set_cc_nz_f64(env->fregs[f1].d); -} - -/* load complement of 128-bit float */ -uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2) -{ - CPU_QuadU x1, x2; - - x2.ll.upper = env->fregs[f2].ll; - x2.ll.lower = env->fregs[f2 + 2].ll; - x1.q = float128_chs(x2.q); - env->fregs[f1].ll = x1.ll.upper; - env->fregs[f1 + 2].ll = x1.ll.lower; - return set_cc_nz_f128(x1.q); -} - -/* 32-bit FP addition RM */ -void HELPER(aeb)(uint32_t f1, uint32_t val) -{ - float32 v1 = env->fregs[f1].l.upper; - CPU_FloatU v2; - - v2.l = val; - HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __func__, - v1, f1, v2.f); - env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status); -} - -/* 32-bit FP division RM */ -void HELPER(deb)(uint32_t f1, uint32_t val) -{ - float32 v1 = env->fregs[f1].l.upper; - CPU_FloatU v2; - - v2.l = val; - HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __func__, - v1, f1, v2.f); - env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status); -} - -/* 32-bit FP multiplication RM */ -void HELPER(meeb)(uint32_t f1, uint32_t val) -{ - float32 v1 = env->fregs[f1].l.upper; - CPU_FloatU v2; - - v2.l = val; - HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __func__, - v1, f1, v2.f); - env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status); -} - -/* 32-bit FP compare RR */ -uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2) -{ - float32 v1 = env->fregs[f1].l.upper; - float32 v2 = env->fregs[f2].l.upper; - - HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __func__, - v1, f1, v2); - return set_cc_f32(v1, v2); -} - -/* 64-bit FP compare RR */ -uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2) -{ - float64 v1 = env->fregs[f1].d; - float64 v2 = env->fregs[f2].d; - - HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __func__, - v1, f1, v2); - return set_cc_f64(v1, v2); -} - -/* 128-bit FP compare RR */ -uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2) -{ - CPU_QuadU v1; - CPU_QuadU v2; - - v1.ll.upper = env->fregs[f1].ll; - v1.ll.lower = env->fregs[f1 + 2].ll; - v2.ll.upper = env->fregs[f2].ll; - v2.ll.lower = env->fregs[f2 + 2].ll; - - return float_comp_to_cc(float128_compare_quiet(v1.q, v2.q, - &env->fpu_status)); -} - -/* 64-bit FP compare RM */ -uint32_t HELPER(cdb)(uint32_t f1, uint64_t a2) -{ - float64 v1 = env->fregs[f1].d; - CPU_DoubleU v2; - - v2.ll = ldq(a2); - HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__, v1, - f1, v2.d); - return set_cc_f64(v1, v2.d); -} - -/* 64-bit FP addition RM */ -uint32_t HELPER(adb)(uint32_t f1, uint64_t a2) -{ - float64 v1 = env->fregs[f1].d; - CPU_DoubleU v2; - - v2.ll = ldq(a2); - HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __func__, - v1, f1, v2.d); - env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status); - return set_cc_nz_f64(v1); -} - -/* 32-bit FP subtraction RM */ -void HELPER(seb)(uint32_t f1, uint32_t val) -{ - float32 v1 = env->fregs[f1].l.upper; - CPU_FloatU v2; - - v2.l = val; - env->fregs[f1].l.upper = float32_sub(v1, v2.f, &env->fpu_status); -} - -/* 64-bit FP subtraction RM */ -uint32_t HELPER(sdb)(uint32_t f1, uint64_t a2) -{ - float64 v1 = env->fregs[f1].d; - CPU_DoubleU v2; - - v2.ll = ldq(a2); - env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status); - return set_cc_nz_f64(v1); -} - -/* 64-bit FP multiplication RM */ -void HELPER(mdb)(uint32_t f1, uint64_t a2) -{ - float64 v1 = env->fregs[f1].d; - CPU_DoubleU v2; - - v2.ll = ldq(a2); - HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __func__, - v1, f1, v2.d); - env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status); -} - -/* 64-bit FP division RM */ -void HELPER(ddb)(uint32_t f1, uint64_t a2) -{ - float64 v1 = env->fregs[f1].d; - CPU_DoubleU v2; - - v2.ll = ldq(a2); - HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __func__, - v1, f1, v2.d); - env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status); -} - -static void set_round_mode(int m3) -{ - switch (m3) { - case 0: - /* current mode */ - break; - case 1: - /* biased round no nearest */ - case 4: - /* round to nearest */ - set_float_rounding_mode(float_round_nearest_even, &env->fpu_status); - break; - case 5: - /* round to zero */ - set_float_rounding_mode(float_round_to_zero, &env->fpu_status); - break; - case 6: - /* round to +inf */ - set_float_rounding_mode(float_round_up, &env->fpu_status); - break; - case 7: - /* round to -inf */ - set_float_rounding_mode(float_round_down, &env->fpu_status); - break; - } -} - -/* convert 32-bit float to 64-bit int */ -uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3) -{ - float32 v2 = env->fregs[f2].l.upper; - - set_round_mode(m3); - env->regs[r1] = float32_to_int64(v2, &env->fpu_status); - return set_cc_nz_f32(v2); -} - -/* convert 64-bit float to 64-bit int */ -uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3) -{ - float64 v2 = env->fregs[f2].d; - - set_round_mode(m3); - env->regs[r1] = float64_to_int64(v2, &env->fpu_status); - return set_cc_nz_f64(v2); -} - -/* convert 128-bit float to 64-bit int */ -uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3) -{ - CPU_QuadU v2; - - v2.ll.upper = env->fregs[f2].ll; - v2.ll.lower = env->fregs[f2 + 2].ll; - set_round_mode(m3); - env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status); - if (float128_is_any_nan(v2.q)) { - return 3; - } else if (float128_is_zero(v2.q)) { - return 0; - } else if (float128_is_neg(v2.q)) { - return 1; - } else { - return 2; - } -} - -/* convert 32-bit float to 32-bit int */ -uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3) -{ - float32 v2 = env->fregs[f2].l.upper; - - set_round_mode(m3); - env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | - float32_to_int32(v2, &env->fpu_status); - return set_cc_nz_f32(v2); -} - -/* convert 64-bit float to 32-bit int */ -uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3) -{ - float64 v2 = env->fregs[f2].d; - - set_round_mode(m3); - env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | - float64_to_int32(v2, &env->fpu_status); - return set_cc_nz_f64(v2); -} - -/* convert 128-bit float to 32-bit int */ -uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3) -{ - CPU_QuadU v2; - - v2.ll.upper = env->fregs[f2].ll; - v2.ll.lower = env->fregs[f2 + 2].ll; - env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | - float128_to_int32(v2.q, &env->fpu_status); - return set_cc_nz_f128(v2.q); -} - -/* load 32-bit FP zero */ -void HELPER(lzer)(uint32_t f1) -{ - env->fregs[f1].l.upper = float32_zero; -} - -/* load 64-bit FP zero */ -void HELPER(lzdr)(uint32_t f1) -{ - env->fregs[f1].d = float64_zero; -} - -/* load 128-bit FP zero */ -void HELPER(lzxr)(uint32_t f1) -{ - CPU_QuadU x; - - x.q = float64_to_float128(float64_zero, &env->fpu_status); - env->fregs[f1].ll = x.ll.upper; - env->fregs[f1 + 1].ll = x.ll.lower; -} - -/* 128-bit FP subtraction RR */ -uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2) -{ - CPU_QuadU v1; - CPU_QuadU v2; - CPU_QuadU res; - - v1.ll.upper = env->fregs[f1].ll; - v1.ll.lower = env->fregs[f1 + 2].ll; - v2.ll.upper = env->fregs[f2].ll; - v2.ll.lower = env->fregs[f2 + 2].ll; - res.q = float128_sub(v1.q, v2.q, &env->fpu_status); - env->fregs[f1].ll = res.ll.upper; - env->fregs[f1 + 2].ll = res.ll.lower; - return set_cc_nz_f128(res.q); -} - -/* 128-bit FP addition RR */ -uint32_t HELPER(axbr)(uint32_t f1, uint32_t f2) -{ - CPU_QuadU v1; - CPU_QuadU v2; - CPU_QuadU res; - - v1.ll.upper = env->fregs[f1].ll; - v1.ll.lower = env->fregs[f1 + 2].ll; - v2.ll.upper = env->fregs[f2].ll; - v2.ll.lower = env->fregs[f2 + 2].ll; - res.q = float128_add(v1.q, v2.q, &env->fpu_status); - env->fregs[f1].ll = res.ll.upper; - env->fregs[f1 + 2].ll = res.ll.lower; - return set_cc_nz_f128(res.q); -} - -/* 32-bit FP multiplication RR */ -void HELPER(meebr)(uint32_t f1, uint32_t f2) -{ - env->fregs[f1].l.upper = float32_mul(env->fregs[f1].l.upper, - env->fregs[f2].l.upper, - &env->fpu_status); -} - -/* 64-bit FP division RR */ -void HELPER(ddbr)(uint32_t f1, uint32_t f2) -{ - env->fregs[f1].d = float64_div(env->fregs[f1].d, env->fregs[f2].d, - &env->fpu_status); -} - -/* 64-bit FP multiply and add RM */ -void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3) -{ - CPU_DoubleU v2; - - HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __func__, f1, a2, f3); - v2.ll = ldq(a2); - env->fregs[f1].d = float64_add(env->fregs[f1].d, - float64_mul(v2.d, env->fregs[f3].d, - &env->fpu_status), - &env->fpu_status); -} - -/* 64-bit FP multiply and add RR */ -void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2) -{ - HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3); - env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d, - env->fregs[f3].d, - &env->fpu_status), - env->fregs[f1].d, &env->fpu_status); -} - -/* 64-bit FP multiply and subtract RR */ -void HELPER(msdbr)(uint32_t f1, uint32_t f3, uint32_t f2) -{ - HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3); - env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d, - env->fregs[f3].d, - &env->fpu_status), - env->fregs[f1].d, &env->fpu_status); -} - -/* 32-bit FP multiply and add RR */ -void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2) -{ - env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper, - float32_mul(env->fregs[f2].l.upper, - env->fregs[f3].l.upper, - &env->fpu_status), - &env->fpu_status); -} - -/* convert 32-bit float to 64-bit float */ -void HELPER(ldeb)(uint32_t f1, uint64_t a2) -{ - uint32_t v2; - - v2 = ldl(a2); - env->fregs[f1].d = float32_to_float64(v2, - &env->fpu_status); -} - -/* convert 64-bit float to 128-bit float */ -void HELPER(lxdb)(uint32_t f1, uint64_t a2) -{ - CPU_DoubleU v2; - CPU_QuadU v1; - - v2.ll = ldq(a2); - v1.q = float64_to_float128(v2.d, &env->fpu_status); - env->fregs[f1].ll = v1.ll.upper; - env->fregs[f1 + 2].ll = v1.ll.lower; -} - -/* test data class 32-bit */ -uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2) -{ - float32 v1 = env->fregs[f1].l.upper; - int neg = float32_is_neg(v1); - uint32_t cc = 0; - - HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, (long)v1, m2, neg); - if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) || - (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) || - (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || - (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { - cc = 1; - } else if (m2 & (1 << (9-neg))) { - /* assume normalized number */ - cc = 1; - } - - /* FIXME: denormalized? */ - return cc; -} - -/* test data class 64-bit */ -uint32_t HELPER(tcdb)(uint32_t f1, uint64_t m2) -{ - float64 v1 = env->fregs[f1].d; - int neg = float64_is_neg(v1); - uint32_t cc = 0; - - HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, v1, m2, neg); - if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) || - (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) || - (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || - (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { - cc = 1; - } else if (m2 & (1 << (9-neg))) { - /* assume normalized number */ - cc = 1; - } - /* FIXME: denormalized? */ - return cc; -} - -/* test data class 128-bit */ -uint32_t HELPER(tcxb)(uint32_t f1, uint64_t m2) -{ - CPU_QuadU v1; - uint32_t cc = 0; - int neg; - - v1.ll.upper = env->fregs[f1].ll; - v1.ll.lower = env->fregs[f1 + 2].ll; - - neg = float128_is_neg(v1.q); - if ((float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) || - (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) || - (float128_is_any_nan(v1.q) && (m2 & (1 << (3-neg)))) || - (float128_is_signaling_nan(v1.q) && (m2 & (1 << (1-neg))))) { - cc = 1; - } else if (m2 & (1 << (9-neg))) { - /* assume normalized number */ - cc = 1; - } - /* FIXME: denormalized? */ - return cc; -} - /* find leftmost one */ uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2) { @@ -1795,12 +999,6 @@ uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2) } } -/* square root 64-bit RR */ -void HELPER(sqdbr)(uint32_t f1, uint32_t f2) -{ - env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status); -} - /* checksum */ void HELPER(cksm)(uint32_t r1, uint32_t r2) { diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 1c1baf5342..c370df3b61 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -667,16 +667,11 @@ static void set_cc_cmp_f32_i64(DisasContext *s, TCGv_i32 v1, TCGv_i64 v2) s->cc_op = CC_OP_LTGT_F32; } -static void set_cc_nz_f32(DisasContext *s, TCGv_i32 v1) +static void gen_set_cc_nz_f32(DisasContext *s, TCGv_i32 v1) { gen_op_update1_cc_i32(s, CC_OP_NZ_F32, v1); } -static inline void set_cc_nz_f64(DisasContext *s, TCGv_i64 v1) -{ - gen_op_update1_cc_i64(s, CC_OP_NZ_F64, v1); -} - /* CC value is in env->cc_op */ static inline void set_cc_static(DisasContext *s) { @@ -2235,7 +2230,7 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2, tcg_temp_free_i32(tmp32); tmp32 = load_freg32(r1); - set_cc_nz_f32(s, tmp32); + gen_set_cc_nz_f32(s, tmp32); tcg_temp_free_i32(tmp32); break; case 0xb: /* SEB R1,D2(X2,B2) [RXE] */ @@ -2248,7 +2243,7 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2, tcg_temp_free_i32(tmp32); tmp32 = load_freg32(r1); - set_cc_nz_f32(s, tmp32); + gen_set_cc_nz_f32(s, tmp32); tcg_temp_free_i32(tmp32); break; case 0xd: /* DEB R1,D2(X2,B2) [RXE] */ From a78b0504e8d5487fca77b6b0cd8d3c98b9bace8c Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 07:33:32 +0000 Subject: [PATCH 0219/2270] target-s390x: split condition code helpers Move condition code helpers to cc_helper.c. Signed-off-by: Blue Swirl Signed-off-by: Alexander Graf --- target-s390x/Makefile.objs | 3 +- target-s390x/cc_helper.c | 551 +++++++++++++++++++++++++++++++++++++ target-s390x/cpu.h | 3 + target-s390x/op_helper.c | 522 +---------------------------------- 4 files changed, 557 insertions(+), 522 deletions(-) create mode 100644 target-s390x/cc_helper.c diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs index 23b3bd9989..f9437d615c 100644 --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -1,7 +1,8 @@ obj-y += translate.o op_helper.o helper.o cpu.o interrupt.o -obj-y += fpu_helper.o +obj-y += fpu_helper.o cc_helper.o obj-$(CONFIG_SOFTMMU) += machine.o obj-$(CONFIG_KVM) += kvm.o $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/fpu_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) +$(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c new file mode 100644 index 0000000000..2ac1659625 --- /dev/null +++ b/target-s390x/cc_helper.c @@ -0,0 +1,551 @@ +/* + * S/390 condition code helper routines + * + * Copyright (c) 2009 Ulrich Hecht + * Copyright (c) 2009 Alexander Graf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "cpu.h" +#include "dyngen-exec.h" +#include "helper.h" + +/* #define DEBUG_HELPER */ +#ifdef DEBUG_HELPER +#define HELPER_LOG(x...) qemu_log(x) +#else +#define HELPER_LOG(x...) +#endif + +static inline uint32_t cc_calc_ltgt_32(CPUS390XState *env, int32_t src, + int32_t dst) +{ + if (src == dst) { + return 0; + } else if (src < dst) { + return 1; + } else { + return 2; + } +} + +static inline uint32_t cc_calc_ltgt0_32(CPUS390XState *env, int32_t dst) +{ + return cc_calc_ltgt_32(env, dst, 0); +} + +static inline uint32_t cc_calc_ltgt_64(CPUS390XState *env, int64_t src, + int64_t dst) +{ + if (src == dst) { + return 0; + } else if (src < dst) { + return 1; + } else { + return 2; + } +} + +static inline uint32_t cc_calc_ltgt0_64(CPUS390XState *env, int64_t dst) +{ + return cc_calc_ltgt_64(env, dst, 0); +} + +static inline uint32_t cc_calc_ltugtu_32(CPUS390XState *env, uint32_t src, + uint32_t dst) +{ + if (src == dst) { + return 0; + } else if (src < dst) { + return 1; + } else { + return 2; + } +} + +static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src, + uint64_t dst) +{ + if (src == dst) { + return 0; + } else if (src < dst) { + return 1; + } else { + return 2; + } +} + +static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, + uint32_t mask) +{ + uint16_t r = val & mask; + + HELPER_LOG("%s: val 0x%x mask 0x%x\n", __func__, val, mask); + if (r == 0 || mask == 0) { + return 0; + } else if (r == mask) { + return 3; + } else { + return 1; + } +} + +/* set condition code for test under mask */ +static inline uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val, + uint32_t mask) +{ + uint16_t r = val & mask; + + HELPER_LOG("%s: val 0x%lx mask 0x%x r 0x%x\n", __func__, val, mask, r); + if (r == 0 || mask == 0) { + return 0; + } else if (r == mask) { + return 3; + } else { + while (!(mask & 0x8000)) { + mask <<= 1; + val <<= 1; + } + if (val & 0x8000) { + return 2; + } else { + return 1; + } + } +} + +static inline uint32_t cc_calc_nz(CPUS390XState *env, uint64_t dst) +{ + return !!dst; +} + +static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1, + int64_t a2, int64_t ar) +{ + if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) { + return 3; /* overflow */ + } else { + if (ar < 0) { + return 1; + } else if (ar > 0) { + return 2; + } else { + return 0; + } + } +} + +static inline uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1, + uint64_t a2, uint64_t ar) +{ + if (ar == 0) { + if (a1) { + return 2; + } else { + return 0; + } + } else { + if (ar < a1 || ar < a2) { + return 3; + } else { + return 1; + } + } +} + +static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1, + int64_t a2, int64_t ar) +{ + if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) { + return 3; /* overflow */ + } else { + if (ar < 0) { + return 1; + } else if (ar > 0) { + return 2; + } else { + return 0; + } + } +} + +static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1, + uint64_t a2, uint64_t ar) +{ + if (ar == 0) { + return 2; + } else { + if (a2 > a1) { + return 1; + } else { + return 3; + } + } +} + +static inline uint32_t cc_calc_abs_64(CPUS390XState *env, int64_t dst) +{ + if ((uint64_t)dst == 0x8000000000000000ULL) { + return 3; + } else if (dst) { + return 1; + } else { + return 0; + } +} + +static inline uint32_t cc_calc_nabs_64(CPUS390XState *env, int64_t dst) +{ + return !!dst; +} + +static inline uint32_t cc_calc_comp_64(CPUS390XState *env, int64_t dst) +{ + if ((uint64_t)dst == 0x8000000000000000ULL) { + return 3; + } else if (dst < 0) { + return 1; + } else if (dst > 0) { + return 2; + } else { + return 0; + } +} + + +static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1, + int32_t a2, int32_t ar) +{ + if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) { + return 3; /* overflow */ + } else { + if (ar < 0) { + return 1; + } else if (ar > 0) { + return 2; + } else { + return 0; + } + } +} + +static inline uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1, + uint32_t a2, uint32_t ar) +{ + if (ar == 0) { + if (a1) { + return 2; + } else { + return 0; + } + } else { + if (ar < a1 || ar < a2) { + return 3; + } else { + return 1; + } + } +} + +static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1, + int32_t a2, int32_t ar) +{ + if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) { + return 3; /* overflow */ + } else { + if (ar < 0) { + return 1; + } else if (ar > 0) { + return 2; + } else { + return 0; + } + } +} + +static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1, + uint32_t a2, uint32_t ar) +{ + if (ar == 0) { + return 2; + } else { + if (a2 > a1) { + return 1; + } else { + return 3; + } + } +} + +static inline uint32_t cc_calc_abs_32(CPUS390XState *env, int32_t dst) +{ + if ((uint32_t)dst == 0x80000000UL) { + return 3; + } else if (dst) { + return 1; + } else { + return 0; + } +} + +static inline uint32_t cc_calc_nabs_32(CPUS390XState *env, int32_t dst) +{ + return !!dst; +} + +static inline uint32_t cc_calc_comp_32(CPUS390XState *env, int32_t dst) +{ + if ((uint32_t)dst == 0x80000000UL) { + return 3; + } else if (dst < 0) { + return 1; + } else if (dst > 0) { + return 2; + } else { + return 0; + } +} + +/* calculate condition code for insert character under mask insn */ +static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask, + uint32_t val) +{ + uint32_t cc; + + HELPER_LOG("%s: mask 0x%x val %d\n", __func__, mask, val); + if (mask == 0xf) { + if (!val) { + return 0; + } else if (val & 0x80000000) { + return 1; + } else { + return 2; + } + } + + if (!val || !mask) { + cc = 0; + } else { + while (mask != 1) { + mask >>= 1; + val >>= 8; + } + if (val & 0x80) { + cc = 1; + } else { + cc = 2; + } + } + return cc; +} + +static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src, + uint64_t shift) +{ + uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift); + uint64_t match, r; + + /* check if the sign bit stays the same */ + if (src & (1ULL << 63)) { + match = mask; + } else { + match = 0; + } + + if ((src & mask) != match) { + /* overflow */ + return 3; + } + + r = ((src << shift) & ((1ULL << 63) - 1)) | (src & (1ULL << 63)); + + if ((int64_t)r == 0) { + return 0; + } else if ((int64_t)r < 0) { + return 1; + } + + return 2; +} + + +static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, + uint64_t src, uint64_t dst, uint64_t vr) +{ + uint32_t r = 0; + + switch (cc_op) { + case CC_OP_CONST0: + case CC_OP_CONST1: + case CC_OP_CONST2: + case CC_OP_CONST3: + /* cc_op value _is_ cc */ + r = cc_op; + break; + case CC_OP_LTGT0_32: + r = cc_calc_ltgt0_32(env, dst); + break; + case CC_OP_LTGT0_64: + r = cc_calc_ltgt0_64(env, dst); + break; + case CC_OP_LTGT_32: + r = cc_calc_ltgt_32(env, src, dst); + break; + case CC_OP_LTGT_64: + r = cc_calc_ltgt_64(env, src, dst); + break; + case CC_OP_LTUGTU_32: + r = cc_calc_ltugtu_32(env, src, dst); + break; + case CC_OP_LTUGTU_64: + r = cc_calc_ltugtu_64(env, src, dst); + break; + case CC_OP_TM_32: + r = cc_calc_tm_32(env, src, dst); + break; + case CC_OP_TM_64: + r = cc_calc_tm_64(env, src, dst); + break; + case CC_OP_NZ: + r = cc_calc_nz(env, dst); + break; + case CC_OP_ADD_64: + r = cc_calc_add_64(env, src, dst, vr); + break; + case CC_OP_ADDU_64: + r = cc_calc_addu_64(env, src, dst, vr); + break; + case CC_OP_SUB_64: + r = cc_calc_sub_64(env, src, dst, vr); + break; + case CC_OP_SUBU_64: + r = cc_calc_subu_64(env, src, dst, vr); + break; + case CC_OP_ABS_64: + r = cc_calc_abs_64(env, dst); + break; + case CC_OP_NABS_64: + r = cc_calc_nabs_64(env, dst); + break; + case CC_OP_COMP_64: + r = cc_calc_comp_64(env, dst); + break; + + case CC_OP_ADD_32: + r = cc_calc_add_32(env, src, dst, vr); + break; + case CC_OP_ADDU_32: + r = cc_calc_addu_32(env, src, dst, vr); + break; + case CC_OP_SUB_32: + r = cc_calc_sub_32(env, src, dst, vr); + break; + case CC_OP_SUBU_32: + r = cc_calc_subu_32(env, src, dst, vr); + break; + case CC_OP_ABS_32: + r = cc_calc_abs_64(env, dst); + break; + case CC_OP_NABS_32: + r = cc_calc_nabs_64(env, dst); + break; + case CC_OP_COMP_32: + r = cc_calc_comp_32(env, dst); + break; + + case CC_OP_ICM: + r = cc_calc_icm_32(env, src, dst); + break; + case CC_OP_SLAG: + r = cc_calc_slag(env, src, dst); + break; + + case CC_OP_LTGT_F32: + r = set_cc_f32(src, dst); + break; + case CC_OP_LTGT_F64: + r = set_cc_f64(src, dst); + break; + case CC_OP_NZ_F32: + r = set_cc_nz_f32(dst); + break; + case CC_OP_NZ_F64: + r = set_cc_nz_f64(dst); + break; + + default: + cpu_abort(env, "Unknown CC operation: %s\n", cc_name(cc_op)); + } + + HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __func__, + cc_name(cc_op), src, dst, vr, r); + return r; +} + +uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst, + uint64_t vr) +{ + return do_calc_cc(env, cc_op, src, dst, vr); +} + +uint32_t HELPER(calc_cc)(uint32_t cc_op, uint64_t src, uint64_t dst, + uint64_t vr) +{ + return do_calc_cc(env, cc_op, src, dst, vr); +} + +/* insert psw mask and condition code into r1 */ +void HELPER(ipm)(uint32_t cc, uint32_t r1) +{ + uint64_t r = env->regs[r1]; + + r &= 0xffffffff00ffffffULL; + r |= (cc << 28) | ((env->psw.mask >> 40) & 0xf); + env->regs[r1] = r; + HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __func__, + cc, env->psw.mask, r); +} + +#ifndef CONFIG_USER_ONLY +void HELPER(load_psw)(uint64_t mask, uint64_t addr) +{ + load_psw(env, mask, addr); + cpu_loop_exit(env); +} + +void HELPER(sacf)(uint64_t a1) +{ + HELPER_LOG("%s: %16" PRIx64 "\n", __func__, a1); + + switch (a1 & 0xf00) { + case 0x000: + env->psw.mask &= ~PSW_MASK_ASC; + env->psw.mask |= PSW_ASC_PRIMARY; + break; + case 0x100: + env->psw.mask &= ~PSW_MASK_ASC; + env->psw.mask |= PSW_ASC_SECONDARY; + break; + case 0x300: + env->psw.mask &= ~PSW_MASK_ASC; + env->psw.mask |= PSW_ASC_HOME; + break; + default: + qemu_log("unknown sacf mode: %" PRIx64 "\n", a1); + program_interrupt(env, PGM_SPECIFICATION, 2); + break; + } +} +#endif diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index b4620c502d..97fde5e2ec 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -1005,4 +1005,7 @@ uint32_t set_cc_f64(float64 v1, float64 v2); uint32_t set_cc_nz_f32(float32 v); uint32_t set_cc_nz_f64(float64 v); +/* op_helper.c */ +void program_interrupt(CPUS390XState *env, uint32_t code, int ilc); + #endif diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c index 270bf14f0b..eced89089c 100644 --- a/target-s390x/op_helper.c +++ b/target-s390x/op_helper.c @@ -779,18 +779,6 @@ uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask) return cc; } -/* insert psw mask and condition code into r1 */ -void HELPER(ipm)(uint32_t cc, uint32_t r1) -{ - uint64_t r = env->regs[r1]; - - r &= 0xffffffff00ffffffULL; - r |= (cc << 28) | ((env->psw.mask >> 40) & 0xf); - env->regs[r1] = r; - HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __func__, - cc, env->psw.mask, r); -} - /* load access registers r1 to r3 from memory at a2 */ void HELPER(lam)(uint32_t r1, uint64_t a2, uint32_t r3) { @@ -1038,483 +1026,6 @@ void HELPER(cksm)(uint32_t r1, uint32_t r2) ((uint32_t)cksm + (cksm >> 32)); } -static inline uint32_t cc_calc_ltgt_32(CPUS390XState *env, int32_t src, - int32_t dst) -{ - if (src == dst) { - return 0; - } else if (src < dst) { - return 1; - } else { - return 2; - } -} - -static inline uint32_t cc_calc_ltgt0_32(CPUS390XState *env, int32_t dst) -{ - return cc_calc_ltgt_32(env, dst, 0); -} - -static inline uint32_t cc_calc_ltgt_64(CPUS390XState *env, int64_t src, - int64_t dst) -{ - if (src == dst) { - return 0; - } else if (src < dst) { - return 1; - } else { - return 2; - } -} - -static inline uint32_t cc_calc_ltgt0_64(CPUS390XState *env, int64_t dst) -{ - return cc_calc_ltgt_64(env, dst, 0); -} - -static inline uint32_t cc_calc_ltugtu_32(CPUS390XState *env, uint32_t src, - uint32_t dst) -{ - if (src == dst) { - return 0; - } else if (src < dst) { - return 1; - } else { - return 2; - } -} - -static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src, - uint64_t dst) -{ - if (src == dst) { - return 0; - } else if (src < dst) { - return 1; - } else { - return 2; - } -} - -static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, - uint32_t mask) -{ - uint16_t r = val & mask; - - HELPER_LOG("%s: val 0x%x mask 0x%x\n", __func__, val, mask); - if (r == 0 || mask == 0) { - return 0; - } else if (r == mask) { - return 3; - } else { - return 1; - } -} - -/* set condition code for test under mask */ -static inline uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val, - uint32_t mask) -{ - uint16_t r = val & mask; - - HELPER_LOG("%s: val 0x%lx mask 0x%x r 0x%x\n", __func__, val, mask, r); - if (r == 0 || mask == 0) { - return 0; - } else if (r == mask) { - return 3; - } else { - while (!(mask & 0x8000)) { - mask <<= 1; - val <<= 1; - } - if (val & 0x8000) { - return 2; - } else { - return 1; - } - } -} - -static inline uint32_t cc_calc_nz(CPUS390XState *env, uint64_t dst) -{ - return !!dst; -} - -static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1, - int64_t a2, int64_t ar) -{ - if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) { - return 3; /* overflow */ - } else { - if (ar < 0) { - return 1; - } else if (ar > 0) { - return 2; - } else { - return 0; - } - } -} - -static inline uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1, - uint64_t a2, uint64_t ar) -{ - if (ar == 0) { - if (a1) { - return 2; - } else { - return 0; - } - } else { - if (ar < a1 || ar < a2) { - return 3; - } else { - return 1; - } - } -} - -static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1, - int64_t a2, int64_t ar) -{ - if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) { - return 3; /* overflow */ - } else { - if (ar < 0) { - return 1; - } else if (ar > 0) { - return 2; - } else { - return 0; - } - } -} - -static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1, - uint64_t a2, uint64_t ar) -{ - if (ar == 0) { - return 2; - } else { - if (a2 > a1) { - return 1; - } else { - return 3; - } - } -} - -static inline uint32_t cc_calc_abs_64(CPUS390XState *env, int64_t dst) -{ - if ((uint64_t)dst == 0x8000000000000000ULL) { - return 3; - } else if (dst) { - return 1; - } else { - return 0; - } -} - -static inline uint32_t cc_calc_nabs_64(CPUS390XState *env, int64_t dst) -{ - return !!dst; -} - -static inline uint32_t cc_calc_comp_64(CPUS390XState *env, int64_t dst) -{ - if ((uint64_t)dst == 0x8000000000000000ULL) { - return 3; - } else if (dst < 0) { - return 1; - } else if (dst > 0) { - return 2; - } else { - return 0; - } -} - - -static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1, - int32_t a2, int32_t ar) -{ - if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) { - return 3; /* overflow */ - } else { - if (ar < 0) { - return 1; - } else if (ar > 0) { - return 2; - } else { - return 0; - } - } -} - -static inline uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1, - uint32_t a2, uint32_t ar) -{ - if (ar == 0) { - if (a1) { - return 2; - } else { - return 0; - } - } else { - if (ar < a1 || ar < a2) { - return 3; - } else { - return 1; - } - } -} - -static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1, - int32_t a2, int32_t ar) -{ - if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) { - return 3; /* overflow */ - } else { - if (ar < 0) { - return 1; - } else if (ar > 0) { - return 2; - } else { - return 0; - } - } -} - -static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1, - uint32_t a2, uint32_t ar) -{ - if (ar == 0) { - return 2; - } else { - if (a2 > a1) { - return 1; - } else { - return 3; - } - } -} - -static inline uint32_t cc_calc_abs_32(CPUS390XState *env, int32_t dst) -{ - if ((uint32_t)dst == 0x80000000UL) { - return 3; - } else if (dst) { - return 1; - } else { - return 0; - } -} - -static inline uint32_t cc_calc_nabs_32(CPUS390XState *env, int32_t dst) -{ - return !!dst; -} - -static inline uint32_t cc_calc_comp_32(CPUS390XState *env, int32_t dst) -{ - if ((uint32_t)dst == 0x80000000UL) { - return 3; - } else if (dst < 0) { - return 1; - } else if (dst > 0) { - return 2; - } else { - return 0; - } -} - -/* calculate condition code for insert character under mask insn */ -static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask, - uint32_t val) -{ - uint32_t cc; - - HELPER_LOG("%s: mask 0x%x val %d\n", __func__, mask, val); - if (mask == 0xf) { - if (!val) { - return 0; - } else if (val & 0x80000000) { - return 1; - } else { - return 2; - } - } - - if (!val || !mask) { - cc = 0; - } else { - while (mask != 1) { - mask >>= 1; - val >>= 8; - } - if (val & 0x80) { - cc = 1; - } else { - cc = 2; - } - } - return cc; -} - -static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src, - uint64_t shift) -{ - uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift); - uint64_t match, r; - - /* check if the sign bit stays the same */ - if (src & (1ULL << 63)) { - match = mask; - } else { - match = 0; - } - - if ((src & mask) != match) { - /* overflow */ - return 3; - } - - r = ((src << shift) & ((1ULL << 63) - 1)) | (src & (1ULL << 63)); - - if ((int64_t)r == 0) { - return 0; - } else if ((int64_t)r < 0) { - return 1; - } - - return 2; -} - - -static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, - uint64_t src, uint64_t dst, uint64_t vr) -{ - uint32_t r = 0; - - switch (cc_op) { - case CC_OP_CONST0: - case CC_OP_CONST1: - case CC_OP_CONST2: - case CC_OP_CONST3: - /* cc_op value _is_ cc */ - r = cc_op; - break; - case CC_OP_LTGT0_32: - r = cc_calc_ltgt0_32(env, dst); - break; - case CC_OP_LTGT0_64: - r = cc_calc_ltgt0_64(env, dst); - break; - case CC_OP_LTGT_32: - r = cc_calc_ltgt_32(env, src, dst); - break; - case CC_OP_LTGT_64: - r = cc_calc_ltgt_64(env, src, dst); - break; - case CC_OP_LTUGTU_32: - r = cc_calc_ltugtu_32(env, src, dst); - break; - case CC_OP_LTUGTU_64: - r = cc_calc_ltugtu_64(env, src, dst); - break; - case CC_OP_TM_32: - r = cc_calc_tm_32(env, src, dst); - break; - case CC_OP_TM_64: - r = cc_calc_tm_64(env, src, dst); - break; - case CC_OP_NZ: - r = cc_calc_nz(env, dst); - break; - case CC_OP_ADD_64: - r = cc_calc_add_64(env, src, dst, vr); - break; - case CC_OP_ADDU_64: - r = cc_calc_addu_64(env, src, dst, vr); - break; - case CC_OP_SUB_64: - r = cc_calc_sub_64(env, src, dst, vr); - break; - case CC_OP_SUBU_64: - r = cc_calc_subu_64(env, src, dst, vr); - break; - case CC_OP_ABS_64: - r = cc_calc_abs_64(env, dst); - break; - case CC_OP_NABS_64: - r = cc_calc_nabs_64(env, dst); - break; - case CC_OP_COMP_64: - r = cc_calc_comp_64(env, dst); - break; - - case CC_OP_ADD_32: - r = cc_calc_add_32(env, src, dst, vr); - break; - case CC_OP_ADDU_32: - r = cc_calc_addu_32(env, src, dst, vr); - break; - case CC_OP_SUB_32: - r = cc_calc_sub_32(env, src, dst, vr); - break; - case CC_OP_SUBU_32: - r = cc_calc_subu_32(env, src, dst, vr); - break; - case CC_OP_ABS_32: - r = cc_calc_abs_64(env, dst); - break; - case CC_OP_NABS_32: - r = cc_calc_nabs_64(env, dst); - break; - case CC_OP_COMP_32: - r = cc_calc_comp_32(env, dst); - break; - - case CC_OP_ICM: - r = cc_calc_icm_32(env, src, dst); - break; - case CC_OP_SLAG: - r = cc_calc_slag(env, src, dst); - break; - - case CC_OP_LTGT_F32: - r = set_cc_f32(src, dst); - break; - case CC_OP_LTGT_F64: - r = set_cc_f64(src, dst); - break; - case CC_OP_NZ_F32: - r = set_cc_nz_f32(dst); - break; - case CC_OP_NZ_F64: - r = set_cc_nz_f64(dst); - break; - - default: - cpu_abort(env, "Unknown CC operation: %s\n", cc_name(cc_op)); - } - - HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __func__, - cc_name(cc_op), src, dst, vr, r); - return r; -} - -uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst, - uint64_t vr) -{ - return do_calc_cc(env, cc_op, src, dst, vr); -} - -uint32_t HELPER(calc_cc)(uint32_t cc_op, uint64_t src, uint64_t dst, - uint64_t vr) -{ - return do_calc_cc(env, cc_op, src, dst, vr); -} - uint64_t HELPER(cvd)(int32_t bin) { /* positive 0 */ @@ -1594,14 +1105,7 @@ void HELPER(tr)(uint32_t len, uint64_t array, uint64_t trans) } #ifndef CONFIG_USER_ONLY - -void HELPER(load_psw)(uint64_t mask, uint64_t addr) -{ - load_psw(env, mask, addr); - cpu_loop_exit(env); -} - -static void program_interrupt(CPUS390XState *env, uint32_t code, int ilc) +void program_interrupt(CPUS390XState *env, uint32_t code, int ilc) { qemu_log("program interrupt at %#" PRIx64 "\n", env->psw.addr); @@ -2175,30 +1679,6 @@ uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr) return cc; } -void HELPER(sacf)(uint64_t a1) -{ - HELPER_LOG("%s: %16" PRIx64 "\n", __func__, a1); - - switch (a1 & 0xf00) { - case 0x000: - env->psw.mask &= ~PSW_MASK_ASC; - env->psw.mask |= PSW_ASC_PRIMARY; - break; - case 0x100: - env->psw.mask &= ~PSW_MASK_ASC; - env->psw.mask |= PSW_ASC_SECONDARY; - break; - case 0x300: - env->psw.mask &= ~PSW_MASK_ASC; - env->psw.mask |= PSW_ASC_HOME; - break; - default: - qemu_log("unknown sacf mode: %" PRIx64 "\n", a1); - program_interrupt(env, PGM_SPECIFICATION, 2); - break; - } -} - /* invalidate pte */ void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr) { From fc8d72c2d34afd6789e8c4374d275a5f69c603f1 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 07:33:33 +0000 Subject: [PATCH 0220/2270] target-s390x: split integer helpers Move integer helpers to int_helper.c. Signed-off-by: Blue Swirl Signed-off-by: Alexander Graf --- target-s390x/Makefile.objs | 3 +- target-s390x/int_helper.c | 201 +++++++++++++++++++++++++++++++++++++ target-s390x/op_helper.c | 170 ------------------------------- 3 files changed, 203 insertions(+), 171 deletions(-) create mode 100644 target-s390x/int_helper.c diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs index f9437d615c..e8f66e93a7 100644 --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -1,8 +1,9 @@ obj-y += translate.o op_helper.o helper.o cpu.o interrupt.o -obj-y += fpu_helper.o cc_helper.o +obj-y += int_helper.o fpu_helper.o cc_helper.o obj-$(CONFIG_SOFTMMU) += machine.o obj-$(CONFIG_KVM) += kvm.o $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) +$(obj)/int_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/fpu_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c new file mode 100644 index 0000000000..e2eeb07575 --- /dev/null +++ b/target-s390x/int_helper.c @@ -0,0 +1,201 @@ +/* + * S/390 integer helper routines + * + * Copyright (c) 2009 Ulrich Hecht + * Copyright (c) 2009 Alexander Graf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "cpu.h" +#include "dyngen-exec.h" +#include "host-utils.h" +#include "helper.h" + +/* #define DEBUG_HELPER */ +#ifdef DEBUG_HELPER +#define HELPER_LOG(x...) qemu_log(x) +#else +#define HELPER_LOG(x...) +#endif + +/* 64/64 -> 128 unsigned multiplication */ +void HELPER(mlg)(uint32_t r1, uint64_t v2) +{ +#if HOST_LONG_BITS == 64 && defined(__GNUC__) + /* assuming 64-bit hosts have __uint128_t */ + __uint128_t res = (__uint128_t)env->regs[r1 + 1]; + + res *= (__uint128_t)v2; + env->regs[r1] = (uint64_t)(res >> 64); + env->regs[r1 + 1] = (uint64_t)res; +#else + mulu64(&env->regs[r1 + 1], &env->regs[r1], env->regs[r1 + 1], v2); +#endif +} + +/* 128 -> 64/64 unsigned division */ +void HELPER(dlg)(uint32_t r1, uint64_t v2) +{ + uint64_t divisor = v2; + + if (!env->regs[r1]) { + /* 64 -> 64/64 case */ + env->regs[r1] = env->regs[r1 + 1] % divisor; + env->regs[r1 + 1] = env->regs[r1 + 1] / divisor; + return; + } else { +#if HOST_LONG_BITS == 64 && defined(__GNUC__) + /* assuming 64-bit hosts have __uint128_t */ + __uint128_t dividend = (((__uint128_t)env->regs[r1]) << 64) | + (env->regs[r1 + 1]); + __uint128_t quotient = dividend / divisor; + __uint128_t remainder = dividend % divisor; + + env->regs[r1 + 1] = quotient; + env->regs[r1] = remainder; +#else + /* 32-bit hosts would need special wrapper functionality - just abort if + we encounter such a case; it's very unlikely anyways. */ + cpu_abort(env, "128 -> 64/64 division not implemented\n"); +#endif + } +} + +/* absolute value 32-bit */ +uint32_t HELPER(abs_i32)(int32_t val) +{ + if (val < 0) { + return -val; + } else { + return val; + } +} + +/* negative absolute value 32-bit */ +int32_t HELPER(nabs_i32)(int32_t val) +{ + if (val < 0) { + return val; + } else { + return -val; + } +} + +/* absolute value 64-bit */ +uint64_t HELPER(abs_i64)(int64_t val) +{ + HELPER_LOG("%s: val 0x%" PRIx64 "\n", __func__, val); + + if (val < 0) { + return -val; + } else { + return val; + } +} + +/* negative absolute value 64-bit */ +int64_t HELPER(nabs_i64)(int64_t val) +{ + if (val < 0) { + return val; + } else { + return -val; + } +} + +/* add with carry 32-bit unsigned */ +uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2) +{ + uint32_t res; + + res = v1 + v2; + if (cc & 2) { + res++; + } + + return res; +} + +/* subtract unsigned v2 from v1 with borrow */ +uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2) +{ + uint32_t v1 = env->regs[r1]; + uint32_t res = v1 + (~v2) + (cc >> 1); + + env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | res; + if (cc & 2) { + /* borrow */ + return v1 ? 1 : 0; + } else { + return v1 ? 3 : 2; + } +} + +/* subtract unsigned v2 from v1 with borrow */ +uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2) +{ + uint64_t res = v1 + (~v2) + (cc >> 1); + + env->regs[r1] = res; + if (cc & 2) { + /* borrow */ + return v1 ? 1 : 0; + } else { + return v1 ? 3 : 2; + } +} + +/* find leftmost one */ +uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2) +{ + uint64_t res = 0; + uint64_t ov2 = v2; + + while (!(v2 & 0x8000000000000000ULL) && v2) { + v2 <<= 1; + res++; + } + + if (!v2) { + env->regs[r1] = 64; + env->regs[r1 + 1] = 0; + return 0; + } else { + env->regs[r1] = res; + env->regs[r1 + 1] = ov2 & ~(0x8000000000000000ULL >> res); + return 2; + } +} + +uint64_t HELPER(cvd)(int32_t bin) +{ + /* positive 0 */ + uint64_t dec = 0x0c; + int shift = 4; + + if (bin < 0) { + bin = -bin; + dec = 0x0d; + } + + for (shift = 4; (shift < 64) && bin; shift += 4) { + int current_number = bin % 10; + + dec |= (current_number) << shift; + bin /= 10; + } + + return dec; +} diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c index eced89089c..3b8b997abf 100644 --- a/target-s390x/op_helper.c +++ b/target-s390x/op_helper.c @@ -352,49 +352,6 @@ void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr) HELPER_LOG("\n"); } -/* 64/64 -> 128 unsigned multiplication */ -void HELPER(mlg)(uint32_t r1, uint64_t v2) -{ -#if HOST_LONG_BITS == 64 && defined(__GNUC__) - /* assuming 64-bit hosts have __uint128_t */ - __uint128_t res = (__uint128_t)env->regs[r1 + 1]; - - res *= (__uint128_t)v2; - env->regs[r1] = (uint64_t)(res >> 64); - env->regs[r1 + 1] = (uint64_t)res; -#else - mulu64(&env->regs[r1 + 1], &env->regs[r1], env->regs[r1 + 1], v2); -#endif -} - -/* 128 -> 64/64 unsigned division */ -void HELPER(dlg)(uint32_t r1, uint64_t v2) -{ - uint64_t divisor = v2; - - if (!env->regs[r1]) { - /* 64 -> 64/64 case */ - env->regs[r1] = env->regs[r1 + 1] % divisor; - env->regs[r1 + 1] = env->regs[r1 + 1] / divisor; - return; - } else { -#if HOST_LONG_BITS == 64 && defined(__GNUC__) - /* assuming 64-bit hosts have __uint128_t */ - __uint128_t dividend = (((__uint128_t)env->regs[r1]) << 64) | - (env->regs[r1 + 1]); - __uint128_t quotient = dividend / divisor; - __uint128_t remainder = dividend % divisor; - - env->regs[r1 + 1] = quotient; - env->regs[r1] = remainder; -#else - /* 32-bit hosts would need special wrapper functionality - just abort if - we encounter such a case; it's very unlikely anyways. */ - cpu_abort(env, "128 -> 64/64 division not implemented\n"); -#endif - } -} - static inline uint64_t get_address(int x2, int b2, int d2) { uint64_t r = d2; @@ -677,61 +634,6 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret) return cc; } -/* absolute value 32-bit */ -uint32_t HELPER(abs_i32)(int32_t val) -{ - if (val < 0) { - return -val; - } else { - return val; - } -} - -/* negative absolute value 32-bit */ -int32_t HELPER(nabs_i32)(int32_t val) -{ - if (val < 0) { - return val; - } else { - return -val; - } -} - -/* absolute value 64-bit */ -uint64_t HELPER(abs_i64)(int64_t val) -{ - HELPER_LOG("%s: val 0x%" PRIx64 "\n", __func__, val); - - if (val < 0) { - return -val; - } else { - return val; - } -} - -/* negative absolute value 64-bit */ -int64_t HELPER(nabs_i64)(int64_t val) -{ - if (val < 0) { - return val; - } else { - return -val; - } -} - -/* add with carry 32-bit unsigned */ -uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2) -{ - uint32_t res; - - res = v1 + v2; - if (cc & 2) { - res++; - } - - return res; -} - /* store character under mask high operates on the upper half of r1 */ void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask) { @@ -936,57 +838,6 @@ uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3) return cc; } -/* subtract unsigned v2 from v1 with borrow */ -uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2) -{ - uint32_t v1 = env->regs[r1]; - uint32_t res = v1 + (~v2) + (cc >> 1); - - env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | res; - if (cc & 2) { - /* borrow */ - return v1 ? 1 : 0; - } else { - return v1 ? 3 : 2; - } -} - -/* subtract unsigned v2 from v1 with borrow */ -uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2) -{ - uint64_t res = v1 + (~v2) + (cc >> 1); - - env->regs[r1] = res; - if (cc & 2) { - /* borrow */ - return v1 ? 1 : 0; - } else { - return v1 ? 3 : 2; - } -} - -/* find leftmost one */ -uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2) -{ - uint64_t res = 0; - uint64_t ov2 = v2; - - while (!(v2 & 0x8000000000000000ULL) && v2) { - v2 <<= 1; - res++; - } - - if (!v2) { - env->regs[r1] = 64; - env->regs[r1 + 1] = 0; - return 0; - } else { - env->regs[r1] = res; - env->regs[r1 + 1] = ov2 & ~(0x8000000000000000ULL >> res); - return 2; - } -} - /* checksum */ void HELPER(cksm)(uint32_t r1, uint32_t r2) { @@ -1026,27 +877,6 @@ void HELPER(cksm)(uint32_t r1, uint32_t r2) ((uint32_t)cksm + (cksm >> 32)); } -uint64_t HELPER(cvd)(int32_t bin) -{ - /* positive 0 */ - uint64_t dec = 0x0c; - int shift = 4; - - if (bin < 0) { - bin = -bin; - dec = 0x0d; - } - - for (shift = 4; (shift < 64) && bin; shift += 4) { - int current_number = bin % 10; - - dec |= (current_number) << shift; - bin /= 10; - } - - return dec; -} - void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src) { int len_dest = len >> 4; From 8ef7f78e190b3a34e167a31c9a8e43c813c7ff78 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 07:33:34 +0000 Subject: [PATCH 0221/2270] target-s390x: split memory access helpers Move memory access helpers to mem_helper.c. Signed-off-by: Blue Swirl [agraf: fold softmmu include ifdefs together] Signed-off-by: Alexander Graf --- target-s390x/Makefile.objs | 3 +- target-s390x/mem_helper.c | 1190 ++++++++++++++++++++++++++++++++++++ target-s390x/op_helper.c | 1159 +---------------------------------- 3 files changed, 1193 insertions(+), 1159 deletions(-) create mode 100644 target-s390x/mem_helper.c diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs index e8f66e93a7..b9b306170c 100644 --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -1,5 +1,5 @@ obj-y += translate.o op_helper.o helper.o cpu.o interrupt.o -obj-y += int_helper.o fpu_helper.o cc_helper.o +obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o obj-$(CONFIG_SOFTMMU) += machine.o obj-$(CONFIG_KVM) += kvm.o @@ -7,3 +7,4 @@ $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/int_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/fpu_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) +$(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c new file mode 100644 index 0000000000..ba05e65cd8 --- /dev/null +++ b/target-s390x/mem_helper.c @@ -0,0 +1,1190 @@ +/* + * S/390 memory access helper routines + * + * Copyright (c) 2009 Ulrich Hecht + * Copyright (c) 2009 Alexander Graf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "cpu.h" +#include "dyngen-exec.h" +#include "helper.h" + +/*****************************************************************************/ +/* Softmmu support */ +#if !defined(CONFIG_USER_ONLY) +#include "softmmu_exec.h" + +#define MMUSUFFIX _mmu + +#define SHIFT 0 +#include "softmmu_template.h" + +#define SHIFT 1 +#include "softmmu_template.h" + +#define SHIFT 2 +#include "softmmu_template.h" + +#define SHIFT 3 +#include "softmmu_template.h" + +/* try to fill the TLB and return an exception if error. If retaddr is + NULL, it means that the function was called in C code (i.e. not + from generated code or from helper.c) */ +/* XXX: fix it to restore all registers */ +void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx, + uintptr_t retaddr) +{ + TranslationBlock *tb; + CPUS390XState *saved_env; + int ret; + + saved_env = env; + env = env1; + ret = cpu_s390x_handle_mmu_fault(env, addr, is_write, mmu_idx); + if (unlikely(ret != 0)) { + if (likely(retaddr)) { + /* now we have a real cpu fault */ + tb = tb_find_pc(retaddr); + if (likely(tb)) { + /* the PC is inside the translated code. It means that we have + a virtual CPU fault */ + cpu_restore_state(tb, env, retaddr); + } + } + cpu_loop_exit(env); + } + env = saved_env; +} + +#endif + +/* #define DEBUG_HELPER */ +#ifdef DEBUG_HELPER +#define HELPER_LOG(x...) qemu_log(x) +#else +#define HELPER_LOG(x...) +#endif + +#ifndef CONFIG_USER_ONLY +static void mvc_fast_memset(CPUS390XState *env, uint32_t l, uint64_t dest, + uint8_t byte) +{ + target_phys_addr_t dest_phys; + target_phys_addr_t len = l; + void *dest_p; + uint64_t asc = env->psw.mask & PSW_MASK_ASC; + int flags; + + if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) { + stb(dest, byte); + cpu_abort(env, "should never reach here"); + } + dest_phys |= dest & ~TARGET_PAGE_MASK; + + dest_p = cpu_physical_memory_map(dest_phys, &len, 1); + + memset(dest_p, byte, len); + + cpu_physical_memory_unmap(dest_p, 1, len, len); +} + +static void mvc_fast_memmove(CPUS390XState *env, uint32_t l, uint64_t dest, + uint64_t src) +{ + target_phys_addr_t dest_phys; + target_phys_addr_t src_phys; + target_phys_addr_t len = l; + void *dest_p; + void *src_p; + uint64_t asc = env->psw.mask & PSW_MASK_ASC; + int flags; + + if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) { + stb(dest, 0); + cpu_abort(env, "should never reach here"); + } + dest_phys |= dest & ~TARGET_PAGE_MASK; + + if (mmu_translate(env, src, 0, asc, &src_phys, &flags)) { + ldub(src); + cpu_abort(env, "should never reach here"); + } + src_phys |= src & ~TARGET_PAGE_MASK; + + dest_p = cpu_physical_memory_map(dest_phys, &len, 1); + src_p = cpu_physical_memory_map(src_phys, &len, 0); + + memmove(dest_p, src_p, len); + + cpu_physical_memory_unmap(dest_p, 1, len, len); + cpu_physical_memory_unmap(src_p, 0, len, len); +} +#endif + +/* and on array */ +uint32_t HELPER(nc)(uint32_t l, uint64_t dest, uint64_t src) +{ + int i; + unsigned char x; + uint32_t cc = 0; + + HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", + __func__, l, dest, src); + for (i = 0; i <= l; i++) { + x = ldub(dest + i) & ldub(src + i); + if (x) { + cc = 1; + } + stb(dest + i, x); + } + return cc; +} + +/* xor on array */ +uint32_t HELPER(xc)(uint32_t l, uint64_t dest, uint64_t src) +{ + int i; + unsigned char x; + uint32_t cc = 0; + + HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", + __func__, l, dest, src); + +#ifndef CONFIG_USER_ONLY + /* xor with itself is the same as memset(0) */ + if ((l > 32) && (src == dest) && + (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK)) { + mvc_fast_memset(env, l + 1, dest, 0); + return 0; + } +#else + if (src == dest) { + memset(g2h(dest), 0, l + 1); + return 0; + } +#endif + + for (i = 0; i <= l; i++) { + x = ldub(dest + i) ^ ldub(src + i); + if (x) { + cc = 1; + } + stb(dest + i, x); + } + return cc; +} + +/* or on array */ +uint32_t HELPER(oc)(uint32_t l, uint64_t dest, uint64_t src) +{ + int i; + unsigned char x; + uint32_t cc = 0; + + HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", + __func__, l, dest, src); + for (i = 0; i <= l; i++) { + x = ldub(dest + i) | ldub(src + i); + if (x) { + cc = 1; + } + stb(dest + i, x); + } + return cc; +} + +/* memmove */ +void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src) +{ + int i = 0; + int x = 0; + uint32_t l_64 = (l + 1) / 8; + + HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", + __func__, l, dest, src); + +#ifndef CONFIG_USER_ONLY + if ((l > 32) && + (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK) && + (dest & TARGET_PAGE_MASK) == ((dest + l) & TARGET_PAGE_MASK)) { + if (dest == (src + 1)) { + mvc_fast_memset(env, l + 1, dest, ldub(src)); + return; + } else if ((src & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) { + mvc_fast_memmove(env, l + 1, dest, src); + return; + } + } +#else + if (dest == (src + 1)) { + memset(g2h(dest), ldub(src), l + 1); + return; + } else { + memmove(g2h(dest), g2h(src), l + 1); + return; + } +#endif + + /* handle the parts that fit into 8-byte loads/stores */ + if (dest != (src + 1)) { + for (i = 0; i < l_64; i++) { + stq(dest + x, ldq(src + x)); + x += 8; + } + } + + /* slow version crossing pages with byte accesses */ + for (i = x; i <= l; i++) { + stb(dest + i, ldub(src + i)); + } +} + +/* compare unsigned byte arrays */ +uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2) +{ + int i; + unsigned char x, y; + uint32_t cc; + + HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n", + __func__, l, s1, s2); + for (i = 0; i <= l; i++) { + x = ldub(s1 + i); + y = ldub(s2 + i); + HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y); + if (x < y) { + cc = 1; + goto done; + } else if (x > y) { + cc = 2; + goto done; + } + } + cc = 0; + done: + HELPER_LOG("\n"); + return cc; +} + +/* compare logical under mask */ +uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr) +{ + uint8_t r, d; + uint32_t cc; + + HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __func__, r1, + mask, addr); + cc = 0; + while (mask) { + if (mask & 8) { + d = ldub(addr); + r = (r1 & 0xff000000UL) >> 24; + HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d, + addr); + if (r < d) { + cc = 1; + break; + } else if (r > d) { + cc = 2; + break; + } + addr++; + } + mask = (mask << 1) & 0xf; + r1 <<= 8; + } + HELPER_LOG("\n"); + return cc; +} + +/* store character under mask */ +void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr) +{ + uint8_t r; + + HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%lx\n", __func__, r1, mask, + addr); + while (mask) { + if (mask & 8) { + r = (r1 & 0xff000000UL) >> 24; + stb(addr, r); + HELPER_LOG("mask 0x%x %02x (0x%lx) ", mask, r, addr); + addr++; + } + mask = (mask << 1) & 0xf; + r1 <<= 8; + } + HELPER_LOG("\n"); +} + +static inline uint64_t get_address(int x2, int b2, int d2) +{ + uint64_t r = d2; + + if (x2) { + r += env->regs[x2]; + } + + if (b2) { + r += env->regs[b2]; + } + + /* 31-Bit mode */ + if (!(env->psw.mask & PSW_MASK_64)) { + r &= 0x7fffffff; + } + + return r; +} + +static inline uint64_t get_address_31fix(int reg) +{ + uint64_t r = env->regs[reg]; + + /* 31-Bit mode */ + if (!(env->psw.mask & PSW_MASK_64)) { + r &= 0x7fffffff; + } + + return r; +} + +/* search string (c is byte to search, r2 is string, r1 end of string) */ +uint32_t HELPER(srst)(uint32_t c, uint32_t r1, uint32_t r2) +{ + uint64_t i; + uint32_t cc = 2; + uint64_t str = get_address_31fix(r2); + uint64_t end = get_address_31fix(r1); + + HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __func__, + c, env->regs[r1], env->regs[r2]); + + for (i = str; i != end; i++) { + if (ldub(i) == c) { + env->regs[r1] = i; + cc = 1; + break; + } + } + + return cc; +} + +/* unsigned string compare (c is string terminator) */ +uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2) +{ + uint64_t s1 = get_address_31fix(r1); + uint64_t s2 = get_address_31fix(r2); + uint8_t v1, v2; + uint32_t cc; + + c = c & 0xff; +#ifdef CONFIG_USER_ONLY + if (!c) { + HELPER_LOG("%s: comparing '%s' and '%s'\n", + __func__, (char *)g2h(s1), (char *)g2h(s2)); + } +#endif + for (;;) { + v1 = ldub(s1); + v2 = ldub(s2); + if ((v1 == c || v2 == c) || (v1 != v2)) { + break; + } + s1++; + s2++; + } + + if (v1 == v2) { + cc = 0; + } else { + cc = (v1 < v2) ? 1 : 2; + /* FIXME: 31-bit mode! */ + env->regs[r1] = s1; + env->regs[r2] = s2; + } + return cc; +} + +/* move page */ +void HELPER(mvpg)(uint64_t r0, uint64_t r1, uint64_t r2) +{ + /* XXX missing r0 handling */ +#ifdef CONFIG_USER_ONLY + int i; + + for (i = 0; i < TARGET_PAGE_SIZE; i++) { + stb(r1 + i, ldub(r2 + i)); + } +#else + mvc_fast_memmove(env, TARGET_PAGE_SIZE, r1, r2); +#endif +} + +/* string copy (c is string terminator) */ +void HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2) +{ + uint64_t dest = get_address_31fix(r1); + uint64_t src = get_address_31fix(r2); + uint8_t v; + + c = c & 0xff; +#ifdef CONFIG_USER_ONLY + if (!c) { + HELPER_LOG("%s: copy '%s' to 0x%lx\n", __func__, (char *)g2h(src), + dest); + } +#endif + for (;;) { + v = ldub(src); + stb(dest, v); + if (v == c) { + break; + } + src++; + dest++; + } + env->regs[r1] = dest; /* FIXME: 31-bit mode! */ +} + +/* compare and swap 64-bit */ +uint32_t HELPER(csg)(uint32_t r1, uint64_t a2, uint32_t r3) +{ + /* FIXME: locking? */ + uint32_t cc; + uint64_t v2 = ldq(a2); + + if (env->regs[r1] == v2) { + cc = 0; + stq(a2, env->regs[r3]); + } else { + cc = 1; + env->regs[r1] = v2; + } + return cc; +} + +/* compare double and swap 64-bit */ +uint32_t HELPER(cdsg)(uint32_t r1, uint64_t a2, uint32_t r3) +{ + /* FIXME: locking? */ + uint32_t cc; + uint64_t v2_hi = ldq(a2); + uint64_t v2_lo = ldq(a2 + 8); + uint64_t v1_hi = env->regs[r1]; + uint64_t v1_lo = env->regs[r1 + 1]; + + if ((v1_hi == v2_hi) && (v1_lo == v2_lo)) { + cc = 0; + stq(a2, env->regs[r3]); + stq(a2 + 8, env->regs[r3 + 1]); + } else { + cc = 1; + env->regs[r1] = v2_hi; + env->regs[r1 + 1] = v2_lo; + } + + return cc; +} + +/* compare and swap 32-bit */ +uint32_t HELPER(cs)(uint32_t r1, uint64_t a2, uint32_t r3) +{ + /* FIXME: locking? */ + uint32_t cc; + uint32_t v2 = ldl(a2); + + HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __func__, r1, a2, r3); + if (((uint32_t)env->regs[r1]) == v2) { + cc = 0; + stl(a2, (uint32_t)env->regs[r3]); + } else { + cc = 1; + env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | v2; + } + return cc; +} + +static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask) +{ + int pos = 24; /* top of the lower half of r1 */ + uint64_t rmask = 0xff000000ULL; + uint8_t val = 0; + int ccd = 0; + uint32_t cc = 0; + + while (mask) { + if (mask & 8) { + env->regs[r1] &= ~rmask; + val = ldub(address); + if ((val & 0x80) && !ccd) { + cc = 1; + } + ccd = 1; + if (val && cc == 0) { + cc = 2; + } + env->regs[r1] |= (uint64_t)val << pos; + address++; + } + mask = (mask << 1) & 0xf; + pos -= 8; + rmask >>= 8; + } + + return cc; +} + +/* execute instruction + this instruction executes an insn modified with the contents of r1 + it does not change the executed instruction in memory + it does not change the program counter + in other words: tricky... + currently implemented by interpreting the cases it is most commonly used in +*/ +uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret) +{ + uint16_t insn = lduw_code(addr); + + HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __func__, v1, addr, + insn); + if ((insn & 0xf0ff) == 0xd000) { + uint32_t l, insn2, b1, b2, d1, d2; + + l = v1 & 0xff; + insn2 = ldl_code(addr + 2); + b1 = (insn2 >> 28) & 0xf; + b2 = (insn2 >> 12) & 0xf; + d1 = (insn2 >> 16) & 0xfff; + d2 = insn2 & 0xfff; + switch (insn & 0xf00) { + case 0x200: + helper_mvc(l, get_address(0, b1, d1), get_address(0, b2, d2)); + break; + case 0x500: + cc = helper_clc(l, get_address(0, b1, d1), get_address(0, b2, d2)); + break; + case 0x700: + cc = helper_xc(l, get_address(0, b1, d1), get_address(0, b2, d2)); + break; + case 0xc00: + helper_tr(l, get_address(0, b1, d1), get_address(0, b2, d2)); + break; + default: + goto abort; + break; + } + } else if ((insn & 0xff00) == 0x0a00) { + /* supervisor call */ + HELPER_LOG("%s: svc %ld via execute\n", __func__, (insn | v1) & 0xff); + env->psw.addr = ret - 4; + env->int_svc_code = (insn | v1) & 0xff; + env->int_svc_ilc = 4; + helper_exception(EXCP_SVC); + } else if ((insn & 0xff00) == 0xbf00) { + uint32_t insn2, r1, r3, b2, d2; + + insn2 = ldl_code(addr + 2); + r1 = (insn2 >> 20) & 0xf; + r3 = (insn2 >> 16) & 0xf; + b2 = (insn2 >> 12) & 0xf; + d2 = insn2 & 0xfff; + cc = helper_icm(r1, get_address(0, b2, d2), r3); + } else { + abort: + cpu_abort(env, "EXECUTE on instruction prefix 0x%x not implemented\n", + insn); + } + return cc; +} + +/* store character under mask high operates on the upper half of r1 */ +void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask) +{ + int pos = 56; /* top of the upper half of r1 */ + + while (mask) { + if (mask & 8) { + stb(address, (env->regs[r1] >> pos) & 0xff); + address++; + } + mask = (mask << 1) & 0xf; + pos -= 8; + } +} + +/* insert character under mask high; same as icm, but operates on the + upper half of r1 */ +uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask) +{ + int pos = 56; /* top of the upper half of r1 */ + uint64_t rmask = 0xff00000000000000ULL; + uint8_t val = 0; + int ccd = 0; + uint32_t cc = 0; + + while (mask) { + if (mask & 8) { + env->regs[r1] &= ~rmask; + val = ldub(address); + if ((val & 0x80) && !ccd) { + cc = 1; + } + ccd = 1; + if (val && cc == 0) { + cc = 2; + } + env->regs[r1] |= (uint64_t)val << pos; + address++; + } + mask = (mask << 1) & 0xf; + pos -= 8; + rmask >>= 8; + } + + return cc; +} + +/* load access registers r1 to r3 from memory at a2 */ +void HELPER(lam)(uint32_t r1, uint64_t a2, uint32_t r3) +{ + int i; + + for (i = r1;; i = (i + 1) % 16) { + env->aregs[i] = ldl(a2); + a2 += 4; + + if (i == r3) { + break; + } + } +} + +/* store access registers r1 to r3 in memory at a2 */ +void HELPER(stam)(uint32_t r1, uint64_t a2, uint32_t r3) +{ + int i; + + for (i = r1;; i = (i + 1) % 16) { + stl(a2, env->aregs[i]); + a2 += 4; + + if (i == r3) { + break; + } + } +} + +/* move long */ +uint32_t HELPER(mvcl)(uint32_t r1, uint32_t r2) +{ + uint64_t destlen = env->regs[r1 + 1] & 0xffffff; + uint64_t dest = get_address_31fix(r1); + uint64_t srclen = env->regs[r2 + 1] & 0xffffff; + uint64_t src = get_address_31fix(r2); + uint8_t pad = src >> 24; + uint8_t v; + uint32_t cc; + + if (destlen == srclen) { + cc = 0; + } else if (destlen < srclen) { + cc = 1; + } else { + cc = 2; + } + + if (srclen > destlen) { + srclen = destlen; + } + + for (; destlen && srclen; src++, dest++, destlen--, srclen--) { + v = ldub(src); + stb(dest, v); + } + + for (; destlen; dest++, destlen--) { + stb(dest, pad); + } + + env->regs[r1 + 1] = destlen; + /* can't use srclen here, we trunc'ed it */ + env->regs[r2 + 1] -= src - env->regs[r2]; + env->regs[r1] = dest; + env->regs[r2] = src; + + return cc; +} + +/* move long extended another memcopy insn with more bells and whistles */ +uint32_t HELPER(mvcle)(uint32_t r1, uint64_t a2, uint32_t r3) +{ + uint64_t destlen = env->regs[r1 + 1]; + uint64_t dest = env->regs[r1]; + uint64_t srclen = env->regs[r3 + 1]; + uint64_t src = env->regs[r3]; + uint8_t pad = a2 & 0xff; + uint8_t v; + uint32_t cc; + + if (!(env->psw.mask & PSW_MASK_64)) { + destlen = (uint32_t)destlen; + srclen = (uint32_t)srclen; + dest &= 0x7fffffff; + src &= 0x7fffffff; + } + + if (destlen == srclen) { + cc = 0; + } else if (destlen < srclen) { + cc = 1; + } else { + cc = 2; + } + + if (srclen > destlen) { + srclen = destlen; + } + + for (; destlen && srclen; src++, dest++, destlen--, srclen--) { + v = ldub(src); + stb(dest, v); + } + + for (; destlen; dest++, destlen--) { + stb(dest, pad); + } + + env->regs[r1 + 1] = destlen; + /* can't use srclen here, we trunc'ed it */ + /* FIXME: 31-bit mode! */ + env->regs[r3 + 1] -= src - env->regs[r3]; + env->regs[r1] = dest; + env->regs[r3] = src; + + return cc; +} + +/* compare logical long extended memcompare insn with padding */ +uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3) +{ + uint64_t destlen = env->regs[r1 + 1]; + uint64_t dest = get_address_31fix(r1); + uint64_t srclen = env->regs[r3 + 1]; + uint64_t src = get_address_31fix(r3); + uint8_t pad = a2 & 0xff; + uint8_t v1 = 0, v2 = 0; + uint32_t cc = 0; + + if (!(destlen || srclen)) { + return cc; + } + + if (srclen > destlen) { + srclen = destlen; + } + + for (; destlen || srclen; src++, dest++, destlen--, srclen--) { + v1 = srclen ? ldub(src) : pad; + v2 = destlen ? ldub(dest) : pad; + if (v1 != v2) { + cc = (v1 < v2) ? 1 : 2; + break; + } + } + + env->regs[r1 + 1] = destlen; + /* can't use srclen here, we trunc'ed it */ + env->regs[r3 + 1] -= src - env->regs[r3]; + env->regs[r1] = dest; + env->regs[r3] = src; + + return cc; +} + +/* checksum */ +void HELPER(cksm)(uint32_t r1, uint32_t r2) +{ + uint64_t src = get_address_31fix(r2); + uint64_t src_len = env->regs[(r2 + 1) & 15]; + uint64_t cksm = (uint32_t)env->regs[r1]; + + while (src_len >= 4) { + cksm += ldl(src); + + /* move to next word */ + src_len -= 4; + src += 4; + } + + switch (src_len) { + case 0: + break; + case 1: + cksm += ldub(src) << 24; + break; + case 2: + cksm += lduw(src) << 16; + break; + case 3: + cksm += lduw(src) << 16; + cksm += ldub(src + 2) << 8; + break; + } + + /* indicate we've processed everything */ + env->regs[r2] = src + src_len; + env->regs[(r2 + 1) & 15] = 0; + + /* store result */ + env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | + ((uint32_t)cksm + (cksm >> 32)); +} + +void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src) +{ + int len_dest = len >> 4; + int len_src = len & 0xf; + uint8_t b; + int second_nibble = 0; + + dest += len_dest; + src += len_src; + + /* last byte is special, it only flips the nibbles */ + b = ldub(src); + stb(dest, (b << 4) | (b >> 4)); + src--; + len_src--; + + /* now pad every nibble with 0xf0 */ + + while (len_dest > 0) { + uint8_t cur_byte = 0; + + if (len_src > 0) { + cur_byte = ldub(src); + } + + len_dest--; + dest--; + + /* only advance one nibble at a time */ + if (second_nibble) { + cur_byte >>= 4; + len_src--; + src--; + } + second_nibble = !second_nibble; + + /* digit */ + cur_byte = (cur_byte & 0xf); + /* zone bits */ + cur_byte |= 0xf0; + + stb(dest, cur_byte); + } +} + +void HELPER(tr)(uint32_t len, uint64_t array, uint64_t trans) +{ + int i; + + for (i = 0; i <= len; i++) { + uint8_t byte = ldub(array + i); + uint8_t new_byte = ldub(trans + byte); + + stb(array + i, new_byte); + } +} + +#if !defined(CONFIG_USER_ONLY) +void HELPER(lctlg)(uint32_t r1, uint64_t a2, uint32_t r3) +{ + int i; + uint64_t src = a2; + + for (i = r1;; i = (i + 1) % 16) { + env->cregs[i] = ldq(src); + HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n", + i, src, env->cregs[i]); + src += sizeof(uint64_t); + + if (i == r3) { + break; + } + } + + tlb_flush(env, 1); +} + +void HELPER(lctl)(uint32_t r1, uint64_t a2, uint32_t r3) +{ + int i; + uint64_t src = a2; + + for (i = r1;; i = (i + 1) % 16) { + env->cregs[i] = (env->cregs[i] & 0xFFFFFFFF00000000ULL) | ldl(src); + src += sizeof(uint32_t); + + if (i == r3) { + break; + } + } + + tlb_flush(env, 1); +} + +void HELPER(stctg)(uint32_t r1, uint64_t a2, uint32_t r3) +{ + int i; + uint64_t dest = a2; + + for (i = r1;; i = (i + 1) % 16) { + stq(dest, env->cregs[i]); + dest += sizeof(uint64_t); + + if (i == r3) { + break; + } + } +} + +void HELPER(stctl)(uint32_t r1, uint64_t a2, uint32_t r3) +{ + int i; + uint64_t dest = a2; + + for (i = r1;; i = (i + 1) % 16) { + stl(dest, env->cregs[i]); + dest += sizeof(uint32_t); + + if (i == r3) { + break; + } + } +} + +uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2) +{ + /* XXX implement */ + + return 0; +} + +/* insert storage key extended */ +uint64_t HELPER(iske)(uint64_t r2) +{ + uint64_t addr = get_address(0, 0, r2); + + if (addr > ram_size) { + return 0; + } + + return env->storage_keys[addr / TARGET_PAGE_SIZE]; +} + +/* set storage key extended */ +void HELPER(sske)(uint32_t r1, uint64_t r2) +{ + uint64_t addr = get_address(0, 0, r2); + + if (addr > ram_size) { + return; + } + + env->storage_keys[addr / TARGET_PAGE_SIZE] = r1; +} + +/* reset reference bit extended */ +uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2) +{ + uint8_t re; + uint8_t key; + + if (r2 > ram_size) { + return 0; + } + + key = env->storage_keys[r2 / TARGET_PAGE_SIZE]; + re = key & (SK_R | SK_C); + env->storage_keys[r2 / TARGET_PAGE_SIZE] = (key & ~SK_R); + + /* + * cc + * + * 0 Reference bit zero; change bit zero + * 1 Reference bit zero; change bit one + * 2 Reference bit one; change bit zero + * 3 Reference bit one; change bit one + */ + + return re >> 1; +} + +/* compare and swap and purge */ +uint32_t HELPER(csp)(uint32_t r1, uint32_t r2) +{ + uint32_t cc; + uint32_t o1 = env->regs[r1]; + uint64_t a2 = get_address_31fix(r2) & ~3ULL; + uint32_t o2 = ldl(a2); + + if (o1 == o2) { + stl(a2, env->regs[(r1 + 1) & 15]); + if (env->regs[r2] & 0x3) { + /* flush TLB / ALB */ + tlb_flush(env, 1); + } + cc = 0; + } else { + env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | o2; + cc = 1; + } + + return cc; +} + +static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2, + uint64_t mode2) +{ + target_ulong src, dest; + int flags, cc = 0, i; + + if (!l) { + return 0; + } else if (l > 256) { + /* max 256 */ + l = 256; + cc = 3; + } + + if (mmu_translate(env, a1 & TARGET_PAGE_MASK, 1, mode1, &dest, &flags)) { + cpu_loop_exit(env); + } + dest |= a1 & ~TARGET_PAGE_MASK; + + if (mmu_translate(env, a2 & TARGET_PAGE_MASK, 0, mode2, &src, &flags)) { + cpu_loop_exit(env); + } + src |= a2 & ~TARGET_PAGE_MASK; + + /* XXX replace w/ memcpy */ + for (i = 0; i < l; i++) { + /* XXX be more clever */ + if ((((dest + i) & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) || + (((src + i) & TARGET_PAGE_MASK) != (src & TARGET_PAGE_MASK))) { + mvc_asc(l - i, a1 + i, mode1, a2 + i, mode2); + break; + } + stb_phys(dest + i, ldub_phys(src + i)); + } + + return cc; +} + +uint32_t HELPER(mvcs)(uint64_t l, uint64_t a1, uint64_t a2) +{ + HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n", + __func__, l, a1, a2); + + return mvc_asc(l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY); +} + +uint32_t HELPER(mvcp)(uint64_t l, uint64_t a1, uint64_t a2) +{ + HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n", + __func__, l, a1, a2); + + return mvc_asc(l, a1, PSW_ASC_PRIMARY, a2, PSW_ASC_SECONDARY); +} + +/* invalidate pte */ +void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr) +{ + uint64_t page = vaddr & TARGET_PAGE_MASK; + uint64_t pte = 0; + + /* XXX broadcast to other CPUs */ + + /* XXX Linux is nice enough to give us the exact pte address. + According to spec we'd have to find it out ourselves */ + /* XXX Linux is fine with overwriting the pte, the spec requires + us to only set the invalid bit */ + stq_phys(pte_addr, pte | _PAGE_INVALID); + + /* XXX we exploit the fact that Linux passes the exact virtual + address here - it's not obliged to! */ + tlb_flush_page(env, page); + + /* XXX 31-bit hack */ + if (page & 0x80000000) { + tlb_flush_page(env, page & ~0x80000000); + } else { + tlb_flush_page(env, page | 0x80000000); + } +} + +/* flush local tlb */ +void HELPER(ptlb)(void) +{ + tlb_flush(env, 1); +} + +/* store using real address */ +void HELPER(stura)(uint64_t addr, uint32_t v1) +{ + stw_phys(get_address(0, 0, addr), v1); +} + +/* load real address */ +uint32_t HELPER(lra)(uint64_t addr, uint32_t r1) +{ + uint32_t cc = 0; + int old_exc = env->exception_index; + uint64_t asc = env->psw.mask & PSW_MASK_ASC; + uint64_t ret; + int flags; + + /* XXX incomplete - has more corner cases */ + if (!(env->psw.mask & PSW_MASK_64) && (addr >> 32)) { + program_interrupt(env, PGM_SPECIAL_OP, 2); + } + + env->exception_index = old_exc; + if (mmu_translate(env, addr, 0, asc, &ret, &flags)) { + cc = 3; + } + if (env->exception_index == EXCP_PGM) { + ret = env->int_pgm_code | 0x80000000; + } else { + ret |= addr & ~TARGET_PAGE_MASK; + } + env->exception_index = old_exc; + + if (!(env->psw.mask & PSW_MASK_64)) { + env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | + (ret & 0xffffffffULL); + } else { + env->regs[r1] = ret; + } + + return cc; +} + +#endif diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c index 3b8b997abf..bb8dbf55d0 100644 --- a/target-s390x/op_helper.c +++ b/target-s390x/op_helper.c @@ -31,58 +31,9 @@ #include #endif -#if !defined(CONFIG_USER_ONLY) -#include "sysemu.h" -#endif - -/*****************************************************************************/ -/* Softmmu support */ #if !defined(CONFIG_USER_ONLY) #include "softmmu_exec.h" - -#define MMUSUFFIX _mmu - -#define SHIFT 0 -#include "softmmu_template.h" - -#define SHIFT 1 -#include "softmmu_template.h" - -#define SHIFT 2 -#include "softmmu_template.h" - -#define SHIFT 3 -#include "softmmu_template.h" - -/* try to fill the TLB and return an exception if error. If retaddr is - NULL, it means that the function was called in C code (i.e. not - from generated code or from helper.c) */ -/* XXX: fix it to restore all registers */ -void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx, - uintptr_t retaddr) -{ - TranslationBlock *tb; - CPUS390XState *saved_env; - int ret; - - saved_env = env; - env = env1; - ret = cpu_s390x_handle_mmu_fault(env, addr, is_write, mmu_idx); - if (unlikely(ret != 0)) { - if (likely(retaddr)) { - /* now we have a real cpu fault */ - tb = tb_find_pc(retaddr); - if (likely(tb)) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, retaddr); - } - } - cpu_loop_exit(env); - } - env = saved_env; -} - +#include "sysemu.h" #endif /* #define DEBUG_HELPER */ @@ -100,840 +51,6 @@ void HELPER(exception)(uint32_t excp) cpu_loop_exit(env); } -#ifndef CONFIG_USER_ONLY -static void mvc_fast_memset(CPUS390XState *env, uint32_t l, uint64_t dest, - uint8_t byte) -{ - target_phys_addr_t dest_phys; - target_phys_addr_t len = l; - void *dest_p; - uint64_t asc = env->psw.mask & PSW_MASK_ASC; - int flags; - - if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) { - stb(dest, byte); - cpu_abort(env, "should never reach here"); - } - dest_phys |= dest & ~TARGET_PAGE_MASK; - - dest_p = cpu_physical_memory_map(dest_phys, &len, 1); - - memset(dest_p, byte, len); - - cpu_physical_memory_unmap(dest_p, 1, len, len); -} - -static void mvc_fast_memmove(CPUS390XState *env, uint32_t l, uint64_t dest, - uint64_t src) -{ - target_phys_addr_t dest_phys; - target_phys_addr_t src_phys; - target_phys_addr_t len = l; - void *dest_p; - void *src_p; - uint64_t asc = env->psw.mask & PSW_MASK_ASC; - int flags; - - if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) { - stb(dest, 0); - cpu_abort(env, "should never reach here"); - } - dest_phys |= dest & ~TARGET_PAGE_MASK; - - if (mmu_translate(env, src, 0, asc, &src_phys, &flags)) { - ldub(src); - cpu_abort(env, "should never reach here"); - } - src_phys |= src & ~TARGET_PAGE_MASK; - - dest_p = cpu_physical_memory_map(dest_phys, &len, 1); - src_p = cpu_physical_memory_map(src_phys, &len, 0); - - memmove(dest_p, src_p, len); - - cpu_physical_memory_unmap(dest_p, 1, len, len); - cpu_physical_memory_unmap(src_p, 0, len, len); -} -#endif - -/* and on array */ -uint32_t HELPER(nc)(uint32_t l, uint64_t dest, uint64_t src) -{ - int i; - unsigned char x; - uint32_t cc = 0; - - HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", - __func__, l, dest, src); - for (i = 0; i <= l; i++) { - x = ldub(dest + i) & ldub(src + i); - if (x) { - cc = 1; - } - stb(dest + i, x); - } - return cc; -} - -/* xor on array */ -uint32_t HELPER(xc)(uint32_t l, uint64_t dest, uint64_t src) -{ - int i; - unsigned char x; - uint32_t cc = 0; - - HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", - __func__, l, dest, src); - -#ifndef CONFIG_USER_ONLY - /* xor with itself is the same as memset(0) */ - if ((l > 32) && (src == dest) && - (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK)) { - mvc_fast_memset(env, l + 1, dest, 0); - return 0; - } -#else - if (src == dest) { - memset(g2h(dest), 0, l + 1); - return 0; - } -#endif - - for (i = 0; i <= l; i++) { - x = ldub(dest + i) ^ ldub(src + i); - if (x) { - cc = 1; - } - stb(dest + i, x); - } - return cc; -} - -/* or on array */ -uint32_t HELPER(oc)(uint32_t l, uint64_t dest, uint64_t src) -{ - int i; - unsigned char x; - uint32_t cc = 0; - - HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", - __func__, l, dest, src); - for (i = 0; i <= l; i++) { - x = ldub(dest + i) | ldub(src + i); - if (x) { - cc = 1; - } - stb(dest + i, x); - } - return cc; -} - -/* memmove */ -void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src) -{ - int i = 0; - int x = 0; - uint32_t l_64 = (l + 1) / 8; - - HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", - __func__, l, dest, src); - -#ifndef CONFIG_USER_ONLY - if ((l > 32) && - (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK) && - (dest & TARGET_PAGE_MASK) == ((dest + l) & TARGET_PAGE_MASK)) { - if (dest == (src + 1)) { - mvc_fast_memset(env, l + 1, dest, ldub(src)); - return; - } else if ((src & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) { - mvc_fast_memmove(env, l + 1, dest, src); - return; - } - } -#else - if (dest == (src + 1)) { - memset(g2h(dest), ldub(src), l + 1); - return; - } else { - memmove(g2h(dest), g2h(src), l + 1); - return; - } -#endif - - /* handle the parts that fit into 8-byte loads/stores */ - if (dest != (src + 1)) { - for (i = 0; i < l_64; i++) { - stq(dest + x, ldq(src + x)); - x += 8; - } - } - - /* slow version crossing pages with byte accesses */ - for (i = x; i <= l; i++) { - stb(dest + i, ldub(src + i)); - } -} - -/* compare unsigned byte arrays */ -uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2) -{ - int i; - unsigned char x, y; - uint32_t cc; - - HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n", - __func__, l, s1, s2); - for (i = 0; i <= l; i++) { - x = ldub(s1 + i); - y = ldub(s2 + i); - HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y); - if (x < y) { - cc = 1; - goto done; - } else if (x > y) { - cc = 2; - goto done; - } - } - cc = 0; - done: - HELPER_LOG("\n"); - return cc; -} - -/* compare logical under mask */ -uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr) -{ - uint8_t r, d; - uint32_t cc; - - HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __func__, r1, - mask, addr); - cc = 0; - while (mask) { - if (mask & 8) { - d = ldub(addr); - r = (r1 & 0xff000000UL) >> 24; - HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d, - addr); - if (r < d) { - cc = 1; - break; - } else if (r > d) { - cc = 2; - break; - } - addr++; - } - mask = (mask << 1) & 0xf; - r1 <<= 8; - } - HELPER_LOG("\n"); - return cc; -} - -/* store character under mask */ -void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr) -{ - uint8_t r; - - HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%lx\n", __func__, r1, mask, - addr); - while (mask) { - if (mask & 8) { - r = (r1 & 0xff000000UL) >> 24; - stb(addr, r); - HELPER_LOG("mask 0x%x %02x (0x%lx) ", mask, r, addr); - addr++; - } - mask = (mask << 1) & 0xf; - r1 <<= 8; - } - HELPER_LOG("\n"); -} - -static inline uint64_t get_address(int x2, int b2, int d2) -{ - uint64_t r = d2; - - if (x2) { - r += env->regs[x2]; - } - - if (b2) { - r += env->regs[b2]; - } - - /* 31-Bit mode */ - if (!(env->psw.mask & PSW_MASK_64)) { - r &= 0x7fffffff; - } - - return r; -} - -static inline uint64_t get_address_31fix(int reg) -{ - uint64_t r = env->regs[reg]; - - /* 31-Bit mode */ - if (!(env->psw.mask & PSW_MASK_64)) { - r &= 0x7fffffff; - } - - return r; -} - -/* search string (c is byte to search, r2 is string, r1 end of string) */ -uint32_t HELPER(srst)(uint32_t c, uint32_t r1, uint32_t r2) -{ - uint64_t i; - uint32_t cc = 2; - uint64_t str = get_address_31fix(r2); - uint64_t end = get_address_31fix(r1); - - HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __func__, - c, env->regs[r1], env->regs[r2]); - - for (i = str; i != end; i++) { - if (ldub(i) == c) { - env->regs[r1] = i; - cc = 1; - break; - } - } - - return cc; -} - -/* unsigned string compare (c is string terminator) */ -uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2) -{ - uint64_t s1 = get_address_31fix(r1); - uint64_t s2 = get_address_31fix(r2); - uint8_t v1, v2; - uint32_t cc; - - c = c & 0xff; -#ifdef CONFIG_USER_ONLY - if (!c) { - HELPER_LOG("%s: comparing '%s' and '%s'\n", - __func__, (char *)g2h(s1), (char *)g2h(s2)); - } -#endif - for (;;) { - v1 = ldub(s1); - v2 = ldub(s2); - if ((v1 == c || v2 == c) || (v1 != v2)) { - break; - } - s1++; - s2++; - } - - if (v1 == v2) { - cc = 0; - } else { - cc = (v1 < v2) ? 1 : 2; - /* FIXME: 31-bit mode! */ - env->regs[r1] = s1; - env->regs[r2] = s2; - } - return cc; -} - -/* move page */ -void HELPER(mvpg)(uint64_t r0, uint64_t r1, uint64_t r2) -{ - /* XXX missing r0 handling */ -#ifdef CONFIG_USER_ONLY - int i; - - for (i = 0; i < TARGET_PAGE_SIZE; i++) { - stb(r1 + i, ldub(r2 + i)); - } -#else - mvc_fast_memmove(env, TARGET_PAGE_SIZE, r1, r2); -#endif -} - -/* string copy (c is string terminator) */ -void HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2) -{ - uint64_t dest = get_address_31fix(r1); - uint64_t src = get_address_31fix(r2); - uint8_t v; - - c = c & 0xff; -#ifdef CONFIG_USER_ONLY - if (!c) { - HELPER_LOG("%s: copy '%s' to 0x%lx\n", __func__, (char *)g2h(src), - dest); - } -#endif - for (;;) { - v = ldub(src); - stb(dest, v); - if (v == c) { - break; - } - src++; - dest++; - } - env->regs[r1] = dest; /* FIXME: 31-bit mode! */ -} - -/* compare and swap 64-bit */ -uint32_t HELPER(csg)(uint32_t r1, uint64_t a2, uint32_t r3) -{ - /* FIXME: locking? */ - uint32_t cc; - uint64_t v2 = ldq(a2); - - if (env->regs[r1] == v2) { - cc = 0; - stq(a2, env->regs[r3]); - } else { - cc = 1; - env->regs[r1] = v2; - } - return cc; -} - -/* compare double and swap 64-bit */ -uint32_t HELPER(cdsg)(uint32_t r1, uint64_t a2, uint32_t r3) -{ - /* FIXME: locking? */ - uint32_t cc; - uint64_t v2_hi = ldq(a2); - uint64_t v2_lo = ldq(a2 + 8); - uint64_t v1_hi = env->regs[r1]; - uint64_t v1_lo = env->regs[r1 + 1]; - - if ((v1_hi == v2_hi) && (v1_lo == v2_lo)) { - cc = 0; - stq(a2, env->regs[r3]); - stq(a2 + 8, env->regs[r3 + 1]); - } else { - cc = 1; - env->regs[r1] = v2_hi; - env->regs[r1 + 1] = v2_lo; - } - - return cc; -} - -/* compare and swap 32-bit */ -uint32_t HELPER(cs)(uint32_t r1, uint64_t a2, uint32_t r3) -{ - /* FIXME: locking? */ - uint32_t cc; - uint32_t v2 = ldl(a2); - - HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __func__, r1, a2, r3); - if (((uint32_t)env->regs[r1]) == v2) { - cc = 0; - stl(a2, (uint32_t)env->regs[r3]); - } else { - cc = 1; - env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | v2; - } - return cc; -} - -static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask) -{ - int pos = 24; /* top of the lower half of r1 */ - uint64_t rmask = 0xff000000ULL; - uint8_t val = 0; - int ccd = 0; - uint32_t cc = 0; - - while (mask) { - if (mask & 8) { - env->regs[r1] &= ~rmask; - val = ldub(address); - if ((val & 0x80) && !ccd) { - cc = 1; - } - ccd = 1; - if (val && cc == 0) { - cc = 2; - } - env->regs[r1] |= (uint64_t)val << pos; - address++; - } - mask = (mask << 1) & 0xf; - pos -= 8; - rmask >>= 8; - } - - return cc; -} - -/* execute instruction - this instruction executes an insn modified with the contents of r1 - it does not change the executed instruction in memory - it does not change the program counter - in other words: tricky... - currently implemented by interpreting the cases it is most commonly used in -*/ -uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret) -{ - uint16_t insn = lduw_code(addr); - - HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __func__, v1, addr, - insn); - if ((insn & 0xf0ff) == 0xd000) { - uint32_t l, insn2, b1, b2, d1, d2; - - l = v1 & 0xff; - insn2 = ldl_code(addr + 2); - b1 = (insn2 >> 28) & 0xf; - b2 = (insn2 >> 12) & 0xf; - d1 = (insn2 >> 16) & 0xfff; - d2 = insn2 & 0xfff; - switch (insn & 0xf00) { - case 0x200: - helper_mvc(l, get_address(0, b1, d1), get_address(0, b2, d2)); - break; - case 0x500: - cc = helper_clc(l, get_address(0, b1, d1), get_address(0, b2, d2)); - break; - case 0x700: - cc = helper_xc(l, get_address(0, b1, d1), get_address(0, b2, d2)); - break; - case 0xc00: - helper_tr(l, get_address(0, b1, d1), get_address(0, b2, d2)); - break; - default: - goto abort; - break; - } - } else if ((insn & 0xff00) == 0x0a00) { - /* supervisor call */ - HELPER_LOG("%s: svc %ld via execute\n", __func__, (insn | v1) & 0xff); - env->psw.addr = ret - 4; - env->int_svc_code = (insn | v1) & 0xff; - env->int_svc_ilc = 4; - helper_exception(EXCP_SVC); - } else if ((insn & 0xff00) == 0xbf00) { - uint32_t insn2, r1, r3, b2, d2; - - insn2 = ldl_code(addr + 2); - r1 = (insn2 >> 20) & 0xf; - r3 = (insn2 >> 16) & 0xf; - b2 = (insn2 >> 12) & 0xf; - d2 = insn2 & 0xfff; - cc = helper_icm(r1, get_address(0, b2, d2), r3); - } else { - abort: - cpu_abort(env, "EXECUTE on instruction prefix 0x%x not implemented\n", - insn); - } - return cc; -} - -/* store character under mask high operates on the upper half of r1 */ -void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask) -{ - int pos = 56; /* top of the upper half of r1 */ - - while (mask) { - if (mask & 8) { - stb(address, (env->regs[r1] >> pos) & 0xff); - address++; - } - mask = (mask << 1) & 0xf; - pos -= 8; - } -} - -/* insert character under mask high; same as icm, but operates on the - upper half of r1 */ -uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask) -{ - int pos = 56; /* top of the upper half of r1 */ - uint64_t rmask = 0xff00000000000000ULL; - uint8_t val = 0; - int ccd = 0; - uint32_t cc = 0; - - while (mask) { - if (mask & 8) { - env->regs[r1] &= ~rmask; - val = ldub(address); - if ((val & 0x80) && !ccd) { - cc = 1; - } - ccd = 1; - if (val && cc == 0) { - cc = 2; - } - env->regs[r1] |= (uint64_t)val << pos; - address++; - } - mask = (mask << 1) & 0xf; - pos -= 8; - rmask >>= 8; - } - - return cc; -} - -/* load access registers r1 to r3 from memory at a2 */ -void HELPER(lam)(uint32_t r1, uint64_t a2, uint32_t r3) -{ - int i; - - for (i = r1;; i = (i + 1) % 16) { - env->aregs[i] = ldl(a2); - a2 += 4; - - if (i == r3) { - break; - } - } -} - -/* store access registers r1 to r3 in memory at a2 */ -void HELPER(stam)(uint32_t r1, uint64_t a2, uint32_t r3) -{ - int i; - - for (i = r1;; i = (i + 1) % 16) { - stl(a2, env->aregs[i]); - a2 += 4; - - if (i == r3) { - break; - } - } -} - -/* move long */ -uint32_t HELPER(mvcl)(uint32_t r1, uint32_t r2) -{ - uint64_t destlen = env->regs[r1 + 1] & 0xffffff; - uint64_t dest = get_address_31fix(r1); - uint64_t srclen = env->regs[r2 + 1] & 0xffffff; - uint64_t src = get_address_31fix(r2); - uint8_t pad = src >> 24; - uint8_t v; - uint32_t cc; - - if (destlen == srclen) { - cc = 0; - } else if (destlen < srclen) { - cc = 1; - } else { - cc = 2; - } - - if (srclen > destlen) { - srclen = destlen; - } - - for (; destlen && srclen; src++, dest++, destlen--, srclen--) { - v = ldub(src); - stb(dest, v); - } - - for (; destlen; dest++, destlen--) { - stb(dest, pad); - } - - env->regs[r1 + 1] = destlen; - /* can't use srclen here, we trunc'ed it */ - env->regs[r2 + 1] -= src - env->regs[r2]; - env->regs[r1] = dest; - env->regs[r2] = src; - - return cc; -} - -/* move long extended another memcopy insn with more bells and whistles */ -uint32_t HELPER(mvcle)(uint32_t r1, uint64_t a2, uint32_t r3) -{ - uint64_t destlen = env->regs[r1 + 1]; - uint64_t dest = env->regs[r1]; - uint64_t srclen = env->regs[r3 + 1]; - uint64_t src = env->regs[r3]; - uint8_t pad = a2 & 0xff; - uint8_t v; - uint32_t cc; - - if (!(env->psw.mask & PSW_MASK_64)) { - destlen = (uint32_t)destlen; - srclen = (uint32_t)srclen; - dest &= 0x7fffffff; - src &= 0x7fffffff; - } - - if (destlen == srclen) { - cc = 0; - } else if (destlen < srclen) { - cc = 1; - } else { - cc = 2; - } - - if (srclen > destlen) { - srclen = destlen; - } - - for (; destlen && srclen; src++, dest++, destlen--, srclen--) { - v = ldub(src); - stb(dest, v); - } - - for (; destlen; dest++, destlen--) { - stb(dest, pad); - } - - env->regs[r1 + 1] = destlen; - /* can't use srclen here, we trunc'ed it */ - /* FIXME: 31-bit mode! */ - env->regs[r3 + 1] -= src - env->regs[r3]; - env->regs[r1] = dest; - env->regs[r3] = src; - - return cc; -} - -/* compare logical long extended memcompare insn with padding */ -uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3) -{ - uint64_t destlen = env->regs[r1 + 1]; - uint64_t dest = get_address_31fix(r1); - uint64_t srclen = env->regs[r3 + 1]; - uint64_t src = get_address_31fix(r3); - uint8_t pad = a2 & 0xff; - uint8_t v1 = 0, v2 = 0; - uint32_t cc = 0; - - if (!(destlen || srclen)) { - return cc; - } - - if (srclen > destlen) { - srclen = destlen; - } - - for (; destlen || srclen; src++, dest++, destlen--, srclen--) { - v1 = srclen ? ldub(src) : pad; - v2 = destlen ? ldub(dest) : pad; - if (v1 != v2) { - cc = (v1 < v2) ? 1 : 2; - break; - } - } - - env->regs[r1 + 1] = destlen; - /* can't use srclen here, we trunc'ed it */ - env->regs[r3 + 1] -= src - env->regs[r3]; - env->regs[r1] = dest; - env->regs[r3] = src; - - return cc; -} - -/* checksum */ -void HELPER(cksm)(uint32_t r1, uint32_t r2) -{ - uint64_t src = get_address_31fix(r2); - uint64_t src_len = env->regs[(r2 + 1) & 15]; - uint64_t cksm = (uint32_t)env->regs[r1]; - - while (src_len >= 4) { - cksm += ldl(src); - - /* move to next word */ - src_len -= 4; - src += 4; - } - - switch (src_len) { - case 0: - break; - case 1: - cksm += ldub(src) << 24; - break; - case 2: - cksm += lduw(src) << 16; - break; - case 3: - cksm += lduw(src) << 16; - cksm += ldub(src + 2) << 8; - break; - } - - /* indicate we've processed everything */ - env->regs[r2] = src + src_len; - env->regs[(r2 + 1) & 15] = 0; - - /* store result */ - env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | - ((uint32_t)cksm + (cksm >> 32)); -} - -void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src) -{ - int len_dest = len >> 4; - int len_src = len & 0xf; - uint8_t b; - int second_nibble = 0; - - dest += len_dest; - src += len_src; - - /* last byte is special, it only flips the nibbles */ - b = ldub(src); - stb(dest, (b << 4) | (b >> 4)); - src--; - len_src--; - - /* now pad every nibble with 0xf0 */ - - while (len_dest > 0) { - uint8_t cur_byte = 0; - - if (len_src > 0) { - cur_byte = ldub(src); - } - - len_dest--; - dest--; - - /* only advance one nibble at a time */ - if (second_nibble) { - cur_byte >>= 4; - len_src--; - src--; - } - second_nibble = !second_nibble; - - /* digit */ - cur_byte = (cur_byte & 0xf); - /* zone bits */ - cur_byte |= 0xf0; - - stb(dest, cur_byte); - } -} - -void HELPER(tr)(uint32_t len, uint64_t array, uint64_t trans) -{ - int i; - - for (i = 0; i <= len; i++) { - uint8_t byte = ldub(array + i); - uint8_t new_byte = ldub(trans + byte); - - stb(array + i, new_byte); - } -} - #ifndef CONFIG_USER_ONLY void program_interrupt(CPUS390XState *env, uint32_t code, int ilc) { @@ -1267,206 +384,6 @@ uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1) return cc; } -void HELPER(lctlg)(uint32_t r1, uint64_t a2, uint32_t r3) -{ - int i; - uint64_t src = a2; - - for (i = r1;; i = (i + 1) % 16) { - env->cregs[i] = ldq(src); - HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n", - i, src, env->cregs[i]); - src += sizeof(uint64_t); - - if (i == r3) { - break; - } - } - - tlb_flush(env, 1); -} - -void HELPER(lctl)(uint32_t r1, uint64_t a2, uint32_t r3) -{ - int i; - uint64_t src = a2; - - for (i = r1;; i = (i + 1) % 16) { - env->cregs[i] = (env->cregs[i] & 0xFFFFFFFF00000000ULL) | ldl(src); - src += sizeof(uint32_t); - - if (i == r3) { - break; - } - } - - tlb_flush(env, 1); -} - -void HELPER(stctg)(uint32_t r1, uint64_t a2, uint32_t r3) -{ - int i; - uint64_t dest = a2; - - for (i = r1;; i = (i + 1) % 16) { - stq(dest, env->cregs[i]); - dest += sizeof(uint64_t); - - if (i == r3) { - break; - } - } -} - -void HELPER(stctl)(uint32_t r1, uint64_t a2, uint32_t r3) -{ - int i; - uint64_t dest = a2; - - for (i = r1;; i = (i + 1) % 16) { - stl(dest, env->cregs[i]); - dest += sizeof(uint32_t); - - if (i == r3) { - break; - } - } -} - -uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2) -{ - /* XXX implement */ - - return 0; -} - -/* insert storage key extended */ -uint64_t HELPER(iske)(uint64_t r2) -{ - uint64_t addr = get_address(0, 0, r2); - - if (addr > ram_size) { - return 0; - } - - return env->storage_keys[addr / TARGET_PAGE_SIZE]; -} - -/* set storage key extended */ -void HELPER(sske)(uint32_t r1, uint64_t r2) -{ - uint64_t addr = get_address(0, 0, r2); - - if (addr > ram_size) { - return; - } - - env->storage_keys[addr / TARGET_PAGE_SIZE] = r1; -} - -/* reset reference bit extended */ -uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2) -{ - uint8_t re; - uint8_t key; - - if (r2 > ram_size) { - return 0; - } - - key = env->storage_keys[r2 / TARGET_PAGE_SIZE]; - re = key & (SK_R | SK_C); - env->storage_keys[r2 / TARGET_PAGE_SIZE] = (key & ~SK_R); - - /* - * cc - * - * 0 Reference bit zero; change bit zero - * 1 Reference bit zero; change bit one - * 2 Reference bit one; change bit zero - * 3 Reference bit one; change bit one - */ - - return re >> 1; -} - -/* compare and swap and purge */ -uint32_t HELPER(csp)(uint32_t r1, uint32_t r2) -{ - uint32_t cc; - uint32_t o1 = env->regs[r1]; - uint64_t a2 = get_address_31fix(r2) & ~3ULL; - uint32_t o2 = ldl(a2); - - if (o1 == o2) { - stl(a2, env->regs[(r1 + 1) & 15]); - if (env->regs[r2] & 0x3) { - /* flush TLB / ALB */ - tlb_flush(env, 1); - } - cc = 0; - } else { - env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | o2; - cc = 1; - } - - return cc; -} - -static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2, - uint64_t mode2) -{ - target_ulong src, dest; - int flags, cc = 0, i; - - if (!l) { - return 0; - } else if (l > 256) { - /* max 256 */ - l = 256; - cc = 3; - } - - if (mmu_translate(env, a1 & TARGET_PAGE_MASK, 1, mode1, &dest, &flags)) { - cpu_loop_exit(env); - } - dest |= a1 & ~TARGET_PAGE_MASK; - - if (mmu_translate(env, a2 & TARGET_PAGE_MASK, 0, mode2, &src, &flags)) { - cpu_loop_exit(env); - } - src |= a2 & ~TARGET_PAGE_MASK; - - /* XXX replace w/ memcpy */ - for (i = 0; i < l; i++) { - /* XXX be more clever */ - if ((((dest + i) & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) || - (((src + i) & TARGET_PAGE_MASK) != (src & TARGET_PAGE_MASK))) { - mvc_asc(l - i, a1 + i, mode1, a2 + i, mode2); - break; - } - stb_phys(dest + i, ldub_phys(src + i)); - } - - return cc; -} - -uint32_t HELPER(mvcs)(uint64_t l, uint64_t a1, uint64_t a2) -{ - HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n", - __func__, l, a1, a2); - - return mvc_asc(l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY); -} - -uint32_t HELPER(mvcp)(uint64_t l, uint64_t a1, uint64_t a2) -{ - HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n", - __func__, l, a1, a2); - - return mvc_asc(l, a1, PSW_ASC_PRIMARY, a2, PSW_ASC_SECONDARY); -} - uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr) { int cc = 0; @@ -1508,78 +425,4 @@ uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr) return cc; } - -/* invalidate pte */ -void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr) -{ - uint64_t page = vaddr & TARGET_PAGE_MASK; - uint64_t pte = 0; - - /* XXX broadcast to other CPUs */ - - /* XXX Linux is nice enough to give us the exact pte address. - According to spec we'd have to find it out ourselves */ - /* XXX Linux is fine with overwriting the pte, the spec requires - us to only set the invalid bit */ - stq_phys(pte_addr, pte | _PAGE_INVALID); - - /* XXX we exploit the fact that Linux passes the exact virtual - address here - it's not obliged to! */ - tlb_flush_page(env, page); - - /* XXX 31-bit hack */ - if (page & 0x80000000) { - tlb_flush_page(env, page & ~0x80000000); - } else { - tlb_flush_page(env, page | 0x80000000); - } -} - -/* flush local tlb */ -void HELPER(ptlb)(void) -{ - tlb_flush(env, 1); -} - -/* store using real address */ -void HELPER(stura)(uint64_t addr, uint32_t v1) -{ - stw_phys(get_address(0, 0, addr), v1); -} - -/* load real address */ -uint32_t HELPER(lra)(uint64_t addr, uint32_t r1) -{ - uint32_t cc = 0; - int old_exc = env->exception_index; - uint64_t asc = env->psw.mask & PSW_MASK_ASC; - uint64_t ret; - int flags; - - /* XXX incomplete - has more corner cases */ - if (!(env->psw.mask & PSW_MASK_64) && (addr >> 32)) { - program_interrupt(env, PGM_SPECIAL_OP, 2); - } - - env->exception_index = old_exc; - if (mmu_translate(env, addr, 0, asc, &ret, &flags)) { - cc = 3; - } - if (env->exception_index == EXCP_PGM) { - ret = env->int_pgm_code | 0x80000000; - } else { - ret |= addr & ~TARGET_PAGE_MASK; - } - env->exception_index = old_exc; - - if (!(env->psw.mask & PSW_MASK_64)) { - env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | - (ret & 0xffffffffULL); - } else { - env->regs[r1] = ret; - } - - return cc; -} - #endif From aea1e885b2b59cf93d0db9356fd5bb6cb1780f01 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 07:33:35 +0000 Subject: [PATCH 0222/2270] target-s390x: rename op_helper.c to misc_helper.c Now op_helper.c contains miscellaneous helpers, rename it to misc_helper.c. Signed-off-by: Blue Swirl [agraf: fix conflict] Signed-off-by: Alexander Graf --- target-s390x/Makefile.objs | 6 +++--- target-s390x/cpu.h | 2 +- target-s390x/{op_helper.c => misc_helper.c} | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename target-s390x/{op_helper.c => misc_helper.c} (99%) diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs index b9b306170c..a87d26fae7 100644 --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -1,10 +1,10 @@ -obj-y += translate.o op_helper.o helper.o cpu.o interrupt.o -obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o +obj-y += translate.o helper.o cpu.o interrupt.o +obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o obj-$(CONFIG_SOFTMMU) += machine.o obj-$(CONFIG_KVM) += kvm.o -$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/int_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/fpu_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) +$(obj)/misc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 97fde5e2ec..0ccb55182b 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -1005,7 +1005,7 @@ uint32_t set_cc_f64(float64 v1, float64 v2); uint32_t set_cc_nz_f32(float32 v); uint32_t set_cc_nz_f64(float64 v); -/* op_helper.c */ +/* misc_helper.c */ void program_interrupt(CPUS390XState *env, uint32_t code, int ilc); #endif diff --git a/target-s390x/op_helper.c b/target-s390x/misc_helper.c similarity index 99% rename from target-s390x/op_helper.c rename to target-s390x/misc_helper.c index bb8dbf55d0..1d5137f984 100644 --- a/target-s390x/op_helper.c +++ b/target-s390x/misc_helper.c @@ -1,5 +1,5 @@ /* - * S/390 helper routines + * S/390 misc helper routines * * Copyright (c) 2009 Ulrich Hecht * Copyright (c) 2009 Alexander Graf From 449c0d70b6d5692bafd8b028e2a8a4e0ed7076fe Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 07:33:36 +0000 Subject: [PATCH 0223/2270] target-s390x: avoid AREG0 for FPU helpers Make FPU helpers take a parameter for CPUState instead of relying on global env. Introduce temporary wrappers for FPU load and store ops. Signed-off-by: Blue Swirl Signed-off-by: Alexander Graf --- target-s390x/Makefile.objs | 1 - target-s390x/cc_helper.c | 4 +- target-s390x/cpu.h | 14 ++- target-s390x/fpu_helper.c | 184 +++++++++++++++++++------------------ target-s390x/helper.h | 126 ++++++++++++------------- target-s390x/mem_helper.c | 49 ++++++++++ target-s390x/translate.c | 70 +++++++------- 7 files changed, 257 insertions(+), 191 deletions(-) diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs index a87d26fae7..7d965e9ca9 100644 --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -4,7 +4,6 @@ obj-$(CONFIG_SOFTMMU) += machine.o obj-$(CONFIG_KVM) += kvm.o $(obj)/int_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) -$(obj)/fpu_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/misc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c index 2ac1659625..9c3a2c4595 100644 --- a/target-s390x/cc_helper.c +++ b/target-s390x/cc_helper.c @@ -473,10 +473,10 @@ static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, break; case CC_OP_LTGT_F32: - r = set_cc_f32(src, dst); + r = set_cc_f32(env, src, dst); break; case CC_OP_LTGT_F64: - r = set_cc_f64(src, dst); + r = set_cc_f64(env, src, dst); break; case CC_OP_NZ_F32: r = set_cc_nz_f32(dst); diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 0ccb55182b..9b7a2e3adc 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -1000,12 +1000,22 @@ static inline void cpu_pc_from_tb(CPUS390XState *env, TranslationBlock* tb) } /* fpu_helper.c */ -uint32_t set_cc_f32(float32 v1, float32 v2); -uint32_t set_cc_f64(float64 v1, float64 v2); +uint32_t set_cc_f32(CPUS390XState *env, float32 v1, float32 v2); +uint32_t set_cc_f64(CPUS390XState *env, float64 v1, float64 v2); uint32_t set_cc_nz_f32(float32 v); uint32_t set_cc_nz_f64(float64 v); /* misc_helper.c */ void program_interrupt(CPUS390XState *env, uint32_t code, int ilc); +/* temporary wrappers */ +uint32_t cpu_ldub_data(CPUS390XState *env, target_ulong ptr); +uint32_t cpu_lduw_data(CPUS390XState *env, target_ulong ptr); +uint32_t cpu_ldl_data(CPUS390XState *env, target_ulong ptr); +uint64_t cpu_ldq_data(CPUS390XState *env, target_ulong ptr); + +void cpu_stb_data(CPUS390XState *env, target_ulong ptr, uint32_t data); +void cpu_stw_data(CPUS390XState *env, target_ulong ptr, uint32_t data); +void cpu_stl_data(CPUS390XState *env, target_ulong ptr, uint32_t data); +void cpu_stq_data(CPUS390XState *env, target_ulong ptr, uint64_t data); #endif diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c index 1389052f5c..e23541922d 100644 --- a/target-s390x/fpu_helper.c +++ b/target-s390x/fpu_helper.c @@ -19,10 +19,10 @@ */ #include "cpu.h" -#include "dyngen-exec.h" #include "helper.h" -#if !defined(CONFIG_USER_ONLY) +/* temporarily disabled due to wrapper use */ +#if 0 && !defined(CONFIG_USER_ONLY) #include "softmmu_exec.h" #endif @@ -33,7 +33,7 @@ #define HELPER_LOG(x...) #endif -static inline int float_comp_to_cc(int float_compare) +static inline int float_comp_to_cc(CPUS390XState *env, int float_compare) { switch (float_compare) { case float_relation_equal: @@ -50,14 +50,16 @@ static inline int float_comp_to_cc(int float_compare) } /* condition codes for binary FP ops */ -uint32_t set_cc_f32(float32 v1, float32 v2) +uint32_t set_cc_f32(CPUS390XState *env, float32 v1, float32 v2) { - return float_comp_to_cc(float32_compare_quiet(v1, v2, &env->fpu_status)); + return float_comp_to_cc(env, float32_compare_quiet(v1, v2, + &env->fpu_status)); } -uint32_t set_cc_f64(float64 v1, float64 v2) +uint32_t set_cc_f64(CPUS390XState *env, float64 v1, float64 v2) { - return float_comp_to_cc(float64_compare_quiet(v1, v2, &env->fpu_status)); + return float_comp_to_cc(env, float64_compare_quiet(v1, v2, + &env->fpu_status)); } /* condition codes for unary FP ops */ @@ -101,14 +103,14 @@ static uint32_t set_cc_nz_f128(float128 v) } /* convert 32-bit int to 64-bit float */ -void HELPER(cdfbr)(uint32_t f1, int32_t v2) +void HELPER(cdfbr)(CPUS390XState *env, uint32_t f1, int32_t v2) { HELPER_LOG("%s: converting %d to f%d\n", __func__, v2, f1); env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status); } /* convert 32-bit int to 128-bit float */ -void HELPER(cxfbr)(uint32_t f1, int32_t v2) +void HELPER(cxfbr)(CPUS390XState *env, uint32_t f1, int32_t v2) { CPU_QuadU v1; @@ -118,21 +120,21 @@ void HELPER(cxfbr)(uint32_t f1, int32_t v2) } /* convert 64-bit int to 32-bit float */ -void HELPER(cegbr)(uint32_t f1, int64_t v2) +void HELPER(cegbr)(CPUS390XState *env, uint32_t f1, int64_t v2) { HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1); env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status); } /* convert 64-bit int to 64-bit float */ -void HELPER(cdgbr)(uint32_t f1, int64_t v2) +void HELPER(cdgbr)(CPUS390XState *env, uint32_t f1, int64_t v2) { HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1); env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status); } /* convert 64-bit int to 128-bit float */ -void HELPER(cxgbr)(uint32_t f1, int64_t v2) +void HELPER(cxgbr)(CPUS390XState *env, uint32_t f1, int64_t v2) { CPU_QuadU x1; @@ -144,7 +146,7 @@ void HELPER(cxgbr)(uint32_t f1, int64_t v2) } /* convert 32-bit int to 32-bit float */ -void HELPER(cefbr)(uint32_t f1, int32_t v2) +void HELPER(cefbr)(CPUS390XState *env, uint32_t f1, int32_t v2) { env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status); HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __func__, v2, @@ -152,7 +154,7 @@ void HELPER(cefbr)(uint32_t f1, int32_t v2) } /* 32-bit FP addition RR */ -uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(aebr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper, env->fregs[f2].l.upper, @@ -164,7 +166,7 @@ uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2) } /* 64-bit FP addition RR */ -uint32_t HELPER(adbr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(adbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d, &env->fpu_status); @@ -175,7 +177,7 @@ uint32_t HELPER(adbr)(uint32_t f1, uint32_t f2) } /* 32-bit FP subtraction RR */ -uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(sebr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper, env->fregs[f2].l.upper, @@ -187,7 +189,7 @@ uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2) } /* 64-bit FP subtraction RR */ -uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(sdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d, &env->fpu_status); @@ -198,7 +200,7 @@ uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2) } /* 32-bit FP division RR */ -void HELPER(debr)(uint32_t f1, uint32_t f2) +void HELPER(debr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { env->fregs[f1].l.upper = float32_div(env->fregs[f1].l.upper, env->fregs[f2].l.upper, @@ -206,7 +208,7 @@ void HELPER(debr)(uint32_t f1, uint32_t f2) } /* 128-bit FP division RR */ -void HELPER(dxbr)(uint32_t f1, uint32_t f2) +void HELPER(dxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { CPU_QuadU v1; CPU_QuadU v2; @@ -222,14 +224,14 @@ void HELPER(dxbr)(uint32_t f1, uint32_t f2) } /* 64-bit FP multiplication RR */ -void HELPER(mdbr)(uint32_t f1, uint32_t f2) +void HELPER(mdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { env->fregs[f1].d = float64_mul(env->fregs[f1].d, env->fregs[f2].d, &env->fpu_status); } /* 128-bit FP multiplication RR */ -void HELPER(mxbr)(uint32_t f1, uint32_t f2) +void HELPER(mxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { CPU_QuadU v1; CPU_QuadU v2; @@ -245,14 +247,14 @@ void HELPER(mxbr)(uint32_t f1, uint32_t f2) } /* convert 32-bit float to 64-bit float */ -void HELPER(ldebr)(uint32_t r1, uint32_t r2) +void HELPER(ldebr)(CPUS390XState *env, uint32_t r1, uint32_t r2) { env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper, &env->fpu_status); } /* convert 128-bit float to 64-bit float */ -void HELPER(ldxbr)(uint32_t f1, uint32_t f2) +void HELPER(ldxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { CPU_QuadU x2; @@ -263,7 +265,7 @@ void HELPER(ldxbr)(uint32_t f1, uint32_t f2) } /* convert 64-bit float to 128-bit float */ -void HELPER(lxdbr)(uint32_t f1, uint32_t f2) +void HELPER(lxdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { CPU_QuadU res; @@ -273,7 +275,7 @@ void HELPER(lxdbr)(uint32_t f1, uint32_t f2) } /* convert 64-bit float to 32-bit float */ -void HELPER(ledbr)(uint32_t f1, uint32_t f2) +void HELPER(ledbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { float64 d2 = env->fregs[f2].d; @@ -281,7 +283,7 @@ void HELPER(ledbr)(uint32_t f1, uint32_t f2) } /* convert 128-bit float to 32-bit float */ -void HELPER(lexbr)(uint32_t f1, uint32_t f2) +void HELPER(lexbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { CPU_QuadU x2; @@ -292,7 +294,7 @@ void HELPER(lexbr)(uint32_t f1, uint32_t f2) } /* absolute value of 32-bit float */ -uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(lpebr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { float32 v1; float32 v2 = env->fregs[f2].d; @@ -303,7 +305,7 @@ uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2) } /* absolute value of 64-bit float */ -uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(lpdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { float64 v1; float64 v2 = env->fregs[f2].d; @@ -314,7 +316,7 @@ uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2) } /* absolute value of 128-bit float */ -uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(lpxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { CPU_QuadU v1; CPU_QuadU v2; @@ -328,21 +330,21 @@ uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2) } /* load and test 64-bit float */ -uint32_t HELPER(ltdbr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(ltdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { env->fregs[f1].d = env->fregs[f2].d; return set_cc_nz_f64(env->fregs[f1].d); } /* load and test 32-bit float */ -uint32_t HELPER(ltebr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(ltebr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { env->fregs[f1].l.upper = env->fregs[f2].l.upper; return set_cc_nz_f32(env->fregs[f1].l.upper); } /* load and test 128-bit float */ -uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(ltxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { CPU_QuadU x; @@ -354,7 +356,7 @@ uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2) } /* load complement of 32-bit float */ -uint32_t HELPER(lcebr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(lcebr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { env->fregs[f1].l.upper = float32_chs(env->fregs[f2].l.upper); @@ -362,7 +364,7 @@ uint32_t HELPER(lcebr)(uint32_t f1, uint32_t f2) } /* load complement of 64-bit float */ -uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(lcdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { env->fregs[f1].d = float64_chs(env->fregs[f2].d); @@ -370,7 +372,7 @@ uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2) } /* load complement of 128-bit float */ -uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(lcxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { CPU_QuadU x1, x2; @@ -383,7 +385,7 @@ uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2) } /* 32-bit FP addition RM */ -void HELPER(aeb)(uint32_t f1, uint32_t val) +void HELPER(aeb)(CPUS390XState *env, uint32_t f1, uint32_t val) { float32 v1 = env->fregs[f1].l.upper; CPU_FloatU v2; @@ -395,7 +397,7 @@ void HELPER(aeb)(uint32_t f1, uint32_t val) } /* 32-bit FP division RM */ -void HELPER(deb)(uint32_t f1, uint32_t val) +void HELPER(deb)(CPUS390XState *env, uint32_t f1, uint32_t val) { float32 v1 = env->fregs[f1].l.upper; CPU_FloatU v2; @@ -407,7 +409,7 @@ void HELPER(deb)(uint32_t f1, uint32_t val) } /* 32-bit FP multiplication RM */ -void HELPER(meeb)(uint32_t f1, uint32_t val) +void HELPER(meeb)(CPUS390XState *env, uint32_t f1, uint32_t val) { float32 v1 = env->fregs[f1].l.upper; CPU_FloatU v2; @@ -419,29 +421,29 @@ void HELPER(meeb)(uint32_t f1, uint32_t val) } /* 32-bit FP compare RR */ -uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(cebr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { float32 v1 = env->fregs[f1].l.upper; float32 v2 = env->fregs[f2].l.upper; HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __func__, v1, f1, v2); - return set_cc_f32(v1, v2); + return set_cc_f32(env, v1, v2); } /* 64-bit FP compare RR */ -uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(cdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { float64 v1 = env->fregs[f1].d; float64 v2 = env->fregs[f2].d; HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __func__, v1, f1, v2); - return set_cc_f64(v1, v2); + return set_cc_f64(env, v1, v2); } /* 128-bit FP compare RR */ -uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(cxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { CPU_QuadU v1; CPU_QuadU v2; @@ -451,29 +453,29 @@ uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2) v2.ll.upper = env->fregs[f2].ll; v2.ll.lower = env->fregs[f2 + 2].ll; - return float_comp_to_cc(float128_compare_quiet(v1.q, v2.q, + return float_comp_to_cc(env, float128_compare_quiet(v1.q, v2.q, &env->fpu_status)); } /* 64-bit FP compare RM */ -uint32_t HELPER(cdb)(uint32_t f1, uint64_t a2) +uint32_t HELPER(cdb)(CPUS390XState *env, uint32_t f1, uint64_t a2) { float64 v1 = env->fregs[f1].d; CPU_DoubleU v2; - v2.ll = ldq(a2); + v2.ll = cpu_ldq_data(env, a2); HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__, v1, f1, v2.d); - return set_cc_f64(v1, v2.d); + return set_cc_f64(env, v1, v2.d); } /* 64-bit FP addition RM */ -uint32_t HELPER(adb)(uint32_t f1, uint64_t a2) +uint32_t HELPER(adb)(CPUS390XState *env, uint32_t f1, uint64_t a2) { float64 v1 = env->fregs[f1].d; CPU_DoubleU v2; - v2.ll = ldq(a2); + v2.ll = cpu_ldq_data(env, a2); HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __func__, v1, f1, v2.d); env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status); @@ -481,7 +483,7 @@ uint32_t HELPER(adb)(uint32_t f1, uint64_t a2) } /* 32-bit FP subtraction RM */ -void HELPER(seb)(uint32_t f1, uint32_t val) +void HELPER(seb)(CPUS390XState *env, uint32_t f1, uint32_t val) { float32 v1 = env->fregs[f1].l.upper; CPU_FloatU v2; @@ -491,41 +493,41 @@ void HELPER(seb)(uint32_t f1, uint32_t val) } /* 64-bit FP subtraction RM */ -uint32_t HELPER(sdb)(uint32_t f1, uint64_t a2) +uint32_t HELPER(sdb)(CPUS390XState *env, uint32_t f1, uint64_t a2) { float64 v1 = env->fregs[f1].d; CPU_DoubleU v2; - v2.ll = ldq(a2); + v2.ll = cpu_ldq_data(env, a2); env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status); return set_cc_nz_f64(v1); } /* 64-bit FP multiplication RM */ -void HELPER(mdb)(uint32_t f1, uint64_t a2) +void HELPER(mdb)(CPUS390XState *env, uint32_t f1, uint64_t a2) { float64 v1 = env->fregs[f1].d; CPU_DoubleU v2; - v2.ll = ldq(a2); + v2.ll = cpu_ldq_data(env, a2); HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __func__, v1, f1, v2.d); env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status); } /* 64-bit FP division RM */ -void HELPER(ddb)(uint32_t f1, uint64_t a2) +void HELPER(ddb)(CPUS390XState *env, uint32_t f1, uint64_t a2) { float64 v1 = env->fregs[f1].d; CPU_DoubleU v2; - v2.ll = ldq(a2); + v2.ll = cpu_ldq_data(env, a2); HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __func__, v1, f1, v2.d); env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status); } -static void set_round_mode(int m3) +static void set_round_mode(CPUS390XState *env, int m3) { switch (m3) { case 0: @@ -553,33 +555,36 @@ static void set_round_mode(int m3) } /* convert 32-bit float to 64-bit int */ -uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3) +uint32_t HELPER(cgebr)(CPUS390XState *env, uint32_t r1, uint32_t f2, + uint32_t m3) { float32 v2 = env->fregs[f2].l.upper; - set_round_mode(m3); + set_round_mode(env, m3); env->regs[r1] = float32_to_int64(v2, &env->fpu_status); return set_cc_nz_f32(v2); } /* convert 64-bit float to 64-bit int */ -uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3) +uint32_t HELPER(cgdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2, + uint32_t m3) { float64 v2 = env->fregs[f2].d; - set_round_mode(m3); + set_round_mode(env, m3); env->regs[r1] = float64_to_int64(v2, &env->fpu_status); return set_cc_nz_f64(v2); } /* convert 128-bit float to 64-bit int */ -uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3) +uint32_t HELPER(cgxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2, + uint32_t m3) { CPU_QuadU v2; v2.ll.upper = env->fregs[f2].ll; v2.ll.lower = env->fregs[f2 + 2].ll; - set_round_mode(m3); + set_round_mode(env, m3); env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status); if (float128_is_any_nan(v2.q)) { return 3; @@ -593,29 +598,32 @@ uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3) } /* convert 32-bit float to 32-bit int */ -uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3) +uint32_t HELPER(cfebr)(CPUS390XState *env, uint32_t r1, uint32_t f2, + uint32_t m3) { float32 v2 = env->fregs[f2].l.upper; - set_round_mode(m3); + set_round_mode(env, m3); env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | float32_to_int32(v2, &env->fpu_status); return set_cc_nz_f32(v2); } /* convert 64-bit float to 32-bit int */ -uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3) +uint32_t HELPER(cfdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2, + uint32_t m3) { float64 v2 = env->fregs[f2].d; - set_round_mode(m3); + set_round_mode(env, m3); env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | float64_to_int32(v2, &env->fpu_status); return set_cc_nz_f64(v2); } /* convert 128-bit float to 32-bit int */ -uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3) +uint32_t HELPER(cfxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2, + uint32_t m3) { CPU_QuadU v2; @@ -627,19 +635,19 @@ uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3) } /* load 32-bit FP zero */ -void HELPER(lzer)(uint32_t f1) +void HELPER(lzer)(CPUS390XState *env, uint32_t f1) { env->fregs[f1].l.upper = float32_zero; } /* load 64-bit FP zero */ -void HELPER(lzdr)(uint32_t f1) +void HELPER(lzdr)(CPUS390XState *env, uint32_t f1) { env->fregs[f1].d = float64_zero; } /* load 128-bit FP zero */ -void HELPER(lzxr)(uint32_t f1) +void HELPER(lzxr)(CPUS390XState *env, uint32_t f1) { CPU_QuadU x; @@ -649,7 +657,7 @@ void HELPER(lzxr)(uint32_t f1) } /* 128-bit FP subtraction RR */ -uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(sxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { CPU_QuadU v1; CPU_QuadU v2; @@ -666,7 +674,7 @@ uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2) } /* 128-bit FP addition RR */ -uint32_t HELPER(axbr)(uint32_t f1, uint32_t f2) +uint32_t HELPER(axbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { CPU_QuadU v1; CPU_QuadU v2; @@ -683,7 +691,7 @@ uint32_t HELPER(axbr)(uint32_t f1, uint32_t f2) } /* 32-bit FP multiplication RR */ -void HELPER(meebr)(uint32_t f1, uint32_t f2) +void HELPER(meebr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { env->fregs[f1].l.upper = float32_mul(env->fregs[f1].l.upper, env->fregs[f2].l.upper, @@ -691,19 +699,19 @@ void HELPER(meebr)(uint32_t f1, uint32_t f2) } /* 64-bit FP division RR */ -void HELPER(ddbr)(uint32_t f1, uint32_t f2) +void HELPER(ddbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { env->fregs[f1].d = float64_div(env->fregs[f1].d, env->fregs[f2].d, &env->fpu_status); } /* 64-bit FP multiply and add RM */ -void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3) +void HELPER(madb)(CPUS390XState *env, uint32_t f1, uint64_t a2, uint32_t f3) { CPU_DoubleU v2; HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __func__, f1, a2, f3); - v2.ll = ldq(a2); + v2.ll = cpu_ldq_data(env, a2); env->fregs[f1].d = float64_add(env->fregs[f1].d, float64_mul(v2.d, env->fregs[f3].d, &env->fpu_status), @@ -711,7 +719,7 @@ void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3) } /* 64-bit FP multiply and add RR */ -void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2) +void HELPER(madbr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2) { HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3); env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d, @@ -721,7 +729,7 @@ void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2) } /* 64-bit FP multiply and subtract RR */ -void HELPER(msdbr)(uint32_t f1, uint32_t f3, uint32_t f2) +void HELPER(msdbr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2) { HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3); env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d, @@ -731,7 +739,7 @@ void HELPER(msdbr)(uint32_t f1, uint32_t f3, uint32_t f2) } /* 32-bit FP multiply and add RR */ -void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2) +void HELPER(maebr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2) { env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper, float32_mul(env->fregs[f2].l.upper, @@ -741,29 +749,29 @@ void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2) } /* convert 32-bit float to 64-bit float */ -void HELPER(ldeb)(uint32_t f1, uint64_t a2) +void HELPER(ldeb)(CPUS390XState *env, uint32_t f1, uint64_t a2) { uint32_t v2; - v2 = ldl(a2); + v2 = cpu_ldl_data(env, a2); env->fregs[f1].d = float32_to_float64(v2, &env->fpu_status); } /* convert 64-bit float to 128-bit float */ -void HELPER(lxdb)(uint32_t f1, uint64_t a2) +void HELPER(lxdb)(CPUS390XState *env, uint32_t f1, uint64_t a2) { CPU_DoubleU v2; CPU_QuadU v1; - v2.ll = ldq(a2); + v2.ll = cpu_ldq_data(env, a2); v1.q = float64_to_float128(v2.d, &env->fpu_status); env->fregs[f1].ll = v1.ll.upper; env->fregs[f1 + 2].ll = v1.ll.lower; } /* test data class 32-bit */ -uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2) +uint32_t HELPER(tceb)(CPUS390XState *env, uint32_t f1, uint64_t m2) { float32 v1 = env->fregs[f1].l.upper; int neg = float32_is_neg(v1); @@ -785,7 +793,7 @@ uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2) } /* test data class 64-bit */ -uint32_t HELPER(tcdb)(uint32_t f1, uint64_t m2) +uint32_t HELPER(tcdb)(CPUS390XState *env, uint32_t f1, uint64_t m2) { float64 v1 = env->fregs[f1].d; int neg = float64_is_neg(v1); @@ -806,7 +814,7 @@ uint32_t HELPER(tcdb)(uint32_t f1, uint64_t m2) } /* test data class 128-bit */ -uint32_t HELPER(tcxb)(uint32_t f1, uint64_t m2) +uint32_t HELPER(tcxb)(CPUS390XState *env, uint32_t f1, uint64_t m2) { CPU_QuadU v1; uint32_t cc = 0; @@ -830,7 +838,7 @@ uint32_t HELPER(tcxb)(uint32_t f1, uint64_t m2) } /* square root 64-bit RR */ -void HELPER(sqdbr)(uint32_t f1, uint32_t f2) +void HELPER(sqdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status); } diff --git a/target-s390x/helper.h b/target-s390x/helper.h index 01c8d0ea84..af987732f6 100644 --- a/target-s390x/helper.h +++ b/target-s390x/helper.h @@ -45,70 +45,70 @@ DEF_HELPER_3(mvcle, i32, i32, i64, i32) DEF_HELPER_3(clcle, i32, i32, i64, i32) DEF_HELPER_3(slb, i32, i32, i32, i32) DEF_HELPER_4(slbg, i32, i32, i32, i64, i64) -DEF_HELPER_2(cefbr, void, i32, s32) -DEF_HELPER_2(cdfbr, void, i32, s32) -DEF_HELPER_2(cxfbr, void, i32, s32) -DEF_HELPER_2(cegbr, void, i32, s64) -DEF_HELPER_2(cdgbr, void, i32, s64) -DEF_HELPER_2(cxgbr, void, i32, s64) -DEF_HELPER_2(adbr, i32, i32, i32) -DEF_HELPER_2(aebr, i32, i32, i32) -DEF_HELPER_2(sebr, i32, i32, i32) -DEF_HELPER_2(sdbr, i32, i32, i32) -DEF_HELPER_2(debr, void, i32, i32) -DEF_HELPER_2(dxbr, void, i32, i32) -DEF_HELPER_2(mdbr, void, i32, i32) -DEF_HELPER_2(mxbr, void, i32, i32) -DEF_HELPER_2(ldebr, void, i32, i32) -DEF_HELPER_2(ldxbr, void, i32, i32) -DEF_HELPER_2(lxdbr, void, i32, i32) -DEF_HELPER_2(ledbr, void, i32, i32) -DEF_HELPER_2(lexbr, void, i32, i32) -DEF_HELPER_2(lpebr, i32, i32, i32) -DEF_HELPER_2(lpdbr, i32, i32, i32) -DEF_HELPER_2(lpxbr, i32, i32, i32) -DEF_HELPER_2(ltebr, i32, i32, i32) -DEF_HELPER_2(ltdbr, i32, i32, i32) -DEF_HELPER_2(ltxbr, i32, i32, i32) -DEF_HELPER_2(lcebr, i32, i32, i32) -DEF_HELPER_2(lcdbr, i32, i32, i32) -DEF_HELPER_2(lcxbr, i32, i32, i32) -DEF_HELPER_2(aeb, void, i32, i32) -DEF_HELPER_2(deb, void, i32, i32) -DEF_HELPER_2(meeb, void, i32, i32) -DEF_HELPER_2(cdb, i32, i32, i64) -DEF_HELPER_2(adb, i32, i32, i64) -DEF_HELPER_2(seb, void, i32, i32) -DEF_HELPER_2(sdb, i32, i32, i64) -DEF_HELPER_2(mdb, void, i32, i64) -DEF_HELPER_2(ddb, void, i32, i64) -DEF_HELPER_FLAGS_2(cebr, TCG_CALL_PURE, i32, i32, i32) -DEF_HELPER_FLAGS_2(cdbr, TCG_CALL_PURE, i32, i32, i32) -DEF_HELPER_FLAGS_2(cxbr, TCG_CALL_PURE, i32, i32, i32) -DEF_HELPER_3(cgebr, i32, i32, i32, i32) -DEF_HELPER_3(cgdbr, i32, i32, i32, i32) -DEF_HELPER_3(cgxbr, i32, i32, i32, i32) -DEF_HELPER_1(lzer, void, i32) -DEF_HELPER_1(lzdr, void, i32) -DEF_HELPER_1(lzxr, void, i32) -DEF_HELPER_3(cfebr, i32, i32, i32, i32) -DEF_HELPER_3(cfdbr, i32, i32, i32, i32) -DEF_HELPER_3(cfxbr, i32, i32, i32, i32) -DEF_HELPER_2(axbr, i32, i32, i32) -DEF_HELPER_2(sxbr, i32, i32, i32) -DEF_HELPER_2(meebr, void, i32, i32) -DEF_HELPER_2(ddbr, void, i32, i32) -DEF_HELPER_3(madb, void, i32, i64, i32) -DEF_HELPER_3(maebr, void, i32, i32, i32) -DEF_HELPER_3(madbr, void, i32, i32, i32) -DEF_HELPER_3(msdbr, void, i32, i32, i32) -DEF_HELPER_2(ldeb, void, i32, i64) -DEF_HELPER_2(lxdb, void, i32, i64) -DEF_HELPER_FLAGS_2(tceb, TCG_CALL_PURE, i32, i32, i64) -DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_PURE, i32, i32, i64) -DEF_HELPER_FLAGS_2(tcxb, TCG_CALL_PURE, i32, i32, i64) +DEF_HELPER_3(cefbr, void, env, i32, s32) +DEF_HELPER_3(cdfbr, void, env, i32, s32) +DEF_HELPER_3(cxfbr, void, env, i32, s32) +DEF_HELPER_3(cegbr, void, env, i32, s64) +DEF_HELPER_3(cdgbr, void, env, i32, s64) +DEF_HELPER_3(cxgbr, void, env, i32, s64) +DEF_HELPER_3(adbr, i32, env, i32, i32) +DEF_HELPER_3(aebr, i32, env, i32, i32) +DEF_HELPER_3(sebr, i32, env, i32, i32) +DEF_HELPER_3(sdbr, i32, env, i32, i32) +DEF_HELPER_3(debr, void, env, i32, i32) +DEF_HELPER_3(dxbr, void, env, i32, i32) +DEF_HELPER_3(mdbr, void, env, i32, i32) +DEF_HELPER_3(mxbr, void, env, i32, i32) +DEF_HELPER_3(ldebr, void, env, i32, i32) +DEF_HELPER_3(ldxbr, void, env, i32, i32) +DEF_HELPER_3(lxdbr, void, env, i32, i32) +DEF_HELPER_3(ledbr, void, env, i32, i32) +DEF_HELPER_3(lexbr, void, env, i32, i32) +DEF_HELPER_3(lpebr, i32, env, i32, i32) +DEF_HELPER_3(lpdbr, i32, env, i32, i32) +DEF_HELPER_3(lpxbr, i32, env, i32, i32) +DEF_HELPER_3(ltebr, i32, env, i32, i32) +DEF_HELPER_3(ltdbr, i32, env, i32, i32) +DEF_HELPER_3(ltxbr, i32, env, i32, i32) +DEF_HELPER_3(lcebr, i32, env, i32, i32) +DEF_HELPER_3(lcdbr, i32, env, i32, i32) +DEF_HELPER_3(lcxbr, i32, env, i32, i32) +DEF_HELPER_3(aeb, void, env, i32, i32) +DEF_HELPER_3(deb, void, env, i32, i32) +DEF_HELPER_3(meeb, void, env, i32, i32) +DEF_HELPER_3(cdb, i32, env, i32, i64) +DEF_HELPER_3(adb, i32, env, i32, i64) +DEF_HELPER_3(seb, void, env, i32, i32) +DEF_HELPER_3(sdb, i32, env, i32, i64) +DEF_HELPER_3(mdb, void, env, i32, i64) +DEF_HELPER_3(ddb, void, env, i32, i64) +DEF_HELPER_FLAGS_3(cebr, TCG_CALL_PURE, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(cdbr, TCG_CALL_PURE, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(cxbr, TCG_CALL_PURE, i32, env, i32, i32) +DEF_HELPER_4(cgebr, i32, env, i32, i32, i32) +DEF_HELPER_4(cgdbr, i32, env, i32, i32, i32) +DEF_HELPER_4(cgxbr, i32, env, i32, i32, i32) +DEF_HELPER_2(lzer, void, env, i32) +DEF_HELPER_2(lzdr, void, env, i32) +DEF_HELPER_2(lzxr, void, env, i32) +DEF_HELPER_4(cfebr, i32, env, i32, i32, i32) +DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32) +DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32) +DEF_HELPER_3(axbr, i32, env, i32, i32) +DEF_HELPER_3(sxbr, i32, env, i32, i32) +DEF_HELPER_3(meebr, void, env, i32, i32) +DEF_HELPER_3(ddbr, void, env, i32, i32) +DEF_HELPER_4(madb, void, env, i32, i64, i32) +DEF_HELPER_4(maebr, void, env, i32, i32, i32) +DEF_HELPER_4(madbr, void, env, i32, i32, i32) +DEF_HELPER_4(msdbr, void, env, i32, i32, i32) +DEF_HELPER_3(ldeb, void, env, i32, i64) +DEF_HELPER_3(lxdb, void, env, i32, i64) +DEF_HELPER_FLAGS_3(tceb, TCG_CALL_PURE, i32, env, i32, i64) +DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_PURE, i32, env, i32, i64) +DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE, i32, env, i32, i64) DEF_HELPER_2(flogr, i32, i32, i64) -DEF_HELPER_2(sqdbr, void, i32, i32) +DEF_HELPER_3(sqdbr, void, env, i32, i32) DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32) DEF_HELPER_3(unpk, void, i32, i64, i64) DEF_HELPER_3(tr, void, i32, i64, i64) diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c index ba05e65cd8..3f8b3bab77 100644 --- a/target-s390x/mem_helper.c +++ b/target-s390x/mem_helper.c @@ -1188,3 +1188,52 @@ uint32_t HELPER(lra)(uint64_t addr, uint32_t r1) } #endif + +/* temporary wrappers */ +#if defined(CONFIG_USER_ONLY) +#define ldub_data(addr) ldub_raw(addr) +#define lduw_data(addr) lduw_raw(addr) +#define ldl_data(addr) ldl_raw(addr) +#define ldq_data(addr) ldq_raw(addr) + +#define stb_data(addr, data) stb_raw(addr, data) +#define stw_data(addr, data) stw_raw(addr, data) +#define stl_data(addr, data) stl_raw(addr, data) +#define stq_data(addr, data) stq_raw(addr, data) +#endif + +#define WRAP_LD(rettype, fn) \ + rettype cpu_ ## fn(CPUS390XState *env1, target_ulong addr) \ + { \ + CPUS390XState *saved_env; \ + rettype ret; \ + \ + saved_env = env; \ + env = env1; \ + ret = fn(addr); \ + env = saved_env; \ + return ret; \ + } + +WRAP_LD(uint32_t, ldub_data) +WRAP_LD(uint32_t, lduw_data) +WRAP_LD(uint32_t, ldl_data) +WRAP_LD(uint64_t, ldq_data) +#undef WRAP_LD + +#define WRAP_ST(datatype, fn) \ + void cpu_ ## fn(CPUS390XState *env1, target_ulong addr, datatype val) \ + { \ + CPUS390XState *saved_env; \ + \ + saved_env = env; \ + env = env1; \ + fn(addr, val); \ + env = saved_env; \ + } + +WRAP_ST(uint32_t, stb_data) +WRAP_ST(uint32_t, stw_data) +WRAP_ST(uint32_t, stl_data) +WRAP_ST(uint64_t, stq_data) +#undef WRAP_ST diff --git a/target-s390x/translate.c b/target-s390x/translate.c index c370df3b61..b1f20718e7 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -2206,11 +2206,11 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2, switch (op) { case 0x4: /* LDEB R1,D2(X2,B2) [RXE] */ potential_page_fault(s); - gen_helper_ldeb(tmp_r1, addr); + gen_helper_ldeb(cpu_env, tmp_r1, addr); break; case 0x5: /* LXDB R1,D2(X2,B2) [RXE] */ potential_page_fault(s); - gen_helper_lxdb(tmp_r1, addr); + gen_helper_lxdb(cpu_env, tmp_r1, addr); break; case 0x9: /* CEB R1,D2(X2,B2) [RXE] */ tmp = tcg_temp_new_i64(); @@ -2225,7 +2225,7 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2, tmp32 = tcg_temp_new_i32(); tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s)); tcg_gen_trunc_i64_i32(tmp32, tmp); - gen_helper_aeb(tmp_r1, tmp32); + gen_helper_aeb(cpu_env, tmp_r1, tmp32); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32); @@ -2238,7 +2238,7 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2, tmp32 = tcg_temp_new_i32(); tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s)); tcg_gen_trunc_i64_i32(tmp32, tmp); - gen_helper_seb(tmp_r1, tmp32); + gen_helper_seb(cpu_env, tmp_r1, tmp32); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32); @@ -2251,23 +2251,23 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2, tmp32 = tcg_temp_new_i32(); tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s)); tcg_gen_trunc_i64_i32(tmp32, tmp); - gen_helper_deb(tmp_r1, tmp32); + gen_helper_deb(cpu_env, tmp_r1, tmp32); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32); break; case 0x10: /* TCEB R1,D2(X2,B2) [RXE] */ potential_page_fault(s); - gen_helper_tceb(cc_op, tmp_r1, addr); + gen_helper_tceb(cc_op, cpu_env, tmp_r1, addr); set_cc_static(s); break; case 0x11: /* TCDB R1,D2(X2,B2) [RXE] */ potential_page_fault(s); - gen_helper_tcdb(cc_op, tmp_r1, addr); + gen_helper_tcdb(cc_op, cpu_env, tmp_r1, addr); set_cc_static(s); break; case 0x12: /* TCXB R1,D2(X2,B2) [RXE] */ potential_page_fault(s); - gen_helper_tcxb(cc_op, tmp_r1, addr); + gen_helper_tcxb(cc_op, cpu_env, tmp_r1, addr); set_cc_static(s); break; case 0x17: /* MEEB R1,D2(X2,B2) [RXE] */ @@ -2275,38 +2275,38 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2, tmp32 = tcg_temp_new_i32(); tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s)); tcg_gen_trunc_i64_i32(tmp32, tmp); - gen_helper_meeb(tmp_r1, tmp32); + gen_helper_meeb(cpu_env, tmp_r1, tmp32); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32); break; case 0x19: /* CDB R1,D2(X2,B2) [RXE] */ potential_page_fault(s); - gen_helper_cdb(cc_op, tmp_r1, addr); + gen_helper_cdb(cc_op, cpu_env, tmp_r1, addr); set_cc_static(s); break; case 0x1a: /* ADB R1,D2(X2,B2) [RXE] */ potential_page_fault(s); - gen_helper_adb(cc_op, tmp_r1, addr); + gen_helper_adb(cc_op, cpu_env, tmp_r1, addr); set_cc_static(s); break; case 0x1b: /* SDB R1,D2(X2,B2) [RXE] */ potential_page_fault(s); - gen_helper_sdb(cc_op, tmp_r1, addr); + gen_helper_sdb(cc_op, cpu_env, tmp_r1, addr); set_cc_static(s); break; case 0x1c: /* MDB R1,D2(X2,B2) [RXE] */ potential_page_fault(s); - gen_helper_mdb(tmp_r1, addr); + gen_helper_mdb(cpu_env, tmp_r1, addr); break; case 0x1d: /* DDB R1,D2(X2,B2) [RXE] */ potential_page_fault(s); - gen_helper_ddb(tmp_r1, addr); + gen_helper_ddb(cpu_env, tmp_r1, addr); break; case 0x1e: /* MADB R1,R3,D2(X2,B2) [RXF] */ /* for RXF insns, r1 is R3 and r1b is R1 */ tmp32 = tcg_const_i32(r1b); potential_page_fault(s); - gen_helper_madb(tmp32, addr, tmp_r1); + gen_helper_madb(cpu_env, tmp32, addr, tmp_r1); tcg_temp_free_i32(tmp32); break; default: @@ -3001,14 +3001,14 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2) #define FP_HELPER(i) \ tmp32_1 = tcg_const_i32(r1); \ tmp32_2 = tcg_const_i32(r2); \ - gen_helper_ ## i (tmp32_1, tmp32_2); \ + gen_helper_ ## i(cpu_env, tmp32_1, tmp32_2); \ tcg_temp_free_i32(tmp32_1); \ tcg_temp_free_i32(tmp32_2); #define FP_HELPER_CC(i) \ tmp32_1 = tcg_const_i32(r1); \ tmp32_2 = tcg_const_i32(r2); \ - gen_helper_ ## i (cc_op, tmp32_1, tmp32_2); \ + gen_helper_ ## i(cc_op, cpu_env, tmp32_1, tmp32_2); \ set_cc_static(s); \ tcg_temp_free_i32(tmp32_1); \ tcg_temp_free_i32(tmp32_2); @@ -3080,13 +3080,13 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2) tmp32_3 = tcg_const_i32(r1); switch (op) { case 0xe: - gen_helper_maebr(tmp32_1, tmp32_3, tmp32_2); + gen_helper_maebr(cpu_env, tmp32_1, tmp32_3, tmp32_2); break; case 0x1e: - gen_helper_madbr(tmp32_1, tmp32_3, tmp32_2); + gen_helper_madbr(cpu_env, tmp32_1, tmp32_3, tmp32_2); break; case 0x1f: - gen_helper_msdbr(tmp32_1, tmp32_3, tmp32_2); + gen_helper_msdbr(cpu_env, tmp32_1, tmp32_3, tmp32_2); break; default: tcg_abort(); @@ -3138,17 +3138,17 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2) break; case 0x74: /* LZER R1 [RRE] */ tmp32_1 = tcg_const_i32(r1); - gen_helper_lzer(tmp32_1); + gen_helper_lzer(cpu_env, tmp32_1); tcg_temp_free_i32(tmp32_1); break; case 0x75: /* LZDR R1 [RRE] */ tmp32_1 = tcg_const_i32(r1); - gen_helper_lzdr(tmp32_1); + gen_helper_lzdr(cpu_env, tmp32_1); tcg_temp_free_i32(tmp32_1); break; case 0x76: /* LZXR R1 [RRE] */ tmp32_1 = tcg_const_i32(r1); - gen_helper_lzxr(tmp32_1); + gen_helper_lzxr(cpu_env, tmp32_1); tcg_temp_free_i32(tmp32_1); break; case 0x84: /* SFPC R1 [RRE] */ @@ -3169,13 +3169,13 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2) tmp32_2 = load_reg32(r2); switch (op) { case 0x94: - gen_helper_cefbr(tmp32_1, tmp32_2); + gen_helper_cefbr(cpu_env, tmp32_1, tmp32_2); break; case 0x95: - gen_helper_cdfbr(tmp32_1, tmp32_2); + gen_helper_cdfbr(cpu_env, tmp32_1, tmp32_2); break; case 0x96: - gen_helper_cxfbr(tmp32_1, tmp32_2); + gen_helper_cxfbr(cpu_env, tmp32_1, tmp32_2); break; default: tcg_abort(); @@ -3191,13 +3191,13 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2) tmp32_3 = tcg_const_i32(m3); switch (op) { case 0x98: - gen_helper_cfebr(cc_op, tmp32_1, tmp32_2, tmp32_3); + gen_helper_cfebr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3); break; case 0x99: - gen_helper_cfdbr(cc_op, tmp32_1, tmp32_2, tmp32_3); + gen_helper_cfdbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3); break; case 0x9a: - gen_helper_cfxbr(cc_op, tmp32_1, tmp32_2, tmp32_3); + gen_helper_cfxbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3); break; default: tcg_abort(); @@ -3213,10 +3213,10 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2) tmp = load_reg(r2); switch (op) { case 0xa4: - gen_helper_cegbr(tmp32_1, tmp); + gen_helper_cegbr(cpu_env, tmp32_1, tmp); break; case 0xa5: - gen_helper_cdgbr(tmp32_1, tmp); + gen_helper_cdgbr(cpu_env, tmp32_1, tmp); break; default: tcg_abort(); @@ -3227,7 +3227,7 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2) case 0xa6: /* CXGBR R1,R2 [RRE] */ tmp32_1 = tcg_const_i32(r1); tmp = load_reg(r2); - gen_helper_cxgbr(tmp32_1, tmp); + gen_helper_cxgbr(cpu_env, tmp32_1, tmp); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i64(tmp); break; @@ -3235,7 +3235,7 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2) tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r2); tmp32_3 = tcg_const_i32(m3); - gen_helper_cgebr(cc_op, tmp32_1, tmp32_2, tmp32_3); + gen_helper_cgebr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3); set_cc_static(s); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); @@ -3245,7 +3245,7 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2) tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r2); tmp32_3 = tcg_const_i32(m3); - gen_helper_cgdbr(cc_op, tmp32_1, tmp32_2, tmp32_3); + gen_helper_cgdbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3); set_cc_static(s); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); @@ -3255,7 +3255,7 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2) tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r2); tmp32_3 = tcg_const_i32(m3); - gen_helper_cgxbr(cc_op, tmp32_1, tmp32_2, tmp32_3); + gen_helper_cgxbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3); set_cc_static(s); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); From 4fda26a7b0d6ffbb4055ab8b756cd94647f5fd22 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 07:33:37 +0000 Subject: [PATCH 0224/2270] target-s390x: avoid AREG0 for integer helpers Make integer helpers take a parameter for CPUState instead of relying on global env. Signed-off-by: Blue Swirl Signed-off-by: Alexander Graf --- target-s390x/Makefile.objs | 1 - target-s390x/helper.h | 10 +++++----- target-s390x/int_helper.c | 12 ++++++------ target-s390x/translate.c | 16 ++++++++-------- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs index 7d965e9ca9..7b2c5c1071 100644 --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -3,7 +3,6 @@ obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o obj-$(CONFIG_SOFTMMU) += machine.o obj-$(CONFIG_KVM) += kvm.o -$(obj)/int_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/misc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-s390x/helper.h b/target-s390x/helper.h index af987732f6..c03cd59347 100644 --- a/target-s390x/helper.h +++ b/target-s390x/helper.h @@ -12,8 +12,8 @@ DEF_HELPER_FLAGS_1(set_cc_comp_s64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64) DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32) DEF_HELPER_3(clm, i32, i32, i32, i64) DEF_HELPER_3(stcm, void, i32, i32, i64) -DEF_HELPER_2(mlg, void, i32, i64) -DEF_HELPER_2(dlg, void, i32, i64) +DEF_HELPER_3(mlg, void, env, i32, i64) +DEF_HELPER_3(dlg, void, env, i32, i64) DEF_HELPER_FLAGS_3(set_cc_add64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64) DEF_HELPER_FLAGS_3(set_cc_addu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64) DEF_HELPER_FLAGS_3(set_cc_add32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32) @@ -43,8 +43,8 @@ DEF_HELPER_3(stam, void, i32, i64, i32) DEF_HELPER_3(lam, void, i32, i64, i32) DEF_HELPER_3(mvcle, i32, i32, i64, i32) DEF_HELPER_3(clcle, i32, i32, i64, i32) -DEF_HELPER_3(slb, i32, i32, i32, i32) -DEF_HELPER_4(slbg, i32, i32, i32, i64, i64) +DEF_HELPER_4(slb, i32, env, i32, i32, i32) +DEF_HELPER_5(slbg, i32, env, i32, i32, i64, i64) DEF_HELPER_3(cefbr, void, env, i32, s32) DEF_HELPER_3(cdfbr, void, env, i32, s32) DEF_HELPER_3(cxfbr, void, env, i32, s32) @@ -107,7 +107,7 @@ DEF_HELPER_3(lxdb, void, env, i32, i64) DEF_HELPER_FLAGS_3(tceb, TCG_CALL_PURE, i32, env, i32, i64) DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_PURE, i32, env, i32, i64) DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE, i32, env, i32, i64) -DEF_HELPER_2(flogr, i32, i32, i64) +DEF_HELPER_3(flogr, i32, env, i32, i64) DEF_HELPER_3(sqdbr, void, env, i32, i32) DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32) DEF_HELPER_3(unpk, void, i32, i64, i64) diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c index e2eeb07575..f202a7e1da 100644 --- a/target-s390x/int_helper.c +++ b/target-s390x/int_helper.c @@ -19,7 +19,6 @@ */ #include "cpu.h" -#include "dyngen-exec.h" #include "host-utils.h" #include "helper.h" @@ -31,7 +30,7 @@ #endif /* 64/64 -> 128 unsigned multiplication */ -void HELPER(mlg)(uint32_t r1, uint64_t v2) +void HELPER(mlg)(CPUS390XState *env, uint32_t r1, uint64_t v2) { #if HOST_LONG_BITS == 64 && defined(__GNUC__) /* assuming 64-bit hosts have __uint128_t */ @@ -46,7 +45,7 @@ void HELPER(mlg)(uint32_t r1, uint64_t v2) } /* 128 -> 64/64 unsigned division */ -void HELPER(dlg)(uint32_t r1, uint64_t v2) +void HELPER(dlg)(CPUS390XState *env, uint32_t r1, uint64_t v2) { uint64_t divisor = v2; @@ -129,7 +128,7 @@ uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2) } /* subtract unsigned v2 from v1 with borrow */ -uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2) +uint32_t HELPER(slb)(CPUS390XState *env, uint32_t cc, uint32_t r1, uint32_t v2) { uint32_t v1 = env->regs[r1]; uint32_t res = v1 + (~v2) + (cc >> 1); @@ -144,7 +143,8 @@ uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2) } /* subtract unsigned v2 from v1 with borrow */ -uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2) +uint32_t HELPER(slbg)(CPUS390XState *env, uint32_t cc, uint32_t r1, + uint64_t v1, uint64_t v2) { uint64_t res = v1 + (~v2) + (cc >> 1); @@ -158,7 +158,7 @@ uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2) } /* find leftmost one */ -uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2) +uint32_t HELPER(flogr)(CPUS390XState *env, uint32_t r1, uint64_t v2) { uint64_t res = 0; uint64_t ov2 = v2; diff --git a/target-s390x/translate.c b/target-s390x/translate.c index b1f20718e7..2a61e92f18 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -1803,7 +1803,7 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2) tmp2 = tcg_temp_new_i64(); tmp32_1 = tcg_const_i32(r1); tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s)); - gen_helper_mlg(tmp32_1, tmp2); + gen_helper_mlg(cpu_env, tmp32_1, tmp2); tcg_temp_free_i64(tmp2); tcg_temp_free_i32(tmp32_1); break; @@ -1811,7 +1811,7 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2) tmp2 = tcg_temp_new_i64(); tmp32_1 = tcg_const_i32(r1); tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s)); - gen_helper_dlg(tmp32_1, tmp2); + gen_helper_dlg(cpu_env, tmp32_1, tmp2); tcg_temp_free_i64(tmp2); tcg_temp_free_i32(tmp32_1); break; @@ -1837,7 +1837,7 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2) tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s)); /* XXX possible optimization point */ gen_op_calc_cc(s); - gen_helper_slbg(cc_op, cc_op, tmp32_1, regs[r1], tmp2); + gen_helper_slbg(cc_op, cpu_env, cc_op, tmp32_1, regs[r1], tmp2); set_cc_static(s); tcg_temp_free_i64(tmp2); tcg_temp_free_i32(tmp32_1); @@ -1917,7 +1917,7 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2) tcg_gen_trunc_i64_i32(tmp32_2, tmp2); /* XXX possible optimization point */ gen_op_calc_cc(s); - gen_helper_slb(cc_op, cc_op, tmp32_1, tmp32_2); + gen_helper_slb(cc_op, cpu_env, cc_op, tmp32_1, tmp32_2); set_cc_static(s); tcg_temp_free_i64(tmp2); tcg_temp_free_i32(tmp32_1); @@ -3535,7 +3535,7 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2) case 0x83: /* FLOGR R1,R2 [RRE] */ tmp = load_reg(r2); tmp32_1 = tcg_const_i32(r1); - gen_helper_flogr(cc_op, tmp32_1, tmp); + gen_helper_flogr(cc_op, cpu_env, tmp32_1, tmp); set_cc_static(s); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); @@ -3555,7 +3555,7 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2) case 0x87: /* DLGR R1,R2 [RRE] */ tmp32_1 = tcg_const_i32(r1); tmp = load_reg(r2); - gen_helper_dlg(tmp32_1, tmp); + gen_helper_dlg(cpu_env, tmp32_1, tmp); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); break; @@ -3580,7 +3580,7 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2) tmp2 = load_reg(r2); tmp32_1 = tcg_const_i32(r1); gen_op_calc_cc(s); - gen_helper_slbg(cc_op, cc_op, tmp32_1, tmp, tmp2); + gen_helper_slbg(cc_op, cpu_env, cc_op, tmp32_1, tmp, tmp2); set_cc_static(s); tcg_temp_free_i64(tmp); tcg_temp_free_i64(tmp2); @@ -3647,7 +3647,7 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2) tmp32_1 = load_reg32(r2); tmp32_2 = tcg_const_i32(r1); gen_op_calc_cc(s); - gen_helper_slb(cc_op, cc_op, tmp32_2, tmp32_1); + gen_helper_slb(cc_op, cpu_env, cc_op, tmp32_2, tmp32_1); set_cc_static(s); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); From 932385a367b2c67f1ea7148dcafb013db188cd23 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 07:33:38 +0000 Subject: [PATCH 0225/2270] target-s390x: avoid AREG0 for condition code helpers Make condition code helpers take a parameter for CPUState instead of relying on global env. Signed-off-by: Blue Swirl Signed-off-by: Alexander Graf --- target-s390x/Makefile.objs | 1 - target-s390x/cc_helper.c | 11 +++++------ target-s390x/helper.h | 10 +++++----- target-s390x/translate.c | 16 ++++++++-------- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs index 7b2c5c1071..736cf331bb 100644 --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -3,6 +3,5 @@ obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o obj-$(CONFIG_SOFTMMU) += machine.o obj-$(CONFIG_KVM) += kvm.o -$(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) $(obj)/misc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c index 9c3a2c4595..19ef145da9 100644 --- a/target-s390x/cc_helper.c +++ b/target-s390x/cc_helper.c @@ -19,7 +19,6 @@ */ #include "cpu.h" -#include "dyngen-exec.h" #include "helper.h" /* #define DEBUG_HELPER */ @@ -500,14 +499,14 @@ uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst, return do_calc_cc(env, cc_op, src, dst, vr); } -uint32_t HELPER(calc_cc)(uint32_t cc_op, uint64_t src, uint64_t dst, - uint64_t vr) +uint32_t HELPER(calc_cc)(CPUS390XState *env, uint32_t cc_op, uint64_t src, + uint64_t dst, uint64_t vr) { return do_calc_cc(env, cc_op, src, dst, vr); } /* insert psw mask and condition code into r1 */ -void HELPER(ipm)(uint32_t cc, uint32_t r1) +void HELPER(ipm)(CPUS390XState *env, uint32_t cc, uint32_t r1) { uint64_t r = env->regs[r1]; @@ -519,13 +518,13 @@ void HELPER(ipm)(uint32_t cc, uint32_t r1) } #ifndef CONFIG_USER_ONLY -void HELPER(load_psw)(uint64_t mask, uint64_t addr) +void HELPER(load_psw)(CPUS390XState *env, uint64_t mask, uint64_t addr) { load_psw(env, mask, addr); cpu_loop_exit(env); } -void HELPER(sacf)(uint64_t a1) +void HELPER(sacf)(CPUS390XState *env, uint64_t a1) { HELPER_LOG("%s: %16" PRIx64 "\n", __func__, a1); diff --git a/target-s390x/helper.h b/target-s390x/helper.h index c03cd59347..876b88e531 100644 --- a/target-s390x/helper.h +++ b/target-s390x/helper.h @@ -36,7 +36,7 @@ DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_PURE|TCG_CALL_CONST, i64, s64) DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_PURE|TCG_CALL_CONST, s64, s64) DEF_HELPER_3(stcmh, void, i32, i64, i32) DEF_HELPER_3(icmh, i32, i32, i64, i32) -DEF_HELPER_2(ipm, void, i32, i32) +DEF_HELPER_3(ipm, void, env, i32, i32) DEF_HELPER_FLAGS_3(addc_u32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32) DEF_HELPER_FLAGS_3(set_cc_addc_u64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64) DEF_HELPER_3(stam, void, i32, i64, i32) @@ -115,7 +115,7 @@ DEF_HELPER_3(tr, void, i32, i64, i64) DEF_HELPER_2(servc, i32, i32, i64) DEF_HELPER_3(diag, i64, i32, i64, i64) -DEF_HELPER_2(load_psw, void, i64, i64) +DEF_HELPER_3(load_psw, void, env, i64, i64) DEF_HELPER_1(program_interrupt, void, i32) DEF_HELPER_FLAGS_1(stidp, TCG_CALL_CONST, void, i64) DEF_HELPER_FLAGS_1(spx, TCG_CALL_CONST, void, i64) @@ -139,14 +139,14 @@ DEF_HELPER_2(csp, i32, i32, i32) DEF_HELPER_3(mvcs, i32, i64, i64, i64) DEF_HELPER_3(mvcp, i32, i64, i64, i64) DEF_HELPER_3(sigp, i32, i64, i32, i64) -DEF_HELPER_1(sacf, void, i64) +DEF_HELPER_2(sacf, void, env, i64) DEF_HELPER_FLAGS_2(ipte, TCG_CALL_CONST, void, i64, i64) DEF_HELPER_FLAGS_0(ptlb, TCG_CALL_CONST, void) DEF_HELPER_2(lra, i32, i64, i32) DEF_HELPER_2(stura, void, i64, i32) DEF_HELPER_2(cksm, void, i32, i32) -DEF_HELPER_FLAGS_4(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST, - i32, i32, i64, i64, i64) +DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST, + i32, env, i32, i64, i64, i64) #include "def-helper.h" diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 2a61e92f18..1d8727211e 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -722,7 +722,7 @@ static void gen_op_calc_cc(DisasContext *s) case CC_OP_NZ_F32: case CC_OP_NZ_F64: /* 1 argument */ - gen_helper_calc_cc(cc_op, local_cc_op, dummy, cc_dst, dummy); + gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy); break; case CC_OP_ICM: case CC_OP_LTGT_32: @@ -735,7 +735,7 @@ static void gen_op_calc_cc(DisasContext *s) case CC_OP_LTGT_F64: case CC_OP_SLAG: /* 2 arguments */ - gen_helper_calc_cc(cc_op, local_cc_op, cc_src, cc_dst, dummy); + gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy); break; case CC_OP_ADD_64: case CC_OP_ADDU_64: @@ -746,11 +746,11 @@ static void gen_op_calc_cc(DisasContext *s) case CC_OP_SUB_32: case CC_OP_SUBU_32: /* 3 arguments */ - gen_helper_calc_cc(cc_op, local_cc_op, cc_src, cc_dst, cc_vr); + gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, cc_vr); break; case CC_OP_DYNAMIC: /* unknown operation - assume 3 arguments and cc_op in env */ - gen_helper_calc_cc(cc_op, cc_op, cc_src, cc_dst, cc_vr); + gen_helper_calc_cc(cc_op, cpu_env, cc_op, cc_src, cc_dst, cc_vr); break; default: tcg_abort(); @@ -2628,7 +2628,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) case 0x22: /* IPM R1 [RRE] */ tmp32_1 = tcg_const_i32(r1); gen_op_calc_cc(s); - gen_helper_ipm(cc_op, tmp32_1); + gen_helper_ipm(cpu_env, cc_op, tmp32_1); tcg_temp_free_i32(tmp32_1); break; case 0x41: /* CKSM R1,R2 [RRE] */ @@ -2916,7 +2916,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); - gen_helper_sacf(tmp); + gen_helper_sacf(cpu_env, tmp); tcg_temp_free_i64(tmp); /* addressing mode has changed, so end the block */ s->pc += ilc * 2; @@ -2967,7 +2967,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) tcg_gen_qemu_ld64(tmp2, tmp, get_mem_index(s)); tcg_gen_addi_i64(tmp, tmp, 8); tcg_gen_qemu_ld64(tmp3, tmp, get_mem_index(s)); - gen_helper_load_psw(tmp2, tmp3); + gen_helper_load_psw(cpu_env, tmp2, tmp3); /* we need to keep cc_op intact */ s->is_jmp = DISAS_JUMP; tcg_temp_free_i64(tmp); @@ -4527,7 +4527,7 @@ static void disas_s390_insn(DisasContext *s) tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s)); tcg_gen_addi_i64(tmp, tmp, 4); tcg_gen_qemu_ld32u(tmp3, tmp, get_mem_index(s)); - gen_helper_load_psw(tmp2, tmp3); + gen_helper_load_psw(cpu_env, tmp2, tmp3); tcg_temp_free_i64(tmp); tcg_temp_free_i64(tmp2); tcg_temp_free_i64(tmp3); From 089f5c06926105a35df461003ae32b7387ed4236 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 07:33:39 +0000 Subject: [PATCH 0226/2270] target-s390x: avoid AREG0 for misc helpers Make misc helpers take a parameter for CPUState instead of relying on global env. Signed-off-by: Blue Swirl [agraf: fix conflict] Signed-off-by: Alexander Graf --- target-s390x/Makefile.objs | 1 - target-s390x/helper.h | 26 +++++++++--------- target-s390x/mem_helper.c | 2 +- target-s390x/misc_helper.c | 55 +++++++++++++++++++++----------------- target-s390x/translate.c | 32 +++++++++++----------- 5 files changed, 60 insertions(+), 56 deletions(-) diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs index 736cf331bb..156d9469a3 100644 --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -4,4 +4,3 @@ obj-$(CONFIG_SOFTMMU) += machine.o obj-$(CONFIG_KVM) += kvm.o $(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) -$(obj)/misc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-s390x/helper.h b/target-s390x/helper.h index 876b88e531..f4e0b37378 100644 --- a/target-s390x/helper.h +++ b/target-s390x/helper.h @@ -1,6 +1,6 @@ #include "def-helper.h" -DEF_HELPER_1(exception, void, i32) +DEF_HELPER_2(exception, void, env, i32) DEF_HELPER_3(nc, i32, i32, i64, i64) DEF_HELPER_3(oc, i32, i32, i64, i64) DEF_HELPER_3(xc, i32, i32, i64, i64) @@ -113,20 +113,20 @@ DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32) DEF_HELPER_3(unpk, void, i32, i64, i64) DEF_HELPER_3(tr, void, i32, i64, i64) -DEF_HELPER_2(servc, i32, i32, i64) -DEF_HELPER_3(diag, i64, i32, i64, i64) +DEF_HELPER_3(servc, i32, env, i32, i64) +DEF_HELPER_4(diag, i64, env, i32, i64, i64) DEF_HELPER_3(load_psw, void, env, i64, i64) DEF_HELPER_1(program_interrupt, void, i32) -DEF_HELPER_FLAGS_1(stidp, TCG_CALL_CONST, void, i64) -DEF_HELPER_FLAGS_1(spx, TCG_CALL_CONST, void, i64) +DEF_HELPER_FLAGS_2(stidp, TCG_CALL_CONST, void, env, i64) +DEF_HELPER_FLAGS_2(spx, TCG_CALL_CONST, void, env, i64) DEF_HELPER_FLAGS_1(sck, TCG_CALL_CONST, i32, i64) -DEF_HELPER_1(stck, i32, i64) -DEF_HELPER_1(stcke, i32, i64) -DEF_HELPER_FLAGS_1(sckc, TCG_CALL_CONST, void, i64) -DEF_HELPER_FLAGS_1(stckc, TCG_CALL_CONST, void, i64) -DEF_HELPER_FLAGS_1(spt, TCG_CALL_CONST, void, i64) -DEF_HELPER_FLAGS_1(stpt, TCG_CALL_CONST, void, i64) -DEF_HELPER_3(stsi, i32, i64, i32, i32) +DEF_HELPER_2(stck, i32, env, i64) +DEF_HELPER_2(stcke, i32, env, i64) +DEF_HELPER_FLAGS_2(sckc, TCG_CALL_CONST, void, env, i64) +DEF_HELPER_FLAGS_2(stckc, TCG_CALL_CONST, void, env, i64) +DEF_HELPER_FLAGS_2(spt, TCG_CALL_CONST, void, env, i64) +DEF_HELPER_FLAGS_2(stpt, TCG_CALL_CONST, void, env, i64) +DEF_HELPER_4(stsi, i32, env, i64, i32, i32) DEF_HELPER_3(lctl, void, i32, i64, i32) DEF_HELPER_3(lctlg, void, i32, i64, i32) DEF_HELPER_3(stctl, void, i32, i64, i32) @@ -138,7 +138,7 @@ DEF_HELPER_FLAGS_2(rrbe, TCG_CALL_CONST, i32, i32, i64) DEF_HELPER_2(csp, i32, i32, i32) DEF_HELPER_3(mvcs, i32, i64, i64, i64) DEF_HELPER_3(mvcp, i32, i64, i64, i64) -DEF_HELPER_3(sigp, i32, i64, i32, i64) +DEF_HELPER_4(sigp, i32, env, i64, i32, i64) DEF_HELPER_2(sacf, void, env, i64) DEF_HELPER_FLAGS_2(ipte, TCG_CALL_CONST, void, i64, i64) DEF_HELPER_FLAGS_0(ptlb, TCG_CALL_CONST, void) diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c index 3f8b3bab77..52f2602e5c 100644 --- a/target-s390x/mem_helper.c +++ b/target-s390x/mem_helper.c @@ -595,7 +595,7 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret) env->psw.addr = ret - 4; env->int_svc_code = (insn | v1) & 0xff; env->int_svc_ilc = 4; - helper_exception(EXCP_SVC); + helper_exception(env, EXCP_SVC); } else if ((insn & 0xff00) == 0xbf00) { uint32_t insn2, r1, r3, b2, d2; diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index 1d5137f984..ced26c6f16 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -21,7 +21,6 @@ #include "cpu.h" #include "memory.h" #include "cputlb.h" -#include "dyngen-exec.h" #include "host-utils.h" #include "helper.h" #include @@ -32,7 +31,10 @@ #endif #if !defined(CONFIG_USER_ONLY) +/* temporarily disabled due to wrapper use */ +#if 0 #include "softmmu_exec.h" +#endif #include "sysemu.h" #endif @@ -44,7 +46,7 @@ #endif /* raise an exception */ -void HELPER(exception)(uint32_t excp) +void HELPER(exception)(CPUS390XState *env, uint32_t excp) { HELPER_LOG("%s: exception %d\n", __func__, excp); env->exception_index = excp; @@ -112,7 +114,7 @@ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code) } /* SCLP service call */ -uint32_t HELPER(servc)(uint32_t r1, uint64_t r2) +uint32_t HELPER(servc)(CPUS390XState *env, uint32_t r1, uint64_t r2) { int r; @@ -125,7 +127,8 @@ uint32_t HELPER(servc)(uint32_t r1, uint64_t r2) } /* DIAG */ -uint64_t HELPER(diag)(uint32_t num, uint64_t mem, uint64_t code) +uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem, + uint64_t code) { uint64_t r; @@ -155,17 +158,17 @@ uint64_t HELPER(diag)(uint32_t num, uint64_t mem, uint64_t code) } /* Store CPU ID */ -void HELPER(stidp)(uint64_t a1) +void HELPER(stidp)(CPUS390XState *env, uint64_t a1) { - stq(a1, env->cpu_num); + cpu_stq_data(env, a1, env->cpu_num); } /* Set Prefix */ -void HELPER(spx)(uint64_t a1) +void HELPER(spx)(CPUS390XState *env, uint64_t a1) { uint32_t prefix; - prefix = ldl(a1); + prefix = cpu_ldl_data(env, a1); env->psa = prefix & 0xfffff000; qemu_log("prefix: %#x\n", prefix); tlb_flush_page(env, 0); @@ -191,31 +194,31 @@ static inline uint64_t clock_value(CPUS390XState *env) } /* Store Clock */ -uint32_t HELPER(stck)(uint64_t a1) +uint32_t HELPER(stck)(CPUS390XState *env, uint64_t a1) { - stq(a1, clock_value(env)); + cpu_stq_data(env, a1, clock_value(env)); return 0; } /* Store Clock Extended */ -uint32_t HELPER(stcke)(uint64_t a1) +uint32_t HELPER(stcke)(CPUS390XState *env, uint64_t a1) { - stb(a1, 0); + cpu_stb_data(env, a1, 0); /* basically the same value as stck */ - stq(a1 + 1, clock_value(env) | env->cpu_num); + cpu_stq_data(env, a1 + 1, clock_value(env) | env->cpu_num); /* more fine grained than stck */ - stq(a1 + 9, 0); + cpu_stq_data(env, a1 + 9, 0); /* XXX programmable fields */ - stw(a1 + 17, 0); + cpu_stw_data(env, a1 + 17, 0); return 0; } /* Set Clock Comparator */ -void HELPER(sckc)(uint64_t a1) +void HELPER(sckc)(CPUS390XState *env, uint64_t a1) { - uint64_t time = ldq(a1); + uint64_t time = cpu_ldq_data(env, a1); if (time == -1ULL) { return; @@ -230,16 +233,16 @@ void HELPER(sckc)(uint64_t a1) } /* Store Clock Comparator */ -void HELPER(stckc)(uint64_t a1) +void HELPER(stckc)(CPUS390XState *env, uint64_t a1) { /* XXX implement */ - stq(a1, 0); + cpu_stq_data(env, a1, 0); } /* Set CPU Timer */ -void HELPER(spt)(uint64_t a1) +void HELPER(spt)(CPUS390XState *env, uint64_t a1) { - uint64_t time = ldq(a1); + uint64_t time = cpu_ldq_data(env, a1); if (time == -1ULL) { return; @@ -252,14 +255,15 @@ void HELPER(spt)(uint64_t a1) } /* Store CPU Timer */ -void HELPER(stpt)(uint64_t a1) +void HELPER(stpt)(CPUS390XState *env, uint64_t a1) { /* XXX implement */ - stq(a1, 0); + cpu_stq_data(env, a1, 0); } /* Store System Information */ -uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1) +uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0, uint32_t r0, + uint32_t r1) { int cc = 0; int sel1, sel2; @@ -384,7 +388,8 @@ uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1) return cc; } -uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr) +uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1, + uint64_t cpu_addr) { int cc = 0; diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 1d8727211e..0c61e6334b 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -312,7 +312,7 @@ static inline void gen_debug(DisasContext *s) TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG); update_psw_addr(s); gen_op_calc_cc(s); - gen_helper_exception(tmp); + gen_helper_exception(cpu_env, tmp); tcg_temp_free_i32(tmp); s->is_jmp = DISAS_EXCP; } @@ -324,7 +324,7 @@ static void gen_illegal_opcode(DisasContext *s, int ilc) TCGv_i32 tmp = tcg_const_i32(EXCP_SPEC); update_psw_addr(s); gen_op_calc_cc(s); - gen_helper_exception(tmp); + gen_helper_exception(cpu_env, tmp); tcg_temp_free_i32(tmp); s->is_jmp = DISAS_EXCP; } @@ -377,7 +377,7 @@ static void gen_program_exception(DisasContext *s, int ilc, int code) /* trigger exception */ tmp = tcg_const_i32(EXCP_PGM); - gen_helper_exception(tmp); + gen_helper_exception(cpu_env, tmp); tcg_temp_free_i32(tmp); /* end TB here */ @@ -2712,7 +2712,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); - gen_helper_stidp(tmp); + gen_helper_stidp(cpu_env, tmp); tcg_temp_free_i64(tmp); break; case 0x04: /* SCK D2(B2) [S] */ @@ -2730,7 +2730,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); - gen_helper_stck(cc_op, tmp); + gen_helper_stck(cc_op, cpu_env, tmp); set_cc_static(s); tcg_temp_free_i64(tmp); break; @@ -2740,7 +2740,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); - gen_helper_sckc(tmp); + gen_helper_sckc(cpu_env, tmp); tcg_temp_free_i64(tmp); break; case 0x07: /* STCKC D2(B2) [S] */ @@ -2749,7 +2749,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); - gen_helper_stckc(tmp); + gen_helper_stckc(cpu_env, tmp); tcg_temp_free_i64(tmp); break; case 0x08: /* SPT D2(B2) [S] */ @@ -2758,7 +2758,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); - gen_helper_spt(tmp); + gen_helper_spt(cpu_env, tmp); tcg_temp_free_i64(tmp); break; case 0x09: /* STPT D2(B2) [S] */ @@ -2767,7 +2767,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); - gen_helper_stpt(tmp); + gen_helper_stpt(cpu_env, tmp); tcg_temp_free_i64(tmp); break; case 0x0a: /* SPKA D2(B2) [S] */ @@ -2793,7 +2793,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); - gen_helper_spx(tmp); + gen_helper_spx(cpu_env, tmp); tcg_temp_free_i64(tmp); break; case 0x11: /* STPX D2(B2) [S] */ @@ -2906,7 +2906,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); - gen_helper_stcke(cc_op, tmp); + gen_helper_stcke(cc_op, cpu_env, tmp); set_cc_static(s); tcg_temp_free_i64(tmp); break; @@ -2930,7 +2930,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) tmp32_1 = load_reg32(0); tmp32_2 = load_reg32(1); potential_page_fault(s); - gen_helper_stsi(cc_op, tmp, tmp32_1, tmp32_2); + gen_helper_stsi(cc_op, cpu_env, tmp, tmp32_1, tmp32_2); set_cc_static(s); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); @@ -2980,7 +2980,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) potential_page_fault(s); tmp32_1 = load_reg32(r2); tmp = load_reg(r1); - gen_helper_servc(cc_op, tmp32_1, tmp); + gen_helper_servc(cc_op, cpu_env, tmp32_1, tmp); set_cc_static(s); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i64(tmp); @@ -3926,7 +3926,7 @@ static void disas_s390_insn(DisasContext *s) tmp32_3 = tcg_const_i32(EXCP_SVC); tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, int_svc_code)); tcg_gen_st_i32(tmp32_2, cpu_env, offsetof(CPUS390XState, int_svc_ilc)); - gen_helper_exception(tmp32_3); + gen_helper_exception(cpu_env, tmp32_3); s->is_jmp = DISAS_EXCP; tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); @@ -4543,7 +4543,7 @@ static void disas_s390_insn(DisasContext *s) tmp32_1 = tcg_const_i32(insn & 0xfff); tmp2 = load_reg(2); tmp3 = load_reg(1); - gen_helper_diag(tmp2, tmp32_1, tmp2, tmp3); + gen_helper_diag(tmp2, cpu_env, tmp32_1, tmp2, tmp3); store_reg(2, tmp2); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i64(tmp2); @@ -4777,7 +4777,7 @@ static void disas_s390_insn(DisasContext *s) tmp2 = load_reg(r3); tmp32_1 = tcg_const_i32(r1); potential_page_fault(s); - gen_helper_sigp(cc_op, tmp, tmp32_1, tmp2); + gen_helper_sigp(cc_op, cpu_env, tmp, tmp32_1, tmp2); set_cc_static(s); tcg_temp_free_i64(tmp); tcg_temp_free_i64(tmp2); From 19b0516fb4fd22b08c6ee42ea4162aaf3b9c8ee1 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 07:33:40 +0000 Subject: [PATCH 0227/2270] target-s390x: switch to AREG0 free mode Add an explicit CPUState parameter instead of relying on AREG0. Remove temporary wrappers and switch to AREG0 free mode. Signed-off-by: Blue Swirl [agraf: fix conflicts] Signed-off-by: Alexander Graf --- configure | 2 +- target-s390x/Makefile.objs | 2 - target-s390x/cpu.h | 10 -- target-s390x/fpu_helper.c | 3 +- target-s390x/helper.c | 6 +- target-s390x/helper.h | 78 ++++----- target-s390x/mem_helper.c | 338 +++++++++++++++++-------------------- target-s390x/misc_helper.c | 3 - target-s390x/translate.c | 88 +++++----- 9 files changed, 239 insertions(+), 291 deletions(-) diff --git a/configure b/configure index d97fd81709..a88a4659b7 100755 --- a/configure +++ b/configure @@ -3829,7 +3829,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile" case "$target_arch2" in - alpha | i386 | or32 | sparc* | x86_64 | xtensa* | ppc*) + alpha | i386 | or32 | s390x | sparc* | x86_64 | xtensa* | ppc*) echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak ;; esac diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs index 156d9469a3..e728abf759 100644 --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -2,5 +2,3 @@ obj-y += translate.o helper.o cpu.o interrupt.o obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o obj-$(CONFIG_SOFTMMU) += machine.o obj-$(CONFIG_KVM) += kvm.o - -$(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 9b7a2e3adc..ed81af33a1 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -1008,14 +1008,4 @@ uint32_t set_cc_nz_f64(float64 v); /* misc_helper.c */ void program_interrupt(CPUS390XState *env, uint32_t code, int ilc); -/* temporary wrappers */ -uint32_t cpu_ldub_data(CPUS390XState *env, target_ulong ptr); -uint32_t cpu_lduw_data(CPUS390XState *env, target_ulong ptr); -uint32_t cpu_ldl_data(CPUS390XState *env, target_ulong ptr); -uint64_t cpu_ldq_data(CPUS390XState *env, target_ulong ptr); - -void cpu_stb_data(CPUS390XState *env, target_ulong ptr, uint32_t data); -void cpu_stw_data(CPUS390XState *env, target_ulong ptr, uint32_t data); -void cpu_stl_data(CPUS390XState *env, target_ulong ptr, uint32_t data); -void cpu_stq_data(CPUS390XState *env, target_ulong ptr, uint64_t data); #endif diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c index e23541922d..ee9420d446 100644 --- a/target-s390x/fpu_helper.c +++ b/target-s390x/fpu_helper.c @@ -21,8 +21,7 @@ #include "cpu.h" #include "helper.h" -/* temporarily disabled due to wrapper use */ -#if 0 && !defined(CONFIG_USER_ONLY) +#if !defined(CONFIG_USER_ONLY) #include "softmmu_exec.h" #endif diff --git a/target-s390x/helper.c b/target-s390x/helper.c index d98e6d9dcc..a5741ecde1 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -499,14 +499,14 @@ static void do_program_interrupt(CPUS390XState *env) switch (ilc) { case ILC_LATER: - ilc = get_ilc(ldub_code(env->psw.addr)); + ilc = get_ilc(cpu_ldub_code(env, env->psw.addr)); break; case ILC_LATER_INC: - ilc = get_ilc(ldub_code(env->psw.addr)); + ilc = get_ilc(cpu_ldub_code(env, env->psw.addr)); env->psw.addr += ilc * 2; break; case ILC_LATER_INC_2: - ilc = get_ilc(ldub_code(env->psw.addr)) * 2; + ilc = get_ilc(cpu_ldub_code(env, env->psw.addr)) * 2; env->psw.addr += ilc; break; } diff --git a/target-s390x/helper.h b/target-s390x/helper.h index f4e0b37378..5419f37dca 100644 --- a/target-s390x/helper.h +++ b/target-s390x/helper.h @@ -1,17 +1,17 @@ #include "def-helper.h" DEF_HELPER_2(exception, void, env, i32) -DEF_HELPER_3(nc, i32, i32, i64, i64) -DEF_HELPER_3(oc, i32, i32, i64, i64) -DEF_HELPER_3(xc, i32, i32, i64, i64) -DEF_HELPER_3(mvc, void, i32, i64, i64) -DEF_HELPER_3(clc, i32, i32, i64, i64) -DEF_HELPER_2(mvcl, i32, i32, i32) +DEF_HELPER_4(nc, i32, env, i32, i64, i64) +DEF_HELPER_4(oc, i32, env, i32, i64, i64) +DEF_HELPER_4(xc, i32, env, i32, i64, i64) +DEF_HELPER_4(mvc, void, env, i32, i64, i64) +DEF_HELPER_4(clc, i32, env, i32, i64, i64) +DEF_HELPER_3(mvcl, i32, env, i32, i32) DEF_HELPER_FLAGS_1(set_cc_comp_s32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32) DEF_HELPER_FLAGS_1(set_cc_comp_s64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64) DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32) -DEF_HELPER_3(clm, i32, i32, i32, i64) -DEF_HELPER_3(stcm, void, i32, i32, i64) +DEF_HELPER_4(clm, i32, env, i32, i32, i64) +DEF_HELPER_4(stcm, void, env, i32, i32, i64) DEF_HELPER_3(mlg, void, env, i32, i64) DEF_HELPER_3(dlg, void, env, i32, i64) DEF_HELPER_FLAGS_3(set_cc_add64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64) @@ -22,27 +22,27 @@ DEF_HELPER_FLAGS_3(set_cc_sub64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s6 DEF_HELPER_FLAGS_3(set_cc_subu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64) DEF_HELPER_FLAGS_3(set_cc_sub32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32) DEF_HELPER_FLAGS_3(set_cc_subu32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32) -DEF_HELPER_3(srst, i32, i32, i32, i32) -DEF_HELPER_3(clst, i32, i32, i32, i32) -DEF_HELPER_3(mvpg, void, i64, i64, i64) -DEF_HELPER_3(mvst, void, i32, i32, i32) -DEF_HELPER_3(csg, i32, i32, i64, i32) -DEF_HELPER_3(cdsg, i32, i32, i64, i32) -DEF_HELPER_3(cs, i32, i32, i64, i32) -DEF_HELPER_4(ex, i32, i32, i64, i64, i64) +DEF_HELPER_4(srst, i32, env, i32, i32, i32) +DEF_HELPER_4(clst, i32, env, i32, i32, i32) +DEF_HELPER_4(mvpg, void, env, i64, i64, i64) +DEF_HELPER_4(mvst, void, env, i32, i32, i32) +DEF_HELPER_4(csg, i32, env, i32, i64, i32) +DEF_HELPER_4(cdsg, i32, env, i32, i64, i32) +DEF_HELPER_4(cs, i32, env, i32, i64, i32) +DEF_HELPER_5(ex, i32, env, i32, i64, i64, i64) DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32) DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_PURE|TCG_CALL_CONST, s32, s32) DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_PURE|TCG_CALL_CONST, i64, s64) DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_PURE|TCG_CALL_CONST, s64, s64) -DEF_HELPER_3(stcmh, void, i32, i64, i32) -DEF_HELPER_3(icmh, i32, i32, i64, i32) +DEF_HELPER_4(stcmh, void, env, i32, i64, i32) +DEF_HELPER_4(icmh, i32, env, i32, i64, i32) DEF_HELPER_3(ipm, void, env, i32, i32) DEF_HELPER_FLAGS_3(addc_u32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32) DEF_HELPER_FLAGS_3(set_cc_addc_u64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64) -DEF_HELPER_3(stam, void, i32, i64, i32) -DEF_HELPER_3(lam, void, i32, i64, i32) -DEF_HELPER_3(mvcle, i32, i32, i64, i32) -DEF_HELPER_3(clcle, i32, i32, i64, i32) +DEF_HELPER_4(stam, void, env, i32, i64, i32) +DEF_HELPER_4(lam, void, env, i32, i64, i32) +DEF_HELPER_4(mvcle, i32, env, i32, i64, i32) +DEF_HELPER_4(clcle, i32, env, i32, i64, i32) DEF_HELPER_4(slb, i32, env, i32, i32, i32) DEF_HELPER_5(slbg, i32, env, i32, i32, i64, i64) DEF_HELPER_3(cefbr, void, env, i32, s32) @@ -110,8 +110,8 @@ DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE, i32, env, i32, i64) DEF_HELPER_3(flogr, i32, env, i32, i64) DEF_HELPER_3(sqdbr, void, env, i32, i32) DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32) -DEF_HELPER_3(unpk, void, i32, i64, i64) -DEF_HELPER_3(tr, void, i32, i64, i64) +DEF_HELPER_4(unpk, void, env, i32, i64, i64) +DEF_HELPER_4(tr, void, env, i32, i64, i64) DEF_HELPER_3(servc, i32, env, i32, i64) DEF_HELPER_4(diag, i64, env, i32, i64, i64) @@ -127,24 +127,24 @@ DEF_HELPER_FLAGS_2(stckc, TCG_CALL_CONST, void, env, i64) DEF_HELPER_FLAGS_2(spt, TCG_CALL_CONST, void, env, i64) DEF_HELPER_FLAGS_2(stpt, TCG_CALL_CONST, void, env, i64) DEF_HELPER_4(stsi, i32, env, i64, i32, i32) -DEF_HELPER_3(lctl, void, i32, i64, i32) -DEF_HELPER_3(lctlg, void, i32, i64, i32) -DEF_HELPER_3(stctl, void, i32, i64, i32) -DEF_HELPER_3(stctg, void, i32, i64, i32) +DEF_HELPER_4(lctl, void, env, i32, i64, i32) +DEF_HELPER_4(lctlg, void, env, i32, i64, i32) +DEF_HELPER_4(stctl, void, env, i32, i64, i32) +DEF_HELPER_4(stctg, void, env, i32, i64, i32) DEF_HELPER_FLAGS_2(tprot, TCG_CALL_CONST, i32, i64, i64) -DEF_HELPER_FLAGS_1(iske, TCG_CALL_PURE|TCG_CALL_CONST, i64, i64) -DEF_HELPER_FLAGS_2(sske, TCG_CALL_CONST, void, i32, i64) -DEF_HELPER_FLAGS_2(rrbe, TCG_CALL_CONST, i32, i32, i64) -DEF_HELPER_2(csp, i32, i32, i32) -DEF_HELPER_3(mvcs, i32, i64, i64, i64) -DEF_HELPER_3(mvcp, i32, i64, i64, i64) +DEF_HELPER_FLAGS_2(iske, TCG_CALL_PURE|TCG_CALL_CONST, i64, env, i64) +DEF_HELPER_FLAGS_3(sske, TCG_CALL_CONST, void, env, i32, i64) +DEF_HELPER_FLAGS_3(rrbe, TCG_CALL_CONST, i32, env, i32, i64) +DEF_HELPER_3(csp, i32, env, i32, i32) +DEF_HELPER_4(mvcs, i32, env, i64, i64, i64) +DEF_HELPER_4(mvcp, i32, env, i64, i64, i64) DEF_HELPER_4(sigp, i32, env, i64, i32, i64) DEF_HELPER_2(sacf, void, env, i64) -DEF_HELPER_FLAGS_2(ipte, TCG_CALL_CONST, void, i64, i64) -DEF_HELPER_FLAGS_0(ptlb, TCG_CALL_CONST, void) -DEF_HELPER_2(lra, i32, i64, i32) -DEF_HELPER_2(stura, void, i64, i32) -DEF_HELPER_2(cksm, void, i32, i32) +DEF_HELPER_FLAGS_3(ipte, TCG_CALL_CONST, void, env, i64, i64) +DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_CONST, void, env) +DEF_HELPER_3(lra, i32, env, i64, i32) +DEF_HELPER_3(stura, void, env, i64, i32) +DEF_HELPER_3(cksm, void, env, i32, i32) DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST, i32, env, i32, i64, i64, i64) diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c index 52f2602e5c..b21b37c5e7 100644 --- a/target-s390x/mem_helper.c +++ b/target-s390x/mem_helper.c @@ -19,7 +19,6 @@ */ #include "cpu.h" -#include "dyngen-exec.h" #include "helper.h" /*****************************************************************************/ @@ -45,15 +44,12 @@ NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ /* XXX: fix it to restore all registers */ -void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx, +void tlb_fill(CPUS390XState *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { TranslationBlock *tb; - CPUS390XState *saved_env; int ret; - saved_env = env; - env = env1; ret = cpu_s390x_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret != 0)) { if (likely(retaddr)) { @@ -67,7 +63,6 @@ void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx, } cpu_loop_exit(env); } - env = saved_env; } #endif @@ -90,7 +85,7 @@ static void mvc_fast_memset(CPUS390XState *env, uint32_t l, uint64_t dest, int flags; if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) { - stb(dest, byte); + cpu_stb_data(env, dest, byte); cpu_abort(env, "should never reach here"); } dest_phys |= dest & ~TARGET_PAGE_MASK; @@ -114,13 +109,13 @@ static void mvc_fast_memmove(CPUS390XState *env, uint32_t l, uint64_t dest, int flags; if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) { - stb(dest, 0); + cpu_stb_data(env, dest, 0); cpu_abort(env, "should never reach here"); } dest_phys |= dest & ~TARGET_PAGE_MASK; if (mmu_translate(env, src, 0, asc, &src_phys, &flags)) { - ldub(src); + cpu_ldub_data(env, src); cpu_abort(env, "should never reach here"); } src_phys |= src & ~TARGET_PAGE_MASK; @@ -136,7 +131,8 @@ static void mvc_fast_memmove(CPUS390XState *env, uint32_t l, uint64_t dest, #endif /* and on array */ -uint32_t HELPER(nc)(uint32_t l, uint64_t dest, uint64_t src) +uint32_t HELPER(nc)(CPUS390XState *env, uint32_t l, uint64_t dest, + uint64_t src) { int i; unsigned char x; @@ -145,17 +141,18 @@ uint32_t HELPER(nc)(uint32_t l, uint64_t dest, uint64_t src) HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", __func__, l, dest, src); for (i = 0; i <= l; i++) { - x = ldub(dest + i) & ldub(src + i); + x = cpu_ldub_data(env, dest + i) & cpu_ldub_data(env, src + i); if (x) { cc = 1; } - stb(dest + i, x); + cpu_stb_data(env, dest + i, x); } return cc; } /* xor on array */ -uint32_t HELPER(xc)(uint32_t l, uint64_t dest, uint64_t src) +uint32_t HELPER(xc)(CPUS390XState *env, uint32_t l, uint64_t dest, + uint64_t src) { int i; unsigned char x; @@ -179,17 +176,18 @@ uint32_t HELPER(xc)(uint32_t l, uint64_t dest, uint64_t src) #endif for (i = 0; i <= l; i++) { - x = ldub(dest + i) ^ ldub(src + i); + x = cpu_ldub_data(env, dest + i) ^ cpu_ldub_data(env, src + i); if (x) { cc = 1; } - stb(dest + i, x); + cpu_stb_data(env, dest + i, x); } return cc; } /* or on array */ -uint32_t HELPER(oc)(uint32_t l, uint64_t dest, uint64_t src) +uint32_t HELPER(oc)(CPUS390XState *env, uint32_t l, uint64_t dest, + uint64_t src) { int i; unsigned char x; @@ -198,17 +196,17 @@ uint32_t HELPER(oc)(uint32_t l, uint64_t dest, uint64_t src) HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", __func__, l, dest, src); for (i = 0; i <= l; i++) { - x = ldub(dest + i) | ldub(src + i); + x = cpu_ldub_data(env, dest + i) | cpu_ldub_data(env, src + i); if (x) { cc = 1; } - stb(dest + i, x); + cpu_stb_data(env, dest + i, x); } return cc; } /* memmove */ -void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src) +void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) { int i = 0; int x = 0; @@ -222,7 +220,7 @@ void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src) (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK) && (dest & TARGET_PAGE_MASK) == ((dest + l) & TARGET_PAGE_MASK)) { if (dest == (src + 1)) { - mvc_fast_memset(env, l + 1, dest, ldub(src)); + mvc_fast_memset(env, l + 1, dest, cpu_ldub_data(env, src)); return; } else if ((src & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) { mvc_fast_memmove(env, l + 1, dest, src); @@ -231,7 +229,7 @@ void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src) } #else if (dest == (src + 1)) { - memset(g2h(dest), ldub(src), l + 1); + memset(g2h(dest), cpu_ldub_data(env, src), l + 1); return; } else { memmove(g2h(dest), g2h(src), l + 1); @@ -242,19 +240,19 @@ void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src) /* handle the parts that fit into 8-byte loads/stores */ if (dest != (src + 1)) { for (i = 0; i < l_64; i++) { - stq(dest + x, ldq(src + x)); + cpu_stq_data(env, dest + x, cpu_ldq_data(env, src + x)); x += 8; } } /* slow version crossing pages with byte accesses */ for (i = x; i <= l; i++) { - stb(dest + i, ldub(src + i)); + cpu_stb_data(env, dest + i, cpu_ldub_data(env, src + i)); } } /* compare unsigned byte arrays */ -uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2) +uint32_t HELPER(clc)(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2) { int i; unsigned char x, y; @@ -263,8 +261,8 @@ uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2) HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n", __func__, l, s1, s2); for (i = 0; i <= l; i++) { - x = ldub(s1 + i); - y = ldub(s2 + i); + x = cpu_ldub_data(env, s1 + i); + y = cpu_ldub_data(env, s2 + i); HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y); if (x < y) { cc = 1; @@ -281,7 +279,8 @@ uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2) } /* compare logical under mask */ -uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr) +uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask, + uint64_t addr) { uint8_t r, d; uint32_t cc; @@ -291,7 +290,7 @@ uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr) cc = 0; while (mask) { if (mask & 8) { - d = ldub(addr); + d = cpu_ldub_data(env, addr); r = (r1 & 0xff000000UL) >> 24; HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d, addr); @@ -312,7 +311,8 @@ uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr) } /* store character under mask */ -void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr) +void HELPER(stcm)(CPUS390XState *env, uint32_t r1, uint32_t mask, + uint64_t addr) { uint8_t r; @@ -321,7 +321,7 @@ void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr) while (mask) { if (mask & 8) { r = (r1 & 0xff000000UL) >> 24; - stb(addr, r); + cpu_stb_data(env, addr, r); HELPER_LOG("mask 0x%x %02x (0x%lx) ", mask, r, addr); addr++; } @@ -331,7 +331,7 @@ void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr) HELPER_LOG("\n"); } -static inline uint64_t get_address(int x2, int b2, int d2) +static inline uint64_t get_address(CPUS390XState *env, int x2, int b2, int d2) { uint64_t r = d2; @@ -351,7 +351,7 @@ static inline uint64_t get_address(int x2, int b2, int d2) return r; } -static inline uint64_t get_address_31fix(int reg) +static inline uint64_t get_address_31fix(CPUS390XState *env, int reg) { uint64_t r = env->regs[reg]; @@ -364,18 +364,18 @@ static inline uint64_t get_address_31fix(int reg) } /* search string (c is byte to search, r2 is string, r1 end of string) */ -uint32_t HELPER(srst)(uint32_t c, uint32_t r1, uint32_t r2) +uint32_t HELPER(srst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2) { uint64_t i; uint32_t cc = 2; - uint64_t str = get_address_31fix(r2); - uint64_t end = get_address_31fix(r1); + uint64_t str = get_address_31fix(env, r2); + uint64_t end = get_address_31fix(env, r1); HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __func__, c, env->regs[r1], env->regs[r2]); for (i = str; i != end; i++) { - if (ldub(i) == c) { + if (cpu_ldub_data(env, i) == c) { env->regs[r1] = i; cc = 1; break; @@ -386,10 +386,10 @@ uint32_t HELPER(srst)(uint32_t c, uint32_t r1, uint32_t r2) } /* unsigned string compare (c is string terminator) */ -uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2) +uint32_t HELPER(clst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2) { - uint64_t s1 = get_address_31fix(r1); - uint64_t s2 = get_address_31fix(r2); + uint64_t s1 = get_address_31fix(env, r1); + uint64_t s2 = get_address_31fix(env, r2); uint8_t v1, v2; uint32_t cc; @@ -401,8 +401,8 @@ uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2) } #endif for (;;) { - v1 = ldub(s1); - v2 = ldub(s2); + v1 = cpu_ldub_data(env, s1); + v2 = cpu_ldub_data(env, s2); if ((v1 == c || v2 == c) || (v1 != v2)) { break; } @@ -422,14 +422,14 @@ uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2) } /* move page */ -void HELPER(mvpg)(uint64_t r0, uint64_t r1, uint64_t r2) +void HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2) { /* XXX missing r0 handling */ #ifdef CONFIG_USER_ONLY int i; for (i = 0; i < TARGET_PAGE_SIZE; i++) { - stb(r1 + i, ldub(r2 + i)); + cpu_stb_data(env, r1 + i, cpu_ldub_data(env, r2 + i)); } #else mvc_fast_memmove(env, TARGET_PAGE_SIZE, r1, r2); @@ -437,10 +437,10 @@ void HELPER(mvpg)(uint64_t r0, uint64_t r1, uint64_t r2) } /* string copy (c is string terminator) */ -void HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2) +void HELPER(mvst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2) { - uint64_t dest = get_address_31fix(r1); - uint64_t src = get_address_31fix(r2); + uint64_t dest = get_address_31fix(env, r1); + uint64_t src = get_address_31fix(env, r2); uint8_t v; c = c & 0xff; @@ -451,8 +451,8 @@ void HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2) } #endif for (;;) { - v = ldub(src); - stb(dest, v); + v = cpu_ldub_data(env, src); + cpu_stb_data(env, dest, v); if (v == c) { break; } @@ -463,15 +463,15 @@ void HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2) } /* compare and swap 64-bit */ -uint32_t HELPER(csg)(uint32_t r1, uint64_t a2, uint32_t r3) +uint32_t HELPER(csg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { /* FIXME: locking? */ uint32_t cc; - uint64_t v2 = ldq(a2); + uint64_t v2 = cpu_ldq_data(env, a2); if (env->regs[r1] == v2) { cc = 0; - stq(a2, env->regs[r3]); + cpu_stq_data(env, a2, env->regs[r3]); } else { cc = 1; env->regs[r1] = v2; @@ -480,19 +480,19 @@ uint32_t HELPER(csg)(uint32_t r1, uint64_t a2, uint32_t r3) } /* compare double and swap 64-bit */ -uint32_t HELPER(cdsg)(uint32_t r1, uint64_t a2, uint32_t r3) +uint32_t HELPER(cdsg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { /* FIXME: locking? */ uint32_t cc; - uint64_t v2_hi = ldq(a2); - uint64_t v2_lo = ldq(a2 + 8); + uint64_t v2_hi = cpu_ldq_data(env, a2); + uint64_t v2_lo = cpu_ldq_data(env, a2 + 8); uint64_t v1_hi = env->regs[r1]; uint64_t v1_lo = env->regs[r1 + 1]; if ((v1_hi == v2_hi) && (v1_lo == v2_lo)) { cc = 0; - stq(a2, env->regs[r3]); - stq(a2 + 8, env->regs[r3 + 1]); + cpu_stq_data(env, a2, env->regs[r3]); + cpu_stq_data(env, a2 + 8, env->regs[r3 + 1]); } else { cc = 1; env->regs[r1] = v2_hi; @@ -503,16 +503,16 @@ uint32_t HELPER(cdsg)(uint32_t r1, uint64_t a2, uint32_t r3) } /* compare and swap 32-bit */ -uint32_t HELPER(cs)(uint32_t r1, uint64_t a2, uint32_t r3) +uint32_t HELPER(cs)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { /* FIXME: locking? */ uint32_t cc; - uint32_t v2 = ldl(a2); + uint32_t v2 = cpu_ldl_data(env, a2); HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __func__, r1, a2, r3); if (((uint32_t)env->regs[r1]) == v2) { cc = 0; - stl(a2, (uint32_t)env->regs[r3]); + cpu_stl_data(env, a2, (uint32_t)env->regs[r3]); } else { cc = 1; env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | v2; @@ -520,7 +520,8 @@ uint32_t HELPER(cs)(uint32_t r1, uint64_t a2, uint32_t r3) return cc; } -static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask) +static uint32_t helper_icm(CPUS390XState *env, uint32_t r1, uint64_t address, + uint32_t mask) { int pos = 24; /* top of the lower half of r1 */ uint64_t rmask = 0xff000000ULL; @@ -531,7 +532,7 @@ static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask) while (mask) { if (mask & 8) { env->regs[r1] &= ~rmask; - val = ldub(address); + val = cpu_ldub_data(env, address); if ((val & 0x80) && !ccd) { cc = 1; } @@ -557,9 +558,10 @@ static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask) in other words: tricky... currently implemented by interpreting the cases it is most commonly used in */ -uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret) +uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, + uint64_t addr, uint64_t ret) { - uint16_t insn = lduw_code(addr); + uint16_t insn = cpu_lduw_code(env, addr); HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __func__, v1, addr, insn); @@ -567,23 +569,27 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret) uint32_t l, insn2, b1, b2, d1, d2; l = v1 & 0xff; - insn2 = ldl_code(addr + 2); + insn2 = cpu_ldl_code(env, addr + 2); b1 = (insn2 >> 28) & 0xf; b2 = (insn2 >> 12) & 0xf; d1 = (insn2 >> 16) & 0xfff; d2 = insn2 & 0xfff; switch (insn & 0xf00) { case 0x200: - helper_mvc(l, get_address(0, b1, d1), get_address(0, b2, d2)); + helper_mvc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2)); break; case 0x500: - cc = helper_clc(l, get_address(0, b1, d1), get_address(0, b2, d2)); + cc = helper_clc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2)); break; case 0x700: - cc = helper_xc(l, get_address(0, b1, d1), get_address(0, b2, d2)); + cc = helper_xc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2)); break; case 0xc00: - helper_tr(l, get_address(0, b1, d1), get_address(0, b2, d2)); + helper_tr(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2)); break; default: goto abort; @@ -599,12 +605,12 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret) } else if ((insn & 0xff00) == 0xbf00) { uint32_t insn2, r1, r3, b2, d2; - insn2 = ldl_code(addr + 2); + insn2 = cpu_ldl_code(env, addr + 2); r1 = (insn2 >> 20) & 0xf; r3 = (insn2 >> 16) & 0xf; b2 = (insn2 >> 12) & 0xf; d2 = insn2 & 0xfff; - cc = helper_icm(r1, get_address(0, b2, d2), r3); + cc = helper_icm(env, r1, get_address(env, 0, b2, d2), r3); } else { abort: cpu_abort(env, "EXECUTE on instruction prefix 0x%x not implemented\n", @@ -614,13 +620,14 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret) } /* store character under mask high operates on the upper half of r1 */ -void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask) +void HELPER(stcmh)(CPUS390XState *env, uint32_t r1, uint64_t address, + uint32_t mask) { int pos = 56; /* top of the upper half of r1 */ while (mask) { if (mask & 8) { - stb(address, (env->regs[r1] >> pos) & 0xff); + cpu_stb_data(env, address, (env->regs[r1] >> pos) & 0xff); address++; } mask = (mask << 1) & 0xf; @@ -630,7 +637,8 @@ void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask) /* insert character under mask high; same as icm, but operates on the upper half of r1 */ -uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask) +uint32_t HELPER(icmh)(CPUS390XState *env, uint32_t r1, uint64_t address, + uint32_t mask) { int pos = 56; /* top of the upper half of r1 */ uint64_t rmask = 0xff00000000000000ULL; @@ -641,7 +649,7 @@ uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask) while (mask) { if (mask & 8) { env->regs[r1] &= ~rmask; - val = ldub(address); + val = cpu_ldub_data(env, address); if ((val & 0x80) && !ccd) { cc = 1; } @@ -661,12 +669,12 @@ uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask) } /* load access registers r1 to r3 from memory at a2 */ -void HELPER(lam)(uint32_t r1, uint64_t a2, uint32_t r3) +void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { int i; for (i = r1;; i = (i + 1) % 16) { - env->aregs[i] = ldl(a2); + env->aregs[i] = cpu_ldl_data(env, a2); a2 += 4; if (i == r3) { @@ -676,12 +684,12 @@ void HELPER(lam)(uint32_t r1, uint64_t a2, uint32_t r3) } /* store access registers r1 to r3 in memory at a2 */ -void HELPER(stam)(uint32_t r1, uint64_t a2, uint32_t r3) +void HELPER(stam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { int i; for (i = r1;; i = (i + 1) % 16) { - stl(a2, env->aregs[i]); + cpu_stl_data(env, a2, env->aregs[i]); a2 += 4; if (i == r3) { @@ -691,12 +699,12 @@ void HELPER(stam)(uint32_t r1, uint64_t a2, uint32_t r3) } /* move long */ -uint32_t HELPER(mvcl)(uint32_t r1, uint32_t r2) +uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) { uint64_t destlen = env->regs[r1 + 1] & 0xffffff; - uint64_t dest = get_address_31fix(r1); + uint64_t dest = get_address_31fix(env, r1); uint64_t srclen = env->regs[r2 + 1] & 0xffffff; - uint64_t src = get_address_31fix(r2); + uint64_t src = get_address_31fix(env, r2); uint8_t pad = src >> 24; uint8_t v; uint32_t cc; @@ -714,12 +722,12 @@ uint32_t HELPER(mvcl)(uint32_t r1, uint32_t r2) } for (; destlen && srclen; src++, dest++, destlen--, srclen--) { - v = ldub(src); - stb(dest, v); + v = cpu_ldub_data(env, src); + cpu_stb_data(env, dest, v); } for (; destlen; dest++, destlen--) { - stb(dest, pad); + cpu_stb_data(env, dest, pad); } env->regs[r1 + 1] = destlen; @@ -732,7 +740,8 @@ uint32_t HELPER(mvcl)(uint32_t r1, uint32_t r2) } /* move long extended another memcopy insn with more bells and whistles */ -uint32_t HELPER(mvcle)(uint32_t r1, uint64_t a2, uint32_t r3) +uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, + uint32_t r3) { uint64_t destlen = env->regs[r1 + 1]; uint64_t dest = env->regs[r1]; @@ -762,12 +771,12 @@ uint32_t HELPER(mvcle)(uint32_t r1, uint64_t a2, uint32_t r3) } for (; destlen && srclen; src++, dest++, destlen--, srclen--) { - v = ldub(src); - stb(dest, v); + v = cpu_ldub_data(env, src); + cpu_stb_data(env, dest, v); } for (; destlen; dest++, destlen--) { - stb(dest, pad); + cpu_stb_data(env, dest, pad); } env->regs[r1 + 1] = destlen; @@ -781,12 +790,13 @@ uint32_t HELPER(mvcle)(uint32_t r1, uint64_t a2, uint32_t r3) } /* compare logical long extended memcompare insn with padding */ -uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3) +uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, + uint32_t r3) { uint64_t destlen = env->regs[r1 + 1]; - uint64_t dest = get_address_31fix(r1); + uint64_t dest = get_address_31fix(env, r1); uint64_t srclen = env->regs[r3 + 1]; - uint64_t src = get_address_31fix(r3); + uint64_t src = get_address_31fix(env, r3); uint8_t pad = a2 & 0xff; uint8_t v1 = 0, v2 = 0; uint32_t cc = 0; @@ -800,8 +810,8 @@ uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3) } for (; destlen || srclen; src++, dest++, destlen--, srclen--) { - v1 = srclen ? ldub(src) : pad; - v2 = destlen ? ldub(dest) : pad; + v1 = srclen ? cpu_ldub_data(env, src) : pad; + v2 = destlen ? cpu_ldub_data(env, dest) : pad; if (v1 != v2) { cc = (v1 < v2) ? 1 : 2; break; @@ -818,14 +828,14 @@ uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3) } /* checksum */ -void HELPER(cksm)(uint32_t r1, uint32_t r2) +void HELPER(cksm)(CPUS390XState *env, uint32_t r1, uint32_t r2) { - uint64_t src = get_address_31fix(r2); + uint64_t src = get_address_31fix(env, r2); uint64_t src_len = env->regs[(r2 + 1) & 15]; uint64_t cksm = (uint32_t)env->regs[r1]; while (src_len >= 4) { - cksm += ldl(src); + cksm += cpu_ldl_data(env, src); /* move to next word */ src_len -= 4; @@ -836,14 +846,14 @@ void HELPER(cksm)(uint32_t r1, uint32_t r2) case 0: break; case 1: - cksm += ldub(src) << 24; + cksm += cpu_ldub_data(env, src) << 24; break; case 2: - cksm += lduw(src) << 16; + cksm += cpu_lduw_data(env, src) << 16; break; case 3: - cksm += lduw(src) << 16; - cksm += ldub(src + 2) << 8; + cksm += cpu_lduw_data(env, src) << 16; + cksm += cpu_ldub_data(env, src + 2) << 8; break; } @@ -856,7 +866,8 @@ void HELPER(cksm)(uint32_t r1, uint32_t r2) ((uint32_t)cksm + (cksm >> 32)); } -void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src) +void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, + uint64_t src) { int len_dest = len >> 4; int len_src = len & 0xf; @@ -867,8 +878,8 @@ void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src) src += len_src; /* last byte is special, it only flips the nibbles */ - b = ldub(src); - stb(dest, (b << 4) | (b >> 4)); + b = cpu_ldub_data(env, src); + cpu_stb_data(env, dest, (b << 4) | (b >> 4)); src--; len_src--; @@ -878,7 +889,7 @@ void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src) uint8_t cur_byte = 0; if (len_src > 0) { - cur_byte = ldub(src); + cur_byte = cpu_ldub_data(env, src); } len_dest--; @@ -897,30 +908,31 @@ void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src) /* zone bits */ cur_byte |= 0xf0; - stb(dest, cur_byte); + cpu_stb_data(env, dest, cur_byte); } } -void HELPER(tr)(uint32_t len, uint64_t array, uint64_t trans) +void HELPER(tr)(CPUS390XState *env, uint32_t len, uint64_t array, + uint64_t trans) { int i; for (i = 0; i <= len; i++) { - uint8_t byte = ldub(array + i); - uint8_t new_byte = ldub(trans + byte); + uint8_t byte = cpu_ldub_data(env, array + i); + uint8_t new_byte = cpu_ldub_data(env, trans + byte); - stb(array + i, new_byte); + cpu_stb_data(env, array + i, new_byte); } } #if !defined(CONFIG_USER_ONLY) -void HELPER(lctlg)(uint32_t r1, uint64_t a2, uint32_t r3) +void HELPER(lctlg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { int i; uint64_t src = a2; for (i = r1;; i = (i + 1) % 16) { - env->cregs[i] = ldq(src); + env->cregs[i] = cpu_ldq_data(env, src); HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n", i, src, env->cregs[i]); src += sizeof(uint64_t); @@ -933,13 +945,14 @@ void HELPER(lctlg)(uint32_t r1, uint64_t a2, uint32_t r3) tlb_flush(env, 1); } -void HELPER(lctl)(uint32_t r1, uint64_t a2, uint32_t r3) +void HELPER(lctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { int i; uint64_t src = a2; for (i = r1;; i = (i + 1) % 16) { - env->cregs[i] = (env->cregs[i] & 0xFFFFFFFF00000000ULL) | ldl(src); + env->cregs[i] = (env->cregs[i] & 0xFFFFFFFF00000000ULL) | + cpu_ldl_data(env, src); src += sizeof(uint32_t); if (i == r3) { @@ -950,13 +963,13 @@ void HELPER(lctl)(uint32_t r1, uint64_t a2, uint32_t r3) tlb_flush(env, 1); } -void HELPER(stctg)(uint32_t r1, uint64_t a2, uint32_t r3) +void HELPER(stctg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { int i; uint64_t dest = a2; for (i = r1;; i = (i + 1) % 16) { - stq(dest, env->cregs[i]); + cpu_stq_data(env, dest, env->cregs[i]); dest += sizeof(uint64_t); if (i == r3) { @@ -965,13 +978,13 @@ void HELPER(stctg)(uint32_t r1, uint64_t a2, uint32_t r3) } } -void HELPER(stctl)(uint32_t r1, uint64_t a2, uint32_t r3) +void HELPER(stctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { int i; uint64_t dest = a2; for (i = r1;; i = (i + 1) % 16) { - stl(dest, env->cregs[i]); + cpu_stl_data(env, dest, env->cregs[i]); dest += sizeof(uint32_t); if (i == r3) { @@ -988,9 +1001,9 @@ uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2) } /* insert storage key extended */ -uint64_t HELPER(iske)(uint64_t r2) +uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2) { - uint64_t addr = get_address(0, 0, r2); + uint64_t addr = get_address(env, 0, 0, r2); if (addr > ram_size) { return 0; @@ -1000,9 +1013,9 @@ uint64_t HELPER(iske)(uint64_t r2) } /* set storage key extended */ -void HELPER(sske)(uint32_t r1, uint64_t r2) +void HELPER(sske)(CPUS390XState *env, uint32_t r1, uint64_t r2) { - uint64_t addr = get_address(0, 0, r2); + uint64_t addr = get_address(env, 0, 0, r2); if (addr > ram_size) { return; @@ -1012,7 +1025,7 @@ void HELPER(sske)(uint32_t r1, uint64_t r2) } /* reset reference bit extended */ -uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2) +uint32_t HELPER(rrbe)(CPUS390XState *env, uint32_t r1, uint64_t r2) { uint8_t re; uint8_t key; @@ -1038,15 +1051,15 @@ uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2) } /* compare and swap and purge */ -uint32_t HELPER(csp)(uint32_t r1, uint32_t r2) +uint32_t HELPER(csp)(CPUS390XState *env, uint32_t r1, uint32_t r2) { uint32_t cc; uint32_t o1 = env->regs[r1]; - uint64_t a2 = get_address_31fix(r2) & ~3ULL; - uint32_t o2 = ldl(a2); + uint64_t a2 = get_address_31fix(env, r2) & ~3ULL; + uint32_t o2 = cpu_ldl_data(env, a2); if (o1 == o2) { - stl(a2, env->regs[(r1 + 1) & 15]); + cpu_stl_data(env, a2, env->regs[(r1 + 1) & 15]); if (env->regs[r2] & 0x3) { /* flush TLB / ALB */ tlb_flush(env, 1); @@ -1060,8 +1073,8 @@ uint32_t HELPER(csp)(uint32_t r1, uint32_t r2) return cc; } -static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2, - uint64_t mode2) +static uint32_t mvc_asc(CPUS390XState *env, int64_t l, uint64_t a1, + uint64_t mode1, uint64_t a2, uint64_t mode2) { target_ulong src, dest; int flags, cc = 0, i; @@ -1089,7 +1102,7 @@ static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2, /* XXX be more clever */ if ((((dest + i) & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) || (((src + i) & TARGET_PAGE_MASK) != (src & TARGET_PAGE_MASK))) { - mvc_asc(l - i, a1 + i, mode1, a2 + i, mode2); + mvc_asc(env, l - i, a1 + i, mode1, a2 + i, mode2); break; } stb_phys(dest + i, ldub_phys(src + i)); @@ -1098,24 +1111,24 @@ static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2, return cc; } -uint32_t HELPER(mvcs)(uint64_t l, uint64_t a1, uint64_t a2) +uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) { HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n", __func__, l, a1, a2); - return mvc_asc(l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY); + return mvc_asc(env, l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY); } -uint32_t HELPER(mvcp)(uint64_t l, uint64_t a1, uint64_t a2) +uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) { HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n", __func__, l, a1, a2); - return mvc_asc(l, a1, PSW_ASC_PRIMARY, a2, PSW_ASC_SECONDARY); + return mvc_asc(env, l, a1, PSW_ASC_PRIMARY, a2, PSW_ASC_SECONDARY); } /* invalidate pte */ -void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr) +void HELPER(ipte)(CPUS390XState *env, uint64_t pte_addr, uint64_t vaddr) { uint64_t page = vaddr & TARGET_PAGE_MASK; uint64_t pte = 0; @@ -1141,19 +1154,19 @@ void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr) } /* flush local tlb */ -void HELPER(ptlb)(void) +void HELPER(ptlb)(CPUS390XState *env) { tlb_flush(env, 1); } /* store using real address */ -void HELPER(stura)(uint64_t addr, uint32_t v1) +void HELPER(stura)(CPUS390XState *env, uint64_t addr, uint32_t v1) { - stw_phys(get_address(0, 0, addr), v1); + stw_phys(get_address(env, 0, 0, addr), v1); } /* load real address */ -uint32_t HELPER(lra)(uint64_t addr, uint32_t r1) +uint32_t HELPER(lra)(CPUS390XState *env, uint64_t addr, uint32_t r1) { uint32_t cc = 0; int old_exc = env->exception_index; @@ -1188,52 +1201,3 @@ uint32_t HELPER(lra)(uint64_t addr, uint32_t r1) } #endif - -/* temporary wrappers */ -#if defined(CONFIG_USER_ONLY) -#define ldub_data(addr) ldub_raw(addr) -#define lduw_data(addr) lduw_raw(addr) -#define ldl_data(addr) ldl_raw(addr) -#define ldq_data(addr) ldq_raw(addr) - -#define stb_data(addr, data) stb_raw(addr, data) -#define stw_data(addr, data) stw_raw(addr, data) -#define stl_data(addr, data) stl_raw(addr, data) -#define stq_data(addr, data) stq_raw(addr, data) -#endif - -#define WRAP_LD(rettype, fn) \ - rettype cpu_ ## fn(CPUS390XState *env1, target_ulong addr) \ - { \ - CPUS390XState *saved_env; \ - rettype ret; \ - \ - saved_env = env; \ - env = env1; \ - ret = fn(addr); \ - env = saved_env; \ - return ret; \ - } - -WRAP_LD(uint32_t, ldub_data) -WRAP_LD(uint32_t, lduw_data) -WRAP_LD(uint32_t, ldl_data) -WRAP_LD(uint64_t, ldq_data) -#undef WRAP_LD - -#define WRAP_ST(datatype, fn) \ - void cpu_ ## fn(CPUS390XState *env1, target_ulong addr, datatype val) \ - { \ - CPUS390XState *saved_env; \ - \ - saved_env = env; \ - env = env1; \ - fn(addr, val); \ - env = saved_env; \ - } - -WRAP_ST(uint32_t, stb_data) -WRAP_ST(uint32_t, stw_data) -WRAP_ST(uint32_t, stl_data) -WRAP_ST(uint64_t, stq_data) -#undef WRAP_ST diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index ced26c6f16..2938ac9c76 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -31,10 +31,7 @@ #endif #if !defined(CONFIG_USER_ONLY) -/* temporarily disabled due to wrapper use */ -#if 0 #include "softmmu_exec.h" -#endif #include "sysemu.h" #endif diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 0c61e6334b..66119cd122 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -276,19 +276,19 @@ static inline void potential_page_fault(DisasContext *s) static inline uint64_t ld_code2(uint64_t pc) { - return (uint64_t)lduw_code(pc); + return (uint64_t)cpu_lduw_code(cpu_single_env, pc); } static inline uint64_t ld_code4(uint64_t pc) { - return (uint64_t)ldl_code(pc); + return (uint64_t)cpu_ldl_code(cpu_single_env, pc); } static inline uint64_t ld_code6(uint64_t pc) { uint64_t opc; - opc = (uint64_t)lduw_code(pc) << 32; - opc |= (uint64_t)(uint32_t)ldl_code(pc+2); + opc = (uint64_t)cpu_lduw_code(cpu_single_env, pc) << 32; + opc |= (uint64_t)(uint32_t)cpu_ldl_code(cpu_single_env, pc + 2); return opc; } @@ -1263,7 +1263,7 @@ static void gen_op_mvc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2) /* Fall back to helper */ vl = tcg_const_i32(l); potential_page_fault(s); - gen_helper_mvc(vl, s1, s2); + gen_helper_mvc(cpu_env, vl, s1, s2); tcg_temp_free_i32(vl); return; } @@ -1455,7 +1455,7 @@ static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2) potential_page_fault(s); vl = tcg_const_i32(l); - gen_helper_clc(cc_op, vl, s1, s2); + gen_helper_clc(cc_op, cpu_env, vl, s1, s2); tcg_temp_free_i32(vl); set_cc_static(s); } @@ -2094,7 +2094,7 @@ do_mh: tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r3); potential_page_fault(s); - gen_helper_stcmh(tmp32_1, tmp, tmp32_2); + gen_helper_stcmh(cpu_env, tmp32_1, tmp, tmp32_2); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); @@ -2107,7 +2107,7 @@ do_mh: tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r3); potential_page_fault(s); - gen_helper_lctlg(tmp32_1, tmp, tmp32_2); + gen_helper_lctlg(cpu_env, tmp32_1, tmp, tmp32_2); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); @@ -2119,7 +2119,7 @@ do_mh: tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r3); potential_page_fault(s); - gen_helper_stctg(tmp32_1, tmp, tmp32_2); + gen_helper_stctg(cpu_env, tmp32_1, tmp, tmp32_2); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); @@ -2131,7 +2131,7 @@ do_mh: tmp32_2 = tcg_const_i32(r3); potential_page_fault(s); /* XXX rewrite in tcg */ - gen_helper_csg(cc_op, tmp32_1, tmp, tmp32_2); + gen_helper_csg(cc_op, cpu_env, tmp32_1, tmp, tmp32_2); set_cc_static(s); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); @@ -2143,7 +2143,7 @@ do_mh: tmp32_2 = tcg_const_i32(r3); potential_page_fault(s); /* XXX rewrite in tcg */ - gen_helper_cdsg(cc_op, tmp32_1, tmp, tmp32_2); + gen_helper_cdsg(cc_op, cpu_env, tmp32_1, tmp, tmp32_2); set_cc_static(s); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); @@ -2183,7 +2183,7 @@ do_mh: tmp32_2 = tcg_const_i32(r3); potential_page_fault(s); /* XXX split CC calculation out */ - gen_helper_icmh(cc_op, tmp32_1, tmp, tmp32_2); + gen_helper_icmh(cc_op, cpu_env, tmp32_1, tmp, tmp32_2); set_cc_static(s); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); @@ -2635,7 +2635,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r2); potential_page_fault(s); - gen_helper_cksm(tmp32_1, tmp32_2); + gen_helper_cksm(cpu_env, tmp32_1, tmp32_2); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); gen_op_movi_cc(s, 0); @@ -2664,7 +2664,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) tmp2 = load_reg(r1); tmp3 = load_reg(r2); potential_page_fault(s); - gen_helper_mvpg(tmp, tmp2, tmp3); + gen_helper_mvpg(cpu_env, tmp, tmp2, tmp3); tcg_temp_free_i64(tmp); tcg_temp_free_i64(tmp2); tcg_temp_free_i64(tmp3); @@ -2676,7 +2676,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) tmp32_2 = tcg_const_i32(r1); tmp32_3 = tcg_const_i32(r2); potential_page_fault(s); - gen_helper_mvst(tmp32_1, tmp32_2, tmp32_3); + gen_helper_mvst(cpu_env, tmp32_1, tmp32_2, tmp32_3); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); tcg_temp_free_i32(tmp32_3); @@ -2687,7 +2687,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) tmp32_2 = tcg_const_i32(r1); tmp32_3 = tcg_const_i32(r2); potential_page_fault(s); - gen_helper_clst(cc_op, tmp32_1, tmp32_2, tmp32_3); + gen_helper_clst(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3); set_cc_static(s); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); @@ -2698,7 +2698,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) tmp32_2 = tcg_const_i32(r1); tmp32_3 = tcg_const_i32(r2); potential_page_fault(s); - gen_helper_srst(cc_op, tmp32_1, tmp32_2, tmp32_3); + gen_helper_srst(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3); set_cc_static(s); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); @@ -2785,7 +2785,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) case 0x0d: /* PTLB [S] */ /* Purge TLB */ check_privileged(s, ilc); - gen_helper_ptlb(); + gen_helper_ptlb(cpu_env); break; case 0x10: /* SPX D2(B2) [S] */ /* Set Prefix Register */ @@ -2828,7 +2828,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) r2 = insn & 0xf; tmp = load_reg(r1); tmp2 = load_reg(r2); - gen_helper_ipte(tmp, tmp2); + gen_helper_ipte(cpu_env, tmp, tmp2); tcg_temp_free_i64(tmp); tcg_temp_free_i64(tmp2); break; @@ -2839,7 +2839,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) r2 = insn & 0xf; tmp = load_reg(r2); tmp2 = tcg_temp_new_i64(); - gen_helper_iske(tmp2, tmp); + gen_helper_iske(tmp2, cpu_env, tmp); store_reg(r1, tmp2); tcg_temp_free_i64(tmp); tcg_temp_free_i64(tmp2); @@ -2851,7 +2851,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) r2 = insn & 0xf; tmp32_1 = load_reg32(r1); tmp = load_reg(r2); - gen_helper_rrbe(cc_op, tmp32_1, tmp); + gen_helper_rrbe(cc_op, cpu_env, tmp32_1, tmp); set_cc_static(s); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i64(tmp); @@ -2863,7 +2863,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) r2 = insn & 0xf; tmp32_1 = load_reg32(r1); tmp = load_reg(r2); - gen_helper_sske(tmp32_1, tmp); + gen_helper_sske(cpu_env, tmp32_1, tmp); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i64(tmp); break; @@ -2880,7 +2880,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) tmp32_1 = load_reg32(r1); tmp = load_reg(r2); potential_page_fault(s); - gen_helper_stura(tmp, tmp32_1); + gen_helper_stura(cpu_env, tmp, tmp32_1); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i64(tmp); break; @@ -2891,7 +2891,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) r2 = insn & 0xf; tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r2); - gen_helper_csp(cc_op, tmp32_1, tmp32_2); + gen_helper_csp(cc_op, cpu_env, tmp32_1, tmp32_2); set_cc_static(s); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); @@ -3865,7 +3865,7 @@ static void disas_s390_insn(DisasContext *s) int ilc; int l1; - opc = ldub_code(s->pc); + opc = cpu_ldub_code(cpu_single_env, s->pc); LOG_DISAS("opc 0x%x\n", opc); ilc = get_ilc(opc); @@ -3951,7 +3951,7 @@ static void disas_s390_insn(DisasContext *s) tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r2); potential_page_fault(s); - gen_helper_mvcl(cc_op, tmp32_1, tmp32_2); + gen_helper_mvcl(cc_op, cpu_env, tmp32_1, tmp32_2); set_cc_static(s); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); @@ -4165,7 +4165,7 @@ static void disas_s390_insn(DisasContext *s) tmp3 = tcg_const_i64(s->pc + 4); update_psw_addr(s); gen_op_calc_cc(s); - gen_helper_ex(cc_op, cc_op, tmp2, tmp, tmp3); + gen_helper_ex(cc_op, cpu_env, cc_op, tmp2, tmp, tmp3); set_cc_static(s); tcg_temp_free_i64(tmp); tcg_temp_free_i64(tmp2); @@ -4694,7 +4694,7 @@ static void disas_s390_insn(DisasContext *s) tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r3); potential_page_fault(s); - gen_helper_lam(tmp32_1, tmp, tmp32_2); + gen_helper_lam(cpu_env, tmp32_1, tmp, tmp32_2); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); @@ -4706,7 +4706,7 @@ static void disas_s390_insn(DisasContext *s) tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r3); potential_page_fault(s); - gen_helper_stam(tmp32_1, tmp, tmp32_2); + gen_helper_stam(cpu_env, tmp32_1, tmp, tmp32_2); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); @@ -4732,7 +4732,7 @@ static void disas_s390_insn(DisasContext *s) tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r3); potential_page_fault(s); - gen_helper_mvcle(cc_op, tmp32_1, tmp, tmp32_2); + gen_helper_mvcle(cc_op, cpu_env, tmp32_1, tmp, tmp32_2); set_cc_static(s); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); @@ -4745,7 +4745,7 @@ static void disas_s390_insn(DisasContext *s) tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r3); potential_page_fault(s); - gen_helper_clcle(cc_op, tmp32_1, tmp, tmp32_2); + gen_helper_clcle(cc_op, cpu_env, tmp32_1, tmp, tmp32_2); set_cc_static(s); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); @@ -4789,7 +4789,7 @@ static void disas_s390_insn(DisasContext *s) tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp32_1 = tcg_const_i32(r1); potential_page_fault(s); - gen_helper_lra(cc_op, tmp, tmp32_1); + gen_helper_lra(cc_op, cpu_env, tmp, tmp32_1); set_cc_static(s); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); @@ -4835,7 +4835,7 @@ static void disas_s390_insn(DisasContext *s) tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r3); potential_page_fault(s); - gen_helper_stctl(tmp32_1, tmp, tmp32_2); + gen_helper_stctl(cpu_env, tmp32_1, tmp, tmp32_2); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); @@ -4849,7 +4849,7 @@ static void disas_s390_insn(DisasContext *s) tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r3); potential_page_fault(s); - gen_helper_lctl(tmp32_1, tmp, tmp32_2); + gen_helper_lctl(cpu_env, tmp32_1, tmp, tmp32_2); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); @@ -4869,7 +4869,7 @@ static void disas_s390_insn(DisasContext *s) tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r3); potential_page_fault(s); - gen_helper_cs(cc_op, tmp32_1, tmp, tmp32_2); + gen_helper_cs(cc_op, cpu_env, tmp32_1, tmp, tmp32_2); set_cc_static(s); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); @@ -4882,7 +4882,7 @@ static void disas_s390_insn(DisasContext *s) tmp32_1 = load_reg32(r1); tmp32_2 = tcg_const_i32(r3); potential_page_fault(s); - gen_helper_clm(cc_op, tmp32_1, tmp32_2, tmp); + gen_helper_clm(cc_op, cpu_env, tmp32_1, tmp32_2, tmp); set_cc_static(s); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); @@ -4895,7 +4895,7 @@ static void disas_s390_insn(DisasContext *s) tmp32_1 = load_reg32(r1); tmp32_2 = tcg_const_i32(r3); potential_page_fault(s); - gen_helper_stcm(tmp32_1, tmp32_2, tmp); + gen_helper_stcm(cpu_env, tmp32_1, tmp32_2, tmp); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_2); @@ -4992,7 +4992,7 @@ static void disas_s390_insn(DisasContext *s) break; case 0xd4: potential_page_fault(s); - gen_helper_nc(cc_op, vl, tmp, tmp2); + gen_helper_nc(cc_op, cpu_env, vl, tmp, tmp2); set_cc_static(s); break; case 0xd5: @@ -5000,22 +5000,22 @@ static void disas_s390_insn(DisasContext *s) break; case 0xd6: potential_page_fault(s); - gen_helper_oc(cc_op, vl, tmp, tmp2); + gen_helper_oc(cc_op, cpu_env, vl, tmp, tmp2); set_cc_static(s); break; case 0xd7: potential_page_fault(s); - gen_helper_xc(cc_op, vl, tmp, tmp2); + gen_helper_xc(cc_op, cpu_env, vl, tmp, tmp2); set_cc_static(s); break; case 0xdc: potential_page_fault(s); - gen_helper_tr(vl, tmp, tmp2); + gen_helper_tr(cpu_env, vl, tmp, tmp2); set_cc_static(s); break; case 0xf3: potential_page_fault(s); - gen_helper_unpk(vl, tmp, tmp2); + gen_helper_unpk(cpu_env, vl, tmp, tmp2); break; default: tcg_abort(); @@ -5040,9 +5040,9 @@ static void disas_s390_insn(DisasContext *s) tmp2 = get_address(s, 0, b1, d1); tmp3 = get_address(s, 0, b2, d2); if (opc == 0xda) { - gen_helper_mvcp(cc_op, tmp, tmp2, tmp3); + gen_helper_mvcp(cc_op, cpu_env, tmp, tmp2, tmp3); } else { - gen_helper_mvcs(cc_op, tmp, tmp2, tmp3); + gen_helper_mvcs(cc_op, cpu_env, tmp, tmp2, tmp3); } set_cc_static(s); tcg_temp_free_i64(tmp); From 6845df48cec9cc6833429942b3ceed333a791119 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 03:45:43 +0000 Subject: [PATCH 0228/2270] tcg/s390: fix ld/st with CONFIG_TCG_PASS_AREG0 The load/store slow path has been broken in e141ab52d: - We need to move 4 registers for store functions and 3 registers for load functions and not the reverse. - According to the s390x calling convention the arguments of a function should be zero extended. This means that the register shift should be done with TCG_TYPE_I64 to ensure the higher word is correctly zero extended when needed. I am aware that CONFIG_TCG_PASS_AREG0 is being removed and thus that this patch can be improved, but doing so means it can also be applied to the 1.1 and 1.2 stable branches. Signed-off-by: Aurelien Jarno Signed-off-by: Alexander Graf --- tcg/s390/tcg-target.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c index 04662c15fd..99b53390c5 100644 --- a/tcg/s390/tcg-target.c +++ b/tcg/s390/tcg-target.c @@ -1509,11 +1509,13 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg, tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R4, mem_index); #ifdef CONFIG_TCG_PASS_AREG0 /* XXX/FIXME: suboptimal */ - tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3], + tcg_target_call_iarg_regs[2]); + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], tcg_target_call_iarg_regs[1]); - tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1], + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1], tcg_target_call_iarg_regs[0]); - tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0); #endif tgen_calli(s, (tcg_target_ulong)qemu_st_helpers[s_bits]); @@ -1521,13 +1523,11 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg, tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index); #ifdef CONFIG_TCG_PASS_AREG0 /* XXX/FIXME: suboptimal */ - tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3], - tcg_target_call_iarg_regs[2]); tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], tcg_target_call_iarg_regs[1]); - tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1], + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1], tcg_target_call_iarg_regs[0]); - tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0); #endif tgen_calli(s, (tcg_target_ulong)qemu_ld_helpers[s_bits]); From cc57407e966e8467f9742e7a4ad47567b5951122 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 27 Aug 2012 08:28:38 +0200 Subject: [PATCH 0229/2270] kvm: Introduce kvm_irqchip_update_msi_route This service allows to update an MSI route without releasing/reacquiring the associated VIRQ. Will be used by PCI device assignment, later on likely also by virtio/vhost and VFIO. Signed-off-by: Jan Kiszka Acked-by: Acked-by: Michael S. Tsirkin Signed-off-by: Avi Kivity --- kvm-all.c | 42 ++++++++++++++++++++++++++++++++++++++++++ kvm.h | 1 + 2 files changed, 43 insertions(+) diff --git a/kvm-all.c b/kvm-all.c index f96be21034..e2abfb98d6 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -963,6 +963,30 @@ static void kvm_add_routing_entry(KVMState *s, kvm_irqchip_commit_routes(s); } +static int kvm_update_routing_entry(KVMState *s, + struct kvm_irq_routing_entry *new_entry) +{ + struct kvm_irq_routing_entry *entry; + int n; + + for (n = 0; n < s->irq_routes->nr; n++) { + entry = &s->irq_routes->entries[n]; + if (entry->gsi != new_entry->gsi) { + continue; + } + + entry->type = new_entry->type; + entry->flags = new_entry->flags; + entry->u = new_entry->u; + + kvm_irqchip_commit_routes(s); + + return 0; + } + + return -ESRCH; +} + void kvm_irqchip_add_irq_route(KVMState *s, int irq, int irqchip, int pin) { struct kvm_irq_routing_entry e; @@ -1125,6 +1149,24 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg) return virq; } +int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg) +{ + struct kvm_irq_routing_entry kroute; + + if (!kvm_irqchip_in_kernel()) { + return -ENOSYS; + } + + kroute.gsi = virq; + kroute.type = KVM_IRQ_ROUTING_MSI; + kroute.flags = 0; + kroute.u.msi.address_lo = (uint32_t)msg.address; + kroute.u.msi.address_hi = msg.address >> 32; + kroute.u.msi.data = msg.data; + + return kvm_update_routing_entry(s, &kroute); +} + static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign) { struct kvm_irqfd irqfd = { diff --git a/kvm.h b/kvm.h index 37d1f8166a..5cefe3a1a3 100644 --- a/kvm.h +++ b/kvm.h @@ -270,6 +270,7 @@ int kvm_set_ioeventfd_mmio(int fd, uint32_t adr, uint32_t val, bool assign, int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign); int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg); +int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg); void kvm_irqchip_release_virq(KVMState *s, int virq); int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq); From 3ab73842446a9f2d9d78b23daa43ff382679eece Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 27 Aug 2012 08:28:39 +0200 Subject: [PATCH 0230/2270] kvm: Introduce kvm_has_intx_set_mask Will be used by PCI device assignment code. Signed-off-by: Jan Kiszka Acked-by: Acked-by: Michael S. Tsirkin Signed-off-by: Avi Kivity --- kvm-all.c | 8 ++++++++ kvm.h | 1 + 2 files changed, 9 insertions(+) diff --git a/kvm-all.c b/kvm-all.c index e2abfb98d6..39cff55f5b 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -88,6 +88,7 @@ struct KVMState int pit_state2; int xsave, xcrs; int many_ioeventfds; + int intx_set_mask; /* The man page (and posix) say ioctl numbers are signed int, but * they're not. Linux, glibc and *BSD all treat ioctl numbers as * unsigned, and treating them as signed here can break things */ @@ -1386,6 +1387,8 @@ int kvm_init(void) s->direct_msi = (kvm_check_extension(s, KVM_CAP_SIGNAL_MSI) > 0); #endif + s->intx_set_mask = kvm_check_extension(s, KVM_CAP_PCI_2_3); + ret = kvm_arch_init(s); if (ret < 0) { goto err; @@ -1740,6 +1743,11 @@ int kvm_has_gsi_routing(void) #endif } +int kvm_has_intx_set_mask(void) +{ + return kvm_state->intx_set_mask; +} + void *kvm_vmalloc(ram_addr_t size) { #ifdef TARGET_S390X diff --git a/kvm.h b/kvm.h index 5cefe3a1a3..dea2998fd4 100644 --- a/kvm.h +++ b/kvm.h @@ -117,6 +117,7 @@ int kvm_has_xcrs(void); int kvm_has_pit_state2(void); int kvm_has_many_ioeventfds(void); int kvm_has_gsi_routing(void); +int kvm_has_intx_set_mask(void); #ifdef NEED_CPU_H int kvm_init_vcpu(CPUArchState *env); From b139bd300f4f579c526d153efa4960c380e2b6e3 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 27 Aug 2012 08:28:40 +0200 Subject: [PATCH 0231/2270] kvm: i386: Add services required for PCI device assignment These helpers abstract the interaction of upcoming pci-assign with the KVM kernel services. Put them under i386 only as other archs will implement device pass-through via VFIO and not this classic interface. Signed-off-by: Jan Kiszka Acked-by: Acked-by: Michael S. Tsirkin Signed-off-by: Avi Kivity --- target-i386/kvm.c | 141 +++++++++++++++++++++++++++++++++++++++++ target-i386/kvm_i386.h | 22 +++++++ 2 files changed, 163 insertions(+) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index ffc294ec39..6790180b0a 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -31,6 +31,7 @@ #include "hw/apic.h" #include "ioport.h" #include "hyperv.h" +#include "hw/pci.h" //#define DEBUG_KVM @@ -2068,3 +2069,143 @@ void kvm_arch_init_irq_routing(KVMState *s) kvm_msi_via_irqfd_allowed = true; kvm_gsi_routing_allowed = true; } + +/* Classic KVM device assignment interface. Will remain x86 only. */ +int kvm_device_pci_assign(KVMState *s, PCIHostDeviceAddress *dev_addr, + uint32_t flags, uint32_t *dev_id) +{ + struct kvm_assigned_pci_dev dev_data = { + .segnr = dev_addr->domain, + .busnr = dev_addr->bus, + .devfn = PCI_DEVFN(dev_addr->slot, dev_addr->function), + .flags = flags, + }; + int ret; + + dev_data.assigned_dev_id = + (dev_addr->domain << 16) | (dev_addr->bus << 8) | dev_data.devfn; + + ret = kvm_vm_ioctl(s, KVM_ASSIGN_PCI_DEVICE, &dev_data); + if (ret < 0) { + return ret; + } + + *dev_id = dev_data.assigned_dev_id; + + return 0; +} + +int kvm_device_pci_deassign(KVMState *s, uint32_t dev_id) +{ + struct kvm_assigned_pci_dev dev_data = { + .assigned_dev_id = dev_id, + }; + + return kvm_vm_ioctl(s, KVM_DEASSIGN_PCI_DEVICE, &dev_data); +} + +static int kvm_assign_irq_internal(KVMState *s, uint32_t dev_id, + uint32_t irq_type, uint32_t guest_irq) +{ + struct kvm_assigned_irq assigned_irq = { + .assigned_dev_id = dev_id, + .guest_irq = guest_irq, + .flags = irq_type, + }; + + if (kvm_check_extension(s, KVM_CAP_ASSIGN_DEV_IRQ)) { + return kvm_vm_ioctl(s, KVM_ASSIGN_DEV_IRQ, &assigned_irq); + } else { + return kvm_vm_ioctl(s, KVM_ASSIGN_IRQ, &assigned_irq); + } +} + +int kvm_device_intx_assign(KVMState *s, uint32_t dev_id, bool use_host_msi, + uint32_t guest_irq) +{ + uint32_t irq_type = KVM_DEV_IRQ_GUEST_INTX | + (use_host_msi ? KVM_DEV_IRQ_HOST_MSI : KVM_DEV_IRQ_HOST_INTX); + + return kvm_assign_irq_internal(s, dev_id, irq_type, guest_irq); +} + +int kvm_device_intx_set_mask(KVMState *s, uint32_t dev_id, bool masked) +{ + struct kvm_assigned_pci_dev dev_data = { + .assigned_dev_id = dev_id, + .flags = masked ? KVM_DEV_ASSIGN_MASK_INTX : 0, + }; + + return kvm_vm_ioctl(s, KVM_ASSIGN_SET_INTX_MASK, &dev_data); +} + +static int kvm_deassign_irq_internal(KVMState *s, uint32_t dev_id, + uint32_t type) +{ + struct kvm_assigned_irq assigned_irq = { + .assigned_dev_id = dev_id, + .flags = type, + }; + + return kvm_vm_ioctl(s, KVM_DEASSIGN_DEV_IRQ, &assigned_irq); +} + +int kvm_device_intx_deassign(KVMState *s, uint32_t dev_id, bool use_host_msi) +{ + return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_INTX | + (use_host_msi ? KVM_DEV_IRQ_HOST_MSI : KVM_DEV_IRQ_HOST_INTX)); +} + +int kvm_device_msi_assign(KVMState *s, uint32_t dev_id, int virq) +{ + return kvm_assign_irq_internal(s, dev_id, KVM_DEV_IRQ_HOST_MSI | + KVM_DEV_IRQ_GUEST_MSI, virq); +} + +int kvm_device_msi_deassign(KVMState *s, uint32_t dev_id) +{ + return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_MSI | + KVM_DEV_IRQ_HOST_MSI); +} + +bool kvm_device_msix_supported(KVMState *s) +{ + /* The kernel lacks a corresponding KVM_CAP, so we probe by calling + * KVM_ASSIGN_SET_MSIX_NR with an invalid parameter. */ + return kvm_vm_ioctl(s, KVM_ASSIGN_SET_MSIX_NR, NULL) == -EFAULT; +} + +int kvm_device_msix_init_vectors(KVMState *s, uint32_t dev_id, + uint32_t nr_vectors) +{ + struct kvm_assigned_msix_nr msix_nr = { + .assigned_dev_id = dev_id, + .entry_nr = nr_vectors, + }; + + return kvm_vm_ioctl(s, KVM_ASSIGN_SET_MSIX_NR, &msix_nr); +} + +int kvm_device_msix_set_vector(KVMState *s, uint32_t dev_id, uint32_t vector, + int virq) +{ + struct kvm_assigned_msix_entry msix_entry = { + .assigned_dev_id = dev_id, + .gsi = virq, + .entry = vector, + }; + + return kvm_vm_ioctl(s, KVM_ASSIGN_SET_MSIX_ENTRY, &msix_entry); +} + +int kvm_device_msix_assign(KVMState *s, uint32_t dev_id) +{ + return kvm_assign_irq_internal(s, dev_id, KVM_DEV_IRQ_HOST_MSIX | + KVM_DEV_IRQ_GUEST_MSIX, 0); +} + +int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id) +{ + return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_MSIX | + KVM_DEV_IRQ_HOST_MSIX); +} diff --git a/target-i386/kvm_i386.h b/target-i386/kvm_i386.h index b82bbf401e..f6ab82f93c 100644 --- a/target-i386/kvm_i386.h +++ b/target-i386/kvm_i386.h @@ -11,6 +11,28 @@ #ifndef QEMU_KVM_I386_H #define QEMU_KVM_I386_H +#include "kvm.h" + bool kvm_allows_irq0_override(void); +int kvm_device_pci_assign(KVMState *s, PCIHostDeviceAddress *dev_addr, + uint32_t flags, uint32_t *dev_id); +int kvm_device_pci_deassign(KVMState *s, uint32_t dev_id); + +int kvm_device_intx_assign(KVMState *s, uint32_t dev_id, + bool use_host_msi, uint32_t guest_irq); +int kvm_device_intx_set_mask(KVMState *s, uint32_t dev_id, bool masked); +int kvm_device_intx_deassign(KVMState *s, uint32_t dev_id, bool use_host_msi); + +int kvm_device_msi_assign(KVMState *s, uint32_t dev_id, int virq); +int kvm_device_msi_deassign(KVMState *s, uint32_t dev_id); + +bool kvm_device_msix_supported(KVMState *s); +int kvm_device_msix_init_vectors(KVMState *s, uint32_t dev_id, + uint32_t nr_vectors); +int kvm_device_msix_set_vector(KVMState *s, uint32_t dev_id, uint32_t vector, + int virq); +int kvm_device_msix_assign(KVMState *s, uint32_t dev_id); +int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id); + #endif From c3ebd3ba786e1be5449527e47001eded6b59322b Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 30 Aug 2012 20:30:00 +0200 Subject: [PATCH 0232/2270] kvm: i386: Add classic PCI device assignment This adds PCI device assignment for i386 targets using the classic KVM interfaces. This version is 100% identical to what is being maintained in qemu-kvm for several years and is supported by libvirt as well. It is expected to remain relevant for another couple of years until kernels without full-features and performance-wise equivalent VFIO support are obsolete. A refactoring to-do that should be done in-tree is to model MSI and MSI-X support via the generic PCI layer, similar to what VFIO is already doing for MSI-X. This should improve the correctness and clean up the code from duplicate logic. Signed-off-by: Jan Kiszka Acked-by: Acked-by: Michael S. Tsirkin Signed-off-by: Avi Kivity --- hw/kvm/Makefile.objs | 2 +- hw/kvm/pci-assign.c | 1915 ++++++++++++++++++++++++++++++++++++++++++ hw/qdev-monitor.c | 1 + 3 files changed, 1917 insertions(+), 1 deletion(-) create mode 100644 hw/kvm/pci-assign.c diff --git a/hw/kvm/Makefile.objs b/hw/kvm/Makefile.objs index 226497a58f..f620d7ff85 100644 --- a/hw/kvm/Makefile.objs +++ b/hw/kvm/Makefile.objs @@ -1 +1 @@ -obj-$(CONFIG_KVM) += clock.o apic.o i8259.o ioapic.o i8254.o +obj-$(CONFIG_KVM) += clock.o apic.o i8259.o ioapic.o i8254.o pci-assign.o diff --git a/hw/kvm/pci-assign.c b/hw/kvm/pci-assign.c new file mode 100644 index 0000000000..05b93d9a51 --- /dev/null +++ b/hw/kvm/pci-assign.c @@ -0,0 +1,1915 @@ +/* + * Copyright (c) 2007, Neocleus Corporation. + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * + * Assign a PCI device from the host to a guest VM. + * + * This implementation uses the classic device assignment interface of KVM + * and is only available on x86 hosts. It is expected to be obsoleted by VFIO + * based device assignment. + * + * Adapted for KVM (qemu-kvm) by Qumranet. QEMU version was based on qemu-kvm + * revision 4144fe9d48. See its repository for the history. + * + * Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com) + * Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com) + * Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com) + * Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com) + * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) + */ +#include +#include +#include +#include +#include +#include +#include "hw/hw.h" +#include "hw/pc.h" +#include "qemu-error.h" +#include "console.h" +#include "hw/loader.h" +#include "monitor.h" +#include "range.h" +#include "sysemu.h" +#include "hw/pci.h" +#include "hw/msi.h" +#include "kvm_i386.h" + +#define MSIX_PAGE_SIZE 0x1000 + +/* From linux/ioport.h */ +#define IORESOURCE_IO 0x00000100 /* Resource type */ +#define IORESOURCE_MEM 0x00000200 +#define IORESOURCE_IRQ 0x00000400 +#define IORESOURCE_DMA 0x00000800 +#define IORESOURCE_PREFETCH 0x00002000 /* No side effects */ + +//#define DEVICE_ASSIGNMENT_DEBUG + +#ifdef DEVICE_ASSIGNMENT_DEBUG +#define DEBUG(fmt, ...) \ + do { \ + fprintf(stderr, "%s: " fmt, __func__ , __VA_ARGS__); \ + } while (0) +#else +#define DEBUG(fmt, ...) +#endif + +typedef struct PCIRegion { + int type; /* Memory or port I/O */ + int valid; + uint64_t base_addr; + uint64_t size; /* size of the region */ + int resource_fd; +} PCIRegion; + +typedef struct PCIDevRegions { + uint8_t bus, dev, func; /* Bus inside domain, device and function */ + int irq; /* IRQ number */ + uint16_t region_number; /* number of active regions */ + + /* Port I/O or MMIO Regions */ + PCIRegion regions[PCI_NUM_REGIONS - 1]; + int config_fd; +} PCIDevRegions; + +typedef struct AssignedDevRegion { + MemoryRegion container; + MemoryRegion real_iomem; + union { + uint8_t *r_virtbase; /* mmapped access address for memory regions */ + uint32_t r_baseport; /* the base guest port for I/O regions */ + } u; + pcibus_t e_size; /* emulated size of region in bytes */ + pcibus_t r_size; /* real size of region in bytes */ + PCIRegion *region; +} AssignedDevRegion; + +#define ASSIGNED_DEVICE_PREFER_MSI_BIT 0 +#define ASSIGNED_DEVICE_SHARE_INTX_BIT 1 + +#define ASSIGNED_DEVICE_PREFER_MSI_MASK (1 << ASSIGNED_DEVICE_PREFER_MSI_BIT) +#define ASSIGNED_DEVICE_SHARE_INTX_MASK (1 << ASSIGNED_DEVICE_SHARE_INTX_BIT) + +typedef struct MSIXTableEntry { + uint32_t addr_lo; + uint32_t addr_hi; + uint32_t data; + uint32_t ctrl; +} MSIXTableEntry; + +typedef enum AssignedIRQType { + ASSIGNED_IRQ_NONE = 0, + ASSIGNED_IRQ_INTX_HOST_INTX, + ASSIGNED_IRQ_INTX_HOST_MSI, + ASSIGNED_IRQ_MSI, + ASSIGNED_IRQ_MSIX +} AssignedIRQType; + +typedef struct AssignedDevice { + PCIDevice dev; + PCIHostDeviceAddress host; + uint32_t dev_id; + uint32_t features; + int intpin; + AssignedDevRegion v_addrs[PCI_NUM_REGIONS - 1]; + PCIDevRegions real_device; + PCIINTxRoute intx_route; + AssignedIRQType assigned_irq_type; + struct { +#define ASSIGNED_DEVICE_CAP_MSI (1 << 0) +#define ASSIGNED_DEVICE_CAP_MSIX (1 << 1) + uint32_t available; +#define ASSIGNED_DEVICE_MSI_ENABLED (1 << 0) +#define ASSIGNED_DEVICE_MSIX_ENABLED (1 << 1) +#define ASSIGNED_DEVICE_MSIX_MASKED (1 << 2) + uint32_t state; + } cap; + uint8_t emulate_config_read[PCI_CONFIG_SPACE_SIZE]; + uint8_t emulate_config_write[PCI_CONFIG_SPACE_SIZE]; + int msi_virq_nr; + int *msi_virq; + MSIXTableEntry *msix_table; + target_phys_addr_t msix_table_addr; + uint16_t msix_max; + MemoryRegion mmio; + char *configfd_name; + int32_t bootindex; +} AssignedDevice; + +static void assigned_dev_update_irq_routing(PCIDevice *dev); + +static void assigned_dev_load_option_rom(AssignedDevice *dev); + +static void assigned_dev_unregister_msix_mmio(AssignedDevice *dev); + +static uint64_t assigned_dev_ioport_rw(AssignedDevRegion *dev_region, + target_phys_addr_t addr, int size, + uint64_t *data) +{ + 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); + } + } 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); + } + } + return val; +} + +static void assigned_dev_ioport_write(void *opaque, target_phys_addr_t addr, + uint64_t data, unsigned size) +{ + assigned_dev_ioport_rw(opaque, addr, size, &data); +} + +static uint64_t assigned_dev_ioport_read(void *opaque, + target_phys_addr_t addr, unsigned size) +{ + return assigned_dev_ioport_rw(opaque, addr, size, NULL); +} + +static uint32_t slow_bar_readb(void *opaque, target_phys_addr_t addr) +{ + AssignedDevRegion *d = opaque; + uint8_t *in = d->u.r_virtbase + addr; + uint32_t r; + + r = *in; + DEBUG("slow_bar_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r); + + return r; +} + +static uint32_t slow_bar_readw(void *opaque, target_phys_addr_t addr) +{ + AssignedDevRegion *d = opaque; + uint16_t *in = (uint16_t *)(d->u.r_virtbase + addr); + uint32_t r; + + r = *in; + DEBUG("slow_bar_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r); + + return r; +} + +static uint32_t slow_bar_readl(void *opaque, target_phys_addr_t addr) +{ + AssignedDevRegion *d = opaque; + uint32_t *in = (uint32_t *)(d->u.r_virtbase + addr); + uint32_t r; + + r = *in; + DEBUG("slow_bar_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r); + + return r; +} + +static void slow_bar_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + AssignedDevRegion *d = opaque; + uint8_t *out = d->u.r_virtbase + addr; + + DEBUG("slow_bar_writeb addr=0x" TARGET_FMT_plx " val=0x%02x\n", addr, val); + *out = val; +} + +static void slow_bar_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + AssignedDevRegion *d = opaque; + uint16_t *out = (uint16_t *)(d->u.r_virtbase + addr); + + DEBUG("slow_bar_writew addr=0x" TARGET_FMT_plx " val=0x%04x\n", addr, val); + *out = val; +} + +static void slow_bar_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + AssignedDevRegion *d = opaque; + uint32_t *out = (uint32_t *)(d->u.r_virtbase + addr); + + DEBUG("slow_bar_writel addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, val); + *out = val; +} + +static const MemoryRegionOps slow_bar_ops = { + .old_mmio = { + .read = { slow_bar_readb, slow_bar_readw, slow_bar_readl, }, + .write = { slow_bar_writeb, slow_bar_writew, slow_bar_writel, }, + }, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void assigned_dev_iomem_setup(PCIDevice *pci_dev, int region_num, + pcibus_t e_size) +{ + AssignedDevice *r_dev = DO_UPCAST(AssignedDevice, dev, pci_dev); + AssignedDevRegion *region = &r_dev->v_addrs[region_num]; + PCIRegion *real_region = &r_dev->real_device.regions[region_num]; + + if (e_size > 0) { + memory_region_init(®ion->container, "assigned-dev-container", + e_size); + memory_region_add_subregion(®ion->container, 0, ®ion->real_iomem); + + /* deal with MSI-X MMIO page */ + if (real_region->base_addr <= r_dev->msix_table_addr && + real_region->base_addr + real_region->size > + r_dev->msix_table_addr) { + uint64_t offset = r_dev->msix_table_addr - real_region->base_addr; + + memory_region_add_subregion_overlap(®ion->container, + offset, + &r_dev->mmio, + 1); + } + } +} + +static const MemoryRegionOps assigned_dev_ioport_ops = { + .read = assigned_dev_ioport_read, + .write = assigned_dev_ioport_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void assigned_dev_ioport_setup(PCIDevice *pci_dev, int region_num, + pcibus_t size) +{ + AssignedDevice *r_dev = DO_UPCAST(AssignedDevice, dev, pci_dev); + AssignedDevRegion *region = &r_dev->v_addrs[region_num]; + + region->e_size = size; + memory_region_init(®ion->container, "assigned-dev-container", size); + memory_region_init_io(®ion->real_iomem, &assigned_dev_ioport_ops, + r_dev->v_addrs + region_num, + "assigned-dev-iomem", size); + memory_region_add_subregion(®ion->container, 0, ®ion->real_iomem); +} + +static uint32_t assigned_dev_pci_read(PCIDevice *d, int pos, int len) +{ + AssignedDevice *pci_dev = DO_UPCAST(AssignedDevice, dev, d); + uint32_t val; + ssize_t ret; + int fd = pci_dev->real_device.config_fd; + +again: + ret = pread(fd, &val, len, pos); + if (ret != len) { + if ((ret < 0) && (errno == EINTR || errno == EAGAIN)) { + goto again; + } + + hw_error("pci read failed, ret = %zd errno = %d\n", ret, errno); + } + + return val; +} + +static uint8_t assigned_dev_pci_read_byte(PCIDevice *d, int pos) +{ + return (uint8_t)assigned_dev_pci_read(d, pos, 1); +} + +static void assigned_dev_pci_write(PCIDevice *d, int pos, uint32_t val, int len) +{ + AssignedDevice *pci_dev = DO_UPCAST(AssignedDevice, dev, d); + ssize_t ret; + int fd = pci_dev->real_device.config_fd; + +again: + ret = pwrite(fd, &val, len, pos); + if (ret != len) { + if ((ret < 0) && (errno == EINTR || errno == EAGAIN)) { + goto again; + } + + hw_error("pci write failed, ret = %zd errno = %d\n", ret, errno); + } +} + +static void assigned_dev_emulate_config_read(AssignedDevice *dev, + uint32_t offset, uint32_t len) +{ + memset(dev->emulate_config_read + offset, 0xff, len); +} + +static void assigned_dev_direct_config_read(AssignedDevice *dev, + uint32_t offset, uint32_t len) +{ + memset(dev->emulate_config_read + offset, 0, len); +} + +static void assigned_dev_direct_config_write(AssignedDevice *dev, + uint32_t offset, uint32_t len) +{ + memset(dev->emulate_config_write + offset, 0, len); +} + +static uint8_t pci_find_cap_offset(PCIDevice *d, uint8_t cap, uint8_t start) +{ + int id; + int max_cap = 48; + int pos = start ? start : PCI_CAPABILITY_LIST; + int status; + + status = assigned_dev_pci_read_byte(d, PCI_STATUS); + if ((status & PCI_STATUS_CAP_LIST) == 0) { + return 0; + } + + while (max_cap--) { + pos = assigned_dev_pci_read_byte(d, pos); + if (pos < 0x40) { + break; + } + + pos &= ~3; + id = assigned_dev_pci_read_byte(d, pos + PCI_CAP_LIST_ID); + + if (id == 0xff) { + break; + } + if (id == cap) { + return pos; + } + + pos += PCI_CAP_LIST_NEXT; + } + return 0; +} + +static int assigned_dev_register_regions(PCIRegion *io_regions, + unsigned long regions_num, + AssignedDevice *pci_dev) +{ + uint32_t i; + PCIRegion *cur_region = io_regions; + + for (i = 0; i < regions_num; i++, cur_region++) { + if (!cur_region->valid) { + continue; + } + + /* handle memory io regions */ + if (cur_region->type & IORESOURCE_MEM) { + int t = cur_region->type & IORESOURCE_PREFETCH + ? PCI_BASE_ADDRESS_MEM_PREFETCH + : PCI_BASE_ADDRESS_SPACE_MEMORY; + + /* map physical memory */ + pci_dev->v_addrs[i].u.r_virtbase = mmap(NULL, cur_region->size, + PROT_WRITE | PROT_READ, + MAP_SHARED, + cur_region->resource_fd, + (off_t)0); + + if (pci_dev->v_addrs[i].u.r_virtbase == MAP_FAILED) { + pci_dev->v_addrs[i].u.r_virtbase = NULL; + error_report("%s: Error: Couldn't mmap 0x%" PRIx64 "!", + __func__, cur_region->base_addr); + return -1; + } + + pci_dev->v_addrs[i].r_size = cur_region->size; + pci_dev->v_addrs[i].e_size = 0; + + /* add offset */ + pci_dev->v_addrs[i].u.r_virtbase += + (cur_region->base_addr & 0xFFF); + + if (cur_region->size & 0xFFF) { + error_report("PCI region %d at address 0x%" PRIx64 " has " + "size 0x%" PRIx64 ", which is not a multiple of " + "4K. You might experience some performance hit " + "due to that.", + i, cur_region->base_addr, cur_region->size); + memory_region_init_io(&pci_dev->v_addrs[i].real_iomem, + &slow_bar_ops, &pci_dev->v_addrs[i], + "assigned-dev-slow-bar", + cur_region->size); + } else { + void *virtbase = pci_dev->v_addrs[i].u.r_virtbase; + char name[32]; + snprintf(name, sizeof(name), "%s.bar%d", + object_get_typename(OBJECT(pci_dev)), i); + memory_region_init_ram_ptr(&pci_dev->v_addrs[i].real_iomem, + name, cur_region->size, + virtbase); + vmstate_register_ram(&pci_dev->v_addrs[i].real_iomem, + &pci_dev->dev.qdev); + } + + assigned_dev_iomem_setup(&pci_dev->dev, i, cur_region->size); + pci_register_bar((PCIDevice *) pci_dev, i, t, + &pci_dev->v_addrs[i].container); + continue; + } else { + /* handle port io regions */ + uint32_t val; + int ret; + + /* Test kernel support for ioport resource read/write. Old + * kernels return EIO. New kernels only allow 1/2/4 byte reads + * so should return EINVAL for a 3 byte read */ + ret = pread(pci_dev->v_addrs[i].region->resource_fd, &val, 3, 0); + if (ret >= 0) { + error_report("Unexpected return from I/O port read: %d", ret); + abort(); + } else if (errno != EINVAL) { + error_report("Kernel doesn't support ioport resource " + "access, hiding this region."); + close(pci_dev->v_addrs[i].region->resource_fd); + cur_region->valid = 0; + continue; + } + + pci_dev->v_addrs[i].u.r_baseport = cur_region->base_addr; + pci_dev->v_addrs[i].r_size = cur_region->size; + pci_dev->v_addrs[i].e_size = 0; + + assigned_dev_ioport_setup(&pci_dev->dev, i, cur_region->size); + pci_register_bar((PCIDevice *) pci_dev, i, + PCI_BASE_ADDRESS_SPACE_IO, + &pci_dev->v_addrs[i].container); + } + } + + /* success */ + return 0; +} + +static int get_real_id(const char *devpath, const char *idname, uint16_t *val) +{ + FILE *f; + char name[128]; + long id; + + snprintf(name, sizeof(name), "%s%s", devpath, idname); + f = fopen(name, "r"); + if (f == NULL) { + error_report("%s: %s: %m", __func__, name); + return -1; + } + if (fscanf(f, "%li\n", &id) == 1) { + *val = id; + } else { + return -1; + } + fclose(f); + + return 0; +} + +static int get_real_vendor_id(const char *devpath, uint16_t *val) +{ + return get_real_id(devpath, "vendor", val); +} + +static int get_real_device_id(const char *devpath, uint16_t *val) +{ + return get_real_id(devpath, "device", val); +} + +static int get_real_device(AssignedDevice *pci_dev, uint16_t r_seg, + uint8_t r_bus, uint8_t r_dev, uint8_t r_func) +{ + char dir[128], name[128]; + int fd, r = 0, v; + FILE *f; + uint64_t start, end, size, flags; + uint16_t id; + PCIRegion *rp; + PCIDevRegions *dev = &pci_dev->real_device; + + dev->region_number = 0; + + snprintf(dir, sizeof(dir), "/sys/bus/pci/devices/%04x:%02x:%02x.%x/", + r_seg, r_bus, r_dev, r_func); + + snprintf(name, sizeof(name), "%sconfig", dir); + + if (pci_dev->configfd_name && *pci_dev->configfd_name) { + if (qemu_isdigit(pci_dev->configfd_name[0])) { + dev->config_fd = strtol(pci_dev->configfd_name, NULL, 0); + } else { + dev->config_fd = monitor_get_fd(cur_mon, pci_dev->configfd_name); + if (dev->config_fd < 0) { + error_report("%s: (%s) unkown", __func__, + pci_dev->configfd_name); + return 1; + } + } + } else { + dev->config_fd = open(name, O_RDWR); + + if (dev->config_fd == -1) { + error_report("%s: %s: %m", __func__, name); + return 1; + } + } +again: + r = read(dev->config_fd, pci_dev->dev.config, + pci_config_size(&pci_dev->dev)); + if (r < 0) { + if (errno == EINTR || errno == EAGAIN) { + goto again; + } + error_report("%s: read failed, errno = %d", __func__, errno); + } + + /* Restore or clear multifunction, this is always controlled by qemu */ + if (pci_dev->dev.cap_present & QEMU_PCI_CAP_MULTIFUNCTION) { + pci_dev->dev.config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION; + } else { + pci_dev->dev.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 + * confusing, unwritable, residual addresses from the host here. */ + memset(&pci_dev->dev.config[PCI_BASE_ADDRESS_0], 0, 24); + memset(&pci_dev->dev.config[PCI_ROM_ADDRESS], 0, 4); + + snprintf(name, sizeof(name), "%sresource", dir); + + f = fopen(name, "r"); + if (f == NULL) { + error_report("%s: %s: %m", __func__, name); + return 1; + } + + for (r = 0; r < PCI_ROM_SLOT; r++) { + if (fscanf(f, "%" SCNi64 " %" SCNi64 " %" SCNi64 "\n", + &start, &end, &flags) != 3) { + break; + } + + rp = dev->regions + r; + rp->valid = 0; + rp->resource_fd = -1; + size = end - start + 1; + flags &= IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH; + if (size == 0 || (flags & ~IORESOURCE_PREFETCH) == 0) { + continue; + } + if (flags & IORESOURCE_MEM) { + flags &= ~IORESOURCE_IO; + } else { + flags &= ~IORESOURCE_PREFETCH; + } + snprintf(name, sizeof(name), "%sresource%d", dir, r); + fd = open(name, O_RDWR); + if (fd == -1) { + continue; + } + rp->resource_fd = fd; + + rp->type = flags; + rp->valid = 1; + rp->base_addr = start; + rp->size = size; + pci_dev->v_addrs[r].region = rp; + DEBUG("region %d size %" PRIu64 " start 0x%" PRIx64 + " type %d resource_fd %d\n", + r, rp->size, start, rp->type, rp->resource_fd); + } + + fclose(f); + + /* read and fill vendor ID */ + v = get_real_vendor_id(dir, &id); + if (v) { + return 1; + } + pci_dev->dev.config[0] = id & 0xff; + pci_dev->dev.config[1] = (id & 0xff00) >> 8; + + /* read and fill device ID */ + v = get_real_device_id(dir, &id); + if (v) { + return 1; + } + pci_dev->dev.config[2] = id & 0xff; + pci_dev->dev.config[3] = (id & 0xff00) >> 8; + + pci_word_test_and_clear_mask(pci_dev->emulate_config_write + PCI_COMMAND, + PCI_COMMAND_MASTER | PCI_COMMAND_INTX_DISABLE); + + dev->region_number = r; + return 0; +} + +static void free_msi_virqs(AssignedDevice *dev) +{ + int i; + + for (i = 0; i < dev->msi_virq_nr; i++) { + if (dev->msi_virq[i] >= 0) { + kvm_irqchip_release_virq(kvm_state, dev->msi_virq[i]); + dev->msi_virq[i] = -1; + } + } + g_free(dev->msi_virq); + dev->msi_virq = NULL; + dev->msi_virq_nr = 0; +} + +static void free_assigned_device(AssignedDevice *dev) +{ + int i; + + if (dev->cap.available & ASSIGNED_DEVICE_CAP_MSIX) { + assigned_dev_unregister_msix_mmio(dev); + } + for (i = 0; i < dev->real_device.region_number; i++) { + PCIRegion *pci_region = &dev->real_device.regions[i]; + AssignedDevRegion *region = &dev->v_addrs[i]; + + if (!pci_region->valid) { + continue; + } + if (pci_region->type & IORESOURCE_IO) { + if (region->u.r_baseport) { + memory_region_del_subregion(®ion->container, + ®ion->real_iomem); + memory_region_destroy(®ion->real_iomem); + memory_region_destroy(®ion->container); + } + } else if (pci_region->type & IORESOURCE_MEM) { + if (region->u.r_virtbase) { + memory_region_del_subregion(®ion->container, + ®ion->real_iomem); + + /* Remove MSI-X table subregion */ + if (pci_region->base_addr <= dev->msix_table_addr && + pci_region->base_addr + pci_region->size > + dev->msix_table_addr) { + memory_region_del_subregion(®ion->container, + &dev->mmio); + } + + memory_region_destroy(®ion->real_iomem); + memory_region_destroy(®ion->container); + if (munmap(region->u.r_virtbase, + (pci_region->size + 0xFFF) & 0xFFFFF000)) { + error_report("Failed to unmap assigned device region: %s", + strerror(errno)); + } + } + } + if (pci_region->resource_fd >= 0) { + close(pci_region->resource_fd); + } + } + + if (dev->real_device.config_fd >= 0) { + close(dev->real_device.config_fd); + } + + free_msi_virqs(dev); +} + +static void assign_failed_examine(AssignedDevice *dev) +{ + char name[PATH_MAX], dir[PATH_MAX], driver[PATH_MAX] = {}, *ns; + uint16_t vendor_id, device_id; + int r; + + snprintf(dir, sizeof(dir), "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/", + dev->host.domain, dev->host.bus, dev->host.slot, + dev->host.function); + + snprintf(name, sizeof(name), "%sdriver", dir); + + r = readlink(name, driver, sizeof(driver)); + if ((r <= 0) || r >= sizeof(driver)) { + goto fail; + } + + ns = strrchr(driver, '/'); + if (!ns) { + goto fail; + } + + ns++; + + if (get_real_vendor_id(dir, &vendor_id) || + get_real_device_id(dir, &device_id)) { + goto fail; + } + + error_report("*** The driver '%s' is occupying your device " + "%04x:%02x:%02x.%x.", + ns, dev->host.domain, dev->host.bus, dev->host.slot, + dev->host.function); + error_report("***"); + error_report("*** You can try the following commands to free it:"); + error_report("***"); + error_report("*** $ echo \"%04x %04x\" > /sys/bus/pci/drivers/pci-stub/" + "new_id", vendor_id, device_id); + error_report("*** $ echo \"%04x:%02x:%02x.%x\" > /sys/bus/pci/drivers/" + "%s/unbind", + dev->host.domain, dev->host.bus, dev->host.slot, + dev->host.function, ns); + error_report("*** $ echo \"%04x:%02x:%02x.%x\" > /sys/bus/pci/drivers/" + "pci-stub/bind", + dev->host.domain, dev->host.bus, dev->host.slot, + dev->host.function); + error_report("*** $ echo \"%04x %04x\" > /sys/bus/pci/drivers/pci-stub" + "/remove_id", vendor_id, device_id); + error_report("***"); + + return; + +fail: + error_report("Couldn't find out why."); +} + +static int assign_device(AssignedDevice *dev) +{ + uint32_t flags = KVM_DEV_ASSIGN_ENABLE_IOMMU; + int r; + + /* Only pass non-zero PCI segment to capable module */ + if (!kvm_check_extension(kvm_state, KVM_CAP_PCI_SEGMENT) && + dev->host.domain) { + error_report("Can't assign device inside non-zero PCI segment " + "as this KVM module doesn't support it."); + return -ENODEV; + } + + if (!kvm_check_extension(kvm_state, KVM_CAP_IOMMU)) { + error_report("No IOMMU found. Unable to assign device \"%s\"", + dev->dev.qdev.id); + return -ENODEV; + } + + if (dev->features & ASSIGNED_DEVICE_SHARE_INTX_MASK && + kvm_has_intx_set_mask()) { + flags |= KVM_DEV_ASSIGN_PCI_2_3; + } + + r = kvm_device_pci_assign(kvm_state, &dev->host, flags, &dev->dev_id); + if (r < 0) { + error_report("Failed to assign device \"%s\" : %s", + dev->dev.qdev.id, strerror(-r)); + + switch (r) { + case -EBUSY: + assign_failed_examine(dev); + break; + default: + break; + } + } + return r; +} + +static bool check_irqchip_in_kernel(void) +{ + if (kvm_irqchip_in_kernel()) { + return true; + } + error_report("pci-assign: error: requires KVM with in-kernel irqchip " + "enabled"); + return false; +} + +static int assign_intx(AssignedDevice *dev) +{ + AssignedIRQType new_type; + PCIINTxRoute intx_route; + bool intx_host_msi; + int r; + + /* Interrupt PIN 0 means don't use INTx */ + if (assigned_dev_pci_read_byte(&dev->dev, PCI_INTERRUPT_PIN) == 0) { + pci_device_set_intx_routing_notifier(&dev->dev, NULL); + return 0; + } + + if (!check_irqchip_in_kernel()) { + return -ENOTSUP; + } + + pci_device_set_intx_routing_notifier(&dev->dev, + assigned_dev_update_irq_routing); + + intx_route = pci_device_route_intx_to_irq(&dev->dev, dev->intpin); + assert(intx_route.mode != PCI_INTX_INVERTED); + + if (dev->intx_route.mode == intx_route.mode && + dev->intx_route.irq == intx_route.irq) { + return 0; + } + + switch (dev->assigned_irq_type) { + case ASSIGNED_IRQ_INTX_HOST_INTX: + case ASSIGNED_IRQ_INTX_HOST_MSI: + intx_host_msi = dev->assigned_irq_type == ASSIGNED_IRQ_INTX_HOST_MSI; + r = kvm_device_intx_deassign(kvm_state, dev->dev_id, intx_host_msi); + break; + case ASSIGNED_IRQ_MSI: + r = kvm_device_msi_deassign(kvm_state, dev->dev_id); + break; + case ASSIGNED_IRQ_MSIX: + r = kvm_device_msix_deassign(kvm_state, dev->dev_id); + break; + default: + r = 0; + break; + } + if (r) { + perror("assign_intx: deassignment of previous interrupt failed"); + } + dev->assigned_irq_type = ASSIGNED_IRQ_NONE; + + if (intx_route.mode == PCI_INTX_DISABLED) { + dev->intx_route = intx_route; + return 0; + } + +retry: + if (dev->features & ASSIGNED_DEVICE_PREFER_MSI_MASK && + dev->cap.available & ASSIGNED_DEVICE_CAP_MSI) { + intx_host_msi = true; + new_type = ASSIGNED_IRQ_INTX_HOST_MSI; + } else { + intx_host_msi = false; + new_type = ASSIGNED_IRQ_INTX_HOST_INTX; + } + + r = kvm_device_intx_assign(kvm_state, dev->dev_id, intx_host_msi, + intx_route.irq); + if (r < 0) { + if (r == -EIO && !(dev->features & ASSIGNED_DEVICE_PREFER_MSI_MASK) && + dev->cap.available & ASSIGNED_DEVICE_CAP_MSI) { + /* Retry with host-side MSI. There might be an IRQ conflict and + * either the kernel or the device doesn't support sharing. */ + error_report("Host-side INTx sharing not supported, " + "using MSI instead.\n" + "Some devices do not to work properly in this mode."); + dev->features |= ASSIGNED_DEVICE_PREFER_MSI_MASK; + goto retry; + } + error_report("Failed to assign irq for \"%s\": %s", + dev->dev.qdev.id, strerror(-r)); + error_report("Perhaps you are assigning a device " + "that shares an IRQ with another device?"); + return r; + } + + dev->intx_route = intx_route; + dev->assigned_irq_type = new_type; + return r; +} + +static void deassign_device(AssignedDevice *dev) +{ + int r; + + r = kvm_device_pci_deassign(kvm_state, dev->dev_id); + assert(r == 0); +} + +/* The pci config space got updated. Check if irq numbers have changed + * for our devices + */ +static void assigned_dev_update_irq_routing(PCIDevice *dev) +{ + AssignedDevice *assigned_dev = DO_UPCAST(AssignedDevice, dev, dev); + Error *err = NULL; + int r; + + r = assign_intx(assigned_dev); + if (r < 0) { + qdev_unplug(&dev->qdev, &err); + assert(!err); + } +} + +static void assigned_dev_update_msi(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); + int r; + + /* Some guests gratuitously disable MSI even if they're not using it, + * try to catch this by only deassigning irqs if the guest is using + * MSI or intends to start. */ + if (assigned_dev->assigned_irq_type == ASSIGNED_IRQ_MSI || + (ctrl_byte & PCI_MSI_FLAGS_ENABLE)) { + r = kvm_device_msi_deassign(kvm_state, assigned_dev->dev_id); + /* -ENXIO means no assigned irq */ + if (r && r != -ENXIO) { + perror("assigned_dev_update_msi: deassign irq"); + } + + free_msi_virqs(assigned_dev); + + assigned_dev->assigned_irq_type = ASSIGNED_IRQ_NONE; + pci_device_set_intx_routing_notifier(pci_dev, NULL); + } + + if (ctrl_byte & PCI_MSI_FLAGS_ENABLE) { + uint8_t *pos = pci_dev->config + pci_dev->msi_cap; + MSIMessage msg; + int virq; + + msg.address = pci_get_long(pos + PCI_MSI_ADDRESS_LO); + msg.data = pci_get_word(pos + PCI_MSI_DATA_32); + virq = kvm_irqchip_add_msi_route(kvm_state, msg); + if (virq < 0) { + perror("assigned_dev_update_msi: kvm_irqchip_add_msi_route"); + return; + } + + assigned_dev->msi_virq = g_malloc(sizeof(*assigned_dev->msi_virq)); + assigned_dev->msi_virq_nr = 1; + assigned_dev->msi_virq[0] = virq; + if (kvm_device_msi_assign(kvm_state, assigned_dev->dev_id, virq) < 0) { + perror("assigned_dev_update_msi: kvm_device_msi_assign"); + } + + assigned_dev->intx_route.mode = PCI_INTX_DISABLED; + assigned_dev->intx_route.irq = -1; + assigned_dev->assigned_irq_type = ASSIGNED_IRQ_MSI; + } else { + assign_intx(assigned_dev); + } +} + +static bool assigned_dev_msix_masked(MSIXTableEntry *entry) +{ + return (entry->ctrl & cpu_to_le32(0x1)) != 0; +} + +static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev) +{ + AssignedDevice *adev = DO_UPCAST(AssignedDevice, dev, pci_dev); + uint16_t entries_nr = 0; + int i, r = 0; + MSIXTableEntry *entry = adev->msix_table; + MSIMessage msg; + + /* Get the usable entry number for allocating */ + for (i = 0; i < adev->msix_max; i++, entry++) { + if (assigned_dev_msix_masked(entry)) { + continue; + } + entries_nr++; + } + + DEBUG("MSI-X entries: %d\n", entries_nr); + + /* It's valid to enable MSI-X with all entries masked */ + if (!entries_nr) { + return 0; + } + + r = kvm_device_msix_init_vectors(kvm_state, adev->dev_id, entries_nr); + if (r != 0) { + error_report("fail to set MSI-X entry number for MSIX! %s", + strerror(-r)); + return r; + } + + free_msi_virqs(adev); + + adev->msi_virq_nr = adev->msix_max; + adev->msi_virq = g_malloc(adev->msix_max * sizeof(*adev->msi_virq)); + + entry = adev->msix_table; + for (i = 0; i < adev->msix_max; i++, entry++) { + adev->msi_virq[i] = -1; + + if (assigned_dev_msix_masked(entry)) { + continue; + } + + msg.address = entry->addr_lo | ((uint64_t)entry->addr_hi << 32); + msg.data = entry->data; + r = kvm_irqchip_add_msi_route(kvm_state, msg); + if (r < 0) { + return r; + } + adev->msi_virq[i] = r; + + DEBUG("MSI-X vector %d, gsi %d, addr %08x_%08x, data %08x\n", i, + r, entry->addr_hi, entry->addr_lo, entry->data); + + r = kvm_device_msix_set_vector(kvm_state, adev->dev_id, i, + adev->msi_virq[i]); + if (r) { + error_report("fail to set MSI-X entry! %s", strerror(-r)); + break; + } + } + + return r; +} + +static void assigned_dev_update_msix(PCIDevice *pci_dev) +{ + AssignedDevice *assigned_dev = DO_UPCAST(AssignedDevice, dev, pci_dev); + uint16_t ctrl_word = pci_get_word(pci_dev->config + pci_dev->msix_cap + + PCI_MSIX_FLAGS); + int r; + + /* Some guests gratuitously disable MSIX even if they're not using it, + * try to catch this by only deassigning irqs if the guest is using + * MSIX or intends to start. */ + if ((assigned_dev->assigned_irq_type == ASSIGNED_IRQ_MSIX) || + (ctrl_word & PCI_MSIX_FLAGS_ENABLE)) { + r = kvm_device_msix_deassign(kvm_state, assigned_dev->dev_id); + /* -ENXIO means no assigned irq */ + if (r && r != -ENXIO) { + perror("assigned_dev_update_msix: deassign irq"); + } + + free_msi_virqs(assigned_dev); + + assigned_dev->assigned_irq_type = ASSIGNED_IRQ_NONE; + pci_device_set_intx_routing_notifier(pci_dev, NULL); + } + + if (ctrl_word & PCI_MSIX_FLAGS_ENABLE) { + if (assigned_dev_update_msix_mmio(pci_dev) < 0) { + perror("assigned_dev_update_msix_mmio"); + return; + } + + if (assigned_dev->msi_virq_nr > 0) { + if (kvm_device_msix_assign(kvm_state, assigned_dev->dev_id) < 0) { + perror("assigned_dev_enable_msix: assign irq"); + return; + } + } + assigned_dev->intx_route.mode = PCI_INTX_DISABLED; + assigned_dev->intx_route.irq = -1; + assigned_dev->assigned_irq_type = ASSIGNED_IRQ_MSIX; + } else { + assign_intx(assigned_dev); + } +} + +static uint32_t assigned_dev_pci_read_config(PCIDevice *pci_dev, + uint32_t address, int len) +{ + AssignedDevice *assigned_dev = DO_UPCAST(AssignedDevice, dev, pci_dev); + uint32_t virt_val = pci_default_read_config(pci_dev, address, len); + uint32_t real_val, emulate_mask, full_emulation_mask; + + emulate_mask = 0; + memcpy(&emulate_mask, assigned_dev->emulate_config_read + address, len); + emulate_mask = le32_to_cpu(emulate_mask); + + full_emulation_mask = 0xffffffff >> (32 - len * 8); + + if (emulate_mask != full_emulation_mask) { + real_val = assigned_dev_pci_read(pci_dev, address, len); + return (virt_val & emulate_mask) | (real_val & ~emulate_mask); + } else { + return virt_val; + } +} + +static void assigned_dev_pci_write_config(PCIDevice *pci_dev, uint32_t address, + uint32_t val, int len) +{ + AssignedDevice *assigned_dev = DO_UPCAST(AssignedDevice, dev, pci_dev); + uint16_t old_cmd = pci_get_word(pci_dev->config + PCI_COMMAND); + uint32_t emulate_mask, full_emulation_mask; + int ret; + + pci_default_write_config(pci_dev, address, val, len); + + if (kvm_has_intx_set_mask() && + range_covers_byte(address, len, PCI_COMMAND + 1)) { + bool intx_masked = (pci_get_word(pci_dev->config + PCI_COMMAND) & + PCI_COMMAND_INTX_DISABLE); + + if (intx_masked != !!(old_cmd & PCI_COMMAND_INTX_DISABLE)) { + ret = kvm_device_intx_set_mask(kvm_state, assigned_dev->dev_id, + intx_masked); + if (ret) { + perror("assigned_dev_pci_write_config: set intx mask"); + } + } + } + if (assigned_dev->cap.available & ASSIGNED_DEVICE_CAP_MSI) { + if (range_covers_byte(address, len, + pci_dev->msi_cap + PCI_MSI_FLAGS)) { + assigned_dev_update_msi(pci_dev); + } + } + if (assigned_dev->cap.available & ASSIGNED_DEVICE_CAP_MSIX) { + if (range_covers_byte(address, len, + pci_dev->msix_cap + PCI_MSIX_FLAGS + 1)) { + assigned_dev_update_msix(pci_dev); + } + } + + emulate_mask = 0; + memcpy(&emulate_mask, assigned_dev->emulate_config_write + address, len); + emulate_mask = le32_to_cpu(emulate_mask); + + full_emulation_mask = 0xffffffff >> (32 - len * 8); + + if (emulate_mask != full_emulation_mask) { + if (emulate_mask) { + val &= ~emulate_mask; + val |= assigned_dev_pci_read(pci_dev, address, len) & emulate_mask; + } + assigned_dev_pci_write(pci_dev, address, val, len); + } +} + +static void assigned_dev_setup_cap_read(AssignedDevice *dev, uint32_t offset, + uint32_t len) +{ + assigned_dev_direct_config_read(dev, offset, len); + assigned_dev_emulate_config_read(dev, offset + PCI_CAP_LIST_NEXT, 1); +} + +static int assigned_device_pci_cap_init(PCIDevice *pci_dev) +{ + AssignedDevice *dev = DO_UPCAST(AssignedDevice, dev, pci_dev); + PCIRegion *pci_region = dev->real_device.regions; + int ret, pos; + + /* Clear initial capabilities pointer and status copied from hw */ + pci_set_byte(pci_dev->config + PCI_CAPABILITY_LIST, 0); + pci_set_word(pci_dev->config + PCI_STATUS, + pci_get_word(pci_dev->config + PCI_STATUS) & + ~PCI_STATUS_CAP_LIST); + + /* Expose MSI capability + * MSI capability is the 1st capability in capability config */ + pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_MSI, 0); + if (pos != 0 && kvm_check_extension(kvm_state, KVM_CAP_ASSIGN_DEV_IRQ)) { + if (!check_irqchip_in_kernel()) { + return -ENOTSUP; + } + dev->cap.available |= ASSIGNED_DEVICE_CAP_MSI; + /* Only 32-bit/no-mask currently supported */ + ret = pci_add_capability(pci_dev, PCI_CAP_ID_MSI, pos, 10); + if (ret < 0) { + return ret; + } + pci_dev->msi_cap = pos; + + pci_set_word(pci_dev->config + pos + PCI_MSI_FLAGS, + pci_get_word(pci_dev->config + pos + PCI_MSI_FLAGS) & + PCI_MSI_FLAGS_QMASK); + pci_set_long(pci_dev->config + pos + PCI_MSI_ADDRESS_LO, 0); + pci_set_word(pci_dev->config + pos + PCI_MSI_DATA_32, 0); + + /* Set writable fields */ + pci_set_word(pci_dev->wmask + pos + PCI_MSI_FLAGS, + PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE); + pci_set_long(pci_dev->wmask + pos + PCI_MSI_ADDRESS_LO, 0xfffffffc); + pci_set_word(pci_dev->wmask + pos + PCI_MSI_DATA_32, 0xffff); + } + /* Expose MSI-X capability */ + pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_MSIX, 0); + if (pos != 0 && kvm_device_msix_supported(kvm_state)) { + int bar_nr; + uint32_t msix_table_entry; + + if (!check_irqchip_in_kernel()) { + return -ENOTSUP; + } + dev->cap.available |= ASSIGNED_DEVICE_CAP_MSIX; + ret = pci_add_capability(pci_dev, PCI_CAP_ID_MSIX, pos, 12); + if (ret < 0) { + return ret; + } + pci_dev->msix_cap = pos; + + pci_set_word(pci_dev->config + pos + PCI_MSIX_FLAGS, + pci_get_word(pci_dev->config + pos + PCI_MSIX_FLAGS) & + PCI_MSIX_FLAGS_QSIZE); + + /* Only enable and function mask bits are writable */ + pci_set_word(pci_dev->wmask + pos + PCI_MSIX_FLAGS, + PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL); + + msix_table_entry = pci_get_long(pci_dev->config + pos + PCI_MSIX_TABLE); + bar_nr = msix_table_entry & PCI_MSIX_FLAGS_BIRMASK; + msix_table_entry &= ~PCI_MSIX_FLAGS_BIRMASK; + dev->msix_table_addr = pci_region[bar_nr].base_addr + msix_table_entry; + dev->msix_max = pci_get_word(pci_dev->config + pos + PCI_MSIX_FLAGS); + dev->msix_max &= PCI_MSIX_FLAGS_QSIZE; + dev->msix_max += 1; + } + + /* Minimal PM support, nothing writable, device appears to NAK changes */ + pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_PM, 0); + if (pos) { + uint16_t pmc; + + ret = pci_add_capability(pci_dev, PCI_CAP_ID_PM, pos, PCI_PM_SIZEOF); + if (ret < 0) { + return ret; + } + + assigned_dev_setup_cap_read(dev, pos, PCI_PM_SIZEOF); + + pmc = pci_get_word(pci_dev->config + pos + PCI_CAP_FLAGS); + pmc &= (PCI_PM_CAP_VER_MASK | PCI_PM_CAP_DSI); + pci_set_word(pci_dev->config + pos + PCI_CAP_FLAGS, pmc); + + /* assign_device will bring the device up to D0, so we don't need + * to worry about doing that ourselves here. */ + pci_set_word(pci_dev->config + pos + PCI_PM_CTRL, + PCI_PM_CTRL_NO_SOFT_RESET); + + pci_set_byte(pci_dev->config + pos + PCI_PM_PPB_EXTENSIONS, 0); + pci_set_byte(pci_dev->config + pos + PCI_PM_DATA_REGISTER, 0); + } + + pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_EXP, 0); + if (pos) { + uint8_t version, size = 0; + uint16_t type, devctl, lnksta; + uint32_t devcap, lnkcap; + + version = pci_get_byte(pci_dev->config + pos + PCI_EXP_FLAGS); + version &= PCI_EXP_FLAGS_VERS; + if (version == 1) { + size = 0x14; + } else if (version == 2) { + /* + * Check for non-std size, accept reduced size to 0x34, + * which is what bcm5761 implemented, violating the + * PCIe v3.0 spec that regs should exist and be read as 0, + * not optionally provided and shorten the struct size. + */ + size = MIN(0x3c, PCI_CONFIG_SPACE_SIZE - pos); + if (size < 0x34) { + error_report("%s: Invalid size PCIe cap-id 0x%x", + __func__, PCI_CAP_ID_EXP); + return -EINVAL; + } else if (size != 0x3c) { + error_report("WARNING, %s: PCIe cap-id 0x%x has " + "non-standard size 0x%x; std size should be 0x3c", + __func__, PCI_CAP_ID_EXP, size); + } + } else if (version == 0) { + uint16_t vid, did; + vid = pci_get_word(pci_dev->config + PCI_VENDOR_ID); + did = pci_get_word(pci_dev->config + PCI_DEVICE_ID); + if (vid == PCI_VENDOR_ID_INTEL && did == 0x10ed) { + /* + * quirk for Intel 82599 VF with invalid PCIe capability + * version, should really be version 2 (same as PF) + */ + size = 0x3c; + } + } + + if (size == 0) { + error_report("%s: Unsupported PCI express capability version %d", + __func__, version); + return -EINVAL; + } + + ret = pci_add_capability(pci_dev, PCI_CAP_ID_EXP, pos, size); + if (ret < 0) { + return ret; + } + + assigned_dev_setup_cap_read(dev, pos, size); + + type = pci_get_word(pci_dev->config + pos + PCI_EXP_FLAGS); + type = (type & PCI_EXP_FLAGS_TYPE) >> 4; + if (type != PCI_EXP_TYPE_ENDPOINT && + type != PCI_EXP_TYPE_LEG_END && type != PCI_EXP_TYPE_RC_END) { + error_report("Device assignment only supports endpoint assignment," + " device type %d", type); + return -EINVAL; + } + + /* capabilities, pass existing read-only copy + * PCI_EXP_FLAGS_IRQ: updated by hardware, should be direct read */ + + /* device capabilities: hide FLR */ + devcap = pci_get_long(pci_dev->config + pos + PCI_EXP_DEVCAP); + devcap &= ~PCI_EXP_DEVCAP_FLR; + pci_set_long(pci_dev->config + pos + PCI_EXP_DEVCAP, devcap); + + /* device control: clear all error reporting enable bits, leaving + * only a few host values. Note, these are + * all writable, but not passed to hw. + */ + devctl = pci_get_word(pci_dev->config + pos + PCI_EXP_DEVCTL); + devctl = (devctl & (PCI_EXP_DEVCTL_READRQ | PCI_EXP_DEVCTL_PAYLOAD)) | + PCI_EXP_DEVCTL_RELAX_EN | PCI_EXP_DEVCTL_NOSNOOP_EN; + pci_set_word(pci_dev->config + pos + PCI_EXP_DEVCTL, devctl); + devctl = PCI_EXP_DEVCTL_BCR_FLR | PCI_EXP_DEVCTL_AUX_PME; + pci_set_word(pci_dev->wmask + pos + PCI_EXP_DEVCTL, ~devctl); + + /* Clear device status */ + pci_set_word(pci_dev->config + pos + PCI_EXP_DEVSTA, 0); + + /* Link capabilities, expose links and latencues, clear reporting */ + lnkcap = pci_get_long(pci_dev->config + pos + PCI_EXP_LNKCAP); + lnkcap &= (PCI_EXP_LNKCAP_SLS | PCI_EXP_LNKCAP_MLW | + PCI_EXP_LNKCAP_ASPMS | PCI_EXP_LNKCAP_L0SEL | + PCI_EXP_LNKCAP_L1EL); + pci_set_long(pci_dev->config + pos + PCI_EXP_LNKCAP, lnkcap); + + /* Link control, pass existing read-only copy. Should be writable? */ + + /* Link status, only expose current speed and width */ + lnksta = pci_get_word(pci_dev->config + pos + PCI_EXP_LNKSTA); + lnksta &= (PCI_EXP_LNKSTA_CLS | PCI_EXP_LNKSTA_NLW); + pci_set_word(pci_dev->config + pos + PCI_EXP_LNKSTA, lnksta); + + if (version >= 2) { + /* Slot capabilities, control, status - not needed for endpoints */ + pci_set_long(pci_dev->config + pos + PCI_EXP_SLTCAP, 0); + pci_set_word(pci_dev->config + pos + PCI_EXP_SLTCTL, 0); + pci_set_word(pci_dev->config + pos + PCI_EXP_SLTSTA, 0); + + /* Root control, capabilities, status - not needed for endpoints */ + pci_set_word(pci_dev->config + pos + PCI_EXP_RTCTL, 0); + pci_set_word(pci_dev->config + pos + PCI_EXP_RTCAP, 0); + pci_set_long(pci_dev->config + pos + PCI_EXP_RTSTA, 0); + + /* Device capabilities/control 2, pass existing read-only copy */ + /* Link control 2, pass existing read-only copy */ + } + } + + pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_PCIX, 0); + if (pos) { + uint16_t cmd; + uint32_t status; + + /* Only expose the minimum, 8 byte capability */ + ret = pci_add_capability(pci_dev, PCI_CAP_ID_PCIX, pos, 8); + if (ret < 0) { + return ret; + } + + assigned_dev_setup_cap_read(dev, pos, 8); + + /* Command register, clear upper bits, including extended modes */ + cmd = pci_get_word(pci_dev->config + pos + PCI_X_CMD); + cmd &= (PCI_X_CMD_DPERR_E | PCI_X_CMD_ERO | PCI_X_CMD_MAX_READ | + PCI_X_CMD_MAX_SPLIT); + pci_set_word(pci_dev->config + pos + PCI_X_CMD, cmd); + + /* Status register, update with emulated PCI bus location, clear + * error bits, leave the rest. */ + status = pci_get_long(pci_dev->config + pos + PCI_X_STATUS); + status &= ~(PCI_X_STATUS_BUS | PCI_X_STATUS_DEVFN); + status |= (pci_bus_num(pci_dev->bus) << 8) | pci_dev->devfn; + status &= ~(PCI_X_STATUS_SPL_DISC | PCI_X_STATUS_UNX_SPL | + PCI_X_STATUS_SPL_ERR); + pci_set_long(pci_dev->config + pos + PCI_X_STATUS, status); + } + + pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_VPD, 0); + if (pos) { + /* Direct R/W passthrough */ + ret = pci_add_capability(pci_dev, PCI_CAP_ID_VPD, pos, 8); + if (ret < 0) { + return ret; + } + + assigned_dev_setup_cap_read(dev, pos, 8); + + /* direct write for cap content */ + assigned_dev_direct_config_write(dev, pos + 2, 6); + } + + /* Devices can have multiple vendor capabilities, get them all */ + for (pos = 0; (pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_VNDR, pos)); + pos += PCI_CAP_LIST_NEXT) { + uint8_t len = pci_get_byte(pci_dev->config + pos + PCI_CAP_FLAGS); + /* Direct R/W passthrough */ + ret = pci_add_capability(pci_dev, PCI_CAP_ID_VNDR, pos, len); + if (ret < 0) { + return ret; + } + + assigned_dev_setup_cap_read(dev, pos, len); + + /* direct write for cap content */ + assigned_dev_direct_config_write(dev, pos + 2, len - 2); + } + + /* If real and virtual capability list status bits differ, virtualize the + * access. */ + if ((pci_get_word(pci_dev->config + PCI_STATUS) & PCI_STATUS_CAP_LIST) != + (assigned_dev_pci_read_byte(pci_dev, PCI_STATUS) & + PCI_STATUS_CAP_LIST)) { + dev->emulate_config_read[PCI_STATUS] |= PCI_STATUS_CAP_LIST; + } + + return 0; +} + +static uint64_t +assigned_dev_msix_mmio_read(void *opaque, target_phys_addr_t addr, + unsigned size) +{ + AssignedDevice *adev = opaque; + uint64_t val; + + memcpy(&val, (void *)((uint8_t *)adev->msix_table + addr), size); + + return val; +} + +static void assigned_dev_msix_mmio_write(void *opaque, target_phys_addr_t addr, + uint64_t val, unsigned size) +{ + AssignedDevice *adev = opaque; + PCIDevice *pdev = &adev->dev; + uint16_t ctrl; + MSIXTableEntry orig; + int i = addr >> 4; + + if (i >= adev->msix_max) { + return; /* Drop write */ + } + + ctrl = pci_get_word(pdev->config + pdev->msix_cap + PCI_MSIX_FLAGS); + + DEBUG("write to MSI-X table offset 0x%lx, val 0x%lx\n", addr, val); + + if (ctrl & PCI_MSIX_FLAGS_ENABLE) { + orig = adev->msix_table[i]; + } + + memcpy((uint8_t *)adev->msix_table + addr, &val, size); + + if (ctrl & PCI_MSIX_FLAGS_ENABLE) { + MSIXTableEntry *entry = &adev->msix_table[i]; + + if (!assigned_dev_msix_masked(&orig) && + assigned_dev_msix_masked(entry)) { + /* + * Vector masked, disable it + * + * XXX It's not clear if we can or should actually attempt + * to mask or disable the interrupt. KVM doesn't have + * support for pending bits and kvm_assign_set_msix_entry + * doesn't modify the device hardware mask. Interrupts + * while masked are simply not injected to the guest, so + * are lost. Can we get away with always injecting an + * interrupt on unmask? + */ + } else if (assigned_dev_msix_masked(&orig) && + !assigned_dev_msix_masked(entry)) { + /* Vector unmasked */ + if (i >= adev->msi_virq_nr || adev->msi_virq[i] < 0) { + /* Previously unassigned vector, start from scratch */ + assigned_dev_update_msix(pdev); + return; + } else { + /* Update an existing, previously masked vector */ + MSIMessage msg; + int ret; + + msg.address = entry->addr_lo | + ((uint64_t)entry->addr_hi << 32); + msg.data = entry->data; + + ret = kvm_irqchip_update_msi_route(kvm_state, + adev->msi_virq[i], msg); + if (ret) { + error_report("Error updating irq routing entry (%d)", ret); + } + } + } + } +} + +static const MemoryRegionOps assigned_dev_msix_mmio_ops = { + .read = assigned_dev_msix_mmio_read, + .write = assigned_dev_msix_mmio_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 4, + .max_access_size = 8, + }, +}; + +static void assigned_dev_msix_reset(AssignedDevice *dev) +{ + MSIXTableEntry *entry; + int i; + + if (!dev->msix_table) { + return; + } + + memset(dev->msix_table, 0, MSIX_PAGE_SIZE); + + for (i = 0, entry = dev->msix_table; i < dev->msix_max; i++, entry++) { + entry->ctrl = cpu_to_le32(0x1); /* Masked */ + } +} + +static int assigned_dev_register_msix_mmio(AssignedDevice *dev) +{ + dev->msix_table = mmap(NULL, MSIX_PAGE_SIZE, PROT_READ|PROT_WRITE, + MAP_ANONYMOUS|MAP_PRIVATE, 0, 0); + if (dev->msix_table == MAP_FAILED) { + error_report("fail allocate msix_table! %s", strerror(errno)); + return -EFAULT; + } + + assigned_dev_msix_reset(dev); + + memory_region_init_io(&dev->mmio, &assigned_dev_msix_mmio_ops, dev, + "assigned-dev-msix", MSIX_PAGE_SIZE); + return 0; +} + +static void assigned_dev_unregister_msix_mmio(AssignedDevice *dev) +{ + if (!dev->msix_table) { + return; + } + + memory_region_destroy(&dev->mmio); + + if (munmap(dev->msix_table, MSIX_PAGE_SIZE) == -1) { + error_report("error unmapping msix_table! %s", strerror(errno)); + } + dev->msix_table = NULL; +} + +static const VMStateDescription vmstate_assigned_device = { + .name = "pci-assign", + .unmigratable = 1, +}; + +static void reset_assigned_device(DeviceState *dev) +{ + PCIDevice *pci_dev = DO_UPCAST(PCIDevice, qdev, dev); + AssignedDevice *adev = DO_UPCAST(AssignedDevice, dev, pci_dev); + char reset_file[64]; + const char reset[] = "1"; + int fd, ret; + + /* + * If a guest is reset without being shutdown, MSI/MSI-X can still + * be running. We want to return the device to a known state on + * reset, so disable those here. We especially do not want MSI-X + * enabled since it lives in MMIO space, which is about to get + * disabled. + */ + if (adev->assigned_irq_type == ASSIGNED_IRQ_MSIX) { + uint16_t ctrl = pci_get_word(pci_dev->config + + pci_dev->msix_cap + PCI_MSIX_FLAGS); + + pci_set_word(pci_dev->config + pci_dev->msix_cap + PCI_MSIX_FLAGS, + ctrl & ~PCI_MSIX_FLAGS_ENABLE); + assigned_dev_update_msix(pci_dev); + } else if (adev->assigned_irq_type == ASSIGNED_IRQ_MSI) { + uint8_t ctrl = pci_get_byte(pci_dev->config + + pci_dev->msi_cap + PCI_MSI_FLAGS); + + pci_set_byte(pci_dev->config + pci_dev->msi_cap + PCI_MSI_FLAGS, + ctrl & ~PCI_MSI_FLAGS_ENABLE); + assigned_dev_update_msi(pci_dev); + } + + snprintf(reset_file, sizeof(reset_file), + "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/reset", + adev->host.domain, adev->host.bus, adev->host.slot, + adev->host.function); + + /* + * Issue a device reset via pci-sysfs. Note that we use write(2) here + * and ignore the return value because some kernels have a bug that + * returns 0 rather than bytes written on success, sending us into an + * infinite retry loop using other write mechanisms. + */ + fd = open(reset_file, O_WRONLY); + if (fd != -1) { + ret = write(fd, reset, strlen(reset)); + (void)ret; + close(fd); + } + + /* + * When a 0 is written to the bus master register, the device is logically + * disconnected from the PCI bus. This avoids further DMA transfers. + */ + assigned_dev_pci_write_config(pci_dev, PCI_COMMAND, 0, 1); +} + +static int assigned_initfn(struct PCIDevice *pci_dev) +{ + AssignedDevice *dev = DO_UPCAST(AssignedDevice, dev, pci_dev); + uint8_t e_intx; + int r; + + if (!kvm_enabled()) { + error_report("pci-assign: error: requires KVM support"); + return -1; + } + + if (!dev->host.domain && !dev->host.bus && !dev->host.slot && + !dev->host.function) { + error_report("pci-assign: error: no host device specified"); + return -1; + } + + /* + * Set up basic config space access control. Will be further refined during + * device initialization. + */ + assigned_dev_emulate_config_read(dev, 0, PCI_CONFIG_SPACE_SIZE); + assigned_dev_direct_config_read(dev, PCI_STATUS, 2); + assigned_dev_direct_config_read(dev, PCI_REVISION_ID, 1); + assigned_dev_direct_config_read(dev, PCI_CLASS_PROG, 3); + assigned_dev_direct_config_read(dev, PCI_CACHE_LINE_SIZE, 1); + assigned_dev_direct_config_read(dev, PCI_LATENCY_TIMER, 1); + assigned_dev_direct_config_read(dev, PCI_BIST, 1); + assigned_dev_direct_config_read(dev, PCI_CARDBUS_CIS, 4); + assigned_dev_direct_config_read(dev, PCI_SUBSYSTEM_VENDOR_ID, 2); + assigned_dev_direct_config_read(dev, PCI_SUBSYSTEM_ID, 2); + assigned_dev_direct_config_read(dev, PCI_CAPABILITY_LIST + 1, 7); + assigned_dev_direct_config_read(dev, PCI_MIN_GNT, 1); + assigned_dev_direct_config_read(dev, PCI_MAX_LAT, 1); + memcpy(dev->emulate_config_write, dev->emulate_config_read, + sizeof(dev->emulate_config_read)); + + if (get_real_device(dev, dev->host.domain, dev->host.bus, + dev->host.slot, dev->host.function)) { + error_report("pci-assign: Error: Couldn't get real device (%s)!", + dev->dev.qdev.id); + goto out; + } + + if (assigned_device_pci_cap_init(pci_dev) < 0) { + goto out; + } + + /* intercept MSI-X entry page in the MMIO */ + if (dev->cap.available & ASSIGNED_DEVICE_CAP_MSIX) { + if (assigned_dev_register_msix_mmio(dev)) { + goto out; + } + } + + /* handle real device's MMIO/PIO BARs */ + if (assigned_dev_register_regions(dev->real_device.regions, + dev->real_device.region_number, + dev)) { + goto out; + } + + /* handle interrupt routing */ + e_intx = dev->dev.config[PCI_INTERRUPT_PIN] - 1; + dev->intpin = e_intx; + dev->intx_route.mode = PCI_INTX_DISABLED; + dev->intx_route.irq = -1; + + /* assign device to guest */ + r = assign_device(dev); + if (r < 0) { + goto out; + } + + /* assign legacy INTx to the device */ + r = assign_intx(dev); + if (r < 0) { + goto assigned_out; + } + + assigned_dev_load_option_rom(dev); + + add_boot_device_path(dev->bootindex, &pci_dev->qdev, NULL); + + return 0; + +assigned_out: + deassign_device(dev); +out: + free_assigned_device(dev); + return -1; +} + +static void assigned_exitfn(struct PCIDevice *pci_dev) +{ + AssignedDevice *dev = DO_UPCAST(AssignedDevice, dev, pci_dev); + + deassign_device(dev); + free_assigned_device(dev); +} + +static Property assigned_dev_properties[] = { + DEFINE_PROP_PCI_HOST_DEVADDR("host", AssignedDevice, host), + DEFINE_PROP_BIT("prefer_msi", AssignedDevice, features, + ASSIGNED_DEVICE_PREFER_MSI_BIT, false), + DEFINE_PROP_BIT("share_intx", AssignedDevice, features, + ASSIGNED_DEVICE_SHARE_INTX_BIT, true), + DEFINE_PROP_INT32("bootindex", AssignedDevice, bootindex, -1), + DEFINE_PROP_STRING("configfd", AssignedDevice, configfd_name), + DEFINE_PROP_END_OF_LIST(), +}; + +static void assign_class_init(ObjectClass *klass, void *data) +{ + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + k->init = assigned_initfn; + k->exit = assigned_exitfn; + k->config_read = assigned_dev_pci_read_config; + k->config_write = assigned_dev_pci_write_config; + dc->props = assigned_dev_properties; + dc->vmsd = &vmstate_assigned_device; + dc->reset = reset_assigned_device; + dc->desc = "KVM-based PCI passthrough"; +} + +static const TypeInfo assign_info = { + .name = "kvm-pci-assign", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(AssignedDevice), + .class_init = assign_class_init, +}; + +static void assign_register_types(void) +{ + type_register_static(&assign_info); +} + +type_init(assign_register_types) + +/* + * Scan the assigned devices for the devices that have an option ROM, and then + * load the corresponding ROM data to RAM. If an error occurs while loading an + * option ROM, we just ignore that option ROM and continue with the next one. + */ +static void assigned_dev_load_option_rom(AssignedDevice *dev) +{ + char name[32], rom_file[64]; + FILE *fp; + uint8_t val; + struct stat st; + void *ptr; + + /* If loading ROM from file, pci handles it */ + if (dev->dev.romfile || !dev->dev.rom_bar) { + return; + } + + snprintf(rom_file, sizeof(rom_file), + "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/rom", + dev->host.domain, dev->host.bus, dev->host.slot, + dev->host.function); + + if (stat(rom_file, &st)) { + return; + } + + if (access(rom_file, F_OK)) { + error_report("pci-assign: Insufficient privileges for %s", rom_file); + return; + } + + /* Write "1" to the ROM file to enable it */ + fp = fopen(rom_file, "r+"); + if (fp == NULL) { + return; + } + val = 1; + if (fwrite(&val, 1, 1, fp) != 1) { + goto close_rom; + } + fseek(fp, 0, SEEK_SET); + + snprintf(name, sizeof(name), "%s.rom", + object_get_typename(OBJECT(dev))); + memory_region_init_ram(&dev->dev.rom, name, st.st_size); + vmstate_register_ram(&dev->dev.rom, &dev->dev.qdev); + ptr = memory_region_get_ram_ptr(&dev->dev.rom); + memset(ptr, 0xff, st.st_size); + + if (!fread(ptr, 1, st.st_size, fp)) { + error_report("pci-assign: Cannot read from host %s\n" + "\tDevice option ROM contents are probably invalid " + "(check dmesg).\n\tSkip option ROM probe with rombar=0, " + "or load from file with romfile=", rom_file); + memory_region_destroy(&dev->dev.rom); + goto close_rom; + } + + pci_register_bar(&dev->dev, PCI_ROM_SLOT, 0, &dev->dev.rom); + dev->dev.has_rom = true; +close_rom: + /* Write "0" to disable ROM */ + fseek(fp, 0, SEEK_SET); + val = 0; + if (!fwrite(&val, 1, 1, fp)) { + DEBUG("%s\n", "Failed to disable pci-sysfs rom file"); + } + fclose(fp); +} diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c index 33b7f79a94..479eecda31 100644 --- a/hw/qdev-monitor.c +++ b/hw/qdev-monitor.c @@ -44,6 +44,7 @@ static const QDevAlias qdev_alias_table[] = { { "virtio-serial-s390", "virtio-serial", QEMU_ARCH_S390X }, { "lsi53c895a", "lsi" }, { "ich9-ahci", "ahci" }, + { "kvm-pci-assign", "pci-assign" }, { } }; From 149eeb5fe57b853081e8059575d91b8a58a4f96c Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Mon, 3 Sep 2012 22:56:00 +0200 Subject: [PATCH 0233/2270] hw/wm8750: Fix potential buffer overflow Report from smatch: hw/wm8750.c:369 wm8750_tx(12) error: buffer overflow 's->i2c_data' 2 <= 2 It looks like the preprocessor statements were simply misplaced. Replace also __FUNCTION__ by __func__ to please checkpatch.pl. Signed-off-by: Stefan Weil Reviewed-by: Peter Maydell Signed-off-by: Aurelien Jarno --- hw/wm8750.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/wm8750.c b/hw/wm8750.c index 11bcec3410..44f138fd51 100644 --- a/hw/wm8750.c +++ b/hw/wm8750.c @@ -361,10 +361,10 @@ static int wm8750_tx(I2CSlave *i2c, uint8_t data) uint16_t value; if (s->i2c_len >= 2) { - printf("%s: long message (%i bytes)\n", __FUNCTION__, s->i2c_len); #ifdef VERBOSE - return 1; + printf("%s: long message (%i bytes)\n", __func__, s->i2c_len); #endif + return 1; } s->i2c_data[s->i2c_len ++] = data; if (s->i2c_len != 2) From 599d64f6dc10f267a45e7abebfcafd8e7626585b Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Tue, 4 Sep 2012 07:35:57 +0200 Subject: [PATCH 0234/2270] target-arm: Fix potential buffer overflow Report from smatch: target-arm/helper.c:651 arm946_prbs_read(6) error: buffer overflow 'env->cp15.c6_region' 8 <= 8 target-arm/helper.c:661 arm946_prbs_write(6) error: buffer overflow 'env->cp15.c6_region' 8 <= 8 c7_region is an array with 8 elements, so the index must be less than 8. Signed-off-by: Stefan Weil Reviewed-by: Peter Maydell Signed-off-by: Aurelien Jarno --- target-arm/helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index dceaa95c80..e27df96272 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -645,7 +645,7 @@ static int pmsav5_insn_ap_read(CPUARMState *env, const ARMCPRegInfo *ri, static int arm946_prbs_read(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t *value) { - if (ri->crm > 8) { + if (ri->crm >= 8) { return EXCP_UDEF; } *value = env->cp15.c6_region[ri->crm]; @@ -655,7 +655,7 @@ static int arm946_prbs_read(CPUARMState *env, const ARMCPRegInfo *ri, static int arm946_prbs_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - if (ri->crm > 8) { + if (ri->crm >= 8) { return EXCP_UDEF; } env->cp15.c6_region[ri->crm] = value; From a32354e206895400d17c3de9a8df1de96d3df289 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Tue, 4 Sep 2012 19:37:39 +0200 Subject: [PATCH 0235/2270] hw/mcf5206: Fix buffer overflow for MBAR read / write Report from smatch: mcf5206.c:384 m5206_mbar_readb(7) error: buffer overflow 'm5206_mbar_width' 128 <= 128 mcf5206.c:403 m5206_mbar_readw(8) error: buffer overflow 'm5206_mbar_width' 128 <= 128 mcf5206.c:427 m5206_mbar_readl(8) error: buffer overflow 'm5206_mbar_width' 128 <= 128 mcf5206.c:451 m5206_mbar_writeb(9) error: buffer overflow 'm5206_mbar_width' 128 <= 128 mcf5206.c:475 m5206_mbar_writew(9) error: buffer overflow 'm5206_mbar_width' 128 <= 128 mcf5206.c:503 m5206_mbar_writel(9) error: buffer overflow 'm5206_mbar_width' 128 <= 128 m5206_mbar_width has 0x80 elements and supports 0 <= offset < 0x200. Signed-off-by: Stefan Weil Reviewed-by: Peter Maydell Signed-off-by: Aurelien Jarno --- hw/mcf5206.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/mcf5206.c b/hw/mcf5206.c index 539b391338..27753e2717 100644 --- a/hw/mcf5206.c +++ b/hw/mcf5206.c @@ -378,7 +378,7 @@ static uint32_t m5206_mbar_readb(void *opaque, target_phys_addr_t offset) { m5206_mbar_state *s = (m5206_mbar_state *)opaque; offset &= 0x3ff; - if (offset > 0x200) { + if (offset >= 0x200) { hw_error("Bad MBAR read offset 0x%x", (int)offset); } if (m5206_mbar_width[offset >> 2] > 1) { @@ -397,7 +397,7 @@ static uint32_t m5206_mbar_readw(void *opaque, target_phys_addr_t offset) m5206_mbar_state *s = (m5206_mbar_state *)opaque; int width; offset &= 0x3ff; - if (offset > 0x200) { + if (offset >= 0x200) { hw_error("Bad MBAR read offset 0x%x", (int)offset); } width = m5206_mbar_width[offset >> 2]; @@ -421,7 +421,7 @@ static uint32_t m5206_mbar_readl(void *opaque, target_phys_addr_t offset) m5206_mbar_state *s = (m5206_mbar_state *)opaque; int width; offset &= 0x3ff; - if (offset > 0x200) { + if (offset >= 0x200) { hw_error("Bad MBAR read offset 0x%x", (int)offset); } width = m5206_mbar_width[offset >> 2]; @@ -445,7 +445,7 @@ static void m5206_mbar_writeb(void *opaque, target_phys_addr_t offset, m5206_mbar_state *s = (m5206_mbar_state *)opaque; int width; offset &= 0x3ff; - if (offset > 0x200) { + if (offset >= 0x200) { hw_error("Bad MBAR write offset 0x%x", (int)offset); } width = m5206_mbar_width[offset >> 2]; @@ -469,7 +469,7 @@ static void m5206_mbar_writew(void *opaque, target_phys_addr_t offset, m5206_mbar_state *s = (m5206_mbar_state *)opaque; int width; offset &= 0x3ff; - if (offset > 0x200) { + if (offset >= 0x200) { hw_error("Bad MBAR write offset 0x%x", (int)offset); } width = m5206_mbar_width[offset >> 2]; @@ -497,7 +497,7 @@ static void m5206_mbar_writel(void *opaque, target_phys_addr_t offset, m5206_mbar_state *s = (m5206_mbar_state *)opaque; int width; offset &= 0x3ff; - if (offset > 0x200) { + if (offset >= 0x200) { hw_error("Bad MBAR write offset 0x%x", (int)offset); } width = m5206_mbar_width[offset >> 2]; From 8bf188aa18ef7a8355d9edbd43871d590468c4ed Mon Sep 17 00:00:00 2001 From: Michael Tokarev Date: Thu, 7 Jun 2012 01:11:00 +0400 Subject: [PATCH 0236/2270] use --libexecdir instead of ignoring it first and reinventing it later MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 7b93fadf3a38d1ed65ea5536a52efc2772c6e3b8 "Add basic version of bridge helper" put the bridge helper executable into a fixed ${prefix}/libexec/ location, instead of using ${libexecdir} for this. At the same time, --libexecdir is being happily ignored by ./configure. Even more, the same patch sets unused $libexecdir variable in the generated config-host.mak, and uses fixed string (\${prefix}/libexecdir) for the bridge helper binary. Fix this braindamage by introducing $libexecdir variable, using it for the bridge helper binary, and recognizing --libexecdir. This patch is applicable to stable-1.1. Reviewed-by: Andreas Färber Reviewed-by: Corey Bryant Signed-off-by: Michael Tokarev Cc: Corey Bryant Cc: Richa Marwaha Cc: qemu-stable@nongnu.org Signed-off-by: Anthony Liguori --- configure | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/configure b/configure index f4de245d96..fa64d5de15 100755 --- a/configure +++ b/configure @@ -183,6 +183,7 @@ datadir="\${prefix}/share" qemu_docdir="\${prefix}/share/doc/qemu" bindir="\${prefix}/bin" libdir="\${prefix}/lib" +libexecdir="\${prefix}/libexec" includedir="\${prefix}/include" sysconfdir="\${prefix}/etc" confsuffix="/qemu" @@ -633,6 +634,8 @@ for opt do ;; --libdir=*) libdir="$optarg" ;; + --libexecdir=*) libexecdir="$optarg" + ;; --includedir=*) includedir="$optarg" ;; --datadir=*) datadir="$optarg" @@ -643,7 +646,7 @@ for opt do ;; --sysconfdir=*) sysconfdir="$optarg" ;; - --sbindir=*|--libexecdir=*|--sharedstatedir=*|--localstatedir=*|\ + --sbindir=*|--sharedstatedir=*|--localstatedir=*|\ --oldincludedir=*|--datarootdir=*|--infodir=*|--localedir=*|\ --htmldir=*|--dvidir=*|--pdfdir=*|--psdir=*) # These switches are silently ignored, for compatibility with @@ -3085,6 +3088,7 @@ echo "Install prefix $prefix" echo "BIOS directory `eval echo $qemu_datadir`" echo "binary directory `eval echo $bindir`" echo "library directory `eval echo $libdir`" +echo "libexec directory `eval echo $libexecdir`" echo "include directory `eval echo $includedir`" echo "config directory `eval echo $sysconfdir`" if test "$mingw32" = "no" ; then @@ -3188,14 +3192,14 @@ echo all: >> $config_host_mak echo "prefix=$prefix" >> $config_host_mak echo "bindir=$bindir" >> $config_host_mak echo "libdir=$libdir" >> $config_host_mak +echo "libexecdir=$libexecdir" >> $config_host_mak echo "includedir=$includedir" >> $config_host_mak echo "mandir=$mandir" >> $config_host_mak echo "sysconfdir=$sysconfdir" >> $config_host_mak echo "qemu_confdir=$qemu_confdir" >> $config_host_mak echo "qemu_datadir=$qemu_datadir" >> $config_host_mak echo "qemu_docdir=$qemu_docdir" >> $config_host_mak -echo "libexecdir=\${prefix}/libexec" >> $config_host_mak -echo "CONFIG_QEMU_HELPERDIR=\"$prefix/libexec\"" >> $config_host_mak +echo "CONFIG_QEMU_HELPERDIR=\"$libexecdir\"" >> $config_host_mak echo "ARCH=$ARCH" >> $config_host_mak if test "$debug_tcg" = "yes" ; then From 455aa1e0818653c41fd794435b982426ce21ba2f Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Wed, 5 Sep 2012 13:52:49 -0500 Subject: [PATCH 0237/2270] socket: don't attempt to reconnect a TCP socket in server mode Commit c3767ed0eb5d0bb25fe409ae5dec06e3411ff1b6 introduced a possible SEGV when using a socket chardev with server=on because it assumes that all TCP sockets are in client mode. This patch adds a check to only reconnect when in client mode. Cc: Lei Li Reported-by: Michael Roth Signed-off-by: Anthony Liguori --- qemu-char.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qemu-char.c b/qemu-char.c index 398baf1e04..767da93862 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2148,10 +2148,12 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) TCPCharDriver *s = chr->opaque; if (s->connected) { return send_all(s->fd, buf, len); - } else { + } else if (s->listen_fd == -1) { /* (Re-)connect for unconnected writing */ tcp_chr_connect(chr); return 0; + } else { + return len; } } From bedc572eae6e250070495116f0db72607826aee5 Mon Sep 17 00:00:00 2001 From: Yang Zhang Date: Thu, 2 Aug 2012 18:04:04 +0200 Subject: [PATCH 0238/2270] RTC: Remove the logic to update time format when DM bit changed Changing the DM (binary/BCD) and 24/12 control bit doesn't affect the internal registers. It only indicates what format is used for those registers. Signed-off-by: Yang Zhang Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- hw/mc146818rtc.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index 3777f858a1..6e5b2f0893 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -220,15 +220,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) rtc_set_time(s); } } - if (((s->cmos_data[RTC_REG_B] ^ data) & (REG_B_DM | REG_B_24H)) && - !(data & REG_B_SET)) { - /* If the time format has changed and not in set mode, - update the registers immediately. */ - s->cmos_data[RTC_REG_B] = data; - rtc_copy_date(s); - } else { - s->cmos_data[RTC_REG_B] = data; - } + s->cmos_data[RTC_REG_B] = data; rtc_timer_update(s, qemu_get_clock_ns(rtc_clock)); break; case RTC_REG_C: From c4c18e246f968f18dc656afa3e8de7cf6b9752e8 Mon Sep 17 00:00:00 2001 From: Yang Zhang Date: Thu, 2 Aug 2012 18:04:05 +0200 Subject: [PATCH 0239/2270] RTC: Rename rtc_timer_update Signed-off-by: Yang Zhang Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- hw/mc146818rtc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index 6e5b2f0893..b99f4d35f4 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -110,7 +110,7 @@ static void rtc_coalesced_timer(void *opaque) } #endif -static void rtc_timer_update(RTCState *s, int64_t current_time) +static void periodic_timer_update(RTCState *s, int64_t current_time) { int period_code, period; int64_t cur_clock, next_irq_clock; @@ -148,7 +148,7 @@ static void rtc_periodic_timer(void *opaque) { RTCState *s = opaque; - rtc_timer_update(s, s->next_periodic_time); + periodic_timer_update(s, s->next_periodic_time); s->cmos_data[RTC_REG_C] |= REG_C_PF; if (s->cmos_data[RTC_REG_B] & REG_B_PIE) { s->cmos_data[RTC_REG_C] |= REG_C_IRQF; @@ -207,7 +207,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) /* UIP bit is read only */ s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) | (s->cmos_data[RTC_REG_A] & REG_A_UIP); - rtc_timer_update(s, qemu_get_clock_ns(rtc_clock)); + periodic_timer_update(s, qemu_get_clock_ns(rtc_clock)); break; case RTC_REG_B: if (data & REG_B_SET) { @@ -221,7 +221,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) } } s->cmos_data[RTC_REG_B] = data; - rtc_timer_update(s, qemu_get_clock_ns(rtc_clock)); + periodic_timer_update(s, qemu_get_clock_ns(rtc_clock)); break; case RTC_REG_C: case RTC_REG_D: @@ -550,7 +550,7 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data) rtc_set_date_from_host(&s->dev); s->next_second_time = now + (get_ticks_per_sec() * 99) / 100; qemu_mod_timer(s->second_timer2, s->next_second_time); - rtc_timer_update(s, now); + periodic_timer_update(s, now); #ifdef TARGET_I386 if (s->lost_tick_policy == LOST_TICK_SLEW) { rtc_coalesced_timer_update(s); From e46deabaa58b78397aeef2b04147aeecf5933794 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 2 Aug 2012 18:04:06 +0200 Subject: [PATCH 0240/2270] RTC: introduce RTC_CLOCK_RATE Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- hw/mc146818rtc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index b99f4d35f4..175ddac6fb 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -46,6 +46,7 @@ #endif #define RTC_REINJECT_ON_ACK_COUNT 20 +#define RTC_CLOCK_RATE 32768 typedef struct RTCState { ISADevice dev; @@ -85,7 +86,7 @@ static void rtc_coalesced_timer_update(RTCState *s) /* divide each RTC interval to 2 - 8 smaller intervals */ int c = MIN(s->irq_coalesced, 7) + 1; int64_t next_clock = qemu_get_clock_ns(rtc_clock) + - muldiv64(s->period / c, get_ticks_per_sec(), 32768); + muldiv64(s->period / c, get_ticks_per_sec(), RTC_CLOCK_RATE); qemu_mod_timer(s->coalesced_timer, next_clock); } } @@ -131,10 +132,10 @@ static void periodic_timer_update(RTCState *s, int64_t current_time) s->period = period; #endif /* compute 32 khz clock */ - cur_clock = muldiv64(current_time, 32768, get_ticks_per_sec()); + cur_clock = muldiv64(current_time, RTC_CLOCK_RATE, get_ticks_per_sec()); next_irq_clock = (cur_clock & ~(period - 1)) + period; s->next_periodic_time = - muldiv64(next_irq_clock, get_ticks_per_sec(), 32768) + 1; + muldiv64(next_irq_clock, get_ticks_per_sec(), RTC_CLOCK_RATE) + 1; qemu_mod_timer(s->periodic_timer, s->next_periodic_time); } else { #ifdef TARGET_I386 @@ -369,7 +370,7 @@ static void rtc_update_second(void *opaque) /* update in progress bit */ s->cmos_data[RTC_REG_A] |= REG_A_UIP; } - /* should be 244 us = 8 / 32768 seconds, but currently the + /* should be 244 us = 8 / RTC_CLOCK_RATE seconds, but currently the timers do not have the necessary resolution. */ delay = (get_ticks_per_sec() * 1) / 100; if (delay < 1) From 9324cc50c6b5df0998d46e8fca76e35f00ced6c3 Mon Sep 17 00:00:00 2001 From: Yang Zhang Date: Thu, 2 Aug 2012 18:04:07 +0200 Subject: [PATCH 0241/2270] RTC: Update interrupt state when interrupts are masked/unmasked If an interrupt flag is already set when the interrupt becomes enabled, raise an interrupt immediately, and vice versa if interrupts become disabled. Signed-off-by: Yang Zhang Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- hw/mc146818rtc.c | 9 +++++++++ hw/mc146818rtc_regs.h | 1 + 2 files changed, 10 insertions(+) diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index 175ddac6fb..b41eb4b944 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -221,6 +221,15 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) rtc_set_time(s); } } + /* if an interrupt flag is already set when the interrupt + * becomes enabled, raise an interrupt immediately. */ + if (data & s->cmos_data[RTC_REG_C] & REG_C_MASK) { + s->cmos_data[RTC_REG_C] |= REG_C_IRQF; + qemu_irq_raise(s->irq); + } else { + s->cmos_data[RTC_REG_C] &= ~REG_C_IRQF; + qemu_irq_lower(s->irq); + } s->cmos_data[RTC_REG_B] = data; periodic_timer_update(s, qemu_get_clock_ns(rtc_clock)); break; diff --git a/hw/mc146818rtc_regs.h b/hw/mc146818rtc_regs.h index 3ab37709f0..fc10076ece 100644 --- a/hw/mc146818rtc_regs.h +++ b/hw/mc146818rtc_regs.h @@ -58,5 +58,6 @@ #define REG_C_IRQF 0x80 #define REG_C_PF 0x40 #define REG_C_AF 0x20 +#define REG_C_MASK 0x70 #endif From 0281518a1c7dd3577dea9ccc78869ecff954589c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 2 Aug 2012 18:04:08 +0200 Subject: [PATCH 0242/2270] vmstate: add VMSTATE_TIMER_V Also, for consistency with other occurrences, implement VMSTATE_TIMER as a special case of VMSTATE_TIMER_V rather than VMSTATE_TIMER_TEST. Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- vmstate.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vmstate.h b/vmstate.h index 5bd2b762ab..c9c320e62e 100644 --- a/vmstate.h +++ b/vmstate.h @@ -503,8 +503,11 @@ extern const VMStateInfo vmstate_info_unused_buffer; #define VMSTATE_TIMER_TEST(_f, _s, _test) \ VMSTATE_POINTER_TEST(_f, _s, _test, vmstate_info_timer, QEMUTimer *) +#define VMSTATE_TIMER_V(_f, _s, _v) \ + VMSTATE_POINTER(_f, _s, _v, vmstate_info_timer, QEMUTimer *) + #define VMSTATE_TIMER(_f, _s) \ - VMSTATE_TIMER_TEST(_f, _s, NULL) + VMSTATE_TIMER_V(_f, _s, 0) #define VMSTATE_TIMER_ARRAY(_f, _s, _n) \ VMSTATE_ARRAY_OF_POINTER(_f, _s, _n, 0, vmstate_info_timer, QEMUTimer *) From 56038ef6234e5fb3d01bad1f6df37c2ccab82af9 Mon Sep 17 00:00:00 2001 From: Yang Zhang Date: Thu, 2 Aug 2012 18:04:09 +0200 Subject: [PATCH 0243/2270] RTC: Update the RTC clock only when reading it Calculate guest RTC based on the time of the last update, instead of using timers. The formula is (base_rtc + guest_time_now - guest_time_last_update + offset) Base_rtc is the RTC value when the RTC was last updated. Guest_time_now is the guest time when the access happens. Guest_time_last_update was the guest time when the RTC was last updated. Offset is used when divider reset happens or the set bit is toggled. The timer is kept in order to signal interrupts, but it only needs to run when either UF or AF is cleared. When the bits are both set, the timer does not run. UIP is now synthesized when reading register A. If the timer is not set, or if there is more than one second before it (as is the case at the end of this series), the leading edge of UIP is computed and the rising edge occurs 220us later. If the update timer occurs within one second, however, the rising edge of the AF and UF bits should coincide withe the falling edge of UIP. We do not know exactly when this will happen because there could be delays in the servicing of the timer. Hence, in this case reading register A only computes for the rising edge of UIP, and latches the bit until the timer is fired and clears it. Signed-off-by: Yang Zhang Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- hw/mc146818rtc.c | 327 ++++++++++++++++++++++++++++------------------- 1 file changed, 193 insertions(+), 134 deletions(-) diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index b41eb4b944..54c98a53d3 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -45,8 +45,11 @@ # define DPRINTF_C(format, ...) do { } while (0) #endif +#define NSEC_PER_SEC 1000000000LL + #define RTC_REINJECT_ON_ACK_COUNT 20 #define RTC_CLOCK_RATE 32768 +#define UIP_HOLD_LENGTH (8 * NSEC_PER_SEC / 32768) typedef struct RTCState { ISADevice dev; @@ -55,27 +58,40 @@ typedef struct RTCState { uint8_t cmos_index; struct tm current_tm; int32_t base_year; + uint64_t base_rtc; + uint64_t last_update; + int64_t offset; qemu_irq irq; qemu_irq sqw_irq; int it_shift; /* periodic timer */ QEMUTimer *periodic_timer; int64_t next_periodic_time; - /* second update */ - int64_t next_second_time; + /* update-ended timer */ + QEMUTimer *update_timer; uint16_t irq_reinject_on_ack_count; uint32_t irq_coalesced; uint32_t period; QEMUTimer *coalesced_timer; - QEMUTimer *second_timer; - QEMUTimer *second_timer2; Notifier clock_reset_notifier; LostTickPolicy lost_tick_policy; Notifier suspend_notifier; } RTCState; static void rtc_set_time(RTCState *s); -static void rtc_copy_date(RTCState *s); +static void rtc_update_time(RTCState *s); +static void rtc_set_cmos(RTCState *s); +static inline int rtc_from_bcd(RTCState *s, int a); + +static uint64_t get_guest_rtc_ns(RTCState *s) +{ + uint64_t guest_rtc; + uint64_t guest_clock = qemu_get_clock_ns(rtc_clock); + + guest_rtc = s->base_rtc * NSEC_PER_SEC + + guest_clock - s->last_update + s->offset; + return guest_rtc; +} #ifdef TARGET_I386 static void rtc_coalesced_timer_update(RTCState *s) @@ -111,6 +127,7 @@ static void rtc_coalesced_timer(void *opaque) } #endif +/* handle periodic timer */ static void periodic_timer_update(RTCState *s, int64_t current_time) { int period_code, period; @@ -176,6 +193,100 @@ static void rtc_periodic_timer(void *opaque) } } +/* handle update-ended timer */ +static void check_update_timer(RTCState *s) +{ + uint64_t next_update_time; + uint64_t guest_nsec; + + /* From the data sheet: setting the SET bit does not prevent + * interrupts from occurring! However, it will prevent an + * alarm interrupt from occurring, because the time of day is + * not updated. + */ + if ((s->cmos_data[RTC_REG_C] & REG_C_UF) && + (s->cmos_data[RTC_REG_B] & REG_B_SET)) { + qemu_del_timer(s->update_timer); + return; + } + if ((s->cmos_data[RTC_REG_C] & REG_C_UF) && + (s->cmos_data[RTC_REG_C] & REG_C_AF)) { + qemu_del_timer(s->update_timer); + return; + } + + guest_nsec = get_guest_rtc_ns(s) % NSEC_PER_SEC; + /* reprogram to next second */ + next_update_time = qemu_get_clock_ns(rtc_clock) + + NSEC_PER_SEC - guest_nsec; + if (next_update_time != qemu_timer_expire_time_ns(s->update_timer)) { + qemu_mod_timer(s->update_timer, next_update_time); + } +} + +static inline uint8_t convert_hour(RTCState *s, uint8_t hour) +{ + if (!(s->cmos_data[RTC_REG_B] & REG_B_24H)) { + hour %= 12; + if (s->cmos_data[RTC_HOURS] & 0x80) { + hour += 12; + } + } + return hour; +} + +static uint32_t check_alarm(RTCState *s) +{ + uint8_t alarm_hour, alarm_min, alarm_sec; + uint8_t cur_hour, cur_min, cur_sec; + + alarm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]); + alarm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]); + alarm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]); + alarm_hour = convert_hour(s, alarm_hour); + + cur_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]); + cur_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]); + cur_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS]); + cur_hour = convert_hour(s, cur_hour); + + if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 + || alarm_sec == cur_sec) && + ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 + || alarm_min == cur_min) && + ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 + || alarm_hour == cur_hour)) { + return 1; + } + return 0; + +} + +static void rtc_update_timer(void *opaque) +{ + RTCState *s = opaque; + int32_t irqs = REG_C_UF; + int32_t new_irqs; + + /* UIP might have been latched, update time and clear it. */ + rtc_update_time(s); + s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; + + if (check_alarm(s)) { + irqs |= REG_C_AF; + if (s->cmos_data[RTC_REG_B] & REG_B_AIE) { + qemu_system_wakeup_request(QEMU_WAKEUP_REASON_RTC); + } + } + new_irqs = irqs & ~s->cmos_data[RTC_REG_C]; + s->cmos_data[RTC_REG_C] |= irqs; + if ((new_irqs & s->cmos_data[RTC_REG_B]) != 0) { + s->cmos_data[RTC_REG_C] |= REG_C_IRQF; + qemu_irq_raise(s->irq); + } + check_update_timer(s); +} + static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) { RTCState *s = opaque; @@ -190,6 +301,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) case RTC_MINUTES_ALARM: case RTC_HOURS_ALARM: s->cmos_data[s->cmos_index] = data; + check_update_timer(s); break; case RTC_SECONDS: case RTC_MINUTES: @@ -202,6 +314,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) /* if in set mode, do not update the time */ if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { rtc_set_time(s); + check_update_timer(s); } break; case RTC_REG_A: @@ -209,15 +322,21 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) | (s->cmos_data[RTC_REG_A] & REG_A_UIP); periodic_timer_update(s, qemu_get_clock_ns(rtc_clock)); + check_update_timer(s); break; case RTC_REG_B: if (data & REG_B_SET) { + /* update cmos to when the rtc was stopping */ + if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { + rtc_update_time(s); + } /* set mode: reset UIP mode */ s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; data &= ~REG_B_UIE; } else { /* if disabling set mode, update the time */ if (s->cmos_data[RTC_REG_B] & REG_B_SET) { + s->offset = get_guest_rtc_ns(s) % NSEC_PER_SEC; rtc_set_time(s); } } @@ -232,6 +351,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) } s->cmos_data[RTC_REG_B] = data; periodic_timer_update(s, qemu_get_clock_ns(rtc_clock)); + check_update_timer(s); break; case RTC_REG_C: case RTC_REG_D: @@ -280,10 +400,13 @@ static void rtc_set_time(RTCState *s) tm->tm_mon = rtc_from_bcd(s, s->cmos_data[RTC_MONTH]) - 1; tm->tm_year = rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900; + s->base_rtc = mktimegm(tm); + s->last_update = qemu_get_clock_ns(rtc_clock); + rtc_change_mon_event(tm); } -static void rtc_copy_date(RTCState *s) +static void rtc_set_cmos(RTCState *s) { const struct tm *tm = &s->current_tm; int year; @@ -309,122 +432,41 @@ static void rtc_copy_date(RTCState *s) s->cmos_data[RTC_YEAR] = rtc_to_bcd(s, year); } -/* month is between 0 and 11. */ -static int get_days_in_month(int month, int year) +static void rtc_update_time(RTCState *s) { - static const int days_tab[12] = { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 - }; - int d; - if ((unsigned )month >= 12) - return 31; - d = days_tab[month]; - if (month == 1) { - if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) - d++; - } - return d; + struct tm ret; + time_t guest_sec; + int64_t guest_nsec; + + guest_nsec = get_guest_rtc_ns(s); + guest_sec = guest_nsec / NSEC_PER_SEC; + gmtime_r(&guest_sec, &ret); + s->current_tm = ret; + rtc_set_cmos(s); } -/* update 'tm' to the next second */ -static void rtc_next_second(struct tm *tm) +static int update_in_progress(RTCState *s) { - int days_in_month; + int64_t guest_nsec; - tm->tm_sec++; - if ((unsigned)tm->tm_sec >= 60) { - tm->tm_sec = 0; - tm->tm_min++; - if ((unsigned)tm->tm_min >= 60) { - tm->tm_min = 0; - tm->tm_hour++; - if ((unsigned)tm->tm_hour >= 24) { - tm->tm_hour = 0; - /* next day */ - tm->tm_wday++; - if ((unsigned)tm->tm_wday >= 7) - tm->tm_wday = 0; - days_in_month = get_days_in_month(tm->tm_mon, - tm->tm_year + 1900); - tm->tm_mday++; - if (tm->tm_mday < 1) { - tm->tm_mday = 1; - } else if (tm->tm_mday > days_in_month) { - tm->tm_mday = 1; - tm->tm_mon++; - if (tm->tm_mon >= 12) { - tm->tm_mon = 0; - tm->tm_year++; - } - } - } - } + if (s->cmos_data[RTC_REG_B] & REG_B_SET) { + return 0; } -} - - -static void rtc_update_second(void *opaque) -{ - RTCState *s = opaque; - int64_t delay; - - /* if the oscillator is not in normal operation, we do not update */ - if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) { - s->next_second_time += get_ticks_per_sec(); - qemu_mod_timer(s->second_timer, s->next_second_time); - } else { - rtc_next_second(&s->current_tm); - - if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { - /* update in progress bit */ + if (qemu_timer_pending(s->update_timer)) { + int64_t next_update_time = qemu_timer_expire_time_ns(s->update_timer); + /* Latch UIP until the timer expires. */ + if (qemu_get_clock_ns(rtc_clock) >= (next_update_time - UIP_HOLD_LENGTH)) { s->cmos_data[RTC_REG_A] |= REG_A_UIP; - } - /* should be 244 us = 8 / RTC_CLOCK_RATE seconds, but currently the - timers do not have the necessary resolution. */ - delay = (get_ticks_per_sec() * 1) / 100; - if (delay < 1) - delay = 1; - qemu_mod_timer(s->second_timer2, - s->next_second_time + delay); - } -} - -static void rtc_update_second2(void *opaque) -{ - RTCState *s = opaque; - - if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { - rtc_copy_date(s); - } - - /* check alarm */ - if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 || - rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]) == s->current_tm.tm_sec) && - ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 || - rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]) == s->current_tm.tm_min) && - ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 || - rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]) == s->current_tm.tm_hour)) { - - s->cmos_data[RTC_REG_C] |= REG_C_AF; - if (s->cmos_data[RTC_REG_B] & REG_B_AIE) { - qemu_system_wakeup_request(QEMU_WAKEUP_REASON_RTC); - qemu_irq_raise(s->irq); - s->cmos_data[RTC_REG_C] |= REG_C_IRQF; + return 1; } } - /* update ended interrupt */ - s->cmos_data[RTC_REG_C] |= REG_C_UF; - if (s->cmos_data[RTC_REG_B] & REG_B_UIE) { - s->cmos_data[RTC_REG_C] |= REG_C_IRQF; - qemu_irq_raise(s->irq); + guest_nsec = get_guest_rtc_ns(s); + /* UIP bit will be set at last 244us of every second. */ + if ((guest_nsec % NSEC_PER_SEC) >= (NSEC_PER_SEC - UIP_HOLD_LENGTH)) { + return 1; } - - /* clear update in progress bit */ - s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; - - s->next_second_time += get_ticks_per_sec(); - qemu_mod_timer(s->second_timer, s->next_second_time); + return 0; } static uint32_t cmos_ioport_read(void *opaque, uint32_t addr) @@ -442,15 +484,28 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr) case RTC_DAY_OF_MONTH: case RTC_MONTH: case RTC_YEAR: + /* if not in set mode, calibrate cmos before + * reading*/ + if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { + rtc_update_time(s); + } ret = s->cmos_data[s->cmos_index]; break; case RTC_REG_A: + if (update_in_progress(s)) { + s->cmos_data[s->cmos_index] |= REG_A_UIP; + } else { + s->cmos_data[s->cmos_index] &= ~REG_A_UIP; + } ret = s->cmos_data[s->cmos_index]; break; case RTC_REG_C: ret = s->cmos_data[s->cmos_index]; qemu_irq_lower(s->irq); s->cmos_data[RTC_REG_C] = 0x00; + if (ret & (REG_C_UF | REG_C_AF)) { + check_update_timer(s); + } #ifdef TARGET_I386 if(s->irq_coalesced && (s->cmos_data[RTC_REG_B] & REG_B_PIE) && @@ -485,13 +540,6 @@ void rtc_set_memory(ISADevice *dev, int addr, int val) s->cmos_data[addr] = val; } -void rtc_set_date(ISADevice *dev, const struct tm *tm) -{ - RTCState *s = DO_UPCAST(RTCState, dev, dev); - s->current_tm = *tm; - rtc_copy_date(s); -} - /* PC cmos mappings */ #define REG_IBM_CENTURY_BYTE 0x32 #define REG_IBM_PS2_CENTURY_BYTE 0x37 @@ -502,9 +550,15 @@ static void rtc_set_date_from_host(ISADevice *dev) struct tm tm; int val; - /* set the CMOS date */ qemu_get_timedate(&tm, 0); - rtc_set_date(dev, &tm); + + s->base_rtc = mktimegm(&tm); + s->last_update = qemu_get_clock_ns(rtc_clock); + s->offset = 0; + + /* set the CMOS date */ + s->current_tm = tm; + rtc_set_cmos(s); val = rtc_to_bcd(s, (tm.tm_year / 100) + 19); rtc_set_memory(dev, REG_IBM_CENTURY_BYTE, val); @@ -513,9 +567,15 @@ static void rtc_set_date_from_host(ISADevice *dev) static int rtc_post_load(void *opaque, int version_id) { -#ifdef TARGET_I386 RTCState *s = opaque; + if (version_id <= 2) { + rtc_set_time(s); + s->offset = 0; + check_update_timer(s); + } + +#ifdef TARGET_I386 if (version_id >= 2) { if (s->lost_tick_policy == LOST_TICK_SLEW) { rtc_coalesced_timer_update(s); @@ -527,7 +587,7 @@ static int rtc_post_load(void *opaque, int version_id) static const VMStateDescription vmstate_rtc = { .name = "mc146818rtc", - .version_id = 2, + .version_id = 3, .minimum_version_id = 1, .minimum_version_id_old = 1, .post_load = rtc_post_load, @@ -543,11 +603,13 @@ static const VMStateDescription vmstate_rtc = { VMSTATE_INT32(current_tm.tm_year, RTCState), VMSTATE_TIMER(periodic_timer, RTCState), VMSTATE_INT64(next_periodic_time, RTCState), - VMSTATE_INT64(next_second_time, RTCState), - VMSTATE_TIMER(second_timer, RTCState), - VMSTATE_TIMER(second_timer2, RTCState), + VMSTATE_UNUSED(3*8), VMSTATE_UINT32_V(irq_coalesced, RTCState, 2), VMSTATE_UINT32_V(period, RTCState, 2), + VMSTATE_UINT64_V(base_rtc, RTCState, 3), + VMSTATE_UINT64_V(last_update, RTCState, 3), + VMSTATE_INT64_V(offset, RTCState, 3), + VMSTATE_TIMER_V(update_timer, RTCState, 3), VMSTATE_END_OF_LIST() } }; @@ -558,9 +620,8 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data) int64_t now = *(int64_t *)data; rtc_set_date_from_host(&s->dev); - s->next_second_time = now + (get_ticks_per_sec() * 99) / 100; - qemu_mod_timer(s->second_timer2, s->next_second_time); periodic_timer_update(s, now); + check_update_timer(s); #ifdef TARGET_I386 if (s->lost_tick_policy == LOST_TICK_SLEW) { rtc_coalesced_timer_update(s); @@ -582,6 +643,7 @@ static void rtc_reset(void *opaque) s->cmos_data[RTC_REG_B] &= ~(REG_B_PIE | REG_B_AIE | REG_B_SQWE); s->cmos_data[RTC_REG_C] &= ~(REG_C_UF | REG_C_IRQF | REG_C_PF | REG_C_AF); + check_update_timer(s); qemu_irq_lower(s->irq); @@ -607,6 +669,7 @@ static void rtc_get_date(Object *obj, Visitor *v, void *opaque, ISADevice *isa = ISA_DEVICE(obj); RTCState *s = DO_UPCAST(RTCState, dev, isa); + rtc_update_time(s); visit_start_struct(v, NULL, "struct tm", name, 0, errp); visit_type_int32(v, &s->current_tm.tm_year, "tm_year", errp); visit_type_int32(v, &s->current_tm.tm_mon, "tm_mon", errp); @@ -643,8 +706,8 @@ static int rtc_initfn(ISADevice *dev) #endif s->periodic_timer = qemu_new_timer_ns(rtc_clock, rtc_periodic_timer, s); - s->second_timer = qemu_new_timer_ns(rtc_clock, rtc_update_second, s); - s->second_timer2 = qemu_new_timer_ns(rtc_clock, rtc_update_second2, s); + s->update_timer = qemu_new_timer_ns(rtc_clock, rtc_update_timer, s); + check_update_timer(s); s->clock_reset_notifier.notify = rtc_notify_clock_reset; qemu_register_clock_reset_notifier(rtc_clock, &s->clock_reset_notifier); @@ -652,14 +715,10 @@ static int rtc_initfn(ISADevice *dev) s->suspend_notifier.notify = rtc_notify_suspend; qemu_register_suspend_notifier(&s->suspend_notifier); - s->next_second_time = - qemu_get_clock_ns(rtc_clock) + (get_ticks_per_sec() * 99) / 100; - qemu_mod_timer(s->second_timer2, s->next_second_time); - memory_region_init_io(&s->io, &cmos_ops, s, "rtc", 2); isa_register_ioport(dev, &s->io, base); - qdev_set_legacy_instance_id(&dev->qdev, base, 2); + qdev_set_legacy_instance_id(&dev->qdev, base, 3); qemu_register_reset(rtc_reset, s); object_property_add(OBJECT(s), "date", "struct tm", From 41a9b8b24d59acec462b0d8e0d2a7ffce6031d55 Mon Sep 17 00:00:00 2001 From: Yang Zhang Date: Thu, 2 Aug 2012 18:04:10 +0200 Subject: [PATCH 0244/2270] RTC: Add divider reset support The first update cycle begins one-half seconds after divider reset is removed. This feature is useful for testing. Signed-off-by: Yang Zhang Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- hw/mc146818rtc.c | 50 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index 54c98a53d3..cb65c4f9ea 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -83,6 +83,12 @@ static void rtc_update_time(RTCState *s); static void rtc_set_cmos(RTCState *s); static inline int rtc_from_bcd(RTCState *s, int a); +static inline bool rtc_running(RTCState *s) +{ + return (!(s->cmos_data[RTC_REG_B] & REG_B_SET) && + (s->cmos_data[RTC_REG_A] & 0x70) <= 0x20); +} + static uint64_t get_guest_rtc_ns(RTCState *s) { uint64_t guest_rtc; @@ -199,11 +205,15 @@ static void check_update_timer(RTCState *s) uint64_t next_update_time; uint64_t guest_nsec; - /* From the data sheet: setting the SET bit does not prevent - * interrupts from occurring! However, it will prevent an - * alarm interrupt from occurring, because the time of day is - * not updated. + /* From the data sheet: "Holding the dividers in reset prevents + * interrupts from operating, while setting the SET bit allows" + * them to occur. However, it will prevent an alarm interrupt + * from occurring, because the time of day is not updated. */ + if ((s->cmos_data[RTC_REG_A] & 0x60) == 0x60) { + qemu_del_timer(s->update_timer); + return; + } if ((s->cmos_data[RTC_REG_C] & REG_C_UF) && (s->cmos_data[RTC_REG_B] & REG_B_SET)) { qemu_del_timer(s->update_timer); @@ -268,6 +278,8 @@ static void rtc_update_timer(void *opaque) int32_t irqs = REG_C_UF; int32_t new_irqs; + assert((s->cmos_data[RTC_REG_A] & 0x60) != 0x60); + /* UIP might have been latched, update time and clear it. */ rtc_update_time(s); s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; @@ -312,12 +324,31 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) case RTC_YEAR: s->cmos_data[s->cmos_index] = data; /* if in set mode, do not update the time */ - if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { + if (rtc_running(s)) { rtc_set_time(s); check_update_timer(s); } break; case RTC_REG_A: + if ((data & 0x60) == 0x60) { + if (rtc_running(s)) { + rtc_update_time(s); + } + /* What happens to UIP when divider reset is enabled is + * unclear from the datasheet. Shouldn't matter much + * though. + */ + s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; + } else if (((s->cmos_data[RTC_REG_A] & 0x60) == 0x60) && + (data & 0x70) <= 0x20) { + /* when the divider reset is removed, the first update cycle + * begins one-half second later*/ + if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { + s->offset = 500000000; + rtc_set_time(s); + } + s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; + } /* UIP bit is read only */ s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) | (s->cmos_data[RTC_REG_A] & REG_A_UIP); @@ -327,7 +358,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) case RTC_REG_B: if (data & REG_B_SET) { /* update cmos to when the rtc was stopping */ - if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { + if (rtc_running(s)) { rtc_update_time(s); } /* set mode: reset UIP mode */ @@ -335,7 +366,8 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) data &= ~REG_B_UIE; } else { /* if disabling set mode, update the time */ - if (s->cmos_data[RTC_REG_B] & REG_B_SET) { + if ((s->cmos_data[RTC_REG_B] & REG_B_SET) && + (s->cmos_data[RTC_REG_A] & 0x70) <= 0x20) { s->offset = get_guest_rtc_ns(s) % NSEC_PER_SEC; rtc_set_time(s); } @@ -449,7 +481,7 @@ static int update_in_progress(RTCState *s) { int64_t guest_nsec; - if (s->cmos_data[RTC_REG_B] & REG_B_SET) { + if (!rtc_running(s)) { return 0; } if (qemu_timer_pending(s->update_timer)) { @@ -486,7 +518,7 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr) case RTC_YEAR: /* if not in set mode, calibrate cmos before * reading*/ - if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { + if (rtc_running(s)) { rtc_update_time(s); } ret = s->cmos_data[s->cmos_index]; From 00cf57747db98c6a9e4219cea39ac3113dde6993 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 2 Aug 2012 18:04:11 +0200 Subject: [PATCH 0245/2270] RTC: Do not fire timer periodically to catch next alarm This patch limits further the usage of a periodic timer. It computes the time of the next alarm, and uses it to skip all intermediate occurrences of the timer. Cc: Yang Zhang Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- hw/mc146818rtc.c | 119 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 104 insertions(+), 15 deletions(-) diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index cb65c4f9ea..9d530a8a12 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -46,6 +46,11 @@ #endif #define NSEC_PER_SEC 1000000000LL +#define SEC_PER_MIN 60 +#define MIN_PER_HOUR 60 +#define SEC_PER_HOUR 3600 +#define HOUR_PER_DAY 24 +#define SEC_PER_DAY 86400 #define RTC_REINJECT_ON_ACK_COUNT 20 #define RTC_CLOCK_RATE 32768 @@ -69,6 +74,7 @@ typedef struct RTCState { int64_t next_periodic_time; /* update-ended timer */ QEMUTimer *update_timer; + uint64_t next_alarm_time; uint16_t irq_reinject_on_ack_count; uint32_t irq_coalesced; uint32_t period; @@ -82,6 +88,7 @@ static void rtc_set_time(RTCState *s); static void rtc_update_time(RTCState *s); static void rtc_set_cmos(RTCState *s); static inline int rtc_from_bcd(RTCState *s, int a); +static uint64_t get_next_alarm(RTCState *s); static inline bool rtc_running(RTCState *s) { @@ -204,6 +211,7 @@ static void check_update_timer(RTCState *s) { uint64_t next_update_time; uint64_t guest_nsec; + int next_alarm_sec; /* From the data sheet: "Holding the dividers in reset prevents * interrupts from operating, while setting the SET bit allows" @@ -226,9 +234,21 @@ static void check_update_timer(RTCState *s) } guest_nsec = get_guest_rtc_ns(s) % NSEC_PER_SEC; - /* reprogram to next second */ + /* if UF is clear, reprogram to next second */ next_update_time = qemu_get_clock_ns(rtc_clock) + NSEC_PER_SEC - guest_nsec; + + /* Compute time of next alarm. One second is already accounted + * for in next_update_time. + */ + next_alarm_sec = get_next_alarm(s); + s->next_alarm_time = next_update_time + (next_alarm_sec - 1) * NSEC_PER_SEC; + + if (s->cmos_data[RTC_REG_C] & REG_C_UF) { + /* UF is set, but AF is clear. Program the timer to target + * the alarm time. */ + next_update_time = s->next_alarm_time; + } if (next_update_time != qemu_timer_expire_time_ns(s->update_timer)) { qemu_mod_timer(s->update_timer, next_update_time); } @@ -245,31 +265,95 @@ static inline uint8_t convert_hour(RTCState *s, uint8_t hour) return hour; } -static uint32_t check_alarm(RTCState *s) +static uint64_t get_next_alarm(RTCState *s) { - uint8_t alarm_hour, alarm_min, alarm_sec; - uint8_t cur_hour, cur_min, cur_sec; + int32_t alarm_sec, alarm_min, alarm_hour, cur_hour, cur_min, cur_sec; + int32_t hour, min, sec; + + rtc_update_time(s); alarm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]); alarm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]); alarm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]); - alarm_hour = convert_hour(s, alarm_hour); + alarm_hour = alarm_hour == -1 ? -1 : convert_hour(s, alarm_hour); cur_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]); cur_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]); cur_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS]); cur_hour = convert_hour(s, cur_hour); - if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 - || alarm_sec == cur_sec) && - ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 - || alarm_min == cur_min) && - ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 - || alarm_hour == cur_hour)) { - return 1; - } - return 0; + if (alarm_hour == -1) { + alarm_hour = cur_hour; + if (alarm_min == -1) { + alarm_min = cur_min; + if (alarm_sec == -1) { + alarm_sec = cur_sec + 1; + } else if (cur_sec > alarm_sec) { + alarm_min++; + } + } else if (cur_min == alarm_min) { + if (alarm_sec == -1) { + alarm_sec = cur_sec + 1; + } else { + if (cur_sec > alarm_sec) { + alarm_hour++; + } + } + if (alarm_sec == SEC_PER_MIN) { + /* wrap to next hour, minutes is not in don't care mode */ + alarm_sec = 0; + alarm_hour++; + } + } else if (cur_min > alarm_min) { + alarm_hour++; + } + } else if (cur_hour == alarm_hour) { + if (alarm_min == -1) { + alarm_min = cur_min; + if (alarm_sec == -1) { + alarm_sec = cur_sec + 1; + } else if (cur_sec > alarm_sec) { + alarm_min++; + } + if (alarm_sec == SEC_PER_MIN) { + alarm_sec = 0; + alarm_min++; + } + /* wrap to next day, hour is not in don't care mode */ + alarm_min %= MIN_PER_HOUR; + } else if (cur_min == alarm_min) { + if (alarm_sec == -1) { + alarm_sec = cur_sec + 1; + } + /* wrap to next day, hours+minutes not in don't care mode */ + alarm_sec %= SEC_PER_MIN; + } + } + + /* values that are still don't care fire at the next min/sec */ + if (alarm_min == -1) { + alarm_min = 0; + } + if (alarm_sec == -1) { + alarm_sec = 0; + } + + /* keep values in range */ + if (alarm_sec == SEC_PER_MIN) { + alarm_sec = 0; + alarm_min++; + } + if (alarm_min == MIN_PER_HOUR) { + alarm_min = 0; + alarm_hour++; + } + alarm_hour %= HOUR_PER_DAY; + + hour = alarm_hour - cur_hour; + min = hour * MIN_PER_HOUR + alarm_min - cur_min; + sec = min * SEC_PER_MIN + alarm_sec - cur_sec; + return sec <= 0 ? sec + SEC_PER_DAY : sec; } static void rtc_update_timer(void *opaque) @@ -284,12 +368,13 @@ static void rtc_update_timer(void *opaque) rtc_update_time(s); s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; - if (check_alarm(s)) { + if (qemu_get_clock_ns(rtc_clock) >= s->next_alarm_time) { irqs |= REG_C_AF; if (s->cmos_data[RTC_REG_B] & REG_B_AIE) { qemu_system_wakeup_request(QEMU_WAKEUP_REASON_RTC); } } + new_irqs = irqs & ~s->cmos_data[RTC_REG_C]; s->cmos_data[RTC_REG_C] |= irqs; if ((new_irqs & s->cmos_data[RTC_REG_B]) != 0) { @@ -407,6 +492,9 @@ static inline int rtc_to_bcd(RTCState *s, int a) static inline int rtc_from_bcd(RTCState *s, int a) { + if ((a & 0xc0) == 0xc0) { + return -1; + } if (s->cmos_data[RTC_REG_B] & REG_B_DM) { return a; } else { @@ -642,6 +730,7 @@ static const VMStateDescription vmstate_rtc = { VMSTATE_UINT64_V(last_update, RTCState, 3), VMSTATE_INT64_V(offset, RTCState, 3), VMSTATE_TIMER_V(update_timer, RTCState, 3), + VMSTATE_UINT64_V(next_alarm_time, RTCState, 3), VMSTATE_END_OF_LIST() } }; From e2826cf4a8c89d64cdf8304f861910293f046aa8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 2 Aug 2012 18:04:12 +0200 Subject: [PATCH 0246/2270] RTC: Get and set time without going through s->current_tm This patch makes rtc_set_time and rtc_set_cmos work without reading s->current_tm. In the case of rtc_set_time I introduce a new function that retrieves the time and stores into a given struct tm (not hard-coded to s->current_tm). In the case of rtc_set_cmos, the current time is similarly taken from a struct tm rather than s->current_tm. Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- hw/mc146818rtc.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index 9d530a8a12..a609f721a3 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -86,7 +86,7 @@ typedef struct RTCState { static void rtc_set_time(RTCState *s); static void rtc_update_time(RTCState *s); -static void rtc_set_cmos(RTCState *s); +static void rtc_set_cmos(RTCState *s, const struct tm *tm); static inline int rtc_from_bcd(RTCState *s, int a); static uint64_t get_next_alarm(RTCState *s); @@ -502,10 +502,8 @@ static inline int rtc_from_bcd(RTCState *s, int a) } } -static void rtc_set_time(RTCState *s) +static void rtc_get_time(RTCState *s, struct tm *tm) { - struct tm *tm = &s->current_tm; - tm->tm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]); tm->tm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]); tm->tm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f); @@ -519,16 +517,22 @@ static void rtc_set_time(RTCState *s) tm->tm_mday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]); tm->tm_mon = rtc_from_bcd(s, s->cmos_data[RTC_MONTH]) - 1; tm->tm_year = rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900; - - s->base_rtc = mktimegm(tm); - s->last_update = qemu_get_clock_ns(rtc_clock); - - rtc_change_mon_event(tm); } -static void rtc_set_cmos(RTCState *s) +static void rtc_set_time(RTCState *s) +{ + struct tm tm; + + rtc_get_time(s, &tm); + s->current_tm = tm; + s->base_rtc = mktimegm(&tm); + s->last_update = qemu_get_clock_ns(rtc_clock); + + rtc_change_mon_event(&tm); +} + +static void rtc_set_cmos(RTCState *s, const struct tm *tm) { - const struct tm *tm = &s->current_tm; int year; s->cmos_data[RTC_SECONDS] = rtc_to_bcd(s, tm->tm_sec); @@ -561,8 +565,8 @@ static void rtc_update_time(RTCState *s) guest_nsec = get_guest_rtc_ns(s); guest_sec = guest_nsec / NSEC_PER_SEC; gmtime_r(&guest_sec, &ret); + rtc_set_cmos(s, &ret); s->current_tm = ret; - rtc_set_cmos(s); } static int update_in_progress(RTCState *s) @@ -677,8 +681,8 @@ static void rtc_set_date_from_host(ISADevice *dev) s->offset = 0; /* set the CMOS date */ + rtc_set_cmos(s, &tm); s->current_tm = tm; - rtc_set_cmos(s); val = rtc_to_bcd(s, (tm.tm_year / 100) + 19); rtc_set_memory(dev, REG_IBM_CENTURY_BYTE, val); @@ -789,15 +793,17 @@ static void rtc_get_date(Object *obj, Visitor *v, void *opaque, { ISADevice *isa = ISA_DEVICE(obj); RTCState *s = DO_UPCAST(RTCState, dev, isa); + struct tm current_tm; rtc_update_time(s); + rtc_get_time(s, ¤t_tm); visit_start_struct(v, NULL, "struct tm", name, 0, errp); - visit_type_int32(v, &s->current_tm.tm_year, "tm_year", errp); - visit_type_int32(v, &s->current_tm.tm_mon, "tm_mon", errp); - visit_type_int32(v, &s->current_tm.tm_mday, "tm_mday", errp); - visit_type_int32(v, &s->current_tm.tm_hour, "tm_hour", errp); - visit_type_int32(v, &s->current_tm.tm_min, "tm_min", errp); - visit_type_int32(v, &s->current_tm.tm_sec, "tm_sec", errp); + visit_type_int32(v, ¤t_tm.tm_year, "tm_year", errp); + visit_type_int32(v, ¤t_tm.tm_mon, "tm_mon", errp); + visit_type_int32(v, ¤t_tm.tm_mday, "tm_mday", errp); + visit_type_int32(v, ¤t_tm.tm_hour, "tm_hour", errp); + visit_type_int32(v, ¤t_tm.tm_min, "tm_min", errp); + visit_type_int32(v, ¤t_tm.tm_sec, "tm_sec", errp); visit_end_struct(v, errp); } From 89166459065353c6a49456794f840ffe57016020 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 2 Aug 2012 18:04:13 +0200 Subject: [PATCH 0247/2270] RTC: Remove the current_tm field This is not used anymore and only written to. Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- hw/mc146818rtc.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index a609f721a3..d63554f896 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -61,7 +61,6 @@ typedef struct RTCState { MemoryRegion io; uint8_t cmos_data[128]; uint8_t cmos_index; - struct tm current_tm; int32_t base_year; uint64_t base_rtc; uint64_t last_update; @@ -524,7 +523,6 @@ static void rtc_set_time(RTCState *s) struct tm tm; rtc_get_time(s, &tm); - s->current_tm = tm; s->base_rtc = mktimegm(&tm); s->last_update = qemu_get_clock_ns(rtc_clock); @@ -566,7 +564,6 @@ static void rtc_update_time(RTCState *s) guest_sec = guest_nsec / NSEC_PER_SEC; gmtime_r(&guest_sec, &ret); rtc_set_cmos(s, &ret); - s->current_tm = ret; } static int update_in_progress(RTCState *s) @@ -682,7 +679,6 @@ static void rtc_set_date_from_host(ISADevice *dev) /* set the CMOS date */ rtc_set_cmos(s, &tm); - s->current_tm = tm; val = rtc_to_bcd(s, (tm.tm_year / 100) + 19); rtc_set_memory(dev, REG_IBM_CENTURY_BYTE, val); @@ -718,13 +714,7 @@ static const VMStateDescription vmstate_rtc = { .fields = (VMStateField []) { VMSTATE_BUFFER(cmos_data, RTCState), VMSTATE_UINT8(cmos_index, RTCState), - VMSTATE_INT32(current_tm.tm_sec, RTCState), - VMSTATE_INT32(current_tm.tm_min, RTCState), - VMSTATE_INT32(current_tm.tm_hour, RTCState), - VMSTATE_INT32(current_tm.tm_wday, RTCState), - VMSTATE_INT32(current_tm.tm_mday, RTCState), - VMSTATE_INT32(current_tm.tm_mon, RTCState), - VMSTATE_INT32(current_tm.tm_year, RTCState), + VMSTATE_UNUSED(7*4), VMSTATE_TIMER(periodic_timer, RTCState), VMSTATE_INT64(next_periodic_time, RTCState), VMSTATE_UNUSED(3*8), From 66d5499b3754b83c09487259c08fe2ce73188a59 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Mon, 10 Sep 2012 12:27:21 +0100 Subject: [PATCH 0248/2270] Add ability to disable build of all targets Allow passing of '--target-list=' to configure to request that all targets are to be disabled. This allows for doing a very fast tools-only build of things like qemu-img, qemu-io, qemu-nbd. Signed-off-by: Daniel P. Berrange Signed-off-by: Anthony Liguori --- configure | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/configure b/configure index 2e4a3b00fa..76289bcc1e 100755 --- a/configure +++ b/configure @@ -127,7 +127,7 @@ cc_i386=i386-pc-linux-gnu-gcc libs_qga="" debug_info="yes" -target_list="" +target_list="DEFAULT" # Default value for a variable defining feature "foo". # * foo="no" feature will only be used if --enable-foo arg is given @@ -1317,15 +1317,10 @@ if ! "$python" -c 'import sys; sys.exit(sys.version_info < (2,4) or sys.version_ exit 1 fi -if test -z "$target_list" ; then - target_list="$default_target_list" -else - target_list=`echo "$target_list" | sed -e 's/,/ /g'` -fi -if test -z "$target_list" ; then - echo "No targets enabled" - exit 1 +if test "$target_list" = "DEFAULT" ; then + target_list=`echo "$default_target_list" | sed -e 's/,/ /g'` fi + # see if system emulation was really requested case " $target_list " in *"-softmmu "*) softmmu=yes From 4b1c11fd20e8901f04a2d9c225cd10fc05a762ff Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Mon, 10 Sep 2012 12:26:29 +0100 Subject: [PATCH 0249/2270] Add ability to force enable/disable of tools build The qemu-img, qemu-nbd and qemu-io tools are built conditionally based on whether any softmmu target is enabled. These are useful self-contained tools which can be used in many other scenarios. Add new --enable-tools/--disable-tools args to configure to allow the user to explicitly turn on / off their build. The default behaviour is now to build these tools are all times, regardless of whether any softmmu target is enabled Signed-off-by: Daniel P. Berrange Signed-off-by: Anthony Liguori --- configure | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/configure b/configure index 76289bcc1e..30be78488e 100755 --- a/configure +++ b/configure @@ -217,6 +217,7 @@ usb_redir="" opengl="" zlib="yes" guest_agent="yes" +want_tools="yes" libiscsi="" coroutine="" seccomp="" @@ -868,6 +869,10 @@ for opt do ;; --disable-guest-agent) guest_agent="no" ;; + --enable-tools) want_tools="yes" + ;; + --disable-tools) want_tools="no" + ;; --enable-seccomp) seccomp="yes" ;; --disable-seccomp) seccomp="no" @@ -3043,9 +3048,14 @@ fi qemu_confdir=$sysconfdir$confsuffix qemu_datadir=$datadir$confsuffix -tools= -if test "$softmmu" = yes ; then +tools="" +if test "$want_tools" = "yes" ; then tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools" + if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then + tools="qemu-nbd\$(EXESUF) $tools" + fi +fi +if test "$softmmu" = yes ; then if test "$virtfs" != no ; then if test "$cap" = yes && test "$linux" = yes && test "$attr" = yes ; then virtfs=yes @@ -3059,14 +3069,13 @@ if test "$softmmu" = yes ; then fi fi if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then - tools="qemu-nbd\$(EXESUF) $tools" if [ "$guest_agent" = "yes" ]; then tools="qemu-ga\$(EXESUF) $tools" fi fi -fi -if test "$smartcard_nss" = "yes" ; then - tools="vscclient\$(EXESUF) $tools" + if test "$smartcard_nss" = "yes" ; then + tools="vscclient\$(EXESUF) $tools" + fi fi # Mac OS X ships with a broken assembler From 45b339b18c660eb85af2ba25bfcaed5469660d77 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 17 Aug 2012 11:39:16 +0200 Subject: [PATCH 0250/2270] usb: controllers do not need to check for babble themselves If an (emulated) usb-device tries to write more data to a packet then its iov len, this will trigger an assert in usb_packet_copy(), and if a driver somehow circumvents that check and writes more data to the iov then there is space, we have a much bigger problem then not correctly reporting babble to the guest. In practice babble will only happen with (real) redirected devices, and there both the usb-host os and the qemu usb-device code already check for it. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 4 ---- hw/usb/hcd-uhci.c | 5 ----- 2 files changed, 9 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 017342b56a..95232472a3 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1481,10 +1481,6 @@ static void ehci_execute_complete(EHCIQueue *q) assert(0); break; } - } else if ((p->usb_status > p->tbytes) && (p->pid == USB_TOKEN_IN)) { - p->usb_status = USB_RET_BABBLE; - q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE); - ehci_raise_irq(q->ehci, USBSTS_ERRINT); } else { // TODO check 4.12 for splits diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index b0db92145a..c7c878635a 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -729,11 +729,6 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_ *int_mask |= 0x01; if (pid == USB_TOKEN_IN) { - if (len > max_len) { - ret = USB_RET_BABBLE; - goto out; - } - if ((td->ctrl & TD_CTRL_SPD) && len < max_len) { *int_mask |= 0x02; /* short packet: do not update QH */ From cc40997489260f405aecccd30d4626ceee862502 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 3 Sep 2012 12:33:44 +0200 Subject: [PATCH 0251/2270] usb-core: Don't set packet state to complete on a nak This way the hcd can re-use the same packet to retry without needing to re-init it. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/usb/core.c b/hw/usb/core.c index 2da38e7fd0..be6d936881 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -399,8 +399,10 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) * otherwise packets can complete out of order! */ assert(!p->ep->pipeline); - p->result = ret; - usb_packet_set_state(p, USB_PACKET_COMPLETE); + if (ret != USB_RET_NAK) { + p->result = ret; + usb_packet_set_state(p, USB_PACKET_COMPLETE); + } } } else { ret = USB_RET_ASYNC; From c13a9e61366cc3e28299d8faeb65e65c6e5964cf Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 28 Aug 2012 09:43:18 +0200 Subject: [PATCH 0252/2270] usb-core: Add a usb_ep_find_packet_by_id() helper function Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb.h | 2 ++ hw/usb/core.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/hw/usb.h b/hw/usb.h index b8fceec895..684e3f4b54 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -377,6 +377,8 @@ void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep, uint16_t raw); int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep); void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled); +USBPacket *usb_ep_find_packet_by_id(USBDevice *dev, int pid, int ep, + uint64_t id); void usb_attach(USBPort *port); void usb_detach(USBPort *port); diff --git a/hw/usb/core.c b/hw/usb/core.c index be6d936881..fe431d02d9 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -726,3 +726,18 @@ void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled) struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); uep->pipeline = enabled; } + +USBPacket *usb_ep_find_packet_by_id(USBDevice *dev, int pid, int ep, + uint64_t id) +{ + struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); + USBPacket *p; + + while ((p = QTAILQ_FIRST(&uep->queue)) != NULL) { + if (p->id == id) { + return p; + } + } + + return NULL; +} From 9c1f67654ab611553bbfca54a1e0922728c25760 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 3 Sep 2012 12:48:49 +0200 Subject: [PATCH 0253/2270] usb-core: Allow the first packet of a pipelined ep to complete immediately This can happen with usb-redir live-migration when the packet gets re-queued after the migration and the original queuing from the migration source side has already finished. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb/core.c b/hw/usb/core.c index fe431d02d9..b9f1f7a8be 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -398,7 +398,7 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) * When pipelining is enabled usb-devices must always return async, * otherwise packets can complete out of order! */ - assert(!p->ep->pipeline); + assert(!p->ep->pipeline || QTAILQ_EMPTY(&p->ep->queue)); if (ret != USB_RET_NAK) { p->result = ret; usb_packet_set_state(p, USB_PACKET_COMPLETE); From 66f092d25697e11847b61d761c38ddebedaed8d1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 29 Aug 2012 10:12:52 +0200 Subject: [PATCH 0254/2270] Revert "ehci: don't flush cache on doorbell rings." This reverts commit 9bc3a3a216e2689bfcdd36c3e079333bbdbf3ba0, which got added to fix an issue where the real, underlying cause was not stopping the ep queue on an error. Now that the underlying cause is fixed by the "usb: Halt ep queue and cancel pending packets on a packet error" patch, the "don't flush" fix is no longer needed. Not only is it not needed, it causes us to see cancellations (unlinks) done by the Linux EHCI driver too late, which in combination with the new usb-core packet-id generation where qtd addresses are used as ids, causes duplicate ids for in flight packets. Signed-off-by: Hans de Goede --- hw/usb/hcd-ehci.c | 35 ++++++----------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 95232472a3..e7c36f4155 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -365,7 +365,6 @@ struct EHCIQueue { uint32_t seen; uint64_t ts; int async; - int revalidate; /* cached data from guest - needs to be flushed * when guest removes an entry (doorbell, handshake sequence) @@ -805,18 +804,7 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr, return NULL; } -static void ehci_queues_tag_unused_async(EHCIState *ehci) -{ - EHCIQueue *q; - - QTAILQ_FOREACH(q, &ehci->aqueues, next) { - if (!q->seen) { - q->revalidate = 1; - } - } -} - -static void ehci_queues_rip_unused(EHCIState *ehci, int async) +static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush) { EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4; @@ -828,7 +816,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async) q->ts = ehci->last_run_ns; continue; } - if (ehci->last_run_ns < q->ts + maxage) { + if (!flush && ehci->last_run_ns < q->ts + maxage) { continue; } ehci_free_queue(q); @@ -1684,7 +1672,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci, int async) ehci_set_usbsts(ehci, USBSTS_REC); } - ehci_queues_rip_unused(ehci, async); + ehci_queues_rip_unused(ehci, async, 0); /* Find the head of the list (4.9.1.1) */ for(i = 0; i < MAX_QH; i++) { @@ -1769,7 +1757,6 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) EHCIPacket *p; uint32_t entry, devaddr; EHCIQueue *q; - EHCIqh qh; entry = ehci_get_fetch_addr(ehci, async); q = ehci_find_queue_by_qh(ehci, entry, async); @@ -1787,17 +1774,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) } get_dwords(ehci, NLPTR_GET(q->qhaddr), - (uint32_t *) &qh, sizeof(EHCIqh) >> 2); - if (q->revalidate && (q->qh.epchar != qh.epchar || - q->qh.epcap != qh.epcap || - q->qh.current_qtd != qh.current_qtd)) { - ehci_free_queue(q); - q = ehci_alloc_queue(ehci, entry, async); - q->seen++; - p = NULL; - } - q->qh = qh; - q->revalidate = 0; + (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2); ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh); devaddr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR); @@ -2306,7 +2283,7 @@ static void ehci_advance_async_state(EHCIState *ehci) */ if (ehci->usbcmd & USBCMD_IAAD) { /* Remove all unseen qhs from the async qhs queue */ - ehci_queues_tag_unused_async(ehci); + ehci_queues_rip_unused(ehci, async, 1); DPRINTF("ASYNC: doorbell request acknowledged\n"); ehci->usbcmd &= ~USBCMD_IAAD; ehci_raise_irq(ehci, USBSTS_IAA); @@ -2359,7 +2336,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci) ehci_set_fetch_addr(ehci, async,entry); ehci_set_state(ehci, async, EST_FETCHENTRY); ehci_advance_state(ehci, async); - ehci_queues_rip_unused(ehci, async); + ehci_queues_rip_unused(ehci, async, 0); break; default: From dafe31fc2a8653b535d58f8c7b250c0827b14420 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 29 Aug 2012 10:37:37 +0200 Subject: [PATCH 0255/2270] ehci: Validate qh is not changed unexpectedly by the guest -combine the qh check with the check for devaddr changes -also ensure that p gets set to NULL when the queue gets cancelled on devaddr change, which was not done properly before this patch Signed-off-by: Hans de Goede --- hw/usb/hcd-ehci.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index e7c36f4155..35eb441f1d 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -780,6 +780,14 @@ static void ehci_cancel_queue(EHCIQueue *q) } while ((p = QTAILQ_FIRST(&q->packets)) != NULL); } +static void ehci_reset_queue(EHCIQueue *q) +{ + trace_usb_ehci_queue_action(q, "reset"); + ehci_cancel_queue(q); + q->dev = NULL; + q->qtdaddr = 0; +} + static void ehci_free_queue(EHCIQueue *q) { EHCIQueueHead *head = q->async ? &q->ehci->aqueues : &q->ehci->pqueues; @@ -1755,8 +1763,9 @@ out: static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) { EHCIPacket *p; - uint32_t entry, devaddr; + uint32_t entry, devaddr, endp; EHCIQueue *q; + EHCIqh qh; entry = ehci_get_fetch_addr(ehci, async); q = ehci_find_queue_by_qh(ehci, entry, async); @@ -1774,17 +1783,25 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) } get_dwords(ehci, NLPTR_GET(q->qhaddr), - (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2); - ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh); + (uint32_t *) &qh, sizeof(EHCIqh) >> 2); + ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &qh); - devaddr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR); - if (q->dev != NULL && q->dev->addr != devaddr) { - if (!QTAILQ_EMPTY(&q->packets)) { - /* should not happen (guest bug) */ - ehci_cancel_queue(q); - } - q->dev = NULL; + /* + * The overlay area of the qh should never be changed by the guest, + * except when idle, in which case the reset is a nop. + */ + devaddr = get_field(qh.epchar, QH_EPCHAR_DEVADDR); + endp = get_field(qh.epchar, QH_EPCHAR_EP); + if ((devaddr != get_field(q->qh.epchar, QH_EPCHAR_DEVADDR)) || + (endp != get_field(q->qh.epchar, QH_EPCHAR_EP)) || + (memcmp(&qh.current_qtd, &q->qh.current_qtd, + 9 * sizeof(uint32_t)) != 0) || + (q->dev != NULL && q->dev->addr != devaddr)) { + ehci_reset_queue(q); + p = NULL; } + q->qh = qh; + if (q->dev == NULL) { q->dev = ehci_find_device(q->ehci, devaddr); } From 522079dd4461c38b9a88bf31a65ea038c5b2be45 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 28 Aug 2012 16:21:12 +0200 Subject: [PATCH 0256/2270] ehci: Update copyright headers to reflect recent work Update copyright headers to reflect all the work Gerd and I have been doing on the EHCI emulation. Signed-off-by: Hans de Goede --- hw/usb/hcd-ehci.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 35eb441f1d..78a248f08b 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -2,6 +2,11 @@ * QEMU USB EHCI Emulation * * Copyright(c) 2008 Emutex Ltd. (address@hidden) + * Copyright(c) 2011-2012 Red Hat, Inc. + * + * Red Hat Authors: + * Gerd Hoffmann + * Hans de Goede * * EHCI project was started by Mark Burkley, with contributions by * Niels de Vos. David S. Ahern continued working on it. Kevin Wolf, From 0e7953525f52aa6c098dc0c1ce0b4a80ce82da45 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 30 Aug 2012 15:00:33 +0200 Subject: [PATCH 0257/2270] ehci: Properly cleanup packets on cancel Signed-off-by: Hans de Goede --- hw/usb/hcd-ehci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 78a248f08b..4fe85c8ef7 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -747,6 +747,8 @@ static void ehci_free_packet(EHCIPacket *p) trace_usb_ehci_packet_action(p->queue, p, "free"); if (p->async == EHCI_ASYNC_INFLIGHT) { usb_cancel_packet(&p->packet); + usb_packet_unmap(&p->packet, &p->sgl); + qemu_sglist_destroy(&p->sgl); } QTAILQ_REMOVE(&p->queue->packets, p, next); usb_packet_cleanup(&p->packet); From 4b63a0df3bda8a2c278e45d9d94d9ba6d5791d8d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 30 Aug 2012 15:18:24 +0200 Subject: [PATCH 0258/2270] ehci: Properly report completed but not yet processed packets to the guest Reported packets which have completed before being cancelled as such to the host. Note that the new code path this patch adds is untested since it I've been unable to actually trigger the race which needs this code path. Signed-off-by: Hans de Goede --- hw/usb/hcd-ehci.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 4fe85c8ef7..0a6c9ef192 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -489,6 +489,9 @@ static const char *ehci_mmio_names[] = { [CONFIGFLAG] = "CONFIGFLAG", }; +static int ehci_state_executing(EHCIQueue *q); +static int ehci_state_writeback(EHCIQueue *q); + static const char *nr2str(const char **n, size_t len, uint32_t nr) { if (nr < len && n[nr] != NULL) { @@ -750,6 +753,16 @@ static void ehci_free_packet(EHCIPacket *p) usb_packet_unmap(&p->packet, &p->sgl); qemu_sglist_destroy(&p->sgl); } + if (p->async == EHCI_ASYNC_FINISHED) { + int state = ehci_get_state(p->queue->ehci, p->queue->async); + /* This is a normal, but rare condition (cancel racing completion) */ + fprintf(stderr, "EHCI: Warning packet completed but not processed\n"); + ehci_state_executing(p->queue); + ehci_state_writeback(p->queue); + ehci_set_state(p->queue->ehci, p->queue->async, state); + /* state_writeback recurses into us with async == EHCI_ASYNC_NONE!! */ + return; + } QTAILQ_REMOVE(&p->queue->packets, p, next); usb_packet_cleanup(&p->packet); g_free(p); From 616789cde2a83fad5e634880fd20214f0c984fd5 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 31 Aug 2012 10:31:54 +0200 Subject: [PATCH 0259/2270] ehci: check for EHCI_ASYNC_FINISHED first in ehci_free_packet Otherwise we'll see the packet free twice in the trace log even though it actually happens only once. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 0a6c9ef192..23221d0c01 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -747,12 +747,6 @@ static EHCIPacket *ehci_alloc_packet(EHCIQueue *q) static void ehci_free_packet(EHCIPacket *p) { - trace_usb_ehci_packet_action(p->queue, p, "free"); - if (p->async == EHCI_ASYNC_INFLIGHT) { - usb_cancel_packet(&p->packet); - usb_packet_unmap(&p->packet, &p->sgl); - qemu_sglist_destroy(&p->sgl); - } if (p->async == EHCI_ASYNC_FINISHED) { int state = ehci_get_state(p->queue->ehci, p->queue->async); /* This is a normal, but rare condition (cancel racing completion) */ @@ -763,6 +757,12 @@ static void ehci_free_packet(EHCIPacket *p) /* state_writeback recurses into us with async == EHCI_ASYNC_NONE!! */ return; } + trace_usb_ehci_packet_action(p->queue, p, "free"); + if (p->async == EHCI_ASYNC_INFLIGHT) { + usb_cancel_packet(&p->packet); + usb_packet_unmap(&p->packet, &p->sgl); + qemu_sglist_destroy(&p->sgl); + } QTAILQ_REMOVE(&p->queue->packets, p, next); usb_packet_cleanup(&p->packet); g_free(p); From 5c514681abbb3ae2f61f517c1aa3197f2f3ca93c Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 31 Aug 2012 10:44:21 +0200 Subject: [PATCH 0260/2270] ehci: trace guest bugs make qemu_queue_{cancel,reset} return the number of packets released, so the caller can figure whenever there have been active packets even though there shouldn't have been any. Add tracepoint to log this. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 26 ++++++++++++++++++++------ trace-events | 1 + 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 23221d0c01..4564615e05 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -716,6 +716,12 @@ static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr, (bool)(sitd->results & SITD_RESULTS_ACTIVE)); } +static void ehci_trace_guest_bug(EHCIState *s, const char *message) +{ + trace_usb_ehci_guest_bug(message); + fprintf(stderr, "ehci warning: %s\n", message); +} + static inline bool ehci_enabled(EHCIState *s) { return s->usbcmd & USBCMD_RUNSTOP; @@ -785,27 +791,33 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint32_t addr, int async) return q; } -static void ehci_cancel_queue(EHCIQueue *q) +static int ehci_cancel_queue(EHCIQueue *q) { EHCIPacket *p; + int packets = 0; p = QTAILQ_FIRST(&q->packets); if (p == NULL) { - return; + return 0; } trace_usb_ehci_queue_action(q, "cancel"); do { ehci_free_packet(p); + packets++; } while ((p = QTAILQ_FIRST(&q->packets)) != NULL); + return packets; } -static void ehci_reset_queue(EHCIQueue *q) +static int ehci_reset_queue(EHCIQueue *q) { + int packets; + trace_usb_ehci_queue_action(q, "reset"); - ehci_cancel_queue(q); + packets = ehci_cancel_queue(q); q->dev = NULL; q->qtdaddr = 0; + return packets; } static void ehci_free_queue(EHCIQueue *q) @@ -1817,7 +1829,9 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) (memcmp(&qh.current_qtd, &q->qh.current_qtd, 9 * sizeof(uint32_t)) != 0) || (q->dev != NULL && q->dev->addr != devaddr)) { - ehci_reset_queue(q); + if (ehci_reset_queue(q) > 0) { + ehci_trace_guest_bug(ehci, "guest updated active QH"); + } p = NULL; } q->qh = qh; @@ -1979,8 +1993,8 @@ static int ehci_state_fetchqtd(EHCIQueue *q) (!NLPTR_TBIT(p->qtd.next) && (p->qtd.next != qtd.next)) || (!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd.altnext)) || p->qtd.bufptr[0] != qtd.bufptr[0]) { - /* guest bug: guest updated active QH or qTD underneath us */ ehci_cancel_queue(q); + ehci_trace_guest_bug(q->ehci, "guest updated active QH or qTD"); p = NULL; } else { p->qtd = qtd; diff --git a/trace-events b/trace-events index 8fcbc50f92..5112a474e0 100644 --- a/trace-events +++ b/trace-events @@ -263,6 +263,7 @@ usb_ehci_data(int rw, uint32_t cpage, uint32_t offset, uint32_t addr, uint32_t l usb_ehci_queue_action(void *q, const char *action) "q %p: %s" usb_ehci_packet_action(void *q, void *p, const char *action) "q %p p %p: %s" usb_ehci_irq(uint32_t level, uint32_t frindex, uint32_t sts, uint32_t mask) "level %d, frindex 0x%04x, sts 0x%x, mask 0x%x" +usb_ehci_guest_bug(const char *reason) "%s" # hw/usb/hcd-uhci.c usb_uhci_reset(void) "=== RESET ===" From 1defcbd1e81d67476b6e4e486bcd4d869162900d Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 31 Aug 2012 12:41:43 +0200 Subject: [PATCH 0261/2270] ehci: add doorbell trace events Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 3 ++- trace-events | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 4564615e05..398f5e09fb 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1241,6 +1241,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) */ s->async_stepdown = 0; qemu_bh_schedule(s->async_bh); + trace_usb_ehci_doorbell_ring(); } if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) != @@ -2335,7 +2336,7 @@ static void ehci_advance_async_state(EHCIState *ehci) if (ehci->usbcmd & USBCMD_IAAD) { /* Remove all unseen qhs from the async qhs queue */ ehci_queues_rip_unused(ehci, async, 1); - DPRINTF("ASYNC: doorbell request acknowledged\n"); + trace_usb_ehci_doorbell_ack(); ehci->usbcmd &= ~USBCMD_IAAD; ehci_raise_irq(ehci, USBSTS_IAA); } diff --git a/trace-events b/trace-events index 5112a474e0..10bc04eac9 100644 --- a/trace-events +++ b/trace-events @@ -264,6 +264,8 @@ usb_ehci_queue_action(void *q, const char *action) "q %p: %s" usb_ehci_packet_action(void *q, void *p, const char *action) "q %p p %p: %s" usb_ehci_irq(uint32_t level, uint32_t frindex, uint32_t sts, uint32_t mask) "level %d, frindex 0x%04x, sts 0x%x, mask 0x%x" usb_ehci_guest_bug(const char *reason) "%s" +usb_ehci_doorbell_ring(void) "" +usb_ehci_doorbell_ack(void) "" # hw/usb/hcd-uhci.c usb_uhci_reset(void) "=== RESET ===" From 3a8ca08e01ea4baafff2a513655008cdd00feebf Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 3 Sep 2012 10:22:16 +0200 Subject: [PATCH 0262/2270] ehci: Add some additional ehci_trace_guest_bug() calls Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 398f5e09fb..5a882687f0 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -820,12 +820,16 @@ static int ehci_reset_queue(EHCIQueue *q) return packets; } -static void ehci_free_queue(EHCIQueue *q) +static void ehci_free_queue(EHCIQueue *q, const char *warn) { EHCIQueueHead *head = q->async ? &q->ehci->aqueues : &q->ehci->pqueues; + int cancelled; trace_usb_ehci_queue_action(q, "free"); - ehci_cancel_queue(q); + cancelled = ehci_cancel_queue(q); + if (warn && cancelled > 0) { + ehci_trace_guest_bug(q->ehci, warn); + } QTAILQ_REMOVE(head, q, next); g_free(q); } @@ -847,6 +851,7 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr, static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush) { EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; + const char *warn = (async && !flush) ? "guest unlinked busy QH" : NULL; uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4; EHCIQueue *q, *tmp; @@ -859,7 +864,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush) if (!flush && ehci->last_run_ns < q->ts + maxage) { continue; } - ehci_free_queue(q); + ehci_free_queue(q, warn); } } @@ -872,17 +877,18 @@ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async) if (q->dev != dev) { continue; } - ehci_free_queue(q); + ehci_free_queue(q, NULL); } } static void ehci_queues_rip_all(EHCIState *ehci, int async) { EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; + const char *warn = async ? "guest stopped busy async schedule" : NULL; EHCIQueue *q, *tmp; QTAILQ_FOREACH_SAFE(q, head, next, tmp) { - ehci_free_queue(q); + ehci_free_queue(q, warn); } } @@ -1549,7 +1555,8 @@ static int ehci_execute(EHCIPacket *p, const char *action) p->tbytes = (p->qtd.token & QTD_TOKEN_TBYTES_MASK) >> QTD_TOKEN_TBYTES_SH; if (p->tbytes > BUFF_SIZE) { - fprintf(stderr, "Request for more bytes than allowed\n"); + ehci_trace_guest_bug(p->queue->ehci, + "guest requested more bytes than allowed"); return USB_RET_PROCERR; } From ef5b234477df80700b128f561f5877a0688a70c8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 3 Sep 2012 11:01:13 +0200 Subject: [PATCH 0263/2270] ehci: Fix memory leak in handling of NAK-ed packets Currently each time we try to execute a NAK-ed packet we redo ehci_init_transfer, and usb_packet_map, re-allocing (without freeing) the sg list every time. This patch fixes this, it does this by introducing another async state, so that we also properly cleanup a NAK-ed packet on cancel. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 5a882687f0..d87aca8331 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -345,6 +345,7 @@ typedef struct EHCIState EHCIState; enum async_state { EHCI_ASYNC_NONE = 0, + EHCI_ASYNC_INITIALIZED, EHCI_ASYNC_INFLIGHT, EHCI_ASYNC_FINISHED, }; @@ -764,6 +765,10 @@ static void ehci_free_packet(EHCIPacket *p) return; } trace_usb_ehci_packet_action(p->queue, p, "free"); + if (p->async == EHCI_ASYNC_INITIALIZED) { + usb_packet_unmap(&p->packet, &p->sgl); + qemu_sglist_destroy(&p->sgl); + } if (p->async == EHCI_ASYNC_INFLIGHT) { usb_cancel_packet(&p->packet); usb_packet_unmap(&p->packet, &p->sgl); @@ -1485,8 +1490,8 @@ static void ehci_execute_complete(EHCIQueue *q) assert(p != NULL); assert(p->qtdaddr == q->qtdaddr); - assert(p->async != EHCI_ASYNC_INFLIGHT); - p->async = EHCI_ASYNC_NONE; + assert(p->async == EHCI_ASYNC_INITIALIZED || + p->async == EHCI_ASYNC_FINISHED); DPRINTF("execute_complete: qhaddr 0x%x, next %x, qtdaddr 0x%x, status %d\n", q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status); @@ -1531,6 +1536,7 @@ static void ehci_execute_complete(EHCIQueue *q) ehci_finish_transfer(q, p->usb_status); usb_packet_unmap(&p->packet, &p->sgl); qemu_sglist_destroy(&p->sgl); + p->async = EHCI_ASYNC_NONE; q->qh.token ^= QTD_TOKEN_DTOGGLE; q->qh.token &= ~QTD_TOKEN_ACTIVE; @@ -1548,6 +1554,9 @@ static int ehci_execute(EHCIPacket *p, const char *action) int ret; int endp; + assert(p->async == EHCI_ASYNC_NONE || + p->async == EHCI_ASYNC_INITIALIZED); + if (!(p->qtd.token & QTD_TOKEN_ACTIVE)) { fprintf(stderr, "Attempting to execute inactive qtd\n"); return USB_RET_PROCERR; @@ -1576,15 +1585,18 @@ static int ehci_execute(EHCIPacket *p, const char *action) break; } - if (ehci_init_transfer(p) != 0) { - return USB_RET_PROCERR; - } - endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP); ep = usb_ep_get(p->queue->dev, p->pid, endp); - usb_packet_setup(&p->packet, p->pid, ep, p->qtdaddr); - usb_packet_map(&p->packet, &p->sgl); + if (p->async == EHCI_ASYNC_NONE) { + if (ehci_init_transfer(p) != 0) { + return USB_RET_PROCERR; + } + + usb_packet_setup(&p->packet, p->pid, ep, p->qtdaddr); + usb_packet_map(&p->packet, &p->sgl); + p->async = EHCI_ASYNC_INITIALIZED; + } trace_usb_ehci_packet_action(p->queue, p, action); ret = usb_handle_packet(p->queue->dev, &p->packet); @@ -2021,11 +2033,15 @@ static int ehci_state_fetchqtd(EHCIQueue *q) } else if (p != NULL) { switch (p->async) { case EHCI_ASYNC_NONE: + /* Should never happen packet should at least be initialized */ + assert(0); + break; + case EHCI_ASYNC_INITIALIZED: /* Previously nacked packet (likely interrupt ep) */ - ehci_set_state(q->ehci, q->async, EST_EXECUTE); - break; + ehci_set_state(q->ehci, q->async, EST_EXECUTE); + break; case EHCI_ASYNC_INFLIGHT: - /* Unfinyshed async handled packet, go horizontal */ + /* Unfinished async handled packet, go horizontal */ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); break; case EHCI_ASYNC_FINISHED: From eff6dce79bd7ad3c16d75c5e55b5a2a137ba6a60 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 3 Sep 2012 11:35:58 +0200 Subject: [PATCH 0264/2270] ehci: Handle USB_RET_PROCERR in ehci_fill_queue USB_RET_PROCERR can be triggered by the guest (by for example requesting more then BUFFSIZE bytes), so don't assert on it. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index d87aca8331..2534394202 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -2076,7 +2076,7 @@ static int ehci_state_horizqh(EHCIQueue *q) return again; } -static void ehci_fill_queue(EHCIPacket *p) +static int ehci_fill_queue(EHCIPacket *p) { EHCIQueue *q = p->queue; EHCIqtd qtd = p->qtd; @@ -2100,9 +2100,13 @@ static void ehci_fill_queue(EHCIPacket *p) p->qtdaddr = qtdaddr; p->qtd = qtd; p->usb_status = ehci_execute(p, "queue"); + if (p->usb_status == USB_RET_PROCERR) { + break; + } assert(p->usb_status == USB_RET_ASYNC); p->async = EHCI_ASYNC_INFLIGHT; } + return p->usb_status; } static int ehci_state_execute(EHCIQueue *q) @@ -2144,8 +2148,7 @@ static int ehci_state_execute(EHCIQueue *q) trace_usb_ehci_packet_action(p->queue, p, "async"); p->async = EHCI_ASYNC_INFLIGHT; ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); - again = 1; - ehci_fill_queue(p); + again = (ehci_fill_queue(p) == USB_RET_PROCERR) ? -1 : 1; goto out; } From cf1f81691d1998fa8fe5bfcb8b498fb3723cf3c3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 3 Sep 2012 12:17:48 +0200 Subject: [PATCH 0265/2270] ehci: Correct a comment in fetchqtd packet processing Since my previous comment said "Should never happen", I tried changing the next line to an assert(0), which did not go well, which as the new comments explains is logical if you think about it for a moment. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 2534394202..2f3e9c03a1 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -2045,7 +2045,10 @@ static int ehci_state_fetchqtd(EHCIQueue *q) ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); break; case EHCI_ASYNC_FINISHED: - /* Should never happen, as this case is caught by fetchqh */ + /* + * We get here when advqueue moves to a packet which is already + * finished, which can happen with packets queued up by fill_queue + */ ehci_set_state(q->ehci, q->async, EST_EXECUTING); break; } From 181133404f520fab40a3ad40d935d91cf3cf546c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 17 Aug 2012 17:27:08 +0200 Subject: [PATCH 0266/2270] usb-redir: Never return USB_RET_NAK for async handled packets USB_RET_NAK is not a valid response for async handled packets (and will trigger an assert as such). Also drop the warning when receiving a status of cancelled for packets not cancelled by qemu itself, this can happen when a device gets unredirected by the usbredir-host while transfers are pending. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 10b4fbb3a7..7f3719b19a 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1028,11 +1028,14 @@ static int usbredir_handle_status(USBRedirDevice *dev, case usb_redir_stall: return USB_RET_STALL; case usb_redir_cancelled: - WARNING("returning cancelled packet to HC?\n"); - return USB_RET_NAK; + /* + * When the usbredir-host unredirects a device, it will report a status + * of cancelled for all pending packets, followed by a disconnect msg. + */ + return USB_RET_IOERROR; case usb_redir_inval: WARNING("got invalid param error from usb-host?\n"); - return USB_RET_NAK; + return USB_RET_IOERROR; case usb_redir_babble: return USB_RET_BABBLE; case usb_redir_ioerror: From ed9873bfbf145c084d039baab08c63b9d67e7bd3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 23 Aug 2012 16:37:19 +0200 Subject: [PATCH 0267/2270] usb-redir: Don't delay handling of open events to a bottom half There is no need for this, and doing so means that a backend trying to write immediately after an open event will see qemu_chr_be_can_write returning 0, which not all backends handle well as there is no wakeup mechanism to detect when the frontend does become writable. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 100 ++++++++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 47 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 7f3719b19a..5cc333490d 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -79,8 +79,8 @@ struct USBRedirDevice { /* Data passed from chardev the fd_read cb to the usbredirparser read cb */ const uint8_t *read_buf; int read_buf_size; - /* For async handling of open/close */ - QEMUBH *open_close_bh; + /* For async handling of close */ + QEMUBH *chardev_close_bh; /* To delay the usb attach in case of quick chardev close + open */ QEMUTimer *attach_timer; int64_t next_attach_time; @@ -784,18 +784,11 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p, * from within the USBDevice data / control packet callbacks and doing a * usb_detach from within these callbacks is not a good idea. * - * So we use a bh handler to take care of close events. We also handle - * open events from this callback to make sure that a close directly followed - * by an open gets handled in the right order. + * So we use a bh handler to take care of close events. */ -static void usbredir_open_close_bh(void *opaque) +static void usbredir_chardev_close_bh(void *opaque) { USBRedirDevice *dev = opaque; - uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, }; - char version[32]; - - strcpy(version, "qemu usb-redir guest "); - pstrcat(version, sizeof(version), qemu_get_version()); usbredir_device_disconnect(dev); @@ -803,36 +796,47 @@ static void usbredir_open_close_bh(void *opaque) usbredirparser_destroy(dev->parser); dev->parser = NULL; } +} - if (dev->cs->opened) { - dev->parser = qemu_oom_check(usbredirparser_create()); - dev->parser->priv = dev; - dev->parser->log_func = usbredir_log; - dev->parser->read_func = usbredir_read; - dev->parser->write_func = usbredir_write; - dev->parser->hello_func = usbredir_hello; - dev->parser->device_connect_func = usbredir_device_connect; - dev->parser->device_disconnect_func = usbredir_device_disconnect; - dev->parser->interface_info_func = usbredir_interface_info; - dev->parser->ep_info_func = usbredir_ep_info; - dev->parser->configuration_status_func = usbredir_configuration_status; - dev->parser->alt_setting_status_func = usbredir_alt_setting_status; - dev->parser->iso_stream_status_func = usbredir_iso_stream_status; - dev->parser->interrupt_receiving_status_func = - usbredir_interrupt_receiving_status; - dev->parser->bulk_streams_status_func = usbredir_bulk_streams_status; - dev->parser->control_packet_func = usbredir_control_packet; - dev->parser->bulk_packet_func = usbredir_bulk_packet; - dev->parser->iso_packet_func = usbredir_iso_packet; - dev->parser->interrupt_packet_func = usbredir_interrupt_packet; - dev->read_buf = NULL; - dev->read_buf_size = 0; +static void usbredir_chardev_open(USBRedirDevice *dev) +{ + uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, }; + char version[32]; - usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version); - usbredirparser_caps_set_cap(caps, usb_redir_cap_filter); - usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE, 0); - usbredirparser_do_write(dev->parser); - } + /* Make sure any pending closes are handled (no-op if none pending) */ + usbredir_chardev_close_bh(dev); + qemu_bh_cancel(dev->chardev_close_bh); + + strcpy(version, "qemu usb-redir guest "); + pstrcat(version, sizeof(version), qemu_get_version()); + + dev->parser = qemu_oom_check(usbredirparser_create()); + dev->parser->priv = dev; + dev->parser->log_func = usbredir_log; + dev->parser->read_func = usbredir_read; + dev->parser->write_func = usbredir_write; + dev->parser->hello_func = usbredir_hello; + dev->parser->device_connect_func = usbredir_device_connect; + dev->parser->device_disconnect_func = usbredir_device_disconnect; + dev->parser->interface_info_func = usbredir_interface_info; + dev->parser->ep_info_func = usbredir_ep_info; + dev->parser->configuration_status_func = usbredir_configuration_status; + dev->parser->alt_setting_status_func = usbredir_alt_setting_status; + dev->parser->iso_stream_status_func = usbredir_iso_stream_status; + dev->parser->interrupt_receiving_status_func = + usbredir_interrupt_receiving_status; + dev->parser->bulk_streams_status_func = usbredir_bulk_streams_status; + dev->parser->control_packet_func = usbredir_control_packet; + dev->parser->bulk_packet_func = usbredir_bulk_packet; + dev->parser->iso_packet_func = usbredir_iso_packet; + dev->parser->interrupt_packet_func = usbredir_interrupt_packet; + dev->read_buf = NULL; + dev->read_buf_size = 0; + + usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version); + usbredirparser_caps_set_cap(caps, usb_redir_cap_filter); + usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE, 0); + usbredirparser_do_write(dev->parser); } static void usbredir_do_attach(void *opaque) @@ -856,13 +860,13 @@ static int usbredir_chardev_can_read(void *opaque) { USBRedirDevice *dev = opaque; - if (dev->parser) { - /* usbredir_parser_do_read will consume *all* data we give it */ - return 1024 * 1024; - } else { - /* usbredir_open_close_bh hasn't handled the open event yet */ + if (!dev->parser) { + WARNING("chardev_can_read called on non open chardev!\n"); return 0; } + + /* usbredir_parser_do_read will consume *all* data we give it */ + return 1024 * 1024; } static void usbredir_chardev_read(void *opaque, const uint8_t *buf, int size) @@ -886,8 +890,10 @@ static void usbredir_chardev_event(void *opaque, int event) switch (event) { case CHR_EVENT_OPENED: + usbredir_chardev_open(dev); + break; case CHR_EVENT_CLOSED: - qemu_bh_schedule(dev->open_close_bh); + qemu_bh_schedule(dev->chardev_close_bh); break; } } @@ -917,7 +923,7 @@ static int usbredir_initfn(USBDevice *udev) } } - dev->open_close_bh = qemu_bh_new(usbredir_open_close_bh, dev); + dev->chardev_close_bh = qemu_bh_new(usbredir_chardev_close_bh, dev); dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev); QTAILQ_INIT(&dev->asyncq); @@ -957,7 +963,7 @@ static void usbredir_handle_destroy(USBDevice *udev) qemu_chr_fe_close(dev->cs); qemu_chr_delete(dev->cs); /* Note must be done after qemu_chr_close, as that causes a close event */ - qemu_bh_delete(dev->open_close_bh); + qemu_bh_delete(dev->chardev_close_bh); qemu_del_timer(dev->attach_timer); qemu_free_timer(dev->attach_timer); From cb897117cdedd488f19985c8ec5ea05971103a27 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 27 Aug 2012 16:33:08 +0200 Subject: [PATCH 0268/2270] usb-redir: Get rid of async-struct get member This is a preparation patch for completely getting rid of the async-packet struct in usb-redir, instead relying on the (new) per ep queues in the qemu usb core. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 5cc333490d..2cae8c5bb1 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1,7 +1,7 @@ /* * USB redirector usb-guest * - * Copyright (c) 2011 Red Hat, Inc. + * Copyright (c) 2011-2012 Red Hat, Inc. * * Red Hat Authors: * Hans de Goede @@ -99,7 +99,6 @@ struct AsyncURB { USBRedirDevice *dev; USBPacket *packet; uint32_t packet_id; - int get; union { struct usb_redir_control_packet_header control_packet; struct usb_redir_bulk_packet_header bulk_packet; @@ -672,7 +671,6 @@ static int usbredir_get_config(USBRedirDevice *dev, USBPacket *p) DPRINTF("get config id %u\n", aurb->packet_id); - aurb->get = 1; usbredirparser_send_get_configuration(dev->parser, aurb->packet_id); usbredirparser_do_write(dev->parser); return USB_RET_ASYNC; @@ -721,7 +719,6 @@ static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p, DPRINTF("get interface %d id %u\n", interface, aurb->packet_id); get_alt.interface = interface; - aurb->get = 1; usbredirparser_send_get_alt_setting(dev->parser, aurb->packet_id, &get_alt); usbredirparser_do_write(dev->parser); @@ -1226,7 +1223,7 @@ static void usbredir_configuration_status(void *priv, uint32_t id, return; } if (aurb->packet) { - if (aurb->get) { + if (dev->dev.setup_buf[0] & USB_DIR_IN) { dev->dev.data_buf[0] = config_status->configuration; len = 1; } @@ -1254,7 +1251,7 @@ static void usbredir_alt_setting_status(void *priv, uint32_t id, return; } if (aurb->packet) { - if (aurb->get) { + if (dev->dev.setup_buf[0] & USB_DIR_IN) { dev->dev.data_buf[0] = alt_setting_status->alt; len = 1; } From 104981d52b63dc3d68f39d4442881c667f44bbb9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 28 Aug 2012 09:05:38 +0200 Subject: [PATCH 0269/2270] usb-redir: Get rid of local shadow copy of packet headers The shadow copy only serves as an extra check (besides the packet-id) to ensure the packet we get back is a reply to the packet we think it is. This check has never triggered in all the time usb-redir is in use now, and since the verified data in the returned packet-header is not used otherwise, removing the check does not open any possibilities for the usbredirhost to confuse us. This is a preparation patch for completely getting rid of the async-packet struct in usb-redir, instead relying on the (new) per ep queues in the qemu usb core. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 2cae8c5bb1..e4ef372b11 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -99,11 +99,6 @@ struct AsyncURB { USBRedirDevice *dev; USBPacket *packet; uint32_t packet_id; - union { - struct usb_redir_control_packet_header control_packet; - struct usb_redir_bulk_packet_header bulk_packet; - struct usb_redir_interrupt_packet_header interrupt_packet; - }; QTAILQ_ENTRY(AsyncURB)next; }; @@ -500,7 +495,6 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p, bulk_packet.endpoint = ep; bulk_packet.length = p->iov.size; bulk_packet.stream_id = 0; - aurb->bulk_packet = bulk_packet; if (ep & USB_DIR_IN) { usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id, @@ -581,7 +575,6 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev, interrupt_packet.endpoint = ep; interrupt_packet.length = p->iov.size; - aurb->interrupt_packet = interrupt_packet; usb_packet_copy(p, buf, p->iov.size); usbredir_log_data(dev, "interrupt data out:", buf, p->iov.size); @@ -762,7 +755,6 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p, control_packet.value = value; control_packet.index = index; control_packet.length = length; - aurb->control_packet = control_packet; if (control_packet.requesttype & USB_DIR_IN) { usbredirparser_send_control_packet(dev->parser, aurb->packet_id, @@ -1326,14 +1318,6 @@ static void usbredir_control_packet(void *priv, uint32_t id, return; } - aurb->control_packet.status = control_packet->status; - aurb->control_packet.length = control_packet->length; - if (memcmp(&aurb->control_packet, control_packet, - sizeof(*control_packet))) { - ERROR("return control packet mismatch, please report this!\n"); - len = USB_RET_NAK; - } - if (aurb->packet) { len = usbredir_handle_status(dev, control_packet->status, len); if (len > 0) { @@ -1371,12 +1355,6 @@ static void usbredir_bulk_packet(void *priv, uint32_t id, return; } - if (aurb->bulk_packet.endpoint != bulk_packet->endpoint || - aurb->bulk_packet.stream_id != bulk_packet->stream_id) { - ERROR("return bulk packet mismatch, please report this!\n"); - len = USB_RET_NAK; - } - if (aurb->packet) { len = usbredir_handle_status(dev, bulk_packet->status, len); if (len > 0) { @@ -1455,11 +1433,6 @@ static void usbredir_interrupt_packet(void *priv, uint32_t id, return; } - if (aurb->interrupt_packet.endpoint != interrupt_packet->endpoint) { - ERROR("return int packet mismatch, please report this!\n"); - len = USB_RET_NAK; - } - if (aurb->packet) { aurb->packet->result = usbredir_handle_status(dev, interrupt_packet->status, len); From 206e7f20fe7b920b362bcc02608680c5d5527f2a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 28 Aug 2012 09:08:45 +0200 Subject: [PATCH 0270/2270] usb-redir: Get rid of unused async-struct dev member This is a preparation patch for completely getting rid of the async-packet struct in usb-redir, instead relying on the (new) per ep queues in the qemu usb core. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index e4ef372b11..6593d506b3 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -96,7 +96,6 @@ struct USBRedirDevice { }; struct AsyncURB { - USBRedirDevice *dev; USBPacket *packet; uint32_t packet_id; QTAILQ_ENTRY(AsyncURB)next; @@ -245,7 +244,6 @@ static int usbredir_write(void *priv, uint8_t *data, int count) static AsyncURB *async_alloc(USBRedirDevice *dev, USBPacket *p) { AsyncURB *aurb = (AsyncURB *) g_malloc0(sizeof(AsyncURB)); - aurb->dev = dev; aurb->packet = p; aurb->packet_id = dev->packet_id; QTAILQ_INSERT_TAIL(&dev->asyncq, aurb, next); From de550a6afb468ed3b8171019e19b63ae8254886d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 28 Aug 2012 11:30:13 +0200 Subject: [PATCH 0271/2270] usb-redir: Move to core packet id and queue handling Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 242 +++++++++++++++++++--------------------------- 1 file changed, 100 insertions(+), 142 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 6593d506b3..fd1f8cc510 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -43,7 +43,7 @@ #define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f)) #define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f)) -typedef struct AsyncURB AsyncURB; +typedef struct Cancelled Cancelled; typedef struct USBRedirDevice USBRedirDevice; /* Struct to hold buffered packets (iso or int input packets) */ @@ -86,8 +86,7 @@ struct USBRedirDevice { int64_t next_attach_time; struct usbredirparser *parser; struct endp_data endpoint[MAX_ENDPOINTS]; - uint32_t packet_id; - QTAILQ_HEAD(, AsyncURB) asyncq; + QTAILQ_HEAD(, Cancelled) cancelled; /* Data for device filtering */ struct usb_redir_device_connect_header device_info; struct usb_redir_interface_info_header interface_info; @@ -95,10 +94,9 @@ struct USBRedirDevice { int filter_rules_count; }; -struct AsyncURB { - USBPacket *packet; - uint32_t packet_id; - QTAILQ_ENTRY(AsyncURB)next; +struct Cancelled { + uint64_t id; + QTAILQ_ENTRY(Cancelled)next; }; static void usbredir_hello(void *priv, struct usb_redir_hello_header *h); @@ -238,57 +236,58 @@ static int usbredir_write(void *priv, uint8_t *data, int count) } /* - * Async and buffered packets helpers + * Cancelled and buffered packets helpers */ -static AsyncURB *async_alloc(USBRedirDevice *dev, USBPacket *p) -{ - AsyncURB *aurb = (AsyncURB *) g_malloc0(sizeof(AsyncURB)); - aurb->packet = p; - aurb->packet_id = dev->packet_id; - QTAILQ_INSERT_TAIL(&dev->asyncq, aurb, next); - dev->packet_id++; - - return aurb; -} - -static void async_free(USBRedirDevice *dev, AsyncURB *aurb) -{ - QTAILQ_REMOVE(&dev->asyncq, aurb, next); - g_free(aurb); -} - -static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id) -{ - AsyncURB *aurb; - - QTAILQ_FOREACH(aurb, &dev->asyncq, next) { - if (aurb->packet_id == packet_id) { - return aurb; - } - } - DPRINTF("could not find async urb for packet_id %u\n", packet_id); - return NULL; -} - static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p) { USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); - AsyncURB *aurb; + Cancelled *c; - QTAILQ_FOREACH(aurb, &dev->asyncq, next) { - if (p != aurb->packet) { - continue; - } + DPRINTF("cancel packet id %"PRIu64"\n", p->id); - DPRINTF("async cancel id %u\n", aurb->packet_id); - usbredirparser_send_cancel_data_packet(dev->parser, aurb->packet_id); - usbredirparser_do_write(dev->parser); + c = g_malloc0(sizeof(Cancelled)); + c->id = p->id; + QTAILQ_INSERT_TAIL(&dev->cancelled, c, next); - /* Mark it as dead */ - aurb->packet = NULL; - break; + usbredirparser_send_cancel_data_packet(dev->parser, p->id); + usbredirparser_do_write(dev->parser); +} + +static int usbredir_is_cancelled(USBRedirDevice *dev, uint64_t id) +{ + Cancelled *c; + + if (!dev->dev.attached) { + return 1; /* Treat everything as cancelled after a disconnect */ } + + QTAILQ_FOREACH(c, &dev->cancelled, next) { + if (c->id == id) { + QTAILQ_REMOVE(&dev->cancelled, c, next); + g_free(c); + return 1; + } + } + return 0; +} + +static USBPacket *usbredir_find_packet_by_id(USBRedirDevice *dev, + uint8_t ep, uint64_t id) +{ + USBPacket *p; + + if (usbredir_is_cancelled(dev, id)) { + return NULL; + } + + p = usb_ep_find_packet_by_id(&dev->dev, + (ep & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT, + ep & 0x0f, id); + if (p == NULL) { + ERROR("could not find packet with id %"PRIu64"\n", id); + } + return p; } static void bufp_alloc(USBRedirDevice *dev, @@ -484,24 +483,22 @@ static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep) static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p, uint8_t ep) { - AsyncURB *aurb = async_alloc(dev, p); struct usb_redir_bulk_packet_header bulk_packet; - DPRINTF("bulk-out ep %02X len %zd id %u\n", ep, - p->iov.size, aurb->packet_id); + DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, p->iov.size, p->id); bulk_packet.endpoint = ep; bulk_packet.length = p->iov.size; bulk_packet.stream_id = 0; if (ep & USB_DIR_IN) { - usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id, + usbredirparser_send_bulk_packet(dev->parser, p->id, &bulk_packet, NULL, 0); } else { uint8_t buf[p->iov.size]; usb_packet_copy(p, buf, p->iov.size); usbredir_log_data(dev, "bulk data out:", buf, p->iov.size); - usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id, + usbredirparser_send_bulk_packet(dev->parser, p->id, &bulk_packet, buf, p->iov.size); } usbredirparser_do_write(dev->parser); @@ -564,19 +561,18 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev, return len; } else { /* Output interrupt endpoint, normal async operation */ - AsyncURB *aurb = async_alloc(dev, p); struct usb_redir_interrupt_packet_header interrupt_packet; uint8_t buf[p->iov.size]; - DPRINTF("interrupt-out ep %02X len %zd id %u\n", ep, p->iov.size, - aurb->packet_id); + DPRINTF("interrupt-out ep %02X len %zd id %"PRIu64"\n", ep, + p->iov.size, p->id); interrupt_packet.endpoint = ep; interrupt_packet.length = p->iov.size; usb_packet_copy(p, buf, p->iov.size); usbredir_log_data(dev, "interrupt data out:", buf, p->iov.size); - usbredirparser_send_interrupt_packet(dev->parser, aurb->packet_id, + usbredirparser_send_interrupt_packet(dev->parser, p->id, &interrupt_packet, buf, p->iov.size); usbredirparser_do_write(dev->parser); return USB_RET_ASYNC; @@ -630,10 +626,9 @@ static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p, int config) { struct usb_redir_set_configuration_header set_config; - AsyncURB *aurb = async_alloc(dev, p); int i; - DPRINTF("set config %d id %u\n", config, aurb->packet_id); + DPRINTF("set config %d id %"PRIu64"\n", config, p->id); for (i = 0; i < MAX_ENDPOINTS; i++) { switch (dev->endpoint[i].type) { @@ -650,19 +645,16 @@ static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p, } set_config.configuration = config; - usbredirparser_send_set_configuration(dev->parser, aurb->packet_id, - &set_config); + usbredirparser_send_set_configuration(dev->parser, p->id, &set_config); usbredirparser_do_write(dev->parser); return USB_RET_ASYNC; } static int usbredir_get_config(USBRedirDevice *dev, USBPacket *p) { - AsyncURB *aurb = async_alloc(dev, p); + DPRINTF("get config id %"PRIu64"\n", p->id); - DPRINTF("get config id %u\n", aurb->packet_id); - - usbredirparser_send_get_configuration(dev->parser, aurb->packet_id); + usbredirparser_send_get_configuration(dev->parser, p->id); usbredirparser_do_write(dev->parser); return USB_RET_ASYNC; } @@ -671,11 +663,9 @@ static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p, int interface, int alt) { struct usb_redir_set_alt_setting_header set_alt; - AsyncURB *aurb = async_alloc(dev, p); int i; - DPRINTF("set interface %d alt %d id %u\n", interface, alt, - aurb->packet_id); + DPRINTF("set interface %d alt %d id %"PRIu64"\n", interface, alt, p->id); for (i = 0; i < MAX_ENDPOINTS; i++) { if (dev->endpoint[i].interface == interface) { @@ -695,8 +685,7 @@ static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p, set_alt.interface = interface; set_alt.alt = alt; - usbredirparser_send_set_alt_setting(dev->parser, aurb->packet_id, - &set_alt); + usbredirparser_send_set_alt_setting(dev->parser, p->id, &set_alt); usbredirparser_do_write(dev->parser); return USB_RET_ASYNC; } @@ -705,13 +694,11 @@ static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p, int interface) { struct usb_redir_get_alt_setting_header get_alt; - AsyncURB *aurb = async_alloc(dev, p); - DPRINTF("get interface %d id %u\n", interface, aurb->packet_id); + DPRINTF("get interface %d id %"PRIu64"\n", interface, p->id); get_alt.interface = interface; - usbredirparser_send_get_alt_setting(dev->parser, aurb->packet_id, - &get_alt); + usbredirparser_send_get_alt_setting(dev->parser, p->id, &get_alt); usbredirparser_do_write(dev->parser); return USB_RET_ASYNC; } @@ -721,7 +708,6 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p, { USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); struct usb_redir_control_packet_header control_packet; - AsyncURB *aurb; /* Special cases for certain standard device requests */ switch (request) { @@ -739,13 +725,10 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p, return usbredir_get_interface(dev, p, index); } - /* "Normal" ctrl requests */ - aurb = async_alloc(dev, p); - - /* Note request is (bRequestType << 8) | bRequest */ - DPRINTF("ctrl-out type 0x%x req 0x%x val 0x%x index %d len %d id %u\n", - request >> 8, request & 0xff, value, index, length, - aurb->packet_id); + /* Normal ctrl requests, note request is (bRequestType << 8) | bRequest */ + DPRINTF( + "ctrl-out type 0x%x req 0x%x val 0x%x index %d len %d id %"PRIu64"\n", + request >> 8, request & 0xff, value, index, length, p->id); control_packet.request = request & 0xFF; control_packet.requesttype = request >> 8; @@ -755,11 +738,11 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p, control_packet.length = length; if (control_packet.requesttype & USB_DIR_IN) { - usbredirparser_send_control_packet(dev->parser, aurb->packet_id, + usbredirparser_send_control_packet(dev->parser, p->id, &control_packet, NULL, 0); } else { usbredir_log_data(dev, "ctrl data out:", data, length); - usbredirparser_send_control_packet(dev->parser, aurb->packet_id, + usbredirparser_send_control_packet(dev->parser, p->id, &control_packet, data, length); } usbredirparser_do_write(dev->parser); @@ -913,7 +896,7 @@ static int usbredir_initfn(USBDevice *udev) dev->chardev_close_bh = qemu_bh_new(usbredir_chardev_close_bh, dev); dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev); - QTAILQ_INIT(&dev->asyncq); + QTAILQ_INIT(&dev->cancelled); for (i = 0; i < MAX_ENDPOINTS; i++) { QTAILQ_INIT(&dev->endpoint[i].bufpq); } @@ -932,11 +915,12 @@ static int usbredir_initfn(USBDevice *udev) static void usbredir_cleanup_device_queues(USBRedirDevice *dev) { - AsyncURB *aurb, *next_aurb; + Cancelled *c, *next_c; int i; - QTAILQ_FOREACH_SAFE(aurb, &dev->asyncq, next, next_aurb) { - async_free(dev, aurb); + QTAILQ_FOREACH_SAFE(c, &dev->cancelled, next, next_c) { + QTAILQ_REMOVE(&dev->cancelled, c, next); + g_free(c); } for (i = 0; i < MAX_ENDPOINTS; i++) { usbredir_free_bufpq(dev, I2EP(i)); @@ -1202,33 +1186,28 @@ static void usbredir_configuration_status(void *priv, uint32_t id, struct usb_redir_configuration_status_header *config_status) { USBRedirDevice *dev = priv; - AsyncURB *aurb; + USBPacket *p; int len = 0; DPRINTF("set config status %d config %d id %u\n", config_status->status, config_status->configuration, id); - aurb = async_find(dev, id); - if (!aurb) { - return; - } - if (aurb->packet) { + p = usbredir_find_packet_by_id(dev, 0, id); + if (p) { if (dev->dev.setup_buf[0] & USB_DIR_IN) { dev->dev.data_buf[0] = config_status->configuration; len = 1; } - aurb->packet->result = - usbredir_handle_status(dev, config_status->status, len); - usb_generic_async_ctrl_complete(&dev->dev, aurb->packet); + p->result = usbredir_handle_status(dev, config_status->status, len); + usb_generic_async_ctrl_complete(&dev->dev, p); } - async_free(dev, aurb); } static void usbredir_alt_setting_status(void *priv, uint32_t id, struct usb_redir_alt_setting_status_header *alt_setting_status) { USBRedirDevice *dev = priv; - AsyncURB *aurb; + USBPacket *p; int len = 0; DPRINTF("alt status %d intf %d alt %d id: %u\n", @@ -1236,20 +1215,16 @@ static void usbredir_alt_setting_status(void *priv, uint32_t id, alt_setting_status->interface, alt_setting_status->alt, id); - aurb = async_find(dev, id); - if (!aurb) { - return; - } - if (aurb->packet) { + p = usbredir_find_packet_by_id(dev, 0, id); + if (p) { if (dev->dev.setup_buf[0] & USB_DIR_IN) { dev->dev.data_buf[0] = alt_setting_status->alt; len = 1; } - aurb->packet->result = + p->result = usbredir_handle_status(dev, alt_setting_status->status, len); - usb_generic_async_ctrl_complete(&dev->dev, aurb->packet); + usb_generic_async_ctrl_complete(&dev->dev, p); } - async_free(dev, aurb); } static void usbredir_iso_stream_status(void *priv, uint32_t id, @@ -1304,19 +1279,14 @@ static void usbredir_control_packet(void *priv, uint32_t id, uint8_t *data, int data_len) { USBRedirDevice *dev = priv; + USBPacket *p; int len = control_packet->length; - AsyncURB *aurb; DPRINTF("ctrl-in status %d len %d id %u\n", control_packet->status, len, id); - aurb = async_find(dev, id); - if (!aurb) { - free(data); - return; - } - - if (aurb->packet) { + p = usbredir_find_packet_by_id(dev, 0, id); + if (p) { len = usbredir_handle_status(dev, control_packet->status, len); if (len > 0) { usbredir_log_data(dev, "ctrl data in:", data, data_len); @@ -1328,10 +1298,9 @@ static void usbredir_control_packet(void *priv, uint32_t id, len = USB_RET_STALL; } } - aurb->packet->result = len; - usb_generic_async_ctrl_complete(&dev->dev, aurb->packet); + p->result = len; + usb_generic_async_ctrl_complete(&dev->dev, p); } - async_free(dev, aurb); free(data); } @@ -1342,33 +1311,27 @@ static void usbredir_bulk_packet(void *priv, uint32_t id, USBRedirDevice *dev = priv; uint8_t ep = bulk_packet->endpoint; int len = bulk_packet->length; - AsyncURB *aurb; + USBPacket *p; DPRINTF("bulk-in status %d ep %02X len %d id %u\n", bulk_packet->status, ep, len, id); - aurb = async_find(dev, id); - if (!aurb) { - free(data); - return; - } - - if (aurb->packet) { + p = usbredir_find_packet_by_id(dev, ep, id); + if (p) { len = usbredir_handle_status(dev, bulk_packet->status, len); if (len > 0) { usbredir_log_data(dev, "bulk data in:", data, data_len); - if (data_len <= aurb->packet->iov.size) { - usb_packet_copy(aurb->packet, data, data_len); + if (data_len <= p->iov.size) { + usb_packet_copy(p, data, data_len); } else { ERROR("bulk buffer too small (%d > %zd)\n", data_len, - aurb->packet->iov.size); + p->iov.size); len = USB_RET_STALL; } } - aurb->packet->result = len; - usb_packet_complete(&dev->dev, aurb->packet); + p->result = len; + usb_packet_complete(&dev->dev, p); } - async_free(dev, aurb); free(data); } @@ -1426,17 +1389,12 @@ static void usbredir_interrupt_packet(void *priv, uint32_t id, } else { int len = interrupt_packet->length; - AsyncURB *aurb = async_find(dev, id); - if (!aurb) { - return; - } - - if (aurb->packet) { - aurb->packet->result = usbredir_handle_status(dev, + USBPacket *p = usbredir_find_packet_by_id(dev, ep, id); + if (p) { + p->result = usbredir_handle_status(dev, interrupt_packet->status, len); - usb_packet_complete(&dev->dev, aurb->packet); + usb_packet_complete(&dev->dev, p); } - async_free(dev, aurb); } } From 2979a36183a3902cd75665e7c6bbc8668668fd17 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 28 Aug 2012 11:33:47 +0200 Subject: [PATCH 0272/2270] usb-redir: Return babble when getting more bulk data then requested Babble is the appropriate error in this case (rather then signalling a stall). Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index fd1f8cc510..ee75217600 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1324,9 +1324,9 @@ static void usbredir_bulk_packet(void *priv, uint32_t id, if (data_len <= p->iov.size) { usb_packet_copy(p, data, data_len); } else { - ERROR("bulk buffer too small (%d > %zd)\n", data_len, - p->iov.size); - len = USB_RET_STALL; + ERROR("bulk got more data then requested (%d > %zd)\n", + data_len, p->iov.size); + len = USB_RET_BABBLE; } } p->result = len; From be4a892846651e06dbbd9a48aa877f4e0397d01e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 31 Aug 2012 13:41:38 +0200 Subject: [PATCH 0273/2270] usb-redir: Convert to new libusbredirparser 0.5 API This gives us support for 64 bit ids which is needed for using XHCI with the new hcd generated ids. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- configure | 2 +- hw/usb/redirect.c | 62 +++++++++++++++++++++++------------------------ 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/configure b/configure index 30be78488e..7656c32b24 100755 --- a/configure +++ b/configure @@ -2758,7 +2758,7 @@ fi # check for usbredirparser for usb network redirection support if test "$usb_redir" != "no" ; then - if $pkg_config --atleast-version=0.3.4 libusbredirparser >/dev/null 2>&1 ; then + if $pkg_config --atleast-version=0.5 libusbredirparser >/dev/null 2>&1 ; then usb_redir="yes" usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null) usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index ee75217600..eeeb003c5b 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -107,27 +107,27 @@ static void usbredir_interface_info(void *priv, struct usb_redir_interface_info_header *interface_info); static void usbredir_ep_info(void *priv, struct usb_redir_ep_info_header *ep_info); -static void usbredir_configuration_status(void *priv, uint32_t id, +static void usbredir_configuration_status(void *priv, uint64_t id, struct usb_redir_configuration_status_header *configuration_status); -static void usbredir_alt_setting_status(void *priv, uint32_t id, +static void usbredir_alt_setting_status(void *priv, uint64_t id, struct usb_redir_alt_setting_status_header *alt_setting_status); -static void usbredir_iso_stream_status(void *priv, uint32_t id, +static void usbredir_iso_stream_status(void *priv, uint64_t id, struct usb_redir_iso_stream_status_header *iso_stream_status); -static void usbredir_interrupt_receiving_status(void *priv, uint32_t id, +static void usbredir_interrupt_receiving_status(void *priv, uint64_t id, struct usb_redir_interrupt_receiving_status_header *interrupt_receiving_status); -static void usbredir_bulk_streams_status(void *priv, uint32_t id, +static void usbredir_bulk_streams_status(void *priv, uint64_t id, struct usb_redir_bulk_streams_status_header *bulk_streams_status); -static void usbredir_control_packet(void *priv, uint32_t id, +static void usbredir_control_packet(void *priv, uint64_t id, struct usb_redir_control_packet_header *control_packet, uint8_t *data, int data_len); -static void usbredir_bulk_packet(void *priv, uint32_t id, +static void usbredir_bulk_packet(void *priv, uint64_t id, struct usb_redir_bulk_packet_header *bulk_packet, uint8_t *data, int data_len); -static void usbredir_iso_packet(void *priv, uint32_t id, +static void usbredir_iso_packet(void *priv, uint64_t id, struct usb_redir_iso_packet_header *iso_packet, uint8_t *data, int data_len); -static void usbredir_interrupt_packet(void *priv, uint32_t id, +static void usbredir_interrupt_packet(void *priv, uint64_t id, struct usb_redir_interrupt_packet_header *interrupt_header, uint8_t *data, int data_len); @@ -805,6 +805,7 @@ static void usbredir_chardev_open(USBRedirDevice *dev) usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version); usbredirparser_caps_set_cap(caps, usb_redir_cap_filter); + usbredirparser_caps_set_cap(caps, usb_redir_cap_64bits_ids); usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE, 0); usbredirparser_do_write(dev->parser); } @@ -1182,15 +1183,15 @@ static void usbredir_ep_info(void *priv, } } -static void usbredir_configuration_status(void *priv, uint32_t id, +static void usbredir_configuration_status(void *priv, uint64_t id, struct usb_redir_configuration_status_header *config_status) { USBRedirDevice *dev = priv; USBPacket *p; int len = 0; - DPRINTF("set config status %d config %d id %u\n", config_status->status, - config_status->configuration, id); + DPRINTF("set config status %d config %d id %"PRIu64"\n", + config_status->status, config_status->configuration, id); p = usbredir_find_packet_by_id(dev, 0, id); if (p) { @@ -1203,16 +1204,15 @@ static void usbredir_configuration_status(void *priv, uint32_t id, } } -static void usbredir_alt_setting_status(void *priv, uint32_t id, +static void usbredir_alt_setting_status(void *priv, uint64_t id, struct usb_redir_alt_setting_status_header *alt_setting_status) { USBRedirDevice *dev = priv; USBPacket *p; int len = 0; - DPRINTF("alt status %d intf %d alt %d id: %u\n", - alt_setting_status->status, - alt_setting_status->interface, + DPRINTF("alt status %d intf %d alt %d id: %"PRIu64"\n", + alt_setting_status->status, alt_setting_status->interface, alt_setting_status->alt, id); p = usbredir_find_packet_by_id(dev, 0, id); @@ -1227,13 +1227,13 @@ static void usbredir_alt_setting_status(void *priv, uint32_t id, } } -static void usbredir_iso_stream_status(void *priv, uint32_t id, +static void usbredir_iso_stream_status(void *priv, uint64_t id, struct usb_redir_iso_stream_status_header *iso_stream_status) { USBRedirDevice *dev = priv; uint8_t ep = iso_stream_status->endpoint; - DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status, + DPRINTF("iso status %d ep %02X id %"PRIu64"\n", iso_stream_status->status, ep, id); if (!dev->dev.attached || !dev->endpoint[EP2I(ep)].iso_started) { @@ -1247,14 +1247,14 @@ static void usbredir_iso_stream_status(void *priv, uint32_t id, } } -static void usbredir_interrupt_receiving_status(void *priv, uint32_t id, +static void usbredir_interrupt_receiving_status(void *priv, uint64_t id, struct usb_redir_interrupt_receiving_status_header *interrupt_receiving_status) { USBRedirDevice *dev = priv; uint8_t ep = interrupt_receiving_status->endpoint; - DPRINTF("interrupt recv status %d ep %02X id %u\n", + DPRINTF("interrupt recv status %d ep %02X id %"PRIu64"\n", interrupt_receiving_status->status, ep, id); if (!dev->dev.attached || !dev->endpoint[EP2I(ep)].interrupt_started) { @@ -1269,12 +1269,12 @@ static void usbredir_interrupt_receiving_status(void *priv, uint32_t id, } } -static void usbredir_bulk_streams_status(void *priv, uint32_t id, +static void usbredir_bulk_streams_status(void *priv, uint64_t id, struct usb_redir_bulk_streams_status_header *bulk_streams_status) { } -static void usbredir_control_packet(void *priv, uint32_t id, +static void usbredir_control_packet(void *priv, uint64_t id, struct usb_redir_control_packet_header *control_packet, uint8_t *data, int data_len) { @@ -1282,7 +1282,7 @@ static void usbredir_control_packet(void *priv, uint32_t id, USBPacket *p; int len = control_packet->length; - DPRINTF("ctrl-in status %d len %d id %u\n", control_packet->status, + DPRINTF("ctrl-in status %d len %d id %"PRIu64"\n", control_packet->status, len, id); p = usbredir_find_packet_by_id(dev, 0, id); @@ -1304,7 +1304,7 @@ static void usbredir_control_packet(void *priv, uint32_t id, free(data); } -static void usbredir_bulk_packet(void *priv, uint32_t id, +static void usbredir_bulk_packet(void *priv, uint64_t id, struct usb_redir_bulk_packet_header *bulk_packet, uint8_t *data, int data_len) { @@ -1313,8 +1313,8 @@ static void usbredir_bulk_packet(void *priv, uint32_t id, int len = bulk_packet->length; USBPacket *p; - DPRINTF("bulk-in status %d ep %02X len %d id %u\n", bulk_packet->status, - ep, len, id); + DPRINTF("bulk-in status %d ep %02X len %d id %"PRIu64"\n", + bulk_packet->status, ep, len, id); p = usbredir_find_packet_by_id(dev, ep, id); if (p) { @@ -1335,15 +1335,15 @@ static void usbredir_bulk_packet(void *priv, uint32_t id, free(data); } -static void usbredir_iso_packet(void *priv, uint32_t id, +static void usbredir_iso_packet(void *priv, uint64_t id, struct usb_redir_iso_packet_header *iso_packet, uint8_t *data, int data_len) { USBRedirDevice *dev = priv; uint8_t ep = iso_packet->endpoint; - DPRINTF2("iso-in status %d ep %02X len %d id %u\n", iso_packet->status, ep, - data_len, id); + DPRINTF2("iso-in status %d ep %02X len %d id %"PRIu64"\n", + iso_packet->status, ep, data_len, id); if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_ISOC) { ERROR("received iso packet for non iso endpoint %02X\n", ep); @@ -1361,14 +1361,14 @@ static void usbredir_iso_packet(void *priv, uint32_t id, bufp_alloc(dev, data, data_len, iso_packet->status, ep); } -static void usbredir_interrupt_packet(void *priv, uint32_t id, +static void usbredir_interrupt_packet(void *priv, uint64_t id, struct usb_redir_interrupt_packet_header *interrupt_packet, uint8_t *data, int data_len) { USBRedirDevice *dev = priv; uint8_t ep = interrupt_packet->endpoint; - DPRINTF("interrupt-in status %d ep %02X len %d id %u\n", + DPRINTF("interrupt-in status %d ep %02X len %d id %"PRIu64"\n", interrupt_packet->status, ep, data_len, id); if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_INT) { From 0fde3b7a826aa654612126cdea9832319a34172c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 3 Sep 2012 11:49:07 +0200 Subject: [PATCH 0274/2270] usb-redir: Set ep max_packet_size if available This is needed for usb-redir to work properly with the xhci emulation. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index eeeb003c5b..a91e073aa9 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -805,6 +805,7 @@ static void usbredir_chardev_open(USBRedirDevice *dev) usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version); usbredirparser_caps_set_cap(caps, usb_redir_cap_filter); + usbredirparser_caps_set_cap(caps, usb_redir_cap_ep_info_max_packet_size); usbredirparser_caps_set_cap(caps, usb_redir_cap_64bits_ids); usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE, 0); usbredirparser_do_write(dev->parser); @@ -1180,6 +1181,10 @@ static void usbredir_ep_info(void *priv, i & 0x0f); usb_ep->type = dev->endpoint[i].type; usb_ep->ifnum = dev->endpoint[i].interface; + if (usbredirparser_peer_has_cap(dev->parser, + usb_redir_cap_ep_info_max_packet_size)) { + usb_ep->max_packet_size = ep_info->max_packet_size[i]; + } } } From 910c1e6b14e4abb188ff7ef584a629187479f82d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 3 Sep 2012 11:53:28 +0200 Subject: [PATCH 0275/2270] usb-redir: Add a usbredir_reject_device helper function Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index a91e073aa9..c5182012f1 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -811,16 +811,21 @@ static void usbredir_chardev_open(USBRedirDevice *dev) usbredirparser_do_write(dev->parser); } +static void usbredir_reject_device(USBRedirDevice *dev) +{ + usbredir_device_disconnect(dev); + if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter)) { + usbredirparser_send_filter_reject(dev->parser); + usbredirparser_do_write(dev->parser); + } +} + static void usbredir_do_attach(void *opaque) { USBRedirDevice *dev = opaque; if (usb_device_attach(&dev->dev) != 0) { - usbredir_device_disconnect(dev); - if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter)) { - usbredirparser_send_filter_reject(dev->parser); - usbredirparser_do_write(dev->parser); - } + usbredir_reject_device(dev); } } @@ -986,11 +991,7 @@ static int usbredir_check_filter(USBRedirDevice *dev) return 0; error: - usbredir_device_disconnect(dev); - if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter)) { - usbredirparser_send_filter_reject(dev->parser); - usbredirparser_do_write(dev->parser); - } + usbredir_reject_device(dev); return -1; } From a508cc42e22a2ac3878b964290780f1d81ec65c1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 3 Sep 2012 12:04:49 +0200 Subject: [PATCH 0276/2270] usb-redir: Ensure our peer has the necessary caps when redirecting to XHCI In order for redirection to work properly when redirecting to an emulated XHCI controller, the usb-redir-host must support both usb_redir_cap_ep_info_max_packet_size and usb_redir_cap_64bits_ids, reject any devices redirected to an XHCI controller when these are not supported. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index c5182012f1..7fb0fb3de8 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -824,6 +824,17 @@ static void usbredir_do_attach(void *opaque) { USBRedirDevice *dev = opaque; + /* In order to work properly with XHCI controllers we need these caps */ + if ((dev->dev.port->speedmask & USB_SPEED_MASK_SUPER) && !( + usbredirparser_peer_has_cap(dev->parser, + usb_redir_cap_ep_info_max_packet_size) && + usbredirparser_peer_has_cap(dev->parser, + usb_redir_cap_64bits_ids))) { + ERROR("usb-redir-host lacks capabilities needed for use with XHCI\n"); + usbredir_reject_device(dev); + return; + } + if (usb_device_attach(&dev->dev) != 0) { usbredir_reject_device(dev); } From 6c67446a427b50a706e628f810116353f5d128cf Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 3 Sep 2012 13:44:04 +0200 Subject: [PATCH 0277/2270] usb-redir: Enable pipelining for bulk endpoints Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 7fb0fb3de8..5301a69c4f 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1197,6 +1197,9 @@ static void usbredir_ep_info(void *priv, usb_redir_cap_ep_info_max_packet_size)) { usb_ep->max_packet_size = ep_info->max_packet_size[i]; } + if (ep_info->type[i] == usb_redir_type_bulk) { + usb_ep->pipeline = true; + } } } From 2964cd9bfa5100e433471d3e3fedcc9d62891894 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 23 Aug 2012 09:59:27 +0200 Subject: [PATCH 0278/2270] Better name usb braille device Windows users need to know that they have to use the Baum driver to make the qemu braille device work. Signed-off-by: Samuel Thibault Signed-off-by: Gerd Hoffmann --- hw/usb/dev-serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 8aa655286b..69b6e48d5a 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -113,7 +113,7 @@ enum { static const USBDescStrings desc_strings = { [STR_MANUFACTURER] = "QEMU", [STR_PRODUCT_SERIAL] = "QEMU USB SERIAL", - [STR_PRODUCT_BRAILLE] = "QEMU USB BRAILLE", + [STR_PRODUCT_BRAILLE] = "QEMU USB BAUM BRAILLE", [STR_SERIALNUMBER] = "1", }; From 2bbd086c41a00dc4384727ec895a94890c688eb5 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 28 Aug 2012 16:43:34 +0200 Subject: [PATCH 0279/2270] usb-audio: fix usb version usb-audio is a full speed (1.1) device, but bcdUSB claims it is usb 2.0. Fix it. Signed-off-by: Gerd Hoffmann --- hw/usb/dev-audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 79b75fb628..2594c78104 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -217,7 +217,7 @@ static const USBDescIface desc_iface[] = { }; static const USBDescDevice desc_device = { - .bcdUSB = 0x0200, + .bcdUSB = 0x0100, .bMaxPacketSize0 = 64, .bNumConfigurations = 1, .confs = (USBDescConfig[]) { From 331e9406f152b6bae6859a153d36e5076c58901d Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 17 Aug 2012 14:05:21 +0200 Subject: [PATCH 0280/2270] xhci: rip out background transfer code original xhci code (the one which used libusb directly) used to use 'background transfers' for iso streams. In upstream qemu the iso stream buffering is handled by usb-host & usb-redir, so we will never ever need this. It has been left in as reference, but is dead code anyway. Rip it out. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 223 +--------------------------------------------- 1 file changed, 4 insertions(+), 219 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 3eb27fadb8..c0a2476f0f 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -45,8 +45,6 @@ #define MAXPORTS (USB2_PORTS+USB3_PORTS) #define TD_QUEUE 24 -#define BG_XFERS 8 -#define BG_PKTS 8 /* Very pessimistic, let's hope it's enough for all cases */ #define EV_QUEUE (((3*TD_QUEUE)+16)*MAXSLOTS) @@ -311,13 +309,11 @@ typedef struct XHCITransfer { bool running_retry; bool cancelled; bool complete; - bool backgrounded; unsigned int iso_pkts; unsigned int slotid; unsigned int epid; bool in_xfer; bool iso_xfer; - bool bg_xfer; unsigned int trb_count; unsigned int trb_alloced; @@ -340,14 +336,9 @@ typedef struct XHCIEPContext { unsigned int comp_xfer; XHCITransfer transfers[TD_QUEUE]; XHCITransfer *retry; - bool bg_running; - bool bg_updating; - unsigned int next_bg; - XHCITransfer bg_transfers[BG_XFERS]; EPType type; dma_addr_t pctx; unsigned int max_psize; - bool has_bg; uint32_t state; } XHCIEPContext; @@ -866,10 +857,6 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, epctx->pctx = pctx; epctx->max_psize = ctx[1]>>16; epctx->max_psize *= 1+((ctx[1]>>8)&0xff); - epctx->has_bg = false; - if (epctx->type == ET_ISO_IN) { - epctx->has_bg = true; - } DPRINTF("xhci: endpoint %d.%d max transaction (burst) size is %d\n", epid/2, epid%2, epctx->max_psize); for (i = 0; i < ARRAY_SIZE(epctx->transfers); i++) { @@ -916,9 +903,6 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid, t->running_retry = 0; epctx->retry = NULL; } - if (t->backgrounded) { - t->backgrounded = 0; - } if (t->trbs) { g_free(t->trbs); } @@ -932,25 +916,6 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid, t->data_length = t->data_alloced = 0; xferi = (xferi + 1) % TD_QUEUE; } - if (epctx->has_bg) { - xferi = epctx->next_bg; - for (i = 0; i < BG_XFERS; i++) { - XHCITransfer *t = &epctx->bg_transfers[xferi]; - if (t->running_async) { - usb_cancel_packet(&t->packet); - t->running_async = 0; - t->cancelled = 1; - DPRINTF("xhci: cancelling bg transfer %d, waiting for it to complete...\n", i); - killed++; - } - if (t->data) { - g_free(t->data); - } - - t->data = NULL; - xferi = (xferi + 1) % BG_XFERS; - } - } return killed; } @@ -1231,160 +1196,6 @@ static void xhci_stall_ep(XHCITransfer *xfer) static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx); -static void xhci_bg_update(XHCIState *xhci, XHCIEPContext *epctx) -{ - if (epctx->bg_updating) { - return; - } - DPRINTF("xhci_bg_update(%p, %p)\n", xhci, epctx); - assert(epctx->has_bg); - DPRINTF("xhci: fg=%d bg=%d\n", epctx->comp_xfer, epctx->next_bg); - epctx->bg_updating = 1; - while (epctx->transfers[epctx->comp_xfer].backgrounded && - epctx->bg_transfers[epctx->next_bg].complete) { - XHCITransfer *fg = &epctx->transfers[epctx->comp_xfer]; - XHCITransfer *bg = &epctx->bg_transfers[epctx->next_bg]; -#if 0 - DPRINTF("xhci: completing fg %d from bg %d.%d (stat: %d)\n", - epctx->comp_xfer, epctx->next_bg, bg->cur_pkt, - bg->usbxfer->iso_packet_desc[bg->cur_pkt].status - ); -#endif - assert(epctx->type == ET_ISO_IN); - assert(bg->iso_xfer); - assert(bg->in_xfer); - uint8_t *p = bg->data + bg->cur_pkt * bg->pktsize; -#if 0 - int len = bg->usbxfer->iso_packet_desc[bg->cur_pkt].actual_length; - fg->status = libusb_to_ccode(bg->usbxfer->iso_packet_desc[bg->cur_pkt].status); -#else - int len = 0; - FIXME(); -#endif - fg->complete = 1; - fg->backgrounded = 0; - - if (fg->status == CC_STALL_ERROR) { - xhci_stall_ep(fg); - } - - xhci_xfer_data(fg, p, len, 1, 0, 1); - - epctx->comp_xfer++; - if (epctx->comp_xfer == TD_QUEUE) { - epctx->comp_xfer = 0; - } - DPRINTF("next fg xfer: %d\n", epctx->comp_xfer); - bg->cur_pkt++; - if (bg->cur_pkt == bg->pkts) { - bg->complete = 0; - if (xhci_submit(xhci, bg, epctx) < 0) { - fprintf(stderr, "xhci: bg resubmit failed\n"); - } - epctx->next_bg++; - if (epctx->next_bg == BG_XFERS) { - epctx->next_bg = 0; - } - DPRINTF("next bg xfer: %d\n", epctx->next_bg); - - xhci_kick_ep(xhci, fg->slotid, fg->epid); - } - } - epctx->bg_updating = 0; -} - -#if 0 -static void xhci_xfer_cb(struct libusb_transfer *transfer) -{ - XHCIState *xhci; - XHCITransfer *xfer; - - xfer = (XHCITransfer *)transfer->user_data; - xhci = xfer->xhci; - - DPRINTF("xhci_xfer_cb(slot=%d, ep=%d, status=%d)\n", xfer->slotid, - xfer->epid, transfer->status); - - assert(xfer->slotid >= 1 && xfer->slotid <= MAXSLOTS); - assert(xfer->epid >= 1 && xfer->epid <= 31); - - if (xfer->cancelled) { - DPRINTF("xhci: transfer cancelled, not reporting anything\n"); - xfer->running = 0; - return; - } - - XHCIEPContext *epctx; - XHCISlot *slot; - slot = &xhci->slots[xfer->slotid-1]; - assert(slot->eps[xfer->epid-1]); - epctx = slot->eps[xfer->epid-1]; - - if (xfer->bg_xfer) { - DPRINTF("xhci: background transfer, updating\n"); - xfer->complete = 1; - xfer->running = 0; - xhci_bg_update(xhci, epctx); - return; - } - - if (xfer->iso_xfer) { - transfer->status = transfer->iso_packet_desc[0].status; - transfer->actual_length = transfer->iso_packet_desc[0].actual_length; - } - - xfer->status = libusb_to_ccode(transfer->status); - - xfer->complete = 1; - xfer->running = 0; - - if (transfer->status == LIBUSB_TRANSFER_STALL) - xhci_stall_ep(xhci, epctx, xfer); - - DPRINTF("xhci: transfer actual length = %d\n", transfer->actual_length); - - if (xfer->in_xfer) { - if (xfer->epid == 1) { - xhci_xfer_data(xhci, xfer, xfer->data + 8, - transfer->actual_length, 1, 0, 1); - } else { - xhci_xfer_data(xhci, xfer, xfer->data, - transfer->actual_length, 1, 0, 1); - } - } else { - xhci_xfer_data(xhci, xfer, NULL, transfer->actual_length, 0, 0, 1); - } - - xhci_kick_ep(xhci, xfer->slotid, xfer->epid); -} - -static int xhci_hle_control(XHCIState *xhci, XHCITransfer *xfer, - uint8_t bmRequestType, uint8_t bRequest, - uint16_t wValue, uint16_t wIndex, uint16_t wLength) -{ - uint16_t type_req = (bmRequestType << 8) | bRequest; - - switch (type_req) { - case 0x0000 | USB_REQ_SET_CONFIGURATION: - DPRINTF("xhci: HLE switch configuration\n"); - return xhci_switch_config(xhci, xfer->slotid, wValue) == 0; - case 0x0100 | USB_REQ_SET_INTERFACE: - DPRINTF("xhci: HLE set interface altsetting\n"); - return xhci_set_iface_alt(xhci, xfer->slotid, wIndex, wValue) == 0; - case 0x0200 | USB_REQ_CLEAR_FEATURE: - if (wValue == 0) { // endpoint halt - DPRINTF("xhci: HLE clear halt\n"); - return xhci_clear_halt(xhci, xfer->slotid, wIndex); - } - case 0x0000 | USB_REQ_SET_ADDRESS: - fprintf(stderr, "xhci: warn: illegal SET_ADDRESS request\n"); - return 0; - default: - return 0; - } -} -#endif - static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev) { USBEndpoint *ep; @@ -1559,9 +1370,7 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx xfer->data_alloced = xfer->data_length; } if (epctx->type == ET_ISO_IN || epctx->type == ET_ISO_OUT) { - if (!xfer->bg_xfer) { - xfer->pkts = 1; - } + xfer->pkts = 1; } else { xfer->pkts = 0; } @@ -1620,32 +1429,8 @@ static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext trace_usb_xhci_xfer_start(xfer, xfer->slotid, xfer->epid, length); - if (!epctx->has_bg) { - xfer->data_length = length; - xfer->backgrounded = 0; - return xhci_submit(xhci, xfer, epctx); - } else { - if (!epctx->bg_running) { - for (i = 0; i < BG_XFERS; i++) { - XHCITransfer *t = &epctx->bg_transfers[i]; - t->xhci = xhci; - t->epid = xfer->epid; - t->slotid = xfer->slotid; - t->pkts = BG_PKTS; - t->pktsize = epctx->max_psize; - t->data_length = t->pkts * t->pktsize; - t->bg_xfer = 1; - if (xhci_submit(xhci, t, epctx) < 0) { - fprintf(stderr, "xhci: bg submit failed\n"); - return -1; - } - } - epctx->bg_running = 1; - } - xfer->backgrounded = 1; - xhci_bg_update(xhci, epctx); - return 0; - } + xfer->data_length = length; + return xhci_submit(xhci, xfer, epctx); } static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid) @@ -1695,7 +1480,7 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid while (1) { XHCITransfer *xfer = &epctx->transfers[epctx->next_xfer]; - if (xfer->running_async || xfer->running_retry || xfer->backgrounded) { + if (xfer->running_async || xfer->running_retry) { break; } length = xhci_ring_chain_length(xhci, &epctx->ring); From d5a15814b413869667b2a3215772986885be574a Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 17 Aug 2012 11:04:36 +0200 Subject: [PATCH 0281/2270] xhci: drop buffering This patch splits the xhci_xfer_data function into three. The xhci_xfer_data function used to do does two things: (1) copy transfer data between guest memory and a temporary buffer. (2) report transfer results to the guest using events. Now we three functions to handle this: (1) xhci_xfer_map creates a scatter list for the transfer and uses that (instead of the temporary buffer) to build a USBPacket. (2) xhci_xfer_unmap undoes the mapping. (3) xhci_xfer_report sends out events. The patch also fixes reporting of transaction errors which must be reported unconditinally, not only in case the guest asks for it using the ISP flag. [ v2: fix warning ] Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 185 ++++++++++++++++++---------------------------- trace-events | 2 +- 2 files changed, 72 insertions(+), 115 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index c0a2476f0f..446d692ea6 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -305,6 +305,7 @@ typedef struct XHCIState XHCIState; typedef struct XHCITransfer { XHCIState *xhci; USBPacket packet; + QEMUSGList sgl; bool running_async; bool running_retry; bool cancelled; @@ -319,10 +320,6 @@ typedef struct XHCITransfer { unsigned int trb_alloced; XHCITRB *trbs; - unsigned int data_length; - unsigned int data_alloced; - uint8_t *data; - TRBCCode status; unsigned int pkts; @@ -906,14 +903,9 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid, if (t->trbs) { g_free(t->trbs); } - if (t->data) { - g_free(t->data); - } t->trbs = NULL; - t->data = NULL; t->trb_count = t->trb_alloced = 0; - t->data_length = t->data_alloced = 0; xferi = (xferi + 1) % TD_QUEUE; } return killed; @@ -1072,24 +1064,13 @@ static TRBCCode xhci_set_ep_dequeue(XHCIState *xhci, unsigned int slotid, return CC_SUCCESS; } -static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data, - unsigned int length, bool in_xfer, bool out_xfer, - bool report) +static int xhci_xfer_map(XHCITransfer *xfer) { - int i; - uint32_t edtla = 0; - unsigned int transferred = 0; - unsigned int left = length; - bool reported = 0; - bool shortpkt = 0; - XHCIEvent event = {ER_TRANSFER, CC_SUCCESS}; + int in_xfer = (xfer->packet.pid == USB_TOKEN_IN); XHCIState *xhci = xfer->xhci; + int i; - DPRINTF("xhci_xfer_data(len=%d, in_xfer=%d, out_xfer=%d, report=%d)\n", - length, in_xfer, out_xfer, report); - - assert(!(in_xfer && out_xfer)); - + pci_dma_sglist_init(&xfer->sgl, &xhci->pci_dev, xfer->trb_count); for (i = 0; i < xfer->trb_count; i++) { XHCITRB *trb = &xfer->trbs[i]; dma_addr_t addr; @@ -1099,54 +1080,70 @@ static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data, case TR_DATA: if ((!(trb->control & TRB_TR_DIR)) != (!in_xfer)) { fprintf(stderr, "xhci: data direction mismatch for TR_DATA\n"); - xhci_die(xhci); - return transferred; + goto err; } /* fallthrough */ case TR_NORMAL: case TR_ISOCH: addr = xhci_mask64(trb->parameter); + chunk = trb->status & 0x1ffff; + if (trb->control & TRB_TR_IDT) { + if (chunk > 8 || in_xfer) { + fprintf(stderr, "xhci: invalid immediate data TRB\n"); + goto err; + } + qemu_sglist_add(&xfer->sgl, trb->addr, chunk); + } else { + qemu_sglist_add(&xfer->sgl, addr, chunk); + } + break; + } + } + + usb_packet_map(&xfer->packet, &xfer->sgl); + return 0; + +err: + qemu_sglist_destroy(&xfer->sgl); + xhci_die(xhci); + return -1; +} + +static void xhci_xfer_unmap(XHCITransfer *xfer) +{ + usb_packet_unmap(&xfer->packet, &xfer->sgl); + qemu_sglist_destroy(&xfer->sgl); +} + +static void xhci_xfer_report(XHCITransfer *xfer) +{ + uint32_t edtla = 0; + unsigned int left; + bool reported = 0; + bool shortpkt = 0; + XHCIEvent event = {ER_TRANSFER, CC_SUCCESS}; + XHCIState *xhci = xfer->xhci; + int i; + + left = xfer->packet.result < 0 ? 0 : xfer->packet.result; + + for (i = 0; i < xfer->trb_count; i++) { + XHCITRB *trb = &xfer->trbs[i]; + unsigned int chunk = 0; + + switch (TRB_TYPE(*trb)) { + case TR_DATA: + case TR_NORMAL: + case TR_ISOCH: chunk = trb->status & 0x1ffff; if (chunk > left) { chunk = left; - shortpkt = 1; - } - if (in_xfer || out_xfer) { - if (trb->control & TRB_TR_IDT) { - uint64_t idata; - if (chunk > 8 || in_xfer) { - fprintf(stderr, "xhci: invalid immediate data TRB\n"); - xhci_die(xhci); - return transferred; - } - idata = le64_to_cpu(trb->parameter); - memcpy(data, &idata, chunk); - } else { - DPRINTF("xhci_xfer_data: r/w(%d) %d bytes at " - DMA_ADDR_FMT "\n", in_xfer, chunk, addr); - if (in_xfer) { - pci_dma_write(&xhci->pci_dev, addr, data, chunk); - } else { - pci_dma_read(&xhci->pci_dev, addr, data, chunk); - } -#ifdef DEBUG_DATA - unsigned int count = chunk; - int i; - if (count > 16) { - count = 16; - } - DPRINTF(" ::"); - for (i = 0; i < count; i++) { - DPRINTF(" %02x", data[i]); - } - DPRINTF("\n"); -#endif + if (xfer->status == CC_SUCCESS) { + shortpkt = 1; } } left -= chunk; - data += chunk; edtla += chunk; - transferred += chunk; break; case TR_STATUS: reported = 0; @@ -1154,8 +1151,9 @@ static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data, break; } - if (report && !reported && (trb->control & TRB_TR_IOC || - (shortpkt && (trb->control & TRB_TR_ISP)))) { + if (!reported && ((trb->control & TRB_TR_IOC) || + (shortpkt && (trb->control & TRB_TR_ISP)) || + (xfer->status != CC_SUCCESS))) { event.slotid = xfer->slotid; event.epid = xfer->epid; event.length = (trb->status & 0x1ffff) - chunk; @@ -1175,9 +1173,11 @@ static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data, } xhci_event(xhci, &event); reported = 1; + if (xfer->status != CC_SUCCESS) { + return; + } } } - return transferred; } static void xhci_stall_ep(XHCITransfer *xfer) @@ -1204,7 +1204,7 @@ static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev) dir = xfer->in_xfer ? USB_TOKEN_IN : USB_TOKEN_OUT; ep = usb_ep_get(dev, dir, xfer->epid >> 1); usb_packet_setup(&xfer->packet, dir, ep, xfer->trbs[0].addr); - usb_packet_addbuf(&xfer->packet, xfer->data, xfer->data_length); + xhci_xfer_map(xfer); DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n", xfer->packet.pid, dev->addr, ep->nr); return 0; @@ -1230,12 +1230,13 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret) xfer->running_async = 0; xfer->running_retry = 0; xfer->complete = 1; + xhci_xfer_unmap(xfer); } if (ret >= 0) { - xfer->status = CC_SUCCESS; - xhci_xfer_data(xfer, xfer->data, ret, xfer->in_xfer, 0, 1); trace_usb_xhci_xfer_success(xfer, ret); + xfer->status = CC_SUCCESS; + xhci_xfer_report(xfer); return 0; } @@ -1244,12 +1245,12 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret) switch (ret) { case USB_RET_NODEV: xfer->status = CC_USB_TRANSACTION_ERROR; - xhci_xfer_data(xfer, xfer->data, 0, xfer->in_xfer, 0, 1); + xhci_xfer_report(xfer); xhci_stall_ep(xfer); break; case USB_RET_STALL: xfer->status = CC_STALL_ERROR; - xhci_xfer_data(xfer, xfer->data, 0, xfer->in_xfer, 0, 1); + xhci_xfer_report(xfer); xhci_stall_ep(xfer); break; default: @@ -1271,7 +1272,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) { XHCITRB *trb_setup, *trb_status; uint8_t bmRequestType; - uint16_t wLength; XHCIPort *port; USBDevice *dev; int ret; @@ -1279,8 +1279,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) trb_setup = &xfer->trbs[0]; trb_status = &xfer->trbs[xfer->trb_count-1]; - trace_usb_xhci_xfer_start(xfer, xfer->slotid, xfer->epid, - trb_setup->parameter >> 48); + trace_usb_xhci_xfer_start(xfer, xfer->slotid, xfer->epid); /* at most one Event Data TRB allowed after STATUS */ if (TRB_TYPE(*trb_status) == TR_EVDATA && xfer->trb_count > 2) { @@ -1309,19 +1308,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) } bmRequestType = trb_setup->parameter; - wLength = trb_setup->parameter >> 48; - - if (xfer->data && xfer->data_alloced < wLength) { - xfer->data_alloced = 0; - g_free(xfer->data); - xfer->data = NULL; - } - if (!xfer->data) { - DPRINTF("xhci: alloc %d bytes data\n", wLength); - xfer->data = g_malloc(wLength+1); - xfer->data_alloced = wLength; - } - xfer->data_length = wLength; port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1]; dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr); @@ -1336,9 +1322,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) xhci_setup_packet(xfer, dev); xfer->packet.parameter = trb_setup->parameter; - if (!xfer->in_xfer) { - xhci_xfer_data(xfer, xfer->data, wLength, 0, 1, 0); - } ret = usb_handle_packet(dev, &xfer->packet); @@ -1359,16 +1342,6 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx xfer->in_xfer = epctx->type>>2; - if (xfer->data && xfer->data_alloced < xfer->data_length) { - xfer->data_alloced = 0; - g_free(xfer->data); - xfer->data = NULL; - } - if (!xfer->data && xfer->data_length) { - DPRINTF("xhci: alloc %d bytes data\n", xfer->data_length); - xfer->data = g_malloc(xfer->data_length); - xfer->data_alloced = xfer->data_length; - } if (epctx->type == ET_ISO_IN || epctx->type == ET_ISO_OUT) { xfer->pkts = 1; } else { @@ -1402,9 +1375,6 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx return -1; } - if (!xfer->in_xfer) { - xhci_xfer_data(xfer, xfer->data, xfer->data_length, 0, 1, 0); - } ret = usb_handle_packet(dev, &xfer->packet); xhci_complete_packet(xfer, ret); @@ -1416,20 +1386,7 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx) { - int i; - unsigned int length = 0; - XHCITRB *trb; - - for (i = 0; i < xfer->trb_count; i++) { - trb = &xfer->trbs[i]; - if (TRB_TYPE(*trb) == TR_NORMAL || TRB_TYPE(*trb) == TR_ISOCH) { - length += trb->status & 0x1ffff; - } - } - - trace_usb_xhci_xfer_start(xfer, xfer->slotid, xfer->epid, length); - - xfer->data_length = length; + trace_usb_xhci_xfer_start(xfer, xfer->slotid, xfer->epid); return xhci_submit(xhci, xfer, epctx); } diff --git a/trace-events b/trace-events index 10bc04eac9..c83d65edef 100644 --- a/trace-events +++ b/trace-events @@ -326,7 +326,7 @@ usb_xhci_ep_disable(uint32_t slotid, uint32_t epid) "slotid %d, epid %d" usb_xhci_ep_kick(uint32_t slotid, uint32_t epid) "slotid %d, epid %d" usb_xhci_ep_stop(uint32_t slotid, uint32_t epid) "slotid %d, epid %d" usb_xhci_ep_reset(uint32_t slotid, uint32_t epid) "slotid %d, epid %d" -usb_xhci_xfer_start(void *xfer, uint32_t slotid, uint32_t epid, uint32_t length) "%p: slotid %d, epid %d, length %d" +usb_xhci_xfer_start(void *xfer, uint32_t slotid, uint32_t epid) "%p: slotid %d, epid %d" usb_xhci_xfer_async(void *xfer) "%p" usb_xhci_xfer_nak(void *xfer) "%p" usb_xhci_xfer_retry(void *xfer) "%p" From 5c08106ff65c904c297dab17cd0b0a3a28b63527 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 24 Aug 2012 14:21:39 +0200 Subject: [PATCH 0282/2270] xhci: move device lookup into xhci_setup_packet Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 74 ++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 446d692ea6..c108c9d47d 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1196,13 +1196,38 @@ static void xhci_stall_ep(XHCITransfer *xfer) static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx); -static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev) +static USBDevice *xhci_find_device(XHCIPort *port, uint8_t addr) { + if (!(port->portsc & PORTSC_PED)) { + return NULL; + } + return usb_find_device(&port->port, addr); +} + +static int xhci_setup_packet(XHCITransfer *xfer) +{ + XHCIState *xhci = xfer->xhci; + XHCIPort *port; + USBDevice *dev; USBEndpoint *ep; int dir; dir = xfer->in_xfer ? USB_TOKEN_IN : USB_TOKEN_OUT; - ep = usb_ep_get(dev, dir, xfer->epid >> 1); + + if (xfer->packet.ep) { + ep = xfer->packet.ep; + dev = ep->dev; + } else { + port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1]; + dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr); + if (!dev) { + fprintf(stderr, "xhci: slot %d port %d has no device\n", + xfer->slotid, xhci->slots[xfer->slotid-1].port); + return -1; + } + ep = usb_ep_get(dev, dir, xfer->epid >> 1); + } + usb_packet_setup(&xfer->packet, dir, ep, xfer->trbs[0].addr); xhci_xfer_map(xfer); DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n", @@ -1260,20 +1285,10 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret) return 0; } -static USBDevice *xhci_find_device(XHCIPort *port, uint8_t addr) -{ - if (!(port->portsc & PORTSC_PED)) { - return NULL; - } - return usb_find_device(&port->port, addr); -} - static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) { XHCITRB *trb_setup, *trb_status; uint8_t bmRequestType; - XHCIPort *port; - USBDevice *dev; int ret; trb_setup = &xfer->trbs[0]; @@ -1309,21 +1324,15 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) bmRequestType = trb_setup->parameter; - port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1]; - dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr); - if (!dev) { - fprintf(stderr, "xhci: slot %d port %d has no device\n", xfer->slotid, - xhci->slots[xfer->slotid-1].port); - return -1; - } - xfer->in_xfer = bmRequestType & USB_DIR_IN; xfer->iso_xfer = false; - xhci_setup_packet(xfer, dev); + if (xhci_setup_packet(xfer) < 0) { + return -1; + } xfer->packet.parameter = trb_setup->parameter; - ret = usb_handle_packet(dev, &xfer->packet); + ret = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet); xhci_complete_packet(xfer, ret); if (!xfer->running_async && !xfer->running_retry) { @@ -1334,8 +1343,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx) { - XHCIPort *port; - USBDevice *dev; int ret; DPRINTF("xhci_submit(slotid=%d,epid=%d)\n", xfer->slotid, xfer->epid); @@ -1348,16 +1355,6 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx xfer->pkts = 0; } - port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1]; - dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr); - if (!dev) { - fprintf(stderr, "xhci: slot %d port %d has no device\n", xfer->slotid, - xhci->slots[xfer->slotid-1].port); - return -1; - } - - xhci_setup_packet(xfer, dev); - switch(epctx->type) { case ET_INTR_OUT: case ET_INTR_IN: @@ -1375,7 +1372,10 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx return -1; } - ret = usb_handle_packet(dev, &xfer->packet); + if (xhci_setup_packet(xfer) < 0) { + return -1; + } + ret = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet); xhci_complete_packet(xfer, ret); if (!xfer->running_async && !xfer->running_retry) { @@ -1418,7 +1418,9 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid trace_usb_xhci_xfer_retry(xfer); assert(xfer->running_retry); - xhci_setup_packet(xfer, xfer->packet.ep->dev); + if (xhci_setup_packet(xfer) < 0) { + return; + } result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet); if (result == USB_RET_NAK) { return; From 01546fa6624ad0d1068423c58fa31bdfc44da2bf Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 21 Aug 2012 12:32:58 +0200 Subject: [PATCH 0283/2270] xhci: implement mfindex Implement mfindex register and mfindex wrap event. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 53 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index c108c9d47d..1d9940dcc3 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -380,8 +380,6 @@ struct XHCIState { XHCISlot slots[MAXSLOTS]; /* Runtime Registers */ - uint32_t mfindex; - /* note: we only support one interrupter */ uint32_t iman; uint32_t imod; uint32_t erstsz; @@ -390,6 +388,9 @@ struct XHCIState { uint32_t erdp_low; uint32_t erdp_high; + int64_t mfindex_start; + QEMUTimer *mfwrap_timer; + dma_addr_t er_start; uint32_t er_size; bool er_pcs; @@ -410,6 +411,11 @@ typedef struct XHCIEvRingSeg { uint32_t rsvd; } XHCIEvRingSeg; +static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, + unsigned int epid); +static void xhci_event(XHCIState *xhci, XHCIEvent *event); +static void xhci_write_event(XHCIState *xhci, XHCIEvent *event); + static const char *TRBType_names[] = { [TRB_RESERVED] = "TRB_RESERVED", [TR_NORMAL] = "TR_NORMAL", @@ -462,8 +468,36 @@ static const char *trb_name(XHCITRB *trb) ARRAY_SIZE(TRBType_names)); } -static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, - unsigned int epid); +static uint64_t xhci_mfindex_get(XHCIState *xhci) +{ + int64_t now = qemu_get_clock_ns(vm_clock); + return (now - xhci->mfindex_start) / 125000; +} + +static void xhci_mfwrap_update(XHCIState *xhci) +{ + const uint32_t bits = USBCMD_RS | USBCMD_EWE; + uint32_t mfindex, left; + int64_t now; + + if ((xhci->usbcmd & bits) == bits) { + now = qemu_get_clock_ns(vm_clock); + mfindex = ((now - xhci->mfindex_start) / 125000) & 0x3fff; + left = 0x4000 - mfindex; + qemu_mod_timer(xhci->mfwrap_timer, now + left * 125000); + } else { + qemu_del_timer(xhci->mfwrap_timer); + } +} + +static void xhci_mfwrap_timer(void *opaque) +{ + XHCIState *xhci = opaque; + XHCIEvent wrap = { ER_MFINDEX_WRAP, CC_SUCCESS }; + + xhci_event(xhci, &wrap); + xhci_mfwrap_update(xhci); +} static inline dma_addr_t xhci_addr64(uint32_t low, uint32_t high) { @@ -793,6 +827,7 @@ static void xhci_run(XHCIState *xhci) { trace_usb_xhci_run(); xhci->usbsts &= ~USBSTS_HCH; + xhci->mfindex_start = qemu_get_clock_ns(vm_clock); } static void xhci_stop(XHCIState *xhci) @@ -2048,7 +2083,6 @@ static void xhci_reset(DeviceState *dev) xhci_update_port(xhci, xhci->ports + i, 0); } - xhci->mfindex = 0; xhci->iman = 0; xhci->imod = 0; xhci->erstsz = 0; @@ -2062,6 +2096,9 @@ static void xhci_reset(DeviceState *dev) xhci->er_full = 0; xhci->ev_buffer_put = 0; xhci->ev_buffer_get = 0; + + xhci->mfindex_start = qemu_get_clock_ns(vm_clock); + xhci_mfwrap_update(xhci); } static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg) @@ -2264,6 +2301,7 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val) xhci_stop(xhci); } xhci->usbcmd = val & 0xc0f; + xhci_mfwrap_update(xhci); if (val & USBCMD_HCRST) { xhci_reset(&xhci->pci_dev.qdev); } @@ -2315,8 +2353,7 @@ static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg) switch (reg) { case 0x00: /* MFINDEX */ - fprintf(stderr, "xhci_runtime_read: MFINDEX not yet implemented\n"); - ret = xhci->mfindex; + ret = xhci_mfindex_get(xhci) & 0x3fff; break; case 0x20: /* IMAN */ ret = xhci->iman; @@ -2616,6 +2653,8 @@ static int usb_xhci_initfn(struct PCIDevice *dev) usb_xhci_init(xhci, &dev->qdev); + xhci->mfwrap_timer = qemu_new_timer_ns(vm_clock, xhci_mfwrap_timer, xhci); + xhci->irq = xhci->pci_dev.irq[0]; memory_region_init_io(&xhci->mem, &xhci_mem_ops, xhci, From 3d1396842dc8acd691d3e5d1d3c59ade39776e5a Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 24 Aug 2012 14:13:08 +0200 Subject: [PATCH 0284/2270] xhci: iso xfer support Add support for iso transfers. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 117 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 101 insertions(+), 16 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 1d9940dcc3..2dc8699f73 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -325,9 +325,15 @@ typedef struct XHCITransfer { unsigned int pkts; unsigned int pktsize; unsigned int cur_pkt; + + uint64_t mfindex_kick; } XHCITransfer; typedef struct XHCIEPContext { + XHCIState *xhci; + unsigned int slotid; + unsigned int epid; + XHCIRing ring; unsigned int next_xfer; unsigned int comp_xfer; @@ -337,6 +343,11 @@ typedef struct XHCIEPContext { dma_addr_t pctx; unsigned int max_psize; uint32_t state; + + /* iso xfer scheduling */ + unsigned int interval; + int64_t mfindex_last; + QEMUTimer *kick_timer; } XHCIEPContext; typedef struct XHCISlot { @@ -856,6 +867,12 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx, epctx->state = state; } +static void xhci_ep_kick_timer(void *opaque) +{ + XHCIEPContext *epctx = opaque; + xhci_kick_ep(epctx->xhci, epctx->slotid, epctx->epid); +} + static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid, dma_addr_t pctx, uint32_t *ctx) @@ -877,6 +894,9 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, epctx = g_malloc(sizeof(XHCIEPContext)); memset(epctx, 0, sizeof(XHCIEPContext)); + epctx->xhci = xhci; + epctx->slotid = slotid; + epctx->epid = epid; slot->eps[epid-1] = epctx; @@ -895,6 +915,10 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, usb_packet_init(&epctx->transfers[i].packet); } + epctx->interval = 1 << (ctx[0] >> 16) & 0xff; + epctx->mfindex_last = 0; + epctx->kick_timer = qemu_new_timer_ns(vm_clock, xhci_ep_kick_timer, epctx); + epctx->state = EP_RUNNING; ctx[0] &= ~EP_STATE_MASK; ctx[0] |= EP_RUNNING; @@ -934,6 +958,7 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid, if (t->running_retry) { t->running_retry = 0; epctx->retry = NULL; + qemu_del_timer(epctx->kick_timer); } if (t->trbs) { g_free(t->trbs); @@ -969,6 +994,7 @@ static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid, xhci_set_ep_state(xhci, epctx, EP_DISABLED); + qemu_free_timer(epctx->kick_timer); g_free(epctx); slot->eps[epid-1] = NULL; @@ -1376,29 +1402,70 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) return 0; } +static void xhci_calc_iso_kick(XHCIState *xhci, XHCITransfer *xfer, + XHCIEPContext *epctx, uint64_t mfindex) +{ + if (xfer->trbs[0].control & TRB_TR_SIA) { + uint64_t asap = ((mfindex + epctx->interval - 1) & + ~(epctx->interval-1)); + if (asap >= epctx->mfindex_last && + asap <= epctx->mfindex_last + epctx->interval * 4) { + xfer->mfindex_kick = epctx->mfindex_last + epctx->interval; + } else { + xfer->mfindex_kick = asap; + } + } else { + xfer->mfindex_kick = (xfer->trbs[0].control >> TRB_TR_FRAMEID_SHIFT) + & TRB_TR_FRAMEID_MASK; + xfer->mfindex_kick |= mfindex & ~0x3fff; + if (xfer->mfindex_kick < mfindex) { + xfer->mfindex_kick += 0x4000; + } + } +} + +static void xhci_check_iso_kick(XHCIState *xhci, XHCITransfer *xfer, + XHCIEPContext *epctx, uint64_t mfindex) +{ + if (xfer->mfindex_kick > mfindex) { + qemu_mod_timer(epctx->kick_timer, qemu_get_clock_ns(vm_clock) + + (xfer->mfindex_kick - mfindex) * 125000); + xfer->running_retry = 1; + } else { + epctx->mfindex_last = xfer->mfindex_kick; + qemu_del_timer(epctx->kick_timer); + xfer->running_retry = 0; + } +} + + static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx) { + uint64_t mfindex; int ret; DPRINTF("xhci_submit(slotid=%d,epid=%d)\n", xfer->slotid, xfer->epid); xfer->in_xfer = epctx->type>>2; - if (epctx->type == ET_ISO_IN || epctx->type == ET_ISO_OUT) { - xfer->pkts = 1; - } else { - xfer->pkts = 0; - } - switch(epctx->type) { case ET_INTR_OUT: case ET_INTR_IN: case ET_BULK_OUT: case ET_BULK_IN: + xfer->pkts = 0; + xfer->iso_xfer = false; break; case ET_ISO_OUT: case ET_ISO_IN: - FIXME(); + xfer->pkts = 1; + xfer->iso_xfer = true; + mfindex = xhci_mfindex_get(xhci); + xhci_calc_iso_kick(xhci, xfer, epctx, mfindex); + xhci_check_iso_kick(xhci, xfer, epctx, mfindex); + if (xfer->running_retry) { + return -1; + } break; default: fprintf(stderr, "xhci: unknown or unhandled EP " @@ -1428,6 +1495,7 @@ static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid) { XHCIEPContext *epctx; + uint64_t mfindex; int length; int i; @@ -1447,20 +1515,35 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid } if (epctx->retry) { - /* retry nak'ed transfer */ XHCITransfer *xfer = epctx->retry; int result; trace_usb_xhci_xfer_retry(xfer); assert(xfer->running_retry); - if (xhci_setup_packet(xfer) < 0) { - return; + if (xfer->iso_xfer) { + /* retry delayed iso transfer */ + mfindex = xhci_mfindex_get(xhci); + xhci_check_iso_kick(xhci, xfer, epctx, mfindex); + if (xfer->running_retry) { + return; + } + if (xhci_setup_packet(xfer) < 0) { + return; + } + result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet); + assert(result != USB_RET_NAK); + xhci_complete_packet(xfer, result); + } else { + /* retry nak'ed transfer */ + if (xhci_setup_packet(xfer) < 0) { + return; + } + result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet); + if (result == USB_RET_NAK) { + return; + } + xhci_complete_packet(xfer, result); } - result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet); - if (result == USB_RET_NAK) { - return; - } - xhci_complete_packet(xfer, result); assert(!xfer->running_retry); epctx->retry = NULL; } @@ -1512,7 +1595,9 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid if (xhci_fire_transfer(xhci, xfer, epctx) >= 0) { epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE; } else { - fprintf(stderr, "xhci: error firing data transfer\n"); + if (!xfer->iso_xfer) { + fprintf(stderr, "xhci: error firing data transfer\n"); + } } } From 873123fe094546ba99ff96d089e8eb02f307043d Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 27 Aug 2012 16:09:20 +0200 Subject: [PATCH 0285/2270] xhci: trace cc codes in cleartext Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++- trace-events | 2 +- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 2dc8699f73..0fd6a029c5 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -465,6 +465,45 @@ static const char *TRBType_names[] = { [CR_VENDOR_NEC_CHALLENGE_RESPONSE] = "CR_VENDOR_NEC_CHALLENGE_RESPONSE", }; +static const char *TRBCCode_names[] = { + [CC_INVALID] = "CC_INVALID", + [CC_SUCCESS] = "CC_SUCCESS", + [CC_DATA_BUFFER_ERROR] = "CC_DATA_BUFFER_ERROR", + [CC_BABBLE_DETECTED] = "CC_BABBLE_DETECTED", + [CC_USB_TRANSACTION_ERROR] = "CC_USB_TRANSACTION_ERROR", + [CC_TRB_ERROR] = "CC_TRB_ERROR", + [CC_STALL_ERROR] = "CC_STALL_ERROR", + [CC_RESOURCE_ERROR] = "CC_RESOURCE_ERROR", + [CC_BANDWIDTH_ERROR] = "CC_BANDWIDTH_ERROR", + [CC_NO_SLOTS_ERROR] = "CC_NO_SLOTS_ERROR", + [CC_INVALID_STREAM_TYPE_ERROR] = "CC_INVALID_STREAM_TYPE_ERROR", + [CC_SLOT_NOT_ENABLED_ERROR] = "CC_SLOT_NOT_ENABLED_ERROR", + [CC_EP_NOT_ENABLED_ERROR] = "CC_EP_NOT_ENABLED_ERROR", + [CC_SHORT_PACKET] = "CC_SHORT_PACKET", + [CC_RING_UNDERRUN] = "CC_RING_UNDERRUN", + [CC_RING_OVERRUN] = "CC_RING_OVERRUN", + [CC_VF_ER_FULL] = "CC_VF_ER_FULL", + [CC_PARAMETER_ERROR] = "CC_PARAMETER_ERROR", + [CC_BANDWIDTH_OVERRUN] = "CC_BANDWIDTH_OVERRUN", + [CC_CONTEXT_STATE_ERROR] = "CC_CONTEXT_STATE_ERROR", + [CC_NO_PING_RESPONSE_ERROR] = "CC_NO_PING_RESPONSE_ERROR", + [CC_EVENT_RING_FULL_ERROR] = "CC_EVENT_RING_FULL_ERROR", + [CC_INCOMPATIBLE_DEVICE_ERROR] = "CC_INCOMPATIBLE_DEVICE_ERROR", + [CC_MISSED_SERVICE_ERROR] = "CC_MISSED_SERVICE_ERROR", + [CC_COMMAND_RING_STOPPED] = "CC_COMMAND_RING_STOPPED", + [CC_COMMAND_ABORTED] = "CC_COMMAND_ABORTED", + [CC_STOPPED] = "CC_STOPPED", + [CC_STOPPED_LENGTH_INVALID] = "CC_STOPPED_LENGTH_INVALID", + [CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR] + = "CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR", + [CC_ISOCH_BUFFER_OVERRUN] = "CC_ISOCH_BUFFER_OVERRUN", + [CC_EVENT_LOST_ERROR] = "CC_EVENT_LOST_ERROR", + [CC_UNDEFINED_ERROR] = "CC_UNDEFINED_ERROR", + [CC_INVALID_STREAM_ID_ERROR] = "CC_INVALID_STREAM_ID_ERROR", + [CC_SECONDARY_BANDWIDTH_ERROR] = "CC_SECONDARY_BANDWIDTH_ERROR", + [CC_SPLIT_TRANSACTION_ERROR] = "CC_SPLIT_TRANSACTION_ERROR", +}; + static const char *lookup_name(uint32_t index, const char **list, uint32_t llen) { if (index >= llen || list[index] == NULL) { @@ -479,6 +518,12 @@ static const char *trb_name(XHCITRB *trb) ARRAY_SIZE(TRBType_names)); } +static const char *event_name(XHCIEvent *event) +{ + return lookup_name(event->ccode, TRBCCode_names, + ARRAY_SIZE(TRBCCode_names)); +} + static uint64_t xhci_mfindex_get(XHCIState *xhci) { int64_t now = qemu_get_clock_ns(vm_clock); @@ -574,7 +619,8 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event) ev_trb.control = cpu_to_le32(ev_trb.control); trace_usb_xhci_queue_event(xhci->er_ep_idx, trb_name(&ev_trb), - ev_trb.parameter, ev_trb.status, ev_trb.control); + event_name(event), ev_trb.parameter, + ev_trb.status, ev_trb.control); addr = xhci->er_start + TRB_SIZE*xhci->er_ep_idx; pci_dma_write(&xhci->pci_dev, addr, &ev_trb, TRB_SIZE); diff --git a/trace-events b/trace-events index c83d65edef..27d59cdad8 100644 --- a/trace-events +++ b/trace-events @@ -313,7 +313,7 @@ usb_xhci_runtime_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x" usb_xhci_doorbell_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x" usb_xhci_irq_intx(uint32_t level) "level %d" usb_xhci_irq_msi(uint32_t nr) "nr %d" -usb_xhci_queue_event(uint32_t idx, const char *name, uint64_t param, uint32_t status, uint32_t control) "idx %d, %s, p %016" PRIx64 ", s %08x, c 0x%08x" +usb_xhci_queue_event(uint32_t idx, const char *trb, const char *evt, uint64_t param, uint32_t status, uint32_t control) "idx %d, %s, %s, p %016" PRIx64 ", s %08x, c 0x%08x" usb_xhci_fetch_trb(uint64_t addr, const char *name, uint64_t param, uint32_t status, uint32_t control) "addr %016" PRIx64 ", %s, p %016" PRIx64 ", s %08x, c 0x%08x" usb_xhci_slot_enable(uint32_t slotid) "slotid %d" usb_xhci_slot_disable(uint32_t slotid) "slotid %d" From d829fde97d25bfa5ec62d21d28ed32991e56ffc7 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 29 Aug 2012 12:54:59 +0200 Subject: [PATCH 0286/2270] xhci: add trace_usb_xhci_ep_set_dequeue Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 2 +- trace-events | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 0fd6a029c5..9521126069 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1145,7 +1145,7 @@ static TRBCCode xhci_set_ep_dequeue(XHCIState *xhci, unsigned int slotid, return CC_TRB_ERROR; } - DPRINTF("xhci_set_ep_dequeue(%d, %d, %016"PRIx64")\n", slotid, epid, pdequeue); + trace_usb_xhci_ep_set_dequeue(slotid, epid, pdequeue); dequeue = xhci_mask64(pdequeue); slot = &xhci->slots[slotid-1]; diff --git a/trace-events b/trace-events index 27d59cdad8..a894689ca4 100644 --- a/trace-events +++ b/trace-events @@ -323,6 +323,7 @@ usb_xhci_slot_evaluate(uint32_t slotid) "slotid %d" usb_xhci_slot_reset(uint32_t slotid) "slotid %d" usb_xhci_ep_enable(uint32_t slotid, uint32_t epid) "slotid %d, epid %d" usb_xhci_ep_disable(uint32_t slotid, uint32_t epid) "slotid %d, epid %d" +usb_xhci_ep_set_dequeue(uint32_t slotid, uint32_t epid, uint64_t param) "slotid %d, epid %d, ptr %016" PRIx64 usb_xhci_ep_kick(uint32_t slotid, uint32_t epid) "slotid %d, epid %d" usb_xhci_ep_stop(uint32_t slotid, uint32_t epid) "slotid %d, epid %d" usb_xhci_ep_reset(uint32_t slotid, uint32_t epid) "slotid %d, epid %d" From 8e9f18b6db1cd67f0a7efd7d0285bee489445197 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 30 Aug 2012 12:42:32 +0200 Subject: [PATCH 0287/2270] xhci: fix runtime write tracepoint Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 9521126069..1920edae7a 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2518,7 +2518,7 @@ static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg) static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val) { - trace_usb_xhci_runtime_read(reg, val); + trace_usb_xhci_runtime_write(reg, val); switch (reg) { case 0x20: /* IMAN */ From 106b214c4fbba80699b32b63020432cbd1cf95db Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 23 Aug 2012 13:26:25 +0200 Subject: [PATCH 0288/2270] xhci: update register layout Change the register layout to be a bit more sparse and also not depend on the number of ports. Useful when for making the number of ports runtime-configurable. --- hw/usb/hcd-xhci.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 1920edae7a..92ee62943f 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -36,13 +36,12 @@ #define FIXME() do { fprintf(stderr, "FIXME %s:%d\n", \ __func__, __LINE__); abort(); } while (0) -#define MAXSLOTS 8 -#define MAXINTRS 1 - #define USB2_PORTS 4 #define USB3_PORTS 4 #define MAXPORTS (USB2_PORTS+USB3_PORTS) +#define MAXSLOTS MAXPORTS +#define MAXINTRS 1 /* MAXPORTS */ #define TD_QUEUE 24 @@ -53,16 +52,22 @@ #define ER_FULL_HACK #define LEN_CAP 0x40 -#define OFF_OPER LEN_CAP #define LEN_OPER (0x400 + 0x10 * MAXPORTS) -#define OFF_RUNTIME ((OFF_OPER + LEN_OPER + 0x20) & ~0x1f) -#define LEN_RUNTIME (0x20 + MAXINTRS * 0x20) -#define OFF_DOORBELL (OFF_RUNTIME + LEN_RUNTIME) +#define LEN_RUNTIME ((MAXINTRS + 1) * 0x20) #define LEN_DOORBELL ((MAXSLOTS + 1) * 0x20) +#define OFF_OPER LEN_CAP +#define OFF_RUNTIME 0x1000 +#define OFF_DOORBELL 0x2000 /* must be power of 2 */ -#define LEN_REGS 0x2000 +#define LEN_REGS 0x4000 +#if (OFF_OPER + LEN_OPER) > OFF_RUNTIME +#error Increase OFF_RUNTIME +#endif +#if (OFF_RUNTIME + LEN_RUNTIME) > OFF_DOORBELL +#error Increase OFF_DOORBELL +#endif #if (OFF_DOORBELL + LEN_DOORBELL) > LEN_REGS # error Increase LEN_REGS #endif From 0846e6359c407e372f446723b8b7b09ac20d0f03 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 28 Aug 2012 13:38:01 +0200 Subject: [PATCH 0289/2270] xhci: update port handling This patch changes the way xhci ports are linked to USBPorts. The fixed 1:1 relationship between xhci ports and USBPorts is gone. Now each USBPort represents a physical plug which has usually two xhci ports assigned: one usb2 and ond usb3 port. usb devices show up at one or the other, depending on whenever they support superspeed or not. This patch also makes the number of usb2 and usb3 ports runtime configurable by adding 'p2' and 'p3' properties. It is allowed to have different numbers of usb2 and usb3 ports. Specifying p2=4,p3=2 will give you an xhci adapter which supports all speeds on physical ports 1+2 and usb2 only on ports 3+4. --- hw/usb/hcd-xhci.c | 137 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 97 insertions(+), 40 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 92ee62943f..f0c1859861 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -36,10 +36,10 @@ #define FIXME() do { fprintf(stderr, "FIXME %s:%d\n", \ __func__, __LINE__); abort(); } while (0) -#define USB2_PORTS 4 -#define USB3_PORTS 4 +#define MAXPORTS_2 8 +#define MAXPORTS_3 8 -#define MAXPORTS (USB2_PORTS+USB3_PORTS) +#define MAXPORTS (MAXPORTS_2+MAXPORTS_3) #define MAXSLOTS MAXPORTS #define MAXINTRS 1 /* MAXPORTS */ @@ -300,8 +300,10 @@ typedef struct XHCIRing { } XHCIRing; typedef struct XHCIPort { - USBPort port; uint32_t portsc; + uint32_t portnr; + USBPort *uport; + uint32_t speedmask; } XHCIPort; struct XHCIState; @@ -379,9 +381,13 @@ struct XHCIState { qemu_irq irq; MemoryRegion mem; const char *name; - uint32_t msi; unsigned int devaddr; + /* properties */ + uint32_t numports_2; + uint32_t numports_3; + uint32_t msi; + /* Operational Registers */ uint32_t usbcmd; uint32_t usbsts; @@ -392,8 +398,10 @@ struct XHCIState { uint32_t dcbaap_high; uint32_t config; + USBPort uports[MAX(MAXPORTS_2, MAXPORTS_3)]; XHCIPort ports[MAXPORTS]; XHCISlot slots[MAXSLOTS]; + uint32_t numports; /* Runtime Registers */ uint32_t iman; @@ -578,6 +586,28 @@ static inline dma_addr_t xhci_mask64(uint64_t addr) } } +static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport) +{ + int index; + + if (!uport->dev) { + return NULL; + } + switch (uport->dev->speed) { + case USB_SPEED_LOW: + case USB_SPEED_FULL: + case USB_SPEED_HIGH: + index = uport->index; + break; + case USB_SPEED_SUPER: + index = uport->index + xhci->numports_2; + break; + default: + return NULL; + } + return &xhci->ports[index]; +} + static void xhci_irq_update(XHCIState *xhci) { int level = 0; @@ -1126,7 +1156,7 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid, ep |= 0x80; } - dev = xhci->ports[xhci->slots[slotid-1].port-1].port.dev; + dev = xhci->ports[xhci->slots[slotid-1].port-1].uport->dev; if (!dev) { return CC_USB_TRANSACTION_ERROR; } @@ -1313,7 +1343,7 @@ static USBDevice *xhci_find_device(XHCIPort *port, uint8_t addr) if (!(port->portsc & PORTSC_PED)) { return NULL; } - return usb_find_device(&port->port, addr); + return usb_find_device(port->uport, addr); } static int xhci_setup_packet(XHCITransfer *xfer) @@ -1734,9 +1764,9 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]); port = (slot_ctx[1]>>16) & 0xFF; - dev = xhci->ports[port-1].port.dev; + dev = xhci->ports[port-1].uport->dev; - if (port < 1 || port > MAXPORTS) { + if (port < 1 || port > xhci->numports) { fprintf(stderr, "xhci: bad port %d\n", port); return CC_TRB_ERROR; } else if (!dev) { @@ -1985,7 +2015,7 @@ static unsigned int xhci_get_slot(XHCIState *xhci, XHCIEvent *event, XHCITRB *tr static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx) { dma_addr_t ctx; - uint8_t bw_ctx[MAXPORTS+1]; + uint8_t bw_ctx[xhci->numports+1]; DPRINTF("xhci_get_port_bandwidth()\n"); @@ -1995,7 +2025,7 @@ static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx) /* TODO: actually implement real values here */ bw_ctx[0] = 0; - memset(&bw_ctx[1], 80, MAXPORTS); /* 80% */ + memset(&bw_ctx[1], 80, xhci->numports); /* 80% */ pci_dma_write(&xhci->pci_dev, ctx, bw_ctx, sizeof(bw_ctx)); return CC_SUCCESS; @@ -2165,12 +2195,11 @@ static void xhci_process_commands(XHCIState *xhci) static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach) { - int nr = port->port.index + 1; - port->portsc = PORTSC_PP; - if (port->port.dev && port->port.dev->attached && !is_detach) { + if (port->uport->dev && port->uport->dev->attached && !is_detach && + (1 << port->uport->dev->speed) & port->speedmask) { port->portsc |= PORTSC_CCS; - switch (port->port.dev->speed) { + switch (port->uport->dev->speed) { case USB_SPEED_LOW: port->portsc |= PORTSC_SPEED_LOW; break; @@ -2180,14 +2209,18 @@ static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach) case USB_SPEED_HIGH: port->portsc |= PORTSC_SPEED_HIGH; break; + case USB_SPEED_SUPER: + port->portsc |= PORTSC_SPEED_SUPER; + break; } } if (xhci_running(xhci)) { port->portsc |= PORTSC_CSC; - XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, nr << 24}; + XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, + port->portnr << 24}; xhci_event(xhci, &ev); - DPRINTF("xhci: port change event for port %d\n", nr); + DPRINTF("xhci: port change event for port %d\n", port->portnr); } } @@ -2215,7 +2248,7 @@ static void xhci_reset(DeviceState *dev) xhci_disable_slot(xhci, i+1); } - for (i = 0; i < MAXPORTS; i++) { + for (i = 0; i < xhci->numports; i++) { xhci_update_port(xhci, xhci->ports + i, 0); } @@ -2246,7 +2279,8 @@ static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg) ret = 0x01000000 | LEN_CAP; break; case 0x04: /* HCSPARAMS 1 */ - ret = (MAXPORTS<<24) | (MAXINTRS<<8) | MAXSLOTS; + ret = ((xhci->numports_2+xhci->numports_3)<<24) + | (MAXINTRS<<8) | MAXSLOTS; break; case 0x08: /* HCSPARAMS 2 */ ret = 0x0000000f; @@ -2276,7 +2310,7 @@ static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg) ret = 0x20425455; /* "USB " */ break; case 0x28: /* Supported Protocol:08 */ - ret = 0x00000001 | (USB2_PORTS<<8); + ret = 0x00000001 | (xhci->numports_2<<8); break; case 0x2c: /* Supported Protocol:0c */ ret = 0x00000000; /* reserved */ @@ -2288,7 +2322,7 @@ static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg) ret = 0x20425455; /* "USB " */ break; case 0x38: /* Supported Protocol:08 */ - ret = 0x00000000 | (USB2_PORTS+1) | (USB3_PORTS<<8); + ret = 0x00000000 | (xhci->numports_2+1) | (xhci->numports_3<<8); break; case 0x3c: /* Supported Protocol:0c */ ret = 0x00000000; /* reserved */ @@ -2307,7 +2341,7 @@ static uint32_t xhci_port_read(XHCIState *xhci, uint32_t reg) uint32_t port = reg >> 4; uint32_t ret; - if (port >= MAXPORTS) { + if (port >= xhci->numports) { fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port); ret = 0; goto out; @@ -2340,7 +2374,7 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val) trace_usb_xhci_port_write(port, reg & 0x0f, val); - if (port >= MAXPORTS) { + if (port >= xhci->numports) { fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port); return; } @@ -2362,7 +2396,7 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val) /* write-1-to-start bits */ if (val & PORTSC_PR) { DPRINTF("xhci: port %d reset\n", port); - usb_device_reset(xhci->ports[port].port.dev); + usb_device_reset(xhci->ports[port].uport->dev); portsc |= PORTSC_PRC | PORTSC_PED; } xhci->ports[port].portsc = portsc; @@ -2657,7 +2691,7 @@ static const MemoryRegionOps xhci_mem_ops = { static void xhci_attach(USBPort *usbport) { XHCIState *xhci = usbport->opaque; - XHCIPort *port = &xhci->ports[usbport->index]; + XHCIPort *port = xhci_lookup_port(xhci, usbport); xhci_update_port(xhci, port, 0); } @@ -2665,7 +2699,7 @@ static void xhci_attach(USBPort *usbport) static void xhci_detach(USBPort *usbport) { XHCIState *xhci = usbport->opaque; - XHCIPort *port = &xhci->ports[usbport->index]; + XHCIPort *port = xhci_lookup_port(xhci, usbport); xhci_update_port(xhci, port, 1); } @@ -2673,9 +2707,9 @@ static void xhci_detach(USBPort *usbport) static void xhci_wakeup(USBPort *usbport) { XHCIState *xhci = usbport->opaque; - XHCIPort *port = &xhci->ports[usbport->index]; - int nr = port->port.index + 1; - XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, nr << 24}; + XHCIPort *port = xhci_lookup_port(xhci, usbport); + XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, + port->portnr << 24}; uint32_t pls; pls = (port->portsc >> PORTSC_PLS_SHIFT) & PORTSC_PLS_MASK; @@ -2757,22 +2791,43 @@ static USBBusOps xhci_bus_ops = { static void usb_xhci_init(XHCIState *xhci, DeviceState *dev) { - int i; + XHCIPort *port; + int i, usbports, speedmask; xhci->usbsts = USBSTS_HCH; + if (xhci->numports_2 > MAXPORTS_2) { + xhci->numports_2 = MAXPORTS_2; + } + if (xhci->numports_3 > MAXPORTS_3) { + xhci->numports_3 = MAXPORTS_3; + } + usbports = MAX(xhci->numports_2, xhci->numports_3); + xhci->numports = xhci->numports_2 + xhci->numports_3; + usb_bus_new(&xhci->bus, &xhci_bus_ops, &xhci->pci_dev.qdev); - for (i = 0; i < MAXPORTS; i++) { - memset(&xhci->ports[i], 0, sizeof(xhci->ports[i])); - usb_register_port(&xhci->bus, &xhci->ports[i].port, xhci, i, - &xhci_port_ops, - USB_SPEED_MASK_LOW | - USB_SPEED_MASK_FULL | - USB_SPEED_MASK_HIGH); - } - for (i = 0; i < MAXSLOTS; i++) { - xhci->slots[i].enabled = 0; + for (i = 0; i < usbports; i++) { + speedmask = 0; + if (i < xhci->numports_2) { + port = &xhci->ports[i]; + port->portnr = i + 1; + port->uport = &xhci->uports[i]; + port->speedmask = + USB_SPEED_MASK_LOW | + USB_SPEED_MASK_FULL | + USB_SPEED_MASK_HIGH; + speedmask |= port->speedmask; + } + if (i < xhci->numports_3) { + port = &xhci->ports[i + xhci->numports_2]; + port->portnr = i + 1 + xhci->numports_2; + port->uport = &xhci->uports[i]; + port->speedmask = USB_SPEED_MASK_SUPER; + speedmask |= port->speedmask; + } + usb_register_port(&xhci->bus, &xhci->uports[i], xhci, i, + &xhci_port_ops, speedmask); } } @@ -2828,6 +2883,8 @@ static const VMStateDescription vmstate_xhci = { static Property xhci_properties[] = { DEFINE_PROP_UINT32("msi", XHCIState, msi, 0), + DEFINE_PROP_UINT32("p2", XHCIState, numports_2, 4), + DEFINE_PROP_UINT32("p3", XHCIState, numports_3, 4), DEFINE_PROP_END_OF_LIST(), }; From 6d51b2bb07030c38e5f2d9048c6c474ca486fe9b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 28 Aug 2012 17:28:50 +0200 Subject: [PATCH 0290/2270] usb3: superspeed descriptors Add superspeed descriptor entry to USBDesc, advertise superspeed support when present. Signed-off-by: Gerd Hoffmann --- hw/usb/desc.c | 10 +++++++++- hw/usb/desc.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/hw/usb/desc.c b/hw/usb/desc.c index 0a9d3c9f60..3e8c6cb503 100644 --- a/hw/usb/desc.c +++ b/hw/usb/desc.c @@ -359,6 +359,9 @@ static void usb_desc_setdefaults(USBDevice *dev) case USB_SPEED_HIGH: dev->device = desc->high; break; + case USB_SPEED_SUPER: + dev->device = desc->super; + break; } usb_desc_set_config(dev, 0); } @@ -376,6 +379,9 @@ void usb_desc_init(USBDevice *dev) if (desc->high) { dev->speedmask |= USB_SPEED_MASK_HIGH; } + if (desc->super) { + dev->speedmask |= USB_SPEED_MASK_SUPER; + } usb_desc_setdefaults(dev); } @@ -384,7 +390,9 @@ void usb_desc_attach(USBDevice *dev) const USBDesc *desc = usb_device_get_usb_desc(dev); assert(desc != NULL); - if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) { + if (desc->super && (dev->port->speedmask & USB_SPEED_MASK_SUPER)) { + dev->speed = USB_SPEED_SUPER; + } else if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) { dev->speed = USB_SPEED_HIGH; } else if (desc->full && (dev->port->speedmask & USB_SPEED_MASK_FULL)) { dev->speed = USB_SPEED_FULL; diff --git a/hw/usb/desc.h b/hw/usb/desc.h index 7cf5442945..d89fa41666 100644 --- a/hw/usb/desc.h +++ b/hw/usb/desc.h @@ -152,6 +152,7 @@ struct USBDesc { USBDescID id; const USBDescDevice *full; const USBDescDevice *high; + const USBDescDevice *super; const char* const *str; }; From b43a28517620c4eba8ab8b96b08e5ec85aedeeaf Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 28 Aug 2012 17:28:03 +0200 Subject: [PATCH 0291/2270] usb3: superspeed endpoint companion Add support for building superspeed endpoint companion descriptors, create them for superspeed usb devices. Signed-off-by: Gerd Hoffmann --- hw/usb.h | 1 + hw/usb/desc.c | 55 +++++++++++++++++++++++++++++++++++++-------------- hw/usb/desc.h | 26 +++++++++++++++++++----- 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/hw/usb.h b/hw/usb.h index 684e3f4b54..78ffdf4ef9 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -137,6 +137,7 @@ #define USB_DT_INTERFACE_ASSOC 0x0B #define USB_DT_CS_INTERFACE 0x24 #define USB_DT_CS_ENDPOINT 0x25 +#define USB_DT_ENDPOINT_COMPANION 0x30 #define USB_ENDPOINT_XFER_CONTROL 0 #define USB_ENDPOINT_XFER_ISOC 1 diff --git a/hw/usb/desc.c b/hw/usb/desc.c index 3e8c6cb503..8f5a8e5199 100644 --- a/hw/usb/desc.c +++ b/hw/usb/desc.c @@ -76,7 +76,8 @@ int usb_desc_device_qualifier(const USBDescDevice *dev, return bLength; } -int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len) +int usb_desc_config(const USBDescConfig *conf, int flags, + uint8_t *dest, size_t len) { uint8_t bLength = 0x09; uint16_t wTotalLength = 0; @@ -99,7 +100,7 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len) /* handle grouped interfaces if any */ for (i = 0; i < conf->nif_groups; i++) { - rc = usb_desc_iface_group(&(conf->if_groups[i]), + rc = usb_desc_iface_group(&(conf->if_groups[i]), flags, dest + wTotalLength, len - wTotalLength); if (rc < 0) { @@ -110,7 +111,8 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len) /* handle normal (ungrouped / no IAD) interfaces if any */ for (i = 0; i < conf->nif; i++) { - rc = usb_desc_iface(conf->ifs + i, dest + wTotalLength, len - wTotalLength); + rc = usb_desc_iface(conf->ifs + i, flags, + dest + wTotalLength, len - wTotalLength); if (rc < 0) { return rc; } @@ -122,8 +124,8 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len) return wTotalLength; } -int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest, - size_t len) +int usb_desc_iface_group(const USBDescIfaceAssoc *iad, int flags, + uint8_t *dest, size_t len) { int pos = 0; int i = 0; @@ -147,7 +149,7 @@ int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest, /* handle associated interfaces in this group */ for (i = 0; i < iad->nif; i++) { - int rc = usb_desc_iface(&(iad->ifs[i]), dest + pos, len - pos); + int rc = usb_desc_iface(&(iad->ifs[i]), flags, dest + pos, len - pos); if (rc < 0) { return rc; } @@ -157,7 +159,8 @@ int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest, return pos; } -int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len) +int usb_desc_iface(const USBDescIface *iface, int flags, + uint8_t *dest, size_t len) { uint8_t bLength = 0x09; int i, rc, pos = 0; @@ -188,7 +191,7 @@ int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len) } for (i = 0; i < iface->bNumEndpoints; i++) { - rc = usb_desc_endpoint(iface->eps + i, dest + pos, len - pos); + rc = usb_desc_endpoint(iface->eps + i, flags, dest + pos, len - pos); if (rc < 0) { return rc; } @@ -198,13 +201,15 @@ int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len) return pos; } -int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len) +int usb_desc_endpoint(const USBDescEndpoint *ep, int flags, + uint8_t *dest, size_t len) { uint8_t bLength = ep->is_audio ? 0x09 : 0x07; uint8_t extralen = ep->extra ? ep->extra[0] : 0; + uint8_t superlen = (flags & USB_DESC_FLAG_SUPER) ? 0x06 : 0; USBDescriptor *d = (void *)dest; - if (len < bLength + extralen) { + if (len < bLength + extralen + superlen) { return -1; } @@ -224,7 +229,21 @@ int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len) memcpy(dest + bLength, ep->extra, extralen); } - return bLength + extralen; + if (superlen) { + USBDescriptor *d = (void *)(dest + bLength + extralen); + + d->bLength = 0x06; + d->bDescriptorType = USB_DT_ENDPOINT_COMPANION; + + d->u.super_endpoint.bMaxBurst = ep->bMaxBurst; + d->u.super_endpoint.bmAttributes = ep->bmAttributes_super; + d->u.super_endpoint.wBytesPerInterval_lo = + usb_lo(ep->wBytesPerInterval); + d->u.super_endpoint.wBytesPerInterval_hi = + usb_hi(ep->wBytesPerInterval); + } + + return bLength + extralen + superlen; } int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len) @@ -509,7 +528,7 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len uint8_t buf[256]; uint8_t type = value >> 8; uint8_t index = value & 0xff; - int ret = -1; + int flags, ret = -1; if (dev->speed == USB_SPEED_HIGH) { other_dev = usb_device_get_usb_desc(dev)->full; @@ -517,6 +536,11 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len other_dev = usb_device_get_usb_desc(dev)->high; } + flags = 0; + if (dev->device->bcdUSB >= 0x0300) { + flags |= USB_DESC_FLAG_SUPER; + } + switch(type) { case USB_DT_DEVICE: ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf)); @@ -524,7 +548,8 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len break; case USB_DT_CONFIG: if (index < dev->device->bNumConfigurations) { - ret = usb_desc_config(dev->device->confs + index, buf, sizeof(buf)); + ret = usb_desc_config(dev->device->confs + index, flags, + buf, sizeof(buf)); } trace_usb_desc_config(dev->addr, index, len, ret); break; @@ -532,7 +557,6 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len ret = usb_desc_string(dev, index, buf, sizeof(buf)); trace_usb_desc_string(dev->addr, index, len, ret); break; - case USB_DT_DEVICE_QUALIFIER: if (other_dev != NULL) { ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf)); @@ -541,7 +565,8 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len break; case USB_DT_OTHER_SPEED_CONFIG: if (other_dev != NULL && index < other_dev->bNumConfigurations) { - ret = usb_desc_config(other_dev->confs + index, buf, sizeof(buf)); + ret = usb_desc_config(other_dev->confs + index, flags, + buf, sizeof(buf)); buf[0x01] = USB_DT_OTHER_SPEED_CONFIG; } trace_usb_desc_other_speed_config(dev->addr, index, len, ret); diff --git a/hw/usb/desc.h b/hw/usb/desc.h index d89fa41666..4b5e88d817 100644 --- a/hw/usb/desc.h +++ b/hw/usb/desc.h @@ -63,6 +63,12 @@ typedef struct USBDescriptor { uint8_t bRefresh; /* only audio ep */ uint8_t bSynchAddress; /* only audio ep */ } endpoint; + struct { + uint8_t bMaxBurst; + uint8_t bmAttributes; + uint8_t wBytesPerInterval_lo; + uint8_t wBytesPerInterval_hi; + } super_endpoint; } u; } QEMU_PACKED USBDescriptor; @@ -139,6 +145,11 @@ struct USBDescEndpoint { uint8_t is_audio; /* has bRefresh + bSynchAddress */ uint8_t *extra; + + /* superspeed endpoint companion */ + uint8_t bMaxBurst; + uint8_t bmAttributes_super; + uint16_t wBytesPerInterval; }; struct USBDescOther { @@ -156,16 +167,21 @@ struct USBDesc { const char* const *str; }; +#define USB_DESC_FLAG_SUPER (1 << 1) + /* generate usb packages from structs */ int usb_desc_device(const USBDescID *id, const USBDescDevice *dev, uint8_t *dest, size_t len); int usb_desc_device_qualifier(const USBDescDevice *dev, uint8_t *dest, size_t len); -int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len); -int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest, - size_t len); -int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len); -int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len); +int usb_desc_config(const USBDescConfig *conf, int flags, + uint8_t *dest, size_t len); +int usb_desc_iface_group(const USBDescIfaceAssoc *iad, int flags, + uint8_t *dest, size_t len); +int usb_desc_iface(const USBDescIface *iface, int flags, + uint8_t *dest, size_t len); +int usb_desc_endpoint(const USBDescEndpoint *ep, int flags, + uint8_t *dest, size_t len); int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len); /* control message emulation helpers */ From 2077469b58066da3cdac9e5b81d3c60178e6d300 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 28 Aug 2012 17:46:29 +0200 Subject: [PATCH 0292/2270] usb3: bos decriptor Add support for creating BOS descriptor and device cappability descriptors. Signed-off-by: Gerd Hoffmann --- hw/usb.h | 6 +++ hw/usb/desc.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++ hw/usb/desc.h | 25 ++++++++++++ trace-events | 1 + 4 files changed, 141 insertions(+) diff --git a/hw/usb.h b/hw/usb.h index 78ffdf4ef9..48c8926a76 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -135,10 +135,16 @@ #define USB_DT_OTHER_SPEED_CONFIG 0x07 #define USB_DT_DEBUG 0x0A #define USB_DT_INTERFACE_ASSOC 0x0B +#define USB_DT_BOS 0x0F +#define USB_DT_DEVICE_CAPABILITY 0x10 #define USB_DT_CS_INTERFACE 0x24 #define USB_DT_CS_ENDPOINT 0x25 #define USB_DT_ENDPOINT_COMPANION 0x30 +#define USB_DEV_CAP_WIRELESS 0x01 +#define USB_DEV_CAP_USB2_EXT 0x02 +#define USB_DEV_CAP_SUPERSPEED 0x03 + #define USB_ENDPOINT_XFER_CONTROL 0 #define USB_ENDPOINT_XFER_ISOC 1 #define USB_ENDPOINT_XFER_BULK 2 diff --git a/hw/usb/desc.c b/hw/usb/desc.c index 8f5a8e5199..1f12eaecbf 100644 --- a/hw/usb/desc.c +++ b/hw/usb/desc.c @@ -258,6 +258,111 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len) return bLength; } +static int usb_desc_cap_usb2_ext(const USBDesc *desc, uint8_t *dest, size_t len) +{ + uint8_t bLength = 0x07; + USBDescriptor *d = (void *)dest; + + if (len < bLength) { + return -1; + } + + d->bLength = bLength; + d->bDescriptorType = USB_DT_DEVICE_CAPABILITY; + d->u.cap.bDevCapabilityType = USB_DEV_CAP_USB2_EXT; + + d->u.cap.u.usb2_ext.bmAttributes_1 = (1 << 1); /* LPM */ + d->u.cap.u.usb2_ext.bmAttributes_2 = 0; + d->u.cap.u.usb2_ext.bmAttributes_3 = 0; + d->u.cap.u.usb2_ext.bmAttributes_4 = 0; + + return bLength; +} + +static int usb_desc_cap_super(const USBDesc *desc, uint8_t *dest, size_t len) +{ + uint8_t bLength = 0x0a; + USBDescriptor *d = (void *)dest; + + if (len < bLength) { + return -1; + } + + d->bLength = bLength; + d->bDescriptorType = USB_DT_DEVICE_CAPABILITY; + d->u.cap.bDevCapabilityType = USB_DEV_CAP_SUPERSPEED; + + d->u.cap.u.super.bmAttributes = 0; + d->u.cap.u.super.wSpeedsSupported_lo = 0; + d->u.cap.u.super.wSpeedsSupported_hi = 0; + d->u.cap.u.super.bFunctionalitySupport = 0; + d->u.cap.u.super.bU1DevExitLat = 0x0a; + d->u.cap.u.super.wU2DevExitLat_lo = 0x20; + d->u.cap.u.super.wU2DevExitLat_hi = 0; + + if (desc->full) { + d->u.cap.u.super.wSpeedsSupported_lo |= (1 << 1); + d->u.cap.u.super.bFunctionalitySupport = 1; + } + if (desc->high) { + d->u.cap.u.super.wSpeedsSupported_lo |= (1 << 2); + if (!d->u.cap.u.super.bFunctionalitySupport) { + d->u.cap.u.super.bFunctionalitySupport = 2; + } + } + if (desc->super) { + d->u.cap.u.super.wSpeedsSupported_lo |= (1 << 3); + if (!d->u.cap.u.super.bFunctionalitySupport) { + d->u.cap.u.super.bFunctionalitySupport = 3; + } + } + + return bLength; +} + +static int usb_desc_bos(const USBDesc *desc, uint8_t *dest, size_t len) +{ + uint8_t bLength = 0x05; + uint16_t wTotalLength = 0; + uint8_t bNumDeviceCaps = 0; + USBDescriptor *d = (void *)dest; + int rc; + + if (len < bLength) { + return -1; + } + + d->bLength = bLength; + d->bDescriptorType = USB_DT_BOS; + + wTotalLength += bLength; + + if (desc->high != NULL) { + rc = usb_desc_cap_usb2_ext(desc, dest + wTotalLength, + len - wTotalLength); + if (rc < 0) { + return rc; + } + wTotalLength += rc; + bNumDeviceCaps++; + } + + if (desc->super != NULL) { + rc = usb_desc_cap_super(desc, dest + wTotalLength, + len - wTotalLength); + if (rc < 0) { + return rc; + } + wTotalLength += rc; + bNumDeviceCaps++; + } + + d->u.bos.wTotalLength_lo = usb_lo(wTotalLength); + d->u.bos.wTotalLength_hi = usb_hi(wTotalLength); + d->u.bos.bNumDeviceCaps = bNumDeviceCaps; + return wTotalLength; +} + /* ------------------------------------------------------------------ */ static void usb_desc_ep_init(USBDevice *dev) @@ -571,6 +676,10 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len } trace_usb_desc_other_speed_config(dev->addr, index, len, ret); break; + case USB_DT_BOS: + ret = usb_desc_bos(desc, buf, sizeof(buf)); + trace_usb_desc_bos(dev->addr, len, ret); + break; case USB_DT_DEBUG: /* ignore silently */ diff --git a/hw/usb/desc.h b/hw/usb/desc.h index 4b5e88d817..68bb570679 100644 --- a/hw/usb/desc.h +++ b/hw/usb/desc.h @@ -69,6 +69,31 @@ typedef struct USBDescriptor { uint8_t wBytesPerInterval_lo; uint8_t wBytesPerInterval_hi; } super_endpoint; + struct { + uint8_t wTotalLength_lo; + uint8_t wTotalLength_hi; + uint8_t bNumDeviceCaps; + } bos; + struct { + uint8_t bDevCapabilityType; + union { + struct { + uint8_t bmAttributes_1; + uint8_t bmAttributes_2; + uint8_t bmAttributes_3; + uint8_t bmAttributes_4; + } usb2_ext; + struct { + uint8_t bmAttributes; + uint8_t wSpeedsSupported_lo; + uint8_t wSpeedsSupported_hi; + uint8_t bFunctionalitySupport; + uint8_t bU1DevExitLat; + uint8_t wU2DevExitLat_lo; + uint8_t wU2DevExitLat_hi; + } super; + } u; + } cap; } u; } QEMU_PACKED USBDescriptor; diff --git a/trace-events b/trace-events index a894689ca4..5bc591a721 100644 --- a/trace-events +++ b/trace-events @@ -340,6 +340,7 @@ usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device quali usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d" usb_desc_other_speed_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d" usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d" +usb_desc_bos(int addr, int len, int ret) "dev %d bos, len %d, ret %d" usb_set_addr(int addr) "dev %d" usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d" usb_set_interface(int addr, int iface, int alt, int ret) "dev %d, interface %d, altsetting %d, ret %d" From 79b40459ba361ac0946bb54fee4a2389d1307c68 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 28 Aug 2012 17:29:15 +0200 Subject: [PATCH 0293/2270] usb-storage: usb3 support Add usb3 descriptors to usb-storage, so it shows up as superspeed device when connected to xhci. Signed-off-by: Gerd Hoffmann --- hw/usb/dev-storage.c | 46 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index ff48d91049..e732191a26 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -78,6 +78,7 @@ enum { STR_SERIALNUMBER, STR_CONFIG_FULL, STR_CONFIG_HIGH, + STR_CONFIG_SUPER, }; static const USBDescStrings desc_strings = { @@ -86,6 +87,7 @@ static const USBDescStrings desc_strings = { [STR_SERIALNUMBER] = "1", [STR_CONFIG_FULL] = "Full speed config (usb 1.1)", [STR_CONFIG_HIGH] = "High speed config (usb 2.0)", + [STR_CONFIG_SUPER] = "Super speed config (usb 3.0)", }; static const USBDescIface desc_iface_full = { @@ -158,6 +160,43 @@ static const USBDescDevice desc_device_high = { }, }; +static const USBDescIface desc_iface_super = { + .bInterfaceNumber = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_MASS_STORAGE, + .bInterfaceSubClass = 0x06, /* SCSI */ + .bInterfaceProtocol = 0x50, /* Bulk */ + .eps = (USBDescEndpoint[]) { + { + .bEndpointAddress = USB_DIR_IN | 0x01, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 1024, + .bMaxBurst = 15, + },{ + .bEndpointAddress = USB_DIR_OUT | 0x02, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 1024, + .bMaxBurst = 15, + }, + } +}; + +static const USBDescDevice desc_device_super = { + .bcdUSB = 0x0300, + .bMaxPacketSize0 = 9, + .bNumConfigurations = 1, + .confs = (USBDescConfig[]) { + { + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = STR_CONFIG_SUPER, + .bmAttributes = 0xc0, + .nif = 1, + .ifs = &desc_iface_super, + }, + }, +}; + static const USBDesc desc = { .id = { .idVendor = 0x46f4, /* CRC16() of "QEMU" */ @@ -167,9 +206,10 @@ static const USBDesc desc = { .iProduct = STR_PRODUCT, .iSerialNumber = STR_SERIALNUMBER, }, - .full = &desc_device_full, - .high = &desc_device_high, - .str = desc_strings, + .full = &desc_device_full, + .high = &desc_device_high, + .super = &desc_device_super, + .str = desc_strings, }; static void usb_msd_copy_data(MSDState *s, USBPacket *p) From c5e9b02dee4a19f7b047fb75399012e1db759190 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 30 Aug 2012 10:57:12 +0200 Subject: [PATCH 0294/2270] xhci: fix & cleanup msi. Drop custom write_config function which isn't needed any more. Make the msi property a bit property so it accepts 'on' & 'off'. Enable MSI by default. TODO: add compat property to disable on old machine types. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index f0c1859861..e3de242a4b 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -386,7 +386,7 @@ struct XHCIState { /* properties */ uint32_t numports_2; uint32_t numports_3; - uint32_t msi; + uint32_t flags; /* Operational Registers */ uint32_t usbcmd; @@ -435,6 +435,10 @@ typedef struct XHCIEvRingSeg { uint32_t rsvd; } XHCIEvRingSeg; +enum xhci_flags { + XHCI_FLAG_USE_MSI = 1, +}; + static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid); static void xhci_event(XHCIState *xhci, XHCIEvent *event); @@ -617,7 +621,7 @@ static void xhci_irq_update(XHCIState *xhci) level = 1; } - if (xhci->msi && msi_enabled(&xhci->pci_dev)) { + if (msi_enabled(&xhci->pci_dev)) { if (level) { trace_usb_xhci_irq_msi(0); msi_notify(&xhci->pci_dev, 0); @@ -2857,32 +2861,20 @@ static int usb_xhci_initfn(struct PCIDevice *dev) ret = pcie_cap_init(&xhci->pci_dev, 0xa0, PCI_EXP_TYPE_ENDPOINT, 0); assert(ret >= 0); - if (xhci->msi) { - ret = msi_init(&xhci->pci_dev, 0x70, 1, true, false); - assert(ret >= 0); + if (xhci->flags & (1 << XHCI_FLAG_USE_MSI)) { + msi_init(&xhci->pci_dev, 0x70, MAXINTRS, true, false); } return 0; } -static void xhci_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, - int len) -{ - XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev, dev); - - pci_default_write_config(dev, addr, val, len); - if (xhci->msi) { - msi_write_config(dev, addr, val, len); - } -} - static const VMStateDescription vmstate_xhci = { .name = "xhci", .unmigratable = 1, }; static Property xhci_properties[] = { - DEFINE_PROP_UINT32("msi", XHCIState, msi, 0), + DEFINE_PROP_BIT("msi", XHCIState, flags, XHCI_FLAG_USE_MSI, true), DEFINE_PROP_UINT32("p2", XHCIState, numports_2, 4), DEFINE_PROP_UINT32("p3", XHCIState, numports_3, 4), DEFINE_PROP_END_OF_LIST(), @@ -2902,7 +2894,6 @@ static void xhci_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_SERIAL_USB; k->revision = 0x03; k->is_express = 1; - k->config_write = xhci_write_config; } static TypeInfo xhci_info = { From 4c4abe7cc903e057d343cd445eca2e5227783579 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 30 Aug 2012 13:05:10 +0200 Subject: [PATCH 0295/2270] xhci: rework interrupt handling Split xhci_irq_update into a function which handles intx updates (including lowering the irq line once the guests acks the interrupt) and one which is used for raising an irq only. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 49 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index e3de242a4b..06c1f51788 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -612,24 +612,43 @@ static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport) return &xhci->ports[index]; } -static void xhci_irq_update(XHCIState *xhci) +static void xhci_intx_update(XHCIState *xhci) { int level = 0; - if (xhci->iman & IMAN_IP && xhci->iman & IMAN_IE && + if (msi_enabled(&xhci->pci_dev)) { + return; + } + + if (xhci->iman & IMAN_IP && + xhci->iman & IMAN_IE && xhci->usbcmd & USBCMD_INTE) { level = 1; } - if (msi_enabled(&xhci->pci_dev)) { - if (level) { - trace_usb_xhci_irq_msi(0); - msi_notify(&xhci->pci_dev, 0); - } - } else { - trace_usb_xhci_irq_intx(level); - qemu_set_irq(xhci->irq, level); + trace_usb_xhci_irq_intx(level); + qemu_set_irq(xhci->irq, level); +} + +static void xhci_intr_raise(XHCIState *xhci) +{ + if (!(xhci->iman & IMAN_IP) || + !(xhci->iman & IMAN_IE)) { + return; } + + if (!(xhci->usbcmd & USBCMD_INTE)) { + return; + } + + if (msi_enabled(&xhci->pci_dev)) { + trace_usb_xhci_irq_msi(0); + msi_notify(&xhci->pci_dev, 0); + return; + } + + trace_usb_xhci_irq_intx(1); + qemu_set_irq(xhci->irq, 1); } static inline int xhci_running(XHCIState *xhci) @@ -732,7 +751,7 @@ static void xhci_events_update(XHCIState *xhci) xhci->erdp_low |= ERDP_EHB; xhci->iman |= IMAN_IP; xhci->usbsts |= USBSTS_EINT; - xhci_irq_update(xhci); + xhci_intr_raise(xhci); } if (xhci->er_full && xhci->ev_buffer_put == xhci->ev_buffer_get) { @@ -796,7 +815,7 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *event) xhci->iman |= IMAN_IP; xhci->usbsts |= USBSTS_EINT; - xhci_irq_update(xhci); + xhci_intr_raise(xhci); } static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring, @@ -2479,13 +2498,13 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val) if (val & USBCMD_HCRST) { xhci_reset(&xhci->pci_dev.qdev); } - xhci_irq_update(xhci); + xhci_intx_update(xhci); break; case 0x04: /* USBSTS */ /* these bits are write-1-to-clear */ xhci->usbsts &= ~(val & (USBSTS_HSE|USBSTS_EINT|USBSTS_PCD|USBSTS_SRE)); - xhci_irq_update(xhci); + xhci_intx_update(xhci); break; case 0x14: /* DNCTRL */ @@ -2570,7 +2589,7 @@ static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val) } xhci->iman &= ~IMAN_IE; xhci->iman |= val & IMAN_IE; - xhci_irq_update(xhci); + xhci_intx_update(xhci); break; case 0x24: /* IMOD */ xhci->imod = val; From 4c47f800631a14c8cb7970ba3a47d4a4ab0ee088 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 30 Aug 2012 12:06:59 +0200 Subject: [PATCH 0296/2270] xhci: add msix support Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- trace-events | 3 +++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 06c1f51788..19bbb164e6 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -23,6 +23,7 @@ #include "hw/usb.h" #include "hw/pci.h" #include "hw/msi.h" +#include "hw/msix.h" #include "trace.h" //#define DEBUG_XHCI @@ -59,6 +60,8 @@ #define OFF_OPER LEN_CAP #define OFF_RUNTIME 0x1000 #define OFF_DOORBELL 0x2000 +#define OFF_MSIX_TABLE 0x3000 +#define OFF_MSIX_PBA 0x3800 /* must be power of 2 */ #define LEN_REGS 0x4000 @@ -411,6 +414,7 @@ struct XHCIState { uint32_t erstba_high; uint32_t erdp_low; uint32_t erdp_high; + bool msix_used; int64_t mfindex_start; QEMUTimer *mfwrap_timer; @@ -437,6 +441,7 @@ typedef struct XHCIEvRingSeg { enum xhci_flags { XHCI_FLAG_USE_MSI = 1, + XHCI_FLAG_USE_MSI_X, }; static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, @@ -616,7 +621,8 @@ static void xhci_intx_update(XHCIState *xhci) { int level = 0; - if (msi_enabled(&xhci->pci_dev)) { + if (msix_enabled(&xhci->pci_dev) || + msi_enabled(&xhci->pci_dev)) { return; } @@ -630,6 +636,30 @@ static void xhci_intx_update(XHCIState *xhci) qemu_set_irq(xhci->irq, level); } +static void xhci_msix_update(XHCIState *xhci) +{ + bool enabled; + + if (!msix_enabled(&xhci->pci_dev)) { + return; + } + + enabled = xhci->iman & IMAN_IE; + if (enabled == xhci->msix_used) { + return; + } + + if (enabled) { + trace_usb_xhci_irq_msix_use(0); + msix_vector_use(&xhci->pci_dev, 0); + xhci->msix_used = true; + } else { + trace_usb_xhci_irq_msix_unuse(0); + msix_vector_unuse(&xhci->pci_dev, 0); + xhci->msix_used = false; + } +} + static void xhci_intr_raise(XHCIState *xhci) { if (!(xhci->iman & IMAN_IP) || @@ -641,6 +671,12 @@ static void xhci_intr_raise(XHCIState *xhci) return; } + if (msix_enabled(&xhci->pci_dev)) { + trace_usb_xhci_irq_msix(0); + msix_notify(&xhci->pci_dev, 0); + return; + } + if (msi_enabled(&xhci->pci_dev)) { trace_usb_xhci_irq_msi(0); msi_notify(&xhci->pci_dev, 0); @@ -2282,6 +2318,7 @@ static void xhci_reset(DeviceState *dev) xhci->erstba_high = 0; xhci->erdp_low = 0; xhci->erdp_high = 0; + xhci->msix_used = 0; xhci->er_ep_idx = 0; xhci->er_pcs = 1; @@ -2590,6 +2627,7 @@ static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val) xhci->iman &= ~IMAN_IE; xhci->iman |= val & IMAN_IE; xhci_intx_update(xhci); + xhci_msix_update(xhci); break; case 0x24: /* IMOD */ xhci->imod = val; @@ -2883,6 +2921,12 @@ static int usb_xhci_initfn(struct PCIDevice *dev) if (xhci->flags & (1 << XHCI_FLAG_USE_MSI)) { msi_init(&xhci->pci_dev, 0x70, MAXINTRS, true, false); } + if (xhci->flags & (1 << XHCI_FLAG_USE_MSI_X)) { + msix_init(&xhci->pci_dev, MAXINTRS, + &xhci->mem, 0, OFF_MSIX_TABLE, + &xhci->mem, 0, OFF_MSIX_PBA, + 0x90); + } return 0; } @@ -2894,6 +2938,7 @@ static const VMStateDescription vmstate_xhci = { static Property xhci_properties[] = { DEFINE_PROP_BIT("msi", XHCIState, flags, XHCI_FLAG_USE_MSI, true), + DEFINE_PROP_BIT("msix", XHCIState, flags, XHCI_FLAG_USE_MSI_X, true), DEFINE_PROP_UINT32("p2", XHCIState, numports_2, 4), DEFINE_PROP_UINT32("p3", XHCIState, numports_3, 4), DEFINE_PROP_END_OF_LIST(), diff --git a/trace-events b/trace-events index 5bc591a721..8589ca4eac 100644 --- a/trace-events +++ b/trace-events @@ -313,6 +313,9 @@ usb_xhci_runtime_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x" usb_xhci_doorbell_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x" usb_xhci_irq_intx(uint32_t level) "level %d" usb_xhci_irq_msi(uint32_t nr) "nr %d" +usb_xhci_irq_msix(uint32_t nr) "nr %d" +usb_xhci_irq_msix_use(uint32_t nr) "nr %d" +usb_xhci_irq_msix_unuse(uint32_t nr) "nr %d" usb_xhci_queue_event(uint32_t idx, const char *trb, const char *evt, uint64_t param, uint32_t status, uint32_t control) "idx %d, %s, %s, p %016" PRIx64 ", s %08x, c 0x%08x" usb_xhci_fetch_trb(uint64_t addr, const char *name, uint64_t param, uint32_t status, uint32_t control) "addr %016" PRIx64 ", %s, p %016" PRIx64 ", s %08x, c 0x%08x" usb_xhci_slot_enable(uint32_t slotid) "slotid %d" From 2cae41195b5b95129d92a189a0bfce3e5d0d8707 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 30 Aug 2012 14:04:04 +0200 Subject: [PATCH 0297/2270] xhci: move register update into xhci_intr_raise Now that we have a separate function to raise an IRQ we can move some comon code into the function. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 19bbb164e6..8dc9986e53 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -662,8 +662,11 @@ static void xhci_msix_update(XHCIState *xhci) static void xhci_intr_raise(XHCIState *xhci) { - if (!(xhci->iman & IMAN_IP) || - !(xhci->iman & IMAN_IE)) { + xhci->erdp_low |= ERDP_EHB; + xhci->iman |= IMAN_IP; + xhci->usbsts |= USBSTS_EINT; + + if (!(xhci->iman & IMAN_IE)) { return; } @@ -784,9 +787,6 @@ static void xhci_events_update(XHCIState *xhci) } if (do_irq) { - xhci->erdp_low |= ERDP_EHB; - xhci->iman |= IMAN_IP; - xhci->usbsts |= USBSTS_EINT; xhci_intr_raise(xhci); } @@ -847,10 +847,6 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *event) xhci_write_event(xhci, event); } - xhci->erdp_low |= ERDP_EHB; - xhci->iman |= IMAN_IP; - xhci->usbsts |= USBSTS_EINT; - xhci_intr_raise(xhci); } From 962d11e17264af0239f259aad1386fcc7ff471aa Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 30 Aug 2012 15:49:03 +0200 Subject: [PATCH 0298/2270] xhci: add XHCIInterrupter Move all state belonging to the (single) interrupter into a separate struct. First step in adding support for multiple interrupters. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 307 ++++++++++++++++++++++++---------------------- trace-events | 2 +- 2 files changed, 161 insertions(+), 148 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 8dc9986e53..0a03053c0f 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -378,6 +378,27 @@ typedef struct XHCIEvent { uint8_t epid; } XHCIEvent; +typedef struct XHCIInterrupter { + uint32_t iman; + uint32_t imod; + uint32_t erstsz; + uint32_t erstba_low; + uint32_t erstba_high; + uint32_t erdp_low; + uint32_t erdp_high; + + bool msix_used, er_pcs, er_full; + + dma_addr_t er_start; + uint32_t er_size; + unsigned int er_ep_idx; + + XHCIEvent ev_buffer[EV_QUEUE]; + unsigned int ev_buffer_put; + unsigned int ev_buffer_get; + +} XHCIInterrupter; + struct XHCIState { PCIDevice pci_dev; USBBus bus; @@ -407,27 +428,9 @@ struct XHCIState { uint32_t numports; /* Runtime Registers */ - uint32_t iman; - uint32_t imod; - uint32_t erstsz; - uint32_t erstba_low; - uint32_t erstba_high; - uint32_t erdp_low; - uint32_t erdp_high; - bool msix_used; - int64_t mfindex_start; QEMUTimer *mfwrap_timer; - - dma_addr_t er_start; - uint32_t er_size; - bool er_pcs; - unsigned int er_ep_idx; - bool er_full; - - XHCIEvent ev_buffer[EV_QUEUE]; - unsigned int ev_buffer_put; - unsigned int ev_buffer_get; + XHCIInterrupter intr[MAXINTRS]; XHCIRing cmd_ring; }; @@ -446,8 +449,8 @@ enum xhci_flags { static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid); -static void xhci_event(XHCIState *xhci, XHCIEvent *event); -static void xhci_write_event(XHCIState *xhci, XHCIEvent *event); +static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v); +static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v); static const char *TRBType_names[] = { [TRB_RESERVED] = "TRB_RESERVED", @@ -573,7 +576,7 @@ static void xhci_mfwrap_timer(void *opaque) XHCIState *xhci = opaque; XHCIEvent wrap = { ER_MFINDEX_WRAP, CC_SUCCESS }; - xhci_event(xhci, &wrap); + xhci_event(xhci, &wrap, 0); xhci_mfwrap_update(xhci); } @@ -626,8 +629,8 @@ static void xhci_intx_update(XHCIState *xhci) return; } - if (xhci->iman & IMAN_IP && - xhci->iman & IMAN_IE && + if (xhci->intr[0].iman & IMAN_IP && + xhci->intr[0].iman & IMAN_IE && xhci->usbcmd & USBCMD_INTE) { level = 1; } @@ -636,7 +639,7 @@ static void xhci_intx_update(XHCIState *xhci) qemu_set_irq(xhci->irq, level); } -static void xhci_msix_update(XHCIState *xhci) +static void xhci_msix_update(XHCIState *xhci, int v) { bool enabled; @@ -644,29 +647,29 @@ static void xhci_msix_update(XHCIState *xhci) return; } - enabled = xhci->iman & IMAN_IE; - if (enabled == xhci->msix_used) { + enabled = xhci->intr[v].iman & IMAN_IE; + if (enabled == xhci->intr[v].msix_used) { return; } if (enabled) { - trace_usb_xhci_irq_msix_use(0); - msix_vector_use(&xhci->pci_dev, 0); - xhci->msix_used = true; + trace_usb_xhci_irq_msix_use(v); + msix_vector_use(&xhci->pci_dev, v); + xhci->intr[v].msix_used = true; } else { - trace_usb_xhci_irq_msix_unuse(0); - msix_vector_unuse(&xhci->pci_dev, 0); - xhci->msix_used = false; + trace_usb_xhci_irq_msix_unuse(v); + msix_vector_unuse(&xhci->pci_dev, v); + xhci->intr[v].msix_used = false; } } -static void xhci_intr_raise(XHCIState *xhci) +static void xhci_intr_raise(XHCIState *xhci, int v) { - xhci->erdp_low |= ERDP_EHB; - xhci->iman |= IMAN_IP; + xhci->intr[v].erdp_low |= ERDP_EHB; + xhci->intr[v].iman |= IMAN_IP; xhci->usbsts |= USBSTS_EINT; - if (!(xhci->iman & IMAN_IE)) { + if (!(xhci->intr[v].iman & IMAN_IE)) { return; } @@ -675,24 +678,26 @@ static void xhci_intr_raise(XHCIState *xhci) } if (msix_enabled(&xhci->pci_dev)) { - trace_usb_xhci_irq_msix(0); - msix_notify(&xhci->pci_dev, 0); + trace_usb_xhci_irq_msix(v); + msix_notify(&xhci->pci_dev, v); return; } if (msi_enabled(&xhci->pci_dev)) { - trace_usb_xhci_irq_msi(0); - msi_notify(&xhci->pci_dev, 0); + trace_usb_xhci_irq_msi(v); + msi_notify(&xhci->pci_dev, v); return; } - trace_usb_xhci_irq_intx(1); - qemu_set_irq(xhci->irq, 1); + if (v == 0) { + trace_usb_xhci_irq_intx(1); + qemu_set_irq(xhci->irq, 1); + } } static inline int xhci_running(XHCIState *xhci) { - return !(xhci->usbsts & USBSTS_HCH) && !xhci->er_full; + return !(xhci->usbsts & USBSTS_HCH) && !xhci->intr[0].er_full; } static void xhci_die(XHCIState *xhci) @@ -701,8 +706,9 @@ static void xhci_die(XHCIState *xhci) fprintf(stderr, "xhci: asserted controller error\n"); } -static void xhci_write_event(XHCIState *xhci, XHCIEvent *event) +static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v) { + XHCIInterrupter *intr = &xhci->intr[v]; XHCITRB ev_trb; dma_addr_t addr; @@ -710,27 +716,28 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event) ev_trb.status = cpu_to_le32(event->length | (event->ccode << 24)); ev_trb.control = (event->slotid << 24) | (event->epid << 16) | event->flags | (event->type << TRB_TYPE_SHIFT); - if (xhci->er_pcs) { + if (intr->er_pcs) { ev_trb.control |= TRB_C; } ev_trb.control = cpu_to_le32(ev_trb.control); - trace_usb_xhci_queue_event(xhci->er_ep_idx, trb_name(&ev_trb), + trace_usb_xhci_queue_event(v, intr->er_ep_idx, trb_name(&ev_trb), event_name(event), ev_trb.parameter, ev_trb.status, ev_trb.control); - addr = xhci->er_start + TRB_SIZE*xhci->er_ep_idx; + addr = intr->er_start + TRB_SIZE*intr->er_ep_idx; pci_dma_write(&xhci->pci_dev, addr, &ev_trb, TRB_SIZE); - xhci->er_ep_idx++; - if (xhci->er_ep_idx >= xhci->er_size) { - xhci->er_ep_idx = 0; - xhci->er_pcs = !xhci->er_pcs; + intr->er_ep_idx++; + if (intr->er_ep_idx >= intr->er_size) { + intr->er_ep_idx = 0; + intr->er_pcs = !intr->er_pcs; } } -static void xhci_events_update(XHCIState *xhci) +static void xhci_events_update(XHCIState *xhci, int v) { + XHCIInterrupter *intr = &xhci->intr[v]; dma_addr_t erdp; unsigned int dp_idx; bool do_irq = 0; @@ -739,115 +746,116 @@ static void xhci_events_update(XHCIState *xhci) return; } - erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high); - if (erdp < xhci->er_start || - erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) { + erdp = xhci_addr64(intr->erdp_low, intr->erdp_high); + if (erdp < intr->er_start || + erdp >= (intr->er_start + TRB_SIZE*intr->er_size)) { fprintf(stderr, "xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp); - fprintf(stderr, "xhci: ER at "DMA_ADDR_FMT" len %d\n", - xhci->er_start, xhci->er_size); + fprintf(stderr, "xhci: ER[%d] at "DMA_ADDR_FMT" len %d\n", + v, intr->er_start, intr->er_size); xhci_die(xhci); return; } - dp_idx = (erdp - xhci->er_start) / TRB_SIZE; - assert(dp_idx < xhci->er_size); + dp_idx = (erdp - intr->er_start) / TRB_SIZE; + assert(dp_idx < intr->er_size); /* NEC didn't read section 4.9.4 of the spec (v1.0 p139 top Note) and thus * deadlocks when the ER is full. Hack it by holding off events until * the driver decides to free at least half of the ring */ - if (xhci->er_full) { - int er_free = dp_idx - xhci->er_ep_idx; + if (intr->er_full) { + int er_free = dp_idx - intr->er_ep_idx; if (er_free <= 0) { - er_free += xhci->er_size; + er_free += intr->er_size; } - if (er_free < (xhci->er_size/2)) { + if (er_free < (intr->er_size/2)) { DPRINTF("xhci_events_update(): event ring still " "more than half full (hack)\n"); return; } } - while (xhci->ev_buffer_put != xhci->ev_buffer_get) { - assert(xhci->er_full); - if (((xhci->er_ep_idx+1) % xhci->er_size) == dp_idx) { + while (intr->ev_buffer_put != intr->ev_buffer_get) { + assert(intr->er_full); + if (((intr->er_ep_idx+1) % intr->er_size) == dp_idx) { DPRINTF("xhci_events_update(): event ring full again\n"); #ifndef ER_FULL_HACK XHCIEvent full = {ER_HOST_CONTROLLER, CC_EVENT_RING_FULL_ERROR}; - xhci_write_event(xhci, &full); + xhci_write_event(xhci, &full, v); #endif do_irq = 1; break; } - XHCIEvent *event = &xhci->ev_buffer[xhci->ev_buffer_get]; - xhci_write_event(xhci, event); - xhci->ev_buffer_get++; + XHCIEvent *event = &intr->ev_buffer[intr->ev_buffer_get]; + xhci_write_event(xhci, event, v); + intr->ev_buffer_get++; do_irq = 1; - if (xhci->ev_buffer_get == EV_QUEUE) { - xhci->ev_buffer_get = 0; + if (intr->ev_buffer_get == EV_QUEUE) { + intr->ev_buffer_get = 0; } } if (do_irq) { - xhci_intr_raise(xhci); + xhci_intr_raise(xhci, v); } - if (xhci->er_full && xhci->ev_buffer_put == xhci->ev_buffer_get) { + if (intr->er_full && intr->ev_buffer_put == intr->ev_buffer_get) { DPRINTF("xhci_events_update(): event ring no longer full\n"); - xhci->er_full = 0; + intr->er_full = 0; } return; } -static void xhci_event(XHCIState *xhci, XHCIEvent *event) +static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v) { + XHCIInterrupter *intr = &xhci->intr[v]; dma_addr_t erdp; unsigned int dp_idx; - if (xhci->er_full) { + if (intr->er_full) { DPRINTF("xhci_event(): ER full, queueing\n"); - if (((xhci->ev_buffer_put+1) % EV_QUEUE) == xhci->ev_buffer_get) { + if (((intr->ev_buffer_put+1) % EV_QUEUE) == intr->ev_buffer_get) { fprintf(stderr, "xhci: event queue full, dropping event!\n"); return; } - xhci->ev_buffer[xhci->ev_buffer_put++] = *event; - if (xhci->ev_buffer_put == EV_QUEUE) { - xhci->ev_buffer_put = 0; + intr->ev_buffer[intr->ev_buffer_put++] = *event; + if (intr->ev_buffer_put == EV_QUEUE) { + intr->ev_buffer_put = 0; } return; } - erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high); - if (erdp < xhci->er_start || - erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) { + erdp = xhci_addr64(intr->erdp_low, intr->erdp_high); + if (erdp < intr->er_start || + erdp >= (intr->er_start + TRB_SIZE*intr->er_size)) { fprintf(stderr, "xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp); - fprintf(stderr, "xhci: ER at "DMA_ADDR_FMT" len %d\n", - xhci->er_start, xhci->er_size); + fprintf(stderr, "xhci: ER[%d] at "DMA_ADDR_FMT" len %d\n", + v, intr->er_start, intr->er_size); xhci_die(xhci); return; } - dp_idx = (erdp - xhci->er_start) / TRB_SIZE; - assert(dp_idx < xhci->er_size); + dp_idx = (erdp - intr->er_start) / TRB_SIZE; + assert(dp_idx < intr->er_size); - if ((xhci->er_ep_idx+1) % xhci->er_size == dp_idx) { + if ((intr->er_ep_idx+1) % intr->er_size == dp_idx) { DPRINTF("xhci_event(): ER full, queueing\n"); #ifndef ER_FULL_HACK XHCIEvent full = {ER_HOST_CONTROLLER, CC_EVENT_RING_FULL_ERROR}; xhci_write_event(xhci, &full); #endif - xhci->er_full = 1; - if (((xhci->ev_buffer_put+1) % EV_QUEUE) == xhci->ev_buffer_get) { + intr->er_full = 1; + if (((intr->ev_buffer_put+1) % EV_QUEUE) == intr->ev_buffer_get) { fprintf(stderr, "xhci: event queue full, dropping event!\n"); return; } - xhci->ev_buffer[xhci->ev_buffer_put++] = *event; - if (xhci->ev_buffer_put == EV_QUEUE) { - xhci->ev_buffer_put = 0; + intr->ev_buffer[intr->ev_buffer_put++] = *event; + if (intr->ev_buffer_put == EV_QUEUE) { + intr->ev_buffer_put = 0; } } else { - xhci_write_event(xhci, event); + xhci_write_event(xhci, event, v); } - xhci_intr_raise(xhci); + xhci_intr_raise(xhci, v); } static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring, @@ -939,17 +947,18 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring) } } -static void xhci_er_reset(XHCIState *xhci) +static void xhci_er_reset(XHCIState *xhci, int v) { + XHCIInterrupter *intr = &xhci->intr[v]; XHCIEvRingSeg seg; /* cache the (sole) event ring segment location */ - if (xhci->erstsz != 1) { - fprintf(stderr, "xhci: invalid value for ERSTSZ: %d\n", xhci->erstsz); + if (intr->erstsz != 1) { + fprintf(stderr, "xhci: invalid value for ERSTSZ: %d\n", intr->erstsz); xhci_die(xhci); return; } - dma_addr_t erstba = xhci_addr64(xhci->erstba_low, xhci->erstba_high); + dma_addr_t erstba = xhci_addr64(intr->erstba_low, intr->erstba_high); pci_dma_read(&xhci->pci_dev, erstba, &seg, sizeof(seg)); le32_to_cpus(&seg.addr_low); le32_to_cpus(&seg.addr_high); @@ -959,15 +968,15 @@ static void xhci_er_reset(XHCIState *xhci) xhci_die(xhci); return; } - xhci->er_start = xhci_addr64(seg.addr_low, seg.addr_high); - xhci->er_size = seg.size; + intr->er_start = xhci_addr64(seg.addr_low, seg.addr_high); + intr->er_size = seg.size; - xhci->er_ep_idx = 0; - xhci->er_pcs = 1; - xhci->er_full = 0; + intr->er_ep_idx = 0; + intr->er_pcs = 1; + intr->er_full = 0; - DPRINTF("xhci: event ring:" DMA_ADDR_FMT " [%d]\n", - xhci->er_start, xhci->er_size); + DPRINTF("xhci: event ring[%d]:" DMA_ADDR_FMT " [%d]\n", + v, intr->er_start, intr->er_size); } static void xhci_run(XHCIState *xhci) @@ -1368,7 +1377,7 @@ static void xhci_xfer_report(XHCITransfer *xfer) DPRINTF("xhci_xfer_data: EDTLA=%d\n", event.length); edtla = 0; } - xhci_event(xhci, &event); + xhci_event(xhci, &event, 0 /* FIXME */); reported = 1; if (xfer->status != CC_SUCCESS) { return; @@ -2244,7 +2253,7 @@ static void xhci_process_commands(XHCIState *xhci) break; } event.slotid = slotid; - xhci_event(xhci, &event); + xhci_event(xhci, &event, 0 /* FIXME */); } } @@ -2274,7 +2283,7 @@ static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach) port->portsc |= PORTSC_CSC; XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, port->portnr << 24}; - xhci_event(xhci, &ev); + xhci_event(xhci, &ev, 0 /* FIXME */); DPRINTF("xhci: port change event for port %d\n", port->portnr); } } @@ -2307,20 +2316,22 @@ static void xhci_reset(DeviceState *dev) xhci_update_port(xhci, xhci->ports + i, 0); } - xhci->iman = 0; - xhci->imod = 0; - xhci->erstsz = 0; - xhci->erstba_low = 0; - xhci->erstba_high = 0; - xhci->erdp_low = 0; - xhci->erdp_high = 0; - xhci->msix_used = 0; + for (i = 0; i < MAXINTRS; i++) { + xhci->intr[i].iman = 0; + xhci->intr[i].imod = 0; + xhci->intr[i].erstsz = 0; + xhci->intr[i].erstba_low = 0; + xhci->intr[i].erstba_high = 0; + xhci->intr[i].erdp_low = 0; + xhci->intr[i].erdp_high = 0; + xhci->intr[i].msix_used = 0; - xhci->er_ep_idx = 0; - xhci->er_pcs = 1; - xhci->er_full = 0; - xhci->ev_buffer_put = 0; - xhci->ev_buffer_get = 0; + xhci->intr[i].er_ep_idx = 0; + xhci->intr[i].er_pcs = 1; + xhci->intr[i].er_full = 0; + xhci->intr[i].ev_buffer_put = 0; + xhci->intr[i].ev_buffer_get = 0; + } xhci->mfindex_start = qemu_get_clock_ns(vm_clock); xhci_mfwrap_update(xhci); @@ -2551,7 +2562,7 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val) if (xhci->crcr_low & (CRCR_CA|CRCR_CS) && (xhci->crcr_low & CRCR_CRR)) { XHCIEvent event = {ER_COMMAND_COMPLETE, CC_COMMAND_RING_STOPPED}; xhci->crcr_low &= ~CRCR_CRR; - xhci_event(xhci, &event); + xhci_event(xhci, &event, 0 /* FIXME */); DPRINTF("xhci: command ring stopped (CRCR=%08x)\n", xhci->crcr_low); } else { dma_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val); @@ -2575,6 +2586,7 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val) static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg) { + XHCIInterrupter *intr = &xhci->intr[0]; uint32_t ret; switch (reg) { @@ -2582,25 +2594,25 @@ static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg) ret = xhci_mfindex_get(xhci) & 0x3fff; break; case 0x20: /* IMAN */ - ret = xhci->iman; + ret = intr->iman; break; case 0x24: /* IMOD */ - ret = xhci->imod; + ret = intr->imod; break; case 0x28: /* ERSTSZ */ - ret = xhci->erstsz; + ret = intr->erstsz; break; case 0x30: /* ERSTBA low */ - ret = xhci->erstba_low; + ret = intr->erstba_low; break; case 0x34: /* ERSTBA high */ - ret = xhci->erstba_high; + ret = intr->erstba_high; break; case 0x38: /* ERDP low */ - ret = xhci->erdp_low; + ret = intr->erdp_low; break; case 0x3c: /* ERDP high */ - ret = xhci->erdp_high; + ret = intr->erdp_high; break; default: fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", reg); @@ -2613,42 +2625,43 @@ static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg) static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val) { + XHCIInterrupter *intr = &xhci->intr[0]; trace_usb_xhci_runtime_write(reg, val); switch (reg) { case 0x20: /* IMAN */ if (val & IMAN_IP) { - xhci->iman &= ~IMAN_IP; + intr->iman &= ~IMAN_IP; } - xhci->iman &= ~IMAN_IE; - xhci->iman |= val & IMAN_IE; + intr->iman &= ~IMAN_IE; + intr->iman |= val & IMAN_IE; xhci_intx_update(xhci); - xhci_msix_update(xhci); + xhci_msix_update(xhci, 0); break; case 0x24: /* IMOD */ - xhci->imod = val; + intr->imod = val; break; case 0x28: /* ERSTSZ */ - xhci->erstsz = val & 0xffff; + intr->erstsz = val & 0xffff; break; case 0x30: /* ERSTBA low */ /* XXX NEC driver bug: it doesn't align this to 64 bytes - xhci->erstba_low = val & 0xffffffc0; */ - xhci->erstba_low = val & 0xfffffff0; + intr->erstba_low = val & 0xffffffc0; */ + intr->erstba_low = val & 0xfffffff0; break; case 0x34: /* ERSTBA high */ - xhci->erstba_high = val; - xhci_er_reset(xhci); + intr->erstba_high = val; + xhci_er_reset(xhci, 0); break; case 0x38: /* ERDP low */ if (val & ERDP_EHB) { - xhci->erdp_low &= ~ERDP_EHB; + intr->erdp_low &= ~ERDP_EHB; } - xhci->erdp_low = (val & ~ERDP_EHB) | (xhci->erdp_low & ERDP_EHB); + intr->erdp_low = (val & ~ERDP_EHB) | (intr->erdp_low & ERDP_EHB); break; case 0x3c: /* ERDP high */ - xhci->erdp_high = val; - xhci_events_update(xhci); + intr->erdp_high = val; + xhci_events_update(xhci, 0); break; default: fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg); @@ -2778,7 +2791,7 @@ static void xhci_wakeup(USBPort *usbport) return; } port->portsc |= PORTSC_PLC; - xhci_event(xhci, &ev); + xhci_event(xhci, &ev, 0 /* FIXME */); } static void xhci_complete(USBPort *port, USBPacket *packet) diff --git a/trace-events b/trace-events index 8589ca4eac..b25ae1c437 100644 --- a/trace-events +++ b/trace-events @@ -316,7 +316,7 @@ usb_xhci_irq_msi(uint32_t nr) "nr %d" usb_xhci_irq_msix(uint32_t nr) "nr %d" usb_xhci_irq_msix_use(uint32_t nr) "nr %d" usb_xhci_irq_msix_unuse(uint32_t nr) "nr %d" -usb_xhci_queue_event(uint32_t idx, const char *trb, const char *evt, uint64_t param, uint32_t status, uint32_t control) "idx %d, %s, %s, p %016" PRIx64 ", s %08x, c 0x%08x" +usb_xhci_queue_event(uint32_t vector, uint32_t idx, const char *trb, const char *evt, uint64_t param, uint32_t status, uint32_t control) "v %d, idx %d, %s, %s, p %016" PRIx64 ", s %08x, c 0x%08x" usb_xhci_fetch_trb(uint64_t addr, const char *name, uint64_t param, uint32_t status, uint32_t control) "addr %016" PRIx64 ", %s, p %016" PRIx64 ", s %08x, c 0x%08x" usb_xhci_slot_enable(uint32_t slotid) "slotid %d" usb_xhci_slot_disable(uint32_t slotid) "slotid %d" From 43d9d6047e0f12b96bfc680982a630f0af78611a Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 30 Aug 2012 17:15:12 +0200 Subject: [PATCH 0299/2270] xhci: prepare xhci_runtime_{read,write} for multiple interrupters Prepare xhci runtime register access function for multiple interrupters. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 100 ++++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 43 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 0a03053c0f..72f4eebb69 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2586,37 +2586,43 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val) static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg) { - XHCIInterrupter *intr = &xhci->intr[0]; - uint32_t ret; + uint32_t ret = 0; - switch (reg) { - case 0x00: /* MFINDEX */ - ret = xhci_mfindex_get(xhci) & 0x3fff; - break; - case 0x20: /* IMAN */ - ret = intr->iman; - break; - case 0x24: /* IMOD */ - ret = intr->imod; - break; - case 0x28: /* ERSTSZ */ - ret = intr->erstsz; - break; - case 0x30: /* ERSTBA low */ - ret = intr->erstba_low; - break; - case 0x34: /* ERSTBA high */ - ret = intr->erstba_high; - break; - case 0x38: /* ERDP low */ - ret = intr->erdp_low; - break; - case 0x3c: /* ERDP high */ - ret = intr->erdp_high; - break; - default: - fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", reg); - ret = 0; + if (reg < 0x20) { + switch (reg) { + case 0x00: /* MFINDEX */ + ret = xhci_mfindex_get(xhci) & 0x3fff; + break; + default: + fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", reg); + break; + } + } else { + int v = (reg - 0x20) / 0x20; + XHCIInterrupter *intr = &xhci->intr[v]; + switch (reg & 0x1f) { + case 0x00: /* IMAN */ + ret = intr->iman; + break; + case 0x04: /* IMOD */ + ret = intr->imod; + break; + case 0x08: /* ERSTSZ */ + ret = intr->erstsz; + break; + case 0x10: /* ERSTBA low */ + ret = intr->erstba_low; + break; + case 0x14: /* ERSTBA high */ + ret = intr->erstba_high; + break; + case 0x18: /* ERDP low */ + ret = intr->erdp_low; + break; + case 0x1c: /* ERDP high */ + ret = intr->erdp_high; + break; + } } trace_usb_xhci_runtime_read(reg, ret); @@ -2625,43 +2631,51 @@ static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg) static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val) { - XHCIInterrupter *intr = &xhci->intr[0]; + int v = (reg - 0x20) / 0x20; + XHCIInterrupter *intr = &xhci->intr[v]; trace_usb_xhci_runtime_write(reg, val); - switch (reg) { - case 0x20: /* IMAN */ + if (reg < 0x20) { + fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg); + return; + } + + switch (reg & 0x1f) { + case 0x00: /* IMAN */ if (val & IMAN_IP) { intr->iman &= ~IMAN_IP; } intr->iman &= ~IMAN_IE; intr->iman |= val & IMAN_IE; - xhci_intx_update(xhci); - xhci_msix_update(xhci, 0); + if (v == 0) { + xhci_intx_update(xhci); + } + xhci_msix_update(xhci, v); break; - case 0x24: /* IMOD */ + case 0x04: /* IMOD */ intr->imod = val; break; - case 0x28: /* ERSTSZ */ + case 0x08: /* ERSTSZ */ intr->erstsz = val & 0xffff; break; - case 0x30: /* ERSTBA low */ + case 0x10: /* ERSTBA low */ /* XXX NEC driver bug: it doesn't align this to 64 bytes intr->erstba_low = val & 0xffffffc0; */ intr->erstba_low = val & 0xfffffff0; break; - case 0x34: /* ERSTBA high */ + case 0x14: /* ERSTBA high */ intr->erstba_high = val; - xhci_er_reset(xhci, 0); + xhci_er_reset(xhci, v); break; - case 0x38: /* ERDP low */ + case 0x18: /* ERDP low */ if (val & ERDP_EHB) { intr->erdp_low &= ~ERDP_EHB; } intr->erdp_low = (val & ~ERDP_EHB) | (intr->erdp_low & ERDP_EHB); break; - case 0x3c: /* ERDP high */ + case 0x1c: /* ERDP high */ intr->erdp_high = val; - xhci_events_update(xhci, 0); + xhci_events_update(xhci, v); break; default: fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg); From 2d1de8508fed1bddb1946d7d57256c96e02c1dd4 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 31 Aug 2012 15:30:51 +0200 Subject: [PATCH 0300/2270] xhci: pick target interrupter Pick the correct interrupter when queuing an event. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 72f4eebb69..157985133c 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -264,6 +264,10 @@ typedef enum TRBCCode { #define TRB_LK_TC (1<<1) +#define TRB_INTR_SHIFT 22 +#define TRB_INTR_MASK 0x3ff +#define TRB_INTR(t) (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK) + #define EP_TYPE_MASK 0x7 #define EP_TYPE_SHIFT 3 @@ -806,10 +810,16 @@ static void xhci_events_update(XHCIState *xhci, int v) static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v) { - XHCIInterrupter *intr = &xhci->intr[v]; + XHCIInterrupter *intr; dma_addr_t erdp; unsigned int dp_idx; + if (v >= MAXINTRS) { + DPRINTF("intr nr out of range (%d >= %d)\n", v, MAXINTRS); + return; + } + intr = &xhci->intr[v]; + if (intr->er_full) { DPRINTF("xhci_event(): ER full, queueing\n"); if (((intr->ev_buffer_put+1) % EV_QUEUE) == intr->ev_buffer_get) { @@ -1377,7 +1387,7 @@ static void xhci_xfer_report(XHCITransfer *xfer) DPRINTF("xhci_xfer_data: EDTLA=%d\n", event.length); edtla = 0; } - xhci_event(xhci, &event, 0 /* FIXME */); + xhci_event(xhci, &event, TRB_INTR(*trb)); reported = 1; if (xfer->status != CC_SUCCESS) { return; @@ -2253,7 +2263,7 @@ static void xhci_process_commands(XHCIState *xhci) break; } event.slotid = slotid; - xhci_event(xhci, &event, 0 /* FIXME */); + xhci_event(xhci, &event, 0); } } @@ -2283,7 +2293,7 @@ static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach) port->portsc |= PORTSC_CSC; XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, port->portnr << 24}; - xhci_event(xhci, &ev, 0 /* FIXME */); + xhci_event(xhci, &ev, 0); DPRINTF("xhci: port change event for port %d\n", port->portnr); } } @@ -2562,7 +2572,7 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val) if (xhci->crcr_low & (CRCR_CA|CRCR_CS) && (xhci->crcr_low & CRCR_CRR)) { XHCIEvent event = {ER_COMMAND_COMPLETE, CC_COMMAND_RING_STOPPED}; xhci->crcr_low &= ~CRCR_CRR; - xhci_event(xhci, &event, 0 /* FIXME */); + xhci_event(xhci, &event, 0); DPRINTF("xhci: command ring stopped (CRCR=%08x)\n", xhci->crcr_low); } else { dma_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val); @@ -2805,7 +2815,7 @@ static void xhci_wakeup(USBPort *usbport) return; } port->portsc |= PORTSC_PLC; - xhci_event(xhci, &ev, 0 /* FIXME */); + xhci_event(xhci, &ev, 0); } static void xhci_complete(USBPort *port, USBPacket *packet) From fa8ee89e8b0a075e82ca54faa6135137abccfa48 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 4 Sep 2012 12:56:55 +0200 Subject: [PATCH 0301/2270] xhci: support multiple interrupters Everything is in place, flip the big switch now and enable support for multiple interrupters. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 157985133c..2e3a6209c8 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -42,7 +42,7 @@ #define MAXPORTS (MAXPORTS_2+MAXPORTS_3) #define MAXSLOTS MAXPORTS -#define MAXINTRS 1 /* MAXPORTS */ +#define MAXINTRS MAXPORTS #define TD_QUEUE 24 @@ -75,10 +75,6 @@ # error Increase LEN_REGS #endif -#if MAXINTRS > 1 -# error TODO: only one interrupter supported -#endif - /* bit definitions */ #define USBCMD_RS (1<<0) #define USBCMD_HCRST (1<<1) From 1b067564ce5db9a144eb15239abbd36c31dd65c8 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 4 Sep 2012 14:42:20 +0200 Subject: [PATCH 0302/2270] xhci: kill xhci_mem_{read,write} dispatcher functions ... and register subregions instead, so we offload the dispatching to the the memory subsystem which is designed to handle it. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 140 +++++++++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 65 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 2e3a6209c8..567ffb159d 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -404,6 +404,10 @@ struct XHCIState { USBBus bus; qemu_irq irq; MemoryRegion mem; + MemoryRegion mem_cap; + MemoryRegion mem_oper; + MemoryRegion mem_runtime; + MemoryRegion mem_doorbell; const char *name; unsigned int devaddr; @@ -2343,8 +2347,9 @@ static void xhci_reset(DeviceState *dev) xhci_mfwrap_update(xhci); } -static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg) +static uint64_t xhci_cap_read(void *ptr, target_phys_addr_t reg, unsigned size) { + XHCIState *xhci = ptr; uint32_t ret; switch (reg) { @@ -2401,7 +2406,7 @@ static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg) ret = 0x00000000; /* reserved */ break; default: - fprintf(stderr, "xhci_cap_read: reg %d unimplemented\n", reg); + fprintf(stderr, "xhci_cap_read: reg %d unimplemented\n", (int)reg); ret = 0; } @@ -2482,8 +2487,9 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val) } } -static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg) +static uint64_t xhci_oper_read(void *ptr, target_phys_addr_t reg, unsigned size) { + XHCIState *xhci = ptr; uint32_t ret; if (reg >= 0x400) { @@ -2519,7 +2525,7 @@ static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg) ret = xhci->config; break; default: - fprintf(stderr, "xhci_oper_read: reg 0x%x unimplemented\n", reg); + fprintf(stderr, "xhci_oper_read: reg 0x%x unimplemented\n", (int)reg); ret = 0; } @@ -2527,8 +2533,11 @@ static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg) return ret; } -static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val) +static void xhci_oper_write(void *ptr, target_phys_addr_t reg, + uint64_t val, unsigned size) { + XHCIState *xhci = ptr; + if (reg >= 0x400) { xhci_port_write(xhci, reg - 0x400, val); return; @@ -2586,12 +2595,14 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val) xhci->config = val & 0xff; break; default: - fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg); + fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", (int)reg); } } -static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg) +static uint64_t xhci_runtime_read(void *ptr, target_phys_addr_t reg, + unsigned size) { + XHCIState *xhci = ptr; uint32_t ret = 0; if (reg < 0x20) { @@ -2600,7 +2611,8 @@ static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg) ret = xhci_mfindex_get(xhci) & 0x3fff; break; default: - fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", reg); + fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", + (int)reg); break; } } else { @@ -2635,14 +2647,16 @@ static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg) return ret; } -static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val) +static void xhci_runtime_write(void *ptr, target_phys_addr_t reg, + uint64_t val, unsigned size) { + XHCIState *xhci = ptr; int v = (reg - 0x20) / 0x20; XHCIInterrupter *intr = &xhci->intr[v]; trace_usb_xhci_runtime_write(reg, val); if (reg < 0x20) { - fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg); + fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", (int)reg); return; } @@ -2684,19 +2698,24 @@ static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val) xhci_events_update(xhci, v); break; default: - fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg); + fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", + (int)reg); } } -static uint32_t xhci_doorbell_read(XHCIState *xhci, uint32_t reg) +static uint64_t xhci_doorbell_read(void *ptr, target_phys_addr_t reg, + unsigned size) { /* doorbells always read as 0 */ trace_usb_xhci_doorbell_read(reg, 0); return 0; } -static void xhci_doorbell_write(XHCIState *xhci, uint32_t reg, uint32_t val) +static void xhci_doorbell_write(void *ptr, target_phys_addr_t reg, + uint64_t val, unsigned size) { + XHCIState *xhci = ptr; + trace_usb_xhci_doorbell_write(reg, val); if (!xhci_running(xhci)) { @@ -2710,69 +2729,47 @@ static void xhci_doorbell_write(XHCIState *xhci, uint32_t reg, uint32_t val) if (val == 0) { xhci_process_commands(xhci); } else { - fprintf(stderr, "xhci: bad doorbell 0 write: 0x%x\n", val); + fprintf(stderr, "xhci: bad doorbell 0 write: 0x%x\n", + (uint32_t)val); } } else { if (reg > MAXSLOTS) { - fprintf(stderr, "xhci: bad doorbell %d\n", reg); + fprintf(stderr, "xhci: bad doorbell %d\n", (int)reg); } else if (val > 31) { - fprintf(stderr, "xhci: bad doorbell %d write: 0x%x\n", reg, val); + fprintf(stderr, "xhci: bad doorbell %d write: 0x%x\n", + (int)reg, (uint32_t)val); } else { xhci_kick_ep(xhci, reg, val); } } } -static uint64_t xhci_mem_read(void *ptr, target_phys_addr_t addr, - unsigned size) -{ - XHCIState *xhci = ptr; +static const MemoryRegionOps xhci_cap_ops = { + .read = xhci_cap_read, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; - /* Only aligned reads are allowed on xHCI */ - if (addr & 3) { - fprintf(stderr, "xhci_mem_read: Mis-aligned read\n"); - return 0; - } +static const MemoryRegionOps xhci_oper_ops = { + .read = xhci_oper_read, + .write = xhci_oper_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; - if (addr < LEN_CAP) { - return xhci_cap_read(xhci, addr); - } else if (addr >= OFF_OPER && addr < (OFF_OPER + LEN_OPER)) { - return xhci_oper_read(xhci, addr - OFF_OPER); - } else if (addr >= OFF_RUNTIME && addr < (OFF_RUNTIME + LEN_RUNTIME)) { - return xhci_runtime_read(xhci, addr - OFF_RUNTIME); - } else if (addr >= OFF_DOORBELL && addr < (OFF_DOORBELL + LEN_DOORBELL)) { - return xhci_doorbell_read(xhci, addr - OFF_DOORBELL); - } else { - fprintf(stderr, "xhci_mem_read: Bad offset %x\n", (int)addr); - return 0; - } -} +static const MemoryRegionOps xhci_runtime_ops = { + .read = xhci_runtime_read, + .write = xhci_runtime_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; -static void xhci_mem_write(void *ptr, target_phys_addr_t addr, - uint64_t val, unsigned size) -{ - XHCIState *xhci = ptr; - - /* Only aligned writes are allowed on xHCI */ - if (addr & 3) { - fprintf(stderr, "xhci_mem_write: Mis-aligned write\n"); - return; - } - - if (addr >= OFF_OPER && addr < (OFF_OPER + LEN_OPER)) { - xhci_oper_write(xhci, addr - OFF_OPER, val); - } else if (addr >= OFF_RUNTIME && addr < (OFF_RUNTIME + LEN_RUNTIME)) { - xhci_runtime_write(xhci, addr - OFF_RUNTIME, val); - } else if (addr >= OFF_DOORBELL && addr < (OFF_DOORBELL + LEN_DOORBELL)) { - xhci_doorbell_write(xhci, addr - OFF_DOORBELL, val); - } else { - fprintf(stderr, "xhci_mem_write: Bad offset %x\n", (int)addr); - } -} - -static const MemoryRegionOps xhci_mem_ops = { - .read = xhci_mem_read, - .write = xhci_mem_write, +static const MemoryRegionOps xhci_doorbell_ops = { + .read = xhci_doorbell_read, + .write = xhci_doorbell_write, .valid.min_access_size = 4, .valid.max_access_size = 4, .endianness = DEVICE_LITTLE_ENDIAN, @@ -2938,8 +2935,21 @@ static int usb_xhci_initfn(struct PCIDevice *dev) xhci->irq = xhci->pci_dev.irq[0]; - memory_region_init_io(&xhci->mem, &xhci_mem_ops, xhci, - "xhci", LEN_REGS); + memory_region_init(&xhci->mem, "xhci", LEN_REGS); + memory_region_init_io(&xhci->mem_cap, &xhci_cap_ops, xhci, + "capabilities", LEN_CAP); + memory_region_init_io(&xhci->mem_oper, &xhci_oper_ops, xhci, + "operational", 0x400 + 0x10 * xhci->numports); + memory_region_init_io(&xhci->mem_runtime, &xhci_runtime_ops, xhci, + "runtime", LEN_RUNTIME); + memory_region_init_io(&xhci->mem_doorbell, &xhci_doorbell_ops, xhci, + "doorbell", LEN_DOORBELL); + + memory_region_add_subregion(&xhci->mem, 0, &xhci->mem_cap); + memory_region_add_subregion(&xhci->mem, OFF_OPER, &xhci->mem_oper); + memory_region_add_subregion(&xhci->mem, OFF_RUNTIME, &xhci->mem_runtime); + memory_region_add_subregion(&xhci->mem, OFF_DOORBELL, &xhci->mem_doorbell); + pci_register_bar(&xhci->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64, &xhci->mem); From 6ee021d41078844df60a3a466e3829a3e82776f3 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 4 Sep 2012 14:48:03 +0200 Subject: [PATCH 0303/2270] xhci: allow bytewise capability register reads Some guests need this according to Alejandro Martinez Ruiz Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 567ffb159d..e0ca69044a 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2746,8 +2746,10 @@ static void xhci_doorbell_write(void *ptr, target_phys_addr_t reg, static const MemoryRegionOps xhci_cap_ops = { .read = xhci_cap_read, - .valid.min_access_size = 4, + .valid.min_access_size = 1, .valid.max_access_size = 4, + .impl.min_access_size = 4, + .impl.max_access_size = 4, .endianness = DEVICE_LITTLE_ENDIAN, }; From c5cc28ff8feac21b502d64453c9491ff38f5d62d Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Thu, 6 Sep 2012 16:47:13 +0200 Subject: [PATCH 0304/2270] tcg: improve profiler Now that there are two passes of optimization (optimize.c, liveness) there is no point of outputing the statistics of the liveness part only. Update the code to take into account both optimizations. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg.c | 12 +++++++++++- tcg/tcg.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 8386b70abd..a4e7f42c78 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -2059,22 +2059,29 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, } #endif +#ifdef CONFIG_PROFILER + s->opt_time -= profile_getclock(); +#endif + #ifdef USE_TCG_OPTIMIZATIONS gen_opparam_ptr = tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs); #endif #ifdef CONFIG_PROFILER + s->opt_time += profile_getclock(); s->la_time -= profile_getclock(); #endif + tcg_liveness_analysis(s); + #ifdef CONFIG_PROFILER s->la_time += profile_getclock(); #endif #ifdef DEBUG_DISAS if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) { - qemu_log("OP after liveness analysis:\n"); + qemu_log("OP after optimization and liveness analysis:\n"); tcg_dump_ops(s); qemu_log("\n"); } @@ -2241,6 +2248,9 @@ void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf) (double)s->interm_time / tot * 100.0); cpu_fprintf(f, " gen_code time %0.1f%%\n", (double)s->code_time / tot * 100.0); + cpu_fprintf(f, "optim./code time %0.1f%%\n", + (double)s->opt_time / (s->code_time ? s->code_time : 1) + * 100.0); cpu_fprintf(f, "liveness/code time %0.1f%%\n", (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0); cpu_fprintf(f, "cpu_restore count %" PRId64 "\n", diff --git a/tcg/tcg.h b/tcg/tcg.h index d710694e0a..7a72729f3a 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -382,6 +382,7 @@ struct TCGContext { int64_t interm_time; int64_t code_time; int64_t la_time; + int64_t opt_time; int64_t restore_count; int64_t restore_time; #endif From 56e4943825e70a45d1fbba4fffa431000c6e1c7a Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Thu, 6 Sep 2012 16:47:13 +0200 Subject: [PATCH 0305/2270] tcg/optimize: split expression simplification Split expression simplification in multiple parts so that a given op can appear multiple times. This patch should not change anything. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index 9c65474a8c..63f970d045 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -322,7 +322,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, break; } - /* Simplify expression if possible. */ + /* Simplify expression for "op r, a, 0 => mov r, a" cases */ switch (op) { CASE_OP_32_64(add): CASE_OP_32_64(sub): @@ -352,6 +352,12 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, continue; } break; + default: + break; + } + + /* Simplify expression for "op r, a, 0 => movi r, 0" cases */ + switch (op) { CASE_OP_32_64(mul): if ((temps[args[2]].state == TCG_TEMP_CONST && temps[args[2]].val == 0)) { @@ -362,6 +368,12 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, continue; } break; + default: + break; + } + + /* Simplify expression for "op r, a, a => mov r, a" cases */ + switch (op) { CASE_OP_32_64(or): CASE_OP_32_64(and): if (args[1] == args[2]) { From 38ee188b1b63606191c013046add021bdc6f1bfd Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Thu, 6 Sep 2012 16:47:14 +0200 Subject: [PATCH 0306/2270] tcg/optimize: simplify or/xor r, a, 0 cases or/xor r, a, 0 is equivalent to a mov r, a. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tcg/optimize.c b/tcg/optimize.c index 63f970d045..0db849edbf 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -331,6 +331,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, CASE_OP_32_64(sar): CASE_OP_32_64(rotl): CASE_OP_32_64(rotr): + CASE_OP_32_64(or): + CASE_OP_32_64(xor): if (temps[args[1]].state == TCG_TEMP_CONST) { /* Proceed with possible constant folding. */ break; From 61251c0c790d0a63468c8e3eb2767c1f4bf3654a Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Thu, 6 Sep 2012 16:47:14 +0200 Subject: [PATCH 0307/2270] tcg/optimize: simplify and r, a, 0 cases and r, a, 0 is equivalent to a movi r, 0. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tcg/optimize.c b/tcg/optimize.c index 0db849edbf..c12cb2bc4b 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -360,6 +360,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, /* Simplify expression for "op r, a, 0 => movi r, 0" cases */ switch (op) { + CASE_OP_32_64(and): CASE_OP_32_64(mul): if ((temps[args[2]].state == TCG_TEMP_CONST && temps[args[2]].val == 0)) { From 01ee5282ea955dee4e189b34ef888be6f36d9861 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Thu, 6 Sep 2012 16:47:14 +0200 Subject: [PATCH 0308/2270] tcg/optimize: simplify shift/rot r, 0, a => movi r, 0 cases shift/rot r, 0, a is equivalent to movi r, 0. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tcg/optimize.c b/tcg/optimize.c index c12cb2bc4b..1698ba39b3 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -322,6 +322,26 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, break; } + /* Simplify expressions for "shift/rot r, 0, a => movi r, 0" */ + switch (op) { + CASE_OP_32_64(shl): + CASE_OP_32_64(shr): + CASE_OP_32_64(sar): + CASE_OP_32_64(rotl): + CASE_OP_32_64(rotr): + if (temps[args[1]].state == TCG_TEMP_CONST + && temps[args[1]].val == 0) { + gen_opc_buf[op_index] = op_to_movi(op); + tcg_opt_gen_movi(gen_args, args[0], 0, nb_temps, nb_globals); + args += 3; + gen_args += 2; + continue; + } + break; + default: + break; + } + /* Simplify expression for "op r, a, 0 => mov r, a" cases */ switch (op) { CASE_OP_32_64(add): From 65a7cce17ddf6fa1a30d4315da1631d9b6c8fd31 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Thu, 6 Sep 2012 16:47:14 +0200 Subject: [PATCH 0309/2270] tcg/optimize: swap brcond/setcond arguments when possible brcond and setcond ops are not commutative, but it's easy to compute the new condition after swapping the arguments. Try to always put the constant argument in second position like for commutative ops, to help backends to generate better code. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tcg/optimize.c b/tcg/optimize.c index 1698ba39b3..7debc8a36a 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -318,6 +318,24 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, args[2] = tmp; } break; + CASE_OP_32_64(brcond): + if (temps[args[0]].state == TCG_TEMP_CONST + && temps[args[1]].state != TCG_TEMP_CONST) { + tmp = args[0]; + args[0] = args[1]; + args[1] = tmp; + args[2] = tcg_swap_cond(args[2]); + } + break; + CASE_OP_32_64(setcond): + if (temps[args[1]].state == TCG_TEMP_CONST + && temps[args[2]].state != TCG_TEMP_CONST) { + tmp = args[1]; + args[1] = args[2]; + args[2] = tmp; + args[3] = tcg_swap_cond(args[3]); + } + break; default: break; } From f8dd19e5c7a5ff8cb5587c9aaea96ef754429713 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Thu, 6 Sep 2012 16:47:14 +0200 Subject: [PATCH 0310/2270] tcg/optimize: add constant folding for setcond Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/tcg/optimize.c b/tcg/optimize.c index 7debc8a36a..1cb1f36335 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -267,6 +267,67 @@ static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y) return res; } +static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x, + TCGArg y, TCGCond c) +{ + switch (op_bits(op)) { + case 32: + switch (c) { + case TCG_COND_EQ: + return (uint32_t)x == (uint32_t)y; + case TCG_COND_NE: + return (uint32_t)x != (uint32_t)y; + case TCG_COND_LT: + return (int32_t)x < (int32_t)y; + case TCG_COND_GE: + return (int32_t)x >= (int32_t)y; + case TCG_COND_LE: + return (int32_t)x <= (int32_t)y; + case TCG_COND_GT: + return (int32_t)x > (int32_t)y; + case TCG_COND_LTU: + return (uint32_t)x < (uint32_t)y; + case TCG_COND_GEU: + return (uint32_t)x >= (uint32_t)y; + case TCG_COND_LEU: + return (uint32_t)x <= (uint32_t)y; + case TCG_COND_GTU: + return (uint32_t)x > (uint32_t)y; + } + break; + case 64: + switch (c) { + case TCG_COND_EQ: + return (uint64_t)x == (uint64_t)y; + case TCG_COND_NE: + return (uint64_t)x != (uint64_t)y; + case TCG_COND_LT: + return (int64_t)x < (int64_t)y; + case TCG_COND_GE: + return (int64_t)x >= (int64_t)y; + case TCG_COND_LE: + return (int64_t)x <= (int64_t)y; + case TCG_COND_GT: + return (int64_t)x > (int64_t)y; + case TCG_COND_LTU: + return (uint64_t)x < (uint64_t)y; + case TCG_COND_GEU: + return (uint64_t)x >= (uint64_t)y; + case TCG_COND_LEU: + return (uint64_t)x <= (uint64_t)y; + case TCG_COND_GTU: + return (uint64_t)x > (uint64_t)y; + } + break; + } + + fprintf(stderr, + "Unrecognized bitness %d or condition %d in " + "do_constant_folding_cond.\n", op_bits(op), c); + tcg_abort(); +} + + /* Propagate constants and copies, fold constant expressions. */ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, TCGArg *args, TCGOpDef *tcg_op_defs) @@ -522,6 +583,26 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, args += 3; break; } + CASE_OP_32_64(setcond): + if (temps[args[1]].state == TCG_TEMP_CONST + && temps[args[2]].state == TCG_TEMP_CONST) { + gen_opc_buf[op_index] = op_to_movi(op); + tmp = do_constant_folding_cond(op, temps[args[1]].val, + temps[args[2]].val, args[3]); + tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals); + gen_args += 2; + args += 4; + break; + } else { + reset_temp(args[0], nb_temps, nb_globals); + gen_args[0] = args[0]; + gen_args[1] = args[1]; + gen_args[2] = args[2]; + gen_args[3] = args[3]; + gen_args += 4; + args += 4; + break; + } case INDEX_op_call: nb_call_args = (args[0] >> 16) + (args[0] & 0xffff); if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) { From fbeaa26c4cf45a83afaab7aac286d5d96199e740 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Thu, 6 Sep 2012 16:47:14 +0200 Subject: [PATCH 0311/2270] tcg/optimize: add constant folding for brcond Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index 1cb1f36335..156e8d9698 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -603,6 +603,32 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, args += 4; break; } + CASE_OP_32_64(brcond): + if (temps[args[0]].state == TCG_TEMP_CONST + && temps[args[1]].state == TCG_TEMP_CONST) { + if (do_constant_folding_cond(op, temps[args[0]].val, + temps[args[1]].val, args[2])) { + memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info)); + gen_opc_buf[op_index] = INDEX_op_br; + gen_args[0] = args[3]; + gen_args += 1; + args += 4; + } else { + gen_opc_buf[op_index] = INDEX_op_nop; + args += 4; + } + break; + } else { + memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info)); + reset_temp(args[0], nb_temps, nb_globals); + gen_args[0] = args[0]; + gen_args[1] = args[1]; + gen_args[2] = args[2]; + gen_args[3] = args[3]; + gen_args += 4; + args += 4; + break; + } case INDEX_op_call: nb_call_args = (args[0] >> 16) + (args[0] & 0xffff); if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) { @@ -624,7 +650,6 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, case INDEX_op_set_label: case INDEX_op_jmp: case INDEX_op_br: - CASE_OP_32_64(brcond): memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info)); for (i = 0; i < def->nb_args; i++) { *gen_args = *args; From fedc0da2510b61742dcc4755938093bef4c6078d Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 7 Sep 2012 12:24:32 +0200 Subject: [PATCH 0312/2270] tcg/optimize: fix if/else/break coding style optimizer.c contains some cases were the break is appearing in both the if and the else parts. Fix that by moving it to the outer part. Also move some common code there. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index 156e8d9698..fba0ed9592 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -441,15 +441,14 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, if ((temps[args[0]].state == TCG_TEMP_COPY && temps[args[0]].val == args[1]) || args[0] == args[1]) { - args += 3; gen_opc_buf[op_index] = INDEX_op_nop; } else { gen_opc_buf[op_index] = op_to_mov(op); tcg_opt_gen_mov(s, gen_args, args[0], args[1], nb_temps, nb_globals); gen_args += 2; - args += 3; } + args += 3; continue; } break; @@ -480,15 +479,14 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, CASE_OP_32_64(and): if (args[1] == args[2]) { if (args[1] == args[0]) { - args += 3; gen_opc_buf[op_index] = INDEX_op_nop; } else { gen_opc_buf[op_index] = op_to_mov(op); tcg_opt_gen_mov(s, gen_args, args[0], args[1], nb_temps, nb_globals); gen_args += 2; - args += 3; } + args += 3; continue; } break; @@ -538,17 +536,14 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, gen_opc_buf[op_index] = op_to_movi(op); tmp = do_constant_folding(op, temps[args[1]].val, 0); tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals); - gen_args += 2; - args += 2; - break; } else { reset_temp(args[0], nb_temps, nb_globals); gen_args[0] = args[0]; gen_args[1] = args[1]; - gen_args += 2; - args += 2; - break; } + gen_args += 2; + args += 2; + break; CASE_OP_32_64(add): CASE_OP_32_64(sub): CASE_OP_32_64(mul): @@ -572,17 +567,15 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, temps[args[2]].val); tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals); gen_args += 2; - args += 3; - break; } else { reset_temp(args[0], nb_temps, nb_globals); gen_args[0] = args[0]; gen_args[1] = args[1]; gen_args[2] = args[2]; gen_args += 3; - args += 3; - break; } + args += 3; + break; CASE_OP_32_64(setcond): if (temps[args[1]].state == TCG_TEMP_CONST && temps[args[2]].state == TCG_TEMP_CONST) { @@ -591,8 +584,6 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, temps[args[2]].val, args[3]); tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals); gen_args += 2; - args += 4; - break; } else { reset_temp(args[0], nb_temps, nb_globals); gen_args[0] = args[0]; @@ -600,9 +591,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, gen_args[2] = args[2]; gen_args[3] = args[3]; gen_args += 4; - args += 4; - break; } + args += 4; + break; CASE_OP_32_64(brcond): if (temps[args[0]].state == TCG_TEMP_CONST && temps[args[1]].state == TCG_TEMP_CONST) { @@ -612,12 +603,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, gen_opc_buf[op_index] = INDEX_op_br; gen_args[0] = args[3]; gen_args += 1; - args += 4; } else { gen_opc_buf[op_index] = INDEX_op_nop; - args += 4; } - break; } else { memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info)); reset_temp(args[0], nb_temps, nb_globals); @@ -626,9 +614,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, gen_args[2] = args[2]; gen_args[3] = args[3]; gen_args += 4; - args += 4; - break; } + args += 4; + break; case INDEX_op_call: nb_call_args = (args[0] >> 16) + (args[0] & 0xffff); if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) { From 2879636d55312b5391ec46c7dee5d3a07714c222 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 18 Jul 2012 11:11:09 +0100 Subject: [PATCH 0313/2270] update-linux-headers.sh: Don't hard code list of architectures Rather than hardcoding the list of architectures in the kernel header update script, just import headers for every architecture which supports KVM (with a blacklist exception for ia64 which has KVM headers but is dead). This reduces the number of QEMU files which need to be updated to add support for a new KVM architecture. Acked-by: Jan Kiszka Signed-off-by: Peter Maydell Signed-off-by: Marcelo Tosatti --- scripts/update-linux-headers.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh index a639c5bff0..53a6f87650 100755 --- a/scripts/update-linux-headers.sh +++ b/scripts/update-linux-headers.sh @@ -28,7 +28,21 @@ if [ -z "$output" ]; then output="$PWD" fi -for arch in x86 powerpc s390; do +# This will pick up non-directories too (eg "Kconfig") but we will +# ignore them in the next loop. +ARCHLIST=$(cd "$linux/arch" && echo *) + +for arch in $ARCHLIST; do + # Discard anything which isn't a KVM-supporting architecture + if ! [ -e "$linux/arch/$arch/include/asm/kvm.h" ]; then + continue + fi + + # Blacklist architectures which have KVM headers but are actually dead + if [ "$arch" = "ia64" ]; then + continue + fi + make -C "$linux" INSTALL_HDR_PATH="$tmpdir" SRCARCH=$arch headers_install rm -rf "$output/linux-headers/asm-$arch" From 8732fbd2afce18afc429da2ad76df7c48b4bac4b Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 15 Aug 2012 12:08:13 +0100 Subject: [PATCH 0314/2270] kvm-all.c: Move init of irqchip_inject_ioctl out of kvm_irqchip_create() Move the init of the irqchip_inject_ioctl field of KVMState out of kvm_irqchip_create() and into kvm_init(), so that kvm_set_irq() can be used even when no irqchip is created (for architectures that support async interrupt notification even without an in kernel irqchip). Signed-off-by: Peter Maydell Signed-off-by: Marcelo Tosatti --- kvm-all.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index 39cff55f5b..f9873db4af 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1237,10 +1237,6 @@ static int kvm_irqchip_create(KVMState *s) return ret; } - s->irqchip_inject_ioctl = KVM_IRQ_LINE; - if (kvm_check_extension(s, KVM_CAP_IRQ_INJECT_STATUS)) { - s->irqchip_inject_ioctl = KVM_IRQ_LINE_STATUS; - } kvm_kernel_irqchip = true; /* If we have an in-kernel IRQ chip then we must have asynchronous * interrupt delivery (though the reverse is not necessarily true) @@ -1389,6 +1385,11 @@ int kvm_init(void) s->intx_set_mask = kvm_check_extension(s, KVM_CAP_PCI_2_3); + s->irqchip_inject_ioctl = KVM_IRQ_LINE; + if (kvm_check_extension(s, KVM_CAP_IRQ_INJECT_STATUS)) { + s->irqchip_inject_ioctl = KVM_IRQ_LINE_STATUS; + } + ret = kvm_arch_init(s); if (ret < 0) { goto err; From d410515e035ccb7433c6a3a8157742f6f679f57f Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 23 Aug 2012 13:02:29 +0200 Subject: [PATCH 0315/2270] memory: Flush coalesced MMIO on selected region access Instead of flushing pending coalesced MMIO requests on every vmexit, this provides a mechanism to selectively flush when memory regions related to the coalesced one are accessed. This first of all includes the coalesced region itself but can also applied to other regions, e.g. of the same device, by calling memory_region_set_flush_coalesced. Signed-off-by: Jan Kiszka Signed-off-by: Marcelo Tosatti --- memory.c | 24 ++++++++++++++++++++++++ memory.h | 26 ++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/memory.c b/memory.c index d528d1f7f3..ae6547f998 100644 --- a/memory.c +++ b/memory.c @@ -311,6 +311,9 @@ static void memory_region_read_accessor(void *opaque, MemoryRegion *mr = opaque; uint64_t tmp; + if (mr->flush_coalesced_mmio) { + qemu_flush_coalesced_mmio_buffer(); + } tmp = mr->ops->read(mr->opaque, addr, size); *value |= (tmp & mask) << shift; } @@ -325,6 +328,9 @@ static void memory_region_write_accessor(void *opaque, MemoryRegion *mr = opaque; uint64_t tmp; + if (mr->flush_coalesced_mmio) { + qemu_flush_coalesced_mmio_buffer(); + } tmp = (*value >> shift) & mask; mr->ops->write(mr->opaque, addr, tmp, size); } @@ -826,6 +832,7 @@ void memory_region_init(MemoryRegion *mr, mr->dirty_log_mask = 0; mr->ioeventfd_nb = 0; mr->ioeventfds = NULL; + mr->flush_coalesced_mmio = false; } static bool memory_region_access_valid(MemoryRegion *mr, @@ -1176,12 +1183,16 @@ void memory_region_add_coalescing(MemoryRegion *mr, cmr->addr = addrrange_make(int128_make64(offset), int128_make64(size)); QTAILQ_INSERT_TAIL(&mr->coalesced, cmr, link); memory_region_update_coalesced_range(mr); + memory_region_set_flush_coalesced(mr); } void memory_region_clear_coalescing(MemoryRegion *mr) { CoalescedMemoryRange *cmr; + qemu_flush_coalesced_mmio_buffer(); + mr->flush_coalesced_mmio = false; + while (!QTAILQ_EMPTY(&mr->coalesced)) { cmr = QTAILQ_FIRST(&mr->coalesced); QTAILQ_REMOVE(&mr->coalesced, cmr, link); @@ -1190,6 +1201,19 @@ void memory_region_clear_coalescing(MemoryRegion *mr) memory_region_update_coalesced_range(mr); } +void memory_region_set_flush_coalesced(MemoryRegion *mr) +{ + mr->flush_coalesced_mmio = true; +} + +void memory_region_clear_flush_coalesced(MemoryRegion *mr) +{ + qemu_flush_coalesced_mmio_buffer(); + if (QTAILQ_EMPTY(&mr->coalesced)) { + mr->flush_coalesced_mmio = false; + } +} + void memory_region_add_eventfd(MemoryRegion *mr, target_phys_addr_t addr, unsigned size, diff --git a/memory.h b/memory.h index bd1bbaeabe..e5aa02868d 100644 --- a/memory.h +++ b/memory.h @@ -133,6 +133,7 @@ struct MemoryRegion { bool enabled; bool rom_device; bool warning_printed; /* For reservations */ + bool flush_coalesced_mmio; MemoryRegion *alias; target_phys_addr_t alias_offset; unsigned priority; @@ -520,6 +521,31 @@ void memory_region_add_coalescing(MemoryRegion *mr, */ void memory_region_clear_coalescing(MemoryRegion *mr); +/** + * memory_region_set_flush_coalesced: Enforce memory coalescing flush before + * accesses. + * + * Ensure that pending coalesced MMIO request are flushed before the memory + * region is accessed. This property is automatically enabled for all regions + * passed to memory_region_set_coalescing() and memory_region_add_coalescing(). + * + * @mr: the memory region to be updated. + */ +void memory_region_set_flush_coalesced(MemoryRegion *mr); + +/** + * memory_region_clear_flush_coalesced: Disable memory coalescing flush before + * accesses. + * + * Clear the automatic coalesced MMIO flushing enabled via + * memory_region_set_flush_coalesced. Note that this service has no effect on + * memory regions that have MMIO coalescing enabled for themselves. For them, + * automatic flushing will stop once coalescing is disabled. + * + * @mr: the memory region to be updated. + */ +void memory_region_clear_flush_coalesced(MemoryRegion *mr); + /** * memory_region_add_eventfd: Request an eventfd to be triggered when a word * is written to a location. From 59023ef41179f61bfc1e2500c406ad28d046b09d Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 23 Aug 2012 13:02:30 +0200 Subject: [PATCH 0316/2270] memory: Use transaction_begin/commit also for single-step operations Wrap also simple operations consisting only of a single step with memory_region_transaction_begin/commit. This allows to perform additional steps like coalesced MMIO flushing from a single place. This requires dropping some micro-optimizations: The skipping of topology updates after updating disabled or unregistered regions. Signed-off-by: Jan Kiszka Signed-off-by: Marcelo Tosatti --- memory.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/memory.c b/memory.c index ae6547f998..5fab415075 100644 --- a/memory.c +++ b/memory.c @@ -1076,8 +1076,9 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client) { uint8_t mask = 1 << client; + memory_region_transaction_begin(); mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask); - memory_region_update_topology(mr); + memory_region_transaction_commit(); } bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr, @@ -1110,16 +1111,18 @@ void memory_region_sync_dirty_bitmap(MemoryRegion *mr) void memory_region_set_readonly(MemoryRegion *mr, bool readonly) { if (mr->readonly != readonly) { + memory_region_transaction_begin(); mr->readonly = readonly; - memory_region_update_topology(mr); + memory_region_transaction_commit(); } } void memory_region_rom_device_set_readable(MemoryRegion *mr, bool readable) { if (mr->readable != readable) { + memory_region_transaction_begin(); mr->readable = readable; - memory_region_update_topology(mr); + memory_region_transaction_commit(); } } @@ -1230,6 +1233,7 @@ void memory_region_add_eventfd(MemoryRegion *mr, }; unsigned i; + memory_region_transaction_begin(); for (i = 0; i < mr->ioeventfd_nb; ++i) { if (memory_region_ioeventfd_before(mrfd, mr->ioeventfds[i])) { break; @@ -1241,7 +1245,7 @@ void memory_region_add_eventfd(MemoryRegion *mr, memmove(&mr->ioeventfds[i+1], &mr->ioeventfds[i], sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb-1 - i)); mr->ioeventfds[i] = mrfd; - memory_region_update_topology(mr); + memory_region_transaction_commit(); } void memory_region_del_eventfd(MemoryRegion *mr, @@ -1260,6 +1264,7 @@ void memory_region_del_eventfd(MemoryRegion *mr, }; unsigned i; + memory_region_transaction_begin(); for (i = 0; i < mr->ioeventfd_nb; ++i) { if (memory_region_ioeventfd_equal(mrfd, mr->ioeventfds[i])) { break; @@ -1271,7 +1276,7 @@ void memory_region_del_eventfd(MemoryRegion *mr, --mr->ioeventfd_nb; mr->ioeventfds = g_realloc(mr->ioeventfds, sizeof(*mr->ioeventfds)*mr->ioeventfd_nb + 1); - memory_region_update_topology(mr); + memory_region_transaction_commit(); } static void memory_region_add_subregion_common(MemoryRegion *mr, @@ -1280,6 +1285,8 @@ static void memory_region_add_subregion_common(MemoryRegion *mr, { MemoryRegion *other; + memory_region_transaction_begin(); + assert(!subregion->parent); subregion->parent = mr; subregion->addr = offset; @@ -1312,7 +1319,7 @@ static void memory_region_add_subregion_common(MemoryRegion *mr, } QTAILQ_INSERT_TAIL(&mr->subregions, subregion, subregions_link); done: - memory_region_update_topology(mr); + memory_region_transaction_commit(); } @@ -1338,10 +1345,11 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr, void memory_region_del_subregion(MemoryRegion *mr, MemoryRegion *subregion) { + memory_region_transaction_begin(); assert(subregion->parent == mr); subregion->parent = NULL; QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link); - memory_region_update_topology(mr); + memory_region_transaction_commit(); } void memory_region_set_enabled(MemoryRegion *mr, bool enabled) @@ -1349,8 +1357,9 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled) if (enabled == mr->enabled) { return; } + memory_region_transaction_begin(); mr->enabled = enabled; - memory_region_update_topology(NULL); + memory_region_transaction_commit(); } void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr) @@ -1376,16 +1385,15 @@ void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr) void memory_region_set_alias_offset(MemoryRegion *mr, target_phys_addr_t offset) { - target_phys_addr_t old_offset = mr->alias_offset; - assert(mr->alias); - mr->alias_offset = offset; - if (offset == old_offset || !mr->parent) { + if (offset == mr->alias_offset) { return; } - memory_region_update_topology(mr); + memory_region_transaction_begin(); + mr->alias_offset = offset; + memory_region_transaction_commit(); } ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr) @@ -1517,14 +1525,16 @@ void memory_listener_unregister(MemoryListener *listener) void set_system_memory_map(MemoryRegion *mr) { + memory_region_transaction_begin(); address_space_memory.root = mr; - memory_region_update_topology(NULL); + memory_region_transaction_commit(); } void set_system_io_map(MemoryRegion *mr) { + memory_region_transaction_begin(); address_space_io.root = mr; - memory_region_update_topology(NULL); + memory_region_transaction_commit(); } uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size) From 02e2b95fb4bcf8b0a512c5eb449cfb9a1ea3d3b7 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 23 Aug 2012 13:02:31 +0200 Subject: [PATCH 0317/2270] memory: Fold memory_region_update_topology into memory_region_transaction_commit Simplify the code as we are using now only a subset of the original features of memory_region_update_topology. Signed-off-by: Jan Kiszka Signed-off-by: Marcelo Tosatti --- memory.c | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/memory.c b/memory.c index 5fab415075..4deeeac575 100644 --- a/memory.c +++ b/memory.c @@ -24,7 +24,6 @@ #include "exec-obsolete.h" unsigned memory_region_transaction_depth = 0; -static bool memory_region_update_pending = false; static bool global_dirty_log = false; static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners @@ -732,31 +731,6 @@ static void address_space_update_topology(AddressSpace *as) address_space_update_ioeventfds(as); } -static void memory_region_update_topology(MemoryRegion *mr) -{ - if (memory_region_transaction_depth) { - memory_region_update_pending |= !mr || mr->enabled; - return; - } - - if (mr && !mr->enabled) { - return; - } - - MEMORY_LISTENER_CALL_GLOBAL(begin, Forward); - - if (address_space_memory.root) { - address_space_update_topology(&address_space_memory); - } - if (address_space_io.root) { - address_space_update_topology(&address_space_io); - } - - MEMORY_LISTENER_CALL_GLOBAL(commit, Forward); - - memory_region_update_pending = false; -} - void memory_region_transaction_begin(void) { ++memory_region_transaction_depth; @@ -766,8 +740,17 @@ void memory_region_transaction_commit(void) { assert(memory_region_transaction_depth); --memory_region_transaction_depth; - if (!memory_region_transaction_depth && memory_region_update_pending) { - memory_region_update_topology(NULL); + if (!memory_region_transaction_depth) { + MEMORY_LISTENER_CALL_GLOBAL(begin, Forward); + + if (address_space_memory.root) { + address_space_update_topology(&address_space_memory); + } + if (address_space_io.root) { + address_space_update_topology(&address_space_io); + } + + MEMORY_LISTENER_CALL_GLOBAL(commit, Forward); } } From bb880ded7a6a77b2a7818e6302ac55fbd9ba5e86 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 23 Aug 2012 13:02:32 +0200 Subject: [PATCH 0318/2270] memory: Flush coalesced MMIO on mapping and state changes Flush pending coalesced MMIO before performing mapping or state changes that could affect the event orderings or route the buffered requests to a wrong region. Signed-off-by: Jan Kiszka Signed-off-by: Marcelo Tosatti --- memory.c | 1 + 1 file changed, 1 insertion(+) diff --git a/memory.c b/memory.c index 4deeeac575..4f3ade06dd 100644 --- a/memory.c +++ b/memory.c @@ -733,6 +733,7 @@ static void address_space_update_topology(AddressSpace *as) void memory_region_transaction_begin(void) { + qemu_flush_coalesced_mmio_buffer(); ++memory_region_transaction_depth; } From bd8f2f5d7034172a53c5a5b229613761f3297493 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 23 Aug 2012 13:02:33 +0200 Subject: [PATCH 0319/2270] VGA: Flush coalesced MMIO on related MMIO/PIO accesses In preparation of stopping to flush coalesced MMIO unconditionally on vmexits, mark VGA MMIO and PIO regions as synchronous /wrt coalesced MMIO and flush the buffer explicitly on PIO accesses that do not use generic memory regions yet. Signed-off-by: Jan Kiszka Signed-off-by: Marcelo Tosatti --- hw/cirrus_vga.c | 7 +++++++ hw/qxl.c | 1 + hw/vga-isa-mm.c | 1 + hw/vga.c | 5 +++++ hw/vmware_vga.c | 1 + 5 files changed, 15 insertions(+) diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index e8dcc6b883..9a0a565723 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -2441,6 +2441,8 @@ static uint32_t cirrus_vga_ioport_read(void *opaque, uint32_t addr) VGACommonState *s = &c->vga; int val, index; + qemu_flush_coalesced_mmio_buffer(); + if (vga_ioport_invalid(s, addr)) { val = 0xff; } else { @@ -2534,6 +2536,8 @@ static void cirrus_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) VGACommonState *s = &c->vga; int index; + qemu_flush_coalesced_mmio_buffer(); + /* check port range access depending on color/monochrome mode */ if (vga_ioport_invalid(s, addr)) { return; @@ -2854,6 +2858,7 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci, /* I/O handler for LFB */ memory_region_init_io(&s->cirrus_linear_io, &cirrus_linear_io_ops, s, "cirrus-linear-io", VGA_RAM_SIZE); + memory_region_set_flush_coalesced(&s->cirrus_linear_io); /* I/O handler for LFB */ memory_region_init_io(&s->cirrus_linear_bitblt_io, @@ -2861,10 +2866,12 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci, s, "cirrus-bitblt-mmio", 0x400000); + memory_region_set_flush_coalesced(&s->cirrus_linear_bitblt_io); /* I/O handler for memory-mapped I/O */ memory_region_init_io(&s->cirrus_mmio_io, &cirrus_mmio_io_ops, s, "cirrus-mmio", CIRRUS_PNPMMIO_SIZE); + memory_region_set_flush_coalesced(&s->cirrus_mmio_io); s->real_vram_size = (s->device_id == CIRRUS_ID_CLGD5446) ? 4096 * 1024 : 2048 * 1024; diff --git a/hw/qxl.c b/hw/qxl.c index 5b3f484266..43d6a67ecc 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1910,6 +1910,7 @@ static int qxl_init_common(PCIQXLDevice *qxl) if (qxl->id == 0) { vga_dirty_log_start(&qxl->vga); } + memory_region_set_flush_coalesced(&qxl->io_bar); pci_register_bar(&qxl->pci, QXL_IO_RANGE_INDEX, diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c index 44ae7d92c8..306e6ba443 100644 --- a/hw/vga-isa-mm.c +++ b/hw/vga-isa-mm.c @@ -107,6 +107,7 @@ static void vga_mm_init(ISAVGAMMState *s, target_phys_addr_t vram_base, s_ioport_ctrl = g_malloc(sizeof(*s_ioport_ctrl)); memory_region_init_io(s_ioport_ctrl, &vga_mm_ctrl_ops, s, "vga-mm-ctrl", 0x100000); + memory_region_set_flush_coalesced(s_ioport_ctrl); vga_io_memory = g_malloc(sizeof(*vga_io_memory)); /* XXX: endianness? */ diff --git a/hw/vga.c b/hw/vga.c index 80299ea1d4..afaef0d711 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -361,6 +361,8 @@ uint32_t vga_ioport_read(void *opaque, uint32_t addr) VGACommonState *s = opaque; int val, index; + qemu_flush_coalesced_mmio_buffer(); + if (vga_ioport_invalid(s, addr)) { val = 0xff; } else { @@ -453,6 +455,8 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) VGACommonState *s = opaque; int index; + qemu_flush_coalesced_mmio_buffer(); + /* check port range access depending on color/monochrome mode */ if (vga_ioport_invalid(s, addr)) { return; @@ -2338,6 +2342,7 @@ MemoryRegion *vga_init_io(VGACommonState *s, vga_mem = g_malloc(sizeof(*vga_mem)); memory_region_init_io(vga_mem, &vga_mem_ops, s, "vga-lowmem", 0x20000); + memory_region_set_flush_coalesced(vga_mem); return vga_mem; } diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index b68e88367f..e815a04e9f 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -1186,6 +1186,7 @@ static int pci_vmsvga_initfn(PCIDevice *dev) memory_region_init_io(&s->io_bar, &vmsvga_io_ops, &s->chip, "vmsvga-io", 0x10); + memory_region_set_flush_coalesced(&s->io_bar); pci_register_bar(&s->card, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar); vmsvga_init(&s->chip, pci_address_space(dev), From 683d4b5d9f46f7453271577ad0212b67bdd9cb1b Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 23 Aug 2012 13:02:34 +0200 Subject: [PATCH 0320/2270] kvm: Stop flushing coalesced MMIO on vmexit The memory subsystem will now take care of flushing whenever affected regions are accessed or the memory mapping changes. Signed-off-by: Jan Kiszka Signed-off-by: Marcelo Tosatti --- kvm-all.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index f9873db4af..a624709103 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1577,8 +1577,6 @@ int kvm_cpu_exec(CPUArchState *env) qemu_mutex_lock_iothread(); kvm_arch_post_run(env, run); - kvm_flush_coalesced_mmio_buffer(); - if (run_ret < 0) { if (run_ret == -EINTR || run_ret == -EAGAIN) { DPRINTF("io window exit\n"); From e333cd694920f056573083c6d38fbdf0238c390d Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 24 Aug 2012 13:34:47 +0200 Subject: [PATCH 0321/2270] kvm: Rename irqchip_inject_ioctl to irq_set_ioctl This variable is no longer bound to irqchip, and the IOCTL sets the IRQ level, does not directly inject it. No functional changes. Reviewed-by: Peter Maydell Signed-off-by: Jan Kiszka Signed-off-by: Marcelo Tosatti --- kvm-all.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index a624709103..b69537ae0b 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -92,7 +92,7 @@ struct KVMState /* The man page (and posix) say ioctl numbers are signed int, but * they're not. Linux, glibc and *BSD all treat ioctl numbers as * unsigned, and treating them as signed here can break things */ - unsigned irqchip_inject_ioctl; + unsigned irq_set_ioctl; #ifdef KVM_CAP_IRQ_ROUTING struct kvm_irq_routing *irq_routes; int nr_allocated_irq_routes; @@ -870,13 +870,13 @@ int kvm_set_irq(KVMState *s, int irq, int level) event.level = level; event.irq = irq; - ret = kvm_vm_ioctl(s, s->irqchip_inject_ioctl, &event); + ret = kvm_vm_ioctl(s, s->irq_set_ioctl, &event); if (ret < 0) { perror("kvm_set_irq"); abort(); } - return (s->irqchip_inject_ioctl == KVM_IRQ_LINE) ? 1 : event.status; + return (s->irq_set_ioctl == KVM_IRQ_LINE) ? 1 : event.status; } #ifdef KVM_CAP_IRQ_ROUTING @@ -1385,9 +1385,9 @@ int kvm_init(void) s->intx_set_mask = kvm_check_extension(s, KVM_CAP_PCI_2_3); - s->irqchip_inject_ioctl = KVM_IRQ_LINE; + s->irq_set_ioctl = KVM_IRQ_LINE; if (kvm_check_extension(s, KVM_CAP_IRQ_INJECT_STATUS)) { - s->irqchip_inject_ioctl = KVM_IRQ_LINE_STATUS; + s->irq_set_ioctl = KVM_IRQ_LINE_STATUS; } ret = kvm_arch_init(s); From b1af98ba3e4c4fd44f233fc7240df2612baeb1c2 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 5 Sep 2012 08:25:08 +0200 Subject: [PATCH 0322/2270] spice: switch to queue for vga mode updates Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 6 +++--- ui/spice-display.c | 25 ++++++++++++++----------- ui/spice-display.h | 3 ++- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 5b3f484266..257a37d3c5 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -597,9 +597,9 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) case QXL_MODE_VGA: ret = false; qemu_mutex_lock(&qxl->ssd.lock); - if (qxl->ssd.update != NULL) { - update = qxl->ssd.update; - qxl->ssd.update = NULL; + update = QTAILQ_FIRST(&qxl->ssd.updates); + if (update != NULL) { + QTAILQ_REMOVE(&qxl->ssd.updates, update, next); *ext = update->ext; ret = true; } diff --git a/ui/spice-display.c b/ui/spice-display.c index 99bc665bc7..59c5fd7642 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -164,7 +164,7 @@ int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd) #endif } -static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) +static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) { SimpleSpiceUpdate *update; QXLDrawable *drawable; @@ -175,7 +175,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) struct timespec time_space; if (qemu_spice_rect_is_empty(&ssd->dirty)) { - return NULL; + return; }; trace_qemu_spice_create_update( @@ -239,7 +239,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) cmd->data = (uintptr_t)drawable; memset(&ssd->dirty, 0, sizeof(ssd->dirty)); - return update; + QTAILQ_INSERT_TAIL(&ssd->updates, update, next); } /* @@ -315,6 +315,7 @@ void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds) { ssd->ds = ds; qemu_mutex_init(&ssd->lock); + QTAILQ_INIT(&ssd->updates); ssd->mouse_x = -1; ssd->mouse_y = -1; if (ssd->num_surfaces == 0) { @@ -345,6 +346,8 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd, void qemu_spice_display_resize(SimpleSpiceDisplay *ssd) { + SimpleSpiceUpdate *update; + dprint(1, "%s:\n", __FUNCTION__); memset(&ssd->dirty, 0, sizeof(ssd->dirty)); @@ -352,9 +355,9 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd) ssd->conv = NULL; qemu_mutex_lock(&ssd->lock); - if (ssd->update != NULL) { - qemu_spice_destroy_update(ssd, ssd->update); - ssd->update = NULL; + while ((update = QTAILQ_FIRST(&ssd->updates)) != NULL) { + QTAILQ_REMOVE(&ssd->updates, update, next); + qemu_spice_destroy_update(ssd, update); } qemu_mutex_unlock(&ssd->lock); qemu_spice_destroy_host_primary(ssd); @@ -384,8 +387,8 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd) vga_hw_update(); qemu_mutex_lock(&ssd->lock); - if (ssd->update == NULL) { - ssd->update = qemu_spice_create_update(ssd); + if (QTAILQ_EMPTY(&ssd->updates)) { + qemu_spice_create_update(ssd); ssd->notify++; } qemu_spice_cursor_refresh_unlocked(ssd); @@ -442,9 +445,9 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) dprint(3, "%s:\n", __FUNCTION__); qemu_mutex_lock(&ssd->lock); - if (ssd->update != NULL) { - update = ssd->update; - ssd->update = NULL; + update = QTAILQ_FIRST(&ssd->updates); + if (update != NULL) { + QTAILQ_REMOVE(&ssd->updates, update, next); *ext = update->ext; ret = true; } diff --git a/ui/spice-display.h b/ui/spice-display.h index 512ab7831b..3fcb6fec25 100644 --- a/ui/spice-display.h +++ b/ui/spice-display.h @@ -92,7 +92,7 @@ struct SimpleSpiceDisplay { * to them must be protected by the lock. */ QemuMutex lock; - SimpleSpiceUpdate *update; + QTAILQ_HEAD(, SimpleSpiceUpdate) updates; QEMUCursor *cursor; int mouse_x, mouse_y; }; @@ -102,6 +102,7 @@ struct SimpleSpiceUpdate { QXLImage image; QXLCommandExt ext; uint8_t *bitmap; + QTAILQ_ENTRY(SimpleSpiceUpdate) next; }; int qemu_spice_rect_is_empty(const QXLRect* r); From c60319a3aa136769e38ea8b24e91fb4867c4587d Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 5 Sep 2012 08:52:23 +0200 Subject: [PATCH 0323/2270] spice: split qemu_spice_create_update Creating one function which creates a single update for a given rectangle. And one (for now) pretty simple wrapper around it to queue up screen updates for the dirty region. [ v2: also update bounding box ] Signed-off-by: Gerd Hoffmann --- ui/spice-display.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/ui/spice-display.c b/ui/spice-display.c index 59c5fd7642..6f68f28137 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -164,7 +164,8 @@ int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd) #endif } -static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) +static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd, + QXLRect *rect) { SimpleSpiceUpdate *update; QXLDrawable *drawable; @@ -174,24 +175,20 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) int by, bw, bh; struct timespec time_space; - if (qemu_spice_rect_is_empty(&ssd->dirty)) { - return; - }; - trace_qemu_spice_create_update( - ssd->dirty.left, ssd->dirty.right, - ssd->dirty.top, ssd->dirty.bottom); + rect->left, rect->right, + rect->top, rect->bottom); update = g_malloc0(sizeof(*update)); drawable = &update->drawable; image = &update->image; cmd = &update->ext.cmd; - bw = ssd->dirty.right - ssd->dirty.left; - bh = ssd->dirty.bottom - ssd->dirty.top; + bw = rect->right - rect->left; + bh = rect->bottom - rect->top; update->bitmap = g_malloc(bw * bh * 4); - drawable->bbox = ssd->dirty; + drawable->bbox = *rect; drawable->clip.type = SPICE_CLIP_TYPE_NONE; drawable->effect = QXL_EFFECT_OPAQUE; drawable->release_info.id = (uintptr_t)update; @@ -226,8 +223,8 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) } src = ds_get_data(ssd->ds) + - ssd->dirty.top * ds_get_linesize(ssd->ds) + - ssd->dirty.left * ds_get_bytes_per_pixel(ssd->ds); + rect->top * ds_get_linesize(ssd->ds) + + rect->left * ds_get_bytes_per_pixel(ssd->ds); dst = update->bitmap; for (by = 0; by < bh; by++) { qemu_pf_conv_run(ssd->conv, dst, src, bw); @@ -238,10 +235,18 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) cmd->type = QXL_CMD_DRAW; cmd->data = (uintptr_t)drawable; - memset(&ssd->dirty, 0, sizeof(ssd->dirty)); QTAILQ_INSERT_TAIL(&ssd->updates, update, next); } +static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) +{ + if (qemu_spice_rect_is_empty(&ssd->dirty)) { + return; + }; + qemu_spice_create_one_update(ssd, &ssd->dirty); + memset(&ssd->dirty, 0, sizeof(ssd->dirty)); +} + /* * Called from spice server thread context (via interface_release_ressource) * We do *not* hold the global qemu mutex here, so extra care is needed From a7310dd34df4d35a1c3e7ea3f4a94c60f6d5064b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 5 Sep 2012 09:35:57 +0200 Subject: [PATCH 0324/2270] spice: add screen mirror Create a screen mirror, keep there a copy of the most recent update passed on to spice-server. Signed-off-by: Gerd Hoffmann --- ui/spice-display.c | 32 ++++++++++++++++++++++---------- ui/spice-display.h | 1 + 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/ui/spice-display.c b/ui/spice-display.c index 6f68f28137..973cd531a3 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -171,8 +171,8 @@ static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd, QXLDrawable *drawable; QXLImage *image; QXLCommand *cmd; - uint8_t *src, *dst; - int by, bw, bh; + uint8_t *src, *mirror, *dst; + int by, bw, bh, offset, bytes; struct timespec time_space; trace_qemu_spice_create_update( @@ -216,19 +216,18 @@ static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd, image->bitmap.palette = 0; image->bitmap.format = SPICE_BITMAP_FMT_32BIT; - if (ssd->conv == NULL) { - PixelFormat dst = qemu_default_pixelformat(32); - ssd->conv = qemu_pf_conv_get(&dst, &ssd->ds->surface->pf); - assert(ssd->conv); - } - - src = ds_get_data(ssd->ds) + + offset = rect->top * ds_get_linesize(ssd->ds) + rect->left * ds_get_bytes_per_pixel(ssd->ds); + bytes = ds_get_bytes_per_pixel(ssd->ds) * bw; + src = ds_get_data(ssd->ds) + offset; + mirror = ssd->ds_mirror + offset; dst = update->bitmap; for (by = 0; by < bh; by++) { - qemu_pf_conv_run(ssd->conv, dst, src, bw); + memcpy(mirror, src, bytes); + qemu_pf_conv_run(ssd->conv, dst, mirror, bw); src += ds_get_linesize(ssd->ds); + mirror += ds_get_linesize(ssd->ds); dst += image->bitmap.stride; } @@ -243,6 +242,17 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) if (qemu_spice_rect_is_empty(&ssd->dirty)) { return; }; + + if (ssd->conv == NULL) { + PixelFormat dst = qemu_default_pixelformat(32); + ssd->conv = qemu_pf_conv_get(&dst, &ssd->ds->surface->pf); + assert(ssd->conv); + } + if (ssd->ds_mirror == NULL) { + int size = ds_get_height(ssd->ds) * ds_get_linesize(ssd->ds); + ssd->ds_mirror = g_malloc0(size); + } + qemu_spice_create_one_update(ssd, &ssd->dirty); memset(&ssd->dirty, 0, sizeof(ssd->dirty)); } @@ -358,6 +368,8 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd) memset(&ssd->dirty, 0, sizeof(ssd->dirty)); qemu_pf_conv_put(ssd->conv); ssd->conv = NULL; + g_free(ssd->ds_mirror); + ssd->ds_mirror = NULL; qemu_mutex_lock(&ssd->lock); while ((update = QTAILQ_FIRST(&ssd->updates)) != NULL) { diff --git a/ui/spice-display.h b/ui/spice-display.h index 3fcb6fec25..dea41c1b71 100644 --- a/ui/spice-display.h +++ b/ui/spice-display.h @@ -72,6 +72,7 @@ typedef struct SimpleSpiceUpdate SimpleSpiceUpdate; struct SimpleSpiceDisplay { DisplayState *ds; + uint8_t *ds_mirror; void *buf; int bufsize; QXLWorker *worker; From b021bd29835b0367d499e042f76afbbf4b6ee026 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 5 Sep 2012 10:41:42 +0200 Subject: [PATCH 0325/2270] spice: send updates only for changed screen content when creating screen updates go compare the current guest screen against the mirror (which holds the most recent update sent), then only create updates for the screen areas which did actually change. [ v2: drop redundant qemu_spice_create_one_update call ] Signed-off-by: Gerd Hoffmann --- ui/spice-display.c | 56 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/ui/spice-display.c b/ui/spice-display.c index 973cd531a3..d0627655f4 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -239,6 +239,13 @@ static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd, static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) { + static const int blksize = 32; + int blocks = (ds_get_width(ssd->ds) + blksize - 1) / blksize; + int dirty_top[blocks]; + int y, yoff, x, xoff, blk, bw; + int bpp = ds_get_bytes_per_pixel(ssd->ds); + uint8_t *guest, *mirror; + if (qemu_spice_rect_is_empty(&ssd->dirty)) { return; }; @@ -253,7 +260,54 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) ssd->ds_mirror = g_malloc0(size); } - qemu_spice_create_one_update(ssd, &ssd->dirty); + for (blk = 0; blk < blocks; blk++) { + dirty_top[blk] = -1; + } + + guest = ds_get_data(ssd->ds); + mirror = ssd->ds_mirror; + for (y = ssd->dirty.top; y < ssd->dirty.bottom; y++) { + yoff = y * ds_get_linesize(ssd->ds); + for (x = ssd->dirty.left; x < ssd->dirty.right; x += blksize) { + xoff = x * bpp; + blk = x / blksize; + bw = MIN(blksize, ssd->dirty.right - x); + if (memcmp(guest + yoff + xoff, + mirror + yoff + xoff, + bw * bpp) == 0) { + if (dirty_top[blk] != -1) { + QXLRect update = { + .top = dirty_top[blk], + .bottom = y, + .left = x, + .right = x + bw, + }; + qemu_spice_create_one_update(ssd, &update); + dirty_top[blk] = -1; + } + } else { + if (dirty_top[blk] == -1) { + dirty_top[blk] = y; + } + } + } + } + + for (x = ssd->dirty.left; x < ssd->dirty.right; x += blksize) { + blk = x / blksize; + bw = MIN(blksize, ssd->dirty.right - x); + if (dirty_top[blk] != -1) { + QXLRect update = { + .top = dirty_top[blk], + .bottom = ssd->dirty.bottom, + .left = x, + .right = x + bw, + }; + qemu_spice_create_one_update(ssd, &update); + dirty_top[blk] = -1; + } + } + memset(&ssd->dirty, 0, sizeof(ssd->dirty)); } From ccc2960d654a233a6ed415b37d8ff41728d817c5 Mon Sep 17 00:00:00 2001 From: Dunrong Huang Date: Fri, 31 Aug 2012 00:44:44 +0800 Subject: [PATCH 0326/2270] qxl: dont update invalid area This patch fixes the following error: $ ~/usr/bin/qemu-system-x86_64 -enable-kvm -m 1024 -spice port=5900,disable-ticketing -vga qxl -cdrom ~/Images/linuxmint-13-mate-dvd-32bit.iso (/home/mathslinux/usr/bin/qemu-system-x86_64:10068): SpiceWorker-CRITICAL **: red_worker.c:4599:red_update_area: condition `area->left >= 0 && area->top >= 0 && area->left < area->right && area->top < area->bottom' failed Aborted spice server terminates QEMU process if we pass invalid area to it, so dont update those invalid areas. Signed-off-by: Dunrong Huang Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hw/qxl.c b/hw/qxl.c index 257a37d3c5..0176b1a11a 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1470,6 +1470,13 @@ async_common: return; } + if (update.left < 0 || update.top < 0 || update.left >= update.right || + update.top >= update.bottom) { + qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: " + "invalid area(%d,%d,%d,%d)\n", update.left, + update.right, update.top, update.bottom); + break; + } if (async == QXL_ASYNC) { cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO, QXL_IO_UPDATE_AREA_ASYNC); From ab902981cf4d46834d82eb095f2b9ab159e017bf Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 7 Sep 2012 21:48:22 +0200 Subject: [PATCH 0327/2270] qxl: Ignore set_client_capabilities pre/post migrate The recent introduction of set_client_capabilities has broken (seamless) migration by trying to call qxl_send_events pre (seamless incoming) and post (*) migration, triggering the following assert: qxl_send_events: Assertion `qemu_spice_display_is_running(&d->ssd)' failed. The solution is easy, pre migration the guest will have already received the client caps on the migration source side, and post migration there no longer is a guest, so we can simply ignore the set_client_capabilities call in both those scenarios. *) Post migration, so not fatal for to the migration itself, but still a crash Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/qxl.c b/hw/qxl.c index 0176b1a11a..e539134c65 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -953,6 +953,11 @@ static void interface_set_client_capabilities(QXLInstance *sin, { PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); + if (runstate_check(RUN_STATE_INMIGRATE) || + runstate_check(RUN_STATE_POSTMIGRATE)) { + return; + } + qxl->shadow_rom.client_present = client_present; memcpy(qxl->shadow_rom.client_capabilities, caps, sizeof(caps)); qxl->rom->client_present = client_present; From 63587e31353b6652cadfcfb869f5692a2b69daeb Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 6 Sep 2012 12:03:41 +0200 Subject: [PATCH 0328/2270] usb-host: allow emulated (non-async) control requests without USBPacket xhci needs this for USB_REQ_SET_ADDRESS due to the way usb addressing is handled by the xhci hardware. Signed-off-by: Gerd Hoffmann --- hw/usb/host-linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c index 8df92074d3..44f1a64b35 100644 --- a/hw/usb/host-linux.c +++ b/hw/usb/host-linux.c @@ -1045,7 +1045,6 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p, /* Note request is (bRequestType << 8) | bRequest */ trace_usb_host_req_control(s->bus_num, s->addr, p, request, value, index); - assert(p->result == 0); switch (request) { case DeviceOutRequest | USB_REQ_SET_ADDRESS: @@ -1074,6 +1073,7 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p, } /* The rest are asynchronous */ + assert(p && p->result == 0); if (length > sizeof(dev->data_buf)) { fprintf(stderr, "husb: ctrl buffer too small (%d > %zu)\n", From 753b8b0d77ba1b343a35f9679cc777ea10a62bba Mon Sep 17 00:00:00 2001 From: Uri Lublin Date: Tue, 11 Sep 2012 10:09:58 +0300 Subject: [PATCH 0329/2270] qxl: better cleanup for surface destroy Add back a call to qxl_spice_destroy_surface_wait_complete() in qxl_spice_destroy_surface_wait(), that was removed by commit c480bb7da465186b84d8427e068ef7502e47ffbf It is needed to complete surface-removal cleanup, for non async. For async, qxl_spice_destroy_surface_wait_complete is called upon operation completion. Signed-off-by: Uri Lublin Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/qxl.c b/hw/qxl.c index e539134c65..12597e75de 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -201,6 +201,7 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id, spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uintptr_t)cookie); } else { qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id); + qxl_spice_destroy_surface_wait_complete(qxl, id); } } From 3e4f910c8d490a1490409a7e381dbbb229f9d272 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 6 Sep 2012 11:24:51 +0200 Subject: [PATCH 0330/2270] ehci: switch to new-style memory ops Also register different memory regions for capabilities, operational registers and port status registers. Create separate tracepoints for operational regs and port status regs. Ditch a bunch of sanity checks because the memory core will do this for us now. Offloading the byte, word and dword access handling to the memory core also has the side effect of fixing ehci register access on bigendian hosts. Cc: David Gibson Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 181 ++++++++++++++++++++++------------------------ trace-events | 9 ++- 2 files changed, 94 insertions(+), 96 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 2f3e9c03a1..f5ba8e1469 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -389,6 +389,9 @@ struct EHCIState { USBBus bus; qemu_irq irq; MemoryRegion mem; + MemoryRegion mem_caps; + MemoryRegion mem_opreg; + MemoryRegion mem_ports; int companion_count; /* properties */ @@ -398,10 +401,10 @@ struct EHCIState { * EHCI spec version 1.0 Section 2.3 * Host Controller Operational Registers */ + uint8_t caps[OPREGBASE]; union { - uint8_t mmio[MMIO_SIZE]; + uint32_t opreg[(PORTSC_BEGIN-OPREGBASE)/sizeof(uint32_t)]; struct { - uint8_t cap[OPREGBASE]; uint32_t usbcmd; uint32_t usbsts; uint32_t usbintr; @@ -411,9 +414,9 @@ struct EHCIState { uint32_t asynclistaddr; uint32_t notused[9]; uint32_t configflag; - uint32_t portsc[NB_PORTS]; }; }; + uint32_t portsc[NB_PORTS]; /* * Internal states, shadow registers, etc @@ -471,22 +474,12 @@ static const char *ehci_state_names[] = { }; static const char *ehci_mmio_names[] = { - [CAPLENGTH] = "CAPLENGTH", - [HCIVERSION] = "HCIVERSION", - [HCSPARAMS] = "HCSPARAMS", - [HCCPARAMS] = "HCCPARAMS", [USBCMD] = "USBCMD", [USBSTS] = "USBSTS", [USBINTR] = "USBINTR", [FRINDEX] = "FRINDEX", [PERIODICLISTBASE] = "P-LIST BASE", [ASYNCLISTADDR] = "A-LIST ADDR", - [PORTSC_BEGIN] = "PORTSC #0", - [PORTSC_BEGIN + 4] = "PORTSC #1", - [PORTSC_BEGIN + 8] = "PORTSC #2", - [PORTSC_BEGIN + 12] = "PORTSC #3", - [PORTSC_BEGIN + 16] = "PORTSC #4", - [PORTSC_BEGIN + 20] = "PORTSC #5", [CONFIGFLAG] = "CONFIGFLAG", }; @@ -509,7 +502,8 @@ static const char *state2str(uint32_t state) static const char *addr2str(target_phys_addr_t addr) { - return nr2str(ehci_mmio_names, ARRAY_SIZE(ehci_mmio_names), addr); + return nr2str(ehci_mmio_names, ARRAY_SIZE(ehci_mmio_names), + addr + OPREGBASE); } static void ehci_trace_usbsts(uint32_t mask, int state) @@ -1018,7 +1012,7 @@ static int ehci_register_companion(USBBus *bus, USBPort *ports[], } s->companion_count++; - s->mmio[0x05] = (s->companion_count << 4) | portcount; + s->caps[0x05] = (s->companion_count << 4) | portcount; return 0; } @@ -1063,7 +1057,8 @@ static void ehci_reset(void *opaque) } } - memset(&s->mmio[OPREGBASE], 0x00, MMIO_SIZE - OPREGBASE); + memset(&s->opreg, 0x00, sizeof(s->opreg)); + memset(&s->portsc, 0x00, sizeof(s->portsc)); s->usbcmd = NB_MAXINTRATE << USBCMD_ITC_SH; s->usbsts = USBSTS_HALT; @@ -1090,50 +1085,35 @@ static void ehci_reset(void *opaque) qemu_bh_cancel(s->async_bh); } -static uint32_t ehci_mem_readb(void *ptr, target_phys_addr_t addr) +static uint64_t ehci_caps_read(void *ptr, target_phys_addr_t addr, + unsigned size) +{ + EHCIState *s = ptr; + return s->caps[addr]; +} + +static uint64_t ehci_opreg_read(void *ptr, target_phys_addr_t addr, + unsigned size) { EHCIState *s = ptr; uint32_t val; - val = s->mmio[addr]; - + val = s->opreg[addr >> 2]; + trace_usb_ehci_opreg_read(addr + OPREGBASE, addr2str(addr), val); return val; } -static uint32_t ehci_mem_readw(void *ptr, target_phys_addr_t addr) +static uint64_t ehci_port_read(void *ptr, target_phys_addr_t addr, + unsigned size) { EHCIState *s = ptr; uint32_t val; - val = s->mmio[addr] | (s->mmio[addr+1] << 8); - + val = s->portsc[addr >> 2]; + trace_usb_ehci_portsc_read(addr + PORTSC_BEGIN, addr >> 2, val); return val; } -static uint32_t ehci_mem_readl(void *ptr, target_phys_addr_t addr) -{ - EHCIState *s = ptr; - uint32_t val; - - val = s->mmio[addr] | (s->mmio[addr+1] << 8) | - (s->mmio[addr+2] << 16) | (s->mmio[addr+3] << 24); - - trace_usb_ehci_mmio_readl(addr, addr2str(addr), val); - return val; -} - -static void ehci_mem_writeb(void *ptr, target_phys_addr_t addr, uint32_t val) -{ - fprintf(stderr, "EHCI doesn't handle byte writes to MMIO\n"); - exit(1); -} - -static void ehci_mem_writew(void *ptr, target_phys_addr_t addr, uint32_t val) -{ - fprintf(stderr, "EHCI doesn't handle 16-bit writes to MMIO\n"); - exit(1); -} - static void handle_port_owner_write(EHCIState *s, int port, uint32_t owner) { USBDevice *dev = s->ports[port].dev; @@ -1162,11 +1142,17 @@ static void handle_port_owner_write(EHCIState *s, int port, uint32_t owner) } } -static void handle_port_status_write(EHCIState *s, int port, uint32_t val) +static void ehci_port_write(void *ptr, target_phys_addr_t addr, + uint64_t val, unsigned size) { + EHCIState *s = ptr; + int port = addr >> 2; uint32_t *portsc = &s->portsc[port]; + uint32_t old = *portsc; USBDevice *dev = s->ports[port].dev; + trace_usb_ehci_portsc_write(addr + PORTSC_BEGIN, addr >> 2, val); + /* Clear rwc bits */ *portsc &= ~(val & PORTSC_RWC_MASK); /* The guest may clear, but not set the PED bit */ @@ -1198,39 +1184,20 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val) *portsc &= ~PORTSC_RO_MASK; *portsc |= val; + trace_usb_ehci_portsc_change(addr + PORTSC_BEGIN, addr >> 2, *portsc, old); } -static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) +static void ehci_opreg_write(void *ptr, target_phys_addr_t addr, + uint64_t val, unsigned size) { EHCIState *s = ptr; - uint32_t *mmio = (uint32_t *)(&s->mmio[addr]); + uint32_t *mmio = s->opreg + (addr >> 2); uint32_t old = *mmio; int i; - trace_usb_ehci_mmio_writel(addr, addr2str(addr), val); + trace_usb_ehci_opreg_write(addr + OPREGBASE, addr2str(addr), val); - /* Only aligned reads are allowed on OHCI */ - if (addr & 3) { - fprintf(stderr, "usb-ehci: Mis-aligned write to addr 0x" - TARGET_FMT_plx "\n", addr); - return; - } - - if (addr >= PORTSC && addr < PORTSC + 4 * NB_PORTS) { - handle_port_status_write(s, (addr-PORTSC)/4, val); - trace_usb_ehci_mmio_change(addr, addr2str(addr), *mmio, old); - return; - } - - if (addr < OPREGBASE) { - fprintf(stderr, "usb-ehci: write attempt to read-only register" - TARGET_FMT_plx "\n", addr); - return; - } - - - /* Do any register specific pre-write processing here. */ - switch(addr) { + switch (addr + OPREGBASE) { case USBCMD: if (val & USBCMD_HCRESET) { ehci_reset(s); @@ -1241,7 +1208,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) /* not supporting dynamic frame list size at the moment */ if ((val & USBCMD_FLS) && !(s->usbcmd & USBCMD_FLS)) { fprintf(stderr, "attempt to set frame list size -- value %d\n", - val & USBCMD_FLS); + (int)val & USBCMD_FLS); val &= ~USBCMD_FLS; } @@ -1308,7 +1275,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) } *mmio = val; - trace_usb_ehci_mmio_change(addr, addr2str(addr), *mmio, old); + trace_usb_ehci_opreg_change(addr + OPREGBASE, addr2str(addr), *mmio, old); } @@ -2520,11 +2487,28 @@ static void ehci_async_bh(void *opaque) ehci_advance_async_state(ehci); } -static const MemoryRegionOps ehci_mem_ops = { - .old_mmio = { - .read = { ehci_mem_readb, ehci_mem_readw, ehci_mem_readl }, - .write = { ehci_mem_writeb, ehci_mem_writew, ehci_mem_writel }, - }, +static const MemoryRegionOps ehci_mmio_caps_ops = { + .read = ehci_caps_read, + .valid.min_access_size = 1, + .valid.max_access_size = 4, + .impl.min_access_size = 1, + .impl.max_access_size = 1, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static const MemoryRegionOps ehci_mmio_opreg_ops = { + .read = ehci_opreg_read, + .write = ehci_opreg_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static const MemoryRegionOps ehci_mmio_port_ops = { + .read = ehci_port_read, + .write = ehci_port_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, .endianness = DEVICE_LITTLE_ENDIAN, }; @@ -2681,19 +2665,19 @@ static int usb_ehci_initfn(PCIDevice *dev) pci_conf[0x6e] = 0x00; pci_conf[0x6f] = 0xc0; // USBLEFCTLSTS - // 2.2 host controller interface version - s->mmio[0x00] = (uint8_t) OPREGBASE; - s->mmio[0x01] = 0x00; - s->mmio[0x02] = 0x00; - s->mmio[0x03] = 0x01; // HC version - s->mmio[0x04] = NB_PORTS; // Number of downstream ports - s->mmio[0x05] = 0x00; // No companion ports at present - s->mmio[0x06] = 0x00; - s->mmio[0x07] = 0x00; - s->mmio[0x08] = 0x80; // We can cache whole frame, not 64-bit capable - s->mmio[0x09] = 0x68; // EECP - s->mmio[0x0a] = 0x00; - s->mmio[0x0b] = 0x00; + /* 2.2 host controller interface version */ + s->caps[0x00] = (uint8_t) OPREGBASE; + s->caps[0x01] = 0x00; + s->caps[0x02] = 0x00; + s->caps[0x03] = 0x01; /* HC version */ + s->caps[0x04] = NB_PORTS; /* Number of downstream ports */ + s->caps[0x05] = 0x00; /* No companion ports at present */ + s->caps[0x06] = 0x00; + s->caps[0x07] = 0x00; + s->caps[0x08] = 0x80; /* We can cache whole frame, no 64-bit */ + s->caps[0x09] = 0x68; /* EECP */ + s->caps[0x0a] = 0x00; + s->caps[0x0b] = 0x00; s->irq = s->dev.irq[3]; @@ -2712,7 +2696,18 @@ static int usb_ehci_initfn(PCIDevice *dev) qemu_register_reset(ehci_reset, s); - memory_region_init_io(&s->mem, &ehci_mem_ops, s, "ehci", MMIO_SIZE); + memory_region_init(&s->mem, "ehci", MMIO_SIZE); + memory_region_init_io(&s->mem_caps, &ehci_mmio_caps_ops, s, + "capabilities", OPREGBASE); + memory_region_init_io(&s->mem_opreg, &ehci_mmio_opreg_ops, s, + "operational", PORTSC_BEGIN - OPREGBASE); + memory_region_init_io(&s->mem_ports, &ehci_mmio_port_ops, s, + "ports", PORTSC_END - PORTSC_BEGIN); + + memory_region_add_subregion(&s->mem, 0, &s->mem_caps); + memory_region_add_subregion(&s->mem, OPREGBASE, &s->mem_opreg); + memory_region_add_subregion(&s->mem, PORTSC_BEGIN, &s->mem_ports); + pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); return 0; diff --git a/trace-events b/trace-events index b25ae1c437..a58b0b71e3 100644 --- a/trace-events +++ b/trace-events @@ -243,9 +243,12 @@ usb_port_release(int bus, const char *port) "bus %d, port %s" # hw/usb/hcd-ehci.c usb_ehci_reset(void) "=== RESET ===" -usb_ehci_mmio_readl(uint32_t addr, const char *str, uint32_t val) "rd mmio %04x [%s] = %x" -usb_ehci_mmio_writel(uint32_t addr, const char *str, uint32_t val) "wr mmio %04x [%s] = %x" -usb_ehci_mmio_change(uint32_t addr, const char *str, uint32_t new, uint32_t old) "ch mmio %04x [%s] = %x (old: %x)" +usb_ehci_opreg_read(uint32_t addr, const char *str, uint32_t val) "rd mmio %04x [%s] = %x" +usb_ehci_opreg_write(uint32_t addr, const char *str, uint32_t val) "wr mmio %04x [%s] = %x" +usb_ehci_opreg_change(uint32_t addr, const char *str, uint32_t new, uint32_t old) "ch mmio %04x [%s] = %x (old: %x)" +usb_ehci_portsc_read(uint32_t addr, uint32_t port, uint32_t val) "rd mmio %04x [port %d] = %x" +usb_ehci_portsc_write(uint32_t addr, uint32_t port, uint32_t val) "wr mmio %04x [port %d] = %x" +usb_ehci_portsc_change(uint32_t addr, uint32_t port, uint32_t new, uint32_t old) "ch mmio %04x [port %d] = %x (old: %x)" usb_ehci_usbsts(const char *sts, int state) "usbsts %s %d" usb_ehci_state(const char *schedule, const char *state) "%s schedule %s" usb_ehci_qh_ptrs(void *q, uint32_t addr, uint32_t nxt, uint32_t c_qtd, uint32_t n_qtd, uint32_t a_qtd) "q %p - QH @ %08x: next %08x qtds %08x,%08x,%08x" From ffa1f2e088eb7e3d57f2fc35f21e7bdb23e592c5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 10 Sep 2012 12:44:10 +0200 Subject: [PATCH 0331/2270] ehci: Fix interrupts stopping when Interrupt Threshold Control is 8 If Interrupt Threshold Control is 8 or a multiple of 8, then s->usbsts_frindex can become exactly 0x4000, at which point (s->usbsts_frindex > s->frindex) will never become true, as s->usbsts_frindex will not be lowered / reset in this case. This patch fixes this. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index f5ba8e1469..54273d777b 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -2413,7 +2413,7 @@ static void ehci_update_frindex(EHCIState *ehci, int frames) if (ehci->frindex == 0x00004000) { ehci_raise_irq(ehci, USBSTS_FLR); ehci->frindex = 0; - if (ehci->usbsts_frindex > 0x00004000) { + if (ehci->usbsts_frindex >= 0x00004000) { ehci->usbsts_frindex -= 0x00004000; } else { ehci->usbsts_frindex = 0; From 8f74ed1e43263293301031a10e440549bab19a6e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 10 Sep 2012 12:44:11 +0200 Subject: [PATCH 0332/2270] ehci: Don't process too much frames in 1 timer tick (v2) The Linux ehci isoc scheduling code fills the entire schedule ahead of time minus 80 frames. If we make a large jump in where we are in the schedule, ie 40 frames, then the scheduler all of a sudden will only have 40 frames left to work in, causing it to fail packet submissions with error -27 (-EFBIG). Changes in v2: -Don't hardcode a maximum number of frames to process in one tick, instead: -Process a minimum number of frames to ensure we do eventually catch up -Stop (after the minimum number) when the guest has requested an irq Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 54273d777b..017a01de8e 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -139,6 +139,7 @@ #define NB_PORTS 6 // Number of downstream ports #define BUFF_SIZE 5*4096 // Max bytes to transfer per transaction #define MAX_QH 100 // Max allowable queue heads in a chain +#define MIN_FR_PER_TICK 3 // Min frames to process when catching up /* Internal periodic / asynchronous schedule state machine states */ @@ -2448,6 +2449,19 @@ static void ehci_frame_timer(void *opaque) } for (i = 0; i < frames; i++) { + /* + * If we're running behind schedule, we should not catch up + * too fast, as that will make some guests unhappy: + * 1) We must process a minimum of MIN_FR_PER_TICK frames, + * otherwise we will never catch up + * 2) Process frames until the guest has requested an irq (IOC) + */ + if (i >= MIN_FR_PER_TICK) { + ehci_commit_irq(ehci); + if ((ehci->usbsts & USBINTR_MASK) & ehci->usbintr) { + break; + } + } ehci_update_frindex(ehci, 1); ehci_advance_periodic_state(ehci); ehci->last_run_ns += FRAME_TIMER_NS; From 1f7a48de4467f31afc51169122453318efdb0f33 Mon Sep 17 00:00:00 2001 From: MORITA Kazutaka Date: Thu, 30 Aug 2012 03:39:45 +0900 Subject: [PATCH 0333/2270] sheepdog: fix savevm and loadvm This patch sets data to be sent to Sheepdog correctly and fixes savevm and loadvm operations on a Sheepdog image. Signed-off-by: MORITA Kazutaka Signed-off-by: Kevin Wolf --- block/sheepdog.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/block/sheepdog.c b/block/sheepdog.c index df4f44107b..e0753ee9e5 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1986,7 +1986,7 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data, vdi_index = pos / SD_DATA_OBJ_SIZE; offset = pos % SD_DATA_OBJ_SIZE; - data_len = MIN(remaining, SD_DATA_OBJ_SIZE); + data_len = MIN(remaining, SD_DATA_OBJ_SIZE - offset); vmstate_oid = vid_to_vmstate_oid(s->inode.vdi_id, vdi_index); @@ -2007,6 +2007,7 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data, } pos += data_len; + data += data_len; remaining -= data_len; } ret = size; From ce560dcf20c14194db5ef3b9fc1ea592d4e68109 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Tue, 31 Jul 2012 11:28:26 +1000 Subject: [PATCH 0334/2270] ATAPI: STARTSTOPUNIT only eject/load media if powercondition is 0 The START STOP UNIT command will only eject/load media if power condition is zero. If power condition is !0 then LOEJ and START will be ignored. From MMC (sbc contains similar wordings too) The Power Conditions field requests the block device to be placed in the power condition defined in Table 558. If this field has a value other than 0h then the Start and LoEj bits shall be ignored. Signed-off-by: Ronnie Sahlberg Signed-off-by: Kevin Wolf --- hw/ide/atapi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index f7f714c726..685cbaa889 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -875,6 +875,12 @@ static void cmd_start_stop_unit(IDEState *s, uint8_t* buf) int sense; bool start = buf[4] & 1; bool loej = buf[4] & 2; /* load on start, eject on !start */ + int pwrcnd = buf[4] & 0xf0; + + if (pwrcnd) { + /* eject/load only happens for power condition == 0 */ + return; + } if (loej) { if (!start && !s->tray_open && s->tray_locked) { From 1e53537fdaa4657d11f130a0f2673fcfb1956381 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Mon, 3 Sep 2012 22:13:56 +0200 Subject: [PATCH 0335/2270] ide: Fix error messages from static code analysis (no real error) Report from smatch: hw/ide/core.c:1472 ide_exec_cmd(423) error: buffer overflow 'smart_attributes' 8 <= 29 hw/ide/core.c:1474 ide_exec_cmd(425) error: buffer overflow 'smart_attributes' 8 <= 29 hw/ide/core.c:1475 ide_exec_cmd(426) error: buffer overflow 'smart_attributes' 8 <= 29 ... The upper limit of 30 was never reached because both for loops terminated when 'smart_attributes' reached end of list, so there was no real buffer overflow. Nevertheless, changing the code not only fixes the error report, but also reduces the size of smart_attributes and simplifies the for loops. Signed-off-by: Stefan Weil Signed-off-by: Kevin Wolf --- hw/ide/core.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index d65ef3d58d..d6fb69c634 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -53,8 +53,6 @@ static const int smart_attributes[][12] = { { 0x0c, 0x03, 0x00, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* airflow-temperature-celsius */ { 190, 0x03, 0x00, 0x45, 0x45, 0x1f, 0x00, 0x1f, 0x1f, 0x00, 0x00, 0x32}, - /* end of list */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; static int ide_handle_rw_error(IDEState *s, int error, int op); @@ -1468,9 +1466,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) case SMART_READ_THRESH: memset(s->io_buffer, 0, 0x200); s->io_buffer[0] = 0x01; /* smart struct version */ - for (n=0; n<30; n++) { - if (smart_attributes[n][0] == 0) - break; + for (n = 0; n < ARRAY_SIZE(smart_attributes); n++) { s->io_buffer[2+0+(n*12)] = smart_attributes[n][0]; s->io_buffer[2+1+(n*12)] = smart_attributes[n][11]; } @@ -1484,10 +1480,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) case SMART_READ_DATA: memset(s->io_buffer, 0, 0x200); s->io_buffer[0] = 0x01; /* smart struct version */ - for (n=0; n<30; n++) { - if (smart_attributes[n][0] == 0) { - break; - } + for (n = 0; n < ARRAY_SIZE(smart_attributes); n++) { int i; for(i = 0; i < 11; i++) { s->io_buffer[2+i+(n*12)] = smart_attributes[n][i]; From 45724d6d02383b0d7d4a90e05787fca7c55cb070 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 1 Sep 2012 11:06:45 +0200 Subject: [PATCH 0336/2270] block/curl: Fix wrong free statement Report from smatch: block/curl.c:546 curl_close(21) info: redundant null check on s->url calling free() The check was redundant, and free was also wrong because the memory was allocated using g_strdup. Signed-off-by: Stefan Weil Signed-off-by: Kevin Wolf --- block/curl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/block/curl.c b/block/curl.c index e7c3634d35..c1074cd2e3 100644 --- a/block/curl.c +++ b/block/curl.c @@ -542,8 +542,7 @@ static void curl_close(BlockDriverState *bs) } if (s->multi) curl_multi_cleanup(s->multi); - if (s->url) - free(s->url); + g_free(s->url); } static int64_t curl_getlength(BlockDriverState *bs) From 514f21a5d4613e495adc2e2dd48f18091454efb8 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 17 Aug 2012 15:23:24 +0200 Subject: [PATCH 0337/2270] vdi: Fix warning from clang ccc-analyzer reports these warnings: block/vdi.c:704:13: warning: Dereference of null pointer bmap[i] = VDI_UNALLOCATED; ^ block/vdi.c:702:13: warning: Dereference of null pointer bmap[i] = i; ^ Moving some code into the if block fixes this. It also avoids calling function write with 0 bytes of data. Signed-off-by: Stefan Weil Signed-off-by: Kevin Wolf --- block/vdi.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/block/vdi.c b/block/vdi.c index c4f1529db9..550cf58a39 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -628,7 +628,6 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options) VdiHeader header; size_t i; size_t bmap_size; - uint32_t *bmap; logout("\n"); @@ -693,21 +692,21 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options) result = -errno; } - bmap = NULL; if (bmap_size > 0) { - bmap = (uint32_t *)g_malloc0(bmap_size); - } - for (i = 0; i < blocks; i++) { - if (image_type == VDI_TYPE_STATIC) { - bmap[i] = i; - } else { - bmap[i] = VDI_UNALLOCATED; + uint32_t *bmap = g_malloc0(bmap_size); + for (i = 0; i < blocks; i++) { + if (image_type == VDI_TYPE_STATIC) { + bmap[i] = i; + } else { + bmap[i] = VDI_UNALLOCATED; + } } + if (write(fd, bmap, bmap_size) < 0) { + result = -errno; + } + g_free(bmap); } - if (write(fd, bmap, bmap_size) < 0) { - result = -errno; - } - g_free(bmap); + if (image_type == VDI_TYPE_STATIC) { if (ftruncate(fd, sizeof(header) + bmap_size + blocks * block_size)) { result = -errno; From 9ca111544c64b5abed2e79cf52e19a8f227b347b Mon Sep 17 00:00:00 2001 From: Pavel Hrdina Date: Thu, 9 Aug 2012 12:44:48 +0200 Subject: [PATCH 0338/2270] block: fix block tray status The tray status should change also if you eject empty block device. Signed-off-by: Pavel Hrdina Signed-off-by: Kevin Wolf --- block.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block.c b/block.c index 470bdcc1f6..c754353ac6 100644 --- a/block.c +++ b/block.c @@ -897,10 +897,10 @@ void bdrv_close(BlockDriverState *bs) bdrv_delete(bs->file); bs->file = NULL; } - - bdrv_dev_change_media_cb(bs, false); } + bdrv_dev_change_media_cb(bs, false); + /*throttling disk I/O limits*/ if (bs->io_limits_enabled) { bdrv_io_limits_disable(bs); From 2a4f4f34e6fe55f4c82507c3e7ec9b58c2e24ad4 Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Tue, 4 Sep 2012 16:08:08 -0400 Subject: [PATCH 0339/2270] ahci: properly reset PxCMD on HBA reset While testing q35, I found that windows 7 (specifically, windows 7 ultimate with sp1 x64), wouldn't install because it can't find the cdrom or disk drive. The failure message is: 'A required cd/dvd device driver is missing. If you have a driver floppy disk, CD, DVD, or USB flash drive, please insert it now.' This can also be reproduced on piix by adding an ahci controller, and observing that windows 7 does not see any devices behind it. The problem is that when windows issues a HBA reset, qemu does not reset the individual ports' PxCMD register. Windows 7 then reads back the PxCMD register and presumably assumes that the ahci controller has already been initialized. Windows then never sets up the PxIE register to enable interrupts, and thus it never gets irqs back when it sends ata device inquiry commands. This change brings qemu into ahci 1.3 specification compliance. Section 10.4.3 HBA Reset: " When GHC.HR is set to '1', GHC.AE, GHC.IE, the IS register, and all port register fields (except PxFB/PxFBU/PxCLB/PxCLBU) that are not HwInit in the HBA's register memory space are reset. " I've also re-tested Fedora 16 and 17 to verify that they continue to work with this change. Signed-off-by: Jason Baron Acked-by: Alexander Graf Signed-off-by: Kevin Wolf --- hw/ide/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 5ea3cadb01..68671bc4de 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1175,7 +1175,6 @@ void ahci_init(AHCIState *s, DeviceState *qdev, DMAContext *dma, int ports) ad->port_no = i; ad->port.dma = &ad->dma; ad->port.dma->ops = &ahci_dma_ops; - ad->port_regs.cmd = PORT_CMD_SPIN_UP | PORT_CMD_POWER_ON; } } @@ -1199,6 +1198,7 @@ void ahci_reset(AHCIState *s) pr->irq_stat = 0; pr->irq_mask = 0; pr->scr_ctl = 0; + pr->cmd = PORT_CMD_SPIN_UP | PORT_CMD_POWER_ON; ahci_reset_port(s, i); } } From c249ee682542ff3b8c310c78be67e3e713fd61d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Canet?= Date: Wed, 5 Sep 2012 13:09:01 +0200 Subject: [PATCH 0340/2270] qapi: Add SnapshotInfo and ImageInfo. Signed-off-by: Benoit Canet Signed-off-by: Kevin Wolf --- qapi-schema.json | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/qapi-schema.json b/qapi-schema.json index a9f465a9ff..1c168c5277 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -155,6 +155,70 @@ 'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm', 'running', 'save-vm', 'shutdown', 'suspended', 'watchdog' ] } +## +# @SnapshotInfo +# +# @id: unique snapshot id +# +# @name: user chosen name +# +# @vm-state-size: size of the VM state +# +# @date-sec: UTC date of the snapshot in seconds +# +# @date-nsec: fractional part in nano seconds to be used with date-sec +# +# @vm-clock-sec: VM clock relative to boot in seconds +# +# @vm-clock-nsec: fractional part in nano seconds to be used with vm-clock-sec +# +# Since: 1.3 +# +## + +{ 'type': 'SnapshotInfo', + 'data': { 'id': 'str', 'name': 'str', 'vm-state-size': 'int', + 'date-sec': 'int', 'date-nsec': 'int', + 'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } } + +## +# @ImageInfo: +# +# Information about a QEMU image file +# +# @filename: name of the image file +# +# @format: format of the image file +# +# @virtual-size: maximum capacity in bytes of the image +# +# @actual-size: #optional actual size on disk in bytes of the image +# +# @dirty-flag: #optional true if image is not cleanly closed +# +# @cluster-size: #optional size of a cluster in bytes +# +# @encrypted: #optional true if the image is encrypted +# +# @backing-filename: #optional name of the backing file +# +# @full-backing-filename: #optional full path of the backing file +# +# @backing-filename-format: #optional the format of the backing file +# +# @snapshots: #optional list of VM snapshots +# +# Since: 1.3 +# +## + +{ 'type': 'ImageInfo', + 'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool', + '*actual-size': 'int', 'virtual-size': 'int', + '*cluster-size': 'int', '*encrypted': 'bool', + '*backing-filename': 'str', '*full-backing-filename': 'str', + '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'] } } + ## # @StatusInfo: # From c054b3fd78f28b12f4d066583fc0ade017752479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Canet?= Date: Wed, 5 Sep 2012 13:09:02 +0200 Subject: [PATCH 0341/2270] qemu-img: Add json output option to the info command. This option --output=[human|json] make qemu-img info output on human or JSON representation at the choice of the user. example: { "snapshots": [ { "vm-clock-nsec": 637102488, "name": "vm-20120821145509", "date-sec": 1345553709, "date-nsec": 220289000, "vm-clock-sec": 20, "id": "1", "vm-state-size": 96522745 }, { "vm-clock-nsec": 28210866, "name": "vm-20120821154059", "date-sec": 1345556459, "date-nsec": 171392000, "vm-clock-sec": 46, "id": "2", "vm-state-size": 101208714 } ], "virtual-size": 1073741824, "filename": "snap.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": 985587712, "dirty-flag": false } Signed-off-by: Benoit Canet Signed-off-by: Kevin Wolf --- Makefile | 3 +- qemu-img-cmds.hx | 4 +- qemu-img.c | 236 ++++++++++++++++++++++++++++++++++++++--------- qemu-img.texi | 5 +- 4 files changed, 199 insertions(+), 49 deletions(-) diff --git a/Makefile b/Makefile index 1cd5bc80d5..971e92fd79 100644 --- a/Makefile +++ b/Makefile @@ -157,7 +157,8 @@ tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \ iohandler.o cutils.o iov.o async.o tools-obj-$(CONFIG_POSIX) += compatfd.o -qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y) +qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y) $(qapi-obj-y) \ + qapi-visit.o qapi-types.o qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y) qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y) diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx index 39419a0314..0ef82e9ac7 100644 --- a/qemu-img-cmds.hx +++ b/qemu-img-cmds.hx @@ -34,9 +34,9 @@ STEXI ETEXI DEF("info", img_info, - "info [-f fmt] filename") + "info [-f fmt] [--output=ofmt] filename") STEXI -@item info [-f @var{fmt}] @var{filename} +@item info [-f @var{fmt}] [--output=@var{ofmt}] @var{filename} ETEXI DEF("snapshot", img_snapshot, diff --git a/qemu-img.c b/qemu-img.c index b41e670a61..30e33c7b6c 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -21,12 +21,16 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#include "qapi-visit.h" +#include "qapi/qmp-output-visitor.h" +#include "qjson.h" #include "qemu-common.h" #include "qemu-option.h" #include "qemu-error.h" #include "osdep.h" #include "sysemu.h" #include "block_int.h" +#include #include #ifdef _WIN32 @@ -84,6 +88,7 @@ static void help(void) " '-p' show progress of command (only certain commands)\n" " '-S' indicates the consecutive number of bytes that must contain only zeros\n" " for qemu-img to create a sparse image during conversion\n" + " '--output' takes the format in which the output must be done (human or json)\n" "\n" "Parameters to check subcommand:\n" " '-r' tries to repair any inconsistencies that are found during the check.\n" @@ -1102,21 +1107,174 @@ static void dump_snapshots(BlockDriverState *bs) g_free(sn_tab); } -static int img_info(int argc, char **argv) +static void collect_snapshots(BlockDriverState *bs , ImageInfo *info) +{ + int i, sn_count; + QEMUSnapshotInfo *sn_tab = NULL; + SnapshotInfoList *info_list, *cur_item = NULL; + sn_count = bdrv_snapshot_list(bs, &sn_tab); + + for (i = 0; i < sn_count; i++) { + info->has_snapshots = true; + info_list = g_new0(SnapshotInfoList, 1); + + info_list->value = g_new0(SnapshotInfo, 1); + info_list->value->id = g_strdup(sn_tab[i].id_str); + info_list->value->name = g_strdup(sn_tab[i].name); + info_list->value->vm_state_size = sn_tab[i].vm_state_size; + info_list->value->date_sec = sn_tab[i].date_sec; + info_list->value->date_nsec = sn_tab[i].date_nsec; + info_list->value->vm_clock_sec = sn_tab[i].vm_clock_nsec / 1000000000; + info_list->value->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000; + + /* XXX: waiting for the qapi to support qemu-queue.h types */ + if (!cur_item) { + info->snapshots = cur_item = info_list; + } else { + cur_item->next = info_list; + cur_item = info_list; + } + + } + + g_free(sn_tab); +} + +static void dump_json_image_info(ImageInfo *info) +{ + Error *errp = NULL; + QString *str; + QmpOutputVisitor *ov = qmp_output_visitor_new(); + QObject *obj; + visit_type_ImageInfo(qmp_output_get_visitor(ov), + &info, NULL, &errp); + obj = qmp_output_get_qobject(ov); + str = qobject_to_json_pretty(obj); + assert(str != NULL); + printf("%s\n", qstring_get_str(str)); + qobject_decref(obj); + qmp_output_visitor_cleanup(ov); + QDECREF(str); +} + +static void collect_image_info(BlockDriverState *bs, + ImageInfo *info, + const char *filename, + const char *fmt) { - int c; - const char *filename, *fmt; - BlockDriverState *bs; - char size_buf[128], dsize_buf[128]; uint64_t total_sectors; - int64_t allocated_size; char backing_filename[1024]; char backing_filename2[1024]; BlockDriverInfo bdi; + bdrv_get_geometry(bs, &total_sectors); + + info->filename = g_strdup(filename); + info->format = g_strdup(bdrv_get_format_name(bs)); + info->virtual_size = total_sectors * 512; + info->actual_size = bdrv_get_allocated_file_size(bs); + info->has_actual_size = info->actual_size >= 0; + if (bdrv_is_encrypted(bs)) { + info->encrypted = true; + info->has_encrypted = true; + } + if (bdrv_get_info(bs, &bdi) >= 0) { + if (bdi.cluster_size != 0) { + info->cluster_size = bdi.cluster_size; + info->has_cluster_size = true; + } + info->dirty_flag = bdi.is_dirty; + info->has_dirty_flag = true; + } + bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename)); + if (backing_filename[0] != '\0') { + info->backing_filename = g_strdup(backing_filename); + info->has_backing_filename = true; + bdrv_get_full_backing_filename(bs, backing_filename2, + sizeof(backing_filename2)); + + if (strcmp(backing_filename, backing_filename2) != 0) { + info->full_backing_filename = + g_strdup(backing_filename2); + info->has_full_backing_filename = true; + } + + if (bs->backing_format[0]) { + info->backing_filename_format = g_strdup(bs->backing_format); + info->has_backing_filename_format = true; + } + } +} + +static void dump_human_image_info(ImageInfo *info) +{ + char size_buf[128], dsize_buf[128]; + if (!info->has_actual_size) { + snprintf(dsize_buf, sizeof(dsize_buf), "unavailable"); + } else { + get_human_readable_size(dsize_buf, sizeof(dsize_buf), + info->actual_size); + } + get_human_readable_size(size_buf, sizeof(size_buf), info->virtual_size); + printf("image: %s\n" + "file format: %s\n" + "virtual size: %s (%" PRId64 " bytes)\n" + "disk size: %s\n", + info->filename, info->format, size_buf, + info->virtual_size, + dsize_buf); + + if (info->has_encrypted && info->encrypted) { + printf("encrypted: yes\n"); + } + + if (info->has_cluster_size) { + printf("cluster_size: %" PRId64 "\n", info->cluster_size); + } + + if (info->has_dirty_flag && info->dirty_flag) { + printf("cleanly shut down: no\n"); + } + + if (info->has_backing_filename) { + printf("backing file: %s", info->backing_filename); + if (info->has_full_backing_filename) { + printf(" (actual path: %s)", info->full_backing_filename); + } + putchar('\n'); + if (info->has_backing_filename_format) { + printf("backing file format: %s\n", info->backing_filename_format); + } + } +} + +enum {OPTION_OUTPUT = 256}; + +typedef enum OutputFormat { + OFORMAT_JSON, + OFORMAT_HUMAN, +} OutputFormat; + +static int img_info(int argc, char **argv) +{ + int c; + OutputFormat output_format = OFORMAT_HUMAN; + const char *filename, *fmt, *output; + BlockDriverState *bs; + ImageInfo *info; + fmt = NULL; + output = NULL; for(;;) { - c = getopt(argc, argv, "f:h"); + int option_index = 0; + static const struct option long_options[] = { + {"help", no_argument, 0, 'h'}, + {"format", required_argument, 0, 'f'}, + {"output", required_argument, 0, OPTION_OUTPUT}, + {0, 0, 0, 0} + }; + c = getopt_long(argc, argv, "f:h", + long_options, &option_index); if (c == -1) { break; } @@ -1128,6 +1286,9 @@ static int img_info(int argc, char **argv) case 'f': fmt = optarg; break; + case OPTION_OUTPUT: + output = optarg; + break; } } if (optind >= argc) { @@ -1135,48 +1296,35 @@ static int img_info(int argc, char **argv) } filename = argv[optind++]; + if (output && !strcmp(output, "json")) { + output_format = OFORMAT_JSON; + } else if (output && !strcmp(output, "human")) { + output_format = OFORMAT_HUMAN; + } else if (output) { + error_report("--output must be used with human or json as argument."); + return 1; + } + bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING); if (!bs) { return 1; } - bdrv_get_geometry(bs, &total_sectors); - get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512); - allocated_size = bdrv_get_allocated_file_size(bs); - if (allocated_size < 0) { - snprintf(dsize_buf, sizeof(dsize_buf), "unavailable"); - } else { - get_human_readable_size(dsize_buf, sizeof(dsize_buf), - allocated_size); + + info = g_new0(ImageInfo, 1); + collect_image_info(bs, info, filename, fmt); + + switch (output_format) { + case OFORMAT_HUMAN: + dump_human_image_info(info); + dump_snapshots(bs); + break; + case OFORMAT_JSON: + collect_snapshots(bs, info); + dump_json_image_info(info); + break; } - printf("image: %s\n" - "file format: %s\n" - "virtual size: %s (%" PRId64 " bytes)\n" - "disk size: %s\n", - filename, bdrv_get_format_name(bs), size_buf, - (total_sectors * 512), - dsize_buf); - if (bdrv_is_encrypted(bs)) { - printf("encrypted: yes\n"); - } - if (bdrv_get_info(bs, &bdi) >= 0) { - if (bdi.cluster_size != 0) { - printf("cluster_size: %d\n", bdi.cluster_size); - } - if (bdi.is_dirty) { - printf("cleanly shut down: no\n"); - } - } - bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename)); - if (backing_filename[0] != '\0') { - bdrv_get_full_backing_filename(bs, backing_filename2, - sizeof(backing_filename2)); - printf("backing file: %s", backing_filename); - if (strcmp(backing_filename, backing_filename2) != 0) { - printf(" (actual path: %s)", backing_filename2); - } - putchar('\n'); - } - dump_snapshots(bs); + + qapi_free_ImageInfo(info); bdrv_delete(bs); return 0; } diff --git a/qemu-img.texi b/qemu-img.texi index 6b42e35fe7..ca8589116f 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -129,12 +129,13 @@ created as a copy on write image of the specified base image; the @var{backing_file} should have the same content as the input's base image, however the path, image format, etc may differ. -@item info [-f @var{fmt}] @var{filename} +@item info [-f @var{fmt}] [--output=@var{ofmt}] @var{filename} Give information about the disk image @var{filename}. Use it in particular to know the size reserved on disk which can be different from the displayed size. If VM snapshots are stored in the disk image, -they are displayed too. +they are displayed too. The command can output in the format @var{ofmt} +which is either @code{human} or @code{json}. @item snapshot [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot} ] @var{filename} From f0536bb848ad6eb2709a7dc675f261bd160c751b Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Mon, 10 Sep 2012 12:11:31 +0100 Subject: [PATCH 0342/2270] Don't require encryption password for 'qemu-img info' command The encryption password is only required if I/O is going to be performed on a disk image. The 'qemu-img info' command merely reports metadata, so it should not ask for a decryption password Signed-off-by: Daniel P. Berrange Signed-off-by: Kevin Wolf --- qemu-img.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index 30e33c7b6c..a374d6736c 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -226,7 +226,8 @@ static int print_block_option_help(const char *filename, const char *fmt) static BlockDriverState *bdrv_new_open(const char *filename, const char *fmt, - int flags) + int flags, + bool require_io) { BlockDriverState *bs; BlockDriver *drv; @@ -251,7 +252,7 @@ static BlockDriverState *bdrv_new_open(const char *filename, goto fail; } - if (bdrv_is_encrypted(bs)) { + if (bdrv_is_encrypted(bs) && require_io) { printf("Disk image '%s' is encrypted.\n", filename); if (read_password(password, sizeof(password)) < 0) { error_report("No password given"); @@ -418,7 +419,7 @@ static int img_check(int argc, char **argv) } filename = argv[optind++]; - bs = bdrv_new_open(filename, fmt, flags); + bs = bdrv_new_open(filename, fmt, flags, true); if (!bs) { return 1; } @@ -525,7 +526,7 @@ static int img_commit(int argc, char **argv) return -1; } - bs = bdrv_new_open(filename, fmt, flags); + bs = bdrv_new_open(filename, fmt, flags, true); if (!bs) { return 1; } @@ -767,7 +768,7 @@ static int img_convert(int argc, char **argv) total_sectors = 0; for (bs_i = 0; bs_i < bs_n; bs_i++) { - bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS); + bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS, true); if (!bs[bs_i]) { error_report("Could not open '%s'", argv[optind + bs_i]); ret = -1; @@ -886,7 +887,7 @@ static int img_convert(int argc, char **argv) return -1; } - out_bs = bdrv_new_open(out_filename, out_fmt, flags); + out_bs = bdrv_new_open(out_filename, out_fmt, flags, true); if (!out_bs) { ret = -1; goto out; @@ -1305,7 +1306,7 @@ static int img_info(int argc, char **argv) return 1; } - bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING); + bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING, false); if (!bs) { return 1; } @@ -1396,7 +1397,7 @@ static int img_snapshot(int argc, char **argv) filename = argv[optind++]; /* Open the image */ - bs = bdrv_new_open(filename, NULL, bdrv_oflags); + bs = bdrv_new_open(filename, NULL, bdrv_oflags, true); if (!bs) { return 1; } @@ -1514,7 +1515,7 @@ static int img_rebase(int argc, char **argv) * Ignore the old backing file for unsafe rebase in case we want to correct * the reference to a renamed or moved backing file. */ - bs = bdrv_new_open(filename, fmt, flags); + bs = bdrv_new_open(filename, fmt, flags, true); if (!bs) { return 1; } @@ -1787,7 +1788,7 @@ static int img_resize(int argc, char **argv) n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0); qemu_opts_del(param); - bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR); + bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, true); if (!bs) { ret = -1; goto out; From fe235a06e1e008dedd2ac3cc0a3a655169ce9b33 Mon Sep 17 00:00:00 2001 From: Dunrong Huang Date: Wed, 5 Sep 2012 21:26:22 +0800 Subject: [PATCH 0343/2270] block: Don't forget to delete temporary file The caller would not delete temporary file after failed get_tmp_filename(). Signed-off-by: Dunrong Huang Signed-off-by: Kevin Wolf --- block.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/block.c b/block.c index c754353ac6..e78039bd5a 100644 --- a/block.c +++ b/block.c @@ -433,7 +433,11 @@ int get_tmp_filename(char *filename, int size) return -EOVERFLOW; } fd = mkstemp(filename); - if (fd < 0 || close(fd)) { + if (fd < 0) { + return -errno; + } + if (close(fd) != 0) { + unlink(filename); return -errno; } return 0; From 917ae08ca1565aab2d10c8b6269cd905d6c5c05b Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Wed, 12 Sep 2012 16:13:26 +0300 Subject: [PATCH 0344/2270] hw/qxl: tracing fixes Add two new trace events: qxl_send_events(int qid, uint32_t events) "%d %d" qxl_set_guest_bug(int qid) "%d" Change qxl_io_unexpected_vga_mode parameters to be equivalent to those of qxl_io_write for easier grouping under a single systemtap probe. Change d to qxl in one place. Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 8 +++++--- trace-events | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 12597e75de..8c46766b8e 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -141,6 +141,7 @@ static void qxl_ring_set_dirty(PCIQXLDevice *qxl); void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) { + trace_qxl_set_guest_bug(qxl->id); qxl_send_events(qxl, QXL_INTERRUPT_ERROR); qxl->guest_bug = 1; if (qxl->guestdebug) { @@ -1408,7 +1409,7 @@ static void ioport_write(void *opaque, target_phys_addr_t addr, break; } trace_qxl_io_unexpected_vga_mode(d->id, - io_port, io_port_to_string(io_port)); + addr, val, io_port_to_string(io_port)); /* be nice to buggy guest drivers */ if (io_port >= QXL_IO_UPDATE_AREA_ASYNC && io_port < QXL_IO_RANGE_SIZE) { @@ -1607,9 +1608,9 @@ cancel_async: static uint64_t ioport_read(void *opaque, target_phys_addr_t addr, unsigned size) { - PCIQXLDevice *d = opaque; + PCIQXLDevice *qxl = opaque; - trace_qxl_io_read_unexpected(d->id); + trace_qxl_io_read_unexpected(qxl->id); return 0xff; } @@ -1639,6 +1640,7 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events) uint32_t old_pending; uint32_t le_events = cpu_to_le32(events); + trace_qxl_send_events(d->id, events); assert(qemu_spice_display_is_running(&d->ssd)); old_pending = __sync_fetch_and_or(&d->ram->int_pending, le_events); if ((old_pending & le_events) == le_events) { diff --git a/trace-events b/trace-events index b25ae1c437..6169c298f4 100644 --- a/trace-events +++ b/trace-events @@ -933,7 +933,7 @@ qxl_interface_update_area_complete_overflow(int qid, int max) "%d max=%d" qxl_interface_update_area_complete_schedule_bh(int qid, uint32_t num_dirty) "%d #dirty=%d" qxl_io_destroy_primary_ignored(int qid, const char *mode) "%d %s" qxl_io_read_unexpected(int qid) "%d" -qxl_io_unexpected_vga_mode(int qid, uint32_t io_port, const char *desc) "%d 0x%x (%s)" +qxl_io_unexpected_vga_mode(int qid, uint64_t addr, uint64_t val, const char *desc) "%d 0x%"PRIx64"=%"PRIu64" (%s)" qxl_io_write(int qid, const char *mode, uint64_t addr, uint64_t val, unsigned size, int async) "%d %s addr=%"PRIu64 " val=%"PRIu64" size=%u async=%d" qxl_memslot_add_guest(int qid, uint32_t slot_id, uint64_t guest_start, uint64_t guest_end) "%d %u: guest phys 0x%"PRIx64 " - 0x%" PRIx64 qxl_post_load(int qid, const char *mode) "%d %s" @@ -964,7 +964,7 @@ qxl_spice_destroy_surfaces(int qid, int async) "%d async=%d" qxl_spice_destroy_surface_wait_complete(int qid, uint32_t id) "%d sid=%d" qxl_spice_destroy_surface_wait(int qid, uint32_t id, int async) "%d sid=%d async=%d" qxl_spice_flush_surfaces_async(int qid, uint32_t surface_count, uint32_t num_free_res) "%d s#=%d, res#=%d" -qxl_spice_monitors_config(int id) "%d" +qxl_spice_monitors_config(int qid) "%d" qxl_spice_loadvm_commands(int qid, void *ext, uint32_t count) "%d ext=%p count=%d" qxl_spice_oom(int qid) "%d" qxl_spice_reset_cursor(int qid) "%d" @@ -973,6 +973,8 @@ qxl_spice_reset_memslots(int qid) "%d" qxl_spice_update_area(int qid, uint32_t surface_id, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "%d sid=%d [%d,%d,%d,%d]" qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dirty_region) "%d #d=%d clear=%d" qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d offset=%d size=%d" +qxl_send_events(int qid, uint32_t events) "%d %d" +qxl_set_guest_bug(int qid) "%d" # hw/qxl-render.c qxl_render_blit_guest_primary_initialized(void) "" From 1a1bc08568b3fc3d893cab774806cdcedfe1b60b Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Wed, 12 Sep 2012 16:13:27 +0300 Subject: [PATCH 0345/2270] qxl: add trace-event for QXL_IO_LOG Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 1 + trace-events | 1 + 2 files changed, 2 insertions(+) diff --git a/hw/qxl.c b/hw/qxl.c index 8c46766b8e..5709e0d957 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1515,6 +1515,7 @@ async_common: qxl_set_mode(d, val, 0); break; case QXL_IO_LOG: + trace_qxl_io_log(d->id, d->ram->log_buf); if (d->guestdebug) { fprintf(stderr, "qxl/guest-%d: %" PRId64 ": %s", d->id, qemu_get_clock_ns(vm_clock), d->ram->log_buf); diff --git a/trace-events b/trace-events index 6169c298f4..cd638f5ae7 100644 --- a/trace-events +++ b/trace-events @@ -932,6 +932,7 @@ qxl_interface_update_area_complete_rest(int qid, uint32_t num_updated_rects) "%d qxl_interface_update_area_complete_overflow(int qid, int max) "%d max=%d" qxl_interface_update_area_complete_schedule_bh(int qid, uint32_t num_dirty) "%d #dirty=%d" qxl_io_destroy_primary_ignored(int qid, const char *mode) "%d %s" +qxl_io_log(int qid, const uint8_t *str) "%d %s" qxl_io_read_unexpected(int qid) "%d" qxl_io_unexpected_vga_mode(int qid, uint64_t addr, uint64_t val, const char *desc) "%d 0x%"PRIx64"=%"PRIu64" (%s)" qxl_io_write(int qid, const char *mode, uint64_t addr, uint64_t val, unsigned size, int async) "%d %s addr=%"PRIu64 " val=%"PRIu64" size=%u async=%d" From a639ab0482952c13c896f3e555d717caf98f138b Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Wed, 12 Sep 2012 16:13:28 +0300 Subject: [PATCH 0346/2270] hw/qxl: support client monitor configuration via device Until now we used only the agent to change the monitor count and each monitor resolution. This patch introduces the qemu part of using the device as the mediator instead of the agent via virtio-serial. Spice (>=0.11.5) calls the new QXLInterface::client_monitors_config, which returns wether the interrupt is enabled, and if so and given a non NULL monitors config will generate an interrupt QXL_INTERRUPT_CLIENT_MONITORS_CONFIG with crc checksum for the guest to verify a second call hasn't interfered. The maximal number of monitors is limited on the QXLRom to 64. Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- configure | 7 +++++ hw/qxl.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ trace-events | 6 +++- 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 7656c32b24..c75c51b163 100755 --- a/configure +++ b/configure @@ -2709,6 +2709,9 @@ EOF if $pkg_config --atleast-version=0.12.0 spice-protocol >/dev/null 2>&1; then spice_qxl_io_monitors_config_async="yes" fi + if $pkg_config --atleast-version=0.12.2 spice-protocol > /dev/null 2>&1; then + spice_qxl_client_monitors_config="yes" + fi else if test "$spice" = "yes" ; then feature_not_found "spice" @@ -3456,6 +3459,10 @@ if test "$spice_qxl_io_monitors_config_async" = "yes" ; then echo "CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC=y" >> $config_host_mak fi +if test "$spice_qxl_client_monitors_config" = "yes" ; then + echo "CONFIG_QXL_CLIENT_MONITORS_CONFIG=y" >> $config_host_mak +fi + if test "$smartcard" = "yes" ; then echo "CONFIG_SMARTCARD=y" >> $config_host_mak fi diff --git a/hw/qxl.c b/hw/qxl.c index 5709e0d957..c464408421 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -18,6 +18,8 @@ * along with this program; if not, see . */ +#include + #include "qemu-common.h" #include "qemu-timer.h" #include "qemu-queue.h" @@ -971,6 +973,79 @@ static void interface_set_client_capabilities(QXLInstance *sin, #endif +#if defined(CONFIG_QXL_CLIENT_MONITORS_CONFIG) \ + && SPICE_SERVER_VERSION >= 0x000b05 + +static uint32_t qxl_crc32(const uint8_t *p, unsigned len) +{ + /* + * zlib xors the seed with 0xffffffff, and xors the result + * again with 0xffffffff; Both are not done with linux's crc32, + * which we want to be compatible with, so undo that. + */ + return crc32(0xffffffff, p, len) ^ 0xffffffff; +} + +/* called from main context only */ +static int interface_client_monitors_config(QXLInstance *sin, + VDAgentMonitorsConfig *monitors_config) +{ + PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); + QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar); + int i; + + /* + * Older windows drivers set int_mask to 0 when their ISR is called, + * then later set it to ~0. So it doesn't relate to the actual interrupts + * handled. However, they are old, so clearly they don't support this + * interrupt + */ + if (qxl->ram->int_mask == 0 || qxl->ram->int_mask == ~0 || + !(qxl->ram->int_mask & QXL_INTERRUPT_CLIENT_MONITORS_CONFIG)) { + trace_qxl_client_monitors_config_unsupported_by_guest(qxl->id, + qxl->ram->int_mask, + monitors_config); + return 0; + } + if (!monitors_config) { + return 1; + } + memset(&rom->client_monitors_config, 0, + sizeof(rom->client_monitors_config)); + rom->client_monitors_config.count = monitors_config->num_of_monitors; + /* monitors_config->flags ignored */ + if (rom->client_monitors_config.count >= + ARRAY_SIZE(rom->client_monitors_config.heads)) { + trace_qxl_client_monitors_config_capped(qxl->id, + monitors_config->num_of_monitors, + ARRAY_SIZE(rom->client_monitors_config.heads)); + rom->client_monitors_config.count = + ARRAY_SIZE(rom->client_monitors_config.heads); + } + for (i = 0 ; i < rom->client_monitors_config.count ; ++i) { + VDAgentMonConfig *monitor = &monitors_config->monitors[i]; + QXLURect *rect = &rom->client_monitors_config.heads[i]; + /* monitor->depth ignored */ + rect->left = monitor->x; + rect->top = monitor->y; + rect->right = monitor->x + monitor->width; + rect->bottom = monitor->y + monitor->height; + } + rom->client_monitors_config_crc = qxl_crc32( + (const uint8_t *)&rom->client_monitors_config, + sizeof(rom->client_monitors_config)); + trace_qxl_client_monitors_config_crc(qxl->id, + sizeof(rom->client_monitors_config), + rom->client_monitors_config_crc); + + trace_qxl_interrupt_client_monitors_config(qxl->id, + rom->client_monitors_config.count, + rom->client_monitors_config.heads); + qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG); + return 1; +} +#endif + static const QXLInterface qxl_interface = { .base.type = SPICE_INTERFACE_QXL, .base.description = "qxl gpu", @@ -995,6 +1070,10 @@ static const QXLInterface qxl_interface = { #if SPICE_SERVER_VERSION >= 0x000b04 .set_client_capabilities = interface_set_client_capabilities, #endif +#if SPICE_SERVER_VERSION >= 0x000b05 && \ + defined(CONFIG_QXL_CLIENT_MONITORS_CONFIG) + .client_monitors_config = interface_client_monitors_config, +#endif }; static void qxl_enter_vga_mode(PCIQXLDevice *d) diff --git a/trace-events b/trace-events index cd638f5ae7..b48fe2d15a 100644 --- a/trace-events +++ b/trace-events @@ -932,7 +932,7 @@ qxl_interface_update_area_complete_rest(int qid, uint32_t num_updated_rects) "%d qxl_interface_update_area_complete_overflow(int qid, int max) "%d max=%d" qxl_interface_update_area_complete_schedule_bh(int qid, uint32_t num_dirty) "%d #dirty=%d" qxl_io_destroy_primary_ignored(int qid, const char *mode) "%d %s" -qxl_io_log(int qid, const uint8_t *str) "%d %s" +qxl_io_log(int qid, const uint8_t *log_buf) "%d %s" qxl_io_read_unexpected(int qid) "%d" qxl_io_unexpected_vga_mode(int qid, uint64_t addr, uint64_t val, const char *desc) "%d 0x%"PRIx64"=%"PRIu64" (%s)" qxl_io_write(int qid, const char *mode, uint64_t addr, uint64_t val, unsigned size, int async) "%d %s addr=%"PRIu64 " val=%"PRIu64" size=%u async=%d" @@ -976,6 +976,10 @@ qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dir qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d offset=%d size=%d" qxl_send_events(int qid, uint32_t events) "%d %d" qxl_set_guest_bug(int qid) "%d" +qxl_interrupt_client_monitors_config(int qid, int num_heads, void *heads) "%d %d %p" +qxl_client_monitors_config_unsupported_by_guest(int qid, uint32_t int_mask, void *client_monitors_config) "%d %X %p" +qxl_client_monitors_config_capped(int qid, int requested, int limit) "%d %d %d" +qxl_client_monitors_config_crc(int qid, unsigned size, uint32_t crc32) "%d %u %u" # hw/qxl-render.c qxl_render_blit_guest_primary_initialized(void) "" From 56ab2ad177dc43d474dc0a0bd84e81ef00f31e11 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 11 Sep 2012 20:57:58 +0200 Subject: [PATCH 0347/2270] configure: usbredir fixes usbredir is only used by system emulation, so add the libraries to libs_softmmu instead of LIBS. Cc: Michael Tokarev Cc: Gerd Hoffmann Signed-off-by: Aurelien Jarno Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 7656c32b24..e42c812529 100755 --- a/configure +++ b/configure @@ -2763,7 +2763,7 @@ if test "$usb_redir" != "no" ; then usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null) usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null) QEMU_CFLAGS="$QEMU_CFLAGS $usb_redir_cflags" - LIBS="$LIBS $usb_redir_libs" + libs_softmmu="$libs_softmmu $usb_redir_libs" else if test "$usb_redir" = "yes"; then feature_not_found "usb-redir" From 8f5457eb04140714eaf57a99bc08dc661d83fa87 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 12 Sep 2012 15:08:32 +0200 Subject: [PATCH 0348/2270] ehci: Don't set seen to 0 when removing unseen queue-heads When removing unseen queue-heads from the async queue list, we should not set the seen flag to 0, as this may cause them to be removed by ehci_queues_rip_unused() during the next call to ehci_advance_async_state() if the timer is late or running at a low frequency. Note: 1) This *may* have caused the instant unlink / relinks described in commit 9bc3a3a216e2689bfcdd36c3e079333bbdbf3ba0 2) Rather then putting more if-s inside ehci_queues_rip_unused, this patch instead introduces a new ehci_queues_rip_unseen function. 3) This patch also makes it save to call ehci_queues_rip_unseen() multiple times, which gets used in the folluw up patch titled: "ehci: Walk async schedule before and after migration" Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 017a01de8e..bc8646081e 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -848,10 +848,10 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr, return NULL; } -static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush) +static void ehci_queues_rip_unused(EHCIState *ehci, int async) { EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; - const char *warn = (async && !flush) ? "guest unlinked busy QH" : NULL; + const char *warn = async ? "guest unlinked busy QH" : NULL; uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4; EHCIQueue *q, *tmp; @@ -861,13 +861,25 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush) q->ts = ehci->last_run_ns; continue; } - if (!flush && ehci->last_run_ns < q->ts + maxage) { + if (ehci->last_run_ns < q->ts + maxage) { continue; } ehci_free_queue(q, warn); } } +static void ehci_queues_rip_unseen(EHCIState *ehci, int async) +{ + EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; + EHCIQueue *q, *tmp; + + QTAILQ_FOREACH_SAFE(q, head, next, tmp) { + if (!q->seen) { + ehci_free_queue(q, NULL); + } + } +} + static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async) { EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; @@ -1700,7 +1712,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci, int async) ehci_set_usbsts(ehci, USBSTS_REC); } - ehci_queues_rip_unused(ehci, async, 0); + ehci_queues_rip_unused(ehci, async); /* Find the head of the list (4.9.1.1) */ for(i = 0; i < MAX_QH; i++) { @@ -2332,7 +2344,7 @@ static void ehci_advance_async_state(EHCIState *ehci) */ if (ehci->usbcmd & USBCMD_IAAD) { /* Remove all unseen qhs from the async qhs queue */ - ehci_queues_rip_unused(ehci, async, 1); + ehci_queues_rip_unseen(ehci, async); trace_usb_ehci_doorbell_ack(); ehci->usbcmd &= ~USBCMD_IAAD; ehci_raise_irq(ehci, USBSTS_IAA); @@ -2385,7 +2397,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci) ehci_set_fetch_addr(ehci, async,entry); ehci_set_state(ehci, async, EST_FETCHENTRY); ehci_advance_state(ehci, async); - ehci_queues_rip_unused(ehci, async, 0); + ehci_queues_rip_unused(ehci, async); break; default: From ceab6f96454fe6589d1b09ce64403c041d79f9d9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 12 Sep 2012 15:08:33 +0200 Subject: [PATCH 0349/2270] ehci: Walk async schedule before and after migration Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index bc8646081e..6a5da8413f 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -34,6 +34,7 @@ #include "monitor.h" #include "trace.h" #include "dma.h" +#include "sysemu.h" #define EHCI_DEBUG 0 @@ -2572,6 +2573,32 @@ static int usb_ehci_post_load(void *opaque, int version_id) return 0; } +static void usb_ehci_vm_state_change(void *opaque, int running, RunState state) +{ + EHCIState *ehci = opaque; + + /* + * We don't migrate the EHCIQueue-s, instead we rebuild them for the + * schedule in guest memory. We must do the rebuilt ASAP, so that + * USB-devices which have async handled packages have a packet in the + * ep queue to match the completion with. + */ + if (state == RUN_STATE_RUNNING) { + ehci_advance_async_state(ehci); + } + + /* + * The schedule rebuilt from guest memory could cause the migration dest + * to miss a QH unlink, and fail to cancel packets, since the unlinked QH + * will never have existed on the destination. Therefor we must flush the + * async schedule on savevm to catch any not yet noticed unlinks. + */ + if (state == RUN_STATE_SAVE_VM) { + ehci_advance_async_state(ehci); + ehci_queues_rip_unseen(ehci, 1); + } +} + static const VMStateDescription vmstate_ehci = { .name = "ehci", .version_id = 2, @@ -2721,6 +2748,7 @@ static int usb_ehci_initfn(PCIDevice *dev) usb_packet_init(&s->ipacket); qemu_register_reset(ehci_reset, s); + qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s); memory_region_init(&s->mem, "ehci", MMIO_SIZE); memory_region_init_io(&s->mem_caps, &ehci_mmio_caps_ops, s, From 8e60452a954978f2f52026aa5f5cfd948e4e2be0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 12 Sep 2012 15:08:34 +0200 Subject: [PATCH 0350/2270] usb-redir: Change cancelled packet code into a generic packet-id queue Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 102 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 31 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 5301a69c4f..603262a45c 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -43,7 +43,6 @@ #define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f)) #define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f)) -typedef struct Cancelled Cancelled; typedef struct USBRedirDevice USBRedirDevice; /* Struct to hold buffered packets (iso or int input packets) */ @@ -69,6 +68,18 @@ struct endp_data { int bufpq_target_size; }; +struct PacketIdQueueEntry { + uint64_t id; + QTAILQ_ENTRY(PacketIdQueueEntry)next; +}; + +struct PacketIdQueue { + USBRedirDevice *dev; + const char *name; + QTAILQ_HEAD(, PacketIdQueueEntry) head; + int size; +}; + struct USBRedirDevice { USBDevice dev; /* Properties */ @@ -86,7 +97,7 @@ struct USBRedirDevice { int64_t next_attach_time; struct usbredirparser *parser; struct endp_data endpoint[MAX_ENDPOINTS]; - QTAILQ_HEAD(, Cancelled) cancelled; + struct PacketIdQueue cancelled; /* Data for device filtering */ struct usb_redir_device_connect_header device_info; struct usb_redir_interface_info_header interface_info; @@ -94,11 +105,6 @@ struct USBRedirDevice { int filter_rules_count; }; -struct Cancelled { - uint64_t id; - QTAILQ_ENTRY(Cancelled)next; -}; - static void usbredir_hello(void *priv, struct usb_redir_hello_header *h); static void usbredir_device_connect(void *priv, struct usb_redir_device_connect_header *device_connect); @@ -239,37 +245,75 @@ static int usbredir_write(void *priv, uint8_t *data, int count) * Cancelled and buffered packets helpers */ +static void packet_id_queue_init(struct PacketIdQueue *q, + USBRedirDevice *dev, const char *name) +{ + q->dev = dev; + q->name = name; + QTAILQ_INIT(&q->head); + q->size = 0; +} + +static void packet_id_queue_add(struct PacketIdQueue *q, uint64_t id) +{ + USBRedirDevice *dev = q->dev; + struct PacketIdQueueEntry *e; + + DPRINTF("adding packet id %"PRIu64" to %s queue\n", id, q->name); + + e = g_malloc0(sizeof(struct PacketIdQueueEntry)); + e->id = id; + QTAILQ_INSERT_TAIL(&q->head, e, next); + q->size++; +} + +static int packet_id_queue_remove(struct PacketIdQueue *q, uint64_t id) +{ + USBRedirDevice *dev = q->dev; + struct PacketIdQueueEntry *e; + + QTAILQ_FOREACH(e, &q->head, next) { + if (e->id == id) { + DPRINTF("removing packet id %"PRIu64" from %s queue\n", + id, q->name); + QTAILQ_REMOVE(&q->head, e, next); + q->size--; + g_free(e); + return 1; + } + } + return 0; +} + +static void packet_id_queue_empty(struct PacketIdQueue *q) +{ + USBRedirDevice *dev = q->dev; + struct PacketIdQueueEntry *e, *next_e; + + DPRINTF("removing %d packet-ids from %s queue\n", q->size, q->name); + + QTAILQ_FOREACH_SAFE(e, &q->head, next, next_e) { + QTAILQ_REMOVE(&q->head, e, next); + g_free(e); + } + q->size = 0; +} + static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p) { USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); - Cancelled *c; - - DPRINTF("cancel packet id %"PRIu64"\n", p->id); - - c = g_malloc0(sizeof(Cancelled)); - c->id = p->id; - QTAILQ_INSERT_TAIL(&dev->cancelled, c, next); + packet_id_queue_add(&dev->cancelled, p->id); usbredirparser_send_cancel_data_packet(dev->parser, p->id); usbredirparser_do_write(dev->parser); } static int usbredir_is_cancelled(USBRedirDevice *dev, uint64_t id) { - Cancelled *c; - if (!dev->dev.attached) { return 1; /* Treat everything as cancelled after a disconnect */ } - - QTAILQ_FOREACH(c, &dev->cancelled, next) { - if (c->id == id) { - QTAILQ_REMOVE(&dev->cancelled, c, next); - g_free(c); - return 1; - } - } - return 0; + return packet_id_queue_remove(&dev->cancelled, id); } static USBPacket *usbredir_find_packet_by_id(USBRedirDevice *dev, @@ -914,7 +958,7 @@ static int usbredir_initfn(USBDevice *udev) dev->chardev_close_bh = qemu_bh_new(usbredir_chardev_close_bh, dev); dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev); - QTAILQ_INIT(&dev->cancelled); + packet_id_queue_init(&dev->cancelled, dev, "cancelled"); for (i = 0; i < MAX_ENDPOINTS; i++) { QTAILQ_INIT(&dev->endpoint[i].bufpq); } @@ -933,13 +977,9 @@ static int usbredir_initfn(USBDevice *udev) static void usbredir_cleanup_device_queues(USBRedirDevice *dev) { - Cancelled *c, *next_c; int i; - QTAILQ_FOREACH_SAFE(c, &dev->cancelled, next, next_c) { - QTAILQ_REMOVE(&dev->cancelled, c, next); - g_free(c); - } + packet_id_queue_empty(&dev->cancelled); for (i = 0; i < MAX_ENDPOINTS; i++) { usbredir_free_bufpq(dev, I2EP(i)); } From 9a8d4067a63702dfb62d0ae3399600a853ad5daa Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 12 Sep 2012 15:08:35 +0200 Subject: [PATCH 0351/2270] usb-redir: Add an already_in_flight packet-id queue After a live migration, the usb-hcd will re-queue all packets by walking over the schedule in the guest memory again, but requests which were encountered on the migration source before will already be in flight, so these should *not* be re-send to the usbredir-host. This patch adds an already in flight packet ud queue, which will be filled by the source before migration and then moved over to the migration dest, any async handled packets are then checked against this queue to avoid sending the same packet to the usbredir-host twice. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 603262a45c..f474da80bb 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -98,6 +98,7 @@ struct USBRedirDevice { struct usbredirparser *parser; struct endp_data endpoint[MAX_ENDPOINTS]; struct PacketIdQueue cancelled; + struct PacketIdQueue already_in_flight; /* Data for device filtering */ struct usb_redir_device_connect_header device_info; struct usb_redir_interface_info_header interface_info; @@ -316,6 +317,34 @@ static int usbredir_is_cancelled(USBRedirDevice *dev, uint64_t id) return packet_id_queue_remove(&dev->cancelled, id); } +static void usbredir_fill_already_in_flight_from_ep(USBRedirDevice *dev, + struct USBEndpoint *ep) +{ + static USBPacket *p; + + QTAILQ_FOREACH(p, &ep->queue, queue) { + packet_id_queue_add(&dev->already_in_flight, p->id); + } +} + +static void usbredir_fill_already_in_flight(USBRedirDevice *dev) +{ + int ep; + struct USBDevice *udev = &dev->dev; + + usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_ctl); + + for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) { + usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_in[ep]); + usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_out[ep]); + } +} + +static int usbredir_already_in_flight(USBRedirDevice *dev, uint64_t id) +{ + return packet_id_queue_remove(&dev->already_in_flight, id); +} + static USBPacket *usbredir_find_packet_by_id(USBRedirDevice *dev, uint8_t ep, uint64_t id) { @@ -531,6 +560,10 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p, DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, p->iov.size, p->id); + if (usbredir_already_in_flight(dev, p->id)) { + return USB_RET_ASYNC; + } + bulk_packet.endpoint = ep; bulk_packet.length = p->iov.size; bulk_packet.stream_id = 0; @@ -611,6 +644,10 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev, DPRINTF("interrupt-out ep %02X len %zd id %"PRIu64"\n", ep, p->iov.size, p->id); + if (usbredir_already_in_flight(dev, p->id)) { + return USB_RET_ASYNC; + } + interrupt_packet.endpoint = ep; interrupt_packet.length = p->iov.size; @@ -753,6 +790,10 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p, USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); struct usb_redir_control_packet_header control_packet; + if (usbredir_already_in_flight(dev, p->id)) { + return USB_RET_ASYNC; + } + /* Special cases for certain standard device requests */ switch (request) { case DeviceOutRequest | USB_REQ_SET_ADDRESS: @@ -959,6 +1000,7 @@ static int usbredir_initfn(USBDevice *udev) dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev); packet_id_queue_init(&dev->cancelled, dev, "cancelled"); + packet_id_queue_init(&dev->already_in_flight, dev, "already-in-flight"); for (i = 0; i < MAX_ENDPOINTS; i++) { QTAILQ_INIT(&dev->endpoint[i].bufpq); } @@ -980,6 +1022,7 @@ static void usbredir_cleanup_device_queues(USBRedirDevice *dev) int i; packet_id_queue_empty(&dev->cancelled); + packet_id_queue_empty(&dev->already_in_flight); for (i = 0; i < MAX_ENDPOINTS; i++) { usbredir_free_bufpq(dev, I2EP(i)); } From 3f4be32824ccc5f6a5566b93c900df989a96d048 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 12 Sep 2012 15:08:36 +0200 Subject: [PATCH 0352/2270] usb-redir: Store max_packet_size in endp_data So that we've a place to migrate it to / from to allow restoring it after migration. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index f474da80bb..3196665e7f 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -57,6 +57,7 @@ struct endp_data { uint8_t type; uint8_t interval; uint8_t interface; /* bInterfaceNumber this ep belongs to */ + uint16_t max_packet_size; /* In bytes, not wMaxPacketSize format !! */ uint8_t iso_started; uint8_t iso_error; /* For reporting iso errors to the HC */ uint8_t interrupt_started; @@ -1278,7 +1279,8 @@ static void usbredir_ep_info(void *priv, usb_ep->ifnum = dev->endpoint[i].interface; if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_ep_info_max_packet_size)) { - usb_ep->max_packet_size = ep_info->max_packet_size[i]; + dev->endpoint[i].max_packet_size = + usb_ep->max_packet_size = ep_info->max_packet_size[i]; } if (ep_info->type[i] == usb_redir_type_bulk) { usb_ep->pipeline = true; From fc3f6e1b106abcf6b8cf487ac8f8e5fc2fd86776 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 12 Sep 2012 15:08:37 +0200 Subject: [PATCH 0353/2270] usb-redir: Add support for migration Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 349 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 346 insertions(+), 3 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 3196665e7f..5e987e99a4 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -65,8 +65,8 @@ struct endp_data { uint8_t bufpq_prefilled; uint8_t bufpq_dropping_packets; QTAILQ_HEAD(, buf_packet) bufpq; - int bufpq_size; - int bufpq_target_size; + int32_t bufpq_size; + int32_t bufpq_target_size; }; struct PacketIdQueueEntry { @@ -240,6 +240,11 @@ static int usbredir_write(void *priv, uint8_t *data, int count) return 0; } + /* Don't send new data to the chardev until our state is fully synced */ + if (!runstate_check(RUN_STATE_RUNNING)) { + return 0; + } + return qemu_chr_fe_write(dev->cs, data, count); } @@ -858,6 +863,7 @@ static void usbredir_chardev_open(USBRedirDevice *dev) { uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, }; char version[32]; + int flags = 0; /* Make sure any pending closes are handled (no-op if none pending) */ usbredir_chardev_close_bh(dev); @@ -893,7 +899,12 @@ static void usbredir_chardev_open(USBRedirDevice *dev) usbredirparser_caps_set_cap(caps, usb_redir_cap_filter); usbredirparser_caps_set_cap(caps, usb_redir_cap_ep_info_max_packet_size); usbredirparser_caps_set_cap(caps, usb_redir_cap_64bits_ids); - usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE, 0); + + if (runstate_check(RUN_STATE_INMIGRATE)) { + flags |= usbredirparser_fl_no_hello; + } + usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE, + flags); usbredirparser_do_write(dev->parser); } @@ -939,6 +950,11 @@ static int usbredir_chardev_can_read(void *opaque) return 0; } + /* Don't read new data from the chardev until our state is fully synced */ + if (!runstate_check(RUN_STATE_RUNNING)) { + return 0; + } + /* usbredir_parser_do_read will consume *all* data we give it */ return 1024 * 1024; } @@ -976,6 +992,15 @@ static void usbredir_chardev_event(void *opaque, int event) * init + destroy */ +static void usbredir_vm_state_change(void *priv, int running, RunState state) +{ + USBRedirDevice *dev = priv; + + if (state == RUN_STATE_RUNNING && dev->parser != NULL) { + usbredirparser_do_write(dev->parser); /* Flush any pending writes */ + } +} + static int usbredir_initfn(USBDevice *udev) { USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); @@ -1014,6 +1039,7 @@ static int usbredir_initfn(USBDevice *udev) qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read, usbredir_chardev_read, usbredir_chardev_event, dev); + qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev); add_boot_device_path(dev->bootindex, &udev->qdev, NULL); return 0; } @@ -1503,6 +1529,322 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id, } } +/* + * Migration code + */ + +static void usbredir_pre_save(void *priv) +{ + USBRedirDevice *dev = priv; + + usbredir_fill_already_in_flight(dev); +} + +static int usbredir_post_load(void *priv, int version_id) +{ + USBRedirDevice *dev = priv; + struct USBEndpoint *usb_ep; + int i; + + switch (dev->device_info.speed) { + case usb_redir_speed_low: + dev->dev.speed = USB_SPEED_LOW; + break; + case usb_redir_speed_full: + dev->dev.speed = USB_SPEED_FULL; + break; + case usb_redir_speed_high: + dev->dev.speed = USB_SPEED_HIGH; + break; + case usb_redir_speed_super: + dev->dev.speed = USB_SPEED_SUPER; + break; + default: + dev->dev.speed = USB_SPEED_FULL; + } + dev->dev.speedmask = (1 << dev->dev.speed); + + for (i = 0; i < MAX_ENDPOINTS; i++) { + usb_ep = usb_ep_get(&dev->dev, + (i & 0x10) ? USB_TOKEN_IN : USB_TOKEN_OUT, + i & 0x0f); + usb_ep->type = dev->endpoint[i].type; + usb_ep->ifnum = dev->endpoint[i].interface; + usb_ep->max_packet_size = dev->endpoint[i].max_packet_size; + if (dev->endpoint[i].type == usb_redir_type_bulk) { + usb_ep->pipeline = true; + } + } + return 0; +} + +/* For usbredirparser migration */ +static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused) +{ + USBRedirDevice *dev = priv; + uint8_t *data; + int len; + + if (dev->parser == NULL) { + qemu_put_be32(f, 0); + return; + } + + usbredirparser_serialize(dev->parser, &data, &len); + qemu_oom_check(data); + + qemu_put_be32(f, len); + qemu_put_buffer(f, data, len); + + free(data); +} + +static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused) +{ + USBRedirDevice *dev = priv; + uint8_t *data; + int len, ret; + + len = qemu_get_be32(f); + if (len == 0) { + return 0; + } + + /* + * Our chardev should be open already at this point, otherwise + * the usbredir channel will be broken (ie spice without seamless) + */ + if (dev->parser == NULL) { + ERROR("get_parser called with closed chardev, failing migration\n"); + return -1; + } + + data = g_malloc(len); + qemu_get_buffer(f, data, len); + + ret = usbredirparser_unserialize(dev->parser, data, len); + + g_free(data); + + return ret; +} + +static const VMStateInfo usbredir_parser_vmstate_info = { + .name = "usb-redir-parser", + .put = usbredir_put_parser, + .get = usbredir_get_parser, +}; + + +/* For buffered packets (iso/irq) queue migration */ +static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused) +{ + struct endp_data *endp = priv; + struct buf_packet *bufp; + int remain = endp->bufpq_size; + + qemu_put_be32(f, endp->bufpq_size); + QTAILQ_FOREACH(bufp, &endp->bufpq, next) { + qemu_put_be32(f, bufp->len); + qemu_put_be32(f, bufp->status); + qemu_put_buffer(f, bufp->data, bufp->len); + remain--; + } + assert(remain == 0); +} + +static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused) +{ + struct endp_data *endp = priv; + struct buf_packet *bufp; + int i; + + endp->bufpq_size = qemu_get_be32(f); + for (i = 0; i < endp->bufpq_size; i++) { + bufp = g_malloc(sizeof(struct buf_packet)); + bufp->len = qemu_get_be32(f); + bufp->status = qemu_get_be32(f); + bufp->data = qemu_oom_check(malloc(bufp->len)); /* regular malloc! */ + qemu_get_buffer(f, bufp->data, bufp->len); + QTAILQ_INSERT_TAIL(&endp->bufpq, bufp, next); + } + return 0; +} + +static const VMStateInfo usbredir_ep_bufpq_vmstate_info = { + .name = "usb-redir-bufpq", + .put = usbredir_put_bufpq, + .get = usbredir_get_bufpq, +}; + + +/* For endp_data migration */ +static const VMStateDescription usbredir_ep_vmstate = { + .name = "usb-redir-ep", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(type, struct endp_data), + VMSTATE_UINT8(interval, struct endp_data), + VMSTATE_UINT8(interface, struct endp_data), + VMSTATE_UINT16(max_packet_size, struct endp_data), + VMSTATE_UINT8(iso_started, struct endp_data), + VMSTATE_UINT8(iso_error, struct endp_data), + VMSTATE_UINT8(interrupt_started, struct endp_data), + VMSTATE_UINT8(interrupt_error, struct endp_data), + VMSTATE_UINT8(bufpq_prefilled, struct endp_data), + VMSTATE_UINT8(bufpq_dropping_packets, struct endp_data), + { + .name = "bufpq", + .version_id = 0, + .field_exists = NULL, + .size = 0, + .info = &usbredir_ep_bufpq_vmstate_info, + .flags = VMS_SINGLE, + .offset = 0, + }, + VMSTATE_INT32(bufpq_target_size, struct endp_data), + VMSTATE_END_OF_LIST() + } +}; + + +/* For PacketIdQueue migration */ +static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused) +{ + struct PacketIdQueue *q = priv; + USBRedirDevice *dev = q->dev; + struct PacketIdQueueEntry *e; + int remain = q->size; + + DPRINTF("put_packet_id_q %s size %d\n", q->name, q->size); + qemu_put_be32(f, q->size); + QTAILQ_FOREACH(e, &q->head, next) { + qemu_put_be64(f, e->id); + remain--; + } + assert(remain == 0); +} + +static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused) +{ + struct PacketIdQueue *q = priv; + USBRedirDevice *dev = q->dev; + int i, size; + uint64_t id; + + size = qemu_get_be32(f); + DPRINTF("get_packet_id_q %s size %d\n", q->name, size); + for (i = 0; i < size; i++) { + id = qemu_get_be64(f); + packet_id_queue_add(q, id); + } + assert(q->size == size); + return 0; +} + +static const VMStateInfo usbredir_ep_packet_id_q_vmstate_info = { + .name = "usb-redir-packet-id-q", + .put = usbredir_put_packet_id_q, + .get = usbredir_get_packet_id_q, +}; + +static const VMStateDescription usbredir_ep_packet_id_queue_vmstate = { + .name = "usb-redir-packet-id-queue", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + { + .name = "queue", + .version_id = 0, + .field_exists = NULL, + .size = 0, + .info = &usbredir_ep_packet_id_q_vmstate_info, + .flags = VMS_SINGLE, + .offset = 0, + }, + VMSTATE_END_OF_LIST() + } +}; + + +/* For usb_redir_device_connect_header migration */ +static const VMStateDescription usbredir_device_info_vmstate = { + .name = "usb-redir-device-info", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(speed, struct usb_redir_device_connect_header), + VMSTATE_UINT8(device_class, struct usb_redir_device_connect_header), + VMSTATE_UINT8(device_subclass, struct usb_redir_device_connect_header), + VMSTATE_UINT8(device_protocol, struct usb_redir_device_connect_header), + VMSTATE_UINT16(vendor_id, struct usb_redir_device_connect_header), + VMSTATE_UINT16(product_id, struct usb_redir_device_connect_header), + VMSTATE_UINT16(device_version_bcd, + struct usb_redir_device_connect_header), + VMSTATE_END_OF_LIST() + } +}; + + +/* For usb_redir_interface_info_header migration */ +static const VMStateDescription usbredir_interface_info_vmstate = { + .name = "usb-redir-interface-info", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(interface_count, + struct usb_redir_interface_info_header), + VMSTATE_UINT8_ARRAY(interface, + struct usb_redir_interface_info_header, 32), + VMSTATE_UINT8_ARRAY(interface_class, + struct usb_redir_interface_info_header, 32), + VMSTATE_UINT8_ARRAY(interface_subclass, + struct usb_redir_interface_info_header, 32), + VMSTATE_UINT8_ARRAY(interface_protocol, + struct usb_redir_interface_info_header, 32), + VMSTATE_END_OF_LIST() + } +}; + + +/* And finally the USBRedirDevice vmstate itself */ +static const VMStateDescription usbredir_vmstate = { + .name = "usb-redir", + .version_id = 1, + .minimum_version_id = 1, + .pre_save = usbredir_pre_save, + .post_load = usbredir_post_load, + .fields = (VMStateField[]) { + VMSTATE_USB_DEVICE(dev, USBRedirDevice), + VMSTATE_TIMER(attach_timer, USBRedirDevice), + { + .name = "parser", + .version_id = 0, + .field_exists = NULL, + .size = 0, + .info = &usbredir_parser_vmstate_info, + .flags = VMS_SINGLE, + .offset = 0, + }, + VMSTATE_STRUCT_ARRAY(endpoint, USBRedirDevice, MAX_ENDPOINTS, 1, + usbredir_ep_vmstate, struct endp_data), + VMSTATE_STRUCT(cancelled, USBRedirDevice, 1, + usbredir_ep_packet_id_queue_vmstate, + struct PacketIdQueue), + VMSTATE_STRUCT(already_in_flight, USBRedirDevice, 1, + usbredir_ep_packet_id_queue_vmstate, + struct PacketIdQueue), + VMSTATE_STRUCT(device_info, USBRedirDevice, 1, + usbredir_device_info_vmstate, + struct usb_redir_device_connect_header), + VMSTATE_STRUCT(interface_info, USBRedirDevice, 1, + usbredir_interface_info_vmstate, + struct usb_redir_interface_info_header), + VMSTATE_END_OF_LIST() + } +}; + static Property usbredir_properties[] = { DEFINE_PROP_CHR("chardev", USBRedirDevice, cs), DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0), @@ -1523,6 +1865,7 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data) uc->handle_reset = usbredir_handle_reset; uc->handle_data = usbredir_handle_data; uc->handle_control = usbredir_handle_control; + dc->vmsd = &usbredir_vmstate; dc->props = usbredir_properties; } From 09054d19e72f6991cd359d41c479badd92f62a06 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 12 Sep 2012 15:08:38 +0200 Subject: [PATCH 0354/2270] usb-redir: Add chardev open / close debug logging Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 5e987e99a4..9a4be6d835 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -854,6 +854,7 @@ static void usbredir_chardev_close_bh(void *opaque) usbredir_device_disconnect(dev); if (dev->parser) { + DPRINTF("destroying usbredirparser\n"); usbredirparser_destroy(dev->parser); dev->parser = NULL; } @@ -869,6 +870,8 @@ static void usbredir_chardev_open(USBRedirDevice *dev) usbredir_chardev_close_bh(dev); qemu_bh_cancel(dev->chardev_close_bh); + DPRINTF("creating usbredirparser\n"); + strcpy(version, "qemu usb-redir guest "); pstrcat(version, sizeof(version), qemu_get_version()); @@ -980,9 +983,11 @@ static void usbredir_chardev_event(void *opaque, int event) switch (event) { case CHR_EVENT_OPENED: + DPRINTF("chardev open\n"); usbredir_chardev_open(dev); break; case CHR_EVENT_CLOSED: + DPRINTF("chardev close\n"); qemu_bh_schedule(dev->chardev_close_bh); break; } @@ -1228,6 +1233,7 @@ static void usbredir_device_disconnect(void *priv) qemu_del_timer(dev->attach_timer); if (dev->dev.attached) { + DPRINTF("detaching device\n"); usb_device_detach(&dev->dev); /* * Delay next usb device attach to give the guest a chance to see From 35efba2cc6812dc980c336d7b9bf81dbfb5daf00 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 12 Sep 2012 15:08:39 +0200 Subject: [PATCH 0355/2270] usb-redir: Revert usb-redir part of commit 93bfef4c Commit 93bfef4c6e4b23caea9d51e1099d06433d8835a4 makes qemu-devices which report the qemu version string to the guest in some way use a qemu_get_version function which reports a machine-specific version string. However usb-redir does not expose the qemu version to the guest, only to the usbredir-host as part of the initial handshake. This can then be logged on the usbredir-host side for debugging purposes and is otherwise completely unused! For debugging purposes it is important to have the real qemu version in there, rather then the machine-specific version. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 9a4be6d835..b10241a139 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -142,6 +142,8 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id, static int usbredir_handle_status(USBRedirDevice *dev, int status, int actual_len); +#define VERSION "qemu usb-redir guest " QEMU_VERSION + /* * Logging stuff */ @@ -863,7 +865,6 @@ static void usbredir_chardev_close_bh(void *opaque) static void usbredir_chardev_open(USBRedirDevice *dev) { uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, }; - char version[32]; int flags = 0; /* Make sure any pending closes are handled (no-op if none pending) */ @@ -872,9 +873,6 @@ static void usbredir_chardev_open(USBRedirDevice *dev) DPRINTF("creating usbredirparser\n"); - strcpy(version, "qemu usb-redir guest "); - pstrcat(version, sizeof(version), qemu_get_version()); - dev->parser = qemu_oom_check(usbredirparser_create()); dev->parser->priv = dev; dev->parser->log_func = usbredir_log; @@ -906,7 +904,7 @@ static void usbredir_chardev_open(USBRedirDevice *dev) if (runstate_check(RUN_STATE_INMIGRATE)) { flags |= usbredirparser_fl_no_hello; } - usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE, + usbredirparser_init(dev->parser, VERSION, caps, USB_REDIR_CAPS_SIZE, flags); usbredirparser_do_write(dev->parser); } From 72a04d0c178f01908d74539230d9de64ffc6da19 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 12 Sep 2012 15:08:40 +0200 Subject: [PATCH 0356/2270] uhci: Don't queue up packets after one with the SPD flag set Don't queue up packets after a packet with the SPD (short packet detect) flag set. Since we won't know if the packet will actually be short until it has completed, and if it is short we should stop the queue. This fixes a miniature photoframe emulating a USB cdrom with the windows software for it not working. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index c7c878635a..cdc8bc3fba 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -1000,6 +1000,9 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td) } assert(ret == TD_RESULT_ASYNC_START); assert(int_mask == 0); + if (ptd.ctrl & TD_CTRL_SPD) { + break; + } plink = ptd.link; } } @@ -1097,7 +1100,7 @@ static void uhci_process_frame(UHCIState *s) case TD_RESULT_ASYNC_START: trace_usb_uhci_td_async(curr_qh & ~0xf, link & ~0xf); - if (is_valid(td.link)) { + if (is_valid(td.link) && !(td.ctrl & TD_CTRL_SPD)) { uhci_fill_queue(s, &td); } link = curr_qh ? qh.link : td.link; From c4d12a743c73a5b88a8705ca68ff620ce0f8bba7 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Tue, 4 Sep 2012 23:20:35 +0200 Subject: [PATCH 0357/2270] slirp: Remove wrong type casts ins debug statements The type casts of pointers to long are not allowed when sizeof(pointer) != sizeof(long). Signed-off-by: Stefan Weil Signed-off-by: Jan Kiszka --- slirp/tcp_subr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c index 025b374367..5890d7a827 100644 --- a/slirp/tcp_subr.c +++ b/slirp/tcp_subr.c @@ -114,9 +114,9 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m, int win = 0; DEBUG_CALL("tcp_respond"); - DEBUG_ARG("tp = %lx", (long)tp); - DEBUG_ARG("ti = %lx", (long)ti); - DEBUG_ARG("m = %lx", (long)m); + DEBUG_ARG("tp = %p", tp); + DEBUG_ARG("ti = %p", ti); + DEBUG_ARG("m = %p", m); DEBUG_ARG("ack = %u", ack); DEBUG_ARG("seq = %u", seq); DEBUG_ARG("flags = %x", flags); From e56afbc54a2132c56931f44bae1992c28119944f Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Tue, 4 Sep 2012 23:20:36 +0200 Subject: [PATCH 0358/2270] slirp: Fix error reported by static code analysis Report from smatch: slirp/tcp_subr.c:127 tcp_respond(17) error: we previously assumed 'tp' could be null (see line 124) Return if 'tp' is NULL. Signed-off-by: Stefan Weil Signed-off-by: Jan Kiszka --- slirp/tcp_subr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c index 5890d7a827..1542e43619 100644 --- a/slirp/tcp_subr.c +++ b/slirp/tcp_subr.c @@ -124,7 +124,7 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m, if (tp) win = sbspace(&tp->t_socket->so_rcv); if (m == NULL) { - if ((m = m_get(tp->t_socket->slirp)) == NULL) + if (!tp || (m = m_get(tp->t_socket->slirp)) == NULL) return; tlen = 0; m->m_data += IF_MAXLINKHDR; From 78be056628c76ff73eedeade86fde44b97343c79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Mon, 10 Sep 2012 20:52:25 +0200 Subject: [PATCH 0359/2270] slirp: improve TFTP performance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When transferring a file, keep it open during the whole transfer, instead of opening/closing it for each block. Signed-off-by: Hervé Poussineau Reviewed-by: Aurelien Jarno Signed-off-by: Jan Kiszka --- slirp/tftp.c | 32 ++++++++++++++++++-------------- slirp/tftp.h | 1 + 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/slirp/tftp.c b/slirp/tftp.c index b78765f3af..520dbd6d3c 100644 --- a/slirp/tftp.c +++ b/slirp/tftp.c @@ -37,6 +37,10 @@ static inline void tftp_session_update(struct tftp_session *spt) static void tftp_session_terminate(struct tftp_session *spt) { + if (spt->fd >= 0) { + close(spt->fd); + spt->fd = -1; + } g_free(spt->filename); spt->slirp = NULL; } @@ -54,7 +58,7 @@ static int tftp_session_allocate(Slirp *slirp, struct tftp_t *tp) /* sessions time out after 5 inactive seconds */ if ((int)(curtime - spt->timestamp) > 5000) { - g_free(spt->filename); + tftp_session_terminate(spt); goto found; } } @@ -64,6 +68,7 @@ static int tftp_session_allocate(Slirp *slirp, struct tftp_t *tp) found: memset(spt, 0, sizeof(*spt)); memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip)); + spt->fd = -1; spt->client_port = tp->udp.uh_sport; spt->slirp = slirp; @@ -95,24 +100,23 @@ static int tftp_session_find(Slirp *slirp, struct tftp_t *tp) static int tftp_read_data(struct tftp_session *spt, uint16_t block_nr, uint8_t *buf, int len) { - int fd; - int bytes_read = 0; + int bytes_read = 0; - fd = open(spt->filename, O_RDONLY | O_BINARY); + if (spt->fd < 0) { + spt->fd = open(spt->filename, O_RDONLY | O_BINARY); + } - if (fd < 0) { - return -1; - } + if (spt->fd < 0) { + return -1; + } - if (len) { - lseek(fd, block_nr * 512, SEEK_SET); + if (len) { + lseek(spt->fd, block_nr * 512, SEEK_SET); - bytes_read = read(fd, buf, len); - } + bytes_read = read(spt->fd, buf, len); + } - close(fd); - - return bytes_read; + return bytes_read; } static int tftp_send_oack(struct tftp_session *spt, diff --git a/slirp/tftp.h b/slirp/tftp.h index 72e5e91bef..9c364ea28e 100644 --- a/slirp/tftp.h +++ b/slirp/tftp.h @@ -33,6 +33,7 @@ struct tftp_t { struct tftp_session { Slirp *slirp; char *filename; + int fd; struct in_addr client_ip; uint16_t client_port; From 4aa401f39e048e71020cceb59f126ab941095a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Thu, 13 Sep 2012 12:39:36 +0200 Subject: [PATCH 0360/2270] slirp: Handle more than 65535 blocks in TFTP transfers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RFC 1350 does not mention block count roll-over. However, a lot of TFTP servers implement it to be able to transmit big files, so do it also. Current block size is 512 bytes, so TFTP files were limited to 32 MB. Signed-off-by: Hervé Poussineau Signed-off-by: Jan Kiszka --- slirp/tftp.c | 24 ++++++++++-------------- slirp/tftp.h | 1 + 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/slirp/tftp.c b/slirp/tftp.c index 520dbd6d3c..c6a5df2dd2 100644 --- a/slirp/tftp.c +++ b/slirp/tftp.c @@ -97,7 +97,7 @@ static int tftp_session_find(Slirp *slirp, struct tftp_t *tp) return -1; } -static int tftp_read_data(struct tftp_session *spt, uint16_t block_nr, +static int tftp_read_data(struct tftp_session *spt, uint32_t block_nr, uint8_t *buf, int len) { int bytes_read = 0; @@ -197,19 +197,14 @@ out: tftp_session_terminate(spt); } -static int tftp_send_data(struct tftp_session *spt, - uint16_t block_nr, - struct tftp_t *recv_tp) +static int tftp_send_next_block(struct tftp_session *spt, + struct tftp_t *recv_tp) { struct sockaddr_in saddr, daddr; struct mbuf *m; struct tftp_t *tp; int nobytes; - if (block_nr < 1) { - return -1; - } - m = m_get(spt->slirp); if (!m) { @@ -223,7 +218,7 @@ static int tftp_send_data(struct tftp_session *spt, m->m_data += sizeof(struct udpiphdr); tp->tp_op = htons(TFTP_DATA); - tp->x.tp_data.tp_block_nr = htons(block_nr); + tp->x.tp_data.tp_block_nr = htons((spt->block_nr + 1) & 0xffff); saddr.sin_addr = recv_tp->ip.ip_dst; saddr.sin_port = recv_tp->udp.uh_dport; @@ -231,7 +226,7 @@ static int tftp_send_data(struct tftp_session *spt, daddr.sin_addr = spt->client_ip; daddr.sin_port = spt->client_port; - nobytes = tftp_read_data(spt, block_nr - 1, tp->x.tp_data.tp_buf, 512); + nobytes = tftp_read_data(spt, spt->block_nr, tp->x.tp_data.tp_buf, 512); if (nobytes < 0) { m_free(m); @@ -255,6 +250,7 @@ static int tftp_send_data(struct tftp_session *spt, tftp_session_terminate(spt); } + spt->block_nr++; return 0; } @@ -373,7 +369,8 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen) } } - tftp_send_data(spt, 1, tp); + spt->block_nr = 0; + tftp_send_next_block(spt, tp); } static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen) @@ -386,9 +383,8 @@ static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen) return; } - if (tftp_send_data(&slirp->tftp_sessions[s], - ntohs(tp->x.tp_data.tp_block_nr) + 1, - tp) < 0) { + if (tftp_send_next_block(&slirp->tftp_sessions[s], + tp) < 0) { return; } } diff --git a/slirp/tftp.h b/slirp/tftp.h index 9c364ea28e..51704e4874 100644 --- a/slirp/tftp.h +++ b/slirp/tftp.h @@ -37,6 +37,7 @@ struct tftp_session { struct in_addr client_ip; uint16_t client_port; + uint32_t block_nr; int timestamp; }; From eb7faf0e3a45b0a0089035f972080ca4bd2e15ce Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 13 Sep 2012 12:44:27 +0200 Subject: [PATCH 0361/2270] slirp: Remove unused return value of tftp_send_next_block No caller actually makes use of this value, so let's simplify the code. Signed-off-by: Jan Kiszka --- slirp/tftp.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/slirp/tftp.c b/slirp/tftp.c index c6a5df2dd2..cf7e3b8238 100644 --- a/slirp/tftp.c +++ b/slirp/tftp.c @@ -197,8 +197,8 @@ out: tftp_session_terminate(spt); } -static int tftp_send_next_block(struct tftp_session *spt, - struct tftp_t *recv_tp) +static void tftp_send_next_block(struct tftp_session *spt, + struct tftp_t *recv_tp) { struct sockaddr_in saddr, daddr; struct mbuf *m; @@ -208,7 +208,7 @@ static int tftp_send_next_block(struct tftp_session *spt, m = m_get(spt->slirp); if (!m) { - return -1; + return; } memset(m->m_data, 0, m->m_size); @@ -235,7 +235,7 @@ static int tftp_send_next_block(struct tftp_session *spt, tftp_send_error(spt, 1, "File not found", tp); - return -1; + return; } m->m_len = sizeof(struct tftp_t) - (512 - nobytes) - @@ -251,7 +251,6 @@ static int tftp_send_next_block(struct tftp_session *spt, } spt->block_nr++; - return 0; } static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen) @@ -383,10 +382,7 @@ static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen) return; } - if (tftp_send_next_block(&slirp->tftp_sessions[s], - tp) < 0) { - return; - } + tftp_send_next_block(&slirp->tftp_sessions[s], tp); } static void tftp_handle_error(Slirp *slirp, struct tftp_t *tp, int pktlen) From 95b1ad7ad86793c27ab8e9987be69571937900d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Thu, 13 Sep 2012 07:55:01 +0200 Subject: [PATCH 0362/2270] slirp: Implement TFTP Blocksize option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This option is described in RFC 1783. As this is only an optional field, we may ignore it in some situations and handle it in some others. However, MS Windows 2003 PXE boot client requests a block size of the MTU (most of the times 1472 bytes), and doesn't work if the option is not acknowledged (with whatever value). According to the RFC 1783, we cannot acknowledge the option with a bigger value than the requested one. As current implementation is using 512 bytes by block, accept the option with a value of 512 if the option was specified, and don't acknowledge it if it is not present or less than 512 bytes. Signed-off-by: Hervé Poussineau Signed-off-by: Jan Kiszka --- slirp/tftp.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/slirp/tftp.c b/slirp/tftp.c index cf7e3b8238..1a79c45cfb 100644 --- a/slirp/tftp.c +++ b/slirp/tftp.c @@ -120,13 +120,13 @@ static int tftp_read_data(struct tftp_session *spt, uint32_t block_nr, } static int tftp_send_oack(struct tftp_session *spt, - const char *key, uint32_t value, + const char *keys[], uint32_t values[], int nb, struct tftp_t *recv_tp) { struct sockaddr_in saddr, daddr; struct mbuf *m; struct tftp_t *tp; - int n = 0; + int i, n = 0; m = m_get(spt->slirp); @@ -140,10 +140,12 @@ static int tftp_send_oack(struct tftp_session *spt, m->m_data += sizeof(struct udpiphdr); tp->tp_op = htons(TFTP_OACK); - n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%s", - key) + 1; - n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%u", - value) + 1; + for (i = 0; i < nb; i++) { + n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%s", + keys[i]) + 1; + n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%u", + values[i]) + 1; + } saddr.sin_addr = recv_tp->ip.ip_dst; saddr.sin_port = recv_tp->udp.uh_dport; @@ -259,6 +261,9 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen) int s, k; size_t prefix_len; char *req_fname; + const char *option_name[2]; + uint32_t option_value[2]; + int nb_options = 0; /* check if a session already exists and if so terminate it */ s = tftp_session_find(slirp, tp); @@ -336,7 +341,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen) return; } - while (k < pktlen) { + while (k < pktlen && nb_options < ARRAY_SIZE(option_name)) { const char *key, *value; key = &tp->x.tp_buf[k]; @@ -363,11 +368,30 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen) } } - tftp_send_oack(spt, "tsize", tsize, tp); - return; + option_name[nb_options] = "tsize"; + option_value[nb_options] = tsize; + nb_options++; + } else if (strcasecmp(key, "blksize") == 0) { + int blksize = atoi(value); + + /* If blksize option is bigger than what we will + * emit, accept the option with our packet size. + * Otherwise, simply do as we didn't see the option. + */ + if (blksize >= 512) { + option_name[nb_options] = "blksize"; + option_value[nb_options] = 512; + nb_options++; + } } } + if (nb_options > 0) { + assert(nb_options <= ARRAY_SIZE(option_name)); + tftp_send_oack(spt, option_name, option_value, nb_options, tp); + return; + } + spt->block_nr = 0; tftp_send_next_block(spt, tp); } From 93d3ad2a8048469d2b2bb157697425b66b2a37aa Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 10 Aug 2012 22:03:27 +0200 Subject: [PATCH 0363/2270] srp: Don't use QEMU_PACKED for single elements of a structured type QEMU_PACKED results in a MinGW compiler warning when it is used for single structure elements: warning: 'gcc_struct' attribute ignored Using QEMU_PACKED for the whole structure avoids the compiler warning without changing the memory layout. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- hw/srp.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/srp.h b/hw/srp.h index 3009bd56ce..5e0cad5c19 100644 --- a/hw/srp.h +++ b/hw/srp.h @@ -177,13 +177,13 @@ struct srp_tsk_mgmt { uint8_t reserved1[6]; uint64_t tag; uint8_t reserved2[4]; - uint64_t lun QEMU_PACKED; + uint64_t lun; uint8_t reserved3[2]; uint8_t tsk_mgmt_func; uint8_t reserved4; uint64_t task_tag; uint8_t reserved5[8]; -}; +} QEMU_PACKED; /* * We need the packed attribute because the SRP spec only aligns the @@ -198,14 +198,14 @@ struct srp_cmd { uint8_t data_in_desc_cnt; uint64_t tag; uint8_t reserved2[4]; - uint64_t lun QEMU_PACKED; + uint64_t lun; uint8_t reserved3; uint8_t task_attr; uint8_t reserved4; uint8_t add_cdb_len; uint8_t cdb[16]; uint8_t add_data[0]; -}; +} QEMU_PACKED; enum { SRP_RSP_FLAG_RSPVALID = 1 << 0, From 0546b8c2f089867cd7606ff47e026e8931157828 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 10 Aug 2012 22:03:25 +0200 Subject: [PATCH 0364/2270] Spelling fixes in comments and documentation These wrong spellings were detected by codespell: * successully -> successfully * alot -> a lot * wanna -> want to * infomation -> information * occured -> occurred ["also is" -> "is also" and "ressources" -> "resources" suggested by Peter Maydell ] Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- docs/specs/ppc-spapr-hcalls.txt | 2 +- docs/usb2.txt | 4 ++-- hw/xen_pt.h | 4 ++-- hw/xen_pt_config_init.c | 14 +++++++------- qemu-img.c | 2 +- qemu-img.texi | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/specs/ppc-spapr-hcalls.txt b/docs/specs/ppc-spapr-hcalls.txt index 52ba8d42ab..667b3fa00e 100644 --- a/docs/specs/ppc-spapr-hcalls.txt +++ b/docs/specs/ppc-spapr-hcalls.txt @@ -31,7 +31,7 @@ Arguments: Returns: - H_SUCCESS : Successully called the RTAS function (RTAS result + H_SUCCESS : Successfully called the RTAS function (RTAS result will have been stored in the parameter block) H_PARAMETER : Unknown token diff --git a/docs/usb2.txt b/docs/usb2.txt index d17e3c0044..43dacdec28 100644 --- a/docs/usb2.txt +++ b/docs/usb2.txt @@ -58,11 +58,11 @@ try ... xhci controller support ----------------------- -There also is xhci host controller support available. It got alot +There is also xhci host controller support available. It got a lot less testing than ehci and there are a bunch of known limitations, so ehci may work better for you. On the other hand the xhci hardware design is much more virtualization-friendly, thus xhci emulation uses -less ressources (especially cpu). If you wanna give xhci a try +less resources (especially cpu). If you want to give xhci a try use this to add the host controller ... qemu -device nec-usb-xhci,id=xhci diff --git a/hw/xen_pt.h b/hw/xen_pt.h index 41904ece93..112477a881 100644 --- a/hw/xen_pt.h +++ b/hw/xen_pt.h @@ -96,7 +96,7 @@ typedef struct XenPTRegion { * - do NOT use ALL F for init_val, otherwise the tbl will not be registered. */ -/* emulated register infomation */ +/* emulated register information */ struct XenPTRegInfo { uint32_t offset; uint32_t size; @@ -140,7 +140,7 @@ typedef int (*xen_pt_reg_size_init_fn) (XenPCIPassthroughState *, const XenPTRegGroupInfo *, uint32_t base_offset, uint8_t *size); -/* emulated register group infomation */ +/* emulated register group information */ struct XenPTRegGroupInfo { uint8_t grp_id; XenPTRegisterGroupType grp_type; diff --git a/hw/xen_pt_config_init.c b/hw/xen_pt_config_init.c index 00eb3d997d..e524a4094d 100644 --- a/hw/xen_pt_config_init.c +++ b/hw/xen_pt_config_init.c @@ -562,7 +562,7 @@ static int xen_pt_exp_rom_bar_reg_write(XenPCIPassthroughState *s, return 0; } -/* Header Type0 reg static infomation table */ +/* Header Type0 reg static information table */ static XenPTRegInfo xen_pt_emu_reg_header0[] = { /* Vendor ID reg */ { @@ -753,7 +753,7 @@ static XenPTRegInfo xen_pt_emu_reg_header0[] = { * Vital Product Data Capability */ -/* Vital Product Data Capability Structure reg static infomation table */ +/* Vital Product Data Capability Structure reg static information table */ static XenPTRegInfo xen_pt_emu_reg_vpd[] = { { .offset = PCI_CAP_LIST_NEXT, @@ -775,7 +775,7 @@ static XenPTRegInfo xen_pt_emu_reg_vpd[] = { * Vendor Specific Capability */ -/* Vendor Specific Capability Structure reg static infomation table */ +/* Vendor Specific Capability Structure reg static information table */ static XenPTRegInfo xen_pt_emu_reg_vendor[] = { { .offset = PCI_CAP_LIST_NEXT, @@ -866,7 +866,7 @@ static int xen_pt_linkctrl2_reg_init(XenPCIPassthroughState *s, return 0; } -/* PCI Express Capability Structure reg static infomation table */ +/* PCI Express Capability Structure reg static information table */ static XenPTRegInfo xen_pt_emu_reg_pcie[] = { /* Next Pointer reg */ { @@ -981,7 +981,7 @@ static int xen_pt_pmcsr_reg_write(XenPCIPassthroughState *s, return 0; } -/* Power Management Capability reg static infomation table */ +/* Power Management Capability reg static information table */ static XenPTRegInfo xen_pt_emu_reg_pm[] = { /* Next Pointer reg */ { @@ -1259,7 +1259,7 @@ static int xen_pt_msgdata_reg_write(XenPCIPassthroughState *s, return 0; } -/* MSI Capability Structure reg static infomation table */ +/* MSI Capability Structure reg static information table */ static XenPTRegInfo xen_pt_emu_reg_msi[] = { /* Next Pointer reg */ { @@ -1396,7 +1396,7 @@ static int xen_pt_msixctrl_reg_write(XenPCIPassthroughState *s, return 0; } -/* MSI-X Capability Structure reg static infomation table */ +/* MSI-X Capability Structure reg static information table */ static XenPTRegInfo xen_pt_emu_reg_msix[] = { /* Next Pointer reg */ { diff --git a/qemu-img.c b/qemu-img.c index b41e670a61..833b2b0180 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -89,7 +89,7 @@ static void help(void) " '-r' tries to repair any inconsistencies that are found during the check.\n" " '-r leaks' repairs only cluster leaks, whereas '-r all' fixes all\n" " kinds of errors, with a higher risk of choosing the wrong fix or\n" - " hiding corruption that has already occured.\n" + " hiding corruption that has already occurred.\n" "\n" "Parameters to snapshot subcommand:\n" " 'snapshot' is the name of the snapshot to create, apply or delete\n" diff --git a/qemu-img.texi b/qemu-img.texi index 6b42e35fe7..360543b807 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -87,7 +87,7 @@ Perform a consistency check on the disk image @var{filename}. If @code{-r} is specified, qemu-img tries to repair any inconsistencies found during the check. @code{-r leaks} repairs only cluster leaks, whereas @code{-r all} fixes all kinds of errors, with a higher risk of choosing the -wrong fix or hiding corruption that has already occured. +wrong fix or hiding corruption that has already occurred. Only the formats @code{qcow2}, @code{qed} and @code{vdi} support consistency checks. From aade7b91d5afce84b1328f0dbbc77452bde00d1f Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 10 Aug 2012 22:03:26 +0200 Subject: [PATCH 0365/2270] Fix spelling (licenced -> licensed) in GPL The patch also fixes the case of "written". Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- hw/imx_avic.c | 4 ++-- hw/imx_timer.c | 4 ++-- hw/kzm.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/imx_avic.c b/hw/imx_avic.c index 4f010e8ee2..b1a8fe6d4c 100644 --- a/hw/imx_avic.c +++ b/hw/imx_avic.c @@ -6,9 +6,9 @@ * * Copyright (c) 2008 OKL * Copyright (c) 2011 NICTA Pty Ltd - * Originally Written by Hans Jiang + * Originally written by Hans Jiang * - * This code is licenced under the GPL version 2 or later. See + * This code is licensed under the GPL version 2 or later. See * the COPYING file in the top-level directory. * * TODO: implement vectors. diff --git a/hw/imx_timer.c b/hw/imx_timer.c index 16215ccf04..c28c53725a 100644 --- a/hw/imx_timer.c +++ b/hw/imx_timer.c @@ -3,10 +3,10 @@ * * Copyright (c) 2008 OK Labs * Copyright (c) 2011 NICTA Pty Ltd - * Originally Written by Hans Jiang + * Originally written by Hans Jiang * Updated by Peter Chubb * - * This code is licenced under GPL version 2 or later. See + * This code is licensed under GPL version 2 or later. See * the COPYING file in the top-level directory. * */ diff --git a/hw/kzm.c b/hw/kzm.c index 6a5e9dfaca..68cd1b48b9 100644 --- a/hw/kzm.c +++ b/hw/kzm.c @@ -5,7 +5,7 @@ * Written by Hans at OK-Labs * Updated by Peter Chubb. * - * This code is licenced under the GPL, version 2 or later. + * This code is licensed under the GPL, version 2 or later. * See the file `COPYING' in the top level directory. * * It (partially) emulates a Kyoto Microcomputer From 52a8e968a325f5dbbdceba06aaad2ac94f30da37 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 16 Aug 2012 15:12:21 +0200 Subject: [PATCH 0366/2270] Spelling fixes in comments and macro names (ressource -> resource) Macro XEN_HOST_PCI_RESOURCE_BUFFER_SIZE is only used locally, so the change should be safe. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- hw/xen-host-pci-device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/xen-host-pci-device.c b/hw/xen-host-pci-device.c index e7ff680ef2..743b37b991 100644 --- a/hw/xen-host-pci-device.c +++ b/hw/xen-host-pci-device.c @@ -47,13 +47,13 @@ static int xen_host_pci_sysfs_path(const XenHostPCIDevice *d, } -/* This size should be enough to read the first 7 lines of a ressource file */ -#define XEN_HOST_PCI_RESSOURCE_BUFFER_SIZE 400 +/* This size should be enough to read the first 7 lines of a resource file */ +#define XEN_HOST_PCI_RESOURCE_BUFFER_SIZE 400 static int xen_host_pci_get_resource(XenHostPCIDevice *d) { int i, rc, fd; char path[PATH_MAX]; - char buf[XEN_HOST_PCI_RESSOURCE_BUFFER_SIZE]; + char buf[XEN_HOST_PCI_RESOURCE_BUFFER_SIZE]; unsigned long long start, end, flags, size; char *endptr, *s; uint8_t type; From 4580c490107ec846fb1ec63be823cf65dbb19f73 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 17 Aug 2012 15:20:00 +0200 Subject: [PATCH 0367/2270] ui: Fix spelling in comment (ressource -> resource) The function is called interface_release_resource. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- ui/spice-display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/spice-display.c b/ui/spice-display.c index 99bc665bc7..11f55c49e1 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -243,7 +243,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) } /* - * Called from spice server thread context (via interface_release_ressource) + * Called from spice server thread context (via interface_release_resource) * We do *not* hold the global qemu mutex here, so extra care is needed * when calling qemu functions. QEMU interfaces used: * - g_free (underlying glibc free is re-entrant). From 7b1532eccf63eae318f9116adfd4cc2ba51e31fd Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 20 Aug 2012 14:03:36 +0100 Subject: [PATCH 0368/2270] linux-user: Remove #if 0'd cpu_get_real_ticks() definition Remove the cpu_get_real_ticks() definition from linux-user/main.c. This has been disabled via #if 0 and unused since commit 1dce7c3c22 in 2006; the definitions we actually use are in qemu-timer.h. Signed-off-by: Peter Maydell Signed-off-by: Stefan Hajnoczi --- linux-user/main.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 1a1c661ee4..e84a18c33c 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -89,19 +89,6 @@ int cpu_get_pic_interrupt(CPUX86State *env) } #endif -/* timers for rdtsc */ - -#if 0 - -static uint64_t emu_time; - -int64_t cpu_get_real_ticks(void) -{ - return emu_time++; -} - -#endif - #if defined(CONFIG_USE_NPTL) /***********************************************************/ /* Helper routines for implementing atomic operations. */ From 1a7e8cae4bfd99beca9103de188440afda6c002a Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 22 Aug 2012 17:18:38 +0200 Subject: [PATCH 0369/2270] Fix copy&paste typos in documentation comments Signed-off-by: BALATON Zoltan Signed-off-by: Stefan Hajnoczi --- memory.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/memory.h b/memory.h index bd1bbaeabe..f6c8e32476 100644 --- a/memory.h +++ b/memory.h @@ -252,9 +252,9 @@ void memory_region_init_ram(MemoryRegion *mr, uint64_t size); /** - * memory_region_init_ram: Initialize RAM memory region from a user-provided. - * pointer. Accesses into the region will modify - * memory directly. + * memory_region_init_ram_ptr: Initialize RAM memory region from a + * user-provided pointer. Accesses into the + * region will modify memory directly. * * @mr: the #MemoryRegion to be initialized. * @name: the name of the region. @@ -581,7 +581,8 @@ void memory_region_add_subregion(MemoryRegion *mr, target_phys_addr_t offset, MemoryRegion *subregion); /** - * memory_region_add_subregion: Add a subregion to a container, with overlap. + * memory_region_add_subregion_overlap: Add a subregion to a container + * with overlap. * * Adds a subregion at @offset. The subregion may overlap with other * subregions. Conflicts are resolved by having a higher @priority hide a @@ -743,7 +744,7 @@ void memory_listener_unregister(MemoryListener *listener); void memory_global_dirty_log_start(void); /** - * memory_global_dirty_log_stop: begin dirty logging for all regions + * memory_global_dirty_log_stop: end dirty logging for all regions */ void memory_global_dirty_log_stop(void); From feadf1a4de0d7468ffb671a2b9f681925469fa58 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 22 Aug 2012 17:19:42 +0200 Subject: [PATCH 0370/2270] console: Clean up bytes per pixel calculation Division with round up is the correct way to compute this even if the only case where division with round down gives incorrect result is probably 15 bpp. This case was explicitely patched up in one of these functions but was unhandled in the other. (I'm not sure about setting 16 bpp for the 15bpp case either but I left that there for now.) Signed-off-by: BALATON Zoltan Signed-off-by: Stefan Hajnoczi --- console.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/console.c b/console.c index c1ed5e09e0..a8bcc42fe4 100644 --- a/console.c +++ b/console.c @@ -1612,7 +1612,7 @@ PixelFormat qemu_different_endianness_pixelformat(int bpp) memset(&pf, 0x00, sizeof(PixelFormat)); pf.bits_per_pixel = bpp; - pf.bytes_per_pixel = bpp / 8; + pf.bytes_per_pixel = DIV_ROUND_UP(bpp, 8); pf.depth = bpp == 32 ? 24 : bpp; switch (bpp) { @@ -1661,13 +1661,12 @@ PixelFormat qemu_default_pixelformat(int bpp) memset(&pf, 0x00, sizeof(PixelFormat)); pf.bits_per_pixel = bpp; - pf.bytes_per_pixel = bpp / 8; + pf.bytes_per_pixel = DIV_ROUND_UP(bpp, 8); pf.depth = bpp == 32 ? 24 : bpp; switch (bpp) { case 15: pf.bits_per_pixel = 16; - pf.bytes_per_pixel = 2; pf.rmask = 0x00007c00; pf.gmask = 0x000003E0; pf.bmask = 0x0000001F; From 6932a69b20a88428c531805cdd20eec8acf05b27 Mon Sep 17 00:00:00 2001 From: Lei Li Date: Thu, 23 Aug 2012 13:14:25 +0800 Subject: [PATCH 0371/2270] qapi: Fix enumeration typo error Signed-off-by: Lei Li Reviewed-by: Luiz Capitulino Signed-off-by: Stefan Hajnoczi --- qapi-schema-guest.json | 2 +- qapi-schema.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json index d955cf11fb..ed0eb698c6 100644 --- a/qapi-schema-guest.json +++ b/qapi-schema-guest.json @@ -293,7 +293,7 @@ ## # @GuestFsFreezeStatus # -# An enumation of filesystem freeze states +# An enumeration of filesystem freeze states # # @thawed: filesystems thawed/unfrozen # diff --git a/qapi-schema.json b/qapi-schema.json index a9f465a9ff..24f5da0d4c 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -118,7 +118,7 @@ ## # @RunState # -# An enumation of VM run states. +# An enumeration of VM run states. # # @debug: QEMU is running on a debugger # @@ -785,7 +785,7 @@ ## # @SpiceQueryMouseMode # -# An enumation of Spice mouse states. +# An enumeration of Spice mouse states. # # @client: Mouse cursor position is determined by the client. # From 6d1cc3210ccc4372ffa337c187da9db68314c0c4 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Mon, 3 Sep 2012 22:40:40 +0200 Subject: [PATCH 0372/2270] kvm: Fix warning from static code analysis Report from smatch: kvm-all.c:1373 kvm_init(135) warn: variable dereferenced before check 's' (see line 1360) 's' cannot by NULL (it was alloced using g_malloc0), so there is no need to check it here. Signed-off-by: Stefan Weil Reviewed-by: Peter Maydell Signed-off-by: Stefan Hajnoczi --- kvm-all.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index 39cff55f5b..e5ed3df1ac 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1409,13 +1409,11 @@ int kvm_init(void) return 0; err: - if (s) { - if (s->vmfd >= 0) { - close(s->vmfd); - } - if (s->fd != -1) { - close(s->fd); - } + if (s->vmfd >= 0) { + close(s->vmfd); + } + if (s->fd != -1) { + close(s->fd); } g_free(s); From ef37a699a06f96e098ee00683b7052b5fbb6ad7d Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Wed, 5 Sep 2012 13:04:56 +0400 Subject: [PATCH 0373/2270] arch_init.c: add missing '%' symbols before PRIu64 in debug printfs '%' symbols were missing in front of PRIu64 macros in DPRINTF() messages in arch_init.c, this caused compilation warnings when compiled with DEBUG_ARCH_INIT defined. Signed-off-by: Igor Mitsyanko Signed-off-by: Stefan Hajnoczi --- arch_init.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch_init.c b/arch_init.c index 5a1173e29a..47977de7c6 100644 --- a/arch_init.c +++ b/arch_init.c @@ -562,7 +562,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) if ((i & 63) == 0) { uint64_t t1 = (qemu_get_clock_ns(rt_clock) - bwidth) / 1000000; if (t1 > MAX_WAIT) { - DPRINTF("big wait: " PRIu64 " milliseconds, %d iterations\n", + DPRINTF("big wait: %" PRIu64 " milliseconds, %d iterations\n", t1, i); break; } @@ -587,7 +587,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth; - DPRINTF("ram_save_live: expected(" PRIu64 ") <= max(" PRIu64 ")?\n", + DPRINTF("ram_save_live: expected(%" PRIu64 ") <= max(%" PRIu64 ")?\n", expected_time, migrate_max_downtime()); if (expected_time <= migrate_max_downtime()) { @@ -799,8 +799,8 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) } while (!(flags & RAM_SAVE_FLAG_EOS)); done: - DPRINTF("Completed load of VM with exit code %d seq iteration " PRIu64 "\n", - ret, seq_iter); + DPRINTF("Completed load of VM with exit code %d seq iteration " + "%" PRIu64 "\n", ret, seq_iter); return ret; } From 987a9b4800003567b1a47a379255e886a77d57ea Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 9 Aug 2012 16:45:55 +0200 Subject: [PATCH 0374/2270] net: notify iothread after flushing queue virtio-net has code to flush the queue and notify the iothread whenever new receive buffers are added by the guest. That is fine, and indeed we need to do the same in all other drivers. However, notifying the iothread should be work for the network subsystem. And since we are at it we can add a little smartness: if some of the queued packets already could not be delivered, there is no need to notify the iothread. Reported-by: Luigi Rizzo Cc: Stefan Hajnoczi Cc: Jan Kiszka Signed-off-by: Paolo Bonzini Reviewed-by: Amos Kong Signed-off-by: Stefan Hajnoczi --- hw/virtio-net.c | 4 ---- net.c | 7 ++++++- net/queue.c | 5 +++-- net/queue.h | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index b1998b27d3..6490743290 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -447,10 +447,6 @@ static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq) VirtIONet *n = to_virtio_net(vdev); qemu_flush_queued_packets(&n->nic->nc); - - /* We now have RX buffers, signal to the IO thread to break out of the - * select to re-poll the tap file descriptor */ - qemu_notify_event(); } static int virtio_net_can_receive(NetClientState *nc) diff --git a/net.c b/net.c index e5d25d4b6d..d9ba1e5b74 100644 --- a/net.c +++ b/net.c @@ -357,7 +357,12 @@ void qemu_flush_queued_packets(NetClientState *nc) { nc->receive_disabled = 0; - qemu_net_queue_flush(nc->send_queue); + if (qemu_net_queue_flush(nc->send_queue)) { + /* We emptied the queue successfully, signal to the IO thread to repoll + * the file descriptor (for tap, for example). + */ + qemu_notify_event(); + } } static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender, diff --git a/net/queue.c b/net/queue.c index e8030aafe4..6e64091463 100644 --- a/net/queue.c +++ b/net/queue.c @@ -228,7 +228,7 @@ void qemu_net_queue_purge(NetQueue *queue, NetClientState *from) } } -void qemu_net_queue_flush(NetQueue *queue) +bool qemu_net_queue_flush(NetQueue *queue) { while (!QTAILQ_EMPTY(&queue->packets)) { NetPacket *packet; @@ -244,7 +244,7 @@ void qemu_net_queue_flush(NetQueue *queue) packet->size); if (ret == 0) { QTAILQ_INSERT_HEAD(&queue->packets, packet, entry); - break; + return false; } if (packet->sent_cb) { @@ -253,4 +253,5 @@ void qemu_net_queue_flush(NetQueue *queue) g_free(packet); } + return true; } diff --git a/net/queue.h b/net/queue.h index 9d44a9b3b8..fc02b33915 100644 --- a/net/queue.h +++ b/net/queue.h @@ -53,6 +53,6 @@ ssize_t qemu_net_queue_send_iov(NetQueue *queue, NetPacketSent *sent_cb); void qemu_net_queue_purge(NetQueue *queue, NetClientState *from); -void qemu_net_queue_flush(NetQueue *queue); +bool qemu_net_queue_flush(NetQueue *queue); #endif /* QEMU_NET_QUEUE_H */ From e8b4c680b41bd960ecccd9ff076b7b058e0afcd4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 9 Aug 2012 16:45:56 +0200 Subject: [PATCH 0375/2270] e1000: flush queue whenever can_receive can go from false to true When the guests replenish the receive ring buffer, the network device should flush its queue of pending packets. This is done with qemu_flush_queued_packets. e1000's can_receive can go from false to true when RCTL or RDT are modified. Reported-by: Luigi Rizzo Cc: Stefan Hajnoczi Cc: Jan Kiszka Signed-off-by: Paolo Bonzini Reviewed-by: Amos Kong Signed-off-by: Stefan Hajnoczi --- hw/e1000.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/e1000.c b/hw/e1000.c index ae8a6c5523..ec3a7c4ecc 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -295,6 +295,7 @@ set_rx_control(E1000State *s, int index, uint32_t val) s->rxbuf_min_shift = ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1; DBGOUT(RX, "RCTL: %d, mac_reg[RCTL] = 0x%x\n", s->mac_reg[RDT], s->mac_reg[RCTL]); + qemu_flush_queued_packets(&s->nic->nc); } static void @@ -926,6 +927,9 @@ set_rdt(E1000State *s, int index, uint32_t val) { s->check_rxov = 0; s->mac_reg[index] = val & 0xffff; + if (e1000_has_rxbufs(s, 1)) { + qemu_flush_queued_packets(&s->nic->nc); + } } static void From a98b140223d3a627eab7ee3ddec645bab630d756 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 9 Aug 2012 16:45:57 +0200 Subject: [PATCH 0376/2270] xen: flush queue when getting an event xen does not have a register that, when written, will cause can_receive to go from false to true. However, flushing the queue can be attempted whenever the front-end raises its side of the Xen event channel. There is a single event channel for tx and rx. Cc: Stefano Stabellini Cc: Stefan Hajnoczi Signed-off-by: Paolo Bonzini Reviewed-by: Amos Kong Signed-off-by: Stefan Hajnoczi --- hw/xen_nic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/xen_nic.c b/hw/xen_nic.c index 8b79bfb73e..cf7d5591b3 100644 --- a/hw/xen_nic.c +++ b/hw/xen_nic.c @@ -415,6 +415,7 @@ static void net_event(struct XenDevice *xendev) { struct XenNetDev *netdev = container_of(xendev, struct XenNetDev, xendev); net_tx_packets(netdev); + qemu_flush_queued_packets(&netdev->nic->nc); } static int net_free(struct XenDevice *xendev) From 1069985fb132cd4324fc02d371f1e61492a1823f Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Wed, 29 Aug 2012 19:26:11 +0800 Subject: [PATCH 0377/2270] eepro100: Fix network hang when rx buffers run out This is reported by QA. When installing os with pxe, after the initial kernel and initrd are loaded, the procedure tries to copy files from install server to local harddisk, the network becomes stall because of running out of receive descriptor. [Whitespace fixes and removed qemu_notify_event() because Paolo's earlier net patches have moved it into qemu_flush_queued_packets(). Additional info: I can reproduce the network hang with a tap device doing a iPXE HTTP boot as follows: $ qemu -enable-kvm -m 1024 \ -netdev tap,id=netdev0,script=no,downscript=no \ -device i82559er,netdev=netdev0,romfile=80861209.rom \ -drive if=virtio,cache=none,file=test.img iPXE> ifopen net0 iPXE> config # set static network configuration iPXE> kernel http://mirror.bytemark.co.uk/fedora/linux/releases/17/Fedora/x86_64/os/images/pxeboot/vmlinuz I needed a vanilla iPXE ROM to get to the iPXE prompt. I think the boot prompt has been disabled in the ROMs that ship with QEMU to reduce boot time. During the vmlinuz HTTP download there is a network hang. hw/eepro100.c has reached the end of the rx descriptor list. When the iPXE driver replenishes the rx descriptor list we don't kick the QEMU net subsystem and event loop, thereby leaving the tap netdev without its file descriptor in select(2). Stefan Hajnoczi ] Signed-off-by: Bo Yang Signed-off-by: Stefan Hajnoczi --- hw/eepro100.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/eepro100.c b/hw/eepro100.c index 50d117e35e..5b231163d8 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -1036,6 +1036,7 @@ static void eepro100_ru_command(EEPRO100State * s, uint8_t val) } set_ru_state(s, ru_ready); s->ru_offset = e100_read_reg4(s, SCBPointer); + qemu_flush_queued_packets(&s->nic->nc); TRACE(OTHER, logout("val=0x%02x (rx start)\n", val)); break; case RX_RESUME: @@ -1770,7 +1771,8 @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size) if (rfd_command & COMMAND_EL) { /* EL bit is set, so this was the last frame. */ logout("receive: Running out of frames\n"); - set_ru_state(s, ru_suspended); + set_ru_state(s, ru_no_resources); + eepro100_rnr_interrupt(s); } if (rfd_command & COMMAND_S) { /* S bit is set. */ From c67f5dc10573687497f0f5c3aec19b15c35c63d7 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 17 Aug 2012 21:16:42 +0100 Subject: [PATCH 0378/2270] net: add receive_disabled logic to iov delivery path This patch adds the missing NetClient->receive_disabled logic in the sendv delivery code path. It seems that commit 893379efd0e1b84ceb0c42a713293f3dbd27b1bd ("net: disable receiving if client returns zero") only added the logic to qemu_deliver_packet() and not qemu_deliver_packet_iov(). The receive_disabled flag should be automatically set when .receive(), .receive_raw(), or .receive_iov() return 0. No further packets will be delivered to the NetClient until the receive_disabled flag is cleared again by calling qemu_flush_queued_packets(). Typically the NetClient will wait until its file descriptor becomes writable and then invoke qemu_flush_queued_packets() to resume transmission. Signed-off-by: Stefan Hajnoczi --- net.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/net.c b/net.c index d9ba1e5b74..a187a7b3db 100644 --- a/net.c +++ b/net.c @@ -423,16 +423,27 @@ ssize_t qemu_deliver_packet_iov(NetClientState *sender, void *opaque) { NetClientState *nc = opaque; + int ret; if (nc->link_down) { return iov_size(iov, iovcnt); } - if (nc->info->receive_iov) { - return nc->info->receive_iov(nc, iov, iovcnt); - } else { - return nc_sendv_compat(nc, iov, iovcnt); + if (nc->receive_disabled) { + return 0; } + + if (nc->info->receive_iov) { + ret = nc->info->receive_iov(nc, iov, iovcnt); + } else { + ret = nc_sendv_compat(nc, iov, iovcnt); + } + + if (ret == 0) { + nc->receive_disabled = 1; + } + + return ret; } ssize_t qemu_sendv_packet_async(NetClientState *sender, From 06b5f36d052b540a59b52150582d65674199b2ce Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 20 Aug 2012 13:35:23 +0100 Subject: [PATCH 0379/2270] net: do not report queued packets as sent Net send functions have a return value where 0 means the packet has not been sent and will be queued. A non-zero value means the packet was sent or an error caused the packet to be dropped. This patch fixes two instances where packets are queued but we return their size. This causes callers to believe the packets were sent. When the caller uses the async send interface this creates a real problem because the callback will be invoked for a packet that the caller believed to be already sent. This bug can cause double-frees in the caller. Signed-off-by: Stefan Hajnoczi --- net/queue.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/net/queue.c b/net/queue.c index 6e64091463..254f28013a 100644 --- a/net/queue.c +++ b/net/queue.c @@ -83,12 +83,12 @@ void qemu_del_net_queue(NetQueue *queue) g_free(queue); } -static ssize_t qemu_net_queue_append(NetQueue *queue, - NetClientState *sender, - unsigned flags, - const uint8_t *buf, - size_t size, - NetPacketSent *sent_cb) +static void qemu_net_queue_append(NetQueue *queue, + NetClientState *sender, + unsigned flags, + const uint8_t *buf, + size_t size, + NetPacketSent *sent_cb) { NetPacket *packet; @@ -100,16 +100,14 @@ static ssize_t qemu_net_queue_append(NetQueue *queue, memcpy(packet->data, buf, size); QTAILQ_INSERT_TAIL(&queue->packets, packet, entry); - - return size; } -static ssize_t qemu_net_queue_append_iov(NetQueue *queue, - NetClientState *sender, - unsigned flags, - const struct iovec *iov, - int iovcnt, - NetPacketSent *sent_cb) +static void qemu_net_queue_append_iov(NetQueue *queue, + NetClientState *sender, + unsigned flags, + const struct iovec *iov, + int iovcnt, + NetPacketSent *sent_cb) { NetPacket *packet; size_t max_len = 0; @@ -133,8 +131,6 @@ static ssize_t qemu_net_queue_append_iov(NetQueue *queue, } QTAILQ_INSERT_TAIL(&queue->packets, packet, entry); - - return packet->size; } static ssize_t qemu_net_queue_deliver(NetQueue *queue, @@ -177,7 +173,8 @@ ssize_t qemu_net_queue_send(NetQueue *queue, ssize_t ret; if (queue->delivering || !qemu_can_send_packet(sender)) { - return qemu_net_queue_append(queue, sender, flags, data, size, sent_cb); + qemu_net_queue_append(queue, sender, flags, data, size, sent_cb); + return 0; } ret = qemu_net_queue_deliver(queue, sender, flags, data, size); @@ -201,8 +198,8 @@ ssize_t qemu_net_queue_send_iov(NetQueue *queue, ssize_t ret; if (queue->delivering || !qemu_can_send_packet(sender)) { - return qemu_net_queue_append_iov(queue, sender, flags, - iov, iovcnt, sent_cb); + qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt, sent_cb); + return 0; } ret = qemu_net_queue_deliver_iov(queue, sender, flags, iov, iovcnt); From 08d12022c7f1aba6acccc75150659c6e4c9dff23 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 14 Aug 2012 14:14:27 +0100 Subject: [PATCH 0380/2270] net: add -netdev options to man page Document the -netdev syntax which supercedes the older -net syntax. This patch is a first step to making -netdev prominent in the QEMU manual. Reported-by: Anatoly Techtonik Signed-off-by: Stefan Hajnoczi --- qemu-options.hx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/qemu-options.hx b/qemu-options.hx index 804a2d1739..0977b3f783 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1357,6 +1357,7 @@ Valid values for @var{type} are Not all devices are supported on all targets. Use -net nic,model=? for a list of available devices for your target. +@item -netdev user,id=@var{id}[,@var{option}][,@var{option}][,...] @item -net user[,@var{option}][,@var{option}][,...] Use the user mode network stack which requires no administrator privilege to run. Valid options are: @@ -1365,6 +1366,7 @@ privilege to run. Valid options are: @item vlan=@var{n} Connect user mode stack to VLAN @var{n} (@var{n} = 0 is the default). +@item id=@var{id} @item name=@var{name} Assign symbolic name for use in monitor commands. @@ -1490,6 +1492,7 @@ processed and applied to -net user. Mixing them with the new configuration syntax gives undefined results. Their use for new applications is discouraged as they will be removed from future versions. +@item -netdev tap,id=@var{id}[,fd=@var{h}][,ifname=@var{name}][,script=@var{file}][,downscript=@var{dfile}][,helper=@var{helper}] @item -net tap[,vlan=@var{n}][,name=@var{name}][,fd=@var{h}][,ifname=@var{name}][,script=@var{file}][,downscript=@var{dfile}][,helper=@var{helper}] Connect the host TAP network interface @var{name} to VLAN @var{n}. @@ -1529,6 +1532,7 @@ qemu-system-i386 linux.img \ -net nic -net tap,"helper=/usr/local/libexec/qemu-bridge-helper" @end example +@item -netdev bridge,id=@var{id}[,br=@var{bridge}][,helper=@var{helper}] @item -net bridge[,vlan=@var{n}][,name=@var{name}][,br=@var{bridge}][,helper=@var{helper}] Connect a host TAP network interface to a host bridge device. @@ -1551,6 +1555,7 @@ qemu-system-i386 linux.img -net bridge -net nic,model=virtio qemu-system-i386 linux.img -net bridge,br=qemubr0 -net nic,model=virtio @end example +@item -netdev socket,id=@var{id}[,fd=@var{h}][,listen=[@var{host}]:@var{port}][,connect=@var{host}:@var{port}] @item -net socket[,vlan=@var{n}][,name=@var{name}][,fd=@var{h}] [,listen=[@var{host}]:@var{port}][,connect=@var{host}:@var{port}] Connect the VLAN @var{n} to a remote VLAN in another QEMU virtual @@ -1573,6 +1578,7 @@ qemu-system-i386 linux.img \ -net socket,connect=127.0.0.1:1234 @end example +@item -netdev socket,id=@var{id}[,fd=@var{h}][,mcast=@var{maddr}:@var{port}[,localaddr=@var{addr}]] @item -net socket[,vlan=@var{n}][,name=@var{name}][,fd=@var{h}][,mcast=@var{maddr}:@var{port}[,localaddr=@var{addr}]] Create a VLAN @var{n} shared with another QEMU virtual @@ -1624,6 +1630,7 @@ qemu-system-i386 linux.img \ -net socket,mcast=239.192.168.1:1102,localaddr=1.2.3.4 @end example +@item -netdev vde,id=@var{id}[,sock=@var{socketpath}][,port=@var{n}][,group=@var{groupname}][,mode=@var{octalmode}] @item -net vde[,vlan=@var{n}][,name=@var{name}][,sock=@var{socketpath}] [,port=@var{n}][,group=@var{groupname}][,mode=@var{octalmode}] Connect VLAN @var{n} to PORT @var{n} of a vde switch running on host and listening for incoming connections on @var{socketpath}. Use GROUP @var{groupname} From f237ddbb89142c6948a2257c459e49dee7500a7c Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 24 Aug 2012 13:32:16 +0100 Subject: [PATCH 0381/2270] net: clean up usbnet_receive() The USB network interface has two code paths depending on whether or not RNDIS mode is enabled. Refactor usbnet_receive() so that there is a common path throughout the function instead of duplicating everything across if (is_rndis(s)) ... else ... code paths. Clean up coding style and 80 character line wrap along the way. Signed-off-by: Stefan Hajnoczi --- hw/usb/dev-network.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index c84892c98d..0b5cb71f98 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -1250,20 +1250,27 @@ static int usb_net_handle_data(USBDevice *dev, USBPacket *p) static ssize_t usbnet_receive(NetClientState *nc, const uint8_t *buf, size_t size) { USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque; - struct rndis_packet_msg_type *msg; + uint8_t *in_buf = s->in_buf; + size_t total_size = size; if (is_rndis(s)) { - msg = (struct rndis_packet_msg_type *) s->in_buf; if (s->rndis_state != RNDIS_DATA_INITIALIZED) { return -1; } - if (size + sizeof(struct rndis_packet_msg_type) > sizeof(s->in_buf)) - return -1; + total_size += sizeof(struct rndis_packet_msg_type); + } + if (total_size > sizeof(s->in_buf)) { + return -1; + } + if (is_rndis(s)) { + struct rndis_packet_msg_type *msg; + + msg = (struct rndis_packet_msg_type *)in_buf; memset(msg, 0, sizeof(struct rndis_packet_msg_type)); msg->MessageType = cpu_to_le32(RNDIS_PACKET_MSG); - msg->MessageLength = cpu_to_le32(size + sizeof(struct rndis_packet_msg_type)); - msg->DataOffset = cpu_to_le32(sizeof(struct rndis_packet_msg_type) - 8); + msg->MessageLength = cpu_to_le32(size + sizeof(*msg)); + msg->DataOffset = cpu_to_le32(sizeof(*msg) - 8); msg->DataLength = cpu_to_le32(size); /* msg->OOBDataOffset; * msg->OOBDataLength; @@ -1273,14 +1280,11 @@ static ssize_t usbnet_receive(NetClientState *nc, const uint8_t *buf, size_t siz * msg->VcHandle; * msg->Reserved; */ - memcpy(msg + 1, buf, size); - s->in_len = size + sizeof(struct rndis_packet_msg_type); - } else { - if (size > sizeof(s->in_buf)) - return -1; - memcpy(s->in_buf, buf, size); - s->in_len = size; + in_buf += sizeof(*msg); } + + memcpy(in_buf, buf, size); + s->in_len = total_size; s->in_ptr = 0; return size; } From 190563f9a90c9df8ad32fc7f3e4b166deda949a6 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 24 Aug 2012 13:37:29 +0100 Subject: [PATCH 0382/2270] net: fix usbnet_receive() packet drops The USB network interface has a single buffer which the guest reads from. This patch prevents multiple calls to usbnet_receive() from clobbering the input buffer. Instead we queue packets until buffer space becomes available again. This is inspired by virtio-net and e1000 rxbuf handling. Signed-off-by: Stefan Hajnoczi --- hw/usb/dev-network.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 0b5cb71f98..e4a43599b5 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -1001,6 +1001,13 @@ static int rndis_keepalive_response(USBNetState *s, return 0; } +/* Prepare to receive the next packet */ +static void usb_net_reset_in_buf(USBNetState *s) +{ + s->in_ptr = s->in_len = 0; + qemu_flush_queued_packets(&s->nic->nc); +} + static int rndis_parse(USBNetState *s, uint8_t *data, int length) { uint32_t msg_type; @@ -1025,7 +1032,8 @@ static int rndis_parse(USBNetState *s, uint8_t *data, int length) case RNDIS_RESET_MSG: rndis_clear_responsequeue(s); - s->out_ptr = s->in_ptr = s->in_len = 0; + s->out_ptr = 0; + usb_net_reset_in_buf(s); return rndis_reset_response(s, (rndis_reset_msg_type *) data); case RNDIS_KEEPALIVE_MSG: @@ -1135,7 +1143,7 @@ static int usb_net_handle_datain(USBNetState *s, USBPacket *p) int ret = USB_RET_NAK; if (s->in_ptr > s->in_len) { - s->in_ptr = s->in_len = 0; + usb_net_reset_in_buf(s); ret = USB_RET_NAK; return ret; } @@ -1152,7 +1160,7 @@ static int usb_net_handle_datain(USBNetState *s, USBPacket *p) if (s->in_ptr >= s->in_len && (is_rndis(s) || (s->in_len & (64 - 1)) || !ret)) { /* no short packet necessary */ - s->in_ptr = s->in_len = 0; + usb_net_reset_in_buf(s); } #ifdef TRAFFIC_DEBUG @@ -1263,6 +1271,11 @@ static ssize_t usbnet_receive(NetClientState *nc, const uint8_t *buf, size_t siz return -1; } + /* Only accept packet if input buffer is empty */ + if (s->in_len > 0) { + return 0; + } + if (is_rndis(s)) { struct rndis_packet_msg_type *msg; From 61518a74ca98870e8ff132f91dd5dda252e31f58 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 24 Aug 2012 13:50:30 +0100 Subject: [PATCH 0383/2270] net: broadcast hub packets if at least one port can receive In commit 60c07d933c66c4b30a83b7ccbc8a0cb3df1b2d0e ("net: fix qemu_can_send_packet logic") the "VLAN" broadcast behavior was changed to queue packets if any net client cannot receive. It turns out that this was not actually the right fix and just hides the real bug that hw/usb/dev-network.c:usbnet_receive() clobbers its receive buffer when called multiple times in a row. The commit also introduced a new bug that "VLAN" packets would not be sent if one of multiple net clients was down. The hw/usb/dev-network.c bug has since been fixed, so this patch reverts broadcast behavior to send packets as long as one net client can receive. Packets simply get queued for the net clients that are temporarily unable to receive. Reported-by: Roy.Li Signed-off-by: Stefan Hajnoczi --- net/hub.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/hub.c b/net/hub.c index ac157e32ee..650a8b4a40 100644 --- a/net/hub.c +++ b/net/hub.c @@ -97,12 +97,12 @@ static int net_hub_port_can_receive(NetClientState *nc) continue; } - if (!qemu_can_send_packet(&port->nc)) { - return 0; + if (qemu_can_send_packet(&port->nc)) { + return 1; } } - return 1; + return 0; } static ssize_t net_hub_port_receive(NetClientState *nc, From 863f678fba4191f3b695620f41056cb7c124425d Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 20 Aug 2012 10:21:54 +0100 Subject: [PATCH 0384/2270] net: asynchronous send/receive infrastructure for net/socket.c The net/socket.c net client is not truly asynchronous. This patch borrows the qemu_set_fd_handler2() code from net/tap.c as the basis for proper asynchronous send/receive. Only read packets from the socket when the peer is able to receive. This avoids needless queuing. Later patches implement asynchronous send. Signed-off-by: Stefan Hajnoczi --- net/socket.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/net/socket.c b/net/socket.c index 7c602e4c3a..7bff5367ac 100644 --- a/net/socket.c +++ b/net/socket.c @@ -42,9 +42,51 @@ typedef struct NetSocketState { unsigned int packet_len; uint8_t buf[4096]; struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */ + IOHandler *send_fn; /* differs between SOCK_STREAM/SOCK_DGRAM */ + bool read_poll; /* waiting to receive data? */ + bool write_poll; /* waiting to transmit data? */ } NetSocketState; static void net_socket_accept(void *opaque); +static void net_socket_writable(void *opaque); + +/* Only read packets from socket when peer can receive them */ +static int net_socket_can_send(void *opaque) +{ + NetSocketState *s = opaque; + + return qemu_can_send_packet(&s->nc); +} + +static void net_socket_update_fd_handler(NetSocketState *s) +{ + qemu_set_fd_handler2(s->fd, + s->read_poll ? net_socket_can_send : NULL, + s->read_poll ? s->send_fn : NULL, + s->write_poll ? net_socket_writable : NULL, + s); +} + +static void net_socket_read_poll(NetSocketState *s, bool enable) +{ + s->read_poll = enable; + net_socket_update_fd_handler(s); +} + +static void net_socket_write_poll(NetSocketState *s, bool enable) +{ + s->write_poll = enable; + net_socket_update_fd_handler(s); +} + +static void net_socket_writable(void *opaque) +{ + NetSocketState *s = opaque; + + net_socket_write_poll(s, false); + + qemu_flush_queued_packets(&s->nc); +} /* XXX: we consider we can send the whole packet without blocking */ static ssize_t net_socket_receive(NetClientState *nc, const uint8_t *buf, size_t size) @@ -81,7 +123,8 @@ static void net_socket_send(void *opaque) } else if (size == 0) { /* end of connection */ eoc: - qemu_set_fd_handler(s->fd, NULL, NULL, NULL); + net_socket_read_poll(s, false); + net_socket_write_poll(s, false); if (s->listen_fd != -1) { qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s); } @@ -152,7 +195,8 @@ static void net_socket_send_dgram(void *opaque) return; if (size == 0) { /* end of connection */ - qemu_set_fd_handler(s->fd, NULL, NULL, NULL); + net_socket_read_poll(s, false); + net_socket_write_poll(s, false); return; } qemu_send_packet(&s->nc, s->buf, size); @@ -243,7 +287,8 @@ static void net_socket_cleanup(NetClientState *nc) { NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); if (s->fd != -1) { - qemu_set_fd_handler(s->fd, NULL, NULL, NULL); + net_socket_read_poll(s, false); + net_socket_write_poll(s, false); close(s->fd); s->fd = -1; } @@ -314,8 +359,8 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer, s->fd = fd; s->listen_fd = -1; - - qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s); + s->send_fn = net_socket_send_dgram; + net_socket_read_poll(s, true); /* mcast: save bound address as dst */ if (is_connected) { @@ -332,7 +377,8 @@ err: static void net_socket_connect(void *opaque) { NetSocketState *s = opaque; - qemu_set_fd_handler(s->fd, net_socket_send, NULL, s); + s->send_fn = net_socket_send; + net_socket_read_poll(s, true); } static NetClientInfo net_socket_info = { From 213fd5087e2e4e2da10ad266df0ba950cf7618bf Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 20 Aug 2012 10:28:53 +0100 Subject: [PATCH 0385/2270] net: EAGAIN handling for net/socket.c UDP Implement asynchronous send for UDP (or other SOCK_DGRAM) sockets. If send fails with EAGAIN we wait for the socket to become writable again. Signed-off-by: Stefan Hajnoczi --- net/socket.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/net/socket.c b/net/socket.c index 7bff5367ac..aabf0a48c5 100644 --- a/net/socket.c +++ b/net/socket.c @@ -102,9 +102,19 @@ static ssize_t net_socket_receive(NetClientState *nc, const uint8_t *buf, size_t static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf, size_t size) { NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); + ssize_t ret; - return sendto(s->fd, (const void *)buf, size, 0, - (struct sockaddr *)&s->dgram_dst, sizeof(s->dgram_dst)); + do { + ret = sendto(s->fd, buf, size, 0, + (struct sockaddr *)&s->dgram_dst, + sizeof(s->dgram_dst)); + } while (ret == -1 && errno == EINTR); + + if (ret == -1 && errno == EAGAIN) { + net_socket_write_poll(s, true); + return 0; + } + return ret; } static void net_socket_send(void *opaque) From 45a7f54a8bb3928ffa58d522e0d61acaee8277bb Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 20 Aug 2012 10:14:35 +0100 Subject: [PATCH 0386/2270] net: EAGAIN handling for net/socket.c TCP Replace spinning send_all() with a proper non-blocking send. When the socket write buffer limit is reached, we should stop trying to send and wait for the socket to become writable again. Non-blocking TCP sockets can return in two different ways when the write buffer limit is reached: 1. ret = -1 and errno = EAGAIN/EWOULDBLOCK. No data has been written. 2. ret < total_size. Short write, only part of the message was transmitted. Handle both cases and keep track of how many bytes have been written in s->send_index. (This includes the 'length' header before the actual payload buffer.) Signed-off-by: Stefan Hajnoczi --- net/socket.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/net/socket.c b/net/socket.c index aabf0a48c5..5e0c92e062 100644 --- a/net/socket.c +++ b/net/socket.c @@ -32,6 +32,7 @@ #include "qemu-error.h" #include "qemu-option.h" #include "qemu_socket.h" +#include "iov.h" typedef struct NetSocketState { NetClientState nc; @@ -40,6 +41,7 @@ typedef struct NetSocketState { int state; /* 0 = getting length, 1 = getting data */ unsigned int index; unsigned int packet_len; + unsigned int send_index; /* number of bytes sent (only SOCK_STREAM) */ uint8_t buf[4096]; struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */ IOHandler *send_fn; /* differs between SOCK_STREAM/SOCK_DGRAM */ @@ -88,15 +90,39 @@ static void net_socket_writable(void *opaque) qemu_flush_queued_packets(&s->nc); } -/* XXX: we consider we can send the whole packet without blocking */ static ssize_t net_socket_receive(NetClientState *nc, const uint8_t *buf, size_t size) { NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); - uint32_t len; - len = htonl(size); + uint32_t len = htonl(size); + struct iovec iov[] = { + { + .iov_base = &len, + .iov_len = sizeof(len), + }, { + .iov_base = (void *)buf, + .iov_len = size, + }, + }; + size_t remaining; + ssize_t ret; - send_all(s->fd, (const uint8_t *)&len, sizeof(len)); - return send_all(s->fd, buf, size); + remaining = iov_size(iov, 2) - s->send_index; + ret = iov_send(s->fd, iov, 2, s->send_index, remaining); + + if (ret == -1 && errno == EAGAIN) { + ret = 0; /* handled further down */ + } + if (ret == -1) { + s->send_index = 0; + return -errno; + } + if (ret < (ssize_t)remaining) { + s->send_index += ret; + net_socket_write_poll(s, true); + return 0; + } + s->send_index = 0; + return size; } static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf, size_t size) From e84d5956cc6215d2f098e7b6090fc5ec4cba1be3 Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN" Date: Thu, 6 Sep 2012 22:40:30 +0200 Subject: [PATCH 0387/2270] configure: fix seccomp check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, if libseccomp is missing but the user explicitly requested seccomp support using --enable-seccomp, configure silently ignores the situation and disables seccomp support. This is unlike all other tests that explicitly fail in such situation. Fix that. Signed-off-by: "Yann E. MORIN" Reviewed-by: Andreas Färber Signed-off-by: Stefan Hajnoczi --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 7656c32b24..92c4076c3f 100755 --- a/configure +++ b/configure @@ -1431,10 +1431,10 @@ if test "$seccomp" != "no" ; then LIBS=`$pkg_config --libs libseccomp` seccomp="yes" else - seccomp="no" if test "$seccomp" = "yes"; then feature_not_found "libseccomp" fi + seccomp="no" fi fi ########################################## From 3cebc3f11d8d74eb87dc02e712629c45e689960b Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 12 Sep 2012 19:18:55 +0200 Subject: [PATCH 0388/2270] tcg: Fix MAX_OPC_PARAM_IARGS DEF_HELPER_FLAGS_5 was added some time ago without adjusting MAX_OPC_PARAM_IARGS. Fixing the definition becomes more important as QEMU is using an increasing number of helper functions called with 5 arguments. Add also a comment to avoid future problems when DEF_HELPER_FLAGS_6 will be added. Signed-off-by: Stefan Weil Reviewed-by: Richard Henderson Signed-off-by: Blue Swirl --- def-helper.h | 2 ++ exec-all.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/def-helper.h b/def-helper.h index b98ff69e4e..022a9ceb6a 100644 --- a/def-helper.h +++ b/def-helper.h @@ -128,6 +128,8 @@ #define DEF_HELPER_5(name, ret, t1, t2, t3, t4, t5) \ DEF_HELPER_FLAGS_5(name, 0, ret, t1, t2, t3, t4, t5) +/* MAX_OPC_PARAM_IARGS must be set to n if last entry is DEF_HELPER_FLAGS_n. */ + #endif /* DEF_HELPER_H */ #ifndef GEN_HELPER diff --git a/exec-all.h b/exec-all.h index c5ec8e1158..4f4fafc05a 100644 --- a/exec-all.h +++ b/exec-all.h @@ -51,7 +51,7 @@ typedef struct TranslationBlock TranslationBlock; #else #define MAX_OPC_PARAM_PER_ARG 1 #endif -#define MAX_OPC_PARAM_IARGS 4 +#define MAX_OPC_PARAM_IARGS 5 #define MAX_OPC_PARAM_OARGS 1 #define MAX_OPC_PARAM_ARGS (MAX_OPC_PARAM_IARGS + MAX_OPC_PARAM_OARGS) From 8bacde8d86a09699207d85d4bab06162aed18dc4 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Wed, 12 Sep 2012 09:06:51 +0000 Subject: [PATCH 0389/2270] configure: properly check if -lrt and -lm is needed Fixes build against uClibc. uClibc provides 2 versions of clock_gettime(), one with realtime support and one without (this is so you can avoid linking in -lrt unless actually needed). This means that the clock_gettime() don't need -lrt. We still need it for timer_create() so we check for this function in addition. We also need check if -lm is needed for isnan(). Both -lm and -lrt are needed for libs_qga. Signed-off-by: Natanael Copa Signed-off-by: Blue Swirl --- configure | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 7656c32b24..9ab13db6f9 100755 --- a/configure +++ b/configure @@ -2670,18 +2670,45 @@ EOF fi +########################################## +# Do we need libm +cat > $TMPC << EOF +#include +int main(void) { return isnan(sin(0.0)); } +EOF +if compile_prog "" "" ; then + : +elif compile_prog "" "-lm" ; then + LIBS="-lm $LIBS" + libs_qga="-lm $libs_qga" +else + echo + echo "Error: libm check failed" + echo + exit 1 +fi + ########################################## # Do we need librt +# uClibc provides 2 versions of clock_gettime(), one with realtime +# support and one without. This means that the clock_gettime() don't +# need -lrt. We still need it for timer_create() so we check for this +# function in addition. cat > $TMPC < #include -int main(void) { return clock_gettime(CLOCK_REALTIME, NULL); } +int main(void) { + timer_create(CLOCK_REALTIME, NULL, NULL); + return clock_gettime(CLOCK_REALTIME, NULL); +} EOF if compile_prog "" "" ; then : -elif compile_prog "" "-lrt" ; then +# we need pthread for static linking. use previous pthread test result +elif compile_prog "" "-lrt $pthread_lib" ; then LIBS="-lrt $LIBS" + libs_qga="-lrt $libs_qga" fi if test "$darwin" != "yes" -a "$mingw32" != "yes" -a "$solaris" != yes -a \ From 46ee3d8455d4d67a1a9438a4b1f1e4ebf977d97b Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sat, 8 Sep 2012 11:15:37 +0000 Subject: [PATCH 0390/2270] target-s390x: avoid cpu_single_env Pass around CPUState instead of using global cpu_single_env. Signed-off-by: Blue Swirl --- target-s390x/translate.c | 356 ++++++++++++++++++++------------------- 1 file changed, 183 insertions(+), 173 deletions(-) diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 66119cd122..3214783aaa 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -274,21 +274,21 @@ static inline void potential_page_fault(DisasContext *s) #endif } -static inline uint64_t ld_code2(uint64_t pc) +static inline uint64_t ld_code2(CPUS390XState *env, uint64_t pc) { - return (uint64_t)cpu_lduw_code(cpu_single_env, pc); + return (uint64_t)cpu_lduw_code(env, pc); } -static inline uint64_t ld_code4(uint64_t pc) +static inline uint64_t ld_code4(CPUS390XState *env, uint64_t pc) { - return (uint64_t)cpu_ldl_code(cpu_single_env, pc); + return (uint64_t)cpu_ldl_code(env, pc); } -static inline uint64_t ld_code6(uint64_t pc) +static inline uint64_t ld_code6(CPUS390XState *env, uint64_t pc) { uint64_t opc; - opc = (uint64_t)cpu_lduw_code(cpu_single_env, pc) << 32; - opc |= (uint64_t)(uint32_t)cpu_ldl_code(cpu_single_env, pc + 2); + opc = (uint64_t)cpu_lduw_code(env, pc) << 32; + opc |= (uint64_t)(uint32_t)cpu_ldl_code(env, pc + 2); return opc; } @@ -319,7 +319,7 @@ static inline void gen_debug(DisasContext *s) #ifdef CONFIG_USER_ONLY -static void gen_illegal_opcode(DisasContext *s, int ilc) +static void gen_illegal_opcode(CPUS390XState *env, DisasContext *s, int ilc) { TCGv_i32 tmp = tcg_const_i32(EXCP_SPEC); update_psw_addr(s); @@ -331,20 +331,20 @@ static void gen_illegal_opcode(DisasContext *s, int ilc) #else /* CONFIG_USER_ONLY */ -static void debug_print_inst(DisasContext *s, int ilc) +static void debug_print_inst(CPUS390XState *env, DisasContext *s, int ilc) { #ifdef DEBUG_ILLEGAL_INSTRUCTIONS uint64_t inst = 0; switch (ilc & 3) { case 1: - inst = ld_code2(s->pc); + inst = ld_code2(env, s->pc); break; case 2: - inst = ld_code4(s->pc); + inst = ld_code4(env, s->pc); break; case 3: - inst = ld_code6(s->pc); + inst = ld_code6(env, s->pc); break; } @@ -353,11 +353,12 @@ static void debug_print_inst(DisasContext *s, int ilc) #endif } -static void gen_program_exception(DisasContext *s, int ilc, int code) +static void gen_program_exception(CPUS390XState *env, DisasContext *s, int ilc, + int code) { TCGv_i32 tmp; - debug_print_inst(s, ilc); + debug_print_inst(env, s, ilc); /* remember what pgm exeption this was */ tmp = tcg_const_i32(code); @@ -385,20 +386,21 @@ static void gen_program_exception(DisasContext *s, int ilc, int code) } -static void gen_illegal_opcode(DisasContext *s, int ilc) +static void gen_illegal_opcode(CPUS390XState *env, DisasContext *s, int ilc) { - gen_program_exception(s, ilc, PGM_SPECIFICATION); + gen_program_exception(env, s, ilc, PGM_SPECIFICATION); } -static void gen_privileged_exception(DisasContext *s, int ilc) +static void gen_privileged_exception(CPUS390XState *env, DisasContext *s, + int ilc) { - gen_program_exception(s, ilc, PGM_PRIVILEGED); + gen_program_exception(env, s, ilc, PGM_PRIVILEGED); } -static void check_privileged(DisasContext *s, int ilc) +static void check_privileged(CPUS390XState *env, DisasContext *s, int ilc) { if (s->tb->flags & (PSW_MASK_PSTATE >> 32)) { - gen_privileged_exception(s, ilc); + gen_privileged_exception(env, s, ilc); } } @@ -1460,7 +1462,8 @@ static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2) set_cc_static(s); } -static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2) +static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1, + int x2, int b2, int d2) { TCGv_i64 addr, tmp, tmp2, tmp3, tmp4; TCGv_i32 tmp32_1, tmp32_2, tmp32_3; @@ -1925,14 +1928,14 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2) break; default: LOG_DISAS("illegal e3 operation 0x%x\n", op); - gen_illegal_opcode(s, 3); + gen_illegal_opcode(env, s, 3); break; } tcg_temp_free_i64(addr); } #ifndef CONFIG_USER_ONLY -static void disas_e5(DisasContext* s, uint64_t insn) +static void disas_e5(CPUS390XState *env, DisasContext* s, uint64_t insn) { TCGv_i64 tmp, tmp2; int op = (insn >> 32) & 0xff; @@ -1950,7 +1953,7 @@ static void disas_e5(DisasContext* s, uint64_t insn) break; default: LOG_DISAS("illegal e5 operation 0x%x\n", op); - gen_illegal_opcode(s, 3); + gen_illegal_opcode(env, s, 3); break; } @@ -1959,7 +1962,8 @@ static void disas_e5(DisasContext* s, uint64_t insn) } #endif -static void disas_eb(DisasContext *s, int op, int r1, int r3, int b2, int d2) +static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1, + int r3, int b2, int d2) { TCGv_i64 tmp, tmp2, tmp3, tmp4; TCGv_i32 tmp32_1, tmp32_2; @@ -2102,7 +2106,7 @@ do_mh: #ifndef CONFIG_USER_ONLY case 0x2f: /* LCTLG R1,R3,D2(B2) [RSE] */ /* Load Control */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); tmp = get_address(s, 0, b2, d2); tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r3); @@ -2114,7 +2118,7 @@ do_mh: break; case 0x25: /* STCTG R1,R3,D2(B2) [RSE] */ /* Store Control */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); tmp = get_address(s, 0, b2, d2); tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r3); @@ -2191,13 +2195,13 @@ do_mh: break; default: LOG_DISAS("illegal eb operation 0x%x\n", op); - gen_illegal_opcode(s, ilc); + gen_illegal_opcode(env, s, ilc); break; } } -static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2, - int r1b) +static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1, + int x2, int b2, int d2, int r1b) { TCGv_i32 tmp_r1, tmp32; TCGv_i64 addr, tmp; @@ -2311,14 +2315,15 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2, break; default: LOG_DISAS("illegal ed operation 0x%x\n", op); - gen_illegal_opcode(s, 3); + gen_illegal_opcode(env, s, 3); return; } tcg_temp_free_i32(tmp_r1); tcg_temp_free_i64(addr); } -static void disas_a5(DisasContext *s, int op, int r1, int i2) +static void disas_a5(CPUS390XState *env, DisasContext *s, int op, int r1, + int i2) { TCGv_i64 tmp, tmp2; TCGv_i32 tmp32; @@ -2467,12 +2472,13 @@ static void disas_a5(DisasContext *s, int op, int r1, int i2) break; default: LOG_DISAS("illegal a5 operation 0x%x\n", op); - gen_illegal_opcode(s, 2); + gen_illegal_opcode(env, s, 2); return; } } -static void disas_a7(DisasContext *s, int op, int r1, int i2) +static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1, + int i2) { TCGv_i64 tmp, tmp2; TCGv_i32 tmp32_1, tmp32_2, tmp32_3; @@ -2604,12 +2610,13 @@ static void disas_a7(DisasContext *s, int op, int r1, int i2) break; default: LOG_DISAS("illegal a7 operation 0x%x\n", op); - gen_illegal_opcode(s, 2); + gen_illegal_opcode(env, s, 2); return; } } -static void disas_b2(DisasContext *s, int op, uint32_t insn) +static void disas_b2(CPUS390XState *env, DisasContext *s, int op, + uint32_t insn) { TCGv_i64 tmp, tmp2, tmp3; TCGv_i32 tmp32_1, tmp32_2, tmp32_3; @@ -2708,7 +2715,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) #ifndef CONFIG_USER_ONLY case 0x02: /* STIDP D2(B2) [S] */ /* Store CPU ID */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); @@ -2717,7 +2724,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x04: /* SCK D2(B2) [S] */ /* Set Clock */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); @@ -2736,7 +2743,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x06: /* SCKC D2(B2) [S] */ /* Set Clock Comparator */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); @@ -2745,7 +2752,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x07: /* STCKC D2(B2) [S] */ /* Store Clock Comparator */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); @@ -2754,7 +2761,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x08: /* SPT D2(B2) [S] */ /* Set CPU Timer */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); @@ -2763,7 +2770,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x09: /* STPT D2(B2) [S] */ /* Store CPU Timer */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); @@ -2772,7 +2779,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x0a: /* SPKA D2(B2) [S] */ /* Set PSW Key from Address */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp2 = tcg_temp_new_i64(); @@ -2784,12 +2791,12 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x0d: /* PTLB [S] */ /* Purge TLB */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); gen_helper_ptlb(cpu_env); break; case 0x10: /* SPX D2(B2) [S] */ /* Set Prefix Register */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); @@ -2798,7 +2805,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x11: /* STPX D2(B2) [S] */ /* Store Prefix */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp2 = tcg_temp_new_i64(); @@ -2809,7 +2816,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x12: /* STAP D2(B2) [S] */ /* Store CPU Address */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp2 = tcg_temp_new_i64(); @@ -2823,7 +2830,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x21: /* IPTE R1,R2 [RRE] */ /* Invalidate PTE */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); r1 = (insn >> 4) & 0xf; r2 = insn & 0xf; tmp = load_reg(r1); @@ -2834,7 +2841,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x29: /* ISKE R1,R2 [RRE] */ /* Insert Storage Key Extended */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); r1 = (insn >> 4) & 0xf; r2 = insn & 0xf; tmp = load_reg(r2); @@ -2846,7 +2853,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x2a: /* RRBE R1,R2 [RRE] */ /* Set Storage Key Extended */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); r1 = (insn >> 4) & 0xf; r2 = insn & 0xf; tmp32_1 = load_reg32(r1); @@ -2858,7 +2865,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x2b: /* SSKE R1,R2 [RRE] */ /* Set Storage Key Extended */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); r1 = (insn >> 4) & 0xf; r2 = insn & 0xf; tmp32_1 = load_reg32(r1); @@ -2869,12 +2876,12 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x34: /* STCH ? */ /* Store Subchannel */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); gen_op_movi_cc(s, 3); break; case 0x46: /* STURA R1,R2 [RRE] */ /* Store Using Real Address */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); r1 = (insn >> 4) & 0xf; r2 = insn & 0xf; tmp32_1 = load_reg32(r1); @@ -2886,7 +2893,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x50: /* CSP R1,R2 [RRE] */ /* Compare And Swap And Purge */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); r1 = (insn >> 4) & 0xf; r2 = insn & 0xf; tmp32_1 = tcg_const_i32(r1); @@ -2898,7 +2905,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x5f: /* CHSC ? */ /* Channel Subsystem Call */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); gen_op_movi_cc(s, 3); break; case 0x78: /* STCKE D2(B2) [S] */ @@ -2912,7 +2919,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x79: /* SACF D2(B2) [S] */ /* Store Clock Extended */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); potential_page_fault(s); @@ -2924,7 +2931,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) s->is_jmp = DISAS_EXCP; break; case 0x7d: /* STSI D2,(B2) [S] */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp32_1 = load_reg32(0); @@ -2950,7 +2957,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0xb1: /* STFL D2(B2) [S] */ /* Store Facility List (CPU features) at 200 */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); tmp2 = tcg_const_i64(0xc0000000); tmp = tcg_const_i64(200); tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s)); @@ -2959,7 +2966,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0xb2: /* LPSWE D2(B2) [S] */ /* Load PSW Extended */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp2 = tcg_temp_new_i64(); @@ -2976,7 +2983,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) break; case 0x20: /* SERVC R1,R2 [RRE] */ /* SCLP Service call (PV hypercall) */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); potential_page_fault(s); tmp32_1 = load_reg32(r2); tmp = load_reg(r1); @@ -2988,12 +2995,13 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) #endif default: LOG_DISAS("illegal b2 operation 0x%x\n", op); - gen_illegal_opcode(s, ilc); + gen_illegal_opcode(env, s, ilc); break; } } -static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2) +static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3, + int r1, int r2) { TCGv_i64 tmp; TCGv_i32 tmp32_1, tmp32_2, tmp32_3; @@ -3263,7 +3271,7 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2) break; default: LOG_DISAS("illegal b3 operation 0x%x\n", op); - gen_illegal_opcode(s, 2); + gen_illegal_opcode(env, s, 2); break; } @@ -3271,7 +3279,8 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2) #undef FP_HELPER } -static void disas_b9(DisasContext *s, int op, int r1, int r2) +static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1, + int r2) { TCGv_i64 tmp, tmp2, tmp3; TCGv_i32 tmp32_1, tmp32_2, tmp32_3; @@ -3654,12 +3663,12 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2) break; default: LOG_DISAS("illegal b9 operation 0x%x\n", op); - gen_illegal_opcode(s, 2); + gen_illegal_opcode(env, s, 2); break; } } -static void disas_c0(DisasContext *s, int op, int r1, int i2) +static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2) { TCGv_i64 tmp; TCGv_i32 tmp32_1, tmp32_2; @@ -3755,12 +3764,13 @@ static void disas_c0(DisasContext *s, int op, int r1, int i2) break; default: LOG_DISAS("illegal c0 operation 0x%x\n", op); - gen_illegal_opcode(s, 3); + gen_illegal_opcode(env, s, 3); break; } } -static void disas_c2(DisasContext *s, int op, int r1, int i2) +static void disas_c2(CPUS390XState *env, DisasContext *s, int op, int r1, + int i2) { TCGv_i64 tmp, tmp2, tmp3; TCGv_i32 tmp32_1, tmp32_2, tmp32_3; @@ -3832,7 +3842,7 @@ static void disas_c2(DisasContext *s, int op, int r1, int i2) break; default: LOG_DISAS("illegal c2 operation 0x%x\n", op); - gen_illegal_opcode(s, 3); + gen_illegal_opcode(env, s, 3); break; } } @@ -3854,7 +3864,7 @@ static void gen_and_or_xor_i32(int opc, TCGv_i32 tmp, TCGv_i32 tmp2) } } -static void disas_s390_insn(DisasContext *s) +static void disas_s390_insn(CPUS390XState *env, DisasContext *s) { TCGv_i64 tmp, tmp2, tmp3, tmp4; TCGv_i32 tmp32_1, tmp32_2, tmp32_3, tmp32_4; @@ -3865,7 +3875,7 @@ static void disas_s390_insn(DisasContext *s) int ilc; int l1; - opc = cpu_ldub_code(cpu_single_env, s->pc); + opc = cpu_ldub_code(env, s->pc); LOG_DISAS("opc 0x%x\n", opc); ilc = get_ilc(opc); @@ -3873,12 +3883,12 @@ static void disas_s390_insn(DisasContext *s) switch (opc) { #ifndef CONFIG_USER_ONLY case 0x01: /* SAM */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); /* set addressing mode, but we only do 64bit anyways */ break; #endif case 0x6: /* BCTR R1,R2 [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); tmp32_1 = load_reg32(r1); tcg_gen_subi_i32(tmp32_1, tmp32_1, 1); @@ -3904,7 +3914,7 @@ static void disas_s390_insn(DisasContext *s) } break; case 0x7: /* BCR M1,R2 [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); if (r2) { tmp = load_reg(r2); @@ -3916,7 +3926,7 @@ static void disas_s390_insn(DisasContext *s) } break; case 0xa: /* SVC I [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); debug_insn(insn); i = insn & 0xff; update_psw_addr(s); @@ -3933,7 +3943,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_3); break; case 0xd: /* BASR R1,R2 [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); tmp = tcg_const_i64(pc_to_link_info(s, s->pc + 2)); store_reg(r1, tmp); @@ -3946,7 +3956,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp); break; case 0xe: /* MVCL R1,R2 [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); tmp32_1 = tcg_const_i32(r1); tmp32_2 = tcg_const_i32(r2); @@ -3957,7 +3967,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_2); break; case 0x10: /* LPR R1,R2 [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); tmp32_1 = load_reg32(r2); set_cc_abs32(s, tmp32_1); @@ -3966,7 +3976,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_1); break; case 0x11: /* LNR R1,R2 [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); tmp32_1 = load_reg32(r2); set_cc_nabs32(s, tmp32_1); @@ -3975,7 +3985,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_1); break; case 0x12: /* LTR R1,R2 [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); tmp32_1 = load_reg32(r2); if (r1 != r2) { @@ -3985,7 +3995,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_1); break; case 0x13: /* LCR R1,R2 [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); tmp32_1 = load_reg32(r2); tcg_gen_neg_i32(tmp32_1, tmp32_1); @@ -3996,7 +4006,7 @@ static void disas_s390_insn(DisasContext *s) case 0x14: /* NR R1,R2 [RR] */ case 0x16: /* OR R1,R2 [RR] */ case 0x17: /* XR R1,R2 [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); tmp32_2 = load_reg32(r2); tmp32_1 = load_reg32(r1); @@ -4007,7 +4017,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_2); break; case 0x18: /* LR R1,R2 [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); tmp32_1 = load_reg32(r2); store_reg32(r1, tmp32_1); @@ -4015,7 +4025,7 @@ static void disas_s390_insn(DisasContext *s) break; case 0x15: /* CLR R1,R2 [RR] */ case 0x19: /* CR R1,R2 [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); tmp32_1 = load_reg32(r1); tmp32_2 = load_reg32(r2); @@ -4029,7 +4039,7 @@ static void disas_s390_insn(DisasContext *s) break; case 0x1a: /* AR R1,R2 [RR] */ case 0x1e: /* ALR R1,R2 [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); tmp32_1 = load_reg32(r1); tmp32_2 = load_reg32(r2); @@ -4047,7 +4057,7 @@ static void disas_s390_insn(DisasContext *s) break; case 0x1b: /* SR R1,R2 [RR] */ case 0x1f: /* SLR R1,R2 [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); tmp32_1 = load_reg32(r1); tmp32_2 = load_reg32(r2); @@ -4065,7 +4075,7 @@ static void disas_s390_insn(DisasContext *s) break; case 0x1c: /* MR R1,R2 [RR] */ /* reg(r1, r1+1) = reg(r1+1) * reg(r2) */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); tmp2 = load_reg(r2); tmp3 = load_reg((r1 + 1) & 15); @@ -4079,7 +4089,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp3); break; case 0x1d: /* DR R1,R2 [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); tmp32_1 = load_reg32(r1); tmp32_2 = load_reg32(r1 + 1); @@ -4114,21 +4124,21 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp3); break; case 0x28: /* LDR R1,R2 [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); tmp = load_freg(r2); store_freg(r1, tmp); tcg_temp_free_i64(tmp); break; case 0x38: /* LER R1,R2 [RR] */ - insn = ld_code2(s->pc); + insn = ld_code2(env, s->pc); decode_rr(s, insn, &r1, &r2); tmp32_1 = load_freg32(r2); store_freg32(r1, tmp32_1); tcg_temp_free_i32(tmp32_1); break; case 0x40: /* STH R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = load_reg(r1); tcg_gen_qemu_st16(tmp2, tmp, get_mem_index(s)); @@ -4136,13 +4146,13 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp2); break; case 0x41: /* la */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); store_reg(r1, tmp); /* FIXME: 31/24-bit addressing */ tcg_temp_free_i64(tmp); break; case 0x42: /* STC R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = load_reg(r1); tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s)); @@ -4150,7 +4160,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp2); break; case 0x43: /* IC R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = tcg_temp_new_i64(); tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s)); @@ -4159,7 +4169,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp2); break; case 0x44: /* EX R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = load_reg(r1); tmp3 = tcg_const_i64(s->pc + 4); @@ -4172,7 +4182,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp3); break; case 0x46: /* BCT R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tcg_temp_free_i64(tmp); @@ -4196,14 +4206,14 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp); break; case 0x47: /* BC M1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); gen_bcr(s, r1, tmp, s->pc + 4); tcg_temp_free_i64(tmp); s->is_jmp = DISAS_TB_JUMP; break; case 0x48: /* LH R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = tcg_temp_new_i64(); tcg_gen_qemu_ld16s(tmp2, tmp, get_mem_index(s)); @@ -4212,7 +4222,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp2); break; case 0x49: /* CH R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp32_1 = load_reg32(r1); tmp32_2 = tcg_temp_new_i32(); @@ -4228,7 +4238,7 @@ static void disas_s390_insn(DisasContext *s) case 0x4a: /* AH R1,D2(X2,B2) [RX] */ case 0x4b: /* SH R1,D2(X2,B2) [RX] */ case 0x4c: /* MH R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = tcg_temp_new_i64(); tmp32_1 = load_reg32(r1); @@ -4261,7 +4271,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp2); break; case 0x4d: /* BAS R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = tcg_const_i64(pc_to_link_info(s, s->pc + 4)); store_reg(r1, tmp2); @@ -4271,7 +4281,7 @@ static void disas_s390_insn(DisasContext *s) s->is_jmp = DISAS_JUMP; break; case 0x4e: /* CVD R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = tcg_temp_new_i64(); tmp32_1 = tcg_temp_new_i32(); @@ -4283,7 +4293,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_1); break; case 0x50: /* st r1, d2(x2, b2) */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = load_reg(r1); tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s)); @@ -4291,7 +4301,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp2); break; case 0x55: /* CL R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = tcg_temp_new_i64(); tmp32_1 = tcg_temp_new_i32(); @@ -4307,7 +4317,7 @@ static void disas_s390_insn(DisasContext *s) case 0x54: /* N R1,D2(X2,B2) [RX] */ case 0x56: /* O R1,D2(X2,B2) [RX] */ case 0x57: /* X R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = tcg_temp_new_i64(); tmp32_1 = load_reg32(r1); @@ -4323,7 +4333,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_2); break; case 0x58: /* l r1, d2(x2, b2) */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = tcg_temp_new_i64(); tmp32_1 = tcg_temp_new_i32(); @@ -4335,7 +4345,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_1); break; case 0x59: /* C R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = tcg_temp_new_i64(); tmp32_1 = tcg_temp_new_i32(); @@ -4352,7 +4362,7 @@ static void disas_s390_insn(DisasContext *s) case 0x5b: /* S R1,D2(X2,B2) [RX] */ case 0x5e: /* AL R1,D2(X2,B2) [RX] */ case 0x5f: /* SL R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp32_1 = load_reg32(r1); tmp32_2 = tcg_temp_new_i32(); @@ -4395,7 +4405,7 @@ static void disas_s390_insn(DisasContext *s) break; case 0x5c: /* M R1,D2(X2,B2) [RX] */ /* reg(r1, r1+1) = reg(r1+1) * *(s32*)addr */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = tcg_temp_new_i64(); tcg_gen_qemu_ld32s(tmp2, tmp, get_mem_index(s)); @@ -4411,7 +4421,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp3); break; case 0x5d: /* D R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp3 = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp32_1 = load_reg32(r1); tmp32_2 = load_reg32(r1 + 1); @@ -4445,7 +4455,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp3); break; case 0x60: /* STD R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = load_freg(r1); tcg_gen_qemu_st64(tmp2, tmp, get_mem_index(s)); @@ -4453,7 +4463,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp2); break; case 0x68: /* LD R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = tcg_temp_new_i64(); tcg_gen_qemu_ld64(tmp2, tmp, get_mem_index(s)); @@ -4462,7 +4472,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp2); break; case 0x70: /* STE R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = tcg_temp_new_i64(); tmp32_1 = load_freg32(r1); @@ -4473,7 +4483,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_1); break; case 0x71: /* MS R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = tcg_temp_new_i64(); tmp32_1 = load_reg32(r1); @@ -4488,7 +4498,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_2); break; case 0x78: /* LE R1,D2(X2,B2) [RX] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp2 = tcg_temp_new_i64(); tmp32_1 = tcg_temp_new_i32(); @@ -4502,8 +4512,8 @@ static void disas_s390_insn(DisasContext *s) #ifndef CONFIG_USER_ONLY case 0x80: /* SSM D2(B2) [S] */ /* Set System Mask */ - check_privileged(s, ilc); - insn = ld_code4(s->pc); + check_privileged(env, s, ilc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp2 = tcg_temp_new_i64(); @@ -4518,8 +4528,8 @@ static void disas_s390_insn(DisasContext *s) break; case 0x82: /* LPSW D2(B2) [S] */ /* Load PSW */ - check_privileged(s, ilc); - insn = ld_code4(s->pc); + check_privileged(env, s, ilc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp2 = tcg_temp_new_i64(); @@ -4536,9 +4546,9 @@ static void disas_s390_insn(DisasContext *s) break; case 0x83: /* DIAG R1,R3,D2 [RS] */ /* Diagnose call (KVM hypercall) */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); potential_page_fault(s); - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp32_1 = tcg_const_i32(insn & 0xfff); tmp2 = load_reg(2); @@ -4553,7 +4563,7 @@ static void disas_s390_insn(DisasContext *s) case 0x88: /* SRL R1,D2(B2) [RS] */ case 0x89: /* SLL R1,D2(B2) [RS] */ case 0x8a: /* SRA R1,D2(B2) [RS] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp32_1 = load_reg32(r1); @@ -4582,7 +4592,7 @@ static void disas_s390_insn(DisasContext *s) case 0x8c: /* SRDL R1,D2(B2) [RS] */ case 0x8d: /* SLDL R1,D2(B2) [RS] */ case 0x8e: /* SRDA R1,D2(B2) [RS] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); /* shift */ tmp2 = tcg_temp_new_i64(); @@ -4611,7 +4621,7 @@ static void disas_s390_insn(DisasContext *s) break; case 0x98: /* LM R1,R3,D2(B2) [RS] */ case 0x90: /* STM R1,R3,D2(B2) [RS] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); @@ -4637,7 +4647,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp4); break; case 0x91: /* TM D1(B1),I2 [SI] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_si(s, insn, &i2, &b1, &d1); tmp2 = tcg_const_i64(i2); tcg_gen_qemu_ld8u(tmp, tmp, get_mem_index(s)); @@ -4646,7 +4656,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp2); break; case 0x92: /* MVI D1(B1),I2 [SI] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_si(s, insn, &i2, &b1, &d1); tmp2 = tcg_const_i64(i2); tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s)); @@ -4656,7 +4666,7 @@ static void disas_s390_insn(DisasContext *s) case 0x94: /* NI D1(B1),I2 [SI] */ case 0x96: /* OI D1(B1),I2 [SI] */ case 0x97: /* XI D1(B1),I2 [SI] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_si(s, insn, &i2, &b1, &d1); tmp2 = tcg_temp_new_i64(); tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s)); @@ -4679,7 +4689,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp2); break; case 0x95: /* CLI D1(B1),I2 [SI] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); tmp = decode_si(s, insn, &i2, &b1, &d1); tmp2 = tcg_temp_new_i64(); tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s)); @@ -4688,7 +4698,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp2); break; case 0x9a: /* LAM R1,R3,D2(B2) [RS] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp32_1 = tcg_const_i32(r1); @@ -4700,7 +4710,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_2); break; case 0x9b: /* STAM R1,R3,D2(B2) [RS] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp32_1 = tcg_const_i32(r1); @@ -4712,21 +4722,21 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_2); break; case 0xa5: - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); r1 = (insn >> 20) & 0xf; op = (insn >> 16) & 0xf; i2 = insn & 0xffff; - disas_a5(s, op, r1, i2); + disas_a5(env, s, op, r1, i2); break; case 0xa7: - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); r1 = (insn >> 20) & 0xf; op = (insn >> 16) & 0xf; i2 = (short)insn; - disas_a7(s, op, r1, i2); + disas_a7(env, s, op, r1, i2); break; case 0xa8: /* MVCLE R1,R3,D2(B2) [RS] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp32_1 = tcg_const_i32(r1); @@ -4739,7 +4749,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_2); break; case 0xa9: /* CLCLE R1,R3,D2(B2) [RS] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp32_1 = tcg_const_i32(r1); @@ -4754,8 +4764,8 @@ static void disas_s390_insn(DisasContext *s) #ifndef CONFIG_USER_ONLY case 0xac: /* STNSM D1(B1),I2 [SI] */ case 0xad: /* STOSM D1(B1),I2 [SI] */ - check_privileged(s, ilc); - insn = ld_code4(s->pc); + check_privileged(env, s, ilc); + insn = ld_code4(env, s->pc); tmp = decode_si(s, insn, &i2, &b1, &d1); tmp2 = tcg_temp_new_i64(); tcg_gen_shri_i64(tmp2, psw_mask, 56); @@ -4770,8 +4780,8 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp2); break; case 0xae: /* SIGP R1,R3,D2(B2) [RS] */ - check_privileged(s, ilc); - insn = ld_code4(s->pc); + check_privileged(env, s, ilc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp2 = load_reg(r3); @@ -4784,8 +4794,8 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_1); break; case 0xb1: /* LRA R1,D2(X2, B2) [RX] */ - check_privileged(s, ilc); - insn = ld_code4(s->pc); + check_privileged(env, s, ilc); + insn = ld_code4(env, s->pc); tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2); tmp32_1 = tcg_const_i32(r1); potential_page_fault(s); @@ -4796,7 +4806,7 @@ static void disas_s390_insn(DisasContext *s) break; #endif case 0xb2: - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); op = (insn >> 16) & 0xff; switch (op) { case 0x9c: /* STFPC D2(B2) [S] */ @@ -4813,23 +4823,23 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i64(tmp2); break; default: - disas_b2(s, op, insn); + disas_b2(env, s, op, insn); break; } break; case 0xb3: - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); op = (insn >> 16) & 0xff; r3 = (insn >> 12) & 0xf; /* aka m3 */ r1 = (insn >> 4) & 0xf; r2 = insn & 0xf; - disas_b3(s, op, r3, r1, r2); + disas_b3(env, s, op, r3, r1, r2); break; #ifndef CONFIG_USER_ONLY case 0xb6: /* STCTL R1,R3,D2(B2) [RS] */ /* Store Control */ - check_privileged(s, ilc); - insn = ld_code4(s->pc); + check_privileged(env, s, ilc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp32_1 = tcg_const_i32(r1); @@ -4842,8 +4852,8 @@ static void disas_s390_insn(DisasContext *s) break; case 0xb7: /* LCTL R1,R3,D2(B2) [RS] */ /* Load Control */ - check_privileged(s, ilc); - insn = ld_code4(s->pc); + check_privileged(env, s, ilc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp32_1 = tcg_const_i32(r1); @@ -4856,14 +4866,14 @@ static void disas_s390_insn(DisasContext *s) break; #endif case 0xb9: - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); r1 = (insn >> 4) & 0xf; r2 = insn & 0xf; op = (insn >> 16) & 0xff; - disas_b9(s, op, r1, r2); + disas_b9(env, s, op, r1, r2); break; case 0xba: /* CS R1,R3,D2(B2) [RS] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp32_1 = tcg_const_i32(r1); @@ -4876,7 +4886,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_2); break; case 0xbd: /* CLM R1,M3,D2(B2) [RS] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp32_1 = load_reg32(r1); @@ -4889,7 +4899,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_2); break; case 0xbe: /* STCM R1,M3,D2(B2) [RS] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); tmp = get_address(s, 0, b2, d2); tmp32_1 = load_reg32(r1); @@ -4901,7 +4911,7 @@ static void disas_s390_insn(DisasContext *s) tcg_temp_free_i32(tmp32_2); break; case 0xbf: /* ICM R1,M3,D2(B2) [RS] */ - insn = ld_code4(s->pc); + insn = ld_code4(env, s->pc); decode_rs(s, insn, &r1, &r3, &b2, &d2); if (r3 == 15) { /* effectively a 32-bit load */ @@ -4956,16 +4966,16 @@ static void disas_s390_insn(DisasContext *s) break; case 0xc0: case 0xc2: - insn = ld_code6(s->pc); + insn = ld_code6(env, s->pc); r1 = (insn >> 36) & 0xf; op = (insn >> 32) & 0xf; i2 = (int)insn; switch (opc) { case 0xc0: - disas_c0(s, op, r1, i2); + disas_c0(env, s, op, r1, i2); break; case 0xc2: - disas_c2(s, op, r1, i2); + disas_c2(env, s, op, r1, i2); break; default: tcg_abort(); @@ -4978,7 +4988,7 @@ static void disas_s390_insn(DisasContext *s) case 0xd7: /* XC D1(L,B1),D2(B2) [SS] */ case 0xdc: /* TR D1(L,B1),D2(B2) [SS] */ case 0xf3: /* UNPK D1(L1,B1),D2(L2,B2) [SS] */ - insn = ld_code6(s->pc); + insn = ld_code6(env, s->pc); vl = tcg_const_i32((insn >> 32) & 0xff); b1 = (insn >> 28) & 0xf; b2 = (insn >> 12) & 0xf; @@ -5026,9 +5036,9 @@ static void disas_s390_insn(DisasContext *s) #ifndef CONFIG_USER_ONLY case 0xda: /* MVCP D1(R1,B1),D2(B2),R3 [SS] */ case 0xdb: /* MVCS D1(R1,B1),D2(B2),R3 [SS] */ - check_privileged(s, ilc); + check_privileged(env, s, ilc); potential_page_fault(s); - insn = ld_code6(s->pc); + insn = ld_code6(env, s->pc); r1 = (insn >> 36) & 0xf; r3 = (insn >> 32) & 0xf; b1 = (insn >> 28) & 0xf; @@ -5051,7 +5061,7 @@ static void disas_s390_insn(DisasContext *s) break; #endif case 0xe3: - insn = ld_code6(s->pc); + insn = ld_code6(env, s->pc); debug_insn(insn); op = insn & 0xff; r1 = (insn >> 36) & 0xf; @@ -5059,19 +5069,19 @@ static void disas_s390_insn(DisasContext *s) b2 = (insn >> 28) & 0xf; d2 = ((int)((((insn >> 16) & 0xfff) | ((insn << 4) & 0xff000)) << 12)) >> 12; - disas_e3(s, op, r1, x2, b2, d2 ); + disas_e3(env, s, op, r1, x2, b2, d2 ); break; #ifndef CONFIG_USER_ONLY case 0xe5: /* Test Protection */ - check_privileged(s, ilc); - insn = ld_code6(s->pc); + check_privileged(env, s, ilc); + insn = ld_code6(env, s->pc); debug_insn(insn); - disas_e5(s, insn); + disas_e5(env, s, insn); break; #endif case 0xeb: - insn = ld_code6(s->pc); + insn = ld_code6(env, s->pc); debug_insn(insn); op = insn & 0xff; r1 = (insn >> 36) & 0xf; @@ -5079,10 +5089,10 @@ static void disas_s390_insn(DisasContext *s) b2 = (insn >> 28) & 0xf; d2 = ((int)((((insn >> 16) & 0xfff) | ((insn << 4) & 0xff000)) << 12)) >> 12; - disas_eb(s, op, r1, r3, b2, d2); + disas_eb(env, s, op, r1, r3, b2, d2); break; case 0xed: - insn = ld_code6(s->pc); + insn = ld_code6(env, s->pc); debug_insn(insn); op = insn & 0xff; r1 = (insn >> 36) & 0xf; @@ -5090,11 +5100,11 @@ static void disas_s390_insn(DisasContext *s) b2 = (insn >> 28) & 0xf; d2 = (short)((insn >> 16) & 0xfff); r1b = (insn >> 12) & 0xf; - disas_ed(s, op, r1, x2, b2, d2, r1b); + disas_ed(env, s, op, r1, x2, b2, d2, r1b); break; default: qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc); - gen_illegal_opcode(s, ilc); + gen_illegal_opcode(env, s, ilc); break; } @@ -5167,7 +5177,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env, LOG_DISAS("pc " TARGET_FMT_lx "\n", dc.pc); #endif - disas_s390_insn(&dc); + disas_s390_insn(env, &dc); num_insns++; if (env->singlestep_enabled) { From 32ac0ca2ecc0ea0eb6b868abcbe0a7d094870cfd Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 06:57:17 +0000 Subject: [PATCH 0391/2270] target-lm32: switch to AREG0 free mode Add an explicit CPUState parameter instead of relying on AREG0 and switch to AREG0 free mode. Signed-off-by: Blue Swirl --- configure | 2 +- target-lm32/Makefile.objs | 2 -- target-lm32/helper.h | 20 ++++++++++---------- target-lm32/op_helper.c | 29 +++++++++++------------------ target-lm32/translate.c | 28 +++++++++++++--------------- 5 files changed, 35 insertions(+), 46 deletions(-) diff --git a/configure b/configure index 9ab13db6f9..a6b25b3646 100755 --- a/configure +++ b/configure @@ -3874,7 +3874,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile" case "$target_arch2" in - alpha | i386 | or32 | s390x | sparc* | x86_64 | xtensa* | ppc*) + alpha | i386 | lm32 | or32 | s390x | sparc* | x86_64 | xtensa* | ppc*) echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak ;; esac diff --git a/target-lm32/Makefile.objs b/target-lm32/Makefile.objs index 2e0e093e1f..ca20f21443 100644 --- a/target-lm32/Makefile.objs +++ b/target-lm32/Makefile.objs @@ -1,4 +1,2 @@ obj-y += translate.o op_helper.o helper.o cpu.o obj-$(CONFIG_SOFTMMU) += machine.o - -$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-lm32/helper.h b/target-lm32/helper.h index 9d335efc45..07f5670172 100644 --- a/target-lm32/helper.h +++ b/target-lm32/helper.h @@ -1,14 +1,14 @@ #include "def-helper.h" -DEF_HELPER_1(raise_exception, void, i32) -DEF_HELPER_0(hlt, void) -DEF_HELPER_1(wcsr_im, void, i32) -DEF_HELPER_1(wcsr_ip, void, i32) -DEF_HELPER_1(wcsr_jtx, void, i32) -DEF_HELPER_1(wcsr_jrx, void, i32) -DEF_HELPER_0(rcsr_im, i32) -DEF_HELPER_0(rcsr_ip, i32) -DEF_HELPER_0(rcsr_jtx, i32) -DEF_HELPER_0(rcsr_jrx, i32) +DEF_HELPER_2(raise_exception, void, env, i32) +DEF_HELPER_1(hlt, void, env) +DEF_HELPER_2(wcsr_im, void, env, i32) +DEF_HELPER_2(wcsr_ip, void, env, i32) +DEF_HELPER_2(wcsr_jtx, void, env, i32) +DEF_HELPER_2(wcsr_jrx, void, env, i32) +DEF_HELPER_1(rcsr_im, i32, env) +DEF_HELPER_1(rcsr_ip, i32, env) +DEF_HELPER_1(rcsr_jtx, i32, env) +DEF_HELPER_1(rcsr_jrx, i32, env) #include "def-helper.h" diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c index 51edc1a0e1..7b91d8c31e 100644 --- a/target-lm32/op_helper.c +++ b/target-lm32/op_helper.c @@ -1,6 +1,5 @@ #include #include "cpu.h" -#include "dyngen-exec.h" #include "helper.h" #include "host-utils.h" @@ -18,55 +17,55 @@ #define SHIFT 3 #include "softmmu_template.h" -void helper_raise_exception(uint32_t index) +void helper_raise_exception(CPULM32State *env, uint32_t index) { env->exception_index = index; cpu_loop_exit(env); } -void helper_hlt(void) +void helper_hlt(CPULM32State *env) { env->halted = 1; env->exception_index = EXCP_HLT; cpu_loop_exit(env); } -void helper_wcsr_im(uint32_t im) +void helper_wcsr_im(CPULM32State *env, uint32_t im) { lm32_pic_set_im(env->pic_state, im); } -void helper_wcsr_ip(uint32_t im) +void helper_wcsr_ip(CPULM32State *env, uint32_t im) { lm32_pic_set_ip(env->pic_state, im); } -void helper_wcsr_jtx(uint32_t jtx) +void helper_wcsr_jtx(CPULM32State *env, uint32_t jtx) { lm32_juart_set_jtx(env->juart_state, jtx); } -void helper_wcsr_jrx(uint32_t jrx) +void helper_wcsr_jrx(CPULM32State *env, uint32_t jrx) { lm32_juart_set_jrx(env->juart_state, jrx); } -uint32_t helper_rcsr_im(void) +uint32_t helper_rcsr_im(CPULM32State *env) { return lm32_pic_get_im(env->pic_state); } -uint32_t helper_rcsr_ip(void) +uint32_t helper_rcsr_ip(CPULM32State *env) { return lm32_pic_get_ip(env->pic_state); } -uint32_t helper_rcsr_jtx(void) +uint32_t helper_rcsr_jtx(CPULM32State *env) { return lm32_juart_get_jtx(env->juart_state); } -uint32_t helper_rcsr_jrx(void) +uint32_t helper_rcsr_jrx(CPULM32State *env) { return lm32_juart_get_jrx(env->juart_state); } @@ -74,17 +73,12 @@ uint32_t helper_rcsr_jrx(void) /* Try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ -/* XXX: fix it to restore all registers */ -void tlb_fill(CPULM32State *env1, target_ulong addr, int is_write, int mmu_idx, +void tlb_fill(CPULM32State *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { TranslationBlock *tb; - CPULM32State *saved_env; int ret; - saved_env = env; - env = env1; - ret = cpu_lm32_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { @@ -98,7 +92,6 @@ void tlb_fill(CPULM32State *env1, target_ulong addr, int is_write, int mmu_idx, } cpu_loop_exit(env); } - env = saved_env; } #endif diff --git a/target-lm32/translate.c b/target-lm32/translate.c index 872a2ba656..5f6dcbac86 100644 --- a/target-lm32/translate.c +++ b/target-lm32/translate.c @@ -116,7 +116,7 @@ static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index) { TCGv_i32 tmp = tcg_const_i32(index); - gen_helper_raise_exception(tmp); + gen_helper_raise_exception(cpu_env, tmp); tcg_temp_free_i32(tmp); } @@ -179,7 +179,7 @@ static void dec_and(DisasContext *dc) } else { if (dc->r0 == 0 && dc->r1 == 0 && dc->r2 == 0) { tcg_gen_movi_tl(cpu_pc, dc->pc + 4); - gen_helper_hlt(); + gen_helper_hlt(cpu_env); } else { tcg_gen_and_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); } @@ -601,10 +601,10 @@ static void dec_rcsr(DisasContext *dc) tcg_gen_mov_tl(cpu_R[dc->r2], cpu_ie); break; case CSR_IM: - gen_helper_rcsr_im(cpu_R[dc->r2]); + gen_helper_rcsr_im(cpu_R[dc->r2], cpu_env); break; case CSR_IP: - gen_helper_rcsr_ip(cpu_R[dc->r2]); + gen_helper_rcsr_ip(cpu_R[dc->r2], cpu_env); break; case CSR_CC: tcg_gen_mov_tl(cpu_R[dc->r2], cpu_cc); @@ -622,10 +622,10 @@ static void dec_rcsr(DisasContext *dc) tcg_gen_mov_tl(cpu_R[dc->r2], cpu_deba); break; case CSR_JTX: - gen_helper_rcsr_jtx(cpu_R[dc->r2]); + gen_helper_rcsr_jtx(cpu_R[dc->r2], cpu_env); break; case CSR_JRX: - gen_helper_rcsr_jrx(cpu_R[dc->r2]); + gen_helper_rcsr_jrx(cpu_R[dc->r2], cpu_env); break; case CSR_ICC: case CSR_DCC: @@ -812,7 +812,7 @@ static void dec_wcsr(DisasContext *dc) if (use_icount) { gen_io_start(); } - gen_helper_wcsr_im(cpu_R[dc->r1]); + gen_helper_wcsr_im(cpu_env, cpu_R[dc->r1]); tcg_gen_movi_tl(cpu_pc, dc->pc + 4); if (use_icount) { gen_io_end(); @@ -824,7 +824,7 @@ static void dec_wcsr(DisasContext *dc) if (use_icount) { gen_io_start(); } - gen_helper_wcsr_ip(cpu_R[dc->r1]); + gen_helper_wcsr_ip(cpu_env, cpu_R[dc->r1]); tcg_gen_movi_tl(cpu_pc, dc->pc + 4); if (use_icount) { gen_io_end(); @@ -844,10 +844,10 @@ static void dec_wcsr(DisasContext *dc) tcg_gen_mov_tl(cpu_deba, cpu_R[dc->r1]); break; case CSR_JTX: - gen_helper_wcsr_jtx(cpu_R[dc->r1]); + gen_helper_wcsr_jtx(cpu_env, cpu_R[dc->r1]); break; case CSR_JRX: - gen_helper_wcsr_jrx(cpu_R[dc->r1]); + gen_helper_wcsr_jrx(cpu_env, cpu_R[dc->r1]); break; case CSR_DC: tcg_gen_mov_tl(cpu_dc, cpu_R[dc->r1]); @@ -940,15 +940,13 @@ static const DecoderInfo decinfo[] = { dec_cmpne }; -static inline void decode(DisasContext *dc) +static inline void decode(DisasContext *dc, uint32_t ir) { - uint32_t ir; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { tcg_gen_debug_insn_start(dc->pc); } - dc->ir = ir = ldl_code(dc->pc); + dc->ir = ir; LOG_DIS("%8.8x\t", dc->ir); /* try guessing 'empty' instruction memory, although it may be a valid @@ -1068,7 +1066,7 @@ static void gen_intermediate_code_internal(CPULM32State *env, gen_io_start(); } - decode(dc); + decode(dc, cpu_ldl_code(env, dc->pc)); dc->pc += 4; num_insns++; From 31871141521225d089b7705a5d73bf03c605c964 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 07:27:38 +0000 Subject: [PATCH 0392/2270] target-m68k: switch to AREG0 free mode Add an explicit CPUState parameter instead of relying on AREG0 and switch to AREG0 free mode. Signed-off-by: Blue Swirl --- configure | 2 +- target-m68k/Makefile.objs | 2 -- target-m68k/helpers.h | 2 +- target-m68k/op_helper.c | 68 ++++++++++++++--------------------- target-m68k/translate.c | 76 ++++++++++++++++++++------------------- 5 files changed, 68 insertions(+), 82 deletions(-) diff --git a/configure b/configure index a6b25b3646..f01e2e9a11 100755 --- a/configure +++ b/configure @@ -3874,7 +3874,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile" case "$target_arch2" in - alpha | i386 | lm32 | or32 | s390x | sparc* | x86_64 | xtensa* | ppc*) + alpha | i386 | lm32 | m68k | or32 | s390x | sparc* | x86_64 | xtensa* | ppc*) echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak ;; esac diff --git a/target-m68k/Makefile.objs b/target-m68k/Makefile.objs index cda60157f5..7eccfab0e4 100644 --- a/target-m68k/Makefile.objs +++ b/target-m68k/Makefile.objs @@ -1,5 +1,3 @@ obj-y += m68k-semi.o obj-y += translate.o op_helper.o helper.o cpu.o obj-$(CONFIG_SOFTMMU) += machine.o - -$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h index cb8a0c7d4a..8112b44a58 100644 --- a/target-m68k/helpers.h +++ b/target-m68k/helpers.h @@ -49,6 +49,6 @@ DEF_HELPER_3(set_mac_exts, void, env, i32, i32) DEF_HELPER_3(set_mac_extu, void, env, i32, i32) DEF_HELPER_2(flush_flags, void, env, i32) -DEF_HELPER_1(raise_exception, void, i32) +DEF_HELPER_2(raise_exception, void, env, i32) #include "def-helper.h" diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c index 1971a57892..3116287093 100644 --- a/target-m68k/op_helper.c +++ b/target-m68k/op_helper.c @@ -17,17 +17,16 @@ * License along with this library; if not, see . */ #include "cpu.h" -#include "dyngen-exec.h" #include "helpers.h" #if defined(CONFIG_USER_ONLY) -void do_interrupt(CPUM68KState *env1) +void do_interrupt(CPUM68KState *env) { - env1->exception_index = -1; + env->exception_index = -1; } -void do_interrupt_m68k_hardirq(CPUM68KState *env1) +void do_interrupt_m68k_hardirq(CPUM68KState *env) { } @@ -54,16 +53,12 @@ extern int semihosting_enabled; /* Try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ -/* XXX: fix it to restore all registers */ -void tlb_fill(CPUM68KState *env1, target_ulong addr, int is_write, int mmu_idx, +void tlb_fill(CPUM68KState *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { TranslationBlock *tb; - CPUM68KState *saved_env; int ret; - saved_env = env; - env = env1; ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { @@ -77,24 +72,23 @@ void tlb_fill(CPUM68KState *env1, target_ulong addr, int is_write, int mmu_idx, } cpu_loop_exit(env); } - env = saved_env; } -static void do_rte(void) +static void do_rte(CPUM68KState *env) { uint32_t sp; uint32_t fmt; sp = env->aregs[7]; - fmt = ldl_kernel(sp); - env->pc = ldl_kernel(sp + 4); + fmt = cpu_ldl_kernel(env, sp); + env->pc = cpu_ldl_kernel(env, sp + 4); sp |= (fmt >> 28) & 3; env->sr = fmt & 0xffff; m68k_switch_sp(env); env->aregs[7] = sp + 8; } -static void do_interrupt_all(int is_hw) +static void do_interrupt_all(CPUM68KState *env, int is_hw) { uint32_t sp; uint32_t fmt; @@ -108,14 +102,14 @@ static void do_interrupt_all(int is_hw) switch (env->exception_index) { case EXCP_RTE: /* Return from an exception. */ - do_rte(); + do_rte(env); return; case EXCP_HALT_INSN: if (semihosting_enabled && (env->sr & SR_S) != 0 && (env->pc & 3) == 0 - && lduw_code(env->pc - 4) == 0x4e71 - && ldl_code(env->pc) == 0x4e7bf000) { + && cpu_lduw_code(env, env->pc - 4) == 0x4e71 + && cpu_ldl_code(env, env->pc) == 0x4e7bf000) { env->pc += 4; do_m68k_semihosting(env, env->dregs[0]); return; @@ -151,44 +145,34 @@ static void do_interrupt_all(int is_hw) /* ??? This could cause MMU faults. */ sp &= ~3; sp -= 4; - stl_kernel(sp, retaddr); + cpu_stl_kernel(env, sp, retaddr); sp -= 4; - stl_kernel(sp, fmt); + cpu_stl_kernel(env, sp, fmt); env->aregs[7] = sp; /* Jump to vector. */ - env->pc = ldl_kernel(env->vbr + vector); + env->pc = cpu_ldl_kernel(env, env->vbr + vector); } -void do_interrupt(CPUM68KState *env1) +void do_interrupt(CPUM68KState *env) { - CPUM68KState *saved_env; - - saved_env = env; - env = env1; - do_interrupt_all(0); - env = saved_env; + do_interrupt_all(env, 0); } -void do_interrupt_m68k_hardirq(CPUM68KState *env1) +void do_interrupt_m68k_hardirq(CPUM68KState *env) { - CPUM68KState *saved_env; - - saved_env = env; - env = env1; - do_interrupt_all(1); - env = saved_env; + do_interrupt_all(env, 1); } #endif -static void raise_exception(int tt) +static void raise_exception(CPUM68KState *env, int tt) { env->exception_index = tt; cpu_loop_exit(env); } -void HELPER(raise_exception)(uint32_t tt) +void HELPER(raise_exception)(CPUM68KState *env, uint32_t tt) { - raise_exception(tt); + raise_exception(env, tt); } void HELPER(divu)(CPUM68KState *env, uint32_t word) @@ -202,8 +186,9 @@ void HELPER(divu)(CPUM68KState *env, uint32_t word) num = env->div1; den = env->div2; /* ??? This needs to make sure the throwing location is accurate. */ - if (den == 0) - raise_exception(EXCP_DIV0); + if (den == 0) { + raise_exception(env, EXCP_DIV0); + } quot = num / den; rem = num % den; flags = 0; @@ -231,8 +216,9 @@ void HELPER(divs)(CPUM68KState *env, uint32_t word) num = env->div1; den = env->div2; - if (den == 0) - raise_exception(EXCP_DIV0); + if (den == 0) { + raise_exception(env, EXCP_DIV0); + } quot = num / den; rem = num % den; flags = 0; diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 9fc1e3102d..10bb3039ed 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -260,9 +260,9 @@ static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val, static inline uint32_t read_im32(DisasContext *s) { uint32_t im; - im = ((uint32_t)lduw_code(s->pc)) << 16; + im = ((uint32_t)cpu_lduw_code(cpu_single_env, s->pc)) << 16; s->pc += 2; - im |= lduw_code(s->pc); + im |= cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; return im; } @@ -297,7 +297,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base) uint32_t bd, od; offset = s->pc; - ext = lduw_code(s->pc); + ext = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX)) @@ -311,7 +311,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base) if ((ext & 0x30) > 0x10) { /* base displacement */ if ((ext & 0x30) == 0x20) { - bd = (int16_t)lduw_code(s->pc); + bd = (int16_t)cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; } else { bd = read_im32(s); @@ -360,7 +360,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base) if ((ext & 3) > 1) { /* outer displacement */ if ((ext & 3) == 2) { - od = (int16_t)lduw_code(s->pc); + od = (int16_t)cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; } else { od = read_im32(s); @@ -514,7 +514,7 @@ static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize) case 5: /* Indirect displacement. */ reg = AREG(insn, 0); tmp = tcg_temp_new(); - ext = lduw_code(s->pc); + ext = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; tcg_gen_addi_i32(tmp, reg, (int16_t)ext); return tmp; @@ -524,7 +524,7 @@ static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize) case 7: /* Other */ switch (insn & 7) { case 0: /* Absolute short. */ - offset = ldsw_code(s->pc); + offset = cpu_ldsw_code(cpu_single_env, s->pc); s->pc += 2; return tcg_const_i32(offset); case 1: /* Absolute long. */ @@ -532,7 +532,7 @@ static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize) return tcg_const_i32(offset); case 2: /* pc displacement */ offset = s->pc; - offset += ldsw_code(s->pc); + offset += cpu_ldsw_code(cpu_single_env, s->pc); s->pc += 2; return tcg_const_i32(offset); case 3: /* pc index+displacement. */ @@ -638,17 +638,19 @@ static TCGv gen_ea(DisasContext *s, uint16_t insn, int opsize, TCGv val, /* Sign extend values for consistency. */ switch (opsize) { case OS_BYTE: - if (what == EA_LOADS) - offset = ldsb_code(s->pc + 1); - else - offset = ldub_code(s->pc + 1); + if (what == EA_LOADS) { + offset = cpu_ldsb_code(cpu_single_env, s->pc + 1); + } else { + offset = cpu_ldub_code(cpu_single_env, s->pc + 1); + } s->pc += 2; break; case OS_WORD: - if (what == EA_LOADS) - offset = ldsw_code(s->pc); - else - offset = lduw_code(s->pc); + if (what == EA_LOADS) { + offset = cpu_ldsw_code(cpu_single_env, s->pc); + } else { + offset = cpu_lduw_code(cpu_single_env, s->pc); + } s->pc += 2; break; case OS_LONG: @@ -815,7 +817,7 @@ static void gen_exception(DisasContext *s, uint32_t where, int nr) { gen_flush_cc_op(s); gen_jmp_im(s, where); - gen_helper_raise_exception(tcg_const_i32(nr)); + gen_helper_raise_exception(cpu_env, tcg_const_i32(nr)); } static inline void gen_addr_fault(DisasContext *s) @@ -934,7 +936,7 @@ DISAS_INSN(divl) TCGv reg; uint16_t ext; - ext = lduw_code(s->pc); + ext = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; if (ext & 0x87f8) { gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); @@ -1086,7 +1088,7 @@ DISAS_INSN(movem) TCGv tmp; int is_load; - mask = lduw_code(s->pc); + mask = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; tmp = gen_lea(s, insn, OS_LONG); if (IS_NULL_QREG(tmp)) { @@ -1130,7 +1132,7 @@ DISAS_INSN(bitop_im) opsize = OS_LONG; op = (insn >> 6) & 3; - bitnum = lduw_code(s->pc); + bitnum = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; if (bitnum & 0xff00) { disas_undef(s, insn); @@ -1383,7 +1385,7 @@ static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only) else if ((insn & 0x3f) == 0x3c) { uint16_t val; - val = lduw_code(s->pc); + val = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; gen_set_sr_im(s, val, ccr_only); } @@ -1507,7 +1509,7 @@ DISAS_INSN(mull) /* The upper 32 bits of the product are discarded, so muls.l and mulu.l are functionally equivalent. */ - ext = lduw_code(s->pc); + ext = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; if (ext & 0x87ff) { gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); @@ -1528,7 +1530,7 @@ DISAS_INSN(link) TCGv reg; TCGv tmp; - offset = ldsw_code(s->pc); + offset = cpu_ldsw_code(cpu_single_env, s->pc); s->pc += 2; reg = AREG(insn, 0); tmp = tcg_temp_new(); @@ -1649,7 +1651,7 @@ DISAS_INSN(branch) op = (insn >> 8) & 0xf; offset = (int8_t)insn; if (offset == 0) { - offset = ldsw_code(s->pc); + offset = cpu_ldsw_code(cpu_single_env, s->pc); s->pc += 2; } else if (offset == -1) { offset = read_im32(s); @@ -1934,13 +1936,13 @@ DISAS_INSN(strldsr) uint32_t addr; addr = s->pc - 2; - ext = lduw_code(s->pc); + ext = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; if (ext != 0x46FC) { gen_exception(s, addr, EXCP_UNSUPPORTED); return; } - ext = lduw_code(s->pc); + ext = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; if (IS_USER(s) || (ext & SR_S) == 0) { gen_exception(s, addr, EXCP_PRIVILEGE); @@ -2008,7 +2010,7 @@ DISAS_INSN(stop) return; } - ext = lduw_code(s->pc); + ext = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; gen_set_sr_im(s, ext, 0); @@ -2035,7 +2037,7 @@ DISAS_INSN(movec) return; } - ext = lduw_code(s->pc); + ext = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; if (ext & 0x8000) { @@ -2100,7 +2102,7 @@ DISAS_INSN(fpu) int set_dest; int opsize; - ext = lduw_code(s->pc); + ext = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; opmode = ext & 0x7f; switch ((ext >> 13) & 7) { @@ -2136,7 +2138,7 @@ DISAS_INSN(fpu) tcg_gen_addi_i32(tmp32, tmp32, -8); break; case 5: - offset = ldsw_code(s->pc); + offset = cpu_ldsw_code(cpu_single_env, s->pc); s->pc += 2; tcg_gen_addi_i32(tmp32, tmp32, offset); break; @@ -2250,12 +2252,12 @@ DISAS_INSN(fpu) tcg_gen_addi_i32(tmp32, tmp32, -8); break; case 5: - offset = ldsw_code(s->pc); + offset = cpu_ldsw_code(cpu_single_env, s->pc); s->pc += 2; tcg_gen_addi_i32(tmp32, tmp32, offset); break; case 7: - offset = ldsw_code(s->pc); + offset = cpu_ldsw_code(cpu_single_env, s->pc); offset += s->pc - 2; s->pc += 2; tcg_gen_addi_i32(tmp32, tmp32, offset); @@ -2381,10 +2383,10 @@ DISAS_INSN(fbcc) int l1; addr = s->pc; - offset = ldsw_code(s->pc); + offset = cpu_ldsw_code(cpu_single_env, s->pc); s->pc += 2; if (insn & (1 << 6)) { - offset = (offset << 16) | lduw_code(s->pc); + offset = (offset << 16) | cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; } @@ -2506,7 +2508,7 @@ DISAS_INSN(mac) s->done_mac = 1; } - ext = lduw_code(s->pc); + ext = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; acc = ((insn >> 7) & 1) | ((ext >> 3) & 2); @@ -2941,7 +2943,7 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s) { uint16_t insn; - insn = lduw_code(s->pc); + insn = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; opcode_table[insn](s, insn); @@ -3028,7 +3030,7 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb, gen_flush_cc_op(dc); tcg_gen_movi_i32(QREG_PC, dc->pc); } - gen_helper_raise_exception(tcg_const_i32(EXCP_DEBUG)); + gen_helper_raise_exception(cpu_env, tcg_const_i32(EXCP_DEBUG)); } else { switch(dc->is_jmp) { case DISAS_NEXT: From d4d79bb144f0958f7ee2c6c9ef820dc06c1ff476 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sat, 8 Sep 2012 10:48:20 +0000 Subject: [PATCH 0393/2270] target-m68k: avoid using cpu_single_env Pass around CPUState instead of using global cpu_single_env. Signed-off-by: Blue Swirl --- target-m68k/translate.c | 270 +++++++++++++++++++++------------------- 1 file changed, 140 insertions(+), 130 deletions(-) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 10bb3039ed..fb707f21bc 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -150,18 +150,24 @@ static void *gen_throws_exception; #define OS_SINGLE 4 #define OS_DOUBLE 5 -typedef void (*disas_proc)(DisasContext *, uint16_t); +typedef void (*disas_proc)(CPUM68KState *env, DisasContext *s, uint16_t insn); #ifdef DEBUG_DISPATCH -#define DISAS_INSN(name) \ - static void real_disas_##name (DisasContext *s, uint16_t insn); \ - static void disas_##name (DisasContext *s, uint16_t insn) { \ - qemu_log("Dispatch " #name "\n"); \ - real_disas_##name(s, insn); } \ - static void real_disas_##name (DisasContext *s, uint16_t insn) +#define DISAS_INSN(name) \ + static void real_disas_##name(CPUM68KState *env, DisasContext *s, \ + uint16_t insn); \ + static void disas_##name(CPUM68KState *env, DisasContext *s, \ + uint16_t insn) \ + { \ + qemu_log("Dispatch " #name "\n"); \ + real_disas_##name(s, env, insn); \ + } \ + static void real_disas_##name(CPUM68KState *env, DisasContext *s, \ + uint16_t insn) #else -#define DISAS_INSN(name) \ - static void disas_##name (DisasContext *s, uint16_t insn) +#define DISAS_INSN(name) \ + static void disas_##name(CPUM68KState *env, DisasContext *s, \ + uint16_t insn) #endif /* Generate a load from the specified address. Narrow values are @@ -257,12 +263,12 @@ static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val, } /* Read a 32-bit immediate constant. */ -static inline uint32_t read_im32(DisasContext *s) +static inline uint32_t read_im32(CPUM68KState *env, DisasContext *s) { uint32_t im; - im = ((uint32_t)cpu_lduw_code(cpu_single_env, s->pc)) << 16; + im = ((uint32_t)cpu_lduw_code(env, s->pc)) << 16; s->pc += 2; - im |= cpu_lduw_code(cpu_single_env, s->pc); + im |= cpu_lduw_code(env, s->pc); s->pc += 2; return im; } @@ -288,7 +294,8 @@ static TCGv gen_addr_index(uint16_t ext, TCGv tmp) /* Handle a base + index + displacement effective addresss. A NULL_QREG base means pc-relative. */ -static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base) +static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, int opsize, + TCGv base) { uint32_t offset; uint16_t ext; @@ -297,7 +304,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base) uint32_t bd, od; offset = s->pc; - ext = cpu_lduw_code(cpu_single_env, s->pc); + ext = cpu_lduw_code(env, s->pc); s->pc += 2; if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX)) @@ -311,10 +318,10 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base) if ((ext & 0x30) > 0x10) { /* base displacement */ if ((ext & 0x30) == 0x20) { - bd = (int16_t)cpu_lduw_code(cpu_single_env, s->pc); + bd = (int16_t)cpu_lduw_code(env, s->pc); s->pc += 2; } else { - bd = read_im32(s); + bd = read_im32(env, s); } } else { bd = 0; @@ -360,10 +367,10 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base) if ((ext & 3) > 1) { /* outer displacement */ if ((ext & 3) == 2) { - od = (int16_t)cpu_lduw_code(cpu_single_env, s->pc); + od = (int16_t)cpu_lduw_code(env, s->pc); s->pc += 2; } else { - od = read_im32(s); + od = read_im32(env, s); } } else { od = 0; @@ -492,7 +499,8 @@ static inline TCGv gen_extend(TCGv val, int opsize, int sign) /* Generate code for an "effective address". Does not adjust the base register for autoincrement addressing modes. */ -static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize) +static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn, + int opsize) { TCGv reg; TCGv tmp; @@ -514,29 +522,29 @@ static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize) case 5: /* Indirect displacement. */ reg = AREG(insn, 0); tmp = tcg_temp_new(); - ext = cpu_lduw_code(cpu_single_env, s->pc); + ext = cpu_lduw_code(env, s->pc); s->pc += 2; tcg_gen_addi_i32(tmp, reg, (int16_t)ext); return tmp; case 6: /* Indirect index + displacement. */ reg = AREG(insn, 0); - return gen_lea_indexed(s, opsize, reg); + return gen_lea_indexed(env, s, opsize, reg); case 7: /* Other */ switch (insn & 7) { case 0: /* Absolute short. */ - offset = cpu_ldsw_code(cpu_single_env, s->pc); + offset = cpu_ldsw_code(env, s->pc); s->pc += 2; return tcg_const_i32(offset); case 1: /* Absolute long. */ - offset = read_im32(s); + offset = read_im32(env, s); return tcg_const_i32(offset); case 2: /* pc displacement */ offset = s->pc; - offset += cpu_ldsw_code(cpu_single_env, s->pc); + offset += cpu_ldsw_code(env, s->pc); s->pc += 2; return tcg_const_i32(offset); case 3: /* pc index+displacement. */ - return gen_lea_indexed(s, opsize, NULL_QREG); + return gen_lea_indexed(env, s, opsize, NULL_QREG); case 4: /* Immediate. */ default: return NULL_QREG; @@ -548,15 +556,16 @@ static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize) /* Helper function for gen_ea. Reuse the computed address between the for read/write operands. */ -static inline TCGv gen_ea_once(DisasContext *s, uint16_t insn, int opsize, - TCGv val, TCGv *addrp, ea_what what) +static inline TCGv gen_ea_once(CPUM68KState *env, DisasContext *s, + uint16_t insn, int opsize, TCGv val, + TCGv *addrp, ea_what what) { TCGv tmp; if (addrp && what == EA_STORE) { tmp = *addrp; } else { - tmp = gen_lea(s, insn, opsize); + tmp = gen_lea(env, s, insn, opsize); if (IS_NULL_QREG(tmp)) return tmp; if (addrp) @@ -568,8 +577,8 @@ static inline TCGv gen_ea_once(DisasContext *s, uint16_t insn, int opsize, /* Generate code to load/store a value ito/from an EA. If VAL > 0 this is a write otherwise it is a read (0 == sign extend, -1 == zero extend). ADDRP is non-null for readwrite operands. */ -static TCGv gen_ea(DisasContext *s, uint16_t insn, int opsize, TCGv val, - TCGv *addrp, ea_what what) +static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn, + int opsize, TCGv val, TCGv *addrp, ea_what what) { TCGv reg; TCGv result; @@ -609,7 +618,7 @@ static TCGv gen_ea(DisasContext *s, uint16_t insn, int opsize, TCGv val, if (addrp && what == EA_STORE) { tmp = *addrp; } else { - tmp = gen_lea(s, insn, opsize); + tmp = gen_lea(env, s, insn, opsize); if (IS_NULL_QREG(tmp)) return tmp; if (addrp) @@ -626,35 +635,35 @@ static TCGv gen_ea(DisasContext *s, uint16_t insn, int opsize, TCGv val, return result; case 5: /* Indirect displacement. */ case 6: /* Indirect index + displacement. */ - return gen_ea_once(s, insn, opsize, val, addrp, what); + return gen_ea_once(env, s, insn, opsize, val, addrp, what); case 7: /* Other */ switch (insn & 7) { case 0: /* Absolute short. */ case 1: /* Absolute long. */ case 2: /* pc displacement */ case 3: /* pc index+displacement. */ - return gen_ea_once(s, insn, opsize, val, addrp, what); + return gen_ea_once(env, s, insn, opsize, val, addrp, what); case 4: /* Immediate. */ /* Sign extend values for consistency. */ switch (opsize) { case OS_BYTE: if (what == EA_LOADS) { - offset = cpu_ldsb_code(cpu_single_env, s->pc + 1); + offset = cpu_ldsb_code(env, s->pc + 1); } else { - offset = cpu_ldub_code(cpu_single_env, s->pc + 1); + offset = cpu_ldub_code(env, s->pc + 1); } s->pc += 2; break; case OS_WORD: if (what == EA_LOADS) { - offset = cpu_ldsw_code(cpu_single_env, s->pc); + offset = cpu_ldsw_code(env, s->pc); } else { - offset = cpu_lduw_code(cpu_single_env, s->pc); + offset = cpu_lduw_code(env, s->pc); } s->pc += 2; break; case OS_LONG: - offset = read_im32(s); + offset = read_im32(env, s); break; default: qemu_assert(0, "Bad immediate operand"); @@ -825,20 +834,21 @@ static inline void gen_addr_fault(DisasContext *s) gen_exception(s, s->insn_pc, EXCP_ADDRESS); } -#define SRC_EA(result, opsize, op_sign, addrp) do { \ - result = gen_ea(s, insn, opsize, NULL_QREG, addrp, op_sign ? EA_LOADS : EA_LOADU); \ - if (IS_NULL_QREG(result)) { \ - gen_addr_fault(s); \ - return; \ - } \ +#define SRC_EA(env, result, opsize, op_sign, addrp) do { \ + result = gen_ea(env, s, insn, opsize, NULL_QREG, addrp, \ + op_sign ? EA_LOADS : EA_LOADU); \ + if (IS_NULL_QREG(result)) { \ + gen_addr_fault(s); \ + return; \ + } \ } while (0) -#define DEST_EA(insn, opsize, val, addrp) do { \ - TCGv ea_result = gen_ea(s, insn, opsize, val, addrp, EA_STORE); \ - if (IS_NULL_QREG(ea_result)) { \ - gen_addr_fault(s); \ - return; \ - } \ +#define DEST_EA(env, insn, opsize, val, addrp) do { \ + TCGv ea_result = gen_ea(env, s, insn, opsize, val, addrp, EA_STORE); \ + if (IS_NULL_QREG(ea_result)) { \ + gen_addr_fault(s); \ + return; \ + } \ } while (0) /* Generate a jump to an immediate address. */ @@ -874,8 +884,7 @@ DISAS_INSN(undef_fpu) DISAS_INSN(undef) { gen_exception(s, s->pc - 2, EXCP_UNSUPPORTED); - cpu_abort(cpu_single_env, "Illegal instruction: %04x @ %08x", - insn, s->pc - 2); + cpu_abort(env, "Illegal instruction: %04x @ %08x", insn, s->pc - 2); } DISAS_INSN(mulw) @@ -892,7 +901,7 @@ DISAS_INSN(mulw) tcg_gen_ext16s_i32(tmp, reg); else tcg_gen_ext16u_i32(tmp, reg); - SRC_EA(src, OS_WORD, sign, NULL); + SRC_EA(env, src, OS_WORD, sign, NULL); tcg_gen_mul_i32(tmp, tmp, src); tcg_gen_mov_i32(reg, tmp); /* Unlike m68k, coldfire always clears the overflow bit. */ @@ -913,7 +922,7 @@ DISAS_INSN(divw) } else { tcg_gen_ext16u_i32(QREG_DIV1, reg); } - SRC_EA(src, OS_WORD, sign, NULL); + SRC_EA(env, src, OS_WORD, sign, NULL); tcg_gen_mov_i32(QREG_DIV2, src); if (sign) { gen_helper_divs(cpu_env, tcg_const_i32(1)); @@ -936,7 +945,7 @@ DISAS_INSN(divl) TCGv reg; uint16_t ext; - ext = cpu_lduw_code(cpu_single_env, s->pc); + ext = cpu_lduw_code(env, s->pc); s->pc += 2; if (ext & 0x87f8) { gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); @@ -945,7 +954,7 @@ DISAS_INSN(divl) num = DREG(ext, 12); reg = DREG(ext, 0); tcg_gen_mov_i32(QREG_DIV1, num); - SRC_EA(den, OS_LONG, 0, NULL); + SRC_EA(env, den, OS_LONG, 0, NULL); tcg_gen_mov_i32(QREG_DIV2, den); if (ext & 0x0800) { gen_helper_divs(cpu_env, tcg_const_i32(0)); @@ -975,11 +984,11 @@ DISAS_INSN(addsub) reg = DREG(insn, 9); dest = tcg_temp_new(); if (insn & 0x100) { - SRC_EA(tmp, OS_LONG, 0, &addr); + SRC_EA(env, tmp, OS_LONG, 0, &addr); src = reg; } else { tmp = reg; - SRC_EA(src, OS_LONG, 0, NULL); + SRC_EA(env, src, OS_LONG, 0, NULL); } if (add) { tcg_gen_add_i32(dest, tmp, src); @@ -992,7 +1001,7 @@ DISAS_INSN(addsub) } gen_update_cc_add(dest, src); if (insn & 0x100) { - DEST_EA(insn, OS_LONG, dest, &addr); + DEST_EA(env, insn, OS_LONG, dest, &addr); } else { tcg_gen_mov_i32(reg, dest); } @@ -1022,7 +1031,7 @@ DISAS_INSN(bitop_reg) else opsize = OS_LONG; op = (insn >> 6) & 3; - SRC_EA(src1, opsize, 0, op ? &addr: NULL); + SRC_EA(env, src1, opsize, 0, op ? &addr: NULL); src2 = DREG(insn, 9); dest = tcg_temp_new(); @@ -1057,7 +1066,7 @@ DISAS_INSN(bitop_reg) break; } if (op) - DEST_EA(insn, opsize, dest, &addr); + DEST_EA(env, insn, opsize, dest, &addr); } DISAS_INSN(sats) @@ -1088,9 +1097,9 @@ DISAS_INSN(movem) TCGv tmp; int is_load; - mask = cpu_lduw_code(cpu_single_env, s->pc); + mask = cpu_lduw_code(env, s->pc); s->pc += 2; - tmp = gen_lea(s, insn, OS_LONG); + tmp = gen_lea(env, s, insn, OS_LONG); if (IS_NULL_QREG(tmp)) { gen_addr_fault(s); return; @@ -1132,14 +1141,14 @@ DISAS_INSN(bitop_im) opsize = OS_LONG; op = (insn >> 6) & 3; - bitnum = cpu_lduw_code(cpu_single_env, s->pc); + bitnum = cpu_lduw_code(env, s->pc); s->pc += 2; if (bitnum & 0xff00) { - disas_undef(s, insn); + disas_undef(env, s, insn); return; } - SRC_EA(src1, opsize, 0, op ? &addr: NULL); + SRC_EA(env, src1, opsize, 0, op ? &addr: NULL); gen_flush_flags(s); if (opsize == OS_BYTE) @@ -1174,7 +1183,7 @@ DISAS_INSN(bitop_im) default: /* btst */ break; } - DEST_EA(insn, opsize, tmp, &addr); + DEST_EA(env, insn, opsize, tmp, &addr); } } @@ -1187,8 +1196,8 @@ DISAS_INSN(arith_im) TCGv addr; op = (insn >> 9) & 7; - SRC_EA(src1, OS_LONG, 0, (op == 6) ? NULL : &addr); - im = read_im32(s); + SRC_EA(env, src1, OS_LONG, 0, (op == 6) ? NULL : &addr); + im = read_im32(env, s); dest = tcg_temp_new(); switch (op) { case 0: /* ori */ @@ -1227,7 +1236,7 @@ DISAS_INSN(arith_im) abort(); } if (op != 6) { - DEST_EA(insn, OS_LONG, dest, &addr); + DEST_EA(env, insn, OS_LONG, dest, &addr); } } @@ -1259,7 +1268,7 @@ DISAS_INSN(move) default: abort(); } - SRC_EA(src, opsize, 1, NULL); + SRC_EA(env, src, opsize, 1, NULL); op = (insn >> 6) & 7; if (op == 1) { /* movea */ @@ -1270,7 +1279,7 @@ DISAS_INSN(move) /* normal move */ uint16_t dest_ea; dest_ea = ((insn >> 9) & 7) | (op << 3); - DEST_EA(dest_ea, opsize, src, NULL); + DEST_EA(env, dest_ea, opsize, src, NULL); /* This will be correct because loads sign extend. */ gen_logic_cc(s, src); } @@ -1291,7 +1300,7 @@ DISAS_INSN(lea) TCGv tmp; reg = AREG(insn, 9); - tmp = gen_lea(s, insn, OS_LONG); + tmp = gen_lea(env, s, insn, OS_LONG); if (IS_NULL_QREG(tmp)) { gen_addr_fault(s); return; @@ -1316,7 +1325,7 @@ DISAS_INSN(clr) default: abort(); } - DEST_EA(insn, opsize, tcg_const_i32(0), NULL); + DEST_EA(env, insn, opsize, tcg_const_i32(0), NULL); gen_logic_cc(s, tcg_const_i32(0)); } @@ -1365,7 +1374,8 @@ static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only) } } -static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only) +static void gen_set_sr(CPUM68KState *env, DisasContext *s, uint16_t insn, + int ccr_only) { TCGv tmp; TCGv reg; @@ -1385,17 +1395,17 @@ static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only) else if ((insn & 0x3f) == 0x3c) { uint16_t val; - val = cpu_lduw_code(cpu_single_env, s->pc); + val = cpu_lduw_code(env, s->pc); s->pc += 2; gen_set_sr_im(s, val, ccr_only); } else - disas_undef(s, insn); + disas_undef(env, s, insn); } DISAS_INSN(move_to_ccr) { - gen_set_sr(s, insn, 1); + gen_set_sr(env, s, insn, 1); } DISAS_INSN(not) @@ -1426,7 +1436,7 @@ DISAS_INSN(pea) { TCGv tmp; - tmp = gen_lea(s, insn, OS_LONG); + tmp = gen_lea(env, s, insn, OS_LONG); if (IS_NULL_QREG(tmp)) { gen_addr_fault(s); return; @@ -1472,7 +1482,7 @@ DISAS_INSN(tst) default: abort(); } - SRC_EA(tmp, opsize, 1, NULL); + SRC_EA(env, tmp, opsize, 1, NULL); gen_logic_cc(s, tmp); } @@ -1494,10 +1504,10 @@ DISAS_INSN(tas) TCGv addr; dest = tcg_temp_new(); - SRC_EA(src1, OS_BYTE, 1, &addr); + SRC_EA(env, src1, OS_BYTE, 1, &addr); gen_logic_cc(s, src1); tcg_gen_ori_i32(dest, src1, 0x80); - DEST_EA(insn, OS_BYTE, dest, &addr); + DEST_EA(env, insn, OS_BYTE, dest, &addr); } DISAS_INSN(mull) @@ -1509,14 +1519,14 @@ DISAS_INSN(mull) /* The upper 32 bits of the product are discarded, so muls.l and mulu.l are functionally equivalent. */ - ext = cpu_lduw_code(cpu_single_env, s->pc); + ext = cpu_lduw_code(env, s->pc); s->pc += 2; if (ext & 0x87ff) { gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); return; } reg = DREG(ext, 12); - SRC_EA(src1, OS_LONG, 0, NULL); + SRC_EA(env, src1, OS_LONG, 0, NULL); dest = tcg_temp_new(); tcg_gen_mul_i32(dest, src1, reg); tcg_gen_mov_i32(reg, dest); @@ -1530,7 +1540,7 @@ DISAS_INSN(link) TCGv reg; TCGv tmp; - offset = cpu_ldsw_code(cpu_single_env, s->pc); + offset = cpu_ldsw_code(env, s->pc); s->pc += 2; reg = AREG(insn, 0); tmp = tcg_temp_new(); @@ -1574,7 +1584,7 @@ DISAS_INSN(jump) /* Load the target address first to ensure correct exception behavior. */ - tmp = gen_lea(s, insn, OS_LONG); + tmp = gen_lea(env, s, insn, OS_LONG); if (IS_NULL_QREG(tmp)) { gen_addr_fault(s); return; @@ -1594,7 +1604,7 @@ DISAS_INSN(addsubq) int val; TCGv addr; - SRC_EA(src1, OS_LONG, 0, &addr); + SRC_EA(env, src1, OS_LONG, 0, &addr); val = (insn >> 9) & 7; if (val == 0) val = 8; @@ -1621,7 +1631,7 @@ DISAS_INSN(addsubq) } gen_update_cc_add(dest, src2); } - DEST_EA(insn, OS_LONG, dest, &addr); + DEST_EA(env, insn, OS_LONG, dest, &addr); } DISAS_INSN(tpf) @@ -1636,7 +1646,7 @@ DISAS_INSN(tpf) case 4: /* No extension words. */ break; default: - disas_undef(s, insn); + disas_undef(env, s, insn); } } @@ -1651,10 +1661,10 @@ DISAS_INSN(branch) op = (insn >> 8) & 0xf; offset = (int8_t)insn; if (offset == 0) { - offset = cpu_ldsw_code(cpu_single_env, s->pc); + offset = cpu_ldsw_code(env, s->pc); s->pc += 2; } else if (offset == -1) { - offset = read_im32(s); + offset = read_im32(env, s); } if (op == 1) { /* bsr */ @@ -1693,7 +1703,7 @@ DISAS_INSN(mvzs) opsize = OS_WORD; else opsize = OS_BYTE; - SRC_EA(src, opsize, (insn & 0x80) == 0, NULL); + SRC_EA(env, src, opsize, (insn & 0x80) == 0, NULL); reg = DREG(insn, 9); tcg_gen_mov_i32(reg, src); gen_logic_cc(s, src); @@ -1709,11 +1719,11 @@ DISAS_INSN(or) reg = DREG(insn, 9); dest = tcg_temp_new(); if (insn & 0x100) { - SRC_EA(src, OS_LONG, 0, &addr); + SRC_EA(env, src, OS_LONG, 0, &addr); tcg_gen_or_i32(dest, src, reg); - DEST_EA(insn, OS_LONG, dest, &addr); + DEST_EA(env, insn, OS_LONG, dest, &addr); } else { - SRC_EA(src, OS_LONG, 0, NULL); + SRC_EA(env, src, OS_LONG, 0, NULL); tcg_gen_or_i32(dest, src, reg); tcg_gen_mov_i32(reg, dest); } @@ -1725,7 +1735,7 @@ DISAS_INSN(suba) TCGv src; TCGv reg; - SRC_EA(src, OS_LONG, 0, NULL); + SRC_EA(env, src, OS_LONG, 0, NULL); reg = AREG(insn, 9); tcg_gen_sub_i32(reg, reg, src); } @@ -1751,7 +1761,7 @@ DISAS_INSN(mov3q) val = -1; src = tcg_const_i32(val); gen_logic_cc(s, src); - DEST_EA(insn, OS_LONG, src, NULL); + DEST_EA(env, insn, OS_LONG, src, NULL); } DISAS_INSN(cmp) @@ -1779,7 +1789,7 @@ DISAS_INSN(cmp) default: abort(); } - SRC_EA(src, opsize, 1, NULL); + SRC_EA(env, src, opsize, 1, NULL); reg = DREG(insn, 9); dest = tcg_temp_new(); tcg_gen_sub_i32(dest, reg, src); @@ -1798,7 +1808,7 @@ DISAS_INSN(cmpa) } else { opsize = OS_WORD; } - SRC_EA(src, opsize, 1, NULL); + SRC_EA(env, src, opsize, 1, NULL); reg = AREG(insn, 9); dest = tcg_temp_new(); tcg_gen_sub_i32(dest, reg, src); @@ -1813,12 +1823,12 @@ DISAS_INSN(eor) TCGv dest; TCGv addr; - SRC_EA(src, OS_LONG, 0, &addr); + SRC_EA(env, src, OS_LONG, 0, &addr); reg = DREG(insn, 9); dest = tcg_temp_new(); tcg_gen_xor_i32(dest, src, reg); gen_logic_cc(s, dest); - DEST_EA(insn, OS_LONG, dest, &addr); + DEST_EA(env, insn, OS_LONG, dest, &addr); } DISAS_INSN(and) @@ -1831,11 +1841,11 @@ DISAS_INSN(and) reg = DREG(insn, 9); dest = tcg_temp_new(); if (insn & 0x100) { - SRC_EA(src, OS_LONG, 0, &addr); + SRC_EA(env, src, OS_LONG, 0, &addr); tcg_gen_and_i32(dest, src, reg); - DEST_EA(insn, OS_LONG, dest, &addr); + DEST_EA(env, insn, OS_LONG, dest, &addr); } else { - SRC_EA(src, OS_LONG, 0, NULL); + SRC_EA(env, src, OS_LONG, 0, NULL); tcg_gen_and_i32(dest, src, reg); tcg_gen_mov_i32(reg, dest); } @@ -1847,7 +1857,7 @@ DISAS_INSN(adda) TCGv src; TCGv reg; - SRC_EA(src, OS_LONG, 0, NULL); + SRC_EA(env, src, OS_LONG, 0, NULL); reg = AREG(insn, 9); tcg_gen_add_i32(reg, reg, src); } @@ -1936,13 +1946,13 @@ DISAS_INSN(strldsr) uint32_t addr; addr = s->pc - 2; - ext = cpu_lduw_code(cpu_single_env, s->pc); + ext = cpu_lduw_code(env, s->pc); s->pc += 2; if (ext != 0x46FC) { gen_exception(s, addr, EXCP_UNSUPPORTED); return; } - ext = cpu_lduw_code(cpu_single_env, s->pc); + ext = cpu_lduw_code(env, s->pc); s->pc += 2; if (IS_USER(s) || (ext & SR_S) == 0) { gen_exception(s, addr, EXCP_PRIVILEGE); @@ -1972,7 +1982,7 @@ DISAS_INSN(move_to_sr) gen_exception(s, s->pc - 2, EXCP_PRIVILEGE); return; } - gen_set_sr(s, insn, 0); + gen_set_sr(env, s, insn, 0); gen_lookup_tb(s); } @@ -2010,7 +2020,7 @@ DISAS_INSN(stop) return; } - ext = cpu_lduw_code(cpu_single_env, s->pc); + ext = cpu_lduw_code(env, s->pc); s->pc += 2; gen_set_sr_im(s, ext, 0); @@ -2037,7 +2047,7 @@ DISAS_INSN(movec) return; } - ext = cpu_lduw_code(cpu_single_env, s->pc); + ext = cpu_lduw_code(env, s->pc); s->pc += 2; if (ext & 0x8000) { @@ -2102,7 +2112,7 @@ DISAS_INSN(fpu) int set_dest; int opsize; - ext = cpu_lduw_code(cpu_single_env, s->pc); + ext = cpu_lduw_code(env, s->pc); s->pc += 2; opmode = ext & 0x7f; switch ((ext >> 13) & 7) { @@ -2138,7 +2148,7 @@ DISAS_INSN(fpu) tcg_gen_addi_i32(tmp32, tmp32, -8); break; case 5: - offset = cpu_ldsw_code(cpu_single_env, s->pc); + offset = cpu_ldsw_code(env, s->pc); s->pc += 2; tcg_gen_addi_i32(tmp32, tmp32, offset); break; @@ -2164,7 +2174,7 @@ DISAS_INSN(fpu) default: goto undef; } - DEST_EA(insn, opsize, tmp32, NULL); + DEST_EA(env, insn, opsize, tmp32, NULL); tcg_temp_free_i32(tmp32); return; case 4: /* fmove to control register. */ @@ -2192,7 +2202,7 @@ DISAS_INSN(fpu) (ext >> 10) & 7); goto undef; } - DEST_EA(insn, OS_LONG, tmp32, NULL); + DEST_EA(env, insn, OS_LONG, tmp32, NULL); break; case 6: /* fmovem */ case 7: @@ -2202,7 +2212,7 @@ DISAS_INSN(fpu) int i; if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0) goto undef; - tmp32 = gen_lea(s, insn, OS_LONG); + tmp32 = gen_lea(env, s, insn, OS_LONG); if (IS_NULL_QREG(tmp32)) { gen_addr_fault(s); return; @@ -2252,12 +2262,12 @@ DISAS_INSN(fpu) tcg_gen_addi_i32(tmp32, tmp32, -8); break; case 5: - offset = cpu_ldsw_code(cpu_single_env, s->pc); + offset = cpu_ldsw_code(env, s->pc); s->pc += 2; tcg_gen_addi_i32(tmp32, tmp32, offset); break; case 7: - offset = cpu_ldsw_code(cpu_single_env, s->pc); + offset = cpu_ldsw_code(env, s->pc); offset += s->pc - 2; s->pc += 2; tcg_gen_addi_i32(tmp32, tmp32, offset); @@ -2277,7 +2287,7 @@ DISAS_INSN(fpu) } tcg_temp_free_i32(tmp32); } else { - SRC_EA(tmp32, opsize, 1, NULL); + SRC_EA(env, tmp32, opsize, 1, NULL); src = tcg_temp_new_i64(); switch (opsize) { case OS_LONG: @@ -2372,7 +2382,7 @@ DISAS_INSN(fpu) undef: /* FIXME: Is this right for offset addressing modes? */ s->pc -= 2; - disas_undef_fpu(s, insn); + disas_undef_fpu(env, s, insn); } DISAS_INSN(fbcc) @@ -2383,10 +2393,10 @@ DISAS_INSN(fbcc) int l1; addr = s->pc; - offset = cpu_ldsw_code(cpu_single_env, s->pc); + offset = cpu_ldsw_code(env, s->pc); s->pc += 2; if (insn & (1 << 6)) { - offset = (offset << 16) | cpu_lduw_code(cpu_single_env, s->pc); + offset = (offset << 16) | cpu_lduw_code(env, s->pc); s->pc += 2; } @@ -2508,18 +2518,18 @@ DISAS_INSN(mac) s->done_mac = 1; } - ext = cpu_lduw_code(cpu_single_env, s->pc); + ext = cpu_lduw_code(env, s->pc); s->pc += 2; acc = ((insn >> 7) & 1) | ((ext >> 3) & 2); dual = ((insn & 0x30) != 0 && (ext & 3) != 0); if (dual && !m68k_feature(s->env, M68K_FEATURE_CF_EMAC_B)) { - disas_undef(s, insn); + disas_undef(env, s, insn); return; } if (insn & 0x30) { /* MAC with load. */ - tmp = gen_lea(s, insn, OS_LONG); + tmp = gen_lea(env, s, insn, OS_LONG); addr = tcg_temp_new(); tcg_gen_and_i32(addr, tmp, QREG_MAC_MASK); /* Load the value now to ensure correct exception behavior. @@ -2733,7 +2743,7 @@ DISAS_INSN(to_mac) int accnum; accnum = (insn >> 9) & 3; acc = MACREG(accnum); - SRC_EA(val, OS_LONG, 0, NULL); + SRC_EA(env, val, OS_LONG, 0, NULL); if (s->env->macsr & MACSR_FI) { tcg_gen_ext_i32_i64(acc, val); tcg_gen_shli_i64(acc, acc, 8); @@ -2750,7 +2760,7 @@ DISAS_INSN(to_mac) DISAS_INSN(to_macsr) { TCGv val; - SRC_EA(val, OS_LONG, 0, NULL); + SRC_EA(env, val, OS_LONG, 0, NULL); gen_helper_set_macsr(cpu_env, val); gen_lookup_tb(s); } @@ -2758,7 +2768,7 @@ DISAS_INSN(to_macsr) DISAS_INSN(to_mask) { TCGv val; - SRC_EA(val, OS_LONG, 0, NULL); + SRC_EA(env, val, OS_LONG, 0, NULL); tcg_gen_ori_i32(QREG_MAC_MASK, val, 0xffff0000); } @@ -2766,7 +2776,7 @@ DISAS_INSN(to_mext) { TCGv val; TCGv acc; - SRC_EA(val, OS_LONG, 0, NULL); + SRC_EA(env, val, OS_LONG, 0, NULL); acc = tcg_const_i32((insn & 0x400) ? 2 : 0); if (s->env->macsr & MACSR_FI) gen_helper_set_mac_extf(cpu_env, val, acc); @@ -2943,10 +2953,10 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s) { uint16_t insn; - insn = cpu_lduw_code(cpu_single_env, s->pc); + insn = cpu_lduw_code(env, s->pc); s->pc += 2; - opcode_table[insn](s, insn); + opcode_table[insn](env, s, insn); } /* generate intermediate code for basic block 'tb'. */ From 04a130eaa10f3d2af6ac9fb68a8daffd40a2f9aa Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 07:42:33 +0000 Subject: [PATCH 0394/2270] target-unicore32: switch to AREG0 free mode Add an explicit CPUState parameter instead of relying on AREG0 and switch to AREG0 free mode. Tested-by: Guan Xuetao Signed-off-by: Blue Swirl --- configure | 2 +- target-unicore32/Makefile.objs | 2 -- target-unicore32/helper.h | 26 +++++++------- target-unicore32/op_helper.c | 65 +++++++++++++--------------------- target-unicore32/translate.c | 38 ++++++++++---------- 5 files changed, 58 insertions(+), 75 deletions(-) diff --git a/configure b/configure index f01e2e9a11..f6ec4be9a2 100755 --- a/configure +++ b/configure @@ -3874,7 +3874,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile" case "$target_arch2" in - alpha | i386 | lm32 | m68k | or32 | s390x | sparc* | x86_64 | xtensa* | ppc*) + alpha | i386 | lm32 | m68k | or32 | s390x | sparc* | unicore32 | x86_64 | xtensa* | ppc*) echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak ;; esac diff --git a/target-unicore32/Makefile.objs b/target-unicore32/Makefile.objs index 777f01fef8..8e143da937 100644 --- a/target-unicore32/Makefile.objs +++ b/target-unicore32/Makefile.objs @@ -2,5 +2,3 @@ obj-y += translate.o op_helper.o helper.o cpu.o obj-y += ucf64_helper.o obj-$(CONFIG_SOFTMMU) += machine.o softmmu.o - -$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-unicore32/helper.h b/target-unicore32/helper.h index 305318ae59..a4b81494aa 100644 --- a/target-unicore32/helper.h +++ b/target-unicore32/helper.h @@ -17,26 +17,26 @@ DEF_HELPER_1(cp1_putc, void, i32) DEF_HELPER_1(clz, i32, i32) DEF_HELPER_1(clo, i32, i32) -DEF_HELPER_1(exception, void, i32) +DEF_HELPER_2(exception, void, env, i32) -DEF_HELPER_2(asr_write, void, i32, i32) -DEF_HELPER_0(asr_read, i32) +DEF_HELPER_3(asr_write, void, env, i32, i32) +DEF_HELPER_1(asr_read, i32, env) -DEF_HELPER_1(get_user_reg, i32, i32) -DEF_HELPER_2(set_user_reg, void, i32, i32) +DEF_HELPER_2(get_user_reg, i32, env, i32) +DEF_HELPER_3(set_user_reg, void, env, i32, i32) -DEF_HELPER_2(add_cc, i32, i32, i32) -DEF_HELPER_2(adc_cc, i32, i32, i32) -DEF_HELPER_2(sub_cc, i32, i32, i32) -DEF_HELPER_2(sbc_cc, i32, i32, i32) +DEF_HELPER_3(add_cc, i32, env, i32, i32) +DEF_HELPER_3(adc_cc, i32, env, i32, i32) +DEF_HELPER_3(sub_cc, i32, env, i32, i32) +DEF_HELPER_3(sbc_cc, i32, env, i32, i32) DEF_HELPER_2(shl, i32, i32, i32) DEF_HELPER_2(shr, i32, i32, i32) DEF_HELPER_2(sar, i32, i32, i32) -DEF_HELPER_2(shl_cc, i32, i32, i32) -DEF_HELPER_2(shr_cc, i32, i32, i32) -DEF_HELPER_2(sar_cc, i32, i32, i32) -DEF_HELPER_2(ror_cc, i32, i32, i32) +DEF_HELPER_3(shl_cc, i32, env, i32, i32) +DEF_HELPER_3(shr_cc, i32, env, i32, i32) +DEF_HELPER_3(sar_cc, i32, env, i32, i32) +DEF_HELPER_3(ror_cc, i32, env, i32, i32) DEF_HELPER_1(ucf64_get_fpscr, i32, env) DEF_HELPER_2(ucf64_set_fpscr, void, env, i32) diff --git a/target-unicore32/op_helper.c b/target-unicore32/op_helper.c index c63789d6cb..f474d1b59b 100644 --- a/target-unicore32/op_helper.c +++ b/target-unicore32/op_helper.c @@ -9,19 +9,18 @@ * later version. See the COPYING file in the top-level directory. */ #include "cpu.h" -#include "dyngen-exec.h" #include "helper.h" #define SIGNBIT (uint32_t)0x80000000 #define SIGNBIT64 ((uint64_t)1 << 63) -void HELPER(exception)(uint32_t excp) +void HELPER(exception)(CPUUniCore32State *env, uint32_t excp) { env->exception_index = excp; cpu_loop_exit(env); } -static target_ulong asr_read(void) +static target_ulong asr_read(CPUUniCore32State *env) { int ZF; ZF = (env->ZF == 0); @@ -29,24 +28,18 @@ static target_ulong asr_read(void) (env->CF << 29) | ((env->VF & 0x80000000) >> 3); } -target_ulong cpu_asr_read(CPUUniCore32State *env1) +target_ulong cpu_asr_read(CPUUniCore32State *env) { - CPUUniCore32State *saved_env; - target_ulong ret; - - saved_env = env; - env = env1; - ret = asr_read(); - env = saved_env; - return ret; + return asr_read(env); } -target_ulong HELPER(asr_read)(void) +target_ulong HELPER(asr_read)(CPUUniCore32State *env) { - return asr_read(); + return asr_read(env); } -static void asr_write(target_ulong val, target_ulong mask) +static void asr_write(CPUUniCore32State *env, target_ulong val, + target_ulong mask) { if (mask & ASR_NZCV) { env->ZF = (~val) & ASR_Z; @@ -62,23 +55,19 @@ static void asr_write(target_ulong val, target_ulong mask) env->uncached_asr = (env->uncached_asr & ~mask) | (val & mask); } -void cpu_asr_write(CPUUniCore32State *env1, target_ulong val, target_ulong mask) +void cpu_asr_write(CPUUniCore32State *env, target_ulong val, target_ulong mask) { - CPUUniCore32State *saved_env; - - saved_env = env; - env = env1; - asr_write(val, mask); - env = saved_env; + asr_write(env, val, mask); } -void HELPER(asr_write)(target_ulong val, target_ulong mask) +void HELPER(asr_write)(CPUUniCore32State *env, target_ulong val, + target_ulong mask) { - asr_write(val, mask); + asr_write(env, val, mask); } /* Access to user mode registers from privileged modes. */ -uint32_t HELPER(get_user_reg)(uint32_t regno) +uint32_t HELPER(get_user_reg)(CPUUniCore32State *env, uint32_t regno) { uint32_t val; @@ -92,7 +81,7 @@ uint32_t HELPER(get_user_reg)(uint32_t regno) return val; } -void HELPER(set_user_reg)(uint32_t regno, uint32_t val) +void HELPER(set_user_reg)(CPUUniCore32State *env, uint32_t regno, uint32_t val) { if (regno == 29) { env->banked_r29[0] = val; @@ -107,7 +96,7 @@ void HELPER(set_user_reg)(uint32_t regno, uint32_t val) The only way to do that in TCG is a conditional branch, which clobbers all our temporaries. For now implement these as helper functions. */ -uint32_t HELPER(add_cc)(uint32_t a, uint32_t b) +uint32_t HELPER(add_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b) { uint32_t result; result = a + b; @@ -117,7 +106,7 @@ uint32_t HELPER(add_cc)(uint32_t a, uint32_t b) return result; } -uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b) +uint32_t HELPER(adc_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b) { uint32_t result; if (!env->CF) { @@ -132,7 +121,7 @@ uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b) return result; } -uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b) +uint32_t HELPER(sub_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b) { uint32_t result; result = a - b; @@ -142,7 +131,7 @@ uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b) return result; } -uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b) +uint32_t HELPER(sbc_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b) { uint32_t result; if (!env->CF) { @@ -186,7 +175,7 @@ uint32_t HELPER(sar)(uint32_t x, uint32_t i) return (int32_t)x >> shift; } -uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i) +uint32_t HELPER(shl_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i) { int shift = i & 0xff; if (shift >= 32) { @@ -203,7 +192,7 @@ uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i) return x; } -uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i) +uint32_t HELPER(shr_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i) { int shift = i & 0xff; if (shift >= 32) { @@ -220,7 +209,7 @@ uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i) return x; } -uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i) +uint32_t HELPER(sar_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i) { int shift = i & 0xff; if (shift >= 32) { @@ -233,7 +222,7 @@ uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i) return x; } -uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i) +uint32_t HELPER(ror_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i) { int shift1, shift; shift1 = i & 0xff; @@ -264,16 +253,13 @@ uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i) #define SHIFT 3 #include "softmmu_template.h" -void tlb_fill(CPUUniCore32State *env1, target_ulong addr, int is_write, - int mmu_idx, uintptr_t retaddr) +void tlb_fill(CPUUniCore32State *env, target_ulong addr, int is_write, + int mmu_idx, uintptr_t retaddr) { TranslationBlock *tb; - CPUUniCore32State *saved_env; unsigned long pc; int ret; - saved_env = env; - env = env1; ret = uc32_cpu_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { @@ -287,6 +273,5 @@ void tlb_fill(CPUUniCore32State *env1, target_ulong addr, int is_write, } cpu_loop_exit(env); } - env = saved_env; } #endif diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index 188bf8c52a..b786a6b890 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -253,7 +253,7 @@ static void disas_ocd_insn(CPUUniCore32State *env, DisasContext *s, static inline void gen_set_asr(TCGv var, uint32_t mask) { TCGv tmp_mask = tcg_const_i32(mask); - gen_helper_asr_write(var, tmp_mask); + gen_helper_asr_write(cpu_env, var, tmp_mask); tcg_temp_free_i32(tmp_mask); } /* Set NZCV flags from the high 4 bits of var. */ @@ -263,7 +263,7 @@ static void gen_exception(int excp) { TCGv tmp = new_tmp(); tcg_gen_movi_i32(tmp, excp); - gen_helper_exception(tmp); + gen_helper_exception(cpu_env, tmp); dead_tmp(tmp); } @@ -416,16 +416,16 @@ static inline void gen_uc32_shift_reg(TCGv var, int shiftop, if (flags) { switch (shiftop) { case 0: - gen_helper_shl_cc(var, var, shift); + gen_helper_shl_cc(var, cpu_env, var, shift); break; case 1: - gen_helper_shr_cc(var, var, shift); + gen_helper_shr_cc(var, cpu_env, var, shift); break; case 2: - gen_helper_sar_cc(var, var, shift); + gen_helper_sar_cc(var, cpu_env, var, shift); break; case 3: - gen_helper_ror_cc(var, var, shift); + gen_helper_ror_cc(var, cpu_env, var, shift); break; } } else { @@ -1323,11 +1323,11 @@ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn) if (IS_USER(s)) { ILLEGAL; } - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); gen_exception_return(s, tmp); } else { if (UCOP_SET_S) { - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); } else { tcg_gen_sub_i32(tmp, tmp, tmp2); } @@ -1336,7 +1336,7 @@ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn) break; case 0x03: if (UCOP_SET_S) { - gen_helper_sub_cc(tmp, tmp2, tmp); + gen_helper_sub_cc(tmp, cpu_env, tmp2, tmp); } else { tcg_gen_sub_i32(tmp, tmp2, tmp); } @@ -1344,7 +1344,7 @@ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn) break; case 0x04: if (UCOP_SET_S) { - gen_helper_add_cc(tmp, tmp, tmp2); + gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); } else { tcg_gen_add_i32(tmp, tmp, tmp2); } @@ -1352,7 +1352,7 @@ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn) break; case 0x05: if (UCOP_SET_S) { - gen_helper_adc_cc(tmp, tmp, tmp2); + gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2); } else { gen_add_carry(tmp, tmp, tmp2); } @@ -1360,7 +1360,7 @@ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn) break; case 0x06: if (UCOP_SET_S) { - gen_helper_sbc_cc(tmp, tmp, tmp2); + gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2); } else { gen_sub_carry(tmp, tmp, tmp2); } @@ -1368,7 +1368,7 @@ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn) break; case 0x07: if (UCOP_SET_S) { - gen_helper_sbc_cc(tmp, tmp2, tmp); + gen_helper_sbc_cc(tmp, cpu_env, tmp2, tmp); } else { gen_sub_carry(tmp, tmp2, tmp); } @@ -1390,13 +1390,13 @@ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn) break; case 0x0a: if (UCOP_SET_S) { - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); } dead_tmp(tmp); break; case 0x0b: if (UCOP_SET_S) { - gen_helper_add_cc(tmp, tmp, tmp2); + gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); } dead_tmp(tmp); break; @@ -1536,7 +1536,7 @@ static void do_misc(CPUUniCore32State *env, DisasContext *s, uint32_t insn) tmp = load_cpu_field(bsr); } else { tmp = new_tmp(); - gen_helper_asr_read(tmp); + gen_helper_asr_read(tmp, cpu_env); } store_reg(s, UCOP_REG_D, tmp); return; @@ -1760,7 +1760,7 @@ static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn) gen_bx(s, tmp); } else if (user) { tmp2 = tcg_const_i32(reg); - gen_helper_set_user_reg(tmp2, tmp); + gen_helper_set_user_reg(cpu_env, tmp2, tmp); tcg_temp_free_i32(tmp2); dead_tmp(tmp); } else if (reg == UCOP_REG_N) { @@ -1778,7 +1778,7 @@ static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn) } else if (user) { tmp = new_tmp(); tmp2 = tcg_const_i32(reg); - gen_helper_get_user_reg(tmp, tmp2); + gen_helper_get_user_reg(tmp, cpu_env, tmp2); tcg_temp_free_i32(tmp2); } else { tmp = load_reg(s, reg); @@ -1861,7 +1861,7 @@ static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s) { unsigned int insn; - insn = ldl_code(s->pc); + insn = cpu_ldl_code(env, s->pc); s->pc += 4; /* UniCore instructions class: From 1ce94f81eca411b64c71a05b11e4c51dea86639f Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Tue, 4 Sep 2012 20:08:34 +0000 Subject: [PATCH 0395/2270] target-arm: convert void helpers Add an explicit CPUState parameter instead of relying on AREG0. For easier review, convert only op helpers which don't return any value. Signed-off-by: Blue Swirl Reviewed-by: Peter Maydell --- target-arm/helper.h | 8 ++++---- target-arm/op_helper.c | 20 ++++++++++---------- target-arm/translate.c | 8 ++++---- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/target-arm/helper.h b/target-arm/helper.h index 21e9cfe05f..106aacdcf5 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -50,10 +50,10 @@ DEF_HELPER_2(usad8, i32, i32, i32) DEF_HELPER_1(logicq_cc, i32, i64) DEF_HELPER_3(sel_flags, i32, i32, i32, i32) -DEF_HELPER_1(exception, void, i32) -DEF_HELPER_0(wfi, void) +DEF_HELPER_2(exception, void, env, i32) +DEF_HELPER_1(wfi, void, env) -DEF_HELPER_2(cpsr_write, void, i32, i32) +DEF_HELPER_3(cpsr_write, void, env, i32, i32) DEF_HELPER_0(cpsr_read, i32) DEF_HELPER_3(v7m_msr, void, env, i32, i32) @@ -68,7 +68,7 @@ DEF_HELPER_2(get_r13_banked, i32, env, i32) DEF_HELPER_3(set_r13_banked, void, env, i32, i32) DEF_HELPER_1(get_user_reg, i32, i32) -DEF_HELPER_2(set_user_reg, void, i32, i32) +DEF_HELPER_3(set_user_reg, void, env, i32, i32) DEF_HELPER_1(vfp_get_fpscr, i32, env) DEF_HELPER_2(vfp_set_fpscr, void, env, i32) diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index d77bfab771..b1adce317f 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -23,7 +23,7 @@ #define SIGNBIT (uint32_t)0x80000000 #define SIGNBIT64 ((uint64_t)1 << 63) -static void raise_exception(int tt) +static void raise_exception(CPUARMState *env, int tt) { env->exception_index = tt; cpu_loop_exit(env); @@ -93,7 +93,7 @@ void tlb_fill(CPUARMState *env1, target_ulong addr, int is_write, int mmu_idx, cpu_restore_state(tb, env, retaddr); } } - raise_exception(env->exception_index); + raise_exception(env, env->exception_index); } env = saved_env; } @@ -230,14 +230,14 @@ uint32_t HELPER(usat16)(uint32_t x, uint32_t shift) return res; } -void HELPER(wfi)(void) +void HELPER(wfi)(CPUARMState *env) { env->exception_index = EXCP_HLT; env->halted = 1; cpu_loop_exit(env); } -void HELPER(exception)(uint32_t excp) +void HELPER(exception)(CPUARMState *env, uint32_t excp) { env->exception_index = excp; cpu_loop_exit(env); @@ -248,7 +248,7 @@ uint32_t HELPER(cpsr_read)(void) return cpsr_read(env) & ~CPSR_EXEC; } -void HELPER(cpsr_write)(uint32_t val, uint32_t mask) +void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask) { cpsr_write(env, val, mask); } @@ -271,7 +271,7 @@ uint32_t HELPER(get_user_reg)(uint32_t regno) return val; } -void HELPER(set_user_reg)(uint32_t regno, uint32_t val) +void HELPER(set_user_reg)(CPUARMState *env, uint32_t regno, uint32_t val) { if (regno == 13) { env->banked_r13[0] = val; @@ -290,7 +290,7 @@ void HELPER(set_cp_reg)(CPUARMState *env, void *rip, uint32_t value) const ARMCPRegInfo *ri = rip; int excp = ri->writefn(env, ri, value); if (excp) { - raise_exception(excp); + raise_exception(env, excp); } } @@ -300,7 +300,7 @@ uint32_t HELPER(get_cp_reg)(CPUARMState *env, void *rip) uint64_t value; int excp = ri->readfn(env, ri, &value); if (excp) { - raise_exception(excp); + raise_exception(env, excp); } return value; } @@ -310,7 +310,7 @@ void HELPER(set_cp_reg64)(CPUARMState *env, void *rip, uint64_t value) const ARMCPRegInfo *ri = rip; int excp = ri->writefn(env, ri, value); if (excp) { - raise_exception(excp); + raise_exception(env, excp); } } @@ -320,7 +320,7 @@ uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void *rip) uint64_t value; int excp = ri->readfn(env, ri, &value); if (excp) { - raise_exception(excp); + raise_exception(env, excp); } return value; } diff --git a/target-arm/translate.c b/target-arm/translate.c index edef79a2cf..6f651d93c7 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -199,7 +199,7 @@ static void store_reg(DisasContext *s, int reg, TCGv var) static inline void gen_set_cpsr(TCGv var, uint32_t mask) { TCGv tmp_mask = tcg_const_i32(mask); - gen_helper_cpsr_write(var, tmp_mask); + gen_helper_cpsr_write(cpu_env, var, tmp_mask); tcg_temp_free_i32(tmp_mask); } /* Set NZCV flags from the high 4 bits of var. */ @@ -209,7 +209,7 @@ static void gen_exception(int excp) { TCGv tmp = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp, excp); - gen_helper_exception(tmp); + gen_helper_exception(cpu_env, tmp); tcg_temp_free_i32(tmp); } @@ -7719,7 +7719,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) tmp = gen_ld32(addr, IS_USER(s)); if (user) { tmp2 = tcg_const_i32(i); - gen_helper_set_user_reg(tmp2, tmp); + gen_helper_set_user_reg(cpu_env, tmp2, tmp); tcg_temp_free_i32(tmp2); tcg_temp_free_i32(tmp); } else if (i == rn) { @@ -9913,7 +9913,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env, /* nothing more to generate */ break; case DISAS_WFI: - gen_helper_wfi(); + gen_helper_wfi(cpu_env); break; case DISAS_SWI: gen_exception(EXCP_SWI); From 9ef392772597693b07959460f6c27b9b5a8287a1 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Tue, 4 Sep 2012 20:19:15 +0000 Subject: [PATCH 0396/2270] target-arm: convert remaining helpers Convert remaining helpers to AREG0 free mode: add an explicit CPUState parameter instead of relying on AREG0. Signed-off-by: Blue Swirl Reviewed-by: Peter Maydell --- target-arm/helper.h | 48 +++++++-------- target-arm/op_helper.c | 64 ++++++++++---------- target-arm/translate.c | 134 ++++++++++++++++++++--------------------- 3 files changed, 123 insertions(+), 123 deletions(-) diff --git a/target-arm/helper.h b/target-arm/helper.h index 106aacdcf5..afdb2b5b1a 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -4,12 +4,12 @@ DEF_HELPER_1(clz, i32, i32) DEF_HELPER_1(sxtb16, i32, i32) DEF_HELPER_1(uxtb16, i32, i32) -DEF_HELPER_2(add_setq, i32, i32, i32) -DEF_HELPER_2(add_saturate, i32, i32, i32) -DEF_HELPER_2(sub_saturate, i32, i32, i32) -DEF_HELPER_2(add_usaturate, i32, i32, i32) -DEF_HELPER_2(sub_usaturate, i32, i32, i32) -DEF_HELPER_1(double_saturate, i32, s32) +DEF_HELPER_3(add_setq, i32, env, i32, i32) +DEF_HELPER_3(add_saturate, i32, env, i32, i32) +DEF_HELPER_3(sub_saturate, i32, env, i32, i32) +DEF_HELPER_3(add_usaturate, i32, env, i32, i32) +DEF_HELPER_3(sub_usaturate, i32, env, i32, i32) +DEF_HELPER_2(double_saturate, i32, env, s32) DEF_HELPER_2(sdiv, s32, s32, s32) DEF_HELPER_2(udiv, i32, i32, i32) DEF_HELPER_1(rbit, i32, i32) @@ -40,10 +40,10 @@ PAS_OP(uq) PAS_OP(uh) #undef PAS_OP -DEF_HELPER_2(ssat, i32, i32, i32) -DEF_HELPER_2(usat, i32, i32, i32) -DEF_HELPER_2(ssat16, i32, i32, i32) -DEF_HELPER_2(usat16, i32, i32, i32) +DEF_HELPER_3(ssat, i32, env, i32, i32) +DEF_HELPER_3(usat, i32, env, i32, i32) +DEF_HELPER_3(ssat16, i32, env, i32, i32) +DEF_HELPER_3(usat16, i32, env, i32, i32) DEF_HELPER_2(usad8, i32, i32, i32) @@ -54,7 +54,7 @@ DEF_HELPER_2(exception, void, env, i32) DEF_HELPER_1(wfi, void, env) DEF_HELPER_3(cpsr_write, void, env, i32, i32) -DEF_HELPER_0(cpsr_read, i32) +DEF_HELPER_1(cpsr_read, i32, env) DEF_HELPER_3(v7m_msr, void, env, i32, i32) DEF_HELPER_2(v7m_mrs, i32, env, i32) @@ -67,7 +67,7 @@ DEF_HELPER_2(get_cp_reg64, i64, env, ptr) DEF_HELPER_2(get_r13_banked, i32, env, i32) DEF_HELPER_3(set_r13_banked, void, env, i32, i32) -DEF_HELPER_1(get_user_reg, i32, i32) +DEF_HELPER_2(get_user_reg, i32, env, i32) DEF_HELPER_3(set_user_reg, void, env, i32, i32) DEF_HELPER_1(vfp_get_fpscr, i32, env) @@ -140,20 +140,20 @@ DEF_HELPER_2(recpe_f32, f32, f32, env) DEF_HELPER_2(rsqrte_f32, f32, f32, env) DEF_HELPER_2(recpe_u32, i32, i32, env) DEF_HELPER_2(rsqrte_u32, i32, i32, env) -DEF_HELPER_4(neon_tbl, i32, i32, i32, i32, i32) +DEF_HELPER_5(neon_tbl, i32, env, i32, i32, i32, i32) -DEF_HELPER_2(add_cc, i32, i32, i32) -DEF_HELPER_2(adc_cc, i32, i32, i32) -DEF_HELPER_2(sub_cc, i32, i32, i32) -DEF_HELPER_2(sbc_cc, i32, i32, i32) +DEF_HELPER_3(add_cc, i32, env, i32, i32) +DEF_HELPER_3(adc_cc, i32, env, i32, i32) +DEF_HELPER_3(sub_cc, i32, env, i32, i32) +DEF_HELPER_3(sbc_cc, i32, env, i32, i32) -DEF_HELPER_2(shl, i32, i32, i32) -DEF_HELPER_2(shr, i32, i32, i32) -DEF_HELPER_2(sar, i32, i32, i32) -DEF_HELPER_2(shl_cc, i32, i32, i32) -DEF_HELPER_2(shr_cc, i32, i32, i32) -DEF_HELPER_2(sar_cc, i32, i32, i32) -DEF_HELPER_2(ror_cc, i32, i32, i32) +DEF_HELPER_3(shl, i32, env, i32, i32) +DEF_HELPER_3(shr, i32, env, i32, i32) +DEF_HELPER_3(sar, i32, env, i32, i32) +DEF_HELPER_3(shl_cc, i32, env, i32, i32) +DEF_HELPER_3(shr_cc, i32, env, i32, i32) +DEF_HELPER_3(sar_cc, i32, env, i32, i32) +DEF_HELPER_3(ror_cc, i32, env, i32, i32) /* neon_helper.c */ DEF_HELPER_3(neon_qadd_u8, i32, env, i32, i32) diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index b1adce317f..5b868bf846 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -29,7 +29,7 @@ static void raise_exception(CPUARMState *env, int tt) cpu_loop_exit(env); } -uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def, +uint32_t HELPER(neon_tbl)(CPUARMState *env, uint32_t ireg, uint32_t def, uint32_t rn, uint32_t maxindex) { uint32_t val; @@ -101,7 +101,7 @@ void tlb_fill(CPUARMState *env1, target_ulong addr, int is_write, int mmu_idx, /* FIXME: Pass an explicit pointer to QF to CPUARMState, and move saturating instructions into helper.c */ -uint32_t HELPER(add_setq)(uint32_t a, uint32_t b) +uint32_t HELPER(add_setq)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t res = a + b; if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) @@ -109,7 +109,7 @@ uint32_t HELPER(add_setq)(uint32_t a, uint32_t b) return res; } -uint32_t HELPER(add_saturate)(uint32_t a, uint32_t b) +uint32_t HELPER(add_saturate)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t res = a + b; if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) { @@ -119,7 +119,7 @@ uint32_t HELPER(add_saturate)(uint32_t a, uint32_t b) return res; } -uint32_t HELPER(sub_saturate)(uint32_t a, uint32_t b) +uint32_t HELPER(sub_saturate)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t res = a - b; if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) { @@ -129,7 +129,7 @@ uint32_t HELPER(sub_saturate)(uint32_t a, uint32_t b) return res; } -uint32_t HELPER(double_saturate)(int32_t val) +uint32_t HELPER(double_saturate)(CPUARMState *env, int32_t val) { uint32_t res; if (val >= 0x40000000) { @@ -144,7 +144,7 @@ uint32_t HELPER(double_saturate)(int32_t val) return res; } -uint32_t HELPER(add_usaturate)(uint32_t a, uint32_t b) +uint32_t HELPER(add_usaturate)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t res = a + b; if (res < a) { @@ -154,7 +154,7 @@ uint32_t HELPER(add_usaturate)(uint32_t a, uint32_t b) return res; } -uint32_t HELPER(sub_usaturate)(uint32_t a, uint32_t b) +uint32_t HELPER(sub_usaturate)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t res = a - b; if (res > a) { @@ -165,7 +165,7 @@ uint32_t HELPER(sub_usaturate)(uint32_t a, uint32_t b) } /* Signed saturation. */ -static inline uint32_t do_ssat(int32_t val, int shift) +static inline uint32_t do_ssat(CPUARMState *env, int32_t val, int shift) { int32_t top; uint32_t mask; @@ -183,7 +183,7 @@ static inline uint32_t do_ssat(int32_t val, int shift) } /* Unsigned saturation. */ -static inline uint32_t do_usat(int32_t val, int shift) +static inline uint32_t do_usat(CPUARMState *env, int32_t val, int shift) { uint32_t max; @@ -199,34 +199,34 @@ static inline uint32_t do_usat(int32_t val, int shift) } /* Signed saturate. */ -uint32_t HELPER(ssat)(uint32_t x, uint32_t shift) +uint32_t HELPER(ssat)(CPUARMState *env, uint32_t x, uint32_t shift) { - return do_ssat(x, shift); + return do_ssat(env, x, shift); } /* Dual halfword signed saturate. */ -uint32_t HELPER(ssat16)(uint32_t x, uint32_t shift) +uint32_t HELPER(ssat16)(CPUARMState *env, uint32_t x, uint32_t shift) { uint32_t res; - res = (uint16_t)do_ssat((int16_t)x, shift); - res |= do_ssat(((int32_t)x) >> 16, shift) << 16; + res = (uint16_t)do_ssat(env, (int16_t)x, shift); + res |= do_ssat(env, ((int32_t)x) >> 16, shift) << 16; return res; } /* Unsigned saturate. */ -uint32_t HELPER(usat)(uint32_t x, uint32_t shift) +uint32_t HELPER(usat)(CPUARMState *env, uint32_t x, uint32_t shift) { - return do_usat(x, shift); + return do_usat(env, x, shift); } /* Dual halfword unsigned saturate. */ -uint32_t HELPER(usat16)(uint32_t x, uint32_t shift) +uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift) { uint32_t res; - res = (uint16_t)do_usat((int16_t)x, shift); - res |= do_usat(((int32_t)x) >> 16, shift) << 16; + res = (uint16_t)do_usat(env, (int16_t)x, shift); + res |= do_usat(env, ((int32_t)x) >> 16, shift) << 16; return res; } @@ -243,7 +243,7 @@ void HELPER(exception)(CPUARMState *env, uint32_t excp) cpu_loop_exit(env); } -uint32_t HELPER(cpsr_read)(void) +uint32_t HELPER(cpsr_read)(CPUARMState *env) { return cpsr_read(env) & ~CPSR_EXEC; } @@ -254,7 +254,7 @@ void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask) } /* Access to user mode registers from privileged modes. */ -uint32_t HELPER(get_user_reg)(uint32_t regno) +uint32_t HELPER(get_user_reg)(CPUARMState *env, uint32_t regno) { uint32_t val; @@ -329,7 +329,7 @@ uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void *rip) The only way to do that in TCG is a conditional branch, which clobbers all our temporaries. For now implement these as helper functions. */ -uint32_t HELPER (add_cc)(uint32_t a, uint32_t b) +uint32_t HELPER (add_cc)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t result; result = a + b; @@ -339,7 +339,7 @@ uint32_t HELPER (add_cc)(uint32_t a, uint32_t b) return result; } -uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b) +uint32_t HELPER(adc_cc)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t result; if (!env->CF) { @@ -354,7 +354,7 @@ uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b) return result; } -uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b) +uint32_t HELPER(sub_cc)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t result; result = a - b; @@ -364,7 +364,7 @@ uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b) return result; } -uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b) +uint32_t HELPER(sbc_cc)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t result; if (!env->CF) { @@ -381,7 +381,7 @@ uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b) /* Similarly for variable shift instructions. */ -uint32_t HELPER(shl)(uint32_t x, uint32_t i) +uint32_t HELPER(shl)(CPUARMState *env, uint32_t x, uint32_t i) { int shift = i & 0xff; if (shift >= 32) @@ -389,7 +389,7 @@ uint32_t HELPER(shl)(uint32_t x, uint32_t i) return x << shift; } -uint32_t HELPER(shr)(uint32_t x, uint32_t i) +uint32_t HELPER(shr)(CPUARMState *env, uint32_t x, uint32_t i) { int shift = i & 0xff; if (shift >= 32) @@ -397,7 +397,7 @@ uint32_t HELPER(shr)(uint32_t x, uint32_t i) return (uint32_t)x >> shift; } -uint32_t HELPER(sar)(uint32_t x, uint32_t i) +uint32_t HELPER(sar)(CPUARMState *env, uint32_t x, uint32_t i) { int shift = i & 0xff; if (shift >= 32) @@ -405,7 +405,7 @@ uint32_t HELPER(sar)(uint32_t x, uint32_t i) return (int32_t)x >> shift; } -uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i) +uint32_t HELPER(shl_cc)(CPUARMState *env, uint32_t x, uint32_t i) { int shift = i & 0xff; if (shift >= 32) { @@ -421,7 +421,7 @@ uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i) return x; } -uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i) +uint32_t HELPER(shr_cc)(CPUARMState *env, uint32_t x, uint32_t i) { int shift = i & 0xff; if (shift >= 32) { @@ -437,7 +437,7 @@ uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i) return x; } -uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i) +uint32_t HELPER(sar_cc)(CPUARMState *env, uint32_t x, uint32_t i) { int shift = i & 0xff; if (shift >= 32) { @@ -450,7 +450,7 @@ uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i) return x; } -uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i) +uint32_t HELPER(ror_cc)(CPUARMState *env, uint32_t x, uint32_t i) { int shift1, shift; shift1 = i & 0xff; diff --git a/target-arm/translate.c b/target-arm/translate.c index 6f651d93c7..9ae3b26aa6 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -490,16 +490,16 @@ static inline void gen_arm_shift_reg(TCGv var, int shiftop, { if (flags) { switch (shiftop) { - case 0: gen_helper_shl_cc(var, var, shift); break; - case 1: gen_helper_shr_cc(var, var, shift); break; - case 2: gen_helper_sar_cc(var, var, shift); break; - case 3: gen_helper_ror_cc(var, var, shift); break; + case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break; + case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break; + case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break; + case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break; } } else { switch (shiftop) { - case 0: gen_helper_shl(var, var, shift); break; - case 1: gen_helper_shr(var, var, shift); break; - case 2: gen_helper_sar(var, var, shift); break; + case 0: gen_helper_shl(var, cpu_env, var, shift); break; + case 1: gen_helper_shr(var, cpu_env, var, shift); break; + case 2: gen_helper_sar(var, cpu_env, var, shift); break; case 3: tcg_gen_andi_i32(shift, shift, 0x1f); tcg_gen_rotr_i32(var, var, shift); break; } @@ -6121,7 +6121,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins tmp2 = neon_load_reg(rm, 0); tmp4 = tcg_const_i32(rn); tmp5 = tcg_const_i32(n); - gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5); + gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5); tcg_temp_free_i32(tmp); if (insn & (1 << 6)) { tmp = neon_load_reg(rd, 1); @@ -6130,7 +6130,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins tcg_gen_movi_i32(tmp, 0); } tmp3 = neon_load_reg(rm, 1); - gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5); + gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5); tcg_temp_free_i32(tmp5); tcg_temp_free_i32(tmp4); neon_store_reg(rd, 0, tmp2); @@ -6818,7 +6818,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) tmp = load_cpu_field(spsr); } else { tmp = tcg_temp_new_i32(); - gen_helper_cpsr_read(tmp); + gen_helper_cpsr_read(tmp, cpu_env); } store_reg(s, rd, tmp); } @@ -6869,11 +6869,11 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) tmp = load_reg(s, rm); tmp2 = load_reg(s, rn); if (op1 & 2) - gen_helper_double_saturate(tmp2, tmp2); + gen_helper_double_saturate(tmp2, cpu_env, tmp2); if (op1 & 1) - gen_helper_sub_saturate(tmp, tmp, tmp2); + gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2); else - gen_helper_add_saturate(tmp, tmp, tmp2); + gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); store_reg(s, rd, tmp); break; @@ -6911,7 +6911,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) tcg_temp_free_i64(tmp64); if ((sh & 2) == 0) { tmp2 = load_reg(s, rn); - gen_helper_add_setq(tmp, tmp, tmp2); + gen_helper_add_setq(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); } store_reg(s, rd, tmp); @@ -6931,7 +6931,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) } else { if (op1 == 0) { tmp2 = load_reg(s, rn); - gen_helper_add_setq(tmp, tmp, tmp2); + gen_helper_add_setq(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); } store_reg(s, rd, tmp); @@ -7005,11 +7005,11 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) if (IS_USER(s)) { goto illegal_op; } - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); gen_exception_return(s, tmp); } else { if (set_cc) { - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); } else { tcg_gen_sub_i32(tmp, tmp, tmp2); } @@ -7018,7 +7018,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x03: if (set_cc) { - gen_helper_sub_cc(tmp, tmp2, tmp); + gen_helper_sub_cc(tmp, cpu_env, tmp2, tmp); } else { tcg_gen_sub_i32(tmp, tmp2, tmp); } @@ -7026,7 +7026,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x04: if (set_cc) { - gen_helper_add_cc(tmp, tmp, tmp2); + gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); } else { tcg_gen_add_i32(tmp, tmp, tmp2); } @@ -7034,7 +7034,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x05: if (set_cc) { - gen_helper_adc_cc(tmp, tmp, tmp2); + gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2); } else { gen_add_carry(tmp, tmp, tmp2); } @@ -7042,7 +7042,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x06: if (set_cc) { - gen_helper_sbc_cc(tmp, tmp, tmp2); + gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2); } else { gen_sub_carry(tmp, tmp, tmp2); } @@ -7050,7 +7050,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x07: if (set_cc) { - gen_helper_sbc_cc(tmp, tmp2, tmp); + gen_helper_sbc_cc(tmp, cpu_env, tmp2, tmp); } else { gen_sub_carry(tmp, tmp2, tmp); } @@ -7072,13 +7072,13 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x0a: if (set_cc) { - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); } tcg_temp_free_i32(tmp); break; case 0x0b: if (set_cc) { - gen_helper_add_cc(tmp, tmp, tmp2); + gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); } tcg_temp_free_i32(tmp); break; @@ -7395,9 +7395,9 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) sh = (insn >> 16) & 0x1f; tmp2 = tcg_const_i32(sh); if (insn & (1 << 22)) - gen_helper_usat(tmp, tmp, tmp2); + gen_helper_usat(tmp, cpu_env, tmp, tmp2); else - gen_helper_ssat(tmp, tmp, tmp2); + gen_helper_ssat(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); store_reg(s, rd, tmp); } else if ((insn & 0x00300fe0) == 0x00200f20) { @@ -7406,9 +7406,9 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) sh = (insn >> 16) & 0x1f; tmp2 = tcg_const_i32(sh); if (insn & (1 << 22)) - gen_helper_usat16(tmp, tmp, tmp2); + gen_helper_usat16(tmp, cpu_env, tmp, tmp2); else - gen_helper_ssat16(tmp, tmp, tmp2); + gen_helper_ssat16(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); store_reg(s, rd, tmp); } else if ((insn & 0x00700fe0) == 0x00000fa0) { @@ -7518,7 +7518,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) * however it may overflow considered as a signed * operation, in which case we must set the Q flag. */ - gen_helper_add_setq(tmp, tmp, tmp2); + gen_helper_add_setq(tmp, cpu_env, tmp, tmp2); } tcg_temp_free_i32(tmp2); if (insn & (1 << 22)) { @@ -7534,7 +7534,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) if (rd != 15) { tmp2 = load_reg(s, rd); - gen_helper_add_setq(tmp, tmp, tmp2); + gen_helper_add_setq(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); } store_reg(s, rn, tmp); @@ -7738,7 +7738,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) } else if (user) { tmp = tcg_temp_new_i32(); tmp2 = tcg_const_i32(i); - gen_helper_get_user_reg(tmp, tmp2); + gen_helper_get_user_reg(tmp, cpu_env, tmp2); tcg_temp_free_i32(tmp2); } else { tmp = load_reg(s, i); @@ -7865,31 +7865,31 @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCG break; case 8: /* add */ if (conds) - gen_helper_add_cc(t0, t0, t1); + gen_helper_add_cc(t0, cpu_env, t0, t1); else tcg_gen_add_i32(t0, t0, t1); break; case 10: /* adc */ if (conds) - gen_helper_adc_cc(t0, t0, t1); + gen_helper_adc_cc(t0, cpu_env, t0, t1); else gen_adc(t0, t1); break; case 11: /* sbc */ if (conds) - gen_helper_sbc_cc(t0, t0, t1); + gen_helper_sbc_cc(t0, cpu_env, t0, t1); else gen_sub_carry(t0, t0, t1); break; case 13: /* sub */ if (conds) - gen_helper_sub_cc(t0, t0, t1); + gen_helper_sub_cc(t0, cpu_env, t0, t1); else tcg_gen_sub_i32(t0, t0, t1); break; case 14: /* rsb */ if (conds) - gen_helper_sub_cc(t0, t1, t0); + gen_helper_sub_cc(t0, cpu_env, t1, t0); else tcg_gen_sub_i32(t0, t1, t0); break; @@ -8111,7 +8111,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw gen_st32(tmp, addr, 0); tcg_gen_addi_i32(addr, addr, 4); tmp = tcg_temp_new_i32(); - gen_helper_cpsr_read(tmp); + gen_helper_cpsr_read(tmp, cpu_env); gen_st32(tmp, addr, 0); if (insn & (1 << 21)) { if ((insn & (1 << 24)) == 0) { @@ -8293,11 +8293,11 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw tmp = load_reg(s, rn); tmp2 = load_reg(s, rm); if (op & 1) - gen_helper_double_saturate(tmp, tmp); + gen_helper_double_saturate(tmp, cpu_env, tmp); if (op & 2) - gen_helper_sub_saturate(tmp, tmp2, tmp); + gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp); else - gen_helper_add_saturate(tmp, tmp, tmp2); + gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); } else { tmp = load_reg(s, rn); @@ -8353,7 +8353,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw tcg_temp_free_i32(tmp2); if (rs != 15) { tmp2 = load_reg(s, rs); - gen_helper_add_setq(tmp, tmp, tmp2); + gen_helper_add_setq(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); } break; @@ -8370,13 +8370,13 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw * however it may overflow considered as a signed * operation, in which case we must set the Q flag. */ - gen_helper_add_setq(tmp, tmp, tmp2); + gen_helper_add_setq(tmp, cpu_env, tmp, tmp2); } tcg_temp_free_i32(tmp2); if (rs != 15) { tmp2 = load_reg(s, rs); - gen_helper_add_setq(tmp, tmp, tmp2); + gen_helper_add_setq(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); } break; @@ -8393,7 +8393,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw if (rs != 15) { tmp2 = load_reg(s, rs); - gen_helper_add_setq(tmp, tmp, tmp2); + gen_helper_add_setq(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); } break; @@ -8632,7 +8632,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw gen_helper_v7m_mrs(tmp, cpu_env, addr); tcg_temp_free_i32(addr); } else { - gen_helper_cpsr_read(tmp); + gen_helper_cpsr_read(tmp, cpu_env); } store_reg(s, rd, tmp); break; @@ -8721,15 +8721,15 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw if (op & 4) { /* Unsigned. */ if ((op & 1) && shift == 0) - gen_helper_usat16(tmp, tmp, tmp2); + gen_helper_usat16(tmp, cpu_env, tmp, tmp2); else - gen_helper_usat(tmp, tmp, tmp2); + gen_helper_usat(tmp, cpu_env, tmp, tmp2); } else { /* Signed. */ if ((op & 1) && shift == 0) - gen_helper_ssat16(tmp, tmp, tmp2); + gen_helper_ssat16(tmp, cpu_env, tmp, tmp2); else - gen_helper_ssat(tmp, tmp, tmp2); + gen_helper_ssat(tmp, cpu_env, tmp, tmp2); } tcg_temp_free_i32(tmp2); break; @@ -9017,12 +9017,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (s->condexec_mask) tcg_gen_sub_i32(tmp, tmp, tmp2); else - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); } else { if (s->condexec_mask) tcg_gen_add_i32(tmp, tmp, tmp2); else - gen_helper_add_cc(tmp, tmp, tmp2); + gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); } tcg_temp_free_i32(tmp2); store_reg(s, rd, tmp); @@ -9053,7 +9053,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) tcg_gen_movi_i32(tmp2, insn & 0xff); switch (op) { case 1: /* cmp */ - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp); tcg_temp_free_i32(tmp2); break; @@ -9061,7 +9061,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (s->condexec_mask) tcg_gen_add_i32(tmp, tmp, tmp2); else - gen_helper_add_cc(tmp, tmp, tmp2); + gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); store_reg(s, rd, tmp); break; @@ -9069,7 +9069,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (s->condexec_mask) tcg_gen_sub_i32(tmp, tmp, tmp2); else - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); store_reg(s, rd, tmp); break; @@ -9105,7 +9105,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) case 1: /* cmp */ tmp = load_reg(s, rd); tmp2 = load_reg(s, rm); - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); tcg_temp_free_i32(tmp); break; @@ -9166,25 +9166,25 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) break; case 0x2: /* lsl */ if (s->condexec_mask) { - gen_helper_shl(tmp2, tmp2, tmp); + gen_helper_shl(tmp2, cpu_env, tmp2, tmp); } else { - gen_helper_shl_cc(tmp2, tmp2, tmp); + gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp); gen_logic_CC(tmp2); } break; case 0x3: /* lsr */ if (s->condexec_mask) { - gen_helper_shr(tmp2, tmp2, tmp); + gen_helper_shr(tmp2, cpu_env, tmp2, tmp); } else { - gen_helper_shr_cc(tmp2, tmp2, tmp); + gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp); gen_logic_CC(tmp2); } break; case 0x4: /* asr */ if (s->condexec_mask) { - gen_helper_sar(tmp2, tmp2, tmp); + gen_helper_sar(tmp2, cpu_env, tmp2, tmp); } else { - gen_helper_sar_cc(tmp2, tmp2, tmp); + gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp); gen_logic_CC(tmp2); } break; @@ -9192,20 +9192,20 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (s->condexec_mask) gen_adc(tmp, tmp2); else - gen_helper_adc_cc(tmp, tmp, tmp2); + gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2); break; case 0x6: /* sbc */ if (s->condexec_mask) gen_sub_carry(tmp, tmp, tmp2); else - gen_helper_sbc_cc(tmp, tmp, tmp2); + gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2); break; case 0x7: /* ror */ if (s->condexec_mask) { tcg_gen_andi_i32(tmp, tmp, 0x1f); tcg_gen_rotr_i32(tmp2, tmp2, tmp); } else { - gen_helper_ror_cc(tmp2, tmp2, tmp); + gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp); gen_logic_CC(tmp2); } break; @@ -9218,14 +9218,14 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (s->condexec_mask) tcg_gen_neg_i32(tmp, tmp2); else - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); break; case 0xa: /* cmp */ - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); rd = 16; break; case 0xb: /* cmn */ - gen_helper_add_cc(tmp, tmp, tmp2); + gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); rd = 16; break; case 0xc: /* orr */ From d31dd73e48561de5f9d718febfb44224f7aab818 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Tue, 4 Sep 2012 20:25:59 +0000 Subject: [PATCH 0397/2270] target-arm: final conversion to AREG0 free mode Convert code load functions and switch to AREG0 free mode. Signed-off-by: Blue Swirl Reviewed-by: Peter Maydell --- configure | 2 +- target-arm/Makefile.objs | 2 -- target-arm/cpu.h | 10 ++++++---- target-arm/helper.c | 9 +++++---- target-arm/op_helper.c | 8 +------- target-arm/translate.c | 6 +++--- 6 files changed, 16 insertions(+), 21 deletions(-) diff --git a/configure b/configure index f6ec4be9a2..e422827f5b 100755 --- a/configure +++ b/configure @@ -3874,7 +3874,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile" case "$target_arch2" in - alpha | i386 | lm32 | m68k | or32 | s390x | sparc* | unicore32 | x86_64 | xtensa* | ppc*) + alpha | arm* | i386 | lm32 | m68k | or32 | s390x | sparc* | unicore32 | x86_64 | xtensa* | ppc*) echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak ;; esac diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs index f447c4fdf2..b6f1a9ebf6 100644 --- a/target-arm/Makefile.objs +++ b/target-arm/Makefile.objs @@ -2,5 +2,3 @@ obj-y += arm-semi.o obj-$(CONFIG_SOFTMMU) += machine.o obj-y += translate.o op_helper.o helper.o cpu.o obj-y += neon_helper.o iwmmxt_helper.o - -$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-arm/cpu.h b/target-arm/cpu.h index d7f93d98f0..7fac94f817 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -734,9 +734,10 @@ static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb) } /* Load an instruction and return it in the standard little-endian order */ -static inline uint32_t arm_ldl_code(uint32_t addr, bool do_swap) +static inline uint32_t arm_ldl_code(CPUARMState *env, uint32_t addr, + bool do_swap) { - uint32_t insn = ldl_code(addr); + uint32_t insn = cpu_ldl_code(env, addr); if (do_swap) { return bswap32(insn); } @@ -744,9 +745,10 @@ static inline uint32_t arm_ldl_code(uint32_t addr, bool do_swap) } /* Ditto, for a halfword (Thumb) instruction */ -static inline uint16_t arm_lduw_code(uint32_t addr, bool do_swap) +static inline uint16_t arm_lduw_code(CPUARMState *env, uint32_t addr, + bool do_swap) { - uint16_t insn = lduw_code(addr); + uint16_t insn = cpu_lduw_code(env, addr); if (do_swap) { return bswap16(insn); } diff --git a/target-arm/helper.c b/target-arm/helper.c index e27df96272..58340bd9e6 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1756,7 +1756,7 @@ static void do_interrupt_v7m(CPUARMState *env) case EXCP_BKPT: if (semihosting_enabled) { int nr; - nr = arm_lduw_code(env->regs[15], env->bswap_code) & 0xff; + nr = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff; if (nr == 0xab) { env->regs[15] += 2; env->regs[0] = do_arm_semihosting(env); @@ -1828,9 +1828,10 @@ void do_interrupt(CPUARMState *env) if (semihosting_enabled) { /* Check for semihosting interrupt. */ if (env->thumb) { - mask = arm_lduw_code(env->regs[15] - 2, env->bswap_code) & 0xff; + mask = arm_lduw_code(env, env->regs[15] - 2, env->bswap_code) + & 0xff; } else { - mask = arm_ldl_code(env->regs[15] - 4, env->bswap_code) + mask = arm_ldl_code(env, env->regs[15] - 4, env->bswap_code) & 0xffffff; } /* Only intercept calls from privileged modes, to provide some @@ -1851,7 +1852,7 @@ void do_interrupt(CPUARMState *env) case EXCP_BKPT: /* See if this is a semihosting syscall. */ if (env->thumb && semihosting_enabled) { - mask = arm_lduw_code(env->regs[15], env->bswap_code) & 0xff; + mask = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff; if (mask == 0xab && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) { env->regs[15] += 2; diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 5b868bf846..f13fc3ae57 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -17,7 +17,6 @@ * License along with this library; if not, see . */ #include "cpu.h" -#include "dyngen-exec.h" #include "helper.h" #define SIGNBIT (uint32_t)0x80000000 @@ -72,16 +71,12 @@ uint32_t HELPER(neon_tbl)(CPUARMState *env, uint32_t ireg, uint32_t def, /* try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ -/* XXX: fix it to restore all registers */ -void tlb_fill(CPUARMState *env1, target_ulong addr, int is_write, int mmu_idx, +void tlb_fill(CPUARMState *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { TranslationBlock *tb; - CPUARMState *saved_env; int ret; - saved_env = env; - env = env1; ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { @@ -95,7 +90,6 @@ void tlb_fill(CPUARMState *env1, target_ulong addr, int is_write, int mmu_idx, } raise_exception(env, env->exception_index); } - env = saved_env; } #endif diff --git a/target-arm/translate.c b/target-arm/translate.c index 9ae3b26aa6..f4b447a49a 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -6534,7 +6534,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) TCGv addr; TCGv_i64 tmp64; - insn = arm_ldl_code(s->pc, s->bswap_code); + insn = arm_ldl_code(env, s->pc, s->bswap_code); s->pc += 4; /* M variants do not implement ARM mode. */ @@ -7962,7 +7962,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw /* Fall through to 32-bit decode. */ } - insn = arm_lduw_code(s->pc, s->bswap_code); + insn = arm_lduw_code(env, s->pc, s->bswap_code); s->pc += 2; insn |= (uint32_t)insn_hw1 << 16; @@ -8992,7 +8992,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) } } - insn = arm_lduw_code(s->pc, s->bswap_code); + insn = arm_lduw_code(env, s->pc, s->bswap_code); s->pc += 2; switch (insn >> 12) { From 64254eba53198fd14b52128b3f0026000d2dc4ab Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 08:39:22 +0000 Subject: [PATCH 0398/2270] target-microblaze: switch to AREG0 free mode Add an explicit CPUState parameter instead of relying on AREG0 and switch to AREG0 free mode. Signed-off-by: Blue Swirl --- configure | 2 +- target-microblaze/Makefile.objs | 2 - target-microblaze/helper.h | 44 ++++++------ target-microblaze/op_helper.c | 115 +++++++++++++++----------------- target-microblaze/translate.c | 61 +++++++++-------- 5 files changed, 108 insertions(+), 116 deletions(-) diff --git a/configure b/configure index e422827f5b..01a1b0b0b4 100755 --- a/configure +++ b/configure @@ -3874,7 +3874,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile" case "$target_arch2" in - alpha | arm* | i386 | lm32 | m68k | or32 | s390x | sparc* | unicore32 | x86_64 | xtensa* | ppc*) + alpha | arm* | i386 | lm32 | m68k | microblaze* | or32 | s390x | sparc* | unicore32 | x86_64 | xtensa* | ppc*) echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak ;; esac diff --git a/target-microblaze/Makefile.objs b/target-microblaze/Makefile.objs index 4b09e8c6b5..afb87bcc80 100644 --- a/target-microblaze/Makefile.objs +++ b/target-microblaze/Makefile.objs @@ -1,4 +1,2 @@ obj-y += translate.o op_helper.o helper.o cpu.o obj-$(CONFIG_SOFTMMU) += mmu.o machine.o - -$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h index 9dcfb0f1d5..a1a732cfdc 100644 --- a/target-microblaze/helper.h +++ b/target-microblaze/helper.h @@ -1,39 +1,39 @@ #include "def-helper.h" -DEF_HELPER_1(raise_exception, void, i32) -DEF_HELPER_0(debug, void) +DEF_HELPER_2(raise_exception, void, env, i32) +DEF_HELPER_1(debug, void, env) DEF_HELPER_FLAGS_3(carry, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32) DEF_HELPER_2(cmp, i32, i32, i32) DEF_HELPER_2(cmpu, i32, i32, i32) DEF_HELPER_FLAGS_1(clz, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32) -DEF_HELPER_2(divs, i32, i32, i32) -DEF_HELPER_2(divu, i32, i32, i32) +DEF_HELPER_3(divs, i32, env, i32, i32) +DEF_HELPER_3(divu, i32, env, i32, i32) -DEF_HELPER_2(fadd, i32, i32, i32) -DEF_HELPER_2(frsub, i32, i32, i32) -DEF_HELPER_2(fmul, i32, i32, i32) -DEF_HELPER_2(fdiv, i32, i32, i32) -DEF_HELPER_1(flt, i32, i32) -DEF_HELPER_1(fint, i32, i32) -DEF_HELPER_1(fsqrt, i32, i32) +DEF_HELPER_3(fadd, i32, env, i32, i32) +DEF_HELPER_3(frsub, i32, env, i32, i32) +DEF_HELPER_3(fmul, i32, env, i32, i32) +DEF_HELPER_3(fdiv, i32, env, i32, i32) +DEF_HELPER_2(flt, i32, env, i32) +DEF_HELPER_2(fint, i32, env, i32) +DEF_HELPER_2(fsqrt, i32, env, i32) -DEF_HELPER_2(fcmp_un, i32, i32, i32) -DEF_HELPER_2(fcmp_lt, i32, i32, i32) -DEF_HELPER_2(fcmp_eq, i32, i32, i32) -DEF_HELPER_2(fcmp_le, i32, i32, i32) -DEF_HELPER_2(fcmp_gt, i32, i32, i32) -DEF_HELPER_2(fcmp_ne, i32, i32, i32) -DEF_HELPER_2(fcmp_ge, i32, i32, i32) +DEF_HELPER_3(fcmp_un, i32, env, i32, i32) +DEF_HELPER_3(fcmp_lt, i32, env, i32, i32) +DEF_HELPER_3(fcmp_eq, i32, env, i32, i32) +DEF_HELPER_3(fcmp_le, i32, env, i32, i32) +DEF_HELPER_3(fcmp_gt, i32, env, i32, i32) +DEF_HELPER_3(fcmp_ne, i32, env, i32, i32) +DEF_HELPER_3(fcmp_ge, i32, env, i32, i32) DEF_HELPER_FLAGS_2(pcmpbf, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32) #if !defined(CONFIG_USER_ONLY) -DEF_HELPER_1(mmu_read, i32, i32) -DEF_HELPER_2(mmu_write, void, i32, i32) +DEF_HELPER_2(mmu_read, i32, env, i32) +DEF_HELPER_3(mmu_write, void, env, i32, i32) #endif -DEF_HELPER_4(memalign, void, i32, i32, i32, i32) -DEF_HELPER_1(stackprot, void, i32) +DEF_HELPER_5(memalign, void, env, i32, i32, i32, i32) +DEF_HELPER_2(stackprot, void, env, i32) DEF_HELPER_2(get, i32, i32, i32) DEF_HELPER_3(put, void, i32, i32, i32) diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c index 3b1f07243e..c9789f44c7 100644 --- a/target-microblaze/op_helper.c +++ b/target-microblaze/op_helper.c @@ -20,7 +20,6 @@ #include #include "cpu.h" -#include "dyngen-exec.h" #include "helper.h" #include "host-utils.h" @@ -42,17 +41,12 @@ /* Try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ -/* XXX: fix it to restore all registers */ -void tlb_fill(CPUMBState *env1, target_ulong addr, int is_write, int mmu_idx, +void tlb_fill(CPUMBState *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { TranslationBlock *tb; - CPUMBState *saved_env; int ret; - saved_env = env; - env = env1; - ret = cpu_mb_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { @@ -66,7 +60,6 @@ void tlb_fill(CPUMBState *env1, target_ulong addr, int is_write, int mmu_idx, } cpu_loop_exit(env); } - env = saved_env; } #endif @@ -105,13 +98,13 @@ uint32_t helper_get(uint32_t id, uint32_t ctrl) return 0xdead0000 | id; } -void helper_raise_exception(uint32_t index) +void helper_raise_exception(CPUMBState *env, uint32_t index) { env->exception_index = index; cpu_loop_exit(env); } -void helper_debug(void) +void helper_debug(CPUMBState *env) { int i; @@ -176,7 +169,7 @@ uint32_t helper_carry(uint32_t a, uint32_t b, uint32_t cf) return ncf; } -static inline int div_prepare(uint32_t a, uint32_t b) +static inline int div_prepare(CPUMBState *env, uint32_t a, uint32_t b) { if (b == 0) { env->sregs[SR_MSR] |= MSR_DZ; @@ -184,7 +177,7 @@ static inline int div_prepare(uint32_t a, uint32_t b) if ((env->sregs[SR_MSR] & MSR_EE) && !(env->pvr.regs[2] & PVR2_DIV_ZERO_EXC_MASK)) { env->sregs[SR_ESR] = ESR_EC_DIVZERO; - helper_raise_exception(EXCP_HW_EXCP); + helper_raise_exception(env, EXCP_HW_EXCP); } return 0; } @@ -192,28 +185,30 @@ static inline int div_prepare(uint32_t a, uint32_t b) return 1; } -uint32_t helper_divs(uint32_t a, uint32_t b) +uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b) { - if (!div_prepare(a, b)) + if (!div_prepare(env, a, b)) { return 0; + } return (int32_t)a / (int32_t)b; } -uint32_t helper_divu(uint32_t a, uint32_t b) +uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b) { - if (!div_prepare(a, b)) + if (!div_prepare(env, a, b)) { return 0; + } return a / b; } /* raise FPU exception. */ -static void raise_fpu_exception(void) +static void raise_fpu_exception(CPUMBState *env) { env->sregs[SR_ESR] = ESR_EC_FPU; - helper_raise_exception(EXCP_HW_EXCP); + helper_raise_exception(env, EXCP_HW_EXCP); } -static void update_fpu_flags(int flags) +static void update_fpu_flags(CPUMBState *env, int flags) { int raise = 0; @@ -236,11 +231,11 @@ static void update_fpu_flags(int flags) if (raise && (env->pvr.regs[2] & PVR2_FPU_EXC_MASK) && (env->sregs[SR_MSR] & MSR_EE)) { - raise_fpu_exception(); + raise_fpu_exception(env); } } -uint32_t helper_fadd(uint32_t a, uint32_t b) +uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b) { CPU_FloatU fd, fa, fb; int flags; @@ -251,11 +246,11 @@ uint32_t helper_fadd(uint32_t a, uint32_t b) fd.f = float32_add(fa.f, fb.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(flags); + update_fpu_flags(env, flags); return fd.l; } -uint32_t helper_frsub(uint32_t a, uint32_t b) +uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b) { CPU_FloatU fd, fa, fb; int flags; @@ -265,11 +260,11 @@ uint32_t helper_frsub(uint32_t a, uint32_t b) fb.l = b; fd.f = float32_sub(fb.f, fa.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(flags); + update_fpu_flags(env, flags); return fd.l; } -uint32_t helper_fmul(uint32_t a, uint32_t b) +uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b) { CPU_FloatU fd, fa, fb; int flags; @@ -279,12 +274,12 @@ uint32_t helper_fmul(uint32_t a, uint32_t b) fb.l = b; fd.f = float32_mul(fa.f, fb.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(flags); + update_fpu_flags(env, flags); return fd.l; } -uint32_t helper_fdiv(uint32_t a, uint32_t b) +uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b) { CPU_FloatU fd, fa, fb; int flags; @@ -294,12 +289,12 @@ uint32_t helper_fdiv(uint32_t a, uint32_t b) fb.l = b; fd.f = float32_div(fb.f, fa.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(flags); + update_fpu_flags(env, flags); return fd.l; } -uint32_t helper_fcmp_un(uint32_t a, uint32_t b) +uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b) { CPU_FloatU fa, fb; uint32_t r = 0; @@ -308,7 +303,7 @@ uint32_t helper_fcmp_un(uint32_t a, uint32_t b) fb.l = b; if (float32_is_signaling_nan(fa.f) || float32_is_signaling_nan(fb.f)) { - update_fpu_flags(float_flag_invalid); + update_fpu_flags(env, float_flag_invalid); r = 1; } @@ -319,7 +314,7 @@ uint32_t helper_fcmp_un(uint32_t a, uint32_t b) return r; } -uint32_t helper_fcmp_lt(uint32_t a, uint32_t b) +uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b) { CPU_FloatU fa, fb; int r; @@ -330,12 +325,12 @@ uint32_t helper_fcmp_lt(uint32_t a, uint32_t b) fb.l = b; r = float32_lt(fb.f, fa.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(flags & float_flag_invalid); + update_fpu_flags(env, flags & float_flag_invalid); return r; } -uint32_t helper_fcmp_eq(uint32_t a, uint32_t b) +uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b) { CPU_FloatU fa, fb; int flags; @@ -346,12 +341,12 @@ uint32_t helper_fcmp_eq(uint32_t a, uint32_t b) fb.l = b; r = float32_eq_quiet(fa.f, fb.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(flags & float_flag_invalid); + update_fpu_flags(env, flags & float_flag_invalid); return r; } -uint32_t helper_fcmp_le(uint32_t a, uint32_t b) +uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b) { CPU_FloatU fa, fb; int flags; @@ -362,13 +357,13 @@ uint32_t helper_fcmp_le(uint32_t a, uint32_t b) set_float_exception_flags(0, &env->fp_status); r = float32_le(fa.f, fb.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(flags & float_flag_invalid); + update_fpu_flags(env, flags & float_flag_invalid); return r; } -uint32_t helper_fcmp_gt(uint32_t a, uint32_t b) +uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b) { CPU_FloatU fa, fb; int flags, r; @@ -378,11 +373,11 @@ uint32_t helper_fcmp_gt(uint32_t a, uint32_t b) set_float_exception_flags(0, &env->fp_status); r = float32_lt(fa.f, fb.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(flags & float_flag_invalid); + update_fpu_flags(env, flags & float_flag_invalid); return r; } -uint32_t helper_fcmp_ne(uint32_t a, uint32_t b) +uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b) { CPU_FloatU fa, fb; int flags, r; @@ -392,12 +387,12 @@ uint32_t helper_fcmp_ne(uint32_t a, uint32_t b) set_float_exception_flags(0, &env->fp_status); r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(flags & float_flag_invalid); + update_fpu_flags(env, flags & float_flag_invalid); return r; } -uint32_t helper_fcmp_ge(uint32_t a, uint32_t b) +uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b) { CPU_FloatU fa, fb; int flags, r; @@ -407,12 +402,12 @@ uint32_t helper_fcmp_ge(uint32_t a, uint32_t b) set_float_exception_flags(0, &env->fp_status); r = !float32_lt(fa.f, fb.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(flags & float_flag_invalid); + update_fpu_flags(env, flags & float_flag_invalid); return r; } -uint32_t helper_flt(uint32_t a) +uint32_t helper_flt(CPUMBState *env, uint32_t a) { CPU_FloatU fd, fa; @@ -421,7 +416,7 @@ uint32_t helper_flt(uint32_t a) return fd.l; } -uint32_t helper_fint(uint32_t a) +uint32_t helper_fint(CPUMBState *env, uint32_t a) { CPU_FloatU fa; uint32_t r; @@ -431,12 +426,12 @@ uint32_t helper_fint(uint32_t a) fa.l = a; r = float32_to_int32(fa.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(flags); + update_fpu_flags(env, flags); return r; } -uint32_t helper_fsqrt(uint32_t a) +uint32_t helper_fsqrt(CPUMBState *env, uint32_t a) { CPU_FloatU fd, fa; int flags; @@ -445,7 +440,7 @@ uint32_t helper_fsqrt(uint32_t a) fa.l = a; fd.l = float32_sqrt(fa.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(flags); + update_fpu_flags(env, flags); return fd.l; } @@ -463,7 +458,8 @@ uint32_t helper_pcmpbf(uint32_t a, uint32_t b) return 0; } -void helper_memalign(uint32_t addr, uint32_t dr, uint32_t wr, uint32_t mask) +void helper_memalign(CPUMBState *env, uint32_t addr, uint32_t dr, uint32_t wr, + uint32_t mask) { if (addr & mask) { qemu_log_mask(CPU_LOG_INT, @@ -478,45 +474,39 @@ void helper_memalign(uint32_t addr, uint32_t dr, uint32_t wr, uint32_t mask) if (!(env->sregs[SR_MSR] & MSR_EE)) { return; } - helper_raise_exception(EXCP_HW_EXCP); + helper_raise_exception(env, EXCP_HW_EXCP); } } -void helper_stackprot(uint32_t addr) +void helper_stackprot(CPUMBState *env, uint32_t addr) { if (addr < env->slr || addr > env->shr) { qemu_log("Stack protector violation at %x %x %x\n", addr, env->slr, env->shr); env->sregs[SR_EAR] = addr; env->sregs[SR_ESR] = ESR_EC_STACKPROT; - helper_raise_exception(EXCP_HW_EXCP); + helper_raise_exception(env, EXCP_HW_EXCP); } } #if !defined(CONFIG_USER_ONLY) /* Writes/reads to the MMU's special regs end up here. */ -uint32_t helper_mmu_read(uint32_t rn) +uint32_t helper_mmu_read(CPUMBState *env, uint32_t rn) { return mmu_read(env, rn); } -void helper_mmu_write(uint32_t rn, uint32_t v) +void helper_mmu_write(CPUMBState *env, uint32_t rn, uint32_t v) { mmu_write(env, rn, v); } -void cpu_unassigned_access(CPUMBState *env1, target_phys_addr_t addr, +void cpu_unassigned_access(CPUMBState *env, target_phys_addr_t addr, int is_write, int is_exec, int is_asi, int size) { - CPUMBState *saved_env; - - saved_env = env; - env = env1; - qemu_log_mask(CPU_LOG_INT, "Unassigned " TARGET_FMT_plx " wr=%d exe=%d\n", addr, is_write, is_exec); if (!(env->sregs[SR_MSR] & MSR_EE)) { - env = saved_env; return; } @@ -524,14 +514,13 @@ void cpu_unassigned_access(CPUMBState *env1, target_phys_addr_t addr, if (is_exec) { if ((env->pvr.regs[2] & PVR2_IOPB_BUS_EXC_MASK)) { env->sregs[SR_ESR] = ESR_EC_INSN_BUS; - helper_raise_exception(EXCP_HW_EXCP); + helper_raise_exception(env, EXCP_HW_EXCP); } } else { if ((env->pvr.regs[2] & PVR2_DOPB_BUS_EXC_MASK)) { env->sregs[SR_ESR] = ESR_EC_DATA_BUS; - helper_raise_exception(EXCP_HW_EXCP); + helper_raise_exception(env, EXCP_HW_EXCP); } } - env = saved_env; } #endif diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index 7470149db3..9c7d77f57a 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -126,7 +126,7 @@ static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index) t_sync_flags(dc); tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); - gen_helper_raise_exception(tmp); + gen_helper_raise_exception(cpu_env, tmp); tcg_temp_free_i32(tmp); dc->is_jmp = DISAS_UPDATE; } @@ -503,9 +503,9 @@ static void dec_msr(DisasContext *dc) sr &= 7; LOG_DIS("m%ss sr%d r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm); if (to) - gen_helper_mmu_write(tcg_const_tl(sr), cpu_R[dc->ra]); + gen_helper_mmu_write(cpu_env, tcg_const_tl(sr), cpu_R[dc->ra]); else - gen_helper_mmu_read(cpu_R[dc->rd], tcg_const_tl(sr)); + gen_helper_mmu_read(cpu_R[dc->rd], cpu_env, tcg_const_tl(sr)); return; } #endif @@ -704,9 +704,11 @@ static void dec_div(DisasContext *dc) } if (u) - gen_helper_divu(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]); + gen_helper_divu(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)), + cpu_R[dc->ra]); else - gen_helper_divs(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]); + gen_helper_divs(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)), + cpu_R[dc->ra]); if (!dc->rd) tcg_gen_movi_tl(cpu_R[dc->rd], 0); } @@ -912,7 +914,7 @@ static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t) tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]); if (stackprot) { - gen_helper_stackprot(*t); + gen_helper_stackprot(cpu_env, *t); } return t; } @@ -930,7 +932,7 @@ static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t) } if (stackprot) { - gen_helper_stackprot(*t); + gen_helper_stackprot(cpu_env, *t); } return t; } @@ -1056,7 +1058,7 @@ static void dec_load(DisasContext *dc) gen_load(dc, v, *addr, size); tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); - gen_helper_memalign(*addr, tcg_const_tl(dc->rd), + gen_helper_memalign(cpu_env, *addr, tcg_const_tl(dc->rd), tcg_const_tl(0), tcg_const_tl(size - 1)); if (dc->rd) { if (rev) { @@ -1218,7 +1220,7 @@ static void dec_store(DisasContext *dc) * the alignment checks in between the probe and the mem * access. */ - gen_helper_memalign(*addr, tcg_const_tl(dc->rd), + gen_helper_memalign(cpu_env, *addr, tcg_const_tl(dc->rd), tcg_const_tl(1), tcg_const_tl(size - 1)); } @@ -1493,49 +1495,53 @@ static void dec_fpu(DisasContext *dc) switch (fpu_insn) { case 0: - gen_helper_fadd(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); + gen_helper_fadd(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], + cpu_R[dc->rb]); break; case 1: - gen_helper_frsub(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); + gen_helper_frsub(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], + cpu_R[dc->rb]); break; case 2: - gen_helper_fmul(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); + gen_helper_fmul(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], + cpu_R[dc->rb]); break; case 3: - gen_helper_fdiv(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); + gen_helper_fdiv(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], + cpu_R[dc->rb]); break; case 4: switch ((dc->ir >> 4) & 7) { case 0: - gen_helper_fcmp_un(cpu_R[dc->rd], + gen_helper_fcmp_un(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], cpu_R[dc->rb]); break; case 1: - gen_helper_fcmp_lt(cpu_R[dc->rd], + gen_helper_fcmp_lt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], cpu_R[dc->rb]); break; case 2: - gen_helper_fcmp_eq(cpu_R[dc->rd], + gen_helper_fcmp_eq(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], cpu_R[dc->rb]); break; case 3: - gen_helper_fcmp_le(cpu_R[dc->rd], + gen_helper_fcmp_le(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], cpu_R[dc->rb]); break; case 4: - gen_helper_fcmp_gt(cpu_R[dc->rd], + gen_helper_fcmp_gt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], cpu_R[dc->rb]); break; case 5: - gen_helper_fcmp_ne(cpu_R[dc->rd], + gen_helper_fcmp_ne(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], cpu_R[dc->rb]); break; case 6: - gen_helper_fcmp_ge(cpu_R[dc->rd], + gen_helper_fcmp_ge(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], cpu_R[dc->rb]); break; default: @@ -1552,21 +1558,21 @@ static void dec_fpu(DisasContext *dc) if (!dec_check_fpuv2(dc)) { return; } - gen_helper_flt(cpu_R[dc->rd], cpu_R[dc->ra]); + gen_helper_flt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]); break; case 6: if (!dec_check_fpuv2(dc)) { return; } - gen_helper_fint(cpu_R[dc->rd], cpu_R[dc->ra]); + gen_helper_fint(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]); break; case 7: if (!dec_check_fpuv2(dc)) { return; } - gen_helper_fsqrt(cpu_R[dc->rd], cpu_R[dc->ra]); + gen_helper_fsqrt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]); break; default: @@ -1654,15 +1660,14 @@ static struct decoder_info { {{0, 0}, dec_null} }; -static inline void decode(DisasContext *dc) +static inline void decode(DisasContext *dc, uint32_t ir) { - uint32_t ir; int i; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) tcg_gen_debug_insn_start(dc->pc); - dc->ir = ir = ldl_code(dc->pc); + dc->ir = ir; LOG_DIS("%8.8x\t", dc->ir); if (dc->ir) @@ -1796,7 +1801,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb, gen_io_start(); dc->clear_imm = 1; - decode(dc); + decode(dc, cpu_ldl_code(env, dc->pc)); if (dc->clear_imm) dc->tb_flags &= ~IMM_FLAG; dc->pc += 4; @@ -1871,7 +1876,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb, if (dc->is_jmp != DISAS_JUMP) { tcg_gen_movi_tl(cpu_SR[SR_PC], npc); } - gen_helper_raise_exception(tmp); + gen_helper_raise_exception(cpu_env, tmp); tcg_temp_free_i32(tmp); } else { switch(dc->is_jmp) { From febc9920c66dd51245c2ca2ee88ada2aa5d0a63e Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Thu, 30 Aug 2012 16:56:39 +0200 Subject: [PATCH 0399/2270] target-cris: Avoid AREG0 for helpers Add an explicit CPUCRISState parameter instead of relying on AREG0. Signed-off-by: Blue Swirl Signed-off-by: Aurelien Jarno --- target-cris/helper.h | 37 +++++++++-------- target-cris/op_helper.c | 80 ++++++++++++++++++++----------------- target-cris/translate.c | 44 ++++++++++---------- target-cris/translate_v10.c | 4 +- 4 files changed, 88 insertions(+), 77 deletions(-) diff --git a/target-cris/helper.h b/target-cris/helper.h index 093063a14b..99fb326a85 100644 --- a/target-cris/helper.h +++ b/target-cris/helper.h @@ -1,26 +1,29 @@ #include "def-helper.h" -DEF_HELPER_1(raise_exception, void, i32) -DEF_HELPER_1(tlb_flush_pid, void, i32) -DEF_HELPER_1(spc_write, void, i32) +DEF_HELPER_2(raise_exception, void, env, i32) +DEF_HELPER_2(tlb_flush_pid, void, env, i32) +DEF_HELPER_2(spc_write, void, env, i32) DEF_HELPER_3(dump, void, i32, i32, i32) -DEF_HELPER_0(rfe, void); -DEF_HELPER_0(rfn, void); +DEF_HELPER_1(rfe, void, env); +DEF_HELPER_1(rfn, void, env); -DEF_HELPER_2(movl_sreg_reg, void, i32, i32) -DEF_HELPER_2(movl_reg_sreg, void, i32, i32) +DEF_HELPER_3(movl_sreg_reg, void, env, i32, i32) +DEF_HELPER_3(movl_reg_sreg, void, env, i32, i32) DEF_HELPER_FLAGS_1(lz, TCG_CALL_PURE, i32, i32); -DEF_HELPER_FLAGS_3(btst, TCG_CALL_PURE, i32, i32, i32, i32); +DEF_HELPER_FLAGS_4(btst, TCG_CALL_PURE, i32, env, i32, i32, i32); -DEF_HELPER_FLAGS_3(evaluate_flags_muls, TCG_CALL_PURE, i32, i32, i32, i32) -DEF_HELPER_FLAGS_3(evaluate_flags_mulu, TCG_CALL_PURE, i32, i32, i32, i32) -DEF_HELPER_FLAGS_4(evaluate_flags_mcp, TCG_CALL_PURE, i32, i32, i32, i32, i32) -DEF_HELPER_FLAGS_4(evaluate_flags_alu_4, TCG_CALL_PURE, i32, i32, i32, i32, i32) -DEF_HELPER_FLAGS_4(evaluate_flags_sub_4, TCG_CALL_PURE, i32, i32, i32, i32, i32) -DEF_HELPER_FLAGS_2(evaluate_flags_move_4, TCG_CALL_PURE, i32, i32, i32) -DEF_HELPER_FLAGS_2(evaluate_flags_move_2, TCG_CALL_PURE, i32, i32, i32) -DEF_HELPER_0(evaluate_flags, void) -DEF_HELPER_0(top_evaluate_flags, void) +DEF_HELPER_FLAGS_4(evaluate_flags_muls, TCG_CALL_PURE, i32, env, i32, i32, i32) +DEF_HELPER_FLAGS_4(evaluate_flags_mulu, TCG_CALL_PURE, i32, env, i32, i32, i32) +DEF_HELPER_FLAGS_5(evaluate_flags_mcp, TCG_CALL_PURE, i32, env, + i32, i32, i32, i32) +DEF_HELPER_FLAGS_5(evaluate_flags_alu_4, TCG_CALL_PURE, i32, env, + i32, i32, i32, i32) +DEF_HELPER_FLAGS_5(evaluate_flags_sub_4, TCG_CALL_PURE, i32, env, + i32, i32, i32, i32) +DEF_HELPER_FLAGS_3(evaluate_flags_move_4, TCG_CALL_PURE, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(evaluate_flags_move_2, TCG_CALL_PURE, i32, env, i32, i32) +DEF_HELPER_1(evaluate_flags, void, env) +DEF_HELPER_1(top_evaluate_flags, void, env) #include "def-helper.h" diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c index ac7c98c8ed..5ca85a09e4 100644 --- a/target-cris/op_helper.c +++ b/target-cris/op_helper.c @@ -79,7 +79,7 @@ void tlb_fill(CPUCRISState *env1, target_ulong addr, int is_write, int mmu_idx, cpu_restore_state(tb, env, retaddr); /* Evaluate flags after retranslation. */ - helper_top_evaluate_flags(); + helper_top_evaluate_flags(env); } } cpu_loop_exit(env); @@ -89,13 +89,13 @@ void tlb_fill(CPUCRISState *env1, target_ulong addr, int is_write, int mmu_idx, #endif -void helper_raise_exception(uint32_t index) +void helper_raise_exception(CPUCRISState *env, uint32_t index) { env->exception_index = index; cpu_loop_exit(env); } -void helper_tlb_flush_pid(uint32_t pid) +void helper_tlb_flush_pid(CPUCRISState *env, uint32_t pid) { #if !defined(CONFIG_USER_ONLY) pid &= 0xff; @@ -104,7 +104,7 @@ void helper_tlb_flush_pid(uint32_t pid) #endif } -void helper_spc_write(uint32_t new_spc) +void helper_spc_write(CPUCRISState *env, uint32_t new_spc) { #if !defined(CONFIG_USER_ONLY) tlb_flush_page(env, env->pregs[PR_SPC]); @@ -121,7 +121,7 @@ void helper_dump(uint32_t a0, uint32_t a1, uint32_t a2) #define EXTRACT_FIELD(src, start, end) \ (((src) >> start) & ((1 << (end - start + 1)) - 1)) -void helper_movl_sreg_reg (uint32_t sreg, uint32_t reg) +void helper_movl_sreg_reg(CPUCRISState *env, uint32_t sreg, uint32_t reg) { uint32_t srs; srs = env->pregs[PR_SRS]; @@ -171,7 +171,7 @@ void helper_movl_sreg_reg (uint32_t sreg, uint32_t reg) #endif } -void helper_movl_reg_sreg (uint32_t reg, uint32_t sreg) +void helper_movl_reg_sreg(CPUCRISState *env, uint32_t reg, uint32_t sreg) { uint32_t srs; env->pregs[PR_SRS] &= 3; @@ -216,7 +216,7 @@ static void cris_ccs_rshift(CPUCRISState *env) env->pregs[PR_CCS] = ccs; } -void helper_rfe(void) +void helper_rfe(CPUCRISState *env) { int rflag = env->pregs[PR_CCS] & R_FLAG; @@ -232,7 +232,7 @@ void helper_rfe(void) env->pregs[PR_CCS] |= P_FLAG; } -void helper_rfn(void) +void helper_rfn(CPUCRISState *env) { int rflag = env->pregs[PR_CCS] & R_FLAG; @@ -256,7 +256,7 @@ uint32_t helper_lz(uint32_t t0) return clz32(t0); } -uint32_t helper_btst(uint32_t t0, uint32_t t1, uint32_t ccs) +uint32_t helper_btst(CPUCRISState *env, uint32_t t0, uint32_t t1, uint32_t ccs) { /* FIXME: clean this up. */ @@ -284,7 +284,8 @@ uint32_t helper_btst(uint32_t t0, uint32_t t1, uint32_t ccs) return ccs; } -static inline uint32_t evaluate_flags_writeback(uint32_t flags, uint32_t ccs) +static inline uint32_t evaluate_flags_writeback(CPUCRISState *env, + uint32_t flags, uint32_t ccs) { unsigned int x, z, mask; @@ -303,7 +304,8 @@ static inline uint32_t evaluate_flags_writeback(uint32_t flags, uint32_t ccs) return ccs; } -uint32_t helper_evaluate_flags_muls(uint32_t ccs, uint32_t res, uint32_t mof) +uint32_t helper_evaluate_flags_muls(CPUCRISState *env, + uint32_t ccs, uint32_t res, uint32_t mof) { uint32_t flags = 0; int64_t tmp; @@ -321,10 +323,11 @@ uint32_t helper_evaluate_flags_muls(uint32_t ccs, uint32_t res, uint32_t mof) if ((dneg && mof != -1) || (!dneg && mof != 0)) flags |= V_FLAG; - return evaluate_flags_writeback(flags, ccs); + return evaluate_flags_writeback(env, flags, ccs); } -uint32_t helper_evaluate_flags_mulu(uint32_t ccs, uint32_t res, uint32_t mof) +uint32_t helper_evaluate_flags_mulu(CPUCRISState *env, + uint32_t ccs, uint32_t res, uint32_t mof) { uint32_t flags = 0; uint64_t tmp; @@ -339,10 +342,10 @@ uint32_t helper_evaluate_flags_mulu(uint32_t ccs, uint32_t res, uint32_t mof) if (mof) flags |= V_FLAG; - return evaluate_flags_writeback(flags, ccs); + return evaluate_flags_writeback(env, flags, ccs); } -uint32_t helper_evaluate_flags_mcp(uint32_t ccs, +uint32_t helper_evaluate_flags_mcp(CPUCRISState *env, uint32_t ccs, uint32_t src, uint32_t dst, uint32_t res) { uint32_t flags = 0; @@ -368,10 +371,10 @@ uint32_t helper_evaluate_flags_mcp(uint32_t ccs, flags |= R_FLAG; } - return evaluate_flags_writeback(flags, ccs); + return evaluate_flags_writeback(env, flags, ccs); } -uint32_t helper_evaluate_flags_alu_4(uint32_t ccs, +uint32_t helper_evaluate_flags_alu_4(CPUCRISState *env, uint32_t ccs, uint32_t src, uint32_t dst, uint32_t res) { uint32_t flags = 0; @@ -397,10 +400,10 @@ uint32_t helper_evaluate_flags_alu_4(uint32_t ccs, flags |= C_FLAG; } - return evaluate_flags_writeback(flags, ccs); + return evaluate_flags_writeback(env, flags, ccs); } -uint32_t helper_evaluate_flags_sub_4(uint32_t ccs, +uint32_t helper_evaluate_flags_sub_4(CPUCRISState *env, uint32_t ccs, uint32_t src, uint32_t dst, uint32_t res) { uint32_t flags = 0; @@ -427,10 +430,11 @@ uint32_t helper_evaluate_flags_sub_4(uint32_t ccs, } flags ^= C_FLAG; - return evaluate_flags_writeback(flags, ccs); + return evaluate_flags_writeback(env, flags, ccs); } -uint32_t helper_evaluate_flags_move_4(uint32_t ccs, uint32_t res) +uint32_t helper_evaluate_flags_move_4(CPUCRISState *env, + uint32_t ccs, uint32_t res) { uint32_t flags = 0; @@ -439,9 +443,10 @@ uint32_t helper_evaluate_flags_move_4(uint32_t ccs, uint32_t res) else if (res == 0L) flags |= Z_FLAG; - return evaluate_flags_writeback(flags, ccs); + return evaluate_flags_writeback(env, flags, ccs); } -uint32_t helper_evaluate_flags_move_2(uint32_t ccs, uint32_t res) +uint32_t helper_evaluate_flags_move_2(CPUCRISState *env, + uint32_t ccs, uint32_t res) { uint32_t flags = 0; @@ -450,12 +455,12 @@ uint32_t helper_evaluate_flags_move_2(uint32_t ccs, uint32_t res) else if (res == 0) flags |= Z_FLAG; - return evaluate_flags_writeback(flags, ccs); + return evaluate_flags_writeback(env, flags, ccs); } /* TODO: This is expensive. We could split things up and only evaluate part of CCR on a need to know basis. For now, we simply re-evaluate everything. */ -void helper_evaluate_flags(void) +void helper_evaluate_flags(CPUCRISState *env) { uint32_t src, dst, res; uint32_t flags = 0; @@ -571,25 +576,26 @@ void helper_evaluate_flags(void) if (env->cc_op == CC_OP_SUB || env->cc_op == CC_OP_CMP) flags ^= C_FLAG; - env->pregs[PR_CCS] = evaluate_flags_writeback(flags, env->pregs[PR_CCS]); + env->pregs[PR_CCS] = evaluate_flags_writeback(env, flags, + env->pregs[PR_CCS]); } -void helper_top_evaluate_flags(void) +void helper_top_evaluate_flags(CPUCRISState *env) { switch (env->cc_op) { case CC_OP_MCP: - env->pregs[PR_CCS] = helper_evaluate_flags_mcp( + env->pregs[PR_CCS] = helper_evaluate_flags_mcp(env, env->pregs[PR_CCS], env->cc_src, env->cc_dest, env->cc_result); break; case CC_OP_MULS: - env->pregs[PR_CCS] = helper_evaluate_flags_muls( + env->pregs[PR_CCS] = helper_evaluate_flags_muls(env, env->pregs[PR_CCS], env->cc_result, env->pregs[PR_MOF]); break; case CC_OP_MULU: - env->pregs[PR_CCS] = helper_evaluate_flags_mulu( + env->pregs[PR_CCS] = helper_evaluate_flags_mulu(env, env->pregs[PR_CCS], env->cc_result, env->pregs[PR_MOF]); break; @@ -604,18 +610,18 @@ void helper_top_evaluate_flags(void) { case 4: env->pregs[PR_CCS] = - helper_evaluate_flags_move_4( + helper_evaluate_flags_move_4(env, env->pregs[PR_CCS], env->cc_result); break; case 2: env->pregs[PR_CCS] = - helper_evaluate_flags_move_2( + helper_evaluate_flags_move_2(env, env->pregs[PR_CCS], env->cc_result); break; default: - helper_evaluate_flags(); + helper_evaluate_flags(env); break; } break; @@ -626,12 +632,12 @@ void helper_top_evaluate_flags(void) case CC_OP_CMP: if (env->cc_size == 4) env->pregs[PR_CCS] = - helper_evaluate_flags_sub_4( + helper_evaluate_flags_sub_4(env, env->pregs[PR_CCS], env->cc_src, env->cc_dest, env->cc_result); else - helper_evaluate_flags(); + helper_evaluate_flags(env); break; default: { @@ -639,13 +645,13 @@ void helper_top_evaluate_flags(void) { case 4: env->pregs[PR_CCS] = - helper_evaluate_flags_alu_4( + helper_evaluate_flags_alu_4(env, env->pregs[PR_CCS], env->cc_src, env->cc_dest, env->cc_result); break; default: - helper_evaluate_flags(); + helper_evaluate_flags(env); break; } } diff --git a/target-cris/translate.c b/target-cris/translate.c index ad3187773e..283dd982bc 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -211,9 +211,9 @@ static inline void t_gen_mov_preg_TN(DisasContext *dc, int r, TCGv tn) tcg_gen_andi_tl(cpu_PR[r], tn, 3); else { if (r == PR_PID) - gen_helper_tlb_flush_pid(tn); + gen_helper_tlb_flush_pid(cpu_env, tn); if (dc->tb_flags & S_FLAG && r == PR_SPC) - gen_helper_spc_write(tn); + gen_helper_spc_write(cpu_env, tn); else if (r == PR_CCS) dc->cpustate_changed = 1; tcg_gen_mov_tl(cpu_PR[r], tn); @@ -278,7 +278,7 @@ static void cris_lock_irq(DisasContext *dc) static inline void t_gen_raise_exception(uint32_t index) { TCGv_i32 tmp = tcg_const_i32(index); - gen_helper_raise_exception(tmp); + gen_helper_raise_exception(cpu_env, tmp); tcg_temp_free_i32(tmp); } @@ -624,17 +624,17 @@ static void cris_evaluate_flags(DisasContext *dc) switch (dc->cc_op) { case CC_OP_MCP: - gen_helper_evaluate_flags_mcp(cpu_PR[PR_CCS], + gen_helper_evaluate_flags_mcp(cpu_PR[PR_CCS], cpu_env, cpu_PR[PR_CCS], cc_src, cc_dest, cc_result); break; case CC_OP_MULS: - gen_helper_evaluate_flags_muls(cpu_PR[PR_CCS], + gen_helper_evaluate_flags_muls(cpu_PR[PR_CCS], cpu_env, cpu_PR[PR_CCS], cc_result, cpu_PR[PR_MOF]); break; case CC_OP_MULU: - gen_helper_evaluate_flags_mulu(cpu_PR[PR_CCS], + gen_helper_evaluate_flags_mulu(cpu_PR[PR_CCS], cpu_env, cpu_PR[PR_CCS], cc_result, cpu_PR[PR_MOF]); break; @@ -648,15 +648,15 @@ static void cris_evaluate_flags(DisasContext *dc) switch (dc->cc_size) { case 4: - gen_helper_evaluate_flags_move_4(cpu_PR[PR_CCS], - cpu_PR[PR_CCS], cc_result); + gen_helper_evaluate_flags_move_4(cpu_PR[PR_CCS], + cpu_env, cpu_PR[PR_CCS], cc_result); break; case 2: - gen_helper_evaluate_flags_move_2(cpu_PR[PR_CCS], - cpu_PR[PR_CCS], cc_result); + gen_helper_evaluate_flags_move_2(cpu_PR[PR_CCS], + cpu_env, cpu_PR[PR_CCS], cc_result); break; default: - gen_helper_evaluate_flags(); + gen_helper_evaluate_flags(cpu_env); break; } break; @@ -666,21 +666,21 @@ static void cris_evaluate_flags(DisasContext *dc) case CC_OP_SUB: case CC_OP_CMP: if (dc->cc_size == 4) - gen_helper_evaluate_flags_sub_4(cpu_PR[PR_CCS], + gen_helper_evaluate_flags_sub_4(cpu_PR[PR_CCS], cpu_env, cpu_PR[PR_CCS], cc_src, cc_dest, cc_result); else - gen_helper_evaluate_flags(); + gen_helper_evaluate_flags(cpu_env); break; default: switch (dc->cc_size) { case 4: - gen_helper_evaluate_flags_alu_4(cpu_PR[PR_CCS], + gen_helper_evaluate_flags_alu_4(cpu_PR[PR_CCS], cpu_env, cpu_PR[PR_CCS], cc_src, cc_dest, cc_result); break; default: - gen_helper_evaluate_flags(); + gen_helper_evaluate_flags(cpu_env); break; } break; @@ -1475,7 +1475,7 @@ static int dec_btstq(DisasContext *dc) cris_cc_mask(dc, CC_MASK_NZ); cris_evaluate_flags(dc); - gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->op2], + gen_helper_btst(cpu_PR[PR_CCS], cpu_env, cpu_R[dc->op2], tcg_const_tl(dc->op1), cpu_PR[PR_CCS]); cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4); @@ -1925,7 +1925,7 @@ static int dec_btst_r(DisasContext *dc) dc->op1, dc->op2); cris_cc_mask(dc, CC_MASK_NZ); cris_evaluate_flags(dc); - gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->op2], + gen_helper_btst(cpu_PR[PR_CCS], cpu_env, cpu_R[dc->op2], cpu_R[dc->op1], cpu_PR[PR_CCS]); cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4); @@ -2135,14 +2135,16 @@ static int dec_move_rs(DisasContext *dc) { LOG_DIS("move $r%u, $s%u\n", dc->op1, dc->op2); cris_cc_mask(dc, 0); - gen_helper_movl_sreg_reg(tcg_const_tl(dc->op2), tcg_const_tl(dc->op1)); + gen_helper_movl_sreg_reg(cpu_env, tcg_const_tl(dc->op2), + tcg_const_tl(dc->op1)); return 2; } static int dec_move_sr(DisasContext *dc) { LOG_DIS("move $s%u, $r%u\n", dc->op2, dc->op1); cris_cc_mask(dc, 0); - gen_helper_movl_reg_sreg(tcg_const_tl(dc->op1), tcg_const_tl(dc->op2)); + gen_helper_movl_reg_sreg(cpu_env, tcg_const_tl(dc->op1), + tcg_const_tl(dc->op2)); return 2; } @@ -2906,14 +2908,14 @@ static int dec_rfe_etc(DisasContext *dc) /* rfe. */ LOG_DIS("rfe\n"); cris_evaluate_flags(dc); - gen_helper_rfe(); + gen_helper_rfe(cpu_env); dc->is_jmp = DISAS_UPDATE; break; case 5: /* rfn. */ LOG_DIS("rfn\n"); cris_evaluate_flags(dc); - gen_helper_rfn(); + gen_helper_rfn(cpu_env); dc->is_jmp = DISAS_UPDATE; break; case 6: diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c index 3629629d9d..9a39c6a83e 100644 --- a/target-cris/translate_v10.c +++ b/target-cris/translate_v10.c @@ -289,7 +289,7 @@ static unsigned int dec10_quick_imm(DisasContext *dc) } else { /* BTST */ cris_update_cc_op(dc, CC_OP_FLAGS, 4); - gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->dst], + gen_helper_btst(cpu_PR[PR_CCS], cpu_env, cpu_R[dc->dst], tcg_const_tl(imm), cpu_PR[PR_CCS]); } break; @@ -723,7 +723,7 @@ static unsigned int dec10_reg(DisasContext *dc) LOG_DIS("btst $r%d, $r%d sz=%d\n", dc->src, dc->dst, size); cris_cc_mask(dc, CC_MASK_NZVC); cris_update_cc_op(dc, CC_OP_FLAGS, 4); - gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->dst], + gen_helper_btst(cpu_PR[PR_CCS], cpu_env, cpu_R[dc->dst], cpu_R[dc->src], cpu_PR[PR_CCS]); break; case CRISV10_REG_DSTEP: From cf7e0c80aa21620ca36161faff7e0ce4f7b866ac Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 7 Sep 2012 16:13:27 +0200 Subject: [PATCH 0400/2270] target-cris: Switch to AREG0 free mode Add an explicit CPUCRISState parameter instead of relying on AREG0, and use cpu_ld* in translation and interrupt handling. Remove AREG0 swapping in tlb_fill(). Switch to AREG0 free mode Signed-off-by: Blue Swirl Signed-off-by: Aurelien Jarno --- configure | 2 +- target-cris/Makefile.objs | 2 - target-cris/helper.c | 4 +- target-cris/op_helper.c | 9 +- target-cris/translate.c | 256 ++++++++++++++++++------------------ target-cris/translate_v10.c | 95 ++++++------- 6 files changed, 181 insertions(+), 187 deletions(-) diff --git a/configure b/configure index 01a1b0b0b4..9698e6dbe6 100755 --- a/configure +++ b/configure @@ -3874,7 +3874,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile" case "$target_arch2" in - alpha | arm* | i386 | lm32 | m68k | microblaze* | or32 | s390x | sparc* | unicore32 | x86_64 | xtensa* | ppc*) + alpha | arm* | cris | i386 | lm32 | m68k | microblaze* | or32 | s390x | sparc* | unicore32 | x86_64 | xtensa* | ppc*) echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak ;; esac diff --git a/target-cris/Makefile.objs b/target-cris/Makefile.objs index 4b09e8c6b5..afb87bcc80 100644 --- a/target-cris/Makefile.objs +++ b/target-cris/Makefile.objs @@ -1,4 +1,2 @@ obj-y += translate.o op_helper.o helper.o cpu.o obj-$(CONFIG_SOFTMMU) += mmu.o machine.o - -$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-cris/helper.c b/target-cris/helper.c index bfbc29ec6a..1bdb7e26b7 100644 --- a/target-cris/helper.c +++ b/target-cris/helper.c @@ -151,7 +151,7 @@ static void do_interruptv10(CPUCRISState *env) } /* Now that we are in kernel mode, load the handlers address. */ - env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4); + env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4); env->locked_irq = 1; env->pregs[PR_CCS] |= F_FLAG_V10; /* set F. */ @@ -233,7 +233,7 @@ void do_interrupt(CPUCRISState *env) /* Now that we are in kernel mode, load the handlers address. This load may not fault, real hw leaves that behaviour as undefined. */ - env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4); + env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4); /* Clear the excption_index to avoid spurios hw_aborts for recursive bus faults. */ diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c index 5ca85a09e4..a7468d41c6 100644 --- a/target-cris/op_helper.c +++ b/target-cris/op_helper.c @@ -19,7 +19,6 @@ */ #include "cpu.h" -#include "dyngen-exec.h" #include "mmu.h" #include "helper.h" #include "host-utils.h" @@ -55,17 +54,12 @@ /* Try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ -/* XXX: fix it to restore all registers */ -void tlb_fill(CPUCRISState *env1, target_ulong addr, int is_write, int mmu_idx, +void tlb_fill(CPUCRISState *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { TranslationBlock *tb; - CPUCRISState *saved_env; int ret; - saved_env = env; - env = env1; - D_LOG("%s pc=%x tpc=%x ra=%p\n", __func__, env->pc, env->debug1, (void *)retaddr); ret = cpu_cris_handle_mmu_fault(env, addr, is_write, mmu_idx); @@ -84,7 +78,6 @@ void tlb_fill(CPUCRISState *env1, target_ulong addr, int is_write, int mmu_idx, } cpu_loop_exit(env); } - env = saved_env; } #endif diff --git a/target-cris/translate.c b/target-cris/translate.c index 283dd982bc..19144b5e29 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -78,7 +78,7 @@ typedef struct DisasContext { target_ulong pc, ppc; /* Decoder. */ - unsigned int (*decoder)(struct DisasContext *dc); + unsigned int (*decoder)(CPUCRISState *env, struct DisasContext *dc); uint32_t ir; uint32_t opcode; unsigned int op1; @@ -233,7 +233,7 @@ static int sign_extend(unsigned int val, unsigned int width) return sval; } -static int cris_fetch(DisasContext *dc, uint32_t addr, +static int cris_fetch(CPUCRISState *env, DisasContext *dc, uint32_t addr, unsigned int size, unsigned int sign) { int r; @@ -241,24 +241,24 @@ static int cris_fetch(DisasContext *dc, uint32_t addr, switch (size) { case 4: { - r = ldl_code(addr); + r = cpu_ldl_code(env, addr); break; } case 2: { if (sign) { - r = ldsw_code(addr); + r = cpu_ldsw_code(env, addr); } else { - r = lduw_code(addr); + r = cpu_lduw_code(env, addr); } break; } case 1: { if (sign) { - r = ldsb_code(addr); + r = cpu_ldsb_code(env, addr); } else { - r = ldub_code(addr); + r = cpu_ldub_code(env, addr); } break; } @@ -1304,8 +1304,8 @@ static void dec_prep_alu_r(DisasContext *dc, int rs, int rd, t_gen_zext(dst, cpu_R[rd], size); } -static int dec_prep_move_m(DisasContext *dc, int s_ext, int memsize, - TCGv dst) +static int dec_prep_move_m(CPUCRISState *env, DisasContext *dc, + int s_ext, int memsize, TCGv dst) { unsigned int rs; uint32_t imm; @@ -1321,7 +1321,7 @@ static int dec_prep_move_m(DisasContext *dc, int s_ext, int memsize, if (memsize == 1) insn_len++; - imm = cris_fetch(dc, dc->pc + 2, memsize, s_ext); + imm = cris_fetch(env, dc, dc->pc + 2, memsize, s_ext); tcg_gen_movi_tl(dst, imm); dc->postinc = 0; } else { @@ -1338,12 +1338,12 @@ static int dec_prep_move_m(DisasContext *dc, int s_ext, int memsize, /* Prepare T0 and T1 for a memory + alu operation. s_ext decides if the operand1 should be sign-extended or zero-extended when needed. */ -static int dec_prep_alu_m(DisasContext *dc, int s_ext, int memsize, - TCGv dst, TCGv src) +static int dec_prep_alu_m(CPUCRISState *env, DisasContext *dc, + int s_ext, int memsize, TCGv dst, TCGv src) { int insn_len; - insn_len = dec_prep_move_m(dc, s_ext, memsize, src); + insn_len = dec_prep_move_m(env, dc, s_ext, memsize, src); tcg_gen_mov_tl(dst, cpu_R[dc->op2]); return insn_len; } @@ -1362,7 +1362,7 @@ static const char *cc_name(int cc) /* Start of insn decoders. */ -static int dec_bccq(DisasContext *dc) +static int dec_bccq(CPUCRISState *env, DisasContext *dc) { int32_t offset; int sign; @@ -1382,7 +1382,7 @@ static int dec_bccq(DisasContext *dc) cris_prepare_cc_branch (dc, offset, cond); return 2; } -static int dec_addoq(DisasContext *dc) +static int dec_addoq(CPUCRISState *env, DisasContext *dc) { int32_t imm; @@ -1396,7 +1396,7 @@ static int dec_addoq(DisasContext *dc) return 2; } -static int dec_addq(DisasContext *dc) +static int dec_addq(CPUCRISState *env, DisasContext *dc) { LOG_DIS("addq %u, $r%u\n", dc->op1, dc->op2); @@ -1408,7 +1408,7 @@ static int dec_addq(DisasContext *dc) cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4); return 2; } -static int dec_moveq(DisasContext *dc) +static int dec_moveq(CPUCRISState *env, DisasContext *dc) { uint32_t imm; @@ -1419,7 +1419,7 @@ static int dec_moveq(DisasContext *dc) tcg_gen_movi_tl(cpu_R[dc->op2], imm); return 2; } -static int dec_subq(DisasContext *dc) +static int dec_subq(CPUCRISState *env, DisasContext *dc) { dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); @@ -1430,7 +1430,7 @@ static int dec_subq(DisasContext *dc) cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4); return 2; } -static int dec_cmpq(DisasContext *dc) +static int dec_cmpq(CPUCRISState *env, DisasContext *dc) { uint32_t imm; dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); @@ -1443,7 +1443,7 @@ static int dec_cmpq(DisasContext *dc) cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4); return 2; } -static int dec_andq(DisasContext *dc) +static int dec_andq(CPUCRISState *env, DisasContext *dc) { uint32_t imm; dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); @@ -1456,7 +1456,7 @@ static int dec_andq(DisasContext *dc) cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4); return 2; } -static int dec_orq(DisasContext *dc) +static int dec_orq(CPUCRISState *env, DisasContext *dc) { uint32_t imm; dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); @@ -1468,7 +1468,7 @@ static int dec_orq(DisasContext *dc) cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4); return 2; } -static int dec_btstq(DisasContext *dc) +static int dec_btstq(CPUCRISState *env, DisasContext *dc) { dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); LOG_DIS("btstq %u, $r%d\n", dc->op1, dc->op2); @@ -1483,7 +1483,7 @@ static int dec_btstq(DisasContext *dc) dc->flags_uptodate = 1; return 2; } -static int dec_asrq(DisasContext *dc) +static int dec_asrq(CPUCRISState *env, DisasContext *dc) { dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); LOG_DIS("asrq %u, $r%d\n", dc->op1, dc->op2); @@ -1495,7 +1495,7 @@ static int dec_asrq(DisasContext *dc) cpu_R[dc->op2], cpu_R[dc->op2], 4); return 2; } -static int dec_lslq(DisasContext *dc) +static int dec_lslq(CPUCRISState *env, DisasContext *dc) { dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); LOG_DIS("lslq %u, $r%d\n", dc->op1, dc->op2); @@ -1509,7 +1509,7 @@ static int dec_lslq(DisasContext *dc) cpu_R[dc->op2], cpu_R[dc->op2], 4); return 2; } -static int dec_lsrq(DisasContext *dc) +static int dec_lsrq(CPUCRISState *env, DisasContext *dc) { dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); LOG_DIS("lsrq %u, $r%d\n", dc->op1, dc->op2); @@ -1523,7 +1523,7 @@ static int dec_lsrq(DisasContext *dc) return 2; } -static int dec_move_r(DisasContext *dc) +static int dec_move_r(CPUCRISState *env, DisasContext *dc) { int size = memsize_zz(dc); @@ -1551,7 +1551,7 @@ static int dec_move_r(DisasContext *dc) return 2; } -static int dec_scc_r(DisasContext *dc) +static int dec_scc_r(CPUCRISState *env, DisasContext *dc) { int cond = dc->op2; @@ -1594,7 +1594,7 @@ static inline void cris_alu_free_temps(DisasContext *dc, int size, TCGv *t) } } -static int dec_and_r(DisasContext *dc) +static int dec_and_r(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int size = memsize_zz(dc); @@ -1611,7 +1611,7 @@ static int dec_and_r(DisasContext *dc) return 2; } -static int dec_lz_r(DisasContext *dc) +static int dec_lz_r(CPUCRISState *env, DisasContext *dc) { TCGv t0; LOG_DIS("lz $r%u, $r%u\n", @@ -1624,7 +1624,7 @@ static int dec_lz_r(DisasContext *dc) return 2; } -static int dec_lsl_r(DisasContext *dc) +static int dec_lsl_r(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int size = memsize_zz(dc); @@ -1641,7 +1641,7 @@ static int dec_lsl_r(DisasContext *dc) return 2; } -static int dec_lsr_r(DisasContext *dc) +static int dec_lsr_r(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int size = memsize_zz(dc); @@ -1658,7 +1658,7 @@ static int dec_lsr_r(DisasContext *dc) return 2; } -static int dec_asr_r(DisasContext *dc) +static int dec_asr_r(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int size = memsize_zz(dc); @@ -1675,7 +1675,7 @@ static int dec_asr_r(DisasContext *dc) return 2; } -static int dec_muls_r(DisasContext *dc) +static int dec_muls_r(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int size = memsize_zz(dc); @@ -1691,7 +1691,7 @@ static int dec_muls_r(DisasContext *dc) return 2; } -static int dec_mulu_r(DisasContext *dc) +static int dec_mulu_r(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int size = memsize_zz(dc); @@ -1708,7 +1708,7 @@ static int dec_mulu_r(DisasContext *dc) } -static int dec_dstep_r(DisasContext *dc) +static int dec_dstep_r(CPUCRISState *env, DisasContext *dc) { LOG_DIS("dstep $r%u, $r%u\n", dc->op1, dc->op2); cris_cc_mask(dc, CC_MASK_NZ); @@ -1717,7 +1717,7 @@ static int dec_dstep_r(DisasContext *dc) return 2; } -static int dec_xor_r(DisasContext *dc) +static int dec_xor_r(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int size = memsize_zz(dc); @@ -1733,7 +1733,7 @@ static int dec_xor_r(DisasContext *dc) return 2; } -static int dec_bound_r(DisasContext *dc) +static int dec_bound_r(CPUCRISState *env, DisasContext *dc) { TCGv l0; int size = memsize_zz(dc); @@ -1747,7 +1747,7 @@ static int dec_bound_r(DisasContext *dc) return 2; } -static int dec_cmp_r(DisasContext *dc) +static int dec_cmp_r(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int size = memsize_zz(dc); @@ -1762,7 +1762,7 @@ static int dec_cmp_r(DisasContext *dc) return 2; } -static int dec_abs_r(DisasContext *dc) +static int dec_abs_r(CPUCRISState *env, DisasContext *dc) { TCGv t0; @@ -1781,7 +1781,7 @@ static int dec_abs_r(DisasContext *dc) return 2; } -static int dec_add_r(DisasContext *dc) +static int dec_add_r(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int size = memsize_zz(dc); @@ -1796,7 +1796,7 @@ static int dec_add_r(DisasContext *dc) return 2; } -static int dec_addc_r(DisasContext *dc) +static int dec_addc_r(CPUCRISState *env, DisasContext *dc) { LOG_DIS("addc $r%u, $r%u\n", dc->op1, dc->op2); @@ -1811,7 +1811,7 @@ static int dec_addc_r(DisasContext *dc) return 2; } -static int dec_mcp_r(DisasContext *dc) +static int dec_mcp_r(CPUCRISState *env, DisasContext *dc) { LOG_DIS("mcp $p%u, $r%u\n", dc->op2, dc->op1); @@ -1838,7 +1838,7 @@ static char * swapmode_name(int mode, char *modename) { } #endif -static int dec_swap_r(DisasContext *dc) +static int dec_swap_r(CPUCRISState *env, DisasContext *dc) { TCGv t0; #if DISAS_CRIS @@ -1864,7 +1864,7 @@ static int dec_swap_r(DisasContext *dc) return 2; } -static int dec_or_r(DisasContext *dc) +static int dec_or_r(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int size = memsize_zz(dc); @@ -1878,7 +1878,7 @@ static int dec_or_r(DisasContext *dc) return 2; } -static int dec_addi_r(DisasContext *dc) +static int dec_addi_r(CPUCRISState *env, DisasContext *dc) { TCGv t0; LOG_DIS("addi.%c $r%u, $r%u\n", @@ -1891,7 +1891,7 @@ static int dec_addi_r(DisasContext *dc) return 2; } -static int dec_addi_acr(DisasContext *dc) +static int dec_addi_acr(CPUCRISState *env, DisasContext *dc) { TCGv t0; LOG_DIS("addi.%c $r%u, $r%u, $acr\n", @@ -1904,7 +1904,7 @@ static int dec_addi_acr(DisasContext *dc) return 2; } -static int dec_neg_r(DisasContext *dc) +static int dec_neg_r(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int size = memsize_zz(dc); @@ -1919,7 +1919,7 @@ static int dec_neg_r(DisasContext *dc) return 2; } -static int dec_btst_r(DisasContext *dc) +static int dec_btst_r(CPUCRISState *env, DisasContext *dc) { LOG_DIS("btst $r%u, $r%u\n", dc->op1, dc->op2); @@ -1934,7 +1934,7 @@ static int dec_btst_r(DisasContext *dc) return 2; } -static int dec_sub_r(DisasContext *dc) +static int dec_sub_r(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int size = memsize_zz(dc); @@ -1949,7 +1949,7 @@ static int dec_sub_r(DisasContext *dc) } /* Zero extension. From size to dword. */ -static int dec_movu_r(DisasContext *dc) +static int dec_movu_r(CPUCRISState *env, DisasContext *dc) { TCGv t0; int size = memsize_z(dc); @@ -1966,7 +1966,7 @@ static int dec_movu_r(DisasContext *dc) } /* Sign extension. From size to dword. */ -static int dec_movs_r(DisasContext *dc) +static int dec_movs_r(CPUCRISState *env, DisasContext *dc) { TCGv t0; int size = memsize_z(dc); @@ -1985,7 +1985,7 @@ static int dec_movs_r(DisasContext *dc) } /* zero extension. From size to dword. */ -static int dec_addu_r(DisasContext *dc) +static int dec_addu_r(CPUCRISState *env, DisasContext *dc) { TCGv t0; int size = memsize_z(dc); @@ -2004,7 +2004,7 @@ static int dec_addu_r(DisasContext *dc) } /* Sign extension. From size to dword. */ -static int dec_adds_r(DisasContext *dc) +static int dec_adds_r(CPUCRISState *env, DisasContext *dc) { TCGv t0; int size = memsize_z(dc); @@ -2023,7 +2023,7 @@ static int dec_adds_r(DisasContext *dc) } /* Zero extension. From size to dword. */ -static int dec_subu_r(DisasContext *dc) +static int dec_subu_r(CPUCRISState *env, DisasContext *dc) { TCGv t0; int size = memsize_z(dc); @@ -2042,7 +2042,7 @@ static int dec_subu_r(DisasContext *dc) } /* Sign extension. From size to dword. */ -static int dec_subs_r(DisasContext *dc) +static int dec_subs_r(CPUCRISState *env, DisasContext *dc) { TCGv t0; int size = memsize_z(dc); @@ -2060,7 +2060,7 @@ static int dec_subs_r(DisasContext *dc) return 2; } -static int dec_setclrf(DisasContext *dc) +static int dec_setclrf(CPUCRISState *env, DisasContext *dc) { uint32_t flags; int set = (~dc->opcode >> 2) & 1; @@ -2131,7 +2131,7 @@ static int dec_setclrf(DisasContext *dc) return 2; } -static int dec_move_rs(DisasContext *dc) +static int dec_move_rs(CPUCRISState *env, DisasContext *dc) { LOG_DIS("move $r%u, $s%u\n", dc->op1, dc->op2); cris_cc_mask(dc, 0); @@ -2139,7 +2139,7 @@ static int dec_move_rs(DisasContext *dc) tcg_const_tl(dc->op1)); return 2; } -static int dec_move_sr(DisasContext *dc) +static int dec_move_sr(CPUCRISState *env, DisasContext *dc) { LOG_DIS("move $s%u, $r%u\n", dc->op2, dc->op1); cris_cc_mask(dc, 0); @@ -2148,7 +2148,7 @@ static int dec_move_sr(DisasContext *dc) return 2; } -static int dec_move_rp(DisasContext *dc) +static int dec_move_rp(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; LOG_DIS("move $r%u, $p%u\n", dc->op1, dc->op2); @@ -2178,7 +2178,7 @@ static int dec_move_rp(DisasContext *dc) tcg_temp_free(t[0]); return 2; } -static int dec_move_pr(DisasContext *dc) +static int dec_move_pr(CPUCRISState *env, DisasContext *dc) { TCGv t0; LOG_DIS("move $p%u, $r%u\n", dc->op2, dc->op1); @@ -2200,7 +2200,7 @@ static int dec_move_pr(DisasContext *dc) return 2; } -static int dec_move_mr(DisasContext *dc) +static int dec_move_mr(CPUCRISState *env, DisasContext *dc) { int memsize = memsize_zz(dc); int insn_len; @@ -2210,7 +2210,7 @@ static int dec_move_mr(DisasContext *dc) dc->op2); if (memsize == 4) { - insn_len = dec_prep_move_m(dc, 0, 4, cpu_R[dc->op2]); + insn_len = dec_prep_move_m(env, dc, 0, 4, cpu_R[dc->op2]); cris_cc_mask(dc, CC_MASK_NZ); cris_update_cc_op(dc, CC_OP_MOVE, 4); cris_update_cc_x(dc); @@ -2220,7 +2220,7 @@ static int dec_move_mr(DisasContext *dc) TCGv t0; t0 = tcg_temp_new(); - insn_len = dec_prep_move_m(dc, 0, memsize, t0); + insn_len = dec_prep_move_m(env, dc, 0, memsize, t0); cris_cc_mask(dc, CC_MASK_NZ); cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t0, memsize); @@ -2242,7 +2242,7 @@ static inline void cris_alu_m_free_temps(TCGv *t) tcg_temp_free(t[1]); } -static int dec_movs_m(DisasContext *dc) +static int dec_movs_m(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int memsize = memsize_z(dc); @@ -2254,7 +2254,7 @@ static int dec_movs_m(DisasContext *dc) cris_alu_m_alloc_temps(t); /* sign extend. */ - insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]); cris_cc_mask(dc, CC_MASK_NZ); cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); @@ -2263,7 +2263,7 @@ static int dec_movs_m(DisasContext *dc) return insn_len; } -static int dec_addu_m(DisasContext *dc) +static int dec_addu_m(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int memsize = memsize_z(dc); @@ -2275,7 +2275,7 @@ static int dec_addu_m(DisasContext *dc) cris_alu_m_alloc_temps(t); /* sign extend. */ - insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); cris_cc_mask(dc, CC_MASK_NZVC); cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); @@ -2284,7 +2284,7 @@ static int dec_addu_m(DisasContext *dc) return insn_len; } -static int dec_adds_m(DisasContext *dc) +static int dec_adds_m(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int memsize = memsize_z(dc); @@ -2296,7 +2296,7 @@ static int dec_adds_m(DisasContext *dc) cris_alu_m_alloc_temps(t); /* sign extend. */ - insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]); cris_cc_mask(dc, CC_MASK_NZVC); cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); do_postinc(dc, memsize); @@ -2304,7 +2304,7 @@ static int dec_adds_m(DisasContext *dc) return insn_len; } -static int dec_subu_m(DisasContext *dc) +static int dec_subu_m(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int memsize = memsize_z(dc); @@ -2316,7 +2316,7 @@ static int dec_subu_m(DisasContext *dc) cris_alu_m_alloc_temps(t); /* sign extend. */ - insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); cris_cc_mask(dc, CC_MASK_NZVC); cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); do_postinc(dc, memsize); @@ -2324,7 +2324,7 @@ static int dec_subu_m(DisasContext *dc) return insn_len; } -static int dec_subs_m(DisasContext *dc) +static int dec_subs_m(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int memsize = memsize_z(dc); @@ -2336,7 +2336,7 @@ static int dec_subs_m(DisasContext *dc) cris_alu_m_alloc_temps(t); /* sign extend. */ - insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]); cris_cc_mask(dc, CC_MASK_NZVC); cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); do_postinc(dc, memsize); @@ -2344,7 +2344,7 @@ static int dec_subs_m(DisasContext *dc) return insn_len; } -static int dec_movu_m(DisasContext *dc) +static int dec_movu_m(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int memsize = memsize_z(dc); @@ -2356,7 +2356,7 @@ static int dec_movu_m(DisasContext *dc) dc->op2); cris_alu_m_alloc_temps(t); - insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); cris_cc_mask(dc, CC_MASK_NZ); cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); do_postinc(dc, memsize); @@ -2364,7 +2364,7 @@ static int dec_movu_m(DisasContext *dc) return insn_len; } -static int dec_cmpu_m(DisasContext *dc) +static int dec_cmpu_m(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int memsize = memsize_z(dc); @@ -2375,7 +2375,7 @@ static int dec_cmpu_m(DisasContext *dc) dc->op2); cris_alu_m_alloc_temps(t); - insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); cris_cc_mask(dc, CC_MASK_NZVC); cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); do_postinc(dc, memsize); @@ -2383,7 +2383,7 @@ static int dec_cmpu_m(DisasContext *dc) return insn_len; } -static int dec_cmps_m(DisasContext *dc) +static int dec_cmps_m(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int memsize = memsize_z(dc); @@ -2394,7 +2394,7 @@ static int dec_cmps_m(DisasContext *dc) dc->op2); cris_alu_m_alloc_temps(t); - insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]); cris_cc_mask(dc, CC_MASK_NZVC); cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], cpu_R[dc->op2], t[1], @@ -2404,7 +2404,7 @@ static int dec_cmps_m(DisasContext *dc) return insn_len; } -static int dec_cmp_m(DisasContext *dc) +static int dec_cmp_m(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int memsize = memsize_zz(dc); @@ -2415,7 +2415,7 @@ static int dec_cmp_m(DisasContext *dc) dc->op2); cris_alu_m_alloc_temps(t); - insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); cris_cc_mask(dc, CC_MASK_NZVC); cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], cpu_R[dc->op2], t[1], @@ -2425,7 +2425,7 @@ static int dec_cmp_m(DisasContext *dc) return insn_len; } -static int dec_test_m(DisasContext *dc) +static int dec_test_m(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int memsize = memsize_zz(dc); @@ -2438,7 +2438,7 @@ static int dec_test_m(DisasContext *dc) cris_evaluate_flags(dc); cris_alu_m_alloc_temps(t); - insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); cris_cc_mask(dc, CC_MASK_NZ); tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3); @@ -2449,7 +2449,7 @@ static int dec_test_m(DisasContext *dc) return insn_len; } -static int dec_and_m(DisasContext *dc) +static int dec_and_m(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int memsize = memsize_zz(dc); @@ -2460,7 +2460,7 @@ static int dec_and_m(DisasContext *dc) dc->op2); cris_alu_m_alloc_temps(t); - insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); cris_cc_mask(dc, CC_MASK_NZ); cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], memsize_zz(dc)); do_postinc(dc, memsize); @@ -2468,7 +2468,7 @@ static int dec_and_m(DisasContext *dc) return insn_len; } -static int dec_add_m(DisasContext *dc) +static int dec_add_m(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int memsize = memsize_zz(dc); @@ -2479,7 +2479,7 @@ static int dec_add_m(DisasContext *dc) dc->op2); cris_alu_m_alloc_temps(t); - insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); cris_cc_mask(dc, CC_MASK_NZVC); cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], t[0], t[1], memsize_zz(dc)); @@ -2488,7 +2488,7 @@ static int dec_add_m(DisasContext *dc) return insn_len; } -static int dec_addo_m(DisasContext *dc) +static int dec_addo_m(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int memsize = memsize_zz(dc); @@ -2499,7 +2499,7 @@ static int dec_addo_m(DisasContext *dc) dc->op2); cris_alu_m_alloc_temps(t); - insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]); cris_cc_mask(dc, 0); cris_alu(dc, CC_OP_ADD, cpu_R[R_ACR], t[0], t[1], 4); do_postinc(dc, memsize); @@ -2507,7 +2507,7 @@ static int dec_addo_m(DisasContext *dc) return insn_len; } -static int dec_bound_m(DisasContext *dc) +static int dec_bound_m(CPUCRISState *env, DisasContext *dc) { TCGv l[2]; int memsize = memsize_zz(dc); @@ -2519,7 +2519,7 @@ static int dec_bound_m(DisasContext *dc) l[0] = tcg_temp_local_new(); l[1] = tcg_temp_local_new(); - insn_len = dec_prep_alu_m(dc, 0, memsize, l[0], l[1]); + insn_len = dec_prep_alu_m(env, dc, 0, memsize, l[0], l[1]); cris_cc_mask(dc, CC_MASK_NZ); cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], l[0], l[1], 4); do_postinc(dc, memsize); @@ -2528,7 +2528,7 @@ static int dec_bound_m(DisasContext *dc) return insn_len; } -static int dec_addc_mr(DisasContext *dc) +static int dec_addc_mr(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int insn_len = 2; @@ -2543,7 +2543,7 @@ static int dec_addc_mr(DisasContext *dc) dc->flags_x = X_FLAG; cris_alu_m_alloc_temps(t); - insn_len = dec_prep_alu_m(dc, 0, 4, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 0, 4, t[0], t[1]); cris_cc_mask(dc, CC_MASK_NZVC); cris_alu(dc, CC_OP_ADDC, cpu_R[dc->op2], t[0], t[1], 4); do_postinc(dc, 4); @@ -2551,7 +2551,7 @@ static int dec_addc_mr(DisasContext *dc) return insn_len; } -static int dec_sub_m(DisasContext *dc) +static int dec_sub_m(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int memsize = memsize_zz(dc); @@ -2562,7 +2562,7 @@ static int dec_sub_m(DisasContext *dc) dc->op2, dc->ir, dc->zzsize); cris_alu_m_alloc_temps(t); - insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); cris_cc_mask(dc, CC_MASK_NZVC); cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], memsize); do_postinc(dc, memsize); @@ -2570,7 +2570,7 @@ static int dec_sub_m(DisasContext *dc) return insn_len; } -static int dec_or_m(DisasContext *dc) +static int dec_or_m(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int memsize = memsize_zz(dc); @@ -2581,7 +2581,7 @@ static int dec_or_m(DisasContext *dc) dc->op2, dc->pc); cris_alu_m_alloc_temps(t); - insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); cris_cc_mask(dc, CC_MASK_NZ); cris_alu(dc, CC_OP_OR, cpu_R[dc->op2], t[0], t[1], memsize_zz(dc)); @@ -2590,7 +2590,7 @@ static int dec_or_m(DisasContext *dc) return insn_len; } -static int dec_move_mp(DisasContext *dc) +static int dec_move_mp(CPUCRISState *env, DisasContext *dc) { TCGv t[2]; int memsize = memsize_zz(dc); @@ -2603,7 +2603,7 @@ static int dec_move_mp(DisasContext *dc) dc->op2); cris_alu_m_alloc_temps(t); - insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); + insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); cris_cc_mask(dc, 0); if (dc->op2 == PR_CCS) { cris_evaluate_flags(dc); @@ -2622,7 +2622,7 @@ static int dec_move_mp(DisasContext *dc) return insn_len; } -static int dec_move_pm(DisasContext *dc) +static int dec_move_pm(CPUCRISState *env, DisasContext *dc) { TCGv t0; int memsize; @@ -2648,7 +2648,7 @@ static int dec_move_pm(DisasContext *dc) return 2; } -static int dec_movem_mr(DisasContext *dc) +static int dec_movem_mr(CPUCRISState *env, DisasContext *dc) { TCGv_i64 tmp[16]; TCGv tmp32; @@ -2695,7 +2695,7 @@ static int dec_movem_mr(DisasContext *dc) return 2; } -static int dec_movem_rm(DisasContext *dc) +static int dec_movem_rm(CPUCRISState *env, DisasContext *dc) { TCGv tmp; TCGv addr; @@ -2724,7 +2724,7 @@ static int dec_movem_rm(DisasContext *dc) return 2; } -static int dec_move_rm(DisasContext *dc) +static int dec_move_rm(CPUCRISState *env, DisasContext *dc) { int memsize; @@ -2743,7 +2743,7 @@ static int dec_move_rm(DisasContext *dc) return 2; } -static int dec_lapcq(DisasContext *dc) +static int dec_lapcq(CPUCRISState *env, DisasContext *dc) { LOG_DIS("lapcq %x, $r%u\n", dc->pc + dc->op1*2, dc->op2); @@ -2752,7 +2752,7 @@ static int dec_lapcq(DisasContext *dc) return 2; } -static int dec_lapc_im(DisasContext *dc) +static int dec_lapc_im(CPUCRISState *env, DisasContext *dc) { unsigned int rd; int32_t imm; @@ -2761,7 +2761,7 @@ static int dec_lapc_im(DisasContext *dc) rd = dc->op2; cris_cc_mask(dc, 0); - imm = cris_fetch(dc, dc->pc + 2, 4, 0); + imm = cris_fetch(env, dc, dc->pc + 2, 4, 0); LOG_DIS("lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2); pc = dc->pc; @@ -2771,7 +2771,7 @@ static int dec_lapc_im(DisasContext *dc) } /* Jump to special reg. */ -static int dec_jump_p(DisasContext *dc) +static int dec_jump_p(CPUCRISState *env, DisasContext *dc) { LOG_DIS("jump $p%u\n", dc->op2); @@ -2786,7 +2786,7 @@ static int dec_jump_p(DisasContext *dc) } /* Jump and save. */ -static int dec_jas_r(DisasContext *dc) +static int dec_jas_r(CPUCRISState *env, DisasContext *dc) { LOG_DIS("jas $r%u, $p%u\n", dc->op1, dc->op2); cris_cc_mask(dc, 0); @@ -2800,11 +2800,11 @@ static int dec_jas_r(DisasContext *dc) return 2; } -static int dec_jas_im(DisasContext *dc) +static int dec_jas_im(CPUCRISState *env, DisasContext *dc) { uint32_t imm; - imm = cris_fetch(dc, dc->pc + 2, 4, 0); + imm = cris_fetch(env, dc, dc->pc + 2, 4, 0); LOG_DIS("jas 0x%x\n", imm); cris_cc_mask(dc, 0); @@ -2816,11 +2816,11 @@ static int dec_jas_im(DisasContext *dc) return 6; } -static int dec_jasc_im(DisasContext *dc) +static int dec_jasc_im(CPUCRISState *env, DisasContext *dc) { uint32_t imm; - imm = cris_fetch(dc, dc->pc + 2, 4, 0); + imm = cris_fetch(env, dc, dc->pc + 2, 4, 0); LOG_DIS("jasc 0x%x\n", imm); cris_cc_mask(dc, 0); @@ -2832,7 +2832,7 @@ static int dec_jasc_im(DisasContext *dc) return 6; } -static int dec_jasc_r(DisasContext *dc) +static int dec_jasc_r(CPUCRISState *env, DisasContext *dc) { LOG_DIS("jasc_r $r%u, $p%u\n", dc->op1, dc->op2); cris_cc_mask(dc, 0); @@ -2843,12 +2843,12 @@ static int dec_jasc_r(DisasContext *dc) return 2; } -static int dec_bcc_im(DisasContext *dc) +static int dec_bcc_im(CPUCRISState *env, DisasContext *dc) { int32_t offset; uint32_t cond = dc->op2; - offset = cris_fetch(dc, dc->pc + 2, 2, 1); + offset = cris_fetch(env, dc, dc->pc + 2, 2, 1); LOG_DIS("b%s %d pc=%x dst=%x\n", cc_name(cond), offset, @@ -2860,12 +2860,12 @@ static int dec_bcc_im(DisasContext *dc) return 4; } -static int dec_bas_im(DisasContext *dc) +static int dec_bas_im(CPUCRISState *env, DisasContext *dc) { int32_t simm; - simm = cris_fetch(dc, dc->pc + 2, 4, 0); + simm = cris_fetch(env, dc, dc->pc + 2, 4, 0); LOG_DIS("bas 0x%x, $p%u\n", dc->pc + simm, dc->op2); cris_cc_mask(dc, 0); @@ -2877,10 +2877,10 @@ static int dec_bas_im(DisasContext *dc) return 6; } -static int dec_basc_im(DisasContext *dc) +static int dec_basc_im(CPUCRISState *env, DisasContext *dc) { int32_t simm; - simm = cris_fetch(dc, dc->pc + 2, 4, 0); + simm = cris_fetch(env, dc, dc->pc + 2, 4, 0); LOG_DIS("basc 0x%x, $p%u\n", dc->pc + simm, dc->op2); cris_cc_mask(dc, 0); @@ -2892,7 +2892,7 @@ static int dec_basc_im(DisasContext *dc) return 6; } -static int dec_rfe_etc(DisasContext *dc) +static int dec_rfe_etc(CPUCRISState *env, DisasContext *dc) { cris_cc_mask(dc, 0); @@ -2939,17 +2939,17 @@ static int dec_rfe_etc(DisasContext *dc) return 2; } -static int dec_ftag_fidx_d_m(DisasContext *dc) +static int dec_ftag_fidx_d_m(CPUCRISState *env, DisasContext *dc) { return 2; } -static int dec_ftag_fidx_i_m(DisasContext *dc) +static int dec_ftag_fidx_i_m(CPUCRISState *env, DisasContext *dc) { return 2; } -static int dec_null(DisasContext *dc) +static int dec_null(CPUCRISState *env, DisasContext *dc) { printf ("unknown insn pc=%x opc=%x op1=%x op2=%x\n", dc->pc, dc->opcode, dc->op1, dc->op2); @@ -2963,7 +2963,7 @@ static struct decoder_info { uint32_t bits; uint32_t mask; }; - int (*dec)(DisasContext *dc); + int (*dec)(CPUCRISState *env, DisasContext *dc); } decinfo[] = { /* Order matters here. */ {DEC_MOVEQ, dec_moveq}, @@ -3069,7 +3069,7 @@ static struct decoder_info { {{0, 0}, dec_null} }; -static unsigned int crisv32_decoder(DisasContext *dc) +static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc) { int insn_len = 2; int i; @@ -3078,7 +3078,7 @@ static unsigned int crisv32_decoder(DisasContext *dc) tcg_gen_debug_insn_start(dc->pc); /* Load a halfword onto the instruction register. */ - dc->ir = cris_fetch(dc, dc->pc, 2, 0); + dc->ir = cris_fetch(env, dc, dc->pc, 2, 0); /* Now decode it. */ dc->opcode = EXTRACT_FIELD(dc->ir, 4, 11); @@ -3092,7 +3092,7 @@ static unsigned int crisv32_decoder(DisasContext *dc) for (i = 0; i < ARRAY_SIZE(decinfo); i++) { if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) { - insn_len = decinfo[i].dec(dc); + insn_len = decinfo[i].dec(env, dc); break; } } @@ -3286,7 +3286,7 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb, gen_io_start(); dc->clear_x = 1; - insn_len = dc->decoder(dc); + insn_len = dc->decoder(env, dc); dc->ppc = dc->pc; dc->pc += insn_len; if (dc->clear_x) diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c index 9a39c6a83e..d2cca892e0 100644 --- a/target-cris/translate_v10.c +++ b/target-cris/translate_v10.c @@ -164,8 +164,8 @@ static unsigned int crisv10_post_memaddr(DisasContext *dc, unsigned int size) return insn_len; } -static int dec10_prep_move_m(DisasContext *dc, int s_ext, int memsize, - TCGv dst) +static int dec10_prep_move_m(CPUCRISState *env, DisasContext *dc, + int s_ext, int memsize, TCGv dst) { unsigned int rs; uint32_t imm; @@ -182,17 +182,17 @@ static int dec10_prep_move_m(DisasContext *dc, int s_ext, int memsize, if (memsize != 4) { if (s_ext) { if (memsize == 1) - imm = ldsb_code(dc->pc + 2); + imm = cpu_ldsb_code(env, dc->pc + 2); else - imm = ldsw_code(dc->pc + 2); + imm = cpu_ldsw_code(env, dc->pc + 2); } else { if (memsize == 1) - imm = ldub_code(dc->pc + 2); + imm = cpu_ldub_code(env, dc->pc + 2); else - imm = lduw_code(dc->pc + 2); + imm = cpu_lduw_code(env, dc->pc + 2); } } else - imm = ldl_code(dc->pc + 2); + imm = cpu_ldl_code(env, dc->pc + 2); tcg_gen_movi_tl(dst, imm); @@ -752,7 +752,8 @@ static unsigned int dec10_reg(DisasContext *dc) return insn_len; } -static unsigned int dec10_ind_move_m_r(DisasContext *dc, unsigned int size) +static unsigned int dec10_ind_move_m_r(CPUCRISState *env, DisasContext *dc, + unsigned int size) { unsigned int insn_len = 2; TCGv t; @@ -762,7 +763,7 @@ static unsigned int dec10_ind_move_m_r(DisasContext *dc, unsigned int size) cris_cc_mask(dc, CC_MASK_NZVC); t = tcg_temp_new(); - insn_len += dec10_prep_move_m(dc, 0, size, t); + insn_len += dec10_prep_move_m(env, dc, 0, size, t); cris_alu(dc, CC_OP_MOVE, cpu_R[dc->dst], cpu_R[dc->dst], t, size); if (dc->dst == 15) { tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]); @@ -789,7 +790,7 @@ static unsigned int dec10_ind_move_r_m(DisasContext *dc, unsigned int size) return insn_len; } -static unsigned int dec10_ind_move_m_pr(DisasContext *dc) +static unsigned int dec10_ind_move_m_pr(CPUCRISState *env, DisasContext *dc) { unsigned int insn_len = 2, rd = dc->dst; TCGv t, addr; @@ -799,7 +800,7 @@ static unsigned int dec10_ind_move_m_pr(DisasContext *dc) addr = tcg_temp_new(); t = tcg_temp_new(); - insn_len += dec10_prep_move_m(dc, 0, 4, t); + insn_len += dec10_prep_move_m(env, dc, 0, 4, t); if (rd == 15) { tcg_gen_mov_tl(env_btarget, t); cris_prepare_jmp(dc, JMP_INDIRECT); @@ -899,14 +900,15 @@ static void dec10_movem_m_r(DisasContext *dc) tcg_temp_free(t0); } -static int dec10_ind_alu(DisasContext *dc, int op, unsigned int size) +static int dec10_ind_alu(CPUCRISState *env, DisasContext *dc, + int op, unsigned int size) { int insn_len = 0; int rd = dc->dst; TCGv t[2]; cris_alu_m_alloc_temps(t); - insn_len += dec10_prep_move_m(dc, 0, size, t[0]); + insn_len += dec10_prep_move_m(env, dc, 0, size, t[0]); cris_alu(dc, op, cpu_R[dc->dst], cpu_R[rd], t[0], size); if (dc->dst == 15) { tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]); @@ -920,14 +922,15 @@ static int dec10_ind_alu(DisasContext *dc, int op, unsigned int size) return insn_len; } -static int dec10_ind_bound(DisasContext *dc, unsigned int size) +static int dec10_ind_bound(CPUCRISState *env, DisasContext *dc, + unsigned int size) { int insn_len = 0; int rd = dc->dst; TCGv t; t = tcg_temp_local_new(); - insn_len += dec10_prep_move_m(dc, 0, size, t); + insn_len += dec10_prep_move_m(env, dc, 0, size, t); cris_alu(dc, CC_OP_BOUND, cpu_R[dc->dst], cpu_R[rd], t, 4); if (dc->dst == 15) { tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]); @@ -940,7 +943,7 @@ static int dec10_ind_bound(DisasContext *dc, unsigned int size) return insn_len; } -static int dec10_alux_m(DisasContext *dc, int op) +static int dec10_alux_m(CPUCRISState *env, DisasContext *dc, int op) { unsigned int size = (dc->size & 1) ? 2 : 1; unsigned int sx = !!(dc->size & 2); @@ -953,7 +956,7 @@ static int dec10_alux_m(DisasContext *dc, int op) t = tcg_temp_new(); cris_cc_mask(dc, CC_MASK_NZVC); - insn_len += dec10_prep_move_m(dc, sx, size, t); + insn_len += dec10_prep_move_m(env, dc, sx, size, t); cris_alu(dc, op, cpu_R[dc->dst], cpu_R[rd], t, 4); if (dc->dst == 15) { tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]); @@ -966,7 +969,7 @@ static int dec10_alux_m(DisasContext *dc, int op) return insn_len; } -static int dec10_dip(DisasContext *dc) +static int dec10_dip(CPUCRISState *env, DisasContext *dc) { int insn_len = 2; uint32_t imm; @@ -974,7 +977,7 @@ static int dec10_dip(DisasContext *dc) LOG_DIS("dip pc=%x opcode=%d r%d r%d\n", dc->pc, dc->opcode, dc->src, dc->dst); if (dc->src == 15) { - imm = ldl_code(dc->pc + 2); + imm = cpu_ldl_code(env, dc->pc + 2); tcg_gen_movi_tl(cpu_PR[PR_PREFIX], imm); if (dc->postinc) insn_len += 4; @@ -989,7 +992,7 @@ static int dec10_dip(DisasContext *dc) return insn_len; } -static int dec10_bdap_m(DisasContext *dc, int size) +static int dec10_bdap_m(CPUCRISState *env, DisasContext *dc, int size) { int insn_len = 2; int rd = dc->dst; @@ -1014,13 +1017,13 @@ static int dec10_bdap_m(DisasContext *dc, int size) } #endif /* Now the rest of the modes are truly indirect. */ - insn_len += dec10_prep_move_m(dc, 1, size, cpu_PR[PR_PREFIX]); + insn_len += dec10_prep_move_m(env, dc, 1, size, cpu_PR[PR_PREFIX]); tcg_gen_add_tl(cpu_PR[PR_PREFIX], cpu_PR[PR_PREFIX], cpu_R[rd]); cris_set_prefix(dc); return insn_len; } -static unsigned int dec10_ind(DisasContext *dc) +static unsigned int dec10_ind(CPUCRISState *env, DisasContext *dc) { unsigned int insn_len = 2; unsigned int size = dec10_size(dc->size); @@ -1031,7 +1034,7 @@ static unsigned int dec10_ind(DisasContext *dc) if (dc->size != 3) { switch (dc->opcode) { case CRISV10_IND_MOVE_M_R: - return dec10_ind_move_m_r(dc, size); + return dec10_ind_move_m_r(env, dc, size); break; case CRISV10_IND_MOVE_R_M: return dec10_ind_move_r_m(dc, size); @@ -1039,7 +1042,7 @@ static unsigned int dec10_ind(DisasContext *dc) case CRISV10_IND_CMP: LOG_DIS("cmp size=%d op=%d %d\n", size, dc->src, dc->dst); cris_cc_mask(dc, CC_MASK_NZVC); - insn_len += dec10_ind_alu(dc, CC_OP_CMP, size); + insn_len += dec10_ind_alu(env, dc, CC_OP_CMP, size); break; case CRISV10_IND_TEST: LOG_DIS("test size=%d op=%d %d\n", size, dc->src, dc->dst); @@ -1047,7 +1050,7 @@ static unsigned int dec10_ind(DisasContext *dc) cris_evaluate_flags(dc); cris_cc_mask(dc, CC_MASK_NZVC); cris_alu_m_alloc_temps(t); - insn_len += dec10_prep_move_m(dc, 0, size, t[0]); + insn_len += dec10_prep_move_m(env, dc, 0, size, t[0]); tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3); cris_alu(dc, CC_OP_CMP, cpu_R[dc->dst], t[0], tcg_const_tl(0), size); @@ -1056,39 +1059,39 @@ static unsigned int dec10_ind(DisasContext *dc) case CRISV10_IND_ADD: LOG_DIS("add size=%d op=%d %d\n", size, dc->src, dc->dst); cris_cc_mask(dc, CC_MASK_NZVC); - insn_len += dec10_ind_alu(dc, CC_OP_ADD, size); + insn_len += dec10_ind_alu(env, dc, CC_OP_ADD, size); break; case CRISV10_IND_SUB: LOG_DIS("sub size=%d op=%d %d\n", size, dc->src, dc->dst); cris_cc_mask(dc, CC_MASK_NZVC); - insn_len += dec10_ind_alu(dc, CC_OP_SUB, size); + insn_len += dec10_ind_alu(env, dc, CC_OP_SUB, size); break; case CRISV10_IND_BOUND: LOG_DIS("bound size=%d op=%d %d\n", size, dc->src, dc->dst); cris_cc_mask(dc, CC_MASK_NZVC); - insn_len += dec10_ind_bound(dc, size); + insn_len += dec10_ind_bound(env, dc, size); break; case CRISV10_IND_AND: LOG_DIS("and size=%d op=%d %d\n", size, dc->src, dc->dst); cris_cc_mask(dc, CC_MASK_NZVC); - insn_len += dec10_ind_alu(dc, CC_OP_AND, size); + insn_len += dec10_ind_alu(env, dc, CC_OP_AND, size); break; case CRISV10_IND_OR: LOG_DIS("or size=%d op=%d %d\n", size, dc->src, dc->dst); cris_cc_mask(dc, CC_MASK_NZVC); - insn_len += dec10_ind_alu(dc, CC_OP_OR, size); + insn_len += dec10_ind_alu(env, dc, CC_OP_OR, size); break; case CRISV10_IND_MOVX: - insn_len = dec10_alux_m(dc, CC_OP_MOVE); + insn_len = dec10_alux_m(env, dc, CC_OP_MOVE); break; case CRISV10_IND_ADDX: - insn_len = dec10_alux_m(dc, CC_OP_ADD); + insn_len = dec10_alux_m(env, dc, CC_OP_ADD); break; case CRISV10_IND_SUBX: - insn_len = dec10_alux_m(dc, CC_OP_SUB); + insn_len = dec10_alux_m(env, dc, CC_OP_SUB); break; case CRISV10_IND_CMPX: - insn_len = dec10_alux_m(dc, CC_OP_CMP); + insn_len = dec10_alux_m(env, dc, CC_OP_CMP); break; case CRISV10_IND_MUL: /* This is a reg insn coded in the mem indir space. */ @@ -1097,7 +1100,7 @@ static unsigned int dec10_ind(DisasContext *dc) dec10_reg_mul(dc, size, dc->ir & (1 << 10)); break; case CRISV10_IND_BDAP_M: - insn_len = dec10_bdap_m(dc, size); + insn_len = dec10_bdap_m(env, dc, size); break; default: LOG_DIS("pc=%x var-ind.%d %d r%d r%d\n", @@ -1110,7 +1113,7 @@ static unsigned int dec10_ind(DisasContext *dc) switch (dc->opcode) { case CRISV10_IND_MOVE_M_SPR: - insn_len = dec10_ind_move_m_pr(dc); + insn_len = dec10_ind_move_m_pr(env, dc); break; case CRISV10_IND_MOVE_SPR_M: insn_len = dec10_ind_move_pr_m(dc); @@ -1119,7 +1122,7 @@ static unsigned int dec10_ind(DisasContext *dc) if (dc->src == 15) { LOG_DIS("jump.%d %d r%d r%d direct\n", size, dc->opcode, dc->src, dc->dst); - imm = ldl_code(dc->pc + 2); + imm = cpu_ldl_code(env, dc->pc + 2); if (dc->mode == CRISV10_MODE_AUTOINC) insn_len += size; @@ -1168,24 +1171,24 @@ static unsigned int dec10_ind(DisasContext *dc) dc->delayed_branch--; /* v10 has no dslot here. */ break; case CRISV10_IND_MOVX: - insn_len = dec10_alux_m(dc, CC_OP_MOVE); + insn_len = dec10_alux_m(env, dc, CC_OP_MOVE); break; case CRISV10_IND_ADDX: - insn_len = dec10_alux_m(dc, CC_OP_ADD); + insn_len = dec10_alux_m(env, dc, CC_OP_ADD); break; case CRISV10_IND_SUBX: - insn_len = dec10_alux_m(dc, CC_OP_SUB); + insn_len = dec10_alux_m(env, dc, CC_OP_SUB); break; case CRISV10_IND_CMPX: - insn_len = dec10_alux_m(dc, CC_OP_CMP); + insn_len = dec10_alux_m(env, dc, CC_OP_CMP); break; case CRISV10_IND_DIP: - insn_len = dec10_dip(dc); + insn_len = dec10_dip(env, dc); break; case CRISV10_IND_BCC_M: cris_cc_mask(dc, 0); - imm = ldsw_code(dc->pc + 2); + imm = cpu_ldsw_code(env, dc->pc + 2); simm = (int16_t)imm; simm += 4; @@ -1202,7 +1205,7 @@ static unsigned int dec10_ind(DisasContext *dc) return insn_len; } -static unsigned int crisv10_decoder(DisasContext *dc) +static unsigned int crisv10_decoder(CPUCRISState *env, DisasContext *dc) { unsigned int insn_len = 2; @@ -1210,7 +1213,7 @@ static unsigned int crisv10_decoder(DisasContext *dc) tcg_gen_debug_insn_start(dc->pc); /* Load a halfword onto the instruction register. */ - dc->ir = lduw_code(dc->pc); + dc->ir = cpu_lduw_code(env, dc->pc); /* Now decode it. */ dc->opcode = EXTRACT_FIELD(dc->ir, 6, 9); @@ -1235,7 +1238,7 @@ static unsigned int crisv10_decoder(DisasContext *dc) break; case CRISV10_MODE_AUTOINC: case CRISV10_MODE_INDIRECT: - insn_len = dec10_ind(dc); + insn_len = dec10_ind(env, dc); break; } From 485d003539b96c33b9f9f7c627d1071524ecc6a7 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 10:37:06 +0000 Subject: [PATCH 0401/2270] target-sh4: switch to AREG0 free mode Add an explicit CPUState parameter instead of relying on AREG0 and switch to AREG0 free mode. Acked-by: Aurelien Jarno Signed-off-by: Blue Swirl --- configure | 2 +- target-sh4/Makefile.objs | 2 - target-sh4/helper.h | 84 +++++++++--------- target-sh4/op_helper.c | 182 +++++++++++++++++++-------------------- target-sh4/translate.c | 114 +++++++++++++----------- 5 files changed, 195 insertions(+), 189 deletions(-) diff --git a/configure b/configure index 9698e6dbe6..4ac9904ac9 100755 --- a/configure +++ b/configure @@ -3874,7 +3874,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile" case "$target_arch2" in - alpha | arm* | cris | i386 | lm32 | m68k | microblaze* | or32 | s390x | sparc* | unicore32 | x86_64 | xtensa* | ppc*) + alpha | arm* | cris | i386 | lm32 | m68k | microblaze* | or32 | s390x | sh4* | sparc* | unicore32 | x86_64 | xtensa* | ppc*) echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak ;; esac diff --git a/target-sh4/Makefile.objs b/target-sh4/Makefile.objs index 2e0e093e1f..ca20f21443 100644 --- a/target-sh4/Makefile.objs +++ b/target-sh4/Makefile.objs @@ -1,4 +1,2 @@ obj-y += translate.o op_helper.o helper.o cpu.o obj-$(CONFIG_SOFTMMU) += machine.o - -$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-sh4/helper.h b/target-sh4/helper.h index 95e3c7c8f7..6e4f108124 100644 --- a/target-sh4/helper.h +++ b/target-sh4/helper.h @@ -1,54 +1,54 @@ #include "def-helper.h" -DEF_HELPER_0(ldtlb, void) -DEF_HELPER_0(raise_illegal_instruction, void) -DEF_HELPER_0(raise_slot_illegal_instruction, void) -DEF_HELPER_0(raise_fpu_disable, void) -DEF_HELPER_0(raise_slot_fpu_disable, void) -DEF_HELPER_0(debug, void) -DEF_HELPER_1(sleep, void, i32) -DEF_HELPER_1(trapa, void, i32) +DEF_HELPER_1(ldtlb, void, env) +DEF_HELPER_1(raise_illegal_instruction, void, env) +DEF_HELPER_1(raise_slot_illegal_instruction, void, env) +DEF_HELPER_1(raise_fpu_disable, void, env) +DEF_HELPER_1(raise_slot_fpu_disable, void, env) +DEF_HELPER_1(debug, void, env) +DEF_HELPER_2(sleep, void, env, i32) +DEF_HELPER_2(trapa, void, env, i32) -DEF_HELPER_2(movcal, void, i32, i32) -DEF_HELPER_0(discard_movcal_backup, void) -DEF_HELPER_1(ocbi, void, i32) +DEF_HELPER_3(movcal, void, env, i32, i32) +DEF_HELPER_1(discard_movcal_backup, void, env) +DEF_HELPER_2(ocbi, void, env, i32) -DEF_HELPER_2(addv, i32, i32, i32) -DEF_HELPER_2(addc, i32, i32, i32) -DEF_HELPER_2(subv, i32, i32, i32) -DEF_HELPER_2(subc, i32, i32, i32) -DEF_HELPER_2(div1, i32, i32, i32) -DEF_HELPER_2(macl, void, i32, i32) -DEF_HELPER_2(macw, void, i32, i32) +DEF_HELPER_3(addv, i32, env, i32, i32) +DEF_HELPER_3(addc, i32, env, i32, i32) +DEF_HELPER_3(subv, i32, env, i32, i32) +DEF_HELPER_3(subc, i32, env, i32, i32) +DEF_HELPER_3(div1, i32, env, i32, i32) +DEF_HELPER_3(macl, void, env, i32, i32) +DEF_HELPER_3(macw, void, env, i32, i32) -DEF_HELPER_1(ld_fpscr, void, i32) +DEF_HELPER_2(ld_fpscr, void, env, i32) DEF_HELPER_1(fabs_FT, f32, f32) DEF_HELPER_1(fabs_DT, f64, f64) -DEF_HELPER_2(fadd_FT, f32, f32, f32) -DEF_HELPER_2(fadd_DT, f64, f64, f64) -DEF_HELPER_1(fcnvsd_FT_DT, f64, f32) -DEF_HELPER_1(fcnvds_DT_FT, f32, f64) +DEF_HELPER_3(fadd_FT, f32, env, f32, f32) +DEF_HELPER_3(fadd_DT, f64, env, f64, f64) +DEF_HELPER_2(fcnvsd_FT_DT, f64, env, f32) +DEF_HELPER_2(fcnvds_DT_FT, f32, env, f64) -DEF_HELPER_2(fcmp_eq_FT, void, f32, f32) -DEF_HELPER_2(fcmp_eq_DT, void, f64, f64) -DEF_HELPER_2(fcmp_gt_FT, void, f32, f32) -DEF_HELPER_2(fcmp_gt_DT, void, f64, f64) -DEF_HELPER_2(fdiv_FT, f32, f32, f32) -DEF_HELPER_2(fdiv_DT, f64, f64, f64) -DEF_HELPER_1(float_FT, f32, i32) -DEF_HELPER_1(float_DT, f64, i32) -DEF_HELPER_3(fmac_FT, f32, f32, f32, f32) -DEF_HELPER_2(fmul_FT, f32, f32, f32) -DEF_HELPER_2(fmul_DT, f64, f64, f64) +DEF_HELPER_3(fcmp_eq_FT, void, env, f32, f32) +DEF_HELPER_3(fcmp_eq_DT, void, env, f64, f64) +DEF_HELPER_3(fcmp_gt_FT, void, env, f32, f32) +DEF_HELPER_3(fcmp_gt_DT, void, env, f64, f64) +DEF_HELPER_3(fdiv_FT, f32, env, f32, f32) +DEF_HELPER_3(fdiv_DT, f64, env, f64, f64) +DEF_HELPER_2(float_FT, f32, env, i32) +DEF_HELPER_2(float_DT, f64, env, i32) +DEF_HELPER_4(fmac_FT, f32, env, f32, f32, f32) +DEF_HELPER_3(fmul_FT, f32, env, f32, f32) +DEF_HELPER_3(fmul_DT, f64, env, f64, f64) DEF_HELPER_1(fneg_T, f32, f32) -DEF_HELPER_2(fsub_FT, f32, f32, f32) -DEF_HELPER_2(fsub_DT, f64, f64, f64) -DEF_HELPER_1(fsqrt_FT, f32, f32) -DEF_HELPER_1(fsqrt_DT, f64, f64) -DEF_HELPER_1(ftrc_FT, i32, f32) -DEF_HELPER_1(ftrc_DT, i32, f64) -DEF_HELPER_2(fipr, void, i32, i32) -DEF_HELPER_1(ftrv, void, i32) +DEF_HELPER_3(fsub_FT, f32, env, f32, f32) +DEF_HELPER_3(fsub_DT, f64, env, f64, f64) +DEF_HELPER_2(fsqrt_FT, f32, env, f32) +DEF_HELPER_2(fsqrt_DT, f64, env, f64) +DEF_HELPER_2(ftrc_FT, i32, env, f32) +DEF_HELPER_2(ftrc_DT, i32, env, f64) +DEF_HELPER_3(fipr, void, env, i32, i32) +DEF_HELPER_2(ftrv, void, env, i32) #include "def-helper.h" diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c index 40547911cd..9b4328de37 100644 --- a/target-sh4/op_helper.c +++ b/target-sh4/op_helper.c @@ -19,10 +19,9 @@ #include #include #include "cpu.h" -#include "dyngen-exec.h" #include "helper.h" -static void cpu_restore_state_from_retaddr(uintptr_t retaddr) +static void cpu_restore_state_from_retaddr(CPUSH4State *env, uintptr_t retaddr) { TranslationBlock *tb; @@ -53,26 +52,22 @@ static void cpu_restore_state_from_retaddr(uintptr_t retaddr) #define SHIFT 3 #include "softmmu_template.h" -void tlb_fill(CPUSH4State *env1, target_ulong addr, int is_write, int mmu_idx, +void tlb_fill(CPUSH4State *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { - CPUSH4State *saved_env; int ret; - saved_env = env; - env = env1; ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx); if (ret) { /* now we have a real cpu fault */ - cpu_restore_state_from_retaddr(retaddr); + cpu_restore_state_from_retaddr(env, retaddr); cpu_loop_exit(env); } - env = saved_env; } #endif -void helper_ldtlb(void) +void helper_ldtlb(CPUSH4State *env) { #ifdef CONFIG_USER_ONLY /* XXXXX */ @@ -82,40 +77,41 @@ void helper_ldtlb(void) #endif } -static inline void raise_exception(int index, uintptr_t retaddr) +static inline void raise_exception(CPUSH4State *env, int index, + uintptr_t retaddr) { env->exception_index = index; - cpu_restore_state_from_retaddr(retaddr); + cpu_restore_state_from_retaddr(env, retaddr); cpu_loop_exit(env); } -void helper_raise_illegal_instruction(void) +void helper_raise_illegal_instruction(CPUSH4State *env) { - raise_exception(0x180, GETPC()); + raise_exception(env, 0x180, GETPC()); } -void helper_raise_slot_illegal_instruction(void) +void helper_raise_slot_illegal_instruction(CPUSH4State *env) { - raise_exception(0x1a0, GETPC()); + raise_exception(env, 0x1a0, GETPC()); } -void helper_raise_fpu_disable(void) +void helper_raise_fpu_disable(CPUSH4State *env) { - raise_exception(0x800, GETPC()); + raise_exception(env, 0x800, GETPC()); } -void helper_raise_slot_fpu_disable(void) +void helper_raise_slot_fpu_disable(CPUSH4State *env) { - raise_exception(0x820, GETPC()); + raise_exception(env, 0x820, GETPC()); } -void helper_debug(void) +void helper_debug(CPUSH4State *env) { env->exception_index = EXCP_DEBUG; cpu_loop_exit(env); } -void helper_sleep(uint32_t next_pc) +void helper_sleep(CPUSH4State *env, uint32_t next_pc) { env->halted = 1; env->in_sleep = 1; @@ -124,13 +120,13 @@ void helper_sleep(uint32_t next_pc) cpu_loop_exit(env); } -void helper_trapa(uint32_t tra) +void helper_trapa(CPUSH4State *env, uint32_t tra) { env->tra = tra << 2; - raise_exception(0x160, GETPC()); + raise_exception(env, 0x160, GETPC()); } -void helper_movcal(uint32_t address, uint32_t value) +void helper_movcal(CPUSH4State *env, uint32_t address, uint32_t value) { if (cpu_sh4_is_cached (env, address)) { @@ -144,7 +140,7 @@ void helper_movcal(uint32_t address, uint32_t value) } } -void helper_discard_movcal_backup(void) +void helper_discard_movcal_backup(CPUSH4State *env) { memory_content *current = env->movcal_backup; @@ -158,7 +154,7 @@ void helper_discard_movcal_backup(void) } } -void helper_ocbi(uint32_t address) +void helper_ocbi(CPUSH4State *env, uint32_t address) { memory_content **current = &(env->movcal_backup); while (*current) @@ -167,7 +163,7 @@ void helper_ocbi(uint32_t address) if ((a & ~0x1F) == (address & ~0x1F)) { memory_content *next = (*current)->next; - stl(a, (*current)->value); + cpu_stl_data(env, a, (*current)->value); if (next == NULL) { @@ -181,7 +177,7 @@ void helper_ocbi(uint32_t address) } } -uint32_t helper_addc(uint32_t arg0, uint32_t arg1) +uint32_t helper_addc(CPUSH4State *env, uint32_t arg0, uint32_t arg1) { uint32_t tmp0, tmp1; @@ -197,7 +193,7 @@ uint32_t helper_addc(uint32_t arg0, uint32_t arg1) return arg1; } -uint32_t helper_addv(uint32_t arg0, uint32_t arg1) +uint32_t helper_addv(CPUSH4State *env, uint32_t arg0, uint32_t arg1) { uint32_t dest, src, ans; @@ -236,7 +232,7 @@ uint32_t helper_addv(uint32_t arg0, uint32_t arg1) #define SETM env->sr |= SR_M #define CLRM env->sr &= ~SR_M -uint32_t helper_div1(uint32_t arg0, uint32_t arg1) +uint32_t helper_div1(CPUSH4State *env, uint32_t arg0, uint32_t arg1) { uint32_t tmp0, tmp2; uint8_t old_q, tmp1 = 0xff; @@ -344,7 +340,7 @@ uint32_t helper_div1(uint32_t arg0, uint32_t arg1) return arg1; } -void helper_macl(uint32_t arg0, uint32_t arg1) +void helper_macl(CPUSH4State *env, uint32_t arg0, uint32_t arg1) { int64_t res; @@ -360,7 +356,7 @@ void helper_macl(uint32_t arg0, uint32_t arg1) } } -void helper_macw(uint32_t arg0, uint32_t arg1) +void helper_macw(CPUSH4State *env, uint32_t arg0, uint32_t arg1) { int64_t res; @@ -379,7 +375,7 @@ void helper_macw(uint32_t arg0, uint32_t arg1) } } -uint32_t helper_subc(uint32_t arg0, uint32_t arg1) +uint32_t helper_subc(CPUSH4State *env, uint32_t arg0, uint32_t arg1) { uint32_t tmp0, tmp1; @@ -395,7 +391,7 @@ uint32_t helper_subc(uint32_t arg0, uint32_t arg1) return arg1; } -uint32_t helper_subv(uint32_t arg0, uint32_t arg1) +uint32_t helper_subv(CPUSH4State *env, uint32_t arg0, uint32_t arg1) { int32_t dest, src, ans; @@ -424,17 +420,17 @@ uint32_t helper_subv(uint32_t arg0, uint32_t arg1) return arg1; } -static inline void set_t(void) +static inline void set_t(CPUSH4State *env) { env->sr |= SR_T; } -static inline void clr_t(void) +static inline void clr_t(CPUSH4State *env) { env->sr &= ~SR_T; } -void helper_ld_fpscr(uint32_t val) +void helper_ld_fpscr(CPUSH4State *env, uint32_t val) { env->fpscr = val & FPSCR_MASK; if ((val & FPSCR_RM_MASK) == FPSCR_RM_ZERO) { @@ -445,7 +441,7 @@ void helper_ld_fpscr(uint32_t val) set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status); } -static void update_fpscr(uintptr_t retaddr) +static void update_fpscr(CPUSH4State *env, uintptr_t retaddr) { int xcpt, cause, enable; @@ -479,7 +475,7 @@ static void update_fpscr(uintptr_t retaddr) cause = (env->fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT; enable = (env->fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT; if (cause & enable) { - cpu_restore_state_from_retaddr(retaddr); + cpu_restore_state_from_retaddr(env, retaddr); env->exception_index = 0x120; cpu_loop_exit(env); } @@ -496,156 +492,156 @@ float64 helper_fabs_DT(float64 t0) return float64_abs(t0); } -float32 helper_fadd_FT(float32 t0, float32 t1) +float32 helper_fadd_FT(CPUSH4State *env, float32 t0, float32 t1) { set_float_exception_flags(0, &env->fp_status); t0 = float32_add(t0, t1, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return t0; } -float64 helper_fadd_DT(float64 t0, float64 t1) +float64 helper_fadd_DT(CPUSH4State *env, float64 t0, float64 t1) { set_float_exception_flags(0, &env->fp_status); t0 = float64_add(t0, t1, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return t0; } -void helper_fcmp_eq_FT(float32 t0, float32 t1) +void helper_fcmp_eq_FT(CPUSH4State *env, float32 t0, float32 t1) { int relation; set_float_exception_flags(0, &env->fp_status); relation = float32_compare(t0, t1, &env->fp_status); if (unlikely(relation == float_relation_unordered)) { - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); } else if (relation == float_relation_equal) { - set_t(); + set_t(env); } else { - clr_t(); + clr_t(env); } } -void helper_fcmp_eq_DT(float64 t0, float64 t1) +void helper_fcmp_eq_DT(CPUSH4State *env, float64 t0, float64 t1) { int relation; set_float_exception_flags(0, &env->fp_status); relation = float64_compare(t0, t1, &env->fp_status); if (unlikely(relation == float_relation_unordered)) { - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); } else if (relation == float_relation_equal) { - set_t(); + set_t(env); } else { - clr_t(); + clr_t(env); } } -void helper_fcmp_gt_FT(float32 t0, float32 t1) +void helper_fcmp_gt_FT(CPUSH4State *env, float32 t0, float32 t1) { int relation; set_float_exception_flags(0, &env->fp_status); relation = float32_compare(t0, t1, &env->fp_status); if (unlikely(relation == float_relation_unordered)) { - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); } else if (relation == float_relation_greater) { - set_t(); + set_t(env); } else { - clr_t(); + clr_t(env); } } -void helper_fcmp_gt_DT(float64 t0, float64 t1) +void helper_fcmp_gt_DT(CPUSH4State *env, float64 t0, float64 t1) { int relation; set_float_exception_flags(0, &env->fp_status); relation = float64_compare(t0, t1, &env->fp_status); if (unlikely(relation == float_relation_unordered)) { - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); } else if (relation == float_relation_greater) { - set_t(); + set_t(env); } else { - clr_t(); + clr_t(env); } } -float64 helper_fcnvsd_FT_DT(float32 t0) +float64 helper_fcnvsd_FT_DT(CPUSH4State *env, float32 t0) { float64 ret; set_float_exception_flags(0, &env->fp_status); ret = float32_to_float64(t0, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return ret; } -float32 helper_fcnvds_DT_FT(float64 t0) +float32 helper_fcnvds_DT_FT(CPUSH4State *env, float64 t0) { float32 ret; set_float_exception_flags(0, &env->fp_status); ret = float64_to_float32(t0, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return ret; } -float32 helper_fdiv_FT(float32 t0, float32 t1) +float32 helper_fdiv_FT(CPUSH4State *env, float32 t0, float32 t1) { set_float_exception_flags(0, &env->fp_status); t0 = float32_div(t0, t1, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return t0; } -float64 helper_fdiv_DT(float64 t0, float64 t1) +float64 helper_fdiv_DT(CPUSH4State *env, float64 t0, float64 t1) { set_float_exception_flags(0, &env->fp_status); t0 = float64_div(t0, t1, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return t0; } -float32 helper_float_FT(uint32_t t0) +float32 helper_float_FT(CPUSH4State *env, uint32_t t0) { float32 ret; set_float_exception_flags(0, &env->fp_status); ret = int32_to_float32(t0, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return ret; } -float64 helper_float_DT(uint32_t t0) +float64 helper_float_DT(CPUSH4State *env, uint32_t t0) { float64 ret; set_float_exception_flags(0, &env->fp_status); ret = int32_to_float64(t0, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return ret; } -float32 helper_fmac_FT(float32 t0, float32 t1, float32 t2) +float32 helper_fmac_FT(CPUSH4State *env, float32 t0, float32 t1, float32 t2) { set_float_exception_flags(0, &env->fp_status); t0 = float32_mul(t0, t1, &env->fp_status); t0 = float32_add(t0, t2, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return t0; } -float32 helper_fmul_FT(float32 t0, float32 t1) +float32 helper_fmul_FT(CPUSH4State *env, float32 t0, float32 t1) { set_float_exception_flags(0, &env->fp_status); t0 = float32_mul(t0, t1, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return t0; } -float64 helper_fmul_DT(float64 t0, float64 t1) +float64 helper_fmul_DT(CPUSH4State *env, float64 t0, float64 t1) { set_float_exception_flags(0, &env->fp_status); t0 = float64_mul(t0, t1, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return t0; } @@ -654,57 +650,57 @@ float32 helper_fneg_T(float32 t0) return float32_chs(t0); } -float32 helper_fsqrt_FT(float32 t0) +float32 helper_fsqrt_FT(CPUSH4State *env, float32 t0) { set_float_exception_flags(0, &env->fp_status); t0 = float32_sqrt(t0, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return t0; } -float64 helper_fsqrt_DT(float64 t0) +float64 helper_fsqrt_DT(CPUSH4State *env, float64 t0) { set_float_exception_flags(0, &env->fp_status); t0 = float64_sqrt(t0, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return t0; } -float32 helper_fsub_FT(float32 t0, float32 t1) +float32 helper_fsub_FT(CPUSH4State *env, float32 t0, float32 t1) { set_float_exception_flags(0, &env->fp_status); t0 = float32_sub(t0, t1, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return t0; } -float64 helper_fsub_DT(float64 t0, float64 t1) +float64 helper_fsub_DT(CPUSH4State *env, float64 t0, float64 t1) { set_float_exception_flags(0, &env->fp_status); t0 = float64_sub(t0, t1, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return t0; } -uint32_t helper_ftrc_FT(float32 t0) +uint32_t helper_ftrc_FT(CPUSH4State *env, float32 t0) { uint32_t ret; set_float_exception_flags(0, &env->fp_status); ret = float32_to_int32_round_to_zero(t0, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return ret; } -uint32_t helper_ftrc_DT(float64 t0) +uint32_t helper_ftrc_DT(CPUSH4State *env, float64 t0) { uint32_t ret; set_float_exception_flags(0, &env->fp_status); ret = float64_to_int32_round_to_zero(t0, &env->fp_status); - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); return ret; } -void helper_fipr(uint32_t m, uint32_t n) +void helper_fipr(CPUSH4State *env, uint32_t m, uint32_t n) { int bank, i; float32 r, p; @@ -719,12 +715,12 @@ void helper_fipr(uint32_t m, uint32_t n) &env->fp_status); r = float32_add(r, p, &env->fp_status); } - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); env->fregs[bank + n + 3] = r; } -void helper_ftrv(uint32_t n) +void helper_ftrv(CPUSH4State *env, uint32_t n) { int bank_matrix, bank_vector; int i, j; @@ -743,7 +739,7 @@ void helper_ftrv(uint32_t n) r[i] = float32_add(r[i], p, &env->fp_status); } } - update_fpscr(GETPC()); + update_fpscr(env, GETPC()); for (i = 0 ; i < 4 ; i++) { env->fregs[bank_vector + i] = r[i]; diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 6532ad2ade..d05c74c8c3 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -276,7 +276,7 @@ static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest) } else { tcg_gen_movi_i32(cpu_pc, dest); if (ctx->singlestep_enabled) - gen_helper_debug(); + gen_helper_debug(cpu_env); tcg_gen_exit_tb(0); } } @@ -288,7 +288,7 @@ static void gen_jump(DisasContext * ctx) delayed jump as immediate jump are conditinal jumps */ tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc); if (ctx->singlestep_enabled) - gen_helper_debug(); + gen_helper_debug(cpu_env); tcg_gen_exit_tb(0); } else { gen_goto_tb(ctx, 0, ctx->delayed_pc); @@ -437,7 +437,7 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg) #define CHECK_NOT_DELAY_SLOT \ if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \ { \ - gen_helper_raise_slot_illegal_instruction(); \ + gen_helper_raise_slot_illegal_instruction(cpu_env); \ ctx->bstate = BS_EXCP; \ return; \ } @@ -445,9 +445,9 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg) #define CHECK_PRIVILEGED \ if (IS_USER(ctx)) { \ if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \ - gen_helper_raise_slot_illegal_instruction(); \ + gen_helper_raise_slot_illegal_instruction(cpu_env); \ } else { \ - gen_helper_raise_illegal_instruction(); \ + gen_helper_raise_illegal_instruction(cpu_env); \ } \ ctx->bstate = BS_EXCP; \ return; \ @@ -456,9 +456,9 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg) #define CHECK_FPU_ENABLED \ if (ctx->flags & SR_FD) { \ if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \ - gen_helper_raise_slot_fpu_disable(); \ + gen_helper_raise_slot_fpu_disable(cpu_env); \ } else { \ - gen_helper_raise_fpu_disable(); \ + gen_helper_raise_fpu_disable(cpu_env); \ } \ ctx->bstate = BS_EXCP; \ return; \ @@ -492,7 +492,7 @@ static void _decode_opc(DisasContext * ctx) if (opcode != 0x0093 /* ocbi */ && opcode != 0x00c3 /* movca.l */) { - gen_helper_discard_movcal_backup (); + gen_helper_discard_movcal_backup(cpu_env); ctx->has_movcal = 0; } } @@ -523,7 +523,7 @@ static void _decode_opc(DisasContext * ctx) return; case 0x0038: /* ldtlb */ CHECK_PRIVILEGED - gen_helper_ldtlb(); + gen_helper_ldtlb(cpu_env); return; case 0x002b: /* rte */ CHECK_PRIVILEGED @@ -551,7 +551,7 @@ static void _decode_opc(DisasContext * ctx) return; case 0x001b: /* sleep */ CHECK_PRIVILEGED - gen_helper_sleep(tcg_const_i32(ctx->pc + 2)); + gen_helper_sleep(cpu_env, tcg_const_i32(ctx->pc + 2)); return; } @@ -761,10 +761,10 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4)); return; case 0x300e: /* addc Rm,Rn */ - gen_helper_addc(REG(B11_8), REG(B7_4), REG(B11_8)); + gen_helper_addc(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8)); return; case 0x300f: /* addv Rm,Rn */ - gen_helper_addv(REG(B11_8), REG(B7_4), REG(B11_8)); + gen_helper_addv(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8)); return; case 0x2009: /* and Rm,Rn */ tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4)); @@ -817,7 +817,7 @@ static void _decode_opc(DisasContext * ctx) } return; case 0x3004: /* div1 Rm,Rn */ - gen_helper_div1(REG(B11_8), REG(B7_4), REG(B11_8)); + gen_helper_div1(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8)); return; case 0x300d: /* dmuls.l Rm,Rn */ { @@ -870,7 +870,7 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_qemu_ld32s(arg0, REG(B7_4), ctx->memidx); arg1 = tcg_temp_new(); tcg_gen_qemu_ld32s(arg1, REG(B11_8), ctx->memidx); - gen_helper_macl(arg0, arg1); + gen_helper_macl(cpu_env, arg0, arg1); tcg_temp_free(arg1); tcg_temp_free(arg0); tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); @@ -884,7 +884,7 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_qemu_ld32s(arg0, REG(B7_4), ctx->memidx); arg1 = tcg_temp_new(); tcg_gen_qemu_ld32s(arg1, REG(B11_8), ctx->memidx); - gen_helper_macw(arg0, arg1); + gen_helper_macw(cpu_env, arg0, arg1); tcg_temp_free(arg1); tcg_temp_free(arg0); tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2); @@ -1013,10 +1013,10 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4)); return; case 0x300a: /* subc Rm,Rn */ - gen_helper_subc(REG(B11_8), REG(B7_4), REG(B11_8)); + gen_helper_subc(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8)); return; case 0x300b: /* subv Rm,Rn */ - gen_helper_subv(REG(B11_8), REG(B7_4), REG(B11_8)); + gen_helper_subv(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8)); return; case 0x2008: /* tst Rm,Rn */ { @@ -1152,22 +1152,22 @@ static void _decode_opc(DisasContext * ctx) gen_load_fpr64(fp1, DREG(B7_4)); switch (ctx->opcode & 0xf00f) { case 0xf000: /* fadd Rm,Rn */ - gen_helper_fadd_DT(fp0, fp0, fp1); + gen_helper_fadd_DT(fp0, cpu_env, fp0, fp1); break; case 0xf001: /* fsub Rm,Rn */ - gen_helper_fsub_DT(fp0, fp0, fp1); + gen_helper_fsub_DT(fp0, cpu_env, fp0, fp1); break; case 0xf002: /* fmul Rm,Rn */ - gen_helper_fmul_DT(fp0, fp0, fp1); + gen_helper_fmul_DT(fp0, cpu_env, fp0, fp1); break; case 0xf003: /* fdiv Rm,Rn */ - gen_helper_fdiv_DT(fp0, fp0, fp1); + gen_helper_fdiv_DT(fp0, cpu_env, fp0, fp1); break; case 0xf004: /* fcmp/eq Rm,Rn */ - gen_helper_fcmp_eq_DT(fp0, fp1); + gen_helper_fcmp_eq_DT(cpu_env, fp0, fp1); return; case 0xf005: /* fcmp/gt Rm,Rn */ - gen_helper_fcmp_gt_DT(fp0, fp1); + gen_helper_fcmp_gt_DT(cpu_env, fp0, fp1); return; } gen_store_fpr64(fp0, DREG(B11_8)); @@ -1176,22 +1176,32 @@ static void _decode_opc(DisasContext * ctx) } else { switch (ctx->opcode & 0xf00f) { case 0xf000: /* fadd Rm,Rn */ - gen_helper_fadd_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B7_4)]); + gen_helper_fadd_FT(cpu_fregs[FREG(B11_8)], cpu_env, + cpu_fregs[FREG(B11_8)], + cpu_fregs[FREG(B7_4)]); break; case 0xf001: /* fsub Rm,Rn */ - gen_helper_fsub_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B7_4)]); + gen_helper_fsub_FT(cpu_fregs[FREG(B11_8)], cpu_env, + cpu_fregs[FREG(B11_8)], + cpu_fregs[FREG(B7_4)]); break; case 0xf002: /* fmul Rm,Rn */ - gen_helper_fmul_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B7_4)]); + gen_helper_fmul_FT(cpu_fregs[FREG(B11_8)], cpu_env, + cpu_fregs[FREG(B11_8)], + cpu_fregs[FREG(B7_4)]); break; case 0xf003: /* fdiv Rm,Rn */ - gen_helper_fdiv_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B7_4)]); + gen_helper_fdiv_FT(cpu_fregs[FREG(B11_8)], cpu_env, + cpu_fregs[FREG(B11_8)], + cpu_fregs[FREG(B7_4)]); break; case 0xf004: /* fcmp/eq Rm,Rn */ - gen_helper_fcmp_eq_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B7_4)]); + gen_helper_fcmp_eq_FT(cpu_env, cpu_fregs[FREG(B11_8)], + cpu_fregs[FREG(B7_4)]); return; case 0xf005: /* fcmp/gt Rm,Rn */ - gen_helper_fcmp_gt_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B7_4)]); + gen_helper_fcmp_gt_FT(cpu_env, cpu_fregs[FREG(B11_8)], + cpu_fregs[FREG(B7_4)]); return; } } @@ -1203,8 +1213,9 @@ static void _decode_opc(DisasContext * ctx) if (ctx->fpscr & FPSCR_PR) { break; /* illegal instruction */ } else { - gen_helper_fmac_FT(cpu_fregs[FREG(B11_8)], - cpu_fregs[FREG(0)], cpu_fregs[FREG(B7_4)], cpu_fregs[FREG(B11_8)]); + gen_helper_fmac_FT(cpu_fregs[FREG(B11_8)], cpu_env, + cpu_fregs[FREG(0)], cpu_fregs[FREG(B7_4)], + cpu_fregs[FREG(B11_8)]); return; } } @@ -1356,7 +1367,7 @@ static void _decode_opc(DisasContext * ctx) TCGv imm; CHECK_NOT_DELAY_SLOT imm = tcg_const_i32(B7_0); - gen_helper_trapa(imm); + gen_helper_trapa(cpu_env, imm); tcg_temp_free(imm); ctx->bstate = BS_BRANCH; } @@ -1531,7 +1542,7 @@ static void _decode_opc(DisasContext * ctx) LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED}) case 0x406a: /* lds Rm,FPSCR */ CHECK_FPU_ENABLED - gen_helper_ld_fpscr(REG(B11_8)); + gen_helper_ld_fpscr(cpu_env, REG(B11_8)); ctx->bstate = BS_STOP; return; case 0x4066: /* lds.l @Rm+,FPSCR */ @@ -1540,7 +1551,7 @@ static void _decode_opc(DisasContext * ctx) TCGv addr = tcg_temp_new(); tcg_gen_qemu_ld32s(addr, REG(B11_8), ctx->memidx); tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); - gen_helper_ld_fpscr(addr); + gen_helper_ld_fpscr(cpu_env, addr); tcg_temp_free(addr); ctx->bstate = BS_STOP; } @@ -1567,7 +1578,7 @@ static void _decode_opc(DisasContext * ctx) { TCGv val = tcg_temp_new(); tcg_gen_qemu_ld32u(val, REG(B11_8), ctx->memidx); - gen_helper_movcal (REG(B11_8), val); + gen_helper_movcal(cpu_env, REG(B11_8), val); tcg_gen_qemu_st32(REG(0), REG(B11_8), ctx->memidx); } ctx->has_movcal = 1; @@ -1619,7 +1630,7 @@ static void _decode_opc(DisasContext * ctx) break; case 0x0093: /* ocbi @Rn */ { - gen_helper_ocbi (REG(B11_8)); + gen_helper_ocbi(cpu_env, REG(B11_8)); } return; case 0x00a3: /* ocbp @Rn */ @@ -1733,12 +1744,12 @@ static void _decode_opc(DisasContext * ctx) if (ctx->opcode & 0x0100) break; /* illegal instruction */ fp = tcg_temp_new_i64(); - gen_helper_float_DT(fp, cpu_fpul); + gen_helper_float_DT(fp, cpu_env, cpu_fpul); gen_store_fpr64(fp, DREG(B11_8)); tcg_temp_free_i64(fp); } else { - gen_helper_float_FT(cpu_fregs[FREG(B11_8)], cpu_fpul); + gen_helper_float_FT(cpu_fregs[FREG(B11_8)], cpu_env, cpu_fpul); } return; case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ @@ -1749,11 +1760,11 @@ static void _decode_opc(DisasContext * ctx) break; /* illegal instruction */ fp = tcg_temp_new_i64(); gen_load_fpr64(fp, DREG(B11_8)); - gen_helper_ftrc_DT(cpu_fpul, fp); + gen_helper_ftrc_DT(cpu_fpul, cpu_env, fp); tcg_temp_free_i64(fp); } else { - gen_helper_ftrc_FT(cpu_fpul, cpu_fregs[FREG(B11_8)]); + gen_helper_ftrc_FT(cpu_fpul, cpu_env, cpu_fregs[FREG(B11_8)]); } return; case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */ @@ -1783,11 +1794,12 @@ static void _decode_opc(DisasContext * ctx) break; /* illegal instruction */ TCGv_i64 fp = tcg_temp_new_i64(); gen_load_fpr64(fp, DREG(B11_8)); - gen_helper_fsqrt_DT(fp, fp); + gen_helper_fsqrt_DT(fp, cpu_env, fp); gen_store_fpr64(fp, DREG(B11_8)); tcg_temp_free_i64(fp); } else { - gen_helper_fsqrt_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)]); + gen_helper_fsqrt_FT(cpu_fregs[FREG(B11_8)], cpu_env, + cpu_fregs[FREG(B11_8)]); } return; case 0xf07d: /* fsrra FRn */ @@ -1809,7 +1821,7 @@ static void _decode_opc(DisasContext * ctx) CHECK_FPU_ENABLED { TCGv_i64 fp = tcg_temp_new_i64(); - gen_helper_fcnvsd_FT_DT(fp, cpu_fpul); + gen_helper_fcnvsd_FT_DT(fp, cpu_env, cpu_fpul); gen_store_fpr64(fp, DREG(B11_8)); tcg_temp_free_i64(fp); } @@ -1819,7 +1831,7 @@ static void _decode_opc(DisasContext * ctx) { TCGv_i64 fp = tcg_temp_new_i64(); gen_load_fpr64(fp, DREG(B11_8)); - gen_helper_fcnvds_DT_FT(cpu_fpul, fp); + gen_helper_fcnvds_DT_FT(cpu_fpul, cpu_env, fp); tcg_temp_free_i64(fp); } return; @@ -1829,7 +1841,7 @@ static void _decode_opc(DisasContext * ctx) TCGv m, n; m = tcg_const_i32((ctx->opcode >> 8) & 3); n = tcg_const_i32((ctx->opcode >> 10) & 3); - gen_helper_fipr(m, n); + gen_helper_fipr(cpu_env, m, n); tcg_temp_free(m); tcg_temp_free(n); return; @@ -1841,7 +1853,7 @@ static void _decode_opc(DisasContext * ctx) (ctx->fpscr & FPSCR_PR) == 0) { TCGv n; n = tcg_const_i32((ctx->opcode >> 10) & 3); - gen_helper_ftrv(n); + gen_helper_ftrv(cpu_env, n); tcg_temp_free(n); return; } @@ -1853,9 +1865,9 @@ static void _decode_opc(DisasContext * ctx) fflush(stderr); #endif if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { - gen_helper_raise_slot_illegal_instruction(); + gen_helper_raise_slot_illegal_instruction(cpu_env); } else { - gen_helper_raise_illegal_instruction(); + gen_helper_raise_illegal_instruction(cpu_env); } ctx->bstate = BS_EXCP; } @@ -1934,7 +1946,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb, if (ctx.pc == bp->pc) { /* We have hit a breakpoint - make sure PC is up-to-date */ tcg_gen_movi_i32(cpu_pc, ctx.pc); - gen_helper_debug(); + gen_helper_debug(cpu_env); ctx.bstate = BS_EXCP; break; } @@ -1958,7 +1970,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb, fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc); fflush(stderr); #endif - ctx.opcode = lduw_code(ctx.pc); + ctx.opcode = cpu_lduw_code(env, ctx.pc); decode_opc(&ctx); num_insns++; ctx.pc += 2; @@ -1975,7 +1987,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb, gen_io_end(); if (env->singlestep_enabled) { tcg_gen_movi_i32(cpu_pc, ctx.pc); - gen_helper_debug(); + gen_helper_debug(cpu_env); } else { switch (ctx.bstate) { case BS_STOP: From 895c2d0435924532c92252fbbf5c4caec8540d34 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 14:52:59 +0000 Subject: [PATCH 0402/2270] target-mips: switch to AREG0 free mode Add an explicit CPUState parameter instead of relying on AREG0 and switch to AREG0 free mode. Signed-off-by: Blue Swirl Acked-by: Aurelien Jarno --- configure | 2 +- target-mips/Makefile.objs | 2 - target-mips/cpu.h | 16 +- target-mips/helper.h | 410 +++++++------- target-mips/op_helper.c | 1065 +++++++++++++++++++------------------ target-mips/translate.c | 754 +++++++++++++------------- 6 files changed, 1163 insertions(+), 1086 deletions(-) diff --git a/configure b/configure index 4ac9904ac9..69f9638e6f 100755 --- a/configure +++ b/configure @@ -3874,7 +3874,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile" case "$target_arch2" in - alpha | arm* | cris | i386 | lm32 | m68k | microblaze* | or32 | s390x | sh4* | sparc* | unicore32 | x86_64 | xtensa* | ppc*) + alpha | arm* | cris | i386 | lm32 | m68k | microblaze* | mips* | or32 | s390x | sh4* | sparc* | unicore32 | x86_64 | xtensa* | ppc*) echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak ;; esac diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs index 2e0e093e1f..ca20f21443 100644 --- a/target-mips/Makefile.objs +++ b/target-mips/Makefile.objs @@ -1,4 +1,2 @@ obj-y += translate.o op_helper.o helper.o cpu.o obj-$(CONFIG_SOFTMMU) += machine.o - -$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 88d92f1182..b7a5112b7b 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -38,10 +38,10 @@ struct CPUMIPSTLBContext { uint32_t nb_tlb; uint32_t tlb_in_use; int (*map_address) (struct CPUMIPSState *env, target_phys_addr_t *physical, int *prot, target_ulong address, int rw, int access_type); - void (*helper_tlbwi) (void); - void (*helper_tlbwr) (void); - void (*helper_tlbp) (void); - void (*helper_tlbr) (void); + void (*helper_tlbwi)(struct CPUMIPSState *env); + void (*helper_tlbwr)(struct CPUMIPSState *env); + void (*helper_tlbp)(struct CPUMIPSState *env); + void (*helper_tlbr)(struct CPUMIPSState *env); union { struct { r4k_tlb_t tlb[MIPS_TLB_MAX]; @@ -485,10 +485,10 @@ int fixed_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int target_ulong address, int rw, int access_type); int r4k_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot, target_ulong address, int rw, int access_type); -void r4k_helper_tlbwi (void); -void r4k_helper_tlbwr (void); -void r4k_helper_tlbp (void); -void r4k_helper_tlbr (void); +void r4k_helper_tlbwi(CPUMIPSState *env); +void r4k_helper_tlbwr(CPUMIPSState *env); +void r4k_helper_tlbp(CPUMIPSState *env); +void r4k_helper_tlbr(CPUMIPSState *env); void cpu_unassigned_access(CPUMIPSState *env, target_phys_addr_t addr, int is_write, int is_exec, int unused, int size); diff --git a/target-mips/helper.h b/target-mips/helper.h index 76fb451e77..109ac37fd6 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -1,25 +1,25 @@ #include "def-helper.h" -DEF_HELPER_2(raise_exception_err, noreturn, i32, int) -DEF_HELPER_1(raise_exception, noreturn, i32) +DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int) +DEF_HELPER_2(raise_exception, noreturn, env, i32) #ifdef TARGET_MIPS64 -DEF_HELPER_3(ldl, tl, tl, tl, int) -DEF_HELPER_3(ldr, tl, tl, tl, int) -DEF_HELPER_3(sdl, void, tl, tl, int) -DEF_HELPER_3(sdr, void, tl, tl, int) +DEF_HELPER_4(ldl, tl, env, tl, tl, int) +DEF_HELPER_4(ldr, tl, env, tl, tl, int) +DEF_HELPER_4(sdl, void, env, tl, tl, int) +DEF_HELPER_4(sdr, void, env, tl, tl, int) #endif -DEF_HELPER_3(lwl, tl, tl, tl, int) -DEF_HELPER_3(lwr, tl, tl, tl, int) -DEF_HELPER_3(swl, void, tl, tl, int) -DEF_HELPER_3(swr, void, tl, tl, int) +DEF_HELPER_4(lwl, tl, env, tl, tl, int) +DEF_HELPER_4(lwr, tl, env, tl, tl, int) +DEF_HELPER_4(swl, void, env, tl, tl, int) +DEF_HELPER_4(swr, void, env, tl, tl, int) #ifndef CONFIG_USER_ONLY -DEF_HELPER_2(ll, tl, tl, int) -DEF_HELPER_3(sc, tl, tl, tl, int) +DEF_HELPER_3(ll, tl, env, tl, int) +DEF_HELPER_4(sc, tl, env, tl, tl, int) #ifdef TARGET_MIPS64 -DEF_HELPER_2(lld, tl, tl, int) -DEF_HELPER_3(scd, tl, tl, tl, int) +DEF_HELPER_3(lld, tl, env, tl, int) +DEF_HELPER_4(scd, tl, env, tl, tl, int) #endif #endif @@ -28,195 +28,195 @@ DEF_HELPER_FLAGS_1(clz, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) #ifdef TARGET_MIPS64 DEF_HELPER_FLAGS_1(dclo, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) DEF_HELPER_FLAGS_1(dclz, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) -DEF_HELPER_2(dmult, void, tl, tl) -DEF_HELPER_2(dmultu, void, tl, tl) +DEF_HELPER_3(dmult, void, env, tl, tl) +DEF_HELPER_3(dmultu, void, env, tl, tl) #endif -DEF_HELPER_2(muls, tl, tl, tl) -DEF_HELPER_2(mulsu, tl, tl, tl) -DEF_HELPER_2(macc, tl, tl, tl) -DEF_HELPER_2(maccu, tl, tl, tl) -DEF_HELPER_2(msac, tl, tl, tl) -DEF_HELPER_2(msacu, tl, tl, tl) -DEF_HELPER_2(mulhi, tl, tl, tl) -DEF_HELPER_2(mulhiu, tl, tl, tl) -DEF_HELPER_2(mulshi, tl, tl, tl) -DEF_HELPER_2(mulshiu, tl, tl, tl) -DEF_HELPER_2(macchi, tl, tl, tl) -DEF_HELPER_2(macchiu, tl, tl, tl) -DEF_HELPER_2(msachi, tl, tl, tl) -DEF_HELPER_2(msachiu, tl, tl, tl) +DEF_HELPER_3(muls, tl, env, tl, tl) +DEF_HELPER_3(mulsu, tl, env, tl, tl) +DEF_HELPER_3(macc, tl, env, tl, tl) +DEF_HELPER_3(maccu, tl, env, tl, tl) +DEF_HELPER_3(msac, tl, env, tl, tl) +DEF_HELPER_3(msacu, tl, env, tl, tl) +DEF_HELPER_3(mulhi, tl, env, tl, tl) +DEF_HELPER_3(mulhiu, tl, env, tl, tl) +DEF_HELPER_3(mulshi, tl, env, tl, tl) +DEF_HELPER_3(mulshiu, tl, env, tl, tl) +DEF_HELPER_3(macchi, tl, env, tl, tl) +DEF_HELPER_3(macchiu, tl, env, tl, tl) +DEF_HELPER_3(msachi, tl, env, tl, tl) +DEF_HELPER_3(msachiu, tl, env, tl, tl) #ifndef CONFIG_USER_ONLY /* CP0 helpers */ -DEF_HELPER_0(mfc0_mvpcontrol, tl) -DEF_HELPER_0(mfc0_mvpconf0, tl) -DEF_HELPER_0(mfc0_mvpconf1, tl) -DEF_HELPER_0(mftc0_vpecontrol, tl) -DEF_HELPER_0(mftc0_vpeconf0, tl) -DEF_HELPER_0(mfc0_random, tl) -DEF_HELPER_0(mfc0_tcstatus, tl) -DEF_HELPER_0(mftc0_tcstatus, tl) -DEF_HELPER_0(mfc0_tcbind, tl) -DEF_HELPER_0(mftc0_tcbind, tl) -DEF_HELPER_0(mfc0_tcrestart, tl) -DEF_HELPER_0(mftc0_tcrestart, tl) -DEF_HELPER_0(mfc0_tchalt, tl) -DEF_HELPER_0(mftc0_tchalt, tl) -DEF_HELPER_0(mfc0_tccontext, tl) -DEF_HELPER_0(mftc0_tccontext, tl) -DEF_HELPER_0(mfc0_tcschedule, tl) -DEF_HELPER_0(mftc0_tcschedule, tl) -DEF_HELPER_0(mfc0_tcschefback, tl) -DEF_HELPER_0(mftc0_tcschefback, tl) -DEF_HELPER_0(mfc0_count, tl) -DEF_HELPER_0(mftc0_entryhi, tl) -DEF_HELPER_0(mftc0_status, tl) -DEF_HELPER_0(mftc0_cause, tl) -DEF_HELPER_0(mftc0_epc, tl) -DEF_HELPER_0(mftc0_ebase, tl) -DEF_HELPER_1(mftc0_configx, tl, tl) -DEF_HELPER_0(mfc0_lladdr, tl) -DEF_HELPER_1(mfc0_watchlo, tl, i32) -DEF_HELPER_1(mfc0_watchhi, tl, i32) -DEF_HELPER_0(mfc0_debug, tl) -DEF_HELPER_0(mftc0_debug, tl) +DEF_HELPER_1(mfc0_mvpcontrol, tl, env) +DEF_HELPER_1(mfc0_mvpconf0, tl, env) +DEF_HELPER_1(mfc0_mvpconf1, tl, env) +DEF_HELPER_1(mftc0_vpecontrol, tl, env) +DEF_HELPER_1(mftc0_vpeconf0, tl, env) +DEF_HELPER_1(mfc0_random, tl, env) +DEF_HELPER_1(mfc0_tcstatus, tl, env) +DEF_HELPER_1(mftc0_tcstatus, tl, env) +DEF_HELPER_1(mfc0_tcbind, tl, env) +DEF_HELPER_1(mftc0_tcbind, tl, env) +DEF_HELPER_1(mfc0_tcrestart, tl, env) +DEF_HELPER_1(mftc0_tcrestart, tl, env) +DEF_HELPER_1(mfc0_tchalt, tl, env) +DEF_HELPER_1(mftc0_tchalt, tl, env) +DEF_HELPER_1(mfc0_tccontext, tl, env) +DEF_HELPER_1(mftc0_tccontext, tl, env) +DEF_HELPER_1(mfc0_tcschedule, tl, env) +DEF_HELPER_1(mftc0_tcschedule, tl, env) +DEF_HELPER_1(mfc0_tcschefback, tl, env) +DEF_HELPER_1(mftc0_tcschefback, tl, env) +DEF_HELPER_1(mfc0_count, tl, env) +DEF_HELPER_1(mftc0_entryhi, tl, env) +DEF_HELPER_1(mftc0_status, tl, env) +DEF_HELPER_1(mftc0_cause, tl, env) +DEF_HELPER_1(mftc0_epc, tl, env) +DEF_HELPER_1(mftc0_ebase, tl, env) +DEF_HELPER_2(mftc0_configx, tl, env, tl) +DEF_HELPER_1(mfc0_lladdr, tl, env) +DEF_HELPER_2(mfc0_watchlo, tl, env, i32) +DEF_HELPER_2(mfc0_watchhi, tl, env, i32) +DEF_HELPER_1(mfc0_debug, tl, env) +DEF_HELPER_1(mftc0_debug, tl, env) #ifdef TARGET_MIPS64 -DEF_HELPER_0(dmfc0_tcrestart, tl) -DEF_HELPER_0(dmfc0_tchalt, tl) -DEF_HELPER_0(dmfc0_tccontext, tl) -DEF_HELPER_0(dmfc0_tcschedule, tl) -DEF_HELPER_0(dmfc0_tcschefback, tl) -DEF_HELPER_0(dmfc0_lladdr, tl) -DEF_HELPER_1(dmfc0_watchlo, tl, i32) +DEF_HELPER_1(dmfc0_tcrestart, tl, env) +DEF_HELPER_1(dmfc0_tchalt, tl, env) +DEF_HELPER_1(dmfc0_tccontext, tl, env) +DEF_HELPER_1(dmfc0_tcschedule, tl, env) +DEF_HELPER_1(dmfc0_tcschefback, tl, env) +DEF_HELPER_1(dmfc0_lladdr, tl, env) +DEF_HELPER_2(dmfc0_watchlo, tl, env, i32) #endif /* TARGET_MIPS64 */ -DEF_HELPER_1(mtc0_index, void, tl) -DEF_HELPER_1(mtc0_mvpcontrol, void, tl) -DEF_HELPER_1(mtc0_vpecontrol, void, tl) -DEF_HELPER_1(mttc0_vpecontrol, void, tl) -DEF_HELPER_1(mtc0_vpeconf0, void, tl) -DEF_HELPER_1(mttc0_vpeconf0, void, tl) -DEF_HELPER_1(mtc0_vpeconf1, void, tl) -DEF_HELPER_1(mtc0_yqmask, void, tl) -DEF_HELPER_1(mtc0_vpeopt, void, tl) -DEF_HELPER_1(mtc0_entrylo0, void, tl) -DEF_HELPER_1(mtc0_tcstatus, void, tl) -DEF_HELPER_1(mttc0_tcstatus, void, tl) -DEF_HELPER_1(mtc0_tcbind, void, tl) -DEF_HELPER_1(mttc0_tcbind, void, tl) -DEF_HELPER_1(mtc0_tcrestart, void, tl) -DEF_HELPER_1(mttc0_tcrestart, void, tl) -DEF_HELPER_1(mtc0_tchalt, void, tl) -DEF_HELPER_1(mttc0_tchalt, void, tl) -DEF_HELPER_1(mtc0_tccontext, void, tl) -DEF_HELPER_1(mttc0_tccontext, void, tl) -DEF_HELPER_1(mtc0_tcschedule, void, tl) -DEF_HELPER_1(mttc0_tcschedule, void, tl) -DEF_HELPER_1(mtc0_tcschefback, void, tl) -DEF_HELPER_1(mttc0_tcschefback, void, tl) -DEF_HELPER_1(mtc0_entrylo1, void, tl) -DEF_HELPER_1(mtc0_context, void, tl) -DEF_HELPER_1(mtc0_pagemask, void, tl) -DEF_HELPER_1(mtc0_pagegrain, void, tl) -DEF_HELPER_1(mtc0_wired, void, tl) -DEF_HELPER_1(mtc0_srsconf0, void, tl) -DEF_HELPER_1(mtc0_srsconf1, void, tl) -DEF_HELPER_1(mtc0_srsconf2, void, tl) -DEF_HELPER_1(mtc0_srsconf3, void, tl) -DEF_HELPER_1(mtc0_srsconf4, void, tl) -DEF_HELPER_1(mtc0_hwrena, void, tl) -DEF_HELPER_1(mtc0_count, void, tl) -DEF_HELPER_1(mtc0_entryhi, void, tl) -DEF_HELPER_1(mttc0_entryhi, void, tl) -DEF_HELPER_1(mtc0_compare, void, tl) -DEF_HELPER_1(mtc0_status, void, tl) -DEF_HELPER_1(mttc0_status, void, tl) -DEF_HELPER_1(mtc0_intctl, void, tl) -DEF_HELPER_1(mtc0_srsctl, void, tl) -DEF_HELPER_1(mtc0_cause, void, tl) -DEF_HELPER_1(mttc0_cause, void, tl) -DEF_HELPER_1(mtc0_ebase, void, tl) -DEF_HELPER_1(mttc0_ebase, void, tl) -DEF_HELPER_1(mtc0_config0, void, tl) -DEF_HELPER_1(mtc0_config2, void, tl) -DEF_HELPER_1(mtc0_lladdr, void, tl) -DEF_HELPER_2(mtc0_watchlo, void, tl, i32) -DEF_HELPER_2(mtc0_watchhi, void, tl, i32) -DEF_HELPER_1(mtc0_xcontext, void, tl) -DEF_HELPER_1(mtc0_framemask, void, tl) -DEF_HELPER_1(mtc0_debug, void, tl) -DEF_HELPER_1(mttc0_debug, void, tl) -DEF_HELPER_1(mtc0_performance0, void, tl) -DEF_HELPER_1(mtc0_taglo, void, tl) -DEF_HELPER_1(mtc0_datalo, void, tl) -DEF_HELPER_1(mtc0_taghi, void, tl) -DEF_HELPER_1(mtc0_datahi, void, tl) +DEF_HELPER_2(mtc0_index, void, env, tl) +DEF_HELPER_2(mtc0_mvpcontrol, void, env, tl) +DEF_HELPER_2(mtc0_vpecontrol, void, env, tl) +DEF_HELPER_2(mttc0_vpecontrol, void, env, tl) +DEF_HELPER_2(mtc0_vpeconf0, void, env, tl) +DEF_HELPER_2(mttc0_vpeconf0, void, env, tl) +DEF_HELPER_2(mtc0_vpeconf1, void, env, tl) +DEF_HELPER_2(mtc0_yqmask, void, env, tl) +DEF_HELPER_2(mtc0_vpeopt, void, env, tl) +DEF_HELPER_2(mtc0_entrylo0, void, env, tl) +DEF_HELPER_2(mtc0_tcstatus, void, env, tl) +DEF_HELPER_2(mttc0_tcstatus, void, env, tl) +DEF_HELPER_2(mtc0_tcbind, void, env, tl) +DEF_HELPER_2(mttc0_tcbind, void, env, tl) +DEF_HELPER_2(mtc0_tcrestart, void, env, tl) +DEF_HELPER_2(mttc0_tcrestart, void, env, tl) +DEF_HELPER_2(mtc0_tchalt, void, env, tl) +DEF_HELPER_2(mttc0_tchalt, void, env, tl) +DEF_HELPER_2(mtc0_tccontext, void, env, tl) +DEF_HELPER_2(mttc0_tccontext, void, env, tl) +DEF_HELPER_2(mtc0_tcschedule, void, env, tl) +DEF_HELPER_2(mttc0_tcschedule, void, env, tl) +DEF_HELPER_2(mtc0_tcschefback, void, env, tl) +DEF_HELPER_2(mttc0_tcschefback, void, env, tl) +DEF_HELPER_2(mtc0_entrylo1, void, env, tl) +DEF_HELPER_2(mtc0_context, void, env, tl) +DEF_HELPER_2(mtc0_pagemask, void, env, tl) +DEF_HELPER_2(mtc0_pagegrain, void, env, tl) +DEF_HELPER_2(mtc0_wired, void, env, tl) +DEF_HELPER_2(mtc0_srsconf0, void, env, tl) +DEF_HELPER_2(mtc0_srsconf1, void, env, tl) +DEF_HELPER_2(mtc0_srsconf2, void, env, tl) +DEF_HELPER_2(mtc0_srsconf3, void, env, tl) +DEF_HELPER_2(mtc0_srsconf4, void, env, tl) +DEF_HELPER_2(mtc0_hwrena, void, env, tl) +DEF_HELPER_2(mtc0_count, void, env, tl) +DEF_HELPER_2(mtc0_entryhi, void, env, tl) +DEF_HELPER_2(mttc0_entryhi, void, env, tl) +DEF_HELPER_2(mtc0_compare, void, env, tl) +DEF_HELPER_2(mtc0_status, void, env, tl) +DEF_HELPER_2(mttc0_status, void, env, tl) +DEF_HELPER_2(mtc0_intctl, void, env, tl) +DEF_HELPER_2(mtc0_srsctl, void, env, tl) +DEF_HELPER_2(mtc0_cause, void, env, tl) +DEF_HELPER_2(mttc0_cause, void, env, tl) +DEF_HELPER_2(mtc0_ebase, void, env, tl) +DEF_HELPER_2(mttc0_ebase, void, env, tl) +DEF_HELPER_2(mtc0_config0, void, env, tl) +DEF_HELPER_2(mtc0_config2, void, env, tl) +DEF_HELPER_2(mtc0_lladdr, void, env, tl) +DEF_HELPER_3(mtc0_watchlo, void, env, tl, i32) +DEF_HELPER_3(mtc0_watchhi, void, env, tl, i32) +DEF_HELPER_2(mtc0_xcontext, void, env, tl) +DEF_HELPER_2(mtc0_framemask, void, env, tl) +DEF_HELPER_2(mtc0_debug, void, env, tl) +DEF_HELPER_2(mttc0_debug, void, env, tl) +DEF_HELPER_2(mtc0_performance0, void, env, tl) +DEF_HELPER_2(mtc0_taglo, void, env, tl) +DEF_HELPER_2(mtc0_datalo, void, env, tl) +DEF_HELPER_2(mtc0_taghi, void, env, tl) +DEF_HELPER_2(mtc0_datahi, void, env, tl) /* MIPS MT functions */ -DEF_HELPER_1(mftgpr, tl, i32); -DEF_HELPER_1(mftlo, tl, i32) -DEF_HELPER_1(mfthi, tl, i32) -DEF_HELPER_1(mftacx, tl, i32) -DEF_HELPER_0(mftdsp, tl) -DEF_HELPER_2(mttgpr, void, tl, i32) -DEF_HELPER_2(mttlo, void, tl, i32) -DEF_HELPER_2(mtthi, void, tl, i32) -DEF_HELPER_2(mttacx, void, tl, i32) -DEF_HELPER_1(mttdsp, void, tl) +DEF_HELPER_2(mftgpr, tl, env, i32); +DEF_HELPER_2(mftlo, tl, env, i32) +DEF_HELPER_2(mfthi, tl, env, i32) +DEF_HELPER_2(mftacx, tl, env, i32) +DEF_HELPER_1(mftdsp, tl, env) +DEF_HELPER_3(mttgpr, void, env, tl, i32) +DEF_HELPER_3(mttlo, void, env, tl, i32) +DEF_HELPER_3(mtthi, void, env, tl, i32) +DEF_HELPER_3(mttacx, void, env, tl, i32) +DEF_HELPER_2(mttdsp, void, env, tl) DEF_HELPER_0(dmt, tl) DEF_HELPER_0(emt, tl) -DEF_HELPER_0(dvpe, tl) -DEF_HELPER_0(evpe, tl) +DEF_HELPER_1(dvpe, tl, env) +DEF_HELPER_1(evpe, tl, env) #endif /* !CONFIG_USER_ONLY */ /* microMIPS functions */ -DEF_HELPER_3(lwm, void, tl, tl, i32); -DEF_HELPER_3(swm, void, tl, tl, i32); +DEF_HELPER_4(lwm, void, env, tl, tl, i32); +DEF_HELPER_4(swm, void, env, tl, tl, i32); #ifdef TARGET_MIPS64 -DEF_HELPER_3(ldm, void, tl, tl, i32); -DEF_HELPER_3(sdm, void, tl, tl, i32); +DEF_HELPER_4(ldm, void, env, tl, tl, i32); +DEF_HELPER_4(sdm, void, env, tl, tl, i32); #endif DEF_HELPER_2(fork, void, tl, tl) -DEF_HELPER_1(yield, tl, tl) +DEF_HELPER_2(yield, tl, env, tl) /* CP1 functions */ -DEF_HELPER_1(cfc1, tl, i32) -DEF_HELPER_2(ctc1, void, tl, i32) +DEF_HELPER_2(cfc1, tl, env, i32) +DEF_HELPER_3(ctc1, void, env, tl, i32) -DEF_HELPER_1(float_cvtd_s, i64, i32) -DEF_HELPER_1(float_cvtd_w, i64, i32) -DEF_HELPER_1(float_cvtd_l, i64, i64) -DEF_HELPER_1(float_cvtl_d, i64, i64) -DEF_HELPER_1(float_cvtl_s, i64, i32) -DEF_HELPER_1(float_cvtps_pw, i64, i64) -DEF_HELPER_1(float_cvtpw_ps, i64, i64) -DEF_HELPER_1(float_cvts_d, i32, i64) -DEF_HELPER_1(float_cvts_w, i32, i32) -DEF_HELPER_1(float_cvts_l, i32, i64) -DEF_HELPER_1(float_cvts_pl, i32, i32) -DEF_HELPER_1(float_cvts_pu, i32, i32) -DEF_HELPER_1(float_cvtw_s, i32, i32) -DEF_HELPER_1(float_cvtw_d, i32, i64) +DEF_HELPER_2(float_cvtd_s, i64, env, i32) +DEF_HELPER_2(float_cvtd_w, i64, env, i32) +DEF_HELPER_2(float_cvtd_l, i64, env, i64) +DEF_HELPER_2(float_cvtl_d, i64, env, i64) +DEF_HELPER_2(float_cvtl_s, i64, env, i32) +DEF_HELPER_2(float_cvtps_pw, i64, env, i64) +DEF_HELPER_2(float_cvtpw_ps, i64, env, i64) +DEF_HELPER_2(float_cvts_d, i32, env, i64) +DEF_HELPER_2(float_cvts_w, i32, env, i32) +DEF_HELPER_2(float_cvts_l, i32, env, i64) +DEF_HELPER_2(float_cvts_pl, i32, env, i32) +DEF_HELPER_2(float_cvts_pu, i32, env, i32) +DEF_HELPER_2(float_cvtw_s, i32, env, i32) +DEF_HELPER_2(float_cvtw_d, i32, env, i64) -DEF_HELPER_2(float_addr_ps, i64, i64, i64) -DEF_HELPER_2(float_mulr_ps, i64, i64, i64) +DEF_HELPER_3(float_addr_ps, i64, env, i64, i64) +DEF_HELPER_3(float_mulr_ps, i64, env, i64, i64) -#define FOP_PROTO(op) \ -DEF_HELPER_1(float_ ## op ## l_s, i64, i32) \ -DEF_HELPER_1(float_ ## op ## l_d, i64, i64) \ -DEF_HELPER_1(float_ ## op ## w_s, i32, i32) \ -DEF_HELPER_1(float_ ## op ## w_d, i32, i64) +#define FOP_PROTO(op) \ +DEF_HELPER_2(float_ ## op ## l_s, i64, env, i32) \ +DEF_HELPER_2(float_ ## op ## l_d, i64, env, i64) \ +DEF_HELPER_2(float_ ## op ## w_s, i32, env, i32) \ +DEF_HELPER_2(float_ ## op ## w_d, i32, env, i64) FOP_PROTO(round) FOP_PROTO(trunc) FOP_PROTO(ceil) FOP_PROTO(floor) #undef FOP_PROTO -#define FOP_PROTO(op) \ -DEF_HELPER_1(float_ ## op ## _s, i32, i32) \ -DEF_HELPER_1(float_ ## op ## _d, i64, i64) +#define FOP_PROTO(op) \ +DEF_HELPER_2(float_ ## op ## _s, i32, env, i32) \ +DEF_HELPER_2(float_ ## op ## _d, i64, env, i64) FOP_PROTO(sqrt) FOP_PROTO(rsqrt) FOP_PROTO(recip) @@ -228,14 +228,20 @@ DEF_HELPER_1(float_ ## op ## _d, i64, i64) \ DEF_HELPER_1(float_ ## op ## _ps, i64, i64) FOP_PROTO(abs) FOP_PROTO(chs) +#undef FOP_PROTO + +#define FOP_PROTO(op) \ +DEF_HELPER_2(float_ ## op ## _s, i32, env, i32) \ +DEF_HELPER_2(float_ ## op ## _d, i64, env, i64) \ +DEF_HELPER_2(float_ ## op ## _ps, i64, env, i64) FOP_PROTO(recip1) FOP_PROTO(rsqrt1) #undef FOP_PROTO -#define FOP_PROTO(op) \ -DEF_HELPER_2(float_ ## op ## _s, i32, i32, i32) \ -DEF_HELPER_2(float_ ## op ## _d, i64, i64, i64) \ -DEF_HELPER_2(float_ ## op ## _ps, i64, i64, i64) +#define FOP_PROTO(op) \ +DEF_HELPER_3(float_ ## op ## _s, i32, env, i32, i32) \ +DEF_HELPER_3(float_ ## op ## _d, i64, env, i64, i64) \ +DEF_HELPER_3(float_ ## op ## _ps, i64, env, i64, i64) FOP_PROTO(add) FOP_PROTO(sub) FOP_PROTO(mul) @@ -244,23 +250,23 @@ FOP_PROTO(recip2) FOP_PROTO(rsqrt2) #undef FOP_PROTO -#define FOP_PROTO(op) \ -DEF_HELPER_3(float_ ## op ## _s, i32, i32, i32, i32) \ -DEF_HELPER_3(float_ ## op ## _d, i64, i64, i64, i64) \ -DEF_HELPER_3(float_ ## op ## _ps, i64, i64, i64, i64) +#define FOP_PROTO(op) \ +DEF_HELPER_4(float_ ## op ## _s, i32, env, i32, i32, i32) \ +DEF_HELPER_4(float_ ## op ## _d, i64, env, i64, i64, i64) \ +DEF_HELPER_4(float_ ## op ## _ps, i64, env, i64, i64, i64) FOP_PROTO(muladd) FOP_PROTO(mulsub) FOP_PROTO(nmuladd) FOP_PROTO(nmulsub) #undef FOP_PROTO -#define FOP_PROTO(op) \ -DEF_HELPER_3(cmp_d_ ## op, void, i64, i64, int) \ -DEF_HELPER_3(cmpabs_d_ ## op, void, i64, i64, int) \ -DEF_HELPER_3(cmp_s_ ## op, void, i32, i32, int) \ -DEF_HELPER_3(cmpabs_s_ ## op, void, i32, i32, int) \ -DEF_HELPER_3(cmp_ps_ ## op, void, i64, i64, int) \ -DEF_HELPER_3(cmpabs_ps_ ## op, void, i64, i64, int) +#define FOP_PROTO(op) \ +DEF_HELPER_4(cmp_d_ ## op, void, env, i64, i64, int) \ +DEF_HELPER_4(cmpabs_d_ ## op, void, env, i64, i64, int) \ +DEF_HELPER_4(cmp_s_ ## op, void, env, i32, i32, int) \ +DEF_HELPER_4(cmpabs_s_ ## op, void, env, i32, i32, int) \ +DEF_HELPER_4(cmp_ps_ ## op, void, env, i64, i64, int) \ +DEF_HELPER_4(cmpabs_ps_ ## op, void, env, i64, i64, int) FOP_PROTO(f) FOP_PROTO(un) FOP_PROTO(eq) @@ -281,20 +287,20 @@ FOP_PROTO(ngt) /* Special functions */ #ifndef CONFIG_USER_ONLY -DEF_HELPER_0(tlbwi, void) -DEF_HELPER_0(tlbwr, void) -DEF_HELPER_0(tlbp, void) -DEF_HELPER_0(tlbr, void) -DEF_HELPER_0(di, tl) -DEF_HELPER_0(ei, tl) -DEF_HELPER_0(eret, void) -DEF_HELPER_0(deret, void) +DEF_HELPER_1(tlbwi, void, env) +DEF_HELPER_1(tlbwr, void, env) +DEF_HELPER_1(tlbp, void, env) +DEF_HELPER_1(tlbr, void, env) +DEF_HELPER_1(di, tl, env) +DEF_HELPER_1(ei, tl, env) +DEF_HELPER_1(eret, void, env) +DEF_HELPER_1(deret, void, env) #endif /* !CONFIG_USER_ONLY */ -DEF_HELPER_0(rdhwr_cpunum, tl) -DEF_HELPER_0(rdhwr_synci_step, tl) -DEF_HELPER_0(rdhwr_cc, tl) -DEF_HELPER_0(rdhwr_ccres, tl) -DEF_HELPER_1(pmon, void, int) -DEF_HELPER_0(wait, void) +DEF_HELPER_1(rdhwr_cpunum, tl, env) +DEF_HELPER_1(rdhwr_synci_step, tl, env) +DEF_HELPER_1(rdhwr_cc, tl, env) +DEF_HELPER_1(rdhwr_ccres, tl, env) +DEF_HELPER_2(pmon, void, env, int) +DEF_HELPER_1(wait, void, env) #include "def-helper.h" diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 3d242aafda..ce5ddaf050 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -18,8 +18,6 @@ */ #include #include "cpu.h" -#include "dyngen-exec.h" - #include "host-utils.h" #include "helper.h" @@ -35,7 +33,8 @@ static inline void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global); /*****************************************************************************/ /* Exceptions processing helpers */ -void helper_raise_exception_err (uint32_t exception, int error_code) +void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception, + int error_code) { #if 1 if (exception < 0x100) @@ -46,13 +45,13 @@ void helper_raise_exception_err (uint32_t exception, int error_code) cpu_loop_exit(env); } -void helper_raise_exception (uint32_t exception) +void helper_raise_exception(CPUMIPSState *env, uint32_t exception) { - helper_raise_exception_err(exception, 0); + helper_raise_exception_err(env, exception, 0); } #if !defined(CONFIG_USER_ONLY) -static void do_restore_state(uintptr_t pc) +static void do_restore_state(CPUMIPSState *env, uintptr_t pc) { TranslationBlock *tb; @@ -65,20 +64,22 @@ static void do_restore_state(uintptr_t pc) #if defined(CONFIG_USER_ONLY) #define HELPER_LD(name, insn, type) \ -static inline type do_##name(target_ulong addr, int mem_idx) \ +static inline type do_##name(CPUMIPSState *env, target_ulong addr, \ + int mem_idx) \ { \ return (type) insn##_raw(addr); \ } #else #define HELPER_LD(name, insn, type) \ -static inline type do_##name(target_ulong addr, int mem_idx) \ +static inline type do_##name(CPUMIPSState *env, target_ulong addr, \ + int mem_idx) \ { \ switch (mem_idx) \ { \ - case 0: return (type) insn##_kernel(addr); break; \ - case 1: return (type) insn##_super(addr); break; \ + case 0: return (type) cpu_##insn##_kernel(env, addr); break; \ + case 1: return (type) cpu_##insn##_super(env, addr); break; \ default: \ - case 2: return (type) insn##_user(addr); break; \ + case 2: return (type) cpu_##insn##_user(env, addr); break; \ } \ } #endif @@ -91,20 +92,22 @@ HELPER_LD(ld, ldq, int64_t) #if defined(CONFIG_USER_ONLY) #define HELPER_ST(name, insn, type) \ -static inline void do_##name(target_ulong addr, type val, int mem_idx) \ +static inline void do_##name(CPUMIPSState *env, target_ulong addr, \ + type val, int mem_idx) \ { \ insn##_raw(addr, val); \ } #else #define HELPER_ST(name, insn, type) \ -static inline void do_##name(target_ulong addr, type val, int mem_idx) \ +static inline void do_##name(CPUMIPSState *env, target_ulong addr, \ + type val, int mem_idx) \ { \ switch (mem_idx) \ { \ - case 0: insn##_kernel(addr, val); break; \ - case 1: insn##_super(addr, val); break; \ + case 0: cpu_##insn##_kernel(env, addr, val); break; \ + case 1: cpu_##insn##_super(env, addr, val); break; \ default: \ - case 2: insn##_user(addr, val); break; \ + case 2: cpu_##insn##_user(env, addr, val); break; \ } \ } #endif @@ -138,12 +141,12 @@ target_ulong helper_dclz (target_ulong arg1) #endif /* TARGET_MIPS64 */ /* 64 bits arithmetic for 32 bits hosts */ -static inline uint64_t get_HILO (void) +static inline uint64_t get_HILO(CPUMIPSState *env) { return ((uint64_t)(env->active_tc.HI[0]) << 32) | (uint32_t)env->active_tc.LO[0]; } -static inline target_ulong set_HIT0_LO(uint64_t HILO) +static inline target_ulong set_HIT0_LO(CPUMIPSState *env, uint64_t HILO) { target_ulong tmp; env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF); @@ -151,7 +154,7 @@ static inline target_ulong set_HIT0_LO(uint64_t HILO) return tmp; } -static inline target_ulong set_HI_LOT0(uint64_t HILO) +static inline target_ulong set_HI_LOT0(CPUMIPSState *env, uint64_t HILO) { target_ulong tmp = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF); env->active_tc.HI[0] = (int32_t)(HILO >> 32); @@ -159,91 +162,110 @@ static inline target_ulong set_HI_LOT0(uint64_t HILO) } /* Multiplication variants of the vr54xx. */ -target_ulong helper_muls (target_ulong arg1, target_ulong arg2) +target_ulong helper_muls(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) { - return set_HI_LOT0(0 - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2)); + return set_HI_LOT0(env, 0 - ((int64_t)(int32_t)arg1 * + (int64_t)(int32_t)arg2)); } -target_ulong helper_mulsu (target_ulong arg1, target_ulong arg2) +target_ulong helper_mulsu(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) { - return set_HI_LOT0(0 - (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); + return set_HI_LOT0(env, 0 - (uint64_t)(uint32_t)arg1 * + (uint64_t)(uint32_t)arg2); } -target_ulong helper_macc (target_ulong arg1, target_ulong arg2) +target_ulong helper_macc(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) { - return set_HI_LOT0((int64_t)get_HILO() + (int64_t)(int32_t)arg1 * - (int64_t)(int32_t)arg2); + return set_HI_LOT0(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 * + (int64_t)(int32_t)arg2); } -target_ulong helper_macchi (target_ulong arg1, target_ulong arg2) +target_ulong helper_macchi(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) { - return set_HIT0_LO((int64_t)get_HILO() + (int64_t)(int32_t)arg1 * - (int64_t)(int32_t)arg2); + return set_HIT0_LO(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 * + (int64_t)(int32_t)arg2); } -target_ulong helper_maccu (target_ulong arg1, target_ulong arg2) +target_ulong helper_maccu(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) { - return set_HI_LOT0((uint64_t)get_HILO() + (uint64_t)(uint32_t)arg1 * - (uint64_t)(uint32_t)arg2); + return set_HI_LOT0(env, (uint64_t)get_HILO(env) + + (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); } -target_ulong helper_macchiu (target_ulong arg1, target_ulong arg2) +target_ulong helper_macchiu(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) { - return set_HIT0_LO((uint64_t)get_HILO() + (uint64_t)(uint32_t)arg1 * - (uint64_t)(uint32_t)arg2); + return set_HIT0_LO(env, (uint64_t)get_HILO(env) + + (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); } -target_ulong helper_msac (target_ulong arg1, target_ulong arg2) +target_ulong helper_msac(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) { - return set_HI_LOT0((int64_t)get_HILO() - (int64_t)(int32_t)arg1 * - (int64_t)(int32_t)arg2); + return set_HI_LOT0(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 * + (int64_t)(int32_t)arg2); } -target_ulong helper_msachi (target_ulong arg1, target_ulong arg2) +target_ulong helper_msachi(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) { - return set_HIT0_LO((int64_t)get_HILO() - (int64_t)(int32_t)arg1 * - (int64_t)(int32_t)arg2); + return set_HIT0_LO(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 * + (int64_t)(int32_t)arg2); } -target_ulong helper_msacu (target_ulong arg1, target_ulong arg2) +target_ulong helper_msacu(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) { - return set_HI_LOT0((uint64_t)get_HILO() - (uint64_t)(uint32_t)arg1 * - (uint64_t)(uint32_t)arg2); + return set_HI_LOT0(env, (uint64_t)get_HILO(env) - + (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); } -target_ulong helper_msachiu (target_ulong arg1, target_ulong arg2) +target_ulong helper_msachiu(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) { - return set_HIT0_LO((uint64_t)get_HILO() - (uint64_t)(uint32_t)arg1 * - (uint64_t)(uint32_t)arg2); + return set_HIT0_LO(env, (uint64_t)get_HILO(env) - + (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); } -target_ulong helper_mulhi (target_ulong arg1, target_ulong arg2) +target_ulong helper_mulhi(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) { - return set_HIT0_LO((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2); + return set_HIT0_LO(env, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2); } -target_ulong helper_mulhiu (target_ulong arg1, target_ulong arg2) +target_ulong helper_mulhiu(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) { - return set_HIT0_LO((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); + return set_HIT0_LO(env, (uint64_t)(uint32_t)arg1 * + (uint64_t)(uint32_t)arg2); } -target_ulong helper_mulshi (target_ulong arg1, target_ulong arg2) +target_ulong helper_mulshi(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) { - return set_HIT0_LO(0 - (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2); + return set_HIT0_LO(env, 0 - (int64_t)(int32_t)arg1 * + (int64_t)(int32_t)arg2); } -target_ulong helper_mulshiu (target_ulong arg1, target_ulong arg2) +target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2) { - return set_HIT0_LO(0 - (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); + return set_HIT0_LO(env, 0 - (uint64_t)(uint32_t)arg1 * + (uint64_t)(uint32_t)arg2); } #ifdef TARGET_MIPS64 -void helper_dmult (target_ulong arg1, target_ulong arg2) +void helper_dmult(CPUMIPSState *env, target_ulong arg1, target_ulong arg2) { muls64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2); } -void helper_dmultu (target_ulong arg1, target_ulong arg2) +void helper_dmultu(CPUMIPSState *env, target_ulong arg1, target_ulong arg2) { mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2); } @@ -251,7 +273,9 @@ void helper_dmultu (target_ulong arg1, target_ulong arg2) #ifndef CONFIG_USER_ONLY -static inline target_phys_addr_t do_translate_address(target_ulong address, int rw) +static inline target_phys_addr_t do_translate_address(CPUMIPSState *env, + target_ulong address, + int rw) { target_phys_addr_t lladdr; @@ -265,10 +289,10 @@ static inline target_phys_addr_t do_translate_address(target_ulong address, int } #define HELPER_LD_ATOMIC(name, insn) \ -target_ulong helper_##name(target_ulong arg, int mem_idx) \ +target_ulong helper_##name(CPUMIPSState *env, target_ulong arg, int mem_idx) \ { \ - env->lladdr = do_translate_address(arg, 0); \ - env->llval = do_##insn(arg, mem_idx); \ + env->lladdr = do_translate_address(env, arg, 0); \ + env->llval = do_##insn(env, arg, mem_idx); \ return env->llval; \ } HELPER_LD_ATOMIC(ll, lw) @@ -278,18 +302,19 @@ HELPER_LD_ATOMIC(lld, ld) #undef HELPER_LD_ATOMIC #define HELPER_ST_ATOMIC(name, ld_insn, st_insn, almask) \ -target_ulong helper_##name(target_ulong arg1, target_ulong arg2, int mem_idx) \ +target_ulong helper_##name(CPUMIPSState *env, target_ulong arg1, \ + target_ulong arg2, int mem_idx) \ { \ target_long tmp; \ \ if (arg2 & almask) { \ env->CP0_BadVAddr = arg2; \ - helper_raise_exception(EXCP_AdES); \ + helper_raise_exception(env, EXCP_AdES); \ } \ - if (do_translate_address(arg2, 1) == env->lladdr) { \ - tmp = do_##ld_insn(arg2, mem_idx); \ + if (do_translate_address(env, arg2, 1) == env->lladdr) { \ + tmp = do_##ld_insn(env, arg2, mem_idx); \ if (tmp == env->llval) { \ - do_##st_insn(arg2, arg1, mem_idx); \ + do_##st_insn(env, arg2, arg1, mem_idx); \ return 1; \ } \ } \ @@ -310,80 +335,84 @@ HELPER_ST_ATOMIC(scd, ld, sd, 0x7) #define GET_OFFSET(addr, offset) (addr - (offset)) #endif -target_ulong helper_lwl(target_ulong arg1, target_ulong arg2, int mem_idx) +target_ulong helper_lwl(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2, int mem_idx) { target_ulong tmp; - tmp = do_lbu(arg2, mem_idx); + tmp = do_lbu(env, arg2, mem_idx); arg1 = (arg1 & 0x00FFFFFF) | (tmp << 24); if (GET_LMASK(arg2) <= 2) { - tmp = do_lbu(GET_OFFSET(arg2, 1), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, 1), mem_idx); arg1 = (arg1 & 0xFF00FFFF) | (tmp << 16); } if (GET_LMASK(arg2) <= 1) { - tmp = do_lbu(GET_OFFSET(arg2, 2), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, 2), mem_idx); arg1 = (arg1 & 0xFFFF00FF) | (tmp << 8); } if (GET_LMASK(arg2) == 0) { - tmp = do_lbu(GET_OFFSET(arg2, 3), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, 3), mem_idx); arg1 = (arg1 & 0xFFFFFF00) | tmp; } return (int32_t)arg1; } -target_ulong helper_lwr(target_ulong arg1, target_ulong arg2, int mem_idx) +target_ulong helper_lwr(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2, int mem_idx) { target_ulong tmp; - tmp = do_lbu(arg2, mem_idx); + tmp = do_lbu(env, arg2, mem_idx); arg1 = (arg1 & 0xFFFFFF00) | tmp; if (GET_LMASK(arg2) >= 1) { - tmp = do_lbu(GET_OFFSET(arg2, -1), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, -1), mem_idx); arg1 = (arg1 & 0xFFFF00FF) | (tmp << 8); } if (GET_LMASK(arg2) >= 2) { - tmp = do_lbu(GET_OFFSET(arg2, -2), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, -2), mem_idx); arg1 = (arg1 & 0xFF00FFFF) | (tmp << 16); } if (GET_LMASK(arg2) == 3) { - tmp = do_lbu(GET_OFFSET(arg2, -3), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, -3), mem_idx); arg1 = (arg1 & 0x00FFFFFF) | (tmp << 24); } return (int32_t)arg1; } -void helper_swl(target_ulong arg1, target_ulong arg2, int mem_idx) +void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, + int mem_idx) { - do_sb(arg2, (uint8_t)(arg1 >> 24), mem_idx); + do_sb(env, arg2, (uint8_t)(arg1 >> 24), mem_idx); if (GET_LMASK(arg2) <= 2) - do_sb(GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 16), mem_idx); + do_sb(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 16), mem_idx); if (GET_LMASK(arg2) <= 1) - do_sb(GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 8), mem_idx); + do_sb(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 8), mem_idx); if (GET_LMASK(arg2) == 0) - do_sb(GET_OFFSET(arg2, 3), (uint8_t)arg1, mem_idx); + do_sb(env, GET_OFFSET(arg2, 3), (uint8_t)arg1, mem_idx); } -void helper_swr(target_ulong arg1, target_ulong arg2, int mem_idx) +void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, + int mem_idx) { - do_sb(arg2, (uint8_t)arg1, mem_idx); + do_sb(env, arg2, (uint8_t)arg1, mem_idx); if (GET_LMASK(arg2) >= 1) - do_sb(GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx); + do_sb(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx); if (GET_LMASK(arg2) >= 2) - do_sb(GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx); + do_sb(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx); if (GET_LMASK(arg2) == 3) - do_sb(GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx); + do_sb(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx); } #if defined(TARGET_MIPS64) @@ -396,167 +425,172 @@ void helper_swr(target_ulong arg1, target_ulong arg2, int mem_idx) #define GET_LMASK64(v) (((v) & 7) ^ 7) #endif -target_ulong helper_ldl(target_ulong arg1, target_ulong arg2, int mem_idx) +target_ulong helper_ldl(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2, int mem_idx) { uint64_t tmp; - tmp = do_lbu(arg2, mem_idx); + tmp = do_lbu(env, arg2, mem_idx); arg1 = (arg1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56); if (GET_LMASK64(arg2) <= 6) { - tmp = do_lbu(GET_OFFSET(arg2, 1), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, 1), mem_idx); arg1 = (arg1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48); } if (GET_LMASK64(arg2) <= 5) { - tmp = do_lbu(GET_OFFSET(arg2, 2), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, 2), mem_idx); arg1 = (arg1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40); } if (GET_LMASK64(arg2) <= 4) { - tmp = do_lbu(GET_OFFSET(arg2, 3), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, 3), mem_idx); arg1 = (arg1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32); } if (GET_LMASK64(arg2) <= 3) { - tmp = do_lbu(GET_OFFSET(arg2, 4), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, 4), mem_idx); arg1 = (arg1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24); } if (GET_LMASK64(arg2) <= 2) { - tmp = do_lbu(GET_OFFSET(arg2, 5), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, 5), mem_idx); arg1 = (arg1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16); } if (GET_LMASK64(arg2) <= 1) { - tmp = do_lbu(GET_OFFSET(arg2, 6), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, 6), mem_idx); arg1 = (arg1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8); } if (GET_LMASK64(arg2) == 0) { - tmp = do_lbu(GET_OFFSET(arg2, 7), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, 7), mem_idx); arg1 = (arg1 & 0xFFFFFFFFFFFFFF00ULL) | tmp; } return arg1; } -target_ulong helper_ldr(target_ulong arg1, target_ulong arg2, int mem_idx) +target_ulong helper_ldr(CPUMIPSState *env, target_ulong arg1, + target_ulong arg2, int mem_idx) { uint64_t tmp; - tmp = do_lbu(arg2, mem_idx); + tmp = do_lbu(env, arg2, mem_idx); arg1 = (arg1 & 0xFFFFFFFFFFFFFF00ULL) | tmp; if (GET_LMASK64(arg2) >= 1) { - tmp = do_lbu(GET_OFFSET(arg2, -1), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, -1), mem_idx); arg1 = (arg1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8); } if (GET_LMASK64(arg2) >= 2) { - tmp = do_lbu(GET_OFFSET(arg2, -2), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, -2), mem_idx); arg1 = (arg1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16); } if (GET_LMASK64(arg2) >= 3) { - tmp = do_lbu(GET_OFFSET(arg2, -3), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, -3), mem_idx); arg1 = (arg1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24); } if (GET_LMASK64(arg2) >= 4) { - tmp = do_lbu(GET_OFFSET(arg2, -4), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, -4), mem_idx); arg1 = (arg1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32); } if (GET_LMASK64(arg2) >= 5) { - tmp = do_lbu(GET_OFFSET(arg2, -5), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, -5), mem_idx); arg1 = (arg1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40); } if (GET_LMASK64(arg2) >= 6) { - tmp = do_lbu(GET_OFFSET(arg2, -6), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, -6), mem_idx); arg1 = (arg1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48); } if (GET_LMASK64(arg2) == 7) { - tmp = do_lbu(GET_OFFSET(arg2, -7), mem_idx); + tmp = do_lbu(env, GET_OFFSET(arg2, -7), mem_idx); arg1 = (arg1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56); } return arg1; } -void helper_sdl(target_ulong arg1, target_ulong arg2, int mem_idx) +void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, + int mem_idx) { - do_sb(arg2, (uint8_t)(arg1 >> 56), mem_idx); + do_sb(env, arg2, (uint8_t)(arg1 >> 56), mem_idx); if (GET_LMASK64(arg2) <= 6) - do_sb(GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 48), mem_idx); + do_sb(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 48), mem_idx); if (GET_LMASK64(arg2) <= 5) - do_sb(GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 40), mem_idx); + do_sb(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 40), mem_idx); if (GET_LMASK64(arg2) <= 4) - do_sb(GET_OFFSET(arg2, 3), (uint8_t)(arg1 >> 32), mem_idx); + do_sb(env, GET_OFFSET(arg2, 3), (uint8_t)(arg1 >> 32), mem_idx); if (GET_LMASK64(arg2) <= 3) - do_sb(GET_OFFSET(arg2, 4), (uint8_t)(arg1 >> 24), mem_idx); + do_sb(env, GET_OFFSET(arg2, 4), (uint8_t)(arg1 >> 24), mem_idx); if (GET_LMASK64(arg2) <= 2) - do_sb(GET_OFFSET(arg2, 5), (uint8_t)(arg1 >> 16), mem_idx); + do_sb(env, GET_OFFSET(arg2, 5), (uint8_t)(arg1 >> 16), mem_idx); if (GET_LMASK64(arg2) <= 1) - do_sb(GET_OFFSET(arg2, 6), (uint8_t)(arg1 >> 8), mem_idx); + do_sb(env, GET_OFFSET(arg2, 6), (uint8_t)(arg1 >> 8), mem_idx); if (GET_LMASK64(arg2) <= 0) - do_sb(GET_OFFSET(arg2, 7), (uint8_t)arg1, mem_idx); + do_sb(env, GET_OFFSET(arg2, 7), (uint8_t)arg1, mem_idx); } -void helper_sdr(target_ulong arg1, target_ulong arg2, int mem_idx) +void helper_sdr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, + int mem_idx) { - do_sb(arg2, (uint8_t)arg1, mem_idx); + do_sb(env, arg2, (uint8_t)arg1, mem_idx); if (GET_LMASK64(arg2) >= 1) - do_sb(GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx); + do_sb(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx); if (GET_LMASK64(arg2) >= 2) - do_sb(GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx); + do_sb(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx); if (GET_LMASK64(arg2) >= 3) - do_sb(GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx); + do_sb(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx); if (GET_LMASK64(arg2) >= 4) - do_sb(GET_OFFSET(arg2, -4), (uint8_t)(arg1 >> 32), mem_idx); + do_sb(env, GET_OFFSET(arg2, -4), (uint8_t)(arg1 >> 32), mem_idx); if (GET_LMASK64(arg2) >= 5) - do_sb(GET_OFFSET(arg2, -5), (uint8_t)(arg1 >> 40), mem_idx); + do_sb(env, GET_OFFSET(arg2, -5), (uint8_t)(arg1 >> 40), mem_idx); if (GET_LMASK64(arg2) >= 6) - do_sb(GET_OFFSET(arg2, -6), (uint8_t)(arg1 >> 48), mem_idx); + do_sb(env, GET_OFFSET(arg2, -6), (uint8_t)(arg1 >> 48), mem_idx); if (GET_LMASK64(arg2) == 7) - do_sb(GET_OFFSET(arg2, -7), (uint8_t)(arg1 >> 56), mem_idx); + do_sb(env, GET_OFFSET(arg2, -7), (uint8_t)(arg1 >> 56), mem_idx); } #endif /* TARGET_MIPS64 */ static const int multiple_regs[] = { 16, 17, 18, 19, 20, 21, 22, 23, 30 }; -void helper_lwm (target_ulong addr, target_ulong reglist, uint32_t mem_idx) +void helper_lwm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, + uint32_t mem_idx) { target_ulong base_reglist = reglist & 0xf; target_ulong do_r31 = reglist & 0x10; #ifdef CONFIG_USER_ONLY #undef ldfun -#define ldfun ldl_raw +#define ldfun(env, addr) ldl_raw(addr) #else - uint32_t (*ldfun)(target_ulong); + uint32_t (*ldfun)(CPUMIPSState *env, target_ulong); switch (mem_idx) { - case 0: ldfun = ldl_kernel; break; - case 1: ldfun = ldl_super; break; + case 0: ldfun = cpu_ldl_kernel; break; + case 1: ldfun = cpu_ldl_super; break; default: - case 2: ldfun = ldl_user; break; + case 2: ldfun = cpu_ldl_user; break; } #endif @@ -564,32 +598,33 @@ void helper_lwm (target_ulong addr, target_ulong reglist, uint32_t mem_idx) target_ulong i; for (i = 0; i < base_reglist; i++) { - env->active_tc.gpr[multiple_regs[i]] = (target_long) ldfun(addr); + env->active_tc.gpr[multiple_regs[i]] = (target_long)ldfun(env, addr); addr += 4; } } if (do_r31) { - env->active_tc.gpr[31] = (target_long) ldfun(addr); + env->active_tc.gpr[31] = (target_long)ldfun(env, addr); } } -void helper_swm (target_ulong addr, target_ulong reglist, uint32_t mem_idx) +void helper_swm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, + uint32_t mem_idx) { target_ulong base_reglist = reglist & 0xf; target_ulong do_r31 = reglist & 0x10; #ifdef CONFIG_USER_ONLY #undef stfun -#define stfun stl_raw +#define stfun(env, addr, val) stl_raw(addr, val) #else - void (*stfun)(target_ulong, uint32_t); + void (*stfun)(CPUMIPSState *env, target_ulong, uint32_t); switch (mem_idx) { - case 0: stfun = stl_kernel; break; - case 1: stfun = stl_super; break; + case 0: stfun = cpu_stl_kernel; break; + case 1: stfun = cpu_stl_super; break; default: - case 2: stfun = stl_user; break; + case 2: stfun = cpu_stl_user; break; } #endif @@ -597,33 +632,34 @@ void helper_swm (target_ulong addr, target_ulong reglist, uint32_t mem_idx) target_ulong i; for (i = 0; i < base_reglist; i++) { - stfun(addr, env->active_tc.gpr[multiple_regs[i]]); + stfun(env, addr, env->active_tc.gpr[multiple_regs[i]]); addr += 4; } } if (do_r31) { - stfun(addr, env->active_tc.gpr[31]); + stfun(env, addr, env->active_tc.gpr[31]); } } #if defined(TARGET_MIPS64) -void helper_ldm (target_ulong addr, target_ulong reglist, uint32_t mem_idx) +void helper_ldm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, + uint32_t mem_idx) { target_ulong base_reglist = reglist & 0xf; target_ulong do_r31 = reglist & 0x10; #ifdef CONFIG_USER_ONLY #undef ldfun -#define ldfun ldq_raw +#define ldfun(env, addr) ldq_raw(addr) #else - uint64_t (*ldfun)(target_ulong); + uint64_t (*ldfun)(CPUMIPSState *env, target_ulong); switch (mem_idx) { - case 0: ldfun = ldq_kernel; break; - case 1: ldfun = ldq_super; break; + case 0: ldfun = cpu_ldq_kernel; break; + case 1: ldfun = cpu_ldq_super; break; default: - case 2: ldfun = ldq_user; break; + case 2: ldfun = cpu_ldq_user; break; } #endif @@ -631,32 +667,33 @@ void helper_ldm (target_ulong addr, target_ulong reglist, uint32_t mem_idx) target_ulong i; for (i = 0; i < base_reglist; i++) { - env->active_tc.gpr[multiple_regs[i]] = ldfun(addr); + env->active_tc.gpr[multiple_regs[i]] = ldfun(env, addr); addr += 8; } } if (do_r31) { - env->active_tc.gpr[31] = ldfun(addr); + env->active_tc.gpr[31] = ldfun(env, addr); } } -void helper_sdm (target_ulong addr, target_ulong reglist, uint32_t mem_idx) +void helper_sdm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, + uint32_t mem_idx) { target_ulong base_reglist = reglist & 0xf; target_ulong do_r31 = reglist & 0x10; #ifdef CONFIG_USER_ONLY #undef stfun -#define stfun stq_raw +#define stfun(env, addr, val) stq_raw(addr, val) #else - void (*stfun)(target_ulong, uint64_t); + void (*stfun)(CPUMIPSState *env, target_ulong, uint64_t); switch (mem_idx) { - case 0: stfun = stq_kernel; break; - case 1: stfun = stq_super; break; + case 0: stfun = cpu_stq_kernel; break; + case 1: stfun = cpu_stq_super; break; default: - case 2: stfun = stq_user; break; + case 2: stfun = cpu_stq_user; break; } #endif @@ -664,13 +701,13 @@ void helper_sdm (target_ulong addr, target_ulong reglist, uint32_t mem_idx) target_ulong i; for (i = 0; i < base_reglist; i++) { - stfun(addr, env->active_tc.gpr[multiple_regs[i]]); + stfun(env, addr, env->active_tc.gpr[multiple_regs[i]]); addr += 8; } } if (do_r31) { - stfun(addr, env->active_tc.gpr[31]); + stfun(env, addr, env->active_tc.gpr[31]); } } #endif @@ -723,7 +760,7 @@ static inline void mips_tc_sleep(CPUMIPSState *c, int tc) FIXME: This code assumes that all VPEs have the same number of TCs, which depends on runtime setup. Can probably be fixed by walking the list of CPUMIPSStates. */ -static CPUMIPSState *mips_cpu_map_tc(int *tc) +static CPUMIPSState *mips_cpu_map_tc(CPUMIPSState *env, int *tc) { CPUMIPSState *other; int vpe_idx, nr_threads = env->nr_threads; @@ -750,7 +787,7 @@ static CPUMIPSState *mips_cpu_map_tc(int *tc) These helper call synchronizes the regs for a given cpu. */ /* Called for updates to CP0_Status. */ -static void sync_c0_status(CPUMIPSState *cpu, int tc) +static void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc) { int32_t tcstatus, *tcst; uint32_t v = cpu->CP0_Status; @@ -785,7 +822,8 @@ static void sync_c0_status(CPUMIPSState *cpu, int tc) } /* Called for updates to CP0_TCStatus. */ -static void sync_c0_tcstatus(CPUMIPSState *cpu, int tc, target_ulong v) +static void sync_c0_tcstatus(CPUMIPSState *cpu, int tc, + target_ulong v) { uint32_t status; uint32_t tcu, tmx, tasid, tksu; @@ -834,35 +872,35 @@ static void sync_c0_entryhi(CPUMIPSState *cpu, int tc) } /* CP0 helpers */ -target_ulong helper_mfc0_mvpcontrol (void) +target_ulong helper_mfc0_mvpcontrol(CPUMIPSState *env) { return env->mvp->CP0_MVPControl; } -target_ulong helper_mfc0_mvpconf0 (void) +target_ulong helper_mfc0_mvpconf0(CPUMIPSState *env) { return env->mvp->CP0_MVPConf0; } -target_ulong helper_mfc0_mvpconf1 (void) +target_ulong helper_mfc0_mvpconf1(CPUMIPSState *env) { return env->mvp->CP0_MVPConf1; } -target_ulong helper_mfc0_random (void) +target_ulong helper_mfc0_random(CPUMIPSState *env) { return (int32_t)cpu_mips_get_random(env); } -target_ulong helper_mfc0_tcstatus (void) +target_ulong helper_mfc0_tcstatus(CPUMIPSState *env) { return env->active_tc.CP0_TCStatus; } -target_ulong helper_mftc0_tcstatus(void) +target_ulong helper_mftc0_tcstatus(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) return other->active_tc.CP0_TCStatus; @@ -870,15 +908,15 @@ target_ulong helper_mftc0_tcstatus(void) return other->tcs[other_tc].CP0_TCStatus; } -target_ulong helper_mfc0_tcbind (void) +target_ulong helper_mfc0_tcbind(CPUMIPSState *env) { return env->active_tc.CP0_TCBind; } -target_ulong helper_mftc0_tcbind(void) +target_ulong helper_mftc0_tcbind(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) return other->active_tc.CP0_TCBind; @@ -886,15 +924,15 @@ target_ulong helper_mftc0_tcbind(void) return other->tcs[other_tc].CP0_TCBind; } -target_ulong helper_mfc0_tcrestart (void) +target_ulong helper_mfc0_tcrestart(CPUMIPSState *env) { return env->active_tc.PC; } -target_ulong helper_mftc0_tcrestart(void) +target_ulong helper_mftc0_tcrestart(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) return other->active_tc.PC; @@ -902,15 +940,15 @@ target_ulong helper_mftc0_tcrestart(void) return other->tcs[other_tc].PC; } -target_ulong helper_mfc0_tchalt (void) +target_ulong helper_mfc0_tchalt(CPUMIPSState *env) { return env->active_tc.CP0_TCHalt; } -target_ulong helper_mftc0_tchalt(void) +target_ulong helper_mftc0_tchalt(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) return other->active_tc.CP0_TCHalt; @@ -918,15 +956,15 @@ target_ulong helper_mftc0_tchalt(void) return other->tcs[other_tc].CP0_TCHalt; } -target_ulong helper_mfc0_tccontext (void) +target_ulong helper_mfc0_tccontext(CPUMIPSState *env) { return env->active_tc.CP0_TCContext; } -target_ulong helper_mftc0_tccontext(void) +target_ulong helper_mftc0_tccontext(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) return other->active_tc.CP0_TCContext; @@ -934,15 +972,15 @@ target_ulong helper_mftc0_tccontext(void) return other->tcs[other_tc].CP0_TCContext; } -target_ulong helper_mfc0_tcschedule (void) +target_ulong helper_mfc0_tcschedule(CPUMIPSState *env) { return env->active_tc.CP0_TCSchedule; } -target_ulong helper_mftc0_tcschedule(void) +target_ulong helper_mftc0_tcschedule(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) return other->active_tc.CP0_TCSchedule; @@ -950,15 +988,15 @@ target_ulong helper_mftc0_tcschedule(void) return other->tcs[other_tc].CP0_TCSchedule; } -target_ulong helper_mfc0_tcschefback (void) +target_ulong helper_mfc0_tcschefback(CPUMIPSState *env) { return env->active_tc.CP0_TCScheFBack; } -target_ulong helper_mftc0_tcschefback(void) +target_ulong helper_mftc0_tcschefback(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) return other->active_tc.CP0_TCScheFBack; @@ -966,24 +1004,24 @@ target_ulong helper_mftc0_tcschefback(void) return other->tcs[other_tc].CP0_TCScheFBack; } -target_ulong helper_mfc0_count (void) +target_ulong helper_mfc0_count(CPUMIPSState *env) { return (int32_t)cpu_mips_get_count(env); } -target_ulong helper_mftc0_entryhi(void) +target_ulong helper_mftc0_entryhi(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); return other->CP0_EntryHi; } -target_ulong helper_mftc0_cause(void) +target_ulong helper_mftc0_cause(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); int32_t tccause; - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) { tccause = other->CP0_Cause; @@ -994,30 +1032,30 @@ target_ulong helper_mftc0_cause(void) return tccause; } -target_ulong helper_mftc0_status(void) +target_ulong helper_mftc0_status(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); return other->CP0_Status; } -target_ulong helper_mfc0_lladdr (void) +target_ulong helper_mfc0_lladdr(CPUMIPSState *env) { return (int32_t)(env->lladdr >> env->CP0_LLAddr_shift); } -target_ulong helper_mfc0_watchlo (uint32_t sel) +target_ulong helper_mfc0_watchlo(CPUMIPSState *env, uint32_t sel) { return (int32_t)env->CP0_WatchLo[sel]; } -target_ulong helper_mfc0_watchhi (uint32_t sel) +target_ulong helper_mfc0_watchhi(CPUMIPSState *env, uint32_t sel) { return env->CP0_WatchHi[sel]; } -target_ulong helper_mfc0_debug (void) +target_ulong helper_mfc0_debug(CPUMIPSState *env) { target_ulong t0 = env->CP0_Debug; if (env->hflags & MIPS_HFLAG_DM) @@ -1026,11 +1064,11 @@ target_ulong helper_mfc0_debug (void) return t0; } -target_ulong helper_mftc0_debug(void) +target_ulong helper_mftc0_debug(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); int32_t tcstatus; - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) tcstatus = other->active_tc.CP0_Debug_tcstatus; @@ -1043,43 +1081,43 @@ target_ulong helper_mftc0_debug(void) } #if defined(TARGET_MIPS64) -target_ulong helper_dmfc0_tcrestart (void) +target_ulong helper_dmfc0_tcrestart(CPUMIPSState *env) { return env->active_tc.PC; } -target_ulong helper_dmfc0_tchalt (void) +target_ulong helper_dmfc0_tchalt(CPUMIPSState *env) { return env->active_tc.CP0_TCHalt; } -target_ulong helper_dmfc0_tccontext (void) +target_ulong helper_dmfc0_tccontext(CPUMIPSState *env) { return env->active_tc.CP0_TCContext; } -target_ulong helper_dmfc0_tcschedule (void) +target_ulong helper_dmfc0_tcschedule(CPUMIPSState *env) { return env->active_tc.CP0_TCSchedule; } -target_ulong helper_dmfc0_tcschefback (void) +target_ulong helper_dmfc0_tcschefback(CPUMIPSState *env) { return env->active_tc.CP0_TCScheFBack; } -target_ulong helper_dmfc0_lladdr (void) +target_ulong helper_dmfc0_lladdr(CPUMIPSState *env) { return env->lladdr >> env->CP0_LLAddr_shift; } -target_ulong helper_dmfc0_watchlo (uint32_t sel) +target_ulong helper_dmfc0_watchlo(CPUMIPSState *env, uint32_t sel) { return env->CP0_WatchLo[sel]; } #endif /* TARGET_MIPS64 */ -void helper_mtc0_index (target_ulong arg1) +void helper_mtc0_index(CPUMIPSState *env, target_ulong arg1) { int num = 1; unsigned int tmp = env->tlb->nb_tlb; @@ -1091,7 +1129,7 @@ void helper_mtc0_index (target_ulong arg1) env->CP0_Index = (env->CP0_Index & 0x80000000) | (arg1 & (num - 1)); } -void helper_mtc0_mvpcontrol (target_ulong arg1) +void helper_mtc0_mvpcontrol(CPUMIPSState *env, target_ulong arg1) { uint32_t mask = 0; uint32_t newval; @@ -1108,7 +1146,7 @@ void helper_mtc0_mvpcontrol (target_ulong arg1) env->mvp->CP0_MVPControl = newval; } -void helper_mtc0_vpecontrol (target_ulong arg1) +void helper_mtc0_vpecontrol(CPUMIPSState *env, target_ulong arg1) { uint32_t mask; uint32_t newval; @@ -1125,10 +1163,10 @@ void helper_mtc0_vpecontrol (target_ulong arg1) env->CP0_VPEControl = newval; } -void helper_mttc0_vpecontrol(target_ulong arg1) +void helper_mttc0_vpecontrol(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); uint32_t mask; uint32_t newval; @@ -1141,23 +1179,23 @@ void helper_mttc0_vpecontrol(target_ulong arg1) other->CP0_VPEControl = newval; } -target_ulong helper_mftc0_vpecontrol(void) +target_ulong helper_mftc0_vpecontrol(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); /* FIXME: Mask away return zero on read bits. */ return other->CP0_VPEControl; } -target_ulong helper_mftc0_vpeconf0(void) +target_ulong helper_mftc0_vpeconf0(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); return other->CP0_VPEConf0; } -void helper_mtc0_vpeconf0 (target_ulong arg1) +void helper_mtc0_vpeconf0(CPUMIPSState *env, target_ulong arg1) { uint32_t mask = 0; uint32_t newval; @@ -1174,10 +1212,10 @@ void helper_mtc0_vpeconf0 (target_ulong arg1) env->CP0_VPEConf0 = newval; } -void helper_mttc0_vpeconf0(target_ulong arg1) +void helper_mttc0_vpeconf0(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); uint32_t mask = 0; uint32_t newval; @@ -1188,7 +1226,7 @@ void helper_mttc0_vpeconf0(target_ulong arg1) other->CP0_VPEConf0 = newval; } -void helper_mtc0_vpeconf1 (target_ulong arg1) +void helper_mtc0_vpeconf1(CPUMIPSState *env, target_ulong arg1) { uint32_t mask = 0; uint32_t newval; @@ -1206,25 +1244,25 @@ void helper_mtc0_vpeconf1 (target_ulong arg1) env->CP0_VPEConf1 = newval; } -void helper_mtc0_yqmask (target_ulong arg1) +void helper_mtc0_yqmask(CPUMIPSState *env, target_ulong arg1) { /* Yield qualifier inputs not implemented. */ env->CP0_YQMask = 0x00000000; } -void helper_mtc0_vpeopt (target_ulong arg1) +void helper_mtc0_vpeopt(CPUMIPSState *env, target_ulong arg1) { env->CP0_VPEOpt = arg1 & 0x0000ffff; } -void helper_mtc0_entrylo0 (target_ulong arg1) +void helper_mtc0_entrylo0(CPUMIPSState *env, target_ulong arg1) { /* Large physaddr (PABITS) not implemented */ /* 1k pages not implemented */ env->CP0_EntryLo0 = arg1 & 0x3FFFFFFF; } -void helper_mtc0_tcstatus (target_ulong arg1) +void helper_mtc0_tcstatus(CPUMIPSState *env, target_ulong arg1) { uint32_t mask = env->CP0_TCStatus_rw_bitmask; uint32_t newval; @@ -1235,10 +1273,10 @@ void helper_mtc0_tcstatus (target_ulong arg1) sync_c0_tcstatus(env, env->current_tc, newval); } -void helper_mttc0_tcstatus (target_ulong arg1) +void helper_mttc0_tcstatus(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) other->active_tc.CP0_TCStatus = arg1; @@ -1247,7 +1285,7 @@ void helper_mttc0_tcstatus (target_ulong arg1) sync_c0_tcstatus(other, other_tc, arg1); } -void helper_mtc0_tcbind (target_ulong arg1) +void helper_mtc0_tcbind(CPUMIPSState *env, target_ulong arg1) { uint32_t mask = (1 << CP0TCBd_TBE); uint32_t newval; @@ -1258,12 +1296,12 @@ void helper_mtc0_tcbind (target_ulong arg1) env->active_tc.CP0_TCBind = newval; } -void helper_mttc0_tcbind (target_ulong arg1) +void helper_mttc0_tcbind(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); uint32_t mask = (1 << CP0TCBd_TBE); uint32_t newval; - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) mask |= (1 << CP0TCBd_CurVPE); @@ -1276,7 +1314,7 @@ void helper_mttc0_tcbind (target_ulong arg1) } } -void helper_mtc0_tcrestart (target_ulong arg1) +void helper_mtc0_tcrestart(CPUMIPSState *env, target_ulong arg1) { env->active_tc.PC = arg1; env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS); @@ -1284,10 +1322,10 @@ void helper_mtc0_tcrestart (target_ulong arg1) /* MIPS16 not implemented. */ } -void helper_mttc0_tcrestart (target_ulong arg1) +void helper_mttc0_tcrestart(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) { other->active_tc.PC = arg1; @@ -1302,7 +1340,7 @@ void helper_mttc0_tcrestart (target_ulong arg1) } } -void helper_mtc0_tchalt (target_ulong arg1) +void helper_mtc0_tchalt(CPUMIPSState *env, target_ulong arg1) { env->active_tc.CP0_TCHalt = arg1 & 0x1; @@ -1314,10 +1352,10 @@ void helper_mtc0_tchalt (target_ulong arg1) } } -void helper_mttc0_tchalt (target_ulong arg1) +void helper_mttc0_tchalt(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); // TODO: Halt TC / Restart (if allocated+active) TC. @@ -1333,15 +1371,15 @@ void helper_mttc0_tchalt (target_ulong arg1) } } -void helper_mtc0_tccontext (target_ulong arg1) +void helper_mtc0_tccontext(CPUMIPSState *env, target_ulong arg1) { env->active_tc.CP0_TCContext = arg1; } -void helper_mttc0_tccontext (target_ulong arg1) +void helper_mttc0_tccontext(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) other->active_tc.CP0_TCContext = arg1; @@ -1349,15 +1387,15 @@ void helper_mttc0_tccontext (target_ulong arg1) other->tcs[other_tc].CP0_TCContext = arg1; } -void helper_mtc0_tcschedule (target_ulong arg1) +void helper_mtc0_tcschedule(CPUMIPSState *env, target_ulong arg1) { env->active_tc.CP0_TCSchedule = arg1; } -void helper_mttc0_tcschedule (target_ulong arg1) +void helper_mttc0_tcschedule(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) other->active_tc.CP0_TCSchedule = arg1; @@ -1365,15 +1403,15 @@ void helper_mttc0_tcschedule (target_ulong arg1) other->tcs[other_tc].CP0_TCSchedule = arg1; } -void helper_mtc0_tcschefback (target_ulong arg1) +void helper_mtc0_tcschefback(CPUMIPSState *env, target_ulong arg1) { env->active_tc.CP0_TCScheFBack = arg1; } -void helper_mttc0_tcschefback (target_ulong arg1) +void helper_mttc0_tcschefback(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) other->active_tc.CP0_TCScheFBack = arg1; @@ -1381,25 +1419,25 @@ void helper_mttc0_tcschefback (target_ulong arg1) other->tcs[other_tc].CP0_TCScheFBack = arg1; } -void helper_mtc0_entrylo1 (target_ulong arg1) +void helper_mtc0_entrylo1(CPUMIPSState *env, target_ulong arg1) { /* Large physaddr (PABITS) not implemented */ /* 1k pages not implemented */ env->CP0_EntryLo1 = arg1 & 0x3FFFFFFF; } -void helper_mtc0_context (target_ulong arg1) +void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1) { env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF); } -void helper_mtc0_pagemask (target_ulong arg1) +void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1) { /* 1k pages not implemented */ env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1)); } -void helper_mtc0_pagegrain (target_ulong arg1) +void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1) { /* SmartMIPS not implemented */ /* Large physaddr (PABITS) not implemented */ @@ -1407,47 +1445,47 @@ void helper_mtc0_pagegrain (target_ulong arg1) env->CP0_PageGrain = 0; } -void helper_mtc0_wired (target_ulong arg1) +void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1) { env->CP0_Wired = arg1 % env->tlb->nb_tlb; } -void helper_mtc0_srsconf0 (target_ulong arg1) +void helper_mtc0_srsconf0(CPUMIPSState *env, target_ulong arg1) { env->CP0_SRSConf0 |= arg1 & env->CP0_SRSConf0_rw_bitmask; } -void helper_mtc0_srsconf1 (target_ulong arg1) +void helper_mtc0_srsconf1(CPUMIPSState *env, target_ulong arg1) { env->CP0_SRSConf1 |= arg1 & env->CP0_SRSConf1_rw_bitmask; } -void helper_mtc0_srsconf2 (target_ulong arg1) +void helper_mtc0_srsconf2(CPUMIPSState *env, target_ulong arg1) { env->CP0_SRSConf2 |= arg1 & env->CP0_SRSConf2_rw_bitmask; } -void helper_mtc0_srsconf3 (target_ulong arg1) +void helper_mtc0_srsconf3(CPUMIPSState *env, target_ulong arg1) { env->CP0_SRSConf3 |= arg1 & env->CP0_SRSConf3_rw_bitmask; } -void helper_mtc0_srsconf4 (target_ulong arg1) +void helper_mtc0_srsconf4(CPUMIPSState *env, target_ulong arg1) { env->CP0_SRSConf4 |= arg1 & env->CP0_SRSConf4_rw_bitmask; } -void helper_mtc0_hwrena (target_ulong arg1) +void helper_mtc0_hwrena(CPUMIPSState *env, target_ulong arg1) { env->CP0_HWREna = arg1 & 0x0000000F; } -void helper_mtc0_count (target_ulong arg1) +void helper_mtc0_count(CPUMIPSState *env, target_ulong arg1) { cpu_mips_store_count(env, arg1); } -void helper_mtc0_entryhi (target_ulong arg1) +void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1) { target_ulong old, val; @@ -1466,21 +1504,21 @@ void helper_mtc0_entryhi (target_ulong arg1) cpu_mips_tlb_flush(env, 1); } -void helper_mttc0_entryhi(target_ulong arg1) +void helper_mttc0_entryhi(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); other->CP0_EntryHi = arg1; sync_c0_entryhi(other, other_tc); } -void helper_mtc0_compare (target_ulong arg1) +void helper_mtc0_compare(CPUMIPSState *env, target_ulong arg1) { cpu_mips_store_compare(env, arg1); } -void helper_mtc0_status (target_ulong arg1) +void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1) { uint32_t val, old; uint32_t mask = env->CP0_Status_rw_bitmask; @@ -1489,7 +1527,7 @@ void helper_mtc0_status (target_ulong arg1) old = env->CP0_Status; env->CP0_Status = (env->CP0_Status & ~mask) | val; if (env->CP0_Config3 & (1 << CP0C3_MT)) { - sync_c0_status(env, env->current_tc); + sync_c0_status(env, env, env->current_tc); } else { compute_hflags(env); } @@ -1508,22 +1546,22 @@ void helper_mtc0_status (target_ulong arg1) } } -void helper_mttc0_status(target_ulong arg1) +void helper_mttc0_status(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); other->CP0_Status = arg1 & ~0xf1000018; - sync_c0_status(other, other_tc); + sync_c0_status(env, other, other_tc); } -void helper_mtc0_intctl (target_ulong arg1) +void helper_mtc0_intctl(CPUMIPSState *env, target_ulong arg1) { /* vectored interrupts not implemented, no performance counters. */ env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000003e0) | (arg1 & 0x000003e0); } -void helper_mtc0_srsctl (target_ulong arg1) +void helper_mtc0_srsctl(CPUMIPSState *env, target_ulong arg1) { uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS); env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (arg1 & mask); @@ -1557,52 +1595,52 @@ static void mtc0_cause(CPUMIPSState *cpu, target_ulong arg1) } } -void helper_mtc0_cause(target_ulong arg1) +void helper_mtc0_cause(CPUMIPSState *env, target_ulong arg1) { mtc0_cause(env, arg1); } -void helper_mttc0_cause(target_ulong arg1) +void helper_mttc0_cause(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); mtc0_cause(other, arg1); } -target_ulong helper_mftc0_epc(void) +target_ulong helper_mftc0_epc(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); return other->CP0_EPC; } -target_ulong helper_mftc0_ebase(void) +target_ulong helper_mftc0_ebase(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); return other->CP0_EBase; } -void helper_mtc0_ebase (target_ulong arg1) +void helper_mtc0_ebase(CPUMIPSState *env, target_ulong arg1) { /* vectored interrupts not implemented */ env->CP0_EBase = (env->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000); } -void helper_mttc0_ebase(target_ulong arg1) +void helper_mttc0_ebase(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); other->CP0_EBase = (other->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000); } -target_ulong helper_mftc0_configx(target_ulong idx) +target_ulong helper_mftc0_configx(CPUMIPSState *env, target_ulong idx) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); switch (idx) { case 0: return other->CP0_Config0; @@ -1618,49 +1656,49 @@ target_ulong helper_mftc0_configx(target_ulong idx) return 0; } -void helper_mtc0_config0 (target_ulong arg1) +void helper_mtc0_config0(CPUMIPSState *env, target_ulong arg1) { env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (arg1 & 0x00000007); } -void helper_mtc0_config2 (target_ulong arg1) +void helper_mtc0_config2(CPUMIPSState *env, target_ulong arg1) { /* tertiary/secondary caches not implemented */ env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF); } -void helper_mtc0_lladdr (target_ulong arg1) +void helper_mtc0_lladdr(CPUMIPSState *env, target_ulong arg1) { target_long mask = env->CP0_LLAddr_rw_bitmask; arg1 = arg1 << env->CP0_LLAddr_shift; env->lladdr = (env->lladdr & ~mask) | (arg1 & mask); } -void helper_mtc0_watchlo (target_ulong arg1, uint32_t sel) +void helper_mtc0_watchlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel) { /* Watch exceptions for instructions, data loads, data stores not implemented. */ env->CP0_WatchLo[sel] = (arg1 & ~0x7); } -void helper_mtc0_watchhi (target_ulong arg1, uint32_t sel) +void helper_mtc0_watchhi(CPUMIPSState *env, target_ulong arg1, uint32_t sel) { env->CP0_WatchHi[sel] = (arg1 & 0x40FF0FF8); env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7); } -void helper_mtc0_xcontext (target_ulong arg1) +void helper_mtc0_xcontext(CPUMIPSState *env, target_ulong arg1) { target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1; env->CP0_XContext = (env->CP0_XContext & mask) | (arg1 & ~mask); } -void helper_mtc0_framemask (target_ulong arg1) +void helper_mtc0_framemask(CPUMIPSState *env, target_ulong arg1) { env->CP0_Framemask = arg1; /* XXX */ } -void helper_mtc0_debug (target_ulong arg1) +void helper_mtc0_debug(CPUMIPSState *env, target_ulong arg1) { env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (arg1 & 0x13300120); if (arg1 & (1 << CP0DB_DM)) @@ -1669,11 +1707,11 @@ void helper_mtc0_debug (target_ulong arg1) env->hflags &= ~MIPS_HFLAG_DM; } -void helper_mttc0_debug(target_ulong arg1) +void helper_mttc0_debug(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); uint32_t val = arg1 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); /* XXX: Might be wrong, check with EJTAG spec. */ if (other_tc == other->current_tc) @@ -1685,36 +1723,36 @@ void helper_mttc0_debug(target_ulong arg1) (arg1 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))); } -void helper_mtc0_performance0 (target_ulong arg1) +void helper_mtc0_performance0(CPUMIPSState *env, target_ulong arg1) { env->CP0_Performance0 = arg1 & 0x000007ff; } -void helper_mtc0_taglo (target_ulong arg1) +void helper_mtc0_taglo(CPUMIPSState *env, target_ulong arg1) { env->CP0_TagLo = arg1 & 0xFFFFFCF6; } -void helper_mtc0_datalo (target_ulong arg1) +void helper_mtc0_datalo(CPUMIPSState *env, target_ulong arg1) { env->CP0_DataLo = arg1; /* XXX */ } -void helper_mtc0_taghi (target_ulong arg1) +void helper_mtc0_taghi(CPUMIPSState *env, target_ulong arg1) { env->CP0_TagHi = arg1; /* XXX */ } -void helper_mtc0_datahi (target_ulong arg1) +void helper_mtc0_datahi(CPUMIPSState *env, target_ulong arg1) { env->CP0_DataHi = arg1; /* XXX */ } /* MIPS MT functions */ -target_ulong helper_mftgpr(uint32_t sel) +target_ulong helper_mftgpr(CPUMIPSState *env, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) return other->active_tc.gpr[sel]; @@ -1722,10 +1760,10 @@ target_ulong helper_mftgpr(uint32_t sel) return other->tcs[other_tc].gpr[sel]; } -target_ulong helper_mftlo(uint32_t sel) +target_ulong helper_mftlo(CPUMIPSState *env, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) return other->active_tc.LO[sel]; @@ -1733,10 +1771,10 @@ target_ulong helper_mftlo(uint32_t sel) return other->tcs[other_tc].LO[sel]; } -target_ulong helper_mfthi(uint32_t sel) +target_ulong helper_mfthi(CPUMIPSState *env, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) return other->active_tc.HI[sel]; @@ -1744,10 +1782,10 @@ target_ulong helper_mfthi(uint32_t sel) return other->tcs[other_tc].HI[sel]; } -target_ulong helper_mftacx(uint32_t sel) +target_ulong helper_mftacx(CPUMIPSState *env, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) return other->active_tc.ACX[sel]; @@ -1755,10 +1793,10 @@ target_ulong helper_mftacx(uint32_t sel) return other->tcs[other_tc].ACX[sel]; } -target_ulong helper_mftdsp(void) +target_ulong helper_mftdsp(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) return other->active_tc.DSPControl; @@ -1766,10 +1804,10 @@ target_ulong helper_mftdsp(void) return other->tcs[other_tc].DSPControl; } -void helper_mttgpr(target_ulong arg1, uint32_t sel) +void helper_mttgpr(CPUMIPSState *env, target_ulong arg1, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) other->active_tc.gpr[sel] = arg1; @@ -1777,10 +1815,10 @@ void helper_mttgpr(target_ulong arg1, uint32_t sel) other->tcs[other_tc].gpr[sel] = arg1; } -void helper_mttlo(target_ulong arg1, uint32_t sel) +void helper_mttlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) other->active_tc.LO[sel] = arg1; @@ -1788,10 +1826,10 @@ void helper_mttlo(target_ulong arg1, uint32_t sel) other->tcs[other_tc].LO[sel] = arg1; } -void helper_mtthi(target_ulong arg1, uint32_t sel) +void helper_mtthi(CPUMIPSState *env, target_ulong arg1, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) other->active_tc.HI[sel] = arg1; @@ -1799,10 +1837,10 @@ void helper_mtthi(target_ulong arg1, uint32_t sel) other->tcs[other_tc].HI[sel] = arg1; } -void helper_mttacx(target_ulong arg1, uint32_t sel) +void helper_mttacx(CPUMIPSState *env, target_ulong arg1, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) other->active_tc.ACX[sel] = arg1; @@ -1810,10 +1848,10 @@ void helper_mttacx(target_ulong arg1, uint32_t sel) other->tcs[other_tc].ACX[sel] = arg1; } -void helper_mttdsp(target_ulong arg1) +void helper_mttdsp(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - CPUMIPSState *other = mips_cpu_map_tc(&other_tc); + CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); if (other_tc == other->current_tc) other->active_tc.DSPControl = arg1; @@ -1834,7 +1872,7 @@ target_ulong helper_emt(void) return 0; } -target_ulong helper_dvpe(void) +target_ulong helper_dvpe(CPUMIPSState *env) { CPUMIPSState *other_cpu = first_cpu; target_ulong prev = env->mvp->CP0_MVPControl; @@ -1850,7 +1888,7 @@ target_ulong helper_dvpe(void) return prev; } -target_ulong helper_evpe(void) +target_ulong helper_evpe(CPUMIPSState *env) { CPUMIPSState *other_cpu = first_cpu; target_ulong prev = env->mvp->CP0_MVPControl; @@ -1876,7 +1914,7 @@ void helper_fork(target_ulong arg1, target_ulong arg2) // TODO: store to TC register } -target_ulong helper_yield(target_ulong arg) +target_ulong helper_yield(CPUMIPSState *env, target_ulong arg) { target_long arg1 = arg; @@ -1887,13 +1925,13 @@ target_ulong helper_yield(target_ulong arg) env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) { env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT; - helper_raise_exception(EXCP_THREAD); + helper_raise_exception(env, EXCP_THREAD); } } } else if (arg1 == 0) { if (0 /* TODO: TC underflow */) { env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); - helper_raise_exception(EXCP_THREAD); + helper_raise_exception(env, EXCP_THREAD); } else { // TODO: Deallocate TC } @@ -1901,7 +1939,7 @@ target_ulong helper_yield(target_ulong arg) /* Yield qualifier inputs not implemented. */ env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT; - helper_raise_exception(EXCP_THREAD); + helper_raise_exception(env, EXCP_THREAD); } return env->CP0_YQMask; } @@ -1923,7 +1961,7 @@ static void r4k_mips_tlb_flush_extra (CPUMIPSState *env, int first) } } -static void r4k_fill_tlb (int idx) +static void r4k_fill_tlb(CPUMIPSState *env, int idx) { r4k_tlb_t *tlb; @@ -1946,7 +1984,7 @@ static void r4k_fill_tlb (int idx) tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12; } -void r4k_helper_tlbwi (void) +void r4k_helper_tlbwi(CPUMIPSState *env) { int idx; @@ -1958,18 +1996,18 @@ void r4k_helper_tlbwi (void) r4k_mips_tlb_flush_extra (env, env->tlb->nb_tlb); r4k_invalidate_tlb(env, idx, 0); - r4k_fill_tlb(idx); + r4k_fill_tlb(env, idx); } -void r4k_helper_tlbwr (void) +void r4k_helper_tlbwr(CPUMIPSState *env) { int r = cpu_mips_get_random(env); r4k_invalidate_tlb(env, r, 1); - r4k_fill_tlb(r); + r4k_fill_tlb(env, r); } -void r4k_helper_tlbp (void) +void r4k_helper_tlbp(CPUMIPSState *env) { r4k_tlb_t *tlb; target_ulong mask; @@ -2011,7 +2049,7 @@ void r4k_helper_tlbp (void) } } -void r4k_helper_tlbr (void) +void r4k_helper_tlbr(CPUMIPSState *env) { r4k_tlb_t *tlb; uint8_t ASID; @@ -2035,28 +2073,28 @@ void r4k_helper_tlbr (void) (tlb->C1 << 3) | (tlb->PFN[1] >> 6); } -void helper_tlbwi(void) +void helper_tlbwi(CPUMIPSState *env) { - env->tlb->helper_tlbwi(); + env->tlb->helper_tlbwi(env); } -void helper_tlbwr(void) +void helper_tlbwr(CPUMIPSState *env) { - env->tlb->helper_tlbwr(); + env->tlb->helper_tlbwr(env); } -void helper_tlbp(void) +void helper_tlbp(CPUMIPSState *env) { - env->tlb->helper_tlbp(); + env->tlb->helper_tlbp(env); } -void helper_tlbr(void) +void helper_tlbr(CPUMIPSState *env) { - env->tlb->helper_tlbr(); + env->tlb->helper_tlbr(env); } /* Specials */ -target_ulong helper_di (void) +target_ulong helper_di(CPUMIPSState *env) { target_ulong t0 = env->CP0_Status; @@ -2064,7 +2102,7 @@ target_ulong helper_di (void) return t0; } -target_ulong helper_ei (void) +target_ulong helper_ei(CPUMIPSState *env) { target_ulong t0 = env->CP0_Status; @@ -2072,7 +2110,7 @@ target_ulong helper_ei (void) return t0; } -static void debug_pre_eret (void) +static void debug_pre_eret(CPUMIPSState *env) { if (qemu_loglevel_mask(CPU_LOG_EXEC)) { qemu_log("ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx, @@ -2085,7 +2123,7 @@ static void debug_pre_eret (void) } } -static void debug_post_eret (void) +static void debug_post_eret(CPUMIPSState *env) { if (qemu_loglevel_mask(CPU_LOG_EXEC)) { qemu_log(" => PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx, @@ -2103,7 +2141,7 @@ static void debug_post_eret (void) } } -static void set_pc (target_ulong error_pc) +static void set_pc(CPUMIPSState *env, target_ulong error_pc) { env->active_tc.PC = error_pc & ~(target_ulong)1; if (error_pc & 1) { @@ -2113,78 +2151,78 @@ static void set_pc (target_ulong error_pc) } } -void helper_eret (void) +void helper_eret(CPUMIPSState *env) { - debug_pre_eret(); + debug_pre_eret(env); if (env->CP0_Status & (1 << CP0St_ERL)) { - set_pc(env->CP0_ErrorEPC); + set_pc(env, env->CP0_ErrorEPC); env->CP0_Status &= ~(1 << CP0St_ERL); } else { - set_pc(env->CP0_EPC); + set_pc(env, env->CP0_EPC); env->CP0_Status &= ~(1 << CP0St_EXL); } compute_hflags(env); - debug_post_eret(); + debug_post_eret(env); env->lladdr = 1; } -void helper_deret (void) +void helper_deret(CPUMIPSState *env) { - debug_pre_eret(); - set_pc(env->CP0_DEPC); + debug_pre_eret(env); + set_pc(env, env->CP0_DEPC); env->hflags &= MIPS_HFLAG_DM; compute_hflags(env); - debug_post_eret(); + debug_post_eret(env); env->lladdr = 1; } #endif /* !CONFIG_USER_ONLY */ -target_ulong helper_rdhwr_cpunum(void) +target_ulong helper_rdhwr_cpunum(CPUMIPSState *env) { if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << 0))) return env->CP0_EBase & 0x3ff; else - helper_raise_exception(EXCP_RI); + helper_raise_exception(env, EXCP_RI); return 0; } -target_ulong helper_rdhwr_synci_step(void) +target_ulong helper_rdhwr_synci_step(CPUMIPSState *env) { if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << 1))) return env->SYNCI_Step; else - helper_raise_exception(EXCP_RI); + helper_raise_exception(env, EXCP_RI); return 0; } -target_ulong helper_rdhwr_cc(void) +target_ulong helper_rdhwr_cc(CPUMIPSState *env) { if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << 2))) return env->CP0_Count; else - helper_raise_exception(EXCP_RI); + helper_raise_exception(env, EXCP_RI); return 0; } -target_ulong helper_rdhwr_ccres(void) +target_ulong helper_rdhwr_ccres(CPUMIPSState *env) { if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << 3))) return env->CCRes; else - helper_raise_exception(EXCP_RI); + helper_raise_exception(env, EXCP_RI); return 0; } -void helper_pmon (int function) +void helper_pmon(CPUMIPSState *env, int function) { function /= 2; switch (function) { @@ -2210,16 +2248,17 @@ void helper_pmon (int function) } } -void helper_wait (void) +void helper_wait(CPUMIPSState *env) { env->halted = 1; cpu_reset_interrupt(env, CPU_INTERRUPT_WAKE); - helper_raise_exception(EXCP_HLT); + helper_raise_exception(env, EXCP_HLT); } #if !defined(CONFIG_USER_ONLY) -static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write, +static void QEMU_NORETURN do_unaligned_access(CPUMIPSState *env, + target_ulong addr, int is_write, int is_user, uintptr_t retaddr); #define MMUSUFFIX _mmu @@ -2237,23 +2276,20 @@ static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write, #define SHIFT 3 #include "softmmu_template.h" -static void do_unaligned_access(target_ulong addr, int is_write, - int is_user, uintptr_t retaddr) +static void do_unaligned_access(CPUMIPSState *env, target_ulong addr, + int is_write, int is_user, uintptr_t retaddr) { env->CP0_BadVAddr = addr; - do_restore_state (retaddr); - helper_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL); + do_restore_state(env, retaddr); + helper_raise_exception(env, (is_write == 1) ? EXCP_AdES : EXCP_AdEL); } -void tlb_fill(CPUMIPSState *env1, target_ulong addr, int is_write, int mmu_idx, +void tlb_fill(CPUMIPSState *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { TranslationBlock *tb; - CPUMIPSState *saved_env; int ret; - saved_env = env; - env = env1; ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx); if (ret) { if (retaddr) { @@ -2265,20 +2301,17 @@ void tlb_fill(CPUMIPSState *env1, target_ulong addr, int is_write, int mmu_idx, cpu_restore_state(tb, env, retaddr); } } - helper_raise_exception_err(env->exception_index, env->error_code); + helper_raise_exception_err(env, env->exception_index, env->error_code); } - env = saved_env; } -void cpu_unassigned_access(CPUMIPSState *env1, target_phys_addr_t addr, +void cpu_unassigned_access(CPUMIPSState *env, target_phys_addr_t addr, int is_write, int is_exec, int unused, int size) { - env = env1; - if (is_exec) - helper_raise_exception(EXCP_IBE); + helper_raise_exception(env, EXCP_IBE); else - helper_raise_exception(EXCP_DBE); + helper_raise_exception(env, EXCP_DBE); } #endif /* !CONFIG_USER_ONLY */ @@ -2307,7 +2340,7 @@ static unsigned int ieee_rm[] = { #define RESTORE_FLUSH_MODE \ set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0, &env->active_fpu.fp_status); -target_ulong helper_cfc1 (uint32_t reg) +target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg) { target_ulong arg1; @@ -2332,7 +2365,7 @@ target_ulong helper_cfc1 (uint32_t reg) return arg1; } -void helper_ctc1 (target_ulong arg1, uint32_t reg) +void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t reg) { switch(reg) { case 25: @@ -2366,7 +2399,7 @@ void helper_ctc1 (target_ulong arg1, uint32_t reg) RESTORE_FLUSH_MODE; set_float_exception_flags(0, &env->active_fpu.fp_status); if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31)) - helper_raise_exception(EXCP_FPE); + helper_raise_exception(env, EXCP_FPE); } static inline int ieee_ex_to_mips(int xcpt) @@ -2392,13 +2425,13 @@ static inline int ieee_ex_to_mips(int xcpt) return ret; } -static inline void update_fcr31(void) +static inline void update_fcr31(CPUMIPSState *env) { int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->active_fpu.fp_status)); SET_FP_CAUSE(env->active_fpu.fcr31, tmp); if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp) - helper_raise_exception(EXCP_FPE); + helper_raise_exception(env, EXCP_FPE); else UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp); } @@ -2409,71 +2442,71 @@ static inline void update_fcr31(void) paired single lower "pl", paired single upper "pu". */ /* unary operations, modifying fp status */ -uint64_t helper_float_sqrt_d(uint64_t fdt0) +uint64_t helper_float_sqrt_d(CPUMIPSState *env, uint64_t fdt0) { return float64_sqrt(fdt0, &env->active_fpu.fp_status); } -uint32_t helper_float_sqrt_s(uint32_t fst0) +uint32_t helper_float_sqrt_s(CPUMIPSState *env, uint32_t fst0) { return float32_sqrt(fst0, &env->active_fpu.fp_status); } -uint64_t helper_float_cvtd_s(uint32_t fst0) +uint64_t helper_float_cvtd_s(CPUMIPSState *env, uint32_t fst0) { uint64_t fdt2; set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return fdt2; } -uint64_t helper_float_cvtd_w(uint32_t wt0) +uint64_t helper_float_cvtd_w(CPUMIPSState *env, uint32_t wt0) { uint64_t fdt2; set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return fdt2; } -uint64_t helper_float_cvtd_l(uint64_t dt0) +uint64_t helper_float_cvtd_l(CPUMIPSState *env, uint64_t dt0) { uint64_t fdt2; set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return fdt2; } -uint64_t helper_float_cvtl_d(uint64_t fdt0) +uint64_t helper_float_cvtl_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t dt2; set_float_exception_flags(0, &env->active_fpu.fp_status); dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) dt2 = FLOAT_SNAN64; return dt2; } -uint64_t helper_float_cvtl_s(uint32_t fst0) +uint64_t helper_float_cvtl_s(CPUMIPSState *env, uint32_t fst0) { uint64_t dt2; set_float_exception_flags(0, &env->active_fpu.fp_status); dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) dt2 = FLOAT_SNAN64; return dt2; } -uint64_t helper_float_cvtps_pw(uint64_t dt0) +uint64_t helper_float_cvtps_pw(CPUMIPSState *env, uint64_t dt0) { uint32_t fst2; uint32_t fsth2; @@ -2481,11 +2514,11 @@ uint64_t helper_float_cvtps_pw(uint64_t dt0) set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return ((uint64_t)fsth2 << 32) | fst2; } -uint64_t helper_float_cvtpw_ps(uint64_t fdt0) +uint64_t helper_float_cvtpw_ps(CPUMIPSState *env, uint64_t fdt0) { uint32_t wt2; uint32_t wth2; @@ -2493,7 +2526,7 @@ uint64_t helper_float_cvtpw_ps(uint64_t fdt0) set_float_exception_flags(0, &env->active_fpu.fp_status); wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) { wt2 = FLOAT_SNAN32; wth2 = FLOAT_SNAN32; @@ -2501,81 +2534,81 @@ uint64_t helper_float_cvtpw_ps(uint64_t fdt0) return ((uint64_t)wth2 << 32) | wt2; } -uint32_t helper_float_cvts_d(uint64_t fdt0) +uint32_t helper_float_cvts_d(CPUMIPSState *env, uint64_t fdt0) { uint32_t fst2; set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return fst2; } -uint32_t helper_float_cvts_w(uint32_t wt0) +uint32_t helper_float_cvts_w(CPUMIPSState *env, uint32_t wt0) { uint32_t fst2; set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return fst2; } -uint32_t helper_float_cvts_l(uint64_t dt0) +uint32_t helper_float_cvts_l(CPUMIPSState *env, uint64_t dt0) { uint32_t fst2; set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return fst2; } -uint32_t helper_float_cvts_pl(uint32_t wt0) +uint32_t helper_float_cvts_pl(CPUMIPSState *env, uint32_t wt0) { uint32_t wt2; set_float_exception_flags(0, &env->active_fpu.fp_status); wt2 = wt0; - update_fcr31(); + update_fcr31(env); return wt2; } -uint32_t helper_float_cvts_pu(uint32_t wth0) +uint32_t helper_float_cvts_pu(CPUMIPSState *env, uint32_t wth0) { uint32_t wt2; set_float_exception_flags(0, &env->active_fpu.fp_status); wt2 = wth0; - update_fcr31(); + update_fcr31(env); return wt2; } -uint32_t helper_float_cvtw_s(uint32_t fst0) +uint32_t helper_float_cvtw_s(CPUMIPSState *env, uint32_t fst0) { uint32_t wt2; set_float_exception_flags(0, &env->active_fpu.fp_status); wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) wt2 = FLOAT_SNAN32; return wt2; } -uint32_t helper_float_cvtw_d(uint64_t fdt0) +uint32_t helper_float_cvtw_d(CPUMIPSState *env, uint64_t fdt0) { uint32_t wt2; set_float_exception_flags(0, &env->active_fpu.fp_status); wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) wt2 = FLOAT_SNAN32; return wt2; } -uint64_t helper_float_roundl_d(uint64_t fdt0) +uint64_t helper_float_roundl_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t dt2; @@ -2583,13 +2616,13 @@ uint64_t helper_float_roundl_d(uint64_t fdt0) set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status); dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) dt2 = FLOAT_SNAN64; return dt2; } -uint64_t helper_float_roundl_s(uint32_t fst0) +uint64_t helper_float_roundl_s(CPUMIPSState *env, uint32_t fst0) { uint64_t dt2; @@ -2597,13 +2630,13 @@ uint64_t helper_float_roundl_s(uint32_t fst0) set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status); dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) dt2 = FLOAT_SNAN64; return dt2; } -uint32_t helper_float_roundw_d(uint64_t fdt0) +uint32_t helper_float_roundw_d(CPUMIPSState *env, uint64_t fdt0) { uint32_t wt2; @@ -2611,13 +2644,13 @@ uint32_t helper_float_roundw_d(uint64_t fdt0) set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status); wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) wt2 = FLOAT_SNAN32; return wt2; } -uint32_t helper_float_roundw_s(uint32_t fst0) +uint32_t helper_float_roundw_s(CPUMIPSState *env, uint32_t fst0) { uint32_t wt2; @@ -2625,61 +2658,61 @@ uint32_t helper_float_roundw_s(uint32_t fst0) set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status); wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) wt2 = FLOAT_SNAN32; return wt2; } -uint64_t helper_float_truncl_d(uint64_t fdt0) +uint64_t helper_float_truncl_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t dt2; set_float_exception_flags(0, &env->active_fpu.fp_status); dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) dt2 = FLOAT_SNAN64; return dt2; } -uint64_t helper_float_truncl_s(uint32_t fst0) +uint64_t helper_float_truncl_s(CPUMIPSState *env, uint32_t fst0) { uint64_t dt2; set_float_exception_flags(0, &env->active_fpu.fp_status); dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) dt2 = FLOAT_SNAN64; return dt2; } -uint32_t helper_float_truncw_d(uint64_t fdt0) +uint32_t helper_float_truncw_d(CPUMIPSState *env, uint64_t fdt0) { uint32_t wt2; set_float_exception_flags(0, &env->active_fpu.fp_status); wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) wt2 = FLOAT_SNAN32; return wt2; } -uint32_t helper_float_truncw_s(uint32_t fst0) +uint32_t helper_float_truncw_s(CPUMIPSState *env, uint32_t fst0) { uint32_t wt2; set_float_exception_flags(0, &env->active_fpu.fp_status); wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) wt2 = FLOAT_SNAN32; return wt2; } -uint64_t helper_float_ceill_d(uint64_t fdt0) +uint64_t helper_float_ceill_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t dt2; @@ -2687,13 +2720,13 @@ uint64_t helper_float_ceill_d(uint64_t fdt0) set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) dt2 = FLOAT_SNAN64; return dt2; } -uint64_t helper_float_ceill_s(uint32_t fst0) +uint64_t helper_float_ceill_s(CPUMIPSState *env, uint32_t fst0) { uint64_t dt2; @@ -2701,13 +2734,13 @@ uint64_t helper_float_ceill_s(uint32_t fst0) set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) dt2 = FLOAT_SNAN64; return dt2; } -uint32_t helper_float_ceilw_d(uint64_t fdt0) +uint32_t helper_float_ceilw_d(CPUMIPSState *env, uint64_t fdt0) { uint32_t wt2; @@ -2715,13 +2748,13 @@ uint32_t helper_float_ceilw_d(uint64_t fdt0) set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) wt2 = FLOAT_SNAN32; return wt2; } -uint32_t helper_float_ceilw_s(uint32_t fst0) +uint32_t helper_float_ceilw_s(CPUMIPSState *env, uint32_t fst0) { uint32_t wt2; @@ -2729,13 +2762,13 @@ uint32_t helper_float_ceilw_s(uint32_t fst0) set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) wt2 = FLOAT_SNAN32; return wt2; } -uint64_t helper_float_floorl_d(uint64_t fdt0) +uint64_t helper_float_floorl_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t dt2; @@ -2743,13 +2776,13 @@ uint64_t helper_float_floorl_d(uint64_t fdt0) set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) dt2 = FLOAT_SNAN64; return dt2; } -uint64_t helper_float_floorl_s(uint32_t fst0) +uint64_t helper_float_floorl_s(CPUMIPSState *env, uint32_t fst0) { uint64_t dt2; @@ -2757,13 +2790,13 @@ uint64_t helper_float_floorl_s(uint32_t fst0) set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) dt2 = FLOAT_SNAN64; return dt2; } -uint32_t helper_float_floorw_d(uint64_t fdt0) +uint32_t helper_float_floorw_d(CPUMIPSState *env, uint64_t fdt0) { uint32_t wt2; @@ -2771,13 +2804,13 @@ uint32_t helper_float_floorw_d(uint64_t fdt0) set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) wt2 = FLOAT_SNAN32; return wt2; } -uint32_t helper_float_floorw_s(uint32_t fst0) +uint32_t helper_float_floorw_s(CPUMIPSState *env, uint32_t fst0) { uint32_t wt2; @@ -2785,7 +2818,7 @@ uint32_t helper_float_floorw_s(uint32_t fst0) set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(); + update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) wt2 = FLOAT_SNAN32; return wt2; @@ -2815,69 +2848,69 @@ FLOAT_UNOP(chs) #undef FLOAT_UNOP /* MIPS specific unary operations */ -uint64_t helper_float_recip_d(uint64_t fdt0) +uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t fdt2; set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return fdt2; } -uint32_t helper_float_recip_s(uint32_t fst0) +uint32_t helper_float_recip_s(CPUMIPSState *env, uint32_t fst0) { uint32_t fst2; set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return fst2; } -uint64_t helper_float_rsqrt_d(uint64_t fdt0) +uint64_t helper_float_rsqrt_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t fdt2; set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status); fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return fdt2; } -uint32_t helper_float_rsqrt_s(uint32_t fst0) +uint32_t helper_float_rsqrt_s(CPUMIPSState *env, uint32_t fst0) { uint32_t fst2; set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status); fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return fst2; } -uint64_t helper_float_recip1_d(uint64_t fdt0) +uint64_t helper_float_recip1_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t fdt2; set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return fdt2; } -uint32_t helper_float_recip1_s(uint32_t fst0) +uint32_t helper_float_recip1_s(CPUMIPSState *env, uint32_t fst0) { uint32_t fst2; set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return fst2; } -uint64_t helper_float_recip1_ps(uint64_t fdt0) +uint64_t helper_float_recip1_ps(CPUMIPSState *env, uint64_t fdt0) { uint32_t fst2; uint32_t fsth2; @@ -2885,33 +2918,33 @@ uint64_t helper_float_recip1_ps(uint64_t fdt0) set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_div(FLOAT_ONE32, fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); fsth2 = float32_div(FLOAT_ONE32, fdt0 >> 32, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return ((uint64_t)fsth2 << 32) | fst2; } -uint64_t helper_float_rsqrt1_d(uint64_t fdt0) +uint64_t helper_float_rsqrt1_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t fdt2; set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status); fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return fdt2; } -uint32_t helper_float_rsqrt1_s(uint32_t fst0) +uint32_t helper_float_rsqrt1_s(CPUMIPSState *env, uint32_t fst0) { uint32_t fst2; set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status); fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return fst2; } -uint64_t helper_float_rsqrt1_ps(uint64_t fdt0) +uint64_t helper_float_rsqrt1_ps(CPUMIPSState *env, uint64_t fdt0) { uint32_t fst2; uint32_t fsth2; @@ -2921,39 +2954,43 @@ uint64_t helper_float_rsqrt1_ps(uint64_t fdt0) fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status); fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status); fsth2 = float32_div(FLOAT_ONE32, fsth2, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return ((uint64_t)fsth2 << 32) | fst2; } -#define FLOAT_OP(name, p) void helper_float_##name##_##p(void) +#define FLOAT_OP(name, p) void helper_float_##name##_##p(CPUMIPSState *env) /* binary operations */ #define FLOAT_BINOP(name) \ -uint64_t helper_float_ ## name ## _d(uint64_t fdt0, uint64_t fdt1) \ +uint64_t helper_float_ ## name ## _d(CPUMIPSState *env, \ + uint64_t fdt0, uint64_t fdt1) \ { \ uint64_t dt2; \ \ set_float_exception_flags(0, &env->active_fpu.fp_status); \ dt2 = float64_ ## name (fdt0, fdt1, &env->active_fpu.fp_status); \ - update_fcr31(); \ + update_fcr31(env); \ if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) \ dt2 = FLOAT_QNAN64; \ return dt2; \ } \ \ -uint32_t helper_float_ ## name ## _s(uint32_t fst0, uint32_t fst1) \ +uint32_t helper_float_ ## name ## _s(CPUMIPSState *env, \ + uint32_t fst0, uint32_t fst1) \ { \ uint32_t wt2; \ \ set_float_exception_flags(0, &env->active_fpu.fp_status); \ wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \ - update_fcr31(); \ + update_fcr31(env); \ if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) \ wt2 = FLOAT_QNAN32; \ return wt2; \ } \ \ -uint64_t helper_float_ ## name ## _ps(uint64_t fdt0, uint64_t fdt1) \ +uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \ + uint64_t fdt0, \ + uint64_t fdt1) \ { \ uint32_t fst0 = fdt0 & 0XFFFFFFFF; \ uint32_t fsth0 = fdt0 >> 32; \ @@ -2965,7 +3002,7 @@ uint64_t helper_float_ ## name ## _ps(uint64_t fdt0, uint64_t fdt1) \ set_float_exception_flags(0, &env->active_fpu.fp_status); \ wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \ wth2 = float32_ ## name (fsth0, fsth1, &env->active_fpu.fp_status); \ - update_fcr31(); \ + update_fcr31(env); \ if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) { \ wt2 = FLOAT_QNAN32; \ wth2 = FLOAT_QNAN32; \ @@ -2981,22 +3018,28 @@ FLOAT_BINOP(div) /* ternary operations */ #define FLOAT_TERNOP(name1, name2) \ -uint64_t helper_float_ ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1, \ - uint64_t fdt2) \ +uint64_t helper_float_ ## name1 ## name2 ## _d(CPUMIPSState *env, \ + uint64_t fdt0, \ + uint64_t fdt1, \ + uint64_t fdt2) \ { \ fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status); \ return float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status); \ } \ \ -uint32_t helper_float_ ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1, \ - uint32_t fst2) \ +uint32_t helper_float_ ## name1 ## name2 ## _s(CPUMIPSState *env, \ + uint32_t fst0, \ + uint32_t fst1, \ + uint32_t fst2) \ { \ fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \ return float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \ } \ \ -uint64_t helper_float_ ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1, \ - uint64_t fdt2) \ +uint64_t helper_float_ ## name1 ## name2 ## _ps(CPUMIPSState *env, \ + uint64_t fdt0, \ + uint64_t fdt1, \ + uint64_t fdt2) \ { \ uint32_t fst0 = fdt0 & 0XFFFFFFFF; \ uint32_t fsth0 = fdt0 >> 32; \ @@ -3018,24 +3061,30 @@ FLOAT_TERNOP(mul, sub) /* negated ternary operations */ #define FLOAT_NTERNOP(name1, name2) \ -uint64_t helper_float_n ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1, \ - uint64_t fdt2) \ +uint64_t helper_float_n ## name1 ## name2 ## _d(CPUMIPSState *env, \ + uint64_t fdt0, \ + uint64_t fdt1, \ + uint64_t fdt2) \ { \ fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status); \ fdt2 = float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status); \ return float64_chs(fdt2); \ } \ \ -uint32_t helper_float_n ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1, \ - uint32_t fst2) \ +uint32_t helper_float_n ## name1 ## name2 ## _s(CPUMIPSState *env, \ + uint32_t fst0, \ + uint32_t fst1, \ + uint32_t fst2) \ { \ fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \ fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \ return float32_chs(fst2); \ } \ \ -uint64_t helper_float_n ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1,\ - uint64_t fdt2) \ +uint64_t helper_float_n ## name1 ## name2 ## _ps(CPUMIPSState *env, \ + uint64_t fdt0, \ + uint64_t fdt1, \ + uint64_t fdt2) \ { \ uint32_t fst0 = fdt0 & 0XFFFFFFFF; \ uint32_t fsth0 = fdt0 >> 32; \ @@ -3058,25 +3107,25 @@ FLOAT_NTERNOP(mul, sub) #undef FLOAT_NTERNOP /* MIPS specific binary operations */ -uint64_t helper_float_recip2_d(uint64_t fdt0, uint64_t fdt2) +uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) { set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status); fdt2 = float64_chs(float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status)); - update_fcr31(); + update_fcr31(env); return fdt2; } -uint32_t helper_float_recip2_s(uint32_t fst0, uint32_t fst2) +uint32_t helper_float_recip2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2) { set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status)); - update_fcr31(); + update_fcr31(env); return fst2; } -uint64_t helper_float_recip2_ps(uint64_t fdt0, uint64_t fdt2) +uint64_t helper_float_recip2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) { uint32_t fst0 = fdt0 & 0XFFFFFFFF; uint32_t fsth0 = fdt0 >> 32; @@ -3088,31 +3137,31 @@ uint64_t helper_float_recip2_ps(uint64_t fdt0, uint64_t fdt2) fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status); fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status)); fsth2 = float32_chs(float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status)); - update_fcr31(); + update_fcr31(env); return ((uint64_t)fsth2 << 32) | fst2; } -uint64_t helper_float_rsqrt2_d(uint64_t fdt0, uint64_t fdt2) +uint64_t helper_float_rsqrt2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) { set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status); fdt2 = float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status); fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->active_fpu.fp_status)); - update_fcr31(); + update_fcr31(env); return fdt2; } -uint32_t helper_float_rsqrt2_s(uint32_t fst0, uint32_t fst2) +uint32_t helper_float_rsqrt2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2) { set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status); fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status)); - update_fcr31(); + update_fcr31(env); return fst2; } -uint64_t helper_float_rsqrt2_ps(uint64_t fdt0, uint64_t fdt2) +uint64_t helper_float_rsqrt2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) { uint32_t fst0 = fdt0 & 0XFFFFFFFF; uint32_t fsth0 = fdt0 >> 32; @@ -3126,11 +3175,11 @@ uint64_t helper_float_rsqrt2_ps(uint64_t fdt0, uint64_t fdt2) fsth2 = float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status); fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status)); fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->active_fpu.fp_status)); - update_fcr31(); + update_fcr31(env); return ((uint64_t)fsth2 << 32) | fst2; } -uint64_t helper_float_addr_ps(uint64_t fdt0, uint64_t fdt1) +uint64_t helper_float_addr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1) { uint32_t fst0 = fdt0 & 0XFFFFFFFF; uint32_t fsth0 = fdt0 >> 32; @@ -3142,11 +3191,11 @@ uint64_t helper_float_addr_ps(uint64_t fdt0, uint64_t fdt1) set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_add (fst0, fsth0, &env->active_fpu.fp_status); fsth2 = float32_add (fst1, fsth1, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return ((uint64_t)fsth2 << 32) | fst2; } -uint64_t helper_float_mulr_ps(uint64_t fdt0, uint64_t fdt1) +uint64_t helper_float_mulr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1) { uint32_t fst0 = fdt0 & 0XFFFFFFFF; uint32_t fsth0 = fdt0 >> 32; @@ -3158,31 +3207,33 @@ uint64_t helper_float_mulr_ps(uint64_t fdt0, uint64_t fdt1) set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_mul (fst0, fsth0, &env->active_fpu.fp_status); fsth2 = float32_mul (fst1, fsth1, &env->active_fpu.fp_status); - update_fcr31(); + update_fcr31(env); return ((uint64_t)fsth2 << 32) | fst2; } /* compare operations */ #define FOP_COND_D(op, cond) \ -void helper_cmp_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \ +void helper_cmp_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \ + uint64_t fdt1, int cc) \ { \ int c; \ set_float_exception_flags(0, &env->active_fpu.fp_status); \ c = cond; \ - update_fcr31(); \ + update_fcr31(env); \ if (c) \ SET_FP_COND(cc, env->active_fpu); \ else \ CLEAR_FP_COND(cc, env->active_fpu); \ } \ -void helper_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \ +void helper_cmpabs_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \ + uint64_t fdt1, int cc) \ { \ int c; \ set_float_exception_flags(0, &env->active_fpu.fp_status); \ fdt0 = float64_abs(fdt0); \ fdt1 = float64_abs(fdt1); \ c = cond; \ - update_fcr31(); \ + update_fcr31(env); \ if (c) \ SET_FP_COND(cc, env->active_fpu); \ else \ @@ -3211,25 +3262,27 @@ FOP_COND_D(le, float64_le(fdt0, fdt1, &env->active_fpu.fp_status)) FOP_COND_D(ngt, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) || float64_le(fdt0, fdt1, &env->active_fpu.fp_status)) #define FOP_COND_S(op, cond) \ -void helper_cmp_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \ +void helper_cmp_s_ ## op(CPUMIPSState *env, uint32_t fst0, \ + uint32_t fst1, int cc) \ { \ int c; \ set_float_exception_flags(0, &env->active_fpu.fp_status); \ c = cond; \ - update_fcr31(); \ + update_fcr31(env); \ if (c) \ SET_FP_COND(cc, env->active_fpu); \ else \ CLEAR_FP_COND(cc, env->active_fpu); \ } \ -void helper_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \ +void helper_cmpabs_s_ ## op(CPUMIPSState *env, uint32_t fst0, \ + uint32_t fst1, int cc) \ { \ int c; \ set_float_exception_flags(0, &env->active_fpu.fp_status); \ fst0 = float32_abs(fst0); \ fst1 = float32_abs(fst1); \ c = cond; \ - update_fcr31(); \ + update_fcr31(env); \ if (c) \ SET_FP_COND(cc, env->active_fpu); \ else \ @@ -3258,7 +3311,8 @@ FOP_COND_S(le, float32_le(fst0, fst1, &env->active_fpu.fp_status)) FOP_COND_S(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status)) #define FOP_COND_PS(op, condl, condh) \ -void helper_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \ +void helper_cmp_ps_ ## op(CPUMIPSState *env, uint64_t fdt0, \ + uint64_t fdt1, int cc) \ { \ uint32_t fst0, fsth0, fst1, fsth1; \ int ch, cl; \ @@ -3269,7 +3323,7 @@ void helper_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \ fsth1 = fdt1 >> 32; \ cl = condl; \ ch = condh; \ - update_fcr31(); \ + update_fcr31(env); \ if (cl) \ SET_FP_COND(cc, env->active_fpu); \ else \ @@ -3279,7 +3333,8 @@ void helper_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \ else \ CLEAR_FP_COND(cc + 1, env->active_fpu); \ } \ -void helper_cmpabs_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \ +void helper_cmpabs_ps_ ## op(CPUMIPSState *env, uint64_t fdt0, \ + uint64_t fdt1, int cc) \ { \ uint32_t fst0, fsth0, fst1, fsth1; \ int ch, cl; \ @@ -3289,7 +3344,7 @@ void helper_cmpabs_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \ fsth1 = float32_abs(fdt1 >> 32); \ cl = condl; \ ch = condh; \ - update_fcr31(); \ + update_fcr31(env); \ if (cl) \ SET_FP_COND(cc, env->active_fpu); \ else \ diff --git a/target-mips/translate.c b/target-mips/translate.c index a884f751bc..52eeb2bf79 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -483,27 +483,45 @@ static uint32_t gen_opc_hflags[OPC_BUF_SIZE]; #include "gen-icount.h" -#define gen_helper_0i(name, arg) do { \ +#define gen_helper_0e0i(name, arg) do { \ TCGv_i32 helper_tmp = tcg_const_i32(arg); \ - gen_helper_##name(helper_tmp); \ + gen_helper_##name(cpu_env, helper_tmp); \ tcg_temp_free_i32(helper_tmp); \ } while(0) -#define gen_helper_1i(name, arg1, arg2) do { \ +#define gen_helper_0e1i(name, arg1, arg2) do { \ TCGv_i32 helper_tmp = tcg_const_i32(arg2); \ - gen_helper_##name(arg1, helper_tmp); \ + gen_helper_##name(cpu_env, arg1, helper_tmp); \ tcg_temp_free_i32(helper_tmp); \ } while(0) -#define gen_helper_2i(name, arg1, arg2, arg3) do { \ +#define gen_helper_1e0i(name, ret, arg1) do { \ + TCGv_i32 helper_tmp = tcg_const_i32(arg1); \ + gen_helper_##name(ret, cpu_env, helper_tmp); \ + tcg_temp_free_i32(helper_tmp); \ + } while(0) + +#define gen_helper_1e1i(name, ret, arg1, arg2) do { \ + TCGv_i32 helper_tmp = tcg_const_i32(arg2); \ + gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \ + tcg_temp_free_i32(helper_tmp); \ + } while(0) + +#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \ TCGv_i32 helper_tmp = tcg_const_i32(arg3); \ - gen_helper_##name(arg1, arg2, helper_tmp); \ + gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \ tcg_temp_free_i32(helper_tmp); \ } while(0) -#define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \ +#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \ + TCGv_i32 helper_tmp = tcg_const_i32(arg3); \ + gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \ + tcg_temp_free_i32(helper_tmp); \ + } while(0) + +#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \ TCGv_i32 helper_tmp = tcg_const_i32(arg4); \ - gen_helper_##name(arg1, arg2, arg3, helper_tmp); \ + gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \ tcg_temp_free_i32(helper_tmp); \ } while(0) @@ -748,7 +766,7 @@ generate_exception_err (DisasContext *ctx, int excp, int err) TCGv_i32 texcp = tcg_const_i32(excp); TCGv_i32 terr = tcg_const_i32(err); save_cpu_state(ctx, 1); - gen_helper_raise_exception_err(texcp, terr); + gen_helper_raise_exception_err(cpu_env, texcp, terr); tcg_temp_free_i32(terr); tcg_temp_free_i32(texcp); } @@ -757,7 +775,7 @@ static inline void generate_exception (DisasContext *ctx, int excp) { save_cpu_state(ctx, 1); - gen_helper_0i(raise_exception, excp); + gen_helper_0e0i(raise_exception, excp); } /* Addresses computation */ @@ -871,22 +889,22 @@ static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \ gen_ldcmp_fpr##bits (ctx, fp0, fs); \ gen_ldcmp_fpr##bits (ctx, fp1, ft); \ switch (n) { \ - case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\ - case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\ - case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\ - case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\ - case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\ - case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\ - case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\ - case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\ - case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\ - case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\ - case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\ - case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\ - case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\ - case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\ - case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\ - case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\ + case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\ + case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\ + case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\ + case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\ + case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\ + case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\ + case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\ + case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\ + case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\ + case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\ + case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\ + case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\ + case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\ + case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\ + case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\ + case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\ default: abort(); \ } \ tcg_temp_free_i##bits (fp0); \ @@ -948,7 +966,7 @@ static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \ #define OP_LD_ATOMIC(insn,fname) \ static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \ { \ - gen_helper_2i(insn, ret, arg1, ctx->mem_idx); \ + gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \ } #endif OP_LD_ATOMIC(ll,ld32s); @@ -975,7 +993,7 @@ static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \ tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \ tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \ - gen_helper_0i(raise_exception, EXCP_SC); \ + gen_helper_0e0i(raise_exception, EXCP_SC); \ gen_set_label(l2); \ tcg_gen_movi_tl(t0, 0); \ gen_store_gpr(t0, rt); \ @@ -986,7 +1004,7 @@ static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \ { \ TCGv t0 = tcg_temp_new(); \ - gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx); \ + gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \ gen_store_gpr(t0, rt); \ tcg_temp_free(t0); \ } @@ -1066,14 +1084,14 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, case OPC_LDL: save_cpu_state(ctx, 1); gen_load_gpr(t1, rt); - gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx); + gen_helper_1e2i(ldl, t1, t1, t0, ctx->mem_idx); gen_store_gpr(t1, rt); opn = "ldl"; break; case OPC_LDR: save_cpu_state(ctx, 1); gen_load_gpr(t1, rt); - gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx); + gen_helper_1e2i(ldr, t1, t1, t0, ctx->mem_idx); gen_store_gpr(t1, rt); opn = "ldr"; break; @@ -1127,14 +1145,14 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, case OPC_LWL: save_cpu_state(ctx, 1); gen_load_gpr(t1, rt); - gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx); + gen_helper_1e2i(lwl, t1, t1, t0, ctx->mem_idx); gen_store_gpr(t1, rt); opn = "lwl"; break; case OPC_LWR: save_cpu_state(ctx, 1); gen_load_gpr(t1, rt); - gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx); + gen_helper_1e2i(lwr, t1, t1, t0, ctx->mem_idx); gen_store_gpr(t1, rt); opn = "lwr"; break; @@ -1170,12 +1188,12 @@ static void gen_st (DisasContext *ctx, uint32_t opc, int rt, break; case OPC_SDL: save_cpu_state(ctx, 1); - gen_helper_2i(sdl, t1, t0, ctx->mem_idx); + gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx); opn = "sdl"; break; case OPC_SDR: save_cpu_state(ctx, 1); - gen_helper_2i(sdr, t1, t0, ctx->mem_idx); + gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx); opn = "sdr"; break; #endif @@ -1196,12 +1214,12 @@ static void gen_st (DisasContext *ctx, uint32_t opc, int rt, break; case OPC_SWL: save_cpu_state(ctx, 1); - gen_helper_2i(swl, t1, t0, ctx->mem_idx); + gen_helper_0e2i(swl, t1, t0, ctx->mem_idx); opn = "swl"; break; case OPC_SWR: save_cpu_state(ctx, 1); - gen_helper_2i(swr, t1, t0, ctx->mem_idx); + gen_helper_0e2i(swr, t1, t0, ctx->mem_idx); opn = "swr"; break; } @@ -2138,11 +2156,11 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, opn = "ddivu"; break; case OPC_DMULT: - gen_helper_dmult(t0, t1); + gen_helper_dmult(cpu_env, t0, t1); opn = "dmult"; break; case OPC_DMULTU: - gen_helper_dmultu(t0, t1); + gen_helper_dmultu(cpu_env, t0, t1); opn = "dmultu"; break; #endif @@ -2254,59 +2272,59 @@ static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc, switch (opc) { case OPC_VR54XX_MULS: - gen_helper_muls(t0, t0, t1); + gen_helper_muls(t0, cpu_env, t0, t1); opn = "muls"; break; case OPC_VR54XX_MULSU: - gen_helper_mulsu(t0, t0, t1); + gen_helper_mulsu(t0, cpu_env, t0, t1); opn = "mulsu"; break; case OPC_VR54XX_MACC: - gen_helper_macc(t0, t0, t1); + gen_helper_macc(t0, cpu_env, t0, t1); opn = "macc"; break; case OPC_VR54XX_MACCU: - gen_helper_maccu(t0, t0, t1); + gen_helper_maccu(t0, cpu_env, t0, t1); opn = "maccu"; break; case OPC_VR54XX_MSAC: - gen_helper_msac(t0, t0, t1); + gen_helper_msac(t0, cpu_env, t0, t1); opn = "msac"; break; case OPC_VR54XX_MSACU: - gen_helper_msacu(t0, t0, t1); + gen_helper_msacu(t0, cpu_env, t0, t1); opn = "msacu"; break; case OPC_VR54XX_MULHI: - gen_helper_mulhi(t0, t0, t1); + gen_helper_mulhi(t0, cpu_env, t0, t1); opn = "mulhi"; break; case OPC_VR54XX_MULHIU: - gen_helper_mulhiu(t0, t0, t1); + gen_helper_mulhiu(t0, cpu_env, t0, t1); opn = "mulhiu"; break; case OPC_VR54XX_MULSHI: - gen_helper_mulshi(t0, t0, t1); + gen_helper_mulshi(t0, cpu_env, t0, t1); opn = "mulshi"; break; case OPC_VR54XX_MULSHIU: - gen_helper_mulshiu(t0, t0, t1); + gen_helper_mulshiu(t0, cpu_env, t0, t1); opn = "mulshiu"; break; case OPC_VR54XX_MACCHI: - gen_helper_macchi(t0, t0, t1); + gen_helper_macchi(t0, cpu_env, t0, t1); opn = "macchi"; break; case OPC_VR54XX_MACCHIU: - gen_helper_macchiu(t0, t0, t1); + gen_helper_macchiu(t0, cpu_env, t0, t1); opn = "macchiu"; break; case OPC_VR54XX_MSACHI: - gen_helper_msachi(t0, t0, t1); + gen_helper_msachi(t0, cpu_env, t0, t1); opn = "msachi"; break; case OPC_VR54XX_MSACHIU: - gen_helper_msachiu(t0, t0, t1); + gen_helper_msachiu(t0, cpu_env, t0, t1); opn = "msachiu"; break; default: @@ -2683,7 +2701,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) gen_save_pc(dest); if (ctx->singlestep_enabled) { save_cpu_state(ctx, 0); - gen_helper_0i(raise_exception, EXCP_DEBUG); + gen_helper_0e0i(raise_exception, EXCP_DEBUG); } tcg_gen_exit_tb(0); } @@ -3187,17 +3205,17 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i break; case 1: check_insn(env, ctx, ASE_MT); - gen_helper_mfc0_mvpcontrol(arg); + gen_helper_mfc0_mvpcontrol(arg, cpu_env); rn = "MVPControl"; break; case 2: check_insn(env, ctx, ASE_MT); - gen_helper_mfc0_mvpconf0(arg); + gen_helper_mfc0_mvpconf0(arg, cpu_env); rn = "MVPConf0"; break; case 3: check_insn(env, ctx, ASE_MT); - gen_helper_mfc0_mvpconf1(arg); + gen_helper_mfc0_mvpconf1(arg, cpu_env); rn = "MVPConf1"; break; default: @@ -3207,7 +3225,7 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 1: switch (sel) { case 0: - gen_helper_mfc0_random(arg); + gen_helper_mfc0_random(arg, cpu_env); rn = "Random"; break; case 1: @@ -3258,37 +3276,37 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i break; case 1: check_insn(env, ctx, ASE_MT); - gen_helper_mfc0_tcstatus(arg); + gen_helper_mfc0_tcstatus(arg, cpu_env); rn = "TCStatus"; break; case 2: check_insn(env, ctx, ASE_MT); - gen_helper_mfc0_tcbind(arg); + gen_helper_mfc0_tcbind(arg, cpu_env); rn = "TCBind"; break; case 3: check_insn(env, ctx, ASE_MT); - gen_helper_mfc0_tcrestart(arg); + gen_helper_mfc0_tcrestart(arg, cpu_env); rn = "TCRestart"; break; case 4: check_insn(env, ctx, ASE_MT); - gen_helper_mfc0_tchalt(arg); + gen_helper_mfc0_tchalt(arg, cpu_env); rn = "TCHalt"; break; case 5: check_insn(env, ctx, ASE_MT); - gen_helper_mfc0_tccontext(arg); + gen_helper_mfc0_tccontext(arg, cpu_env); rn = "TCContext"; break; case 6: check_insn(env, ctx, ASE_MT); - gen_helper_mfc0_tcschedule(arg); + gen_helper_mfc0_tcschedule(arg, cpu_env); rn = "TCSchedule"; break; case 7: check_insn(env, ctx, ASE_MT); - gen_helper_mfc0_tcschefback(arg); + gen_helper_mfc0_tcschefback(arg, cpu_env); rn = "TCScheFBack"; break; default: @@ -3399,7 +3417,7 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i /* Mark as an IO operation because we read the time. */ if (use_icount) gen_io_start(); - gen_helper_mfc0_count(arg); + gen_helper_mfc0_count(arg, cpu_env); if (use_icount) { gen_io_end(); } @@ -3531,7 +3549,7 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 17: switch (sel) { case 0: - gen_helper_mfc0_lladdr(arg); + gen_helper_mfc0_lladdr(arg, cpu_env); rn = "LLAddr"; break; default: @@ -3541,7 +3559,7 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 18: switch (sel) { case 0 ... 7: - gen_helper_1i(mfc0_watchlo, arg, sel); + gen_helper_1e0i(mfc0_watchlo, arg, sel); rn = "WatchLo"; break; default: @@ -3551,7 +3569,7 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 19: switch (sel) { case 0 ...7: - gen_helper_1i(mfc0_watchhi, arg, sel); + gen_helper_1e0i(mfc0_watchhi, arg, sel); rn = "WatchHi"; break; default: @@ -3590,7 +3608,7 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 23: switch (sel) { case 0: - gen_helper_mfc0_debug(arg); /* EJTAG support */ + gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */ rn = "Debug"; break; case 1: @@ -3765,12 +3783,12 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 0: switch (sel) { case 0: - gen_helper_mtc0_index(arg); + gen_helper_mtc0_index(cpu_env, arg); rn = "Index"; break; case 1: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_mvpcontrol(arg); + gen_helper_mtc0_mvpcontrol(cpu_env, arg); rn = "MVPControl"; break; case 2: @@ -3795,22 +3813,22 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i break; case 1: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_vpecontrol(arg); + gen_helper_mtc0_vpecontrol(cpu_env, arg); rn = "VPEControl"; break; case 2: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_vpeconf0(arg); + gen_helper_mtc0_vpeconf0(cpu_env, arg); rn = "VPEConf0"; break; case 3: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_vpeconf1(arg); + gen_helper_mtc0_vpeconf1(cpu_env, arg); rn = "VPEConf1"; break; case 4: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_yqmask(arg); + gen_helper_mtc0_yqmask(cpu_env, arg); rn = "YQMask"; break; case 5: @@ -3825,7 +3843,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i break; case 7: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_vpeopt(arg); + gen_helper_mtc0_vpeopt(cpu_env, arg); rn = "VPEOpt"; break; default: @@ -3835,42 +3853,42 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 2: switch (sel) { case 0: - gen_helper_mtc0_entrylo0(arg); + gen_helper_mtc0_entrylo0(cpu_env, arg); rn = "EntryLo0"; break; case 1: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_tcstatus(arg); + gen_helper_mtc0_tcstatus(cpu_env, arg); rn = "TCStatus"; break; case 2: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_tcbind(arg); + gen_helper_mtc0_tcbind(cpu_env, arg); rn = "TCBind"; break; case 3: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_tcrestart(arg); + gen_helper_mtc0_tcrestart(cpu_env, arg); rn = "TCRestart"; break; case 4: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_tchalt(arg); + gen_helper_mtc0_tchalt(cpu_env, arg); rn = "TCHalt"; break; case 5: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_tccontext(arg); + gen_helper_mtc0_tccontext(cpu_env, arg); rn = "TCContext"; break; case 6: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_tcschedule(arg); + gen_helper_mtc0_tcschedule(cpu_env, arg); rn = "TCSchedule"; break; case 7: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_tcschefback(arg); + gen_helper_mtc0_tcschefback(cpu_env, arg); rn = "TCScheFBack"; break; default: @@ -3880,7 +3898,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 3: switch (sel) { case 0: - gen_helper_mtc0_entrylo1(arg); + gen_helper_mtc0_entrylo1(cpu_env, arg); rn = "EntryLo1"; break; default: @@ -3890,11 +3908,11 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 4: switch (sel) { case 0: - gen_helper_mtc0_context(arg); + gen_helper_mtc0_context(cpu_env, arg); rn = "Context"; break; case 1: -// gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */ +// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */ rn = "ContextConfig"; // break; default: @@ -3904,12 +3922,12 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 5: switch (sel) { case 0: - gen_helper_mtc0_pagemask(arg); + gen_helper_mtc0_pagemask(cpu_env, arg); rn = "PageMask"; break; case 1: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_pagegrain(arg); + gen_helper_mtc0_pagegrain(cpu_env, arg); rn = "PageGrain"; break; default: @@ -3919,32 +3937,32 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 6: switch (sel) { case 0: - gen_helper_mtc0_wired(arg); + gen_helper_mtc0_wired(cpu_env, arg); rn = "Wired"; break; case 1: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_srsconf0(arg); + gen_helper_mtc0_srsconf0(cpu_env, arg); rn = "SRSConf0"; break; case 2: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_srsconf1(arg); + gen_helper_mtc0_srsconf1(cpu_env, arg); rn = "SRSConf1"; break; case 3: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_srsconf2(arg); + gen_helper_mtc0_srsconf2(cpu_env, arg); rn = "SRSConf2"; break; case 4: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_srsconf3(arg); + gen_helper_mtc0_srsconf3(cpu_env, arg); rn = "SRSConf3"; break; case 5: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_srsconf4(arg); + gen_helper_mtc0_srsconf4(cpu_env, arg); rn = "SRSConf4"; break; default: @@ -3955,7 +3973,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i switch (sel) { case 0: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_hwrena(arg); + gen_helper_mtc0_hwrena(cpu_env, arg); rn = "HWREna"; break; default: @@ -3969,7 +3987,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 9: switch (sel) { case 0: - gen_helper_mtc0_count(arg); + gen_helper_mtc0_count(cpu_env, arg); rn = "Count"; break; /* 6,7 are implementation dependent */ @@ -3980,7 +3998,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 10: switch (sel) { case 0: - gen_helper_mtc0_entryhi(arg); + gen_helper_mtc0_entryhi(cpu_env, arg); rn = "EntryHi"; break; default: @@ -3990,7 +4008,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 11: switch (sel) { case 0: - gen_helper_mtc0_compare(arg); + gen_helper_mtc0_compare(cpu_env, arg); rn = "Compare"; break; /* 6,7 are implementation dependent */ @@ -4002,7 +4020,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i switch (sel) { case 0: save_cpu_state(ctx, 1); - gen_helper_mtc0_status(arg); + gen_helper_mtc0_status(cpu_env, arg); /* BS_STOP isn't good enough here, hflags may have changed. */ gen_save_pc(ctx->pc + 4); ctx->bstate = BS_EXCP; @@ -4010,14 +4028,14 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i break; case 1: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_intctl(arg); + gen_helper_mtc0_intctl(cpu_env, arg); /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; rn = "IntCtl"; break; case 2: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_srsctl(arg); + gen_helper_mtc0_srsctl(cpu_env, arg); /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; rn = "SRSCtl"; @@ -4037,7 +4055,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i switch (sel) { case 0: save_cpu_state(ctx, 1); - gen_helper_mtc0_cause(arg); + gen_helper_mtc0_cause(cpu_env, arg); rn = "Cause"; break; default: @@ -4062,7 +4080,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i break; case 1: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_ebase(arg); + gen_helper_mtc0_ebase(cpu_env, arg); rn = "EBase"; break; default: @@ -4072,7 +4090,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 16: switch (sel) { case 0: - gen_helper_mtc0_config0(arg); + gen_helper_mtc0_config0(cpu_env, arg); rn = "Config"; /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; @@ -4082,7 +4100,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i rn = "Config1"; break; case 2: - gen_helper_mtc0_config2(arg); + gen_helper_mtc0_config2(cpu_env, arg); rn = "Config2"; /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; @@ -4109,7 +4127,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 17: switch (sel) { case 0: - gen_helper_mtc0_lladdr(arg); + gen_helper_mtc0_lladdr(cpu_env, arg); rn = "LLAddr"; break; default: @@ -4119,7 +4137,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 18: switch (sel) { case 0 ... 7: - gen_helper_1i(mtc0_watchlo, arg, sel); + gen_helper_0e1i(mtc0_watchlo, arg, sel); rn = "WatchLo"; break; default: @@ -4129,7 +4147,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 19: switch (sel) { case 0 ... 7: - gen_helper_1i(mtc0_watchhi, arg, sel); + gen_helper_0e1i(mtc0_watchhi, arg, sel); rn = "WatchHi"; break; default: @@ -4141,7 +4159,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 0: #if defined(TARGET_MIPS64) check_insn(env, ctx, ISA_MIPS3); - gen_helper_mtc0_xcontext(arg); + gen_helper_mtc0_xcontext(cpu_env, arg); rn = "XContext"; break; #endif @@ -4153,7 +4171,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i /* Officially reserved, but sel 0 is used for R1x000 framemask */ switch (sel) { case 0: - gen_helper_mtc0_framemask(arg); + gen_helper_mtc0_framemask(cpu_env, arg); rn = "Framemask"; break; default: @@ -4167,20 +4185,20 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 23: switch (sel) { case 0: - gen_helper_mtc0_debug(arg); /* EJTAG support */ + gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */ /* BS_STOP isn't good enough here, hflags may have changed. */ gen_save_pc(ctx->pc + 4); ctx->bstate = BS_EXCP; rn = "Debug"; break; case 1: -// gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */ +// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */ rn = "TraceControl"; /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; // break; case 2: -// gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */ +// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */ rn = "TraceControl2"; /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; @@ -4188,13 +4206,13 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 3: /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; -// gen_helper_mtc0_usertracedata(arg); /* PDtrace support */ +// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */ rn = "UserTraceData"; /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; // break; case 4: -// gen_helper_mtc0_tracebpc(arg); /* PDtrace support */ +// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */ /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; rn = "TraceBPC"; @@ -4217,7 +4235,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 25: switch (sel) { case 0: - gen_helper_mtc0_performance0(arg); + gen_helper_mtc0_performance0(cpu_env, arg); rn = "Performance0"; break; case 1: @@ -4272,14 +4290,14 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 2: case 4: case 6: - gen_helper_mtc0_taglo(arg); + gen_helper_mtc0_taglo(cpu_env, arg); rn = "TagLo"; break; case 1: case 3: case 5: case 7: - gen_helper_mtc0_datalo(arg); + gen_helper_mtc0_datalo(cpu_env, arg); rn = "DataLo"; break; default: @@ -4292,14 +4310,14 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i case 2: case 4: case 6: - gen_helper_mtc0_taghi(arg); + gen_helper_mtc0_taghi(cpu_env, arg); rn = "TagHi"; break; case 1: case 3: case 5: case 7: - gen_helper_mtc0_datahi(arg); + gen_helper_mtc0_datahi(cpu_env, arg); rn = "DataHi"; break; default: @@ -4364,17 +4382,17 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, break; case 1: check_insn(env, ctx, ASE_MT); - gen_helper_mfc0_mvpcontrol(arg); + gen_helper_mfc0_mvpcontrol(arg, cpu_env); rn = "MVPControl"; break; case 2: check_insn(env, ctx, ASE_MT); - gen_helper_mfc0_mvpconf0(arg); + gen_helper_mfc0_mvpconf0(arg, cpu_env); rn = "MVPConf0"; break; case 3: check_insn(env, ctx, ASE_MT); - gen_helper_mfc0_mvpconf1(arg); + gen_helper_mfc0_mvpconf1(arg, cpu_env); rn = "MVPConf1"; break; default: @@ -4384,7 +4402,7 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 1: switch (sel) { case 0: - gen_helper_mfc0_random(arg); + gen_helper_mfc0_random(arg, cpu_env); rn = "Random"; break; case 1: @@ -4434,37 +4452,37 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, break; case 1: check_insn(env, ctx, ASE_MT); - gen_helper_mfc0_tcstatus(arg); + gen_helper_mfc0_tcstatus(arg, cpu_env); rn = "TCStatus"; break; case 2: check_insn(env, ctx, ASE_MT); - gen_helper_mfc0_tcbind(arg); + gen_helper_mfc0_tcbind(arg, cpu_env); rn = "TCBind"; break; case 3: check_insn(env, ctx, ASE_MT); - gen_helper_dmfc0_tcrestart(arg); + gen_helper_dmfc0_tcrestart(arg, cpu_env); rn = "TCRestart"; break; case 4: check_insn(env, ctx, ASE_MT); - gen_helper_dmfc0_tchalt(arg); + gen_helper_dmfc0_tchalt(arg, cpu_env); rn = "TCHalt"; break; case 5: check_insn(env, ctx, ASE_MT); - gen_helper_dmfc0_tccontext(arg); + gen_helper_dmfc0_tccontext(arg, cpu_env); rn = "TCContext"; break; case 6: check_insn(env, ctx, ASE_MT); - gen_helper_dmfc0_tcschedule(arg); + gen_helper_dmfc0_tcschedule(arg, cpu_env); rn = "TCSchedule"; break; case 7: check_insn(env, ctx, ASE_MT); - gen_helper_dmfc0_tcschefback(arg); + gen_helper_dmfc0_tcschefback(arg, cpu_env); rn = "TCScheFBack"; break; default: @@ -4572,7 +4590,7 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, /* Mark as an IO operation because we read the time. */ if (use_icount) gen_io_start(); - gen_helper_mfc0_count(arg); + gen_helper_mfc0_count(arg, cpu_env); if (use_icount) { gen_io_end(); } @@ -4701,7 +4719,7 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 17: switch (sel) { case 0: - gen_helper_dmfc0_lladdr(arg); + gen_helper_dmfc0_lladdr(arg, cpu_env); rn = "LLAddr"; break; default: @@ -4711,7 +4729,7 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 18: switch (sel) { case 0 ... 7: - gen_helper_1i(dmfc0_watchlo, arg, sel); + gen_helper_1e0i(dmfc0_watchlo, arg, sel); rn = "WatchLo"; break; default: @@ -4721,7 +4739,7 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 19: switch (sel) { case 0 ... 7: - gen_helper_1i(mfc0_watchhi, arg, sel); + gen_helper_1e0i(mfc0_watchhi, arg, sel); rn = "WatchHi"; break; default: @@ -4757,23 +4775,23 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 23: switch (sel) { case 0: - gen_helper_mfc0_debug(arg); /* EJTAG support */ + gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */ rn = "Debug"; break; case 1: -// gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */ +// gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */ rn = "TraceControl"; // break; case 2: -// gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */ +// gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */ rn = "TraceControl2"; // break; case 3: -// gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */ +// gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */ rn = "UserTraceData"; // break; case 4: -// gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */ +// gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */ rn = "TraceBPC"; // break; default: @@ -4931,12 +4949,12 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 0: switch (sel) { case 0: - gen_helper_mtc0_index(arg); + gen_helper_mtc0_index(cpu_env, arg); rn = "Index"; break; case 1: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_mvpcontrol(arg); + gen_helper_mtc0_mvpcontrol(cpu_env, arg); rn = "MVPControl"; break; case 2: @@ -4961,22 +4979,22 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, break; case 1: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_vpecontrol(arg); + gen_helper_mtc0_vpecontrol(cpu_env, arg); rn = "VPEControl"; break; case 2: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_vpeconf0(arg); + gen_helper_mtc0_vpeconf0(cpu_env, arg); rn = "VPEConf0"; break; case 3: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_vpeconf1(arg); + gen_helper_mtc0_vpeconf1(cpu_env, arg); rn = "VPEConf1"; break; case 4: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_yqmask(arg); + gen_helper_mtc0_yqmask(cpu_env, arg); rn = "YQMask"; break; case 5: @@ -4991,7 +5009,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, break; case 7: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_vpeopt(arg); + gen_helper_mtc0_vpeopt(cpu_env, arg); rn = "VPEOpt"; break; default: @@ -5001,42 +5019,42 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 2: switch (sel) { case 0: - gen_helper_mtc0_entrylo0(arg); + gen_helper_mtc0_entrylo0(cpu_env, arg); rn = "EntryLo0"; break; case 1: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_tcstatus(arg); + gen_helper_mtc0_tcstatus(cpu_env, arg); rn = "TCStatus"; break; case 2: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_tcbind(arg); + gen_helper_mtc0_tcbind(cpu_env, arg); rn = "TCBind"; break; case 3: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_tcrestart(arg); + gen_helper_mtc0_tcrestart(cpu_env, arg); rn = "TCRestart"; break; case 4: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_tchalt(arg); + gen_helper_mtc0_tchalt(cpu_env, arg); rn = "TCHalt"; break; case 5: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_tccontext(arg); + gen_helper_mtc0_tccontext(cpu_env, arg); rn = "TCContext"; break; case 6: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_tcschedule(arg); + gen_helper_mtc0_tcschedule(cpu_env, arg); rn = "TCSchedule"; break; case 7: check_insn(env, ctx, ASE_MT); - gen_helper_mtc0_tcschefback(arg); + gen_helper_mtc0_tcschefback(cpu_env, arg); rn = "TCScheFBack"; break; default: @@ -5046,7 +5064,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 3: switch (sel) { case 0: - gen_helper_mtc0_entrylo1(arg); + gen_helper_mtc0_entrylo1(cpu_env, arg); rn = "EntryLo1"; break; default: @@ -5056,11 +5074,11 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 4: switch (sel) { case 0: - gen_helper_mtc0_context(arg); + gen_helper_mtc0_context(cpu_env, arg); rn = "Context"; break; case 1: -// gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */ +// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */ rn = "ContextConfig"; // break; default: @@ -5070,12 +5088,12 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 5: switch (sel) { case 0: - gen_helper_mtc0_pagemask(arg); + gen_helper_mtc0_pagemask(cpu_env, arg); rn = "PageMask"; break; case 1: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_pagegrain(arg); + gen_helper_mtc0_pagegrain(cpu_env, arg); rn = "PageGrain"; break; default: @@ -5085,32 +5103,32 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 6: switch (sel) { case 0: - gen_helper_mtc0_wired(arg); + gen_helper_mtc0_wired(cpu_env, arg); rn = "Wired"; break; case 1: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_srsconf0(arg); + gen_helper_mtc0_srsconf0(cpu_env, arg); rn = "SRSConf0"; break; case 2: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_srsconf1(arg); + gen_helper_mtc0_srsconf1(cpu_env, arg); rn = "SRSConf1"; break; case 3: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_srsconf2(arg); + gen_helper_mtc0_srsconf2(cpu_env, arg); rn = "SRSConf2"; break; case 4: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_srsconf3(arg); + gen_helper_mtc0_srsconf3(cpu_env, arg); rn = "SRSConf3"; break; case 5: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_srsconf4(arg); + gen_helper_mtc0_srsconf4(cpu_env, arg); rn = "SRSConf4"; break; default: @@ -5121,7 +5139,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, switch (sel) { case 0: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_hwrena(arg); + gen_helper_mtc0_hwrena(cpu_env, arg); rn = "HWREna"; break; default: @@ -5135,7 +5153,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 9: switch (sel) { case 0: - gen_helper_mtc0_count(arg); + gen_helper_mtc0_count(cpu_env, arg); rn = "Count"; break; /* 6,7 are implementation dependent */ @@ -5148,7 +5166,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 10: switch (sel) { case 0: - gen_helper_mtc0_entryhi(arg); + gen_helper_mtc0_entryhi(cpu_env, arg); rn = "EntryHi"; break; default: @@ -5158,7 +5176,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 11: switch (sel) { case 0: - gen_helper_mtc0_compare(arg); + gen_helper_mtc0_compare(cpu_env, arg); rn = "Compare"; break; /* 6,7 are implementation dependent */ @@ -5172,7 +5190,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, switch (sel) { case 0: save_cpu_state(ctx, 1); - gen_helper_mtc0_status(arg); + gen_helper_mtc0_status(cpu_env, arg); /* BS_STOP isn't good enough here, hflags may have changed. */ gen_save_pc(ctx->pc + 4); ctx->bstate = BS_EXCP; @@ -5180,14 +5198,14 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, break; case 1: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_intctl(arg); + gen_helper_mtc0_intctl(cpu_env, arg); /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; rn = "IntCtl"; break; case 2: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_srsctl(arg); + gen_helper_mtc0_srsctl(cpu_env, arg); /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; rn = "SRSCtl"; @@ -5212,7 +5230,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, if (use_icount) { gen_io_start(); } - gen_helper_mtc0_cause(arg); + gen_helper_mtc0_cause(cpu_env, arg); if (use_icount) { gen_io_end(); } @@ -5242,7 +5260,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, break; case 1: check_insn(env, ctx, ISA_MIPS32R2); - gen_helper_mtc0_ebase(arg); + gen_helper_mtc0_ebase(cpu_env, arg); rn = "EBase"; break; default: @@ -5252,7 +5270,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 16: switch (sel) { case 0: - gen_helper_mtc0_config0(arg); + gen_helper_mtc0_config0(cpu_env, arg); rn = "Config"; /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; @@ -5262,7 +5280,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, rn = "Config1"; break; case 2: - gen_helper_mtc0_config2(arg); + gen_helper_mtc0_config2(cpu_env, arg); rn = "Config2"; /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; @@ -5280,7 +5298,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 17: switch (sel) { case 0: - gen_helper_mtc0_lladdr(arg); + gen_helper_mtc0_lladdr(cpu_env, arg); rn = "LLAddr"; break; default: @@ -5290,7 +5308,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 18: switch (sel) { case 0 ... 7: - gen_helper_1i(mtc0_watchlo, arg, sel); + gen_helper_0e1i(mtc0_watchlo, arg, sel); rn = "WatchLo"; break; default: @@ -5300,7 +5318,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 19: switch (sel) { case 0 ... 7: - gen_helper_1i(mtc0_watchhi, arg, sel); + gen_helper_0e1i(mtc0_watchhi, arg, sel); rn = "WatchHi"; break; default: @@ -5311,7 +5329,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, switch (sel) { case 0: check_insn(env, ctx, ISA_MIPS3); - gen_helper_mtc0_xcontext(arg); + gen_helper_mtc0_xcontext(cpu_env, arg); rn = "XContext"; break; default: @@ -5322,7 +5340,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, /* Officially reserved, but sel 0 is used for R1x000 framemask */ switch (sel) { case 0: - gen_helper_mtc0_framemask(arg); + gen_helper_mtc0_framemask(cpu_env, arg); rn = "Framemask"; break; default: @@ -5336,32 +5354,32 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 23: switch (sel) { case 0: - gen_helper_mtc0_debug(arg); /* EJTAG support */ + gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */ /* BS_STOP isn't good enough here, hflags may have changed. */ gen_save_pc(ctx->pc + 4); ctx->bstate = BS_EXCP; rn = "Debug"; break; case 1: -// gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */ +// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */ /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; rn = "TraceControl"; // break; case 2: -// gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */ +// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */ /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; rn = "TraceControl2"; // break; case 3: -// gen_helper_mtc0_usertracedata(arg); /* PDtrace support */ +// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */ /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; rn = "UserTraceData"; // break; case 4: -// gen_helper_mtc0_tracebpc(arg); /* PDtrace support */ +// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */ /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; rn = "TraceBPC"; @@ -5384,35 +5402,35 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 25: switch (sel) { case 0: - gen_helper_mtc0_performance0(arg); + gen_helper_mtc0_performance0(cpu_env, arg); rn = "Performance0"; break; case 1: -// gen_helper_mtc0_performance1(arg); +// gen_helper_mtc0_performance1(cpu_env, arg); rn = "Performance1"; // break; case 2: -// gen_helper_mtc0_performance2(arg); +// gen_helper_mtc0_performance2(cpu_env, arg); rn = "Performance2"; // break; case 3: -// gen_helper_mtc0_performance3(arg); +// gen_helper_mtc0_performance3(cpu_env, arg); rn = "Performance3"; // break; case 4: -// gen_helper_mtc0_performance4(arg); +// gen_helper_mtc0_performance4(cpu_env, arg); rn = "Performance4"; // break; case 5: -// gen_helper_mtc0_performance5(arg); +// gen_helper_mtc0_performance5(cpu_env, arg); rn = "Performance5"; // break; case 6: -// gen_helper_mtc0_performance6(arg); +// gen_helper_mtc0_performance6(cpu_env, arg); rn = "Performance6"; // break; case 7: -// gen_helper_mtc0_performance7(arg); +// gen_helper_mtc0_performance7(cpu_env, arg); rn = "Performance7"; // break; default: @@ -5439,14 +5457,14 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 2: case 4: case 6: - gen_helper_mtc0_taglo(arg); + gen_helper_mtc0_taglo(cpu_env, arg); rn = "TagLo"; break; case 1: case 3: case 5: case 7: - gen_helper_mtc0_datalo(arg); + gen_helper_mtc0_datalo(cpu_env, arg); rn = "DataLo"; break; default: @@ -5459,14 +5477,14 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, case 2: case 4: case 6: - gen_helper_mtc0_taghi(arg); + gen_helper_mtc0_taghi(cpu_env, arg); rn = "TagHi"; break; case 1: case 3: case 5: case 7: - gen_helper_mtc0_datahi(arg); + gen_helper_mtc0_datahi(cpu_env, arg); rn = "DataHi"; break; default: @@ -5533,10 +5551,10 @@ static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd, case 1: switch (sel) { case 1: - gen_helper_mftc0_vpecontrol(t0); + gen_helper_mftc0_vpecontrol(t0, cpu_env); break; case 2: - gen_helper_mftc0_vpeconf0(t0); + gen_helper_mftc0_vpeconf0(t0, cpu_env); break; default: goto die; @@ -5546,25 +5564,25 @@ static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd, case 2: switch (sel) { case 1: - gen_helper_mftc0_tcstatus(t0); + gen_helper_mftc0_tcstatus(t0, cpu_env); break; case 2: - gen_helper_mftc0_tcbind(t0); + gen_helper_mftc0_tcbind(t0, cpu_env); break; case 3: - gen_helper_mftc0_tcrestart(t0); + gen_helper_mftc0_tcrestart(t0, cpu_env); break; case 4: - gen_helper_mftc0_tchalt(t0); + gen_helper_mftc0_tchalt(t0, cpu_env); break; case 5: - gen_helper_mftc0_tccontext(t0); + gen_helper_mftc0_tccontext(t0, cpu_env); break; case 6: - gen_helper_mftc0_tcschedule(t0); + gen_helper_mftc0_tcschedule(t0, cpu_env); break; case 7: - gen_helper_mftc0_tcschefback(t0); + gen_helper_mftc0_tcschefback(t0, cpu_env); break; default: gen_mfc0(env, ctx, t0, rt, sel); @@ -5574,7 +5592,7 @@ static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd, case 10: switch (sel) { case 0: - gen_helper_mftc0_entryhi(t0); + gen_helper_mftc0_entryhi(t0, cpu_env); break; default: gen_mfc0(env, ctx, t0, rt, sel); @@ -5583,7 +5601,7 @@ static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd, case 12: switch (sel) { case 0: - gen_helper_mftc0_status(t0); + gen_helper_mftc0_status(t0, cpu_env); break; default: gen_mfc0(env, ctx, t0, rt, sel); @@ -5592,7 +5610,7 @@ static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd, case 13: switch (sel) { case 0: - gen_helper_mftc0_cause(t0); + gen_helper_mftc0_cause(t0, cpu_env); break; default: goto die; @@ -5602,7 +5620,7 @@ static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd, case 14: switch (sel) { case 0: - gen_helper_mftc0_epc(t0); + gen_helper_mftc0_epc(t0, cpu_env); break; default: goto die; @@ -5612,7 +5630,7 @@ static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd, case 15: switch (sel) { case 1: - gen_helper_mftc0_ebase(t0); + gen_helper_mftc0_ebase(t0, cpu_env); break; default: goto die; @@ -5622,7 +5640,7 @@ static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd, case 16: switch (sel) { case 0 ... 7: - gen_helper_mftc0_configx(t0, tcg_const_tl(sel)); + gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel)); break; default: goto die; @@ -5632,7 +5650,7 @@ static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd, case 23: switch (sel) { case 0: - gen_helper_mftc0_debug(t0); + gen_helper_mftc0_debug(t0, cpu_env); break; default: gen_mfc0(env, ctx, t0, rt, sel); @@ -5645,49 +5663,49 @@ static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd, } else switch (sel) { /* GPR registers. */ case 0: - gen_helper_1i(mftgpr, t0, rt); + gen_helper_1e0i(mftgpr, t0, rt); break; /* Auxiliary CPU registers */ case 1: switch (rt) { case 0: - gen_helper_1i(mftlo, t0, 0); + gen_helper_1e0i(mftlo, t0, 0); break; case 1: - gen_helper_1i(mfthi, t0, 0); + gen_helper_1e0i(mfthi, t0, 0); break; case 2: - gen_helper_1i(mftacx, t0, 0); + gen_helper_1e0i(mftacx, t0, 0); break; case 4: - gen_helper_1i(mftlo, t0, 1); + gen_helper_1e0i(mftlo, t0, 1); break; case 5: - gen_helper_1i(mfthi, t0, 1); + gen_helper_1e0i(mfthi, t0, 1); break; case 6: - gen_helper_1i(mftacx, t0, 1); + gen_helper_1e0i(mftacx, t0, 1); break; case 8: - gen_helper_1i(mftlo, t0, 2); + gen_helper_1e0i(mftlo, t0, 2); break; case 9: - gen_helper_1i(mfthi, t0, 2); + gen_helper_1e0i(mfthi, t0, 2); break; case 10: - gen_helper_1i(mftacx, t0, 2); + gen_helper_1e0i(mftacx, t0, 2); break; case 12: - gen_helper_1i(mftlo, t0, 3); + gen_helper_1e0i(mftlo, t0, 3); break; case 13: - gen_helper_1i(mfthi, t0, 3); + gen_helper_1e0i(mfthi, t0, 3); break; case 14: - gen_helper_1i(mftacx, t0, 3); + gen_helper_1e0i(mftacx, t0, 3); break; case 16: - gen_helper_mftdsp(t0); + gen_helper_mftdsp(t0, cpu_env); break; default: goto die; @@ -5712,7 +5730,7 @@ static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd, break; case 3: /* XXX: For now we support only a single FPU context. */ - gen_helper_1i(cfc1, t0, rt); + gen_helper_1e0i(cfc1, t0, rt); break; /* COP2: Not implemented. */ case 4: @@ -5751,10 +5769,10 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, case 1: switch (sel) { case 1: - gen_helper_mttc0_vpecontrol(t0); + gen_helper_mttc0_vpecontrol(cpu_env, t0); break; case 2: - gen_helper_mttc0_vpeconf0(t0); + gen_helper_mttc0_vpeconf0(cpu_env, t0); break; default: goto die; @@ -5764,25 +5782,25 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, case 2: switch (sel) { case 1: - gen_helper_mttc0_tcstatus(t0); + gen_helper_mttc0_tcstatus(cpu_env, t0); break; case 2: - gen_helper_mttc0_tcbind(t0); + gen_helper_mttc0_tcbind(cpu_env, t0); break; case 3: - gen_helper_mttc0_tcrestart(t0); + gen_helper_mttc0_tcrestart(cpu_env, t0); break; case 4: - gen_helper_mttc0_tchalt(t0); + gen_helper_mttc0_tchalt(cpu_env, t0); break; case 5: - gen_helper_mttc0_tccontext(t0); + gen_helper_mttc0_tccontext(cpu_env, t0); break; case 6: - gen_helper_mttc0_tcschedule(t0); + gen_helper_mttc0_tcschedule(cpu_env, t0); break; case 7: - gen_helper_mttc0_tcschefback(t0); + gen_helper_mttc0_tcschefback(cpu_env, t0); break; default: gen_mtc0(env, ctx, t0, rd, sel); @@ -5792,7 +5810,7 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, case 10: switch (sel) { case 0: - gen_helper_mttc0_entryhi(t0); + gen_helper_mttc0_entryhi(cpu_env, t0); break; default: gen_mtc0(env, ctx, t0, rd, sel); @@ -5801,7 +5819,7 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, case 12: switch (sel) { case 0: - gen_helper_mttc0_status(t0); + gen_helper_mttc0_status(cpu_env, t0); break; default: gen_mtc0(env, ctx, t0, rd, sel); @@ -5810,7 +5828,7 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, case 13: switch (sel) { case 0: - gen_helper_mttc0_cause(t0); + gen_helper_mttc0_cause(cpu_env, t0); break; default: goto die; @@ -5820,7 +5838,7 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, case 15: switch (sel) { case 1: - gen_helper_mttc0_ebase(t0); + gen_helper_mttc0_ebase(cpu_env, t0); break; default: goto die; @@ -5830,7 +5848,7 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, case 23: switch (sel) { case 0: - gen_helper_mttc0_debug(t0); + gen_helper_mttc0_debug(cpu_env, t0); break; default: gen_mtc0(env, ctx, t0, rd, sel); @@ -5843,49 +5861,49 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, } else switch (sel) { /* GPR registers. */ case 0: - gen_helper_1i(mttgpr, t0, rd); + gen_helper_0e1i(mttgpr, t0, rd); break; /* Auxiliary CPU registers */ case 1: switch (rd) { case 0: - gen_helper_1i(mttlo, t0, 0); + gen_helper_0e1i(mttlo, t0, 0); break; case 1: - gen_helper_1i(mtthi, t0, 0); + gen_helper_0e1i(mtthi, t0, 0); break; case 2: - gen_helper_1i(mttacx, t0, 0); + gen_helper_0e1i(mttacx, t0, 0); break; case 4: - gen_helper_1i(mttlo, t0, 1); + gen_helper_0e1i(mttlo, t0, 1); break; case 5: - gen_helper_1i(mtthi, t0, 1); + gen_helper_0e1i(mtthi, t0, 1); break; case 6: - gen_helper_1i(mttacx, t0, 1); + gen_helper_0e1i(mttacx, t0, 1); break; case 8: - gen_helper_1i(mttlo, t0, 2); + gen_helper_0e1i(mttlo, t0, 2); break; case 9: - gen_helper_1i(mtthi, t0, 2); + gen_helper_0e1i(mtthi, t0, 2); break; case 10: - gen_helper_1i(mttacx, t0, 2); + gen_helper_0e1i(mttacx, t0, 2); break; case 12: - gen_helper_1i(mttlo, t0, 3); + gen_helper_0e1i(mttlo, t0, 3); break; case 13: - gen_helper_1i(mtthi, t0, 3); + gen_helper_0e1i(mtthi, t0, 3); break; case 14: - gen_helper_1i(mttacx, t0, 3); + gen_helper_0e1i(mttacx, t0, 3); break; case 16: - gen_helper_mttdsp(t0); + gen_helper_mttdsp(cpu_env, t0); break; default: goto die; @@ -5910,7 +5928,7 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, break; case 3: /* XXX: For now we support only a single FPU context. */ - gen_helper_1i(ctc1, t0, rd); + gen_helper_0e1i(ctc1, t0, rd); break; /* COP2: Not implemented. */ case 4: @@ -5995,30 +6013,30 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, opn = "tlbwi"; if (!env->tlb->helper_tlbwi) goto die; - gen_helper_tlbwi(); + gen_helper_tlbwi(cpu_env); break; case OPC_TLBWR: opn = "tlbwr"; if (!env->tlb->helper_tlbwr) goto die; - gen_helper_tlbwr(); + gen_helper_tlbwr(cpu_env); break; case OPC_TLBP: opn = "tlbp"; if (!env->tlb->helper_tlbp) goto die; - gen_helper_tlbp(); + gen_helper_tlbp(cpu_env); break; case OPC_TLBR: opn = "tlbr"; if (!env->tlb->helper_tlbr) goto die; - gen_helper_tlbr(); + gen_helper_tlbr(cpu_env); break; case OPC_ERET: opn = "eret"; check_insn(env, ctx, ISA_MIPS2); - gen_helper_eret(); + gen_helper_eret(cpu_env); ctx->bstate = BS_EXCP; break; case OPC_DERET: @@ -6028,7 +6046,7 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, MIPS_INVAL(opn); generate_exception(ctx, EXCP_RI); } else { - gen_helper_deret(); + gen_helper_deret(cpu_env); ctx->bstate = BS_EXCP; } break; @@ -6039,7 +6057,7 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, ctx->pc += 4; save_cpu_state(ctx, 1); ctx->pc -= 4; - gen_helper_wait(); + gen_helper_wait(cpu_env); ctx->bstate = BS_EXCP; break; default: @@ -6340,13 +6358,13 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) opn = "mtc1"; break; case OPC_CFC1: - gen_helper_1i(cfc1, t0, fs); + gen_helper_1e0i(cfc1, t0, fs); gen_store_gpr(t0, rt); opn = "cfc1"; break; case OPC_CTC1: gen_load_gpr(t0, rt); - gen_helper_1i(ctc1, t0, fs); + gen_helper_0e1i(ctc1, t0, fs); opn = "ctc1"; break; #if defined(TARGET_MIPS64) @@ -6543,7 +6561,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr32(fp0, fs); gen_load_fpr32(fp1, ft); - gen_helper_float_add_s(fp0, fp0, fp1); + gen_helper_float_add_s(fp0, cpu_env, fp0, fp1); tcg_temp_free_i32(fp1); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); @@ -6558,7 +6576,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr32(fp0, fs); gen_load_fpr32(fp1, ft); - gen_helper_float_sub_s(fp0, fp0, fp1); + gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1); tcg_temp_free_i32(fp1); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); @@ -6573,7 +6591,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr32(fp0, fs); gen_load_fpr32(fp1, ft); - gen_helper_float_mul_s(fp0, fp0, fp1); + gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1); tcg_temp_free_i32(fp1); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); @@ -6588,7 +6606,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr32(fp0, fs); gen_load_fpr32(fp1, ft); - gen_helper_float_div_s(fp0, fp0, fp1); + gen_helper_float_div_s(fp0, cpu_env, fp0, fp1); tcg_temp_free_i32(fp1); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); @@ -6601,7 +6619,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i32 fp0 = tcg_temp_new_i32(); gen_load_fpr32(fp0, fs); - gen_helper_float_sqrt_s(fp0, fp0); + gen_helper_float_sqrt_s(fp0, cpu_env, fp0); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); } @@ -6646,7 +6664,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp64 = tcg_temp_new_i64(); gen_load_fpr32(fp32, fs); - gen_helper_float_roundl_s(fp64, fp32); + gen_helper_float_roundl_s(fp64, cpu_env, fp32); tcg_temp_free_i32(fp32); gen_store_fpr64(ctx, fp64, fd); tcg_temp_free_i64(fp64); @@ -6660,7 +6678,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp64 = tcg_temp_new_i64(); gen_load_fpr32(fp32, fs); - gen_helper_float_truncl_s(fp64, fp32); + gen_helper_float_truncl_s(fp64, cpu_env, fp32); tcg_temp_free_i32(fp32); gen_store_fpr64(ctx, fp64, fd); tcg_temp_free_i64(fp64); @@ -6674,7 +6692,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp64 = tcg_temp_new_i64(); gen_load_fpr32(fp32, fs); - gen_helper_float_ceill_s(fp64, fp32); + gen_helper_float_ceill_s(fp64, cpu_env, fp32); tcg_temp_free_i32(fp32); gen_store_fpr64(ctx, fp64, fd); tcg_temp_free_i64(fp64); @@ -6688,7 +6706,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp64 = tcg_temp_new_i64(); gen_load_fpr32(fp32, fs); - gen_helper_float_floorl_s(fp64, fp32); + gen_helper_float_floorl_s(fp64, cpu_env, fp32); tcg_temp_free_i32(fp32); gen_store_fpr64(ctx, fp64, fd); tcg_temp_free_i64(fp64); @@ -6700,7 +6718,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i32 fp0 = tcg_temp_new_i32(); gen_load_fpr32(fp0, fs); - gen_helper_float_roundw_s(fp0, fp0); + gen_helper_float_roundw_s(fp0, cpu_env, fp0); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); } @@ -6711,7 +6729,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i32 fp0 = tcg_temp_new_i32(); gen_load_fpr32(fp0, fs); - gen_helper_float_truncw_s(fp0, fp0); + gen_helper_float_truncw_s(fp0, cpu_env, fp0); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); } @@ -6722,7 +6740,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i32 fp0 = tcg_temp_new_i32(); gen_load_fpr32(fp0, fs); - gen_helper_float_ceilw_s(fp0, fp0); + gen_helper_float_ceilw_s(fp0, cpu_env, fp0); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); } @@ -6733,7 +6751,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i32 fp0 = tcg_temp_new_i32(); gen_load_fpr32(fp0, fs); - gen_helper_float_floorw_s(fp0, fp0); + gen_helper_float_floorw_s(fp0, cpu_env, fp0); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); } @@ -6781,7 +6799,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i32 fp0 = tcg_temp_new_i32(); gen_load_fpr32(fp0, fs); - gen_helper_float_recip_s(fp0, fp0); + gen_helper_float_recip_s(fp0, cpu_env, fp0); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); } @@ -6793,7 +6811,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i32 fp0 = tcg_temp_new_i32(); gen_load_fpr32(fp0, fs); - gen_helper_float_rsqrt_s(fp0, fp0); + gen_helper_float_rsqrt_s(fp0, cpu_env, fp0); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); } @@ -6807,7 +6825,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr32(fp0, fs); gen_load_fpr32(fp1, ft); - gen_helper_float_recip2_s(fp0, fp0, fp1); + gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1); tcg_temp_free_i32(fp1); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); @@ -6820,7 +6838,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i32 fp0 = tcg_temp_new_i32(); gen_load_fpr32(fp0, fs); - gen_helper_float_recip1_s(fp0, fp0); + gen_helper_float_recip1_s(fp0, cpu_env, fp0); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); } @@ -6832,7 +6850,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i32 fp0 = tcg_temp_new_i32(); gen_load_fpr32(fp0, fs); - gen_helper_float_rsqrt1_s(fp0, fp0); + gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); } @@ -6846,7 +6864,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr32(fp0, fs); gen_load_fpr32(fp1, ft); - gen_helper_float_rsqrt2_s(fp0, fp0, fp1); + gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1); tcg_temp_free_i32(fp1); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); @@ -6860,7 +6878,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp64 = tcg_temp_new_i64(); gen_load_fpr32(fp32, fs); - gen_helper_float_cvtd_s(fp64, fp32); + gen_helper_float_cvtd_s(fp64, cpu_env, fp32); tcg_temp_free_i32(fp32); gen_store_fpr64(ctx, fp64, fd); tcg_temp_free_i64(fp64); @@ -6872,7 +6890,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i32 fp0 = tcg_temp_new_i32(); gen_load_fpr32(fp0, fs); - gen_helper_float_cvtw_s(fp0, fp0); + gen_helper_float_cvtw_s(fp0, cpu_env, fp0); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); } @@ -6885,7 +6903,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp64 = tcg_temp_new_i64(); gen_load_fpr32(fp32, fs); - gen_helper_float_cvtl_s(fp64, fp32); + gen_helper_float_cvtl_s(fp64, cpu_env, fp32); tcg_temp_free_i32(fp32); gen_store_fpr64(ctx, fp64, fd); tcg_temp_free_i64(fp64); @@ -6941,7 +6959,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); - gen_helper_float_add_d(fp0, fp0, fp1); + gen_helper_float_add_d(fp0, cpu_env, fp0, fp1); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); @@ -6957,7 +6975,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); - gen_helper_float_sub_d(fp0, fp0, fp1); + gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); @@ -6973,7 +6991,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); - gen_helper_float_mul_d(fp0, fp0, fp1); + gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); @@ -6989,7 +7007,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); - gen_helper_float_div_d(fp0, fp0, fp1); + gen_helper_float_div_d(fp0, cpu_env, fp0, fp1); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); @@ -7003,7 +7021,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_sqrt_d(fp0, fp0); + gen_helper_float_sqrt_d(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -7050,7 +7068,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_roundl_d(fp0, fp0); + gen_helper_float_roundl_d(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -7062,7 +7080,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_truncl_d(fp0, fp0); + gen_helper_float_truncl_d(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -7074,7 +7092,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_ceill_d(fp0, fp0); + gen_helper_float_ceill_d(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -7086,7 +7104,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_floorl_d(fp0, fp0); + gen_helper_float_floorl_d(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -7099,7 +7117,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp64 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp64, fs); - gen_helper_float_roundw_d(fp32, fp64); + gen_helper_float_roundw_d(fp32, cpu_env, fp64); tcg_temp_free_i64(fp64); gen_store_fpr32(fp32, fd); tcg_temp_free_i32(fp32); @@ -7113,7 +7131,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp64 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp64, fs); - gen_helper_float_truncw_d(fp32, fp64); + gen_helper_float_truncw_d(fp32, cpu_env, fp64); tcg_temp_free_i64(fp64); gen_store_fpr32(fp32, fd); tcg_temp_free_i32(fp32); @@ -7127,7 +7145,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp64 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp64, fs); - gen_helper_float_ceilw_d(fp32, fp64); + gen_helper_float_ceilw_d(fp32, cpu_env, fp64); tcg_temp_free_i64(fp64); gen_store_fpr32(fp32, fd); tcg_temp_free_i32(fp32); @@ -7141,7 +7159,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp64 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp64, fs); - gen_helper_float_floorw_d(fp32, fp64); + gen_helper_float_floorw_d(fp32, cpu_env, fp64); tcg_temp_free_i64(fp64); gen_store_fpr32(fp32, fd); tcg_temp_free_i32(fp32); @@ -7190,7 +7208,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_recip_d(fp0, fp0); + gen_helper_float_recip_d(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -7202,7 +7220,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_rsqrt_d(fp0, fp0); + gen_helper_float_rsqrt_d(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -7216,7 +7234,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); - gen_helper_float_recip2_d(fp0, fp0, fp1); + gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); @@ -7229,7 +7247,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_recip1_d(fp0, fp0); + gen_helper_float_recip1_d(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -7241,7 +7259,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_rsqrt1_d(fp0, fp0); + gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -7255,7 +7273,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); - gen_helper_float_rsqrt2_d(fp0, fp0, fp1); + gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); @@ -7293,7 +7311,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp64 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp64, fs); - gen_helper_float_cvts_d(fp32, fp64); + gen_helper_float_cvts_d(fp32, cpu_env, fp64); tcg_temp_free_i64(fp64); gen_store_fpr32(fp32, fd); tcg_temp_free_i32(fp32); @@ -7307,7 +7325,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp64 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp64, fs); - gen_helper_float_cvtw_d(fp32, fp64); + gen_helper_float_cvtw_d(fp32, cpu_env, fp64); tcg_temp_free_i64(fp64); gen_store_fpr32(fp32, fd); tcg_temp_free_i32(fp32); @@ -7320,7 +7338,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_cvtl_d(fp0, fp0); + gen_helper_float_cvtl_d(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -7331,7 +7349,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i32 fp0 = tcg_temp_new_i32(); gen_load_fpr32(fp0, fs); - gen_helper_float_cvts_w(fp0, fp0); + gen_helper_float_cvts_w(fp0, cpu_env, fp0); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); } @@ -7344,7 +7362,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp64 = tcg_temp_new_i64(); gen_load_fpr32(fp32, fs); - gen_helper_float_cvtd_w(fp64, fp32); + gen_helper_float_cvtd_w(fp64, cpu_env, fp32); tcg_temp_free_i32(fp32); gen_store_fpr64(ctx, fp64, fd); tcg_temp_free_i64(fp64); @@ -7358,7 +7376,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp64 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp64, fs); - gen_helper_float_cvts_l(fp32, fp64); + gen_helper_float_cvts_l(fp32, cpu_env, fp64); tcg_temp_free_i64(fp64); gen_store_fpr32(fp32, fd); tcg_temp_free_i32(fp32); @@ -7371,7 +7389,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_cvtd_l(fp0, fp0); + gen_helper_float_cvtd_l(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -7383,7 +7401,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_cvtps_pw(fp0, fp0); + gen_helper_float_cvtps_pw(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -7397,7 +7415,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); - gen_helper_float_add_ps(fp0, fp0, fp1); + gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); @@ -7412,7 +7430,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); - gen_helper_float_sub_ps(fp0, fp0, fp1); + gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); @@ -7427,7 +7445,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); - gen_helper_float_mul_ps(fp0, fp0, fp1); + gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); @@ -7515,7 +7533,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr64(ctx, fp0, ft); gen_load_fpr64(ctx, fp1, fs); - gen_helper_float_addr_ps(fp0, fp0, fp1); + gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); @@ -7530,7 +7548,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr64(ctx, fp0, ft); gen_load_fpr64(ctx, fp1, fs); - gen_helper_float_mulr_ps(fp0, fp0, fp1); + gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); @@ -7545,7 +7563,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); - gen_helper_float_recip2_ps(fp0, fp0, fp1); + gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); @@ -7558,7 +7576,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_recip1_ps(fp0, fp0); + gen_helper_float_recip1_ps(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -7570,7 +7588,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_rsqrt1_ps(fp0, fp0); + gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -7584,7 +7602,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); - gen_helper_float_rsqrt2_ps(fp0, fp0, fp1); + gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); @@ -7597,7 +7615,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i32 fp0 = tcg_temp_new_i32(); gen_load_fpr32h(fp0, fs); - gen_helper_float_cvts_pu(fp0, fp0); + gen_helper_float_cvts_pu(fp0, cpu_env, fp0); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); } @@ -7609,7 +7627,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - gen_helper_float_cvtpw_ps(fp0, fp0); + gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -7621,7 +7639,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, TCGv_i32 fp0 = tcg_temp_new_i32(); gen_load_fpr32(fp0, fs); - gen_helper_float_cvts_pl(fp0, fp0); + gen_helper_float_cvts_pl(fp0, cpu_env, fp0); gen_store_fpr32(fp0, fd); tcg_temp_free_i32(fp0); } @@ -7887,7 +7905,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr32(fp0, fs); gen_load_fpr32(fp1, ft); gen_load_fpr32(fp2, fr); - gen_helper_float_muladd_s(fp2, fp0, fp1, fp2); + gen_helper_float_muladd_s(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i32(fp0); tcg_temp_free_i32(fp1); gen_store_fpr32(fp2, fd); @@ -7906,7 +7924,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); gen_load_fpr64(ctx, fp2, fr); - gen_helper_float_muladd_d(fp2, fp0, fp1, fp2); + gen_helper_float_muladd_d(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i64(fp0); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp2, fd); @@ -7924,7 +7942,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); gen_load_fpr64(ctx, fp2, fr); - gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2); + gen_helper_float_muladd_ps(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i64(fp0); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp2, fd); @@ -7942,7 +7960,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr32(fp0, fs); gen_load_fpr32(fp1, ft); gen_load_fpr32(fp2, fr); - gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2); + gen_helper_float_mulsub_s(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i32(fp0); tcg_temp_free_i32(fp1); gen_store_fpr32(fp2, fd); @@ -7961,7 +7979,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); gen_load_fpr64(ctx, fp2, fr); - gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2); + gen_helper_float_mulsub_d(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i64(fp0); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp2, fd); @@ -7979,7 +7997,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); gen_load_fpr64(ctx, fp2, fr); - gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2); + gen_helper_float_mulsub_ps(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i64(fp0); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp2, fd); @@ -7997,7 +8015,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr32(fp0, fs); gen_load_fpr32(fp1, ft); gen_load_fpr32(fp2, fr); - gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2); + gen_helper_float_nmuladd_s(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i32(fp0); tcg_temp_free_i32(fp1); gen_store_fpr32(fp2, fd); @@ -8016,7 +8034,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); gen_load_fpr64(ctx, fp2, fr); - gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2); + gen_helper_float_nmuladd_d(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i64(fp0); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp2, fd); @@ -8034,7 +8052,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); gen_load_fpr64(ctx, fp2, fr); - gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2); + gen_helper_float_nmuladd_ps(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i64(fp0); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp2, fd); @@ -8052,7 +8070,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr32(fp0, fs); gen_load_fpr32(fp1, ft); gen_load_fpr32(fp2, fr); - gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2); + gen_helper_float_nmulsub_s(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i32(fp0); tcg_temp_free_i32(fp1); gen_store_fpr32(fp2, fd); @@ -8071,7 +8089,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); gen_load_fpr64(ctx, fp2, fr); - gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2); + gen_helper_float_nmulsub_d(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i64(fp0); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp2, fd); @@ -8089,7 +8107,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); gen_load_fpr64(ctx, fp2, fr); - gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2); + gen_helper_float_nmulsub_ps(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i64(fp0); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp2, fd); @@ -8122,22 +8140,22 @@ gen_rdhwr (CPUMIPSState *env, DisasContext *ctx, int rt, int rd) switch (rd) { case 0: save_cpu_state(ctx, 1); - gen_helper_rdhwr_cpunum(t0); + gen_helper_rdhwr_cpunum(t0, cpu_env); gen_store_gpr(t0, rt); break; case 1: save_cpu_state(ctx, 1); - gen_helper_rdhwr_synci_step(t0); + gen_helper_rdhwr_synci_step(t0, cpu_env); gen_store_gpr(t0, rt); break; case 2: save_cpu_state(ctx, 1); - gen_helper_rdhwr_cc(t0); + gen_helper_rdhwr_cc(t0, cpu_env); gen_store_gpr(t0, rt); break; case 3: save_cpu_state(ctx, 1); - gen_helper_rdhwr_ccres(t0); + gen_helper_rdhwr_ccres(t0, cpu_env); gen_store_gpr(t0, rt); break; case 29: @@ -8214,7 +8232,7 @@ static void handle_delay_slot (CPUMIPSState *env, DisasContext *ctx, } if (ctx->singlestep_enabled) { save_cpu_state(ctx, 0); - gen_helper_0i(raise_exception, EXCP_DEBUG); + gen_helper_0e0i(raise_exception, EXCP_DEBUG); } tcg_gen_exit_tb(0); break; @@ -8678,7 +8696,7 @@ static void decode_i64_mips16 (CPUMIPSState *env, DisasContext *ctx, static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) { - int extend = lduw_code(ctx->pc + 2); + int extend = cpu_lduw_code(env, ctx->pc + 2); int op, rx, ry, funct, sa; int16_t imm, offset; @@ -8904,7 +8922,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, /* No delay slot, so just process as a normal instruction */ break; case M16_OPC_JAL: - offset = lduw_code(ctx->pc + 2); + offset = cpu_lduw_code(env, ctx->pc + 2); offset = (((ctx->opcode & 0x1f) << 21) | ((ctx->opcode >> 5) & 0x1f) << 16 | offset) << 2; @@ -9855,17 +9873,17 @@ static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist, save_cpu_state(ctx, 1); switch (opc) { case LWM32: - gen_helper_lwm(t0, t1, t2); + gen_helper_lwm(cpu_env, t0, t1, t2); break; case SWM32: - gen_helper_swm(t0, t1, t2); + gen_helper_swm(cpu_env, t0, t1, t2); break; #ifdef TARGET_MIPS64 case LDM: - gen_helper_ldm(t0, t1, t2); + gen_helper_ldm(cpu_env, t0, t1, t2); break; case SDM: - gen_helper_sdm(t0, t1, t2); + gen_helper_sdm(cpu_env, t0, t1, t2); break; #endif } @@ -10287,7 +10305,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs, TCGv t0 = tcg_temp_new(); save_cpu_state(ctx, 1); - gen_helper_di(t0); + gen_helper_di(t0, cpu_env); gen_store_gpr(t0, rs); /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; @@ -10300,7 +10318,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs, TCGv t0 = tcg_temp_new(); save_cpu_state(ctx, 1); - gen_helper_ei(t0); + gen_helper_ei(t0, cpu_env); gen_store_gpr(t0, rs); /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; @@ -10635,7 +10653,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, uint32_t op, minor, mips32_op; uint32_t cond, fmt, cc; - insn = lduw_code(ctx->pc + 2); + insn = cpu_lduw_code(env, ctx->pc + 2); ctx->opcode = (ctx->opcode << 16) | insn; rt = (ctx->opcode >> 21) & 0x1f; @@ -11827,7 +11845,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) MIPS_INVAL("PMON / selsl"); generate_exception(ctx, EXCP_RI); #else - gen_helper_0i(pmon, sa); + gen_helper_0e0i(pmon, sa); #endif break; case OPC_SYSCALL: @@ -12045,7 +12063,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) save_cpu_state(ctx, 1); gen_load_gpr(t0, rs); - gen_helper_yield(t0, t0); + gen_helper_yield(t0, cpu_env, t0); gen_store_gpr(t0, rd); tcg_temp_free(t0); } @@ -12144,18 +12162,18 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) break; case OPC_DVPE: check_insn(env, ctx, ASE_MT); - gen_helper_dvpe(t0); + gen_helper_dvpe(t0, cpu_env); gen_store_gpr(t0, rt); break; case OPC_EVPE: check_insn(env, ctx, ASE_MT); - gen_helper_evpe(t0); + gen_helper_evpe(t0, cpu_env); gen_store_gpr(t0, rt); break; case OPC_DI: check_insn(env, ctx, ISA_MIPS32R2); save_cpu_state(ctx, 1); - gen_helper_di(t0); + gen_helper_di(t0, cpu_env); gen_store_gpr(t0, rt); /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; @@ -12163,7 +12181,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_EI: check_insn(env, ctx, ISA_MIPS32R2); save_cpu_state(ctx, 1); - gen_helper_ei(t0); + gen_helper_ei(t0, cpu_env); gen_store_gpr(t0, rt); /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; @@ -12432,7 +12450,7 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb, if (bp->pc == ctx.pc) { save_cpu_state(&ctx, 1); ctx.bstate = BS_BRANCH; - gen_helper_0i(raise_exception, EXCP_DEBUG); + gen_helper_0e0i(raise_exception, EXCP_DEBUG); /* Include the breakpoint location or the tb won't * be flushed when it must be. */ ctx.pc += 4; @@ -12458,14 +12476,14 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb, is_branch = 0; if (!(ctx.hflags & MIPS_HFLAG_M16)) { - ctx.opcode = ldl_code(ctx.pc); + ctx.opcode = cpu_ldl_code(env, ctx.pc); insn_bytes = 4; decode_opc(env, &ctx, &is_branch); } else if (env->insn_flags & ASE_MICROMIPS) { - ctx.opcode = lduw_code(ctx.pc); + ctx.opcode = cpu_lduw_code(env, ctx.pc); insn_bytes = decode_micromips_opc(env, &ctx, &is_branch); } else if (env->insn_flags & ASE_MIPS16) { - ctx.opcode = lduw_code(ctx.pc); + ctx.opcode = cpu_lduw_code(env, ctx.pc); insn_bytes = decode_mips16_opc(env, &ctx, &is_branch); } else { generate_exception(&ctx, EXCP_RI); @@ -12502,7 +12520,7 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb, gen_io_end(); if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) { save_cpu_state(&ctx, ctx.bstate == BS_NONE); - gen_helper_0i(raise_exception, EXCP_DEBUG); + gen_helper_0e0i(raise_exception, EXCP_DEBUG); } else { switch (ctx.bstate) { case BS_STOP: From 89c33337fd21930de671a6e34793e8b1ee257e2e Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Sep 2012 15:28:56 +0000 Subject: [PATCH 0403/2270] Remove unused CONFIG_TCG_PASS_AREG0 and dead code Now that CONFIG_TCG_PASS_AREG0 is enabled for all targets, remove dead code and support for !CONFIG_TCG_PASS_AREG0 case. Remove dyngen-exec.h and all references to it. Although included by hw/spapr_hcall.c, it does not seem to use it. Remove unused HELPER_CFLAGS. Signed-off-by: Blue Swirl Reviewed-by: Richard Henderson --- Makefile.target | 8 ----- configure | 11 ------ cpu-all.h | 11 ------ cputlb.c | 5 --- dyngen-exec.h | 70 ------------------------------------ exec-all.h | 4 --- hw/spapr_hcall.c | 1 - softmmu_defs.h | 21 ----------- softmmu_header.h | 63 +++++++++++---------------------- softmmu_template.h | 72 ++++++++++++++------------------------ target-m68k/op_helper.c | 3 -- target-sparc/Makefile.objs | 2 -- tcg/arm/tcg-target.c | 31 ++-------------- tcg/arm/tcg-target.h | 1 - tcg/hppa/tcg-target.c | 24 ------------- tcg/hppa/tcg-target.h | 1 - tcg/i386/tcg-target.c | 30 ---------------- tcg/i386/tcg-target.h | 1 - tcg/ia64/tcg-target.c | 34 ------------------ tcg/ia64/tcg-target.h | 1 - tcg/mips/tcg-target.c | 31 ++-------------- tcg/mips/tcg-target.h | 1 - tcg/ppc/tcg-target.c | 38 -------------------- tcg/ppc64/tcg-target.c | 28 --------------- tcg/s390/tcg-target.c | 24 ------------- tcg/s390/tcg-target.h | 1 - tcg/sparc/tcg-target.c | 30 ---------------- tcg/sparc/tcg-target.h | 1 - tcg/tci/tcg-target.c | 4 --- tci.c | 12 ------- user-exec.c | 14 -------- 31 files changed, 53 insertions(+), 525 deletions(-) delete mode 100644 dyngen-exec.h diff --git a/Makefile.target b/Makefile.target index 7892a8df63..d9d54b8dd0 100644 --- a/Makefile.target +++ b/Makefile.target @@ -80,14 +80,6 @@ obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o tci-dis.o: QEMU_CFLAGS += -I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/tci -# HELPER_CFLAGS is used for all the legacy code compiled with static register -# variables -user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS) - -# Note: this is a workaround. The real fix is to avoid compiling -# cpu_signal_handler() in user-exec.c. -%/signal.o: QEMU_CFLAGS += $(HELPER_CFLAGS) - ######################################################### # Linux user emulator target diff --git a/configure b/configure index 69f9638e6f..7e23309dd4 100755 --- a/configure +++ b/configure @@ -118,7 +118,6 @@ audio_card_list="ac97 es1370 sb16 hda" audio_possible_cards="ac97 es1370 sb16 cs4231a adlib gus hda" block_drv_whitelist="" host_cc="gcc" -helper_cflags="" libs_softmmu="" libs_tools="" audio_pt_int="" @@ -902,7 +901,6 @@ case "$cpu" in QEMU_CFLAGS="-m32 -ffixed-g2 -ffixed-g3 $QEMU_CFLAGS" if test "$solaris" = "no" ; then QEMU_CFLAGS="-ffixed-g1 -ffixed-g6 $QEMU_CFLAGS" - helper_cflags="-ffixed-i0" fi ;; sparc64) @@ -927,7 +925,6 @@ case "$cpu" in QEMU_CFLAGS="-m32 $QEMU_CFLAGS" LDFLAGS="-m32 $LDFLAGS" cc_i386='$(CC) -m32' - helper_cflags="-fomit-frame-pointer" host_guest_base="yes" ;; x86_64) @@ -3617,7 +3614,6 @@ if test "$sparse" = "yes" ; then echo "HOST_CC := REAL_CC=\"\$(HOST_CC)\" cgcc" >> $config_host_mak echo "QEMU_CFLAGS += -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-non-pointer-null" >> $config_host_mak fi -echo "HELPER_CFLAGS=$helper_cflags" >> $config_host_mak echo "LDFLAGS=$LDFLAGS" >> $config_host_mak echo "ARLIBS_BEGIN=$arlibs_begin" >> $config_host_mak echo "ARLIBS_END=$arlibs_end" >> $config_host_mak @@ -3872,13 +3868,6 @@ fi symlink "$source_path/Makefile.target" "$target_dir/Makefile" - -case "$target_arch2" in - alpha | arm* | cris | i386 | lm32 | m68k | microblaze* | mips* | or32 | s390x | sh4* | sparc* | unicore32 | x86_64 | xtensa* | ppc*) - echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak - ;; -esac - upper() { echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]' } diff --git a/cpu-all.h b/cpu-all.h index 5e07d28508..74d3681c29 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -260,14 +260,6 @@ extern unsigned long reserved_va; #define stfl(p, v) stfl_raw(p, v) #define stfq(p, v) stfq_raw(p, v) -#ifndef CONFIG_TCG_PASS_AREG0 -#define ldub_code(p) ldub_raw(p) -#define ldsb_code(p) ldsb_raw(p) -#define lduw_code(p) lduw_raw(p) -#define ldsw_code(p) ldsw_raw(p) -#define ldl_code(p) ldl_raw(p) -#define ldq_code(p) ldq_raw(p) -#else #define cpu_ldub_code(env1, p) ldub_raw(p) #define cpu_ldsb_code(env1, p) ldsb_raw(p) #define cpu_lduw_code(env1, p) lduw_raw(p) @@ -296,7 +288,6 @@ extern unsigned long reserved_va; #define cpu_stw_kernel(env, addr, data) stw_raw(addr, data) #define cpu_stl_kernel(env, addr, data) stl_raw(addr, data) #define cpu_stq_kernel(env, addr, data) stq_raw(addr, data) -#endif #define ldub_kernel(p) ldub_raw(p) #define ldsb_kernel(p) ldsb_raw(p) @@ -313,7 +304,6 @@ extern unsigned long reserved_va; #define stfl_kernel(p, v) stfl_raw(p, v) #define stfq_kernel(p, vt) stfq_raw(p, v) -#ifdef CONFIG_TCG_PASS_AREG0 #define cpu_ldub_data(env, addr) ldub_raw(addr) #define cpu_lduw_data(env, addr) lduw_raw(addr) #define cpu_ldl_data(env, addr) ldl_raw(addr) @@ -321,7 +311,6 @@ extern unsigned long reserved_va; #define cpu_stb_data(env, addr, data) stb_raw(addr, data) #define cpu_stw_data(env, addr, data) stw_raw(addr, data) #define cpu_stl_data(env, addr, data) stl_raw(addr, data) -#endif #endif /* defined(CONFIG_USER_ONLY) */ /* page related stuff */ diff --git a/cputlb.c b/cputlb.c index d3e7b257ae..51b5897d37 100644 --- a/cputlb.c +++ b/cputlb.c @@ -325,11 +325,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr) mmu_idx = cpu_mmu_index(env1); if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code != (addr & TARGET_PAGE_MASK))) { -#ifdef CONFIG_TCG_PASS_AREG0 cpu_ldub_code(env1, addr); -#else - ldub_code(addr); -#endif } pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK; mr = iotlb_to_region(pd); @@ -348,7 +344,6 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr) #define MMUSUFFIX _cmmu #undef GETPC #define GETPC() ((uintptr_t)0) -#define env cpu_single_env #define SOFTMMU_CODE_ACCESS #define SHIFT 0 diff --git a/dyngen-exec.h b/dyngen-exec.h deleted file mode 100644 index 083e20bed7..0000000000 --- a/dyngen-exec.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * dyngen defines for micro operation code - * - * Copyright (c) 2003 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#if !defined(__DYNGEN_EXEC_H__) -#define __DYNGEN_EXEC_H__ - -#if defined(CONFIG_TCG_INTERPRETER) -/* The TCG interpreter does not need a special register AREG0, - * but it is possible to use one by defining AREG0. - * On i386, register edi seems to work. */ -/* Run without special register AREG0 or use a value defined elsewhere. */ -#elif defined(__i386__) -#define AREG0 "ebp" -#elif defined(__x86_64__) -#define AREG0 "r14" -#elif defined(_ARCH_PPC) -#define AREG0 "r27" -#elif defined(__arm__) -#define AREG0 "r6" -#elif defined(__hppa__) -#define AREG0 "r17" -#elif defined(__mips__) -#define AREG0 "s0" -#elif defined(__sparc__) -#ifdef CONFIG_SOLARIS -#define AREG0 "g2" -#else -#ifdef __sparc_v9__ -#define AREG0 "g5" -#else -#define AREG0 "g6" -#endif -#endif -#elif defined(__s390__) -#define AREG0 "r10" -#elif defined(__alpha__) -/* Note $15 is the frame pointer, so anything in op-i386.c that would - require a frame pointer, like alloca, would probably loose. */ -#define AREG0 "$15" -#elif defined(__mc68000) -#define AREG0 "%a5" -#elif defined(__ia64__) -#define AREG0 "r7" -#else -#error unsupported CPU -#endif - -#if defined(AREG0) -register CPUArchState *env asm(AREG0); -#else -/* TODO: Try env = cpu_single_env. */ -extern CPUArchState *env; -#endif - -#endif /* !defined(__DYNGEN_EXEC_H__) */ diff --git a/exec-all.h b/exec-all.h index 4f4fafc05a..dba96098b8 100644 --- a/exec-all.h +++ b/exec-all.h @@ -323,9 +323,6 @@ void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx, #define ACCESS_TYPE (NB_MMU_MODES + 1) #define MEMSUFFIX _code -#ifndef CONFIG_TCG_PASS_AREG0 -#define env cpu_single_env -#endif #define DATA_SIZE 1 #include "softmmu_header.h" @@ -341,7 +338,6 @@ void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx, #undef ACCESS_TYPE #undef MEMSUFFIX -#undef env #endif diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c index a5990a9617..abd847f96c 100644 --- a/hw/spapr_hcall.c +++ b/hw/spapr_hcall.c @@ -1,6 +1,5 @@ #include "sysemu.h" #include "cpu.h" -#include "dyngen-exec.h" #include "qemu-char.h" #include "sysemu.h" #include "qemu-char.h" diff --git a/softmmu_defs.h b/softmmu_defs.h index 8d59f9d4f8..1f25e33ce4 100644 --- a/softmmu_defs.h +++ b/softmmu_defs.h @@ -9,25 +9,6 @@ #ifndef SOFTMMU_DEFS_H #define SOFTMMU_DEFS_H -#ifndef CONFIG_TCG_PASS_AREG0 -uint8_t __ldb_mmu(target_ulong addr, int mmu_idx); -void __stb_mmu(target_ulong addr, uint8_t val, int mmu_idx); -uint16_t __ldw_mmu(target_ulong addr, int mmu_idx); -void __stw_mmu(target_ulong addr, uint16_t val, int mmu_idx); -uint32_t __ldl_mmu(target_ulong addr, int mmu_idx); -void __stl_mmu(target_ulong addr, uint32_t val, int mmu_idx); -uint64_t __ldq_mmu(target_ulong addr, int mmu_idx); -void __stq_mmu(target_ulong addr, uint64_t val, int mmu_idx); - -uint8_t __ldb_cmmu(target_ulong addr, int mmu_idx); -void __stb_cmmu(target_ulong addr, uint8_t val, int mmu_idx); -uint16_t __ldw_cmmu(target_ulong addr, int mmu_idx); -void __stw_cmmu(target_ulong addr, uint16_t val, int mmu_idx); -uint32_t __ldl_cmmu(target_ulong addr, int mmu_idx); -void __stl_cmmu(target_ulong addr, uint32_t val, int mmu_idx); -uint64_t __ldq_cmmu(target_ulong addr, int mmu_idx); -void __stq_cmmu(target_ulong addr, uint64_t val, int mmu_idx); -#else uint8_t helper_ldb_mmu(CPUArchState *env, target_ulong addr, int mmu_idx); void helper_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val, int mmu_idx); @@ -54,5 +35,3 @@ uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); void helper_stq_cmmu(CPUArchState *env, target_ulong addr, uint64_t val, int mmu_idx); #endif - -#endif diff --git a/softmmu_header.h b/softmmu_header.h index cf1aa38fc7..d8d9c81b05 100644 --- a/softmmu_header.h +++ b/softmmu_header.h @@ -78,23 +78,10 @@ #define ADDR_READ addr_read #endif -#ifndef CONFIG_TCG_PASS_AREG0 -#define ENV_PARAM -#define ENV_VAR -#define CPU_PREFIX -#define HELPER_PREFIX __ -#else -#define ENV_PARAM CPUArchState *env, -#define ENV_VAR env, -#define CPU_PREFIX cpu_ -#define HELPER_PREFIX helper_ -#endif - /* generic load/store macros */ static inline RES_TYPE -glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM - target_ulong ptr) +glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) { int page_index; RES_TYPE res; @@ -106,9 +93,7 @@ glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM mmu_idx = CPU_MMU_INDEX; if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ != (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { - res = glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_VAR - addr, - mmu_idx); + res = glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(env, addr, mmu_idx); } else { uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; res = glue(glue(ld, USUFFIX), _raw)(hostaddr); @@ -118,8 +103,7 @@ glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM #if DATA_SIZE <= 2 static inline int -glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM - target_ulong ptr) +glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) { int res, page_index; target_ulong addr; @@ -130,8 +114,8 @@ glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM mmu_idx = CPU_MMU_INDEX; if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ != (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { - res = (DATA_STYPE)glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), - MMUSUFFIX)(ENV_VAR addr, mmu_idx); + res = (DATA_STYPE)glue(glue(helper_ld, SUFFIX), + MMUSUFFIX)(env, addr, mmu_idx); } else { uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; res = glue(glue(lds, SUFFIX), _raw)(hostaddr); @@ -145,8 +129,8 @@ glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM /* generic store macro */ static inline void -glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr, - RES_TYPE v) +glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr, + RES_TYPE v) { int page_index; target_ulong addr; @@ -157,8 +141,7 @@ glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr, mmu_idx = CPU_MMU_INDEX; if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write != (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { - glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_VAR addr, v, - mmu_idx); + glue(glue(helper_st, SUFFIX), MMUSUFFIX)(env, addr, v, mmu_idx); } else { uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; glue(glue(st, SUFFIX), _raw)(hostaddr, v); @@ -170,52 +153,50 @@ glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr, #if ACCESS_TYPE != (NB_MMU_MODES + 1) #if DATA_SIZE == 8 -static inline float64 glue(glue(CPU_PREFIX, ldfq), MEMSUFFIX)(ENV_PARAM - target_ulong ptr) +static inline float64 glue(cpu_ldfq, MEMSUFFIX)(CPUArchState *env, + target_ulong ptr) { union { float64 d; uint64_t i; } u; - u.i = glue(glue(CPU_PREFIX, ldq), MEMSUFFIX)(ENV_VAR ptr); + u.i = glue(cpu_ldq, MEMSUFFIX)(env, ptr); return u.d; } -static inline void glue(glue(CPU_PREFIX, stfq), MEMSUFFIX)(ENV_PARAM - target_ulong ptr, - float64 v) +static inline void glue(cpu_stfq, MEMSUFFIX)(CPUArchState *env, + target_ulong ptr, float64 v) { union { float64 d; uint64_t i; } u; u.d = v; - glue(glue(CPU_PREFIX, stq), MEMSUFFIX)(ENV_VAR ptr, u.i); + glue(cpu_stq, MEMSUFFIX)(env, ptr, u.i); } #endif /* DATA_SIZE == 8 */ #if DATA_SIZE == 4 -static inline float32 glue(glue(CPU_PREFIX, ldfl), MEMSUFFIX)(ENV_PARAM - target_ulong ptr) +static inline float32 glue(cpu_ldfl, MEMSUFFIX)(CPUArchState *env, + target_ulong ptr) { union { float32 f; uint32_t i; } u; - u.i = glue(glue(CPU_PREFIX, ldl), MEMSUFFIX)(ENV_VAR ptr); + u.i = glue(cpu_ldl, MEMSUFFIX)(env, ptr); return u.f; } -static inline void glue(glue(CPU_PREFIX, stfl), MEMSUFFIX)(ENV_PARAM - target_ulong ptr, - float32 v) +static inline void glue(cpu_stfl, MEMSUFFIX)(CPUArchState *env, + target_ulong ptr, float32 v) { union { float32 f; uint32_t i; } u; u.f = v; - glue(glue(CPU_PREFIX, stl), MEMSUFFIX)(ENV_VAR ptr, u.i); + glue(cpu_stl, MEMSUFFIX)(env, ptr, u.i); } #endif /* DATA_SIZE == 4 */ @@ -230,7 +211,3 @@ static inline void glue(glue(CPU_PREFIX, stfl), MEMSUFFIX)(ENV_PARAM #undef CPU_MMU_INDEX #undef MMUSUFFIX #undef ADDR_READ -#undef ENV_PARAM -#undef ENV_VAR -#undef CPU_PREFIX -#undef HELPER_PREFIX diff --git a/softmmu_template.h b/softmmu_template.h index b8bd700325..e2490f03a7 100644 --- a/softmmu_template.h +++ b/softmmu_template.h @@ -54,23 +54,11 @@ #define ADDR_READ addr_read #endif -#ifndef CONFIG_TCG_PASS_AREG0 -#define ENV_PARAM -#define ENV_VAR -#define CPU_PREFIX -#define HELPER_PREFIX __ -#else -#define ENV_PARAM CPUArchState *env, -#define ENV_VAR env, -#define CPU_PREFIX cpu_ -#define HELPER_PREFIX helper_ -#endif - -static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM +static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr, int mmu_idx, uintptr_t retaddr); -static inline DATA_TYPE glue(io_read, SUFFIX)(ENV_PARAM +static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env, target_phys_addr_t physaddr, target_ulong addr, uintptr_t retaddr) @@ -104,9 +92,8 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(ENV_PARAM /* handle all cases except unaligned access which span two pages */ DATA_TYPE -glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM - target_ulong addr, - int mmu_idx) +glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr, + int mmu_idx) { DATA_TYPE res; int index; @@ -126,15 +113,15 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM goto do_unaligned_access; retaddr = GETPC(); ioaddr = env->iotlb[mmu_idx][index]; - res = glue(io_read, SUFFIX)(ENV_VAR ioaddr, addr, retaddr); + res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr); } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { /* slow unaligned access (it spans two pages or IO) */ do_unaligned_access: retaddr = GETPC(); #ifdef ALIGNED_ONLY - do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr); + do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); #endif - res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_VAR addr, + res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(env, addr, mmu_idx, retaddr); } else { /* unaligned/aligned access in the same page */ @@ -142,7 +129,7 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) { retaddr = GETPC(); - do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr); + do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); } #endif addend = env->tlb_table[mmu_idx][index].addend; @@ -154,7 +141,7 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM retaddr = GETPC(); #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) - do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr); + do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); #endif tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); goto redo; @@ -164,7 +151,7 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM /* handle all unaligned cases */ static DATA_TYPE -glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM +glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr, int mmu_idx, uintptr_t retaddr) @@ -183,15 +170,15 @@ glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM if ((addr & (DATA_SIZE - 1)) != 0) goto do_unaligned_access; ioaddr = env->iotlb[mmu_idx][index]; - res = glue(io_read, SUFFIX)(ENV_VAR ioaddr, addr, retaddr); + res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr); } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { do_unaligned_access: /* slow unaligned access (it spans two pages) */ addr1 = addr & ~(DATA_SIZE - 1); addr2 = addr1 + DATA_SIZE; - res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_VAR addr1, + res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(env, addr1, mmu_idx, retaddr); - res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_VAR addr2, + res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(env, addr2, mmu_idx, retaddr); shift = (addr & (DATA_SIZE - 1)) * 8; #ifdef TARGET_WORDS_BIGENDIAN @@ -216,13 +203,13 @@ glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM #ifndef SOFTMMU_CODE_ACCESS -static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM +static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr, DATA_TYPE val, int mmu_idx, uintptr_t retaddr); -static inline void glue(io_write, SUFFIX)(ENV_PARAM +static inline void glue(io_write, SUFFIX)(CPUArchState *env, target_phys_addr_t physaddr, DATA_TYPE val, target_ulong addr, @@ -253,10 +240,9 @@ static inline void glue(io_write, SUFFIX)(ENV_PARAM #endif /* SHIFT > 2 */ } -void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM - target_ulong addr, - DATA_TYPE val, - int mmu_idx) +void glue(glue(helper_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, + target_ulong addr, DATA_TYPE val, + int mmu_idx) { target_phys_addr_t ioaddr; target_ulong tlb_addr; @@ -273,14 +259,14 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM goto do_unaligned_access; retaddr = GETPC(); ioaddr = env->iotlb[mmu_idx][index]; - glue(io_write, SUFFIX)(ENV_VAR ioaddr, val, addr, retaddr); + glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr); } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { do_unaligned_access: retaddr = GETPC(); #ifdef ALIGNED_ONLY - do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr); + do_unaligned_access(env, addr, 1, mmu_idx, retaddr); #endif - glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_VAR addr, val, + glue(glue(slow_st, SUFFIX), MMUSUFFIX)(env, addr, val, mmu_idx, retaddr); } else { /* aligned/unaligned access in the same page */ @@ -288,7 +274,7 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) { retaddr = GETPC(); - do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr); + do_unaligned_access(env, addr, 1, mmu_idx, retaddr); } #endif addend = env->tlb_table[mmu_idx][index].addend; @@ -300,7 +286,7 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM retaddr = GETPC(); #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) - do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr); + do_unaligned_access(env, addr, 1, mmu_idx, retaddr); #endif tlb_fill(env, addr, 1, mmu_idx, retaddr); goto redo; @@ -308,7 +294,7 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM } /* handles all unaligned cases */ -static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM +static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr, DATA_TYPE val, int mmu_idx, @@ -327,7 +313,7 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM if ((addr & (DATA_SIZE - 1)) != 0) goto do_unaligned_access; ioaddr = env->iotlb[mmu_idx][index]; - glue(io_write, SUFFIX)(ENV_VAR ioaddr, val, addr, retaddr); + glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr); } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { do_unaligned_access: /* XXX: not efficient, but simple */ @@ -335,11 +321,11 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM * previous page from the TLB cache. */ for(i = DATA_SIZE - 1; i >= 0; i--) { #ifdef TARGET_WORDS_BIGENDIAN - glue(slow_stb, MMUSUFFIX)(ENV_VAR addr + i, + glue(slow_stb, MMUSUFFIX)(env, addr + i, val >> (((DATA_SIZE - 1) * 8) - (i * 8)), mmu_idx, retaddr); #else - glue(slow_stb, MMUSUFFIX)(ENV_VAR addr + i, + glue(slow_stb, MMUSUFFIX)(env, addr + i, val >> (i * 8), mmu_idx, retaddr); #endif @@ -366,7 +352,3 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM #undef USUFFIX #undef DATA_SIZE #undef ADDR_READ -#undef ENV_PARAM -#undef ENV_VAR -#undef CPU_PREFIX -#undef HELPER_PREFIX diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c index 3116287093..aa005048e1 100644 --- a/target-m68k/op_helper.c +++ b/target-m68k/op_helper.c @@ -192,9 +192,6 @@ void HELPER(divu)(CPUM68KState *env, uint32_t word) quot = num / den; rem = num % den; flags = 0; - /* Avoid using a PARAM1 of zero. This breaks dyngen because it uses - the address of a symbol, and gcc knows symbols can't have address - zero. */ if (word && quot > 0xffff) flags |= CCF_V; if (quot == 0) diff --git a/target-sparc/Makefile.objs b/target-sparc/Makefile.objs index a93e07deb1..9fc42ea9b0 100644 --- a/target-sparc/Makefile.objs +++ b/target-sparc/Makefile.objs @@ -4,5 +4,3 @@ obj-y += fop_helper.o cc_helper.o win_helper.o mmu_helper.o ldst_helper.o obj-$(TARGET_SPARC) += int32_helper.o obj-$(TARGET_SPARC64) += int64_helper.o obj-$(TARGET_SPARC64) += vis_helper.o - -$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index cf0ca3d0b3..aed3b53247 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -176,7 +176,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) so don't use these. */ tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0); tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1); -#if defined(CONFIG_TCG_PASS_AREG0) && (TARGET_LONG_BITS == 64) +#if TARGET_LONG_BITS == 64 /* If we're passing env to the helper as r0 and need a regpair * for the address then r2 will be overwritten as we're setting * up the args to the helper. @@ -204,8 +204,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) use these. */ tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0); tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1); -#if defined(CONFIG_SOFTMMU) && \ - defined(CONFIG_TCG_PASS_AREG0) && (TARGET_LONG_BITS == 64) +#if defined(CONFIG_SOFTMMU) && (TARGET_LONG_BITS == 64) /* Avoid clashes with registers being used for helper args */ tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2); tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3); @@ -223,7 +222,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) #ifdef CONFIG_SOFTMMU /* r2 is still needed to load data_reg, so don't use it. */ tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2); -#if defined(CONFIG_TCG_PASS_AREG0) && (TARGET_LONG_BITS == 64) +#if TARGET_LONG_BITS == 64 /* Avoid clashes with registers being used for helper args */ tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3); #endif @@ -954,7 +953,6 @@ static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index) #include "../../softmmu_defs.h" -#ifdef CONFIG_TCG_PASS_AREG0 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void * const qemu_ld_helpers[4] = { @@ -972,25 +970,6 @@ static const void * const qemu_st_helpers[4] = { helper_stl_mmu, helper_stq_mmu, }; -#else -/* legacy helper signature: __ld_mmu(target_ulong addr, int - mmu_idx) */ -static void *qemu_ld_helpers[4] = { - __ldb_mmu, - __ldw_mmu, - __ldl_mmu, - __ldq_mmu, -}; - -/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val, - int mmu_idx) */ -static void *qemu_st_helpers[4] = { - __stb_mmu, - __stw_mmu, - __stl_mmu, - __stq_mmu, -}; -#endif /* Helper routines for marshalling helper function arguments into * the correct registers and stack. @@ -1203,9 +1182,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) * trash by moving the earlier arguments into them. */ argreg = TCG_REG_R0; -#ifdef CONFIG_TCG_PASS_AREG0 argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0); -#endif #if TARGET_LONG_BITS == 64 argreg = tcg_out_arg_reg64(s, argreg, addr_reg, addr_reg2); #else @@ -1421,9 +1398,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) * trash by moving the earlier arguments into them. */ argreg = TCG_REG_R0; -#ifdef CONFIG_TCG_PASS_AREG0 argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0); -#endif #if TARGET_LONG_BITS == 64 argreg = tcg_out_arg_reg64(s, argreg, addr_reg, addr_reg2); #else diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index f90b834795..c0b8f7274d 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -77,7 +77,6 @@ typedef enum { #define TCG_TARGET_HAS_GUEST_BASE enum { - /* Note: must be synced with dyngen-exec.h */ TCG_AREG0 = TCG_REG_R6, }; diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c index 2885212e3a..8b81b70f17 100644 --- a/tcg/hppa/tcg-target.c +++ b/tcg/hppa/tcg-target.c @@ -882,7 +882,6 @@ static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret, #if defined(CONFIG_SOFTMMU) #include "../../softmmu_defs.h" -#ifdef CONFIG_TCG_PASS_AREG0 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void * const qemu_ld_helpers[4] = { @@ -900,25 +899,6 @@ static const void * const qemu_st_helpers[4] = { helper_stl_mmu, helper_stq_mmu, }; -#else -/* legacy helper signature: __ld_mmu(target_ulong addr, int - mmu_idx) */ -static void *qemu_ld_helpers[4] = { - __ldb_mmu, - __ldw_mmu, - __ldl_mmu, - __ldq_mmu, -}; - -/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val, - int mmu_idx) */ -static void *qemu_st_helpers[4] = { - __stb_mmu, - __stw_mmu, - __stl_mmu, - __stq_mmu, -}; -#endif /* Load and compare a TLB entry, and branch if TLB miss. OFFSET is set to the offset of the first ADDR_READ or ADDR_WRITE member of the appropriate @@ -1085,7 +1065,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) } tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index); -#ifdef CONFIG_TCG_PASS_AREG0 /* XXX/FIXME: suboptimal */ tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], tcg_target_call_iarg_regs[1]); @@ -1093,7 +1072,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) tcg_target_call_iarg_regs[0]); tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0); -#endif tcg_out_call(s, qemu_ld_helpers[opc & 3]); switch (opc) { @@ -1245,7 +1223,6 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) tcg_abort(); } -#ifdef CONFIG_TCG_PASS_AREG0 /* XXX/FIXME: suboptimal */ tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3], tcg_target_call_iarg_regs[2]); @@ -1255,7 +1232,6 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) tcg_target_call_iarg_regs[0]); tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0); -#endif tcg_out_call(s, qemu_st_helpers[opc]); /* label2: */ diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h index d4bf6fe756..01ef9605f7 100644 --- a/tcg/hppa/tcg-target.h +++ b/tcg/hppa/tcg-target.h @@ -104,7 +104,6 @@ typedef enum { #define TCG_TARGET_HAS_GUEST_BASE -/* Note: must be synced with dyngen-exec.h */ #define TCG_AREG0 TCG_REG_R17 diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index da17bba39d..34c2df80a6 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -183,9 +183,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_set32(ct->u.regs, 0, 0xffff); tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[0]); tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[1]); -#ifdef CONFIG_TCG_PASS_AREG0 tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[2]); -#endif } else { tcg_regset_set32(ct->u.regs, 0, 0xff); tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX); @@ -965,7 +963,6 @@ static void tcg_out_jmp(TCGContext *s, tcg_target_long dest) #include "../../softmmu_defs.h" -#ifdef CONFIG_TCG_PASS_AREG0 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void *qemu_ld_helpers[4] = { @@ -983,25 +980,6 @@ static const void *qemu_st_helpers[4] = { helper_stl_mmu, helper_stq_mmu, }; -#else -/* legacy helper signature: __ld_mmu(target_ulong addr, int - mmu_idx) */ -static void *qemu_ld_helpers[4] = { - __ldb_mmu, - __ldw_mmu, - __ldl_mmu, - __ldq_mmu, -}; - -/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val, - int mmu_idx) */ -static void *qemu_st_helpers[4] = { - __stb_mmu, - __stw_mmu, - __stl_mmu, - __stq_mmu, -}; -#endif /* Perform the TLB load and compare. @@ -1220,16 +1198,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, } tcg_out_push(s, args[addrlo_idx]); stack_adjust += 4; -#ifdef CONFIG_TCG_PASS_AREG0 tcg_out_push(s, TCG_AREG0); stack_adjust += 4; -#endif #else /* The first argument is already loaded with addrlo. */ arg_idx = 1; tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx], mem_index); -#ifdef CONFIG_TCG_PASS_AREG0 /* XXX/FIXME: suboptimal */ tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3], tcg_target_call_iarg_regs[2]); @@ -1239,7 +1214,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, tcg_target_call_iarg_regs[0]); tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0); -#endif #endif tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]); @@ -1436,16 +1410,13 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, } tcg_out_push(s, args[addrlo_idx]); stack_adjust += 4; -#ifdef CONFIG_TCG_PASS_AREG0 tcg_out_push(s, TCG_AREG0); stack_adjust += 4; -#endif #else tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32), tcg_target_call_iarg_regs[1], data_reg); tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], mem_index); stack_adjust = 0; -#ifdef CONFIG_TCG_PASS_AREG0 /* XXX/FIXME: suboptimal */ tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3], tcg_target_call_iarg_regs[2]); @@ -1455,7 +1426,6 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, tcg_target_call_iarg_regs[0]); tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0); -#endif #endif tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]); diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index c3cfe05f62..8be42f3ccb 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -116,7 +116,6 @@ typedef enum { #define TCG_TARGET_HAS_GUEST_BASE -/* Note: must be synced with dyngen-exec.h */ #if TCG_TARGET_REG_BITS == 64 # define TCG_AREG0 TCG_REG_R14 #else diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index dc588dbea5..1745038f14 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1452,7 +1452,6 @@ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGArg addr_reg, TCG_REG_P7, TCG_REG_R3, TCG_REG_R57)); } -#ifdef CONFIG_TCG_PASS_AREG0 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void * const qemu_ld_helpers[4] = { @@ -1461,16 +1460,6 @@ static const void * const qemu_ld_helpers[4] = { helper_ldl_mmu, helper_ldq_mmu, }; -#else -/* legacy helper signature: __ld_mmu(target_ulong addr, int - mmu_idx) */ -static void *qemu_ld_helpers[4] = { - __ldb_mmu, - __ldw_mmu, - __ldl_mmu, - __ldq_mmu, -}; -#endif static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) { @@ -1530,7 +1519,6 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0)); } -#ifdef CONFIG_TCG_PASS_AREG0 /* XXX/FIXME: suboptimal */ tcg_out_bundle(s, mII, tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R58, @@ -1539,7 +1527,6 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) TCG_REG_R57, 0, TCG_REG_R56), tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, TCG_REG_R56, 0, TCG_AREG0)); -#endif if (!bswap || s_bits == 0) { tcg_out_bundle(s, miB, tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), @@ -1570,7 +1557,6 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) } } -#ifdef CONFIG_TCG_PASS_AREG0 /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr, uintxx_t val, int mmu_idx) */ static const void * const qemu_st_helpers[4] = { @@ -1579,16 +1565,6 @@ static const void * const qemu_st_helpers[4] = { helper_stl_mmu, helper_stq_mmu, }; -#else -/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val, - int mmu_idx) */ -static void *qemu_st_helpers[4] = { - __stb_mmu, - __stw_mmu, - __stl_mmu, - __stq_mmu, -}; -#endif static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) { @@ -1658,7 +1634,6 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) data_reg = TCG_REG_R2; } -#ifdef CONFIG_TCG_PASS_AREG0 /* XXX/FIXME: suboptimal */ tcg_out_bundle(s, mII, tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R59, @@ -1674,15 +1649,6 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) TCG_REG_R56, 0, TCG_AREG0), tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, TCG_REG_B0, TCG_REG_B6)); -#else - tcg_out_bundle(s, miB, - tcg_opc_m4 (TCG_REG_P6, opc_st_m4[opc], - data_reg, TCG_REG_R3), - tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R58, - mem_index, TCG_REG_R0), - tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, - TCG_REG_B0, TCG_REG_B6)); -#endif } #else /* !CONFIG_SOFTMMU */ diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index 0631b9f180..c22962ac12 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -140,7 +140,6 @@ typedef enum { #define TCG_TARGET_HAS_not_i32 0 /* xor r1, -1, r3 */ #define TCG_TARGET_HAS_not_i64 0 /* xor r1, -1, r3 */ -/* Note: must be synced with dyngen-exec.h */ #define TCG_AREG0 TCG_REG_R7 /* Guest base is supported */ diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index 1006e28000..74db83d440 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -217,7 +217,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_set(ct->u.regs, 0xffffffff); #if defined(CONFIG_SOFTMMU) tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0); -# if defined(CONFIG_TCG_PASS_AREG0) && (TARGET_LONG_BITS == 64) +# if (TARGET_LONG_BITS == 64) tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2); # endif #endif @@ -227,12 +227,11 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_set(ct->u.regs, 0xffffffff); tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0); #if defined(CONFIG_SOFTMMU) -# if (defined(CONFIG_TCG_PASS_AREG0) && TARGET_LONG_BITS == 32) || \ - (!defined(CONFIG_TCG_PASS_AREG0) && TARGET_LONG_BITS == 64) +# if (TARGET_LONG_BITS == 32) tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1); # endif tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2); -# if defined(CONFIG_TCG_PASS_AREG0) && TARGET_LONG_BITS == 64 +# if TARGET_LONG_BITS == 64 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3); # endif #endif @@ -821,7 +820,6 @@ static void tcg_out_setcond2(TCGContext *s, TCGCond cond, int ret, #include "../../softmmu_defs.h" -#ifdef CONFIG_TCG_PASS_AREG0 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void * const qemu_ld_helpers[4] = { @@ -839,25 +837,6 @@ static const void * const qemu_st_helpers[4] = { helper_stl_mmu, helper_stq_mmu, }; -#else -/* legacy helper signature: __ld_mmu(target_ulong addr, int - mmu_idx) */ -static void *qemu_ld_helpers[4] = { - __ldb_mmu, - __ldw_mmu, - __ldl_mmu, - __ldq_mmu, -}; - -/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val, - int mmu_idx) */ -static void *qemu_st_helpers[4] = { - __stb_mmu, - __stw_mmu, - __stl_mmu, - __stq_mmu, -}; -#endif #endif static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, @@ -942,9 +921,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, /* slow path */ arg_num = 0; -# ifdef CONFIG_TCG_PASS_AREG0 tcg_out_call_iarg_reg32(s, &arg_num, TCG_AREG0); -# endif # if TARGET_LONG_BITS == 64 tcg_out_call_iarg_reg64(s, &arg_num, addr_regl, addr_regh); # else @@ -1127,9 +1104,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, /* slow path */ arg_num = 0; -# ifdef CONFIG_TCG_PASS_AREG0 tcg_out_call_iarg_reg32(s, &arg_num, TCG_AREG0); -# endif # if TARGET_LONG_BITS == 64 tcg_out_call_iarg_reg64(s, &arg_num, addr_regl, addr_regh); # else diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index d3c804d9a4..1c6193180c 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -96,7 +96,6 @@ typedef enum { #define TCG_TARGET_HAS_ext8u_i32 0 /* andi rt, rs, 0xff */ #define TCG_TARGET_HAS_ext16u_i32 0 /* andi rt, rs, 0xffff */ -/* Note: must be synced with dyngen-exec.h */ #define TCG_AREG0 TCG_REG_S0 /* guest base is supported */ diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 0cff181257..26c4b33e60 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -248,18 +248,12 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_set32(ct->u.regs, 0, 0xffffffff); tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3); tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4); -#ifdef CONFIG_TCG_PASS_AREG0 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5); #if TARGET_LONG_BITS == 64 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6); #ifdef TCG_TARGET_CALL_ALIGN_ARGS tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7); #endif -#endif -#else /* !AREG0 */ -#if TARGET_LONG_BITS == 64 - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5); -#endif #endif break; case 'K': /* qemu_st[8..32] constraint */ @@ -268,18 +262,12 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3); tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4); tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5); -#ifdef CONFIG_TCG_PASS_AREG0 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6); #if TARGET_LONG_BITS == 64 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7); #ifdef TCG_TARGET_CALL_ALIGN_ARGS tcg_regset_reset_reg(ct->u.regs, TCG_REG_R8); #endif -#endif -#else /* !AREG0 */ -#if TARGET_LONG_BITS == 64 - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6); -#endif #endif break; case 'M': /* qemu_st64 constraint */ @@ -290,11 +278,9 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5); tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6); tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7); -#if defined(CONFIG_TCG_PASS_AREG0) tcg_regset_reset_reg(ct->u.regs, TCG_REG_R8); #ifdef TCG_TARGET_CALL_ALIGN_ARGS tcg_regset_reset_reg(ct->u.regs, TCG_REG_R9); -#endif #endif break; #else @@ -541,7 +527,6 @@ static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg) #include "../../softmmu_defs.h" -#ifdef CONFIG_TCG_PASS_AREG0 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void * const qemu_ld_helpers[4] = { @@ -559,25 +544,6 @@ static const void * const qemu_st_helpers[4] = { helper_stl_mmu, helper_stq_mmu, }; -#else -/* legacy helper signature: __ld_mmu(target_ulong addr, int - mmu_idx) */ -static void *qemu_ld_helpers[4] = { - __ldb_mmu, - __ldw_mmu, - __ldl_mmu, - __ldq_mmu, -}; - -/* legacy helper signature: __ld_mmu(target_ulong addr, int - mmu_idx) */ -static void *qemu_st_helpers[4] = { - __stb_mmu, - __stw_mmu, - __stl_mmu, - __stq_mmu, -}; -#endif #endif static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) @@ -647,9 +613,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) /* slow path */ ir = 3; -#ifdef CONFIG_TCG_PASS_AREG0 tcg_out_mov (s, TCG_TYPE_I32, ir++, TCG_AREG0); -#endif #if TARGET_LONG_BITS == 32 tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg); #else @@ -849,9 +813,7 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) /* slow path */ ir = 3; -#ifdef CONFIG_TCG_PASS_AREG0 tcg_out_mov (s, TCG_TYPE_I32, ir++, TCG_AREG0); -#endif #if TARGET_LONG_BITS == 32 tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg); #else diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c index 27a0ae88ec..337cd419f8 100644 --- a/tcg/ppc64/tcg-target.c +++ b/tcg/ppc64/tcg-target.c @@ -235,9 +235,7 @@ static int target_parse_constraint (TCGArgConstraint *ct, const char **pct_str) tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3); #ifdef CONFIG_SOFTMMU tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4); -#ifdef CONFIG_TCG_PASS_AREG0 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R5); -#endif #endif break; case 'S': /* qemu_st constraint */ @@ -247,9 +245,7 @@ static int target_parse_constraint (TCGArgConstraint *ct, const char **pct_str) #ifdef CONFIG_SOFTMMU tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4); tcg_regset_reset_reg (ct->u.regs, TCG_REG_R5); -#ifdef CONFIG_TCG_PASS_AREG0 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R6); -#endif #endif break; case 'Z': @@ -558,7 +554,6 @@ static void tcg_out_ldsta (TCGContext *s, int ret, int addr, #include "../../softmmu_defs.h" -#ifdef CONFIG_TCG_PASS_AREG0 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void * const qemu_ld_helpers[4] = { @@ -576,25 +571,6 @@ static const void * const qemu_st_helpers[4] = { helper_stl_mmu, helper_stq_mmu, }; -#else -/* legacy helper signature: __ld_mmu(target_ulong addr, int - mmu_idx) */ -static void *qemu_ld_helpers[4] = { - __ldb_mmu, - __ldw_mmu, - __ldl_mmu, - __ldq_mmu, -}; - -/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val, - int mmu_idx) */ -static void *qemu_st_helpers[4] = { - __stb_mmu, - __stw_mmu, - __stl_mmu, - __stq_mmu, -}; -#endif static void tcg_out_tlb_read (TCGContext *s, int r0, int r1, int r2, int addr_reg, int s_bits, int offset) @@ -676,9 +652,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) /* slow path */ ir = 3; -#ifdef CONFIG_TCG_PASS_AREG0 tcg_out_mov (s, TCG_TYPE_I64, ir++, TCG_AREG0); -#endif tcg_out_mov (s, TCG_TYPE_I64, ir++, addr_reg); tcg_out_movi (s, TCG_TYPE_I64, ir++, mem_index); @@ -827,9 +801,7 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) /* slow path */ ir = 3; -#ifdef CONFIG_TCG_PASS_AREG0 tcg_out_mov (s, TCG_TYPE_I64, ir++, TCG_AREG0); -#endif tcg_out_mov (s, TCG_TYPE_I64, ir++, addr_reg); tcg_out_rld (s, RLDICL, ir++, data_reg, 0, 64 - (1 << (3 + opc))); tcg_out_movi (s, TCG_TYPE_I64, ir++, mem_index); diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c index 99b53390c5..aac11d9b61 100644 --- a/tcg/s390/tcg-target.c +++ b/tcg/s390/tcg-target.c @@ -301,7 +301,6 @@ static const uint8_t tcg_cond_to_ltr_cond[10] = { #include "../../softmmu_defs.h" -#ifdef CONFIG_TCG_PASS_AREG0 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void * const qemu_ld_helpers[4] = { @@ -319,25 +318,6 @@ static const void * const qemu_st_helpers[4] = { helper_stl_mmu, helper_stq_mmu, }; -#else -/* legacy helper signature: __ld_mmu(target_ulong addr, int - mmu_idx) */ -static void *qemu_ld_helpers[4] = { - __ldb_mmu, - __ldw_mmu, - __ldl_mmu, - __ldq_mmu, -}; - -/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val, - int mmu_idx) */ -static void *qemu_st_helpers[4] = { - __stb_mmu, - __stw_mmu, - __stl_mmu, - __stq_mmu, -}; -#endif #endif static uint8_t *tb_ret_addr; @@ -1507,7 +1487,6 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg, tcg_abort(); } tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R4, mem_index); -#ifdef CONFIG_TCG_PASS_AREG0 /* XXX/FIXME: suboptimal */ tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3], tcg_target_call_iarg_regs[2]); @@ -1517,11 +1496,9 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg, tcg_target_call_iarg_regs[0]); tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0); -#endif tgen_calli(s, (tcg_target_ulong)qemu_st_helpers[s_bits]); } else { tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index); -#ifdef CONFIG_TCG_PASS_AREG0 /* XXX/FIXME: suboptimal */ tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], tcg_target_call_iarg_regs[1]); @@ -1529,7 +1506,6 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg, tcg_target_call_iarg_regs[0]); tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0); -#endif tgen_calli(s, (tcg_target_ulong)qemu_ld_helpers[s_bits]); /* sign extension */ diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h index d12f90b705..4f7dfaba50 100644 --- a/tcg/s390/tcg-target.h +++ b/tcg/s390/tcg-target.h @@ -96,7 +96,6 @@ typedef enum TCGReg { #define TCG_TARGET_EXTEND_ARGS 1 enum { - /* Note: must be synced with dyngen-exec.h */ TCG_AREG0 = TCG_REG_R10, }; diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 247a27814a..baed3b49ff 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -59,11 +59,7 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { }; #endif -#ifdef CONFIG_TCG_PASS_AREG0 #define ARG_OFFSET 1 -#else -#define ARG_OFFSET 0 -#endif static const int tcg_target_reg_alloc_order[] = { TCG_REG_L0, @@ -161,9 +157,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0); tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1); tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2); -#ifdef CONFIG_TCG_PASS_AREG0 tcg_regset_reset_reg(ct->u.regs, TCG_REG_O3); -#endif break; case 'I': ct->ct |= TCG_CT_CONST_S11; @@ -715,7 +709,6 @@ static void tcg_target_qemu_prologue(TCGContext *s) #include "../../softmmu_defs.h" -#ifdef CONFIG_TCG_PASS_AREG0 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void * const qemu_ld_helpers[4] = { @@ -733,25 +726,6 @@ static const void * const qemu_st_helpers[4] = { helper_stl_mmu, helper_stq_mmu, }; -#else -/* legacy helper signature: __ld_mmu(target_ulong addr, int - mmu_idx) */ -static const void * const qemu_ld_helpers[4] = { - __ldb_mmu, - __ldw_mmu, - __ldl_mmu, - __ldq_mmu, -}; - -/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val, - int mmu_idx) */ -static const void * const qemu_st_helpers[4] = { - __stb_mmu, - __stw_mmu, - __stl_mmu, - __stq_mmu, -}; -#endif #endif #if TARGET_LONG_BITS == 32 @@ -834,7 +808,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, /* mov */ tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index); -#ifdef CONFIG_TCG_PASS_AREG0 /* XXX/FIXME: suboptimal */ tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3], tcg_target_call_iarg_regs[2]); @@ -844,7 +817,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, tcg_target_call_iarg_regs[0]); tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0); -#endif /* XXX: move that code at the end of the TB */ /* qemu_ld_helper[s_bits](arg0, arg1) */ @@ -1061,7 +1033,6 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, /* mov */ tcg_out_movi(s, TCG_TYPE_I32, arg2, mem_index); -#ifdef CONFIG_TCG_PASS_AREG0 /* XXX/FIXME: suboptimal */ tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3], tcg_target_call_iarg_regs[2]); @@ -1071,7 +1042,6 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, tcg_target_call_iarg_regs[0]); tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0); -#endif /* XXX: move that code at the end of the TB */ /* qemu_st_helper[s_bits](arg0, arg1, arg2) */ tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[s_bits] diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index ee2274d595..0ea87bef72 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -125,7 +125,6 @@ typedef enum { #define TCG_TARGET_HAS_deposit_i64 0 #endif -/* Note: must be synced with dyngen-exec.h */ #ifdef CONFIG_SOLARIS #define TCG_AREG0 TCG_REG_G2 #elif defined(__sparc_v9__) diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c index ef8580fc8d..003244cb0b 100644 --- a/tcg/tci/tcg-target.c +++ b/tcg/tci/tcg-target.c @@ -798,9 +798,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_qemu_st8: case INDEX_op_qemu_st16: case INDEX_op_qemu_st32: -#ifdef CONFIG_TCG_PASS_AREG0 tcg_out_r(s, TCG_AREG0); -#endif tcg_out_r(s, *args++); tcg_out_r(s, *args++); #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS @@ -811,9 +809,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, #endif break; case INDEX_op_qemu_st64: -#ifdef CONFIG_TCG_PASS_AREG0 tcg_out_r(s, TCG_AREG0); -#endif tcg_out_r(s, *args++); #if TCG_TARGET_REG_BITS == 32 tcg_out_r(s, *args++); diff --git a/tci.c b/tci.c index c79350d242..ce8a988147 100644 --- a/tci.c +++ b/tci.c @@ -25,7 +25,6 @@ #endif #include "qemu-common.h" -#include "dyngen-exec.h" /* env */ #include "exec-all.h" /* MAX_OPC_PARAM_IARGS */ #include "tcg-op.h" @@ -63,17 +62,6 @@ uintptr_t tci_tb_ptr; static tcg_target_ulong tci_reg[TCG_TARGET_NB_REGS]; -#if !defined(CONFIG_TCG_PASS_AREG0) -# define helper_ldb_mmu(env, addr, mmu_idx) __ldb_mmu(addr, mmu_idx) -# define helper_ldw_mmu(env, addr, mmu_idx) __ldw_mmu(addr, mmu_idx) -# define helper_ldl_mmu(env, addr, mmu_idx) __ldl_mmu(addr, mmu_idx) -# define helper_ldq_mmu(env, addr, mmu_idx) __ldq_mmu(addr, mmu_idx) -# define helper_stb_mmu(env, addr, val, mmu_idx) __stb_mmu(addr, val, mmu_idx) -# define helper_stw_mmu(env, addr, val, mmu_idx) __stw_mmu(addr, val, mmu_idx) -# define helper_stl_mmu(env, addr, val, mmu_idx) __stl_mmu(addr, val, mmu_idx) -# define helper_stq_mmu(env, addr, val, mmu_idx) __stq_mmu(addr, val, mmu_idx) -#endif /* !CONFIG_TCG_PASS_AREG0 */ - static tcg_target_ulong tci_read_reg(TCGReg index) { assert(index < ARRAY_SIZE(tci_reg)); diff --git a/user-exec.c b/user-exec.c index b9ea9dd32f..ef9b1727b3 100644 --- a/user-exec.c +++ b/user-exec.c @@ -18,9 +18,6 @@ */ #include "config.h" #include "cpu.h" -#ifndef CONFIG_TCG_PASS_AREG0 -#include "dyngen-exec.h" -#endif #include "disas.h" #include "tcg.h" @@ -60,12 +57,6 @@ void cpu_resume_from_signal(CPUArchState *env1, void *puc) struct sigcontext *uc = puc; #endif -#ifndef CONFIG_TCG_PASS_AREG0 - env = env1; - - /* XXX: restore cpu registers saved in host registers */ -#endif - if (puc) { /* XXX: use siglongjmp ? */ #ifdef __linux__ @@ -93,11 +84,6 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address, TranslationBlock *tb; int ret; -#ifndef CONFIG_TCG_PASS_AREG0 - if (cpu_single_env) { - env = cpu_single_env; /* XXX: find a correct solution for multithread */ - } -#endif #if defined(DEBUG_SIGNAL) qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", pc, address, is_write, *(unsigned long *)old_set); From 8490fc78e708eaaaa20f06b5efe190bfeabe0064 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 5 Sep 2012 16:50:16 -0300 Subject: [PATCH 0404/2270] add -machine mem-merge=on|off option It allows to disable memory merge support (KSM on Linux), which is enabled by default otherwise. Signed-off-by: Luiz Capitulino Signed-off-by: Anthony Liguori --- exec.c | 19 ++++++++++++++++--- qemu-config.c | 4 ++++ qemu-options.hx | 7 ++++++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/exec.c b/exec.c index 58347664b2..c0fbd5b149 100644 --- a/exec.c +++ b/exec.c @@ -2525,6 +2525,19 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) } } +static int memory_try_enable_merging(void *addr, size_t len) +{ + QemuOpts *opts; + + opts = qemu_opts_find(qemu_find_opts("machine"), 0); + if (opts && !qemu_opt_get_bool(opts, "mem-merge", true)) { + /* disabled by the user */ + return 0; + } + + return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE); +} + ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, MemoryRegion *mr) { @@ -2544,7 +2557,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, new_block->host = file_ram_alloc(new_block, size, mem_path); if (!new_block->host) { new_block->host = qemu_vmalloc(size); - qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE); + memory_try_enable_merging(new_block->host, size); } #else fprintf(stderr, "-mem-path option unsupported\n"); @@ -2559,7 +2572,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, } else { new_block->host = qemu_vmalloc(size); } - qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE); + memory_try_enable_merging(new_block->host, size); } } new_block->length = size; @@ -2689,7 +2702,7 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) length, addr); exit(1); } - qemu_madvise(vaddr, length, QEMU_MADV_MERGEABLE); + memory_try_enable_merging(vaddr, length); qemu_ram_setup_dump(vaddr, length); } return; diff --git a/qemu-config.c b/qemu-config.c index eba977ebca..12eafbb4f5 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -615,6 +615,10 @@ static QemuOptsList qemu_machine_opts = { .name = "dump-guest-core", .type = QEMU_OPT_BOOL, .help = "Include guest memory in a core dump", + }, { + .name = "mem-merge", + .type = QEMU_OPT_BOOL, + .help = "enable/disable memory merge support", }, { /* End of list */ } }, diff --git a/qemu-options.hx b/qemu-options.hx index 804a2d1739..5f96f356c3 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -38,7 +38,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \ " supported accelerators are kvm, xen, tcg (default: tcg)\n" " kernel_irqchip=on|off controls accelerated irqchip support\n" " kvm_shadow_mem=size of KVM shadow MMU\n" - " dump-guest-core=on|off include guest memory in a core dump (default=on)\n", + " dump-guest-core=on|off include guest memory in a core dump (default=on)\n" + " mem-merge=on|off controls memory merge support (default: on)\n", QEMU_ARCH_ALL) STEXI @item -machine [type=]@var{name}[,prop=@var{value}[,...]] @@ -57,6 +58,10 @@ Enables in-kernel irqchip support for the chosen accelerator when available. Defines the size of the KVM shadow MMU. @item dump-guest-core=on|off Include guest memory in a core dump. The default is on. +@item mem-merge=on|off +Enables or disables memory merge support. This feature, when supported by +the host, de-duplicates identical memory pages among VMs instances +(enabled by default). @end table ETEXI From ed0ec1aa858ac1fcfe3664e4159e695c2c063df8 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 11 Sep 2012 16:38:25 +0200 Subject: [PATCH 0405/2270] pc: Drop practically unused BOCHS BIOS debug ports We have debugcon these days to listen on those ports that receive debug messages. Also drop the others that have no effect anymore. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- hw/pc.c | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/hw/pc.c b/hw/pc.c index 112739a278..7e7e0e2235 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -53,9 +53,6 @@ #include "bitmap.h" #include "vga-pci.h" -/* output Bochs bios info messages */ -//#define DEBUG_BIOS - /* debug PC/ISA interrupts */ //#define DEBUG_IRQ @@ -534,17 +531,6 @@ static void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val) static int shutdown_index = 0; switch(addr) { - /* Bochs BIOS messages */ - case 0x400: - case 0x401: - /* used to be panic, now unused */ - break; - case 0x402: - case 0x403: -#ifdef DEBUG_BIOS - fprintf(stderr, "%c", val); -#endif - break; case 0x8900: /* same as Bochs power off */ if (val == shutdown_str[shutdown_index]) { @@ -558,16 +544,9 @@ static void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val) } break; - /* LGPL'ed VGA BIOS messages */ case 0x501: case 0x502: exit((val << 1) | 1); - case 0x500: - case 0x503: -#ifdef DEBUG_BIOS - fprintf(stderr, "%c", val); -#endif - break; } } @@ -596,17 +575,11 @@ static void *bochs_bios_init(void) uint64_t *numa_fw_cfg; int i, j; - register_ioport_write(0x400, 1, 2, bochs_bios_write, NULL); - register_ioport_write(0x401, 1, 2, bochs_bios_write, NULL); - register_ioport_write(0x402, 1, 1, bochs_bios_write, NULL); - register_ioport_write(0x403, 1, 1, bochs_bios_write, NULL); register_ioport_write(0x8900, 1, 1, bochs_bios_write, NULL); register_ioport_write(0x501, 1, 1, bochs_bios_write, NULL); register_ioport_write(0x501, 1, 2, bochs_bios_write, NULL); register_ioport_write(0x502, 1, 2, bochs_bios_write, NULL); - register_ioport_write(0x500, 1, 1, bochs_bios_write, NULL); - register_ioport_write(0x503, 1, 1, bochs_bios_write, NULL); fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0); From 6db0fdce02d72546a4c47100a9b2cd0090cf464d Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Wed, 12 Sep 2012 14:34:07 -0500 Subject: [PATCH 0406/2270] Revert 455aa1e08 and c3767ed0eb commit c3767ed0eb5d0bb25fe409ae5dec06e3411ff1b6 qemu-char: (Re-)connect for tcp_chr_write() unconnected writing Has no hope of working because tcp_chr_connect() does not actually connect. 455aa1e08 just fixes the SEGV with server() but the attempt to connect a client socket is still completely broken. This patch reverts both. Reported-by: Richard W.M. Jones Signed-off-by: Anthony Liguori --- qemu-char.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 767da93862..10d1504948 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2141,18 +2141,13 @@ typedef struct { static void tcp_chr_accept(void *opaque); -static void tcp_chr_connect(void *opaque); - static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) { TCPCharDriver *s = chr->opaque; if (s->connected) { return send_all(s->fd, buf, len); - } else if (s->listen_fd == -1) { - /* (Re-)connect for unconnected writing */ - tcp_chr_connect(chr); - return 0; } else { + /* XXX: indicate an error ? */ return len; } } From bbdd2ad0814ea0911076419ea21b7957505cf1cc Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 10 Sep 2012 12:30:56 +1000 Subject: [PATCH 0407/2270] qemu-char: BUGFIX, don't call FD_ISSET with negative fd tcp_chr_connect(), unlike for example udp_chr_update_read_handler() does not check if the fd it is using is valid (>= 0) before passing it to qemu_set_fd_handler2(). If using e.g. a TCP serial port, which is not initially connected, this can result in -1 being passed to FD_ISSET, which has undefined behaviour. On x86 it seems to harmlessly return 0, but on PowerPC, it causes a fortify buffer overflow error to be thrown. This patch fixes this by putting an extra test in tcp_chr_connect(), and also adds an assert qemu_set_fd_handler2() to catch other such errors on all platforms, rather than just some. Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- iohandler.c | 2 ++ qemu-char.c | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/iohandler.c b/iohandler.c index dea43552d2..a2d871bb91 100644 --- a/iohandler.c +++ b/iohandler.c @@ -56,6 +56,8 @@ int qemu_set_fd_handler2(int fd, { IOHandlerRecord *ioh; + assert(fd >= 0); + if (!fd_read && !fd_write) { QLIST_FOREACH(ioh, &io_handlers, next) { if (ioh->fd == fd) { diff --git a/qemu-char.c b/qemu-char.c index 10d1504948..7f0f895157 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2329,8 +2329,10 @@ static void tcp_chr_connect(void *opaque) TCPCharDriver *s = chr->opaque; s->connected = 1; - qemu_set_fd_handler2(s->fd, tcp_chr_read_poll, - tcp_chr_read, NULL, chr); + if (s->fd >= 0) { + qemu_set_fd_handler2(s->fd, tcp_chr_read_poll, + tcp_chr_read, NULL, chr); + } qemu_chr_generic_open(chr); } From 0b57e287138728f72d88b06e69b970c5d745c44a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 10 Sep 2012 12:30:57 +1000 Subject: [PATCH 0408/2270] cpu_physical_memory_write_rom() needs to do TB invalidates cpu_physical_memory_write_rom(), despite the name, can also be used to write images into RAM - and will often be used that way if the machine uses load_image_targphys() into RAM addresses. However, cpu_physical_memory_write_rom(), unlike cpu_physical_memory_rw() doesn't invalidate any cached TBs which might be affected by the region written. This was breaking reset (under full emu) on the pseries machine - we loaded our firmware image into RAM, and while executing it rewrite the code at the entry point (correctly causing a TB invalidate/refresh). When we reset the firmware image was reloaded, but the TB from the rewrite was still active and caused us to get an illegal instruction trap. This patch fixes the bug by duplicating the tb invalidate code from cpu_physical_memory_rw() in cpu_physical_memory_write_rom(). Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- exec.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/exec.c b/exec.c index c0fbd5b149..f22e9e6951 100644 --- a/exec.c +++ b/exec.c @@ -3536,6 +3536,13 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr, /* ROM/RAM case */ ptr = qemu_get_ram_ptr(addr1); memcpy(ptr, buf, l); + if (!cpu_physical_memory_is_dirty(addr1)) { + /* invalidate code */ + tb_invalidate_phys_page_range(addr1, addr1 + l, 0); + /* set dirty bit */ + cpu_physical_memory_set_dirty_flags( + addr1, (0xff & ~CODE_DIRTY_FLAG)); + } qemu_put_ram_ptr(ptr); } len -= l; From 121afa9e0c02617c2a774996512e4f85f3e93da8 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Fri, 14 Sep 2012 08:17:03 -0500 Subject: [PATCH 0409/2270] Revert "Add ability to disable build of all targets" This reverts commit 66d5499b3754b83c09487259c08fe2ce73188a59. This commit broke --target-list="x86_64-softmmu" and the fix isn't immediatley obvious. Signed-off-by: Anthony Liguori --- configure | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 7e23309dd4..b13fde733b 100755 --- a/configure +++ b/configure @@ -126,7 +126,7 @@ cc_i386=i386-pc-linux-gnu-gcc libs_qga="" debug_info="yes" -target_list="DEFAULT" +target_list="" # Default value for a variable defining feature "foo". # * foo="no" feature will only be used if --enable-foo arg is given @@ -1319,10 +1319,15 @@ if ! "$python" -c 'import sys; sys.exit(sys.version_info < (2,4) or sys.version_ exit 1 fi -if test "$target_list" = "DEFAULT" ; then - target_list=`echo "$default_target_list" | sed -e 's/,/ /g'` +if test -z "$target_list" ; then + target_list="$default_target_list" +else + target_list=`echo "$target_list" | sed -e 's/,/ /g'` +fi +if test -z "$target_list" ; then + echo "No targets enabled" + exit 1 fi - # see if system emulation was really requested case " $target_list " in *"-softmmu "*) softmmu=yes From fa26c26b078b298a18686adb06a38bea3cdee990 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 22 Aug 2012 15:13:30 +0200 Subject: [PATCH 0410/2270] nbd: add more constants Avoid magic numbers and magic size computations; hide them behind constants. Signed-off-by: Paolo Bonzini --- nbd.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/nbd.c b/nbd.c index 0dd60c5f4c..8201b7a392 100644 --- a/nbd.c +++ b/nbd.c @@ -57,9 +57,12 @@ /* This is all part of the "official" NBD API */ +#define NBD_REQUEST_SIZE (4 + 4 + 8 + 8 + 4) #define NBD_REPLY_SIZE (4 + 4 + 8) #define NBD_REQUEST_MAGIC 0x25609513 #define NBD_REPLY_MAGIC 0x67446698 +#define NBD_OPTS_MAGIC 0x49484156454F5054LL +#define NBD_CLIENT_MAGIC 0x0000420281861253LL #define NBD_SET_SOCK _IO(0xab, 0) #define NBD_SET_BLKSIZE _IO(0xab, 1) @@ -213,7 +216,7 @@ static int nbd_send_negotiate(int csock, off_t size, uint32_t flags) /* Negotiate [ 0 .. 7] passwd ("NBDMAGIC") - [ 8 .. 15] magic (0x00420281861253) + [ 8 .. 15] magic (NBD_CLIENT_MAGIC) [16 .. 23] size [24 .. 27] flags [28 .. 151] reserved (0) @@ -224,7 +227,7 @@ static int nbd_send_negotiate(int csock, off_t size, uint32_t flags) TRACE("Beginning negotiation."); memcpy(buf, "NBDMAGIC", 8); - cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL); + cpu_to_be64w((uint64_t*)(buf + 8), NBD_CLIENT_MAGIC); cpu_to_be64w((uint64_t*)(buf + 16), size); cpu_to_be32w((uint32_t*)(buf + 24), flags | NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM | @@ -295,7 +298,7 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, uint32_t namesize; TRACE("Checking magic (opts_magic)"); - if (magic != 0x49484156454F5054LL) { + if (magic != NBD_OPTS_MAGIC) { LOG("Bad magic received"); goto fail; } @@ -334,7 +337,7 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, } else { TRACE("Checking magic (cli_magic)"); - if (magic != 0x00420281861253LL) { + if (magic != NBD_CLIENT_MAGIC) { LOG("Bad magic received"); goto fail; } @@ -477,7 +480,7 @@ int nbd_client(int fd) ssize_t nbd_send_request(int csock, struct nbd_request *request) { - uint8_t buf[4 + 4 + 8 + 8 + 4]; + uint8_t buf[NBD_REQUEST_SIZE]; ssize_t ret; cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC); @@ -504,7 +507,7 @@ ssize_t nbd_send_request(int csock, struct nbd_request *request) static ssize_t nbd_receive_request(int csock, struct nbd_request *request) { - uint8_t buf[4 + 4 + 8 + 8 + 4]; + uint8_t buf[NBD_REQUEST_SIZE]; uint32_t magic; ssize_t ret; @@ -582,7 +585,7 @@ ssize_t nbd_receive_reply(int csock, struct nbd_reply *reply) static ssize_t nbd_send_reply(int csock, struct nbd_reply *reply) { - uint8_t buf[4 + 4 + 8]; + uint8_t buf[NBD_REPLY_SIZE]; ssize_t ret; /* Reply From 9a304d29a79a3daeeaf15c68d7439713037405b1 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 22 Aug 2012 15:30:31 +0200 Subject: [PATCH 0411/2270] nbd: pass NBDClient to nbd_send_negotiate We will need the NBDClient in nbd_send_negotiate to store the export requested by the client. Signed-off-by: Paolo Bonzini --- nbd.c | 78 +++++++++++++++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/nbd.c b/nbd.c index 8201b7a392..5a3088d232 100644 --- a/nbd.c +++ b/nbd.c @@ -78,6 +78,39 @@ #define NBD_OPT_EXPORT_NAME (1 << 0) +/* Definitions for opaque data types */ + +typedef struct NBDRequest NBDRequest; + +struct NBDRequest { + QSIMPLEQ_ENTRY(NBDRequest) entry; + NBDClient *client; + uint8_t *data; +}; + +struct NBDExport { + BlockDriverState *bs; + off_t dev_offset; + off_t size; + uint32_t nbdflags; + QSIMPLEQ_HEAD(, NBDRequest) requests; +}; + +struct NBDClient { + int refcount; + void (*close)(NBDClient *client); + + NBDExport *exp; + int sock; + + Coroutine *recv_coroutine; + + CoMutex send_lock; + Coroutine *send_coroutine; + + int nb_requests; +}; + /* That's all folks */ ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read) @@ -209,8 +242,9 @@ int unix_socket_outgoing(const char *path) Request (type == 2) */ -static int nbd_send_negotiate(int csock, off_t size, uint32_t flags) +static int nbd_send_negotiate(NBDClient *client) { + int csock = client->sock; char buf[8 + 8 + 8 + 128]; int rc; @@ -228,9 +262,9 @@ static int nbd_send_negotiate(int csock, off_t size, uint32_t flags) TRACE("Beginning negotiation."); memcpy(buf, "NBDMAGIC", 8); cpu_to_be64w((uint64_t*)(buf + 8), NBD_CLIENT_MAGIC); - cpu_to_be64w((uint64_t*)(buf + 16), size); + cpu_to_be64w((uint64_t*)(buf + 16), client->exp->size); cpu_to_be32w((uint32_t*)(buf + 24), - flags | NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM | + client->exp->nbdflags | NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM | NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA); memset(buf + 28, 0, 124); @@ -613,37 +647,6 @@ static ssize_t nbd_send_reply(int csock, struct nbd_reply *reply) #define MAX_NBD_REQUESTS 16 -typedef struct NBDRequest NBDRequest; - -struct NBDRequest { - QSIMPLEQ_ENTRY(NBDRequest) entry; - NBDClient *client; - uint8_t *data; -}; - -struct NBDExport { - BlockDriverState *bs; - off_t dev_offset; - off_t size; - uint32_t nbdflags; - QSIMPLEQ_HEAD(, NBDRequest) requests; -}; - -struct NBDClient { - int refcount; - void (*close)(NBDClient *client); - - NBDExport *exp; - int sock; - - Coroutine *recv_coroutine; - - CoMutex send_lock; - Coroutine *send_coroutine; - - int nb_requests; -}; - static void nbd_client_get(NBDClient *client) { client->refcount++; @@ -977,13 +980,14 @@ NBDClient *nbd_client_new(NBDExport *exp, int csock, void (*close)(NBDClient *)) { NBDClient *client; - if (nbd_send_negotiate(csock, exp->size, exp->nbdflags) < 0) { - return NULL; - } client = g_malloc0(sizeof(NBDClient)); client->refcount = 1; client->exp = exp; client->sock = csock; + if (nbd_send_negotiate(client) < 0) { + g_free(client); + return NULL; + } client->close = close; qemu_co_mutex_init(&client->send_lock); qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, NULL, client); From a4aab7b4cb2d994e17c987d7d3fb2b6645ea92a2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 22 Aug 2012 18:50:30 +0200 Subject: [PATCH 0412/2270] nbd: do not close BlockDriverState in nbd_export_close This is not desirable when embedding the NBD server inside QEMU. Move the bdrv_close to qemu-nbd. Signed-off-by: Paolo Bonzini --- nbd.c | 1 - qemu-nbd.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/nbd.c b/nbd.c index 5a3088d232..83200bdccd 100644 --- a/nbd.c +++ b/nbd.c @@ -721,7 +721,6 @@ void nbd_export_close(NBDExport *exp) g_free(first); } - bdrv_close(exp->bs); g_free(exp); } diff --git a/qemu-nbd.c b/qemu-nbd.c index 1c1cf6a463..23392e0d3c 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -586,6 +586,7 @@ int main(int argc, char **argv) } while (!sigterm_reported && (persistent || !nbd_started || nb_fds > 0)); nbd_export_close(exp); + bdrv_close(bs); if (sockpath) { unlink(sockpath); } From ce33967af74523685c7f911f6576c689728fcc81 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 18 Sep 2012 13:17:52 +0200 Subject: [PATCH 0413/2270] nbd: make refcount interface public After the next patch, the close callback will have to release its reference. Signed-off-by: Paolo Bonzini --- nbd.c | 4 ++-- nbd.h | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/nbd.c b/nbd.c index 83200bdccd..4aeb80ae18 100644 --- a/nbd.c +++ b/nbd.c @@ -647,12 +647,12 @@ static ssize_t nbd_send_reply(int csock, struct nbd_reply *reply) #define MAX_NBD_REQUESTS 16 -static void nbd_client_get(NBDClient *client) +void nbd_client_get(NBDClient *client) { client->refcount++; } -static void nbd_client_put(NBDClient *client) +void nbd_client_put(NBDClient *client) { if (--client->refcount == 0) { g_free(client); diff --git a/nbd.h b/nbd.h index 40d58d359f..a9038dc196 100644 --- a/nbd.h +++ b/nbd.h @@ -81,7 +81,10 @@ typedef struct NBDClient NBDClient; NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size, uint32_t nbdflags); void nbd_export_close(NBDExport *exp); + NBDClient *nbd_client_new(NBDExport *exp, int csock, void (*close)(NBDClient *)); +void nbd_client_get(NBDClient *client); +void nbd_client_put(NBDClient *client); #endif From ff2b68aa70d10b7eae813b04e9a23723dbd89ebd Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 22 Aug 2012 18:45:12 +0200 Subject: [PATCH 0414/2270] nbd: do not leak nbd_trip coroutines when a connection is torn down Because nbd_client_close removes the I/O handlers for the client socket, there is no way that any suspended coroutines are restarted. This will be a problem with the QEMU embedded NBD server, because we will have a QMP command to forcibly close all connections with the clients. Instead, we can exploit the reference counting of NBDClients; shutdown the client socket, which will make it readable and writeable. Also call the close callback, which will release the user's reference. The coroutines then will fail and exit cleanly, and release all remaining references, until the last refcount finally triggers the closure of the client. Signed-off-by: Paolo Bonzini --- nbd.c | 33 +++++++++++++++++++++++++++------ nbd.h | 1 + 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/nbd.c b/nbd.c index 4aeb80ae18..eb72f4a6e5 100644 --- a/nbd.c +++ b/nbd.c @@ -109,6 +109,7 @@ struct NBDClient { Coroutine *send_coroutine; int nb_requests; + bool closing; }; /* That's all folks */ @@ -655,19 +656,35 @@ void nbd_client_get(NBDClient *client) void nbd_client_put(NBDClient *client) { if (--client->refcount == 0) { + /* The last reference should be dropped by client->close, + * which is called by nbd_client_close. + */ + assert(client->closing); + + qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL); + close(client->sock); + client->sock = -1; g_free(client); } } -static void nbd_client_close(NBDClient *client) +void nbd_client_close(NBDClient *client) { - qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL); - close(client->sock); - client->sock = -1; + if (client->closing) { + return; + } + + client->closing = true; + + /* Force requests to finish. They will drop their own references, + * then we'll close the socket and free the NBDClient. + */ + shutdown(client->sock, 2); + + /* Also tell the client, so that they release their reference. */ if (client->close) { client->close(client); } - nbd_client_put(client); } static NBDRequest *nbd_request_get(NBDClient *client) @@ -810,14 +827,18 @@ out: static void nbd_trip(void *opaque) { NBDClient *client = opaque; - NBDRequest *req = nbd_request_get(client); NBDExport *exp = client->exp; + NBDRequest *req; struct nbd_request request; struct nbd_reply reply; ssize_t ret; TRACE("Reading request."); + if (client->closing) { + return; + } + req = nbd_request_get(client); ret = nbd_co_receive_request(req, &request); if (ret == -EAGAIN) { goto done; diff --git a/nbd.h b/nbd.h index a9038dc196..8b84a50ed4 100644 --- a/nbd.h +++ b/nbd.h @@ -84,6 +84,7 @@ void nbd_export_close(NBDExport *exp); NBDClient *nbd_client_new(NBDExport *exp, int csock, void (*close)(NBDClient *)); +void nbd_client_close(NBDClient *client); void nbd_client_get(NBDClient *client); void nbd_client_put(NBDClient *client); From 2c8d9f065538a5a0ef2421e90b6076d05148accf Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 18 Sep 2012 13:26:25 +0200 Subject: [PATCH 0415/2270] nbd: add reference counting to NBDExport We will use a similar two-phase destruction for NBDExport, so we need each NBDClient to add a reference to NBDExport. Signed-off-by: Paolo Bonzini --- nbd.c | 37 +++++++++++++++++++++++++++++++------ nbd.h | 2 ++ qemu-nbd.c | 2 ++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/nbd.c b/nbd.c index eb72f4a6e5..4922d38ea3 100644 --- a/nbd.c +++ b/nbd.c @@ -89,6 +89,7 @@ struct NBDRequest { }; struct NBDExport { + int refcount; BlockDriverState *bs; off_t dev_offset; off_t size; @@ -664,6 +665,7 @@ void nbd_client_put(NBDClient *client) qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL); close(client->sock); client->sock = -1; + nbd_export_put(client->exp); g_free(client); } } @@ -722,6 +724,7 @@ NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, { NBDExport *exp = g_malloc0(sizeof(NBDExport)); QSIMPLEQ_INIT(&exp->requests); + exp->refcount = 1; exp->bs = bs; exp->dev_offset = dev_offset; exp->nbdflags = nbdflags; @@ -731,14 +734,34 @@ NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, void nbd_export_close(NBDExport *exp) { - while (!QSIMPLEQ_EMPTY(&exp->requests)) { - NBDRequest *first = QSIMPLEQ_FIRST(&exp->requests); - QSIMPLEQ_REMOVE_HEAD(&exp->requests, entry); - qemu_vfree(first->data); - g_free(first); + assert(exp->refcount == 1); + + /* stub */ +} + +void nbd_export_get(NBDExport *exp) +{ + assert(exp->refcount > 0); + exp->refcount++; +} + +void nbd_export_put(NBDExport *exp) +{ + assert(exp->refcount > 0); + if (exp->refcount == 1) { + nbd_export_close(exp); } - g_free(exp); + if (--exp->refcount == 0) { + while (!QSIMPLEQ_EMPTY(&exp->requests)) { + NBDRequest *first = QSIMPLEQ_FIRST(&exp->requests); + QSIMPLEQ_REMOVE_HEAD(&exp->requests, entry); + qemu_vfree(first->data); + g_free(first); + } + + g_free(exp); + } } static int nbd_can_read(void *opaque); @@ -1011,5 +1034,7 @@ NBDClient *nbd_client_new(NBDExport *exp, int csock, client->close = close; qemu_co_mutex_init(&client->send_lock); qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, NULL, client); + + nbd_export_get(exp); return client; } diff --git a/nbd.h b/nbd.h index 8b84a50ed4..86921cd048 100644 --- a/nbd.h +++ b/nbd.h @@ -81,6 +81,8 @@ typedef struct NBDClient NBDClient; NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size, uint32_t nbdflags); void nbd_export_close(NBDExport *exp); +void nbd_export_get(NBDExport *exp); +void nbd_export_put(NBDExport *exp); NBDClient *nbd_client_new(NBDExport *exp, int csock, void (*close)(NBDClient *)); diff --git a/qemu-nbd.c b/qemu-nbd.c index 23392e0d3c..2a2cba3f73 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -586,7 +586,9 @@ int main(int argc, char **argv) } while (!sigterm_reported && (persistent || !nbd_started || nb_fds > 0)); nbd_export_close(exp); + nbd_export_put(exp); bdrv_close(bs); + if (sockpath) { unlink(sockpath); } From 4b9441f6b3565ba6affa95141590cd2be4ae0cd9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 18 Sep 2012 13:58:25 +0200 Subject: [PATCH 0416/2270] nbd: track clients into NBDExport Track the NBDClients of each NBDExport, and use it to implement nbd_export_close. Signed-off-by: Paolo Bonzini --- nbd.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/nbd.c b/nbd.c index 4922d38ea3..c39692b61f 100644 --- a/nbd.c +++ b/nbd.c @@ -94,6 +94,7 @@ struct NBDExport { off_t dev_offset; off_t size; uint32_t nbdflags; + QTAILQ_HEAD(, NBDClient) clients; QSIMPLEQ_HEAD(, NBDRequest) requests; }; @@ -109,6 +110,7 @@ struct NBDClient { CoMutex send_lock; Coroutine *send_coroutine; + QTAILQ_ENTRY(NBDClient) next; int nb_requests; bool closing; }; @@ -665,6 +667,7 @@ void nbd_client_put(NBDClient *client) qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL); close(client->sock); client->sock = -1; + QTAILQ_REMOVE(&client->exp->clients, client, next); nbd_export_put(client->exp); g_free(client); } @@ -725,6 +728,7 @@ NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, NBDExport *exp = g_malloc0(sizeof(NBDExport)); QSIMPLEQ_INIT(&exp->requests); exp->refcount = 1; + QTAILQ_INIT(&exp->clients); exp->bs = bs; exp->dev_offset = dev_offset; exp->nbdflags = nbdflags; @@ -734,9 +738,13 @@ NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, void nbd_export_close(NBDExport *exp) { - assert(exp->refcount == 1); + NBDClient *client, *next; - /* stub */ + nbd_export_get(exp); + QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) { + nbd_client_close(client); + } + nbd_export_put(exp); } void nbd_export_get(NBDExport *exp) @@ -1035,6 +1043,7 @@ NBDClient *nbd_client_new(NBDExport *exp, int csock, qemu_co_mutex_init(&client->send_lock); qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, NULL, client); + QTAILQ_INSERT_TAIL(&exp->clients, client, next); nbd_export_get(exp); return client; } From 0ddf08db22a9ef6b122d8c4cfe5b25d2c2c51962 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 18 Sep 2012 13:59:03 +0200 Subject: [PATCH 0417/2270] nbd: add notification for closing an NBDExport In order to exit cleanly from qemu-nbd, add a callback that triggers when an NBDExport is closed. In the case of qemu-nbd it will exit the main loop. Signed-off-by: Paolo Bonzini --- nbd.c | 10 +++++++++- nbd.h | 3 ++- qemu-nbd.c | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/nbd.c b/nbd.c index c39692b61f..2e9de70288 100644 --- a/nbd.c +++ b/nbd.c @@ -90,6 +90,8 @@ struct NBDRequest { struct NBDExport { int refcount; + void (*close)(NBDExport *exp); + BlockDriverState *bs; off_t dev_offset; off_t size; @@ -723,7 +725,8 @@ static void nbd_request_put(NBDRequest *req) } NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, - off_t size, uint32_t nbdflags) + off_t size, uint32_t nbdflags, + void (*close)(NBDExport *)) { NBDExport *exp = g_malloc0(sizeof(NBDExport)); QSIMPLEQ_INIT(&exp->requests); @@ -733,6 +736,7 @@ NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, exp->dev_offset = dev_offset; exp->nbdflags = nbdflags; exp->size = size == -1 ? bdrv_getlength(bs) : size; + exp->close = close; return exp; } @@ -761,6 +765,10 @@ void nbd_export_put(NBDExport *exp) } if (--exp->refcount == 0) { + if (exp->close) { + exp->close(exp); + } + while (!QSIMPLEQ_EMPTY(&exp->requests)) { NBDRequest *first = QSIMPLEQ_FIRST(&exp->requests); QSIMPLEQ_REMOVE_HEAD(&exp->requests, entry); diff --git a/nbd.h b/nbd.h index 86921cd048..895820b450 100644 --- a/nbd.h +++ b/nbd.h @@ -79,7 +79,8 @@ typedef struct NBDExport NBDExport; typedef struct NBDClient NBDClient; NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, - off_t size, uint32_t nbdflags); + off_t size, uint32_t nbdflags, + void (*close)(NBDExport *)); void nbd_export_close(NBDExport *exp); void nbd_export_get(NBDExport *exp); void nbd_export_put(NBDExport *exp); diff --git a/qemu-nbd.c b/qemu-nbd.c index 2a2cba3f73..8b87dea5f6 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -546,7 +546,7 @@ int main(int argc, char **argv) } } - exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags); + exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags, NULL); if (sockpath) { fd = unix_socket_incoming(sockpath); From 7860a380ac2a9fd09a6e8f31fd9db5318fc91285 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 18 Sep 2012 13:31:56 +0200 Subject: [PATCH 0418/2270] qemu-nbd: rewrite termination conditions to use a state machine Use a simple state machine with the following states: - RUNNING => accepting connections - TERMINATE => main loop must call nbd_export_close/put, and not accept connections anymore - TERMINATING => waiting for pending requests to finish - TERMINATED => the NBDExport has been closed Signed-off-by: Paolo Bonzini --- qemu-nbd.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/qemu-nbd.c b/qemu-nbd.c index 8b87dea5f6..15bcd08123 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -41,8 +41,8 @@ static NBDExport *exp; static int verbose; static char *srcpath; static char *sockpath; -static bool sigterm_reported; -static bool nbd_started; +static int persistent = 0; +static enum { RUNNING, TERMINATE, TERMINATING, TERMINATED } state; static int shared = 1; static int nb_fds; @@ -186,7 +186,7 @@ static int find_partition(BlockDriverState *bs, int partition, static void termsig_handler(int signum) { - sigterm_reported = true; + state = TERMINATE; qemu_notify_event(); } @@ -269,10 +269,20 @@ static int nbd_can_accept(void *opaque) return nb_fds < shared; } +static void nbd_export_closed(NBDExport *exp) +{ + assert(state == TERMINATING); + state = TERMINATED; +} + static void nbd_client_closed(NBDClient *client) { nb_fds--; + if (nb_fds == 0 && !persistent && state == RUNNING) { + state = TERMINATE; + } qemu_notify_event(); + nbd_client_put(client); } static void nbd_accept(void *opaque) @@ -282,7 +292,11 @@ static void nbd_accept(void *opaque) socklen_t addr_len = sizeof(addr); int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len); - nbd_started = true; + if (state >= TERMINATE) { + close(fd); + return; + } + if (fd >= 0 && nbd_client_new(exp, fd, nbd_client_closed)) { nb_fds++; } @@ -329,7 +343,6 @@ int main(int argc, char **argv) int partition = -1; int ret; int fd; - int persistent = 0; bool seen_cache = false; #ifdef CONFIG_LINUX_AIO bool seen_aio = false; @@ -546,7 +559,7 @@ int main(int argc, char **argv) } } - exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags, NULL); + exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags, nbd_export_closed); if (sockpath) { fd = unix_socket_incoming(sockpath); @@ -581,14 +594,18 @@ int main(int argc, char **argv) err(EXIT_FAILURE, "Could not chdir to root directory"); } + state = RUNNING; do { main_loop_wait(false); - } while (!sigterm_reported && (persistent || !nbd_started || nb_fds > 0)); + if (state == TERMINATE) { + state = TERMINATING; + nbd_export_close(exp); + nbd_export_put(exp); + exp = NULL; + } + } while (state != TERMINATED); - nbd_export_close(exp); - nbd_export_put(exp); bdrv_close(bs); - if (sockpath) { unlink(sockpath); } From ee0a19ec2a98989ff634857fb203bc2879d96bff Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 22 Aug 2012 15:59:23 +0200 Subject: [PATCH 0419/2270] nbd: register named exports Add an API to register and find named exports. Signed-off-by: Paolo Bonzini --- nbd.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ nbd.h | 4 ++++ 2 files changed, 53 insertions(+) diff --git a/nbd.c b/nbd.c index 2e9de70288..2d2221c7fc 100644 --- a/nbd.c +++ b/nbd.c @@ -93,13 +93,17 @@ struct NBDExport { void (*close)(NBDExport *exp); BlockDriverState *bs; + char *name; off_t dev_offset; off_t size; uint32_t nbdflags; QTAILQ_HEAD(, NBDClient) clients; QSIMPLEQ_HEAD(, NBDRequest) requests; + QTAILQ_ENTRY(NBDExport) next; }; +static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports); + struct NBDClient { int refcount; void (*close)(NBDClient *client); @@ -740,6 +744,39 @@ NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, return exp; } +NBDExport *nbd_export_find(const char *name) +{ + NBDExport *exp; + QTAILQ_FOREACH(exp, &exports, next) { + if (strcmp(name, exp->name) == 0) { + return exp; + } + } + + return NULL; +} + +void nbd_export_set_name(NBDExport *exp, const char *name) +{ + if (exp->name == name) { + return; + } + + nbd_export_get(exp); + if (exp->name != NULL) { + g_free(exp->name); + exp->name = NULL; + QTAILQ_REMOVE(&exports, exp, next); + nbd_export_put(exp); + } + if (name != NULL) { + nbd_export_get(exp); + exp->name = g_strdup(name); + QTAILQ_INSERT_TAIL(&exports, exp, next); + } + nbd_export_put(exp); +} + void nbd_export_close(NBDExport *exp) { NBDClient *client, *next; @@ -765,6 +802,8 @@ void nbd_export_put(NBDExport *exp) } if (--exp->refcount == 0) { + assert(exp->name == NULL); + if (exp->close) { exp->close(exp); } @@ -780,6 +819,16 @@ void nbd_export_put(NBDExport *exp) } } +void nbd_export_close_all(void) +{ + NBDExport *exp, *next; + + QTAILQ_FOREACH_SAFE(exp, &exports, next, next) { + nbd_export_close(exp); + nbd_export_set_name(exp, NULL); + } +} + static int nbd_can_read(void *opaque); static void nbd_read(void *opaque); static void nbd_restart_write(void *opaque); diff --git a/nbd.h b/nbd.h index 895820b450..f0edb9cdf1 100644 --- a/nbd.h +++ b/nbd.h @@ -85,6 +85,10 @@ void nbd_export_close(NBDExport *exp); void nbd_export_get(NBDExport *exp); void nbd_export_put(NBDExport *exp); +NBDExport *nbd_export_find(const char *name); +void nbd_export_set_name(NBDExport *exp, const char *name); +void nbd_export_close_all(void); + NBDClient *nbd_client_new(NBDExport *exp, int csock, void (*close)(NBDClient *)); void nbd_client_close(NBDClient *client); From 6b8c01e781524ab713faa31a4fb5b20a745f638a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 23 Aug 2012 14:57:11 +0200 Subject: [PATCH 0420/2270] nbd: negotiate with named exports Allow negotiation to receive the name of the requested export from the client. Passing a NULL export to nbd_client_new will cause the server to send the extended negotiation header. The exp field is then filled during negotiation. Signed-off-by: Paolo Bonzini --- nbd.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 150 insertions(+), 19 deletions(-) diff --git a/nbd.c b/nbd.c index 2d2221c7fc..6f60dcfce5 100644 --- a/nbd.c +++ b/nbd.c @@ -238,11 +238,23 @@ int unix_socket_outgoing(const char *path) return unix_connect(path); } -/* Basic flow +/* Basic flow for negotiation Server Client - Negotiate + + or + + Server Client + Negotiate #1 + Option + Negotiate #2 + + ---- + + followed by + + Server Client Request Response Request @@ -250,20 +262,112 @@ int unix_socket_outgoing(const char *path) ... ... Request (type == 2) + */ +static int nbd_receive_options(NBDClient *client) +{ + int csock = client->sock; + char name[256]; + uint32_t tmp, length; + uint64_t magic; + int rc; + + /* Client sends: + [ 0 .. 3] reserved (0) + [ 4 .. 11] NBD_OPTS_MAGIC + [12 .. 15] NBD_OPT_EXPORT_NAME + [16 .. 19] length + [20 .. xx] export name (length bytes) + */ + + rc = -EINVAL; + if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { + LOG("read failed"); + goto fail; + } + TRACE("Checking reserved"); + if (tmp != 0) { + LOG("Bad reserved received"); + goto fail; + } + + if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { + LOG("read failed"); + goto fail; + } + TRACE("Checking reserved"); + if (magic != be64_to_cpu(NBD_OPTS_MAGIC)) { + LOG("Bad magic received"); + goto fail; + } + + if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { + LOG("read failed"); + goto fail; + } + TRACE("Checking option"); + if (tmp != be32_to_cpu(NBD_OPT_EXPORT_NAME)) { + LOG("Bad option received"); + goto fail; + } + + if (read_sync(csock, &length, sizeof(length)) != sizeof(length)) { + LOG("read failed"); + goto fail; + } + TRACE("Checking length"); + length = be32_to_cpu(length); + if (length > 255) { + LOG("Bad length received"); + goto fail; + } + if (read_sync(csock, name, length) != length) { + LOG("read failed"); + goto fail; + } + name[length] = '\0'; + + client->exp = nbd_export_find(name); + if (!client->exp) { + LOG("export not found"); + goto fail; + } + + QTAILQ_INSERT_TAIL(&client->exp->clients, client, next); + nbd_export_get(client->exp); + + TRACE("Option negotiation succeeded."); + rc = 0; +fail: + return rc; +} + static int nbd_send_negotiate(NBDClient *client) { int csock = client->sock; char buf[8 + 8 + 8 + 128]; int rc; + const int myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM | + NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA); - /* Negotiate - [ 0 .. 7] passwd ("NBDMAGIC") - [ 8 .. 15] magic (NBD_CLIENT_MAGIC) + /* Negotiation header without options: + [ 0 .. 7] passwd ("NBDMAGIC") + [ 8 .. 15] magic (NBD_CLIENT_MAGIC) [16 .. 23] size - [24 .. 27] flags - [28 .. 151] reserved (0) + [24 .. 25] server flags (0) + [24 .. 27] export flags + [28 .. 151] reserved (0) + + Negotiation header with options, part 1: + [ 0 .. 7] passwd ("NBDMAGIC") + [ 8 .. 15] magic (NBD_OPTS_MAGIC) + [16 .. 17] server flags (0) + + part 2 (after options are sent): + [18 .. 25] size + [26 .. 27] export flags + [28 .. 151] reserved (0) */ socket_set_block(csock); @@ -271,16 +375,39 @@ static int nbd_send_negotiate(NBDClient *client) TRACE("Beginning negotiation."); memcpy(buf, "NBDMAGIC", 8); - cpu_to_be64w((uint64_t*)(buf + 8), NBD_CLIENT_MAGIC); - cpu_to_be64w((uint64_t*)(buf + 16), client->exp->size); - cpu_to_be32w((uint32_t*)(buf + 24), - client->exp->nbdflags | NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM | - NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA); + if (client->exp) { + assert ((client->exp->nbdflags & ~65535) == 0); + cpu_to_be64w((uint64_t*)(buf + 8), NBD_CLIENT_MAGIC); + cpu_to_be64w((uint64_t*)(buf + 16), client->exp->size); + cpu_to_be16w((uint16_t*)(buf + 26), client->exp->nbdflags | myflags); + } else { + cpu_to_be64w((uint64_t*)(buf + 8), NBD_OPTS_MAGIC); + } memset(buf + 28, 0, 124); - if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { - LOG("write failed"); - goto fail; + if (client->exp) { + if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { + LOG("write failed"); + goto fail; + } + } else { + if (write_sync(csock, buf, 18) != 18) { + LOG("write failed"); + goto fail; + } + rc = nbd_receive_options(client); + if (rc < 0) { + LOG("option negotiation failed"); + goto fail; + } + + assert ((client->exp->nbdflags & ~65535) == 0); + cpu_to_be64w((uint64_t*)(buf + 18), client->exp->size); + cpu_to_be16w((uint16_t*)(buf + 26), client->exp->nbdflags | myflags); + if (write_sync(csock, buf + 18, sizeof(buf) - 18) != sizeof(buf) - 18) { + LOG("write failed"); + goto fail; + } } TRACE("Negotiation succeeded."); @@ -673,8 +800,10 @@ void nbd_client_put(NBDClient *client) qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL); close(client->sock); client->sock = -1; - QTAILQ_REMOVE(&client->exp->clients, client, next); - nbd_export_put(client->exp); + if (client->exp) { + QTAILQ_REMOVE(&client->exp->clients, client, next); + nbd_export_put(client->exp); + } g_free(client); } } @@ -1100,7 +1229,9 @@ NBDClient *nbd_client_new(NBDExport *exp, int csock, qemu_co_mutex_init(&client->send_lock); qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, NULL, client); - QTAILQ_INSERT_TAIL(&exp->clients, client, next); - nbd_export_get(exp); + if (exp) { + QTAILQ_INSERT_TAIL(&exp->clients, client, next); + nbd_export_get(exp); + } return client; } From 125afda8cbd228583c1e7c32c0f86eeb8de39c73 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 18 Sep 2012 14:31:44 +0200 Subject: [PATCH 0421/2270] nbd: add nbd_export_get_blockdev Signed-off-by: Paolo Bonzini --- nbd.c | 7 ++++++- nbd.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/nbd.c b/nbd.c index 6f60dcfce5..57edfde0c9 100644 --- a/nbd.c +++ b/nbd.c @@ -914,6 +914,7 @@ void nbd_export_close(NBDExport *exp) QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) { nbd_client_close(client); } + nbd_export_set_name(exp, NULL); nbd_export_put(exp); } @@ -948,13 +949,17 @@ void nbd_export_put(NBDExport *exp) } } +BlockDriverState *nbd_export_get_blockdev(NBDExport *exp) +{ + return exp->bs; +} + void nbd_export_close_all(void) { NBDExport *exp, *next; QTAILQ_FOREACH_SAFE(exp, &exports, next, next) { nbd_export_close(exp); - nbd_export_set_name(exp, NULL); } } diff --git a/nbd.h b/nbd.h index f0edb9cdf1..344f05b794 100644 --- a/nbd.h +++ b/nbd.h @@ -85,6 +85,8 @@ void nbd_export_close(NBDExport *exp); void nbd_export_get(NBDExport *exp); void nbd_export_put(NBDExport *exp); +BlockDriverState *nbd_export_get_blockdev(NBDExport *exp); + NBDExport *nbd_export_find(const char *name); void nbd_export_set_name(NBDExport *exp, const char *name); void nbd_export_close_all(void); From 55d4fd3c24bd253bd96270c7fdf1bb862f3a3400 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 19 Sep 2012 14:51:38 +0100 Subject: [PATCH 0422/2270] arch_init.c: Improve '-soundhw help' for non-HAS_AUDIO_CHOICE archs For architectures which don't set HAS_AUDIO_CHOICE, improve the '-soundhw help' message so that it doesn't simply print an empty list, implying no sound support at all. Signed-off-by: Peter Maydell Signed-off-by: malc --- arch_init.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch_init.c b/arch_init.c index 47977de7c6..f849f9b872 100644 --- a/arch_init.c +++ b/arch_init.c @@ -922,11 +922,16 @@ void select_soundhw(const char *optarg) if (is_help_option(optarg)) { show_valid_cards: +#ifdef HAS_AUDIO_CHOICE printf("Valid sound card names (comma separated):\n"); for (c = soundhw; c->name; ++c) { printf ("%-11s %s\n", c->name, c->descr); } printf("\n-soundhw all will enable all of the above\n"); +#else + printf("Machine has no user-selectable audio hardware " + "(it may or may not have always-present audio hardware).\n"); +#endif exit(!is_help_option(optarg)); } else { From c0a1dcb9f0baf9269f8baeb02cbcca8dad75454c Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Thu, 28 Jun 2012 12:52:23 +1000 Subject: [PATCH 0423/2270] xilinx_timer: Removed comma in device name Fixes an error in a61e4b07a30c062260d2d01771773f14820d1eb7 Signed-off-by: Peter A. G. Crosthwaite --- hw/xilinx.h | 2 +- hw/xilinx_timer.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/xilinx.h b/hw/xilinx.h index 556c5aa9f1..df06a001d3 100644 --- a/hw/xilinx.h +++ b/hw/xilinx.h @@ -21,7 +21,7 @@ xilinx_timer_create(target_phys_addr_t base, qemu_irq irq, int oto, int freq) { DeviceState *dev; - dev = qdev_create(NULL, "xlnx,xps-timer"); + dev = qdev_create(NULL, "xlnx.xps-timer"); qdev_prop_set_uint32(dev, "one-timer-only", oto); qdev_prop_set_uint32(dev, "frequency", freq); qdev_init_nofail(dev); diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c index b562bd065e..053ba02b50 100644 --- a/hw/xilinx_timer.c +++ b/hw/xilinx_timer.c @@ -217,7 +217,7 @@ static int xilinx_timer_init(SysBusDevice *dev) ptimer_set_freq(xt->ptimer, t->freq_hz); } - memory_region_init_io(&t->mmio, &timer_ops, t, "xlnx,xps-timer", + memory_region_init_io(&t->mmio, &timer_ops, t, "xlnx.xps-timer", R_MAX * 4 * num_timers(t)); sysbus_init_mmio(dev, &t->mmio); return 0; @@ -239,7 +239,7 @@ static void xilinx_timer_class_init(ObjectClass *klass, void *data) } static TypeInfo xilinx_timer_info = { - .name = "xlnx,xps-timer", + .name = "xlnx.xps-timer", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(struct timerblock), .class_init = xilinx_timer_class_init, From e03377ae75808d33d0a7afc803b37bcda9f796b3 Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Thu, 28 Jun 2012 16:28:03 +1000 Subject: [PATCH 0424/2270] xilinx_timer: Send dbg msgs to stderr not stdout Signed-off-by: Peter A. G. Crosthwaite --- hw/xilinx_timer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c index 053ba02b50..c02e6caf3e 100644 --- a/hw/xilinx_timer.c +++ b/hw/xilinx_timer.c @@ -119,7 +119,7 @@ timer_read(void *opaque, target_phys_addr_t addr, unsigned int size) break; } - D(printf("%s timer=%d %x=%x\n", __func__, timer, addr * 4, r)); + D(fprintf(stderr, "%s timer=%d %x=%x\n", __func__, timer, addr * 4, r)); return r; } @@ -127,7 +127,7 @@ static void timer_enable(struct xlx_timer *xt) { uint64_t count; - D(printf("%s timer=%d down=%d\n", __func__, + D(fprintf(stderr, "%s timer=%d down=%d\n", __func__, xt->nr, xt->regs[R_TCSR] & TCSR_UDT)); ptimer_stop(xt->ptimer); @@ -152,7 +152,7 @@ timer_write(void *opaque, target_phys_addr_t addr, addr >>= 2; timer = timer_from_addr(addr); xt = &t->timers[timer]; - D(printf("%s addr=%x val=%x (timer=%d off=%d)\n", + D(fprintf(stderr, "%s addr=%x val=%x (timer=%d off=%d)\n", __func__, addr * 4, value, timer, addr & 3)); /* Further decoding to address a specific timers reg. */ addr &= 3; @@ -189,7 +189,7 @@ static void timer_hit(void *opaque) { struct xlx_timer *xt = opaque; struct timerblock *t = xt->parent; - D(printf("%s %d\n", __func__, timer)); + D(fprintf(stderr, "%s %d\n", __func__, timer)); xt->regs[R_TCSR] |= TCSR_TINT; if (xt->regs[R_TCSR] & TCSR_ARHT) From 919f89f44c7e3a8dee6a0f0eebd0cc81766da612 Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Fri, 29 Jun 2012 13:20:46 +1000 Subject: [PATCH 0425/2270] xilinx_timer: Fixed "frequency" prop name The "frequency" qdev prop matches the "clock-frequency" property in Xilinx EDK. Renamed "frequency" -> "clock-frequency" accordingly. Signed-off-by: Peter A. G. Crosthwaite --- hw/xilinx.h | 2 +- hw/xilinx_timer.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/xilinx.h b/hw/xilinx.h index df06a001d3..45a6bdc190 100644 --- a/hw/xilinx.h +++ b/hw/xilinx.h @@ -23,7 +23,7 @@ xilinx_timer_create(target_phys_addr_t base, qemu_irq irq, int oto, int freq) dev = qdev_create(NULL, "xlnx.xps-timer"); qdev_prop_set_uint32(dev, "one-timer-only", oto); - qdev_prop_set_uint32(dev, "frequency", freq); + qdev_prop_set_uint32(dev, "clock-frequency", freq); qdev_init_nofail(dev); sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq); diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c index c02e6caf3e..9eb5ef7114 100644 --- a/hw/xilinx_timer.c +++ b/hw/xilinx_timer.c @@ -224,7 +224,8 @@ static int xilinx_timer_init(SysBusDevice *dev) } static Property xilinx_timer_properties[] = { - DEFINE_PROP_UINT32("frequency", struct timerblock, freq_hz, 62 * 1000000), + DEFINE_PROP_UINT32("clock-frequency", struct timerblock, freq_hz, + 62 * 1000000), DEFINE_PROP_UINT8("one-timer-only", struct timerblock, one_timer_only, 0), DEFINE_PROP_END_OF_LIST(), }; From 4b5e52101f9ad077d1c016f2b7130e2fdae6d2da Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Mon, 17 Sep 2012 13:41:39 +1000 Subject: [PATCH 0426/2270] xilinx.h: Error check when setting links Assert that the ethernet and dma controller are sucessfully linked to their peers. Signed-off-by: Peter A. G. Crosthwaite --- hw/xilinx.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hw/xilinx.h b/hw/xilinx.h index 45a6bdc190..4d29265b9a 100644 --- a/hw/xilinx.h +++ b/hw/xilinx.h @@ -55,13 +55,16 @@ xilinx_axiethernet_create(NICInfo *nd, StreamSlave *peer, int txmem, int rxmem) { DeviceState *dev; + Error *errp = NULL; + qemu_check_nic_model(nd, "xlnx.axi-ethernet"); dev = qdev_create(NULL, "xlnx.axi-ethernet"); qdev_set_nic_properties(dev, nd); qdev_prop_set_uint32(dev, "rxmem", rxmem); qdev_prop_set_uint32(dev, "txmem", txmem); - object_property_set_link(OBJECT(dev), OBJECT(peer), "tx_dev", NULL); + object_property_set_link(OBJECT(dev), OBJECT(peer), "tx_dev", &errp); + assert_no_error(errp); qdev_init_nofail(dev); sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq); @@ -74,8 +77,11 @@ xilinx_axiethernetdma_init(DeviceState *dev, StreamSlave *peer, target_phys_addr_t base, qemu_irq irq, qemu_irq irq2, int freqhz) { + Error *errp = NULL; + qdev_prop_set_uint32(dev, "freqhz", freqhz); - object_property_set_link(OBJECT(dev), OBJECT(peer), "tx_dev", NULL); + object_property_set_link(OBJECT(dev), OBJECT(peer), "tx_dev", &errp); + assert_no_error(errp); qdev_init_nofail(dev); sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); From c9b6e1f6bbc93cd1a43dbde625077dde5806c7d7 Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Mon, 17 Sep 2012 14:06:32 +1000 Subject: [PATCH 0427/2270] xilinx: fix names of ethernet and dma links. These names were incorrect. Fixed to match to actual link names Signed-off-by: Peter A. G. Crosthwaite --- hw/xilinx.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/xilinx.h b/hw/xilinx.h index 4d29265b9a..98300477ab 100644 --- a/hw/xilinx.h +++ b/hw/xilinx.h @@ -63,7 +63,8 @@ xilinx_axiethernet_create(NICInfo *nd, StreamSlave *peer, qdev_set_nic_properties(dev, nd); qdev_prop_set_uint32(dev, "rxmem", rxmem); qdev_prop_set_uint32(dev, "txmem", txmem); - object_property_set_link(OBJECT(dev), OBJECT(peer), "tx_dev", &errp); + object_property_set_link(OBJECT(dev), OBJECT(peer), "axistream-connected", + &errp); assert_no_error(errp); qdev_init_nofail(dev); sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); @@ -80,7 +81,8 @@ xilinx_axiethernetdma_init(DeviceState *dev, StreamSlave *peer, Error *errp = NULL; qdev_prop_set_uint32(dev, "freqhz", freqhz); - object_property_set_link(OBJECT(dev), OBJECT(peer), "tx_dev", &errp); + object_property_set_link(OBJECT(dev), OBJECT(peer), "axistream-connected", + &errp); assert_no_error(errp); qdev_init_nofail(dev); From 8354cd722e0afae63bee3e4cb21c8f0ddb6874c2 Mon Sep 17 00:00:00 2001 From: Chris Wulff Date: Sun, 9 Sep 2012 20:20:07 -0400 Subject: [PATCH 0428/2270] xilinx_timer: Fix a compile error if debug enabled There was a missing include of qemu-log and a variable name in a printf was out of date. Signed-off-by: Chris Wulff Signed-off-by: Peter A. G. Crosthwaite --- hw/xilinx_timer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c index 9eb5ef7114..2e48ca2bee 100644 --- a/hw/xilinx_timer.c +++ b/hw/xilinx_timer.c @@ -24,6 +24,7 @@ #include "sysbus.h" #include "ptimer.h" +#include "qemu-log.h" #define D(x) @@ -189,7 +190,7 @@ static void timer_hit(void *opaque) { struct xlx_timer *xt = opaque; struct timerblock *t = xt->parent; - D(fprintf(stderr, "%s %d\n", __func__, timer)); + D(fprintf(stderr, "%s %d\n", __func__, xt->nr)); xt->regs[R_TCSR] |= TCSR_TINT; if (xt->regs[R_TCSR] & TCSR_ARHT) From 5c2d2a9ee5f1978ae980598fba80151c761105a0 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Mon, 10 Sep 2012 13:56:24 +0200 Subject: [PATCH 0429/2270] tcg/i386: allow constants in load/store ops On x86, it is possible to move a constant value to memory. Add code to handle a constant argument to load/store ops. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/i386/tcg-target.c | 50 ++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 34c2df80a6..3017858751 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -263,6 +263,7 @@ static inline int tcg_target_const_match(tcg_target_long val, #define OPC_MOVB_EvGv (0x88) /* stores, more or less */ #define OPC_MOVL_EvGv (0x89) /* stores, more or less */ #define OPC_MOVL_GvEv (0x8b) /* loads, more or less */ +#define OPC_MOVB_EvIz (0xc6) #define OPC_MOVL_EvIz (0xc7) #define OPC_MOVL_Iv (0xb8) #define OPC_MOVSBL (0xbe | P_EXT) @@ -1543,18 +1544,35 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; OP_32_64(st8): - tcg_out_modrm_offset(s, OPC_MOVB_EvGv | P_REXB_R, - args[0], args[1], args[2]); + if (const_args[0]) { + tcg_out_modrm_offset(s, OPC_MOVB_EvIz, + 0, args[1], args[2]); + tcg_out8(s, args[0]); + } else { + tcg_out_modrm_offset(s, OPC_MOVB_EvGv | P_REXB_R, + args[0], args[1], args[2]); + } break; OP_32_64(st16): - tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16, - args[0], args[1], args[2]); + if (const_args[0]) { + tcg_out_modrm_offset(s, OPC_MOVL_EvIz | P_DATA16, + 0, args[1], args[2]); + tcg_out16(s, args[0]); + } else { + tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16, + args[0], args[1], args[2]); + } break; #if TCG_TARGET_REG_BITS == 64 case INDEX_op_st32_i64: #endif case INDEX_op_st_i32: - tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]); + if (const_args[0]) { + tcg_out_modrm_offset(s, OPC_MOVL_EvIz, 0, args[1], args[2]); + tcg_out32(s, args[0]); + } else { + tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]); + } break; OP_32_64(add): @@ -1758,7 +1776,13 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_ld(s, TCG_TYPE_I64, args[0], args[1], args[2]); break; case INDEX_op_st_i64: - tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]); + if (const_args[0]) { + tcg_out_modrm_offset(s, OPC_MOVL_EvIz | P_REXW, + 0, args[1], args[2]); + tcg_out32(s, args[0]); + } else { + tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]); + } break; case INDEX_op_qemu_ld32s: tcg_out_qemu_ld(s, args, 2 | 4); @@ -1820,9 +1844,9 @@ static const TCGTargetOpDef x86_op_defs[] = { { INDEX_op_ld16u_i32, { "r", "r" } }, { INDEX_op_ld16s_i32, { "r", "r" } }, { INDEX_op_ld_i32, { "r", "r" } }, - { INDEX_op_st8_i32, { "q", "r" } }, - { INDEX_op_st16_i32, { "r", "r" } }, - { INDEX_op_st_i32, { "r", "r" } }, + { INDEX_op_st8_i32, { "qi", "r" } }, + { INDEX_op_st16_i32, { "ri", "r" } }, + { INDEX_op_st_i32, { "ri", "r" } }, { INDEX_op_add_i32, { "r", "r", "ri" } }, { INDEX_op_sub_i32, { "r", "0", "ri" } }, @@ -1873,10 +1897,10 @@ static const TCGTargetOpDef x86_op_defs[] = { { INDEX_op_ld32u_i64, { "r", "r" } }, { INDEX_op_ld32s_i64, { "r", "r" } }, { INDEX_op_ld_i64, { "r", "r" } }, - { INDEX_op_st8_i64, { "r", "r" } }, - { INDEX_op_st16_i64, { "r", "r" } }, - { INDEX_op_st32_i64, { "r", "r" } }, - { INDEX_op_st_i64, { "r", "r" } }, + { INDEX_op_st8_i64, { "ri", "r" } }, + { INDEX_op_st16_i64, { "ri", "r" } }, + { INDEX_op_st32_i64, { "ri", "r" } }, + { INDEX_op_st_i64, { "re", "r" } }, { INDEX_op_add_i64, { "r", "0", "re" } }, { INDEX_op_mul_i64, { "r", "0", "re" } }, From 332864bd95257111bf457e3f0501114028c107d6 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Mon, 10 Sep 2012 14:23:49 +0200 Subject: [PATCH 0430/2270] tcg: mark set_label with TCG_OPF_BB_END flag set_label is effectively the end of a basic block, as no optimization can be made accross it. It was treated as such in the liveness analysis code, but as a special case. Mark it with TCG_OPF_BB_END flag so that this information can be used by other parts of the TCG code, and remove the special case in the liveness analysis code. Cc: Blue Swirl Signed-off-by: Aurelien Jarno --- tcg/tcg-opc.h | 2 +- tcg/tcg.c | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h index 8e06d03b17..d12e8d01e9 100644 --- a/tcg/tcg-opc.h +++ b/tcg/tcg-opc.h @@ -36,7 +36,7 @@ DEF(nopn, 0, 0, 1, 0) /* variable number of parameters */ DEF(discard, 1, 0, 0, 0) -DEF(set_label, 0, 0, 1, 0) +DEF(set_label, 0, 0, 1, TCG_OPF_BB_END) DEF(call, 0, 1, 2, TCG_OPF_SIDE_EFFECTS) /* variable number of parameters */ DEF(jmp, 0, 1, 0, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) DEF(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) diff --git a/tcg/tcg.c b/tcg/tcg.c index a4e7f42c78..b8a1bec5dc 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1297,11 +1297,6 @@ static void tcg_liveness_analysis(TCGContext *s) args--; } break; - case INDEX_op_set_label: - args--; - /* mark end of basic block */ - tcg_la_bb_end(s, dead_temps); - break; case INDEX_op_debug_insn_start: args -= def->nb_args; break; From d104bebd073cc05a1a572529a060857a377be6aa Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Mon, 10 Sep 2012 13:14:12 +0200 Subject: [PATCH 0431/2270] revert "TCG: fix copy propagation" Given the copy propagation breakage on 32-bit hosts has been fixed commit e31b0a7c050711884ad570fe73df806520953618 can be reverted. Cc: Blue Swirl Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 15 ++++++--------- tcg/tcg.h | 5 ----- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index fba0ed9592..10d9773dcb 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -107,15 +107,12 @@ static TCGOpcode op_to_movi(TCGOpcode op) } } -static void tcg_opt_gen_mov(TCGContext *s, TCGArg *gen_args, TCGArg dst, - TCGArg src, int nb_temps, int nb_globals) +static void tcg_opt_gen_mov(TCGArg *gen_args, TCGArg dst, TCGArg src, + int nb_temps, int nb_globals) { reset_temp(dst, nb_temps, nb_globals); assert(temps[src].state != TCG_TEMP_COPY); - /* Don't try to copy if one of temps is a global or either one - is local and another is register */ - if (src >= nb_globals && dst >= nb_globals && - tcg_arg_is_local(s, src) == tcg_arg_is_local(s, dst)) { + if (src >= nb_globals) { assert(temps[src].state != TCG_TEMP_CONST); if (temps[src].state != TCG_TEMP_HAS_COPY) { temps[src].state = TCG_TEMP_HAS_COPY; @@ -444,7 +441,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, gen_opc_buf[op_index] = INDEX_op_nop; } else { gen_opc_buf[op_index] = op_to_mov(op); - tcg_opt_gen_mov(s, gen_args, args[0], args[1], + tcg_opt_gen_mov(gen_args, args[0], args[1], nb_temps, nb_globals); gen_args += 2; } @@ -482,7 +479,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, gen_opc_buf[op_index] = INDEX_op_nop; } else { gen_opc_buf[op_index] = op_to_mov(op); - tcg_opt_gen_mov(s, gen_args, args[0], args[1], nb_temps, + tcg_opt_gen_mov(gen_args, args[0], args[1], nb_temps, nb_globals); gen_args += 2; } @@ -507,7 +504,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, break; } if (temps[args[1]].state != TCG_TEMP_CONST) { - tcg_opt_gen_mov(s, gen_args, args[0], args[1], + tcg_opt_gen_mov(gen_args, args[0], args[1], nb_temps, nb_globals); gen_args += 2; args += 2; diff --git a/tcg/tcg.h b/tcg/tcg.h index 7a72729f3a..477775dba6 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -459,11 +459,6 @@ static inline TCGv_i64 tcg_temp_local_new_i64(void) void tcg_temp_free_i64(TCGv_i64 arg); char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg); -static inline bool tcg_arg_is_local(TCGContext *s, TCGArg arg) -{ - return s->temps[arg].temp_local; -} - #if defined(CONFIG_DEBUG_TCG) /* If you call tcg_clear_temp_count() at the start of a section of * code which is not supposed to leak any TCG temporaries, then From 262e1eaafabf32d33a9fa0b03b3c8ea426c5ae1b Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Mon, 3 Sep 2012 22:47:03 +0200 Subject: [PATCH 0432/2270] pflash_cfi01: fix vendor specific extended query pflash_cfi01 announces a version number of 1.1, which implies "Protection Register Information" and "Burst Read information" sections, which are not provided. Decrease the version number to 1.0 so that only the "Protection Register Information" section is needed. Set the number of protection fields (0x3f) to 0x01, as 0x00 means 256 protections field, which makes the CFI table bigger than the current implementation, causing some kernels to fail to read it. Signed-off-by: Aurelien Jarno --- hw/pflash_cfi01.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index d1c742379b..d56b51abe6 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -711,7 +711,7 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base, pfl->cfi_table[0x33] = 'I'; pfl->cfi_table[0x34] = '1'; - pfl->cfi_table[0x35] = '1'; + pfl->cfi_table[0x35] = '0'; pfl->cfi_table[0x36] = 0x00; pfl->cfi_table[0x37] = 0x00; @@ -723,6 +723,8 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base, pfl->cfi_table[0x3b] = 0x00; pfl->cfi_table[0x3c] = 0x00; + pfl->cfi_table[0x3f] = 0x01; /* Number of protection fields */ + return pfl; } From eb99c9a993cc45f431a0b755595c8536aa947ace Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 18 Sep 2012 14:53:42 +0100 Subject: [PATCH 0433/2270] hw/pflash_cfi0[12]: Use host-utils.h ctz32() Drop the private reimplementation of ctz32() from pflash_cfi0[12] in favour of using the standard version from host-utils.h. Signed-off-by: Peter Maydell Reviewed-by: Stefan Weil Signed-off-by: Aurelien Jarno --- hw/pflash_cfi01.c | 37 +------------------------------------ hw/pflash_cfi02.c | 37 +------------------------------------ 2 files changed, 2 insertions(+), 72 deletions(-) diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index d56b51abe6..9c42d3105c 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -41,6 +41,7 @@ #include "block.h" #include "qemu-timer.h" #include "exec-memory.h" +#include "host-utils.h" #define PFLASH_BUG(fmt, ...) \ do { \ @@ -543,42 +544,6 @@ static const MemoryRegionOps pflash_cfi01_ops_le = { .endianness = DEVICE_NATIVE_ENDIAN, }; -/* Count trailing zeroes of a 32 bits quantity */ -static int ctz32 (uint32_t n) -{ - int ret; - - ret = 0; - if (!(n & 0xFFFF)) { - ret += 16; - n = n >> 16; - } - if (!(n & 0xFF)) { - ret += 8; - n = n >> 8; - } - if (!(n & 0xF)) { - ret += 4; - n = n >> 4; - } - if (!(n & 0x3)) { - ret += 2; - n = n >> 2; - } - if (!(n & 0x1)) { - ret++; -#if 0 /* This is not necessary as n is never 0 */ - n = n >> 1; -#endif - } -#if 0 /* This is not necessary as n is never 0 */ - if (!n) - ret++; -#endif - - return ret; -} - pflash_t *pflash_cfi01_register(target_phys_addr_t base, DeviceState *qdev, const char *name, target_phys_addr_t size, diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c index 3e2002e4b3..8cb1549587 100644 --- a/hw/pflash_cfi02.c +++ b/hw/pflash_cfi02.c @@ -40,6 +40,7 @@ #include "qemu-timer.h" #include "block.h" #include "exec-memory.h" +#include "host-utils.h" //#define PFLASH_DEBUG #ifdef PFLASH_DEBUG @@ -575,42 +576,6 @@ static const MemoryRegionOps pflash_cfi02_ops_le = { .endianness = DEVICE_NATIVE_ENDIAN, }; -/* Count trailing zeroes of a 32 bits quantity */ -static int ctz32 (uint32_t n) -{ - int ret; - - ret = 0; - if (!(n & 0xFFFF)) { - ret += 16; - n = n >> 16; - } - if (!(n & 0xFF)) { - ret += 8; - n = n >> 8; - } - if (!(n & 0xF)) { - ret += 4; - n = n >> 4; - } - if (!(n & 0x3)) { - ret += 2; - n = n >> 2; - } - if (!(n & 0x1)) { - ret++; -#if 0 /* This is not necessary as n is never 0 */ - n = n >> 1; -#endif - } -#if 0 /* This is not necessary as n is never 0 */ - if (!n) - ret++; -#endif - - return ret; -} - pflash_t *pflash_cfi02_register(target_phys_addr_t base, DeviceState *qdev, const char *name, target_phys_addr_t size, From e1050a7637d24d9f49e739cbe6d6d657359603db Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 18 Sep 2012 21:55:32 -0700 Subject: [PATCH 0434/2270] target-mips: Set opn in gen_ldst_multiple. Used by MIPS_DEBUG, when enabled. Signed-off-by: Richard Henderson Acked-by: Aurelien Jarno Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target-mips/translate.c b/target-mips/translate.c index 52eeb2bf79..50153a9db4 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -9855,6 +9855,7 @@ static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx) static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist, int base, int16_t offset) { + const char *opn = "ldst_multiple"; TCGv t0, t1; TCGv_i32 t2; @@ -9874,19 +9875,24 @@ static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist, switch (opc) { case LWM32: gen_helper_lwm(cpu_env, t0, t1, t2); + opn = "lwm"; break; case SWM32: gen_helper_swm(cpu_env, t0, t1, t2); + opn = "swm"; break; #ifdef TARGET_MIPS64 case LDM: gen_helper_ldm(cpu_env, t0, t1, t2); + opn = "ldm"; break; case SDM: gen_helper_sdm(cpu_env, t0, t1, t2); + opn = "sdm"; break; #endif } + (void)opn; MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]); tcg_temp_free(t0); tcg_temp_free(t1); From 9fa7748873c99cbf8b281650bdc18fd442be4743 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 18 Sep 2012 21:55:33 -0700 Subject: [PATCH 0435/2270] target-mips: Fix MIPS_DEBUG. The macro uses the DisasContext. Pass it around as needed. Signed-off-by: Richard Henderson Acked-by: Aurelien Jarno Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 74 +++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 50153a9db4..f93b444299 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1431,7 +1431,8 @@ static void gen_arith_imm (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, } /* Logic with immediate operand */ -static void gen_logic_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm) +static void gen_logic_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc, + int rt, int rs, int16_t imm) { target_ulong uimm; const char *opn = "imm logic"; @@ -1474,7 +1475,8 @@ static void gen_logic_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int1 } /* Set on less than with immediate operand */ -static void gen_slt_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm) +static void gen_slt_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc, + int rt, int rs, int16_t imm) { target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */ const char *opn = "imm arith"; @@ -1775,7 +1777,8 @@ static void gen_arith (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, } /* Conditional move */ -static void gen_cond_move (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt) +static void gen_cond_move(CPUMIPSState *env, DisasContext *ctx, uint32_t opc, + int rd, int rs, int rt) { const char *opn = "cond move"; int l1; @@ -1813,7 +1816,8 @@ static void gen_cond_move (CPUMIPSState *env, uint32_t opc, int rd, int rs, int } /* Logic */ -static void gen_logic (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt) +static void gen_logic(CPUMIPSState *env, DisasContext *ctx, uint32_t opc, + int rd, int rs, int rt) { const char *opn = "logic"; @@ -1874,7 +1878,8 @@ static void gen_logic (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt) } /* Set on lower than */ -static void gen_slt (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt) +static void gen_slt(CPUMIPSState *env, DisasContext *ctx, uint32_t opc, + int rd, int rs, int rt) { const char *opn = "slt"; TCGv t0, t1; @@ -8778,10 +8783,10 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx, gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm); break; case M16_OPC_SLTI: - gen_slt_imm(env, OPC_SLTI, 24, rx, imm); + gen_slt_imm(env, ctx, OPC_SLTI, 24, rx, imm); break; case M16_OPC_SLTIU: - gen_slt_imm(env, OPC_SLTIU, 24, rx, imm); + gen_slt_imm(env, ctx, OPC_SLTIU, 24, rx, imm); break; case M16_OPC_I8: switch (funct) { @@ -8992,15 +8997,13 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, case M16_OPC_SLTI: { int16_t imm = (uint8_t) ctx->opcode; - - gen_slt_imm(env, OPC_SLTI, 24, rx, imm); + gen_slt_imm(env, ctx, OPC_SLTI, 24, rx, imm); } break; case M16_OPC_SLTIU: { int16_t imm = (uint8_t) ctx->opcode; - - gen_slt_imm(env, OPC_SLTIU, 24, rx, imm); + gen_slt_imm(env, ctx, OPC_SLTIU, 24, rx, imm); } break; case M16_OPC_I8: @@ -9075,8 +9078,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, case M16_OPC_CMPI: { int16_t imm = (uint8_t) ctx->opcode; - - gen_logic_imm(env, OPC_XORI, 24, rx, imm); + gen_logic_imm(env, ctx, OPC_XORI, 24, rx, imm); } break; #if defined(TARGET_MIPS64) @@ -9188,10 +9190,10 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, } break; case RR_SLT: - gen_slt(env, OPC_SLT, 24, rx, ry); + gen_slt(env, ctx, OPC_SLT, 24, rx, ry); break; case RR_SLTU: - gen_slt(env, OPC_SLTU, 24, rx, ry); + gen_slt(env, ctx, OPC_SLTU, 24, rx, ry); break; case RR_BREAK: generate_exception(ctx, EXCP_BREAK); @@ -9212,22 +9214,22 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, break; #endif case RR_CMP: - gen_logic(env, OPC_XOR, 24, rx, ry); + gen_logic(env, ctx, OPC_XOR, 24, rx, ry); break; case RR_NEG: gen_arith(env, ctx, OPC_SUBU, rx, 0, ry); break; case RR_AND: - gen_logic(env, OPC_AND, rx, rx, ry); + gen_logic(env, ctx, OPC_AND, rx, rx, ry); break; case RR_OR: - gen_logic(env, OPC_OR, rx, rx, ry); + gen_logic(env, ctx, OPC_OR, rx, rx, ry); break; case RR_XOR: - gen_logic(env, OPC_XOR, rx, rx, ry); + gen_logic(env, ctx, OPC_XOR, rx, rx, ry); break; case RR_NOT: - gen_logic(env, OPC_NOR, rx, ry, 0); + gen_logic(env, ctx, OPC_NOR, rx, ry, 0); break; case RR_MFHI: gen_HILO(ctx, OPC_MFHI, rx); @@ -9849,7 +9851,7 @@ static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx) int rs = mmreg(uMIPS_RS(ctx->opcode)); int encoded = ZIMM(ctx->opcode, 0, 4); - gen_logic_imm(env, OPC_ANDI, rd, rs, decoded_imm[encoded]); + gen_logic_imm(env, ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]); } static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist, @@ -9911,25 +9913,25 @@ static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_bran case NOT16 + 1: case NOT16 + 2: case NOT16 + 3: - gen_logic(env, OPC_NOR, rd, rs, 0); + gen_logic(env, ctx, OPC_NOR, rd, rs, 0); break; case XOR16 + 0: case XOR16 + 1: case XOR16 + 2: case XOR16 + 3: - gen_logic(env, OPC_XOR, rd, rd, rs); + gen_logic(env, ctx, OPC_XOR, rd, rd, rs); break; case AND16 + 0: case AND16 + 1: case AND16 + 2: case AND16 + 3: - gen_logic(env, OPC_AND, rd, rd, rs); + gen_logic(env, ctx, OPC_AND, rd, rd, rs); break; case OR16 + 0: case OR16 + 1: case OR16 + 2: case OR16 + 3: - gen_logic(env, OPC_OR, rd, rd, rs); + gen_logic(env, ctx, OPC_OR, rd, rd, rs); break; case LWM16 + 0: case LWM16 + 1: @@ -10743,7 +10745,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, case XOR32: mips32_op = OPC_XOR; do_logic: - gen_logic(env, mips32_op, rd, rs, rt); + gen_logic(env, ctx, mips32_op, rd, rs, rt); break; /* Set less than */ case SLT: @@ -10752,7 +10754,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, case SLTU: mips32_op = OPC_SLTU; do_slt: - gen_slt(env, mips32_op, rd, rs, rt); + gen_slt(env, ctx, mips32_op, rd, rs, rt); break; default: goto pool32a_invalid; @@ -10768,7 +10770,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, case MOVZ: mips32_op = OPC_MOVZ; do_cmov: - gen_cond_move(env, mips32_op, rd, rs, rt); + gen_cond_move(env, ctx, mips32_op, rd, rs, rt); break; case LWXS: gen_ldxs(ctx, rs, rt, rd); @@ -11181,7 +11183,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, target. */ break; case LUI: - gen_logic_imm(env, OPC_LUI, rs, -1, imm); + gen_logic_imm(env, ctx, OPC_LUI, rs, -1, imm); break; case SYNCI: break; @@ -11300,7 +11302,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, case ANDI32: mips32_op = OPC_ANDI; do_logici: - gen_logic_imm(env, mips32_op, rt, rs, imm); + gen_logic_imm(env, ctx, mips32_op, rt, rs, imm); break; /* Set less than immediate */ @@ -11310,7 +11312,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, case SLTIU32: mips32_op = OPC_SLTIU; do_slti: - gen_slt_imm(env, mips32_op, rt, rs, imm); + gen_slt_imm(env, ctx, mips32_op, rt, rs, imm); break; case JALX32: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; @@ -11787,7 +11789,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_MOVZ: check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 | INSN_LOONGSON2E | INSN_LOONGSON2F); - gen_cond_move(env, op1, rd, rs, rt); + gen_cond_move(env, ctx, op1, rd, rs, rt); break; case OPC_ADD ... OPC_SUBU: gen_arith(env, ctx, op1, rd, rs, rt); @@ -11814,13 +11816,13 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) break; case OPC_SLT: /* Set on less than */ case OPC_SLTU: - gen_slt(env, op1, rd, rs, rt); + gen_slt(env, ctx, op1, rd, rs, rt); break; case OPC_AND: /* Logic*/ case OPC_OR: case OPC_NOR: case OPC_XOR: - gen_logic(env, op1, rd, rs, rt); + gen_logic(env, ctx, op1, rd, rs, rt); break; case OPC_MULT ... OPC_DIVU: if (sa) { @@ -12221,13 +12223,13 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) break; case OPC_SLTI: /* Set on less than with immediate opcode */ case OPC_SLTIU: - gen_slt_imm(env, op, rt, rs, imm); + gen_slt_imm(env, ctx, op, rt, rs, imm); break; case OPC_ANDI: /* Arithmetic with immediate opcode */ case OPC_LUI: case OPC_ORI: case OPC_XORI: - gen_logic_imm(env, op, rt, rs, imm); + gen_logic_imm(env, ctx, op, rt, rs, imm); break; case OPC_J ... OPC_JAL: /* Jump */ offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; From fb7729e2d03e1ffb4306f2411c18aa20f737dba8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 18 Sep 2012 21:55:34 -0700 Subject: [PATCH 0436/2270] target-mips: Always evaluate debugging macro arguments this will prevent some of the compilation errors with debugging enabled from creeping back in. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index f93b444299..4e04e97ce2 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -28,7 +28,7 @@ #define GEN_HELPER 1 #include "helper.h" -//#define MIPS_DEBUG_DISAS +#define MIPS_DEBUG_DISAS 0 //#define MIPS_DEBUG_SIGN_EXTENSIONS /* MIPS major opcodes */ @@ -566,22 +566,25 @@ static const char *fregnames[] = "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", }; -#ifdef MIPS_DEBUG_DISAS -#define MIPS_DEBUG(fmt, ...) \ - qemu_log_mask(CPU_LOG_TB_IN_ASM, \ - TARGET_FMT_lx ": %08x " fmt "\n", \ - ctx->pc, ctx->opcode , ## __VA_ARGS__) -#define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__) -#else -#define MIPS_DEBUG(fmt, ...) do { } while(0) -#define LOG_DISAS(...) do { } while (0) -#endif +#define MIPS_DEBUG(fmt, ...) \ + do { \ + if (MIPS_DEBUG_DISAS) { \ + qemu_log_mask(CPU_LOG_TB_IN_ASM, \ + TARGET_FMT_lx ": %08x " fmt "\n", \ + ctx->pc, ctx->opcode , ## __VA_ARGS__); \ + } \ + } while (0) + +#define LOG_DISAS(...) \ + do { \ + if (MIPS_DEBUG_DISAS) { \ + qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \ + } \ + } while (0) #define MIPS_INVAL(op) \ -do { \ MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \ - ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \ -} while (0) + ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)) /* General purpose registers moves. */ static inline void gen_load_gpr (TCGv t, int reg) From bd277fa1966bc400f1b411f868f39125cda0c403 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 18 Sep 2012 21:59:44 -0700 Subject: [PATCH 0437/2270] target-mips: Implement Loongson Multimedia Instructions Implements all of the COP2 instructions except for the S family of comparisons. The documentation is unclear for those. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/Makefile.objs | 2 +- target-mips/helper.h | 59 +++ target-mips/lmi_helper.c | 744 ++++++++++++++++++++++++++++++++++++++ target-mips/translate.c | 379 ++++++++++++++++++- 4 files changed, 1180 insertions(+), 4 deletions(-) create mode 100644 target-mips/lmi_helper.c diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs index ca20f21443..3eeeeac8b8 100644 --- a/target-mips/Makefile.objs +++ b/target-mips/Makefile.objs @@ -1,2 +1,2 @@ -obj-y += translate.o op_helper.o helper.o cpu.o +obj-y += translate.o op_helper.o lmi_helper.o helper.o cpu.o obj-$(CONFIG_SOFTMMU) += machine.o diff --git a/target-mips/helper.h b/target-mips/helper.h index 109ac37fd6..f35ed78c16 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -303,4 +303,63 @@ DEF_HELPER_1(rdhwr_ccres, tl, env) DEF_HELPER_2(pmon, void, env, int) DEF_HELPER_1(wait, void, env) +/* Loongson multimedia functions. */ +DEF_HELPER_FLAGS_2(paddsh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddush, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddsb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddusb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(psubsh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubush, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubsb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubusb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(pshufh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(packsswh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(packsshb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(packushb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(punpcklhw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(punpckhhw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(punpcklbh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(punpckhbh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(punpcklwd, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(punpckhwd, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(pavgh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pavgb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pmaxsh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pminsh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pmaxub, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pminub, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(pcmpeqw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pcmpgtw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pcmpeqh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pcmpgth, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pcmpeqb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pcmpgtb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(psllw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psllh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psrlw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psrlh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psraw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psrah, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(pmullh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pmulhh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pmulhuh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pmaddhw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) + +DEF_HELPER_FLAGS_2(pasubub, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_1(biadd, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64) +DEF_HELPER_FLAGS_1(pmovmskb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64) + #include "def-helper.h" diff --git a/target-mips/lmi_helper.c b/target-mips/lmi_helper.c new file mode 100644 index 0000000000..1b24353519 --- /dev/null +++ b/target-mips/lmi_helper.c @@ -0,0 +1,744 @@ +/* + * Loongson Multimedia Instruction emulation helpers for QEMU. + * + * Copyright (c) 2011 Richard Henderson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "cpu.h" +#include "helper.h" + +/* If the byte ordering doesn't matter, i.e. all columns are treated + identically, then this union can be used directly. If byte ordering + does matter, we generally ignore dumping to memory. */ +typedef union { + uint8_t ub[8]; + int8_t sb[8]; + uint16_t uh[4]; + int16_t sh[4]; + uint32_t uw[2]; + int32_t sw[2]; + uint64_t d; +} LMIValue; + +/* Some byte ordering issues can be mitigated by XORing in the following. */ +#ifdef HOST_WORDS_BIGENDIAN +# define BYTE_ORDER_XOR(N) N +#else +# define BYTE_ORDER_XOR(N) 0 +#endif + +#define SATSB(x) (x < -0x80 ? -0x80 : x > 0x7f ? 0x7f : x) +#define SATUB(x) (x > 0xff ? 0xff : x) + +#define SATSH(x) (x < -0x8000 ? -0x8000 : x > 0x7fff ? 0x7fff : x) +#define SATUH(x) (x > 0xffff ? 0xffff : x) + +#define SATSW(x) \ + (x < -0x80000000ll ? -0x80000000ll : x > 0x7fffffff ? 0x7fffffff : x) +#define SATUW(x) (x > 0xffffffffull ? 0xffffffffull : x) + +uint64_t helper_paddsb(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned int i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 8; ++i) { + int r = vs.sb[i] + vt.sb[i]; + vs.sb[i] = SATSB(r); + } + return vs.d; +} + +uint64_t helper_paddusb(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned int i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 8; ++i) { + int r = vs.ub[i] + vt.ub[i]; + vs.ub[i] = SATUB(r); + } + return vs.d; +} + +uint64_t helper_paddsh(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned int i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 4; ++i) { + int r = vs.sh[i] + vt.sh[i]; + vs.sh[i] = SATSH(r); + } + return vs.d; +} + +uint64_t helper_paddush(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned int i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 4; ++i) { + int r = vs.uh[i] + vt.uh[i]; + vs.uh[i] = SATUH(r); + } + return vs.d; +} + +uint64_t helper_paddb(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned int i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 8; ++i) { + vs.ub[i] += vt.ub[i]; + } + return vs.d; +} + +uint64_t helper_paddh(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned int i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 4; ++i) { + vs.uh[i] += vt.uh[i]; + } + return vs.d; +} + +uint64_t helper_paddw(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned int i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 2; ++i) { + vs.uw[i] += vt.uw[i]; + } + return vs.d; +} + +uint64_t helper_psubsb(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned int i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 8; ++i) { + int r = vs.sb[i] - vt.sb[i]; + vs.sb[i] = SATSB(r); + } + return vs.d; +} + +uint64_t helper_psubusb(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned int i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 8; ++i) { + int r = vs.ub[i] - vt.ub[i]; + vs.ub[i] = SATUB(r); + } + return vs.d; +} + +uint64_t helper_psubsh(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned int i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 4; ++i) { + int r = vs.sh[i] - vt.sh[i]; + vs.sh[i] = SATSH(r); + } + return vs.d; +} + +uint64_t helper_psubush(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned int i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 4; ++i) { + int r = vs.uh[i] - vt.uh[i]; + vs.uh[i] = SATUH(r); + } + return vs.d; +} + +uint64_t helper_psubb(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned int i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 8; ++i) { + vs.ub[i] -= vt.ub[i]; + } + return vs.d; +} + +uint64_t helper_psubh(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned int i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 4; ++i) { + vs.uh[i] -= vt.uh[i]; + } + return vs.d; +} + +uint64_t helper_psubw(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned int i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 2; ++i) { + vs.uw[i] -= vt.uw[i]; + } + return vs.d; +} + +uint64_t helper_pshufh(uint64_t fs, uint64_t ft) +{ + unsigned host = BYTE_ORDER_XOR(3); + LMIValue vd, vs; + unsigned i; + + vs.d = fs; + vd.d = 0; + for (i = 0; i < 4; i++, ft >>= 2) { + vd.uh[i ^ host] = vs.uh[(ft & 3) ^ host]; + } + return vd.d; +} + +uint64_t helper_packsswh(uint64_t fs, uint64_t ft) +{ + uint64_t fd = 0; + int64_t tmp; + + tmp = (int32_t)(fs >> 0); + tmp = SATSH(tmp); + fd |= (tmp & 0xffff) << 0; + + tmp = (int32_t)(fs >> 32); + tmp = SATSH(tmp); + fd |= (tmp & 0xffff) << 16; + + tmp = (int32_t)(ft >> 0); + tmp = SATSH(tmp); + fd |= (tmp & 0xffff) << 32; + + tmp = (int32_t)(ft >> 32); + tmp = SATSH(tmp); + fd |= (tmp & 0xffff) << 48; + + return fd; +} + +uint64_t helper_packsshb(uint64_t fs, uint64_t ft) +{ + uint64_t fd = 0; + unsigned int i; + + for (i = 0; i < 4; ++i) { + int16_t tmp = fs >> (i * 16); + tmp = SATSB(tmp); + fd |= (uint64_t)(tmp & 0xff) << (i * 8); + } + for (i = 0; i < 4; ++i) { + int16_t tmp = ft >> (i * 16); + tmp = SATSB(tmp); + fd |= (uint64_t)(tmp & 0xff) << (i * 8 + 32); + } + + return fd; +} + +uint64_t helper_packushb(uint64_t fs, uint64_t ft) +{ + uint64_t fd = 0; + unsigned int i; + + for (i = 0; i < 4; ++i) { + int16_t tmp = fs >> (i * 16); + tmp = SATUB(tmp); + fd |= (uint64_t)(tmp & 0xff) << (i * 8); + } + for (i = 0; i < 4; ++i) { + int16_t tmp = ft >> (i * 16); + tmp = SATUB(tmp); + fd |= (uint64_t)(tmp & 0xff) << (i * 8 + 32); + } + + return fd; +} + +uint64_t helper_punpcklwd(uint64_t fs, uint64_t ft) +{ + return (fs & 0xffffffff) | (ft << 32); +} + +uint64_t helper_punpckhwd(uint64_t fs, uint64_t ft) +{ + return (fs >> 32) | (ft & ~0xffffffffull); +} + +uint64_t helper_punpcklhw(uint64_t fs, uint64_t ft) +{ + unsigned host = BYTE_ORDER_XOR(3); + LMIValue vd, vs, vt; + + vs.d = fs; + vt.d = ft; + vd.uh[0 ^ host] = vs.uh[0 ^ host]; + vd.uh[1 ^ host] = vt.uh[0 ^ host]; + vd.uh[2 ^ host] = vs.uh[1 ^ host]; + vd.uh[3 ^ host] = vt.uh[1 ^ host]; + + return vd.d; +} + +uint64_t helper_punpckhhw(uint64_t fs, uint64_t ft) +{ + unsigned host = BYTE_ORDER_XOR(3); + LMIValue vd, vs, vt; + + vs.d = fs; + vt.d = ft; + vd.uh[0 ^ host] = vs.uh[2 ^ host]; + vd.uh[1 ^ host] = vt.uh[2 ^ host]; + vd.uh[2 ^ host] = vs.uh[3 ^ host]; + vd.uh[3 ^ host] = vt.uh[3 ^ host]; + + return vd.d; +} + +uint64_t helper_punpcklbh(uint64_t fs, uint64_t ft) +{ + unsigned host = BYTE_ORDER_XOR(7); + LMIValue vd, vs, vt; + + vs.d = fs; + vt.d = ft; + vd.ub[0 ^ host] = vs.ub[0 ^ host]; + vd.ub[1 ^ host] = vt.ub[0 ^ host]; + vd.ub[2 ^ host] = vs.ub[1 ^ host]; + vd.ub[3 ^ host] = vt.ub[1 ^ host]; + vd.ub[4 ^ host] = vs.ub[2 ^ host]; + vd.ub[5 ^ host] = vt.ub[2 ^ host]; + vd.ub[6 ^ host] = vs.ub[3 ^ host]; + vd.ub[7 ^ host] = vt.ub[3 ^ host]; + + return vd.d; +} + +uint64_t helper_punpckhbh(uint64_t fs, uint64_t ft) +{ + unsigned host = BYTE_ORDER_XOR(7); + LMIValue vd, vs, vt; + + vs.d = fs; + vt.d = ft; + vd.ub[0 ^ host] = vs.ub[4 ^ host]; + vd.ub[1 ^ host] = vt.ub[4 ^ host]; + vd.ub[2 ^ host] = vs.ub[5 ^ host]; + vd.ub[3 ^ host] = vt.ub[5 ^ host]; + vd.ub[4 ^ host] = vs.ub[6 ^ host]; + vd.ub[5 ^ host] = vt.ub[6 ^ host]; + vd.ub[6 ^ host] = vs.ub[7 ^ host]; + vd.ub[7 ^ host] = vt.ub[7 ^ host]; + + return vd.d; +} + +uint64_t helper_pavgh(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 4; i++) { + vs.uh[i] = (vs.uh[i] + vt.uh[i] + 1) >> 1; + } + return vs.d; +} + +uint64_t helper_pavgb(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 8; i++) { + vs.ub[i] = (vs.ub[i] + vt.ub[i] + 1) >> 1; + } + return vs.d; +} + +uint64_t helper_pmaxsh(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 4; i++) { + vs.sh[i] = (vs.sh[i] >= vt.sh[i] ? vs.sh[i] : vt.sh[i]); + } + return vs.d; +} + +uint64_t helper_pminsh(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 4; i++) { + vs.sh[i] = (vs.sh[i] <= vt.sh[i] ? vs.sh[i] : vt.sh[i]); + } + return vs.d; +} + +uint64_t helper_pmaxub(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 4; i++) { + vs.ub[i] = (vs.ub[i] >= vt.ub[i] ? vs.ub[i] : vt.ub[i]); + } + return vs.d; +} + +uint64_t helper_pminub(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 4; i++) { + vs.ub[i] = (vs.ub[i] <= vt.ub[i] ? vs.ub[i] : vt.ub[i]); + } + return vs.d; +} + +uint64_t helper_pcmpeqw(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 2; i++) { + vs.uw[i] = -(vs.uw[i] == vt.uw[i]); + } + return vs.d; +} + +uint64_t helper_pcmpgtw(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 2; i++) { + vs.uw[i] = -(vs.uw[i] > vt.uw[i]); + } + return vs.d; +} + +uint64_t helper_pcmpeqh(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 4; i++) { + vs.uh[i] = -(vs.uh[i] == vt.uh[i]); + } + return vs.d; +} + +uint64_t helper_pcmpgth(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 4; i++) { + vs.uh[i] = -(vs.uh[i] > vt.uh[i]); + } + return vs.d; +} + +uint64_t helper_pcmpeqb(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 8; i++) { + vs.ub[i] = -(vs.ub[i] == vt.ub[i]); + } + return vs.d; +} + +uint64_t helper_pcmpgtb(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 8; i++) { + vs.ub[i] = -(vs.ub[i] > vt.ub[i]); + } + return vs.d; +} + +uint64_t helper_psllw(uint64_t fs, uint64_t ft) +{ + LMIValue vs; + unsigned i; + + ft &= 0x7f; + if (ft > 31) { + return 0; + } + vs.d = fs; + for (i = 0; i < 2; ++i) { + vs.uw[i] <<= ft; + } + return vs.d; +} + +uint64_t helper_psrlw(uint64_t fs, uint64_t ft) +{ + LMIValue vs; + unsigned i; + + ft &= 0x7f; + if (ft > 31) { + return 0; + } + vs.d = fs; + for (i = 0; i < 2; ++i) { + vs.uw[i] >>= ft; + } + return vs.d; +} + +uint64_t helper_psraw(uint64_t fs, uint64_t ft) +{ + LMIValue vs; + unsigned i; + + ft &= 0x7f; + if (ft > 31) { + ft = 31; + } + vs.d = fs; + for (i = 0; i < 2; ++i) { + vs.sw[i] >>= ft; + } + return vs.d; +} + +uint64_t helper_psllh(uint64_t fs, uint64_t ft) +{ + LMIValue vs; + unsigned i; + + ft &= 0x7f; + if (ft > 15) { + return 0; + } + vs.d = fs; + for (i = 0; i < 4; ++i) { + vs.uh[i] <<= ft; + } + return vs.d; +} + +uint64_t helper_psrlh(uint64_t fs, uint64_t ft) +{ + LMIValue vs; + unsigned i; + + ft &= 0x7f; + if (ft > 15) { + return 0; + } + vs.d = fs; + for (i = 0; i < 4; ++i) { + vs.uh[i] >>= ft; + } + return vs.d; +} + +uint64_t helper_psrah(uint64_t fs, uint64_t ft) +{ + LMIValue vs; + unsigned i; + + ft &= 0x7f; + if (ft > 15) { + ft = 15; + } + vs.d = fs; + for (i = 0; i < 4; ++i) { + vs.sh[i] >>= ft; + } + return vs.d; +} + +uint64_t helper_pmullh(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 4; ++i) { + vs.sh[i] *= vt.sh[i]; + } + return vs.d; +} + +uint64_t helper_pmulhh(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 4; ++i) { + int32_t r = vs.sh[i] * vt.sh[i]; + vs.sh[i] = r >> 16; + } + return vs.d; +} + +uint64_t helper_pmulhuh(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 4; ++i) { + uint32_t r = vs.uh[i] * vt.uh[i]; + vs.uh[i] = r >> 16; + } + return vs.d; +} + +uint64_t helper_pmaddhw(uint64_t fs, uint64_t ft) +{ + unsigned host = BYTE_ORDER_XOR(3); + LMIValue vs, vt; + uint32_t p0, p1; + + vs.d = fs; + vt.d = ft; + p0 = vs.sh[0 ^ host] * vt.sh[0 ^ host]; + p0 += vs.sh[1 ^ host] * vt.sh[1 ^ host]; + p1 = vs.sh[2 ^ host] * vt.sh[2 ^ host]; + p1 += vs.sh[3 ^ host] * vt.sh[3 ^ host]; + + return ((uint64_t)p1 << 32) | p0; +} + +uint64_t helper_pasubub(uint64_t fs, uint64_t ft) +{ + LMIValue vs, vt; + unsigned i; + + vs.d = fs; + vt.d = ft; + for (i = 0; i < 8; ++i) { + int r = vs.ub[i] - vt.ub[i]; + vs.ub[i] = (r < 0 ? -r : r); + } + return vs.d; +} + +uint64_t helper_biadd(uint64_t fs) +{ + unsigned i, fd; + + for (i = fd = 0; i < 8; ++i) { + fd += (fs >> (i * 8)) & 0xff; + } + return fd & 0xffff; +} + +uint64_t helper_pmovmskb(uint64_t fs) +{ + unsigned fd = 0; + + fd |= ((fs >> 7) & 1) << 0; + fd |= ((fs >> 15) & 1) << 1; + fd |= ((fs >> 23) & 1) << 2; + fd |= ((fs >> 31) & 1) << 3; + fd |= ((fs >> 39) & 1) << 4; + fd |= ((fs >> 47) & 1) << 5; + fd |= ((fs >> 55) & 1) << 6; + fd |= ((fs >> 63) & 1) << 7; + + return fd & 0xff; +} diff --git a/target-mips/translate.c b/target-mips/translate.c index 4e04e97ce2..fa79d4945b 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -446,6 +446,103 @@ enum { OPC_BC2 = (0x08 << 21) | OPC_CP2, }; +#define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F)) + +enum { + OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2, + OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2, + OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2, + OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2, + OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2, + OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2, + OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2, + OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2, + + OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2, + OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2, + OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2, + OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2, + OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2, + OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2, + OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2, + OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2, + + OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2, + OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2, + OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2, + OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2, + OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2, + OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2, + OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2, + OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2, + + OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2, + OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2, + OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2, + OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2, + OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2, + OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2, + OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2, + OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2, + + OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2, + OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2, + OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2, + OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2, + OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2, + OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2, + + OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2, + OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2, + OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2, + OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2, + OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2, + OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2, + + OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2, + OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2, + OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2, + OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2, + OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2, + OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2, + + OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2, + OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2, + OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2, + OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2, + OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2, + OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2, + + OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2, + OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2, + OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2, + OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2, + OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2, + OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2, + + OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2, + OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2, + OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2, + OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2, + OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2, + OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2, + + OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2, + OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2, + OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2, + OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2, + OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2, + OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2, + + OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2, + OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2, + OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2, + OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2, + OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2, + OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2, +}; + + #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F) enum { @@ -2388,8 +2485,8 @@ static void gen_cl (DisasContext *ctx, uint32_t opc, } /* Godson integer instructions */ -static void gen_loongson_integer (DisasContext *ctx, uint32_t opc, - int rd, int rs, int rt) +static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, + int rd, int rs, int rt) { const char *opn = "loongson"; TCGv t0, t1; @@ -2602,6 +2699,278 @@ static void gen_loongson_integer (DisasContext *ctx, uint32_t opc, tcg_temp_free(t1); } +/* Loongson multimedia instructions */ +static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt) +{ + const char *opn = "loongson_cp2"; + uint32_t opc, shift_max; + TCGv_i64 t0, t1; + + opc = MASK_LMI(ctx->opcode); + switch (opc) { + case OPC_ADD_CP2: + case OPC_SUB_CP2: + case OPC_DADD_CP2: + case OPC_DSUB_CP2: + t0 = tcg_temp_local_new_i64(); + t1 = tcg_temp_local_new_i64(); + break; + default: + t0 = tcg_temp_new_i64(); + t1 = tcg_temp_new_i64(); + break; + } + + gen_load_fpr64(ctx, t0, rs); + gen_load_fpr64(ctx, t1, rt); + +#define LMI_HELPER(UP, LO) \ + case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break +#define LMI_HELPER_1(UP, LO) \ + case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break +#define LMI_DIRECT(UP, LO, OP) \ + case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break + + switch (opc) { + LMI_HELPER(PADDSH, paddsh); + LMI_HELPER(PADDUSH, paddush); + LMI_HELPER(PADDH, paddh); + LMI_HELPER(PADDW, paddw); + LMI_HELPER(PADDSB, paddsb); + LMI_HELPER(PADDUSB, paddusb); + LMI_HELPER(PADDB, paddb); + + LMI_HELPER(PSUBSH, psubsh); + LMI_HELPER(PSUBUSH, psubush); + LMI_HELPER(PSUBH, psubh); + LMI_HELPER(PSUBW, psubw); + LMI_HELPER(PSUBSB, psubsb); + LMI_HELPER(PSUBUSB, psubusb); + LMI_HELPER(PSUBB, psubb); + + LMI_HELPER(PSHUFH, pshufh); + LMI_HELPER(PACKSSWH, packsswh); + LMI_HELPER(PACKSSHB, packsshb); + LMI_HELPER(PACKUSHB, packushb); + + LMI_HELPER(PUNPCKLHW, punpcklhw); + LMI_HELPER(PUNPCKHHW, punpckhhw); + LMI_HELPER(PUNPCKLBH, punpcklbh); + LMI_HELPER(PUNPCKHBH, punpckhbh); + LMI_HELPER(PUNPCKLWD, punpcklwd); + LMI_HELPER(PUNPCKHWD, punpckhwd); + + LMI_HELPER(PAVGH, pavgh); + LMI_HELPER(PAVGB, pavgb); + LMI_HELPER(PMAXSH, pmaxsh); + LMI_HELPER(PMINSH, pminsh); + LMI_HELPER(PMAXUB, pmaxub); + LMI_HELPER(PMINUB, pminub); + + LMI_HELPER(PCMPEQW, pcmpeqw); + LMI_HELPER(PCMPGTW, pcmpgtw); + LMI_HELPER(PCMPEQH, pcmpeqh); + LMI_HELPER(PCMPGTH, pcmpgth); + LMI_HELPER(PCMPEQB, pcmpeqb); + LMI_HELPER(PCMPGTB, pcmpgtb); + + LMI_HELPER(PSLLW, psllw); + LMI_HELPER(PSLLH, psllh); + LMI_HELPER(PSRLW, psrlw); + LMI_HELPER(PSRLH, psrlh); + LMI_HELPER(PSRAW, psraw); + LMI_HELPER(PSRAH, psrah); + + LMI_HELPER(PMULLH, pmullh); + LMI_HELPER(PMULHH, pmulhh); + LMI_HELPER(PMULHUH, pmulhuh); + LMI_HELPER(PMADDHW, pmaddhw); + + LMI_HELPER(PASUBUB, pasubub); + LMI_HELPER_1(BIADD, biadd); + LMI_HELPER_1(PMOVMSKB, pmovmskb); + + LMI_DIRECT(PADDD, paddd, add); + LMI_DIRECT(PSUBD, psubd, sub); + LMI_DIRECT(XOR_CP2, xor, xor); + LMI_DIRECT(NOR_CP2, nor, nor); + LMI_DIRECT(AND_CP2, and, and); + LMI_DIRECT(PANDN, pandn, andc); + LMI_DIRECT(OR, or, or); + + case OPC_PINSRH_0: + tcg_gen_deposit_i64(t0, t0, t1, 0, 16); + opn = "pinsrh_0"; + break; + case OPC_PINSRH_1: + tcg_gen_deposit_i64(t0, t0, t1, 16, 16); + opn = "pinsrh_1"; + break; + case OPC_PINSRH_2: + tcg_gen_deposit_i64(t0, t0, t1, 32, 16); + opn = "pinsrh_2"; + break; + case OPC_PINSRH_3: + tcg_gen_deposit_i64(t0, t0, t1, 48, 16); + opn = "pinsrh_3"; + break; + + case OPC_PEXTRH: + tcg_gen_andi_i64(t1, t1, 3); + tcg_gen_shli_i64(t1, t1, 4); + tcg_gen_shr_i64(t0, t0, t1); + tcg_gen_ext16u_i64(t0, t0); + opn = "pextrh"; + break; + + case OPC_ADDU_CP2: + tcg_gen_add_i64(t0, t0, t1); + tcg_gen_ext32s_i64(t0, t0); + opn = "addu"; + break; + case OPC_SUBU_CP2: + tcg_gen_sub_i64(t0, t0, t1); + tcg_gen_ext32s_i64(t0, t0); + opn = "addu"; + break; + + case OPC_SLL_CP2: + opn = "sll"; + shift_max = 32; + goto do_shift; + case OPC_SRL_CP2: + opn = "srl"; + shift_max = 32; + goto do_shift; + case OPC_SRA_CP2: + opn = "sra"; + shift_max = 32; + goto do_shift; + case OPC_DSLL_CP2: + opn = "dsll"; + shift_max = 64; + goto do_shift; + case OPC_DSRL_CP2: + opn = "dsrl"; + shift_max = 64; + goto do_shift; + case OPC_DSRA_CP2: + opn = "dsra"; + shift_max = 64; + goto do_shift; + do_shift: + /* Make sure shift count isn't TCG undefined behaviour. */ + tcg_gen_andi_i64(t1, t1, shift_max - 1); + + switch (opc) { + case OPC_SLL_CP2: + case OPC_DSLL_CP2: + tcg_gen_shl_i64(t0, t0, t1); + break; + case OPC_SRA_CP2: + case OPC_DSRA_CP2: + /* Since SRA is UndefinedResult without sign-extended inputs, + we can treat SRA and DSRA the same. */ + tcg_gen_sar_i64(t0, t0, t1); + break; + case OPC_SRL_CP2: + /* We want to shift in zeros for SRL; zero-extend first. */ + tcg_gen_ext32u_i64(t0, t0); + /* FALLTHRU */ + case OPC_DSRL_CP2: + tcg_gen_shr_i64(t0, t0, t1); + break; + } + + if (shift_max == 32) { + tcg_gen_ext32s_i64(t0, t0); + } + + /* Shifts larger than MAX produce zero. */ + tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max); + tcg_gen_neg_i64(t1, t1); + tcg_gen_and_i64(t0, t0, t1); + break; + + case OPC_ADD_CP2: + case OPC_DADD_CP2: + { + TCGv_i64 t2 = tcg_temp_new_i64(); + int lab = gen_new_label(); + + tcg_gen_mov_i64(t2, t0); + tcg_gen_add_i64(t0, t1, t2); + if (opc == OPC_ADD_CP2) { + tcg_gen_ext32s_i64(t0, t0); + } + tcg_gen_xor_i64(t1, t1, t2); + tcg_gen_xor_i64(t2, t2, t0); + tcg_gen_andc_i64(t1, t2, t1); + tcg_temp_free_i64(t2); + tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab); + generate_exception(ctx, EXCP_OVERFLOW); + gen_set_label(lab); + + opn = (opc == OPC_ADD_CP2 ? "add" : "dadd"); + break; + } + + case OPC_SUB_CP2: + case OPC_DSUB_CP2: + { + TCGv_i64 t2 = tcg_temp_new_i64(); + int lab = gen_new_label(); + + tcg_gen_mov_i64(t2, t0); + tcg_gen_sub_i64(t0, t1, t2); + if (opc == OPC_SUB_CP2) { + tcg_gen_ext32s_i64(t0, t0); + } + tcg_gen_xor_i64(t1, t1, t2); + tcg_gen_xor_i64(t2, t2, t0); + tcg_gen_and_i64(t1, t1, t2); + tcg_temp_free_i64(t2); + tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab); + generate_exception(ctx, EXCP_OVERFLOW); + gen_set_label(lab); + + opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub"); + break; + } + + case OPC_PMULUW: + tcg_gen_ext32u_i64(t0, t0); + tcg_gen_ext32u_i64(t1, t1); + tcg_gen_mul_i64(t0, t0, t1); + opn = "pmuluw"; + break; + + case OPC_SEQU_CP2: + case OPC_SEQ_CP2: + case OPC_SLTU_CP2: + case OPC_SLT_CP2: + case OPC_SLEU_CP2: + case OPC_SLE_CP2: + /* ??? Document is unclear: Set FCC[CC]. Does that mean the + FD field is the CC field? */ + default: + MIPS_INVAL(opn); + generate_exception(ctx, EXCP_RI); + return; + } + +#undef LMI_HELPER +#undef LMI_DIRECT + + gen_store_fpr64(ctx, t0, rd); + + (void)opn; /* avoid a compiler warning */ + MIPS_DEBUG("%s %s, %s, %s", opn, + fregnames[rd], fregnames[rs], fregnames[rt]); + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); +} + /* Traps */ static void gen_trap (DisasContext *ctx, uint32_t opc, int rs, int rt, int16_t imm) @@ -12327,10 +12696,14 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_LDC2: case OPC_SWC2: case OPC_SDC2: - case OPC_CP2: /* COP2: Not implemented. */ generate_exception_err(ctx, EXCP_CpU, 2); break; + case OPC_CP2: + check_insn(env, ctx, INSN_LOONGSON2F); + /* Note that these instructions use different fields. */ + gen_loongson_multimedia(ctx, sa, rd, rt); + break; case OPC_CP3: if (env->CP0_Config1 & (1 << CP0C1_FP)) { From a25506603914d706f4ac4c63d3b93b4f1227b9b4 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Wed, 19 Sep 2012 21:40:30 +0200 Subject: [PATCH 0438/2270] tcg/optimize: fix end of basic block detection Commit e31b0a7c050711884ad570fe73df806520953618 fixed copy propagation on 32-bit host by restricting the copy between different types. This was the wrong fix. The real problem is that the all temps states should be reset at the end of a basic block. This was done by adding such operations in the switch, but brcond2 was forgotten (that's why the crash was only observed on 32-bit hosts). Fix that by looking at the TCG_OPF_BB_END instead. We need to keep the case for op_set_label as temps might be modified through another path. Cc: Blue Swirl Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index 10d9773dcb..9da333c303 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -632,21 +632,17 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, i--; } break; - case INDEX_op_set_label: - case INDEX_op_jmp: - case INDEX_op_br: - memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info)); - for (i = 0; i < def->nb_args; i++) { - *gen_args = *args; - args++; - gen_args++; - } - break; default: /* Default case: we do know nothing about operation so no - propagation is done. We only trash output args. */ - for (i = 0; i < def->nb_oargs; i++) { - reset_temp(args[i], nb_temps, nb_globals); + propagation is done. We trash everything if the operation + is the end of a basic block, otherwise we only trash the + output args. */ + if (def->flags & TCG_OPF_BB_END) { + memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info)); + } else { + for (i = 0; i < def->nb_oargs; i++) { + reset_temp(args[i], nb_temps, nb_globals); + } } for (i = 0; i < def->nb_args; i++) { gen_args[i] = args[i]; From f9cb5045d1eb6d187b0849d0f36735d3aac1a37f Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Fri, 21 Sep 2012 02:59:49 +0400 Subject: [PATCH 0439/2270] target-xtensa: fix extui shift amount extui opcode only uses lowermost op1 bit for sa4. Reported-by: malc Signed-off-by: Max Filippov Cc: qemu-stable Signed-off-by: malc --- target-xtensa/translate.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 1900bd5d44..7a1c528fc8 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -1778,12 +1778,30 @@ static void disas_xtensa_insn(DisasContext *dc) case 5: gen_window_check2(dc, RRR_R, RRR_T); { - int shiftimm = RRR_S | (OP1 << 4); + int shiftimm = RRR_S | ((OP1 & 1) << 4); int maskimm = (1 << (OP2 + 1)) - 1; TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_shri_i32(tmp, cpu_R[RRR_T], shiftimm); - tcg_gen_andi_i32(cpu_R[RRR_R], tmp, maskimm); + + if (shiftimm) { + tcg_gen_shri_i32(tmp, cpu_R[RRR_T], shiftimm); + } else { + tcg_gen_mov_i32(tmp, cpu_R[RRR_T]); + } + + switch (maskimm) { + case 0xff: + tcg_gen_ext8u_i32(cpu_R[RRR_R], tmp); + break; + + case 0xffff: + tcg_gen_ext16u_i32(cpu_R[RRR_R], tmp); + break; + + default: + tcg_gen_andi_i32(cpu_R[RRR_R], tmp, maskimm); + break; + } tcg_temp_free(tmp); } break; From c26032b2c91721245bfec542d94f37a0238e986e Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Fri, 21 Sep 2012 02:59:50 +0400 Subject: [PATCH 0440/2270] target-xtensa: don't emit extra tcg_gen_goto_tb Unconditional gen_check_loop_end at the end of disas_xtensa_insn can emit tcg_gen_goto_tb with slot id already used in the TB (e.g. when TB ends at LEND with a branch). Signed-off-by: Max Filippov Cc: qemu-stable Signed-off-by: malc --- target-xtensa/translate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 7a1c528fc8..b6643eb818 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -2520,7 +2520,9 @@ static void disas_xtensa_insn(DisasContext *dc) break; } - gen_check_loop_end(dc, 0); + if (dc->is_jmp == DISAS_NEXT) { + gen_check_loop_end(dc, 0); + } dc->pc = dc->next_pc; return; From f2ca052414d7eddc10517e98a5a27ba8099b19b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 17 Sep 2012 19:10:32 +0200 Subject: [PATCH 0441/2270] MAINTAINERS: Add entry for QOM CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 61f8b45cb5..25733fc864 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -531,6 +531,12 @@ M: Anthony Liguori S: Maintained F: qemu-char.c +CPU +M: Andreas Färber +S: Supported +F: qom/cpu.c +F: include/qemu/cpu.h + Device Tree M: Peter Crosthwaite M: Alexander Graf From 6cdf8854203e51a222c9ce94a8c8c568da834cf6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 5 Sep 2012 17:41:07 -0300 Subject: [PATCH 0442/2270] target-i386: Fold -cpu ?cpuid, ?model output into -cpu help, drop ?dump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit c8057f95 (accidentally) disabled the ability to pass option strings starting with '?' to the target-specific cpu_list function, so the target-i386 specific "-cpu ?dump", "-cpu ?cpuid" and "-cpu ?model" stopped working. Since these options are undocumented and not used by libvirt, simply drop them completely rather than reinstating them with new style syntax. Instead, we fold the ?model and ?cpuid output into the output of the plain "-cpu help" output. The detailed output produced by ?dump is dropped. Signed-off-by: Peter Maydell Signed-off-by: Eduardo Habkost Reviewed-by: Eduardo Habkost Reviewed-by: Igor Mammedov Signed-off-by: Andreas Färber --- target-i386/cpu.c | 64 ++++++++--------------------------------------- 1 file changed, 11 insertions(+), 53 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 423e00905d..5c98064c46 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1073,70 +1073,28 @@ static void listflags(char *buf, int bufsize, uint32_t fbits, } } -/* generate CPU information: - * -? list model names - * -?model list model names/IDs - * -?dump output all model (x86_def_t) data - * -?cpuid list all recognized cpuid flag names - */ +/* generate CPU information */ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf, const char *optarg) { - unsigned char model = !strcmp("?model", optarg); - unsigned char dump = !strcmp("?dump", optarg); - unsigned char cpuid = !strcmp("?cpuid", optarg); x86_def_t *def; char buf[256]; - if (cpuid) { - (*cpu_fprintf)(f, "Recognized CPUID flags:\n"); - listflags(buf, sizeof (buf), (uint32_t)~0, feature_name, 1); - (*cpu_fprintf)(f, " f_edx: %s\n", buf); - listflags(buf, sizeof (buf), (uint32_t)~0, ext_feature_name, 1); - (*cpu_fprintf)(f, " f_ecx: %s\n", buf); - listflags(buf, sizeof (buf), (uint32_t)~0, ext2_feature_name, 1); - (*cpu_fprintf)(f, " extf_edx: %s\n", buf); - listflags(buf, sizeof (buf), (uint32_t)~0, ext3_feature_name, 1); - (*cpu_fprintf)(f, " extf_ecx: %s\n", buf); - return; - } for (def = x86_defs; def; def = def->next) { snprintf(buf, sizeof (buf), def->flags ? "[%s]": "%s", def->name); - if (model || dump) { - (*cpu_fprintf)(f, "x86 %16s %-48s\n", buf, def->model_id); - } else { - (*cpu_fprintf)(f, "x86 %16s\n", buf); - } - if (dump) { - memcpy(buf, &def->vendor1, sizeof (def->vendor1)); - memcpy(buf + 4, &def->vendor2, sizeof (def->vendor2)); - memcpy(buf + 8, &def->vendor3, sizeof (def->vendor3)); - buf[12] = '\0'; - (*cpu_fprintf)(f, - " family %d model %d stepping %d level %d xlevel 0x%x" - " vendor \"%s\"\n", - def->family, def->model, def->stepping, def->level, - def->xlevel, buf); - listflags(buf, sizeof (buf), def->features, feature_name, 0); - (*cpu_fprintf)(f, " feature_edx %08x (%s)\n", def->features, - buf); - listflags(buf, sizeof (buf), def->ext_features, ext_feature_name, - 0); - (*cpu_fprintf)(f, " feature_ecx %08x (%s)\n", def->ext_features, - buf); - listflags(buf, sizeof (buf), def->ext2_features, ext2_feature_name, - 0); - (*cpu_fprintf)(f, " extfeature_edx %08x (%s)\n", - def->ext2_features, buf); - listflags(buf, sizeof (buf), def->ext3_features, ext3_feature_name, - 0); - (*cpu_fprintf)(f, " extfeature_ecx %08x (%s)\n", - def->ext3_features, buf); - (*cpu_fprintf)(f, "\n"); - } + (*cpu_fprintf)(f, "x86 %16s %-48s\n", buf, def->model_id); } if (kvm_enabled()) { (*cpu_fprintf)(f, "x86 %16s\n", "[host]"); } + (*cpu_fprintf)(f, "\nRecognized CPUID flags:\n"); + listflags(buf, sizeof(buf), (uint32_t)~0, feature_name, 1); + (*cpu_fprintf)(f, " f_edx: %s\n", buf); + listflags(buf, sizeof(buf), (uint32_t)~0, ext_feature_name, 1); + (*cpu_fprintf)(f, " f_ecx: %s\n", buf); + listflags(buf, sizeof(buf), (uint32_t)~0, ext2_feature_name, 1); + (*cpu_fprintf)(f, " extf_edx: %s\n", buf); + listflags(buf, sizeof(buf), (uint32_t)~0, ext3_feature_name, 1); + (*cpu_fprintf)(f, " extf_ecx: %s\n", buf); } CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) From e916cbf80328d46b288f6c82a12cb3b8fc4fbd4a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 5 Sep 2012 17:41:08 -0300 Subject: [PATCH 0443/2270] Drop cpu_list_id macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the only user of the extended cpu_list_id() format was the x86 ?model/?dump/?cpuid output, we can drop it completely. Signed-off-by: Peter Maydell Reviewed-by: Eduardo Habkost Signed-off-by: Eduardo Habkost Reviewed-by: Igor Mammedov Signed-off-by: Andreas Färber --- cpus.c | 6 ++---- linux-user/main.c | 6 ++---- target-i386/cpu.c | 4 ++-- target-i386/cpu.h | 4 ++-- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/cpus.c b/cpus.c index e476a3cd5e..4b726ef4e7 100644 --- a/cpus.c +++ b/cpus.c @@ -1192,10 +1192,8 @@ void set_cpu_log_filename(const char *optarg) void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg) { /* XXX: implement xxx_cpu_list for targets that still miss it */ -#if defined(cpu_list_id) - cpu_list_id(f, cpu_fprintf, optarg); -#elif defined(cpu_list) - cpu_list(f, cpu_fprintf); /* deprecated */ +#if defined(cpu_list) + cpu_list(f, cpu_fprintf); #endif } diff --git a/linux-user/main.c b/linux-user/main.c index e84a18c33c..9f3476ba57 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3130,10 +3130,8 @@ static void handle_arg_cpu(const char *arg) cpu_model = strdup(arg); if (cpu_model == NULL || is_help_option(cpu_model)) { /* XXX: implement xxx_cpu_list for targets that still miss it */ -#if defined(cpu_list_id) - cpu_list_id(stdout, &fprintf, ""); -#elif defined(cpu_list) - cpu_list(stdout, &fprintf); /* deprecated */ +#if defined(cpu_list) + cpu_list(stdout, &fprintf); #endif exit(1); } diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 5c98064c46..d2af0ff5c4 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1073,8 +1073,8 @@ static void listflags(char *buf, int bufsize, uint32_t fbits, } } -/* generate CPU information */ -void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf, const char *optarg) +/* generate CPU information. */ +void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) { x86_def_t *def; char buf[256]; diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 0677502dcc..49e0259430 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -792,7 +792,7 @@ typedef struct CPUX86State { X86CPU *cpu_x86_init(const char *cpu_model); int cpu_x86_exec(CPUX86State *s); -void x86_cpu_list (FILE *f, fprintf_function cpu_fprintf, const char *optarg); +void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf); void x86_cpudef_setup(void); int cpu_x86_support_mca_broadcast(CPUX86State *env); @@ -976,7 +976,7 @@ static inline CPUX86State *cpu_init(const char *cpu_model) #define cpu_exec cpu_x86_exec #define cpu_gen_code cpu_x86_gen_code #define cpu_signal_handler cpu_x86_signal_handler -#define cpu_list_id x86_cpu_list +#define cpu_list x86_cpu_list #define cpudef_setup x86_cpudef_setup #define CPU_SAVE_VERSION 12 From a75b081846176b020e5f39b37a0ae197172b7838 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 5 Sep 2012 17:41:09 -0300 Subject: [PATCH 0444/2270] target-i386: Add missing CPUID_* constants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those constants will be used by new CPU model definitions. Signed-off-by: Eduardo Habkost Reviewed-by: Igor Mammedov Signed-off-by: Andreas Färber --- target-i386/cpu.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 49e0259430..d7ea2f92a8 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -382,6 +382,7 @@ #define CPUID_PBE (1 << 31) #define CPUID_EXT_SSE3 (1 << 0) +#define CPUID_EXT_PCLMULQDQ (1 << 1) #define CPUID_EXT_DTES64 (1 << 2) #define CPUID_EXT_MONITOR (1 << 3) #define CPUID_EXT_DSCPL (1 << 4) @@ -401,14 +402,33 @@ #define CPUID_EXT_MOVBE (1 << 22) #define CPUID_EXT_POPCNT (1 << 23) #define CPUID_EXT_TSC_DEADLINE_TIMER (1 << 24) +#define CPUID_EXT_AES (1 << 25) #define CPUID_EXT_XSAVE (1 << 26) #define CPUID_EXT_OSXSAVE (1 << 27) +#define CPUID_EXT_AVX (1 << 28) #define CPUID_EXT_HYPERVISOR (1 << 31) +#define CPUID_EXT2_FPU (1 << 0) +#define CPUID_EXT2_DE (1 << 2) +#define CPUID_EXT2_PSE (1 << 3) +#define CPUID_EXT2_TSC (1 << 4) +#define CPUID_EXT2_MSR (1 << 5) +#define CPUID_EXT2_PAE (1 << 6) +#define CPUID_EXT2_MCE (1 << 7) +#define CPUID_EXT2_CX8 (1 << 8) +#define CPUID_EXT2_APIC (1 << 9) #define CPUID_EXT2_SYSCALL (1 << 11) +#define CPUID_EXT2_MTRR (1 << 12) +#define CPUID_EXT2_PGE (1 << 13) +#define CPUID_EXT2_MCA (1 << 14) +#define CPUID_EXT2_CMOV (1 << 15) +#define CPUID_EXT2_PAT (1 << 16) +#define CPUID_EXT2_PSE36 (1 << 17) #define CPUID_EXT2_MP (1 << 19) #define CPUID_EXT2_NX (1 << 20) #define CPUID_EXT2_MMXEXT (1 << 22) +#define CPUID_EXT2_MMX (1 << 23) +#define CPUID_EXT2_FXSR (1 << 24) #define CPUID_EXT2_FFXSR (1 << 25) #define CPUID_EXT2_PDPE1GB (1 << 26) #define CPUID_EXT2_RDTSCP (1 << 27) @@ -427,7 +447,9 @@ #define CPUID_EXT3_3DNOWPREFETCH (1 << 8) #define CPUID_EXT3_OSVW (1 << 9) #define CPUID_EXT3_IBS (1 << 10) +#define CPUID_EXT3_XOP (1 << 11) #define CPUID_EXT3_SKINIT (1 << 12) +#define CPUID_EXT3_FMA4 (1 << 16) #define CPUID_SVM_NPT (1 << 0) #define CPUID_SVM_LBRV (1 << 1) From 3eca46420c9f727ea5c50086d50a610f939affe5 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 5 Sep 2012 17:41:10 -0300 Subject: [PATCH 0445/2270] target-i386: Move CPU models from cpus-x86_64.conf to C MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those models are maintained by QEMU and may require compatibility code to be added when making some changes. Keeping the data in the C source code should make it simpler to handle those details. Signed-off-by: Eduardo Habkost Reviewed-by: Igor Mammedov Reviewed-by: Don Slutz Signed-off-by: Andreas Färber --- sysconfigs/target/cpus-x86_64.conf | 129 +---------------- target-i386/cpu.c | 219 +++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+), 128 deletions(-) diff --git a/sysconfigs/target/cpus-x86_64.conf b/sysconfigs/target/cpus-x86_64.conf index cee0ea9e55..3902189836 100644 --- a/sysconfigs/target/cpus-x86_64.conf +++ b/sysconfigs/target/cpus-x86_64.conf @@ -1,128 +1 @@ -# x86 CPU MODELS - -[cpudef] - name = "Conroe" - level = "2" - vendor = "GenuineIntel" - family = "6" - model = "2" - stepping = "3" - feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "ssse3 sse3" - extfeature_edx = "i64 xd syscall" - extfeature_ecx = "lahf_lm" - xlevel = "0x8000000A" - model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)" - -[cpudef] - name = "Penryn" - level = "2" - vendor = "GenuineIntel" - family = "6" - model = "2" - stepping = "3" - feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "sse4.1 cx16 ssse3 sse3" - extfeature_edx = "i64 xd syscall" - extfeature_ecx = "lahf_lm" - xlevel = "0x8000000A" - model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)" - -[cpudef] - name = "Nehalem" - level = "2" - vendor = "GenuineIntel" - family = "6" - model = "2" - stepping = "3" - feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "popcnt sse4.2 sse4.1 cx16 ssse3 sse3" - extfeature_edx = "i64 syscall xd" - extfeature_ecx = "lahf_lm" - xlevel = "0x8000000A" - model_id = "Intel Core i7 9xx (Nehalem Class Core i7)" - -[cpudef] - name = "Westmere" - level = "11" - vendor = "GenuineIntel" - family = "6" - model = "44" - stepping = "1" - feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "aes popcnt sse4.2 sse4.1 cx16 ssse3 sse3" - extfeature_edx = "i64 syscall xd" - extfeature_ecx = "lahf_lm" - xlevel = "0x8000000A" - model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)" - -[cpudef] - name = "SandyBridge" - level = "0xd" - vendor = "GenuineIntel" - family = "6" - model = "42" - stepping = "1" - feature_edx = " sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "avx xsave aes tsc-deadline popcnt x2apic sse4.2 sse4.1 cx16 ssse3 pclmulqdq sse3" - extfeature_edx = "i64 rdtscp nx syscall " - extfeature_ecx = "lahf_lm" - xlevel = "0x8000000A" - model_id = "Intel Xeon E312xx (Sandy Bridge)" - -[cpudef] - name = "Opteron_G1" - level = "5" - vendor = "AuthenticAMD" - family = "15" - model = "6" - stepping = "1" - feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "sse3" - extfeature_edx = "lm fxsr mmx nx pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de fpu" - extfeature_ecx = " " - xlevel = "0x80000008" - model_id = "AMD Opteron 240 (Gen 1 Class Opteron)" - -[cpudef] - name = "Opteron_G2" - level = "5" - vendor = "AuthenticAMD" - family = "15" - model = "6" - stepping = "1" - feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "cx16 sse3" - extfeature_edx = "lm rdtscp fxsr mmx nx pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de fpu" - extfeature_ecx = "svm lahf_lm" - xlevel = "0x80000008" - model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)" - -[cpudef] - name = "Opteron_G3" - level = "5" - vendor = "AuthenticAMD" - family = "15" - model = "6" - stepping = "1" - feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "popcnt cx16 monitor sse3" - extfeature_edx = "lm rdtscp fxsr mmx nx pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de fpu" - extfeature_ecx = "misalignsse sse4a abm svm lahf_lm" - xlevel = "0x80000008" - model_id = "AMD Opteron 23xx (Gen 3 Class Opteron)" - -[cpudef] - name = "Opteron_G4" - level = "0xd" - vendor = "AuthenticAMD" - family = "21" - model = "1" - stepping = "2" - feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "avx xsave aes popcnt sse4.2 sse4.1 cx16 ssse3 pclmulqdq sse3" - extfeature_edx = "lm rdtscp pdpe1gb fxsr mmx nx pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de fpu" - extfeature_ecx = " fma4 xop 3dnowprefetch misalignsse sse4a abm svm lahf_lm" - xlevel = "0x8000001A" - model_id = "AMD Opteron 62xx class CPU" - +# The CPU models from this file are now built-in in the QEMU source code diff --git a/target-i386/cpu.c b/target-i386/cpu.c index d2af0ff5c4..73302d80e5 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -490,6 +490,225 @@ static x86_def_t builtin_x86_defs[] = { .xlevel = 0x8000000A, .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz", }, + { + .name = "Conroe", + .level = 2, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, + .model = 2, + .stepping = 3, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_SSSE3 | CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, + .ext3_features = CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000000A, + .model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)", + }, + { + .name = "Penryn", + .level = 2, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, + .model = 2, + .stepping = 3, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | + CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, + .ext3_features = CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000000A, + .model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)", + }, + { + .name = "Nehalem", + .level = 2, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, + .model = 2, + .stepping = 3, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | + CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .ext3_features = CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000000A, + .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)", + }, + { + .name = "Westmere", + .level = 11, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, + .model = 44, + .stepping = 1, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | + CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | + CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .ext3_features = CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000000A, + .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)", + }, + { + .name = "SandyBridge", + .level = 0xd, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, + .model = 42, + .stepping = 1, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | + CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT | + CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | + CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | + CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | + CPUID_EXT2_SYSCALL, + .ext3_features = CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000000A, + .model_id = "Intel Xeon E312xx (Sandy Bridge)", + }, + { + .name = "Opteron_G1", + .level = 5, + .vendor1 = CPUID_VENDOR_AMD_1, + .vendor2 = CPUID_VENDOR_AMD_2, + .vendor3 = CPUID_VENDOR_AMD_3, + .family = 15, + .model = 6, + .stepping = 1, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_FXSR | CPUID_EXT2_MMX | + CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT | + CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE | + CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC | + CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR | + CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU, + .xlevel = 0x80000008, + .model_id = "AMD Opteron 240 (Gen 1 Class Opteron)", + }, + { + .name = "Opteron_G2", + .level = 5, + .vendor1 = CPUID_VENDOR_AMD_1, + .vendor2 = CPUID_VENDOR_AMD_2, + .vendor3 = CPUID_VENDOR_AMD_3, + .family = 15, + .model = 6, + .stepping = 1, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_CX16 | CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR | + CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 | + CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA | + CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | + CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE | + CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE | + CPUID_EXT2_DE | CPUID_EXT2_FPU, + .ext3_features = CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM, + .xlevel = 0x80000008, + .model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)", + }, + { + .name = "Opteron_G3", + .level = 5, + .vendor1 = CPUID_VENDOR_AMD_1, + .vendor2 = CPUID_VENDOR_AMD_2, + .vendor3 = CPUID_VENDOR_AMD_3, + .family = 15, + .model = 6, + .stepping = 1, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_POPCNT | CPUID_EXT_CX16 | CPUID_EXT_MONITOR | + CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR | + CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 | + CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA | + CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | + CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE | + CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE | + CPUID_EXT2_DE | CPUID_EXT2_FPU, + .ext3_features = CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | + CPUID_EXT3_ABM | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM, + .xlevel = 0x80000008, + .model_id = "AMD Opteron 23xx (Gen 3 Class Opteron)", + }, + { + .name = "Opteron_G4", + .level = 0xd, + .vendor1 = CPUID_VENDOR_AMD_1, + .vendor2 = CPUID_VENDOR_AMD_2, + .vendor3 = CPUID_VENDOR_AMD_3, + .family = 21, + .model = 1, + .stepping = 2, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | + CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | + CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | + CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | + CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX | + CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT | + CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE | + CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC | + CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR | + CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU, + .ext3_features = CPUID_EXT3_FMA4 | CPUID_EXT3_XOP | + CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE | + CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM | + CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000001A, + .model_id = "AMD Opteron 62xx class CPU", + }, }; static int cpu_x86_fill_model_id(char *str) From ba6212d8a809b89151a9d76b452b814836474029 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 5 Sep 2012 17:41:11 -0300 Subject: [PATCH 0446/2270] Eliminate cpus-x86_64.conf file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This file is not needed anymore, as QEMU won't ship any config-based cpudefs out of the box, relying only on the builtin CPU models. Signed-off-by: Eduardo Habkost Reviewed-by: Igor Mammedov Signed-off-by: Andreas Färber --- Makefile | 1 - arch_init.c | 1 - sysconfigs/target/cpus-x86_64.conf | 1 - 3 files changed, 3 deletions(-) delete mode 100644 sysconfigs/target/cpus-x86_64.conf diff --git a/Makefile b/Makefile index 971e92fd79..def2ae23cd 100644 --- a/Makefile +++ b/Makefile @@ -298,7 +298,6 @@ install-confdir: install-sysconfig: install-datadir install-confdir $(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/target-x86_64.conf "$(DESTDIR)$(qemu_confdir)" - $(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/cpus-x86_64.conf "$(DESTDIR)$(qemu_datadir)" install: all $(if $(BUILD_DOCS),install-doc) install-sysconfig install-datadir $(INSTALL_DIR) "$(DESTDIR)$(bindir)" diff --git a/arch_init.c b/arch_init.c index f849f9b872..9904f95478 100644 --- a/arch_init.c +++ b/arch_init.c @@ -136,7 +136,6 @@ static struct defconfig_file { /* Indicates it is an user config file (disabled by -no-user-config) */ bool userconfig; } default_config_files[] = { - { CONFIG_QEMU_DATADIR "/cpus-" TARGET_ARCH ".conf", false }, { CONFIG_QEMU_CONFDIR "/qemu.conf", true }, { CONFIG_QEMU_CONFDIR "/target-" TARGET_ARCH ".conf", true }, { NULL }, /* end of list */ diff --git a/sysconfigs/target/cpus-x86_64.conf b/sysconfigs/target/cpus-x86_64.conf deleted file mode 100644 index 3902189836..0000000000 --- a/sysconfigs/target/cpus-x86_64.conf +++ /dev/null @@ -1 +0,0 @@ -# The CPU models from this file are now built-in in the QEMU source code From bc3e1291ddcbc0f6548886a321c98227fa710173 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 5 Sep 2012 17:41:12 -0300 Subject: [PATCH 0447/2270] target-i386: x86_cpudef_setup() coding style change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make source code lines shorter. Signed-off-by: Eduardo Habkost Reviewed-by: Don Slutz Signed-off-by: Andreas Färber --- target-i386/cpu.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 73302d80e5..e13e6d55e2 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1513,20 +1513,23 @@ void x86_cpudef_setup(void) static const char *model_with_versions[] = { "qemu32", "qemu64", "athlon" }; for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) { - builtin_x86_defs[i].next = x86_defs; - builtin_x86_defs[i].flags = 1; + x86_def_t *def = &builtin_x86_defs[i]; + def->next = x86_defs; + def->flags = 1; /* Look for specific "cpudef" models that */ /* have the QEMU version in .model_id */ for (j = 0; j < ARRAY_SIZE(model_with_versions); j++) { - if (strcmp(model_with_versions[j], builtin_x86_defs[i].name) == 0) { - pstrcpy(builtin_x86_defs[i].model_id, sizeof(builtin_x86_defs[i].model_id), "QEMU Virtual CPU version "); - pstrcat(builtin_x86_defs[i].model_id, sizeof(builtin_x86_defs[i].model_id), qemu_get_version()); + if (strcmp(model_with_versions[j], def->name) == 0) { + pstrcpy(def->model_id, sizeof(def->model_id), + "QEMU Virtual CPU version "); + pstrcat(def->model_id, sizeof(def->model_id), + qemu_get_version()); break; } } - x86_defs = &builtin_x86_defs[i]; + x86_defs = def; } #if !defined(CONFIG_USER_ONLY) qemu_opts_foreach(qemu_find_opts("cpudef"), cpudef_register, NULL, 0); From c04321b3685a0b06d737d04146a0f1f2c5950b39 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 5 Sep 2012 17:41:13 -0300 Subject: [PATCH 0448/2270] target-i386: Kill cpudef config section support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's nice to have a flexible system to maintain CPU models as data, but this is holding us from making improvements in the CPU code because it's not using the common infra-structure, and because the machine-type data is still inside C code. Users who want to configure CPU features directly may simply use the "-cpu" command-line option (and maybe an equivalent -device option in the future) to set CPU features. Signed-off-by: Eduardo Habkost Signed-off-by: Andreas Färber --- target-i386/cpu.c | 101 +--------------------------------------------- 1 file changed, 2 insertions(+), 99 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index e13e6d55e2..7c0953f81e 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -240,7 +240,6 @@ typedef struct x86_def_t { uint32_t xlevel; char model_id[48]; int vendor_override; - uint32_t flags; /* Store the results of Centaur's CPUID instructions */ uint32_t ext4_features; uint32_t xlevel2; @@ -1299,7 +1298,7 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) char buf[256]; for (def = x86_defs; def; def = def->next) { - snprintf(buf, sizeof (buf), def->flags ? "[%s]": "%s", def->name); + snprintf(buf, sizeof(buf), "%s", def->name); (*cpu_fprintf)(f, "x86 %16s %-48s\n", buf, def->model_id); } if (kvm_enabled()) { @@ -1393,16 +1392,6 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) } #if !defined(CONFIG_USER_ONLY) -/* copy vendor id string to 32 bit register, nul pad as needed - */ -static void cpyid(const char *s, uint32_t *id) -{ - char *d = (char *)id; - char i; - - for (i = sizeof (*id); i--; ) - *d++ = *s ? *s++ : '\0'; -} /* interpret radix and convert from string to arbitrary scalar, * otherwise flag failure @@ -1416,87 +1405,6 @@ static void cpyid(const char *s, uint32_t *id) *str && !*pend ? (*pval = ul) : (*perr = 1); \ } -/* map cpuid options to feature bits, otherwise return failure - * (option tags in *str are delimited by whitespace) - */ -static void setfeatures(uint32_t *pval, const char *str, - const char **featureset, int *perr) -{ - const char *p, *q; - - for (q = p = str; *p || *q; q = p) { - while (iswhite(*p)) - q = ++p; - while (*p && !iswhite(*p)) - ++p; - if (!*q && !*p) - return; - if (!lookup_feature(pval, q, p, featureset)) { - fprintf(stderr, "error: feature \"%.*s\" not available in set\n", - (int)(p - q), q); - *perr = 1; - return; - } - } -} - -/* map config file options to x86_def_t form - */ -static int cpudef_setfield(const char *name, const char *str, void *opaque) -{ - x86_def_t *def = opaque; - int err = 0; - - if (!strcmp(name, "name")) { - g_free((void *)def->name); - def->name = g_strdup(str); - } else if (!strcmp(name, "model_id")) { - strncpy(def->model_id, str, sizeof (def->model_id)); - } else if (!strcmp(name, "level")) { - setscalar(&def->level, str, &err) - } else if (!strcmp(name, "vendor")) { - cpyid(&str[0], &def->vendor1); - cpyid(&str[4], &def->vendor2); - cpyid(&str[8], &def->vendor3); - } else if (!strcmp(name, "family")) { - setscalar(&def->family, str, &err) - } else if (!strcmp(name, "model")) { - setscalar(&def->model, str, &err) - } else if (!strcmp(name, "stepping")) { - setscalar(&def->stepping, str, &err) - } else if (!strcmp(name, "feature_edx")) { - setfeatures(&def->features, str, feature_name, &err); - } else if (!strcmp(name, "feature_ecx")) { - setfeatures(&def->ext_features, str, ext_feature_name, &err); - } else if (!strcmp(name, "extfeature_edx")) { - setfeatures(&def->ext2_features, str, ext2_feature_name, &err); - } else if (!strcmp(name, "extfeature_ecx")) { - setfeatures(&def->ext3_features, str, ext3_feature_name, &err); - } else if (!strcmp(name, "xlevel")) { - setscalar(&def->xlevel, str, &err) - } else { - fprintf(stderr, "error: unknown option [%s = %s]\n", name, str); - return (1); - } - if (err) { - fprintf(stderr, "error: bad option value [%s = %s]\n", name, str); - return (1); - } - return (0); -} - -/* register config file entry as x86_def_t - */ -static int cpudef_register(QemuOpts *opts, void *opaque) -{ - x86_def_t *def = g_malloc0(sizeof (x86_def_t)); - - qemu_opt_foreach(opts, cpudef_setfield, def, 1); - def->next = x86_defs; - x86_defs = def; - return (0); -} - void cpu_clear_apic_feature(CPUX86State *env) { env->cpuid_features &= ~CPUID_APIC; @@ -1504,8 +1412,7 @@ void cpu_clear_apic_feature(CPUX86State *env) #endif /* !CONFIG_USER_ONLY */ -/* register "cpudef" models defined in configuration file. Here we first - * preload any built-in definitions +/* Initialize list of CPU models, filling some non-static fields if necessary */ void x86_cpudef_setup(void) { @@ -1515,7 +1422,6 @@ void x86_cpudef_setup(void) for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) { x86_def_t *def = &builtin_x86_defs[i]; def->next = x86_defs; - def->flags = 1; /* Look for specific "cpudef" models that */ /* have the QEMU version in .model_id */ @@ -1531,9 +1437,6 @@ void x86_cpudef_setup(void) x86_defs = def; } -#if !defined(CONFIG_USER_ONLY) - qemu_opts_foreach(qemu_find_opts("cpudef"), cpudef_register, NULL, 0); -#endif } static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx, From 473955e5c3bce09c007ba3b64937cfca6f18f525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 17 Sep 2012 19:02:13 +0200 Subject: [PATCH 0449/2270] target-i386: Drop unused setscalar() macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was only used by now removed setfeatures() function. Suggested-by: Igor Mammedov Signed-off-by: Andreas Färber --- target-i386/cpu.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 7c0953f81e..c2e65ea311 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1393,18 +1393,6 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) #if !defined(CONFIG_USER_ONLY) -/* interpret radix and convert from string to arbitrary scalar, - * otherwise flag failure - */ -#define setscalar(pval, str, perr) \ -{ \ - char *pend; \ - unsigned long ul; \ - \ - ul = strtoul(str, &pend, 0); \ - *str && !*pend ? (*pval = ul) : (*perr = 1); \ -} - void cpu_clear_apic_feature(CPUX86State *env) { env->cpuid_features &= ~CPUID_APIC; From 2b85cf0efd81a6190320e7b488a0a4bad9743cc3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 14:15:36 +0200 Subject: [PATCH 0450/2270] target-alpha: Initialize env->cpu_model_str MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Save the cpu_model_str so that we have a non-null value when creating a new cpu during clone. Signed-off-by: Richard Henderson Signed-off-by: Andreas Färber --- target-alpha/translate.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 12de6a3fb6..93063fbe73 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -3549,6 +3549,7 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model) } env->implver = implver; env->amask = amask; + env->cpu_model_str = cpu_model; qemu_init_vcpu(env); return env; From f1a12821d7df2e4d21be4f2206f84b4640533e53 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Thu, 30 Aug 2012 17:28:40 -0700 Subject: [PATCH 0451/2270] iSCSI: We need to support SG_IO also from iscsi_ioctl() We need to support SG_IO from the synchronous iscsi_ioctl() since scsi-block uses this to do an INQ to the device to discover its properties This patch makes scsi-block work with iscsi. Signed-off-by: Ronnie Sahlberg Signed-off-by: Paolo Bonzini --- block/iscsi.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/block/iscsi.c b/block/iscsi.c index 0b96165ec2..ea1660948d 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -628,9 +628,17 @@ static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs, return &acb->common; } + +static void ioctl_cb(void *opaque, int status) +{ + int *p_status = opaque; + *p_status = status; +} + static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) { IscsiLun *iscsilun = bs->opaque; + int status; switch (req) { case SG_GET_VERSION_NUM: @@ -639,6 +647,15 @@ static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) case SG_GET_SCSI_ID: ((struct sg_scsi_id *)buf)->scsi_type = iscsilun->type; break; + case SG_IO: + status = -EINPROGRESS; + iscsi_aio_ioctl(bs, req, buf, ioctl_cb, &status); + + while (status == -EINPROGRESS) { + qemu_aio_wait(); + } + + return 0; default: return -1; } From 40a13ca8d28c21062e35b10d9b80e76b92405bdf Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Thu, 30 Aug 2012 16:56:36 -0700 Subject: [PATCH 0452/2270] iSCSI: We dont need to explicitely call qemu_notify_event() any more We no longer need to explicitely call qemu_notify_event() any more since this is now done automatically any time the filehandles we listen to change. Signed-off-by: Ronnie Sahlberg Signed-off-by: Paolo Bonzini --- block/iscsi.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/block/iscsi.c b/block/iscsi.c index ea1660948d..fb001b955c 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -167,12 +167,6 @@ iscsi_set_events(IscsiLun *iscsilun) } - /* If we just added an event, the callback might be delayed - * unless we call qemu_notify_event(). - */ - if (ev & ~iscsilun->events) { - qemu_notify_event(); - } iscsilun->events = ev; } From 444bc908611ccaf4512dc37c33ac3b54d873a62b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 5 Sep 2012 17:46:18 +0200 Subject: [PATCH 0453/2270] scsi-disk: introduce check_lba_range Abstract the test for an out-of-range (starting block, block count) pair. Signed-off-by: Paolo Bonzini --- hw/scsi-disk.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 1585683bce..3959603b0f 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -1449,6 +1449,18 @@ invalid_field: return; } +static inline bool check_lba_range(SCSIDiskState *s, + uint64_t sector_num, uint32_t nb_sectors) +{ + /* + * The first line tests that no overflow happens when computing the last + * sector. The second line tests that the last accessed sector is in + * range. + */ + return (sector_num <= sector_num + nb_sectors && + sector_num + nb_sectors - 1 <= s->qdev.max_lba); +} + typedef struct UnmapCBData { SCSIDiskReq *r; uint8_t *inbuf; @@ -1473,8 +1485,7 @@ static void scsi_unmap_complete(void *opaque, int ret) if (data->count > 0 && !r->req.io_canceled) { sector_num = ldq_be_p(&data->inbuf[0]); nb_sectors = ldl_be_p(&data->inbuf[8]) & 0xffffffffULL; - if (sector_num > sector_num + nb_sectors || - sector_num + nb_sectors - 1 > s->qdev.max_lba) { + if (!check_lba_range(s, sector_num, nb_sectors)) { scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE)); goto done; } @@ -1802,8 +1813,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED)); return 0; } - if (r->req.cmd.lba > r->req.cmd.lba + nb_sectors || - r->req.cmd.lba + nb_sectors - 1 > s->qdev.max_lba) { + if (!check_lba_range(s, r->req.cmd.lba, nb_sectors)) { goto illegal_lba; } @@ -1878,8 +1888,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) if (r->req.cmd.buf[1] & 0xe0) { goto illegal_request; } - if (r->req.cmd.lba > r->req.cmd.lba + len || - r->req.cmd.lba + len - 1 > s->qdev.max_lba) { + if (!check_lba_range(s, r->req.cmd.lba, len)) { goto illegal_lba; } r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512); @@ -1907,8 +1916,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) if (r->req.cmd.buf[1] & 0xe0) { goto illegal_request; } - if (r->req.cmd.lba > r->req.cmd.lba + len || - r->req.cmd.lba + len - 1 > s->qdev.max_lba) { + if (!check_lba_range(s, r->req.cmd.lba, len)) { goto illegal_lba; } r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512); From 12ca76fc48081b3a0ad1a70546abfcf198aedfc4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 5 Sep 2012 17:54:36 +0200 Subject: [PATCH 0454/2270] scsi-disk: fix check for out-of-range LBA This fix is needed to correctly handle 0-block read and writes. Without it, a 0-block access at LBA 0 would underflow. Signed-off-by: Paolo Bonzini --- hw/scsi-disk.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 3959603b0f..d621852857 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -1456,9 +1456,13 @@ static inline bool check_lba_range(SCSIDiskState *s, * The first line tests that no overflow happens when computing the last * sector. The second line tests that the last accessed sector is in * range. + * + * Careful, the computations should not underflow for nb_sectors == 0, + * and a 0-block read to the first LBA beyond the end of device is + * valid. */ return (sector_num <= sector_num + nb_sectors && - sector_num + nb_sectors - 1 <= s->qdev.max_lba); + sector_num + nb_sectors <= s->qdev.max_lba + 1); } typedef struct UnmapCBData { From bb729f758195a36db1dd0d5c01ec983e466729eb Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 5 Sep 2012 17:57:19 +0200 Subject: [PATCH 0455/2270] scsi: introduce scsi_cdb_length and scsi_data_cdb_length Signed-off-by: Paolo Bonzini --- hw/scsi-bus.c | 23 ++++++++++++++++++----- hw/scsi.h | 2 ++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 4981a02436..058d3b237f 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -801,26 +801,39 @@ static int ata_passthrough_16_xfer_size(SCSIDevice *dev, uint8_t *buf) return xfer * unit; } -static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf) +uint32_t scsi_data_cdb_length(uint8_t *buf) +{ + if ((buf[0] >> 5) == 0 && buf[4] == 0) { + return 256; + } else { + return scsi_cdb_length(buf); + } +} + +uint32_t scsi_cdb_length(uint8_t *buf) { switch (buf[0] >> 5) { case 0: - cmd->xfer = buf[4]; + return buf[4]; break; case 1: case 2: - cmd->xfer = lduw_be_p(&buf[7]); + return lduw_be_p(&buf[7]); break; case 4: - cmd->xfer = ldl_be_p(&buf[10]) & 0xffffffffULL; + return ldl_be_p(&buf[10]) & 0xffffffffULL; break; case 5: - cmd->xfer = ldl_be_p(&buf[6]) & 0xffffffffULL; + return ldl_be_p(&buf[6]) & 0xffffffffULL; break; default: return -1; } +} +static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf) +{ + cmd->xfer = scsi_cdb_length(buf); switch (buf[0]) { case TEST_UNIT_READY: case REWIND: diff --git a/hw/scsi.h b/hw/scsi.h index 1aeee4659c..b8f73577d3 100644 --- a/hw/scsi.h +++ b/hw/scsi.h @@ -218,6 +218,8 @@ extern const struct SCSISense sense_code_WRITE_PROTECTED; #define SENSE_CODE(x) sense_code_ ## x +uint32_t scsi_data_cdb_length(uint8_t *buf); +uint32_t scsi_cdb_length(uint8_t *buf); int scsi_sense_valid(SCSISense sense); int scsi_build_sense(uint8_t *in_buf, int in_len, uint8_t *buf, int len, bool fixed); From e93176d55f1eb4be1a366b51afeaf4f4c8c31d75 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 5 Sep 2012 18:00:57 +0200 Subject: [PATCH 0456/2270] scsi-disk: use scsi_data_cdb_length This simplifies and unifies the parsing of READ, WRITE and WRITE SAME commands. Signed-off-by: Paolo Bonzini --- hw/scsi-disk.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index d621852857..4ffca7aae5 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -1808,11 +1808,8 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) DPRINTF("Unmap (len %lu)\n", (long)r->req.cmd.xfer); break; case WRITE_SAME_10: - nb_sectors = lduw_be_p(&req->cmd.buf[7]); - goto write_same; case WRITE_SAME_16: - nb_sectors = ldl_be_p(&req->cmd.buf[10]) & 0xffffffffULL; - write_same: + nb_sectors = scsi_data_cdb_length(r->req.cmd.buf); if (bdrv_is_read_only(s->qdev.conf.bs)) { scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED)); return 0; @@ -1872,7 +1869,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) { SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req); SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); - int32_t len; + uint32_t len; uint8_t command; command = buf[0]; @@ -1882,13 +1879,13 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) return 0; } + len = scsi_data_cdb_length(r->req.cmd.buf); switch (command) { case READ_6: case READ_10: case READ_12: case READ_16: - len = r->req.cmd.xfer / s->qdev.blocksize; - DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len); + DPRINTF("Read (sector %" PRId64 ", count %u)\n", r->req.cmd.lba, len); if (r->req.cmd.buf[1] & 0xe0) { goto illegal_request; } @@ -1913,8 +1910,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) case VERIFY_10: case VERIFY_12: case VERIFY_16: - len = r->req.cmd.xfer / s->qdev.blocksize; - DPRINTF("Write %s(sector %" PRId64 ", count %d)\n", + DPRINTF("Write %s(sector %" PRId64 ", count %u)\n", (command & 0xe) == 0xe ? "And Verify " : "", r->req.cmd.lba, len); if (r->req.cmd.buf[1] & 0xe0) { From 1109c894052751df99962c009fd7dbae397721f5 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Fri, 14 Sep 2012 18:13:29 -0700 Subject: [PATCH 0457/2270] SCSI: Standard INQUIRY data should report HiSup flag as set. QEMU as far as I know only reports LUN numbers using the modes that are described in SAM4. As such, since all LUN numbers generated by the SCSI emulation in QEMU follow SAM4, we should set the HiSup bit in the standard INQUIRY data to indicate such. From SAM4: 4.6.3 LUNs overview All LUN formats described in this standard are hierarchical in structure even when only a single level in that hierarchy is used. The HISUP bit shall be set to one in the standard INQUIRY data (see SPC-4) when any LUN format described in this standard is used. Non-hierarchical formats are outside the scope of this standard. Signed-off-by: Ronnie Sahlberg --- hw/scsi-disk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 4ffca7aae5..95e91585e6 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -678,7 +678,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) * is actually implemented, but we're good enough. */ outbuf[2] = 5; - outbuf[3] = 2; /* Format 2 */ + outbuf[3] = 2 | 0x10; /* Format 2, HiSup */ if (buflen > 36) { outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */ From f8e7343956c91ba6cf26bf41b5a9a94e97ad4261 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 16 Sep 2012 13:12:20 +0200 Subject: [PATCH 0458/2270] target-sh4: mark a few helpers const and pure Signed-off-by: Aurelien Jarno --- target-sh4/helper.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target-sh4/helper.h b/target-sh4/helper.h index 6e4f108124..d498719f18 100644 --- a/target-sh4/helper.h +++ b/target-sh4/helper.h @@ -23,8 +23,8 @@ DEF_HELPER_3(macw, void, env, i32, i32) DEF_HELPER_2(ld_fpscr, void, env, i32) -DEF_HELPER_1(fabs_FT, f32, f32) -DEF_HELPER_1(fabs_DT, f64, f64) +DEF_HELPER_FLAGS_1(fabs_FT, TCG_CALL_CONST | TCG_CALL_PURE, f32, f32) +DEF_HELPER_FLAGS_1(fabs_DT, TCG_CALL_CONST | TCG_CALL_PURE, f64, f64) DEF_HELPER_3(fadd_FT, f32, env, f32, f32) DEF_HELPER_3(fadd_DT, f64, env, f64, f64) DEF_HELPER_2(fcnvsd_FT_DT, f64, env, f32) @@ -41,7 +41,7 @@ DEF_HELPER_2(float_DT, f64, env, i32) DEF_HELPER_4(fmac_FT, f32, env, f32, f32, f32) DEF_HELPER_3(fmul_FT, f32, env, f32, f32) DEF_HELPER_3(fmul_DT, f64, env, f64, f64) -DEF_HELPER_1(fneg_T, f32, f32) +DEF_HELPER_FLAGS_1(fneg_T, TCG_CALL_CONST | TCG_CALL_PURE, f32, f32) DEF_HELPER_3(fsub_FT, f32, env, f32, f32) DEF_HELPER_3(fsub_DT, f64, env, f64, f64) DEF_HELPER_2(fsqrt_FT, f32, env, f32) From ff2086fed268d2b2fedb273f6794949ed2ef9e10 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 16 Sep 2012 13:12:20 +0200 Subject: [PATCH 0459/2270] target-sh4: use float32_muladd() to implement fmac There is no need to add a SH4 specific pickNaNMulAdd() to softfloat as SH4 is always returning a default NaN. Signed-off-by: Aurelien Jarno --- target-sh4/op_helper.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c index 9b4328de37..bf835fac0f 100644 --- a/target-sh4/op_helper.c +++ b/target-sh4/op_helper.c @@ -623,8 +623,7 @@ float64 helper_float_DT(CPUSH4State *env, uint32_t t0) float32 helper_fmac_FT(CPUSH4State *env, float32 t0, float32 t1, float32 t2) { set_float_exception_flags(0, &env->fp_status); - t0 = float32_mul(t0, t1, &env->fp_status); - t0 = float32_add(t0, t2, &env->fp_status); + t0 = float32_muladd(t0, t1, t2, 0, &env->fp_status); update_fpscr(env, GETPC()); return t0; } From 22b88fd77e2fbb8aefb6e50a6a24d670b0ecb022 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 16 Sep 2012 13:12:20 +0200 Subject: [PATCH 0460/2270] target-sh4: implement addc and subc using TCG Now that setcond is available, the addc and subc can easily be implemented using TCG. Signed-off-by: Aurelien Jarno --- target-sh4/helper.h | 2 -- target-sh4/op_helper.c | 32 -------------------------------- target-sh4/translate.c | 38 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/target-sh4/helper.h b/target-sh4/helper.h index d498719f18..92d6dd7656 100644 --- a/target-sh4/helper.h +++ b/target-sh4/helper.h @@ -14,9 +14,7 @@ DEF_HELPER_1(discard_movcal_backup, void, env) DEF_HELPER_2(ocbi, void, env, i32) DEF_HELPER_3(addv, i32, env, i32, i32) -DEF_HELPER_3(addc, i32, env, i32, i32) DEF_HELPER_3(subv, i32, env, i32, i32) -DEF_HELPER_3(subc, i32, env, i32, i32) DEF_HELPER_3(div1, i32, env, i32, i32) DEF_HELPER_3(macl, void, env, i32, i32) DEF_HELPER_3(macw, void, env, i32, i32) diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c index bf835fac0f..3ad10bab94 100644 --- a/target-sh4/op_helper.c +++ b/target-sh4/op_helper.c @@ -177,22 +177,6 @@ void helper_ocbi(CPUSH4State *env, uint32_t address) } } -uint32_t helper_addc(CPUSH4State *env, uint32_t arg0, uint32_t arg1) -{ - uint32_t tmp0, tmp1; - - tmp1 = arg0 + arg1; - tmp0 = arg1; - arg1 = tmp1 + (env->sr & 1); - if (tmp0 > tmp1) - env->sr |= SR_T; - else - env->sr &= ~SR_T; - if (tmp1 > arg1) - env->sr |= SR_T; - return arg1; -} - uint32_t helper_addv(CPUSH4State *env, uint32_t arg0, uint32_t arg1) { uint32_t dest, src, ans; @@ -375,22 +359,6 @@ void helper_macw(CPUSH4State *env, uint32_t arg0, uint32_t arg1) } } -uint32_t helper_subc(CPUSH4State *env, uint32_t arg0, uint32_t arg1) -{ - uint32_t tmp0, tmp1; - - tmp1 = arg1 - arg0; - tmp0 = arg1; - arg1 = tmp1 - (env->sr & SR_T); - if (tmp0 < tmp1) - env->sr |= SR_T; - else - env->sr &= ~SR_T; - if (tmp1 < arg1) - env->sr |= SR_T; - return arg1; -} - uint32_t helper_subv(CPUSH4State *env, uint32_t arg0, uint32_t arg1) { int32_t dest, src, ans; diff --git a/target-sh4/translate.c b/target-sh4/translate.c index d05c74c8c3..92f9b462ff 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -761,7 +761,24 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4)); return; case 0x300e: /* addc Rm,Rn */ - gen_helper_addc(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8)); + { + TCGv t0, t1, t2; + t0 = tcg_temp_new(); + tcg_gen_andi_i32(t0, cpu_sr, SR_T); + t1 = tcg_temp_new(); + tcg_gen_add_i32(t1, REG(B7_4), REG(B11_8)); + tcg_gen_add_i32(t0, t0, t1); + t2 = tcg_temp_new(); + tcg_gen_setcond_i32(TCG_COND_GTU, t2, REG(B11_8), t1); + tcg_gen_setcond_i32(TCG_COND_GTU, t1, t1, t0); + tcg_gen_or_i32(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T); + tcg_gen_or_i32(cpu_sr, cpu_sr, t1); + tcg_temp_free(t1); + tcg_gen_mov_i32(REG(B11_8), t0); + tcg_temp_free(t0); + } return; case 0x300f: /* addv Rm,Rn */ gen_helper_addv(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8)); @@ -1013,7 +1030,24 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4)); return; case 0x300a: /* subc Rm,Rn */ - gen_helper_subc(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8)); + { + TCGv t0, t1, t2; + t0 = tcg_temp_new(); + tcg_gen_andi_i32(t0, cpu_sr, SR_T); + t1 = tcg_temp_new(); + tcg_gen_sub_i32(t1, REG(B11_8), REG(B7_4)); + tcg_gen_sub_i32(t0, t1, t0); + t2 = tcg_temp_new(); + tcg_gen_setcond_i32(TCG_COND_LTU, t2, REG(B11_8), t1); + tcg_gen_setcond_i32(TCG_COND_LTU, t1, t1, t0); + tcg_gen_or_i32(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T); + tcg_gen_or_i32(cpu_sr, cpu_sr, t1); + tcg_temp_free(t1); + tcg_gen_mov_i32(REG(B11_8), t0); + tcg_temp_free(t0); + } return; case 0x300b: /* subv Rm,Rn */ gen_helper_subv(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8)); From ad8d25a11f13cb8acc69558d03cd69202f5a3cc2 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 16 Sep 2012 13:12:20 +0200 Subject: [PATCH 0461/2270] target-sh4: implement addv and subv using TCG addv and subv helpers implementation is directly copied from the SH4 manual and looks quite complex. It is however possible to explain it without branches, and is therefore possible to implement it with TCG. Signed-off-by: Aurelien Jarno --- target-sh4/helper.h | 2 -- target-sh4/op_helper.c | 58 ------------------------------------------ target-sh4/translate.c | 36 ++++++++++++++++++++++++-- 3 files changed, 34 insertions(+), 62 deletions(-) diff --git a/target-sh4/helper.h b/target-sh4/helper.h index 92d6dd7656..a00b7dd1e7 100644 --- a/target-sh4/helper.h +++ b/target-sh4/helper.h @@ -13,8 +13,6 @@ DEF_HELPER_3(movcal, void, env, i32, i32) DEF_HELPER_1(discard_movcal_backup, void, env) DEF_HELPER_2(ocbi, void, env, i32) -DEF_HELPER_3(addv, i32, env, i32, i32) -DEF_HELPER_3(subv, i32, env, i32, i32) DEF_HELPER_3(div1, i32, env, i32, i32) DEF_HELPER_3(macl, void, env, i32, i32) DEF_HELPER_3(macw, void, env, i32, i32) diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c index 3ad10bab94..4f1f754680 100644 --- a/target-sh4/op_helper.c +++ b/target-sh4/op_helper.c @@ -177,35 +177,6 @@ void helper_ocbi(CPUSH4State *env, uint32_t address) } } -uint32_t helper_addv(CPUSH4State *env, uint32_t arg0, uint32_t arg1) -{ - uint32_t dest, src, ans; - - if ((int32_t) arg1 >= 0) - dest = 0; - else - dest = 1; - if ((int32_t) arg0 >= 0) - src = 0; - else - src = 1; - src += dest; - arg1 += arg0; - if ((int32_t) arg1 >= 0) - ans = 0; - else - ans = 1; - ans += dest; - if (src == 0 || src == 2) { - if (ans == 1) - env->sr |= SR_T; - else - env->sr &= ~SR_T; - } else - env->sr &= ~SR_T; - return arg1; -} - #define T (env->sr & SR_T) #define Q (env->sr & SR_Q ? 1 : 0) #define M (env->sr & SR_M ? 1 : 0) @@ -359,35 +330,6 @@ void helper_macw(CPUSH4State *env, uint32_t arg0, uint32_t arg1) } } -uint32_t helper_subv(CPUSH4State *env, uint32_t arg0, uint32_t arg1) -{ - int32_t dest, src, ans; - - if ((int32_t) arg1 >= 0) - dest = 0; - else - dest = 1; - if ((int32_t) arg0 >= 0) - src = 0; - else - src = 1; - src += dest; - arg1 -= arg0; - if ((int32_t) arg1 >= 0) - ans = 0; - else - ans = 1; - ans += dest; - if (src == 1) { - if (ans == 1) - env->sr |= SR_T; - else - env->sr &= ~SR_T; - } else - env->sr &= ~SR_T; - return arg1; -} - static inline void set_t(CPUSH4State *env) { env->sr |= SR_T; diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 92f9b462ff..41a1f228c7 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -781,7 +781,23 @@ static void _decode_opc(DisasContext * ctx) } return; case 0x300f: /* addv Rm,Rn */ - gen_helper_addv(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8)); + { + TCGv t0, t1, t2; + t0 = tcg_temp_new(); + tcg_gen_add_i32(t0, REG(B7_4), REG(B11_8)); + t1 = tcg_temp_new(); + tcg_gen_xor_i32(t1, t0, REG(B11_8)); + t2 = tcg_temp_new(); + tcg_gen_xor_i32(t2, REG(B7_4), REG(B11_8)); + tcg_gen_andc_i32(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_shri_i32(t1, t1, 31); + tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T); + tcg_gen_or_i32(cpu_sr, cpu_sr, t1); + tcg_temp_free(t1); + tcg_gen_mov_i32(REG(B7_4), t0); + tcg_temp_free(t0); + } return; case 0x2009: /* and Rm,Rn */ tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4)); @@ -1050,7 +1066,23 @@ static void _decode_opc(DisasContext * ctx) } return; case 0x300b: /* subv Rm,Rn */ - gen_helper_subv(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8)); + { + TCGv t0, t1, t2; + t0 = tcg_temp_new(); + tcg_gen_sub_i32(t0, REG(B11_8), REG(B7_4)); + t1 = tcg_temp_new(); + tcg_gen_xor_i32(t1, t0, REG(B7_4)); + t2 = tcg_temp_new(); + tcg_gen_xor_i32(t2, REG(B11_8), REG(B7_4)); + tcg_gen_and_i32(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_shri_i32(t1, t1, 31); + tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T); + tcg_gen_or_i32(cpu_sr, cpu_sr, t1); + tcg_temp_free(t1); + tcg_gen_mov_i32(REG(B11_8), t0); + tcg_temp_free(t0); + } return; case 0x2008: /* tst Rm,Rn */ { From f16640f47bb0b8f907fff08a2e8d1c891ce82480 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 16 Sep 2012 13:12:20 +0200 Subject: [PATCH 0462/2270] target-sh4: optimize xtrct The register being 32 bit long, after a shift to the right by 16 bits, the upper 16 bit are already cleared. There is no need to call ext16u to clear them. Signed-off-by: Aurelien Jarno --- target-sh4/translate.c | 1 - 1 file changed, 1 deletion(-) diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 41a1f228c7..92c5a1fb6d 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -751,7 +751,6 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_shli_i32(high, REG(B7_4), 16); low = tcg_temp_new(); tcg_gen_shri_i32(low, REG(B11_8), 16); - tcg_gen_ext16u_i32(low, low); tcg_gen_or_i32(REG(B11_8), high, low); tcg_temp_free(low); tcg_temp_free(high); From c53b36d210a55c67eca3ae89ebfdf665c0f2c3e2 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 16 Sep 2012 13:12:20 +0200 Subject: [PATCH 0463/2270] target-sh4: optimize swap.w It's possible swap the two 16-bit words of a 32-bit register using a rotation. If the TCG target doesn't implement rotation, the replacement code is similar to the previously implemented code. Signed-off-by: Aurelien Jarno --- target-sh4/translate.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 92c5a1fb6d..9ecbe471e6 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -732,17 +732,7 @@ static void _decode_opc(DisasContext * ctx) } return; case 0x6009: /* swap.w Rm,Rn */ - { - TCGv high, low; - high = tcg_temp_new(); - tcg_gen_shli_i32(high, REG(B7_4), 16); - low = tcg_temp_new(); - tcg_gen_shri_i32(low, REG(B7_4), 16); - tcg_gen_ext16u_i32(low, low); - tcg_gen_or_i32(REG(B11_8), high, low); - tcg_temp_free(low); - tcg_temp_free(high); - } + tcg_gen_rotli_i32(REG(B11_8), REG(B7_4), 16); return; case 0x200d: /* xtrct Rm,Rn */ { From ed22e6f30e7f8c723f9b1be30869b9c0368e3e4e Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 16 Sep 2012 13:12:20 +0200 Subject: [PATCH 0464/2270] target-sh4: remove gen_clr_t() and gen_set_t() gen_clr_t() and gen_set_t() have very few callers and can be remplaced by a single line. Remove them. Signed-off-by: Aurelien Jarno --- target-sh4/translate.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 9ecbe471e6..cdc4e3bc5f 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -339,16 +339,6 @@ static void gen_delayed_conditional_jump(DisasContext * ctx) gen_jump(ctx); } -static inline void gen_set_t(void) -{ - tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_T); -} - -static inline void gen_clr_t(void) -{ - tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T); -} - static inline void gen_cmp(int cond, TCGv t0, TCGv t1) { TCGv t; @@ -519,7 +509,7 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_S); return; case 0x0008: /* clrt */ - gen_clr_t(); + tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T); return; case 0x0038: /* ldtlb */ CHECK_PRIVILEGED @@ -537,7 +527,7 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_S); return; case 0x0018: /* sett */ - gen_set_t(); + tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_T); return; case 0xfbfd: /* frchg */ tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR); @@ -1660,7 +1650,7 @@ static void _decode_opc(DisasContext * ctx) */ if (ctx->features & SH_FEATURE_SH4A) { int label = gen_new_label(); - gen_clr_t(); + tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T); tcg_gen_or_i32(cpu_sr, cpu_sr, cpu_ldst); tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ldst, 0, label); tcg_gen_qemu_st32(REG(0), REG(B11_8), ctx->memidx); From 1012740098d0307ce5d957ebbe9a7f020da7f574 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 16 Sep 2012 13:12:21 +0200 Subject: [PATCH 0465/2270] target-sh4: rework exceptions handling Since commit fd4bab102 PC is restored in case of exception through code retranslation. While it is clearly the thing to do in case it is not not known if an helper is going to trigger an exception or not (e.g. for load/store, FPU, etc.), it just make things slower when the exception is already known at translation time. Partially revert this commit and save PC in the TCG code. Set bstate to BS_BRANCH to not generate TCG exit code. Micro-optimize the sleep helper. Make all the exception helpers to call raise_exception and mark it as noreturn. Signed-off-by: Aurelien Jarno --- target-sh4/helper.h | 14 +++++++------- target-sh4/op_helper.c | 30 +++++++++++++----------------- target-sh4/translate.c | 18 ++++++++++++------ 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/target-sh4/helper.h b/target-sh4/helper.h index a00b7dd1e7..6c1a47da9f 100644 --- a/target-sh4/helper.h +++ b/target-sh4/helper.h @@ -1,13 +1,13 @@ #include "def-helper.h" DEF_HELPER_1(ldtlb, void, env) -DEF_HELPER_1(raise_illegal_instruction, void, env) -DEF_HELPER_1(raise_slot_illegal_instruction, void, env) -DEF_HELPER_1(raise_fpu_disable, void, env) -DEF_HELPER_1(raise_slot_fpu_disable, void, env) -DEF_HELPER_1(debug, void, env) -DEF_HELPER_2(sleep, void, env, i32) -DEF_HELPER_2(trapa, void, env, i32) +DEF_HELPER_1(raise_illegal_instruction, noreturn, env) +DEF_HELPER_1(raise_slot_illegal_instruction, noreturn, env) +DEF_HELPER_1(raise_fpu_disable, noreturn, env) +DEF_HELPER_1(raise_slot_fpu_disable, noreturn, env) +DEF_HELPER_1(debug, noreturn, env) +DEF_HELPER_1(sleep, noreturn, env) +DEF_HELPER_2(trapa, noreturn, env, i32) DEF_HELPER_3(movcal, void, env, i32, i32) DEF_HELPER_1(discard_movcal_backup, void, env) diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c index 4f1f754680..60ec4cbc4d 100644 --- a/target-sh4/op_helper.c +++ b/target-sh4/op_helper.c @@ -21,7 +21,8 @@ #include "cpu.h" #include "helper.h" -static void cpu_restore_state_from_retaddr(CPUSH4State *env, uintptr_t retaddr) +static inline void cpu_restore_state_from_retaddr(CPUSH4State *env, + uintptr_t retaddr) { TranslationBlock *tb; @@ -77,8 +78,8 @@ void helper_ldtlb(CPUSH4State *env) #endif } -static inline void raise_exception(CPUSH4State *env, int index, - uintptr_t retaddr) +static inline void QEMU_NORETURN raise_exception(CPUSH4State *env, int index, + uintptr_t retaddr) { env->exception_index = index; cpu_restore_state_from_retaddr(env, retaddr); @@ -87,43 +88,40 @@ static inline void raise_exception(CPUSH4State *env, int index, void helper_raise_illegal_instruction(CPUSH4State *env) { - raise_exception(env, 0x180, GETPC()); + raise_exception(env, 0x180, 0); } void helper_raise_slot_illegal_instruction(CPUSH4State *env) { - raise_exception(env, 0x1a0, GETPC()); + raise_exception(env, 0x1a0, 0); } void helper_raise_fpu_disable(CPUSH4State *env) { - raise_exception(env, 0x800, GETPC()); + raise_exception(env, 0x800, 0); } void helper_raise_slot_fpu_disable(CPUSH4State *env) { - raise_exception(env, 0x820, GETPC()); + raise_exception(env, 0x820, 0); } void helper_debug(CPUSH4State *env) { - env->exception_index = EXCP_DEBUG; - cpu_loop_exit(env); + raise_exception(env, EXCP_DEBUG, 0); } -void helper_sleep(CPUSH4State *env, uint32_t next_pc) +void helper_sleep(CPUSH4State *env) { env->halted = 1; env->in_sleep = 1; - env->exception_index = EXCP_HLT; - env->pc = next_pc; - cpu_loop_exit(env); + raise_exception(env, EXCP_HLT, 0); } void helper_trapa(CPUSH4State *env, uint32_t tra) { env->tra = tra << 2; - raise_exception(env, 0x160, GETPC()); + raise_exception(env, 0x160, 0); } void helper_movcal(CPUSH4State *env, uint32_t address, uint32_t value) @@ -385,9 +383,7 @@ static void update_fpscr(CPUSH4State *env, uintptr_t retaddr) cause = (env->fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT; enable = (env->fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT; if (cause & enable) { - cpu_restore_state_from_retaddr(env, retaddr); - env->exception_index = 0x120; - cpu_loop_exit(env); + raise_exception(env, 0x120, retaddr); } } } diff --git a/target-sh4/translate.c b/target-sh4/translate.c index cdc4e3bc5f..6305db80f7 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -427,30 +427,33 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg) #define CHECK_NOT_DELAY_SLOT \ if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \ { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc); \ gen_helper_raise_slot_illegal_instruction(cpu_env); \ - ctx->bstate = BS_EXCP; \ + ctx->bstate = BS_BRANCH; \ return; \ } #define CHECK_PRIVILEGED \ if (IS_USER(ctx)) { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc); \ if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \ gen_helper_raise_slot_illegal_instruction(cpu_env); \ } else { \ gen_helper_raise_illegal_instruction(cpu_env); \ } \ - ctx->bstate = BS_EXCP; \ + ctx->bstate = BS_BRANCH; \ return; \ } #define CHECK_FPU_ENABLED \ if (ctx->flags & SR_FD) { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc); \ if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \ gen_helper_raise_slot_fpu_disable(cpu_env); \ } else { \ gen_helper_raise_fpu_disable(cpu_env); \ } \ - ctx->bstate = BS_EXCP; \ + ctx->bstate = BS_BRANCH; \ return; \ } @@ -541,7 +544,8 @@ static void _decode_opc(DisasContext * ctx) return; case 0x001b: /* sleep */ CHECK_PRIVILEGED - gen_helper_sleep(cpu_env, tcg_const_i32(ctx->pc + 2)); + tcg_gen_movi_i32(cpu_pc, ctx->pc + 2); + gen_helper_sleep(cpu_env); return; } @@ -1411,6 +1415,7 @@ static void _decode_opc(DisasContext * ctx) { TCGv imm; CHECK_NOT_DELAY_SLOT + tcg_gen_movi_i32(cpu_pc, ctx->pc); imm = tcg_const_i32(B7_0); gen_helper_trapa(cpu_env, imm); tcg_temp_free(imm); @@ -1909,12 +1914,13 @@ static void _decode_opc(DisasContext * ctx) ctx->opcode, ctx->pc); fflush(stderr); #endif + tcg_gen_movi_i32(cpu_pc, ctx->pc); if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { gen_helper_raise_slot_illegal_instruction(cpu_env); } else { gen_helper_raise_illegal_instruction(cpu_env); } - ctx->bstate = BS_EXCP; + ctx->bstate = BS_BRANCH; } static void decode_opc(DisasContext * ctx) @@ -1992,7 +1998,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb, /* We have hit a breakpoint - make sure PC is up-to-date */ tcg_gen_movi_i32(cpu_pc, ctx.pc); gen_helper_debug(cpu_env); - ctx.bstate = BS_EXCP; + ctx.bstate = BS_BRANCH; break; } } From 7a64244fda7b9b6257de30cfe93498ccd6017630 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 16 Sep 2012 13:12:21 +0200 Subject: [PATCH 0466/2270] target-sh4: cleanup DisasContext We should avoid accessing env at translation stage, except of course for static values like the supported features. Remove variables copied from env in DisasContext and use the TB flags instead. Signed-off-by: Aurelien Jarno --- target-sh4/translate.c | 56 ++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 6305db80f7..e5478cb98b 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -32,8 +32,6 @@ typedef struct DisasContext { struct TranslationBlock *tb; target_ulong pc; - uint32_t sr; - uint32_t fpscr; uint16_t opcode; uint32_t flags; int bstate; @@ -47,7 +45,7 @@ typedef struct DisasContext { #if defined(CONFIG_USER_ONLY) #define IS_USER(ctx) 1 #else -#define IS_USER(ctx) (!(ctx->sr & SR_MD)) +#define IS_USER(ctx) (!(ctx->flags & SR_MD)) #endif enum { @@ -413,15 +411,15 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg) #define B11_8 ((ctx->opcode >> 8) & 0xf) #define B15_12 ((ctx->opcode >> 12) & 0xf) -#define REG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB) ? \ - (cpu_gregs[x + 16]) : (cpu_gregs[x])) +#define REG(x) ((x) < 8 && (ctx->flags & (SR_MD | SR_RB)) == (SR_MD | SR_RB) \ + ? (cpu_gregs[x + 16]) : (cpu_gregs[x])) -#define ALTREG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) != (SR_MD | SR_RB) \ +#define ALTREG(x) ((x) < 8 && (ctx->flags & (SR_MD | SR_RB)) != (SR_MD | SR_RB)\ ? (cpu_gregs[x + 16]) : (cpu_gregs[x])) -#define FREG(x) (ctx->fpscr & FPSCR_FR ? (x) ^ 0x10 : (x)) +#define FREG(x) (ctx->flags & FPSCR_FR ? (x) ^ 0x10 : (x)) #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe)) -#define XREG(x) (ctx->fpscr & FPSCR_FR ? XHACK(x) ^ 0x10 : XHACK(x)) +#define XREG(x) (ctx->flags & FPSCR_FR ? XHACK(x) ^ 0x10 : XHACK(x)) #define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */ #define CHECK_NOT_DELAY_SLOT \ @@ -537,7 +535,7 @@ static void _decode_opc(DisasContext * ctx) ctx->bstate = BS_STOP; return; case 0xf3fd: /* fschg */ - tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ); + tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ); ctx->bstate = BS_STOP; return; case 0x0009: /* nop */ @@ -1080,7 +1078,7 @@ static void _decode_opc(DisasContext * ctx) return; case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */ CHECK_FPU_ENABLED - if (ctx->fpscr & FPSCR_SZ) { + if (ctx->flags & FPSCR_SZ) { TCGv_i64 fp = tcg_temp_new_i64(); gen_load_fpr64(fp, XREG(B7_4)); gen_store_fpr64(fp, XREG(B11_8)); @@ -1091,7 +1089,7 @@ static void _decode_opc(DisasContext * ctx) return; case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */ CHECK_FPU_ENABLED - if (ctx->fpscr & FPSCR_SZ) { + if (ctx->flags & FPSCR_SZ) { TCGv addr_hi = tcg_temp_new(); int fr = XREG(B7_4); tcg_gen_addi_i32(addr_hi, REG(B11_8), 4); @@ -1104,7 +1102,7 @@ static void _decode_opc(DisasContext * ctx) return; case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */ CHECK_FPU_ENABLED - if (ctx->fpscr & FPSCR_SZ) { + if (ctx->flags & FPSCR_SZ) { TCGv addr_hi = tcg_temp_new(); int fr = XREG(B11_8); tcg_gen_addi_i32(addr_hi, REG(B7_4), 4); @@ -1117,7 +1115,7 @@ static void _decode_opc(DisasContext * ctx) return; case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */ CHECK_FPU_ENABLED - if (ctx->fpscr & FPSCR_SZ) { + if (ctx->flags & FPSCR_SZ) { TCGv addr_hi = tcg_temp_new(); int fr = XREG(B11_8); tcg_gen_addi_i32(addr_hi, REG(B7_4), 4); @@ -1132,7 +1130,7 @@ static void _decode_opc(DisasContext * ctx) return; case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */ CHECK_FPU_ENABLED - if (ctx->fpscr & FPSCR_SZ) { + if (ctx->flags & FPSCR_SZ) { TCGv addr = tcg_temp_new_i32(); int fr = XREG(B7_4); tcg_gen_subi_i32(addr, REG(B11_8), 4); @@ -1155,7 +1153,7 @@ static void _decode_opc(DisasContext * ctx) { TCGv addr = tcg_temp_new_i32(); tcg_gen_add_i32(addr, REG(B7_4), REG(0)); - if (ctx->fpscr & FPSCR_SZ) { + if (ctx->flags & FPSCR_SZ) { int fr = XREG(B11_8); tcg_gen_qemu_ld32u(cpu_fregs[fr ], addr, ctx->memidx); tcg_gen_addi_i32(addr, addr, 4); @@ -1171,7 +1169,7 @@ static void _decode_opc(DisasContext * ctx) { TCGv addr = tcg_temp_new(); tcg_gen_add_i32(addr, REG(B11_8), REG(0)); - if (ctx->fpscr & FPSCR_SZ) { + if (ctx->flags & FPSCR_SZ) { int fr = XREG(B7_4); tcg_gen_qemu_ld32u(cpu_fregs[fr ], addr, ctx->memidx); tcg_gen_addi_i32(addr, addr, 4); @@ -1190,7 +1188,7 @@ static void _decode_opc(DisasContext * ctx) case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ { CHECK_FPU_ENABLED - if (ctx->fpscr & FPSCR_PR) { + if (ctx->flags & FPSCR_PR) { TCGv_i64 fp0, fp1; if (ctx->opcode & 0x0110) @@ -1259,7 +1257,7 @@ static void _decode_opc(DisasContext * ctx) case 0xf00e: /* fmac FR0,RM,Rn */ { CHECK_FPU_ENABLED - if (ctx->fpscr & FPSCR_PR) { + if (ctx->flags & FPSCR_PR) { break; /* illegal instruction */ } else { gen_helper_fmac_FT(cpu_fregs[FREG(B11_8)], cpu_env, @@ -1789,7 +1787,7 @@ static void _decode_opc(DisasContext * ctx) return; case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */ CHECK_FPU_ENABLED - if (ctx->fpscr & FPSCR_PR) { + if (ctx->flags & FPSCR_PR) { TCGv_i64 fp; if (ctx->opcode & 0x0100) break; /* illegal instruction */ @@ -1804,7 +1802,7 @@ static void _decode_opc(DisasContext * ctx) return; case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ CHECK_FPU_ENABLED - if (ctx->fpscr & FPSCR_PR) { + if (ctx->flags & FPSCR_PR) { TCGv_i64 fp; if (ctx->opcode & 0x0100) break; /* illegal instruction */ @@ -1825,7 +1823,7 @@ static void _decode_opc(DisasContext * ctx) return; case 0xf05d: /* fabs FRn/DRn */ CHECK_FPU_ENABLED - if (ctx->fpscr & FPSCR_PR) { + if (ctx->flags & FPSCR_PR) { if (ctx->opcode & 0x0100) break; /* illegal instruction */ TCGv_i64 fp = tcg_temp_new_i64(); @@ -1839,7 +1837,7 @@ static void _decode_opc(DisasContext * ctx) return; case 0xf06d: /* fsqrt FRn */ CHECK_FPU_ENABLED - if (ctx->fpscr & FPSCR_PR) { + if (ctx->flags & FPSCR_PR) { if (ctx->opcode & 0x0100) break; /* illegal instruction */ TCGv_i64 fp = tcg_temp_new_i64(); @@ -1857,13 +1855,13 @@ static void _decode_opc(DisasContext * ctx) break; case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */ CHECK_FPU_ENABLED - if (!(ctx->fpscr & FPSCR_PR)) { + if (!(ctx->flags & FPSCR_PR)) { tcg_gen_movi_i32(cpu_fregs[FREG(B11_8)], 0); } return; case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */ CHECK_FPU_ENABLED - if (!(ctx->fpscr & FPSCR_PR)) { + if (!(ctx->flags & FPSCR_PR)) { tcg_gen_movi_i32(cpu_fregs[FREG(B11_8)], 0x3f800000); } return; @@ -1887,7 +1885,7 @@ static void _decode_opc(DisasContext * ctx) return; case 0xf0ed: /* fipr FVm,FVn */ CHECK_FPU_ENABLED - if ((ctx->fpscr & FPSCR_PR) == 0) { + if ((ctx->flags & FPSCR_PR) == 0) { TCGv m, n; m = tcg_const_i32((ctx->opcode >> 8) & 3); n = tcg_const_i32((ctx->opcode >> 10) & 3); @@ -1900,7 +1898,7 @@ static void _decode_opc(DisasContext * ctx) case 0xf0fd: /* ftrv XMTRX,FVn */ CHECK_FPU_ENABLED if ((ctx->opcode & 0x0300) == 0x0100 && - (ctx->fpscr & FPSCR_PR) == 0) { + (ctx->flags & FPSCR_PR) == 0) { TCGv n; n = tcg_const_i32((ctx->opcode >> 10) & 3); gen_helper_ftrv(cpu_env, n); @@ -1974,16 +1972,14 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb, ctx.pc = pc_start; ctx.flags = (uint32_t)tb->flags; ctx.bstate = BS_NONE; - ctx.sr = env->sr; - ctx.fpscr = env->fpscr; - ctx.memidx = (env->sr & SR_MD) == 0 ? 1 : 0; + ctx.memidx = (ctx.flags & SR_MD) == 0 ? 1 : 0; /* We don't know if the delayed pc came from a dynamic or static branch, so assume it is a dynamic branch. */ ctx.delayed_pc = -1; /* use delayed pc from env pointer */ ctx.tb = tb; ctx.singlestep_enabled = env->singlestep_enabled; ctx.features = env->features; - ctx.has_movcal = (tb->flags & TB_FLAG_PENDING_MOVCA); + ctx.has_movcal = (ctx.flags & TB_FLAG_PENDING_MOVCA); ii = -1; num_insns = 0; From 080df491db6400fade2bdf1bdeee3a459529398b Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 16 Sep 2012 13:12:21 +0200 Subject: [PATCH 0467/2270] target-sh4: remove useless code Almost dead code. Signed-off-by: Aurelien Jarno --- target-sh4/translate.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/target-sh4/translate.c b/target-sh4/translate.c index e5478cb98b..0fa83cab99 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -18,7 +18,6 @@ */ #define DEBUG_DISAS -#define SH4_DEBUG_DISAS //#define SH4_SINGLE_STEP #include "cpu.h" @@ -2069,9 +2068,6 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb, } #ifdef DEBUG_DISAS -#ifdef SH4_DEBUG_DISAS - qemu_log_mask(CPU_LOG_TB_IN_ASM, "\n"); -#endif if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { qemu_log("IN:\n"); /* , lookup_symbol(pc_start)); */ log_target_disas(pc_start, ctx.pc - pc_start, 0); From ffc5ea09afb8f9487ed9d660f54a492889a067c7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 10:13:34 -0700 Subject: [PATCH 0468/2270] tcg: Introduce movcond Implemented with setcond if the target does not provide the optional opcode. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/README | 6 ++++++ tcg/arm/tcg-target.h | 1 + tcg/hppa/tcg-target.h | 1 + tcg/i386/tcg-target.h | 2 ++ tcg/ia64/tcg-target.h | 2 ++ tcg/mips/tcg-target.h | 1 + tcg/ppc/tcg-target.h | 1 + tcg/ppc64/tcg-target.h | 2 ++ tcg/s390/tcg-target.h | 2 ++ tcg/sparc/tcg-target.h | 2 ++ tcg/tcg-op.h | 40 ++++++++++++++++++++++++++++++++++++++++ tcg/tcg-opc.h | 2 ++ tcg/tcg.c | 11 +++++------ tcg/tcg.h | 1 + tcg/tci/tcg-target.h | 2 ++ 15 files changed, 70 insertions(+), 6 deletions(-) diff --git a/tcg/README b/tcg/README index cfdfd96d09..d03ae05e34 100644 --- a/tcg/README +++ b/tcg/README @@ -307,6 +307,12 @@ dest = (t1 cond t2) Set DEST to 1 if (T1 cond T2) is true, otherwise set to 0. +* movcond_i32/i64 cond, dest, c1, c2, v1, v2 + +dest = (c1 cond c2 ? v1 : v2) + +Set DEST to V1 if (C1 cond C2) is true, otherwise set to V2. + ********* Type conversions * ext_i32_i64 t0, t1 diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index c0b8f7274d..e2299cadd3 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -73,6 +73,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 0 +#define TCG_TARGET_HAS_movcond_i32 0 #define TCG_TARGET_HAS_GUEST_BASE diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h index 01ef9605f7..4defd28577 100644 --- a/tcg/hppa/tcg-target.h +++ b/tcg/hppa/tcg-target.h @@ -96,6 +96,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 1 +#define TCG_TARGET_HAS_movcond_i32 0 /* optional instructions automatically implemented */ #define TCG_TARGET_HAS_neg_i32 0 /* sub rd, 0, rs */ diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index 8be42f3ccb..504f9534ce 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -86,6 +86,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 1 +#define TCG_TARGET_HAS_movcond_i32 0 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_div2_i64 1 @@ -107,6 +108,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 1 +#define TCG_TARGET_HAS_movcond_i64 0 #endif #define TCG_TARGET_deposit_i32_valid(ofs, len) \ diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index c22962ac12..368aee4196 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -133,6 +133,8 @@ typedef enum { #define TCG_TARGET_HAS_rot_i64 1 #define TCG_TARGET_HAS_deposit_i32 0 #define TCG_TARGET_HAS_deposit_i64 0 +#define TCG_TARGET_HAS_movcond_i32 0 +#define TCG_TARGET_HAS_movcond_i64 0 /* optional instructions automatically implemented */ #define TCG_TARGET_HAS_neg_i32 0 /* sub r1, r0, r3 */ diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index 1c6193180c..9c68a32582 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -90,6 +90,7 @@ typedef enum { #define TCG_TARGET_HAS_eqv_i32 0 #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_deposit_i32 0 +#define TCG_TARGET_HAS_movcond_i32 0 /* optional instructions automatically implemented */ #define TCG_TARGET_HAS_neg_i32 0 /* sub rd, zero, rt */ diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h index 2f37fd289b..177eea1d79 100644 --- a/tcg/ppc/tcg-target.h +++ b/tcg/ppc/tcg-target.h @@ -92,6 +92,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 1 #define TCG_TARGET_HAS_nor_i32 1 #define TCG_TARGET_HAS_deposit_i32 1 +#define TCG_TARGET_HAS_movcond_i32 0 #define TCG_AREG0 TCG_REG_R27 diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h index 97eec0843d..57569e8938 100644 --- a/tcg/ppc64/tcg-target.h +++ b/tcg/ppc64/tcg-target.h @@ -83,6 +83,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 0 +#define TCG_TARGET_HAS_movcond_i32 0 #define TCG_TARGET_HAS_div_i64 1 #define TCG_TARGET_HAS_rot_i64 0 @@ -103,6 +104,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 0 +#define TCG_TARGET_HAS_movcond_i64 0 #define TCG_AREG0 TCG_REG_R27 diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h index 4f7dfaba50..ed55c331c6 100644 --- a/tcg/s390/tcg-target.h +++ b/tcg/s390/tcg-target.h @@ -63,6 +63,7 @@ typedef enum TCGReg { #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 0 +#define TCG_TARGET_HAS_movcond_i32 0 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_div2_i64 1 @@ -84,6 +85,7 @@ typedef enum TCGReg { #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 0 +#define TCG_TARGET_HAS_movcond_i64 0 #endif #define TCG_TARGET_HAS_GUEST_BASE diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index 0ea87bef72..d76257403d 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -102,6 +102,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 0 +#define TCG_TARGET_HAS_movcond_i32 0 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_div_i64 1 @@ -123,6 +124,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 0 +#define TCG_TARGET_HAS_movcond_i64 0 #endif #ifdef CONFIG_SOLARIS diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 169d3b2b0d..6d28f82ad8 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -2118,6 +2118,44 @@ static inline void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, tcg_temp_free_i64(t1); } +static inline void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, + TCGv_i32 c1, TCGv_i32 c2, + TCGv_i32 v1, TCGv_i32 v2) +{ + if (TCG_TARGET_HAS_movcond_i32) { + tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond); + } else { + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + tcg_gen_setcond_i32(cond, t0, c1, c2); + tcg_gen_neg_i32(t0, t0); + tcg_gen_and_i32(t1, v1, t0); + tcg_gen_andc_i32(ret, v2, t0); + tcg_gen_or_i32(ret, ret, t1); + tcg_temp_free_i32(t0); + tcg_temp_free_i32(t1); + } +} + +static inline void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, + TCGv_i64 c1, TCGv_i64 c2, + TCGv_i64 v1, TCGv_i64 v2) +{ + if (TCG_TARGET_HAS_movcond_i64) { + tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond); + } else { + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + tcg_gen_setcond_i64(cond, t0, c1, c2); + tcg_gen_neg_i64(t0, t0); + tcg_gen_and_i64(t1, v1, t0); + tcg_gen_andc_i64(ret, v2, t0); + tcg_gen_or_i64(ret, ret, t1); + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); + } +} + /***************************************/ /* QEMU specific operations. Their type depend on the QEMU CPU type. */ @@ -2434,6 +2472,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) #define tcg_gen_deposit_tl tcg_gen_deposit_i64 #define tcg_const_tl tcg_const_i64 #define tcg_const_local_tl tcg_const_local_i64 +#define tcg_gen_movcond_tl tcg_gen_movcond_i64 #else #define tcg_gen_movi_tl tcg_gen_movi_i32 #define tcg_gen_mov_tl tcg_gen_mov_i32 @@ -2505,6 +2544,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) #define tcg_gen_deposit_tl tcg_gen_deposit_i32 #define tcg_const_tl tcg_const_i32 #define tcg_const_local_tl tcg_const_local_i32 +#define tcg_gen_movcond_tl tcg_gen_movcond_i32 #endif #if TCG_TARGET_REG_BITS == 32 diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h index d12e8d01e9..dbb0e3916a 100644 --- a/tcg/tcg-opc.h +++ b/tcg/tcg-opc.h @@ -51,6 +51,7 @@ DEF(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) DEF(mov_i32, 1, 1, 0, 0) DEF(movi_i32, 1, 0, 1, 0) DEF(setcond_i32, 1, 2, 1, 0) +DEF(movcond_i32, 1, 4, 1, IMPL(TCG_TARGET_HAS_movcond_i32)) /* load/store */ DEF(ld8u_i32, 1, 1, 1, 0) DEF(ld8s_i32, 1, 1, 1, 0) @@ -107,6 +108,7 @@ DEF(nor_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_nor_i32)) DEF(mov_i64, 1, 1, 0, IMPL64) DEF(movi_i64, 1, 0, 1, IMPL64) DEF(setcond_i64, 1, 2, 1, IMPL64) +DEF(movcond_i64, 1, 4, 1, IMPL64 | IMPL(TCG_TARGET_HAS_movcond_i64)) /* load/store */ DEF(ld8u_i64, 1, 1, 1, IMPL64) DEF(ld8s_i64, 1, 1, 1, IMPL64) diff --git a/tcg/tcg.c b/tcg/tcg.c index b8a1bec5dc..bb9c9952aa 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -991,16 +991,15 @@ void tcg_dump_ops(TCGContext *s) } switch (c) { case INDEX_op_brcond_i32: + case INDEX_op_setcond_i32: + case INDEX_op_movcond_i32: #if TCG_TARGET_REG_BITS == 32 case INDEX_op_brcond2_i32: -#elif TCG_TARGET_REG_BITS == 64 - case INDEX_op_brcond_i64: -#endif - case INDEX_op_setcond_i32: -#if TCG_TARGET_REG_BITS == 32 case INDEX_op_setcond2_i32: -#elif TCG_TARGET_REG_BITS == 64 +#else + case INDEX_op_brcond_i64: case INDEX_op_setcond_i64: + case INDEX_op_movcond_i64: #endif if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) { qemu_log(",%s", cond_name[args[k++]]); diff --git a/tcg/tcg.h b/tcg/tcg.h index 477775dba6..7e903f30f0 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -79,6 +79,7 @@ typedef uint64_t TCGRegSet; #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 0 +#define TCG_TARGET_HAS_movcond_i64 0 #endif #ifndef TCG_TARGET_deposit_i32_valid diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h index 30a0f21596..6d894953aa 100644 --- a/tcg/tci/tcg-target.h +++ b/tcg/tci/tcg-target.h @@ -75,6 +75,7 @@ #define TCG_TARGET_HAS_not_i32 1 #define TCG_TARGET_HAS_orc_i32 0 #define TCG_TARGET_HAS_rot_i32 1 +#define TCG_TARGET_HAS_movcond_i32 0 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_bswap16_i64 1 @@ -98,6 +99,7 @@ #define TCG_TARGET_HAS_not_i64 1 #define TCG_TARGET_HAS_orc_i64 0 #define TCG_TARGET_HAS_rot_i64 1 +#define TCG_TARGET_HAS_movcond_i64 0 #endif /* TCG_TARGET_REG_BITS == 64 */ /* Offset to user memory in user mode. */ From 57e289de7330a97ff4c9919a1dad54ca0650cfa7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 10:13:35 -0700 Subject: [PATCH 0469/2270] target-alpha: Use movcond For proper cmov insns, as well as the non-goto-tb case of conditional branch. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-alpha/translate.c | 124 +++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 65 deletions(-) diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 12de6a3fb6..4a9011a2b6 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -426,27 +426,15 @@ static ExitStatus gen_bcond_internal(DisasContext *ctx, TCGCond cond, return EXIT_GOTO_TB; } else { - int lab_over = gen_new_label(); + TCGv_i64 z = tcg_const_i64(0); + TCGv_i64 d = tcg_const_i64(dest); + TCGv_i64 p = tcg_const_i64(ctx->pc); - /* ??? Consider using either - movi pc, next - addi tmp, pc, disp - movcond pc, cond, 0, tmp, pc - or - setcond tmp, cond, 0 - movi pc, next - neg tmp, tmp - andi tmp, tmp, disp - add pc, pc, tmp - The current diamond subgraph surely isn't efficient. */ - - tcg_gen_brcondi_i64(cond, cmp, 0, lab_true); - tcg_gen_movi_i64(cpu_pc, ctx->pc); - tcg_gen_br(lab_over); - gen_set_label(lab_true); - tcg_gen_movi_i64(cpu_pc, dest); - gen_set_label(lab_over); + tcg_gen_movcond_i64(cond, cpu_pc, cmp, z, d, p); + tcg_temp_free_i64(z); + tcg_temp_free_i64(d); + tcg_temp_free_i64(p); return EXIT_PC_UPDATED; } } @@ -521,61 +509,67 @@ static ExitStatus gen_fbcond(DisasContext *ctx, TCGCond cond, int ra, static void gen_cmov(TCGCond cond, int ra, int rb, int rc, int islit, uint8_t lit, int mask) { - TCGCond inv_cond = tcg_invert_cond(cond); - int l1; - - if (unlikely(rc == 31)) - return; - - l1 = gen_new_label(); - - if (ra != 31) { - if (mask) { - TCGv tmp = tcg_temp_new(); - tcg_gen_andi_i64(tmp, cpu_ir[ra], 1); - tcg_gen_brcondi_i64(inv_cond, tmp, 0, l1); - tcg_temp_free(tmp); - } else - tcg_gen_brcondi_i64(inv_cond, cpu_ir[ra], 0, l1); - } else { - /* Very uncommon case - Do not bother to optimize. */ - TCGv tmp = tcg_const_i64(0); - tcg_gen_brcondi_i64(inv_cond, tmp, 0, l1); - tcg_temp_free(tmp); - } - - if (islit) - tcg_gen_movi_i64(cpu_ir[rc], lit); - else - tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]); - gen_set_label(l1); -} - -static void gen_fcmov(TCGCond cond, int ra, int rb, int rc) -{ - TCGv cmp_tmp; - int l1; + TCGv_i64 c1, z, v1; if (unlikely(rc == 31)) { return; } - cmp_tmp = tcg_temp_new(); - if (unlikely(ra == 31)) { - tcg_gen_movi_i64(cmp_tmp, 0); + if (ra == 31) { + /* Very uncommon case - Do not bother to optimize. */ + c1 = tcg_const_i64(0); + } else if (mask) { + c1 = tcg_const_i64(1); + tcg_gen_and_i64(c1, c1, cpu_ir[ra]); } else { - gen_fold_mzero(cond, cmp_tmp, cpu_fir[ra]); + c1 = cpu_ir[ra]; + } + if (islit) { + v1 = tcg_const_i64(lit); + } else { + v1 = cpu_ir[rb]; + } + z = tcg_const_i64(0); + + tcg_gen_movcond_i64(cond, cpu_ir[rc], c1, z, v1, cpu_ir[rc]); + + tcg_temp_free_i64(z); + if (ra == 31 || mask) { + tcg_temp_free_i64(c1); + } + if (islit) { + tcg_temp_free_i64(v1); + } +} + +static void gen_fcmov(TCGCond cond, int ra, int rb, int rc) +{ + TCGv_i64 c1, z, v1; + + if (unlikely(rc == 31)) { + return; } - l1 = gen_new_label(); - tcg_gen_brcondi_i64(tcg_invert_cond(cond), cmp_tmp, 0, l1); - tcg_temp_free(cmp_tmp); + c1 = tcg_temp_new_i64(); + if (unlikely(ra == 31)) { + tcg_gen_movi_i64(c1, 0); + } else { + gen_fold_mzero(cond, c1, cpu_fir[ra]); + } + if (rb == 31) { + v1 = tcg_const_i64(0); + } else { + v1 = cpu_fir[rb]; + } + z = tcg_const_i64(0); - if (rb != 31) - tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[rb]); - else - tcg_gen_movi_i64(cpu_fir[rc], 0); - gen_set_label(l1); + tcg_gen_movcond_i64(cond, cpu_fir[rc], c1, z, v1, cpu_fir[rc]); + + tcg_temp_free_i64(z); + tcg_temp_free_i64(c1); + if (rb == 31) { + tcg_temp_free_i64(v1); + } } #define QUAL_RM_N 0x080 /* Round mode nearest even */ From d0a16297c97ecf6be259a9a98af7a2dac9230939 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 10:13:36 -0700 Subject: [PATCH 0470/2270] tcg-i386: Implement movcond Signed-off-by: Richard Henderson Reviewed-by: Aurelien Jarno Signed-off-by: Aurelien Jarno --- tcg/i386/tcg-target.c | 29 +++++++++++++++++++++++++++++ tcg/i386/tcg-target.h | 7 ++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 3017858751..aa1fa9ff4c 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -249,6 +249,7 @@ static inline int tcg_target_const_match(tcg_target_long val, #define OPC_ADD_GvEv (OPC_ARITH_GvEv | (ARITH_ADD << 3)) #define OPC_BSWAP (0xc8 | P_EXT) #define OPC_CALL_Jz (0xe8) +#define OPC_CMOVCC (0x40 | P_EXT) /* ... plus condition code */ #define OPC_CMP_GvEv (OPC_ARITH_GvEv | (ARITH_CMP << 3)) #define OPC_DEC_r32 (0x48) #define OPC_IMUL_GvEv (0xaf | P_EXT) @@ -936,6 +937,24 @@ static void tcg_out_setcond2(TCGContext *s, const TCGArg *args, } #endif +static void tcg_out_movcond32(TCGContext *s, TCGCond cond, TCGArg dest, + TCGArg c1, TCGArg c2, int const_c2, + TCGArg v1) +{ + tcg_out_cmp(s, c1, c2, const_c2, 0); + tcg_out_modrm(s, OPC_CMOVCC | tcg_cond_to_jcc[cond], dest, v1); +} + +#if TCG_TARGET_REG_BITS == 64 +static void tcg_out_movcond64(TCGContext *s, TCGCond cond, TCGArg dest, + TCGArg c1, TCGArg c2, int const_c2, + TCGArg v1) +{ + tcg_out_cmp(s, c1, c2, const_c2, P_REXW); + tcg_out_modrm(s, OPC_CMOVCC | tcg_cond_to_jcc[cond] | P_REXW, dest, v1); +} +#endif + static void tcg_out_branch(TCGContext *s, int call, tcg_target_long dest) { tcg_target_long disp = dest - (tcg_target_long)s->code_ptr - 5; @@ -1668,6 +1687,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_setcond32(s, args[3], args[0], args[1], args[2], const_args[2]); break; + case INDEX_op_movcond_i32: + tcg_out_movcond32(s, args[5], args[0], args[1], + args[2], const_args[2], args[3]); + break; OP_32_64(bswap16): tcg_out_rolw_8(s, args[0]); @@ -1796,6 +1819,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_setcond64(s, args[3], args[0], args[1], args[2], const_args[2]); break; + case INDEX_op_movcond_i64: + tcg_out_movcond64(s, args[5], args[0], args[1], + args[2], const_args[2], args[3]); + break; case INDEX_op_bswap64_i64: tcg_out_bswap64(s, args[0]); @@ -1880,6 +1907,7 @@ static const TCGTargetOpDef x86_op_defs[] = { { INDEX_op_setcond_i32, { "q", "r", "ri" } }, { INDEX_op_deposit_i32, { "Q", "0", "Q" } }, + { INDEX_op_movcond_i32, { "r", "r", "ri", "r", "0" } }, #if TCG_TARGET_REG_BITS == 32 { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } }, @@ -1934,6 +1962,7 @@ static const TCGTargetOpDef x86_op_defs[] = { { INDEX_op_ext32u_i64, { "r", "r" } }, { INDEX_op_deposit_i64, { "Q", "0", "Q" } }, + { INDEX_op_movcond_i64, { "r", "r", "re", "r", "0" } }, #endif #if TCG_TARGET_REG_BITS == 64 diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index 504f9534ce..b356d76312 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -86,7 +86,12 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 1 +#if defined(__x86_64__) || defined(__i686__) +/* Use cmov only if the compiler is already doing so. */ +#define TCG_TARGET_HAS_movcond_i32 1 +#else #define TCG_TARGET_HAS_movcond_i32 0 +#endif #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_div2_i64 1 @@ -108,7 +113,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 1 -#define TCG_TARGET_HAS_movcond_i64 0 +#define TCG_TARGET_HAS_movcond_i64 1 #endif #define TCG_TARGET_deposit_i32_valid(ofs, len) \ From fa01a2084e5643504b28ebba2d9dbdb73d2f74a4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 10:13:37 -0700 Subject: [PATCH 0471/2270] tcg: Optimize movcond for constant comparisons Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tcg/optimize.c b/tcg/optimize.c index 9da333c303..26038a695d 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -394,6 +394,14 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, args[3] = tcg_swap_cond(args[3]); } break; + CASE_OP_32_64(movcond): + if (temps[args[1]].state == TCG_TEMP_CONST + && temps[args[2]].state != TCG_TEMP_CONST) { + tmp = args[1]; + args[1] = args[2]; + args[2] = tmp; + args[5] = tcg_swap_cond(args[5]); + } default: break; } @@ -614,6 +622,38 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, } args += 4; break; + CASE_OP_32_64(movcond): + if (temps[args[1]].state == TCG_TEMP_CONST + && temps[args[2]].state == TCG_TEMP_CONST) { + tmp = do_constant_folding_cond(op, temps[args[1]].val, + temps[args[2]].val, args[5]); + if (args[0] == args[4-tmp] + || (temps[args[4-tmp]].state == TCG_TEMP_COPY + && temps[args[4-tmp]].val == args[0])) { + gen_opc_buf[op_index] = INDEX_op_nop; + } else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) { + gen_opc_buf[op_index] = op_to_movi(op); + tcg_opt_gen_movi(gen_args, args[0], temps[args[4-tmp]].val, + nb_temps, nb_globals); + gen_args += 2; + } else { + gen_opc_buf[op_index] = op_to_mov(op); + tcg_opt_gen_mov(gen_args, args[0], args[4-tmp], + nb_temps, nb_globals); + gen_args += 2; + } + } else { + reset_temp(args[0], nb_temps, nb_globals); + gen_args[0] = args[0]; + gen_args[1] = args[1]; + gen_args[2] = args[2]; + gen_args[3] = args[3]; + gen_args[4] = args[4]; + gen_args[5] = args[5]; + gen_args += 6; + } + args += 6; + break; case INDEX_op_call: nb_call_args = (args[0] >> 16) + (args[0] & 0xffff); if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) { From 5d8f53630011f93dc774f1b2dc9557c7eac3ad89 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 10:13:38 -0700 Subject: [PATCH 0472/2270] tcg: Optimize two-address commutative operations While swapping constants to the second operand, swap sources matching destinations to the first operand. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index 26038a695d..1be7631672 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -334,6 +334,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, const TCGOpDef *def; TCGArg *gen_args; TCGArg tmp; + TCGCond cond; + /* Array VALS has an element for each temp. If this temp holds a constant then its value is kept in VALS' element. If this temp is a copy of other ones then this equivalence class' @@ -395,13 +397,24 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, } break; CASE_OP_32_64(movcond): + cond = args[5]; if (temps[args[1]].state == TCG_TEMP_CONST && temps[args[2]].state != TCG_TEMP_CONST) { tmp = args[1]; args[1] = args[2]; args[2] = tmp; - args[5] = tcg_swap_cond(args[5]); + cond = tcg_swap_cond(cond); } + /* For movcond, we canonicalize the "false" input reg to match + the destination reg so that the tcg backend can implement + a "move if true" operation. */ + if (args[0] == args[3]) { + tmp = args[3]; + args[3] = args[4]; + args[4] = tmp; + cond = tcg_invert_cond(cond); + } + args[5] = cond; default: break; } From eca5c303339016c8640567f2e5a31ef1d6487df9 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 16 Sep 2012 13:12:21 +0200 Subject: [PATCH 0473/2270] gdbstub/sh4: fix build with USE_SOFTFLOAT_STRUCT_TYPES We have to use different type to access float values when USE_SOFTFLOAT_STRUCT_TYPES is defined. Rework SH4 version of cpu_gdb_{read,write}_register() using a single case, and fixing the coding style. Use ldll_p() and stfl_p() to access float values. Signed-off-by: Aurelien Jarno --- gdbstub.c | 148 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 92 insertions(+), 56 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index 5d37dd98f4..a91709f271 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -1226,33 +1226,48 @@ static int cpu_gdb_write_register(CPUOpenRISCState *env, static int cpu_gdb_read_register(CPUSH4State *env, uint8_t *mem_buf, int n) { - if (n < 8) { + switch (n) { + case 0 ... 7: if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) { GET_REGL(env->gregs[n + 16]); } else { GET_REGL(env->gregs[n]); } - } else if (n < 16) { + case 8 ... 15: GET_REGL(env->gregs[n]); - } else if (n >= 25 && n < 41) { - GET_REGL(env->fregs[(n - 25) + ((env->fpscr & FPSCR_FR) ? 16 : 0)]); - } else if (n >= 43 && n < 51) { - GET_REGL(env->gregs[n - 43]); - } else if (n >= 51 && n < 59) { - GET_REGL(env->gregs[n - (51 - 16)]); - } - switch (n) { - case 16: GET_REGL(env->pc); - case 17: GET_REGL(env->pr); - case 18: GET_REGL(env->gbr); - case 19: GET_REGL(env->vbr); - case 20: GET_REGL(env->mach); - case 21: GET_REGL(env->macl); - case 22: GET_REGL(env->sr); - case 23: GET_REGL(env->fpul); - case 24: GET_REGL(env->fpscr); - case 41: GET_REGL(env->ssr); - case 42: GET_REGL(env->spc); + case 16: + GET_REGL(env->pc); + case 17: + GET_REGL(env->pr); + case 18: + GET_REGL(env->gbr); + case 19: + GET_REGL(env->vbr); + case 20: + GET_REGL(env->mach); + case 21: + GET_REGL(env->macl); + case 22: + GET_REGL(env->sr); + case 23: + GET_REGL(env->fpul); + case 24: + GET_REGL(env->fpscr); + case 25 ... 40: + if (env->fpscr & FPSCR_FR) { + stfl_p(mem_buf, env->fregs[n - 9]); + } else { + stfl_p(mem_buf, env->fregs[n - 25]); + } + return 4; + case 41: + GET_REGL(env->ssr); + case 42: + GET_REGL(env->spc); + case 43 ... 50: + GET_REGL(env->gregs[n - 43]); + case 51 ... 58: + GET_REGL(env->gregs[n - (51 - 16)]); } return 0; @@ -1260,42 +1275,63 @@ static int cpu_gdb_read_register(CPUSH4State *env, uint8_t *mem_buf, int n) static int cpu_gdb_write_register(CPUSH4State *env, uint8_t *mem_buf, int n) { - uint32_t tmp; - - tmp = ldl_p(mem_buf); - - if (n < 8) { - if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) { - env->gregs[n + 16] = tmp; - } else { - env->gregs[n] = tmp; - } - return 4; - } else if (n < 16) { - env->gregs[n] = tmp; - return 4; - } else if (n >= 25 && n < 41) { - env->fregs[(n - 25) + ((env->fpscr & FPSCR_FR) ? 16 : 0)] = tmp; - return 4; - } else if (n >= 43 && n < 51) { - env->gregs[n - 43] = tmp; - return 4; - } else if (n >= 51 && n < 59) { - env->gregs[n - (51 - 16)] = tmp; - return 4; - } switch (n) { - case 16: env->pc = tmp; break; - case 17: env->pr = tmp; break; - case 18: env->gbr = tmp; break; - case 19: env->vbr = tmp; break; - case 20: env->mach = tmp; break; - case 21: env->macl = tmp; break; - case 22: env->sr = tmp; break; - case 23: env->fpul = tmp; break; - case 24: env->fpscr = tmp; break; - case 41: env->ssr = tmp; break; - case 42: env->spc = tmp; break; + case 0 ... 7: + if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) { + env->gregs[n + 16] = ldl_p(mem_buf); + } else { + env->gregs[n] = ldl_p(mem_buf); + } + break; + case 8 ... 15: + env->gregs[n] = ldl_p(mem_buf); + break; + case 16: + env->pc = ldl_p(mem_buf); + break; + case 17: + env->pr = ldl_p(mem_buf); + break; + case 18: + env->gbr = ldl_p(mem_buf); + break; + case 19: + env->vbr = ldl_p(mem_buf); + break; + case 20: + env->mach = ldl_p(mem_buf); + break; + case 21: + env->macl = ldl_p(mem_buf); + break; + case 22: + env->sr = ldl_p(mem_buf); + break; + case 23: + env->fpul = ldl_p(mem_buf); + break; + case 24: + env->fpscr = ldl_p(mem_buf); + break; + case 25 ... 40: + if (env->fpscr & FPSCR_FR) { + env->fregs[n - 9] = ldfl_p(mem_buf); + } else { + env->fregs[n - 25] = ldfl_p(mem_buf); + } + break; + case 41: + env->ssr = ldl_p(mem_buf); + break; + case 42: + env->spc = ldl_p(mem_buf); + break; + case 43 ... 50: + env->gregs[n - 43] = ldl_p(mem_buf); + break; + case 51 ... 58: + env->gregs[n - (51 - 16)] = ldl_p(mem_buf); + break; default: return 0; } From fe7e1d3ec4410d91a1a687ff4a9288870aefac40 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 17 Sep 2012 08:28:52 -0700 Subject: [PATCH 0474/2270] tcg: Fix !USE_DIRECT_JUMP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 6375e09e changed the type of TranslationBlock.tb_next, but failed to change the type of TCGContext.tb_next. Signed-off-by: Richard Henderson Reviewed-by: Andreas Färber Signed-off-by: Aurelien Jarno --- tcg/tcg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcg/tcg.h b/tcg/tcg.h index 7e903f30f0..48a56f0b15 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -344,7 +344,7 @@ struct TCGContext { /* goto_tb support */ uint8_t *code_buf; - unsigned long *tb_next; + uintptr_t *tb_next; uint16_t *tb_next_offset; uint16_t *tb_jmp_offset; /* != NULL if USE_DIRECT_JUMP */ From c08d9ee38d240ef45496620cbfe8e1b5ed81accb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 18 Sep 2012 19:59:47 -0700 Subject: [PATCH 0475/2270] tcg-hppa: Fix brcond2 and setcond2 Neither of these functions were performing double-word compares properly. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/hppa/tcg-target.c | 53 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c index 8b81b70f17..a76569d967 100644 --- a/tcg/hppa/tcg-target.c +++ b/tcg/hppa/tcg-target.c @@ -820,19 +820,34 @@ static void tcg_out_comclr(TCGContext *s, int cond, TCGArg ret, tcg_out32(s, op); } +static TCGCond const tcg_high_cond[] = { + [TCG_COND_EQ] = TCG_COND_EQ, + [TCG_COND_NE] = TCG_COND_NE, + [TCG_COND_LT] = TCG_COND_LT, + [TCG_COND_LE] = TCG_COND_LT, + [TCG_COND_GT] = TCG_COND_GT, + [TCG_COND_GE] = TCG_COND_GT, + [TCG_COND_LTU] = TCG_COND_LTU, + [TCG_COND_LEU] = TCG_COND_LTU, + [TCG_COND_GTU] = TCG_COND_GTU, + [TCG_COND_GEU] = TCG_COND_GTU +}; + static void tcg_out_brcond2(TCGContext *s, int cond, TCGArg al, TCGArg ah, TCGArg bl, int blconst, TCGArg bh, int bhconst, int label_index) { switch (cond) { case TCG_COND_EQ: - case TCG_COND_NE: - tcg_out_comclr(s, tcg_invert_cond(cond), TCG_REG_R0, al, bl, blconst); - tcg_out_brcond(s, cond, ah, bh, bhconst, label_index); + tcg_out_comclr(s, TCG_COND_NE, TCG_REG_R0, al, bl, blconst); + tcg_out_brcond(s, TCG_COND_EQ, ah, bh, bhconst, label_index); + break; + case TCG_COND_NE: + tcg_out_brcond(s, TCG_COND_NE, al, bl, bhconst, label_index); + tcg_out_brcond(s, TCG_COND_NE, ah, bh, bhconst, label_index); break; - default: - tcg_out_brcond(s, cond, ah, bh, bhconst, label_index); + tcg_out_brcond(s, tcg_high_cond[cond], ah, bh, bhconst, label_index); tcg_out_comclr(s, TCG_COND_NE, TCG_REG_R0, ah, bh, bhconst); tcg_out_brcond(s, tcg_unsigned_cond(cond), al, bl, blconst, label_index); @@ -853,9 +868,8 @@ static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret, { int scratch = TCG_REG_R20; - if (ret != al && ret != ah - && (blconst || ret != bl) - && (bhconst || ret != bh)) { + /* Note that the low parts are fully consumed before scratch is set. */ + if (ret != ah && (bhconst || ret != bh)) { scratch = ret; } @@ -867,13 +881,32 @@ static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret, tcg_out_movi(s, TCG_TYPE_I32, scratch, cond == TCG_COND_NE); break; - default: + case TCG_COND_GE: + case TCG_COND_GEU: + case TCG_COND_LT: + case TCG_COND_LTU: + /* Optimize compares with low part zero. */ + if (bl == 0) { + tcg_out_setcond(s, cond, ret, ah, bh, bhconst); + return; + } + /* FALLTHRU */ + + case TCG_COND_LE: + case TCG_COND_LEU: + case TCG_COND_GT: + case TCG_COND_GTU: + /* <= : ah < bh | (ah == bh && al <= bl) */ tcg_out_setcond(s, tcg_unsigned_cond(cond), scratch, al, bl, blconst); tcg_out_comclr(s, TCG_COND_EQ, TCG_REG_R0, ah, bh, bhconst); tcg_out_movi(s, TCG_TYPE_I32, scratch, 0); - tcg_out_comclr(s, cond, TCG_REG_R0, ah, bh, bhconst); + tcg_out_comclr(s, tcg_invert_cond(tcg_high_cond[cond]), + TCG_REG_R0, ah, bh, bhconst); tcg_out_movi(s, TCG_TYPE_I32, scratch, 1); break; + + default: + tcg_abort(); } tcg_out_mov(s, TCG_TYPE_I32, ret, scratch); From e55f523d7977480462151d8abb0ebb4b1747eabf Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 18 Sep 2012 19:59:48 -0700 Subject: [PATCH 0476/2270] tcg-hppa: Fix broken load/store helpers The CONFIG_TCG_PASS_AREG0 code for calling ld/st helpers was not respecting the ABI requirement for 64-bit values being aligned in registers. Mirror the ARM port in use of helper functions to marshal arguments into the correct registers. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/hppa/tcg-target.c | 134 +++++++++++++++++++++++------------------- 1 file changed, 73 insertions(+), 61 deletions(-) diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c index a76569d967..5385d45cdc 100644 --- a/tcg/hppa/tcg-target.c +++ b/tcg/hppa/tcg-target.c @@ -976,10 +976,11 @@ static int tcg_out_tlb_read(TCGContext *s, int r0, int r1, int addrlo, tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, r1, offset); } - /* Compute the value that ought to appear in the TLB for a hit, namely, the page - of the address. We include the low N bits of the address to catch unaligned - accesses and force them onto the slow path. Do this computation after having - issued the load from the TLB slot to give the load time to complete. */ + /* Compute the value that ought to appear in the TLB for a hit, namely, + the page of the address. We include the low N bits of the address + to catch unaligned accesses and force them onto the slow path. Do + this computation after having issued the load from the TLB slot to + give the load time to complete. */ tcg_out_andi(s, r0, addrlo, TARGET_PAGE_MASK | ((1 << s_bits) - 1)); /* If not equal, jump to lab_miss. */ @@ -992,6 +993,36 @@ static int tcg_out_tlb_read(TCGContext *s, int r0, int r1, int addrlo, return ret; } + +static int tcg_out_arg_reg32(TCGContext *s, int argno, TCGArg v, bool vconst) +{ + if (argno < 4) { + if (vconst) { + tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[argno], v); + } else { + tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[argno], v); + } + } else { + if (vconst && v != 0) { + tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R20, v); + v = TCG_REG_R20; + } + tcg_out_st(s, TCG_TYPE_I32, v, TCG_REG_CALL_STACK, + TCG_TARGET_CALL_STACK_OFFSET - ((argno - 3) * 4)); + } + return argno + 1; +} + +static int tcg_out_arg_reg64(TCGContext *s, int argno, TCGArg vl, TCGArg vh) +{ + /* 64-bit arguments must go in even reg pairs and stack slots. */ + if (argno & 1) { + argno++; + } + argno = tcg_out_arg_reg32(s, argno, vl, false); + argno = tcg_out_arg_reg32(s, argno, vh, false); + return argno; +} #endif static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo_reg, int datahi_reg, @@ -1072,39 +1103,36 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) /* Note that addrhi_reg is only used for 64-bit guests. */ int addrhi_reg = (TARGET_LONG_BITS == 64 ? *args++ : TCG_REG_R0); int mem_index = *args; - int lab1, lab2, argreg, offset; + int lab1, lab2, argno, offset; lab1 = gen_new_label(); lab2 = gen_new_label(); offset = offsetof(CPUArchState, tlb_table[mem_index][0].addr_read); - offset = tcg_out_tlb_read(s, TCG_REG_R26, TCG_REG_R25, addrlo_reg, addrhi_reg, - opc & 3, lab1, offset); + offset = tcg_out_tlb_read(s, TCG_REG_R26, TCG_REG_R25, addrlo_reg, + addrhi_reg, opc & 3, lab1, offset); /* TLB Hit. */ - tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, (offset ? TCG_REG_R1 : TCG_REG_R25), + tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, + (offset ? TCG_REG_R1 : TCG_REG_R25), offsetof(CPUArchState, tlb_table[mem_index][0].addend) - offset); - tcg_out_qemu_ld_direct(s, datalo_reg, datahi_reg, addrlo_reg, TCG_REG_R20, opc); + tcg_out_qemu_ld_direct(s, datalo_reg, datahi_reg, addrlo_reg, + TCG_REG_R20, opc); tcg_out_branch(s, lab2, 1); /* TLB Miss. */ /* label1: */ tcg_out_label(s, lab1, s->code_ptr); - argreg = TCG_REG_R26; - tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrlo_reg); + argno = 0; + argno = tcg_out_arg_reg32(s, argno, TCG_AREG0, false); if (TARGET_LONG_BITS == 64) { - tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrhi_reg); + argno = tcg_out_arg_reg64(s, argno, addrlo_reg, addrhi_reg); + } else { + argno = tcg_out_arg_reg32(s, argno, addrlo_reg, false); } - tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index); + argno = tcg_out_arg_reg32(s, argno, mem_index, true); - /* XXX/FIXME: suboptimal */ - tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], - tcg_target_call_iarg_regs[1]); - tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1], - tcg_target_call_iarg_regs[0]); - tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], - TCG_AREG0); tcg_out_call(s, qemu_ld_helpers[opc & 3]); switch (opc) { @@ -1140,8 +1168,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) #endif } -static void tcg_out_qemu_st_direct(TCGContext *s, int datalo_reg, int datahi_reg, - int addr_reg, int opc) +static void tcg_out_qemu_st_direct(TCGContext *s, int datalo_reg, + int datahi_reg, int addr_reg, int opc) { #ifdef TARGET_WORDS_BIGENDIAN const int bswap = 0; @@ -1194,17 +1222,18 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) /* Note that addrhi_reg is only used for 64-bit guests. */ int addrhi_reg = (TARGET_LONG_BITS == 64 ? *args++ : TCG_REG_R0); int mem_index = *args; - int lab1, lab2, argreg, offset; + int lab1, lab2, argno, next, offset; lab1 = gen_new_label(); lab2 = gen_new_label(); offset = offsetof(CPUArchState, tlb_table[mem_index][0].addr_write); - offset = tcg_out_tlb_read(s, TCG_REG_R26, TCG_REG_R25, addrlo_reg, addrhi_reg, - opc, lab1, offset); + offset = tcg_out_tlb_read(s, TCG_REG_R26, TCG_REG_R25, addrlo_reg, + addrhi_reg, opc, lab1, offset); /* TLB Hit. */ - tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, (offset ? TCG_REG_R1 : TCG_REG_R25), + tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, + (offset ? TCG_REG_R1 : TCG_REG_R25), offsetof(CPUArchState, tlb_table[mem_index][0].addend) - offset); /* There are no indexed stores, so we must do this addition explitly. @@ -1217,63 +1246,46 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) /* label1: */ tcg_out_label(s, lab1, s->code_ptr); - argreg = TCG_REG_R26; - tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrlo_reg); + argno = 0; + argno = tcg_out_arg_reg32(s, argno, TCG_AREG0, false); if (TARGET_LONG_BITS == 64) { - tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrhi_reg); + argno = tcg_out_arg_reg64(s, argno, addrlo_reg, addrhi_reg); + } else { + argno = tcg_out_arg_reg32(s, argno, addrlo_reg, false); } + next = (argno < 4 ? tcg_target_call_iarg_regs[argno] : TCG_REG_R20); switch(opc) { case 0: - tcg_out_andi(s, argreg--, datalo_reg, 0xff); - tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index); + tcg_out_andi(s, next, datalo_reg, 0xff); + argno = tcg_out_arg_reg32(s, argno, next, false); break; case 1: - tcg_out_andi(s, argreg--, datalo_reg, 0xffff); - tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index); + tcg_out_andi(s, next, datalo_reg, 0xffff); + argno = tcg_out_arg_reg32(s, argno, next, false); break; case 2: - tcg_out_mov(s, TCG_TYPE_I32, argreg--, datalo_reg); - tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index); + argno = tcg_out_arg_reg32(s, argno, datalo_reg, false); break; case 3: - /* Because of the alignment required by the 64-bit data argument, - we will always use R23/R24. Also, we will always run out of - argument registers for storing mem_index, so that will have - to go on the stack. */ - if (mem_index == 0) { - argreg = TCG_REG_R0; - } else { - argreg = TCG_REG_R20; - tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index); - } - tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R23, datahi_reg); - tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R24, datalo_reg); - tcg_out_st(s, TCG_TYPE_I32, argreg, TCG_REG_CALL_STACK, - TCG_TARGET_CALL_STACK_OFFSET - 4); + argno = tcg_out_arg_reg64(s, argno, datalo_reg, datahi_reg); break; default: tcg_abort(); } + argno = tcg_out_arg_reg32(s, argno, mem_index, true); - /* XXX/FIXME: suboptimal */ - tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3], - tcg_target_call_iarg_regs[2]); - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], - tcg_target_call_iarg_regs[1]); - tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1], - tcg_target_call_iarg_regs[0]); - tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], - TCG_AREG0); tcg_out_call(s, qemu_st_helpers[opc]); /* label2: */ tcg_out_label(s, lab2, s->code_ptr); #else - /* There are no indexed stores, so if GUEST_BASE is set we must do the add - explicitly. Careful to avoid R20, which is used for the bswaps to follow. */ + /* There are no indexed stores, so if GUEST_BASE is set we must do + the add explicitly. Careful to avoid R20, which is used for the + bswaps to follow. */ if (GUEST_BASE != 0) { - tcg_out_arith(s, TCG_REG_R31, addrlo_reg, TCG_GUEST_BASE_REG, INSN_ADDL); + tcg_out_arith(s, TCG_REG_R31, addrlo_reg, + TCG_GUEST_BASE_REG, INSN_ADDL); addrlo_reg = TCG_REG_R31; } tcg_out_qemu_st_direct(s, datalo_reg, datahi_reg, addrlo_reg, opc); From 62724cc5ebd7fb9113f156cbc0d2bb5e3cb0a9ae Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 24 Mar 2012 21:31:25 +0100 Subject: [PATCH 0477/2270] linux-user: Use memcpy in get_user/put_user. When host and target have differing alignment rules, using a cast and direct memory operation can result in SIGBUS. Use memcpy instead, which the compiler will happily optimize when alignment is satisfied. Signed-off-by: Richard Henderson Reviewed-by: Peter Maydell --- linux-user/qemu.h | 47 +++++++++++++++-------------------------------- 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 69b27d7146..fc4cc00b9f 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -289,46 +289,29 @@ static inline int access_ok(int type, abi_ulong addr, abi_ulong size) * struct has been locked - usually with lock_user_struct(). */ #define __put_user(x, hptr)\ -({\ +({ __typeof(*hptr) pu_ = (x);\ switch(sizeof(*hptr)) {\ - case 1:\ - *(uint8_t *)(hptr) = (uint8_t)(typeof(*hptr))(x);\ - break;\ - case 2:\ - *(uint16_t *)(hptr) = tswap16((uint16_t)(typeof(*hptr))(x));\ - break;\ - case 4:\ - *(uint32_t *)(hptr) = tswap32((uint32_t)(typeof(*hptr))(x));\ - break;\ - case 8:\ - *(uint64_t *)(hptr) = tswap64((typeof(*hptr))(x));\ - break;\ - default:\ - abort();\ + case 1: break;\ + case 2: pu_ = tswap16(pu_); break; \ + case 4: pu_ = tswap32(pu_); break; \ + case 8: pu_ = tswap64(pu_); break; \ + default: abort();\ }\ + memcpy(hptr, &pu_, sizeof(pu_)); \ 0;\ }) #define __get_user(x, hptr) \ -({\ +({ __typeof(*hptr) gu_; \ + memcpy(&gu_, hptr, sizeof(gu_)); \ switch(sizeof(*hptr)) {\ - case 1:\ - x = (typeof(*hptr))*(uint8_t *)(hptr);\ - break;\ - case 2:\ - x = (typeof(*hptr))tswap16(*(uint16_t *)(hptr));\ - break;\ - case 4:\ - x = (typeof(*hptr))tswap32(*(uint32_t *)(hptr));\ - break;\ - case 8:\ - x = (typeof(*hptr))tswap64(*(uint64_t *)(hptr));\ - break;\ - default:\ - /* avoid warning */\ - x = 0;\ - abort();\ + case 1: break; \ + case 2: gu_ = tswap16(gu_); break; \ + case 4: gu_ = tswap32(gu_); break; \ + case 8: gu_ = tswap64(gu_); break; \ + default: abort();\ }\ + (x) = gu_; \ 0;\ }) From 3ee60ad44a3a8673ad38e3da5af05455fed377b8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 24 Mar 2012 21:30:20 +0100 Subject: [PATCH 0478/2270] tcg-sparc: Hack in qemu_ld/st64 for 32-bit. Not actually implemented, but at least we avoid the tcg assert at startup. Signed-off-by: Richard Henderson --- tcg/sparc/tcg-target.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index baed3b49ff..608fc46dc0 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -1556,6 +1556,9 @@ static const TCGTargetOpDef sparc_op_defs[] = { { INDEX_op_brcond_i64, { "r", "rJ" } }, { INDEX_op_setcond_i64, { "r", "r", "rJ" } }, +#else + { INDEX_op_qemu_ld64, { "L", "L", "L" } }, + { INDEX_op_qemu_st64, { "L", "L", "L" } }, #endif { -1 }, }; From a221ae3fcc55fcc3911587bc572af88eed3342dd Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 23 Mar 2012 23:57:12 +0100 Subject: [PATCH 0479/2270] tcg-sparc: Fix ADDX opcode. Signed-off-by: Richard Henderson --- tcg/sparc/tcg-target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 608fc46dc0..0a19313148 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -236,7 +236,7 @@ static inline int tcg_target_const_match(tcg_target_long val, #define ARITH_XOR (INSN_OP(2) | INSN_OP3(0x03)) #define ARITH_SUB (INSN_OP(2) | INSN_OP3(0x04)) #define ARITH_SUBCC (INSN_OP(2) | INSN_OP3(0x14)) -#define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x10)) +#define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x08)) #define ARITH_SUBX (INSN_OP(2) | INSN_OP3(0x0c)) #define ARITH_UMUL (INSN_OP(2) | INSN_OP3(0x0a)) #define ARITH_UDIV (INSN_OP(2) | INSN_OP3(0x0e)) From d5dd696fe3049657c08eb14f40cb74b6e94e79cc Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 10:40:48 -0700 Subject: [PATCH 0480/2270] tcg-sparc: Don't MAP_FIXED on top of the program The address we pick in sparc64.ld is also 0x60000000, so doing a fixed map on top of that is guaranteed to blow up. Choosing 0x40000000 is exactly right for the max of code_gen_buffer_size set below. No need to ever use MAP_FIXED. While getting our desired address helps optimize the generated code, we won't fail if we don't get it. Signed-off-by: Richard Henderson --- exec.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/exec.c b/exec.c index f22e9e6951..4510985f1f 100644 --- a/exec.c +++ b/exec.c @@ -543,8 +543,7 @@ static void code_gen_alloc(unsigned long tb_size) code_gen_buffer_size = (800 * 1024 * 1024); #elif defined(__sparc_v9__) // Map the buffer below 2G, so we can use direct calls and branches - flags |= MAP_FIXED; - start = (void *) 0x60000000UL; + start = (void *) 0x40000000UL; if (code_gen_buffer_size > (512 * 1024 * 1024)) code_gen_buffer_size = (512 * 1024 * 1024); #elif defined(__arm__) @@ -584,8 +583,7 @@ static void code_gen_alloc(unsigned long tb_size) code_gen_buffer_size = (800 * 1024 * 1024); #elif defined(__sparc_v9__) // Map the buffer below 2G, so we can use direct calls and branches - flags |= MAP_FIXED; - addr = (void *) 0x60000000UL; + addr = (void *) 0x40000000UL; if (code_gen_buffer_size > (512 * 1024 * 1024)) { code_gen_buffer_size = (512 * 1024 * 1024); } From 9b9c37c36439ee0452632253dac7a31897f27f70 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 10:34:21 -0700 Subject: [PATCH 0481/2270] tcg-sparc: Assume v9 cpu always, i.e. force v8plus in 32-bit mode. Current code doesn't actually work in 32-bit mode at all. Since no one really noticed, drop the complication of v7 and v8 cpus. Eliminate the --sparc_cpu configure option and standardize macro testing on TCG_TARGET_REG_BITS / HOST_LONG_BITS Signed-off-by: Richard Henderson --- configure | 40 ++++------------------------------------ disas.c | 2 -- exec.c | 6 +++--- qemu-timer.h | 8 +++++--- tcg/sparc/tcg-target.c | 20 +++++--------------- tcg/sparc/tcg-target.h | 7 ++++--- tcg/tcg.c | 3 ++- 7 files changed, 23 insertions(+), 63 deletions(-) diff --git a/configure b/configure index 9caa545abb..df888f2332 100755 --- a/configure +++ b/configure @@ -111,7 +111,6 @@ source_path=`dirname "$0"` cpu="" interp_prefix="/usr/gnemul/qemu-%M" static="no" -sparc_cpu="" cross_prefix="" audio_drv_list="" audio_card_list="ac97 es1370 sb16 hda" @@ -241,21 +240,6 @@ for opt do ;; --disable-debug-info) debug_info="no" ;; - --sparc_cpu=*) - sparc_cpu="$optarg" - case $sparc_cpu in - v7|v8|v8plus|v8plusa) - cpu="sparc" - ;; - v9) - cpu="sparc64" - ;; - *) - echo "undefined SPARC architecture. Exiting"; - exit 1 - ;; - esac - ;; esac done # OS specific @@ -343,8 +327,6 @@ elif check_define __i386__ ; then elif check_define __x86_64__ ; then cpu="x86_64" elif check_define __sparc__ ; then - # We can't check for 64 bit (when gcc is biarch) or V8PLUSA - # They must be specified using --sparc_cpu if check_define __arch64__ ; then cpu="sparc64" else @@ -792,8 +774,6 @@ for opt do ;; --enable-uname-release=*) uname_release="$optarg" ;; - --sparc_cpu=*) - ;; --enable-werror) werror="yes" ;; --disable-werror) werror="no" @@ -881,31 +861,19 @@ for opt do esac done -# -# If cpu ~= sparc and sparc_cpu hasn't been defined, plug in the right -# QEMU_CFLAGS/LDFLAGS (assume sparc_v8plus for 32-bit and sparc_v9 for 64-bit) -# host_guest_base="no" case "$cpu" in - sparc) case $sparc_cpu in - v7|v8) - QEMU_CFLAGS="-mcpu=${sparc_cpu} -D__sparc_${sparc_cpu}__ $QEMU_CFLAGS" - ;; - v8plus|v8plusa) - QEMU_CFLAGS="-mcpu=ultrasparc -D__sparc_${sparc_cpu}__ $QEMU_CFLAGS" - ;; - *) # sparc_cpu not defined in the command line - QEMU_CFLAGS="-mcpu=ultrasparc -D__sparc_v8plus__ $QEMU_CFLAGS" - esac + sparc) LDFLAGS="-m32 $LDFLAGS" - QEMU_CFLAGS="-m32 -ffixed-g2 -ffixed-g3 $QEMU_CFLAGS" + QEMU_CFLAGS="-m32 -mcpu=ultrasparc $QEMU_CFLAGS" + QEMU_CFLAGS="-ffixed-g2 -ffixed-g3 $QEMU_CFLAGS" if test "$solaris" = "no" ; then QEMU_CFLAGS="-ffixed-g1 -ffixed-g6 $QEMU_CFLAGS" fi ;; sparc64) - QEMU_CFLAGS="-m64 -mcpu=ultrasparc -D__sparc_v9__ $QEMU_CFLAGS" LDFLAGS="-m64 $LDFLAGS" + QEMU_CFLAGS="-m64 -mcpu=ultrasparc $QEMU_CFLAGS" QEMU_CFLAGS="-ffixed-g5 -ffixed-g6 -ffixed-g7 $QEMU_CFLAGS" if test "$solaris" != "no" ; then QEMU_CFLAGS="-ffixed-g1 $QEMU_CFLAGS" diff --git a/disas.c b/disas.c index 7b2acc9943..b801c8f51d 100644 --- a/disas.c +++ b/disas.c @@ -316,9 +316,7 @@ void disas(FILE *out, void *code, unsigned long size) print_insn = print_insn_alpha; #elif defined(__sparc__) print_insn = print_insn_sparc; -#if defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__) disasm_info.mach = bfd_mach_sparc_v9b; -#endif #elif defined(__arm__) print_insn = print_insn_arm; #elif defined(__MIPSEB__) diff --git a/exec.c b/exec.c index 4510985f1f..bb6aa4a070 100644 --- a/exec.c +++ b/exec.c @@ -86,7 +86,7 @@ static int nb_tbs; /* any access to the tbs or the page table must use this lock */ spinlock_t tb_lock = SPIN_LOCK_UNLOCKED; -#if defined(__arm__) || defined(__sparc_v9__) +#if defined(__arm__) || defined(__sparc__) /* The prologue must be reachable with a direct jump. ARM and Sparc64 have limited branch ranges (possibly also PPC) so place it in a section close to code segment. */ @@ -541,7 +541,7 @@ static void code_gen_alloc(unsigned long tb_size) /* Cannot map more than that */ if (code_gen_buffer_size > (800 * 1024 * 1024)) code_gen_buffer_size = (800 * 1024 * 1024); -#elif defined(__sparc_v9__) +#elif defined(__sparc__) && HOST_LONG_BITS == 64 // Map the buffer below 2G, so we can use direct calls and branches start = (void *) 0x40000000UL; if (code_gen_buffer_size > (512 * 1024 * 1024)) @@ -581,7 +581,7 @@ static void code_gen_alloc(unsigned long tb_size) /* Cannot map more than that */ if (code_gen_buffer_size > (800 * 1024 * 1024)) code_gen_buffer_size = (800 * 1024 * 1024); -#elif defined(__sparc_v9__) +#elif defined(__sparc__) && HOST_LONG_BITS == 64 // Map the buffer below 2G, so we can use direct calls and branches addr = (void *) 0x40000000UL; if (code_gen_buffer_size > (512 * 1024 * 1024)) { diff --git a/qemu-timer.h b/qemu-timer.h index f8af595f13..da7e97cd5a 100644 --- a/qemu-timer.h +++ b/qemu-timer.h @@ -218,7 +218,7 @@ static inline int64_t cpu_get_real_ticks(void) return val; } -#elif defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__) +#elif defined(__sparc__) static inline int64_t cpu_get_real_ticks (void) { @@ -227,6 +227,8 @@ static inline int64_t cpu_get_real_ticks (void) asm volatile("rd %%tick,%0" : "=r"(rval)); return rval; #else + /* We need an %o or %g register for this. For recent enough gcc + there is an "h" constraint for that. Don't bother with that. */ union { uint64_t i64; struct { @@ -234,8 +236,8 @@ static inline int64_t cpu_get_real_ticks (void) uint32_t low; } i32; } rval; - asm volatile("rd %%tick,%1; srlx %1,32,%0" - : "=r"(rval.i32.high), "=r"(rval.i32.low)); + asm volatile("rd %%tick,%%g1; srlx %%g1,32,%0; mov %%g1,%1" + : "=r"(rval.i32.high), "=r"(rval.i32.low) : : "g1"); return rval.i64; #endif } diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 0a19313148..23c2fda1fa 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -621,18 +621,10 @@ static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGArg ret, default: tcg_out_cmp(s, c1, c2, c2const); -#if defined(__sparc_v9__) || defined(__sparc_v8plus__) tcg_out_movi_imm13(s, ret, 0); - tcg_out32 (s, ARITH_MOVCC | INSN_RD(ret) - | INSN_RS1(tcg_cond_to_bcond[cond]) - | MOVCC_ICC | INSN_IMM11(1)); -#else - t = gen_new_label(); - tcg_out_branch_i32(s, INSN_COND(tcg_cond_to_bcond[cond], 1), t); - tcg_out_movi_imm13(s, ret, 1); - tcg_out_movi_imm13(s, ret, 0); - tcg_out_label(s, t, s->code_ptr); -#endif + tcg_out32(s, ARITH_MOVCC | INSN_RD(ret) + | INSN_RS1(tcg_cond_to_bcond[cond]) + | MOVCC_ICC | INSN_IMM11(1)); return; } @@ -742,7 +734,7 @@ static const void * const qemu_st_helpers[4] = { #endif #endif -#ifdef __arch64__ +#if TCG_TARGET_REG_BITS == 64 #define HOST_LD_OP LDX #define HOST_ST_OP STX #define HOST_SLL_OP SHIFT_SLLX @@ -1600,11 +1592,9 @@ static void tcg_target_init(TCGContext *s) #if TCG_TARGET_REG_BITS == 64 # define ELF_HOST_MACHINE EM_SPARCV9 -#elif defined(__sparc_v8plus__) +#else # define ELF_HOST_MACHINE EM_SPARC32PLUS # define ELF_HOST_FLAGS EF_SPARC_32PLUS -#else -# define ELF_HOST_MACHINE EM_SPARC #endif typedef struct { diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index d76257403d..adca1d2200 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -67,7 +67,8 @@ typedef enum { /* used for function call generation */ #define TCG_REG_CALL_STACK TCG_REG_I6 -#ifdef __arch64__ + +#if TCG_TARGET_REG_BITS == 64 // Reserve space for AREG0 #define TCG_TARGET_STACK_MINFRAME (176 + 4 * (int)sizeof(long) + \ TCG_STATIC_CALL_ARGS_SIZE) @@ -81,7 +82,7 @@ typedef enum { #define TCG_TARGET_STACK_ALIGN 8 #endif -#ifdef __arch64__ +#if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_EXTEND_ARGS 1 #endif @@ -129,7 +130,7 @@ typedef enum { #ifdef CONFIG_SOLARIS #define TCG_AREG0 TCG_REG_G2 -#elif defined(__sparc_v9__) +#elif HOST_LONG_BITS == 64 #define TCG_AREG0 TCG_REG_G5 #else #define TCG_AREG0 TCG_REG_G6 diff --git a/tcg/tcg.c b/tcg/tcg.c index bb9c9952aa..45a26f2c19 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1457,7 +1457,8 @@ static void temp_allocate_frame(TCGContext *s, int temp) { TCGTemp *ts; ts = &s->temps[temp]; -#ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */ +#if !(defined(__sparc__) && TCG_TARGET_REG_BITS == 64) + /* Sparc64 stack is accessed with offset of 2047 */ s->current_frame_offset = (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1); From a0ce341aac61ca3d56bcb56dcfb6ac11272fd567 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 23 Mar 2012 23:27:39 +0100 Subject: [PATCH 0482/2270] tcg-sparc: Fix qemu_ld/st to handle 32-bit host. At the same time, split out the tlb load logic to a new function. Fixes the cases of two data registers and two address registers. Fixes the signature of, and adds missing, qemu_ld/st opcodes. Signed-off-by: Richard Henderson --- tcg/sparc/tcg-target.c | 799 ++++++++++++++++++----------------------- 1 file changed, 359 insertions(+), 440 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 23c2fda1fa..d89c19ba29 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -59,8 +59,6 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { }; #endif -#define ARG_OFFSET 1 - static const int tcg_target_reg_alloc_order[] = { TCG_REG_L0, TCG_REG_L1, @@ -288,6 +286,16 @@ static inline int tcg_target_const_match(tcg_target_long val, #define ASI_PRIMARY_LITTLE 0x88 #endif +#define LDUH_LE (LDUHA | INSN_ASI(ASI_PRIMARY_LITTLE)) +#define LDSH_LE (LDSHA | INSN_ASI(ASI_PRIMARY_LITTLE)) +#define LDUW_LE (LDUWA | INSN_ASI(ASI_PRIMARY_LITTLE)) +#define LDSW_LE (LDSWA | INSN_ASI(ASI_PRIMARY_LITTLE)) +#define LDX_LE (LDXA | INSN_ASI(ASI_PRIMARY_LITTLE)) + +#define STH_LE (STHA | INSN_ASI(ASI_PRIMARY_LITTLE)) +#define STW_LE (STWA | INSN_ASI(ASI_PRIMARY_LITTLE)) +#define STX_LE (STXA | INSN_ASI(ASI_PRIMARY_LITTLE)) + static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2, int op) { @@ -360,64 +368,43 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type, } } -static inline void tcg_out_ld_raw(TCGContext *s, int ret, - tcg_target_long arg) +static inline void tcg_out_ldst_rr(TCGContext *s, int data, int a1, + int a2, int op) { - tcg_out_sethi(s, ret, arg); - tcg_out32(s, LDUW | INSN_RD(ret) | INSN_RS1(ret) | - INSN_IMM13(arg & 0x3ff)); + tcg_out32(s, op | INSN_RD(data) | INSN_RS1(a1) | INSN_RS2(a2)); } -static inline void tcg_out_ld_ptr(TCGContext *s, int ret, - tcg_target_long arg) +static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, + int offset, int op) { - if (!check_fit_tl(arg, 10)) - tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ffULL); - if (TCG_TARGET_REG_BITS == 64) { - tcg_out32(s, LDX | INSN_RD(ret) | INSN_RS1(ret) | - INSN_IMM13(arg & 0x3ff)); - } else { - tcg_out32(s, LDUW | INSN_RD(ret) | INSN_RS1(ret) | - INSN_IMM13(arg & 0x3ff)); - } -} - -static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset, int op) -{ - if (check_fit_tl(offset, 13)) + if (check_fit_tl(offset, 13)) { tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) | INSN_IMM13(offset)); - else { + } else { tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, offset); - tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(TCG_REG_I5) | - INSN_RS2(addr)); + tcg_out_ldst_rr(s, ret, addr, TCG_REG_I5, op); } } -static inline void tcg_out_ldst_asi(TCGContext *s, int ret, int addr, - int offset, int op, int asi) -{ - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, offset); - tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(TCG_REG_I5) | - INSN_ASI(asi) | INSN_RS2(addr)); -} - static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, tcg_target_long arg2) { - if (type == TCG_TYPE_I32) - tcg_out_ldst(s, ret, arg1, arg2, LDUW); - else - tcg_out_ldst(s, ret, arg1, arg2, LDX); + tcg_out_ldst(s, ret, arg1, arg2, (type == TCG_TYPE_I32 ? LDUW : LDX)); } static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, tcg_target_long arg2) { - if (type == TCG_TYPE_I32) - tcg_out_ldst(s, arg, arg1, arg2, STW); - else - tcg_out_ldst(s, arg, arg1, arg2, STX); + tcg_out_ldst(s, arg, arg1, arg2, (type == TCG_TYPE_I32 ? STW : STX)); +} + +static inline void tcg_out_ld_ptr(TCGContext *s, int ret, + tcg_target_long arg) +{ + if (!check_fit_tl(arg, 10)) { + tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ff); + } + tcg_out_ld(s, TCG_TYPE_PTR, ret, ret, arg & 0x3ff); } static inline void tcg_out_sety(TCGContext *s, int rs) @@ -442,14 +429,15 @@ static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) } } -static inline void tcg_out_andi(TCGContext *s, int reg, tcg_target_long val) +static inline void tcg_out_andi(TCGContext *s, int rd, int rs, + tcg_target_long val) { if (val != 0) { if (check_fit_tl(val, 13)) - tcg_out_arithi(s, reg, reg, val, ARITH_AND); + tcg_out_arithi(s, rd, rs, val, ARITH_AND); else { tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_I5, val); - tcg_out_arith(s, reg, reg, TCG_REG_I5, ARITH_AND); + tcg_out_arith(s, rd, rs, TCG_REG_I5, ARITH_AND); } } } @@ -718,418 +706,328 @@ static const void * const qemu_st_helpers[4] = { helper_stl_mmu, helper_stq_mmu, }; -#endif -#if TARGET_LONG_BITS == 32 -#define TARGET_LD_OP LDUW -#else -#define TARGET_LD_OP LDX -#endif +/* Perform the TLB load and compare. -#if defined(CONFIG_SOFTMMU) -#if HOST_LONG_BITS == 32 -#define TARGET_ADDEND_LD_OP LDUW -#else -#define TARGET_ADDEND_LD_OP LDX -#endif -#endif + Inputs: + ADDRLO_IDX contains the index into ARGS of the low part of the + address; the high part of the address is at ADDR_LOW_IDX+1. -#if TCG_TARGET_REG_BITS == 64 -#define HOST_LD_OP LDX -#define HOST_ST_OP STX -#define HOST_SLL_OP SHIFT_SLLX -#define HOST_SRA_OP SHIFT_SRAX -#else -#define HOST_LD_OP LDUW -#define HOST_ST_OP STW -#define HOST_SLL_OP SHIFT_SLL -#define HOST_SRA_OP SHIFT_SRA -#endif + MEM_INDEX and S_BITS are the memory context and log2 size of the load. -static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, - int opc) + WHICH is the offset into the CPUTLBEntry structure of the slot to read. + This should be offsetof addr_read or addr_write. + + The result of the TLB comparison is in %[ix]cc. The sanitized address + is in the returned register, maybe %o0. The TLB addend is in %o1. */ + +static int tcg_out_tlb_load(TCGContext *s, int addrlo_idx, int mem_index, + int s_bits, const TCGArg *args, int which) { - int addr_reg, data_reg, arg0, arg1, arg2, mem_index, s_bits; -#if defined(CONFIG_SOFTMMU) - uint32_t *label1_ptr, *label2_ptr; -#endif + const int addrlo = args[addrlo_idx]; + const int r0 = TCG_REG_O0; + const int r1 = TCG_REG_O1; + const int r2 = TCG_REG_O2; + int addr = addrlo; + int tlb_ofs; - data_reg = *args++; - addr_reg = *args++; - mem_index = *args; - s_bits = opc & 3; + if (TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 64) { + /* Assemble the 64-bit address in R0. */ + tcg_out_arithi(s, r0, addrlo, 0, SHIFT_SRL); + tcg_out_arithi(s, r1, args[addrlo_idx + 1], 32, SHIFT_SLLX); + tcg_out_arith(s, r0, r0, r1, ARITH_OR); + } - arg0 = TCG_REG_O0; - arg1 = TCG_REG_O1; - arg2 = TCG_REG_O2; + /* Shift the page number down to tlb-entry. */ + tcg_out_arithi(s, r1, addrlo, + TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS, SHIFT_SRL); -#if defined(CONFIG_SOFTMMU) - /* srl addr_reg, x, arg1 */ - tcg_out_arithi(s, arg1, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS, - SHIFT_SRL); - /* and addr_reg, x, arg0 */ - tcg_out_arithi(s, arg0, addr_reg, TARGET_PAGE_MASK | ((1 << s_bits) - 1), - ARITH_AND); + /* Mask out the page offset, except for the required alignment. */ + tcg_out_andi(s, r0, addr, TARGET_PAGE_MASK | ((1 << s_bits) - 1)); - /* and arg1, x, arg1 */ - tcg_out_andi(s, arg1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS); + /* Compute tlb index, modulo tlb size. */ + tcg_out_andi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS); - /* add arg1, x, arg1 */ - tcg_out_addi(s, arg1, offsetof(CPUArchState, - tlb_table[mem_index][0].addr_read)); + /* Relative to the current ENV. */ + tcg_out_arith(s, r1, TCG_AREG0, r1, ARITH_ADD); - /* add env, arg1, arg1 */ - tcg_out_arith(s, arg1, TCG_AREG0, arg1, ARITH_ADD); + /* Find a base address that can load both tlb comparator and addend. */ + tlb_ofs = offsetof(CPUArchState, tlb_table[mem_index][0]); + if (!check_fit_tl(tlb_ofs + sizeof(CPUTLBEntry), 13)) { + tcg_out_addi(s, r1, tlb_ofs); + tlb_ofs = 0; + } - /* ld [arg1], arg2 */ - tcg_out32(s, TARGET_LD_OP | INSN_RD(arg2) | INSN_RS1(arg1) | - INSN_RS2(TCG_REG_G0)); + /* Load the tlb comparator and the addend. */ + tcg_out_ld(s, TCG_TYPE_TL, r2, r1, tlb_ofs + which); + tcg_out_ld(s, TCG_TYPE_PTR, r1, r1, tlb_ofs+offsetof(CPUTLBEntry, addend)); /* subcc arg0, arg2, %g0 */ - tcg_out_arith(s, TCG_REG_G0, arg0, arg2, ARITH_SUBCC); + tcg_out_cmp(s, r0, r2, 0); - /* will become: - be label1 - or - be,pt %xcc label1 */ - label1_ptr = (uint32_t *)s->code_ptr; - tcg_out32(s, 0); + /* If the guest address must be zero-extended, do so now. */ + if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) { + tcg_out_arithi(s, r0, addrlo, 0, SHIFT_SRL); + return r0; + } + return addrlo; +} +#endif /* CONFIG_SOFTMMU */ - /* mov (delay slot) */ - tcg_out_mov(s, TCG_TYPE_PTR, arg0, addr_reg); +static const int qemu_ld_opc[8] = { +#ifdef TARGET_WORDS_BIGENDIAN + LDUB, LDUH, LDUW, LDX, LDSB, LDSH, LDSW, LDX +#else + LDUB, LDUH_LE, LDUW_LE, LDX_LE, LDSB, LDSH_LE, LDSW_LE, LDX_LE +#endif +}; - /* mov */ - tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index); - /* XXX/FIXME: suboptimal */ - tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3], - tcg_target_call_iarg_regs[2]); - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], - tcg_target_call_iarg_regs[1]); - tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1], - tcg_target_call_iarg_regs[0]); - tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], - TCG_AREG0); +static const int qemu_st_opc[4] = { +#ifdef TARGET_WORDS_BIGENDIAN + STB, STH, STW, STX +#else + STB, STH_LE, STW_LE, STX_LE +#endif +}; + +static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop) +{ + int addrlo_idx = 1, datalo, datahi, addr_reg; +#if defined(CONFIG_SOFTMMU) + int memi_idx, memi, s_bits, n; + uint32_t *label_ptr[2]; +#endif + + datahi = datalo = args[0]; + if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) { + datahi = args[1]; + addrlo_idx = 2; + } + +#if defined(CONFIG_SOFTMMU) + memi_idx = addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS); + memi = args[memi_idx]; + s_bits = sizeop & 3; + + addr_reg = tcg_out_tlb_load(s, addrlo_idx, memi, s_bits, args, + offsetof(CPUTLBEntry, addr_read)); + + if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) { + int reg64; + + /* bne,pn %[xi]cc, label0 */ + label_ptr[0] = (uint32_t *)s->code_ptr; + tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_NE, 0) | INSN_OP2(0x1) + | ((TARGET_LONG_BITS == 64) << 21))); + + /* TLB Hit. */ + /* Load all 64-bits into an O/G register. */ + reg64 = (datalo < 16 ? datalo : TCG_REG_O0); + tcg_out_ldst_rr(s, reg64, addr_reg, TCG_REG_O1, qemu_ld_opc[sizeop]); + + /* Move the two 32-bit pieces into the destination registers. */ + tcg_out_arithi(s, datahi, reg64, 32, SHIFT_SRLX); + if (reg64 != datalo) { + tcg_out_mov(s, TCG_TYPE_I32, datalo, reg64); + } + + /* b,a,pt label1 */ + label_ptr[1] = (uint32_t *)s->code_ptr; + tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x1) + | (1 << 29) | (1 << 19))); + } else { + /* The fast path is exactly one insn. Thus we can perform the + entire TLB Hit in the (annulled) delay slot of the branch + over the TLB Miss case. */ + + /* beq,a,pt %[xi]cc, label0 */ + label_ptr[0] = NULL; + label_ptr[1] = (uint32_t *)s->code_ptr; + tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1) + | ((TARGET_LONG_BITS == 64) << 21) + | (1 << 29) | (1 << 19))); + /* delay slot */ + tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_O1, qemu_ld_opc[sizeop]); + } + + /* TLB Miss. */ + + if (label_ptr[0]) { + *label_ptr[0] |= INSN_OFF19((unsigned long)s->code_ptr - + (unsigned long)label_ptr[0]); + } + n = 0; + tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[n++], TCG_AREG0); + if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) { + tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], + args[addrlo_idx + 1]); + } + tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], + args[addrlo_idx]); + + /* Store AREG0 in stack to avoid ugly glibc bugs that mangle + global registers */ + tcg_out_st(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK, + TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - + sizeof(long)); - /* XXX: move that code at the end of the TB */ /* qemu_ld_helper[s_bits](arg0, arg1) */ tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_ld_helpers[s_bits] - (tcg_target_ulong)s->code_ptr) >> 2) & 0x3fffffff)); - /* Store AREG0 in stack to avoid ugly glibc bugs that mangle - global registers */ - // delay slot - tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK, - TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - - sizeof(long), HOST_ST_OP); - tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK, - TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - - sizeof(long), HOST_LD_OP); + /* delay slot */ + tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[n], memi); - /* data_reg = sign_extend(arg0) */ - switch(opc) { + /* Reload AREG0. */ + tcg_out_ld(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK, + TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - + sizeof(long)); + + n = tcg_target_call_oarg_regs[0]; + /* datalo = sign_extend(arg0) */ + switch (sizeop) { case 0 | 4: - /* sll arg0, 24/56, data_reg */ - tcg_out_arithi(s, data_reg, arg0, (int)sizeof(tcg_target_long) * 8 - 8, - HOST_SLL_OP); - /* sra data_reg, 24/56, data_reg */ - tcg_out_arithi(s, data_reg, data_reg, - (int)sizeof(tcg_target_long) * 8 - 8, HOST_SRA_OP); + /* Recall that SRA sign extends from bit 31 through bit 63. */ + tcg_out_arithi(s, datalo, n, 24, SHIFT_SLL); + tcg_out_arithi(s, datalo, datalo, 24, SHIFT_SRA); break; case 1 | 4: - /* sll arg0, 16/48, data_reg */ - tcg_out_arithi(s, data_reg, arg0, - (int)sizeof(tcg_target_long) * 8 - 16, HOST_SLL_OP); - /* sra data_reg, 16/48, data_reg */ - tcg_out_arithi(s, data_reg, data_reg, - (int)sizeof(tcg_target_long) * 8 - 16, HOST_SRA_OP); + tcg_out_arithi(s, datalo, n, 16, SHIFT_SLL); + tcg_out_arithi(s, datalo, datalo, 16, SHIFT_SRA); break; case 2 | 4: - /* sll arg0, 32, data_reg */ - tcg_out_arithi(s, data_reg, arg0, 32, HOST_SLL_OP); - /* sra data_reg, 32, data_reg */ - tcg_out_arithi(s, data_reg, data_reg, 32, HOST_SRA_OP); + tcg_out_arithi(s, datalo, n, 0, SHIFT_SRA); break; + case 3: + if (TCG_TARGET_REG_BITS == 32) { + tcg_out_mov(s, TCG_TYPE_REG, datahi, n); + tcg_out_mov(s, TCG_TYPE_REG, datalo, n + 1); + break; + } + /* FALLTHRU */ case 0: case 1: case 2: - case 3: default: /* mov */ - tcg_out_mov(s, TCG_TYPE_REG, data_reg, arg0); + tcg_out_mov(s, TCG_TYPE_REG, datalo, n); break; } - /* will become: - ba label2 */ - label2_ptr = (uint32_t *)s->code_ptr; - tcg_out32(s, 0); - - /* nop (delay slot */ - tcg_out_nop(s); - - /* label1: */ -#if TARGET_LONG_BITS == 32 - /* be label1 */ - *label1_ptr = (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x2) | - INSN_OFF22((unsigned long)s->code_ptr - - (unsigned long)label1_ptr)); + *label_ptr[1] |= INSN_OFF19((unsigned long)s->code_ptr - + (unsigned long)label_ptr[1]); #else - /* be,pt %xcc label1 */ - *label1_ptr = (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1) | - (0x5 << 19) | INSN_OFF19((unsigned long)s->code_ptr - - (unsigned long)label1_ptr)); -#endif - - /* ld [arg1 + x], arg1 */ - tcg_out_ldst(s, arg1, arg1, offsetof(CPUTLBEntry, addend) - - offsetof(CPUTLBEntry, addr_read), TARGET_ADDEND_LD_OP); - -#if TARGET_LONG_BITS == 32 - /* and addr_reg, x, arg0 */ - tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_I5, 0xffffffff); - tcg_out_arith(s, arg0, addr_reg, TCG_REG_I5, ARITH_AND); - /* add arg0, arg1, arg0 */ - tcg_out_arith(s, arg0, arg0, arg1, ARITH_ADD); -#else - /* add addr_reg, arg1, arg0 */ - tcg_out_arith(s, arg0, addr_reg, arg1, ARITH_ADD); -#endif - -#else - arg0 = addr_reg; -#endif - - switch(opc) { - case 0: - /* ldub [arg0], data_reg */ - tcg_out_ldst(s, data_reg, arg0, 0, LDUB); - break; - case 0 | 4: - /* ldsb [arg0], data_reg */ - tcg_out_ldst(s, data_reg, arg0, 0, LDSB); - break; - case 1: -#ifdef TARGET_WORDS_BIGENDIAN - /* lduh [arg0], data_reg */ - tcg_out_ldst(s, data_reg, arg0, 0, LDUH); -#else - /* lduha [arg0] ASI_PRIMARY_LITTLE, data_reg */ - tcg_out_ldst_asi(s, data_reg, arg0, 0, LDUHA, ASI_PRIMARY_LITTLE); -#endif - break; - case 1 | 4: -#ifdef TARGET_WORDS_BIGENDIAN - /* ldsh [arg0], data_reg */ - tcg_out_ldst(s, data_reg, arg0, 0, LDSH); -#else - /* ldsha [arg0] ASI_PRIMARY_LITTLE, data_reg */ - tcg_out_ldst_asi(s, data_reg, arg0, 0, LDSHA, ASI_PRIMARY_LITTLE); -#endif - break; - case 2: -#ifdef TARGET_WORDS_BIGENDIAN - /* lduw [arg0], data_reg */ - tcg_out_ldst(s, data_reg, arg0, 0, LDUW); -#else - /* lduwa [arg0] ASI_PRIMARY_LITTLE, data_reg */ - tcg_out_ldst_asi(s, data_reg, arg0, 0, LDUWA, ASI_PRIMARY_LITTLE); -#endif - break; - case 2 | 4: -#ifdef TARGET_WORDS_BIGENDIAN - /* ldsw [arg0], data_reg */ - tcg_out_ldst(s, data_reg, arg0, 0, LDSW); -#else - /* ldswa [arg0] ASI_PRIMARY_LITTLE, data_reg */ - tcg_out_ldst_asi(s, data_reg, arg0, 0, LDSWA, ASI_PRIMARY_LITTLE); -#endif - break; - case 3: -#ifdef TARGET_WORDS_BIGENDIAN - /* ldx [arg0], data_reg */ - tcg_out_ldst(s, data_reg, arg0, 0, LDX); -#else - /* ldxa [arg0] ASI_PRIMARY_LITTLE, data_reg */ - tcg_out_ldst_asi(s, data_reg, arg0, 0, LDXA, ASI_PRIMARY_LITTLE); -#endif - break; - default: - tcg_abort(); + addr_reg = args[addrlo_idx]; + if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) { + tcg_out_arithi(s, TCG_REG_I5, addr_reg, 0, SHIFT_SRL); + addr_reg = TCG_REG_I5; } + if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) { + int reg64 = (datalo < 16 ? datalo : TCG_REG_O0); -#if defined(CONFIG_SOFTMMU) - /* label2: */ - *label2_ptr = (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2) | - INSN_OFF22((unsigned long)s->code_ptr - - (unsigned long)label2_ptr)); -#endif + tcg_out_ldst_rr(s, reg64, addr_reg, TCG_REG_G0, qemu_ld_opc[sizeop]); + + tcg_out_arithi(s, datahi, reg64, 32, SHIFT_SRLX); + if (reg64 != datalo) { + tcg_out_mov(s, TCG_TYPE_I32, datalo, reg64); + } + } else { + tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_G0, qemu_ld_opc[sizeop]); + } +#endif /* CONFIG_SOFTMMU */ } -static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, - int opc) +static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop) { - int addr_reg, data_reg, arg0, arg1, arg2, mem_index, s_bits; + int addrlo_idx = 1, datalo, datahi, addr_reg; #if defined(CONFIG_SOFTMMU) - uint32_t *label1_ptr, *label2_ptr; + int memi_idx, memi, n; + uint32_t *label_ptr; #endif - data_reg = *args++; - addr_reg = *args++; - mem_index = *args; - - s_bits = opc; - - arg0 = TCG_REG_O0; - arg1 = TCG_REG_O1; - arg2 = TCG_REG_O2; - -#if defined(CONFIG_SOFTMMU) - /* srl addr_reg, x, arg1 */ - tcg_out_arithi(s, arg1, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS, - SHIFT_SRL); - - /* and addr_reg, x, arg0 */ - tcg_out_arithi(s, arg0, addr_reg, TARGET_PAGE_MASK | ((1 << s_bits) - 1), - ARITH_AND); - - /* and arg1, x, arg1 */ - tcg_out_andi(s, arg1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS); - - /* add arg1, x, arg1 */ - tcg_out_addi(s, arg1, offsetof(CPUArchState, - tlb_table[mem_index][0].addr_write)); - - /* add env, arg1, arg1 */ - tcg_out_arith(s, arg1, TCG_AREG0, arg1, ARITH_ADD); - - /* ld [arg1], arg2 */ - tcg_out32(s, TARGET_LD_OP | INSN_RD(arg2) | INSN_RS1(arg1) | - INSN_RS2(TCG_REG_G0)); - - /* subcc arg0, arg2, %g0 */ - tcg_out_arith(s, TCG_REG_G0, arg0, arg2, ARITH_SUBCC); - - /* will become: - be label1 - or - be,pt %xcc label1 */ - label1_ptr = (uint32_t *)s->code_ptr; - tcg_out32(s, 0); - - /* mov (delay slot) */ - tcg_out_mov(s, TCG_TYPE_PTR, arg0, addr_reg); - - /* mov */ - tcg_out_mov(s, TCG_TYPE_REG, arg1, data_reg); - - /* mov */ - tcg_out_movi(s, TCG_TYPE_I32, arg2, mem_index); - - /* XXX/FIXME: suboptimal */ - tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3], - tcg_target_call_iarg_regs[2]); - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], - tcg_target_call_iarg_regs[1]); - tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1], - tcg_target_call_iarg_regs[0]); - tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], - TCG_AREG0); - /* XXX: move that code at the end of the TB */ - /* qemu_st_helper[s_bits](arg0, arg1, arg2) */ - tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[s_bits] - - (tcg_target_ulong)s->code_ptr) >> 2) - & 0x3fffffff)); - /* Store AREG0 in stack to avoid ugly glibc bugs that mangle - global registers */ - // delay slot - tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK, - TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - - sizeof(long), HOST_ST_OP); - tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK, - TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - - sizeof(long), HOST_LD_OP); - - /* will become: - ba label2 */ - label2_ptr = (uint32_t *)s->code_ptr; - tcg_out32(s, 0); - - /* nop (delay slot) */ - tcg_out_nop(s); - -#if TARGET_LONG_BITS == 32 - /* be label1 */ - *label1_ptr = (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x2) | - INSN_OFF22((unsigned long)s->code_ptr - - (unsigned long)label1_ptr)); -#else - /* be,pt %xcc label1 */ - *label1_ptr = (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1) | - (0x5 << 19) | INSN_OFF19((unsigned long)s->code_ptr - - (unsigned long)label1_ptr)); -#endif - - /* ld [arg1 + x], arg1 */ - tcg_out_ldst(s, arg1, arg1, offsetof(CPUTLBEntry, addend) - - offsetof(CPUTLBEntry, addr_write), TARGET_ADDEND_LD_OP); - -#if TARGET_LONG_BITS == 32 - /* and addr_reg, x, arg0 */ - tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_I5, 0xffffffff); - tcg_out_arith(s, arg0, addr_reg, TCG_REG_I5, ARITH_AND); - /* add arg0, arg1, arg0 */ - tcg_out_arith(s, arg0, arg0, arg1, ARITH_ADD); -#else - /* add addr_reg, arg1, arg0 */ - tcg_out_arith(s, arg0, addr_reg, arg1, ARITH_ADD); -#endif - -#else - arg0 = addr_reg; -#endif - - switch(opc) { - case 0: - /* stb data_reg, [arg0] */ - tcg_out_ldst(s, data_reg, arg0, 0, STB); - break; - case 1: -#ifdef TARGET_WORDS_BIGENDIAN - /* sth data_reg, [arg0] */ - tcg_out_ldst(s, data_reg, arg0, 0, STH); -#else - /* stha data_reg, [arg0] ASI_PRIMARY_LITTLE */ - tcg_out_ldst_asi(s, data_reg, arg0, 0, STHA, ASI_PRIMARY_LITTLE); -#endif - break; - case 2: -#ifdef TARGET_WORDS_BIGENDIAN - /* stw data_reg, [arg0] */ - tcg_out_ldst(s, data_reg, arg0, 0, STW); -#else - /* stwa data_reg, [arg0] ASI_PRIMARY_LITTLE */ - tcg_out_ldst_asi(s, data_reg, arg0, 0, STWA, ASI_PRIMARY_LITTLE); -#endif - break; - case 3: -#ifdef TARGET_WORDS_BIGENDIAN - /* stx data_reg, [arg0] */ - tcg_out_ldst(s, data_reg, arg0, 0, STX); -#else - /* stxa data_reg, [arg0] ASI_PRIMARY_LITTLE */ - tcg_out_ldst_asi(s, data_reg, arg0, 0, STXA, ASI_PRIMARY_LITTLE); -#endif - break; - default: - tcg_abort(); + datahi = datalo = args[0]; + if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) { + datahi = args[1]; + addrlo_idx = 2; } #if defined(CONFIG_SOFTMMU) - /* label2: */ - *label2_ptr = (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2) | - INSN_OFF22((unsigned long)s->code_ptr - - (unsigned long)label2_ptr)); -#endif + memi_idx = addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS); + memi = args[memi_idx]; + + addr_reg = tcg_out_tlb_load(s, addrlo_idx, memi, sizeop, args, + offsetof(CPUTLBEntry, addr_write)); + + if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) { + /* Reconstruct the full 64-bit value in %g1, using %o2 as temp. */ + /* ??? Redefine the temps from %i4/%i5 so that we have a o/g temp. */ + tcg_out_arithi(s, TCG_REG_G1, datalo, 0, SHIFT_SRL); + tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX); + tcg_out_arith(s, TCG_REG_G1, TCG_REG_G1, TCG_REG_O2, ARITH_OR); + datalo = TCG_REG_G1; + } + + /* The fast path is exactly one insn. Thus we can perform the entire + TLB Hit in the (annulled) delay slot of the branch over TLB Miss. */ + /* beq,a,pt %[xi]cc, label0 */ + label_ptr = (uint32_t *)s->code_ptr; + tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1) + | ((TARGET_LONG_BITS == 64) << 21) + | (1 << 29) | (1 << 19))); + /* delay slot */ + tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_O1, qemu_st_opc[sizeop]); + + /* TLB Miss. */ + + n = 0; + tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[n++], TCG_AREG0); + if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) { + tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], + args[addrlo_idx + 1]); + } + tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], + args[addrlo_idx]); + if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) { + tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], datahi); + } + tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], datalo); + + /* Store AREG0 in stack to avoid ugly glibc bugs that mangle + global registers */ + tcg_out_st(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK, + TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - + sizeof(long)); + + /* qemu_st_helper[s_bits](arg0, arg1, arg2) */ + tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[sizeop] + - (tcg_target_ulong)s->code_ptr) >> 2) + & 0x3fffffff)); + /* delay slot */ + tcg_out_movi(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n], memi); + + /* Reload AREG0. */ + tcg_out_ld(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK, + TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - + sizeof(long)); + + *label_ptr |= INSN_OFF19((unsigned long)s->code_ptr - + (unsigned long)label_ptr); +#else + addr_reg = args[addrlo_idx]; + if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) { + tcg_out_arithi(s, TCG_REG_I5, addr_reg, 0, SHIFT_SRL); + addr_reg = TCG_REG_I5; + } + if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) { + /* Reconstruct the full 64-bit value in %g1, using %o2 as temp. */ + /* ??? Redefine the temps from %i4/%i5 so that we have a o/g temp. */ + tcg_out_arithi(s, TCG_REG_G1, datalo, 0, SHIFT_SRL); + tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX); + tcg_out_arith(s, TCG_REG_G1, TCG_REG_G1, TCG_REG_O2, ARITH_OR); + datalo = TCG_REG_G1; + } + tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_G0, qemu_st_opc[sizeop]); +#endif /* CONFIG_SOFTMMU */ } static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, @@ -1175,12 +1073,12 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, /* Store AREG0 in stack to avoid ugly glibc bugs that mangle global registers */ // delay slot - tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK, - TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - - sizeof(long), HOST_ST_OP); - tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK, - TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - - sizeof(long), HOST_LD_OP); + tcg_out_st(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK, + TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - + sizeof(long)); + tcg_out_ld(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK, + TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - + sizeof(long)); break; case INDEX_op_jmp: case INDEX_op_br: @@ -1348,6 +1246,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, tcg_out_qemu_ld(s, args, 2 | 4); break; #endif + case INDEX_op_qemu_ld64: + tcg_out_qemu_ld(s, args, 3); + break; case INDEX_op_qemu_st8: tcg_out_qemu_st(s, args, 0); break; @@ -1357,6 +1258,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_qemu_st32: tcg_out_qemu_st(s, args, 2); break; + case INDEX_op_qemu_st64: + tcg_out_qemu_st(s, args, 3); + break; #if TCG_TARGET_REG_BITS == 64 case INDEX_op_movi_i64: @@ -1421,13 +1325,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, args[2], const_args[2]); break; - case INDEX_op_qemu_ld64: - tcg_out_qemu_ld(s, args, 3); - break; - case INDEX_op_qemu_st64: - tcg_out_qemu_st(s, args, 3); - break; - #endif gen_arith: tcg_out_arithc(s, args[0], args[1], args[2], const_args[2], c); @@ -1492,20 +1389,6 @@ static const TCGTargetOpDef sparc_op_defs[] = { { INDEX_op_mulu2_i32, { "r", "r", "r", "rJ" } }, #endif - { INDEX_op_qemu_ld8u, { "r", "L" } }, - { INDEX_op_qemu_ld8s, { "r", "L" } }, - { INDEX_op_qemu_ld16u, { "r", "L" } }, - { INDEX_op_qemu_ld16s, { "r", "L" } }, - { INDEX_op_qemu_ld32, { "r", "L" } }, -#if TCG_TARGET_REG_BITS == 64 - { INDEX_op_qemu_ld32u, { "r", "L" } }, - { INDEX_op_qemu_ld32s, { "r", "L" } }, -#endif - - { INDEX_op_qemu_st8, { "L", "L" } }, - { INDEX_op_qemu_st16, { "L", "L" } }, - { INDEX_op_qemu_st32, { "L", "L" } }, - #if TCG_TARGET_REG_BITS == 64 { INDEX_op_mov_i64, { "r", "r" } }, { INDEX_op_movi_i64, { "r" } }, @@ -1520,8 +1403,6 @@ static const TCGTargetOpDef sparc_op_defs[] = { { INDEX_op_st16_i64, { "r", "r" } }, { INDEX_op_st32_i64, { "r", "r" } }, { INDEX_op_st_i64, { "r", "r" } }, - { INDEX_op_qemu_ld64, { "L", "L" } }, - { INDEX_op_qemu_st64, { "L", "L" } }, { INDEX_op_add_i64, { "r", "r", "rJ" } }, { INDEX_op_mul_i64, { "r", "r", "rJ" } }, @@ -1548,10 +1429,48 @@ static const TCGTargetOpDef sparc_op_defs[] = { { INDEX_op_brcond_i64, { "r", "rJ" } }, { INDEX_op_setcond_i64, { "r", "r", "rJ" } }, -#else - { INDEX_op_qemu_ld64, { "L", "L", "L" } }, - { INDEX_op_qemu_st64, { "L", "L", "L" } }, #endif + +#if TCG_TARGET_REG_BITS == 64 + { INDEX_op_qemu_ld8u, { "r", "L" } }, + { INDEX_op_qemu_ld8s, { "r", "L" } }, + { INDEX_op_qemu_ld16u, { "r", "L" } }, + { INDEX_op_qemu_ld16s, { "r", "L" } }, + { INDEX_op_qemu_ld32, { "r", "L" } }, + { INDEX_op_qemu_ld32u, { "r", "L" } }, + { INDEX_op_qemu_ld32s, { "r", "L" } }, + { INDEX_op_qemu_ld64, { "r", "L" } }, + + { INDEX_op_qemu_st8, { "L", "L" } }, + { INDEX_op_qemu_st16, { "L", "L" } }, + { INDEX_op_qemu_st32, { "L", "L" } }, + { INDEX_op_qemu_st64, { "L", "L" } }, +#elif TARGET_LONG_BITS <= TCG_TARGET_REG_BITS + { INDEX_op_qemu_ld8u, { "r", "L" } }, + { INDEX_op_qemu_ld8s, { "r", "L" } }, + { INDEX_op_qemu_ld16u, { "r", "L" } }, + { INDEX_op_qemu_ld16s, { "r", "L" } }, + { INDEX_op_qemu_ld32, { "r", "L" } }, + { INDEX_op_qemu_ld64, { "r", "r", "L" } }, + + { INDEX_op_qemu_st8, { "L", "L" } }, + { INDEX_op_qemu_st16, { "L", "L" } }, + { INDEX_op_qemu_st32, { "L", "L" } }, + { INDEX_op_qemu_st64, { "L", "L", "L" } }, +#else + { INDEX_op_qemu_ld8u, { "r", "L", "L" } }, + { INDEX_op_qemu_ld8s, { "r", "L", "L" } }, + { INDEX_op_qemu_ld16u, { "r", "L", "L" } }, + { INDEX_op_qemu_ld16s, { "r", "L", "L" } }, + { INDEX_op_qemu_ld32, { "r", "L", "L" } }, + { INDEX_op_qemu_ld64, { "L", "L", "L", "L" } }, + + { INDEX_op_qemu_st8, { "L", "L", "L" } }, + { INDEX_op_qemu_st16, { "L", "L", "L" } }, + { INDEX_op_qemu_st32, { "L", "L", "L" } }, + { INDEX_op_qemu_st64, { "L", "L", "L", "L" } }, +#endif + { -1 }, }; From c6f7e4fb9a0f82bb826f4bd7dff6f2c90d6a83be Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 24 Mar 2012 22:11:25 +0100 Subject: [PATCH 0483/2270] tcg-sparc: Support GUEST_BASE. Signed-off-by: Richard Henderson --- configure | 2 ++ tcg/sparc/tcg-target.c | 26 +++++++++++++++++++++++--- tcg/sparc/tcg-target.h | 2 ++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/configure b/configure index df888f2332..0dc41708f9 100755 --- a/configure +++ b/configure @@ -870,6 +870,7 @@ case "$cpu" in if test "$solaris" = "no" ; then QEMU_CFLAGS="-ffixed-g1 -ffixed-g6 $QEMU_CFLAGS" fi + host_guest_base="yes" ;; sparc64) LDFLAGS="-m64 $LDFLAGS" @@ -878,6 +879,7 @@ case "$cpu" in if test "$solaris" != "no" ; then QEMU_CFLAGS="-ffixed-g1 $QEMU_CFLAGS" fi + host_guest_base="yes" ;; s390) QEMU_CFLAGS="-m31 -march=z990 $QEMU_CFLAGS" diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index d89c19ba29..5acfeba9a2 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -59,6 +59,12 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { }; #endif +#ifdef CONFIG_USE_GUEST_BASE +# define TCG_GUEST_BASE_REG TCG_REG_I3 +#else +# define TCG_GUEST_BASE_REG TCG_REG_G0 +#endif + static const int tcg_target_reg_alloc_order[] = { TCG_REG_L0, TCG_REG_L1, @@ -680,6 +686,14 @@ static void tcg_target_qemu_prologue(TCGContext *s) tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) | INSN_IMM13(-(TCG_TARGET_STACK_MINFRAME + CPU_TEMP_BUF_NLONGS * (int)sizeof(long)))); + +#ifdef CONFIG_USE_GUEST_BASE + if (GUEST_BASE != 0) { + tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE); + tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG); + } +#endif + tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I1) | INSN_RS2(TCG_REG_G0)); tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_I0); @@ -925,14 +939,18 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop) if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) { int reg64 = (datalo < 16 ? datalo : TCG_REG_O0); - tcg_out_ldst_rr(s, reg64, addr_reg, TCG_REG_G0, qemu_ld_opc[sizeop]); + tcg_out_ldst_rr(s, reg64, addr_reg, + (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0), + qemu_ld_opc[sizeop]); tcg_out_arithi(s, datahi, reg64, 32, SHIFT_SRLX); if (reg64 != datalo) { tcg_out_mov(s, TCG_TYPE_I32, datalo, reg64); } } else { - tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_G0, qemu_ld_opc[sizeop]); + tcg_out_ldst_rr(s, datalo, addr_reg, + (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0), + qemu_ld_opc[sizeop]); } #endif /* CONFIG_SOFTMMU */ } @@ -1026,7 +1044,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop) tcg_out_arith(s, TCG_REG_G1, TCG_REG_G1, TCG_REG_O2, ARITH_OR); datalo = TCG_REG_G1; } - tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_G0, qemu_st_opc[sizeop]); + tcg_out_ldst_rr(s, datalo, addr_reg, + (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0), + qemu_st_opc[sizeop]); #endif /* CONFIG_SOFTMMU */ } diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index adca1d2200..99e9f571fa 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -128,6 +128,8 @@ typedef enum { #define TCG_TARGET_HAS_movcond_i64 0 #endif +#define TCG_TARGET_HAS_GUEST_BASE + #ifdef CONFIG_SOLARIS #define TCG_AREG0 TCG_REG_G2 #elif HOST_LONG_BITS == 64 From 0c554161b6fadf75e42d4228e952ff100176ff8a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Mar 2012 19:52:11 +0200 Subject: [PATCH 0484/2270] tcg-sparc: Change AREG0 in generated code to %i0. We can now move the TCG variable from %g[56] to a call-preserved windowed register. Signed-off-by: Richard Henderson --- tcg/sparc/tcg-target.c | 3 ++- tcg/sparc/tcg-target.h | 8 +------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 5acfeba9a2..9ab5746868 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -696,7 +696,8 @@ static void tcg_target_qemu_prologue(TCGContext *s) tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I1) | INSN_RS2(TCG_REG_G0)); - tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_I0); + /* delay slot */ + tcg_out_nop(s); } #if defined(CONFIG_SOFTMMU) diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index 99e9f571fa..ee154d00fa 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -130,13 +130,7 @@ typedef enum { #define TCG_TARGET_HAS_GUEST_BASE -#ifdef CONFIG_SOLARIS -#define TCG_AREG0 TCG_REG_G2 -#elif HOST_LONG_BITS == 64 -#define TCG_AREG0 TCG_REG_G5 -#else -#define TCG_AREG0 TCG_REG_G6 -#endif +#define TCG_AREG0 TCG_REG_I0 static inline void flush_icache_range(tcg_target_ulong start, tcg_target_ulong stop) From 4c3204cb12a966d0d1255eeeaabf30ee4bd34629 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Mar 2012 21:21:46 +0200 Subject: [PATCH 0485/2270] tcg-sparc: Clean up cruft stemming from attempts to use global registers. Don't use -ffixed-gN. Don't link statically. Don't save/restore AREG0 around calls. Don't allocate space on the stack for AREG0 save. Signed-off-by: Richard Henderson --- configure | 12 --------- tcg/sparc/tcg-target.c | 55 +++++++++++++++--------------------------- tcg/sparc/tcg-target.h | 18 ++++++-------- 3 files changed, 26 insertions(+), 59 deletions(-) diff --git a/configure b/configure index 0dc41708f9..1b865174e1 100755 --- a/configure +++ b/configure @@ -866,19 +866,11 @@ case "$cpu" in sparc) LDFLAGS="-m32 $LDFLAGS" QEMU_CFLAGS="-m32 -mcpu=ultrasparc $QEMU_CFLAGS" - QEMU_CFLAGS="-ffixed-g2 -ffixed-g3 $QEMU_CFLAGS" - if test "$solaris" = "no" ; then - QEMU_CFLAGS="-ffixed-g1 -ffixed-g6 $QEMU_CFLAGS" - fi host_guest_base="yes" ;; sparc64) LDFLAGS="-m64 $LDFLAGS" QEMU_CFLAGS="-m64 -mcpu=ultrasparc $QEMU_CFLAGS" - QEMU_CFLAGS="-ffixed-g5 -ffixed-g6 -ffixed-g7 $QEMU_CFLAGS" - if test "$solaris" != "no" ; then - QEMU_CFLAGS="-ffixed-g1 $QEMU_CFLAGS" - fi host_guest_base="yes" ;; s390) @@ -4101,10 +4093,6 @@ fi if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then case "$ARCH" in - sparc) - # -static is used to avoid g1/g3 usage by the dynamic linker - ldflags="$linker_script -static $ldflags" - ;; alpha | s390x) # The default placement of the application is fine. ;; diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 9ab5746868..e625aa3223 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -161,7 +161,6 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0); tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1); tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_O3); break; case 'I': ct->ct |= TCG_CT_CONST_S11; @@ -681,11 +680,22 @@ static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret, /* Generate global QEMU prologue and epilogue code */ static void tcg_target_qemu_prologue(TCGContext *s) { - tcg_set_frame(s, TCG_REG_I6, TCG_TARGET_CALL_STACK_OFFSET, - CPU_TEMP_BUF_NLONGS * (int)sizeof(long)); + int tmp_buf_size, frame_size; + + /* The TCG temp buffer is at the top of the frame, immediately + below the frame pointer. */ + tmp_buf_size = CPU_TEMP_BUF_NLONGS * (int)sizeof(long); + tcg_set_frame(s, TCG_REG_I6, TCG_TARGET_STACK_BIAS - tmp_buf_size, + tmp_buf_size); + + /* TCG_TARGET_CALL_STACK_OFFSET includes the stack bias, but is + otherwise the minimal frame usable by callees. */ + frame_size = TCG_TARGET_CALL_STACK_OFFSET - TCG_TARGET_STACK_BIAS; + frame_size += TCG_STATIC_CALL_ARGS_SIZE + tmp_buf_size; + frame_size += TCG_TARGET_STACK_ALIGN - 1; + frame_size &= -TCG_TARGET_STACK_ALIGN; tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) | - INSN_IMM13(-(TCG_TARGET_STACK_MINFRAME + - CPU_TEMP_BUF_NLONGS * (int)sizeof(long)))); + INSN_IMM13(-frame_size)); #ifdef CONFIG_USE_GUEST_BASE if (GUEST_BASE != 0) { @@ -698,6 +708,8 @@ static void tcg_target_qemu_prologue(TCGContext *s) INSN_RS2(TCG_REG_G0)); /* delay slot */ tcg_out_nop(s); + + /* No epilogue required. We issue ret + restore directly in the TB. */ } #if defined(CONFIG_SOFTMMU) @@ -880,12 +892,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop) tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], args[addrlo_idx]); - /* Store AREG0 in stack to avoid ugly glibc bugs that mangle - global registers */ - tcg_out_st(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK, - TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - - sizeof(long)); - /* qemu_ld_helper[s_bits](arg0, arg1) */ tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_ld_helpers[s_bits] - (tcg_target_ulong)s->code_ptr) >> 2) @@ -893,11 +899,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop) /* delay slot */ tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[n], memi); - /* Reload AREG0. */ - tcg_out_ld(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK, - TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - - sizeof(long)); - n = tcg_target_call_oarg_regs[0]; /* datalo = sign_extend(arg0) */ switch (sizeop) { @@ -1011,12 +1012,6 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop) } tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], datalo); - /* Store AREG0 in stack to avoid ugly glibc bugs that mangle - global registers */ - tcg_out_st(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK, - TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - - sizeof(long)); - /* qemu_st_helper[s_bits](arg0, arg1, arg2) */ tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[sizeop] - (tcg_target_ulong)s->code_ptr) >> 2) @@ -1024,11 +1019,6 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop) /* delay slot */ tcg_out_movi(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n], memi); - /* Reload AREG0. */ - tcg_out_ld(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK, - TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - - sizeof(long)); - *label_ptr |= INSN_OFF19((unsigned long)s->code_ptr - (unsigned long)label_ptr); #else @@ -1091,15 +1081,8 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_I5) | INSN_RS2(TCG_REG_G0)); } - /* Store AREG0 in stack to avoid ugly glibc bugs that mangle - global registers */ - // delay slot - tcg_out_st(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK, - TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - - sizeof(long)); - tcg_out_ld(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK, - TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE - - sizeof(long)); + /* delay slot */ + tcg_out_nop(s); break; case INDEX_op_jmp: case INDEX_op_br: diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index ee154d00fa..6314ffb303 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -66,20 +66,16 @@ typedef enum { #define TCG_CT_CONST_S13 0x200 /* used for function call generation */ -#define TCG_REG_CALL_STACK TCG_REG_I6 +#define TCG_REG_CALL_STACK TCG_REG_O6 #if TCG_TARGET_REG_BITS == 64 -// Reserve space for AREG0 -#define TCG_TARGET_STACK_MINFRAME (176 + 4 * (int)sizeof(long) + \ - TCG_STATIC_CALL_ARGS_SIZE) -#define TCG_TARGET_CALL_STACK_OFFSET (2047 - 16) -#define TCG_TARGET_STACK_ALIGN 16 +#define TCG_TARGET_STACK_BIAS 2047 +#define TCG_TARGET_STACK_ALIGN 16 +#define TCG_TARGET_CALL_STACK_OFFSET (128 + 6*8 + TCG_TARGET_STACK_BIAS) #else -// AREG0 + one word for alignment -#define TCG_TARGET_STACK_MINFRAME (92 + (2 + 1) * (int)sizeof(long) + \ - TCG_STATIC_CALL_ARGS_SIZE) -#define TCG_TARGET_CALL_STACK_OFFSET TCG_TARGET_STACK_MINFRAME -#define TCG_TARGET_STACK_ALIGN 8 +#define TCG_TARGET_STACK_BIAS 0 +#define TCG_TARGET_STACK_ALIGN 8 +#define TCG_TARGET_CALL_STACK_OFFSET (64 + 4 + 6*4) #endif #if TCG_TARGET_REG_BITS == 64 From 1fd959466574c3d46f4898f2e27cd3b1060338e4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Mar 2012 21:36:28 +0200 Subject: [PATCH 0486/2270] tcg-sparc: Mask shift immediates to avoid illegal insns. The xtensa-test image generates a sra_i32 with count 0x40. Whether this is accident of tcg constant propagation or originating directly from the instruction stream is immaterial. Signed-off-by: Richard Henderson --- tcg/sparc/tcg-target.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index e625aa3223..be5c1706d2 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -1154,13 +1154,16 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, goto gen_arith; case INDEX_op_shl_i32: c = SHIFT_SLL; - goto gen_arith; + do_shift32: + /* Limit immediate shift count lest we create an illegal insn. */ + tcg_out_arithc(s, args[0], args[1], args[2] & 31, const_args[2], c); + break; case INDEX_op_shr_i32: c = SHIFT_SRL; - goto gen_arith; + goto do_shift32; case INDEX_op_sar_i32: c = SHIFT_SRA; - goto gen_arith; + goto do_shift32; case INDEX_op_mul_i32: c = ARITH_UMUL; goto gen_arith; @@ -1281,13 +1284,16 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, break; case INDEX_op_shl_i64: c = SHIFT_SLLX; - goto gen_arith; + do_shift64: + /* Limit immediate shift count lest we create an illegal insn. */ + tcg_out_arithc(s, args[0], args[1], args[2] & 63, const_args[2], c); + break; case INDEX_op_shr_i64: c = SHIFT_SRLX; - goto gen_arith; + goto do_shift64; case INDEX_op_sar_i64: c = SHIFT_SRAX; - goto gen_arith; + goto do_shift64; case INDEX_op_mul_i64: c = ARITH_MULX; goto gen_arith; From 375816f84b820e087fab8ff584bd5b8f27811cdb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Mar 2012 22:04:59 +0200 Subject: [PATCH 0487/2270] tcg-sparc: Use defines for temporaries. And change from %i4/%i5 to %g1/%o7 to remove a v8plus fixme. Signed-off-by: Richard Henderson --- tcg/sparc/tcg-target.c | 115 +++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 56 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index be5c1706d2..d401f8ef7c 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -59,8 +59,12 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { }; #endif +/* Define some temporary registers. T2 is used for constant generation. */ +#define TCG_REG_T1 TCG_REG_G1 +#define TCG_REG_T2 TCG_REG_O7 + #ifdef CONFIG_USE_GUEST_BASE -# define TCG_GUEST_BASE_REG TCG_REG_I3 +# define TCG_GUEST_BASE_REG TCG_REG_I5 #else # define TCG_GUEST_BASE_REG TCG_REG_G0 #endif @@ -79,6 +83,7 @@ static const int tcg_target_reg_alloc_order[] = { TCG_REG_I2, TCG_REG_I3, TCG_REG_I4, + TCG_REG_I5, }; static const int tcg_target_call_iarg_regs[6] = { @@ -366,10 +371,10 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type, tcg_out_sethi(s, ret, ~arg); tcg_out_arithi(s, ret, ret, (arg & 0x3ff) | -0x400, ARITH_XOR); } else { - tcg_out_movi_imm32(s, TCG_REG_I4, arg >> (TCG_TARGET_REG_BITS / 2)); - tcg_out_arithi(s, TCG_REG_I4, TCG_REG_I4, 32, SHIFT_SLLX); - tcg_out_movi_imm32(s, ret, arg); - tcg_out_arith(s, ret, ret, TCG_REG_I4, ARITH_OR); + tcg_out_movi_imm32(s, ret, arg >> (TCG_TARGET_REG_BITS / 2)); + tcg_out_arithi(s, ret, ret, 32, SHIFT_SLLX); + tcg_out_movi_imm32(s, TCG_REG_T2, arg); + tcg_out_arith(s, ret, ret, TCG_REG_T2, ARITH_OR); } } @@ -386,8 +391,8 @@ static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) | INSN_IMM13(offset)); } else { - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, offset); - tcg_out_ldst_rr(s, ret, addr, TCG_REG_I5, op); + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, offset); + tcg_out_ldst_rr(s, ret, addr, TCG_REG_T1, op); } } @@ -428,8 +433,8 @@ static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) if (check_fit_tl(val, 13)) tcg_out_arithi(s, reg, reg, val, ARITH_ADD); else { - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, val); - tcg_out_arith(s, reg, reg, TCG_REG_I5, ARITH_ADD); + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, val); + tcg_out_arith(s, reg, reg, TCG_REG_T1, ARITH_ADD); } } } @@ -441,8 +446,8 @@ static inline void tcg_out_andi(TCGContext *s, int rd, int rs, if (check_fit_tl(val, 13)) tcg_out_arithi(s, rd, rs, val, ARITH_AND); else { - tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_I5, val); - tcg_out_arith(s, rd, rs, TCG_REG_I5, ARITH_AND); + tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T1, val); + tcg_out_arith(s, rd, rs, TCG_REG_T1, ARITH_AND); } } } @@ -454,8 +459,8 @@ static void tcg_out_div32(TCGContext *s, int rd, int rs1, if (uns) { tcg_out_sety(s, TCG_REG_G0); } else { - tcg_out_arithi(s, TCG_REG_I5, rs1, 31, SHIFT_SRA); - tcg_out_sety(s, TCG_REG_I5); + tcg_out_arithi(s, TCG_REG_T1, rs1, 31, SHIFT_SRA); + tcg_out_sety(s, TCG_REG_T1); } tcg_out_arithc(s, rd, rs1, val2, val2const, @@ -601,8 +606,8 @@ static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGArg ret, case TCG_COND_GTU: case TCG_COND_GEU: if (c2const && c2 != 0) { - tcg_out_movi_imm13(s, TCG_REG_I5, c2); - c2 = TCG_REG_I5; + tcg_out_movi_imm13(s, TCG_REG_T1, c2); + c2 = TCG_REG_T1; } t = c1, c1 = c2, c2 = t, c2const = 0; cond = tcg_swap_cond(cond); @@ -649,15 +654,15 @@ static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret, switch (cond) { case TCG_COND_EQ: - tcg_out_setcond_i32(s, TCG_COND_EQ, TCG_REG_I5, al, bl, blconst); + tcg_out_setcond_i32(s, TCG_COND_EQ, TCG_REG_T1, al, bl, blconst); tcg_out_setcond_i32(s, TCG_COND_EQ, ret, ah, bh, bhconst); - tcg_out_arith(s, ret, ret, TCG_REG_I5, ARITH_AND); + tcg_out_arith(s, ret, ret, TCG_REG_T1, ARITH_AND); break; case TCG_COND_NE: - tcg_out_setcond_i32(s, TCG_COND_NE, TCG_REG_I5, al, al, blconst); + tcg_out_setcond_i32(s, TCG_COND_NE, TCG_REG_T1, al, al, blconst); tcg_out_setcond_i32(s, TCG_COND_NE, ret, ah, bh, bhconst); - tcg_out_arith(s, ret, ret, TCG_REG_I5, ARITH_OR); + tcg_out_arith(s, ret, ret, TCG_REG_T1, ARITH_OR); break; default: @@ -935,8 +940,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop) #else addr_reg = args[addrlo_idx]; if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) { - tcg_out_arithi(s, TCG_REG_I5, addr_reg, 0, SHIFT_SRL); - addr_reg = TCG_REG_I5; + tcg_out_arithi(s, TCG_REG_T1, addr_reg, 0, SHIFT_SRL); + addr_reg = TCG_REG_T1; } if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) { int reg64 = (datalo < 16 ? datalo : TCG_REG_O0); @@ -979,12 +984,11 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop) offsetof(CPUTLBEntry, addr_write)); if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) { - /* Reconstruct the full 64-bit value in %g1, using %o2 as temp. */ - /* ??? Redefine the temps from %i4/%i5 so that we have a o/g temp. */ - tcg_out_arithi(s, TCG_REG_G1, datalo, 0, SHIFT_SRL); + /* Reconstruct the full 64-bit value. */ + tcg_out_arithi(s, TCG_REG_T1, datalo, 0, SHIFT_SRL); tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX); - tcg_out_arith(s, TCG_REG_G1, TCG_REG_G1, TCG_REG_O2, ARITH_OR); - datalo = TCG_REG_G1; + tcg_out_arith(s, TCG_REG_O2, TCG_REG_T1, TCG_REG_O2, ARITH_OR); + datalo = TCG_REG_O2; } /* The fast path is exactly one insn. Thus we can perform the entire @@ -1024,16 +1028,14 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop) #else addr_reg = args[addrlo_idx]; if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) { - tcg_out_arithi(s, TCG_REG_I5, addr_reg, 0, SHIFT_SRL); - addr_reg = TCG_REG_I5; + tcg_out_arithi(s, TCG_REG_T1, addr_reg, 0, SHIFT_SRL); + addr_reg = TCG_REG_T1; } if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) { - /* Reconstruct the full 64-bit value in %g1, using %o2 as temp. */ - /* ??? Redefine the temps from %i4/%i5 so that we have a o/g temp. */ - tcg_out_arithi(s, TCG_REG_G1, datalo, 0, SHIFT_SRL); + tcg_out_arithi(s, TCG_REG_T1, datalo, 0, SHIFT_SRL); tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX); - tcg_out_arith(s, TCG_REG_G1, TCG_REG_G1, TCG_REG_O2, ARITH_OR); - datalo = TCG_REG_G1; + tcg_out_arith(s, TCG_REG_O2, TCG_REG_T1, TCG_REG_O2, ARITH_OR); + datalo = TCG_REG_O2; } tcg_out_ldst_rr(s, datalo, addr_reg, (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0), @@ -1057,28 +1059,29 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_goto_tb: if (s->tb_jmp_offset) { /* direct jump method */ - tcg_out_sethi(s, TCG_REG_I5, args[0] & 0xffffe000); - tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I5) | + tcg_out_sethi(s, TCG_REG_T1, args[0] & 0xffffe000); + tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_T1) | INSN_IMM13((args[0] & 0x1fff))); s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; } else { /* indirect jump method */ - tcg_out_ld_ptr(s, TCG_REG_I5, (tcg_target_long)(s->tb_next + args[0])); - tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I5) | + tcg_out_ld_ptr(s, TCG_REG_T1, + (tcg_target_long)(s->tb_next + args[0])); + tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_T1) | INSN_RS2(TCG_REG_G0)); } tcg_out_nop(s); s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; break; case INDEX_op_call: - if (const_args[0]) + if (const_args[0]) { tcg_out32(s, CALL | ((((tcg_target_ulong)args[0] - (tcg_target_ulong)s->code_ptr) >> 2) & 0x3fffffff)); - else { - tcg_out_ld_ptr(s, TCG_REG_I5, + } else { + tcg_out_ld_ptr(s, TCG_REG_T1, (tcg_target_long)(s->tb_next + args[0])); - tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_I5) | + tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_T1) | INSN_RS2(TCG_REG_G0)); } /* delay slot */ @@ -1184,11 +1187,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_rem_i32: case INDEX_op_remu_i32: - tcg_out_div32(s, TCG_REG_I5, args[1], args[2], const_args[2], + tcg_out_div32(s, TCG_REG_T1, args[1], args[2], const_args[2], opc == INDEX_op_remu_i32); - tcg_out_arithc(s, TCG_REG_I5, TCG_REG_I5, args[2], const_args[2], + tcg_out_arithc(s, TCG_REG_T1, TCG_REG_T1, args[2], const_args[2], ARITH_UMUL); - tcg_out_arith(s, args[0], args[1], TCG_REG_I5, ARITH_SUB); + tcg_out_arith(s, args[0], args[1], TCG_REG_T1, ARITH_SUB); break; case INDEX_op_brcond_i32: @@ -1305,11 +1308,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, goto gen_arith; case INDEX_op_rem_i64: case INDEX_op_remu_i64: - tcg_out_arithc(s, TCG_REG_I5, args[1], args[2], const_args[2], + tcg_out_arithc(s, TCG_REG_T1, args[1], args[2], const_args[2], opc == INDEX_op_rem_i64 ? ARITH_SDIVX : ARITH_UDIVX); - tcg_out_arithc(s, TCG_REG_I5, TCG_REG_I5, args[2], const_args[2], + tcg_out_arithc(s, TCG_REG_T1, TCG_REG_T1, args[2], const_args[2], ARITH_MULX); - tcg_out_arith(s, args[0], args[1], TCG_REG_I5, ARITH_SUB); + tcg_out_arith(s, args[0], args[1], TCG_REG_T1, ARITH_SUB); break; case INDEX_op_ext32s_i64: if (const_args[1]) { @@ -1507,15 +1510,15 @@ static void tcg_target_init(TCGContext *s) (1 << TCG_REG_O7)); tcg_regset_clear(s->reserved_regs); - tcg_regset_set_reg(s->reserved_regs, TCG_REG_G0); -#if TCG_TARGET_REG_BITS == 64 - tcg_regset_set_reg(s->reserved_regs, TCG_REG_I4); // for internal use -#endif - tcg_regset_set_reg(s->reserved_regs, TCG_REG_I5); // for internal use - tcg_regset_set_reg(s->reserved_regs, TCG_REG_I6); - tcg_regset_set_reg(s->reserved_regs, TCG_REG_I7); - tcg_regset_set_reg(s->reserved_regs, TCG_REG_O6); - tcg_regset_set_reg(s->reserved_regs, TCG_REG_O7); + tcg_regset_set_reg(s->reserved_regs, TCG_REG_G0); /* zero */ + tcg_regset_set_reg(s->reserved_regs, TCG_REG_G6); /* reserved for os */ + tcg_regset_set_reg(s->reserved_regs, TCG_REG_G7); /* thread pointer */ + tcg_regset_set_reg(s->reserved_regs, TCG_REG_I6); /* frame pointer */ + tcg_regset_set_reg(s->reserved_regs, TCG_REG_I7); /* return address */ + tcg_regset_set_reg(s->reserved_regs, TCG_REG_O6); /* stack pointer */ + tcg_regset_set_reg(s->reserved_regs, TCG_REG_T1); /* for internal use */ + tcg_regset_set_reg(s->reserved_regs, TCG_REG_T2); /* for internal use */ + tcg_add_target_add_op_defs(sparc_op_defs); } From 26adfb759c4c6ad42958c365812945316f3468ae Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Mar 2012 22:43:17 +0200 Subject: [PATCH 0488/2270] tcg-sparc: Add %g/%o registers to alloc_order Signed-off-by: Richard Henderson --- tcg/sparc/tcg-target.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index d401f8ef7c..03c385a997 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -78,12 +78,25 @@ static const int tcg_target_reg_alloc_order[] = { TCG_REG_L5, TCG_REG_L6, TCG_REG_L7, + TCG_REG_I0, TCG_REG_I1, TCG_REG_I2, TCG_REG_I3, TCG_REG_I4, TCG_REG_I5, + + TCG_REG_G2, + TCG_REG_G3, + TCG_REG_G4, + TCG_REG_G5, + + TCG_REG_O0, + TCG_REG_O1, + TCG_REG_O2, + TCG_REG_O3, + TCG_REG_O4, + TCG_REG_O5, }; static const int tcg_target_call_iarg_regs[6] = { From 5bbd2cae8e087b4329e17c3f44439096e4c3ec6a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 10:48:51 -0700 Subject: [PATCH 0489/2270] tcg-sparc: Fix and enable direct TB chaining. Signed-off-by: Richard Henderson --- exec-all.h | 9 ++++++--- tcg/sparc/tcg-target.c | 21 ++++++++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/exec-all.h b/exec-all.h index dba96098b8..6516da071d 100644 --- a/exec-all.h +++ b/exec-all.h @@ -132,9 +132,10 @@ static inline void tlb_flush(CPUArchState *env, int flush_global) #define CODE_GEN_AVG_BLOCK_SIZE 64 #endif -#if defined(_ARCH_PPC) || defined(__x86_64__) || defined(__arm__) || defined(__i386__) -#define USE_DIRECT_JUMP -#elif defined(CONFIG_TCG_INTERPRETER) +#if defined(__arm__) || defined(_ARCH_PPC) \ + || defined(__x86_64__) || defined(__i386__) \ + || defined(__sparc__) \ + || defined(CONFIG_TCG_INTERPRETER) #define USE_DIRECT_JUMP #endif @@ -244,6 +245,8 @@ static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr) __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg)); #endif } +#elif defined(__sparc__) +void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr); #else #error tb_set_jmp_target1 is missing #endif diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 03c385a997..1db0c9d4c3 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -1072,10 +1072,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_goto_tb: if (s->tb_jmp_offset) { /* direct jump method */ - tcg_out_sethi(s, TCG_REG_T1, args[0] & 0xffffe000); - tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_T1) | - INSN_IMM13((args[0] & 0x1fff))); + uint32_t old_insn = *(uint32_t *)s->code_ptr; s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; + /* Make sure to preserve links during retranslation. */ + tcg_out32(s, CALL | (old_insn & ~INSN_OP(-1))); } else { /* indirect jump method */ tcg_out_ld_ptr(s, TCG_REG_T1, @@ -1595,3 +1595,18 @@ void tcg_register_jit(void *buf, size_t buf_size) tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); } + +void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr) +{ + uint32_t *ptr = (uint32_t *)jmp_addr; + tcg_target_long disp = (tcg_target_long)(addr - jmp_addr) >> 2; + + /* We can reach the entire address space for 32-bit. For 64-bit + the code_gen_buffer can't be larger than 2GB. */ + if (TCG_TARGET_REG_BITS == 64 && !check_fit_tl(disp, 30)) { + tcg_abort(); + } + + *ptr = CALL | (disp & 0x3fffffff); + flush_icache_range(jmp_addr, jmp_addr + 4); +} From f4bf0b912e780978a37979f7a9fad40f99aa2241 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 11:00:23 -0700 Subject: [PATCH 0490/2270] tcg-sparc: Preserve branch destinations during retranslation Signed-off-by: Richard Henderson --- tcg/sparc/tcg-target.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 1db0c9d4c3..876da4f6b9 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -488,30 +488,33 @@ static inline void tcg_out_nop(TCGContext *s) static void tcg_out_branch_i32(TCGContext *s, int opc, int label_index) { TCGLabel *l = &s->labels[label_index]; + uint32_t off22; if (l->has_value) { - tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) - | INSN_OFF22(l->u.value - (unsigned long)s->code_ptr))); + off22 = INSN_OFF22(l->u.value - (unsigned long)s->code_ptr); } else { + /* Make sure to preserve destinations during retranslation. */ + off22 = *(uint32_t *)s->code_ptr & INSN_OFF22(-1); tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP22, label_index, 0); - tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) | 0)); } + tcg_out32(s, INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) | off22); } #if TCG_TARGET_REG_BITS == 64 static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index) { TCGLabel *l = &s->labels[label_index]; + uint32_t off19; if (l->has_value) { - tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) | - (0x5 << 19) | - INSN_OFF19(l->u.value - (unsigned long)s->code_ptr))); + off19 = INSN_OFF19(l->u.value - (unsigned long)s->code_ptr); } else { + /* Make sure to preserve destinations during retranslation. */ + off19 = *(uint32_t *)s->code_ptr & INSN_OFF19(-1); tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, label_index, 0); - tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) | - (0x5 << 19) | 0)); } + tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) | + (0x5 << 19) | off19)); } #endif From 2ceb3a9e0f2110c7d96134f2db7593609ed50bc2 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 21 Sep 2012 18:20:25 +0200 Subject: [PATCH 0491/2270] tcg-mips: fix wrong usage of 'Z' constraint The 'Z' constraint has been introduced to map the zero register. However when the op also accept a constant, there is no point to accept the zero register in addition. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/mips/tcg-target.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index 74db83d440..9293745525 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -1453,24 +1453,24 @@ static const TCGTargetOpDef mips_op_defs[] = { { INDEX_op_st16_i32, { "rZ", "r" } }, { INDEX_op_st_i32, { "rZ", "r" } }, - { INDEX_op_add_i32, { "r", "rZ", "rJZ" } }, + { INDEX_op_add_i32, { "r", "rZ", "rJ" } }, { INDEX_op_mul_i32, { "r", "rZ", "rZ" } }, { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } }, { INDEX_op_div_i32, { "r", "rZ", "rZ" } }, { INDEX_op_divu_i32, { "r", "rZ", "rZ" } }, { INDEX_op_rem_i32, { "r", "rZ", "rZ" } }, { INDEX_op_remu_i32, { "r", "rZ", "rZ" } }, - { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } }, + { INDEX_op_sub_i32, { "r", "rZ", "rJ" } }, - { INDEX_op_and_i32, { "r", "rZ", "rIZ" } }, + { INDEX_op_and_i32, { "r", "rZ", "rI" } }, { INDEX_op_nor_i32, { "r", "rZ", "rZ" } }, { INDEX_op_not_i32, { "r", "rZ" } }, { INDEX_op_or_i32, { "r", "rZ", "rIZ" } }, { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } }, - { INDEX_op_shl_i32, { "r", "rZ", "riZ" } }, - { INDEX_op_shr_i32, { "r", "rZ", "riZ" } }, - { INDEX_op_sar_i32, { "r", "rZ", "riZ" } }, + { INDEX_op_shl_i32, { "r", "rZ", "ri" } }, + { INDEX_op_shr_i32, { "r", "rZ", "ri" } }, + { INDEX_op_sar_i32, { "r", "rZ", "ri" } }, { INDEX_op_ext8s_i32, { "r", "rZ" } }, { INDEX_op_ext16s_i32, { "r", "rZ" } }, @@ -1479,8 +1479,8 @@ static const TCGTargetOpDef mips_op_defs[] = { { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } }, { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } }, - { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } }, - { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } }, + { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } }, + { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } }, { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } }, #if TARGET_LONG_BITS == 32 From 0834c9eac31d6a6780594be17c7b3a3d6403ac16 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 21 Sep 2012 18:20:25 +0200 Subject: [PATCH 0492/2270] tcg/mips: kill warnings in user mode Recent versions of GCC emit warnings when compiling user mode targets. Kill them by reordering a bit the #ifdef. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/mips/tcg-target.c | 86 ++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index 9293745525..a09c0d6ca8 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -842,18 +842,16 @@ static const void * const qemu_st_helpers[4] = { static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) { - int addr_regl, addr_meml; - int data_regl, data_regh, data_reg1, data_reg2; - int mem_index, s_bits; + int addr_regl, data_regl, data_regh, data_reg1, data_reg2; #if defined(CONFIG_SOFTMMU) void *label1_ptr, *label2_ptr; int arg_num; -#endif -#if TARGET_LONG_BITS == 64 -# if defined(CONFIG_SOFTMMU) + int mem_index, s_bits; + int addr_meml; +# if TARGET_LONG_BITS == 64 uint8_t *label3_ptr; -# endif int addr_regh, addr_memh; +# endif #endif data_regl = *args++; if (opc == 3) @@ -861,11 +859,22 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, else data_regh = 0; addr_regl = *args++; -#if TARGET_LONG_BITS == 64 +#if defined(CONFIG_SOFTMMU) +# if TARGET_LONG_BITS == 64 addr_regh = *args++; -#endif +# if defined(TCG_TARGET_WORDS_BIGENDIAN) + addr_memh = 0; + addr_meml = 4; +# else + addr_memh = 4; + addr_meml = 0; +# endif +# else + addr_meml = 0; +# endif mem_index = *args; s_bits = opc & 3; +#endif if (opc == 3) { #if defined(TCG_TARGET_WORDS_BIGENDIAN) @@ -879,18 +888,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, data_reg1 = data_regl; data_reg2 = 0; } -#if TARGET_LONG_BITS == 64 -# if defined(TCG_TARGET_WORDS_BIGENDIAN) - addr_memh = 0; - addr_meml = 4; -# else - addr_memh = 4; - addr_meml = 0; -# endif -#else - addr_meml = 0; -#endif - #if defined(CONFIG_SOFTMMU) tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS); @@ -1029,23 +1026,44 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) { - int addr_regl, addr_meml; - int data_regl, data_regh, data_reg1, data_reg2; - int mem_index, s_bits; + int addr_regl, data_regl, data_regh, data_reg1, data_reg2; #if defined(CONFIG_SOFTMMU) uint8_t *label1_ptr, *label2_ptr; int arg_num; + int mem_index, s_bits; + int addr_meml; #endif #if TARGET_LONG_BITS == 64 # if defined(CONFIG_SOFTMMU) uint8_t *label3_ptr; -# endif int addr_regh, addr_memh; +# endif #endif - data_regl = *args++; if (opc == 3) { data_regh = *args++; + } else { + data_regh = 0; + } + addr_regl = *args++; +#if defined(CONFIG_SOFTMMU) +# if TARGET_LONG_BITS == 64 + addr_regh = *args++; +# if defined(TCG_TARGET_WORDS_BIGENDIAN) + addr_memh = 0; + addr_meml = 4; +# else + addr_memh = 4; + addr_meml = 0; +# endif +# else + addr_meml = 0; +# endif + mem_index = *args; + s_bits = opc; +#endif + + if (opc == 3) { #if defined(TCG_TARGET_WORDS_BIGENDIAN) data_reg1 = data_regh; data_reg2 = data_regl; @@ -1056,23 +1074,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, } else { data_reg1 = data_regl; data_reg2 = 0; - data_regh = 0; } - addr_regl = *args++; -#if TARGET_LONG_BITS == 64 - addr_regh = *args++; -# if defined(TCG_TARGET_WORDS_BIGENDIAN) - addr_memh = 0; - addr_meml = 4; -# else - addr_memh = 4; - addr_meml = 0; -# endif -#else - addr_meml = 0; -#endif - mem_index = *args; - s_bits = opc; #if defined(CONFIG_SOFTMMU) tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); From 5a0eed379ddff07f1c136c7acedd380b60eecd28 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 21 Sep 2012 18:20:26 +0200 Subject: [PATCH 0493/2270] tcg/mips: use TCGArg or TCGReg instead of int Instead of int, use the correct TCGArg and TCGReg type: TCGReg when representing a TCG target register, TCGArg when representing the latter or a constant. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/mips/tcg-target.c | 63 ++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index a09c0d6ca8..8b38f988d8 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -68,7 +68,7 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { #endif /* check if we really need so many registers :P */ -static const int tcg_target_reg_alloc_order[] = { +static const TCGReg tcg_target_reg_alloc_order[] = { TCG_REG_S0, TCG_REG_S1, TCG_REG_S2, @@ -94,14 +94,14 @@ static const int tcg_target_reg_alloc_order[] = { TCG_REG_V1 }; -static const int tcg_target_call_iarg_regs[4] = { +static const TCGReg tcg_target_call_iarg_regs[4] = { TCG_REG_A0, TCG_REG_A1, TCG_REG_A2, TCG_REG_A3 }; -static const int tcg_target_call_oarg_regs[2] = { +static const TCGReg tcg_target_call_oarg_regs[2] = { TCG_REG_V0, TCG_REG_V1 }; @@ -327,7 +327,8 @@ enum { /* * Type reg */ -static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int rt) +static inline void tcg_out_opc_reg(TCGContext *s, int opc, + TCGReg rd, TCGReg rs, TCGReg rt) { int32_t inst; @@ -341,7 +342,8 @@ static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int r /* * Type immediate */ -static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int imm) +static inline void tcg_out_opc_imm(TCGContext *s, int opc, + TCGReg rt, TCGReg rs, TCGArg imm) { int32_t inst; @@ -355,7 +357,8 @@ static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int i /* * Type branch */ -static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs) +static inline void tcg_out_opc_br(TCGContext *s, int opc, + TCGReg rt, TCGReg rs) { /* We pay attention here to not modify the branch target by reading the existing value and using it again. This ensure that caches and @@ -368,7 +371,8 @@ static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs) /* * Type sa */ -static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa) +static inline void tcg_out_opc_sa(TCGContext *s, int opc, + TCGReg rd, TCGReg rt, TCGArg sa) { int32_t inst; @@ -407,7 +411,7 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type, } } -static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg) +static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg) { /* ret and arg can't be register at */ if (ret == TCG_REG_AT || arg == TCG_REG_AT) { @@ -422,7 +426,7 @@ static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg) tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); } -static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg) +static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg) { /* ret and arg can't be register at */ if (ret == TCG_REG_AT || arg == TCG_REG_AT) { @@ -437,7 +441,7 @@ static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg) tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); } -static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg) +static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg) { /* ret and arg must be different and can't be register at */ if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) { @@ -458,7 +462,7 @@ static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg) tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); } -static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg) +static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg) { #ifdef _MIPS_ARCH_MIPS32R2 tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg); @@ -468,7 +472,7 @@ static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg) #endif } -static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg) +static inline void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg) { #ifdef _MIPS_ARCH_MIPS32R2 tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg); @@ -478,8 +482,8 @@ static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg) #endif } -static inline void tcg_out_ldst(TCGContext *s, int opc, int arg, - int arg1, tcg_target_long arg2) +static inline void tcg_out_ldst(TCGContext *s, int opc, TCGArg arg, + TCGReg arg1, TCGArg arg2) { if (arg2 == (int16_t) arg2) { tcg_out_opc_imm(s, opc, arg, arg1, arg2); @@ -502,7 +506,7 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, tcg_out_ldst(s, OPC_SW, arg, arg1, arg2); } -static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) +static inline void tcg_out_addi(TCGContext *s, TCGReg reg, TCGArg val) { if (val == (int16_t)val) { tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val); @@ -543,7 +547,7 @@ DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_reg16, TCGReg arg) #undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG #define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \ tcg_out_movi(s, TCG_TYPE_I32, A, arg); -DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_imm32, uint32_t arg) +DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_imm32, TCGArg arg) #undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG /* We don't use the macro for this one to avoid an unnecessary reg-reg @@ -573,8 +577,8 @@ static inline void tcg_out_call_iarg_reg64(TCGContext *s, int *arg_num, #endif } -static void tcg_out_brcond(TCGContext *s, TCGCond cond, int arg1, - int arg2, int label_index) +static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGArg arg1, + TCGArg arg2, int label_index) { TCGLabel *l = &s->labels[label_index]; @@ -631,8 +635,9 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, int arg1, /* XXX: we implement it at the target level to avoid having to handle cross basic blocks temporaries */ -static void tcg_out_brcond2(TCGContext *s, TCGCond cond, int arg1, - int arg2, int arg3, int arg4, int label_index) +static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGArg arg1, + TCGArg arg2, TCGArg arg3, TCGArg arg4, + int label_index) { void *label_ptr; @@ -694,8 +699,8 @@ static void tcg_out_brcond2(TCGContext *s, TCGCond cond, int arg1, reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr); } -static void tcg_out_setcond(TCGContext *s, TCGCond cond, int ret, - int arg1, int arg2) +static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, + TCGArg arg1, TCGArg arg2) { switch (cond) { case TCG_COND_EQ: @@ -754,8 +759,8 @@ static void tcg_out_setcond(TCGContext *s, TCGCond cond, int ret, /* XXX: we implement it at the target level to avoid having to handle cross basic blocks temporaries */ -static void tcg_out_setcond2(TCGContext *s, TCGCond cond, int ret, - int arg1, int arg2, int arg3, int arg4) +static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret, + TCGArg arg1, TCGArg arg2, TCGArg arg3, TCGArg arg4) { switch (cond) { case TCG_COND_EQ: @@ -842,7 +847,7 @@ static const void * const qemu_st_helpers[4] = { static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) { - int addr_regl, data_regl, data_regh, data_reg1, data_reg2; + TCGReg addr_regl, data_regl, data_regh, data_reg1, data_reg2; #if defined(CONFIG_SOFTMMU) void *label1_ptr, *label2_ptr; int arg_num; @@ -850,7 +855,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int addr_meml; # if TARGET_LONG_BITS == 64 uint8_t *label3_ptr; - int addr_regh, addr_memh; + TCGReg addr_regh; + int addr_memh; # endif #endif data_regl = *args++; @@ -1026,7 +1032,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) { - int addr_regl, data_regl, data_regh, data_reg1, data_reg2; + TCGReg addr_regl, data_regl, data_regh, data_reg1, data_reg2; #if defined(CONFIG_SOFTMMU) uint8_t *label1_ptr, *label2_ptr; int arg_num; @@ -1036,7 +1042,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, #if TARGET_LONG_BITS == 64 # if defined(CONFIG_SOFTMMU) uint8_t *label3_ptr; - int addr_regh, addr_memh; + TCGReg addr_regh; + int addr_memh; # endif #endif data_regl = *args++; From 3314e0089f1bae4b0430f9bf3299c3b16d6ea32b Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 21 Sep 2012 18:20:26 +0200 Subject: [PATCH 0494/2270] tcg/mips: don't use global pointer Don't use the global pointer in TCG, in case helpers try access global variables. Signed-off-by: Aurelien Jarno --- tcg/mips/tcg-target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index 8b38f988d8..0ea6a76fb7 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -1529,7 +1529,6 @@ static int tcg_target_callee_save_regs[] = { TCG_REG_S5, TCG_REG_S6, TCG_REG_S7, - TCG_REG_GP, TCG_REG_FP, TCG_REG_RA, /* should be last for ABI compliance */ }; @@ -1595,6 +1594,7 @@ static void tcg_target_init(TCGContext *s) tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0); /* internal use */ tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */ tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */ + tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */ tcg_add_target_add_op_defs(mips_op_defs); tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf), From 0d0b53a6708d0ae3ea37828ec6a967d55827ed6d Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 21 Sep 2012 18:20:26 +0200 Subject: [PATCH 0495/2270] tcg/mips: use stack for TCG temps Use stack instead of temp_buf array in CPUState for TCG temps. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/mips/tcg-target.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index 0ea6a76fb7..c05169f88f 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -1538,11 +1538,15 @@ static void tcg_target_qemu_prologue(TCGContext *s) { int i, frame_size; - /* reserve some stack space */ + /* reserve some stack space, also for TCG temps. */ frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4 - + TCG_STATIC_CALL_ARGS_SIZE; + + TCG_STATIC_CALL_ARGS_SIZE + + CPU_TEMP_BUF_NLONGS * sizeof(long); frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & ~(TCG_TARGET_STACK_ALIGN - 1); + tcg_set_frame(s, TCG_REG_SP, ARRAY_SIZE(tcg_target_callee_save_regs) * 4 + + TCG_STATIC_CALL_ARGS_SIZE, + CPU_TEMP_BUF_NLONGS * sizeof(long)); /* TB prologue */ tcg_out_addi(s, TCG_REG_SP, -frame_size); @@ -1597,6 +1601,4 @@ static void tcg_target_init(TCGContext *s) tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */ tcg_add_target_add_op_defs(mips_op_defs); - tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf), - CPU_TEMP_BUF_NLONGS * sizeof(long)); } From 0f46c064eebc9c93b8f925416e0812cc7b4bb503 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 21 Sep 2012 18:20:26 +0200 Subject: [PATCH 0496/2270] tcg/mips: optimize brcond arg, 0 MIPS has some conditional branch instructions when comparing with zero. Use them. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/mips/tcg-target.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index c05169f88f..6aa4527257 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -278,6 +278,8 @@ static inline int tcg_target_const_match(tcg_target_long val, enum { OPC_BEQ = 0x04 << 26, OPC_BNE = 0x05 << 26, + OPC_BLEZ = 0x06 << 26, + OPC_BGTZ = 0x07 << 26, OPC_ADDIU = 0x09 << 26, OPC_SLTI = 0x0A << 26, OPC_SLTIU = 0x0B << 26, @@ -319,6 +321,10 @@ enum { OPC_SLT = OPC_SPECIAL | 0x2A, OPC_SLTU = OPC_SPECIAL | 0x2B, + OPC_REGIMM = 0x01 << 26, + OPC_BLTZ = OPC_REGIMM | (0x00 << 16), + OPC_BGEZ = OPC_REGIMM | (0x01 << 16), + OPC_SPECIAL3 = 0x1f << 26, OPC_SEB = OPC_SPECIAL3 | 0x420, OPC_SEH = OPC_SPECIAL3 | 0x620, @@ -590,32 +596,48 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGArg arg1, tcg_out_opc_br(s, OPC_BNE, arg1, arg2); break; case TCG_COND_LT: - tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2); - tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO); + if (arg2 == 0) { + tcg_out_opc_br(s, OPC_BLTZ, 0, arg1); + } else { + tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2); + tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO); + } break; case TCG_COND_LTU: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2); tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO); break; case TCG_COND_GE: - tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2); - tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO); + if (arg2 == 0) { + tcg_out_opc_br(s, OPC_BGEZ, 0, arg1); + } else { + tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2); + tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO); + } break; case TCG_COND_GEU: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2); tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO); break; case TCG_COND_LE: - tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1); - tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO); + if (arg2 == 0) { + tcg_out_opc_br(s, OPC_BLEZ, 0, arg1); + } else { + tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1); + tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO); + } break; case TCG_COND_LEU: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1); tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO); break; case TCG_COND_GT: - tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1); - tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO); + if (arg2 == 0) { + tcg_out_opc_br(s, OPC_BGTZ, 0, arg1); + } else { + tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1); + tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO); + } break; case TCG_COND_GTU: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1); From c1cf85c9acb847c4871c0b241ced8fabf410d502 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 21 Sep 2012 18:20:26 +0200 Subject: [PATCH 0497/2270] tcg/mips: optimize bswap{16,16s,32} on MIPS32R2 bswap operations can be optimized on MIPS32 Release 2 using the ROTR, WSBH and SEH instructions. We can't use the non-R2 code to implement the ops due to registers constraints, so don't define the corresponding TCG_TARGET_HAS_bswap* values. Also bswap16* operations are supposed to be called with the 16 high bits zeroed. This is the case everywhere (including for TCG by definition) except when called from the store helper. Remove the AND instructions from bswap16* and move it there. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/mips/tcg-target.c | 34 +++++++++++++++++++++++++++++----- tcg/mips/tcg-target.h | 11 +++++++++-- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index 6aa4527257..8b2f9fc7d6 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -326,6 +326,7 @@ enum { OPC_BGEZ = OPC_REGIMM | (0x01 << 16), OPC_SPECIAL3 = 0x1f << 26, + OPC_WSBH = OPC_SPECIAL3 | 0x0a0, OPC_SEB = OPC_SPECIAL3 | 0x420, OPC_SEH = OPC_SPECIAL3 | 0x620, }; @@ -419,36 +420,45 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type, static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg) { +#ifdef _MIPS_ARCH_MIPS32R2 + tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg); +#else /* ret and arg can't be register at */ if (ret == TCG_REG_AT || arg == TCG_REG_AT) { tcg_abort(); } tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8); - tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff); - tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8); tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00); tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); +#endif } static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg) { +#ifdef _MIPS_ARCH_MIPS32R2 + tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg); + tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret); +#else /* ret and arg can't be register at */ if (ret == TCG_REG_AT || arg == TCG_REG_AT) { tcg_abort(); } tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8); - tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff); - tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24); tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16); tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); +#endif } static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg) { +#ifdef _MIPS_ARCH_MIPS32R2 + tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg); + tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16); +#else /* ret and arg must be different and can't be register at */ if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) { tcg_abort(); @@ -466,6 +476,7 @@ static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg) tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8); tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00); tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); +#endif } static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg) @@ -1188,7 +1199,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, break; case 1: if (TCG_NEED_BSWAP) { - tcg_out_bswap16(s, TCG_REG_T0, data_reg1); + tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_T0, data_reg1, 0xffff); + tcg_out_bswap16(s, TCG_REG_T0, TCG_REG_T0); tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, TCG_REG_A0, 0); } else { tcg_out_opc_imm(s, OPC_SH, data_reg1, TCG_REG_A0, 0); @@ -1409,6 +1421,15 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, } break; + /* The bswap routines do not work on non-R2 CPU. In that case + we let TCG generating the corresponding code. */ + case INDEX_op_bswap16_i32: + tcg_out_bswap16(s, args[0], args[1]); + break; + case INDEX_op_bswap32_i32: + tcg_out_bswap32(s, args[0], args[1]); + break; + case INDEX_op_ext8s_i32: tcg_out_ext8s(s, args[0], args[1]); break; @@ -1503,6 +1524,9 @@ static const TCGTargetOpDef mips_op_defs[] = { { INDEX_op_shr_i32, { "r", "rZ", "ri" } }, { INDEX_op_sar_i32, { "r", "rZ", "ri" } }, + { INDEX_op_bswap16_i32, { "r", "r" } }, + { INDEX_op_bswap32_i32, { "r", "r" } }, + { INDEX_op_ext8s_i32, { "r", "rZ" } }, { INDEX_op_ext16s_i32, { "r", "rZ" } }, diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index 9c68a32582..c5c13f71d3 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -83,8 +83,6 @@ typedef enum { #define TCG_TARGET_HAS_rot_i32 0 #define TCG_TARGET_HAS_ext8s_i32 1 #define TCG_TARGET_HAS_ext16s_i32 1 -#define TCG_TARGET_HAS_bswap32_i32 0 -#define TCG_TARGET_HAS_bswap16_i32 0 #define TCG_TARGET_HAS_andc_i32 0 #define TCG_TARGET_HAS_orc_i32 0 #define TCG_TARGET_HAS_eqv_i32 0 @@ -92,6 +90,15 @@ typedef enum { #define TCG_TARGET_HAS_deposit_i32 0 #define TCG_TARGET_HAS_movcond_i32 0 +/* optional instructions only implemented on MIPS32R2 */ +#ifdef _MIPS_ARCH_MIPS32R2 +#define TCG_TARGET_HAS_bswap16_i32 1 +#define TCG_TARGET_HAS_bswap32_i32 1 +#else +#define TCG_TARGET_HAS_bswap16_i32 0 +#define TCG_TARGET_HAS_bswap32_i32 0 +#endif + /* optional instructions automatically implemented */ #define TCG_TARGET_HAS_neg_i32 0 /* sub rd, zero, rt */ #define TCG_TARGET_HAS_ext8u_i32 0 /* andi rt, rs, 0xff */ From 9a152519a9f767297c92b5840c91a22235295c8d Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 21 Sep 2012 18:20:26 +0200 Subject: [PATCH 0498/2270] tcg/mips: implement rotl/rotr ops on MIPS32R2 rotr operations can be optimized on MIPS32 Release 2 using the ROTR and ROTRV instructions. Also implemented rotl operations by subtracting the shift from 32. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/mips/tcg-target.c | 20 ++++++++++++++++++++ tcg/mips/tcg-target.h | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index 8b2f9fc7d6..592e42a2bc 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -300,9 +300,11 @@ enum { OPC_SPECIAL = 0x00 << 26, OPC_SLL = OPC_SPECIAL | 0x00, OPC_SRL = OPC_SPECIAL | 0x02, + OPC_ROTR = OPC_SPECIAL | (0x01 << 21) | 0x02, OPC_SRA = OPC_SPECIAL | 0x03, OPC_SLLV = OPC_SPECIAL | 0x04, OPC_SRLV = OPC_SPECIAL | 0x06, + OPC_ROTRV = OPC_SPECIAL | (0x01 << 6) | 0x06, OPC_SRAV = OPC_SPECIAL | 0x07, OPC_JR = OPC_SPECIAL | 0x08, OPC_JALR = OPC_SPECIAL | 0x09, @@ -1420,6 +1422,22 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]); } break; + case INDEX_op_rotl_i32: + if (const_args[2]) { + tcg_out_opc_sa(s, OPC_ROTR, args[0], args[1], 0x20 - args[2]); + } else { + tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, 32); + tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, TCG_REG_AT, args[2]); + tcg_out_opc_reg(s, OPC_ROTRV, args[0], TCG_REG_AT, args[1]); + } + break; + case INDEX_op_rotr_i32: + if (const_args[2]) { + tcg_out_opc_sa(s, OPC_ROTR, args[0], args[1], args[2]); + } else { + tcg_out_opc_reg(s, OPC_ROTRV, args[0], args[2], args[1]); + } + break; /* The bswap routines do not work on non-R2 CPU. In that case we let TCG generating the corresponding code. */ @@ -1523,6 +1541,8 @@ static const TCGTargetOpDef mips_op_defs[] = { { INDEX_op_shl_i32, { "r", "rZ", "ri" } }, { INDEX_op_shr_i32, { "r", "rZ", "ri" } }, { INDEX_op_sar_i32, { "r", "rZ", "ri" } }, + { INDEX_op_rotr_i32, { "r", "rZ", "ri" } }, + { INDEX_op_rotl_i32, { "r", "rZ", "ri" } }, { INDEX_op_bswap16_i32, { "r", "r" } }, { INDEX_op_bswap32_i32, { "r", "r" } }, diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index c5c13f71d3..470314cc99 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -80,7 +80,6 @@ typedef enum { #define TCG_TARGET_HAS_div_i32 1 #define TCG_TARGET_HAS_not_i32 1 #define TCG_TARGET_HAS_nor_i32 1 -#define TCG_TARGET_HAS_rot_i32 0 #define TCG_TARGET_HAS_ext8s_i32 1 #define TCG_TARGET_HAS_ext16s_i32 1 #define TCG_TARGET_HAS_andc_i32 0 @@ -94,9 +93,11 @@ typedef enum { #ifdef _MIPS_ARCH_MIPS32R2 #define TCG_TARGET_HAS_bswap16_i32 1 #define TCG_TARGET_HAS_bswap32_i32 1 +#define TCG_TARGET_HAS_rot_i32 1 #else #define TCG_TARGET_HAS_bswap16_i32 0 #define TCG_TARGET_HAS_bswap32_i32 0 +#define TCG_TARGET_HAS_rot_i32 0 #endif /* optional instructions automatically implemented */ From 04f71aa3fd002d8c3aeb6db72a9219e1a8b3fef4 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 21 Sep 2012 18:20:26 +0200 Subject: [PATCH 0499/2270] tcg/mips: implement deposit op on MIPS32R2 deposit operations can be optimized on MIPS32 Release 2 using the INS instruction. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/mips/tcg-target.c | 8 ++++++++ tcg/mips/tcg-target.h | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index 592e42a2bc..b2e1056693 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -328,6 +328,7 @@ enum { OPC_BGEZ = OPC_REGIMM | (0x01 << 16), OPC_SPECIAL3 = 0x1f << 26, + OPC_INS = OPC_SPECIAL3 | 0x004, OPC_WSBH = OPC_SPECIAL3 | 0x0a0, OPC_SEB = OPC_SPECIAL3 | 0x420, OPC_SEH = OPC_SPECIAL3 | 0x620, @@ -1455,6 +1456,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_ext16s(s, args[0], args[1]); break; + case INDEX_op_deposit_i32: + tcg_out_opc_imm(s, OPC_INS, args[0], args[2], + ((args[3] + args[4] - 1) << 11) | (args[3] << 6)); + break; + case INDEX_op_brcond_i32: tcg_out_brcond(s, args[2], args[0], args[1], args[3]); break; @@ -1550,6 +1556,8 @@ static const TCGTargetOpDef mips_op_defs[] = { { INDEX_op_ext8s_i32, { "r", "rZ" } }, { INDEX_op_ext16s_i32, { "r", "rZ" } }, + { INDEX_op_deposit_i32, { "r", "0", "rZ" } }, + { INDEX_op_brcond_i32, { "rZ", "rZ" } }, { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } }, { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } }, diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index 470314cc99..897a737ccc 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -86,7 +86,6 @@ typedef enum { #define TCG_TARGET_HAS_orc_i32 0 #define TCG_TARGET_HAS_eqv_i32 0 #define TCG_TARGET_HAS_nand_i32 0 -#define TCG_TARGET_HAS_deposit_i32 0 #define TCG_TARGET_HAS_movcond_i32 0 /* optional instructions only implemented on MIPS32R2 */ @@ -94,10 +93,12 @@ typedef enum { #define TCG_TARGET_HAS_bswap16_i32 1 #define TCG_TARGET_HAS_bswap32_i32 1 #define TCG_TARGET_HAS_rot_i32 1 +#define TCG_TARGET_HAS_deposit_i32 1 #else #define TCG_TARGET_HAS_bswap16_i32 0 #define TCG_TARGET_HAS_bswap32_i32 0 #define TCG_TARGET_HAS_rot_i32 0 +#define TCG_TARGET_HAS_deposit_i32 0 #endif /* optional instructions automatically implemented */ From 7d7c4930ab83349ee31945d93a1747331c37c0eb Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 21 Sep 2012 18:20:26 +0200 Subject: [PATCH 0500/2270] tcg/mips: implement movcond op on MIPS32R2 movcond operation can be implemented on MIPS32 Release 2 using the MOVN, MOVZ, SLT and SLTU instructions. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/mips/tcg-target.c | 69 +++++++++++++++++++++++++++++++++++++++++++ tcg/mips/tcg-target.h | 8 +++++ 2 files changed, 77 insertions(+) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index b2e1056693..c272b38a7d 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -308,6 +308,8 @@ enum { OPC_SRAV = OPC_SPECIAL | 0x07, OPC_JR = OPC_SPECIAL | 0x08, OPC_JALR = OPC_SPECIAL | 0x09, + OPC_MOVZ = OPC_SPECIAL | 0x0A, + OPC_MOVN = OPC_SPECIAL | 0x0B, OPC_MFHI = OPC_SPECIAL | 0x10, OPC_MFLO = OPC_SPECIAL | 0x12, OPC_MULT = OPC_SPECIAL | 0x18, @@ -735,6 +737,68 @@ static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGArg arg1, reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr); } +static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret, + TCGArg c1, TCGArg c2, TCGArg v) +{ + switch (cond) { + case TCG_COND_EQ: + if (c1 == 0) { + tcg_out_opc_reg(s, OPC_MOVZ, ret, v, c2); + } else if (c2 == 0) { + tcg_out_opc_reg(s, OPC_MOVZ, ret, v, c1); + } else { + tcg_out_opc_reg(s, OPC_XOR, TCG_REG_AT, c1, c2); + tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT); + } + break; + case TCG_COND_NE: + if (c1 == 0) { + tcg_out_opc_reg(s, OPC_MOVN, ret, v, c2); + } else if (c2 == 0) { + tcg_out_opc_reg(s, OPC_MOVN, ret, v, c1); + } else { + tcg_out_opc_reg(s, OPC_XOR, TCG_REG_AT, c1, c2); + tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT); + } + break; + case TCG_COND_LT: + tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c1, c2); + tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT); + break; + case TCG_COND_LTU: + tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c1, c2); + tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT); + break; + case TCG_COND_GE: + tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c1, c2); + tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT); + break; + case TCG_COND_GEU: + tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c1, c2); + tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT); + break; + case TCG_COND_LE: + tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c2, c1); + tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT); + break; + case TCG_COND_LEU: + tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c2, c1); + tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT); + break; + case TCG_COND_GT: + tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c2, c1); + tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT); + break; + case TCG_COND_GTU: + tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c2, c1); + tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT); + break; + default: + tcg_abort(); + break; + } +} + static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, TCGArg arg1, TCGArg arg2) { @@ -1468,6 +1532,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]); break; + case INDEX_op_movcond_i32: + tcg_out_movcond(s, args[5], args[0], args[1], args[2], args[3]); + break; + case INDEX_op_setcond_i32: tcg_out_setcond(s, args[3], args[0], args[1], args[2]); break; @@ -1559,6 +1627,7 @@ static const TCGTargetOpDef mips_op_defs[] = { { INDEX_op_deposit_i32, { "r", "0", "rZ" } }, { INDEX_op_brcond_i32, { "rZ", "rZ" } }, + { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } }, { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } }, { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } }, diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index 897a737ccc..d147e70eb1 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -86,7 +86,15 @@ typedef enum { #define TCG_TARGET_HAS_orc_i32 0 #define TCG_TARGET_HAS_eqv_i32 0 #define TCG_TARGET_HAS_nand_i32 0 + +/* optional instructions only implemented on MIPS4, MIPS32 and Loongson 2 */ +#if defined(_MIPS_ARCH_MIPS4) || defined(_MIPS_ARCH_MIPS32) || \ + defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_LOONGSON2E) || \ + defined(_MIPS_ARCH_LOONGSON2F) +#define TCG_TARGET_HAS_movcond_i32 1 +#else #define TCG_TARGET_HAS_movcond_i32 0 +#endif /* optional instructions only implemented on MIPS32R2 */ #ifdef _MIPS_ARCH_MIPS32R2 From 48b56ce1683dec02a29448f31861fca4dd0a0b33 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Mon, 10 Sep 2012 23:51:42 +0200 Subject: [PATCH 0501/2270] tcg/optimize: remove TCG_TEMP_ANY TCG_TEMP_ANY has no different meaning than TCG_TEMP_UNDEF, so use the later instead. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index 1be7631672..308b7f9033 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -39,8 +39,7 @@ typedef enum { TCG_TEMP_UNDEF = 0, TCG_TEMP_CONST, TCG_TEMP_COPY, - TCG_TEMP_HAS_COPY, - TCG_TEMP_ANY + TCG_TEMP_HAS_COPY } tcg_temp_state; struct tcg_temp_info { @@ -52,7 +51,7 @@ struct tcg_temp_info { static struct tcg_temp_info temps[TCG_MAX_TEMPS]; -/* Reset TEMP's state to TCG_TEMP_ANY. If TEMP was a representative of some +/* Reset TEMP's state to TCG_TEMP_UNDEF. If TEMP was a representative of some class of equivalent temp's, a new representative should be chosen in this class. */ static void reset_temp(TCGArg temp, int nb_temps, int nb_globals) @@ -69,7 +68,7 @@ static void reset_temp(TCGArg temp, int nb_temps, int nb_globals) } for (i = temps[temp].next_copy; i != temp; i = temps[i].next_copy) { if (new_base == (TCGArg)-1) { - temps[i].state = TCG_TEMP_ANY; + temps[i].state = TCG_TEMP_UNDEF; } else { temps[i].val = new_base; } @@ -81,9 +80,9 @@ static void reset_temp(TCGArg temp, int nb_temps, int nb_globals) temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy; new_base = temps[temp].val; } - temps[temp].state = TCG_TEMP_ANY; + temps[temp].state = TCG_TEMP_UNDEF; if (new_base != (TCGArg)-1 && temps[new_base].next_copy == new_base) { - temps[new_base].state = TCG_TEMP_ANY; + temps[new_base].state = TCG_TEMP_UNDEF; } } From b80bb016d8c8e9d74345a90ab6dac1cb547904e0 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 11 Sep 2012 12:26:23 +0200 Subject: [PATCH 0502/2270] tcg/optimize: check types in copy propagation The copy propagation doesn't check the types of the temps during copy propagation. However TCG is using the mov_i32 for the i64 to i32 conversion and thus the two are not equivalent. With this patch tcg_opt_gen_mov() doesn't consider two temps of different type as copies anymore. So far it seems the optimization was not aggressive enough to trigger this bug, but it will be triggered later in this series once the copy propagation is improved. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index 308b7f9033..da8dffe9cd 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -106,12 +106,13 @@ static TCGOpcode op_to_movi(TCGOpcode op) } } -static void tcg_opt_gen_mov(TCGArg *gen_args, TCGArg dst, TCGArg src, - int nb_temps, int nb_globals) +static void tcg_opt_gen_mov(TCGContext *s, TCGArg *gen_args, + TCGArg dst, TCGArg src) { - reset_temp(dst, nb_temps, nb_globals); + reset_temp(dst, s->nb_temps, s->nb_globals); assert(temps[src].state != TCG_TEMP_COPY); - if (src >= nb_globals) { + /* Only consider temps with the same type (width) as copies. */ + if (src >= s->nb_globals && s->temps[dst].type == s->temps[src].type) { assert(temps[src].state != TCG_TEMP_CONST); if (temps[src].state != TCG_TEMP_HAS_COPY) { temps[src].state = TCG_TEMP_HAS_COPY; @@ -461,8 +462,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, gen_opc_buf[op_index] = INDEX_op_nop; } else { gen_opc_buf[op_index] = op_to_mov(op); - tcg_opt_gen_mov(gen_args, args[0], args[1], - nb_temps, nb_globals); + tcg_opt_gen_mov(s, gen_args, args[0], args[1]); gen_args += 2; } args += 3; @@ -499,8 +499,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, gen_opc_buf[op_index] = INDEX_op_nop; } else { gen_opc_buf[op_index] = op_to_mov(op); - tcg_opt_gen_mov(gen_args, args[0], args[1], nb_temps, - nb_globals); + tcg_opt_gen_mov(s, gen_args, args[0], args[1]); gen_args += 2; } args += 3; @@ -524,8 +523,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, break; } if (temps[args[1]].state != TCG_TEMP_CONST) { - tcg_opt_gen_mov(gen_args, args[0], args[1], - nb_temps, nb_globals); + tcg_opt_gen_mov(s, gen_args, args[0], args[1]); gen_args += 2; args += 2; break; From e590d4e6b3c73b38a9d9ed10c898f73ed8a29f1d Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 11 Sep 2012 12:31:21 +0200 Subject: [PATCH 0503/2270] tcg/optimize: rework copy progagation The copy propagation pass tries to keep track what is a copy of what and what has copy of what, and in addition it keep a circular list of of all the copies. Unfortunately this doesn't fully work: a mov from a temp which has a state "COPY" changed it into a state "HAS_COPY". Later when this temp is used again, it is considered has not having copy and thus no propagation is done. This patch fixes that by removing the hiearchy between copies, and thus only keeping a "COPY" state both meaning "is a copy" and "has a copy". The decision of which copy to use is deferred to the actual temp replacement. At this stage there is not one best choice to do, but only better choices than others. For doing the best choice the operation would have to be parsed in reversed to know if a temp is going to be used later or not. That what is done by the liveness analysis. At this stage it is known that globals will be always live, that local temps will be dead at the end of the translation block, and that the temps will be dead at the end of the basic block. This means that this stage should try to replace temps by local temps or globals and local temps by globals. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 167 +++++++++++++++++++++++++++---------------------- 1 file changed, 92 insertions(+), 75 deletions(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index da8dffe9cd..1904b396a6 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -39,7 +39,6 @@ typedef enum { TCG_TEMP_UNDEF = 0, TCG_TEMP_CONST, TCG_TEMP_COPY, - TCG_TEMP_HAS_COPY } tcg_temp_state; struct tcg_temp_info { @@ -51,39 +50,19 @@ struct tcg_temp_info { static struct tcg_temp_info temps[TCG_MAX_TEMPS]; -/* Reset TEMP's state to TCG_TEMP_UNDEF. If TEMP was a representative of some - class of equivalent temp's, a new representative should be chosen in this - class. */ -static void reset_temp(TCGArg temp, int nb_temps, int nb_globals) +/* Reset TEMP's state to TCG_TEMP_UNDEF. If TEMP only had one copy, remove + the copy flag from the left temp. */ +static void reset_temp(TCGArg temp) { - int i; - TCGArg new_base = (TCGArg)-1; - if (temps[temp].state == TCG_TEMP_HAS_COPY) { - for (i = temps[temp].next_copy; i != temp; i = temps[i].next_copy) { - if (i >= nb_globals) { - temps[i].state = TCG_TEMP_HAS_COPY; - new_base = i; - break; - } + if (temps[temp].state == TCG_TEMP_COPY) { + if (temps[temp].prev_copy == temps[temp].next_copy) { + temps[temps[temp].next_copy].state = TCG_TEMP_UNDEF; + } else { + temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy; + temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy; } - for (i = temps[temp].next_copy; i != temp; i = temps[i].next_copy) { - if (new_base == (TCGArg)-1) { - temps[i].state = TCG_TEMP_UNDEF; - } else { - temps[i].val = new_base; - } - } - temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy; - temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy; - } else if (temps[temp].state == TCG_TEMP_COPY) { - temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy; - temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy; - new_base = temps[temp].val; } temps[temp].state = TCG_TEMP_UNDEF; - if (new_base != (TCGArg)-1 && temps[new_base].next_copy == new_base) { - temps[new_base].state = TCG_TEMP_UNDEF; - } } static int op_bits(TCGOpcode op) @@ -106,34 +85,83 @@ static TCGOpcode op_to_movi(TCGOpcode op) } } +static TCGArg find_better_copy(TCGContext *s, TCGArg temp) +{ + TCGArg i; + + /* If this is already a global, we can't do better. */ + if (temp < s->nb_globals) { + return temp; + } + + /* Search for a global first. */ + for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) { + if (i < s->nb_globals) { + return i; + } + } + + /* If it is a temp, search for a temp local. */ + if (!s->temps[temp].temp_local) { + for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) { + if (s->temps[i].temp_local) { + return i; + } + } + } + + /* Failure to find a better representation, return the same temp. */ + return temp; +} + +static bool temps_are_copies(TCGArg arg1, TCGArg arg2) +{ + TCGArg i; + + if (arg1 == arg2) { + return true; + } + + if (temps[arg1].state != TCG_TEMP_COPY + || temps[arg2].state != TCG_TEMP_COPY) { + return false; + } + + for (i = temps[arg1].next_copy ; i != arg1 ; i = temps[i].next_copy) { + if (i == arg2) { + return true; + } + } + + return false; +} + static void tcg_opt_gen_mov(TCGContext *s, TCGArg *gen_args, TCGArg dst, TCGArg src) { - reset_temp(dst, s->nb_temps, s->nb_globals); - assert(temps[src].state != TCG_TEMP_COPY); - /* Only consider temps with the same type (width) as copies. */ - if (src >= s->nb_globals && s->temps[dst].type == s->temps[src].type) { - assert(temps[src].state != TCG_TEMP_CONST); - if (temps[src].state != TCG_TEMP_HAS_COPY) { - temps[src].state = TCG_TEMP_HAS_COPY; + reset_temp(dst); + assert(temps[src].state != TCG_TEMP_CONST); + + if (s->temps[src].type == s->temps[dst].type) { + if (temps[src].state != TCG_TEMP_COPY) { + temps[src].state = TCG_TEMP_COPY; temps[src].next_copy = src; temps[src].prev_copy = src; } temps[dst].state = TCG_TEMP_COPY; - temps[dst].val = src; temps[dst].next_copy = temps[src].next_copy; temps[dst].prev_copy = src; temps[temps[dst].next_copy].prev_copy = dst; temps[src].next_copy = dst; } + gen_args[0] = dst; gen_args[1] = src; } -static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val, - int nb_temps, int nb_globals) +static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val) { - reset_temp(dst, nb_temps, nb_globals); + reset_temp(dst); temps[dst].state = TCG_TEMP_CONST; temps[dst].val = val; gen_args[0] = dst; @@ -324,7 +352,6 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x, tcg_abort(); } - /* Propagate constants and copies, fold constant expressions. */ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, TCGArg *args, TCGOpDef *tcg_op_defs) @@ -338,10 +365,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, /* Array VALS has an element for each temp. If this temp holds a constant then its value is kept in VALS' element. - If this temp is a copy of other ones then this equivalence class' - representative is kept in VALS' element. - If this temp is neither copy nor constant then corresponding VALS' - element is unused. */ + If this temp is a copy of other ones then the other copies are + available through the doubly linked circular list. */ nb_temps = s->nb_temps; nb_globals = s->nb_globals; @@ -357,7 +382,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, assert(op != INDEX_op_call); for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) { if (temps[args[i]].state == TCG_TEMP_COPY) { - args[i] = temps[args[i]].val; + args[i] = find_better_copy(s, args[i]); } } } @@ -429,7 +454,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, if (temps[args[1]].state == TCG_TEMP_CONST && temps[args[1]].val == 0) { gen_opc_buf[op_index] = op_to_movi(op); - tcg_opt_gen_movi(gen_args, args[0], 0, nb_temps, nb_globals); + tcg_opt_gen_movi(gen_args, args[0], 0); args += 3; gen_args += 2; continue; @@ -456,9 +481,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, } if (temps[args[2]].state == TCG_TEMP_CONST && temps[args[2]].val == 0) { - if ((temps[args[0]].state == TCG_TEMP_COPY - && temps[args[0]].val == args[1]) - || args[0] == args[1]) { + if (temps_are_copies(args[0], args[1])) { gen_opc_buf[op_index] = INDEX_op_nop; } else { gen_opc_buf[op_index] = op_to_mov(op); @@ -480,7 +503,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, if ((temps[args[2]].state == TCG_TEMP_CONST && temps[args[2]].val == 0)) { gen_opc_buf[op_index] = op_to_movi(op); - tcg_opt_gen_movi(gen_args, args[0], 0, nb_temps, nb_globals); + tcg_opt_gen_movi(gen_args, args[0], 0); args += 3; gen_args += 2; continue; @@ -495,7 +518,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, CASE_OP_32_64(or): CASE_OP_32_64(and): if (args[1] == args[2]) { - if (args[1] == args[0]) { + if (temps_are_copies(args[0], args[1])) { gen_opc_buf[op_index] = INDEX_op_nop; } else { gen_opc_buf[op_index] = op_to_mov(op); @@ -515,9 +538,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, allocator where needed and possible. Also detect copies. */ switch (op) { CASE_OP_32_64(mov): - if ((temps[args[1]].state == TCG_TEMP_COPY - && temps[args[1]].val == args[0]) - || args[0] == args[1]) { + if (temps_are_copies(args[0], args[1])) { args += 2; gen_opc_buf[op_index] = INDEX_op_nop; break; @@ -535,7 +556,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, args[1] = temps[args[1]].val; /* fallthrough */ CASE_OP_32_64(movi): - tcg_opt_gen_movi(gen_args, args[0], args[1], nb_temps, nb_globals); + tcg_opt_gen_movi(gen_args, args[0], args[1]); gen_args += 2; args += 2; break; @@ -550,9 +571,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, if (temps[args[1]].state == TCG_TEMP_CONST) { gen_opc_buf[op_index] = op_to_movi(op); tmp = do_constant_folding(op, temps[args[1]].val, 0); - tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals); + tcg_opt_gen_movi(gen_args, args[0], tmp); } else { - reset_temp(args[0], nb_temps, nb_globals); + reset_temp(args[0]); gen_args[0] = args[0]; gen_args[1] = args[1]; } @@ -580,10 +601,10 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, gen_opc_buf[op_index] = op_to_movi(op); tmp = do_constant_folding(op, temps[args[1]].val, temps[args[2]].val); - tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals); + tcg_opt_gen_movi(gen_args, args[0], tmp); gen_args += 2; } else { - reset_temp(args[0], nb_temps, nb_globals); + reset_temp(args[0]); gen_args[0] = args[0]; gen_args[1] = args[1]; gen_args[2] = args[2]; @@ -597,10 +618,10 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, gen_opc_buf[op_index] = op_to_movi(op); tmp = do_constant_folding_cond(op, temps[args[1]].val, temps[args[2]].val, args[3]); - tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals); + tcg_opt_gen_movi(gen_args, args[0], tmp); gen_args += 2; } else { - reset_temp(args[0], nb_temps, nb_globals); + reset_temp(args[0]); gen_args[0] = args[0]; gen_args[1] = args[1]; gen_args[2] = args[2]; @@ -623,7 +644,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, } } else { memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info)); - reset_temp(args[0], nb_temps, nb_globals); + reset_temp(args[0]); gen_args[0] = args[0]; gen_args[1] = args[1]; gen_args[2] = args[2]; @@ -637,23 +658,19 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, && temps[args[2]].state == TCG_TEMP_CONST) { tmp = do_constant_folding_cond(op, temps[args[1]].val, temps[args[2]].val, args[5]); - if (args[0] == args[4-tmp] - || (temps[args[4-tmp]].state == TCG_TEMP_COPY - && temps[args[4-tmp]].val == args[0])) { + if (temps_are_copies(args[0], args[4-tmp])) { gen_opc_buf[op_index] = INDEX_op_nop; } else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) { gen_opc_buf[op_index] = op_to_movi(op); - tcg_opt_gen_movi(gen_args, args[0], temps[args[4-tmp]].val, - nb_temps, nb_globals); + tcg_opt_gen_movi(gen_args, args[0], temps[args[4-tmp]].val); gen_args += 2; } else { gen_opc_buf[op_index] = op_to_mov(op); - tcg_opt_gen_mov(gen_args, args[0], args[4-tmp], - nb_temps, nb_globals); + tcg_opt_gen_mov(s, gen_args, args[0], args[4-tmp]); gen_args += 2; } } else { - reset_temp(args[0], nb_temps, nb_globals); + reset_temp(args[0]); gen_args[0] = args[0]; gen_args[1] = args[1]; gen_args[2] = args[2]; @@ -668,11 +685,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, nb_call_args = (args[0] >> 16) + (args[0] & 0xffff); if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) { for (i = 0; i < nb_globals; i++) { - reset_temp(i, nb_temps, nb_globals); + reset_temp(i); } } for (i = 0; i < (args[0] >> 16); i++) { - reset_temp(args[i + 1], nb_temps, nb_globals); + reset_temp(args[i + 1]); } i = nb_call_args + 3; while (i) { @@ -691,7 +708,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info)); } else { for (i = 0; i < def->nb_oargs; i++) { - reset_temp(args[i], nb_temps, nb_globals); + reset_temp(args[i]); } } for (i = 0; i < def->nb_args; i++) { From 1ff8c5418a680d6766493908eaa07cc11dce7f13 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 11 Sep 2012 16:18:49 +0200 Subject: [PATCH 0504/2270] tcg/optimize: do copy propagation for all operations It is possible to due copy propagation for all operations, even the one that have side effects or clobber arguments (it only concerns input arguments). That said, the call operation should be handled differently due to the variable number of arguments. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index 1904b396a6..aeb2225f2a 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -378,8 +378,15 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, op = gen_opc_buf[op_index]; def = &tcg_op_defs[op]; /* Do copy propagation */ - if (!(def->flags & (TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS))) { - assert(op != INDEX_op_call); + if (op == INDEX_op_call) { + int nb_oargs = args[0] >> 16; + int nb_iargs = args[0] & 0xffff; + for (i = nb_oargs + 1; i < nb_oargs + nb_iargs + 1; i++) { + if (temps[args[i]].state == TCG_TEMP_COPY) { + args[i] = find_better_copy(s, args[i]); + } + } + } else { for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) { if (temps[args[i]].state == TCG_TEMP_COPY) { args[i] = find_better_copy(s, args[i]); From 0aba1c7376ad325202f328211ab6dfcae94c7f2a Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 18 Sep 2012 19:11:32 +0200 Subject: [PATCH 0505/2270] tcg/optimize: optimize "op r, a, a => mov r, a" Now that we can easily detect all copies, we can optimize the "op r, a, a => mov r, a" case a bit more. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index aeb2225f2a..b9a7da920f 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -524,7 +524,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, switch (op) { CASE_OP_32_64(or): CASE_OP_32_64(and): - if (args[1] == args[2]) { + if (temps_are_copies(args[1], args[2])) { if (temps_are_copies(args[0], args[1])) { gen_opc_buf[op_index] = INDEX_op_nop; } else { From 3c94193e0bbdd855bcbedabd27e3cbe1e6bc6242 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 18 Sep 2012 19:12:36 +0200 Subject: [PATCH 0506/2270] tcg/optimize: optimize "op r, a, a => movi r, 0" Now that it's possible to detect copies, we can optimize the case the "op r, a, a => movi r, 0". This helps in the computation of overflow flags when one of the two args is 0. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tcg/optimize.c b/tcg/optimize.c index b9a7da920f..ceea6441bc 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -540,6 +540,22 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, break; } + /* Simplify expression for "op r, a, a => movi r, 0" cases */ + switch (op) { + CASE_OP_32_64(sub): + CASE_OP_32_64(xor): + if (temps_are_copies(args[1], args[2])) { + gen_opc_buf[op_index] = op_to_movi(op); + tcg_opt_gen_movi(gen_args, args[0], 0); + gen_args += 2; + args += 3; + continue; + } + break; + default: + break; + } + /* Propagate constants through copy operations and do constant folding. Constants will be substituted to arguments by register allocator where needed and possible. Also detect copies. */ From b336ceb6918b8f9eb54dcbb1043521482c7be83b Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 18 Sep 2012 19:37:00 +0200 Subject: [PATCH 0507/2270] tcg/optimize: further optimize brcond/movcond/setcond When both argument of brcond/movcond/setcond are the same or when one of the two values is a constant equal to zero, it's possible to do further optimizations. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 135 +++++++++++++++++++++++++++++-------------------- 1 file changed, 80 insertions(+), 55 deletions(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index ceea6441bc..abe016a28a 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -292,58 +292,88 @@ static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y) return res; } +/* Return 2 if the condition can't be simplified, and the result + of the condition (0 or 1) if it can */ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x, TCGArg y, TCGCond c) { - switch (op_bits(op)) { - case 32: - switch (c) { - case TCG_COND_EQ: - return (uint32_t)x == (uint32_t)y; - case TCG_COND_NE: - return (uint32_t)x != (uint32_t)y; - case TCG_COND_LT: - return (int32_t)x < (int32_t)y; - case TCG_COND_GE: - return (int32_t)x >= (int32_t)y; - case TCG_COND_LE: - return (int32_t)x <= (int32_t)y; - case TCG_COND_GT: - return (int32_t)x > (int32_t)y; - case TCG_COND_LTU: - return (uint32_t)x < (uint32_t)y; - case TCG_COND_GEU: - return (uint32_t)x >= (uint32_t)y; - case TCG_COND_LEU: - return (uint32_t)x <= (uint32_t)y; - case TCG_COND_GTU: - return (uint32_t)x > (uint32_t)y; + if (temps[x].state == TCG_TEMP_CONST && temps[y].state == TCG_TEMP_CONST) { + switch (op_bits(op)) { + case 32: + switch (c) { + case TCG_COND_EQ: + return (uint32_t)temps[x].val == (uint32_t)temps[y].val; + case TCG_COND_NE: + return (uint32_t)temps[x].val != (uint32_t)temps[y].val; + case TCG_COND_LT: + return (int32_t)temps[x].val < (int32_t)temps[y].val; + case TCG_COND_GE: + return (int32_t)temps[x].val >= (int32_t)temps[y].val; + case TCG_COND_LE: + return (int32_t)temps[x].val <= (int32_t)temps[y].val; + case TCG_COND_GT: + return (int32_t)temps[x].val > (int32_t)temps[y].val; + case TCG_COND_LTU: + return (uint32_t)temps[x].val < (uint32_t)temps[y].val; + case TCG_COND_GEU: + return (uint32_t)temps[x].val >= (uint32_t)temps[y].val; + case TCG_COND_LEU: + return (uint32_t)temps[x].val <= (uint32_t)temps[y].val; + case TCG_COND_GTU: + return (uint32_t)temps[x].val > (uint32_t)temps[y].val; + } + break; + case 64: + switch (c) { + case TCG_COND_EQ: + return (uint64_t)temps[x].val == (uint64_t)temps[y].val; + case TCG_COND_NE: + return (uint64_t)temps[x].val != (uint64_t)temps[y].val; + case TCG_COND_LT: + return (int64_t)temps[x].val < (int64_t)temps[y].val; + case TCG_COND_GE: + return (int64_t)temps[x].val >= (int64_t)temps[y].val; + case TCG_COND_LE: + return (int64_t)temps[x].val <= (int64_t)temps[y].val; + case TCG_COND_GT: + return (int64_t)temps[x].val > (int64_t)temps[y].val; + case TCG_COND_LTU: + return (uint64_t)temps[x].val < (uint64_t)temps[y].val; + case TCG_COND_GEU: + return (uint64_t)temps[x].val >= (uint64_t)temps[y].val; + case TCG_COND_LEU: + return (uint64_t)temps[x].val <= (uint64_t)temps[y].val; + case TCG_COND_GTU: + return (uint64_t)temps[x].val > (uint64_t)temps[y].val; + } + break; } - break; - case 64: + } else if (temps_are_copies(x, y)) { switch (c) { - case TCG_COND_EQ: - return (uint64_t)x == (uint64_t)y; - case TCG_COND_NE: - return (uint64_t)x != (uint64_t)y; - case TCG_COND_LT: - return (int64_t)x < (int64_t)y; - case TCG_COND_GE: - return (int64_t)x >= (int64_t)y; - case TCG_COND_LE: - return (int64_t)x <= (int64_t)y; case TCG_COND_GT: - return (int64_t)x > (int64_t)y; case TCG_COND_LTU: - return (uint64_t)x < (uint64_t)y; - case TCG_COND_GEU: - return (uint64_t)x >= (uint64_t)y; - case TCG_COND_LEU: - return (uint64_t)x <= (uint64_t)y; + case TCG_COND_LT: case TCG_COND_GTU: - return (uint64_t)x > (uint64_t)y; + case TCG_COND_NE: + return 0; + case TCG_COND_GE: + case TCG_COND_GEU: + case TCG_COND_LE: + case TCG_COND_LEU: + case TCG_COND_EQ: + return 1; } - break; + } else if (temps[y].state == TCG_TEMP_CONST && temps[y].val == 0) { + switch (c) { + case TCG_COND_LTU: + return 0; + case TCG_COND_GEU: + return 1; + default: + return 2; + } + } else { + return 2; } fprintf(stderr, @@ -636,11 +666,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, args += 3; break; CASE_OP_32_64(setcond): - if (temps[args[1]].state == TCG_TEMP_CONST - && temps[args[2]].state == TCG_TEMP_CONST) { + tmp = do_constant_folding_cond(op, args[1], args[2], args[3]); + if (tmp != 2) { gen_opc_buf[op_index] = op_to_movi(op); - tmp = do_constant_folding_cond(op, temps[args[1]].val, - temps[args[2]].val, args[3]); tcg_opt_gen_movi(gen_args, args[0], tmp); gen_args += 2; } else { @@ -654,10 +682,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, args += 4; break; CASE_OP_32_64(brcond): - if (temps[args[0]].state == TCG_TEMP_CONST - && temps[args[1]].state == TCG_TEMP_CONST) { - if (do_constant_folding_cond(op, temps[args[0]].val, - temps[args[1]].val, args[2])) { + tmp = do_constant_folding_cond(op, args[0], args[1], args[2]); + if (tmp != 2) { + if (tmp) { memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info)); gen_opc_buf[op_index] = INDEX_op_br; gen_args[0] = args[3]; @@ -677,10 +704,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, args += 4; break; CASE_OP_32_64(movcond): - if (temps[args[1]].state == TCG_TEMP_CONST - && temps[args[2]].state == TCG_TEMP_CONST) { - tmp = do_constant_folding_cond(op, temps[args[1]].val, - temps[args[2]].val, args[5]); + tmp = do_constant_folding_cond(op, args[1], args[2], args[5]); + if (tmp != 2) { if (temps_are_copies(args[0], args[4-tmp])) { gen_opc_buf[op_index] = INDEX_op_nop; } else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) { From c2b0e2fea2ef7a183233d3b86c37c5d4bcb89544 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Wed, 19 Sep 2012 22:00:22 +0200 Subject: [PATCH 0508/2270] tcg/optimize: prefer the "op a, a, b" form for commutative ops The "op a, a, b" form is better handled on non-RISC host than the "op a, b, a" form, so swap the arguments to this form when possible, and when b is not a constant. This reduces the number of generated instructions by a tiny bit. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index abe016a28a..c8ae50bc91 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -434,7 +434,10 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, CASE_OP_32_64(eqv): CASE_OP_32_64(nand): CASE_OP_32_64(nor): - if (temps[args[1]].state == TCG_TEMP_CONST) { + /* Prefer the constant in second argument, and then the form + op a, a, b, which is better handled on non-RISC hosts. */ + if (temps[args[1]].state == TCG_TEMP_CONST || (args[0] == args[2] + && temps[args[2]].state != TCG_TEMP_CONST)) { tmp = args[1]; args[1] = args[2]; args[2] = tmp; From fba3161fd289f1282f5afce5f91c32e2575e5e8e Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 21 Sep 2012 10:02:45 +0200 Subject: [PATCH 0509/2270] tcg: remove #ifdef #endif around TCGOpcode tests Commit 25c4d9cc changed all TCGOpcode enums to be available, so we don't need to #ifdef #endif the one that are available only on some targets. This makes the code easier to read. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index bb9c9952aa..4afd035877 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -937,11 +937,7 @@ void tcg_dump_ops(TCGContext *s) args[nb_oargs + i])); } } - } else if (c == INDEX_op_movi_i32 -#if TCG_TARGET_REG_BITS == 64 - || c == INDEX_op_movi_i64 -#endif - ) { + } else if (c == INDEX_op_movi_i32 || c == INDEX_op_movi_i64) { tcg_target_ulong val; TCGHelperInfo *th; @@ -993,14 +989,11 @@ void tcg_dump_ops(TCGContext *s) case INDEX_op_brcond_i32: case INDEX_op_setcond_i32: case INDEX_op_movcond_i32: -#if TCG_TARGET_REG_BITS == 32 case INDEX_op_brcond2_i32: case INDEX_op_setcond2_i32: -#else case INDEX_op_brcond_i64: case INDEX_op_setcond_i64: case INDEX_op_movcond_i64: -#endif if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) { qemu_log(",%s", cond_name[args[k++]]); } else { @@ -2102,16 +2095,12 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, #endif switch(opc) { case INDEX_op_mov_i32: -#if TCG_TARGET_REG_BITS == 64 case INDEX_op_mov_i64: -#endif dead_args = s->op_dead_args[op_index]; tcg_reg_alloc_mov(s, def, args, dead_args); break; case INDEX_op_movi_i32: -#if TCG_TARGET_REG_BITS == 64 case INDEX_op_movi_i64: -#endif tcg_reg_alloc_movi(s, args); break; case INDEX_op_debug_insn_start: From 7ef55fc91926f518f905692db19ed0b4a8018989 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 21 Sep 2012 11:07:29 +0200 Subject: [PATCH 0510/2270] tcg/optimize: add constant folding for deposit Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tcg/optimize.c b/tcg/optimize.c index c8ae50bc91..35532a1e03 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -668,6 +668,26 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, } args += 3; break; + CASE_OP_32_64(deposit): + if (temps[args[1]].state == TCG_TEMP_CONST + && temps[args[2]].state == TCG_TEMP_CONST) { + gen_opc_buf[op_index] = op_to_movi(op); + tmp = ((1ull << args[4]) - 1); + tmp = (temps[args[1]].val & ~(tmp << args[3])) + | ((temps[args[2]].val & tmp) << args[3]); + tcg_opt_gen_movi(gen_args, args[0], tmp); + gen_args += 2; + } else { + reset_temp(args[0]); + gen_args[0] = args[0]; + gen_args[1] = args[1]; + gen_args[2] = args[2]; + gen_args[3] = args[3]; + gen_args[4] = args[4]; + gen_args += 5; + } + args += 5; + break; CASE_OP_32_64(setcond): tmp = do_constant_folding_cond(op, args[1], args[2], args[3]); if (tmp != 2) { From f0da375754666511acefa89b57487a22a2b9f945 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 18:46:32 -0700 Subject: [PATCH 0511/2270] tcg-hppa: Implement movcond Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/hppa/tcg-target.c | 21 +++++++++++++++++++++ tcg/hppa/tcg-target.h | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c index 5385d45cdc..793b90da45 100644 --- a/tcg/hppa/tcg-target.c +++ b/tcg/hppa/tcg-target.c @@ -912,6 +912,18 @@ static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret, tcg_out_mov(s, TCG_TYPE_I32, ret, scratch); } +static void tcg_out_movcond(TCGContext *s, int cond, TCGArg ret, + TCGArg c1, TCGArg c2, int c2const, + TCGArg v1, int v1const) +{ + tcg_out_comclr(s, tcg_invert_cond(cond), TCG_REG_R0, c1, c2, c2const); + if (v1const) { + tcg_out_movi(s, TCG_TYPE_I32, ret, v1); + } else { + tcg_out_mov(s, TCG_TYPE_I32, ret, v1); + } +} + #if defined(CONFIG_SOFTMMU) #include "../../softmmu_defs.h" @@ -1520,6 +1532,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, args[3], const_args[3], args[4], const_args[4]); break; + case INDEX_op_movcond_i32: + tcg_out_movcond(s, args[5], args[0], args[1], args[2], const_args[2], + args[3], const_args[3]); + break; + case INDEX_op_add2_i32: tcg_out_add2(s, args[0], args[1], args[2], args[3], args[4], args[5], const_args[4]); @@ -1628,6 +1645,10 @@ static const TCGTargetOpDef hppa_op_defs[] = { { INDEX_op_setcond_i32, { "r", "rZ", "rI" } }, { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rI", "rI" } }, + /* ??? We can actually support a signed 14-bit arg3, but we + only have existing constraints for a signed 11-bit. */ + { INDEX_op_movcond_i32, { "r", "rZ", "rI", "rI", "0" } }, + { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rI", "rZ" } }, { INDEX_op_sub2_i32, { "r", "r", "rI", "rZ", "rK", "rZ" } }, diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h index 4defd28577..5351353719 100644 --- a/tcg/hppa/tcg-target.h +++ b/tcg/hppa/tcg-target.h @@ -96,7 +96,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 1 -#define TCG_TARGET_HAS_movcond_i32 0 +#define TCG_TARGET_HAS_movcond_i32 1 /* optional instructions automatically implemented */ #define TCG_TARGET_HAS_neg_i32 0 /* sub rd, 0, rs */ From 9bacf4143190ca57771c8db5981d040f9c625ae5 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Fri, 21 Sep 2012 04:18:07 +0400 Subject: [PATCH 0512/2270] tcg/README: document tcg_gen_goto_tb restrictions See http://lists.nongnu.org/archive/html/qemu-devel/2012-09/msg03196.html for the whole story. Signed-off-by: Max Filippov Signed-off-by: Aurelien Jarno --- tcg/README | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tcg/README b/tcg/README index d03ae05e34..33783ee17b 100644 --- a/tcg/README +++ b/tcg/README @@ -392,7 +392,8 @@ Exit the current TB and return the value t0 (word type). Exit the current TB and jump to the TB index 'index' (constant) if the current TB was linked to this TB. Otherwise execute the next -instructions. +instructions. Only indices 0 and 1 are valid and tcg_gen_goto_tb may be issued +at most once with each slot index per TB. * qemu_ld8u t0, t1, flags qemu_ld8s t0, t1, flags From 1b7621ad99d352629c096cba40eadc6fb2b0c294 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 13 Sep 2012 19:37:43 +0200 Subject: [PATCH 0513/2270] w64: Fix TCG helper functions with 5 arguments TCG uses 6 registers for function arguments on 64 bit Linux hosts, but only 4 registers on W64 hosts. Commit 2999a0b20074a7e4a58f56572bb1436749368f59 increased the number of arguments for some important helper functions from 4 to 5 which triggered a bug for W64 hosts: QEMU aborts when executing helper_lcall_real in the guest's BIOS because function tcg_target_get_call_iarg_regs_count always returned 6. As W64 has only 4 registers for arguments, the 5th argument must be passed on the stack using a correct stack offset. Signed-off-by: Stefan Weil Signed-off-by: Aurelien Jarno --- tcg/i386/tcg-target.c | 2 +- tcg/i386/tcg-target.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index aa1fa9ff4c..85c6b8159e 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -118,7 +118,7 @@ static void patch_reloc(uint8_t *code_ptr, int type, static inline int tcg_target_get_call_iarg_regs_count(int flags) { if (TCG_TARGET_REG_BITS == 64) { - return 6; + return ARRAY_SIZE(tcg_target_call_iarg_regs); } return 0; diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index b356d76312..ace63ba37b 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -67,7 +67,11 @@ typedef enum { /* used for function call generation */ #define TCG_REG_CALL_STACK TCG_REG_ESP #define TCG_TARGET_STACK_ALIGN 16 +#if defined(_WIN64) +#define TCG_TARGET_CALL_STACK_OFFSET 32 +#else #define TCG_TARGET_CALL_STACK_OFFSET 0 +#endif /* optional instructions */ #define TCG_TARGET_HAS_div2_i32 1 From b18212c66870f119111e0777fcc19462ae07eb70 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 13 Sep 2012 19:37:44 +0200 Subject: [PATCH 0514/2270] tcg/i386: Add shortcuts for registers used in L constraint While 64 bit hosts use the first three registers which are also used as function input parameters, 32 bit hosts use TCG_REG_EAX and TCG_REG_EDX which are not used in parameter passing. After defining new register macros for the registers used in L constraint, the patch replaces most occurrences of tcg_target_call_iarg_regs[0], tcg_target_call_iarg_regs[1] and tcg_target_call_iarg_regs[2] by those new macros. tcg_target_call_iarg_regs remains unchanged when it is used for input arguments (only with 64 bit hosts) before tcg_out_calli. A comment related to those registers was fixed, too. Signed-off-by: Stefan Weil [aurel32: build fix on i386, small optimization for i386 in the prologue] Signed-off-by: Aurelien Jarno --- tcg/i386/tcg-target.c | 96 +++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 85c6b8159e..a87c8ba10c 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -88,6 +88,18 @@ static const int tcg_target_call_oarg_regs[] = { #endif }; +/* Registers used with L constraint, which are the first argument + registers on x86_64, and two random call clobbered registers on + i386. */ +#if TCG_TARGET_REG_BITS == 64 +# define TCG_REG_L0 tcg_target_call_iarg_regs[0] +# define TCG_REG_L1 tcg_target_call_iarg_regs[1] +# define TCG_REG_L2 tcg_target_call_iarg_regs[2] +#else +# define TCG_REG_L0 TCG_REG_EAX +# define TCG_REG_L1 TCG_REG_EDX +#endif + static uint8_t *tb_ret_addr; static void patch_reloc(uint8_t *code_ptr, int type, @@ -179,16 +191,16 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) /* qemu_ld/st address constraint */ case 'L': ct->ct |= TCG_CT_REG; - if (TCG_TARGET_REG_BITS == 64) { +#if TCG_TARGET_REG_BITS == 64 tcg_regset_set32(ct->u.regs, 0, 0xffff); - tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[0]); - tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[1]); - tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[2]); - } else { + tcg_regset_reset_reg(ct->u.regs, TCG_REG_L0); + tcg_regset_reset_reg(ct->u.regs, TCG_REG_L1); + tcg_regset_reset_reg(ct->u.regs, TCG_REG_L2); +#else tcg_regset_set32(ct->u.regs, 0, 0xff); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_EDX); - } + tcg_regset_reset_reg(ct->u.regs, TCG_REG_L0); + tcg_regset_reset_reg(ct->u.regs, TCG_REG_L1); +#endif break; case 'e': @@ -1029,8 +1041,8 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx, uint8_t **label_ptr, int which) { const int addrlo = args[addrlo_idx]; - const int r0 = tcg_target_call_iarg_regs[0]; - const int r1 = tcg_target_call_iarg_regs[1]; + const int r0 = TCG_REG_L0; + const int r1 = TCG_REG_L1; TCGType type = TCG_TYPE_I32; int rexw = 0; @@ -1192,8 +1204,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, label_ptr, offsetof(CPUTLBEntry, addr_read)); /* TLB Hit. */ - tcg_out_qemu_ld_direct(s, data_reg, data_reg2, - tcg_target_call_iarg_regs[0], 0, opc); + tcg_out_qemu_ld_direct(s, data_reg, data_reg2, TCG_REG_L0, 0, opc); /* jmp label2 */ tcg_out8(s, OPC_JMP_short); @@ -1226,14 +1237,10 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx], mem_index); /* XXX/FIXME: suboptimal */ - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3], - tcg_target_call_iarg_regs[2]); - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], - tcg_target_call_iarg_regs[1]); - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1], - tcg_target_call_iarg_regs[0]); - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], - TCG_AREG0); + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3], TCG_REG_L2); + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], TCG_REG_L1); + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1], TCG_REG_L0); + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0); #endif tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]); @@ -1299,11 +1306,9 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, use the ADDR32 prefix. For now, do nothing. */ if (offset != GUEST_BASE) { - tcg_out_movi(s, TCG_TYPE_I64, - tcg_target_call_iarg_regs[0], GUEST_BASE); - tgen_arithr(s, ARITH_ADD + P_REXW, - tcg_target_call_iarg_regs[0], base); - base = tcg_target_call_iarg_regs[0]; + tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L0, GUEST_BASE); + tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L0, base); + base = TCG_REG_L0; offset = 0; } } @@ -1324,8 +1329,8 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi, /* ??? Ideally we wouldn't need a scratch register. For user-only, we could perform the bswap twice to restore the original value instead of moving to the scratch. But as it is, the L constraint - means that the second argument reg is definitely free here. */ - int scratch = tcg_target_call_iarg_regs[1]; + means that TCG_REG_L1 is definitely free here. */ + const int scratch = TCG_REG_L1; switch (sizeop) { case 0: @@ -1398,8 +1403,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, label_ptr, offsetof(CPUTLBEntry, addr_write)); /* TLB Hit. */ - tcg_out_qemu_st_direct(s, data_reg, data_reg2, - tcg_target_call_iarg_regs[0], 0, opc); + tcg_out_qemu_st_direct(s, data_reg, data_reg2, TCG_REG_L0, 0, opc); /* jmp label2 */ tcg_out8(s, OPC_JMP_short); @@ -1434,18 +1438,14 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, stack_adjust += 4; #else tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32), - tcg_target_call_iarg_regs[1], data_reg); - tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], mem_index); + TCG_REG_L1, data_reg); + tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_L2, mem_index); stack_adjust = 0; /* XXX/FIXME: suboptimal */ - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3], - tcg_target_call_iarg_regs[2]); - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], - tcg_target_call_iarg_regs[1]); - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1], - tcg_target_call_iarg_regs[0]); - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], - TCG_AREG0); + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3], TCG_REG_L2); + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], TCG_REG_L1); + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1], TCG_REG_L0); + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0); #endif tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]); @@ -1472,11 +1472,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, use the ADDR32 prefix. For now, do nothing. */ if (offset != GUEST_BASE) { - tcg_out_movi(s, TCG_TYPE_I64, - tcg_target_call_iarg_regs[0], GUEST_BASE); - tgen_arithr(s, ARITH_ADD + P_REXW, - tcg_target_call_iarg_regs[0], base); - base = tcg_target_call_iarg_regs[0]; + tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L0, GUEST_BASE); + tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L0, base); + base = TCG_REG_L0; offset = 0; } } @@ -2061,15 +2059,17 @@ static void tcg_target_qemu_prologue(TCGContext *s) #if TCG_TARGET_REG_BITS == 32 tcg_out_ld(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP, (ARRAY_SIZE(tcg_target_callee_save_regs) + 1) * 4); - tcg_out_ld(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[1], TCG_REG_ESP, - (ARRAY_SIZE(tcg_target_callee_save_regs) + 2) * 4); + tcg_out_addi(s, TCG_REG_ESP, -stack_addend); + /* jmp *tb. */ + tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, TCG_REG_ESP, + (ARRAY_SIZE(tcg_target_callee_save_regs) + 2) * 4 + + stack_addend); #else tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); -#endif tcg_out_addi(s, TCG_REG_ESP, -stack_addend); - /* jmp *tb. */ tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[1]); +#endif /* TB epilogue */ tb_ret_addr = s->code_ptr; From d73685e3c3936fd7851a32eff5443405cb5368be Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 13 Sep 2012 19:37:45 +0200 Subject: [PATCH 0515/2270] tcg/i386: Remove unused registers from tcg_target_call_iarg_regs 32 bit x86 hosts don't need registers for helper function arguments because they use the default stack based calling convention. Removing the registers allows simpler code for function tcg_target_get_call_iarg_regs_count. Signed-off-by: Stefan Weil Signed-off-by: Aurelien Jarno --- tcg/i386/tcg-target.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index a87c8ba10c..43c97190aa 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -75,9 +75,7 @@ static const int tcg_target_call_iarg_regs[] = { TCG_REG_R8, TCG_REG_R9, #else - TCG_REG_EAX, - TCG_REG_EDX, - TCG_REG_ECX + /* 32 bit mode uses stack based calling convention (GCC default). */ #endif }; @@ -129,11 +127,7 @@ static void patch_reloc(uint8_t *code_ptr, int type, /* maximum number of register used for input function arguments */ static inline int tcg_target_get_call_iarg_regs_count(int flags) { - if (TCG_TARGET_REG_BITS == 64) { - return ARRAY_SIZE(tcg_target_call_iarg_regs); - } - - return 0; + return ARRAY_SIZE(tcg_target_call_iarg_regs); } /* parse target specific constraints */ From 6e17d0c5cdf7b3d0086708ba1d2df931e18cb5b5 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 13 Sep 2012 19:37:46 +0200 Subject: [PATCH 0516/2270] tcg: Remove tcg_target_get_call_iarg_regs_count The TCG targets no longer need individual implementations. Since commit 6a18ae2d2947532d5c26439548afa0481c4529f9, 'flags' is no longer used in tcg_target_get_call_iarg_regs_count. The remaining tcg_target_get_call_iarg_regs_count is trivial and only called once. Therefore the patch eliminates it completely. Signed-off-by: Stefan Weil Signed-off-by: Aurelien Jarno --- tcg/arm/tcg-target.c | 6 ------ tcg/hppa/tcg-target.c | 6 ------ tcg/i386/tcg-target.c | 6 ------ tcg/ia64/tcg-target.c | 6 ------ tcg/mips/tcg-target.c | 6 ------ tcg/ppc/tcg-target.c | 6 ------ tcg/ppc64/tcg-target.c | 6 ------ tcg/s390/tcg-target.c | 5 ----- tcg/sparc/tcg-target.c | 6 ------ tcg/tcg.c | 3 +-- tcg/tci/tcg-target.c | 6 ------ 11 files changed, 1 insertion(+), 61 deletions(-) diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index aed3b53247..2bad0a2b17 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -145,12 +145,6 @@ static void patch_reloc(uint8_t *code_ptr, int type, } } -/* maximum number of register used for input function arguments */ -static inline int tcg_target_get_call_iarg_regs_count(int flags) -{ - return 4; -} - /* parse target specific constraints */ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) { diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c index 793b90da45..2c79c1081e 100644 --- a/tcg/hppa/tcg-target.c +++ b/tcg/hppa/tcg-target.c @@ -175,12 +175,6 @@ static void patch_reloc(uint8_t *code_ptr, int type, *insn_ptr = insn; } -/* maximum number of register used for input function arguments */ -static inline int tcg_target_get_call_iarg_regs_count(int flags) -{ - return 4; -} - /* parse target specific constraints */ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) { diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 43c97190aa..122d63630c 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -124,12 +124,6 @@ static void patch_reloc(uint8_t *code_ptr, int type, } } -/* maximum number of register used for input function arguments */ -static inline int tcg_target_get_call_iarg_regs_count(int flags) -{ - return ARRAY_SIZE(tcg_target_call_iarg_regs); -} - /* parse target specific constraints */ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) { diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 1745038f14..dc9c12cf18 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -176,12 +176,6 @@ static const int tcg_target_call_oarg_regs[] = { TCG_REG_R8 }; -/* maximum number of register used for input function arguments */ -static inline int tcg_target_get_call_iarg_regs_count(int flags) -{ - return 8; -} - /* * opcode formation */ diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index c272b38a7d..f70910a90f 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -185,12 +185,6 @@ static void patch_reloc(uint8_t *code_ptr, int type, } } -/* maximum number of register used for input function arguments */ -static inline int tcg_target_get_call_iarg_regs_count(int flags) -{ - return 4; -} - /* parse target specific constraints */ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) { diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 26c4b33e60..ec028670dd 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -221,12 +221,6 @@ static void patch_reloc(uint8_t *code_ptr, int type, } } -/* maximum number of register used for input function arguments */ -static int tcg_target_get_call_iarg_regs_count(int flags) -{ - return ARRAY_SIZE (tcg_target_call_iarg_regs); -} - /* parse target specific constraints */ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) { diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c index 337cd419f8..19944bc427 100644 --- a/tcg/ppc64/tcg-target.c +++ b/tcg/ppc64/tcg-target.c @@ -208,12 +208,6 @@ static void patch_reloc (uint8_t *code_ptr, int type, } } -/* maximum number of register used for input function arguments */ -static int tcg_target_get_call_iarg_regs_count (int flags) -{ - return ARRAY_SIZE (tcg_target_call_iarg_regs); -} - /* parse target specific constraints */ static int target_parse_constraint (TCGArgConstraint *ct, const char **pct_str) { diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c index aac11d9b61..3b90605fb1 100644 --- a/tcg/s390/tcg-target.c +++ b/tcg/s390/tcg-target.c @@ -356,11 +356,6 @@ static void patch_reloc(uint8_t *code_ptr, int type, } } -static int tcg_target_get_call_iarg_regs_count(int flags) -{ - return sizeof(tcg_target_call_iarg_regs) / sizeof(int); -} - /* parse target specific constraints */ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) { diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index baed3b49ff..014bbfd25e 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -133,12 +133,6 @@ static void patch_reloc(uint8_t *code_ptr, int type, } } -/* maximum number of register used for input function arguments */ -static inline int tcg_target_get_call_iarg_regs_count(int flags) -{ - return 6; -} - /* parse target specific constraints */ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) { diff --git a/tcg/tcg.c b/tcg/tcg.c index 4afd035877..6edf170008 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -89,7 +89,6 @@ static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, tcg_target_long arg2); static int tcg_target_const_match(tcg_target_long val, const TCGArgConstraint *arg_ct); -static int tcg_target_get_call_iarg_regs_count(int flags); TCGOpDef tcg_op_defs[] = { #define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags }, @@ -1853,7 +1852,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, flags = args[nb_oargs + nb_iargs]; - nb_regs = tcg_target_get_call_iarg_regs_count(flags); + nb_regs = ARRAY_SIZE(tcg_target_call_iarg_regs); if (nb_regs > nb_params) nb_regs = nb_params; diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c index 003244cb0b..3f4a24bb8b 100644 --- a/tcg/tci/tcg-target.c +++ b/tcg/tci/tcg-target.c @@ -863,12 +863,6 @@ static int tcg_target_const_match(tcg_target_long val, return arg_ct->ct & TCG_CT_CONST; } -/* Maximum number of register used for input function arguments. */ -static int tcg_target_get_call_iarg_regs_count(int flags) -{ - return ARRAY_SIZE(tcg_target_call_iarg_regs); -} - static void tcg_target_init(TCGContext *s) { #if defined(CONFIG_DEBUG_TCG_INTERPRETER) From ad49d1f75115663731bfe06dec61eed6775526ad Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 22 Sep 2012 17:07:23 +0200 Subject: [PATCH 0517/2270] tcg/mips --- tcg/mips/tcg-target.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index f70910a90f..dc80abd637 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -1681,8 +1681,8 @@ static void tcg_target_qemu_prologue(TCGContext *s) + CPU_TEMP_BUF_NLONGS * sizeof(long); frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & ~(TCG_TARGET_STACK_ALIGN - 1); - tcg_set_frame(s, TCG_REG_SP, ARRAY_SIZE(tcg_target_callee_save_regs) * 4 - + TCG_STATIC_CALL_ARGS_SIZE, + tcg_set_frame(s, TCG_REG_SP, frame_size + - CPU_TEMP_BUF_NLONGS * sizeof(long), CPU_TEMP_BUF_NLONGS * sizeof(long)); /* TB prologue */ From 23f3ff2604679a0ba7a23be7576529169e5e7921 Mon Sep 17 00:00:00 2001 From: malc Date: Sat, 22 Sep 2012 19:14:33 +0400 Subject: [PATCH 0518/2270] tcg/ppc32: Implement movcond32 Thanks to Richard Henderson Signed-off-by: malc --- tcg/ppc/tcg-target.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ tcg/ppc/tcg-target.h | 2 +- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index ec028670dd..90c275d698 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -384,6 +384,7 @@ static int tcg_target_const_match(tcg_target_long val, #define ORC XO31(412) #define EQV XO31(284) #define NAND XO31(476) +#define ISEL XO31( 15) #define LBZX XO31( 87) #define LHZX XO31(279) @@ -1263,6 +1264,72 @@ static void tcg_out_setcond2 (TCGContext *s, const TCGArg *args, ); } +static void tcg_out_movcond (TCGContext *s, TCGCond cond, + TCGArg dest, + TCGArg c1, TCGArg c2, + TCGArg v1, TCGArg v2, + int const_c2) +{ + tcg_out_cmp (s, cond, c1, c2, const_c2, 7); + + if (1) { + /* At least here on 7747A bit twiddling hacks are outperformed + by jumpy code (the testing was not scientific) */ + if (dest == v2) { + cond = tcg_invert_cond (cond); + v2 = v1; + } + else { + if (dest != v1) { + tcg_out_mov (s, TCG_TYPE_I32, dest, v1); + } + } + /* Branch forward over one insn */ + tcg_out32 (s, tcg_to_bc[cond] | 8); + tcg_out_mov (s, TCG_TYPE_I32, dest, v2); + } + else { + /* isel version, "if (1)" above should be replaced once a way + to figure out availability of isel on the underlying + hardware is found */ + int tab, bc; + + switch (cond) { + case TCG_COND_EQ: + tab = TAB (dest, v1, v2); + bc = CR_EQ; + break; + case TCG_COND_NE: + tab = TAB (dest, v2, v1); + bc = CR_EQ; + break; + case TCG_COND_LTU: + case TCG_COND_LT: + tab = TAB (dest, v1, v2); + bc = CR_LT; + break; + case TCG_COND_GEU: + case TCG_COND_GE: + tab = TAB (dest, v2, v1); + bc = CR_LT; + break; + case TCG_COND_LEU: + case TCG_COND_LE: + tab = TAB (dest, v2, v1); + bc = CR_GT; + break; + case TCG_COND_GTU: + case TCG_COND_GT: + tab = TAB (dest, v1, v2); + bc = CR_GT; + break; + default: + tcg_abort (); + } + tcg_out32 (s, ISEL | tab | ((bc + 28) << 6)); + } +} + static void tcg_out_brcond (TCGContext *s, TCGCond cond, TCGArg arg1, TCGArg arg2, int const_arg2, int label_index) @@ -1820,6 +1887,13 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, ); break; + case INDEX_op_movcond_i32: + tcg_out_movcond (s, args[5], args[0], + args[1], args[2], + args[3], args[4], + const_args[2]); + break; + default: tcg_dump_ops (s); tcg_abort (); @@ -1916,6 +1990,7 @@ static const TCGTargetOpDef ppc_op_defs[] = { { INDEX_op_ext16u_i32, { "r", "r" } }, { INDEX_op_deposit_i32, { "r", "0", "r" } }, + { INDEX_op_movcond_i32, { "r", "r", "ri", "r", "r" } }, { -1 }, }; diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h index 177eea1d79..3259d898ab 100644 --- a/tcg/ppc/tcg-target.h +++ b/tcg/ppc/tcg-target.h @@ -92,7 +92,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 1 #define TCG_TARGET_HAS_nor_i32 1 #define TCG_TARGET_HAS_deposit_i32 1 -#define TCG_TARGET_HAS_movcond_i32 0 +#define TCG_TARGET_HAS_movcond_i32 1 #define TCG_AREG0 TCG_REG_R27 From e809c0dc70522cba07dc2f16f677d1adf01523fc Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 22 Sep 2012 19:24:49 +0200 Subject: [PATCH 0519/2270] Revert "tcg/mips" This reverts commit ad49d1f75115663731bfe06dec61eed6775526ad. This commit was not supposed to be pushed. Signed-off-by: Aurelien Jarno --- tcg/mips/tcg-target.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index dc80abd637..f70910a90f 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -1681,8 +1681,8 @@ static void tcg_target_qemu_prologue(TCGContext *s) + CPU_TEMP_BUF_NLONGS * sizeof(long); frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & ~(TCG_TARGET_STACK_ALIGN - 1); - tcg_set_frame(s, TCG_REG_SP, frame_size - - CPU_TEMP_BUF_NLONGS * sizeof(long), + tcg_set_frame(s, TCG_REG_SP, ARRAY_SIZE(tcg_target_callee_save_regs) * 4 + + TCG_STATIC_CALL_ARGS_SIZE, CPU_TEMP_BUF_NLONGS * sizeof(long)); /* TB prologue */ From 66176802960ad1f7c3d061d17b784088c2e28d59 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 19 Sep 2012 04:23:50 +0400 Subject: [PATCH 0520/2270] softfloat: make float_muladd_negate_* flags independent Flags passed into float{32,64}_muladd are treated as bits; assign independent bits to float_muladd_negate_* to allow precise control over what gets negated in float{32,64}_muladd. Signed-off-by: Max Filippov Reviewed-by: Aurelien Jarno Signed-off-by: Blue Swirl --- fpu/softfloat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpu/softfloat.h b/fpu/softfloat.h index feec3a180e..2860ca0175 100644 --- a/fpu/softfloat.h +++ b/fpu/softfloat.h @@ -219,7 +219,7 @@ void float_raise( int8 flags STATUS_PARAM); enum { float_muladd_negate_c = 1, float_muladd_negate_product = 2, - float_muladd_negate_result = 3, + float_muladd_negate_result = 4, }; /*---------------------------------------------------------------------------- From 213ff4e6df0f74e93995a5d3d7429acb4ad3ee86 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 19 Sep 2012 04:23:51 +0400 Subject: [PATCH 0521/2270] softfloat: add NO_SIGNALING_NANS Architectures that don't have signaling NaNs can define NO_SIGNALING_NANS, it will make float*_is_quiet_nan return 1 for any NaN and float*_is_signaling_nan always return 0. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl --- fpu/softfloat-specialize.h | 67 ++++++++++++++++++++++++++++++++++++++ fpu/softfloat.h | 5 +++ 2 files changed, 72 insertions(+) diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h index 490245004f..50b54b8791 100644 --- a/fpu/softfloat-specialize.h +++ b/fpu/softfloat-specialize.h @@ -41,6 +41,13 @@ these four paragraphs for those parts of this code that are retained. #define SNAN_BIT_IS_ONE 0 #endif +#if defined(TARGET_XTENSA) +/* Define for architectures which deviate from IEEE in not supporting + * signaling NaNs (so all NaNs are treated as quiet). + */ +#define NO_SIGNALING_NANS 1 +#endif + /*---------------------------------------------------------------------------- | The pattern for a default generated half-precision NaN. *----------------------------------------------------------------------------*/ @@ -127,6 +134,17 @@ typedef struct { uint64_t high, low; } commonNaNT; +#ifdef NO_SIGNALING_NANS +int float16_is_quiet_nan(float16 a_) +{ + return float16_is_any_nan(a_); +} + +int float16_is_signaling_nan(float16 a_) +{ + return 0; +} +#else /*---------------------------------------------------------------------------- | Returns 1 if the half-precision floating-point value `a' is a quiet | NaN; otherwise returns 0. @@ -156,6 +174,7 @@ int float16_is_signaling_nan(float16 a_) return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF); #endif } +#endif /*---------------------------------------------------------------------------- | Returns a quiet NaN if the half-precision floating point value `a' is a @@ -217,6 +236,17 @@ static float16 commonNaNToFloat16(commonNaNT a STATUS_PARAM) } } +#ifdef NO_SIGNALING_NANS +int float32_is_quiet_nan(float32 a_) +{ + return float32_is_any_nan(a_); +} + +int float32_is_signaling_nan(float32 a_) +{ + return 0; +} +#else /*---------------------------------------------------------------------------- | Returns 1 if the single-precision floating-point value `a' is a quiet | NaN; otherwise returns 0. @@ -246,6 +276,7 @@ int float32_is_signaling_nan( float32 a_ ) return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); #endif } +#endif /*---------------------------------------------------------------------------- | Returns a quiet NaN if the single-precision floating point value `a' is a @@ -586,6 +617,17 @@ static float32 propagateFloat32MulAddNaN(float32 a, float32 b, } } +#ifdef NO_SIGNALING_NANS +int float64_is_quiet_nan(float64 a_) +{ + return float64_is_any_nan(a_); +} + +int float64_is_signaling_nan(float64 a_) +{ + return 0; +} +#else /*---------------------------------------------------------------------------- | Returns 1 if the double-precision floating-point value `a' is a quiet | NaN; otherwise returns 0. @@ -619,6 +661,7 @@ int float64_is_signaling_nan( float64 a_ ) && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); #endif } +#endif /*---------------------------------------------------------------------------- | Returns a quiet NaN if the double-precision floating point value `a' is a @@ -773,6 +816,17 @@ static float64 propagateFloat64MulAddNaN(float64 a, float64 b, } } +#ifdef NO_SIGNALING_NANS +int floatx80_is_quiet_nan(floatx80 a_) +{ + return floatx80_is_any_nan(a_); +} + +int floatx80_is_signaling_nan(floatx80 a_) +{ + return 0; +} +#else /*---------------------------------------------------------------------------- | Returns 1 if the extended double-precision floating-point value `a' is a | quiet NaN; otherwise returns 0. This slightly differs from the same @@ -816,6 +870,7 @@ int floatx80_is_signaling_nan( floatx80 a ) && ( a.low == aLow ); #endif } +#endif /*---------------------------------------------------------------------------- | Returns a quiet NaN if the extended double-precision floating point value @@ -929,6 +984,17 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM) } } +#ifdef NO_SIGNALING_NANS +int float128_is_quiet_nan(float128 a_) +{ + return float128_is_any_nan(a_); +} + +int float128_is_signaling_nan(float128 a_) +{ + return 0; +} +#else /*---------------------------------------------------------------------------- | Returns 1 if the quadruple-precision floating-point value `a' is a quiet | NaN; otherwise returns 0. @@ -964,6 +1030,7 @@ int float128_is_signaling_nan( float128 a ) && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); #endif } +#endif /*---------------------------------------------------------------------------- | Returns a quiet NaN if the quadruple-precision floating point value `a' is diff --git a/fpu/softfloat.h b/fpu/softfloat.h index 2860ca0175..d8999b311a 100644 --- a/fpu/softfloat.h +++ b/fpu/softfloat.h @@ -251,6 +251,11 @@ int float16_is_quiet_nan( float16 ); int float16_is_signaling_nan( float16 ); float16 float16_maybe_silence_nan( float16 ); +INLINE int float16_is_any_nan(float16 a) +{ + return ((float16_val(a) & ~0x8000) > 0x7c00); +} + /*---------------------------------------------------------------------------- | The pattern for a default generated half-precision NaN. *----------------------------------------------------------------------------*/ From 10f6ca034089e201aaff1da5ed99b127811081d5 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 19 Sep 2012 04:23:52 +0400 Subject: [PATCH 0522/2270] target-xtensa: handle boolean option in overlays Signed-off-by: Max Filippov Signed-off-by: Blue Swirl --- target-xtensa/overlay_tool.h | 1 + 1 file changed, 1 insertion(+) diff --git a/target-xtensa/overlay_tool.h b/target-xtensa/overlay_tool.h index a3a5650fb0..e39505316b 100644 --- a/target-xtensa/overlay_tool.h +++ b/target-xtensa/overlay_tool.h @@ -58,6 +58,7 @@ XCHAL_OPTION(XCHAL_HAVE_SEXT, XTENSA_OPTION_MISC_OP_SEXT) | \ XCHAL_OPTION(XCHAL_HAVE_CLAMPS, XTENSA_OPTION_MISC_OP_CLAMPS) | \ XCHAL_OPTION(XCHAL_HAVE_CP, XTENSA_OPTION_COPROCESSOR) | \ + XCHAL_OPTION(XCHAL_HAVE_BOOLEANS, XTENSA_OPTION_BOOLEAN) | \ XCHAL_OPTION(XCHAL_HAVE_FP, XTENSA_OPTION_FP_COPROCESSOR) | \ XCHAL_OPTION(XCHAL_HAVE_RELEASE_SYNC, XTENSA_OPTION_MP_SYNCHRO) | \ XCHAL_OPTION(XCHAL_HAVE_S32C1I, XTENSA_OPTION_CONDITIONAL_STORE) | \ From b81fe822dad134871cd336e26ed55d165e597f4e Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 19 Sep 2012 04:23:53 +0400 Subject: [PATCH 0523/2270] target-xtensa: specialize softfloat NaN rules NaN propagation rule: leftmost NaN in the expression gets propagated to the result. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl --- fpu/softfloat-specialize.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h index 50b54b8791..a1d489e425 100644 --- a/fpu/softfloat-specialize.h +++ b/fpu/softfloat-specialize.h @@ -64,7 +64,8 @@ const float16 float16_default_nan = const_float16(0xFE00); *----------------------------------------------------------------------------*/ #if defined(TARGET_SPARC) const float32 float32_default_nan = const_float32(0x7FFFFFFF); -#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) +#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \ + defined(TARGET_XTENSA) const float32 float32_default_nan = const_float32(0x7FC00000); #elif SNAN_BIT_IS_ONE const float32 float32_default_nan = const_float32(0x7FBFFFFF); @@ -403,7 +404,7 @@ static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, return 1; } } -#elif defined(TARGET_PPC) +#elif defined(TARGET_PPC) || defined(TARGET_XTENSA) static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, flag aIsLargerSignificand) { From dd519cbec63434f2b883f0b4a20f827bbd59793e Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 19 Sep 2012 04:23:54 +0400 Subject: [PATCH 0524/2270] target-xtensa: add FP registers There are 16 32-bit FP registers (f0 - f15), control and status user registers (fcr, fsr). See ISA, 4.3.10 for more details. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl --- gdbstub.c | 8 ++++++ target-xtensa/cpu.h | 3 +++ target-xtensa/helper.h | 2 ++ target-xtensa/op_helper.c | 13 ++++++++++ target-xtensa/translate.c | 52 +++++++++++++++++++++++++++++++++------ 5 files changed, 71 insertions(+), 7 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index a91709f271..d02ec75384 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -1696,6 +1696,10 @@ static int cpu_gdb_read_register(CPUXtensaState *env, uint8_t *mem_buf, int n) GET_REG32(env->uregs[reg->targno & 0xff]); break; + case 4: /*f*/ + GET_REG32(float32_val(env->fregs[reg->targno & 0x0f])); + break; + case 8: /*a*/ GET_REG32(env->regs[reg->targno & 0x0f]); break; @@ -1736,6 +1740,10 @@ static int cpu_gdb_write_register(CPUXtensaState *env, uint8_t *mem_buf, int n) env->uregs[reg->targno & 0xff] = tmp; break; + case 4: /*f*/ + env->fregs[reg->targno & 0x0f] = make_float32(tmp); + break; + case 8: /*a*/ env->regs[reg->targno & 0x0f] = tmp; break; diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h index 177094ae9a..b4562832b3 100644 --- a/target-xtensa/cpu.h +++ b/target-xtensa/cpu.h @@ -36,6 +36,7 @@ #include "config.h" #include "qemu-common.h" #include "cpu-defs.h" +#include "fpu/softfloat.h" #define TARGET_HAS_ICE 1 @@ -325,6 +326,8 @@ typedef struct CPUXtensaState { uint32_t sregs[256]; uint32_t uregs[256]; uint32_t phys_regs[MAX_NAREG]; + float32 fregs[16]; + float_status fp_status; xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE]; xtensa_tlb_entry dtlb[10][MAX_TLB_WAY_SIZE]; diff --git a/target-xtensa/helper.h b/target-xtensa/helper.h index 152fec044d..1662552c8e 100644 --- a/target-xtensa/helper.h +++ b/target-xtensa/helper.h @@ -36,4 +36,6 @@ DEF_HELPER_3(wsr_ibreaka, void, env, i32, i32) DEF_HELPER_3(wsr_dbreaka, void, env, i32, i32) DEF_HELPER_3(wsr_dbreakc, void, env, i32, i32) +DEF_HELPER_2(wur_fcr, void, env, i32) + #include "def-helper.h" diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c index 2659c0e00f..3bf7339511 100644 --- a/target-xtensa/op_helper.c +++ b/target-xtensa/op_helper.c @@ -771,3 +771,16 @@ void HELPER(wsr_dbreakc)(CPUXtensaState *env, uint32_t i, uint32_t v) } env->sregs[DBREAKC + i] = v; } + +void HELPER(wur_fcr)(CPUXtensaState *env, uint32_t v) +{ + static const int rounding_mode[] = { + float_round_nearest_even, + float_round_to_zero, + float_round_up, + float_round_down, + }; + + env->uregs[FCR] = v & 0xfffff07f; + set_float_rounding_mode(rounding_mode[v & 3], &env->fp_status); +} diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index b6643eb818..74b1b54b46 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -70,6 +70,7 @@ typedef struct DisasContext { static TCGv_ptr cpu_env; static TCGv_i32 cpu_pc; static TCGv_i32 cpu_R[16]; +static TCGv_i32 cpu_FR[16]; static TCGv_i32 cpu_SR[256]; static TCGv_i32 cpu_UR[256]; @@ -155,6 +156,12 @@ void xtensa_translate_init(void) "ar8", "ar9", "ar10", "ar11", "ar12", "ar13", "ar14", "ar15", }; + static const char * const fregnames[] = { + "f0", "f1", "f2", "f3", + "f4", "f5", "f6", "f7", + "f8", "f9", "f10", "f11", + "f12", "f13", "f14", "f15", + }; int i; cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); @@ -167,6 +174,12 @@ void xtensa_translate_init(void) regnames[i]); } + for (i = 0; i < 16; i++) { + cpu_FR[i] = tcg_global_mem_new_i32(TCG_AREG0, + offsetof(CPUXtensaState, fregs[i]), + fregnames[i]); + } + for (i = 0; i < 256; ++i) { if (sregnames[i]) { cpu_SR[i] = tcg_global_mem_new_i32(TCG_AREG0, @@ -692,6 +705,23 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s) } } +static void gen_wur(uint32_t ur, TCGv_i32 s) +{ + switch (ur) { + case FCR: + gen_helper_wur_fcr(cpu_env, s); + break; + + case FSR: + tcg_gen_andi_i32(cpu_UR[ur], s, 0xffffff80); + break; + + default: + tcg_gen_mov_i32(cpu_UR[ur], s); + break; + } +} + static void gen_load_store_alignment(DisasContext *dc, int shift, TCGv_i32 addr, bool no_hw_alignment) { @@ -1761,13 +1791,11 @@ static void disas_xtensa_insn(DisasContext *dc) case 15: /*WUR*/ gen_window_check1(dc, RRR_T); - { - if (uregnames[RSR_SR]) { - tcg_gen_mov_i32(cpu_UR[RSR_SR], cpu_R[RRR_T]); - } else { - qemu_log("WUR %d not implemented, ", RSR_SR); - TBD(); - } + if (uregnames[RSR_SR]) { + gen_wur(RSR_SR, cpu_R[RRR_T]); + } else { + qemu_log("WUR %d not implemented, ", RSR_SR); + TBD(); } break; @@ -2730,6 +2758,16 @@ void cpu_dump_state(CPUXtensaState *env, FILE *f, fprintf_function cpu_fprintf, cpu_fprintf(f, "AR%02d=%08x%c", i, env->phys_regs[i], (i % 4) == 3 ? '\n' : ' '); } + + if (xtensa_option_enabled(env->config, XTENSA_OPTION_FP_COPROCESSOR)) { + cpu_fprintf(f, "\n"); + + for (i = 0; i < 16; ++i) { + cpu_fprintf(f, "F%02d=%08x (%+10.8e)%c", i, + float32_val(env->fregs[i]), + *(float *)&env->fregs[i], (i % 2) == 1 ? '\n' : ' '); + } + } } void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, int pc_pos) From 9ed7ae12afacdd234a749aa5af27dd93ea1594ec Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 19 Sep 2012 04:23:55 +0400 Subject: [PATCH 0525/2270] target-xtensa: implement LSCX and LSCI groups These are load/store instructions for FP registers with immediate or register index and optional base post-update. See ISA, 4.3.10 for more details. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl --- target-xtensa/translate.c | 58 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 74b1b54b46..0f85b36eed 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -1843,8 +1843,33 @@ static void disas_xtensa_insn(DisasContext *dc) break; case 8: /*LSCXp*/ - HAS_OPTION(XTENSA_OPTION_COPROCESSOR); - TBD(); + switch (OP2) { + case 0: /*LSXf*/ + case 1: /*LSXUf*/ + case 4: /*SSXf*/ + case 5: /*SSXUf*/ + HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR); + gen_window_check2(dc, RRR_S, RRR_T); + { + TCGv_i32 addr = tcg_temp_new_i32(); + tcg_gen_add_i32(addr, cpu_R[RRR_S], cpu_R[RRR_T]); + gen_load_store_alignment(dc, 2, addr, false); + if (OP2 & 0x4) { + tcg_gen_qemu_st32(cpu_FR[RRR_R], addr, dc->cring); + } else { + tcg_gen_qemu_ld32u(cpu_FR[RRR_R], addr, dc->cring); + } + if (OP2 & 0x1) { + tcg_gen_mov_i32(cpu_R[RRR_S], addr); + } + tcg_temp_free(addr); + } + break; + + default: /*reserved*/ + RESERVED(); + break; + } break; case 9: /*LSC4*/ @@ -2118,8 +2143,33 @@ static void disas_xtensa_insn(DisasContext *dc) break; case 3: /*LSCIp*/ - HAS_OPTION(XTENSA_OPTION_COPROCESSOR); - TBD(); + switch (RRI8_R) { + case 0: /*LSIf*/ + case 4: /*SSIf*/ + case 8: /*LSIUf*/ + case 12: /*SSIUf*/ + HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR); + gen_window_check1(dc, RRI8_S); + { + TCGv_i32 addr = tcg_temp_new_i32(); + tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2); + gen_load_store_alignment(dc, 2, addr, false); + if (RRI8_R & 0x4) { + tcg_gen_qemu_st32(cpu_FR[RRI8_T], addr, dc->cring); + } else { + tcg_gen_qemu_ld32u(cpu_FR[RRI8_T], addr, dc->cring); + } + if (RRI8_R & 0x8) { + tcg_gen_mov_i32(cpu_R[RRI8_S], addr); + } + tcg_temp_free(addr); + } + break; + + default: /*reserved*/ + RESERVED(); + break; + } break; case 4: /*MAC16d*/ From 0b6df8385d24a4eed0ff546493c59e047b16537b Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 19 Sep 2012 04:23:56 +0400 Subject: [PATCH 0526/2270] target-xtensa: implement FP0 arithmetic These are FP arithmetic opcodes. See ISA, 4.3.10 for more details. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl --- target-xtensa/helper.h | 7 +++++ target-xtensa/op_helper.c | 37 ++++++++++++++++++++++++ target-xtensa/translate.c | 61 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 104 insertions(+), 1 deletion(-) diff --git a/target-xtensa/helper.h b/target-xtensa/helper.h index 1662552c8e..4e6e4176ee 100644 --- a/target-xtensa/helper.h +++ b/target-xtensa/helper.h @@ -37,5 +37,12 @@ DEF_HELPER_3(wsr_dbreaka, void, env, i32, i32) DEF_HELPER_3(wsr_dbreakc, void, env, i32, i32) DEF_HELPER_2(wur_fcr, void, env, i32) +DEF_HELPER_FLAGS_1(abs_s, TCG_CALL_CONST | TCG_CALL_PURE, f32, f32) +DEF_HELPER_FLAGS_1(neg_s, TCG_CALL_CONST | TCG_CALL_PURE, f32, f32) +DEF_HELPER_3(add_s, f32, env, f32, f32) +DEF_HELPER_3(sub_s, f32, env, f32, f32) +DEF_HELPER_3(mul_s, f32, env, f32, f32) +DEF_HELPER_4(madd_s, f32, env, f32, f32, f32) +DEF_HELPER_4(msub_s, f32, env, f32, f32, f32) #include "def-helper.h" diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c index 3bf7339511..ba935a87ca 100644 --- a/target-xtensa/op_helper.c +++ b/target-xtensa/op_helper.c @@ -784,3 +784,40 @@ void HELPER(wur_fcr)(CPUXtensaState *env, uint32_t v) env->uregs[FCR] = v & 0xfffff07f; set_float_rounding_mode(rounding_mode[v & 3], &env->fp_status); } + +float32 HELPER(abs_s)(float32 v) +{ + return float32_abs(v); +} + +float32 HELPER(neg_s)(float32 v) +{ + return float32_chs(v); +} + +float32 HELPER(add_s)(CPUXtensaState *env, float32 a, float32 b) +{ + return float32_add(a, b, &env->fp_status); +} + +float32 HELPER(sub_s)(CPUXtensaState *env, float32 a, float32 b) +{ + return float32_sub(a, b, &env->fp_status); +} + +float32 HELPER(mul_s)(CPUXtensaState *env, float32 a, float32 b) +{ + return float32_mul(a, b, &env->fp_status); +} + +float32 HELPER(madd_s)(CPUXtensaState *env, float32 a, float32 b, float32 c) +{ + return float32_muladd(b, c, a, 0, + &env->fp_status); +} + +float32 HELPER(msub_s)(CPUXtensaState *env, float32 a, float32 b, float32 c) +{ + return float32_muladd(b, c, a, float_muladd_negate_product, + &env->fp_status); +} diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 0f85b36eed..2125b1d00a 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -1907,7 +1907,66 @@ static void disas_xtensa_insn(DisasContext *dc) case 10: /*FP0*/ HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR); - TBD(); + switch (OP2) { + case 0: /*ADD.Sf*/ + gen_helper_add_s(cpu_FR[RRR_R], cpu_env, + cpu_FR[RRR_S], cpu_FR[RRR_T]); + break; + + case 1: /*SUB.Sf*/ + gen_helper_sub_s(cpu_FR[RRR_R], cpu_env, + cpu_FR[RRR_S], cpu_FR[RRR_T]); + break; + + case 2: /*MUL.Sf*/ + gen_helper_mul_s(cpu_FR[RRR_R], cpu_env, + cpu_FR[RRR_S], cpu_FR[RRR_T]); + break; + + case 4: /*MADD.Sf*/ + gen_helper_madd_s(cpu_FR[RRR_R], cpu_env, + cpu_FR[RRR_R], cpu_FR[RRR_S], cpu_FR[RRR_T]); + break; + + case 5: /*MSUB.Sf*/ + gen_helper_msub_s(cpu_FR[RRR_R], cpu_env, + cpu_FR[RRR_R], cpu_FR[RRR_S], cpu_FR[RRR_T]); + break; + + case 15: /*FP1OP*/ + switch (RRR_T) { + case 0: /*MOV.Sf*/ + tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_FR[RRR_S]); + break; + + case 1: /*ABS.Sf*/ + gen_helper_abs_s(cpu_FR[RRR_R], cpu_FR[RRR_S]); + break; + + case 4: /*RFRf*/ + gen_window_check1(dc, RRR_R); + tcg_gen_mov_i32(cpu_R[RRR_R], cpu_FR[RRR_S]); + break; + + case 5: /*WFRf*/ + gen_window_check1(dc, RRR_S); + tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_R[RRR_S]); + break; + + case 6: /*NEG.Sf*/ + gen_helper_neg_s(cpu_FR[RRR_R], cpu_FR[RRR_S]); + break; + + default: /*reserved*/ + RESERVED(); + break; + } + break; + + default: /*reserved*/ + RESERVED(); + break; + } break; case 11: /*FP1*/ From b7ee8c6a32987e5039f0a2c2976fad556965727d Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 19 Sep 2012 04:23:57 +0400 Subject: [PATCH 0527/2270] target-xtensa: implement FP0 conversions These are FP to integer and integer to FP conversion opcodes. See ISA, 4.3.10 for more details. Note that ISA description for utrunc.s is currently incorrect and will be fixed in future revisions. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl --- target-xtensa/helper.h | 4 ++++ target-xtensa/op_helper.c | 37 ++++++++++++++++++++++++++++++ target-xtensa/translate.c | 48 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) diff --git a/target-xtensa/helper.h b/target-xtensa/helper.h index 4e6e4176ee..9557347f1b 100644 --- a/target-xtensa/helper.h +++ b/target-xtensa/helper.h @@ -44,5 +44,9 @@ DEF_HELPER_3(sub_s, f32, env, f32, f32) DEF_HELPER_3(mul_s, f32, env, f32, f32) DEF_HELPER_4(madd_s, f32, env, f32, f32, f32) DEF_HELPER_4(msub_s, f32, env, f32, f32, f32) +DEF_HELPER_FLAGS_3(ftoi, TCG_CALL_CONST | TCG_CALL_PURE, i32, f32, i32, i32) +DEF_HELPER_FLAGS_3(ftoui, TCG_CALL_CONST | TCG_CALL_PURE, i32, f32, i32, i32) +DEF_HELPER_3(itof, f32, env, i32, i32) +DEF_HELPER_3(uitof, f32, env, i32, i32) #include "def-helper.h" diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c index ba935a87ca..5cf9c02e05 100644 --- a/target-xtensa/op_helper.c +++ b/target-xtensa/op_helper.c @@ -821,3 +821,40 @@ float32 HELPER(msub_s)(CPUXtensaState *env, float32 a, float32 b, float32 c) return float32_muladd(b, c, a, float_muladd_negate_product, &env->fp_status); } + +uint32_t HELPER(ftoi)(float32 v, uint32_t rounding_mode, uint32_t scale) +{ + float_status fp_status = {0}; + + set_float_rounding_mode(rounding_mode, &fp_status); + return float32_to_int32( + float32_scalbn(v, scale, &fp_status), &fp_status); +} + +uint32_t HELPER(ftoui)(float32 v, uint32_t rounding_mode, uint32_t scale) +{ + float_status fp_status = {0}; + float32 res; + + set_float_rounding_mode(rounding_mode, &fp_status); + + res = float32_scalbn(v, scale, &fp_status); + + if (float32_is_neg(v) && !float32_is_any_nan(v)) { + return float32_to_int32(res, &fp_status); + } else { + return float32_to_uint32(res, &fp_status); + } +} + +float32 HELPER(itof)(CPUXtensaState *env, uint32_t v, uint32_t scale) +{ + return float32_scalbn(int32_to_float32(v, &env->fp_status), + (int32_t)scale, &env->fp_status); +} + +float32 HELPER(uitof)(CPUXtensaState *env, uint32_t v, uint32_t scale) +{ + return float32_scalbn(uint32_to_float32(v, &env->fp_status), + (int32_t)scale, &env->fp_status); +} diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 2125b1d00a..1627ad0dbf 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -1933,6 +1933,54 @@ static void disas_xtensa_insn(DisasContext *dc) cpu_FR[RRR_R], cpu_FR[RRR_S], cpu_FR[RRR_T]); break; + case 8: /*ROUND.Sf*/ + case 9: /*TRUNC.Sf*/ + case 10: /*FLOOR.Sf*/ + case 11: /*CEIL.Sf*/ + case 14: /*UTRUNC.Sf*/ + gen_window_check1(dc, RRR_R); + { + static const unsigned rounding_mode_const[] = { + float_round_nearest_even, + float_round_to_zero, + float_round_down, + float_round_up, + [6] = float_round_to_zero, + }; + TCGv_i32 rounding_mode = tcg_const_i32( + rounding_mode_const[OP2 & 7]); + TCGv_i32 scale = tcg_const_i32(RRR_T); + + if (OP2 == 14) { + gen_helper_ftoui(cpu_R[RRR_R], cpu_FR[RRR_S], + rounding_mode, scale); + } else { + gen_helper_ftoi(cpu_R[RRR_R], cpu_FR[RRR_S], + rounding_mode, scale); + } + + tcg_temp_free(rounding_mode); + tcg_temp_free(scale); + } + break; + + case 12: /*FLOAT.Sf*/ + case 13: /*UFLOAT.Sf*/ + gen_window_check1(dc, RRR_S); + { + TCGv_i32 scale = tcg_const_i32(-RRR_T); + + if (OP2 == 13) { + gen_helper_uitof(cpu_FR[RRR_R], cpu_env, + cpu_R[RRR_S], scale); + } else { + gen_helper_itof(cpu_FR[RRR_R], cpu_env, + cpu_R[RRR_S], scale); + } + tcg_temp_free(scale); + } + break; + case 15: /*FP1OP*/ switch (RRR_T) { case 0: /*MOV.Sf*/ From 4e273869671d78660cd709183d3c5dec3a17de79 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 19 Sep 2012 04:23:58 +0400 Subject: [PATCH 0528/2270] target-xtensa: implement FP1 group These are comparison and conditional move opcodes. See ISA, 4.3.10 for more details. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl --- target-xtensa/helper.h | 8 ++++ target-xtensa/op_helper.c | 47 +++++++++++++++++++++++ target-xtensa/translate.c | 81 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 135 insertions(+), 1 deletion(-) diff --git a/target-xtensa/helper.h b/target-xtensa/helper.h index 9557347f1b..4cc0088c36 100644 --- a/target-xtensa/helper.h +++ b/target-xtensa/helper.h @@ -49,4 +49,12 @@ DEF_HELPER_FLAGS_3(ftoui, TCG_CALL_CONST | TCG_CALL_PURE, i32, f32, i32, i32) DEF_HELPER_3(itof, f32, env, i32, i32) DEF_HELPER_3(uitof, f32, env, i32, i32) +DEF_HELPER_4(un_s, void, env, i32, f32, f32) +DEF_HELPER_4(oeq_s, void, env, i32, f32, f32) +DEF_HELPER_4(ueq_s, void, env, i32, f32, f32) +DEF_HELPER_4(olt_s, void, env, i32, f32, f32) +DEF_HELPER_4(ult_s, void, env, i32, f32, f32) +DEF_HELPER_4(ole_s, void, env, i32, f32, f32) +DEF_HELPER_4(ule_s, void, env, i32, f32, f32) + #include "def-helper.h" diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c index 5cf9c02e05..ae0c09977b 100644 --- a/target-xtensa/op_helper.c +++ b/target-xtensa/op_helper.c @@ -858,3 +858,50 @@ float32 HELPER(uitof)(CPUXtensaState *env, uint32_t v, uint32_t scale) return float32_scalbn(uint32_to_float32(v, &env->fp_status), (int32_t)scale, &env->fp_status); } + +static inline void set_br(CPUXtensaState *env, bool v, uint32_t br) +{ + if (v) { + env->sregs[BR] |= br; + } else { + env->sregs[BR] &= ~br; + } +} + +void HELPER(un_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) +{ + set_br(env, float32_unordered_quiet(a, b, &env->fp_status), br); +} + +void HELPER(oeq_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) +{ + set_br(env, float32_eq_quiet(a, b, &env->fp_status), br); +} + +void HELPER(ueq_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) +{ + int v = float32_compare_quiet(a, b, &env->fp_status); + set_br(env, v == float_relation_equal || v == float_relation_unordered, br); +} + +void HELPER(olt_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) +{ + set_br(env, float32_lt_quiet(a, b, &env->fp_status), br); +} + +void HELPER(ult_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) +{ + int v = float32_compare_quiet(a, b, &env->fp_status); + set_br(env, v == float_relation_less || v == float_relation_unordered, br); +} + +void HELPER(ole_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) +{ + set_br(env, float32_le_quiet(a, b, &env->fp_status), br); +} + +void HELPER(ule_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) +{ + int v = float32_compare_quiet(a, b, &env->fp_status); + set_br(env, v != float_relation_greater, br); +} diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 1627ad0dbf..9308cdfbaa 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -2019,7 +2019,86 @@ static void disas_xtensa_insn(DisasContext *dc) case 11: /*FP1*/ HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR); - TBD(); + +#define gen_compare(rel, br, a, b) \ + do { \ + TCGv_i32 bit = tcg_const_i32(1 << br); \ + \ + gen_helper_##rel(cpu_env, bit, cpu_FR[a], cpu_FR[b]); \ + tcg_temp_free(bit); \ + } while (0) + + switch (OP2) { + case 1: /*UN.Sf*/ + gen_compare(un_s, RRR_R, RRR_S, RRR_T); + break; + + case 2: /*OEQ.Sf*/ + gen_compare(oeq_s, RRR_R, RRR_S, RRR_T); + break; + + case 3: /*UEQ.Sf*/ + gen_compare(ueq_s, RRR_R, RRR_S, RRR_T); + break; + + case 4: /*OLT.Sf*/ + gen_compare(olt_s, RRR_R, RRR_S, RRR_T); + break; + + case 5: /*ULT.Sf*/ + gen_compare(ult_s, RRR_R, RRR_S, RRR_T); + break; + + case 6: /*OLE.Sf*/ + gen_compare(ole_s, RRR_R, RRR_S, RRR_T); + break; + + case 7: /*ULE.Sf*/ + gen_compare(ule_s, RRR_R, RRR_S, RRR_T); + break; + +#undef gen_compare + + case 8: /*MOVEQZ.Sf*/ + case 9: /*MOVNEZ.Sf*/ + case 10: /*MOVLTZ.Sf*/ + case 11: /*MOVGEZ.Sf*/ + gen_window_check1(dc, RRR_T); + { + static const TCGCond cond[] = { + TCG_COND_NE, + TCG_COND_EQ, + TCG_COND_GE, + TCG_COND_LT + }; + int label = gen_new_label(); + tcg_gen_brcondi_i32(cond[OP2 - 8], cpu_R[RRR_T], 0, label); + tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_FR[RRR_S]); + gen_set_label(label); + } + break; + + case 12: /*MOVF.Sf*/ + case 13: /*MOVT.Sf*/ + HAS_OPTION(XTENSA_OPTION_BOOLEAN); + { + int label = gen_new_label(); + TCGv_i32 tmp = tcg_temp_new_i32(); + + tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << RRR_T); + tcg_gen_brcondi_i32( + OP2 & 1 ? TCG_COND_EQ : TCG_COND_NE, + tmp, 0, label); + tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_FR[RRR_S]); + gen_set_label(label); + tcg_temp_free(tmp); + } + break; + + default: /*reserved*/ + RESERVED(); + break; + } break; default: /*reserved*/ From ef04a8467eae31bc93b9458ad3d30a6ad1303327 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 19 Sep 2012 04:23:59 +0400 Subject: [PATCH 0529/2270] target-xtensa: implement coprocessor context option In case Coprocessor Context option is enabled CPENABLE SR bits control whether access to coprocessors is allowed or would rise one of CoprocessorXDisabled exceptions. See ISA, 4.4.5 for more details. FP is coprocessor 0. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl --- target-xtensa/cpu.h | 5 +++++ target-xtensa/translate.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h index b4562832b3..7348277edc 100644 --- a/target-xtensa/cpu.h +++ b/target-xtensa/cpu.h @@ -468,6 +468,8 @@ static inline int cpu_mmu_index(CPUXtensaState *env) #define XTENSA_TBFLAG_LITBASE 0x8 #define XTENSA_TBFLAG_DEBUG 0x10 #define XTENSA_TBFLAG_ICOUNT 0x20 +#define XTENSA_TBFLAG_CPENABLE_MASK 0x3fc0 +#define XTENSA_TBFLAG_CPENABLE_SHIFT 6 static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc, target_ulong *cs_base, int *flags) @@ -491,6 +493,9 @@ static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc, *flags |= XTENSA_TBFLAG_ICOUNT; } } + if (xtensa_option_enabled(env->config, XTENSA_OPTION_COPROCESSOR)) { + *flags |= env->sregs[CPENABLE] << XTENSA_TBFLAG_CPENABLE_SHIFT; + } } #include "cpu-all.h" diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 9308cdfbaa..ba3ffcb7a4 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -65,6 +65,8 @@ typedef struct DisasContext { bool debug; bool icount; TCGv_i32 next_icount; + + unsigned cpenable; } DisasContext; static TCGv_ptr cpu_env; @@ -331,6 +333,15 @@ static void gen_check_privilege(DisasContext *dc) } } +static void gen_check_cpenable(DisasContext *dc, unsigned cp) +{ + if (option_enabled(dc, XTENSA_OPTION_COPROCESSOR) && + !(dc->cpenable & (1 << cp))) { + gen_exception_cause(dc, COPROCESSOR0_DISABLED + cp); + dc->is_jmp = DISAS_UPDATE; + } +} + static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot) { tcg_gen_mov_i32(cpu_pc, dest); @@ -579,6 +590,13 @@ static void gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v) } } +static void gen_wsr_cpenable(DisasContext *dc, uint32_t sr, TCGv_i32 v) +{ + tcg_gen_andi_i32(cpu_SR[sr], v, 0xff); + /* This can change tb->flags, so exit tb */ + gen_jumpi_check_loop_end(dc, -1); +} + static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v) { tcg_gen_andi_i32(cpu_SR[sr], v, @@ -681,6 +699,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s) [DBREAKA + 1] = gen_wsr_dbreaka, [DBREAKC] = gen_wsr_dbreakc, [DBREAKC + 1] = gen_wsr_dbreakc, + [CPENABLE] = gen_wsr_cpenable, [INTSET] = gen_wsr_intset, [INTCLEAR] = gen_wsr_intclear, [INTENABLE] = gen_wsr_intenable, @@ -1850,6 +1869,7 @@ static void disas_xtensa_insn(DisasContext *dc) case 5: /*SSXUf*/ HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR); gen_window_check2(dc, RRR_S, RRR_T); + gen_check_cpenable(dc, 0); { TCGv_i32 addr = tcg_temp_new_i32(); tcg_gen_add_i32(addr, cpu_R[RRR_S], cpu_R[RRR_T]); @@ -1909,26 +1929,31 @@ static void disas_xtensa_insn(DisasContext *dc) HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR); switch (OP2) { case 0: /*ADD.Sf*/ + gen_check_cpenable(dc, 0); gen_helper_add_s(cpu_FR[RRR_R], cpu_env, cpu_FR[RRR_S], cpu_FR[RRR_T]); break; case 1: /*SUB.Sf*/ + gen_check_cpenable(dc, 0); gen_helper_sub_s(cpu_FR[RRR_R], cpu_env, cpu_FR[RRR_S], cpu_FR[RRR_T]); break; case 2: /*MUL.Sf*/ + gen_check_cpenable(dc, 0); gen_helper_mul_s(cpu_FR[RRR_R], cpu_env, cpu_FR[RRR_S], cpu_FR[RRR_T]); break; case 4: /*MADD.Sf*/ + gen_check_cpenable(dc, 0); gen_helper_madd_s(cpu_FR[RRR_R], cpu_env, cpu_FR[RRR_R], cpu_FR[RRR_S], cpu_FR[RRR_T]); break; case 5: /*MSUB.Sf*/ + gen_check_cpenable(dc, 0); gen_helper_msub_s(cpu_FR[RRR_R], cpu_env, cpu_FR[RRR_R], cpu_FR[RRR_S], cpu_FR[RRR_T]); break; @@ -1939,6 +1964,7 @@ static void disas_xtensa_insn(DisasContext *dc) case 11: /*CEIL.Sf*/ case 14: /*UTRUNC.Sf*/ gen_window_check1(dc, RRR_R); + gen_check_cpenable(dc, 0); { static const unsigned rounding_mode_const[] = { float_round_nearest_even, @@ -1967,6 +1993,7 @@ static void disas_xtensa_insn(DisasContext *dc) case 12: /*FLOAT.Sf*/ case 13: /*UFLOAT.Sf*/ gen_window_check1(dc, RRR_S); + gen_check_cpenable(dc, 0); { TCGv_i32 scale = tcg_const_i32(-RRR_T); @@ -1984,24 +2011,29 @@ static void disas_xtensa_insn(DisasContext *dc) case 15: /*FP1OP*/ switch (RRR_T) { case 0: /*MOV.Sf*/ + gen_check_cpenable(dc, 0); tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_FR[RRR_S]); break; case 1: /*ABS.Sf*/ + gen_check_cpenable(dc, 0); gen_helper_abs_s(cpu_FR[RRR_R], cpu_FR[RRR_S]); break; case 4: /*RFRf*/ gen_window_check1(dc, RRR_R); + gen_check_cpenable(dc, 0); tcg_gen_mov_i32(cpu_R[RRR_R], cpu_FR[RRR_S]); break; case 5: /*WFRf*/ gen_window_check1(dc, RRR_S); + gen_check_cpenable(dc, 0); tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_R[RRR_S]); break; case 6: /*NEG.Sf*/ + gen_check_cpenable(dc, 0); gen_helper_neg_s(cpu_FR[RRR_R], cpu_FR[RRR_S]); break; @@ -2024,6 +2056,7 @@ static void disas_xtensa_insn(DisasContext *dc) do { \ TCGv_i32 bit = tcg_const_i32(1 << br); \ \ + gen_check_cpenable(dc, 0); \ gen_helper_##rel(cpu_env, bit, cpu_FR[a], cpu_FR[b]); \ tcg_temp_free(bit); \ } while (0) @@ -2064,6 +2097,7 @@ static void disas_xtensa_insn(DisasContext *dc) case 10: /*MOVLTZ.Sf*/ case 11: /*MOVGEZ.Sf*/ gen_window_check1(dc, RRR_T); + gen_check_cpenable(dc, 0); { static const TCGCond cond[] = { TCG_COND_NE, @@ -2081,6 +2115,7 @@ static void disas_xtensa_insn(DisasContext *dc) case 12: /*MOVF.Sf*/ case 13: /*MOVT.Sf*/ HAS_OPTION(XTENSA_OPTION_BOOLEAN); + gen_check_cpenable(dc, 0); { int label = gen_new_label(); TCGv_i32 tmp = tcg_temp_new_i32(); @@ -2336,6 +2371,7 @@ static void disas_xtensa_insn(DisasContext *dc) case 12: /*SSIUf*/ HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR); gen_window_check1(dc, RRI8_S); + gen_check_cpenable(dc, 0); { TCGv_i32 addr = tcg_temp_new_i32(); tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2); @@ -2853,6 +2889,8 @@ static void gen_intermediate_code_internal( dc.ccount_delta = 0; dc.debug = tb->flags & XTENSA_TBFLAG_DEBUG; dc.icount = tb->flags & XTENSA_TBFLAG_ICOUNT; + dc.cpenable = (tb->flags & XTENSA_TBFLAG_CPENABLE_MASK) >> + XTENSA_TBFLAG_CPENABLE_SHIFT; init_litbase(&dc); init_sar_tracker(&dc); From 93b6599734f81328ee3d608f57667742cafeea72 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Mon, 3 Sep 2012 09:25:16 +0000 Subject: [PATCH 0530/2270] audio: Fix warning from static code analysis smatch report: audio/audio_template.h:416 AUD_open_out(18) warn: variable dereferenced before check 'as' (see line 414) Moving the ldebug statement after the statement which checks 'as' fixes that warning. Signed-off-by: Stefan Weil Signed-off-by: malc --- audio/audio_template.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/audio/audio_template.h b/audio/audio_template.h index 519432a7c5..16f7880770 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -410,15 +410,15 @@ SW *glue (AUD_open_, TYPE) ( SW *old_sw = NULL; #endif - ldebug ("open %s, freq %d, nchannels %d, fmt %d\n", - name, as->freq, as->nchannels, as->fmt); - if (audio_bug (AUDIO_FUNC, !card || !name || !callback_fn || !as)) { dolog ("card=%p name=%p callback_fn=%p as=%p\n", card, name, callback_fn, as); goto fail; } + ldebug ("open %s, freq %d, nchannels %d, fmt %d\n", + name, as->freq, as->nchannels, as->fmt); + if (audio_bug (AUDIO_FUNC, audio_validate_settings (as))) { audio_print_settings (as); goto fail; From 2e84849aa2cc7f220d3b3668f5f7e3c57bb1b590 Mon Sep 17 00:00:00 2001 From: Don Slutz Date: Fri, 21 Sep 2012 20:13:13 -0400 Subject: [PATCH 0531/2270] target-i386: Allow tsc-frequency to be larger then 2.147G The check using INT_MAX (2147483647) is wrong in this case. Signed-off-by: Fred Oliveira Signed-off-by: Don Slutz Signed-off-by: Stefan Hajnoczi --- target-i386/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 423e00905d..cbc172e9fc 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -846,7 +846,7 @@ static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque, { X86CPU *cpu = X86_CPU(obj); const int64_t min = 0; - const int64_t max = INT_MAX; + const int64_t max = INT64_MAX; int64_t value; visit_type_int(v, &value, name, errp); From b548828862d3bf7214b7ef9cb361356b153b89c9 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 1 Sep 2012 09:34:15 +0200 Subject: [PATCH 0532/2270] qemu-ga: Remove unreachable code after g_error Report from smatch: qemu-ga.c:117 register_signal_handlers(11) info: ignoring unreachable code. qemu-ga.c:122 register_signal_handlers(16) info: ignoring unreachable code. g_error calls abort which terminates the program. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- qemu-ga.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/qemu-ga.c b/qemu-ga.c index 7623079887..b7474708f0 100644 --- a/qemu-ga.c +++ b/qemu-ga.c @@ -114,12 +114,10 @@ static gboolean register_signal_handlers(void) ret = sigaction(SIGINT, &sigact, NULL); if (ret == -1) { g_error("error configuring signal handler: %s", strerror(errno)); - return false; } ret = sigaction(SIGTERM, &sigact, NULL); if (ret == -1) { g_error("error configuring signal handler: %s", strerror(errno)); - return false; } return true; From 39b384591fda27d6e1213cea0b11b1ebe0ed4b74 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 1 Sep 2012 09:40:26 +0200 Subject: [PATCH 0533/2270] qemu-sockets: Fix potential memory leak The old code leaks variable 'peer'. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- qemu-sockets.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu-sockets.c b/qemu-sockets.c index 361d890da3..037775b86b 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -353,7 +353,7 @@ int inet_dgram_opts(QemuOpts *opts) if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) { fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port, gai_strerror(rc)); - return -1; + goto err; } /* create socket */ From 5d40097fc09fe5d34cf316a411dc27d455ac2cd0 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 1 Sep 2012 11:12:23 +0200 Subject: [PATCH 0534/2270] cadence_uart: Fix buffer overflow Report from smatch: hw/cadence_uart.c:413 uart_read(13) error: buffer overflow 's->r' 18 <= 18 This fixes read access to s->r[R_MAX] which is behind the limits of s->r. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- hw/cadence_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c index d98e531372..f8afc4ed26 100644 --- a/hw/cadence_uart.c +++ b/hw/cadence_uart.c @@ -404,7 +404,7 @@ static uint64_t uart_read(void *opaque, target_phys_addr_t offset, uint32_t c = 0; offset >>= 2; - if (offset > R_MAX) { + if (offset >= R_MAX) { return 0; } else if (offset == R_TX_RX) { uart_read_rx_fifo(s, &c); From 8139626643cbe8dc07bd9acc88057effeedf8064 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 1 Sep 2012 12:43:41 +0200 Subject: [PATCH 0535/2270] lm4549: Fix buffer overflow Report from smatch: lm4549.c:234 lm4549_write_samples(14) error: buffer overflow 's->buffer' 1024 <= 1024 There must be enough space to add two entries starting with index s->buffer_level, therefore the old check was wrong. [Peter Maydell clarifies the nature of the analyser warning: I don't object to making the change to placate the analyser, but I don't think this is actually a buffer overrun. We always add and remove samples from the buffer two at a time, so it's not possible to get here with s->buffer_level == BUFFER_SIZE-1 (which is the only case where the old and new conditions give different answers).] Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- hw/lm4549.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/lm4549.c b/hw/lm4549.c index 80b3ec4a5d..e0137d54b6 100644 --- a/hw/lm4549.c +++ b/hw/lm4549.c @@ -224,7 +224,7 @@ uint32_t lm4549_write_samples(lm4549_state *s, uint32_t left, uint32_t right) This model supports 16-bit playback. */ - if (s->buffer_level >= LM4549_BUFFER_SIZE) { + if (s->buffer_level > LM4549_BUFFER_SIZE - 2) { DPRINTF("write_sample Buffer full\n"); return 0; } From 997f15672a5ca7714cf310d92f475d2c5fe40970 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 1 Sep 2012 12:56:03 +0200 Subject: [PATCH 0536/2270] ioh3420: Remove unreachable code Report from smatch: hw/ioh3420.c:128 ioh3420_initfn(35) info: ignoring unreachable code. Signed-off-by: Stefan Weil Reviewed-by: Juan Quintela Signed-off-by: Stefan Hajnoczi --- hw/ioh3420.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/ioh3420.c b/hw/ioh3420.c index 94a537c9b3..4d314733b9 100644 --- a/hw/ioh3420.c +++ b/hw/ioh3420.c @@ -125,7 +125,6 @@ static int ioh3420_initfn(PCIDevice *d) rc = pcie_chassis_add_slot(s); if (rc < 0) { goto err_pcie_cap; - return rc; } pcie_cap_root_init(d); rc = pcie_aer_init(d, IOH_EP_AER_OFFSET); From 12dabc79f976d66755025272f7e2e8e4da31715a Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 1 Sep 2012 13:00:48 +0200 Subject: [PATCH 0537/2270] pflash_cfi01: Fix warning caused by unreachable code Report from smatch: hw/pflash_cfi01.c:431 pflash_write(180) info: ignoring unreachable code. Instead of removing the return statement after the switch statement, the patch replaces the return statements in the switch statement by break statements. Other switch statements in the same code do it also like that. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- hw/pflash_cfi01.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index 9c42d3105c..855890d1f1 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -321,7 +321,7 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset, } pfl->wcycle++; pfl->cmd = cmd; - return; + break; case 1: switch (pfl->cmd) { case 0x10: /* Single Byte Program */ @@ -376,7 +376,7 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset, default: goto error_flash; } - return; + break; case 2: switch (pfl->cmd) { case 0xe8: /* Block write */ @@ -407,7 +407,7 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset, default: goto error_flash; } - return; + break; case 3: /* Confirm mode */ switch (pfl->cmd) { case 0xe8: /* Block write */ @@ -423,7 +423,7 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset, default: goto error_flash; } - return; + break; default: /* Should never happen */ DPRINTF("%s: invalid write state\n", __func__); From d8f8a860f2403533fc73f541122c65a34b21e42f Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Sun, 2 Sep 2012 02:04:16 +0300 Subject: [PATCH 0538/2270] dtrace backend: add function to reserved words Signed-off-by: Alon Levy Signed-off-by: Stefan Hajnoczi --- scripts/tracetool/backend/dtrace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/tracetool/backend/dtrace.py b/scripts/tracetool/backend/dtrace.py index 9cab75cde8..6be7047018 100644 --- a/scripts/tracetool/backend/dtrace.py +++ b/scripts/tracetool/backend/dtrace.py @@ -87,7 +87,7 @@ def stap(events): if len(e.args) > 0: for name in e.args.names(): # Append underscore to reserved keywords - if name in ('limit', 'in', 'next', 'self'): + if name in ('limit', 'in', 'next', 'self', 'function'): name += '_' out(' %s = $arg%d;' % (name, i)) i += 1 From 995ee2bf469de6bbe5ce133ec853392b2a4ce34c Mon Sep 17 00:00:00 2001 From: Hitoshi Mitake Date: Sat, 15 Sep 2012 01:15:41 +0900 Subject: [PATCH 0539/2270] curses: don't initialize curses when qemu is daemonized Current qemu initializes curses even if -daemonize option is passed. This cause problem because shell prompt appears without calling endwin(). This patch adds new function, is_daemonized(), to OS dependent code. With this function, curses_display_init() can check that qemu is daemonized or not. If daemonized, curses_display_init() isn't called and the problem is avoided. Of course, -daemonize && -curses doesn't make sense. Users shouldn't pass the arguments at the same time. But the problem is very painful because Ctrl-C cannot be delivered to the terminal. Cc: Andrzej Zaborowski Cc: Stefan Hajnoczi Cc: Anthony Liguori Cc: Michael Roth Signed-off-by: Hitoshi Mitake Signed-off-by: Stefan Hajnoczi --- os-posix.c | 5 +++++ qemu-os-posix.h | 2 ++ qemu-os-win32.h | 5 +++++ vl.c | 4 +++- 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/os-posix.c b/os-posix.c index 79fa2288e4..eabccb8fe0 100644 --- a/os-posix.c +++ b/os-posix.c @@ -360,3 +360,8 @@ int qemu_create_pidfile(const char *filename) /* keep pidfile open & locked forever */ return 0; } + +bool is_daemonized(void) +{ + return daemonize; +} diff --git a/qemu-os-posix.h b/qemu-os-posix.h index 8e1149d964..7f198e475c 100644 --- a/qemu-os-posix.h +++ b/qemu-os-posix.h @@ -46,4 +46,6 @@ typedef struct timeval qemu_timeval; typedef struct timespec qemu_timespec; int qemu_utimens(const char *path, const qemu_timespec *times); +bool is_daemonized(void); + #endif diff --git a/qemu-os-win32.h b/qemu-os-win32.h index 753679b194..b3e451b719 100644 --- a/qemu-os-win32.h +++ b/qemu-os-win32.h @@ -86,4 +86,9 @@ typedef struct { } qemu_timeval; int qemu_gettimeofday(qemu_timeval *tp); +static inline bool is_daemonized(void) +{ + return false; +} + #endif diff --git a/vl.c b/vl.c index 7c577fa544..48049ef0b6 100644 --- a/vl.c +++ b/vl.c @@ -3657,7 +3657,9 @@ int main(int argc, char **argv, char **envp) break; #if defined(CONFIG_CURSES) case DT_CURSES: - curses_display_init(ds, full_screen); + if (!is_daemonized()) { + curses_display_init(ds, full_screen); + } break; #endif #if defined(CONFIG_SDL) From c10600af60865ba6c60987be313102ebb5fcee57 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Mon, 17 Sep 2012 11:10:03 +0200 Subject: [PATCH 0540/2270] TextConsole: saturate escape parameter in TTY_STATE_CSI Signed-off-by: Laszlo Ersek Reviewed-by: Markus Armbruster Signed-off-by: Stefan Hajnoczi --- console.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/console.c b/console.c index a8bcc42fe4..3f3d2547bf 100644 --- a/console.c +++ b/console.c @@ -938,8 +938,11 @@ static void console_putchar(TextConsole *s, int ch) case TTY_STATE_CSI: /* handle escape sequence parameters */ if (ch >= '0' && ch <= '9') { if (s->nb_esc_params < MAX_ESC_PARAMS) { - s->esc_params[s->nb_esc_params] = - s->esc_params[s->nb_esc_params] * 10 + ch - '0'; + int *param = &s->esc_params[s->nb_esc_params]; + int digit = (ch - '0'); + + *param = (*param <= (INT_MAX - digit) / 10) ? + *param * 10 + digit : INT_MAX; } } else { if (s->nb_esc_params < MAX_ESC_PARAMS) From 144b97c26cdef7fecd62dae2db6ce312cd493751 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 19 Sep 2012 15:52:44 +0200 Subject: [PATCH 0541/2270] qemu-timer: simplify qemu_run_timers ptimer_head is an invariant pointer to clock->active_timers. Remove it, and just reference clock->active_timers directly. Signed-off-by: Paolo Bonzini Signed-off-by: Stefan Hajnoczi --- qemu-timer.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/qemu-timer.c b/qemu-timer.c index c7a1551a36..908a1030b6 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -372,21 +372,20 @@ bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time) void qemu_run_timers(QEMUClock *clock) { - QEMUTimer **ptimer_head, *ts; + QEMUTimer *ts; int64_t current_time; if (!clock->enabled) return; current_time = qemu_get_clock_ns(clock); - ptimer_head = &clock->active_timers; for(;;) { - ts = *ptimer_head; + ts = clock->active_timers; if (!qemu_timer_expired_ns(ts, current_time)) { break; } /* remove timer from the list before calling the callback */ - *ptimer_head = ts->next; + clock->active_timers = ts->next; ts->next = NULL; /* run the callback (the timer list can be modified) */ From ad11ad77748bdd8016370db210751683dc038dd6 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Tue, 4 Sep 2012 22:14:19 +0200 Subject: [PATCH 0542/2270] linux-user: Remove redundant null check and replace free by g_free Report from smatch: linux-user/syscall.c:3632 do_ioctl_dm(220) info: redundant null check on big_buf calling free() 'big_buf' was allocated by g_malloc0, therefore free was also replaced by g_free. Signed-off-by: Stefan Weil Reviewed-by: Peter Maydell Signed-off-by: Stefan Hajnoczi --- linux-user/syscall.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 6257a04d0a..471d0605f7 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3628,9 +3628,7 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd, unlock_user(argptr, arg, target_size); } out: - if (big_buf) { - free(big_buf); - } + g_free(big_buf); return ret; } From 73062dfe6be0050dbd43ce3516e935ebb2545add Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 22 Sep 2012 21:13:28 +0200 Subject: [PATCH 0543/2270] net/socket: Fix compiler warning (regression for MinGW) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 213fd5087e2e4e2da10ad266df0ba950cf7618bf removed a type cast which is needed for MinGW: net/socket.c:136: warning: pointer targets in passing argument 2 of ‘sendto’ differ in signedness /usr/lib/gcc/amd64-mingw32msvc/4.4.4/../../../../amd64-mingw32msvc/include/winsock2.h:1313: note: expected ‘const char *’ but argument is of type ‘const uint8_t *’ Add a 'qemu_sendto' macro which provides that type cast where needed and use the new macro instead of 'sendto'. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- net/socket.c | 6 +++--- qemu-common.h | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/net/socket.c b/net/socket.c index 5e0c92e062..f3d7878264 100644 --- a/net/socket.c +++ b/net/socket.c @@ -131,9 +131,9 @@ static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf, ssize_t ret; do { - ret = sendto(s->fd, buf, size, 0, - (struct sockaddr *)&s->dgram_dst, - sizeof(s->dgram_dst)); + ret = qemu_sendto(s->fd, buf, size, 0, + (struct sockaddr *)&s->dgram_dst, + sizeof(s->dgram_dst)); } while (ret == -1 && errno == EINTR); if (ret == -1 && errno == EAGAIN) { diff --git a/qemu-common.h b/qemu-common.h index e5c2bcd204..15d9e4ed71 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -223,9 +223,14 @@ int qemu_pipe(int pipefd[2]); #endif #ifdef _WIN32 +/* MinGW needs a type cast for the 'buf' argument. */ #define qemu_recv(sockfd, buf, len, flags) recv(sockfd, (void *)buf, len, flags) +#define qemu_sendto(sockfd, buf, len, flags, destaddr, addrlen) \ + sendto(sockfd, (const void *)buf, len, flags, destaddr, addrlen) #else #define qemu_recv(sockfd, buf, len, flags) recv(sockfd, buf, len, flags) +#define qemu_sendto(sockfd, buf, len, flags, destaddr, addrlen) \ + sendto(sockfd, buf, len, flags, destaddr, addrlen) #endif /* Error handling. */ From 95df51a4a02a853af8828c281bce2d4f2a41d6fd Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 22 Aug 2012 21:42:32 +0200 Subject: [PATCH 0544/2270] w32: Always use standard instead of native format strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GLib 2.0 include files use __printf__ for the format attribute which resolves to native format strings on w32 hosts. QEMU wants standard format strings instead of native format strings, so we simply change any declaration with __printf__ to use __gnu_printf__. This works because all basic printf functions support both kinds of format strings. This fixes a compiler warning: qapi/string-output-visitor.c: In function ‘print_type_int’: qapi/string-output-visitor.c:34:5: warning: unknown conversion type character ‘l’ in format [-Wformat] qapi/string-output-visitor.c:34:5: warning: too many arguments for format [-Wformat-extra-args] Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- compiler.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler.h b/compiler.h index 07ba1f8113..c734a71c67 100644 --- a/compiler.h +++ b/compiler.h @@ -44,6 +44,11 @@ /* Use gnu_printf when supported (qemu uses standard format strings). */ # define GCC_ATTR __attribute__((__unused__, format(gnu_printf, 1, 2))) # define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m))) +# if defined(_WIN32) + /* Map __printf__ to __gnu_printf__ because we want standard format strings + * even when MinGW or GLib include files use __printf__. */ +# define __printf__ __gnu_printf__ +# endif # endif #if defined(_WIN32) #define GCC_WEAK __attribute__((weak)) From d3e8f95753114a827f9cd8e819b1d5cc8333f76b Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 22 Sep 2012 22:26:19 +0200 Subject: [PATCH 0545/2270] w32: Add implementation of gmtime_r, localtime_r Those functions are missing in MinGW. Some versions of MinGW-w64 include defines for gmtime_r and localtime_r. Older versions of these macros are buggy (they return a pointer to a static variable), therefore we don't want them. Newer versions are similar to the code used here, but without the memset. The implementation which is used here is not strictly reentrant, but sufficiently good for QEMU on w32 or w64. Signed-off-by: Stefan Weil [blauwirbel@gmail.com: added comment about locking] Signed-off-by: Blue Swirl --- oslib-win32.c | 24 ++++++++++++++++++++++++ qemu-os-win32.h | 6 ++++++ 2 files changed, 30 insertions(+) diff --git a/oslib-win32.c b/oslib-win32.c index ffbc6d0c9f..51b33e8b20 100644 --- a/oslib-win32.c +++ b/oslib-win32.c @@ -74,6 +74,30 @@ void qemu_vfree(void *ptr) VirtualFree(ptr, 0, MEM_RELEASE); } +/* FIXME: add proper locking */ +struct tm *gmtime_r(const time_t *timep, struct tm *result) +{ + struct tm *p = gmtime(timep); + memset(result, 0, sizeof(*result)); + if (p) { + *result = *p; + p = result; + } + return p; +} + +/* FIXME: add proper locking */ +struct tm *localtime_r(const time_t *timep, struct tm *result) +{ + struct tm *p = localtime(timep); + memset(result, 0, sizeof(*result)); + if (p) { + *result = *p; + p = result; + } + return p; +} + void socket_set_block(int fd) { unsigned long opt = 0; diff --git a/qemu-os-win32.h b/qemu-os-win32.h index 753679b194..3b5a35b6c2 100644 --- a/qemu-os-win32.h +++ b/qemu-os-win32.h @@ -68,6 +68,12 @@ /* Declaration of ffs() is missing in MinGW's strings.h. */ int ffs(int i); +/* Missing POSIX functions. Don't use MinGW-w64 macros. */ +#undef gmtime_r +struct tm *gmtime_r(const time_t *timep, struct tm *result); +#undef localtime_r +struct tm *localtime_r(const time_t *timep, struct tm *result); + static inline void os_setup_signal_handling(void) {} static inline void os_daemonize(void) {} static inline void os_setup_post(void) {} From 80dd1aae3657a902d262f5d20a7a3c655b23705e Mon Sep 17 00:00:00 2001 From: Kevin Shanahan Date: Fri, 21 Sep 2012 08:50:22 +0930 Subject: [PATCH 0546/2270] blockdev: preserve readonly and snapshot states across media changes If readonly=on is given at device creation time, the ->readonly flag needs to be set in the block driver state for this device so that readonly-ness is preserved across media changes (qmp change command). Similarly, to preserve the snapshot property requires ->open_flags to be correct. Signed-off-by: Kevin Shanahan Signed-off-by: Kevin Wolf --- blockdev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/blockdev.c b/blockdev.c index 7c83baa353..e5d450f0bb 100644 --- a/blockdev.c +++ b/blockdev.c @@ -527,6 +527,8 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) if_name[type], mediastr, unit_id); } dinfo->bdrv = bdrv_new(dinfo->id); + dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0; + dinfo->bdrv->read_only = ro; dinfo->devaddr = devaddr; dinfo->type = type; dinfo->bus = bus_id; From be028adcedd68ca4d78fdc43e7e2fa4f1cdbc653 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:17 -0400 Subject: [PATCH 0547/2270] block: correctly set the keep_read_only flag I believe the bs->keep_read_only flag is supposed to reflect the initial open state of the device. If the device is initially opened R/O, then commit operations, or reopen operations changing to R/W, are prohibited. Currently, the keep_read_only flag is only accurate for the active layer, and its backing file. Subsequent images end up always having the keep_read_only flag set. For instance, what happens now: [ base ] kro = 1, ro = 1 | v [ snap-1 ] kro = 1, ro = 1 | v [ snap-2 ] kro = 0, ro = 1 | v [ active ] kro = 0, ro = 0 What we want: [ base ] kro = 0, ro = 1 | v [ snap-1 ] kro = 0, ro = 1 | v [ snap-2 ] kro = 0, ro = 1 | v [ active ] kro = 0, ro = 0 Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block.c | 14 +++++++------- block.h | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/block.c b/block.c index e78039bd5a..4c0e7f5439 100644 --- a/block.c +++ b/block.c @@ -668,7 +668,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename, open_flags |= BDRV_O_RDWR; } - bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR); + bs->read_only = !(open_flags & BDRV_O_RDWR); /* Open the image, either directly or using a protocol */ if (drv->bdrv_file_open) { @@ -808,6 +808,12 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, goto unlink_and_fail; } + if (flags & BDRV_O_RDWR) { + flags |= BDRV_O_ALLOW_RDWR; + } + + bs->keep_read_only = !(flags & BDRV_O_ALLOW_RDWR); + /* Open the image */ ret = bdrv_open_common(bs, filename, flags, drv); if (ret < 0) { @@ -837,12 +843,6 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, bdrv_close(bs); return ret; } - if (bs->is_temporary) { - bs->backing_hd->keep_read_only = !(flags & BDRV_O_RDWR); - } else { - /* base image inherits from "parent" */ - bs->backing_hd->keep_read_only = bs->keep_read_only; - } } if (!bdrv_key_required(bs)) { diff --git a/block.h b/block.h index 2e2be11071..4d919c249f 100644 --- a/block.h +++ b/block.h @@ -80,6 +80,7 @@ typedef struct BlockDevOps { #define BDRV_O_COPY_ON_READ 0x0400 /* copy read backing sectors into image */ #define BDRV_O_INCOMING 0x0800 /* consistency hint for incoming migration */ #define BDRV_O_CHECK 0x1000 /* open solely for consistency check */ +#define BDRV_O_ALLOW_RDWR 0x2000 /* allow reopen to change from r/o to r/w */ #define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH) From 55b110f24ec765a09cfb7f4c013fcd90dd807628 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:18 -0400 Subject: [PATCH 0548/2270] block: make bdrv_set_enable_write_cache() modify open_flags bdrv_set_enable_write_cache() sets the bs->enable_write_cache flag, but without the flag recorded in bs->open_flags, then next time a reopen() is performed the enable_write_cache setting may be inadvertently lost. This will set the flag in open_flags, so it is preserved across reopens. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/block.c b/block.c index 4c0e7f5439..458bcc9b13 100644 --- a/block.c +++ b/block.c @@ -2168,6 +2168,13 @@ int bdrv_enable_write_cache(BlockDriverState *bs) void bdrv_set_enable_write_cache(BlockDriverState *bs, bool wce) { bs->enable_write_cache = wce; + + /* so a reopen() will preserve wce */ + if (wce) { + bs->open_flags |= BDRV_O_CACHE_WB; + } else { + bs->open_flags &= ~BDRV_O_CACHE_WB; + } } int bdrv_is_encrypted(BlockDriverState *bs) From e971aa12739f269d6fbfaeabdd4acaeb0f15960b Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:19 -0400 Subject: [PATCH 0549/2270] block: Framework for reopening files safely This is based on Supriya Kannery's bdrv_reopen() patch series. This provides a transactional method to reopen multiple images files safely. Image files are queue for reopen via bdrv_reopen_queue(), and the reopen occurs when bdrv_reopen_multiple() is called. Changes are staged in bdrv_reopen_prepare() and in the equivalent driver level functions. If any of the staged images fails a prepare, then all of the images left untouched, and the staged changes for each image abandoned. Block drivers are passed a reopen state structure, that contains: * BDS to reopen * flags for the reopen * opaque pointer for any driver-specific data that needs to be persistent from _prepare to _commit/_abort * reopen queue pointer, if the driver needs to queue additional BDS for a reopen Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++++++++ block.h | 17 ++++ block_int.h | 8 ++ 3 files changed, 257 insertions(+) diff --git a/block.c b/block.c index 458bcc9b13..c7c1a3bd33 100644 --- a/block.c +++ b/block.c @@ -863,6 +863,238 @@ unlink_and_fail: return ret; } +typedef struct BlockReopenQueueEntry { + bool prepared; + BDRVReopenState state; + QSIMPLEQ_ENTRY(BlockReopenQueueEntry) entry; +} BlockReopenQueueEntry; + +/* + * Adds a BlockDriverState to a simple queue for an atomic, transactional + * reopen of multiple devices. + * + * bs_queue can either be an existing BlockReopenQueue that has had QSIMPLE_INIT + * already performed, or alternatively may be NULL a new BlockReopenQueue will + * be created and initialized. This newly created BlockReopenQueue should be + * passed back in for subsequent calls that are intended to be of the same + * atomic 'set'. + * + * bs is the BlockDriverState to add to the reopen queue. + * + * flags contains the open flags for the associated bs + * + * returns a pointer to bs_queue, which is either the newly allocated + * bs_queue, or the existing bs_queue being used. + * + */ +BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue, + BlockDriverState *bs, int flags) +{ + assert(bs != NULL); + + BlockReopenQueueEntry *bs_entry; + if (bs_queue == NULL) { + bs_queue = g_new0(BlockReopenQueue, 1); + QSIMPLEQ_INIT(bs_queue); + } + + if (bs->file) { + bdrv_reopen_queue(bs_queue, bs->file, flags); + } + + bs_entry = g_new0(BlockReopenQueueEntry, 1); + QSIMPLEQ_INSERT_TAIL(bs_queue, bs_entry, entry); + + bs_entry->state.bs = bs; + bs_entry->state.flags = flags; + + return bs_queue; +} + +/* + * Reopen multiple BlockDriverStates atomically & transactionally. + * + * The queue passed in (bs_queue) must have been built up previous + * via bdrv_reopen_queue(). + * + * Reopens all BDS specified in the queue, with the appropriate + * flags. All devices are prepared for reopen, and failure of any + * device will cause all device changes to be abandonded, and intermediate + * data cleaned up. + * + * If all devices prepare successfully, then the changes are committed + * to all devices. + * + */ +int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp) +{ + int ret = -1; + BlockReopenQueueEntry *bs_entry, *next; + Error *local_err = NULL; + + assert(bs_queue != NULL); + + bdrv_drain_all(); + + QSIMPLEQ_FOREACH(bs_entry, bs_queue, entry) { + if (bdrv_reopen_prepare(&bs_entry->state, bs_queue, &local_err)) { + error_propagate(errp, local_err); + goto cleanup; + } + bs_entry->prepared = true; + } + + /* If we reach this point, we have success and just need to apply the + * changes + */ + QSIMPLEQ_FOREACH(bs_entry, bs_queue, entry) { + bdrv_reopen_commit(&bs_entry->state); + } + + ret = 0; + +cleanup: + QSIMPLEQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) { + if (ret && bs_entry->prepared) { + bdrv_reopen_abort(&bs_entry->state); + } + g_free(bs_entry); + } + g_free(bs_queue); + return ret; +} + + +/* Reopen a single BlockDriverState with the specified flags. */ +int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp) +{ + int ret = -1; + Error *local_err = NULL; + BlockReopenQueue *queue = bdrv_reopen_queue(NULL, bs, bdrv_flags); + + ret = bdrv_reopen_multiple(queue, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + } + return ret; +} + + +/* + * Prepares a BlockDriverState for reopen. All changes are staged in the + * 'opaque' field of the BDRVReopenState, which is used and allocated by + * the block driver layer .bdrv_reopen_prepare() + * + * bs is the BlockDriverState to reopen + * flags are the new open flags + * queue is the reopen queue + * + * Returns 0 on success, non-zero on error. On error errp will be set + * as well. + * + * On failure, bdrv_reopen_abort() will be called to clean up any data. + * It is the responsibility of the caller to then call the abort() or + * commit() for any other BDS that have been left in a prepare() state + * + */ +int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue, + Error **errp) +{ + int ret = -1; + Error *local_err = NULL; + BlockDriver *drv; + + assert(reopen_state != NULL); + assert(reopen_state->bs->drv != NULL); + drv = reopen_state->bs->drv; + + /* if we are to stay read-only, do not allow permission change + * to r/w */ + if (!(reopen_state->bs->open_flags & BDRV_O_ALLOW_RDWR) && + reopen_state->flags & BDRV_O_RDWR) { + error_set(errp, QERR_DEVICE_IS_READ_ONLY, + reopen_state->bs->device_name); + goto error; + } + + + ret = bdrv_flush(reopen_state->bs); + if (ret) { + error_set(errp, ERROR_CLASS_GENERIC_ERROR, "Error (%s) flushing drive", + strerror(-ret)); + goto error; + } + + if (drv->bdrv_reopen_prepare) { + ret = drv->bdrv_reopen_prepare(reopen_state, queue, &local_err); + if (ret) { + if (local_err != NULL) { + error_propagate(errp, local_err); + } else { + error_set(errp, QERR_OPEN_FILE_FAILED, + reopen_state->bs->filename); + } + goto error; + } + } else { + /* It is currently mandatory to have a bdrv_reopen_prepare() + * handler for each supported drv. */ + error_set(errp, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, + drv->format_name, reopen_state->bs->device_name, + "reopening of file"); + ret = -1; + goto error; + } + + ret = 0; + +error: + return ret; +} + +/* + * Takes the staged changes for the reopen from bdrv_reopen_prepare(), and + * makes them final by swapping the staging BlockDriverState contents into + * the active BlockDriverState contents. + */ +void bdrv_reopen_commit(BDRVReopenState *reopen_state) +{ + BlockDriver *drv; + + assert(reopen_state != NULL); + drv = reopen_state->bs->drv; + assert(drv != NULL); + + /* If there are any driver level actions to take */ + if (drv->bdrv_reopen_commit) { + drv->bdrv_reopen_commit(reopen_state); + } + + /* set BDS specific flags now */ + reopen_state->bs->open_flags = reopen_state->flags; + reopen_state->bs->enable_write_cache = !!(reopen_state->flags & + BDRV_O_CACHE_WB); + reopen_state->bs->read_only = !(reopen_state->flags & BDRV_O_RDWR); +} + +/* + * Abort the reopen, and delete and free the staged changes in + * reopen_state + */ +void bdrv_reopen_abort(BDRVReopenState *reopen_state) +{ + BlockDriver *drv; + + assert(reopen_state != NULL); + drv = reopen_state->bs->drv; + assert(drv != NULL); + + if (drv->bdrv_reopen_abort) { + drv->bdrv_reopen_abort(reopen_state); + } +} + + void bdrv_close(BlockDriverState *bs) { bdrv_flush(bs); diff --git a/block.h b/block.h index 4d919c249f..b1095d8599 100644 --- a/block.h +++ b/block.h @@ -97,6 +97,15 @@ typedef enum { BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP } BlockQMPEventAction; +typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue; + +typedef struct BDRVReopenState { + BlockDriverState *bs; + int flags; + void *opaque; +} BDRVReopenState; + + void bdrv_iostatus_enable(BlockDriverState *bs); void bdrv_iostatus_reset(BlockDriverState *bs); void bdrv_iostatus_disable(BlockDriverState *bs); @@ -131,6 +140,14 @@ int bdrv_parse_cache_flags(const char *mode, int *flags); int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags); int bdrv_open(BlockDriverState *bs, const char *filename, int flags, BlockDriver *drv); +BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue, + BlockDriverState *bs, int flags); +int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp); +int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp); +int bdrv_reopen_prepare(BDRVReopenState *reopen_state, + BlockReopenQueue *queue, Error **errp); +void bdrv_reopen_commit(BDRVReopenState *reopen_state); +void bdrv_reopen_abort(BDRVReopenState *reopen_state); void bdrv_close(BlockDriverState *bs); int bdrv_attach_dev(BlockDriverState *bs, void *dev); void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev); diff --git a/block_int.h b/block_int.h index 4452f6f398..22b3d93d19 100644 --- a/block_int.h +++ b/block_int.h @@ -139,6 +139,13 @@ struct BlockDriver { int instance_size; int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename); int (*bdrv_probe_device)(const char *filename); + + /* For handling image reopen for split or non-split files */ + int (*bdrv_reopen_prepare)(BDRVReopenState *reopen_state, + BlockReopenQueue *queue, Error **errp); + void (*bdrv_reopen_commit)(BDRVReopenState *reopen_state); + void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state); + int (*bdrv_open)(BlockDriverState *bs, int flags); int (*bdrv_file_open)(BlockDriverState *bs, const char *filename, int flags); int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num, @@ -336,6 +343,7 @@ struct BlockDriverState { /* long-running background operation */ BlockJob *job; + }; int get_tmp_filename(char *filename, int size); From fc32a72dc19a79f7e16156784b1e76a128d41841 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:20 -0400 Subject: [PATCH 0550/2270] block: move aio initialization into a helper function Move AIO initialization for raw-posix block driver into a helper function. In addition to just code motion, the aio_ctx pointer is checked for NULL, prior to calling laio_init(), to make sure laio_init() is only run once. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block/raw-posix.c | 53 +++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index 6be20b1925..5981d04473 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -185,6 +185,38 @@ static int raw_normalize_devicepath(const char **filename) } #endif +#ifdef CONFIG_LINUX_AIO +static int raw_set_aio(void **aio_ctx, int *use_aio, int bdrv_flags) +{ + int ret = -1; + assert(aio_ctx != NULL); + assert(use_aio != NULL); + /* + * Currently Linux do AIO only for files opened with O_DIRECT + * specified so check NOCACHE flag too + */ + if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) == + (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) { + + /* if non-NULL, laio_init() has already been run */ + if (*aio_ctx == NULL) { + *aio_ctx = laio_init(); + if (!*aio_ctx) { + goto error; + } + } + *use_aio = 1; + } else { + *use_aio = 0; + } + + ret = 0; + +error: + return ret; +} +#endif + static int raw_open_common(BlockDriverState *bs, const char *filename, int bdrv_flags, int open_flags) { @@ -240,25 +272,10 @@ static int raw_open_common(BlockDriverState *bs, const char *filename, } #ifdef CONFIG_LINUX_AIO - /* - * Currently Linux do AIO only for files opened with O_DIRECT - * specified so check NOCACHE flag too - */ - if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) == - (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) { - - s->aio_ctx = laio_init(); - if (!s->aio_ctx) { - goto out_free_buf; - } - s->use_aio = 1; - } else -#endif - { -#ifdef CONFIG_LINUX_AIO - s->use_aio = 0; -#endif + if (raw_set_aio(&s->aio_ctx, &s->use_aio, bdrv_flags)) { + goto out_close; } +#endif #ifdef CONFIG_XFS if (platform_test_xfs_fd(s->fd)) { From 6a8dc0422e508fc85390e55cbca1b93cb242d22d Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:21 -0400 Subject: [PATCH 0551/2270] block: move open flag parsing in raw block drivers to helper functions Code motion, to move parsing of open flags into a helper function. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block/raw-posix.c | 38 ++++++++++++++++++++++++-------------- block/raw-win32.c | 43 +++++++++++++++++++++++-------------------- 2 files changed, 47 insertions(+), 34 deletions(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index 5981d04473..155205f7ee 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -185,6 +185,28 @@ static int raw_normalize_devicepath(const char **filename) } #endif +static void raw_parse_flags(int bdrv_flags, int *open_flags) +{ + assert(open_flags != NULL); + + *open_flags |= O_BINARY; + *open_flags &= ~O_ACCMODE; + if (bdrv_flags & BDRV_O_RDWR) { + *open_flags |= O_RDWR; + } else { + *open_flags |= O_RDONLY; + } + + /* Use O_DSYNC for write-through caching, no flags for write-back caching, + * and O_DIRECT for no caching. */ + if ((bdrv_flags & BDRV_O_NOCACHE)) { + *open_flags |= O_DIRECT; + } + if (!(bdrv_flags & BDRV_O_CACHE_WB)) { + *open_flags |= O_DSYNC; + } +} + #ifdef CONFIG_LINUX_AIO static int raw_set_aio(void **aio_ctx, int *use_aio, int bdrv_flags) { @@ -228,20 +250,8 @@ static int raw_open_common(BlockDriverState *bs, const char *filename, return ret; } - s->open_flags = open_flags | O_BINARY; - s->open_flags &= ~O_ACCMODE; - if (bdrv_flags & BDRV_O_RDWR) { - s->open_flags |= O_RDWR; - } else { - s->open_flags |= O_RDONLY; - } - - /* Use O_DSYNC for write-through caching, no flags for write-back caching, - * and O_DIRECT for no caching. */ - if ((bdrv_flags & BDRV_O_NOCACHE)) - s->open_flags |= O_DIRECT; - if (!(bdrv_flags & BDRV_O_CACHE_WB)) - s->open_flags |= O_DSYNC; + s->open_flags = open_flags; + raw_parse_flags(bdrv_flags, &s->open_flags); s->fd = -1; fd = qemu_open(filename, s->open_flags, 0644); diff --git a/block/raw-win32.c b/block/raw-win32.c index c56bf83375..335c06a101 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -77,6 +77,26 @@ static int set_sparse(int fd) NULL, 0, NULL, 0, &returned, NULL); } +static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped) +{ + assert(access_flags != NULL); + assert(overlapped != NULL); + + if (flags & BDRV_O_RDWR) { + *access_flags = GENERIC_READ | GENERIC_WRITE; + } else { + *access_flags = GENERIC_READ; + } + + *overlapped = FILE_ATTRIBUTE_NORMAL; + if (flags & BDRV_O_NOCACHE) { + *overlapped |= FILE_FLAG_NO_BUFFERING; + } + if (!(flags & BDRV_O_CACHE_WB)) { + *overlapped |= FILE_FLAG_WRITE_THROUGH; + } +} + static int raw_open(BlockDriverState *bs, const char *filename, int flags) { BDRVRawState *s = bs->opaque; @@ -85,17 +105,8 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags) s->type = FTYPE_FILE; - if (flags & BDRV_O_RDWR) { - access_flags = GENERIC_READ | GENERIC_WRITE; - } else { - access_flags = GENERIC_READ; - } + raw_parse_flags(flags, &access_flags, &overlapped); - overlapped = FILE_ATTRIBUTE_NORMAL; - if (flags & BDRV_O_NOCACHE) - overlapped |= FILE_FLAG_NO_BUFFERING; - if (!(flags & BDRV_O_CACHE_WB)) - overlapped |= FILE_FLAG_WRITE_THROUGH; s->hfile = CreateFile(filename, access_flags, FILE_SHARE_READ, NULL, OPEN_EXISTING, overlapped, NULL); @@ -374,18 +385,10 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags) } s->type = find_device_type(bs, filename); - if (flags & BDRV_O_RDWR) { - access_flags = GENERIC_READ | GENERIC_WRITE; - } else { - access_flags = GENERIC_READ; - } + raw_parse_flags(flags, &access_flags, &overlapped); + create_flags = OPEN_EXISTING; - overlapped = FILE_ATTRIBUTE_NORMAL; - if (flags & BDRV_O_NOCACHE) - overlapped |= FILE_FLAG_NO_BUFFERING; - if (!(flags & BDRV_O_CACHE_WB)) - overlapped |= FILE_FLAG_WRITE_THROUGH; s->hfile = CreateFile(filename, access_flags, FILE_SHARE_READ, NULL, create_flags, overlapped, NULL); From 39c9fb9565613a5ca0ae6e83ea115585f91527bb Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:22 -0400 Subject: [PATCH 0552/2270] block: do not parse BDRV_O_CACHE_WB in block drivers Block drivers should ignore BDRV_O_CACHE_WB in .bdrv_open flags, and in the bs->open_flags. This patch removes the code, leaving the behaviour behind as if BDRV_O_CACHE_WB was set. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block/iscsi.c | 4 ---- block/raw-posix.c | 3 --- block/raw-win32.c | 3 --- block/rbd.c | 6 ------ block/sheepdog.c | 14 ++++++-------- 5 files changed, 6 insertions(+), 24 deletions(-) diff --git a/block/iscsi.c b/block/iscsi.c index 0b96165ec2..70cf700e53 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -268,10 +268,6 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num, acb->task->xfer_dir = SCSI_XFER_WRITE; acb->task->cdb_size = 16; acb->task->cdb[0] = 0x8a; - if (!(bs->open_flags & BDRV_O_CACHE_WB)) { - /* set FUA on writes when cache mode is write through */ - acb->task->cdb[1] |= 0x04; - } lba = sector_qemu2lun(sector_num, iscsilun); *(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32); *(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff); diff --git a/block/raw-posix.c b/block/raw-posix.c index 155205f7ee..288e7ff238 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -202,9 +202,6 @@ static void raw_parse_flags(int bdrv_flags, int *open_flags) if ((bdrv_flags & BDRV_O_NOCACHE)) { *open_flags |= O_DIRECT; } - if (!(bdrv_flags & BDRV_O_CACHE_WB)) { - *open_flags |= O_DSYNC; - } } #ifdef CONFIG_LINUX_AIO diff --git a/block/raw-win32.c b/block/raw-win32.c index 335c06a101..78c830648b 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -92,9 +92,6 @@ static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped) if (flags & BDRV_O_NOCACHE) { *overlapped |= FILE_FLAG_NO_BUFFERING; } - if (!(flags & BDRV_O_CACHE_WB)) { - *overlapped |= FILE_FLAG_WRITE_THROUGH; - } } static int raw_open(BlockDriverState *bs, const char *filename, int flags) diff --git a/block/rbd.c b/block/rbd.c index 5a0f79fc8f..015a9db0ad 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -487,12 +487,6 @@ static int qemu_rbd_open(BlockDriverState *bs, const char *filename, int flags) rados_conf_set(s->cluster, "rbd_cache", "false"); } else { rados_conf_set(s->cluster, "rbd_cache", "true"); - if (!(flags & BDRV_O_CACHE_WB)) { - r = rados_conf_set(s->cluster, "rbd_cache_max_dirty", "0"); - if (r < 0) { - rados_conf_set(s->cluster, "rbd_cache", "false"); - } - } } if (strstr(conf, "conf=") == NULL) { diff --git a/block/sheepdog.c b/block/sheepdog.c index e0753ee9e5..4742f8ae6f 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1114,14 +1114,12 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags) goto out; } - if (flags & BDRV_O_CACHE_WB) { - s->cache_enabled = 1; - s->flush_fd = connect_to_sdog(s->addr, s->port); - if (s->flush_fd < 0) { - error_report("failed to connect"); - ret = s->flush_fd; - goto out; - } + s->cache_enabled = 1; + s->flush_fd = connect_to_sdog(s->addr, s->port); + if (s->flush_fd < 0) { + error_report("failed to connect"); + ret = s->flush_fd; + goto out; } if (snapid || tag[0] != '\0') { From 9acc5a06d41416400dda0ae9495707236911e234 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:23 -0400 Subject: [PATCH 0553/2270] block: use BDRV_O_NOCACHE instead of s->aligned_buf in raw-posix.c Rather than check for a non-NULL aligned_buf to determine if raw_aio_submit needs to check for alignment, check for the presence of BDRV_O_NOCACHE in the bs->open_flags. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block/raw-posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index 288e7ff238..1e727eb042 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -354,7 +354,7 @@ static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs, * boundary. Check if this is the case or tell the low-level * driver that it needs to copy the buffer. */ - if (s->aligned_buf) { + if ((bs->open_flags & BDRV_O_NOCACHE)) { if (!qiov_is_aligned(bs, qiov)) { type |= QEMU_AIO_MISALIGNED; #ifdef CONFIG_LINUX_AIO From 3d1807ac6707773526b193f296e72c6c86969bf7 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:24 -0400 Subject: [PATCH 0554/2270] block: purge s->aligned_buf and s->aligned_buf_size from raw-posix.c The aligned_buf pointer and aligned_buf size are no longer used in raw_posix.c, so remove all references to them. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block/raw-posix.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index 1e727eb042..0ffb3d0e92 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -133,8 +133,6 @@ typedef struct BDRVRawState { int use_aio; void *aio_ctx; #endif - uint8_t *aligned_buf; - unsigned aligned_buf_size; #ifdef CONFIG_XFS bool is_xfs : 1; #endif @@ -259,23 +257,10 @@ static int raw_open_common(BlockDriverState *bs, const char *filename, return ret; } s->fd = fd; - s->aligned_buf = NULL; - - if ((bdrv_flags & BDRV_O_NOCACHE)) { - /* - * Allocate a buffer for read/modify/write cycles. Chose the size - * pessimistically as we don't know the block size yet. - */ - s->aligned_buf_size = 32 * MAX_BLOCKSIZE; - s->aligned_buf = qemu_memalign(MAX_BLOCKSIZE, s->aligned_buf_size); - if (s->aligned_buf == NULL) { - goto out_close; - } - } /* We're falling back to POSIX AIO in some cases so init always */ if (paio_init() < 0) { - goto out_free_buf; + goto out_close; } #ifdef CONFIG_LINUX_AIO @@ -292,8 +277,6 @@ static int raw_open_common(BlockDriverState *bs, const char *filename, return 0; -out_free_buf: - qemu_vfree(s->aligned_buf); out_close: qemu_close(fd); return -errno; @@ -402,8 +385,6 @@ static void raw_close(BlockDriverState *bs) if (s->fd >= 0) { qemu_close(s->fd); s->fd = -1; - if (s->aligned_buf != NULL) - qemu_vfree(s->aligned_buf); } } From eeb6b45d48800e96f67ef2a5c80332557fd45ddb Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:25 -0400 Subject: [PATCH 0555/2270] block: raw-posix image file reopen This is derived from the Supriya Kannery's reopen patches. This contains the raw-posix driver changes for the bdrv_reopen_* functions. All changes are staged into a temporary scratch buffer during the prepare() stage, and copied over to the live structure during commit(). Upon abort(), all changes are abandoned, and the live structures are unmodified. The _prepare() will create an extra fd - either by means of a dup, if possible, or opening a new fd if not (for instance, access control changes). Upon _commit(), the original fd is closed and the new fd is used. Upon _abort(), the duplicate/new fd is closed. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block/raw-posix.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/block/raw-posix.c b/block/raw-posix.c index 0ffb3d0e92..28d439fa81 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -138,6 +138,14 @@ typedef struct BDRVRawState { #endif } BDRVRawState; +typedef struct BDRVRawReopenState { + int fd; + int open_flags; +#ifdef CONFIG_LINUX_AIO + int use_aio; +#endif +} BDRVRawReopenState; + static int fd_open(BlockDriverState *bs); static int64_t raw_getlength(BlockDriverState *bs); @@ -290,6 +298,109 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags) return raw_open_common(bs, filename, flags, 0); } +static int raw_reopen_prepare(BDRVReopenState *state, + BlockReopenQueue *queue, Error **errp) +{ + BDRVRawState *s; + BDRVRawReopenState *raw_s; + int ret = 0; + + assert(state != NULL); + assert(state->bs != NULL); + + s = state->bs->opaque; + + state->opaque = g_malloc0(sizeof(BDRVRawReopenState)); + raw_s = state->opaque; + +#ifdef CONFIG_LINUX_AIO + raw_s->use_aio = s->use_aio; + + /* we can use s->aio_ctx instead of a copy, because the use_aio flag is + * valid in the 'false' condition even if aio_ctx is set, and raw_set_aio() + * won't override aio_ctx if aio_ctx is non-NULL */ + if (raw_set_aio(&s->aio_ctx, &raw_s->use_aio, state->flags)) { + return -1; + } +#endif + + raw_parse_flags(state->flags, &raw_s->open_flags); + + raw_s->fd = -1; + + int fcntl_flags = O_APPEND | O_ASYNC | O_NONBLOCK; +#ifdef O_NOATIME + fcntl_flags |= O_NOATIME; +#endif + + if ((raw_s->open_flags & ~fcntl_flags) == (s->open_flags & ~fcntl_flags)) { + /* dup the original fd */ + /* TODO: use qemu fcntl wrapper */ +#ifdef F_DUPFD_CLOEXEC + raw_s->fd = fcntl(s->fd, F_DUPFD_CLOEXEC, 0); +#else + raw_s->fd = dup(s->fd); + if (raw_s->fd != -1) { + qemu_set_cloexec(raw_s->fd); + } +#endif + if (raw_s->fd >= 0) { + ret = fcntl_setfl(raw_s->fd, raw_s->open_flags); + if (ret) { + qemu_close(raw_s->fd); + raw_s->fd = -1; + } + } + } + + /* If we cannot use fcntl, or fcntl failed, fall back to qemu_open() */ + if (raw_s->fd == -1) { + assert(!(raw_s->open_flags & O_CREAT)); + raw_s->fd = qemu_open(state->bs->filename, raw_s->open_flags); + if (raw_s->fd == -1) { + ret = -1; + } + } + return ret; +} + + +static void raw_reopen_commit(BDRVReopenState *state) +{ + BDRVRawReopenState *raw_s = state->opaque; + BDRVRawState *s = state->bs->opaque; + + s->open_flags = raw_s->open_flags; + + qemu_close(s->fd); + s->fd = raw_s->fd; +#ifdef CONFIG_LINUX_AIO + s->use_aio = raw_s->use_aio; +#endif + + g_free(state->opaque); + state->opaque = NULL; +} + + +static void raw_reopen_abort(BDRVReopenState *state) +{ + BDRVRawReopenState *raw_s = state->opaque; + + /* nothing to do if NULL, we didn't get far enough */ + if (raw_s == NULL) { + return; + } + + if (raw_s->fd >= 0) { + qemu_close(raw_s->fd); + raw_s->fd = -1; + } + g_free(state->opaque); + state->opaque = NULL; +} + + /* XXX: use host sector size if necessary with: #ifdef DIOCGSECTORSIZE { @@ -740,6 +851,9 @@ static BlockDriver bdrv_file = { .instance_size = sizeof(BDRVRawState), .bdrv_probe = NULL, /* no probe for protocols */ .bdrv_file_open = raw_open, + .bdrv_reopen_prepare = raw_reopen_prepare, + .bdrv_reopen_commit = raw_reopen_commit, + .bdrv_reopen_abort = raw_reopen_abort, .bdrv_close = raw_close, .bdrv_create = raw_create, .bdrv_co_discard = raw_co_discard, From 01bdddb5aaf4f660355cf764874f19271978f74f Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:26 -0400 Subject: [PATCH 0556/2270] block: raw image file reopen These are the stubs for the file reopen drivers for the raw format. There is currently nothing that needs to be done by the raw driver in reopen. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block/raw.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/block/raw.c b/block/raw.c index ff34ea41e7..253e949b8c 100644 --- a/block/raw.c +++ b/block/raw.c @@ -9,6 +9,14 @@ static int raw_open(BlockDriverState *bs, int flags) return 0; } +/* We have nothing to do for raw reopen, stubs just return + * success */ +static int raw_reopen_prepare(BDRVReopenState *state, + BlockReopenQueue *queue, Error **errp) +{ + return 0; +} + static int coroutine_fn raw_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov) { @@ -115,6 +123,8 @@ static BlockDriver bdrv_raw = { .bdrv_open = raw_open, .bdrv_close = raw_close, + .bdrv_reopen_prepare = raw_reopen_prepare, + .bdrv_co_readv = raw_co_readv, .bdrv_co_writev = raw_co_writev, .bdrv_co_is_allocated = raw_co_is_allocated, From f9cb20f167ff205e37a895ee6a03d5a183ef8acf Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:27 -0400 Subject: [PATCH 0557/2270] block: qed image file reopen These are the stubs for the file reopen drivers for the qed format. There is currently nothing that needs to be done by the qed driver in reopen. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block/qed.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/block/qed.c b/block/qed.c index 21cb239870..6c182ca917 100644 --- a/block/qed.c +++ b/block/qed.c @@ -505,6 +505,14 @@ out: return ret; } +/* We have nothing to do for QED reopen, stubs just return + * success */ +static int bdrv_qed_reopen_prepare(BDRVReopenState *state, + BlockReopenQueue *queue, Error **errp) +{ + return 0; +} + static void bdrv_qed_close(BlockDriverState *bs) { BDRVQEDState *s = bs->opaque; @@ -1564,6 +1572,7 @@ static BlockDriver bdrv_qed = { .bdrv_rebind = bdrv_qed_rebind, .bdrv_open = bdrv_qed_open, .bdrv_close = bdrv_qed_close, + .bdrv_reopen_prepare = bdrv_qed_reopen_prepare, .bdrv_create = bdrv_qed_create, .bdrv_co_is_allocated = bdrv_qed_co_is_allocated, .bdrv_make_empty = bdrv_qed_make_empty, From 21d82ac95f67947ebc32ada96184f00831a9b911 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:28 -0400 Subject: [PATCH 0558/2270] block: qcow2 image file reopen These are the stubs for the file reopen drivers for the qcow2 format. There is currently nothing that needs to be done by the qcow2 driver in reopen. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block/qcow2.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/block/qcow2.c b/block/qcow2.c index 8f183f1465..aa5e603cd3 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -52,6 +52,7 @@ typedef struct { uint32_t magic; uint32_t len; } QCowExtension; + #define QCOW2_EXT_MAGIC_END 0 #define QCOW2_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA #define QCOW2_EXT_MAGIC_FEATURE_TABLE 0x6803f857 @@ -558,6 +559,14 @@ static int qcow2_set_key(BlockDriverState *bs, const char *key) return 0; } +/* We have nothing to do for QCOW2 reopen, stubs just return + * success */ +static int qcow2_reopen_prepare(BDRVReopenState *state, + BlockReopenQueue *queue, Error **errp) +{ + return 0; +} + static int coroutine_fn qcow2_co_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum) { @@ -1679,6 +1688,7 @@ static BlockDriver bdrv_qcow2 = { .bdrv_probe = qcow2_probe, .bdrv_open = qcow2_open, .bdrv_close = qcow2_close, + .bdrv_reopen_prepare = qcow2_reopen_prepare, .bdrv_create = qcow2_create, .bdrv_co_is_allocated = qcow2_co_is_allocated, .bdrv_set_key = qcow2_set_key, From d177692ede3129dcb18a6b0f5472577bed2e2688 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:29 -0400 Subject: [PATCH 0559/2270] block: qcow image file reopen These are the stubs for the file reopen drivers for the qcow format. There is currently nothing that needs to be done by the qcow driver in reopen. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block/qcow.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/block/qcow.c b/block/qcow.c index 7b5ab87d2d..b239c82ae0 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -197,6 +197,15 @@ static int qcow_open(BlockDriverState *bs, int flags) return ret; } + +/* We have nothing to do for QCOW reopen, stubs just return + * success */ +static int qcow_reopen_prepare(BDRVReopenState *state, + BlockReopenQueue *queue, Error **errp) +{ + return 0; +} + static int qcow_set_key(BlockDriverState *bs, const char *key) { BDRVQcowState *s = bs->opaque; @@ -868,6 +877,7 @@ static BlockDriver bdrv_qcow = { .bdrv_probe = qcow_probe, .bdrv_open = qcow_open, .bdrv_close = qcow_close, + .bdrv_reopen_prepare = qcow_reopen_prepare, .bdrv_create = qcow_create, .bdrv_co_readv = qcow_co_readv, From 3897575f1cd96370a604be8cb5cf1e3fae2be0c1 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:30 -0400 Subject: [PATCH 0560/2270] block: vmdk image file reopen This patch supports reopen for VMDK image files. VMDK extents are added to the existing reopen queue, so that the transactional model of reopen is maintained with multiple image files. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block/vmdk.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/block/vmdk.c b/block/vmdk.c index bba4c61a74..f2e861b074 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -300,6 +300,40 @@ static int vmdk_is_cid_valid(BlockDriverState *bs) return 1; } +/* Queue extents, if any, for reopen() */ +static int vmdk_reopen_prepare(BDRVReopenState *state, + BlockReopenQueue *queue, Error **errp) +{ + BDRVVmdkState *s; + int ret = -1; + int i; + VmdkExtent *e; + + assert(state != NULL); + assert(state->bs != NULL); + + if (queue == NULL) { + error_set(errp, ERROR_CLASS_GENERIC_ERROR, + "No reopen queue for VMDK extents"); + goto exit; + } + + s = state->bs->opaque; + + assert(s != NULL); + + for (i = 0; i < s->num_extents; i++) { + e = &s->extents[i]; + if (e->file != state->bs->file) { + bdrv_reopen_queue(queue, e->file, state->flags); + } + } + ret = 0; + +exit: + return ret; +} + static int vmdk_parent_open(BlockDriverState *bs) { char *p_name; @@ -1646,6 +1680,7 @@ static BlockDriver bdrv_vmdk = { .instance_size = sizeof(BDRVVmdkState), .bdrv_probe = vmdk_probe, .bdrv_open = vmdk_open, + .bdrv_reopen_prepare = vmdk_reopen_prepare, .bdrv_read = vmdk_co_read, .bdrv_write = vmdk_co_write, .bdrv_close = vmdk_close, From ecfe2bbabbc25e08b21ae57d66e484ef64c4aefa Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:32 -0400 Subject: [PATCH 0561/2270] block: vdi image file reopen There is currently nothing that needs to be done for VDI reopen. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block/vdi.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/block/vdi.c b/block/vdi.c index 550cf58a39..f35b12ec98 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -454,6 +454,12 @@ static int vdi_open(BlockDriverState *bs, int flags) return -1; } +static int vdi_reopen_prepare(BDRVReopenState *state, + BlockReopenQueue *queue, Error **errp) +{ + return 0; +} + static int coroutine_fn vdi_co_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum) { @@ -761,6 +767,7 @@ static BlockDriver bdrv_vdi = { .bdrv_probe = vdi_probe, .bdrv_open = vdi_open, .bdrv_close = vdi_close, + .bdrv_reopen_prepare = vdi_reopen_prepare, .bdrv_create = vdi_create, .bdrv_co_is_allocated = vdi_co_is_allocated, .bdrv_make_empty = vdi_make_empty, From 3fe4b70008f3a0323e1d685becc6a9cff2b71de7 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:33 -0400 Subject: [PATCH 0562/2270] block: vpc image file reopen There is currently nothing that needs to be done for VPC image file reopen. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block/vpc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/block/vpc.c b/block/vpc.c index c0b82c4f57..b6bf52f140 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -265,6 +265,12 @@ static int vpc_open(BlockDriverState *bs, int flags) return err; } +static int vpc_reopen_prepare(BDRVReopenState *state, + BlockReopenQueue *queue, Error **errp) +{ + return 0; +} + /* * Returns the absolute byte offset of the given sector in the image file. * If the sector is not allocated, -1 is returned instead. @@ -783,6 +789,7 @@ static BlockDriver bdrv_vpc = { .bdrv_probe = vpc_probe, .bdrv_open = vpc_open, .bdrv_close = vpc_close, + .bdrv_reopen_prepare = vpc_reopen_prepare, .bdrv_create = vpc_create, .bdrv_read = vpc_co_read, From 0bce597d6ec34b2af802799eb53ebc863c704d05 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:34 -0400 Subject: [PATCH 0563/2270] block: convert bdrv_commit() to use bdrv_reopen() Currently, bdrv_commit() reopens images r/w itself, via risky _delete() and _open() calls. Use the new safe method for drive reopen. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block.c | 48 +++++------------------------------------------- 1 file changed, 5 insertions(+), 43 deletions(-) diff --git a/block.c b/block.c index c7c1a3bd33..84544d23bb 100644 --- a/block.c +++ b/block.c @@ -1501,13 +1501,11 @@ int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix) int bdrv_commit(BlockDriverState *bs) { BlockDriver *drv = bs->drv; - BlockDriver *backing_drv; int64_t sector, total_sectors; int n, ro, open_flags; - int ret = 0, rw_ret = 0; + int ret = 0; uint8_t *buf; char filename[1024]; - BlockDriverState *bs_rw, *bs_ro; if (!drv) return -ENOMEDIUM; @@ -1516,42 +1514,18 @@ int bdrv_commit(BlockDriverState *bs) return -ENOTSUP; } - if (bs->backing_hd->keep_read_only) { - return -EACCES; - } - if (bdrv_in_use(bs) || bdrv_in_use(bs->backing_hd)) { return -EBUSY; } - backing_drv = bs->backing_hd->drv; ro = bs->backing_hd->read_only; strncpy(filename, bs->backing_hd->filename, sizeof(filename)); open_flags = bs->backing_hd->open_flags; if (ro) { - /* re-open as RW */ - bdrv_delete(bs->backing_hd); - bs->backing_hd = NULL; - bs_rw = bdrv_new(""); - rw_ret = bdrv_open(bs_rw, filename, open_flags | BDRV_O_RDWR, - backing_drv); - if (rw_ret < 0) { - bdrv_delete(bs_rw); - /* try to re-open read-only */ - bs_ro = bdrv_new(""); - ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, - backing_drv); - if (ret < 0) { - bdrv_delete(bs_ro); - /* drive not functional anymore */ - bs->drv = NULL; - return ret; - } - bs->backing_hd = bs_ro; - return rw_ret; + if (bdrv_reopen(bs->backing_hd, open_flags | BDRV_O_RDWR, NULL)) { + return -EACCES; } - bs->backing_hd = bs_rw; } total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS; @@ -1588,20 +1562,8 @@ ro_cleanup: g_free(buf); if (ro) { - /* re-open as RO */ - bdrv_delete(bs->backing_hd); - bs->backing_hd = NULL; - bs_ro = bdrv_new(""); - ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, - backing_drv); - if (ret < 0) { - bdrv_delete(bs_ro); - /* drive not functional anymore */ - bs->drv = NULL; - return ret; - } - bs->backing_hd = bs_ro; - bs->backing_hd->keep_read_only = 0; + /* ignoring error return here */ + bdrv_reopen(bs->backing_hd, open_flags & ~BDRV_O_RDWR, NULL); } return ret; From dc1c13d96912731d4c7c7e13d31c93b8735f1203 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 20 Sep 2012 15:13:35 -0400 Subject: [PATCH 0564/2270] block: remove keep_read_only flag from BlockDriverState struct The keep_read_only flag is no longer used, in favor of the bdrv flag BDRV_O_ALLOW_RDWR. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- block.c | 2 -- block_int.h | 1 - 2 files changed, 3 deletions(-) diff --git a/block.c b/block.c index 84544d23bb..751ebdc06b 100644 --- a/block.c +++ b/block.c @@ -812,8 +812,6 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, flags |= BDRV_O_ALLOW_RDWR; } - bs->keep_read_only = !(flags & BDRV_O_ALLOW_RDWR); - /* Open the image */ ret = bdrv_open_common(bs, filename, flags, drv); if (ret < 0) { diff --git a/block_int.h b/block_int.h index 22b3d93d19..ac4245cb18 100644 --- a/block_int.h +++ b/block_int.h @@ -275,7 +275,6 @@ struct BlockDriverState { int64_t total_sectors; /* if we are reading a disk image, give its size in sectors */ int read_only; /* if true, the media is read only */ - int keep_read_only; /* if true, the media was requested to stay read only */ int open_flags; /* flags used to open the file, re-used for re-open */ int encrypted; /* if true, the media is encrypted */ int valid_key; /* if true, a valid encryption key has been set */ From 8f06bf693dec29642255adcc2828bc6b7daa83d9 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 22 Sep 2012 23:08:38 +0200 Subject: [PATCH 0565/2270] tcg/mips: fix MIPS32(R2) detection Fix the MIPS32(R2) cpu detection so that it also works with -march=octeon. Thanks to Andrew Pinski for the hint. Cc: Andrew Pinski Signed-off-by: Aurelien Jarno --- tcg/mips/tcg-target.c | 10 +++++----- tcg/mips/tcg-target.h | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index f70910a90f..34e3e7f823 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -419,7 +419,7 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type, static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg) { -#ifdef _MIPS_ARCH_MIPS32R2 +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg); #else /* ret and arg can't be register at */ @@ -436,7 +436,7 @@ static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg) static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg) { -#ifdef _MIPS_ARCH_MIPS32R2 +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg); tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret); #else @@ -454,7 +454,7 @@ static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg) static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg) { -#ifdef _MIPS_ARCH_MIPS32R2 +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg); tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16); #else @@ -480,7 +480,7 @@ static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg) static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg) { -#ifdef _MIPS_ARCH_MIPS32R2 +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg); #else tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24); @@ -490,7 +490,7 @@ static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg) static inline void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg) { -#ifdef _MIPS_ARCH_MIPS32R2 +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg); #else tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16); diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index d147e70eb1..7020d65845 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -88,16 +88,16 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 0 /* optional instructions only implemented on MIPS4, MIPS32 and Loongson 2 */ -#if defined(_MIPS_ARCH_MIPS4) || defined(_MIPS_ARCH_MIPS32) || \ - defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_LOONGSON2E) || \ - defined(_MIPS_ARCH_LOONGSON2F) +#if (defined(__mips_isa_rev) && (__mips_isa_rev >= 1)) || \ + defined(_MIPS_ARCH_LOONGSON2E) || defined(_MIPS_ARCH_LOONGSON2F) || \ + defined(_MIPS_ARCH_MIPS4) #define TCG_TARGET_HAS_movcond_i32 1 #else #define TCG_TARGET_HAS_movcond_i32 0 #endif /* optional instructions only implemented on MIPS32R2 */ -#ifdef _MIPS_ARCH_MIPS32R2 +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) #define TCG_TARGET_HAS_bswap16_i32 1 #define TCG_TARGET_HAS_bswap32_i32 1 #define TCG_TARGET_HAS_rot_i32 1 From 5a696f6ac0641f200cdd2dfe7a6fd397d48ea7bd Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 17:18:09 -0700 Subject: [PATCH 0566/2270] tcg: Adjust descriptions of *cond opcodes The README file documented the operand ordering of the tcg_gen_* functions. Since we're documenting opcodes here, use the true operand ordering. Signed-off-by: Richard Henderson Cc: malc Signed-off-by: Aurelien Jarno --- tcg/README | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tcg/README b/tcg/README index 33783ee17b..27846f1ea4 100644 --- a/tcg/README +++ b/tcg/README @@ -141,7 +141,7 @@ Define label 'label' at the current program point. Jump to label. -* brcond_i32/i64 cond, t0, t1, label +* brcond_i32/i64 t0, t1, cond, label Conditional jump if t0 cond t1 is true. cond can be: TCG_COND_EQ @@ -301,13 +301,13 @@ This operation would be equivalent to ********* Conditional moves -* setcond_i32/i64 cond, dest, t1, t2 +* setcond_i32/i64 dest, t1, t2, cond dest = (t1 cond t2) Set DEST to 1 if (T1 cond T2) is true, otherwise set to 0. -* movcond_i32/i64 cond, dest, c1, c2, v1, v2 +* movcond_i32/i64 dest, c1, c2, v1, v2, cond dest = (c1 cond c2 ? v1 : v2) @@ -360,7 +360,7 @@ The following opcodes are internal to TCG. Thus they are to be implemented by 32-bit host code generators, but are not to be emitted by guest translators. They are emitted as needed by inline functions within "tcg-op.h". -* brcond2_i32 cond, t0_low, t0_high, t1_low, t1_high, label +* brcond2_i32 t0_low, t0_high, t1_low, t1_high, cond, label Similar to brcond, except that the 64-bit values T0 and T1 are formed from two 32-bit arguments. @@ -377,7 +377,7 @@ is returned in two 32-bit outputs. Similar to mul, except two 32-bit (unsigned) inputs T1 and T2 yielding the full 64-bit product T0. The later is returned in two 32-bit outputs. -* setcond2_i32 cond, dest, t1_low, t1_high, t2_low, t2_high +* setcond2_i32 dest, t1_low, t1_high, t2_low, t2_high, cond Similar to setcond, except that the 64-bit values T1 and T2 are formed from two 32-bit arguments. The result is a 32-bit value. From 42ce3e2015b26df591e1d4c5aa1814fb8c45c36c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 17:18:10 -0700 Subject: [PATCH 0567/2270] tcg: Emit ANDI as EXTU for appropriate constants Note that andi_i64 failed to perform even the minimal optimizations promised by the README. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg-op.h | 65 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 10 deletions(-) diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 6d28f82ad8..c8633ffd78 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -518,18 +518,34 @@ static inline void tcg_gen_and_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) } } -static inline void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) +static inline void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2) { - /* some cases can be optimized here */ - if (arg2 == 0) { + TCGv_i32 t0; + /* Some cases can be optimized here. */ + switch (arg2) { + case 0: tcg_gen_movi_i32(ret, 0); - } else if (arg2 == 0xffffffff) { + return; + case 0xffffffffu: tcg_gen_mov_i32(ret, arg1); - } else { - TCGv_i32 t0 = tcg_const_i32(arg2); - tcg_gen_and_i32(ret, arg1, t0); - tcg_temp_free_i32(t0); + return; + case 0xffu: + /* Don't recurse with tcg_gen_ext8u_i32. */ + if (TCG_TARGET_HAS_ext8u_i32) { + tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg1); + return; + } + break; + case 0xffffu: + if (TCG_TARGET_HAS_ext16u_i32) { + tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg1); + return; + } + break; } + t0 = tcg_const_i32(arg2); + tcg_gen_and_i32(ret, arg1, t0); + tcg_temp_free_i32(t0); } static inline void tcg_gen_or_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) @@ -1120,9 +1136,38 @@ static inline void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) } } -static inline void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) +static inline void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2) { - TCGv_i64 t0 = tcg_const_i64(arg2); + TCGv_i64 t0; + /* Some cases can be optimized here. */ + switch (arg2) { + case 0: + tcg_gen_movi_i64(ret, 0); + return; + case 0xffffffffffffffffull: + tcg_gen_mov_i64(ret, arg1); + return; + case 0xffull: + /* Don't recurse with tcg_gen_ext8u_i32. */ + if (TCG_TARGET_HAS_ext8u_i64) { + tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1); + return; + } + break; + case 0xffffu: + if (TCG_TARGET_HAS_ext16u_i64) { + tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1); + return; + } + break; + case 0xffffffffull: + if (TCG_TARGET_HAS_ext32u_i64) { + tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1); + return; + } + break; + } + t0 = tcg_const_i64(arg2); tcg_gen_and_i64(ret, arg1, t0); tcg_temp_free_i64(t0); } From d81ada7fa43e588a24856da4bfcdcac020d8e25b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 17:18:11 -0700 Subject: [PATCH 0568/2270] tcg: Optimize initial inputs for ori_i64 Copy the same optimizations from ori_i32. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg-op.h | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index c8633ffd78..fd1649996c 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -559,9 +559,9 @@ static inline void tcg_gen_or_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) static inline void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) { - /* some cases can be optimized here */ - if (arg2 == 0xffffffff) { - tcg_gen_movi_i32(ret, 0xffffffff); + /* Some cases can be optimized here. */ + if (arg2 == -1) { + tcg_gen_movi_i32(ret, -1); } else if (arg2 == 0) { tcg_gen_mov_i32(ret, arg1); } else { @@ -1183,9 +1183,16 @@ static inline void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) static inline void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) { - TCGv_i64 t0 = tcg_const_i64(arg2); - tcg_gen_or_i64(ret, arg1, t0); - tcg_temp_free_i64(t0); + /* Some cases can be optimized here. */ + if (arg2 == -1) { + tcg_gen_movi_i64(ret, -1); + } else if (arg2 == 0) { + tcg_gen_mov_i64(ret, arg1); + } else { + TCGv_i64 t0 = tcg_const_i64(arg2); + tcg_gen_or_i64(ret, arg1, t0); + tcg_temp_free_i64(t0); + } } static inline void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) From 6f3bb33eaa79570b7009f3704ca55c4f8296219f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 17:18:12 -0700 Subject: [PATCH 0569/2270] tcg: Emit XORI as NOT for appropriate constants Note that xori_i64 failed to perform even the minimal optimizations promised by the README. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg-op.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index fd1649996c..bcfb60b507 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -582,9 +582,12 @@ static inline void tcg_gen_xor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) static inline void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) { - /* some cases can be optimized here */ + /* Some cases can be optimized here. */ if (arg2 == 0) { tcg_gen_mov_i32(ret, arg1); + } else if (arg2 == -1 && TCG_TARGET_HAS_not_i32) { + /* Don't recurse with tcg_gen_not_i32. */ + tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1); } else { TCGv_i32 t0 = tcg_const_i32(arg2); tcg_gen_xor_i32(ret, arg1, t0); @@ -1206,9 +1209,17 @@ static inline void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) static inline void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) { - TCGv_i64 t0 = tcg_const_i64(arg2); - tcg_gen_xor_i64(ret, arg1, t0); - tcg_temp_free_i64(t0); + /* Some cases can be optimized here. */ + if (arg2 == 0) { + tcg_gen_mov_i64(ret, arg1); + } else if (arg2 == -1 && TCG_TARGET_HAS_not_i64) { + /* Don't recurse with tcg_gen_not_i64. */ + tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1); + } else { + TCGv_i64 t0 = tcg_const_i64(arg2); + tcg_gen_xor_i64(ret, arg1, t0); + tcg_temp_free_i64(t0); + } } static inline void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) From 77276f6581b660a14bec069ec8d20f1280bddeb6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 17:18:13 -0700 Subject: [PATCH 0570/2270] tcg: Implement concat*_i64 with deposit_i64 For tcg_gen_concat_i32_i64 we only use deposit if the host supports it. For tcg_gen_concat32_i64 even if the host does not, as we get identical code before and after. Note that this relies on the ANDI -> EXTU patch for the identity claim. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg-op.h | 60 ++++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index bcfb60b507..d2fb283764 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -1809,36 +1809,6 @@ static inline void tcg_gen_discard_i64(TCGv_i64 arg) #endif } -static inline void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high) -{ -#if TCG_TARGET_REG_BITS == 32 - tcg_gen_mov_i32(TCGV_LOW(dest), low); - tcg_gen_mov_i32(TCGV_HIGH(dest), high); -#else - TCGv_i64 tmp = tcg_temp_new_i64(); - /* This extension is only needed for type correctness. - We may be able to do better given target specific information. */ - tcg_gen_extu_i32_i64(tmp, high); - tcg_gen_shli_i64(tmp, tmp, 32); - tcg_gen_extu_i32_i64(dest, low); - tcg_gen_or_i64(dest, dest, tmp); - tcg_temp_free_i64(tmp); -#endif -} - -static inline void tcg_gen_concat32_i64(TCGv_i64 dest, TCGv_i64 low, TCGv_i64 high) -{ -#if TCG_TARGET_REG_BITS == 32 - tcg_gen_concat_i32_i64(dest, TCGV_LOW(low), TCGV_LOW(high)); -#else - TCGv_i64 tmp = tcg_temp_new_i64(); - tcg_gen_ext32u_i64(dest, low); - tcg_gen_shli_i64(tmp, high, 32); - tcg_gen_or_i64(dest, dest, tmp); - tcg_temp_free_i64(tmp); -#endif -} - static inline void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) { if (TCG_TARGET_HAS_andc_i32) { @@ -2181,6 +2151,36 @@ static inline void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, tcg_temp_free_i64(t1); } +static inline void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, + TCGv_i32 high) +{ +#if TCG_TARGET_REG_BITS == 32 + tcg_gen_mov_i32(TCGV_LOW(dest), low); + tcg_gen_mov_i32(TCGV_HIGH(dest), high); +#else + TCGv_i64 tmp = tcg_temp_new_i64(); + /* These extensions are only needed for type correctness. + We may be able to do better given target specific information. */ + tcg_gen_extu_i32_i64(tmp, high); + tcg_gen_extu_i32_i64(dest, low); + /* If deposit is available, use it. Otherwise use the extra + knowledge that we have of the zero-extensions above. */ + if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) { + tcg_gen_deposit_i64(dest, dest, tmp, 32, 32); + } else { + tcg_gen_shli_i64(tmp, tmp, 32); + tcg_gen_or_i64(dest, dest, tmp); + } + tcg_temp_free_i64(tmp); +#endif +} + +static inline void tcg_gen_concat32_i64(TCGv_i64 dest, TCGv_i64 low, + TCGv_i64 high) +{ + tcg_gen_deposit_i64(dest, low, high, 32, 32); +} + static inline void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1, TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2) From c552d6c038f7cf4058d1fd5987118ffd41e0e050 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 17:18:14 -0700 Subject: [PATCH 0571/2270] tcg: Add tcg_debug_assert Like the C assert macro, except only enabled for CONFIG_DEBUG_TCG, and without having to set _NDEBUG and disable all other asserts at the same time. The use of __builtin_unreachable (when available) gives the compiler the same information, which may (or may not) help it optimize better. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tcg/tcg.h b/tcg/tcg.h index 48a56f0b15..4501c1520f 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -530,6 +530,15 @@ do {\ abort();\ } while (0) +#ifdef CONFIG_DEBUG_TCG +# define tcg_debug_assert(X) do { assert(X); } while (0) +#elif QEMU_GNUC_PREREQ(4, 5) +# define tcg_debug_assert(X) \ + do { if (!(X)) { __builtin_unreachable(); } } while (0) +#else +# define tcg_debug_assert(X) do { (void)(X); } while (0) +#endif + void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs); #if TCG_TARGET_REG_BITS == 32 From 717e70368bdc339d241f84aba00ed72d051e0236 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 17:18:15 -0700 Subject: [PATCH 0572/2270] tcg: Sanity check deposit inputs Given these are constants, checking once here means everything after can assume they're correct. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg-op.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index d2fb283764..ecb1ac3e2e 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -2081,6 +2081,10 @@ static inline void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t mask; TCGv_i32 t1; + tcg_debug_assert(ofs < 32); + tcg_debug_assert(len <= 32); + tcg_debug_assert(ofs + len <= 32); + if (ofs == 0 && len == 32) { tcg_gen_mov_i32(ret, arg2); return; @@ -2112,6 +2116,10 @@ static inline void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t mask; TCGv_i64 t1; + tcg_debug_assert(ofs < 64); + tcg_debug_assert(len <= 64); + tcg_debug_assert(ofs + len <= 64); + if (ofs == 0 && len == 64) { tcg_gen_mov_i64(ret, arg2); return; From 0a209d4bb119b92eb14b9afab55cef5bc0555554 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Sep 2012 17:18:16 -0700 Subject: [PATCH 0573/2270] tcg: Sanity check goto_tb input Checking that we don't try for idx != [01] is trivial. Checking that we don't issue more than one of any index requires a tad more data and some ifdefs protecting that new variable. Signed-off-by: Richard Henderson Cc: Max Filippov Signed-off-by: Aurelien Jarno --- tcg/tcg-op.h | 9 ++++++++- tcg/tcg.c | 4 ++++ tcg/tcg.h | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index ecb1ac3e2e..9bfed48830 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -2275,8 +2275,15 @@ static inline void tcg_gen_exit_tb(tcg_target_long val) tcg_gen_op1i(INDEX_op_exit_tb, val); } -static inline void tcg_gen_goto_tb(int idx) +static inline void tcg_gen_goto_tb(unsigned idx) { + /* We only support two chained exits. */ + tcg_debug_assert(idx <= 1); +#ifdef CONFIG_DEBUG_TCG + /* Verify that we havn't seen this numbered exit before. */ + tcg_debug_assert((tcg_ctx.goto_tb_issue_mask & (1 << idx)) == 0); + tcg_ctx.goto_tb_issue_mask |= 1 << idx; +#endif tcg_gen_op1i(INDEX_op_goto_tb, idx); } diff --git a/tcg/tcg.c b/tcg/tcg.c index b3c265013d..c069e44a0e 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -298,6 +298,10 @@ void tcg_func_start(TCGContext *s) s->nb_labels = 0; s->current_frame_offset = s->frame_start; +#ifdef CONFIG_DEBUG_TCG + s->goto_tb_issue_mask = 0; +#endif + gen_opc_ptr = gen_opc_buf; gen_opparam_ptr = gen_opparam_buf; } diff --git a/tcg/tcg.h b/tcg/tcg.h index 4501c1520f..af7464a650 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -390,6 +390,7 @@ struct TCGContext { #ifdef CONFIG_DEBUG_TCG int temps_in_use; + int goto_tb_issue_mask; #endif }; From a463133ee26b9172728476962eb9d411985b480f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 24 Sep 2012 13:44:59 -0700 Subject: [PATCH 0574/2270] tcg: Streamline movcond_i64 using 32-bit arithmetic Avoiding 64-bit arithmetic (outside of the compare) reduces the generated op count from 15 to 12, and the generated code size on i686 from 105 to 88 bytes. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg-op.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 9bfed48830..027270cd63 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -2212,6 +2212,25 @@ static inline void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1, TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2) { +#if TCG_TARGET_REG_BITS == 32 + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0, + TCGV_LOW(c1), TCGV_HIGH(c1), + TCGV_LOW(c2), TCGV_HIGH(c2), cond); + tcg_gen_neg_i32(t0, t0); + + tcg_gen_and_i32(t1, TCGV_LOW(v1), t0); + tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0); + tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1); + + tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0); + tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0); + tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1); + + tcg_temp_free_i32(t0); + tcg_temp_free_i32(t1); +#else if (TCG_TARGET_HAS_movcond_i64) { tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond); } else { @@ -2225,6 +2244,7 @@ static inline void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, tcg_temp_free_i64(t0); tcg_temp_free_i64(t1); } +#endif } /***************************************/ From a80a6b63e362cc8eda7aae5b4c3f9e4e49013d62 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 24 Sep 2012 13:45:00 -0700 Subject: [PATCH 0575/2270] tcg: Streamline movcond_i64 using movcond_i32 When movcond_i32 is available we can further reduce the generated op count from 12 to 6, and the generated code size on i686 from 88 to 74 bytes. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg-op.h | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 027270cd63..bd93fe4f03 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -2218,16 +2218,24 @@ static inline void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0, TCGV_LOW(c1), TCGV_HIGH(c1), TCGV_LOW(c2), TCGV_HIGH(c2), cond); - tcg_gen_neg_i32(t0, t0); - tcg_gen_and_i32(t1, TCGV_LOW(v1), t0); - tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0); - tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1); + if (TCG_TARGET_HAS_movcond_i32) { + tcg_gen_movi_i32(t1, 0); + tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1, + TCGV_LOW(v1), TCGV_LOW(v2)); + tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1, + TCGV_HIGH(v1), TCGV_HIGH(v2)); + } else { + tcg_gen_neg_i32(t0, t0); - tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0); - tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0); - tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1); + tcg_gen_and_i32(t1, TCGV_LOW(v1), t0); + tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0); + tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1); + tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0); + tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0); + tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1); + } tcg_temp_free_i32(t0); tcg_temp_free_i32(t1); #else From f813cb838f19ee8637d3c365659e6a6bb0c9c974 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Wed, 26 Sep 2012 00:30:12 +0200 Subject: [PATCH 0576/2270] tcg/i386: fix build with -march < i686 The movcond_i32 op has to be protected with TCG_TARGET_HAS_movcond_i32 to fix the build with -march < i686. Thanks to Richard Henderson for the hint. Reported-by: Alex Barcelo Signed-off-by: Aurelien Jarno --- tcg/i386/tcg-target.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 122d63630c..0e218c8614 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -1893,7 +1893,9 @@ static const TCGTargetOpDef x86_op_defs[] = { { INDEX_op_setcond_i32, { "q", "r", "ri" } }, { INDEX_op_deposit_i32, { "Q", "0", "Q" } }, +#if TCG_TARGET_HAS_movcond_i32 { INDEX_op_movcond_i32, { "r", "r", "ri", "r", "0" } }, +#endif #if TCG_TARGET_REG_BITS == 32 { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } }, From a9552c8edbd31bf75d42b561f0a592c00aff1038 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 5 Sep 2012 23:06:21 +0200 Subject: [PATCH 0577/2270] Introduce powerdown_notifiers Notifier will be used for signaling powerdown request to guest in a more general way and intended to replace very specific qemu_irq_rise(qemu_system_powerdown) and will allow to remove global variable qemu_system_powerdown. Signed-off-by: Igor Mammedov Signed-off-by: Anthony Liguori --- sysemu.h | 1 + vl.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/sysemu.h b/sysemu.h index 65552acee5..803c8588cf 100644 --- a/sysemu.h +++ b/sysemu.h @@ -52,6 +52,7 @@ void qemu_system_wakeup_enable(WakeupReason reason, bool enabled); void qemu_register_wakeup_notifier(Notifier *notifier); void qemu_system_shutdown_request(void); void qemu_system_powerdown_request(void); +void qemu_register_powerdown_notifier(Notifier *notifier); void qemu_system_debug_request(void); void qemu_system_vmstop_request(RunState reason); int qemu_shutdown_requested_get(void); diff --git a/vl.c b/vl.c index 48049ef0b6..a65759ad5a 100644 --- a/vl.c +++ b/vl.c @@ -1355,6 +1355,8 @@ static int powerdown_requested; static int debug_requested; static int suspend_requested; static int wakeup_requested; +static NotifierList powerdown_notifiers = + NOTIFIER_LIST_INITIALIZER(powerdown_notifiers); static NotifierList suspend_notifiers = NOTIFIER_LIST_INITIALIZER(suspend_notifiers); static NotifierList wakeup_notifiers = @@ -1569,6 +1571,11 @@ void qemu_system_powerdown_request(void) qemu_notify_event(); } +void qemu_register_powerdown_notifier(Notifier *notifier) +{ + notifier_list_add(&powerdown_notifiers, notifier); +} + void qemu_system_debug_request(void) { debug_requested = 1; @@ -1620,6 +1627,7 @@ static bool main_loop_should_exit(void) } if (qemu_powerdown_requested()) { monitor_protocol_event(QEVENT_POWERDOWN, NULL); + notifier_list_notify(&powerdown_notifiers, NULL); qemu_irq_raise(qemu_system_powerdown); } if (qemu_vmstop_requested(&r)) { From d010f91c3ab97862c1d0a6a6b6832ed388fb6cd7 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 5 Sep 2012 23:06:22 +0200 Subject: [PATCH 0578/2270] acpi: use notifier for signaling guest system_powerdown command In addition, there is no need to allocate an extra irq just for rising SCI in irq handler. Just rise SCI right from notifier handler instead. Signed-off-by: Igor Mammedov Signed-off-by: Anthony Liguori --- hw/acpi_piix4.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index c56220b368..15275cf3e5 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -67,6 +67,7 @@ typedef struct PIIX4PMState { qemu_irq smi_irq; int kvm_enabled; Notifier machine_ready; + Notifier powerdown_notifier; /* for pci hotplug */ struct pci_status pci0_status; @@ -362,9 +363,9 @@ static void piix4_reset(void *opaque) piix4_update_hotplug(s); } -static void piix4_powerdown(void *opaque, int irq, int power_failing) +static void piix4_pm_powerdown_req(Notifier *n, void *opaque) { - PIIX4PMState *s = opaque; + PIIX4PMState *s = container_of(n, PIIX4PMState, powerdown_notifier); assert(s != NULL); acpi_pm1_evt_power_down(&s->ar); @@ -416,7 +417,8 @@ static int piix4_pm_initfn(PCIDevice *dev) acpi_pm_tmr_init(&s->ar, pm_tmr_timer); acpi_gpe_init(&s->ar, GPE_LEN); - qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1); + s->powerdown_notifier.notify = piix4_pm_powerdown_req; + qemu_register_powerdown_notifier(&s->powerdown_notifier); pm_smbus_init(&s->dev.qdev, &s->smb); s->machine_ready.notify = piix4_pm_machine_ready; From c72ddb1e4734ce021c3101b6b4f8ed02439c9e21 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 5 Sep 2012 23:06:23 +0200 Subject: [PATCH 0579/2270] target-arm: use notifier for signaling guest system_powerdown command Acked-by: Peter Maydell Signed-off-by: Igor Mammedov Signed-off-by: Anthony Liguori --- hw/nseries.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/hw/nseries.c b/hw/nseries.c index 4df2670327..6df71ebb48 100644 --- a/hw/nseries.c +++ b/hw/nseries.c @@ -189,6 +189,17 @@ static void n8x0_nand_setup(struct n800_s *s) /* XXX: in theory should also update the OOB for both pages */ } +static qemu_irq n8x0_system_powerdown; + +static void n8x0_powerdown_req(Notifier *n, void *opaque) +{ + qemu_irq_raise(n8x0_system_powerdown); +} + +static Notifier n8x0_system_powerdown_notifier = { + .notify = n8x0_powerdown_req +}; + static void n8x0_i2c_setup(struct n800_s *s) { DeviceState *dev; @@ -201,7 +212,8 @@ static void n8x0_i2c_setup(struct n800_s *s) qdev_get_gpio_in(s->mpu->ih[0], OMAP_INT_24XX_SYS_NIRQ)); - qemu_system_powerdown = qdev_get_gpio_in(dev, 3); + n8x0_system_powerdown = qdev_get_gpio_in(dev, 3); + qemu_register_powerdown_notifier(&n8x0_system_powerdown_notifier); /* Attach a TMP105 PM chip (A0 wired to ground) */ dev = i2c_create_slave(i2c, "tmp105", N8X0_TMP105_ADDR); From bea42280dad1e016225654a062b98bafe99e51fe Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 5 Sep 2012 23:06:24 +0200 Subject: [PATCH 0580/2270] target-sparc: use notifier for signaling guest system_powerdown command Signed-off-by: Igor Mammedov Signed-off-by: Anthony Liguori --- hw/sun4m.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/hw/sun4m.c b/hw/sun4m.c index 0f909b5f86..c98cd5ec3f 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -472,6 +472,17 @@ static void slavio_timer_init_all(target_phys_addr_t addr, qemu_irq master_irq, } } +static qemu_irq slavio_system_powerdown; + +static void slavio_powerdown_req(Notifier *n, void *opaque) +{ + qemu_irq_raise(slavio_system_powerdown); +} + +static Notifier slavio_system_powerdown_notifier = { + .notify = slavio_powerdown_req +}; + #define MISC_LEDS 0x01600000 #define MISC_CFG 0x01800000 #define MISC_DIAG 0x01a00000 @@ -514,7 +525,8 @@ static void slavio_misc_init(target_phys_addr_t base, } sysbus_connect_irq(s, 0, irq); sysbus_connect_irq(s, 1, fdc_tc); - qemu_system_powerdown = qdev_get_gpio_in(dev, 0); + slavio_system_powerdown = qdev_get_gpio_in(dev, 0); + qemu_register_powerdown_notifier(&slavio_system_powerdown_notifier); } static void ecc_init(target_phys_addr_t base, qemu_irq irq, uint32_t version) From 013c2f150f617d0e19ab487539df2234b2d4209b Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 5 Sep 2012 23:06:25 +0200 Subject: [PATCH 0581/2270] Cleanup unused global var qemu_system_powerdown All deps that used global qemu_system_powerdown var are now converted to notifiers, so remove it. Signed-off-by: Igor Mammedov Signed-off-by: Anthony Liguori --- sysemu.h | 1 - vl.c | 12 +++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sysemu.h b/sysemu.h index 803c8588cf..109304672d 100644 --- a/sysemu.h +++ b/sysemu.h @@ -62,7 +62,6 @@ int qemu_reset_requested(void); int qemu_powerdown_requested(void); void qemu_system_killed(int signal, pid_t pid); void qemu_kill_report(void); -extern qemu_irq qemu_system_powerdown; void qemu_devices_reset(void); void qemu_system_reset(bool report); diff --git a/vl.c b/vl.c index a65759ad5a..599d17a752 100644 --- a/vl.c +++ b/vl.c @@ -1565,6 +1565,12 @@ void qemu_system_shutdown_request(void) qemu_notify_event(); } +static void qemu_system_powerdown(void) +{ + monitor_protocol_event(QEVENT_POWERDOWN, NULL); + notifier_list_notify(&powerdown_notifiers, NULL); +} + void qemu_system_powerdown_request(void) { powerdown_requested = 1; @@ -1588,8 +1594,6 @@ void qemu_system_vmstop_request(RunState state) qemu_notify_event(); } -qemu_irq qemu_system_powerdown; - static bool main_loop_should_exit(void) { RunState r; @@ -1626,9 +1630,7 @@ static bool main_loop_should_exit(void) monitor_protocol_event(QEVENT_WAKEUP, NULL); } if (qemu_powerdown_requested()) { - monitor_protocol_event(QEVENT_POWERDOWN, NULL); - notifier_list_notify(&powerdown_notifiers, NULL); - qemu_irq_raise(qemu_system_powerdown); + qemu_system_powerdown(); } if (qemu_vmstop_requested(&r)) { vm_stop(r); From f430694188293f99a316bfa375b7cc17d23a06ed Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 13 Sep 2012 11:08:00 +0200 Subject: [PATCH 0582/2270] add pc-1.3 machine type Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- hw/pc_piix.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 88ff0411ca..5a0796bed0 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -349,8 +349,8 @@ static void pc_xen_hvm_init(ram_addr_t ram_size, } #endif -static QEMUMachine pc_machine_v1_2 = { - .name = "pc-1.2", +static QEMUMachine pc_machine_v1_3 = { + .name = "pc-1.3", .alias = "pc", .desc = "Standard PC", .init = pc_init_pci, @@ -358,6 +358,13 @@ static QEMUMachine pc_machine_v1_2 = { .is_default = 1, }; +static QEMUMachine pc_machine_v1_2 = { + .name = "pc-1.2", + .desc = "Standard PC", + .init = pc_init_pci, + .max_cpus = 255, +}; + #define PC_COMPAT_1_1 \ {\ .driver = "virtio-scsi-pci",\ @@ -655,6 +662,7 @@ static QEMUMachine xenfv_machine = { static void pc_machine_init(void) { + qemu_register_machine(&pc_machine_v1_3); qemu_register_machine(&pc_machine_v1_2); qemu_register_machine(&pc_machine_v1_1); qemu_register_machine(&pc_machine_v1_0); From 183c5eaa41f7814ed4e83c16812c67a857eac6aa Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 13 Sep 2012 11:08:01 +0200 Subject: [PATCH 0583/2270] compat: turn off msi/msix on xhci for old machine types Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- hw/pc_piix.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 5a0796bed0..afd8361dfb 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -358,14 +358,30 @@ static QEMUMachine pc_machine_v1_3 = { .is_default = 1, }; +#define PC_COMPAT_1_2 \ + {\ + .driver = "nec-usb-xhci",\ + .property = "msi",\ + .value = "off",\ + },{\ + .driver = "nec-usb-xhci",\ + .property = "msix",\ + .value = "off",\ + } + static QEMUMachine pc_machine_v1_2 = { .name = "pc-1.2", .desc = "Standard PC", .init = pc_init_pci, .max_cpus = 255, + .compat_props = (GlobalProperty[]) { + PC_COMPAT_1_2, + { /* end of list */ } + }, }; #define PC_COMPAT_1_1 \ + PC_COMPAT_1_2,\ {\ .driver = "virtio-scsi-pci",\ .property = "hotplug",\ From c08ba66f13d3977402e0c9cd6ef35323ea11c0d6 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 13 Sep 2012 11:08:02 +0200 Subject: [PATCH 0584/2270] ivshmem: add 64bit option This patch adds a "use64" property which will make the ivshmem driver register a 64bit memory bar when set, so you have something to play with when testing 64bit pci bits. It also allows to have quite big shared memory regions, like this: [root@fedora ~]# lspci -vs1:1 01:01.0 RAM memory: Red Hat, Inc Device 1110 Subsystem: Red Hat, Inc Device 1100 Physical Slot: 1-1 Flags: fast devsel Memory at fd400000 (32-bit, non-prefetchable) [disabled] [size=256] Memory at 8040000000 (64-bit, prefetchable) [size=1G] [ v5: rebase, update compat property for post-1.2 merge ] [ v4: rebase & adapt to latest master again ] [ v3: rebase & adapt to latest master ] [ v2: default to on as suggested by avi, turn off for pc-$old using compat property ] Signed-off-by: Gerd Hoffmann Tested-by: Cam Macdonell Signed-off-by: Anthony Liguori --- hw/ivshmem.c | 13 ++++++++++--- hw/pc_piix.c | 4 ++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/hw/ivshmem.c b/hw/ivshmem.c index 62fe53ae2b..59f1aa4265 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -71,6 +71,8 @@ typedef struct IVShmemState { MemoryRegion bar; MemoryRegion ivshmem; uint64_t ivshmem_size; /* size of shared memory region */ + uint32_t ivshmem_attr; + uint32_t ivshmem_64bit; int shm_fd; /* shared memory file descriptor */ Peer *peers; @@ -339,7 +341,7 @@ static void create_shared_memory_BAR(IVShmemState *s, int fd) { memory_region_add_subregion(&s->bar, 0, &s->ivshmem); /* region for shared memory */ - pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar); + pci_register_bar(&s->dev, 2, s->ivshmem_attr, &s->bar); } static void ivshmem_add_eventfd(IVShmemState *s, int posn, int i) @@ -690,6 +692,11 @@ static int pci_ivshmem_init(PCIDevice *dev) &s->ivshmem_mmio); memory_region_init(&s->bar, "ivshmem-bar2-container", s->ivshmem_size); + s->ivshmem_attr = PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_PREFETCH; + if (s->ivshmem_64bit) { + s->ivshmem_attr |= PCI_BASE_ADDRESS_MEM_TYPE_64; + } if ((s->server_chr != NULL) && (strncmp(s->server_chr->filename, "unix:", 5) == 0)) { @@ -715,8 +722,7 @@ static int pci_ivshmem_init(PCIDevice *dev) /* allocate/initialize space for interrupt handling */ s->peers = g_malloc0(s->nb_peers * sizeof(Peer)); - pci_register_bar(&s->dev, 2, - PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar); + pci_register_bar(&s->dev, 2, s->ivshmem_attr, &s->bar); s->eventfd_chr = g_malloc0(s->vectors * sizeof(CharDriverState *)); @@ -786,6 +792,7 @@ static Property ivshmem_properties[] = { DEFINE_PROP_BIT("msi", IVShmemState, features, IVSHMEM_MSI, true), DEFINE_PROP_STRING("shm", IVShmemState, shmobj), DEFINE_PROP_STRING("role", IVShmemState, role), + DEFINE_PROP_UINT32("use64", IVShmemState, ivshmem_64bit, 1), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/pc_piix.c b/hw/pc_piix.c index afd8361dfb..fd5898fba6 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -367,6 +367,10 @@ static QEMUMachine pc_machine_v1_3 = { .driver = "nec-usb-xhci",\ .property = "msix",\ .value = "off",\ + },{\ + .driver = "ivshmem",\ + .property = "use64",\ + .value = "0",\ } static QEMUMachine pc_machine_v1_2 = { From 8bdd3d499fe0ddffa9901c56ab3bc8911d5b8be0 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 14 Sep 2012 19:02:30 +0200 Subject: [PATCH 0585/2270] configure: Allow builds without any system or user emulation The old code aborted configure when no emulation target was selected. Even after removing the 'exit 1', it tried to read from STDIN when QEMU was configured with configure' '--disable-user' '--disable-system' This is fixed here. Signed-off-by: Stefan Weil Signed-off-by: Anthony Liguori --- Makefile | 5 +++++ configure | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index def2ae23cd..04642975af 100644 --- a/Makefile +++ b/Makefile @@ -52,8 +52,13 @@ SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory) BUILD_DIR=$(BUILD_DIR) SUBDIR_DEVICES_MAK=$(patsubst %, %/config-devices.mak, $(TARGET_DIRS)) SUBDIR_DEVICES_MAK_DEP=$(patsubst %, %/config-devices.mak.d, $(TARGET_DIRS)) +ifeq ($(SUBDIR_DEVICES_MAK),) +config-all-devices.mak: + $(call quiet-command,echo '# no devices' > $@," GEN $@") +else config-all-devices.mak: $(SUBDIR_DEVICES_MAK) $(call quiet-command,cat $(SUBDIR_DEVICES_MAK) | grep =y | sort -u > $@," GEN $@") +endif -include $(SUBDIR_DEVICES_MAK_DEP) diff --git a/configure b/configure index 1b865174e1..8f99b7b941 100755 --- a/configure +++ b/configure @@ -1286,10 +1286,6 @@ if test -z "$target_list" ; then else target_list=`echo "$target_list" | sed -e 's/,/ /g'` fi -if test -z "$target_list" ; then - echo "No targets enabled" - exit 1 -fi # see if system emulation was really requested case " $target_list " in *"-softmmu "*) softmmu=yes From 05bc1d8a4b2f77df8cc9880a552047e30c16f1f8 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 24 Sep 2012 13:11:07 +0200 Subject: [PATCH 0586/2270] Refactor inet_connect_opts function refactor address resolution code to fix nonblocking connect remove getnameinfo call Signed-off-by: Michael S. Tsirkin Signed-off-by: Amos Kong Signed-off-by: Orit Wasserman Signed-off-by: Anthony Liguori --- qemu-sockets.c | 162 ++++++++++++++++++++++++++++--------------------- 1 file changed, 92 insertions(+), 70 deletions(-) diff --git a/qemu-sockets.c b/qemu-sockets.c index 037775b86b..22797bf2eb 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -209,95 +209,117 @@ listen: return slisten; } -int inet_connect_opts(QemuOpts *opts, bool *in_progress, Error **errp) -{ - struct addrinfo ai,*res,*e; - const char *addr; - const char *port; - char uaddr[INET6_ADDRSTRLEN+1]; - char uport[33]; - int sock,rc; - bool block; +#ifdef _WIN32 +#define QEMU_SOCKET_RC_INPROGRESS(rc) \ + ((rc) == -EINPROGRESS || (rc) == -EWOULDBLOCK || (rc) == -WSAEALREADY) +#else +#define QEMU_SOCKET_RC_INPROGRESS(rc) \ + ((rc) == -EINPROGRESS) +#endif - memset(&ai,0, sizeof(ai)); - ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; - ai.ai_family = PF_UNSPEC; - ai.ai_socktype = SOCK_STREAM; +static int inet_connect_addr(struct addrinfo *addr, bool block, + bool *in_progress) +{ + int sock, rc; if (in_progress) { *in_progress = false; } + sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + if (sock < 0) { + fprintf(stderr, "%s: socket(%s): %s\n", __func__, + inet_strfamily(addr->ai_family), strerror(errno)); + return -1; + } + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + if (!block) { + socket_set_nonblock(sock); + } + /* connect to peer */ + do { + rc = 0; + if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) { + rc = -socket_error(); + } + } while (rc == -EINTR); + + if (!block && QEMU_SOCKET_RC_INPROGRESS(rc)) { + if (in_progress) { + *in_progress = true; + } + } else if (rc < 0) { + closesocket(sock); + return -1; + } + return sock; +} + +static struct addrinfo *inet_parse_connect_opts(QemuOpts *opts, Error **errp) +{ + struct addrinfo ai, *res; + int rc; + const char *addr; + const char *port; + + memset(&ai, 0, sizeof(ai)); + ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; + ai.ai_family = PF_UNSPEC; + ai.ai_socktype = SOCK_STREAM; + addr = qemu_opt_get(opts, "host"); port = qemu_opt_get(opts, "port"); - block = qemu_opt_get_bool(opts, "block", 0); if (addr == NULL || port == NULL) { - fprintf(stderr, "inet_connect: host and/or port not specified\n"); + fprintf(stderr, + "inet_parse_connect_opts: host and/or port not specified\n"); error_set(errp, QERR_SOCKET_CREATE_FAILED); + return NULL; + } + + if (qemu_opt_get_bool(opts, "ipv4", 0)) { + ai.ai_family = PF_INET; + } + if (qemu_opt_get_bool(opts, "ipv6", 0)) { + ai.ai_family = PF_INET6; + } + + /* lookup */ + rc = getaddrinfo(addr, port, &ai, &res); + if (rc != 0) { + fprintf(stderr, "getaddrinfo(%s,%s): %s\n", addr, port, + gai_strerror(rc)); + error_set(errp, QERR_SOCKET_CREATE_FAILED); + return NULL; + } + return res; +} + +int inet_connect_opts(QemuOpts *opts, bool *in_progress, Error **errp) +{ + struct addrinfo *res, *e; + int sock = -1; + bool block = qemu_opt_get_bool(opts, "block", 0); + + res = inet_parse_connect_opts(opts, errp); + if (!res) { return -1; } - if (qemu_opt_get_bool(opts, "ipv4", 0)) - ai.ai_family = PF_INET; - if (qemu_opt_get_bool(opts, "ipv6", 0)) - ai.ai_family = PF_INET6; - - /* lookup */ - if (0 != (rc = getaddrinfo(addr, port, &ai, &res))) { - fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port, - gai_strerror(rc)); - error_set(errp, QERR_SOCKET_CREATE_FAILED); - return -1; + if (in_progress) { + *in_progress = false; } for (e = res; e != NULL; e = e->ai_next) { - if (getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, - uaddr,INET6_ADDRSTRLEN,uport,32, - NI_NUMERICHOST | NI_NUMERICSERV) != 0) { - fprintf(stderr,"%s: getnameinfo: oops\n", __FUNCTION__); - continue; + sock = inet_connect_addr(e, block, in_progress); + if (sock >= 0) { + break; } - sock = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); - if (sock < 0) { - fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, - inet_strfamily(e->ai_family), strerror(errno)); - continue; - } - setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on)); - if (!block) { - socket_set_nonblock(sock); - } - /* connect to peer */ - do { - rc = 0; - if (connect(sock, e->ai_addr, e->ai_addrlen) < 0) { - rc = -socket_error(); - } - } while (rc == -EINTR); - - #ifdef _WIN32 - if (!block && (rc == -EINPROGRESS || rc == -EWOULDBLOCK - || rc == -WSAEALREADY)) { - #else - if (!block && (rc == -EINPROGRESS)) { - #endif - if (in_progress) { - *in_progress = true; - } - } else if (rc < 0) { - if (NULL == e->ai_next) - fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__, - inet_strfamily(e->ai_family), - e->ai_canonname, uaddr, uport, strerror(errno)); - closesocket(sock); - continue; - } - freeaddrinfo(res); - return sock; } - error_set(errp, QERR_SOCKET_CONNECT_FAILED); + if (sock < 0) { + error_set(errp, QERR_SOCKET_CONNECT_FAILED); + } freeaddrinfo(res); - return -1; + return sock; } int inet_dgram_opts(QemuOpts *opts) From 5db5f44cb4b7f24b9e0efdefc9015e36b7c34881 Mon Sep 17 00:00:00 2001 From: Orit Wasserman Date: Mon, 24 Sep 2012 13:11:08 +0200 Subject: [PATCH 0587/2270] Separate inet_connect into inet_connect (blocking) and inet_nonblocking_connect No need to add non blocking parameters to the blocking inet_connect add block parameter for inet_connect_opts instead of using QemuOpt "block". Signed-off-by: Orit Wasserman Signed-off-by: Anthony Liguori --- migration-tcp.c | 2 +- nbd.c | 2 +- qemu-char.c | 2 +- qemu-sockets.c | 58 ++++++++++++++++++++++++++++++++++++++++--------- qemu_socket.h | 7 ++++-- ui/vnc.c | 2 +- 6 files changed, 57 insertions(+), 16 deletions(-) diff --git a/migration-tcp.c b/migration-tcp.c index ac891c38a3..7f6ad98727 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -88,7 +88,7 @@ int tcp_start_outgoing_migration(MigrationState *s, const char *host_port, s->write = socket_write; s->close = tcp_close; - s->fd = inet_connect(host_port, false, &in_progress, errp); + s->fd = inet_nonblocking_connect(host_port, &in_progress, errp); if (error_is_set(errp)) { migrate_fd_error(s); return -1; diff --git a/nbd.c b/nbd.c index 57edfde0c9..6f0db62deb 100644 --- a/nbd.c +++ b/nbd.c @@ -208,7 +208,7 @@ int tcp_socket_outgoing(const char *address, uint16_t port) int tcp_socket_outgoing_spec(const char *address_and_port) { - return inet_connect(address_and_port, true, NULL, NULL); + return inet_connect(address_and_port, NULL); } int tcp_socket_incoming(const char *address, uint16_t port) diff --git a/qemu-char.c b/qemu-char.c index 7f0f895157..13b87b53c1 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2456,7 +2456,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) if (is_listen) { fd = inet_listen_opts(opts, 0, NULL); } else { - fd = inet_connect_opts(opts, NULL, NULL); + fd = inet_connect_opts(opts, true, NULL, NULL); } } if (fd < 0) { diff --git a/qemu-sockets.c b/qemu-sockets.c index 22797bf2eb..0883a66eb2 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -54,9 +54,6 @@ static QemuOptsList dummy_opts = { },{ .name = "ipv6", .type = QEMU_OPT_BOOL, - },{ - .name = "block", - .type = QEMU_OPT_BOOL, }, { /* end if list */ } }, @@ -294,11 +291,22 @@ static struct addrinfo *inet_parse_connect_opts(QemuOpts *opts, Error **errp) return res; } -int inet_connect_opts(QemuOpts *opts, bool *in_progress, Error **errp) +/** + * Create a socket and connect it to an address. + * + * @opts: QEMU options, recognized parameters strings "host" and "port", + * bools "ipv4" and "ipv6". + * @block: set true for blocking socket + * @in_progress: set to true in case of ongoing connect + * @errp: set on error + * + * Returns: -1 on error, file descriptor on success. + */ +int inet_connect_opts(QemuOpts *opts, bool block, bool *in_progress, + Error **errp) { struct addrinfo *res, *e; int sock = -1; - bool block = qemu_opt_get_bool(opts, "block", 0); res = inet_parse_connect_opts(opts, errp); if (!res) { @@ -515,17 +523,47 @@ int inet_listen(const char *str, char *ostr, int olen, return sock; } -int inet_connect(const char *str, bool block, bool *in_progress, Error **errp) +/** + * Create a blocking socket and connect it to an address. + * + * @str: address string + * @errp: set in case of an error + * + * Returns -1 in case of error, file descriptor on success + **/ +int inet_connect(const char *str, Error **errp) { QemuOpts *opts; int sock = -1; opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); if (inet_parse(opts, str) == 0) { - if (block) { - qemu_opt_set(opts, "block", "on"); - } - sock = inet_connect_opts(opts, in_progress, errp); + sock = inet_connect_opts(opts, true, NULL, errp); + } else { + error_set(errp, QERR_SOCKET_CREATE_FAILED); + } + qemu_opts_del(opts); + return sock; +} + +/** + * Create a non-blocking socket and connect it to an address. + * + * @str: address string + * @in_progress: set to true in case of ongoing connect + * @errp: set in case of an error + * + * Returns: -1 on error, file descriptor on success. + **/ +int inet_nonblocking_connect(const char *str, bool *in_progress, + Error **errp) +{ + QemuOpts *opts; + int sock = -1; + + opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); + if (inet_parse(opts, str) == 0) { + sock = inet_connect_opts(opts, false, in_progress, errp); } else { error_set(errp, QERR_SOCKET_CREATE_FAILED); } diff --git a/qemu_socket.h b/qemu_socket.h index 30ae6af8b8..80696aa6d8 100644 --- a/qemu_socket.h +++ b/qemu_socket.h @@ -42,8 +42,11 @@ int send_all(int fd, const void *buf, int len1); int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp); int inet_listen(const char *str, char *ostr, int olen, int socktype, int port_offset, Error **errp); -int inet_connect_opts(QemuOpts *opts, bool *in_progress, Error **errp); -int inet_connect(const char *str, bool block, bool *in_progress, Error **errp); +int inet_connect_opts(QemuOpts *opts, bool block, bool *in_progress, + Error **errp); +int inet_connect(const char *str, Error **errp); +int inet_nonblocking_connect(const char *str, bool *in_progress, + Error **errp); int inet_dgram_opts(QemuOpts *opts); const char *inet_strfamily(int family); diff --git a/ui/vnc.c b/ui/vnc.c index 385e345c31..01b2dafea2 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -3061,7 +3061,7 @@ int vnc_display_open(DisplayState *ds, const char *display) if (strncmp(display, "unix:", 5) == 0) vs->lsock = unix_connect(display+5); else - vs->lsock = inet_connect(display, true, NULL, NULL); + vs->lsock = inet_connect(display, NULL); if (-1 == vs->lsock) { g_free(vs->display); vs->display = NULL; From 233aa5c2d1cf4655ffe335025a68cf5454f87dad Mon Sep 17 00:00:00 2001 From: Orit Wasserman Date: Mon, 24 Sep 2012 13:11:09 +0200 Subject: [PATCH 0588/2270] Fix address handling in inet_nonblocking_connect getaddrinfo can give us a list of addresses, but we only try to connect to the first one. If that fails we never proceed to the next one. This is common on desktop setups that often have ipv6 configured but not actually working. To fix this make inet_connect_nonblocking retry connection with a different address. callers on inet_nonblocking_connect register a callback function that will be called when connect opertion completes, in case of failure the fd will have a negative value Signed-off-by: Orit Wasserman Signed-off-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- migration-tcp.c | 37 ++++---------- qemu-char.c | 2 +- qemu-sockets.c | 129 +++++++++++++++++++++++++++++++++++++++--------- qemu_socket.h | 16 ++++-- 4 files changed, 126 insertions(+), 58 deletions(-) diff --git a/migration-tcp.c b/migration-tcp.c index 7f6ad98727..a15c2b87a1 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -53,54 +53,35 @@ static int tcp_close(MigrationState *s) return r; } -static void tcp_wait_for_connect(void *opaque) +static void tcp_wait_for_connect(int fd, void *opaque) { MigrationState *s = opaque; - int val, ret; - socklen_t valsize = sizeof(val); - DPRINTF("connect completed\n"); - do { - ret = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (void *) &val, &valsize); - } while (ret == -1 && (socket_error()) == EINTR); - - if (ret < 0) { + if (fd < 0) { + DPRINTF("migrate connect error\n"); + s->fd = -1; migrate_fd_error(s); - return; - } - - qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); - - if (val == 0) + } else { + DPRINTF("migrate connect success\n"); + s->fd = fd; migrate_fd_connect(s); - else { - DPRINTF("error connecting %d\n", val); - migrate_fd_error(s); } } int tcp_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp) { - bool in_progress; - s->get_error = socket_errno; s->write = socket_write; s->close = tcp_close; - s->fd = inet_nonblocking_connect(host_port, &in_progress, errp); + s->fd = inet_nonblocking_connect(host_port, tcp_wait_for_connect, s, + errp); if (error_is_set(errp)) { migrate_fd_error(s); return -1; } - if (in_progress) { - DPRINTF("connect in progress\n"); - qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s); - } else { - migrate_fd_connect(s); - } - return 0; } diff --git a/qemu-char.c b/qemu-char.c index 13b87b53c1..b082bae11b 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2456,7 +2456,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) if (is_listen) { fd = inet_listen_opts(opts, 0, NULL); } else { - fd = inet_connect_opts(opts, true, NULL, NULL); + fd = inet_connect_opts(opts, NULL, NULL, NULL); } } if (fd < 0) { diff --git a/qemu-sockets.c b/qemu-sockets.c index 0883a66eb2..1f14e8bc63 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -24,6 +24,7 @@ #include "qemu_socket.h" #include "qemu-common.h" /* for qemu_isdigit */ +#include "main-loop.h" #ifndef AI_ADDRCONFIG # define AI_ADDRCONFIG 0 @@ -214,14 +215,66 @@ listen: ((rc) == -EINPROGRESS) #endif -static int inet_connect_addr(struct addrinfo *addr, bool block, - bool *in_progress) +/* Struct to store connect state for non blocking connect */ +typedef struct ConnectState { + int fd; + struct addrinfo *addr_list; + struct addrinfo *current_addr; + NonBlockingConnectHandler *callback; + void *opaque; +} ConnectState; + +static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, + ConnectState *connect_state); + +static void wait_for_connect(void *opaque) +{ + ConnectState *s = opaque; + int val = 0, rc = 0; + socklen_t valsize = sizeof(val); + bool in_progress; + + qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); + + do { + rc = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (void *) &val, &valsize); + } while (rc == -1 && socket_error() == EINTR); + + /* update rc to contain error */ + if (!rc && val) { + rc = -1; + } + + /* connect error */ + if (rc < 0) { + closesocket(s->fd); + s->fd = rc; + } + + /* try to connect to the next address on the list */ + while (s->current_addr->ai_next != NULL && s->fd < 0) { + s->current_addr = s->current_addr->ai_next; + s->fd = inet_connect_addr(s->current_addr, &in_progress, s); + /* connect in progress */ + if (in_progress) { + return; + } + } + + freeaddrinfo(s->addr_list); + if (s->callback) { + s->callback(s->fd, s->opaque); + } + g_free(s); + return; +} + +static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, + ConnectState *connect_state) { int sock, rc; - if (in_progress) { - *in_progress = false; - } + *in_progress = false; sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if (sock < 0) { @@ -230,7 +283,7 @@ static int inet_connect_addr(struct addrinfo *addr, bool block, return -1; } setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); - if (!block) { + if (connect_state != NULL) { socket_set_nonblock(sock); } /* connect to peer */ @@ -241,10 +294,11 @@ static int inet_connect_addr(struct addrinfo *addr, bool block, } } while (rc == -EINTR); - if (!block && QEMU_SOCKET_RC_INPROGRESS(rc)) { - if (in_progress) { - *in_progress = true; - } + if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { + connect_state->fd = sock; + qemu_set_fd_handler2(sock, NULL, NULL, wait_for_connect, + connect_state); + *in_progress = true; } else if (rc < 0) { closesocket(sock); return -1; @@ -260,6 +314,7 @@ static struct addrinfo *inet_parse_connect_opts(QemuOpts *opts, Error **errp) const char *port; memset(&ai, 0, sizeof(ai)); + ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; ai.ai_family = PF_UNSPEC; ai.ai_socktype = SOCK_STREAM; @@ -296,36 +351,55 @@ static struct addrinfo *inet_parse_connect_opts(QemuOpts *opts, Error **errp) * * @opts: QEMU options, recognized parameters strings "host" and "port", * bools "ipv4" and "ipv6". - * @block: set true for blocking socket - * @in_progress: set to true in case of ongoing connect * @errp: set on error + * @callback: callback function for non-blocking connect + * @opaque: opaque for callback function * * Returns: -1 on error, file descriptor on success. + * + * If @callback is non-null, the connect is non-blocking. If this + * function succeeds, callback will be called when the connection + * completes, with the file descriptor on success, or -1 on error. */ -int inet_connect_opts(QemuOpts *opts, bool block, bool *in_progress, - Error **errp) +int inet_connect_opts(QemuOpts *opts, Error **errp, + NonBlockingConnectHandler *callback, void *opaque) { struct addrinfo *res, *e; int sock = -1; + bool in_progress; + ConnectState *connect_state = NULL; res = inet_parse_connect_opts(opts, errp); if (!res) { return -1; } - if (in_progress) { - *in_progress = false; + if (callback != NULL) { + connect_state = g_malloc0(sizeof(*connect_state)); + connect_state->addr_list = res; + connect_state->callback = callback; + connect_state->opaque = opaque; } for (e = res; e != NULL; e = e->ai_next) { - sock = inet_connect_addr(e, block, in_progress); - if (sock >= 0) { + if (connect_state != NULL) { + connect_state->current_addr = e; + } + sock = inet_connect_addr(e, &in_progress, connect_state); + if (in_progress) { + return sock; + } else if (sock >= 0) { + /* non blocking socket immediate success, call callback */ + if (callback != NULL) { + callback(sock, opaque); + } break; } } if (sock < 0) { error_set(errp, QERR_SOCKET_CONNECT_FAILED); } + g_free(connect_state); freeaddrinfo(res); return sock; } @@ -538,7 +612,7 @@ int inet_connect(const char *str, Error **errp) opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); if (inet_parse(opts, str) == 0) { - sock = inet_connect_opts(opts, true, NULL, errp); + sock = inet_connect_opts(opts, errp, NULL, NULL); } else { error_set(errp, QERR_SOCKET_CREATE_FAILED); } @@ -548,22 +622,29 @@ int inet_connect(const char *str, Error **errp) /** * Create a non-blocking socket and connect it to an address. + * Calls the callback function with fd in case of success or -1 in case of + * error. * * @str: address string - * @in_progress: set to true in case of ongoing connect + * @callback: callback function that is called when connect completes, + * cannot be NULL. + * @opaque: opaque for callback function * @errp: set in case of an error * - * Returns: -1 on error, file descriptor on success. + * Returns: -1 on immediate error, file descriptor on success. **/ -int inet_nonblocking_connect(const char *str, bool *in_progress, - Error **errp) +int inet_nonblocking_connect(const char *str, + NonBlockingConnectHandler *callback, + void *opaque, Error **errp) { QemuOpts *opts; int sock = -1; + g_assert(callback != NULL); + opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); if (inet_parse(opts, str) == 0) { - sock = inet_connect_opts(opts, false, in_progress, errp); + sock = inet_connect_opts(opts, errp, callback, opaque); } else { error_set(errp, QERR_SOCKET_CREATE_FAILED); } diff --git a/qemu_socket.h b/qemu_socket.h index 80696aa6d8..3e8aee9cad 100644 --- a/qemu_socket.h +++ b/qemu_socket.h @@ -38,15 +38,21 @@ void socket_set_block(int fd); void socket_set_nonblock(int fd); int send_all(int fd, const void *buf, int len1); -/* New, ipv6-ready socket helper functions, see qemu-sockets.c */ +/* callback function for nonblocking connect + * valid fd on success, negative error code on failure + */ +typedef void NonBlockingConnectHandler(int fd, void *opaque); + int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp); int inet_listen(const char *str, char *ostr, int olen, int socktype, int port_offset, Error **errp); -int inet_connect_opts(QemuOpts *opts, bool block, bool *in_progress, - Error **errp); +int inet_connect_opts(QemuOpts *opts, Error **errp, + NonBlockingConnectHandler *callback, void *opaque); int inet_connect(const char *str, Error **errp); -int inet_nonblocking_connect(const char *str, bool *in_progress, - Error **errp); +int inet_nonblocking_connect(const char *str, + NonBlockingConnectHandler *callback, + void *opaque, Error **errp); + int inet_dgram_opts(QemuOpts *opts); const char *inet_strfamily(int family); From 3202becaa2b805497ce9e6faa6edfb83665f91b1 Mon Sep 17 00:00:00 2001 From: Orit Wasserman Date: Mon, 24 Sep 2012 13:11:10 +0200 Subject: [PATCH 0589/2270] Clear handler only for valid fd Signed-off-by: Orit Wasserman Signed-off-by: Anthony Liguori --- migration.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/migration.c b/migration.c index 1edeec5ddd..22a05c437d 100644 --- a/migration.c +++ b/migration.c @@ -240,7 +240,9 @@ static int migrate_fd_cleanup(MigrationState *s) { int ret = 0; - qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); + if (s->fd != -1) { + qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); + } if (s->file) { DPRINTF("closing file\n"); From ac05f3492421caeb05809ffa02c6198ede179e43 Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Fri, 7 Sep 2012 11:11:03 +0800 Subject: [PATCH 0590/2270] add a boot parameter to set reboot timeout Added an option to let qemu transfer a configuration file to bios, "etc/boot-fail-wait", which could be specified by command -boot reboot-timeout=T T have a max value of 0xffff, unit is ms. With this option, guest will wait for a given time if not find bootabled device, then reboot. If reboot-timeout is '-1', guest will not reboot, qemu passes '-1' to bios by default. This feature need the new seabios's support. Seabios pulls the value from the fwcfg "file" interface, this interface is used because SeaBIOS needs a reliable way of obtaining a name, value size, and value. It in no way requires that there be a real file on the user's host machine. Signed-off-by: Amos Kong Signed-off-by: Anthony Liguori --- hw/fw_cfg.c | 25 +++++++++++++++++++++++++ qemu-config.c | 3 +++ qemu-options.hx | 12 +++++++++--- vl.c | 3 ++- 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c index 7b3b5769a2..dcde1a943c 100644 --- a/hw/fw_cfg.c +++ b/hw/fw_cfg.c @@ -183,6 +183,30 @@ static void fw_cfg_bootsplash(FWCfgState *s) } } +static void fw_cfg_reboot(FWCfgState *s) +{ + int reboot_timeout = -1; + char *p; + const char *temp; + + /* get user configuration */ + QemuOptsList *plist = qemu_find_opts("boot-opts"); + QemuOpts *opts = QTAILQ_FIRST(&plist->head); + if (opts != NULL) { + temp = qemu_opt_get(opts, "reboot-timeout"); + if (temp != NULL) { + p = (char *)temp; + reboot_timeout = strtol(p, (char **)&p, 10); + } + } + /* validate the input */ + if (reboot_timeout > 0xffff) { + error_report("reboot timeout is larger than 65535, force it to 65535."); + reboot_timeout = 0xffff; + } + fw_cfg_add_file(s, "etc/boot-fail-wait", g_memdup(&reboot_timeout, 4), 4); +} + static void fw_cfg_write(FWCfgState *s, uint8_t value) { int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL); @@ -497,6 +521,7 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port, fw_cfg_add_i16(s, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu); fw_cfg_bootsplash(s); + fw_cfg_reboot(s); s->machine_ready.notify = fw_cfg_machine_ready; qemu_add_machine_init_done_notifier(&s->machine_ready); diff --git a/qemu-config.c b/qemu-config.c index 12eafbb4f5..cd1ec2165a 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -645,6 +645,9 @@ QemuOptsList qemu_boot_opts = { }, { .name = "splash-time", .type = QEMU_OPT_STRING, + }, { + .name = "reboot-timeout", + .type = QEMU_OPT_STRING, }, { /*End of list */ } }, diff --git a/qemu-options.hx b/qemu-options.hx index 09c86c4cb0..7d97f96928 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -344,13 +344,14 @@ ETEXI DEF("boot", HAS_ARG, QEMU_OPTION_boot, "-boot [order=drives][,once=drives][,menu=on|off]\n" - " [,splash=sp_name][,splash-time=sp_time]\n" + " [,splash=sp_name][,splash-time=sp_time][,reboot-timeout=rb_time]\n" " 'drives': floppy (a), hard disk (c), CD-ROM (d), network (n)\n" " 'sp_name': the file's name that would be passed to bios as logo picture, if menu=on\n" - " 'sp_time': the period that splash picture last if menu=on, unit is ms\n", + " 'sp_time': the period that splash picture last if menu=on, unit is ms\n" + " 'rb_timeout': the timeout before guest reboot when boot failed, unit is ms\n", QEMU_ARCH_ALL) STEXI -@item -boot [order=@var{drives}][,once=@var{drives}][,menu=on|off][,splash=@var{sp_name}][,splash-time=@var{sp_time}] +@item -boot [order=@var{drives}][,once=@var{drives}][,menu=on|off][,splash=@var{sp_name}][,splash-time=@var{sp_time}][,reboot-timeout=@var{rb_timeout}] @findex -boot Specify boot order @var{drives} as a string of drive letters. Valid drive letters depend on the target achitecture. The x86 PC uses: a, b @@ -369,6 +370,11 @@ limitation: The splash file could be a jpeg file or a BMP file in 24 BPP format(true color). The resolution should be supported by the SVGA mode, so the recommended is 320x240, 640x480, 800x640. +A timeout could be passed to bios, guest will pause for @var{rb_timeout} ms +when boot failed, then reboot. If @var{rb_timeout} is '-1', guest will not +reboot, qemu passes '-1' to bios by default. Currently Seabios for X86 +system support it. + @example # try to boot from network first, then from hard disk qemu-system-i386 -boot order=nc diff --git a/vl.c b/vl.c index 599d17a752..8d305ca59b 100644 --- a/vl.c +++ b/vl.c @@ -2632,7 +2632,8 @@ int main(int argc, char **argv, char **envp) { static const char * const params[] = { "order", "once", "menu", - "splash", "splash-time", NULL + "splash", "splash-time", + "reboot-timeout", NULL }; char buf[sizeof(boot_devices)]; char *standard_boot_devices; From 356d83725675c0140db27b24afed3a2c0c7d9702 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 13 Sep 2012 10:50:31 +0200 Subject: [PATCH 0591/2270] add pc-1.3 machine type Signed-off-by: Gerd Hoffmann --- hw/pc_piix.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 88ff0411ca..5a0796bed0 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -349,8 +349,8 @@ static void pc_xen_hvm_init(ram_addr_t ram_size, } #endif -static QEMUMachine pc_machine_v1_2 = { - .name = "pc-1.2", +static QEMUMachine pc_machine_v1_3 = { + .name = "pc-1.3", .alias = "pc", .desc = "Standard PC", .init = pc_init_pci, @@ -358,6 +358,13 @@ static QEMUMachine pc_machine_v1_2 = { .is_default = 1, }; +static QEMUMachine pc_machine_v1_2 = { + .name = "pc-1.2", + .desc = "Standard PC", + .init = pc_init_pci, + .max_cpus = 255, +}; + #define PC_COMPAT_1_1 \ {\ .driver = "virtio-scsi-pci",\ @@ -655,6 +662,7 @@ static QEMUMachine xenfv_machine = { static void pc_machine_init(void) { + qemu_register_machine(&pc_machine_v1_3); qemu_register_machine(&pc_machine_v1_2); qemu_register_machine(&pc_machine_v1_1); qemu_register_machine(&pc_machine_v1_0); From a2879190ab08b2b75d65b576fad7ff95d7d7d641 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 13 Sep 2012 10:53:23 +0200 Subject: [PATCH 0592/2270] compat: turn off msi/msix on xhci for old machine types Signed-off-by: Gerd Hoffmann --- hw/pc_piix.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 5a0796bed0..afd8361dfb 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -358,14 +358,30 @@ static QEMUMachine pc_machine_v1_3 = { .is_default = 1, }; +#define PC_COMPAT_1_2 \ + {\ + .driver = "nec-usb-xhci",\ + .property = "msi",\ + .value = "off",\ + },{\ + .driver = "nec-usb-xhci",\ + .property = "msix",\ + .value = "off",\ + } + static QEMUMachine pc_machine_v1_2 = { .name = "pc-1.2", .desc = "Standard PC", .init = pc_init_pci, .max_cpus = 255, + .compat_props = (GlobalProperty[]) { + PC_COMPAT_1_2, + { /* end of list */ } + }, }; #define PC_COMPAT_1_1 \ + PC_COMPAT_1_2,\ {\ .driver = "virtio-scsi-pci",\ .property = "hotplug",\ From d95e74eaed8b74b0c75ab343e9cb826b1f5c9007 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 20 Sep 2012 09:55:49 +0200 Subject: [PATCH 0593/2270] xhci: tweak limits Set maxports to 15. This is what the usb3 route string can handle. Set maxslots to 64. This is more than the number of root ports we can have, but with additional hubs you can end up with more devices. Set maxintrs (aka msi vectors) to 16. Should be enougth, especially considering that vectors are a limited ressource. Linux guests use only three at the moment. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index e0ca69044a..14148262af 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -37,12 +37,12 @@ #define FIXME() do { fprintf(stderr, "FIXME %s:%d\n", \ __func__, __LINE__); abort(); } while (0) -#define MAXPORTS_2 8 -#define MAXPORTS_3 8 +#define MAXPORTS_2 15 +#define MAXPORTS_3 15 #define MAXPORTS (MAXPORTS_2+MAXPORTS_3) -#define MAXSLOTS MAXPORTS -#define MAXINTRS MAXPORTS +#define MAXSLOTS 64 +#define MAXINTRS 16 #define TD_QUEUE 24 From ccaf87a085c748910efddbcfb5077f6a67cc354a Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 18 Sep 2012 17:30:52 +0200 Subject: [PATCH 0594/2270] xhci: route string & usb hub support Parse route string in slot contexts and support devices connected via hub. --- hw/usb/hcd-xhci.c | 86 ++++++++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 31 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 14148262af..8c0155bb1e 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -363,7 +363,7 @@ typedef struct XHCIEPContext { typedef struct XHCISlot { bool enabled; dma_addr_t ctx; - unsigned int port; + USBPort *uport; unsigned int devaddr; XHCIEPContext * eps[31]; } XHCISlot; @@ -1230,7 +1230,7 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid, ep |= 0x80; } - dev = xhci->ports[xhci->slots[slotid-1].port-1].uport->dev; + dev = xhci->slots[slotid-1].uport->dev; if (!dev) { return CC_USB_TRANSACTION_ERROR; } @@ -1412,18 +1412,9 @@ static void xhci_stall_ep(XHCITransfer *xfer) static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx); -static USBDevice *xhci_find_device(XHCIPort *port, uint8_t addr) -{ - if (!(port->portsc & PORTSC_PED)) { - return NULL; - } - return usb_find_device(port->uport, addr); -} - static int xhci_setup_packet(XHCITransfer *xfer) { XHCIState *xhci = xfer->xhci; - XHCIPort *port; USBDevice *dev; USBEndpoint *ep; int dir; @@ -1434,13 +1425,12 @@ static int xhci_setup_packet(XHCITransfer *xfer) ep = xfer->packet.ep; dev = ep->dev; } else { - port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1]; - dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr); - if (!dev) { - fprintf(stderr, "xhci: slot %d port %d has no device\n", - xfer->slotid, xhci->slots[xfer->slotid-1].port); + if (!xhci->slots[xfer->slotid-1].uport) { + fprintf(stderr, "xhci: slot %d has no device\n", + xfer->slotid); return -1; } + dev = xhci->slots[xfer->slotid-1].uport->dev; ep = usb_ep_get(dev, dir, xfer->epid >> 1); } @@ -1772,7 +1762,7 @@ static TRBCCode xhci_enable_slot(XHCIState *xhci, unsigned int slotid) trace_usb_xhci_slot_enable(slotid); assert(slotid >= 1 && slotid <= MAXSLOTS); xhci->slots[slotid-1].enabled = 1; - xhci->slots[slotid-1].port = 0; + xhci->slots[slotid-1].uport = NULL; memset(xhci->slots[slotid-1].eps, 0, sizeof(XHCIEPContext*)*31); return CC_SUCCESS; @@ -1795,17 +1785,42 @@ static TRBCCode xhci_disable_slot(XHCIState *xhci, unsigned int slotid) return CC_SUCCESS; } +static USBPort *xhci_lookup_uport(XHCIState *xhci, uint32_t *slot_ctx) +{ + USBPort *uport; + char path[32]; + int i, pos, port; + + port = (slot_ctx[1]>>16) & 0xFF; + port = xhci->ports[port-1].uport->index+1; + pos = snprintf(path, sizeof(path), "%d", port); + for (i = 0; i < 5; i++) { + port = (slot_ctx[0] >> 4*i) & 0x0f; + if (!port) { + break; + } + pos += snprintf(path + pos, sizeof(path) - pos, ".%d", port); + } + + QTAILQ_FOREACH(uport, &xhci->bus.used, next) { + if (strcmp(uport->path, path) == 0) { + return uport; + } + } + return NULL; +} + static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, uint64_t pictx, bool bsr) { XHCISlot *slot; + USBPort *uport; USBDevice *dev; dma_addr_t ictx, octx, dcbaap; uint64_t poctx; uint32_t ictl_ctx[2]; uint32_t slot_ctx[4]; uint32_t ep0_ctx[5]; - unsigned int port; int i; TRBCCode res; @@ -1837,27 +1852,28 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, DPRINTF("xhci: input ep0 context: %08x %08x %08x %08x %08x\n", ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]); - port = (slot_ctx[1]>>16) & 0xFF; - dev = xhci->ports[port-1].uport->dev; - - if (port < 1 || port > xhci->numports) { - fprintf(stderr, "xhci: bad port %d\n", port); + uport = xhci_lookup_uport(xhci, slot_ctx); + if (uport == NULL) { + fprintf(stderr, "xhci: port not found\n"); return CC_TRB_ERROR; - } else if (!dev) { - fprintf(stderr, "xhci: port %d not connected\n", port); + } + + dev = uport->dev; + if (!dev) { + fprintf(stderr, "xhci: port %s not connected\n", uport->path); return CC_USB_TRANSACTION_ERROR; } for (i = 0; i < MAXSLOTS; i++) { - if (xhci->slots[i].port == port) { - fprintf(stderr, "xhci: port %d already assigned to slot %d\n", - port, i+1); + if (xhci->slots[i].uport == uport) { + fprintf(stderr, "xhci: port %s already assigned to slot %d\n", + uport->path, i+1); return CC_TRB_ERROR; } } slot = &xhci->slots[slotid-1]; - slot->port = port; + slot->uport = uport; slot->ctx = octx; if (bsr) { @@ -2821,9 +2837,17 @@ static void xhci_complete(USBPort *port, USBPacket *packet) xhci_kick_ep(xfer->xhci, xfer->slotid, xfer->epid); } -static void xhci_child_detach(USBPort *port, USBDevice *child) +static void xhci_child_detach(USBPort *uport, USBDevice *child) { - FIXME(); + USBBus *bus = usb_bus_from_device(child); + XHCIState *xhci = container_of(bus, XHCIState, bus); + int i; + + for (i = 0; i < MAXSLOTS; i++) { + if (xhci->slots[i].uport == uport) { + xhci->slots[i].uport = NULL; + } + } } static USBPortOps xhci_port_ops = { From 1d8a4e69eeda7e474d1a6b50951b0b1680f8186e Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 20 Sep 2012 13:36:04 +0200 Subject: [PATCH 0595/2270] xhci: create a memory region for each port Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 85 ++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 8c0155bb1e..e79a8724c5 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -285,6 +285,8 @@ typedef enum TRBCCode { #define SLOT_CONTEXT_ENTRIES_MASK 0x1f #define SLOT_CONTEXT_ENTRIES_SHIFT 27 +typedef struct XHCIState XHCIState; + typedef enum EPType { ET_INVALID = 0, ET_ISO_OUT, @@ -303,15 +305,15 @@ typedef struct XHCIRing { } XHCIRing; typedef struct XHCIPort { + XHCIState *xhci; uint32_t portsc; uint32_t portnr; USBPort *uport; uint32_t speedmask; + char name[16]; + MemoryRegion mem; } XHCIPort; -struct XHCIState; -typedef struct XHCIState XHCIState; - typedef struct XHCITransfer { XHCIState *xhci; USBPacket packet; @@ -2430,20 +2432,14 @@ static uint64_t xhci_cap_read(void *ptr, target_phys_addr_t reg, unsigned size) return ret; } -static uint32_t xhci_port_read(XHCIState *xhci, uint32_t reg) +static uint64_t xhci_port_read(void *ptr, target_phys_addr_t reg, unsigned size) { - uint32_t port = reg >> 4; + XHCIPort *port = ptr; uint32_t ret; - if (port >= xhci->numports) { - fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port); - ret = 0; - goto out; - } - - switch (reg & 0xf) { + switch (reg) { case 0x00: /* PORTSC */ - ret = xhci->ports[port].portsc; + ret = port->portsc; break; case 0x04: /* PORTPMSC */ case 0x08: /* PORTLI */ @@ -2452,30 +2448,25 @@ static uint32_t xhci_port_read(XHCIState *xhci, uint32_t reg) case 0x0c: /* reserved */ default: fprintf(stderr, "xhci_port_read (port %d): reg 0x%x unimplemented\n", - port, reg); + port->portnr, (uint32_t)reg); ret = 0; } -out: - trace_usb_xhci_port_read(port, reg & 0x0f, ret); + trace_usb_xhci_port_read(port->portnr, reg, ret); return ret; } -static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val) +static void xhci_port_write(void *ptr, target_phys_addr_t reg, + uint64_t val, unsigned size) { - uint32_t port = reg >> 4; + XHCIPort *port = ptr; uint32_t portsc; - trace_usb_xhci_port_write(port, reg & 0x0f, val); + trace_usb_xhci_port_write(port->portnr, reg, val); - if (port >= xhci->numports) { - fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port); - return; - } - - switch (reg & 0xf) { + switch (reg) { case 0x00: /* PORTSC */ - portsc = xhci->ports[port].portsc; + portsc = port->portsc; /* write-1-to-clear bits*/ portsc &= ~(val & (PORTSC_CSC|PORTSC_PEC|PORTSC_WRC|PORTSC_OCC| PORTSC_PRC|PORTSC_PLC|PORTSC_CEC)); @@ -2490,16 +2481,16 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val) /* write-1-to-start bits */ if (val & PORTSC_PR) { DPRINTF("xhci: port %d reset\n", port); - usb_device_reset(xhci->ports[port].uport->dev); + usb_device_reset(port->uport->dev); portsc |= PORTSC_PRC | PORTSC_PED; } - xhci->ports[port].portsc = portsc; + port->portsc = portsc; break; case 0x04: /* PORTPMSC */ case 0x08: /* PORTLI */ default: fprintf(stderr, "xhci_port_write (port %d): reg 0x%x unimplemented\n", - port, reg); + port->portnr, (uint32_t)reg); } } @@ -2508,10 +2499,6 @@ static uint64_t xhci_oper_read(void *ptr, target_phys_addr_t reg, unsigned size) XHCIState *xhci = ptr; uint32_t ret; - if (reg >= 0x400) { - return xhci_port_read(xhci, reg - 0x400); - } - switch (reg) { case 0x00: /* USBCMD */ ret = xhci->usbcmd; @@ -2554,11 +2541,6 @@ static void xhci_oper_write(void *ptr, target_phys_addr_t reg, { XHCIState *xhci = ptr; - if (reg >= 0x400) { - xhci_port_write(xhci, reg - 0x400, val); - return; - } - trace_usb_xhci_oper_write(reg, val); switch (reg) { @@ -2777,6 +2759,14 @@ static const MemoryRegionOps xhci_oper_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; +static const MemoryRegionOps xhci_port_ops = { + .read = xhci_port_read, + .write = xhci_port_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + static const MemoryRegionOps xhci_runtime_ops = { .read = xhci_runtime_read, .write = xhci_runtime_write, @@ -2850,7 +2840,7 @@ static void xhci_child_detach(USBPort *uport, USBDevice *child) } } -static USBPortOps xhci_port_ops = { +static USBPortOps xhci_uport_ops = { .attach = xhci_attach, .detach = xhci_detach, .wakeup = xhci_wakeup, @@ -2930,6 +2920,7 @@ static void usb_xhci_init(XHCIState *xhci, DeviceState *dev) USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL | USB_SPEED_MASK_HIGH; + snprintf(port->name, sizeof(port->name), "usb2 port #%d", i+1); speedmask |= port->speedmask; } if (i < xhci->numports_3) { @@ -2937,16 +2928,17 @@ static void usb_xhci_init(XHCIState *xhci, DeviceState *dev) port->portnr = i + 1 + xhci->numports_2; port->uport = &xhci->uports[i]; port->speedmask = USB_SPEED_MASK_SUPER; + snprintf(port->name, sizeof(port->name), "usb3 port #%d", i+1); speedmask |= port->speedmask; } usb_register_port(&xhci->bus, &xhci->uports[i], xhci, i, - &xhci_port_ops, speedmask); + &xhci_uport_ops, speedmask); } } static int usb_xhci_initfn(struct PCIDevice *dev) { - int ret; + int i, ret; XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev, dev); @@ -2965,7 +2957,7 @@ static int usb_xhci_initfn(struct PCIDevice *dev) memory_region_init_io(&xhci->mem_cap, &xhci_cap_ops, xhci, "capabilities", LEN_CAP); memory_region_init_io(&xhci->mem_oper, &xhci_oper_ops, xhci, - "operational", 0x400 + 0x10 * xhci->numports); + "operational", 0x400); memory_region_init_io(&xhci->mem_runtime, &xhci_runtime_ops, xhci, "runtime", LEN_RUNTIME); memory_region_init_io(&xhci->mem_doorbell, &xhci_doorbell_ops, xhci, @@ -2976,6 +2968,15 @@ static int usb_xhci_initfn(struct PCIDevice *dev) memory_region_add_subregion(&xhci->mem, OFF_RUNTIME, &xhci->mem_runtime); memory_region_add_subregion(&xhci->mem, OFF_DOORBELL, &xhci->mem_doorbell); + for (i = 0; i < xhci->numports; i++) { + XHCIPort *port = &xhci->ports[i]; + uint32_t offset = OFF_OPER + 0x400 + 0x10 * i; + port->xhci = xhci; + memory_region_init_io(&port->mem, &xhci_port_ops, port, + port->name, 0x10); + memory_region_add_subregion(&xhci->mem, offset, &port->mem); + } + pci_register_bar(&xhci->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64, &xhci->mem); From cae5d3f4b3fbe9b681c0c4046008af424bd1d6a5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 20 Sep 2012 17:38:07 +0200 Subject: [PATCH 0596/2270] ehci: Fix interrupt packet MULT handling There are several issues with our handling of the MULT epcap field of interrupt qhs, which this patch fixes. 1) When we don't execute a transaction because of the transaction counter being 0, p->async stays EHCI_ASYNC_NONE, and the next time we process the same qtd we hit an assert in ehci_state_fetchqtd because of this. Even though I believe that this is caused by 3 below, this patch still removes the assert, as that can still happen without 3, when multiple packets are queued for the same interrupt ep. 2) We only *check* the transaction counter from ehci_state_execute, any packets queued up by fill_queue bypass this check. This is fixed by not calling fill_queue for interrupt packets. 3) Some versions of Windows set the MULT field of the qh to 0, which is a clear violation of the EHCI spec, but still they do it. This means that we will never execute a qtd for these, making interrupt ep-s on USB-2 devices not work, and after recent changes, triggering 1). So far we've stored the transaction counter in our copy of the mult field, but with this beginnig at 0 already when dealing with these version of windows this won't work. So this patch adds a transact_ctr field to our qh struct, and sets this to the MULT field value on fetchqh. When the MULT field value is 0, we set it to 4. Assuming that windows gets way with setting it to 0, by the actual hardware going horizontal on a 1 -> 0 transition, which will give it 4 transactions (MULT goes from 0 - 3). Note that we cannot stop on detecting the 1 -> 0 transition, as our decrement of the transaction counter, and checking for it are done in 2 different places. Reported-by: Shawn Starr Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 6a5da8413f..8bdb806b9b 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -373,6 +373,7 @@ struct EHCIQueue { uint32_t seen; uint64_t ts; int async; + int transact_ctr; /* cached data from guest - needs to be flushed * when guest removes an entry (doorbell, handshake sequence) @@ -1837,6 +1838,11 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) } q->qh = qh; + q->transact_ctr = get_field(q->qh.epcap, QH_EPCAP_MULT); + if (q->transact_ctr == 0) { /* Guest bug in some versions of windows */ + q->transact_ctr = 4; + } + if (q->dev == NULL) { q->dev = ehci_find_device(q->ehci, devaddr); } @@ -2014,11 +2020,8 @@ static int ehci_state_fetchqtd(EHCIQueue *q) } else if (p != NULL) { switch (p->async) { case EHCI_ASYNC_NONE: - /* Should never happen packet should at least be initialized */ - assert(0); - break; case EHCI_ASYNC_INITIALIZED: - /* Previously nacked packet (likely interrupt ep) */ + /* Not yet executed (MULT), or previously nacked (int) packet */ ehci_set_state(q->ehci, q->async, EST_EXECUTE); break; case EHCI_ASYNC_INFLIGHT: @@ -2107,15 +2110,12 @@ static int ehci_state_execute(EHCIQueue *q) // TODO verify enough time remains in the uframe as in 4.4.1.1 // TODO write back ptr to async list when done or out of time - // TODO Windows does not seem to ever set the MULT field - if (!q->async) { - int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT); - if (!transactCtr) { - ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); - again = 1; - goto out; - } + /* 4.10.3, bottom of page 82, go horizontal on transaction counter == 0 */ + if (!q->async && q->transact_ctr == 0) { + ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); + again = 1; + goto out; } if (q->async) { @@ -2132,7 +2132,11 @@ static int ehci_state_execute(EHCIQueue *q) trace_usb_ehci_packet_action(p->queue, p, "async"); p->async = EHCI_ASYNC_INFLIGHT; ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); - again = (ehci_fill_queue(p) == USB_RET_PROCERR) ? -1 : 1; + if (q->async) { + again = (ehci_fill_queue(p) == USB_RET_PROCERR) ? -1 : 1; + } else { + again = 1; + } goto out; } @@ -2152,13 +2156,9 @@ static int ehci_state_executing(EHCIQueue *q) ehci_execute_complete(q); - // 4.10.3 - if (!q->async) { - int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT); - transactCtr--; - set_field(&q->qh.epcap, transactCtr, QH_EPCAP_MULT); - // 4.10.3, bottom of page 82, should exit this state when transaction - // counter decrements to 0 + /* 4.10.3 */ + if (!q->async && q->transact_ctr > 0) { + q->transact_ctr--; } /* 4.10.5 */ From 8b626aa7841ef79b70066c880b3b6c29496797af Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 25 Sep 2012 13:22:21 +0200 Subject: [PATCH 0597/2270] usb-redir: Adjust pkg-config check for usbredirparser .pc file rename (v2) The usbredir 0.5 release introduced the new API for 64 bit packet ids, but it kept the libusbredirparser.pc name as is, meaning that older versions of qemu will still have their pkg-config check for usbredirparser fulfilled, and build with the usb-redir device. Due to the API change there will be some compiler warnings, but the build will succeed, however the usb-redir device will be broken on 32 bit machines. To solve this a new usbredir-0.5.2 release is coming, which renames the libusbredirparser.pc file to libusbredirparser-0.5.pc, so that it will no longer fulfill the pkg-config check of the qemu-1.2 and older releases, stopping the (silent) breakage. This patch adjusts qemu master's configure to properly detect the new usbredir release. Changes in v2: -Not only use the new .pc name in the check but also when getting cflags and libs! Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- configure | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 1b865174e1..4f240620d7 100755 --- a/configure +++ b/configure @@ -2752,10 +2752,10 @@ fi # check for usbredirparser for usb network redirection support if test "$usb_redir" != "no" ; then - if $pkg_config --atleast-version=0.5 libusbredirparser >/dev/null 2>&1 ; then + if $pkg_config --atleast-version=0.5 libusbredirparser-0.5 >/dev/null 2>&1 ; then usb_redir="yes" - usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null) - usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null) + usb_redir_cflags=$($pkg_config --cflags libusbredirparser-0.5 2>/dev/null) + usb_redir_libs=$($pkg_config --libs libusbredirparser-0.5 2>/dev/null) QEMU_CFLAGS="$QEMU_CFLAGS $usb_redir_cflags" libs_softmmu="$libs_softmmu $usb_redir_libs" else From 39c138c8420f51a7da7b35233a8d7400a0b589ac Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 26 Sep 2012 12:59:31 +1000 Subject: [PATCH 0598/2270] usb: Fix usb_packet_map() in the presence of IOMMUs With the IOMMU infrastructure introduced before 1.2, we need to use dma_memory_map() to obtain a qemu pointer to memory from an IO bus address. However, dma_memory_map() alters the given length to reflect the length over which the used DMA translation is valid - which could be either more or less than the requested length. usb_packet_map() does not correctly handle these cases, simply failing if dma_memory_map() alters the requested length. If dma_memory_map() increased the length, we just need to use the requested length for the qemu_iovec_add(). However, if it decreased the length, it means that a single DMA translation is not valid for the whole sglist element, and so we need to loop, splitting it up into multiple iovec entries for each piece with a DMA translation (in practice >2 pieces is unlikely). This patch implements the correct behaviour Signed-off-by: David Gibson Signed-off-by: Gerd Hoffmann --- hw/usb/libhw.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/hw/usb/libhw.c b/hw/usb/libhw.c index c0de30ea88..703e2d213b 100644 --- a/hw/usb/libhw.c +++ b/hw/usb/libhw.c @@ -28,19 +28,25 @@ int usb_packet_map(USBPacket *p, QEMUSGList *sgl) { DMADirection dir = (p->pid == USB_TOKEN_IN) ? DMA_DIRECTION_FROM_DEVICE : DMA_DIRECTION_TO_DEVICE; - dma_addr_t len; void *mem; int i; for (i = 0; i < sgl->nsg; i++) { - len = sgl->sg[i].len; - mem = dma_memory_map(sgl->dma, sgl->sg[i].base, &len, dir); - if (!mem) { - goto err; - } - qemu_iovec_add(&p->iov, mem, len); - if (len != sgl->sg[i].len) { - goto err; + dma_addr_t base = sgl->sg[i].base; + dma_addr_t len = sgl->sg[i].len; + + while (len) { + dma_addr_t xlen = len; + mem = dma_memory_map(sgl->dma, sgl->sg[i].base, &xlen, dir); + if (!mem) { + goto err; + } + if (xlen > len) { + xlen = len; + } + qemu_iovec_add(&p->iov, mem, xlen); + len -= xlen; + base += xlen; } } return 0; From e9d17b6890ae772f3652c8cacf4e1f72f576f907 Mon Sep 17 00:00:00 2001 From: Ryota Ozaki Date: Fri, 14 Sep 2012 21:44:20 +0900 Subject: [PATCH 0599/2270] Make negotiation optional in QEMUMonitorProtocol This is a preparation for qemu-ga-client which uses QEMUMonitorProtocol class. The class tries to negotiate capabilities on connect, however, qemu-ga doesn't suppose it and fails. This change makes the negotiation optional, though it's still performed by default for compatibility. Signed-off-by: Ryota Ozaki Signed-off-by: Luiz Capitulino --- QMP/qmp.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/QMP/qmp.py b/QMP/qmp.py index 36ecc1dfae..5a573e1488 100644 --- a/QMP/qmp.py +++ b/QMP/qmp.py @@ -49,7 +49,6 @@ class QEMUMonitorProtocol: return socket.socket(family, socket.SOCK_STREAM) def __negotiate_capabilities(self): - self.__sockfile = self.__sock.makefile() greeting = self.__json_read() if greeting is None or not greeting.has_key('QMP'): raise QMPConnectError @@ -73,7 +72,7 @@ class QEMUMonitorProtocol: error = socket.error - def connect(self): + def connect(self, negotiate=True): """ Connect to the QMP Monitor and perform capabilities negotiation. @@ -83,7 +82,9 @@ class QEMUMonitorProtocol: @raise QMPCapabilitiesError if fails to negotiate capabilities """ self.__sock.connect(self.__address) - return self.__negotiate_capabilities() + self.__sockfile = self.__sock.makefile() + if negotiate: + return self.__negotiate_capabilities() def accept(self): """ From e37b350aa8766ae36ec9bf40fab665455d4a5530 Mon Sep 17 00:00:00 2001 From: Ryota Ozaki Date: Fri, 14 Sep 2012 21:44:21 +0900 Subject: [PATCH 0600/2270] Support settimeout in QEMUMonitorProtocol This method is used in the following qemu-ga-client script to implement non-blocking operations. Signed-off-by: Ryota Ozaki Signed-off-by: Luiz Capitulino --- QMP/qmp.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/QMP/qmp.py b/QMP/qmp.py index 5a573e1488..33c7d36d9b 100644 --- a/QMP/qmp.py +++ b/QMP/qmp.py @@ -162,3 +162,8 @@ class QEMUMonitorProtocol: def close(self): self.__sock.close() self.__sockfile.close() + + timeout = socket.timeout + + def settimeout(self, timeout): + self.__sock.settimeout(timeout) From f513cbf7503d8db3778df436beaf25f3d8260317 Mon Sep 17 00:00:00 2001 From: Ryota Ozaki Date: Fri, 14 Sep 2012 21:44:22 +0900 Subject: [PATCH 0601/2270] Add qemu-ga-client script This is an easy-to-use QEMU guest agent client written in Python. It simply provides commands to call guest agent functions like ping, fsfreeze and shutdown. Additionally, it provides extra useful commands, e.g, cat, ifconfig and reboot, by using guet agent functions. Examples: $ export QGA_CLIENT_ADDRESS=/tmp/qga.sock $ qemu-ga-client ping $ qemu-ga-client cat /etc/resolv.conf # Generated by NetworkManager nameserver 10.0.2.3 $ qemu-ga-client fsfreeze status thawed $ qemu-ga-client fsfreeze freeze 2 filesystems frozen The script communicates with a guest agent by means of qmp.QEMUMonitorProtocol. Every commands are called with timeout (3 sec.) to avoid blocking. The script always calls sync command prior to issuing an actual command (except for ping which doesn't need sync). Signed-off-by: Ryota Ozaki Signed-off-by: Luiz Capitulino --- QMP/qemu-ga-client | 299 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100755 QMP/qemu-ga-client diff --git a/QMP/qemu-ga-client b/QMP/qemu-ga-client new file mode 100755 index 0000000000..46676c3750 --- /dev/null +++ b/QMP/qemu-ga-client @@ -0,0 +1,299 @@ +#!/usr/bin/python + +# QEMU Guest Agent Client +# +# Copyright (C) 2012 Ryota Ozaki +# +# This work is licensed under the terms of the GNU GPL, version 2. See +# the COPYING file in the top-level directory. +# +# Usage: +# +# Start QEMU with: +# +# # qemu [...] -chardev socket,path=/tmp/qga.sock,server,nowait,id=qga0 \ +# -device virtio-serial -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0 +# +# Run the script: +# +# $ qemu-ga-client --address=/tmp/qga.sock [args...] +# +# or +# +# $ export QGA_CLIENT_ADDRESS=/tmp/qga.sock +# $ qemu-ga-client [args...] +# +# For example: +# +# $ qemu-ga-client cat /etc/resolv.conf +# # Generated by NetworkManager +# nameserver 10.0.2.3 +# $ qemu-ga-client fsfreeze status +# thawed +# $ qemu-ga-client fsfreeze freeze +# 2 filesystems frozen +# +# See also: http://wiki.qemu.org/Features/QAPI/GuestAgent +# + +import base64 +import random + +import qmp + + +class QemuGuestAgent(qmp.QEMUMonitorProtocol): + def __getattr__(self, name): + def wrapper(**kwds): + return self.command('guest-' + name.replace('_', '-'), **kwds) + return wrapper + + +class QemuGuestAgentClient: + error = QemuGuestAgent.error + + def __init__(self, address): + self.qga = QemuGuestAgent(address) + self.qga.connect(negotiate=False) + + def sync(self, timeout=3): + # Avoid being blocked forever + if not self.ping(timeout): + raise EnvironmentError('Agent seems not alive') + uid = random.randint(0, (1 << 32) - 1) + while True: + ret = self.qga.sync(id=uid) + if isinstance(ret, int) and int(ret) == uid: + break + + def __file_read_all(self, handle): + eof = False + data = '' + while not eof: + ret = self.qga.file_read(handle=handle, count=1024) + _data = base64.b64decode(ret['buf-b64']) + data += _data + eof = ret['eof'] + return data + + def read(self, path): + handle = self.qga.file_open(path=path) + try: + data = self.__file_read_all(handle) + finally: + self.qga.file_close(handle=handle) + return data + + def info(self): + info = self.qga.info() + + msgs = [] + msgs.append('version: ' + info['version']) + msgs.append('supported_commands:') + enabled = [c['name'] for c in info['supported_commands'] if c['enabled']] + msgs.append('\tenabled: ' + ', '.join(enabled)) + disabled = [c['name'] for c in info['supported_commands'] if not c['enabled']] + msgs.append('\tdisabled: ' + ', '.join(disabled)) + + return '\n'.join(msgs) + + def __gen_ipv4_netmask(self, prefixlen): + mask = int('1' * prefixlen + '0' * (32 - prefixlen), 2) + return '.'.join([str(mask >> 24), + str((mask >> 16) & 0xff), + str((mask >> 8) & 0xff), + str(mask & 0xff)]) + + def ifconfig(self): + nifs = self.qga.network_get_interfaces() + + msgs = [] + for nif in nifs: + msgs.append(nif['name'] + ':') + if 'ip-addresses' in nif: + for ipaddr in nif['ip-addresses']: + if ipaddr['ip-address-type'] == 'ipv4': + addr = ipaddr['ip-address'] + mask = self.__gen_ipv4_netmask(int(ipaddr['prefix'])) + msgs.append("\tinet %s netmask %s" % (addr, mask)) + elif ipaddr['ip-address-type'] == 'ipv6': + addr = ipaddr['ip-address'] + prefix = ipaddr['prefix'] + msgs.append("\tinet6 %s prefixlen %s" % (addr, prefix)) + if nif['hardware-address'] != '00:00:00:00:00:00': + msgs.append("\tether " + nif['hardware-address']) + + return '\n'.join(msgs) + + def ping(self, timeout): + self.qga.settimeout(timeout) + try: + self.qga.ping() + except self.qga.timeout: + return False + return True + + def fsfreeze(self, cmd): + if cmd not in ['status', 'freeze', 'thaw']: + raise StandardError('Invalid command: ' + cmd) + + return getattr(self.qga, 'fsfreeze' + '_' + cmd)() + + def fstrim(self, minimum=0): + return getattr(self.qga, 'fstrim')(minimum=minimum) + + def suspend(self, mode): + if mode not in ['disk', 'ram', 'hybrid']: + raise StandardError('Invalid mode: ' + mode) + + try: + getattr(self.qga, 'suspend' + '_' + mode)() + # On error exception will raise + except self.qga.timeout: + # On success command will timed out + return + + def shutdown(self, mode='powerdown'): + if mode not in ['powerdown', 'halt', 'reboot']: + raise StandardError('Invalid mode: ' + mode) + + try: + self.qga.shutdown(mode=mode) + except self.qga.timeout: + return + + +def _cmd_cat(client, args): + if len(args) != 1: + print('Invalid argument') + print('Usage: cat ') + sys.exit(1) + print(client.read(args[0])) + + +def _cmd_fsfreeze(client, args): + usage = 'Usage: fsfreeze status|freeze|thaw' + if len(args) != 1: + print('Invalid argument') + print(usage) + sys.exit(1) + if args[0] not in ['status', 'freeze', 'thaw']: + print('Invalid command: ' + args[0]) + print(usage) + sys.exit(1) + cmd = args[0] + ret = client.fsfreeze(cmd) + if cmd == 'status': + print(ret) + elif cmd == 'freeze': + print("%d filesystems frozen" % ret) + else: + print("%d filesystems thawed" % ret) + + +def _cmd_fstrim(client, args): + if len(args) == 0: + minimum = 0 + else: + minimum = int(args[0]) + print(client.fstrim(minimum)) + + +def _cmd_ifconfig(client, args): + print(client.ifconfig()) + + +def _cmd_info(client, args): + print(client.info()) + + +def _cmd_ping(client, args): + if len(args) == 0: + timeout = 3 + else: + timeout = float(args[0]) + alive = client.ping(timeout) + if not alive: + print("Not responded in %s sec" % args[0]) + sys.exit(1) + + +def _cmd_suspend(client, args): + usage = 'Usage: suspend disk|ram|hybrid' + if len(args) != 1: + print('Less argument') + print(usage) + sys.exit(1) + if args[0] not in ['disk', 'ram', 'hybrid']: + print('Invalid command: ' + args[0]) + print(usage) + sys.exit(1) + client.suspend(args[0]) + + +def _cmd_shutdown(client, args): + client.shutdown() +_cmd_powerdown = _cmd_shutdown + + +def _cmd_halt(client, args): + client.shutdown('halt') + + +def _cmd_reboot(client, args): + client.shutdown('reboot') + + +commands = [m.replace('_cmd_', '') for m in dir() if '_cmd_' in m] + + +def main(address, cmd, args): + if not os.path.exists(address): + print('%s not found' % address) + sys.exit(1) + + if cmd not in commands: + print('Invalid command: ' + cmd) + print('Available commands: ' + ', '.join(commands)) + sys.exit(1) + + try: + client = QemuGuestAgentClient(address) + except QemuGuestAgent.error, e: + import errno + + print(e) + if e.errno == errno.ECONNREFUSED: + print('Hint: qemu is not running?') + sys.exit(1) + + if cmd != 'ping': + client.sync() + + globals()['_cmd_' + cmd](client, args) + + +if __name__ == '__main__': + import sys + import os + import optparse + + address = os.environ['QGA_CLIENT_ADDRESS'] if 'QGA_CLIENT_ADDRESS' in os.environ else None + + usage = "%prog [--address=|] [args...]\n" + usage += ': ' + ', '.join(commands) + parser = optparse.OptionParser(usage=usage) + parser.add_option('--address', action='store', type='string', + default=address, help='Specify a ip:port pair or a unix socket path') + options, args = parser.parse_args() + + address = options.address + if address is None: + parser.error('address is not specified') + sys.exit(1) + + if len(args) == 0: + parser.error('Less argument') + sys.exit(1) + + main(address, args[0], args[1:]) From eda50a656f52a5172fa8a95f7b217565b90d413e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 19 Sep 2012 16:31:06 +0200 Subject: [PATCH 0602/2270] qapi: do not protect enum values from namespace pollution Enum values are always preceded by the uppercase name of the enum, so they do not conflict with reserved words. Signed-off-by: Paolo Bonzini Signed-off-by: Luiz Capitulino --- scripts/qapi-types.py | 4 ++-- scripts/qapi-visit.py | 2 +- scripts/qapi.py | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index 49ef569a2f..1b84834959 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -91,9 +91,9 @@ const char *%(name)s_lookup[] = { def generate_enum_name(name): if name.isupper(): - return c_fun(name) + return c_fun(name, False) new_name = '' - for c in c_fun(name): + for c in c_fun(name, False): if c.isupper(): new_name += '_' new_name += c diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index e2093e8947..a360de719f 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -173,7 +173,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** break; ''', abbrev = de_camel_case(name).upper(), - enum = c_fun(de_camel_case(key)).upper(), + enum = c_fun(de_camel_case(key),False).upper(), c_type=members[key], c_name=c_fun(key)) diff --git a/scripts/qapi.py b/scripts/qapi.py index 122b4cb6d1..057332e4ca 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -141,7 +141,7 @@ def camel_case(name): new_name += ch.lower() return new_name -def c_var(name): +def c_var(name, protect=True): # ANSI X3J11/88-090, 3.1.1 c89_words = set(['auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do', 'double', 'else', 'enum', 'extern', 'float', @@ -156,12 +156,12 @@ def c_var(name): # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html # excluding _.* gcc_words = set(['asm', 'typeof']) - if name in c89_words | c99_words | c11_words | gcc_words: + if protect and (name in c89_words | c99_words | c11_words | gcc_words): return "q_" + name return name.replace('-', '_').lstrip("*") -def c_fun(name): - return c_var(name).replace('.', '_') +def c_fun(name, protect=True): + return c_var(name, protect).replace('.', '_') def c_list_type(name): return '%sList' % name From 1057725f6629fc2771a294a92ce8eedb92c86fe8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 19 Sep 2012 16:31:07 +0200 Subject: [PATCH 0603/2270] qapi: add "unix" to the set of reserved words It is #defined to 1. Signed-off-by: Paolo Bonzini Signed-off-by: Luiz Capitulino --- scripts/qapi.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/qapi.py b/scripts/qapi.py index 057332e4ca..afc5f32aeb 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -156,7 +156,9 @@ def c_var(name, protect=True): # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html # excluding _.* gcc_words = set(['asm', 'typeof']) - if protect and (name in c89_words | c99_words | c11_words | gcc_words): + # namespace pollution: + polluted_words = set(['unix']) + if protect and (name in c89_words | c99_words | c11_words | gcc_words | polluted_words): return "q_" + name return name.replace('-', '_').lstrip("*") From 9a3a88956c7f32130ad20011f7c3c161fa5876d8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 20 Sep 2012 16:50:32 +0200 Subject: [PATCH 0604/2270] pci-assign: use monitor_handle_fd_param There is no need to open-code the choice between a file descriptor number or a named one. Just use monitor_handle_fd_param, which also takes care of printing the error message. Signed-off-by: Paolo Bonzini Signed-off-by: Luiz Capitulino Reviewed-by: Markus Armbruster --- hw/kvm/pci-assign.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/hw/kvm/pci-assign.c b/hw/kvm/pci-assign.c index 05b93d9a51..7a0998c518 100644 --- a/hw/kvm/pci-assign.c +++ b/hw/kvm/pci-assign.c @@ -579,15 +579,9 @@ static int get_real_device(AssignedDevice *pci_dev, uint16_t r_seg, snprintf(name, sizeof(name), "%sconfig", dir); if (pci_dev->configfd_name && *pci_dev->configfd_name) { - if (qemu_isdigit(pci_dev->configfd_name[0])) { - dev->config_fd = strtol(pci_dev->configfd_name, NULL, 0); - } else { - dev->config_fd = monitor_get_fd(cur_mon, pci_dev->configfd_name); - if (dev->config_fd < 0) { - error_report("%s: (%s) unkown", __func__, - pci_dev->configfd_name); - return 1; - } + dev->config_fd = monitor_handle_fd_param(cur_mon, pci_dev->configfd_name); + if (dev->config_fd < 0) { + return 1; } } else { dev->config_fd = open(name, O_RDWR); From a9940fc4cba811adfb296fe07b247ee707265f90 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 20 Sep 2012 16:50:32 +0200 Subject: [PATCH 0605/2270] monitor: add Error * argument to monitor_get_fd Signed-off-by: Paolo Bonzini Signed-off-by: Luiz Capitulino Reviewed-by: Markus Armbruster --- dump.c | 3 +-- migration-fd.c | 2 +- monitor.c | 15 +++++++++------ monitor.h | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/dump.c b/dump.c index 2bf8d8d994..1a3c7164be 100644 --- a/dump.c +++ b/dump.c @@ -836,9 +836,8 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin, #if !defined(WIN32) if (strstart(file, "fd:", &p)) { - fd = monitor_get_fd(cur_mon, p); + fd = monitor_get_fd(cur_mon, p, errp); if (fd == -1) { - error_set(errp, QERR_FD_NOT_FOUND, p); return; } } diff --git a/migration-fd.c b/migration-fd.c index 50138edb34..73351678e0 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -75,7 +75,7 @@ static int fd_close(MigrationState *s) int fd_start_outgoing_migration(MigrationState *s, const char *fdname) { - s->fd = monitor_get_fd(cur_mon, fdname); + s->fd = monitor_get_fd(cur_mon, fdname, NULL); if (s->fd == -1) { DPRINTF("fd_migration: invalid file descriptor identifier\n"); goto err_after_get_fd; diff --git a/monitor.c b/monitor.c index 67064e2706..c24235e909 100644 --- a/monitor.c +++ b/monitor.c @@ -951,7 +951,7 @@ static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_d CharDriverState *s; if (strcmp(protocol, "spice") == 0) { - int fd = monitor_get_fd(mon, fdname); + int fd = monitor_get_fd(mon, fdname, NULL); int skipauth = qdict_get_try_bool(qdict, "skipauth", 0); int tls = qdict_get_try_bool(qdict, "tls", 0); if (!using_spice) { @@ -965,13 +965,13 @@ static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_d return 0; #ifdef CONFIG_VNC } else if (strcmp(protocol, "vnc") == 0) { - int fd = monitor_get_fd(mon, fdname); + int fd = monitor_get_fd(mon, fdname, NULL); int skipauth = qdict_get_try_bool(qdict, "skipauth", 0); vnc_display_add_client(NULL, fd, skipauth); return 0; #endif } else if ((s = qemu_chr_find(protocol)) != NULL) { - int fd = monitor_get_fd(mon, fdname); + int fd = monitor_get_fd(mon, fdname, NULL); if (qemu_chr_add_client(s, fd) < 0) { qerror_report(QERR_ADD_CLIENT_FAILED); return -1; @@ -2118,7 +2118,7 @@ static void do_loadvm(Monitor *mon, const QDict *qdict) } } -int monitor_get_fd(Monitor *mon, const char *fdname) +int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp) { mon_fd_t *monfd; @@ -2139,6 +2139,7 @@ int monitor_get_fd(Monitor *mon, const char *fdname) return fd; } + error_setg(errp, "File descriptor named '%s' has not been found", fdname); return -1; } @@ -2410,12 +2411,14 @@ int monitor_fdset_dup_fd_remove(int dup_fd) int monitor_handle_fd_param(Monitor *mon, const char *fdname) { int fd; + Error *local_err = NULL; if (!qemu_isdigit(fdname[0]) && mon) { - fd = monitor_get_fd(mon, fdname); + fd = monitor_get_fd(mon, fdname, &local_err); if (fd == -1) { - error_report("No file descriptor named %s found", fdname); + qerror_report_err(local_err); + error_free(local_err); return -1; } } else { diff --git a/monitor.h b/monitor.h index 64c1561844..e240c3f42d 100644 --- a/monitor.h +++ b/monitor.h @@ -66,7 +66,7 @@ int monitor_read_block_device_key(Monitor *mon, const char *device, BlockDriverCompletionFunc *completion_cb, void *opaque); -int monitor_get_fd(Monitor *mon, const char *fdname); +int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp); int monitor_handle_fd_param(Monitor *mon, const char *fdname); void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) From b224e5e2162a767dd56dbc366f796fbe45ca5baa Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 13 Sep 2012 16:52:20 -0300 Subject: [PATCH 0606/2270] qapi: convert add_client Also fixes a few issues while there: 1. The fd returned by monitor_get_fd() leaks in most error conditions 2. monitor_get_fd() return value is not checked. Best case we get an error that is not correctly reported, worse case one of the functions using the fd (with value of -1) will explode 3. A few error conditions aren't reported 4. We now "use up" @fdname always. Before, it was left alone for invalid @protocol Signed-off-by: Luiz Capitulino Reviewed-by: Markus Armbruster --- monitor.c | 39 --------------------------------------- qapi-schema.json | 25 +++++++++++++++++++++++++ qmp-commands.hx | 5 +---- qmp.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 43 deletions(-) diff --git a/monitor.c b/monitor.c index c24235e909..c9f460ac46 100644 --- a/monitor.c +++ b/monitor.c @@ -944,45 +944,6 @@ static void do_trace_print_events(Monitor *mon) trace_print_events((FILE *)mon, &monitor_fprintf); } -static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_data) -{ - const char *protocol = qdict_get_str(qdict, "protocol"); - const char *fdname = qdict_get_str(qdict, "fdname"); - CharDriverState *s; - - if (strcmp(protocol, "spice") == 0) { - int fd = monitor_get_fd(mon, fdname, NULL); - int skipauth = qdict_get_try_bool(qdict, "skipauth", 0); - int tls = qdict_get_try_bool(qdict, "tls", 0); - if (!using_spice) { - /* correct one? spice isn't a device ,,, */ - qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice"); - return -1; - } - if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) { - close(fd); - } - return 0; -#ifdef CONFIG_VNC - } else if (strcmp(protocol, "vnc") == 0) { - int fd = monitor_get_fd(mon, fdname, NULL); - int skipauth = qdict_get_try_bool(qdict, "skipauth", 0); - vnc_display_add_client(NULL, fd, skipauth); - return 0; -#endif - } else if ((s = qemu_chr_find(protocol)) != NULL) { - int fd = monitor_get_fd(mon, fdname, NULL); - if (qemu_chr_add_client(s, fd) < 0) { - qerror_report(QERR_ADD_CLIENT_FAILED); - return -1; - } - return 0; - } - - qerror_report(QERR_INVALID_PARAMETER, "protocol"); - return -1; -} - static int client_migrate_info(Monitor *mon, const QDict *qdict, MonitorCompletion cb, void *opaque) { diff --git a/qapi-schema.json b/qapi-schema.json index 14e44199b7..191d92194c 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -32,6 +32,31 @@ 'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap', 'MigrationExpected' ] } +## +# @add_client +# +# Allow client connections for VNC, Spice and socket based +# character devices to be passed in to QEMU via SCM_RIGHTS. +# +# @protocol: protocol name. Valid names are "vnc", "spice" or the +# name of a character device (eg. from -chardev id=XXXX) +# +# @fdname: file descriptor name previously passed via 'getfd' command +# +# @skipauth: #optional whether to skip authentication. Only applies +# to "vnc" and "spice" protocols +# +# @tls: #optional whether to perform TLS. Only applies to the "spice" +# protocol +# +# Returns: nothing on success. +# +# Since: 0.14.0 +## +{ 'command': 'add_client', + 'data': { 'protocol': 'str', 'fdname': 'str', '*skipauth': 'bool', + '*tls': 'bool' } } + ## # @NameInfo: # diff --git a/qmp-commands.hx b/qmp-commands.hx index 6e21ddba61..36e08d9ffc 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1231,10 +1231,7 @@ EQMP { .name = "add_client", .args_type = "protocol:s,fdname:s,skipauth:b?,tls:b?", - .params = "protocol fdname skipauth tls", - .help = "add a graphics client", - .user_print = monitor_user_noop, - .mhandler.cmd_new = add_graphics_client, + .mhandler.cmd_new = qmp_marshal_input_add_client, }, SQMP diff --git a/qmp.c b/qmp.c index 84639220d0..36c54c57cf 100644 --- a/qmp.c +++ b/qmp.c @@ -479,3 +479,46 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) return arch_query_cpu_definitions(errp); } +void qmp_add_client(const char *protocol, const char *fdname, + bool has_skipauth, bool skipauth, bool has_tls, bool tls, + Error **errp) +{ + CharDriverState *s; + int fd; + + fd = monitor_get_fd(cur_mon, fdname, errp); + if (fd < 0) { + return; + } + + if (strcmp(protocol, "spice") == 0) { + if (!using_spice) { + error_set(errp, QERR_DEVICE_NOT_ACTIVE, "spice"); + close(fd); + return; + } + skipauth = has_skipauth ? skipauth : false; + tls = has_tls ? tls : false; + if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) { + error_setg(errp, "spice failed to add client"); + close(fd); + } + return; +#ifdef CONFIG_VNC + } else if (strcmp(protocol, "vnc") == 0) { + skipauth = has_skipauth ? skipauth : false; + vnc_display_add_client(NULL, fd, skipauth); + return; +#endif + } else if ((s = qemu_chr_find(protocol)) != NULL) { + if (qemu_chr_add_client(s, fd) < 0) { + error_setg(errp, "failed to add client"); + close(fd); + return; + } + return; + } + + error_setg(errp, "protocol '%s' is invalid", protocol); + close(fd); +} From 14c126baf1c38607c5bd988878de85a06cefd8cf Mon Sep 17 00:00:00 2001 From: Brendan Fennell Date: Wed, 26 Sep 2012 16:46:28 +0100 Subject: [PATCH 0607/2270] pl190: fix read of VECTADDR Reading VECTADDR was causing us to set the current priority to the wrong value, the most obvious effect of which was that we would return the vector for the wrong interrupt as the result of the read. Signed-off-by: Brendan Fennell Signed-off-by: Peter Maydell --- hw/pl190.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/hw/pl190.c b/hw/pl190.c index cb50afb9f4..7332f4dbae 100644 --- a/hw/pl190.c +++ b/hw/pl190.c @@ -117,12 +117,18 @@ static uint64_t pl190_read(void *opaque, target_phys_addr_t offset, return s->protected; case 12: /* VECTADDR */ /* Read vector address at the start of an ISR. Increases the - current priority level to that of the current interrupt. */ - for (i = 0; i < s->priority; i++) - { - if ((s->level | s->soft_level) & s->prio_mask[i]) - break; - } + * current priority level to that of the current interrupt. + * + * Since an enabled interrupt X at priority P causes prio_mask[Y] + * to have bit X set for all Y > P, this loop will stop with + * i == the priority of the highest priority set interrupt. + */ + for (i = 0; i < s->priority; i++) { + if ((s->level | s->soft_level) & s->prio_mask[i + 1]) { + break; + } + } + /* Reading this value with no pending interrupts is undefined. We return the default address. */ if (i == PL190_NUM_PRIO) From 9892cae39562d2e6c00ccc5966302c00f23be6d4 Mon Sep 17 00:00:00 2001 From: Meador Inge Date: Wed, 26 Sep 2012 16:46:28 +0100 Subject: [PATCH 0608/2270] hw/armv7m_nvic: Correctly register GIC region when setting up NVIC When setting up the NVIC memory regions the memory range 0x100..0xcff is aliased to an IO memory region that belongs to the ARM GIC. This aliased region should be added to the NVIC memory container, but the actual GIC IO memory region was being added instead. This mixup was causing the wrong IO memory access functions to be called when accessing parts of the NVIC memory. Signed-off-by: Meador Inge Signed-off-by: Peter Maydell --- hw/armv7m_nvic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c index 6a0832eb3f..5c09116478 100644 --- a/hw/armv7m_nvic.c +++ b/hw/armv7m_nvic.c @@ -489,7 +489,8 @@ static int armv7m_nvic_init(SysBusDevice *dev) */ memory_region_init_alias(&s->gic_iomem_alias, "nvic-gic", &s->gic.iomem, 0x100, 0xc00); - memory_region_add_subregion_overlap(&s->container, 0x100, &s->gic.iomem, 1); + memory_region_add_subregion_overlap(&s->container, 0x100, + &s->gic_iomem_alias, 1); /* Map the whole thing into system memory at the location required * by the v7M architecture. */ From 661bafb3e14bfffcb0a7c7910534c7944608ca45 Mon Sep 17 00:00:00 2001 From: Francesco Lavra Date: Wed, 19 Sep 2012 05:51:58 +0000 Subject: [PATCH 0609/2270] Versatile Express: Fix NOR flash 0 address and remove flash alias In the A series memory map (implemented in the Cortex A15 CoreTile), the first NOR flash bank (flash 0) is mapped to address 0x08000000, while address 0x00000000 can be configured as alias to either the first or the second flash bank. This patch fixes the definition of flash 0 address, and for simplicity removes the alias definition. Signed-off-by: Francesco Lavra Signed-off-by: Peter Maydell --- hw/vexpress.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/hw/vexpress.c b/hw/vexpress.c index b6158447d7..454c2bbae0 100644 --- a/hw/vexpress.c +++ b/hw/vexpress.c @@ -62,7 +62,6 @@ enum { VE_COMPACTFLASH, VE_CLCD, VE_NORFLASH0, - VE_NORFLASH0ALIAS, VE_NORFLASH1, VE_SRAM, VE_VIDEORAM, @@ -104,9 +103,8 @@ static target_phys_addr_t motherboard_legacy_map[] = { }; static target_phys_addr_t motherboard_aseries_map[] = { - /* CS0: 0x00000000 .. 0x0c000000 */ - [VE_NORFLASH0] = 0x00000000, - [VE_NORFLASH0ALIAS] = 0x08000000, + /* CS0: 0x08000000 .. 0x0c000000 */ + [VE_NORFLASH0] = 0x08000000, /* CS4: 0x0c000000 .. 0x10000000 */ [VE_NORFLASH1] = 0x0c000000, /* CS5: 0x10000000 .. 0x14000000 */ @@ -413,7 +411,6 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, sysbus_create_simple("pl111", map[VE_CLCD], pic[14]); /* VE_NORFLASH0: not modelled */ - /* VE_NORFLASH0ALIAS: not modelled */ /* VE_NORFLASH1: not modelled */ sram_size = 0x2000000; From 3dc3e7dd936f2e7f3e6dd4056f81c8961dc8201b Mon Sep 17 00:00:00 2001 From: Francesco Lavra Date: Wed, 19 Sep 2012 05:57:21 +0000 Subject: [PATCH 0610/2270] Versatile Express: Add modelling of NOR flash This patch adds modelling of the two NOR flash banks found on the Versatile Express motherboard. Tested with U-Boot running on an emulated Versatile Express, with either A9 or A15 CoreTile. Signed-off-by: Francesco Lavra Signed-off-by: Peter Maydell --- hw/vexpress.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/hw/vexpress.c b/hw/vexpress.c index 454c2bbae0..3596d1e33f 100644 --- a/hw/vexpress.c +++ b/hw/vexpress.c @@ -29,8 +29,12 @@ #include "sysemu.h" #include "boards.h" #include "exec-memory.h" +#include "blockdev.h" +#include "flash.h" #define VEXPRESS_BOARD_ID 0x8e0 +#define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024) +#define VEXPRESS_FLASH_SECT_SIZE (256 * 1024) static struct arm_boot_info vexpress_binfo; @@ -355,6 +359,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, qemu_irq pic[64]; uint32_t proc_id; uint32_t sys_id; + DriveInfo *dinfo; ram_addr_t vram_size, sram_size; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *vram = g_new(MemoryRegion, 1); @@ -410,8 +415,25 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, sysbus_create_simple("pl111", map[VE_CLCD], pic[14]); - /* VE_NORFLASH0: not modelled */ - /* VE_NORFLASH1: not modelled */ + dinfo = drive_get_next(IF_PFLASH); + if (!pflash_cfi01_register(map[VE_NORFLASH0], NULL, "vexpress.flash0", + VEXPRESS_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL, + VEXPRESS_FLASH_SECT_SIZE, + VEXPRESS_FLASH_SIZE / VEXPRESS_FLASH_SECT_SIZE, 4, + 0x00, 0x89, 0x00, 0x18, 0)) { + fprintf(stderr, "vexpress: error registering flash 0.\n"); + exit(1); + } + + dinfo = drive_get_next(IF_PFLASH); + if (!pflash_cfi01_register(map[VE_NORFLASH1], NULL, "vexpress.flash1", + VEXPRESS_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL, + VEXPRESS_FLASH_SECT_SIZE, + VEXPRESS_FLASH_SIZE / VEXPRESS_FLASH_SECT_SIZE, 4, + 0x00, 0x89, 0x00, 0x18, 0)) { + fprintf(stderr, "vexpress: error registering flash 1.\n"); + exit(1); + } sram_size = 0x2000000; memory_region_init_ram(sram, "vexpress.sram", sram_size); From d691180e41f58cc3c1f9fa848c2ab89193503160 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Fri, 21 Sep 2012 13:10:58 -0300 Subject: [PATCH 0611/2270] qmp: dump-guest-memory: improve schema doc (again) o Add a note about memory allocation with paging=true o Fix indentation Signed-off-by: Luiz Capitulino Reviewed-by: Eric Blake Reviewed-by: Markus Armbruster --- qapi-schema.json | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/qapi-schema.json b/qapi-schema.json index 191d92194c..c6a676783c 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2007,26 +2007,33 @@ # supported on i386 and x86_64. # # @paging: if true, do paging to get guest's memory mapping. This allows -# using gdb to process the core file. However, setting @paging to false -# may be desirable because of two reasons: +# using gdb to process the core file. # -# 1. The guest may be in a catastrophic state or can have corrupted -# memory, which cannot be trusted -# 2. The guest can be in real-mode even if paging is enabled. For example, -# the guest uses ACPI to sleep, and ACPI sleep state goes in real-mode +# IMPORTANT: this option can make QEMU allocate several gigabytes +# of RAM. This can happen for a large guest, or a +# malicious guest pretending to be large. +# +# Also, paging=true has the following limitations: +# +# 1. The guest may be in a catastrophic state or can have corrupted +# memory, which cannot be trusted +# 2. The guest can be in real-mode even if paging is enabled. For +# example, the guest uses ACPI to sleep, and ACPI sleep state +# goes in real-mode # # @protocol: the filename or file descriptor of the vmcore. The supported -# protocols are: +# protocols are: # -# 1. file: the protocol starts with "file:", and the following string is -# the file's path. -# 2. fd: the protocol starts with "fd:", and the following string is the -# fd's name. +# 1. file: the protocol starts with "file:", and the following +# string is the file's path. +# 2. fd: the protocol starts with "fd:", and the following string +# is the fd's name. # # @begin: #optional if specified, the starting physical address. # # @length: #optional if specified, the memory size, in bytes. If you don't -# want to dump all guest's memory, please specify the start @begin and @length +# want to dump all guest's memory, please specify the start @begin +# and @length # # Returns: nothing on success # @@ -2035,6 +2042,7 @@ { 'command': 'dump-guest-memory', 'data': { 'paging': 'bool', 'protocol': 'str', '*begin': 'int', '*length': 'int' } } + ## # @netdev_add: # From 2f61652d660ec1ffdadf926401a174c11f5c13a7 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Fri, 21 Sep 2012 13:17:55 -0300 Subject: [PATCH 0612/2270] qmp: dump-guest-memory: don't spin if non-blocking fd would block fd_write_vmcore() will indefinitely spin for a non-blocking file-descriptor that would block. However, if the fd is non-blocking, how does it make sense to spin? Change this behavior to return an error instead. Note that this can only happen with an fd provided by a management application. The fd opened internally by dump-guest-memory is blocking. While there, also fix 'writen_size' variable name. Signed-off-by: Luiz Capitulino Reviewed-by: Eric Blake Reviewed-by: Markus Armbruster --- dump.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/dump.c b/dump.c index 1a3c7164be..6b7c127906 100644 --- a/dump.c +++ b/dump.c @@ -100,18 +100,11 @@ static void dump_error(DumpState *s, const char *reason) static int fd_write_vmcore(void *buf, size_t size, void *opaque) { DumpState *s = opaque; - int fd = s->fd; - size_t writen_size; + size_t written_size; - /* The fd may be passed from user, and it can be non-blocked */ - while (size) { - writen_size = qemu_write_full(fd, buf, size); - if (writen_size != size && errno != EAGAIN) { - return -1; - } - - buf += writen_size; - size -= writen_size; + written_size = qemu_write_full(s->fd, buf, size); + if (written_size != size) { + return -1; } return 0; From 753637695bcf6b80ea96614de5d31161603ad50f Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Fri, 21 Sep 2012 13:53:00 -0300 Subject: [PATCH 0613/2270] hmp: dump-guest-memory: hardcode protocol argument to "file:" Today, it's necessary to specify the protocol you want to use when dumping the guest memory, for example: (qemu) dump-guest-memory file:/tmp/guest-memory This has a few issues: 1. It's cumbersome to type 2. We loose file path autocompletion 3. Being able to specify fd:X in HMP makes little sense for humans Because of these reasons, hardcode the 'protocol' argument to 'file:' in HMP. Signed-off-by: Luiz Capitulino Reviewed-by: Eric Blake Reviewed-by: Markus Armbruster --- hmp-commands.hx | 8 +++----- hmp.c | 8 ++++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index ed67e997fd..0302458df2 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -914,12 +914,11 @@ ETEXI #if defined(CONFIG_HAVE_CORE_DUMP) { .name = "dump-guest-memory", - .args_type = "paging:-p,protocol:s,begin:i?,length:i?", - .params = "[-p] protocol [begin] [length]", + .args_type = "paging:-p,filename:F,begin:i?,length:i?", + .params = "[-p] filename [begin] [length]", .help = "dump guest memory to file" "\n\t\t\t begin(optional): the starting physical address" "\n\t\t\t length(optional): the memory size, in bytes", - .user_print = monitor_user_noop, .mhandler.cmd = hmp_dump_guest_memory, }, @@ -929,8 +928,7 @@ STEXI @findex dump-guest-memory Dump guest memory to @var{protocol}. The file can be processed with crash or gdb. - protocol: destination file(started with "file:") or destination file - descriptor (started with "fd:") + filename: dump file name paging: do paging to get guest's memory mapping begin: the starting physical address. It's optional, and should be specified with length together. diff --git a/hmp.c b/hmp.c index ba6fbd3dcf..2de31401e6 100644 --- a/hmp.c +++ b/hmp.c @@ -1042,11 +1042,12 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict) { Error *errp = NULL; int paging = qdict_get_try_bool(qdict, "paging", 0); - const char *file = qdict_get_str(qdict, "protocol"); + const char *file = qdict_get_str(qdict, "filename"); bool has_begin = qdict_haskey(qdict, "begin"); bool has_length = qdict_haskey(qdict, "length"); int64_t begin = 0; int64_t length = 0; + char *prot; if (has_begin) { begin = qdict_get_int(qdict, "begin"); @@ -1055,9 +1056,12 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict) length = qdict_get_int(qdict, "length"); } - qmp_dump_guest_memory(paging, file, has_begin, begin, has_length, length, + prot = g_strconcat("file:", file, NULL); + + qmp_dump_guest_memory(paging, prot, has_begin, begin, has_length, length, &errp); hmp_handle_error(mon, &errp); + g_free(prot); } void hmp_netdev_add(Monitor *mon, const QDict *qdict) From 05a3543dbddd03d6be723be4074e2e661b00b851 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 20 Sep 2012 13:44:28 -0300 Subject: [PATCH 0614/2270] input: qmp_send_key(): simplify The current code duplicates the QKeyCodeList keys in order to store the key values for release_keys() late run. This is a bit complicated though, as we have to care about correct ordering and then release_keys() will have to index key_defs[] over again. Switch to an array of integers, which is dynamically allocated and stores the already converted key value. This simplifies the current code and the next commit. Signed-off-by: Luiz Capitulino Reviewed-by: Eric Blake Reviewed-by: Markus Armbruster --- input.c | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/input.c b/input.c index c4b0619a74..32c6057485 100644 --- a/input.c +++ b/input.c @@ -224,30 +224,31 @@ int index_from_keycode(int code) return i; } -static QKeyCodeList *keycodes; +static int *keycodes; +static int keycodes_size; static QEMUTimer *key_timer; static void release_keys(void *opaque) { - int keycode; - QKeyCodeList *p; + int i; - for (p = keycodes; p != NULL; p = p->next) { - keycode = key_defs[p->value]; - if (keycode & 0x80) { + for (i = 0; i < keycodes_size; i++) { + if (keycodes[i] & 0x80) { kbd_put_keycode(0xe0); } - kbd_put_keycode(keycode | 0x80); + kbd_put_keycode(keycodes[i]| 0x80); } - qapi_free_QKeyCodeList(keycodes); + + g_free(keycodes); keycodes = NULL; + keycodes_size = 0; } void qmp_send_key(QKeyCodeList *keys, bool has_hold_time, int64_t hold_time, Error **errp) { int keycode; - QKeyCodeList *p, *keylist, *head = NULL, *tmp = NULL; + QKeyCodeList *p; if (!key_timer) { key_timer = qemu_new_timer_ns(vm_clock, release_keys, NULL); @@ -257,31 +258,22 @@ void qmp_send_key(QKeyCodeList *keys, bool has_hold_time, int64_t hold_time, qemu_del_timer(key_timer); release_keys(NULL); } + if (!has_hold_time) { hold_time = 100; } for (p = keys; p != NULL; p = p->next) { - keylist = g_malloc0(sizeof(*keylist)); - keylist->value = p->value; - keylist->next = NULL; - - if (!head) { - head = keylist; - } - if (tmp) { - tmp->next = keylist; - } - tmp = keylist; - /* key down events */ keycode = key_defs[p->value]; if (keycode & 0x80) { kbd_put_keycode(0xe0); } kbd_put_keycode(keycode & 0x7f); + + keycodes = g_realloc(keycodes, sizeof(int) * (keycodes_size + 1)); + keycodes[keycodes_size++] = keycode; } - keycodes = head; /* delayed key up events */ qemu_mod_timer(key_timer, qemu_get_clock_ns(vm_clock) + From 9f32897768064841fe9a99145c9d15ab6667ffed Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 20 Sep 2012 14:19:47 -0300 Subject: [PATCH 0615/2270] qmp: qmp_send_key(): accept key codes in hex Before the qapi conversion, the sendkey command could be used to send key codes in hex directly to the guest. In HMP, this would be like: (qemu) sendkey 0xdc However, the qapi conversion broke this, as it only supports sending QKeyCode values to the guest. That's a regression. This commit fixes the problem by adding hex value support down the QMP interface, qmp_send_key(). In more detail, this commit: 1. Adds the KeyValue union. This can represent an hex value or a QKeyCode value 2. *Changes* the QMP send-key command to take an KeyValue argument instead of a QKeyCode one 3. Adapt hmp_send_key() to the QMP interface changes Item 2 is an incompatible change, but as we're in development phase (and this command has been merged a few weeks ago) this shouldn't be a problem. Finally, it's not possible to split this commit without breaking the build. Reported-by: Avi Kivity Signed-off-by: Luiz Capitulino Reviewed-by: Eric Blake Reviewed-by: Markus Armbruster --- hmp.c | 43 +++++++++++++++++++++++++++++-------------- input.c | 33 +++++++++++++++++++++++++++------ qapi-schema.json | 20 +++++++++++++++++--- 3 files changed, 73 insertions(+), 23 deletions(-) diff --git a/hmp.c b/hmp.c index 2de31401e6..3306bcdbb4 100644 --- a/hmp.c +++ b/hmp.c @@ -1113,13 +1113,13 @@ void hmp_closefd(Monitor *mon, const QDict *qdict) void hmp_send_key(Monitor *mon, const QDict *qdict) { const char *keys = qdict_get_str(qdict, "keys"); - QKeyCodeList *keylist, *head = NULL, *tmp = NULL; + KeyValueList *keylist, *head = NULL, *tmp = NULL; int has_hold_time = qdict_haskey(qdict, "hold-time"); int hold_time = qdict_get_try_int(qdict, "hold-time", -1); Error *err = NULL; char keyname_buf[16]; char *separator; - int keyname_len, idx; + int keyname_len; while (1) { separator = strchr(keys, '-'); @@ -1133,15 +1133,8 @@ void hmp_send_key(Monitor *mon, const QDict *qdict) } keyname_buf[keyname_len] = 0; - idx = index_from_key(keyname_buf); - if (idx == Q_KEY_CODE_MAX) { - monitor_printf(mon, "invalid parameter: %s\n", keyname_buf); - break; - } - keylist = g_malloc0(sizeof(*keylist)); - keylist->value = idx; - keylist->next = NULL; + keylist->value = g_malloc0(sizeof(*keylist->value)); if (!head) { head = keylist; @@ -1151,17 +1144,39 @@ void hmp_send_key(Monitor *mon, const QDict *qdict) } tmp = keylist; + if (strstart(keyname_buf, "0x", NULL)) { + char *endp; + int value = strtoul(keyname_buf, &endp, 0); + if (*endp != '\0') { + goto err_out; + } + keylist->value->kind = KEY_VALUE_KIND_NUMBER; + keylist->value->number = value; + } else { + int idx = index_from_key(keyname_buf); + if (idx == Q_KEY_CODE_MAX) { + goto err_out; + } + keylist->value->kind = KEY_VALUE_KIND_QCODE; + keylist->value->qcode = idx; + } + if (!separator) { break; } keys = separator + 1; } - if (idx != Q_KEY_CODE_MAX) { - qmp_send_key(head, has_hold_time, hold_time, &err); - } + qmp_send_key(head, has_hold_time, hold_time, &err); hmp_handle_error(mon, &err); - qapi_free_QKeyCodeList(head); + +out: + qapi_free_KeyValueList(head); + return; + +err_out: + monitor_printf(mon, "invalid parameter: %s\n", keyname_buf); + goto out; } void hmp_screen_dump(Monitor *mon, const QDict *qdict) diff --git a/input.c b/input.c index 32c6057485..76ade64d04 100644 --- a/input.c +++ b/input.c @@ -228,6 +228,23 @@ static int *keycodes; static int keycodes_size; static QEMUTimer *key_timer; +static int keycode_from_keyvalue(const KeyValue *value) +{ + if (value->kind == KEY_VALUE_KIND_QCODE) { + return key_defs[value->qcode]; + } else { + assert(value->kind == KEY_VALUE_KIND_NUMBER); + return value->number; + } +} + +static void free_keycodes(void) +{ + g_free(keycodes); + keycodes = NULL; + keycodes_size = 0; +} + static void release_keys(void *opaque) { int i; @@ -239,16 +256,14 @@ static void release_keys(void *opaque) kbd_put_keycode(keycodes[i]| 0x80); } - g_free(keycodes); - keycodes = NULL; - keycodes_size = 0; + free_keycodes(); } -void qmp_send_key(QKeyCodeList *keys, bool has_hold_time, int64_t hold_time, +void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time, Error **errp) { int keycode; - QKeyCodeList *p; + KeyValueList *p; if (!key_timer) { key_timer = qemu_new_timer_ns(vm_clock, release_keys, NULL); @@ -265,7 +280,13 @@ void qmp_send_key(QKeyCodeList *keys, bool has_hold_time, int64_t hold_time, for (p = keys; p != NULL; p = p->next) { /* key down events */ - keycode = key_defs[p->value]; + keycode = keycode_from_keyvalue(p->value); + if (keycode < 0x01 || keycode > 0xff) { + error_setg(errp, "invalid hex keycode 0x%x\n", keycode); + free_keycodes(); + return; + } + if (keycode & 0x80) { kbd_put_keycode(0xe0); } diff --git a/qapi-schema.json b/qapi-schema.json index c6a676783c..28d8815df8 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2620,13 +2620,27 @@ 'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut', 'lf', 'help', 'meta_l', 'meta_r', 'compose' ] } +## +# @KeyValue +# +# Represents a keyboard key. +# +# Since: 1.3.0 +## +{ 'union': 'KeyValue', + 'data': { + 'number': 'int', + 'qcode': 'QKeyCode' } } + ## # @send-key: # # Send keys to guest. # -# @keys: key sequence. 'keys' is the name of the key. Use a JSON array to -# press several keys simultaneously. +# @keys: An array of @KeyValue elements. All @KeyValues in this array are +# simultaneously sent to the guest. A @KeyValue.number value is sent +# directly to the guest, while @KeyValue.qcode must be a valid +# @QKeyCode value # # @hold-time: #optional time to delay key up events, milliseconds. Defaults # to 100 @@ -2638,7 +2652,7 @@ # ## { 'command': 'send-key', - 'data': { 'keys': ['QKeyCode'], '*hold-time': 'int' } } + 'data': { 'keys': ['KeyValue'], '*hold-time': 'int' } } ## # @screendump: From 9d537c9019e6a05713b44900c78447a0cfb06567 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 20 Sep 2012 14:47:02 -0300 Subject: [PATCH 0616/2270] input: index_from_key(): drop unused code The hex key conversion is unused since last commit. Signed-off-by: Luiz Capitulino Reviewed-by: Eric Blake Reviewed-by: Markus Armbruster --- input.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/input.c b/input.c index 76ade64d04..25d3973e21 100644 --- a/input.c +++ b/input.c @@ -186,8 +186,7 @@ static const int key_defs[] = { int index_from_key(const char *key) { - int i, keycode; - char *endp; + int i; for (i = 0; QKeyCode_lookup[i] != NULL; i++) { if (!strcmp(key, QKeyCode_lookup[i])) { @@ -195,17 +194,6 @@ int index_from_key(const char *key) } } - if (strstart(key, "0x", NULL)) { - keycode = strtoul(key, &endp, 0); - if (*endp == '\0' && keycode >= 0x01 && keycode <= 0xff) { - for (i = 0; i < Q_KEY_CODE_MAX; i++) { - if (keycode == key_defs[i]) { - break; - } - } - } - } - /* Return Q_KEY_CODE_MAX if the key is invalid */ return i; } From 8bde9b6f8892c15e46e1f37a37ac038313be4d58 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 26 Sep 2012 16:34:29 +0200 Subject: [PATCH 0617/2270] block: live snapshot documentation tweaks Signed-off-by: Paolo Bonzini Signed-off-by: Luiz Capitulino --- qapi-schema.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qapi-schema.json b/qapi-schema.json index 28d8815df8..f4c21855cf 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1399,7 +1399,7 @@ # @format: #optional the format of the snapshot image, default is 'qcow2'. # # @mode: #optional whether and how QEMU should create a new image, default is -# 'absolute-paths'. +# 'absolute-paths'. ## { 'type': 'BlockdevSnapshot', 'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str', @@ -1453,7 +1453,7 @@ # @format: #optional the format of the snapshot image, default is 'qcow2'. # # @mode: #optional whether and how QEMU should create a new image, default is -# 'absolute-paths'. +# 'absolute-paths'. # # Returns: nothing on success # If @device is not a valid block device, DeviceNotFound From 6673f47da21718d07346b0f3725f0dbf0d6d8e45 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Tue, 18 Sep 2012 22:43:38 +0200 Subject: [PATCH 0618/2270] tci: Fix for AREG0 free mode Support for helper functions with 5 arguments was missing in the code generator and in the interpreter. There is no need to pass the constant TCG_AREG0 from the code generator to the interpreter. Remove that code for the INDEX_op_qemu_st* opcodes. Signed-off-by: Stefan Weil Signed-off-by: Aurelien Jarno --- tcg/tci/tcg-target.c | 10 +++++----- tci.c | 13 +++++++++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c index 3f4a24bb8b..d272a906e8 100644 --- a/tcg/tci/tcg-target.c +++ b/tcg/tci/tcg-target.c @@ -300,7 +300,7 @@ static const int tcg_target_reg_alloc_order[] = { #endif }; -#if MAX_OPC_PARAM_IARGS != 4 +#if MAX_OPC_PARAM_IARGS != 5 # error Fix needed, number of supported input arguments changed! #endif @@ -309,16 +309,18 @@ static const int tcg_target_call_iarg_regs[] = { TCG_REG_R1, TCG_REG_R2, TCG_REG_R3, -#if TCG_TARGET_REG_BITS == 32 - /* 32 bit hosts need 2 * MAX_OPC_PARAM_IARGS registers. */ #if 0 /* used for TCG_REG_CALL_STACK */ TCG_REG_R4, #endif TCG_REG_R5, +#if TCG_TARGET_REG_BITS == 32 + /* 32 bit hosts need 2 * MAX_OPC_PARAM_IARGS registers. */ TCG_REG_R6, TCG_REG_R7, #if TCG_TARGET_NB_REGS >= 16 TCG_REG_R8, + TCG_REG_R9, + TCG_REG_R10, #else # error Too few input registers available #endif @@ -798,7 +800,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_qemu_st8: case INDEX_op_qemu_st16: case INDEX_op_qemu_st32: - tcg_out_r(s, TCG_AREG0); tcg_out_r(s, *args++); tcg_out_r(s, *args++); #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS @@ -809,7 +810,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, #endif break; case INDEX_op_qemu_st64: - tcg_out_r(s, TCG_AREG0); tcg_out_r(s, *args++); #if TCG_TARGET_REG_BITS == 32 tcg_out_r(s, *args++); diff --git a/tci.c b/tci.c index ce8a988147..a4f7b78418 100644 --- a/tci.c +++ b/tci.c @@ -36,17 +36,19 @@ tcg_abort(); \ } while (0) -#if MAX_OPC_PARAM_IARGS != 4 +#if MAX_OPC_PARAM_IARGS != 5 # error Fix needed, number of supported input arguments changed! #endif #if TCG_TARGET_REG_BITS == 32 typedef uint64_t (*helper_function)(tcg_target_ulong, tcg_target_ulong, + tcg_target_ulong, tcg_target_ulong, tcg_target_ulong, tcg_target_ulong, tcg_target_ulong, tcg_target_ulong, tcg_target_ulong, tcg_target_ulong); #else typedef uint64_t (*helper_function)(tcg_target_ulong, tcg_target_ulong, - tcg_target_ulong, tcg_target_ulong); + tcg_target_ulong, tcg_target_ulong, + tcg_target_ulong); #endif /* TCI can optionally use a global register variable for env. */ @@ -489,14 +491,17 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr) tci_read_reg(TCG_REG_R5), tci_read_reg(TCG_REG_R6), tci_read_reg(TCG_REG_R7), - tci_read_reg(TCG_REG_R8)); + tci_read_reg(TCG_REG_R8), + tci_read_reg(TCG_REG_R9), + tci_read_reg(TCG_REG_R10)); tci_write_reg(TCG_REG_R0, tmp64); tci_write_reg(TCG_REG_R1, tmp64 >> 32); #else tmp64 = ((helper_function)t0)(tci_read_reg(TCG_REG_R0), tci_read_reg(TCG_REG_R1), tci_read_reg(TCG_REG_R2), - tci_read_reg(TCG_REG_R3)); + tci_read_reg(TCG_REG_R3), + tci_read_reg(TCG_REG_R5)); tci_write_reg(TCG_REG_R0, tmp64); #endif break; From fdefe51c288866b98e62663fa18c8af1d66bf5f6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 24 Sep 2012 14:55:47 -0700 Subject: [PATCH 0619/2270] Emit debug_insn for CPU_LOG_TB_OP_OPT as well. For all targets that currently call tcg_gen_debug_insn_start, add CPU_LOG_TB_OP_OPT to the condition that gates it. This is useful for comparing optimization dumps, when the pre-optimization dump is merely noise. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-alpha/translate.c | 2 +- target-arm/translate.c | 2 +- target-cris/translate.c | 3 ++- target-i386/translate.c | 3 ++- target-lm32/translate.c | 2 +- target-microblaze/translate.c | 3 ++- target-mips/translate.c | 3 ++- target-openrisc/translate.c | 2 +- target-ppc/translate.c | 3 ++- target-sh4/translate.c | 2 +- target-sparc/translate.c | 3 ++- target-xtensa/translate.c | 2 +- 12 files changed, 18 insertions(+), 12 deletions(-) diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 3f9aee12d4..f707d8deb9 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -3421,7 +3421,7 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env, insn = cpu_ldl_code(env, ctx.pc); num_insns++; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(ctx.pc); } diff --git a/target-arm/translate.c b/target-arm/translate.c index f4b447a49a..5fded491ec 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -9816,7 +9816,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env, if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) gen_io_start(); - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(dc->pc); } diff --git a/target-cris/translate.c b/target-cris/translate.c index 19144b5e29..755de659df 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -3074,8 +3074,9 @@ static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc) int insn_len = 2; int i; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(dc->pc); + } /* Load a halfword onto the instruction register. */ dc->ir = cris_fetch(env, dc, dc->pc, 2, 0); diff --git a/target-i386/translate.c b/target-i386/translate.c index eb0cabcf19..323869d874 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -4202,8 +4202,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) target_ulong next_eip, tval; int rex_w, rex_r; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(pc_start); + } s->pc = pc_start; prefixes = 0; aflag = s->code32; diff --git a/target-lm32/translate.c b/target-lm32/translate.c index 5f6dcbac86..77c2866611 100644 --- a/target-lm32/translate.c +++ b/target-lm32/translate.c @@ -942,7 +942,7 @@ static const DecoderInfo decinfo[] = { static inline void decode(DisasContext *dc, uint32_t ir) { - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(dc->pc); } diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index 9c7d77f57a..7d864b1dac 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -1664,8 +1664,9 @@ static inline void decode(DisasContext *dc, uint32_t ir) { int i; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(dc->pc); + } dc->ir = ir; LOG_DIS("%8.8x\t", dc->ir); diff --git a/target-mips/translate.c b/target-mips/translate.c index fa79d4945b..454e5cc818 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -12124,8 +12124,9 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) gen_set_label(l1); } - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(ctx->pc); + } op = MASK_OP_MAJOR(ctx->opcode); rs = (ctx->opcode >> 21) & 0x1f; diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index 325ba09cb5..e2cad3ad42 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -1715,7 +1715,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu, gen_opc_icount[k] = num_insns; } - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(dc->pc); } diff --git a/target-ppc/translate.c b/target-ppc/translate.c index ac915ccade..1042268ecf 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -9690,8 +9690,9 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env, LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n", ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode), opc3(ctx.opcode), little_endian ? "little" : "big"); - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(ctx.nip); + } ctx.nip += 4; table = env->opcodes; num_insns++; diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 0fa83cab99..9d955eb204 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -1924,7 +1924,7 @@ static void decode_opc(DisasContext * ctx) { uint32_t old_flags = ctx->flags; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(ctx->pc); } diff --git a/target-sparc/translate.c b/target-sparc/translate.c index b95f91cd3b..e5ebedfa2c 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2394,8 +2394,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64; target_long simm; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(dc->pc); + } opc = GET_FIELD(insn, 0, 1); diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index ba3ffcb7a4..b9acd706ce 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -2923,7 +2923,7 @@ static void gen_intermediate_code_internal( gen_opc_icount[lj] = insn_count; } - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(dc.pc); } From fa547e617c2f499903dccb8f1b9031bfe724e11e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 24 Sep 2012 14:55:48 -0700 Subject: [PATCH 0620/2270] target-m68k: Call tcg_gen_debug_insn_start Cc: Paul Brook Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-m68k/translate.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index fb707f21bc..451ef7410f 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2953,6 +2953,10 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s) { uint16_t insn; + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { + tcg_gen_debug_insn_start(s->pc); + } + insn = cpu_lduw_code(env, s->pc); s->pc += 2; From 7193b5f6f52d633531406771b9370d7b591cef88 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 24 Sep 2012 14:55:49 -0700 Subject: [PATCH 0621/2270] target-s390x: Call tcg_gen_debug_insn_start Cc: Alexander Graf Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-s390x/translate.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 3214783aaa..6fa76a00f4 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -5173,10 +5173,11 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env, if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } -#if defined(S390X_DEBUG_DISAS_VERBOSE) - LOG_DISAS("pc " TARGET_FMT_lx "\n", - dc.pc); -#endif + + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { + tcg_gen_debug_insn_start(dc.pc); + } + disas_s390_insn(env, &dc); num_insns++; From daa47c34a893917d712923b107d33f7b89a3a53b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 24 Sep 2012 14:55:50 -0700 Subject: [PATCH 0622/2270] target-unicore32: Call tcg_gen_debug_insn_start Acked-by: Guan Xuetao Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-unicore32/translate.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index b786a6b890..36f4f2f966 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -1861,6 +1861,10 @@ static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s) { unsigned int insn; + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { + tcg_gen_debug_insn_start(s->pc); + } + insn = cpu_ldl_code(env, s->pc); s->pc += 4; From 0d404541b24b332f6a822139c6bd889b7e319762 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 24 Sep 2012 14:55:51 -0700 Subject: [PATCH 0623/2270] target-s390x: Use CPU_LOG_INT Three places in the interrupt code did we not honor the mask. Reviewed-by: Alexander Graf Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-s390x/helper.c | 7 ++++--- target-s390x/misc_helper.c | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/target-s390x/helper.c b/target-s390x/helper.c index a5741ecde1..22256b057d 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -511,7 +511,8 @@ static void do_program_interrupt(CPUS390XState *env) break; } - qemu_log("%s: code=0x%x ilc=%d\n", __func__, env->int_pgm_code, ilc); + qemu_log_mask(CPU_LOG_INT, "%s: code=0x%x ilc=%d\n", + __func__, env->int_pgm_code, ilc); lowcore = cpu_physical_memory_map(env->psa, &len, 1); @@ -575,8 +576,8 @@ static void do_ext_interrupt(CPUS390XState *env) void do_interrupt(CPUS390XState *env) { - qemu_log("%s: %d at pc=%" PRIx64 "\n", __func__, env->exception_index, - env->psw.addr); + qemu_log_mask(CPU_LOG_INT, "%s: %d at pc=%" PRIx64 "\n", + __func__, env->exception_index, env->psw.addr); s390_add_running_cpu(env); /* handle external interrupts */ diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index 2938ac9c76..e9b3caed49 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -53,7 +53,8 @@ void HELPER(exception)(CPUS390XState *env, uint32_t excp) #ifndef CONFIG_USER_ONLY void program_interrupt(CPUS390XState *env, uint32_t code, int ilc) { - qemu_log("program interrupt at %#" PRIx64 "\n", env->psw.addr); + qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n", + env->psw.addr); if (kvm_enabled()) { #ifdef CONFIG_KVM From 87a5395bdd75c22e8c9b92c5655810762a7fd5bf Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 24 Sep 2012 14:55:52 -0700 Subject: [PATCH 0624/2270] target-s390x: Avoid double CPU_LOG_TB_CPU This is already handled generically in cpu_exec. Reviewed-by: Alexander Graf Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-s390x/translate.c | 1 - 1 file changed, 1 deletion(-) diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 6fa76a00f4..4cc92255a3 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -5220,7 +5220,6 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env, tb->icount = num_insns; } #if defined(S390X_DEBUG_DISAS) - log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0); if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { qemu_log("IN: %s\n", lookup_symbol(pc_start)); log_target_disas(pc_start, dc.pc - pc_start, 1); From d885bdd481fc1c11d3158cc1c4c68bffdb2c26fe Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 24 Sep 2012 14:55:53 -0700 Subject: [PATCH 0625/2270] target-s390x: Tidy cpu_dump_state The blank lines inside the single dump make it difficult for the eye to pick out the block. Worse, with interior newlines, but no blank line following, the PSW line appears to belong to the next dump block. Reviewed-by: Alexander Graf Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-s390x/translate.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 4cc92255a3..db464cc073 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -79,6 +79,14 @@ void cpu_dump_state(CPUS390XState *env, FILE *f, fprintf_function cpu_fprintf, { int i; + if (env->cc_op > 3) { + cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %15s\n", + env->psw.mask, env->psw.addr, cc_name(env->cc_op)); + } else { + cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %02x\n", + env->psw.mask, env->psw.addr, env->cc_op); + } + for (i = 0; i < 16; i++) { cpu_fprintf(f, "R%02d=%016" PRIx64, i, env->regs[i]); if ((i % 4) == 3) { @@ -97,8 +105,6 @@ void cpu_dump_state(CPUS390XState *env, FILE *f, fprintf_function cpu_fprintf, } } - cpu_fprintf(f, "\n"); - #ifndef CONFIG_USER_ONLY for (i = 0; i < 16; i++) { cpu_fprintf(f, "C%02d=%016" PRIx64, i, env->cregs[i]); @@ -110,22 +116,14 @@ void cpu_dump_state(CPUS390XState *env, FILE *f, fprintf_function cpu_fprintf, } #endif - cpu_fprintf(f, "\n"); - - if (env->cc_op > 3) { - cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %15s\n", - env->psw.mask, env->psw.addr, cc_name(env->cc_op)); - } else { - cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %02x\n", - env->psw.mask, env->psw.addr, env->cc_op); - } - #ifdef DEBUG_INLINE_BRANCHES for (i = 0; i < CC_OP_MAX; i++) { cpu_fprintf(f, " %15s = %10ld\t%10ld\n", cc_name(i), inline_branch_miss[i], inline_branch_hit[i]); } #endif + + cpu_fprintf(f, "\n"); } static TCGv_i64 psw_addr; From 0cea71a207508c2b8f563b2644ac46009832c8f4 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 24 Sep 2012 15:09:30 +0200 Subject: [PATCH 0626/2270] virtio: don't mark unaccessed memory as dirty offset of accessed buffer is calculated using iov_length, so it can exceed accessed len. If that happens math in len - offset wraps around, and size becomes wrong. As real value is 0, so this is harmless but unnecessary. Signed-off-by: Michael S. Tsirkin --- hw/virtio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/virtio.c b/hw/virtio.c index 209c763751..b5764bb8f7 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -241,7 +241,7 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, elem->in_sg[i].iov_len, 1, size); - offset += elem->in_sg[i].iov_len; + offset += size; } for (i = 0; i < elem->out_num; i++) From 40bad8f3deba15e2074ff34cfe923c12916b1cc5 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 24 Sep 2012 15:15:43 +0200 Subject: [PATCH 0627/2270] virtio-net: fix used len for tx There is no out sg for TX, so used buf length for tx should always be 0. Signed-off-by: Michael S. Tsirkin --- hw/virtio-net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 6490743290..247d7bef56 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -690,7 +690,7 @@ static void virtio_net_tx_complete(NetClientState *nc, ssize_t len) { VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque; - virtqueue_push(n->tx_vq, &n->async_tx.elem, n->async_tx.len); + virtqueue_push(n->tx_vq, &n->async_tx.elem, 0); virtio_notify(&n->vdev, n->tx_vq); n->async_tx.elem.out_num = n->async_tx.len = 0; @@ -754,7 +754,7 @@ static int32_t virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq) len += ret; - virtqueue_push(vq, &elem, len); + virtqueue_push(vq, &elem, 0); virtio_notify(&n->vdev, vq); if (++num_packets >= n->tx_burst) { From 844b5cea8ea6cbe964670a26d1b34037067569df Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 24 Sep 2012 12:50:32 +0200 Subject: [PATCH 0628/2270] iov: add const annotation iov_from_buf does not change iov, make it const. Signed-off-by: Michael S. Tsirkin --- iov.c | 2 +- iov.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/iov.c b/iov.c index 60705c73ab..c6a66f0afe 100644 --- a/iov.c +++ b/iov.c @@ -26,7 +26,7 @@ # include #endif -size_t iov_from_buf(struct iovec *iov, unsigned int iov_cnt, +size_t iov_from_buf(const struct iovec *iov, unsigned int iov_cnt, size_t offset, const void *buf, size_t bytes) { size_t done; diff --git a/iov.h b/iov.h index 381f37a546..a73569f94e 100644 --- a/iov.h +++ b/iov.h @@ -36,7 +36,7 @@ size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt); * such "large" value is -1 (sinice size_t is unsigned), * so specifying `-1' as `bytes' means 'up to the end of iovec'. */ -size_t iov_from_buf(struct iovec *iov, unsigned int iov_cnt, +size_t iov_from_buf(const struct iovec *iov, unsigned int iov_cnt, size_t offset, const void *buf, size_t bytes); size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt, size_t offset, void *buf, size_t bytes); From 385ce95d9d060f20870402c8b2b503d0b6ab8af0 Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Tue, 25 Sep 2012 00:05:14 +0530 Subject: [PATCH 0629/2270] virtio: use unsigned int for counting bytes in vq The virtqueue_avail_bytes() function counts bytes in an int. Use an unsigned int instead. Signed-off-by: Amit Shah Signed-off-by: Michael S. Tsirkin --- hw/virtio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/virtio.c b/hw/virtio.c index b5764bb8f7..cfad363613 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -338,7 +338,7 @@ static unsigned virtqueue_next_desc(target_phys_addr_t desc_pa, int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) { unsigned int idx; - int total_bufs, in_total, out_total; + unsigned int total_bufs, in_total, out_total; idx = vq->last_avail_idx; From 0d8d7690850eb0cf2b2b60933cf47669a6b6f18f Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Tue, 25 Sep 2012 00:05:15 +0530 Subject: [PATCH 0630/2270] virtio: Introduce virtqueue_get_avail_bytes() The current virtqueue_avail_bytes() is oddly named, and checks if a particular number of bytes are available in a vq. A better API is to fetch the number of bytes available in the vq, and let the caller do what's interesting with the numbers. Introduce virtqueue_get_avail_bytes(), which returns the number of bytes for buffers marked for both, in as well as out. virtqueue_avail_bytes() is made a wrapper over this new function. Signed-off-by: Amit Shah Signed-off-by: Michael S. Tsirkin --- hw/virtio.c | 28 +++++++++++++++++++++------- hw/virtio.h | 5 ++++- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/hw/virtio.c b/hw/virtio.c index cfad363613..6821092df2 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -335,7 +335,8 @@ static unsigned virtqueue_next_desc(target_phys_addr_t desc_pa, return next; } -int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) +void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes, + unsigned int *out_bytes) { unsigned int idx; unsigned int total_bufs, in_total, out_total; @@ -380,13 +381,9 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) } if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) { - if (in_bytes > 0 && - (in_total += vring_desc_len(desc_pa, i)) >= in_bytes) - return 1; + in_total += vring_desc_len(desc_pa, i); } else { - if (out_bytes > 0 && - (out_total += vring_desc_len(desc_pa, i)) >= out_bytes) - return 1; + out_total += vring_desc_len(desc_pa, i); } } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max); @@ -395,7 +392,24 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) else total_bufs++; } + if (in_bytes) { + *in_bytes = in_total; + } + if (out_bytes) { + *out_bytes = out_total; + } +} +int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes, + unsigned int out_bytes) +{ + unsigned int in_total, out_total; + + virtqueue_get_avail_bytes(vq, &in_total, &out_total); + if ((in_bytes && in_bytes < in_total) + || (out_bytes && out_bytes < out_total)) { + return 1; + } return 0; } diff --git a/hw/virtio.h b/hw/virtio.h index 7a4f564529..80de3757e3 100644 --- a/hw/virtio.h +++ b/hw/virtio.h @@ -147,7 +147,10 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, void virtqueue_map_sg(struct iovec *sg, target_phys_addr_t *addr, size_t num_sg, int is_write); int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem); -int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes); +int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes, + unsigned int out_bytes); +void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes, + unsigned int *out_bytes); void virtio_notify(VirtIODevice *vdev, VirtQueue *vq); From ad3005ad8c70a69705149d3ce6d1e51fb76edb15 Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Tue, 25 Sep 2012 00:05:16 +0530 Subject: [PATCH 0631/2270] virtio-serial-bus: let chardev know the exact number of bytes requested Using the virtqueue_avail_bytes() function had an unnecessarily crippling effect on the number of bytes needed by the guest as reported to the chardev layer in the can_read() callback. Using the new virtqueue_get_avail_bytes() function will let us advertise the exact number of bytes we can send to the guest. Signed-off-by: Amit Shah Signed-off-by: Michael S. Tsirkin --- hw/virtio-serial-bus.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index 82073f5dc2..d20bd8bf75 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -287,6 +287,7 @@ ssize_t virtio_serial_write(VirtIOSerialPort *port, const uint8_t *buf, size_t virtio_serial_guest_ready(VirtIOSerialPort *port) { VirtQueue *vq = port->ivq; + unsigned int bytes; if (!virtio_queue_ready(vq) || !(port->vser->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK) || @@ -296,14 +297,8 @@ size_t virtio_serial_guest_ready(VirtIOSerialPort *port) if (use_multiport(port->vser) && !port->guest_connected) { return 0; } - - if (virtqueue_avail_bytes(vq, 4096, 0)) { - return 4096; - } - if (virtqueue_avail_bytes(vq, 1, 0)) { - return 1; - } - return 0; + virtqueue_get_avail_bytes(vq, &bytes, NULL); + return bytes; } static void flush_queued_data_bh(void *opaque) From 946d58be1533bf843b499df12e1d9f97b28245c8 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 25 Sep 2012 15:47:36 +0200 Subject: [PATCH 0632/2270] block-migration: Flush requests in blk_mig_cleanup When cancelling block migration, all in-flight requests of the block migration must be completed before the data can be freed. This was visible as failing assertions and segfaults. Reported-by: Peter Lieven Signed-off-by: Kevin Wolf --- block-migration.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/block-migration.c b/block-migration.c index 7def8ab197..ed933017f9 100644 --- a/block-migration.c +++ b/block-migration.c @@ -519,6 +519,8 @@ static void blk_mig_cleanup(void) BlkMigDevState *bmds; BlkMigBlock *blk; + bdrv_drain_all(); + set_dirty_tracking(0); while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) { From 870f5681c9dbafc738082b1fd48e0cc013bf43c7 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Tue, 25 Sep 2012 12:29:39 -0400 Subject: [PATCH 0633/2270] block: after creating a live snapshot, make old image read-only Currently, after a live snapshot of a drive, the image that has been 'demoted' to be below the new active layer remains r/w. This patch reopens it read-only. Note that we do not check for error on the reopen(), because we will not abort the snapshots if the reopen fails. This patch depends on the bdrv_reopen() series. Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf --- blockdev.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/blockdev.c b/blockdev.c index e5d450f0bb..0267fa30bf 100644 --- a/blockdev.c +++ b/blockdev.c @@ -805,6 +805,11 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp) 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); } /* success */ From 00f78533326c5ba2e62fafada16655aa558a5520 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 24 Sep 2012 14:40:56 +0530 Subject: [PATCH 0634/2270] aio: Fix qemu_aio_wait() to maintain correct walking_handlers count Fix qemu_aio_wait() to ensure that registered aio handlers don't get deleted when they are still active. This is ensured by maintaning the right count of walking_handlers. Signed-off-by: Paolo Bonzini Signed-off-by: Bharata B Rao Signed-off-by: Kevin Wolf --- aio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/aio.c b/aio.c index 0a9eb10c76..99b8b72263 100644 --- a/aio.c +++ b/aio.c @@ -119,7 +119,7 @@ bool qemu_aio_wait(void) return true; } - walking_handlers = 1; + walking_handlers++; FD_ZERO(&rdfds); FD_ZERO(&wrfds); @@ -147,7 +147,7 @@ bool qemu_aio_wait(void) } } - walking_handlers = 0; + walking_handlers--; /* No AIO operations? Get us out of here */ if (!busy) { @@ -159,7 +159,7 @@ bool qemu_aio_wait(void) /* if we have any readable fds, dispatch event */ if (ret > 0) { - walking_handlers = 1; + walking_handlers++; /* we have to walk very carefully in case * qemu_aio_set_fd_handler is called while we're walking */ @@ -187,7 +187,7 @@ bool qemu_aio_wait(void) } } - walking_handlers = 0; + walking_handlers--; } return true; From ca0defb95c69f88a905d64adbe253e7bb8fde14a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 24 Sep 2012 14:42:02 +0530 Subject: [PATCH 0635/2270] qemu: URI parsing library Add a new URI parsing library to QEMU. The code has been borrowed from libxml2 and libvirt. Signed-off-by: Paolo Bonzini Signed-off-by: Bharata B Rao Signed-off-by: Kevin Wolf --- Makefile.objs | 2 +- uri.c | 2249 +++++++++++++++++++++++++++++++++++++++++++++++++ uri.h | 113 +++ 3 files changed, 2363 insertions(+), 1 deletion(-) create mode 100644 uri.c create mode 100644 uri.h diff --git a/Makefile.objs b/Makefile.objs index 4412757309..7c1c68206b 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -42,7 +42,7 @@ coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o # block-obj-y is code used by both qemu system emulation and qemu-img block-obj-y = cutils.o iov.o cache-utils.o qemu-option.o module.o async.o -block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-progress.o qemu-sockets.o +block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-progress.o qemu-sockets.o uri.o block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y) block-obj-$(CONFIG_POSIX) += posix-aio-compat.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o diff --git a/uri.c b/uri.c new file mode 100644 index 0000000000..dd922de339 --- /dev/null +++ b/uri.c @@ -0,0 +1,2249 @@ +/** + * uri.c: set of generic URI related routines + * + * Reference: RFCs 3986, 2732 and 2373 + * + * Copyright (C) 1998-2003 Daniel Veillard. All Rights Reserved. + * + * 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 + * DANIEL VEILLARD 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. + * + * Except as contained in this notice, the name of Daniel Veillard shall not + * be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from him. + * + * daniel@veillard.com + * + ** + * + * Copyright (C) 2007, 2009-2010 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Richard W.M. Jones + * + */ + +#include +#include +#include + +#include "uri.h" + +static void uri_clean(URI *uri); + +/* + * Old rule from 2396 used in legacy handling code + * alpha = lowalpha | upalpha + */ +#define IS_ALPHA(x) (IS_LOWALPHA(x) || IS_UPALPHA(x)) + + +/* + * lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | + * "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | + * "u" | "v" | "w" | "x" | "y" | "z" + */ + +#define IS_LOWALPHA(x) (((x) >= 'a') && ((x) <= 'z')) + +/* + * upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | + * "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | + * "U" | "V" | "W" | "X" | "Y" | "Z" + */ +#define IS_UPALPHA(x) (((x) >= 'A') && ((x) <= 'Z')) + +#ifdef IS_DIGIT +#undef IS_DIGIT +#endif +/* + * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" + */ +#define IS_DIGIT(x) (((x) >= '0') && ((x) <= '9')) + +/* + * alphanum = alpha | digit + */ + +#define IS_ALPHANUM(x) (IS_ALPHA(x) || IS_DIGIT(x)) + +/* + * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" + */ + +#define IS_MARK(x) (((x) == '-') || ((x) == '_') || ((x) == '.') || \ + ((x) == '!') || ((x) == '~') || ((x) == '*') || ((x) == '\'') || \ + ((x) == '(') || ((x) == ')')) + +/* + * unwise = "{" | "}" | "|" | "\" | "^" | "`" + */ + +#define IS_UNWISE(p) \ + (((*(p) == '{')) || ((*(p) == '}')) || ((*(p) == '|')) || \ + ((*(p) == '\\')) || ((*(p) == '^')) || ((*(p) == '[')) || \ + ((*(p) == ']')) || ((*(p) == '`'))) +/* + * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," | + * "[" | "]" + */ + +#define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') || \ + ((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') || \ + ((x) == '+') || ((x) == '$') || ((x) == ',') || ((x) == '[') || \ + ((x) == ']')) + +/* + * unreserved = alphanum | mark + */ + +#define IS_UNRESERVED(x) (IS_ALPHANUM(x) || IS_MARK(x)) + +/* + * Skip to next pointer char, handle escaped sequences + */ + +#define NEXT(p) ((*p == '%')? p += 3 : p++) + +/* + * Productions from the spec. + * + * authority = server | reg_name + * reg_name = 1*( unreserved | escaped | "$" | "," | + * ";" | ":" | "@" | "&" | "=" | "+" ) + * + * path = [ abs_path | opaque_part ] + */ + + +/************************************************************************ + * * + * RFC 3986 parser * + * * + ************************************************************************/ + +#define ISA_DIGIT(p) ((*(p) >= '0') && (*(p) <= '9')) +#define ISA_ALPHA(p) (((*(p) >= 'a') && (*(p) <= 'z')) || \ + ((*(p) >= 'A') && (*(p) <= 'Z'))) +#define ISA_HEXDIG(p) \ + (ISA_DIGIT(p) || ((*(p) >= 'a') && (*(p) <= 'f')) || \ + ((*(p) >= 'A') && (*(p) <= 'F'))) + +/* + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ +#define ISA_SUB_DELIM(p) \ + (((*(p) == '!')) || ((*(p) == '$')) || ((*(p) == '&')) || \ + ((*(p) == '(')) || ((*(p) == ')')) || ((*(p) == '*')) || \ + ((*(p) == '+')) || ((*(p) == ',')) || ((*(p) == ';')) || \ + ((*(p) == '=')) || ((*(p) == '\''))) + +/* + * gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" + */ +#define ISA_GEN_DELIM(p) \ + (((*(p) == ':')) || ((*(p) == '/')) || ((*(p) == '?')) || \ + ((*(p) == '#')) || ((*(p) == '[')) || ((*(p) == ']')) || \ + ((*(p) == '@'))) + +/* + * reserved = gen-delims / sub-delims + */ +#define ISA_RESERVED(p) (ISA_GEN_DELIM(p) || (ISA_SUB_DELIM(p))) + +/* + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + */ +#define ISA_UNRESERVED(p) \ + ((ISA_ALPHA(p)) || (ISA_DIGIT(p)) || ((*(p) == '-')) || \ + ((*(p) == '.')) || ((*(p) == '_')) || ((*(p) == '~'))) + +/* + * pct-encoded = "%" HEXDIG HEXDIG + */ +#define ISA_PCT_ENCODED(p) \ + ((*(p) == '%') && (ISA_HEXDIG(p + 1)) && (ISA_HEXDIG(p + 2))) + +/* + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + */ +#define ISA_PCHAR(p) \ + (ISA_UNRESERVED(p) || ISA_PCT_ENCODED(p) || ISA_SUB_DELIM(p) || \ + ((*(p) == ':')) || ((*(p) == '@'))) + +/** + * rfc3986_parse_scheme: + * @uri: pointer to an URI structure + * @str: pointer to the string to analyze + * + * Parse an URI scheme + * + * ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + * + * Returns 0 or the error code + */ +static int +rfc3986_parse_scheme(URI *uri, const char **str) { + const char *cur; + + if (str == NULL) + return(-1); + + cur = *str; + if (!ISA_ALPHA(cur)) + return(2); + cur++; + while (ISA_ALPHA(cur) || ISA_DIGIT(cur) || + (*cur == '+') || (*cur == '-') || (*cur == '.')) cur++; + if (uri != NULL) { + if (uri->scheme != NULL) g_free(uri->scheme); + uri->scheme = g_strndup(*str, cur - *str); + } + *str = cur; + return(0); +} + +/** + * rfc3986_parse_fragment: + * @uri: pointer to an URI structure + * @str: pointer to the string to analyze + * + * Parse the query part of an URI + * + * fragment = *( pchar / "/" / "?" ) + * NOTE: the strict syntax as defined by 3986 does not allow '[' and ']' + * in the fragment identifier but this is used very broadly for + * xpointer scheme selection, so we are allowing it here to not break + * for example all the DocBook processing chains. + * + * Returns 0 or the error code + */ +static int +rfc3986_parse_fragment(URI *uri, const char **str) +{ + const char *cur; + + if (str == NULL) + return (-1); + + cur = *str; + + while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') || + (*cur == '[') || (*cur == ']') || + ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) + NEXT(cur); + if (uri != NULL) { + if (uri->fragment != NULL) + g_free(uri->fragment); + if (uri->cleanup & 2) + uri->fragment = g_strndup(*str, cur - *str); + else + uri->fragment = uri_string_unescape(*str, cur - *str, NULL); + } + *str = cur; + return (0); +} + +/** + * rfc3986_parse_query: + * @uri: pointer to an URI structure + * @str: pointer to the string to analyze + * + * Parse the query part of an URI + * + * query = *uric + * + * Returns 0 or the error code + */ +static int +rfc3986_parse_query(URI *uri, const char **str) +{ + const char *cur; + + if (str == NULL) + return (-1); + + cur = *str; + + while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') || + ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) + NEXT(cur); + if (uri != NULL) { + if (uri->query != NULL) + g_free (uri->query); + uri->query = g_strndup (*str, cur - *str); + } + *str = cur; + return (0); +} + +/** + * rfc3986_parse_port: + * @uri: pointer to an URI structure + * @str: the string to analyze + * + * Parse a port part and fills in the appropriate fields + * of the @uri structure + * + * port = *DIGIT + * + * Returns 0 or the error code + */ +static int +rfc3986_parse_port(URI *uri, const char **str) +{ + const char *cur = *str; + + if (ISA_DIGIT(cur)) { + if (uri != NULL) + uri->port = 0; + while (ISA_DIGIT(cur)) { + if (uri != NULL) + uri->port = uri->port * 10 + (*cur - '0'); + cur++; + } + *str = cur; + return(0); + } + return(1); +} + +/** + * rfc3986_parse_user_info: + * @uri: pointer to an URI structure + * @str: the string to analyze + * + * Parse an user informations part and fills in the appropriate fields + * of the @uri structure + * + * userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) + * + * Returns 0 or the error code + */ +static int +rfc3986_parse_user_info(URI *uri, const char **str) +{ + const char *cur; + + cur = *str; + while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || + ISA_SUB_DELIM(cur) || (*cur == ':')) + NEXT(cur); + if (*cur == '@') { + if (uri != NULL) { + if (uri->user != NULL) g_free(uri->user); + if (uri->cleanup & 2) + uri->user = g_strndup(*str, cur - *str); + else + uri->user = uri_string_unescape(*str, cur - *str, NULL); + } + *str = cur; + return(0); + } + return(1); +} + +/** + * rfc3986_parse_dec_octet: + * @str: the string to analyze + * + * dec-octet = DIGIT ; 0-9 + * / %x31-39 DIGIT ; 10-99 + * / "1" 2DIGIT ; 100-199 + * / "2" %x30-34 DIGIT ; 200-249 + * / "25" %x30-35 ; 250-255 + * + * Skip a dec-octet. + * + * Returns 0 if found and skipped, 1 otherwise + */ +static int +rfc3986_parse_dec_octet(const char **str) { + const char *cur = *str; + + if (!(ISA_DIGIT(cur))) + return(1); + if (!ISA_DIGIT(cur+1)) + cur++; + else if ((*cur != '0') && (ISA_DIGIT(cur + 1)) && (!ISA_DIGIT(cur+2))) + cur += 2; + else if ((*cur == '1') && (ISA_DIGIT(cur + 1)) && (ISA_DIGIT(cur + 2))) + cur += 3; + else if ((*cur == '2') && (*(cur + 1) >= '0') && + (*(cur + 1) <= '4') && (ISA_DIGIT(cur + 2))) + cur += 3; + else if ((*cur == '2') && (*(cur + 1) == '5') && + (*(cur + 2) >= '0') && (*(cur + 1) <= '5')) + cur += 3; + else + return(1); + *str = cur; + return(0); +} +/** + * rfc3986_parse_host: + * @uri: pointer to an URI structure + * @str: the string to analyze + * + * Parse an host part and fills in the appropriate fields + * of the @uri structure + * + * host = IP-literal / IPv4address / reg-name + * IP-literal = "[" ( IPv6address / IPvFuture ) "]" + * IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet + * reg-name = *( unreserved / pct-encoded / sub-delims ) + * + * Returns 0 or the error code + */ +static int +rfc3986_parse_host(URI *uri, const char **str) +{ + const char *cur = *str; + const char *host; + + host = cur; + /* + * IPv6 and future adressing scheme are enclosed between brackets + */ + if (*cur == '[') { + cur++; + while ((*cur != ']') && (*cur != 0)) + cur++; + if (*cur != ']') + return(1); + cur++; + goto found; + } + /* + * try to parse an IPv4 + */ + if (ISA_DIGIT(cur)) { + if (rfc3986_parse_dec_octet(&cur) != 0) + goto not_ipv4; + if (*cur != '.') + goto not_ipv4; + cur++; + if (rfc3986_parse_dec_octet(&cur) != 0) + goto not_ipv4; + if (*cur != '.') + goto not_ipv4; + if (rfc3986_parse_dec_octet(&cur) != 0) + goto not_ipv4; + if (*cur != '.') + goto not_ipv4; + if (rfc3986_parse_dec_octet(&cur) != 0) + goto not_ipv4; + goto found; +not_ipv4: + cur = *str; + } + /* + * then this should be a hostname which can be empty + */ + while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || ISA_SUB_DELIM(cur)) + NEXT(cur); +found: + if (uri != NULL) { + if (uri->authority != NULL) g_free(uri->authority); + uri->authority = NULL; + if (uri->server != NULL) g_free(uri->server); + if (cur != host) { + if (uri->cleanup & 2) + uri->server = g_strndup(host, cur - host); + else + uri->server = uri_string_unescape(host, cur - host, NULL); + } else + uri->server = NULL; + } + *str = cur; + return(0); +} + +/** + * rfc3986_parse_authority: + * @uri: pointer to an URI structure + * @str: the string to analyze + * + * Parse an authority part and fills in the appropriate fields + * of the @uri structure + * + * authority = [ userinfo "@" ] host [ ":" port ] + * + * Returns 0 or the error code + */ +static int +rfc3986_parse_authority(URI *uri, const char **str) +{ + const char *cur; + int ret; + + cur = *str; + /* + * try to parse an userinfo and check for the trailing @ + */ + ret = rfc3986_parse_user_info(uri, &cur); + if ((ret != 0) || (*cur != '@')) + cur = *str; + else + cur++; + ret = rfc3986_parse_host(uri, &cur); + if (ret != 0) return(ret); + if (*cur == ':') { + cur++; + ret = rfc3986_parse_port(uri, &cur); + if (ret != 0) return(ret); + } + *str = cur; + return(0); +} + +/** + * rfc3986_parse_segment: + * @str: the string to analyze + * @forbid: an optional forbidden character + * @empty: allow an empty segment + * + * Parse a segment and fills in the appropriate fields + * of the @uri structure + * + * segment = *pchar + * segment-nz = 1*pchar + * segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) + * ; non-zero-length segment without any colon ":" + * + * Returns 0 or the error code + */ +static int +rfc3986_parse_segment(const char **str, char forbid, int empty) +{ + const char *cur; + + cur = *str; + if (!ISA_PCHAR(cur)) { + if (empty) + return(0); + return(1); + } + while (ISA_PCHAR(cur) && (*cur != forbid)) + NEXT(cur); + *str = cur; + return (0); +} + +/** + * rfc3986_parse_path_ab_empty: + * @uri: pointer to an URI structure + * @str: the string to analyze + * + * Parse an path absolute or empty and fills in the appropriate fields + * of the @uri structure + * + * path-abempty = *( "/" segment ) + * + * Returns 0 or the error code + */ +static int +rfc3986_parse_path_ab_empty(URI *uri, const char **str) +{ + const char *cur; + int ret; + + cur = *str; + + while (*cur == '/') { + cur++; + ret = rfc3986_parse_segment(&cur, 0, 1); + if (ret != 0) return(ret); + } + if (uri != NULL) { + if (uri->path != NULL) g_free(uri->path); + if (*str != cur) { + if (uri->cleanup & 2) + uri->path = g_strndup(*str, cur - *str); + else + uri->path = uri_string_unescape(*str, cur - *str, NULL); + } else { + uri->path = NULL; + } + } + *str = cur; + return (0); +} + +/** + * rfc3986_parse_path_absolute: + * @uri: pointer to an URI structure + * @str: the string to analyze + * + * Parse an path absolute and fills in the appropriate fields + * of the @uri structure + * + * path-absolute = "/" [ segment-nz *( "/" segment ) ] + * + * Returns 0 or the error code + */ +static int +rfc3986_parse_path_absolute(URI *uri, const char **str) +{ + const char *cur; + int ret; + + cur = *str; + + if (*cur != '/') + return(1); + cur++; + ret = rfc3986_parse_segment(&cur, 0, 0); + if (ret == 0) { + while (*cur == '/') { + cur++; + ret = rfc3986_parse_segment(&cur, 0, 1); + if (ret != 0) return(ret); + } + } + if (uri != NULL) { + if (uri->path != NULL) g_free(uri->path); + if (cur != *str) { + if (uri->cleanup & 2) + uri->path = g_strndup(*str, cur - *str); + else + uri->path = uri_string_unescape(*str, cur - *str, NULL); + } else { + uri->path = NULL; + } + } + *str = cur; + return (0); +} + +/** + * rfc3986_parse_path_rootless: + * @uri: pointer to an URI structure + * @str: the string to analyze + * + * Parse an path without root and fills in the appropriate fields + * of the @uri structure + * + * path-rootless = segment-nz *( "/" segment ) + * + * Returns 0 or the error code + */ +static int +rfc3986_parse_path_rootless(URI *uri, const char **str) +{ + const char *cur; + int ret; + + cur = *str; + + ret = rfc3986_parse_segment(&cur, 0, 0); + if (ret != 0) return(ret); + while (*cur == '/') { + cur++; + ret = rfc3986_parse_segment(&cur, 0, 1); + if (ret != 0) return(ret); + } + if (uri != NULL) { + if (uri->path != NULL) g_free(uri->path); + if (cur != *str) { + if (uri->cleanup & 2) + uri->path = g_strndup(*str, cur - *str); + else + uri->path = uri_string_unescape(*str, cur - *str, NULL); + } else { + uri->path = NULL; + } + } + *str = cur; + return (0); +} + +/** + * rfc3986_parse_path_no_scheme: + * @uri: pointer to an URI structure + * @str: the string to analyze + * + * Parse an path which is not a scheme and fills in the appropriate fields + * of the @uri structure + * + * path-noscheme = segment-nz-nc *( "/" segment ) + * + * Returns 0 or the error code + */ +static int +rfc3986_parse_path_no_scheme(URI *uri, const char **str) +{ + const char *cur; + int ret; + + cur = *str; + + ret = rfc3986_parse_segment(&cur, ':', 0); + if (ret != 0) return(ret); + while (*cur == '/') { + cur++; + ret = rfc3986_parse_segment(&cur, 0, 1); + if (ret != 0) return(ret); + } + if (uri != NULL) { + if (uri->path != NULL) g_free(uri->path); + if (cur != *str) { + if (uri->cleanup & 2) + uri->path = g_strndup(*str, cur - *str); + else + uri->path = uri_string_unescape(*str, cur - *str, NULL); + } else { + uri->path = NULL; + } + } + *str = cur; + return (0); +} + +/** + * rfc3986_parse_hier_part: + * @uri: pointer to an URI structure + * @str: the string to analyze + * + * Parse an hierarchical part and fills in the appropriate fields + * of the @uri structure + * + * hier-part = "//" authority path-abempty + * / path-absolute + * / path-rootless + * / path-empty + * + * Returns 0 or the error code + */ +static int +rfc3986_parse_hier_part(URI *uri, const char **str) +{ + const char *cur; + int ret; + + cur = *str; + + if ((*cur == '/') && (*(cur + 1) == '/')) { + cur += 2; + ret = rfc3986_parse_authority(uri, &cur); + if (ret != 0) return(ret); + ret = rfc3986_parse_path_ab_empty(uri, &cur); + if (ret != 0) return(ret); + *str = cur; + return(0); + } else if (*cur == '/') { + ret = rfc3986_parse_path_absolute(uri, &cur); + if (ret != 0) return(ret); + } else if (ISA_PCHAR(cur)) { + ret = rfc3986_parse_path_rootless(uri, &cur); + if (ret != 0) return(ret); + } else { + /* path-empty is effectively empty */ + if (uri != NULL) { + if (uri->path != NULL) g_free(uri->path); + uri->path = NULL; + } + } + *str = cur; + return (0); +} + +/** + * rfc3986_parse_relative_ref: + * @uri: pointer to an URI structure + * @str: the string to analyze + * + * Parse an URI string and fills in the appropriate fields + * of the @uri structure + * + * relative-ref = relative-part [ "?" query ] [ "#" fragment ] + * relative-part = "//" authority path-abempty + * / path-absolute + * / path-noscheme + * / path-empty + * + * Returns 0 or the error code + */ +static int +rfc3986_parse_relative_ref(URI *uri, const char *str) { + int ret; + + if ((*str == '/') && (*(str + 1) == '/')) { + str += 2; + ret = rfc3986_parse_authority(uri, &str); + if (ret != 0) return(ret); + ret = rfc3986_parse_path_ab_empty(uri, &str); + if (ret != 0) return(ret); + } else if (*str == '/') { + ret = rfc3986_parse_path_absolute(uri, &str); + if (ret != 0) return(ret); + } else if (ISA_PCHAR(str)) { + ret = rfc3986_parse_path_no_scheme(uri, &str); + if (ret != 0) return(ret); + } else { + /* path-empty is effectively empty */ + if (uri != NULL) { + if (uri->path != NULL) g_free(uri->path); + uri->path = NULL; + } + } + + if (*str == '?') { + str++; + ret = rfc3986_parse_query(uri, &str); + if (ret != 0) return(ret); + } + if (*str == '#') { + str++; + ret = rfc3986_parse_fragment(uri, &str); + if (ret != 0) return(ret); + } + if (*str != 0) { + uri_clean(uri); + return(1); + } + return(0); +} + + +/** + * rfc3986_parse: + * @uri: pointer to an URI structure + * @str: the string to analyze + * + * Parse an URI string and fills in the appropriate fields + * of the @uri structure + * + * scheme ":" hier-part [ "?" query ] [ "#" fragment ] + * + * Returns 0 or the error code + */ +static int +rfc3986_parse(URI *uri, const char *str) { + int ret; + + ret = rfc3986_parse_scheme(uri, &str); + if (ret != 0) return(ret); + if (*str != ':') { + return(1); + } + str++; + ret = rfc3986_parse_hier_part(uri, &str); + if (ret != 0) return(ret); + if (*str == '?') { + str++; + ret = rfc3986_parse_query(uri, &str); + if (ret != 0) return(ret); + } + if (*str == '#') { + str++; + ret = rfc3986_parse_fragment(uri, &str); + if (ret != 0) return(ret); + } + if (*str != 0) { + uri_clean(uri); + return(1); + } + return(0); +} + +/** + * rfc3986_parse_uri_reference: + * @uri: pointer to an URI structure + * @str: the string to analyze + * + * Parse an URI reference string and fills in the appropriate fields + * of the @uri structure + * + * URI-reference = URI / relative-ref + * + * Returns 0 or the error code + */ +static int +rfc3986_parse_uri_reference(URI *uri, const char *str) { + int ret; + + if (str == NULL) + return(-1); + uri_clean(uri); + + /* + * Try first to parse absolute refs, then fallback to relative if + * it fails. + */ + ret = rfc3986_parse(uri, str); + if (ret != 0) { + uri_clean(uri); + ret = rfc3986_parse_relative_ref(uri, str); + if (ret != 0) { + uri_clean(uri); + return(ret); + } + } + return(0); +} + +/** + * uri_parse: + * @str: the URI string to analyze + * + * Parse an URI based on RFC 3986 + * + * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] + * + * Returns a newly built URI or NULL in case of error + */ +URI * +uri_parse(const char *str) { + URI *uri; + int ret; + + if (str == NULL) + return(NULL); + uri = uri_new(); + if (uri != NULL) { + ret = rfc3986_parse_uri_reference(uri, str); + if (ret) { + uri_free(uri); + return(NULL); + } + } + return(uri); +} + +/** + * uri_parse_into: + * @uri: pointer to an URI structure + * @str: the string to analyze + * + * Parse an URI reference string based on RFC 3986 and fills in the + * appropriate fields of the @uri structure + * + * URI-reference = URI / relative-ref + * + * Returns 0 or the error code + */ +int +uri_parse_into(URI *uri, const char *str) { + return(rfc3986_parse_uri_reference(uri, str)); +} + +/** + * uri_parse_raw: + * @str: the URI string to analyze + * @raw: if 1 unescaping of URI pieces are disabled + * + * Parse an URI but allows to keep intact the original fragments. + * + * URI-reference = URI / relative-ref + * + * Returns a newly built URI or NULL in case of error + */ +URI * +uri_parse_raw(const char *str, int raw) { + URI *uri; + int ret; + + if (str == NULL) + return(NULL); + uri = uri_new(); + if (uri != NULL) { + if (raw) { + uri->cleanup |= 2; + } + ret = uri_parse_into(uri, str); + if (ret) { + uri_free(uri); + return(NULL); + } + } + return(uri); +} + +/************************************************************************ + * * + * Generic URI structure functions * + * * + ************************************************************************/ + +/** + * uri_new: + * + * Simply creates an empty URI + * + * Returns the new structure or NULL in case of error + */ +URI * +uri_new(void) { + URI *ret; + + ret = (URI *) g_malloc(sizeof(URI)); + memset(ret, 0, sizeof(URI)); + return(ret); +} + +/** + * realloc2n: + * + * Function to handle properly a reallocation when saving an URI + * Also imposes some limit on the length of an URI string output + */ +static char * +realloc2n(char *ret, int *max) { + char *temp; + int tmp; + + tmp = *max * 2; + temp = g_realloc(ret, (tmp + 1)); + *max = tmp; + return(temp); +} + +/** + * uri_to_string: + * @uri: pointer to an URI + * + * Save the URI as an escaped string + * + * Returns a new string (to be deallocated by caller) + */ +char * +uri_to_string(URI *uri) { + char *ret = NULL; + char *temp; + const char *p; + int len; + int max; + + if (uri == NULL) return(NULL); + + + max = 80; + ret = g_malloc(max + 1); + len = 0; + + if (uri->scheme != NULL) { + p = uri->scheme; + while (*p != 0) { + if (len >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = *p++; + } + if (len >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = ':'; + } + if (uri->opaque != NULL) { + p = uri->opaque; + while (*p != 0) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + if (IS_RESERVED(*(p)) || IS_UNRESERVED(*(p))) + ret[len++] = *p++; + else { + int val = *(unsigned char *)p++; + int hi = val / 0x10, lo = val % 0x10; + ret[len++] = '%'; + ret[len++] = hi + (hi > 9? 'A'-10 : '0'); + ret[len++] = lo + (lo > 9? 'A'-10 : '0'); + } + } + } else { + if (uri->server != NULL) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = '/'; + ret[len++] = '/'; + if (uri->user != NULL) { + p = uri->user; + while (*p != 0) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + if ((IS_UNRESERVED(*(p))) || + ((*(p) == ';')) || ((*(p) == ':')) || + ((*(p) == '&')) || ((*(p) == '=')) || + ((*(p) == '+')) || ((*(p) == '$')) || + ((*(p) == ','))) + ret[len++] = *p++; + else { + int val = *(unsigned char *)p++; + int hi = val / 0x10, lo = val % 0x10; + ret[len++] = '%'; + ret[len++] = hi + (hi > 9? 'A'-10 : '0'); + ret[len++] = lo + (lo > 9? 'A'-10 : '0'); + } + } + if (len + 3 >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = '@'; + } + p = uri->server; + while (*p != 0) { + if (len >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = *p++; + } + if (uri->port > 0) { + if (len + 10 >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + len += snprintf(&ret[len], max - len, ":%d", uri->port); + } + } else if (uri->authority != NULL) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = '/'; + ret[len++] = '/'; + p = uri->authority; + while (*p != 0) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + if ((IS_UNRESERVED(*(p))) || + ((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) || + ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) || + ((*(p) == '=')) || ((*(p) == '+'))) + ret[len++] = *p++; + else { + int val = *(unsigned char *)p++; + int hi = val / 0x10, lo = val % 0x10; + ret[len++] = '%'; + ret[len++] = hi + (hi > 9? 'A'-10 : '0'); + ret[len++] = lo + (lo > 9? 'A'-10 : '0'); + } + } + } else if (uri->scheme != NULL) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = '/'; + ret[len++] = '/'; + } + if (uri->path != NULL) { + p = uri->path; + /* + * the colon in file:///d: should not be escaped or + * Windows accesses fail later. + */ + if ((uri->scheme != NULL) && + (p[0] == '/') && + (((p[1] >= 'a') && (p[1] <= 'z')) || + ((p[1] >= 'A') && (p[1] <= 'Z'))) && + (p[2] == ':') && + (!strcmp(uri->scheme, "file"))) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = *p++; + ret[len++] = *p++; + ret[len++] = *p++; + } + while (*p != 0) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + if ((IS_UNRESERVED(*(p))) || ((*(p) == '/')) || + ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) || + ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) || + ((*(p) == ','))) + ret[len++] = *p++; + else { + int val = *(unsigned char *)p++; + int hi = val / 0x10, lo = val % 0x10; + ret[len++] = '%'; + ret[len++] = hi + (hi > 9? 'A'-10 : '0'); + ret[len++] = lo + (lo > 9? 'A'-10 : '0'); + } + } + } + if (uri->query != NULL) { + if (len + 1 >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = '?'; + p = uri->query; + while (*p != 0) { + if (len + 1 >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = *p++; + } + } + } + if (uri->fragment != NULL) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = '#'; + p = uri->fragment; + while (*p != 0) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) + ret[len++] = *p++; + else { + int val = *(unsigned char *)p++; + int hi = val / 0x10, lo = val % 0x10; + ret[len++] = '%'; + ret[len++] = hi + (hi > 9? 'A'-10 : '0'); + ret[len++] = lo + (lo > 9? 'A'-10 : '0'); + } + } + } + if (len >= max) { + temp = realloc2n(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len] = 0; + return(ret); + +mem_error: + g_free(ret); + return(NULL); +} + +/** + * uri_clean: + * @uri: pointer to an URI + * + * Make sure the URI struct is free of content + */ +static void +uri_clean(URI *uri) { + if (uri == NULL) return; + + if (uri->scheme != NULL) g_free(uri->scheme); + uri->scheme = NULL; + if (uri->server != NULL) g_free(uri->server); + uri->server = NULL; + if (uri->user != NULL) g_free(uri->user); + uri->user = NULL; + if (uri->path != NULL) g_free(uri->path); + uri->path = NULL; + if (uri->fragment != NULL) g_free(uri->fragment); + uri->fragment = NULL; + if (uri->opaque != NULL) g_free(uri->opaque); + uri->opaque = NULL; + if (uri->authority != NULL) g_free(uri->authority); + uri->authority = NULL; + if (uri->query != NULL) g_free(uri->query); + uri->query = NULL; +} + +/** + * uri_free: + * @uri: pointer to an URI + * + * Free up the URI struct + */ +void +uri_free(URI *uri) { + uri_clean(uri); + g_free(uri); +} + +/************************************************************************ + * * + * Helper functions * + * * + ************************************************************************/ + +/** + * normalize_uri_path: + * @path: pointer to the path string + * + * Applies the 5 normalization steps to a path string--that is, RFC 2396 + * Section 5.2, steps 6.c through 6.g. + * + * Normalization occurs directly on the string, no new allocation is done + * + * Returns 0 or an error code + */ +static int +normalize_uri_path(char *path) { + char *cur, *out; + + if (path == NULL) + return(-1); + + /* Skip all initial "/" chars. We want to get to the beginning of the + * first non-empty segment. + */ + cur = path; + while (cur[0] == '/') + ++cur; + if (cur[0] == '\0') + return(0); + + /* Keep everything we've seen so far. */ + out = cur; + + /* + * Analyze each segment in sequence for cases (c) and (d). + */ + while (cur[0] != '\0') { + /* + * c) All occurrences of "./", where "." is a complete path segment, + * are removed from the buffer string. + */ + if ((cur[0] == '.') && (cur[1] == '/')) { + cur += 2; + /* '//' normalization should be done at this point too */ + while (cur[0] == '/') + cur++; + continue; + } + + /* + * d) If the buffer string ends with "." as a complete path segment, + * that "." is removed. + */ + if ((cur[0] == '.') && (cur[1] == '\0')) + break; + + /* Otherwise keep the segment. */ + while (cur[0] != '/') { + if (cur[0] == '\0') + goto done_cd; + (out++)[0] = (cur++)[0]; + } + /* nomalize // */ + while ((cur[0] == '/') && (cur[1] == '/')) + cur++; + + (out++)[0] = (cur++)[0]; + } + done_cd: + out[0] = '\0'; + + /* Reset to the beginning of the first segment for the next sequence. */ + cur = path; + while (cur[0] == '/') + ++cur; + if (cur[0] == '\0') + return(0); + + /* + * Analyze each segment in sequence for cases (e) and (f). + * + * e) All occurrences of "/../", where is a + * complete path segment not equal to "..", are removed from the + * buffer string. Removal of these path segments is performed + * iteratively, removing the leftmost matching pattern on each + * iteration, until no matching pattern remains. + * + * f) If the buffer string ends with "/..", where + * is a complete path segment not equal to "..", that + * "/.." is removed. + * + * To satisfy the "iterative" clause in (e), we need to collapse the + * string every time we find something that needs to be removed. Thus, + * we don't need to keep two pointers into the string: we only need a + * "current position" pointer. + */ + while (1) { + char *segp, *tmp; + + /* At the beginning of each iteration of this loop, "cur" points to + * the first character of the segment we want to examine. + */ + + /* Find the end of the current segment. */ + segp = cur; + while ((segp[0] != '/') && (segp[0] != '\0')) + ++segp; + + /* If this is the last segment, we're done (we need at least two + * segments to meet the criteria for the (e) and (f) cases). + */ + if (segp[0] == '\0') + break; + + /* If the first segment is "..", or if the next segment _isn't_ "..", + * keep this segment and try the next one. + */ + ++segp; + if (((cur[0] == '.') && (cur[1] == '.') && (segp == cur+3)) + || ((segp[0] != '.') || (segp[1] != '.') + || ((segp[2] != '/') && (segp[2] != '\0')))) { + cur = segp; + continue; + } + + /* If we get here, remove this segment and the next one and back up + * to the previous segment (if there is one), to implement the + * "iteratively" clause. It's pretty much impossible to back up + * while maintaining two pointers into the buffer, so just compact + * the whole buffer now. + */ + + /* If this is the end of the buffer, we're done. */ + if (segp[2] == '\0') { + cur[0] = '\0'; + break; + } + /* Valgrind complained, strcpy(cur, segp + 3); */ + /* string will overlap, do not use strcpy */ + tmp = cur; + segp += 3; + while ((*tmp++ = *segp++) != 0) + ; + + /* If there are no previous segments, then keep going from here. */ + segp = cur; + while ((segp > path) && ((--segp)[0] == '/')) + ; + if (segp == path) + continue; + + /* "segp" is pointing to the end of a previous segment; find it's + * start. We need to back up to the previous segment and start + * over with that to handle things like "foo/bar/../..". If we + * don't do this, then on the first pass we'll remove the "bar/..", + * but be pointing at the second ".." so we won't realize we can also + * remove the "foo/..". + */ + cur = segp; + while ((cur > path) && (cur[-1] != '/')) + --cur; + } + out[0] = '\0'; + + /* + * g) If the resulting buffer string still begins with one or more + * complete path segments of "..", then the reference is + * considered to be in error. Implementations may handle this + * error by retaining these components in the resolved path (i.e., + * treating them as part of the final URI), by removing them from + * the resolved path (i.e., discarding relative levels above the + * root), or by avoiding traversal of the reference. + * + * We discard them from the final path. + */ + if (path[0] == '/') { + cur = path; + while ((cur[0] == '/') && (cur[1] == '.') && (cur[2] == '.') + && ((cur[3] == '/') || (cur[3] == '\0'))) + cur += 3; + + if (cur != path) { + out = path; + while (cur[0] != '\0') + (out++)[0] = (cur++)[0]; + out[0] = 0; + } + } + + return(0); +} + +static int is_hex(char c) { + if (((c >= '0') && (c <= '9')) || + ((c >= 'a') && (c <= 'f')) || + ((c >= 'A') && (c <= 'F'))) + return(1); + return(0); +} + + +/** + * uri_string_unescape: + * @str: the string to unescape + * @len: the length in bytes to unescape (or <= 0 to indicate full string) + * @target: optional destination buffer + * + * Unescaping routine, but does not check that the string is an URI. The + * output is a direct unsigned char translation of %XX values (no encoding) + * Note that the length of the result can only be smaller or same size as + * the input string. + * + * Returns a copy of the string, but unescaped, will return NULL only in case + * of error + */ +char * +uri_string_unescape(const char *str, int len, char *target) { + char *ret, *out; + const char *in; + + if (str == NULL) + return(NULL); + if (len <= 0) len = strlen(str); + if (len < 0) return(NULL); + + if (target == NULL) { + ret = g_malloc(len + 1); + } else + ret = target; + in = str; + out = ret; + while(len > 0) { + if ((len > 2) && (*in == '%') && (is_hex(in[1])) && (is_hex(in[2]))) { + in++; + if ((*in >= '0') && (*in <= '9')) + *out = (*in - '0'); + else if ((*in >= 'a') && (*in <= 'f')) + *out = (*in - 'a') + 10; + else if ((*in >= 'A') && (*in <= 'F')) + *out = (*in - 'A') + 10; + in++; + if ((*in >= '0') && (*in <= '9')) + *out = *out * 16 + (*in - '0'); + else if ((*in >= 'a') && (*in <= 'f')) + *out = *out * 16 + (*in - 'a') + 10; + else if ((*in >= 'A') && (*in <= 'F')) + *out = *out * 16 + (*in - 'A') + 10; + in++; + len -= 3; + out++; + } else { + *out++ = *in++; + len--; + } + } + *out = 0; + return(ret); +} + +/** + * uri_string_escape: + * @str: string to escape + * @list: exception list string of chars not to escape + * + * This routine escapes a string to hex, ignoring reserved characters (a-z) + * and the characters in the exception list. + * + * Returns a new escaped string or NULL in case of error. + */ +char * +uri_string_escape(const char *str, const char *list) { + char *ret, ch; + char *temp; + const char *in; + int len, out; + + if (str == NULL) + return(NULL); + if (str[0] == 0) + return(g_strdup(str)); + len = strlen(str); + if (!(len > 0)) return(NULL); + + len += 20; + ret = g_malloc(len); + in = str; + out = 0; + while(*in != 0) { + if (len - out <= 3) { + temp = realloc2n(ret, &len); + ret = temp; + } + + ch = *in; + + if ((ch != '@') && (!IS_UNRESERVED(ch)) && (!strchr(list, ch))) { + unsigned char val; + ret[out++] = '%'; + val = ch >> 4; + if (val <= 9) + ret[out++] = '0' + val; + else + ret[out++] = 'A' + val - 0xA; + val = ch & 0xF; + if (val <= 9) + ret[out++] = '0' + val; + else + ret[out++] = 'A' + val - 0xA; + in++; + } else { + ret[out++] = *in++; + } + + } + ret[out] = 0; + return(ret); +} + +/************************************************************************ + * * + * Public functions * + * * + ************************************************************************/ + +/** + * uri_resolve: + * @URI: the URI instance found in the document + * @base: the base value + * + * Computes he final URI of the reference done by checking that + * the given URI is valid, and building the final URI using the + * base URI. This is processed according to section 5.2 of the + * RFC 2396 + * + * 5.2. Resolving Relative References to Absolute Form + * + * Returns a new URI string (to be freed by the caller) or NULL in case + * of error. + */ +char * +uri_resolve(const char *uri, const char *base) { + char *val = NULL; + int ret, len, indx, cur, out; + URI *ref = NULL; + URI *bas = NULL; + URI *res = NULL; + + /* + * 1) The URI reference is parsed into the potential four components and + * fragment identifier, as described in Section 4.3. + * + * NOTE that a completely empty URI is treated by modern browsers + * as a reference to "." rather than as a synonym for the current + * URI. Should we do that here? + */ + if (uri == NULL) + ret = -1; + else { + if (*uri) { + ref = uri_new(); + if (ref == NULL) + goto done; + ret = uri_parse_into(ref, uri); + } + else + ret = 0; + } + if (ret != 0) + goto done; + if ((ref != NULL) && (ref->scheme != NULL)) { + /* + * The URI is absolute don't modify. + */ + val = g_strdup(uri); + goto done; + } + if (base == NULL) + ret = -1; + else { + bas = uri_new(); + if (bas == NULL) + goto done; + ret = uri_parse_into(bas, base); + } + if (ret != 0) { + if (ref) + val = uri_to_string(ref); + goto done; + } + if (ref == NULL) { + /* + * the base fragment must be ignored + */ + if (bas->fragment != NULL) { + g_free(bas->fragment); + bas->fragment = NULL; + } + val = uri_to_string(bas); + goto done; + } + + /* + * 2) If the path component is empty and the scheme, authority, and + * query components are undefined, then it is a reference to the + * current document and we are done. Otherwise, the reference URI's + * query and fragment components are defined as found (or not found) + * within the URI reference and not inherited from the base URI. + * + * NOTE that in modern browsers, the parsing differs from the above + * in the following aspect: the query component is allowed to be + * defined while still treating this as a reference to the current + * document. + */ + res = uri_new(); + if (res == NULL) + goto done; + if ((ref->scheme == NULL) && (ref->path == NULL) && + ((ref->authority == NULL) && (ref->server == NULL))) { + if (bas->scheme != NULL) + res->scheme = g_strdup(bas->scheme); + if (bas->authority != NULL) + res->authority = g_strdup(bas->authority); + else if (bas->server != NULL) { + res->server = g_strdup(bas->server); + if (bas->user != NULL) + res->user = g_strdup(bas->user); + res->port = bas->port; + } + if (bas->path != NULL) + res->path = g_strdup(bas->path); + if (ref->query != NULL) + res->query = g_strdup (ref->query); + else if (bas->query != NULL) + res->query = g_strdup(bas->query); + if (ref->fragment != NULL) + res->fragment = g_strdup(ref->fragment); + goto step_7; + } + + /* + * 3) If the scheme component is defined, indicating that the reference + * starts with a scheme name, then the reference is interpreted as an + * absolute URI and we are done. Otherwise, the reference URI's + * scheme is inherited from the base URI's scheme component. + */ + if (ref->scheme != NULL) { + val = uri_to_string(ref); + goto done; + } + if (bas->scheme != NULL) + res->scheme = g_strdup(bas->scheme); + + if (ref->query != NULL) + res->query = g_strdup(ref->query); + if (ref->fragment != NULL) + res->fragment = g_strdup(ref->fragment); + + /* + * 4) If the authority component is defined, then the reference is a + * network-path and we skip to step 7. Otherwise, the reference + * URI's authority is inherited from the base URI's authority + * component, which will also be undefined if the URI scheme does not + * use an authority component. + */ + if ((ref->authority != NULL) || (ref->server != NULL)) { + if (ref->authority != NULL) + res->authority = g_strdup(ref->authority); + else { + res->server = g_strdup(ref->server); + if (ref->user != NULL) + res->user = g_strdup(ref->user); + res->port = ref->port; + } + if (ref->path != NULL) + res->path = g_strdup(ref->path); + goto step_7; + } + if (bas->authority != NULL) + res->authority = g_strdup(bas->authority); + else if (bas->server != NULL) { + res->server = g_strdup(bas->server); + if (bas->user != NULL) + res->user = g_strdup(bas->user); + res->port = bas->port; + } + + /* + * 5) If the path component begins with a slash character ("/"), then + * the reference is an absolute-path and we skip to step 7. + */ + if ((ref->path != NULL) && (ref->path[0] == '/')) { + res->path = g_strdup(ref->path); + goto step_7; + } + + + /* + * 6) If this step is reached, then we are resolving a relative-path + * reference. The relative path needs to be merged with the base + * URI's path. Although there are many ways to do this, we will + * describe a simple method using a separate string buffer. + * + * Allocate a buffer large enough for the result string. + */ + len = 2; /* extra / and 0 */ + if (ref->path != NULL) + len += strlen(ref->path); + if (bas->path != NULL) + len += strlen(bas->path); + res->path = g_malloc(len); + res->path[0] = 0; + + /* + * a) All but the last segment of the base URI's path component is + * copied to the buffer. In other words, any characters after the + * last (right-most) slash character, if any, are excluded. + */ + cur = 0; + out = 0; + if (bas->path != NULL) { + while (bas->path[cur] != 0) { + while ((bas->path[cur] != 0) && (bas->path[cur] != '/')) + cur++; + if (bas->path[cur] == 0) + break; + + cur++; + while (out < cur) { + res->path[out] = bas->path[out]; + out++; + } + } + } + res->path[out] = 0; + + /* + * b) The reference's path component is appended to the buffer + * string. + */ + if (ref->path != NULL && ref->path[0] != 0) { + indx = 0; + /* + * Ensure the path includes a '/' + */ + if ((out == 0) && (bas->server != NULL)) + res->path[out++] = '/'; + while (ref->path[indx] != 0) { + res->path[out++] = ref->path[indx++]; + } + } + res->path[out] = 0; + + /* + * Steps c) to h) are really path normalization steps + */ + normalize_uri_path(res->path); + +step_7: + + /* + * 7) The resulting URI components, including any inherited from the + * base URI, are recombined to give the absolute form of the URI + * reference. + */ + val = uri_to_string(res); + +done: + if (ref != NULL) + uri_free(ref); + if (bas != NULL) + uri_free(bas); + if (res != NULL) + uri_free(res); + return(val); +} + +/** + * uri_resolve_relative: + * @URI: the URI reference under consideration + * @base: the base value + * + * Expresses the URI of the reference in terms relative to the + * base. Some examples of this operation include: + * base = "http://site1.com/docs/book1.html" + * URI input URI returned + * docs/pic1.gif pic1.gif + * docs/img/pic1.gif img/pic1.gif + * img/pic1.gif ../img/pic1.gif + * http://site1.com/docs/pic1.gif pic1.gif + * http://site2.com/docs/pic1.gif http://site2.com/docs/pic1.gif + * + * base = "docs/book1.html" + * URI input URI returned + * docs/pic1.gif pic1.gif + * docs/img/pic1.gif img/pic1.gif + * img/pic1.gif ../img/pic1.gif + * http://site1.com/docs/pic1.gif http://site1.com/docs/pic1.gif + * + * + * Note: if the URI reference is really wierd or complicated, it may be + * worthwhile to first convert it into a "nice" one by calling + * uri_resolve (using 'base') before calling this routine, + * since this routine (for reasonable efficiency) assumes URI has + * already been through some validation. + * + * Returns a new URI string (to be freed by the caller) or NULL in case + * error. + */ +char * +uri_resolve_relative (const char *uri, const char * base) +{ + char *val = NULL; + int ret; + int ix; + int pos = 0; + int nbslash = 0; + int len; + URI *ref = NULL; + URI *bas = NULL; + char *bptr, *uptr, *vptr; + int remove_path = 0; + + if ((uri == NULL) || (*uri == 0)) + return NULL; + + /* + * First parse URI into a standard form + */ + ref = uri_new (); + if (ref == NULL) + return NULL; + /* If URI not already in "relative" form */ + if (uri[0] != '.') { + ret = uri_parse_into (ref, uri); + if (ret != 0) + goto done; /* Error in URI, return NULL */ + } else + ref->path = g_strdup(uri); + + /* + * Next parse base into the same standard form + */ + if ((base == NULL) || (*base == 0)) { + val = g_strdup (uri); + goto done; + } + bas = uri_new (); + if (bas == NULL) + goto done; + if (base[0] != '.') { + ret = uri_parse_into (bas, base); + if (ret != 0) + goto done; /* Error in base, return NULL */ + } else + bas->path = g_strdup(base); + + /* + * If the scheme / server on the URI differs from the base, + * just return the URI + */ + if ((ref->scheme != NULL) && + ((bas->scheme == NULL) || + (strcmp (bas->scheme, ref->scheme)) || + (strcmp (bas->server, ref->server)))) { + val = g_strdup (uri); + goto done; + } + if (!strcmp(bas->path, ref->path)) { + val = g_strdup(""); + goto done; + } + if (bas->path == NULL) { + val = g_strdup(ref->path); + goto done; + } + if (ref->path == NULL) { + ref->path = (char *) "/"; + remove_path = 1; + } + + /* + * At this point (at last!) we can compare the two paths + * + * First we take care of the special case where either of the + * two path components may be missing (bug 316224) + */ + if (bas->path == NULL) { + if (ref->path != NULL) { + uptr = ref->path; + if (*uptr == '/') + uptr++; + /* exception characters from uri_to_string */ + val = uri_string_escape(uptr, "/;&=+$,"); + } + goto done; + } + bptr = bas->path; + if (ref->path == NULL) { + for (ix = 0; bptr[ix] != 0; ix++) { + if (bptr[ix] == '/') + nbslash++; + } + uptr = NULL; + len = 1; /* this is for a string terminator only */ + } else { + /* + * Next we compare the two strings and find where they first differ + */ + if ((ref->path[pos] == '.') && (ref->path[pos+1] == '/')) + pos += 2; + if ((*bptr == '.') && (bptr[1] == '/')) + bptr += 2; + else if ((*bptr == '/') && (ref->path[pos] != '/')) + bptr++; + while ((bptr[pos] == ref->path[pos]) && (bptr[pos] != 0)) + pos++; + + if (bptr[pos] == ref->path[pos]) { + val = g_strdup(""); + goto done; /* (I can't imagine why anyone would do this) */ + } + + /* + * In URI, "back up" to the last '/' encountered. This will be the + * beginning of the "unique" suffix of URI + */ + ix = pos; + if ((ref->path[ix] == '/') && (ix > 0)) + ix--; + else if ((ref->path[ix] == 0) && (ix > 1) && (ref->path[ix - 1] == '/')) + ix -= 2; + for (; ix > 0; ix--) { + if (ref->path[ix] == '/') + break; + } + if (ix == 0) { + uptr = ref->path; + } else { + ix++; + uptr = &ref->path[ix]; + } + + /* + * In base, count the number of '/' from the differing point + */ + if (bptr[pos] != ref->path[pos]) {/* check for trivial URI == base */ + for (; bptr[ix] != 0; ix++) { + if (bptr[ix] == '/') + nbslash++; + } + } + len = strlen (uptr) + 1; + } + + if (nbslash == 0) { + if (uptr != NULL) + /* exception characters from uri_to_string */ + val = uri_string_escape(uptr, "/;&=+$,"); + goto done; + } + + /* + * Allocate just enough space for the returned string - + * length of the remainder of the URI, plus enough space + * for the "../" groups, plus one for the terminator + */ + val = g_malloc (len + 3 * nbslash); + vptr = val; + /* + * Put in as many "../" as needed + */ + for (; nbslash>0; nbslash--) { + *vptr++ = '.'; + *vptr++ = '.'; + *vptr++ = '/'; + } + /* + * Finish up with the end of the URI + */ + if (uptr != NULL) { + if ((vptr > val) && (len > 0) && + (uptr[0] == '/') && (vptr[-1] == '/')) { + memcpy (vptr, uptr + 1, len - 1); + vptr[len - 2] = 0; + } else { + memcpy (vptr, uptr, len); + vptr[len - 1] = 0; + } + } else { + vptr[len - 1] = 0; + } + + /* escape the freshly-built path */ + vptr = val; + /* exception characters from uri_to_string */ + val = uri_string_escape(vptr, "/;&=+$,"); + g_free(vptr); + +done: + /* + * Free the working variables + */ + if (remove_path != 0) + ref->path = NULL; + if (ref != NULL) + uri_free (ref); + if (bas != NULL) + uri_free (bas); + + return val; +} + +/* + * Utility functions to help parse and assemble query strings. + */ + +struct QueryParams * +query_params_new (int init_alloc) +{ + struct QueryParams *ps; + + if (init_alloc <= 0) init_alloc = 1; + + ps = g_new(QueryParams, 1); + ps->n = 0; + ps->alloc = init_alloc; + ps->p = g_new(QueryParam, ps->alloc); + + return ps; +} + +/* Ensure there is space to store at least one more parameter + * at the end of the set. + */ +static int +query_params_append (struct QueryParams *ps, + const char *name, const char *value) +{ + if (ps->n >= ps->alloc) { + ps->p = g_renew(QueryParam, ps->p, ps->alloc * 2); + ps->alloc *= 2; + } + + ps->p[ps->n].name = g_strdup(name); + ps->p[ps->n].value = value ? g_strdup(value) : NULL; + ps->p[ps->n].ignore = 0; + ps->n++; + + return 0; +} + +void +query_params_free (struct QueryParams *ps) +{ + int i; + + for (i = 0; i < ps->n; ++i) { + g_free (ps->p[i].name); + g_free (ps->p[i].value); + } + g_free (ps->p); + g_free (ps); +} + +struct QueryParams * +query_params_parse (const char *query) +{ + struct QueryParams *ps; + const char *end, *eq; + + ps = query_params_new (0); + if (!query || query[0] == '\0') return ps; + + while (*query) { + char *name = NULL, *value = NULL; + + /* Find the next separator, or end of the string. */ + end = strchr (query, '&'); + if (!end) + end = strchr (query, ';'); + if (!end) + end = query + strlen (query); + + /* Find the first '=' character between here and end. */ + eq = strchr (query, '='); + if (eq && eq >= end) eq = NULL; + + /* Empty section (eg. "&&"). */ + if (end == query) + goto next; + + /* If there is no '=' character, then we have just "name" + * and consistent with CGI.pm we assume value is "". + */ + else if (!eq) { + name = uri_string_unescape (query, end - query, NULL); + value = NULL; + } + /* Or if we have "name=" here (works around annoying + * problem when calling uri_string_unescape with len = 0). + */ + else if (eq+1 == end) { + name = uri_string_unescape (query, eq - query, NULL); + value = g_new0(char, 1); + } + /* If the '=' character is at the beginning then we have + * "=value" and consistent with CGI.pm we _ignore_ this. + */ + else if (query == eq) + goto next; + + /* Otherwise it's "name=value". */ + else { + name = uri_string_unescape (query, eq - query, NULL); + value = uri_string_unescape (eq+1, end - (eq+1), NULL); + } + + /* Append to the parameter set. */ + query_params_append (ps, name, value); + g_free(name); + g_free(value); + + next: + query = end; + if (*query) query ++; /* skip '&' separator */ + } + + return ps; +} diff --git a/uri.h b/uri.h new file mode 100644 index 0000000000..de99b3bd4b --- /dev/null +++ b/uri.h @@ -0,0 +1,113 @@ +/** + * Summary: library of generic URI related routines + * Description: library of generic URI related routines + * Implements RFC 2396 + * + * Copyright (C) 1998-2003 Daniel Veillard. All Rights Reserved. + * + * 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 + * DANIEL VEILLARD 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. + * + * Except as contained in this notice, the name of Daniel Veillard shall not + * be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from him. + * + * Author: Daniel Veillard + ** + * Copyright (C) 2007 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Richard W.M. Jones + * + * Utility functions to help parse and assemble query strings. + */ + +#ifndef QEMU_URI_H +#define QEMU_URI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * URI: + * + * A parsed URI reference. This is a struct containing the various fields + * as described in RFC 2396 but separated for further processing. + */ +typedef struct URI { + char *scheme; /* the URI scheme */ + char *opaque; /* opaque part */ + char *authority; /* the authority part */ + char *server; /* the server part */ + char *user; /* the user part */ + int port; /* the port number */ + char *path; /* the path string */ + char *fragment; /* the fragment identifier */ + int cleanup; /* parsing potentially unclean URI */ + char *query; /* the query string (as it appears in the URI) */ +} URI; + +URI *uri_new(void); +char *uri_resolve(const char *URI, const char *base); +char *uri_resolve_relative(const char *URI, const char *base); +URI *uri_parse(const char *str); +URI *uri_parse_raw(const char *str, int raw); +int uri_parse_into(URI *uri, const char *str); +char *uri_to_string(URI *uri); +char *uri_string_escape(const char *str, const char *list); +char *uri_string_unescape(const char *str, int len, char *target); +void uri_free(URI *uri); + +/* Single web service query parameter 'name=value'. */ +typedef struct QueryParam { + char *name; /* Name (unescaped). */ + char *value; /* Value (unescaped). */ + int ignore; /* Ignore this field in qparam_get_query */ +} QueryParam; + +/* Set of parameters. */ +typedef struct QueryParams { + int n; /* number of parameters used */ + int alloc; /* allocated space */ + QueryParam *p; /* array of parameters */ +} QueryParams; + +struct QueryParams *query_params_new (int init_alloc); +int query_param_append (QueryParams *ps, const char *name, const char *value); +extern char *query_param_to_string (const QueryParams *ps); +extern QueryParams *query_params_parse (const char *query); +extern void query_params_free (QueryParams *ps); + +#ifdef __cplusplus +} +#endif +#endif /* QEMU_URI_H */ From 2db2bfc0ccac5fd68dbf0ceb70fbc372c5d8a8c7 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 27 Sep 2012 19:27:43 +0530 Subject: [PATCH 0636/2270] aio: Another fix to the walking_handlers logic The AIO dispatch loop will call QLIST_REMOVE and g_free even if there are other pending calls to qemu_aio_wait outside the current one. Signed-off-by: Paolo Bonzini Signed-off-by: Bharata B Rao Signed-off-by: Kevin Wolf --- aio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aio.c b/aio.c index 99b8b72263..c738a4e15d 100644 --- a/aio.c +++ b/aio.c @@ -159,14 +159,14 @@ bool qemu_aio_wait(void) /* if we have any readable fds, dispatch event */ if (ret > 0) { - walking_handlers++; - /* we have to walk very carefully in case * qemu_aio_set_fd_handler is called while we're walking */ node = QLIST_FIRST(&aio_handlers); while (node) { AioHandler *tmp; + walking_handlers++; + if (!node->deleted && FD_ISSET(node->fd, &rdfds) && node->io_read) { @@ -181,13 +181,13 @@ bool qemu_aio_wait(void) tmp = node; node = QLIST_NEXT(node, node); - if (tmp->deleted) { + walking_handlers--; + + if (!walking_handlers && tmp->deleted) { QLIST_REMOVE(tmp, node); g_free(tmp); } } - - walking_handlers--; } return true; From eb100396b9d2658e8bf9cdc14bfcb16a9152f464 Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Mon, 24 Sep 2012 14:42:45 +0530 Subject: [PATCH 0637/2270] configure: Add a config option for GlusterFS as block backend GlusterFS support in QEMU depends on libgfapi, libgfrpc and libgfxdr provided by GlusterFS. Signed-off-by: Bharata B Rao Signed-off-by: Kevin Wolf --- configure | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/configure b/configure index 8f99b7b941..72d4b0d989 100755 --- a/configure +++ b/configure @@ -219,6 +219,7 @@ want_tools="yes" libiscsi="" coroutine="" seccomp="" +glusterfs="" # parse CC options first for opt do @@ -856,6 +857,10 @@ for opt do ;; --disable-seccomp) seccomp="no" ;; + --disable-glusterfs) glusterfs="no" + ;; + --enable-glusterfs) glusterfs="yes" + ;; *) echo "ERROR: unknown option $opt"; show_help="yes" ;; esac @@ -1128,6 +1133,8 @@ echo " --disable-seccomp disable seccomp support" echo " --enable-seccomp enables seccomp support" echo " --with-coroutine=BACKEND coroutine backend. Supported options:" echo " gthread, ucontext, sigaltstack, windows" +echo " --enable-glusterfs enable GlusterFS backend" +echo " --disable-glusterfs disable GlusterFS backend" echo "" echo "NOTE: The object files are built at the place where configure is launched" exit 1 @@ -2303,6 +2310,29 @@ EOF fi fi +########################################## +# glusterfs probe +if test "$glusterfs" != "no" ; then + cat > $TMPC < +int main(void) { + (void) glfs_new("volume"); + return 0; +} +EOF + glusterfs_libs="-lgfapi -lgfrpc -lgfxdr" + if compile_prog "" "$glusterfs_libs" ; then + glusterfs=yes + libs_tools="$glusterfs_libs $libs_tools" + libs_softmmu="$glusterfs_libs $libs_softmmu" + else + if test "$glusterfs" = "yes" ; then + feature_not_found "GlusterFS backend support" + fi + glusterfs=no + fi +fi + # # Check for xxxat() functions when we are building linux-user # emulator. This is done because older glibc versions don't @@ -3170,6 +3200,7 @@ echo "libiscsi support $libiscsi" echo "build guest agent $guest_agent" echo "seccomp support $seccomp" echo "coroutine backend $coroutine_backend" +echo "GlusterFS support $glusterfs" if test "$sdl_too_old" = "yes"; then echo "-> Your SDL version is too old - please upgrade to have SDL support" @@ -3516,6 +3547,10 @@ if test "$has_environ" = "yes" ; then echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak fi +if test "$glusterfs" = "yes" ; then + echo "CONFIG_GLUSTERFS=y" >> $config_host_mak +fi + # USB host support case "$usb" in linux) From 8d6d89cb63c57569864ecdeb84d3a1c2ebd031cc Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Thu, 27 Sep 2012 19:30:32 +0530 Subject: [PATCH 0638/2270] block: Support GlusterFS as a QEMU block backend. This patch adds gluster as the new block backend in QEMU. This gives QEMU the ability to boot VM images from gluster volumes. Its already possible to boot from VM images on gluster volumes using FUSE mount, but this patchset provides the ability to boot VM images from gluster volumes by by-passing the FUSE layer in gluster. This is made possible by using libgfapi routines to perform IO on gluster volumes directly. VM Image on gluster volume is specified like this: file=gluster[+transport]://[server[:port]]/volname/image[?socket=...] 'gluster' is the protocol. 'transport' specifies the transport type used to connect to gluster management daemon (glusterd). Valid transport types are tcp, unix and rdma. If a transport type isn't specified, then tcp type is assumed. 'server' specifies the server where the volume file specification for the given volume resides. This can be either hostname, ipv4 address or ipv6 address. ipv6 address needs to be within square brackets [ ]. If transport type is 'unix', then 'server' field should not be specifed. The 'socket' field needs to be populated with the path to unix domain socket. 'port' is the port number on which glusterd is listening. This is optional and if not specified, QEMU will send 0 which will make gluster to use the default port. If the transport type is unix, then 'port' should not be specified. 'volname' is the name of the gluster volume which contains the VM image. 'image' is the path to the actual VM image that resides on gluster volume. Examples: file=gluster://1.2.3.4/testvol/a.img file=gluster+tcp://1.2.3.4/testvol/a.img file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img file=gluster+tcp://[1:2:3:4:5:6:7:8]/testvol/dir/a.img file=gluster+tcp://[1:2:3:4:5:6:7:8]:24007/testvol/dir/a.img file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket file=gluster+rdma://1.2.3.4:24007/testvol/a.img Signed-off-by: Bharata B Rao Signed-off-by: Kevin Wolf --- block/Makefile.objs | 1 + block/gluster.c | 624 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 625 insertions(+) create mode 100644 block/gluster.c diff --git a/block/Makefile.objs b/block/Makefile.objs index b5754d39bf..a1ae67f336 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -9,3 +9,4 @@ block-obj-$(CONFIG_POSIX) += raw-posix.o block-obj-$(CONFIG_LIBISCSI) += iscsi.o block-obj-$(CONFIG_CURL) += curl.o block-obj-$(CONFIG_RBD) += rbd.o +block-obj-$(CONFIG_GLUSTERFS) += gluster.o diff --git a/block/gluster.c b/block/gluster.c new file mode 100644 index 0000000000..3588d7377f --- /dev/null +++ b/block/gluster.c @@ -0,0 +1,624 @@ +/* + * GlusterFS backend for QEMU + * + * Copyright (C) 2012 Bharata B Rao + * + * Pipe handling mechanism in AIO implementation is derived from + * block/rbd.c. Hence, + * + * Copyright (C) 2010-2011 Christian Brunner , + * Josh Durgin + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ +#include +#include "block_int.h" +#include "qemu_socket.h" +#include "uri.h" + +typedef struct GlusterAIOCB { + BlockDriverAIOCB common; + int64_t size; + int ret; + bool *finished; + QEMUBH *bh; +} GlusterAIOCB; + +typedef struct BDRVGlusterState { + struct glfs *glfs; + int fds[2]; + struct glfs_fd *fd; + int qemu_aio_count; + int event_reader_pos; + GlusterAIOCB *event_acb; +} BDRVGlusterState; + +#define GLUSTER_FD_READ 0 +#define GLUSTER_FD_WRITE 1 + +typedef struct GlusterConf { + char *server; + int port; + char *volname; + char *image; + char *transport; +} GlusterConf; + +static void qemu_gluster_gconf_free(GlusterConf *gconf) +{ + g_free(gconf->server); + g_free(gconf->volname); + g_free(gconf->image); + g_free(gconf->transport); + g_free(gconf); +} + +static int parse_volume_options(GlusterConf *gconf, char *path) +{ + char *p, *q; + + if (!path) { + return -EINVAL; + } + + /* volume */ + p = q = path + strspn(path, "/"); + p += strcspn(p, "/"); + if (*p == '\0') { + return -EINVAL; + } + gconf->volname = g_strndup(q, p - q); + + /* image */ + p += strspn(p, "/"); + if (*p == '\0') { + return -EINVAL; + } + gconf->image = g_strdup(p); + return 0; +} + +/* + * file=gluster[+transport]://[server[:port]]/volname/image[?socket=...] + * + * 'gluster' is the protocol. + * + * 'transport' specifies the transport type used to connect to gluster + * management daemon (glusterd). Valid transport types are + * tcp, unix and rdma. If a transport type isn't specified, then tcp + * type is assumed. + * + * 'server' specifies the server where the volume file specification for + * the given volume resides. This can be either hostname, ipv4 address + * or ipv6 address. ipv6 address needs to be within square brackets [ ]. + * If transport type is 'unix', then 'server' field should not be specifed. + * The 'socket' field needs to be populated with the path to unix domain + * socket. + * + * 'port' is the port number on which glusterd is listening. This is optional + * and if not specified, QEMU will send 0 which will make gluster to use the + * default port. If the transport type is unix, then 'port' should not be + * specified. + * + * 'volname' is the name of the gluster volume which contains the VM image. + * + * 'image' is the path to the actual VM image that resides on gluster volume. + * + * Examples: + * + * file=gluster://1.2.3.4/testvol/a.img + * file=gluster+tcp://1.2.3.4/testvol/a.img + * file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img + * file=gluster+tcp://[1:2:3:4:5:6:7:8]/testvol/dir/a.img + * file=gluster+tcp://[1:2:3:4:5:6:7:8]:24007/testvol/dir/a.img + * file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img + * file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket + * file=gluster+rdma://1.2.3.4:24007/testvol/a.img + */ +static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename) +{ + URI *uri; + QueryParams *qp = NULL; + bool is_unix = false; + int ret = 0; + + uri = uri_parse(filename); + if (!uri) { + return -EINVAL; + } + + /* transport */ + if (!strcmp(uri->scheme, "gluster")) { + gconf->transport = g_strdup("tcp"); + } else if (!strcmp(uri->scheme, "gluster+tcp")) { + gconf->transport = g_strdup("tcp"); + } else if (!strcmp(uri->scheme, "gluster+unix")) { + gconf->transport = g_strdup("unix"); + is_unix = true; + } else if (!strcmp(uri->scheme, "gluster+rdma")) { + gconf->transport = g_strdup("rdma"); + } else { + ret = -EINVAL; + goto out; + } + + ret = parse_volume_options(gconf, uri->path); + if (ret < 0) { + goto out; + } + + qp = query_params_parse(uri->query); + if (qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n)) { + ret = -EINVAL; + goto out; + } + + if (is_unix) { + if (uri->server || uri->port) { + ret = -EINVAL; + goto out; + } + if (strcmp(qp->p[0].name, "socket")) { + ret = -EINVAL; + goto out; + } + gconf->server = g_strdup(qp->p[0].value); + } else { + gconf->server = g_strdup(uri->server); + gconf->port = uri->port; + } + +out: + if (qp) { + query_params_free(qp); + } + uri_free(uri); + return ret; +} + +static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename) +{ + struct glfs *glfs = NULL; + int ret; + int old_errno; + + ret = qemu_gluster_parseuri(gconf, filename); + if (ret < 0) { + error_report("Usage: file=gluster[+transport]://[server[:port]]/" + "volname/image[?socket=...]"); + errno = -ret; + goto out; + } + + glfs = glfs_new(gconf->volname); + if (!glfs) { + goto out; + } + + ret = glfs_set_volfile_server(glfs, gconf->transport, gconf->server, + gconf->port); + if (ret < 0) { + goto out; + } + + /* + * TODO: Use GF_LOG_ERROR instead of hard code value of 4 here when + * GlusterFS makes GF_LOG_* macros available to libgfapi users. + */ + ret = glfs_set_logging(glfs, "-", 4); + if (ret < 0) { + goto out; + } + + ret = glfs_init(glfs); + if (ret) { + error_report("Gluster connection failed for server=%s port=%d " + "volume=%s image=%s transport=%s\n", gconf->server, gconf->port, + gconf->volname, gconf->image, gconf->transport); + goto out; + } + return glfs; + +out: + if (glfs) { + old_errno = errno; + glfs_fini(glfs); + errno = old_errno; + } + return NULL; +} + +static void qemu_gluster_complete_aio(GlusterAIOCB *acb, BDRVGlusterState *s) +{ + int ret; + bool *finished = acb->finished; + BlockDriverCompletionFunc *cb = acb->common.cb; + void *opaque = acb->common.opaque; + + if (!acb->ret || acb->ret == acb->size) { + ret = 0; /* Success */ + } else if (acb->ret < 0) { + ret = acb->ret; /* Read/Write failed */ + } else { + ret = -EIO; /* Partial read/write - fail it */ + } + + s->qemu_aio_count--; + qemu_aio_release(acb); + cb(opaque, ret); + if (finished) { + *finished = true; + } +} + +static void qemu_gluster_aio_event_reader(void *opaque) +{ + BDRVGlusterState *s = opaque; + ssize_t ret; + + do { + char *p = (char *)&s->event_acb; + + ret = read(s->fds[GLUSTER_FD_READ], p + s->event_reader_pos, + sizeof(s->event_acb) - s->event_reader_pos); + if (ret > 0) { + s->event_reader_pos += ret; + if (s->event_reader_pos == sizeof(s->event_acb)) { + s->event_reader_pos = 0; + qemu_gluster_complete_aio(s->event_acb, s); + } + } + } while (ret < 0 && errno == EINTR); +} + +static int qemu_gluster_aio_flush_cb(void *opaque) +{ + BDRVGlusterState *s = opaque; + + return (s->qemu_aio_count > 0); +} + +static int qemu_gluster_open(BlockDriverState *bs, const char *filename, + int bdrv_flags) +{ + BDRVGlusterState *s = bs->opaque; + int open_flags = O_BINARY; + int ret = 0; + GlusterConf *gconf = g_malloc0(sizeof(GlusterConf)); + + s->glfs = qemu_gluster_init(gconf, filename); + if (!s->glfs) { + ret = -errno; + goto out; + } + + if (bdrv_flags & BDRV_O_RDWR) { + open_flags |= O_RDWR; + } else { + open_flags |= O_RDONLY; + } + + if ((bdrv_flags & BDRV_O_NOCACHE)) { + open_flags |= O_DIRECT; + } + + s->fd = glfs_open(s->glfs, gconf->image, open_flags); + if (!s->fd) { + ret = -errno; + goto out; + } + + ret = qemu_pipe(s->fds); + if (ret < 0) { + ret = -errno; + goto out; + } + fcntl(s->fds[GLUSTER_FD_READ], F_SETFL, O_NONBLOCK); + qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], + qemu_gluster_aio_event_reader, NULL, qemu_gluster_aio_flush_cb, s); + +out: + qemu_gluster_gconf_free(gconf); + if (!ret) { + return ret; + } + if (s->fd) { + glfs_close(s->fd); + } + if (s->glfs) { + glfs_fini(s->glfs); + } + return ret; +} + +static int qemu_gluster_create(const char *filename, + QEMUOptionParameter *options) +{ + struct glfs *glfs; + struct glfs_fd *fd; + int ret = 0; + int64_t total_size = 0; + GlusterConf *gconf = g_malloc0(sizeof(GlusterConf)); + + glfs = qemu_gluster_init(gconf, filename); + if (!glfs) { + ret = -errno; + goto out; + } + + while (options && options->name) { + if (!strcmp(options->name, BLOCK_OPT_SIZE)) { + total_size = options->value.n / BDRV_SECTOR_SIZE; + } + options++; + } + + fd = glfs_creat(glfs, gconf->image, + O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR); + if (!fd) { + ret = -errno; + } else { + if (glfs_ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) { + ret = -errno; + } + if (glfs_close(fd) != 0) { + ret = -errno; + } + } +out: + qemu_gluster_gconf_free(gconf); + if (glfs) { + glfs_fini(glfs); + } + return ret; +} + +static void qemu_gluster_aio_cancel(BlockDriverAIOCB *blockacb) +{ + GlusterAIOCB *acb = (GlusterAIOCB *)blockacb; + bool finished = false; + + acb->finished = &finished; + while (!finished) { + qemu_aio_wait(); + } +} + +static AIOPool gluster_aio_pool = { + .aiocb_size = sizeof(GlusterAIOCB), + .cancel = qemu_gluster_aio_cancel, +}; + +static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg) +{ + GlusterAIOCB *acb = (GlusterAIOCB *)arg; + BlockDriverState *bs = acb->common.bs; + BDRVGlusterState *s = bs->opaque; + int retval; + + acb->ret = ret; + retval = qemu_write_full(s->fds[GLUSTER_FD_WRITE], &acb, sizeof(acb)); + if (retval != sizeof(acb)) { + /* + * Gluster AIO callback thread failed to notify the waiting + * QEMU thread about IO completion. + * + * Complete this IO request and make the disk inaccessible for + * subsequent reads and writes. + */ + error_report("Gluster failed to notify QEMU about IO completion"); + + qemu_mutex_lock_iothread(); /* We are in gluster thread context */ + acb->common.cb(acb->common.opaque, -EIO); + qemu_aio_release(acb); + s->qemu_aio_count--; + close(s->fds[GLUSTER_FD_READ]); + close(s->fds[GLUSTER_FD_WRITE]); + qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], NULL, NULL, NULL, + NULL); + bs->drv = NULL; /* Make the disk inaccessible */ + qemu_mutex_unlock_iothread(); + } +} + +static BlockDriverAIOCB *qemu_gluster_aio_rw(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque, int write) +{ + int ret; + GlusterAIOCB *acb; + BDRVGlusterState *s = bs->opaque; + size_t size; + off_t offset; + + offset = sector_num * BDRV_SECTOR_SIZE; + size = nb_sectors * BDRV_SECTOR_SIZE; + s->qemu_aio_count++; + + acb = qemu_aio_get(&gluster_aio_pool, bs, cb, opaque); + acb->size = size; + acb->ret = 0; + acb->finished = NULL; + + if (write) { + ret = glfs_pwritev_async(s->fd, qiov->iov, qiov->niov, offset, 0, + &gluster_finish_aiocb, acb); + } else { + ret = glfs_preadv_async(s->fd, qiov->iov, qiov->niov, offset, 0, + &gluster_finish_aiocb, acb); + } + + if (ret < 0) { + goto out; + } + return &acb->common; + +out: + s->qemu_aio_count--; + qemu_aio_release(acb); + return NULL; +} + +static BlockDriverAIOCB *qemu_gluster_aio_readv(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +{ + return qemu_gluster_aio_rw(bs, sector_num, qiov, nb_sectors, cb, opaque, 0); +} + +static BlockDriverAIOCB *qemu_gluster_aio_writev(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +{ + return qemu_gluster_aio_rw(bs, sector_num, qiov, nb_sectors, cb, opaque, 1); +} + +static BlockDriverAIOCB *qemu_gluster_aio_flush(BlockDriverState *bs, + BlockDriverCompletionFunc *cb, void *opaque) +{ + int ret; + GlusterAIOCB *acb; + BDRVGlusterState *s = bs->opaque; + + acb = qemu_aio_get(&gluster_aio_pool, bs, cb, opaque); + acb->size = 0; + acb->ret = 0; + acb->finished = NULL; + s->qemu_aio_count++; + + ret = glfs_fsync_async(s->fd, &gluster_finish_aiocb, acb); + if (ret < 0) { + goto out; + } + return &acb->common; + +out: + s->qemu_aio_count--; + qemu_aio_release(acb); + return NULL; +} + +static int64_t qemu_gluster_getlength(BlockDriverState *bs) +{ + BDRVGlusterState *s = bs->opaque; + int64_t ret; + + ret = glfs_lseek(s->fd, 0, SEEK_END); + if (ret < 0) { + return -errno; + } else { + return ret; + } +} + +static int64_t qemu_gluster_allocated_file_size(BlockDriverState *bs) +{ + BDRVGlusterState *s = bs->opaque; + struct stat st; + int ret; + + ret = glfs_fstat(s->fd, &st); + if (ret < 0) { + return -errno; + } else { + return st.st_blocks * 512; + } +} + +static void qemu_gluster_close(BlockDriverState *bs) +{ + BDRVGlusterState *s = bs->opaque; + + close(s->fds[GLUSTER_FD_READ]); + close(s->fds[GLUSTER_FD_WRITE]); + qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], NULL, NULL, NULL, NULL); + + if (s->fd) { + glfs_close(s->fd); + s->fd = NULL; + } + glfs_fini(s->glfs); +} + +static QEMUOptionParameter qemu_gluster_create_options[] = { + { + .name = BLOCK_OPT_SIZE, + .type = OPT_SIZE, + .help = "Virtual disk size" + }, + { NULL } +}; + +static BlockDriver bdrv_gluster = { + .format_name = "gluster", + .protocol_name = "gluster", + .instance_size = sizeof(BDRVGlusterState), + .bdrv_file_open = qemu_gluster_open, + .bdrv_close = qemu_gluster_close, + .bdrv_create = qemu_gluster_create, + .bdrv_getlength = qemu_gluster_getlength, + .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size, + .bdrv_aio_readv = qemu_gluster_aio_readv, + .bdrv_aio_writev = qemu_gluster_aio_writev, + .bdrv_aio_flush = qemu_gluster_aio_flush, + .create_options = qemu_gluster_create_options, +}; + +static BlockDriver bdrv_gluster_tcp = { + .format_name = "gluster", + .protocol_name = "gluster+tcp", + .instance_size = sizeof(BDRVGlusterState), + .bdrv_file_open = qemu_gluster_open, + .bdrv_close = qemu_gluster_close, + .bdrv_create = qemu_gluster_create, + .bdrv_getlength = qemu_gluster_getlength, + .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size, + .bdrv_aio_readv = qemu_gluster_aio_readv, + .bdrv_aio_writev = qemu_gluster_aio_writev, + .bdrv_aio_flush = qemu_gluster_aio_flush, + .create_options = qemu_gluster_create_options, +}; + +static BlockDriver bdrv_gluster_unix = { + .format_name = "gluster", + .protocol_name = "gluster+unix", + .instance_size = sizeof(BDRVGlusterState), + .bdrv_file_open = qemu_gluster_open, + .bdrv_close = qemu_gluster_close, + .bdrv_create = qemu_gluster_create, + .bdrv_getlength = qemu_gluster_getlength, + .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size, + .bdrv_aio_readv = qemu_gluster_aio_readv, + .bdrv_aio_writev = qemu_gluster_aio_writev, + .bdrv_aio_flush = qemu_gluster_aio_flush, + .create_options = qemu_gluster_create_options, +}; + +static BlockDriver bdrv_gluster_rdma = { + .format_name = "gluster", + .protocol_name = "gluster+rdma", + .instance_size = sizeof(BDRVGlusterState), + .bdrv_file_open = qemu_gluster_open, + .bdrv_close = qemu_gluster_close, + .bdrv_create = qemu_gluster_create, + .bdrv_getlength = qemu_gluster_getlength, + .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size, + .bdrv_aio_readv = qemu_gluster_aio_readv, + .bdrv_aio_writev = qemu_gluster_aio_writev, + .bdrv_aio_flush = qemu_gluster_aio_flush, + .create_options = qemu_gluster_create_options, +}; + +static void bdrv_gluster_init(void) +{ + bdrv_register(&bdrv_gluster_rdma); + bdrv_register(&bdrv_gluster_unix); + bdrv_register(&bdrv_gluster_tcp); + bdrv_register(&bdrv_gluster); +} + +block_init(bdrv_gluster_init); From 6ebdcee2d8e9e4b41ffe4e49039927550848b926 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 27 Sep 2012 13:29:12 -0400 Subject: [PATCH 0639/2270] block: add support functions for live commit, to find and delete images. Add bdrv_find_overlay(), and bdrv_drop_intermediate(). bdrv_find_overlay(): given 'bs' and the active (topmost) BDS of an image chain, find the image that is the immediate top of 'bs' bdrv_drop_intermediate(): Given 3 BDS (active, top, base), drop images above base up to and including top, and set base to be the backing file of top's overlay node. E.g., this converts: bottom <- base <- intermediate <- top <- active to bottom <- base <- active Signed-off-by: Jeff Cody Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- block.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ block.h | 4 ++ 2 files changed, 147 insertions(+) diff --git a/block.c b/block.c index 751ebdc06b..54209a526e 100644 --- a/block.c +++ b/block.c @@ -1724,6 +1724,149 @@ int bdrv_change_backing_file(BlockDriverState *bs, return ret; } +/* + * Finds the image layer in the chain that has 'bs' as its backing file. + * + * active is the current topmost image. + * + * Returns NULL if bs is not found in active's image chain, + * or if active == bs. + */ +BlockDriverState *bdrv_find_overlay(BlockDriverState *active, + BlockDriverState *bs) +{ + BlockDriverState *overlay = NULL; + BlockDriverState *intermediate; + + assert(active != NULL); + assert(bs != NULL); + + /* if bs is the same as active, then by definition it has no overlay + */ + if (active == bs) { + return NULL; + } + + intermediate = active; + while (intermediate->backing_hd) { + if (intermediate->backing_hd == bs) { + overlay = intermediate; + break; + } + intermediate = intermediate->backing_hd; + } + + return overlay; +} + +typedef struct BlkIntermediateStates { + BlockDriverState *bs; + QSIMPLEQ_ENTRY(BlkIntermediateStates) entry; +} BlkIntermediateStates; + + +/* + * Drops images above 'base' up to and including 'top', and sets the image + * above 'top' to have base as its backing file. + * + * Requires that the overlay to 'top' is opened r/w, so that the backing file + * information in 'bs' can be properly updated. + * + * E.g., this will convert the following chain: + * bottom <- base <- intermediate <- top <- active + * + * to + * + * bottom <- base <- active + * + * It is allowed for bottom==base, in which case it converts: + * + * base <- intermediate <- top <- active + * + * to + * + * base <- active + * + * Error conditions: + * if active == top, that is considered an error + * + */ +int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top, + BlockDriverState *base) +{ + BlockDriverState *intermediate; + BlockDriverState *base_bs = NULL; + BlockDriverState *new_top_bs = NULL; + BlkIntermediateStates *intermediate_state, *next; + int ret = -EIO; + + QSIMPLEQ_HEAD(states_to_delete, BlkIntermediateStates) states_to_delete; + QSIMPLEQ_INIT(&states_to_delete); + + if (!top->drv || !base->drv) { + goto exit; + } + + new_top_bs = bdrv_find_overlay(active, top); + + if (new_top_bs == NULL) { + /* we could not find the image above 'top', this is an error */ + goto exit; + } + + /* special case of new_top_bs->backing_hd already pointing to base - nothing + * to do, no intermediate images */ + if (new_top_bs->backing_hd == base) { + ret = 0; + goto exit; + } + + intermediate = top; + + /* now we will go down through the list, and add each BDS we find + * into our deletion queue, until we hit the 'base' + */ + while (intermediate) { + intermediate_state = g_malloc0(sizeof(BlkIntermediateStates)); + intermediate_state->bs = intermediate; + QSIMPLEQ_INSERT_TAIL(&states_to_delete, intermediate_state, entry); + + if (intermediate->backing_hd == base) { + base_bs = intermediate->backing_hd; + break; + } + intermediate = intermediate->backing_hd; + } + if (base_bs == NULL) { + /* something went wrong, we did not end at the base. safely + * unravel everything, and exit with error */ + goto exit; + } + + /* success - we can delete the intermediate states, and link top->base */ + ret = bdrv_change_backing_file(new_top_bs, base_bs->filename, + base_bs->drv ? base_bs->drv->format_name : ""); + if (ret) { + goto exit; + } + new_top_bs->backing_hd = base_bs; + + + QSIMPLEQ_FOREACH_SAFE(intermediate_state, &states_to_delete, entry, next) { + /* so that bdrv_close() does not recursively close the chain */ + intermediate_state->bs->backing_hd = NULL; + bdrv_delete(intermediate_state->bs); + } + ret = 0; + +exit: + QSIMPLEQ_FOREACH_SAFE(intermediate_state, &states_to_delete, entry, next) { + g_free(intermediate_state); + } + return ret; +} + + static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset, size_t size) { diff --git a/block.h b/block.h index b1095d8599..8c9b4245d4 100644 --- a/block.h +++ b/block.h @@ -203,6 +203,10 @@ int bdrv_commit_all(void); int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file, const char *backing_fmt); void bdrv_register(BlockDriver *bdrv); +int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top, + BlockDriverState *base); +BlockDriverState *bdrv_find_overlay(BlockDriverState *active, + BlockDriverState *bs); typedef struct BdrvCheckResult { From 747ff602636fd83daae7ee4b1dd6e8d257a89fea Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 27 Sep 2012 13:29:13 -0400 Subject: [PATCH 0640/2270] block: add live block commit functionality This adds the live commit coroutine. This iteration focuses on the commit only below the active layer, and not the active layer itself. The behaviour is similar to block streaming; the sectors are walked through, and anything that exists above 'base' is committed back down into base. At the end, intermediate images are deleted, and the chain stitched together. Images are restored to their original open flags upon completion. Signed-off-by: Jeff Cody Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- block/Makefile.objs | 1 + block/commit.c | 267 ++++++++++++++++++++++++++++++++++++++++++++ block_int.h | 16 +++ trace-events | 2 + 4 files changed, 286 insertions(+) create mode 100644 block/commit.c diff --git a/block/Makefile.objs b/block/Makefile.objs index a1ae67f336..81fd43cefb 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -4,6 +4,7 @@ block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o block-obj-y += qed-check.o block-obj-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o block-obj-y += stream.o +block-obj-y += commit.o block-obj-$(CONFIG_WIN32) += raw-win32.o block-obj-$(CONFIG_POSIX) += raw-posix.o block-obj-$(CONFIG_LIBISCSI) += iscsi.o diff --git a/block/commit.c b/block/commit.c new file mode 100644 index 0000000000..624ec5f62a --- /dev/null +++ b/block/commit.c @@ -0,0 +1,267 @@ +/* + * Live block commit + * + * Copyright Red Hat, Inc. 2012 + * + * Authors: + * Jeff Cody + * Based on stream.c by Stefan Hajnoczi + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "trace.h" +#include "block_int.h" +#include "qemu/ratelimit.h" + +enum { + /* + * Size of data buffer for populating the image file. This should be large + * enough to process multiple clusters in a single call, so that populating + * contiguous regions of the image is efficient. + */ + COMMIT_BUFFER_SIZE = 512 * 1024, /* in bytes */ +}; + +#define SLICE_TIME 100000000ULL /* ns */ + +typedef struct CommitBlockJob { + BlockJob common; + RateLimit limit; + BlockDriverState *active; + BlockDriverState *top; + BlockDriverState *base; + BlockErrorAction on_error; + int base_flags; + int orig_overlay_flags; +} CommitBlockJob; + +static int coroutine_fn commit_populate(BlockDriverState *bs, + BlockDriverState *base, + int64_t sector_num, int nb_sectors, + void *buf) +{ + int ret = 0; + + ret = bdrv_read(bs, sector_num, buf, nb_sectors); + if (ret) { + return ret; + } + + ret = bdrv_write(base, sector_num, buf, nb_sectors); + if (ret) { + return ret; + } + + return 0; +} + +static void coroutine_fn commit_run(void *opaque) +{ + CommitBlockJob *s = opaque; + BlockDriverState *active = s->active; + BlockDriverState *top = s->top; + BlockDriverState *base = s->base; + BlockDriverState *overlay_bs = NULL; + int64_t sector_num, end; + int ret = 0; + int n = 0; + void *buf; + int bytes_written = 0; + int64_t base_len; + + ret = s->common.len = bdrv_getlength(top); + + + if (s->common.len < 0) { + goto exit_restore_reopen; + } + + ret = base_len = bdrv_getlength(base); + if (base_len < 0) { + goto exit_restore_reopen; + } + + if (base_len < s->common.len) { + ret = bdrv_truncate(base, s->common.len); + if (ret) { + goto exit_restore_reopen; + } + } + + overlay_bs = bdrv_find_overlay(active, top); + + end = s->common.len >> BDRV_SECTOR_BITS; + buf = qemu_blockalign(top, COMMIT_BUFFER_SIZE); + + for (sector_num = 0; sector_num < end; sector_num += n) { + uint64_t delay_ns = 0; + bool copy; + +wait: + /* Note that even when no rate limit is applied we need to yield + * with no pending I/O here so that qemu_aio_flush() returns. + */ + block_job_sleep_ns(&s->common, rt_clock, delay_ns); + if (block_job_is_cancelled(&s->common)) { + break; + } + /* Copy if allocated above the base */ + ret = bdrv_co_is_allocated_above(top, base, sector_num, + COMMIT_BUFFER_SIZE / BDRV_SECTOR_SIZE, + &n); + copy = (ret == 1); + trace_commit_one_iteration(s, sector_num, n, ret); + if (copy) { + if (s->common.speed) { + delay_ns = ratelimit_calculate_delay(&s->limit, n); + if (delay_ns > 0) { + goto wait; + } + } + ret = commit_populate(top, base, sector_num, n, buf); + bytes_written += n * BDRV_SECTOR_SIZE; + } + if (ret < 0) { + if (s->on_error == BLOCK_ERR_STOP_ANY || + s->on_error == BLOCK_ERR_REPORT || + (s->on_error == BLOCK_ERR_STOP_ENOSPC && ret == -ENOSPC)) { + goto exit_free_buf; + } else { + n = 0; + continue; + } + } + /* Publish progress */ + s->common.offset += n * BDRV_SECTOR_SIZE; + } + + ret = 0; + + if (!block_job_is_cancelled(&s->common) && sector_num == end) { + /* success */ + ret = bdrv_drop_intermediate(active, top, base); + } + +exit_free_buf: + qemu_vfree(buf); + +exit_restore_reopen: + /* restore base open flags here if appropriate (e.g., change the base back + * to r/o). These reopens do not need to be atomic, since we won't abort + * even on failure here */ + if (s->base_flags != bdrv_get_flags(base)) { + bdrv_reopen(base, s->base_flags, NULL); + } + if (s->orig_overlay_flags != bdrv_get_flags(overlay_bs)) { + bdrv_reopen(overlay_bs, s->orig_overlay_flags, NULL); + } + + block_job_complete(&s->common, ret); +} + +static void commit_set_speed(BlockJob *job, int64_t speed, Error **errp) +{ + CommitBlockJob *s = container_of(job, CommitBlockJob, common); + + if (speed < 0) { + error_set(errp, QERR_INVALID_PARAMETER, "speed"); + return; + } + ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE, SLICE_TIME); +} + +static BlockJobType commit_job_type = { + .instance_size = sizeof(CommitBlockJob), + .job_type = "commit", + .set_speed = commit_set_speed, +}; + +void commit_start(BlockDriverState *bs, BlockDriverState *base, + BlockDriverState *top, int64_t speed, + BlockErrorAction on_error, BlockDriverCompletionFunc *cb, + void *opaque, Error **errp) +{ + CommitBlockJob *s; + BlockReopenQueue *reopen_queue = NULL; + int orig_overlay_flags; + int orig_base_flags; + BlockDriverState *overlay_bs; + Error *local_err = NULL; + + if ((on_error == BLOCK_ERR_STOP_ANY || + on_error == BLOCK_ERR_STOP_ENOSPC) && + !bdrv_iostatus_is_enabled(bs)) { + error_set(errp, QERR_INVALID_PARAMETER_COMBINATION); + return; + } + + /* Once we support top == active layer, remove this check */ + if (top == bs) { + error_setg(errp, + "Top image as the active layer is currently unsupported"); + return; + } + + if (top == base) { + error_setg(errp, "Invalid files for merge: top and base are the same"); + return; + } + + /* top and base may be valid, but let's make sure that base is reachable + * from top */ + if (bdrv_find_backing_image(top, base->filename) != base) { + error_setg(errp, + "Base (%s) is not reachable from top (%s)", + base->filename, top->filename); + return; + } + + overlay_bs = bdrv_find_overlay(bs, top); + + if (overlay_bs == NULL) { + error_setg(errp, "Could not find overlay image for %s:", top->filename); + return; + } + + orig_base_flags = bdrv_get_flags(base); + orig_overlay_flags = bdrv_get_flags(overlay_bs); + + /* convert base & overlay_bs to r/w, if necessary */ + if (!(orig_base_flags & BDRV_O_RDWR)) { + reopen_queue = bdrv_reopen_queue(reopen_queue, base, + orig_base_flags | BDRV_O_RDWR); + } + if (!(orig_overlay_flags & BDRV_O_RDWR)) { + reopen_queue = bdrv_reopen_queue(reopen_queue, overlay_bs, + orig_overlay_flags | BDRV_O_RDWR); + } + if (reopen_queue) { + bdrv_reopen_multiple(reopen_queue, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } + } + + + s = block_job_create(&commit_job_type, bs, speed, cb, opaque, errp); + if (!s) { + return; + } + + s->base = base; + s->top = top; + s->active = bs; + + s->base_flags = orig_base_flags; + s->orig_overlay_flags = orig_overlay_flags; + + s->on_error = on_error; + s->common.co = qemu_coroutine_create(commit_run); + + trace_commit_start(bs, base, top, s, s->common.co, opaque); + qemu_coroutine_enter(s->common.co, s); +} diff --git a/block_int.h b/block_int.h index ac4245cb18..56164a742a 100644 --- a/block_int.h +++ b/block_int.h @@ -463,4 +463,20 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base, BlockDriverCompletionFunc *cb, void *opaque, Error **errp); +/** + * commit_start: + * @bs: Top Block device + * @base: Block device that will be written into, and become the new top + * @speed: The maximum speed, in bytes per second, or 0 for unlimited. + * @on_error: The action to take upon error. + * @cb: Completion function for the job. + * @opaque: Opaque pointer value passed to @cb. + * @errp: Error object. + * + */ +void commit_start(BlockDriverState *bs, BlockDriverState *base, + BlockDriverState *top, int64_t speed, + BlockErrorAction on_error, BlockDriverCompletionFunc *cb, + void *opaque, Error **errp); + #endif /* BLOCK_INT_H */ diff --git a/trace-events b/trace-events index f5b5097552..dbc3007219 100644 --- a/trace-events +++ b/trace-events @@ -74,6 +74,8 @@ bdrv_co_do_copy_on_readv(void *bs, int64_t sector_num, int nb_sectors, int64_t c # block/stream.c stream_one_iteration(void *s, int64_t sector_num, int nb_sectors, int is_allocated) "s %p sector_num %"PRId64" nb_sectors %d is_allocated %d" stream_start(void *bs, void *base, void *s, void *co, void *opaque) "bs %p base %p s %p co %p opaque %p" +commit_one_iteration(void *s, int64_t sector_num, int nb_sectors, int is_allocated) "s %p sector_num %"PRId64" nb_sectors %d is_allocated %d" +commit_start(void *bs, void *base, void *top, void *s, void *co, void *opaque) "bs %p base %p top %p s %p co %p opaque %p" # blockdev.c qmp_block_job_cancel(void *job) "job %p" From 9abf2dbaf6ae990c498ec0245986bddcd6b013ea Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 27 Sep 2012 13:29:14 -0400 Subject: [PATCH 0641/2270] blockdev: rename block_stream_cb to a generic block_job_cb Signed-off-by: Jeff Cody Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- blockdev.c | 6 +++--- trace-events | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/blockdev.c b/blockdev.c index 0267fa30bf..f910ac5302 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1070,12 +1070,12 @@ static QObject *qobject_from_block_job(BlockJob *job) job->speed); } -static void block_stream_cb(void *opaque, int ret) +static void block_job_cb(void *opaque, int ret) { BlockDriverState *bs = opaque; QObject *obj; - trace_block_stream_cb(bs, bs->job, ret); + trace_block_job_cb(bs, bs->job, ret); assert(bs->job); obj = qobject_from_block_job(bs->job); @@ -1117,7 +1117,7 @@ void qmp_block_stream(const char *device, bool has_base, } stream_start(bs, base_bs, base, has_speed ? speed : 0, - block_stream_cb, bs, &local_err); + block_job_cb, bs, &local_err); if (error_is_set(&local_err)) { error_propagate(errp, local_err); return; diff --git a/trace-events b/trace-events index dbc3007219..29771a7b47 100644 --- a/trace-events +++ b/trace-events @@ -79,7 +79,7 @@ commit_start(void *bs, void *base, void *top, void *s, void *co, void *opaque) " # blockdev.c qmp_block_job_cancel(void *job) "job %p" -block_stream_cb(void *bs, void *job, int ret) "bs %p job %p ret %d" +block_job_cb(void *bs, void *job, int ret) "bs %p job %p ret %d" qmp_block_stream(void *bs, void *job) "bs %p job %p" # hw/virtio-blk.c From 79fac5680d3680c9fb43d14a8d4e39ced25530f8 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 27 Sep 2012 13:29:15 -0400 Subject: [PATCH 0642/2270] block: helper function, to find the base image of a chain This is a simple helper function, that will return the base image of a given image chain. Signed-off-by: Jeff Cody Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- block.c | 16 ++++++++++++++++ block.h | 1 + 2 files changed, 17 insertions(+) diff --git a/block.c b/block.c index 54209a526e..d7a6d14a98 100644 --- a/block.c +++ b/block.c @@ -3117,6 +3117,22 @@ int bdrv_get_backing_file_depth(BlockDriverState *bs) return 1 + bdrv_get_backing_file_depth(bs->backing_hd); } +BlockDriverState *bdrv_find_base(BlockDriverState *bs) +{ + BlockDriverState *curr_bs = NULL; + + if (!bs) { + return NULL; + } + + curr_bs = bs; + + while (curr_bs->backing_hd) { + curr_bs = curr_bs->backing_hd; + } + return curr_bs; +} + #define NB_SUFFIXES 4 char *get_human_readable_size(char *buf, int buf_size, int64_t size) diff --git a/block.h b/block.h index 8c9b4245d4..e9249c44e6 100644 --- a/block.h +++ b/block.h @@ -207,6 +207,7 @@ int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top, BlockDriverState *base); BlockDriverState *bdrv_find_overlay(BlockDriverState *active, BlockDriverState *bs); +BlockDriverState *bdrv_find_base(BlockDriverState *bs); typedef struct BdrvCheckResult { From ed61fc10e8c8d2d1287f7edae92e44f5c97c540d Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 27 Sep 2012 13:29:16 -0400 Subject: [PATCH 0643/2270] QAPI: add command for live block commit, 'block-commit' The command for live block commit is added, which has the following arguments: device: the block device to perform the commit on (mandatory) base: the base image to commit into; optional (if not specified, it is the underlying original image) top: the top image of the commit - all data from inside top down to base will be committed into base (mandatory for now; see note, below) speed: maximum speed, in bytes/sec Note: Eventually this command will support merging down the active layer, but that code is not yet complete. If the active layer is passed in as top, then an error will be returned. Once merging down the active layer is supported, the 'top' argument may become optional, and default to the active layer. The is done as a block job, so upon completion a BLOCK_JOB_COMPLETED will be emitted. Signed-off-by: Jeff Cody Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- QMP/qmp-events.txt | 6 +++-- blockdev.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++ qapi-schema.json | 34 +++++++++++++++++++++++++++ qmp-commands.hx | 6 +++++ 4 files changed, 102 insertions(+), 2 deletions(-) diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt index 287805825f..4491020423 100644 --- a/QMP/qmp-events.txt +++ b/QMP/qmp-events.txt @@ -50,7 +50,8 @@ Emitted when a block job has been cancelled. Data: -- "type": Job type ("stream" for image streaming, json-string) +- "type": Job type (json-string; "stream" for image streaming + "commit" for block commit) - "device": Device name (json-string) - "len": Maximum progress value (json-int) - "offset": Current progress value (json-int) @@ -73,7 +74,8 @@ Emitted when a block job has completed. Data: -- "type": Job type ("stream" for image streaming, json-string) +- "type": Job type (json-string; "stream" for image streaming + "commit" for block commit) - "device": Device name (json-string) - "len": Maximum progress value (json-int) - "offset": Current progress value (json-int) diff --git a/blockdev.c b/blockdev.c index f910ac5302..cea22e4978 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1131,6 +1131,64 @@ void qmp_block_stream(const char *device, bool has_base, trace_qmp_block_stream(bs, bs->job); } +void qmp_block_commit(const char *device, + bool has_base, const char *base, const char *top, + bool has_speed, int64_t speed, + Error **errp) +{ + BlockDriverState *bs; + BlockDriverState *base_bs, *top_bs; + Error *local_err = NULL; + /* This will be part of the QMP command, if/when the + * BlockdevOnError change for blkmirror makes it in + */ + BlockErrorAction on_error = BLOCK_ERR_REPORT; + + /* drain all i/o before commits */ + bdrv_drain_all(); + + bs = bdrv_find(device); + if (!bs) { + error_set(errp, QERR_DEVICE_NOT_FOUND, device); + return; + } + if (base && has_base) { + base_bs = bdrv_find_backing_image(bs, base); + } else { + base_bs = bdrv_find_base(bs); + } + + if (base_bs == NULL) { + error_set(errp, QERR_BASE_NOT_FOUND, base ? base : "NULL"); + return; + } + + /* default top_bs is the active layer */ + top_bs = bs; + + if (top) { + if (strcmp(bs->filename, top) != 0) { + top_bs = bdrv_find_backing_image(bs, top); + } + } + + if (top_bs == NULL) { + error_setg(errp, "Top image file %s not found", top ? top : "NULL"); + return; + } + + commit_start(bs, base_bs, top_bs, speed, on_error, block_job_cb, bs, + &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } + /* Grab a reference so hotplug does not delete the BlockDriverState from + * underneath us. + */ + drive_get_ref(drive_get_by_blockdev(bs)); +} + static BlockJob *find_block_job(const char *device) { BlockDriverState *bs; diff --git a/qapi-schema.json b/qapi-schema.json index 14e44199b7..58165453f4 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1468,6 +1468,40 @@ 'returns': 'str' } ## +# @block-commit +# +# Live commit of data from overlay image nodes into backing nodes - i.e., +# writes data between 'top' and 'base' into 'base'. +# +# @device: the name of the device +# +# @base: #optional The file name of the backing image to write data into. +# If not specified, this is the deepest backing image +# +# @top: The file name of the backing image within the image chain, +# which contains the topmost data to be committed down. +# Note, the active layer as 'top' is currently unsupported. +# +# If top == base, that is an error. +# +# +# @speed: #optional the maximum speed, in bytes per second +# +# Returns: Nothing on success +# If commit or stream is already active on this device, DeviceInUse +# If @device does not exist, DeviceNotFound +# If image commit is not supported by this device, NotSupported +# If @base or @top is invalid, a generic error is returned +# If @top is the active layer, or omitted, a generic error is returned +# If @speed is invalid, InvalidParameter +# +# Since: 1.3 +# +## +{ 'command': 'block-commit', + 'data': { 'device': 'str', '*base': 'str', 'top': 'str', + '*speed': 'int' } } + # @migrate_cancel # # Cancel the current executing migration process. diff --git a/qmp-commands.hx b/qmp-commands.hx index 6e21ddba61..a55a3f54ba 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -791,6 +791,12 @@ EQMP .mhandler.cmd_new = qmp_marshal_input_block_stream, }, + { + .name = "block-commit", + .args_type = "device:B,base:s?,top:s,speed:o?", + .mhandler.cmd_new = qmp_marshal_input_block_commit, + }, + { .name = "block-job-set-speed", .args_type = "device:B,speed:o", From 747051cd97c384e70eec0ceb905f08e630b6a1c4 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Thu, 27 Sep 2012 13:29:17 -0400 Subject: [PATCH 0644/2270] qemu-iotests: add initial tests for live block commit Derived from the streaming test cases (030), this adds the following 9 tests: 1. For the following image chain, commit [mid] into [backing], and use qemu-io to verify [backing] has its original data, as well as the data from [mid] [backing] <-- [mid] <-- [test] 2. Verifies that 'block-commit' with the 'speed' parameter sets the speed parameter, as reported by 'query-block-jobs' 3. Verifies that a bogus 'device' parameter to 'block-commit' results in error 4-9: Appropriate error values returned for the following argument errors: * top == base * top is nonexistent * base is nonexistent * top == active layer (this is currently not supported) * top and base arguments are reversed * top argument is omitted Signed-off-by: Jeff Cody Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- tests/qemu-iotests/040 | 178 +++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/040.out | 5 ++ tests/qemu-iotests/group | 1 + 3 files changed, 184 insertions(+) create mode 100755 tests/qemu-iotests/040 create mode 100644 tests/qemu-iotests/040.out diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040 new file mode 100755 index 0000000000..258e7eae38 --- /dev/null +++ b/tests/qemu-iotests/040 @@ -0,0 +1,178 @@ +#!/usr/bin/env python +# +# Tests for image block commit. +# +# Copyright (C) 2012 IBM, Corp. +# Copyright (C) 2012 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 . +# +# Test for live block commit +# Derived from Image Streaming Test 030 + +import time +import os +import iotests +from iotests import qemu_img, qemu_io +import struct + +backing_img = os.path.join(iotests.test_dir, 'backing.img') +mid_img = os.path.join(iotests.test_dir, 'mid.img') +test_img = os.path.join(iotests.test_dir, 'test.img') + +class ImageCommitTestCase(iotests.QMPTestCase): + '''Abstract base class for image commit test cases''' + + def assert_no_active_commit(self): + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return', []) + + def cancel_and_wait(self, drive='drive0'): + '''Cancel a block job and wait for it to finish''' + result = self.vm.qmp('block-job-cancel', device=drive) + self.assert_qmp(result, 'return', {}) + + cancelled = False + while not cancelled: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_CANCELLED': + self.assert_qmp(event, 'data/type', 'commit') + self.assert_qmp(event, 'data/device', drive) + cancelled = True + + self.assert_no_active_commit() + + def create_image(self, name, size): + file = open(name, 'w') + i = 0 + while i < size: + sector = struct.pack('>l504xl', i / 512, i / 512) + file.write(sector) + i = i + 512 + file.close() + + +class TestSingleDrive(ImageCommitTestCase): + image_len = 1 * 1024 * 1024 + test_len = 1 * 1024 * 256 + + def setUp(self): + self.create_image(backing_img, TestSingleDrive.image_len) + qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img) + qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img) + qemu_io('-c', 'write -P 0xab 0 524288', backing_img) + qemu_io('-c', 'write -P 0xef 524288 524288', mid_img) + self.vm = iotests.VM().add_drive(test_img) + self.vm.launch() + + def tearDown(self): + self.vm.shutdown() + os.remove(test_img) + os.remove(mid_img) + os.remove(backing_img) + + def test_commit(self): + self.assert_no_active_commit() + result = self.vm.qmp('block-commit', device='drive0', top='%s' % mid_img) + self.assert_qmp(result, 'return', {}) + + completed = False + while not completed: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_COMPLETED': + self.assert_qmp(event, 'data/type', 'commit') + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/offset', self.image_len) + self.assert_qmp(event, 'data/len', self.image_len) + completed = True + + self.assert_no_active_commit() + self.vm.shutdown() + + self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) + self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) + + def test_device_not_found(self): + result = self.vm.qmp('block-commit', device='nonexistent', top='%s' % mid_img) + self.assert_qmp(result, 'error/class', 'DeviceNotFound') + + def test_top_same_base(self): + self.assert_no_active_commit() + result = self.vm.qmp('block-commit', device='drive0', top='%s' % backing_img, base='%s' % backing_img) + self.assert_qmp(result, 'error/class', 'GenericError') + self.assert_qmp(result, 'error/desc', 'Invalid files for merge: top and base are the same') + + def test_top_invalid(self): + self.assert_no_active_commit() + result = self.vm.qmp('block-commit', device='drive0', top='badfile', base='%s' % backing_img) + self.assert_qmp(result, 'error/class', 'GenericError') + self.assert_qmp(result, 'error/desc', 'Top image file badfile not found') + + def test_base_invalid(self): + self.assert_no_active_commit() + result = self.vm.qmp('block-commit', device='drive0', top='%s' % mid_img, base='badfile') + self.assert_qmp(result, 'error/class', 'GenericError') + self.assert_qmp(result, 'error/desc', 'Base \'badfile\' not found') + + def test_top_is_active(self): + self.assert_no_active_commit() + result = self.vm.qmp('block-commit', device='drive0', top='%s' % test_img, base='%s' % backing_img) + self.assert_qmp(result, 'error/class', 'GenericError') + self.assert_qmp(result, 'error/desc', 'Top image as the active layer is currently unsupported') + + def test_top_and_base_reversed(self): + self.assert_no_active_commit() + result = self.vm.qmp('block-commit', device='drive0', top='%s' % backing_img, base='%s' % mid_img) + self.assert_qmp(result, 'error/class', 'GenericError') + self.assert_qmp(result, 'error/desc', 'Base (%(1)s) is not reachable from top (%(2)s)' % {"1" : mid_img, "2" : backing_img}) + + def test_top_omitted(self): + self.assert_no_active_commit() + result = self.vm.qmp('block-commit', device='drive0') + self.assert_qmp(result, 'error/class', 'GenericError') + self.assert_qmp(result, 'error/desc', "Parameter 'top' is missing") + + +class TestSetSpeed(ImageCommitTestCase): + image_len = 80 * 1024 * 1024 # MB + + def setUp(self): + qemu_img('create', backing_img, str(TestSetSpeed.image_len)) + qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img) + qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img) + self.vm = iotests.VM().add_drive(test_img) + self.vm.launch() + + def tearDown(self): + self.vm.shutdown() + os.remove(test_img) + os.remove(mid_img) + os.remove(backing_img) + + def test_set_speed(self): + self.assert_no_active_commit() + + result = self.vm.qmp('block-commit', device='drive0', top=mid_img, speed=1024 * 1024) + self.assert_qmp(result, 'return', {}) + + # Ensure the speed we set was accepted + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/device', 'drive0') + self.assert_qmp(result, 'return[0]/speed', 1024 * 1024) + + self.cancel_and_wait() + + +if __name__ == '__main__': + iotests.main(supported_fmts=['qcow2', 'qed']) diff --git a/tests/qemu-iotests/040.out b/tests/qemu-iotests/040.out new file mode 100644 index 0000000000..dae404e278 --- /dev/null +++ b/tests/qemu-iotests/040.out @@ -0,0 +1,5 @@ +......... +---------------------------------------------------------------------- +Ran 9 tests + +OK diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index ebb5ca4b41..4b54fa61f9 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -46,3 +46,4 @@ 037 rw auto backing 038 rw auto backing 039 rw auto +040 rw auto From 7ef1507045d35bd4d220cf3bfe0e80e7ac101d00 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:22:44 +0200 Subject: [PATCH 0645/2270] qerror/block: introduce QERR_BLOCK_JOB_NOT_ACTIVE The DeviceNotActive text is not a particularly good match, add a separate text while keeping the same class. Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- blockdev.c | 4 ++-- qerror.h | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/blockdev.c b/blockdev.c index cea22e4978..d824612089 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1205,7 +1205,7 @@ void qmp_block_job_set_speed(const char *device, int64_t speed, Error **errp) BlockJob *job = find_block_job(device); if (!job) { - error_set(errp, QERR_DEVICE_NOT_ACTIVE, device); + error_set(errp, QERR_BLOCK_JOB_NOT_ACTIVE, device); return; } @@ -1217,7 +1217,7 @@ void qmp_block_job_cancel(const char *device, Error **errp) BlockJob *job = find_block_job(device); if (!job) { - error_set(errp, QERR_DEVICE_NOT_ACTIVE, device); + error_set(errp, QERR_BLOCK_JOB_NOT_ACTIVE, device); return; } diff --git a/qerror.h b/qerror.h index d0a76a4f71..485c773662 100644 --- a/qerror.h +++ b/qerror.h @@ -48,6 +48,9 @@ void assert_no_error(Error *err); #define QERR_BASE_NOT_FOUND \ ERROR_CLASS_GENERIC_ERROR, "Base '%s' not found" +#define QERR_BLOCK_JOB_NOT_ACTIVE \ + ERROR_CLASS_DEVICE_NOT_ACTIVE, "No active block job on device '%s'" + #define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \ ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by device '%s' does not support feature '%s'" From 7e03a9342fff50f2a6a4086906fa66e6c6d4351d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:22:46 +0200 Subject: [PATCH 0646/2270] block: fix documentation of block_job_cancel_sync Do this in a separate commit before we move the functions to blockjob.h. Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- block_int.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/block_int.h b/block_int.h index 56164a742a..6b6b3ab639 100644 --- a/block_int.h +++ b/block_int.h @@ -425,15 +425,13 @@ void block_job_cancel(BlockJob *job); bool block_job_is_cancelled(BlockJob *job); /** - * block_job_cancel: + * block_job_cancel_sync: * @job: The job to be canceled. * - * Asynchronously cancel the job and wait for it to reach a quiescent - * state. Note that the completion callback will still be called - * asynchronously, hence it is *not* valid to call #bdrv_delete - * immediately after #block_job_cancel_sync. Users of block jobs - * will usually protect the BlockDriverState objects with a reference - * count, should this be a concern. + * Synchronously cancel the job. The completion callback is called + * before the function returns. The job may actually complete + * instead of canceling itself; the circumstances under which this + * happens depend on the kind of job that is active. * * Returns the return value from the job if the job actually completed * during the call, or -ECANCELED if it was canceled. From 2f0c9fe64c6a2887047b7eab05cd85b2643234c8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:22:47 +0200 Subject: [PATCH 0647/2270] block: move job APIs to separate files Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- Makefile.objs | 5 +- block.c | 128 +------------------------------ block.h | 2 + block/Makefile.objs | 5 +- block/commit.c | 1 + block/stream.c | 1 + block_int.h | 151 ------------------------------------- blockdev.c | 1 + blockjob.c | 163 ++++++++++++++++++++++++++++++++++++++++ blockjob.h | 179 ++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 354 insertions(+), 282 deletions(-) create mode 100644 blockjob.c create mode 100644 blockjob.h diff --git a/Makefile.objs b/Makefile.objs index 7c1c68206b..b1f3e22547 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -42,7 +42,8 @@ coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o # block-obj-y is code used by both qemu system emulation and qemu-img block-obj-y = cutils.o iov.o cache-utils.o qemu-option.o module.o async.o -block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-progress.o qemu-sockets.o uri.o +block-obj-y += nbd.o block.o blockjob.o aio.o aes.o qemu-config.o +block-obj-y += qemu-progress.o qemu-sockets.o uri.o block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y) block-obj-$(CONFIG_POSIX) += posix-aio-compat.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o @@ -59,7 +60,7 @@ endif # suppress *all* target specific code in case of system emulation, i.e. a # single QEMU executable should support all CPUs and machines. -common-obj-y = $(block-obj-y) blockdev.o +common-obj-y = $(block-obj-y) blockdev.o block/ common-obj-y += net.o net/ common-obj-y += qom/ common-obj-y += readline.o console.o cursor.o diff --git a/block.c b/block.c index d7a6d14a98..8202f27167 100644 --- a/block.c +++ b/block.c @@ -26,6 +26,7 @@ #include "trace.h" #include "monitor.h" #include "block_int.h" +#include "blockjob.h" #include "module.h" #include "qjson.h" #include "qemu-coroutine.h" @@ -4406,130 +4407,3 @@ out: return ret; } - -void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs, - int64_t speed, BlockDriverCompletionFunc *cb, - void *opaque, Error **errp) -{ - BlockJob *job; - - if (bs->job || bdrv_in_use(bs)) { - error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs)); - return NULL; - } - bdrv_set_in_use(bs, 1); - - job = g_malloc0(job_type->instance_size); - job->job_type = job_type; - job->bs = bs; - job->cb = cb; - job->opaque = opaque; - job->busy = true; - bs->job = job; - - /* Only set speed when necessary to avoid NotSupported error */ - if (speed != 0) { - Error *local_err = NULL; - - block_job_set_speed(job, speed, &local_err); - if (error_is_set(&local_err)) { - bs->job = NULL; - g_free(job); - bdrv_set_in_use(bs, 0); - error_propagate(errp, local_err); - return NULL; - } - } - return job; -} - -void block_job_complete(BlockJob *job, int ret) -{ - BlockDriverState *bs = job->bs; - - assert(bs->job == job); - job->cb(job->opaque, ret); - bs->job = NULL; - g_free(job); - bdrv_set_in_use(bs, 0); -} - -void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) -{ - Error *local_err = NULL; - - if (!job->job_type->set_speed) { - error_set(errp, QERR_NOT_SUPPORTED); - return; - } - job->job_type->set_speed(job, speed, &local_err); - if (error_is_set(&local_err)) { - error_propagate(errp, local_err); - return; - } - - job->speed = speed; -} - -void block_job_cancel(BlockJob *job) -{ - job->cancelled = true; - if (job->co && !job->busy) { - qemu_coroutine_enter(job->co, NULL); - } -} - -bool block_job_is_cancelled(BlockJob *job) -{ - return job->cancelled; -} - -struct BlockCancelData { - BlockJob *job; - BlockDriverCompletionFunc *cb; - void *opaque; - bool cancelled; - int ret; -}; - -static void block_job_cancel_cb(void *opaque, int ret) -{ - struct BlockCancelData *data = opaque; - - data->cancelled = block_job_is_cancelled(data->job); - data->ret = ret; - data->cb(data->opaque, ret); -} - -int block_job_cancel_sync(BlockJob *job) -{ - struct BlockCancelData data; - BlockDriverState *bs = job->bs; - - assert(bs->job == job); - - /* Set up our own callback to store the result and chain to - * the original callback. - */ - data.job = job; - data.cb = job->cb; - data.opaque = job->opaque; - data.ret = -EINPROGRESS; - job->cb = block_job_cancel_cb; - job->opaque = &data; - block_job_cancel(job); - while (data.ret == -EINPROGRESS) { - qemu_aio_wait(); - } - return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret; -} - -void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns) -{ - /* Check cancellation *before* setting busy = false, too! */ - if (!block_job_is_cancelled(job)) { - job->busy = false; - co_sleep_ns(clock, ns); - job->busy = true; - } -} diff --git a/block.h b/block.h index e9249c44e6..bd002d573e 100644 --- a/block.h +++ b/block.h @@ -6,9 +6,11 @@ #include "qemu-option.h" #include "qemu-coroutine.h" #include "qobject.h" +#include "qapi-types.h" /* block.c */ typedef struct BlockDriver BlockDriver; +typedef struct BlockJob BlockJob; typedef struct BlockDriverInfo { /* in bytes, 0 if irrelevant */ diff --git a/block/Makefile.objs b/block/Makefile.objs index 81fd43cefb..554f429d05 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -3,11 +3,12 @@ block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-c block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o block-obj-y += qed-check.o block-obj-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o -block-obj-y += stream.o -block-obj-y += commit.o block-obj-$(CONFIG_WIN32) += raw-win32.o block-obj-$(CONFIG_POSIX) += raw-posix.o block-obj-$(CONFIG_LIBISCSI) += iscsi.o block-obj-$(CONFIG_CURL) += curl.o block-obj-$(CONFIG_RBD) += rbd.o block-obj-$(CONFIG_GLUSTERFS) += gluster.o + +common-obj-y += stream.o +common-obj-y += commit.o diff --git a/block/commit.c b/block/commit.c index 624ec5f62a..cabb470b5b 100644 --- a/block/commit.c +++ b/block/commit.c @@ -14,6 +14,7 @@ #include "trace.h" #include "block_int.h" +#include "blockjob.h" #include "qemu/ratelimit.h" enum { diff --git a/block/stream.c b/block/stream.c index c4f87dd5b6..57e4be7c64 100644 --- a/block/stream.c +++ b/block/stream.c @@ -13,6 +13,7 @@ #include "trace.h" #include "block_int.h" +#include "blockjob.h" #include "qemu/ratelimit.h" enum { diff --git a/block_int.h b/block_int.h index 6b6b3ab639..61dc73b0e4 100644 --- a/block_int.h +++ b/block_int.h @@ -67,73 +67,6 @@ typedef struct BlockIOBaseValue { uint64_t ios[2]; } BlockIOBaseValue; -typedef struct BlockJob BlockJob; - -/** - * BlockJobType: - * - * A class type for block job objects. - */ -typedef struct BlockJobType { - /** Derived BlockJob struct size */ - size_t instance_size; - - /** String describing the operation, part of query-block-jobs QMP API */ - const char *job_type; - - /** Optional callback for job types that support setting a speed limit */ - void (*set_speed)(BlockJob *job, int64_t speed, Error **errp); -} BlockJobType; - -/** - * BlockJob: - * - * Long-running operation on a BlockDriverState. - */ -struct BlockJob { - /** The job type, including the job vtable. */ - const BlockJobType *job_type; - - /** The block device on which the job is operating. */ - BlockDriverState *bs; - - /** - * The coroutine that executes the job. If not NULL, it is - * reentered when busy is false and the job is cancelled. - */ - Coroutine *co; - - /** - * Set to true if the job should cancel itself. The flag must - * always be tested just before toggling the busy flag from false - * to true. After a job has been cancelled, it should only yield - * if #qemu_aio_wait will ("sooner or later") reenter the coroutine. - */ - bool cancelled; - - /** - * Set to false by the job while it is in a quiescent state, where - * no I/O is pending and the job has yielded on any condition - * that is not detected by #qemu_aio_wait, such as a timer. - */ - bool busy; - - /** Offset that is published by the query-block-jobs QMP API */ - int64_t offset; - - /** Length that is published by the query-block-jobs QMP API */ - int64_t len; - - /** Speed that was set with @block_job_set_speed. */ - int64_t speed; - - /** The completion function that will be called when the job completes. */ - BlockDriverCompletionFunc *cb; - - /** The opaque value that is passed to the completion function. */ - void *opaque; -}; - struct BlockDriver { const char *format_name; int instance_size; @@ -354,90 +287,6 @@ void bdrv_set_io_limits(BlockDriverState *bs, int is_windows_drive(const char *filename); #endif -/** - * block_job_create: - * @job_type: The class object for the newly-created job. - * @bs: The block - * @speed: The maximum speed, in bytes per second, or 0 for unlimited. - * @cb: Completion function for the job. - * @opaque: Opaque pointer value passed to @cb. - * @errp: Error object. - * - * Create a new long-running block device job and return it. The job - * will call @cb asynchronously when the job completes. Note that - * @bs may have been closed at the time the @cb it is called. If - * this is the case, the job may be reported as either cancelled or - * completed. - * - * This function is not part of the public job interface; it should be - * called from a wrapper that is specific to the job type. - */ -void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs, - int64_t speed, BlockDriverCompletionFunc *cb, - void *opaque, Error **errp); - -/** - * block_job_sleep_ns: - * @job: The job that calls the function. - * @clock: The clock to sleep on. - * @ns: How many nanoseconds to stop for. - * - * Put the job to sleep (assuming that it wasn't canceled) for @ns - * nanoseconds. Canceling the job will interrupt the wait immediately. - */ -void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns); - -/** - * block_job_complete: - * @job: The job being completed. - * @ret: The status code. - * - * Call the completion function that was registered at creation time, and - * free @job. - */ -void block_job_complete(BlockJob *job, int ret); - -/** - * block_job_set_speed: - * @job: The job to set the speed for. - * @speed: The new value - * @errp: Error object. - * - * Set a rate-limiting parameter for the job; the actual meaning may - * vary depending on the job type. - */ -void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp); - -/** - * block_job_cancel: - * @job: The job to be canceled. - * - * Asynchronously cancel the specified job. - */ -void block_job_cancel(BlockJob *job); - -/** - * block_job_is_cancelled: - * @job: The job being queried. - * - * Returns whether the job is scheduled for cancellation. - */ -bool block_job_is_cancelled(BlockJob *job); - -/** - * block_job_cancel_sync: - * @job: The job to be canceled. - * - * Synchronously cancel the job. The completion callback is called - * before the function returns. The job may actually complete - * instead of canceling itself; the circumstances under which this - * happens depend on the kind of job that is active. - * - * Returns the return value from the job if the job actually completed - * during the call, or -ECANCELED if it was canceled. - */ -int block_job_cancel_sync(BlockJob *job); - /** * stream_start: * @bs: Block device to operate on. diff --git a/blockdev.c b/blockdev.c index d824612089..d3f91c0aea 100644 --- a/blockdev.c +++ b/blockdev.c @@ -9,6 +9,7 @@ #include "blockdev.h" #include "hw/block-common.h" +#include "blockjob.h" #include "monitor.h" #include "qerror.h" #include "qemu-option.h" diff --git a/blockjob.c b/blockjob.c new file mode 100644 index 0000000000..9737a43b27 --- /dev/null +++ b/blockjob.c @@ -0,0 +1,163 @@ +/* + * QEMU System Emulator block driver + * + * Copyright (c) 2011 IBM Corp. + * Copyright (c) 2012 Red Hat, Inc. + * + * 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 "config-host.h" +#include "qemu-common.h" +#include "trace.h" +#include "monitor.h" +#include "block.h" +#include "blockjob.h" +#include "block_int.h" +#include "qjson.h" +#include "qemu-coroutine.h" +#include "qmp-commands.h" +#include "qemu-timer.h" + +void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs, + int64_t speed, BlockDriverCompletionFunc *cb, + void *opaque, Error **errp) +{ + BlockJob *job; + + if (bs->job || bdrv_in_use(bs)) { + error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs)); + return NULL; + } + bdrv_set_in_use(bs, 1); + + job = g_malloc0(job_type->instance_size); + job->job_type = job_type; + job->bs = bs; + job->cb = cb; + job->opaque = opaque; + job->busy = true; + bs->job = job; + + /* Only set speed when necessary to avoid NotSupported error */ + if (speed != 0) { + Error *local_err = NULL; + + block_job_set_speed(job, speed, &local_err); + if (error_is_set(&local_err)) { + bs->job = NULL; + g_free(job); + bdrv_set_in_use(bs, 0); + error_propagate(errp, local_err); + return NULL; + } + } + return job; +} + +void block_job_complete(BlockJob *job, int ret) +{ + BlockDriverState *bs = job->bs; + + assert(bs->job == job); + job->cb(job->opaque, ret); + bs->job = NULL; + g_free(job); + bdrv_set_in_use(bs, 0); +} + +void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) +{ + Error *local_err = NULL; + + if (!job->job_type->set_speed) { + error_set(errp, QERR_NOT_SUPPORTED); + return; + } + job->job_type->set_speed(job, speed, &local_err); + if (error_is_set(&local_err)) { + error_propagate(errp, local_err); + return; + } + + job->speed = speed; +} + +void block_job_cancel(BlockJob *job) +{ + job->cancelled = true; + if (job->co && !job->busy) { + qemu_coroutine_enter(job->co, NULL); + } +} + +bool block_job_is_cancelled(BlockJob *job) +{ + return job->cancelled; +} + +struct BlockCancelData { + BlockJob *job; + BlockDriverCompletionFunc *cb; + void *opaque; + bool cancelled; + int ret; +}; + +static void block_job_cancel_cb(void *opaque, int ret) +{ + struct BlockCancelData *data = opaque; + + data->cancelled = block_job_is_cancelled(data->job); + data->ret = ret; + data->cb(data->opaque, ret); +} + +int block_job_cancel_sync(BlockJob *job) +{ + struct BlockCancelData data; + BlockDriverState *bs = job->bs; + + assert(bs->job == job); + + /* Set up our own callback to store the result and chain to + * the original callback. + */ + data.job = job; + data.cb = job->cb; + data.opaque = job->opaque; + data.ret = -EINPROGRESS; + job->cb = block_job_cancel_cb; + job->opaque = &data; + block_job_cancel(job); + while (data.ret == -EINPROGRESS) { + qemu_aio_wait(); + } + return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret; +} + +void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns) +{ + /* Check cancellation *before* setting busy = false, too! */ + if (!block_job_is_cancelled(job)) { + job->busy = false; + co_sleep_ns(clock, ns); + job->busy = true; + } +} diff --git a/blockjob.h b/blockjob.h new file mode 100644 index 0000000000..753f5bcd17 --- /dev/null +++ b/blockjob.h @@ -0,0 +1,179 @@ +/* + * Declarations for long-running block device operations + * + * Copyright (c) 2011 IBM Corp. + * Copyright (c) 2012 Red Hat, Inc. + * + * 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. + */ +#ifndef BLOCKJOB_H +#define BLOCKJOB_H 1 + +#include "block.h" + +/** + * BlockJobType: + * + * A class type for block job objects. + */ +typedef struct BlockJobType { + /** Derived BlockJob struct size */ + size_t instance_size; + + /** String describing the operation, part of query-block-jobs QMP API */ + const char *job_type; + + /** Optional callback for job types that support setting a speed limit */ + void (*set_speed)(BlockJob *job, int64_t speed, Error **errp); +} BlockJobType; + +/** + * BlockJob: + * + * Long-running operation on a BlockDriverState. + */ +struct BlockJob { + /** The job type, including the job vtable. */ + const BlockJobType *job_type; + + /** The block device on which the job is operating. */ + BlockDriverState *bs; + + /** + * The coroutine that executes the job. If not NULL, it is + * reentered when busy is false and the job is cancelled. + */ + Coroutine *co; + + /** + * Set to true if the job should cancel itself. The flag must + * always be tested just before toggling the busy flag from false + * to true. After a job has been cancelled, it should only yield + * if #qemu_aio_wait will ("sooner or later") reenter the coroutine. + */ + bool cancelled; + + /** + * Set to false by the job while it is in a quiescent state, where + * no I/O is pending and the job has yielded on any condition + * that is not detected by #qemu_aio_wait, such as a timer. + */ + bool busy; + + /** Offset that is published by the query-block-jobs QMP API */ + int64_t offset; + + /** Length that is published by the query-block-jobs QMP API */ + int64_t len; + + /** Speed that was set with @block_job_set_speed. */ + int64_t speed; + + /** The completion function that will be called when the job completes. */ + BlockDriverCompletionFunc *cb; + + /** The opaque value that is passed to the completion function. */ + void *opaque; +}; + +/** + * block_job_create: + * @job_type: The class object for the newly-created job. + * @bs: The block + * @speed: The maximum speed, in bytes per second, or 0 for unlimited. + * @cb: Completion function for the job. + * @opaque: Opaque pointer value passed to @cb. + * @errp: Error object. + * + * Create a new long-running block device job and return it. The job + * will call @cb asynchronously when the job completes. Note that + * @bs may have been closed at the time the @cb it is called. If + * this is the case, the job may be reported as either cancelled or + * completed. + * + * This function is not part of the public job interface; it should be + * called from a wrapper that is specific to the job type. + */ +void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs, + int64_t speed, BlockDriverCompletionFunc *cb, + void *opaque, Error **errp); + +/** + * block_job_sleep_ns: + * @job: The job that calls the function. + * @clock: The clock to sleep on. + * @ns: How many nanoseconds to stop for. + * + * Put the job to sleep (assuming that it wasn't canceled) for @ns + * nanoseconds. Canceling the job will interrupt the wait immediately. + */ +void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns); + +/** + * block_job_complete: + * @job: The job being completed. + * @ret: The status code. + * + * Call the completion function that was registered at creation time, and + * free @job. + */ +void block_job_complete(BlockJob *job, int ret); + +/** + * block_job_set_speed: + * @job: The job to set the speed for. + * @speed: The new value + * @errp: Error object. + * + * Set a rate-limiting parameter for the job; the actual meaning may + * vary depending on the job type. + */ +void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp); + +/** + * block_job_cancel: + * @job: The job to be canceled. + * + * Asynchronously cancel the specified job. + */ +void block_job_cancel(BlockJob *job); + +/** + * block_job_is_cancelled: + * @job: The job being queried. + * + * Returns whether the job is scheduled for cancellation. + */ +bool block_job_is_cancelled(BlockJob *job); + +/** + * block_job_cancel_sync: + * @job: The job to be canceled. + * + * Synchronously cancel the job. The completion callback is called + * before the function returns. The job may actually complete + * instead of canceling itself; the circumstances under which this + * happens depend on the kind of job that is active. + * + * Returns the return value from the job if the job actually completed + * during the call, or -ECANCELED if it was canceled. + */ +int block_job_cancel_sync(BlockJob *job); + +#endif From 30e628b709fcd30db298878e435e3bc93919c48c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:22:48 +0200 Subject: [PATCH 0648/2270] block: add block_job_query Extract it out of the implementation of info block-jobs. Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- blockdev.c | 15 ++------------- blockjob.c | 11 +++++++++++ blockjob.h | 8 ++++++++ 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/blockdev.c b/blockdev.c index d3f91c0aea..9a98ce9c89 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1232,19 +1232,8 @@ static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs) BlockJob *job = bs->job; if (job) { - BlockJobInfoList *elem; - BlockJobInfo *info = g_new(BlockJobInfo, 1); - *info = (BlockJobInfo){ - .type = g_strdup(job->job_type->job_type), - .device = g_strdup(bdrv_get_device_name(bs)), - .len = job->len, - .offset = job->offset, - .speed = job->speed, - }; - - elem = g_new0(BlockJobInfoList, 1); - elem->value = info; - + BlockJobInfoList *elem = g_new0(BlockJobInfoList, 1); + elem->value = block_job_query(bs->job); (*prev)->next = elem; *prev = elem; } diff --git a/blockjob.c b/blockjob.c index 9737a43b27..dea63f8c1f 100644 --- a/blockjob.c +++ b/blockjob.c @@ -161,3 +161,14 @@ void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns) job->busy = true; } } + +BlockJobInfo *block_job_query(BlockJob *job) +{ + BlockJobInfo *info = g_new0(BlockJobInfo, 1); + info->type = g_strdup(job->job_type->job_type); + info->device = g_strdup(bdrv_get_device_name(job->bs)); + info->len = job->len; + info->offset = job->offset; + info->speed = job->speed; + return info; +} diff --git a/blockjob.h b/blockjob.h index 753f5bcd17..f3d8d58ce3 100644 --- a/blockjob.h +++ b/blockjob.h @@ -162,6 +162,14 @@ void block_job_cancel(BlockJob *job); */ bool block_job_is_cancelled(BlockJob *job); +/** + * block_job_query: + * @job: The job to get information about. + * + * Return information about a job. + */ +BlockJobInfo *block_job_query(BlockJob *job); + /** * block_job_cancel_sync: * @job: The job to be canceled. From 8d65883fff22e00d70f5880a26b7a1248c59a2d8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:22:49 +0200 Subject: [PATCH 0649/2270] qmp: add 'busy' member to BlockJobInfo Because pausing a job is asynchronous, we need to know whether it has completed. This is described by the "busy" field of BlockJob; copy it to BlockJobInfo. Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- blockjob.c | 1 + qapi-schema.json | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/blockjob.c b/blockjob.c index dea63f8c1f..64c9d2dda1 100644 --- a/blockjob.c +++ b/blockjob.c @@ -168,6 +168,7 @@ BlockJobInfo *block_job_query(BlockJob *job) info->type = g_strdup(job->job_type->job_type); info->device = g_strdup(bdrv_get_device_name(job->bs)); info->len = job->len; + info->busy = job->busy; info->offset = job->offset; info->speed = job->speed; return info; diff --git a/qapi-schema.json b/qapi-schema.json index 58165453f4..6fc6edaa2d 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1098,6 +1098,9 @@ # # @len: the maximum progress value # +# @busy: false if the job is known to be in a quiescent state, with +# no pending I/O. Since 1.3. +# # @offset: the current progress value # # @speed: the rate limit, bytes per second @@ -1106,7 +1109,7 @@ ## { 'type': 'BlockJobInfo', 'data': {'type': 'str', 'device': 'str', 'len': 'int', - 'offset': 'int', 'speed': 'int'} } + 'offset': 'int', 'busy': 'bool', 'speed': 'int'} } ## # @query-block-jobs: From 8acc72a4d20910d522516dab31272fe66da8da28 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:22:50 +0200 Subject: [PATCH 0650/2270] block: add support for job pause/resume Job pausing reuses the existing support for cancellable sleeps. A pause happens at the next sleeping point and lasts until the coroutine is re-entered explicitly. Cancellation was already doing a forced resume, so implement it explicitly in terms of resume. Paused jobs cannot be canceled without first resuming them. This ensures that I/O errors are never missed by management. Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- blockdev.c | 4 ++++ blockjob.c | 37 +++++++++++++++++++++++++++++++------ blockjob.h | 31 +++++++++++++++++++++++++++++++ qapi-schema.json | 5 ++++- qerror.h | 3 +++ 5 files changed, 73 insertions(+), 7 deletions(-) diff --git a/blockdev.c b/blockdev.c index 9a98ce9c89..612dd71f2d 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1221,6 +1221,10 @@ void qmp_block_job_cancel(const char *device, Error **errp) error_set(errp, QERR_BLOCK_JOB_NOT_ACTIVE, device); return; } + if (job->paused) { + error_set(errp, QERR_BLOCK_JOB_PAUSED, device); + return; + } trace_qmp_block_job_cancel(job); block_job_cancel(job); diff --git a/blockjob.c b/blockjob.c index 64c9d2dda1..8219f73979 100644 --- a/blockjob.c +++ b/blockjob.c @@ -99,14 +99,30 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) job->speed = speed; } -void block_job_cancel(BlockJob *job) +void block_job_pause(BlockJob *job) { - job->cancelled = true; + job->paused = true; +} + +bool block_job_is_paused(BlockJob *job) +{ + return job->paused; +} + +void block_job_resume(BlockJob *job) +{ + job->paused = false; if (job->co && !job->busy) { qemu_coroutine_enter(job->co, NULL); } } +void block_job_cancel(BlockJob *job) +{ + job->cancelled = true; + block_job_resume(job); +} + bool block_job_is_cancelled(BlockJob *job) { return job->cancelled; @@ -154,12 +170,20 @@ int block_job_cancel_sync(BlockJob *job) void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns) { + assert(job->busy); + /* Check cancellation *before* setting busy = false, too! */ - if (!block_job_is_cancelled(job)) { - job->busy = false; - co_sleep_ns(clock, ns); - job->busy = true; + if (block_job_is_cancelled(job)) { + return; } + + job->busy = false; + if (block_job_is_paused(job)) { + qemu_coroutine_yield(); + } else { + co_sleep_ns(clock, ns); + } + job->busy = true; } BlockJobInfo *block_job_query(BlockJob *job) @@ -169,6 +193,7 @@ BlockJobInfo *block_job_query(BlockJob *job) info->device = g_strdup(bdrv_get_device_name(job->bs)); info->len = job->len; info->busy = job->busy; + info->paused = job->paused; info->offset = job->offset; info->speed = job->speed; return info; diff --git a/blockjob.h b/blockjob.h index f3d8d58ce3..ece5afa75b 100644 --- a/blockjob.h +++ b/blockjob.h @@ -69,6 +69,12 @@ struct BlockJob { */ bool cancelled; + /** + * Set to true if the job is either paused, or will pause itself + * as soon as possible (if busy == true). + */ + bool paused; + /** * Set to false by the job while it is in a quiescent state, where * no I/O is pending and the job has yielded on any condition @@ -170,6 +176,31 @@ bool block_job_is_cancelled(BlockJob *job); */ BlockJobInfo *block_job_query(BlockJob *job); +/** + * block_job_pause: + * @job: The job to be paused. + * + * Asynchronously pause the specified job. + */ +void block_job_pause(BlockJob *job); + +/** + * block_job_resume: + * @job: The job to be resumed. + * + * Resume the specified job. + */ +void block_job_resume(BlockJob *job); + +/** + * block_job_is_paused: + * @job: The job being queried. + * + * Returns whether the job is currently paused, or will pause + * as soon as it reaches a sleeping point. + */ +bool block_job_is_paused(BlockJob *job); + /** * block_job_cancel_sync: * @job: The job to be canceled. diff --git a/qapi-schema.json b/qapi-schema.json index 6fc6edaa2d..86a6c7fe93 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1101,6 +1101,9 @@ # @busy: false if the job is known to be in a quiescent state, with # no pending I/O. Since 1.3. # +# @paused: whether the job is paused or, if @busy is true, will +# pause itself as soon as possible. Since 1.3. +# # @offset: the current progress value # # @speed: the rate limit, bytes per second @@ -1109,7 +1112,7 @@ ## { 'type': 'BlockJobInfo', 'data': {'type': 'str', 'device': 'str', 'len': 'int', - 'offset': 'int', 'busy': 'bool', 'speed': 'int'} } + 'offset': 'int', 'busy': 'bool', 'paused': 'bool', 'speed': 'int'} } ## # @query-block-jobs: diff --git a/qerror.h b/qerror.h index 485c773662..c91708cc3c 100644 --- a/qerror.h +++ b/qerror.h @@ -51,6 +51,9 @@ void assert_no_error(Error *err); #define QERR_BLOCK_JOB_NOT_ACTIVE \ ERROR_CLASS_DEVICE_NOT_ACTIVE, "No active block job on device '%s'" +#define QERR_BLOCK_JOB_PAUSED \ + ERROR_CLASS_GENERIC_ERROR, "The block job for device '%s' is currently paused" + #define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \ ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by device '%s' does not support feature '%s'" From 6e37fb811ac86739e5ed30dba3a8e4848bd21b56 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:22:51 +0200 Subject: [PATCH 0651/2270] qmp: add block-job-pause and block-job-resume Add QMP commands matching the functionality. Paused jobs cannot be canceled without first resuming them. This ensures that I/O errors are never missed by management. However, an optional force argument can be specified to allow that. Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- blockdev.c | 41 ++++++++++++++++++++++++++++++++++++----- hmp-commands.hx | 35 ++++++++++++++++++++++++++++++++--- hmp.c | 23 ++++++++++++++++++++++- hmp.h | 2 ++ qapi-schema.json | 46 +++++++++++++++++++++++++++++++++++++++++++++- qmp-commands.hx | 12 +++++++++++- trace-events | 2 ++ 7 files changed, 150 insertions(+), 11 deletions(-) diff --git a/blockdev.c b/blockdev.c index 612dd71f2d..f097e5743a 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1213,7 +1213,29 @@ void qmp_block_job_set_speed(const char *device, int64_t speed, Error **errp) block_job_set_speed(job, speed, errp); } -void qmp_block_job_cancel(const char *device, Error **errp) +void qmp_block_job_cancel(const char *device, + bool has_force, bool force, Error **errp) +{ + BlockJob *job = find_block_job(device); + + if (!has_force) { + force = false; + } + + if (!job) { + error_set(errp, QERR_BLOCK_JOB_NOT_ACTIVE, device); + return; + } + if (job->paused && !force) { + error_set(errp, QERR_BLOCK_JOB_PAUSED, device); + return; + } + + trace_qmp_block_job_cancel(job); + block_job_cancel(job); +} + +void qmp_block_job_pause(const char *device, Error **errp) { BlockJob *job = find_block_job(device); @@ -1221,13 +1243,22 @@ void qmp_block_job_cancel(const char *device, Error **errp) error_set(errp, QERR_BLOCK_JOB_NOT_ACTIVE, device); return; } - if (job->paused) { - error_set(errp, QERR_BLOCK_JOB_PAUSED, device); + + trace_qmp_block_job_pause(job); + block_job_pause(job); +} + +void qmp_block_job_resume(const char *device, Error **errp) +{ + BlockJob *job = find_block_job(device); + + if (!job) { + error_set(errp, QERR_BLOCK_JOB_NOT_ACTIVE, device); return; } - trace_qmp_block_job_cancel(job); - block_job_cancel(job); + trace_qmp_block_job_resume(job); + block_job_resume(job); } static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs) diff --git a/hmp-commands.hx b/hmp-commands.hx index ed67e997fd..27d90a24af 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -99,9 +99,10 @@ ETEXI { .name = "block_job_cancel", - .args_type = "device:B", - .params = "device", - .help = "stop an active background block operation", + .args_type = "force:-f,device:B", + .params = "[-f] device", + .help = "stop an active background block operation (use -f" + "\n\t\t\t if the operation is currently paused)", .mhandler.cmd = hmp_block_job_cancel, }, @@ -109,6 +110,34 @@ STEXI @item block_job_cancel @findex block_job_cancel Stop an active block streaming operation. +ETEXI + + { + .name = "block_job_pause", + .args_type = "device:B", + .params = "device", + .help = "pause an active background block operation", + .mhandler.cmd = hmp_block_job_pause, + }, + +STEXI +@item block_job_pause +@findex block_job_pause +Pause an active block streaming operation. +ETEXI + + { + .name = "block_job_resume", + .args_type = "device:B", + .params = "device", + .help = "resume a paused background block operation", + .mhandler.cmd = hmp_block_job_resume, + }, + +STEXI +@item block_job_resume +@findex block_job_resume +Resume a paused block streaming operation. ETEXI { diff --git a/hmp.c b/hmp.c index ba6fbd3dcf..55601f7dad 100644 --- a/hmp.c +++ b/hmp.c @@ -950,8 +950,29 @@ void hmp_block_job_cancel(Monitor *mon, const QDict *qdict) { Error *error = NULL; const char *device = qdict_get_str(qdict, "device"); + bool force = qdict_get_try_bool(qdict, "force", 0); - qmp_block_job_cancel(device, &error); + qmp_block_job_cancel(device, true, force, &error); + + hmp_handle_error(mon, &error); +} + +void hmp_block_job_pause(Monitor *mon, const QDict *qdict) +{ + Error *error = NULL; + const char *device = qdict_get_str(qdict, "device"); + + qmp_block_job_pause(device, &error); + + hmp_handle_error(mon, &error); +} + +void hmp_block_job_resume(Monitor *mon, const QDict *qdict) +{ + Error *error = NULL; + const char *device = qdict_get_str(qdict, "device"); + + qmp_block_job_resume(device, &error); hmp_handle_error(mon, &error); } diff --git a/hmp.h b/hmp.h index 48b9c59f8a..71ea384523 100644 --- a/hmp.h +++ b/hmp.h @@ -64,6 +64,8 @@ void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict); void hmp_block_stream(Monitor *mon, const QDict *qdict); void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict); void hmp_block_job_cancel(Monitor *mon, const QDict *qdict); +void hmp_block_job_pause(Monitor *mon, const QDict *qdict); +void hmp_block_job_resume(Monitor *mon, const QDict *qdict); void hmp_migrate(Monitor *mon, const QDict *qdict); void hmp_device_del(Monitor *mon, const QDict *qdict); void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict); diff --git a/qapi-schema.json b/qapi-schema.json index 86a6c7fe93..0f2b1a0a1d 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1893,12 +1893,56 @@ # # @device: the device name # +# @force: #optional whether to allow cancellation of a paused job (default +# false). Since 1.3. +# # Returns: Nothing on success # If no background operation is active on this device, DeviceNotActive # # Since: 1.1 ## -{ 'command': 'block-job-cancel', 'data': { 'device': 'str' } } +{ 'command': 'block-job-cancel', 'data': { 'device': 'str', '*force': 'bool' } } + +## +# @block-job-pause: +# +# Pause an active background block operation. +# +# This command returns immediately after marking the active background block +# operation for pausing. It is an error to call this command if no +# operation is in progress. Pausing an already paused job has no cumulative +# effect; a single block-job-resume command will resume the job. +# +# The operation will pause as soon as possible. No event is emitted when +# the operation is actually paused. Cancelling a paused job automatically +# resumes it. +# +# @device: the device name +# +# Returns: Nothing on success +# If no background operation is active on this device, DeviceNotActive +# +# Since: 1.3 +## +{ 'command': 'block-job-pause', 'data': { 'device': 'str' } } + +## +# @block-job-resume: +# +# Resume an active background block operation. +# +# This command returns immediately after resuming a paused background block +# operation. It is an error to call this command if no operation is in +# progress. Resuming an already running job is not an error. +# +# @device: the device name +# +# Returns: Nothing on success +# If no background operation is active on this device, DeviceNotActive +# +# Since: 1.3 +## +{ 'command': 'block-job-resume', 'data': { 'device': 'str' } } ## # @ObjectTypeInfo: diff --git a/qmp-commands.hx b/qmp-commands.hx index a55a3f54ba..71d7c25f5c 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -805,9 +805,19 @@ EQMP { .name = "block-job-cancel", - .args_type = "device:B", + .args_type = "device:B,force:b?", .mhandler.cmd_new = qmp_marshal_input_block_job_cancel, }, + { + .name = "block-job-pause", + .args_type = "device:B", + .mhandler.cmd_new = qmp_marshal_input_block_job_pause, + }, + { + .name = "block-job-resume", + .args_type = "device:B", + .mhandler.cmd_new = qmp_marshal_input_block_job_resume, + }, { .name = "transaction", .args_type = "actions:q", diff --git a/trace-events b/trace-events index 29771a7b47..42b66f19f4 100644 --- a/trace-events +++ b/trace-events @@ -79,6 +79,8 @@ commit_start(void *bs, void *base, void *top, void *s, void *co, void *opaque) " # blockdev.c qmp_block_job_cancel(void *job) "job %p" +qmp_block_job_pause(void *job) "job %p" +qmp_block_job_resume(void *job) "job %p" block_job_cb(void *bs, void *job, int ret) "bs %p job %p ret %d" qmp_block_stream(void *bs, void *job) "bs %p job %p" From 0c81734765c9af1705f8e531b9431d63ee8ffd3d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:22:52 +0200 Subject: [PATCH 0652/2270] qemu-iotests: add test for pausing a streaming operation These check that a paused streaming job does not advance its offset. Sometimes the new test fails; the map is different between the source and the destination of the streaming because qemu-io does not always pack adjacent clusters that have the same allocated/unallocated state. However, this also happens with the existing test_stream testcase, and is better fixed in qemu-io. Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- tests/qemu-iotests/030 | 40 ++++++++++++++++++++++++++++++++++++-- tests/qemu-iotests/030.out | 4 ++-- tests/qemu-iotests/group | 2 +- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030 index 55b16f81dd..dfacdf11ad 100755 --- a/tests/qemu-iotests/030 +++ b/tests/qemu-iotests/030 @@ -18,6 +18,7 @@ # along with this program. If not, see . # +import time import os import iotests from iotests import qemu_img, qemu_io @@ -98,6 +99,43 @@ class TestSingleDrive(ImageStreamingTestCase): qemu_io('-c', 'map', test_img), 'image file map does not match backing file after streaming') + def test_stream_pause(self): + self.assert_no_active_streams() + + result = self.vm.qmp('block-stream', device='drive0') + self.assert_qmp(result, 'return', {}) + + result = self.vm.qmp('block-job-pause', device='drive0') + self.assert_qmp(result, 'return', {}) + + time.sleep(1) + result = self.vm.qmp('query-block-jobs') + offset = self.dictpath(result, 'return[0]/offset') + + time.sleep(1) + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/offset', offset) + + result = self.vm.qmp('block-job-resume', device='drive0') + self.assert_qmp(result, 'return', {}) + + completed = False + while not completed: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_COMPLETED': + self.assert_qmp(event, 'data/type', 'stream') + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/offset', self.image_len) + self.assert_qmp(event, 'data/len', self.image_len) + completed = True + + self.assert_no_active_streams() + self.vm.shutdown() + + self.assertEqual(qemu_io('-c', 'map', backing_img), + qemu_io('-c', 'map', test_img), + 'image file map does not match backing file after streaming') + def test_stream_partial(self): self.assert_no_active_streams() @@ -173,8 +211,6 @@ class TestStreamStop(ImageStreamingTestCase): os.remove(backing_img) def test_stream_stop(self): - import time - self.assert_no_active_streams() result = self.vm.qmp('block-stream', device='drive0') diff --git a/tests/qemu-iotests/030.out b/tests/qemu-iotests/030.out index 2f7d3902f2..594c16f49f 100644 --- a/tests/qemu-iotests/030.out +++ b/tests/qemu-iotests/030.out @@ -1,5 +1,5 @@ -....... +........ ---------------------------------------------------------------------- -Ran 7 tests +Ran 8 tests OK diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 4b54fa61f9..66d2ba9689 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -36,7 +36,7 @@ 027 rw auto quick 028 rw backing auto 029 rw auto quick -030 rw auto +030 rw auto backing 031 rw auto quick 032 rw auto 033 rw auto From ff06f5f351c3b19d5cdcb8bcb9f9cc9a01cac066 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:22:54 +0200 Subject: [PATCH 0653/2270] iostatus: rename BlockErrorAction, BlockQMPEventAction We want to remove knowledge of BLOCK_ERR_STOP_ENOSPC from drivers; drivers should only be told whether to stop/report/ignore the error. On the other hand, we want to keep using the nicer BlockErrorAction name in the drivers. So rename the enums, while leaving aside the names of the enum values for now. Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- block.c | 8 ++++---- block.h | 12 ++++++------ block_int.h | 2 +- hw/ide/core.c | 2 +- hw/scsi-disk.c | 2 +- hw/virtio-blk.c | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/block.c b/block.c index 8202f27167..7b4508295c 100644 --- a/block.c +++ b/block.c @@ -1387,7 +1387,7 @@ void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, } void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, - BlockQMPEventAction action, int is_read) + BlockErrorAction action, int is_read) { QObject *data; const char *action_str; @@ -2474,14 +2474,14 @@ void bdrv_set_io_limits(BlockDriverState *bs, bs->io_limits_enabled = bdrv_io_limits_enabled(bs); } -void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error, - BlockErrorAction on_write_error) +void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error, + BlockdevOnError on_write_error) { bs->on_read_error = on_read_error; bs->on_write_error = on_write_error; } -BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read) +BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, int is_read) { return is_read ? bs->on_read_error : bs->on_write_error; } diff --git a/block.h b/block.h index bd002d573e..038621f426 100644 --- a/block.h +++ b/block.h @@ -93,11 +93,11 @@ typedef struct BlockDevOps { typedef enum { BLOCK_ERR_REPORT, BLOCK_ERR_IGNORE, BLOCK_ERR_STOP_ENOSPC, BLOCK_ERR_STOP_ANY -} BlockErrorAction; +} BlockdevOnError; typedef enum { BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP -} BlockQMPEventAction; +} BlockErrorAction; typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue; @@ -114,7 +114,7 @@ void bdrv_iostatus_disable(BlockDriverState *bs); bool bdrv_iostatus_is_enabled(const BlockDriverState *bs); void bdrv_iostatus_set_err(BlockDriverState *bs, int error); void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, - BlockQMPEventAction action, int is_read); + BlockErrorAction action, int is_read); void bdrv_info_print(Monitor *mon, const QObject *data); void bdrv_info(Monitor *mon, QObject **ret_data); void bdrv_stats_print(Monitor *mon, const QObject *data); @@ -284,9 +284,9 @@ int bdrv_has_zero_init(BlockDriverState *bs); int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum); -void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error, - BlockErrorAction on_write_error); -BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read); +void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error, + BlockdevOnError on_write_error); +BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, int is_read); int bdrv_is_read_only(BlockDriverState *bs); int bdrv_is_sg(BlockDriverState *bs); int bdrv_enable_write_cache(BlockDriverState *bs); diff --git a/block_int.h b/block_int.h index 61dc73b0e4..b98c770b96 100644 --- a/block_int.h +++ b/block_int.h @@ -262,7 +262,7 @@ struct BlockDriverState { /* NOTE: the following infos are only hints for real hardware drivers. They are not used by the block driver */ - BlockErrorAction on_read_error, on_write_error; + BlockdevOnError on_read_error, on_write_error; bool iostatus_enabled; BlockDeviceIoStatus iostatus; char device_name[32]; diff --git a/hw/ide/core.c b/hw/ide/core.c index d6fb69c634..57b9fa458d 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -557,7 +557,7 @@ void ide_dma_error(IDEState *s) static int ide_handle_rw_error(IDEState *s, int error, int op) { int is_read = (op & BM_STATUS_RETRY_READ); - BlockErrorAction action = bdrv_get_on_error(s->bs, is_read); + BlockdevOnError action = bdrv_get_on_error(s->bs, is_read); if (action == BLOCK_ERR_IGNORE) { bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_IGNORE, is_read); diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 95e91585e6..fef83a3606 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -388,7 +388,7 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error) { int is_read = (r->req.cmd.xfer == SCSI_XFER_FROM_DEV); SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); - BlockErrorAction action = bdrv_get_on_error(s->qdev.conf.bs, is_read); + BlockdevOnError action = bdrv_get_on_error(s->qdev.conf.bs, is_read); if (action == BLOCK_ERR_IGNORE) { bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_IGNORE, is_read); diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 6f6d172fd0..01e537dc9b 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -66,7 +66,7 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, int status) static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, int is_read) { - BlockErrorAction action = bdrv_get_on_error(req->dev->bs, is_read); + BlockdevOnError action = bdrv_get_on_error(req->dev->bs, is_read); VirtIOBlock *s = req->dev; if (action == BLOCK_ERR_IGNORE) { From 92aa5c6d77ac29574c1717bcf57827fa1e586f31 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:22:55 +0200 Subject: [PATCH 0654/2270] iostatus: move BlockdevOnError declaration to QAPI This will let block-stream reuse the enum. Places that used the enums are renamed accordingly. Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- block.c | 6 +++--- block.h | 5 ----- block/commit.c | 14 +++++++------- block_int.h | 2 +- blockdev.c | 14 +++++++------- hw/fdc.c | 4 ++-- hw/ide/core.c | 6 +++--- hw/scsi-disk.c | 6 +++--- hw/scsi-generic.c | 4 ++-- hw/virtio-blk.c | 6 +++--- qapi-schema.json | 23 +++++++++++++++++++++++ 11 files changed, 54 insertions(+), 36 deletions(-) diff --git a/block.c b/block.c index 7b4508295c..1c3ebd7858 100644 --- a/block.c +++ b/block.c @@ -4209,9 +4209,9 @@ void bdrv_iostatus_enable(BlockDriverState *bs) bool bdrv_iostatus_is_enabled(const BlockDriverState *bs) { return (bs->iostatus_enabled && - (bs->on_write_error == BLOCK_ERR_STOP_ENOSPC || - bs->on_write_error == BLOCK_ERR_STOP_ANY || - bs->on_read_error == BLOCK_ERR_STOP_ANY)); + (bs->on_write_error == BLOCKDEV_ON_ERROR_ENOSPC || + bs->on_write_error == BLOCKDEV_ON_ERROR_STOP || + bs->on_read_error == BLOCKDEV_ON_ERROR_STOP)); } void bdrv_iostatus_disable(BlockDriverState *bs) diff --git a/block.h b/block.h index 038621f426..ee81129456 100644 --- a/block.h +++ b/block.h @@ -90,11 +90,6 @@ typedef struct BlockDevOps { #define BDRV_SECTOR_SIZE (1ULL << BDRV_SECTOR_BITS) #define BDRV_SECTOR_MASK ~(BDRV_SECTOR_SIZE - 1) -typedef enum { - BLOCK_ERR_REPORT, BLOCK_ERR_IGNORE, BLOCK_ERR_STOP_ENOSPC, - BLOCK_ERR_STOP_ANY -} BlockdevOnError; - typedef enum { BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP } BlockErrorAction; diff --git a/block/commit.c b/block/commit.c index cabb470b5b..733c91403c 100644 --- a/block/commit.c +++ b/block/commit.c @@ -34,7 +34,7 @@ typedef struct CommitBlockJob { BlockDriverState *active; BlockDriverState *top; BlockDriverState *base; - BlockErrorAction on_error; + BlockdevOnError on_error; int base_flags; int orig_overlay_flags; } CommitBlockJob; @@ -126,9 +126,9 @@ wait: bytes_written += n * BDRV_SECTOR_SIZE; } if (ret < 0) { - if (s->on_error == BLOCK_ERR_STOP_ANY || - s->on_error == BLOCK_ERR_REPORT || - (s->on_error == BLOCK_ERR_STOP_ENOSPC && ret == -ENOSPC)) { + if (s->on_error == BLOCKDEV_ON_ERROR_STOP || + s->on_error == BLOCKDEV_ON_ERROR_REPORT|| + (s->on_error == BLOCKDEV_ON_ERROR_ENOSPC && ret == -ENOSPC)) { goto exit_free_buf; } else { n = 0; @@ -182,7 +182,7 @@ static BlockJobType commit_job_type = { void commit_start(BlockDriverState *bs, BlockDriverState *base, BlockDriverState *top, int64_t speed, - BlockErrorAction on_error, BlockDriverCompletionFunc *cb, + BlockdevOnError on_error, BlockDriverCompletionFunc *cb, void *opaque, Error **errp) { CommitBlockJob *s; @@ -192,8 +192,8 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base, BlockDriverState *overlay_bs; Error *local_err = NULL; - if ((on_error == BLOCK_ERR_STOP_ANY || - on_error == BLOCK_ERR_STOP_ENOSPC) && + if ((on_error == BLOCKDEV_ON_ERROR_STOP || + on_error == BLOCKDEV_ON_ERROR_ENOSPC) && !bdrv_iostatus_is_enabled(bs)) { error_set(errp, QERR_INVALID_PARAMETER_COMBINATION); return; diff --git a/block_int.h b/block_int.h index b98c770b96..615aafca8e 100644 --- a/block_int.h +++ b/block_int.h @@ -323,7 +323,7 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base, */ void commit_start(BlockDriverState *bs, BlockDriverState *base, BlockDriverState *top, int64_t speed, - BlockErrorAction on_error, BlockDriverCompletionFunc *cb, + BlockdevOnError on_error, BlockDriverCompletionFunc *cb, void *opaque, Error **errp); #endif /* BLOCK_INT_H */ diff --git a/blockdev.c b/blockdev.c index f097e5743a..63307154b0 100644 --- a/blockdev.c +++ b/blockdev.c @@ -241,13 +241,13 @@ static void drive_put_ref_bh_schedule(DriveInfo *dinfo) static int parse_block_error_action(const char *buf, int is_read) { if (!strcmp(buf, "ignore")) { - return BLOCK_ERR_IGNORE; + return BLOCKDEV_ON_ERROR_IGNORE; } else if (!is_read && !strcmp(buf, "enospc")) { - return BLOCK_ERR_STOP_ENOSPC; + return BLOCKDEV_ON_ERROR_ENOSPC; } else if (!strcmp(buf, "stop")) { - return BLOCK_ERR_STOP_ANY; + return BLOCKDEV_ON_ERROR_STOP; } else if (!strcmp(buf, "report")) { - return BLOCK_ERR_REPORT; + return BLOCKDEV_ON_ERROR_REPORT; } else { error_report("'%s' invalid %s error action", buf, is_read ? "read" : "write"); @@ -433,7 +433,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) return NULL; } - on_write_error = BLOCK_ERR_STOP_ENOSPC; + on_write_error = BLOCKDEV_ON_ERROR_ENOSPC; if ((buf = qemu_opt_get(opts, "werror")) != NULL) { if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) { error_report("werror is not supported by this bus type"); @@ -446,7 +446,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) } } - on_read_error = BLOCK_ERR_REPORT; + on_read_error = BLOCKDEV_ON_ERROR_REPORT; if ((buf = qemu_opt_get(opts, "rerror")) != NULL) { if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI && type != IF_NONE) { error_report("rerror is not supported by this bus type"); @@ -1143,7 +1143,7 @@ void qmp_block_commit(const char *device, /* This will be part of the QMP command, if/when the * BlockdevOnError change for blkmirror makes it in */ - BlockErrorAction on_error = BLOCK_ERR_REPORT; + BlockdevOnError on_error = BLOCKDEV_ON_ERROR_REPORT; /* drain all i/o before commits */ bdrv_drain_all(); diff --git a/hw/fdc.c b/hw/fdc.c index 08830c1ba2..43b0f20503 100644 --- a/hw/fdc.c +++ b/hw/fdc.c @@ -1994,11 +1994,11 @@ static int fdctrl_connect_drives(FDCtrl *fdctrl) drive->fdctrl = fdctrl; if (drive->bs) { - if (bdrv_get_on_error(drive->bs, 0) != BLOCK_ERR_STOP_ENOSPC) { + if (bdrv_get_on_error(drive->bs, 0) != BLOCKDEV_ON_ERROR_ENOSPC) { error_report("fdc doesn't support drive option werror"); return -1; } - if (bdrv_get_on_error(drive->bs, 1) != BLOCK_ERR_REPORT) { + if (bdrv_get_on_error(drive->bs, 1) != BLOCKDEV_ON_ERROR_REPORT) { error_report("fdc doesn't support drive option rerror"); return -1; } diff --git a/hw/ide/core.c b/hw/ide/core.c index 57b9fa458d..2620e87ae4 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -559,13 +559,13 @@ static int ide_handle_rw_error(IDEState *s, int error, int op) int is_read = (op & BM_STATUS_RETRY_READ); BlockdevOnError action = bdrv_get_on_error(s->bs, is_read); - if (action == BLOCK_ERR_IGNORE) { + if (action == BLOCKDEV_ON_ERROR_IGNORE) { bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_IGNORE, is_read); return 0; } - if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC) - || action == BLOCK_ERR_STOP_ANY) { + if ((error == ENOSPC && action == BLOCKDEV_ON_ERROR_ENOSPC) + || action == BLOCKDEV_ON_ERROR_STOP) { s->bus->dma->ops->set_unit(s->bus->dma, s->unit); s->bus->error_status = op; bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_STOP, is_read); diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index fef83a3606..c295326e99 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -390,13 +390,13 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error) SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); BlockdevOnError action = bdrv_get_on_error(s->qdev.conf.bs, is_read); - if (action == BLOCK_ERR_IGNORE) { + if (action == BLOCKDEV_ON_ERROR_IGNORE) { bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_IGNORE, is_read); return 0; } - if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC) - || action == BLOCK_ERR_STOP_ANY) { + if ((error == ENOSPC && action == BLOCKDEV_ON_ERROR_ENOSPC) + || action == BLOCKDEV_ON_ERROR_STOP) { bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_STOP, is_read); vm_stop(RUN_STATE_IO_ERROR); diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index a5eb663ecf..d9045341ba 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -400,11 +400,11 @@ static int scsi_generic_initfn(SCSIDevice *s) return -1; } - if (bdrv_get_on_error(s->conf.bs, 0) != BLOCK_ERR_STOP_ENOSPC) { + if (bdrv_get_on_error(s->conf.bs, 0) != BLOCKDEV_ON_ERROR_ENOSPC) { error_report("Device doesn't support drive option werror"); return -1; } - if (bdrv_get_on_error(s->conf.bs, 1) != BLOCK_ERR_REPORT) { + if (bdrv_get_on_error(s->conf.bs, 1) != BLOCKDEV_ON_ERROR_REPORT) { error_report("Device doesn't support drive option rerror"); return -1; } diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 01e537dc9b..f178fa86c7 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -69,13 +69,13 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, BlockdevOnError action = bdrv_get_on_error(req->dev->bs, is_read); VirtIOBlock *s = req->dev; - if (action == BLOCK_ERR_IGNORE) { + if (action == BLOCKDEV_ON_ERROR_IGNORE) { bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_IGNORE, is_read); return 0; } - if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC) - || action == BLOCK_ERR_STOP_ANY) { + if ((error == ENOSPC && action == BLOCKDEV_ON_ERROR_ENOSPC) + || action == BLOCKDEV_ON_ERROR_STOP) { req->next = s->rq; s->rq = req; bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_STOP, is_read); diff --git a/qapi-schema.json b/qapi-schema.json index 0f2b1a0a1d..a7264135a1 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1087,6 +1087,29 @@ ## { 'command': 'query-pci', 'returns': ['PciInfo'] } +## +# @BlockdevOnError: +# +# An enumeration of possible behaviors for errors on I/O operations. +# The exact meaning depends on whether the I/O was initiated by a guest +# or by a block job +# +# @report: for guest operations, report the error to the guest; +# for jobs, cancel the job +# +# @ignore: ignore the error, only report a QMP event (BLOCK_IO_ERROR +# or BLOCK_JOB_ERROR) +# +# @enospc: same as @stop on ENOSPC, same as @report otherwise. +# +# @stop: for guest operations, stop the virtual machine; +# for jobs, pause the job +# +# Since: 1.3 +## +{ 'enum': 'BlockdevOnError', + 'data': ['report', 'ignore', 'enospc', 'stop'] } + ## # @BlockJobInfo: # From 1ceee0d5cc841fc9ca8e72b81450b598ab307f14 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:22:56 +0200 Subject: [PATCH 0655/2270] iostatus: change is_read to a bool Do this while we are touching this part of the code, before introducing more uses of "int is_read". Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- block.c | 4 ++-- block.h | 4 ++-- blockdev.c | 2 +- hw/ide/core.c | 2 +- hw/ide/pci.c | 4 ++-- hw/scsi-disk.c | 2 +- hw/virtio-blk.c | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/block.c b/block.c index 1c3ebd7858..0bae0461d0 100644 --- a/block.c +++ b/block.c @@ -1387,7 +1387,7 @@ void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, } void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, - BlockErrorAction action, int is_read) + BlockErrorAction action, bool is_read) { QObject *data; const char *action_str; @@ -2481,7 +2481,7 @@ void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error, bs->on_write_error = on_write_error; } -BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, int is_read) +BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, bool is_read) { return is_read ? bs->on_read_error : bs->on_write_error; } diff --git a/block.h b/block.h index ee81129456..47dd905bc4 100644 --- a/block.h +++ b/block.h @@ -109,7 +109,7 @@ void bdrv_iostatus_disable(BlockDriverState *bs); bool bdrv_iostatus_is_enabled(const BlockDriverState *bs); void bdrv_iostatus_set_err(BlockDriverState *bs, int error); void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, - BlockErrorAction action, int is_read); + BlockErrorAction action, bool is_read); void bdrv_info_print(Monitor *mon, const QObject *data); void bdrv_info(Monitor *mon, QObject **ret_data); void bdrv_stats_print(Monitor *mon, const QObject *data); @@ -281,7 +281,7 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error, BlockdevOnError on_write_error); -BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, int is_read); +BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, bool is_read); int bdrv_is_read_only(BlockDriverState *bs); int bdrv_is_sg(BlockDriverState *bs); int bdrv_enable_write_cache(BlockDriverState *bs); diff --git a/blockdev.c b/blockdev.c index 63307154b0..d52a830769 100644 --- a/blockdev.c +++ b/blockdev.c @@ -238,7 +238,7 @@ static void drive_put_ref_bh_schedule(DriveInfo *dinfo) qemu_bh_schedule(s->bh); } -static int parse_block_error_action(const char *buf, int is_read) +static int parse_block_error_action(const char *buf, bool is_read) { if (!strcmp(buf, "ignore")) { return BLOCKDEV_ON_ERROR_IGNORE; diff --git a/hw/ide/core.c b/hw/ide/core.c index 2620e87ae4..c03db4a3a2 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -556,7 +556,7 @@ void ide_dma_error(IDEState *s) static int ide_handle_rw_error(IDEState *s, int error, int op) { - int is_read = (op & BM_STATUS_RETRY_READ); + bool is_read = (op & BM_STATUS_RETRY_READ) != 0; BlockdevOnError action = bdrv_get_on_error(s->bs, is_read); if (action == BLOCKDEV_ON_ERROR_IGNORE) { diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 88c0942e34..644533f777 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -188,7 +188,7 @@ static void bmdma_restart_bh(void *opaque) { BMDMAState *bm = opaque; IDEBus *bus = bm->bus; - int is_read; + bool is_read; int error_status; qemu_bh_delete(bm->bh); @@ -198,7 +198,7 @@ static void bmdma_restart_bh(void *opaque) return; } - is_read = !!(bus->error_status & BM_STATUS_RETRY_READ); + is_read = (bus->error_status & BM_STATUS_RETRY_READ) != 0; /* The error status must be cleared before resubmitting the request: The * request may fail again, and this case can only be distinguished if the diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index c295326e99..2dd99a90a9 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -386,7 +386,7 @@ static void scsi_read_data(SCSIRequest *req) */ static int scsi_handle_rw_error(SCSIDiskReq *r, int error) { - int is_read = (r->req.cmd.xfer == SCSI_XFER_FROM_DEV); + bool is_read = (r->req.cmd.xfer == SCSI_XFER_FROM_DEV); SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); BlockdevOnError action = bdrv_get_on_error(s->qdev.conf.bs, is_read); diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index f178fa86c7..1ac2483b53 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -64,7 +64,7 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, int status) } static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, - int is_read) + bool is_read) { BlockdevOnError action = bdrv_get_on_error(req->dev->bs, is_read); VirtIOBlock *s = req->dev; @@ -98,7 +98,7 @@ static void virtio_blk_rw_complete(void *opaque, int ret) trace_virtio_blk_rw_complete(req, ret); if (ret) { - int is_read = !(ldl_p(&req->out->type) & VIRTIO_BLK_T_OUT); + bool is_read = !(ldl_p(&req->out->type) & VIRTIO_BLK_T_OUT); if (virtio_blk_handle_rw_error(req, -ret, is_read)) return; } From 3e1caa5f76a9104a0d574b0f28b3dafe986a8408 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:22:57 +0200 Subject: [PATCH 0656/2270] iostatus: reorganize io error code Move the common part of IDE/SCSI/virtio error handling to the block layer. The new function bdrv_error_action subsumes all three of bdrv_emit_qmp_error_event, vm_stop, bdrv_iostatus_set_err. The same scheme will be used for errors in block jobs. Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- block.c | 46 ++++++++++++++++++++++++++++++++++++++-------- block.h | 5 +++-- hw/ide/core.c | 20 +++++--------------- hw/scsi-disk.c | 23 +++++++---------------- hw/virtio-blk.c | 19 +++++-------------- qemu-tool.c | 6 ++++++ 6 files changed, 64 insertions(+), 55 deletions(-) diff --git a/block.c b/block.c index 0bae0461d0..8b0ba6722a 100644 --- a/block.c +++ b/block.c @@ -29,6 +29,7 @@ #include "blockjob.h" #include "module.h" #include "qjson.h" +#include "sysemu.h" #include "qemu-coroutine.h" #include "qmp-commands.h" #include "qemu-timer.h" @@ -1386,8 +1387,8 @@ void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, } } -void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, - BlockErrorAction action, bool is_read) +static void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, + BlockErrorAction action, bool is_read) { QObject *data; const char *action_str; @@ -2486,6 +2487,39 @@ BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, bool is_read) return is_read ? bs->on_read_error : bs->on_write_error; } +BlockErrorAction bdrv_get_error_action(BlockDriverState *bs, bool is_read, int error) +{ + BlockdevOnError on_err = is_read ? bs->on_read_error : bs->on_write_error; + + switch (on_err) { + case BLOCKDEV_ON_ERROR_ENOSPC: + return (error == ENOSPC) ? BDRV_ACTION_STOP : BDRV_ACTION_REPORT; + case BLOCKDEV_ON_ERROR_STOP: + return BDRV_ACTION_STOP; + case BLOCKDEV_ON_ERROR_REPORT: + return BDRV_ACTION_REPORT; + case BLOCKDEV_ON_ERROR_IGNORE: + return BDRV_ACTION_IGNORE; + default: + abort(); + } +} + +/* This is done by device models because, while the block layer knows + * about the error, it does not know whether an operation comes from + * the device or the block layer (from a job, for example). + */ +void bdrv_error_action(BlockDriverState *bs, BlockErrorAction action, + bool is_read, int error) +{ + assert(error >= 0); + bdrv_emit_qmp_error_event(bs, action, is_read); + if (action == BDRV_ACTION_STOP) { + vm_stop(RUN_STATE_IO_ERROR); + bdrv_iostatus_set_err(bs, error); + } +} + int bdrv_is_read_only(BlockDriverState *bs) { return bs->read_only; @@ -4226,14 +4260,10 @@ void bdrv_iostatus_reset(BlockDriverState *bs) } } -/* XXX: Today this is set by device models because it makes the implementation - quite simple. However, the block layer knows about the error, so it's - possible to implement this without device models being involved */ void bdrv_iostatus_set_err(BlockDriverState *bs, int error) { - if (bdrv_iostatus_is_enabled(bs) && - bs->iostatus == BLOCK_DEVICE_IO_STATUS_OK) { - assert(error >= 0); + assert(bdrv_iostatus_is_enabled(bs)); + if (bs->iostatus == BLOCK_DEVICE_IO_STATUS_OK) { bs->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE : BLOCK_DEVICE_IO_STATUS_FAILED; } diff --git a/block.h b/block.h index 47dd905bc4..e2d89d7bc1 100644 --- a/block.h +++ b/block.h @@ -108,8 +108,6 @@ void bdrv_iostatus_reset(BlockDriverState *bs); void bdrv_iostatus_disable(BlockDriverState *bs); bool bdrv_iostatus_is_enabled(const BlockDriverState *bs); void bdrv_iostatus_set_err(BlockDriverState *bs, int error); -void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, - BlockErrorAction action, bool is_read); void bdrv_info_print(Monitor *mon, const QObject *data); void bdrv_info(Monitor *mon, QObject **ret_data); void bdrv_stats_print(Monitor *mon, const QObject *data); @@ -282,6 +280,9 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error, BlockdevOnError on_write_error); BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, bool is_read); +BlockErrorAction bdrv_get_error_action(BlockDriverState *bs, bool is_read, int error); +void bdrv_error_action(BlockDriverState *bs, BlockErrorAction action, + bool is_read, int error); int bdrv_is_read_only(BlockDriverState *bs); int bdrv_is_sg(BlockDriverState *bs); int bdrv_enable_write_cache(BlockDriverState *bs); diff --git a/hw/ide/core.c b/hw/ide/core.c index c03db4a3a2..d683a8cc84 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -557,31 +557,21 @@ void ide_dma_error(IDEState *s) static int ide_handle_rw_error(IDEState *s, int error, int op) { bool is_read = (op & BM_STATUS_RETRY_READ) != 0; - BlockdevOnError action = bdrv_get_on_error(s->bs, is_read); + BlockErrorAction action = bdrv_get_error_action(s->bs, is_read, error); - if (action == BLOCKDEV_ON_ERROR_IGNORE) { - bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_IGNORE, is_read); - return 0; - } - - if ((error == ENOSPC && action == BLOCKDEV_ON_ERROR_ENOSPC) - || action == BLOCKDEV_ON_ERROR_STOP) { + if (action == BDRV_ACTION_STOP) { s->bus->dma->ops->set_unit(s->bus->dma, s->unit); s->bus->error_status = op; - bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_STOP, is_read); - vm_stop(RUN_STATE_IO_ERROR); - bdrv_iostatus_set_err(s->bs, error); - } else { + } else if (action == BDRV_ACTION_REPORT) { if (op & BM_STATUS_DMA_RETRY) { dma_buf_commit(s); ide_dma_error(s); } else { ide_rw_error(s); } - bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_REPORT, is_read); } - - return 1; + bdrv_error_action(s->bs, action, is_read, error); + return action != BDRV_ACTION_IGNORE; } void ide_dma_cb(void *opaque, int ret) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 2dd99a90a9..99bb02ebf8 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -388,21 +388,9 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error) { bool is_read = (r->req.cmd.xfer == SCSI_XFER_FROM_DEV); SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); - BlockdevOnError action = bdrv_get_on_error(s->qdev.conf.bs, is_read); + BlockErrorAction action = bdrv_get_error_action(s->qdev.conf.bs, is_read, error); - if (action == BLOCKDEV_ON_ERROR_IGNORE) { - bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_IGNORE, is_read); - return 0; - } - - if ((error == ENOSPC && action == BLOCKDEV_ON_ERROR_ENOSPC) - || action == BLOCKDEV_ON_ERROR_STOP) { - - bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_STOP, is_read); - vm_stop(RUN_STATE_IO_ERROR); - bdrv_iostatus_set_err(s->qdev.conf.bs, error); - scsi_req_retry(&r->req); - } else { + if (action == BDRV_ACTION_REPORT) { switch (error) { case ENOMEDIUM: scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); @@ -417,9 +405,12 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error) scsi_check_condition(r, SENSE_CODE(IO_ERROR)); break; } - bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_REPORT, is_read); } - return 1; + bdrv_error_action(s->qdev.conf.bs, action, is_read, error); + if (action == BDRV_ACTION_STOP) { + scsi_req_retry(&r->req); + } + return action != BDRV_ACTION_IGNORE; } static void scsi_write_complete(void * opaque, int ret) diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 1ac2483b53..e25cc96477 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -66,29 +66,20 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, int status) static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, bool is_read) { - BlockdevOnError action = bdrv_get_on_error(req->dev->bs, is_read); + BlockErrorAction action = bdrv_get_error_action(req->dev->bs, is_read, error); VirtIOBlock *s = req->dev; - if (action == BLOCKDEV_ON_ERROR_IGNORE) { - bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_IGNORE, is_read); - return 0; - } - - if ((error == ENOSPC && action == BLOCKDEV_ON_ERROR_ENOSPC) - || action == BLOCKDEV_ON_ERROR_STOP) { + if (action == BDRV_ACTION_STOP) { req->next = s->rq; s->rq = req; - bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_STOP, is_read); - vm_stop(RUN_STATE_IO_ERROR); - bdrv_iostatus_set_err(s->bs, error); - } else { + } else if (action == BDRV_ACTION_REPORT) { virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR); bdrv_acct_done(s->bs, &req->acct); g_free(req); - bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_REPORT, is_read); } - return 1; + bdrv_error_action(s->bs, action, is_read, error); + return action != BDRV_ACTION_IGNORE; } static void virtio_blk_rw_complete(void *opaque, int ret) diff --git a/qemu-tool.c b/qemu-tool.c index 18205babab..f2f98138ce 100644 --- a/qemu-tool.c +++ b/qemu-tool.c @@ -19,6 +19,7 @@ #include "qemu-log.h" #include "migration.h" #include "main-loop.h" +#include "sysemu.h" #include "qemu_socket.h" #include "slirp/libslirp.h" @@ -37,6 +38,11 @@ const char *qemu_get_vm_name(void) Monitor *cur_mon; +void vm_stop(RunState state) +{ + abort(); +} + int monitor_cur_is_qmp(void) { return 0; From 32c81a4a6ecc3f50efc9c270a269e4d3d8a9fbd5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:22:58 +0200 Subject: [PATCH 0657/2270] block: introduce block job error The following behaviors are possible: 'report': The behavior is the same as in 1.1. An I/O error, respectively during a read or a write, will complete the job immediately with an error code. 'ignore': An I/O error, respectively during a read or a write, will be ignored. For streaming, the job will complete with an error and the backing file will be left in place. For mirroring, the sector will be marked again as dirty and re-examined later. 'stop': The job will be paused and the job iostatus will be set to failed or nospace, while the VM will keep running. This can only be specified if the block device has rerror=stop and werror=stop or enospc. 'enospc': Behaves as 'stop' for ENOSPC errors, 'report' for others. In all cases, even for 'report', the I/O error is reported as a QMP event BLOCK_JOB_ERROR, with the same arguments as BLOCK_IO_ERROR. It is possible that while stopping the VM a BLOCK_IO_ERROR event will be reported and will clobber the event from BLOCK_JOB_ERROR, or vice versa. This is not really avoidable since stopping the VM completes all pending I/O requests. In fact, it is already possible now that a series of BLOCK_IO_ERROR events are reported with rerror=stop, because vm_stop calls bdrv_drain_all and this can generate further errors. Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- QMP/qmp-events.txt | 22 ++++++++++++++++ block.c | 9 ++++--- block_int.h | 4 +++ blockjob.c | 63 ++++++++++++++++++++++++++++++++++++++++------ blockjob.h | 25 ++++++++++++++++++ monitor.c | 1 + monitor.h | 1 + qapi-schema.json | 7 +++++- 8 files changed, 120 insertions(+), 12 deletions(-) diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt index 4491020423..987c5756b3 100644 --- a/QMP/qmp-events.txt +++ b/QMP/qmp-events.txt @@ -96,6 +96,28 @@ Example: "speed": 0 }, "timestamp": { "seconds": 1267061043, "microseconds": 959568 } } +BLOCK_JOB_ERROR +--------------- + +Emitted when a block job encounters an error. + +Data: + +- "device": device name (json-string) +- "operation": I/O operation (json-string, "read" or "write") +- "action": action that has been taken, it's one of the following (json-string): + "ignore": error has been ignored, the job may fail later + "report": error will be reported and the job canceled + "stop": error caused job to be paused + +Example: + +{ "event": "BLOCK_JOB_ERROR", + "data": { "device": "ide0-hd1", + "operation": "write", + "action": "stop" }, + "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } + DEVICE_TRAY_MOVED ----------------- diff --git a/block.c b/block.c index 8b0ba6722a..c108a76952 100644 --- a/block.c +++ b/block.c @@ -1387,8 +1387,9 @@ void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, } } -static void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, - BlockErrorAction action, bool is_read) +void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, + enum MonitorEvent ev, + BlockErrorAction action, bool is_read) { QObject *data; const char *action_str; @@ -1411,7 +1412,7 @@ static void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, bdrv->device_name, action_str, is_read ? "read" : "write"); - monitor_protocol_event(QEVENT_BLOCK_IO_ERROR, data); + monitor_protocol_event(ev, data); qobject_decref(data); } @@ -2513,7 +2514,7 @@ void bdrv_error_action(BlockDriverState *bs, BlockErrorAction action, bool is_read, int error) { assert(error >= 0); - bdrv_emit_qmp_error_event(bs, action, is_read); + bdrv_emit_qmp_error_event(bs, QEVENT_BLOCK_IO_ERROR, action, is_read); if (action == BDRV_ACTION_STOP) { vm_stop(RUN_STATE_IO_ERROR); bdrv_iostatus_set_err(bs, error); diff --git a/block_int.h b/block_int.h index 615aafca8e..785d43d61a 100644 --- a/block_int.h +++ b/block_int.h @@ -31,6 +31,7 @@ #include "qemu-timer.h" #include "qapi-types.h" #include "qerror.h" +#include "monitor.h" #define BLOCK_FLAG_ENCRYPT 1 #define BLOCK_FLAG_COMPAT6 4 @@ -286,6 +287,9 @@ void bdrv_set_io_limits(BlockDriverState *bs, #ifdef _WIN32 int is_windows_drive(const char *filename); #endif +void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, + enum MonitorEvent ev, + BlockErrorAction action, bool is_read); /** * stream_start: diff --git a/blockjob.c b/blockjob.c index 8219f73979..f55f55a193 100644 --- a/blockjob.c +++ b/blockjob.c @@ -112,6 +112,7 @@ bool block_job_is_paused(BlockJob *job) void block_job_resume(BlockJob *job) { job->paused = false; + block_job_iostatus_reset(job); if (job->co && !job->busy) { qemu_coroutine_enter(job->co, NULL); } @@ -128,6 +129,11 @@ bool block_job_is_cancelled(BlockJob *job) return job->cancelled; } +void block_job_iostatus_reset(BlockJob *job) +{ + job->iostatus = BLOCK_DEVICE_IO_STATUS_OK; +} + struct BlockCancelData { BlockJob *job; BlockDriverCompletionFunc *cb; @@ -189,12 +195,55 @@ void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns) BlockJobInfo *block_job_query(BlockJob *job) { BlockJobInfo *info = g_new0(BlockJobInfo, 1); - info->type = g_strdup(job->job_type->job_type); - info->device = g_strdup(bdrv_get_device_name(job->bs)); - info->len = job->len; - info->busy = job->busy; - info->paused = job->paused; - info->offset = job->offset; - info->speed = job->speed; + info->type = g_strdup(job->job_type->job_type); + info->device = g_strdup(bdrv_get_device_name(job->bs)); + info->len = job->len; + info->busy = job->busy; + info->paused = job->paused; + info->offset = job->offset; + info->speed = job->speed; + info->io_status = job->iostatus; return info; } + +static void block_job_iostatus_set_err(BlockJob *job, int error) +{ + if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) { + job->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE : + BLOCK_DEVICE_IO_STATUS_FAILED; + } +} + + +BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs, + BlockdevOnError on_err, + int is_read, int error) +{ + BlockErrorAction action; + + switch (on_err) { + case BLOCKDEV_ON_ERROR_ENOSPC: + action = (error == ENOSPC) ? BDRV_ACTION_STOP : BDRV_ACTION_REPORT; + break; + case BLOCKDEV_ON_ERROR_STOP: + action = BDRV_ACTION_STOP; + break; + case BLOCKDEV_ON_ERROR_REPORT: + action = BDRV_ACTION_REPORT; + break; + case BLOCKDEV_ON_ERROR_IGNORE: + action = BDRV_ACTION_IGNORE; + break; + default: + abort(); + } + bdrv_emit_qmp_error_event(job->bs, QEVENT_BLOCK_JOB_ERROR, action, is_read); + if (action == BDRV_ACTION_STOP) { + block_job_pause(job); + block_job_iostatus_set_err(job, error); + if (bs != job->bs) { + bdrv_iostatus_set_err(bs, error); + } + } + return action; +} diff --git a/blockjob.h b/blockjob.h index ece5afa75b..930cc3c46a 100644 --- a/blockjob.h +++ b/blockjob.h @@ -82,6 +82,9 @@ struct BlockJob { */ bool busy; + /** Status that is published by the query-block-jobs QMP API */ + BlockDeviceIoStatus iostatus; + /** Offset that is published by the query-block-jobs QMP API */ int64_t offset; @@ -215,4 +218,26 @@ bool block_job_is_paused(BlockJob *job); */ int block_job_cancel_sync(BlockJob *job); +/** + * block_job_iostatus_reset: + * @job: The job whose I/O status should be reset. + * + * Reset I/O status on @job. + */ +void block_job_iostatus_reset(BlockJob *job); + +/** + * block_job_error_action: + * @job: The job to signal an error for. + * @bs: The block device on which to set an I/O error. + * @on_err: The error action setting. + * @is_read: Whether the operation was a read. + * @error: The error that was reported. + * + * Report an I/O error for a block job and possibly stop the VM. Return the + * action that was selected based on @on_err and @error. + */ +BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs, + BlockdevOnError on_err, + int is_read, int error); #endif diff --git a/monitor.c b/monitor.c index 67064e2706..d4bd5feb60 100644 --- a/monitor.c +++ b/monitor.c @@ -450,6 +450,7 @@ static const char *monitor_event_names[] = { [QEVENT_SPICE_DISCONNECTED] = "SPICE_DISCONNECTED", [QEVENT_BLOCK_JOB_COMPLETED] = "BLOCK_JOB_COMPLETED", [QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED", + [QEVENT_BLOCK_JOB_ERROR] = "BLOCK_JOB_ERROR", [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED", [QEVENT_SUSPEND] = "SUSPEND", [QEVENT_SUSPEND_DISK] = "SUSPEND_DISK", diff --git a/monitor.h b/monitor.h index 64c1561844..43040af1c2 100644 --- a/monitor.h +++ b/monitor.h @@ -38,6 +38,7 @@ typedef enum MonitorEvent { QEVENT_SPICE_DISCONNECTED, QEVENT_BLOCK_JOB_COMPLETED, QEVENT_BLOCK_JOB_CANCELLED, + QEVENT_BLOCK_JOB_ERROR, QEVENT_DEVICE_TRAY_MOVED, QEVENT_SUSPEND, QEVENT_SUSPEND_DISK, diff --git a/qapi-schema.json b/qapi-schema.json index a7264135a1..14e7a0d686 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1131,11 +1131,14 @@ # # @speed: the rate limit, bytes per second # +# @io-status: the status of the job (since 1.3) +# # Since: 1.1 ## { 'type': 'BlockJobInfo', 'data': {'type': 'str', 'device': 'str', 'len': 'int', - 'offset': 'int', 'busy': 'bool', 'paused': 'bool', 'speed': 'int'} } + 'offset': 'int', 'busy': 'bool', 'paused': 'bool', 'speed': 'int', + 'io-status': 'BlockDeviceIoStatus'} } ## # @query-block-jobs: @@ -1958,6 +1961,8 @@ # operation. It is an error to call this command if no operation is in # progress. Resuming an already running job is not an error. # +# This command also clears the error status of the job. +# # @device: the device name # # Returns: Nothing on success From 1d809098aa9518cda41c2cf6e660d3d602614907 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:22:59 +0200 Subject: [PATCH 0658/2270] stream: add on-error argument This patch adds support for error management to streaming. Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- block/stream.c | 28 +++++++++++++++++++++++++++- block_int.h | 3 ++- blockdev.c | 11 ++++++++--- hmp.c | 3 ++- qapi-schema.json | 9 +++++++-- qmp-commands.hx | 2 +- 6 files changed, 47 insertions(+), 9 deletions(-) diff --git a/block/stream.c b/block/stream.c index 57e4be7c64..792665276e 100644 --- a/block/stream.c +++ b/block/stream.c @@ -31,6 +31,7 @@ typedef struct StreamBlockJob { BlockJob common; RateLimit limit; BlockDriverState *base; + BlockdevOnError on_error; char backing_file_id[1024]; } StreamBlockJob; @@ -78,6 +79,7 @@ static void coroutine_fn stream_run(void *opaque) BlockDriverState *bs = s->common.bs; BlockDriverState *base = s->base; int64_t sector_num, end; + int error = 0; int ret = 0; int n = 0; void *buf; @@ -142,7 +144,19 @@ wait: ret = stream_populate(bs, sector_num, n, buf); } if (ret < 0) { - break; + BlockErrorAction action = + block_job_error_action(&s->common, s->common.bs, s->on_error, + true, -ret); + if (action == BDRV_ACTION_STOP) { + n = 0; + continue; + } + if (error == 0) { + error = ret; + } + if (action == BDRV_ACTION_REPORT) { + break; + } } ret = 0; @@ -154,6 +168,9 @@ wait: bdrv_disable_copy_on_read(bs); } + /* Do not remove the backing file if an error was there but ignored. */ + ret = error; + if (!block_job_is_cancelled(&s->common) && sector_num == end && ret == 0) { const char *base_id = NULL, *base_fmt = NULL; if (base) { @@ -189,11 +206,19 @@ static BlockJobType stream_job_type = { void stream_start(BlockDriverState *bs, BlockDriverState *base, const char *base_id, int64_t speed, + BlockdevOnError on_error, BlockDriverCompletionFunc *cb, void *opaque, Error **errp) { StreamBlockJob *s; + if ((on_error == BLOCKDEV_ON_ERROR_STOP || + on_error == BLOCKDEV_ON_ERROR_ENOSPC) && + !bdrv_iostatus_is_enabled(bs)) { + error_set(errp, QERR_INVALID_PARAMETER, "on-error"); + return; + } + s = block_job_create(&stream_job_type, bs, speed, cb, opaque, errp); if (!s) { return; @@ -204,6 +229,7 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base, pstrcpy(s->backing_file_id, sizeof(s->backing_file_id), base_id); } + s->on_error = on_error; s->common.co = qemu_coroutine_create(stream_run); trace_stream_start(bs, base, s, s->common.co, opaque); qemu_coroutine_enter(s->common.co, s); diff --git a/block_int.h b/block_int.h index 785d43d61a..f4bae04401 100644 --- a/block_int.h +++ b/block_int.h @@ -299,6 +299,7 @@ void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, * @base_id: The file name that will be written to @bs as the new * backing file if the job completes. Ignored if @base is %NULL. * @speed: The maximum speed, in bytes per second, or 0 for unlimited. + * @on_error: The action to take upon error. * @cb: Completion function for the job. * @opaque: Opaque pointer value passed to @cb. * @errp: Error object. @@ -310,7 +311,7 @@ void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, * @base_id in the written image and to @base in the live BlockDriverState. */ void stream_start(BlockDriverState *bs, BlockDriverState *base, - const char *base_id, int64_t speed, + const char *base_id, int64_t speed, BlockdevOnError on_error, BlockDriverCompletionFunc *cb, void *opaque, Error **errp); diff --git a/blockdev.c b/blockdev.c index d52a830769..5f18dfa97b 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1096,13 +1096,18 @@ static void block_job_cb(void *opaque, int ret) } void qmp_block_stream(const char *device, bool has_base, - const char *base, bool has_speed, - int64_t speed, Error **errp) + const char *base, bool has_speed, int64_t speed, + bool has_on_error, BlockdevOnError on_error, + Error **errp) { BlockDriverState *bs; BlockDriverState *base_bs = NULL; Error *local_err = NULL; + if (!has_on_error) { + on_error = BLOCKDEV_ON_ERROR_REPORT; + } + bs = bdrv_find(device); if (!bs) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); @@ -1118,7 +1123,7 @@ void qmp_block_stream(const char *device, bool has_base, } stream_start(bs, base_bs, base, has_speed ? speed : 0, - block_job_cb, bs, &local_err); + on_error, block_job_cb, bs, &local_err); if (error_is_set(&local_err)) { error_propagate(errp, local_err); return; diff --git a/hmp.c b/hmp.c index 55601f7dad..df789b2351 100644 --- a/hmp.c +++ b/hmp.c @@ -930,7 +930,8 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict) int64_t speed = qdict_get_try_int(qdict, "speed", 0); qmp_block_stream(device, base != NULL, base, - qdict_haskey(qdict, "speed"), speed, &error); + qdict_haskey(qdict, "speed"), speed, + BLOCKDEV_ON_ERROR_REPORT, true, &error); hmp_handle_error(mon, &error); } diff --git a/qapi-schema.json b/qapi-schema.json index 14e7a0d686..768b4c785a 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1869,13 +1869,18 @@ # # @speed: #optional the maximum speed, in bytes per second # +# @on-error: #optional the action to take on an error (default report). +# 'stop' and 'enospc' can only be used if the block device +# supports io-status (see BlockInfo). Since 1.3. +# # Returns: Nothing on success # If @device does not exist, DeviceNotFound # # Since: 1.1 ## -{ 'command': 'block-stream', 'data': { 'device': 'str', '*base': 'str', - '*speed': 'int' } } +{ 'command': 'block-stream', + 'data': { 'device': 'str', '*base': 'str', '*speed': 'int', + '*on-error': 'BlockdevOnError' } } ## # @block-job-set-speed: diff --git a/qmp-commands.hx b/qmp-commands.hx index 71d7c25f5c..ea93b1d4a9 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -787,7 +787,7 @@ EQMP { .name = "block-stream", - .args_type = "device:B,base:s?,speed:o?", + .args_type = "device:B,base:s?,speed:o?,on-error:s?", .mhandler.cmd_new = qmp_marshal_input_block_stream, }, From 8f96b5be92fbd74798b97b1dc1ff5fbbe249ed11 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:23:00 +0200 Subject: [PATCH 0659/2270] blkdebug: process all set_state rules in the old state Currently it is impossible to write a blkdebug script that ping-pongs between two states, because the second set-state rule will use the state that is set in the first. If you have [set-state] event = "..." state = "1" new_state = "2" [set-state] event = "..." state = "2" new_state = "1" for example the state will remain locked at 1. This can be fixed by first processing all rules, and then setting the state. Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- block/blkdebug.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/block/blkdebug.c b/block/blkdebug.c index 59dcea0650..1206d5256b 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -28,6 +28,7 @@ typedef struct BDRVBlkdebugState { int state; + int new_state; QLIST_HEAD(, BlkdebugRule) rules[BLKDBG_EVENT_MAX]; QSIMPLEQ_HEAD(, BlkdebugRule) active_rules; } BDRVBlkdebugState; @@ -403,12 +404,12 @@ static void blkdebug_close(BlockDriverState *bs) } static bool process_rule(BlockDriverState *bs, struct BlkdebugRule *rule, - int old_state, bool injected) + bool injected) { BDRVBlkdebugState *s = bs->opaque; /* Only process rules for the current state */ - if (rule->state && rule->state != old_state) { + if (rule->state && rule->state != s->state) { return injected; } @@ -423,7 +424,7 @@ static bool process_rule(BlockDriverState *bs, struct BlkdebugRule *rule, break; case ACTION_SET_STATE: - s->state = rule->options.set_state.new_state; + s->new_state = rule->options.set_state.new_state; break; } return injected; @@ -433,15 +434,16 @@ static void blkdebug_debug_event(BlockDriverState *bs, BlkDebugEvent event) { BDRVBlkdebugState *s = bs->opaque; struct BlkdebugRule *rule; - int old_state = s->state; bool injected; assert((int)event >= 0 && event < BLKDBG_EVENT_MAX); injected = false; + s->new_state = s->state; QLIST_FOREACH(rule, &s->rules[event], next) { - injected = process_rule(bs, rule, old_state, injected); + injected = process_rule(bs, rule, injected); } + s->state = s->new_state; } static int64_t blkdebug_getlength(BlockDriverState *bs) From 4f45056841abced5d57485edf0ff1d2ffc042cb1 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:23:01 +0200 Subject: [PATCH 0660/2270] qemu-iotests: map underscore to dash in QMP argument names iotests.py provides a convenience function that uses Python keyword arguments to represent QMP command arguments. However, almost all QMP commands use dashes for argument names (the sole exception is block_set_io_throttle), and dashes are not allowed in a keyword argument name. Hence provide automatic conversion of underscores to dashes. Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- tests/qemu-iotests/iotests.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index e05b1d640b..a94ea75bb1 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -19,6 +19,7 @@ import os import re import subprocess +import string import unittest import sys; sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'QMP')) import qmp @@ -96,9 +97,14 @@ class VM(object): os.remove(self._qemu_log_path) self._popen = None + underscore_to_dash = string.maketrans('_', '-') def qmp(self, cmd, **args): '''Invoke a QMP command and return the result dict''' - return self._qmp.cmd(cmd, args=args) + qmp_args = dict() + for k in args.keys(): + qmp_args[k.translate(self.underscore_to_dash)] = args[k] + + return self._qmp.cmd(cmd, args=qmp_args) def get_qmp_events(self, wait=False): '''Poll for queued QMP events and return a list of dicts''' From 90f0b71153c6a85d03967244b9889f892841d835 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 28 Sep 2012 17:23:02 +0200 Subject: [PATCH 0661/2270] qemu-iotests: add tests for streaming error handling Add a test for each of report/ignore/stop. The tests use blkdebug to generate an error in the middle of a script. The error is recoverable (once = "on") so that we can test resuming a job after stopping for an error. Signed-off-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- tests/qemu-iotests/030 | 220 ++++++++++++++++++++++++++++++++++ tests/qemu-iotests/030.out | 4 +- tests/qemu-iotests/iotests.py | 7 ++ 3 files changed, 229 insertions(+), 2 deletions(-) diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030 index dfacdf11ad..dd4ef11996 100755 --- a/tests/qemu-iotests/030 +++ b/tests/qemu-iotests/030 @@ -195,6 +195,226 @@ class TestSmallerBackingFile(ImageStreamingTestCase): self.assert_no_active_streams() self.vm.shutdown() +class TestErrors(ImageStreamingTestCase): + image_len = 2 * 1024 * 1024 # MB + + # this should match STREAM_BUFFER_SIZE/512 in block/stream.c + STREAM_BUFFER_SIZE = 512 * 1024 + + def create_blkdebug_file(self, name, event, errno): + file = open(name, 'w') + file.write(''' +[inject-error] +state = "1" +event = "%s" +errno = "%d" +immediately = "off" +once = "on" +sector = "%d" + +[set-state] +state = "1" +event = "%s" +new_state = "2" + +[set-state] +state = "2" +event = "%s" +new_state = "1" +''' % (event, errno, self.STREAM_BUFFER_SIZE / 512, event, event)) + file.close() + +class TestEIO(TestErrors): + def setUp(self): + self.blkdebug_file = backing_img + ".blkdebug" + self.create_image(backing_img, TestErrors.image_len) + self.create_blkdebug_file(self.blkdebug_file, "read_aio", 5) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw' + % (self.blkdebug_file, backing_img), + test_img) + self.vm = iotests.VM().add_drive(test_img) + self.vm.launch() + + def tearDown(self): + self.vm.shutdown() + os.remove(test_img) + os.remove(backing_img) + os.remove(self.blkdebug_file) + + def test_report(self): + self.assert_no_active_streams() + + result = self.vm.qmp('block-stream', device='drive0') + self.assert_qmp(result, 'return', {}) + + completed = False + error = False + while not completed: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_ERROR': + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/operation', 'read') + error = True + elif event['event'] == 'BLOCK_JOB_COMPLETED': + self.assertTrue(error, 'job completed unexpectedly') + self.assert_qmp(event, 'data/type', 'stream') + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/error', 'Input/output error') + self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE) + self.assert_qmp(event, 'data/len', self.image_len) + completed = True + + self.assert_no_active_streams() + self.vm.shutdown() + + def test_ignore(self): + self.assert_no_active_streams() + + result = self.vm.qmp('block-stream', device='drive0', on_error='ignore') + self.assert_qmp(result, 'return', {}) + + error = False + completed = False + while not completed: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_ERROR': + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/operation', 'read') + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/paused', False) + error = True + elif event['event'] == 'BLOCK_JOB_COMPLETED': + self.assertTrue(error, 'job completed unexpectedly') + self.assert_qmp(event, 'data/type', 'stream') + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/error', 'Input/output error') + self.assert_qmp(event, 'data/offset', self.image_len) + self.assert_qmp(event, 'data/len', self.image_len) + completed = True + + self.assert_no_active_streams() + self.vm.shutdown() + + def test_stop(self): + self.assert_no_active_streams() + + result = self.vm.qmp('block-stream', device='drive0', on_error='stop') + self.assert_qmp(result, 'return', {}) + + error = False + completed = False + while not completed: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_ERROR': + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/operation', 'read') + + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/paused', True) + self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE) + self.assert_qmp(result, 'return[0]/io-status', 'failed') + + result = self.vm.qmp('block-job-resume', device='drive0') + self.assert_qmp(result, 'return', {}) + + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/paused', False) + self.assert_qmp(result, 'return[0]/io-status', 'ok') + error = True + elif event['event'] == 'BLOCK_JOB_COMPLETED': + self.assertTrue(error, 'job completed unexpectedly') + self.assert_qmp(event, 'data/type', 'stream') + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp_absent(event, 'data/error') + self.assert_qmp(event, 'data/offset', self.image_len) + self.assert_qmp(event, 'data/len', self.image_len) + completed = True + + self.assert_no_active_streams() + self.vm.shutdown() + + def test_enospc(self): + self.assert_no_active_streams() + + result = self.vm.qmp('block-stream', device='drive0', on_error='enospc') + self.assert_qmp(result, 'return', {}) + + completed = False + error = False + while not completed: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_ERROR': + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/operation', 'read') + error = True + elif event['event'] == 'BLOCK_JOB_COMPLETED': + self.assertTrue(error, 'job completed unexpectedly') + self.assert_qmp(event, 'data/type', 'stream') + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/error', 'Input/output error') + self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE) + self.assert_qmp(event, 'data/len', self.image_len) + completed = True + + self.assert_no_active_streams() + self.vm.shutdown() + +class TestENOSPC(TestErrors): + def setUp(self): + self.blkdebug_file = backing_img + ".blkdebug" + self.create_image(backing_img, TestErrors.image_len) + self.create_blkdebug_file(self.blkdebug_file, "read_aio", 28) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw' + % (self.blkdebug_file, backing_img), + test_img) + self.vm = iotests.VM().add_drive(test_img) + self.vm.launch() + + def tearDown(self): + self.vm.shutdown() + os.remove(test_img) + os.remove(backing_img) + os.remove(self.blkdebug_file) + + def test_enospc(self): + self.assert_no_active_streams() + + result = self.vm.qmp('block-stream', device='drive0', on_error='enospc') + self.assert_qmp(result, 'return', {}) + + error = False + completed = False + while not completed: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_ERROR': + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/operation', 'read') + + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/paused', True) + self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE) + self.assert_qmp(result, 'return[0]/io-status', 'nospace') + + result = self.vm.qmp('block-job-resume', device='drive0') + self.assert_qmp(result, 'return', {}) + + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/paused', False) + self.assert_qmp(result, 'return[0]/io-status', 'ok') + error = True + elif event['event'] == 'BLOCK_JOB_COMPLETED': + self.assertTrue(error, 'job completed unexpectedly') + self.assert_qmp(event, 'data/type', 'stream') + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp_absent(event, 'data/error') + self.assert_qmp(event, 'data/offset', self.image_len) + self.assert_qmp(event, 'data/len', self.image_len) + completed = True + + self.assert_no_active_streams() + self.vm.shutdown() class TestStreamStop(ImageStreamingTestCase): image_len = 8 * 1024 * 1024 * 1024 # GB diff --git a/tests/qemu-iotests/030.out b/tests/qemu-iotests/030.out index 594c16f49f..fa16b5ccef 100644 --- a/tests/qemu-iotests/030.out +++ b/tests/qemu-iotests/030.out @@ -1,5 +1,5 @@ -........ +............. ---------------------------------------------------------------------- -Ran 8 tests +Ran 13 tests OK diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index a94ea75bb1..3c60b2d163 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -138,6 +138,13 @@ class QMPTestCase(unittest.TestCase): self.fail('invalid index "%s" in path "%s" in "%s"' % (idx, path, str(d))) return d + def assert_qmp_absent(self, d, path): + try: + result = self.dictpath(d, path) + except AssertionError: + return + self.fail('path "%s" has value "%s"' % (path, str(result))) + def assert_qmp(self, d, path, value): '''Assert that the value for a specific path in a QMP dict matches''' result = self.dictpath(d, path) From b1f4679392a03f2b26a37bfa52e95d6cc4f73d82 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 6 Sep 2012 10:05:35 +0000 Subject: [PATCH 0662/2270] i386: kvm: bit 10 of CPUID[8000_0001].EDX is reserved Bit 10 of CPUID[8000_0001].EDX is not defined as an alias of CPUID[1].EDX[10], so do not duplicate it on kvm_arch_get_supported_cpuid(). Signed-off-by: Eduardo Habkost Reviewed-By: Igor Mammedov Reviewed-by: Don Slutz Signed-off-by: Blue Swirl --- target-i386/kvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 6790180b0a..acb93693b4 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -165,7 +165,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, * so add missing bits according to the AMD spec: */ cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); - ret |= cpuid_1_edx & 0x183f7ff; + ret |= cpuid_1_edx & 0x183f3ff; break; } break; From 8fad4b44a0f71cd404f95f109657c0ccbf11f8f9 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 6 Sep 2012 10:05:36 +0000 Subject: [PATCH 0663/2270] i386: kvm: use a #define for the set of alias feature bits Instea of using a hardcoded hex constant, define CPUID_EXT2_AMD_ALIASES as the set of CPUID[8000_0001].EDX bits that on AMD are the same as the bits of CPUID[1].EDX. Signed-off-by: Eduardo Habkost Reviewed-By: Igor Mammedov Reviewed-by: Don Slutz Signed-off-by: Blue Swirl --- target-i386/cpu.h | 12 ++++++++++++ target-i386/kvm.c | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index d7ea2f92a8..49950843f6 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -409,6 +409,7 @@ #define CPUID_EXT_HYPERVISOR (1 << 31) #define CPUID_EXT2_FPU (1 << 0) +#define CPUID_EXT2_VME (1 << 1) #define CPUID_EXT2_DE (1 << 2) #define CPUID_EXT2_PSE (1 << 3) #define CPUID_EXT2_TSC (1 << 4) @@ -436,6 +437,17 @@ #define CPUID_EXT2_3DNOWEXT (1 << 30) #define CPUID_EXT2_3DNOW (1 << 31) +/* CPUID[8000_0001].EDX bits that are aliase of CPUID[1].EDX bits on AMD CPUs */ +#define CPUID_EXT2_AMD_ALIASES (CPUID_EXT2_FPU | CPUID_EXT2_VME | \ + CPUID_EXT2_DE | CPUID_EXT2_PSE | \ + CPUID_EXT2_TSC | CPUID_EXT2_MSR | \ + CPUID_EXT2_PAE | CPUID_EXT2_MCE | \ + CPUID_EXT2_CX8 | CPUID_EXT2_APIC | \ + CPUID_EXT2_MTRR | CPUID_EXT2_PGE | \ + CPUID_EXT2_MCA | CPUID_EXT2_CMOV | \ + CPUID_EXT2_PAT | CPUID_EXT2_PSE36 | \ + CPUID_EXT2_MMX | CPUID_EXT2_FXSR) + #define CPUID_EXT3_LAHF_LM (1 << 0) #define CPUID_EXT3_CMP_LEG (1 << 1) #define CPUID_EXT3_SVM (1 << 2) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index acb93693b4..5b18383d8f 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -165,7 +165,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, * so add missing bits according to the AMD spec: */ cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); - ret |= cpuid_1_edx & 0x183f3ff; + ret |= cpuid_1_edx & CPUID_EXT2_AMD_ALIASES; break; } break; From 60032ac04c675cf8950497f9d06e681b2dc7085c Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 6 Sep 2012 10:05:37 +0000 Subject: [PATCH 0664/2270] i386: cpu: replace EXT2_FEATURE_MASK with CPUID_EXT2_AMD_ALIASES Both constants have the same value, but CPUID_EXT2_AMD_ALIASES is defined without using magic numbers. Signed-off-by: Eduardo Habkost Reviewed-by: Don Slutz Signed-off-by: Blue Swirl --- target-i386/cpu.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index fd4fe2898b..7cad3b5ac8 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -258,7 +258,6 @@ typedef struct x86_def_t { CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \ CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \ CPUID_PAE | CPUID_SEP | CPUID_APIC) -#define EXT2_FEATURE_MASK 0x0183F3FF #define TCG_FEATURES (CPUID_FP87 | CPUID_PSE | CPUID_TSC | CPUID_MSR | \ CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | CPUID_SEP | \ @@ -276,7 +275,7 @@ typedef struct x86_def_t { /* missing: CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_XSAVE */ -#define TCG_EXT2_FEATURES ((TCG_FEATURES & EXT2_FEATURE_MASK) | \ +#define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \ CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \ CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT) /* missing: @@ -305,7 +304,7 @@ static x86_def_t builtin_x86_defs[] = { CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36, .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT, - .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | + .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A, @@ -325,7 +324,7 @@ static x86_def_t builtin_x86_defs[] = { CPUID_PSE36 | CPUID_VME | CPUID_HT, .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 | CPUID_EXT_POPCNT, - .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | + .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT | CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP, @@ -373,7 +372,7 @@ static x86_def_t builtin_x86_defs[] = { /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */ .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16, /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */ - .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | + .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, /* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC, CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A, @@ -402,7 +401,7 @@ static x86_def_t builtin_x86_defs[] = { .features = PPRO_FEATURES | CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36, .ext_features = CPUID_EXT_SSE3, - .ext2_features = PPRO_FEATURES & EXT2_FEATURE_MASK, + .ext2_features = PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES, .ext3_features = 0, .xlevel = 0x80000008, .model_id = "Common 32-bit KVM processor" @@ -467,8 +466,10 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 2, .stepping = 3, - .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA, - .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT, + .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | + CPUID_MCA, + .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | + CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT, .xlevel = 0x80000008, }, { @@ -484,7 +485,8 @@ static x86_def_t builtin_x86_defs[] = { /* Some CPUs got no CPUID_SEP */ .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | CPUID_EXT_DSCPL | CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR, - .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_NX, + .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | + CPUID_EXT2_NX, .ext3_features = CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz", From 3b671a40cab2404bc63e57db8cd3afa4ec70bfab Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 6 Sep 2012 10:05:38 +0000 Subject: [PATCH 0665/2270] i386: cpu: eliminate duplicate feature names Instead of having duplicate feature names on the ext2_feature array for the AMD feature bit aliases, we keep the feature names only on the feature_name[] array, and copy the corresponding bits to cpuid_ext2_features in case the CPU vendor is AMD. This will: - Make sure we don't set the feature bit aliases on Intel CPUs; - Make it easier to convert feature bits to CPU properties, as now we have a single bit on the x86_def_t struct for each CPU feature. Signed-off-by: Eduardo Habkost Reviewed-by: Don Slutz Signed-off-by: Blue Swirl --- target-i386/cpu.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 7cad3b5ac8..7577381b98 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -61,15 +61,19 @@ static const char *ext_feature_name[] = { "tsc-deadline", "aes", "xsave", "osxsave", "avx", NULL, NULL, "hypervisor", }; +/* Feature names that are already defined on feature_name[] but are set on + * CPUID[8000_0001].EDX on AMD CPUs don't have their names on + * ext2_feature_name[]. They are copied automatically to cpuid_ext2_features + * if and only if CPU vendor is AMD. + */ static const char *ext2_feature_name[] = { - "fpu", "vme", "de", "pse", - "tsc", "msr", "pae", "mce", - "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", - "mtrr", "pge", "mca", "cmov", - "pat", "pse36", NULL, NULL /* Linux mp */, - "nx|xd", NULL, "mmxext", "mmx", - "fxsr", "fxsr_opt|ffxsr", "pdpe1gb" /* AMD Page1GB */, "rdtscp", - NULL, "lm|i64", "3dnowext", "3dnow", + NULL /* fpu */, NULL /* vme */, NULL /* de */, NULL /* pse */, + NULL /* tsc */, NULL /* msr */, NULL /* pae */, NULL /* mce */, + NULL /* cx8 */ /* AMD CMPXCHG8B */, NULL /* apic */, NULL, "syscall", + NULL /* mtrr */, NULL /* pge */, NULL /* mca */, NULL /* cmov */, + NULL /* pat */, NULL /* pse36 */, NULL, NULL /* Linux mp */, + "nx|xd", NULL, "mmxext", NULL /* mmx */, + NULL /* fxsr */, "fxsr_opt|ffxsr", "pdpe1gb" /* AMD Page1GB */, "rdtscp", }; static const char *ext3_feature_name[] = { "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, @@ -1374,6 +1378,17 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) env->cpuid_xlevel2 = def->xlevel2; object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000, "tsc-frequency", &error); + + /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on + * CPUID[1].EDX. + */ + if (env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && + env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && + env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) { + env->cpuid_ext2_features &= ~CPUID_EXT2_AMD_ALIASES; + env->cpuid_ext2_features |= (def->features & CPUID_EXT2_AMD_ALIASES); + } + if (!kvm_enabled()) { env->cpuid_features &= TCG_FEATURES; env->cpuid_ext_features &= TCG_EXT_FEATURES; From 4a19e505df659dd25a77fb790399744f3e1f971c Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 6 Sep 2012 10:05:39 +0000 Subject: [PATCH 0666/2270] i386: -cpu help: remove reference to specific CPUID leaves/registers The -cpu configuration interface is based on a list of feature names or properties, on a single namespace, so there's no need to mention on which CPUID leaf/register each flag is located. Signed-off-by: Eduardo Habkost Reviewed-by: Don Slutz Signed-off-by: Blue Swirl --- target-i386/cpu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 7577381b98..c4e6163c9a 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1312,13 +1312,13 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) } (*cpu_fprintf)(f, "\nRecognized CPUID flags:\n"); listflags(buf, sizeof(buf), (uint32_t)~0, feature_name, 1); - (*cpu_fprintf)(f, " f_edx: %s\n", buf); + (*cpu_fprintf)(f, " %s\n", buf); listflags(buf, sizeof(buf), (uint32_t)~0, ext_feature_name, 1); - (*cpu_fprintf)(f, " f_ecx: %s\n", buf); + (*cpu_fprintf)(f, " %s\n", buf); listflags(buf, sizeof(buf), (uint32_t)~0, ext2_feature_name, 1); - (*cpu_fprintf)(f, " extf_edx: %s\n", buf); + (*cpu_fprintf)(f, " %s\n", buf); listflags(buf, sizeof(buf), (uint32_t)~0, ext3_feature_name, 1); - (*cpu_fprintf)(f, " extf_ecx: %s\n", buf); + (*cpu_fprintf)(f, " %s\n", buf); } CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) From a9321a4d49d65d29c2926a51aedc5b91a01f3591 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 26 Sep 2012 13:18:43 -0700 Subject: [PATCH 0667/2270] x86: Implement SMEP and SMAP This patch implements Supervisor Mode Execution Prevention (SMEP) and Supervisor Mode Access Prevention (SMAP) for x86. The purpose of the patch, obviously, is to help kernel developers debug the support for those features. A fair bit of the code relates to the handling of CPUID features. The CPUID code probably would get greatly simplified if all the feature bit words were unified into a single vector object, but in the interest of producing a minimal patch for SMEP/SMAP, and because I had very limited time for this project, I followed the existing style. [ v2: don't change the definition of the qemu64 CPU shorthand, since that breaks loading old snapshots. Per Anthony Liguori this can be fixed once the CPU feature set is snapshot. Change the coding style slightly to conform to checkpatch.pl. ] Signed-off-by: H. Peter Anvin Signed-off-by: Anthony Liguori --- target-i386/cc_helper.c | 10 +++ target-i386/cpu.c | 34 ++++++--- target-i386/cpu.h | 33 +++++++-- target-i386/helper.c | 150 ++++++++++++++++++++++++++++++++-------- target-i386/helper.h | 2 + target-i386/translate.c | 27 ++++++-- 6 files changed, 207 insertions(+), 49 deletions(-) diff --git a/target-i386/cc_helper.c b/target-i386/cc_helper.c index 07892f9049..9422003f24 100644 --- a/target-i386/cc_helper.c +++ b/target-i386/cc_helper.c @@ -353,6 +353,16 @@ void helper_sti(CPUX86State *env) env->eflags |= IF_MASK; } +void helper_clac(CPUX86State *env) +{ + env->eflags &= ~AC_MASK; +} + +void helper_stac(CPUX86State *env) +{ + env->eflags |= AC_MASK; +} + #if 0 /* vm86plus instructions */ void helper_cli_vm(CPUX86State *env) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index c4e6163c9a..bb1e44eb01 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -104,6 +104,13 @@ static const char *svm_feature_name[] = { NULL, NULL, NULL, NULL, }; +static const char *cpuid_7_0_ebx_feature_name[] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, "smep", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "smap", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +}; + /* collects per-function cpuid data */ typedef struct model_features_t { @@ -219,14 +226,17 @@ static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features, uint32_t *ext2_features, uint32_t *ext3_features, uint32_t *kvm_features, - uint32_t *svm_features) + uint32_t *svm_features, + uint32_t *cpuid_7_0_ebx_features) { if (!lookup_feature(features, flagname, NULL, feature_name) && !lookup_feature(ext_features, flagname, NULL, ext_feature_name) && !lookup_feature(ext2_features, flagname, NULL, ext2_feature_name) && !lookup_feature(ext3_features, flagname, NULL, ext3_feature_name) && !lookup_feature(kvm_features, flagname, NULL, kvm_feature_name) && - !lookup_feature(svm_features, flagname, NULL, svm_feature_name)) + !lookup_feature(svm_features, flagname, NULL, svm_feature_name) && + !lookup_feature(cpuid_7_0_ebx_features, flagname, NULL, + cpuid_7_0_ebx_feature_name)) fprintf(stderr, "CPU feature %s not found\n", flagname); } @@ -287,6 +297,7 @@ typedef struct x86_def_t { #define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \ CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A) #define TCG_SVM_FEATURES 0 +#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP) /* maintains list of cpu model definitions */ @@ -1097,10 +1108,12 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) uint32_t plus_features = 0, plus_ext_features = 0; uint32_t plus_ext2_features = 0, plus_ext3_features = 0; uint32_t plus_kvm_features = 0, plus_svm_features = 0; + uint32_t plus_7_0_ebx_features = 0; /* Features to be removed */ uint32_t minus_features = 0, minus_ext_features = 0; uint32_t minus_ext2_features = 0, minus_ext3_features = 0; uint32_t minus_kvm_features = 0, minus_svm_features = 0; + uint32_t minus_7_0_ebx_features = 0; uint32_t numvalue; for (def = x86_defs; def; def = def->next) @@ -1127,8 +1140,8 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) #endif add_flagname_to_bitmaps("hypervisor", &plus_features, - &plus_ext_features, &plus_ext2_features, &plus_ext3_features, - &plus_kvm_features, &plus_svm_features); + &plus_ext_features, &plus_ext2_features, &plus_ext3_features, + &plus_kvm_features, &plus_svm_features, &plus_7_0_ebx_features); featurestr = strtok(NULL, ","); @@ -1138,12 +1151,12 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features, &plus_kvm_features, - &plus_svm_features); + &plus_svm_features, &plus_7_0_ebx_features); } else if (featurestr[0] == '-') { add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features, &minus_kvm_features, - &minus_svm_features); + &minus_svm_features, &minus_7_0_ebx_features); } else if ((val = strchr(featurestr, '='))) { *val = 0; val++; if (!strcmp(featurestr, "family")) { @@ -1249,16 +1262,21 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) x86_cpu_def->ext3_features |= plus_ext3_features; x86_cpu_def->kvm_features |= plus_kvm_features; x86_cpu_def->svm_features |= plus_svm_features; + x86_cpu_def->cpuid_7_0_ebx_features |= plus_7_0_ebx_features; x86_cpu_def->features &= ~minus_features; x86_cpu_def->ext_features &= ~minus_ext_features; x86_cpu_def->ext2_features &= ~minus_ext2_features; x86_cpu_def->ext3_features &= ~minus_ext3_features; x86_cpu_def->kvm_features &= ~minus_kvm_features; x86_cpu_def->svm_features &= ~minus_svm_features; + x86_cpu_def->cpuid_7_0_ebx_features &= ~minus_7_0_ebx_features; if (check_cpuid) { if (check_features_against_host(x86_cpu_def) && enforce_cpuid) goto error; } + if (x86_cpu_def->cpuid_7_0_ebx_features && x86_cpu_def->level < 7) { + x86_cpu_def->level = 7; + } g_free(s); return 0; @@ -1374,7 +1392,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) env->cpuid_kvm_features = def->kvm_features; env->cpuid_svm_features = def->svm_features; env->cpuid_ext4_features = def->ext4_features; - env->cpuid_7_0_ebx = def->cpuid_7_0_ebx_features; + env->cpuid_7_0_ebx_features = def->cpuid_7_0_ebx_features; env->cpuid_xlevel2 = def->xlevel2; object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000, "tsc-frequency", &error); @@ -1562,7 +1580,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, /* Structured Extended Feature Flags Enumeration Leaf */ if (count == 0) { *eax = 0; /* Maximum ECX value for sub-leaves */ - *ebx = env->cpuid_7_0_ebx; /* Feature flags */ + *ebx = env->cpuid_7_0_ebx_features; /* Feature flags */ *ecx = 0; /* Reserved */ *edx = 0; /* Reserved */ } else { diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 49950843f6..e4a7d5b6e4 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -123,8 +123,8 @@ /* hidden flags - used internally by qemu to represent additional cpu states. Only the CPL, INHIBIT_IRQ, SMM and SVMI are not - redundant. We avoid using the IOPL_MASK, TF_MASK and VM_MASK bit - position to ease oring with eflags. */ + redundant. We avoid using the IOPL_MASK, TF_MASK, VM_MASK and AC_MASK + bit positions to ease oring with eflags. */ /* current cpl */ #define HF_CPL_SHIFT 0 /* true if soft mmu is being used */ @@ -147,10 +147,12 @@ #define HF_CS64_SHIFT 15 /* only used on x86_64: 64 bit code segment */ #define HF_RF_SHIFT 16 /* must be same as eflags */ #define HF_VM_SHIFT 17 /* must be same as eflags */ +#define HF_AC_SHIFT 18 /* must be same as eflags */ #define HF_SMM_SHIFT 19 /* CPU in SMM mode */ #define HF_SVME_SHIFT 20 /* SVME enabled (copy of EFER.SVME) */ #define HF_SVMI_SHIFT 21 /* SVM intercepts are active */ #define HF_OSFXSR_SHIFT 22 /* CR4.OSFXSR */ +#define HF_SMAP_SHIFT 23 /* CR4.SMAP */ #define HF_CPL_MASK (3 << HF_CPL_SHIFT) #define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT) @@ -168,10 +170,12 @@ #define HF_CS64_MASK (1 << HF_CS64_SHIFT) #define HF_RF_MASK (1 << HF_RF_SHIFT) #define HF_VM_MASK (1 << HF_VM_SHIFT) +#define HF_AC_MASK (1 << HF_AC_SHIFT) #define HF_SMM_MASK (1 << HF_SMM_SHIFT) #define HF_SVME_MASK (1 << HF_SVME_SHIFT) #define HF_SVMI_MASK (1 << HF_SVMI_SHIFT) #define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT) +#define HF_SMAP_MASK (1 << HF_SMAP_SHIFT) /* hflags2 */ @@ -210,6 +214,13 @@ #define CR4_OSFXSR_SHIFT 9 #define CR4_OSFXSR_MASK (1 << CR4_OSFXSR_SHIFT) #define CR4_OSXMMEXCPT_MASK (1 << 10) +#define CR4_VMXE_MASK (1 << 13) +#define CR4_SMXE_MASK (1 << 14) +#define CR4_FSGSBASE_MASK (1 << 16) +#define CR4_PCIDE_MASK (1 << 17) +#define CR4_OSXSAVE_MASK (1 << 18) +#define CR4_SMEP_MASK (1 << 20) +#define CR4_SMAP_MASK (1 << 21) #define DR6_BD (1 << 13) #define DR6_BS (1 << 14) @@ -474,6 +485,9 @@ #define CPUID_SVM_PAUSEFILTER (1 << 10) #define CPUID_SVM_PFTHRESHOLD (1 << 12) +#define CPUID_7_0_EBX_SMEP (1 << 7) +#define CPUID_7_0_EBX_SMAP (1 << 20) + #define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */ #define CPUID_VENDOR_INTEL_2 0x49656e69 /* "ineI" */ #define CPUID_VENDOR_INTEL_3 0x6c65746e /* "ntel" */ @@ -649,7 +663,7 @@ typedef struct { #define CPU_NB_REGS CPU_NB_REGS32 #endif -#define NB_MMU_MODES 2 +#define NB_MMU_MODES 3 typedef enum TPRAccess { TPR_ACCESS_READ, @@ -779,7 +793,7 @@ typedef struct CPUX86State { uint32_t cpuid_xlevel2; uint32_t cpuid_ext4_features; /* Flags from CPUID[EAX=7,ECX=0].EBX */ - uint32_t cpuid_7_0_ebx; + uint32_t cpuid_7_0_ebx_features; /* MTRRs */ uint64_t mtrr_fixed[11]; @@ -1018,10 +1032,15 @@ static inline CPUX86State *cpu_init(const char *cpu_model) /* MMU modes definitions */ #define MMU_MODE0_SUFFIX _kernel #define MMU_MODE1_SUFFIX _user -#define MMU_USER_IDX 1 +#define MMU_MODE2_SUFFIX _ksmap /* Kernel with SMAP override */ +#define MMU_KERNEL_IDX 0 +#define MMU_USER_IDX 1 +#define MMU_KSMAP_IDX 2 static inline int cpu_mmu_index (CPUX86State *env) { - return (env->hflags & HF_CPL_MASK) == 3 ? 1 : 0; + return (env->hflags & HF_CPL_MASK) == 3 ? MMU_USER_IDX : + ((env->hflags & HF_SMAP_MASK) && (env->eflags & AC_MASK)) + ? MMU_KSMAP_IDX : MMU_KERNEL_IDX; } #undef EAX @@ -1107,7 +1126,7 @@ static inline void cpu_get_tb_cpu_state(CPUX86State *env, target_ulong *pc, *cs_base = env->segs[R_CS].base; *pc = *cs_base + env->eip; *flags = env->hflags | - (env->eflags & (IOPL_MASK | TF_MASK | RF_MASK | VM_MASK)); + (env->eflags & (IOPL_MASK | TF_MASK | RF_MASK | VM_MASK | AC_MASK)); } void do_cpu_init(X86CPU *cpu); diff --git a/target-i386/helper.c b/target-i386/helper.c index 8a5da3d7c0..c635667d60 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -443,17 +443,27 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4) #if defined(DEBUG_MMU) printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]); #endif - if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) != - (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) { + if ((new_cr4 ^ env->cr[4]) & + (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK | + CR4_SMEP_MASK | CR4_SMAP_MASK)) { tlb_flush(env, 1); } /* SSE handling */ - if (!(env->cpuid_features & CPUID_SSE)) + if (!(env->cpuid_features & CPUID_SSE)) { new_cr4 &= ~CR4_OSFXSR_MASK; - if (new_cr4 & CR4_OSFXSR_MASK) + } + env->hflags &= ~HF_OSFXSR_MASK; + if (new_cr4 & CR4_OSFXSR_MASK) { env->hflags |= HF_OSFXSR_MASK; - else - env->hflags &= ~HF_OSFXSR_MASK; + } + + if (!(env->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)) { + new_cr4 &= ~CR4_SMAP_MASK; + } + env->hflags &= ~HF_SMAP_MASK; + if (new_cr4 & CR4_SMAP_MASK) { + env->hflags |= HF_SMAP_MASK; + } env->cr[4] = new_cr4; } @@ -591,17 +601,38 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, /* 2 MB page */ page_size = 2048 * 1024; ptep ^= PG_NX_MASK; - if ((ptep & PG_NX_MASK) && is_write1 == 2) + if ((ptep & PG_NX_MASK) && is_write1 == 2) { goto do_fault_protect; - if (is_user) { - if (!(ptep & PG_USER_MASK)) + } + switch (mmu_idx) { + case MMU_USER_IDX: + if (!(ptep & PG_USER_MASK)) { goto do_fault_protect; - if (is_write && !(ptep & PG_RW_MASK)) + } + if (is_write && !(ptep & PG_RW_MASK)) { goto do_fault_protect; - } else { + } + break; + + case MMU_KERNEL_IDX: + if (is_write1 != 2 && (env->cr[4] & CR4_SMAP_MASK) && + (ptep & PG_USER_MASK)) { + goto do_fault_protect; + } + /* fall through */ + case MMU_KSMAP_IDX: + if (is_write1 == 2 && (env->cr[4] & CR4_SMEP_MASK) && + (ptep & PG_USER_MASK)) { + goto do_fault_protect; + } if ((env->cr[0] & CR0_WP_MASK) && - is_write && !(ptep & PG_RW_MASK)) + is_write && !(ptep & PG_RW_MASK)) { goto do_fault_protect; + } + break; + + default: /* cannot happen */ + break; } is_dirty = is_write && !(pde & PG_DIRTY_MASK); if (!(pde & PG_ACCESSED_MASK) || is_dirty) { @@ -635,15 +666,35 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, ptep ^= PG_NX_MASK; if ((ptep & PG_NX_MASK) && is_write1 == 2) goto do_fault_protect; - if (is_user) { - if (!(ptep & PG_USER_MASK)) + switch (mmu_idx) { + case MMU_USER_IDX: + if (!(ptep & PG_USER_MASK)) { goto do_fault_protect; - if (is_write && !(ptep & PG_RW_MASK)) + } + if (is_write && !(ptep & PG_RW_MASK)) { goto do_fault_protect; - } else { + } + break; + + case MMU_KERNEL_IDX: + if (is_write1 != 2 && (env->cr[4] & CR4_SMAP_MASK) && + (ptep & PG_USER_MASK)) { + goto do_fault_protect; + } + /* fall through */ + case MMU_KSMAP_IDX: + if (is_write1 == 2 && (env->cr[4] & CR4_SMEP_MASK) && + (ptep & PG_USER_MASK)) { + goto do_fault_protect; + } if ((env->cr[0] & CR0_WP_MASK) && - is_write && !(ptep & PG_RW_MASK)) + is_write && !(ptep & PG_RW_MASK)) { goto do_fault_protect; + } + break; + + default: /* cannot happen */ + break; } is_dirty = is_write && !(pte & PG_DIRTY_MASK); if (!(pte & PG_ACCESSED_MASK) || is_dirty) { @@ -670,15 +721,35 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, /* if PSE bit is set, then we use a 4MB page */ if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) { page_size = 4096 * 1024; - if (is_user) { - if (!(pde & PG_USER_MASK)) + switch (mmu_idx) { + case MMU_USER_IDX: + if (!(pde & PG_USER_MASK)) { goto do_fault_protect; - if (is_write && !(pde & PG_RW_MASK)) + } + if (is_write && !(pde & PG_RW_MASK)) { goto do_fault_protect; - } else { + } + break; + + case MMU_KERNEL_IDX: + if (is_write1 != 2 && (env->cr[4] & CR4_SMAP_MASK) && + (pde & PG_USER_MASK)) { + goto do_fault_protect; + } + /* fall through */ + case MMU_KSMAP_IDX: + if (is_write1 == 2 && (env->cr[4] & CR4_SMEP_MASK) && + (pde & PG_USER_MASK)) { + goto do_fault_protect; + } if ((env->cr[0] & CR0_WP_MASK) && - is_write && !(pde & PG_RW_MASK)) + is_write && !(pde & PG_RW_MASK)) { goto do_fault_protect; + } + break; + + default: /* cannot happen */ + break; } is_dirty = is_write && !(pde & PG_DIRTY_MASK); if (!(pde & PG_ACCESSED_MASK) || is_dirty) { @@ -707,15 +778,35 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, } /* combine pde and pte user and rw protections */ ptep = pte & pde; - if (is_user) { - if (!(ptep & PG_USER_MASK)) + switch (mmu_idx) { + case MMU_USER_IDX: + if (!(ptep & PG_USER_MASK)) { goto do_fault_protect; - if (is_write && !(ptep & PG_RW_MASK)) + } + if (is_write && !(ptep & PG_RW_MASK)) { goto do_fault_protect; - } else { + } + break; + + case MMU_KERNEL_IDX: + if (is_write1 != 2 && (env->cr[4] & CR4_SMAP_MASK) && + (ptep & PG_USER_MASK)) { + goto do_fault_protect; + } + /* fall through */ + case MMU_KSMAP_IDX: + if (is_write1 == 2 && (env->cr[4] & CR4_SMEP_MASK) && + (ptep & PG_USER_MASK)) { + goto do_fault_protect; + } if ((env->cr[0] & CR0_WP_MASK) && - is_write && !(ptep & PG_RW_MASK)) + is_write && !(ptep & PG_RW_MASK)) { goto do_fault_protect; + } + break; + + default: /* cannot happen */ + break; } is_dirty = is_write && !(pte & PG_DIRTY_MASK); if (!(pte & PG_ACCESSED_MASK) || is_dirty) { @@ -762,8 +853,9 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, if (is_user) error_code |= PG_ERROR_U_MASK; if (is_write1 == 2 && - (env->efer & MSR_EFER_NXE) && - (env->cr[4] & CR4_PAE_MASK)) + (((env->efer & MSR_EFER_NXE) && + (env->cr[4] & CR4_PAE_MASK)) || + (env->cr[4] & CR4_SMEP_MASK))) error_code |= PG_ERROR_I_D_MASK; if (env->intercept_exceptions & (1 << EXCP0E_PAGE)) { /* cr2 is not modified in case of exceptions */ diff --git a/target-i386/helper.h b/target-i386/helper.h index ab6af638e6..93850ceecd 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -67,6 +67,8 @@ DEF_HELPER_3(raise_interrupt, void, env, int, int) DEF_HELPER_2(raise_exception, void, env, int) DEF_HELPER_1(cli, void, env) DEF_HELPER_1(sti, void, env) +DEF_HELPER_1(clac, void, env) +DEF_HELPER_1(stac, void, env) DEF_HELPER_1(set_inhibit_irq, void, env) DEF_HELPER_1(reset_inhibit_irq, void, env) DEF_HELPER_3(boundw, void, env, tl, int) diff --git a/target-i386/translate.c b/target-i386/translate.c index 323869d874..0a7e4e3487 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -107,6 +107,7 @@ typedef struct DisasContext { int cpuid_ext_features; int cpuid_ext2_features; int cpuid_ext3_features; + int cpuid_7_0_ebx_features; } DisasContext; static void gen_eob(DisasContext *s); @@ -6556,7 +6557,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } gen_pop_update(s); s->cc_op = CC_OP_EFLAGS; - /* abort translation because TF flag may change */ + /* abort translation because TF/AC flag may change */ gen_jmp_im(s->pc - s->cs_base); gen_eob(s); } @@ -7206,6 +7207,24 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start)); gen_eob(s); break; + case 2: /* clac */ + if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) || + s->cpl != 0) { + goto illegal_op; + } + gen_helper_clac(cpu_env); + gen_jmp_im(s->pc - s->cs_base); + gen_eob(s); + break; + case 3: /* stac */ + if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) || + s->cpl != 0) { + goto illegal_op; + } + gen_helper_stac(cpu_env); + gen_jmp_im(s->pc - s->cs_base); + gen_eob(s); + break; default: goto illegal_op; } @@ -7901,15 +7920,13 @@ static inline void gen_intermediate_code_internal(CPUX86State *env, /* select memory access functions */ dc->mem_index = 0; if (flags & HF_SOFTMMU_MASK) { - if (dc->cpl == 3) - dc->mem_index = 2 * 4; - else - dc->mem_index = 1 * 4; + dc->mem_index = (cpu_mmu_index(env) + 1) << 2; } dc->cpuid_features = env->cpuid_features; dc->cpuid_ext_features = env->cpuid_ext_features; dc->cpuid_ext2_features = env->cpuid_ext2_features; dc->cpuid_ext3_features = env->cpuid_ext3_features; + dc->cpuid_7_0_ebx_features = env->cpuid_7_0_ebx_features; #ifdef TARGET_X86_64 dc->lma = (flags >> HF_LMA_SHIFT) & 1; dc->code64 = (flags >> HF_CS64_SHIFT) & 1; From df8c1b0207689a4bcc2396bf5327d5ea135a45bb Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 26 Sep 2012 11:19:18 -0600 Subject: [PATCH 0668/2270] Update kernel header script to include vfio Signed-off-by: Alex Williamson Acked-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- scripts/update-linux-headers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh index 53a6f87650..67be2efecd 100755 --- a/scripts/update-linux-headers.sh +++ b/scripts/update-linux-headers.sh @@ -57,7 +57,7 @@ done rm -rf "$output/linux-headers/linux" mkdir -p "$output/linux-headers/linux" -for header in kvm.h kvm_para.h vhost.h virtio_config.h virtio_ring.h; do +for header in kvm.h kvm_para.h vfio.h vhost.h virtio_config.h virtio_ring.h; do cp "$tmpdir/include/linux/$header" "$output/linux-headers/linux" done rm -rf "$output/linux-headers/asm-generic" From 883f0b85f0cbb8c31baeadfcbfd144a1ed29d935 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 26 Sep 2012 11:19:25 -0600 Subject: [PATCH 0669/2270] Update Linux kernel headers Based on Linux as of 1a95620. Signed-off-by: Alex Williamson Acked-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- linux-headers/linux/vfio.h | 368 +++++++++++++++++++++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 linux-headers/linux/vfio.h diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h new file mode 100644 index 0000000000..f787b727a9 --- /dev/null +++ b/linux-headers/linux/vfio.h @@ -0,0 +1,368 @@ +/* + * VFIO API definition + * + * Copyright (C) 2012 Red Hat, Inc. All rights reserved. + * Author: Alex Williamson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef VFIO_H +#define VFIO_H + +#include +#include + +#define VFIO_API_VERSION 0 + + +/* Kernel & User level defines for VFIO IOCTLs. */ + +/* Extensions */ + +#define VFIO_TYPE1_IOMMU 1 + +/* + * The IOCTL interface is designed for extensibility by embedding the + * structure length (argsz) and flags into structures passed between + * kernel and userspace. We therefore use the _IO() macro for these + * defines to avoid implicitly embedding a size into the ioctl request. + * As structure fields are added, argsz will increase to match and flag + * bits will be defined to indicate additional fields with valid data. + * It's *always* the caller's responsibility to indicate the size of + * the structure passed by setting argsz appropriately. + */ + +#define VFIO_TYPE (';') +#define VFIO_BASE 100 + +/* -------- IOCTLs for VFIO file descriptor (/dev/vfio/vfio) -------- */ + +/** + * VFIO_GET_API_VERSION - _IO(VFIO_TYPE, VFIO_BASE + 0) + * + * Report the version of the VFIO API. This allows us to bump the entire + * API version should we later need to add or change features in incompatible + * ways. + * Return: VFIO_API_VERSION + * Availability: Always + */ +#define VFIO_GET_API_VERSION _IO(VFIO_TYPE, VFIO_BASE + 0) + +/** + * VFIO_CHECK_EXTENSION - _IOW(VFIO_TYPE, VFIO_BASE + 1, __u32) + * + * Check whether an extension is supported. + * Return: 0 if not supported, 1 (or some other positive integer) if supported. + * Availability: Always + */ +#define VFIO_CHECK_EXTENSION _IO(VFIO_TYPE, VFIO_BASE + 1) + +/** + * VFIO_SET_IOMMU - _IOW(VFIO_TYPE, VFIO_BASE + 2, __s32) + * + * Set the iommu to the given type. The type must be supported by an + * iommu driver as verified by calling CHECK_EXTENSION using the same + * type. A group must be set to this file descriptor before this + * ioctl is available. The IOMMU interfaces enabled by this call are + * specific to the value set. + * Return: 0 on success, -errno on failure + * Availability: When VFIO group attached + */ +#define VFIO_SET_IOMMU _IO(VFIO_TYPE, VFIO_BASE + 2) + +/* -------- IOCTLs for GROUP file descriptors (/dev/vfio/$GROUP) -------- */ + +/** + * VFIO_GROUP_GET_STATUS - _IOR(VFIO_TYPE, VFIO_BASE + 3, + * struct vfio_group_status) + * + * Retrieve information about the group. Fills in provided + * struct vfio_group_info. Caller sets argsz. + * Return: 0 on succes, -errno on failure. + * Availability: Always + */ +struct vfio_group_status { + __u32 argsz; + __u32 flags; +#define VFIO_GROUP_FLAGS_VIABLE (1 << 0) +#define VFIO_GROUP_FLAGS_CONTAINER_SET (1 << 1) +}; +#define VFIO_GROUP_GET_STATUS _IO(VFIO_TYPE, VFIO_BASE + 3) + +/** + * VFIO_GROUP_SET_CONTAINER - _IOW(VFIO_TYPE, VFIO_BASE + 4, __s32) + * + * Set the container for the VFIO group to the open VFIO file + * descriptor provided. Groups may only belong to a single + * container. Containers may, at their discretion, support multiple + * groups. Only when a container is set are all of the interfaces + * of the VFIO file descriptor and the VFIO group file descriptor + * available to the user. + * Return: 0 on success, -errno on failure. + * Availability: Always + */ +#define VFIO_GROUP_SET_CONTAINER _IO(VFIO_TYPE, VFIO_BASE + 4) + +/** + * VFIO_GROUP_UNSET_CONTAINER - _IO(VFIO_TYPE, VFIO_BASE + 5) + * + * Remove the group from the attached container. This is the + * opposite of the SET_CONTAINER call and returns the group to + * an initial state. All device file descriptors must be released + * prior to calling this interface. When removing the last group + * from a container, the IOMMU will be disabled and all state lost, + * effectively also returning the VFIO file descriptor to an initial + * state. + * Return: 0 on success, -errno on failure. + * Availability: When attached to container + */ +#define VFIO_GROUP_UNSET_CONTAINER _IO(VFIO_TYPE, VFIO_BASE + 5) + +/** + * VFIO_GROUP_GET_DEVICE_FD - _IOW(VFIO_TYPE, VFIO_BASE + 6, char) + * + * Return a new file descriptor for the device object described by + * the provided string. The string should match a device listed in + * the devices subdirectory of the IOMMU group sysfs entry. The + * group containing the device must already be added to this context. + * Return: new file descriptor on success, -errno on failure. + * Availability: When attached to container + */ +#define VFIO_GROUP_GET_DEVICE_FD _IO(VFIO_TYPE, VFIO_BASE + 6) + +/* --------------- IOCTLs for DEVICE file descriptors --------------- */ + +/** + * VFIO_DEVICE_GET_INFO - _IOR(VFIO_TYPE, VFIO_BASE + 7, + * struct vfio_device_info) + * + * Retrieve information about the device. Fills in provided + * struct vfio_device_info. Caller sets argsz. + * Return: 0 on success, -errno on failure. + */ +struct vfio_device_info { + __u32 argsz; + __u32 flags; +#define VFIO_DEVICE_FLAGS_RESET (1 << 0) /* Device supports reset */ +#define VFIO_DEVICE_FLAGS_PCI (1 << 1) /* vfio-pci device */ + __u32 num_regions; /* Max region index + 1 */ + __u32 num_irqs; /* Max IRQ index + 1 */ +}; +#define VFIO_DEVICE_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 7) + +/** + * VFIO_DEVICE_GET_REGION_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 8, + * struct vfio_region_info) + * + * Retrieve information about a device region. Caller provides + * struct vfio_region_info with index value set. Caller sets argsz. + * Implementation of region mapping is bus driver specific. This is + * intended to describe MMIO, I/O port, as well as bus specific + * regions (ex. PCI config space). Zero sized regions may be used + * to describe unimplemented regions (ex. unimplemented PCI BARs). + * Return: 0 on success, -errno on failure. + */ +struct vfio_region_info { + __u32 argsz; + __u32 flags; +#define VFIO_REGION_INFO_FLAG_READ (1 << 0) /* Region supports read */ +#define VFIO_REGION_INFO_FLAG_WRITE (1 << 1) /* Region supports write */ +#define VFIO_REGION_INFO_FLAG_MMAP (1 << 2) /* Region supports mmap */ + __u32 index; /* Region index */ + __u32 resv; /* Reserved for alignment */ + __u64 size; /* Region size (bytes) */ + __u64 offset; /* Region offset from start of device fd */ +}; +#define VFIO_DEVICE_GET_REGION_INFO _IO(VFIO_TYPE, VFIO_BASE + 8) + +/** + * VFIO_DEVICE_GET_IRQ_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 9, + * struct vfio_irq_info) + * + * Retrieve information about a device IRQ. Caller provides + * struct vfio_irq_info with index value set. Caller sets argsz. + * Implementation of IRQ mapping is bus driver specific. Indexes + * using multiple IRQs are primarily intended to support MSI-like + * interrupt blocks. Zero count irq blocks may be used to describe + * unimplemented interrupt types. + * + * The EVENTFD flag indicates the interrupt index supports eventfd based + * signaling. + * + * The MASKABLE flags indicates the index supports MASK and UNMASK + * actions described below. + * + * AUTOMASKED indicates that after signaling, the interrupt line is + * automatically masked by VFIO and the user needs to unmask the line + * to receive new interrupts. This is primarily intended to distinguish + * level triggered interrupts. + * + * The NORESIZE flag indicates that the interrupt lines within the index + * are setup as a set and new subindexes cannot be enabled without first + * disabling the entire index. This is used for interrupts like PCI MSI + * and MSI-X where the driver may only use a subset of the available + * indexes, but VFIO needs to enable a specific number of vectors + * upfront. In the case of MSI-X, where the user can enable MSI-X and + * then add and unmask vectors, it's up to userspace to make the decision + * whether to allocate the maximum supported number of vectors or tear + * down setup and incrementally increase the vectors as each is enabled. + */ +struct vfio_irq_info { + __u32 argsz; + __u32 flags; +#define VFIO_IRQ_INFO_EVENTFD (1 << 0) +#define VFIO_IRQ_INFO_MASKABLE (1 << 1) +#define VFIO_IRQ_INFO_AUTOMASKED (1 << 2) +#define VFIO_IRQ_INFO_NORESIZE (1 << 3) + __u32 index; /* IRQ index */ + __u32 count; /* Number of IRQs within this index */ +}; +#define VFIO_DEVICE_GET_IRQ_INFO _IO(VFIO_TYPE, VFIO_BASE + 9) + +/** + * VFIO_DEVICE_SET_IRQS - _IOW(VFIO_TYPE, VFIO_BASE + 10, struct vfio_irq_set) + * + * Set signaling, masking, and unmasking of interrupts. Caller provides + * struct vfio_irq_set with all fields set. 'start' and 'count' indicate + * the range of subindexes being specified. + * + * The DATA flags specify the type of data provided. If DATA_NONE, the + * operation performs the specified action immediately on the specified + * interrupt(s). For example, to unmask AUTOMASKED interrupt [0,0]: + * flags = (DATA_NONE|ACTION_UNMASK), index = 0, start = 0, count = 1. + * + * DATA_BOOL allows sparse support for the same on arrays of interrupts. + * For example, to mask interrupts [0,1] and [0,3] (but not [0,2]): + * flags = (DATA_BOOL|ACTION_MASK), index = 0, start = 1, count = 3, + * data = {1,0,1} + * + * DATA_EVENTFD binds the specified ACTION to the provided __s32 eventfd. + * A value of -1 can be used to either de-assign interrupts if already + * assigned or skip un-assigned interrupts. For example, to set an eventfd + * to be trigger for interrupts [0,0] and [0,2]: + * flags = (DATA_EVENTFD|ACTION_TRIGGER), index = 0, start = 0, count = 3, + * data = {fd1, -1, fd2} + * If index [0,1] is previously set, two count = 1 ioctls calls would be + * required to set [0,0] and [0,2] without changing [0,1]. + * + * Once a signaling mechanism is set, DATA_BOOL or DATA_NONE can be used + * with ACTION_TRIGGER to perform kernel level interrupt loopback testing + * from userspace (ie. simulate hardware triggering). + * + * Setting of an event triggering mechanism to userspace for ACTION_TRIGGER + * enables the interrupt index for the device. Individual subindex interrupts + * can be disabled using the -1 value for DATA_EVENTFD or the index can be + * disabled as a whole with: flags = (DATA_NONE|ACTION_TRIGGER), count = 0. + * + * Note that ACTION_[UN]MASK specify user->kernel signaling (irqfds) while + * ACTION_TRIGGER specifies kernel->user signaling. + */ +struct vfio_irq_set { + __u32 argsz; + __u32 flags; +#define VFIO_IRQ_SET_DATA_NONE (1 << 0) /* Data not present */ +#define VFIO_IRQ_SET_DATA_BOOL (1 << 1) /* Data is bool (u8) */ +#define VFIO_IRQ_SET_DATA_EVENTFD (1 << 2) /* Data is eventfd (s32) */ +#define VFIO_IRQ_SET_ACTION_MASK (1 << 3) /* Mask interrupt */ +#define VFIO_IRQ_SET_ACTION_UNMASK (1 << 4) /* Unmask interrupt */ +#define VFIO_IRQ_SET_ACTION_TRIGGER (1 << 5) /* Trigger interrupt */ + __u32 index; + __u32 start; + __u32 count; + __u8 data[]; +}; +#define VFIO_DEVICE_SET_IRQS _IO(VFIO_TYPE, VFIO_BASE + 10) + +#define VFIO_IRQ_SET_DATA_TYPE_MASK (VFIO_IRQ_SET_DATA_NONE | \ + VFIO_IRQ_SET_DATA_BOOL | \ + VFIO_IRQ_SET_DATA_EVENTFD) +#define VFIO_IRQ_SET_ACTION_TYPE_MASK (VFIO_IRQ_SET_ACTION_MASK | \ + VFIO_IRQ_SET_ACTION_UNMASK | \ + VFIO_IRQ_SET_ACTION_TRIGGER) +/** + * VFIO_DEVICE_RESET - _IO(VFIO_TYPE, VFIO_BASE + 11) + * + * Reset a device. + */ +#define VFIO_DEVICE_RESET _IO(VFIO_TYPE, VFIO_BASE + 11) + +/* + * The VFIO-PCI bus driver makes use of the following fixed region and + * IRQ index mapping. Unimplemented regions return a size of zero. + * Unimplemented IRQ types return a count of zero. + */ + +enum { + VFIO_PCI_BAR0_REGION_INDEX, + VFIO_PCI_BAR1_REGION_INDEX, + VFIO_PCI_BAR2_REGION_INDEX, + VFIO_PCI_BAR3_REGION_INDEX, + VFIO_PCI_BAR4_REGION_INDEX, + VFIO_PCI_BAR5_REGION_INDEX, + VFIO_PCI_ROM_REGION_INDEX, + VFIO_PCI_CONFIG_REGION_INDEX, + VFIO_PCI_NUM_REGIONS +}; + +enum { + VFIO_PCI_INTX_IRQ_INDEX, + VFIO_PCI_MSI_IRQ_INDEX, + VFIO_PCI_MSIX_IRQ_INDEX, + VFIO_PCI_NUM_IRQS +}; + +/* -------- API for Type1 VFIO IOMMU -------- */ + +/** + * VFIO_IOMMU_GET_INFO - _IOR(VFIO_TYPE, VFIO_BASE + 12, struct vfio_iommu_info) + * + * Retrieve information about the IOMMU object. Fills in provided + * struct vfio_iommu_info. Caller sets argsz. + * + * XXX Should we do these by CHECK_EXTENSION too? + */ +struct vfio_iommu_type1_info { + __u32 argsz; + __u32 flags; +#define VFIO_IOMMU_INFO_PGSIZES (1 << 0) /* supported page sizes info */ + __u64 iova_pgsizes; /* Bitmap of supported page sizes */ +}; + +#define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12) + +/** + * VFIO_IOMMU_MAP_DMA - _IOW(VFIO_TYPE, VFIO_BASE + 13, struct vfio_dma_map) + * + * Map process virtual addresses to IO virtual addresses using the + * provided struct vfio_dma_map. Caller sets argsz. READ &/ WRITE required. + */ +struct vfio_iommu_type1_dma_map { + __u32 argsz; + __u32 flags; +#define VFIO_DMA_MAP_FLAG_READ (1 << 0) /* readable from device */ +#define VFIO_DMA_MAP_FLAG_WRITE (1 << 1) /* writable from device */ + __u64 vaddr; /* Process virtual address */ + __u64 iova; /* IO virtual address */ + __u64 size; /* Size of mapping (bytes) */ +}; + +#define VFIO_IOMMU_MAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 13) + +/** + * VFIO_IOMMU_UNMAP_DMA - _IOW(VFIO_TYPE, VFIO_BASE + 14, struct vfio_dma_unmap) + * + * Unmap IO virtual addresses using the provided struct vfio_dma_unmap. + * Caller sets argsz. + */ +struct vfio_iommu_type1_dma_unmap { + __u32 argsz; + __u32 flags; + __u64 iova; /* IO virtual address */ + __u64 size; /* Size of mapping (bytes) */ +}; + +#define VFIO_IOMMU_UNMAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 14) + +#endif /* VFIO_H */ From 65501a745dbaf28284e099f724aa5fc478eae0e7 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 26 Sep 2012 11:19:32 -0600 Subject: [PATCH 0670/2270] vfio: vfio-pci device assignment driver This adds the core of the QEMU VFIO-based PCI device assignment driver. To make use of this driver, enable CONFIG_VFIO, CONFIG_VFIO_IOMMU_TYPE1, and CONFIG_VFIO_PCI in your host Linux kernel config. Load the vfio-pci module. To assign device 0000:05:00.0 to a guest, do the following: for dev in $(ls /sys/bus/pci/devices/0000:05:00.0/iommu_group/devices); do vendor=$(cat /sys/bus/pci/devices/$dev/vendor) device=$(cat /sys/bus/pci/devices/$dev/device) if [ -e /sys/bus/pci/devices/$dev/driver ]; then echo $dev > /sys/bus/pci/devices/$dev/driver/unbind fi echo $vendor $device > /sys/bus/pci/drivers/vfio-pci/new_id done See Documentation/vfio.txt in the Linux kernel tree for further description of IOMMU groups and VFIO. Then launch qemu including the option: -device vfio-pci,host=0000:05:00.0 Legacy PCI interrupts (INTx) currently makes use of a kludge where we trap BAR accesses and assume the access is in response to an interrupt, therefore de-asserting and unmasking the interrupt. It's not quite as targetted as using the EOI for this, but it's self contained and seems to work across all architectures. The side-effect is a significant performance slow-down for device in INTx mode. Some devices, like graphics cards, don't really use their interrupt, so this can be turned off with the x-intx=off option, which disables INTx alltogether. This should be considered an experimental option until we refine this code. Both MSI and MSI-X are supported and avoid these issues. Signed-off-by: Alex Williamson Acked-by: Michael S. Tsirkin Signed-off-by: Anthony Liguori --- hw/vfio_pci.c | 1864 +++++++++++++++++++++++++++++++++++++++++++++ hw/vfio_pci_int.h | 114 +++ 2 files changed, 1978 insertions(+) create mode 100644 hw/vfio_pci.c create mode 100644 hw/vfio_pci_int.h diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c new file mode 100644 index 0000000000..a24558aaa0 --- /dev/null +++ b/hw/vfio_pci.c @@ -0,0 +1,1864 @@ +/* + * vfio based device assignment support + * + * Copyright Red Hat, Inc. 2012 + * + * Authors: + * Alex Williamson + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Based on qemu-kvm device-assignment: + * Adapted for KVM by Qumranet. + * Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com) + * Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com) + * Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com) + * Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com) + * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "event_notifier.h" +#include "exec-memory.h" +#include "kvm.h" +#include "memory.h" +#include "msi.h" +#include "msix.h" +#include "qemu-error.h" +#include "range.h" +#include "vfio_pci_int.h" + +/* #define DEBUG_VFIO */ +#ifdef DEBUG_VFIO +#define DPRINTF(fmt, ...) \ + do { fprintf(stderr, "vfio: " fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ + do { } while (0) +#endif + +#define MSIX_CAP_LENGTH 12 + +static QLIST_HEAD(, VFIOContainer) + container_list = QLIST_HEAD_INITIALIZER(container_list); + +static QLIST_HEAD(, VFIOGroup) + group_list = QLIST_HEAD_INITIALIZER(group_list); + +static void vfio_disable_interrupts(VFIODevice *vdev); +static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len); +static void vfio_mmap_set_enabled(VFIODevice *vdev, bool enabled); + +/* + * Common VFIO interrupt disable + */ +static void vfio_disable_irqindex(VFIODevice *vdev, int index) +{ + struct vfio_irq_set irq_set = { + .argsz = sizeof(irq_set), + .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER, + .index = index, + .start = 0, + .count = 0, + }; + + ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); + + vdev->interrupt = VFIO_INT_NONE; +} + +/* + * INTx + */ +static void vfio_unmask_intx(VFIODevice *vdev) +{ + struct vfio_irq_set irq_set = { + .argsz = sizeof(irq_set), + .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_UNMASK, + .index = VFIO_PCI_INTX_IRQ_INDEX, + .start = 0, + .count = 1, + }; + + ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); +} + +static void vfio_intx_interrupt(void *opaque) +{ + VFIODevice *vdev = opaque; + + if (!event_notifier_test_and_clear(&vdev->intx.interrupt)) { + return; + } + + DPRINTF("%s(%04x:%02x:%02x.%x) Pin %c\n", __func__, vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function, + 'A' + vdev->intx.pin); + + vdev->intx.pending = true; + qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 1); +} + +static void vfio_eoi(VFIODevice *vdev) +{ + if (!vdev->intx.pending) { + return; + } + + DPRINTF("%s(%04x:%02x:%02x.%x) EOI\n", __func__, vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function); + + vdev->intx.pending = false; + qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0); + vfio_unmask_intx(vdev); +} + +typedef struct QEMU_PACKED VFIOIRQSetFD { + struct vfio_irq_set irq_set; + int32_t fd; +} VFIOIRQSetFD; + +static int vfio_enable_intx(VFIODevice *vdev) +{ + VFIOIRQSetFD irq_set_fd = { + .irq_set = { + .argsz = sizeof(irq_set_fd), + .flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER, + .index = VFIO_PCI_INTX_IRQ_INDEX, + .start = 0, + .count = 1, + }, + }; + uint8_t pin = vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1); + int ret; + + if (vdev->intx.disabled || !pin) { + return 0; + } + + vfio_disable_interrupts(vdev); + + vdev->intx.pin = pin - 1; /* Pin A (1) -> irq[0] */ + ret = event_notifier_init(&vdev->intx.interrupt, 0); + if (ret) { + error_report("vfio: Error: event_notifier_init failed\n"); + return ret; + } + + irq_set_fd.fd = event_notifier_get_fd(&vdev->intx.interrupt); + qemu_set_fd_handler(irq_set_fd.fd, vfio_intx_interrupt, NULL, vdev); + + if (ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set_fd)) { + error_report("vfio: Error: Failed to setup INTx fd: %m\n"); + return -errno; + } + + /* + * Disable mmaps so we can trap on BAR accesses. We interpret any + * access as a response to an interrupt and unmask the physical + * device. The device will re-assert if the interrupt is still + * pending. We'll likely retrigger on the host multiple times per + * guest interrupt, but without EOI notification it's better than + * nothing. Acceleration paths through KVM will avoid this. + */ + vfio_mmap_set_enabled(vdev, false); + + vdev->interrupt = VFIO_INT_INTx; + + DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function); + + return 0; +} + +static void vfio_disable_intx(VFIODevice *vdev) +{ + int fd; + + vfio_disable_irqindex(vdev, VFIO_PCI_INTX_IRQ_INDEX); + vdev->intx.pending = false; + qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0); + vfio_mmap_set_enabled(vdev, true); + + fd = event_notifier_get_fd(&vdev->intx.interrupt); + qemu_set_fd_handler(fd, NULL, NULL, vdev); + event_notifier_cleanup(&vdev->intx.interrupt); + + vdev->interrupt = VFIO_INT_NONE; + + DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function); +} + +/* + * MSI/X + */ +static void vfio_msi_interrupt(void *opaque) +{ + VFIOMSIVector *vector = opaque; + VFIODevice *vdev = vector->vdev; + int nr = vector - vdev->msi_vectors; + + if (!event_notifier_test_and_clear(&vector->interrupt)) { + return; + } + + DPRINTF("%s(%04x:%02x:%02x.%x) vector %d\n", __func__, + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function, nr); + + if (vdev->interrupt == VFIO_INT_MSIX) { + msix_notify(&vdev->pdev, nr); + } else if (vdev->interrupt == VFIO_INT_MSI) { + msi_notify(&vdev->pdev, nr); + } else { + error_report("vfio: MSI interrupt receieved, but not enabled?\n"); + } +} + +static int vfio_enable_vectors(VFIODevice *vdev, bool msix) +{ + struct vfio_irq_set *irq_set; + int ret = 0, i, argsz; + int32_t *fds; + + argsz = sizeof(*irq_set) + (vdev->nr_vectors * sizeof(*fds)); + + irq_set = g_malloc0(argsz); + irq_set->argsz = argsz; + irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER; + irq_set->index = msix ? VFIO_PCI_MSIX_IRQ_INDEX : VFIO_PCI_MSI_IRQ_INDEX; + irq_set->start = 0; + irq_set->count = vdev->nr_vectors; + fds = (int32_t *)&irq_set->data; + + for (i = 0; i < vdev->nr_vectors; i++) { + if (!vdev->msi_vectors[i].use) { + fds[i] = -1; + continue; + } + + fds[i] = event_notifier_get_fd(&vdev->msi_vectors[i].interrupt); + } + + ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set); + + g_free(irq_set); + + if (!ret) { + vdev->interrupt = msix ? VFIO_INT_MSIX : VFIO_INT_MSI; + } + + return ret; +} + +static int vfio_msix_vector_use(PCIDevice *pdev, + unsigned int nr, MSIMessage msg) +{ + VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev); + VFIOMSIVector *vector; + int ret; + + DPRINTF("%s(%04x:%02x:%02x.%x) vector %d used\n", __func__, + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function, nr); + + if (vdev->interrupt != VFIO_INT_MSIX) { + vfio_disable_interrupts(vdev); + } + + if (!vdev->msi_vectors) { + vdev->msi_vectors = g_malloc0(vdev->msix->entries * + sizeof(VFIOMSIVector)); + } + + vector = &vdev->msi_vectors[nr]; + vector->vdev = vdev; + vector->use = true; + + msix_vector_use(pdev, nr); + + if (event_notifier_init(&vector->interrupt, 0)) { + error_report("vfio: Error: event_notifier_init failed\n"); + } + + /* + * Attempt to enable route through KVM irqchip, + * default to userspace handling if unavailable. + */ + vector->virq = kvm_irqchip_add_msi_route(kvm_state, msg); + if (vector->virq < 0 || + kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt, + vector->virq) < 0) { + if (vector->virq >= 0) { + kvm_irqchip_release_virq(kvm_state, vector->virq); + vector->virq = -1; + } + qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), + vfio_msi_interrupt, NULL, vector); + } + + /* + * We don't want to have the host allocate all possible MSI vectors + * for a device if they're not in use, so we shutdown and incrementally + * increase them as needed. + */ + if (vdev->nr_vectors < nr + 1) { + int i; + + vfio_disable_irqindex(vdev, VFIO_PCI_MSIX_IRQ_INDEX); + vdev->nr_vectors = nr + 1; + ret = vfio_enable_vectors(vdev, true); + if (ret) { + error_report("vfio: failed to enable vectors, %d\n", ret); + } + + /* We don't know if we've missed interrupts in the interim... */ + for (i = 0; i < vdev->msix->entries; i++) { + if (vdev->msi_vectors[i].use) { + msix_notify(&vdev->pdev, i); + } + } + } else { + VFIOIRQSetFD irq_set_fd = { + .irq_set = { + .argsz = sizeof(irq_set_fd), + .flags = VFIO_IRQ_SET_DATA_EVENTFD | + VFIO_IRQ_SET_ACTION_TRIGGER, + .index = VFIO_PCI_MSIX_IRQ_INDEX, + .start = nr, + .count = 1, + }, + .fd = event_notifier_get_fd(&vector->interrupt), + }; + ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set_fd); + if (ret) { + error_report("vfio: failed to modify vector, %d\n", ret); + } + + /* + * If we were connected to the hardware PBA we could skip this, + * until then, a spurious interrupt is better than starvation. + */ + msix_notify(&vdev->pdev, nr); + } + + return 0; +} + +static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr) +{ + VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev); + VFIOMSIVector *vector = &vdev->msi_vectors[nr]; + VFIOIRQSetFD irq_set_fd = { + .irq_set = { + .argsz = sizeof(irq_set_fd), + .flags = VFIO_IRQ_SET_DATA_EVENTFD | + VFIO_IRQ_SET_ACTION_TRIGGER, + .index = VFIO_PCI_MSIX_IRQ_INDEX, + .start = nr, + .count = 1, + }, + .fd = -1, + }; + + DPRINTF("%s(%04x:%02x:%02x.%x) vector %d released\n", __func__, + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function, nr); + + /* + * XXX What's the right thing to do here? This turns off the interrupt + * completely, but do we really just want to switch the interrupt to + * bouncing through userspace and let msix.c drop it? Not sure. + */ + msix_vector_unuse(pdev, nr); + ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set_fd); + + if (vector->virq < 0) { + qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), + NULL, NULL, NULL); + } else { + kvm_irqchip_remove_irqfd_notifier(kvm_state, &vector->interrupt, + vector->virq); + kvm_irqchip_release_virq(kvm_state, vector->virq); + vector->virq = -1; + } + + event_notifier_cleanup(&vector->interrupt); + vector->use = false; +} + +/* TODO This should move to msi.c */ +static MSIMessage msi_get_msg(PCIDevice *pdev, unsigned int vector) +{ + uint16_t flags = pci_get_word(pdev->config + pdev->msi_cap + PCI_MSI_FLAGS); + bool msi64bit = flags & PCI_MSI_FLAGS_64BIT; + MSIMessage msg; + + if (msi64bit) { + msg.address = pci_get_quad(pdev->config + + pdev->msi_cap + PCI_MSI_ADDRESS_LO); + } else { + msg.address = pci_get_long(pdev->config + + pdev->msi_cap + PCI_MSI_ADDRESS_LO); + } + + msg.data = pci_get_word(pdev->config + pdev->msi_cap + + (msi64bit ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32)); + msg.data += vector; + + return msg; +} + +/* So should this */ +static void msi_set_qsize(PCIDevice *pdev, uint8_t size) +{ + uint8_t *config = pdev->config + pdev->msi_cap; + uint16_t flags; + + flags = pci_get_word(config + PCI_MSI_FLAGS); + flags = le16_to_cpu(flags); + flags &= ~PCI_MSI_FLAGS_QSIZE; + flags |= (size & 0x7) << 4; + flags = cpu_to_le16(flags); + pci_set_word(config + PCI_MSI_FLAGS, flags); +} + +static void vfio_enable_msi(VFIODevice *vdev) +{ + int ret, i; + + vfio_disable_interrupts(vdev); + + vdev->nr_vectors = msi_nr_vectors_allocated(&vdev->pdev); +retry: + vdev->msi_vectors = g_malloc0(vdev->nr_vectors * sizeof(VFIOMSIVector)); + + for (i = 0; i < vdev->nr_vectors; i++) { + MSIMessage msg; + VFIOMSIVector *vector = &vdev->msi_vectors[i]; + + vector->vdev = vdev; + vector->use = true; + + if (event_notifier_init(&vector->interrupt, 0)) { + error_report("vfio: Error: event_notifier_init failed\n"); + } + + msg = msi_get_msg(&vdev->pdev, i); + + /* + * Attempt to enable route through KVM irqchip, + * default to userspace handling if unavailable. + */ + vector->virq = kvm_irqchip_add_msi_route(kvm_state, msg); + if (vector->virq < 0 || + kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt, + vector->virq) < 0) { + qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), + vfio_msi_interrupt, NULL, vector); + } + } + + ret = vfio_enable_vectors(vdev, false); + if (ret) { + if (ret < 0) { + error_report("vfio: Error: Failed to setup MSI fds: %m\n"); + } else if (ret != vdev->nr_vectors) { + error_report("vfio: Error: Failed to enable %d " + "MSI vectors, retry with %d\n", vdev->nr_vectors, ret); + } + + for (i = 0; i < vdev->nr_vectors; i++) { + VFIOMSIVector *vector = &vdev->msi_vectors[i]; + if (vector->virq >= 0) { + kvm_irqchip_remove_irqfd_notifier(kvm_state, &vector->interrupt, + vector->virq); + kvm_irqchip_release_virq(kvm_state, vector->virq); + vector->virq = -1; + } else { + qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), + NULL, NULL, NULL); + } + event_notifier_cleanup(&vector->interrupt); + } + + g_free(vdev->msi_vectors); + + if (ret > 0 && ret != vdev->nr_vectors) { + vdev->nr_vectors = ret; + goto retry; + } + vdev->nr_vectors = 0; + + return; + } + + msi_set_qsize(&vdev->pdev, vdev->nr_vectors); + + DPRINTF("%s(%04x:%02x:%02x.%x) Enabled %d MSI vectors\n", __func__, + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function, vdev->nr_vectors); +} + +static void vfio_disable_msi_x(VFIODevice *vdev, bool msix) +{ + int i; + + vfio_disable_irqindex(vdev, msix ? VFIO_PCI_MSIX_IRQ_INDEX : + VFIO_PCI_MSI_IRQ_INDEX); + + for (i = 0; i < vdev->nr_vectors; i++) { + VFIOMSIVector *vector = &vdev->msi_vectors[i]; + + if (!vector->use) { + continue; + } + + if (vector->virq >= 0) { + kvm_irqchip_remove_irqfd_notifier(kvm_state, + &vector->interrupt, vector->virq); + kvm_irqchip_release_virq(kvm_state, vector->virq); + vector->virq = -1; + } else { + qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), + NULL, NULL, NULL); + } + + if (msix) { + msix_vector_unuse(&vdev->pdev, i); + } + + event_notifier_cleanup(&vector->interrupt); + } + + g_free(vdev->msi_vectors); + vdev->msi_vectors = NULL; + vdev->nr_vectors = 0; + + if (!msix) { + msi_set_qsize(&vdev->pdev, 0); /* Actually still means 1 vector */ + } + + DPRINTF("%s(%04x:%02x:%02x.%x, msi%s)\n", __func__, + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function, msix ? "x" : ""); + + vfio_enable_intx(vdev); +} + +/* + * IO Port/MMIO - Beware of the endians, VFIO is always little endian + */ +static void vfio_bar_write(void *opaque, target_phys_addr_t addr, + uint64_t data, unsigned size) +{ + VFIOBAR *bar = opaque; + union { + uint8_t byte; + uint16_t word; + uint32_t dword; + uint64_t qword; + } buf; + + switch (size) { + case 1: + buf.byte = data; + break; + case 2: + buf.word = cpu_to_le16(data); + break; + case 4: + buf.dword = cpu_to_le32(data); + break; + default: + hw_error("vfio: unsupported write size, %d bytes\n", size); + break; + } + + if (pwrite(bar->fd, &buf, size, bar->fd_offset + addr) != size) { + error_report("%s(,0x%"TARGET_PRIxPHYS", 0x%"PRIx64", %d) failed: %m\n", + __func__, addr, data, size); + } + + DPRINTF("%s(BAR%d+0x%"TARGET_PRIxPHYS", 0x%"PRIx64", %d)\n", + __func__, bar->nr, addr, data, size); + + /* + * A read or write to a BAR always signals an INTx EOI. This will + * do nothing if not pending (including not in INTx mode). We assume + * that a BAR access is in response to an interrupt and that BAR + * accesses will service the interrupt. Unfortunately, we don't know + * which access will service the interrupt, so we're potentially + * getting quite a few host interrupts per guest interrupt. + */ + vfio_eoi(DO_UPCAST(VFIODevice, bars[bar->nr], bar)); +} + +static uint64_t vfio_bar_read(void *opaque, + target_phys_addr_t addr, unsigned size) +{ + VFIOBAR *bar = opaque; + union { + uint8_t byte; + uint16_t word; + uint32_t dword; + uint64_t qword; + } buf; + uint64_t data = 0; + + if (pread(bar->fd, &buf, size, bar->fd_offset + addr) != size) { + error_report("%s(,0x%"TARGET_PRIxPHYS", %d) failed: %m\n", + __func__, addr, size); + return (uint64_t)-1; + } + + switch (size) { + case 1: + data = buf.byte; + break; + case 2: + data = le16_to_cpu(buf.word); + break; + case 4: + data = le32_to_cpu(buf.dword); + break; + default: + hw_error("vfio: unsupported read size, %d bytes\n", size); + break; + } + + DPRINTF("%s(BAR%d+0x%"TARGET_PRIxPHYS", %d) = 0x%"PRIx64"\n", + __func__, bar->nr, addr, size, data); + + /* Same as write above */ + vfio_eoi(DO_UPCAST(VFIODevice, bars[bar->nr], bar)); + + return data; +} + +static const MemoryRegionOps vfio_bar_ops = { + .read = vfio_bar_read, + .write = vfio_bar_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +/* + * PCI config space + */ +static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len) +{ + VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev); + uint32_t val = 0; + + /* + * We only need QEMU PCI config support for the ROM BAR, the MSI and MSIX + * capabilities, and the multifunction bit below. We let VFIO handle + * virtualizing everything else. Performance is not a concern here. + */ + if (ranges_overlap(addr, len, PCI_ROM_ADDRESS, 4) || + (pdev->cap_present & QEMU_PCI_CAP_MSIX && + ranges_overlap(addr, len, pdev->msix_cap, MSIX_CAP_LENGTH)) || + (pdev->cap_present & QEMU_PCI_CAP_MSI && + ranges_overlap(addr, len, pdev->msi_cap, vdev->msi_cap_size))) { + + val = pci_default_read_config(pdev, addr, len); + } else { + if (pread(vdev->fd, &val, len, vdev->config_offset + addr) != len) { + error_report("%s(%04x:%02x:%02x.%x, 0x%x, 0x%x) failed: %m\n", + __func__, vdev->host.domain, vdev->host.bus, + vdev->host.slot, vdev->host.function, addr, len); + return -errno; + } + val = le32_to_cpu(val); + } + + /* Multifunction bit is virualized in QEMU */ + if (unlikely(ranges_overlap(addr, len, PCI_HEADER_TYPE, 1))) { + uint32_t mask = PCI_HEADER_TYPE_MULTI_FUNCTION; + + if (len == 4) { + mask <<= 16; + } + + if (pdev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) { + val |= mask; + } else { + val &= ~mask; + } + } + + DPRINTF("%s(%04x:%02x:%02x.%x, @0x%x, len=0x%x) %x\n", __func__, + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function, addr, len, val); + + return val; +} + +static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr, + uint32_t val, int len) +{ + VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev); + uint32_t val_le = cpu_to_le32(val); + + DPRINTF("%s(%04x:%02x:%02x.%x, @0x%x, 0x%x, len=0x%x)\n", __func__, + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function, addr, val, len); + + /* Write everything to VFIO, let it filter out what we can't write */ + if (pwrite(vdev->fd, &val_le, len, vdev->config_offset + addr) != len) { + error_report("%s(%04x:%02x:%02x.%x, 0x%x, 0x%x, 0x%x) failed: %m\n", + __func__, vdev->host.domain, vdev->host.bus, + vdev->host.slot, vdev->host.function, addr, val, len); + } + + /* Write standard header bits to emulation */ + if (addr < PCI_CONFIG_HEADER_SIZE) { + pci_default_write_config(pdev, addr, val, len); + return; + } + + /* MSI/MSI-X Enabling/Disabling */ + if (pdev->cap_present & QEMU_PCI_CAP_MSI && + ranges_overlap(addr, len, pdev->msi_cap, vdev->msi_cap_size)) { + int is_enabled, was_enabled = msi_enabled(pdev); + + pci_default_write_config(pdev, addr, val, len); + + is_enabled = msi_enabled(pdev); + + if (!was_enabled && is_enabled) { + vfio_enable_msi(vdev); + } else if (was_enabled && !is_enabled) { + vfio_disable_msi_x(vdev, false); + } + } + + if (pdev->cap_present & QEMU_PCI_CAP_MSIX && + ranges_overlap(addr, len, pdev->msix_cap, MSIX_CAP_LENGTH)) { + int is_enabled, was_enabled = msix_enabled(pdev); + + pci_default_write_config(pdev, addr, val, len); + + is_enabled = msix_enabled(pdev); + + if (!was_enabled && is_enabled) { + /* vfio_msix_vector_use handles this automatically */ + } else if (was_enabled && !is_enabled) { + vfio_disable_msi_x(vdev, true); + } + } +} + +/* + * DMA - Mapping and unmapping for the "type1" IOMMU interface used on x86 + */ +static int vfio_dma_map(VFIOContainer *container, target_phys_addr_t iova, + ram_addr_t size, void *vaddr, bool readonly) +{ + struct vfio_iommu_type1_dma_map map = { + .argsz = sizeof(map), + .flags = VFIO_DMA_MAP_FLAG_READ, + .vaddr = (__u64)vaddr, + .iova = iova, + .size = size, + }; + + if (!readonly) { + map.flags |= VFIO_DMA_MAP_FLAG_WRITE; + } + + if (ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map)) { + DPRINTF("VFIO_MAP_DMA: %d\n", -errno); + return -errno; + } + + return 0; +} + +static int vfio_dma_unmap(VFIOContainer *container, + target_phys_addr_t iova, ram_addr_t size) +{ + struct vfio_iommu_type1_dma_unmap unmap = { + .argsz = sizeof(unmap), + .flags = 0, + .iova = iova, + .size = size, + }; + + if (ioctl(container->fd, VFIO_IOMMU_UNMAP_DMA, &unmap)) { + DPRINTF("VFIO_UNMAP_DMA: %d\n", -errno); + return -errno; + } + + return 0; +} + +static void vfio_listener_dummy1(MemoryListener *listener) +{ + /* We don't do batching (begin/commit) or care about logging */ +} + +static void vfio_listener_dummy2(MemoryListener *listener, + MemoryRegionSection *section) +{ + /* We don't do logging or care about nops */ +} + +static void vfio_listener_dummy3(MemoryListener *listener, + MemoryRegionSection *section, + bool match_data, uint64_t data, + EventNotifier *e) +{ + /* We don't care about eventfds */ +} + +static bool vfio_listener_skipped_section(MemoryRegionSection *section) +{ + return !memory_region_is_ram(section->mr); +} + +static void vfio_listener_region_add(MemoryListener *listener, + MemoryRegionSection *section) +{ + VFIOContainer *container = container_of(listener, VFIOContainer, + iommu_data.listener); + target_phys_addr_t iova, end; + void *vaddr; + int ret; + + if (vfio_listener_skipped_section(section)) { + DPRINTF("vfio: SKIPPING region_add %"TARGET_PRIxPHYS" - %"PRIx64"\n", + section->offset_within_address_space, + section->offset_within_address_space + section->size - 1); + return; + } + + if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) != + (section->offset_within_region & ~TARGET_PAGE_MASK))) { + error_report("%s received unaligned region\n", __func__); + return; + } + + iova = TARGET_PAGE_ALIGN(section->offset_within_address_space); + end = (section->offset_within_address_space + section->size) & + TARGET_PAGE_MASK; + + if (iova >= end) { + return; + } + + vaddr = memory_region_get_ram_ptr(section->mr) + + section->offset_within_region + + (iova - section->offset_within_address_space); + + DPRINTF("vfio: region_add %"TARGET_PRIxPHYS" - %"TARGET_PRIxPHYS" [%p]\n", + iova, end - 1, vaddr); + + ret = vfio_dma_map(container, iova, end - iova, vaddr, section->readonly); + if (ret) { + error_report("vfio_dma_map(%p, 0x%"TARGET_PRIxPHYS", " + "0x%"TARGET_PRIxPHYS", %p) = %d (%m)\n", + container, iova, end - iova, vaddr, ret); + } +} + +static void vfio_listener_region_del(MemoryListener *listener, + MemoryRegionSection *section) +{ + VFIOContainer *container = container_of(listener, VFIOContainer, + iommu_data.listener); + target_phys_addr_t iova, end; + int ret; + + if (vfio_listener_skipped_section(section)) { + DPRINTF("vfio: SKIPPING region_del %"TARGET_PRIxPHYS" - %"PRIx64"\n", + section->offset_within_address_space, + section->offset_within_address_space + section->size - 1); + return; + } + + if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) != + (section->offset_within_region & ~TARGET_PAGE_MASK))) { + error_report("%s received unaligned region\n", __func__); + return; + } + + iova = TARGET_PAGE_ALIGN(section->offset_within_address_space); + end = (section->offset_within_address_space + section->size) & + TARGET_PAGE_MASK; + + if (iova >= end) { + return; + } + + DPRINTF("vfio: region_del %"TARGET_PRIxPHYS" - %"TARGET_PRIxPHYS"\n", + iova, end - 1); + + ret = vfio_dma_unmap(container, iova, end - iova); + if (ret) { + error_report("vfio_dma_unmap(%p, 0x%"TARGET_PRIxPHYS", " + "0x%"TARGET_PRIxPHYS") = %d (%m)\n", + container, iova, end - iova, ret); + } +} + +static MemoryListener vfio_memory_listener = { + .begin = vfio_listener_dummy1, + .commit = vfio_listener_dummy1, + .region_add = vfio_listener_region_add, + .region_del = vfio_listener_region_del, + .region_nop = vfio_listener_dummy2, + .log_start = vfio_listener_dummy2, + .log_stop = vfio_listener_dummy2, + .log_sync = vfio_listener_dummy2, + .log_global_start = vfio_listener_dummy1, + .log_global_stop = vfio_listener_dummy1, + .eventfd_add = vfio_listener_dummy3, + .eventfd_del = vfio_listener_dummy3, +}; + +static void vfio_listener_release(VFIOContainer *container) +{ + memory_listener_unregister(&container->iommu_data.listener); +} + +/* + * Interrupt setup + */ +static void vfio_disable_interrupts(VFIODevice *vdev) +{ + switch (vdev->interrupt) { + case VFIO_INT_INTx: + vfio_disable_intx(vdev); + break; + case VFIO_INT_MSI: + vfio_disable_msi_x(vdev, false); + break; + case VFIO_INT_MSIX: + vfio_disable_msi_x(vdev, true); + break; + } +} + +static int vfio_setup_msi(VFIODevice *vdev, int pos) +{ + uint16_t ctrl; + bool msi_64bit, msi_maskbit; + int ret, entries; + + /* + * TODO: don't peek into msi_supported, let msi_init fail and + * check for ENOTSUP + */ + if (!msi_supported) { + return 0; + } + + if (pread(vdev->fd, &ctrl, sizeof(ctrl), + vdev->config_offset + pos + PCI_CAP_FLAGS) != sizeof(ctrl)) { + return -errno; + } + ctrl = le16_to_cpu(ctrl); + + msi_64bit = !!(ctrl & PCI_MSI_FLAGS_64BIT); + msi_maskbit = !!(ctrl & PCI_MSI_FLAGS_MASKBIT); + entries = 1 << ((ctrl & PCI_MSI_FLAGS_QMASK) >> 1); + + DPRINTF("%04x:%02x:%02x.%x PCI MSI CAP @0x%x\n", vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function, pos); + + ret = msi_init(&vdev->pdev, pos, entries, msi_64bit, msi_maskbit); + if (ret < 0) { + error_report("vfio: msi_init failed\n"); + return ret; + } + vdev->msi_cap_size = 0xa + (msi_maskbit ? 0xa : 0) + (msi_64bit ? 0x4 : 0); + + return 0; +} + +/* + * We don't have any control over how pci_add_capability() inserts + * capabilities into the chain. In order to setup MSI-X we need a + * MemoryRegion for the BAR. In order to setup the BAR and not + * attempt to mmap the MSI-X table area, which VFIO won't allow, we + * need to first look for where the MSI-X table lives. So we + * unfortunately split MSI-X setup across two functions. + */ +static int vfio_early_setup_msix(VFIODevice *vdev) +{ + uint8_t pos; + uint16_t ctrl; + uint32_t table, pba; + + pos = pci_find_capability(&vdev->pdev, PCI_CAP_ID_MSIX); + if (!pos) { + return 0; + } + + if (pread(vdev->fd, &ctrl, sizeof(ctrl), + vdev->config_offset + pos + PCI_CAP_FLAGS) != sizeof(ctrl)) { + return -errno; + } + + if (pread(vdev->fd, &table, sizeof(table), + vdev->config_offset + pos + PCI_MSIX_TABLE) != sizeof(table)) { + return -errno; + } + + if (pread(vdev->fd, &pba, sizeof(pba), + vdev->config_offset + pos + PCI_MSIX_PBA) != sizeof(pba)) { + return -errno; + } + + ctrl = le16_to_cpu(ctrl); + table = le32_to_cpu(table); + pba = le32_to_cpu(pba); + + vdev->msix = g_malloc0(sizeof(*(vdev->msix))); + vdev->msix->table_bar = table & PCI_MSIX_FLAGS_BIRMASK; + vdev->msix->table_offset = table & ~PCI_MSIX_FLAGS_BIRMASK; + vdev->msix->pba_bar = pba & PCI_MSIX_FLAGS_BIRMASK; + vdev->msix->pba_offset = pba & ~PCI_MSIX_FLAGS_BIRMASK; + vdev->msix->entries = (ctrl & PCI_MSIX_FLAGS_QSIZE) + 1; + + DPRINTF("%04x:%02x:%02x.%x " + "PCI MSI-X CAP @0x%x, BAR %d, offset 0x%x, entries %d\n", + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function, pos, vdev->msix->table_bar, + vdev->msix->table_offset, vdev->msix->entries); + + return 0; +} + +static int vfio_setup_msix(VFIODevice *vdev, int pos) +{ + int ret; + + /* + * TODO: don't peek into msi_supported, let msix_init fail and + * check for ENOTSUP + */ + if (!msi_supported) { + return 0; + } + + ret = msix_init(&vdev->pdev, vdev->msix->entries, + &vdev->bars[vdev->msix->table_bar].mem, + vdev->msix->table_bar, vdev->msix->table_offset, + &vdev->bars[vdev->msix->pba_bar].mem, + vdev->msix->pba_bar, vdev->msix->pba_offset, pos); + if (ret < 0) { + error_report("vfio: msix_init failed\n"); + return ret; + } + + ret = msix_set_vector_notifiers(&vdev->pdev, vfio_msix_vector_use, + vfio_msix_vector_release); + if (ret) { + error_report("vfio: msix_set_vector_notifiers failed %d\n", ret); + msix_uninit(&vdev->pdev, &vdev->bars[vdev->msix->table_bar].mem, + &vdev->bars[vdev->msix->pba_bar].mem); + return ret; + } + + return 0; +} + +static void vfio_teardown_msi(VFIODevice *vdev) +{ + msi_uninit(&vdev->pdev); + + if (vdev->msix) { + /* FIXME: Why can't unset just silently do nothing?? */ + if (vdev->pdev.msix_vector_use_notifier && + vdev->pdev.msix_vector_release_notifier) { + msix_unset_vector_notifiers(&vdev->pdev); + } + + msix_uninit(&vdev->pdev, &vdev->bars[vdev->msix->table_bar].mem, + &vdev->bars[vdev->msix->pba_bar].mem); + } +} + +/* + * Resource setup + */ +static void vfio_mmap_set_enabled(VFIODevice *vdev, bool enabled) +{ + int i; + + for (i = 0; i < PCI_ROM_SLOT; i++) { + VFIOBAR *bar = &vdev->bars[i]; + + if (!bar->size) { + continue; + } + + memory_region_set_enabled(&bar->mmap_mem, enabled); + if (vdev->msix && vdev->msix->table_bar == i) { + memory_region_set_enabled(&vdev->msix->mmap_mem, enabled); + } + } +} + +static void vfio_unmap_bar(VFIODevice *vdev, int nr) +{ + VFIOBAR *bar = &vdev->bars[nr]; + + if (!bar->size) { + return; + } + + memory_region_del_subregion(&bar->mem, &bar->mmap_mem); + munmap(bar->mmap, memory_region_size(&bar->mmap_mem)); + + if (vdev->msix && vdev->msix->table_bar == nr) { + memory_region_del_subregion(&bar->mem, &vdev->msix->mmap_mem); + munmap(vdev->msix->mmap, memory_region_size(&vdev->msix->mmap_mem)); + } + + memory_region_destroy(&bar->mem); +} + +static int vfio_mmap_bar(VFIOBAR *bar, MemoryRegion *mem, MemoryRegion *submem, + void **map, size_t size, off_t offset, + const char *name) +{ + int ret = 0; + + if (size && bar->flags & VFIO_REGION_INFO_FLAG_MMAP) { + int prot = 0; + + if (bar->flags & VFIO_REGION_INFO_FLAG_READ) { + prot |= PROT_READ; + } + + if (bar->flags & VFIO_REGION_INFO_FLAG_WRITE) { + prot |= PROT_WRITE; + } + + *map = mmap(NULL, size, prot, MAP_SHARED, + bar->fd, bar->fd_offset + offset); + if (*map == MAP_FAILED) { + *map = NULL; + ret = -errno; + goto empty_region; + } + + memory_region_init_ram_ptr(submem, name, size, *map); + } else { +empty_region: + /* Create a zero sized sub-region to make cleanup easy. */ + memory_region_init(submem, name, 0); + } + + memory_region_add_subregion(mem, offset, submem); + + return ret; +} + +static void vfio_map_bar(VFIODevice *vdev, int nr) +{ + VFIOBAR *bar = &vdev->bars[nr]; + unsigned size = bar->size; + char name[64]; + uint32_t pci_bar; + uint8_t type; + int ret; + + /* Skip both unimplemented BARs and the upper half of 64bit BARS. */ + if (!size) { + return; + } + + snprintf(name, sizeof(name), "VFIO %04x:%02x:%02x.%x BAR %d", + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function, nr); + + /* Determine what type of BAR this is for registration */ + ret = pread(vdev->fd, &pci_bar, sizeof(pci_bar), + vdev->config_offset + PCI_BASE_ADDRESS_0 + (4 * nr)); + if (ret != sizeof(pci_bar)) { + error_report("vfio: Failed to read BAR %d (%m)\n", nr); + return; + } + + pci_bar = le32_to_cpu(pci_bar); + type = pci_bar & (pci_bar & PCI_BASE_ADDRESS_SPACE_IO ? + ~PCI_BASE_ADDRESS_IO_MASK : ~PCI_BASE_ADDRESS_MEM_MASK); + + /* A "slow" read/write mapping underlies all BARs */ + memory_region_init_io(&bar->mem, &vfio_bar_ops, bar, name, size); + pci_register_bar(&vdev->pdev, nr, type, &bar->mem); + + /* + * We can't mmap areas overlapping the MSIX vector table, so we + * potentially insert a direct-mapped subregion before and after it. + */ + if (vdev->msix && vdev->msix->table_bar == nr) { + size = vdev->msix->table_offset & TARGET_PAGE_MASK; + } + + strncat(name, " mmap", sizeof(name) - strlen(name) - 1); + if (vfio_mmap_bar(bar, &bar->mem, + &bar->mmap_mem, &bar->mmap, size, 0, name)) { + error_report("%s unsupported. Performance may be slow\n", name); + } + + if (vdev->msix && vdev->msix->table_bar == nr) { + unsigned start; + + start = TARGET_PAGE_ALIGN(vdev->msix->table_offset + + (vdev->msix->entries * PCI_MSIX_ENTRY_SIZE)); + + size = start < bar->size ? bar->size - start : 0; + strncat(name, " msix-hi", sizeof(name) - strlen(name) - 1); + /* VFIOMSIXInfo contains another MemoryRegion for this mapping */ + if (vfio_mmap_bar(bar, &bar->mem, &vdev->msix->mmap_mem, + &vdev->msix->mmap, size, start, name)) { + error_report("%s unsupported. Performance may be slow\n", name); + } + } +} + +static void vfio_map_bars(VFIODevice *vdev) +{ + int i; + + for (i = 0; i < PCI_ROM_SLOT; i++) { + vfio_map_bar(vdev, i); + } +} + +static void vfio_unmap_bars(VFIODevice *vdev) +{ + int i; + + for (i = 0; i < PCI_ROM_SLOT; i++) { + vfio_unmap_bar(vdev, i); + } +} + +/* + * General setup + */ +static uint8_t vfio_std_cap_max_size(PCIDevice *pdev, uint8_t pos) +{ + uint8_t tmp, next = 0xff; + + for (tmp = pdev->config[PCI_CAPABILITY_LIST]; tmp; + tmp = pdev->config[tmp + 1]) { + if (tmp > pos && tmp < next) { + next = tmp; + } + } + + return next - pos; +} + +static int vfio_add_std_cap(VFIODevice *vdev, uint8_t pos) +{ + PCIDevice *pdev = &vdev->pdev; + uint8_t cap_id, next, size; + int ret; + + cap_id = pdev->config[pos]; + next = pdev->config[pos + 1]; + + /* + * If it becomes important to configure capabilities to their actual + * size, use this as the default when it's something we don't recognize. + * Since QEMU doesn't actually handle many of the config accesses, + * exact size doesn't seem worthwhile. + */ + size = vfio_std_cap_max_size(pdev, pos); + + /* + * pci_add_capability always inserts the new capability at the head + * of the chain. Therefore to end up with a chain that matches the + * physical device, we insert from the end by making this recursive. + * This is also why we pre-caclulate size above as cached config space + * will be changed as we unwind the stack. + */ + if (next) { + ret = vfio_add_std_cap(vdev, next); + if (ret) { + return ret; + } + } else { + pdev->config[PCI_CAPABILITY_LIST] = 0; /* Begin the rebuild */ + } + + switch (cap_id) { + case PCI_CAP_ID_MSI: + ret = vfio_setup_msi(vdev, pos); + break; + case PCI_CAP_ID_MSIX: + ret = vfio_setup_msix(vdev, pos); + break; + default: + ret = pci_add_capability(pdev, cap_id, pos, size); + break; + } + + if (ret < 0) { + error_report("vfio: %04x:%02x:%02x.%x Error adding PCI capability " + "0x%x[0x%x]@0x%x: %d\n", vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function, + cap_id, size, pos, ret); + return ret; + } + + return 0; +} + +static int vfio_add_capabilities(VFIODevice *vdev) +{ + PCIDevice *pdev = &vdev->pdev; + + if (!(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST) || + !pdev->config[PCI_CAPABILITY_LIST]) { + return 0; /* Nothing to add */ + } + + return vfio_add_std_cap(vdev, pdev->config[PCI_CAPABILITY_LIST]); +} + +static int vfio_load_rom(VFIODevice *vdev) +{ + uint64_t size = vdev->rom_size; + char name[32]; + off_t off = 0, voff = vdev->rom_offset; + ssize_t bytes; + void *ptr; + + /* If loading ROM from file, pci handles it */ + if (vdev->pdev.romfile || !vdev->pdev.rom_bar || !size) { + return 0; + } + + DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function); + + snprintf(name, sizeof(name), "vfio[%04x:%02x:%02x.%x].rom", + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function); + memory_region_init_ram(&vdev->pdev.rom, name, size); + ptr = memory_region_get_ram_ptr(&vdev->pdev.rom); + memset(ptr, 0xff, size); + + while (size) { + bytes = pread(vdev->fd, ptr + off, size, voff + off); + if (bytes == 0) { + break; /* expect that we could get back less than the ROM BAR */ + } else if (bytes > 0) { + off += bytes; + size -= bytes; + } else { + if (errno == EINTR || errno == EAGAIN) { + continue; + } + error_report("vfio: Error reading device ROM: %m\n"); + memory_region_destroy(&vdev->pdev.rom); + return -errno; + } + } + + pci_register_bar(&vdev->pdev, PCI_ROM_SLOT, 0, &vdev->pdev.rom); + vdev->pdev.has_rom = true; + return 0; +} + +static int vfio_connect_container(VFIOGroup *group) +{ + VFIOContainer *container; + int ret, fd; + + if (group->container) { + return 0; + } + + QLIST_FOREACH(container, &container_list, next) { + if (!ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &container->fd)) { + group->container = container; + QLIST_INSERT_HEAD(&container->group_list, group, container_next); + return 0; + } + } + + fd = qemu_open("/dev/vfio/vfio", O_RDWR); + if (fd < 0) { + error_report("vfio: failed to open /dev/vfio/vfio: %m\n"); + return -errno; + } + + ret = ioctl(fd, VFIO_GET_API_VERSION); + if (ret != VFIO_API_VERSION) { + error_report("vfio: supported vfio version: %d, " + "reported version: %d\n", VFIO_API_VERSION, ret); + close(fd); + return -EINVAL; + } + + container = g_malloc0(sizeof(*container)); + container->fd = fd; + + if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU)) { + ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd); + if (ret) { + error_report("vfio: failed to set group container: %m\n"); + g_free(container); + close(fd); + return -errno; + } + + ret = ioctl(fd, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU); + if (ret) { + error_report("vfio: failed to set iommu for container: %m\n"); + g_free(container); + close(fd); + return -errno; + } + + container->iommu_data.listener = vfio_memory_listener; + container->iommu_data.release = vfio_listener_release; + + memory_listener_register(&container->iommu_data.listener, + get_system_memory()); + } else { + error_report("vfio: No available IOMMU models\n"); + g_free(container); + close(fd); + return -EINVAL; + } + + QLIST_INIT(&container->group_list); + QLIST_INSERT_HEAD(&container_list, container, next); + + group->container = container; + QLIST_INSERT_HEAD(&container->group_list, group, container_next); + + return 0; +} + +static void vfio_disconnect_container(VFIOGroup *group) +{ + VFIOContainer *container = group->container; + + if (ioctl(group->fd, VFIO_GROUP_UNSET_CONTAINER, &container->fd)) { + error_report("vfio: error disconnecting group %d from container\n", + group->groupid); + } + + QLIST_REMOVE(group, container_next); + group->container = NULL; + + if (QLIST_EMPTY(&container->group_list)) { + if (container->iommu_data.release) { + container->iommu_data.release(container); + } + QLIST_REMOVE(container, next); + DPRINTF("vfio_disconnect_container: close container->fd\n"); + close(container->fd); + g_free(container); + } +} + +static VFIOGroup *vfio_get_group(int groupid) +{ + VFIOGroup *group; + char path[32]; + struct vfio_group_status status = { .argsz = sizeof(status) }; + + QLIST_FOREACH(group, &group_list, next) { + if (group->groupid == groupid) { + return group; + } + } + + group = g_malloc0(sizeof(*group)); + + snprintf(path, sizeof(path), "/dev/vfio/%d", groupid); + group->fd = qemu_open(path, O_RDWR); + if (group->fd < 0) { + error_report("vfio: error opening %s: %m\n", path); + g_free(group); + return NULL; + } + + if (ioctl(group->fd, VFIO_GROUP_GET_STATUS, &status)) { + error_report("vfio: error getting group status: %m\n"); + close(group->fd); + g_free(group); + return NULL; + } + + if (!(status.flags & VFIO_GROUP_FLAGS_VIABLE)) { + error_report("vfio: error, group %d is not viable, please ensure " + "all devices within the iommu_group are bound to their " + "vfio bus driver.\n", groupid); + close(group->fd); + g_free(group); + return NULL; + } + + group->groupid = groupid; + QLIST_INIT(&group->device_list); + + if (vfio_connect_container(group)) { + error_report("vfio: failed to setup container for group %d\n", groupid); + close(group->fd); + g_free(group); + return NULL; + } + + QLIST_INSERT_HEAD(&group_list, group, next); + + return group; +} + +static void vfio_put_group(VFIOGroup *group) +{ + if (!QLIST_EMPTY(&group->device_list)) { + return; + } + + vfio_disconnect_container(group); + QLIST_REMOVE(group, next); + DPRINTF("vfio_put_group: close group->fd\n"); + close(group->fd); + g_free(group); +} + +static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev) +{ + struct vfio_device_info dev_info = { .argsz = sizeof(dev_info) }; + struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) }; + int ret, i; + + ret = ioctl(group->fd, VFIO_GROUP_GET_DEVICE_FD, name); + if (ret < 0) { + error_report("vfio: error getting device %s from group %d: %m\n", + name, group->groupid); + error_report("Verify all devices in group %d are bound to vfio-pci " + "or pci-stub and not already in use\n", group->groupid); + return ret; + } + + vdev->fd = ret; + vdev->group = group; + QLIST_INSERT_HEAD(&group->device_list, vdev, next); + + /* Sanity check device */ + ret = ioctl(vdev->fd, VFIO_DEVICE_GET_INFO, &dev_info); + if (ret) { + error_report("vfio: error getting device info: %m\n"); + goto error; + } + + DPRINTF("Device %s flags: %u, regions: %u, irgs: %u\n", name, + dev_info.flags, dev_info.num_regions, dev_info.num_irqs); + + if (!(dev_info.flags & VFIO_DEVICE_FLAGS_PCI)) { + error_report("vfio: Um, this isn't a PCI device\n"); + goto error; + } + + vdev->reset_works = !!(dev_info.flags & VFIO_DEVICE_FLAGS_RESET); + if (!vdev->reset_works) { + error_report("Warning, device %s does not support reset\n", name); + } + + if (dev_info.num_regions != VFIO_PCI_NUM_REGIONS) { + error_report("vfio: unexpected number of io regions %u\n", + dev_info.num_regions); + goto error; + } + + if (dev_info.num_irqs != VFIO_PCI_NUM_IRQS) { + error_report("vfio: unexpected number of irqs %u\n", dev_info.num_irqs); + goto error; + } + + for (i = VFIO_PCI_BAR0_REGION_INDEX; i < VFIO_PCI_ROM_REGION_INDEX; i++) { + reg_info.index = i; + + ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, ®_info); + if (ret) { + error_report("vfio: Error getting region %d info: %m\n", i); + goto error; + } + + DPRINTF("Device %s region %d:\n", name, i); + DPRINTF(" size: 0x%lx, offset: 0x%lx, flags: 0x%lx\n", + (unsigned long)reg_info.size, (unsigned long)reg_info.offset, + (unsigned long)reg_info.flags); + + vdev->bars[i].flags = reg_info.flags; + vdev->bars[i].size = reg_info.size; + vdev->bars[i].fd_offset = reg_info.offset; + vdev->bars[i].fd = vdev->fd; + vdev->bars[i].nr = i; + } + + reg_info.index = VFIO_PCI_ROM_REGION_INDEX; + + ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, ®_info); + if (ret) { + error_report("vfio: Error getting ROM info: %m\n"); + goto error; + } + + DPRINTF("Device %s ROM:\n", name); + DPRINTF(" size: 0x%lx, offset: 0x%lx, flags: 0x%lx\n", + (unsigned long)reg_info.size, (unsigned long)reg_info.offset, + (unsigned long)reg_info.flags); + + vdev->rom_size = reg_info.size; + vdev->rom_offset = reg_info.offset; + + reg_info.index = VFIO_PCI_CONFIG_REGION_INDEX; + + ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, ®_info); + if (ret) { + error_report("vfio: Error getting config info: %m\n"); + goto error; + } + + DPRINTF("Device %s config:\n", name); + DPRINTF(" size: 0x%lx, offset: 0x%lx, flags: 0x%lx\n", + (unsigned long)reg_info.size, (unsigned long)reg_info.offset, + (unsigned long)reg_info.flags); + + vdev->config_size = reg_info.size; + vdev->config_offset = reg_info.offset; + +error: + if (ret) { + QLIST_REMOVE(vdev, next); + vdev->group = NULL; + close(vdev->fd); + } + return ret; +} + +static void vfio_put_device(VFIODevice *vdev) +{ + QLIST_REMOVE(vdev, next); + vdev->group = NULL; + DPRINTF("vfio_put_device: close vdev->fd\n"); + close(vdev->fd); + if (vdev->msix) { + g_free(vdev->msix); + vdev->msix = NULL; + } +} + +static int vfio_initfn(PCIDevice *pdev) +{ + VFIODevice *pvdev, *vdev = DO_UPCAST(VFIODevice, pdev, pdev); + VFIOGroup *group; + char path[PATH_MAX], iommu_group_path[PATH_MAX], *group_name; + ssize_t len; + struct stat st; + int groupid; + int ret; + + /* Check that the host device exists */ + snprintf(path, sizeof(path), + "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/", + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function); + if (stat(path, &st) < 0) { + error_report("vfio: error: no such host device: %s\n", path); + return -errno; + } + + strncat(path, "iommu_group", sizeof(path) - strlen(path) - 1); + + len = readlink(path, iommu_group_path, PATH_MAX); + if (len <= 0) { + error_report("vfio: error no iommu_group for device\n"); + return -errno; + } + + iommu_group_path[len] = 0; + group_name = basename(iommu_group_path); + + if (sscanf(group_name, "%d", &groupid) != 1) { + error_report("vfio: error reading %s: %m\n", path); + return -errno; + } + + DPRINTF("%s(%04x:%02x:%02x.%x) group %d\n", __func__, vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function, groupid); + + group = vfio_get_group(groupid); + if (!group) { + error_report("vfio: failed to get group %d\n", groupid); + return -ENOENT; + } + + snprintf(path, sizeof(path), "%04x:%02x:%02x.%01x", + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function); + + QLIST_FOREACH(pvdev, &group->device_list, next) { + if (pvdev->host.domain == vdev->host.domain && + pvdev->host.bus == vdev->host.bus && + pvdev->host.slot == vdev->host.slot && + pvdev->host.function == vdev->host.function) { + + error_report("vfio: error: device %s is already attached\n", path); + vfio_put_group(group); + return -EBUSY; + } + } + + ret = vfio_get_device(group, path, vdev); + if (ret) { + error_report("vfio: failed to get device %s\n", path); + vfio_put_group(group); + return ret; + } + + /* Get a copy of config space */ + ret = pread(vdev->fd, vdev->pdev.config, + MIN(pci_config_size(&vdev->pdev), vdev->config_size), + vdev->config_offset); + if (ret < (int)MIN(pci_config_size(&vdev->pdev), vdev->config_size)) { + ret = ret < 0 ? -errno : -EFAULT; + error_report("vfio: Failed to read device config space\n"); + goto out_put; + } + + /* + * 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 + * confusing, unwritable, residual addresses from the host here. + */ + memset(&vdev->pdev.config[PCI_BASE_ADDRESS_0], 0, 24); + memset(&vdev->pdev.config[PCI_ROM_ADDRESS], 0, 4); + + vfio_load_rom(vdev); + + ret = vfio_early_setup_msix(vdev); + if (ret) { + goto out_put; + } + + vfio_map_bars(vdev); + + ret = vfio_add_capabilities(vdev); + if (ret) { + goto out_teardown; + } + + if (vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1)) { + if (vdev->intx.intx && strcmp(vdev->intx.intx, "off")) { + error_report("vfio: Unknown option x-intx=%s, " + "valid options: \"off\".\n", vdev->intx.intx); + ret = -EINVAL; + goto out_teardown; + } + + if (vdev->intx.intx && !strcmp(vdev->intx.intx, "off")) { + vdev->intx.disabled = true; + } + + ret = vfio_enable_intx(vdev); + if (ret) { + goto out_teardown; + } + } + + return 0; + +out_teardown: + pci_device_set_intx_routing_notifier(&vdev->pdev, NULL); + vfio_teardown_msi(vdev); + vfio_unmap_bars(vdev); +out_put: + vfio_put_device(vdev); + vfio_put_group(group); + return ret; +} + +static void vfio_exitfn(PCIDevice *pdev) +{ + VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev); + VFIOGroup *group = vdev->group; + + pci_device_set_intx_routing_notifier(&vdev->pdev, NULL); + vfio_disable_interrupts(vdev); + vfio_teardown_msi(vdev); + vfio_unmap_bars(vdev); + vfio_put_device(vdev); + vfio_put_group(group); +} + +static void vfio_pci_reset(DeviceState *dev) +{ + PCIDevice *pdev = DO_UPCAST(PCIDevice, qdev, dev); + VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev); + + if (!vdev->reset_works) { + return; + } + + if (ioctl(vdev->fd, VFIO_DEVICE_RESET)) { + error_report("vfio: Error unable to reset physical device " + "(%04x:%02x:%02x.%x): %m\n", vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function); + } +} + +static Property vfio_pci_dev_properties[] = { + DEFINE_PROP_PCI_HOST_DEVADDR("host", VFIODevice, host), + DEFINE_PROP_STRING("x-intx", VFIODevice, intx.intx), + /* + * TODO - support passed fds... is this necessary? + * DEFINE_PROP_STRING("vfiofd", VFIODevice, vfiofd_name), + * DEFINE_PROP_STRING("vfiogroupfd, VFIODevice, vfiogroupfd_name), + */ + DEFINE_PROP_END_OF_LIST(), +}; + + +static void vfio_pci_dev_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *pdc = PCI_DEVICE_CLASS(klass); + + dc->reset = vfio_pci_reset; + dc->props = vfio_pci_dev_properties; + pdc->init = vfio_initfn; + pdc->exit = vfio_exitfn; + pdc->config_read = vfio_pci_read_config; + pdc->config_write = vfio_pci_write_config; +} + +static const TypeInfo vfio_pci_dev_info = { + .name = "vfio-pci", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(VFIODevice), + .class_init = vfio_pci_dev_class_init, +}; + +static void register_vfio_pci_dev_type(void) +{ + type_register_static(&vfio_pci_dev_info); +} + +type_init(register_vfio_pci_dev_type) diff --git a/hw/vfio_pci_int.h b/hw/vfio_pci_int.h new file mode 100644 index 0000000000..3812d8d7f1 --- /dev/null +++ b/hw/vfio_pci_int.h @@ -0,0 +1,114 @@ +/* + * vfio based device assignment support + * + * Copyright Red Hat, Inc. 2012 + * + * Authors: + * Alex Williamson + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#ifndef HW_VFIO_PCI_INT_H +#define HW_VFIO_PCI_INT_H + +#include "qemu-common.h" +#include "qemu-queue.h" +#include "pci.h" +#include "event_notifier.h" + +typedef struct VFIOBAR { + off_t fd_offset; /* offset of BAR within device fd */ + int fd; /* device fd, allows us to pass VFIOBAR as opaque data */ + MemoryRegion mem; /* slow, read/write access */ + MemoryRegion mmap_mem; /* direct mapped access */ + void *mmap; + size_t size; + uint32_t flags; /* VFIO region flags (rd/wr/mmap) */ + uint8_t nr; /* cache the BAR number for debug */ +} VFIOBAR; + +typedef struct VFIOINTx { + bool pending; /* interrupt pending */ + bool kvm_accel; /* set when QEMU bypass through KVM enabled */ + uint8_t pin; /* which pin to pull for qemu_set_irq */ + EventNotifier interrupt; /* eventfd triggered on interrupt */ + EventNotifier unmask; /* eventfd for unmask on QEMU bypass */ + PCIINTxRoute route; /* routing info for QEMU bypass */ + bool disabled; + char *intx; +} VFIOINTx; + +struct VFIODevice; + +typedef struct VFIOMSIVector { + EventNotifier interrupt; /* eventfd triggered on interrupt */ + struct VFIODevice *vdev; /* back pointer to device */ + int virq; /* KVM irqchip route for QEMU bypass */ + bool use; +} VFIOMSIVector; + +enum { + VFIO_INT_NONE = 0, + VFIO_INT_INTx = 1, + VFIO_INT_MSI = 2, + VFIO_INT_MSIX = 3, +}; + +struct VFIOGroup; + +typedef struct VFIOContainer { + int fd; /* /dev/vfio/vfio, empowered by the attached groups */ + struct { + /* enable abstraction to support various iommu backends */ + union { + MemoryListener listener; /* Used by type1 iommu */ + }; + void (*release)(struct VFIOContainer *); + } iommu_data; + QLIST_HEAD(, VFIOGroup) group_list; + QLIST_ENTRY(VFIOContainer) next; +} VFIOContainer; + +/* Cache of MSI-X setup plus extra mmap and memory region for split BAR map */ +typedef struct VFIOMSIXInfo { + uint8_t table_bar; + uint8_t pba_bar; + uint16_t entries; + uint32_t table_offset; + uint32_t pba_offset; + MemoryRegion mmap_mem; + void *mmap; +} VFIOMSIXInfo; + +typedef struct VFIODevice { + PCIDevice pdev; + int fd; + VFIOINTx intx; + unsigned int config_size; + off_t config_offset; /* Offset of config space region within device fd */ + unsigned int rom_size; + off_t rom_offset; /* Offset of ROM region within device fd */ + int msi_cap_size; + VFIOMSIVector *msi_vectors; + VFIOMSIXInfo *msix; + int nr_vectors; /* Number of MSI/MSIX vectors currently in use */ + int interrupt; /* Current interrupt type */ + VFIOBAR bars[PCI_NUM_REGIONS - 1]; /* No ROM */ + PCIHostDeviceAddress host; + QLIST_ENTRY(VFIODevice) next; + struct VFIOGroup *group; + bool reset_works; +} VFIODevice; + +typedef struct VFIOGroup { + int fd; + int groupid; + VFIOContainer *container; + QLIST_HEAD(, VFIODevice) device_list; + QLIST_ENTRY(VFIOGroup) next; + QLIST_ENTRY(VFIOGroup) container_next; +} VFIOGroup; + +#endif /* HW_VFIO_PCI_INT_H */ From 92e1fb5ed1a26d09ee754845d5691d473410c1dc Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 26 Sep 2012 11:19:39 -0600 Subject: [PATCH 0671/2270] vfio: Enable vfio-pci and mark supported Enabled for all softmmu guests supporting PCI on Linux hosts. Note that currently only x86 hosts have the kernel side VFIO IOMMU support for this. PPC (g3beige) is the only non-x86 guest known to work. ARM (veratile) hangs in firmware, others untested. Signed-off-by: Alex Williamson Signed-off-by: Anthony Liguori --- MAINTAINERS | 5 +++++ hw/Makefile.objs | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 25733fc864..29aac4fce6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -474,6 +474,11 @@ M: Gerd Hoffmann S: Maintained F: hw/usb* +VFIO +M: Alex Williamson +S: Supported +F: hw/vfio* + vhost M: Michael S. Tsirkin S: Supported diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 6dfebd2978..ecdbe44ddd 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -198,7 +198,8 @@ obj-$(CONFIG_VGA) += vga.o obj-$(CONFIG_SOFTMMU) += device-hotplug.o obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o -# Inter-VM PCI shared memory +# Inter-VM PCI shared memory & VFIO PCI device assignment ifeq ($(CONFIG_PCI), y) obj-$(CONFIG_KVM) += ivshmem.o +obj-$(CONFIG_LINUX) += vfio_pci.o endif From 0f41dc182c7e4e2ae160641552101a2a199f7c4c Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Mon, 1 Oct 2012 13:40:15 -0500 Subject: [PATCH 0672/2270] vfio_pci: fix build on 32-bit systems We cannot cast directly from pointer to uint64. Cc: Alex Williamson Cc: Alex Barcelo Reported-by: Alex Barcelo Signed-off-by: Anthony Liguori --- hw/vfio_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index a24558aaa0..a1eeced8fd 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -768,7 +768,7 @@ static int vfio_dma_map(VFIOContainer *container, target_phys_addr_t iova, struct vfio_iommu_type1_dma_map map = { .argsz = sizeof(map), .flags = VFIO_DMA_MAP_FLAG_READ, - .vaddr = (__u64)vaddr, + .vaddr = (__u64)(intptr_t)vaddr, .iova = iova, .size = size, }; From 4be8eeacb9f2b01ad98747ad88e54a7feabc664c Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 24 Sep 2012 17:28:35 +0100 Subject: [PATCH 0673/2270] fpu/softfloat.c: Remove pointless shift of always-zero value In float16_to_float32, when returning an infinity, just pass zero as the mantissa argument to packFloat32(), rather than shifting a value which we know must be zero. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- fpu/softfloat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index b29256a8eb..01a28cab1a 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -3007,7 +3007,7 @@ float32 float16_to_float32(float16 a, flag ieee STATUS_PARAM) if (aSig) { return commonNaNToFloat32(float16ToCommonNaN(a STATUS_VAR) STATUS_VAR); } - return packFloat32(aSign, 0xff, aSig << 13); + return packFloat32(aSign, 0xff, 0); } if (aExp == 0) { int8 shiftCount; From e744c06fca438dc08271e626034e632a270c91c8 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 28 Sep 2012 16:17:03 +0100 Subject: [PATCH 0674/2270] fpu/softfloat.c: Return correctly signed values from uint64_to_float32 The uint64_to_float32() conversion function was incorrectly always returning numbers with the sign bit set (ie negative numbers). Correct this so we return positive numbers instead. Signed-off-by: Peter Maydell Signed-off-by: Aurelien Jarno --- fpu/softfloat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 01a28cab1a..841314686b 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1238,7 +1238,7 @@ float32 uint64_to_float32( uint64 a STATUS_PARAM ) if ( a == 0 ) return float32_zero; shiftCount = countLeadingZeros64( a ) - 40; if ( 0 <= shiftCount ) { - return packFloat32( 1 > 0, 0x95 - shiftCount, a< 0, 0x9C - shiftCount, a STATUS_VAR ); + return roundAndPackFloat32(0, 0x9C - shiftCount, a STATUS_VAR); } } From bd4982a6c6f1b133aff38873bc3b580af15cd334 Mon Sep 17 00:00:00 2001 From: Anthony PERARD Date: Wed, 3 Oct 2012 13:45:24 +0000 Subject: [PATCH 0675/2270] xen: Fix, no unplug of pt device by platform device. The Xen platform device will unplug any NICs if requested by the guest (PVonHVM) including a NIC that would have been passthrough. This patch makes sure that a passthrough device will not be unplug. Reported-by: "Zhang, Yang Z" Signed-off-by: Anthony PERARD Signed-off-by: Stefano Stabellini --- hw/xen_platform.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hw/xen_platform.c b/hw/xen_platform.c index 0d6c2ff8c3..956dbfeae4 100644 --- a/hw/xen_platform.c +++ b/hw/xen_platform.c @@ -85,8 +85,10 @@ static void log_writeb(PCIXenPlatformState *s, char val) static void unplug_nic(PCIBus *b, PCIDevice *d, void *o) { + /* We have to ignore passthrough devices */ if (pci_get_word(d->config + PCI_CLASS_DEVICE) == - PCI_CLASS_NETWORK_ETHERNET) { + PCI_CLASS_NETWORK_ETHERNET + && strcmp(d->name, "xen-pci-passthrough") != 0) { qdev_free(&d->qdev); } } @@ -98,8 +100,10 @@ static void pci_unplug_nics(PCIBus *bus) static void unplug_disks(PCIBus *b, PCIDevice *d, void *o) { + /* We have to ignore passthrough devices */ if (pci_get_word(d->config + PCI_CLASS_DEVICE) == - PCI_CLASS_STORAGE_IDE) { + PCI_CLASS_STORAGE_IDE + && strcmp(d->name, "xen-pci-passthrough") != 0) { qdev_unplug(&(d->qdev), NULL); } } From aabc8530c7ba2be89e21463f051056ad7c255e6e Mon Sep 17 00:00:00 2001 From: Xudong Hao Date: Wed, 3 Oct 2012 13:46:23 +0000 Subject: [PATCH 0676/2270] qemu/xen: Add 64 bits big bar support on qemu Currently it is assumed PCI device BAR access < 4G memory. If there is such a device whose BAR size is larger than 4G, it must access > 4G memory address. This patch enable the 64bits big BAR support on qemu. Signed-off-by: Xudong Hao Signed-off-by: Xiantao Zhang Signed-off-by: Stefano Stabellini --- hw/xen_pt.c | 7 +++++-- hw/xen_pt_config_init.c | 39 ++++++++++++++++++++++++++------------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/hw/xen_pt.c b/hw/xen_pt.c index 307119a12f..838bcea4d6 100644 --- a/hw/xen_pt.c +++ b/hw/xen_pt.c @@ -410,14 +410,17 @@ static int xen_pt_register_regions(XenPCIPassthroughState *s) if (r->type & XEN_HOST_PCI_REGION_TYPE_PREFETCH) { type |= PCI_BASE_ADDRESS_MEM_PREFETCH; } + if (r->type & XEN_HOST_PCI_REGION_TYPE_MEM_64) { + type |= PCI_BASE_ADDRESS_MEM_TYPE_64; + } } memory_region_init_io(&s->bar[i], &ops, &s->dev, "xen-pci-pt-bar", r->size); pci_register_bar(&s->dev, i, type, &s->bar[i]); - XEN_PT_LOG(&s->dev, "IO region %i registered (size=0x%08"PRIx64 - " base_addr=0x%08"PRIx64" type: %#x)\n", + XEN_PT_LOG(&s->dev, "IO region %i registered (size=0x%lx"PRIx64 + " base_addr=0x%lx"PRIx64" type: %#x)\n", i, r->size, r->base_addr, type); } diff --git a/hw/xen_pt_config_init.c b/hw/xen_pt_config_init.c index e524a4094d..0a5f82cb80 100644 --- a/hw/xen_pt_config_init.c +++ b/hw/xen_pt_config_init.c @@ -342,6 +342,23 @@ static int xen_pt_cmd_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry, #define XEN_PT_BAR_IO_RO_MASK 0x00000003 /* BAR ReadOnly mask(I/O) */ #define XEN_PT_BAR_IO_EMU_MASK 0xFFFFFFFC /* BAR emul mask(I/O) */ +static bool is_64bit_bar(PCIIORegion *r) +{ + return !!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64); +} + +static uint64_t xen_pt_get_bar_size(PCIIORegion *r) +{ + if (is_64bit_bar(r)) { + uint64_t size64; + size64 = (r + 1)->size; + size64 <<= 32; + size64 += r->size; + return size64; + } + return r->size; +} + static XenPTBarFlag xen_pt_bar_reg_parse(XenPCIPassthroughState *s, XenPTRegInfo *reg) { @@ -366,7 +383,7 @@ static XenPTBarFlag xen_pt_bar_reg_parse(XenPCIPassthroughState *s, /* check unused BAR */ r = &d->io_regions[index]; - if (r->size == 0) { + if (!xen_pt_get_bar_size(r)) { return XEN_PT_BAR_FLAG_UNUSED; } @@ -481,7 +498,12 @@ static int xen_pt_bar_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry, switch (s->bases[index].bar_flag) { case XEN_PT_BAR_FLAG_MEM: bar_emu_mask = XEN_PT_BAR_MEM_EMU_MASK; - bar_ro_mask = XEN_PT_BAR_MEM_RO_MASK | (r_size - 1); + if (!r_size) { + /* low 32 bits mask for 64 bit bars */ + bar_ro_mask = XEN_PT_BAR_ALLF; + } else { + bar_ro_mask = XEN_PT_BAR_MEM_RO_MASK | (r_size - 1); + } break; case XEN_PT_BAR_FLAG_IO: bar_emu_mask = XEN_PT_BAR_IO_EMU_MASK; @@ -489,7 +511,7 @@ static int xen_pt_bar_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry, break; case XEN_PT_BAR_FLAG_UPPER: bar_emu_mask = XEN_PT_BAR_ALLF; - bar_ro_mask = 0; /* all upper 32bit are R/W */ + bar_ro_mask = r_size ? r_size - 1 : 0; break; default: break; @@ -501,22 +523,13 @@ static int xen_pt_bar_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry, /* check whether we need to update the virtual region address or not */ switch (s->bases[index].bar_flag) { + case XEN_PT_BAR_FLAG_UPPER: case XEN_PT_BAR_FLAG_MEM: /* nothing to do */ break; case XEN_PT_BAR_FLAG_IO: /* nothing to do */ break; - case XEN_PT_BAR_FLAG_UPPER: - if (cfg_entry->data) { - if (cfg_entry->data != (XEN_PT_BAR_ALLF & ~bar_ro_mask)) { - XEN_PT_WARN(d, "Guest attempt to set high MMIO Base Address. " - "Ignore mapping. " - "(offset: 0x%02x, high address: 0x%08x)\n", - reg->offset, cfg_entry->data); - } - } - break; default: break; } From 39f42439d0629d3921629dc4b38e68df8f2f7b83 Mon Sep 17 00:00:00 2001 From: Anthony PERARD Date: Wed, 3 Oct 2012 13:48:19 +0000 Subject: [PATCH 0677/2270] QMP, Introduce xen-set-global-dirty-log command. This command is used during a migration of a guest under Xen. It calls memory_global_dirty_log_start or memory_global_dirty_log_stop according to the argument pass to the command. Signed-off-by: Anthony PERARD Reviewed-by: Luiz Capitulino --- qapi-schema.json | 13 +++++++++++++ qmp-commands.hx | 24 ++++++++++++++++++++++++ xen-all.c | 15 +++++++++++++++ xen-stub.c | 5 +++++ 4 files changed, 57 insertions(+) diff --git a/qapi-schema.json b/qapi-schema.json index 14e44199b7..4a4a850f5f 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1955,6 +1955,19 @@ ## { 'command': 'xen-save-devices-state', 'data': {'filename': 'str'} } +## +# @xen-set-global-dirty-log +# +# Enable or disable the global dirty log mode. +# +# @enable: true to enable, false to disable. +# +# Returns: nothing +# +# Since: 1.3 +## +{ 'command': 'xen-set-global-dirty-log', 'data': { 'enable': 'bool' } } + ## # @device_del: # diff --git a/qmp-commands.hx b/qmp-commands.hx index 6e21ddba61..662b7cf32c 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -490,6 +490,30 @@ Example: "arguments": { "filename": "/tmp/save" } } <- { "return": {} } +EQMP + + { + .name = "xen-set-global-dirty-log", + .args_type = "enable:b", + .mhandler.cmd_new = qmp_marshal_input_xen_set_global_dirty_log, + }, + +SQMP +xen-set-global-dirty-log +------- + +Enable or disable the global dirty log mode. + +Arguments: + +- "enable": Enable it or disable it. + +Example: + +-> { "execute": "xen-set-global-dirty-log", + "arguments": { "enable": true } } +<- { "return": {} } + EQMP { diff --git a/xen-all.c b/xen-all.c index f76b051eee..f75ae9fd28 100644 --- a/xen-all.c +++ b/xen-all.c @@ -14,6 +14,7 @@ #include "hw/pc.h" #include "hw/xen_common.h" #include "hw/xen_backend.h" +#include "qmp-commands.h" #include "range.h" #include "xen-mapcache.h" @@ -36,6 +37,7 @@ static MemoryRegion ram_memory, ram_640k, ram_lo, ram_hi; static MemoryRegion *framebuffer; +static bool xen_in_migration; /* Compatibility with older version */ #if __XEN_LATEST_INTERFACE_VERSION__ < 0x0003020a @@ -552,10 +554,14 @@ static void xen_log_sync(MemoryListener *listener, MemoryRegionSection *section) static void xen_log_global_start(MemoryListener *listener) { + if (xen_enabled()) { + xen_in_migration = true; + } } static void xen_log_global_stop(MemoryListener *listener) { + xen_in_migration = false; } static void xen_eventfd_add(MemoryListener *listener, @@ -588,6 +594,15 @@ static MemoryListener xen_memory_listener = { .priority = 10, }; +void qmp_xen_set_global_dirty_log(bool enable, Error **errp) +{ + if (enable) { + memory_global_dirty_log_start(); + } else { + memory_global_dirty_log_stop(); + } +} + /* VCPU Operations, MMIO, IO ring ... */ static void xen_reset_vcpu(void *opaque) diff --git a/xen-stub.c b/xen-stub.c index 8ff2b79ac6..5e66ba8f04 100644 --- a/xen-stub.c +++ b/xen-stub.c @@ -11,6 +11,7 @@ #include "qemu-common.h" #include "hw/xen.h" #include "memory.h" +#include "qmp-commands.h" void xenstore_store_pv_console_info(int i, CharDriverState *chr) { @@ -54,3 +55,7 @@ int xen_init(void) void xen_register_framebuffer(MemoryRegion *mr) { } + +void qmp_xen_set_global_dirty_log(bool enable, Error **errp) +{ +} From 910b38e4dc4c37683c8b821e75a7f4cf095e4b21 Mon Sep 17 00:00:00 2001 From: Anthony PERARD Date: Wed, 3 Oct 2012 13:48:45 +0000 Subject: [PATCH 0678/2270] xen: Introduce xen_modified_memory. This function is to be used during live migration. Every write access to the guest memory should call this funcion so the Xen tools knows which pages are dirty. Signed-off-by: Anthony PERARD Acked-by: Stefano Stabellini --- hw/xen.h | 1 + xen-all.c | 21 +++++++++++++++++++++ xen-stub.c | 4 ++++ 3 files changed, 26 insertions(+) diff --git a/hw/xen.h b/hw/xen.h index e5926b7b8a..d14e92d5aa 100644 --- a/hw/xen.h +++ b/hw/xen.h @@ -48,6 +48,7 @@ void xenstore_store_pv_console_info(int i, struct CharDriverState *chr); struct MemoryRegion; void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, struct MemoryRegion *mr); +void xen_modified_memory(ram_addr_t start, ram_addr_t length); #endif struct MemoryRegion; diff --git a/xen-all.c b/xen-all.c index f75ae9fd28..b11542c3e7 100644 --- a/xen-all.c +++ b/xen-all.c @@ -1228,3 +1228,24 @@ void xen_shutdown_fatal_error(const char *fmt, ...) /* destroy the domain */ qemu_system_shutdown_request(); } + +void xen_modified_memory(ram_addr_t start, ram_addr_t length) +{ + if (unlikely(xen_in_migration)) { + int rc; + ram_addr_t start_pfn, nb_pages; + + if (length == 0) { + length = TARGET_PAGE_SIZE; + } + start_pfn = start >> TARGET_PAGE_BITS; + nb_pages = ((start + length + TARGET_PAGE_SIZE - 1) >> TARGET_PAGE_BITS) + - start_pfn; + rc = xc_hvm_modified_memory(xen_xc, xen_domid, start_pfn, nb_pages); + if (rc) { + fprintf(stderr, + "%s failed for "RAM_ADDR_FMT" ("RAM_ADDR_FMT"): %i, %s\n", + __func__, start, nb_pages, rc, strerror(-rc)); + } + } +} diff --git a/xen-stub.c b/xen-stub.c index 5e66ba8f04..921439263a 100644 --- a/xen-stub.c +++ b/xen-stub.c @@ -59,3 +59,7 @@ void xen_register_framebuffer(MemoryRegion *mr) void qmp_xen_set_global_dirty_log(bool enable, Error **errp) { } + +void xen_modified_memory(ram_addr_t start, ram_addr_t length) +{ +} From 51d7a9eb2b64e787c90bea1027308087eac22065 Mon Sep 17 00:00:00 2001 From: Anthony PERARD Date: Wed, 3 Oct 2012 13:49:05 +0000 Subject: [PATCH 0679/2270] exec: Introduce helper to set dirty flags. This new helper/hook is used in the next patch to add an extra call in a single place. Signed-off-by: Anthony PERARD Reviewed-by: Avi Kivity --- exec.c | 52 +++++++++++++++++----------------------------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/exec.c b/exec.c index bb6aa4a070..366684cd78 100644 --- a/exec.c +++ b/exec.c @@ -3417,6 +3417,18 @@ int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr, } #else + +static void invalidate_and_set_dirty(target_phys_addr_t addr, + target_phys_addr_t length) +{ + if (!cpu_physical_memory_is_dirty(addr)) { + /* invalidate code */ + tb_invalidate_phys_page_range(addr, addr + length, 0); + /* set dirty bit */ + cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG)); + } +} + void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, int len, int is_write) { @@ -3462,13 +3474,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, /* RAM case */ ptr = qemu_get_ram_ptr(addr1); memcpy(ptr, buf, l); - if (!cpu_physical_memory_is_dirty(addr1)) { - /* invalidate code */ - tb_invalidate_phys_page_range(addr1, addr1 + l, 0); - /* set dirty bit */ - cpu_physical_memory_set_dirty_flags( - addr1, (0xff & ~CODE_DIRTY_FLAG)); - } + invalidate_and_set_dirty(addr1, l); qemu_put_ram_ptr(ptr); } } else { @@ -3534,13 +3540,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr, /* ROM/RAM case */ ptr = qemu_get_ram_ptr(addr1); memcpy(ptr, buf, l); - if (!cpu_physical_memory_is_dirty(addr1)) { - /* invalidate code */ - tb_invalidate_phys_page_range(addr1, addr1 + l, 0); - /* set dirty bit */ - cpu_physical_memory_set_dirty_flags( - addr1, (0xff & ~CODE_DIRTY_FLAG)); - } + invalidate_and_set_dirty(addr1, l); qemu_put_ram_ptr(ptr); } len -= l; @@ -3666,13 +3666,7 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, l = TARGET_PAGE_SIZE; if (l > access_len) l = access_len; - if (!cpu_physical_memory_is_dirty(addr1)) { - /* invalidate code */ - tb_invalidate_phys_page_range(addr1, addr1 + l, 0); - /* set dirty bit */ - cpu_physical_memory_set_dirty_flags( - addr1, (0xff & ~CODE_DIRTY_FLAG)); - } + invalidate_and_set_dirty(addr1, l); addr1 += l; access_len -= l; } @@ -3978,13 +3972,7 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val, stl_p(ptr, val); break; } - if (!cpu_physical_memory_is_dirty(addr1)) { - /* invalidate code */ - tb_invalidate_phys_page_range(addr1, addr1 + 4, 0); - /* set dirty bit */ - cpu_physical_memory_set_dirty_flags(addr1, - (0xff & ~CODE_DIRTY_FLAG)); - } + invalidate_and_set_dirty(addr1, 4); } } @@ -4051,13 +4039,7 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val, stw_p(ptr, val); break; } - if (!cpu_physical_memory_is_dirty(addr1)) { - /* invalidate code */ - tb_invalidate_phys_page_range(addr1, addr1 + 2, 0); - /* set dirty bit */ - cpu_physical_memory_set_dirty_flags(addr1, - (0xff & ~CODE_DIRTY_FLAG)); - } + invalidate_and_set_dirty(addr1, 2); } } From e226939de5814527a21396903b08c3d0ed989558 Mon Sep 17 00:00:00 2001 From: Anthony PERARD Date: Wed, 3 Oct 2012 13:49:22 +0000 Subject: [PATCH 0680/2270] exec, memory: Call to xen_modified_memory. This patch add some calls to xen_modified_memory to notify Xen about dirtybits during migration. Signed-off-by: Anthony PERARD Reviewed-by: Avi Kivity --- exec-obsolete.h | 2 ++ exec.c | 1 + 2 files changed, 3 insertions(+) diff --git a/exec-obsolete.h b/exec-obsolete.h index c09925610d..286e2f75e1 100644 --- a/exec-obsolete.h +++ b/exec-obsolete.h @@ -24,6 +24,7 @@ #endif #ifndef CONFIG_USER_ONLY +#include "hw/xen.h" ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, MemoryRegion *mr); @@ -111,6 +112,7 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { cpu_physical_memory_set_dirty_flags(addr, dirty_flags); } + xen_modified_memory(addr, length); } static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start, diff --git a/exec.c b/exec.c index 366684cd78..1114a0932b 100644 --- a/exec.c +++ b/exec.c @@ -3427,6 +3427,7 @@ static void invalidate_and_set_dirty(target_phys_addr_t addr, /* set dirty bit */ cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG)); } + xen_modified_memory(addr, length); } void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, From 8aba7dc02d5660df7e7d8651304b3079908358be Mon Sep 17 00:00:00 2001 From: Anthony PERARD Date: Wed, 3 Oct 2012 13:49:40 +0000 Subject: [PATCH 0681/2270] xen: Set the vram dirty when an error occur. If the call to xc_hvm_track_dirty_vram() fails, then we set dirtybit on all the video ram. This case happens during migration. Signed-off-by: Anthony PERARD Acked-by: Stefano Stabellini --- xen-all.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xen-all.c b/xen-all.c index b11542c3e7..e6308be23a 100644 --- a/xen-all.c +++ b/xen-all.c @@ -507,7 +507,8 @@ static void xen_sync_dirty_bitmap(XenIOState *state, bitmap); if (rc < 0) { if (rc != -ENODATA) { - fprintf(stderr, "xen: track_dirty_vram failed (0x" TARGET_FMT_plx + memory_region_set_dirty(framebuffer, 0, size); + DPRINTF("xen: track_dirty_vram failed (0x" TARGET_FMT_plx ", 0x" TARGET_FMT_plx "): %s\n", start_addr, start_addr + size, strerror(-rc)); } From 8a269ca4167b43cbf1acaf51929f3f5919edcd1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 22 Aug 2012 05:48:44 +0000 Subject: [PATCH 0682/2270] MAINTAINERS: Document sPAPR (pSeries) machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber Acked-by: David Gibson Signed-off-by: Alexander Graf --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 29aac4fce6..af7c7db815 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -374,6 +374,13 @@ S: Odd Fixes F: hw/ppc_prep.c F: hw/prep_pci.[hc] +sPAPR +M: David Gibson +M: Alexander Graf +L: qemu-ppc@nongnu.org +S: Supported +F: hw/spapr* + SH4 Machines ------------ R2D From 98cded3a05de6a3295e89cc149ff267f1619bdc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 22 Aug 2012 05:48:45 +0000 Subject: [PATCH 0683/2270] MAINTAINERS: Document e500 machines and devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber Cc: Alexander Graf Cc: Scott Wood Signed-off-by: Alexander Graf --- MAINTAINERS | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index af7c7db815..cfb73944c0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -352,6 +352,22 @@ L: qemu-ppc@nongnu.org S: Maintained F: hw/ppc405_boards.c +e500 +M: Alexander Graf +M: Scott Wood +L: qemu-ppc@nongnu.org +S: Supported +F: hw/ppc/e500.[hc] +F: hw/ppc/e500plat.c + +mpc8544ds +M: Alexander Graf +M: Scott Wood +L: qemu-ppc@nongnu.org +S: Supported +F: hw/ppc/mpc8544ds.c +F: hw/mpc8544_guts.c + New World M: Alexander Graf L: qemu-ppc@nongnu.org @@ -464,6 +480,13 @@ S: Supported F: hw/pci* F: hw/piix* +ppce500 +M: Alexander Graf +M: Scott Wood +L: qemu-ppc@nongnu.org +S: Supported +F: hw/ppce500_* + SCSI M: Paolo Bonzini S: Supported From 9b9fe13540d2375a109c1d17b53d240a592e442d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 22 Aug 2012 05:48:46 +0000 Subject: [PATCH 0684/2270] MAINTAINERS: Downgrade ppc405 to Odd Fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As requested by Alex. Signed-off-by: Andreas Färber Signed-off-by: Alexander Graf --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index cfb73944c0..9d4ccfce7f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -349,7 +349,7 @@ PowerPC Machines 405 M: Alexander Graf L: qemu-ppc@nongnu.org -S: Maintained +S: Odd Fixes F: hw/ppc405_boards.c e500 From aaade8d7d4d2a3d9b7fb99b198369b1b35a75450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 22 Aug 2012 05:48:47 +0000 Subject: [PATCH 0685/2270] MAINTAINERS: Document Bamboo machine and ppc4xx devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Place it in alphabetical order and add new Devices section ppc4xx to share file rules with 405 and virtex_ml507. Signed-off-by: Andreas Färber Signed-off-by: Alexander Graf --- MAINTAINERS | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 9d4ccfce7f..dca8753ee9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -352,6 +352,12 @@ L: qemu-ppc@nongnu.org S: Odd Fixes F: hw/ppc405_boards.c +Bamboo +M: Alexander Graf +L: qemu-ppc@nongnu.org +S: Odd Fixes +F: hw/ppc440_bamboo.c + e500 M: Alexander Graf M: Scott Wood @@ -480,6 +486,12 @@ S: Supported F: hw/pci* F: hw/piix* +ppc4xx +M: Alexander Graf +L: qemu-ppc@nongnu.org +S: Odd Fixes +F: hw/ppc4xx*.[hc] + ppce500 M: Alexander Graf M: Scott Wood From 794d00bfc7c38cfc559fbec137ecd0117b40e77b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 22 Aug 2012 05:48:48 +0000 Subject: [PATCH 0686/2270] MAINTAINERS: Document virtex_ml507 machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Place it in alphabetical order, there is a separate section for sharing ppc4xx devices now. Signed-off-by: Andreas Färber Acked-by: Edgar E. Iglesias Signed-off-by: Alexander Graf --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index dca8753ee9..78d4ff227e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -403,6 +403,12 @@ L: qemu-ppc@nongnu.org S: Supported F: hw/spapr* +virtex_ml507 +M: Edgar E. Iglesias +L: qemu-ppc@nongnu.org +S: Odd Fixes +F: hw/virtex_ml507.c + SH4 Machines ------------ R2D From ef9bd1507b60edba0619e16f1179b158eac2c3ac Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 11 Sep 2012 08:47:10 +0000 Subject: [PATCH 0687/2270] target-ppc: simplify NaN propagation for vector functions Commit e024e881bb1a8b5085026589360d26ed97acdd64 provided a pickNaN() function for PowerPC, implementing the correct NaN propagation rules. Therefore there is no need to test the operands manually, we can rely on the softfloat code to do that. Signed-off-by: Aurelien Jarno Signed-off-by: Alexander Graf --- target-ppc/int_helper.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c index f638b2a07c..5b2a3c8792 100644 --- a/target-ppc/int_helper.c +++ b/target-ppc/int_helper.c @@ -409,9 +409,7 @@ VARITH(uwm, u32) int i; \ \ for (i = 0; i < ARRAY_SIZE(r->f); i++) { \ - HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) { \ - r->f[i] = func(a->f[i], b->f[i], &env->vec_status); \ - } \ + r->f[i] = func(a->f[i], b->f[i], &env->vec_status); \ } \ } VARITHFP(addfp, float32_add) @@ -1039,9 +1037,7 @@ void helper_vrefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b) int i; for (i = 0; i < ARRAY_SIZE(r->f); i++) { - HANDLE_NAN1(r->f[i], b->f[i]) { - r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status); - } + r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status); } } @@ -1054,9 +1050,7 @@ void helper_vrefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b) \ set_float_rounding_mode(rounding, &s); \ for (i = 0; i < ARRAY_SIZE(r->f); i++) { \ - HANDLE_NAN1(r->f[i], b->f[i]) { \ - r->f[i] = float32_round_to_int (b->f[i], &s); \ - } \ + r->f[i] = float32_round_to_int (b->f[i], &s); \ } \ } VRFI(n, float_round_nearest_even) @@ -1089,11 +1083,9 @@ void helper_vrsqrtefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b) int i; for (i = 0; i < ARRAY_SIZE(r->f); i++) { - HANDLE_NAN1(r->f[i], b->f[i]) { - float32 t = float32_sqrt(b->f[i], &env->vec_status); + float32 t = float32_sqrt(b->f[i], &env->vec_status); - r->f[i] = float32_div(float32_one, t, &env->vec_status); - } + r->f[i] = float32_div(float32_one, t, &env->vec_status); } } @@ -1109,9 +1101,7 @@ void helper_vexptefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b) int i; for (i = 0; i < ARRAY_SIZE(r->f); i++) { - HANDLE_NAN1(r->f[i], b->f[i]) { - r->f[i] = float32_exp2(b->f[i], &env->vec_status); - } + r->f[i] = float32_exp2(b->f[i], &env->vec_status); } } @@ -1120,9 +1110,7 @@ void helper_vlogefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b) int i; for (i = 0; i < ARRAY_SIZE(r->f); i++) { - HANDLE_NAN1(r->f[i], b->f[i]) { - r->f[i] = float32_log2(b->f[i], &env->vec_status); - } + r->f[i] = float32_log2(b->f[i], &env->vec_status); } } From db1babb8dbb6d18433a51f1b4c3d186ea7057a6f Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 11 Sep 2012 08:47:11 +0000 Subject: [PATCH 0688/2270] target-ppc: use the softfloat min/max functions Use the new softfloat float32_min() and float32_max() to implement the vminfp and vmaxfp instructions. As a bonus we can get rid of the call to the HANDLE_NAN2 macro, as the NaN handling is directly done at the softfloat level. Signed-off-by: Aurelien Jarno Signed-off-by: Alexander Graf --- target-ppc/int_helper.c | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c index 5b2a3c8792..61412433d0 100644 --- a/target-ppc/int_helper.c +++ b/target-ppc/int_helper.c @@ -414,6 +414,8 @@ VARITH(uwm, u32) } VARITHFP(addfp, float32_add) VARITHFP(subfp, float32_sub) +VARITHFP(minfp, float32_min) +VARITHFP(maxfp, float32_max) #undef VARITHFP #define VARITHSAT_CASE(type, op, cvt, element) \ @@ -728,27 +730,6 @@ VMINMAX(uw, u32) #undef VMINMAX_DO #undef VMINMAX -#define VMINMAXFP(suffix, rT, rF) \ - void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \ - ppc_avr_t *b) \ - { \ - int i; \ - \ - for (i = 0; i < ARRAY_SIZE(r->f); i++) { \ - HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) { \ - if (float32_lt_quiet(a->f[i], b->f[i], \ - &env->vec_status)) { \ - r->f[i] = rT->f[i]; \ - } else { \ - r->f[i] = rF->f[i]; \ - } \ - } \ - } \ - } -VMINMAXFP(minfp, a, b) -VMINMAXFP(maxfp, b, a) -#undef VMINMAXFP - void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) { int i; From 2f93c23fe71420e5095f2fae1877fe747ad9f876 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 11 Sep 2012 08:47:12 +0000 Subject: [PATCH 0689/2270] target-ppc: use the softfloat float32_muladd function Use the new softfloat float32_muladd() function to implement the vmaddfp and vnmsubfp instructions. As a bonus we can get rid of the call to the HANDLE_NAN3 macro, as the NaN handling is directly done at the softfloat level. Signed-off-by: Aurelien Jarno Signed-off-by: Alexander Graf --- target-ppc/int_helper.c | 57 ++++++++++------------------------------- 1 file changed, 14 insertions(+), 43 deletions(-) diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c index 61412433d0..6f9beffb2a 100644 --- a/target-ppc/int_helper.c +++ b/target-ppc/int_helper.c @@ -418,6 +418,20 @@ VARITHFP(minfp, float32_min) VARITHFP(maxfp, float32_max) #undef VARITHFP +#define VARITHFPFMA(suffix, type) \ + void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \ + ppc_avr_t *b, ppc_avr_t *c) \ + { \ + int i; \ + for (i = 0; i < ARRAY_SIZE(r->f); i++) { \ + r->f[i] = float32_muladd(a->f[i], c->f[i], b->f[i], \ + type, &env->vec_status); \ + } \ + } +VARITHFPFMA(maddfp, 0); +VARITHFPFMA(nmsubfp, float_muladd_negate_result | float_muladd_negate_c); +#undef VARITHFPFMA + #define VARITHSAT_CASE(type, op, cvt, element) \ { \ type result = (type)a->element[i] op (type)b->element[i]; \ @@ -649,27 +663,6 @@ VCT(uxs, cvtsduw, u32) VCT(sxs, cvtsdsw, s32) #undef VCT -void helper_vmaddfp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, - ppc_avr_t *c) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(r->f); i++) { - HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) { - /* Need to do the computation in higher precision and round - * once at the end. */ - float64 af, bf, cf, t; - - af = float32_to_float64(a->f[i], &env->vec_status); - bf = float32_to_float64(b->f[i], &env->vec_status); - cf = float32_to_float64(c->f[i], &env->vec_status); - t = float64_mul(af, cf, &env->vec_status); - t = float64_add(t, bf, &env->vec_status); - r->f[i] = float64_to_float32(t, &env->vec_status); - } - } -} - void helper_vmhaddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) { @@ -909,28 +902,6 @@ VMUL(uh, u16, u32) #undef VMUL_DO #undef VMUL -void helper_vnmsubfp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, - ppc_avr_t *b, ppc_avr_t *c) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(r->f); i++) { - HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) { - /* Need to do the computation is higher precision and round - * once at the end. */ - float64 af, bf, cf, t; - - af = float32_to_float64(a->f[i], &env->vec_status); - bf = float32_to_float64(b->f[i], &env->vec_status); - cf = float32_to_float64(c->f[i], &env->vec_status); - t = float64_mul(af, cf, &env->vec_status); - t = float64_sub(t, bf, &env->vec_status); - t = float64_chs(t); - r->f[i] = float64_to_float32(t, &env->vec_status); - } - } -} - void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) { From 89243b3b0183471a373d1457e7f93811773b64a7 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 11 Sep 2012 08:47:13 +0000 Subject: [PATCH 0690/2270] target-ppc: get rid of the HANDLE_NAN{1, 2, 3} macros We can finally get rid of the ugly HANDLE_NAN{1,2,3} macros. Signed-off-by: Aurelien Jarno Signed-off-by: Alexander Graf --- target-ppc/int_helper.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c index 6f9beffb2a..f39b4f682a 100644 --- a/target-ppc/int_helper.c +++ b/target-ppc/int_helper.c @@ -287,23 +287,6 @@ target_ulong helper_602_mfrom(target_ulong arg) for (index = ARRAY_SIZE(r->element)-1; index >= 0; index--) #endif -/* If X is a NaN, store the corresponding QNaN into RESULT. Otherwise, - * execute the following block. */ -#define DO_HANDLE_NAN(result, x) \ - if (float32_is_any_nan(x)) { \ - CPU_FloatU __f; \ - __f.f = x; \ - __f.l = __f.l | (1 << 22); /* Set QNaN bit. */ \ - result = __f.f; \ - } else - -#define HANDLE_NAN1(result, x) \ - DO_HANDLE_NAN(result, x) -#define HANDLE_NAN2(result, x, y) \ - DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y) -#define HANDLE_NAN3(result, x, y, z) \ - DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y) DO_HANDLE_NAN(result, z) - /* Saturating arithmetic helpers. */ #define SATCVT(from, to, from_type, to_type, min, max) \ static inline to_type cvt##from##to(from_type x, int *sat) \ @@ -1413,10 +1396,6 @@ VUPK(lsh, s32, s16, UPKLO) #undef UPKHI #undef UPKLO -#undef DO_HANDLE_NAN -#undef HANDLE_NAN1 -#undef HANDLE_NAN2 -#undef HANDLE_NAN3 #undef VECTOR_FOR_INORDER_I #undef HI_IDX #undef LO_IDX From f1af19d767073a0926ce12c19b1f06c4933bca35 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Sep 2012 16:57:09 +0000 Subject: [PATCH 0691/2270] ppc: Make kvm_arch_put_registers() put *all* the registers At least when invoked with high enough 'level' arguments, kvm_arch_put_registers() is supposed to copy essentially all the cpu state as encoded in qemu's internal structures into the kvm state. Currently the ppc version does not do this - it never calls KVM_SET_SREGS, for example, and therefore never sets the SDR1 and various other important though rarely changed registers. Instead, the code paths which need to set these registers need to explicitly make (conditional) kvm calls which transfer the changes to kvm. This breaks the usual model of handling state updates in qemu, where code just changes the internal model and has it flushed out to kvm automatically at some later point. This patch fixes this for Book S ppc CPUs by adding a suitable call to KVM_SET_SREGS and als to KVM_SET_ONE_REG to set the HIOR (the only register that is set with that call so far). This lets us remove the hacks to explicitly set these registers from the kvmppc_set_papr() function. The problem still exists for Book E CPUs (which use a different version of the kvm_sregs structure). But fixing that has some complications of its own so can be left to another day. Lkewise, there is still some ugly code for setting the PVR through special calls to SET_SREGS which is left in for now. The PVR needs to be set especially early because it can affect what other features are available on the CPU, so I need to do more thinking to see if it can be integrated into the normal paths or not. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- target-ppc/kvm.c | 89 +++++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 39 deletions(-) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index a31d278a5f..1a7489bac8 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -60,6 +60,7 @@ static int cap_booke_sregs; static int cap_ppc_smt; static int cap_ppc_rma; static int cap_spapr_tce; +static int cap_hior; /* XXX We have a race condition where we actually have a level triggered * interrupt, but the infrastructure can't expose that yet, so the guest @@ -86,6 +87,7 @@ int kvm_arch_init(KVMState *s) cap_ppc_smt = kvm_check_extension(s, KVM_CAP_PPC_SMT); cap_ppc_rma = kvm_check_extension(s, KVM_CAP_PPC_RMA); cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE); + cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR); if (!cap_interrupt_level) { fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the " @@ -469,6 +471,53 @@ int kvm_arch_put_registers(CPUPPCState *env, int level) env->tlb_dirty = false; } + if (cap_segstate && (level >= KVM_PUT_RESET_STATE)) { + struct kvm_sregs sregs; + + sregs.pvr = env->spr[SPR_PVR]; + + sregs.u.s.sdr1 = env->spr[SPR_SDR1]; + + /* Sync SLB */ +#ifdef TARGET_PPC64 + for (i = 0; i < 64; i++) { + sregs.u.s.ppc64.slb[i].slbe = env->slb[i].esid; + sregs.u.s.ppc64.slb[i].slbv = env->slb[i].vsid; + } +#endif + + /* Sync SRs */ + for (i = 0; i < 16; i++) { + sregs.u.s.ppc32.sr[i] = env->sr[i]; + } + + /* Sync BATs */ + for (i = 0; i < 8; i++) { + sregs.u.s.ppc32.dbat[i] = ((uint64_t)env->DBAT[1][i] << 32) + | env->DBAT[0][i]; + sregs.u.s.ppc32.ibat[i] = ((uint64_t)env->IBAT[1][i] << 32) + | env->IBAT[0][i]; + } + + ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs); + if (ret) { + return ret; + } + } + + if (cap_hior && (level >= KVM_PUT_RESET_STATE)) { + uint64_t hior = env->spr[SPR_HIOR]; + struct kvm_one_reg reg = { + .id = KVM_REG_PPC_HIOR, + .addr = (uintptr_t) &hior, + }; + + ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, ®); + if (ret) { + return ret; + } + } + return ret; } @@ -946,52 +995,14 @@ int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len) void kvmppc_set_papr(CPUPPCState *env) { struct kvm_enable_cap cap = {}; - struct kvm_one_reg reg = {}; - struct kvm_sregs sregs = {}; int ret; - uint64_t hior = env->spr[SPR_HIOR]; cap.cap = KVM_CAP_PPC_PAPR; ret = kvm_vcpu_ioctl(env, KVM_ENABLE_CAP, &cap); if (ret) { - goto fail; + cpu_abort(env, "This KVM version does not support PAPR\n"); } - - /* - * XXX We set HIOR here. It really should be a qdev property of - * the CPU node, but we don't have CPUs converted to qdev yet. - * - * Once we have qdev CPUs, move HIOR to a qdev property and - * remove this chunk. - */ - reg.id = KVM_REG_PPC_HIOR; - reg.addr = (uintptr_t)&hior; - ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, ®); - if (ret) { - fprintf(stderr, "Couldn't set HIOR. Maybe you're running an old \n" - "kernel with support for HV KVM but no PAPR PR \n" - "KVM in which case things will work. If they don't \n" - "please update your host kernel!\n"); - } - - /* Set SDR1 so kernel space finds the HTAB */ - ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs); - if (ret) { - goto fail; - } - - sregs.u.s.sdr1 = env->spr[SPR_SDR1]; - - ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs); - if (ret) { - goto fail; - } - - return; - -fail: - cpu_abort(env, "This KVM version does not support PAPR\n"); } int kvmppc_smt_threads(void) From 048706d971c1830d7813052ca027ae00c519e894 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Sep 2012 16:57:10 +0000 Subject: [PATCH 0692/2270] pseries: Fix and cleanup CPU initialization and reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current pseries machine init function iterates over the CPUs at several points, doing various bits of initialization. This is messy; these can and should be merged into a single iteration doing all the necessary per cpu initialization. Worse, some of these initializations were setting up state which should be set on every reset, not just at machine init time. A few of the initializations simply weren't necessary at all. This patch, therefore, moves those things that need to be to the per-cpu reset handler, and combines the remainder into two loops over the cpus (which also creates them). The second loop is for setting up hash table information, and will be removed in a subsequent patch also making other fixes to the hash table setup. This exposes a bug in our start-cpu RTAS routine (called by the guest to start up CPUs other than CPU0) under kvm. Previously, this function did not make a call to ensure that it's changes to the new cpu's state were pushed into KVM in-kernel state. We sort-of got away with this because some of the initializations had already placed the secondary CPUs into the right starting state for the sorts of Linux guests we've been running. Nonetheless the start-cpu RTAS call's behaviour was not correct and could easily have been broken by guest changes. This patch also fixes it. Signed-off-by: David Gibson Reviewed-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/spapr.c | 34 ++++++++++++++++++++-------------- hw/spapr_rtas.c | 5 +++++ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index c34b767c6e..d88525aadd 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -581,8 +581,16 @@ static void spapr_reset(void *opaque) static void spapr_cpu_reset(void *opaque) { PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; cpu_reset(CPU(cpu)); + + /* All CPUs start halted. CPU0 is unhalted from the machine level + * reset code and the rest are explicitly started up by the guest + * using an RTAS call */ + env->halted = 1; + + env->spr[SPR_HIOR] = 0; } /* Returns whether we want to use VGA or not */ @@ -665,11 +673,16 @@ static void ppc_spapr_init(ram_addr_t ram_size, /* Set time-base frequency to 512 MHz */ cpu_ppc_tb_init(env, TIMEBASE_FREQ); - qemu_register_reset(spapr_cpu_reset, cpu); - env->hreset_vector = 0x60; + /* PAPR always has exception vectors in RAM not ROM */ env->hreset_excp_prefix = 0; - env->gpr[3] = env->cpu_index; + + /* Tell KVM that we're in PAPR mode */ + if (kvm_enabled()) { + kvmppc_set_papr(env); + } + + qemu_register_reset(spapr_cpu_reset, cpu); } /* allocate RAM */ @@ -685,7 +698,10 @@ static void ppc_spapr_init(ram_addr_t ram_size, /* allocate hash page table. For now we always make this 16mb, * later we should probably make it scale to the size of guest - * RAM */ + * RAM. FIXME: setting the htab information in the CPU env really + * belongs at CPU reset time, but we can get away with it for now + * because the PAPR guest is not permitted to write SDR1 so in + * fact these settings will never change during the run */ spapr->htab_size = 1ULL << (pteg_shift + 7); spapr->htab = qemu_memalign(spapr->htab_size, spapr->htab_size); @@ -697,11 +713,6 @@ static void ppc_spapr_init(ram_addr_t ram_size, /* Tell KVM that we're in PAPR mode */ env->spr[SPR_SDR1] = (unsigned long)spapr->htab | ((pteg_shift + 7) - 18); - env->spr[SPR_HIOR] = 0; - - if (kvm_enabled()) { - kvmppc_set_papr(env); - } } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin"); @@ -827,11 +838,6 @@ static void ppc_spapr_init(ram_addr_t ram_size, spapr->entry_point = 0x100; - /* SLOF will startup the secondary CPUs using RTAS */ - for (env = first_cpu; env != NULL; env = env->next_cpu) { - env->halted = 1; - } - /* Prepare the device tree */ spapr->fdt_skel = spapr_create_fdt_skel(cpu_model, rma_size, initrd_base, initrd_size, diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c index ae18595150..b808f80017 100644 --- a/hw/spapr_rtas.c +++ b/hw/spapr_rtas.c @@ -184,6 +184,11 @@ static void rtas_start_cpu(sPAPREnvironment *spapr, return; } + /* This will make sure qemu state is up to date with kvm, and + * mark it dirty so our changes get flushed back before the + * new cpu enters */ + kvm_cpu_synchronize_state(env); + env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME); env->nip = start; env->gpr[3] = r3; From c8787ad477f3be5a971b877dcb1bae5752c5796a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Sep 2012 16:57:11 +0000 Subject: [PATCH 0693/2270] pseries: Use new method to correct reset sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A number of things need to occur during reset of the PAPR paravirtualized platform in a specific order. For example, the hash table needs to be cleared before the CPUs are reset, so that they initialize their register state correctly, and the CPUs need to have their main reset called before we set up the entry point state on the boot cpu. We also need to have the main qdev reset happen before the creation and installation of the device tree for the new boot, because we need the state of the devices settled to correctly construct the device tree. We currently do the pseries once-per-reset initializations done from a reset handler. However we can't adequately control when this handler is called during the reset - in particular we can't guarantee it happens after all the qdev resets (since qdevs might be registered after the machine init function has executed). This patch uses the new QEMUMachine reset method to to fix this problem, ensuring the various order dependent reset steps happen in the correct order. Signed-off-by: David Gibson Reviewed-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/spapr.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index d88525aadd..68542e89b6 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -559,13 +559,13 @@ static void emulate_spapr_hypercall(CPUPPCState *env) env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]); } -static void spapr_reset(void *opaque) +static void ppc_spapr_reset(void) { - sPAPREnvironment *spapr = (sPAPREnvironment *)opaque; - /* flush out the hash table */ memset(spapr->htab, 0, spapr->htab_size); + qemu_devices_reset(); + /* Load the fdt */ spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr, spapr->rtas_size); @@ -845,14 +845,13 @@ static void ppc_spapr_init(ram_addr_t ram_size, boot_device, kernel_cmdline, pteg_shift + 7); assert(spapr->fdt_skel != NULL); - - qemu_register_reset(spapr_reset, spapr); } static QEMUMachine spapr_machine = { .name = "pseries", .desc = "pSeries Logical Partition (PAPR compliant)", .init = ppc_spapr_init, + .reset = ppc_spapr_reset, .max_cpus = MAX_CPUS, .no_parallel = 1, .use_scsi = 1, From 7f763a5d994bbddb50705d2e50decdf52937521f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Sep 2012 16:57:12 +0000 Subject: [PATCH 0694/2270] pseries: Add support for new KVM hash table control call This adds support for then new "reset htab" ioctl which allows qemu to properly cleanup the MMU hash table when the guest is reset. With the corresponding kernel support, reset of a guest now works properly. This also paves the way for indicating a different size hash table to the kernel and for the kernel to be able to impose limits on the requested size. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.c | 288 +++++++++++++++++++++++++------------------ hw/spapr.h | 4 +- target-ppc/kvm.c | 29 +++++ target-ppc/kvm_ppc.h | 19 +++ 4 files changed, 220 insertions(+), 120 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 68542e89b6..0a0e9cddc6 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -85,6 +85,8 @@ #define PHANDLE_XICP 0x00001111 +#define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift)) + sPAPREnvironment *spapr; int spapr_allocate_irq(int hint, enum xics_irq_type type) @@ -134,12 +136,13 @@ int spapr_allocate_irq_block(int num, enum xics_irq_type type) return first; } -static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr) +static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr) { int ret = 0, offset; CPUPPCState *env; char cpu_model[32]; int smt = kvmppc_smt_threads(); + uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; assert(spapr->cpu_model); @@ -163,8 +166,16 @@ static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr) return offset; } - ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity, - sizeof(associativity)); + if (nb_numa_nodes > 1) { + ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity, + sizeof(associativity)); + if (ret < 0) { + return ret; + } + } + + ret = fdt_setprop(fdt, offset, "ibm,pft-size", + pft_size_prop, sizeof(pft_size_prop)); if (ret < 0) { return ret; } @@ -206,36 +217,6 @@ static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop, return (p - prop) * sizeof(uint32_t); } -static void *spapr_create_fdt_skel(const char *cpu_model, - target_phys_addr_t rma_size, - target_phys_addr_t initrd_base, - target_phys_addr_t initrd_size, - target_phys_addr_t kernel_size, - const char *boot_device, - const char *kernel_cmdline, - long hash_shift) -{ - void *fdt; - CPUPPCState *env; - uint64_t mem_reg_property[2]; - uint32_t start_prop = cpu_to_be32(initrd_base); - uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size); - uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)}; - char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt" - "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk"; - char qemu_hypertas_prop[] = "hcall-memop1"; - uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)}; - int i; - char *modelname; - int smt = kvmppc_smt_threads(); - unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80}; - uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)}; - uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0), - cpu_to_be32(0x0), cpu_to_be32(0x0), - cpu_to_be32(0x0)}; - char mem_name[32]; - target_phys_addr_t node0_size, mem_start; - #define _FDT(exp) \ do { \ int ret = (exp); \ @@ -246,6 +227,27 @@ static void *spapr_create_fdt_skel(const char *cpu_model, } \ } while (0) + +static void *spapr_create_fdt_skel(const char *cpu_model, + target_phys_addr_t initrd_base, + target_phys_addr_t initrd_size, + target_phys_addr_t kernel_size, + const char *boot_device, + const char *kernel_cmdline) +{ + void *fdt; + CPUPPCState *env; + uint32_t start_prop = cpu_to_be32(initrd_base); + uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size); + char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt" + "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk"; + char qemu_hypertas_prop[] = "hcall-memop1"; + uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)}; + uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)}; + char *modelname; + int i, smt = kvmppc_smt_threads(); + unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80}; + fdt = g_malloc0(FDT_MAX_SIZE); _FDT((fdt_create(fdt, FDT_MAX_SIZE))); @@ -289,55 +291,6 @@ static void *spapr_create_fdt_skel(const char *cpu_model, _FDT((fdt_end_node(fdt))); - /* memory node(s) */ - node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size; - if (rma_size > node0_size) { - rma_size = node0_size; - } - - /* RMA */ - mem_reg_property[0] = 0; - mem_reg_property[1] = cpu_to_be64(rma_size); - _FDT((fdt_begin_node(fdt, "memory@0"))); - _FDT((fdt_property_string(fdt, "device_type", "memory"))); - _FDT((fdt_property(fdt, "reg", mem_reg_property, - sizeof(mem_reg_property)))); - _FDT((fdt_property(fdt, "ibm,associativity", associativity, - sizeof(associativity)))); - _FDT((fdt_end_node(fdt))); - - /* RAM: Node 0 */ - if (node0_size > rma_size) { - mem_reg_property[0] = cpu_to_be64(rma_size); - mem_reg_property[1] = cpu_to_be64(node0_size - rma_size); - - sprintf(mem_name, "memory@" TARGET_FMT_lx, rma_size); - _FDT((fdt_begin_node(fdt, mem_name))); - _FDT((fdt_property_string(fdt, "device_type", "memory"))); - _FDT((fdt_property(fdt, "reg", mem_reg_property, - sizeof(mem_reg_property)))); - _FDT((fdt_property(fdt, "ibm,associativity", associativity, - sizeof(associativity)))); - _FDT((fdt_end_node(fdt))); - } - - /* RAM: Node 1 and beyond */ - mem_start = node0_size; - for (i = 1; i < nb_numa_nodes; i++) { - mem_reg_property[0] = cpu_to_be64(mem_start); - mem_reg_property[1] = cpu_to_be64(node_mem[i]); - associativity[3] = associativity[4] = cpu_to_be32(i); - sprintf(mem_name, "memory@" TARGET_FMT_lx, mem_start); - _FDT((fdt_begin_node(fdt, mem_name))); - _FDT((fdt_property_string(fdt, "device_type", "memory"))); - _FDT((fdt_property(fdt, "reg", mem_reg_property, - sizeof(mem_reg_property)))); - _FDT((fdt_property(fdt, "ibm,associativity", associativity, - sizeof(associativity)))); - _FDT((fdt_end_node(fdt))); - mem_start += node_mem[i]; - } - /* cpus */ _FDT((fdt_begin_node(fdt, "cpus"))); @@ -389,8 +342,6 @@ static void *spapr_create_fdt_skel(const char *cpu_model, _FDT((fdt_property_cell(fdt, "timebase-frequency", tbfreq))); _FDT((fdt_property_cell(fdt, "clock-frequency", cpufreq))); _FDT((fdt_property_cell(fdt, "ibm,slb-size", env->slb_nr))); - _FDT((fdt_property(fdt, "ibm,pft-size", - pft_size_prop, sizeof(pft_size_prop)))); _FDT((fdt_property_string(fdt, "status", "okay"))); _FDT((fdt_property(fdt, "64-bit", NULL, 0))); @@ -489,6 +440,68 @@ static void *spapr_create_fdt_skel(const char *cpu_model, return fdt; } +static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt) +{ + uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0), + cpu_to_be32(0x0), cpu_to_be32(0x0), + cpu_to_be32(0x0)}; + char mem_name[32]; + target_phys_addr_t node0_size, mem_start; + uint64_t mem_reg_property[2]; + int i, off; + + /* memory node(s) */ + node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size; + if (spapr->rma_size > node0_size) { + spapr->rma_size = node0_size; + } + + /* RMA */ + mem_reg_property[0] = 0; + mem_reg_property[1] = cpu_to_be64(spapr->rma_size); + off = fdt_add_subnode(fdt, 0, "memory@0"); + _FDT(off); + _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); + _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, + sizeof(mem_reg_property)))); + _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, + sizeof(associativity)))); + + /* RAM: Node 0 */ + if (node0_size > spapr->rma_size) { + mem_reg_property[0] = cpu_to_be64(spapr->rma_size); + mem_reg_property[1] = cpu_to_be64(node0_size - spapr->rma_size); + + sprintf(mem_name, "memory@" TARGET_FMT_lx, spapr->rma_size); + off = fdt_add_subnode(fdt, 0, mem_name); + _FDT(off); + _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); + _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, + sizeof(mem_reg_property)))); + _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, + sizeof(associativity)))); + } + + /* RAM: Node 1 and beyond */ + mem_start = node0_size; + for (i = 1; i < nb_numa_nodes; i++) { + mem_reg_property[0] = cpu_to_be64(mem_start); + mem_reg_property[1] = cpu_to_be64(node_mem[i]); + associativity[3] = associativity[4] = cpu_to_be32(i); + sprintf(mem_name, "memory@" TARGET_FMT_lx, mem_start); + off = fdt_add_subnode(fdt, 0, mem_name); + _FDT(off); + _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); + _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, + sizeof(mem_reg_property)))); + _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, + sizeof(associativity)))); + mem_start += node_mem[i]; + } + + return 0; +} + static void spapr_finalize_fdt(sPAPREnvironment *spapr, target_phys_addr_t fdt_addr, target_phys_addr_t rtas_addr, @@ -503,6 +516,12 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr, /* open out the base tree into a temp buffer for the final tweaks */ _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE))); + ret = spapr_populate_memory(spapr, fdt); + if (ret < 0) { + fprintf(stderr, "couldn't setup memory nodes in fdt\n"); + exit(1); + } + ret = spapr_populate_vdevice(spapr->vio_bus, fdt); if (ret < 0) { fprintf(stderr, "couldn't setup vio devices in fdt\n"); @@ -525,11 +544,9 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr, } /* Advertise NUMA via ibm,associativity */ - if (nb_numa_nodes > 1) { - ret = spapr_set_associativity(fdt, spapr); - if (ret < 0) { - fprintf(stderr, "Couldn't set up NUMA device tree properties\n"); - } + ret = spapr_fixup_cpu_dt(fdt, spapr); + if (ret < 0) { + fprintf(stderr, "Couldn't finalize CPU device tree properties\n"); } if (!spapr->has_graphics) { @@ -559,10 +576,39 @@ static void emulate_spapr_hypercall(CPUPPCState *env) env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]); } +static void spapr_reset_htab(sPAPREnvironment *spapr) +{ + long shift; + + /* allocate hash page table. For now we always make this 16mb, + * later we should probably make it scale to the size of guest + * RAM */ + + shift = kvmppc_reset_htab(spapr->htab_shift); + + if (shift > 0) { + /* Kernel handles htab, we don't need to allocate one */ + spapr->htab_shift = shift; + } else { + if (!spapr->htab) { + /* Allocate an htab if we don't yet have one */ + spapr->htab = qemu_memalign(HTAB_SIZE(spapr), HTAB_SIZE(spapr)); + } + + /* And clear it */ + memset(spapr->htab, 0, HTAB_SIZE(spapr)); + } + + /* Update the RMA size if necessary */ + if (spapr->vrma_adjust) { + spapr->rma_size = kvmppc_rma_size(ram_size, spapr->htab_shift); + } +} + static void ppc_spapr_reset(void) { - /* flush out the hash table */ - memset(spapr->htab, 0, spapr->htab_size); + /* Reset the hash table & recalc the RMA */ + spapr_reset_htab(spapr); qemu_devices_reset(); @@ -591,6 +637,12 @@ static void spapr_cpu_reset(void *opaque) env->halted = 1; env->spr[SPR_HIOR] = 0; + + env->external_htab = spapr->htab; + env->htab_base = -1; + env->htab_mask = HTAB_SIZE(spapr) - 1; + env->spr[SPR_SDR1] = (unsigned long)spapr->htab | + (spapr->htab_shift - 18); } /* Returns whether we want to use VGA or not */ @@ -624,11 +676,10 @@ static void ppc_spapr_init(ram_addr_t ram_size, int i; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); - target_phys_addr_t rma_alloc_size, rma_size; + target_phys_addr_t rma_alloc_size; uint32_t initrd_base = 0; long kernel_size = 0, initrd_size = 0; long load_limit, rtas_limit, fw_size; - long pteg_shift = 17; char *filename; msi_supported = true; @@ -645,20 +696,39 @@ static void ppc_spapr_init(ram_addr_t ram_size, hw_error("qemu: Unable to create RMA\n"); exit(1); } + if (rma_alloc_size && (rma_alloc_size < ram_size)) { - rma_size = rma_alloc_size; + spapr->rma_size = rma_alloc_size; } else { - rma_size = ram_size; + spapr->rma_size = ram_size; + + /* With KVM, we don't actually know whether KVM supports an + * unbounded RMA (PR KVM) or is limited by the hash table size + * (HV KVM using VRMA), so we always assume the latter + * + * In that case, we also limit the initial allocations for RTAS + * etc... to 256M since we have no way to know what the VRMA size + * is going to be as it depends on the size of the hash table + * isn't determined yet. + */ + if (kvm_enabled()) { + spapr->vrma_adjust = 1; + spapr->rma_size = MIN(spapr->rma_size, 0x10000000); + } } /* We place the device tree and RTAS just below either the top of the RMA, * or just below 2GB, whichever is lowere, so that it can be * processed with 32-bit real mode code if necessary */ - rtas_limit = MIN(rma_size, 0x80000000); + rtas_limit = MIN(spapr->rma_size, 0x80000000); spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE; spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE; load_limit = spapr->fdt_addr - FW_OVERHEAD; + /* For now, always aim for a 16MB hash table */ + /* FIXME: we should change this default based on RAM size */ + spapr->htab_shift = 24; + /* init CPUs */ if (cpu_model == NULL) { cpu_model = kvm_enabled() ? "host" : "POWER7"; @@ -696,25 +766,6 @@ static void ppc_spapr_init(ram_addr_t ram_size, memory_region_add_subregion(sysmem, nonrma_base, ram); } - /* allocate hash page table. For now we always make this 16mb, - * later we should probably make it scale to the size of guest - * RAM. FIXME: setting the htab information in the CPU env really - * belongs at CPU reset time, but we can get away with it for now - * because the PAPR guest is not permitted to write SDR1 so in - * fact these settings will never change during the run */ - spapr->htab_size = 1ULL << (pteg_shift + 7); - spapr->htab = qemu_memalign(spapr->htab_size, spapr->htab_size); - - for (env = first_cpu; env != NULL; env = env->next_cpu) { - env->external_htab = spapr->htab; - env->htab_base = -1; - env->htab_mask = spapr->htab_size - 1; - - /* Tell KVM that we're in PAPR mode */ - env->spr[SPR_SDR1] = (unsigned long)spapr->htab | - ((pteg_shift + 7) - 18); - } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin"); spapr->rtas_size = load_image_targphys(filename, spapr->rtas_addr, rtas_limit - spapr->rtas_addr); @@ -787,7 +838,7 @@ static void ppc_spapr_init(ram_addr_t ram_size, } } - if (rma_size < (MIN_RMA_SLOF << 20)) { + if (spapr->rma_size < (MIN_RMA_SLOF << 20)) { fprintf(stderr, "qemu: pSeries SLOF firmware requires >= " "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF); exit(1); @@ -839,11 +890,10 @@ static void ppc_spapr_init(ram_addr_t ram_size, spapr->entry_point = 0x100; /* Prepare the device tree */ - spapr->fdt_skel = spapr_create_fdt_skel(cpu_model, rma_size, + spapr->fdt_skel = spapr_create_fdt_skel(cpu_model, initrd_base, initrd_size, kernel_size, - boot_device, kernel_cmdline, - pteg_shift + 7); + boot_device, kernel_cmdline); assert(spapr->fdt_skel != NULL); } diff --git a/hw/spapr.h b/hw/spapr.h index ac34a171e3..f1fb646a56 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -15,7 +15,9 @@ typedef struct sPAPREnvironment { target_phys_addr_t ram_limit; void *htab; - long htab_size; + long htab_shift; + target_phys_addr_t rma_size; + int vrma_adjust; target_phys_addr_t fdt_addr, rtas_addr; long rtas_size; void *fdt_skel; diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 1a7489bac8..546c11604c 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -1010,6 +1010,7 @@ int kvmppc_smt_threads(void) return cap_ppc_smt ? cap_ppc_smt : 1; } +#ifdef TARGET_PPC64 off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem) { void *rma; @@ -1053,6 +1054,16 @@ off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem) return size; } +uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift) +{ + if (cap_ppc_rma >= 2) { + return current_size; + } + return MIN(current_size, + getrampagesize() << (hash_shift - 7)); +} +#endif + void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd) { struct kvm_create_spapr_tce args = { @@ -1112,6 +1123,24 @@ int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t window_size) return 0; } +int kvmppc_reset_htab(int shift_hint) +{ + uint32_t shift = shift_hint; + + if (kvm_enabled() && + kvm_check_extension(kvm_state, KVM_CAP_PPC_ALLOC_HTAB)) { + int ret; + ret = kvm_vm_ioctl(kvm_state, KVM_PPC_ALLOCATE_HTAB, &shift); + if (ret < 0) { + return ret; + } + return shift; + } + + /* For now.. */ + return 0; +} + static inline uint32_t mfpvr(void) { uint32_t pvr; diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h index e2f8703853..baad6eb75b 100644 --- a/target-ppc/kvm_ppc.h +++ b/target-ppc/kvm_ppc.h @@ -27,6 +27,8 @@ int kvmppc_smt_threads(void); off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem); void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd); int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size); +int kvmppc_reset_htab(int shift_hint); +uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift); #endif /* !CONFIG_USER_ONLY */ const ppc_def_t *kvmppc_host_cpu_def(void); int kvmppc_fixup_cpu(CPUPPCState *env); @@ -94,6 +96,23 @@ static inline int kvmppc_remove_spapr_tce(void *table, int pfd, { return -1; } + +static inline int kvmppc_reset_htab(int shift_hint) +{ + return -1; +} + +static inline uint64_t kvmppc_rma_size(uint64_t current_size, + unsigned int hash_shift) +{ + return ram_size; +} + +static inline int kvmppc_update_sdr1(CPUPPCState *env) +{ + return 0; +} + #endif /* !CONFIG_USER_ONLY */ static inline const ppc_def_t *kvmppc_host_cpu_def(void) From 4dd96f244f62d5e4b493c1f4071c0d4a4a57474d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Sep 2012 16:57:13 +0000 Subject: [PATCH 0695/2270] pseries: Clear TCE and signal state when resetting PAPR VIO devices When we reset the system, the reset method for VIO bus devices resets the state of their request queue (if present) as it should. However it was not resetting the state of their TCE table (DMA translation) if present. It was also not resetting the state of the per-device signal mask set with H_VIO_SIGNAL. This patch corrects both bugs, and also removes some small code duplication in the reset paths. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_vio.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index 7ca445216d..752836e76c 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -324,9 +324,7 @@ static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev) } dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size); - dev->crq.qladdr = 0; - dev->crq.qsize = 0; - dev->crq.qnext = 0; + free_crq(dev); } static void rtas_set_tce_bypass(sPAPREnvironment *spapr, uint32_t token, @@ -409,9 +407,10 @@ static void spapr_vio_busdev_reset(DeviceState *qdev) VIOsPAPRDevice *dev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev); VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev); - if (dev->crq.qsize) { - free_crq(dev); - } + /* Shut down the request queue and TCEs if necessary */ + spapr_vio_quiesce_one(dev); + + dev->signal_state = 0; if (pc->reset) { pc->reset(dev); From eddeed26ac83392053aef823a341f643ea8e3d2f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Sep 2012 16:57:14 +0000 Subject: [PATCH 0696/2270] pseries: Reset emulated PCI TCE tables on system reset The emulated PCI host bridge on the pseries machine incorporates an IOMMU (PAPR TCE table). Currently the mappings in this IOMMU are not cleared when we reset the system. This patch fixes this bug. To do this it adds a new reset function to the IOMMU emulation code. The VIO devices already reset their TCE tables, but they do so by destroying and re-creating their DMA context. This doesn't work for the PCI host bridge, because the infrastructure for PCI IOMMUs has already copied/cached the DMA pointer context into the subordinate PCI device structures. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.h | 1 + hw/spapr_iommu.c | 11 +++++++++++ hw/spapr_pci.c | 10 ++++++++++ 3 files changed, 22 insertions(+) diff --git a/hw/spapr.h b/hw/spapr.h index f1fb646a56..f9a7b0fa33 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -338,6 +338,7 @@ typedef struct sPAPRTCE { void spapr_iommu_init(void); DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size); void spapr_tce_free(DMAContext *dma); +void spapr_tce_reset(DMAContext *dma); int spapr_dma_dt(void *fdt, int node_off, const char *propname, uint32_t liobn, uint64_t window, uint32_t size); int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname, diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c index 53b731773a..216aa06809 100644 --- a/hw/spapr_iommu.c +++ b/hw/spapr_iommu.c @@ -162,6 +162,17 @@ void spapr_tce_free(DMAContext *dma) } } +void spapr_tce_reset(DMAContext *dma) +{ + if (dma) { + sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma); + size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT) + * sizeof(sPAPRTCE); + + memset(tcet->table, 0, table_size); + } +} + static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba, target_ulong tce) { diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 661c05bc30..203155e32b 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -595,6 +595,15 @@ static int spapr_phb_init(SysBusDevice *s) return 0; } +static void spapr_phb_reset(DeviceState *qdev) +{ + SysBusDevice *s = sysbus_from_qdev(qdev); + sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s); + + /* Reset the IOMMU state */ + spapr_tce_reset(sphb->dma); +} + static Property spapr_phb_properties[] = { DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, 0), DEFINE_PROP_STRING("busname", sPAPRPHBState, busname), @@ -613,6 +622,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data) sdc->init = spapr_phb_init; dc->props = spapr_phb_properties; + dc->reset = spapr_phb_reset; } static const TypeInfo spapr_phb_info = { From 256b408abea2cfe18d8c0278e5b46213509db271 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Sep 2012 16:57:15 +0000 Subject: [PATCH 0697/2270] pseries: Fix XICS reset The XICS interrupt controller used on the pseries machine currently has no reset handler. We can get away with this under some circumstances, but it's not correct, and can cause failures if the XICS happens to be in the wrong state at the time of reset. This patch adds a hook to properly reset the XICS state. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/xics.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/hw/xics.c b/hw/xics.c index b674771dc4..a8a08ce02e 100644 --- a/hw/xics.c +++ b/hw/xics.c @@ -489,11 +489,36 @@ static void rtas_int_on(sPAPREnvironment *spapr, uint32_t token, rtas_st(rets, 0, 0); /* Success */ } +static void xics_reset(void *opaque) +{ + struct icp_state *icp = (struct icp_state *)opaque; + struct ics_state *ics = icp->ics; + int i; + + for (i = 0; i < icp->nr_servers; i++) { + icp->ss[i].xirr = 0; + icp->ss[i].pending_priority = 0; + icp->ss[i].mfrr = 0xff; + /* Make all outputs are deasserted */ + qemu_set_irq(icp->ss[i].output, 0); + } + + for (i = 0; i < ics->nr_irqs; i++) { + /* Reset everything *except* the type */ + ics->irqs[i].server = 0; + ics->irqs[i].asserted = 0; + ics->irqs[i].sent = 0; + ics->irqs[i].rejected = 0; + ics->irqs[i].masked_pending = 0; + ics->irqs[i].priority = 0xff; + ics->irqs[i].saved_priority = 0xff; + } +} + struct icp_state *xics_system_init(int nr_irqs) { CPUPPCState *env; int max_server_num; - int i; struct icp_state *icp; struct ics_state *ics; @@ -508,10 +533,6 @@ struct icp_state *xics_system_init(int nr_irqs) icp->nr_servers = max_server_num + 1; icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state)); - for (i = 0; i < icp->nr_servers; i++) { - icp->ss[i].mfrr = 0xff; - } - for (env = first_cpu; env != NULL; env = env->next_cpu) { struct icp_server_state *ss = &icp->ss[env->cpu_index]; @@ -539,11 +560,6 @@ struct icp_state *xics_system_init(int nr_irqs) icp->ics = ics; ics->icp = icp; - for (i = 0; i < nr_irqs; i++) { - ics->irqs[i].priority = 0xff; - ics->irqs[i].saved_priority = 0xff; - } - ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, nr_irqs); spapr_register_hypercall(H_CPPR, h_cppr); @@ -556,5 +572,7 @@ struct icp_state *xics_system_init(int nr_irqs) spapr_rtas_register("ibm,int-off", rtas_int_off); spapr_rtas_register("ibm,int-on", rtas_int_on); + qemu_register_reset(xics_reset, icp); + return icp; } From 1dd088946cf464a994bc93945a360aef049493af Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Sep 2012 16:57:16 +0000 Subject: [PATCH 0698/2270] pseries: Small cleanup to H_CEDE implementation The H_CEDE hypercall implementation for the pseries machine doesn't trigger quite the right path in the main cpu exec loop. We should set exit_request to pop up one extra level and recheck state, and we should set the exception_index to EXCP_HLT (H_CEDE is roughly equivalent to the hlt instruction on x86). In practice, this doesn't really matter except for KVM, and KVM implements H_CEDE internally so we never hit this code path. But we might as well get it right, just in case it matters some day. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_hcall.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c index abd847f96c..2df94d197a 100644 --- a/hw/spapr_hcall.c +++ b/hw/spapr_hcall.c @@ -544,6 +544,8 @@ static target_ulong h_cede(CPUPPCState *env, sPAPREnvironment *spapr, hreg_compute_hflags(env); if (!cpu_has_work(env)) { env->halted = 1; + env->exception_index = EXCP_HLT; + env->exit_request = 1; } return H_SUCCESS; } From 98ca8c023825fc6dd99e6cea1956d84ed8cadb3a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Sep 2012 16:57:17 +0000 Subject: [PATCH 0699/2270] pseries: Remove C bitfields from xics code The XICS interrupt controller emulation uses some C bitfield variables in its internal state structure. This makes like awkward for saving the state because we don't have easy VMSTATE helpers for bitfields. This patch removes the bitfields, instead using explicit bit masking in a single status variable. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/xics.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/hw/xics.c b/hw/xics.c index a8a08ce02e..648af2538d 100644 --- a/hw/xics.c +++ b/hw/xics.c @@ -165,11 +165,12 @@ struct ics_irq_state { int server; uint8_t priority; uint8_t saved_priority; +#define XICS_STATUS_ASSERTED 0x1 +#define XICS_STATUS_SENT 0x2 +#define XICS_STATUS_REJECTED 0x4 +#define XICS_STATUS_MASKED_PENDING 0x8 + uint8_t status; enum xics_irq_type type; - int asserted:1; - int sent:1; - int rejected:1; - int masked_pending:1; }; struct ics_state { @@ -191,8 +192,8 @@ static void resend_msi(struct ics_state *ics, int srcno) struct ics_irq_state *irq = ics->irqs + srcno; /* FIXME: filter by server#? */ - if (irq->rejected) { - irq->rejected = 0; + if (irq->status & XICS_STATUS_REJECTED) { + irq->status &= ~XICS_STATUS_REJECTED; if (irq->priority != 0xff) { icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority); @@ -204,8 +205,10 @@ static void resend_lsi(struct ics_state *ics, int srcno) { struct ics_irq_state *irq = ics->irqs + srcno; - if ((irq->priority != 0xff) && irq->asserted && !irq->sent) { - irq->sent = 1; + if ((irq->priority != 0xff) + && (irq->status & XICS_STATUS_ASSERTED) + && !(irq->status & XICS_STATUS_SENT)) { + irq->status |= XICS_STATUS_SENT; icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority); } } @@ -216,7 +219,7 @@ static void set_irq_msi(struct ics_state *ics, int srcno, int val) if (val) { if (irq->priority == 0xff) { - irq->masked_pending = 1; + irq->status |= XICS_STATUS_MASKED_PENDING; /* masked pending */ ; } else { icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority); @@ -228,7 +231,11 @@ static void set_irq_lsi(struct ics_state *ics, int srcno, int val) { struct ics_irq_state *irq = ics->irqs + srcno; - irq->asserted = val; + if (val) { + irq->status |= XICS_STATUS_ASSERTED; + } else { + irq->status &= ~XICS_STATUS_ASSERTED; + } resend_lsi(ics, srcno); } @@ -248,11 +255,12 @@ static void write_xive_msi(struct ics_state *ics, int srcno) { struct ics_irq_state *irq = ics->irqs + srcno; - if (!irq->masked_pending || (irq->priority == 0xff)) { + if (!(irq->status & XICS_STATUS_MASKED_PENDING) + || (irq->priority == 0xff)) { return; } - irq->masked_pending = 0; + irq->status &= ~XICS_STATUS_MASKED_PENDING; icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority); } @@ -281,8 +289,8 @@ static void ics_reject(struct ics_state *ics, int nr) { struct ics_irq_state *irq = ics->irqs + nr - ics->offset; - irq->rejected = 1; /* Irrelevant but harmless for LSI */ - irq->sent = 0; /* Irrelevant but harmless for MSI */ + irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */ + irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */ } static void ics_resend(struct ics_state *ics) @@ -307,7 +315,7 @@ static void ics_eoi(struct ics_state *ics, int nr) struct ics_irq_state *irq = ics->irqs + srcno; if (irq->type == XICS_LSI) { - irq->sent = 0; + irq->status &= ~XICS_STATUS_SENT; } } @@ -506,10 +514,7 @@ static void xics_reset(void *opaque) for (i = 0; i < ics->nr_irqs; i++) { /* Reset everything *except* the type */ ics->irqs[i].server = 0; - ics->irqs[i].asserted = 0; - ics->irqs[i].sent = 0; - ics->irqs[i].rejected = 0; - ics->irqs[i].masked_pending = 0; + ics->irqs[i].status = 0; ics->irqs[i].priority = 0xff; ics->irqs[i].saved_priority = 0xff; } From ff9d2afa618acd81d926c9c213b4ff5f7163db1d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Sep 2012 16:57:18 +0000 Subject: [PATCH 0700/2270] pseries: Remove XICS irq type enum type Currently the XICS interrupt controller emulation uses a custom enum to specify whether a given interrupt is level-sensitive or message-triggered. This enum makes life awkward for saving the state, and isn't particularly useful since there are only two possibilities. This patch replaces the enum with a simple bool. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.c | 8 ++++---- hw/spapr.h | 8 ++++---- hw/spapr_pci.c | 2 +- hw/xics.c | 16 +++++++--------- hw/xics.h | 8 +------- 5 files changed, 17 insertions(+), 25 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 0a0e9cddc6..1177efaa98 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -89,7 +89,7 @@ sPAPREnvironment *spapr; -int spapr_allocate_irq(int hint, enum xics_irq_type type) +int spapr_allocate_irq(int hint, bool lsi) { int irq; @@ -105,13 +105,13 @@ int spapr_allocate_irq(int hint, enum xics_irq_type type) return 0; } - xics_set_irq_type(spapr->icp, irq, type); + xics_set_irq_type(spapr->icp, irq, lsi); return irq; } /* Allocate block of consequtive IRQs, returns a number of the first */ -int spapr_allocate_irq_block(int num, enum xics_irq_type type) +int spapr_allocate_irq_block(int num, bool lsi) { int first = -1; int i; @@ -119,7 +119,7 @@ int spapr_allocate_irq_block(int num, enum xics_irq_type type) for (i = 0; i < num; ++i) { int irq; - irq = spapr_allocate_irq(0, type); + irq = spapr_allocate_irq(0, lsi); if (!irq) { return -1; } diff --git a/hw/spapr.h b/hw/spapr.h index f9a7b0fa33..51a966b1e9 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -291,17 +291,17 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn); target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode, target_ulong *args); -int spapr_allocate_irq(int hint, enum xics_irq_type type); -int spapr_allocate_irq_block(int num, enum xics_irq_type type); +int spapr_allocate_irq(int hint, bool lsi); +int spapr_allocate_irq_block(int num, bool lsi); static inline int spapr_allocate_msi(int hint) { - return spapr_allocate_irq(hint, XICS_MSI); + return spapr_allocate_irq(hint, false); } static inline int spapr_allocate_lsi(int hint) { - return spapr_allocate_irq(hint, XICS_LSI); + return spapr_allocate_irq(hint, true); } static inline uint32_t rtas_ld(target_ulong phys, int n) diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 203155e32b..b628f89a02 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -351,7 +351,7 @@ static void rtas_ibm_change_msi(sPAPREnvironment *spapr, /* There is no cached config, allocate MSIs */ if (!phb->msi_table[ndev].nvec) { - irq = spapr_allocate_irq_block(req_num, XICS_MSI); + irq = spapr_allocate_irq_block(req_num, true); if (irq < 0) { fprintf(stderr, "Cannot allocate MSIs for device#%d", ndev); rtas_st(rets, 0, -1); /* Hardware error */ diff --git a/hw/xics.c b/hw/xics.c index 648af2538d..75c8cca41d 100644 --- a/hw/xics.c +++ b/hw/xics.c @@ -170,7 +170,7 @@ struct ics_irq_state { #define XICS_STATUS_REJECTED 0x4 #define XICS_STATUS_MASKED_PENDING 0x8 uint8_t status; - enum xics_irq_type type; + bool lsi; }; struct ics_state { @@ -244,7 +244,7 @@ static void ics_set_irq(void *opaque, int srcno, int val) struct ics_state *ics = (struct ics_state *)opaque; struct ics_irq_state *irq = ics->irqs + srcno; - if (irq->type == XICS_LSI) { + if (irq->lsi) { set_irq_lsi(ics, srcno, val); } else { set_irq_msi(ics, srcno, val); @@ -278,7 +278,7 @@ static void ics_write_xive(struct ics_state *ics, int nr, int server, irq->server = server; irq->priority = priority; - if (irq->type == XICS_LSI) { + if (irq->lsi) { write_xive_lsi(ics, srcno); } else { write_xive_msi(ics, srcno); @@ -301,7 +301,7 @@ static void ics_resend(struct ics_state *ics) struct ics_irq_state *irq = ics->irqs + i; /* FIXME: filter by server#? */ - if (irq->type == XICS_LSI) { + if (irq->lsi) { resend_lsi(ics, i); } else { resend_msi(ics, i); @@ -314,7 +314,7 @@ static void ics_eoi(struct ics_state *ics, int nr) int srcno = nr - ics->offset; struct ics_irq_state *irq = ics->irqs + srcno; - if (irq->type == XICS_LSI) { + if (irq->lsi) { irq->status &= ~XICS_STATUS_SENT; } } @@ -333,14 +333,12 @@ qemu_irq xics_get_qirq(struct icp_state *icp, int irq) return icp->ics->qirqs[irq - icp->ics->offset]; } -void xics_set_irq_type(struct icp_state *icp, int irq, - enum xics_irq_type type) +void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi) { assert((irq >= icp->ics->offset) && (irq < (icp->ics->offset + icp->ics->nr_irqs))); - assert((type == XICS_MSI) || (type == XICS_LSI)); - icp->ics->irqs[irq - icp->ics->offset].type = type; + icp->ics->irqs[irq - icp->ics->offset].lsi = lsi; } static target_ulong h_cppr(CPUPPCState *env, sPAPREnvironment *spapr, diff --git a/hw/xics.h b/hw/xics.h index 99b96ac85a..6817268697 100644 --- a/hw/xics.h +++ b/hw/xics.h @@ -31,14 +31,8 @@ struct icp_state; -enum xics_irq_type { - XICS_MSI, /* Message-signalled (edge) interrupt */ - XICS_LSI, /* Level-signalled interrupt */ -}; - qemu_irq xics_get_qirq(struct icp_state *icp, int irq); -void xics_set_irq_type(struct icp_state *icp, int irq, - enum xics_irq_type type); +void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi); struct icp_state *xics_system_init(int nr_irqs); From 490d4a2b6edafb27cd688ded7fdb1290453d71b0 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Sep 2012 16:57:19 +0000 Subject: [PATCH 0701/2270] pseries: Remove never used flags field from spapr vio devices The general device state structure for PAPR VIO emulated devices includes a 'flags' field which was never used. This patch removes it. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_vio.h | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h index ea6aa43e26..acef65efd3 100644 --- a/hw/spapr_vio.h +++ b/hw/spapr_vio.h @@ -60,7 +60,6 @@ typedef struct VIOsPAPRDeviceClass { struct VIOsPAPRDevice { DeviceState qdev; uint32_t reg; - uint32_t flags; uint32_t irq; target_ulong signal_state; VIOsPAPR_CRQ crq; From 53724ee565565f69560dbe17553bede8c0169379 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Sep 2012 16:57:20 +0000 Subject: [PATCH 0702/2270] pseries: Rework implementation of TCE bypass On the pseries machine the IOMMU (aka TCE tables) is always active for all PCI and VIO devices. Mostly to simplify the SLOF firmware, we implement an extension which allows the IOMMU to be temporarily disabled for certain devices. Currently this is implemented by setting the device's DMAContext pointer to NULL (thus reverting to qemu's default no-IOMMU DMA behaviour), then replacing it when bypass mode is disabled. This approach causes a bunch of complications though. It complexifies the management of the DMAContext lifetimes, it's problematic for savevm/loadvm, and it means that while bypass is active we have nowhere to store the device's LIOBN (Logical IO Bus Number, used to identify DMA address spaces). At present we regenerate the LIOBN from other address information but this restricts how we can allocate LIOBNs. This patch gives up on this approach, replacing it with the much simpler one of having a 'bypass' boolean flag in the TCE state structure. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.h | 1 + hw/spapr_iommu.c | 25 +++++++++++++++++++------ hw/spapr_vio.c | 26 ++++++++++---------------- hw/spapr_vio.h | 1 - 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/hw/spapr.h b/hw/spapr.h index 51a966b1e9..e984e3fc3c 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -339,6 +339,7 @@ void spapr_iommu_init(void); DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size); void spapr_tce_free(DMAContext *dma); void spapr_tce_reset(DMAContext *dma); +void spapr_tce_set_bypass(DMAContext *dma, bool bypass); int spapr_dma_dt(void *fdt, int node_off, const char *propname, uint32_t liobn, uint64_t window, uint32_t size); int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname, diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c index 216aa06809..38034c07bd 100644 --- a/hw/spapr_iommu.c +++ b/hw/spapr_iommu.c @@ -42,6 +42,7 @@ struct sPAPRTCETable { uint32_t liobn; uint32_t window_size; sPAPRTCE *table; + bool bypass; int fd; QLIST_ENTRY(sPAPRTCETable) list; }; @@ -78,6 +79,12 @@ static int spapr_tce_translate(DMAContext *dma, DMA_ADDR_FMT "\n", tcet->liobn, addr); #endif + if (tcet->bypass) { + *paddr = addr; + *len = (target_phys_addr_t)-1; + return 0; + } + /* Check if we are in bound */ if (addr >= tcet->window_size) { #ifdef DEBUG_TCE @@ -162,15 +169,21 @@ void spapr_tce_free(DMAContext *dma) } } +void spapr_tce_set_bypass(DMAContext *dma, bool bypass) +{ + sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma); + + tcet->bypass = bypass; +} + void spapr_tce_reset(DMAContext *dma) { - if (dma) { - sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma); - size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT) - * sizeof(sPAPRTCE); + sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma); + size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT) + * sizeof(sPAPRTCE); - memset(tcet->table, 0, table_size); - } + tcet->bypass = false; + memset(tcet->table, 0, table_size); } static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba, diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index 752836e76c..848806d3f1 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -316,14 +316,9 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq) static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev) { - VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev); - uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg; - if (dev->dma) { - spapr_tce_free(dev->dma); + spapr_tce_reset(dev->dma); } - dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size); - free_crq(dev); } @@ -346,16 +341,14 @@ static void rtas_set_tce_bypass(sPAPREnvironment *spapr, uint32_t token, rtas_st(rets, 0, -3); return; } - if (enable) { - spapr_tce_free(dev->dma); - dev->dma = NULL; - } else { - VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev); - uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg; - dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size); + if (!dev->dma) { + rtas_st(rets, 0, -3); + return; } + spapr_tce_set_bypass(dev->dma, !!enable); + rtas_st(rets, 0, 0); } @@ -421,7 +414,6 @@ static int spapr_vio_busdev_init(DeviceState *qdev) { VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev; VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev); - uint32_t liobn; char *id; if (dev->reg != -1) { @@ -463,8 +455,10 @@ static int spapr_vio_busdev_init(DeviceState *qdev) return -1; } - liobn = SPAPR_VIO_BASE_LIOBN | dev->reg; - dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size); + if (pc->rtce_window_size) { + uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg; + dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size); + } return pc->init(dev); } diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h index acef65efd3..cc85d26101 100644 --- a/hw/spapr_vio.h +++ b/hw/spapr_vio.h @@ -131,7 +131,6 @@ void spapr_vscsi_create(VIOsPAPRBus *bus); VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus); -int spapr_tce_set_bypass(uint32_t unit, uint32_t enable); void spapr_vio_quiesce(void); #endif /* _HW_SPAPR_VIO_H */ From 3fe719f467530b7c8ac0797881ff4b66d1357c18 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Sep 2012 16:57:21 +0000 Subject: [PATCH 0703/2270] pseries: Fix semantics of RTAS int-on, int-off and set-xive functions Currently the ibm,int-on and ibm,int-off RTAS functions are implemented as no-ops. This is because when implemented as specified in PAPR they caused Linux (which calls both int-on/off and set-xive) to end up with interrupts masked when they should not be. Since Linux's set-xive calls make the int-on/off calls redundant, making them nops worked around the problem. In fact, the problem was caused because there was a subtle bug in set-xive, PAPR specifies that as well as updating the current priority, it also needs to update the saved priority used by int-on/off. With this bug fixed the problem goes away. This patch implements this more correct fix. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/xics.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/hw/xics.c b/hw/xics.c index 75c8cca41d..ce88aa750b 100644 --- a/hw/xics.c +++ b/hw/xics.c @@ -270,13 +270,14 @@ static void write_xive_lsi(struct ics_state *ics, int srcno) } static void ics_write_xive(struct ics_state *ics, int nr, int server, - uint8_t priority) + uint8_t priority, uint8_t saved_priority) { int srcno = nr - ics->offset; struct ics_irq_state *irq = ics->irqs + srcno; irq->server = server; irq->priority = priority; + irq->saved_priority = saved_priority; if (irq->lsi) { write_xive_lsi(ics, srcno); @@ -405,7 +406,7 @@ static void rtas_set_xive(sPAPREnvironment *spapr, uint32_t token, return; } - ics_write_xive(ics, nr, server, priority); + ics_write_xive(ics, nr, server, priority, priority); rtas_st(rets, 0, 0); /* Success */ } @@ -453,14 +454,8 @@ static void rtas_int_off(sPAPREnvironment *spapr, uint32_t token, return; } - /* This is a NOP for now, since the described PAPR semantics don't - * seem to gel with what Linux does */ -#if 0 - struct ics_irq_state *irq = xics->irqs + (nr - xics->offset); - - irq->saved_priority = irq->priority; - ics_write_xive_msi(xics, nr, irq->server, 0xff); -#endif + ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff, + ics->irqs[nr - ics->offset].priority); rtas_st(rets, 0, 0); /* Success */ } @@ -484,13 +479,9 @@ static void rtas_int_on(sPAPREnvironment *spapr, uint32_t token, return; } - /* This is a NOP for now, since the described PAPR semantics don't - * seem to gel with what Linux does */ -#if 0 - struct ics_irq_state *irq = xics->irqs + (nr - xics->offset); - - ics_write_xive_msi(xics, nr, irq->server, irq->saved_priority); -#endif + ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, + ics->irqs[nr - ics->offset].saved_priority, + ics->irqs[nr - ics->offset].saved_priority); rtas_st(rets, 0, 0); /* Success */ } From ace9a2cbac9b2949aadc176ffa83a1d2a0873e2c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 19 Sep 2012 21:08:42 +0000 Subject: [PATCH 0704/2270] target-ppc: KVM: Fix some kernel version edge cases for kvmppc_reset_htab() The kvmppc_reset_htab() function invokes the KVM_PPC_ALLOCATE_HTAB vm ioctl to request KVM to allocate and reset a hash page table for the guest - it returns the size of hash table allocated, or 0 to indicate that qemu needs to allocate the hash table itself. In practice qemu needs to allocate the htab for full emulation and with Book3sPR KVM, but the kernel has to allocate it for Book3sHV KVM (the hash table needs to be physically contiguous in that case). Unfortunately, the logic in this function is incorrect for some existing kernels. Specifically: * at least some PR KVM versions advertise the relevant capability but don't actually implement the ioctl(), returning ENOTTY. * For old kernels which don't have the capability, we currently return 0. This is correct for PV KVM, where we need to allocate the htab, but not for HV KVM - kernels of this era always allocate a 16MB hash table per guest. This patch corrects both of these edge cases. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- target-ppc/kvm.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 546c11604c..1975323eb7 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -1127,18 +1127,38 @@ int kvmppc_reset_htab(int shift_hint) { uint32_t shift = shift_hint; - if (kvm_enabled() && - kvm_check_extension(kvm_state, KVM_CAP_PPC_ALLOC_HTAB)) { + if (!kvm_enabled()) { + /* Full emulation, tell caller to allocate htab itself */ + return 0; + } + if (kvm_check_extension(kvm_state, KVM_CAP_PPC_ALLOC_HTAB)) { int ret; ret = kvm_vm_ioctl(kvm_state, KVM_PPC_ALLOCATE_HTAB, &shift); - if (ret < 0) { + if (ret == -ENOTTY) { + /* At least some versions of PR KVM advertise the + * capability, but don't implement the ioctl(). Oops. + * Return 0 so that we allocate the htab in qemu, as is + * correct for PR. */ + return 0; + } else if (ret < 0) { return ret; } return shift; } - /* For now.. */ - return 0; + /* We have a kernel that predates the htab reset calls. For PR + * KVM, we need to allocate the htab ourselves, for an HV KVM of + * this era, it has allocated a 16MB fixed size hash table + * already. Kernels of this era have the GET_PVINFO capability + * only on PR, so we use this hack to determine the right + * answer */ + if (kvm_check_extension(kvm_state, KVM_CAP_PPC_GET_PVINFO)) { + /* PR - tell caller to allocate htab */ + return 0; + } else { + /* HV - assume 16MB kernel allocated htab */ + return 24; + } } static inline uint32_t mfpvr(void) From 5a1972c8472fafd519a68b689fdcaf33ec857945 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 31 Aug 2012 22:21:21 +0200 Subject: [PATCH 0705/2270] ppc405_uc: Fix buffer overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Report from smatch: ppc405_uc.c:209 dcr_read_pob(12) error: buffer overflow 'pob->besr' 2 <= 2 ppc405_uc.c:232 dcr_write_pob(12) error: buffer overflow 'pob->besr' 2 <= 2 The old code reads and writes besr[POB0_BESR1 - POB0_BESR0] or besr[2] which is one too much. Signed-off-by: Stefan Weil Reviewed-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/ppc405_uc.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c index 89e5013b57..b52ab2f179 100644 --- a/hw/ppc405_uc.c +++ b/hw/ppc405_uc.c @@ -191,7 +191,8 @@ enum { typedef struct ppc4xx_pob_t ppc4xx_pob_t; struct ppc4xx_pob_t { uint32_t bear; - uint32_t besr[2]; + uint32_t besr0; + uint32_t besr1; }; static uint32_t dcr_read_pob (void *opaque, int dcrn) @@ -205,8 +206,10 @@ static uint32_t dcr_read_pob (void *opaque, int dcrn) ret = pob->bear; break; case POB0_BESR0: + ret = pob->besr0; + break; case POB0_BESR1: - ret = pob->besr[dcrn - POB0_BESR0]; + ret = pob->besr1; break; default: /* Avoid gcc warning */ @@ -227,9 +230,12 @@ static void dcr_write_pob (void *opaque, int dcrn, uint32_t val) /* Read only */ break; case POB0_BESR0: + /* Write-clear */ + pob->besr0 &= ~val; + break; case POB0_BESR1: /* Write-clear */ - pob->besr[dcrn - POB0_BESR0] &= ~val; + pob->besr1 &= ~val; break; } } @@ -241,8 +247,8 @@ static void ppc4xx_pob_reset (void *opaque) pob = opaque; /* No error */ pob->bear = 0x00000000; - pob->besr[0] = 0x0000000; - pob->besr[1] = 0x0000000; + pob->besr0 = 0x0000000; + pob->besr1 = 0x0000000; } static void ppc4xx_pob_init(CPUPPCState *env) From 35f9304d925a5423c51bd2c83a81fa3cc2b6e680 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 20 Sep 2012 17:42:30 +0000 Subject: [PATCH 0706/2270] pseries: Remove unnecessary locking from PAPR hash table hcalls In the paravirtualized environment provided by PAPR, there is a standard locking scheme so that hypercalls updating the hash page table from different guest threads don't corrupt the haah table state. We implement this HVLOCK bit in out page table hypercalls. However, it is not necessary in our case, since the hypercalls all run in the qemu environment under the big qemu lock. Therefore, this patch removes the locking code. This has the additional advantage of freeing up a hash PTE bit which will be useful for migration support. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_hcall.c | 42 ++++-------------------------------------- 1 file changed, 4 insertions(+), 38 deletions(-) diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c index 2df94d197a..826ca673fc 100644 --- a/hw/spapr_hcall.c +++ b/hw/spapr_hcall.c @@ -39,22 +39,6 @@ #define HPTE_V_1TB_SEG 0x4000000000000000ULL #define HPTE_V_VRMA_MASK 0x4001ffffff000000ULL -#define HPTE_V_HVLOCK 0x40ULL - -static inline int lock_hpte(void *hpte, target_ulong bits) -{ - uint64_t pteh; - - pteh = ldq_p(hpte); - - /* We're protected by qemu's global lock here */ - if (pteh & bits) { - return 0; - } - stq_p(hpte, pteh | HPTE_V_HVLOCK); - return 1; -} - static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r, target_ulong pte_index) { @@ -151,8 +135,7 @@ static target_ulong h_enter(CPUPPCState *env, sPAPREnvironment *spapr, if (i == 8) { return H_PTEG_FULL; } - if (((ldq_p(hpte) & HPTE_V_VALID) == 0) && - lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID)) { + if ((ldq_p(hpte) & HPTE_V_VALID) == 0) { break; } hpte += HASH_PTE_SIZE_64; @@ -160,7 +143,7 @@ static target_ulong h_enter(CPUPPCState *env, sPAPREnvironment *spapr, } else { i = 0; hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64); - if (!lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID)) { + if (ldq_p(hpte) & HPTE_V_VALID) { return H_PTEG_FULL; } } @@ -168,7 +151,6 @@ static target_ulong h_enter(CPUPPCState *env, sPAPREnvironment *spapr, /* eieio(); FIXME: need some sort of barrier for smp? */ stq_p(hpte, pteh); - assert(!(ldq_p(hpte) & HPTE_V_HVLOCK)); args[0] = pte_index + i; return H_SUCCESS; } @@ -193,11 +175,6 @@ static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex, } hpte = env->external_htab + (ptex * HASH_PTE_SIZE_64); - while (!lock_hpte(hpte, HPTE_V_HVLOCK)) { - /* We have no real concurrency in qemu soft-emulation, so we - * will never actually have a contested lock */ - assert(0); - } v = ldq_p(hpte); r = ldq_p(hpte + (HASH_PTE_SIZE_64/2)); @@ -205,16 +182,13 @@ static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex, if ((v & HPTE_V_VALID) == 0 || ((flags & H_AVPN) && (v & ~0x7fULL) != avpn) || ((flags & H_ANDCOND) && (v & avpn) != 0)) { - stq_p(hpte, v & ~HPTE_V_HVLOCK); - assert(!(ldq_p(hpte) & HPTE_V_HVLOCK)); return REMOVE_NOT_FOUND; } - *vp = v & ~HPTE_V_HVLOCK; + *vp = v; *rp = r; stq_p(hpte, 0); rb = compute_tlbie_rb(v, r, ptex); ppc_tlb_invalidate_one(env, rb); - assert(!(ldq_p(hpte) & HPTE_V_HVLOCK)); return REMOVE_SUCCESS; } @@ -324,19 +298,12 @@ static target_ulong h_protect(CPUPPCState *env, sPAPREnvironment *spapr, } hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64); - while (!lock_hpte(hpte, HPTE_V_HVLOCK)) { - /* We have no real concurrency in qemu soft-emulation, so we - * will never actually have a contested lock */ - assert(0); - } v = ldq_p(hpte); r = ldq_p(hpte + (HASH_PTE_SIZE_64/2)); if ((v & HPTE_V_VALID) == 0 || ((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) { - stq_p(hpte, v & ~HPTE_V_HVLOCK); - assert(!(ldq_p(hpte) & HPTE_V_HVLOCK)); return H_NOT_FOUND; } @@ -350,8 +317,7 @@ static target_ulong h_protect(CPUPPCState *env, sPAPREnvironment *spapr, ppc_tlb_invalidate_one(env, rb); stq_p(hpte + (HASH_PTE_SIZE_64/2), r); /* Don't need a memory barrier, due to qemu's global lock */ - stq_p(hpte, v & ~HPTE_V_HVLOCK); - assert(!(ldq_p(hpte) & HPTE_V_HVLOCK)); + stq_p(hpte, v); return H_SUCCESS; } From 382be75df77142cf6bdc7f5852738029eeb9e23a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 20 Sep 2012 17:42:27 +0000 Subject: [PATCH 0707/2270] pseries: Set hash table size based on RAM size Currently the pseries machine code always attempts to set the size of the guests's hash page table to 16MB. However, because of the way the POWER MMU works, a suitable hash page table size should really depend on memory size. 16MB will be excessive for guests with <1GB and RAM, and may not be enough for guests with >2GB of RAM (depending on guest page size and other factors). The usual given rule of thumb is that the hash table should be 1/64 of the size of memory, but in fact the Linux guests we are aiming at don't really need that much. This patch, therefore, changes the hash table allocation code to aim for 1/128 of the size of RAM (rounding up). When using KVM, this size may still be adjusted by the host kernel if it is unable to allocate a suitable (contiguous) table. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 1177efaa98..a8bd3c1ae6 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -725,9 +725,16 @@ static void ppc_spapr_init(ram_addr_t ram_size, spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE; load_limit = spapr->fdt_addr - FW_OVERHEAD; - /* For now, always aim for a 16MB hash table */ - /* FIXME: we should change this default based on RAM size */ - spapr->htab_shift = 24; + /* We aim for a hash table of size 1/128 the size of RAM. The + * normal rule of thumb is 1/64 the size of RAM, but that's much + * more than needed for the Linux guests we support. */ + spapr->htab_shift = 18; /* Minimum architected size */ + while (spapr->htab_shift <= 46) { + if ((1ULL << (spapr->htab_shift + 7)) >= ram_size) { + break; + } + spapr->htab_shift++; + } /* init CPUs */ if (cpu_model == NULL) { From 011aba24ed73000e126dd1bb90a6bea2afd91649 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 20 Sep 2012 17:42:28 +0000 Subject: [PATCH 0708/2270] target-ppc: Remove unused power_mode field from cpu state CPUPPCState includes a variable 'power_mode' which is used nowhere. This patch removes it. This includes saving a dummy zero in its place during vmsave, to avoid breaking the save format. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- target-ppc/cpu.h | 1 - target-ppc/machine.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index ca2fc2198e..faf4404078 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1079,7 +1079,6 @@ struct CPUPPCState { int mmu_idx; /* precomputed MMU index to speed up mem accesses */ /* Power management */ - int power_mode; int (*check_pow)(CPUPPCState *env); #if !defined(CONFIG_USER_ONLY) diff --git a/target-ppc/machine.c b/target-ppc/machine.c index d6c2ee41b3..21ce7575e3 100644 --- a/target-ppc/machine.c +++ b/target-ppc/machine.c @@ -82,7 +82,7 @@ void cpu_save(QEMUFile *f, void *opaque) qemu_put_betls(f, &env->hflags); qemu_put_betls(f, &env->hflags_nmsr); qemu_put_sbe32s(f, &env->mmu_idx); - qemu_put_sbe32s(f, &env->power_mode); + qemu_put_sbe32(f, 0); } int cpu_load(QEMUFile *f, void *opaque, int version_id) @@ -167,7 +167,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) qemu_get_betls(f, &env->hflags); qemu_get_betls(f, &env->hflags_nmsr); qemu_get_sbe32s(f, &env->mmu_idx); - qemu_get_sbe32s(f, &env->power_mode); + qemu_get_sbe32(f); /* Discard unused power_mode */ return 0; } From 711934334eb3895a89c555c1f57eb3d84ddb2906 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sun, 23 Sep 2012 08:37:59 +0200 Subject: [PATCH 0709/2270] fdt: move dumpdtb interpretation code to device_tree.c The dumpdtb code can be useful in more places than just for e500. Move it to a generic place. Signed-off-by: Alexander Graf --- device_tree.c | 22 ++++++++++++++++++++++ device_tree.h | 2 ++ hw/ppc/e500.c | 15 +-------------- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/device_tree.c b/device_tree.c index d7a9b6bb89..69ca953b4a 100644 --- a/device_tree.c +++ b/device_tree.c @@ -304,3 +304,25 @@ int qemu_devtree_add_subnode(void *fdt, const char *name) g_free(dupname); return retval; } + +void qemu_devtree_dumpdtb(void *fdt, int size) +{ + QemuOpts *machine_opts; + + machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); + if (machine_opts) { + const char *dumpdtb = qemu_opt_get(machine_opts, "dumpdtb"); + if (dumpdtb) { + /* Dump the dtb to a file and quit */ + FILE *f = fopen(dumpdtb, "wb"); + size_t len; + len = fwrite(fdt, size, 1, f); + fclose(f); + if (len != size) { + exit(1); + } + exit(0); + } + } + +} diff --git a/device_tree.h b/device_tree.h index f7a3e6cfc5..f0b3f35e03 100644 --- a/device_tree.h +++ b/device_tree.h @@ -49,4 +49,6 @@ int qemu_devtree_add_subnode(void *fdt, const char *name); sizeof(qdt_tmp)); \ } while (0) +void qemu_devtree_dumpdtb(void *fdt, int size); + #endif /* __DEVICE_TREE_H__ */ diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 6f0de6d959..5bab340475 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -139,12 +139,10 @@ static int ppce500_load_device_tree(CPUPPCState *env, 0x0, 0x10000, }; QemuOpts *machine_opts; - const char *dumpdtb = NULL; const char *dtb_file = NULL; machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); if (machine_opts) { - dumpdtb = qemu_opt_get(machine_opts, "dumpdtb"); dtb_file = qemu_opt_get(machine_opts, "dtb"); toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); } @@ -334,18 +332,7 @@ static int ppce500_load_device_tree(CPUPPCState *env, } done: - if (dumpdtb) { - /* Dump the dtb to a file and quit */ - FILE *f = fopen(dumpdtb, "wb"); - size_t len; - len = fwrite(fdt, fdt_size, 1, f); - fclose(f); - if (len != fdt_size) { - exit(1); - } - exit(0); - } - + qemu_devtree_dumpdtb(fdt, fdt_size); ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); if (ret < 0) { goto out; From 6641b77254d3c191ecee5a87947425f623ac9ca0 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sun, 23 Sep 2012 23:27:37 +0200 Subject: [PATCH 0710/2270] device tree: simplify dumpdtb code As per Peter's suggestion, we can use glib to write out a buffer in whole to a file, simplifying the code dramatically. Signed-off-by: Alexander Graf --- device_tree.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/device_tree.c b/device_tree.c index 69ca953b4a..a9236133c7 100644 --- a/device_tree.c +++ b/device_tree.c @@ -314,14 +314,7 @@ void qemu_devtree_dumpdtb(void *fdt, int size) const char *dumpdtb = qemu_opt_get(machine_opts, "dumpdtb"); if (dumpdtb) { /* Dump the dtb to a file and quit */ - FILE *f = fopen(dumpdtb, "wb"); - size_t len; - len = fwrite(fdt, size, 1, f); - fclose(f); - if (len != size) { - exit(1); - } - exit(0); + exit(g_file_set_contents(dumpdtb, fdt, size, NULL) ? 0 : 1); } } From 9dd5eba1bc69bccbd83885d157d84e2514799a22 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Wed, 22 Aug 2012 14:55:40 +0000 Subject: [PATCH 0711/2270] PPC: e500: increase DTC_LOAD_PAD An allowance of 5 MiB for BSS is not enough for Linux kernels with certain debug options enabled (not sure exactly which one caused it, but I'd guess lockdep). The kernel I ran into this with had a BSS of around 6.4 MB. Unfortunately, uImage does not give us enough information to determine the actual BSS size. Increase the allowance to 18 MiB to give us plenty of room. Eventually this should be more intelligent, possibly packing initrd+dtb at the end of guest RAM. Signed-off-by: Scott Wood Signed-off-by: Alexander Graf --- hw/ppc/e500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 5bab340475..fc3fde0b66 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -36,7 +36,7 @@ #define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb" #define UIMAGE_LOAD_BASE 0 -#define DTC_LOAD_PAD 0x500000 +#define DTC_LOAD_PAD 0x1800000 #define DTC_PAD_MASK 0xFFFFF #define INITRD_LOAD_PAD 0x2000000 #define INITRD_PAD_MASK 0xFFFFFF From 7e7ec2d290ca5b1bdd555da9852dc5ee60232fe5 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Wed, 22 Aug 2012 14:55:41 +0000 Subject: [PATCH 0712/2270] PPC: e500: calculate initrd_base like dt_base While investigating dtb pad issues, I noticed that initrd_base wasn't taking loadaddr into account the way dt_base was. This seems wrong. Signed-off-by: Scott Wood Signed-off-by: Alexander Graf --- hw/ppc/e500.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index fc3fde0b66..feb712e5a9 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -540,7 +540,8 @@ void ppce500_init(PPCE500Params *params) /* Load initrd. */ if (params->initrd_filename) { - initrd_base = (kernel_size + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK; + initrd_base = (loadaddr + kernel_size + INITRD_LOAD_PAD) & + ~INITRD_PAD_MASK; initrd_size = load_image_targphys(params->initrd_filename, initrd_base, ram_size - initrd_base); From efcb9383b974114e5f682e531346006f8f2466c0 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 25 Sep 2012 17:12:20 +0000 Subject: [PATCH 0713/2270] pseries: Don't test for MSR_PR for hypercalls under KVM PAPR hypercalls should only be invoked from the guest kernel, not guest user programs, that is, with MSR[PR]=0. Currently we check this in spapr_hypercall, returning H_PRIVILEGE if MSR[PR]=1. However, under KVM the state of MSR[PR] is already checked by the host kernel before passing the hypercall to qemu, making this check redundant. Worse, however, we don't generally synchronize KVM and qemu state on the hypercall path, meaning that qemu could incorrectly reject a hypercall because it has a stale MSR value. This patch fixes the problem by moving the privilege test exclusively to the TCG hypercall path. Signed-off-by: David Gibson CC: qemu-stable@nongnu.org Signed-off-by: Alexander Graf --- hw/spapr.c | 7 ++++++- hw/spapr_hcall.c | 5 ----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index a8bd3c1ae6..ab227a0093 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -573,7 +573,12 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr) static void emulate_spapr_hypercall(CPUPPCState *env) { - env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]); + if (msr_pr) { + hcall_dprintf("Hypercall made with MSR[PR]=1\n"); + env->gpr[3] = H_PRIVILEGE; + } else { + env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]); + } } static void spapr_reset_htab(sPAPREnvironment *spapr) diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c index 826ca673fc..194d9c24b5 100644 --- a/hw/spapr_hcall.c +++ b/hw/spapr_hcall.c @@ -681,11 +681,6 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn) target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode, target_ulong *args) { - if (msr_pr) { - hcall_dprintf("Hypercall made with MSR[PR]=1\n"); - return H_PRIVILEGE; - } - if ((opcode <= MAX_HCALL_OPCODE) && ((opcode & 0x3) == 0)) { spapr_hcall_fn fn = papr_hypercall_table[opcode / 4]; From 2b15811c8cd4dbe8dcde32320936fe74e51e4279 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 25 Sep 2012 17:12:21 +0000 Subject: [PATCH 0714/2270] ppc/pseries: Reset VPA registration on CPU reset The ppc specific CPU state contains several variables which track the VPA, SLB shadow and dispatch trace log. These are structures shared between OS and hypervisor that are used on the pseries machine to track various per-CPU quantities. The address of these structures needs to be registered by the guest on each boot, however currently this registration is not cleared when we reset the cpu. This patch corrects this bug. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- target-ppc/translate_init.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index fba2b42427..a972287035 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -10423,6 +10423,14 @@ static void ppc_cpu_reset(CPUState *s) env->pending_interrupts = 0; env->exception_index = POWERPC_EXCP_NONE; env->error_code = 0; + +#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) + env->vpa = 0; + env->slb_shadow = 0; + env->dispatch_trace_log = 0; + env->dtl_size = 0; +#endif /* TARGET_PPC64 */ + /* Flush all TLBs */ tlb_flush(env, 1); } From fb37c3029c5a695e367baaacc6baf17640cc63cc Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 4 Oct 2012 18:52:21 +0200 Subject: [PATCH 0715/2270] PPC: e500: Only expose even TLB sizes in initial TLB When booting our e500 machine, we automatically generate a big TLB entry in TLB1 that covers all of the code we need to run in there until the guest can handle its TLB on its own. However, e500v2 can only handle MAS1.0 sizes. However, we keep our TLB information in MAS2.0 layout, which means we have twice as many TLB sizes to choose from. That also means we can run into a situation where we try to add a TLB size that could not fit into the MAS1.0 size bits. Fix it by making sure we always have the lower bit set to 0. That way we are always guaranteed to have MAS1.0 compatible TLB size information. Signed-off-by: Alexander Graf --- hw/ppc/e500.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index feb712e5a9..d23f9b2f60 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -362,6 +362,10 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env) the device tree top */ dt_end = bi->dt_base + bi->dt_size; ps = booke206_page_size_to_tlb(dt_end) + 1; + if (ps & 1) { + /* e500v2 can only do even TLB size bits */ + ps++; + } size = (ps << MAS1_TSIZE_SHIFT); tlb->mas1 = MAS1_VALID | size; tlb->mas2 = 0; From 4be403c8158e1b6be743f0fef004310cea4e3975 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 4 Oct 2012 12:36:04 +0200 Subject: [PATCH 0716/2270] Make target_phys_addr_t 64 bits unconditionally The hassle and compile time overhead of maintaining both 32-bit and 64-bit capable source isn't worth the tiny performance advantage which is seen on a minority of configurations. Switch to compiling libhw only once, with target_phys_addr_t unconditionally typedefed to uint64_t. Signed-off-by: Avi Kivity Signed-off-by: Anthony Liguori --- .gitignore | 1 + Makefile | 2 +- Makefile.hw | 1 - Makefile.target | 3 --- configure | 34 ++++------------------------------ cpu-common.h | 2 +- dma.h | 2 +- hw/hw.h | 2 +- hw/intel-hda.c | 8 +------- hw/rtl8139.c | 6 +----- monitor.c | 4 ---- target-ppc/mmu_helper.c | 4 +--- targphys.h | 19 +------------------ 13 files changed, 13 insertions(+), 75 deletions(-) diff --git a/.gitignore b/.gitignore index 824c0d24df..3ef77d0622 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ trace-dtrace.dtrace *-linux-user *-bsd-user libdis* +libhw libhw32 libhw64 libuser diff --git a/Makefile b/Makefile index 04642975af..1cebe3a9db 100644 --- a/Makefile +++ b/Makefile @@ -214,7 +214,7 @@ $(qga-obj-y) qemu-ga.o: $(QGALIB_GEN) qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(tools-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y) -QEMULIBS=libhw32 libhw64 libuser libdis libdis-user +QEMULIBS=libhw libuser libdis libdis-user clean: # avoid old build problems by removing potentially incorrect old files diff --git a/Makefile.hw b/Makefile.hw index 59f5b48350..86f0bf40f4 100644 --- a/Makefile.hw +++ b/Makefile.hw @@ -2,7 +2,6 @@ include ../config-host.mak include ../config-all-devices.mak -include config.mak include $(SRC_PATH)/rules.mak .PHONY: all diff --git a/Makefile.target b/Makefile.target index d9d54b8dd0..4449444a0e 100644 --- a/Makefile.target +++ b/Makefile.target @@ -4,9 +4,6 @@ include ../config-host.mak include config-devices.mak include config-target.mak include $(SRC_PATH)/rules.mak -ifneq ($(HWDIR),) -include $(HWDIR)/config.mak -endif $(call set-vpath, $(SRC_PATH)) ifdef CONFIG_LINUX diff --git a/configure b/configure index 8f99b7b941..65bd876cd7 100755 --- a/configure +++ b/configure @@ -3694,7 +3694,6 @@ TARGET_ABI_DIR="" case "$target_arch2" in i386) - target_phys_bits=64 ;; x86_64) TARGET_BASE_ARCH=i386 @@ -3702,7 +3701,6 @@ case "$target_arch2" in target_long_alignment=8 ;; alpha) - target_phys_bits=64 target_long_alignment=8 target_nptl="yes" ;; @@ -3711,22 +3709,18 @@ case "$target_arch2" in bflt="yes" target_nptl="yes" gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml" - target_phys_bits=64 target_llong_alignment=4 target_libs_softmmu="$fdt_libs" ;; cris) target_nptl="yes" - target_phys_bits=32 ;; lm32) - target_phys_bits=32 target_libs_softmmu="$opengl_libs" ;; m68k) bflt="yes" gdb_xml_files="cf-core.xml cf-fp.xml" - target_phys_bits=32 target_int_alignment=2 target_long_alignment=2 target_llong_alignment=2 @@ -3735,36 +3729,30 @@ case "$target_arch2" in TARGET_ARCH=microblaze bflt="yes" target_nptl="yes" - target_phys_bits=32 target_libs_softmmu="$fdt_libs" ;; mips|mipsel) TARGET_ARCH=mips echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak target_nptl="yes" - target_phys_bits=64 ;; mipsn32|mipsn32el) TARGET_ARCH=mipsn32 TARGET_BASE_ARCH=mips echo "TARGET_ABI_MIPSN32=y" >> $config_target_mak - target_phys_bits=64 ;; mips64|mips64el) TARGET_ARCH=mips64 TARGET_BASE_ARCH=mips echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak - target_phys_bits=64 target_long_alignment=8 ;; or32) TARGET_ARCH=openrisc TARGET_BASE_ARCH=openrisc - target_phys_bits=32 ;; ppc) gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml" - target_phys_bits=64 target_nptl="yes" target_libs_softmmu="$fdt_libs" ;; @@ -3772,7 +3760,6 @@ case "$target_arch2" in TARGET_BASE_ARCH=ppc TARGET_ABI_DIR=ppc gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml" - target_phys_bits=64 target_nptl="yes" target_libs_softmmu="$fdt_libs" ;; @@ -3780,7 +3767,6 @@ case "$target_arch2" in TARGET_BASE_ARCH=ppc TARGET_ABI_DIR=ppc gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml" - target_phys_bits=64 target_long_alignment=8 target_libs_softmmu="$fdt_libs" ;; @@ -3790,21 +3776,17 @@ case "$target_arch2" in TARGET_ABI_DIR=ppc echo "TARGET_ABI32=y" >> $config_target_mak gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml" - target_phys_bits=64 target_libs_softmmu="$fdt_libs" ;; sh4|sh4eb) TARGET_ARCH=sh4 bflt="yes" target_nptl="yes" - target_phys_bits=32 ;; sparc) - target_phys_bits=64 ;; sparc64) TARGET_BASE_ARCH=sparc - target_phys_bits=64 target_long_alignment=8 ;; sparc32plus) @@ -3812,11 +3794,9 @@ case "$target_arch2" in TARGET_BASE_ARCH=sparc TARGET_ABI_DIR=sparc echo "TARGET_ABI32=y" >> $config_target_mak - target_phys_bits=64 ;; s390x) target_nptl="yes" - target_phys_bits=64 target_long_alignment=8 ;; unicore32) @@ -3824,7 +3804,6 @@ case "$target_arch2" in ;; xtensa|xtensaeb) TARGET_ARCH=xtensa - target_phys_bits=32 ;; *) echo "Unsupported target CPU" @@ -3859,7 +3838,6 @@ echo "TARGET_ABI_DIR=$TARGET_ABI_DIR" >> $config_target_mak case "$target_arch2" in i386|x86_64) if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then - target_phys_bits=64 echo "CONFIG_XEN=y" >> $config_target_mak if test "$xen_pci_passthrough" = yes; then echo "CONFIG_XEN_PCI_PASSTHROUGH=y" >> "$config_target_mak" @@ -3899,11 +3877,10 @@ if test "$target_bigendian" = "yes" ; then echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak fi if test "$target_softmmu" = "yes" ; then - echo "TARGET_PHYS_ADDR_BITS=$target_phys_bits" >> $config_target_mak echo "CONFIG_SOFTMMU=y" >> $config_target_mak echo "LIBS+=$libs_softmmu $target_libs_softmmu" >> $config_target_mak - echo "HWDIR=../libhw$target_phys_bits" >> $config_target_mak - echo "subdir-$target: subdir-libhw$target_phys_bits" >> $config_host_mak + echo "HWDIR=../libhw" >> $config_target_mak + echo "subdir-$target: subdir-libhw" >> $config_host_mak if test "$smartcard_nss" = "yes" ; then echo "subdir-$target: subdir-libcacard" >> $config_host_mak fi @@ -4145,11 +4122,8 @@ for rom in seabios vgabios ; do echo "LD=$ld" >> $config_mak done -for hwlib in 32 64; do - d=libhw$hwlib - symlink "$source_path/Makefile.hw" "$d/Makefile" - echo "QEMU_CFLAGS+=-DTARGET_PHYS_ADDR_BITS=$hwlib" > $d/config.mak -done +d=libhw +symlink "$source_path/Makefile.hw" "$d/Makefile" d=libuser symlink "$source_path/Makefile.user" "$d/Makefile" diff --git a/cpu-common.h b/cpu-common.h index 85548de5ea..c0d27afd82 100644 --- a/cpu-common.h +++ b/cpu-common.h @@ -21,7 +21,7 @@ enum device_endian { }; /* address in the RAM (different from a physical address) */ -#if defined(CONFIG_XEN_BACKEND) && TARGET_PHYS_ADDR_BITS == 64 +#if defined(CONFIG_XEN_BACKEND) typedef uint64_t ram_addr_t; # define RAM_ADDR_MAX UINT64_MAX # define RAM_ADDR_FMT "%" PRIx64 diff --git a/dma.h b/dma.h index f35c4b6632..1a33603f22 100644 --- a/dma.h +++ b/dma.h @@ -31,7 +31,7 @@ struct QEMUSGList { DMAContext *dma; }; -#if defined(TARGET_PHYS_ADDR_BITS) +#ifndef CONFIG_USER_ONLY /* * When an IOMMU is present, bus addresses become distinct from diff --git a/hw/hw.h b/hw/hw.h index e5cb9bf94d..16101de3ce 100644 --- a/hw/hw.h +++ b/hw/hw.h @@ -4,7 +4,7 @@ #include "qemu-common.h" -#if defined(TARGET_PHYS_ADDR_BITS) && !defined(NEED_CPU_H) +#if !defined(CONFIG_USER_ONLY) && !defined(NEED_CPU_H) #include "cpu-common.h" #endif diff --git a/hw/intel-hda.c b/hw/intel-hda.c index 127e81888b..d8e1b23a60 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -210,13 +210,7 @@ static target_phys_addr_t intel_hda_addr(uint32_t lbase, uint32_t ubase) { target_phys_addr_t addr; -#if TARGET_PHYS_ADDR_BITS == 32 - addr = lbase; -#else - addr = ubase; - addr <<= 32; - addr |= lbase; -#endif + addr = ((uint64_t)ubase << 32) | lbase; return addr; } diff --git a/hw/rtl8139.c b/hw/rtl8139.c index 844f1b8c3f..b7c82ee027 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -774,11 +774,7 @@ static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) #define MIN_BUF_SIZE 60 static inline dma_addr_t rtl8139_addr64(uint32_t low, uint32_t high) { -#if TARGET_PHYS_ADDR_BITS > 32 - return low | ((target_phys_addr_t)high << 32); -#else - return low; -#endif + return low | ((uint64_t)high << 32); } /* Workaround for buggy guest driver such as linux who allocates rx diff --git a/monitor.c b/monitor.c index 67064e2706..7beac9a806 100644 --- a/monitor.c +++ b/monitor.c @@ -3259,11 +3259,7 @@ static int64_t expr_unary(Monitor *mon) break; default: errno = 0; -#if TARGET_PHYS_ADDR_BITS > 32 n = strtoull(pch, &p, 0); -#else - n = strtoul(pch, &p, 0); -#endif if (errno == ERANGE) { expr_error(mon, "number too large"); } diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c index d2664acef0..532b114aed 100644 --- a/target-ppc/mmu_helper.c +++ b/target-ppc/mmu_helper.c @@ -1032,12 +1032,10 @@ static int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb, return -1; } *raddrp = (tlb->RPN & mask) | (address & ~mask); -#if (TARGET_PHYS_ADDR_BITS >= 36) if (ext) { /* Extend the physical address to 36 bits */ - *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32; + *raddrp |= (uint64_t)(tlb->RPN & 0xF) << 32; } -#endif return 0; } diff --git a/targphys.h b/targphys.h index bd4938fc02..08cade9096 100644 --- a/targphys.h +++ b/targphys.h @@ -3,25 +3,10 @@ #ifndef TARGPHYS_H #define TARGPHYS_H -#ifdef TARGET_PHYS_ADDR_BITS +#define TARGET_PHYS_ADDR_BITS 64 /* target_phys_addr_t is the type of a physical address (its size can be different from 'target_ulong'). */ -#if TARGET_PHYS_ADDR_BITS == 32 -typedef uint32_t target_phys_addr_t; -#define TARGET_PHYS_ADDR_MAX UINT32_MAX -#define TARGET_FMT_plx "%08x" -/* Format strings for printing target_phys_addr_t types. - * These are recommended over the less flexible TARGET_FMT_plx, - * which is retained for the benefit of existing code. - */ -#define TARGET_PRIdPHYS PRId32 -#define TARGET_PRIiPHYS PRIi32 -#define TARGET_PRIoPHYS PRIo32 -#define TARGET_PRIuPHYS PRIu32 -#define TARGET_PRIxPHYS PRIx32 -#define TARGET_PRIXPHYS PRIX32 -#elif TARGET_PHYS_ADDR_BITS == 64 typedef uint64_t target_phys_addr_t; #define TARGET_PHYS_ADDR_MAX UINT64_MAX #define TARGET_FMT_plx "%016" PRIx64 @@ -31,7 +16,5 @@ typedef uint64_t target_phys_addr_t; #define TARGET_PRIuPHYS PRIu64 #define TARGET_PRIxPHYS PRIx64 #define TARGET_PRIXPHYS PRIX64 -#endif -#endif #endif From ef8beb0e94c75984e016e855164361c36e15396c Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 5 Oct 2012 04:34:40 +0200 Subject: [PATCH 0717/2270] PPC: KVM: Fix BAT put In the sregs API, upper and lower 32bit segments of the BAT registers are swapped when doing a set. Since we need to support old kernels out there, don't bother to fix it in the kernel, but instead work around the problem in QEMU by swapping on put. Signed-off-by: Alexander Graf --- target-ppc/kvm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 1975323eb7..93c5bb75e7 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -493,10 +493,11 @@ int kvm_arch_put_registers(CPUPPCState *env, int level) /* Sync BATs */ for (i = 0; i < 8; i++) { - sregs.u.s.ppc32.dbat[i] = ((uint64_t)env->DBAT[1][i] << 32) - | env->DBAT[0][i]; - sregs.u.s.ppc32.ibat[i] = ((uint64_t)env->IBAT[1][i] << 32) - | env->IBAT[0][i]; + /* Beware. We have to swap upper and lower bits here */ + sregs.u.s.ppc32.dbat[i] = ((uint64_t)env->DBAT[0][i] << 32) + | env->DBAT[1][i]; + sregs.u.s.ppc32.ibat[i] = ((uint64_t)env->IBAT[0][i] << 32) + | env->IBAT[1][i]; } ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs); From 7a608f562ebd91e811ed0b725e528c894e4f19c4 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sun, 23 Sep 2012 08:51:01 +0200 Subject: [PATCH 0718/2270] hw: Fix return value check for bdrv_read, bdrv_write Those functions return -errno in case of an error. The old code would typically only detect EPERM (1) errors. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- hw/nand.c | 34 ++++++++++++++++++++++------------ hw/onenand.c | 2 +- hw/sd.c | 16 +++++++++------- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/hw/nand.c b/hw/nand.c index e9501ae038..01f3adaee1 100644 --- a/hw/nand.c +++ b/hw/nand.c @@ -654,7 +654,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) sector = SECTOR(s->addr); off = (s->addr & PAGE_MASK) + s->offset; soff = SECTOR_OFFSET(s->addr); - if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1) { + if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, sector); return; } @@ -666,21 +666,23 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) MIN(OOB_SIZE, off + s->iolen - PAGE_SIZE)); } - if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1) + if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, sector); + } } else { off = PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset; sector = off >> 9; soff = off & 0x1ff; - if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1) { + if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, sector); return; } mem_and(iobuf + soff, s->io, s->iolen); - if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1) + if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, sector); + } } s->offset = 0; } @@ -704,31 +706,37 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s) i = SECTOR(addr); page = SECTOR(addr + (ADDR_SHIFT + s->erase_shift)); for (; i < page; i ++) - if (bdrv_write(s->bdrv, i, iobuf, 1) == -1) + if (bdrv_write(s->bdrv, i, iobuf, 1) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, i); + } } else { addr = PAGE_START(addr); page = addr >> 9; - if (bdrv_read(s->bdrv, page, iobuf, 1) == -1) + if (bdrv_read(s->bdrv, page, iobuf, 1) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, page); + } memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1); - if (bdrv_write(s->bdrv, page, iobuf, 1) == -1) + if (bdrv_write(s->bdrv, page, iobuf, 1) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, page); + } memset(iobuf, 0xff, 0x200); i = (addr & ~0x1ff) + 0x200; for (addr += ((PAGE_SIZE + OOB_SIZE) << s->erase_shift) - 0x200; i < addr; i += 0x200) - if (bdrv_write(s->bdrv, i >> 9, iobuf, 1) == -1) + if (bdrv_write(s->bdrv, i >> 9, iobuf, 1) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, i >> 9); + } page = i >> 9; - if (bdrv_read(s->bdrv, page, iobuf, 1) == -1) + if (bdrv_read(s->bdrv, page, iobuf, 1) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, page); + } memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1); - if (bdrv_write(s->bdrv, page, iobuf, 1) == -1) + if (bdrv_write(s->bdrv, page, iobuf, 1) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, page); + } } } @@ -740,18 +748,20 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s, if (s->bdrv) { if (s->mem_oob) { - if (bdrv_read(s->bdrv, SECTOR(addr), s->io, PAGE_SECTORS) == -1) + if (bdrv_read(s->bdrv, SECTOR(addr), s->io, PAGE_SECTORS) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, SECTOR(addr)); + } memcpy(s->io + SECTOR_OFFSET(s->addr) + PAGE_SIZE, s->storage + (PAGE(s->addr) << OOB_SHIFT), OOB_SIZE); s->ioaddr = s->io + SECTOR_OFFSET(s->addr) + offset; } else { if (bdrv_read(s->bdrv, PAGE_START(addr) >> 9, - s->io, (PAGE_SECTORS + 2)) == -1) + s->io, (PAGE_SECTORS + 2)) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, PAGE_START(addr) >> 9); + } s->ioaddr = s->io + (PAGE_START(addr) & 0x1ff) + offset; } } else { diff --git a/hw/onenand.c b/hw/onenand.c index db6af682c4..0f7b755a6d 100644 --- a/hw/onenand.c +++ b/hw/onenand.c @@ -351,7 +351,7 @@ static inline int onenand_erase(OneNANDState *s, int sec, int num) for (; num > 0; num--, sec++) { if (s->bdrv_cur) { int erasesec = s->secs_cur + (sec >> 5); - if (bdrv_write(s->bdrv_cur, sec, blankbuf, 1)) { + if (bdrv_write(s->bdrv_cur, sec, blankbuf, 1) < 0) { goto fail; } if (bdrv_read(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) { diff --git a/hw/sd.c b/hw/sd.c index ec26407543..297580aabe 100644 --- a/hw/sd.c +++ b/hw/sd.c @@ -1407,7 +1407,7 @@ static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len) DPRINTF("sd_blk_read: addr = 0x%08llx, len = %d\n", (unsigned long long) addr, len); - if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) == -1) { + if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) < 0) { fprintf(stderr, "sd_blk_read: read error on host side\n"); return; } @@ -1415,7 +1415,7 @@ static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len) if (end > (addr & ~511) + 512) { memcpy(sd->data, sd->buf + (addr & 511), 512 - (addr & 511)); - if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) == -1) { + if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) < 0) { fprintf(stderr, "sd_blk_read: read error on host side\n"); return; } @@ -1429,29 +1429,31 @@ static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len) uint64_t end = addr + len; if ((addr & 511) || len < 512) - if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) == -1) { + if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) < 0) { fprintf(stderr, "sd_blk_write: read error on host side\n"); return; } if (end > (addr & ~511) + 512) { memcpy(sd->buf + (addr & 511), sd->data, 512 - (addr & 511)); - if (bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) == -1) { + if (bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) < 0) { fprintf(stderr, "sd_blk_write: write error on host side\n"); return; } - if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) == -1) { + if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) < 0) { fprintf(stderr, "sd_blk_write: read error on host side\n"); return; } memcpy(sd->buf, sd->data + 512 - (addr & 511), end & 511); - if (bdrv_write(sd->bdrv, end >> 9, sd->buf, 1) == -1) + if (bdrv_write(sd->bdrv, end >> 9, sd->buf, 1) < 0) { fprintf(stderr, "sd_blk_write: write error on host side\n"); + } } else { memcpy(sd->buf + (addr & 511), sd->data, len); - if (!sd->bdrv || bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) == -1) + if (!sd->bdrv || bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) < 0) { fprintf(stderr, "sd_blk_write: write error on host side\n"); + } } } From afb63ebd0a9599312c27ecceb839a399740e00ef Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 26 Sep 2012 22:04:38 +0200 Subject: [PATCH 0719/2270] configure: Support empty target list (--target-list=) Specifying an empty target list with --target-list= is shorter than specifying --disable-user --disable-system. Both variants should give the same result: no targets at all. This modification implements that feature. It uses a trick which works with POSIX compliant shells to test whether target_list is undefined (=> default targets) or empty (=> no targets). Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- configure | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/configure b/configure index e58846d5e2..e51a793987 100755 --- a/configure +++ b/configure @@ -125,7 +125,8 @@ cc_i386=i386-pc-linux-gnu-gcc libs_qga="" debug_info="yes" -target_list="" +# Don't accept a target_list environment variable. +unset target_list # Default value for a variable defining feature "foo". # * foo="no" feature will only be used if --enable-foo arg is given @@ -1288,7 +1289,7 @@ if ! "$python" -c 'import sys; sys.exit(sys.version_info < (2,4) or sys.version_ exit 1 fi -if test -z "$target_list" ; then +if test -z "${target_list+xxx}" ; then target_list="$default_target_list" else target_list=`echo "$target_list" | sed -e 's/,/ /g'` From b2532d88c9eb4f4734f62d5075585ee8c1516605 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 27 Sep 2012 07:41:42 +0200 Subject: [PATCH 0720/2270] cpu: Add missing 'static' attribute to qemu_global_mutex Contrary to its name, 'qemu_global_mutex' is only used locally in cpus.c. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- cpus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpus.c b/cpus.c index 4b726ef4e7..1d5d4904cc 100644 --- a/cpus.c +++ b/cpus.c @@ -613,7 +613,7 @@ static void qemu_tcg_init_cpu_signals(void) } #endif /* _WIN32 */ -QemuMutex qemu_global_mutex; +static QemuMutex qemu_global_mutex; static QemuCond qemu_io_proceeded_cond; static bool iothread_requesting_mutex; From f97713ff191ab855ca5c03458f8dab0c9bf58443 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 27 Sep 2012 14:55:43 +0100 Subject: [PATCH 0721/2270] tcg/arm: Use tcg_out_mov_reg rather than inline equivalent code Use the recently introduced tcg_out_mov_reg() function rather than the equivalent inline code. Signed-off-by: Peter Maydell Reviewed-by: Aurelien Jarno Signed-off-by: Stefan Hajnoczi --- tcg/arm/tcg-target.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index 2bad0a2b17..5e8dbdd888 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -1197,20 +1197,11 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) case 1: case 2: default: - if (data_reg != TCG_REG_R0) { - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - data_reg, 0, TCG_REG_R0, SHIFT_IMM_LSL(0)); - } + tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0); break; case 3: - if (data_reg != TCG_REG_R0) { - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - data_reg, 0, TCG_REG_R0, SHIFT_IMM_LSL(0)); - } - if (data_reg2 != TCG_REG_R1) { - tcg_out_dat_reg(s, COND_AL, ARITH_MOV, - data_reg2, 0, TCG_REG_R1, SHIFT_IMM_LSL(0)); - } + tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0); + tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1); break; } From 30daca5f77588a75bf9bcd604e21c5506402fabb Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 27 Sep 2012 20:57:38 +0200 Subject: [PATCH 0722/2270] slirp: Fix spelling in comment (enought -> enough, insure -> ensure) Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- slirp/ip_icmp.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slirp/ip_icmp.h b/slirp/ip_icmp.h index 1a1af91e1e..be4426b8e7 100644 --- a/slirp/ip_icmp.h +++ b/slirp/ip_icmp.h @@ -92,8 +92,8 @@ struct icmp { /* * Lower bounds on packet lengths for various types. - * For the error advice packets must first insure that the - * packet is large enought to contain the returned ip header. + * For the error advice packets must first ensure that the + * packet is large enough to contain the returned ip header. * Only then can we do the check to see if 64 bits of packet * data have been returned, since we need to check the returned * ip header length. From d69eba24269c0d3d376b7de4095dcca376a3beea Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 28 Sep 2012 18:11:49 +0200 Subject: [PATCH 0723/2270] vnc: Fix spelling (hellmen -> hellman) in comment The algorithm was named after Martin E. Hellman. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- ui/vnc-tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/vnc-tls.c b/ui/vnc-tls.c index 3aaa93928a..a7f7d07ac8 100644 --- a/ui/vnc-tls.c +++ b/ui/vnc-tls.c @@ -49,7 +49,7 @@ static int vnc_tls_initialize(void) if (gnutls_global_init () < 0) return 0; - /* XXX ought to re-generate diffie-hellmen params periodically */ + /* XXX ought to re-generate diffie-hellman params periodically */ if (gnutls_dh_params_init (&dh_params) < 0) return 0; if (gnutls_dh_params_generate2 (dh_params, DH_BITS) < 0) From 58455eb9f2865d54c8bf208805f7a4c217b5c00d Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 28 Sep 2012 19:07:39 +0200 Subject: [PATCH 0724/2270] qemu-sockets: Fix compiler warning (regression for MinGW) setsockopt needs a type cast for MinGW. That type cast is missing in a recent commit which results in a compiler warning. Like for other socket related functions which have the same problem, we add a 'qemu_setsockopt' macro which provides that type cast where needed and use the new macro to avoid the warning. A 'qemu_getsockopt' is also added and can be used for future modifications. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- qemu-common.h | 10 +++++++++- qemu-sockets.c | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/qemu-common.h b/qemu-common.h index 15d9e4ed71..b54612b1a5 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -223,11 +223,19 @@ int qemu_pipe(int pipefd[2]); #endif #ifdef _WIN32 -/* MinGW needs a type cast for the 'buf' argument. */ +/* MinGW needs type casts for the 'buf' and 'optval' arguments. */ +#define qemu_getsockopt(sockfd, level, optname, optval, optlen) \ + getsockopt(sockfd, level, optname, (void *)optval, optlen) +#define qemu_setsockopt(sockfd, level, optname, optval, optlen) \ + setsockopt(sockfd, level, optname, (const void *)optval, optlen) #define qemu_recv(sockfd, buf, len, flags) recv(sockfd, (void *)buf, len, flags) #define qemu_sendto(sockfd, buf, len, flags, destaddr, addrlen) \ sendto(sockfd, (const void *)buf, len, flags, destaddr, addrlen) #else +#define qemu_getsockopt(sockfd, level, optname, optval, optlen) \ + getsockopt(sockfd, level, optname, optval, optlen) +#define qemu_setsockopt(sockfd, level, optname, optval, optlen) \ + setsockopt(sockfd, level, optname, optval, optlen) #define qemu_recv(sockfd, buf, len, flags) recv(sockfd, buf, len, flags) #define qemu_sendto(sockfd, buf, len, flags, destaddr, addrlen) \ sendto(sockfd, buf, len, flags, destaddr, addrlen) diff --git a/qemu-sockets.c b/qemu-sockets.c index 1f14e8bc63..0f59490859 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -282,7 +282,7 @@ static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, inet_strfamily(addr->ai_family), strerror(errno)); return -1; } - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (connect_state != NULL) { socket_set_nonblock(sock); } From a5cf8262e4eb9c4646434e2c6211ef8608db3233 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:09:44 +0200 Subject: [PATCH 0725/2270] scsi, pci, qdev, isa-bus, sysbus: don't let *_get_fw_dev_path return NULL Use g_strdup rather than strdup, because the sole caller (qdev_get_fw_dev_path_helper) assumes it gets non-NULL, and dereferences it. Besides, in that caller, the allocated buffer is already freed with g_free, so it's better to allocate with a matching g_strdup. In one case, (scsi-bus.c) it was trivial, so I replaced an snprintf+ g_strdup combination with an equivalent g_strdup_printf use. Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- hw/ide/qdev.c | 2 +- hw/isa-bus.c | 2 +- hw/pci.c | 2 +- hw/qdev.c | 2 +- hw/scsi-bus.c | 8 ++------ hw/sysbus.c | 2 +- 6 files changed, 7 insertions(+), 11 deletions(-) diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 5ea9b8f4b2..f2e4ea4207 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -60,7 +60,7 @@ static char *idebus_get_fw_dev_path(DeviceState *dev) snprintf(path, sizeof(path), "%s@%d", qdev_fw_name(dev), ((IDEBus*)dev->parent_bus)->bus_id); - return strdup(path); + return g_strdup(path); } static int ide_qdev_init(DeviceState *qdev) diff --git a/hw/isa-bus.c b/hw/isa-bus.c index f9b237387a..47c93d37b6 100644 --- a/hw/isa-bus.c +++ b/hw/isa-bus.c @@ -236,7 +236,7 @@ static char *isabus_get_fw_dev_path(DeviceState *dev) snprintf(path + off, sizeof(path) - off, "@%04x", d->ioport_id); } - return strdup(path); + return g_strdup(path); } MemoryRegion *isa_address_space(ISADevice *dev) diff --git a/hw/pci.c b/hw/pci.c index f855cf3f39..de4b4485e7 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1962,7 +1962,7 @@ static char *pcibus_get_fw_dev_path(DeviceState *dev) PCI_SLOT(d->devfn)); if (PCI_FUNC(d->devfn)) snprintf(path + off, sizeof(path) + off, ",%x", PCI_FUNC(d->devfn)); - return strdup(path); + return g_strdup(path); } static char *pcibus_get_dev_path(DeviceState *dev) diff --git a/hw/qdev.c b/hw/qdev.c index b5a52ac503..3b5ce3312f 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -520,7 +520,7 @@ char* qdev_get_fw_dev_path(DeviceState *dev) path[l-1] = '\0'; - return strdup(path); + return g_strdup(path); } char *qdev_get_dev_path(DeviceState *dev) diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 058d3b237f..dfb2631210 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -1723,12 +1723,8 @@ static char *scsibus_get_dev_path(DeviceState *dev) static char *scsibus_get_fw_dev_path(DeviceState *dev) { SCSIDevice *d = SCSI_DEVICE(dev); - char path[100]; - - snprintf(path, sizeof(path), "channel@%x/%s@%x,%x", d->channel, - qdev_fw_name(dev), d->id, d->lun); - - return strdup(path); + return g_strdup_printf("channel@%x/%s@%x,%x", d->channel, + qdev_fw_name(dev), d->id, d->lun); } SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun) diff --git a/hw/sysbus.c b/hw/sysbus.c index 9d8b1eaf7d..c1738403dd 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -211,7 +211,7 @@ static char *sysbus_get_fw_dev_path(DeviceState *dev) snprintf(path + off, sizeof(path) - off, "@i%04x", s->pio[0]); } - return strdup(path); + return g_strdup(path); } void sysbus_add_memory(SysBusDevice *dev, target_phys_addr_t addr, From bfad67399bcca8c1afbbc93593d365044d92f7c6 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:09:45 +0200 Subject: [PATCH 0726/2270] sparc: use g_strdup in place of unchecked strdup This avoids a NULL-deref upon strdup failure. Also update matching free to g_free. Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- target-sparc/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c index f7c004c7d8..eb9f0e7259 100644 --- a/target-sparc/cpu.c +++ b/target-sparc/cpu.c @@ -643,7 +643,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model) { unsigned int i; const sparc_def_t *def = NULL; - char *s = strdup(cpu_model); + char *s = g_strdup(cpu_model); char *featurestr, *name = strtok(s, ","); uint32_t plus_features = 0; uint32_t minus_features = 0; @@ -735,7 +735,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model) #ifdef DEBUG_FEATURES print_features(stderr, fprintf, cpu_def->features, NULL); #endif - free(s); + g_free(s); return 0; error: From c2cba3d9314f972dfaf724d0ec2d018eb54c95f1 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:09:46 +0200 Subject: [PATCH 0727/2270] block: avoid buffer overrun by using pstrcpy, not strncpy Also, use PATH_MAX, rather than the arbitrary 1024. Using PATH_MAX is more consistent with other filename-related variables in this file, like backing_filename and tmp_filename. Acked-by: Kevin Wolf Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- block.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/block.c b/block.c index c108a76952..e95f613aa4 100644 --- a/block.c +++ b/block.c @@ -1506,7 +1506,7 @@ int bdrv_commit(BlockDriverState *bs) int n, ro, open_flags; int ret = 0; uint8_t *buf; - char filename[1024]; + char filename[PATH_MAX]; if (!drv) return -ENOMEDIUM; @@ -1520,7 +1520,8 @@ int bdrv_commit(BlockDriverState *bs) } ro = bs->backing_hd->read_only; - strncpy(filename, bs->backing_hd->filename, sizeof(filename)); + /* Use pstrcpy (not strncpy): filename must be NUL-terminated. */ + pstrcpy(filename, sizeof(filename), bs->backing_hd->filename); open_flags = bs->backing_hd->open_flags; if (ro) { From 3178e2755ec5a7fb1afe583fb6ac2622c2c42184 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:09:47 +0200 Subject: [PATCH 0728/2270] sheepdog: avoid a few buffer overruns * parse_vdiname: Use pstrcpy, not strncpy, when the destination buffer must be NUL-terminated. * sd_open: Likewise, avoid buffer overrun. * do_sd_create: Likewise. Leave the preceding memset, since pstrcpy does not NUL-fill, and filename needs that. * sd_snapshot_create: Add a comment/question. * find_vdi_name: Remove a useless memset. * sd_snapshot_goto: Remove a useless memset. Use pstrcpy to NUL-terminate, because find_vdi_name requires that its vdi arg (filename parameter) be NUL-terminated. It seems ok not to NUL-fill the buffer. Do the same for snapid: remove useless memset-0 (instead, zero tag[0]). Use pstrcpy, not strncpy. * sd_snapshot_list: Use pstrcpy, not strncpy to write into the ->name member. Each must be NUL-terminated. Acked-by: Kevin Wolf Acked-by: MORITA Kazutaka Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- block/sheepdog.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/block/sheepdog.c b/block/sheepdog.c index 4742f8ae6f..f35ff5bbe1 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -866,14 +866,14 @@ static int parse_vdiname(BDRVSheepdogState *s, const char *filename, s->port = 0; } - strncpy(vdi, p, SD_MAX_VDI_LEN); + pstrcpy(vdi, SD_MAX_VDI_LEN, p); p = strchr(vdi, ':'); if (p) { *p++ = '\0'; *snapid = strtoul(p, NULL, 10); if (*snapid == 0) { - strncpy(tag, p, SD_MAX_VDI_TAG_LEN); + pstrcpy(tag, SD_MAX_VDI_TAG_LEN, p); } } else { *snapid = CURRENT_VDI_ID; /* search current vdi */ @@ -900,7 +900,10 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid, return fd; } - memset(buf, 0, sizeof(buf)); + /* This pair of strncpy calls ensures that the buffer is zero-filled, + * which is desirable since we'll soon be sending those bytes, and + * don't want the send_req to read uninitialized data. + */ strncpy(buf, filename, SD_MAX_VDI_LEN); strncpy(buf + SD_MAX_VDI_LEN, tag, SD_MAX_VDI_TAG_LEN); @@ -1149,7 +1152,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags) s->max_dirty_data_idx = 0; bs->total_sectors = s->inode.vdi_size / SECTOR_SIZE; - strncpy(s->name, vdi, sizeof(s->name)); + pstrcpy(s->name, sizeof(s->name), vdi); qemu_co_mutex_init(&s->lock); g_free(buf); return 0; @@ -1177,8 +1180,11 @@ static int do_sd_create(char *filename, int64_t vdi_size, return fd; } + /* FIXME: would it be better to fail (e.g., return -EIO) when filename + * does not fit in buf? For now, just truncate and avoid buffer overrun. + */ memset(buf, 0, sizeof(buf)); - strncpy(buf, filename, SD_MAX_VDI_LEN); + pstrcpy(buf, sizeof(buf), filename); memset(&hdr, 0, sizeof(hdr)); hdr.opcode = SD_OP_NEW_VDI; @@ -1752,6 +1758,9 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) s->inode.vm_state_size = sn_info->vm_state_size; s->inode.vm_clock_nsec = sn_info->vm_clock_nsec; + /* It appears that inode.tag does not require a NUL terminator, + * which means this use of strncpy is ok. + */ strncpy(s->inode.tag, sn_info->name, sizeof(s->inode.tag)); /* we don't need to update entire object */ datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id); @@ -1811,13 +1820,13 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) memcpy(old_s, s, sizeof(BDRVSheepdogState)); - memset(vdi, 0, sizeof(vdi)); - strncpy(vdi, s->name, sizeof(vdi)); + pstrcpy(vdi, sizeof(vdi), s->name); - memset(tag, 0, sizeof(tag)); snapid = strtoul(snapshot_id, NULL, 10); - if (!snapid) { - strncpy(tag, s->name, sizeof(tag)); + if (snapid) { + tag[0] = 0; + } else { + pstrcpy(tag, sizeof(tag), s->name); } ret = find_vdi_name(s, vdi, snapid, tag, &vid, 1); @@ -1946,8 +1955,9 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) snprintf(sn_tab[found].id_str, sizeof(sn_tab[found].id_str), "%u", inode.snap_id); - strncpy(sn_tab[found].name, inode.tag, - MIN(sizeof(sn_tab[found].name), sizeof(inode.tag))); + pstrcpy(sn_tab[found].name, + MIN(sizeof(sn_tab[found].name), sizeof(inode.tag)), + inode.tag); found++; } } From d66f8e7bd3de4a2ecf0680c635f870f2138425b8 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:09:48 +0200 Subject: [PATCH 0729/2270] vmdk: relative_path: use pstrcpy in place of strncpy Avoid strncpy+manual-NUL-terminate. Use pstrcpy instead. Acked-by: Kevin Wolf Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- block/vmdk.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index f2e861b074..1a80e5a247 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1408,8 +1408,7 @@ static int relative_path(char *dest, int dest_size, return -1; } if (path_is_absolute(target)) { - dest[dest_size - 1] = '\0'; - strncpy(dest, target, dest_size - 1); + pstrcpy(dest, dest_size, target); return 0; } while (base[i] == target[i]) { From a79b5f8b80890b402fdb0733b0a073695a7875b5 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:09:49 +0200 Subject: [PATCH 0730/2270] hw/9pfs: avoid buffer overrun v9fs_add_dir_node and qemu_v9fs_synth_add_file used strncpy to form node->name, which requires NUL-termination, but strncpy does not ensure NUL-termination. Use pstrcpy, which does. Acked-by: Aneesh Kumar K.V Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- hw/9pfs/virtio-9p-synth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/9pfs/virtio-9p-synth.c b/hw/9pfs/virtio-9p-synth.c index 92e0b09d38..e95a856d25 100644 --- a/hw/9pfs/virtio-9p-synth.c +++ b/hw/9pfs/virtio-9p-synth.c @@ -58,7 +58,7 @@ static V9fsSynthNode *v9fs_add_dir_node(V9fsSynthNode *parent, int mode, node->attr->read = NULL; } node->private = node; - strncpy(node->name, name, sizeof(node->name)); + pstrcpy(node->name, sizeof(node->name), name); QLIST_INSERT_HEAD_RCU(&parent->child, node, sibling); return node; } @@ -132,7 +132,7 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode, node->attr->write = write; node->attr->mode = mode; node->private = arg; - strncpy(node->name, name, sizeof(node->name)); + pstrcpy(node->name, sizeof(node->name), name); QLIST_INSERT_HEAD_RCU(&parent->child, node, sibling); ret = 0; err_out: From 1044dc1118d9a90e2aa324047bea9c91c889e28f Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:09:50 +0200 Subject: [PATCH 0731/2270] lm32: avoid buffer overrun Actually do what the comment says, using pstrcpy NUL-terminate: strncpy does not always do that. Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- hw/lm32_hwsetup.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/lm32_hwsetup.h b/hw/lm32_hwsetup.h index 8fc285efc2..70dc61f9e7 100644 --- a/hw/lm32_hwsetup.h +++ b/hw/lm32_hwsetup.h @@ -96,7 +96,7 @@ static inline void hwsetup_add_tag(HWSetup *hw, enum hwsetup_tag t) static inline void hwsetup_add_str(HWSetup *hw, const char *str) { - strncpy(hw->ptr, str, 31); /* make sure last byte is zero */ + pstrcpy(hw->ptr, 32, str); hw->ptr += 32; } From 3eadc68ebd174f5bad51fe6e0bbcf6d6651c784c Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:09:51 +0200 Subject: [PATCH 0732/2270] os-posix: avoid buffer overrun os_set_proc_name: Use pstrcpy, in place of strncpy and the ineffectual preceding assignment: name[sizeof(name) - 1] = 0; Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- os-posix.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/os-posix.c b/os-posix.c index eabccb8fe0..f855abb09a 100644 --- a/os-posix.c +++ b/os-posix.c @@ -148,8 +148,7 @@ void os_set_proc_name(const char *s) char name[16]; if (!s) return; - name[sizeof(name) - 1] = 0; - strncpy(name, s, sizeof(name)); + pstrcpy(name, sizeof(name), s); /* Could rewrite argv[0] too, but that's a bit more complicated. This simple way is enough for `top'. */ if (prctl(PR_SET_NAME, name)) { From ae2150680190e510dcbcdfdbfb3a54369c75367f Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:09:52 +0200 Subject: [PATCH 0733/2270] ppc: avoid buffer overrun: use pstrcpy, not strncpy A terminal NUL is required by caller's use of strchr. It's better not to use strncpy at all, since there is no need to zero out hundreds of trailing bytes for each iteration. Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- target-ppc/kvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index a31d278a5f..7f6e4e0b87 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -795,7 +795,7 @@ static int read_cpuinfo(const char *field, char *value, int len) break; } if (!strncmp(line, field, field_len)) { - strncpy(value, line, len); + pstrcpy(value, len, line); ret = 0; break; } From 900cfbcac6fa689b5fc8d53b60c3ed39047b8a33 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:09:53 +0200 Subject: [PATCH 0734/2270] linux-user: remove two unchecked uses of strdup Remove two uses of strdup (use g_path_get_basename instead), and add a comment that this strncpy use is ok. Reviewed-by: Peter Maydell Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- linux-user/elfload.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 819fdd515a..1d8bcb4e79 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -2442,7 +2442,7 @@ static void fill_prstatus(struct target_elf_prstatus *prstatus, static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts) { - char *filename, *base_filename; + char *base_filename; unsigned int i, len; (void) memset(psinfo, 0, sizeof (*psinfo)); @@ -2464,13 +2464,15 @@ static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts) psinfo->pr_uid = getuid(); psinfo->pr_gid = getgid(); - filename = strdup(ts->bprm->filename); - base_filename = strdup(basename(filename)); + base_filename = g_path_get_basename(ts->bprm->filename); + /* + * Using strncpy here is fine: at max-length, + * this field is not NUL-terminated. + */ (void) strncpy(psinfo->pr_fname, base_filename, sizeof(psinfo->pr_fname)); - free(base_filename); - free(filename); + g_free(base_filename); bswap_psinfo(psinfo); return (0); } From 5847d9e1399d3497be8eeca6f3a20a18a40b114b Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:09:54 +0200 Subject: [PATCH 0735/2270] ui/vnc: simplify and avoid strncpy Don't bother with strncpy. There's no need for its zero-fill. Use g_strndup in place of g_malloc+strncpy+NUL-terminate. Reviewed-by: Peter Maydell Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- ui/vnc-auth-sasl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c index 8fba7702c2..bfdcb46efe 100644 --- a/ui/vnc-auth-sasl.c +++ b/ui/vnc-auth-sasl.c @@ -432,9 +432,7 @@ static int protocol_client_auth_sasl_start_len(VncState *vs, uint8_t *data, size static int protocol_client_auth_sasl_mechname(VncState *vs, uint8_t *data, size_t len) { - char *mechname = g_malloc(len + 1); - strncpy(mechname, (char*)data, len); - mechname[len] = '\0'; + char *mechname = g_strndup((const char *) data, len); VNC_DEBUG("Got client mechname '%s' check against '%s'\n", mechname, vs->sasl.mechlist); From e5fda03839e3c61b01d6c60de5625501d01c69d0 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:09:55 +0200 Subject: [PATCH 0736/2270] bt: replace fragile snprintf use and unwarranted strncpy In bt_hci_name_req a failed snprintf could return len larger than sizeof(params.name), which means the following memset call would have a "length" value of (size_t)-1, -2, etc... Sounds scary. But currently, one can deduce that there is no problem: strlen(slave->lmp_name) is guaranteed to be smaller than CHANGE_LOCAL_NAME_CP_SIZE, which is the same as sizeof(params.name), so this cannot happen. Regardless, there is no justification for using snprintf+memset. Use pstrcpy instead. Also, in bt_hci_event_complete_read_local_name, use pstrcpy in place of unwarranted strncpy. Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- hw/bt-hci.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/hw/bt-hci.c b/hw/bt-hci.c index a3a7fb49e2..47f9a4e496 100644 --- a/hw/bt-hci.c +++ b/hw/bt-hci.c @@ -943,7 +943,6 @@ static int bt_hci_name_req(struct bt_hci_s *hci, bdaddr_t *bdaddr) { struct bt_device_s *slave; evt_remote_name_req_complete params; - int len; for (slave = hci->device.net->slave; slave; slave = slave->next) if (slave->page_scan && !bacmp(&slave->bd_addr, bdaddr)) @@ -955,9 +954,7 @@ static int bt_hci_name_req(struct bt_hci_s *hci, bdaddr_t *bdaddr) params.status = HCI_SUCCESS; bacpy(¶ms.bdaddr, &slave->bd_addr); - len = snprintf(params.name, sizeof(params.name), - "%s", slave->lmp_name ?: ""); - memset(params.name + len, 0, sizeof(params.name) - len); + pstrcpy(params.name, sizeof(params.name), slave->lmp_name ?: ""); bt_hci_event(hci, EVT_REMOTE_NAME_REQ_COMPLETE, ¶ms, EVT_REMOTE_NAME_REQ_COMPLETE_SIZE); @@ -1388,7 +1385,7 @@ static inline void bt_hci_event_complete_read_local_name(struct bt_hci_s *hci) params.status = HCI_SUCCESS; memset(params.name, 0, sizeof(params.name)); if (hci->device.lmp_name) - strncpy(params.name, hci->device.lmp_name, sizeof(params.name)); + pstrcpy(params.name, sizeof(params.name), hci->device.lmp_name); bt_hci_event_complete(hci, ¶ms, READ_LOCAL_NAME_RP_SIZE); } From 9238c2099d37748a4e2cbbe709ed1ebffa6f3c8b Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:09:56 +0200 Subject: [PATCH 0737/2270] virtio-9p: avoid unwarranted uses of strncpy In all of these cases, the uses of strncpy were unnecessary, since at each point of use we know that the NUL-terminated source bytes fit in the destination buffer. Use memcpy in place of strncpy. Acked-by: Aneesh Kumar K.V Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- hw/9pfs/virtio-9p-posix-acl.c | 6 ++++-- hw/9pfs/virtio-9p-xattr-user.c | 3 ++- hw/9pfs/virtio-9p-xattr.c | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/9pfs/virtio-9p-posix-acl.c b/hw/9pfs/virtio-9p-posix-acl.c index a1948e3aff..c064017b1f 100644 --- a/hw/9pfs/virtio-9p-posix-acl.c +++ b/hw/9pfs/virtio-9p-posix-acl.c @@ -44,7 +44,8 @@ static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path, return -1; } - strncpy(value, ACL_ACCESS, len); + /* len includes the trailing NUL */ + memcpy(value, ACL_ACCESS, len); return 0; } @@ -95,7 +96,8 @@ static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path, return -1; } - strncpy(value, ACL_DEFAULT, len); + /* len includes the trailing NUL */ + memcpy(value, ACL_ACCESS, len); return 0; } diff --git a/hw/9pfs/virtio-9p-xattr-user.c b/hw/9pfs/virtio-9p-xattr-user.c index 5044a3e5ab..5bb6020070 100644 --- a/hw/9pfs/virtio-9p-xattr-user.c +++ b/hw/9pfs/virtio-9p-xattr-user.c @@ -61,7 +61,8 @@ static ssize_t mp_user_listxattr(FsContext *ctx, const char *path, return -1; } - strncpy(value, name, name_size); + /* name_size includes the trailing NUL. */ + memcpy(value, name, name_size); return name_size; } diff --git a/hw/9pfs/virtio-9p-xattr.c b/hw/9pfs/virtio-9p-xattr.c index 7f08f6e176..a83960676d 100644 --- a/hw/9pfs/virtio-9p-xattr.c +++ b/hw/9pfs/virtio-9p-xattr.c @@ -53,7 +53,8 @@ ssize_t pt_listxattr(FsContext *ctx, const char *path, return -1; } - strncpy(value, name, name_size); + /* no need for strncpy: name_size is strlen(name)+1 */ + memcpy(value, name, name_size); return name_size; } From 9d055d8ac83cfd590263e8862ff683f705dfdf56 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:09:57 +0200 Subject: [PATCH 0738/2270] vscsi: avoid unwarranted strncpy Don't use strncpy when the source string is known to fit in the destination buffer. Use equivalent memcpy. We could even use strcpy, here, but some static analyzers warn about that, so don't add new uses. Acked-by: David Gibson Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- hw/spapr_vscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c index 3cf5844e0f..e3d4b237f1 100644 --- a/hw/spapr_vscsi.c +++ b/hw/spapr_vscsi.c @@ -737,7 +737,7 @@ static int vscsi_send_adapter_info(VSCSIState *s, vscsi_req *req) #endif memset(&info, 0, sizeof(info)); strcpy(info.srp_version, SRP_VERSION); - strncpy(info.partition_name, "qemu", sizeof("qemu")); + memcpy(info.partition_name, "qemu", sizeof("qemu")); info.partition_number = cpu_to_be32(0); info.mad_version = cpu_to_be32(1); info.os_type = cpu_to_be32(2); From 1ab516ed9b6ba00bafc5ca37604f8af4680323ca Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:09:58 +0200 Subject: [PATCH 0739/2270] qemu-ga: prefer pstrcpy: consistently NUL-terminate ifreq.ifr_name NUL-termination of the .ifr_name field is not required, but is fine (and preferable to using strncpy and leaving the reader to wonder), since the first thing the linux kernel does is to clear the last byte. Besides, using pstrcpy here makes this setting of ifr_name consistent with the other code (e.g., net/tap-linux.c) that does the same thing. Reviewed-by: Luiz Capitulino Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- qga/commands-posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index ce9042123c..b9f357cb96 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -828,7 +828,7 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) } memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, info->value->name, IF_NAMESIZE); + pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->value->name); if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) { snprintf(err_msg, sizeof(err_msg), "failed to get MAC address of %s: %s", From 2e679780ae86c6ca8bc81efe0a376a0b99b09b8f Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:09:59 +0200 Subject: [PATCH 0740/2270] libcacard/vcard_emul_nss: use pstrcpy in place of strncpy Replace strncpy+NUL-terminate use with use of pstrcpy. This requires linking with cutils.o (or else vssclient doesn't link), so add that in the Makefile. Acked-by: Alon Levy Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- libcacard/Makefile | 3 +++ libcacard/vcard_emul_nss.c | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libcacard/Makefile b/libcacard/Makefile index 63990b7003..487f434894 100644 --- a/libcacard/Makefile +++ b/libcacard/Makefile @@ -14,6 +14,9 @@ QEMU_CFLAGS+=-I../ libcacard.lib-y=$(patsubst %.o,%.lo,$(libcacard-y)) +vscclient: $(libcacard-y) $(QEMU_OBJS) vscclient.o cutils.o + $(call quiet-command,$(CC) -o $@ $^ $(libcacard_libs) $(LIBS)," LINK $@") + clean: rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~ vscclient *.lo */*.lo .libs/* */.libs/* *.la */*.la *.pc rm -Rf .libs */.libs diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c index 802cae3a29..e1cae5bc51 100644 --- a/libcacard/vcard_emul_nss.c +++ b/libcacard/vcard_emul_nss.c @@ -1169,8 +1169,7 @@ vcard_emul_options(const char *args) NEXT_TOKEN(vname) NEXT_TOKEN(type_params) type_params_length = MIN(type_params_length, sizeof(type_str)-1); - strncpy(type_str, type_params, type_params_length); - type_str[type_params_length] = 0; + pstrcpy(type_str, type_params_length, type_params); type = vcard_emul_type_from_string(type_str); NEXT_TOKEN(type_params) From 3cda346269784c234c7a296ff6851f36a1a9189d Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:10:00 +0200 Subject: [PATCH 0741/2270] acpi: remove strzcpy (strncpy-identical) function; just use strncpy Adjust all uses s/strzcpy/strncpy/ and mark these uses of strncpy as "ok". Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- hw/acpi.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/hw/acpi.c b/hw/acpi.c index f7950be267..f4aca493fc 100644 --- a/hw/acpi.c +++ b/hw/acpi.c @@ -61,18 +61,6 @@ static int acpi_checksum(const uint8_t *data, int len) return (-sum) & 0xff; } -/* like strncpy() but zero-fills the tail of destination */ -static void strzcpy(char *dst, const char *src, size_t size) -{ - size_t len = strlen(src); - if (len >= size) { - len = size; - } else { - memset(dst + len, 0, size - len); - } - memcpy(dst, src, len); -} - /* XXX fixme: this function uses obsolete argument parsing interface */ int acpi_table_add(const char *t) { @@ -157,7 +145,8 @@ int acpi_table_add(const char *t) hdr._length = cpu_to_le16(len); if (get_param_value(buf, sizeof(buf), "sig", t)) { - strzcpy(hdr.sig, buf, sizeof(hdr.sig)); + /* strncpy is justified: the field need not be NUL-terminated. */ + strncpy(hdr.sig, buf, sizeof(hdr.sig)); ++changed; } @@ -187,12 +176,14 @@ int acpi_table_add(const char *t) } if (get_param_value(buf, sizeof(buf), "oem_id", t)) { - strzcpy(hdr.oem_id, buf, sizeof(hdr.oem_id)); + /* strncpy is justified: the field need not be NUL-terminated. */ + strncpy(hdr.oem_id, buf, sizeof(hdr.oem_id)); ++changed; } if (get_param_value(buf, sizeof(buf), "oem_table_id", t)) { - strzcpy(hdr.oem_table_id, buf, sizeof(hdr.oem_table_id)); + /* strncpy is justified: the field need not be NUL-terminated. */ + strncpy(hdr.oem_table_id, buf, sizeof(hdr.oem_table_id)); ++changed; } @@ -207,7 +198,8 @@ int acpi_table_add(const char *t) } if (get_param_value(buf, sizeof(buf), "asl_compiler_id", t)) { - strzcpy(hdr.asl_compiler_id, buf, sizeof(hdr.asl_compiler_id)); + /* strncpy is justified: the field need not be NUL-terminated. */ + strncpy(hdr.asl_compiler_id, buf, sizeof(hdr.asl_compiler_id)); ++changed; } From 00ea188125f6ee33e6beaff5da878fa9478e6a0d Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:10:01 +0200 Subject: [PATCH 0742/2270] qcow2: mark this file's sole strncpy use as justified Acked-by: Kevin Wolf Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- block/qcow2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block/qcow2.c b/block/qcow2.c index aa5e603cd3..c1ff31f482 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1096,6 +1096,7 @@ int qcow2_update_header(BlockDriverState *bs) goto fail; } + /* Using strncpy is ok here, since buf is not NUL-terminated. */ strncpy(buf, bs->backing_file, buflen); header->backing_file_offset = cpu_to_be64(buf - ((char*) header)); From 9310b9be14f73d4c1e98bfa315fe84326ad9e8e7 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:10:02 +0200 Subject: [PATCH 0743/2270] hw/r2d: add comment: this strncpy use is ok Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- hw/r2d.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/r2d.c b/hw/r2d.c index 0f16e81afe..1bc191ff3e 100644 --- a/hw/r2d.c +++ b/hw/r2d.c @@ -332,6 +332,8 @@ static void r2d_init(ram_addr_t ram_size, } if (kernel_cmdline) { + /* I see no evidence that this .kernel_cmdline buffer requires + NUL-termination, so using strncpy should be ok. */ strncpy(boot_params.kernel_cmdline, kernel_cmdline, sizeof(boot_params.kernel_cmdline)); } From 9b9e3ec1b47f615f635055924e24705cc3f45b20 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 4 Oct 2012 13:10:03 +0200 Subject: [PATCH 0744/2270] doc: update HACKING wrt strncpy/pstrcpy Reword the section on strncpy: its NUL-filling is important in some cases. Mention that pstrcpy's signature is different. Signed-off-by: Jim Meyering Signed-off-by: Anthony Liguori --- HACKING | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/HACKING b/HACKING index 471cf1d197..dddd617a6b 100644 --- a/HACKING +++ b/HACKING @@ -91,10 +91,11 @@ emulators. 4. String manipulation -Do not use the strncpy function. According to the man page, it does -*not* guarantee a NULL-terminated buffer, which makes it extremely dangerous -to use. Instead, use functionally equivalent function: -void pstrcpy(char *buf, int buf_size, const char *str) +Do not use the strncpy function. As mentioned in the man page, it does *not* +guarantee a NULL-terminated buffer, which makes it extremely dangerous to use. +It also zeros trailing destination bytes out to the specified length. Instead, +use this similar function when possible, but note its different signature: +void pstrcpy(char *dest, int dest_buf_size, const char *src) Don't use strcat because it can't check for buffer overflows, but: char *pstrcat(char *buf, int buf_size, const char *s) From 610b823ef66b993660f1ab1447a769f190e4f3b3 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 3 Oct 2012 23:11:02 +0200 Subject: [PATCH 0745/2270] qemu-barrier: Fix compiler version check for future gcc versions The current check will give a wrong result for gcc-5.x with x < 4. Using QEMU_GNUC_PREREQ is simpler and fixes that issue. Signed-off-by: Stefan Weil Signed-off-by: Anthony Liguori --- qemu-barrier.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu-barrier.h b/qemu-barrier.h index 7e11197814..16f09429c3 100644 --- a/qemu-barrier.h +++ b/qemu-barrier.h @@ -19,7 +19,7 @@ * mfence on 32 bit as well, e.g. if built with -march=pentium-m. * However, on i386, there seem to be known bugs as recently as 4.3. * */ -#if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 +#if QEMU_GNUC_PREREQ(4, 4) #define smp_mb() __sync_synchronize() #else #define smp_mb() asm volatile("lock; addl $0,0(%%esp) " ::: "memory") From e0fea6b1e4df2067a51e08e67a17cb98a547287c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 1 Oct 2012 14:18:07 +0200 Subject: [PATCH 0746/2270] qtest: implement QTEST_STOP It is quite difficult to debug qtest test cases without extra wrapper scripts for QEMU or similar. This patch adds a simple environment variable-based trigger that sends a STOP signal to the QEMU instance under test, before attempting to connect to its QMP session. This will block execution of the testcase and give time to attach a debugger to the stopped QEMU process. Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- tests/libqtest.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/tests/libqtest.c b/tests/libqtest.c index 02d039218d..71b84c12dd 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -85,6 +85,22 @@ static int socket_accept(int sock) return ret; } +static pid_t qtest_qemu_pid(QTestState *s) +{ + FILE *f; + char buffer[1024]; + pid_t pid = -1; + + f = fopen(s->pid_file, "r"); + if (f) { + if (fgets(buffer, sizeof(buffer), f)) { + pid = atoi(buffer); + } + } + fclose(f); + return pid; +} + QTestState *qtest_init(const char *extra_args) { QTestState *s; @@ -136,25 +152,21 @@ QTestState *qtest_init(const char *extra_args) qtest_qmp(s, ""); qtest_qmp(s, "{ 'execute': 'qmp_capabilities' }"); + if (getenv("QTEST_STOP")) { + kill(qtest_qemu_pid(s), SIGSTOP); + } + return s; } void qtest_quit(QTestState *s) { - FILE *f; - char buffer[1024]; + int status; - f = fopen(s->pid_file, "r"); - if (f) { - if (fgets(buffer, sizeof(buffer), f)) { - pid_t pid = atoi(buffer); - int status = 0; - - kill(pid, SIGTERM); - waitpid(pid, &status, 0); - } - - fclose(f); + pid_t pid = qtest_qemu_pid(s); + if (pid != -1) { + kill(pid, SIGTERM); + waitpid(pid, &status, 0); } unlink(s->pid_file); From b6db4aca20e9af4f62c9c9e08b9b9672a6ed3390 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 1 Oct 2012 14:22:06 +0200 Subject: [PATCH 0747/2270] rtc: fix overflow in mktimegm When setting a date in 1980, Linux is actually disregarding the century byte and setting the year to 2080. This causes a year-2038 overflow in mktimegm. Fix this by doing the days-to-seconds computation in 64-bit math. Reported-by: Lucas Meneghel Rodrigues Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- cutils.c | 2 +- tests/rtc-test.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/cutils.c b/cutils.c index 8ef648f4b9..8edd8fa13c 100644 --- a/cutils.c +++ b/cutils.c @@ -115,7 +115,7 @@ time_t mktimegm(struct tm *tm) m += 12; y--; } - t = 86400 * (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + + t = 86400ULL * (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469); t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec; return t; diff --git a/tests/rtc-test.c b/tests/rtc-test.c index f23ac3a6cf..2b9aa63c1f 100644 --- a/tests/rtc-test.c +++ b/tests/rtc-test.c @@ -179,6 +179,50 @@ static void check_time(int wiggle) static int wiggle = 2; +static void set_year(void) +{ + /* Set BCD mode */ + cmos_write(RTC_REG_B, cmos_read(RTC_REG_B) & ~REG_B_DM); + cmos_write(RTC_REG_A, 0x76); + cmos_write(RTC_YEAR, 0x11); + cmos_write(RTC_MONTH, 0x02); + cmos_write(RTC_DAY_OF_MONTH, 0x02); + cmos_write(RTC_HOURS, 0x02); + cmos_write(RTC_MINUTES, 0x04); + cmos_write(RTC_SECONDS, 0x58); + cmos_write(RTC_REG_A, 0x26); + + g_assert_cmpint(cmos_read(RTC_HOURS), ==, 0x02); + g_assert_cmpint(cmos_read(RTC_MINUTES), ==, 0x04); + g_assert_cmpint(cmos_read(RTC_SECONDS), >=, 0x58); + g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02); + g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02); + g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x11); + + /* Set a date in 2080 to ensure there is no year-2038 overflow. */ + cmos_write(RTC_REG_A, 0x76); + cmos_write(RTC_YEAR, 0x80); + cmos_write(RTC_REG_A, 0x26); + + g_assert_cmpint(cmos_read(RTC_HOURS), ==, 0x02); + g_assert_cmpint(cmos_read(RTC_MINUTES), ==, 0x04); + g_assert_cmpint(cmos_read(RTC_SECONDS), >=, 0x58); + g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02); + g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02); + g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x80); + + cmos_write(RTC_REG_A, 0x76); + cmos_write(RTC_YEAR, 0x11); + cmos_write(RTC_REG_A, 0x26); + + g_assert_cmpint(cmos_read(RTC_HOURS), ==, 0x02); + g_assert_cmpint(cmos_read(RTC_MINUTES), ==, 0x04); + g_assert_cmpint(cmos_read(RTC_SECONDS), >=, 0x58); + g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02); + g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02); + g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x11); +} + static void bcd_check_time(void) { /* Set BCD mode */ @@ -269,6 +313,7 @@ int main(int argc, char **argv) qtest_add_func("/rtc/bcd/check-time", bcd_check_time); qtest_add_func("/rtc/dec/check-time", dec_check_time); qtest_add_func("/rtc/alarm-time", alarm_time); + qtest_add_func("/rtc/set-year", set_year); qtest_add_func("/rtc/fuzz-registers", fuzz_registers); ret = g_test_run(); From e67edb943f0c812530aaae2491da56f9542f928b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 1 Oct 2012 14:22:07 +0200 Subject: [PATCH 0748/2270] rtc: map CMOS index 0x37 to 0x32 on read and writes QEMU's attempt to implement the century byte cover two possible places for the byte. A common one on modern chipsets is 0x32, but QEMU also stores the value in 0x37 (apparently for IBM PS/2 compatibility---it's only been 25 years). To simplify the implementation of the century byte, store it only at 0x32 but remap transparently 0x37 to 0x32 when reading and writing from CMOS. Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- hw/mc146818rtc.c | 15 +++++++++------ hw/mc146818rtc_regs.h | 4 ++++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index d63554f896..a7d20d5c25 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -399,6 +399,10 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) s->cmos_data[s->cmos_index] = data; check_update_timer(s); break; + case RTC_IBM_PS2_CENTURY_BYTE: + s->cmos_index = RTC_CENTURY; + /* fall through */ + case RTC_CENTURY: case RTC_SECONDS: case RTC_MINUTES: case RTC_HOURS: @@ -598,6 +602,10 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr) return 0xff; } else { switch(s->cmos_index) { + case RTC_IBM_PS2_CENTURY_BYTE: + s->cmos_index = RTC_CENTURY; + /* fall through */ + case RTC_CENTURY: case RTC_SECONDS: case RTC_MINUTES: case RTC_HOURS: @@ -661,10 +669,6 @@ void rtc_set_memory(ISADevice *dev, int addr, int val) s->cmos_data[addr] = val; } -/* PC cmos mappings */ -#define REG_IBM_CENTURY_BYTE 0x32 -#define REG_IBM_PS2_CENTURY_BYTE 0x37 - static void rtc_set_date_from_host(ISADevice *dev) { RTCState *s = DO_UPCAST(RTCState, dev, dev); @@ -681,8 +685,7 @@ static void rtc_set_date_from_host(ISADevice *dev) rtc_set_cmos(s, &tm); val = rtc_to_bcd(s, (tm.tm_year / 100) + 19); - rtc_set_memory(dev, REG_IBM_CENTURY_BYTE, val); - rtc_set_memory(dev, REG_IBM_PS2_CENTURY_BYTE, val); + rtc_set_memory(dev, RTC_CENTURY, val); } static int rtc_post_load(void *opaque, int version_id) diff --git a/hw/mc146818rtc_regs.h b/hw/mc146818rtc_regs.h index fc10076ece..ccdee42b3c 100644 --- a/hw/mc146818rtc_regs.h +++ b/hw/mc146818rtc_regs.h @@ -44,6 +44,10 @@ #define RTC_REG_C 12 #define RTC_REG_D 13 +/* PC cmos mappings */ +#define RTC_CENTURY 0x32 +#define RTC_IBM_PS2_CENTURY_BYTE 0x37 + #define REG_A_UIP 0x80 #define REG_B_SET 0x80 From b8994faf2a8d6fc791669bb432bdb3a7a1711013 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 1 Oct 2012 14:22:08 +0200 Subject: [PATCH 0749/2270] rtc: implement century byte Implement the century byte in the RTC emulation, and test that it works. This leads to some annoying compatibility code because we need to treat a value of 2000 for the base_year property as "use the century byte properly" (which would be a value of 0). The century byte will now be always-zero, rather than always-20, for the MIPS Magnum machine whose base_year is 1980. Commit 42fc73a (Support epoch of 1980 in RTC emulation for MIPS Magnum, 2009-01-24) correctly said: With an epoch of 1980 and a year of 2009, one could argue that [the century byte] should hold either 0, 1, 19 or 20. NT 3.50 on MIPS does not read the century byte. so I picked the simplest and most sensible implementation which is to return 0 for 1980-2079, 1 for 2080-2179 and so on. Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- hw/mc146818rtc.c | 27 ++++++++++++++++++--------- tests/rtc-test.c | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index a7d20d5c25..332a77d4dc 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -519,7 +519,9 @@ static void rtc_get_time(RTCState *s, struct tm *tm) tm->tm_wday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1; tm->tm_mday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]); tm->tm_mon = rtc_from_bcd(s, s->cmos_data[RTC_MONTH]) - 1; - tm->tm_year = rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900; + tm->tm_year = + rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year + + rtc_from_bcd(s, s->cmos_data[RTC_CENTURY]) * 100 - 1900; } static void rtc_set_time(RTCState *s) @@ -552,10 +554,9 @@ static void rtc_set_cmos(RTCState *s, const struct tm *tm) s->cmos_data[RTC_DAY_OF_WEEK] = rtc_to_bcd(s, tm->tm_wday + 1); s->cmos_data[RTC_DAY_OF_MONTH] = rtc_to_bcd(s, tm->tm_mday); s->cmos_data[RTC_MONTH] = rtc_to_bcd(s, tm->tm_mon + 1); - year = (tm->tm_year - s->base_year) % 100; - if (year < 0) - year += 100; - s->cmos_data[RTC_YEAR] = rtc_to_bcd(s, year); + year = tm->tm_year + 1900 - s->base_year; + s->cmos_data[RTC_YEAR] = rtc_to_bcd(s, year % 100); + s->cmos_data[RTC_CENTURY] = rtc_to_bcd(s, year / 100); } static void rtc_update_time(RTCState *s) @@ -673,7 +674,6 @@ static void rtc_set_date_from_host(ISADevice *dev) { RTCState *s = DO_UPCAST(RTCState, dev, dev); struct tm tm; - int val; qemu_get_timedate(&tm, 0); @@ -683,9 +683,6 @@ static void rtc_set_date_from_host(ISADevice *dev) /* set the CMOS date */ rtc_set_cmos(s, &tm); - - val = rtc_to_bcd(s, (tm.tm_year / 100) + 19); - rtc_set_memory(dev, RTC_CENTURY, val); } static int rtc_post_load(void *opaque, int version_id) @@ -810,6 +807,18 @@ static int rtc_initfn(ISADevice *dev) s->cmos_data[RTC_REG_C] = 0x00; s->cmos_data[RTC_REG_D] = 0x80; + /* This is for historical reasons. The default base year qdev property + * was set to 2000 for most machine types before the century byte was + * implemented. + * + * This if statement means that the century byte will be always 0 + * (at least until 2079...) for base_year = 1980, but will be set + * correctly for base_year = 2000. + */ + if (s->base_year == 2000) { + s->base_year = 0; + } + rtc_set_date_from_host(dev); #ifdef TARGET_I386 diff --git a/tests/rtc-test.c b/tests/rtc-test.c index 2b9aa63c1f..7fdc94a3de 100644 --- a/tests/rtc-test.c +++ b/tests/rtc-test.c @@ -179,12 +179,13 @@ static void check_time(int wiggle) static int wiggle = 2; -static void set_year(void) +static void set_year_20xx(void) { /* Set BCD mode */ cmos_write(RTC_REG_B, cmos_read(RTC_REG_B) & ~REG_B_DM); cmos_write(RTC_REG_A, 0x76); cmos_write(RTC_YEAR, 0x11); + cmos_write(RTC_CENTURY, 0x20); cmos_write(RTC_MONTH, 0x02); cmos_write(RTC_DAY_OF_MONTH, 0x02); cmos_write(RTC_HOURS, 0x02); @@ -198,6 +199,7 @@ static void set_year(void) g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02); g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02); g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x11); + g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x20); /* Set a date in 2080 to ensure there is no year-2038 overflow. */ cmos_write(RTC_REG_A, 0x76); @@ -210,6 +212,7 @@ static void set_year(void) g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02); g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02); g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x80); + g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x20); cmos_write(RTC_REG_A, 0x76); cmos_write(RTC_YEAR, 0x11); @@ -221,6 +224,30 @@ static void set_year(void) g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02); g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02); g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x11); + g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x20); +} + +static void set_year_1980(void) +{ + /* Set BCD mode */ + cmos_write(RTC_REG_B, cmos_read(RTC_REG_B) & ~REG_B_DM); + cmos_write(RTC_REG_A, 0x76); + cmos_write(RTC_YEAR, 0x80); + cmos_write(RTC_CENTURY, 0x19); + cmos_write(RTC_MONTH, 0x02); + cmos_write(RTC_DAY_OF_MONTH, 0x02); + cmos_write(RTC_HOURS, 0x02); + cmos_write(RTC_MINUTES, 0x04); + cmos_write(RTC_SECONDS, 0x58); + cmos_write(RTC_REG_A, 0x26); + + g_assert_cmpint(cmos_read(RTC_HOURS), ==, 0x02); + g_assert_cmpint(cmos_read(RTC_MINUTES), ==, 0x04); + g_assert_cmpint(cmos_read(RTC_SECONDS), >=, 0x58); + g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02); + g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02); + g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x80); + g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x19); } static void bcd_check_time(void) @@ -313,7 +340,8 @@ int main(int argc, char **argv) qtest_add_func("/rtc/bcd/check-time", bcd_check_time); qtest_add_func("/rtc/dec/check-time", dec_check_time); qtest_add_func("/rtc/alarm-time", alarm_time); - qtest_add_func("/rtc/set-year", set_year); + qtest_add_func("/rtc/set-year/20xx", set_year_20xx); + qtest_add_func("/rtc/set-year/1980", set_year_1980); qtest_add_func("/rtc/fuzz-registers", fuzz_registers); ret = g_test_run(); From 4d5b97da35ecbfdad6fe1cbe7fdd7d71ef735602 Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Sat, 29 Sep 2012 13:36:21 +0800 Subject: [PATCH 0750/2270] cleanup useless return sentence This patch cleans up return sentences in the end of void functions. Reported-by: Paolo Bonzini Signed-off-by: Amos Kong Signed-off-by: Stefan Hajnoczi --- block/qed-table.c | 1 - blockdev.c | 1 - hw/9pfs/virtio-9p.c | 5 ----- hw/blizzard.c | 2 -- hw/bt-hci.c | 1 - hw/device-hotplug.c | 1 - hw/exynos4210_combiner.c | 4 ---- hw/exynos4210_gic.c | 4 ---- hw/exynos4210_mct.c | 2 -- hw/fdc.c | 2 -- hw/framebuffer.c | 1 - hw/ide/macio.c | 1 - hw/ivshmem.c | 4 ---- hw/megasas.c | 1 - hw/msix.c | 1 - hw/pflash_cfi01.c | 1 - hw/pflash_cfi02.c | 1 - hw/pxa2xx_keypad.c | 1 - hw/sb16.c | 1 - hw/scsi-disk.c | 2 -- hw/tcx.c | 1 - hw/usb/dev-uas.c | 2 -- hw/usb/hcd-ohci.c | 2 -- hw/usb/hcd-xhci.c | 1 - hw/xen_domainbuild.c | 1 - libcacard/vcard.c | 1 - libcacard/vcard_emul_nss.c | 3 --- libcacard/vreader.c | 1 - linux-user/signal.c | 2 -- os-posix.c | 1 - qemu-sockets.c | 1 - qga/commands-posix.c | 2 -- qga/commands-win32.c | 2 -- savevm.c | 1 - slirp/ip_input.c | 1 - slirp/tcp_input.c | 2 -- slirp/udp.c | 1 - target-unicore32/translate.c | 2 -- ui/vnc-auth-sasl.c | 1 - vl.c | 1 - xen-all.c | 1 - 41 files changed, 67 deletions(-) diff --git a/block/qed-table.c b/block/qed-table.c index ce07b05549..de845ec3d0 100644 --- a/block/qed-table.c +++ b/block/qed-table.c @@ -103,7 +103,6 @@ static void qed_write_table_cb(void *opaque, int ret) out: qemu_vfree(write_table_cb->table); gencb_complete(&write_table_cb->gencb, ret); - return; } /** diff --git a/blockdev.c b/blockdev.c index 5f18dfa97b..99828ad2bd 100644 --- a/blockdev.c +++ b/blockdev.c @@ -830,7 +830,6 @@ exit: QSIMPLEQ_FOREACH_SAFE(states, &snap_bdrv_states, entry, next) { g_free(states); } - return; } diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 4b52540116..8b9cdc96ed 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -505,7 +505,6 @@ static void virtfs_reset(V9fsPDU *pdu) error_report("9pfs:%s: One or more uncluncked fids " "found during reset", __func__); } - return; } #define P9_QID_TYPE_DIR 0x80 @@ -934,7 +933,6 @@ static void v9fs_version(void *opaque) out: complete_pdu(s, pdu, offset); v9fs_string_free(&version); - return; } static void v9fs_attach(void *opaque) @@ -1314,7 +1312,6 @@ out_nofid: g_free(wnames); g_free(qids); } - return; } static int32_t get_iounit(V9fsPDU *pdu, V9fsPath *path) @@ -2257,7 +2254,6 @@ static void v9fs_flush(void *opaque) free_pdu(pdu->s, cancel_pdu); } complete_pdu(s, pdu, 7); - return; } static void v9fs_link(void *opaque) @@ -2763,7 +2759,6 @@ out: put_fid(pdu, fidp); out_nofid: complete_pdu(s, pdu, retval); - return; } static void v9fs_mknod(void *opaque) diff --git a/hw/blizzard.c b/hw/blizzard.c index d1c9d81510..06e19b364b 100644 --- a/hw/blizzard.c +++ b/hw/blizzard.c @@ -878,8 +878,6 @@ void s1d13745_write_block(void *opaque, int dc, len -= 2; buf += 2; } - - return; } static void blizzard_update_display(void *opaque) diff --git a/hw/bt-hci.c b/hw/bt-hci.c index a3a7fb49e2..f19299a778 100644 --- a/hw/bt-hci.c +++ b/hw/bt-hci.c @@ -786,7 +786,6 @@ static void bt_hci_lmp_connection_request(struct bt_link_s *link) memcpy(¶ms.dev_class, &link->host->class, sizeof(params.dev_class)); params.link_type = ACL_LINK; bt_hci_event(hci, EVT_CONN_REQUEST, ¶ms, EVT_CONN_REQUEST_SIZE); - return; } static void bt_hci_conn_accept_timeout(void *opaque) diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c index 2bdc615b49..eec0fe3148 100644 --- a/hw/device-hotplug.c +++ b/hw/device-hotplug.c @@ -89,5 +89,4 @@ err: if (dinfo) { drive_put_ref(dinfo); } - return; } diff --git a/hw/exynos4210_combiner.c b/hw/exynos4210_combiner.c index 80af22cc33..60b33c7886 100644 --- a/hw/exynos4210_combiner.c +++ b/hw/exynos4210_combiner.c @@ -347,8 +347,6 @@ static void exynos4210_combiner_write(void *opaque, target_phys_addr_t offset, TARGET_FMT_plx "\n", offset); break; } - - return; } /* Get combiner group and bit from irq number */ @@ -380,8 +378,6 @@ static void exynos4210_combiner_handler(void *opaque, int irq, int level) } exynos4210_combiner_update(s, group_n); - - return; } static void exynos4210_combiner_reset(DeviceState *d) diff --git a/hw/exynos4210_gic.c b/hw/exynos4210_gic.c index 7d03dd9ae3..4fea09873a 100644 --- a/hw/exynos4210_gic.c +++ b/hw/exynos4210_gic.c @@ -193,8 +193,6 @@ static void exynos4210_irq_handler(void *opaque, int irq, int level) /* Bypass */ qemu_set_irq(s->board_irqs[irq], level); - - return; } /* @@ -410,8 +408,6 @@ static void exynos4210_irq_gate_handler(void *opaque, int irq, int level) } qemu_irq_lower(s->out); - - return; } static void exynos4210_irq_gate_reset(DeviceState *d) diff --git a/hw/exynos4210_mct.c b/hw/exynos4210_mct.c index 7a22b1f900..6f94ce230c 100644 --- a/hw/exynos4210_mct.c +++ b/hw/exynos4210_mct.c @@ -574,8 +574,6 @@ static void exynos4210_gfrc_event(void *opaque) exynos4210_gfrc_set_count(&s->g_timer, distance); exynos4210_gfrc_start(&s->g_timer); - - return; } /* diff --git a/hw/fdc.c b/hw/fdc.c index 43b0f20503..25a49e350c 100644 --- a/hw/fdc.c +++ b/hw/fdc.c @@ -1286,8 +1286,6 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction) fdctrl->msr |= FD_MSR_DIO; /* IO based transfer: calculate len */ fdctrl_raise_irq(fdctrl, FD_SR0_SEEK); - - return; } /* Prepare a transfer of deleted data */ diff --git a/hw/framebuffer.c b/hw/framebuffer.c index 85a00a5798..27fa6f51fb 100644 --- a/hw/framebuffer.c +++ b/hw/framebuffer.c @@ -107,5 +107,4 @@ void framebuffer_update_display( DIRTY_MEMORY_VGA); *first_row = first; *last_row = last; - return; } diff --git a/hw/ide/macio.c b/hw/ide/macio.c index 848cb31429..f228725142 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -89,7 +89,6 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) done: bdrv_acct_done(s->bs, &s->acct); io->dma_end(opaque); - return; } static void pmac_ide_transfer_cb(void *opaque, int ret) diff --git a/hw/ivshmem.c b/hw/ivshmem.c index 59f1aa4265..5c4ccb85f0 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -149,7 +149,6 @@ static void ivshmem_IntrStatus_write(IVShmemState *s, uint32_t val) s->intrstatus = val; ivshmem_update_irq(s, val); - return; } static uint32_t ivshmem_IntrStatus_read(IVShmemState *s) @@ -510,8 +509,6 @@ static void ivshmem_read(void *opaque, const uint8_t * buf, int flags) if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) { ivshmem_add_eventfd(s, incoming_posn, guest_max_eventfd); } - - return; } /* Select the MSI-X vectors used by device. @@ -536,7 +533,6 @@ static void ivshmem_reset(DeviceState *d) s->intrstatus = 0; ivshmem_use_msix(s); - return; } static uint64_t ivshmem_get_size(IVShmemState * s) { diff --git a/hw/megasas.c b/hw/megasas.c index c728aea699..0e57740fd2 100644 --- a/hw/megasas.c +++ b/hw/megasas.c @@ -652,7 +652,6 @@ static void megasas_finish_dcmd(MegasasCmd *cmd, uint32_t iov_size) } } cmd->iov_size = 0; - return; } static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) diff --git a/hw/msix.c b/hw/msix.c index d812094139..b623cb597c 100644 --- a/hw/msix.c +++ b/hw/msix.c @@ -366,7 +366,6 @@ void msix_uninit(PCIDevice *dev, MemoryRegion *table_bar, MemoryRegion *pba_bar) g_free(dev->msix_entry_used); dev->msix_entry_used = NULL; dev->cap_present &= ~QEMU_PCI_CAP_MSIX; - return; } void msix_uninit_exclusive_bar(PCIDevice *dev) diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index 855890d1f1..3b437da9c3 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -442,7 +442,6 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset, pfl->bypass = 0; pfl->wcycle = 0; pfl->cmd = 0; - return; } diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c index 8cb1549587..39337ec304 100644 --- a/hw/pflash_cfi02.c +++ b/hw/pflash_cfi02.c @@ -474,7 +474,6 @@ static void pflash_write (pflash_t *pfl, target_phys_addr_t offset, do_bypass: pfl->wcycle = 2; pfl->cmd = 0; - return; } diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c index 59db02584e..1a997c9c83 100644 --- a/hw/pxa2xx_keypad.c +++ b/hw/pxa2xx_keypad.c @@ -172,7 +172,6 @@ static void pxa27x_keyboard_event (PXA2xxKeyPadState *kp, int keycode) kp->kpc |= KPC_MI; qemu_irq_raise(kp->irq); } - return; } static uint64_t pxa2xx_keypad_read(void *opaque, target_phys_addr_t offset, diff --git a/hw/sb16.c b/hw/sb16.c index c81455d7f3..523ab0d5fd 100644 --- a/hw/sb16.c +++ b/hw/sb16.c @@ -822,7 +822,6 @@ static void complete (SB16State *s) ldebug ("\n"); s->cmd = -1; - return; } static void legacy_reset (SB16State *s) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 99bb02ebf8..1b0afa6352 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -1437,7 +1437,6 @@ invalid_param_len: invalid_field: scsi_check_condition(r, SENSE_CODE(INVALID_FIELD)); - return; } static inline bool check_lba_range(SCSIDiskState *s, @@ -1535,7 +1534,6 @@ static void scsi_disk_emulate_unmap(SCSIDiskReq *r, uint8_t *inbuf) invalid_param_len: scsi_check_condition(r, SENSE_CODE(INVALID_PARAM_LEN)); - return; } static void scsi_disk_emulate_write_data(SCSIRequest *req) diff --git a/hw/tcx.c b/hw/tcx.c index 93994d6440..2db2db1235 100644 --- a/hw/tcx.c +++ b/hw/tcx.c @@ -472,7 +472,6 @@ static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint64_t val, default: break; } - return; } static const MemoryRegionOps tcx_dac_ops = { diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index 5a0057a36b..4389380e95 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -576,7 +576,6 @@ bad_target: */ usb_uas_queue_response(uas, req->tag, UAS_RC_INVALID_INFO_UNIT, 0); g_free(req); - return; } static void usb_uas_task(UASDevice *uas, uas_ui *ui) @@ -640,7 +639,6 @@ bad_target: incorrect_lun: usb_uas_queue_response(uas, tag, UAS_RC_INCORRECT_LUN, 0); - return; } static int usb_uas_handle_data(USBDevice *dev, USBPacket *p) diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index c36184ae4f..59c7055cb5 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -1470,8 +1470,6 @@ static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val) if (old_state != port->ctrl) ohci_set_interrupt(ohci, OHCI_INTR_RHSC); - - return; } static uint64_t ohci_mem_read(void *opaque, diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index e79a8724c5..3a41b067c4 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -807,7 +807,6 @@ static void xhci_events_update(XHCIState *xhci, int v) DPRINTF("xhci_events_update(): event ring no longer full\n"); intr->er_full = 0; } - return; } static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v) diff --git a/hw/xen_domainbuild.c b/hw/xen_domainbuild.c index a6a12e5930..db1497469a 100644 --- a/hw/xen_domainbuild.c +++ b/hw/xen_domainbuild.c @@ -153,7 +153,6 @@ static void xen_domain_poll(void *opaque) quit: qemu_system_shutdown_request(); - return; } static int xen_domain_watcher(void) diff --git a/libcacard/vcard.c b/libcacard/vcard.c index b02556ee0c..539177bb4c 100644 --- a/libcacard/vcard.c +++ b/libcacard/vcard.c @@ -200,7 +200,6 @@ vcard_free(VCard *vcard) } vcard_buffer_response_delete(vcard->vcard_buffer_response); g_free(vcard); - return; } void diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c index 802cae3a29..b861c5afcc 100644 --- a/libcacard/vcard_emul_nss.c +++ b/libcacard/vcard_emul_nss.c @@ -168,7 +168,6 @@ vcard_emul_delete_key(VCardKey *key) if (key->slot) { PK11_FreeSlot(key->slot); } - return; } /* @@ -418,7 +417,6 @@ vcard_emul_reset(VCard *card, VCardPower power) /* TODO: we may also need to send insertion/removal events? */ slot = vcard_emul_card_get_slot(card); PK11_Logout(slot); /* NOTE: ignoring SECStatus return value */ - return; } @@ -535,7 +533,6 @@ vcard_emul_get_atr(VCard *card, unsigned char *atr, int *atr_len) memcpy(atr, nss_atr, len); *atr_len = len; - return; } /* diff --git a/libcacard/vreader.c b/libcacard/vreader.c index ec126dfa46..96d2407e78 100644 --- a/libcacard/vreader.c +++ b/libcacard/vreader.c @@ -93,7 +93,6 @@ vreader_free(VReader *reader) reader->reader_private_free(reader->reader_private); } g_free(reader); - return; } static VCard * diff --git a/linux-user/signal.c b/linux-user/signal.c index 78691473fa..15bc4e8f62 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -2762,7 +2762,6 @@ static void setup_frame(int sig, struct target_sigaction * ka, give_sigsegv: unlock_user_struct(frame, frame_addr, 1); force_sig(TARGET_SIGSEGV/*, current*/); - return; } long do_sigreturn(CPUMIPSState *regs) @@ -2871,7 +2870,6 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, give_sigsegv: unlock_user_struct(frame, frame_addr, 1); force_sig(TARGET_SIGSEGV/*, current*/); - return; } long do_rt_sigreturn(CPUMIPSState *env) diff --git a/os-posix.c b/os-posix.c index eabccb8fe0..178e7caa4a 100644 --- a/os-posix.c +++ b/os-posix.c @@ -194,7 +194,6 @@ void os_parse_cmd_args(int index, const char *optarg) break; #endif } - return; } static void change_process_uid(void) diff --git a/qemu-sockets.c b/qemu-sockets.c index 0f59490859..2b1ed2f0e9 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -266,7 +266,6 @@ static void wait_for_connect(void *opaque) s->callback(s->fd, s->opaque); } g_free(s); - return; } static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, diff --git a/qga/commands-posix.c b/qga/commands-posix.c index ce9042123c..b0eec74148 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -988,8 +988,6 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err) void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err) { error_set(err, QERR_UNSUPPORTED); - - return; } #endif diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 54bc5462e2..5bd8fb27f2 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -180,8 +180,6 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err) void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err) { error_set(err, QERR_UNSUPPORTED); - - return; } typedef enum { diff --git a/savevm.c b/savevm.c index c7fe283145..31fd2e0ad3 100644 --- a/savevm.c +++ b/savevm.c @@ -2201,7 +2201,6 @@ void qmp_xen_save_devices_state(const char *filename, Error **errp) the_end: if (saved_vm_running) vm_start(); - return; } int load_vmstate(const char *name) diff --git a/slirp/ip_input.c b/slirp/ip_input.c index ce24faf165..6f4cff8fdd 100644 --- a/slirp/ip_input.c +++ b/slirp/ip_input.c @@ -213,7 +213,6 @@ ip_input(struct mbuf *m) return; bad: m_free(m); - return; } #define iptofrag(P) ((struct ipasfrag *)(((char*)(P)) - sizeof(struct qlink))) diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c index 942aaf44f1..6440eae7fa 100644 --- a/slirp/tcp_input.c +++ b/slirp/tcp_input.c @@ -1281,8 +1281,6 @@ drop: * Drop space held by incoming segment and return. */ m_free(m); - - return; } static void diff --git a/slirp/udp.c b/slirp/udp.c index ced509656d..9286cb7d31 100644 --- a/slirp/udp.c +++ b/slirp/udp.c @@ -231,7 +231,6 @@ udp_input(register struct mbuf *m, int iphlen) return; bad: m_free(m); - return; } int udp_output2(struct socket *so, struct mbuf *m, diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index 36f4f2f966..c3cdafa18e 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -1932,8 +1932,6 @@ static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s) } ILLEGAL; } - - return; } /* generate intermediate code in gen_opc_buf and gen_opparam_buf for diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c index 8fba7702c2..9a0ad30a94 100644 --- a/ui/vnc-auth-sasl.c +++ b/ui/vnc-auth-sasl.c @@ -619,7 +619,6 @@ void start_auth_sasl(VncState *vs) authabort: vnc_client_error(vs); - return; } diff --git a/vl.c b/vl.c index 8d305ca59b..29e05a303b 100644 --- a/vl.c +++ b/vl.c @@ -1023,7 +1023,6 @@ static void numa_add(const char *optarg) } nb_numa_nodes++; } - return; } static void smp_parse(const char *optarg) diff --git a/xen-all.c b/xen-all.c index e6308be23a..bcb7ef7c84 100644 --- a/xen-all.c +++ b/xen-all.c @@ -1092,7 +1092,6 @@ static void xen_read_physmap(XenIOState *state) QLIST_INSERT_HEAD(&state->physmap, physmap, list); } free(entries); - return; } int xen_hvm_init(void) From da665c99f1b5d3247f7f9f8a24f3eb1fda94e1e4 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 3 Oct 2012 11:19:39 +0200 Subject: [PATCH 0751/2270] hw: Add missing 'static' attribute for QEMUMachine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was missing for leon3 and mips_fulong2e. Signed-off-by: Stefan Weil Reviewed-by: Andreas Färber Signed-off-by: Stefan Hajnoczi --- hw/leon3.c | 2 +- hw/mips_fulong2e.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/leon3.c b/hw/leon3.c index 878d3aa557..7a9729dc28 100644 --- a/hw/leon3.c +++ b/hw/leon3.c @@ -210,7 +210,7 @@ static void leon3_generic_hw_init(ram_addr_t ram_size, } } -QEMUMachine leon3_generic_machine = { +static QEMUMachine leon3_generic_machine = { .name = "leon3_generic", .desc = "Leon-3 generic", .init = leon3_generic_hw_init, diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c index 38e4b86150..d4a8672f23 100644 --- a/hw/mips_fulong2e.c +++ b/hw/mips_fulong2e.c @@ -392,7 +392,7 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device, network_init(); } -QEMUMachine mips_fulong2e_machine = { +static QEMUMachine mips_fulong2e_machine = { .name = "fulong2e", .desc = "Fulong 2e mini pc", .init = mips_fulong2e_init, From 8e7e2b14e7c86cdceb337cf7f5c4c351ab350775 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 3 Oct 2012 23:11:02 +0200 Subject: [PATCH 0752/2270] qemu-barrier: Fix compiler version check for future gcc versions The current check will give a wrong result for gcc-5.x with x < 4. Using QEMU_GNUC_PREREQ is simpler and fixes that issue. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- qemu-barrier.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu-barrier.h b/qemu-barrier.h index 7e11197814..16f09429c3 100644 --- a/qemu-barrier.h +++ b/qemu-barrier.h @@ -19,7 +19,7 @@ * mfence on 32 bit as well, e.g. if built with -march=pentium-m. * However, on i386, there seem to be known bugs as recently as 4.3. * */ -#if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 +#if QEMU_GNUC_PREREQ(4, 4) #define smp_mb() __sync_synchronize() #else #define smp_mb() asm volatile("lock; addl $0,0(%%esp) " ::: "memory") From c36b7de64dfb106ee0384d2634fd4037218ffbca Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 16:15:21 -0300 Subject: [PATCH 0753/2270] qdev: kill bogus comment When the DeviceInfo code was removed, the comment describing qdev_subclass_init() was left in the code by mistake. Remove it. Cc: qemu-trivial@nongnu.org Signed-off-by: Eduardo Habkost Signed-off-by: Stefan Hajnoczi --- hw/qdev.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/qdev.c b/hw/qdev.c index b5a52ac503..a7270a5cb4 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -34,7 +34,6 @@ int qdev_hotplug = 0; static bool qdev_hot_added = false; static bool qdev_hot_removed = false; -/* Register a new device type. */ const VMStateDescription *qdev_get_vmsd(DeviceState *dev) { DeviceClass *dc = DEVICE_GET_CLASS(dev); From 02cd521f6e207bd8843a7c1309f6d065cf01c6ee Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 4 Oct 2012 22:49:43 +0200 Subject: [PATCH 0754/2270] versatilepb: Use symbolic indices for ARM PIC It is more readable, and all other code does it like that, too. Signed-off-by: Stefan Weil Reviewed-by: Peter Maydell Signed-off-by: Stefan Hajnoczi --- hw/versatilepb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/versatilepb.c b/hw/versatilepb.c index 7a92034718..b3f8077146 100644 --- a/hw/versatilepb.c +++ b/hw/versatilepb.c @@ -211,7 +211,8 @@ static void versatile_init(ram_addr_t ram_size, cpu_pic = arm_pic_init_cpu(cpu); dev = sysbus_create_varargs("pl190", 0x10140000, - cpu_pic[0], cpu_pic[1], NULL); + cpu_pic[ARM_PIC_CPU_IRQ], + cpu_pic[ARM_PIC_CPU_FIQ], NULL); for (n = 0; n < 32; n++) { pic[n] = qdev_get_gpio_in(dev, n); } From 6fd2a026fbf46ed5927a57e3e043a2039a0651d0 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 5 Oct 2012 15:04:43 +0100 Subject: [PATCH 0755/2270] cpu_dump_state: move DUMP_FPU and DUMP_CCOP flags from x86-only to generic Move the DUMP_FPU and DUMP_CCOP flags for cpu_dump_state() from being x86-specific flags to being generic ones. This allows us to drop some TARGET_I386 ifdefs in various places, and means that we can (potentially) be more consistent across architectures about which monitor commands or debug abort printouts include FPU register contents and info about QEMU's condition-code optimisations. Signed-off-by: Peter Maydell --- cpu-all.h | 3 +++ cpu-exec.c | 2 +- cpus.c | 6 +----- exec.c | 12 ++---------- monitor.c | 8 +------- target-i386/cpu.c | 2 +- target-i386/cpu.h | 4 ---- target-i386/helper.c | 4 ++-- target-i386/seg_helper.c | 4 ++-- target-i386/smm_helper.c | 4 ++-- 10 files changed, 15 insertions(+), 34 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index 74d3681c29..2b99682677 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -356,6 +356,9 @@ CPUArchState *cpu_copy(CPUArchState *env); CPUArchState *qemu_get_cpu(int cpu); #define CPU_DUMP_CODE 0x00010000 +#define CPU_DUMP_FPU 0x00020000 /* dump FPU register state, not just integer */ +/* dump info about TCG QEMU's condition code optimization state */ +#define CPU_DUMP_CCOP 0x00040000 void cpu_dump_state(CPUArchState *env, FILE *f, fprintf_function cpu_fprintf, int flags); diff --git a/cpu-exec.c b/cpu-exec.c index 134b3c4fcf..252da86882 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -552,7 +552,7 @@ int cpu_exec(CPUArchState *env) #if defined(TARGET_I386) env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP) | (DF & DF_MASK); - log_cpu_state(env, X86_DUMP_CCOP); + log_cpu_state(env, CPU_DUMP_CCOP); env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); #elif defined(TARGET_M68K) cpu_m68k_flush_flags(env, env->cc_op); diff --git a/cpus.c b/cpus.c index 4b726ef4e7..5ba87fe0cc 100644 --- a/cpus.c +++ b/cpus.c @@ -395,11 +395,7 @@ void hw_error(const char *fmt, ...) fprintf(stderr, "\n"); for(env = first_cpu; env != NULL; env = env->next_cpu) { fprintf(stderr, "CPU #%d:\n", env->cpu_index); -#ifdef TARGET_I386 - cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU); -#else - cpu_dump_state(env, stderr, fprintf, 0); -#endif + cpu_dump_state(env, stderr, fprintf, CPU_DUMP_FPU); } va_end(ap); abort(); diff --git a/exec.c b/exec.c index 1114a0932b..7899042ce9 100644 --- a/exec.c +++ b/exec.c @@ -1742,20 +1742,12 @@ void cpu_abort(CPUArchState *env, const char *fmt, ...) fprintf(stderr, "qemu: fatal: "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); -#ifdef TARGET_I386 - cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP); -#else - cpu_dump_state(env, stderr, fprintf, 0); -#endif + cpu_dump_state(env, stderr, fprintf, CPU_DUMP_FPU | CPU_DUMP_CCOP); if (qemu_log_enabled()) { qemu_log("qemu: fatal: "); qemu_log_vprintf(fmt, ap2); qemu_log("\n"); -#ifdef TARGET_I386 - log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP); -#else - log_cpu_state(env, 0); -#endif + log_cpu_state(env, CPU_DUMP_FPU | CPU_DUMP_CCOP); qemu_log_flush(); qemu_log_close(); } diff --git a/monitor.c b/monitor.c index a0e3ffb924..131b325f1b 100644 --- a/monitor.c +++ b/monitor.c @@ -898,13 +898,7 @@ static void do_info_registers(Monitor *mon) { CPUArchState *env; env = mon_get_cpu(); -#ifdef TARGET_I386 - cpu_dump_state(env, (FILE *)mon, monitor_fprintf, - X86_DUMP_FPU); -#else - cpu_dump_state(env, (FILE *)mon, monitor_fprintf, - 0); -#endif + cpu_dump_state(env, (FILE *)mon, monitor_fprintf, CPU_DUMP_FPU); } static void do_info_jit(Monitor *mon) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index bb1e44eb01..f3708e63b7 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1759,7 +1759,7 @@ static void x86_cpu_reset(CPUState *s) if (qemu_loglevel_mask(CPU_LOG_RESET)) { qemu_log("CPU Reset (CPU %d)\n", env->cpu_index); - log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP); + log_cpu_state(env, CPU_DUMP_FPU | CPU_DUMP_CCOP); } xcc->parent_reset(s); diff --git a/target-i386/cpu.h b/target-i386/cpu.h index e4a7d5b6e4..871c270116 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -995,10 +995,6 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4); void cpu_smm_update(CPUX86State *env); uint64_t cpu_get_tsc(CPUX86State *env); -/* used to debug */ -#define X86_DUMP_FPU 0x0001 /* dump FPU state too */ -#define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */ - #define TARGET_PAGE_BITS 12 #ifdef TARGET_X86_64 diff --git a/target-i386/helper.c b/target-i386/helper.c index c635667d60..2ee7c6d1b1 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -284,7 +284,7 @@ void cpu_dump_state(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf, cpu_fprintf(f, "\nDR6=" TARGET_FMT_lx " DR7=" TARGET_FMT_lx "\n", env->dr[6], env->dr[7]); } - if (flags & X86_DUMP_CCOP) { + if (flags & CPU_DUMP_CCOP) { if ((unsigned)env->cc_op < CC_OP_NB) snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]); else @@ -303,7 +303,7 @@ void cpu_dump_state(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf, } } cpu_fprintf(f, "EFER=%016" PRIx64 "\n", env->efer); - if (flags & X86_DUMP_FPU) { + if (flags & CPU_DUMP_FPU) { int fptag; fptag = 0; for(i = 0; i < 8; i++) { diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c index 5fff8d59c6..ff9337441b 100644 --- a/target-i386/seg_helper.c +++ b/target-i386/seg_helper.c @@ -31,7 +31,7 @@ #ifdef DEBUG_PCALL # define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__) # define LOG_PCALL_STATE(env) \ - log_cpu_state_mask(CPU_LOG_PCALL, (env), X86_DUMP_CCOP) + log_cpu_state_mask(CPU_LOG_PCALL, (env), CPU_DUMP_CCOP) #else # define LOG_PCALL(...) do { } while (0) # define LOG_PCALL_STATE(env) do { } while (0) @@ -1177,7 +1177,7 @@ static void do_interrupt_all(CPUX86State *env, int intno, int is_int, qemu_log(" EAX=" TARGET_FMT_lx, EAX); } qemu_log("\n"); - log_cpu_state(env, X86_DUMP_CCOP); + log_cpu_state(env, CPU_DUMP_CCOP); #if 0 { int i; diff --git a/target-i386/smm_helper.c b/target-i386/smm_helper.c index 8b04eb2e00..eea2fe9782 100644 --- a/target-i386/smm_helper.c +++ b/target-i386/smm_helper.c @@ -47,7 +47,7 @@ void do_smm_enter(CPUX86State *env) int i, offset; qemu_log_mask(CPU_LOG_INT, "SMM: enter\n"); - log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP); + log_cpu_state_mask(CPU_LOG_INT, env, CPU_DUMP_CCOP); env->hflags |= HF_SMM_MASK; cpu_smm_update(env); @@ -295,7 +295,7 @@ void helper_rsm(CPUX86State *env) cpu_smm_update(env); qemu_log_mask(CPU_LOG_INT, "SMM: after RSM\n"); - log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP); + log_cpu_state_mask(CPU_LOG_INT, env, CPU_DUMP_CCOP); } #endif /* !CONFIG_USER_ONLY */ From f2617cfc237a7f7e72bd3791ed1f3d35f496bb22 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 5 Oct 2012 15:04:44 +0100 Subject: [PATCH 0756/2270] target-arm: Reinstate display of VFP registers in cpu_dump_state Reinstate the display of VFP registers in cpu_dump_state(), if the CPU has them (this code had been #if 0'd out a for a long time). We drop the attempt ot display the values as floating point, since this makes assumptions about the host 'float' and 'double' formats and is not done by eg the i386 cpu_dump_state(). This display is gated on the CPU_DUMP_FPU flag, as for x86. Signed-off-by: Peter Maydell --- target-arm/translate.c | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/target-arm/translate.c b/target-arm/translate.c index 5fded491ec..bb53e35db3 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -9970,19 +9970,6 @@ void cpu_dump_state(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf, int flags) { int i; -#if 0 - union { - uint32_t i; - float s; - } s0, s1; - CPU_DoubleU d; - /* ??? This assumes float64 and double have the same layout. - Oh well, it's only debug dumps. */ - union { - float64 f64; - double d; - } d0; -#endif uint32_t psr; for(i=0;i<16;i++) { @@ -10002,20 +9989,23 @@ void cpu_dump_state(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf, psr & CPSR_T ? 'T' : 'A', cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26); -#if 0 - for (i = 0; i < 16; i++) { - d.d = env->vfp.regs[i]; - s0.i = d.l.lower; - s1.i = d.l.upper; - d0.f64 = d.d; - cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n", - i * 2, (int)s0.i, s0.s, - i * 2 + 1, (int)s1.i, s1.s, - i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower, - d0.d); + if (flags & CPU_DUMP_FPU) { + int numvfpregs = 0; + if (arm_feature(env, ARM_FEATURE_VFP)) { + numvfpregs += 16; + } + if (arm_feature(env, ARM_FEATURE_VFP3)) { + numvfpregs += 16; + } + for (i = 0; i < numvfpregs; i++) { + uint64_t v = float64_val(env->vfp.regs[i]); + cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n", + i * 2, (uint32_t)v, + i * 2 + 1, (uint32_t)(v >> 32), + i, v); + } + cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]); } - cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]); -#endif } void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos) From 66c374de8a949062bfb1792f7e685a168c61c416 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 5 Oct 2012 15:04:44 +0100 Subject: [PATCH 0757/2270] target-arm: use globals for CC flags Use globals for CC flags instead of loading/storing them each they are accessed. This allows some optimizations to be performed by the TCG optimization passes. Signed-off-by: Aurelien Jarno Signed-off-by: Peter Maydell --- target-arm/translate.c | 127 +++++++++++++++-------------------------- 1 file changed, 46 insertions(+), 81 deletions(-) diff --git a/target-arm/translate.c b/target-arm/translate.c index bb53e35db3..1055931659 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -85,6 +85,7 @@ static TCGv_ptr cpu_env; /* We reuse the same 64-bit temporaries for efficiency. */ static TCGv_i64 cpu_V0, cpu_V1, cpu_M0; static TCGv_i32 cpu_R[16]; +static TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF; static TCGv_i32 cpu_exclusive_addr; static TCGv_i32 cpu_exclusive_val; static TCGv_i32 cpu_exclusive_high; @@ -115,6 +116,11 @@ void arm_translate_init(void) offsetof(CPUARMState, regs[i]), regnames[i]); } + cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, CF), "CF"); + cpu_NF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, NF), "NF"); + cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF"); + cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF"); + cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, exclusive_addr), "exclusive_addr"); cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0, @@ -369,53 +375,39 @@ static void gen_add16(TCGv t0, TCGv t1) tcg_temp_free_i32(t1); } -#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, CF)) - /* Set CF to the top bit of var. */ static void gen_set_CF_bit31(TCGv var) { - TCGv tmp = tcg_temp_new_i32(); - tcg_gen_shri_i32(tmp, var, 31); - gen_set_CF(tmp); - tcg_temp_free_i32(tmp); + tcg_gen_shri_i32(cpu_CF, var, 31); } /* Set N and Z flags from var. */ static inline void gen_logic_CC(TCGv var) { - tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, NF)); - tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, ZF)); + 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) { - TCGv tmp; tcg_gen_add_i32(t0, t0, t1); - tmp = load_cpu_field(CF); - tcg_gen_add_i32(t0, t0, tmp); - tcg_temp_free_i32(tmp); + tcg_gen_add_i32(t0, t0, cpu_CF); } /* dest = T0 + T1 + CF. */ static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1) { - TCGv tmp; tcg_gen_add_i32(dest, t0, t1); - tmp = load_cpu_field(CF); - tcg_gen_add_i32(dest, dest, tmp); - tcg_temp_free_i32(tmp); + tcg_gen_add_i32(dest, dest, cpu_CF); } /* dest = T0 - T1 + CF - 1. */ static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1) { - TCGv tmp; tcg_gen_sub_i32(dest, t0, t1); - tmp = load_cpu_field(CF); - tcg_gen_add_i32(dest, dest, tmp); + tcg_gen_add_i32(dest, dest, cpu_CF); tcg_gen_subi_i32(dest, dest, 1); - tcg_temp_free_i32(tmp); } /* FIXME: Implement this natively. */ @@ -423,16 +415,14 @@ static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1) static void shifter_out_im(TCGv var, int shift) { - TCGv tmp = tcg_temp_new_i32(); if (shift == 0) { - tcg_gen_andi_i32(tmp, var, 1); + tcg_gen_andi_i32(cpu_CF, var, 1); } else { - tcg_gen_shri_i32(tmp, var, shift); - if (shift != 31) - tcg_gen_andi_i32(tmp, tmp, 1); + tcg_gen_shri_i32(cpu_CF, var, shift); + if (shift != 31) { + tcg_gen_andi_i32(cpu_CF, cpu_CF, 1); + } } - gen_set_CF(tmp); - tcg_temp_free_i32(tmp); } /* Shift by immediate. Includes special handling for shift == 0. */ @@ -449,8 +439,7 @@ static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags) case 1: /* LSR */ if (shift == 0) { if (flags) { - tcg_gen_shri_i32(var, var, 31); - gen_set_CF(var); + tcg_gen_shri_i32(cpu_CF, var, 31); } tcg_gen_movi_i32(var, 0); } else { @@ -474,11 +463,11 @@ 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 = load_cpu_field(CF); + TCGv tmp = tcg_temp_new_i32(); if (flags) shifter_out_im(var, 0); tcg_gen_shri_i32(var, var, 1); - tcg_gen_shli_i32(tmp, tmp, 31); + tcg_gen_shli_i32(tmp, cpu_CF, 31); tcg_gen_or_i32(var, var, tmp); tcg_temp_free_i32(tmp); } @@ -603,99 +592,75 @@ 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 tmp2; int inv; switch (cc) { case 0: /* eq: Z */ - tmp = load_cpu_field(ZF); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); + tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label); break; case 1: /* ne: !Z */ - tmp = load_cpu_field(ZF); - tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label); + tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label); break; case 2: /* cs: C */ - tmp = load_cpu_field(CF); - tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label); + tcg_gen_brcondi_i32(TCG_COND_NE, cpu_CF, 0, label); break; case 3: /* cc: !C */ - tmp = load_cpu_field(CF); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); + tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label); break; case 4: /* mi: N */ - tmp = load_cpu_field(NF); - tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); + tcg_gen_brcondi_i32(TCG_COND_LT, cpu_NF, 0, label); break; case 5: /* pl: !N */ - tmp = load_cpu_field(NF); - tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); + tcg_gen_brcondi_i32(TCG_COND_GE, cpu_NF, 0, label); break; case 6: /* vs: V */ - tmp = load_cpu_field(VF); - tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); + tcg_gen_brcondi_i32(TCG_COND_LT, cpu_VF, 0, label); break; case 7: /* vc: !V */ - tmp = load_cpu_field(VF); - tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); + tcg_gen_brcondi_i32(TCG_COND_GE, cpu_VF, 0, label); break; case 8: /* hi: C && !Z */ inv = gen_new_label(); - tmp = load_cpu_field(CF); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv); - tcg_temp_free_i32(tmp); - tmp = load_cpu_field(ZF); - tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label); + tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, inv); + tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label); gen_set_label(inv); break; case 9: /* ls: !C || Z */ - tmp = load_cpu_field(CF); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); - tcg_temp_free_i32(tmp); - tmp = load_cpu_field(ZF); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); + tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label); + tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label); break; case 10: /* ge: N == V -> N ^ V == 0 */ - tmp = load_cpu_field(VF); - tmp2 = load_cpu_field(NF); - tcg_gen_xor_i32(tmp, tmp, tmp2); - tcg_temp_free_i32(tmp2); + tmp = tcg_temp_new_i32(); + tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF); tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); + tcg_temp_free_i32(tmp); break; case 11: /* lt: N != V -> N ^ V != 0 */ - tmp = load_cpu_field(VF); - tmp2 = load_cpu_field(NF); - tcg_gen_xor_i32(tmp, tmp, tmp2); - tcg_temp_free_i32(tmp2); + tmp = tcg_temp_new_i32(); + tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF); tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); + tcg_temp_free_i32(tmp); break; case 12: /* gt: !Z && N == V */ inv = gen_new_label(); - tmp = load_cpu_field(ZF); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv); - tcg_temp_free_i32(tmp); - tmp = load_cpu_field(VF); - tmp2 = load_cpu_field(NF); - tcg_gen_xor_i32(tmp, tmp, tmp2); - tcg_temp_free_i32(tmp2); + tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, inv); + tmp = tcg_temp_new_i32(); + tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF); tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); + tcg_temp_free_i32(tmp); gen_set_label(inv); break; case 13: /* le: Z || N != V */ - tmp = load_cpu_field(ZF); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); - tcg_temp_free_i32(tmp); - tmp = load_cpu_field(VF); - tmp2 = load_cpu_field(NF); - tcg_gen_xor_i32(tmp, tmp, tmp2); - tcg_temp_free_i32(tmp2); + tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label); + tmp = tcg_temp_new_i32(); + tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF); tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); + tcg_temp_free_i32(tmp); break; default: fprintf(stderr, "Bad condition code 0x%x\n", cc); abort(); } - tcg_temp_free_i32(tmp); } static const uint8_t table_logic_cc[16] = { From 72485ec4f63d86c428f9223fc966bd7d2cc8100c Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 5 Oct 2012 15:04:44 +0100 Subject: [PATCH 0758/2270] target-arm: convert add_cc and sub_cc helpers to TCG Now that the setcond TCG op is available, it's possible to replace add_cc and sub_cc helpers by TCG code. The code generated by TCG is actually very close to the one generated by GCC for the helper, and this avoid all the consequences of using an helper: globals saved back to memory, no possible optimization, call overhead, etc. Signed-off-by: Aurelien Jarno Signed-off-by: Peter Maydell --- target-arm/helper.h | 2 -- target-arm/op_helper.c | 20 ------------- target-arm/translate.c | 66 ++++++++++++++++++++++++++++++------------ 3 files changed, 48 insertions(+), 40 deletions(-) diff --git a/target-arm/helper.h b/target-arm/helper.h index afdb2b5b1a..7151e28d4b 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -142,9 +142,7 @@ DEF_HELPER_2(recpe_u32, i32, i32, env) DEF_HELPER_2(rsqrte_u32, i32, i32, env) DEF_HELPER_5(neon_tbl, i32, env, i32, i32, i32, i32) -DEF_HELPER_3(add_cc, i32, env, i32, i32) DEF_HELPER_3(adc_cc, i32, env, i32, i32) -DEF_HELPER_3(sub_cc, i32, env, i32, i32) DEF_HELPER_3(sbc_cc, i32, env, i32, i32) DEF_HELPER_3(shl, i32, env, i32, i32) diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index f13fc3ae57..6095f2435c 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -323,16 +323,6 @@ uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void *rip) The only way to do that in TCG is a conditional branch, which clobbers all our temporaries. For now implement these as helper functions. */ -uint32_t HELPER (add_cc)(CPUARMState *env, uint32_t a, uint32_t b) -{ - uint32_t result; - result = a + b; - env->NF = env->ZF = result; - env->CF = result < a; - env->VF = (a ^ b ^ -1) & (a ^ result); - return result; -} - uint32_t HELPER(adc_cc)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t result; @@ -348,16 +338,6 @@ uint32_t HELPER(adc_cc)(CPUARMState *env, uint32_t a, uint32_t b) return result; } -uint32_t HELPER(sub_cc)(CPUARMState *env, uint32_t a, uint32_t b) -{ - uint32_t result; - result = a - b; - env->NF = env->ZF = result; - env->CF = a >= b; - env->VF = (a ^ b) & (a ^ result); - return result; -} - uint32_t HELPER(sbc_cc)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t result; diff --git a/target-arm/translate.c b/target-arm/translate.c index 1055931659..da3246a952 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -410,6 +410,36 @@ static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1) tcg_gen_subi_i32(dest, dest, 1); } +/* dest = T0 + T1. Compute C, N, V and Z flags */ +static void gen_add_CC(TCGv dest, TCGv t0, TCGv t1) +{ + TCGv tmp; + tcg_gen_add_i32(cpu_NF, t0, t1); + tcg_gen_mov_i32(cpu_ZF, cpu_NF); + tcg_gen_setcond_i32(TCG_COND_LTU, cpu_CF, cpu_NF, t0); + tcg_gen_xor_i32(cpu_VF, cpu_NF, t0); + tmp = tcg_temp_new_i32(); + tcg_gen_xor_i32(tmp, t0, t1); + tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp); + tcg_temp_free_i32(tmp); + tcg_gen_mov_i32(dest, cpu_NF); +} + +/* dest = T0 - T1. Compute C, N, V and Z flags */ +static void gen_sub_CC(TCGv dest, TCGv t0, TCGv t1) +{ + TCGv 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); + tcg_gen_xor_i32(cpu_VF, cpu_NF, t0); + tmp = tcg_temp_new_i32(); + tcg_gen_xor_i32(tmp, t0, t1); + tcg_gen_and_i32(cpu_VF, cpu_VF, tmp); + tcg_temp_free_i32(tmp); + tcg_gen_mov_i32(dest, cpu_NF); +} + /* FIXME: Implement this natively. */ #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1) @@ -6970,11 +7000,11 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) if (IS_USER(s)) { goto illegal_op; } - gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); + gen_sub_CC(tmp, tmp, tmp2); gen_exception_return(s, tmp); } else { if (set_cc) { - gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); + gen_sub_CC(tmp, tmp, tmp2); } else { tcg_gen_sub_i32(tmp, tmp, tmp2); } @@ -6983,7 +7013,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x03: if (set_cc) { - gen_helper_sub_cc(tmp, cpu_env, tmp2, tmp); + gen_sub_CC(tmp, tmp2, tmp); } else { tcg_gen_sub_i32(tmp, tmp2, tmp); } @@ -6991,7 +7021,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x04: if (set_cc) { - gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); + gen_add_CC(tmp, tmp, tmp2); } else { tcg_gen_add_i32(tmp, tmp, tmp2); } @@ -7037,13 +7067,13 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x0a: if (set_cc) { - gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); + gen_sub_CC(tmp, tmp, tmp2); } tcg_temp_free_i32(tmp); break; case 0x0b: if (set_cc) { - gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); + gen_add_CC(tmp, tmp, tmp2); } tcg_temp_free_i32(tmp); break; @@ -7830,7 +7860,7 @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCG break; case 8: /* add */ if (conds) - gen_helper_add_cc(t0, cpu_env, t0, t1); + gen_add_CC(t0, t0, t1); else tcg_gen_add_i32(t0, t0, t1); break; @@ -7848,13 +7878,13 @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCG break; case 13: /* sub */ if (conds) - gen_helper_sub_cc(t0, cpu_env, t0, t1); + gen_sub_CC(t0, t0, t1); else tcg_gen_sub_i32(t0, t0, t1); break; case 14: /* rsb */ if (conds) - gen_helper_sub_cc(t0, cpu_env, t1, t0); + gen_sub_CC(t0, t1, t0); else tcg_gen_sub_i32(t0, t1, t0); break; @@ -8982,12 +9012,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (s->condexec_mask) tcg_gen_sub_i32(tmp, tmp, tmp2); else - gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); + gen_sub_CC(tmp, tmp, tmp2); } else { if (s->condexec_mask) tcg_gen_add_i32(tmp, tmp, tmp2); else - gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); + gen_add_CC(tmp, tmp, tmp2); } tcg_temp_free_i32(tmp2); store_reg(s, rd, tmp); @@ -9018,7 +9048,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) tcg_gen_movi_i32(tmp2, insn & 0xff); switch (op) { case 1: /* cmp */ - gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); + gen_sub_CC(tmp, tmp, tmp2); tcg_temp_free_i32(tmp); tcg_temp_free_i32(tmp2); break; @@ -9026,7 +9056,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (s->condexec_mask) tcg_gen_add_i32(tmp, tmp, tmp2); else - gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); + gen_add_CC(tmp, tmp, tmp2); tcg_temp_free_i32(tmp2); store_reg(s, rd, tmp); break; @@ -9034,7 +9064,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (s->condexec_mask) tcg_gen_sub_i32(tmp, tmp, tmp2); else - gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); + gen_sub_CC(tmp, tmp, tmp2); tcg_temp_free_i32(tmp2); store_reg(s, rd, tmp); break; @@ -9070,7 +9100,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) case 1: /* cmp */ tmp = load_reg(s, rd); tmp2 = load_reg(s, rm); - gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); + gen_sub_CC(tmp, tmp, tmp2); tcg_temp_free_i32(tmp2); tcg_temp_free_i32(tmp); break; @@ -9183,14 +9213,14 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (s->condexec_mask) tcg_gen_neg_i32(tmp, tmp2); else - gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); + gen_sub_CC(tmp, tmp, tmp2); break; case 0xa: /* cmp */ - gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); + gen_sub_CC(tmp, tmp, tmp2); rd = 16; break; case 0xb: /* cmn */ - gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); + gen_add_CC(tmp, tmp, tmp2); rd = 16; break; case 0xc: /* orr */ From 365af80e47bf150506345cdfbcbf32120f18cdf6 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 5 Oct 2012 15:04:44 +0100 Subject: [PATCH 0759/2270] target-arm: convert sar, shl and shr helpers to TCG Now that the movcond TCG op is available, it's possible to replace shl and shr helpers by TCG code. The code generated by TCG is slightly longer than the code generated by GCC for the helper but is still worth it as this avoid all the consequences of using an helper: globals saved back to memory, no possible optimization, call overhead, etc. Signed-off-by: Aurelien Jarno Signed-off-by: Peter Maydell --- target-arm/helper.h | 3 --- target-arm/op_helper.c | 24 --------------------- target-arm/translate.c | 49 ++++++++++++++++++++++++++++++++++++------ 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/target-arm/helper.h b/target-arm/helper.h index 7151e28d4b..794e2b1869 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -145,9 +145,6 @@ DEF_HELPER_5(neon_tbl, i32, env, i32, i32, i32, i32) DEF_HELPER_3(adc_cc, i32, env, i32, i32) DEF_HELPER_3(sbc_cc, i32, env, i32, i32) -DEF_HELPER_3(shl, i32, env, i32, i32) -DEF_HELPER_3(shr, i32, env, i32, i32) -DEF_HELPER_3(sar, i32, env, i32, i32) DEF_HELPER_3(shl_cc, i32, env, i32, i32) DEF_HELPER_3(shr_cc, i32, env, i32, i32) DEF_HELPER_3(sar_cc, i32, env, i32, i32) diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 6095f2435c..aef592ab8d 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -355,30 +355,6 @@ uint32_t HELPER(sbc_cc)(CPUARMState *env, uint32_t a, uint32_t b) /* Similarly for variable shift instructions. */ -uint32_t HELPER(shl)(CPUARMState *env, uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) - return 0; - return x << shift; -} - -uint32_t HELPER(shr)(CPUARMState *env, uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) - return 0; - return (uint32_t)x >> shift; -} - -uint32_t HELPER(sar)(CPUARMState *env, uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) - shift = 31; - return (int32_t)x >> shift; -} - uint32_t HELPER(shl_cc)(CPUARMState *env, uint32_t x, uint32_t i) { int shift = i & 0xff; diff --git a/target-arm/translate.c b/target-arm/translate.c index da3246a952..92ceacd873 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -440,6 +440,37 @@ static void gen_sub_CC(TCGv dest, TCGv t0, TCGv t1) tcg_gen_mov_i32(dest, cpu_NF); } +#define GEN_SHIFT(name) \ +static void gen_##name(TCGv dest, TCGv t0, TCGv t1) \ +{ \ + TCGv tmp1, tmp2, tmp3; \ + tmp1 = tcg_temp_new_i32(); \ + tcg_gen_andi_i32(tmp1, t1, 0xff); \ + tmp2 = tcg_const_i32(0); \ + tmp3 = tcg_const_i32(0x1f); \ + tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \ + tcg_temp_free_i32(tmp3); \ + tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \ + tcg_gen_##name##_i32(dest, tmp2, tmp1); \ + tcg_temp_free_i32(tmp2); \ + tcg_temp_free_i32(tmp1); \ +} +GEN_SHIFT(shl) +GEN_SHIFT(shr) +#undef GEN_SHIFT + +static void gen_sar(TCGv dest, TCGv t0, TCGv t1) +{ + TCGv tmp1, tmp2; + tmp1 = tcg_temp_new_i32(); + tcg_gen_andi_i32(tmp1, t1, 0xff); + tmp2 = tcg_const_i32(0x1f); + tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1); + tcg_temp_free_i32(tmp2); + tcg_gen_sar_i32(dest, t0, tmp1); + tcg_temp_free_i32(tmp1); +} + /* FIXME: Implement this natively. */ #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1) @@ -516,9 +547,15 @@ static inline void gen_arm_shift_reg(TCGv var, int shiftop, } } else { switch (shiftop) { - case 0: gen_helper_shl(var, cpu_env, var, shift); break; - case 1: gen_helper_shr(var, cpu_env, var, shift); break; - case 2: gen_helper_sar(var, cpu_env, var, shift); break; + case 0: + gen_shl(var, var, shift); + break; + case 1: + gen_shr(var, var, shift); + break; + case 2: + gen_sar(var, var, shift); + break; case 3: tcg_gen_andi_i32(shift, shift, 0x1f); tcg_gen_rotr_i32(var, var, shift); break; } @@ -9161,7 +9198,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) break; case 0x2: /* lsl */ if (s->condexec_mask) { - gen_helper_shl(tmp2, cpu_env, tmp2, tmp); + gen_shl(tmp2, tmp2, tmp); } else { gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp); gen_logic_CC(tmp2); @@ -9169,7 +9206,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) break; case 0x3: /* lsr */ if (s->condexec_mask) { - gen_helper_shr(tmp2, cpu_env, tmp2, tmp); + gen_shr(tmp2, tmp2, tmp); } else { gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp); gen_logic_CC(tmp2); @@ -9177,7 +9214,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) break; case 0x4: /* asr */ if (s->condexec_mask) { - gen_helper_sar(tmp2, cpu_env, tmp2, tmp); + gen_sar(tmp2, tmp2, tmp); } else { gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp); gen_logic_CC(tmp2); From 00e3ab2db059d243e210052937fc4f4169aa839c Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 5 Oct 2012 15:04:45 +0100 Subject: [PATCH 0760/2270] target-arm: mark a few integer helpers const and pure Signed-off-by: Aurelien Jarno Signed-off-by: Peter Maydell --- target-arm/helper.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/target-arm/helper.h b/target-arm/helper.h index 794e2b1869..8b9adf1311 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -1,8 +1,8 @@ #include "def-helper.h" -DEF_HELPER_1(clz, i32, i32) -DEF_HELPER_1(sxtb16, i32, i32) -DEF_HELPER_1(uxtb16, i32, i32) +DEF_HELPER_FLAGS_1(clz, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) +DEF_HELPER_FLAGS_1(sxtb16, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) +DEF_HELPER_FLAGS_1(uxtb16, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) DEF_HELPER_3(add_setq, i32, env, i32, i32) DEF_HELPER_3(add_saturate, i32, env, i32, i32) @@ -10,10 +10,10 @@ DEF_HELPER_3(sub_saturate, i32, env, i32, i32) DEF_HELPER_3(add_usaturate, i32, env, i32, i32) DEF_HELPER_3(sub_usaturate, i32, env, i32, i32) DEF_HELPER_2(double_saturate, i32, env, s32) -DEF_HELPER_2(sdiv, s32, s32, s32) -DEF_HELPER_2(udiv, i32, i32, i32) -DEF_HELPER_1(rbit, i32, i32) -DEF_HELPER_1(abs, i32, i32) +DEF_HELPER_FLAGS_2(sdiv, TCG_CALL_CONST | TCG_CALL_PURE, s32, s32, s32) +DEF_HELPER_FLAGS_2(udiv, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32) +DEF_HELPER_FLAGS_1(rbit, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) +DEF_HELPER_FLAGS_1(abs, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) #define PAS_OP(pfx) \ DEF_HELPER_3(pfx ## add8, i32, i32, i32, ptr) \ @@ -45,11 +45,12 @@ DEF_HELPER_3(usat, i32, env, i32, i32) DEF_HELPER_3(ssat16, i32, env, i32, i32) DEF_HELPER_3(usat16, i32, env, i32, i32) -DEF_HELPER_2(usad8, i32, i32, i32) +DEF_HELPER_FLAGS_2(usad8, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32) DEF_HELPER_1(logicq_cc, i32, i64) -DEF_HELPER_3(sel_flags, i32, i32, i32, i32) +DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_CONST | TCG_CALL_PURE, + i32, i32, i32, i32) DEF_HELPER_2(exception, void, env, i32) DEF_HELPER_1(wfi, void, env) From d593c48ef91b6fee609d9c87958fe76dd2b36852 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 5 Oct 2012 15:04:45 +0100 Subject: [PATCH 0761/2270] target-arm: use deposit instead of hardcoded version Use the deposit op instead of and hardcoded bit field insertion. It allows the host to emit the corresponding instruction if available. Signed-off-by: Aurelien Jarno Signed-off-by: Peter Maydell --- target-arm/translate.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/target-arm/translate.c b/target-arm/translate.c index 92ceacd873..c6840b7832 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -277,15 +277,6 @@ static void gen_sbfx(TCGv var, int shift, int width) } } -/* Bitfield insertion. Insert val into base. Clobbers base and val. */ -static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask) -{ - tcg_gen_andi_i32(val, val, mask); - tcg_gen_shli_i32(val, val, shift); - tcg_gen_andi_i32(base, base, ~(mask << shift)); - tcg_gen_or_i32(dest, base, val); -} - /* Return (b << 32) + a. Mark inputs as dead */ static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b) { @@ -2660,12 +2651,12 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn) switch (size) { case 0: tmp2 = neon_load_reg(rn, pass); - gen_bfi(tmp, tmp2, tmp, offset, 0xff); + tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8); tcg_temp_free_i32(tmp2); break; case 1: tmp2 = neon_load_reg(rn, pass); - gen_bfi(tmp, tmp2, tmp, offset, 0xffff); + tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16); tcg_temp_free_i32(tmp2); break; case 2: @@ -4021,7 +4012,8 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn) } if (size != 2) { tmp2 = neon_load_reg(rd, pass); - gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff); + tcg_gen_deposit_i32(tmp, tmp2, tmp, + shift, size ? 16 : 8); tcg_temp_free_i32(tmp2); } neon_store_reg(rd, pass, tmp); @@ -7625,7 +7617,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) } if (i != 32) { tmp2 = load_reg(s, rd); - gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1); + tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i); tcg_temp_free_i32(tmp2); } store_reg(s, rd, tmp); @@ -8736,7 +8728,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw imm = imm + 1 - shift; if (imm != 32) { tmp2 = load_reg(s, rd); - gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1); + tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm); tcg_temp_free_i32(tmp2); } break; From 1273d9ca09e91bb290d10f704055f6abec363dd6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 5 Oct 2012 15:04:45 +0100 Subject: [PATCH 0762/2270] target-arm: Drop unused DECODE_CPREG_CRN macro This macro snuck through code review despite being unused; drop it. Signed-off-by: Peter Maydell --- target-arm/cpu.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 7fac94f817..ff4de10f12 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -423,8 +423,6 @@ void armv7m_nvic_complete_irq(void *opaque, int irq); (((cp) << 16) | ((is64) << 15) | ((crn) << 11) | \ ((crm) << 7) | ((opc1) << 3) | (opc2)) -#define DECODE_CPREG_CRN(enc) (((enc) >> 7) & 0xf) - /* ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a * special-behaviour cp reg and bits [15..8] indicate what behaviour * it has. Otherwise it is a simple cp reg, where CONST indicates that From c9159fe9aa9abe24115ea4d16127179e9cb07e22 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 5 Oct 2012 19:39:33 +0200 Subject: [PATCH 0763/2270] Remove libhw The entries for libhw* are no longer needed in .gitignore. There is also no longer a difference between common-obj-y and hw-obj-y, so one of those two macros is sufficient. Signed-off-by: Stefan Weil Signed-off-by: Anthony Liguori --- .gitignore | 3 - Makefile | 2 +- Makefile.hw | 22 ----- Makefile.objs | 9 +- Makefile.target | 1 - configure | 5 - hw/9pfs/Makefile.objs | 14 +-- hw/Makefile.objs | 220 +++++++++++++++++++++--------------------- hw/ide/Makefile.objs | 20 ++-- hw/usb/Makefile.objs | 14 +-- 10 files changed, 138 insertions(+), 172 deletions(-) delete mode 100644 Makefile.hw diff --git a/.gitignore b/.gitignore index 3ef77d0622..bd6ba1c71e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,9 +12,6 @@ trace-dtrace.dtrace *-linux-user *-bsd-user libdis* -libhw -libhw32 -libhw64 libuser linux-headers/asm qapi-generated diff --git a/Makefile b/Makefile index 1cebe3a9db..a9c22bf1d9 100644 --- a/Makefile +++ b/Makefile @@ -214,7 +214,7 @@ $(qga-obj-y) qemu-ga.o: $(QGALIB_GEN) qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(tools-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y) -QEMULIBS=libhw libuser libdis libdis-user +QEMULIBS=libuser libdis libdis-user clean: # avoid old build problems by removing potentially incorrect old files diff --git a/Makefile.hw b/Makefile.hw deleted file mode 100644 index 86f0bf40f4..0000000000 --- a/Makefile.hw +++ /dev/null @@ -1,22 +0,0 @@ -# Makefile for qemu target independent devices. - -include ../config-host.mak -include ../config-all-devices.mak -include $(SRC_PATH)/rules.mak - -.PHONY: all - -$(call set-vpath, $(SRC_PATH)) - -QEMU_CFLAGS+=-I.. -QEMU_CFLAGS += -I$(SRC_PATH)/include - -include $(SRC_PATH)/Makefile.objs - -all: $(hw-obj-y) -# Dummy command so that make thinks it has done something - @true - -clean: - rm -f $(addsuffix *.o, $(sort $(dir $(hw-obj-y)))) - rm -f $(addsuffix *.d, $(sort $(dir $(hw-obj-y)))) diff --git a/Makefile.objs b/Makefile.objs index b1f3e22547..74b35422ce 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -90,10 +90,13 @@ common-obj-y += hw/ common-obj-y += ui/ common-obj-y += bt-host.o bt-vhci.o +common-obj-y += dma-helpers.o common-obj-y += iov.o acl.o common-obj-$(CONFIG_POSIX) += compatfd.o common-obj-y += notify.o event_notifier.o common-obj-y += qemu-timer.o qemu-timer-common.o +common-obj-y += qtest.o +common-obj-y += vl.o common-obj-$(CONFIG_SLIRP) += slirp/ @@ -115,11 +118,6 @@ user-obj-y += qemu-user.o user-obj-y += $(trace-obj-y) user-obj-y += qom/ -###################################################################### -# libhw - -hw-obj-y = vl.o dma-helpers.o qtest.o hw/ - ###################################################################### # libdis # NOTE: the disassembler code is only needed for debugging @@ -240,7 +238,6 @@ vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS) QEMU_CFLAGS+=$(GLIB_CFLAGS) nested-vars += \ - hw-obj-y \ qga-obj-y \ block-obj-y \ qom-obj-y \ diff --git a/Makefile.target b/Makefile.target index 4449444a0e..3822bc5ac3 100644 --- a/Makefile.target +++ b/Makefile.target @@ -154,7 +154,6 @@ all-obj-y += $(addprefix ../, $(universal-obj-y)) ifdef CONFIG_SOFTMMU all-obj-y += $(addprefix ../, $(common-obj-y)) all-obj-y += $(addprefix ../libdis/, $(libdis-y)) -all-obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y)) all-obj-y += $(addprefix ../, $(trace-obj-y)) else all-obj-y += $(addprefix ../libuser/, $(user-obj-y)) diff --git a/configure b/configure index e58846d5e2..73a5f3dc7c 100755 --- a/configure +++ b/configure @@ -3914,8 +3914,6 @@ fi if test "$target_softmmu" = "yes" ; then echo "CONFIG_SOFTMMU=y" >> $config_target_mak echo "LIBS+=$libs_softmmu $target_libs_softmmu" >> $config_target_mak - echo "HWDIR=../libhw" >> $config_target_mak - echo "subdir-$target: subdir-libhw" >> $config_host_mak if test "$smartcard_nss" = "yes" ; then echo "subdir-$target: subdir-libcacard" >> $config_host_mak fi @@ -4157,9 +4155,6 @@ for rom in seabios vgabios ; do echo "LD=$ld" >> $config_mak done -d=libhw -symlink "$source_path/Makefile.hw" "$d/Makefile" - d=libuser symlink "$source_path/Makefile.user" "$d/Makefile" diff --git a/hw/9pfs/Makefile.objs b/hw/9pfs/Makefile.objs index 972df24050..1e9b595cb4 100644 --- a/hw/9pfs/Makefile.objs +++ b/hw/9pfs/Makefile.objs @@ -1,9 +1,9 @@ -hw-obj-y = virtio-9p.o -hw-obj-y += virtio-9p-local.o virtio-9p-xattr.o -hw-obj-y += virtio-9p-xattr-user.o virtio-9p-posix-acl.o -hw-obj-y += virtio-9p-coth.o cofs.o codir.o cofile.o -hw-obj-y += coxattr.o virtio-9p-synth.o -hw-obj-$(CONFIG_OPEN_BY_HANDLE) += virtio-9p-handle.o -hw-obj-y += virtio-9p-proxy.o +common-obj-y = virtio-9p.o +common-obj-y += virtio-9p-local.o virtio-9p-xattr.o +common-obj-y += virtio-9p-xattr-user.o virtio-9p-posix-acl.o +common-obj-y += virtio-9p-coth.o cofs.o codir.o cofile.o +common-obj-y += coxattr.o virtio-9p-synth.o +common-obj-$(CONFIG_OPEN_BY_HANDLE) += virtio-9p-handle.o +common-obj-y += virtio-9p-proxy.o obj-y += virtio-9p-device.o diff --git a/hw/Makefile.objs b/hw/Makefile.objs index ecdbe44ddd..b59c74953f 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -1,140 +1,140 @@ -hw-obj-y = usb/ ide/ -hw-obj-y += loader.o -hw-obj-$(CONFIG_VIRTIO) += virtio-console.o -hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o -hw-obj-y += fw_cfg.o -hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o pci_bridge_dev.o -hw-obj-$(CONFIG_PCI) += msix.o msi.o -hw-obj-$(CONFIG_PCI) += shpc.o -hw-obj-$(CONFIG_PCI) += slotid_cap.o -hw-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o -hw-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o -hw-obj-y += watchdog.o -hw-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o -hw-obj-$(CONFIG_ECC) += ecc.o -hw-obj-$(CONFIG_NAND) += nand.o -hw-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o -hw-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o +common-obj-y = usb/ ide/ +common-obj-y += loader.o +common-obj-$(CONFIG_VIRTIO) += virtio-console.o +common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o +common-obj-y += fw_cfg.o +common-obj-$(CONFIG_PCI) += pci.o pci_bridge.o pci_bridge_dev.o +common-obj-$(CONFIG_PCI) += msix.o msi.o +common-obj-$(CONFIG_PCI) += shpc.o +common-obj-$(CONFIG_PCI) += slotid_cap.o +common-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o +common-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o +common-obj-y += watchdog.o +common-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o +common-obj-$(CONFIG_ECC) += ecc.o +common-obj-$(CONFIG_NAND) += nand.o +common-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o +common-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o -hw-obj-$(CONFIG_M48T59) += m48t59.o -hw-obj-$(CONFIG_ESCC) += escc.o -hw-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o +common-obj-$(CONFIG_M48T59) += m48t59.o +common-obj-$(CONFIG_ESCC) += escc.o +common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o -hw-obj-$(CONFIG_SERIAL) += serial.o -hw-obj-$(CONFIG_PARALLEL) += parallel.o -hw-obj-$(CONFIG_I8254) += i8254_common.o i8254.o -hw-obj-$(CONFIG_PCSPK) += pcspk.o -hw-obj-$(CONFIG_PCKBD) += pckbd.o -hw-obj-$(CONFIG_FDC) += fdc.o -hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o -hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o -hw-obj-$(CONFIG_DMA) += dma.o -hw-obj-$(CONFIG_I82374) += i82374.o -hw-obj-$(CONFIG_HPET) += hpet.o -hw-obj-$(CONFIG_APPLESMC) += applesmc.o -hw-obj-$(CONFIG_SMARTCARD) += ccid-card-passthru.o -hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o -hw-obj-$(CONFIG_I8259) += i8259_common.o i8259.o +common-obj-$(CONFIG_SERIAL) += serial.o +common-obj-$(CONFIG_PARALLEL) += parallel.o +common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o +common-obj-$(CONFIG_PCSPK) += pcspk.o +common-obj-$(CONFIG_PCKBD) += pckbd.o +common-obj-$(CONFIG_FDC) += fdc.o +common-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o +common-obj-$(CONFIG_APM) += pm_smbus.o apm.o +common-obj-$(CONFIG_DMA) += dma.o +common-obj-$(CONFIG_I82374) += i82374.o +common-obj-$(CONFIG_HPET) += hpet.o +common-obj-$(CONFIG_APPLESMC) += applesmc.o +common-obj-$(CONFIG_SMARTCARD) += ccid-card-passthru.o +common-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o +common-obj-$(CONFIG_I8259) += i8259_common.o i8259.o # PPC devices -hw-obj-$(CONFIG_PREP_PCI) += prep_pci.o -hw-obj-$(CONFIG_I82378) += i82378.o +common-obj-$(CONFIG_PREP_PCI) += prep_pci.o +common-obj-$(CONFIG_I82378) += i82378.o # Mac shared devices -hw-obj-$(CONFIG_MACIO) += macio.o -hw-obj-$(CONFIG_CUDA) += cuda.o -hw-obj-$(CONFIG_ADB) += adb.o -hw-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o -hw-obj-$(CONFIG_MAC_DBDMA) += mac_dbdma.o +common-obj-$(CONFIG_MACIO) += macio.o +common-obj-$(CONFIG_CUDA) += cuda.o +common-obj-$(CONFIG_ADB) += adb.o +common-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o +common-obj-$(CONFIG_MAC_DBDMA) += mac_dbdma.o # OldWorld PowerMac -hw-obj-$(CONFIG_HEATHROW_PIC) += heathrow_pic.o -hw-obj-$(CONFIG_GRACKLE_PCI) += grackle_pci.o +common-obj-$(CONFIG_HEATHROW_PIC) += heathrow_pic.o +common-obj-$(CONFIG_GRACKLE_PCI) += grackle_pci.o # NewWorld PowerMac -hw-obj-$(CONFIG_UNIN_PCI) += unin_pci.o -hw-obj-$(CONFIG_DEC_PCI) += dec_pci.o +common-obj-$(CONFIG_UNIN_PCI) += unin_pci.o +common-obj-$(CONFIG_DEC_PCI) += dec_pci.o # PowerPC E500 boards -hw-obj-$(CONFIG_PPCE500_PCI) += ppce500_pci.o +common-obj-$(CONFIG_PPCE500_PCI) += ppce500_pci.o # MIPS devices -hw-obj-$(CONFIG_PIIX4) += piix4.o -hw-obj-$(CONFIG_G364FB) += g364fb.o -hw-obj-$(CONFIG_JAZZ_LED) += jazz_led.o +common-obj-$(CONFIG_PIIX4) += piix4.o +common-obj-$(CONFIG_G364FB) += g364fb.o +common-obj-$(CONFIG_JAZZ_LED) += jazz_led.o # Xilinx devices -hw-obj-$(CONFIG_XILINX) += xilinx_intc.o -hw-obj-$(CONFIG_XILINX) += xilinx_timer.o -hw-obj-$(CONFIG_XILINX) += xilinx_uartlite.o -hw-obj-$(CONFIG_XILINX_AXI) += xilinx_axidma.o -hw-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o -hw-obj-$(CONFIG_XILINX_AXI) += stream.o +common-obj-$(CONFIG_XILINX) += xilinx_intc.o +common-obj-$(CONFIG_XILINX) += xilinx_timer.o +common-obj-$(CONFIG_XILINX) += xilinx_uartlite.o +common-obj-$(CONFIG_XILINX_AXI) += xilinx_axidma.o +common-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o +common-obj-$(CONFIG_XILINX_AXI) += stream.o # PKUnity SoC devices -hw-obj-$(CONFIG_PUV3) += puv3_intc.o -hw-obj-$(CONFIG_PUV3) += puv3_ost.o -hw-obj-$(CONFIG_PUV3) += puv3_gpio.o -hw-obj-$(CONFIG_PUV3) += puv3_pm.o -hw-obj-$(CONFIG_PUV3) += puv3_dma.o +common-obj-$(CONFIG_PUV3) += puv3_intc.o +common-obj-$(CONFIG_PUV3) += puv3_ost.o +common-obj-$(CONFIG_PUV3) += puv3_gpio.o +common-obj-$(CONFIG_PUV3) += puv3_pm.o +common-obj-$(CONFIG_PUV3) += puv3_dma.o # ARM devices -hw-obj-$(CONFIG_ARM_TIMER) += arm_timer.o -hw-obj-$(CONFIG_PL011) += pl011.o -hw-obj-$(CONFIG_PL022) += pl022.o -hw-obj-$(CONFIG_PL031) += pl031.o -hw-obj-$(CONFIG_PL041) += pl041.o lm4549.o -hw-obj-$(CONFIG_PL050) += pl050.o -hw-obj-$(CONFIG_PL061) += pl061.o -hw-obj-$(CONFIG_PL080) += pl080.o -hw-obj-$(CONFIG_PL110) += pl110.o -hw-obj-$(CONFIG_PL181) += pl181.o -hw-obj-$(CONFIG_PL190) += pl190.o -hw-obj-$(CONFIG_PL310) += arm_l2x0.o -hw-obj-$(CONFIG_VERSATILE_PCI) += versatile_pci.o -hw-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o -hw-obj-$(CONFIG_CADENCE) += cadence_uart.o -hw-obj-$(CONFIG_CADENCE) += cadence_ttc.o -hw-obj-$(CONFIG_CADENCE) += cadence_gem.o -hw-obj-$(CONFIG_XGMAC) += xgmac.o +common-obj-$(CONFIG_ARM_TIMER) += arm_timer.o +common-obj-$(CONFIG_PL011) += pl011.o +common-obj-$(CONFIG_PL022) += pl022.o +common-obj-$(CONFIG_PL031) += pl031.o +common-obj-$(CONFIG_PL041) += pl041.o lm4549.o +common-obj-$(CONFIG_PL050) += pl050.o +common-obj-$(CONFIG_PL061) += pl061.o +common-obj-$(CONFIG_PL080) += pl080.o +common-obj-$(CONFIG_PL110) += pl110.o +common-obj-$(CONFIG_PL181) += pl181.o +common-obj-$(CONFIG_PL190) += pl190.o +common-obj-$(CONFIG_PL310) += arm_l2x0.o +common-obj-$(CONFIG_VERSATILE_PCI) += versatile_pci.o +common-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o +common-obj-$(CONFIG_CADENCE) += cadence_uart.o +common-obj-$(CONFIG_CADENCE) += cadence_ttc.o +common-obj-$(CONFIG_CADENCE) += cadence_gem.o +common-obj-$(CONFIG_XGMAC) += xgmac.o # PCI watchdog devices -hw-obj-$(CONFIG_PCI) += wdt_i6300esb.o +common-obj-$(CONFIG_PCI) += wdt_i6300esb.o -hw-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o +common-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o # PCI network cards -hw-obj-$(CONFIG_NE2000_PCI) += ne2000.o -hw-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o -hw-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o -hw-obj-$(CONFIG_PCNET_COMMON) += pcnet.o -hw-obj-$(CONFIG_E1000_PCI) += e1000.o -hw-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o +common-obj-$(CONFIG_NE2000_PCI) += ne2000.o +common-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o +common-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o +common-obj-$(CONFIG_PCNET_COMMON) += pcnet.o +common-obj-$(CONFIG_E1000_PCI) += e1000.o +common-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o -hw-obj-$(CONFIG_SMC91C111) += smc91c111.o -hw-obj-$(CONFIG_LAN9118) += lan9118.o -hw-obj-$(CONFIG_NE2000_ISA) += ne2000-isa.o -hw-obj-$(CONFIG_OPENCORES_ETH) += opencores_eth.o +common-obj-$(CONFIG_SMC91C111) += smc91c111.o +common-obj-$(CONFIG_LAN9118) += lan9118.o +common-obj-$(CONFIG_NE2000_ISA) += ne2000-isa.o +common-obj-$(CONFIG_OPENCORES_ETH) += opencores_eth.o # SCSI layer -hw-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o -hw-obj-$(CONFIG_MEGASAS_SCSI_PCI) += megasas.o -hw-obj-$(CONFIG_ESP) += esp.o -hw-obj-$(CONFIG_ESP_PCI) += esp-pci.o +common-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o +common-obj-$(CONFIG_MEGASAS_SCSI_PCI) += megasas.o +common-obj-$(CONFIG_ESP) += esp.o +common-obj-$(CONFIG_ESP_PCI) += esp-pci.o -hw-obj-y += sysbus.o isa-bus.o -hw-obj-y += qdev-addr.o +common-obj-y += sysbus.o isa-bus.o +common-obj-y += qdev-addr.o # VGA -hw-obj-$(CONFIG_VGA_PCI) += vga-pci.o -hw-obj-$(CONFIG_VGA_ISA) += vga-isa.o -hw-obj-$(CONFIG_VGA_ISA_MM) += vga-isa-mm.o -hw-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o -hw-obj-$(CONFIG_VMMOUSE) += vmmouse.o -hw-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o +common-obj-$(CONFIG_VGA_PCI) += vga-pci.o +common-obj-$(CONFIG_VGA_ISA) += vga-isa.o +common-obj-$(CONFIG_VGA_ISA_MM) += vga-isa-mm.o +common-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o +common-obj-$(CONFIG_VMMOUSE) += vmmouse.o +common-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o -hw-obj-$(CONFIG_RC4030) += rc4030.o -hw-obj-$(CONFIG_DP8393X) += dp8393x.o -hw-obj-$(CONFIG_DS1225Y) += ds1225y.o -hw-obj-$(CONFIG_MIPSNET) += mipsnet.o +common-obj-$(CONFIG_RC4030) += rc4030.o +common-obj-$(CONFIG_DP8393X) += dp8393x.o +common-obj-$(CONFIG_DS1225Y) += ds1225y.o +common-obj-$(CONFIG_MIPSNET) += mipsnet.o -hw-obj-y += null-machine.o +common-obj-y += null-machine.o # Sound sound-obj-y = @@ -148,9 +148,9 @@ sound-obj-$(CONFIG_HDA) += intel-hda.o hda-audio.o $(obj)/adlib.o $(obj)/fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0 -hw-obj-$(CONFIG_SOUND) += $(sound-obj-y) +common-obj-$(CONFIG_SOUND) += $(sound-obj-y) -hw-obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/ +common-obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/ common-obj-y += usb/ common-obj-y += irq.o diff --git a/hw/ide/Makefile.objs b/hw/ide/Makefile.objs index cf718dd016..5c8c22aad7 100644 --- a/hw/ide/Makefile.objs +++ b/hw/ide/Makefile.objs @@ -1,10 +1,10 @@ -hw-obj-$(CONFIG_IDE_CORE) += core.o atapi.o -hw-obj-$(CONFIG_IDE_QDEV) += qdev.o -hw-obj-$(CONFIG_IDE_PCI) += pci.o -hw-obj-$(CONFIG_IDE_ISA) += isa.o -hw-obj-$(CONFIG_IDE_PIIX) += piix.o -hw-obj-$(CONFIG_IDE_CMD646) += cmd646.o -hw-obj-$(CONFIG_IDE_MACIO) += macio.o -hw-obj-$(CONFIG_IDE_VIA) += via.o -hw-obj-$(CONFIG_AHCI) += ahci.o -hw-obj-$(CONFIG_AHCI) += ich.o +common-obj-$(CONFIG_IDE_CORE) += core.o atapi.o +common-obj-$(CONFIG_IDE_QDEV) += qdev.o +common-obj-$(CONFIG_IDE_PCI) += pci.o +common-obj-$(CONFIG_IDE_ISA) += isa.o +common-obj-$(CONFIG_IDE_PIIX) += piix.o +common-obj-$(CONFIG_IDE_CMD646) += cmd646.o +common-obj-$(CONFIG_IDE_MACIO) += macio.o +common-obj-$(CONFIG_IDE_VIA) += via.o +common-obj-$(CONFIG_AHCI) += ahci.o +common-obj-$(CONFIG_AHCI) += ich.o diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs index 4225136d0f..6425c1ff73 100644 --- a/hw/usb/Makefile.objs +++ b/hw/usb/Makefile.objs @@ -1,11 +1,11 @@ -hw-obj-$(CONFIG_USB_UHCI) += hcd-uhci.o -hw-obj-$(CONFIG_USB_OHCI) += hcd-ohci.o -hw-obj-$(CONFIG_USB_EHCI) += hcd-ehci.o -hw-obj-$(CONFIG_USB_XHCI) += hcd-xhci.o -hw-obj-y += libhw.o +common-obj-$(CONFIG_USB_UHCI) += hcd-uhci.o +common-obj-$(CONFIG_USB_OHCI) += hcd-ohci.o +common-obj-$(CONFIG_USB_EHCI) += hcd-ehci.o +common-obj-$(CONFIG_USB_XHCI) += hcd-xhci.o +common-obj-y += libhw.o -hw-obj-$(CONFIG_SMARTCARD) += dev-smartcard-reader.o -hw-obj-$(CONFIG_USB_REDIR) += redirect.o +common-obj-$(CONFIG_SMARTCARD) += dev-smartcard-reader.o +common-obj-$(CONFIG_USB_REDIR) += redirect.o common-obj-y += core.o bus.o desc.o dev-hub.o common-obj-y += host-$(HOST_USB).o dev-bluetooth.o From f783cb22409c6537b3cab7e78e527f62b4237d1e Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Mon, 1 Oct 2012 21:00:42 +0200 Subject: [PATCH 0764/2270] target-xtensa: de-optimize EXTUI Now that "and" with 0xff, 0xffff and 0xffffffff and "shr" with 0 shift are optimized in tcg/tcg-op.h there is no need to do it in target-xtensa/translate.c. Acked-by: Max Filippov Signed-off-by: Aurelien Jarno --- target-xtensa/translate.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index b9acd706ce..82e8cccadc 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -1829,26 +1829,8 @@ static void disas_xtensa_insn(DisasContext *dc) int maskimm = (1 << (OP2 + 1)) - 1; TCGv_i32 tmp = tcg_temp_new_i32(); - - if (shiftimm) { - tcg_gen_shri_i32(tmp, cpu_R[RRR_T], shiftimm); - } else { - tcg_gen_mov_i32(tmp, cpu_R[RRR_T]); - } - - switch (maskimm) { - case 0xff: - tcg_gen_ext8u_i32(cpu_R[RRR_R], tmp); - break; - - case 0xffff: - tcg_gen_ext16u_i32(cpu_R[RRR_R], tmp); - break; - - default: - tcg_gen_andi_i32(cpu_R[RRR_R], tmp, maskimm); - break; - } + tcg_gen_shri_i32(tmp, cpu_R[RRR_T], shiftimm); + tcg_gen_andi_i32(cpu_R[RRR_R], tmp, maskimm); tcg_temp_free(tmp); } break; From 626cd050e2c9094c1b005bc39cab637f8cbe3755 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Mon, 1 Oct 2012 21:00:43 +0200 Subject: [PATCH 0765/2270] tcg: remove obsolete jmp op The TCG jmp operation doesn't really make sense in the QEMU context, it is unused, it is not implemented by some targets, and it is wrongly implemented by some others. This patch simply removes it. Reviewed-by: Richard Henderson Acked-by: Blue Swirl Acked-by: Stefan Weil Signed-off-by: Aurelien Jarno --- tcg/README | 7 +------ tcg/arm/tcg-target.c | 7 ------- tcg/hppa/tcg-target.c | 6 ------ tcg/i386/tcg-target.c | 9 --------- tcg/ia64/tcg-target.c | 4 ---- tcg/mips/tcg-target.c | 5 ----- tcg/ppc/tcg-target.c | 10 ---------- tcg/ppc64/tcg-target.c | 10 ---------- tcg/s390/tcg-target.c | 6 ------ tcg/sparc/tcg-target.c | 2 -- tcg/tcg-opc.h | 1 - tcg/tci/tcg-target.c | 4 ---- tci.c | 1 - 13 files changed, 1 insertion(+), 71 deletions(-) diff --git a/tcg/README b/tcg/README index 27846f1ea4..aa86992bca 100644 --- a/tcg/README +++ b/tcg/README @@ -88,8 +88,7 @@ supported. * Branches: -Use the instruction 'br' to jump to a label. Use 'jmp' to jump to an -explicit address. Conditional branches can only jump to labels. +Use the instruction 'br' to jump to a label. 3.3) Code Optimizations @@ -129,10 +128,6 @@ call function 'ptr' (pointer type) ********* Jumps/Labels -* jmp t0 - -Absolute jump to address t0 (pointer type). - * set_label $label Define label 'label' at the current program point. diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index 2bad0a2b17..1e61864d42 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -1530,12 +1530,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, else tcg_out_callr(s, COND_AL, args[0]); break; - case INDEX_op_jmp: - if (const_args[0]) - tcg_out_goto(s, COND_AL, args[0]); - else - tcg_out_bx(s, COND_AL, args[0]); - break; case INDEX_op_br: tcg_out_goto_label(s, COND_AL, args[0]); break; @@ -1769,7 +1763,6 @@ static const TCGTargetOpDef arm_op_defs[] = { { INDEX_op_exit_tb, { } }, { INDEX_op_goto_tb, { } }, { INDEX_op_call, { "ri" } }, - { INDEX_op_jmp, { "ri" } }, { INDEX_op_br, { } }, { INDEX_op_mov_i32, { "r", "r" } }, diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c index 2c79c1081e..44974c4e86 100644 --- a/tcg/hppa/tcg-target.c +++ b/tcg/hppa/tcg-target.c @@ -1353,11 +1353,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, } break; - case INDEX_op_jmp: - fprintf(stderr, "unimplemented jmp\n"); - tcg_abort(); - break; - case INDEX_op_br: tcg_out_branch(s, args[0], 1); break; @@ -1592,7 +1587,6 @@ static const TCGTargetOpDef hppa_op_defs[] = { { INDEX_op_goto_tb, { } }, { INDEX_op_call, { "ri" } }, - { INDEX_op_jmp, { "r" } }, { INDEX_op_br, { } }, { INDEX_op_mov_i32, { "r", "r" } }, diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 0e218c8614..bb2306df8d 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -1513,14 +1513,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_modrm(s, OPC_GRP5, EXT5_CALLN_Ev, args[0]); } break; - case INDEX_op_jmp: - if (const_args[0]) { - tcg_out_jmp(s, args[0]); - } else { - /* jmp *reg */ - tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, args[0]); - } - break; case INDEX_op_br: tcg_out_jxx(s, JCC_JMP, args[0], 0); break; @@ -1848,7 +1840,6 @@ static const TCGTargetOpDef x86_op_defs[] = { { INDEX_op_exit_tb, { } }, { INDEX_op_goto_tb, { } }, { INDEX_op_call, { "ri" } }, - { INDEX_op_jmp, { "ri" } }, { INDEX_op_br, { } }, { INDEX_op_mov_i32, { "r", "r" } }, { INDEX_op_movi_i32, { "r" } }, diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index dc9c12cf18..705712f775 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1916,9 +1916,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_goto_tb: tcg_out_goto_tb(s, args[0]); break; - case INDEX_op_jmp: - tcg_out_jmp(s, args[0]); - break; case INDEX_op_movi_i32: tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]); @@ -2156,7 +2153,6 @@ static const TCGTargetOpDef ia64_op_defs[] = { { INDEX_op_call, { "r" } }, { INDEX_op_exit_tb, { } }, { INDEX_op_goto_tb, { } }, - { INDEX_op_jmp, { "r" } }, { INDEX_op_mov_i32, { "r", "r" } }, { INDEX_op_movi_i32, { "r" } }, diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index 34e3e7f823..7e4013e1e6 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -1322,10 +1322,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0); tcg_out_nop(s); break; - case INDEX_op_jmp: - tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0); - tcg_out_nop(s); - break; case INDEX_op_br: tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]); break; @@ -1577,7 +1573,6 @@ static const TCGTargetOpDef mips_op_defs[] = { { INDEX_op_exit_tb, { } }, { INDEX_op_goto_tb, { } }, { INDEX_op_call, { "C" } }, - { INDEX_op_jmp, { "r" } }, { INDEX_op_br, { } }, { INDEX_op_mov_i32, { "r", "r" } }, diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 90c275d698..56baedda58 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -1417,15 +1417,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_call: tcg_out_call (s, args[0], const_args[0]); break; - case INDEX_op_jmp: - if (const_args[0]) { - tcg_out_b (s, 0, args[0]); - } - else { - tcg_out32 (s, MTSPR | RS (args[0]) | CTR); - tcg_out32 (s, BCCTR | BO_ALWAYS); - } - break; case INDEX_op_movi_i32: tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]); break; @@ -1904,7 +1895,6 @@ static const TCGTargetOpDef ppc_op_defs[] = { { INDEX_op_exit_tb, { } }, { INDEX_op_goto_tb, { } }, { INDEX_op_call, { "ri" } }, - { INDEX_op_jmp, { "ri" } }, { INDEX_op_br, { } }, { INDEX_op_mov_i32, { "r", "r" } }, diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c index 19944bc427..6e9b363a1b 100644 --- a/tcg/ppc64/tcg-target.c +++ b/tcg/ppc64/tcg-target.c @@ -1245,15 +1245,6 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_call: tcg_out_call (s, args[0], const_args[0]); break; - case INDEX_op_jmp: - if (const_args[0]) { - tcg_out_b (s, 0, args[0]); - } - else { - tcg_out32 (s, MTSPR | RS (args[0]) | CTR); - tcg_out32 (s, BCCTR | BO_ALWAYS); - } - break; case INDEX_op_movi_i32: tcg_out_movi (s, TCG_TYPE_I32, args[0], args[1]); break; @@ -1588,7 +1579,6 @@ static const TCGTargetOpDef ppc_op_defs[] = { { INDEX_op_exit_tb, { } }, { INDEX_op_goto_tb, { } }, { INDEX_op_call, { "ri" } }, - { INDEX_op_jmp, { "ri" } }, { INDEX_op_br, { } }, { INDEX_op_mov_i32, { "r", "r" } }, diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c index 3b90605fb1..4b4305952d 100644 --- a/tcg/s390/tcg-target.c +++ b/tcg/s390/tcg-target.c @@ -2037,11 +2037,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; #endif /* TCG_TARGET_REG_BITS == 64 */ - case INDEX_op_jmp: - /* This one is obsolete and never emitted. */ - tcg_abort(); - break; - default: fprintf(stderr,"unimplemented opc 0x%x\n",opc); tcg_abort(); @@ -2052,7 +2047,6 @@ static const TCGTargetOpDef s390_op_defs[] = { { INDEX_op_exit_tb, { } }, { INDEX_op_goto_tb, { } }, { INDEX_op_call, { "ri" } }, - { INDEX_op_jmp, { "ri" } }, { INDEX_op_br, { } }, { INDEX_op_mov_i32, { "r", "r" } }, diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 8fd7f86de0..e82fab2622 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -1097,7 +1097,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, /* delay slot */ tcg_out_nop(s); break; - case INDEX_op_jmp: case INDEX_op_br: tcg_out_branch_i32(s, COND_A, args[0]); tcg_out_nop(s); @@ -1367,7 +1366,6 @@ static const TCGTargetOpDef sparc_op_defs[] = { { INDEX_op_exit_tb, { } }, { INDEX_op_goto_tb, { } }, { INDEX_op_call, { "ri" } }, - { INDEX_op_jmp, { "ri" } }, { INDEX_op_br, { } }, { INDEX_op_mov_i32, { "r", "r" } }, diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h index dbb0e3916a..04cb7ca038 100644 --- a/tcg/tcg-opc.h +++ b/tcg/tcg-opc.h @@ -38,7 +38,6 @@ DEF(discard, 1, 0, 0, 0) DEF(set_label, 0, 0, 1, TCG_OPF_BB_END) DEF(call, 0, 1, 2, TCG_OPF_SIDE_EFFECTS) /* variable number of parameters */ -DEF(jmp, 0, 1, 0, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) DEF(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) #define IMPL(X) (X ? 0 : TCG_OPF_NOT_PRESENT) diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c index d272a906e8..e930740835 100644 --- a/tcg/tci/tcg-target.c +++ b/tcg/tci/tcg-target.c @@ -69,7 +69,6 @@ static const TCGTargetOpDef tcg_target_op_defs[] = { { INDEX_op_exit_tb, { NULL } }, { INDEX_op_goto_tb, { NULL } }, { INDEX_op_call, { RI } }, - { INDEX_op_jmp, { RI } }, { INDEX_op_br, { NULL } }, { INDEX_op_mov_i32, { R, R } }, @@ -583,9 +582,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_call: tcg_out_ri(s, const_args[0], args[0]); break; - case INDEX_op_jmp: - TODO(); - break; case INDEX_op_setcond_i32: tcg_out_r(s, args[0]); tcg_out_r(s, args[1]); diff --git a/tci.c b/tci.c index a4f7b78418..98f5f713e0 100644 --- a/tci.c +++ b/tci.c @@ -505,7 +505,6 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr) tci_write_reg(TCG_REG_R0, tmp64); #endif break; - case INDEX_op_jmp: case INDEX_op_br: label = tci_read_label(&tb_ptr); assert(tb_ptr == old_code_ptr + op_size); From a1e472119aa2efa88a2a24b1aa50e45ea8cc8f31 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 11:38:41 +0200 Subject: [PATCH 0766/2270] vga: rename pci_vga_init() into pci_std_vga_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This better explains what is this function about. Adjust all callers. Cc: Alexander Graf Cc: Andreas Färber Cc: David Gibson Cc: Anthony Liguori Acked-by: Richard Henderson Acked-by: Blue Swirl Acked-by: Andreas Färber Signed-off-by: Aurelien Jarno --- hw/alpha_pci.c | 2 +- hw/mips_malta.c | 2 +- hw/pc.c | 2 +- hw/ppc_newworld.c | 2 +- hw/ppc_oldworld.c | 2 +- hw/ppc_prep.c | 2 +- hw/spapr.c | 2 +- hw/sun4u.c | 2 +- hw/vga-pci.c | 6 +++--- hw/vga-pci.h | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c index ea546f83f1..0352e72d5f 100644 --- a/hw/alpha_pci.c +++ b/hw/alpha_pci.c @@ -128,6 +128,6 @@ void alpha_pci_vga_setup(PCIBus *pci_bus) /* If VGA is enabled at all, and one of the above didn't work, then fallback to Standard VGA. */ if (vga_interface_type != VGA_NONE) { - pci_vga_init(pci_bus); + pci_std_vga_init(pci_bus); } } diff --git a/hw/mips_malta.c b/hw/mips_malta.c index ad23f26e59..c39dee5830 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -992,7 +992,7 @@ void mips_malta_init (ram_addr_t ram_size, } else if (vmsvga_enabled) { pci_vmsvga_init(pci_bus); } else if (std_vga_enabled) { - pci_vga_init(pci_bus); + pci_std_vga_init(pci_bus); } } diff --git a/hw/pc.c b/hw/pc.c index 7e7e0e2235..33fee622d5 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -1014,7 +1014,7 @@ DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus) #endif } else if (std_vga_enabled) { if (pci_bus) { - dev = pci_vga_init(pci_bus); + dev = pci_std_vga_init(pci_bus); } else { dev = isa_vga_init(isa_bus); } diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index e95cfe831e..84af948f5a 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -330,7 +330,7 @@ static void ppc_core99_init (ram_addr_t ram_size, machine_arch = ARCH_MAC99; } /* init basic PC hardware */ - pci_vga_init(pci_bus); + pci_std_vga_init(pci_bus); escc_mem = escc_init(0, pic[0x25], pic[0x24], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index 1dcd8a6c36..8267eb43b2 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -250,7 +250,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size, pci_bus = pci_grackle_init(0xfec00000, pic, get_system_memory(), get_system_io()); - pci_vga_init(pci_bus); + pci_std_vga_init(pci_bus); escc_mem = escc_init(0, pic[0x0f], pic[0x10], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index 592b7b255f..1fa7609705 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -611,7 +611,7 @@ static void ppc_prep_init (ram_addr_t ram_size, memory_region_add_subregion(sysmem, 0x80000000, PPC_io_memory); /* init basic PC hardware */ - pci_vga_init(pci_bus); + pci_std_vga_init(pci_bus); if (serial_hds[0]) serial_isa_init(isa_bus, 0, serial_hds[0]); diff --git a/hw/spapr.c b/hw/spapr.c index c34b767c6e..80735d6ab4 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -590,7 +590,7 @@ static int spapr_vga_init(PCIBus *pci_bus) { switch (vga_interface_type) { case VGA_STD: - pci_vga_init(pci_bus); + pci_std_vga_init(pci_bus); return 1; case VGA_NONE: return 0; diff --git a/hw/sun4u.c b/hw/sun4u.c index 07cd04273a..cca090f87e 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -821,7 +821,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, ivec_irqs = qemu_allocate_irqs(cpu_set_ivec_irq, env, IVEC_MAX); pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_bus2, &pci_bus3, &pbm_irqs); - pci_vga_init(pci_bus); + pci_std_vga_init(pci_bus); // XXX Should be pci_bus3 isa_bus = pci_ebus_init(pci_bus, -1, pbm_irqs); diff --git a/hw/vga-pci.c b/hw/vga-pci.c index 9abbada8f1..992ffd98b2 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -47,7 +47,7 @@ static const VMStateDescription vmstate_vga_pci = { } }; -static int pci_vga_initfn(PCIDevice *dev) +static int pci_std_vga_initfn(PCIDevice *dev) { PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev); VGACommonState *s = &d->vga; @@ -70,7 +70,7 @@ static int pci_vga_initfn(PCIDevice *dev) return 0; } -DeviceState *pci_vga_init(PCIBus *bus) +DeviceState *pci_std_vga_init(PCIBus *bus) { return &pci_create_simple(bus, -1, "VGA")->qdev; } @@ -86,7 +86,7 @@ static void vga_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); k->no_hotplug = 1; - k->init = pci_vga_initfn; + k->init = pci_std_vga_initfn; k->romfile = "vgabios-stdvga.bin"; k->vendor_id = PCI_VENDOR_ID_QEMU; k->device_id = PCI_DEVICE_ID_QEMU_VGA; diff --git a/hw/vga-pci.h b/hw/vga-pci.h index 49abf1309d..d111cdc016 100644 --- a/hw/vga-pci.h +++ b/hw/vga-pci.h @@ -4,7 +4,7 @@ #include "qemu-common.h" /* vga-pci.c */ -DeviceState *pci_vga_init(PCIBus *bus); +DeviceState *pci_std_vga_init(PCIBus *bus); /* cirrus_vga.c */ DeviceState *pci_cirrus_vga_init(PCIBus *bus); From 6405c86412719a0ccd1a09b81baf0b78e8a4ae6b Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 16:40:56 +0200 Subject: [PATCH 0767/2270] vga: rename isa_vga_init() to isa_std_vga_init() This better explains what is this function about. Adjust all callers. Cc: Anthony Liguori Signed-off-by: Aurelien Jarno --- hw/mips_r4k.c | 2 +- hw/pc.c | 2 +- hw/pc.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index 967a76e533..2115f7f3d4 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -281,7 +281,7 @@ void mips_r4k_init (ram_addr_t ram_size, } } - isa_vga_init(isa_bus); + isa_std_vga_init(isa_bus); if (nd_table[0].used) isa_ne2000_init(isa_bus, 0x300, 9, &nd_table[0]); diff --git a/hw/pc.c b/hw/pc.c index 33fee622d5..78805f625e 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -1016,7 +1016,7 @@ DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus) if (pci_bus) { dev = pci_std_vga_init(pci_bus); } else { - dev = isa_vga_init(isa_bus); + dev = isa_std_vga_init(isa_bus); } } diff --git a/hw/pc.h b/hw/pc.h index e4db0715b8..77c38d6091 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -176,7 +176,7 @@ enum vga_retrace_method { extern enum vga_retrace_method vga_retrace_method; -static inline DeviceState *isa_vga_init(ISABus *bus) +static inline DeviceState *isa_std_vga_init(ISABus *bus) { ISADevice *dev; From 36b7f27d2195a09dbfb7f08b2323d807c1ad90b0 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 16:01:20 +0200 Subject: [PATCH 0768/2270] vl.c: convert *vga_enabled functions to QOM And get rid of qdev_exists(). Signed-off-by: Aurelien Jarno --- hw/qdev.c | 5 ----- hw/qdev.h | 1 - vl.c | 7 ++++--- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/hw/qdev.c b/hw/qdev.c index 3b5ce3312f..adfc4a7ea3 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -52,11 +52,6 @@ const char *qdev_fw_name(DeviceState *dev) return object_get_typename(OBJECT(dev)); } -bool qdev_exists(const char *name) -{ - return !!object_class_by_name(name); -} - static void qdev_property_add_legacy(DeviceState *dev, Property *prop, Error **errp); diff --git a/hw/qdev.h b/hw/qdev.h index d699194418..c6ac636200 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -153,7 +153,6 @@ typedef struct GlobalProperty { DeviceState *qdev_create(BusState *bus, const char *name); DeviceState *qdev_try_create(BusState *bus, const char *name); -bool qdev_exists(const char *name); int qdev_device_help(QemuOpts *opts); DeviceState *qdev_device_add(QemuOpts *opts); int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT; diff --git a/vl.c b/vl.c index 8d305ca59b..bf9cdf8eb2 100644 --- a/vl.c +++ b/vl.c @@ -1700,17 +1700,18 @@ static const QEMUOption qemu_options[] = { static bool vga_available(void) { - return qdev_exists("VGA") || qdev_exists("isa-vga"); + return object_class_by_name("VGA") || object_class_by_name("isa-vga"); } static bool cirrus_vga_available(void) { - return qdev_exists("cirrus-vga") || qdev_exists("isa-cirrus-vga"); + return object_class_by_name("cirrus-vga") + || object_class_by_name("isa-cirrus-vga"); } static bool vmware_vga_available(void) { - return qdev_exists("vmware-svga"); + return object_class_by_name("vmware-svga"); } static void select_vgahw (const char *p) From 879049a39724f91224f10c8d80b3cf70c9dc1c5e Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 12:01:06 +0200 Subject: [PATCH 0769/2270] vl.c: check for qxl availability Check for qxl availability in vl.c. This will allow to remove #ifdef CONFIG_SPICE .. #endif later in this series Cc: Anthony Liguori Cc: Gerd Hoffmann Signed-off-by: Aurelien Jarno --- vl.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/vl.c b/vl.c index bf9cdf8eb2..17a33a0968 100644 --- a/vl.c +++ b/vl.c @@ -1714,6 +1714,11 @@ static bool vmware_vga_available(void) return object_class_by_name("vmware-svga"); } +static bool qxl_vga_available(void) +{ + return object_class_by_name("qxl-vga"); +} + static void select_vgahw (const char *p) { const char *opts; @@ -1743,7 +1748,12 @@ static void select_vgahw (const char *p) } else if (strstart(p, "xenfb", &opts)) { vga_interface_type = VGA_XENFB; } else if (strstart(p, "qxl", &opts)) { - vga_interface_type = VGA_QXL; + if (qxl_vga_available()) { + vga_interface_type = VGA_QXL; + } else { + fprintf(stderr, "Error: QXL VGA not available\n"); + exit(0); + } } else if (!strstart(p, "none", &opts)) { invalid_vga: fprintf(stderr, "Unknown vga type: %s\n", p); From 3605ded557eb2a6d06a942b952c8fac4c676b125 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Mon, 10 Sep 2012 01:01:44 +0200 Subject: [PATCH 0770/2270] vl.c: default to std if cirrus is not available Signed-off-by: Aurelien Jarno --- vl.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/vl.c b/vl.c index 17a33a0968..02dade19fc 100644 --- a/vl.c +++ b/vl.c @@ -3617,8 +3617,12 @@ int main(int argc, char **argv, char **envp) exit(1); /* If no default VGA is requested, the default is "none". */ - if (default_vga && cirrus_vga_available()) { - vga_model = "cirrus"; + if (default_vga) { + if (cirrus_vga_available()) { + vga_model = "cirrus"; + } else if (vga_available()) { + vga_model = "std"; + } } select_vgahw(vga_model); From 129d42fb8496de5c1896160fddab949784d4dea4 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 11:49:24 +0200 Subject: [PATCH 0771/2270] pci: add a pci_vga_init() function This function create a PCI VGA device according to the value of vga_interface_type. It returns a PCIDevice (and not a DeviceState). Cc: Anthony Liguori Signed-off-by: Aurelien Jarno --- hw/pci.c | 18 ++++++++++++++++++ hw/pci.h | 3 +++ 2 files changed, 21 insertions(+) diff --git a/hw/pci.c b/hw/pci.c index de4b4485e7..2ca6ff6fec 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1474,6 +1474,24 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model, return res; } +PCIDevice *pci_vga_init(PCIBus *bus) +{ + switch (vga_interface_type) { + case VGA_CIRRUS: + return pci_create_simple(bus, -1, "cirrus-vga"); + case VGA_QXL: + return pci_create_simple(bus, -1, "qxl-vga"); + case VGA_STD: + return pci_create_simple(bus, -1, "VGA"); + case VGA_VMWARE: + return pci_create_simple(bus, -1, "vmware-svga"); + case VGA_NONE: + default: /* Other non-PCI types. Checking for unsupported types is already + done in vl.c. */ + return NULL; + } +} + /* Whether a given bus number is in range of the secondary * bus of the given bridge device. */ static bool pci_secondary_bus_in_range(PCIDevice *dev, int bus_num) diff --git a/hw/pci.h b/hw/pci.h index 4b6ab3d190..d50d26c8ac 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -334,6 +334,9 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model, const char *default_devaddr); PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model, const char *default_devaddr); + +PCIDevice *pci_vga_init(PCIBus *bus); + int pci_bus_num(PCIBus *s); void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDevice *d, void *opaque), From 14e7a6456e1dba2c6499b3b05637fee9f553e6ce Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 16:58:57 +0200 Subject: [PATCH 0772/2270] isa: add a isa_vga_init() function This function create a ISA VGA device according to the value of vga_interface_type. It returns a ISADevice (and not a DeviceState). Signed-off-by: Aurelien Jarno --- hw/isa-bus.c | 20 ++++++++++++++++++++ hw/isa.h | 2 ++ 2 files changed, 22 insertions(+) diff --git a/hw/isa-bus.c b/hw/isa-bus.c index 47c93d37b6..214f19457d 100644 --- a/hw/isa-bus.c +++ b/hw/isa-bus.c @@ -19,6 +19,7 @@ #include "hw.h" #include "monitor.h" #include "sysbus.h" +#include "sysemu.h" #include "isa.h" #include "exec-memory.h" @@ -166,6 +167,25 @@ ISADevice *isa_create_simple(ISABus *bus, const char *name) return dev; } +ISADevice *isa_vga_init(ISABus *bus) +{ + switch (vga_interface_type) { + case VGA_CIRRUS: + return isa_create_simple(bus, "isa-cirrus-vga"); + case VGA_QXL: + fprintf(stderr, "%s: qxl: no PCI bus\n", __func__); + return NULL; + case VGA_STD: + return isa_create_simple(bus, "isa-vga"); + case VGA_VMWARE: + fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __func__); + return NULL; + case VGA_NONE: + default: + return NULL; + } +} + static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent) { ISADevice *d = ISA_DEVICE(dev); diff --git a/hw/isa.h b/hw/isa.h index dc970527ae..8fb498aa8d 100644 --- a/hw/isa.h +++ b/hw/isa.h @@ -47,6 +47,8 @@ ISADevice *isa_create(ISABus *bus, const char *name); ISADevice *isa_try_create(ISABus *bus, const char *name); ISADevice *isa_create_simple(ISABus *bus, const char *name); +ISADevice *isa_vga_init(ISABus *bus); + /** * isa_register_ioport: Install an I/O port region on the ISA bus. * From 9c59864d16d720184e723c0c29c505c34e94fed5 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 11:53:12 +0200 Subject: [PATCH 0773/2270] mips/malta: use the new pci_vga_init() function Signed-off-by: Aurelien Jarno --- hw/mips_malta.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/hw/mips_malta.c b/hw/mips_malta.c index c39dee5830..632b466e32 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -33,7 +33,6 @@ #include "mips.h" #include "mips_cpudevs.h" #include "pci.h" -#include "vmware_vga.h" #include "qemu-char.h" #include "sysemu.h" #include "arch_init.h" @@ -48,7 +47,6 @@ #include "blockdev.h" #include "exec-memory.h" #include "sysbus.h" /* SysBusDevice */ -#include "vga-pci.h" //#define DEBUG_BOARD_INIT @@ -987,13 +985,7 @@ void mips_malta_init (ram_addr_t ram_size, network_init(); /* Optional PCI video card */ - if (cirrus_vga_enabled) { - pci_cirrus_vga_init(pci_bus); - } else if (vmsvga_enabled) { - pci_vmsvga_init(pci_bus); - } else if (std_vga_enabled) { - pci_std_vga_init(pci_bus); - } + pci_vga_init(pci_bus); } static int mips_malta_sysbus_device_init(SysBusDevice *sysbusdev) From 606f90cc22094bab743c84d40a11f6ded603ad34 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 12:16:28 +0200 Subject: [PATCH 0774/2270] alpha: use the new pci_vga_init() function This remove the fallback to std-vga in case, as availability of the requested vga device is now tested in vl.c, and returns an error message to the user. Acked-by: Richard Henderson Signed-off-by: Aurelien Jarno --- hw/alpha_dp264.c | 2 +- hw/alpha_pci.c | 24 ------------------------ hw/alpha_sys.h | 2 -- 3 files changed, 1 insertion(+), 27 deletions(-) diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c index 9eb939f383..5ea04c75ac 100644 --- a/hw/alpha_dp264.c +++ b/hw/alpha_dp264.c @@ -77,7 +77,7 @@ static void clipper_init(ram_addr_t ram_size, isa_create_simple(isa_bus, "i8042"); /* VGA setup. Don't bother loading the bios. */ - alpha_pci_vga_setup(pci_bus); + pci_vga_init(pci_bus); /* Serial code setup. */ for (i = 0; i < MAX_SERIAL_PORTS; ++i) { diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c index 0352e72d5f..8079a46ae0 100644 --- a/hw/alpha_pci.c +++ b/hw/alpha_pci.c @@ -10,8 +10,6 @@ #include "alpha_sys.h" #include "qemu-log.h" #include "sysemu.h" -#include "vmware_vga.h" -#include "vga-pci.h" /* PCI IO reads/writes, to byte-word addressable memory. */ @@ -109,25 +107,3 @@ const MemoryRegionOps alpha_pci_iack_ops = { .max_access_size = 4, }, }; - -void alpha_pci_vga_setup(PCIBus *pci_bus) -{ - switch (vga_interface_type) { -#ifdef CONFIG_SPICE - case VGA_QXL: - pci_create_simple(pci_bus, -1, "qxl-vga"); - return; -#endif - case VGA_CIRRUS: - pci_cirrus_vga_init(pci_bus); - return; - case VGA_VMWARE: - pci_vmsvga_init(pci_bus); - return; - } - /* If VGA is enabled at all, and one of the above didn't work, then - fallback to Standard VGA. */ - if (vga_interface_type != VGA_NONE) { - pci_std_vga_init(pci_bus); - } -} diff --git a/hw/alpha_sys.h b/hw/alpha_sys.h index de40f8b613..7604d09c80 100644 --- a/hw/alpha_sys.h +++ b/hw/alpha_sys.h @@ -19,6 +19,4 @@ extern const MemoryRegionOps alpha_pci_bw_io_ops; extern const MemoryRegionOps alpha_pci_conf1_ops; extern const MemoryRegionOps alpha_pci_iack_ops; -void alpha_pci_vga_setup(PCIBus *pci_bus); - #endif From e7a2e96df0692e19f253476027a565dc7c11da76 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 12:19:38 +0200 Subject: [PATCH 0775/2270] ppc/newworld: use the new pci_vga_init() function As a bonus it allows new vga card types (including none). Cc: Alexander Graf Signed-off-by: Aurelien Jarno --- hw/ppc_newworld.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index 84af948f5a..b8d3c9c988 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -67,7 +67,6 @@ #include "hw/usb.h" #include "blockdev.h" #include "exec-memory.h" -#include "vga-pci.h" #define MAX_IDE_BUS 2 #define CFG_ADDR 0xf0000510 @@ -330,7 +329,7 @@ static void ppc_core99_init (ram_addr_t ram_size, machine_arch = ARCH_MAC99; } /* init basic PC hardware */ - pci_std_vga_init(pci_bus); + pci_vga_init(pci_bus); escc_mem = escc_init(0, pic[0x25], pic[0x24], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); From 3e20ad3a9b674abc3464504d59bba46304316136 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 12:21:20 +0200 Subject: [PATCH 0776/2270] ppc/oldworld: use the new pci_vga_init() function As a bonus it allows new vga card types (including none). Cc: Alexander Graf Signed-off-by: Aurelien Jarno --- hw/ppc_oldworld.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index 8267eb43b2..2c4a47813f 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -43,7 +43,6 @@ #include "kvm_ppc.h" #include "blockdev.h" #include "exec-memory.h" -#include "vga-pci.h" #define MAX_IDE_BUS 2 #define CFG_ADDR 0xf0000510 @@ -250,7 +249,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size, pci_bus = pci_grackle_init(0xfec00000, pic, get_system_memory(), get_system_io()); - pci_std_vga_init(pci_bus); + pci_vga_init(pci_bus); escc_mem = escc_init(0, pic[0x0f], pic[0x10], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); From 95fa01fab0082483c1849f1439303db4183c8dd4 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 12:22:44 +0200 Subject: [PATCH 0777/2270] ppc/prep: use the new pci_vga_init() function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As a bonus it allows new vga card types (including none). Acked-by: Andreas Färber Signed-off-by: Aurelien Jarno --- hw/ppc_prep.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index 1fa7609705..15444303e4 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -39,7 +39,6 @@ #include "blockdev.h" #include "arch_init.h" #include "exec-memory.h" -#include "vga-pci.h" //#define HARD_DEBUG_PPC_IO //#define DEBUG_PPC_IO @@ -611,7 +610,7 @@ static void ppc_prep_init (ram_addr_t ram_size, memory_region_add_subregion(sysmem, 0x80000000, PPC_io_memory); /* init basic PC hardware */ - pci_std_vga_init(pci_bus); + pci_vga_init(pci_bus); if (serial_hds[0]) serial_isa_init(isa_bus, 0, serial_hds[0]); From 1ddcae82a2509668b94a13e84921bdcafddcdfff Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 12:40:45 +0200 Subject: [PATCH 0778/2270] ppc/pSeries: use the new pci_vga_init() function Keep the case to prevent some vga card to be selected. Cc: Alexander Graf Cc: David Gibson Signed-off-by: Aurelien Jarno --- hw/spapr.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 80735d6ab4..8b0c390269 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -46,7 +46,6 @@ #include "kvm.h" #include "kvm_ppc.h" #include "pci.h" -#include "vga-pci.h" #include "exec-memory.h" #include "hw/usb.h" @@ -589,11 +588,9 @@ static void spapr_cpu_reset(void *opaque) static int spapr_vga_init(PCIBus *pci_bus) { switch (vga_interface_type) { - case VGA_STD: - pci_std_vga_init(pci_bus); - return 1; case VGA_NONE: - return 0; + case VGA_STD: + return pci_vga_init(pci_bus) != NULL; default: fprintf(stderr, "This vga model is not supported," "currently it only supports -vga std\n"); From f2898771435701df33145cacabeb42c6aa3a9a16 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 12:23:54 +0200 Subject: [PATCH 0779/2270] sun/sun4u: use the new pci_vga_init() function As a bonus it allows new vga card types (including none). Acked-by: Blue Swirl Signed-off-by: Aurelien Jarno --- hw/sun4u.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/sun4u.c b/hw/sun4u.c index cca090f87e..137a7c6666 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -39,7 +39,6 @@ #include "elf.h" #include "blockdev.h" #include "exec-memory.h" -#include "vga-pci.h" //#define DEBUG_IRQ //#define DEBUG_EBUS @@ -821,7 +820,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, ivec_irqs = qemu_allocate_irqs(cpu_set_ivec_irq, env, IVEC_MAX); pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_bus2, &pci_bus3, &pbm_irqs); - pci_std_vga_init(pci_bus); + pci_vga_init(pci_bus); // XXX Should be pci_bus3 isa_bus = pci_ebus_init(pci_bus, -1, pbm_irqs); From 16094b75b38dcb5582810bd4149fa8336a939dc8 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 12:47:45 +0200 Subject: [PATCH 0780/2270] pc: use the new pci_vga_init() and isa_vga_init() functions The CONFIG_SPICE is now tested in vl.c and thus not needed anymore. Cc: Anthony Liguori Signed-off-by: Aurelien Jarno --- hw/pc.c | 35 ++++++----------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/hw/pc.c b/hw/pc.c index 78805f625e..6c0722db5c 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -27,7 +27,6 @@ #include "fdc.h" #include "ide.h" #include "pci.h" -#include "vmware_vga.h" #include "monitor.h" #include "fw_cfg.h" #include "hpet_emul.h" @@ -51,7 +50,6 @@ #include "exec-memory.h" #include "arch_init.h" #include "bitmap.h" -#include "vga-pci.h" /* debug PC/ISA interrupts */ //#define DEBUG_IRQ @@ -992,34 +990,13 @@ DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus) { DeviceState *dev = NULL; - if (cirrus_vga_enabled) { - if (pci_bus) { - dev = pci_cirrus_vga_init(pci_bus); - } else { - dev = &isa_create_simple(isa_bus, "isa-cirrus-vga")->qdev; - } - } else if (vmsvga_enabled) { - if (pci_bus) { - dev = pci_vmsvga_init(pci_bus); - } else { - fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__); - } -#ifdef CONFIG_SPICE - } else if (qxl_enabled) { - if (pci_bus) { - dev = &pci_create_simple(pci_bus, -1, "qxl-vga")->qdev; - } else { - fprintf(stderr, "%s: qxl: no PCI bus\n", __FUNCTION__); - } -#endif - } else if (std_vga_enabled) { - if (pci_bus) { - dev = pci_std_vga_init(pci_bus); - } else { - dev = isa_std_vga_init(isa_bus); - } + if (pci_bus) { + PCIDevice *pcidev = pci_vga_init(pci_bus); + dev = pcidev ? &pcidev->qdev : NULL; + } else if (isa_bus) { + ISADevice *isadev = isa_vga_init(isa_bus); + dev = isadev ? &isadev->qdev : NULL; } - return dev; } From f642dfce199eecda5a558ce94c17a34707d63ccd Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 17:02:29 +0200 Subject: [PATCH 0781/2270] mips/r4k: use the new is_vga_init() function Signed-off-by: Aurelien Jarno --- hw/mips_r4k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index 2115f7f3d4..967a76e533 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -281,7 +281,7 @@ void mips_r4k_init (ram_addr_t ram_size, } } - isa_std_vga_init(isa_bus); + isa_vga_init(isa_bus); if (nd_table[0].used) isa_ne2000_init(isa_bus, 0x300, 9, &nd_table[0]); From 457ebdcd91aa7f0df094e12a8c46235f0c7d4f9b Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 8 Sep 2012 12:58:09 +0200 Subject: [PATCH 0782/2270] vga: cleanup after isa_vga_init() and pci_vga_init() conversion Now that all machines call isa_vga_init() or pci_vga_init(), some unused code can be removed. Cc: Anthony Liguori Signed-off-by: Aurelien Jarno --- hw/cirrus_vga.c | 6 ------ hw/pc.h | 13 ------------- hw/vga-pci.c | 6 ------ hw/vga-pci.h | 12 ------------ hw/vmware_vga.c | 1 - hw/vmware_vga.h | 15 --------------- sysemu.h | 3 --- 7 files changed, 56 deletions(-) delete mode 100644 hw/vga-pci.h delete mode 100644 hw/vmware_vga.h diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index 9a0a565723..a10132953c 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -28,7 +28,6 @@ */ #include "hw.h" #include "pci.h" -#include "vga-pci.h" #include "console.h" #include "vga_int.h" #include "loader.h" @@ -2970,11 +2969,6 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev) return 0; } -DeviceState *pci_cirrus_vga_init(PCIBus *bus) -{ - return &pci_create_simple(bus, -1, "cirrus-vga")->qdev; -} - static void cirrus_vga_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); diff --git a/hw/pc.h b/hw/pc.h index 77c38d6091..9923d96027 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -176,19 +176,6 @@ enum vga_retrace_method { extern enum vga_retrace_method vga_retrace_method; -static inline DeviceState *isa_std_vga_init(ISABus *bus) -{ - ISADevice *dev; - - dev = isa_try_create(bus, "isa-vga"); - if (!dev) { - fprintf(stderr, "Warning: isa-vga not available\n"); - return NULL; - } - qdev_init_nofail(&dev->qdev); - return &dev->qdev; -} - int isa_vga_mm_init(target_phys_addr_t vram_base, target_phys_addr_t ctrl_base, int it_shift, MemoryRegion *address_space); diff --git a/hw/vga-pci.c b/hw/vga-pci.c index 992ffd98b2..996d47f23a 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -24,7 +24,6 @@ #include "hw.h" #include "console.h" #include "pci.h" -#include "vga-pci.h" #include "vga_int.h" #include "pixel_ops.h" #include "qemu-timer.h" @@ -70,11 +69,6 @@ static int pci_std_vga_initfn(PCIDevice *dev) return 0; } -DeviceState *pci_std_vga_init(PCIBus *bus) -{ - return &pci_create_simple(bus, -1, "VGA")->qdev; -} - static Property vga_pci_properties[] = { DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/vga-pci.h b/hw/vga-pci.h deleted file mode 100644 index d111cdc016..0000000000 --- a/hw/vga-pci.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef VGA_PCI_H -#define VGA_PCI_H - -#include "qemu-common.h" - -/* vga-pci.c */ -DeviceState *pci_std_vga_init(PCIBus *bus); - -/* cirrus_vga.c */ -DeviceState *pci_cirrus_vga_init(PCIBus *bus); - -#endif diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index e815a04e9f..6f7074e55f 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -25,7 +25,6 @@ #include "loader.h" #include "console.h" #include "pci.h" -#include "vmware_vga.h" #undef VERBOSE #define HW_RECT_ACCEL diff --git a/hw/vmware_vga.h b/hw/vmware_vga.h deleted file mode 100644 index 000fbddc0f..0000000000 --- a/hw/vmware_vga.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef QEMU_VMWARE_VGA_H -#define QEMU_VMWARE_VGA_H - -#include "qemu-common.h" - -/* vmware_vga.c */ -static inline DeviceState *pci_vmsvga_init(PCIBus *bus) -{ - PCIDevice *dev; - - dev = pci_create_simple(bus, -1, "vmware-svga"); - return &dev->qdev; -} - -#endif diff --git a/sysemu.h b/sysemu.h index 109304672d..0c39a3ac1a 100644 --- a/sysemu.h +++ b/sysemu.h @@ -105,10 +105,7 @@ typedef enum { } VGAInterfaceType; extern int vga_interface_type; -#define cirrus_vga_enabled (vga_interface_type == VGA_CIRRUS) -#define std_vga_enabled (vga_interface_type == VGA_STD) #define xenfb_enabled (vga_interface_type == VGA_XENFB) -#define vmsvga_enabled (vga_interface_type == VGA_VMWARE) #define qxl_enabled (vga_interface_type == VGA_QXL) extern int graphic_width; From bcc66562ad185e9c2a667b00426f625e2489bda9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 24 Sep 2012 14:21:39 -0700 Subject: [PATCH 0783/2270] tcg: Add is_unsigned_cond Before we rearrange the TCG_COND enumeration, add a predicate for the (single) use of comparisons vs TCGCond. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/s390/tcg-target.c | 2 +- tcg/tcg.h | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c index 4b4305952d..c0ef6ba9a6 100644 --- a/tcg/s390/tcg-target.c +++ b/tcg/s390/tcg-target.c @@ -1113,7 +1113,7 @@ static void tgen64_xori(TCGContext *s, TCGReg dest, tcg_target_ulong val) static int tgen_cmp(TCGContext *s, TCGType type, TCGCond c, TCGReg r1, TCGArg c2, int c2const) { - bool is_unsigned = (c > TCG_COND_GT); + bool is_unsigned = is_unsigned_cond(c); if (c2const) { if (c2 == 0) { if (type == TCG_TYPE_I32) { diff --git a/tcg/tcg.h b/tcg/tcg.h index af7464a650..6ff2ab55be 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -298,6 +298,11 @@ static inline TCGCond tcg_unsigned_cond(TCGCond c) return (c >= TCG_COND_LT && c <= TCG_COND_GT ? c + 4 : c); } +static inline bool is_unsigned_cond(TCGCond c) +{ + return c >= TCG_COND_LTU; +} + #define TEMP_VAL_DEAD 0 #define TEMP_VAL_REG 1 #define TEMP_VAL_MEM 2 From 0aed257f08444feb6269d0c302b35a8fb10fcb3f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 24 Sep 2012 14:21:40 -0700 Subject: [PATCH 0784/2270] tcg: Add TCG_COND_NEVER, TCG_COND_ALWAYS There are several cases that can be handled easier inside both translators and code generators if we have out-of-band values for conditions. It's easy enough to handle ALWAYS and NEVER in the natural way inside the tcg middle-end. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/arm/tcg-target.c | 2 +- tcg/hppa/tcg-target.c | 2 +- tcg/i386/tcg-target.c | 2 +- tcg/optimize.c | 6 ++++ tcg/ppc/tcg-target.c | 2 +- tcg/ppc64/tcg-target.c | 2 +- tcg/s390/tcg-target.c | 4 +-- tcg/sparc/tcg-target.c | 2 +- tcg/tcg-op.h | 82 ++++++++++++++++++++++++++++++++---------- tcg/tcg.c | 2 ++ tcg/tcg.h | 37 +++++++++++-------- 11 files changed, 102 insertions(+), 41 deletions(-) diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index 1e61864d42..fbbbefe985 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -335,7 +335,7 @@ enum arm_cond_code_e { COND_AL = 0xe, }; -static const uint8_t tcg_cond_to_arm_cond[10] = { +static const uint8_t tcg_cond_to_arm_cond[] = { [TCG_COND_EQ] = COND_EQ, [TCG_COND_NE] = COND_NE, [TCG_COND_LT] = COND_LT, diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c index 44974c4e86..b93343015a 100644 --- a/tcg/hppa/tcg-target.c +++ b/tcg/hppa/tcg-target.c @@ -732,7 +732,7 @@ static void tcg_out_branch(TCGContext *s, int label_index, int nul) } } -static const uint8_t tcg_cond_to_cmp_cond[10] = +static const uint8_t tcg_cond_to_cmp_cond[] = { [TCG_COND_EQ] = COND_EQ, [TCG_COND_NE] = COND_EQ | COND_FALSE, diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index bb2306df8d..4952c057b3 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -338,7 +338,7 @@ static inline int tcg_target_const_match(tcg_target_long val, #define JCC_JLE 0xe #define JCC_JG 0xf -static const uint8_t tcg_cond_to_jcc[10] = { +static const uint8_t tcg_cond_to_jcc[] = { [TCG_COND_EQ] = JCC_JE, [TCG_COND_NE] = JCC_JNE, [TCG_COND_LT] = JCC_JL, diff --git a/tcg/optimize.c b/tcg/optimize.c index 35532a1e03..edb2b0ea90 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -321,6 +321,8 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x, return (uint32_t)temps[x].val <= (uint32_t)temps[y].val; case TCG_COND_GTU: return (uint32_t)temps[x].val > (uint32_t)temps[y].val; + default: + break; } break; case 64: @@ -345,6 +347,8 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x, return (uint64_t)temps[x].val <= (uint64_t)temps[y].val; case TCG_COND_GTU: return (uint64_t)temps[x].val > (uint64_t)temps[y].val; + default: + break; } break; } @@ -362,6 +366,8 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x, case TCG_COND_LEU: case TCG_COND_EQ: return 1; + default: + break; } } else if (temps[y].state == TCG_TEMP_CONST && temps[y].val == 0) { switch (c) { diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 56baedda58..60b7b92621 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -437,7 +437,7 @@ enum { CR_SO }; -static const uint32_t tcg_to_bc[10] = { +static const uint32_t tcg_to_bc[] = { [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE, [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE, [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE, diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c index 6e9b363a1b..5403fc1f91 100644 --- a/tcg/ppc64/tcg-target.c +++ b/tcg/ppc64/tcg-target.c @@ -418,7 +418,7 @@ enum { CR_SO }; -static const uint32_t tcg_to_bc[10] = { +static const uint32_t tcg_to_bc[] = { [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE, [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE, [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE, diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c index c0ef6ba9a6..fd9286f52d 100644 --- a/tcg/s390/tcg-target.c +++ b/tcg/s390/tcg-target.c @@ -268,7 +268,7 @@ static const int tcg_target_call_oarg_regs[] = { #define S390_CC_ALWAYS 15 /* Condition codes that result from a COMPARE and COMPARE LOGICAL. */ -static const uint8_t tcg_cond_to_s390_cond[10] = { +static const uint8_t tcg_cond_to_s390_cond[] = { [TCG_COND_EQ] = S390_CC_EQ, [TCG_COND_NE] = S390_CC_NE, [TCG_COND_LT] = S390_CC_LT, @@ -284,7 +284,7 @@ static const uint8_t tcg_cond_to_s390_cond[10] = { /* Condition codes that result from a LOAD AND TEST. Here, we have no unsigned instruction variation, however since the test is vs zero we can re-map the outcomes appropriately. */ -static const uint8_t tcg_cond_to_ltr_cond[10] = { +static const uint8_t tcg_cond_to_ltr_cond[] = { [TCG_COND_EQ] = S390_CC_EQ, [TCG_COND_NE] = S390_CC_NE, [TCG_COND_LT] = S390_CC_LT, diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index e82fab2622..0c32baa50e 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -512,7 +512,7 @@ static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index) } #endif -static const uint8_t tcg_cond_to_bcond[10] = { +static const uint8_t tcg_cond_to_bcond[] = { [TCG_COND_EQ] = COND_E, [TCG_COND_NE] = COND_NE, [TCG_COND_LT] = COND_L, diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index bd93fe4f03..551845801d 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -646,29 +646,49 @@ static inline void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) static inline void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, TCGv_i32 arg2, int label_index) { - tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_index); + if (cond == TCG_COND_ALWAYS) { + tcg_gen_br(label_index); + } else if (cond != TCG_COND_NEVER) { + tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_index); + } } static inline void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, int32_t arg2, int label_index) { - TCGv_i32 t0 = tcg_const_i32(arg2); - tcg_gen_brcond_i32(cond, arg1, t0, label_index); - tcg_temp_free_i32(t0); + if (cond == TCG_COND_ALWAYS) { + tcg_gen_br(label_index); + } else if (cond != TCG_COND_NEVER) { + TCGv_i32 t0 = tcg_const_i32(arg2); + tcg_gen_brcond_i32(cond, arg1, t0, label_index); + tcg_temp_free_i32(t0); + } } static inline void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) { - tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond); + if (cond == TCG_COND_ALWAYS) { + tcg_gen_movi_i32(ret, 1); + } else if (cond == TCG_COND_NEVER) { + tcg_gen_movi_i32(ret, 0); + } else { + tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond); + } } static inline void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) { - TCGv_i32 t0 = tcg_const_i32(arg2); - tcg_gen_setcond_i32(cond, ret, arg1, t0); - tcg_temp_free_i32(t0); + if (cond == TCG_COND_ALWAYS) { + tcg_gen_movi_i32(ret, 1); + } else if (cond == TCG_COND_NEVER) { + tcg_gen_movi_i32(ret, 0); + } else { + TCGv_i32 t0 = tcg_const_i32(arg2); + tcg_gen_setcond_i32(cond, ret, arg1, t0); + tcg_temp_free_i32(t0); + } } static inline void tcg_gen_mul_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) @@ -964,17 +984,27 @@ static inline void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) static inline void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, int label_index) { - tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, - TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2), - TCGV_HIGH(arg2), cond, label_index); + if (cond == TCG_COND_ALWAYS) { + tcg_gen_br(label_index); + } else if (cond != TCG_COND_NEVER) { + tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, + TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2), + TCGV_HIGH(arg2), cond, label_index); + } } static inline void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) { - tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret), - TCGV_LOW(arg1), TCGV_HIGH(arg1), - TCGV_LOW(arg2), TCGV_HIGH(arg2), cond); + if (cond == TCG_COND_ALWAYS) { + tcg_gen_movi_i32(TCGV_LOW(ret), 1); + } else if (cond == TCG_COND_NEVER) { + tcg_gen_movi_i32(TCGV_LOW(ret), 0); + } else { + tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret), + TCGV_LOW(arg1), TCGV_HIGH(arg1), + TCGV_LOW(arg2), TCGV_HIGH(arg2), cond); + } tcg_gen_movi_i32(TCGV_HIGH(ret), 0); } @@ -1273,13 +1303,23 @@ static inline void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) static inline void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2, int label_index) { - tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, label_index); + if (cond == TCG_COND_ALWAYS) { + tcg_gen_br(label_index); + } else if (cond != TCG_COND_NEVER) { + tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, label_index); + } } static inline void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) { - tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond); + if (cond == TCG_COND_ALWAYS) { + tcg_gen_movi_i64(ret, 1); + } else if (cond == TCG_COND_NEVER) { + tcg_gen_movi_i64(ret, 0); + } else { + tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond); + } } static inline void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) @@ -1397,9 +1437,13 @@ static inline void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) static inline void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, int label_index) { - TCGv_i64 t0 = tcg_const_i64(arg2); - tcg_gen_brcond_i64(cond, arg1, t0, label_index); - tcg_temp_free_i64(t0); + if (cond == TCG_COND_ALWAYS) { + tcg_gen_br(label_index); + } else if (cond != TCG_COND_NEVER) { + TCGv_i64 t0 = tcg_const_i64(arg2); + tcg_gen_brcond_i64(cond, arg1, t0, label_index); + tcg_temp_free_i64(t0); + } } static inline void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret, diff --git a/tcg/tcg.c b/tcg/tcg.c index c069e44a0e..78ef50b6ee 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -864,6 +864,8 @@ static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val) static const char * const cond_name[] = { + [TCG_COND_NEVER] = "never", + [TCG_COND_ALWAYS] = "always", [TCG_COND_EQ] = "eq", [TCG_COND_NE] = "ne", [TCG_COND_LT] = "lt", diff --git a/tcg/tcg.h b/tcg/tcg.h index 6ff2ab55be..75f0239709 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -266,18 +266,28 @@ typedef int TCGv_i64; #define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-1) #define TCG_CALL_DUMMY_ARG ((TCGArg)(-1)) +/* Conditions. Note that these are layed out for easy manipulation by + the the functions below: + bit 0 is used for inverting; + bit 1 is signed, + bit 2 is unsigned, + bit 3 is used with bit 0 for swapping signed/unsigned. */ typedef enum { - TCG_COND_EQ, - TCG_COND_NE, - TCG_COND_LT, - TCG_COND_GE, - TCG_COND_LE, - TCG_COND_GT, + /* non-signed */ + TCG_COND_NEVER = 0 | 0 | 0 | 0, + TCG_COND_ALWAYS = 0 | 0 | 0 | 1, + TCG_COND_EQ = 8 | 0 | 0 | 0, + TCG_COND_NE = 8 | 0 | 0 | 1, + /* signed */ + TCG_COND_LT = 0 | 0 | 2 | 0, + TCG_COND_GE = 0 | 0 | 2 | 1, + TCG_COND_LE = 8 | 0 | 2 | 0, + TCG_COND_GT = 8 | 0 | 2 | 1, /* unsigned */ - TCG_COND_LTU, - TCG_COND_GEU, - TCG_COND_LEU, - TCG_COND_GTU, + TCG_COND_LTU = 0 | 4 | 0 | 0, + TCG_COND_GEU = 0 | 4 | 0 | 1, + TCG_COND_LEU = 8 | 4 | 0 | 0, + TCG_COND_GTU = 8 | 4 | 0 | 1, } TCGCond; /* Invert the sense of the comparison. */ @@ -289,18 +299,17 @@ static inline TCGCond tcg_invert_cond(TCGCond c) /* Swap the operands in a comparison. */ static inline TCGCond tcg_swap_cond(TCGCond c) { - int mask = (c < TCG_COND_LT ? 0 : c < TCG_COND_LTU ? 7 : 15); - return (TCGCond)(c ^ mask); + return c & 6 ? (TCGCond)(c ^ 9) : c; } static inline TCGCond tcg_unsigned_cond(TCGCond c) { - return (c >= TCG_COND_LT && c <= TCG_COND_GT ? c + 4 : c); + return c & 2 ? (TCGCond)(c ^ 6) : c; } static inline bool is_unsigned_cond(TCGCond c) { - return c >= TCG_COND_LTU; + return (c & 4) != 0; } #define TEMP_VAL_DEAD 0 From d1e321b82a021c2e86d204af870356bc72b22546 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 24 Sep 2012 14:21:41 -0700 Subject: [PATCH 0785/2270] tcg: Add tcg_high_cond The table that was recently added for hppa is generally usable. And with the renumbering of the TCG_COND constants it's not too difficult to compute rather than have a table. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/hppa/tcg-target.c | 17 ++--------------- tcg/tcg.h | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c index b93343015a..de500ae181 100644 --- a/tcg/hppa/tcg-target.c +++ b/tcg/hppa/tcg-target.c @@ -814,19 +814,6 @@ static void tcg_out_comclr(TCGContext *s, int cond, TCGArg ret, tcg_out32(s, op); } -static TCGCond const tcg_high_cond[] = { - [TCG_COND_EQ] = TCG_COND_EQ, - [TCG_COND_NE] = TCG_COND_NE, - [TCG_COND_LT] = TCG_COND_LT, - [TCG_COND_LE] = TCG_COND_LT, - [TCG_COND_GT] = TCG_COND_GT, - [TCG_COND_GE] = TCG_COND_GT, - [TCG_COND_LTU] = TCG_COND_LTU, - [TCG_COND_LEU] = TCG_COND_LTU, - [TCG_COND_GTU] = TCG_COND_GTU, - [TCG_COND_GEU] = TCG_COND_GTU -}; - static void tcg_out_brcond2(TCGContext *s, int cond, TCGArg al, TCGArg ah, TCGArg bl, int blconst, TCGArg bh, int bhconst, int label_index) @@ -841,7 +828,7 @@ static void tcg_out_brcond2(TCGContext *s, int cond, TCGArg al, TCGArg ah, tcg_out_brcond(s, TCG_COND_NE, ah, bh, bhconst, label_index); break; default: - tcg_out_brcond(s, tcg_high_cond[cond], ah, bh, bhconst, label_index); + tcg_out_brcond(s, tcg_high_cond(cond), ah, bh, bhconst, label_index); tcg_out_comclr(s, TCG_COND_NE, TCG_REG_R0, ah, bh, bhconst); tcg_out_brcond(s, tcg_unsigned_cond(cond), al, bl, blconst, label_index); @@ -894,7 +881,7 @@ static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret, tcg_out_setcond(s, tcg_unsigned_cond(cond), scratch, al, bl, blconst); tcg_out_comclr(s, TCG_COND_EQ, TCG_REG_R0, ah, bh, bhconst); tcg_out_movi(s, TCG_TYPE_I32, scratch, 0); - tcg_out_comclr(s, tcg_invert_cond(tcg_high_cond[cond]), + tcg_out_comclr(s, tcg_invert_cond(tcg_high_cond(cond)), TCG_REG_R0, ah, bh, bhconst); tcg_out_movi(s, TCG_TYPE_I32, scratch, 1); break; diff --git a/tcg/tcg.h b/tcg/tcg.h index 75f0239709..562f0adcd4 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -302,16 +302,33 @@ static inline TCGCond tcg_swap_cond(TCGCond c) return c & 6 ? (TCGCond)(c ^ 9) : c; } +/* Create an "unsigned" version of a "signed" comparison. */ static inline TCGCond tcg_unsigned_cond(TCGCond c) { return c & 2 ? (TCGCond)(c ^ 6) : c; } +/* Must a comparison be considered unsigned? */ static inline bool is_unsigned_cond(TCGCond c) { return (c & 4) != 0; } +/* Create a "high" version of a double-word comparison. + This removes equality from a LTE or GTE comparison. */ +static inline TCGCond tcg_high_cond(TCGCond c) +{ + switch (c) { + case TCG_COND_GE: + case TCG_COND_LE: + case TCG_COND_GEU: + case TCG_COND_LEU: + return (TCGCond)(c ^ 8); + default: + return c; + } +} + #define TEMP_VAL_DEAD 0 #define TEMP_VAL_REG 1 #define TEMP_VAL_MEM 2 From 1d31fca470648ec66afd8743491bfb5846306341 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 6 Oct 2012 12:46:15 +0200 Subject: [PATCH 0786/2270] qemu-barrier: Fix compilation on i386 hosts Commit 610b823ef66b993660f1ab1447a769f190e4f3b3 uses QEMU_GNUC_PREREQ on i386 hosts. That macro is defined in qemu-common.h which is not always included before qemu-barrier.h, so compilation on i386 hosts was broken. Signed-off-by: Stefan Weil Signed-off-by: Aurelien Jarno --- qemu-barrier.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qemu-barrier.h b/qemu-barrier.h index 16f09429c3..1de914e882 100644 --- a/qemu-barrier.h +++ b/qemu-barrier.h @@ -6,6 +6,8 @@ #if defined(__i386__) +#include "qemu-common.h" /* QEMU_GNUC_PREREQ */ + /* * Because of the strongly ordered x86 storage model, wmb() and rmb() are nops * on x86(well, a compiler barrier only). Well, at least as long as From d838201111894b17ca9123d5d2a74ab4cf6376d6 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 4 Oct 2012 20:29:02 +0200 Subject: [PATCH 0787/2270] tcg: Remove redundant pointer from TCGContext The pointer entry 'temps' always refers to the array entry 'static_temps'. Removing the pointer and renaming 'static_temps' to 'temps' reduces the size of TCGContext (4 or 8 byte) and allows better code generation. Signed-off-by: Stefan Weil Reviewed-by: Richard Henderson Signed-off-by: Blue Swirl --- tcg/tcg.c | 1 - tcg/tcg.h | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 78ef50b6ee..32cd0c6b65 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -242,7 +242,6 @@ void tcg_context_init(TCGContext *s) int *sorted_args; memset(s, 0, sizeof(*s)); - s->temps = s->static_temps; s->nb_globals = 0; /* Count total number of arguments and allocate the corresponding diff --git a/tcg/tcg.h b/tcg/tcg.h index 562f0adcd4..7bafe0eeb6 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -367,7 +367,6 @@ struct TCGContext { TCGPool *pool_first, *pool_current, *pool_first_large; TCGLabel *labels; int nb_labels; - TCGTemp *temps; /* globals first, temps after */ int nb_globals; int nb_temps; /* index of free temps, -1 if none */ @@ -393,7 +392,7 @@ struct TCGContext { int frame_reg; uint8_t *code_ptr; - TCGTemp static_temps[TCG_MAX_TEMPS]; + TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */ TCGHelperInfo *helpers; int nb_helpers; From 76a23ca099084ce72f5c30a3c5dc18e331384c59 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:54:48 -0700 Subject: [PATCH 0788/2270] target-sparc: Tidy cpu_dump_state We don't really need to be told that %g are general register, etc. Issue a trailing newline to separate blocks. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/cpu.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c index eb9f0e7259..882d30642a 100644 --- a/target-sparc/cpu.c +++ b/target-sparc/cpu.c @@ -792,7 +792,6 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf, cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc, env->npc); - cpu_fprintf(f, "General Registers:\n"); for (i = 0; i < 8; i++) { if (i % REGS_PER_LINE == 0) { @@ -803,7 +802,6 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf, cpu_fprintf(f, "\n"); } } - cpu_fprintf(f, "\nCurrent Register Window:\n"); for (x = 0; x < 3; x++) { for (i = 0; i < 8; i++) { if (i % REGS_PER_LINE == 0) { @@ -817,10 +815,10 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf, } } } - cpu_fprintf(f, "\nFloating Point Registers:\n"); + for (i = 0; i < TARGET_DPREGS; i++) { if ((i & 3) == 0) { - cpu_fprintf(f, "%%f%02d:", i * 2); + cpu_fprintf(f, "%%f%02d: ", i * 2); } cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll); if ((i & 3) == 3) { @@ -850,6 +848,7 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf, cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n", env->fsr, env->y); #endif + cpu_fprintf(f, "\n"); } static void sparc_cpu_initfn(Object *obj) From b884fc5ecaacd241829f225282356d59eb186645 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:54:49 -0700 Subject: [PATCH 0789/2270] target-sparc: Make CPU_LOG_INT useful by default No need for ifdefs when the log mask does just as well. No need to print pc/npc when we're dumping the whole cpu state. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/int32_helper.c | 7 ++----- target-sparc/int64_helper.c | 8 ++------ 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c index 5e33d50e23..9ac5aac33a 100644 --- a/target-sparc/int32_helper.c +++ b/target-sparc/int32_helper.c @@ -21,7 +21,7 @@ #include "trace.h" #include "sysemu.h" -//#define DEBUG_PCALL +#define DEBUG_PCALL #ifdef DEBUG_PCALL static const char * const excp_names[0x80] = { @@ -78,10 +78,7 @@ void do_interrupt(CPUSPARCState *env) } } - qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n", - count, name, intno, - env->pc, - env->npc, env->regwptr[6]); + qemu_log("%6d: %s (v=%02x)\n", count, name, intno); log_cpu_state(env, 0); #if 0 { diff --git a/target-sparc/int64_helper.c b/target-sparc/int64_helper.c index 5e3eff76dd..5d0bc6c6d2 100644 --- a/target-sparc/int64_helper.c +++ b/target-sparc/int64_helper.c @@ -21,7 +21,7 @@ #include "helper.h" #include "trace.h" -//#define DEBUG_PCALL +#define DEBUG_PCALL #ifdef DEBUG_PCALL static const char * const excp_names[0x80] = { @@ -84,11 +84,7 @@ void do_interrupt(CPUSPARCState *env) } } - qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64 - " SP=%016" PRIx64 "\n", - count, name, intno, - env->pc, - env->npc, env->regwptr[6]); + qemu_log("%6d: %s (v=%04x)\n", count, name, intno); log_cpu_state(env, 0); #if 0 { From d4a288ef9c2b432307961429bdcacb2416ad8a99 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:54:50 -0700 Subject: [PATCH 0790/2270] target-sparc: Tidy do_branch interfaces We always pass cpu_cond to the r_cond parameter. Use that global register directly instead of passing it down. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index e5ebedfa2c..079a040442 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -1337,8 +1337,7 @@ static inline void gen_cond_reg(TCGv r_dst, int cond, TCGv r_src) } #endif -static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc, - TCGv r_cond) +static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc) { unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29)); target_ulong target = dc->pc + offset; @@ -1368,10 +1367,10 @@ static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc, tcg_gen_mov_tl(cpu_pc, cpu_npc); } } else { - flush_cond(dc, r_cond); - gen_cond(r_cond, cc, cond, dc); + flush_cond(dc, cpu_cond); + gen_cond(cpu_cond, cc, cond, dc); if (a) { - gen_branch_a(dc, target, dc->npc, r_cond); + gen_branch_a(dc, target, dc->npc, cpu_cond); dc->is_br = 1; } else { dc->pc = dc->npc; @@ -1387,8 +1386,7 @@ static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc, } } -static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc, - TCGv r_cond) +static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc) { unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29)); target_ulong target = dc->pc + offset; @@ -1418,10 +1416,10 @@ static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc, tcg_gen_mov_tl(cpu_pc, cpu_npc); } } else { - flush_cond(dc, r_cond); - gen_fcond(r_cond, cc, cond); + flush_cond(dc, cpu_cond); + gen_fcond(cpu_cond, cc, cond); if (a) { - gen_branch_a(dc, target, dc->npc, r_cond); + gen_branch_a(dc, target, dc->npc, cpu_cond); dc->is_br = 1; } else { dc->pc = dc->npc; @@ -1439,7 +1437,7 @@ static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc, #ifdef TARGET_SPARC64 static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn, - TCGv r_cond, TCGv r_reg) + TCGv r_reg) { unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29)); target_ulong target = dc->pc + offset; @@ -1447,10 +1445,10 @@ static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn, if (unlikely(AM_CHECK(dc))) { target &= 0xffffffffULL; } - flush_cond(dc, r_cond); - gen_cond_reg(r_cond, cond, r_reg); + flush_cond(dc, cpu_cond); + gen_cond_reg(cpu_cond, cond, r_reg); if (a) { - gen_branch_a(dc, target, dc->npc, r_cond); + gen_branch_a(dc, target, dc->npc, cpu_cond); dc->is_br = 1; } else { dc->pc = dc->npc; @@ -2421,9 +2419,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) target <<= 2; cc = GET_FIELD_SP(insn, 20, 21); if (cc == 0) - do_branch(dc, target, insn, 0, cpu_cond); + do_branch(dc, target, insn, 0); else if (cc == 2) - do_branch(dc, target, insn, 1, cpu_cond); + do_branch(dc, target, insn, 1); else goto illegal_insn; goto jmp_insn; @@ -2435,7 +2433,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) target = sign_extend(target, 16); target <<= 2; cpu_src1 = get_src1(insn, cpu_src1); - do_branch_reg(dc, target, insn, cpu_cond, cpu_src1); + do_branch_reg(dc, target, insn, cpu_src1); goto jmp_insn; } case 0x5: /* V9 FBPcc */ @@ -2446,7 +2444,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) target = GET_FIELD_SP(insn, 0, 18); target = sign_extend(target, 19); target <<= 2; - do_fbranch(dc, target, insn, cc, cpu_cond); + do_fbranch(dc, target, insn, cc); goto jmp_insn; } #else @@ -2460,7 +2458,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) target = GET_FIELD(insn, 10, 31); target = sign_extend(target, 22); target <<= 2; - do_branch(dc, target, insn, 0, cpu_cond); + do_branch(dc, target, insn, 0); goto jmp_insn; } case 0x6: /* FBN+x */ @@ -2470,7 +2468,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) target = GET_FIELD(insn, 10, 31); target = sign_extend(target, 22); target <<= 2; - do_fbranch(dc, target, insn, 0, cpu_cond); + do_fbranch(dc, target, insn, 0); goto jmp_insn; } case 0x4: /* SETHI */ From dee8913cbf82a03fed661ac6c461491045dac7f5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:54:51 -0700 Subject: [PATCH 0791/2270] target-sparc: Tidy flush_cond interface We always pass cpu_cond to the cond parameter. Use that global register directly instead of passing it down. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 079a040442..5b2d5ea71b 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -1118,10 +1118,10 @@ static inline void gen_generic_branch(target_ulong npc1, target_ulong npc2, /* call this function before using the condition register as it may have been set for a jump */ -static inline void flush_cond(DisasContext *dc, TCGv cond) +static inline void flush_cond(DisasContext *dc) { if (dc->npc == JUMP_PC) { - gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cond); + gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cpu_cond); dc->npc = DYNAMIC_PC; } } @@ -1367,7 +1367,7 @@ static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc) tcg_gen_mov_tl(cpu_pc, cpu_npc); } } else { - flush_cond(dc, cpu_cond); + flush_cond(dc); gen_cond(cpu_cond, cc, cond, dc); if (a) { gen_branch_a(dc, target, dc->npc, cpu_cond); @@ -1416,7 +1416,7 @@ static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc) tcg_gen_mov_tl(cpu_pc, cpu_npc); } } else { - flush_cond(dc, cpu_cond); + flush_cond(dc); gen_fcond(cpu_cond, cc, cond); if (a) { gen_branch_a(dc, target, dc->npc, cpu_cond); @@ -1445,7 +1445,7 @@ static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn, if (unlikely(AM_CHECK(dc))) { target &= 0xffffffffULL; } - flush_cond(dc, cpu_cond); + flush_cond(dc); gen_cond_reg(cpu_cond, cond, r_reg); if (a) { gen_branch_a(dc, target, dc->npc, cpu_cond); From 5b12f1e8a1aad8030c3ec5790cb5f8f370a1df1f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:54:52 -0700 Subject: [PATCH 0792/2270] target-sparc: Tidy gen_trap_ifnofpu interface We always pass cpu_cond to the cond parameter. Use that global register directly instead of passing it down. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 46 ++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 5b2d5ea71b..9787664a24 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -1615,13 +1615,13 @@ static inline void gen_op_fpexception_im(int fsr_flags) tcg_temp_free_i32(r_const); } -static int gen_trap_ifnofpu(DisasContext *dc, TCGv r_cond) +static int gen_trap_ifnofpu(DisasContext *dc) { #if !defined(CONFIG_USER_ONLY) if (!dc->fpu_enabled) { TCGv_i32 r_const; - save_state(dc, r_cond); + save_state(dc, cpu_cond); r_const = tcg_const_i32(TT_NFPU_INSN); gen_helper_raise_exception(cpu_env, r_const); tcg_temp_free_i32(r_const); @@ -2439,8 +2439,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x5: /* V9 FBPcc */ { int cc = GET_FIELD_SP(insn, 20, 21); - if (gen_trap_ifnofpu(dc, cpu_cond)) + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; + } target = GET_FIELD_SP(insn, 0, 18); target = sign_extend(target, 19); target <<= 2; @@ -2463,8 +2464,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } case 0x6: /* FBN+x */ { - if (gen_trap_ifnofpu(dc, cpu_cond)) + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; + } target = GET_FIELD(insn, 10, 31); target = sign_extend(target, 22); target <<= 2; @@ -2643,8 +2645,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0xf: /* V9 membar */ break; /* no effect */ case 0x13: /* Graphics Status */ - if (gen_trap_ifnofpu(dc, cpu_cond)) + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; + } gen_movl_TN_reg(rd, cpu_gsr); break; case 0x16: /* Softint */ @@ -2861,8 +2864,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; #endif } else if (xop == 0x34) { /* FPU Operations */ - if (gen_trap_ifnofpu(dc, cpu_cond)) + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; + } gen_op_clear_ieee_excp_and_FTT(); rs1 = GET_FIELD(insn, 13, 17); rs2 = GET_FIELD(insn, 27, 31); @@ -3035,8 +3039,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #ifdef TARGET_SPARC64 int cond; #endif - if (gen_trap_ifnofpu(dc, cpu_cond)) + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; + } gen_op_clear_ieee_excp_and_FTT(); rs1 = GET_FIELD(insn, 13, 17); rs2 = GET_FIELD(insn, 27, 31); @@ -3699,8 +3704,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #endif break; case 0x13: /* Graphics Status */ - if (gen_trap_ifnofpu(dc, cpu_cond)) + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; + } tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2); break; case 0x14: /* Softint set */ @@ -4105,8 +4111,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) int opf = GET_FIELD_SP(insn, 5, 13); rs1 = GET_FIELD(insn, 13, 17); rs2 = GET_FIELD(insn, 27, 31); - if (gen_trap_ifnofpu(dc, cpu_cond)) + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; + } switch (opf) { case 0x000: /* VIS I edge8cc */ @@ -4873,7 +4880,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x2d: /* V9 prefetch, no effect */ goto skip_move; case 0x30: /* V9 ldfa */ - if (gen_trap_ifnofpu(dc, cpu_cond)) { + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } save_state(dc, cpu_cond); @@ -4881,7 +4888,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_update_fprs_dirty(rd); goto skip_move; case 0x33: /* V9 lddfa */ - if (gen_trap_ifnofpu(dc, cpu_cond)) { + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } save_state(dc, cpu_cond); @@ -4892,7 +4899,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto skip_move; case 0x32: /* V9 ldqfa */ CHECK_FPU_FEATURE(dc, FLOAT128); - if (gen_trap_ifnofpu(dc, cpu_cond)) { + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } save_state(dc, cpu_cond); @@ -4908,8 +4915,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) skip_move: ; #endif } else if (xop >= 0x20 && xop < 0x24) { - if (gen_trap_ifnofpu(dc, cpu_cond)) + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; + } save_state(dc, cpu_cond); switch (xop) { case 0x20: /* ldf, load fpreg */ @@ -5056,8 +5064,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto illegal_insn; } } else if (xop > 0x23 && xop < 0x28) { - if (gen_trap_ifnofpu(dc, cpu_cond)) + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; + } save_state(dc, cpu_cond); switch (xop) { case 0x24: /* stf, store fpreg */ @@ -5100,8 +5109,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #else if (!supervisor(dc)) goto priv_insn; - if (gen_trap_ifnofpu(dc, cpu_cond)) + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; + } goto nfq_insn; #endif #endif @@ -5118,7 +5128,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) switch (xop) { #ifdef TARGET_SPARC64 case 0x34: /* V9 stfa */ - if (gen_trap_ifnofpu(dc, cpu_cond)) { + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } gen_stf_asi(cpu_addr, insn, 4, rd); @@ -5128,7 +5138,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) TCGv_i32 r_const; CHECK_FPU_FEATURE(dc, FLOAT128); - if (gen_trap_ifnofpu(dc, cpu_cond)) { + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } r_const = tcg_const_i32(7); @@ -5138,7 +5148,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } break; case 0x37: /* V9 stdfa */ - if (gen_trap_ifnofpu(dc, cpu_cond)) { + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd)); From 66442b07ae37a23c727ecd8c30a25054a7f21886 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:54:53 -0700 Subject: [PATCH 0793/2270] target-sparc: Tidy save_state interface Use the cpu_cond global register directly instead of passing it down. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 98 ++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 9787664a24..eb952608df 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -1136,7 +1136,7 @@ static inline void save_npc(DisasContext *dc, TCGv cond) } } -static inline void save_state(DisasContext *dc, TCGv cond) +static inline void save_state(DisasContext *dc) { tcg_gen_movi_tl(cpu_pc, dc->pc); /* flush pending conditional evaluations before exposing cpu state */ @@ -1144,7 +1144,7 @@ static inline void save_state(DisasContext *dc, TCGv cond) dc->cc_op = CC_OP_FLAGS; gen_helper_compute_psr(cpu_env); } - save_npc(dc, cond); + save_npc(dc, cpu_cond); } static inline void gen_mov_pc_npc(DisasContext *dc, TCGv cond) @@ -1621,7 +1621,7 @@ static int gen_trap_ifnofpu(DisasContext *dc) if (!dc->fpu_enabled) { TCGv_i32 r_const; - save_state(dc, cpu_cond); + save_state(dc); r_const = tcg_const_i32(TT_NFPU_INSN); gen_helper_raise_exception(cpu_env, r_const); tcg_temp_free_i32(r_const); @@ -2529,7 +2529,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) cond = GET_FIELD(insn, 3, 6); if (cond == 0x8) { /* Trap Always */ - save_state(dc, cpu_cond); + save_state(dc); if ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)) tcg_gen_andi_tl(cpu_dst, cpu_dst, UA2005_HTRAP_MASK); @@ -2546,7 +2546,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) /* V9 icc/xcc */ int cc = GET_FIELD_SP(insn, 11, 12); - save_state(dc, cpu_cond); + save_state(dc); if (cc == 0) gen_cond(r_cond, 0, cond, dc); else if (cc == 2) @@ -2554,7 +2554,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) else goto illegal_insn; #else - save_state(dc, cpu_cond); + save_state(dc); gen_cond(r_cond, 0, cond, dc); #endif l1 = gen_new_label(); @@ -2854,7 +2854,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; } else if (xop == 0x2b) { /* rdtbr / V9 flushw */ #ifdef TARGET_SPARC64 - save_state(dc, cpu_cond); + save_state(dc); gen_helper_flushw(cpu_env); #else if (!supervisor(dc)) @@ -2871,7 +2871,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) rs1 = GET_FIELD(insn, 13, 17); rs2 = GET_FIELD(insn, 27, 31); xop = GET_FIELD(insn, 18, 26); - save_state(dc, cpu_cond); + save_state(dc); switch (xop) { case 0x1: /* fmovs */ cpu_src1_32 = gen_load_fpr_F(dc, rs2); @@ -3046,7 +3046,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) rs1 = GET_FIELD(insn, 13, 17); rs2 = GET_FIELD(insn, 27, 31); xop = GET_FIELD(insn, 18, 26); - save_state(dc, cpu_cond); + save_state(dc); #ifdef TARGET_SPARC64 if ((xop & 0x11f) == 0x005) { // V9 fmovsr int l1; @@ -3607,14 +3607,14 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) dc->cc_op = CC_OP_TSUB; break; case 0x22: /* taddcctv */ - save_state(dc, cpu_cond); + save_state(dc); gen_op_tadd_ccTV(cpu_dst, cpu_src1, cpu_src2); gen_movl_TN_reg(rd, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADDTV); dc->cc_op = CC_OP_TADDTV; break; case 0x23: /* tsubcctv */ - save_state(dc, cpu_cond); + save_state(dc); gen_op_tsub_ccTV(cpu_dst, cpu_src1, cpu_src2); gen_movl_TN_reg(rd, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUBTV); @@ -3691,7 +3691,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x6: /* V9 wrfprs */ tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2); tcg_gen_trunc_tl_i32(cpu_fprs, cpu_dst); - save_state(dc, cpu_cond); + save_state(dc); gen_op_next_insn(); tcg_gen_exit_tb(0); dc->is_br = 1; @@ -3818,7 +3818,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_helper_wrpsr(cpu_env, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS); dc->cc_op = CC_OP_FLAGS; - save_state(dc, cpu_cond); + save_state(dc); gen_op_next_insn(); tcg_gen_exit_tb(0); dc->is_br = 1; @@ -3898,7 +3898,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) TCGv r_tmp = tcg_temp_local_new(); tcg_gen_mov_tl(r_tmp, cpu_tmp0); - save_state(dc, cpu_cond); + save_state(dc); gen_helper_wrpstate(cpu_env, r_tmp); tcg_temp_free(r_tmp); dc->npc = DYNAMIC_PC; @@ -3909,7 +3909,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) TCGv r_tmp = tcg_temp_local_new(); tcg_gen_mov_tl(r_tmp, cpu_tmp0); - save_state(dc, cpu_cond); + save_state(dc); tcg_gen_trunc_tl_i32(cpu_tmp32, r_tmp); tcg_temp_free(r_tmp); tcg_gen_st_i32(cpu_tmp32, cpu_env, @@ -3991,7 +3991,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) switch (rd) { case 0: // hpstate // XXX gen_op_wrhpstate(); - save_state(dc, cpu_cond); + save_state(dc); gen_op_next_insn(); tcg_gen_exit_tb(0); dc->is_br = 1; @@ -4559,7 +4559,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } else if (xop == 0x39) { /* V9 return */ TCGv_i32 r_const; - save_state(dc, cpu_cond); + save_state(dc); cpu_src1 = get_src1(insn, cpu_src1); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); @@ -4635,12 +4635,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) /* nop */ break; case 0x3c: /* save */ - save_state(dc, cpu_cond); + save_state(dc); gen_helper_save(cpu_env); gen_movl_TN_reg(rd, cpu_dst); break; case 0x3d: /* restore */ - save_state(dc, cpu_cond); + save_state(dc); gen_helper_restore(cpu_env); gen_movl_TN_reg(rd, cpu_dst); break; @@ -4723,7 +4723,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) else { TCGv_i32 r_const; - save_state(dc, cpu_cond); + save_state(dc); r_const = tcg_const_i32(7); /* XXX remove alignment check */ gen_helper_check_align(cpu_env, cpu_addr, r_const); @@ -4774,7 +4774,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (!supervisor(dc)) goto priv_insn; #endif - save_state(dc, cpu_cond); + save_state(dc); gen_ld_asi(cpu_val, cpu_addr, insn, 4, 0); break; case 0x11: /* lduba, load unsigned byte alternate */ @@ -4784,7 +4784,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (!supervisor(dc)) goto priv_insn; #endif - save_state(dc, cpu_cond); + save_state(dc); gen_ld_asi(cpu_val, cpu_addr, insn, 1, 0); break; case 0x12: /* lduha, load unsigned halfword alternate */ @@ -4794,7 +4794,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (!supervisor(dc)) goto priv_insn; #endif - save_state(dc, cpu_cond); + save_state(dc); gen_ld_asi(cpu_val, cpu_addr, insn, 2, 0); break; case 0x13: /* ldda, load double word alternate */ @@ -4806,7 +4806,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #endif if (rd & 1) goto illegal_insn; - save_state(dc, cpu_cond); + save_state(dc); gen_ldda_asi(cpu_val, cpu_addr, insn, rd); goto skip_move; case 0x19: /* ldsba, load signed byte alternate */ @@ -4816,7 +4816,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (!supervisor(dc)) goto priv_insn; #endif - save_state(dc, cpu_cond); + save_state(dc); gen_ld_asi(cpu_val, cpu_addr, insn, 1, 1); break; case 0x1a: /* ldsha, load signed halfword alternate */ @@ -4826,7 +4826,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (!supervisor(dc)) goto priv_insn; #endif - save_state(dc, cpu_cond); + save_state(dc); gen_ld_asi(cpu_val, cpu_addr, insn, 2, 1); break; case 0x1d: /* ldstuba -- XXX: should be atomically */ @@ -4836,7 +4836,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (!supervisor(dc)) goto priv_insn; #endif - save_state(dc, cpu_cond); + save_state(dc); gen_ldstub_asi(cpu_val, cpu_addr, insn); break; case 0x1f: /* swapa, swap reg with alt. memory. Also @@ -4848,7 +4848,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (!supervisor(dc)) goto priv_insn; #endif - save_state(dc, cpu_cond); + save_state(dc); gen_movl_reg_TN(rd, cpu_val); gen_swap_asi(cpu_val, cpu_addr, insn); break; @@ -4870,11 +4870,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx); break; case 0x18: /* V9 ldswa */ - save_state(dc, cpu_cond); + save_state(dc); gen_ld_asi(cpu_val, cpu_addr, insn, 4, 1); break; case 0x1b: /* V9 ldxa */ - save_state(dc, cpu_cond); + save_state(dc); gen_ld_asi(cpu_val, cpu_addr, insn, 8, 0); break; case 0x2d: /* V9 prefetch, no effect */ @@ -4883,7 +4883,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } - save_state(dc, cpu_cond); + save_state(dc); gen_ldf_asi(cpu_addr, insn, 4, rd); gen_update_fprs_dirty(rd); goto skip_move; @@ -4891,7 +4891,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } - save_state(dc, cpu_cond); + save_state(dc); gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd)); gen_update_fprs_dirty(DFPREG(rd)); goto skip_move; @@ -4902,7 +4902,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } - save_state(dc, cpu_cond); + save_state(dc); gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd)); gen_update_fprs_dirty(QFPREG(rd)); goto skip_move; @@ -4918,7 +4918,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } - save_state(dc, cpu_cond); + save_state(dc); switch (xop) { case 0x20: /* ldf, load fpreg */ gen_address_mask(dc, cpu_addr); @@ -4989,7 +4989,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) else { TCGv_i32 r_const; - save_state(dc, cpu_cond); + save_state(dc); gen_address_mask(dc, cpu_addr); r_const = tcg_const_i32(7); /* XXX remove alignment check */ @@ -5008,7 +5008,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (!supervisor(dc)) goto priv_insn; #endif - save_state(dc, cpu_cond); + save_state(dc); gen_st_asi(cpu_val, cpu_addr, insn, 4); dc->npc = DYNAMIC_PC; break; @@ -5019,7 +5019,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (!supervisor(dc)) goto priv_insn; #endif - save_state(dc, cpu_cond); + save_state(dc); gen_st_asi(cpu_val, cpu_addr, insn, 1); dc->npc = DYNAMIC_PC; break; @@ -5030,7 +5030,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (!supervisor(dc)) goto priv_insn; #endif - save_state(dc, cpu_cond); + save_state(dc); gen_st_asi(cpu_val, cpu_addr, insn, 2); dc->npc = DYNAMIC_PC; break; @@ -5044,7 +5044,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (rd & 1) goto illegal_insn; else { - save_state(dc, cpu_cond); + save_state(dc); gen_stda_asi(cpu_val, cpu_addr, insn, rd); } break; @@ -5055,7 +5055,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx); break; case 0x1e: /* V9 stxa */ - save_state(dc, cpu_cond); + save_state(dc); gen_st_asi(cpu_val, cpu_addr, insn, 8); dc->npc = DYNAMIC_PC; break; @@ -5067,7 +5067,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } - save_state(dc, cpu_cond); + save_state(dc); switch (xop) { case 0x24: /* stf, store fpreg */ gen_address_mask(dc, cpu_addr); @@ -5124,7 +5124,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto illegal_insn; } } else if (xop > 0x33 && xop < 0x3f) { - save_state(dc, cpu_cond); + save_state(dc); switch (xop) { #ifdef TARGET_SPARC64 case 0x34: /* V9 stfa */ @@ -5194,7 +5194,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) { TCGv_i32 r_const; - save_state(dc, cpu_cond); + save_state(dc); r_const = tcg_const_i32(TT_ILL_INSN); gen_helper_raise_exception(cpu_env, r_const); tcg_temp_free_i32(r_const); @@ -5205,7 +5205,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) { TCGv_i32 r_const; - save_state(dc, cpu_cond); + save_state(dc); r_const = tcg_const_i32(TT_UNIMP_FLUSH); gen_helper_raise_exception(cpu_env, r_const); tcg_temp_free_i32(r_const); @@ -5217,7 +5217,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) { TCGv_i32 r_const; - save_state(dc, cpu_cond); + save_state(dc); r_const = tcg_const_i32(TT_PRIV_INSN); gen_helper_raise_exception(cpu_env, r_const); tcg_temp_free_i32(r_const); @@ -5226,13 +5226,13 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto egress; #endif nfpu_insn: - save_state(dc, cpu_cond); + save_state(dc); gen_op_fpexception_im(FSR_FTT_UNIMPFPOP); dc->is_br = 1; goto egress; #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) nfq_insn: - save_state(dc, cpu_cond); + save_state(dc); gen_op_fpexception_im(FSR_FTT_SEQ_ERROR); dc->is_br = 1; goto egress; @@ -5242,7 +5242,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) { TCGv r_const; - save_state(dc, cpu_cond); + save_state(dc); r_const = tcg_const_i32(TT_NCP_INSN); gen_helper_raise_exception(cpu_env, r_const); tcg_temp_free(r_const); @@ -5308,7 +5308,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, QTAILQ_FOREACH(bp, &env->breakpoints, entry) { if (bp->pc == dc->pc) { if (dc->pc != pc_start) - save_state(dc, cpu_cond); + save_state(dc); gen_helper_debug(cpu_env); tcg_gen_exit_tb(0); dc->is_br = 1; From 13a6dd00433005831c2bc671b0e085cb5b04b424 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:54:54 -0700 Subject: [PATCH 0794/2270] target-sparc: Tidy gen_mov_pc_npc interface Use the cpu_cond global register directly instead of passing it down. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index eb952608df..d9e1b01550 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -1147,10 +1147,10 @@ static inline void save_state(DisasContext *dc) save_npc(dc, cpu_cond); } -static inline void gen_mov_pc_npc(DisasContext *dc, TCGv cond) +static inline void gen_mov_pc_npc(DisasContext *dc) { if (dc->npc == JUMP_PC) { - gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cond); + gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cpu_cond); tcg_gen_mov_tl(cpu_pc, cpu_npc); dc->pc = DYNAMIC_PC; } else if (dc->npc == DYNAMIC_PC) { @@ -2499,7 +2499,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_movl_TN_reg(15, r_const); tcg_temp_free(r_const); target += dc->pc; - gen_mov_pc_npc(dc, cpu_cond); + gen_mov_pc_npc(dc); #ifdef TARGET_SPARC64 if (unlikely(AM_CHECK(dc))) { target &= 0xffffffffULL; @@ -4573,7 +4573,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_mov_tl(cpu_dst, cpu_src1); } gen_helper_restore(cpu_env); - gen_mov_pc_npc(dc, cpu_cond); + gen_mov_pc_npc(dc); r_const = tcg_const_i32(3); gen_helper_check_align(cpu_env, cpu_dst, r_const); tcg_temp_free_i32(r_const); @@ -4603,7 +4603,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) r_pc = tcg_const_tl(dc->pc); gen_movl_TN_reg(rd, r_pc); tcg_temp_free(r_pc); - gen_mov_pc_npc(dc, cpu_cond); + gen_mov_pc_npc(dc); r_const = tcg_const_i32(3); gen_helper_check_align(cpu_env, cpu_dst, r_const); tcg_temp_free_i32(r_const); @@ -4619,7 +4619,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (!supervisor(dc)) goto priv_insn; - gen_mov_pc_npc(dc, cpu_cond); + gen_mov_pc_npc(dc); r_const = tcg_const_i32(3); gen_helper_check_align(cpu_env, cpu_dst, r_const); tcg_temp_free_i32(r_const); From 934da7ee0840f582c7720d0ce4507456d9955feb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:54:55 -0700 Subject: [PATCH 0795/2270] target-sparc: Tidy save_npc interface Use the cpu_cond global register directly instead of passing it down. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index d9e1b01550..4cc78872d4 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -1126,10 +1126,10 @@ static inline void flush_cond(DisasContext *dc) } } -static inline void save_npc(DisasContext *dc, TCGv cond) +static inline void save_npc(DisasContext *dc) { if (dc->npc == JUMP_PC) { - gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cond); + gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cpu_cond); dc->npc = DYNAMIC_PC; } else if (dc->npc != DYNAMIC_PC) { tcg_gen_movi_tl(cpu_npc, dc->npc); @@ -1144,7 +1144,7 @@ static inline void save_state(DisasContext *dc) dc->cc_op = CC_OP_FLAGS; gen_helper_compute_psr(cpu_env); } - save_npc(dc, cpu_cond); + save_npc(dc); } static inline void gen_mov_pc_npc(DisasContext *dc) @@ -5372,7 +5372,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, } else { if (dc->pc != DYNAMIC_PC) tcg_gen_movi_tl(cpu_pc, dc->pc); - save_npc(dc, cpu_cond); + save_npc(dc); tcg_gen_exit_tb(0); } } From 2e655fe768d9873d07be3be264c042c35720694b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:54:56 -0700 Subject: [PATCH 0796/2270] target-sparc: Tidy gen_generic_branch interface The arguments passed are always the same. Pass down just DisasContext instead. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 4cc78872d4..d759da21c8 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -1098,21 +1098,20 @@ static inline void gen_branch_a(DisasContext *dc, target_ulong pc1, gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8); } -static inline void gen_generic_branch(target_ulong npc1, target_ulong npc2, - TCGv r_cond) +static inline void gen_generic_branch(DisasContext *dc) { int l1, l2; l1 = gen_new_label(); l2 = gen_new_label(); - tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_cond, 0, l1); - tcg_gen_movi_tl(cpu_npc, npc1); + tcg_gen_movi_tl(cpu_npc, dc->jump_pc[0]); tcg_gen_br(l2); gen_set_label(l1); - tcg_gen_movi_tl(cpu_npc, npc2); + tcg_gen_movi_tl(cpu_npc, dc->jump_pc[1]); gen_set_label(l2); } @@ -1121,7 +1120,7 @@ static inline void gen_generic_branch(target_ulong npc1, target_ulong npc2, static inline void flush_cond(DisasContext *dc) { if (dc->npc == JUMP_PC) { - gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cpu_cond); + gen_generic_branch(dc); dc->npc = DYNAMIC_PC; } } @@ -1129,7 +1128,7 @@ static inline void flush_cond(DisasContext *dc) static inline void save_npc(DisasContext *dc) { if (dc->npc == JUMP_PC) { - gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cpu_cond); + gen_generic_branch(dc); dc->npc = DYNAMIC_PC; } else if (dc->npc != DYNAMIC_PC) { tcg_gen_movi_tl(cpu_npc, dc->npc); @@ -1150,7 +1149,7 @@ static inline void save_state(DisasContext *dc) static inline void gen_mov_pc_npc(DisasContext *dc) { if (dc->npc == JUMP_PC) { - gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cpu_cond); + gen_generic_branch(dc); tcg_gen_mov_tl(cpu_pc, cpu_npc); dc->pc = DYNAMIC_PC; } else if (dc->npc == DYNAMIC_PC) { From 416fcaea1ef7e9a71ccb0a968de594618ed7675e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:54:57 -0700 Subject: [PATCH 0797/2270] target-sparc: Introduce DisasCompare and functions to generate it For the moment gen_cond et al retain their existing interface, using setcond to turn a (potential) comparison back into a boolean. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 92 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 9 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index d759da21c8..d61a9a031f 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -86,6 +86,13 @@ typedef struct DisasContext { int n_t32; } DisasContext; +typedef struct { + TCGCond cond; + bool is_bool; + bool g1, g2; + TCGv c1, c2; +} DisasCompare; + // This function uses non-native bit order #define GET_FIELD(X, FROM, TO) \ ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1)) @@ -1166,10 +1173,28 @@ static inline void gen_op_next_insn(void) tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); } -static inline void gen_cond(TCGv r_dst, unsigned int cc, unsigned int cond, - DisasContext *dc) +static void free_compare(DisasCompare *cmp) +{ + if (!cmp->g1) { + tcg_temp_free(cmp->c1); + } + if (!cmp->g2) { + tcg_temp_free(cmp->c2); + } +} + +static void gen_compare(DisasCompare *cmp, unsigned int cc, unsigned int cond, + DisasContext *dc) { TCGv_i32 r_src; + TCGv r_dst; + + /* For now we still generate a straight boolean result. */ + cmp->cond = TCG_COND_NE; + cmp->is_bool = true; + cmp->g1 = cmp->g2 = false; + cmp->c1 = r_dst = tcg_temp_new(); + cmp->c2 = tcg_const_tl(0); #ifdef TARGET_SPARC64 if (cc) @@ -1239,9 +1264,17 @@ static inline void gen_cond(TCGv r_dst, unsigned int cc, unsigned int cond, } } -static inline void gen_fcond(TCGv r_dst, unsigned int cc, unsigned int cond) +static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond) { unsigned int offset; + TCGv r_dst; + + /* For now we still generate a straight boolean result. */ + cmp->cond = TCG_COND_NE; + cmp->is_bool = true; + cmp->g1 = cmp->g2 = false; + cmp->c1 = r_dst = tcg_temp_new(); + cmp->c2 = tcg_const_tl(0); switch (cc) { default: @@ -1311,6 +1344,37 @@ static inline void gen_fcond(TCGv r_dst, unsigned int cc, unsigned int cond) } } +static void gen_cond(TCGv r_dst, unsigned int cc, unsigned int cond, + DisasContext *dc) +{ + DisasCompare cmp; + gen_compare(&cmp, cc, cond, dc); + + /* The interface is to return a boolean in r_dst. */ + if (cmp.is_bool) { + tcg_gen_mov_tl(r_dst, cmp.c1); + } else { + tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2); + } + + free_compare(&cmp); +} + +static void gen_fcond(TCGv r_dst, unsigned int cc, unsigned int cond) +{ + DisasCompare cmp; + gen_fcompare(&cmp, cc, cond); + + /* The interface is to return a boolean in r_dst. */ + if (cmp.is_bool) { + tcg_gen_mov_tl(r_dst, cmp.c1); + } else { + tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2); + } + + free_compare(&cmp); +} + #ifdef TARGET_SPARC64 // Inverted logic static const int gen_tcg_cond_reg[8] = { @@ -1324,15 +1388,25 @@ static const int gen_tcg_cond_reg[8] = { TCG_COND_LT, }; +static void gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src) +{ + cmp->cond = tcg_invert_cond(gen_tcg_cond_reg[cond]); + cmp->is_bool = false; + cmp->g1 = true; + cmp->g2 = false; + cmp->c1 = r_src; + cmp->c2 = tcg_const_tl(0); +} + static inline void gen_cond_reg(TCGv r_dst, int cond, TCGv r_src) { - int l1; + DisasCompare cmp; + gen_compare_reg(&cmp, cond, r_src); - l1 = gen_new_label(); - tcg_gen_movi_tl(r_dst, 0); - tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], r_src, 0, l1); - tcg_gen_movi_tl(r_dst, 1); - gen_set_label(l1); + /* The interface is to return a boolean in r_dst. */ + tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2); + + free_compare(&cmp); } #endif From 3a49e7598b78bca019e35c42590914faab2a817a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:54:58 -0700 Subject: [PATCH 0798/2270] target-sparc: Use DisasCompare in Tcc Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index d61a9a031f..fa9a05799c 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2613,25 +2613,28 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_helper_raise_exception(cpu_env, cpu_tmp32); } else if (cond != 0) { - TCGv r_cond = tcg_temp_new(); + DisasCompare cmp; int l1; #ifdef TARGET_SPARC64 /* V9 icc/xcc */ int cc = GET_FIELD_SP(insn, 11, 12); save_state(dc); - if (cc == 0) - gen_cond(r_cond, 0, cond, dc); - else if (cc == 2) - gen_cond(r_cond, 1, cond, dc); - else + if (cc == 0) { + gen_compare(&cmp, 0, cond, dc); + } else if (cc == 2) { + gen_compare(&cmp, 1, cond, dc); + } else { goto illegal_insn; + } #else save_state(dc); - gen_cond(r_cond, 0, cond, dc); + gen_compare(&cmp, 0, cond, dc); #endif l1 = gen_new_label(); - tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1); + tcg_gen_brcond_tl(tcg_invert_cond(cmp.cond), + cmp.c1, cmp.c2, l1); + free_compare(&cmp); if ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)) @@ -2643,7 +2646,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_helper_raise_exception(cpu_env, cpu_tmp32); gen_set_label(l1); - tcg_temp_free(r_cond); } gen_op_next_insn(); tcg_gen_exit_tb(0); From 7e480893cc3eb9f307199517f0e1d5c8e72a030f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:54:59 -0700 Subject: [PATCH 0799/2270] target-sparc: Use DisasCompare and movcond in FMOVR, FMOVCC Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 203 +++++++++++++++++---------------------- 1 file changed, 86 insertions(+), 117 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index fa9a05799c..a7cd67767f 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2281,6 +2281,57 @@ static inline TCGv get_src2(unsigned int insn, TCGv def) } #ifdef TARGET_SPARC64 +static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs) +{ + TCGv_i32 c32, zero, dst, s1, s2; + + /* We have two choices here: extend the 32 bit data and use movcond_i64, + or fold the comparison down to 32 bits and use movcond_i32. Choose + the later. */ + c32 = tcg_temp_new_i32(); + if (cmp->is_bool) { + tcg_gen_trunc_i64_i32(c32, cmp->c1); + } else { + TCGv_i64 c64 = tcg_temp_new_i64(); + tcg_gen_setcond_i64(cmp->cond, c64, cmp->c1, cmp->c2); + tcg_gen_trunc_i64_i32(c32, c64); + tcg_temp_free_i64(c64); + } + + s1 = gen_load_fpr_F(dc, rs); + s2 = gen_load_fpr_F(dc, rd); + dst = gen_dest_fpr_F(); + zero = tcg_const_i32(0); + + tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2); + + tcg_temp_free_i32(c32); + tcg_temp_free_i32(zero); + gen_store_fpr_F(dc, rd, dst); +} + +static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs) +{ + TCGv_i64 dst = gen_dest_fpr_D(); + tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, cmp->c2, + gen_load_fpr_D(dc, rs), + gen_load_fpr_D(dc, rd)); + gen_store_fpr_D(dc, rd, dst); +} + +static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs) +{ + int qd = QFPREG(rd); + int qs = QFPREG(rs); + + tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, cmp->c2, + cpu_fpr[qs / 2], cpu_fpr[qd / 2]); + tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, cmp->c2, + cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]); + + gen_update_fprs_dirty(qd); +} + static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_ptr cpu_env) { TCGv_i32 r_tl = tcg_temp_new_i32(); @@ -3163,168 +3214,86 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #endif switch (xop) { #ifdef TARGET_SPARC64 -#define FMOVSCC(fcc) \ - { \ - TCGv r_cond; \ - int l1; \ - \ - l1 = gen_new_label(); \ - r_cond = tcg_temp_new(); \ +#define FMOVCC(fcc, sz) \ + do { \ + DisasCompare cmp; \ cond = GET_FIELD_SP(insn, 14, 17); \ - gen_fcond(r_cond, fcc, cond); \ - tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \ - 0, l1); \ - cpu_src1_32 = gen_load_fpr_F(dc, rs2); \ - gen_store_fpr_F(dc, rd, cpu_src1_32); \ - gen_set_label(l1); \ - tcg_temp_free(r_cond); \ - } -#define FMOVDCC(fcc) \ - { \ - TCGv r_cond; \ - int l1; \ - \ - l1 = gen_new_label(); \ - r_cond = tcg_temp_new(); \ - cond = GET_FIELD_SP(insn, 14, 17); \ - gen_fcond(r_cond, fcc, cond); \ - tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \ - 0, l1); \ - cpu_src1_64 = gen_load_fpr_D(dc, rs2); \ - gen_store_fpr_D(dc, rd, cpu_src1_64); \ - gen_set_label(l1); \ - tcg_temp_free(r_cond); \ - } -#define FMOVQCC(fcc) \ - { \ - TCGv r_cond; \ - int l1; \ - \ - l1 = gen_new_label(); \ - r_cond = tcg_temp_new(); \ - cond = GET_FIELD_SP(insn, 14, 17); \ - gen_fcond(r_cond, fcc, cond); \ - tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \ - 0, l1); \ - gen_move_Q(rd, rs2); \ - gen_set_label(l1); \ - tcg_temp_free(r_cond); \ - } + gen_fcompare(&cmp, fcc, cond); \ + gen_fmov##sz(dc, &cmp, rd, rs2); \ + free_compare(&cmp); \ + } while (0) + case 0x001: /* V9 fmovscc %fcc0 */ - FMOVSCC(0); + FMOVCC(0, s); break; case 0x002: /* V9 fmovdcc %fcc0 */ - FMOVDCC(0); + FMOVCC(0, d); break; case 0x003: /* V9 fmovqcc %fcc0 */ CHECK_FPU_FEATURE(dc, FLOAT128); - FMOVQCC(0); + FMOVCC(0, q); break; case 0x041: /* V9 fmovscc %fcc1 */ - FMOVSCC(1); + FMOVCC(1, s); break; case 0x042: /* V9 fmovdcc %fcc1 */ - FMOVDCC(1); + FMOVCC(1, d); break; case 0x043: /* V9 fmovqcc %fcc1 */ CHECK_FPU_FEATURE(dc, FLOAT128); - FMOVQCC(1); + FMOVCC(1, q); break; case 0x081: /* V9 fmovscc %fcc2 */ - FMOVSCC(2); + FMOVCC(2, s); break; case 0x082: /* V9 fmovdcc %fcc2 */ - FMOVDCC(2); + FMOVCC(2, d); break; case 0x083: /* V9 fmovqcc %fcc2 */ CHECK_FPU_FEATURE(dc, FLOAT128); - FMOVQCC(2); + FMOVCC(2, q); break; case 0x0c1: /* V9 fmovscc %fcc3 */ - FMOVSCC(3); + FMOVCC(3, s); break; case 0x0c2: /* V9 fmovdcc %fcc3 */ - FMOVDCC(3); + FMOVCC(3, d); break; case 0x0c3: /* V9 fmovqcc %fcc3 */ CHECK_FPU_FEATURE(dc, FLOAT128); - FMOVQCC(3); + FMOVCC(3, q); break; -#undef FMOVSCC -#undef FMOVDCC -#undef FMOVQCC -#define FMOVSCC(icc) \ - { \ - TCGv r_cond; \ - int l1; \ - \ - l1 = gen_new_label(); \ - r_cond = tcg_temp_new(); \ +#undef FMOVCC +#define FMOVCC(xcc, sz) \ + do { \ + DisasCompare cmp; \ cond = GET_FIELD_SP(insn, 14, 17); \ - gen_cond(r_cond, icc, cond, dc); \ - tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \ - 0, l1); \ - cpu_src1_32 = gen_load_fpr_F(dc, rs2); \ - gen_store_fpr_F(dc, rd, cpu_src1_32); \ - gen_set_label(l1); \ - tcg_temp_free(r_cond); \ - } -#define FMOVDCC(icc) \ - { \ - TCGv r_cond; \ - int l1; \ - \ - l1 = gen_new_label(); \ - r_cond = tcg_temp_new(); \ - cond = GET_FIELD_SP(insn, 14, 17); \ - gen_cond(r_cond, icc, cond, dc); \ - tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \ - 0, l1); \ - cpu_src1_64 = gen_load_fpr_D(dc, rs2); \ - gen_store_fpr_D(dc, rd, cpu_src1_64); \ - gen_update_fprs_dirty(DFPREG(rd)); \ - gen_set_label(l1); \ - tcg_temp_free(r_cond); \ - } -#define FMOVQCC(icc) \ - { \ - TCGv r_cond; \ - int l1; \ - \ - l1 = gen_new_label(); \ - r_cond = tcg_temp_new(); \ - cond = GET_FIELD_SP(insn, 14, 17); \ - gen_cond(r_cond, icc, cond, dc); \ - tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \ - 0, l1); \ - gen_move_Q(rd, rs2); \ - gen_set_label(l1); \ - tcg_temp_free(r_cond); \ - } + gen_compare(&cmp, xcc, cond, dc); \ + gen_fmov##sz(dc, &cmp, rd, rs2); \ + free_compare(&cmp); \ + } while (0) case 0x101: /* V9 fmovscc %icc */ - FMOVSCC(0); + FMOVCC(0, s); break; case 0x102: /* V9 fmovdcc %icc */ - FMOVDCC(0); + FMOVCC(0, d); break; case 0x103: /* V9 fmovqcc %icc */ CHECK_FPU_FEATURE(dc, FLOAT128); - FMOVQCC(0); + FMOVCC(0, q); break; case 0x181: /* V9 fmovscc %xcc */ - FMOVSCC(1); + FMOVCC(1, s); break; case 0x182: /* V9 fmovdcc %xcc */ - FMOVDCC(1); + FMOVCC(1, d); break; case 0x183: /* V9 fmovqcc %xcc */ CHECK_FPU_FEATURE(dc, FLOAT128); - FMOVQCC(1); + FMOVCC(1, q); break; -#undef FMOVSCC -#undef FMOVDCC -#undef FMOVQCC +#undef FMOVCC #endif case 0x51: /* fcmps, V9 %fcc */ cpu_src1_32 = gen_load_fpr_F(dc, rs1); From f52879b4410aa511e7c2baccc6a2fe37096b471e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:55:00 -0700 Subject: [PATCH 0800/2270] target-sparc: Use DisasCompare and movcond in MOVCC Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 44 ++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index a7cd67767f..6c9be294e8 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -4075,38 +4075,34 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) { int cc = GET_FIELD_SP(insn, 11, 12); int cond = GET_FIELD_SP(insn, 14, 17); - TCGv r_cond; - int l1; + DisasCompare cmp; - r_cond = tcg_temp_new(); if (insn & (1 << 18)) { - if (cc == 0) - gen_cond(r_cond, 0, cond, dc); - else if (cc == 2) - gen_cond(r_cond, 1, cond, dc); - else + if (cc == 0) { + gen_compare(&cmp, 0, cond, dc); + } else if (cc == 2) { + gen_compare(&cmp, 1, cond, dc); + } else { goto illegal_insn; + } } else { - gen_fcond(r_cond, cc, cond); + gen_fcompare(&cmp, cc, cond); } - l1 = gen_new_label(); - - tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1); - if (IS_IMM) { /* immediate */ - TCGv r_const; - + /* The get_src2 above loaded the normal 13-bit + immediate field, not the 11-bit field we have + in movcc. But it did handle the reg case. */ + if (IS_IMM) { simm = GET_FIELD_SPs(insn, 0, 10); - r_const = tcg_const_tl(simm); - gen_movl_TN_reg(rd, r_const); - tcg_temp_free(r_const); - } else { - rs2 = GET_FIELD_SP(insn, 0, 4); - gen_movl_reg_TN(rs2, cpu_tmp0); - gen_movl_TN_reg(rd, cpu_tmp0); + tcg_gen_movi_tl(cpu_src2, simm); } - gen_set_label(l1); - tcg_temp_free(r_cond); + + gen_movl_reg_TN(rd, cpu_dst); + tcg_gen_movcond_tl(cmp.cond, cpu_dst, + cmp.c1, cmp.c2, + cpu_src2, cpu_dst); + free_compare(&cmp); + gen_movl_TN_reg(rd, cpu_dst); break; } case 0x2d: /* V9 sdivx */ From c33f80f52a4621e6ed2d021adb08c7de8bec09d8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:55:01 -0700 Subject: [PATCH 0801/2270] target-sparc: Use DisasCompare and movcond in MOVR Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 6c9be294e8..9aef8e58fd 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -4118,27 +4118,24 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x2f: /* V9 movr */ { int cond = GET_FIELD_SP(insn, 10, 12); - int l1; + DisasCompare cmp; - cpu_src1 = get_src1(insn, cpu_src1); - - l1 = gen_new_label(); - - tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], - cpu_src1, 0, l1); - if (IS_IMM) { /* immediate */ - TCGv r_const; + gen_compare_reg(&cmp, cond, cpu_src1); + /* The get_src2 above loaded the normal 13-bit + immediate field, not the 10-bit field we have + in movr. But it did handle the reg case. */ + if (IS_IMM) { simm = GET_FIELD_SPs(insn, 0, 9); - r_const = tcg_const_tl(simm); - gen_movl_TN_reg(rd, r_const); - tcg_temp_free(r_const); - } else { - rs2 = GET_FIELD_SP(insn, 0, 4); - gen_movl_reg_TN(rs2, cpu_tmp0); - gen_movl_TN_reg(rd, cpu_tmp0); + tcg_gen_movi_tl(cpu_src2, simm); } - gen_set_label(l1); + + gen_movl_reg_TN(rd, cpu_dst); + tcg_gen_movcond_tl(cmp.cond, cpu_dst, + cmp.c1, cmp.c2, + cpu_src2, cpu_dst); + free_compare(&cmp); + gen_movl_TN_reg(rd, cpu_dst); break; } #endif From 61316742e2bc7b5b5257198f2248c42a9d238c84 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:55:02 -0700 Subject: [PATCH 0802/2270] target-sparc: Use movcond in gen_generic_branch Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 9aef8e58fd..c1a1dc4808 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -1107,19 +1107,15 @@ static inline void gen_branch_a(DisasContext *dc, target_ulong pc1, static inline void gen_generic_branch(DisasContext *dc) { - int l1, l2; + TCGv npc0 = tcg_const_tl(dc->jump_pc[0]); + TCGv npc1 = tcg_const_tl(dc->jump_pc[1]); + TCGv zero = tcg_const_tl(0); - l1 = gen_new_label(); - l2 = gen_new_label(); + tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, zero, npc0, npc1); - tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_cond, 0, l1); - - tcg_gen_movi_tl(cpu_npc, dc->jump_pc[0]); - tcg_gen_br(l2); - - gen_set_label(l1); - tcg_gen_movi_tl(cpu_npc, dc->jump_pc[1]); - gen_set_label(l2); + tcg_temp_free(npc0); + tcg_temp_free(npc1); + tcg_temp_free(zero); } /* call this function before using the condition register as it may From c28ae41ecd3bec70f1db8545e0800b9023891057 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:55:03 -0700 Subject: [PATCH 0803/2270] target-sparc: Move sdivx and udivx out of line The branches around the exception are maintaining an otherwise unnecessary use of local temps for the cpu destination. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/cpu.h | 1 + target-sparc/helper.c | 28 ++++++++++++++++++++ target-sparc/helper.h | 4 +++ target-sparc/ldst_helper.c | 4 +-- target-sparc/translate.c | 52 ++------------------------------------ 5 files changed, 37 insertions(+), 52 deletions(-) diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index e16b7b3515..214d01dd71 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -714,6 +714,7 @@ trap_state* cpu_tsptr(CPUSPARCState* env); void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write, int is_user, uintptr_t retaddr); +void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr); #define TB_FLAG_FPU_ENABLED (1 << 4) #define TB_FLAG_AM_ENABLED (1 << 5) diff --git a/target-sparc/helper.c b/target-sparc/helper.c index 65e1740e19..4555d2bfc0 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -75,6 +75,7 @@ static target_ulong helper_udiv_common(CPUSPARCState *env, target_ulong a, x1 = (b & 0xffffffff); if (x1 == 0) { + cpu_restore_state2(env, GETPC()); helper_raise_exception(env, TT_DIV_ZERO); } @@ -113,6 +114,7 @@ static target_ulong helper_sdiv_common(CPUSPARCState *env, target_ulong a, x1 = (b & 0xffffffff); if (x1 == 0) { + cpu_restore_state2(env, GETPC()); helper_raise_exception(env, TT_DIV_ZERO); } @@ -139,3 +141,29 @@ target_ulong helper_sdiv_cc(CPUSPARCState *env, target_ulong a, target_ulong b) { return helper_sdiv_common(env, a, b, 1); } + +#ifdef TARGET_SPARC64 +int64_t helper_sdivx(CPUSPARCState *env, int64_t a, int64_t b) +{ + if (b == 0) { + /* Raise divide by zero trap. */ + cpu_restore_state2(env, GETPC()); + helper_raise_exception(env, TT_DIV_ZERO); + } else if (b == -1) { + /* Avoid overflow trap with i386 divide insn. */ + return -a; + } else { + return a / b; + } +} + +uint64_t helper_udivx(CPUSPARCState *env, uint64_t a, uint64_t b) +{ + if (b == 0) { + /* Raise divide by zero trap. */ + cpu_restore_state2(env, GETPC()); + helper_raise_exception(env, TT_DIV_ZERO); + } + return a / b; +} +#endif diff --git a/target-sparc/helper.h b/target-sparc/helper.h index e3c7fddbe8..827df67cc2 100644 --- a/target-sparc/helper.h +++ b/target-sparc/helper.h @@ -38,6 +38,10 @@ DEF_HELPER_3(udiv, tl, env, tl, tl) DEF_HELPER_3(udiv_cc, tl, env, tl, tl) DEF_HELPER_3(sdiv, tl, env, tl, tl) DEF_HELPER_3(sdiv_cc, tl, env, tl, tl) +#ifdef TARGET_SPARC64 +DEF_HELPER_3(sdivx, s64, env, s64, s64) +DEF_HELPER_3(udivx, i64, env, i64, i64) +#endif DEF_HELPER_3(ldqf, void, env, tl, int) DEF_HELPER_3(stqf, void, env, tl, int) #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c index 9bec7a92f7..2ca9a5c4a9 100644 --- a/target-sparc/ldst_helper.c +++ b/target-sparc/ldst_helper.c @@ -2390,9 +2390,8 @@ void cpu_unassigned_access(CPUSPARCState *env, target_phys_addr_t addr, #endif #endif -#if !defined(CONFIG_USER_ONLY) /* XXX: make it generic ? */ -static void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr) +void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr) { TranslationBlock *tb; @@ -2407,6 +2406,7 @@ static void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr) } } +#if !defined(CONFIG_USER_ONLY) void do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write, int is_user, uintptr_t retaddr) { diff --git a/target-sparc/translate.c b/target-sparc/translate.c index c1a1dc4808..1628cf355b 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -768,44 +768,6 @@ static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2) gen_op_multiply(dst, src1, src2, 1); } -#ifdef TARGET_SPARC64 -static inline void gen_trap_ifdivzero_tl(TCGv divisor) -{ - TCGv_i32 r_const; - int l1; - - l1 = gen_new_label(); - tcg_gen_brcondi_tl(TCG_COND_NE, divisor, 0, l1); - r_const = tcg_const_i32(TT_DIV_ZERO); - gen_helper_raise_exception(cpu_env, r_const); - tcg_temp_free_i32(r_const); - gen_set_label(l1); -} - -static inline void gen_op_sdivx(TCGv dst, TCGv src1, TCGv src2) -{ - int l1, l2; - TCGv r_temp1, r_temp2; - - l1 = gen_new_label(); - l2 = gen_new_label(); - r_temp1 = tcg_temp_local_new(); - r_temp2 = tcg_temp_local_new(); - tcg_gen_mov_tl(r_temp1, src1); - tcg_gen_mov_tl(r_temp2, src2); - gen_trap_ifdivzero_tl(r_temp2); - tcg_gen_brcondi_tl(TCG_COND_NE, r_temp1, INT64_MIN, l1); - tcg_gen_brcondi_tl(TCG_COND_NE, r_temp2, -1, l1); - tcg_gen_movi_i64(dst, INT64_MIN); - tcg_gen_br(l2); - gen_set_label(l1); - tcg_gen_div_i64(dst, r_temp1, r_temp2); - gen_set_label(l2); - tcg_temp_free(r_temp1); - tcg_temp_free(r_temp2); -} -#endif - // 1 static inline void gen_op_eval_ba(TCGv dst) { @@ -3591,17 +3553,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; #ifdef TARGET_SPARC64 case 0xd: /* V9 udivx */ - { - TCGv r_temp1, r_temp2; - r_temp1 = tcg_temp_local_new(); - r_temp2 = tcg_temp_local_new(); - tcg_gen_mov_tl(r_temp1, cpu_src1); - tcg_gen_mov_tl(r_temp2, cpu_src2); - gen_trap_ifdivzero_tl(r_temp2); - tcg_gen_divu_i64(cpu_dst, r_temp1, r_temp2); - tcg_temp_free(r_temp1); - tcg_temp_free(r_temp2); - } + gen_helper_udivx(cpu_dst, cpu_env, cpu_src1, cpu_src2); break; #endif case 0xe: /* udiv */ @@ -4102,7 +4054,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; } case 0x2d: /* V9 sdivx */ - gen_op_sdivx(cpu_dst, cpu_src1, cpu_src2); + gen_helper_sdivx(cpu_dst, cpu_env, cpu_src1, cpu_src2); gen_movl_TN_reg(rd, cpu_dst); break; case 0x2e: /* V9 popc */ From bd49ed41ebe518c79bd52e46ce5b9cf278f8a2af Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:55:04 -0700 Subject: [PATCH 0804/2270] target-sparc: Tidy Tcc Share more code between unconditional and conditional paths. Move the computation of the trap number into the conditional BB; avoid using temporaries that have gone out of scope (cpu_tmp32) or rely on local temps (cpu_dst). Fully fold the exception number when the trap number is %g0+imm. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 97 +++++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 41 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 1628cf355b..111c025dde 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2594,41 +2594,23 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) { unsigned int xop = GET_FIELD(insn, 7, 12); if (xop == 0x3a) { /* generate trap */ - int cond; + int cond = GET_FIELD(insn, 3, 6); + TCGv_i32 trap; + int l1 = -1, mask; - cpu_src1 = get_src1(insn, cpu_src1); - if (IS_IMM) { - rs2 = GET_FIELD(insn, 25, 31); - tcg_gen_addi_tl(cpu_dst, cpu_src1, rs2); - } else { - rs2 = GET_FIELD(insn, 27, 31); - if (rs2 != 0) { - gen_movl_reg_TN(rs2, cpu_src2); - tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2); - } else - tcg_gen_mov_tl(cpu_dst, cpu_src1); + if (cond == 0) { + /* Trap never. */ + break; } - cond = GET_FIELD(insn, 3, 6); - if (cond == 0x8) { /* Trap Always */ - save_state(dc); - if ((dc->def->features & CPU_FEATURE_HYPV) && - supervisor(dc)) - tcg_gen_andi_tl(cpu_dst, cpu_dst, UA2005_HTRAP_MASK); - else - tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK); - tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP); - tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst); - gen_helper_raise_exception(cpu_env, cpu_tmp32); + save_state(dc); - } else if (cond != 0) { + if (cond != 8) { + /* Conditional trap. */ DisasCompare cmp; - int l1; #ifdef TARGET_SPARC64 /* V9 icc/xcc */ int cc = GET_FIELD_SP(insn, 11, 12); - - save_state(dc); if (cc == 0) { gen_compare(&cmp, 0, cond, dc); } else if (cc == 2) { @@ -2637,27 +2619,60 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto illegal_insn; } #else - save_state(dc); gen_compare(&cmp, 0, cond, dc); #endif l1 = gen_new_label(); tcg_gen_brcond_tl(tcg_invert_cond(cmp.cond), cmp.c1, cmp.c2, l1); free_compare(&cmp); - - if ((dc->def->features & CPU_FEATURE_HYPV) && - supervisor(dc)) - tcg_gen_andi_tl(cpu_dst, cpu_dst, UA2005_HTRAP_MASK); - else - tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK); - tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP); - tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst); - gen_helper_raise_exception(cpu_env, cpu_tmp32); - - gen_set_label(l1); } - gen_op_next_insn(); - tcg_gen_exit_tb(0); + + mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc) + ? UA2005_HTRAP_MASK : V8_TRAP_MASK); + + /* Don't use the normal temporaries, as they may well have + gone out of scope with the branch above. While we're + doing that we might as well pre-truncate to 32-bit. */ + trap = tcg_temp_new_i32(); + + rs1 = GET_FIELD_SP(insn, 14, 18); + if (IS_IMM) { + rs2 = GET_FIELD_SP(insn, 0, 6); + if (rs1 == 0) { + tcg_gen_movi_i32(trap, (rs2 & mask) + TT_TRAP); + /* Signal that the trap value is fully constant. */ + mask = 0; + } else { + TCGv t1 = tcg_temp_new(); + gen_movl_reg_TN(rs1, t1); + tcg_gen_trunc_tl_i32(trap, t1); + tcg_temp_free(t1); + tcg_gen_addi_i32(trap, trap, rs2); + } + } else { + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_temp_new(); + rs2 = GET_FIELD_SP(insn, 0, 4); + gen_movl_reg_TN(rs1, t1); + gen_movl_reg_TN(rs2, t2); + tcg_gen_add_tl(t1, t1, t2); + tcg_gen_trunc_tl_i32(trap, t1); + tcg_temp_free(t1); + tcg_temp_free(t2); + } + if (mask != 0) { + tcg_gen_andi_i32(trap, trap, mask); + tcg_gen_addi_i32(trap, trap, TT_TRAP); + } + + gen_helper_raise_exception(cpu_env, trap); + tcg_temp_free_i32(trap); + + if (cond != 8) { + gen_set_label(l1); + gen_op_next_insn(); + tcg_gen_exit_tb(0); + } dc->is_br = 1; goto jmp_insn; } else if (xop == 0x28) { From a2ea4aa9898086c1e45e1db9b5f94d16dbf0762e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:55:05 -0700 Subject: [PATCH 0805/2270] target-sparc: Move taddcctv and tsubcctv out of line The branches around the exception are maintaining an otherwise unnecessary use of local temps for the cpu destination. Note that gen_op_t{add,sub}_cc were identical to gen_op_{add,sub}_cc. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/helper.c | 58 +++++++++++++++++++++ target-sparc/helper.h | 2 + target-sparc/translate.c | 108 +++------------------------------------ 3 files changed, 66 insertions(+), 102 deletions(-) diff --git a/target-sparc/helper.c b/target-sparc/helper.c index 4555d2bfc0..556ac286eb 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -167,3 +167,61 @@ uint64_t helper_udivx(CPUSPARCState *env, uint64_t a, uint64_t b) return a / b; } #endif + +target_ulong helper_taddcctv(CPUSPARCState *env, target_ulong src1, + target_ulong src2) +{ + target_ulong dst; + + /* Tag overflow occurs if either input has bits 0 or 1 set. */ + if ((src1 | src2) & 3) { + goto tag_overflow; + } + + dst = src1 + src2; + + /* Tag overflow occurs if the addition overflows. */ + if (~(src1 ^ src2) & (src1 ^ dst) & (1u << 31)) { + goto tag_overflow; + } + + /* Only modify the CC after any exceptions have been generated. */ + env->cc_op = CC_OP_TADDTV; + env->cc_src = src1; + env->cc_src2 = src2; + env->cc_dst = dst; + return dst; + + tag_overflow: + cpu_restore_state2(env, GETPC()); + helper_raise_exception(env, TT_TOVF); +} + +target_ulong helper_tsubcctv(CPUSPARCState *env, target_ulong src1, + target_ulong src2) +{ + target_ulong dst; + + /* Tag overflow occurs if either input has bits 0 or 1 set. */ + if ((src1 | src2) & 3) { + goto tag_overflow; + } + + dst = src1 - src2; + + /* Tag overflow occurs if the subtraction overflows. */ + if ((src1 ^ src2) & (src1 ^ dst) & (1u << 31)) { + goto tag_overflow; + } + + /* Only modify the CC after any exceptions have been generated. */ + env->cc_op = CC_OP_TSUBTV; + env->cc_src = src1; + env->cc_src2 = src2; + env->cc_dst = dst; + return dst; + + tag_overflow: + cpu_restore_state2(env, GETPC()); + helper_raise_exception(env, TT_TOVF); +} diff --git a/target-sparc/helper.h b/target-sparc/helper.h index 827df67cc2..e1ae3c7086 100644 --- a/target-sparc/helper.h +++ b/target-sparc/helper.h @@ -38,6 +38,8 @@ DEF_HELPER_3(udiv, tl, env, tl, tl) DEF_HELPER_3(udiv_cc, tl, env, tl, tl) DEF_HELPER_3(sdiv, tl, env, tl, tl) DEF_HELPER_3(sdiv_cc, tl, env, tl, tl) +DEF_HELPER_3(taddcctv, tl, env, tl, tl) +DEF_HELPER_3(tsubcctv, tl, env, tl, tl) #ifdef TARGET_SPARC64 DEF_HELPER_3(sdivx, s64, env, s64, s64) DEF_HELPER_3(udivx, i64, env, i64, i64) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 111c025dde..98efb8445e 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -336,43 +336,6 @@ static inline void gen_mov_reg_C(TCGv reg, TCGv_i32 src) tcg_gen_andi_tl(reg, reg, 0x1); } -static inline void gen_add_tv(TCGv dst, TCGv src1, TCGv src2) -{ - TCGv r_temp; - TCGv_i32 r_const; - int l1; - - l1 = gen_new_label(); - - r_temp = tcg_temp_new(); - tcg_gen_xor_tl(r_temp, src1, src2); - tcg_gen_not_tl(r_temp, r_temp); - tcg_gen_xor_tl(cpu_tmp0, src1, dst); - tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0); - tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31)); - tcg_gen_brcondi_tl(TCG_COND_EQ, r_temp, 0, l1); - r_const = tcg_const_i32(TT_TOVF); - gen_helper_raise_exception(cpu_env, r_const); - tcg_temp_free_i32(r_const); - gen_set_label(l1); - tcg_temp_free(r_temp); -} - -static inline void gen_tag_tv(TCGv src1, TCGv src2) -{ - int l1; - TCGv_i32 r_const; - - l1 = gen_new_label(); - tcg_gen_or_tl(cpu_tmp0, src1, src2); - tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0x3); - tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, l1); - r_const = tcg_const_i32(TT_TOVF); - gen_helper_raise_exception(cpu_env, r_const); - tcg_temp_free_i32(r_const); - gen_set_label(l1); -} - static inline void gen_op_addi_cc(TCGv dst, TCGv src1, target_long src2) { tcg_gen_mov_tl(cpu_cc_src, src1); @@ -517,45 +480,6 @@ static void gen_op_addx_int(DisasContext *dc, TCGv dst, TCGv src1, } } -static inline void gen_op_tadd_cc(TCGv dst, TCGv src1, TCGv src2) -{ - tcg_gen_mov_tl(cpu_cc_src, src1); - tcg_gen_mov_tl(cpu_cc_src2, src2); - tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2); - tcg_gen_mov_tl(dst, cpu_cc_dst); -} - -static inline void gen_op_tadd_ccTV(TCGv dst, TCGv src1, TCGv src2) -{ - tcg_gen_mov_tl(cpu_cc_src, src1); - tcg_gen_mov_tl(cpu_cc_src2, src2); - gen_tag_tv(cpu_cc_src, cpu_cc_src2); - tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2); - gen_add_tv(cpu_cc_dst, cpu_cc_src, cpu_cc_src2); - tcg_gen_mov_tl(dst, cpu_cc_dst); -} - -static inline void gen_sub_tv(TCGv dst, TCGv src1, TCGv src2) -{ - TCGv r_temp; - TCGv_i32 r_const; - int l1; - - l1 = gen_new_label(); - - r_temp = tcg_temp_new(); - tcg_gen_xor_tl(r_temp, src1, src2); - tcg_gen_xor_tl(cpu_tmp0, src1, dst); - tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0); - tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31)); - tcg_gen_brcondi_tl(TCG_COND_EQ, r_temp, 0, l1); - r_const = tcg_const_i32(TT_TOVF); - gen_helper_raise_exception(cpu_env, r_const); - tcg_temp_free_i32(r_const); - gen_set_label(l1); - tcg_temp_free(r_temp); -} - static inline void gen_op_subi_cc(TCGv dst, TCGv src1, target_long src2, DisasContext *dc) { tcg_gen_mov_tl(cpu_cc_src, src1); @@ -656,24 +580,6 @@ static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1, } } -static inline void gen_op_tsub_cc(TCGv dst, TCGv src1, TCGv src2) -{ - tcg_gen_mov_tl(cpu_cc_src, src1); - tcg_gen_mov_tl(cpu_cc_src2, src2); - tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2); - tcg_gen_mov_tl(dst, cpu_cc_dst); -} - -static inline void gen_op_tsub_ccTV(TCGv dst, TCGv src1, TCGv src2) -{ - tcg_gen_mov_tl(cpu_cc_src, src1); - tcg_gen_mov_tl(cpu_cc_src2, src2); - gen_tag_tv(cpu_cc_src, cpu_cc_src2); - tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2); - gen_sub_tv(cpu_cc_dst, cpu_cc_src, cpu_cc_src2); - tcg_gen_mov_tl(dst, cpu_cc_dst); -} - static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2) { TCGv r_temp; @@ -3602,29 +3508,27 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) cpu_src2 = get_src2(insn, cpu_src2); switch (xop) { case 0x20: /* taddcc */ - gen_op_tadd_cc(cpu_dst, cpu_src1, cpu_src2); + gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2); gen_movl_TN_reg(rd, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADD); dc->cc_op = CC_OP_TADD; break; case 0x21: /* tsubcc */ - gen_op_tsub_cc(cpu_dst, cpu_src1, cpu_src2); + gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2); gen_movl_TN_reg(rd, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUB); dc->cc_op = CC_OP_TSUB; break; case 0x22: /* taddcctv */ - save_state(dc); - gen_op_tadd_ccTV(cpu_dst, cpu_src1, cpu_src2); + gen_helper_taddcctv(cpu_dst, cpu_env, + cpu_src1, cpu_src2); gen_movl_TN_reg(rd, cpu_dst); - tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADDTV); dc->cc_op = CC_OP_TADDTV; break; case 0x23: /* tsubcctv */ - save_state(dc); - gen_op_tsub_ccTV(cpu_dst, cpu_src1, cpu_src2); + gen_helper_tsubcctv(cpu_dst, cpu_env, + cpu_src1, cpu_src2); gen_movl_TN_reg(rd, cpu_dst); - tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUBTV); dc->cc_op = CC_OP_TSUBTV; break; case 0x24: /* mulscc */ From 6cb675b0f89131dcb7bc4f9e0801ac7620374185 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:55:06 -0700 Subject: [PATCH 0806/2270] target-sparc: Use movcond in mulscc Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 98efb8445e..614905e1f0 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -582,22 +582,21 @@ static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1, static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2) { - TCGv r_temp; - int l1; + TCGv r_temp, zero; - l1 = gen_new_label(); r_temp = tcg_temp_new(); /* old op: if (!(env->y & 1)) T1 = 0; */ + zero = tcg_const_tl(0); tcg_gen_andi_tl(cpu_cc_src, src1, 0xffffffff); tcg_gen_andi_tl(r_temp, cpu_y, 0x1); tcg_gen_andi_tl(cpu_cc_src2, src2, 0xffffffff); - tcg_gen_brcondi_tl(TCG_COND_NE, r_temp, 0, l1); - tcg_gen_movi_tl(cpu_cc_src2, 0); - gen_set_label(l1); + tcg_gen_movcond_tl(TCG_COND_EQ, cpu_cc_src2, r_temp, zero, + zero, cpu_cc_src2); + tcg_temp_free(zero); // b2 = T0 & 1; // env->y = (b2 << 31) | (env->y >> 1); From 690995a615ed584a4d494a7b61ede4f849d83e4a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:55:07 -0700 Subject: [PATCH 0807/2270] target-sparc: Use movcond for FMOV*R Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 46 ++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 614905e1f0..d594284da9 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -3051,44 +3051,30 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) rs2 = GET_FIELD(insn, 27, 31); xop = GET_FIELD(insn, 18, 26); save_state(dc); -#ifdef TARGET_SPARC64 - if ((xop & 0x11f) == 0x005) { // V9 fmovsr - int l1; - l1 = gen_new_label(); - cond = GET_FIELD_SP(insn, 14, 17); - cpu_src1 = get_src1(insn, cpu_src1); - tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1, - 0, l1); - cpu_src1_32 = gen_load_fpr_F(dc, rs2); - gen_store_fpr_F(dc, rd, cpu_src1_32); - gen_set_label(l1); +#ifdef TARGET_SPARC64 +#define FMOVR(sz) \ + do { \ + DisasCompare cmp; \ + cond = GET_FIELD_SP(insn, 14, 17); \ + cpu_src1 = get_src1(insn, cpu_src1); \ + gen_compare_reg(&cmp, cond, cpu_src1); \ + gen_fmov##sz(dc, &cmp, rd, rs2); \ + free_compare(&cmp); \ + } while (0) + + if ((xop & 0x11f) == 0x005) { /* V9 fmovsr */ + FMOVR(s); break; } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr - int l1; - - l1 = gen_new_label(); - cond = GET_FIELD_SP(insn, 14, 17); - cpu_src1 = get_src1(insn, cpu_src1); - tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1, - 0, l1); - cpu_src1_64 = gen_load_fpr_D(dc, rs2); - gen_store_fpr_D(dc, rd, cpu_src1_64); - gen_set_label(l1); + FMOVR(d); break; } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr - int l1; - CHECK_FPU_FEATURE(dc, FLOAT128); - l1 = gen_new_label(); - cond = GET_FIELD_SP(insn, 14, 17); - cpu_src1 = get_src1(insn, cpu_src1); - tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1, - 0, l1); - gen_move_Q(rd, rs2); - gen_set_label(l1); + FMOVR(q); break; } +#undef FMOVR #endif switch (xop) { #ifdef TARGET_SPARC64 From b09b2fd30ce3079fbca1bbd7c1a87459378c5bd7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:55:08 -0700 Subject: [PATCH 0808/2270] target-sparc: Cleanup "global" temporary allocation There are 6 temporaries that disas_sparc_insn relies on having been allocated. Now that they are no longer referenced across branches, they need not be allocated as local temps. Move the allocation/free of these temporaries to make it clear that they are local to the translation of a single insn. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index d594284da9..48c245eeb2 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -5177,16 +5177,6 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, dc->singlestep = (env->singlestep_enabled || singlestep); gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; - cpu_tmp0 = tcg_temp_new(); - cpu_tmp32 = tcg_temp_new_i32(); - cpu_tmp64 = tcg_temp_new_i64(); - - cpu_dst = tcg_temp_local_new(); - - // loads and stores - cpu_val = tcg_temp_local_new(); - cpu_addr = tcg_temp_local_new(); - num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; if (max_insns == 0) @@ -5222,9 +5212,24 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, gen_io_start(); last_pc = dc->pc; insn = cpu_ldl_code(env, dc->pc); + + cpu_tmp0 = tcg_temp_new(); + cpu_tmp32 = tcg_temp_new_i32(); + cpu_tmp64 = tcg_temp_new_i64(); + cpu_dst = tcg_temp_new(); + cpu_val = tcg_temp_new(); + cpu_addr = tcg_temp_new(); + disas_sparc_insn(dc, insn); num_insns++; + tcg_temp_free(cpu_addr); + tcg_temp_free(cpu_val); + tcg_temp_free(cpu_dst); + tcg_temp_free_i64(cpu_tmp64); + tcg_temp_free_i32(cpu_tmp32); + tcg_temp_free(cpu_tmp0); + if (dc->is_br) break; /* if the next PC is different, we abort now */ @@ -5244,23 +5249,18 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, num_insns < max_insns); exit_gen_loop: - tcg_temp_free(cpu_addr); - tcg_temp_free(cpu_val); - tcg_temp_free(cpu_dst); - tcg_temp_free_i64(cpu_tmp64); - tcg_temp_free_i32(cpu_tmp32); - tcg_temp_free(cpu_tmp0); - - if (tb->cflags & CF_LAST_IO) + if (tb->cflags & CF_LAST_IO) { gen_io_end(); + } if (!dc->is_br) { if (dc->pc != DYNAMIC_PC && (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) { /* static PC and NPC: we can use direct chaining */ gen_goto_tb(dc, 0, dc->pc, dc->npc); } else { - if (dc->pc != DYNAMIC_PC) + if (dc->pc != DYNAMIC_PC) { tcg_gen_movi_tl(cpu_pc, dc->pc); + } save_npc(dc); tcg_gen_exit_tb(0); } From fe1755cbb21c34a40234e2c380d049b9b031c4e2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:55:09 -0700 Subject: [PATCH 0809/2270] target-sparc: Fall through from not-taken trap Now that we've cleaned up global temporary allocation, we can continue translating the fallthru path of a conditional trap. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 48c245eeb2..a7f64074f2 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2573,13 +2573,15 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_helper_raise_exception(cpu_env, trap); tcg_temp_free_i32(trap); - if (cond != 8) { + if (cond == 8) { + /* An unconditional trap ends the TB. */ + dc->is_br = 1; + goto jmp_insn; + } else { + /* A conditional trap falls through to the next insn. */ gen_set_label(l1); - gen_op_next_insn(); - tcg_gen_exit_tb(0); + break; } - dc->is_br = 1; - goto jmp_insn; } else if (xop == 0x28) { rs1 = GET_FIELD(insn, 13, 17); switch(rs1) { From 2a484ecf8283814c92b5743845e285f0efc23247 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 5 Oct 2012 16:55:10 -0700 Subject: [PATCH 0810/2270] target-sparc: Optimize conditionals using SUBCC Aka "normal" comparisons. We now have the infrastructure to pass back non-boolean results from gen_compare. This will automatically get used by both branches and conditional moves. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 192 ++++++++++++++++++++++++++------------- 1 file changed, 131 insertions(+), 61 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index a7f64074f2..472eb518cd 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -1046,83 +1046,153 @@ static void free_compare(DisasCompare *cmp) } } -static void gen_compare(DisasCompare *cmp, unsigned int cc, unsigned int cond, +static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond, DisasContext *dc) { + static int subcc_cond[16] = { + -1, /* never */ + TCG_COND_EQ, + TCG_COND_LE, + TCG_COND_LT, + TCG_COND_LEU, + TCG_COND_LTU, + -1, /* neg */ + -1, /* overflow */ + -1, /* always */ + TCG_COND_NE, + TCG_COND_GT, + TCG_COND_GE, + TCG_COND_GTU, + TCG_COND_GEU, + -1, /* pos */ + -1, /* no overflow */ + }; + TCGv_i32 r_src; TCGv r_dst; - /* For now we still generate a straight boolean result. */ - cmp->cond = TCG_COND_NE; - cmp->is_bool = true; - cmp->g1 = cmp->g2 = false; - cmp->c1 = r_dst = tcg_temp_new(); - cmp->c2 = tcg_const_tl(0); - #ifdef TARGET_SPARC64 - if (cc) + if (xcc) { r_src = cpu_xcc; - else + } else { r_src = cpu_psr; + } #else r_src = cpu_psr; #endif + switch (dc->cc_op) { - case CC_OP_FLAGS: + case CC_OP_SUB: + switch (cond) { + case 6: /* neg */ + case 14: /* pos */ + cmp->cond = (cond == 6 ? TCG_COND_LT : TCG_COND_GE); + cmp->is_bool = false; + cmp->g2 = false; + cmp->c2 = tcg_const_tl(0); +#ifdef TARGET_SPARC64 + if (!xcc) { + cmp->g1 = false; + cmp->c1 = tcg_temp_new(); + tcg_gen_ext32s_tl(cmp->c1, cpu_cc_dst); + break; + } +#endif + cmp->g1 = true; + cmp->c1 = cpu_cc_dst; + break; + + case 0: /* never */ + case 8: /* always */ + case 7: /* overflow */ + case 15: /* !overflow */ + goto do_dynamic; + + default: + cmp->cond = subcc_cond[cond]; + cmp->is_bool = false; +#ifdef TARGET_SPARC64 + if (!xcc) { + /* Note that sign-extension works for unsigned compares as + long as both operands are sign-extended. */ + cmp->g1 = cmp->g2 = false; + cmp->c1 = tcg_temp_new(); + cmp->c2 = tcg_temp_new(); + tcg_gen_ext32s_tl(cmp->c1, cpu_cc_src); + tcg_gen_ext32s_tl(cmp->c2, cpu_cc_src2); + } +#endif + cmp->g1 = cmp->g2 = true; + cmp->c1 = cpu_cc_src; + cmp->c2 = cpu_cc_src2; + break; + } break; + default: + do_dynamic: gen_helper_compute_psr(cpu_env); dc->cc_op = CC_OP_FLAGS; - break; - } - switch (cond) { - case 0x0: - gen_op_eval_bn(r_dst); - break; - case 0x1: - gen_op_eval_be(r_dst, r_src); - break; - case 0x2: - gen_op_eval_ble(r_dst, r_src); - break; - case 0x3: - gen_op_eval_bl(r_dst, r_src); - break; - case 0x4: - gen_op_eval_bleu(r_dst, r_src); - break; - case 0x5: - gen_op_eval_bcs(r_dst, r_src); - break; - case 0x6: - gen_op_eval_bneg(r_dst, r_src); - break; - case 0x7: - gen_op_eval_bvs(r_dst, r_src); - break; - case 0x8: - gen_op_eval_ba(r_dst); - break; - case 0x9: - gen_op_eval_bne(r_dst, r_src); - break; - case 0xa: - gen_op_eval_bg(r_dst, r_src); - break; - case 0xb: - gen_op_eval_bge(r_dst, r_src); - break; - case 0xc: - gen_op_eval_bgu(r_dst, r_src); - break; - case 0xd: - gen_op_eval_bcc(r_dst, r_src); - break; - case 0xe: - gen_op_eval_bpos(r_dst, r_src); - break; - case 0xf: - gen_op_eval_bvc(r_dst, r_src); + /* FALLTHRU */ + + case CC_OP_FLAGS: + /* We're going to generate a boolean result. */ + cmp->cond = TCG_COND_NE; + cmp->is_bool = true; + cmp->g1 = cmp->g2 = false; + cmp->c1 = r_dst = tcg_temp_new(); + cmp->c2 = tcg_const_tl(0); + + switch (cond) { + case 0x0: + gen_op_eval_bn(r_dst); + break; + case 0x1: + gen_op_eval_be(r_dst, r_src); + break; + case 0x2: + gen_op_eval_ble(r_dst, r_src); + break; + case 0x3: + gen_op_eval_bl(r_dst, r_src); + break; + case 0x4: + gen_op_eval_bleu(r_dst, r_src); + break; + case 0x5: + gen_op_eval_bcs(r_dst, r_src); + break; + case 0x6: + gen_op_eval_bneg(r_dst, r_src); + break; + case 0x7: + gen_op_eval_bvs(r_dst, r_src); + break; + case 0x8: + gen_op_eval_ba(r_dst); + break; + case 0x9: + gen_op_eval_bne(r_dst, r_src); + break; + case 0xa: + gen_op_eval_bg(r_dst, r_src); + break; + case 0xb: + gen_op_eval_bge(r_dst, r_src); + break; + case 0xc: + gen_op_eval_bgu(r_dst, r_src); + break; + case 0xd: + gen_op_eval_bcc(r_dst, r_src); + break; + case 0xe: + gen_op_eval_bpos(r_dst, r_src); + break; + case 0xf: + gen_op_eval_bvc(r_dst, r_src); + break; + } break; } } From f1829782d6cb931973d71649f8ad1dad66188c34 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 7 Oct 2012 20:07:11 +0200 Subject: [PATCH 0811/2270] qemu-barrier: Fix compilation on i386 hosts Commit 1d31fca470648ec66afd8743491bfb5846306341 tried to fix bug introduced by 610b823ef66b993660f1ab1447a769f190e4f3b3 by including qemu-common.h, which breaks the build further. Include compiler.h instead, as suggested by Blue Swirl. Signed-off-by: Aurelien Jarno --- qemu-barrier.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu-barrier.h b/qemu-barrier.h index 1de914e882..faa83d265e 100644 --- a/qemu-barrier.h +++ b/qemu-barrier.h @@ -6,7 +6,7 @@ #if defined(__i386__) -#include "qemu-common.h" /* QEMU_GNUC_PREREQ */ +#include "compiler.h" /* QEMU_GNUC_PREREQ */ /* * Because of the strongly ordered x86 storage model, wmb() and rmb() are nops From 0ec8df3974d2a4ff95b5fd4785b9bd3def7252f3 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 14 Sep 2012 22:09:23 +0200 Subject: [PATCH 0812/2270] qxl: always update displaysurface on resize Don't try to be clever and skip displaysurface reinitialization in case the size hasn't changed. Other parameters might have changed nevertheless, for example depth or stride, resulting in rendering being broken then. Trigger: boot linux guest with vesafb, start X11, make sure both vesafb and X11 use the display same resolution. Then watch X11 screen being upside down. Signed-off-by: Gerd Hoffmann --- hw/qxl-render.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/hw/qxl-render.c b/hw/qxl-render.c index e2e3fe2d37..b66c168ef6 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -99,7 +99,6 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) { VGACommonState *vga = &qxl->vga; int i; - DisplaySurface *surface = vga->ds->surface; if (qxl->guest_primary.resized) { qxl->guest_primary.resized = 0; @@ -112,9 +111,6 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) qxl->guest_primary.qxl_stride, qxl->guest_primary.bytes_pp, qxl->guest_primary.bits_pp); - } - if (surface->width != qxl->guest_primary.surface.width || - surface->height != qxl->guest_primary.surface.height) { if (qxl->guest_primary.qxl_stride > 0) { qemu_free_displaysurface(vga->ds); qemu_create_displaysurface_from(qxl->guest_primary.surface.width, From 36a03e0ba5202cf49749b2128bb62d41983681d6 Mon Sep 17 00:00:00 2001 From: Michael Tokarev Date: Wed, 19 Sep 2012 17:41:26 +0400 Subject: [PATCH 0813/2270] qxl/update_area_io: cleanup invalid parameters handling This cleans up two additions of almost the same code in commits 511b13e2c9 and ccc2960d654. While at it, make error paths consistent (always use 'break' instead of 'return'). Signed-off-by: Michael Tokarev Cc: Dunrong Huang Cc: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 33169f348a..3c82c2a96f 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1547,20 +1547,13 @@ async_common: if (d->ram->update_surface > d->ssd.num_surfaces) { qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: invalid surface id %d\n", d->ram->update_surface); - return; + break; } - if (update.left >= update.right || update.top >= update.bottom) { + if (update.left >= update.right || update.top >= update.bottom || + update.left < 0 || update.top < 0) { qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: invalid area (%ux%u)x(%ux%u)\n", update.left, update.top, update.right, update.bottom); - return; - } - - if (update.left < 0 || update.top < 0 || update.left >= update.right || - update.top >= update.bottom) { - qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: " - "invalid area(%d,%d,%d,%d)\n", update.left, - update.right, update.top, update.bottom); break; } if (async == QXL_ASYNC) { From ffe01e599f106bedf13ba0e0f6956735b1942a0c Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 25 Sep 2012 13:56:40 +0200 Subject: [PATCH 0814/2270] qxl: fix range check for rev3 io commands. Enables QXL_IO_FLUSH_SURFACES_ASYNC and QXL_IO_FLUSH_RELEASE which are part of the qxl rev3 feature set. Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/qxl.c b/hw/qxl.c index 3c82c2a96f..eb7707c84c 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1466,7 +1466,7 @@ static void ioport_write(void *opaque, target_phys_addr_t addr, } if (d->revision <= QXL_REVISION_STABLE_V10 && - io_port >= QXL_IO_FLUSH_SURFACES_ASYNC) { + io_port > QXL_IO_FLUSH_RELEASE) { qxl_set_guest_bug(d, "unsupported io %d for revision %d\n", io_port, d->revision); return; From e25a0651f4be22099122b5e14c77c354be0aa88b Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Wed, 3 Oct 2012 20:13:58 +0200 Subject: [PATCH 0815/2270] hw/qxl: exit on failure to register qxl interface This prevents a segfault later on when the device reset handler tries to access a NULL ssd.worker since interface_attach_worker has not been called. Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/qxl.c b/hw/qxl.c index eb7707c84c..e99ed55b54 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -2037,7 +2037,11 @@ static int qxl_init_common(PCIQXLDevice *qxl) qxl->ssd.qxl.base.sif = &qxl_interface.base; qxl->ssd.qxl.id = qxl->id; - qemu_spice_add_interface(&qxl->ssd.qxl.base); + if (qemu_spice_add_interface(&qxl->ssd.qxl.base) != 0) { + error_report("qxl interface %d.%d not supported by spice-server\n", + SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR); + return -1; + } qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl); init_pipe_signaling(qxl); From d96aafca057845a4d58cd7b36771f2c97c78cd56 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Tue, 2 Oct 2012 11:39:14 +0200 Subject: [PATCH 0816/2270] hw/qxl: fix condition for exiting guest_bug Reported and suggested by Paolo Bonzini, thanks. Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/qxl.c b/hw/qxl.c index e99ed55b54..772b6c00d1 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1461,7 +1461,7 @@ static void ioport_write(void *opaque, target_phys_addr_t addr, qxl_async_io async = QXL_SYNC; uint32_t orig_io_port = io_port; - if (d->guest_bug && !io_port == QXL_IO_RESET) { + if (d->guest_bug && io_port != QXL_IO_RESET) { return; } From c5825ac6c861bfe1a4adfa27517931b56079e298 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Sun, 7 Oct 2012 17:03:35 +0200 Subject: [PATCH 0817/2270] hw/qxl: qxl_dirty_surfaces: use uintptr_t As suggested by Paolo Bonzini, to avoid possible integer overflow issues. Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 772b6c00d1..c246147420 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1804,7 +1804,7 @@ static void qxl_hw_text_update(void *opaque, console_ch_t *chardata) static void qxl_dirty_surfaces(PCIQXLDevice *qxl) { - intptr_t vram_start; + uintptr_t vram_start; int i; if (qxl->mode != QXL_MODE_NATIVE && qxl->mode != QXL_MODE_COMPAT) { @@ -1815,7 +1815,7 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl) qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset, qxl->shadow_rom.surface0_area_size); - vram_start = (intptr_t)memory_region_get_ram_ptr(&qxl->vram_bar); + vram_start = (uintptr_t)memory_region_get_ram_ptr(&qxl->vram_bar); /* dirty the off-screen surfaces */ for (i = 0; i < qxl->ssd.num_surfaces; i++) { From 67be6726b6459472103ee87ceaf2e8e97c154965 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 24 Sep 2012 10:23:40 +0200 Subject: [PATCH 0818/2270] spice: raise requirement to 0.12 With the next qemu version (1.3) we are going to bump the qxl device revision to 4. The new features available require a recent spice-server version, so raise up the bar. Otherwise we would end up with different qxl revisions depending on the spice-server version installed, which would be a major PITA when it comes to compat properties. Clear out a big bunch of #ifdefs which are not needed any more. Signed-off-by: Gerd Hoffmann --- configure | 18 ++-------------- hw/qxl.c | 30 --------------------------- ui/spice-core.c | 51 ++-------------------------------------------- ui/spice-display.c | 38 ---------------------------------- ui/spice-display.h | 5 ----- 5 files changed, 4 insertions(+), 138 deletions(-) diff --git a/configure b/configure index c4a78376b6..c0226fcac4 100755 --- a/configure +++ b/configure @@ -2716,20 +2716,14 @@ int main(void) { spice_server_new(); return 0; } EOF spice_cflags=$($pkg_config --cflags spice-protocol spice-server 2>/dev/null) spice_libs=$($pkg_config --libs spice-protocol spice-server 2>/dev/null) - if $pkg_config --atleast-version=0.8.2 spice-server >/dev/null 2>&1 && \ - $pkg_config --atleast-version=0.8.1 spice-protocol > /dev/null 2>&1 && \ + if $pkg_config --atleast-version=0.12.0 spice-server >/dev/null 2>&1 && \ + $pkg_config --atleast-version=0.12.2 spice-protocol > /dev/null 2>&1 && \ compile_prog "$spice_cflags" "$spice_libs" ; then spice="yes" libs_softmmu="$libs_softmmu $spice_libs" QEMU_CFLAGS="$QEMU_CFLAGS $spice_cflags" spice_protocol_version=$($pkg_config --modversion spice-protocol) spice_server_version=$($pkg_config --modversion spice-server) - if $pkg_config --atleast-version=0.12.0 spice-protocol >/dev/null 2>&1; then - spice_qxl_io_monitors_config_async="yes" - fi - if $pkg_config --atleast-version=0.12.2 spice-protocol > /dev/null 2>&1; then - spice_qxl_client_monitors_config="yes" - fi else if test "$spice" = "yes" ; then feature_not_found "spice" @@ -3474,14 +3468,6 @@ if test "$spice" = "yes" ; then echo "CONFIG_SPICE=y" >> $config_host_mak fi -if test "$spice_qxl_io_monitors_config_async" = "yes" ; then - echo "CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC=y" >> $config_host_mak -fi - -if test "$spice_qxl_client_monitors_config" = "yes" ; then - echo "CONFIG_QXL_CLIENT_MONITORS_CONFIG=y" >> $config_host_mak -fi - if test "$smartcard" = "yes" ; then echo "CONFIG_SMARTCARD=y" >> $config_host_mak fi diff --git a/hw/qxl.c b/hw/qxl.c index c246147420..1d16863c5e 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -29,11 +29,6 @@ #include "qxl.h" -#ifndef CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC -/* spice-protocol is too old, add missing definitions */ -#define QXL_IO_MONITORS_CONFIG_ASYNC (QXL_IO_FLUSH_RELEASE + 1) -#endif - /* * NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as * such can be changed by the guest, so to avoid a guest trigerrable @@ -262,9 +257,6 @@ static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async) static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay) { trace_qxl_spice_monitors_config(qxl->id); -/* 0x000b01 == 0.11.1 */ -#if SPICE_SERVER_VERSION >= 0x000b01 && \ - defined(CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC) if (replay) { /* * don't use QXL_COOKIE_TYPE_IO: @@ -286,10 +278,6 @@ static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay) (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO, QXL_IO_MONITORS_CONFIG_ASYNC)); } -#else - fprintf(stderr, "qxl: too old spice-protocol/spice-server for " - "QXL_IO_MONITORS_CONFIG_ASYNC\n"); -#endif } void qxl_spice_reset_image_cache(PCIQXLDevice *qxl) @@ -948,8 +936,6 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token) } } -#if SPICE_SERVER_VERSION >= 0x000b04 - /* called from spice server thread context only */ static void interface_set_client_capabilities(QXLInstance *sin, uint8_t client_present, @@ -971,11 +957,6 @@ static void interface_set_client_capabilities(QXLInstance *sin, qxl_send_events(qxl, QXL_INTERRUPT_CLIENT); } -#endif - -#if defined(CONFIG_QXL_CLIENT_MONITORS_CONFIG) \ - && SPICE_SERVER_VERSION >= 0x000b05 - static uint32_t qxl_crc32(const uint8_t *p, unsigned len) { /* @@ -1044,7 +1025,6 @@ static int interface_client_monitors_config(QXLInstance *sin, qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG); return 1; } -#endif static const QXLInterface qxl_interface = { .base.type = SPICE_INTERFACE_QXL, @@ -1067,13 +1047,8 @@ static const QXLInterface qxl_interface = { .flush_resources = interface_flush_resources, .async_complete = interface_async_complete, .update_area_complete = interface_update_area_complete, -#if SPICE_SERVER_VERSION >= 0x000b04 .set_client_capabilities = interface_set_client_capabilities, -#endif -#if SPICE_SERVER_VERSION >= 0x000b05 && \ - defined(CONFIG_QXL_CLIENT_MONITORS_CONFIG) .client_monitors_config = interface_client_monitors_config, -#endif }; static void qxl_enter_vga_mode(PCIQXLDevice *d) @@ -1847,7 +1822,6 @@ static void qxl_vm_change_state_handler(void *opaque, int running, RunState state) { PCIQXLDevice *qxl = opaque; - qemu_spice_vm_change_state_handler(&qxl->ssd, running, state); if (running) { /* @@ -1964,14 +1938,10 @@ static int qxl_init_common(PCIQXLDevice *qxl) pci_device_rev = QXL_REVISION_STABLE_V10; io_size = 32; /* PCI region size must be pow2 */ break; -/* 0x000b01 == 0.11.1 */ -#if SPICE_SERVER_VERSION >= 0x000b01 && \ - defined(CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC) case 4: /* qxl-4 */ pci_device_rev = QXL_REVISION_STABLE_V12; io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1); break; -#endif default: error_report("Invalid revision %d for qxl device (max %d)", qxl->revision, QXL_DEFAULT_REVISION); diff --git a/ui/spice-core.c b/ui/spice-core.c index ba0d0bdbc2..51473650c0 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -223,7 +223,6 @@ static void channel_event(int event, SpiceChannelEventInfo *info) client = qdict_new(); server = qdict_new(); -#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT if (info->flags & SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT) { add_addr_info(client, (struct sockaddr *)&info->paddr_ext, info->plen_ext); @@ -232,12 +231,7 @@ static void channel_event(int event, SpiceChannelEventInfo *info) } else { error_report("spice: %s, extended address is expected", __func__); -#endif - add_addr_info(client, &info->paddr, info->plen); - add_addr_info(server, &info->laddr, info->llen); -#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT } -#endif if (event == SPICE_CHANNEL_EVENT_INITIALIZED) { qdict_put(server, "auth", qstring_from_str(auth)); @@ -276,7 +270,6 @@ static SpiceCoreInterface core_interface = { .channel_event = channel_event, }; -#ifdef SPICE_INTERFACE_MIGRATION typedef struct SpiceMigration { SpiceMigrateInstance sin; struct { @@ -313,7 +306,6 @@ static void migrate_end_complete_cb(SpiceMigrateInstance *sin) monitor_protocol_event(QEVENT_SPICE_MIGRATE_COMPLETED, NULL); spice_migration_completed = true; } -#endif /* config string parsing */ @@ -393,17 +385,13 @@ static SpiceChannelList *qmp_query_spice_channels(void) chan = g_malloc0(sizeof(*chan)); chan->value = g_malloc0(sizeof(*chan->value)); -#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT if (item->info->flags & SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT) { paddr = (struct sockaddr *)&item->info->paddr_ext; plen = item->info->plen_ext; } else { -#endif paddr = &item->info->paddr; plen = item->info->plen; -#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT } -#endif getnameinfo(paddr, plen, host, sizeof(host), port, sizeof(port), @@ -473,13 +461,10 @@ SpiceInfo *qmp_query_spice(Error **errp) info->tls_port = tls_port; } -#if SPICE_SERVER_VERSION >= 0x000a03 /* 0.10.3 */ info->mouse_mode = spice_server_is_server_mouse(spice_server) ? SPICE_QUERY_MOUSE_MODE_SERVER : SPICE_QUERY_MOUSE_MODE_CLIENT; -#else - info->mouse_mode = SPICE_QUERY_MOUSE_MODE_UNKNOWN; -#endif + /* for compatibility with the original command */ info->has_channels = true; info->channels = qmp_query_spice_channels(); @@ -492,19 +477,11 @@ static void migration_state_notifier(Notifier *notifier, void *data) MigrationState *s = data; if (migration_is_active(s)) { -#ifdef SPICE_INTERFACE_MIGRATION spice_server_migrate_start(spice_server); -#endif } else if (migration_has_finished(s)) { -#ifndef SPICE_INTERFACE_MIGRATION - spice_server_migrate_switch(spice_server); - monitor_protocol_event(QEVENT_SPICE_MIGRATE_COMPLETED, NULL); - spice_migration_completed = true; -#else spice_server_migrate_end(spice_server, true); } else if (migration_has_failed(s)) { spice_server_migrate_end(spice_server, false); -#endif } } @@ -513,16 +490,11 @@ int qemu_spice_migrate_info(const char *hostname, int port, int tls_port, MonitorCompletion *cb, void *opaque) { int ret; -#ifdef SPICE_INTERFACE_MIGRATION + spice_migrate.connect_complete.cb = cb; spice_migrate.connect_complete.opaque = opaque; ret = spice_server_migrate_connect(spice_server, hostname, port, tls_port, subject); -#else - ret = spice_server_migrate_info(spice_server, hostname, - port, tls_port, subject); - cb(opaque, NULL); -#endif return ret; } @@ -561,7 +533,6 @@ static int add_channel(const char *name, const char *value, void *opaque) static void vm_change_state_handler(void *opaque, int running, RunState state) { -#if SPICE_SERVER_VERSION >= 0x000b02 /* 0.11.2 */ if (running) { qemu_spice_display_start(); spice_server_vm_start(spice_server); @@ -569,7 +540,6 @@ static void vm_change_state_handler(void *opaque, int running, spice_server_vm_stop(spice_server); qemu_spice_display_stop(); } -#endif } void qemu_spice_init(void) @@ -585,9 +555,7 @@ void qemu_spice_init(void) int port, tls_port, len, addr_flags; spice_image_compression_t compression; spice_wan_compression_t wan_compr; -#if SPICE_SERVER_VERSION >= 0x000b02 /* 0.11.2 */ bool seamless_migration; -#endif qemu_thread_get_self(&me); @@ -672,16 +640,11 @@ void qemu_spice_init(void) spice_server_set_ticket(spice_server, password, 0, 0, 0); } if (qemu_opt_get_bool(opts, "sasl", 0)) { -#if SPICE_SERVER_VERSION >= 0x000900 /* 0.9.0 */ if (spice_server_set_sasl_appname(spice_server, "qemu") == -1 || spice_server_set_sasl(spice_server, 1) == -1) { error_report("spice: failed to enable sasl"); exit(1); } -#else - error_report("spice: sasl is not available (spice >= 0.9 required)"); - exit(1); -#endif } if (qemu_opt_get_bool(opts, "disable-ticketing", 0)) { auth = "none"; @@ -726,15 +689,11 @@ void qemu_spice_init(void) qemu_opt_foreach(opts, add_channel, &tls_port, 0); -#if SPICE_SERVER_VERSION >= 0x000a02 /* 0.10.2 */ spice_server_set_name(spice_server, qemu_name); spice_server_set_uuid(spice_server, qemu_uuid); -#endif -#if SPICE_SERVER_VERSION >= 0x000b02 /* 0.11.2 */ seamless_migration = qemu_opt_get_bool(opts, "seamless-migration", 0); spice_server_set_seamless_migration(spice_server, seamless_migration); -#endif if (0 != spice_server_init(spice_server, &core_interface)) { error_report("failed to initialize spice server"); exit(1); @@ -743,11 +702,9 @@ void qemu_spice_init(void) migration_state.notify = migration_state_notifier; add_migration_state_change_notifier(&migration_state); -#ifdef SPICE_INTERFACE_MIGRATION spice_migrate.sin.base.sif = &migrate_interface.base; spice_migrate.connect_complete.cb = NULL; qemu_spice_add_interface(&spice_migrate.sin.base); -#endif qemu_spice_input_init(); qemu_spice_audio_init(); @@ -815,15 +772,11 @@ int qemu_spice_set_pw_expire(time_t expires) int qemu_spice_display_add_client(int csock, int skipauth, int tls) { -#if SPICE_SERVER_VERSION >= 0x000a01 if (tls) { return spice_server_add_ssl_client(spice_server, csock, skipauth); } else { return spice_server_add_client(spice_server, csock, skipauth); } -#else - return -1; -#endif } static void spice_register_config(void) diff --git a/ui/spice-display.c b/ui/spice-display.c index 50fbefb067..b61764f381 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -126,21 +126,6 @@ void qemu_spice_wakeup(SimpleSpiceDisplay *ssd) ssd->worker->wakeup(ssd->worker); } -#if SPICE_SERVER_VERSION < 0x000b02 /* before 0.11.2 */ -static void qemu_spice_start(SimpleSpiceDisplay *ssd) -{ - trace_qemu_spice_start(ssd->qxl.id); - ssd->worker->start(ssd->worker); -} - -static void qemu_spice_stop(SimpleSpiceDisplay *ssd) -{ - trace_qemu_spice_stop(ssd->qxl.id); - ssd->worker->stop(ssd->worker); -} - -#else - static int spice_display_is_running; void qemu_spice_display_start(void) @@ -153,15 +138,9 @@ void qemu_spice_display_stop(void) spice_display_is_running = false; } -#endif - int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd) { -#if SPICE_SERVER_VERSION < 0x000b02 /* before 0.11.2 */ - return ssd->running; -#else return spice_display_is_running; -#endif } static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd, @@ -364,22 +343,6 @@ void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd) qemu_spice_destroy_primary_surface(ssd, 0, QXL_SYNC); } -void qemu_spice_vm_change_state_handler(void *opaque, int running, - RunState state) -{ -#if SPICE_SERVER_VERSION < 0x000b02 /* before 0.11.2 */ - SimpleSpiceDisplay *ssd = opaque; - - if (running) { - ssd->running = true; - qemu_spice_start(ssd); - } else { - qemu_spice_stop(ssd); - ssd->running = false; - } -#endif -} - void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds) { ssd->ds = ds; @@ -623,7 +586,6 @@ void qemu_spice_display_init(DisplayState *ds) qemu_spice_add_interface(&sdpy.qxl.base); assert(sdpy.worker); - qemu_add_vm_change_state_handler(qemu_spice_vm_change_state_handler, &sdpy); qemu_spice_create_host_memslot(&sdpy); qemu_spice_create_host_primary(&sdpy); } diff --git a/ui/spice-display.h b/ui/spice-display.h index dea41c1b71..d7669277fd 100644 --- a/ui/spice-display.h +++ b/ui/spice-display.h @@ -83,9 +83,6 @@ struct SimpleSpiceDisplay { QXLRect dirty; int notify; -#if SPICE_SERVER_VERSION < 0x000b02 /* before 0.11.2 */ - int running; -#endif /* * All struct members below this comment can be accessed from @@ -133,8 +130,6 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id, void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id, qxl_async_io async); void qemu_spice_wakeup(SimpleSpiceDisplay *ssd); -#if SPICE_SERVER_VERSION >= 0x000b02 /* before 0.11.2 */ void qemu_spice_display_start(void); void qemu_spice_display_stop(void); -#endif int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd); From 591af14359f698d89cd334622237a20f19ae7060 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 8 Oct 2012 10:05:22 +0200 Subject: [PATCH 0819/2270] qxl: set default revision to 4 Set qxl pci revision to 4 (for pc-1.3+) so guests know spice-server 0.12 features are available. Signed-off-by: Gerd Hoffmann --- hw/pc_piix.c | 8 ++++++++ hw/qxl.h | 5 ----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index fd5898fba6..82364ab0d5 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -371,6 +371,14 @@ static QEMUMachine pc_machine_v1_3 = { .driver = "ivshmem",\ .property = "use64",\ .value = "0",\ + },{\ + .driver = "qxl",\ + .property = "revision",\ + .value = stringify(3),\ + },{\ + .driver = "qxl-vga",\ + .property = "revision",\ + .value = stringify(3),\ } static QEMUMachine pc_machine_v1_2 = { diff --git a/hw/qxl.h b/hw/qxl.h index 5553824bee..e583cfb750 100644 --- a/hw/qxl.h +++ b/hw/qxl.h @@ -129,12 +129,7 @@ typedef struct PCIQXLDevice { } \ } while (0) -#if 0 -/* spice-server 0.12 is still in development */ #define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V12 -#else -#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V10 -#endif /* qxl.c */ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id); From 9e12c5aff2cfdd1574bf732c4bbf579d0c2e85c1 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Fri, 28 Sep 2012 10:06:00 +0800 Subject: [PATCH 0820/2270] rtl8139: implement 8139cp link status Add a link status chang callback and change the link status bit in BMSR & MSR accordingly. Tested in Linux/Windows guests. The link status bit of MediaStatus is infered from BasicModeStatus, they are inverse. nc.link_down could not be migrated, this patch updates link_down in rtl8139_post_load() to keep it coincident with real link status. Signed-off-by: Jason Wang Signed-off-by: Amos Kong Signed-off-by: Stefan Hajnoczi --- hw/rtl8139.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/hw/rtl8139.c b/hw/rtl8139.c index b7c82ee027..6b28fea96a 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -167,7 +167,7 @@ enum IntrStatusBits { PCIErr = 0x8000, PCSTimeout = 0x4000, RxFIFOOver = 0x40, - RxUnderrun = 0x20, + RxUnderrun = 0x20, /* Packet Underrun / Link Change */ RxOverflow = 0x10, TxErr = 0x08, TxOK = 0x04, @@ -3003,7 +3003,8 @@ static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr) break; case MediaStatus: - ret = 0xd0; + /* The LinkDown bit of MediaStatus is inverse with link status */ + ret = 0xd0 | (~s->BasicModeStatus & 0x04); DPRINTF("MediaStatus read 0x%x\n", ret); break; @@ -3258,6 +3259,10 @@ static int rtl8139_post_load(void *opaque, int version_id) s->cplus_enabled = s->CpCmd != 0; } + /* nc.link_down can't be migrated, so infer link_down according + * to link status bit in BasicModeStatus */ + s->nic->nc.link_down = (s->BasicModeStatus & 0x04) == 0; + return 0; } @@ -3449,12 +3454,27 @@ static void pci_rtl8139_uninit(PCIDevice *dev) qemu_del_net_client(&s->nic->nc); } +static void rtl8139_set_link_status(NetClientState *nc) +{ + RTL8139State *s = DO_UPCAST(NICState, nc, nc)->opaque; + + if (nc->link_down) { + s->BasicModeStatus &= ~0x04; + } else { + s->BasicModeStatus |= 0x04; + } + + s->IntrStatus |= RxUnderrun; + rtl8139_update_irq(s); +} + static NetClientInfo net_rtl8139_info = { .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = rtl8139_can_receive, .receive = rtl8139_receive, .cleanup = rtl8139_cleanup, + .link_status_changed = rtl8139_set_link_status, }; static int pci_rtl8139_init(PCIDevice *dev) From e4b823644044de1b8070fde82d0aad8053dc3333 Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Fri, 28 Sep 2012 10:06:01 +0800 Subject: [PATCH 0821/2270] e1000: update nc.link_down in e1000_post_load() This patch introduced e1000_post_load(), it will be called in the end of migration. nc.link_down could not be migrated, this patch updates link_down in e1000_post_load() to keep it coincident with real link status. Signed-off-by: Amos Kong Signed-off-by: Stefan Hajnoczi --- hw/e1000.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hw/e1000.c b/hw/e1000.c index ec3a7c4ecc..63fee10794 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -1079,11 +1079,23 @@ static bool is_version_1(void *opaque, int version_id) return version_id == 1; } +static int e1000_post_load(void *opaque, int version_id) +{ + E1000State *s = opaque; + + /* nc.link_down can't be migrated, so infer link_down according + * to link status bit in mac_reg[STATUS] */ + s->nic->nc.link_down = (s->mac_reg[STATUS] & E1000_STATUS_LU) == 0; + + return 0; +} + static const VMStateDescription vmstate_e1000 = { .name = "e1000", .version_id = 2, .minimum_version_id = 1, .minimum_version_id_old = 1, + .post_load = e1000_post_load, .fields = (VMStateField []) { VMSTATE_PCI_DEVICE(dev, E1000State), VMSTATE_UNUSED_TEST(is_version_1, 4), /* was instance id */ From 9899148110627da388f82c02997bca6d678d1aa1 Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Fri, 28 Sep 2012 10:06:02 +0800 Subject: [PATCH 0822/2270] virtio-net: update nc.link_down in virtio_net_load() nc.link_down could not be migrated, this patch updates link_down in virtio_post_load() to keep it coincident with real link status. Signed-off-by: Amos Kong Signed-off-by: Stefan Hajnoczi --- hw/virtio-net.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 247d7bef56..8342391d90 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -973,6 +973,11 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) } } n->mac_table.first_multi = i; + + /* nc.link_down can't be migrated, so infer link_down according + * to link status bit in n->status */ + n->nic->nc.link_down = (n->status & VIRTIO_NET_S_LINK_UP) == 0; + return 0; } From a245fc18352fe286ba45ae0661a73b3841514889 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Sep 2012 18:43:51 +0200 Subject: [PATCH 0823/2270] net: consolidate NetClientState header files into one This patch doesn't seem much useful alone, I must admit. However, it makes sense as part of the upcoming directory reorganization, where I want to have include/net/tap.h as the net<->hw interface for tap. Then having both net/tap.h and include/net/tap.h does not work. "Fixed" by moving all the init functions to a single header file net/clients.h. The patch also adopts a uniform style for including net/*.h files from net/*.c, without the net/ path. Signed-off-by: Paolo Bonzini Signed-off-by: Stefan Hajnoczi --- net.c | 11 ++++------- net/{socket.h => clients.h} | 28 +++++++++++++++++++++++++--- net/dump.c | 2 +- net/dump.h | 33 --------------------------------- net/hub.c | 1 + net/hub.h | 2 -- net/slirp.c | 3 ++- net/slirp.h | 3 --- net/socket.c | 3 +-- net/tap-win32.c | 2 +- net/tap.c | 3 ++- net/tap.h | 6 ------ net/vde.c | 3 +-- net/vde.h | 37 ------------------------------------- 14 files changed, 38 insertions(+), 99 deletions(-) rename net/{socket.h => clients.h} (62%) delete mode 100644 net/dump.h delete mode 100644 net/vde.h diff --git a/net.c b/net.c index a187a7b3db..ae4bc0d431 100644 --- a/net.c +++ b/net.c @@ -21,17 +21,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "net.h" - #include "config-host.h" -#include "net/tap.h" -#include "net/socket.h" -#include "net/dump.h" -#include "net/slirp.h" -#include "net/vde.h" +#include "net.h" +#include "net/clients.h" #include "net/hub.h" +#include "net/slirp.h" #include "net/util.h" + #include "monitor.h" #include "qemu-common.h" #include "qemu_socket.h" diff --git a/net/socket.h b/net/clients.h similarity index 62% rename from net/socket.h rename to net/clients.h index 3f8a092459..c58cc6087c 100644 --- a/net/socket.h +++ b/net/clients.h @@ -21,13 +21,35 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef QEMU_NET_SOCKET_H -#define QEMU_NET_SOCKET_H +#ifndef QEMU_NET_CLIENTS_H +#define QEMU_NET_CLIENTS_H #include "net.h" #include "qapi-types.h" +int net_init_dump(const NetClientOptions *opts, const char *name, + NetClientState *peer); + +#ifdef CONFIG_SLIRP +int net_init_slirp(const NetClientOptions *opts, const char *name, + NetClientState *peer); +#endif + +int net_init_hubport(const NetClientOptions *opts, const char *name, + NetClientState *peer); + int net_init_socket(const NetClientOptions *opts, const char *name, NetClientState *peer); -#endif /* QEMU_NET_SOCKET_H */ +int net_init_tap(const NetClientOptions *opts, const char *name, + NetClientState *peer); + +int net_init_bridge(const NetClientOptions *opts, const char *name, + NetClientState *peer); + +#ifdef CONFIG_VDE +int net_init_vde(const NetClientOptions *opts, const char *name, + NetClientState *peer); +#endif + +#endif /* QEMU_NET_CLIENTS_H */ diff --git a/net/dump.c b/net/dump.c index 004231d481..e0a5d74644 100644 --- a/net/dump.c +++ b/net/dump.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "dump.h" +#include "clients.h" #include "qemu-common.h" #include "qemu-error.h" #include "qemu-log.h" diff --git a/net/dump.h b/net/dump.h deleted file mode 100644 index 33f152b460..0000000000 --- a/net/dump.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * QEMU System Emulator - * - * Copyright (c) 2003-2008 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. - */ -#ifndef QEMU_NET_DUMP_H -#define QEMU_NET_DUMP_H - -#include "net.h" -#include "qapi-types.h" - -int net_init_dump(const NetClientOptions *opts, const char *name, - NetClientState *peer); - -#endif /* QEMU_NET_DUMP_H */ diff --git a/net/hub.c b/net/hub.c index 650a8b4a40..be413012bb 100644 --- a/net/hub.c +++ b/net/hub.c @@ -14,6 +14,7 @@ #include "monitor.h" #include "net.h" +#include "clients.h" #include "hub.h" #include "iov.h" diff --git a/net/hub.h b/net/hub.h index 26a1ade1f9..4cbfdb128b 100644 --- a/net/hub.h +++ b/net/hub.h @@ -17,8 +17,6 @@ #include "qemu-common.h" -int net_init_hubport(const NetClientOptions *opts, const char *name, - NetClientState *peer); NetClientState *net_hub_add_port(int hub_id, const char *name); NetClientState *net_hub_find_client_by_name(int hub_id, const char *name); void net_hub_info(Monitor *mon); diff --git a/net/slirp.c b/net/slirp.c index 8db66ea539..bf86a446c3 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -30,7 +30,8 @@ #include #endif #include "net.h" -#include "net/hub.h" +#include "clients.h" +#include "hub.h" #include "monitor.h" #include "qemu_socket.h" #include "slirp/libslirp.h" diff --git a/net/slirp.h b/net/slirp.h index 5f685c4fb1..2ca09b65b7 100644 --- a/net/slirp.h +++ b/net/slirp.h @@ -31,9 +31,6 @@ #ifdef CONFIG_SLIRP -int net_init_slirp(const NetClientOptions *opts, const char *name, - NetClientState *peer); - void net_slirp_hostfwd_add(Monitor *mon, const QDict *qdict); void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict); diff --git a/net/socket.c b/net/socket.c index f3d7878264..b75d567695 100644 --- a/net/socket.c +++ b/net/socket.c @@ -21,11 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "net/socket.h" - #include "config-host.h" #include "net.h" +#include "clients.h" #include "monitor.h" #include "qemu-char.h" #include "qemu-common.h" diff --git a/net/tap-win32.c b/net/tap-win32.c index c0ea954ca1..f1801e22d2 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -26,7 +26,7 @@ * distribution); if not, see . */ -#include "net/tap.h" +#include "tap.h" #include "qemu-common.h" #include "net.h" diff --git a/net/tap.c b/net/tap.c index a88ae8f61a..df89caaac6 100644 --- a/net/tap.c +++ b/net/tap.c @@ -23,7 +23,7 @@ * THE SOFTWARE. */ -#include "net/tap.h" +#include "tap.h" #include "config-host.h" @@ -34,6 +34,7 @@ #include #include "net.h" +#include "clients.h" #include "monitor.h" #include "sysemu.h" #include "qemu-char.h" diff --git a/net/tap.h b/net/tap.h index 0fb018c4b7..d44d83ae73 100644 --- a/net/tap.h +++ b/net/tap.h @@ -32,9 +32,6 @@ #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" #define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown" -int net_init_tap(const NetClientOptions *opts, const char *name, - NetClientState *peer); - int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required); ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen); @@ -58,7 +55,4 @@ int tap_get_fd(NetClientState *nc); struct vhost_net; struct vhost_net *tap_get_vhost_net(NetClientState *nc); -int net_init_bridge(const NetClientOptions *opts, const char *name, - NetClientState *peer); - #endif /* QEMU_NET_TAP_H */ diff --git a/net/vde.c b/net/vde.c index b91a6c799b..275bda92c3 100644 --- a/net/vde.c +++ b/net/vde.c @@ -21,13 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "net/vde.h" - #include "config-host.h" #include #include "net.h" +#include "clients.h" #include "qemu-char.h" #include "qemu-common.h" #include "qemu-option.h" diff --git a/net/vde.h b/net/vde.h deleted file mode 100644 index 6ce6698937..0000000000 --- a/net/vde.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * QEMU System Emulator - * - * Copyright (c) 2003-2008 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. - */ -#ifndef QEMU_NET_VDE_H -#define QEMU_NET_VDE_H - -#include "qemu-common.h" -#include "qapi-types.h" - -#ifdef CONFIG_VDE - -int net_init_vde(const NetClientOptions *opts, const char *name, - NetClientState *peer); - -#endif /* CONFIG_VDE */ - -#endif /* QEMU_NET_VDE_H */ From ea486926b07d2ebd73ef67315ebb1eecf39faf5a Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 8 Oct 2012 08:45:29 -0600 Subject: [PATCH 0824/2270] vfio-pci: Update slow path INTx algorithm We can't afford the overhead of switching out and back into mmap mode around each interrupt, but we can do it lazily via a timer. On INTx interrupt, disable the mmap'd memory regions and set a timer. On every interrupt, push the timer out. If the timer expires and the interrupt is no longer pending, switch back to mmap mode. This has the benefit that things like graphics cards, which rarely or never, fire an interrupt don't need manual user intervention to add the x-intx=off parameter. They'll just remain in mmap mode until they trigger an interrupt, and if they don't continue to regularly fire interrupts, they'll switch back. The default timeout is tuned for network cards so that a ping is just enough to keep them in non-mmap mode, where they have much better latency. It is tunable with an experimental option, x-intx-mmap-timeout-ms. A value of 0 keeps the device in non-mmap mode after the first interrupt. It's possible we could look at the class code of devices and come up with reasonable per-class defaults based on expected interrupt frequency and latency. None of this is used for MSI interrupts and also won't be used if we can bypass through KVM. Signed-off-by: Alex Williamson --- hw/vfio_pci.c | 65 ++++++++++++++++++++++++++++++----------------- hw/vfio_pci_int.h | 4 +-- 2 files changed, 44 insertions(+), 25 deletions(-) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index a1eeced8fd..7ec9c30cd8 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -92,6 +92,34 @@ static void vfio_unmask_intx(VFIODevice *vdev) ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); } +/* + * Disabling BAR mmaping can be slow, but toggling it around INTx can + * also be a huge overhead. We try to get the best of both worlds by + * waiting until an interrupt to disable mmaps (subsequent transitions + * to the same state are effectively no overhead). If the interrupt has + * been serviced and the time gap is long enough, we re-enable mmaps for + * performance. This works well for things like graphics cards, which + * may not use their interrupt at all and are penalized to an unusable + * level by read/write BAR traps. Other devices, like NICs, have more + * regular interrupts and see much better latency by staying in non-mmap + * mode. We therefore set the default mmap_timeout such that a ping + * is just enough to keep the mmap disabled. Users can experiment with + * other options with the x-intx-mmap-timeout-ms parameter (a value of + * zero disables the timer). + */ +static void vfio_intx_mmap_enable(void *opaque) +{ + VFIODevice *vdev = opaque; + + if (vdev->intx.pending) { + qemu_mod_timer(vdev->intx.mmap_timer, + qemu_get_clock_ms(vm_clock) + vdev->intx.mmap_timeout); + return; + } + + vfio_mmap_set_enabled(vdev, true); +} + static void vfio_intx_interrupt(void *opaque) { VFIODevice *vdev = opaque; @@ -106,6 +134,11 @@ static void vfio_intx_interrupt(void *opaque) vdev->intx.pending = true; qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 1); + vfio_mmap_set_enabled(vdev, false); + if (vdev->intx.mmap_timeout) { + qemu_mod_timer(vdev->intx.mmap_timer, + qemu_get_clock_ms(vm_clock) + vdev->intx.mmap_timeout); + } } static void vfio_eoi(VFIODevice *vdev) @@ -141,7 +174,7 @@ static int vfio_enable_intx(VFIODevice *vdev) uint8_t pin = vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1); int ret; - if (vdev->intx.disabled || !pin) { + if (!pin) { return 0; } @@ -162,16 +195,6 @@ static int vfio_enable_intx(VFIODevice *vdev) return -errno; } - /* - * Disable mmaps so we can trap on BAR accesses. We interpret any - * access as a response to an interrupt and unmask the physical - * device. The device will re-assert if the interrupt is still - * pending. We'll likely retrigger on the host multiple times per - * guest interrupt, but without EOI notification it's better than - * nothing. Acceleration paths through KVM will avoid this. - */ - vfio_mmap_set_enabled(vdev, false); - vdev->interrupt = VFIO_INT_INTx; DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain, @@ -184,6 +207,7 @@ static void vfio_disable_intx(VFIODevice *vdev) { int fd; + qemu_del_timer(vdev->intx.mmap_timer); vfio_disable_irqindex(vdev, VFIO_PCI_INTX_IRQ_INDEX); vdev->intx.pending = false; qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0); @@ -1766,17 +1790,8 @@ static int vfio_initfn(PCIDevice *pdev) } if (vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1)) { - if (vdev->intx.intx && strcmp(vdev->intx.intx, "off")) { - error_report("vfio: Unknown option x-intx=%s, " - "valid options: \"off\".\n", vdev->intx.intx); - ret = -EINVAL; - goto out_teardown; - } - - if (vdev->intx.intx && !strcmp(vdev->intx.intx, "off")) { - vdev->intx.disabled = true; - } - + vdev->intx.mmap_timer = qemu_new_timer_ms(vm_clock, + vfio_intx_mmap_enable, vdev); ret = vfio_enable_intx(vdev); if (ret) { goto out_teardown; @@ -1802,6 +1817,9 @@ static void vfio_exitfn(PCIDevice *pdev) pci_device_set_intx_routing_notifier(&vdev->pdev, NULL); vfio_disable_interrupts(vdev); + if (vdev->intx.mmap_timer) { + qemu_free_timer(vdev->intx.mmap_timer); + } vfio_teardown_msi(vdev); vfio_unmap_bars(vdev); vfio_put_device(vdev); @@ -1826,7 +1844,8 @@ static void vfio_pci_reset(DeviceState *dev) static Property vfio_pci_dev_properties[] = { DEFINE_PROP_PCI_HOST_DEVADDR("host", VFIODevice, host), - DEFINE_PROP_STRING("x-intx", VFIODevice, intx.intx), + DEFINE_PROP_UINT32("x-intx-mmap-timeout-ms", VFIODevice, + intx.mmap_timeout, 1100), /* * TODO - support passed fds... is this necessary? * DEFINE_PROP_STRING("vfiofd", VFIODevice, vfiofd_name), diff --git a/hw/vfio_pci_int.h b/hw/vfio_pci_int.h index 3812d8d7f1..e69bf5f939 100644 --- a/hw/vfio_pci_int.h +++ b/hw/vfio_pci_int.h @@ -36,8 +36,8 @@ typedef struct VFIOINTx { EventNotifier interrupt; /* eventfd triggered on interrupt */ EventNotifier unmask; /* eventfd for unmask on QEMU bypass */ PCIINTxRoute route; /* routing info for QEMU bypass */ - bool disabled; - char *intx; + uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */ + QEMUTimer *mmap_timer; /* enable mmaps after periods w/o interrupts */ } VFIOINTx; struct VFIODevice; From af6bc27e39fafadbc03c8876ffa95851c5869683 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 8 Oct 2012 08:45:29 -0600 Subject: [PATCH 0825/2270] vfio-pci: Re-order map/unmap This cleans up the next patch that calls unmap from map. Signed-off-by: Alex Williamson --- hw/vfio_pci.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 7ec9c30cd8..2d89d171ee 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -786,6 +786,24 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr, /* * DMA - Mapping and unmapping for the "type1" IOMMU interface used on x86 */ +static int vfio_dma_unmap(VFIOContainer *container, + target_phys_addr_t iova, ram_addr_t size) +{ + struct vfio_iommu_type1_dma_unmap unmap = { + .argsz = sizeof(unmap), + .flags = 0, + .iova = iova, + .size = size, + }; + + if (ioctl(container->fd, VFIO_IOMMU_UNMAP_DMA, &unmap)) { + DPRINTF("VFIO_UNMAP_DMA: %d\n", -errno); + return -errno; + } + + return 0; +} + static int vfio_dma_map(VFIOContainer *container, target_phys_addr_t iova, ram_addr_t size, void *vaddr, bool readonly) { @@ -809,24 +827,6 @@ static int vfio_dma_map(VFIOContainer *container, target_phys_addr_t iova, return 0; } -static int vfio_dma_unmap(VFIOContainer *container, - target_phys_addr_t iova, ram_addr_t size) -{ - struct vfio_iommu_type1_dma_unmap unmap = { - .argsz = sizeof(unmap), - .flags = 0, - .iova = iova, - .size = size, - }; - - if (ioctl(container->fd, VFIO_IOMMU_UNMAP_DMA, &unmap)) { - DPRINTF("VFIO_UNMAP_DMA: %d\n", -errno); - return -errno; - } - - return 0; -} - static void vfio_listener_dummy1(MemoryListener *listener) { /* We don't do batching (begin/commit) or care about logging */ From 12af1344871aee4a8df011c3b0548f7c77332d54 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 8 Oct 2012 08:45:29 -0600 Subject: [PATCH 0826/2270] vfio-pci: Unmap and retry DMA mapping Occasionally we get regions added that overlap with existing mappings. These always seems to be in the VGA ROM range. VFIO returns EBUSY for these mapping attempts. We can try a little harder and assume that the latest mapping is correct by removing any overlapping ranges and retrying the original request. Signed-off-by: Alex Williamson --- hw/vfio_pci.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 2d89d171ee..7413f2d531 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -819,12 +819,19 @@ static int vfio_dma_map(VFIOContainer *container, target_phys_addr_t iova, map.flags |= VFIO_DMA_MAP_FLAG_WRITE; } - if (ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map)) { - DPRINTF("VFIO_MAP_DMA: %d\n", -errno); - return -errno; + /* + * Try the mapping, if it fails with EBUSY, unmap the region and try + * again. This shouldn't be necessary, but we sometimes see it in + * the the VGA ROM space. + */ + if (ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map) == 0 || + (errno == EBUSY && vfio_dma_unmap(container, iova, size) == 0 && + ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map) == 0)) { + return 0; } - return 0; + DPRINTF("VFIO_MAP_DMA: %d\n", -errno); + return -errno; } static void vfio_listener_dummy1(MemoryListener *listener) From fd704adc479810477606c3418aeb64a590f51fe3 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 8 Oct 2012 08:45:29 -0600 Subject: [PATCH 0827/2270] vfio-pci: Rework MSIX setup/teardown We try to do lazy initialization of MSIX since we don't actually need to setup anything until MSIX vectors start getting used. This leads to problems if MSIX is enabled, but never used (we can end up trying to re-enable INTx while it's still enabled). We also run into problems trying to expand our reset function to tear down interrupts as we can then get vector release notifications after we've released data structures. By making explicit initialization and teardown we can avoid both of these problems and behave more similar to bare metal. Signed-off-by: Alex Williamson --- hw/vfio_pci.c | 108 +++++++++++++++++++++++++------------------------- 1 file changed, 55 insertions(+), 53 deletions(-) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 7413f2d531..89e00ba5e6 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -72,8 +72,6 @@ static void vfio_disable_irqindex(VFIODevice *vdev, int index) }; ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); - - vdev->interrupt = VFIO_INT_NONE; } /* @@ -278,10 +276,6 @@ static int vfio_enable_vectors(VFIODevice *vdev, bool msix) g_free(irq_set); - if (!ret) { - vdev->interrupt = msix ? VFIO_INT_MSIX : VFIO_INT_MSI; - } - return ret; } @@ -296,15 +290,6 @@ static int vfio_msix_vector_use(PCIDevice *pdev, vdev->host.domain, vdev->host.bus, vdev->host.slot, vdev->host.function, nr); - if (vdev->interrupt != VFIO_INT_MSIX) { - vfio_disable_interrupts(vdev); - } - - if (!vdev->msi_vectors) { - vdev->msi_vectors = g_malloc0(vdev->msix->entries * - sizeof(VFIOMSIVector)); - } - vector = &vdev->msi_vectors[nr]; vector->vdev = vdev; vector->use = true; @@ -457,6 +442,23 @@ static void msi_set_qsize(PCIDevice *pdev, uint8_t size) pci_set_word(config + PCI_MSI_FLAGS, flags); } +static void vfio_enable_msix(VFIODevice *vdev) +{ + vfio_disable_interrupts(vdev); + + vdev->msi_vectors = g_malloc0(vdev->msix->entries * sizeof(VFIOMSIVector)); + + vdev->interrupt = VFIO_INT_MSIX; + + if (msix_set_vector_notifiers(&vdev->pdev, vfio_msix_vector_use, + vfio_msix_vector_release)) { + error_report("vfio: msix_set_vector_notifiers failed\n"); + } + + DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function); +} + static void vfio_enable_msi(VFIODevice *vdev) { int ret, i; @@ -529,17 +531,43 @@ retry: msi_set_qsize(&vdev->pdev, vdev->nr_vectors); + vdev->interrupt = VFIO_INT_MSI; + DPRINTF("%s(%04x:%02x:%02x.%x) Enabled %d MSI vectors\n", __func__, vdev->host.domain, vdev->host.bus, vdev->host.slot, vdev->host.function, vdev->nr_vectors); } -static void vfio_disable_msi_x(VFIODevice *vdev, bool msix) +static void vfio_disable_msi_common(VFIODevice *vdev) +{ + g_free(vdev->msi_vectors); + vdev->msi_vectors = NULL; + vdev->nr_vectors = 0; + vdev->interrupt = VFIO_INT_NONE; + + vfio_enable_intx(vdev); +} + +static void vfio_disable_msix(VFIODevice *vdev) +{ + msix_unset_vector_notifiers(&vdev->pdev); + + if (vdev->nr_vectors) { + vfio_disable_irqindex(vdev, VFIO_PCI_MSIX_IRQ_INDEX); + } + + vfio_disable_msi_common(vdev); + + DPRINTF("%s(%04x:%02x:%02x.%x, msi%s)\n", __func__, + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function, msix ? "x" : ""); +} + +static void vfio_disable_msi(VFIODevice *vdev) { int i; - vfio_disable_irqindex(vdev, msix ? VFIO_PCI_MSIX_IRQ_INDEX : - VFIO_PCI_MSI_IRQ_INDEX); + vfio_disable_irqindex(vdev, VFIO_PCI_MSI_IRQ_INDEX); for (i = 0; i < vdev->nr_vectors; i++) { VFIOMSIVector *vector = &vdev->msi_vectors[i]; @@ -558,26 +586,15 @@ static void vfio_disable_msi_x(VFIODevice *vdev, bool msix) NULL, NULL, NULL); } - if (msix) { - msix_vector_unuse(&vdev->pdev, i); - } - event_notifier_cleanup(&vector->interrupt); } - g_free(vdev->msi_vectors); - vdev->msi_vectors = NULL; - vdev->nr_vectors = 0; + vfio_disable_msi_common(vdev); - if (!msix) { - msi_set_qsize(&vdev->pdev, 0); /* Actually still means 1 vector */ - } + msi_set_qsize(&vdev->pdev, 0); /* Actually still means 1 vector */ - DPRINTF("%s(%04x:%02x:%02x.%x, msi%s)\n", __func__, - vdev->host.domain, vdev->host.bus, vdev->host.slot, - vdev->host.function, msix ? "x" : ""); - - vfio_enable_intx(vdev); + DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function); } /* @@ -763,7 +780,7 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr, if (!was_enabled && is_enabled) { vfio_enable_msi(vdev); } else if (was_enabled && !is_enabled) { - vfio_disable_msi_x(vdev, false); + vfio_disable_msi(vdev); } } @@ -776,9 +793,9 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr, is_enabled = msix_enabled(pdev); if (!was_enabled && is_enabled) { - /* vfio_msix_vector_use handles this automatically */ + vfio_enable_msix(vdev); } else if (was_enabled && !is_enabled) { - vfio_disable_msi_x(vdev, true); + vfio_disable_msix(vdev); } } } @@ -973,10 +990,10 @@ static void vfio_disable_interrupts(VFIODevice *vdev) vfio_disable_intx(vdev); break; case VFIO_INT_MSI: - vfio_disable_msi_x(vdev, false); + vfio_disable_msi(vdev); break; case VFIO_INT_MSIX: - vfio_disable_msi_x(vdev, true); + vfio_disable_msix(vdev); break; } } @@ -1094,15 +1111,6 @@ static int vfio_setup_msix(VFIODevice *vdev, int pos) return ret; } - ret = msix_set_vector_notifiers(&vdev->pdev, vfio_msix_vector_use, - vfio_msix_vector_release); - if (ret) { - error_report("vfio: msix_set_vector_notifiers failed %d\n", ret); - msix_uninit(&vdev->pdev, &vdev->bars[vdev->msix->table_bar].mem, - &vdev->bars[vdev->msix->pba_bar].mem); - return ret; - } - return 0; } @@ -1111,12 +1119,6 @@ static void vfio_teardown_msi(VFIODevice *vdev) msi_uninit(&vdev->pdev); if (vdev->msix) { - /* FIXME: Why can't unset just silently do nothing?? */ - if (vdev->pdev.msix_vector_use_notifier && - vdev->pdev.msix_vector_release_notifier) { - msix_unset_vector_notifiers(&vdev->pdev); - } - msix_uninit(&vdev->pdev, &vdev->bars[vdev->msix->table_bar].mem, &vdev->bars[vdev->msix->pba_bar].mem); } From 98cd5a5eaf4ad96d240e680eb1b26460dc278c33 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 8 Oct 2012 08:45:29 -0600 Subject: [PATCH 0828/2270] vfio-pci: No spurious MSIs FreeBSD doesn't like these spurious MSIs, remove them as they're mostly paranoia anyway. Signed-off-by: Alex Williamson --- hw/vfio_pci.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 89e00ba5e6..bca40835d6 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -322,21 +322,12 @@ static int vfio_msix_vector_use(PCIDevice *pdev, * increase them as needed. */ if (vdev->nr_vectors < nr + 1) { - int i; - vfio_disable_irqindex(vdev, VFIO_PCI_MSIX_IRQ_INDEX); vdev->nr_vectors = nr + 1; ret = vfio_enable_vectors(vdev, true); if (ret) { error_report("vfio: failed to enable vectors, %d\n", ret); } - - /* We don't know if we've missed interrupts in the interim... */ - for (i = 0; i < vdev->msix->entries; i++) { - if (vdev->msi_vectors[i].use) { - msix_notify(&vdev->pdev, i); - } - } } else { VFIOIRQSetFD irq_set_fd = { .irq_set = { @@ -353,12 +344,6 @@ static int vfio_msix_vector_use(PCIDevice *pdev, if (ret) { error_report("vfio: failed to modify vector, %d\n", ret); } - - /* - * If we were connected to the hardware PBA we could skip this, - * until then, a spurious interrupt is better than starvation. - */ - msix_notify(&vdev->pdev, nr); } return 0; From 5c97e5eba665b66395eee87d88cf2f8301594145 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 8 Oct 2012 08:45:30 -0600 Subject: [PATCH 0829/2270] vfio-pci: Roll the header into the .c file It's only ~100 lines and nobody else should be using this. Suggested by Michael Tsirkin. Signed-off-by: Alex Williamson --- hw/vfio_pci.c | 97 ++++++++++++++++++++++++++++++++++++++- hw/vfio_pci_int.h | 114 ---------------------------------------------- 2 files changed, 96 insertions(+), 115 deletions(-) delete mode 100644 hw/vfio_pci_int.h diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index bca40835d6..4d0170756c 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -33,9 +33,11 @@ #include "memory.h" #include "msi.h" #include "msix.h" +#include "pci.h" +#include "qemu-common.h" #include "qemu-error.h" +#include "qemu-queue.h" #include "range.h" -#include "vfio_pci_int.h" /* #define DEBUG_VFIO */ #ifdef DEBUG_VFIO @@ -46,6 +48,99 @@ do { } while (0) #endif +typedef struct VFIOBAR { + off_t fd_offset; /* offset of BAR within device fd */ + int fd; /* device fd, allows us to pass VFIOBAR as opaque data */ + MemoryRegion mem; /* slow, read/write access */ + MemoryRegion mmap_mem; /* direct mapped access */ + void *mmap; + size_t size; + uint32_t flags; /* VFIO region flags (rd/wr/mmap) */ + uint8_t nr; /* cache the BAR number for debug */ +} VFIOBAR; + +typedef struct VFIOINTx { + bool pending; /* interrupt pending */ + bool kvm_accel; /* set when QEMU bypass through KVM enabled */ + uint8_t pin; /* which pin to pull for qemu_set_irq */ + EventNotifier interrupt; /* eventfd triggered on interrupt */ + EventNotifier unmask; /* eventfd for unmask on QEMU bypass */ + PCIINTxRoute route; /* routing info for QEMU bypass */ + uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */ + QEMUTimer *mmap_timer; /* enable mmaps after periods w/o interrupts */ +} VFIOINTx; + +struct VFIODevice; + +typedef struct VFIOMSIVector { + EventNotifier interrupt; /* eventfd triggered on interrupt */ + struct VFIODevice *vdev; /* back pointer to device */ + int virq; /* KVM irqchip route for QEMU bypass */ + bool use; +} VFIOMSIVector; + +enum { + VFIO_INT_NONE = 0, + VFIO_INT_INTx = 1, + VFIO_INT_MSI = 2, + VFIO_INT_MSIX = 3, +}; + +struct VFIOGroup; + +typedef struct VFIOContainer { + int fd; /* /dev/vfio/vfio, empowered by the attached groups */ + struct { + /* enable abstraction to support various iommu backends */ + union { + MemoryListener listener; /* Used by type1 iommu */ + }; + void (*release)(struct VFIOContainer *); + } iommu_data; + QLIST_HEAD(, VFIOGroup) group_list; + QLIST_ENTRY(VFIOContainer) next; +} VFIOContainer; + +/* Cache of MSI-X setup plus extra mmap and memory region for split BAR map */ +typedef struct VFIOMSIXInfo { + uint8_t table_bar; + uint8_t pba_bar; + uint16_t entries; + uint32_t table_offset; + uint32_t pba_offset; + MemoryRegion mmap_mem; + void *mmap; +} VFIOMSIXInfo; + +typedef struct VFIODevice { + PCIDevice pdev; + int fd; + VFIOINTx intx; + unsigned int config_size; + off_t config_offset; /* Offset of config space region within device fd */ + unsigned int rom_size; + off_t rom_offset; /* Offset of ROM region within device fd */ + int msi_cap_size; + VFIOMSIVector *msi_vectors; + VFIOMSIXInfo *msix; + int nr_vectors; /* Number of MSI/MSIX vectors currently in use */ + int interrupt; /* Current interrupt type */ + VFIOBAR bars[PCI_NUM_REGIONS - 1]; /* No ROM */ + PCIHostDeviceAddress host; + QLIST_ENTRY(VFIODevice) next; + struct VFIOGroup *group; + bool reset_works; +} VFIODevice; + +typedef struct VFIOGroup { + int fd; + int groupid; + VFIOContainer *container; + QLIST_HEAD(, VFIODevice) device_list; + QLIST_ENTRY(VFIOGroup) next; + QLIST_ENTRY(VFIOGroup) container_next; +} VFIOGroup; + #define MSIX_CAP_LENGTH 12 static QLIST_HEAD(, VFIOContainer) diff --git a/hw/vfio_pci_int.h b/hw/vfio_pci_int.h deleted file mode 100644 index e69bf5f939..0000000000 --- a/hw/vfio_pci_int.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * vfio based device assignment support - * - * Copyright Red Hat, Inc. 2012 - * - * Authors: - * Alex Williamson - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - */ - -#ifndef HW_VFIO_PCI_INT_H -#define HW_VFIO_PCI_INT_H - -#include "qemu-common.h" -#include "qemu-queue.h" -#include "pci.h" -#include "event_notifier.h" - -typedef struct VFIOBAR { - off_t fd_offset; /* offset of BAR within device fd */ - int fd; /* device fd, allows us to pass VFIOBAR as opaque data */ - MemoryRegion mem; /* slow, read/write access */ - MemoryRegion mmap_mem; /* direct mapped access */ - void *mmap; - size_t size; - uint32_t flags; /* VFIO region flags (rd/wr/mmap) */ - uint8_t nr; /* cache the BAR number for debug */ -} VFIOBAR; - -typedef struct VFIOINTx { - bool pending; /* interrupt pending */ - bool kvm_accel; /* set when QEMU bypass through KVM enabled */ - uint8_t pin; /* which pin to pull for qemu_set_irq */ - EventNotifier interrupt; /* eventfd triggered on interrupt */ - EventNotifier unmask; /* eventfd for unmask on QEMU bypass */ - PCIINTxRoute route; /* routing info for QEMU bypass */ - uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */ - QEMUTimer *mmap_timer; /* enable mmaps after periods w/o interrupts */ -} VFIOINTx; - -struct VFIODevice; - -typedef struct VFIOMSIVector { - EventNotifier interrupt; /* eventfd triggered on interrupt */ - struct VFIODevice *vdev; /* back pointer to device */ - int virq; /* KVM irqchip route for QEMU bypass */ - bool use; -} VFIOMSIVector; - -enum { - VFIO_INT_NONE = 0, - VFIO_INT_INTx = 1, - VFIO_INT_MSI = 2, - VFIO_INT_MSIX = 3, -}; - -struct VFIOGroup; - -typedef struct VFIOContainer { - int fd; /* /dev/vfio/vfio, empowered by the attached groups */ - struct { - /* enable abstraction to support various iommu backends */ - union { - MemoryListener listener; /* Used by type1 iommu */ - }; - void (*release)(struct VFIOContainer *); - } iommu_data; - QLIST_HEAD(, VFIOGroup) group_list; - QLIST_ENTRY(VFIOContainer) next; -} VFIOContainer; - -/* Cache of MSI-X setup plus extra mmap and memory region for split BAR map */ -typedef struct VFIOMSIXInfo { - uint8_t table_bar; - uint8_t pba_bar; - uint16_t entries; - uint32_t table_offset; - uint32_t pba_offset; - MemoryRegion mmap_mem; - void *mmap; -} VFIOMSIXInfo; - -typedef struct VFIODevice { - PCIDevice pdev; - int fd; - VFIOINTx intx; - unsigned int config_size; - off_t config_offset; /* Offset of config space region within device fd */ - unsigned int rom_size; - off_t rom_offset; /* Offset of ROM region within device fd */ - int msi_cap_size; - VFIOMSIVector *msi_vectors; - VFIOMSIXInfo *msix; - int nr_vectors; /* Number of MSI/MSIX vectors currently in use */ - int interrupt; /* Current interrupt type */ - VFIOBAR bars[PCI_NUM_REGIONS - 1]; /* No ROM */ - PCIHostDeviceAddress host; - QLIST_ENTRY(VFIODevice) next; - struct VFIOGroup *group; - bool reset_works; -} VFIODevice; - -typedef struct VFIOGroup { - int fd; - int groupid; - VFIOContainer *container; - QLIST_HEAD(, VFIODevice) device_list; - QLIST_ENTRY(VFIOGroup) next; - QLIST_ENTRY(VFIOGroup) container_next; -} VFIOGroup; - -#endif /* HW_VFIO_PCI_INT_H */ From e43b9a5a4fb2b501fbbec411faff899b74a2d451 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 8 Oct 2012 08:45:30 -0600 Subject: [PATCH 0830/2270] vfio-pci: Don't peak at msi_supported Let the init function fail, just don't warn for -ENOTSUP. Signed-off-by: Alex Williamson --- hw/vfio_pci.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 4d0170756c..d62ddd152f 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -1084,14 +1084,6 @@ static int vfio_setup_msi(VFIODevice *vdev, int pos) bool msi_64bit, msi_maskbit; int ret, entries; - /* - * TODO: don't peek into msi_supported, let msi_init fail and - * check for ENOTSUP - */ - if (!msi_supported) { - return 0; - } - if (pread(vdev->fd, &ctrl, sizeof(ctrl), vdev->config_offset + pos + PCI_CAP_FLAGS) != sizeof(ctrl)) { return -errno; @@ -1107,6 +1099,9 @@ static int vfio_setup_msi(VFIODevice *vdev, int pos) ret = msi_init(&vdev->pdev, pos, entries, msi_64bit, msi_maskbit); if (ret < 0) { + if (ret == -ENOTSUP) { + return 0; + } error_report("vfio: msi_init failed\n"); return ret; } @@ -1173,20 +1168,15 @@ static int vfio_setup_msix(VFIODevice *vdev, int pos) { int ret; - /* - * TODO: don't peek into msi_supported, let msix_init fail and - * check for ENOTSUP - */ - if (!msi_supported) { - return 0; - } - ret = msix_init(&vdev->pdev, vdev->msix->entries, &vdev->bars[vdev->msix->table_bar].mem, vdev->msix->table_bar, vdev->msix->table_offset, &vdev->bars[vdev->msix->pba_bar].mem, vdev->msix->pba_bar, vdev->msix->pba_offset, pos); if (ret < 0) { + if (ret == -ENOTSUP) { + return 0; + } error_report("vfio: msix_init failed\n"); return ret; } From 5976cdd58b657692e8c1af5310d55a60aecc9089 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 8 Oct 2012 08:45:30 -0600 Subject: [PATCH 0831/2270] vfio-pci: Use uintptr_t for void* cast We don't seem to run into any sign extension problems, but unsigned looks more correct. Signed-off-by: Alex williamson --- hw/vfio_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index d62ddd152f..0ca77cf9d1 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -907,7 +907,7 @@ static int vfio_dma_map(VFIOContainer *container, target_phys_addr_t iova, struct vfio_iommu_type1_dma_map map = { .argsz = sizeof(map), .flags = VFIO_DMA_MAP_FLAG_READ, - .vaddr = (__u64)(intptr_t)vaddr, + .vaddr = (__u64)(uintptr_t)vaddr, .iova = iova, .size = size, }; From 9b1e45c8f1355592cb60c6aed9ac1f90b606a1a8 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 8 Oct 2012 08:45:30 -0600 Subject: [PATCH 0832/2270] vfio-pci: Remove setting of MSI qsize This was a misinterpretation of the spec, hardware doesn't get to specify how many were actually enabled through this field. Signed-off-by: Alex Williamson --- hw/vfio_pci.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 0ca77cf9d1..a554e7cc65 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -508,20 +508,6 @@ static MSIMessage msi_get_msg(PCIDevice *pdev, unsigned int vector) return msg; } -/* So should this */ -static void msi_set_qsize(PCIDevice *pdev, uint8_t size) -{ - uint8_t *config = pdev->config + pdev->msi_cap; - uint16_t flags; - - flags = pci_get_word(config + PCI_MSI_FLAGS); - flags = le16_to_cpu(flags); - flags &= ~PCI_MSI_FLAGS_QSIZE; - flags |= (size & 0x7) << 4; - flags = cpu_to_le16(flags); - pci_set_word(config + PCI_MSI_FLAGS, flags); -} - static void vfio_enable_msix(VFIODevice *vdev) { vfio_disable_interrupts(vdev); @@ -609,8 +595,6 @@ retry: return; } - msi_set_qsize(&vdev->pdev, vdev->nr_vectors); - vdev->interrupt = VFIO_INT_MSI; DPRINTF("%s(%04x:%02x:%02x.%x) Enabled %d MSI vectors\n", __func__, @@ -671,8 +655,6 @@ static void vfio_disable_msi(VFIODevice *vdev) vfio_disable_msi_common(vdev); - msi_set_qsize(&vdev->pdev, 0); /* Actually still means 1 vector */ - DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain, vdev->host.bus, vdev->host.slot, vdev->host.function); } From 5834a83f4803de88949162346e6dfa2060d3fca6 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 8 Oct 2012 08:45:30 -0600 Subject: [PATCH 0833/2270] vfio-pci: Extend reset Take what we've learned from pci-assign and apply it to vfio-pci. On reset, disable previous interrupt config, perform a device reset if available, re-enable INTx, and disable memory regions on the device to prevent continuing DMA. Signed-off-by: Alex Williamson --- hw/vfio_pci.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index a554e7cc65..b2383c4b55 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -1891,16 +1891,31 @@ static void vfio_pci_reset(DeviceState *dev) { PCIDevice *pdev = DO_UPCAST(PCIDevice, qdev, dev); VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev); + uint16_t cmd; - if (!vdev->reset_works) { - return; + DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function); + + vfio_disable_interrupts(vdev); + + /* + * Stop any ongoing DMA by disconecting I/O, MMIO, and bus master. + * Also put INTx Disable in known state. + */ + cmd = vfio_pci_read_config(pdev, PCI_COMMAND, 2); + cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | + PCI_COMMAND_INTX_DISABLE); + vfio_pci_write_config(pdev, PCI_COMMAND, cmd, 2); + + if (vdev->reset_works) { + if (ioctl(vdev->fd, VFIO_DEVICE_RESET)) { + error_report("vfio: Error unable to reset physical device " + "(%04x:%02x:%02x.%x): %m\n", vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function); + } } - if (ioctl(vdev->fd, VFIO_DEVICE_RESET)) { - error_report("vfio: Error unable to reset physical device " - "(%04x:%02x:%02x.%x): %m\n", vdev->host.domain, - vdev->host.bus, vdev->host.slot, vdev->host.function); - } + vfio_enable_intx(vdev); } static Property vfio_pci_dev_properties[] = { From ce59af2dba6fde2e3990b831f4c9a83641f5609e Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 8 Oct 2012 08:45:30 -0600 Subject: [PATCH 0834/2270] vfio-pci: Cleanup on INTx setup failure Missing some unwind code. Signed-off-by: Alex Williamson --- hw/vfio_pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index b2383c4b55..2325272c44 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -285,6 +285,8 @@ static int vfio_enable_intx(VFIODevice *vdev) if (ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set_fd)) { error_report("vfio: Error: Failed to setup INTx fd: %m\n"); + qemu_set_fd_handler(irq_set_fd.fd, NULL, NULL, vdev); + event_notifier_cleanup(&vdev->intx.interrupt); return -errno; } From 1a40313381262ebb5f30fb95d5550b674280f396 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 8 Oct 2012 08:45:31 -0600 Subject: [PATCH 0835/2270] vfio-pci: Clang cleanup Blue Swirl reports that Clang doesn't like the structure we define to avoid dynamic allocation for a number of calls to VFIO_DEVICE_SET_IRQS. Adding an element after a variable sized type is a GNU extension. Switch back to dynamic allocation, which really isn't a problem since this is only done on interrupt setup changes. Cc: Blue Swirl Signed-off-by: Alex Williamson --- hw/vfio_pci.c | 101 +++++++++++++++++++++++++++++--------------------- 1 file changed, 58 insertions(+), 43 deletions(-) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 2325272c44..85b16bbd23 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -248,24 +248,12 @@ static void vfio_eoi(VFIODevice *vdev) vfio_unmask_intx(vdev); } -typedef struct QEMU_PACKED VFIOIRQSetFD { - struct vfio_irq_set irq_set; - int32_t fd; -} VFIOIRQSetFD; - static int vfio_enable_intx(VFIODevice *vdev) { - VFIOIRQSetFD irq_set_fd = { - .irq_set = { - .argsz = sizeof(irq_set_fd), - .flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER, - .index = VFIO_PCI_INTX_IRQ_INDEX, - .start = 0, - .count = 1, - }, - }; uint8_t pin = vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1); - int ret; + int ret, argsz; + struct vfio_irq_set *irq_set; + int32_t *pfd; if (!pin) { return 0; @@ -280,12 +268,24 @@ static int vfio_enable_intx(VFIODevice *vdev) return ret; } - irq_set_fd.fd = event_notifier_get_fd(&vdev->intx.interrupt); - qemu_set_fd_handler(irq_set_fd.fd, vfio_intx_interrupt, NULL, vdev); + argsz = sizeof(*irq_set) + sizeof(*pfd); - if (ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set_fd)) { + irq_set = g_malloc0(argsz); + irq_set->argsz = argsz; + irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER; + irq_set->index = VFIO_PCI_INTX_IRQ_INDEX; + irq_set->start = 0; + irq_set->count = 1; + pfd = (int32_t *)&irq_set->data; + + *pfd = event_notifier_get_fd(&vdev->intx.interrupt); + qemu_set_fd_handler(*pfd, vfio_intx_interrupt, NULL, vdev); + + ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set); + g_free(irq_set); + if (ret) { error_report("vfio: Error: Failed to setup INTx fd: %m\n"); - qemu_set_fd_handler(irq_set_fd.fd, NULL, NULL, vdev); + qemu_set_fd_handler(*pfd, NULL, NULL, vdev); event_notifier_cleanup(&vdev->intx.interrupt); return -errno; } @@ -426,18 +426,25 @@ static int vfio_msix_vector_use(PCIDevice *pdev, error_report("vfio: failed to enable vectors, %d\n", ret); } } else { - VFIOIRQSetFD irq_set_fd = { - .irq_set = { - .argsz = sizeof(irq_set_fd), - .flags = VFIO_IRQ_SET_DATA_EVENTFD | - VFIO_IRQ_SET_ACTION_TRIGGER, - .index = VFIO_PCI_MSIX_IRQ_INDEX, - .start = nr, - .count = 1, - }, - .fd = event_notifier_get_fd(&vector->interrupt), - }; - ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set_fd); + int argsz; + struct vfio_irq_set *irq_set; + int32_t *pfd; + + argsz = sizeof(*irq_set) + sizeof(*pfd); + + irq_set = g_malloc0(argsz); + irq_set->argsz = argsz; + irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | + VFIO_IRQ_SET_ACTION_TRIGGER; + irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX; + irq_set->start = nr; + irq_set->count = 1; + pfd = (int32_t *)&irq_set->data; + + *pfd = event_notifier_get_fd(&vector->interrupt); + + ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set); + g_free(irq_set); if (ret) { error_report("vfio: failed to modify vector, %d\n", ret); } @@ -450,17 +457,9 @@ static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr) { VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev); VFIOMSIVector *vector = &vdev->msi_vectors[nr]; - VFIOIRQSetFD irq_set_fd = { - .irq_set = { - .argsz = sizeof(irq_set_fd), - .flags = VFIO_IRQ_SET_DATA_EVENTFD | - VFIO_IRQ_SET_ACTION_TRIGGER, - .index = VFIO_PCI_MSIX_IRQ_INDEX, - .start = nr, - .count = 1, - }, - .fd = -1, - }; + int argsz; + struct vfio_irq_set *irq_set; + int32_t *pfd; DPRINTF("%s(%04x:%02x:%02x.%x) vector %d released\n", __func__, vdev->host.domain, vdev->host.bus, vdev->host.slot, @@ -472,7 +471,23 @@ static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr) * bouncing through userspace and let msix.c drop it? Not sure. */ msix_vector_unuse(pdev, nr); - ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set_fd); + + argsz = sizeof(*irq_set) + sizeof(*pfd); + + irq_set = g_malloc0(argsz); + irq_set->argsz = argsz; + irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | + VFIO_IRQ_SET_ACTION_TRIGGER; + irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX; + irq_set->start = nr; + irq_set->count = 1; + pfd = (int32_t *)&irq_set->data; + + *pfd = -1; + + ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set); + + g_free(irq_set); if (vector->virq < 0) { qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), From 3a4f2816fac1b0f9cc197bb2208ddf03dc7bc592 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Oct 2012 08:45:31 -0600 Subject: [PATCH 0836/2270] vfio-pci: Fix BAR->VFIODevice translation in DO_UPCAST is supposed to translate from the first member of a struct to that struct, not from arbitrary ones. And it (usually) breaks the build when neglecting this rule. Use container_of to fix the build breakage and likely also the runtime behavior. Signed-off-by: Jan Kiszka aw: runtime behavior is actually the same, but clearly misuse of DO_UPCAST Signed-off-by: Alex Williamson --- hw/vfio_pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 85b16bbd23..639371e7a2 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -721,7 +721,7 @@ static void vfio_bar_write(void *opaque, target_phys_addr_t addr, * which access will service the interrupt, so we're potentially * getting quite a few host interrupts per guest interrupt. */ - vfio_eoi(DO_UPCAST(VFIODevice, bars[bar->nr], bar)); + vfio_eoi(container_of(bar, VFIODevice, bars[bar->nr])); } static uint64_t vfio_bar_read(void *opaque, @@ -761,7 +761,7 @@ static uint64_t vfio_bar_read(void *opaque, __func__, bar->nr, addr, size, data); /* Same as write above */ - vfio_eoi(DO_UPCAST(VFIODevice, bars[bar->nr], bar)); + vfio_eoi(container_of(bar, VFIODevice, bars[bar->nr])); return data; } From 785c23ae5cf1d697834a635daf45b0a6bd93c00f Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 3 Oct 2012 18:35:57 -0300 Subject: [PATCH 0837/2270] configure: add --localstatedir Next commit wants to use it. Signed-off-by: Luiz Capitulino Reviewed-by: Paolo Bonzini Reviewed-by: Michael Roth Signed-off-by: Michael Roth --- configure | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/configure b/configure index c4a78376b6..6600d8895a 100755 --- a/configure +++ b/configure @@ -185,6 +185,7 @@ libdir="\${prefix}/lib" libexecdir="\${prefix}/libexec" includedir="\${prefix}/include" sysconfdir="\${prefix}/etc" +local_statedir="\${prefix}/var" confsuffix="/qemu" slirp="yes" fmod_lib="" @@ -554,6 +555,7 @@ EOF qemu_docdir="\${prefix}" bindir="\${prefix}" sysconfdir="\${prefix}" + local_statedir="\${prefix}" confsuffix="" libs_qga="-lws2_32 -lwinmm -lpowrprof $libs_qga" fi @@ -630,7 +632,9 @@ for opt do ;; --sysconfdir=*) sysconfdir="$optarg" ;; - --sbindir=*|--sharedstatedir=*|--localstatedir=*|\ + --localstatedir=*) local_statedir="$optarg" + ;; + --sbindir=*|--sharedstatedir=*|\ --oldincludedir=*|--datarootdir=*|--infodir=*|--localedir=*|\ --htmldir=*|--dvidir=*|--pdfdir=*|--psdir=*) # These switches are silently ignored, for compatibility with @@ -1028,6 +1032,7 @@ echo " --datadir=PATH install firmware in PATH$confsuffix" echo " --docdir=PATH install documentation in PATH$confsuffix" echo " --bindir=PATH install binaries in PATH" echo " --sysconfdir=PATH install config in PATH$confsuffix" +echo " --localstatedir=PATH install local state in PATH" echo " --with-confsuffix=SUFFIX suffix for QEMU data inside datadir and sysconfdir [$confsuffix]" echo " --enable-debug-tcg enable TCG debugging" echo " --disable-debug-tcg disable TCG debugging (default)" @@ -3117,6 +3122,7 @@ echo "library directory `eval echo $libdir`" echo "libexec directory `eval echo $libexecdir`" echo "include directory `eval echo $includedir`" echo "config directory `eval echo $sysconfdir`" +echo "local state directory `eval echo $local_statedir`" if test "$mingw32" = "no" ; then echo "Manual directory `eval echo $mandir`" echo "ELF interp prefix $interp_prefix" @@ -3226,6 +3232,7 @@ echo "sysconfdir=$sysconfdir" >> $config_host_mak echo "qemu_confdir=$qemu_confdir" >> $config_host_mak echo "qemu_datadir=$qemu_datadir" >> $config_host_mak echo "qemu_docdir=$qemu_docdir" >> $config_host_mak +echo "qemu_localstatedir=$local_statedir" >> $config_host_mak echo "CONFIG_QEMU_HELPERDIR=\"$libexecdir\"" >> $config_host_mak echo "ARCH=$ARCH" >> $config_host_mak From 6a3c8c14c8467c5db3539f1b6e43e03318e5e21b Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 3 Oct 2012 18:35:58 -0300 Subject: [PATCH 0838/2270] qemu-ga: use state dir from CONFIG_QEMU_LOCALSTATEDIR Has the side effect of changing the default directory used to save the freeze status file from /tmp to ${prefix}/var/run. This is a beneficial change for two reasons: 1. FHS states that programs must not assume that files in /tmp will still exist between invocations of the program. This defeats the purpose of the freeze status file 2. FHS dictates that /var/run must be cleaned on boot, this ensures that a stale freeze status file will be removed on boot Signed-off-by: Luiz Capitulino Reviewed-by: Paolo Bonzini Reviewed-by: Michael Roth Signed-off-by: Michael Roth --- qemu-ga.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu-ga.c b/qemu-ga.c index b7474708f0..daeaea5461 100644 --- a/qemu-ga.c +++ b/qemu-ga.c @@ -40,8 +40,8 @@ #else #define QGA_VIRTIO_PATH_DEFAULT "\\\\.\\Global\\org.qemu.guest_agent.0" #endif -#define QGA_PIDFILE_DEFAULT "/var/run/qemu-ga.pid" -#define QGA_STATEDIR_DEFAULT "/tmp" +#define QGA_STATEDIR_DEFAULT CONFIG_QEMU_LOCALSTATEDIR "/run" +#define QGA_PIDFILE_DEFAULT QGA_STATEDIR_DEFAULT "/qemu-ga.pid" #define QGA_SENTINEL_BYTE 0xFF struct GAState { From 9d6f1b73f83a02fb28438fa9a487f5c7d245e4af Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 3 Oct 2012 18:40:01 -0300 Subject: [PATCH 0839/2270] qemu-ga: ga_open_pidfile(): add new line to pidfile FHS requires that pid files should end with a new line. Also change to snprintf() while there. Signed-off-by: Luiz Capitulino Reviewed-by: Michael Roth Signed-off-by: Michael Roth --- qemu-ga.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu-ga.c b/qemu-ga.c index daeaea5461..9b59a52461 100644 --- a/qemu-ga.c +++ b/qemu-ga.c @@ -255,7 +255,7 @@ static bool ga_open_pidfile(const char *pidfile) g_critical("Failed to truncate pid file"); goto fail; } - sprintf(pidstr, "%d", getpid()); + snprintf(pidstr, sizeof(pidstr), "%d\n", getpid()); if (write(pidfd, pidstr, strlen(pidstr)) != strlen(pidstr)) { g_critical("Failed to write pid file"); goto fail; From b4a76e84f4997392c9d2eb6f4373dc376d2ffd82 Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Tue, 24 Jul 2012 10:55:15 +1000 Subject: [PATCH 0840/2270] ssi: Support for multiple attached devices Removed assertion that only one device is attached to the SSI bus. When multiple devices are attached, all slaves have their transfer function called for transfers. Each device is responsible for knowing whether or not its CS is active, and if not returning 0. The returned data is the logical or of all responses from the (mulitple) devices. Signed-off-by: Peter A. G. Crosthwaite Acked-by: Peter Maydell --- hw/ssi.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/hw/ssi.c b/hw/ssi.c index e5f14a0cef..35d0a04a08 100644 --- a/hw/ssi.c +++ b/hw/ssi.c @@ -2,6 +2,8 @@ * QEMU Synchronous Serial Interface support * * Copyright (c) 2009 CodeSourcery. + * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com) + * Copyright (c) 2012 PetaLogix Pty Ltd. * Written by Paul Brook * * This code is licensed under the GNU GPL v2. @@ -29,14 +31,6 @@ static int ssi_slave_init(DeviceState *dev) { SSISlave *s = SSI_SLAVE(dev); SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s); - SSIBus *bus; - BusChild *kid; - - bus = FROM_QBUS(SSIBus, qdev_get_parent_bus(dev)); - kid = QTAILQ_FIRST(&bus->qbus.children); - if (kid->child != dev || QTAILQ_NEXT(kid, sibling) != NULL) { - hw_error("Too many devices on SSI bus"); - } return ssc->init(s); } @@ -74,16 +68,16 @@ SSIBus *ssi_create_bus(DeviceState *parent, const char *name) uint32_t ssi_transfer(SSIBus *bus, uint32_t val) { BusChild *kid; - SSISlave *slave; SSISlaveClass *ssc; + uint32_t r = 0; - kid = QTAILQ_FIRST(&bus->qbus.children); - if (!kid) { - return 0; + QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) { + SSISlave *slave = SSI_SLAVE(kid->child); + ssc = SSI_SLAVE_GET_CLASS(slave); + r |= ssc->transfer(slave, val); } - slave = SSI_SLAVE(kid->child); - ssc = SSI_SLAVE_GET_CLASS(slave); - return ssc->transfer(slave, val); + + return r; } static void ssi_slave_register_types(void) From 66530953319427d7c67a723076acd68075dc7db2 Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Tue, 24 Jul 2012 12:23:22 +1000 Subject: [PATCH 0841/2270] ssi: Implemented CS behaviour Added default CS behaviour for SSI slaves. SSI devices can set a property to enable CS behaviour which will create a GPIO on the device which is the CS. Tristating of the bus on SSI transfers is implemented. Signed-off-by: Peter A. G. Crosthwaite Acked-by: Peter Maydell --- hw/ads7846.c | 7 ++++--- hw/max111x.c | 7 ++++--- hw/spitz.c | 8 +++++--- hw/ssd0323.c | 6 ++++++ hw/ssi-sd.c | 6 ++++++ hw/ssi.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- hw/ssi.h | 37 +++++++++++++++++++++++++++++++++++++ hw/stellaris.c | 7 ++++--- hw/z2.c | 7 ++++--- 9 files changed, 118 insertions(+), 16 deletions(-) diff --git a/hw/ads7846.c b/hw/ads7846.c index 41c7f101c4..2ea9e55bb5 100644 --- a/hw/ads7846.c +++ b/hw/ads7846.c @@ -119,11 +119,12 @@ static int ads7856_post_load(void *opaque, int version_id) static const VMStateDescription vmstate_ads7846 = { .name = "ads7846", - .version_id = 0, - .minimum_version_id = 0, - .minimum_version_id_old = 0, + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, .post_load = ads7856_post_load, .fields = (VMStateField[]) { + VMSTATE_SSI_SLAVE(ssidev, ADS7846State), VMSTATE_INT32_ARRAY(input, ADS7846State, 8), VMSTATE_INT32(noise, ADS7846State), VMSTATE_INT32(cycle, ADS7846State), diff --git a/hw/max111x.c b/hw/max111x.c index 706d89f4fd..67640f109a 100644 --- a/hw/max111x.c +++ b/hw/max111x.c @@ -99,10 +99,11 @@ static uint32_t max111x_transfer(SSISlave *dev, uint32_t value) static const VMStateDescription vmstate_max111x = { .name = "max111x", - .version_id = 0, - .minimum_version_id = 0, - .minimum_version_id_old = 0, + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, .fields = (VMStateField[]) { + VMSTATE_SSI_SLAVE(ssidev, MAX111xState), VMSTATE_UINT8(tb1, MAX111xState), VMSTATE_UINT8(rb2, MAX111xState), VMSTATE_UINT8(rb3, MAX111xState), diff --git a/hw/spitz.c b/hw/spitz.c index 20e7835191..24346dcd5a 100644 --- a/hw/spitz.c +++ b/hw/spitz.c @@ -1083,10 +1083,11 @@ static TypeInfo spitz_keyboard_info = { static const VMStateDescription vmstate_corgi_ssp_regs = { .name = "corgi-ssp", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, + .version_id = 2, + .minimum_version_id = 2, + .minimum_version_id_old = 2, .fields = (VMStateField []) { + VMSTATE_SSI_SLAVE(ssidev, CorgiSSPState), VMSTATE_UINT32_ARRAY(enable, CorgiSSPState, 3), VMSTATE_END_OF_LIST(), } @@ -1115,6 +1116,7 @@ static const VMStateDescription vmstate_spitz_lcdtg_regs = { .minimum_version_id = 1, .minimum_version_id_old = 1, .fields = (VMStateField []) { + VMSTATE_SSI_SLAVE(ssidev, SpitzLCDTG), VMSTATE_UINT32(bl_intensity, SpitzLCDTG), VMSTATE_UINT32(bl_power, SpitzLCDTG), VMSTATE_END_OF_LIST(), diff --git a/hw/ssd0323.c b/hw/ssd0323.c index b101c5112c..5d05a35bc2 100644 --- a/hw/ssd0323.c +++ b/hw/ssd0323.c @@ -279,6 +279,7 @@ static void ssd0323_cd(void *opaque, int n, int level) static void ssd0323_save(QEMUFile *f, void *opaque) { + SSISlave *ss = SSI_SLAVE(opaque); ssd0323_state *s = (ssd0323_state *)opaque; int i; @@ -296,10 +297,13 @@ static void ssd0323_save(QEMUFile *f, void *opaque) qemu_put_be32(f, s->remap); qemu_put_be32(f, s->mode); qemu_put_buffer(f, s->framebuffer, sizeof(s->framebuffer)); + + qemu_put_be32(f, ss->cs); } static int ssd0323_load(QEMUFile *f, void *opaque, int version_id) { + SSISlave *ss = SSI_SLAVE(opaque); ssd0323_state *s = (ssd0323_state *)opaque; int i; @@ -321,6 +325,8 @@ static int ssd0323_load(QEMUFile *f, void *opaque, int version_id) s->mode = qemu_get_be32(f); qemu_get_buffer(f, s->framebuffer, sizeof(s->framebuffer)); + ss->cs = qemu_get_be32(f); + return 0; } diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c index b519bdb29a..cbbc645213 100644 --- a/hw/ssi-sd.c +++ b/hw/ssi-sd.c @@ -197,6 +197,7 @@ static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val) static void ssi_sd_save(QEMUFile *f, void *opaque) { + SSISlave *ss = SSI_SLAVE(opaque); ssi_sd_state *s = (ssi_sd_state *)opaque; int i; @@ -209,10 +210,13 @@ static void ssi_sd_save(QEMUFile *f, void *opaque) qemu_put_be32(f, s->arglen); qemu_put_be32(f, s->response_pos); qemu_put_be32(f, s->stopping); + + qemu_put_be32(f, ss->cs); } static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id) { + SSISlave *ss = SSI_SLAVE(opaque); ssi_sd_state *s = (ssi_sd_state *)opaque; int i; @@ -229,6 +233,8 @@ static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id) s->response_pos = qemu_get_be32(f); s->stopping = qemu_get_be32(f); + ss->cs = qemu_get_be32(f); + return 0; } diff --git a/hw/ssi.c b/hw/ssi.c index 35d0a04a08..2e4f2fecd1 100644 --- a/hw/ssi.c +++ b/hw/ssi.c @@ -27,19 +27,55 @@ static const TypeInfo ssi_bus_info = { .instance_size = sizeof(SSIBus), }; +static void ssi_cs_default(void *opaque, int n, int level) +{ + SSISlave *s = SSI_SLAVE(opaque); + bool cs = !!level; + assert(n == 0); + if (s->cs != cs) { + SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s); + if (ssc->set_cs) { + ssc->set_cs(s, cs); + } + } + s->cs = cs; +} + +static uint32_t ssi_transfer_raw_default(SSISlave *dev, uint32_t val) +{ + SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(dev); + + if ((dev->cs && ssc->cs_polarity == SSI_CS_HIGH) || + (!dev->cs && ssc->cs_polarity == SSI_CS_LOW) || + ssc->cs_polarity == SSI_CS_NONE) { + return ssc->transfer(dev, val); + } + return 0; +} + static int ssi_slave_init(DeviceState *dev) { SSISlave *s = SSI_SLAVE(dev); SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s); + if (ssc->transfer_raw == ssi_transfer_raw_default && + ssc->cs_polarity != SSI_CS_NONE) { + qdev_init_gpio_in(&s->qdev, ssi_cs_default, 1); + } + return ssc->init(s); } static void ssi_slave_class_init(ObjectClass *klass, void *data) { + SSISlaveClass *ssc = SSI_SLAVE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); + dc->init = ssi_slave_init; dc->bus_type = TYPE_SSI_BUS; + if (!ssc->transfer_raw) { + ssc->transfer_raw = ssi_transfer_raw_default; + } } static TypeInfo ssi_slave_info = { @@ -74,12 +110,23 @@ uint32_t ssi_transfer(SSIBus *bus, uint32_t val) QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) { SSISlave *slave = SSI_SLAVE(kid->child); ssc = SSI_SLAVE_GET_CLASS(slave); - r |= ssc->transfer(slave, val); + r |= ssc->transfer_raw(slave, val); } return r; } +const VMStateDescription vmstate_ssi_slave = { + .name = "SSISlave", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_BOOL(cs, SSISlave), + VMSTATE_END_OF_LIST() + } +}; + static void ssi_slave_register_types(void) { type_register_static(&ssi_bus_info); diff --git a/hw/ssi.h b/hw/ssi.h index 06657d7c16..65b159dcab 100644 --- a/hw/ssi.h +++ b/hw/ssi.h @@ -23,21 +23,58 @@ typedef struct SSISlave SSISlave; #define SSI_SLAVE_GET_CLASS(obj) \ OBJECT_GET_CLASS(SSISlaveClass, (obj), TYPE_SSI_SLAVE) +typedef enum { + SSI_CS_NONE = 0, + SSI_CS_LOW, + SSI_CS_HIGH, +} SSICSMode; + /* Slave devices. */ typedef struct SSISlaveClass { DeviceClass parent_class; int (*init)(SSISlave *dev); + + /* if you have standard or no CS behaviour, just override transfer. + * This is called when the device cs is active (true by default). + */ uint32_t (*transfer)(SSISlave *dev, uint32_t val); + /* called when the CS line changes. Optional, devices only need to implement + * this if they have side effects associated with the cs line (beyond + * tristating the txrx lines). + */ + int (*set_cs)(SSISlave *dev, bool select); + /* define whether or not CS exists and is active low/high */ + SSICSMode cs_polarity; + + /* if you have non-standard CS behaviour override this to take control + * of the CS behaviour at the device level. transfer, set_cs, and + * cs_polarity are unused if this is overwritten. Transfer_raw will + * always be called for the device for every txrx access to the parent bus + */ + uint32_t (*transfer_raw)(SSISlave *dev, uint32_t val); } SSISlaveClass; struct SSISlave { DeviceState qdev; + + /* Chip select state */ + bool cs; }; #define SSI_SLAVE_FROM_QDEV(dev) DO_UPCAST(SSISlave, qdev, dev) #define FROM_SSI_SLAVE(type, dev) DO_UPCAST(type, ssidev, dev) +extern const VMStateDescription vmstate_ssi_slave; + +#define VMSTATE_SSI_SLAVE(_field, _state) { \ + .name = (stringify(_field)), \ + .size = sizeof(SSISlave), \ + .vmsd = &vmstate_ssi_slave, \ + .flags = VMS_STRUCT, \ + .offset = vmstate_offset_value(_state, _field, SSISlave), \ +} + DeviceState *ssi_create_slave(SSIBus *bus, const char *name); /* Master interface. */ diff --git a/hw/stellaris.c b/hw/stellaris.c index 562fbbf494..01050d15ff 100644 --- a/hw/stellaris.c +++ b/hw/stellaris.c @@ -1184,10 +1184,11 @@ static uint32_t stellaris_ssi_bus_transfer(SSISlave *dev, uint32_t val) static const VMStateDescription vmstate_stellaris_ssi_bus = { .name = "stellaris_ssi_bus", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, + .version_id = 2, + .minimum_version_id = 2, + .minimum_version_id_old = 2, .fields = (VMStateField[]) { + VMSTATE_SSI_SLAVE(ssidev, stellaris_ssi_bus_state), VMSTATE_INT32(current_dev, stellaris_ssi_bus_state), VMSTATE_END_OF_LIST() } diff --git a/hw/z2.c b/hw/z2.c index 289cee90c4..076fad20c6 100644 --- a/hw/z2.c +++ b/hw/z2.c @@ -161,10 +161,11 @@ static int zipit_lcd_init(SSISlave *dev) static VMStateDescription vmstate_zipit_lcd_state = { .name = "zipit-lcd", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, + .version_id = 2, + .minimum_version_id = 2, + .minimum_version_id_old = 2, .fields = (VMStateField[]) { + VMSTATE_SSI_SLAVE(ssidev, ZipitLCD), VMSTATE_INT32(selected, ZipitLCD), VMSTATE_INT32(enabled, ZipitLCD), VMSTATE_BUFFER(buf, ZipitLCD), From 74687e40b0406a0863234ca011c3cba7720864b0 Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Tue, 24 Jul 2012 13:56:27 +1000 Subject: [PATCH 0842/2270] ssi: Added create_slave_no_init() Slave creation function that can be used to create an SSI slave without qdev_init() being called. This give machine models a chance to set properties. Signed-off-by: Peter A. G. Crosthwaite Acked-by: Peter Maydell --- hw/ssi.c | 9 +++++++-- hw/ssi.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/hw/ssi.c b/hw/ssi.c index 2e4f2fecd1..c47419d57f 100644 --- a/hw/ssi.c +++ b/hw/ssi.c @@ -86,10 +86,15 @@ static TypeInfo ssi_slave_info = { .abstract = true, }; +DeviceState *ssi_create_slave_no_init(SSIBus *bus, const char *name) +{ + return qdev_create(&bus->qbus, name); +} + DeviceState *ssi_create_slave(SSIBus *bus, const char *name) { - DeviceState *dev; - dev = qdev_create(&bus->qbus, name); + DeviceState *dev = ssi_create_slave_no_init(bus, name); + qdev_init_nofail(dev); return dev; } diff --git a/hw/ssi.h b/hw/ssi.h index 65b159dcab..2bde9f5b44 100644 --- a/hw/ssi.h +++ b/hw/ssi.h @@ -76,6 +76,7 @@ extern const VMStateDescription vmstate_ssi_slave; } DeviceState *ssi_create_slave(SSIBus *bus, const char *name); +DeviceState *ssi_create_slave_no_init(SSIBus *bus, const char *name); /* Master interface. */ SSIBus *ssi_create_bus(DeviceState *parent, const char *name); From 1e5b31e6bd4fa8a9c679a18388d2219feece275a Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Tue, 31 Jul 2012 12:24:06 +1000 Subject: [PATCH 0843/2270] qdev: allow multiple qdev_init_gpio_in() calls Allow multiple qdev_init_gpio_in() calls for the one device. The first call will define GPIOs 0-N-1, the next GPIOs N- ... . Allows different GPIOs to be handled with different handlers. Needed when two levels of the QOM class heirachy both define GPIO functionality, as a single GPIO handler with an index selecter is not possible. Signed-off-by: Peter A. G. Crosthwaite Reviewed-by: Peter Maydell --- hw/irq.c | 27 ++++++++++++++++++++------- hw/irq.h | 11 ++++++++++- hw/qdev.c | 6 +++--- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/hw/irq.c b/hw/irq.c index d413a0b235..f4e2a7804a 100644 --- a/hw/irq.c +++ b/hw/irq.c @@ -38,24 +38,37 @@ void qemu_set_irq(qemu_irq irq, int level) irq->handler(irq->opaque, irq->n, level); } -qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n) +qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler, + void *opaque, int n) { qemu_irq *s; struct IRQState *p; int i; - s = (qemu_irq *)g_malloc0(sizeof(qemu_irq) * n); - p = (struct IRQState *)g_malloc0(sizeof(struct IRQState) * n); - for (i = 0; i < n; i++) { - p->handler = handler; - p->opaque = opaque; - p->n = i; + if (!old) { + n_old = 0; + } + s = old ? g_renew(qemu_irq, old, n + n_old) : g_new(qemu_irq, n); + p = old ? g_renew(struct IRQState, s[0], n + n_old) : + g_new(struct IRQState, n); + for (i = 0; i < n + n_old; i++) { + if (i >= n_old) { + p->handler = handler; + p->opaque = opaque; + p->n = i; + } s[i] = p; p++; } return s; } +qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n) +{ + return qemu_extend_irqs(NULL, 0, handler, opaque, n); +} + + void qemu_free_irqs(qemu_irq *s) { g_free(s[0]); diff --git a/hw/irq.h b/hw/irq.h index 56c55f0c46..e640c105e7 100644 --- a/hw/irq.h +++ b/hw/irq.h @@ -23,8 +23,17 @@ static inline void qemu_irq_pulse(qemu_irq irq) qemu_set_irq(irq, 0); } -/* Returns an array of N IRQs. */ +/* Returns an array of N IRQs. Each IRQ is assigned the argument handler and + * opaque data. + */ qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n); + +/* Extends an Array of IRQs. Old IRQs have their handlers and opaque data + * preserved. New IRQs are assigned the argument handler and opaque data. + */ +qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler, + void *opaque, int n); + void qemu_free_irqs(qemu_irq *s); /* Returns a new IRQ with opposite polarity. */ diff --git a/hw/qdev.c b/hw/qdev.c index b6e9207ede..9b9aba376b 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -285,9 +285,9 @@ BusState *qdev_get_parent_bus(DeviceState *dev) void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) { - assert(dev->num_gpio_in == 0); - dev->num_gpio_in = n; - dev->gpio_in = qemu_allocate_irqs(handler, dev, n); + dev->gpio_in = qemu_extend_irqs(dev->gpio_in, dev->num_gpio_in, handler, + dev, n); + dev->num_gpio_in += n; } void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n) From 8120e7144b4007d26531835c7b6bc2b40a736cd2 Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Tue, 31 Jul 2012 16:42:04 +1000 Subject: [PATCH 0844/2270] stellaris: Removed SSI mux Removed the explicit SSI mux and wired the CS line directly up to the SSI devices. Signed-off-by: Peter A. G. Crosthwaite --- hw/ssd0323.c | 1 + hw/ssi-sd.c | 1 + hw/stellaris.c | 92 ++++++++------------------------------------------ 3 files changed, 17 insertions(+), 77 deletions(-) diff --git a/hw/ssd0323.c b/hw/ssd0323.c index 5d05a35bc2..9c42d648e2 100644 --- a/hw/ssd0323.c +++ b/hw/ssd0323.c @@ -354,6 +354,7 @@ static void ssd0323_class_init(ObjectClass *klass, void *data) k->init = ssd0323_init; k->transfer = ssd0323_transfer; + k->cs_polarity = SSI_CS_HIGH; } static TypeInfo ssd0323_info = { diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c index cbbc645213..c5505ee24f 100644 --- a/hw/ssi-sd.c +++ b/hw/ssi-sd.c @@ -256,6 +256,7 @@ static void ssi_sd_class_init(ObjectClass *klass, void *data) k->init = ssi_sd_init; k->transfer = ssi_sd_transfer; + k->cs_polarity = SSI_CS_LOW; } static TypeInfo ssi_sd_info = { diff --git a/hw/stellaris.c b/hw/stellaris.c index 01050d15ff..353ca4c046 100644 --- a/hw/stellaris.c +++ b/hw/stellaris.c @@ -1154,58 +1154,6 @@ static int stellaris_adc_init(SysBusDevice *dev) return 0; } -/* Some boards have both an OLED controller and SD card connected to - the same SSI port, with the SD card chip select connected to a - GPIO pin. Technically the OLED chip select is connected to the SSI - Fss pin. We do not bother emulating that as both devices should - never be selected simultaneously, and our OLED controller ignores stray - 0xff commands that occur when deselecting the SD card. */ - -typedef struct { - SSISlave ssidev; - qemu_irq irq; - int current_dev; - SSIBus *bus[2]; -} stellaris_ssi_bus_state; - -static void stellaris_ssi_bus_select(void *opaque, int irq, int level) -{ - stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque; - - s->current_dev = level; -} - -static uint32_t stellaris_ssi_bus_transfer(SSISlave *dev, uint32_t val) -{ - stellaris_ssi_bus_state *s = FROM_SSI_SLAVE(stellaris_ssi_bus_state, dev); - - return ssi_transfer(s->bus[s->current_dev], val); -} - -static const VMStateDescription vmstate_stellaris_ssi_bus = { - .name = "stellaris_ssi_bus", - .version_id = 2, - .minimum_version_id = 2, - .minimum_version_id_old = 2, - .fields = (VMStateField[]) { - VMSTATE_SSI_SLAVE(ssidev, stellaris_ssi_bus_state), - VMSTATE_INT32(current_dev, stellaris_ssi_bus_state), - VMSTATE_END_OF_LIST() - } -}; - -static int stellaris_ssi_bus_init(SSISlave *dev) -{ - stellaris_ssi_bus_state *s = FROM_SSI_SLAVE(stellaris_ssi_bus_state, dev); - - s->bus[0] = ssi_create_bus(&dev->qdev, "ssi0"); - s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1"); - qdev_init_gpio_in(&dev->qdev, stellaris_ssi_bus_select, 1); - - vmstate_register(&dev->qdev, -1, &vmstate_stellaris_ssi_bus, s); - return 0; -} - /* Board init. */ static stellaris_board_info stellaris_boards[] = { { "LM3S811EVB", @@ -1306,19 +1254,25 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, if (board->dc2 & (1 << 4)) { dev = sysbus_create_simple("pl022", 0x40008000, pic[7]); if (board->peripherals & BP_OLED_SSI) { - DeviceState *mux; void *bus; + DeviceState *sddev; + DeviceState *ssddev; + /* Some boards have both an OLED controller and SD card connected to + * the same SSI port, with the SD card chip select connected to a + * GPIO pin. Technically the OLED chip select is connected to the + * SSI Fss pin. We do not bother emulating that as both devices + * should never be selected simultaneously, and our OLED controller + * ignores stray 0xff commands that occur when deselecting the SD + * card. + */ bus = qdev_get_child_bus(dev, "ssi"); - mux = ssi_create_slave(bus, "evb6965-ssi"); - gpio_out[GPIO_D][0] = qdev_get_gpio_in(mux, 0); - bus = qdev_get_child_bus(mux, "ssi0"); - ssi_create_slave(bus, "ssi-sd"); - - bus = qdev_get_child_bus(mux, "ssi1"); - dev = ssi_create_slave(bus, "ssd0323"); - gpio_out[GPIO_C][7] = qdev_get_gpio_in(dev, 0); + sddev = ssi_create_slave(bus, "ssi-sd"); + ssddev = ssi_create_slave(bus, "ssd0323"); + gpio_out[GPIO_D][0] = qemu_irq_split(qdev_get_gpio_in(sddev, 0), + qdev_get_gpio_in(ssddev, 0)); + gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 1); /* Make sure the select pin is high. */ qemu_irq_raise(gpio_out[GPIO_D][0]); @@ -1395,21 +1349,6 @@ static void stellaris_machine_init(void) machine_init(stellaris_machine_init); -static void stellaris_ssi_bus_class_init(ObjectClass *klass, void *data) -{ - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); - - k->init = stellaris_ssi_bus_init; - k->transfer = stellaris_ssi_bus_transfer; -} - -static TypeInfo stellaris_ssi_bus_info = { - .name = "evb6965-ssi", - .parent = TYPE_SSI_SLAVE, - .instance_size = sizeof(stellaris_ssi_bus_state), - .class_init = stellaris_ssi_bus_class_init, -}; - static void stellaris_i2c_class_init(ObjectClass *klass, void *data) { SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); @@ -1457,7 +1396,6 @@ static void stellaris_register_types(void) type_register_static(&stellaris_i2c_info); type_register_static(&stellaris_gptm_info); type_register_static(&stellaris_adc_info); - type_register_static(&stellaris_ssi_bus_info); } type_init(stellaris_register_types) From a3578d4a51250365fb7f048e8154942a2659cc4a Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Wed, 1 Aug 2012 20:26:12 +1000 Subject: [PATCH 0845/2270] hw: Added generic FIFO API. Added a FIFO API that can be used to create and operate byte FIFOs. Signed-off-by: Peter A. G. Crosthwaite --- hw/Makefile.objs | 1 + hw/fifo.c | 78 ++++++++++++++++++++++++++++++++++++++ hw/fifo.h | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 hw/fifo.c create mode 100644 hw/fifo.h diff --git a/hw/Makefile.objs b/hw/Makefile.objs index b59c74953f..66abbb2c7e 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -35,6 +35,7 @@ common-obj-$(CONFIG_APPLESMC) += applesmc.o common-obj-$(CONFIG_SMARTCARD) += ccid-card-passthru.o common-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o common-obj-$(CONFIG_I8259) += i8259_common.o i8259.o +common-obj-y += fifo.o # PPC devices common-obj-$(CONFIG_PREP_PCI) += prep_pci.o diff --git a/hw/fifo.c b/hw/fifo.c new file mode 100644 index 0000000000..68a955a77b --- /dev/null +++ b/hw/fifo.c @@ -0,0 +1,78 @@ +/* + * Generic FIFO component, implemented as a circular buffer. + * + * Copyright (c) 2012 Peter A. G. Crosthwaite + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#include "fifo.h" + +void fifo8_create(Fifo8 *fifo, uint32_t capacity) +{ + fifo->data = g_new(uint8_t, capacity); + fifo->capacity = capacity; + fifo->head = 0; + fifo->num = 0; +} + +void fifo8_destroy(Fifo8 *fifo) +{ + g_free(fifo->data); +} + +void fifo8_push(Fifo8 *fifo, uint8_t data) +{ + if (fifo->num == fifo->capacity) { + abort(); + } + fifo->data[(fifo->head + fifo->num) % fifo->capacity] = data; + fifo->num++; +} + +uint8_t fifo8_pop(Fifo8 *fifo) +{ + uint8_t ret; + + if (fifo->num == 0) { + abort(); + } + ret = fifo->data[fifo->head++]; + fifo->head %= fifo->capacity; + fifo->num--; + return ret; +} + +void fifo8_reset(Fifo8 *fifo) +{ + fifo->num = 0; +} + +bool fifo8_is_empty(Fifo8 *fifo) +{ + return (fifo->num == 0); +} + +bool fifo8_is_full(Fifo8 *fifo) +{ + return (fifo->num == fifo->capacity); +} + +const VMStateDescription vmstate_fifo8 = { + .name = "Fifo8", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity), + VMSTATE_UINT32(head, Fifo8), + VMSTATE_UINT32(num, Fifo8), + VMSTATE_END_OF_LIST() + } +}; diff --git a/hw/fifo.h b/hw/fifo.h new file mode 100644 index 0000000000..f23890abf4 --- /dev/null +++ b/hw/fifo.h @@ -0,0 +1,99 @@ +#ifndef FIFO_H +#define FIFO_H + +#include "hw.h" + +typedef struct { + /* All fields are private */ + uint8_t *data; + uint32_t capacity; + uint32_t head; + uint32_t num; +} Fifo8; + +/** + * fifo8_create: + * @fifo: struct Fifo8 to initialise with new FIFO + * @capacity: capacity of the newly created FIFO + * + * Create a FIFO of the specified size. Clients should call fifo8_destroy() + * when finished using the fifo. The FIFO is initially empty. + */ + +void fifo8_create(Fifo8 *fifo, uint32_t capacity); + +/** + * fifo8_destroy: + * @fifo: FIFO to cleanup + * + * Cleanup a FIFO created with fifo8_create(). Frees memory created for FIFO + *storage. The FIFO is no longer usable after this has been called. + */ + +void fifo8_destroy(Fifo8 *fifo); + +/** + * fifo8_push: + * @fifo: FIFO to push to + * @data: data byte to push + * + * Push a data byte to the FIFO. Behaviour is undefined if the FIFO is full. + * Clients are responsible for checking for fullness using fifo8_is_full(). + */ + +void fifo8_push(Fifo8 *fifo, uint8_t data); + +/** + * fifo8_pop: + * @fifo: fifo to pop from + * + * Pop a data byte from the FIFO. Behaviour is undefined if the FIFO is empty. + * Clients are responsible for checking for emptyness using fifo8_is_empty(). + * + * Returns: The popped data byte. + */ + +uint8_t fifo8_pop(Fifo8 *fifo); + +/** + * fifo8_reset: + * @fifo: FIFO to reset + * + * Reset a FIFO. All data is discarded and the FIFO is emptied. + */ + +void fifo8_reset(Fifo8 *fifo); + +/** + * fifo8_is_empty: + * @fifo: FIFO to check + * + * Check if a FIFO is empty. + * + * Returns: True if the fifo is empty, false otherwise. + */ + +bool fifo8_is_empty(Fifo8 *fifo); + +/** + * fifo8_is_full: + * @fifo: FIFO to check + * + * Check if a FIFO is full. + * + * Returns: True if the fifo is full, false otherwise. + */ + +bool fifo8_is_full(Fifo8 *fifo); + +extern const VMStateDescription vmstate_fifo8; + +#define VMSTATE_FIFO8(_field, _state) { \ + .name = (stringify(_field)), \ + .size = sizeof(Fifo8), \ + .vmsd = &vmstate_fifo8, \ + .flags = VMS_STRUCT, \ + .offset = vmstate_offset_value(_state, _field, Fifo8), \ +} + +#endif /* FIFO_H */ From 82a2499011a73bcafab723e1bab4127e55a64844 Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Mon, 26 Mar 2012 22:10:59 +1000 Subject: [PATCH 0846/2270] m25p80: Initial implementation of SPI flash device Added device model for m25p80 style SPI flash family. Signed-off-by: Peter A. G. Crosthwaite --- default-configs/arm-softmmu.mak | 1 + default-configs/microblaze-softmmu.mak | 2 + default-configs/microblazeel-softmmu.mak | 2 + hw/Makefile.objs | 1 + hw/m25p80.c | 598 +++++++++++++++++++++++ 5 files changed, 604 insertions(+) create mode 100644 hw/m25p80.c diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index f335a725f0..2f1a5c9943 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -22,6 +22,7 @@ CONFIG_ADS7846=y CONFIG_MAX111X=y CONFIG_SSI=y CONFIG_SSI_SD=y +CONFIG_SSI_M25P80=y CONFIG_LAN9118=y CONFIG_SMC91C111=y CONFIG_DS1338=y diff --git a/default-configs/microblaze-softmmu.mak b/default-configs/microblaze-softmmu.mak index 64c9485de4..2f442e5aea 100644 --- a/default-configs/microblaze-softmmu.mak +++ b/default-configs/microblaze-softmmu.mak @@ -5,3 +5,5 @@ CONFIG_PFLASH_CFI01=y CONFIG_SERIAL=y CONFIG_XILINX=y CONFIG_XILINX_AXI=y +CONFIG_SSI=y +CONFIG_SSI_M25P80=y diff --git a/default-configs/microblazeel-softmmu.mak b/default-configs/microblazeel-softmmu.mak index a9622760c9..af9a3cde0d 100644 --- a/default-configs/microblazeel-softmmu.mak +++ b/default-configs/microblazeel-softmmu.mak @@ -5,3 +5,5 @@ CONFIG_PFLASH_CFI01=y CONFIG_SERIAL=y CONFIG_XILINX=y CONFIG_XILINX_AXI=y +CONFIG_SSI=y +CONFIG_SSI_M25P80=y diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 66abbb2c7e..854faa9b5b 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -174,6 +174,7 @@ common-obj-y += scsi-disk.o cdrom.o hd-geometry.o block-common.o common-obj-y += scsi-generic.o scsi-bus.o common-obj-y += hid.o common-obj-$(CONFIG_SSI) += ssi.o +common-obj-$(CONFIG_SSI_M25P80) += m25p80.o common-obj-$(CONFIG_SSI_SD) += ssi-sd.o common-obj-$(CONFIG_SD) += sd.o common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o diff --git a/hw/m25p80.c b/hw/m25p80.c new file mode 100644 index 0000000000..9a56de8023 --- /dev/null +++ b/hw/m25p80.c @@ -0,0 +1,598 @@ +/* + * ST M25P80 emulator. Emulate all SPI flash devices based on the m25p80 command + * set. Known devices table current as of Jun/2012 and taken from linux. + * See drivers/mtd/devices/m25p80.c. + * + * Copyright (C) 2011 Edgar E. Iglesias + * Copyright (C) 2012 Peter A. G. Crosthwaite + * Copyright (C) 2012 PetaLogix + * + * 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 or + * (at your option) a later version of the License. + * + * 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 . + */ + +#include "hw.h" +#include "blockdev.h" +#include "ssi.h" +#include "devices.h" + +#ifdef M25P80_ERR_DEBUG +#define DB_PRINT(...) do { \ + fprintf(stderr, ": %s: ", __func__); \ + fprintf(stderr, ## __VA_ARGS__); \ + } while (0); +#else + #define DB_PRINT(...) +#endif + +/* Fields for FlashPartInfo->flags */ + +/* erase capabilities */ +#define ER_4K 1 +#define ER_32K 2 +/* set to allow the page program command to write 0s back to 1. Useful for + * modelling EEPROM with SPI flash command set + */ +#define WR_1 0x100 + +typedef struct FlashPartInfo { + const char *part_name; + /* jedec code. (jedec >> 16) & 0xff is the 1st byte, >> 8 the 2nd etc */ + uint32_t jedec; + /* extended jedec code */ + uint16_t ext_jedec; + /* there is confusion between manufacturers as to what a sector is. In this + * device model, a "sector" is the size that is erased by the ERASE_SECTOR + * command (opcode 0xd8). + */ + uint32_t sector_size; + uint32_t n_sectors; + uint32_t page_size; + uint8_t flags; +} FlashPartInfo; + +/* adapted from linux */ + +#define INFO(_part_name, _jedec, _ext_jedec, _sector_size, _n_sectors, _flags)\ + .part_name = (_part_name),\ + .jedec = (_jedec),\ + .ext_jedec = (_ext_jedec),\ + .sector_size = (_sector_size),\ + .n_sectors = (_n_sectors),\ + .page_size = 256,\ + .flags = (_flags),\ + +static const FlashPartInfo known_devices[] = { + /* Atmel -- some are (confusingly) marketed as "DataFlash" */ + { INFO("at25fs010", 0x1f6601, 0, 32 << 10, 4, ER_4K) }, + { INFO("at25fs040", 0x1f6604, 0, 64 << 10, 8, ER_4K) }, + + { INFO("at25df041a", 0x1f4401, 0, 64 << 10, 8, ER_4K) }, + { INFO("at25df321a", 0x1f4701, 0, 64 << 10, 64, ER_4K) }, + { INFO("at25df641", 0x1f4800, 0, 64 << 10, 128, ER_4K) }, + + { INFO("at26f004", 0x1f0400, 0, 64 << 10, 8, ER_4K) }, + { INFO("at26df081a", 0x1f4501, 0, 64 << 10, 16, ER_4K) }, + { INFO("at26df161a", 0x1f4601, 0, 64 << 10, 32, ER_4K) }, + { INFO("at26df321", 0x1f4700, 0, 64 << 10, 64, ER_4K) }, + + /* EON -- en25xxx */ + { INFO("en25f32", 0x1c3116, 0, 64 << 10, 64, ER_4K) }, + { INFO("en25p32", 0x1c2016, 0, 64 << 10, 64, 0) }, + { INFO("en25q32b", 0x1c3016, 0, 64 << 10, 64, 0) }, + { INFO("en25p64", 0x1c2017, 0, 64 << 10, 128, 0) }, + + /* Intel/Numonyx -- xxxs33b */ + { INFO("160s33b", 0x898911, 0, 64 << 10, 32, 0) }, + { INFO("320s33b", 0x898912, 0, 64 << 10, 64, 0) }, + { INFO("640s33b", 0x898913, 0, 64 << 10, 128, 0) }, + + /* Macronix */ + { INFO("mx25l4005a", 0xc22013, 0, 64 << 10, 8, ER_4K) }, + { INFO("mx25l8005", 0xc22014, 0, 64 << 10, 16, 0) }, + { INFO("mx25l1606e", 0xc22015, 0, 64 << 10, 32, ER_4K) }, + { INFO("mx25l3205d", 0xc22016, 0, 64 << 10, 64, 0) }, + { INFO("mx25l6405d", 0xc22017, 0, 64 << 10, 128, 0) }, + { INFO("mx25l12805d", 0xc22018, 0, 64 << 10, 256, 0) }, + { INFO("mx25l12855e", 0xc22618, 0, 64 << 10, 256, 0) }, + { INFO("mx25l25635e", 0xc22019, 0, 64 << 10, 512, 0) }, + { INFO("mx25l25655e", 0xc22619, 0, 64 << 10, 512, 0) }, + + /* Spansion -- single (large) sector size only, at least + * for the chips listed here (without boot sectors). + */ + { INFO("s25sl004a", 0x010212, 0, 64 << 10, 8, 0) }, + { INFO("s25sl008a", 0x010213, 0, 64 << 10, 16, 0) }, + { INFO("s25sl016a", 0x010214, 0, 64 << 10, 32, 0) }, + { INFO("s25sl032a", 0x010215, 0, 64 << 10, 64, 0) }, + { INFO("s25sl032p", 0x010215, 0x4d00, 64 << 10, 64, ER_4K) }, + { INFO("s25sl064a", 0x010216, 0, 64 << 10, 128, 0) }, + { INFO("s25fl256s0", 0x010219, 0x4d00, 256 << 10, 128, 0) }, + { INFO("s25fl256s1", 0x010219, 0x4d01, 64 << 10, 512, 0) }, + { INFO("s25fl512s", 0x010220, 0x4d00, 256 << 10, 256, 0) }, + { INFO("s70fl01gs", 0x010221, 0x4d00, 256 << 10, 256, 0) }, + { INFO("s25sl12800", 0x012018, 0x0300, 256 << 10, 64, 0) }, + { INFO("s25sl12801", 0x012018, 0x0301, 64 << 10, 256, 0) }, + { INFO("s25fl129p0", 0x012018, 0x4d00, 256 << 10, 64, 0) }, + { INFO("s25fl129p1", 0x012018, 0x4d01, 64 << 10, 256, 0) }, + { INFO("s25fl016k", 0xef4015, 0, 64 << 10, 32, ER_4K | ER_32K) }, + { INFO("s25fl064k", 0xef4017, 0, 64 << 10, 128, ER_4K | ER_32K) }, + + /* SST -- large erase sizes are "overlays", "sectors" are 4<< 10 */ + { INFO("sst25vf040b", 0xbf258d, 0, 64 << 10, 8, ER_4K) }, + { INFO("sst25vf080b", 0xbf258e, 0, 64 << 10, 16, ER_4K) }, + { INFO("sst25vf016b", 0xbf2541, 0, 64 << 10, 32, ER_4K) }, + { INFO("sst25vf032b", 0xbf254a, 0, 64 << 10, 64, ER_4K) }, + { INFO("sst25wf512", 0xbf2501, 0, 64 << 10, 1, ER_4K) }, + { INFO("sst25wf010", 0xbf2502, 0, 64 << 10, 2, ER_4K) }, + { INFO("sst25wf020", 0xbf2503, 0, 64 << 10, 4, ER_4K) }, + { INFO("sst25wf040", 0xbf2504, 0, 64 << 10, 8, ER_4K) }, + + /* ST Microelectronics -- newer production may have feature updates */ + { INFO("m25p05", 0x202010, 0, 32 << 10, 2, 0) }, + { INFO("m25p10", 0x202011, 0, 32 << 10, 4, 0) }, + { INFO("m25p20", 0x202012, 0, 64 << 10, 4, 0) }, + { INFO("m25p40", 0x202013, 0, 64 << 10, 8, 0) }, + { INFO("m25p80", 0x202014, 0, 64 << 10, 16, 0) }, + { INFO("m25p16", 0x202015, 0, 64 << 10, 32, 0) }, + { INFO("m25p32", 0x202016, 0, 64 << 10, 64, 0) }, + { INFO("m25p64", 0x202017, 0, 64 << 10, 128, 0) }, + { INFO("m25p128", 0x202018, 0, 256 << 10, 64, 0) }, + + { INFO("m45pe10", 0x204011, 0, 64 << 10, 2, 0) }, + { INFO("m45pe80", 0x204014, 0, 64 << 10, 16, 0) }, + { INFO("m45pe16", 0x204015, 0, 64 << 10, 32, 0) }, + + { INFO("m25pe80", 0x208014, 0, 64 << 10, 16, 0) }, + { INFO("m25pe16", 0x208015, 0, 64 << 10, 32, ER_4K) }, + + { INFO("m25px32", 0x207116, 0, 64 << 10, 64, ER_4K) }, + { INFO("m25px32-s0", 0x207316, 0, 64 << 10, 64, ER_4K) }, + { INFO("m25px32-s1", 0x206316, 0, 64 << 10, 64, ER_4K) }, + { INFO("m25px64", 0x207117, 0, 64 << 10, 128, 0) }, + + /* Winbond -- w25x "blocks" are 64k, "sectors" are 4KiB */ + { INFO("w25x10", 0xef3011, 0, 64 << 10, 2, ER_4K) }, + { INFO("w25x20", 0xef3012, 0, 64 << 10, 4, ER_4K) }, + { INFO("w25x40", 0xef3013, 0, 64 << 10, 8, ER_4K) }, + { INFO("w25x80", 0xef3014, 0, 64 << 10, 16, ER_4K) }, + { INFO("w25x16", 0xef3015, 0, 64 << 10, 32, ER_4K) }, + { INFO("w25x32", 0xef3016, 0, 64 << 10, 64, ER_4K) }, + { INFO("w25q32", 0xef4016, 0, 64 << 10, 64, ER_4K) }, + { INFO("w25x64", 0xef3017, 0, 64 << 10, 128, ER_4K) }, + { INFO("w25q64", 0xef4017, 0, 64 << 10, 128, ER_4K) }, + + /* Numonyx -- n25q128 */ + { INFO("n25q128", 0x20ba18, 0, 64 << 10, 256, 0) }, + + { }, +}; + +typedef enum { + NOP = 0, + PP = 0x2, + READ = 0x3, + WRDI = 0x4, + RDSR = 0x5, + WREN = 0x6, + FAST_READ = 0xb, + ERASE_4K = 0x20, + ERASE_32K = 0x52, + ERASE_SECTOR = 0xd8, + JEDEC_READ = 0x9f, + BULK_ERASE = 0xc7, +} FlashCMD; + +typedef enum { + STATE_IDLE, + STATE_PAGE_PROGRAM, + STATE_READ, + STATE_COLLECTING_DATA, + STATE_READING_DATA, +} CMDState; + +typedef struct Flash { + SSISlave ssidev; + uint32_t r; + + BlockDriverState *bdrv; + + uint8_t *storage; + uint32_t size; + int page_size; + + uint8_t state; + uint8_t data[16]; + uint32_t len; + uint32_t pos; + uint8_t needed_bytes; + uint8_t cmd_in_progress; + uint64_t cur_addr; + bool write_enable; + + int64_t dirty_page; + + char *part_name; + const FlashPartInfo *pi; + +} Flash; + +static void bdrv_sync_complete(void *opaque, int ret) +{ + /* do nothing. Masters do not directly interact with the backing store, + * only the working copy so no mutexing required. + */ +} + +static void flash_sync_page(Flash *s, int page) +{ + if (s->bdrv) { + int bdrv_sector, nb_sectors; + QEMUIOVector iov; + + bdrv_sector = (page * s->pi->page_size) / BDRV_SECTOR_SIZE; + nb_sectors = DIV_ROUND_UP(s->pi->page_size, BDRV_SECTOR_SIZE); + qemu_iovec_init(&iov, 1); + qemu_iovec_add(&iov, s->storage + bdrv_sector * BDRV_SECTOR_SIZE, + nb_sectors * BDRV_SECTOR_SIZE); + bdrv_aio_writev(s->bdrv, bdrv_sector, &iov, nb_sectors, + bdrv_sync_complete, NULL); + } +} + +static inline void flash_sync_area(Flash *s, int64_t off, int64_t len) +{ + int64_t start, end, nb_sectors; + QEMUIOVector iov; + + if (!s->bdrv) { + return; + } + + assert(!(len % BDRV_SECTOR_SIZE)); + start = off / BDRV_SECTOR_SIZE; + end = (off + len) / BDRV_SECTOR_SIZE; + nb_sectors = end - start; + qemu_iovec_init(&iov, 1); + qemu_iovec_add(&iov, s->storage + (start * BDRV_SECTOR_SIZE), + nb_sectors * BDRV_SECTOR_SIZE); + bdrv_aio_writev(s->bdrv, start, &iov, nb_sectors, bdrv_sync_complete, NULL); +} + +static void flash_erase(Flash *s, int offset, FlashCMD cmd) +{ + uint32_t len; + uint8_t capa_to_assert = 0; + + switch (cmd) { + case ERASE_4K: + len = 4 << 10; + capa_to_assert = ER_4K; + break; + case ERASE_32K: + len = 32 << 10; + capa_to_assert = ER_32K; + break; + case ERASE_SECTOR: + len = s->pi->sector_size; + break; + case BULK_ERASE: + len = s->size; + break; + default: + abort(); + } + + DB_PRINT("offset = %#x, len = %d\n", offset, len); + if ((s->pi->flags & capa_to_assert) != capa_to_assert) { + hw_error("m25p80: %dk erase size not supported by device\n", len); + } + + if (!s->write_enable) { + DB_PRINT("erase with write protect!\n"); + return; + } + memset(s->storage + offset, 0xff, len); + flash_sync_area(s, offset, len); +} + +static inline void flash_sync_dirty(Flash *s, int64_t newpage) +{ + if (s->dirty_page >= 0 && s->dirty_page != newpage) { + flash_sync_page(s, s->dirty_page); + s->dirty_page = newpage; + } +} + +static inline +void flash_write8(Flash *s, uint64_t addr, uint8_t data) +{ + int64_t page = addr / s->pi->page_size; + uint8_t prev = s->storage[s->cur_addr]; + + if (!s->write_enable) { + DB_PRINT("write with write protect!\n"); + } + + if ((prev ^ data) & data) { + DB_PRINT("programming zero to one! addr=%lx %x -> %x\n", + addr, prev, data); + } + + if (s->pi->flags & WR_1) { + s->storage[s->cur_addr] = data; + } else { + s->storage[s->cur_addr] &= data; + } + + flash_sync_dirty(s, page); + s->dirty_page = page; +} + +static void complete_collecting_data(Flash *s) +{ + s->cur_addr = s->data[0] << 16; + s->cur_addr |= s->data[1] << 8; + s->cur_addr |= s->data[2]; + + switch (s->cmd_in_progress) { + case PP: + s->state = STATE_PAGE_PROGRAM; + break; + case READ: + case FAST_READ: + s->state = STATE_READ; + break; + case ERASE_4K: + case ERASE_32K: + case ERASE_SECTOR: + flash_erase(s, s->cur_addr, s->cmd_in_progress); + break; + default: + break; + } +} + +static void decode_new_cmd(Flash *s, uint32_t value) +{ + s->cmd_in_progress = value; + DB_PRINT("decoded new command:%x\n", value); + + switch (value) { + + case ERASE_4K: + case ERASE_32K: + case ERASE_SECTOR: + case READ: + case PP: + s->needed_bytes = 3; + s->pos = 0; + s->len = 0; + s->state = STATE_COLLECTING_DATA; + break; + + case FAST_READ: + s->needed_bytes = 4; + s->pos = 0; + s->len = 0; + s->state = STATE_COLLECTING_DATA; + break; + + case WRDI: + s->write_enable = false; + break; + case WREN: + s->write_enable = true; + break; + + case RDSR: + s->data[0] = (!!s->write_enable) << 1; + s->pos = 0; + s->len = 1; + s->state = STATE_READING_DATA; + break; + + case JEDEC_READ: + DB_PRINT("populated jedec code\n"); + s->data[0] = (s->pi->jedec >> 16) & 0xff; + s->data[1] = (s->pi->jedec >> 8) & 0xff; + s->data[2] = s->pi->jedec & 0xff; + if (s->pi->ext_jedec) { + s->data[3] = (s->pi->ext_jedec >> 8) & 0xff; + s->data[4] = s->pi->ext_jedec & 0xff; + s->len = 5; + } else { + s->len = 3; + } + s->pos = 0; + s->state = STATE_READING_DATA; + break; + + case BULK_ERASE: + if (s->write_enable) { + DB_PRINT("chip erase\n"); + flash_erase(s, 0, BULK_ERASE); + } else { + DB_PRINT("chip erase with write protect!\n"); + } + break; + case NOP: + break; + default: + DB_PRINT("Unknown cmd %x\n", value); + break; + } +} + +static int m25p80_cs(SSISlave *ss, bool select) +{ + Flash *s = FROM_SSI_SLAVE(Flash, ss); + + if (select) { + s->len = 0; + s->pos = 0; + s->state = STATE_IDLE; + flash_sync_dirty(s, -1); + } + + DB_PRINT("%sselect\n", select ? "de" : ""); + + return 0; +} + +static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx) +{ + Flash *s = FROM_SSI_SLAVE(Flash, ss); + uint32_t r = 0; + + switch (s->state) { + + case STATE_PAGE_PROGRAM: + DB_PRINT("page program cur_addr=%lx data=%x\n", s->cur_addr, + (uint8_t)tx); + flash_write8(s, s->cur_addr, (uint8_t)tx); + s->cur_addr++; + break; + + case STATE_READ: + r = s->storage[s->cur_addr]; + DB_PRINT("READ 0x%lx=%x\n", s->cur_addr, r); + s->cur_addr = (s->cur_addr + 1) % s->size; + break; + + case STATE_COLLECTING_DATA: + s->data[s->len] = (uint8_t)tx; + s->len++; + + if (s->len == s->needed_bytes) { + complete_collecting_data(s); + } + break; + + case STATE_READING_DATA: + r = s->data[s->pos]; + s->pos++; + if (s->pos == s->len) { + s->pos = 0; + s->state = STATE_IDLE; + } + break; + + default: + case STATE_IDLE: + decode_new_cmd(s, (uint8_t)tx); + break; + } + + return r; +} + +static int m25p80_init(SSISlave *ss) +{ + DriveInfo *dinfo; + Flash *s = FROM_SSI_SLAVE(Flash, ss); + const FlashPartInfo *i; + + if (!s->part_name) { /* default to actual m25p80 if no partname given */ + s->part_name = (char *)"m25p80"; + } + + i = known_devices; + for (i = known_devices;; i++) { + assert(i); + if (!i->part_name) { + fprintf(stderr, "Unknown SPI flash part: \"%s\"\n", s->part_name); + return 1; + } else if (!strcmp(i->part_name, s->part_name)) { + s->pi = i; + break; + } + } + + s->size = s->pi->sector_size * s->pi->n_sectors; + s->dirty_page = -1; + s->storage = qemu_blockalign(s->bdrv, s->size); + + dinfo = drive_get_next(IF_MTD); + + if (dinfo && dinfo->bdrv) { + DB_PRINT("Binding to IF_MTD drive\n"); + s->bdrv = dinfo->bdrv; + /* FIXME: Move to late init */ + if (bdrv_read(s->bdrv, 0, s->storage, DIV_ROUND_UP(s->size, + BDRV_SECTOR_SIZE))) { + fprintf(stderr, "Failed to initialize SPI flash!\n"); + return 1; + } + } else { + memset(s->storage, 0xFF, s->size); + } + + return 0; +} + +static void m25p80_pre_save(void *opaque) +{ + flash_sync_dirty((Flash *)opaque, -1); +} + +static const VMStateDescription vmstate_m25p80 = { + .name = "xilinx_spi", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .pre_save = m25p80_pre_save, + .fields = (VMStateField[]) { + VMSTATE_UINT8(state, Flash), + VMSTATE_UINT8_ARRAY(data, Flash, 16), + VMSTATE_UINT32(len, Flash), + VMSTATE_UINT32(pos, Flash), + VMSTATE_UINT8(needed_bytes, Flash), + VMSTATE_UINT8(cmd_in_progress, Flash), + VMSTATE_UINT64(cur_addr, Flash), + VMSTATE_BOOL(write_enable, Flash), + VMSTATE_END_OF_LIST() + } +}; + +static Property m25p80_properties[] = { + DEFINE_PROP_STRING("partname", Flash, part_name), + DEFINE_PROP_END_OF_LIST(), +}; + +static void m25p80_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + + k->init = m25p80_init; + k->transfer = m25p80_transfer8; + k->set_cs = m25p80_cs; + k->cs_polarity = SSI_CS_LOW; + dc->props = m25p80_properties; + dc->vmsd = &vmstate_m25p80; +} + +static const TypeInfo m25p80_info = { + .name = "m25p80", + .parent = TYPE_SSI_SLAVE, + .instance_size = sizeof(Flash), + .class_init = m25p80_class_init, +}; + +static void m25p80_register_types(void) +{ + type_register_static(&m25p80_info); +} + +type_init(m25p80_register_types) From 929d1b52c43327b8a9e5a19f916ad6c9d1e6de5d Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Mon, 26 Mar 2012 22:59:55 +1000 Subject: [PATCH 0847/2270] xilinx_spi: Initial impl. of Xilinx SPI controller Device model for xilinx XPS SPI controller (v2.0) Signed-off-by: Peter A. G. Crosthwaite --- hw/microblaze/Makefile.objs | 1 + hw/xilinx_spi.c | 383 ++++++++++++++++++++++++++++++++++++ 2 files changed, 384 insertions(+) create mode 100644 hw/xilinx_spi.c diff --git a/hw/microblaze/Makefile.objs b/hw/microblaze/Makefile.objs index 274d2c543e..3028e651c8 100644 --- a/hw/microblaze/Makefile.objs +++ b/hw/microblaze/Makefile.objs @@ -1,6 +1,7 @@ obj-y = petalogix_s3adsp1800_mmu.o obj-y += petalogix_ml605_mmu.o obj-y += microblaze_boot.o +obj-y += xilinx_spi.o obj-y += microblaze_pic_cpu.o obj-y += xilinx_ethlite.o diff --git a/hw/xilinx_spi.c b/hw/xilinx_spi.c new file mode 100644 index 0000000000..7db47877e2 --- /dev/null +++ b/hw/xilinx_spi.c @@ -0,0 +1,383 @@ +/* + * QEMU model of the Xilinx SPI Controller + * + * Copyright (C) 2010 Edgar E. Iglesias. + * Copyright (C) 2012 Peter A. G. Crosthwaite + * Copyright (C) 2012 PetaLogix + * + * 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 "sysbus.h" +#include "sysemu.h" +#include "qemu-log.h" +#include "fifo.h" + +#include "ssi.h" + +#ifdef XILINX_SPI_ERR_DEBUG +#define DB_PRINT(...) do { \ + fprintf(stderr, ": %s: ", __func__); \ + fprintf(stderr, ## __VA_ARGS__); \ + } while (0); +#else + #define DB_PRINT(...) +#endif + +#define R_DGIER (0x1c / 4) +#define R_DGIER_IE (1 << 31) + +#define R_IPISR (0x20 / 4) +#define IRQ_DRR_NOT_EMPTY (1 << (31 - 23)) +#define IRQ_DRR_OVERRUN (1 << (31 - 26)) +#define IRQ_DRR_FULL (1 << (31 - 27)) +#define IRQ_TX_FF_HALF_EMPTY (1 << 6) +#define IRQ_DTR_UNDERRUN (1 << 3) +#define IRQ_DTR_EMPTY (1 << (31 - 29)) + +#define R_IPIER (0x28 / 4) +#define R_SRR (0x40 / 4) +#define R_SPICR (0x60 / 4) +#define R_SPICR_TXFF_RST (1 << 5) +#define R_SPICR_RXFF_RST (1 << 6) +#define R_SPICR_MTI (1 << 8) + +#define R_SPISR (0x64 / 4) +#define SR_TX_FULL (1 << 3) +#define SR_TX_EMPTY (1 << 2) +#define SR_RX_FULL (1 << 1) +#define SR_RX_EMPTY (1 << 0) + +#define R_SPIDTR (0x68 / 4) +#define R_SPIDRR (0x6C / 4) +#define R_SPISSR (0x70 / 4) +#define R_TX_FF_OCY (0x74 / 4) +#define R_RX_FF_OCY (0x78 / 4) +#define R_MAX (0x7C / 4) + +#define FIFO_CAPACITY 256 + +typedef struct XilinxSPI { + SysBusDevice busdev; + MemoryRegion mmio; + + qemu_irq irq; + int irqline; + + uint8_t num_cs; + qemu_irq *cs_lines; + + SSIBus *spi; + + Fifo8 rx_fifo; + Fifo8 tx_fifo; + + uint32_t regs[R_MAX]; +} XilinxSPI; + +static void txfifo_reset(XilinxSPI *s) +{ + fifo8_reset(&s->tx_fifo); + + s->regs[R_SPISR] &= ~SR_TX_FULL; + s->regs[R_SPISR] |= SR_TX_EMPTY; +} + +static void rxfifo_reset(XilinxSPI *s) +{ + fifo8_reset(&s->rx_fifo); + + s->regs[R_SPISR] |= SR_RX_EMPTY; + s->regs[R_SPISR] &= ~SR_RX_FULL; +} + +static void xlx_spi_update_cs(XilinxSPI *s) +{ + int i; + + for (i = 0; i < s->num_cs; ++i) { + qemu_set_irq(s->cs_lines[i], !(~s->regs[R_SPISSR] & 1 << i)); + } +} + +static void xlx_spi_update_irq(XilinxSPI *s) +{ + uint32_t pending; + + s->regs[R_IPISR] |= + (!fifo8_is_empty(&s->rx_fifo) ? IRQ_DRR_NOT_EMPTY : 0) | + (fifo8_is_full(&s->rx_fifo) ? IRQ_DRR_FULL : 0); + + pending = s->regs[R_IPISR] & s->regs[R_IPIER]; + + pending = pending && (s->regs[R_DGIER] & R_DGIER_IE); + pending = !!pending; + + /* This call lies right in the data paths so don't call the + irq chain unless things really changed. */ + if (pending != s->irqline) { + s->irqline = pending; + DB_PRINT("irq_change of state %d ISR:%x IER:%X\n", + pending, s->regs[R_IPISR], s->regs[R_IPIER]); + qemu_set_irq(s->irq, pending); + } + +} + +static void xlx_spi_do_reset(XilinxSPI *s) +{ + memset(s->regs, 0, sizeof s->regs); + + rxfifo_reset(s); + txfifo_reset(s); + + s->regs[R_SPISSR] = ~0; + xlx_spi_update_irq(s); + xlx_spi_update_cs(s); +} + +static void xlx_spi_reset(DeviceState *d) +{ + xlx_spi_do_reset(DO_UPCAST(XilinxSPI, busdev.qdev, d)); +} + +static inline int spi_master_enabled(XilinxSPI *s) +{ + return !(s->regs[R_SPICR] & R_SPICR_MTI); +} + +static void spi_flush_txfifo(XilinxSPI *s) +{ + uint32_t tx; + uint32_t rx; + + while (!fifo8_is_empty(&s->tx_fifo)) { + tx = (uint32_t)fifo8_pop(&s->tx_fifo); + DB_PRINT("data tx:%x\n", tx); + rx = ssi_transfer(s->spi, tx); + DB_PRINT("data rx:%x\n", rx); + if (fifo8_is_full(&s->rx_fifo)) { + s->regs[R_IPISR] |= IRQ_DRR_OVERRUN; + } else { + fifo8_push(&s->rx_fifo, (uint8_t)rx); + if (fifo8_is_full(&s->rx_fifo)) { + s->regs[R_SPISR] |= SR_RX_FULL; + s->regs[R_IPISR] |= IRQ_DRR_FULL; + } + } + + s->regs[R_SPISR] &= ~SR_RX_EMPTY; + s->regs[R_SPISR] &= ~SR_TX_FULL; + s->regs[R_SPISR] |= SR_TX_EMPTY; + + s->regs[R_IPISR] |= IRQ_DTR_EMPTY; + s->regs[R_IPISR] |= IRQ_DRR_NOT_EMPTY; + } + +} + +static uint64_t +spi_read(void *opaque, target_phys_addr_t addr, unsigned int size) +{ + XilinxSPI *s = opaque; + uint32_t r = 0; + + addr >>= 2; + switch (addr) { + case R_SPIDRR: + if (fifo8_is_empty(&s->rx_fifo)) { + DB_PRINT("Read from empty FIFO!\n"); + return 0xdeadbeef; + } + + s->regs[R_SPISR] &= ~SR_RX_FULL; + r = fifo8_pop(&s->rx_fifo); + if (fifo8_is_empty(&s->rx_fifo)) { + s->regs[R_SPISR] |= SR_RX_EMPTY; + } + break; + + case R_SPISR: + r = s->regs[addr]; + break; + + default: + if (addr < ARRAY_SIZE(s->regs)) { + r = s->regs[addr]; + } + break; + + } + DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, r); + xlx_spi_update_irq(s); + return r; +} + +static void +spi_write(void *opaque, target_phys_addr_t addr, + uint64_t val64, unsigned int size) +{ + XilinxSPI *s = opaque; + uint32_t value = val64; + + DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr, value); + addr >>= 2; + switch (addr) { + case R_SRR: + if (value != 0xa) { + DB_PRINT("Invalid write to SRR %x\n", value); + } else { + xlx_spi_do_reset(s); + } + break; + + case R_SPIDTR: + s->regs[R_SPISR] &= ~SR_TX_EMPTY; + fifo8_push(&s->tx_fifo, (uint8_t)value); + if (fifo8_is_full(&s->tx_fifo)) { + s->regs[R_SPISR] |= SR_TX_FULL; + } + if (!spi_master_enabled(s)) { + goto done; + } else { + DB_PRINT("DTR and master enabled\n"); + } + spi_flush_txfifo(s); + break; + + case R_SPISR: + DB_PRINT("Invalid write to SPISR %x\n", value); + break; + + case R_IPISR: + /* Toggle the bits. */ + s->regs[addr] ^= value; + break; + + /* Slave Select Register. */ + case R_SPISSR: + s->regs[addr] = value; + xlx_spi_update_cs(s); + break; + + case R_SPICR: + /* FIXME: reset irq and sr state to empty queues. */ + if (value & R_SPICR_RXFF_RST) { + rxfifo_reset(s); + } + + if (value & R_SPICR_TXFF_RST) { + txfifo_reset(s); + } + value &= ~(R_SPICR_RXFF_RST | R_SPICR_TXFF_RST); + s->regs[addr] = value; + + if (!(value & R_SPICR_MTI)) { + spi_flush_txfifo(s); + } + break; + + default: + if (addr < ARRAY_SIZE(s->regs)) { + s->regs[addr] = value; + } + break; + } + +done: + xlx_spi_update_irq(s); +} + +static const MemoryRegionOps spi_ops = { + .read = spi_read, + .write = spi_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } +}; + +static int xilinx_spi_init(SysBusDevice *dev) +{ + int i; + XilinxSPI *s = FROM_SYSBUS(typeof(*s), dev); + + DB_PRINT("\n"); + sysbus_init_irq(dev, &s->irq); + s->cs_lines = g_new(qemu_irq, s->num_cs); + for (i = 0; i < s->num_cs; ++i) { + sysbus_init_irq(dev, &s->cs_lines[i]); + } + + memory_region_init_io(&s->mmio, &spi_ops, s, "xilinx-spi", R_MAX * 4); + sysbus_init_mmio(dev, &s->mmio); + + s->irqline = -1; + + s->spi = ssi_create_bus(&dev->qdev, "spi"); + + fifo8_create(&s->tx_fifo, FIFO_CAPACITY); + fifo8_create(&s->rx_fifo, FIFO_CAPACITY); + + return 0; +} + +static const VMStateDescription vmstate_xilinx_spi = { + .name = "xilinx_spi", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_FIFO8(tx_fifo, XilinxSPI), + VMSTATE_FIFO8(rx_fifo, XilinxSPI), + VMSTATE_UINT32_ARRAY(regs, XilinxSPI, R_MAX), + VMSTATE_END_OF_LIST() + } +}; + +static Property xilinx_spi_properties[] = { + DEFINE_PROP_UINT8("num-ss-bits", XilinxSPI, num_cs, 1), + DEFINE_PROP_END_OF_LIST(), +}; + +static void xilinx_spi_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = xilinx_spi_init; + dc->reset = xlx_spi_reset; + dc->props = xilinx_spi_properties; + dc->vmsd = &vmstate_xilinx_spi; +} + +static TypeInfo xilinx_spi_info = { + .name = "xlnx.xps-spi", + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(XilinxSPI), + .class_init = xilinx_spi_class_init, +}; + +static void xilinx_spi_register_types(void) +{ + type_register_static(&xilinx_spi_info); +} + +type_init(xilinx_spi_register_types) From acd3b6be325a66f8f10f0eed19ed5261ced411cf Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Tue, 27 Mar 2012 17:57:47 +1000 Subject: [PATCH 0848/2270] petalogix-ml605: added SPI controller with n25q128 Added SPI controller to the reference design, with two n25q128 spi-flashes connected. Signed-off-by: Peter A. G. Crosthwaite Acked-by: Peter Maydell --- hw/petalogix_ml605_mmu.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c index dced648f45..b9bfbed4c4 100644 --- a/hw/petalogix_ml605_mmu.c +++ b/hw/petalogix_ml605_mmu.c @@ -36,6 +36,7 @@ #include "blockdev.h" #include "pc.h" #include "exec-memory.h" +#include "ssi.h" #include "microblaze_boot.h" #include "microblaze_pic_cpu.h" @@ -47,6 +48,8 @@ #define BINARY_DEVICE_TREE_FILE "petalogix-ml605.dtb" +#define NUM_SPI_FLASHES 4 + #define MEMORY_BASEADDR 0x50000000 #define FLASH_BASEADDR 0x86000000 #define INTC_BASEADDR 0x81800000 @@ -79,6 +82,7 @@ petalogix_ml605_init(ram_addr_t ram_size, MemoryRegion *address_space_mem = get_system_memory(); DeviceState *dev, *dma, *eth0; MicroBlazeCPU *cpu; + SysBusDevice *busdev; CPUMBState *env; DriveInfo *dinfo; int i; @@ -139,6 +143,29 @@ petalogix_ml605_init(ram_addr_t ram_size, xilinx_axiethernetdma_init(dma, STREAM_SLAVE(eth0), 0x84600000, irq[1], irq[0], 100 * 1000000); + { + SSIBus *spi; + + dev = qdev_create(NULL, "xlnx.xps-spi"); + qdev_prop_set_uint8(dev, "num-ss-bits", NUM_SPI_FLASHES); + qdev_init_nofail(dev); + busdev = sysbus_from_qdev(dev); + sysbus_mmio_map(busdev, 0, 0x40a00000); + sysbus_connect_irq(busdev, 0, irq[4]); + + spi = (SSIBus *)qdev_get_child_bus(dev, "spi"); + + for (i = 0; i < NUM_SPI_FLASHES; i++) { + qemu_irq cs_line; + + dev = ssi_create_slave_no_init(spi, "m25p80"); + qdev_prop_set_string(dev, "partname", "n25q128"); + qdev_init_nofail(dev); + cs_line = qdev_get_gpio_in(dev, 0); + sysbus_connect_irq(busdev, i+1, cs_line); + } + } + microblaze_load_kernel(cpu, ddr_base, ram_size, BINARY_DEVICE_TREE_FILE, machine_cpu_reset); From 94befa454d430655fc863a7a855302b80f7a4812 Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Wed, 1 Aug 2012 20:52:36 +1000 Subject: [PATCH 0849/2270] xilinx_spips: Xilinx Zynq SPI cntrlr device model Added device model for the Xilinx Zynq SPI controller (SPIPS). Signed-off-by: Peter A. G. Crosthwaite Acked-by: Peter Maydell --- hw/arm/Makefile.objs | 1 + hw/xilinx_spips.c | 352 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 353 insertions(+) create mode 100644 hw/xilinx_spips.c diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 2b39fb3c85..6d049e7de6 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -1,6 +1,7 @@ obj-y = integratorcp.o versatilepb.o arm_pic.o obj-y += arm_boot.o obj-y += xilinx_zynq.o zynq_slcr.o +obj-y += xilinx_spips.o obj-y += arm_gic.o arm_gic_common.o obj-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o obj-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c new file mode 100644 index 0000000000..a886c5d311 --- /dev/null +++ b/hw/xilinx_spips.c @@ -0,0 +1,352 @@ +/* + * QEMU model of the Xilinx Zynq SPI controller + * + * Copyright (c) 2012 Peter A. G. Crosthwaite + * + * 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 "sysbus.h" +#include "sysemu.h" +#include "ptimer.h" +#include "qemu-log.h" +#include "fifo.h" +#include "ssi.h" + +#ifdef XILINX_SPIPS_ERR_DEBUG +#define DB_PRINT(...) do { \ + fprintf(stderr, ": %s: ", __func__); \ + fprintf(stderr, ## __VA_ARGS__); \ + } while (0); +#else + #define DB_PRINT(...) +#endif + +/* config register */ +#define R_CONFIG (0x00 / 4) +#define MODEFAIL_GEN_EN (1 << 17) +#define MAN_START_COM (1 << 16) +#define MAN_START_EN (1 << 15) +#define MANUAL_CS (1 << 14) +#define CS (0xF << 10) +#define CS_SHIFT (10) +#define PERI_SEL (1 << 9) +#define REF_CLK (1 << 8) +#define FIFO_WIDTH (3 << 6) +#define BAUD_RATE_DIV (7 << 3) +#define CLK_PH (1 << 2) +#define CLK_POL (1 << 1) +#define MODE_SEL (1 << 0) + +/* interrupt mechanism */ +#define R_INTR_STATUS (0x04 / 4) +#define R_INTR_EN (0x08 / 4) +#define R_INTR_DIS (0x0C / 4) +#define R_INTR_MASK (0x10 / 4) +#define IXR_TX_FIFO_UNDERFLOW (1 << 6) +#define IXR_RX_FIFO_FULL (1 << 5) +#define IXR_RX_FIFO_NOT_EMPTY (1 << 4) +#define IXR_TX_FIFO_FULL (1 << 3) +#define IXR_TX_FIFO_NOT_FULL (1 << 2) +#define IXR_TX_FIFO_MODE_FAIL (1 << 1) +#define IXR_RX_FIFO_OVERFLOW (1 << 0) +#define IXR_ALL ((IXR_TX_FIFO_UNDERFLOW<<1)-1) + +#define R_EN (0x14 / 4) +#define R_DELAY (0x18 / 4) +#define R_TX_DATA (0x1C / 4) +#define R_RX_DATA (0x20 / 4) +#define R_SLAVE_IDLE_COUNT (0x24 / 4) +#define R_TX_THRES (0x28 / 4) +#define R_RX_THRES (0x2C / 4) +#define R_MOD_ID (0xFC / 4) + +#define R_MAX (R_MOD_ID+1) + +/* size of TXRX FIFOs */ +#define NUM_CS_LINES 4 +#define RXFF_A 32 +#define TXFF_A 32 + +typedef struct { + SysBusDevice busdev; + MemoryRegion iomem; + qemu_irq irq; + int irqline; + + qemu_irq cs_lines[NUM_CS_LINES]; + SSIBus *spi; + + Fifo8 rx_fifo; + Fifo8 tx_fifo; + + uint32_t regs[R_MAX]; +} XilinxSPIPS; + +static void xilinx_spips_update_cs_lines(XilinxSPIPS *s) +{ + int i; + bool found = false; + int field = s->regs[R_CONFIG] >> CS_SHIFT; + + for (i = 0; i < NUM_CS_LINES; i++) { + if (~field & (1 << i) && !found) { + found = true; + DB_PRINT("selecting slave %d\n", i); + qemu_set_irq(s->cs_lines[i], 0); + } else { + qemu_set_irq(s->cs_lines[i], 1); + } + } +} + +static void xilinx_spips_update_ixr(XilinxSPIPS *s) +{ + /* These are set/cleared as they occur */ + s->regs[R_INTR_STATUS] &= (IXR_TX_FIFO_UNDERFLOW | IXR_RX_FIFO_OVERFLOW | + IXR_TX_FIFO_MODE_FAIL); + /* these are pure functions of fifo state, set them here */ + s->regs[R_INTR_STATUS] |= + (fifo8_is_full(&s->rx_fifo) ? IXR_RX_FIFO_FULL : 0) | + (s->rx_fifo.num >= s->regs[R_RX_THRES] ? IXR_RX_FIFO_NOT_EMPTY : 0) | + (fifo8_is_full(&s->tx_fifo) ? IXR_TX_FIFO_FULL : 0) | + (s->tx_fifo.num < s->regs[R_TX_THRES] ? IXR_TX_FIFO_NOT_FULL : 0); + /* drive external interrupt pin */ + int new_irqline = !!(s->regs[R_INTR_MASK] & s->regs[R_INTR_STATUS] & + IXR_ALL); + if (new_irqline != s->irqline) { + s->irqline = new_irqline; + qemu_set_irq(s->irq, s->irqline); + } +} + +static void xilinx_spips_reset(DeviceState *d) +{ + XilinxSPIPS *s = DO_UPCAST(XilinxSPIPS, busdev.qdev, d); + + int i; + for (i = 0; i < R_MAX; i++) { + s->regs[i] = 0; + } + + fifo8_reset(&s->rx_fifo); + fifo8_reset(&s->rx_fifo); + /* non zero resets */ + s->regs[R_CONFIG] |= MODEFAIL_GEN_EN; + s->regs[R_SLAVE_IDLE_COUNT] = 0xFF; + s->regs[R_TX_THRES] = 1; + s->regs[R_RX_THRES] = 1; + /* FIXME: move magic number definition somewhere sensible */ + s->regs[R_MOD_ID] = 0x01090106; + xilinx_spips_update_ixr(s); + xilinx_spips_update_cs_lines(s); +} + +static void xilinx_spips_flush_txfifo(XilinxSPIPS *s) +{ + for (;;) { + uint32_t r; + uint8_t value; + + if (fifo8_is_empty(&s->tx_fifo)) { + s->regs[R_INTR_STATUS] |= IXR_TX_FIFO_UNDERFLOW; + break; + } else { + value = fifo8_pop(&s->tx_fifo); + } + + r = ssi_transfer(s->spi, (uint32_t)value); + DB_PRINT("tx = %02x rx = %02x\n", value, r); + if (fifo8_is_full(&s->rx_fifo)) { + s->regs[R_INTR_STATUS] |= IXR_RX_FIFO_OVERFLOW; + DB_PRINT("rx FIFO overflow"); + } else { + fifo8_push(&s->rx_fifo, (uint8_t)r); + } + } + xilinx_spips_update_ixr(s); +} + +static uint64_t xilinx_spips_read(void *opaque, target_phys_addr_t addr, + unsigned size) +{ + XilinxSPIPS *s = opaque; + uint32_t mask = ~0; + uint32_t ret; + + addr >>= 2; + switch (addr) { + case R_CONFIG: + mask = 0x0002FFFF; + break; + case R_INTR_STATUS: + case R_INTR_MASK: + mask = IXR_ALL; + break; + case R_EN: + mask = 0x1; + break; + case R_SLAVE_IDLE_COUNT: + mask = 0xFF; + break; + case R_MOD_ID: + mask = 0x01FFFFFF; + break; + case R_INTR_EN: + case R_INTR_DIS: + case R_TX_DATA: + mask = 0; + break; + case R_RX_DATA: + ret = (uint32_t)fifo8_pop(&s->rx_fifo); + DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, ret); + xilinx_spips_update_ixr(s); + return ret; + } + DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, s->regs[addr] & mask); + return s->regs[addr] & mask; + +} + +static void xilinx_spips_write(void *opaque, target_phys_addr_t addr, + uint64_t value, unsigned size) +{ + int mask = ~0; + int man_start_com = 0; + XilinxSPIPS *s = opaque; + + DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr, (unsigned)value); + addr >>= 2; + switch (addr) { + case R_CONFIG: + mask = 0x0002FFFF; + if (value & MAN_START_COM) { + man_start_com = 1; + } + break; + case R_INTR_STATUS: + mask = IXR_ALL; + s->regs[R_INTR_STATUS] &= ~(mask & value); + goto no_reg_update; + case R_INTR_DIS: + mask = IXR_ALL; + s->regs[R_INTR_MASK] &= ~(mask & value); + goto no_reg_update; + case R_INTR_EN: + mask = IXR_ALL; + s->regs[R_INTR_MASK] |= mask & value; + goto no_reg_update; + case R_EN: + mask = 0x1; + break; + case R_SLAVE_IDLE_COUNT: + mask = 0xFF; + break; + case R_RX_DATA: + case R_INTR_MASK: + case R_MOD_ID: + mask = 0; + break; + case R_TX_DATA: + fifo8_push(&s->tx_fifo, (uint8_t)value); + goto no_reg_update; + } + s->regs[addr] = (s->regs[addr] & ~mask) | (value & mask); +no_reg_update: + if (man_start_com) { + xilinx_spips_flush_txfifo(s); + } + xilinx_spips_update_ixr(s); + xilinx_spips_update_cs_lines(s); +} + +static const MemoryRegionOps spips_ops = { + .read = xilinx_spips_read, + .write = xilinx_spips_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static int xilinx_spips_init(SysBusDevice *dev) +{ + XilinxSPIPS *s = FROM_SYSBUS(typeof(*s), dev); + int i; + + DB_PRINT("inited device model\n"); + + sysbus_init_irq(dev, &s->irq); + for (i = 0; i < NUM_CS_LINES; ++i) { + sysbus_init_irq(dev, &s->cs_lines[i]); + } + + memory_region_init_io(&s->iomem, &spips_ops, s, "spi", R_MAX*4); + sysbus_init_mmio(dev, &s->iomem); + + s->irqline = -1; + s->spi = ssi_create_bus(&dev->qdev, "spi"); + + fifo8_create(&s->rx_fifo, RXFF_A); + fifo8_create(&s->tx_fifo, TXFF_A); + + return 0; +} + +static int xilinx_spips_post_load(void *opaque, int version_id) +{ + xilinx_spips_update_ixr((XilinxSPIPS *)opaque); + xilinx_spips_update_cs_lines((XilinxSPIPS *)opaque); + return 0; +} + +static const VMStateDescription vmstate_xilinx_spips = { + .name = "xilinx_spips", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .post_load = xilinx_spips_post_load, + .fields = (VMStateField[]) { + VMSTATE_FIFO8(tx_fifo, XilinxSPIPS), + VMSTATE_FIFO8(rx_fifo, XilinxSPIPS), + VMSTATE_UINT32_ARRAY(regs, XilinxSPIPS, R_MAX), + VMSTATE_END_OF_LIST() + } +}; + +static void xilinx_spips_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); + + sdc->init = xilinx_spips_init; + dc->reset = xilinx_spips_reset; + dc->vmsd = &vmstate_xilinx_spips; +} + +static const TypeInfo xilinx_spips_info = { + .name = "xilinx,spips", + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(XilinxSPIPS), + .class_init = xilinx_spips_class_init, +}; + +static void xilinx_spips_register_types(void) +{ + type_register_static(&xilinx_spips_info); +} + +type_init(xilinx_spips_register_types) From 559d489f137a696920d89ad2e3225b869c52b745 Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Fri, 3 Aug 2012 16:08:48 +1000 Subject: [PATCH 0850/2270] xilinx_zynq: Added SPI controllers + flashes Added the two SPI controllers to the zynq machine model. Attached two SPI flash devices to each controller. Signed-off-by: Peter A. G. Crosthwaite Acked-by: Peter Maydell --- hw/xilinx_zynq.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c index 7e6c27359e..fd46ba2527 100644 --- a/hw/xilinx_zynq.c +++ b/hw/xilinx_zynq.c @@ -24,6 +24,9 @@ #include "flash.h" #include "blockdev.h" #include "loader.h" +#include "ssi.h" + +#define NUM_SPI_FLASHES 4 #define FLASH_SIZE (64 * 1024 * 1024) #define FLASH_SECTOR_SIZE (128 * 1024) @@ -46,6 +49,34 @@ static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq) sysbus_connect_irq(s, 0, irq); } +static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq) +{ + DeviceState *dev; + SysBusDevice *busdev; + SSIBus *spi; + int i; + + dev = qdev_create(NULL, "xilinx,spips"); + qdev_init_nofail(dev); + busdev = sysbus_from_qdev(dev); + sysbus_mmio_map(busdev, 0, base_addr); + sysbus_connect_irq(busdev, 0, irq); + + spi = (SSIBus *)qdev_get_child_bus(dev, "spi"); + + for (i = 0; i < NUM_SPI_FLASHES; ++i) { + qemu_irq cs_line; + + dev = ssi_create_slave_no_init(spi, "m25p80"); + qdev_prop_set_string(dev, "partname", "n25q128"); + qdev_init_nofail(dev); + + cs_line = qdev_get_gpio_in(dev, 0); + sysbus_connect_irq(busdev, i+1, cs_line); + } + +} + static void zynq_init(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) @@ -113,6 +144,9 @@ static void zynq_init(ram_addr_t ram_size, const char *boot_device, pic[n] = qdev_get_gpio_in(dev, n); } + zynq_init_spi_flashes(0xE0006000, pic[58-IRQ_OFFSET]); + zynq_init_spi_flashes(0xE0007000, pic[81-IRQ_OFFSET]); + sysbus_create_simple("cadence_uart", 0xE0000000, pic[59-IRQ_OFFSET]); sysbus_create_simple("cadence_uart", 0xE0001000, pic[82-IRQ_OFFSET]); From fcb5629d3eb208d84c0fe9aa1ef64a6af7de0139 Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Mon, 6 Aug 2012 11:38:19 +1000 Subject: [PATCH 0851/2270] MAINTAINERS: Added maintainerships for SSI Added maintainership for SSI, M25P80 and the Xilinx SPI controllers. Signed-off-by: Peter A. G. Crosthwaite Acked-by: Peter Maydell --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 78d4ff227e..f1f925007e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -268,6 +268,7 @@ S: Maintained F: hw/xilinx_zynq.c F: hw/zynq_slcr.c F: hw/cadence_* +F: hw/xilinx_spips.c CRIS Machines ------------- @@ -517,6 +518,12 @@ M: Paul Brook S: Odd Fixes F: hw/lsi53c895a.c +SSI +M: Peter Crosthwaite +S: Maintained +F: hw/ssi.* +F: hw/m25p80.c + USB M: Gerd Hoffmann S: Maintained @@ -565,6 +572,7 @@ F: hw/xilinx_intc.c F: hw/xilinx_ethlite.c F: hw/xilinx_timer.c F: hw/xilinx.h +F: hw/xilinx_spi.c Subsystems ---------- From b4ae3cfa57b8c1bdbbd7b7d420971e9171203ade Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Mon, 1 Oct 2012 12:34:37 +1000 Subject: [PATCH 0852/2270] ssi: Add slave autoconnect helper Added helper function to automatically connect SPI slaves based on the QOM child nodes of a device. A SSI master device can call this routine to automatically hook-up all child nodes to its SPI bus. Signed-off-by: Peter Crosthwaite Acked-by: Peter Maydell --- hw/ssi.c | 33 +++++++++++++++++++++++++++++++++ hw/ssi.h | 4 ++++ hw/xilinx_spi.c | 6 ++++-- hw/xilinx_spips.c | 4 +++- 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/hw/ssi.c b/hw/ssi.c index c47419d57f..2b56357153 100644 --- a/hw/ssi.c +++ b/hw/ssi.c @@ -139,3 +139,36 @@ static void ssi_slave_register_types(void) } type_init(ssi_slave_register_types) + +typedef struct SSIAutoConnectArg { + qemu_irq **cs_linep; + SSIBus *bus; +} SSIAutoConnectArg; + +static int ssi_auto_connect_slave(Object *child, void *opaque) +{ + SSIAutoConnectArg *arg = opaque; + SSISlave *dev = (SSISlave *)object_dynamic_cast(child, TYPE_SSI_SLAVE); + qemu_irq cs_line; + + if (!dev) { + return 0; + } + + cs_line = qdev_get_gpio_in(DEVICE(dev), 0); + qdev_set_parent_bus(DEVICE(dev), &arg->bus->qbus); + **arg->cs_linep = cs_line; + (*arg->cs_linep)++; + return 0; +} + +void ssi_auto_connect_slaves(DeviceState *parent, qemu_irq *cs_line, + SSIBus *bus) +{ + SSIAutoConnectArg arg = { + .cs_linep = &cs_line, + .bus = bus + }; + + object_child_foreach(OBJECT(parent), ssi_auto_connect_slave, &arg); +} diff --git a/hw/ssi.h b/hw/ssi.h index 2bde9f5b44..a05d60beb4 100644 --- a/hw/ssi.h +++ b/hw/ssi.h @@ -83,6 +83,10 @@ SSIBus *ssi_create_bus(DeviceState *parent, const char *name); uint32_t ssi_transfer(SSIBus *bus, uint32_t val); +/* Automatically connect all children nodes a spi controller as slaves */ +void ssi_auto_connect_slaves(DeviceState *parent, qemu_irq *cs_lines, + SSIBus *bus); + /* max111x.c */ void max111x_set_input(DeviceState *dev, int line, uint8_t value); diff --git a/hw/xilinx_spi.c b/hw/xilinx_spi.c index 7db47877e2..5cdf967c20 100644 --- a/hw/xilinx_spi.c +++ b/hw/xilinx_spi.c @@ -320,8 +320,12 @@ static int xilinx_spi_init(SysBusDevice *dev) XilinxSPI *s = FROM_SYSBUS(typeof(*s), dev); DB_PRINT("\n"); + + s->spi = ssi_create_bus(&dev->qdev, "spi"); + sysbus_init_irq(dev, &s->irq); s->cs_lines = g_new(qemu_irq, s->num_cs); + ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi); for (i = 0; i < s->num_cs; ++i) { sysbus_init_irq(dev, &s->cs_lines[i]); } @@ -331,8 +335,6 @@ static int xilinx_spi_init(SysBusDevice *dev) s->irqline = -1; - s->spi = ssi_create_bus(&dev->qdev, "spi"); - fifo8_create(&s->tx_fifo, FIFO_CAPACITY); fifo8_create(&s->rx_fifo, FIFO_CAPACITY); diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c index a886c5d311..f64a7828fe 100644 --- a/hw/xilinx_spips.c +++ b/hw/xilinx_spips.c @@ -289,6 +289,9 @@ static int xilinx_spips_init(SysBusDevice *dev) DB_PRINT("inited device model\n"); + s->spi = ssi_create_bus(&dev->qdev, "spi"); + + ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi); sysbus_init_irq(dev, &s->irq); for (i = 0; i < NUM_CS_LINES; ++i) { sysbus_init_irq(dev, &s->cs_lines[i]); @@ -298,7 +301,6 @@ static int xilinx_spips_init(SysBusDevice *dev) sysbus_init_mmio(dev, &s->iomem); s->irqline = -1; - s->spi = ssi_create_bus(&dev->qdev, "spi"); fifo8_create(&s->rx_fifo, RXFF_A); fifo8_create(&s->tx_fifo, TXFF_A); From dbbf01958e777b6f03fc4ab425879f84800b9cda Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 27 Sep 2012 17:25:44 +0200 Subject: [PATCH 0853/2270] usb-redir: Change usbredir_open_chardev into usbredir_create_parser As we need to create the parser at more places. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index b10241a139..5e0f98daf2 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -862,15 +862,11 @@ static void usbredir_chardev_close_bh(void *opaque) } } -static void usbredir_chardev_open(USBRedirDevice *dev) +static void usbredir_create_parser(USBRedirDevice *dev) { uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, }; int flags = 0; - /* Make sure any pending closes are handled (no-op if none pending) */ - usbredir_chardev_close_bh(dev); - qemu_bh_cancel(dev->chardev_close_bh); - DPRINTF("creating usbredirparser\n"); dev->parser = qemu_oom_check(usbredirparser_create()); @@ -982,7 +978,10 @@ static void usbredir_chardev_event(void *opaque, int event) switch (event) { case CHR_EVENT_OPENED: DPRINTF("chardev open\n"); - usbredir_chardev_open(dev); + /* Make sure any pending closes are handled (no-op if none pending) */ + usbredir_chardev_close_bh(dev); + qemu_bh_cancel(dev->chardev_close_bh); + usbredir_create_parser(dev); break; case CHR_EVENT_CLOSED: DPRINTF("chardev close\n"); From 5c16f767813602fbf57414e2a11057e252e0d422 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 27 Sep 2012 17:25:45 +0200 Subject: [PATCH 0854/2270] usb-redir: Don't make migration fail in none seamless case Instead simple disconnect the device like host redirection does on migration. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 5e0f98daf2..2283565b0c 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1614,12 +1614,17 @@ static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused) } /* - * Our chardev should be open already at this point, otherwise - * the usbredir channel will be broken (ie spice without seamless) + * If our chardev is not open already at this point the usbredir connection + * has been broken (non seamless migration, or restore from disk). + * + * In this case create a temporary parser to receive the migration data, + * and schedule the close_bh to report the device as disconnected to the + * guest and to destroy the parser again. */ if (dev->parser == NULL) { - ERROR("get_parser called with closed chardev, failing migration\n"); - return -1; + WARNING("usb-redir connection broken during migration\n"); + usbredir_create_parser(dev); + qemu_bh_schedule(dev->chardev_close_bh); } data = g_malloc(len); From 883bca776daa43111e9c39008f0038f7c62ae723 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 10 Oct 2012 15:50:36 +0200 Subject: [PATCH 0855/2270] uhci: Raise interrupt when requested even for non active tds According to the spec we must raise an interrupt when one is requested even for non active tds. Linux depends on this, for bulk transfers it runs an inactivity timer to work around a bug in early uhci revisions, when we take longer then 200 ms to process a packet, this timer goes of, and as part of the handling Linux then unlinks the qh, and relinks it after the frindex has increased by atleast 1, the problem is Linux only checks for the frindex increases on an interrupt, and we don't send that, causing the qh to go inactive for more then 32 frames, at which point we consider the packet cancelled. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index cdc8bc3fba..c2f08e3735 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -826,8 +826,16 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, USBEndpoint *ep; /* Is active ? */ - if (!(td->ctrl & TD_CTRL_ACTIVE)) + if (!(td->ctrl & TD_CTRL_ACTIVE)) { + /* + * ehci11d spec page 22: "Even if the Active bit in the TD is already + * cleared when the TD is fetched ... an IOC interrupt is generated" + */ + if (td->ctrl & TD_CTRL_IOC) { + *int_mask |= 0x01; + } return TD_RESULT_NEXT_QH; + } async = uhci_async_find_td(s, addr, td); if (async) { From 1e14afef00493bd375264dcea5fb8c7718b23355 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 5 Oct 2012 17:33:22 +0100 Subject: [PATCH 0856/2270] configure: Tidy up remnants of non-64-bit physaddrs Tidy up some remnants of code to support non-64-bit physaddrs which were accidentally omitted from commit 4be403c8. Signed-off-by: Peter Maydell Signed-off-by: Stefan Hajnoczi --- configure | 2 -- 1 file changed, 2 deletions(-) diff --git a/configure b/configure index c4a78376b6..f1c56eb464 100755 --- a/configure +++ b/configure @@ -3733,7 +3733,6 @@ case "$target_arch2" in ;; x86_64) TARGET_BASE_ARCH=i386 - target_phys_bits=64 target_long_alignment=8 ;; alpha) @@ -3836,7 +3835,6 @@ case "$target_arch2" in target_long_alignment=8 ;; unicore32) - target_phys_bits=32 ;; xtensa|xtensaeb) TARGET_ARCH=xtensa From 2f5368017f8a0c00e982c3e315acb332a0907792 Mon Sep 17 00:00:00 2001 From: MORITA Kazutaka Date: Sun, 7 Oct 2012 01:57:14 +0900 Subject: [PATCH 0857/2270] sheepdog: use bool for boolean variables This improves readability. Signed-off-by: MORITA Kazutaka Signed-off-by: Stefan Hajnoczi --- block/sheepdog.c | 70 ++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/block/sheepdog.c b/block/sheepdog.c index f35ff5bbe1..93061744d6 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -201,12 +201,12 @@ static inline uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval) return hval; } -static inline int is_data_obj_writable(SheepdogInode *inode, unsigned int idx) +static inline bool is_data_obj_writable(SheepdogInode *inode, unsigned int idx) { return inode->vdi_id == inode->data_vdi_id[idx]; } -static inline int is_data_obj(uint64_t oid) +static inline bool is_data_obj(uint64_t oid) { return !(VDI_BIT & oid); } @@ -231,7 +231,7 @@ static inline uint64_t vid_to_data_oid(uint32_t vid, uint32_t idx) return ((uint64_t)vid << VDI_SPACE_SHIFT) | idx; } -static inline int is_snapshot(struct SheepdogInode *inode) +static inline bool is_snapshot(struct SheepdogInode *inode) { return !!inode->snap_ctime; } @@ -281,7 +281,7 @@ struct SheepdogAIOCB { Coroutine *coroutine; void (*aio_done_func)(SheepdogAIOCB *); - int canceled; + bool canceled; int nr_pending; }; @@ -292,8 +292,8 @@ typedef struct BDRVSheepdogState { uint32_t max_dirty_data_idx; char name[SD_MAX_VDI_LEN]; - int is_snapshot; - uint8_t cache_enabled; + bool is_snapshot; + bool cache_enabled; char *addr; char *port; @@ -417,7 +417,7 @@ static void sd_aio_cancel(BlockDriverAIOCB *blockacb) */ acb->ret = -EIO; qemu_coroutine_enter(acb->coroutine, NULL); - acb->canceled = 1; + acb->canceled = true; } static AIOPool sd_aio_pool = { @@ -439,7 +439,7 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov, acb->nb_sectors = nb_sectors; acb->aio_done_func = NULL; - acb->canceled = 0; + acb->canceled = false; acb->coroutine = qemu_coroutine_self(); acb->ret = 0; acb->nr_pending = 0; @@ -613,7 +613,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data, } static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, - struct iovec *iov, int niov, int create, + struct iovec *iov, int niov, bool create, enum AIOCBState aiocb_type); @@ -646,7 +646,7 @@ static void coroutine_fn send_pending_req(BDRVSheepdogState *s, uint64_t oid) QLIST_REMOVE(aio_req, aio_siblings); QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings); ret = add_aio_request(s, aio_req, acb->qiov->iov, - acb->qiov->niov, 0, acb->aiocb_type); + acb->qiov->niov, false, acb->aiocb_type); if (ret < 0) { error_report("add_aio_request is failed"); free_aio_req(s, aio_req); @@ -943,7 +943,7 @@ out: } static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, - struct iovec *iov, int niov, int create, + struct iovec *iov, int niov, bool create, enum AIOCBState aiocb_type) { int nr_copies = s->inode.nr_copies; @@ -1022,7 +1022,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, static int read_write_object(int fd, char *buf, uint64_t oid, int copies, unsigned int datalen, uint64_t offset, - int write, int create, uint8_t cache) + bool write, bool create, bool cache) { SheepdogObjReq hdr; SheepdogObjRsp *rsp = (SheepdogObjRsp *)&hdr; @@ -1071,18 +1071,18 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies, } static int read_object(int fd, char *buf, uint64_t oid, int copies, - unsigned int datalen, uint64_t offset, uint8_t cache) + unsigned int datalen, uint64_t offset, bool cache) { - return read_write_object(fd, buf, oid, copies, datalen, offset, 0, 0, - cache); + return read_write_object(fd, buf, oid, copies, datalen, offset, false, + false, cache); } static int write_object(int fd, char *buf, uint64_t oid, int copies, - unsigned int datalen, uint64_t offset, int create, - uint8_t cache) + unsigned int datalen, uint64_t offset, bool create, + bool cache) { - return read_write_object(fd, buf, oid, copies, datalen, offset, 1, create, - cache); + return read_write_object(fd, buf, oid, copies, datalen, offset, true, + create, cache); } static int sd_open(BlockDriverState *bs, const char *filename, int flags) @@ -1117,7 +1117,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags) goto out; } - s->cache_enabled = 1; + s->cache_enabled = true; s->flush_fd = connect_to_sdog(s->addr, s->port); if (s->flush_fd < 0) { error_report("failed to connect"); @@ -1127,7 +1127,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags) if (snapid || tag[0] != '\0') { dprintf("%" PRIx32 " snapshot inode was open.\n", vid); - s->is_snapshot = 1; + s->is_snapshot = true; } fd = connect_to_sdog(s->addr, s->port); @@ -1270,7 +1270,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) BDRVSheepdogState *s; char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN]; uint32_t snapid; - int prealloc = 0; + bool prealloc = false; const char *vdiname; s = g_malloc0(sizeof(BDRVSheepdogState)); @@ -1292,9 +1292,9 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) backing_file = options->value.s; } else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) { if (!options->value.s || !strcmp(options->value.s, "off")) { - prealloc = 0; + prealloc = false; } else if (!strcmp(options->value.s, "full")) { - prealloc = 1; + prealloc = true; } else { error_report("Invalid preallocation mode: '%s'", options->value.s); @@ -1422,7 +1422,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset) datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id); s->inode.vdi_size = offset; ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id), - s->inode.nr_copies, datalen, 0, 0, s->cache_enabled); + s->inode.nr_copies, datalen, 0, false, s->cache_enabled); close(fd); if (ret < 0) { @@ -1461,7 +1461,7 @@ static void coroutine_fn sd_write_done(SheepdogAIOCB *acb) aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id), data_len, offset, 0, 0, offset); QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings); - ret = add_aio_request(s, aio_req, &iov, 1, 0, AIOCB_WRITE_UDATA); + ret = add_aio_request(s, aio_req, &iov, 1, false, AIOCB_WRITE_UDATA); if (ret) { free_aio_req(s, aio_req); acb->ret = -EIO; @@ -1515,7 +1515,7 @@ static int sd_create_branch(BDRVSheepdogState *s) memcpy(&s->inode, buf, sizeof(s->inode)); - s->is_snapshot = 0; + s->is_snapshot = false; ret = 0; dprintf("%" PRIx32 " was newly created.\n", s->inode.vdi_id); @@ -1570,7 +1570,7 @@ static int coroutine_fn sd_co_rw_vector(void *p) while (done != total) { uint8_t flags = 0; uint64_t old_oid = 0; - int create = 0; + bool create = false; oid = vid_to_data_oid(inode->data_vdi_id[idx], idx); @@ -1585,10 +1585,10 @@ static int coroutine_fn sd_co_rw_vector(void *p) break; case AIOCB_WRITE_UDATA: if (!inode->data_vdi_id[idx]) { - create = 1; + create = true; } else if (!is_data_obj_writable(inode, idx)) { /* Copy-On-Write */ - create = 1; + create = true; old_oid = oid; flags = SD_FLAG_CMD_COW; } @@ -1722,7 +1722,7 @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs) if (rsp->result == SD_RES_INVALID_PARMS) { dprintf("disable write cache since the server doesn't support it\n"); - s->cache_enabled = 0; + s->cache_enabled = false; closesocket(s->flush_fd); return 0; } @@ -1773,7 +1773,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) } ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id), - s->inode.nr_copies, datalen, 0, 0, s->cache_enabled); + s->inode.nr_copies, datalen, 0, false, s->cache_enabled); if (ret < 0) { error_report("failed to write snapshot's inode."); goto cleanup; @@ -1860,7 +1860,7 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) goto out; } - s->is_snapshot = 1; + s->is_snapshot = true; g_free(buf); g_free(old_s); @@ -1978,8 +1978,8 @@ out: static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data, int64_t pos, int size, int load) { - int fd, create; - int ret = 0, remaining = size; + bool create; + int fd, ret = 0, remaining = size; unsigned int data_len; uint64_t vmstate_oid; uint32_t vdi_index; From 417b0b88904fe1dd8c41bff8092dfbab0134d9cb Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 10 Oct 2012 14:30:58 +0200 Subject: [PATCH 0858/2270] vnc: fix "info vnc" with "-vnc ..., reverse=on" When reverse connection is in use, there is no active VNC server socket. Because of this, getsockopt(-1, ...) is attempted and the following error is emitted: $ socat TCP-LISTEN:5900,reuseaddr TCP-LISTEN:5901,reuseaddr & $ x86_64-softmmu/qemu-system-x86_64 -vnc localhost:5900,reverse -monitor stdio QEMU 1.2.50 monitor - type 'help' for more information (qemu) info vnc An undefined error has occurred Because however the host, family, service and auth fields are optional, we can just exit if there is no active server socket. $ x86_64-softmmu/qemu-system-x86_64 -vnc localhost:5900,reverse -monitor stdio QEMU 1.2.50 monitor - type 'help' for more information (qemu) info vnc Server: Client: address: 127.0.0.1:5900 x509_dname: none username: none Signed-off-by: Paolo Bonzini Signed-off-by: Stefan Hajnoczi --- ui/vnc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/vnc.c b/ui/vnc.c index 01b2dafea2..33e6386a6e 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -372,6 +372,10 @@ VncInfo *qmp_query_vnc(Error **errp) } } + if (vnc_display->lsock == -1) { + return info; + } + if (getsockname(vnc_display->lsock, (struct sockaddr *)&sa, &salen) == -1) { error_set(errp, QERR_UNDEFINED_ERROR); From 884285bf646d93e9dfa4a605bca9f8dc5280b23d Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Fri, 12 Oct 2012 11:54:37 +0100 Subject: [PATCH 0859/2270] cadence_ttc: Fix 'clear on read' behavior A missing call to qemu_set_irq() when reading the IRQ register required SW to write to the IRQ register to acknowledge an interrupt. With this patch the behavior is fixed: - Reading the interrupt register clears it and updates the timers interrupt status - Writes to the interrupt register are ignored Signed-off-by: Soren Brinkmann Signed-off-by: Peter Crosthwaite Signed-off-by: Peter Maydell --- hw/cadence_ttc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/cadence_ttc.c b/hw/cadence_ttc.c index dd02f86eb9..77b6976eda 100644 --- a/hw/cadence_ttc.c +++ b/hw/cadence_ttc.c @@ -274,6 +274,7 @@ static uint32_t cadence_ttc_read_imp(void *opaque, target_phys_addr_t offset) /* cleared after read */ value = s->reg_intr; s->reg_intr = 0; + cadence_timer_update(s); return value; case 0x60: /* interrupt enable */ @@ -355,7 +356,6 @@ static void cadence_ttc_write(void *opaque, target_phys_addr_t offset, case 0x54: /* interrupt register */ case 0x58: case 0x5c: - s->reg_intr &= (~value & 0xfff); break; case 0x60: /* interrupt enable */ From 9ab1b6053f03d58ba8e7accc8f19c882fbffb66f Mon Sep 17 00:00:00 2001 From: Evgeny Voevodin Date: Fri, 12 Oct 2012 11:54:37 +0100 Subject: [PATCH 0860/2270] hw/arm_gic.c: Fix improper DPRINTF output. s->cpu_enabled is an array, so s->cpu_enabled ? "En" : "Dis" returns "En" always. We should use s->cpu_enabled[cpu] here. Signed-off-by: Evgeny Voevodin Signed-off-by: Peter Maydell --- hw/arm_gic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/arm_gic.c b/hw/arm_gic.c index 55871fad19..4024daeea4 100644 --- a/hw/arm_gic.c +++ b/hw/arm_gic.c @@ -566,7 +566,7 @@ static void gic_cpu_write(gic_state *s, int cpu, int offset, uint32_t value) switch (offset) { case 0x00: /* Control */ s->cpu_enabled[cpu] = (value & 1); - DPRINTF("CPU %d %sabled\n", cpu, s->cpu_enabled ? "En" : "Dis"); + DPRINTF("CPU %d %sabled\n", cpu, s->cpu_enabled[cpu] ? "En" : "Dis"); break; case 0x04: /* Priority mask */ s->priority_mask[cpu] = (value & 0xff); From ba4906a9b64e165a958e12f6208ca834dc7a36dc Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 12 Oct 2012 11:54:38 +0100 Subject: [PATCH 0861/2270] hw/ds1338: Fix mishandling of register pointer Correct several deficiencies in the handling of the register pointer: * it should wrap around after 0x3f, not 0xff * guard against the caller handing us an out of range pointer (on h/w this can never happen, because only a 7 bit value is transferred over the I2C bus) * there was confusion over whether nvram[] holds only the 56 bytes of guest-accessible NVRAM, or also the secondary registers which hold the value of the clock captured at the start of a multibyte read. Correct to consistently be the latter, by fixing the array size and the offset used for NVRAM writes. * ds1338_send was attempting to use 'data' as both the data and the register offset simultaneously, which meant that writes to any register were broken; fix to use the register pointer. Signed-off-by: Peter Maydell --- hw/ds1338.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/hw/ds1338.c b/hw/ds1338.c index d590d9c007..be68140ae2 100644 --- a/hw/ds1338.c +++ b/hw/ds1338.c @@ -12,11 +12,16 @@ #include "i2c.h" +/* Size of NVRAM including both the user-accessible area and the + * secondary register area. + */ +#define NVRAM_SIZE 64 + typedef struct { I2CSlave i2c; time_t offset; struct tm now; - uint8_t nvram[56]; + uint8_t nvram[NVRAM_SIZE]; int ptr; int addr_byte; } DS1338State; @@ -57,7 +62,7 @@ static int ds1338_recv(I2CSlave *i2c) uint8_t res; res = s->nvram[s->ptr]; - s->ptr = (s->ptr + 1) & 0xff; + s->ptr = (s->ptr + 1) & (NVRAM_SIZE - 1); return res; } @@ -65,14 +70,13 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data) { DS1338State *s = FROM_I2C_SLAVE(DS1338State, i2c); if (s->addr_byte) { - s->ptr = data; + s->ptr = data & (NVRAM_SIZE - 1); s->addr_byte = 0; return 0; } - s->nvram[s->ptr - 8] = data; - if (data < 8) { + if (s->ptr < 8) { qemu_get_timedate(&s->now, s->offset); - switch(data) { + switch(s->ptr) { case 0: /* TODO: Implement CH (stop) bit. */ s->now.tm_sec = from_bcd(data & 0x7f); @@ -109,8 +113,10 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data) break; } s->offset = qemu_timedate_diff(&s->now); + } else { + s->nvram[s->ptr] = data; } - s->ptr = (s->ptr + 1) & 0xff; + s->ptr = (s->ptr + 1) & (NVRAM_SIZE - 1); return 0; } From 35b87a861394ed088c4db3b7ba9a67d8bb2b289e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 12 Oct 2012 11:54:38 +0100 Subject: [PATCH 0862/2270] hw/ds1338: Recapture current time when register pointer wraps around The DS1338 datasheet documents that the current time is captured into the secondary registers when the register pointer wraps round to zero as well as at a START condition. Implement this. Signed-off-by: Peter Maydell --- hw/ds1338.c | 59 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/hw/ds1338.c b/hw/ds1338.c index be68140ae2..842d2de14d 100644 --- a/hw/ds1338.c +++ b/hw/ds1338.c @@ -26,27 +26,52 @@ typedef struct { int addr_byte; } DS1338State; +static void capture_current_time(DS1338State *s) +{ + /* Capture the current time into the secondary registers + * which will be actually read by the data transfer operation. + */ + qemu_get_timedate(&s->now, s->offset); + s->nvram[0] = to_bcd(s->now.tm_sec); + s->nvram[1] = to_bcd(s->now.tm_min); + if (s->nvram[2] & 0x40) { + s->nvram[2] = (to_bcd((s->now.tm_hour % 12)) + 1) | 0x40; + if (s->now.tm_hour >= 12) { + s->nvram[2] |= 0x20; + } + } else { + s->nvram[2] = to_bcd(s->now.tm_hour); + } + s->nvram[3] = to_bcd(s->now.tm_wday) + 1; + s->nvram[4] = to_bcd(s->now.tm_mday); + s->nvram[5] = to_bcd(s->now.tm_mon) + 1; + s->nvram[6] = to_bcd(s->now.tm_year - 100); +} + +static void inc_regptr(DS1338State *s) +{ + /* The register pointer wraps around after 0x3F; wraparound + * causes the current time/date to be retransferred into + * the secondary registers. + */ + s->ptr = (s->ptr + 1) & (NVRAM_SIZE - 1); + if (!s->ptr) { + capture_current_time(s); + } +} + static void ds1338_event(I2CSlave *i2c, enum i2c_event event) { DS1338State *s = FROM_I2C_SLAVE(DS1338State, i2c); switch (event) { case I2C_START_RECV: - qemu_get_timedate(&s->now, s->offset); - s->nvram[0] = to_bcd(s->now.tm_sec); - s->nvram[1] = to_bcd(s->now.tm_min); - if (s->nvram[2] & 0x40) { - s->nvram[2] = (to_bcd((s->now.tm_hour % 12)) + 1) | 0x40; - if (s->now.tm_hour >= 12) { - s->nvram[2] |= 0x20; - } - } else { - s->nvram[2] = to_bcd(s->now.tm_hour); - } - s->nvram[3] = to_bcd(s->now.tm_wday) + 1; - s->nvram[4] = to_bcd(s->now.tm_mday); - s->nvram[5] = to_bcd(s->now.tm_mon) + 1; - s->nvram[6] = to_bcd(s->now.tm_year - 100); + /* In h/w, capture happens on any START condition, not just a + * START_RECV, but there is no need to actually capture on + * START_SEND, because the guest can't get at that data + * without going through a START_RECV which would overwrite it. + */ + capture_current_time(s); break; case I2C_START_SEND: s->addr_byte = 1; @@ -62,7 +87,7 @@ static int ds1338_recv(I2CSlave *i2c) uint8_t res; res = s->nvram[s->ptr]; - s->ptr = (s->ptr + 1) & (NVRAM_SIZE - 1); + inc_regptr(s); return res; } @@ -116,7 +141,7 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data) } else { s->nvram[s->ptr] = data; } - s->ptr = (s->ptr + 1) & (NVRAM_SIZE - 1); + inc_regptr(s); return 0; } From 7f7fd0f2e4d6b4f2ec137cda67f6c9a140668ea3 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 12 Oct 2012 11:54:38 +0100 Subject: [PATCH 0863/2270] hw/ds1338: Remove 'now' field from state struct The 'struct tm now' field in the state structure is in fact only ever used as a temporary (the actual RTC state is held in 'offset'). Remove it from the state structure in favour of using local variables to avoid confusion about whether it needs to be saved on migration. Signed-off-by: Peter Maydell --- hw/ds1338.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/hw/ds1338.c b/hw/ds1338.c index 842d2de14d..16aba4b158 100644 --- a/hw/ds1338.c +++ b/hw/ds1338.c @@ -20,7 +20,6 @@ typedef struct { I2CSlave i2c; time_t offset; - struct tm now; uint8_t nvram[NVRAM_SIZE]; int ptr; int addr_byte; @@ -31,21 +30,22 @@ static void capture_current_time(DS1338State *s) /* Capture the current time into the secondary registers * which will be actually read by the data transfer operation. */ - qemu_get_timedate(&s->now, s->offset); - s->nvram[0] = to_bcd(s->now.tm_sec); - s->nvram[1] = to_bcd(s->now.tm_min); + struct tm now; + qemu_get_timedate(&now, s->offset); + s->nvram[0] = to_bcd(now.tm_sec); + s->nvram[1] = to_bcd(now.tm_min); if (s->nvram[2] & 0x40) { - s->nvram[2] = (to_bcd((s->now.tm_hour % 12)) + 1) | 0x40; - if (s->now.tm_hour >= 12) { + s->nvram[2] = (to_bcd((now.tm_hour % 12)) + 1) | 0x40; + if (now.tm_hour >= 12) { s->nvram[2] |= 0x20; } } else { - s->nvram[2] = to_bcd(s->now.tm_hour); + s->nvram[2] = to_bcd(now.tm_hour); } - s->nvram[3] = to_bcd(s->now.tm_wday) + 1; - s->nvram[4] = to_bcd(s->now.tm_mday); - s->nvram[5] = to_bcd(s->now.tm_mon) + 1; - s->nvram[6] = to_bcd(s->now.tm_year - 100); + s->nvram[3] = to_bcd(now.tm_wday) + 1; + s->nvram[4] = to_bcd(now.tm_mday); + s->nvram[5] = to_bcd(now.tm_mon) + 1; + s->nvram[6] = to_bcd(now.tm_year - 100); } static void inc_regptr(DS1338State *s) @@ -100,14 +100,15 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data) return 0; } if (s->ptr < 8) { - qemu_get_timedate(&s->now, s->offset); + struct tm now; + qemu_get_timedate(&now, s->offset); switch(s->ptr) { case 0: /* TODO: Implement CH (stop) bit. */ - s->now.tm_sec = from_bcd(data & 0x7f); + now.tm_sec = from_bcd(data & 0x7f); break; case 1: - s->now.tm_min = from_bcd(data & 0x7f); + now.tm_min = from_bcd(data & 0x7f); break; case 2: if (data & 0x40) { @@ -119,25 +120,25 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data) } else { data = from_bcd(data); } - s->now.tm_hour = data; + now.tm_hour = data; break; case 3: - s->now.tm_wday = from_bcd(data & 7) - 1; + now.tm_wday = from_bcd(data & 7) - 1; break; case 4: - s->now.tm_mday = from_bcd(data & 0x3f); + now.tm_mday = from_bcd(data & 0x3f); break; case 5: - s->now.tm_mon = from_bcd(data & 0x1f) - 1; + now.tm_mon = from_bcd(data & 0x1f) - 1; break; case 6: - s->now.tm_year = from_bcd(data) + 100; + now.tm_year = from_bcd(data) + 100; break; case 7: /* Control register. Currently ignored. */ break; } - s->offset = qemu_timedate_diff(&s->now); + s->offset = qemu_timedate_diff(&now); } else { s->nvram[s->ptr] = data; } From f4741402ab8afe9014b6a54aed4cb0423041dbcb Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 12 Oct 2012 11:54:38 +0100 Subject: [PATCH 0864/2270] hw/ds1338: Implement state save/restore Implement state save/restore for the DS1338. This requires the usual minor adjustment of types in the state struct to get fixed-width ones with vmstate macros. Signed-off-by: Peter Maydell --- hw/ds1338.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/hw/ds1338.c b/hw/ds1338.c index 16aba4b158..b576d56438 100644 --- a/hw/ds1338.c +++ b/hw/ds1338.c @@ -19,12 +19,27 @@ typedef struct { I2CSlave i2c; - time_t offset; + int64_t offset; uint8_t nvram[NVRAM_SIZE]; - int ptr; - int addr_byte; + int32_t ptr; + bool addr_byte; } DS1338State; +static const VMStateDescription vmstate_ds1338 = { + .name = "ds1338", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_I2C_SLAVE(i2c, DS1338State), + VMSTATE_INT64(offset, DS1338State), + VMSTATE_UINT8_ARRAY(nvram, DS1338State, NVRAM_SIZE), + VMSTATE_INT32(ptr, DS1338State), + VMSTATE_BOOL(addr_byte, DS1338State), + VMSTATE_END_OF_LIST() + } +}; + static void capture_current_time(DS1338State *s) { /* Capture the current time into the secondary registers @@ -74,7 +89,7 @@ static void ds1338_event(I2CSlave *i2c, enum i2c_event event) capture_current_time(s); break; case I2C_START_SEND: - s->addr_byte = 1; + s->addr_byte = true; break; default: break; @@ -96,7 +111,7 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data) DS1338State *s = FROM_I2C_SLAVE(DS1338State, i2c); if (s->addr_byte) { s->ptr = data & (NVRAM_SIZE - 1); - s->addr_byte = 0; + s->addr_byte = false; return 0; } if (s->ptr < 8) { @@ -153,12 +168,14 @@ static int ds1338_init(I2CSlave *i2c) static void ds1338_class_init(ObjectClass *klass, void *data) { + DeviceClass *dc = DEVICE_CLASS(klass); I2CSlaveClass *k = I2C_SLAVE_CLASS(klass); k->init = ds1338_init; k->event = ds1338_event; k->recv = ds1338_recv; k->send = ds1338_send; + dc->vmsd = &vmstate_ds1338; } static TypeInfo ds1338_info = { From 853e65e0b45403477c8a89afdb4c0abd4c3f97da Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Fri, 12 Oct 2012 11:54:39 +0100 Subject: [PATCH 0865/2270] versatilepb: add gpio pl061 support Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Peter Maydell --- hw/versatilepb.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/versatilepb.c b/hw/versatilepb.c index b3f8077146..7b1b0256aa 100644 --- a/hw/versatilepb.c +++ b/hw/versatilepb.c @@ -266,6 +266,11 @@ static void versatile_init(ram_addr_t ram_size, sysbus_create_simple("sp804", 0x101e2000, pic[4]); sysbus_create_simple("sp804", 0x101e3000, pic[5]); + sysbus_create_simple("pl061", 0x101e4000, pic[6]); + sysbus_create_simple("pl061", 0x101e5000, pic[7]); + sysbus_create_simple("pl061", 0x101e6000, pic[8]); + sysbus_create_simple("pl061", 0x101e7000, pic[9]); + /* The versatile/PB actually has a modified Color LCD controller that includes hardware cursor support from the PL111. */ dev = sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]); From fa2ddcb4f5f33c07c68cec67615c88a98fab02de Mon Sep 17 00:00:00 2001 From: "Peter A. G. Crosthwaite" Date: Fri, 12 Oct 2012 11:54:39 +0100 Subject: [PATCH 0866/2270] zynq_slcr: Fixed ResetValues enum There is a gap in the reset region of the address space at offset 0x208. This throws out all these enum values by one when translating them to address offsets. Fixed by putting the corresponding gap in the enum as well. Signed-off-by: Peter A. G. Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/zynq_slcr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/zynq_slcr.c b/hw/zynq_slcr.c index 4f97575770..8acba01c3a 100644 --- a/hw/zynq_slcr.c +++ b/hw/zynq_slcr.c @@ -91,7 +91,7 @@ typedef enum { typedef enum { PSS, DDDR, - DMAC, + DMAC = 3, USB, GEM, SDIO, From fae15286751d8a8209724b14b62d065f1111e621 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 12 Oct 2012 11:54:39 +0100 Subject: [PATCH 0867/2270] arm_gic: Rename gic_state to GICState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the gic_state struct to match QEMU's coding style conventions for structure names, since the impending KVM-for-ARM patches will create another subclass of it. This patch was created using: sed -i 's/gic_state/GICState/g' hw/arm_gic.c hw/arm_gic_common.c \ hw/arm_gic_internal.h hw/armv7m_nvic.c Acked-by: Andreas Färber Signed-off-by: Peter Maydell --- hw/arm_gic.c | 44 +++++++++++++++++++++---------------------- hw/arm_gic_common.c | 16 ++++++++-------- hw/arm_gic_internal.h | 20 ++++++++++---------- hw/armv7m_nvic.c | 6 +++--- 4 files changed, 43 insertions(+), 43 deletions(-) diff --git a/hw/arm_gic.c b/hw/arm_gic.c index 4024daeea4..56376c0d75 100644 --- a/hw/arm_gic.c +++ b/hw/arm_gic.c @@ -36,7 +36,7 @@ static const uint8_t gic_id[] = { #define NUM_CPU(s) ((s)->num_cpu) -static inline int gic_get_current_cpu(gic_state *s) +static inline int gic_get_current_cpu(GICState *s) { if (s->num_cpu > 1) { return cpu_single_env->cpu_index; @@ -46,7 +46,7 @@ static inline int gic_get_current_cpu(gic_state *s) /* TODO: Many places that call this routine could be optimized. */ /* Update interrupt status after enabled or pending bits have been changed. */ -void gic_update(gic_state *s) +void gic_update(GICState *s) { int best_irq; int best_prio; @@ -84,7 +84,7 @@ void gic_update(gic_state *s) } } -void gic_set_pending_private(gic_state *s, int cpu, int irq) +void gic_set_pending_private(GICState *s, int cpu, int irq) { int cm = 1 << cpu; @@ -105,7 +105,7 @@ static void gic_set_irq(void *opaque, int irq, int level) * [N+32..N+63] : PPI (internal interrupts for CPU 1 * ... */ - gic_state *s = (gic_state *)opaque; + GICState *s = (GICState *)opaque; int cm, target; if (irq < (s->num_irq - GIC_INTERNAL)) { /* The first external input line is internal interrupt 32. */ @@ -137,7 +137,7 @@ static void gic_set_irq(void *opaque, int irq, int level) gic_update(s); } -static void gic_set_running_irq(gic_state *s, int cpu, int irq) +static void gic_set_running_irq(GICState *s, int cpu, int irq) { s->running_irq[cpu] = irq; if (irq == 1023) { @@ -148,7 +148,7 @@ static void gic_set_running_irq(gic_state *s, int cpu, int irq) gic_update(s); } -uint32_t gic_acknowledge_irq(gic_state *s, int cpu) +uint32_t gic_acknowledge_irq(GICState *s, int cpu) { int new_irq; int cm = 1 << cpu; @@ -167,7 +167,7 @@ uint32_t gic_acknowledge_irq(gic_state *s, int cpu) return new_irq; } -void gic_complete_irq(gic_state *s, int cpu, int irq) +void gic_complete_irq(GICState *s, int cpu, int irq) { int update = 0; int cm = 1 << cpu; @@ -214,7 +214,7 @@ void gic_complete_irq(gic_state *s, int cpu, int irq) static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset) { - gic_state *s = (gic_state *)opaque; + GICState *s = (GICState *)opaque; uint32_t res; int irq; int i; @@ -347,7 +347,7 @@ static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset) static void gic_dist_writeb(void *opaque, target_phys_addr_t offset, uint32_t value) { - gic_state *s = (gic_state *)opaque; + GICState *s = (GICState *)opaque; int irq; int i; int cpu; @@ -500,7 +500,7 @@ static void gic_dist_writew(void *opaque, target_phys_addr_t offset, static void gic_dist_writel(void *opaque, target_phys_addr_t offset, uint32_t value) { - gic_state *s = (gic_state *)opaque; + GICState *s = (GICState *)opaque; if (offset == 0xf00) { int cpu; int irq; @@ -539,7 +539,7 @@ static const MemoryRegionOps gic_dist_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint32_t gic_cpu_read(gic_state *s, int cpu, int offset) +static uint32_t gic_cpu_read(GICState *s, int cpu, int offset) { switch (offset) { case 0x00: /* Control */ @@ -561,7 +561,7 @@ static uint32_t gic_cpu_read(gic_state *s, int cpu, int offset) } } -static void gic_cpu_write(gic_state *s, int cpu, int offset, uint32_t value) +static void gic_cpu_write(GICState *s, int cpu, int offset, uint32_t value) { switch (offset) { case 0x00: /* Control */ @@ -587,25 +587,25 @@ static void gic_cpu_write(gic_state *s, int cpu, int offset, uint32_t value) static uint64_t gic_thiscpu_read(void *opaque, target_phys_addr_t addr, unsigned size) { - gic_state *s = (gic_state *)opaque; + GICState *s = (GICState *)opaque; return gic_cpu_read(s, gic_get_current_cpu(s), addr); } static void gic_thiscpu_write(void *opaque, target_phys_addr_t addr, uint64_t value, unsigned size) { - gic_state *s = (gic_state *)opaque; + GICState *s = (GICState *)opaque; gic_cpu_write(s, gic_get_current_cpu(s), addr, value); } /* Wrappers to read/write the GIC CPU interface for a specific CPU. - * These just decode the opaque pointer into gic_state* + cpu id. + * These just decode the opaque pointer into GICState* + cpu id. */ static uint64_t gic_do_cpu_read(void *opaque, target_phys_addr_t addr, unsigned size) { - gic_state **backref = (gic_state **)opaque; - gic_state *s = *backref; + GICState **backref = (GICState **)opaque; + GICState *s = *backref; int id = (backref - s->backref); return gic_cpu_read(s, id, addr); } @@ -613,8 +613,8 @@ static uint64_t gic_do_cpu_read(void *opaque, target_phys_addr_t addr, static void gic_do_cpu_write(void *opaque, target_phys_addr_t addr, uint64_t value, unsigned size) { - gic_state **backref = (gic_state **)opaque; - gic_state *s = *backref; + GICState **backref = (GICState **)opaque; + GICState *s = *backref; int id = (backref - s->backref); gic_cpu_write(s, id, addr, value); } @@ -631,7 +631,7 @@ static const MemoryRegionOps gic_cpu_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -void gic_init_irqs_and_distributor(gic_state *s, int num_irq) +void gic_init_irqs_and_distributor(GICState *s, int num_irq) { int i; @@ -657,7 +657,7 @@ static int arm_gic_init(SysBusDevice *dev) { /* Device instance init function for the GIC sysbus device */ int i; - gic_state *s = FROM_SYSBUS(gic_state, dev); + GICState *s = FROM_SYSBUS(GICState, dev); ARMGICClass *agc = ARM_GIC_GET_CLASS(s); agc->parent_init(dev); @@ -701,7 +701,7 @@ static void arm_gic_class_init(ObjectClass *klass, void *data) static TypeInfo arm_gic_info = { .name = TYPE_ARM_GIC, .parent = TYPE_ARM_GIC_COMMON, - .instance_size = sizeof(gic_state), + .instance_size = sizeof(GICState), .class_init = arm_gic_class_init, .class_size = sizeof(ARMGICClass), }; diff --git a/hw/arm_gic_common.c b/hw/arm_gic_common.c index 360e7823f7..8369309d21 100644 --- a/hw/arm_gic_common.c +++ b/hw/arm_gic_common.c @@ -22,7 +22,7 @@ static void gic_save(QEMUFile *f, void *opaque) { - gic_state *s = (gic_state *)opaque; + GICState *s = (GICState *)opaque; int i; int j; @@ -56,7 +56,7 @@ static void gic_save(QEMUFile *f, void *opaque) static int gic_load(QEMUFile *f, void *opaque, int version_id) { - gic_state *s = (gic_state *)opaque; + GICState *s = (GICState *)opaque; int i; int j; @@ -96,7 +96,7 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id) static int arm_gic_common_init(SysBusDevice *dev) { - gic_state *s = FROM_SYSBUS(gic_state, dev); + GICState *s = FROM_SYSBUS(GICState, dev); int num_irq = s->num_irq; if (s->num_cpu > NCPU) { @@ -123,7 +123,7 @@ static int arm_gic_common_init(SysBusDevice *dev) static void arm_gic_common_reset(DeviceState *dev) { - gic_state *s = FROM_SYSBUS(gic_state, sysbus_from_qdev(dev)); + GICState *s = FROM_SYSBUS(GICState, sysbus_from_qdev(dev)); int i; memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state)); for (i = 0 ; i < s->num_cpu; i++) { @@ -147,13 +147,13 @@ static void arm_gic_common_reset(DeviceState *dev) } static Property arm_gic_common_properties[] = { - DEFINE_PROP_UINT32("num-cpu", gic_state, num_cpu, 1), - DEFINE_PROP_UINT32("num-irq", gic_state, num_irq, 32), + DEFINE_PROP_UINT32("num-cpu", GICState, num_cpu, 1), + DEFINE_PROP_UINT32("num-irq", GICState, num_irq, 32), /* Revision can be 1 or 2 for GIC architecture specification * versions 1 or 2, or 0 to indicate the legacy 11MPCore GIC. * (Internally, 0xffffffff also indicates "not a GIC but an NVIC".) */ - DEFINE_PROP_UINT32("revision", gic_state, revision, 1), + DEFINE_PROP_UINT32("revision", GICState, revision, 1), DEFINE_PROP_END_OF_LIST(), }; @@ -170,7 +170,7 @@ static void arm_gic_common_class_init(ObjectClass *klass, void *data) static TypeInfo arm_gic_common_type = { .name = TYPE_ARM_GIC_COMMON, .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(gic_state), + .instance_size = sizeof(GICState), .class_size = sizeof(ARMGICCommonClass), .class_init = arm_gic_common_class_init, .abstract = true, diff --git a/hw/arm_gic_internal.h b/hw/arm_gic_internal.h index db4fad564f..699352ca8b 100644 --- a/hw/arm_gic_internal.h +++ b/hw/arm_gic_internal.h @@ -69,7 +69,7 @@ typedef struct gic_irq_state { unsigned trigger:1; /* nonzero = edge triggered. */ } gic_irq_state; -typedef struct gic_state { +typedef struct GICState { SysBusDevice busdev; qemu_irq parent_irq[NCPU]; int enabled; @@ -92,25 +92,25 @@ typedef struct gic_state { /* This is just so we can have an opaque pointer which identifies * both this GIC and which CPU interface we should be accessing. */ - struct gic_state *backref[NCPU]; + struct GICState *backref[NCPU]; MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */ uint32_t num_irq; uint32_t revision; -} gic_state; +} GICState; /* The special cases for the revision property: */ #define REV_11MPCORE 0 #define REV_NVIC 0xffffffff -void gic_set_pending_private(gic_state *s, int cpu, int irq); -uint32_t gic_acknowledge_irq(gic_state *s, int cpu); -void gic_complete_irq(gic_state *s, int cpu, int irq); -void gic_update(gic_state *s); -void gic_init_irqs_and_distributor(gic_state *s, int num_irq); +void gic_set_pending_private(GICState *s, int cpu, int irq); +uint32_t gic_acknowledge_irq(GICState *s, int cpu); +void gic_complete_irq(GICState *s, int cpu, int irq); +void gic_update(GICState *s); +void gic_init_irqs_and_distributor(GICState *s, int num_irq); #define TYPE_ARM_GIC_COMMON "arm_gic_common" #define ARM_GIC_COMMON(obj) \ - OBJECT_CHECK(gic_state, (obj), TYPE_ARM_GIC_COMMON) + OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC_COMMON) #define ARM_GIC_COMMON_CLASS(klass) \ OBJECT_CLASS_CHECK(ARMGICCommonClass, (klass), TYPE_ARM_GIC_COMMON) #define ARM_GIC_COMMON_GET_CLASS(obj) \ @@ -122,7 +122,7 @@ typedef struct ARMGICCommonClass { #define TYPE_ARM_GIC "arm_gic" #define ARM_GIC(obj) \ - OBJECT_CHECK(gic_state, (obj), TYPE_ARM_GIC) + OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC) #define ARM_GIC_CLASS(klass) \ OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC) #define ARM_GIC_GET_CLASS(obj) \ diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c index 5c09116478..c449e08089 100644 --- a/hw/armv7m_nvic.c +++ b/hw/armv7m_nvic.c @@ -17,7 +17,7 @@ #include "arm_gic_internal.h" typedef struct { - gic_state gic; + GICState gic; struct { uint32_t control; uint32_t reload; @@ -505,9 +505,9 @@ static void armv7m_nvic_instance_init(Object *obj) * than our superclass. This function runs after qdev init * has set the defaults from the Property array and before * any user-specified property setting, so just modify the - * value in the gic_state struct. + * value in the GICState struct. */ - gic_state *s = ARM_GIC_COMMON(obj); + GICState *s = ARM_GIC_COMMON(obj); /* The ARM v7m may have anything from 0 to 496 external interrupt * IRQ lines. We default to 64. Other boards may differ and should * set the num-irq property appropriately. From 229d3376a38bf97aa09b6f73a957c5389badcd06 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 19 Sep 2012 04:39:53 +0200 Subject: [PATCH 0868/2270] linux-user: fix statfs The statfs syscall should always memset(0) its full struct extent before writing to it. Newer versions of the syscall use one of the reserved fields for flags, which would otherwise get stale values from uncleaned memory. This fixes libarchive for me, which got confused about the return value of pathconf("/", _PC_REC_XFER_ALIGN) otherwise, as it some times gave old pointers as return value. Signed-off-by: Alexander Graf Signed-off-by: Riku Voipio --- linux-user/syscall.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 471d0605f7..1a381699ef 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6529,6 +6529,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]); __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]); __put_user(stfs.f_namelen, &target_stfs->f_namelen); + __put_user(stfs.f_frsize, &target_stfs->f_frsize); + memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare)); unlock_user_struct(target_stfs, arg2, 1); } break; @@ -6557,6 +6559,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]); __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]); __put_user(stfs.f_namelen, &target_stfs->f_namelen); + __put_user(stfs.f_frsize, &target_stfs->f_frsize); + memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare)); unlock_user_struct(target_stfs, arg3, 1); } break; From 1bdd7c7ea8a711efcb5141663865cc1f7e4e824d Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 30 May 2012 14:45:21 +0200 Subject: [PATCH 0869/2270] linux-user: fix multi-threaded /proc/self/maps When reading our faked /proc/self/maps from a secondary thread, we get an invalid stack entry. This is because ts->stack_base is not initialized in non-primary threads. However, ts->info is, and the stack layout information we're looking for is there too. So let's use that one instead! Signed-off-by: Alexander Graf Signed-off-by: Riku Voipio --- linux-user/syscall.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1a381699ef..cf0b3858fa 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4962,8 +4962,8 @@ static int open_self_maps(void *cpu_env, int fd) #if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32) dprintf(fd, "%08llx-%08llx rw-p %08llx 00:00 0 [stack]\n", (unsigned long long)ts->info->stack_limit, - (unsigned long long)(ts->stack_base + (TARGET_PAGE_SIZE - 1)) - & TARGET_PAGE_MASK, + (unsigned long long)(ts->info->start_stack + + (TARGET_PAGE_SIZE - 1)) & TARGET_PAGE_MASK, (unsigned long long)0); #endif From f287b2c2d4d20d35880ab6dca44bda0476e67dce Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 15 Sep 2012 13:20:25 -0700 Subject: [PATCH 0870/2270] linux-user: Perform more checks on iovec lists Validate count between 0 and IOV_MAX. Limit total length of operation in the same way the kernel does. Signed-off-by: Richard Henderson Signed-off-by: Riku Voipio --- linux-user/syscall.c | 166 +++++++++++++++++++++++++++---------------- 1 file changed, 104 insertions(+), 62 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index cf0b3858fa..038aefe548 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1744,55 +1744,96 @@ static abi_long do_getsockopt(int sockfd, int level, int optname, return ret; } -/* FIXME - * lock_iovec()/unlock_iovec() have a return code of 0 for success where - * other lock functions have a return code of 0 for failure. - */ -static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr, - int count, int copy) +static struct iovec *lock_iovec(int type, abi_ulong target_addr, + int count, int copy) { struct target_iovec *target_vec; - abi_ulong base; + struct iovec *vec; + abi_ulong total_len, max_len; int i; - target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1); - if (!target_vec) - return -TARGET_EFAULT; - for(i = 0;i < count; i++) { - base = tswapal(target_vec[i].iov_base); - vec[i].iov_len = tswapal(target_vec[i].iov_len); - if (vec[i].iov_len != 0) { - vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy); - /* Don't check lock_user return value. We must call writev even - if a element has invalid base address. */ - } else { - /* zero length pointer is ignored */ - vec[i].iov_base = NULL; - } + if (count == 0) { + errno = 0; + return NULL; } - unlock_user (target_vec, target_addr, 0); - return 0; + if (count > IOV_MAX) { + errno = EINVAL; + return NULL; + } + + vec = calloc(count, sizeof(struct iovec)); + if (vec == NULL) { + errno = ENOMEM; + return NULL; + } + + target_vec = lock_user(VERIFY_READ, target_addr, + count * sizeof(struct target_iovec), 1); + if (target_vec == NULL) { + errno = EFAULT; + goto fail2; + } + + /* ??? If host page size > target page size, this will result in a + value larger than what we can actually support. */ + max_len = 0x7fffffff & TARGET_PAGE_MASK; + total_len = 0; + + for (i = 0; i < count; i++) { + abi_ulong base = tswapal(target_vec[i].iov_base); + abi_long len = tswapal(target_vec[i].iov_len); + + if (len < 0) { + errno = EINVAL; + goto fail; + } else if (len == 0) { + /* Zero length pointer is ignored. */ + vec[i].iov_base = 0; + } else { + vec[i].iov_base = lock_user(type, base, len, copy); + if (!vec[i].iov_base) { + errno = EFAULT; + goto fail; + } + if (len > max_len - total_len) { + len = max_len - total_len; + } + } + vec[i].iov_len = len; + total_len += len; + } + + unlock_user(target_vec, target_addr, 0); + return vec; + + fail: + free(vec); + fail2: + unlock_user(target_vec, target_addr, 0); + return NULL; } -static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr, - int count, int copy) +static void unlock_iovec(struct iovec *vec, abi_ulong target_addr, + int count, int copy) { struct target_iovec *target_vec; - abi_ulong base; int i; - target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1); - if (!target_vec) - return -TARGET_EFAULT; - for(i = 0;i < count; i++) { - if (target_vec[i].iov_base) { - base = tswapal(target_vec[i].iov_base); + target_vec = lock_user(VERIFY_READ, target_addr, + count * sizeof(struct target_iovec), 1); + if (target_vec) { + for (i = 0; i < count; i++) { + abi_ulong base = tswapal(target_vec[i].iov_base); + abi_long len = tswapal(target_vec[i].iov_base); + if (len < 0) { + break; + } unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0); } + unlock_user(target_vec, target_addr, 0); } - unlock_user (target_vec, target_addr, 0); - return 0; + free(vec); } /* do_socket() Must return target values and target errnos. */ @@ -1888,8 +1929,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, ret = target_to_host_sockaddr(msg.msg_name, tswapal(msgp->msg_name), msg.msg_namelen); if (ret) { - unlock_user_struct(msgp, target_msg, send ? 0 : 1); - return ret; + goto out2; } } else { msg.msg_name = NULL; @@ -1900,9 +1940,13 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, msg.msg_flags = tswap32(msgp->msg_flags); count = tswapal(msgp->msg_iovlen); - vec = alloca(count * sizeof(struct iovec)); target_vec = tswapal(msgp->msg_iov); - lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send); + vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, + target_vec, count, send); + if (vec == NULL) { + ret = -host_to_target_errno(errno); + goto out2; + } msg.msg_iovlen = count; msg.msg_iov = vec; @@ -1932,6 +1976,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, out: unlock_iovec(vec, target_vec, count, !send); +out2: unlock_user_struct(msgp, target_msg, send ? 0 : 1); return ret; } @@ -7188,26 +7233,24 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; case TARGET_NR_readv: { - int count = arg3; - struct iovec *vec; - - vec = alloca(count * sizeof(struct iovec)); - if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0) - goto efault; - ret = get_errno(readv(arg1, vec, count)); - unlock_iovec(vec, arg2, count, 1); + struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0); + if (vec != NULL) { + ret = get_errno(readv(arg1, vec, arg3)); + unlock_iovec(vec, arg2, arg3, 1); + } else { + ret = -host_to_target_errno(errno); + } } break; case TARGET_NR_writev: { - int count = arg3; - struct iovec *vec; - - vec = alloca(count * sizeof(struct iovec)); - if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0) - goto efault; - ret = get_errno(writev(arg1, vec, count)); - unlock_iovec(vec, arg2, count, 0); + struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); + if (vec != NULL) { + ret = get_errno(writev(arg1, vec, arg3)); + unlock_iovec(vec, arg2, arg3, 0); + } else { + ret = -host_to_target_errno(errno); + } } break; case TARGET_NR_getsid: @@ -8632,14 +8675,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #ifdef TARGET_NR_vmsplice case TARGET_NR_vmsplice: { - int count = arg3; - struct iovec *vec; - - vec = alloca(count * sizeof(struct iovec)); - if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0) - goto efault; - ret = get_errno(vmsplice(arg1, vec, count, arg4)); - unlock_iovec(vec, arg2, count, 0); + struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); + if (vec != NULL) { + ret = get_errno(vmsplice(arg1, vec, arg3, arg4)); + unlock_iovec(vec, arg2, arg3, 0); + } else { + ret = -host_to_target_errno(errno); + } } break; #endif From 3d21d29c32380384e5ee5b804d0b0bf720469d97 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 15 Sep 2012 13:20:46 -0700 Subject: [PATCH 0871/2270] linux-user: Implement gethostname Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Signed-off-by: Riku Voipio --- linux-user/syscall.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 038aefe548..89c74ada23 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8867,6 +8867,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } break; } +#endif +#ifdef TARGET_NR_gethostname + case TARGET_NR_gethostname: + { + char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0); + if (name) { + ret = get_errno(gethostname(name, arg2)); + unlock_user(name, arg1, arg2); + } else { + ret = -TARGET_EFAULT; + } + break; + } #endif default: unimplemented: From b7fb2310136090aab86004363f7c031b30845f2f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 14 Sep 2012 15:59:24 -0700 Subject: [PATCH 0872/2270] alpha-linux-user: Fix sigaltstack structure definition Signed-off-by: Richard Henderson Signed-off-by: Riku Voipio --- linux-user/alpha/target_signal.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/linux-user/alpha/target_signal.h b/linux-user/alpha/target_signal.h index 94f15f612f..d3822da60e 100644 --- a/linux-user/alpha/target_signal.h +++ b/linux-user/alpha/target_signal.h @@ -6,9 +6,10 @@ /* this struct defines a stack used during syscall handling */ typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_long ss_flags; - abi_ulong ss_size; + abi_ulong ss_sp; + int32_t ss_flags; + int32_t dummy; + abi_ulong ss_size; } target_stack_t; From a05c64091509056b7e321537196db967f2545601 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 15 Sep 2012 11:34:20 -0700 Subject: [PATCH 0873/2270] linux-user: Fix siginfo handling Compare signal numbers in the proper domain. Convert all of the fields for SIGIO and SIGCHLD. Signed-off-by: Richard Henderson Signed-off-by: Riku Voipio --- linux-user/qemu.h | 3 +++ linux-user/signal.c | 59 ++++++++++++++++++++++++++++++-------------- linux-user/syscall.c | 2 +- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index fc4cc00b9f..5e53dca09e 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -219,6 +219,9 @@ unsigned long init_guest_space(unsigned long host_start, #include "qemu-log.h" +/* syscall.c */ +int host_to_target_waitstatus(int status); + /* strace.c */ void print_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3, diff --git a/linux-user/signal.c b/linux-user/signal.c index 15bc4e8f62..95e2ffa007 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -202,46 +202,67 @@ void target_to_host_old_sigset(sigset_t *sigset, static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, const siginfo_t *info) { - int sig; - sig = host_to_target_signal(info->si_signo); + int sig = host_to_target_signal(info->si_signo); tinfo->si_signo = sig; tinfo->si_errno = 0; tinfo->si_code = info->si_code; - if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || - sig == SIGBUS || sig == SIGTRAP) { - /* should never come here, but who knows. The information for - the target is irrelevant */ + + if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV + || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) { + /* Should never come here, but who knows. The information for + the target is irrelevant. */ tinfo->_sifields._sigfault._addr = 0; - } else if (sig == SIGIO) { + } else if (sig == TARGET_SIGIO) { + tinfo->_sifields._sigpoll._band = info->si_band; tinfo->_sifields._sigpoll._fd = info->si_fd; + } else if (sig == TARGET_SIGCHLD) { + tinfo->_sifields._sigchld._pid = info->si_pid; + tinfo->_sifields._sigchld._uid = info->si_uid; + tinfo->_sifields._sigchld._status + = host_to_target_waitstatus(info->si_status); + tinfo->_sifields._sigchld._utime = info->si_utime; + tinfo->_sifields._sigchld._stime = info->si_stime; } else if (sig >= TARGET_SIGRTMIN) { tinfo->_sifields._rt._pid = info->si_pid; tinfo->_sifields._rt._uid = info->si_uid; /* XXX: potential problem if 64 bit */ - tinfo->_sifields._rt._sigval.sival_ptr = - (abi_ulong)(unsigned long)info->si_value.sival_ptr; + tinfo->_sifields._rt._sigval.sival_ptr + = (abi_ulong)(unsigned long)info->si_value.sival_ptr; } } static void tswap_siginfo(target_siginfo_t *tinfo, const target_siginfo_t *info) { - int sig; - sig = info->si_signo; + int sig = info->si_signo; tinfo->si_signo = tswap32(sig); tinfo->si_errno = tswap32(info->si_errno); tinfo->si_code = tswap32(info->si_code); - if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || - sig == SIGBUS || sig == SIGTRAP) { - tinfo->_sifields._sigfault._addr = - tswapal(info->_sifields._sigfault._addr); - } else if (sig == SIGIO) { - tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd); + + if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV + || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) { + tinfo->_sifields._sigfault._addr + = tswapal(info->_sifields._sigfault._addr); + } else if (sig == TARGET_SIGIO) { + tinfo->_sifields._sigpoll._band + = tswap32(info->_sifields._sigpoll._band); + tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd); + } else if (sig == TARGET_SIGCHLD) { + tinfo->_sifields._sigchld._pid + = tswap32(info->_sifields._sigchld._pid); + tinfo->_sifields._sigchld._uid + = tswap32(info->_sifields._sigchld._uid); + tinfo->_sifields._sigchld._status + = tswap32(info->_sifields._sigchld._status); + tinfo->_sifields._sigchld._utime + = tswapal(info->_sifields._sigchld._utime); + tinfo->_sifields._sigchld._stime + = tswapal(info->_sifields._sigchld._stime); } else if (sig >= TARGET_SIGRTMIN) { tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid); tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid); - tinfo->_sifields._rt._sigval.sival_ptr = - tswapal(info->_sifields._rt._sigval.sival_ptr); + tinfo->_sifields._rt._sigval.sival_ptr + = tswapal(info->_sifields._rt._sigval.sival_ptr); } } diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 89c74ada23..009bf8f1a9 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4918,7 +4918,7 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout, /* Map host to target signal numbers for the wait family of syscalls. Assume all other status bits are the same. */ -static int host_to_target_waitstatus(int status) +int host_to_target_waitstatus(int status) { if (WIFSIGNALED(status)) { return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f); From 885c1d10b803fc37e6656e733ba916c702b6f515 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 24 Aug 2012 06:55:53 +0000 Subject: [PATCH 0874/2270] linux-user: If loading fails, print error as string, not number If the attempt to load the guest executable fails, print the error message as a string, not a number. This requires us to fix a couple of places in loader_exec() where we were returning -1 instead of a valid negative errno. The change allows us to drop the "Unknown binary format" message because the strerror-enhanced message is now a more self-explanatory "Error while loading $guest-binary: Exec format error". Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/linuxload.c | 8 ++++---- linux-user/main.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c index b47025f08a..381ab8914b 100644 --- a/linux-user/linuxload.c +++ b/linux-user/linuxload.c @@ -140,8 +140,9 @@ int loader_exec(const char * filename, char ** argv, char ** envp, bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int); memset(bprm->page, 0, sizeof(bprm->page)); retval = open(filename, O_RDONLY); - if (retval < 0) - return retval; + if (retval < 0) { + return -errno; + } bprm->fd = retval; bprm->filename = (char *)filename; bprm->argc = count(argv); @@ -165,8 +166,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp, retval = load_flt_binary(bprm,regs,infop); #endif } else { - fprintf(stderr, "Unknown binary format\n"); - return -1; + return -ENOEXEC; } } diff --git a/linux-user/main.c b/linux-user/main.c index 9f3476ba57..bcaadb67cb 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3569,7 +3569,7 @@ int main(int argc, char **argv, char **envp) ret = loader_exec(filename, target_argv, target_environ, regs, info, &bprm); if (ret != 0) { - printf("Error %d while loading %s\n", ret, filename); + printf("Error while loading %s: %s\n", filename, strerror(-ret)); _exit(1); } From 30163d89953e2ec3e5fc53918682c8bc4b1b3b8d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 9 Oct 2012 03:16:49 +0000 Subject: [PATCH 0875/2270] configure: Remove unnecessary host_guest_base code All TCG hosts now support guest-base functionality, so we can remove the setting of host_guest_base to 'yes' in every arm of the case "$cpu" statement, and simply set guest_base to default to 'yes'. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Signed-off-by: Riku Voipio --- configure | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/configure b/configure index c4a78376b6..a6bdf9aff9 100755 --- a/configure +++ b/configure @@ -198,7 +198,7 @@ cocoa="no" softmmu="yes" linux_user="no" bsd_user="no" -guest_base="" +guest_base="yes" uname_release="" mixemu="no" aix="no" @@ -867,63 +867,36 @@ for opt do esac done -host_guest_base="no" case "$cpu" in sparc) LDFLAGS="-m32 $LDFLAGS" QEMU_CFLAGS="-m32 -mcpu=ultrasparc $QEMU_CFLAGS" - host_guest_base="yes" ;; sparc64) LDFLAGS="-m64 $LDFLAGS" QEMU_CFLAGS="-m64 -mcpu=ultrasparc $QEMU_CFLAGS" - host_guest_base="yes" ;; s390) QEMU_CFLAGS="-m31 -march=z990 $QEMU_CFLAGS" LDFLAGS="-m31 $LDFLAGS" - host_guest_base="yes" ;; s390x) QEMU_CFLAGS="-m64 -march=z990 $QEMU_CFLAGS" LDFLAGS="-m64 $LDFLAGS" - host_guest_base="yes" ;; i386) QEMU_CFLAGS="-m32 $QEMU_CFLAGS" LDFLAGS="-m32 $LDFLAGS" cc_i386='$(CC) -m32' - host_guest_base="yes" ;; x86_64) QEMU_CFLAGS="-m64 $QEMU_CFLAGS" LDFLAGS="-m64 $LDFLAGS" cc_i386='$(CC) -m32' - host_guest_base="yes" - ;; - arm*) - host_guest_base="yes" - ;; - ppc*) - host_guest_base="yes" - ;; - mips*) - host_guest_base="yes" - ;; - ia64*) - host_guest_base="yes" - ;; - hppa*) - host_guest_base="yes" - ;; - unicore32*) - host_guest_base="yes" ;; + # No special flags required for other host CPUs esac -[ -z "$guest_base" ] && guest_base="$host_guest_base" - - default_target_list="" # these targets are portable From 07e10e5de1470bdf1d1ed97c85cb7ed9e4826775 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 9 Oct 2012 03:16:50 +0000 Subject: [PATCH 0876/2270] tcg: Remove TCG_TARGET_HAS_GUEST_BASE define GUEST_BASE support is now supported by all TCG backends, and is now mandatory. Drop the now-pointless TCG_TARGET_HAS_GUEST_BASE define (set by every backend) and the error if it is unset. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Signed-off-by: Riku Voipio --- tcg/arm/tcg-target.h | 2 -- tcg/hppa/tcg-target.h | 2 -- tcg/i386/tcg-target.h | 2 -- tcg/ia64/tcg-target.h | 3 --- tcg/mips/tcg-target.h | 3 --- tcg/ppc/tcg-target.h | 2 -- tcg/ppc64/tcg-target.h | 1 - tcg/s390/tcg-target.h | 2 -- tcg/sparc/tcg-target.h | 2 -- tcg/tcg.c | 4 ---- tcg/tci/tcg-target.h | 3 --- 11 files changed, 26 deletions(-) diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index e2299cadd3..2bc7dff846 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -75,8 +75,6 @@ typedef enum { #define TCG_TARGET_HAS_deposit_i32 0 #define TCG_TARGET_HAS_movcond_i32 0 -#define TCG_TARGET_HAS_GUEST_BASE - enum { TCG_AREG0 = TCG_REG_R6, }; diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h index 5351353719..f43fb419ae 100644 --- a/tcg/hppa/tcg-target.h +++ b/tcg/hppa/tcg-target.h @@ -103,8 +103,6 @@ typedef enum { #define TCG_TARGET_HAS_ext8u_i32 0 /* and rd, rs, 0xff */ #define TCG_TARGET_HAS_ext16u_i32 0 /* and rd, rs, 0xffff */ -#define TCG_TARGET_HAS_GUEST_BASE - #define TCG_AREG0 TCG_REG_R17 diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index ace63ba37b..dbc6756414 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -125,8 +125,6 @@ typedef enum { ((ofs) == 0 && (len) == 16)) #define TCG_TARGET_deposit_i64_valid TCG_TARGET_deposit_i32_valid -#define TCG_TARGET_HAS_GUEST_BASE - #if TCG_TARGET_REG_BITS == 64 # define TCG_AREG0 TCG_REG_R14 #else diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index 368aee4196..b7e01b25ae 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -144,9 +144,6 @@ typedef enum { #define TCG_AREG0 TCG_REG_R7 -/* Guest base is supported */ -#define TCG_TARGET_HAS_GUEST_BASE - static inline void flush_icache_range(tcg_target_ulong start, tcg_target_ulong stop) { diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index 7020d65845..65b5c59e89 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -116,9 +116,6 @@ typedef enum { #define TCG_AREG0 TCG_REG_S0 -/* guest base is supported */ -#define TCG_TARGET_HAS_GUEST_BASE - #ifdef __OpenBSD__ #include #else diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h index 3259d898ab..ad433ae5bb 100644 --- a/tcg/ppc/tcg-target.h +++ b/tcg/ppc/tcg-target.h @@ -96,8 +96,6 @@ typedef enum { #define TCG_AREG0 TCG_REG_R27 -#define TCG_TARGET_HAS_GUEST_BASE - #define tcg_qemu_tb_exec(env, tb_ptr) \ ((long __attribute__ ((longcall)) \ (*)(void *, void *))code_gen_prologue)(env, tb_ptr) diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h index 57569e8938..97fc5c9885 100644 --- a/tcg/ppc64/tcg-target.h +++ b/tcg/ppc64/tcg-target.h @@ -108,5 +108,4 @@ typedef enum { #define TCG_AREG0 TCG_REG_R27 -#define TCG_TARGET_HAS_GUEST_BASE #define TCG_TARGET_EXTEND_ARGS 1 diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h index ed55c331c6..a0181aef74 100644 --- a/tcg/s390/tcg-target.h +++ b/tcg/s390/tcg-target.h @@ -88,8 +88,6 @@ typedef enum TCGReg { #define TCG_TARGET_HAS_movcond_i64 0 #endif -#define TCG_TARGET_HAS_GUEST_BASE - /* used for function call generation */ #define TCG_REG_CALL_STACK TCG_REG_R15 #define TCG_TARGET_STACK_ALIGN 8 diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index 6314ffb303..4a17f1e118 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -124,8 +124,6 @@ typedef enum { #define TCG_TARGET_HAS_movcond_i64 0 #endif -#define TCG_TARGET_HAS_GUEST_BASE - #define TCG_AREG0 TCG_REG_I0 static inline void flush_icache_range(tcg_target_ulong start, diff --git a/tcg/tcg.c b/tcg/tcg.c index 32cd0c6b65..a171f784a4 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -62,10 +62,6 @@ #include "elf.h" -#if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE) -#error GUEST_BASE not supported on this host. -#endif - /* Forward declarations for functions declared in tcg-target.c and used here. */ static void tcg_target_init(TCGContext *s); static void tcg_target_qemu_prologue(TCGContext *s); diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h index 6d894953aa..37f28c0522 100644 --- a/tcg/tci/tcg-target.h +++ b/tcg/tci/tcg-target.h @@ -102,9 +102,6 @@ #define TCG_TARGET_HAS_movcond_i64 0 #endif /* TCG_TARGET_REG_BITS == 64 */ -/* Offset to user memory in user mode. */ -#define TCG_TARGET_HAS_GUEST_BASE - /* Number of registers available. For 32 bit hosts, we need more than 8 registers (call arguments). */ /* #define TCG_TARGET_NB_REGS 8 */ From 4a1def4e4ec2f0eb72b15596a04a030cdc889370 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 29 Sep 2012 15:32:38 +0000 Subject: [PATCH 0877/2270] linux-user: ppc: mark as long long aligned The SysV PPC32 ABI dictates that long long (64bit) parameters are pass in odd/even register pairs. Because unlike ARM and MIPS we start at an odd register number, we can reuse the same aligning code that ARM and MIPS use. Clarified inline comment that it is SysV ABI that requires long long aligned parameters - Riku Signed-off-by: Alexander Graf Signed-off-by: Riku Voipio --- linux-user/syscall.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 009bf8f1a9..3da8e5137c 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -587,12 +587,17 @@ extern int setfsgid(int); extern int setgroups(int, gid_t *); /* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */ -#ifdef TARGET_ARM +#ifdef TARGET_ARM static inline int regpairs_aligned(void *cpu_env) { return ((((CPUARMState *)cpu_env)->eabi) == 1) ; } #elif defined(TARGET_MIPS) static inline int regpairs_aligned(void *cpu_env) { return 1; } +#elif defined(TARGET_PPC) && !defined(TARGET_PPC64) +/* SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs + * of registers which translates to the same as ARM/MIPS, because we start with + * r3 as arg1 */ +static inline int regpairs_aligned(void *cpu_env) { return 1; } #else static inline int regpairs_aligned(void *cpu_env) { return 0; } #endif From ae017a5b95962f68ece21065376cd3266998fd02 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 29 Sep 2012 15:32:39 +0000 Subject: [PATCH 0878/2270] linux-user: register align p{read, write}64 pread64 and pwrite64 pass 64bit parameters which for some architectures need to be aligned to special argument pairs, creating a gap argument. Handle this special case the same way we handle it in other places of the code. Reported-by: Alex Barcelo Signed-off-by: Alexander Graf Tested-by: Alex Barcelo Reviewed-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/syscall.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 3da8e5137c..14a6b32ab1 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7467,12 +7467,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_pread64 case TARGET_NR_pread64: + if (regpairs_aligned(cpu_env)) { + arg4 = arg5; + arg5 = arg6; + } if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) goto efault; ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5))); unlock_user(p, arg2, ret); break; case TARGET_NR_pwrite64: + if (regpairs_aligned(cpu_env)) { + arg4 = arg5; + arg5 = arg6; + } if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) goto efault; ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5))); From 0fa2a0660c7516d13bc149ff9a3b417e9778137e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 9 Oct 2012 14:49:57 -0700 Subject: [PATCH 0879/2270] target-sparc: Fix optimized %icc comparisons Signed-off-by: Richard Henderson Tested-by: Aurelien Jarno Signed-off-by: Blue Swirl --- target-sparc/translate.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 472eb518cd..71b9d65f91 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -1120,6 +1120,7 @@ static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond, cmp->c2 = tcg_temp_new(); tcg_gen_ext32s_tl(cmp->c1, cpu_cc_src); tcg_gen_ext32s_tl(cmp->c2, cpu_cc_src2); + break; } #endif cmp->g1 = cmp->g2 = true; From 96b5a3d3cf49d27e6da7ceac683a1b38d122e6fa Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 9 Oct 2012 14:49:58 -0700 Subject: [PATCH 0880/2270] target-sparc: Optimize CC_OP_LOGIC conditions Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 58 +++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 71b9d65f91..4409f69abf 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -1050,7 +1050,7 @@ static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond, DisasContext *dc) { static int subcc_cond[16] = { - -1, /* never */ + TCG_COND_NEVER, TCG_COND_EQ, TCG_COND_LE, TCG_COND_LT, @@ -1058,7 +1058,7 @@ static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond, TCG_COND_LTU, -1, /* neg */ -1, /* overflow */ - -1, /* always */ + TCG_COND_ALWAYS, TCG_COND_NE, TCG_COND_GT, TCG_COND_GE, @@ -1068,6 +1068,25 @@ static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond, -1, /* no overflow */ }; + static int logic_cond[16] = { + TCG_COND_NEVER, + TCG_COND_EQ, /* eq: Z */ + TCG_COND_LE, /* le: Z | (N ^ V) -> Z | N */ + TCG_COND_LT, /* lt: N ^ V -> N */ + TCG_COND_EQ, /* leu: C | Z -> Z */ + TCG_COND_NEVER, /* ltu: C -> 0 */ + TCG_COND_LT, /* neg: N */ + TCG_COND_NEVER, /* vs: V -> 0 */ + TCG_COND_ALWAYS, + TCG_COND_NE, /* ne: !Z */ + TCG_COND_GT, /* gt: !(Z | (N ^ V)) -> !(Z | N) */ + TCG_COND_GE, /* ge: !(N ^ V) -> !N */ + TCG_COND_NE, /* gtu: !(C | Z) -> !Z */ + TCG_COND_ALWAYS, /* geu: !C -> 1 */ + TCG_COND_GE, /* pos: !N */ + TCG_COND_ALWAYS, /* vc: !V -> 1 */ + }; + TCGv_i32 r_src; TCGv r_dst; @@ -1082,28 +1101,31 @@ static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond, #endif switch (dc->cc_op) { + case CC_OP_LOGIC: + cmp->cond = logic_cond[cond]; + do_compare_dst_0: + cmp->is_bool = false; + cmp->g2 = false; + cmp->c2 = tcg_const_tl(0); +#ifdef TARGET_SPARC64 + if (!xcc) { + cmp->g1 = false; + cmp->c1 = tcg_temp_new(); + tcg_gen_ext32s_tl(cmp->c1, cpu_cc_dst); + break; + } +#endif + cmp->g1 = true; + cmp->c1 = cpu_cc_dst; + break; + case CC_OP_SUB: switch (cond) { case 6: /* neg */ case 14: /* pos */ cmp->cond = (cond == 6 ? TCG_COND_LT : TCG_COND_GE); - cmp->is_bool = false; - cmp->g2 = false; - cmp->c2 = tcg_const_tl(0); -#ifdef TARGET_SPARC64 - if (!xcc) { - cmp->g1 = false; - cmp->c1 = tcg_temp_new(); - tcg_gen_ext32s_tl(cmp->c1, cpu_cc_dst); - break; - } -#endif - cmp->g1 = true; - cmp->c1 = cpu_cc_dst; - break; + goto do_compare_dst_0; - case 0: /* never */ - case 8: /* always */ case 7: /* overflow */ case 15: /* !overflow */ goto do_dynamic; From 6234ac09a947d1402f92b6d25ccea6faa4433b5b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 9 Oct 2012 14:49:59 -0700 Subject: [PATCH 0881/2270] target-sparc: Avoid unnecessary local temporaries Now that save_state never ends a BB, we don't need to copy values into local temps around it. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 4409f69abf..65e6f23ae1 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -143,7 +143,7 @@ static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src) if (src & 1) { return MAKE_TCGV_I32(GET_TCGV_I64(cpu_fpr[src / 2])); } else { - TCGv_i32 ret = tcg_temp_local_new_i32(); + TCGv_i32 ret = tcg_temp_new_i32(); TCGv_i64 t = tcg_temp_new_i64(); tcg_gen_shri_i64(t, cpu_fpr[src / 2], 32); @@ -3885,28 +3885,16 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_mov_tl(cpu_tbr, cpu_tmp0); break; case 6: // pstate - { - TCGv r_tmp = tcg_temp_local_new(); - - tcg_gen_mov_tl(r_tmp, cpu_tmp0); - save_state(dc); - gen_helper_wrpstate(cpu_env, r_tmp); - tcg_temp_free(r_tmp); - dc->npc = DYNAMIC_PC; - } + save_state(dc); + gen_helper_wrpstate(cpu_env, cpu_tmp0); + dc->npc = DYNAMIC_PC; break; case 7: // tl - { - TCGv r_tmp = tcg_temp_local_new(); - - tcg_gen_mov_tl(r_tmp, cpu_tmp0); - save_state(dc); - tcg_gen_trunc_tl_i32(cpu_tmp32, r_tmp); - tcg_temp_free(r_tmp); - tcg_gen_st_i32(cpu_tmp32, cpu_env, - offsetof(CPUSPARCState, tl)); - dc->npc = DYNAMIC_PC; - } + save_state(dc); + tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0); + tcg_gen_st_i32(cpu_tmp32, cpu_env, + offsetof(CPUSPARCState, tl)); + dc->npc = DYNAMIC_PC; break; case 8: // pil gen_helper_wrpil(cpu_env, cpu_tmp0); From 20132b96055e1da1d114067c15bf53e78a25d1c4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 9 Oct 2012 14:50:00 -0700 Subject: [PATCH 0882/2270] target-sparc: Don't compute full flags value so often Avoid speculatively computing flags before every potentially trapping operation and instead do the flags computation when a trap actually occurs. This gives approximately 30% speedup in emulation. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- linux-user/main.c | 5 +++++ target-sparc/int32_helper.c | 5 +++++ target-sparc/int64_helper.c | 5 +++++ target-sparc/translate.c | 30 +++++++++++------------------- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 9f3476ba57..f4bbe697f7 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -1114,6 +1114,11 @@ void cpu_loop (CPUSPARCState *env) while (1) { trapnr = cpu_sparc_exec (env); + /* Compute PSR before exposing state. */ + if (env->cc_op != CC_OP_FLAGS) { + cpu_get_psr(env); + } + switch (trapnr) { #ifndef TARGET_SPARC64 case 0x88: diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c index 9ac5aac33a..507c355cac 100644 --- a/target-sparc/int32_helper.c +++ b/target-sparc/int32_helper.c @@ -62,6 +62,11 @@ void do_interrupt(CPUSPARCState *env) { int cwp, intno = env->exception_index; + /* Compute PSR before exposing state. */ + if (env->cc_op != CC_OP_FLAGS) { + cpu_get_psr(env); + } + #ifdef DEBUG_PCALL if (qemu_loglevel_mask(CPU_LOG_INT)) { static int count; diff --git a/target-sparc/int64_helper.c b/target-sparc/int64_helper.c index 5d0bc6c6d2..df37aa1d14 100644 --- a/target-sparc/int64_helper.c +++ b/target-sparc/int64_helper.c @@ -64,6 +64,11 @@ void do_interrupt(CPUSPARCState *env) int intno = env->exception_index; trap_state *tsptr; + /* Compute PSR before exposing state. */ + if (env->cc_op != CC_OP_FLAGS) { + cpu_get_psr(env); + } + #ifdef DEBUG_PCALL if (qemu_loglevel_mask(CPU_LOG_INT)) { static int count; diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 65e6f23ae1..6cef96bfa6 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -1005,14 +1005,17 @@ static inline void save_npc(DisasContext *dc) } } -static inline void save_state(DisasContext *dc) +static inline void update_psr(DisasContext *dc) { - tcg_gen_movi_tl(cpu_pc, dc->pc); - /* flush pending conditional evaluations before exposing cpu state */ if (dc->cc_op != CC_OP_FLAGS) { dc->cc_op = CC_OP_FLAGS; gen_helper_compute_psr(cpu_env); } +} + +static inline void save_state(DisasContext *dc) +{ + tcg_gen_movi_tl(cpu_pc, dc->pc); save_npc(dc); } @@ -2704,7 +2707,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; #ifdef TARGET_SPARC64 case 0x2: /* V9 rdccr */ - gen_helper_compute_psr(cpu_env); + update_psr(dc); gen_helper_rdccr(cpu_dst, cpu_env); gen_movl_TN_reg(rd, cpu_dst); break; @@ -2783,10 +2786,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #if !defined(CONFIG_USER_ONLY) } else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */ #ifndef TARGET_SPARC64 - if (!supervisor(dc)) + if (!supervisor(dc)) { goto priv_insn; - gen_helper_compute_psr(cpu_env); - dc->cc_op = CC_OP_FLAGS; + } + update_psr(dc); gen_helper_rdpsr(cpu_dst, cpu_env); #else CHECK_IU_FEATURE(dc, HYPV); @@ -3612,7 +3615,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) dc->cc_op = CC_OP_TSUBTV; break; case 0x24: /* mulscc */ - gen_helper_compute_psr(cpu_env); + update_psr(dc); gen_op_mulscc(cpu_dst, cpu_src1, cpu_src2); gen_movl_TN_reg(rd, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD); @@ -4651,12 +4654,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) { unsigned int xop = GET_FIELD(insn, 7, 12); - /* flush pending conditional evaluations before exposing - cpu state */ - if (dc->cc_op != CC_OP_FLAGS) { - dc->cc_op = CC_OP_FLAGS; - gen_helper_compute_psr(cpu_env); - } cpu_src1 = get_src1(insn, cpu_src1); if (xop == 0x3c || xop == 0x3e) { // V9 casa/casxa rs2 = GET_FIELD(insn, 27, 31); @@ -5507,9 +5504,4 @@ void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb, int pc_pos) } else { env->npc = npc; } - - /* flush pending conditional evaluations before exposing cpu state */ - if (CC_OP != CC_OP_FLAGS) { - helper_compute_psr(env); - } } From 24c7f75459a042ac5467e0efdcb67e6c2127d5ea Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Oct 2012 09:02:36 -0700 Subject: [PATCH 0883/2270] tcg-sparc: Fix brcond2 Much the same problem as recently fixed for hppa. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- tcg/sparc/tcg-target.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 0c32baa50e..2475808c73 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -561,33 +561,24 @@ static void tcg_out_brcond2_i32(TCGContext *s, TCGCond cond, /* Note that we fill one of the delay slots with the second compare. */ switch (cond) { case TCG_COND_EQ: - cc = INSN_COND(tcg_cond_to_bcond[TCG_COND_NE], 0); - tcg_out_branch_i32(s, cc, label_next); + tcg_out_branch_i32(s, COND_NE, label_next); tcg_out_cmp(s, al, bl, blconst); - cc = INSN_COND(tcg_cond_to_bcond[TCG_COND_EQ], 0); - tcg_out_branch_i32(s, cc, label_dest); + tcg_out_branch_i32(s, COND_E, label_dest); break; case TCG_COND_NE: - cc = INSN_COND(tcg_cond_to_bcond[TCG_COND_NE], 0); - tcg_out_branch_i32(s, cc, label_dest); + tcg_out_branch_i32(s, COND_NE, label_dest); tcg_out_cmp(s, al, bl, blconst); - tcg_out_branch_i32(s, cc, label_dest); + tcg_out_branch_i32(s, COND_NE, label_dest); break; default: - /* ??? One could fairly easily special-case 64-bit unsigned - compares against 32-bit zero-extended constants. For instance, - we know that (unsigned)AH < 0 is false and need not emit it. - Similarly, (unsigned)AH > 0 being true implies AH != 0, so the - second branch will never be taken. */ - cc = INSN_COND(tcg_cond_to_bcond[cond], 0); + cc = tcg_cond_to_bcond[tcg_high_cond(cond)]; tcg_out_branch_i32(s, cc, label_dest); tcg_out_nop(s); - cc = INSN_COND(tcg_cond_to_bcond[TCG_COND_NE], 0); - tcg_out_branch_i32(s, cc, label_next); + tcg_out_branch_i32(s, COND_NE, label_next); tcg_out_cmp(s, al, bl, blconst); - cc = INSN_COND(tcg_cond_to_bcond[tcg_unsigned_cond(cond)], 0); + cc = tcg_cond_to_bcond[tcg_unsigned_cond(cond)]; tcg_out_branch_i32(s, cc, label_dest); break; } From ded37f0d96f81b6294c728d4693d9880135e3cb9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Oct 2012 09:02:37 -0700 Subject: [PATCH 0884/2270] tcg-sparc: Implement movcond. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- tcg/sparc/tcg-target.c | 43 +++++++++++++++++++++++++++++++++++------- tcg/sparc/tcg-target.h | 4 ++-- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 2475808c73..79530ecb64 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -539,6 +539,22 @@ static void tcg_out_brcond_i32(TCGContext *s, TCGCond cond, tcg_out_nop(s); } +static void tcg_out_movcc(TCGContext *s, TCGCond cond, int cc, TCGArg ret, + TCGArg v1, int v1const) +{ + tcg_out32(s, ARITH_MOVCC | cc | INSN_RD(ret) + | INSN_RS1(tcg_cond_to_bcond[cond]) + | (v1const ? INSN_IMM11(v1) : INSN_RS2(v1))); +} + +static void tcg_out_movcond_i32(TCGContext *s, TCGCond cond, TCGArg ret, + TCGArg c1, TCGArg c2, int c2const, + TCGArg v1, int v1const) +{ + tcg_out_cmp(s, c1, c2, c2const); + tcg_out_movcc(s, cond, MOVCC_ICC, ret, v1, v1const); +} + #if TCG_TARGET_REG_BITS == 64 static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGArg arg1, TCGArg arg2, int const_arg2, @@ -548,6 +564,14 @@ static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, tcg_out_branch_i64(s, tcg_cond_to_bcond[cond], label_index); tcg_out_nop(s); } + +static void tcg_out_movcond_i64(TCGContext *s, TCGCond cond, TCGArg ret, + TCGArg c1, TCGArg c2, int c2const, + TCGArg v1, int v1const) +{ + tcg_out_cmp(s, c1, c2, c2const); + tcg_out_movcc(s, cond, MOVCC_XCC, ret, v1, v1const); +} #else static void tcg_out_brcond2_i32(TCGContext *s, TCGCond cond, TCGArg al, TCGArg ah, @@ -621,9 +645,7 @@ static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGArg ret, default: tcg_out_cmp(s, c1, c2, c2const); tcg_out_movi_imm13(s, ret, 0); - tcg_out32(s, ARITH_MOVCC | INSN_RD(ret) - | INSN_RS1(tcg_cond_to_bcond[cond]) - | MOVCC_ICC | INSN_IMM11(1)); + tcg_out_movcc(s, cond, MOVCC_ICC, ret, 1, 1); return; } @@ -641,9 +663,7 @@ static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGArg ret, { tcg_out_cmp(s, c1, c2, c2const); tcg_out_movi_imm13(s, ret, 0); - tcg_out32 (s, ARITH_MOVCC | INSN_RD(ret) - | INSN_RS1(tcg_cond_to_bcond[cond]) - | MOVCC_XCC | INSN_IMM11(1)); + tcg_out_movcc(s, cond, MOVCC_XCC, ret, 1, 1); } #else static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret, @@ -1202,6 +1222,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, tcg_out_setcond_i32(s, args[3], args[0], args[1], args[2], const_args[2]); break; + case INDEX_op_movcond_i32: + tcg_out_movcond_i32(s, args[5], args[0], args[1], + args[2], const_args[2], args[3], const_args[3]); + break; #if TCG_TARGET_REG_BITS == 32 case INDEX_op_brcond2_i32: @@ -1337,7 +1361,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, tcg_out_setcond_i64(s, args[3], args[0], args[1], args[2], const_args[2]); break; - + case INDEX_op_movcond_i64: + tcg_out_movcond_i64(s, args[5], args[0], args[1], + args[2], const_args[2], args[3], const_args[3]); + break; #endif gen_arith: tcg_out_arithc(s, args[0], args[1], args[2], const_args[2], c); @@ -1392,6 +1419,7 @@ static const TCGTargetOpDef sparc_op_defs[] = { { INDEX_op_brcond_i32, { "r", "rJ" } }, { INDEX_op_setcond_i32, { "r", "r", "rJ" } }, + { INDEX_op_movcond_i32, { "r", "r", "rJ", "rI", "0" } }, #if TCG_TARGET_REG_BITS == 32 { INDEX_op_brcond2_i32, { "r", "r", "rJ", "rJ" } }, @@ -1441,6 +1469,7 @@ static const TCGTargetOpDef sparc_op_defs[] = { { INDEX_op_brcond_i64, { "r", "rJ" } }, { INDEX_op_setcond_i64, { "r", "r", "rJ" } }, + { INDEX_op_movcond_i64, { "r", "r", "rJ", "rI", "0" } }, #endif #if TCG_TARGET_REG_BITS == 64 diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index 6314ffb303..c718a52e26 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -99,7 +99,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 0 -#define TCG_TARGET_HAS_movcond_i32 0 +#define TCG_TARGET_HAS_movcond_i32 1 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_div_i64 1 @@ -121,7 +121,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 0 -#define TCG_TARGET_HAS_movcond_i64 0 +#define TCG_TARGET_HAS_movcond_i64 1 #endif #define TCG_TARGET_HAS_GUEST_BASE From dda73c782ffb1333eaf96444e27dcce5bc658454 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Oct 2012 09:02:38 -0700 Subject: [PATCH 0885/2270] tcg-sparc: Fix setcond2 Like brcond2, use tcg_high_cond. Use movcc instead of branches. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- tcg/sparc/tcg-target.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 79530ecb64..bdc282d29a 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -337,7 +337,9 @@ static void tcg_out_arithc(TCGContext *s, int rd, int rs1, static inline void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) { - tcg_out_arith(s, ret, arg, TCG_REG_G0, ARITH_OR); + if (ret != arg) { + tcg_out_arith(s, ret, arg, TCG_REG_G0, ARITH_OR); + } } static inline void tcg_out_sethi(TCGContext *s, int ret, uint32_t arg) @@ -671,33 +673,29 @@ static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret, TCGArg bl, int blconst, TCGArg bh, int bhconst) { - int lab; + int tmp = TCG_REG_T1; + + /* Note that the low parts are fully consumed before tmp is set. */ + if (ret != ah && (bhconst || ret != bh)) { + tmp = ret; + } switch (cond) { case TCG_COND_EQ: - tcg_out_setcond_i32(s, TCG_COND_EQ, TCG_REG_T1, al, bl, blconst); - tcg_out_setcond_i32(s, TCG_COND_EQ, ret, ah, bh, bhconst); - tcg_out_arith(s, ret, ret, TCG_REG_T1, ARITH_AND); - break; - case TCG_COND_NE: - tcg_out_setcond_i32(s, TCG_COND_NE, TCG_REG_T1, al, al, blconst); - tcg_out_setcond_i32(s, TCG_COND_NE, ret, ah, bh, bhconst); - tcg_out_arith(s, ret, ret, TCG_REG_T1, ARITH_OR); + tcg_out_setcond_i32(s, cond, tmp, al, bl, blconst); + tcg_out_cmp(s, ah, bh, bhconst); + tcg_out_mov(s, TCG_TYPE_I32, ret, tmp); + tcg_out_movcc(s, TCG_COND_NE, MOVCC_ICC, ret, cond == TCG_COND_NE, 1); break; default: - lab = gen_new_label(); - + /* <= : ah < bh | (ah == bh && al <= bl) */ + tcg_out_setcond_i32(s, tcg_unsigned_cond(cond), tmp, al, bl, blconst); tcg_out_cmp(s, ah, bh, bhconst); - tcg_out_branch_i32(s, INSN_COND(tcg_cond_to_bcond[cond], 1), lab); - tcg_out_movi_imm13(s, ret, 1); - tcg_out_branch_i32(s, INSN_COND(COND_NE, 1), lab); - tcg_out_movi_imm13(s, ret, 0); - - tcg_out_setcond_i32(s, tcg_unsigned_cond(cond), ret, al, bl, blconst); - - tcg_out_label(s, lab, s->code_ptr); + tcg_out_mov(s, TCG_TYPE_I32, ret, tmp); + tcg_out_movcc(s, TCG_COND_NE, MOVCC_ICC, ret, 0, 1); + tcg_out_movcc(s, tcg_high_cond(cond), MOVCC_ICC, ret, 1, 1); break; } } From a7a49843d70232e0f179e1da330355e5f03ab182 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Oct 2012 09:02:39 -0700 Subject: [PATCH 0886/2270] tcg-sparc: Fix qemu_st for 32-bit The datalo variable is still live in the miss path. Use another when reconstructing the full data value. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- tcg/sparc/tcg-target.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index bdc282d29a..3144044a43 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -985,7 +985,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop) { int addrlo_idx = 1, datalo, datahi, addr_reg; #if defined(CONFIG_SOFTMMU) - int memi_idx, memi, n; + int memi_idx, memi, n, datafull; uint32_t *label_ptr; #endif @@ -1002,12 +1002,13 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop) addr_reg = tcg_out_tlb_load(s, addrlo_idx, memi, sizeop, args, offsetof(CPUTLBEntry, addr_write)); + datafull = datalo; if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) { /* Reconstruct the full 64-bit value. */ tcg_out_arithi(s, TCG_REG_T1, datalo, 0, SHIFT_SRL); tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX); tcg_out_arith(s, TCG_REG_O2, TCG_REG_T1, TCG_REG_O2, ARITH_OR); - datalo = TCG_REG_O2; + datafull = TCG_REG_O2; } /* The fast path is exactly one insn. Thus we can perform the entire @@ -1018,7 +1019,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop) | ((TARGET_LONG_BITS == 64) << 21) | (1 << 29) | (1 << 19))); /* delay slot */ - tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_O1, qemu_st_opc[sizeop]); + tcg_out_ldst_rr(s, datafull, addr_reg, TCG_REG_O1, qemu_st_opc[sizeop]); /* TLB Miss. */ From 7d458a7567ffde5b16d7a4b5e9f585434b2afc35 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Oct 2012 09:02:40 -0700 Subject: [PATCH 0887/2270] tcg-sparc: Fix setcond The set of comparisons that can immediately use the carry are LTU/GEU, not LTU/LEU. Don't swap operands when we need a temp register; the register may already be in use from setcond2. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- tcg/sparc/tcg-target.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 3144044a43..31e8204b31 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -617,32 +617,37 @@ static void tcg_out_brcond2_i32(TCGContext *s, TCGCond cond, static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGArg ret, TCGArg c1, TCGArg c2, int c2const) { - TCGArg t; - /* For 32-bit comparisons, we can play games with ADDX/SUBX. */ switch (cond) { + case TCG_COND_LTU: + case TCG_COND_GEU: + /* The result of the comparison is in the carry bit. */ + break; + case TCG_COND_EQ: case TCG_COND_NE: + /* For equality, we can transform to inequality vs zero. */ if (c2 != 0) { tcg_out_arithc(s, ret, c1, c2, c2const, ARITH_XOR); } c1 = TCG_REG_G0, c2 = ret, c2const = 0; - cond = (cond == TCG_COND_EQ ? TCG_COND_LEU : TCG_COND_LTU); + cond = (cond == TCG_COND_EQ ? TCG_COND_GEU : TCG_COND_LTU); break; case TCG_COND_GTU: - case TCG_COND_GEU: - if (c2const && c2 != 0) { - tcg_out_movi_imm13(s, TCG_REG_T1, c2); - c2 = TCG_REG_T1; - } - t = c1, c1 = c2, c2 = t, c2const = 0; - cond = tcg_swap_cond(cond); - break; - - case TCG_COND_LTU: case TCG_COND_LEU: - break; + /* If we don't need to load a constant into a register, we can + swap the operands on GTU/LEU. There's no benefit to loading + the constant into a temporary register. */ + if (!c2const || c2 == 0) { + TCGArg t = c1; + c1 = c2; + c2 = t; + c2const = 0; + cond = tcg_swap_cond(cond); + break; + } + /* FALLTHRU */ default: tcg_out_cmp(s, c1, c2, c2const); From 4ec28e255f532c245cb477d49d0793af657e4149 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Oct 2012 09:02:41 -0700 Subject: [PATCH 0888/2270] tcg-sparc: Fix add2/sub2 We must care not to clobber the high parts before we consume them. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- tcg/sparc/tcg-target.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 31e8204b31..d6da9fa953 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -704,6 +704,22 @@ static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret, break; } } + +static void tcg_out_addsub2(TCGContext *s, TCGArg rl, TCGArg rh, + TCGArg al, TCGArg ah, TCGArg bl, int blconst, + TCGArg bh, int bhconst, int opl, int oph) +{ + TCGArg tmp = TCG_REG_T1; + + /* Note that the low parts are fully consumed before tmp is set. */ + if (rl != ah && (bhconst || rl != bh)) { + tmp = rl; + } + + tcg_out_arithc(s, tmp, al, bl, blconst, opl); + tcg_out_arithc(s, rh, ah, bh, bhconst, oph); + tcg_out_mov(s, TCG_TYPE_I32, rl, tmp); +} #endif /* Generate global QEMU prologue and epilogue code */ @@ -1243,16 +1259,14 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, args[4], const_args[4]); break; case INDEX_op_add2_i32: - tcg_out_arithc(s, args[0], args[2], args[4], const_args[4], - ARITH_ADDCC); - tcg_out_arithc(s, args[1], args[3], args[5], const_args[5], - ARITH_ADDX); + tcg_out_addsub2(s, args[0], args[1], args[2], args[3], + args[4], const_args[4], args[5], const_args[5], + ARITH_ADDCC, ARITH_ADDX); break; case INDEX_op_sub2_i32: - tcg_out_arithc(s, args[0], args[2], args[4], const_args[4], - ARITH_SUBCC); - tcg_out_arithc(s, args[1], args[3], args[5], const_args[5], - ARITH_SUBX); + tcg_out_addsub2(s, args[0], args[1], args[2], args[3], + args[4], const_args[4], args[5], const_args[5], + ARITH_SUBCC, ARITH_SUBX); break; case INDEX_op_mulu2_i32: tcg_out_arithc(s, args[0], args[2], args[3], const_args[3], From 89269f6cea17d8381e0c366c44780f58ac3c67d8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Oct 2012 09:02:42 -0700 Subject: [PATCH 0889/2270] tcg-sparc: Use Z constraint for %g0 Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- tcg/sparc/tcg-target.c | 113 +++++++++++++++++++++-------------------- tcg/sparc/tcg-target.h | 5 +- 2 files changed, 62 insertions(+), 56 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index d6da9fa953..f7d52d63e2 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -180,6 +180,9 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) case 'J': ct->ct |= TCG_CT_CONST_S13; break; + case 'Z': + ct->ct |= TCG_CT_CONST_ZERO; + break; default: return -1; } @@ -192,17 +195,19 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) static inline int tcg_target_const_match(tcg_target_long val, const TCGArgConstraint *arg_ct) { - int ct; + int ct = arg_ct->ct; - ct = arg_ct->ct; - if (ct & TCG_CT_CONST) + if (ct & TCG_CT_CONST) { return 1; - else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11)) + } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) { return 1; - else if ((ct & TCG_CT_CONST_S13) && check_fit_tl(val, 13)) + } else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11)) { return 1; - else + } else if ((ct & TCG_CT_CONST_S13) && check_fit_tl(val, 13)) { + return 1; + } else { return 0; + } } #define INSN_OP(x) ((x) << 30) @@ -1411,40 +1416,40 @@ static const TCGTargetOpDef sparc_op_defs[] = { { INDEX_op_ld16u_i32, { "r", "r" } }, { INDEX_op_ld16s_i32, { "r", "r" } }, { INDEX_op_ld_i32, { "r", "r" } }, - { INDEX_op_st8_i32, { "r", "r" } }, - { INDEX_op_st16_i32, { "r", "r" } }, - { INDEX_op_st_i32, { "r", "r" } }, + { INDEX_op_st8_i32, { "rZ", "r" } }, + { INDEX_op_st16_i32, { "rZ", "r" } }, + { INDEX_op_st_i32, { "rZ", "r" } }, - { INDEX_op_add_i32, { "r", "r", "rJ" } }, - { INDEX_op_mul_i32, { "r", "r", "rJ" } }, - { INDEX_op_div_i32, { "r", "r", "rJ" } }, - { INDEX_op_divu_i32, { "r", "r", "rJ" } }, - { INDEX_op_rem_i32, { "r", "r", "rJ" } }, - { INDEX_op_remu_i32, { "r", "r", "rJ" } }, - { INDEX_op_sub_i32, { "r", "r", "rJ" } }, - { INDEX_op_and_i32, { "r", "r", "rJ" } }, - { INDEX_op_andc_i32, { "r", "r", "rJ" } }, - { INDEX_op_or_i32, { "r", "r", "rJ" } }, - { INDEX_op_orc_i32, { "r", "r", "rJ" } }, - { INDEX_op_xor_i32, { "r", "r", "rJ" } }, + { INDEX_op_add_i32, { "r", "rZ", "rJ" } }, + { INDEX_op_mul_i32, { "r", "rZ", "rJ" } }, + { INDEX_op_div_i32, { "r", "rZ", "rJ" } }, + { INDEX_op_divu_i32, { "r", "rZ", "rJ" } }, + { INDEX_op_rem_i32, { "r", "rZ", "rJ" } }, + { INDEX_op_remu_i32, { "r", "rZ", "rJ" } }, + { INDEX_op_sub_i32, { "r", "rZ", "rJ" } }, + { INDEX_op_and_i32, { "r", "rZ", "rJ" } }, + { INDEX_op_andc_i32, { "r", "rZ", "rJ" } }, + { INDEX_op_or_i32, { "r", "rZ", "rJ" } }, + { INDEX_op_orc_i32, { "r", "rZ", "rJ" } }, + { INDEX_op_xor_i32, { "r", "rZ", "rJ" } }, - { INDEX_op_shl_i32, { "r", "r", "rJ" } }, - { INDEX_op_shr_i32, { "r", "r", "rJ" } }, - { INDEX_op_sar_i32, { "r", "r", "rJ" } }, + { INDEX_op_shl_i32, { "r", "rZ", "rJ" } }, + { INDEX_op_shr_i32, { "r", "rZ", "rJ" } }, + { INDEX_op_sar_i32, { "r", "rZ", "rJ" } }, { INDEX_op_neg_i32, { "r", "rJ" } }, { INDEX_op_not_i32, { "r", "rJ" } }, - { INDEX_op_brcond_i32, { "r", "rJ" } }, - { INDEX_op_setcond_i32, { "r", "r", "rJ" } }, - { INDEX_op_movcond_i32, { "r", "r", "rJ", "rI", "0" } }, + { INDEX_op_brcond_i32, { "rZ", "rJ" } }, + { INDEX_op_setcond_i32, { "r", "rZ", "rJ" } }, + { INDEX_op_movcond_i32, { "r", "rZ", "rJ", "rI", "0" } }, #if TCG_TARGET_REG_BITS == 32 - { INDEX_op_brcond2_i32, { "r", "r", "rJ", "rJ" } }, - { INDEX_op_setcond2_i32, { "r", "r", "r", "rJ", "rJ" } }, - { INDEX_op_add2_i32, { "r", "r", "r", "r", "rJ", "rJ" } }, - { INDEX_op_sub2_i32, { "r", "r", "r", "r", "rJ", "rJ" } }, - { INDEX_op_mulu2_i32, { "r", "r", "r", "rJ" } }, + { INDEX_op_brcond2_i32, { "rZ", "rZ", "rJ", "rJ" } }, + { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rJ", "rJ" } }, + { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } }, + { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } }, + { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rJ" } }, #endif #if TCG_TARGET_REG_BITS == 64 @@ -1457,27 +1462,27 @@ static const TCGTargetOpDef sparc_op_defs[] = { { INDEX_op_ld32u_i64, { "r", "r" } }, { INDEX_op_ld32s_i64, { "r", "r" } }, { INDEX_op_ld_i64, { "r", "r" } }, - { INDEX_op_st8_i64, { "r", "r" } }, - { INDEX_op_st16_i64, { "r", "r" } }, - { INDEX_op_st32_i64, { "r", "r" } }, - { INDEX_op_st_i64, { "r", "r" } }, + { INDEX_op_st8_i64, { "rZ", "r" } }, + { INDEX_op_st16_i64, { "rZ", "r" } }, + { INDEX_op_st32_i64, { "rZ", "r" } }, + { INDEX_op_st_i64, { "rZ", "r" } }, - { INDEX_op_add_i64, { "r", "r", "rJ" } }, - { INDEX_op_mul_i64, { "r", "r", "rJ" } }, - { INDEX_op_div_i64, { "r", "r", "rJ" } }, - { INDEX_op_divu_i64, { "r", "r", "rJ" } }, - { INDEX_op_rem_i64, { "r", "r", "rJ" } }, - { INDEX_op_remu_i64, { "r", "r", "rJ" } }, - { INDEX_op_sub_i64, { "r", "r", "rJ" } }, - { INDEX_op_and_i64, { "r", "r", "rJ" } }, - { INDEX_op_andc_i64, { "r", "r", "rJ" } }, - { INDEX_op_or_i64, { "r", "r", "rJ" } }, - { INDEX_op_orc_i64, { "r", "r", "rJ" } }, - { INDEX_op_xor_i64, { "r", "r", "rJ" } }, + { INDEX_op_add_i64, { "r", "rZ", "rJ" } }, + { INDEX_op_mul_i64, { "r", "rZ", "rJ" } }, + { INDEX_op_div_i64, { "r", "rZ", "rJ" } }, + { INDEX_op_divu_i64, { "r", "rZ", "rJ" } }, + { INDEX_op_rem_i64, { "r", "rZ", "rJ" } }, + { INDEX_op_remu_i64, { "r", "rZ", "rJ" } }, + { INDEX_op_sub_i64, { "r", "rZ", "rJ" } }, + { INDEX_op_and_i64, { "r", "rZ", "rJ" } }, + { INDEX_op_andc_i64, { "r", "rZ", "rJ" } }, + { INDEX_op_or_i64, { "r", "rZ", "rJ" } }, + { INDEX_op_orc_i64, { "r", "rZ", "rJ" } }, + { INDEX_op_xor_i64, { "r", "rZ", "rJ" } }, - { INDEX_op_shl_i64, { "r", "r", "rJ" } }, - { INDEX_op_shr_i64, { "r", "r", "rJ" } }, - { INDEX_op_sar_i64, { "r", "r", "rJ" } }, + { INDEX_op_shl_i64, { "r", "rZ", "rJ" } }, + { INDEX_op_shr_i64, { "r", "rZ", "rJ" } }, + { INDEX_op_sar_i64, { "r", "rZ", "rJ" } }, { INDEX_op_neg_i64, { "r", "rJ" } }, { INDEX_op_not_i64, { "r", "rJ" } }, @@ -1485,9 +1490,9 @@ static const TCGTargetOpDef sparc_op_defs[] = { { INDEX_op_ext32s_i64, { "r", "ri" } }, { INDEX_op_ext32u_i64, { "r", "ri" } }, - { INDEX_op_brcond_i64, { "r", "rJ" } }, - { INDEX_op_setcond_i64, { "r", "r", "rJ" } }, - { INDEX_op_movcond_i64, { "r", "r", "rJ", "rI", "0" } }, + { INDEX_op_brcond_i64, { "rZ", "rJ" } }, + { INDEX_op_setcond_i64, { "r", "rZ", "rJ" } }, + { INDEX_op_movcond_i64, { "r", "rZ", "rJ", "rI", "0" } }, #endif #if TCG_TARGET_REG_BITS == 64 diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index c718a52e26..c2fbb23abb 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -62,8 +62,9 @@ typedef enum { TCG_REG_I7, } TCGReg; -#define TCG_CT_CONST_S11 0x100 -#define TCG_CT_CONST_S13 0x200 +#define TCG_CT_CONST_S11 0x100 +#define TCG_CT_CONST_S13 0x200 +#define TCG_CT_CONST_ZERO 0x400 /* used for function call generation */ #define TCG_REG_CALL_STACK TCG_REG_O6 From fd84ea2391c044a7840c25dd35336bdaf2a302d0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Oct 2012 09:02:43 -0700 Subject: [PATCH 0890/2270] tcg-sparc: Optimize setcond2 equality compare with 0. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- tcg/sparc/tcg-target.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index f7d52d63e2..9c87cb632a 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -693,9 +693,18 @@ static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret, switch (cond) { case TCG_COND_EQ: case TCG_COND_NE: - tcg_out_setcond_i32(s, cond, tmp, al, bl, blconst); - tcg_out_cmp(s, ah, bh, bhconst); - tcg_out_mov(s, TCG_TYPE_I32, ret, tmp); + if (bl == 0 && bh == 0) { + if (cond == TCG_COND_EQ) { + tcg_out_arith(s, TCG_REG_G0, al, ah, ARITH_ORCC); + tcg_out_movi(s, TCG_TYPE_I32, ret, 1); + } else { + tcg_out_arith(s, ret, al, ah, ARITH_ORCC); + } + } else { + tcg_out_setcond_i32(s, cond, tmp, al, bl, blconst); + tcg_out_cmp(s, ah, bh, bhconst); + tcg_out_mov(s, TCG_TYPE_I32, ret, tmp); + } tcg_out_movcc(s, TCG_COND_NE, MOVCC_ICC, ret, cond == TCG_COND_NE, 1); break; From a115f3ea47cbd3ae64c754779321264857ab5bde Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Oct 2012 09:02:44 -0700 Subject: [PATCH 0891/2270] tcg-sparc: Drop use of Bicc in favor of BPcc Now that we're always sparcv9, we can not bother using Bicc for 32-bit branches and BPcc for 64-bit branches and instead always use BPcc. New interfaces allow less direct use of tcg_out32 and raw numbers inside the qemu_ld/st routines. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- tcg/sparc/tcg-target.c | 305 ++++++++++++++++++++--------------------- 1 file changed, 145 insertions(+), 160 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 9c87cb632a..ab47c98378 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -115,101 +115,6 @@ static const int tcg_target_call_oarg_regs[] = { TCG_REG_O3, }; -static inline int check_fit_tl(tcg_target_long val, unsigned int bits) -{ - return (val << ((sizeof(tcg_target_long) * 8 - bits)) - >> (sizeof(tcg_target_long) * 8 - bits)) == val; -} - -static inline int check_fit_i32(uint32_t val, unsigned int bits) -{ - return ((val << (32 - bits)) >> (32 - bits)) == val; -} - -static void patch_reloc(uint8_t *code_ptr, int type, - tcg_target_long value, tcg_target_long addend) -{ - value += addend; - switch (type) { - case R_SPARC_32: - if (value != (uint32_t)value) - tcg_abort(); - *(uint32_t *)code_ptr = value; - break; - case R_SPARC_WDISP22: - value -= (long)code_ptr; - value >>= 2; - if (!check_fit_tl(value, 22)) - tcg_abort(); - *(uint32_t *)code_ptr = ((*(uint32_t *)code_ptr) & ~0x3fffff) | value; - break; - case R_SPARC_WDISP19: - value -= (long)code_ptr; - value >>= 2; - if (!check_fit_tl(value, 19)) - tcg_abort(); - *(uint32_t *)code_ptr = ((*(uint32_t *)code_ptr) & ~0x7ffff) | value; - break; - default: - tcg_abort(); - } -} - -/* parse target specific constraints */ -static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) -{ - const char *ct_str; - - ct_str = *pct_str; - switch (ct_str[0]) { - case 'r': - ct->ct |= TCG_CT_REG; - tcg_regset_set32(ct->u.regs, 0, 0xffffffff); - break; - case 'L': /* qemu_ld/st constraint */ - ct->ct |= TCG_CT_REG; - tcg_regset_set32(ct->u.regs, 0, 0xffffffff); - // Helper args - tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2); - break; - case 'I': - ct->ct |= TCG_CT_CONST_S11; - break; - case 'J': - ct->ct |= TCG_CT_CONST_S13; - break; - case 'Z': - ct->ct |= TCG_CT_CONST_ZERO; - break; - default: - return -1; - } - ct_str++; - *pct_str = ct_str; - return 0; -} - -/* test if a constant matches the constraint */ -static inline int tcg_target_const_match(tcg_target_long val, - const TCGArgConstraint *arg_ct) -{ - int ct = arg_ct->ct; - - if (ct & TCG_CT_CONST) { - return 1; - } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) { - return 1; - } else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11)) { - return 1; - } else if ((ct & TCG_CT_CONST_S13) && check_fit_tl(val, 13)) { - return 1; - } else { - return 0; - } -} - #define INSN_OP(x) ((x) << 30) #define INSN_OP2(x) ((x) << 22) #define INSN_OP3(x) ((x) << 19) @@ -222,9 +127,8 @@ static inline int tcg_target_const_match(tcg_target_long val, #define INSN_IMM11(x) ((1 << 13) | ((x) & 0x7ff)) #define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff)) #define INSN_OFF19(x) (((x) >> 2) & 0x07ffff) -#define INSN_OFF22(x) (((x) >> 2) & 0x3fffff) +#define INSN_COND(x) ((x) << 25) -#define INSN_COND(x, a) (((x) << 25) | ((a) << 29)) #define COND_N 0x0 #define COND_E 0x1 #define COND_LE 0x2 @@ -241,11 +145,17 @@ static inline int tcg_target_const_match(tcg_target_long val, #define COND_CC 0xd #define COND_POS 0xe #define COND_VC 0xf -#define BA (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2)) +#define BA (INSN_OP(0) | INSN_COND(COND_A) | INSN_OP2(0x2)) #define MOVCC_ICC (1 << 18) #define MOVCC_XCC (1 << 18 | 1 << 12) +#define BPCC_ICC 0 +#define BPCC_XCC (2 << 20) +#define BPCC_PT (1 << 19) +#define BPCC_PN 0 +#define BPCC_A (1 << 29) + #define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00)) #define ARITH_ADDCC (INSN_OP(2) | INSN_OP3(0x10)) #define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01)) @@ -318,6 +228,99 @@ static inline int tcg_target_const_match(tcg_target_long val, #define STW_LE (STWA | INSN_ASI(ASI_PRIMARY_LITTLE)) #define STX_LE (STXA | INSN_ASI(ASI_PRIMARY_LITTLE)) +static inline int check_fit_tl(tcg_target_long val, unsigned int bits) +{ + return (val << ((sizeof(tcg_target_long) * 8 - bits)) + >> (sizeof(tcg_target_long) * 8 - bits)) == val; +} + +static inline int check_fit_i32(uint32_t val, unsigned int bits) +{ + return ((val << (32 - bits)) >> (32 - bits)) == val; +} + +static void patch_reloc(uint8_t *code_ptr, int type, + tcg_target_long value, tcg_target_long addend) +{ + uint32_t insn; + value += addend; + switch (type) { + case R_SPARC_32: + if (value != (uint32_t)value) { + tcg_abort(); + } + *(uint32_t *)code_ptr = value; + break; + case R_SPARC_WDISP19: + value -= (long)code_ptr; + if (!check_fit_tl(value >> 2, 19)) { + tcg_abort(); + } + insn = *(uint32_t *)code_ptr; + insn &= ~INSN_OFF19(-1); + insn |= INSN_OFF19(value); + *(uint32_t *)code_ptr = insn; + break; + default: + tcg_abort(); + } +} + +/* parse target specific constraints */ +static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) +{ + const char *ct_str; + + ct_str = *pct_str; + switch (ct_str[0]) { + case 'r': + ct->ct |= TCG_CT_REG; + tcg_regset_set32(ct->u.regs, 0, 0xffffffff); + break; + case 'L': /* qemu_ld/st constraint */ + ct->ct |= TCG_CT_REG; + tcg_regset_set32(ct->u.regs, 0, 0xffffffff); + // Helper args + tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0); + tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1); + tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2); + break; + case 'I': + ct->ct |= TCG_CT_CONST_S11; + break; + case 'J': + ct->ct |= TCG_CT_CONST_S13; + break; + case 'Z': + ct->ct |= TCG_CT_CONST_ZERO; + break; + default: + return -1; + } + ct_str++; + *pct_str = ct_str; + return 0; +} + +/* test if a constant matches the constraint */ +static inline int tcg_target_const_match(tcg_target_long val, + const TCGArgConstraint *arg_ct) +{ + int ct = arg_ct->ct; + + if (ct & TCG_CT_CONST) { + return 1; + } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) { + return 1; + } else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11)) { + return 1; + } else if ((ct & TCG_CT_CONST_S13) && check_fit_tl(val, 13)) { + return 1; + } else { + return 0; + } +} + static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2, int op) { @@ -486,39 +489,6 @@ static inline void tcg_out_nop(TCGContext *s) tcg_out_sethi(s, TCG_REG_G0, 0); } -static void tcg_out_branch_i32(TCGContext *s, int opc, int label_index) -{ - TCGLabel *l = &s->labels[label_index]; - uint32_t off22; - - if (l->has_value) { - off22 = INSN_OFF22(l->u.value - (unsigned long)s->code_ptr); - } else { - /* Make sure to preserve destinations during retranslation. */ - off22 = *(uint32_t *)s->code_ptr & INSN_OFF22(-1); - tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP22, label_index, 0); - } - tcg_out32(s, INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) | off22); -} - -#if TCG_TARGET_REG_BITS == 64 -static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index) -{ - TCGLabel *l = &s->labels[label_index]; - uint32_t off19; - - if (l->has_value) { - off19 = INSN_OFF19(l->u.value - (unsigned long)s->code_ptr); - } else { - /* Make sure to preserve destinations during retranslation. */ - off19 = *(uint32_t *)s->code_ptr & INSN_OFF19(-1); - tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, label_index, 0); - } - tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) | - (0x5 << 19) | off19)); -} -#endif - static const uint8_t tcg_cond_to_bcond[] = { [TCG_COND_EQ] = COND_E, [TCG_COND_NE] = COND_NE, @@ -532,17 +502,36 @@ static const uint8_t tcg_cond_to_bcond[] = { [TCG_COND_GTU] = COND_GU, }; +static void tcg_out_bpcc0(TCGContext *s, int scond, int flags, int off19) +{ + tcg_out32(s, INSN_OP(0) | INSN_OP2(1) | INSN_COND(scond) | flags | off19); +} + +static void tcg_out_bpcc(TCGContext *s, int scond, int flags, int label) +{ + TCGLabel *l = &s->labels[label]; + int off19; + + if (l->has_value) { + off19 = INSN_OFF19(l->u.value - (unsigned long)s->code_ptr); + } else { + /* Make sure to preserve destinations during retranslation. */ + off19 = *(uint32_t *)s->code_ptr & INSN_OFF19(-1); + tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, label, 0); + } + tcg_out_bpcc0(s, scond, flags, off19); +} + static void tcg_out_cmp(TCGContext *s, TCGArg c1, TCGArg c2, int c2const) { tcg_out_arithc(s, TCG_REG_G0, c1, c2, c2const, ARITH_SUBCC); } -static void tcg_out_brcond_i32(TCGContext *s, TCGCond cond, - TCGArg arg1, TCGArg arg2, int const_arg2, - int label_index) +static void tcg_out_brcond_i32(TCGContext *s, TCGCond cond, TCGArg arg1, + TCGArg arg2, int const_arg2, int label) { tcg_out_cmp(s, arg1, arg2, const_arg2); - tcg_out_branch_i32(s, tcg_cond_to_bcond[cond], label_index); + tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_ICC | BPCC_PT, label); tcg_out_nop(s); } @@ -563,12 +552,11 @@ static void tcg_out_movcond_i32(TCGContext *s, TCGCond cond, TCGArg ret, } #if TCG_TARGET_REG_BITS == 64 -static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, - TCGArg arg1, TCGArg arg2, int const_arg2, - int label_index) +static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGArg arg1, + TCGArg arg2, int const_arg2, int label) { tcg_out_cmp(s, arg1, arg2, const_arg2); - tcg_out_branch_i64(s, tcg_cond_to_bcond[cond], label_index); + tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_XCC | BPCC_PT, label); tcg_out_nop(s); } @@ -585,32 +573,32 @@ static void tcg_out_brcond2_i32(TCGContext *s, TCGCond cond, TCGArg bl, int blconst, TCGArg bh, int bhconst, int label_dest) { - int cc, label_next = gen_new_label(); + int scond, label_next = gen_new_label(); tcg_out_cmp(s, ah, bh, bhconst); /* Note that we fill one of the delay slots with the second compare. */ switch (cond) { case TCG_COND_EQ: - tcg_out_branch_i32(s, COND_NE, label_next); + tcg_out_bpcc(s, COND_NE, BPCC_ICC | BPCC_PT, label_next); tcg_out_cmp(s, al, bl, blconst); - tcg_out_branch_i32(s, COND_E, label_dest); + tcg_out_bpcc(s, COND_E, BPCC_ICC | BPCC_PT, label_dest); break; case TCG_COND_NE: - tcg_out_branch_i32(s, COND_NE, label_dest); + tcg_out_bpcc(s, COND_NE, BPCC_ICC | BPCC_PT, label_dest); tcg_out_cmp(s, al, bl, blconst); - tcg_out_branch_i32(s, COND_NE, label_dest); + tcg_out_bpcc(s, COND_NE, BPCC_ICC | BPCC_PT, label_dest); break; default: - cc = tcg_cond_to_bcond[tcg_high_cond(cond)]; - tcg_out_branch_i32(s, cc, label_dest); + scond = tcg_cond_to_bcond[tcg_high_cond(cond)]; + tcg_out_bpcc(s, scond, BPCC_ICC | BPCC_PT, label_dest); tcg_out_nop(s); - tcg_out_branch_i32(s, COND_NE, label_next); + tcg_out_bpcc(s, COND_NE, BPCC_ICC | BPCC_PT, label_next); tcg_out_cmp(s, al, bl, blconst); - cc = tcg_cond_to_bcond[tcg_unsigned_cond(cond)]; - tcg_out_branch_i32(s, cc, label_dest); + scond = tcg_cond_to_bcond[tcg_unsigned_cond(cond)]; + tcg_out_bpcc(s, scond, BPCC_ICC | BPCC_PT, label_dest); break; } tcg_out_nop(s); @@ -903,8 +891,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop) /* bne,pn %[xi]cc, label0 */ label_ptr[0] = (uint32_t *)s->code_ptr; - tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_NE, 0) | INSN_OP2(0x1) - | ((TARGET_LONG_BITS == 64) << 21))); + tcg_out_bpcc0(s, COND_NE, BPCC_PN + | (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0); /* TLB Hit. */ /* Load all 64-bits into an O/G register. */ @@ -919,8 +907,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop) /* b,a,pt label1 */ label_ptr[1] = (uint32_t *)s->code_ptr; - tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x1) - | (1 << 29) | (1 << 19))); + tcg_out_bpcc0(s, COND_A, BPCC_A | BPCC_PT, 0); } else { /* The fast path is exactly one insn. Thus we can perform the entire TLB Hit in the (annulled) delay slot of the branch @@ -929,9 +916,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop) /* beq,a,pt %[xi]cc, label0 */ label_ptr[0] = NULL; label_ptr[1] = (uint32_t *)s->code_ptr; - tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1) - | ((TARGET_LONG_BITS == 64) << 21) - | (1 << 29) | (1 << 19))); + tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT + | (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0); /* delay slot */ tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_O1, qemu_ld_opc[sizeop]); } @@ -1050,9 +1036,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop) TLB Hit in the (annulled) delay slot of the branch over TLB Miss. */ /* beq,a,pt %[xi]cc, label0 */ label_ptr = (uint32_t *)s->code_ptr; - tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1) - | ((TARGET_LONG_BITS == 64) << 21) - | (1 << 29) | (1 << 19))); + tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT + | (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0); /* delay slot */ tcg_out_ldst_rr(s, datafull, addr_reg, TCG_REG_O1, qemu_st_opc[sizeop]); @@ -1143,7 +1128,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, tcg_out_nop(s); break; case INDEX_op_br: - tcg_out_branch_i32(s, COND_A, args[0]); + tcg_out_bpcc(s, COND_A, BPCC_PT, args[0]); tcg_out_nop(s); break; case INDEX_op_movi_i32: From 345ce423dd58b3ddc3cfbcbb1ca2eee25546e8be Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Oct 2012 09:02:45 -0700 Subject: [PATCH 0892/2270] tcg-sparc: Dump illegal opode contents Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- sparc-dis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sparc-dis.c b/sparc-dis.c index cdd337a738..1d017faaa3 100644 --- a/sparc-dis.c +++ b/sparc-dis.c @@ -3270,6 +3270,6 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info) } info->insn_type = dis_noninsn; /* Mark as non-valid instruction. */ - (*info->fprintf_func) (stream, _("unknown")); + (*info->fprintf_func) (stream, ".long %#08lx", insn); return sizeof (buffer); } From ab1339b9b40752d076ae9784ed07f14194f130bd Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Oct 2012 09:02:46 -0700 Subject: [PATCH 0893/2270] tcg-sparc: Emit BPr insns for brcond_i64 Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- tcg/sparc/tcg-target.c | 49 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index ab47c98378..3b18fceb6f 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -126,6 +126,7 @@ static const int tcg_target_call_oarg_regs[] = { #define INSN_IMM11(x) ((1 << 13) | ((x) & 0x7ff)) #define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff)) +#define INSN_OFF16(x) ((((x) >> 2) & 0x3fff) | ((((x) >> 16) & 3) << 20)) #define INSN_OFF19(x) (((x) >> 2) & 0x07ffff) #define INSN_COND(x) ((x) << 25) @@ -147,6 +148,13 @@ static const int tcg_target_call_oarg_regs[] = { #define COND_VC 0xf #define BA (INSN_OP(0) | INSN_COND(COND_A) | INSN_OP2(0x2)) +#define RCOND_Z 1 +#define RCOND_LEZ 2 +#define RCOND_LZ 3 +#define RCOND_NZ 5 +#define RCOND_GZ 6 +#define RCOND_GEZ 7 + #define MOVCC_ICC (1 << 18) #define MOVCC_XCC (1 << 18 | 1 << 12) @@ -156,6 +164,8 @@ static const int tcg_target_call_oarg_regs[] = { #define BPCC_PN 0 #define BPCC_A (1 << 29) +#define BPR_PT BPCC_PT + #define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00)) #define ARITH_ADDCC (INSN_OP(2) | INSN_OP3(0x10)) #define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01)) @@ -251,6 +261,16 @@ static void patch_reloc(uint8_t *code_ptr, int type, } *(uint32_t *)code_ptr = value; break; + case R_SPARC_WDISP16: + value -= (long)code_ptr; + if (!check_fit_tl(value >> 2, 16)) { + tcg_abort(); + } + insn = *(uint32_t *)code_ptr; + insn &= ~INSN_OFF16(-1); + insn |= INSN_OFF16(value); + *(uint32_t *)code_ptr = insn; + break; case R_SPARC_WDISP19: value -= (long)code_ptr; if (!check_fit_tl(value >> 2, 19)) { @@ -502,6 +522,15 @@ static const uint8_t tcg_cond_to_bcond[] = { [TCG_COND_GTU] = COND_GU, }; +static const uint8_t tcg_cond_to_rcond[] = { + [TCG_COND_EQ] = RCOND_Z, + [TCG_COND_NE] = RCOND_NZ, + [TCG_COND_LT] = RCOND_LZ, + [TCG_COND_GT] = RCOND_GZ, + [TCG_COND_LE] = RCOND_LEZ, + [TCG_COND_GE] = RCOND_GEZ +}; + static void tcg_out_bpcc0(TCGContext *s, int scond, int flags, int off19) { tcg_out32(s, INSN_OP(0) | INSN_OP2(1) | INSN_COND(scond) | flags | off19); @@ -555,8 +584,24 @@ static void tcg_out_movcond_i32(TCGContext *s, TCGCond cond, TCGArg ret, static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGArg arg1, TCGArg arg2, int const_arg2, int label) { - tcg_out_cmp(s, arg1, arg2, const_arg2); - tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_XCC | BPCC_PT, label); + /* For 64-bit signed comparisons vs zero, we can avoid the compare. */ + if (arg2 == 0 && !is_unsigned_cond(cond)) { + TCGLabel *l = &s->labels[label]; + int off16; + + if (l->has_value) { + off16 = INSN_OFF16(l->u.value - (unsigned long)s->code_ptr); + } else { + /* Make sure to preserve destinations during retranslation. */ + off16 = *(uint32_t *)s->code_ptr & INSN_OFF16(-1); + tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP16, label, 0); + } + tcg_out32(s, INSN_OP(0) | INSN_OP2(3) | BPR_PT | INSN_RS1(arg1) + | INSN_COND(tcg_cond_to_rcond[cond]) | off16); + } else { + tcg_out_cmp(s, arg1, arg2, const_arg2); + tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_XCC | BPCC_PT, label); + } tcg_out_nop(s); } From 203342d8dc852bc09488e9dc5b853aa48aeed14c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Oct 2012 09:02:47 -0700 Subject: [PATCH 0894/2270] tcg-sparc: Emit MOVR insns for setcond_i64 and movcond_64 Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- tcg/sparc/tcg-target.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 3b18fceb6f..f146647874 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -124,6 +124,7 @@ static const int tcg_target_call_oarg_regs[] = { #define INSN_RS2(x) (x) #define INSN_ASI(x) ((x) << 5) +#define INSN_IMM10(x) ((1 << 13) | ((x) & 0x3ff)) #define INSN_IMM11(x) ((1 << 13) | ((x) & 0x7ff)) #define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff)) #define INSN_OFF16(x) ((((x) >> 2) & 0x3fff) | ((((x) >> 16) & 3) << 20)) @@ -185,6 +186,7 @@ static const int tcg_target_call_oarg_regs[] = { #define ARITH_UDIVX (INSN_OP(2) | INSN_OP3(0x0d)) #define ARITH_SDIVX (INSN_OP(2) | INSN_OP3(0x2d)) #define ARITH_MOVCC (INSN_OP(2) | INSN_OP3(0x2c)) +#define ARITH_MOVR (INSN_OP(2) | INSN_OP3(0x2f)) #define SHIFT_SLL (INSN_OP(2) | INSN_OP3(0x25)) #define SHIFT_SRL (INSN_OP(2) | INSN_OP3(0x26)) @@ -605,12 +607,28 @@ static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGArg arg1, tcg_out_nop(s); } +static void tcg_out_movr(TCGContext *s, TCGCond cond, TCGArg ret, TCGArg c1, + TCGArg v1, int v1const) +{ + tcg_out32(s, ARITH_MOVR | INSN_RD(ret) | INSN_RS1(c1) + | (tcg_cond_to_rcond[cond] << 10) + | (v1const ? INSN_IMM10(v1) : INSN_RS2(v1))); +} + static void tcg_out_movcond_i64(TCGContext *s, TCGCond cond, TCGArg ret, TCGArg c1, TCGArg c2, int c2const, TCGArg v1, int v1const) { - tcg_out_cmp(s, c1, c2, c2const); - tcg_out_movcc(s, cond, MOVCC_XCC, ret, v1, v1const); + /* For 64-bit signed comparisons vs zero, we can avoid the compare. + Note that the immediate range is one bit smaller, so we must check + for that as well. */ + if (c2 == 0 && !is_unsigned_cond(cond) + && (!v1const || check_fit_tl(v1, 10))) { + tcg_out_movr(s, cond, ret, c1, v1, v1const); + } else { + tcg_out_cmp(s, c1, c2, c2const); + tcg_out_movcc(s, cond, MOVCC_XCC, ret, v1, v1const); + } } #else static void tcg_out_brcond2_i32(TCGContext *s, TCGCond cond, @@ -706,9 +724,16 @@ static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGArg ret, static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGArg ret, TCGArg c1, TCGArg c2, int c2const) { - tcg_out_cmp(s, c1, c2, c2const); - tcg_out_movi_imm13(s, ret, 0); - tcg_out_movcc(s, cond, MOVCC_XCC, ret, 1, 1); + /* For 64-bit signed comparisons vs zero, we can avoid the compare + if the input does not overlap the output. */ + if (c2 == 0 && !is_unsigned_cond(cond) && c1 != ret) { + tcg_out_movi_imm13(s, ret, 0); + tcg_out_movr(s, cond, ret, c1, 1, 1); + } else { + tcg_out_cmp(s, c1, c2, c2const); + tcg_out_movi_imm13(s, ret, 0); + tcg_out_movcc(s, cond, MOVCC_XCC, ret, 1, 1); + } } #else static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret, From e0bbf9b573e1a19a906abef861ee28293e44b3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 12 Oct 2012 04:23:04 +0200 Subject: [PATCH 0895/2270] sun4m: Pass SPARCCPU to cpu_set_irq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for changing cpu_kick_irq() argument type to SPARCCPU. Signed-off-by: Andreas Färber Signed-off-by: Blue Swirl --- hw/sun4m.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/sun4m.c b/hw/sun4m.c index c98cd5ec3f..c1ee8bd738 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -262,7 +262,8 @@ static void cpu_kick_irq(CPUSPARCState *env) static void cpu_set_irq(void *opaque, int irq, int level) { - CPUSPARCState *env = opaque; + SPARCCPU *cpu = opaque; + CPUSPARCState *env = &cpu->env; if (level) { trace_sun4m_cpu_set_irq_raise(irq); @@ -840,7 +841,7 @@ static void cpu_devinit(const char *cpu_model, unsigned int id, qemu_register_reset(secondary_cpu_reset, cpu); env->halted = 1; } - *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS); + *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS); env->prom_addr = prom_addr; } From 38c66cf2817366fd56af7cd2099a696d715365ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 12 Oct 2012 04:23:05 +0200 Subject: [PATCH 0896/2270] sun4m: Pass SPARCCPU to cpu_kick_irq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for changing qemu_cpu_kick() argument type to CPUState. Signed-off-by: Andreas Färber Signed-off-by: Blue Swirl --- hw/sun4m.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/sun4m.c b/hw/sun4m.c index c1ee8bd738..a04b485eda 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -253,8 +253,10 @@ void cpu_check_irqs(CPUSPARCState *env) } } -static void cpu_kick_irq(CPUSPARCState *env) +static void cpu_kick_irq(SPARCCPU *cpu) { + CPUSPARCState *env = &cpu->env; + env->halted = 0; cpu_check_irqs(env); qemu_cpu_kick(env); @@ -268,7 +270,7 @@ static void cpu_set_irq(void *opaque, int irq, int level) if (level) { trace_sun4m_cpu_set_irq_raise(irq); env->pil_in |= 1 << irq; - cpu_kick_irq(env); + cpu_kick_irq(cpu); } else { trace_sun4m_cpu_set_irq_lower(irq); env->pil_in &= ~(1 << irq); From 6b678e1f9b92e21ee2e2614440740ca76fc7d2d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 12 Oct 2012 04:23:06 +0200 Subject: [PATCH 0897/2270] sun4u: Pass SPARCCPU to {,s,hs}tick_irq() and cpu_timer_create() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for changing cpu_kick_irq() argument type to SPARCCPU. Signed-off-by: Andreas Färber Signed-off-by: Blue Swirl --- hw/sun4u.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/hw/sun4u.c b/hw/sun4u.c index 137a7c6666..4cea102cb3 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -366,7 +366,7 @@ void cpu_get_timer(QEMUFile *f, CPUTimer *s) qemu_get_timer(f, s->qtimer); } -static CPUTimer* cpu_timer_create(const char* name, CPUSPARCState *env, +static CPUTimer *cpu_timer_create(const char *name, SPARCCPU *cpu, QEMUBHFunc *cb, uint32_t frequency, uint64_t disabled_mask) { @@ -379,7 +379,7 @@ static CPUTimer* cpu_timer_create(const char* name, CPUSPARCState *env, timer->disabled = 1; timer->clock_offset = qemu_get_clock_ns(vm_clock); - timer->qtimer = qemu_new_timer_ns(vm_clock, cb, env); + timer->qtimer = qemu_new_timer_ns(vm_clock, cb, cpu); return timer; } @@ -418,7 +418,8 @@ static void main_cpu_reset(void *opaque) static void tick_irq(void *opaque) { - CPUSPARCState *env = opaque; + SPARCCPU *cpu = opaque; + CPUSPARCState *env = &cpu->env; CPUTimer* timer = env->tick; @@ -435,7 +436,8 @@ static void tick_irq(void *opaque) static void stick_irq(void *opaque) { - CPUSPARCState *env = opaque; + SPARCCPU *cpu = opaque; + CPUSPARCState *env = &cpu->env; CPUTimer* timer = env->stick; @@ -452,7 +454,8 @@ static void stick_irq(void *opaque) static void hstick_irq(void *opaque) { - CPUSPARCState *env = opaque; + SPARCCPU *cpu = opaque; + CPUSPARCState *env = &cpu->env; CPUTimer* timer = env->hstick; @@ -772,13 +775,13 @@ static SPARCCPU *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef) } env = &cpu->env; - env->tick = cpu_timer_create("tick", env, tick_irq, + env->tick = cpu_timer_create("tick", cpu, tick_irq, tick_frequency, TICK_NPT_MASK); - env->stick = cpu_timer_create("stick", env, stick_irq, + env->stick = cpu_timer_create("stick", cpu, stick_irq, stick_frequency, TICK_INT_DIS); - env->hstick = cpu_timer_create("hstick", env, hstick_irq, + env->hstick = cpu_timer_create("hstick", cpu, hstick_irq, hstick_frequency, TICK_INT_DIS); reset_info = g_malloc0(sizeof(ResetData)); From ce18c558f08ea392b2ec79046eb40e791be5fc88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 12 Oct 2012 04:23:07 +0200 Subject: [PATCH 0898/2270] sun4u: Pass SPARCCPU to cpu_kick_irq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for changing qemu_cpu_kick() argument type to CPUState. Signed-off-by: Andreas Färber Signed-off-by: Blue Swirl --- hw/sun4u.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/hw/sun4u.c b/hw/sun4u.c index 4cea102cb3..045352277e 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -310,8 +310,10 @@ void cpu_check_irqs(CPUSPARCState *env) } } -static void cpu_kick_irq(CPUSPARCState *env) +static void cpu_kick_irq(SPARCCPU *cpu) { + CPUSPARCState *env = &cpu->env; + env->halted = 0; cpu_check_irqs(env); qemu_cpu_kick(env); @@ -431,7 +433,7 @@ static void tick_irq(void *opaque) } env->softint |= SOFTINT_TIMER; - cpu_kick_irq(env); + cpu_kick_irq(cpu); } static void stick_irq(void *opaque) @@ -449,7 +451,7 @@ static void stick_irq(void *opaque) } env->softint |= SOFTINT_STIMER; - cpu_kick_irq(env); + cpu_kick_irq(cpu); } static void hstick_irq(void *opaque) @@ -467,7 +469,7 @@ static void hstick_irq(void *opaque) } env->softint |= SOFTINT_STIMER; - cpu_kick_irq(env); + cpu_kick_irq(cpu); } static int64_t cpu_to_timer_ticks(int64_t cpu_ticks, uint32_t frequency) From b64ba4b232e776d891a7a5137a6129221b6a9cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 12 Oct 2012 04:23:08 +0200 Subject: [PATCH 0899/2270] sun4u: Pass SPARCCPU to cpu_set_ivec_irq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for moving halted field to CPUState. Signed-off-by: Andreas Färber Signed-off-by: Blue Swirl --- hw/sun4u.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/hw/sun4u.c b/hw/sun4u.c index 045352277e..940db3348a 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -321,7 +321,8 @@ static void cpu_kick_irq(SPARCCPU *cpu) static void cpu_set_ivec_irq(void *opaque, int irq, int level) { - CPUSPARCState *env = opaque; + SPARCCPU *cpu = opaque; + CPUSPARCState *env = &cpu->env; if (level) { if (!(env->ivec_status & 0x20)) { @@ -802,7 +803,6 @@ static void sun4uv_init(MemoryRegion *address_space_mem, const struct hwdef *hwdef) { SPARCCPU *cpu; - CPUSPARCState *env; M48t59State *nvram; unsigned int i; uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry; @@ -815,14 +815,13 @@ static void sun4uv_init(MemoryRegion *address_space_mem, /* init CPUs */ cpu = cpu_devinit(cpu_model, hwdef); - env = &cpu->env; /* set up devices */ ram_init(0, RAM_size); prom_init(hwdef->prom_addr, bios_name); - ivec_irqs = qemu_allocate_irqs(cpu_set_ivec_irq, env, IVEC_MAX); + ivec_irqs = qemu_allocate_irqs(cpu_set_ivec_irq, cpu, IVEC_MAX); pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_bus2, &pci_bus3, &pbm_irqs); pci_vga_init(pci_bus); From 8b4a3df8081f3e6f1061ed5cbb303ad623ade66b Mon Sep 17 00:00:00 2001 From: malc Date: Sun, 14 Oct 2012 14:54:38 +0400 Subject: [PATCH 0900/2270] Fix popcnt in long mode Thanks to Andriy Gapon for initial problem report. Signed-off-by: malc --- target-i386/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-i386/translate.c b/target-i386/translate.c index 0a7e4e3487..ee7585044b 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -7768,7 +7768,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) goto illegal_op; modrm = cpu_ldub_code(cpu_single_env, s->pc++); - reg = ((modrm >> 3) & 7); + reg = ((modrm >> 3) & 7) | rex_r; if (s->prefix & PREFIX_DATA) ot = OT_WORD; From 7762c2c1e02e44fdc473cbe75105faba08b906cc Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 20 Sep 2012 16:02:51 +0300 Subject: [PATCH 0901/2270] memory: rename 'exec-obsolete.h' exec-obsolete.h used to hold pre-memory-API functions that were used from device code prior to the transition to the memory API. Now that the transition is complete, the name no longer describes the file. The functions still need to be merged better into the memory core, but there's no danger of anyone using them. Reviewed-by: Anthony Liguori Signed-off-by: Avi Kivity --- cputlb.c | 3 +-- exec.c | 3 +-- exec-obsolete.h => memory-internal.h | 8 ++------ memory.c | 3 +-- 4 files changed, 5 insertions(+), 12 deletions(-) rename exec-obsolete.h => memory-internal.h (97%) diff --git a/cputlb.c b/cputlb.c index 51b5897d37..0627f32e35 100644 --- a/cputlb.c +++ b/cputlb.c @@ -24,8 +24,7 @@ #include "cputlb.h" -#define WANT_EXEC_OBSOLETE -#include "exec-obsolete.h" +#include "memory-internal.h" //#define DEBUG_TLB //#define DEBUG_TLB_CHECK diff --git a/exec.c b/exec.c index 7899042ce9..eb0ec93f9a 100644 --- a/exec.c +++ b/exec.c @@ -59,8 +59,7 @@ #include "cputlb.h" -#define WANT_EXEC_OBSOLETE -#include "exec-obsolete.h" +#include "memory-internal.h" //#define DEBUG_TB_INVALIDATE //#define DEBUG_FLUSH diff --git a/exec-obsolete.h b/memory-internal.h similarity index 97% rename from exec-obsolete.h rename to memory-internal.h index 286e2f75e1..43fa886264 100644 --- a/exec-obsolete.h +++ b/memory-internal.h @@ -16,12 +16,8 @@ * The functions declared here will be removed soon. */ -#ifndef EXEC_OBSOLETE_H -#define EXEC_OBSOLETE_H - -#ifndef WANT_EXEC_OBSOLETE -#error Do not include exec-obsolete.h -#endif +#ifndef MEMORY_INTERNAL_H +#define MEMORY_INTERNAL_H #ifndef CONFIG_USER_ONLY #include "hw/xen.h" diff --git a/memory.c b/memory.c index 4f3ade06dd..1aeca08dda 100644 --- a/memory.c +++ b/memory.c @@ -20,8 +20,7 @@ #include "kvm.h" #include -#define WANT_EXEC_OBSOLETE -#include "exec-obsolete.h" +#include "memory-internal.h" unsigned memory_region_transaction_depth = 0; static bool global_dirty_log = false; From 0fada67420e29f389119ca6f44285203400e0730 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 30 Sep 2012 22:02:53 +0200 Subject: [PATCH 0902/2270] vhost: use MemoryListener filtering to only monitor RAM address space Instead of checking manually, let the listener filter for us. This prepares us for DMA address spaces. Signed-off-by: Avi Kivity --- hw/vhost.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/vhost.c b/hw/vhost.c index d0ce5aad9b..100f7659a0 100644 --- a/hw/vhost.c +++ b/hw/vhost.c @@ -434,8 +434,7 @@ static void vhost_set_memory(MemoryListener *listener, static bool vhost_section(MemoryRegionSection *section) { - return section->address_space == get_system_memory() - && memory_region_is_ram(section->mr); + return memory_region_is_ram(section->mr); } static void vhost_begin(MemoryListener *listener) @@ -793,7 +792,7 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, const char *devpath, hdev->log_size = 0; hdev->log_enabled = false; hdev->started = false; - memory_listener_register(&hdev->memory_listener, NULL); + memory_listener_register(&hdev->memory_listener, get_system_memory()); hdev->force = force; return 0; fail: From d22b096ef6e0b20810193b68a1d472f3fb8a4f9e Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 30 Sep 2012 22:21:11 +0200 Subject: [PATCH 0903/2270] kvm: use separate MemoryListeners for memory and I/O The construct if (address_space == get_system_memory()) { // memory thing } else { // io thing } fails if we have more than two address spaces. Use a separate listener for memory and I/O, and utilize MemoryListener's address space filtering to fix this. Signed-off-by: Avi Kivity --- kvm-all.c | 83 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 39 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index 92a71374ed..c69e012004 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -755,9 +755,16 @@ static void kvm_log_global_stop(struct MemoryListener *listener) assert(r >= 0); } -static void kvm_mem_ioeventfd_add(MemoryRegionSection *section, - bool match_data, uint64_t data, int fd) +static void kvm_log_nop(struct MemoryListener *listener) { +} + +static void kvm_mem_ioeventfd_add(MemoryListener *listener, + MemoryRegionSection *section, + bool match_data, uint64_t data, + EventNotifier *e) +{ + int fd = event_notifier_get_fd(e); int r; assert(match_data && section->size <= 8); @@ -769,9 +776,12 @@ static void kvm_mem_ioeventfd_add(MemoryRegionSection *section, } } -static void kvm_mem_ioeventfd_del(MemoryRegionSection *section, - bool match_data, uint64_t data, int fd) +static void kvm_mem_ioeventfd_del(MemoryListener *listener, + MemoryRegionSection *section, + bool match_data, uint64_t data, + EventNotifier *e) { + int fd = event_notifier_get_fd(e); int r; r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space, @@ -781,9 +791,12 @@ static void kvm_mem_ioeventfd_del(MemoryRegionSection *section, } } -static void kvm_io_ioeventfd_add(MemoryRegionSection *section, - bool match_data, uint64_t data, int fd) +static void kvm_io_ioeventfd_add(MemoryListener *listener, + MemoryRegionSection *section, + bool match_data, uint64_t data, + EventNotifier *e) { + int fd = event_notifier_get_fd(e); int r; assert(match_data && section->size == 2); @@ -795,10 +808,13 @@ static void kvm_io_ioeventfd_add(MemoryRegionSection *section, } } -static void kvm_io_ioeventfd_del(MemoryRegionSection *section, - bool match_data, uint64_t data, int fd) +static void kvm_io_ioeventfd_del(MemoryListener *listener, + MemoryRegionSection *section, + bool match_data, uint64_t data, + EventNotifier *e) { + int fd = event_notifier_get_fd(e); int r; r = kvm_set_ioeventfd_pio_word(fd, section->offset_within_address_space, @@ -808,34 +824,6 @@ static void kvm_io_ioeventfd_del(MemoryRegionSection *section, } } -static void kvm_eventfd_add(MemoryListener *listener, - MemoryRegionSection *section, - bool match_data, uint64_t data, - EventNotifier *e) -{ - if (section->address_space == get_system_memory()) { - kvm_mem_ioeventfd_add(section, match_data, data, - event_notifier_get_fd(e)); - } else { - kvm_io_ioeventfd_add(section, match_data, data, - event_notifier_get_fd(e)); - } -} - -static void kvm_eventfd_del(MemoryListener *listener, - MemoryRegionSection *section, - bool match_data, uint64_t data, - EventNotifier *e) -{ - if (section->address_space == get_system_memory()) { - kvm_mem_ioeventfd_del(section, match_data, data, - event_notifier_get_fd(e)); - } else { - kvm_io_ioeventfd_del(section, match_data, data, - event_notifier_get_fd(e)); - } -} - static MemoryListener kvm_memory_listener = { .begin = kvm_begin, .commit = kvm_commit, @@ -847,8 +835,24 @@ static MemoryListener kvm_memory_listener = { .log_sync = kvm_log_sync, .log_global_start = kvm_log_global_start, .log_global_stop = kvm_log_global_stop, - .eventfd_add = kvm_eventfd_add, - .eventfd_del = kvm_eventfd_del, + .eventfd_add = kvm_mem_ioeventfd_add, + .eventfd_del = kvm_mem_ioeventfd_del, + .priority = 10, +}; + +static MemoryListener kvm_io_listener = { + .begin = kvm_begin, + .commit = kvm_commit, + .region_add = kvm_region_nop, + .region_del = kvm_region_nop, + .region_nop = kvm_region_nop, + .log_start = kvm_region_nop, + .log_stop = kvm_region_nop, + .log_sync = kvm_region_nop, + .log_global_start = kvm_log_nop, + .log_global_stop = kvm_log_nop, + .eventfd_add = kvm_io_ioeventfd_add, + .eventfd_del = kvm_io_ioeventfd_del, .priority = 10, }; @@ -1401,7 +1405,8 @@ int kvm_init(void) } kvm_state = s; - memory_listener_register(&kvm_memory_listener, NULL); + memory_listener_register(&kvm_memory_listener, get_system_memory()); + memory_listener_register(&kvm_io_listener, get_system_io()); s->many_ioeventfds = kvm_check_many_ioeventfds(); From 12b40e471f33e552fa3d962887b416cf67831446 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 30 Sep 2012 22:21:11 +0200 Subject: [PATCH 0904/2270] xen_pt: use separate MemoryListeners for memory and I/O Using an unfiltered memory listener will cause regions to be reported fails multiple times if we have more than two address spaces. Use a separate listener for memory and I/O, and utilize MemoryListener's address space filtering to fix this. Signed-off-by: Avi Kivity --- hw/xen_pt.c | 38 +++++++++++++++++++++++++++++++++++++- hw/xen_pt.h | 1 + 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/hw/xen_pt.c b/hw/xen_pt.c index 838bcea4d6..4f90ad9e7a 100644 --- a/hw/xen_pt.c +++ b/hw/xen_pt.c @@ -59,6 +59,7 @@ #include "xen_backend.h" #include "xen_pt.h" #include "range.h" +#include "exec-memory.h" #define XEN_PT_NR_IRQS (256) static uint8_t xen_pt_mapped_machine_irq[XEN_PT_NR_IRQS] = {0}; @@ -624,6 +625,22 @@ static void xen_pt_region_del(MemoryListener *l, MemoryRegionSection *sec) xen_pt_region_update(s, sec, false); } +static void xen_pt_io_region_add(MemoryListener *l, MemoryRegionSection *sec) +{ + XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState, + io_listener); + + xen_pt_region_update(s, sec, true); +} + +static void xen_pt_io_region_del(MemoryListener *l, MemoryRegionSection *sec) +{ + XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState, + io_listener); + + xen_pt_region_update(s, sec, false); +} + static void xen_pt_region_nop(MemoryListener *l, MemoryRegionSection *s) { } @@ -657,6 +674,22 @@ static const MemoryListener xen_pt_memory_listener = { .priority = 10, }; +static const MemoryListener xen_pt_io_listener = { + .begin = xen_pt_begin, + .commit = xen_pt_commit, + .region_add = xen_pt_io_region_add, + .region_nop = xen_pt_region_nop, + .region_del = xen_pt_io_region_del, + .log_start = xen_pt_log_fns, + .log_stop = xen_pt_log_fns, + .log_sync = xen_pt_log_fns, + .log_global_start = xen_pt_log_global_fns, + .log_global_stop = xen_pt_log_global_fns, + .eventfd_add = xen_pt_eventfd_fns, + .eventfd_del = xen_pt_eventfd_fns, + .priority = 10, +}; + /* init */ static int xen_pt_initfn(PCIDevice *d) @@ -694,6 +727,7 @@ static int xen_pt_initfn(PCIDevice *d) } s->memory_listener = xen_pt_memory_listener; + s->io_listener = xen_pt_io_listener; /* Handle real device's MMIO/PIO BARs */ xen_pt_register_regions(s); @@ -760,7 +794,8 @@ static int xen_pt_initfn(PCIDevice *d) } out: - memory_listener_register(&s->memory_listener, NULL); + memory_listener_register(&s->memory_listener, get_system_memory()); + memory_listener_register(&s->io_listener, get_system_io()); XEN_PT_LOG(d, "Real physical device %02x:%02x.%d registered successfuly!\n", bus, slot, func); @@ -815,6 +850,7 @@ static void xen_pt_unregister_device(PCIDevice *d) xen_pt_unregister_regions(s); memory_listener_unregister(&s->memory_listener); + memory_listener_unregister(&s->io_listener); xen_host_pci_device_put(&s->real_device); } diff --git a/hw/xen_pt.h b/hw/xen_pt.h index 112477a881..f15e69a290 100644 --- a/hw/xen_pt.h +++ b/hw/xen_pt.h @@ -209,6 +209,7 @@ struct XenPCIPassthroughState { MemoryRegion rom; MemoryListener memory_listener; + MemoryListener io_listener; }; int xen_pt_config_init(XenPCIPassthroughState *s); From 8786db7cb96f8ce5c75c6e1e074319c9dca8d356 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 13:53:41 +0200 Subject: [PATCH 0905/2270] memory: prepare AddressSpace for exporting AddressSpace contains a member, current_map, of type FlatView. Since we want to limit the leakage of internal types to public headers, switch to a pointer to a FlatView. There is no performance impact as this isn't used during lookups, only address space reconfigurations. Reviewed-by: Anthony Liguori Signed-off-by: Avi Kivity --- memory.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/memory.c b/memory.c index 1aeca08dda..7e9e373a8c 100644 --- a/memory.c +++ b/memory.c @@ -222,7 +222,7 @@ typedef struct AddressSpaceOps AddressSpaceOps; /* A system address space - I/O, memory, etc. */ struct AddressSpace { MemoryRegion *root; - FlatView current_map; + FlatView *current_map; int ioeventfd_nb; MemoryRegionIoeventfd *ioeventfds; }; @@ -631,7 +631,7 @@ static void address_space_update_ioeventfds(AddressSpace *as) AddrRange tmp; unsigned i; - FOR_EACH_FLAT_RANGE(fr, &as->current_map) { + FOR_EACH_FLAT_RANGE(fr, as->current_map) { for (i = 0; i < fr->mr->ioeventfd_nb; ++i) { tmp = addrrange_shift(fr->mr->ioeventfds[i].addr, int128_sub(fr->addr.start, @@ -719,13 +719,13 @@ static void address_space_update_topology_pass(AddressSpace *as, static void address_space_update_topology(AddressSpace *as) { - FlatView old_view = as->current_map; + FlatView old_view = *as->current_map; FlatView new_view = generate_memory_topology(as->root); address_space_update_topology_pass(as, old_view, new_view, false); address_space_update_topology_pass(as, old_view, new_view, true); - as->current_map = new_view; + *as->current_map = new_view; flatview_destroy(&old_view); address_space_update_ioeventfds(as); } @@ -1083,7 +1083,7 @@ void memory_region_sync_dirty_bitmap(MemoryRegion *mr) { FlatRange *fr; - FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) { + FOR_EACH_FLAT_RANGE(fr, address_space_memory.current_map) { if (fr->mr == mr) { MEMORY_LISTENER_UPDATE_REGION(fr, &address_space_memory, Forward, log_sync); @@ -1135,7 +1135,7 @@ static void memory_region_update_coalesced_range(MemoryRegion *mr) CoalescedMemoryRange *cmr; AddrRange tmp; - FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) { + FOR_EACH_FLAT_RANGE(fr, address_space_memory.current_map) { if (fr->mr == mr) { qemu_unregister_coalesced_mmio(int128_get64(fr->addr.start), int128_get64(fr->addr.size)); @@ -1399,7 +1399,7 @@ static int cmp_flatrange_addr(const void *addr_, const void *fr_) static FlatRange *address_space_lookup(AddressSpace *as, AddrRange addr) { - return bsearch(&addr, as->current_map.ranges, as->current_map.nr, + return bsearch(&addr, as->current_map->ranges, as->current_map->nr, sizeof(FlatRange), cmp_flatrange_addr); } @@ -1416,7 +1416,7 @@ MemoryRegionSection memory_region_find(MemoryRegion *address_space, return ret; } - while (fr > as->current_map.ranges + while (fr > as->current_map->ranges && addrrange_intersects(fr[-1].addr, range)) { --fr; } @@ -1437,7 +1437,7 @@ void memory_global_sync_dirty_bitmap(MemoryRegion *address_space) AddressSpace *as = memory_region_to_address_space(address_space); FlatRange *fr; - FOR_EACH_FLAT_RANGE(fr, &as->current_map) { + FOR_EACH_FLAT_RANGE(fr, as->current_map) { MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync); } } @@ -1459,6 +1459,10 @@ static void listener_add_address_space(MemoryListener *listener, { FlatRange *fr; + if (!as->root) { + return; + } + if (listener->address_space_filter && listener->address_space_filter != as->root) { return; @@ -1467,7 +1471,7 @@ static void listener_add_address_space(MemoryListener *listener, if (global_dirty_log) { listener->log_global_start(listener); } - FOR_EACH_FLAT_RANGE(fr, &as->current_map) { + FOR_EACH_FLAT_RANGE(fr, as->current_map) { MemoryRegionSection section = { .mr = fr->mr, .address_space = as->root, @@ -1506,18 +1510,23 @@ void memory_listener_unregister(MemoryListener *listener) QTAILQ_REMOVE(&memory_listeners, listener, link); } -void set_system_memory_map(MemoryRegion *mr) +static void address_space_init(AddressSpace *as, MemoryRegion *root) { memory_region_transaction_begin(); - address_space_memory.root = mr; + as->root = root; + as->current_map = g_new(FlatView, 1); + flatview_init(as->current_map); memory_region_transaction_commit(); } +void set_system_memory_map(MemoryRegion *mr) +{ + address_space_init(&address_space_memory, mr); +} + void set_system_io_map(MemoryRegion *mr) { - memory_region_transaction_begin(); - address_space_io.root = mr; - memory_region_transaction_commit(); + address_space_init(&address_space_io, mr); } uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size) From 9ad2bbc16788d3048d514f3450d0975e59d46119 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 14:59:23 +0200 Subject: [PATCH 0906/2270] memory: export AddressSpace The DMA API will use an AddressSpace to differentiate among different initiators. Reviewed-by: Anthony Liguori Signed-off-by: Avi Kivity --- memory.c | 11 +---------- memory.h | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/memory.c b/memory.c index 7e9e373a8c..431a8672a2 100644 --- a/memory.c +++ b/memory.c @@ -216,17 +216,8 @@ struct FlatView { unsigned nr_allocated; }; -typedef struct AddressSpace AddressSpace; typedef struct AddressSpaceOps AddressSpaceOps; -/* A system address space - I/O, memory, etc. */ -struct AddressSpace { - MemoryRegion *root; - FlatView *current_map; - int ioeventfd_nb; - MemoryRegionIoeventfd *ioeventfds; -}; - #define FOR_EACH_FLAT_RANGE(var, view) \ for (var = (view)->ranges; var < (view)->ranges + (view)->nr; ++var) @@ -1510,7 +1501,7 @@ void memory_listener_unregister(MemoryListener *listener) QTAILQ_REMOVE(&memory_listeners, listener, link); } -static void address_space_init(AddressSpace *as, MemoryRegion *root) +void address_space_init(AddressSpace *as, MemoryRegion *root) { memory_region_transaction_begin(); as->root = root; diff --git a/memory.h b/memory.h index 37ce1517ca..a1d75e761c 100644 --- a/memory.h +++ b/memory.h @@ -157,6 +157,19 @@ struct MemoryRegionPortio { #define PORTIO_END_OF_LIST() { } +typedef struct AddressSpace AddressSpace; + +/** + * AddressSpace: describes a mapping of addresses to #MemoryRegion objects + */ +struct AddressSpace { + /* All fields are private. */ + MemoryRegion *root; + struct FlatView *current_map; + int ioeventfd_nb; + struct MemoryRegionIoeventfd *ioeventfds; +}; + typedef struct MemoryRegionSection MemoryRegionSection; /** @@ -776,6 +789,14 @@ void memory_global_dirty_log_stop(void); void mtree_info(fprintf_function mon_printf, void *f); +/** + * address_space_init: initializes an address space + * + * @as: an uninitialized #AddressSpace + * @root: a #MemoryRegion that routes addesses for the address space + */ +void address_space_init(AddressSpace *as, MemoryRegion *root); + #endif #endif From 0d673e36a74d366ce090ab096955317b581c0fb0 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 15:28:50 +0200 Subject: [PATCH 0907/2270] memory: maintain a list of address spaces Instead of embedding knowledge of the memory and I/O address spaces in the memory core, maintain a list of all address spaces. This list will later be extended dynamically for other bus masters. Reviewed-by: Anthony Liguori Signed-off-by: Avi Kivity --- memory.c | 75 ++++++++++++++++++++++++++++++++++---------------------- memory.h | 2 ++ 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/memory.c b/memory.c index 431a8672a2..b58b97ccdd 100644 --- a/memory.c +++ b/memory.c @@ -28,6 +28,9 @@ static bool global_dirty_log = false; static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners = QTAILQ_HEAD_INITIALIZER(memory_listeners); +static QTAILQ_HEAD(, AddressSpace) address_spaces + = QTAILQ_HEAD_INITIALIZER(address_spaces); + typedef struct AddrRange AddrRange; /* @@ -449,14 +452,15 @@ static AddressSpace address_space_io; static AddressSpace *memory_region_to_address_space(MemoryRegion *mr) { + AddressSpace *as; + while (mr->parent) { mr = mr->parent; } - if (mr == address_space_memory.root) { - return &address_space_memory; - } - if (mr == address_space_io.root) { - return &address_space_io; + QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { + if (mr == as->root) { + return as; + } } abort(); } @@ -729,16 +733,15 @@ void memory_region_transaction_begin(void) void memory_region_transaction_commit(void) { + AddressSpace *as; + assert(memory_region_transaction_depth); --memory_region_transaction_depth; if (!memory_region_transaction_depth) { MEMORY_LISTENER_CALL_GLOBAL(begin, Forward); - if (address_space_memory.root) { - address_space_update_topology(&address_space_memory); - } - if (address_space_io.root) { - address_space_update_topology(&address_space_io); + QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { + address_space_update_topology(as); } MEMORY_LISTENER_CALL_GLOBAL(commit, Forward); @@ -1072,12 +1075,14 @@ void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr, void memory_region_sync_dirty_bitmap(MemoryRegion *mr) { + AddressSpace *as; FlatRange *fr; - FOR_EACH_FLAT_RANGE(fr, address_space_memory.current_map) { - if (fr->mr == mr) { - MEMORY_LISTENER_UPDATE_REGION(fr, &address_space_memory, - Forward, log_sync); + QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { + FOR_EACH_FLAT_RANGE(fr, as->current_map) { + if (fr->mr == mr) { + MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync); + } } } } @@ -1120,13 +1125,13 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr) return qemu_get_ram_ptr(mr->ram_addr & TARGET_PAGE_MASK); } -static void memory_region_update_coalesced_range(MemoryRegion *mr) +static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpace *as) { FlatRange *fr; CoalescedMemoryRange *cmr; AddrRange tmp; - FOR_EACH_FLAT_RANGE(fr, address_space_memory.current_map) { + FOR_EACH_FLAT_RANGE(fr, as->current_map) { if (fr->mr == mr) { qemu_unregister_coalesced_mmio(int128_get64(fr->addr.start), int128_get64(fr->addr.size)); @@ -1145,6 +1150,15 @@ static void memory_region_update_coalesced_range(MemoryRegion *mr) } } +static void memory_region_update_coalesced_range(MemoryRegion *mr) +{ + AddressSpace *as; + + QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { + memory_region_update_coalesced_range_as(mr, as); + } +} + void memory_region_set_coalescing(MemoryRegion *mr) { memory_region_clear_coalescing(mr); @@ -1450,10 +1464,6 @@ static void listener_add_address_space(MemoryListener *listener, { FlatRange *fr; - if (!as->root) { - return; - } - if (listener->address_space_filter && listener->address_space_filter != as->root) { return; @@ -1478,6 +1488,7 @@ static void listener_add_address_space(MemoryListener *listener, void memory_listener_register(MemoryListener *listener, MemoryRegion *filter) { MemoryListener *other = NULL; + AddressSpace *as; listener->address_space_filter = filter; if (QTAILQ_EMPTY(&memory_listeners) @@ -1492,8 +1503,10 @@ void memory_listener_register(MemoryListener *listener, MemoryRegion *filter) } QTAILQ_INSERT_BEFORE(other, listener, link); } - listener_add_address_space(listener, &address_space_memory); - listener_add_address_space(listener, &address_space_io); + + QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { + listener_add_address_space(listener, as); + } } void memory_listener_unregister(MemoryListener *listener) @@ -1507,17 +1520,21 @@ void address_space_init(AddressSpace *as, MemoryRegion *root) as->root = root; as->current_map = g_new(FlatView, 1); flatview_init(as->current_map); + QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link); + as->name = NULL; memory_region_transaction_commit(); } void set_system_memory_map(MemoryRegion *mr) { address_space_init(&address_space_memory, mr); + address_space_memory.name = "memory"; } void set_system_io_map(MemoryRegion *mr) { address_space_init(&address_space_io, mr); + address_space_io.name = "I/O"; } uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size) @@ -1637,16 +1654,16 @@ void mtree_info(fprintf_function mon_printf, void *f) { MemoryRegionListHead ml_head; MemoryRegionList *ml, *ml2; + AddressSpace *as; QTAILQ_INIT(&ml_head); - mon_printf(f, "memory\n"); - mtree_print_mr(mon_printf, f, address_space_memory.root, 0, 0, &ml_head); - - if (address_space_io.root && - !QTAILQ_EMPTY(&address_space_io.root->subregions)) { - mon_printf(f, "I/O\n"); - mtree_print_mr(mon_printf, f, address_space_io.root, 0, 0, &ml_head); + QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { + if (!as->name) { + continue; + } + mon_printf(f, "%s\n", as->name); + mtree_print_mr(mon_printf, f, as->root, 0, 0, &ml_head); } mon_printf(f, "aliases\n"); diff --git a/memory.h b/memory.h index a1d75e761c..46bc5e1cfd 100644 --- a/memory.h +++ b/memory.h @@ -164,10 +164,12 @@ typedef struct AddressSpace AddressSpace; */ struct AddressSpace { /* All fields are private. */ + const char *name; MemoryRegion *root; struct FlatView *current_map; int ioeventfd_nb; struct MemoryRegionIoeventfd *ioeventfds; + QTAILQ_ENTRY(AddressSpace) address_spaces_link; }; typedef struct MemoryRegionSection MemoryRegionSection; From 975aefe011197453284a4ab777000183e6096d5b Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 16:39:57 +0200 Subject: [PATCH 0908/2270] memory: provide defaults for MemoryListener operations Many listeners don't need to respond to all MemoryListener callbacks; provide suitable no-op defaults instead. Signed-off-by: Avi Kivity --- memory.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/memory.c b/memory.c index b58b97ccdd..269af3f6b0 100644 --- a/memory.c +++ b/memory.c @@ -99,13 +99,17 @@ static bool memory_listener_match(MemoryListener *listener, switch (_direction) { \ case Forward: \ QTAILQ_FOREACH(_listener, &memory_listeners, link) { \ - _listener->_callback(_listener, ##_args); \ + if (_listener->_callback) { \ + _listener->_callback(_listener, ##_args); \ + } \ } \ break; \ case Reverse: \ QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners, \ memory_listeners, link) { \ - _listener->_callback(_listener, ##_args); \ + if (_listener->_callback) { \ + _listener->_callback(_listener, ##_args); \ + } \ } \ break; \ default: \ @@ -120,7 +124,8 @@ static bool memory_listener_match(MemoryListener *listener, switch (_direction) { \ case Forward: \ QTAILQ_FOREACH(_listener, &memory_listeners, link) { \ - if (memory_listener_match(_listener, _section)) { \ + if (_listener->_callback \ + && memory_listener_match(_listener, _section)) { \ _listener->_callback(_listener, _section, ##_args); \ } \ } \ @@ -128,7 +133,8 @@ static bool memory_listener_match(MemoryListener *listener, case Reverse: \ QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners, \ memory_listeners, link) { \ - if (memory_listener_match(_listener, _section)) { \ + if (_listener->_callback \ + && memory_listener_match(_listener, _section)) { \ _listener->_callback(_listener, _section, ##_args); \ } \ } \ @@ -1470,8 +1476,11 @@ static void listener_add_address_space(MemoryListener *listener, } if (global_dirty_log) { - listener->log_global_start(listener); + if (listener->log_global_start) { + listener->log_global_start(listener); + } } + FOR_EACH_FLAT_RANGE(fr, as->current_map) { MemoryRegionSection section = { .mr = fr->mr, @@ -1481,7 +1490,9 @@ static void listener_add_address_space(MemoryListener *listener, .offset_within_address_space = int128_get64(fr->addr.start), .readonly = fr->readonly, }; - listener->region_add(listener, §ion); + if (listener->region_add) { + listener->region_add(listener, §ion); + } } } From 9a2c913b77b54f650d60680d14b995bacbc63e50 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 16:42:23 +0200 Subject: [PATCH 0909/2270] memory: drop no-op MemoryListener callbacks Removes quite a bit of useless code. Signed-off-by: Avi Kivity --- exec.c | 96 ---------------------------------------------------------- 1 file changed, 96 deletions(-) diff --git a/exec.c b/exec.c index eb0ec93f9a..6558728d09 100644 --- a/exec.c +++ b/exec.c @@ -3194,32 +3194,12 @@ static void core_region_add(MemoryListener *listener, cpu_register_physical_memory_log(section, section->readonly); } -static void core_region_del(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - static void core_region_nop(MemoryListener *listener, MemoryRegionSection *section) { cpu_register_physical_memory_log(section, section->readonly); } -static void core_log_start(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - -static void core_log_stop(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - -static void core_log_sync(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - static void core_log_global_start(MemoryListener *listener) { cpu_physical_memory_set_dirty_tracking(1); @@ -3230,26 +3210,6 @@ static void core_log_global_stop(MemoryListener *listener) cpu_physical_memory_set_dirty_tracking(0); } -static void core_eventfd_add(MemoryListener *listener, - MemoryRegionSection *section, - bool match_data, uint64_t data, EventNotifier *e) -{ -} - -static void core_eventfd_del(MemoryListener *listener, - MemoryRegionSection *section, - bool match_data, uint64_t data, EventNotifier *e) -{ -} - -static void io_begin(MemoryListener *listener) -{ -} - -static void io_commit(MemoryListener *listener) -{ -} - static void io_region_add(MemoryListener *listener, MemoryRegionSection *section) { @@ -3268,75 +3228,19 @@ static void io_region_del(MemoryListener *listener, isa_unassign_ioport(section->offset_within_address_space, section->size); } -static void io_region_nop(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - -static void io_log_start(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - -static void io_log_stop(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - -static void io_log_sync(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - -static void io_log_global_start(MemoryListener *listener) -{ -} - -static void io_log_global_stop(MemoryListener *listener) -{ -} - -static void io_eventfd_add(MemoryListener *listener, - MemoryRegionSection *section, - bool match_data, uint64_t data, EventNotifier *e) -{ -} - -static void io_eventfd_del(MemoryListener *listener, - MemoryRegionSection *section, - bool match_data, uint64_t data, EventNotifier *e) -{ -} - static MemoryListener core_memory_listener = { .begin = core_begin, .commit = core_commit, .region_add = core_region_add, - .region_del = core_region_del, .region_nop = core_region_nop, - .log_start = core_log_start, - .log_stop = core_log_stop, - .log_sync = core_log_sync, .log_global_start = core_log_global_start, .log_global_stop = core_log_global_stop, - .eventfd_add = core_eventfd_add, - .eventfd_del = core_eventfd_del, .priority = 0, }; static MemoryListener io_memory_listener = { - .begin = io_begin, - .commit = io_commit, .region_add = io_region_add, .region_del = io_region_del, - .region_nop = io_region_nop, - .log_start = io_log_start, - .log_stop = io_log_stop, - .log_sync = io_log_sync, - .log_global_start = io_log_global_start, - .log_global_stop = io_log_global_stop, - .eventfd_add = io_eventfd_add, - .eventfd_del = io_eventfd_del, .priority = 0, }; From e71e602cb5ac194ea414816068f398080d913abb Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 16:42:23 +0200 Subject: [PATCH 0910/2270] vfio: drop no-op MemoryListener callbacks Removes quite a bit of useless code. Signed-off-by: Avi Kivity --- hw/vfio_pci.c | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 639371e7a2..49e11e7db3 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -930,25 +930,6 @@ static int vfio_dma_map(VFIOContainer *container, target_phys_addr_t iova, return -errno; } -static void vfio_listener_dummy1(MemoryListener *listener) -{ - /* We don't do batching (begin/commit) or care about logging */ -} - -static void vfio_listener_dummy2(MemoryListener *listener, - MemoryRegionSection *section) -{ - /* We don't do logging or care about nops */ -} - -static void vfio_listener_dummy3(MemoryListener *listener, - MemoryRegionSection *section, - bool match_data, uint64_t data, - EventNotifier *e) -{ - /* We don't care about eventfds */ -} - static bool vfio_listener_skipped_section(MemoryRegionSection *section) { return !memory_region_is_ram(section->mr); @@ -1040,18 +1021,8 @@ static void vfio_listener_region_del(MemoryListener *listener, } static MemoryListener vfio_memory_listener = { - .begin = vfio_listener_dummy1, - .commit = vfio_listener_dummy1, .region_add = vfio_listener_region_add, .region_del = vfio_listener_region_del, - .region_nop = vfio_listener_dummy2, - .log_start = vfio_listener_dummy2, - .log_stop = vfio_listener_dummy2, - .log_sync = vfio_listener_dummy2, - .log_global_start = vfio_listener_dummy1, - .log_global_stop = vfio_listener_dummy1, - .eventfd_add = vfio_listener_dummy3, - .eventfd_del = vfio_listener_dummy3, }; static void vfio_listener_release(VFIOContainer *container) From 6381fc188cd1c41c69ce947853dd1281d8f3c07e Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 16:42:23 +0200 Subject: [PATCH 0911/2270] xen_pt: drop no-op MemoryListener callbacks Removes quite a bit of useless code. Signed-off-by: Avi Kivity --- hw/xen_pt.c | 45 --------------------------------------------- 1 file changed, 45 deletions(-) diff --git a/hw/xen_pt.c b/hw/xen_pt.c index 4f90ad9e7a..d5dc11e582 100644 --- a/hw/xen_pt.c +++ b/hw/xen_pt.c @@ -601,14 +601,6 @@ static void xen_pt_region_update(XenPCIPassthroughState *s, } } -static void xen_pt_begin(MemoryListener *l) -{ -} - -static void xen_pt_commit(MemoryListener *l) -{ -} - static void xen_pt_region_add(MemoryListener *l, MemoryRegionSection *sec) { XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState, @@ -641,52 +633,15 @@ static void xen_pt_io_region_del(MemoryListener *l, MemoryRegionSection *sec) xen_pt_region_update(s, sec, false); } -static void xen_pt_region_nop(MemoryListener *l, MemoryRegionSection *s) -{ -} - -static void xen_pt_log_fns(MemoryListener *l, MemoryRegionSection *s) -{ -} - -static void xen_pt_log_global_fns(MemoryListener *l) -{ -} - -static void xen_pt_eventfd_fns(MemoryListener *l, MemoryRegionSection *s, - bool match_data, uint64_t data, EventNotifier *n) -{ -} - static const MemoryListener xen_pt_memory_listener = { - .begin = xen_pt_begin, - .commit = xen_pt_commit, .region_add = xen_pt_region_add, - .region_nop = xen_pt_region_nop, .region_del = xen_pt_region_del, - .log_start = xen_pt_log_fns, - .log_stop = xen_pt_log_fns, - .log_sync = xen_pt_log_fns, - .log_global_start = xen_pt_log_global_fns, - .log_global_stop = xen_pt_log_global_fns, - .eventfd_add = xen_pt_eventfd_fns, - .eventfd_del = xen_pt_eventfd_fns, .priority = 10, }; static const MemoryListener xen_pt_io_listener = { - .begin = xen_pt_begin, - .commit = xen_pt_commit, .region_add = xen_pt_io_region_add, - .region_nop = xen_pt_region_nop, .region_del = xen_pt_io_region_del, - .log_start = xen_pt_log_fns, - .log_stop = xen_pt_log_fns, - .log_sync = xen_pt_log_fns, - .log_global_start = xen_pt_log_global_fns, - .log_global_stop = xen_pt_log_global_fns, - .eventfd_add = xen_pt_eventfd_fns, - .eventfd_del = xen_pt_eventfd_fns, .priority = 10, }; From ad1ff3d99a55f559e00a11de14d91ca33a139252 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 16:42:23 +0200 Subject: [PATCH 0912/2270] kvm: drop no-op MemoryListener callbacks Removes quite a bit of useless code. Signed-off-by: Avi Kivity --- kvm-all.c | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index c69e012004..46cf7e9ec4 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -703,14 +703,6 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add) } } -static void kvm_begin(MemoryListener *listener) -{ -} - -static void kvm_commit(MemoryListener *listener) -{ -} - static void kvm_region_add(MemoryListener *listener, MemoryRegionSection *section) { @@ -723,11 +715,6 @@ static void kvm_region_del(MemoryListener *listener, kvm_set_phys_mem(section, false); } -static void kvm_region_nop(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - static void kvm_log_sync(MemoryListener *listener, MemoryRegionSection *section) { @@ -755,10 +742,6 @@ static void kvm_log_global_stop(struct MemoryListener *listener) assert(r >= 0); } -static void kvm_log_nop(struct MemoryListener *listener) -{ -} - static void kvm_mem_ioeventfd_add(MemoryListener *listener, MemoryRegionSection *section, bool match_data, uint64_t data, @@ -825,11 +808,8 @@ static void kvm_io_ioeventfd_del(MemoryListener *listener, } static MemoryListener kvm_memory_listener = { - .begin = kvm_begin, - .commit = kvm_commit, .region_add = kvm_region_add, .region_del = kvm_region_del, - .region_nop = kvm_region_nop, .log_start = kvm_log_start, .log_stop = kvm_log_stop, .log_sync = kvm_log_sync, @@ -841,16 +821,6 @@ static MemoryListener kvm_memory_listener = { }; static MemoryListener kvm_io_listener = { - .begin = kvm_begin, - .commit = kvm_commit, - .region_add = kvm_region_nop, - .region_del = kvm_region_nop, - .region_nop = kvm_region_nop, - .log_start = kvm_region_nop, - .log_stop = kvm_region_nop, - .log_sync = kvm_region_nop, - .log_global_start = kvm_log_nop, - .log_global_stop = kvm_log_nop, .eventfd_add = kvm_io_ioeventfd_add, .eventfd_del = kvm_io_ioeventfd_del, .priority = 10, From bf83601fddb976753b498a879cbdc8f107f59f53 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 16:42:23 +0200 Subject: [PATCH 0913/2270] xen: drop no-op MemoryListener callbacks Removes quite a bit of useless code. Signed-off-by: Avi Kivity --- xen-all.c | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/xen-all.c b/xen-all.c index bcb7ef7c84..8731e1165b 100644 --- a/xen-all.c +++ b/xen-all.c @@ -454,14 +454,6 @@ static void xen_set_memory(struct MemoryListener *listener, } } -static void xen_begin(MemoryListener *listener) -{ -} - -static void xen_commit(MemoryListener *listener) -{ -} - static void xen_region_add(MemoryListener *listener, MemoryRegionSection *section) { @@ -474,11 +466,6 @@ static void xen_region_del(MemoryListener *listener, xen_set_memory(listener, section, false); } -static void xen_region_nop(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - static void xen_sync_dirty_bitmap(XenIOState *state, target_phys_addr_t start_addr, ram_addr_t size) @@ -565,33 +552,14 @@ static void xen_log_global_stop(MemoryListener *listener) xen_in_migration = false; } -static void xen_eventfd_add(MemoryListener *listener, - MemoryRegionSection *section, - bool match_data, uint64_t data, - EventNotifier *e) -{ -} - -static void xen_eventfd_del(MemoryListener *listener, - MemoryRegionSection *section, - bool match_data, uint64_t data, - EventNotifier *e) -{ -} - static MemoryListener xen_memory_listener = { - .begin = xen_begin, - .commit = xen_commit, .region_add = xen_region_add, .region_del = xen_region_del, - .region_nop = xen_region_nop, .log_start = xen_log_start, .log_stop = xen_log_stop, .log_sync = xen_log_sync, .log_global_start = xen_log_global_start, .log_global_stop = xen_log_global_stop, - .eventfd_add = xen_eventfd_add, - .eventfd_del = xen_eventfd_del, .priority = 10, }; From 7fc645bf7a313d75904f8901f4e231008e79999a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 26 Sep 2012 19:48:54 +0100 Subject: [PATCH 0914/2270] tcg/arm: Factor out code to emit immediate or reg-reg op The code to emit either an immediate cmp or a register cmp insn is duplicated in several places; factor it out into its own function. Signed-off-by: Peter Maydell Signed-off-by: Aurelien Jarno --- tcg/arm/tcg-target.c | 46 +++++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index 737200e5e6..3596bce325 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -467,6 +467,21 @@ static inline void tcg_out_movi32(TCGContext *s, } } +static inline void tcg_out_dat_rI(TCGContext *s, int cond, int opc, TCGArg dst, + TCGArg lhs, TCGArg rhs, int rhs_is_const) +{ + /* Emit either the reg,imm or reg,reg form of a data-processing insn. + * rhs must satisfy the "rI" constraint. + */ + if (rhs_is_const) { + int rot = encode_imm(rhs); + assert(rot >= 0); + tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7)); + } else { + tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0)); + } +} + static inline void tcg_out_mul32(TCGContext *s, int cond, int rd, int rs, int rm) { @@ -1576,14 +1591,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, c = ARITH_EOR; /* Fall through. */ gen_arith: - if (const_args[2]) { - int rot; - rot = encode_imm(args[2]); - tcg_out_dat_imm(s, COND_AL, c, - args[0], args[1], rotl(args[2], rot) | (rot << 7)); - } else - tcg_out_dat_reg(s, COND_AL, c, - args[0], args[1], args[2], SHIFT_IMM_LSL(0)); + tcg_out_dat_rI(s, COND_AL, c, args[0], args[1], args[2], const_args[2]); break; case INDEX_op_add2_i32: tcg_out_dat_reg2(s, COND_AL, ARITH_ADD, ARITH_ADC, @@ -1643,15 +1651,8 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_brcond_i32: - if (const_args[1]) { - int rot; - rot = encode_imm(args[1]); - tcg_out_dat_imm(s, COND_AL, ARITH_CMP, 0, - args[0], rotl(args[1], rot) | (rot << 7)); - } else { - tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, - args[0], args[1], SHIFT_IMM_LSL(0)); - } + tcg_out_dat_rI(s, COND_AL, ARITH_CMP, 0, + args[0], args[1], const_args[1]); tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]], args[3]); break; case INDEX_op_brcond2_i32: @@ -1670,15 +1671,8 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]], args[5]); break; case INDEX_op_setcond_i32: - if (const_args[2]) { - int rot; - rot = encode_imm(args[2]); - tcg_out_dat_imm(s, COND_AL, ARITH_CMP, 0, - args[1], rotl(args[2], rot) | (rot << 7)); - } else { - tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, - args[1], args[2], SHIFT_IMM_LSL(0)); - } + tcg_out_dat_rI(s, COND_AL, ARITH_CMP, 0, + args[1], args[2], const_args[2]); tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[3]], ARITH_MOV, args[0], 0, 1); tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])], From 4a1d241e3cc0a0cacb5de9084a4edb543d529d51 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 26 Sep 2012 19:48:55 +0100 Subject: [PATCH 0915/2270] tcg/arm: Implement movcond_i32 Implement movcond_i32 for ARM, as the sequence mov dst, v2 (implicitly done by the tcg common code) cmp c1, c2 movCC dst, v1 Signed-off-by: Peter Maydell Signed-off-by: Aurelien Jarno --- tcg/arm/tcg-target.c | 10 ++++++++++ tcg/arm/tcg-target.h | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index 3596bce325..e790bf04b4 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -1572,6 +1572,15 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_movi_i32: tcg_out_movi32(s, COND_AL, args[0], args[1]); break; + case INDEX_op_movcond_i32: + /* Constraints mean that v2 is always in the same register as dest, + * so we only need to do "if condition passed, move v1 to dest". + */ + tcg_out_dat_rI(s, COND_AL, ARITH_CMP, 0, + args[1], args[2], const_args[2]); + tcg_out_dat_rI(s, tcg_cond_to_arm_cond[args[5]], + ARITH_MOV, args[0], 0, args[3], const_args[3]); + break; case INDEX_op_add_i32: c = ARITH_ADD; goto gen_arith; @@ -1782,6 +1791,7 @@ static const TCGTargetOpDef arm_op_defs[] = { { INDEX_op_brcond_i32, { "r", "rI" } }, { INDEX_op_setcond_i32, { "r", "r", "rI" } }, + { INDEX_op_movcond_i32, { "r", "r", "rI", "rI", "0" } }, /* TODO: "r", "r", "r", "r", "ri", "ri" */ { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } }, diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index e2299cadd3..0df33520f8 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -73,7 +73,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 0 -#define TCG_TARGET_HAS_movcond_i32 0 +#define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_GUEST_BASE From da897bf5ae2d0276dcabe941ba3a402aa718b740 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Tue, 9 Oct 2012 21:53:55 +0200 Subject: [PATCH 0916/2270] tcg/ia64: use stack for TCG temps Use stack instead of temp_buf array in CPUState for TCG temps. Signed-off-by: Blue Swirl Signed-off-by: Aurelien Jarno --- tcg/ia64/tcg-target.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 705712f775..4cba344bdc 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -2269,9 +2269,12 @@ static void tcg_target_qemu_prologue(TCGContext *s) int frame_size; /* reserve some stack space */ - frame_size = TCG_STATIC_CALL_ARGS_SIZE; + frame_size = TCG_STATIC_CALL_ARGS_SIZE + + CPU_TEMP_BUF_NLONGS * sizeof(long); frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & ~(TCG_TARGET_STACK_ALIGN - 1); + tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE, + CPU_TEMP_BUF_NLONGS * sizeof(long)); /* First emit adhoc function descriptor */ *(uint64_t *)(s->code_ptr) = (uint64_t)s->code_ptr + 16; /* entry point */ @@ -2378,6 +2381,4 @@ static void tcg_target_init(TCGContext *s) tcg_regset_set_reg(s->reserved_regs, TCG_REG_R6); tcg_add_target_add_op_defs(ia64_op_defs); - tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf), - CPU_TEMP_BUF_NLONGS * sizeof(long)); } From b90cf716928d7934f4c1392f9097247a84b295d2 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:55 +0200 Subject: [PATCH 0917/2270] tcg/ia64: implement movcond_i32/64 Implement movcond_i32/64 on ia64 hosts. It is not possible to have immediate compare arguments without adding a new bundle, but it is possible to have 22-bit immediate value arguments. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/ia64/tcg-target.c | 38 ++++++++++++++++++++++++++++++++++++++ tcg/ia64/tcg-target.h | 4 ++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 4cba344bdc..d4d350fe36 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1404,6 +1404,34 @@ static inline void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGArg ret, tcg_opc_a5(TCG_REG_P7, OPC_ADDL_A5, ret, 0, TCG_REG_R0)); } +static inline void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGArg ret, + TCGArg c1, TCGArg c2, + TCGArg v1, int const_v1, + TCGArg v2, int const_v2, int cmp4) +{ + uint64_t opc1, opc2; + + if (const_v1) { + opc1 = tcg_opc_a5(TCG_REG_P6, OPC_ADDL_A5, ret, v1, TCG_REG_R0); + } else if (ret == v1) { + opc1 = tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0); + } else { + opc1 = tcg_opc_a4(TCG_REG_P6, OPC_ADDS_A4, ret, 0, v1); + } + if (const_v2) { + opc2 = tcg_opc_a5(TCG_REG_P7, OPC_ADDL_A5, ret, v2, TCG_REG_R0); + } else if (ret == v2) { + opc2 = tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0); + } else { + opc2 = tcg_opc_a4(TCG_REG_P7, OPC_ADDS_A4, ret, 0, v2); + } + + tcg_out_bundle(s, MmI, + tcg_opc_cmp_a(TCG_REG_P0, cond, c1, c2, cmp4), + opc1, + opc2); +} + #if defined(CONFIG_SOFTMMU) #include "../../softmmu_defs.h" @@ -2106,6 +2134,14 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_setcond_i64: tcg_out_setcond(s, args[3], args[0], args[1], args[2], 0); break; + case INDEX_op_movcond_i32: + tcg_out_movcond(s, args[5], args[0], args[1], args[2], + args[3], const_args[3], args[4], const_args[4], 1); + break; + case INDEX_op_movcond_i64: + tcg_out_movcond(s, args[5], args[0], args[1], args[2], + args[3], const_args[3], args[4], const_args[4], 0); + break; case INDEX_op_qemu_ld8u: tcg_out_qemu_ld(s, args, 0); @@ -2196,6 +2232,7 @@ static const TCGTargetOpDef ia64_op_defs[] = { { INDEX_op_brcond_i32, { "rI", "rI" } }, { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } }, + { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rI", "rI" } }, { INDEX_op_mov_i64, { "r", "r" } }, { INDEX_op_movi_i64, { "r" } }, @@ -2245,6 +2282,7 @@ static const TCGTargetOpDef ia64_op_defs[] = { { INDEX_op_brcond_i64, { "rI", "rI" } }, { INDEX_op_setcond_i64, { "r", "rZ", "rZ" } }, + { INDEX_op_movcond_i64, { "r", "rZ", "rZ", "rI", "rI" } }, { INDEX_op_qemu_ld8u, { "r", "r" } }, { INDEX_op_qemu_ld8s, { "r", "r" } }, diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index 368aee4196..5e7d970982 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -131,10 +131,10 @@ typedef enum { #define TCG_TARGET_HAS_orc_i64 1 #define TCG_TARGET_HAS_rot_i32 1 #define TCG_TARGET_HAS_rot_i64 1 +#define TCG_TARGET_HAS_movcond_i32 1 +#define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_deposit_i32 0 #define TCG_TARGET_HAS_deposit_i64 0 -#define TCG_TARGET_HAS_movcond_i32 0 -#define TCG_TARGET_HAS_movcond_i64 0 /* optional instructions automatically implemented */ #define TCG_TARGET_HAS_neg_i32 0 /* sub r1, r0, r3 */ From 2174d1e1ff3522f6f64260bad460185b7ca5bd26 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:55 +0200 Subject: [PATCH 0918/2270] tcg/ia64: remove suboptimal register shifting in qemu_ld/st ops Remove suboptimal register shifting in qemu_ld/st ops, introduced at the CONFIG_TCG_PASS_AREG0 time. As mem_idx is now loaded in register R58/R59 for the slow path, we have to make sure to do it last, to not add additional register constraints. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/ia64/tcg-target.c | 82 +++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index d4d350fe36..16edc1b85a 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1438,7 +1438,7 @@ static inline void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGArg ret, /* Load and compare a TLB entry, and return the result in (p6, p7). R2 is loaded with the address of the addend TLB entry. - R56 is loaded with the address, zero extented on 32-bit targets. */ + R57 is loaded with the address, zero extented on 32-bit targets. */ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGArg addr_reg, int s_bits, uint64_t offset_rw, uint64_t offset_addend) @@ -1456,9 +1456,9 @@ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGArg addr_reg, tcg_opc_a5 (TCG_REG_P0, OPC_ADDL_A5, TCG_REG_R2, offset_rw, TCG_REG_R2), #if TARGET_LONG_BITS == 32 - tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29, TCG_REG_R56, addr_reg), + tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29, TCG_REG_R57, addr_reg), #else - tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4, TCG_REG_R56, + tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4, TCG_REG_R57, 0, addr_reg), #endif tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2, @@ -1466,12 +1466,12 @@ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGArg addr_reg, tcg_out_bundle(s, mII, tcg_opc_m3 (TCG_REG_P0, (TARGET_LONG_BITS == 32 - ? OPC_LD4_M3 : OPC_LD8_M3), TCG_REG_R57, + ? OPC_LD4_M3 : OPC_LD8_M3), TCG_REG_R56, TCG_REG_R2, offset_addend - offset_rw), tcg_opc_a1 (TCG_REG_P0, OPC_AND_A1, TCG_REG_R3, - TCG_REG_R3, TCG_REG_R56), + TCG_REG_R3, TCG_REG_R57), tcg_opc_a6 (TCG_REG_P0, OPC_CMP_EQ_A6, TCG_REG_P6, - TCG_REG_P7, TCG_REG_R3, TCG_REG_R57)); + TCG_REG_P7, TCG_REG_R3, TCG_REG_R56)); } /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, @@ -1508,8 +1508,8 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) /* P6 is the fast path, and P7 the slow path */ tcg_out_bundle(s, mLX, - tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R57, - mem_index, TCG_REG_R0), + tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, + TCG_REG_R56, 0, TCG_AREG0), tcg_opc_l2 ((tcg_target_long) qemu_ld_helpers[s_bits]), tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R2, (tcg_target_long) qemu_ld_helpers[s_bits])); @@ -1517,7 +1517,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) tcg_opc_m3 (TCG_REG_P0, OPC_LD8_M3, TCG_REG_R3, TCG_REG_R2, 8), tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R3, - TCG_REG_R3, TCG_REG_R56), + TCG_REG_R3, TCG_REG_R57), tcg_opc_i21(TCG_REG_P7, OPC_MOV_I21, TCG_REG_B6, TCG_REG_R3, 0)); if (bswap && s_bits == 1) { @@ -1541,23 +1541,17 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0)); } - /* XXX/FIXME: suboptimal */ - tcg_out_bundle(s, mII, - tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R58, - mem_index, TCG_REG_R0), - tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, - TCG_REG_R57, 0, TCG_REG_R56), - tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, - TCG_REG_R56, 0, TCG_AREG0)); if (!bswap || s_bits == 0) { tcg_out_bundle(s, miB, - tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), + tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R58, + mem_index, TCG_REG_R0), tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0), tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, TCG_REG_B0, TCG_REG_B6)); } else { tcg_out_bundle(s, miB, - tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), + tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R58, + mem_index, TCG_REG_R0), tcg_opc_i3 (TCG_REG_P6, OPC_MUX1_I3, TCG_REG_R8, TCG_REG_R8, 0xb), tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, @@ -1609,8 +1603,8 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) /* P6 is the fast path, and P7 the slow path */ tcg_out_bundle(s, mLX, - tcg_opc_a4(TCG_REG_P7, OPC_ADDS_A4, TCG_REG_R57, - 0, data_reg), + tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, + TCG_REG_R56, 0, TCG_AREG0), tcg_opc_l2 ((tcg_target_long) qemu_st_helpers[opc]), tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R2, (tcg_target_long) qemu_st_helpers[opc])); @@ -1618,31 +1612,42 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) tcg_opc_m3 (TCG_REG_P0, OPC_LD8_M3, TCG_REG_R3, TCG_REG_R2, 8), tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R3, - TCG_REG_R3, TCG_REG_R56), + TCG_REG_R3, TCG_REG_R57), tcg_opc_i21(TCG_REG_P7, OPC_MOV_I21, TCG_REG_B6, TCG_REG_R3, 0)); if (!bswap || opc == 0) { - tcg_out_bundle(s, mII, + tcg_out_bundle(s, mii, + tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, + TCG_REG_R1, TCG_REG_R2), + tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, TCG_REG_R58, + 0, data_reg), + tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0)); + } else if (opc == 1) { + tcg_out_bundle(s, miI, tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0), - tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0)); - } else if (opc == 1) { - tcg_out_bundle(s, mII, - tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, - TCG_REG_R1, TCG_REG_R2), tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12, - TCG_REG_R2, data_reg, 15, 15), + TCG_REG_R2, data_reg, 15, 15)); + tcg_out_bundle(s, miI, + tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, TCG_REG_R58, + 0, data_reg), + tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0), tcg_opc_i3 (TCG_REG_P6, OPC_MUX1_I3, TCG_REG_R2, TCG_REG_R2, 0xb)); data_reg = TCG_REG_R2; } else if (opc == 2) { - tcg_out_bundle(s, mII, + tcg_out_bundle(s, miI, tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), + tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0), tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12, - TCG_REG_R2, data_reg, 31, 31), + TCG_REG_R2, data_reg, 31, 31)); + tcg_out_bundle(s, miI, + tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, TCG_REG_R58, + 0, data_reg), + tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0), tcg_opc_i3 (TCG_REG_P6, OPC_MUX1_I3, TCG_REG_R2, TCG_REG_R2, 0xb)); data_reg = TCG_REG_R2; @@ -1650,25 +1655,18 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) tcg_out_bundle(s, miI, tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2), - tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0), + tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, TCG_REG_R58, + 0, data_reg), tcg_opc_i3 (TCG_REG_P6, OPC_MUX1_I3, TCG_REG_R2, data_reg, 0xb)); data_reg = TCG_REG_R2; } - /* XXX/FIXME: suboptimal */ - tcg_out_bundle(s, mII, - tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R59, - mem_index, TCG_REG_R0), - tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, - TCG_REG_R58, 0, TCG_REG_R57), - tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, - TCG_REG_R57, 0, TCG_REG_R56)); tcg_out_bundle(s, miB, tcg_opc_m4 (TCG_REG_P6, opc_st_m4[opc], data_reg, TCG_REG_R3), - tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, - TCG_REG_R56, 0, TCG_AREG0), + tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R59, + mem_index, TCG_REG_R0), tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, TCG_REG_B0, TCG_REG_B6)); } From 63975ea7dfb3ec258433c782c2455bf64fab5e49 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:55 +0200 Subject: [PATCH 0919/2270] tcg/ia64: slightly optimize TLB access code It is possible to slightly optimize the TLB access code, by replacing the movi + and instructions by a deposit instruction. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/ia64/tcg-target.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 16edc1b85a..6f018f4c67 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -230,6 +230,7 @@ enum { OPC_CMP4_LT_A6 = 0x18400000000ull, OPC_CMP4_LTU_A6 = 0x1a400000000ull, OPC_CMP4_EQ_A6 = 0x1c400000000ull, + OPC_DEP_I14 = 0x0ae00000000ull, OPC_DEP_Z_I12 = 0x0a600000000ull, OPC_EXTR_I11 = 0x0a400002000ull, OPC_EXTR_U_I11 = 0x0a400000000ull, @@ -501,6 +502,18 @@ static inline uint64_t tcg_opc_i12(int qp, uint64_t opc, int r1, | (qp & 0x3f); } +static inline uint64_t tcg_opc_i14(int qp, uint64_t opc, int r1, uint64_t imm, + int r3, uint64_t pos, uint64_t len) +{ + return opc + | ((imm & 0x01) << 36) + | ((len & 0x3f) << 27) + | ((r3 & 0x7f) << 20) + | ((pos & 0x3f) << 14) + | ((r1 & 0x7f) << 6) + | (qp & 0x3f); +} + static inline uint64_t tcg_opc_i18(int qp, uint64_t opc, uint64_t imm) { return opc @@ -1444,9 +1457,7 @@ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGArg addr_reg, uint64_t offset_addend) { tcg_out_bundle(s, mII, - tcg_opc_a5 (TCG_REG_P0, OPC_ADDL_A5, TCG_REG_R3, - TARGET_PAGE_MASK | ((1 << s_bits) - 1), - TCG_REG_R0), + tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, TCG_REG_R2, addr_reg, TARGET_PAGE_BITS, CPU_TLB_BITS - 1), tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, TCG_REG_R2, @@ -1468,8 +1479,9 @@ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGArg addr_reg, (TARGET_LONG_BITS == 32 ? OPC_LD4_M3 : OPC_LD8_M3), TCG_REG_R56, TCG_REG_R2, offset_addend - offset_rw), - tcg_opc_a1 (TCG_REG_P0, OPC_AND_A1, TCG_REG_R3, - TCG_REG_R3, TCG_REG_R57), + tcg_opc_i14(TCG_REG_P0, OPC_DEP_I14, TCG_REG_R3, 0, + TCG_REG_R57, 63 - s_bits, + TARGET_PAGE_BITS - s_bits - 1), tcg_opc_a6 (TCG_REG_P0, OPC_CMP_EQ_A6, TCG_REG_P6, TCG_REG_P7, TCG_REG_R3, TCG_REG_R56)); } From c7d4475a701c61f964a593d6fe81a8ea7a33add7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Oct 2012 16:01:35 -0700 Subject: [PATCH 0920/2270] tcg-ia64: Implement deposit Note that in the general reg=reg,reg case we're restricted to 16-bit insertions. This makes it easy to allow "any" constant as input, as post-truncation it will fit into the constant load insn for which we have room in the bundle. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/ia64/tcg-target.c | 53 +++++++++++++++++++++++++++++++++++++++++++ tcg/ia64/tcg-target.h | 7 ++++-- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 6f018f4c67..06570bea38 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -231,6 +231,7 @@ enum { OPC_CMP4_LTU_A6 = 0x1a400000000ull, OPC_CMP4_EQ_A6 = 0x1c400000000ull, OPC_DEP_I14 = 0x0ae00000000ull, + OPC_DEP_I15 = 0x08000000000ull, OPC_DEP_Z_I12 = 0x0a600000000ull, OPC_EXTR_I11 = 0x0a400002000ull, OPC_EXTR_U_I11 = 0x0a400000000ull, @@ -514,6 +515,18 @@ static inline uint64_t tcg_opc_i14(int qp, uint64_t opc, int r1, uint64_t imm, | (qp & 0x3f); } +static inline uint64_t tcg_opc_i15(int qp, uint64_t opc, int r1, int r2, + int r3, uint64_t pos, uint64_t len) +{ + return opc + | ((pos & 0x3f) << 31) + | ((len & 0x0f) << 27) + | ((r3 & 0x7f) << 20) + | ((r2 & 0x7f) << 13) + | ((r1 & 0x7f) << 6) + | (qp & 0x3f); +} + static inline uint64_t tcg_opc_i18(int qp, uint64_t opc, uint64_t imm) { return opc @@ -1325,6 +1338,37 @@ static inline void tcg_out_bswap64(TCGContext *s, TCGArg ret, TCGArg arg) tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3, ret, arg, 0xb)); } +static inline void tcg_out_deposit(TCGContext *s, TCGArg ret, TCGArg a1, + TCGArg a2, int const_a2, int pos, int len) +{ + uint64_t i1 = 0, i2 = 0; + int cpos = 63 - pos, lm1 = len - 1; + + if (const_a2) { + /* Truncate the value of a constant a2 to the width of the field. */ + int mask = (1u << len) - 1; + a2 &= mask; + + if (a2 == 0 || a2 == mask) { + /* 1-bit signed constant inserted into register. */ + i2 = tcg_opc_i14(TCG_REG_P0, OPC_DEP_I14, ret, a2, a1, cpos, lm1); + } else { + /* Otherwise, load any constant into a temporary. Do this into + the first I slot to help out with cross-unit delays. */ + i1 = tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5, + TCG_REG_R2, a2, TCG_REG_R0); + a2 = TCG_REG_R2; + } + } + if (i2 == 0) { + i2 = tcg_opc_i15(TCG_REG_P0, OPC_DEP_I15, ret, a2, a1, cpos, lm1); + } + tcg_out_bundle(s, (i1 ? mII : miI), + tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), + i1 ? i1 : tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0), + i2); +} + static inline uint64_t tcg_opc_cmp_a(int qp, TCGCond cond, TCGArg arg1, TCGArg arg2, int cmp4) { @@ -2130,6 +2174,12 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_bswap64(s, args[0], args[1]); break; + case INDEX_op_deposit_i32: + case INDEX_op_deposit_i64: + tcg_out_deposit(s, args[0], args[1], args[2], const_args[2], + args[3], args[4]); + break; + case INDEX_op_brcond_i32: tcg_out_brcond(s, args[2], args[0], const_args[0], args[1], const_args[1], args[3], 1); @@ -2294,6 +2344,9 @@ static const TCGTargetOpDef ia64_op_defs[] = { { INDEX_op_setcond_i64, { "r", "rZ", "rZ" } }, { INDEX_op_movcond_i64, { "r", "rZ", "rZ", "rI", "rI" } }, + { INDEX_op_deposit_i32, { "r", "rZ", "ri" } }, + { INDEX_op_deposit_i64, { "r", "rZ", "ri" } }, + { INDEX_op_qemu_ld8u, { "r", "r" } }, { INDEX_op_qemu_ld8s, { "r", "r" } }, { INDEX_op_qemu_ld16u, { "r", "r" } }, diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index 5e7d970982..4255ca5225 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -133,8 +133,11 @@ typedef enum { #define TCG_TARGET_HAS_rot_i64 1 #define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_movcond_i64 1 -#define TCG_TARGET_HAS_deposit_i32 0 -#define TCG_TARGET_HAS_deposit_i64 0 +#define TCG_TARGET_HAS_deposit_i32 1 +#define TCG_TARGET_HAS_deposit_i64 1 + +#define TCG_TARGET_deposit_i32_valid(ofs, len) ((len) <= 16) +#define TCG_TARGET_deposit_i64_valid(ofs, len) ((len) <= 16) /* optional instructions automatically implemented */ #define TCG_TARGET_HAS_neg_i32 0 /* sub r1, r0, r3 */ From 81bad50ec40311797c38a7691844c7d2df9b3823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 12 Oct 2012 00:56:33 +0200 Subject: [PATCH 0921/2270] target-mips: Clean up other_cpu in helper_{d,e}vpe() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Free the variable name "other_cpu" for later use for MIPSCPU. Fix off-by-one indentation while at it. Signed-off-by: Andreas Färber Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index ce5ddaf050..1051c44217 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1874,35 +1874,35 @@ target_ulong helper_emt(void) target_ulong helper_dvpe(CPUMIPSState *env) { - CPUMIPSState *other_cpu = first_cpu; + CPUMIPSState *other_cpu_env = first_cpu; target_ulong prev = env->mvp->CP0_MVPControl; do { /* Turn off all VPEs except the one executing the dvpe. */ - if (other_cpu != env) { - other_cpu->mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP); - mips_vpe_sleep(other_cpu); + if (other_cpu_env != env) { + other_cpu_env->mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP); + mips_vpe_sleep(other_cpu_env); } - other_cpu = other_cpu->next_cpu; - } while (other_cpu); + other_cpu_env = other_cpu_env->next_cpu; + } while (other_cpu_env); return prev; } target_ulong helper_evpe(CPUMIPSState *env) { - CPUMIPSState *other_cpu = first_cpu; + CPUMIPSState *other_cpu_env = first_cpu; target_ulong prev = env->mvp->CP0_MVPControl; do { - if (other_cpu != env - /* If the VPE is WFI, don't disturb its sleep. */ - && !mips_vpe_is_wfi(other_cpu)) { + if (other_cpu_env != env + /* If the VPE is WFI, don't disturb its sleep. */ + && !mips_vpe_is_wfi(other_cpu_env)) { /* Enable the VPE. */ - other_cpu->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP); - mips_vpe_wake(other_cpu); /* And wake it up. */ + other_cpu_env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP); + mips_vpe_wake(other_cpu_env); /* And wake it up. */ } - other_cpu = other_cpu->next_cpu; - } while (other_cpu); + other_cpu_env = other_cpu_env->next_cpu; + } while (other_cpu_env); return prev; } #endif /* !CONFIG_USER_ONLY */ From 135dd63a190a084fa5e9f1b4695397016bf0ce5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 12 Oct 2012 00:56:34 +0200 Subject: [PATCH 0922/2270] target-mips: Pass MIPSCPU to mips_tc_wake() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for changing mips_vpe_is_wfi() argument type to MIPSCPU. Signed-off-by: Andreas Färber Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 1051c44217..e721a4d659 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -737,8 +737,10 @@ static inline void mips_vpe_sleep(CPUMIPSState *c) cpu_reset_interrupt(c, CPU_INTERRUPT_WAKE); } -static inline void mips_tc_wake(CPUMIPSState *c, int tc) +static inline void mips_tc_wake(MIPSCPU *cpu, int tc) { + CPUMIPSState *c = &cpu->env; + /* FIXME: TC reschedule. */ if (mips_vpe_active(c) && !mips_vpe_is_wfi(c)) { mips_vpe_wake(c); @@ -1342,13 +1344,15 @@ void helper_mttc0_tcrestart(CPUMIPSState *env, target_ulong arg1) void helper_mtc0_tchalt(CPUMIPSState *env, target_ulong arg1) { + MIPSCPU *cpu = mips_env_get_cpu(env); + env->active_tc.CP0_TCHalt = arg1 & 0x1; // TODO: Halt TC / Restart (if allocated+active) TC. if (env->active_tc.CP0_TCHalt & 1) { mips_tc_sleep(env, env->current_tc); } else { - mips_tc_wake(env, env->current_tc); + mips_tc_wake(cpu, env->current_tc); } } @@ -1356,6 +1360,7 @@ void helper_mttc0_tchalt(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); + MIPSCPU *other_cpu = mips_env_get_cpu(other); // TODO: Halt TC / Restart (if allocated+active) TC. @@ -1367,7 +1372,7 @@ void helper_mttc0_tchalt(CPUMIPSState *env, target_ulong arg1) if (arg1 & 1) { mips_tc_sleep(other, other_tc); } else { - mips_tc_wake(other, other_tc); + mips_tc_wake(other_cpu, other_tc); } } From b35d77d73c0fc0b60c9937471a17d41c6fb32947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 12 Oct 2012 00:56:35 +0200 Subject: [PATCH 0923/2270] target-mips: Pass MIPSCPU to mips_vpe_is_wfi() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for moving halted field to CPUState. The variable name "c" is retained for MIPSCPU to leave "cpu" for CPUState. Also change return type to bool while at it. Signed-off-by: Andreas Färber Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index e721a4d659..9770741cd3 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -714,11 +714,13 @@ void helper_sdm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, #ifndef CONFIG_USER_ONLY /* SMP helpers. */ -static int mips_vpe_is_wfi(CPUMIPSState *c) +static bool mips_vpe_is_wfi(MIPSCPU *c) { + CPUMIPSState *env = &c->env; + /* If the VPE is halted but otherwise active, it means it's waiting for an interrupt. */ - return c->halted && mips_vpe_active(c); + return env->halted && mips_vpe_active(env); } static inline void mips_vpe_wake(CPUMIPSState *c) @@ -742,7 +744,7 @@ static inline void mips_tc_wake(MIPSCPU *cpu, int tc) CPUMIPSState *c = &cpu->env; /* FIXME: TC reschedule. */ - if (mips_vpe_active(c) && !mips_vpe_is_wfi(c)) { + if (mips_vpe_active(c) && !mips_vpe_is_wfi(cpu)) { mips_vpe_wake(c); } } @@ -1899,9 +1901,11 @@ target_ulong helper_evpe(CPUMIPSState *env) target_ulong prev = env->mvp->CP0_MVPControl; do { + MIPSCPU *other_cpu = mips_env_get_cpu(other_cpu_env); + if (other_cpu_env != env /* If the VPE is WFI, don't disturb its sleep. */ - && !mips_vpe_is_wfi(other_cpu_env)) { + && !mips_vpe_is_wfi(other_cpu)) { /* Enable the VPE. */ other_cpu_env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP); mips_vpe_wake(other_cpu_env); /* And wake it up. */ From c6679e9038027e28b0360039d2bb7d3aa55b934e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 12 Oct 2012 00:56:36 +0200 Subject: [PATCH 0924/2270] target-mips: Pass MIPSCPU to mips_tc_sleep() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for changing mips_vpe_sleep() argument type to MIPSCPU. Signed-off-by: Andreas Färber Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 9770741cd3..5710dd08df 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -749,8 +749,10 @@ static inline void mips_tc_wake(MIPSCPU *cpu, int tc) } } -static inline void mips_tc_sleep(CPUMIPSState *c, int tc) +static inline void mips_tc_sleep(MIPSCPU *cpu, int tc) { + CPUMIPSState *c = &cpu->env; + /* FIXME: TC reschedule. */ if (!mips_vpe_active(c)) { mips_vpe_sleep(c); @@ -1352,7 +1354,7 @@ void helper_mtc0_tchalt(CPUMIPSState *env, target_ulong arg1) // TODO: Halt TC / Restart (if allocated+active) TC. if (env->active_tc.CP0_TCHalt & 1) { - mips_tc_sleep(env, env->current_tc); + mips_tc_sleep(cpu, env->current_tc); } else { mips_tc_wake(cpu, env->current_tc); } @@ -1372,7 +1374,7 @@ void helper_mttc0_tchalt(CPUMIPSState *env, target_ulong arg1) other->tcs[other_tc].CP0_TCHalt = arg1; if (arg1 & 1) { - mips_tc_sleep(other, other_tc); + mips_tc_sleep(other_cpu, other_tc); } else { mips_tc_wake(other_cpu, other_tc); } From 6f4d6b09088ee161ff4be0e4db4e4c0962c79070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 12 Oct 2012 00:56:37 +0200 Subject: [PATCH 0925/2270] target-mips: Pass MIPSCPU to mips_vpe_sleep() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for moving halted field to CPUState. Signed-off-by: Andreas Färber Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 5710dd08df..05b7730987 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -731,8 +731,10 @@ static inline void mips_vpe_wake(CPUMIPSState *c) cpu_interrupt(c, CPU_INTERRUPT_WAKE); } -static inline void mips_vpe_sleep(CPUMIPSState *c) +static inline void mips_vpe_sleep(MIPSCPU *cpu) { + CPUMIPSState *c = &cpu->env; + /* The VPE was shut off, really go to bed. Reset any old _WAKE requests. */ c->halted = 1; @@ -755,7 +757,7 @@ static inline void mips_tc_sleep(MIPSCPU *cpu, int tc) /* FIXME: TC reschedule. */ if (!mips_vpe_active(c)) { - mips_vpe_sleep(c); + mips_vpe_sleep(cpu); } } @@ -1889,8 +1891,10 @@ target_ulong helper_dvpe(CPUMIPSState *env) do { /* Turn off all VPEs except the one executing the dvpe. */ if (other_cpu_env != env) { + MIPSCPU *other_cpu = mips_env_get_cpu(other_cpu_env); + other_cpu_env->mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP); - mips_vpe_sleep(other_cpu_env); + mips_vpe_sleep(other_cpu); } other_cpu_env = other_cpu_env->next_cpu; } while (other_cpu_env); From 28f362be6e7f45ea9b7a57a08555c4c784f36198 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 15 Oct 2012 20:30:28 +0200 Subject: [PATCH 0926/2270] memory: Make eventfd adhere to device endianness Our memory API MMIO regions know the concept of device endianness. This is used to automatically swap endianness between devices and host CPU, depending on whether buses in between would swizzle the bits. The ioeventfd value comparison does not adhere to that semantic though. Probably because nobody has been running ioeventfd on a BE platform and the only device implementing ioeventfd right now is LE (PCI) based. So add swizzling to ioeventfd registration / deletion to make the rest of the code as consistent as possible. Thanks a lot to Michael Tsirkin to point me towards the right direction. Signed-off-by: Alexander Graf Signed-off-by: Avi Kivity --- memory.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/memory.c b/memory.c index 4f3ade06dd..d2f2fd66fb 100644 --- a/memory.c +++ b/memory.c @@ -1217,6 +1217,7 @@ void memory_region_add_eventfd(MemoryRegion *mr, }; unsigned i; + adjust_endianness(mr, &mrfd.data, size); memory_region_transaction_begin(); for (i = 0; i < mr->ioeventfd_nb; ++i) { if (memory_region_ioeventfd_before(mrfd, mr->ioeventfds[i])) { @@ -1248,6 +1249,7 @@ void memory_region_del_eventfd(MemoryRegion *mr, }; unsigned i; + adjust_endianness(mr, &mrfd.data, size); memory_region_transaction_begin(); for (i = 0; i < mr->ioeventfd_nb; ++i) { if (memory_region_ioeventfd_equal(mrfd, mr->ioeventfds[i])) { From 2725aec70114cf1bee00443aeb47a305f9b0c665 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 17 Oct 2012 17:10:04 +0200 Subject: [PATCH 0927/2270] i440fx: avoid destroying memory regions within a transaction Calling memory_region_destroy() within a transaction is illegal, since the memory API is allowed to continue to dispatch to a region until the transaction commits. 440fx does that however when managing PAM registers. This bug is benign, since the regions are all aliases (which the memory core tends to throw anyway), and since we don't do concurrent dispatch yet, but instead of relying on that, tighten ship ahead of the coming concurrency storm. Fix by having a predefined set of regions, of which one will be enabled at any time. Signed-off-by: Avi Kivity --- hw/piix_pci.c | 69 ++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/hw/piix_pci.c b/hw/piix_pci.c index 537fc1973c..5bca41d67b 100644 --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@ -69,8 +69,8 @@ typedef struct PIIX3State { } PIIX3State; typedef struct PAMMemoryRegion { - MemoryRegion mem; - bool initialized; + MemoryRegion alias[4]; /* index = PAM value */ + unsigned current; } PAMMemoryRegion; struct PCII440FXState { @@ -105,37 +105,35 @@ static int pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx) return (pci_intx + slot_addend) & 3; } -static void update_pam(PCII440FXState *d, uint32_t start, uint32_t end, int r, - PAMMemoryRegion *mem) +static void init_pam(PCII440FXState *d, PAMMemoryRegion *mem, + uint32_t start, uint32_t size) { - if (mem->initialized) { - memory_region_del_subregion(d->system_memory, &mem->mem); - memory_region_destroy(&mem->mem); - } + int i; - // printf("ISA mapping %08x-0x%08x: %d\n", start, end, r); - switch(r) { - case 3: - /* RAM */ - memory_region_init_alias(&mem->mem, "pam-ram", d->ram_memory, - start, end - start); - break; - case 1: - /* ROM (XXX: not quite correct) */ - memory_region_init_alias(&mem->mem, "pam-rom", d->ram_memory, - start, end - start); - memory_region_set_readonly(&mem->mem, true); - break; - case 2: - case 0: - /* XXX: should distinguish read/write cases */ - memory_region_init_alias(&mem->mem, "pam-pci", d->pci_address_space, - start, end - start); - break; + /* RAM */ + memory_region_init_alias(&mem->alias[3], "pam-ram", d->ram_memory, start, size); + /* ROM (XXX: not quite correct) */ + memory_region_init_alias(&mem->alias[1], "pam-rom", d->ram_memory, start, size); + memory_region_set_readonly(&mem->alias[1], true); + + /* XXX: should distinguish read/write cases */ + memory_region_init_alias(&mem->alias[0], "pam-pci", d->pci_address_space, + start, size); + memory_region_init_alias(&mem->alias[2], "pam-pci", d->pci_address_space, + start, size); + + for (i = 0; i < 4; ++i) { + memory_region_set_enabled(&mem->alias[i], false); + memory_region_add_subregion_overlap(d->system_memory, start, &mem->alias[i], 1); } - memory_region_add_subregion_overlap(d->system_memory, - start, &mem->mem, 1); - mem->initialized = true; + mem->current = 0; +} + +static void update_pam(PAMMemoryRegion *pam, unsigned r) +{ + memory_region_set_enabled(&pam->alias[pam->current], false); + pam->current = r; + memory_region_set_enabled(&pam->alias[pam->current], true); } static void i440fx_update_memory_mappings(PCII440FXState *d) @@ -145,12 +143,10 @@ static void i440fx_update_memory_mappings(PCII440FXState *d) bool smram_enabled; memory_region_transaction_begin(); - update_pam(d, 0xf0000, 0x100000, (d->dev.config[I440FX_PAM] >> 4) & 3, - &d->pam_regions[0]); + update_pam(&d->pam_regions[0], (d->dev.config[I440FX_PAM] >> 4) & 3); for(i = 0; i < 12; i++) { r = (d->dev.config[(i >> 1) + (I440FX_PAM + 1)] >> ((i & 1) * 4)) & 3; - update_pam(d, 0xc0000 + 0x4000 * i, 0xc0000 + 0x4000 * (i + 1), r, - &d->pam_regions[i+1]); + update_pam(&d->pam_regions[i+1], r); } smram = d->dev.config[I440FX_SMRAM]; smram_enabled = (d->smm_enabled && (smram & 0x08)) || (smram & 0x40); @@ -272,6 +268,7 @@ static PCIBus *i440fx_common_init(const char *device_name, PCIHostState *s; PIIX3State *piix3; PCII440FXState *f; + unsigned i; dev = qdev_create(NULL, "i440FX-pcihost"); s = PCI_HOST_BRIDGE(dev); @@ -303,6 +300,10 @@ static PCIBus *i440fx_common_init(const char *device_name, memory_region_add_subregion_overlap(f->system_memory, 0xa0000, &f->smram_region, 1); memory_region_set_enabled(&f->smram_region, false); + init_pam(f, &f->pam_regions[0], 0xf0000, 0x10000); + for (i = 0; i < 12; ++i) { + init_pam(f, &f->pam_regions[i+1], 0xc0000 + i * 0x4000, 0x4000); + } /* Xen supports additional interrupt routes from the PCI devices to * the IOAPIC: the four pins of each PCI device on the bus are also From 2be0e25f4b6a4f91e39388cc365bbe53b56ab62a Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 17 Oct 2012 17:14:41 +0200 Subject: [PATCH 0928/2270] memory: abort if a memory region is destroyed during a transaction Destroying a memory region is illegal within a transaction, as until the transaction is committed, the memory core may hold references to the region. Add an assert to check for violations of this rule. Signed-off-by: Avi Kivity --- memory.c | 1 + 1 file changed, 1 insertion(+) diff --git a/memory.c b/memory.c index d2f2fd66fb..94049a797d 100644 --- a/memory.c +++ b/memory.c @@ -1022,6 +1022,7 @@ void memory_region_init_reservation(MemoryRegion *mr, void memory_region_destroy(MemoryRegion *mr) { assert(QTAILQ_EMPTY(&mr->subregions)); + assert(memory_region_transaction_depth == 0); mr->destructor(mr); memory_region_clear_coalescing(mr); g_free((char *)mr->name); From 24c9ae4eba5eec59256d0d0ace4d868a19f87528 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Oct 2012 11:32:21 -0700 Subject: [PATCH 0929/2270] tcg: Split out swap_commutative as a subroutine Reduces code duplication and prefers movcond d, c1, c2, const, s to movcond d, c1, c2, s, const It also prefers add r, r, c over add r, c, r when both inputs are known constants. This doesn't matter for true add, as we will fully constant fold that. But it matters for a follow-on patch using this routine for add2 which may not be fully foldable. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 56 ++++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index edb2b0ea90..ff4ddb2efc 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -388,6 +388,23 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x, tcg_abort(); } +static bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2) +{ + TCGArg a1 = *p1, a2 = *p2; + int sum = 0; + sum += temps[a1].state == TCG_TEMP_CONST; + sum -= temps[a2].state == TCG_TEMP_CONST; + + /* Prefer the constant in second argument, and then the form + op a, a, b, which is better handled on non-RISC hosts. */ + if (sum > 0 || (sum == 0 && dest == a2)) { + *p1 = a2; + *p2 = a1; + return true; + } + return false; +} + /* Propagate constants and copies, fold constant expressions. */ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, TCGArg *args, TCGOpDef *tcg_op_defs) @@ -397,7 +414,6 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, const TCGOpDef *def; TCGArg *gen_args; TCGArg tmp; - TCGCond cond; /* Array VALS has an element for each temp. If this temp holds a constant then its value is kept in VALS' element. @@ -440,52 +456,28 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, CASE_OP_32_64(eqv): CASE_OP_32_64(nand): CASE_OP_32_64(nor): - /* Prefer the constant in second argument, and then the form - op a, a, b, which is better handled on non-RISC hosts. */ - if (temps[args[1]].state == TCG_TEMP_CONST || (args[0] == args[2] - && temps[args[2]].state != TCG_TEMP_CONST)) { - tmp = args[1]; - args[1] = args[2]; - args[2] = tmp; - } + swap_commutative(args[0], &args[1], &args[2]); break; CASE_OP_32_64(brcond): - if (temps[args[0]].state == TCG_TEMP_CONST - && temps[args[1]].state != TCG_TEMP_CONST) { - tmp = args[0]; - args[0] = args[1]; - args[1] = tmp; + if (swap_commutative(-1, &args[0], &args[1])) { args[2] = tcg_swap_cond(args[2]); } break; CASE_OP_32_64(setcond): - if (temps[args[1]].state == TCG_TEMP_CONST - && temps[args[2]].state != TCG_TEMP_CONST) { - tmp = args[1]; - args[1] = args[2]; - args[2] = tmp; + if (swap_commutative(args[0], &args[1], &args[2])) { args[3] = tcg_swap_cond(args[3]); } break; CASE_OP_32_64(movcond): - cond = args[5]; - if (temps[args[1]].state == TCG_TEMP_CONST - && temps[args[2]].state != TCG_TEMP_CONST) { - tmp = args[1]; - args[1] = args[2]; - args[2] = tmp; - cond = tcg_swap_cond(cond); + if (swap_commutative(-1, &args[1], &args[2])) { + args[5] = tcg_swap_cond(args[5]); } /* For movcond, we canonicalize the "false" input reg to match the destination reg so that the tcg backend can implement a "move if true" operation. */ - if (args[0] == args[3]) { - tmp = args[3]; - args[3] = args[4]; - args[4] = tmp; - cond = tcg_invert_cond(cond); + if (swap_commutative(args[0], &args[4], &args[3])) { + args[5] = tcg_invert_cond(args[5]); } - args[5] = cond; default: break; } From 1e484e61e2d9387c18a40e9e239b304003f5d183 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Oct 2012 11:32:22 -0700 Subject: [PATCH 0930/2270] tcg: Canonicalize add2 operand ordering Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tcg/optimize.c b/tcg/optimize.c index ff4ddb2efc..8d74186ab3 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -478,6 +478,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, if (swap_commutative(args[0], &args[4], &args[3])) { args[5] = tcg_invert_cond(args[5]); } + break; + case INDEX_op_add2_i32: + swap_commutative(args[0], &args[2], &args[4]); + swap_commutative(args[1], &args[3], &args[5]); + break; default: break; } From 0bfcb86538d0bcffa3ef5434810f91aa861431ce Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Oct 2012 11:32:23 -0700 Subject: [PATCH 0931/2270] tcg: Swap commutative double-word comparisons Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tcg/optimize.c b/tcg/optimize.c index 8d74186ab3..9ecea7085a 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -405,6 +405,22 @@ static bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2) return false; } +static bool swap_commutative2(TCGArg *p1, TCGArg *p2) +{ + int sum = 0; + sum += temps[p1[0]].state == TCG_TEMP_CONST; + sum += temps[p1[1]].state == TCG_TEMP_CONST; + sum -= temps[p2[0]].state == TCG_TEMP_CONST; + sum -= temps[p2[1]].state == TCG_TEMP_CONST; + if (sum > 0) { + TCGArg t; + t = p1[0], p1[0] = p2[0], p2[0] = t; + t = p1[1], p1[1] = p2[1], p2[1] = t; + return true; + } + return false; +} + /* Propagate constants and copies, fold constant expressions. */ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, TCGArg *args, TCGOpDef *tcg_op_defs) @@ -483,6 +499,16 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, swap_commutative(args[0], &args[2], &args[4]); swap_commutative(args[1], &args[3], &args[5]); break; + case INDEX_op_brcond2_i32: + if (swap_commutative2(&args[0], &args[2])) { + args[4] = tcg_swap_cond(args[4]); + } + break; + case INDEX_op_setcond2_i32: + if (swap_commutative2(&args[1], &args[3])) { + args[5] = tcg_swap_cond(args[5]); + } + break; default: break; } From 6e14e91b6681dac9614b7b09b561351813046193 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Oct 2012 11:32:24 -0700 Subject: [PATCH 0932/2270] tcg: Use common code when failing to optimize This saves a whole lot of repetitive code sequences. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 91 ++++++++++++++++++-------------------------------- 1 file changed, 32 insertions(+), 59 deletions(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index 9ecea7085a..0fd7db3654 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -645,6 +645,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, gen_args += 2; args += 2; break; + CASE_OP_32_64(not): CASE_OP_32_64(neg): CASE_OP_32_64(ext8s): @@ -657,14 +658,12 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, gen_opc_buf[op_index] = op_to_movi(op); tmp = do_constant_folding(op, temps[args[1]].val, 0); tcg_opt_gen_movi(gen_args, args[0], tmp); - } else { - reset_temp(args[0]); - gen_args[0] = args[0]; - gen_args[1] = args[1]; + gen_args += 2; + args += 2; + break; } - gen_args += 2; - args += 2; - break; + goto do_default; + CASE_OP_32_64(add): CASE_OP_32_64(sub): CASE_OP_32_64(mul): @@ -688,15 +687,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, temps[args[2]].val); tcg_opt_gen_movi(gen_args, args[0], tmp); gen_args += 2; - } else { - reset_temp(args[0]); - gen_args[0] = args[0]; - gen_args[1] = args[1]; - gen_args[2] = args[2]; - gen_args += 3; + args += 3; + break; } - args += 3; - break; + goto do_default; + CASE_OP_32_64(deposit): if (temps[args[1]].state == TCG_TEMP_CONST && temps[args[2]].state == TCG_TEMP_CONST) { @@ -706,33 +701,22 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, | ((temps[args[2]].val & tmp) << args[3]); tcg_opt_gen_movi(gen_args, args[0], tmp); gen_args += 2; - } else { - reset_temp(args[0]); - gen_args[0] = args[0]; - gen_args[1] = args[1]; - gen_args[2] = args[2]; - gen_args[3] = args[3]; - gen_args[4] = args[4]; - gen_args += 5; + args += 5; + break; } - args += 5; - break; + goto do_default; + CASE_OP_32_64(setcond): tmp = do_constant_folding_cond(op, args[1], args[2], args[3]); if (tmp != 2) { gen_opc_buf[op_index] = op_to_movi(op); tcg_opt_gen_movi(gen_args, args[0], tmp); gen_args += 2; - } else { - reset_temp(args[0]); - gen_args[0] = args[0]; - gen_args[1] = args[1]; - gen_args[2] = args[2]; - gen_args[3] = args[3]; - gen_args += 4; + args += 4; + break; } - args += 4; - break; + goto do_default; + CASE_OP_32_64(brcond): tmp = do_constant_folding_cond(op, args[0], args[1], args[2]); if (tmp != 2) { @@ -744,17 +728,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, } else { gen_opc_buf[op_index] = INDEX_op_nop; } - } else { - memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info)); - reset_temp(args[0]); - gen_args[0] = args[0]; - gen_args[1] = args[1]; - gen_args[2] = args[2]; - gen_args[3] = args[3]; - gen_args += 4; + args += 4; + break; } - args += 4; - break; + goto do_default; + CASE_OP_32_64(movcond): tmp = do_constant_folding_cond(op, args[1], args[2], args[5]); if (tmp != 2) { @@ -769,18 +747,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, tcg_opt_gen_mov(s, gen_args, args[0], args[4-tmp]); gen_args += 2; } - } else { - reset_temp(args[0]); - gen_args[0] = args[0]; - gen_args[1] = args[1]; - gen_args[2] = args[2]; - gen_args[3] = args[3]; - gen_args[4] = args[4]; - gen_args[5] = args[5]; - gen_args += 6; + args += 6; + break; } - args += 6; - break; + goto do_default; + case INDEX_op_call: nb_call_args = (args[0] >> 16) + (args[0] & 0xffff); if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) { @@ -799,11 +770,13 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, i--; } break; + default: - /* Default case: we do know nothing about operation so no - propagation is done. We trash everything if the operation - is the end of a basic block, otherwise we only trash the - output args. */ + do_default: + /* Default case: we know nothing about operation (or were unable + to compute the operation result) so no propagation is done. + We trash everything if the operation is the end of a basic + block, otherwise we only trash the output args. */ if (def->flags & TCG_OPF_BB_END) { memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info)); } else { From bc1473eff4d9a3b62d669b7232383f85eb82b376 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Oct 2012 11:32:25 -0700 Subject: [PATCH 0933/2270] tcg: Optimize double-word comparisons against zero Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tcg/optimize.c b/tcg/optimize.c index 0fd7db3654..0a55352870 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -752,6 +752,45 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, } goto do_default; + case INDEX_op_brcond2_i32: + /* Simplify LT/GE comparisons vs zero to a single compare + vs the high word of the input. */ + if ((args[4] == TCG_COND_LT || args[4] == TCG_COND_GE) + && temps[args[2]].state == TCG_TEMP_CONST + && temps[args[3]].state == TCG_TEMP_CONST + && temps[args[2]].val == 0 + && temps[args[3]].val == 0) { + gen_opc_buf[op_index] = INDEX_op_brcond_i32; + gen_args[0] = args[1]; + gen_args[1] = args[3]; + gen_args[2] = args[4]; + gen_args[3] = args[5]; + gen_args += 4; + args += 6; + memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info)); + break; + } + goto do_default; + + case INDEX_op_setcond2_i32: + /* Simplify LT/GE comparisons vs zero to a single compare + vs the high word of the input. */ + if ((args[5] == TCG_COND_LT || args[5] == TCG_COND_GE) + && temps[args[3]].state == TCG_TEMP_CONST + && temps[args[4]].state == TCG_TEMP_CONST + && temps[args[3]].val == 0 + && temps[args[4]].val == 0) { + gen_opc_buf[op_index] = INDEX_op_setcond_i32; + gen_args[0] = args[0]; + gen_args[1] = args[2]; + gen_args[2] = args[4]; + gen_args[3] = args[5]; + gen_args += 4; + args += 6; + break; + } + goto do_default; + case INDEX_op_call: nb_call_args = (args[0] >> 16) + (args[0] & 0xffff); if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) { From 9519da7e39516c5cb5bd7146a849a5d8c0958105 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Oct 2012 11:32:26 -0700 Subject: [PATCH 0934/2270] tcg: Split out subroutines from do_constant_folding_cond We can re-use these for implementing double-word folding. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 152 ++++++++++++++++++++++++++----------------------- 1 file changed, 81 insertions(+), 71 deletions(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index 0a55352870..38027dc5ad 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -292,6 +292,82 @@ static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y) return res; } +static bool do_constant_folding_cond_32(uint32_t x, uint32_t y, TCGCond c) +{ + switch (c) { + case TCG_COND_EQ: + return x == y; + case TCG_COND_NE: + return x != y; + case TCG_COND_LT: + return (int32_t)x < (int32_t)y; + case TCG_COND_GE: + return (int32_t)x >= (int32_t)y; + case TCG_COND_LE: + return (int32_t)x <= (int32_t)y; + case TCG_COND_GT: + return (int32_t)x > (int32_t)y; + case TCG_COND_LTU: + return x < y; + case TCG_COND_GEU: + return x >= y; + case TCG_COND_LEU: + return x <= y; + case TCG_COND_GTU: + return x > y; + default: + tcg_abort(); + } +} + +static bool do_constant_folding_cond_64(uint64_t x, uint64_t y, TCGCond c) +{ + switch (c) { + case TCG_COND_EQ: + return x == y; + case TCG_COND_NE: + return x != y; + case TCG_COND_LT: + return (int64_t)x < (int64_t)y; + case TCG_COND_GE: + return (int64_t)x >= (int64_t)y; + case TCG_COND_LE: + return (int64_t)x <= (int64_t)y; + case TCG_COND_GT: + return (int64_t)x > (int64_t)y; + case TCG_COND_LTU: + return x < y; + case TCG_COND_GEU: + return x >= y; + case TCG_COND_LEU: + return x <= y; + case TCG_COND_GTU: + return x > y; + default: + tcg_abort(); + } +} + +static bool do_constant_folding_cond_eq(TCGCond c) +{ + switch (c) { + case TCG_COND_GT: + case TCG_COND_LTU: + case TCG_COND_LT: + case TCG_COND_GTU: + case TCG_COND_NE: + return 0; + case TCG_COND_GE: + case TCG_COND_GEU: + case TCG_COND_LE: + case TCG_COND_LEU: + case TCG_COND_EQ: + return 1; + default: + tcg_abort(); + } +} + /* Return 2 if the condition can't be simplified, and the result of the condition (0 or 1) if it can */ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x, @@ -300,75 +376,14 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x, if (temps[x].state == TCG_TEMP_CONST && temps[y].state == TCG_TEMP_CONST) { switch (op_bits(op)) { case 32: - switch (c) { - case TCG_COND_EQ: - return (uint32_t)temps[x].val == (uint32_t)temps[y].val; - case TCG_COND_NE: - return (uint32_t)temps[x].val != (uint32_t)temps[y].val; - case TCG_COND_LT: - return (int32_t)temps[x].val < (int32_t)temps[y].val; - case TCG_COND_GE: - return (int32_t)temps[x].val >= (int32_t)temps[y].val; - case TCG_COND_LE: - return (int32_t)temps[x].val <= (int32_t)temps[y].val; - case TCG_COND_GT: - return (int32_t)temps[x].val > (int32_t)temps[y].val; - case TCG_COND_LTU: - return (uint32_t)temps[x].val < (uint32_t)temps[y].val; - case TCG_COND_GEU: - return (uint32_t)temps[x].val >= (uint32_t)temps[y].val; - case TCG_COND_LEU: - return (uint32_t)temps[x].val <= (uint32_t)temps[y].val; - case TCG_COND_GTU: - return (uint32_t)temps[x].val > (uint32_t)temps[y].val; - default: - break; - } - break; + return do_constant_folding_cond_32(temps[x].val, temps[y].val, c); case 64: - switch (c) { - case TCG_COND_EQ: - return (uint64_t)temps[x].val == (uint64_t)temps[y].val; - case TCG_COND_NE: - return (uint64_t)temps[x].val != (uint64_t)temps[y].val; - case TCG_COND_LT: - return (int64_t)temps[x].val < (int64_t)temps[y].val; - case TCG_COND_GE: - return (int64_t)temps[x].val >= (int64_t)temps[y].val; - case TCG_COND_LE: - return (int64_t)temps[x].val <= (int64_t)temps[y].val; - case TCG_COND_GT: - return (int64_t)temps[x].val > (int64_t)temps[y].val; - case TCG_COND_LTU: - return (uint64_t)temps[x].val < (uint64_t)temps[y].val; - case TCG_COND_GEU: - return (uint64_t)temps[x].val >= (uint64_t)temps[y].val; - case TCG_COND_LEU: - return (uint64_t)temps[x].val <= (uint64_t)temps[y].val; - case TCG_COND_GTU: - return (uint64_t)temps[x].val > (uint64_t)temps[y].val; - default: - break; - } - break; + return do_constant_folding_cond_64(temps[x].val, temps[y].val, c); + default: + tcg_abort(); } } else if (temps_are_copies(x, y)) { - switch (c) { - case TCG_COND_GT: - case TCG_COND_LTU: - case TCG_COND_LT: - case TCG_COND_GTU: - case TCG_COND_NE: - return 0; - case TCG_COND_GE: - case TCG_COND_GEU: - case TCG_COND_LE: - case TCG_COND_LEU: - case TCG_COND_EQ: - return 1; - default: - break; - } + return do_constant_folding_cond_eq(c); } else if (temps[y].state == TCG_TEMP_CONST && temps[y].val == 0) { switch (c) { case TCG_COND_LTU: @@ -381,11 +396,6 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x, } else { return 2; } - - fprintf(stderr, - "Unrecognized bitness %d or condition %d in " - "do_constant_folding_cond.\n", op_bits(op), c); - tcg_abort(); } static bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2) From 6c4382f8f47d12eec24c7c5335141a9c78104016 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Oct 2012 11:32:27 -0700 Subject: [PATCH 0935/2270] tcg: Do constant folding on double-word comparisons Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 93 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 21 deletions(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index 38027dc5ad..d9251e4677 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -398,6 +398,40 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x, } } +/* Return 2 if the condition can't be simplified, and the result + of the condition (0 or 1) if it can */ +static TCGArg do_constant_folding_cond2(TCGArg *p1, TCGArg *p2, TCGCond c) +{ + TCGArg al = p1[0], ah = p1[1]; + TCGArg bl = p2[0], bh = p2[1]; + + if (temps[bl].state == TCG_TEMP_CONST + && temps[bh].state == TCG_TEMP_CONST) { + uint64_t b = ((uint64_t)temps[bh].val << 32) | (uint32_t)temps[bl].val; + + if (temps[al].state == TCG_TEMP_CONST + && temps[ah].state == TCG_TEMP_CONST) { + uint64_t a; + a = ((uint64_t)temps[ah].val << 32) | (uint32_t)temps[al].val; + return do_constant_folding_cond_64(a, b, c); + } + if (b == 0) { + switch (c) { + case TCG_COND_LTU: + return 0; + case TCG_COND_GEU: + return 1; + default: + break; + } + } + } + if (temps_are_copies(al, bl) && temps_are_copies(ah, bh)) { + return do_constant_folding_cond_eq(c); + } + return 2; +} + static bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2) { TCGArg a1 = *p1, a2 = *p2; @@ -763,43 +797,60 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, goto do_default; case INDEX_op_brcond2_i32: - /* Simplify LT/GE comparisons vs zero to a single compare - vs the high word of the input. */ - if ((args[4] == TCG_COND_LT || args[4] == TCG_COND_GE) - && temps[args[2]].state == TCG_TEMP_CONST - && temps[args[3]].state == TCG_TEMP_CONST - && temps[args[2]].val == 0 - && temps[args[3]].val == 0) { + tmp = do_constant_folding_cond2(&args[0], &args[2], args[4]); + if (tmp != 2) { + if (tmp) { + memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info)); + gen_opc_buf[op_index] = INDEX_op_br; + gen_args[0] = args[5]; + gen_args += 1; + } else { + gen_opc_buf[op_index] = INDEX_op_nop; + } + } else if ((args[4] == TCG_COND_LT || args[4] == TCG_COND_GE) + && temps[args[2]].state == TCG_TEMP_CONST + && temps[args[3]].state == TCG_TEMP_CONST + && temps[args[2]].val == 0 + && temps[args[3]].val == 0) { + /* Simplify LT/GE comparisons vs zero to a single compare + vs the high word of the input. */ + memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info)); gen_opc_buf[op_index] = INDEX_op_brcond_i32; gen_args[0] = args[1]; gen_args[1] = args[3]; gen_args[2] = args[4]; gen_args[3] = args[5]; gen_args += 4; - args += 6; - memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info)); - break; + } else { + goto do_default; } - goto do_default; + args += 6; + break; case INDEX_op_setcond2_i32: - /* Simplify LT/GE comparisons vs zero to a single compare - vs the high word of the input. */ - if ((args[5] == TCG_COND_LT || args[5] == TCG_COND_GE) - && temps[args[3]].state == TCG_TEMP_CONST - && temps[args[4]].state == TCG_TEMP_CONST - && temps[args[3]].val == 0 - && temps[args[4]].val == 0) { + tmp = do_constant_folding_cond2(&args[1], &args[3], args[5]); + if (tmp != 2) { + gen_opc_buf[op_index] = INDEX_op_movi_i32; + tcg_opt_gen_movi(gen_args, args[0], tmp); + gen_args += 2; + } else if ((args[5] == TCG_COND_LT || args[5] == TCG_COND_GE) + && temps[args[3]].state == TCG_TEMP_CONST + && temps[args[4]].state == TCG_TEMP_CONST + && temps[args[3]].val == 0 + && temps[args[4]].val == 0) { + /* Simplify LT/GE comparisons vs zero to a single compare + vs the high word of the input. */ gen_opc_buf[op_index] = INDEX_op_setcond_i32; gen_args[0] = args[0]; gen_args[1] = args[2]; gen_args[2] = args[4]; gen_args[3] = args[5]; gen_args += 4; - args += 6; - break; + } else { + goto do_default; } - goto do_default; + args += 6; + break; case INDEX_op_call: nb_call_args = (args[0] >> 16) + (args[0] & 0xffff); From 212c328d615f6750659d39c6fd544d05be314fa1 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Oct 2012 11:32:28 -0700 Subject: [PATCH 0936/2270] tcg: Constant fold add2 and sub2 Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 35 +++++++++++++++++++++++++++++++++++ tcg/tcg-op.h | 9 +++++++++ 2 files changed, 44 insertions(+) diff --git a/tcg/optimize.c b/tcg/optimize.c index d9251e4677..05891ef380 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -796,6 +796,41 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, } goto do_default; + case INDEX_op_add2_i32: + case INDEX_op_sub2_i32: + if (temps[args[2]].state == TCG_TEMP_CONST + && temps[args[3]].state == TCG_TEMP_CONST + && temps[args[4]].state == TCG_TEMP_CONST + && temps[args[5]].state == TCG_TEMP_CONST) { + uint32_t al = temps[args[2]].val; + uint32_t ah = temps[args[3]].val; + uint32_t bl = temps[args[4]].val; + uint32_t bh = temps[args[5]].val; + uint64_t a = ((uint64_t)ah << 32) | al; + uint64_t b = ((uint64_t)bh << 32) | bl; + TCGArg rl, rh; + + if (op == INDEX_op_add2_i32) { + a += b; + } else { + a -= b; + } + + /* We emit the extra nop when we emit the add2/sub2. */ + assert(gen_opc_buf[op_index + 1] == INDEX_op_nop); + + rl = args[0]; + rh = args[1]; + gen_opc_buf[op_index] = INDEX_op_movi_i32; + gen_opc_buf[++op_index] = INDEX_op_movi_i32; + tcg_opt_gen_movi(&gen_args[0], rl, (uint32_t)a); + tcg_opt_gen_movi(&gen_args[2], rh, (uint32_t)(a >> 32)); + gen_args += 4; + args += 6; + break; + } + goto do_default; + case INDEX_op_brcond2_i32: tmp = do_constant_folding_cond2(&args[0], &args[2], args[4]); if (tmp != 2) { diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 551845801d..a580cfea07 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -25,6 +25,11 @@ int gen_new_label(void); +static inline void tcg_gen_op0(TCGOpcode opc) +{ + *gen_opc_ptr++ = opc; +} + static inline void tcg_gen_op1_i32(TCGOpcode opc, TCGv_i32 arg1) { *gen_opc_ptr++ = opc; @@ -886,6 +891,8 @@ static inline void tcg_gen_add_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) tcg_gen_op6_i32(INDEX_op_add2_i32, TCGV_LOW(ret), TCGV_HIGH(ret), TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2), TCGV_HIGH(arg2)); + /* Allow the optimizer room to replace add2 with two moves. */ + tcg_gen_op0(INDEX_op_nop); } static inline void tcg_gen_sub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) @@ -893,6 +900,8 @@ static inline void tcg_gen_sub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) tcg_gen_op6_i32(INDEX_op_sub2_i32, TCGV_LOW(ret), TCGV_HIGH(ret), TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2), TCGV_HIGH(arg2)); + /* Allow the optimizer room to replace sub2 with two moves. */ + tcg_gen_op0(INDEX_op_nop); } static inline void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) From 1305c451e67e3def030720013415103f5e0f5e11 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Oct 2012 11:32:29 -0700 Subject: [PATCH 0937/2270] tcg: Optimize half-dead add2/sub2 When x86_64 guest is not in 64-bit mode, the high-part of the 64-bit add is dead. When the host is 32-bit, we can simplify to 32-bit arithmetic. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 32cd0c6b65..0eb407b723 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1307,8 +1307,39 @@ static void tcg_liveness_analysis(TCGContext *s) break; case INDEX_op_end: break; - /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */ + + case INDEX_op_add2_i32: + case INDEX_op_sub2_i32: + args -= 6; + nb_iargs = 4; + nb_oargs = 2; + /* Test if the high part of the operation is dead, but not + the low part. The result can be optimized to a simple + add or sub. This happens often for x86_64 guest when the + cpu mode is set to 32 bit. */ + if (dead_temps[args[1]]) { + if (dead_temps[args[0]]) { + goto do_remove; + } + /* Create the single operation plus nop. */ + if (op == INDEX_op_add2_i32) { + op = INDEX_op_add_i32; + } else { + op = INDEX_op_sub_i32; + } + gen_opc_buf[op_index] = op; + args[1] = args[2]; + args[2] = args[4]; + assert(gen_opc_buf[op_index + 1] == INDEX_op_nop); + tcg_set_nop(s, gen_opc_buf + op_index + 1, args + 3, 3); + /* Fall through and mark the single-word operation live. */ + nb_iargs = 2; + nb_oargs = 1; + } + goto do_not_remove; + default: + /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */ args -= def->nb_args; nb_iargs = def->nb_iargs; nb_oargs = def->nb_oargs; @@ -1322,6 +1353,7 @@ static void tcg_liveness_analysis(TCGContext *s) if (!dead_temps[arg]) goto do_not_remove; } + do_remove: tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args); #ifdef CONFIG_PROFILER s->del_op_count++; From 1414968a6aecd23cb037bc9e718d6f05ead2afaf Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Oct 2012 11:32:30 -0700 Subject: [PATCH 0938/2270] tcg: Optimize mulu2 Like add2, do operand ordering, constant folding, and dead operand elimination. The latter happens about 15% of all mulu2 during an x86_64 bios boot. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/optimize.c | 26 ++++++++++++++++++++++++++ tcg/tcg-op.h | 2 ++ tcg/tcg.c | 19 +++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/tcg/optimize.c b/tcg/optimize.c index 05891ef380..a06c8eb43e 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -543,6 +543,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, swap_commutative(args[0], &args[2], &args[4]); swap_commutative(args[1], &args[3], &args[5]); break; + case INDEX_op_mulu2_i32: + swap_commutative(args[0], &args[2], &args[3]); + break; case INDEX_op_brcond2_i32: if (swap_commutative2(&args[0], &args[2])) { args[4] = tcg_swap_cond(args[4]); @@ -831,6 +834,29 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, } goto do_default; + case INDEX_op_mulu2_i32: + if (temps[args[2]].state == TCG_TEMP_CONST + && temps[args[3]].state == TCG_TEMP_CONST) { + uint32_t a = temps[args[2]].val; + uint32_t b = temps[args[3]].val; + uint64_t r = (uint64_t)a * b; + TCGArg rl, rh; + + /* We emit the extra nop when we emit the mulu2. */ + assert(gen_opc_buf[op_index + 1] == INDEX_op_nop); + + rl = args[0]; + rh = args[1]; + gen_opc_buf[op_index] = INDEX_op_movi_i32; + gen_opc_buf[++op_index] = INDEX_op_movi_i32; + tcg_opt_gen_movi(&gen_args[0], rl, (uint32_t)r); + tcg_opt_gen_movi(&gen_args[2], rh, (uint32_t)(r >> 32)); + gen_args += 4; + args += 4; + break; + } + goto do_default; + case INDEX_op_brcond2_i32: tmp = do_constant_folding_cond2(&args[0], &args[2], args[4]); if (tmp != 2) { diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index a580cfea07..8100a5a2e0 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -1027,6 +1027,8 @@ static inline void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) tcg_gen_op4_i32(INDEX_op_mulu2_i32, TCGV_LOW(t0), TCGV_HIGH(t0), TCGV_LOW(arg1), TCGV_LOW(arg2)); + /* Allow the optimizer room to replace mulu2 with two moves. */ + tcg_gen_op0(INDEX_op_nop); tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2)); tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1); diff --git a/tcg/tcg.c b/tcg/tcg.c index 0eb407b723..f0deea25b2 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1338,6 +1338,25 @@ static void tcg_liveness_analysis(TCGContext *s) } goto do_not_remove; + case INDEX_op_mulu2_i32: + args -= 4; + nb_iargs = 2; + nb_oargs = 2; + /* Likewise, test for the high part of the operation dead. */ + if (dead_temps[args[1]]) { + if (dead_temps[args[0]]) { + goto do_remove; + } + gen_opc_buf[op_index] = op = INDEX_op_mul_i32; + args[1] = args[2]; + args[2] = args[3]; + assert(gen_opc_buf[op_index + 1] == INDEX_op_nop); + tcg_set_nop(s, gen_opc_buf + op_index + 1, args + 3, 1); + /* Fall through and mark the single-word operation live. */ + nb_oargs = 1; + } + goto do_not_remove; + default: /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */ args -= def->nb_args; From 05e72dc5812a9f461fc2c606dff2572909eafc39 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 24 Jul 2012 14:14:32 +0200 Subject: [PATCH 0939/2270] buffered_file: g_realloc() can't fail Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini Reviewed-by: Orit Wasserman --- buffered_file.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index f170aa046f..4148abbee0 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -50,20 +50,12 @@ static void buffered_append(QEMUFileBuffered *s, const uint8_t *buf, size_t size) { if (size > (s->buffer_capacity - s->buffer_size)) { - void *tmp; - DPRINTF("increasing buffer capacity from %zu by %zu\n", s->buffer_capacity, size + 1024); s->buffer_capacity += size + 1024; - tmp = g_realloc(s->buffer, s->buffer_capacity); - if (tmp == NULL) { - fprintf(stderr, "qemu file buffer expansion failed\n"); - exit(1); - } - - s->buffer = tmp; + s->buffer = g_realloc(s->buffer, s->buffer_capacity); } memcpy(s->buffer + s->buffer_size, buf, size); From 79536f4f16934d6759a1d67f0342b4e7ceb66671 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 3 Aug 2012 12:58:16 +0200 Subject: [PATCH 0940/2270] fix migration sync Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- arch_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch_init.c b/arch_init.c index 9904f95478..671d3545cc 100644 --- a/arch_init.c +++ b/arch_init.c @@ -517,6 +517,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) } memory_global_dirty_log_start(); + memory_global_sync_dirty_bitmap(get_system_memory()); qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE); From 97d4d961d98c1ad54eee657d81e2e50911a92acf Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 10 Aug 2012 21:53:08 +0200 Subject: [PATCH 0941/2270] migration: store end_time in a local variable Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini Reviewed-by: Orit Wasserman --- migration.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/migration.c b/migration.c index 22a05c437d..7a110264ee 100644 --- a/migration.c +++ b/migration.c @@ -329,6 +329,7 @@ static void migrate_fd_put_ready(void *opaque) migrate_fd_error(s); } else if (ret == 1) { int old_vm_running = runstate_is_running(); + int64_t end_time; DPRINTF("done iterating\n"); qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); @@ -339,7 +340,8 @@ static void migrate_fd_put_ready(void *opaque) } else { migrate_fd_completed(s); } - s->total_time = qemu_get_clock_ms(rt_clock) - s->total_time; + end_time = qemu_get_clock_ms(rt_clock); + s->total_time = end_time - s->total_time; if (s->state != MIG_STATE_COMPLETED) { if (old_vm_running) { vm_start(); From 9c5a9fcf5399450a873e7460b397a89447c7ef11 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 13 Aug 2012 09:35:16 +0200 Subject: [PATCH 0942/2270] migration: print total downtime for final phase of migration Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini Reviewed-by: Orit Wasserman --- hmp.c | 4 ++++ migration.c | 6 +++++- migration.h | 1 + qapi-schema.json | 7 ++++++- qmp-commands.hx | 3 +++ 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/hmp.c b/hmp.c index 70bdec2433..a8e5aea7c3 100644 --- a/hmp.c +++ b/hmp.c @@ -152,6 +152,10 @@ void hmp_info_migrate(Monitor *mon) monitor_printf(mon, "Migration status: %s\n", info->status); monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n", info->total_time); + if (info->has_downtime) { + monitor_printf(mon, "downtime: %" PRIu64 " milliseconds\n", + info->downtime); + } } if (info->has_ram) { diff --git a/migration.c b/migration.c index 7a110264ee..1375e7e184 100644 --- a/migration.c +++ b/migration.c @@ -195,6 +195,8 @@ MigrationInfo *qmp_query_migrate(Error **errp) info->has_status = true; info->status = g_strdup("completed"); info->total_time = s->total_time; + info->has_downtime = true; + info->downtime = s->downtime; info->has_ram = true; info->ram = g_malloc0(sizeof(*info->ram)); @@ -329,9 +331,10 @@ static void migrate_fd_put_ready(void *opaque) migrate_fd_error(s); } else if (ret == 1) { int old_vm_running = runstate_is_running(); - int64_t end_time; + int64_t start_time, end_time; DPRINTF("done iterating\n"); + start_time = qemu_get_clock_ms(rt_clock); qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); @@ -342,6 +345,7 @@ static void migrate_fd_put_ready(void *opaque) } end_time = qemu_get_clock_ms(rt_clock); s->total_time = end_time - s->total_time; + s->downtime = end_time - start_time; if (s->state != MIG_STATE_COMPLETED) { if (old_vm_running) { vm_start(); diff --git a/migration.h b/migration.h index a9852fcae0..3462917425 100644 --- a/migration.h +++ b/migration.h @@ -40,6 +40,7 @@ struct MigrationState void *opaque; MigrationParams params; int64_t total_time; + int64_t downtime; bool enabled_capabilities[MIGRATION_CAPABILITY_MAX]; int64_t xbzrle_cache_size; }; diff --git a/qapi-schema.json b/qapi-schema.json index f9dbdae699..720068706a 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -438,13 +438,18 @@ # If migration has ended, it returns the total migration # time. (since 1.2) # +# @downtime: #optional only present when migration finishes correctly +# total downtime in milliseconds for the guest. +# (since 1.3) +# # Since: 0.14.0 ## { 'type': 'MigrationInfo', 'data': {'*status': 'str', '*ram': 'MigrationStats', '*disk': 'MigrationStats', '*xbzrle-cache': 'XBZRLECacheStats', - '*total-time': 'int'} } + '*total-time': 'int', + '*downtime': 'int'} } ## # @query-migrate diff --git a/qmp-commands.hx b/qmp-commands.hx index 2f8477e2a8..4686057050 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -2304,6 +2304,8 @@ The main json-object contains the following: - "total-time": total amount of ms since migration started. If migration has ended, it returns the total migration time (json-int) +- "downtime": only present when migration has finished correctly + total amount in ms for downtime that happened (json-int) - "ram": only present if "status" is "active", it is a json-object with the following RAM information (in bytes): - "transferred": amount transferred (json-int) @@ -2341,6 +2343,7 @@ Examples: "remaining":123, "total":246, "total-time":12345, + "downtime":12345, "duplicate":123, "normal":123, "normal-bytes":123456 From c00012f68b736c0ad9d0ff245373c7005ea0721a Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 13 Aug 2012 09:36:36 +0200 Subject: [PATCH 0943/2270] migration: rename expected_time to expected_downtime Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini Reviewed-by: Orit Wasserman --- arch_init.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch_init.c b/arch_init.c index 671d3545cc..1d6dda8449 100644 --- a/arch_init.c +++ b/arch_init.c @@ -538,7 +538,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) double bwidth = 0; int ret; int i; - uint64_t expected_time; + uint64_t expected_downtime; bytes_transferred_last = bytes_transferred; bwidth = qemu_get_clock_ns(rt_clock); @@ -577,24 +577,24 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) bwidth = qemu_get_clock_ns(rt_clock) - bwidth; bwidth = (bytes_transferred - bytes_transferred_last) / bwidth; - /* if we haven't transferred anything this round, force expected_time to a - * a very high value, but without crashing */ + /* if we haven't transferred anything this round, force + * expected_downtime to a very high value, but without + * crashing */ if (bwidth == 0) { bwidth = 0.000001; } qemu_put_be64(f, RAM_SAVE_FLAG_EOS); - expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth; + expected_downtime = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth; + DPRINTF("ram_save_live: expected(%" PRIu64 ") <= max(" PRIu64 ")?\n", + expected_downtime, migrate_max_downtime()); - DPRINTF("ram_save_live: expected(%" PRIu64 ") <= max(%" PRIu64 ")?\n", - expected_time, migrate_max_downtime()); - - if (expected_time <= migrate_max_downtime()) { + if (expected_downtime <= migrate_max_downtime()) { memory_global_sync_dirty_bitmap(get_system_memory()); - expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth; + expected_downtime = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth; - return expected_time <= migrate_max_downtime(); + return expected_downtime <= migrate_max_downtime(); } return 0; } From 859bc7569a2d244ee6183a99b71186462049ca86 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 13 Aug 2012 09:42:49 +0200 Subject: [PATCH 0944/2270] migration: export migrate_get_current() Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- migration.c | 2 +- migration.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/migration.c b/migration.c index 1375e7e184..fc615c8096 100644 --- a/migration.c +++ b/migration.c @@ -53,7 +53,7 @@ static NotifierList migration_state_notifiers = migrations at once. For now we don't need to add dynamic creation of migration */ -static MigrationState *migrate_get_current(void) +MigrationState *migrate_get_current(void) { static MigrationState current_migration = { .state = MIG_STATE_SETUP, diff --git a/migration.h b/migration.h index 3462917425..dabc333f5b 100644 --- a/migration.h +++ b/migration.h @@ -81,6 +81,7 @@ void remove_migration_state_change_notifier(Notifier *notify); bool migration_is_active(MigrationState *); bool migration_has_finished(MigrationState *); bool migration_has_failed(MigrationState *); +MigrationState *migrate_get_current(void); uint64_t ram_bytes_remaining(void); uint64_t ram_bytes_transferred(void); From 2c52ddf1cb3057bc2c6ae256857077627f6da43a Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 13 Aug 2012 09:53:12 +0200 Subject: [PATCH 0945/2270] migration: print expected downtime in info migrate Signed-off-by: Juan Quintela --- arch_init.c | 2 ++ hmp.c | 4 ++++ migration.c | 2 ++ migration.h | 1 + qapi-schema.json | 5 +++++ qmp-commands.hx | 6 ++++++ 6 files changed, 20 insertions(+) diff --git a/arch_init.c b/arch_init.c index 1d6dda8449..3fddb38179 100644 --- a/arch_init.c +++ b/arch_init.c @@ -539,6 +539,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) int ret; int i; uint64_t expected_downtime; + MigrationState *s = migrate_get_current(); bytes_transferred_last = bytes_transferred; bwidth = qemu_get_clock_ns(rt_clock); @@ -593,6 +594,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) if (expected_downtime <= migrate_max_downtime()) { memory_global_sync_dirty_bitmap(get_system_memory()); expected_downtime = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth; + s->expected_downtime = expected_downtime / 1000000; /* ns -> ms */ return expected_downtime <= migrate_max_downtime(); } diff --git a/hmp.c b/hmp.c index a8e5aea7c3..96e21742ec 100644 --- a/hmp.c +++ b/hmp.c @@ -152,6 +152,10 @@ void hmp_info_migrate(Monitor *mon) monitor_printf(mon, "Migration status: %s\n", info->status); monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n", info->total_time); + if (info->has_expected_downtime) { + monitor_printf(mon, "expected downtime: %" PRIu64 " milliseconds\n", + info->expected_downtime); + } if (info->has_downtime) { monitor_printf(mon, "downtime: %" PRIu64 " milliseconds\n", info->downtime); diff --git a/migration.c b/migration.c index fc615c8096..8d3e018dc0 100644 --- a/migration.c +++ b/migration.c @@ -169,6 +169,8 @@ MigrationInfo *qmp_query_migrate(Error **errp) info->has_total_time = true; info->total_time = qemu_get_clock_ms(rt_clock) - s->total_time; + info->has_expected_downtime = true; + info->expected_downtime = s->expected_downtime; info->has_ram = true; info->ram = g_malloc0(sizeof(*info->ram)); diff --git a/migration.h b/migration.h index dabc333f5b..552200c348 100644 --- a/migration.h +++ b/migration.h @@ -41,6 +41,7 @@ struct MigrationState MigrationParams params; int64_t total_time; int64_t downtime; + int64_t expected_downtime; bool enabled_capabilities[MIGRATION_CAPABILITY_MAX]; int64_t xbzrle_cache_size; }; diff --git a/qapi-schema.json b/qapi-schema.json index 720068706a..bcb5edb89d 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -442,6 +442,10 @@ # total downtime in milliseconds for the guest. # (since 1.3) # +# @expected-downtime: #optional only present while migration is active +# expected downtime in milliseconds for the guest in last walk +# of the dirty bitmap. (since 1.3) +# # Since: 0.14.0 ## { 'type': 'MigrationInfo', @@ -449,6 +453,7 @@ '*disk': 'MigrationStats', '*xbzrle-cache': 'XBZRLECacheStats', '*total-time': 'int', + '*expected-downtime': 'int', '*downtime': 'int'} } ## diff --git a/qmp-commands.hx b/qmp-commands.hx index 4686057050..5ba8c48cb4 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -2306,6 +2306,9 @@ The main json-object contains the following: time (json-int) - "downtime": only present when migration has finished correctly total amount in ms for downtime that happened (json-int) +- "expected-downtime": only present while migration is active + total amount in ms for downtime that was calculated on + the last bitmap round (json-int) - "ram": only present if "status" is "active", it is a json-object with the following RAM information (in bytes): - "transferred": amount transferred (json-int) @@ -2367,6 +2370,7 @@ Examples: "remaining":123, "total":246, "total-time":12345, + "expected-downtime":12345, "duplicate":123, "normal":123, "normal-bytes":123456 @@ -2385,6 +2389,7 @@ Examples: "remaining":1053304, "transferred":3720, "total-time":12345, + "expected-downtime":12345, "duplicate":123, "normal":123, "normal-bytes":123456 @@ -2409,6 +2414,7 @@ Examples: "remaining":1053304, "transferred":3720, "total-time":12345, + "expected-downtime":12345, "duplicate":10, "normal":3333, "normal-bytes":3412992 From 5a17077529f7feec559e1881792e89554c2ae5b6 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 17 Jul 2012 17:02:24 +0200 Subject: [PATCH 0946/2270] savevm: Factorize ram globals reset in its own function Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini Reviewed-by: Orit Wasserman --- arch_init.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/arch_init.c b/arch_init.c index 3fddb38179..6b9f949db3 100644 --- a/arch_init.c +++ b/arch_init.c @@ -481,6 +481,14 @@ static void ram_migration_cancel(void *opaque) migration_end(); } + +static void reset_ram_globals(void) +{ + last_block = NULL; + last_offset = 0; + sort_ram_list(); +} + #define MAX_WAIT 50 /* ms, half buffered_file limit */ static int ram_save_setup(QEMUFile *f, void *opaque) @@ -489,9 +497,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) RAMBlock *block; bytes_transferred = 0; - last_block = NULL; - last_offset = 0; - sort_ram_list(); + reset_ram_globals(); if (migrate_use_xbzrle()) { XBZRLE.cache = cache_init(migrate_xbzrle_cache_size() / From e44d26c8f3894a220f29ff5b27abf87f570d2c07 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 20 Jul 2012 10:16:08 +0200 Subject: [PATCH 0947/2270] ram: introduce migration_bitmap_set_dirty() It just marks a region of memory as dirty. Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini Reviewed-by: Orit Wasserman --- arch_init.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/arch_init.c b/arch_init.c index 6b9f949db3..fa470515db 100644 --- a/arch_init.c +++ b/arch_init.c @@ -331,6 +331,18 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data, static RAMBlock *last_block; static ram_addr_t last_offset; +static inline void migration_bitmap_set_dirty(MemoryRegion *mr, int length) +{ + ram_addr_t addr; + + for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) { + if (!memory_region_get_dirty(mr, addr, TARGET_PAGE_SIZE, + DIRTY_MEMORY_MIGRATION)) { + memory_region_set_dirty(mr, addr, TARGET_PAGE_SIZE); + } + } +} + /* * ram_save_block: Writes a page of memory to the stream f * @@ -493,7 +505,6 @@ static void reset_ram_globals(void) static int ram_save_setup(QEMUFile *f, void *opaque) { - ram_addr_t addr; RAMBlock *block; bytes_transferred = 0; @@ -514,12 +525,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) /* Make sure all dirty bits are set */ QLIST_FOREACH(block, &ram_list.blocks, next) { - for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) { - if (!memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE, - DIRTY_MEMORY_MIGRATION)) { - memory_region_set_dirty(block->mr, addr, TARGET_PAGE_SIZE); - } - } + migration_bitmap_set_dirty(block->mr, block->length); } memory_global_dirty_log_start(); From 69268cde142d169e2e47836bcf0a26341e30218a Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 20 Jul 2012 10:36:12 +0200 Subject: [PATCH 0948/2270] ram: Introduce migration_bitmap_test_and_reset_dirty() It just test if the dirty bit is set, and clears it. Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini Reviewed-by: Orit Wasserman --- arch_init.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/arch_init.c b/arch_init.c index fa470515db..90a722e6c9 100644 --- a/arch_init.c +++ b/arch_init.c @@ -331,6 +331,19 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data, static RAMBlock *last_block; static ram_addr_t last_offset; +static inline bool migration_bitmap_test_and_reset_dirty(MemoryRegion *mr, + ram_addr_t offset) +{ + bool ret = memory_region_get_dirty(mr, offset, TARGET_PAGE_SIZE, + DIRTY_MEMORY_MIGRATION); + + if (ret) { + memory_region_reset_dirty(mr, offset, TARGET_PAGE_SIZE, + DIRTY_MEMORY_MIGRATION); + } + return ret; +} + static inline void migration_bitmap_set_dirty(MemoryRegion *mr, int length) { ram_addr_t addr; @@ -364,14 +377,10 @@ static int ram_save_block(QEMUFile *f, bool last_stage) do { mr = block->mr; - if (memory_region_get_dirty(mr, offset, TARGET_PAGE_SIZE, - DIRTY_MEMORY_MIGRATION)) { + if (migration_bitmap_test_and_reset_dirty(mr, offset)) { uint8_t *p; int cont = (block == last_block) ? RAM_SAVE_FLAG_CONTINUE : 0; - memory_region_reset_dirty(mr, offset, TARGET_PAGE_SIZE, - DIRTY_MEMORY_MIGRATION); - p = memory_region_get_ram_ptr(mr) + offset; if (is_dup_page(p)) { From 652d7ec291d1726ad01587e13331d7277fa402ec Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 20 Jul 2012 10:37:54 +0200 Subject: [PATCH 0949/2270] ram: Export last_ram_offset() Is the only way of knowing the RAM size. Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- cpu-all.h | 1 + exec.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cpu-all.h b/cpu-all.h index 2b99682677..287b0003ea 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -518,6 +518,7 @@ extern int mem_prealloc; #define TLB_MMIO (1 << 5) void dump_exec_info(FILE *f, fprintf_function cpu_fprintf); +ram_addr_t last_ram_offset(void); #endif /* !CONFIG_USER_ONLY */ int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr, diff --git a/exec.c b/exec.c index 7899042ce9..e63ad0da3d 100644 --- a/exec.c +++ b/exec.c @@ -2454,7 +2454,7 @@ static ram_addr_t find_ram_offset(ram_addr_t size) return offset; } -static ram_addr_t last_ram_offset(void) +ram_addr_t last_ram_offset(void) { RAMBlock *block; ram_addr_t last = 0; From dd2df737ef3930f6d88116520d6ca7ff3cf0c41f Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 20 Jul 2012 10:52:51 +0200 Subject: [PATCH 0950/2270] ram: introduce migration_bitmap_sync() Helper that we use each time that we need to syncronize the migration bitmap with the other dirty bitmaps. Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- arch_init.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch_init.c b/arch_init.c index 90a722e6c9..3a5fecccc7 100644 --- a/arch_init.c +++ b/arch_init.c @@ -356,6 +356,12 @@ static inline void migration_bitmap_set_dirty(MemoryRegion *mr, int length) } } +static void migration_bitmap_sync(void) +{ + memory_global_sync_dirty_bitmap(get_system_memory()); +} + + /* * ram_save_block: Writes a page of memory to the stream f * @@ -613,7 +619,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) expected_downtime, migrate_max_downtime()); if (expected_downtime <= migrate_max_downtime()) { - memory_global_sync_dirty_bitmap(get_system_memory()); + migration_bitmap_sync(); expected_downtime = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth; s->expected_downtime = expected_downtime / 1000000; /* ns -> ms */ @@ -624,7 +630,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) static int ram_save_complete(QEMUFile *f, void *opaque) { - memory_global_sync_dirty_bitmap(get_system_memory()); + migration_bitmap_sync(); /* try transferring iterative blocks of memory */ From 3c12193d998249bcbe5099edf85039bcd25c3a80 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 4 Sep 2012 13:08:57 +0200 Subject: [PATCH 0951/2270] ram: create trace event for migration sync bitmap Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- arch_init.c | 6 ++++++ trace-events | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/arch_init.c b/arch_init.c index 3a5fecccc7..cec3ead8de 100644 --- a/arch_init.c +++ b/arch_init.c @@ -45,6 +45,7 @@ #include "hw/pcspk.h" #include "qemu/page_cache.h" #include "qmp-commands.h" +#include "trace.h" #ifdef DEBUG_ARCH_INIT #define DPRINTF(fmt, ...) \ @@ -358,7 +359,12 @@ static inline void migration_bitmap_set_dirty(MemoryRegion *mr, int length) static void migration_bitmap_sync(void) { + uint64_t num_dirty_pages_init = ram_list.dirty_pages; + + trace_migration_bitmap_sync_start(); memory_global_sync_dirty_bitmap(get_system_memory()); + trace_migration_bitmap_sync_end(ram_list.dirty_pages + - num_dirty_pages_init); } diff --git a/trace-events b/trace-events index 42b66f19f4..e2d4580d4c 100644 --- a/trace-events +++ b/trace-events @@ -921,6 +921,10 @@ ppm_save(const char *filename, void *display_surface) "%s surface=%p" savevm_section_start(void) "" savevm_section_end(unsigned int section_id) "section_id %u" +# arch_init.c +migration_bitmap_sync_start(void) "" +migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64"" + # hw/qxl.c disable qxl_interface_set_mm_time(int qid, uint32_t mm_time) "%d %d" disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t val) "%d %s addr=%u val=%u" From c6bf8e0e0cf04b40a8a22426e00ebbd727331d8b Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 20 Jul 2012 12:33:00 +0200 Subject: [PATCH 0952/2270] Separate migration bitmap This patch creates a migration bitmap, which is periodically kept in sync with the qemu bitmap. A separate copy of the dirty bitmap for the migration limits the amount of concurrent access to the qemu bitmap from iothread and migration thread (which requires taking the big lock). We use the qemu bitmap type. We have to "undo" the dirty_pages counting optimization on the general dirty bitmap and do the counting optimization with the migration local bitmap. Signed-off-by: Umesh Deshpande Signed-off-by: Paolo Bonzini Signed-off-by: Juan Quintela --- arch_init.c | 63 +++++++++++++++++++++++++++++++++---------------- cpu-all.h | 1 - exec-obsolete.h | 10 -------- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/arch_init.c b/arch_init.c index cec3ead8de..d918844028 100644 --- a/arch_init.c +++ b/arch_init.c @@ -31,6 +31,8 @@ #include "config.h" #include "monitor.h" #include "sysemu.h" +#include "bitops.h" +#include "bitmap.h" #include "arch_init.h" #include "audio/audio.h" #include "hw/pc.h" @@ -331,39 +333,57 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data, static RAMBlock *last_block; static ram_addr_t last_offset; +static unsigned long *migration_bitmap; +static uint64_t migration_dirty_pages; static inline bool migration_bitmap_test_and_reset_dirty(MemoryRegion *mr, ram_addr_t offset) { - bool ret = memory_region_get_dirty(mr, offset, TARGET_PAGE_SIZE, - DIRTY_MEMORY_MIGRATION); + bool ret; + int nr = (mr->ram_addr + offset) >> TARGET_PAGE_BITS; + + ret = test_and_clear_bit(nr, migration_bitmap); if (ret) { - memory_region_reset_dirty(mr, offset, TARGET_PAGE_SIZE, - DIRTY_MEMORY_MIGRATION); + migration_dirty_pages--; } return ret; } -static inline void migration_bitmap_set_dirty(MemoryRegion *mr, int length) +static inline bool migration_bitmap_set_dirty(MemoryRegion *mr, + ram_addr_t offset) { - ram_addr_t addr; + bool ret; + int nr = (mr->ram_addr + offset) >> TARGET_PAGE_BITS; - for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) { - if (!memory_region_get_dirty(mr, addr, TARGET_PAGE_SIZE, - DIRTY_MEMORY_MIGRATION)) { - memory_region_set_dirty(mr, addr, TARGET_PAGE_SIZE); - } + ret = test_and_set_bit(nr, migration_bitmap); + + if (!ret) { + migration_dirty_pages++; } + return ret; } static void migration_bitmap_sync(void) { - uint64_t num_dirty_pages_init = ram_list.dirty_pages; + RAMBlock *block; + ram_addr_t addr; + uint64_t num_dirty_pages_init = migration_dirty_pages; trace_migration_bitmap_sync_start(); memory_global_sync_dirty_bitmap(get_system_memory()); - trace_migration_bitmap_sync_end(ram_list.dirty_pages + + QLIST_FOREACH(block, &ram_list.blocks, next) { + for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) { + if (memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE, + DIRTY_MEMORY_MIGRATION)) { + migration_bitmap_set_dirty(block->mr, addr); + } + } + memory_region_reset_dirty(block->mr, 0, block->length, + DIRTY_MEMORY_MIGRATION); + } + trace_migration_bitmap_sync_end(migration_dirty_pages - num_dirty_pages_init); } @@ -442,7 +462,7 @@ static uint64_t bytes_transferred; static ram_addr_t ram_save_remaining(void) { - return ram_list.dirty_pages; + return migration_dirty_pages; } uint64_t ram_bytes_remaining(void) @@ -527,6 +547,11 @@ static void reset_ram_globals(void) static int ram_save_setup(QEMUFile *f, void *opaque) { RAMBlock *block; + int64_t ram_pages = last_ram_offset() >> TARGET_PAGE_BITS; + + migration_bitmap = bitmap_new(ram_pages); + bitmap_set(migration_bitmap, 1, ram_pages); + migration_dirty_pages = ram_pages; bytes_transferred = 0; reset_ram_globals(); @@ -544,13 +569,8 @@ static int ram_save_setup(QEMUFile *f, void *opaque) acct_clear(); } - /* Make sure all dirty bits are set */ - QLIST_FOREACH(block, &ram_list.blocks, next) { - migration_bitmap_set_dirty(block->mr, block->length); - } - memory_global_dirty_log_start(); - memory_global_sync_dirty_bitmap(get_system_memory()); + migration_bitmap_sync(); qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE); @@ -655,6 +675,9 @@ static int ram_save_complete(QEMUFile *f, void *opaque) qemu_put_be64(f, RAM_SAVE_FLAG_EOS); + g_free(migration_bitmap); + migration_bitmap = NULL; + return 0; } diff --git a/cpu-all.h b/cpu-all.h index 287b0003ea..6aa7e58cb1 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -500,7 +500,6 @@ typedef struct RAMBlock { typedef struct RAMList { uint8_t *phys_dirty; QLIST_HEAD(, RAMBlock) blocks; - uint64_t dirty_pages; } RAMList; extern RAMList ram_list; diff --git a/exec-obsolete.h b/exec-obsolete.h index 286e2f75e1..6d35d4b83e 100644 --- a/exec-obsolete.h +++ b/exec-obsolete.h @@ -75,11 +75,6 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t start, static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr, int dirty_flags) { - if ((dirty_flags & MIGRATION_DIRTY_FLAG) && - !cpu_physical_memory_get_dirty(addr, TARGET_PAGE_SIZE, - MIGRATION_DIRTY_FLAG)) { - ram_list.dirty_pages++; - } return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags; } @@ -93,11 +88,6 @@ static inline int cpu_physical_memory_clear_dirty_flags(ram_addr_t addr, { int mask = ~dirty_flags; - if ((dirty_flags & MIGRATION_DIRTY_FLAG) && - cpu_physical_memory_get_dirty(addr, TARGET_PAGE_SIZE, - MIGRATION_DIRTY_FLAG)) { - ram_list.dirty_pages--; - } return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] &= mask; } From 8d017193e2b66a65adf53e46a6372e55470fe7fd Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 13 Aug 2012 12:31:25 +0200 Subject: [PATCH 0953/2270] migration: Add dirty_pages_rate to query migrate output It indicates how many pages were dirtied during the last second. Signed-off-by: Juan Quintela --- arch_init.c | 18 ++++++++++++++++++ hmp.c | 4 ++++ migration.c | 2 ++ migration.h | 1 + qapi-schema.json | 8 ++++++-- 5 files changed, 31 insertions(+), 2 deletions(-) diff --git a/arch_init.c b/arch_init.c index d918844028..e6effe809a 100644 --- a/arch_init.c +++ b/arch_init.c @@ -369,6 +369,14 @@ static void migration_bitmap_sync(void) RAMBlock *block; ram_addr_t addr; uint64_t num_dirty_pages_init = migration_dirty_pages; + MigrationState *s = migrate_get_current(); + static int64_t start_time; + static int64_t num_dirty_pages_period; + int64_t end_time; + + if (!start_time) { + start_time = qemu_get_clock_ms(rt_clock); + } trace_migration_bitmap_sync_start(); memory_global_sync_dirty_bitmap(get_system_memory()); @@ -385,6 +393,16 @@ static void migration_bitmap_sync(void) } trace_migration_bitmap_sync_end(migration_dirty_pages - num_dirty_pages_init); + num_dirty_pages_period += migration_dirty_pages - num_dirty_pages_init; + end_time = qemu_get_clock_ms(rt_clock); + + /* more than 1 second = 1000 millisecons */ + if (end_time > start_time + 1000) { + s->dirty_pages_rate = num_dirty_pages_period * 1000 + / (end_time - start_time); + start_time = end_time; + num_dirty_pages_period = 0; + } } diff --git a/hmp.c b/hmp.c index 96e21742ec..2b979826ee 100644 --- a/hmp.c +++ b/hmp.c @@ -175,6 +175,10 @@ void hmp_info_migrate(Monitor *mon) info->ram->normal); monitor_printf(mon, "normal bytes: %" PRIu64 " kbytes\n", info->ram->normal_bytes >> 10); + if (info->ram->dirty_pages_rate) { + monitor_printf(mon, "dirty pages rate: %" PRIu64 " pages\n", + info->ram->dirty_pages_rate); + } } if (info->has_disk) { diff --git a/migration.c b/migration.c index 8d3e018dc0..330c16a97f 100644 --- a/migration.c +++ b/migration.c @@ -180,6 +180,8 @@ MigrationInfo *qmp_query_migrate(Error **errp) info->ram->duplicate = dup_mig_pages_transferred(); info->ram->normal = norm_mig_pages_transferred(); info->ram->normal_bytes = norm_mig_bytes_transferred(); + info->ram->dirty_pages_rate = s->dirty_pages_rate; + if (blk_mig_active()) { info->has_disk = true; diff --git a/migration.h b/migration.h index 552200c348..66d7f68bb8 100644 --- a/migration.h +++ b/migration.h @@ -42,6 +42,7 @@ struct MigrationState int64_t total_time; int64_t downtime; int64_t expected_downtime; + int64_t dirty_pages_rate; bool enabled_capabilities[MIGRATION_CAPABILITY_MAX]; int64_t xbzrle_cache_size; }; diff --git a/qapi-schema.json b/qapi-schema.json index bcb5edb89d..c615ee212d 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -383,13 +383,17 @@ # # @normal : number of normal pages (since 1.2) # -# @normal-bytes : number of normal bytes sent (since 1.2) +# @normal-bytes: number of normal bytes sent (since 1.2) +# +# @dirty-pages-rate: number of pages dirtied by second by the +# guest (since 1.3) # # Since: 0.14.0 ## { 'type': 'MigrationStats', 'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' , - 'duplicate': 'int', 'normal': 'int', 'normal-bytes': 'int' } } + 'duplicate': 'int', 'normal': 'int', 'normal-bytes': 'int', + 'dirty-pages-rate' : 'int' } } ## # @XBZRLECacheStats From 2dddf6f4133975af62e64cb6406ec1239491fa89 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 16 Aug 2011 16:43:24 -0700 Subject: [PATCH 0954/2270] BufferedFile: append, then flush Simplify the logic for pushing data from the buffer to the output pipe/socket. This also matches more closely what will be the operation of the migration thread. Signed-off-by: Paolo Bonzini Reviewed-by: Paolo Bonzini Reviewed-by: Orit Wasserman --- buffered_file.c | 50 +++++++++++-------------------------------------- 1 file changed, 11 insertions(+), 39 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 4148abbee0..71558009bd 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -75,7 +75,7 @@ static void buffered_flush(QEMUFileBuffered *s) DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size); - while (offset < s->buffer_size) { + while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) { ssize_t ret; ret = s->put_buffer(s->opaque, s->buffer + offset, @@ -93,6 +93,7 @@ static void buffered_flush(QEMUFileBuffered *s) } else { DPRINTF("flushed %zd byte(s)\n", ret); offset += ret; + s->bytes_xfer += ret; } } @@ -104,8 +105,7 @@ static void buffered_flush(QEMUFileBuffered *s) static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size) { QEMUFileBuffered *s = opaque; - int offset = 0, error; - ssize_t ret; + int error; DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos); @@ -118,48 +118,22 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in DPRINTF("unfreezing output\n"); s->freeze_output = 0; - buffered_flush(s); - - while (!s->freeze_output && offset < size) { - if (s->bytes_xfer > s->xfer_limit) { - DPRINTF("transfer limit exceeded when putting\n"); - break; - } - - ret = s->put_buffer(s->opaque, buf + offset, size - offset); - if (ret == -EAGAIN) { - DPRINTF("backend not ready, freezing\n"); - s->freeze_output = 1; - break; - } - - if (ret <= 0) { - DPRINTF("error putting\n"); - qemu_file_set_error(s->file, ret); - offset = -EINVAL; - break; - } - - DPRINTF("put %zd byte(s)\n", ret); - offset += ret; - s->bytes_xfer += ret; - } - - if (offset >= 0) { + if (size > 0) { DPRINTF("buffering %d bytes\n", size - offset); - buffered_append(s, buf + offset, size - offset); - offset = size; + buffered_append(s, buf, size); } + buffered_flush(s); + if (pos == 0 && size == 0) { DPRINTF("file is ready\n"); - if (s->bytes_xfer <= s->xfer_limit) { + if (!s->freeze_output && s->bytes_xfer < s->xfer_limit) { DPRINTF("notifying client\n"); s->put_ready(s->opaque); } } - return offset; + return size; } static int buffered_close(void *opaque) @@ -169,6 +143,7 @@ static int buffered_close(void *opaque) DPRINTF("closing\n"); + s->xfer_limit = INT_MAX; while (!qemu_file_get_error(s->file) && s->buffer_size) { buffered_flush(s); if (s->freeze_output) @@ -248,10 +223,7 @@ static void buffered_rate_tick(void *opaque) s->bytes_xfer = 0; - buffered_flush(s); - - /* Add some checks around this */ - s->put_ready(s->opaque); + buffered_put_buffer(s, NULL, 0, 0); } QEMUFile *qemu_fopen_ops_buffered(void *opaque, From 8e92c9e24f8c4edd7976aca82abf90e9a12667b4 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 20 Jul 2012 13:04:42 +0200 Subject: [PATCH 0955/2270] buffered_file: rename opaque to migration_state Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- buffered_file.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 71558009bd..33b700be50 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -27,7 +27,7 @@ typedef struct QEMUFileBuffered BufferedPutReadyFunc *put_ready; BufferedWaitForUnfreezeFunc *wait_for_unfreeze; BufferedCloseFunc *close; - void *opaque; + void *migration_state; QEMUFile *file; int freeze_output; size_t bytes_xfer; @@ -78,7 +78,7 @@ static void buffered_flush(QEMUFileBuffered *s) while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) { ssize_t ret; - ret = s->put_buffer(s->opaque, s->buffer + offset, + ret = s->put_buffer(s->migration_state, s->buffer + offset, s->buffer_size - offset); if (ret == -EAGAIN) { DPRINTF("backend not ready, freezing\n"); @@ -129,7 +129,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in DPRINTF("file is ready\n"); if (!s->freeze_output && s->bytes_xfer < s->xfer_limit) { DPRINTF("notifying client\n"); - s->put_ready(s->opaque); + s->put_ready(s->migration_state); } } @@ -147,10 +147,10 @@ static int buffered_close(void *opaque) while (!qemu_file_get_error(s->file) && s->buffer_size) { buffered_flush(s); if (s->freeze_output) - s->wait_for_unfreeze(s->opaque); + s->wait_for_unfreeze(s->migration_state); } - ret = s->close(s->opaque); + ret = s->close(s->migration_state); qemu_del_timer(s->timer); qemu_free_timer(s->timer); @@ -237,7 +237,7 @@ QEMUFile *qemu_fopen_ops_buffered(void *opaque, s = g_malloc0(sizeof(*s)); - s->opaque = opaque; + s->migration_state = opaque; s->xfer_limit = bytes_per_sec / 10; s->put_buffer = put_buffer; s->put_ready = put_ready; From c7a8f0cdd25ed552e6dba124877bd3364054c55c Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 20 Jul 2012 13:07:17 +0200 Subject: [PATCH 0956/2270] buffered_file: opaque is MigrationState It always have that type, just change it. We will remove buffered file later on the migration thread series. Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- buffered_file.c | 6 +++--- buffered_file.h | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 33b700be50..59d952df0a 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -27,7 +27,7 @@ typedef struct QEMUFileBuffered BufferedPutReadyFunc *put_ready; BufferedWaitForUnfreezeFunc *wait_for_unfreeze; BufferedCloseFunc *close; - void *migration_state; + MigrationState *migration_state; QEMUFile *file; int freeze_output; size_t bytes_xfer; @@ -226,7 +226,7 @@ static void buffered_rate_tick(void *opaque) buffered_put_buffer(s, NULL, 0, 0); } -QEMUFile *qemu_fopen_ops_buffered(void *opaque, +QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state, size_t bytes_per_sec, BufferedPutFunc *put_buffer, BufferedPutReadyFunc *put_ready, @@ -237,7 +237,7 @@ QEMUFile *qemu_fopen_ops_buffered(void *opaque, s = g_malloc0(sizeof(*s)); - s->migration_state = opaque; + s->migration_state = migration_state; s->xfer_limit = bytes_per_sec / 10; s->put_buffer = put_buffer; s->put_ready = put_ready; diff --git a/buffered_file.h b/buffered_file.h index 98d358baea..39f7fa005d 100644 --- a/buffered_file.h +++ b/buffered_file.h @@ -15,13 +15,15 @@ #define QEMU_BUFFERED_FILE_H #include "hw/hw.h" +#include "migration.h" typedef ssize_t (BufferedPutFunc)(void *opaque, const void *data, size_t size); typedef void (BufferedPutReadyFunc)(void *opaque); typedef void (BufferedWaitForUnfreezeFunc)(void *opaque); typedef int (BufferedCloseFunc)(void *opaque); -QEMUFile *qemu_fopen_ops_buffered(void *opaque, size_t xfer_limit, +QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state, + size_t xfer_limit, BufferedPutFunc *put_buffer, BufferedPutReadyFunc *put_ready, BufferedWaitForUnfreezeFunc *wait_for_unfreeze, From c87b015bc71734db74f5bdffeda122a224c75bbb Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 20 Jul 2012 13:10:54 +0200 Subject: [PATCH 0957/2270] buffered_file: unfold migrate_fd_put_buffer We only used it once, just remove the callback indirection Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- buffered_file.c | 7 ++----- buffered_file.h | 2 -- migration.c | 6 ++---- migration.h | 3 +++ 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 59d952df0a..702a7266b6 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -23,7 +23,6 @@ typedef struct QEMUFileBuffered { - BufferedPutFunc *put_buffer; BufferedPutReadyFunc *put_ready; BufferedWaitForUnfreezeFunc *wait_for_unfreeze; BufferedCloseFunc *close; @@ -78,8 +77,8 @@ static void buffered_flush(QEMUFileBuffered *s) while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) { ssize_t ret; - ret = s->put_buffer(s->migration_state, s->buffer + offset, - s->buffer_size - offset); + ret = migrate_fd_put_buffer(s->migration_state, s->buffer + offset, + s->buffer_size - offset); if (ret == -EAGAIN) { DPRINTF("backend not ready, freezing\n"); s->freeze_output = 1; @@ -228,7 +227,6 @@ static void buffered_rate_tick(void *opaque) QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state, size_t bytes_per_sec, - BufferedPutFunc *put_buffer, BufferedPutReadyFunc *put_ready, BufferedWaitForUnfreezeFunc *wait_for_unfreeze, BufferedCloseFunc *close) @@ -239,7 +237,6 @@ QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state, s->migration_state = migration_state; s->xfer_limit = bytes_per_sec / 10; - s->put_buffer = put_buffer; s->put_ready = put_ready; s->wait_for_unfreeze = wait_for_unfreeze; s->close = close; diff --git a/buffered_file.h b/buffered_file.h index 39f7fa005d..ca7e62d4b3 100644 --- a/buffered_file.h +++ b/buffered_file.h @@ -17,14 +17,12 @@ #include "hw/hw.h" #include "migration.h" -typedef ssize_t (BufferedPutFunc)(void *opaque, const void *data, size_t size); typedef void (BufferedPutReadyFunc)(void *opaque); typedef void (BufferedWaitForUnfreezeFunc)(void *opaque); typedef int (BufferedCloseFunc)(void *opaque); QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state, size_t xfer_limit, - BufferedPutFunc *put_buffer, BufferedPutReadyFunc *put_ready, BufferedWaitForUnfreezeFunc *wait_for_unfreeze, BufferedCloseFunc *close); diff --git a/migration.c b/migration.c index 330c16a97f..f6ee7cdb6a 100644 --- a/migration.c +++ b/migration.c @@ -295,10 +295,9 @@ static void migrate_fd_put_notify(void *opaque) } } -static ssize_t migrate_fd_put_buffer(void *opaque, const void *data, - size_t size) +ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data, + size_t size) { - MigrationState *s = opaque; ssize_t ret; if (s->state != MIG_STATE_ACTIVE) { @@ -436,7 +435,6 @@ void migrate_fd_connect(MigrationState *s) s->state = MIG_STATE_ACTIVE; s->file = qemu_fopen_ops_buffered(s, s->bandwidth_limit, - migrate_fd_put_buffer, migrate_fd_put_ready, migrate_fd_wait_for_unfreeze, migrate_fd_close); diff --git a/migration.h b/migration.h index 66d7f68bb8..02d0219e86 100644 --- a/migration.h +++ b/migration.h @@ -78,6 +78,9 @@ void migrate_fd_error(MigrationState *s); void migrate_fd_connect(MigrationState *s); +ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data, + size_t size); + void add_migration_state_change_notifier(Notifier *notify); void remove_migration_state_change_notifier(Notifier *notify); bool migration_is_active(MigrationState *); From 2c9adcb850bba7a24caec4d666dc01deca9f7649 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 20 Jul 2012 13:13:59 +0200 Subject: [PATCH 0958/2270] buffered_file: unfold migrate_fd_put_ready We only use it once, just remove the callback indirection. Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- buffered_file.c | 5 +---- buffered_file.h | 2 -- migration.c | 4 +--- migration.h | 1 + 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 702a7266b6..4c6a7976b1 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -23,7 +23,6 @@ typedef struct QEMUFileBuffered { - BufferedPutReadyFunc *put_ready; BufferedWaitForUnfreezeFunc *wait_for_unfreeze; BufferedCloseFunc *close; MigrationState *migration_state; @@ -128,7 +127,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in DPRINTF("file is ready\n"); if (!s->freeze_output && s->bytes_xfer < s->xfer_limit) { DPRINTF("notifying client\n"); - s->put_ready(s->migration_state); + migrate_fd_put_ready(s->migration_state); } } @@ -227,7 +226,6 @@ static void buffered_rate_tick(void *opaque) QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state, size_t bytes_per_sec, - BufferedPutReadyFunc *put_ready, BufferedWaitForUnfreezeFunc *wait_for_unfreeze, BufferedCloseFunc *close) { @@ -237,7 +235,6 @@ QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state, s->migration_state = migration_state; s->xfer_limit = bytes_per_sec / 10; - s->put_ready = put_ready; s->wait_for_unfreeze = wait_for_unfreeze; s->close = close; diff --git a/buffered_file.h b/buffered_file.h index ca7e62d4b3..dd239b3d02 100644 --- a/buffered_file.h +++ b/buffered_file.h @@ -17,13 +17,11 @@ #include "hw/hw.h" #include "migration.h" -typedef void (BufferedPutReadyFunc)(void *opaque); typedef void (BufferedWaitForUnfreezeFunc)(void *opaque); typedef int (BufferedCloseFunc)(void *opaque); QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state, size_t xfer_limit, - BufferedPutReadyFunc *put_ready, BufferedWaitForUnfreezeFunc *wait_for_unfreeze, BufferedCloseFunc *close); diff --git a/migration.c b/migration.c index f6ee7cdb6a..051b1b56aa 100644 --- a/migration.c +++ b/migration.c @@ -318,9 +318,8 @@ ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data, return ret; } -static void migrate_fd_put_ready(void *opaque) +void migrate_fd_put_ready(MigrationState *s) { - MigrationState *s = opaque; int ret; if (s->state != MIG_STATE_ACTIVE) { @@ -435,7 +434,6 @@ void migrate_fd_connect(MigrationState *s) s->state = MIG_STATE_ACTIVE; s->file = qemu_fopen_ops_buffered(s, s->bandwidth_limit, - migrate_fd_put_ready, migrate_fd_wait_for_unfreeze, migrate_fd_close); diff --git a/migration.h b/migration.h index 02d0219e86..031c2ab2ed 100644 --- a/migration.h +++ b/migration.h @@ -80,6 +80,7 @@ void migrate_fd_connect(MigrationState *s); ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data, size_t size); +void migrate_fd_put_ready(MigrationState *s); void add_migration_state_change_notifier(Notifier *notify); void remove_migration_state_change_notifier(Notifier *notify); From 749f7909d942f5c7425d0895242ce720cd663e92 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 20 Jul 2012 13:16:28 +0200 Subject: [PATCH 0959/2270] buffered_file: unfold migrate_fd_wait_for_unfreeze We only used it once, just remove the callback indirection. Signed-off-by: Juan Quintela --- buffered_file.c | 5 +---- buffered_file.h | 2 -- migration.c | 4 +--- migration.h | 1 + 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 4c6a7976b1..d257496b7e 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -23,7 +23,6 @@ typedef struct QEMUFileBuffered { - BufferedWaitForUnfreezeFunc *wait_for_unfreeze; BufferedCloseFunc *close; MigrationState *migration_state; QEMUFile *file; @@ -145,7 +144,7 @@ static int buffered_close(void *opaque) while (!qemu_file_get_error(s->file) && s->buffer_size) { buffered_flush(s); if (s->freeze_output) - s->wait_for_unfreeze(s->migration_state); + migrate_fd_wait_for_unfreeze(s->migration_state); } ret = s->close(s->migration_state); @@ -226,7 +225,6 @@ static void buffered_rate_tick(void *opaque) QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state, size_t bytes_per_sec, - BufferedWaitForUnfreezeFunc *wait_for_unfreeze, BufferedCloseFunc *close) { QEMUFileBuffered *s; @@ -235,7 +233,6 @@ QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state, s->migration_state = migration_state; s->xfer_limit = bytes_per_sec / 10; - s->wait_for_unfreeze = wait_for_unfreeze; s->close = close; s->file = qemu_fopen_ops(s, buffered_put_buffer, NULL, diff --git a/buffered_file.h b/buffered_file.h index dd239b3d02..926e5c6fc5 100644 --- a/buffered_file.h +++ b/buffered_file.h @@ -17,12 +17,10 @@ #include "hw/hw.h" #include "migration.h" -typedef void (BufferedWaitForUnfreezeFunc)(void *opaque); typedef int (BufferedCloseFunc)(void *opaque); QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state, size_t xfer_limit, - BufferedWaitForUnfreezeFunc *wait_for_unfreeze, BufferedCloseFunc *close); #endif diff --git a/migration.c b/migration.c index 051b1b56aa..30def68f1d 100644 --- a/migration.c +++ b/migration.c @@ -370,9 +370,8 @@ static void migrate_fd_cancel(MigrationState *s) migrate_fd_cleanup(s); } -static void migrate_fd_wait_for_unfreeze(void *opaque) +void migrate_fd_wait_for_unfreeze(MigrationState *s) { - MigrationState *s = opaque; int ret; DPRINTF("wait for unfreeze\n"); @@ -434,7 +433,6 @@ void migrate_fd_connect(MigrationState *s) s->state = MIG_STATE_ACTIVE; s->file = qemu_fopen_ops_buffered(s, s->bandwidth_limit, - migrate_fd_wait_for_unfreeze, migrate_fd_close); DPRINTF("beginning savevm\n"); diff --git a/migration.h b/migration.h index 031c2ab2ed..d6341d66a3 100644 --- a/migration.h +++ b/migration.h @@ -81,6 +81,7 @@ void migrate_fd_connect(MigrationState *s); ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data, size_t size); void migrate_fd_put_ready(MigrationState *s); +void migrate_fd_wait_for_unfreeze(MigrationState *s); void add_migration_state_change_notifier(Notifier *notify); void remove_migration_state_change_notifier(Notifier *notify); From 11c7674129a81b5b69e00ad252a63186e15bf6b6 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 20 Jul 2012 13:19:36 +0200 Subject: [PATCH 0960/2270] buffered_file: unfold migrate_fd_close We only used it once, just remove the callback indirection. Signed-off-by: Juan Quintela --- buffered_file.c | 7 ++----- buffered_file.h | 5 +---- migration.c | 8 ++------ migration.h | 1 + 4 files changed, 6 insertions(+), 15 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index d257496b7e..4fca774dd8 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -23,7 +23,6 @@ typedef struct QEMUFileBuffered { - BufferedCloseFunc *close; MigrationState *migration_state; QEMUFile *file; int freeze_output; @@ -147,7 +146,7 @@ static int buffered_close(void *opaque) migrate_fd_wait_for_unfreeze(s->migration_state); } - ret = s->close(s->migration_state); + ret = migrate_fd_close(s->migration_state); qemu_del_timer(s->timer); qemu_free_timer(s->timer); @@ -224,8 +223,7 @@ static void buffered_rate_tick(void *opaque) } QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state, - size_t bytes_per_sec, - BufferedCloseFunc *close) + size_t bytes_per_sec) { QEMUFileBuffered *s; @@ -233,7 +231,6 @@ QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state, s->migration_state = migration_state; s->xfer_limit = bytes_per_sec / 10; - s->close = close; s->file = qemu_fopen_ops(s, buffered_put_buffer, NULL, buffered_close, buffered_rate_limit, diff --git a/buffered_file.h b/buffered_file.h index 926e5c6fc5..8a38754146 100644 --- a/buffered_file.h +++ b/buffered_file.h @@ -17,10 +17,7 @@ #include "hw/hw.h" #include "migration.h" -typedef int (BufferedCloseFunc)(void *opaque); - QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state, - size_t xfer_limit, - BufferedCloseFunc *close); + size_t xfer_limit); #endif diff --git a/migration.c b/migration.c index 30def68f1d..f647a3fccb 100644 --- a/migration.c +++ b/migration.c @@ -392,10 +392,8 @@ void migrate_fd_wait_for_unfreeze(MigrationState *s) } } -static int migrate_fd_close(void *opaque) +int migrate_fd_close(MigrationState *s) { - MigrationState *s = opaque; - qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); return s->close(s); } @@ -431,9 +429,7 @@ void migrate_fd_connect(MigrationState *s) int ret; s->state = MIG_STATE_ACTIVE; - s->file = qemu_fopen_ops_buffered(s, - s->bandwidth_limit, - migrate_fd_close); + s->file = qemu_fopen_ops_buffered(s, s->bandwidth_limit); DPRINTF("beginning savevm\n"); ret = qemu_savevm_state_begin(s->file, &s->params); diff --git a/migration.h b/migration.h index d6341d66a3..ec022d604f 100644 --- a/migration.h +++ b/migration.h @@ -82,6 +82,7 @@ ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data, size_t size); void migrate_fd_put_ready(MigrationState *s); void migrate_fd_wait_for_unfreeze(MigrationState *s); +int migrate_fd_close(MigrationState *s); void add_migration_state_change_notifier(Notifier *notify); void remove_migration_state_change_notifier(Notifier *notify); From 796b4b0f5011e30cffbc57ed5a4ab93c6f5eaab7 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 20 Jul 2012 13:33:53 +0200 Subject: [PATCH 0961/2270] buffered_file: We can access directly to bandwidth_limit Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- buffered_file.c | 5 ++--- buffered_file.h | 3 +-- migration.c | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 4fca774dd8..43e68b6515 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -222,15 +222,14 @@ static void buffered_rate_tick(void *opaque) buffered_put_buffer(s, NULL, 0, 0); } -QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state, - size_t bytes_per_sec) +QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state) { QEMUFileBuffered *s; s = g_malloc0(sizeof(*s)); s->migration_state = migration_state; - s->xfer_limit = bytes_per_sec / 10; + s->xfer_limit = migration_state->bandwidth_limit / 10; s->file = qemu_fopen_ops(s, buffered_put_buffer, NULL, buffered_close, buffered_rate_limit, diff --git a/buffered_file.h b/buffered_file.h index 8a38754146..ef010febfe 100644 --- a/buffered_file.h +++ b/buffered_file.h @@ -17,7 +17,6 @@ #include "hw/hw.h" #include "migration.h" -QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state, - size_t xfer_limit); +QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state); #endif diff --git a/migration.c b/migration.c index f647a3fccb..ea21dc40e1 100644 --- a/migration.c +++ b/migration.c @@ -429,7 +429,7 @@ void migrate_fd_connect(MigrationState *s) int ret; s->state = MIG_STATE_ACTIVE; - s->file = qemu_fopen_ops_buffered(s, s->bandwidth_limit); + s->file = qemu_fopen_ops_buffered(s); DPRINTF("beginning savevm\n"); ret = qemu_savevm_state_begin(s->file, &s->params); From 3d6dff316f20137a87e099c30136358df029c0f6 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 24 Aug 2012 11:45:31 +0200 Subject: [PATCH 0962/2270] buffered_file: callers of buffered_flush() already check for errors Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- buffered_file.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 43e68b6515..747d672b43 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -61,13 +61,6 @@ static void buffered_append(QEMUFileBuffered *s, static void buffered_flush(QEMUFileBuffered *s) { size_t offset = 0; - int error; - - error = qemu_file_get_error(s->file); - if (error != 0) { - DPRINTF("flush when error, bailing: %s\n", strerror(-error)); - return; - } DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size); From d2dbc8e6a95a9f66f886c35db42786efc906c777 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 24 Aug 2012 12:43:04 +0200 Subject: [PATCH 0963/2270] buffered_file: make buffered_flush return the error code Or the amount of data written if there is no error. Adjust all callers. Signed-off-by: Juan Quintela --- buffered_file.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 747d672b43..d3bc160835 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -58,26 +58,26 @@ static void buffered_append(QEMUFileBuffered *s, s->buffer_size += size; } -static void buffered_flush(QEMUFileBuffered *s) +static ssize_t buffered_flush(QEMUFileBuffered *s) { size_t offset = 0; + ssize_t ret = 0; DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size); while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) { - ssize_t ret; ret = migrate_fd_put_buffer(s->migration_state, s->buffer + offset, s->buffer_size - offset); if (ret == -EAGAIN) { DPRINTF("backend not ready, freezing\n"); + ret = 0; s->freeze_output = 1; break; } if (ret <= 0) { DPRINTF("error flushing data, %zd\n", ret); - qemu_file_set_error(s->file, ret); break; } else { DPRINTF("flushed %zd byte(s)\n", ret); @@ -89,12 +89,17 @@ static void buffered_flush(QEMUFileBuffered *s) DPRINTF("flushed %zu of %zu byte(s)\n", offset, s->buffer_size); memmove(s->buffer, s->buffer + offset, s->buffer_size - offset); s->buffer_size -= offset; + + if (ret < 0) { + return ret; + } + return offset; } static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size) { QEMUFileBuffered *s = opaque; - int error; + ssize_t error; DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos); @@ -112,7 +117,13 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in buffered_append(s, buf, size); } - buffered_flush(s); + error = buffered_flush(s); + if (error < 0) { + DPRINTF("buffered flush error. bailing: %s\n", strerror(-error)); + qemu_file_set_error(s->file, error); + + return error; + } if (pos == 0 && size == 0) { DPRINTF("file is ready\n"); @@ -128,19 +139,25 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in static int buffered_close(void *opaque) { QEMUFileBuffered *s = opaque; - int ret; + ssize_t ret = 0; + int ret2; DPRINTF("closing\n"); s->xfer_limit = INT_MAX; while (!qemu_file_get_error(s->file) && s->buffer_size) { - buffered_flush(s); + ret = buffered_flush(s); + if (ret < 0) { + break; + } if (s->freeze_output) migrate_fd_wait_for_unfreeze(s->migration_state); } - ret = migrate_fd_close(s->migration_state); - + ret2 = migrate_fd_close(s->migration_state); + if (ret >= 0) { + ret = ret2; + } qemu_del_timer(s->timer); qemu_free_timer(s->timer); g_free(s->buffer); From 9499743f36169cf7d974640f123bc29836f75a2d Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 24 Aug 2012 12:51:48 +0200 Subject: [PATCH 0964/2270] migration: make migrate_fd_wait_for_unfreeze() return errors Adjust all callers Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- buffered_file.c | 8 ++++++-- migration.c | 7 ++++--- migration.h | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index d3bc160835..77928f02c1 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -150,8 +150,12 @@ static int buffered_close(void *opaque) if (ret < 0) { break; } - if (s->freeze_output) - migrate_fd_wait_for_unfreeze(s->migration_state); + if (s->freeze_output) { + ret = migrate_fd_wait_for_unfreeze(s->migration_state); + if (ret < 0) { + break; + } + } } ret2 = migrate_fd_close(s->migration_state); diff --git a/migration.c b/migration.c index ea21dc40e1..2c93951423 100644 --- a/migration.c +++ b/migration.c @@ -370,13 +370,13 @@ static void migrate_fd_cancel(MigrationState *s) migrate_fd_cleanup(s); } -void migrate_fd_wait_for_unfreeze(MigrationState *s) +int migrate_fd_wait_for_unfreeze(MigrationState *s) { int ret; DPRINTF("wait for unfreeze\n"); if (s->state != MIG_STATE_ACTIVE) - return; + return -EINVAL; do { fd_set wfds; @@ -388,8 +388,9 @@ void migrate_fd_wait_for_unfreeze(MigrationState *s) } while (ret == -1 && (s->get_error(s)) == EINTR); if (ret == -1) { - qemu_file_set_error(s->file, -s->get_error(s)); + return -s->get_error(s); } + return 0; } int migrate_fd_close(MigrationState *s) diff --git a/migration.h b/migration.h index ec022d604f..1c3e9b750e 100644 --- a/migration.h +++ b/migration.h @@ -81,7 +81,7 @@ void migrate_fd_connect(MigrationState *s); ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data, size_t size); void migrate_fd_put_ready(MigrationState *s); -void migrate_fd_wait_for_unfreeze(MigrationState *s); +int migrate_fd_wait_for_unfreeze(MigrationState *s); int migrate_fd_close(MigrationState *s); void add_migration_state_change_notifier(Notifier *notify); From ffbfc74d1eb822ed086503a6c24413617c19d31a Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 28 Aug 2012 13:54:06 +0200 Subject: [PATCH 0965/2270] savevm: unexport qemu_fflush It is not used outside of savevm.c Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- qemu-file.h | 1 - savevm.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/qemu-file.h b/qemu-file.h index 31b83f6bb3..d8487cd881 100644 --- a/qemu-file.h +++ b/qemu-file.h @@ -71,7 +71,6 @@ QEMUFile *qemu_fopen_socket(int fd); QEMUFile *qemu_popen(FILE *popen_file, const char *mode); QEMUFile *qemu_popen_cmd(const char *command, const char *mode); int qemu_stdio_fd(QEMUFile *f); -void qemu_fflush(QEMUFile *f); int qemu_fclose(QEMUFile *f); void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size); void qemu_put_byte(QEMUFile *f, int v); diff --git a/savevm.c b/savevm.c index 31fd2e0ad3..cf5f9477df 100644 --- a/savevm.c +++ b/savevm.c @@ -461,7 +461,7 @@ static void qemu_file_set_if_error(QEMUFile *f, int ret) * * In case of error, last_error is set. */ -void qemu_fflush(QEMUFile *f) +static void qemu_fflush(QEMUFile *f) { if (!f->put_buffer) return; From e398d61b4777125f32a99fa49519c5edbb00809b Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 29 Aug 2012 19:03:09 +0200 Subject: [PATCH 0966/2270] virtio-net: use qemu_get_buffer() in a temp buffer qemu_fseek() is known to be wrong. Would be removed on the next commit. This code should never been used (value has been MAC_TABLE_ENTRIES since 2009). Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- hw/virtio-net.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 8342391d90..50ba728c02 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -921,7 +921,9 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) qemu_get_buffer(f, n->mac_table.macs, n->mac_table.in_use * ETH_ALEN); } else if (n->mac_table.in_use) { - qemu_fseek(f, n->mac_table.in_use * ETH_ALEN, SEEK_CUR); + uint8_t *buf = g_malloc0(n->mac_table.in_use); + qemu_get_buffer(f, buf, n->mac_table.in_use * ETH_ALEN); + g_free(buf); n->mac_table.multi_overflow = n->mac_table.uni_overflow = 1; n->mac_table.in_use = 0; } From e5ae97cee4c0ecd252991aa868c6e233ef8c8f35 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 29 Aug 2012 19:04:47 +0200 Subject: [PATCH 0967/2270] savevm: Remove qemu_fseek() It has no users, and is only half implemented. Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- qemu-file.h | 1 - savevm.c | 21 --------------------- 2 files changed, 22 deletions(-) diff --git a/qemu-file.h b/qemu-file.h index d8487cd881..7fe7274d1f 100644 --- a/qemu-file.h +++ b/qemu-file.h @@ -232,6 +232,5 @@ static inline void qemu_get_sbe64s(QEMUFile *f, int64_t *pv) } int64_t qemu_ftell(QEMUFile *f); -int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence); #endif diff --git a/savevm.c b/savevm.c index cf5f9477df..8a785fc783 100644 --- a/savevm.c +++ b/savevm.c @@ -676,27 +676,6 @@ int64_t qemu_ftell(QEMUFile *f) return f->buf_offset - f->buf_size + f->buf_index; } -int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence) -{ - if (whence == SEEK_SET) { - /* nothing to do */ - } else if (whence == SEEK_CUR) { - pos += qemu_ftell(f); - } else { - /* SEEK_END not supported */ - return -1; - } - if (f->put_buffer) { - qemu_fflush(f); - f->buf_offset = pos; - } else { - f->buf_offset = pos; - f->buf_index = 0; - f->buf_size = 0; - } - return pos; -} - int qemu_file_rate_limit(QEMUFile *f) { if (f->rate_limit) From 7311bea33fab3bed02e9fca8b36fd6234a3a7cb9 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 29 Aug 2012 19:08:59 +0200 Subject: [PATCH 0968/2270] savevm: make qemu_fflush() return an error code Adjust all the callers. We moved the set of last_error from inside qemu_fflush() to all the callers. Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- savevm.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/savevm.c b/savevm.c index 8a785fc783..0705cd73bc 100644 --- a/savevm.c +++ b/savevm.c @@ -459,23 +459,22 @@ static void qemu_file_set_if_error(QEMUFile *f, int ret) /** Flushes QEMUFile buffer * - * In case of error, last_error is set. */ -static void qemu_fflush(QEMUFile *f) +static int qemu_fflush(QEMUFile *f) { + int ret = 0; + if (!f->put_buffer) - return; + return 0; if (f->is_write && f->buf_index > 0) { - int len; - - len = f->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index); - if (len > 0) + ret = f->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index); + if (ret >= 0) { f->buf_offset += f->buf_index; - else - qemu_file_set_error(f, -EINVAL); + } f->buf_index = 0; } + return ret; } static void qemu_fill_buffer(QEMUFile *f) @@ -533,9 +532,13 @@ static int qemu_fclose_internal(QEMUFile *f) */ int qemu_fclose(QEMUFile *f) { - int ret; - qemu_fflush(f); - ret = qemu_fclose_internal(f); + int ret, ret2; + ret = qemu_fflush(f); + ret2 = qemu_fclose_internal(f); + + if (ret >= 0) { + ret = ret2; + } /* If any error was spotted before closing, we should report it * instead of the close() return value. */ @@ -570,8 +573,10 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) f->buf_index += l; buf += l; size -= l; - if (f->buf_index >= IO_BUF_SIZE) - qemu_fflush(f); + if (f->buf_index >= IO_BUF_SIZE) { + int ret = qemu_fflush(f); + qemu_file_set_if_error(f, ret); + } } } @@ -585,8 +590,10 @@ void qemu_put_byte(QEMUFile *f, int v) f->buf[f->buf_index++] = v; f->is_write = 1; - if (f->buf_index >= IO_BUF_SIZE) - qemu_fflush(f); + if (f->buf_index >= IO_BUF_SIZE) { + int ret = qemu_fflush(f); + qemu_file_set_if_error(f, ret); + } } static void qemu_file_skip(QEMUFile *f, int size) From 29eee86f312a7351b0e694e48b435084355630f7 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 29 Aug 2012 19:14:54 +0200 Subject: [PATCH 0969/2270] savevm: unfold qemu_fclose_internal() It was used only one, and was only one if. It makes error handling saner. Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- savevm.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/savevm.c b/savevm.c index 0705cd73bc..ba69b44c8b 100644 --- a/savevm.c +++ b/savevm.c @@ -506,22 +506,6 @@ static void qemu_fill_buffer(QEMUFile *f) qemu_file_set_error(f, len); } -/** Calls close function and set last_error if needed - * - * Internal function. qemu_fflush() must be called before this. - * - * Returns f->close() return value, or 0 if close function is not set. - */ -static int qemu_fclose_internal(QEMUFile *f) -{ - int ret = 0; - if (f->close) { - ret = f->close(f->opaque); - qemu_file_set_if_error(f, ret); - } - return ret; -} - /** Closes the file * * Returns negative error value if any error happened on previous operations or @@ -532,12 +516,14 @@ static int qemu_fclose_internal(QEMUFile *f) */ int qemu_fclose(QEMUFile *f) { - int ret, ret2; + int ret; ret = qemu_fflush(f); - ret2 = qemu_fclose_internal(f); - if (ret >= 0) { - ret = ret2; + if (f->close) { + int ret2 = f->close(f->opaque); + if (ret >= 0) { + ret = ret2; + } } /* If any error was spotted before closing, we should report it * instead of the close() return value. From 3aee4be1de440de08ef68b936e51e028a9f6f6ab Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 29 Aug 2012 19:16:56 +0200 Subject: [PATCH 0970/2270] savevm: unexport qemu_ftell() It was unused out of savevm.c. Signed-off-by: Juan Quintela --- qemu-file.h | 3 --- savevm.c | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/qemu-file.h b/qemu-file.h index 7fe7274d1f..289849a789 100644 --- a/qemu-file.h +++ b/qemu-file.h @@ -230,7 +230,4 @@ static inline void qemu_get_sbe64s(QEMUFile *f, int64_t *pv) { qemu_get_be64s(f, (uint64_t *)pv); } - -int64_t qemu_ftell(QEMUFile *f); - #endif diff --git a/savevm.c b/savevm.c index ba69b44c8b..32fe7a2067 100644 --- a/savevm.c +++ b/savevm.c @@ -664,7 +664,7 @@ int qemu_get_byte(QEMUFile *f) return result; } -int64_t qemu_ftell(QEMUFile *f) +static int64_t qemu_ftell(QEMUFile *f) { return f->buf_offset - f->buf_size + f->buf_index; } From 02c4a0511bc58b005511c94055a55b1e19c6be71 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 29 Aug 2012 19:36:26 +0200 Subject: [PATCH 0971/2270] savevm: make qemu_fill_buffer() be consistent It was setting last_error directly once, and with the helper the other time. Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- savevm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/savevm.c b/savevm.c index 32fe7a2067..943d100e18 100644 --- a/savevm.c +++ b/savevm.c @@ -501,7 +501,7 @@ static void qemu_fill_buffer(QEMUFile *f) f->buf_size += len; f->buf_offset += len; } else if (len == 0) { - f->last_error = -EIO; + qemu_file_set_error(f, -EIO); } else if (len != -EAGAIN) qemu_file_set_error(f, len); } From c10682cb031525a8bdf3999ef6a033777929d304 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 29 Aug 2012 19:43:39 +0200 Subject: [PATCH 0972/2270] savevm: Only qemu_fflush() can generate errors Move the error check to the beggining of the callers. Once this is fixed qemu_file_set_if_error() is not used anymore, so remove it. Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- savevm.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/savevm.c b/savevm.c index 943d100e18..e44bede55f 100644 --- a/savevm.c +++ b/savevm.c @@ -445,18 +445,6 @@ void qemu_file_set_error(QEMUFile *f, int ret) f->last_error = ret; } -/** Sets last_error conditionally - * - * Sets last_error only if ret is negative _and_ no error - * was set before. - */ -static void qemu_file_set_if_error(QEMUFile *f, int ret) -{ - if (ret < 0 && !f->last_error) { - qemu_file_set_error(f, ret); - } -} - /** Flushes QEMUFile buffer * */ @@ -544,13 +532,17 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) { int l; - if (!f->last_error && f->is_write == 0 && f->buf_index > 0) { + if (f->last_error) { + return; + } + + if (f->is_write == 0 && f->buf_index > 0) { fprintf(stderr, "Attempted to write to buffer while read buffer is not empty\n"); abort(); } - while (!f->last_error && size > 0) { + while (size > 0) { l = IO_BUF_SIZE - f->buf_index; if (l > size) l = size; @@ -561,14 +553,21 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) size -= l; if (f->buf_index >= IO_BUF_SIZE) { int ret = qemu_fflush(f); - qemu_file_set_if_error(f, ret); + if (ret < 0) { + qemu_file_set_error(f, ret); + break; + } } } } void qemu_put_byte(QEMUFile *f, int v) { - if (!f->last_error && f->is_write == 0 && f->buf_index > 0) { + if (f->last_error) { + return; + } + + if (f->is_write == 0 && f->buf_index > 0) { fprintf(stderr, "Attempted to write to buffer while read buffer is not empty\n"); abort(); @@ -578,7 +577,9 @@ void qemu_put_byte(QEMUFile *f, int v) f->is_write = 1; if (f->buf_index >= IO_BUF_SIZE) { int ret = qemu_fflush(f); - qemu_file_set_if_error(f, ret); + if (ret < 0) { + qemu_file_set_error(f, ret); + } } } From 81fdf640e4b479df75fcedf03fb300018f054bfa Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 29 Aug 2012 19:52:16 +0200 Subject: [PATCH 0973/2270] buffered_file: buffered_put_buffer() don't need to set last_error Callers on savevm.c:qemu_fflush() will set it. Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- buffered_file.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 77928f02c1..ed92df1053 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -120,8 +120,6 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in error = buffered_flush(s); if (error < 0) { DPRINTF("buffered flush error. bailing: %s\n", strerror(-error)); - qemu_file_set_error(s->file, error); - return error; } From 59feec424723c0cacf503670a42d76e7c47167c1 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 29 Aug 2012 20:17:13 +0200 Subject: [PATCH 0974/2270] block-migration: make flush_blks() return errors This means we don't need to pass through qemu_file to get the errors. Adjust all callers. Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- block-migration.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/block-migration.c b/block-migration.c index ed933017f9..f5ce386450 100644 --- a/block-migration.c +++ b/block-migration.c @@ -444,9 +444,10 @@ static int blk_mig_save_dirty_block(QEMUFile *f, int is_async) return ret; } -static void flush_blks(QEMUFile* f) +static int flush_blks(QEMUFile *f) { BlkMigBlock *blk; + int ret = 0; DPRINTF("%s Enter submitted %d read_done %d transferred %d\n", __FUNCTION__, block_mig_state.submitted, block_mig_state.read_done, @@ -457,7 +458,7 @@ static void flush_blks(QEMUFile* f) break; } if (blk->ret < 0) { - qemu_file_set_error(f, blk->ret); + ret = blk->ret; break; } blk_send(f, blk); @@ -474,6 +475,7 @@ static void flush_blks(QEMUFile* f) DPRINTF("%s Exit submitted %d read_done %d transferred %d\n", __FUNCTION__, block_mig_state.submitted, block_mig_state.read_done, block_mig_state.transferred); + return ret; } static int64_t get_remaining_dirty(void) @@ -555,9 +557,7 @@ static int block_save_setup(QEMUFile *f, void *opaque) /* start track dirty blocks */ set_dirty_tracking(1); - flush_blks(f); - - ret = qemu_file_get_error(f); + ret = flush_blks(f); if (ret) { blk_mig_cleanup(); return ret; @@ -577,9 +577,7 @@ static int block_save_iterate(QEMUFile *f, void *opaque) DPRINTF("Enter save live iterate submitted %d transferred %d\n", block_mig_state.submitted, block_mig_state.transferred); - flush_blks(f); - - ret = qemu_file_get_error(f); + ret = flush_blks(f); if (ret) { blk_mig_cleanup(); return ret; @@ -605,9 +603,7 @@ static int block_save_iterate(QEMUFile *f, void *opaque) } } - flush_blks(f); - - ret = qemu_file_get_error(f); + ret = flush_blks(f); if (ret) { blk_mig_cleanup(); return ret; @@ -625,9 +621,7 @@ static int block_save_complete(QEMUFile *f, void *opaque) DPRINTF("Enter save live complete submitted %d transferred %d\n", block_mig_state.submitted, block_mig_state.transferred); - flush_blks(f); - - ret = qemu_file_get_error(f); + ret = flush_blks(f); if (ret) { blk_mig_cleanup(); return ret; From ceb2bd09a13ea71d06353bf826524df3cf584735 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 29 Aug 2012 21:37:14 +0200 Subject: [PATCH 0975/2270] block-migration: Switch meaning of return value Make consistent the result of blk_mig_save_dirty_block() and mig_save_device_dirty() Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- block-migration.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/block-migration.c b/block-migration.c index f5ce386450..b47a063834 100644 --- a/block-migration.c +++ b/block-migration.c @@ -429,14 +429,18 @@ error: return 0; } +/* return value: + * 0: too much data for max_downtime + * 1: few enough data for max_downtime +*/ static int blk_mig_save_dirty_block(QEMUFile *f, int is_async) { BlkMigDevState *bmds; - int ret = 0; + int ret = 1; QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) { - if (mig_save_device_dirty(f, bmds, is_async) == 0) { - ret = 1; + ret = mig_save_device_dirty(f, bmds, is_async); + if (ret == 0) { break; } } @@ -596,7 +600,7 @@ static int block_save_iterate(QEMUFile *f, void *opaque) block_mig_state.bulk_completed = 1; } } else { - if (blk_mig_save_dirty_block(f, 1) == 0) { + if (blk_mig_save_dirty_block(f, 1) != 0) { /* no more dirty blocks */ break; } @@ -633,7 +637,7 @@ static int block_save_complete(QEMUFile *f, void *opaque) all async read completed */ assert(block_mig_state.submitted == 0); - while (blk_mig_save_dirty_block(f, 0) != 0) { + while (blk_mig_save_dirty_block(f, 0) == 0) { /* Do nothing */ } blk_mig_cleanup(); From 43be3a25c931a7f61a76fbfc9d35584cbfc5fb58 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 29 Aug 2012 21:59:22 +0200 Subject: [PATCH 0976/2270] block-migration: handle errors with the return codes correctly Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- block-migration.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/block-migration.c b/block-migration.c index b47a063834..71b9601e00 100644 --- a/block-migration.c +++ b/block-migration.c @@ -423,10 +423,9 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds, error: DPRINTF("Error reading sector %" PRId64 "\n", sector); - qemu_file_set_error(f, ret); g_free(blk->buf); g_free(blk); - return 0; + return ret; } /* return value: @@ -440,7 +439,7 @@ static int blk_mig_save_dirty_block(QEMUFile *f, int is_async) QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) { ret = mig_save_device_dirty(f, bmds, is_async); - if (ret == 0) { + if (ret <= 0) { break; } } @@ -600,12 +599,17 @@ static int block_save_iterate(QEMUFile *f, void *opaque) block_mig_state.bulk_completed = 1; } } else { - if (blk_mig_save_dirty_block(f, 1) != 0) { + ret = blk_mig_save_dirty_block(f, 1); + if (ret != 0) { /* no more dirty blocks */ break; } } } + if (ret) { + blk_mig_cleanup(); + return ret; + } ret = flush_blks(f); if (ret) { @@ -637,18 +641,16 @@ static int block_save_complete(QEMUFile *f, void *opaque) all async read completed */ assert(block_mig_state.submitted == 0); - while (blk_mig_save_dirty_block(f, 0) == 0) { - /* Do nothing */ - } + do { + ret = blk_mig_save_dirty_block(f, 0); + } while (ret == 0); + blk_mig_cleanup(); - - /* report completion */ - qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS); - - ret = qemu_file_get_error(f); if (ret) { return ret; } + /* report completion */ + qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS); DPRINTF("Block migration completed\n"); From 6f121ff575e1601d652f3eecf4f9ab1205c12df1 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Thu, 30 Aug 2012 13:37:56 +0200 Subject: [PATCH 0977/2270] savevm: un-export qemu_file_set_error() Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- qemu-file.h | 1 - savevm.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/qemu-file.h b/qemu-file.h index 289849a789..8dd920790c 100644 --- a/qemu-file.h +++ b/qemu-file.h @@ -103,7 +103,6 @@ int qemu_file_rate_limit(QEMUFile *f); int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate); int64_t qemu_file_get_rate_limit(QEMUFile *f); int qemu_file_get_error(QEMUFile *f); -void qemu_file_set_error(QEMUFile *f, int error); /* Try to send any outstanding data. This function is useful when output is * halted due to rate limiting or EAGAIN errors occur as it can be used to diff --git a/savevm.c b/savevm.c index e44bede55f..dee689998b 100644 --- a/savevm.c +++ b/savevm.c @@ -440,7 +440,7 @@ int qemu_file_get_error(QEMUFile *f) return f->last_error; } -void qemu_file_set_error(QEMUFile *f, int ret) +static void qemu_file_set_error(QEMUFile *f, int ret) { f->last_error = ret; } From a2b413512443e67cd58285b8d98b84792a66c710 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 4 Sep 2012 12:45:42 +0200 Subject: [PATCH 0978/2270] savevm: make qemu_file_put_notify() return errors Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- migration.c | 5 +++-- qemu-file.h | 2 +- savevm.c | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/migration.c b/migration.c index 2c93951423..62e030487d 100644 --- a/migration.c +++ b/migration.c @@ -287,10 +287,11 @@ static void migrate_fd_completed(MigrationState *s) static void migrate_fd_put_notify(void *opaque) { MigrationState *s = opaque; + int ret; qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); - qemu_file_put_notify(s->file); - if (s->file && qemu_file_get_error(s->file)) { + ret = qemu_file_put_notify(s->file); + if (ret) { migrate_fd_error(s); } } diff --git a/qemu-file.h b/qemu-file.h index 8dd920790c..9c8985b610 100644 --- a/qemu-file.h +++ b/qemu-file.h @@ -107,7 +107,7 @@ int qemu_file_get_error(QEMUFile *f); /* Try to send any outstanding data. This function is useful when output is * halted due to rate limiting or EAGAIN errors occur as it can be used to * resume output. */ -void qemu_file_put_notify(QEMUFile *f); +int qemu_file_put_notify(QEMUFile *f); static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv) { diff --git a/savevm.c b/savevm.c index dee689998b..b080d37258 100644 --- a/savevm.c +++ b/savevm.c @@ -523,9 +523,9 @@ int qemu_fclose(QEMUFile *f) return ret; } -void qemu_file_put_notify(QEMUFile *f) +int qemu_file_put_notify(QEMUFile *f) { - f->put_buffer(f->opaque, NULL, 0, 0); + return f->put_buffer(f->opaque, NULL, 0, 0); } void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) From aa723c23147e93fef8475bd80fd29e633378c34d Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 18 Sep 2012 16:30:11 +0200 Subject: [PATCH 0979/2270] cpus: create qemu_in_vcpu_thread() Old code used !io_thread to know if a thread was an vcpu or not. That fails when we introduce the iothread. Signed-off-by: Juan Quintela --- cpus.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cpus.c b/cpus.c index 750a76fbc8..191cbf5f6d 100644 --- a/cpus.c +++ b/cpus.c @@ -898,6 +898,11 @@ int qemu_cpu_is_self(void *_env) return qemu_thread_is_self(cpu->thread); } +static bool qemu_in_vcpu_thread(void) +{ + return cpu_single_env && qemu_cpu_is_self(cpu_single_env); +} + void qemu_mutex_lock_iothread(void) { if (!tcg_enabled()) { @@ -943,7 +948,7 @@ void pause_all_vcpus(void) penv = penv->next_cpu; } - if (!qemu_thread_is_self(&io_thread)) { + if (qemu_in_vcpu_thread()) { cpu_stop_current(); if (!kvm_enabled()) { while (penv) { @@ -1060,7 +1065,7 @@ void cpu_stop_current(void) void vm_stop(RunState state) { - if (!qemu_thread_is_self(&io_thread)) { + if (qemu_in_vcpu_thread()) { qemu_system_vmstop_request(state); /* * FIXME: should not return to device code in case From a011b10e0c385c58469e654595801a592fb4137a Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 17 Oct 2012 11:20:11 -0600 Subject: [PATCH 0980/2270] vfio-pci: Fix debug build Stray variable from before MSI-X rework Signed-off-by: Alex Williamson --- hw/vfio_pci.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 639371e7a2..0619af4854 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -639,9 +639,8 @@ static void vfio_disable_msix(VFIODevice *vdev) vfio_disable_msi_common(vdev); - DPRINTF("%s(%04x:%02x:%02x.%x, msi%s)\n", __func__, - vdev->host.domain, vdev->host.bus, vdev->host.slot, - vdev->host.function, msix ? "x" : ""); + DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function); } static void vfio_disable_msi(VFIODevice *vdev) From d9f0e63898d639629bb7eb914786529185334635 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 17 Oct 2012 11:20:14 -0600 Subject: [PATCH 0981/2270] vfio-pci: Mark non-migratable We haven't magically fixed this yet. Toss in a description too. Signed-off-by: Alex Williamson --- hw/vfio_pci.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 0619af4854..d5ff367c1b 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -1946,6 +1946,10 @@ static Property vfio_pci_dev_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static const VMStateDescription vfio_pci_vmstate = { + .name = "vfio-pci", + .unmigratable = 1, +}; static void vfio_pci_dev_class_init(ObjectClass *klass, void *data) { @@ -1954,6 +1958,8 @@ static void vfio_pci_dev_class_init(ObjectClass *klass, void *data) dc->reset = vfio_pci_reset; dc->props = vfio_pci_dev_properties; + dc->vmsd = &vfio_pci_vmstate; + dc->desc = "VFIO-based PCI device assignment"; pdc->init = vfio_initfn; pdc->exit = vfio_exitfn; pdc->config_read = vfio_pci_read_config; From b6348f29d033d5a8a26f633d2ee94362595f32a4 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 16 Oct 2012 19:15:50 +1000 Subject: [PATCH 0982/2270] target-arm/translate: Fix RRX operands Instructions that both use the RRX second operand and update CS were incorrect, as the Carry flag was updated too early. An example of such an instruction would be: ands r12,r13,RRX Ands, because of the "s" flag will update the carry flag. But the RRX second operand rotates through the C flag which should happen before the update. Fixed the ordering of the two, the old carry is read by "r13,RRX" before being updated. Signed-off-by: Peter Crosthwaite Reported-by: Vinesh Peringat Reviewed-by: Peter Maydell Signed-off-by: Aurelien Jarno --- target-arm/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-arm/translate.c b/target-arm/translate.c index c6840b7832..daccb15c23 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -516,10 +516,10 @@ static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags) tcg_gen_rotri_i32(var, var, shift); break; } else { TCGv tmp = tcg_temp_new_i32(); + tcg_gen_shli_i32(tmp, cpu_CF, 31); if (flags) shifter_out_im(var, 0); tcg_gen_shri_i32(var, var, 1); - tcg_gen_shli_i32(tmp, cpu_CF, 31); tcg_gen_or_i32(var, var, tmp); tcg_temp_free_i32(tmp); } From fe3e7f2dc05225cdd2ba40defcd4e2581bebc5e0 Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Wed, 16 May 2012 12:54:25 +0000 Subject: [PATCH 0983/2270] ui/vnc: Only report/use TIGHT_PNG encoding if enabled. If TIGHT_PNG is not enabled by the --enable-vnc-png configure flag then do not report to the client that it is supported. Also, since TIGHT_PNG is the same as the TIGHT encoding but with the filter/copy replaced with PNG data, adding it to the supported encodings list when it is disabled will cause the TIGHT encoding to be used even though the client requested TIGHT_PNG. Signed-off-by: Joel Martin Signed-off-by: Stefan Hajnoczi --- ui/vnc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/vnc.c b/ui/vnc.c index 33e6386a6e..66ae93010f 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1806,10 +1806,12 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) vs->features |= VNC_FEATURE_TIGHT_MASK; vs->vnc_encoding = enc; break; +#ifdef CONFIG_VNC_PNG case VNC_ENCODING_TIGHT_PNG: vs->features |= VNC_FEATURE_TIGHT_PNG_MASK; vs->vnc_encoding = enc; break; +#endif case VNC_ENCODING_ZLIB: vs->features |= VNC_FEATURE_ZLIB_MASK; vs->vnc_encoding = enc; From 301592ea6f9c23d233fadc73124301d1305af13c Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 12 Oct 2012 18:59:44 +0100 Subject: [PATCH 0984/2270] targphys.h: Don't define target_phys_addr_t for user-mode emulators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 4be403c accidentally defined the target_phys_addr_t type when building user-mode emulators. Since the type doesn't really make any sense except for system emulators, avoid defining it when building in user mode. Signed-off-by: Peter Maydell Acked-by: Andreas Färber Signed-off-by: Stefan Hajnoczi --- targphys.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/targphys.h b/targphys.h index 08cade9096..50911fd12f 100644 --- a/targphys.h +++ b/targphys.h @@ -3,6 +3,8 @@ #ifndef TARGPHYS_H #define TARGPHYS_H +#ifndef CONFIG_USER_ONLY + #define TARGET_PHYS_ADDR_BITS 64 /* target_phys_addr_t is the type of a physical address (its size can be different from 'target_ulong'). */ @@ -18,3 +20,5 @@ typedef uint64_t target_phys_addr_t; #define TARGET_PRIXPHYS PRIX64 #endif + +#endif From 02c7ac0c0f00ce7fb259a0d68c2590a09adb73f4 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 12 Oct 2012 19:07:23 +0100 Subject: [PATCH 0985/2270] target-arm/neon_helper: Remove obsolete FIXME comment Commit 33ebc29 fixed the bugs in the implementation of VQRSHL, but forgot to remove the FIXME comment... Signed-off-by: Peter Maydell Signed-off-by: Stefan Hajnoczi --- target-arm/neon_helper.c | 1 - 1 file changed, 1 deletion(-) diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c index 8bb5129d6a..9aa920d2ac 100644 --- a/target-arm/neon_helper.c +++ b/target-arm/neon_helper.c @@ -788,7 +788,6 @@ uint64_t HELPER(neon_qshlu_s64)(CPUARMState *env, uint64_t valop, uint64_t shift return helper_neon_qshl_u64(env, valop, shiftop); } -/* FIXME: This is wrong. */ #define NEON_FN(dest, src1, src2) do { \ int8_t tmp; \ tmp = (int8_t)src2; \ From abab1a0f32e44cb4e6c317e24d1705f182b88cd0 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Mon, 15 Oct 2012 07:45:40 +0200 Subject: [PATCH 0986/2270] configure: Remove unused parameters from main function This modification is required if compiler option -Wunused-parameter is activated. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 353d7889f7..499ad811a0 100755 --- a/configure +++ b/configure @@ -1323,7 +1323,7 @@ if test -z "$cross_prefix" ; then # big/little endian test cat > $TMPC << EOF #include -int main(int argc, char ** argv){ +int main(void) { volatile uint32_t i=0x01234567; return (*((uint8_t*)(&i))) == 0x67; } @@ -2896,7 +2896,7 @@ static int sfaa(int *ptr) return __sync_fetch_and_and(ptr, 0); } -int main(int argc, char **argv) +int main(void) { int val = 42; sfaa(&val); From 08778b398328c4978e6e6bed023e37a3141dba84 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 17 Oct 2012 19:53:50 +0200 Subject: [PATCH 0987/2270] net/tap-win32: Fix compiler warning caused by missing include statement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The include file for net_init_tap was missing: net/tap-win32.c:703: warning: no previous prototype for ‘net_init_tap’ Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- net/tap-win32.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/tap-win32.c b/net/tap-win32.c index f1801e22d2..22dad3f8fb 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -29,6 +29,7 @@ #include "tap.h" #include "qemu-common.h" +#include "clients.h" /* net_init_tap */ #include "net.h" #include "sysemu.h" #include "qemu-error.h" From 11f66978618b542986172a62fcd6acfa36c0d178 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Oct 2012 17:40:53 +0100 Subject: [PATCH 0988/2270] ui/vnc-jobs.c: Fix minor typos in comments Fix some minor typos/grammar errors in comments. Signed-off-by: Peter Maydell Reviewed-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- ui/vnc-jobs.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c index 087b84d319..3c592b3f3d 100644 --- a/ui/vnc-jobs.c +++ b/ui/vnc-jobs.c @@ -33,21 +33,21 @@ /* * Locking: * - * There is three levels of locking: + * There are three levels of locking: * - jobs queue lock: for each operation on the queue (push, pop, isEmpty?) * - VncDisplay global lock: mainly used for framebuffer updates to avoid * screen corruption if the framebuffer is updated - * while the worker is doing something. + * while the worker is doing something. * - VncState::output lock: used to make sure the output buffer is not corrupted - * if two threads try to write on it at the same time + * if two threads try to write on it at the same time * - * While the VNC worker thread is working, the VncDisplay global lock is hold - * to avoid screen corruptions (this does not block vnc_refresh() because it - * uses trylock()) but the output lock is not hold because the thread work on + * While the VNC worker thread is working, the VncDisplay global lock is held + * to avoid screen corruption (this does not block vnc_refresh() because it + * uses trylock()) but the output lock is not held because the thread works on * its own output buffer. * When the encoding job is done, the worker thread will hold the output lock * and copy its output buffer in vs->output. -*/ + */ struct VncJobQueue { QemuCond cond; @@ -62,7 +62,7 @@ typedef struct VncJobQueue VncJobQueue; /* * We use a single global queue, but most of the functions are - * already reetrant, so we can easilly add more than one encoding thread + * already reentrant, so we can easily add more than one encoding thread */ static VncJobQueue *queue; From a5b3bdcba8a105439ad3a44121526306c449e100 Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Thu, 26 Apr 2012 14:17:41 +0200 Subject: [PATCH 0989/2270] microblaze: Support setting of TLS ptr Signed-off-by: Edgar E. Iglesias --- linux-user/syscall.c | 2 ++ target-microblaze/cpu.h | 1 + 2 files changed, 3 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 471d0605f7..c6a6337426 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6888,6 +6888,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4)); #elif defined(TARGET_CRIS) ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5)); +#elif defined(TARGET_MICROBLAZE) + ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5)); #elif defined(TARGET_S390X) ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4)); #else diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h index 4968c244e8..88430b5057 100644 --- a/target-microblaze/cpu.h +++ b/target-microblaze/cpu.h @@ -345,6 +345,7 @@ static inline void cpu_clone_regs(CPUMBState *env, target_ulong newsp) static inline void cpu_set_tls(CPUMBState *env, target_ulong newtls) { + env->regs[21] = newtls; } static inline int cpu_interrupts_enabled(CPUMBState *env) From d7dce494769e47c9a1eec6f55578d3acdfab888b Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Thu, 26 Apr 2012 14:18:25 +0200 Subject: [PATCH 0990/2270] microblaze: Update PC before simulating syscall Fixes a clone() emulation bug were the new thread starts at the point of the syscall and thus clones in a loop. Signed-off-by: Edgar E. Iglesias --- linux-user/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/main.c b/linux-user/main.c index f4bbe697f7..5827ee6a27 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -2527,6 +2527,7 @@ void cpu_loop(CPUMBState *env) case EXCP_BREAK: /* Return address is 4 bytes after the call. */ env->regs[14] += 4; + env->sregs[SR_PC] = env->regs[14]; ret = do_syscall(env, env->regs[12], env->regs[5], @@ -2537,7 +2538,6 @@ void cpu_loop(CPUMBState *env) env->regs[10], 0, 0); env->regs[3] = ret; - env->sregs[SR_PC] = env->regs[14]; break; case EXCP_HW_EXCP: env->regs[17] = env->sregs[SR_PC] + 4; From 585f60368f23e6603cf86cfdaeceb89d1169f4b8 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 4 Oct 2012 16:22:01 +0100 Subject: [PATCH 0991/2270] qemu-options.hx: Change from recommending '?' to 'help' Update the -help output and documentation so that it recommends 'help' rather than '?' for the various "list valid values for this option" cases. '?' is deprecated (as it can fail confusingly if not quoted), so it's better to steer users towards 'help'. ('?' still works, for backwards compatibility.) This is the -help option part of the change otherwise done in commit c8057f9, since we are now past release 1.2 and free to change our help text without worrying about breaking libvirt. Signed-off-by: Peter Maydell Reviewed-by: Eric Blake Signed-off-by: Aurelien Jarno --- qemu-options.hx | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index 7d97f96928..46f0539182 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -6,10 +6,6 @@ HXCOMM construct option structures, enums and help message for specified HXCOMM architectures. HXCOMM HXCOMM can be used for comments, discarded from both texi and C -HXCOMM TODO : when we are able to change -help output without breaking -HXCOMM libvirt we should update the help options which refer to -cpu ?, -HXCOMM -driver ?, etc to use the preferred -cpu help etc instead. - DEFHEADING(Standard options:) STEXI @table @option @@ -33,7 +29,7 @@ ETEXI DEF("machine", HAS_ARG, QEMU_OPTION_machine, \ "-machine [type=]name[,prop[=value][,...]]\n" - " selects emulated machine (-machine ? for list)\n" + " selects emulated machine ('-machine help' for list)\n" " property accel=accel1[:accel2[:...]] selects accelerator\n" " supported accelerators are kvm, xen, tcg (default: tcg)\n" " kernel_irqchip=on|off controls accelerated irqchip support\n" @@ -44,7 +40,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \ STEXI @item -machine [type=]@var{name}[,prop=@var{value}[,...]] @findex -machine -Select the emulated machine by @var{name}. Use @code{-machine ?} to list +Select the emulated machine by @var{name}. Use @code{-machine help} to list available machines. Supported machine properties are: @table @option @item accel=@var{accels1}[:@var{accels2}[:...]] @@ -69,11 +65,11 @@ HXCOMM Deprecated by -machine DEF("M", HAS_ARG, QEMU_OPTION_M, "", QEMU_ARCH_ALL) DEF("cpu", HAS_ARG, QEMU_OPTION_cpu, - "-cpu cpu select CPU (-cpu ? for list)\n", QEMU_ARCH_ALL) + "-cpu cpu select CPU ('-cpu help' for list)\n", QEMU_ARCH_ALL) STEXI @item -cpu @var{model} @findex -cpu -Select CPU model (-cpu ? for list and additional feature selection) +Select CPU model (@code{-cpu help} for list and additional feature selection) ETEXI DEF("smp", HAS_ARG, QEMU_OPTION_smp, @@ -463,12 +459,12 @@ ETEXI DEF("soundhw", HAS_ARG, QEMU_OPTION_soundhw, "-soundhw c1,... enable audio support\n" " and only specified sound cards (comma separated list)\n" - " use -soundhw ? to get the list of supported cards\n" - " use -soundhw all to enable all of them\n", QEMU_ARCH_ALL) + " use '-soundhw help' to get the list of supported cards\n" + " use '-soundhw all' to enable all of them\n", QEMU_ARCH_ALL) STEXI @item -soundhw @var{card1}[,@var{card2},...] or -soundhw all @findex -soundhw -Enable audio and selected sound hardware. Use ? to print all +Enable audio and selected sound hardware. Use 'help' to print all available sound hardware. @example @@ -477,7 +473,7 @@ qemu-system-i386 -soundhw es1370 disk.img qemu-system-i386 -soundhw ac97 disk.img qemu-system-i386 -soundhw hda disk.img qemu-system-i386 -soundhw all disk.img -qemu-system-i386 -soundhw ? +qemu-system-i386 -soundhw help @end example Note that Linux's i810_audio OSS kernel (for AC97) module might @@ -566,16 +562,16 @@ DEF("device", HAS_ARG, QEMU_OPTION_device, "-device driver[,prop[=value][,...]]\n" " add device (based on driver)\n" " prop=value,... sets driver properties\n" - " use -device ? to print all possible drivers\n" - " use -device driver,? to print all possible properties\n", + " use '-device help' to print all possible drivers\n" + " use '-device driver,help' to print all possible properties\n", QEMU_ARCH_ALL) STEXI @item -device @var{driver}[,@var{prop}[=@var{value}][,...]] @findex -device Add device @var{driver}. @var{prop}=@var{value} sets driver properties. Valid properties depend on the driver. To get help on -possible drivers and properties, use @code{-device ?} and -@code{-device @var{driver},?}. +possible drivers and properties, use @code{-device help} and +@code{-device @var{driver},help}. ETEXI DEFHEADING() @@ -1365,7 +1361,7 @@ Valid values for @var{type} are @code{virtio}, @code{i82551}, @code{i82557b}, @code{i82559er}, @code{ne2k_pci}, @code{ne2k_isa}, @code{pcnet}, @code{rtl8139}, @code{e1000}, @code{smc91c111}, @code{lance} and @code{mcf_fec}. -Not all devices are supported on all targets. Use -net nic,model=? +Not all devices are supported on all targets. Use @code{-net nic,model=help} for a list of available devices for your target. @item -netdev user,id=@var{id}[,@var{option}][,@var{option}][,...] @@ -2398,7 +2394,7 @@ Shorthand for -gdb tcp::1234, i.e. open a gdbserver on TCP port 1234 ETEXI DEF("d", HAS_ARG, QEMU_OPTION_d, \ - "-d item1,... output log to /tmp/qemu.log (use -d ? for a list of log items)\n", + "-d item1,... output log to /tmp/qemu.log (use '-d help' for a list of log items)\n", QEMU_ARCH_ALL) STEXI @item -d @@ -2533,13 +2529,13 @@ ETEXI DEF("clock", HAS_ARG, QEMU_OPTION_clock, \ "-clock force the use of the given methods for timer alarm.\n" \ - " To see what timers are available use -clock ?\n", + " To see what timers are available use '-clock help'\n", QEMU_ARCH_ALL) STEXI @item -clock @var{method} @findex -clock Force the use of the given methods for timer alarm. To see what timers -are available use -clock ?. +are available use @code{-clock help}. ETEXI HXCOMM Options deprecated by -rtc @@ -2608,7 +2604,7 @@ watchdog with a single timer, or @code{i6300esb} (Intel 6300ESB I/O controller hub) which is a much more featureful PCI-based dual-timer watchdog. Choose a model for which your guest has drivers. -Use @code{-watchdog ?} to list available hardware models. Only one +Use @code{-watchdog help} to list available hardware models. Only one watchdog can be enabled for a guest. ETEXI From 38f419f35225decdbaea9fe1fd00218f8924ce84 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Wed, 17 Oct 2012 19:09:25 +0200 Subject: [PATCH 0992/2270] configure: Fix CONFIG_QEMU_HELPERDIR generation We need to evaluate $libexecdir in configure, otherwise we literally end up with "${prefix}/libexec" instead of the absolute path as CONFIG_QEMU_HELPERDIR. Signed-off-by: Jan Kiszka Signed-off-by: Aurelien Jarno --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index f9c31f4195..9f33c7d723 100755 --- a/configure +++ b/configure @@ -3200,7 +3200,7 @@ echo "qemu_confdir=$qemu_confdir" >> $config_host_mak echo "qemu_datadir=$qemu_datadir" >> $config_host_mak echo "qemu_docdir=$qemu_docdir" >> $config_host_mak echo "qemu_localstatedir=$local_statedir" >> $config_host_mak -echo "CONFIG_QEMU_HELPERDIR=\"$libexecdir\"" >> $config_host_mak +echo "CONFIG_QEMU_HELPERDIR=\"`eval echo $libexecdir`\"" >> $config_host_mak echo "ARCH=$ARCH" >> $config_host_mak if test "$debug_tcg" = "yes" ; then From 1cd0f8ce731574afbf219b7ae2b938f305b77e86 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Sun, 7 Oct 2012 18:08:49 +0200 Subject: [PATCH 0993/2270] MAINTAINERS: Update email address for Stefan Hajnoczi Switch to my new work email address from which I am contributing. Signed-off-by: Stefan Hajnoczi Signed-off-by: Aurelien Jarno --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index f1f925007e..8f5681fd64 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -641,7 +641,7 @@ F: monitor.c Network device layer M: Anthony Liguori -M: Stefan Hajnoczi +M: Stefan Hajnoczi S: Maintained F: net/ T: git git://github.com/stefanha/qemu.git net @@ -661,7 +661,7 @@ F: slirp/ T: git git://git.kiszka.org/qemu.git queues/slirp Tracing -M: Stefan Hajnoczi +M: Stefan Hajnoczi S: Maintained F: trace/ F: scripts/tracetool.py From 42a159284570b6fbb0b097e18c7590c094a5188c Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Mon, 8 Oct 2012 15:45:49 -0500 Subject: [PATCH 0994/2270] tci: fix build breakage for target-sparc commit c28ae41 introduced GETPC() usage for sparc, which is currently not defined when building with --enable-tcg-interpreter. Add sparc to the list of targets we selectively define GETPC() for. Signed-off-by: Michael Roth Reviewed-by: Stefan Weil Signed-off-by: Aurelien Jarno --- exec-all.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exec-all.h b/exec-all.h index 6516da071d..f7f649ee61 100644 --- a/exec-all.h +++ b/exec-all.h @@ -296,7 +296,8 @@ extern int tb_invalidated_flag; #if defined(CONFIG_TCG_INTERPRETER) /* Alpha and SH4 user mode emulations and Softmmu call GETPC(). For all others, GETPC remains undefined (which makes TCI a little faster. */ -# if defined(CONFIG_SOFTMMU) || defined(TARGET_ALPHA) || defined(TARGET_SH4) +# if defined(CONFIG_SOFTMMU) || defined(TARGET_ALPHA) || defined(TARGET_SH4) \ + || defined(TARGET_SPARC) extern uintptr_t tci_tb_ptr; # define GETPC() tci_tb_ptr # endif From 7748b8cb1d100105753a80976d2d02ab107d8107 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 16 Sep 2012 16:07:13 -0400 Subject: [PATCH 0995/2270] allow make {dist, }clean work w/out configure There's no reason to require configure to run before running a clean target, so check MAKECMDGOALS before. Signed-off-by: Mike Frysinger Signed-off-by: Aurelien Jarno --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index a9c22bf1d9..88285a474b 100644 --- a/Makefile +++ b/Makefile @@ -14,9 +14,11 @@ config-host.mak: $(SRC_PATH)/configure @sed -n "/.*Configured with/s/[^:]*: //p" $@ | sh else config-host.mak: +ifneq ($(filter-out %clean,$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail)) @echo "Please call configure before running make!" @exit 1 endif +endif GENERATED_HEADERS = config-host.h trace.h qemu-options.def ifeq ($(TRACE_BACKEND),dtrace) @@ -403,7 +405,9 @@ qemu-doc.dvi qemu-doc.html qemu-doc.info qemu-doc.pdf: \ # Add a dependency on the generated files, so that they are always # rebuilt before other object files +ifneq ($(filter-out %clean,$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail)) Makefile: $(GENERATED_HEADERS) +endif # Include automatically generated dependency files # Dependencies in Makefile.objs files come from our recursive subdir rules From f62cb1b6ddc2c82694abac23ab5eeddd85800074 Mon Sep 17 00:00:00 2001 From: Catalin Patulea Date: Tue, 16 Oct 2012 16:00:23 -0400 Subject: [PATCH 0996/2270] tests/tcg: fix build This broke when the tests were moved from tests/ to tests/tcg/. On x86_64 host/i386-linux-user non-kvm guest, test-i386 and test-mmap are broken, but at least they build. To build/run the tests: $ cd $BUILD_PATH/tests/tcg $ SRC_PATH=path/to/qemu make Signed-off-by: Catalin Patulea Reviewed-by: Peter Maydell Signed-off-by: Aurelien Jarno --- tests/tcg/Makefile | 18 +++++++++++------- tests/tcg/linux-test.c | 2 ++ tests/tcg/test-i386.c | 3 ++- tests/tcg/test_path.c | 13 +++++++------ 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/tests/tcg/Makefile b/tests/tcg/Makefile index 15e36a208c..80b1a4b529 100644 --- a/tests/tcg/Makefile +++ b/tests/tcg/Makefile @@ -1,13 +1,13 @@ --include ../config-host.mak +-include ../../config-host.mak -include $(SRC_PATH)/rules.mak -$(call set-vpath, $(SRC_PATH)/tests) +$(call set-vpath, $(SRC_PATH)/tests/tcg) -QEMU=../i386-linux-user/qemu-i386 -QEMU_X86_64=../x86_64-linux-user/qemu-x86_64 +QEMU=../../i386-linux-user/qemu-i386 +QEMU_X86_64=../../x86_64-linux-user/qemu-x86_64 CC_X86_64=$(CC_I386) -m64 -QEMU_INCLUDES += -I.. +QEMU_INCLUDES += -I../.. CFLAGS=-Wall -O2 -g -fno-strict-aliasing #CFLAGS+=-msse2 LDFLAGS= @@ -36,6 +36,7 @@ TESTS += $(I386_TESTS) endif all: $(patsubst %,run-%,$(TESTS)) +test: all # rules to run tests @@ -74,7 +75,10 @@ run-test_path: test_path # rules to compile tests test_path: test_path.o + $(CC_I386) $(LDFLAGS) -o $@ $^ $(LIBS) + test_path.o: test_path.c + $(CC_I386) $(QEMU_INCLUDES) $(GLIB_CFLAGS) $(CFLAGS) -c -o $@ $^ hello-i386: hello-i386.c $(CC_I386) -nostdlib $(CFLAGS) -static $(LDFLAGS) -o $@ $< @@ -86,12 +90,12 @@ testthread: testthread.c # i386/x86_64 emulation test (test various opcodes) */ test-i386: test-i386.c test-i386-code16.S test-i386-vm86.S \ test-i386.h test-i386-shift.h test-i386-muldiv.h - $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ \ + $(CC_I386) $(QEMU_INCLUDES) $(CFLAGS) $(LDFLAGS) -o $@ \ $(. */ +#define _GNU_SOURCE #include #include #include @@ -38,6 +39,7 @@ #include #include #include +#include #define TESTPATH "/tmp/linux-test.tmp" #define TESTPORT 7654 diff --git a/tests/tcg/test-i386.c b/tests/tcg/test-i386.c index 8e64bbaf38..64d929e482 100644 --- a/tests/tcg/test-i386.c +++ b/tests/tcg/test-i386.c @@ -17,6 +17,7 @@ * along with this program; if not, see . */ #define _GNU_SOURCE +#include "compiler.h" #include #include #include @@ -1827,7 +1828,7 @@ void test_exceptions(void) printf("lock nop exception:\n"); if (setjmp(jmp_env) == 0) { /* now execute an invalid instruction */ - asm volatile("lock nop"); + asm volatile(".byte 0xf0, 0x90"); /* lock nop */ } printf("INT exception:\n"); diff --git a/tests/tcg/test_path.c b/tests/tcg/test_path.c index 7265a9445d..a064eea8fb 100644 --- a/tests/tcg/test_path.c +++ b/tests/tcg/test_path.c @@ -1,11 +1,12 @@ /* Test path override code */ -#include "../config-host.h" -#include "../qemu-malloc.c" -#include "../cutils.c" -#include "../path.c" -#include "../trace.c" +#define _GNU_SOURCE +#include "config-host.h" +#include "iov.c" +#include "cutils.c" +#include "path.c" +#include "trace.c" #ifdef CONFIG_TRACE_SIMPLE -#include "../simpletrace.c" +#include "../trace/simple.c" #endif #include From 0d0302e2033087ebcd0bcaa2ac1a79452f86d2a7 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 15 Oct 2012 08:02:54 +0200 Subject: [PATCH 0997/2270] vga: fix indention Signed-off-by: Gerd Hoffmann Signed-off-by: Blue Swirl --- hw/vga-pci.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/hw/vga-pci.c b/hw/vga-pci.c index 996d47f23a..5f55f361a2 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -48,25 +48,25 @@ static const VMStateDescription vmstate_vga_pci = { static int pci_std_vga_initfn(PCIDevice *dev) { - PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev); - VGACommonState *s = &d->vga; + PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev); + VGACommonState *s = &d->vga; - // vga + console init - vga_common_init(s); - vga_init(s, pci_address_space(dev), pci_address_space_io(dev), true); + /* vga + console init */ + vga_common_init(s); + vga_init(s, pci_address_space(dev), pci_address_space_io(dev), true); - s->ds = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, s); + s->ds = graphic_console_init(s->update, s->invalidate, + s->screen_dump, s->text_update, s); - /* XXX: VGA_RAM_SIZE must be a power of two */ - pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); + /* XXX: VGA_RAM_SIZE must be a power of two */ + pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); - if (!dev->rom_bar) { - /* compatibility with pc-0.13 and older */ - vga_init_vbe(s, pci_address_space(dev)); - } + if (!dev->rom_bar) { + /* compatibility with pc-0.13 and older */ + vga_init_vbe(s, pci_address_space(dev)); + } - return 0; + return 0; } static Property vga_pci_properties[] = { From 803ff052b69c888df3d21e199626a5ef6e3ccf12 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 15 Oct 2012 08:02:55 +0200 Subject: [PATCH 0998/2270] vga: add mmio bar to standard vga This patch adds a mmio bar to the qemu standard vga which allows to access the standard vga registers and bochs dispi interface registers via mmio. Cc: Benjamin Herrenschmidt Signed-off-by: Gerd Hoffmann Signed-off-by: Blue Swirl --- hw/pc_piix.c | 4 ++ hw/vga-pci.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++ hw/vga.c | 6 +-- hw/vga_int.h | 6 +++ 4 files changed, 121 insertions(+), 3 deletions(-) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 82364ab0d5..5bd4572d47 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -379,6 +379,10 @@ static QEMUMachine pc_machine_v1_3 = { .driver = "qxl-vga",\ .property = "revision",\ .value = stringify(3),\ + },{\ + .driver = "VGA",\ + .property = "mmio",\ + .value = "off",\ } static QEMUMachine pc_machine_v1_2 = { diff --git a/hw/vga-pci.c b/hw/vga-pci.c index 5f55f361a2..f7d0256e87 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -29,9 +29,23 @@ #include "qemu-timer.h" #include "loader.h" +#define PCI_VGA_IOPORT_OFFSET 0x400 +#define PCI_VGA_IOPORT_SIZE (0x3e0 - 0x3c0) +#define PCI_VGA_BOCHS_OFFSET 0x500 +#define PCI_VGA_BOCHS_SIZE (0x0b * 2) +#define PCI_VGA_MMIO_SIZE 0x1000 + +enum vga_pci_flags { + PCI_VGA_FLAG_ENABLE_MMIO = 1, +}; + typedef struct PCIVGAState { PCIDevice dev; VGACommonState vga; + uint32_t flags; + MemoryRegion mmio; + MemoryRegion ioport; + MemoryRegion bochs; } PCIVGAState; static const VMStateDescription vmstate_vga_pci = { @@ -46,6 +60,84 @@ static const VMStateDescription vmstate_vga_pci = { } }; +static uint64_t pci_vga_ioport_read(void *ptr, target_phys_addr_t addr, + unsigned size) +{ + PCIVGAState *d = ptr; + uint64_t ret = 0; + + switch (size) { + case 1: + ret = vga_ioport_read(&d->vga, addr); + break; + case 2: + ret = vga_ioport_read(&d->vga, addr); + ret |= vga_ioport_read(&d->vga, addr+1) << 8; + break; + } + return ret; +} + +static void pci_vga_ioport_write(void *ptr, target_phys_addr_t addr, + uint64_t val, unsigned size) +{ + PCIVGAState *d = ptr; + switch (size) { + case 1: + vga_ioport_write(&d->vga, addr, val); + break; + case 2: + /* + * Update bytes in little endian order. Allows to update + * indexed registers with a single word write because the + * index byte is updated first. + */ + vga_ioport_write(&d->vga, addr, val & 0xff); + vga_ioport_write(&d->vga, addr+1, (val >> 8) & 0xff); + break; + } +} + +static const MemoryRegionOps pci_vga_ioport_ops = { + .read = pci_vga_ioport_read, + .write = pci_vga_ioport_write, + .valid.min_access_size = 1, + .valid.max_access_size = 4, + .impl.min_access_size = 1, + .impl.max_access_size = 2, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static uint64_t pci_vga_bochs_read(void *ptr, target_phys_addr_t addr, + unsigned size) +{ + PCIVGAState *d = ptr; + int index = addr >> 1; + + vbe_ioport_write_index(&d->vga, 0, index); + return vbe_ioport_read_data(&d->vga, 0); +} + +static void pci_vga_bochs_write(void *ptr, target_phys_addr_t addr, + uint64_t val, unsigned size) +{ + PCIVGAState *d = ptr; + int index = addr >> 1; + + vbe_ioport_write_index(&d->vga, 0, index); + vbe_ioport_write_data(&d->vga, 0, val); +} + +static const MemoryRegionOps pci_vga_bochs_ops = { + .read = pci_vga_bochs_read, + .write = pci_vga_bochs_write, + .valid.min_access_size = 1, + .valid.max_access_size = 4, + .impl.min_access_size = 2, + .impl.max_access_size = 2, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + static int pci_std_vga_initfn(PCIDevice *dev) { PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev); @@ -61,6 +153,21 @@ static int pci_std_vga_initfn(PCIDevice *dev) /* XXX: VGA_RAM_SIZE must be a power of two */ pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); + /* mmio bar for vga register access */ + if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_MMIO)) { + memory_region_init(&d->mmio, "vga.mmio", 4096); + memory_region_init_io(&d->ioport, &pci_vga_ioport_ops, d, + "vga ioports remapped", PCI_VGA_IOPORT_SIZE); + memory_region_init_io(&d->bochs, &pci_vga_bochs_ops, d, + "bochs dispi interface", PCI_VGA_BOCHS_SIZE); + + memory_region_add_subregion(&d->mmio, PCI_VGA_IOPORT_OFFSET, + &d->ioport); + memory_region_add_subregion(&d->mmio, PCI_VGA_BOCHS_OFFSET, + &d->bochs); + pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); + } + if (!dev->rom_bar) { /* compatibility with pc-0.13 and older */ vga_init_vbe(s, pci_address_space(dev)); @@ -71,6 +178,7 @@ static int pci_std_vga_initfn(PCIDevice *dev) static Property vga_pci_properties[] = { DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16), + DEFINE_PROP_BIT("mmio", PCIVGAState, flags, PCI_VGA_FLAG_ENABLE_MMIO, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/vga.c b/hw/vga.c index afaef0d711..6afe48ce58 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -591,7 +591,7 @@ static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr) return val; } -static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr) +uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr) { VGACommonState *s = opaque; uint32_t val; @@ -627,13 +627,13 @@ static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr) return val; } -static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val) +void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val) { VGACommonState *s = opaque; s->vbe_index = val; } -static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) +void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) { VGACommonState *s = opaque; diff --git a/hw/vga_int.h b/hw/vga_int.h index 330a32f77d..5b68490301 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -208,7 +208,13 @@ void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2); void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp); int vga_ioport_invalid(VGACommonState *s, uint32_t addr); + +#ifdef CONFIG_BOCHS_VBE void vga_init_vbe(VGACommonState *s, MemoryRegion *address_space); +uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr); +void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val); +void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val); +#endif extern const uint8_t sr_mask[8]; extern const uint8_t gr_mask[16]; From cc22824860a18e9e073496396b1cfc860d010a26 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 15 Oct 2012 08:02:56 +0200 Subject: [PATCH 0999/2270] vga: add specs for standard vga Signed-off-by: Gerd Hoffmann Signed-off-by: Blue Swirl --- docs/specs/standard-vga.txt | 64 +++++++++++++++++++++++++++++++++++++ hw/vga-isa.c | 2 ++ hw/vga-pci.c | 2 ++ 3 files changed, 68 insertions(+) create mode 100644 docs/specs/standard-vga.txt diff --git a/docs/specs/standard-vga.txt b/docs/specs/standard-vga.txt new file mode 100644 index 0000000000..1cecccd469 --- /dev/null +++ b/docs/specs/standard-vga.txt @@ -0,0 +1,64 @@ + +QEMU Standard VGA +================= + +Exists in two variants, for isa and pci. + +command line switches: + -vga std [ picks isa for -M isapc, otherwise pci ] + -device VGA [ pci variant ] + -device isa-vga [ isa variant ] + + +PCI spec +-------- + +Applies to the pci variant only for obvious reasons. + +PCI ID: 1234:1111 + +PCI Region 0: + Framebuffer memory, 16 MB in size (by default). + Size is tunable via vga_mem_mb property. + +PCI Region 1: + Reserved (so we have the option to make the framebuffer bar 64bit). + +PCI Region 2: + MMIO bar, 4096 bytes in size (qemu 1.3+) + +PCI ROM Region: + Holds the vgabios (qemu 0.14+). + + +IO ports used +------------- + +03c0 - 03df : standard vga ports +01ce : bochs vbe interface index port +01cf : bochs vbe interface data port + + +Memory regions used +------------------- + +0xe0000000 : Framebuffer memory, isa variant only. + +The pci variant used to mirror the framebuffer bar here, qemu 0.14+ +stops doing that (except when in -M pc-$old compat mode). + + +MMIO area spec +-------------- + +Likewise applies to the pci variant only for obvious reasons. + +0000 - 03ff : reserved, for possible virtio extension. +0400 - 041f : vga ioports (0x3c0 -> 0x3df), remapped 1:1. + word access is supported, bytes are written + in little endia order (aka index port first), + so indexed registers can be updated with a + single mmio write (and thus only one vmexit). +0500 - 0515 : bochs dispi interface registers, mapped flat + without index/data ports. Use (index << 1) + as offset for (16bit) register access. diff --git a/hw/vga-isa.c b/hw/vga-isa.c index d2904737bc..046602b3d2 100644 --- a/hw/vga-isa.c +++ b/hw/vga-isa.c @@ -1,6 +1,8 @@ /* * QEMU ISA VGA Emulator. * + * see docs/specs/standard-vga.txt for virtual hardware specs. + * * Copyright (c) 2003 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/hw/vga-pci.c b/hw/vga-pci.c index f7d0256e87..5c4daee397 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -1,6 +1,8 @@ /* * QEMU PCI VGA Emulator. * + * see docs/specs/standard-vga.txt for virtual hardware specs. + * * Copyright (c) 2003 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy From a96d8bea8e23473bd5b4b4111ba9187fcb976865 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 15 Oct 2012 08:02:57 +0200 Subject: [PATCH 1000/2270] vga: remove CONFIG_BOCHS_VBE Signed-off-by: Gerd Hoffmann Signed-off-by: Blue Swirl --- hw/vga.c | 34 +++++----------------------------- hw/vga_int.h | 28 +++++++--------------------- 2 files changed, 12 insertions(+), 50 deletions(-) diff --git a/hw/vga.c b/hw/vga.c index 6afe48ce58..a07a6fb1ca 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -582,7 +582,6 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) } } -#ifdef CONFIG_BOCHS_VBE static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr) { VGACommonState *s = opaque; @@ -784,7 +783,6 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) } } } -#endif /* called for accesses between 0xa0000 and 0xc0000 */ uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr) @@ -1129,14 +1127,12 @@ static void vga_get_offsets(VGACommonState *s, uint32_t *pline_compare) { uint32_t start_addr, line_offset, line_compare; -#ifdef CONFIG_BOCHS_VBE + if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { line_offset = s->vbe_line_offset; start_addr = s->vbe_start_addr; line_compare = 65535; - } else -#endif - { + } else { /* compute line_offset in bytes */ line_offset = s->cr[VGA_CRTC_OFFSET]; line_offset <<= 3; @@ -1572,12 +1568,10 @@ static vga_draw_line_func * const vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_ static int vga_get_bpp(VGACommonState *s) { int ret; -#ifdef CONFIG_BOCHS_VBE + if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { ret = s->vbe_regs[VBE_DISPI_INDEX_BPP]; - } else -#endif - { + } else { ret = 0; } return ret; @@ -1587,13 +1581,10 @@ static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight) { int width, height; -#ifdef CONFIG_BOCHS_VBE if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { width = s->vbe_regs[VBE_DISPI_INDEX_XRES]; height = s->vbe_regs[VBE_DISPI_INDEX_YRES]; - } else -#endif - { + } else { width = (s->cr[VGA_CRTC_H_DISP] + 1) * 8; height = s->cr[VGA_CRTC_V_DISP_END] | ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) | @@ -1948,14 +1939,12 @@ void vga_common_reset(VGACommonState *s) s->dac_8bit = 0; memset(s->palette, '\0', sizeof(s->palette)); s->bank_offset = 0; -#ifdef CONFIG_BOCHS_VBE s->vbe_index = 0; memset(s->vbe_regs, '\0', sizeof(s->vbe_regs)); s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5; s->vbe_start_addr = 0; s->vbe_line_offset = 0; s->vbe_bank_mask = (s->vram_size >> 16) - 1; -#endif memset(s->font_offsets, '\0', sizeof(s->font_offsets)); s->graphic_mode = -1; /* force full update */ s->shift_control = 0; @@ -2229,13 +2218,11 @@ const VMStateDescription vmstate_vga_common = { VMSTATE_INT32(bank_offset, VGACommonState), VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState), -#ifdef CONFIG_BOCHS_VBE VMSTATE_UINT16(vbe_index, VGACommonState), VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB), VMSTATE_UINT32(vbe_start_addr, VGACommonState), VMSTATE_UINT32(vbe_line_offset, VGACommonState), VMSTATE_UINT32(vbe_bank_mask, VGACommonState), -#endif VMSTATE_END_OF_LIST() } }; @@ -2275,11 +2262,7 @@ void vga_common_init(VGACommonState *s) } s->vram_size_mb = s->vram_size >> 20; -#ifdef CONFIG_BOCHS_VBE s->is_vbe_vmstate = 1; -#else - s->is_vbe_vmstate = 0; -#endif memory_region_init_ram(&s->vram, "vga.vram", s->vram_size); vmstate_register_ram_global(&s->vram); xen_register_framebuffer(&s->vram); @@ -2314,7 +2297,6 @@ static const MemoryRegionPortio vga_portio_list[] = { PORTIO_END_OF_LIST(), }; -#ifdef CONFIG_BOCHS_VBE static const MemoryRegionPortio vbe_portio_list[] = { { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index }, # ifdef TARGET_I386 @@ -2324,7 +2306,6 @@ static const MemoryRegionPortio vbe_portio_list[] = { # endif PORTIO_END_OF_LIST(), }; -#endif /* CONFIG_BOCHS_VBE */ /* Used by both ISA and PCI */ MemoryRegion *vga_init_io(VGACommonState *s, @@ -2334,10 +2315,7 @@ MemoryRegion *vga_init_io(VGACommonState *s, MemoryRegion *vga_mem; *vga_ports = vga_portio_list; - *vbe_ports = NULL; -#ifdef CONFIG_BOCHS_VBE *vbe_ports = vbe_portio_list; -#endif vga_mem = g_malloc(sizeof(*vga_mem)); memory_region_init_io(vga_mem, &vga_mem_ops, s, @@ -2379,7 +2357,6 @@ void vga_init(VGACommonState *s, MemoryRegion *address_space, void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory) { -#ifdef CONFIG_BOCHS_VBE /* With pc-0.12 and below we map both the PCI BAR and the fixed VBE region, * so use an alias to avoid double-mapping the same region. */ @@ -2390,7 +2367,6 @@ void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory) VBE_DISPI_LFB_PHYSICAL_ADDRESS, &s->vram_vbe); s->vbe_mapped = 1; -#endif } /********************************************************/ /* vga screen dump */ diff --git a/hw/vga_int.h b/hw/vga_int.h index 5b68490301..144e7d3c35 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -29,9 +29,6 @@ #define ST01_V_RETRACE 0x08 #define ST01_DISP_ENABLE 0x01 -/* bochs VBE support */ -#define CONFIG_BOCHS_VBE - #define VBE_DISPI_MAX_XRES 16000 #define VBE_DISPI_MAX_YRES 12000 #define VBE_DISPI_MAX_BPP 32 @@ -65,21 +62,6 @@ #define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 -#ifdef CONFIG_BOCHS_VBE - -#define VGA_STATE_COMMON_BOCHS_VBE \ - uint16_t vbe_index; \ - uint16_t vbe_regs[VBE_DISPI_INDEX_NB]; \ - uint32_t vbe_start_addr; \ - uint32_t vbe_line_offset; \ - uint32_t vbe_bank_mask; \ - int vbe_mapped; -#else - -#define VGA_STATE_COMMON_BOCHS_VBE - -#endif /* !CONFIG_BOCHS_VBE */ - #define CH_ATTR_SIZE (160 * 100) #define VGA_MAX_HEIGHT 2048 @@ -140,7 +122,13 @@ typedef struct VGACommonState { void (*get_resolution)(struct VGACommonState *s, int *pwidth, int *pheight); - VGA_STATE_COMMON_BOCHS_VBE + /* bochs vbe state */ + uint16_t vbe_index; + uint16_t vbe_regs[VBE_DISPI_INDEX_NB]; + uint32_t vbe_start_addr; + uint32_t vbe_line_offset; + uint32_t vbe_bank_mask; + int vbe_mapped; /* display refresh support */ DisplayState *ds; uint32_t font_offsets[2]; @@ -209,12 +197,10 @@ void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp); int vga_ioport_invalid(VGACommonState *s, uint32_t addr); -#ifdef CONFIG_BOCHS_VBE void vga_init_vbe(VGACommonState *s, MemoryRegion *address_space); uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr); void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val); void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val); -#endif extern const uint8_t sr_mask[8]; extern const uint8_t gr_mask[16]; From 5f072e1f3075bd869e0ace9f2545a85992ac0084 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Mon, 15 Oct 2012 17:22:02 -0300 Subject: [PATCH 1001/2270] create struct for machine initialization arguments This should help us to: - More easily add or remove machine initialization arguments without having to change every single machine init function; - More easily make mechanical changes involving the machine init functions in the future; - Let machine initialization forward the init arguments to other functions more easily. This change was half-mechanical process: first the struct was added with the local ram_size, boot_device, kernel_*, initrd_*, and cpu_model local variable initialization to all functions. Then the compiler helped me locate the local variables that are unused, so they could be removed. Signed-off-by: Blue Swirl --- hw/alpha_dp264.c | 12 +-- hw/an5206.c | 8 +- hw/axis_dev88.c | 9 ++- hw/boards.h | 16 ++-- hw/collie.c | 9 ++- hw/dummy_m68k.c | 8 +- hw/exynos4_boards.c | 16 ++-- hw/gumstix.c | 11 +-- hw/highbank.c | 10 ++- hw/integratorcp.c | 10 ++- hw/kzm.c | 10 ++- hw/leon3.c | 10 +-- hw/lm32_boards.c | 18 ++--- hw/mainstone.c | 10 ++- hw/mcf5208.c | 8 +- hw/milkymist.c | 10 +-- hw/mips_fulong2e.c | 9 ++- hw/mips_jazz.c | 14 ++-- hw/mips_malta.c | 10 ++- hw/mips_mipssim.c | 10 ++- hw/mips_r4k.c | 10 ++- hw/musicpal.c | 9 ++- hw/nseries.c | 22 ++++-- hw/null-machine.c | 7 +- hw/omap_sx1.c | 22 ++++-- hw/openrisc_sim.c | 10 +-- hw/palm.c | 9 ++- hw/pc_piix.c | 50 ++++++------- hw/petalogix_ml605_mmu.c | 8 +- hw/petalogix_s3adsp1800_mmu.c | 8 +- hw/ppc/e500plat.c | 13 ++-- hw/ppc/mpc8544ds.c | 13 ++-- hw/ppc405_boards.c | 25 +++---- hw/ppc440_bamboo.c | 12 +-- hw/ppc_newworld.c | 13 ++-- hw/ppc_oldworld.c | 13 ++-- hw/ppc_prep.c | 13 ++-- hw/puv3.c | 8 +- hw/r2d.c | 9 ++- hw/realview.c | 44 +++++++---- hw/s390-virtio.c | 13 ++-- hw/shix.c | 6 +- hw/spapr.c | 13 ++-- hw/spitz.c | 40 ++++++---- hw/stellaris.c | 14 ++-- hw/sun4m.c | 133 +++++++++++++++++++++------------- hw/sun4u.c | 33 ++++++--- hw/tosa.c | 9 ++- hw/versatilepb.c | 22 ++++-- hw/vexpress.c | 26 ++++--- hw/virtex_ml507.c | 10 +-- hw/xen_machine_pv.c | 11 ++- hw/xilinx_zynq.c | 9 ++- hw/xtensa_lx60.c | 22 ++++-- hw/xtensa_sim.c | 11 ++- hw/z2.c | 9 ++- vl.c | 9 ++- 57 files changed, 515 insertions(+), 411 deletions(-) diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c index 5ea04c75ac..8f082a6656 100644 --- a/hw/alpha_dp264.c +++ b/hw/alpha_dp264.c @@ -42,13 +42,13 @@ static int clipper_pci_map_irq(PCIDevice *d, int irq_num) return (slot + 1) * 4 + irq_num; } -static void clipper_init(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) +static void clipper_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; CPUAlphaState *cpus[4]; PCIBus *pci_bus; ISABus *isa_bus; diff --git a/hw/an5206.c b/hw/an5206.c index 25407c0f50..042c5fcd14 100644 --- a/hw/an5206.c +++ b/hw/an5206.c @@ -19,11 +19,11 @@ /* Board init. */ -static void an5206_init(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) +static void an5206_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; CPUM68KState *env; int kernel_size; uint64_t elf_entry; diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c index eab6327bed..2fd7356fce 100644 --- a/hw/axis_dev88.c +++ b/hw/axis_dev88.c @@ -242,11 +242,12 @@ static const MemoryRegionOps gpio_ops = { static struct cris_load_info li; static -void axisdev88_init (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 axisdev88_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; CRISCPU *cpu; CPUCRISState *env; DeviceState *dev; diff --git a/hw/boards.h b/hw/boards.h index a2e0a54497..813d0e5109 100644 --- a/hw/boards.h +++ b/hw/boards.h @@ -5,12 +5,16 @@ #include "qdev.h" -typedef void QEMUMachineInitFunc(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); +typedef struct QEMUMachineInitArgs { + 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; +} QEMUMachineInitArgs; + +typedef void QEMUMachineInitFunc(QEMUMachineInitArgs *args); typedef void QEMUMachineResetFunc(void); diff --git a/hw/collie.c b/hw/collie.c index 56f89a9f2e..695982a99f 100644 --- a/hw/collie.c +++ b/hw/collie.c @@ -23,11 +23,12 @@ static struct arm_boot_info collie_binfo = { .ram_size = 0x20000000, }; -static void collie_init(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) +static void collie_init(QEMUMachineInitArgs *args) { + 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; StrongARMState *s; DriveInfo *dinfo; MemoryRegion *sysmem = get_system_memory(); diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c index 7cc7a99bfb..f436a0cbc6 100644 --- a/hw/dummy_m68k.c +++ b/hw/dummy_m68k.c @@ -16,11 +16,11 @@ /* Board init. */ -static void dummy_m68k_init(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) +static void dummy_m68k_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; CPUM68KState *env; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); diff --git a/hw/exynos4_boards.c b/hw/exynos4_boards.c index 4bb0a60cb1..4951064c3f 100644 --- a/hw/exynos4_boards.c +++ b/hw/exynos4_boards.c @@ -130,22 +130,22 @@ static Exynos4210State *exynos4_boards_init_common( exynos4_board_ram_size[board_type]); } -static void nuri_init(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) +static void nuri_init(QEMUMachineInitArgs *args) { + const char *kernel_filename = args->kernel_filename; + const char *kernel_cmdline = args->kernel_cmdline; + const char *initrd_filename = args->initrd_filename; exynos4_boards_init_common(kernel_filename, kernel_cmdline, initrd_filename, EXYNOS4_BOARD_NURI); arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo); } -static void smdkc210_init(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) +static void smdkc210_init(QEMUMachineInitArgs *args) { + const char *kernel_filename = args->kernel_filename; + const char *kernel_cmdline = args->kernel_cmdline; + const char *initrd_filename = args->initrd_filename; Exynos4210State *s = exynos4_boards_init_common(kernel_filename, kernel_cmdline, initrd_filename, EXYNOS4_BOARD_SMDKC210); diff --git a/hw/gumstix.c b/hw/gumstix.c index 13a36ea5c5..4103a88b80 100644 --- a/hw/gumstix.c +++ b/hw/gumstix.c @@ -45,10 +45,7 @@ static const int sector_len = 128 * 1024; -static void connex_init(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) +static void connex_init(QEMUMachineInitArgs *args) { PXA2xxState *cpu; DriveInfo *dinfo; @@ -84,11 +81,9 @@ static void connex_init(ram_addr_t ram_size, qdev_get_gpio_in(cpu->gpio, 36)); } -static void verdex_init(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) +static void verdex_init(QEMUMachineInitArgs *args) { + const char *cpu_model = args->cpu_model; PXA2xxState *cpu; DriveInfo *dinfo; int be; diff --git a/hw/highbank.c b/hw/highbank.c index 11aa1312c0..15036b6390 100644 --- a/hw/highbank.c +++ b/hw/highbank.c @@ -187,11 +187,13 @@ static struct arm_boot_info highbank_binfo; * 32-bit host, set the reg value of memory to 0xf7ff00000 in the * device tree and pass -m 2047 to QEMU. */ -static void highbank_init(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) +static void highbank_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; DeviceState *dev; SysBusDevice *busdev; qemu_irq *irqp; diff --git a/hw/integratorcp.c b/hw/integratorcp.c index d0e2e9068e..ac0ea83492 100644 --- a/hw/integratorcp.c +++ b/hw/integratorcp.c @@ -438,11 +438,13 @@ static struct arm_boot_info integrator_binfo = { .board_id = 0x113, }; -static void integratorcp_init(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) +static void integratorcp_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; ARMCPU *cpu; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); diff --git a/hw/kzm.c b/hw/kzm.c index 68cd1b48b9..d1266d9305 100644 --- a/hw/kzm.c +++ b/hw/kzm.c @@ -70,11 +70,13 @@ static struct arm_boot_info kzm_binfo = { .board_id = 1722, }; -static void kzm_init(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) +static void kzm_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; ARMCPU *cpu; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); diff --git a/hw/leon3.c b/hw/leon3.c index 7a9729dc28..774273828f 100644 --- a/hw/leon3.c +++ b/hw/leon3.c @@ -94,13 +94,11 @@ static void leon3_set_pil_in(void *opaque, uint32_t pil_in) } } -static void leon3_generic_hw_init(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) +static void leon3_generic_hw_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; SPARCCPU *cpu; CPUSPARCState *env; MemoryRegion *address_space_mem = get_system_memory(); diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c index b76d8008be..c5a62c8264 100644 --- a/hw/lm32_boards.c +++ b/hw/lm32_boards.c @@ -69,12 +69,10 @@ static void main_cpu_reset(void *opaque) env->deba = reset_info->flash_base; } -static void lm32_evr_init(ram_addr_t ram_size_not_used, - const char *boot_device, - const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename, const char *cpu_model) +static void lm32_evr_init(QEMUMachineInitArgs *args) { + const char *cpu_model = args->cpu_model; + const char *kernel_filename = args->kernel_filename; LM32CPU *cpu; CPULM32State *env; DriveInfo *dinfo; @@ -159,12 +157,12 @@ static void lm32_evr_init(ram_addr_t ram_size_not_used, qemu_register_reset(main_cpu_reset, reset_info); } -static void lm32_uclinux_init(ram_addr_t ram_size_not_used, - const char *boot_device, - const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename, const char *cpu_model) +static void lm32_uclinux_init(QEMUMachineInitArgs *args) { + 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; LM32CPU *cpu; CPULM32State *env; DriveInfo *dinfo; diff --git a/hw/mainstone.c b/hw/mainstone.c index 97687b6eeb..c0d6034147 100644 --- a/hw/mainstone.c +++ b/hw/mainstone.c @@ -171,11 +171,13 @@ static void mainstone_common_init(MemoryRegion *address_space_mem, arm_load_kernel(mpu->cpu, &mainstone_binfo); } -static void mainstone_init(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) +static void mainstone_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; mainstone_common_init(get_system_memory(), ram_size, kernel_filename, kernel_cmdline, initrd_filename, cpu_model, mainstone, 0x196); } diff --git a/hw/mcf5208.c b/hw/mcf5208.c index ee25b1b387..688bc3c1a6 100644 --- a/hw/mcf5208.c +++ b/hw/mcf5208.c @@ -187,11 +187,11 @@ static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic) } } -static void mcf5208evb_init(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) +static void mcf5208evb_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; CPUM68KState *env; int kernel_size; uint64_t elf_entry; diff --git a/hw/milkymist.c b/hw/milkymist.c index 2e7235b4b3..ca9ed43d99 100644 --- a/hw/milkymist.c +++ b/hw/milkymist.c @@ -73,12 +73,12 @@ static void main_cpu_reset(void *opaque) } static void -milkymist_init(ram_addr_t ram_size_not_used, - const char *boot_device, - const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename, const char *cpu_model) +milkymist_init(QEMUMachineInitArgs *args) { + 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; LM32CPU *cpu; CPULM32State *env; int kernel_size; diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c index d4a8672f23..fb50a1f67b 100644 --- a/hw/mips_fulong2e.c +++ b/hw/mips_fulong2e.c @@ -256,10 +256,13 @@ static void cpu_request_exit(void *opaque, int irq, int level) } } -static void mips_fulong2e_init(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) +static void mips_fulong2e_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; char *filename; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c index db927f14d0..14df4d7745 100644 --- a/hw/mips_jazz.c +++ b/hw/mips_jazz.c @@ -302,21 +302,19 @@ static void mips_jazz_init(MemoryRegion *address_space, } static -void mips_magnum_init (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 mips_magnum_init(QEMUMachineInitArgs *args) { + ram_addr_t ram_size = args->ram_size; + const char *cpu_model = args->cpu_model; mips_jazz_init(get_system_memory(), get_system_io(), ram_size, cpu_model, JAZZ_MAGNUM); } static -void mips_pica61_init (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 mips_pica61_init(QEMUMachineInitArgs *args) { + ram_addr_t ram_size = args->ram_size; + const char *cpu_model = args->cpu_model; mips_jazz_init(get_system_memory(), get_system_io(), ram_size, cpu_model, JAZZ_PICA61); } diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 632b466e32..ad4910ff66 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -775,11 +775,13 @@ static void cpu_request_exit(void *opaque, int irq, int level) } static -void mips_malta_init (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 mips_malta_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; char *filename; pflash_t *fl; MemoryRegion *system_memory = get_system_memory(); diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c index 830f635597..a1d3945cbb 100644 --- a/hw/mips_mipssim.c +++ b/hw/mips_mipssim.c @@ -131,11 +131,13 @@ static void mipsnet_init(int base, qemu_irq irq, NICInfo *nd) } static void -mips_mipssim_init (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) +mips_mipssim_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; char *filename; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index 967a76e533..b73cdc38ec 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -151,11 +151,13 @@ static void main_cpu_reset(void *opaque) static const int sector_len = 32 * 1024; static -void mips_r4k_init (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 mips_r4k_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; char *filename; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); diff --git a/hw/musicpal.c b/hw/musicpal.c index f305e21038..f06814c83b 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -1508,11 +1508,12 @@ static struct arm_boot_info musicpal_binfo = { .board_id = 0x20e, }; -static void musicpal_init(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) +static void musicpal_init(QEMUMachineInitArgs *args) { + 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; ARMCPU *cpu; qemu_irq *cpu_pic; qemu_irq pic[32]; diff --git a/hw/nseries.c b/hw/nseries.c index 6df71ebb48..7ada90d280 100644 --- a/hw/nseries.c +++ b/hw/nseries.c @@ -1397,21 +1397,27 @@ static struct arm_boot_info n810_binfo = { .atag_board = n810_atag_setup, }; -static void n800_init(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) +static void n800_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; return n8x0_init(ram_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model, &n800_binfo, 800); } -static void n810_init(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) +static void n810_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; return n8x0_init(ram_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model, &n810_binfo, 810); diff --git a/hw/null-machine.c b/hw/null-machine.c index 69910d399c..d813c089e7 100644 --- a/hw/null-machine.c +++ b/hw/null-machine.c @@ -15,12 +15,7 @@ #include "hw/hw.h" #include "hw/boards.h" -static void machine_none_init(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) +static void machine_none_init(QEMUMachineInitArgs *args) { } diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c index abca341926..ad17487fd2 100644 --- a/hw/omap_sx1.c +++ b/hw/omap_sx1.c @@ -209,20 +209,26 @@ static void sx1_init(ram_addr_t ram_size, //~ qemu_console_resize(ds, 640, 480); } -static void sx1_init_v1(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) +static void sx1_init_v1(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; sx1_init(ram_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model, 1); } -static void sx1_init_v2(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) +static void sx1_init_v2(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; sx1_init(ram_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model, 2); } diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c index 55e97f0959..e96a94492b 100644 --- a/hw/openrisc_sim.c +++ b/hw/openrisc_sim.c @@ -90,13 +90,11 @@ static void cpu_openrisc_load_kernel(ram_addr_t ram_size, cpu->env.pc = entry; } -static void openrisc_sim_init(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) +static void openrisc_sim_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; OpenRISCCPU *cpu = NULL; MemoryRegion *ram; int n; diff --git a/hw/palm.c b/hw/palm.c index bacdc90d4a..032b8d6510 100644 --- a/hw/palm.c +++ b/hw/palm.c @@ -190,11 +190,12 @@ static struct arm_boot_info palmte_binfo = { .board_id = 0x331, }; -static void palmte_init(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) +static void palmte_init(QEMUMachineInitArgs *args) { + 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; MemoryRegion *address_space_mem = get_system_memory(); struct omap_mpu_state_s *mpu; int flash_size = 0x00800000; diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 5bd4572d47..bf04a42da5 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -287,13 +287,14 @@ static void pc_init1(MemoryRegion *system_memory, } } -static void pc_init_pci(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) +static void pc_init_pci(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; pc_init1(get_system_memory(), get_system_io(), ram_size, boot_device, @@ -301,13 +302,14 @@ static void pc_init_pci(ram_addr_t ram_size, initrd_filename, cpu_model, 1, 1); } -static void pc_init_pci_no_kvmclock(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) +static void pc_init_pci_no_kvmclock(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; pc_init1(get_system_memory(), get_system_io(), ram_size, boot_device, @@ -315,13 +317,14 @@ static void pc_init_pci_no_kvmclock(ram_addr_t ram_size, initrd_filename, cpu_model, 1, 0); } -static void pc_init_isa(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) +static void pc_init_isa(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; if (cpu_model == NULL) cpu_model = "486"; pc_init1(get_system_memory(), @@ -332,19 +335,12 @@ static void pc_init_isa(ram_addr_t ram_size, } #ifdef CONFIG_XEN -static void pc_xen_hvm_init(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) +static void pc_xen_hvm_init(QEMUMachineInitArgs *args) { if (xen_hvm_init() != 0) { hw_error("xen hardware virtual machine initialisation failed"); } - pc_init_pci_no_kvmclock(ram_size, boot_device, - kernel_filename, kernel_cmdline, - initrd_filename, cpu_model); + pc_init_pci_no_kvmclock(args); xen_vcpu_init(); } #endif diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c index b9bfbed4c4..39df25175b 100644 --- a/hw/petalogix_ml605_mmu.c +++ b/hw/petalogix_ml605_mmu.c @@ -73,12 +73,10 @@ static void machine_cpu_reset(MicroBlazeCPU *cpu) } static void -petalogix_ml605_init(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) +petalogix_ml605_init(QEMUMachineInitArgs *args) { + ram_addr_t ram_size = args->ram_size; + const char *cpu_model = args->cpu_model; MemoryRegion *address_space_mem = get_system_memory(); DeviceState *dev, *dma, *eth0; MicroBlazeCPU *cpu; diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c index 2cf68828ed..71c32ce889 100644 --- a/hw/petalogix_s3adsp1800_mmu.c +++ b/hw/petalogix_s3adsp1800_mmu.c @@ -57,12 +57,10 @@ static void machine_cpu_reset(MicroBlazeCPU *cpu) } static void -petalogix_s3adsp1800_init(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) +petalogix_s3adsp1800_init(QEMUMachineInitArgs *args) { + ram_addr_t ram_size = args->ram_size; + const char *cpu_model = args->cpu_model; DeviceState *dev; MicroBlazeCPU *cpu; CPUMBState *env; diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c index 60a5cb3bd0..4cfb94061a 100644 --- a/hw/ppc/e500plat.c +++ b/hw/ppc/e500plat.c @@ -25,13 +25,14 @@ static void e500plat_fixup_devtree(PPCE500Params *params, void *fdt) sizeof(compatible)); } -static void e500plat_init(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) +static void e500plat_init(QEMUMachineInitArgs *args) { + ram_addr_t ram_size = args->ram_size; + const char *boot_device = args->boot_device; + 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; PPCE500Params params = { .ram_size = ram_size, .boot_device = boot_device, diff --git a/hw/ppc/mpc8544ds.c b/hw/ppc/mpc8544ds.c index 984d21cbf5..e651661941 100644 --- a/hw/ppc/mpc8544ds.c +++ b/hw/ppc/mpc8544ds.c @@ -25,13 +25,14 @@ static void mpc8544ds_fixup_devtree(PPCE500Params *params, void *fdt) sizeof(compatible)); } -static void mpc8544ds_init(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) +static void mpc8544ds_init(QEMUMachineInitArgs *args) { + ram_addr_t ram_size = args->ram_size; + const char *boot_device = args->boot_device; + 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; PPCE500Params params = { .ram_size = ram_size, .boot_device = boot_device, diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c index 476775d05b..e848cb0b5c 100644 --- a/hw/ppc405_boards.c +++ b/hw/ppc405_boards.c @@ -158,7 +158,7 @@ static void ref405ep_fpga_reset (void *opaque) fpga->reg1 = 0x0F; } -static void ref405ep_fpga_init (MemoryRegion *sysmem, uint32_t base) +static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base) { ref405ep_fpga_t *fpga; MemoryRegion *fpga_memory = g_new(MemoryRegion, 1); @@ -170,13 +170,12 @@ static void ref405ep_fpga_init (MemoryRegion *sysmem, uint32_t base) qemu_register_reset(&ref405ep_fpga_reset, fpga); } -static void ref405ep_init (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) +static void ref405ep_init(QEMUMachineInitArgs *args) { + ram_addr_t ram_size = args->ram_size; + const char *kernel_filename = args->kernel_filename; + const char *kernel_cmdline = args->kernel_cmdline; + const char *initrd_filename = args->initrd_filename; char *filename; ppc4xx_bd_info_t bd; CPUPPCState *env; @@ -484,7 +483,7 @@ static void taihu_cpld_reset (void *opaque) cpld->reg1 = 0x80; } -static void taihu_cpld_init (MemoryRegion *sysmem, uint32_t base) +static void taihu_cpld_init(MemoryRegion *sysmem, uint32_t base) { taihu_cpld_t *cpld; MemoryRegion *cpld_memory = g_new(MemoryRegion, 1); @@ -495,13 +494,11 @@ static void taihu_cpld_init (MemoryRegion *sysmem, uint32_t base) qemu_register_reset(&taihu_cpld_reset, cpld); } -static void taihu_405ep_init(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) +static void taihu_405ep_init(QEMUMachineInitArgs *args) { + ram_addr_t ram_size = args->ram_size; + const char *kernel_filename = args->kernel_filename; + const char *initrd_filename = args->initrd_filename; char *filename; qemu_irq *pic; MemoryRegion *sysmem = get_system_memory(); diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c index c198071170..78e7985305 100644 --- a/hw/ppc440_bamboo.c +++ b/hw/ppc440_bamboo.c @@ -157,13 +157,13 @@ static void main_cpu_reset(void *opaque) mmubooke_create_initial_mapping(env, 0, 0); } -static void bamboo_init(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) +static void bamboo_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; unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 }; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram_memories diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index b8d3c9c988..a265445b70 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -128,13 +128,14 @@ static void ppc_core99_reset(void *opaque) } /* PowerPC Mac99 hardware initialisation */ -static void ppc_core99_init (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) +static void ppc_core99_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; PowerPCCPU *cpu = NULL; CPUPPCState *env = NULL; char *filename; diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index 2c4a47813f..de334080ff 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -71,13 +71,14 @@ static void ppc_heathrow_reset(void *opaque) cpu_reset(CPU(cpu)); } -static void ppc_heathrow_init (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) +static void ppc_heathrow_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; MemoryRegion *sysmem = get_system_memory(); PowerPCCPU *cpu = NULL; CPUPPCState *env = NULL; diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index 15444303e4..b426891e29 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -447,13 +447,14 @@ static void ppc_prep_reset(void *opaque) } /* PowerPC PREP hardware initialisation */ -static void ppc_prep_init (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) +static void ppc_prep_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; MemoryRegion *sysmem = get_system_memory(); PowerPCCPU *cpu = NULL; CPUPPCState *env = NULL; diff --git a/hw/puv3.c b/hw/puv3.c index 43f7216e4e..764799cff4 100644 --- a/hw/puv3.c +++ b/hw/puv3.c @@ -91,10 +91,12 @@ static void puv3_load_kernel(const char *kernel_filename) graphic_console_init(NULL, NULL, NULL, NULL, NULL); } -static void puv3_init(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) +static void puv3_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 *initrd_filename = args->initrd_filename; CPUUniCore32State *env; if (initrd_filename) { diff --git a/hw/r2d.c b/hw/r2d.c index 1bc191ff3e..3cb6942056 100644 --- a/hw/r2d.c +++ b/hw/r2d.c @@ -219,11 +219,12 @@ static struct QEMU_PACKED char kernel_cmdline[256]; } boot_params; -static void r2d_init(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) +static void r2d_init(QEMUMachineInitArgs *args) { + 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; SuperHCPU *cpu; CPUSH4State *env; ResetData *reset_info; diff --git a/hw/realview.c b/hw/realview.c index 19db4d026b..8dc4be6ae0 100644 --- a/hw/realview.c +++ b/hw/realview.c @@ -330,11 +330,14 @@ static void realview_init(ram_addr_t ram_size, arm_load_kernel(arm_env_get_cpu(first_cpu), &realview_binfo); } -static void realview_eb_init(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) +static void realview_eb_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; if (!cpu_model) { cpu_model = "arm926"; } @@ -342,11 +345,14 @@ static void realview_eb_init(ram_addr_t ram_size, initrd_filename, cpu_model, BOARD_EB); } -static void realview_eb_mpcore_init(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) +static void realview_eb_mpcore_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; if (!cpu_model) { cpu_model = "arm11mpcore"; } @@ -354,11 +360,14 @@ static void realview_eb_mpcore_init(ram_addr_t ram_size, initrd_filename, cpu_model, BOARD_EB_MPCORE); } -static void realview_pb_a8_init(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) +static void realview_pb_a8_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; if (!cpu_model) { cpu_model = "cortex-a8"; } @@ -366,11 +375,14 @@ static void realview_pb_a8_init(ram_addr_t ram_size, initrd_filename, cpu_model, BOARD_PB_A8); } -static void realview_pbx_a9_init(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) +static void realview_pbx_a9_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; if (!cpu_model) { cpu_model = "cortex-a9"; } diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index 47eed35da3..39ff17828b 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -151,13 +151,14 @@ unsigned s390_del_running_cpu(CPUS390XState *env) } /* PC hardware initialisation */ -static void s390_init(ram_addr_t my_ram_size, - const char *boot_device, - const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename, - const char *cpu_model) +static void s390_init(QEMUMachineInitArgs *args) { + ram_addr_t my_ram_size = args->ram_size; + 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; CPUS390XState *env = NULL; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); diff --git a/hw/shix.c b/hw/shix.c index dd9ce174f9..b56dd54f75 100644 --- a/hw/shix.c +++ b/hw/shix.c @@ -37,11 +37,9 @@ #define BIOS_FILENAME "shix_bios.bin" #define BIOS_ADDRESS 0xA0000000 -static void shix_init(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) +static void shix_init(QEMUMachineInitArgs *args) { + const char *cpu_model = args->cpu_model; int ret; CPUSH4State *env; struct SH7750State *s; diff --git a/hw/spapr.c b/hw/spapr.c index 09b8e99221..637b3fb718 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -665,13 +665,14 @@ static int spapr_vga_init(PCIBus *pci_bus) } /* pSeries LPAR / sPAPR hardware init */ -static void ppc_spapr_init(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) +static void ppc_spapr_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; PowerPCCPU *cpu; CPUPPCState *env; PCIHostState *phb; diff --git a/hw/spitz.c b/hw/spitz.c index 24346dcd5a..29426266b1 100644 --- a/hw/spitz.c +++ b/hw/spitz.c @@ -936,38 +936,46 @@ static void spitz_common_init(ram_addr_t ram_size, sl_bootparam_write(SL_PXA_PARAM_BASE); } -static void spitz_init(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) +static void spitz_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; spitz_common_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename, cpu_model, spitz, 0x2c9); } -static void borzoi_init(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) +static void borzoi_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; spitz_common_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename, cpu_model, borzoi, 0x33f); } -static void akita_init(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) +static void akita_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; spitz_common_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename, cpu_model, akita, 0x2e8); } -static void terrier_init(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) +static void terrier_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; spitz_common_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename, cpu_model, terrier, 0x33f); } diff --git a/hw/stellaris.c b/hw/stellaris.c index 353ca4c046..bfb18b014e 100644 --- a/hw/stellaris.c +++ b/hw/stellaris.c @@ -1313,19 +1313,17 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, } /* FIXME: Figure out how to generate these from stellaris_boards. */ -static void lm3s811evb_init(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) +static void lm3s811evb_init(QEMUMachineInitArgs *args) { + const char *cpu_model = args->cpu_model; + const char *kernel_filename = args->kernel_filename; stellaris_init(kernel_filename, cpu_model, &stellaris_boards[0]); } -static void lm3s6965evb_init(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) +static void lm3s6965evb_init(QEMUMachineInitArgs *args) { + const char *cpu_model = args->cpu_model; + const char *kernel_filename = args->kernel_filename; stellaris_init(kernel_filename, cpu_model, &stellaris_boards[1]); } diff --git a/hw/sun4m.c b/hw/sun4m.c index a04b485eda..dbe93f9eb9 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -1306,92 +1306,118 @@ static const struct sun4m_hwdef sun4m_hwdefs[] = { }; /* SPARCstation 5 hardware initialisation */ -static void ss5_init(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) +static void ss5_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; sun4m_hw_init(&sun4m_hwdefs[0], RAM_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } /* SPARCstation 10 hardware initialisation */ -static void ss10_init(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) +static void ss10_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; sun4m_hw_init(&sun4m_hwdefs[1], RAM_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } /* SPARCserver 600MP hardware initialisation */ -static void ss600mp_init(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) +static void ss600mp_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; sun4m_hw_init(&sun4m_hwdefs[2], RAM_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } /* SPARCstation 20 hardware initialisation */ -static void ss20_init(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) +static void ss20_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; sun4m_hw_init(&sun4m_hwdefs[3], RAM_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } /* SPARCstation Voyager hardware initialisation */ -static void vger_init(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) +static void vger_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; sun4m_hw_init(&sun4m_hwdefs[4], RAM_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } /* SPARCstation LX hardware initialisation */ -static void ss_lx_init(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) +static void ss_lx_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; sun4m_hw_init(&sun4m_hwdefs[5], RAM_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } /* SPARCstation 4 hardware initialisation */ -static void ss4_init(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) +static void ss4_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; sun4m_hw_init(&sun4m_hwdefs[6], RAM_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } /* SPARCClassic hardware initialisation */ -static void scls_init(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) +static void scls_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; sun4m_hw_init(&sun4m_hwdefs[7], RAM_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } /* SPARCbook hardware initialisation */ -static void sbook_init(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) +static void sbook_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; sun4m_hw_init(&sun4m_hwdefs[8], RAM_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } @@ -1654,21 +1680,27 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size, } /* SPARCserver 1000 hardware initialisation */ -static void ss1000_init(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) +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(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) +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); } @@ -1848,11 +1880,14 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size, } /* SPARCstation 2 hardware initialisation */ -static void ss2_init(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) +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); } diff --git a/hw/sun4u.c b/hw/sun4u.c index 940db3348a..abf68cf50f 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -933,31 +933,40 @@ static const struct hwdef hwdefs[] = { }; /* Sun4u hardware initialisation */ -static void sun4u_init(ram_addr_t RAM_size, - const char *boot_devices, - const char *kernel_filename, const char *kernel_cmdline, - const char *initrd_filename, const char *cpu_model) +static void sun4u_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_devices = args->boot_device; sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename, kernel_cmdline, initrd_filename, cpu_model, &hwdefs[0]); } /* Sun4v hardware initialisation */ -static void sun4v_init(ram_addr_t RAM_size, - const char *boot_devices, - const char *kernel_filename, const char *kernel_cmdline, - const char *initrd_filename, const char *cpu_model) +static void sun4v_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_devices = args->boot_device; sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename, kernel_cmdline, initrd_filename, cpu_model, &hwdefs[1]); } /* Niagara hardware initialisation */ -static void niagara_init(ram_addr_t RAM_size, - const char *boot_devices, - const char *kernel_filename, const char *kernel_cmdline, - const char *initrd_filename, const char *cpu_model) +static void niagara_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_devices = args->boot_device; sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename, kernel_cmdline, initrd_filename, cpu_model, &hwdefs[2]); } diff --git a/hw/tosa.c b/hw/tosa.c index 297a8c2ed0..512278c241 100644 --- a/hw/tosa.c +++ b/hw/tosa.c @@ -205,11 +205,12 @@ static struct arm_boot_info tosa_binfo = { .ram_size = 0x04000000, }; -static void tosa_init(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) +static void tosa_init(QEMUMachineInitArgs *args) { + 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; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *rom = g_new(MemoryRegion, 1); PXA2xxState *mpu; diff --git a/hw/versatilepb.c b/hw/versatilepb.c index 7b1b0256aa..756ec29da5 100644 --- a/hw/versatilepb.c +++ b/hw/versatilepb.c @@ -348,22 +348,28 @@ static void versatile_init(ram_addr_t ram_size, arm_load_kernel(cpu, &versatile_binfo); } -static void vpb_init(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) +static void vpb_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; versatile_init(ram_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model, 0x183); } -static void vab_init(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) +static void vab_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; versatile_init(ram_size, boot_device, kernel_filename, kernel_cmdline, diff --git a/hw/vexpress.c b/hw/vexpress.c index 3596d1e33f..36503d69fa 100644 --- a/hw/vexpress.c +++ b/hw/vexpress.c @@ -467,25 +467,27 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, arm_load_kernel(arm_env_get_cpu(first_cpu), &vexpress_binfo); } -static void vexpress_a9_init(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) +static void vexpress_a9_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; vexpress_common_init(&a9_daughterboard, ram_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } -static void vexpress_a15_init(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) +static void vexpress_a15_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; vexpress_common_init(&a15_daughterboard, ram_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c index 79bc0d10ee..a09b27a346 100644 --- a/hw/virtex_ml507.c +++ b/hw/virtex_ml507.c @@ -183,12 +183,12 @@ static int xilinx_load_device_tree(target_phys_addr_t addr, return fdt_size; } -static void virtex_init(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) +static void virtex_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; MemoryRegion *address_space_mem = get_system_memory(); DeviceState *dev; PowerPCCPU *cpu; diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c index 4b72aa7557..426470351e 100644 --- a/hw/xen_machine_pv.c +++ b/hw/xen_machine_pv.c @@ -29,13 +29,12 @@ #include "xen_domainbuild.h" #include "blockdev.h" -static void xen_init_pv(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) +static void xen_init_pv(QEMUMachineInitArgs *args) { + 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; X86CPU *cpu; CPUX86State *env; DriveInfo *dinfo; diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c index fd46ba2527..c55dafba6b 100644 --- a/hw/xilinx_zynq.c +++ b/hw/xilinx_zynq.c @@ -77,10 +77,13 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq) } -static void zynq_init(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) +static void zynq_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; ARMCPU *cpu; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ext_ram = g_new(MemoryRegion, 1); diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c index 3653f65b1e..1fd2c47ac5 100644 --- a/hw/xtensa_lx60.c +++ b/hw/xtensa_lx60.c @@ -268,11 +268,14 @@ static void lx_init(const LxBoardDesc *board, } } -static void xtensa_lx60_init(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) +static void xtensa_lx60_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; static const LxBoardDesc lx60_board = { .flash_size = 0x400000, .flash_sector_size = 0x10000, @@ -283,11 +286,14 @@ static void xtensa_lx60_init(ram_addr_t ram_size, initrd_filename, cpu_model); } -static void xtensa_lx200_init(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) +static void xtensa_lx200_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; static const LxBoardDesc lx200_board = { .flash_size = 0x1000000, .flash_sector_size = 0x20000, diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c index 831460b7c4..2e846d8aa6 100644 --- a/hw/xtensa_sim.c +++ b/hw/xtensa_sim.c @@ -96,11 +96,14 @@ static void sim_init(ram_addr_t ram_size, } } -static void xtensa_sim_init(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) +static void xtensa_sim_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; if (!cpu_model) { cpu_model = XTENSA_DEFAULT_CPU_MODEL; } diff --git a/hw/z2.c b/hw/z2.c index 076fad20c6..f62b8067bf 100644 --- a/hw/z2.c +++ b/hw/z2.c @@ -295,11 +295,12 @@ static TypeInfo aer915_info = { .class_init = aer915_class_init, }; -static void z2_init(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) +static void z2_init(QEMUMachineInitArgs *args) { + 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; MemoryRegion *address_space_mem = get_system_memory(); uint32_t sector_len = 0x10000; PXA2xxState *mpu; diff --git a/vl.c b/vl.c index 5b357a3b06..ee3c43ae2f 100644 --- a/vl.c +++ b/vl.c @@ -3638,8 +3638,13 @@ int main(int argc, char **argv, char **envp) qdev_machine_init(); - machine->init(ram_size, boot_devices, - kernel_filename, kernel_cmdline, initrd_filename, cpu_model); + QEMUMachineInitArgs args = { .ram_size = ram_size, + .boot_device = boot_devices, + .kernel_filename = kernel_filename, + .kernel_cmdline = kernel_cmdline, + .initrd_filename = initrd_filename, + .cpu_model = cpu_model }; + machine->init(&args); cpu_synchronize_all_post_init(); From f1bc0bcc9dbbbf5674add3075b5efe0a93fe34f0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 17:30:10 +1000 Subject: [PATCH 1002/2270] exec: Split up and tidy code_gen_buffer It now consists of: A macro definition of MAX_CODE_GEN_BUFFER_SIZE with host-specific values, A function size_code_gen_buffer that applies most of the reasoning for choosing a buffer size, Three variations of a function alloc_code_gen_buffer that contain all of the logic for allocating executable memory via a given allocation mechanism. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- exec.c | 201 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 106 insertions(+), 95 deletions(-) diff --git a/exec.c b/exec.c index 7899042ce9..eecae2f174 100644 --- a/exec.c +++ b/exec.c @@ -103,9 +103,9 @@ spinlock_t tb_lock = SPIN_LOCK_UNLOCKED; uint8_t code_gen_prologue[1024] code_gen_section; static uint8_t *code_gen_buffer; -static unsigned long code_gen_buffer_size; +static size_t code_gen_buffer_size; /* threshold to flush the translated code buffer */ -static unsigned long code_gen_buffer_max_size; +static size_t code_gen_buffer_max_size; static uint8_t *code_gen_ptr; #if !defined(CONFIG_USER_ONLY) @@ -497,110 +497,121 @@ bool memory_region_is_unassigned(MemoryRegion *mr) #define mmap_unlock() do { } while(0) #endif -#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024) - #if defined(CONFIG_USER_ONLY) /* Currently it is not recommended to allocate big chunks of data in - user mode. It will change when a dedicated libc will be used */ + user mode. It will change when a dedicated libc will be used. */ +/* ??? 64-bit hosts ought to have no problem mmaping data outside the + region in which the guest needs to run. Revisit this. */ #define USE_STATIC_CODE_GEN_BUFFER #endif +/* ??? Should configure for this, not list operating systems here. */ +#if (defined(__linux__) \ + || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \ + || defined(__DragonFly__) || defined(__OpenBSD__) \ + || defined(__NetBSD__)) +# define USE_MMAP +#endif + +/* Maximum size of the code gen buffer we'd like to use. Unless otherwise + indicated, this is constrained by the range of direct branches on the + host cpu, as used by the TCG implementation of goto_tb. */ +#if defined(__x86_64__) +# define MAX_CODE_GEN_BUFFER_SIZE (2ul * 1024 * 1024 * 1024) +#elif defined(__sparc__) +# define MAX_CODE_GEN_BUFFER_SIZE (2ul * 1024 * 1024 * 1024) +#elif defined(__arm__) +# define MAX_CODE_GEN_BUFFER_SIZE (16u * 1024 * 1024) +#elif defined(__s390x__) + /* We have a +- 4GB range on the branches; leave some slop. */ +# define MAX_CODE_GEN_BUFFER_SIZE (3ul * 1024 * 1024 * 1024) +#else +# define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1) +#endif + +#define DEFAULT_CODE_GEN_BUFFER_SIZE (32u * 1024 * 1024) + +static inline size_t size_code_gen_buffer(size_t tb_size) +{ + /* Size the buffer. */ + if (tb_size == 0) { +#ifdef USE_STATIC_CODE_GEN_BUFFER + tb_size = DEFAULT_CODE_GEN_BUFFER_SIZE; +#else + /* ??? Needs adjustments. */ + /* ??? If we relax the requirement that CONFIG_USER_ONLY use the + static buffer, we could size this on RESERVED_VA, on the text + segment size of the executable, or continue to use the default. */ + tb_size = (unsigned long)(ram_size / 4); +#endif + } + if (tb_size < MIN_CODE_GEN_BUFFER_SIZE) { + tb_size = MIN_CODE_GEN_BUFFER_SIZE; + } + if (tb_size > MAX_CODE_GEN_BUFFER_SIZE) { + tb_size = MAX_CODE_GEN_BUFFER_SIZE; + } + code_gen_buffer_size = tb_size; + return tb_size; +} + #ifdef USE_STATIC_CODE_GEN_BUFFER static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE] - __attribute__((aligned (CODE_GEN_ALIGN))); -#endif + __attribute__((aligned(CODE_GEN_ALIGN))); -static void code_gen_alloc(unsigned long tb_size) +static inline void *alloc_code_gen_buffer(void) { -#ifdef USE_STATIC_CODE_GEN_BUFFER - code_gen_buffer = static_code_gen_buffer; - code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE; - map_exec(code_gen_buffer, code_gen_buffer_size); -#else - code_gen_buffer_size = tb_size; - if (code_gen_buffer_size == 0) { -#if defined(CONFIG_USER_ONLY) - code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE; -#else - /* XXX: needs adjustments */ - code_gen_buffer_size = (unsigned long)(ram_size / 4); -#endif - } - if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE) - code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE; - /* The code gen buffer location may have constraints depending on - the host cpu and OS */ -#if defined(__linux__) - { - int flags; - void *start = NULL; + map_exec(static_code_gen_buffer, code_gen_buffer_size); + return static_code_gen_buffer; +} +#elif defined(USE_MMAP) +static inline void *alloc_code_gen_buffer(void) +{ + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + uintptr_t start = 0; + void *buf; - flags = MAP_PRIVATE | MAP_ANONYMOUS; -#if defined(__x86_64__) - flags |= MAP_32BIT; - /* Cannot map more than that */ - if (code_gen_buffer_size > (800 * 1024 * 1024)) - code_gen_buffer_size = (800 * 1024 * 1024); -#elif defined(__sparc__) && HOST_LONG_BITS == 64 - // Map the buffer below 2G, so we can use direct calls and branches - start = (void *) 0x40000000UL; - if (code_gen_buffer_size > (512 * 1024 * 1024)) - code_gen_buffer_size = (512 * 1024 * 1024); -#elif defined(__arm__) - /* Keep the buffer no bigger than 16MB to branch between blocks */ - if (code_gen_buffer_size > 16 * 1024 * 1024) - code_gen_buffer_size = 16 * 1024 * 1024; -#elif defined(__s390x__) - /* Map the buffer so that we can use direct calls and branches. */ - /* We have a +- 4GB range on the branches; leave some slop. */ - if (code_gen_buffer_size > (3ul * 1024 * 1024 * 1024)) { - code_gen_buffer_size = 3ul * 1024 * 1024 * 1024; - } - start = (void *)0x90000000UL; -#endif - code_gen_buffer = mmap(start, code_gen_buffer_size, - PROT_WRITE | PROT_READ | PROT_EXEC, - flags, -1, 0); - if (code_gen_buffer == MAP_FAILED) { - fprintf(stderr, "Could not allocate dynamic translator buffer\n"); - exit(1); - } - } -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \ - || defined(__DragonFly__) || defined(__OpenBSD__) \ - || defined(__NetBSD__) - { - int flags; - void *addr = NULL; - flags = MAP_PRIVATE | MAP_ANONYMOUS; -#if defined(__x86_64__) - /* FreeBSD doesn't have MAP_32BIT, use MAP_FIXED and assume - * 0x40000000 is free */ - flags |= MAP_FIXED; - addr = (void *)0x40000000; - /* Cannot map more than that */ - if (code_gen_buffer_size > (800 * 1024 * 1024)) - code_gen_buffer_size = (800 * 1024 * 1024); -#elif defined(__sparc__) && HOST_LONG_BITS == 64 - // Map the buffer below 2G, so we can use direct calls and branches - addr = (void *) 0x40000000UL; - if (code_gen_buffer_size > (512 * 1024 * 1024)) { - code_gen_buffer_size = (512 * 1024 * 1024); - } -#endif - code_gen_buffer = mmap(addr, code_gen_buffer_size, - PROT_WRITE | PROT_READ | PROT_EXEC, - flags, -1, 0); - if (code_gen_buffer == MAP_FAILED) { - fprintf(stderr, "Could not allocate dynamic translator buffer\n"); - exit(1); - } + /* Constrain the position of the buffer based on the host cpu. + Note that these addresses are chosen in concert with the + addresses assigned in the relevant linker script file. */ +# if defined(__x86_64__) && defined(MAP_32BIT) + /* Force the memory down into low memory with the executable. + Leave the choice of exact location with the kernel. */ + flags |= MAP_32BIT; + /* Cannot expect to map more than 800MB in low memory. */ + if (code_gen_buffer_size > 800u * 1024 * 1024) { + code_gen_buffer_size = 800u * 1024 * 1024; } +# elif defined(__sparc__) + start = 0x40000000ul; +# elif defined(__s390x__) + start = 0x90000000ul; +# endif + + buf = mmap((void *)start, code_gen_buffer_size, + PROT_WRITE | PROT_READ | PROT_EXEC, flags, -1, 0); + return buf == MAP_FAILED ? NULL : buf; +} #else - code_gen_buffer = g_malloc(code_gen_buffer_size); - map_exec(code_gen_buffer, code_gen_buffer_size); -#endif -#endif /* !USE_STATIC_CODE_GEN_BUFFER */ +static inline void *alloc_code_gen_buffer(void) +{ + void *buf = g_malloc(code_gen_buffer_size); + if (buf) { + map_exec(buf, code_gen_buffer_size); + } + return buf; +} +#endif /* USE_STATIC_CODE_GEN_BUFFER, USE_MMAP */ + +static inline void code_gen_alloc(size_t tb_size) +{ + code_gen_buffer_size = size_code_gen_buffer(tb_size); + code_gen_buffer = alloc_code_gen_buffer(); + if (code_gen_buffer == NULL) { + fprintf(stderr, "Could not allocate dynamic translator buffer\n"); + exit(1); + } + map_exec(code_gen_prologue, sizeof(code_gen_prologue)); code_gen_buffer_max_size = code_gen_buffer_size - (TCG_MAX_OP_SIZE * OPC_BUF_SIZE); @@ -4188,7 +4199,7 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) } /* XXX: avoid using doubles ? */ cpu_fprintf(f, "Translation buffer state:\n"); - cpu_fprintf(f, "gen code size %td/%ld\n", + cpu_fprintf(f, "gen code size %td/%zd\n", code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size); cpu_fprintf(f, "TB count %d/%d\n", nb_tbs, code_gen_max_blocks); From 3d85a72fd8af6804f66a48d85187f448b14ddba3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 17:30:11 +1000 Subject: [PATCH 1003/2270] exec: Don't make DEFAULT_CODE_GEN_BUFFER_SIZE too large For ARM we cap the buffer size to 16MB. Do not allocate 32MB in that case. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- exec.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/exec.c b/exec.c index eecae2f174..6c0b2d715a 100644 --- a/exec.c +++ b/exec.c @@ -529,7 +529,11 @@ bool memory_region_is_unassigned(MemoryRegion *mr) # define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1) #endif -#define DEFAULT_CODE_GEN_BUFFER_SIZE (32u * 1024 * 1024) +#define DEFAULT_CODE_GEN_BUFFER_SIZE_1 (32u * 1024 * 1024) + +#define DEFAULT_CODE_GEN_BUFFER_SIZE \ + (DEFAULT_CODE_GEN_BUFFER_SIZE_1 < MAX_CODE_GEN_BUFFER_SIZE \ + ? DEFAULT_CODE_GEN_BUFFER_SIZE_1 : MAX_CODE_GEN_BUFFER_SIZE) static inline size_t size_code_gen_buffer(size_t tb_size) { From 405def18466d0cbd84e6a0edb598466b0a5e15c3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 17:30:12 +1000 Subject: [PATCH 1004/2270] exec: Do not use absolute address hints for code_gen_buffer with -fpie The hard-coded addresses inside alloc_code_gen_buffer only make sense if we're building an executable that will actually run at the address we've put into the linker scripts. When we're building with -fpie, the executable will run at some random location chosen by the kernel. We get better placement for the code_gen_buffer if we allow the kernel to place the memory, as it will tend to to place it near the executable, based on the PROT_EXEC bit. Since code_gen_prologue is always inside the executable, this effect is easily seen at the end of most TB, with the exit_tb opcode, and with any calls to helper functions. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- exec.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/exec.c b/exec.c index 6c0b2d715a..5e33a3d435 100644 --- a/exec.c +++ b/exec.c @@ -578,7 +578,12 @@ static inline void *alloc_code_gen_buffer(void) /* Constrain the position of the buffer based on the host cpu. Note that these addresses are chosen in concert with the addresses assigned in the relevant linker script file. */ -# if defined(__x86_64__) && defined(MAP_32BIT) +# if defined(__PIE__) || defined(__PIC__) + /* Don't bother setting a preferred location if we're building + a position-independent executable. We're more likely to get + an address near the main executable if we let the kernel + choose the address. */ +# elif defined(__x86_64__) && defined(MAP_32BIT) /* Force the memory down into low memory with the executable. Leave the choice of exact location with the kernel. */ flags |= MAP_32BIT; From 4438c8a9469d79fa2c58189418befb506da54d97 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 17:30:13 +1000 Subject: [PATCH 1005/2270] exec: Allocate code_gen_prologue from code_gen_buffer We had a hack for arm and sparc, allocating code_gen_prologue to a special section. Which, honestly does no good under certain cases. We've already got limits on code_gen_buffer_size to ensure that all TBs can use direct branches between themselves; reuse this limit to ensure the prologue is also reachable. As a bonus, we get to avoid marking a page of the main executable's data segment as executable. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- exec.c | 30 +++++++++++------------------- tcg/tcg.h | 2 +- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/exec.c b/exec.c index 5e33a3d435..8958b281dc 100644 --- a/exec.c +++ b/exec.c @@ -86,22 +86,7 @@ static int nb_tbs; /* any access to the tbs or the page table must use this lock */ spinlock_t tb_lock = SPIN_LOCK_UNLOCKED; -#if defined(__arm__) || defined(__sparc__) -/* The prologue must be reachable with a direct jump. ARM and Sparc64 - have limited branch ranges (possibly also PPC) so place it in a - section close to code segment. */ -#define code_gen_section \ - __attribute__((__section__(".gen_code"))) \ - __attribute__((aligned (32))) -#elif defined(_WIN32) && !defined(_WIN64) -#define code_gen_section \ - __attribute__((aligned (16))) -#else -#define code_gen_section \ - __attribute__((aligned (32))) -#endif - -uint8_t code_gen_prologue[1024] code_gen_section; +uint8_t *code_gen_prologue; static uint8_t *code_gen_buffer; static size_t code_gen_buffer_size; /* threshold to flush the translated code buffer */ @@ -221,7 +206,7 @@ static int tb_flush_count; static int tb_phys_invalidate_count; #ifdef _WIN32 -static void map_exec(void *addr, long size) +static inline void map_exec(void *addr, long size) { DWORD old_protect; VirtualProtect(addr, size, @@ -229,7 +214,7 @@ static void map_exec(void *addr, long size) } #else -static void map_exec(void *addr, long size) +static inline void map_exec(void *addr, long size) { unsigned long start, end, page_size; @@ -621,7 +606,14 @@ static inline void code_gen_alloc(size_t tb_size) exit(1); } - map_exec(code_gen_prologue, sizeof(code_gen_prologue)); + /* Steal room for the prologue at the end of the buffer. This ensures + (via the MAX_CODE_GEN_BUFFER_SIZE limits above) that direct branches + from TB's to the prologue are going to be in range. It also means + that we don't need to mark (additional) portions of the data segment + as executable. */ + code_gen_prologue = code_gen_buffer + code_gen_buffer_size - 1024; + code_gen_buffer_size -= 1024; + code_gen_buffer_max_size = code_gen_buffer_size - (TCG_MAX_OP_SIZE * OPC_BUF_SIZE); code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE; diff --git a/tcg/tcg.h b/tcg/tcg.h index 7bafe0eeb6..45e94f536c 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -616,7 +616,7 @@ TCGv_i64 tcg_const_i64(int64_t val); TCGv_i32 tcg_const_local_i32(int32_t val); TCGv_i64 tcg_const_local_i64(int64_t val); -extern uint8_t code_gen_prologue[]; +extern uint8_t *code_gen_prologue; /* TCG targets may use a different definition of tcg_qemu_tb_exec. */ #if !defined(tcg_qemu_tb_exec) From 74d590c8e930e42832711604ef0ffd7df6bd5873 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 17:30:14 +1000 Subject: [PATCH 1006/2270] exec: Make MIN_CODE_GEN_BUFFER_SIZE private to exec.c It is used nowhere else, and the corresponding MAX_CODE_GEN_BUFFER_SIZE also lives there. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- exec-all.h | 2 -- exec.c | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/exec-all.h b/exec-all.h index f7f649ee61..16caf49db7 100644 --- a/exec-all.h +++ b/exec-all.h @@ -121,8 +121,6 @@ static inline void tlb_flush(CPUArchState *env, int flush_global) #define CODE_GEN_PHYS_HASH_BITS 15 #define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS) -#define MIN_CODE_GEN_BUFFER_SIZE (1024 * 1024) - /* estimated block size for TB allocation */ /* XXX: use a per code average code fragment size and modulate it according to the host CPU */ diff --git a/exec.c b/exec.c index 8958b281dc..4a86b0f4c4 100644 --- a/exec.c +++ b/exec.c @@ -498,6 +498,10 @@ bool memory_region_is_unassigned(MemoryRegion *mr) # define USE_MMAP #endif +/* Minimum size of the code gen buffer. This number is randomly chosen, + but not so small that we can't have a fair number of TB's live. */ +#define MIN_CODE_GEN_BUFFER_SIZE (1024u * 1024) + /* Maximum size of the code gen buffer we'd like to use. Unless otherwise indicated, this is constrained by the range of direct branches on the host cpu, as used by the TCG implementation of goto_tb. */ From 8802361689c7aa9224aea39329af72fbc7b366ef Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:12 +1000 Subject: [PATCH 1007/2270] target-sparc: Add gen_load/store/dest_gpr Infrastructure to be used to clean up handling of temporaries. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 52 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 6cef96bfa6..eec0db0d70 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -83,7 +83,9 @@ typedef struct DisasContext { struct TranslationBlock *tb; sparc_def_t *def; TCGv_i32 t32[3]; + TCGv ttl[5]; int n_t32; + int n_ttl; } DisasContext; typedef struct { @@ -263,6 +265,49 @@ static inline void gen_address_mask(DisasContext *dc, TCGv addr) #endif } +static inline TCGv get_temp_tl(DisasContext *dc) +{ + TCGv t; + assert(dc->n_ttl < ARRAY_SIZE(dc->ttl)); + dc->ttl[dc->n_ttl++] = t = tcg_temp_new(); + return t; +} + +static inline TCGv gen_load_gpr(DisasContext *dc, int reg) +{ + if (reg == 0 || reg >= 8) { + TCGv t = get_temp_tl(dc); + if (reg == 0) { + tcg_gen_movi_tl(t, 0); + } else { + tcg_gen_ld_tl(t, cpu_regwptr, (reg - 8) * sizeof(target_ulong)); + } + return t; + } else { + return cpu_gregs[reg]; + } +} + +static inline void gen_store_gpr(DisasContext *dc, int reg, TCGv v) +{ + if (reg > 0) { + if (reg < 8) { + tcg_gen_mov_tl(cpu_gregs[reg], v); + } else { + tcg_gen_st_tl(v, cpu_regwptr, (reg - 8) * sizeof(target_ulong)); + } + } +} + +static inline TCGv gen_dest_gpr(DisasContext *dc, int reg) +{ + if (reg == 0 || reg >= 8) { + return get_temp_tl(dc); + } else { + return cpu_gregs[reg]; + } +} + static inline void gen_movl_reg_TN(int reg, TCGv tn) { if (reg == 0) @@ -5229,6 +5274,13 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } dc->n_t32 = 0; } + if (dc->n_ttl != 0) { + int i; + for (i = dc->n_ttl - 1; i >= 0; --i) { + tcg_temp_free(dc->ttl[i]); + } + dc->n_ttl = 0; + } } static inline void gen_intermediate_code_internal(TranslationBlock * tb, From 97ea285917d473c8c8ecb627a637d76082cd6584 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:13 +1000 Subject: [PATCH 1008/2270] target-sparc: Conversion to gen_*_gpr, part 1 Only handle the easy cases directly within disas_sparc_insn. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 420 +++++++++++++++++---------------------- 1 file changed, 177 insertions(+), 243 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index eec0db0d70..0ec3d488c8 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2602,13 +2602,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto jmp_insn; } case 0x4: /* SETHI */ - if (rd) { // nop + /* Special-case %g0 because that's the canonical nop. */ + if (rd) { uint32_t value = GET_FIELD(insn, 10, 31); - TCGv r_const; - - r_const = tcg_const_tl(value << 10); - gen_movl_TN_reg(rd, r_const); - tcg_temp_free(r_const); + TCGv t = gen_dest_gpr(dc, rd); + tcg_gen_movi_tl(t, value << 10); + gen_store_gpr(dc, rd, t); } break; case 0x0: /* UNIMPL */ @@ -2621,11 +2620,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 1: /*CALL*/ { target_long target = GET_FIELDs(insn, 2, 31) << 2; - TCGv r_const; + TCGv o7 = gen_dest_gpr(dc, 15); - r_const = tcg_const_tl(dc->pc); - gen_movl_TN_reg(15, r_const); - tcg_temp_free(r_const); + tcg_gen_movi_tl(o7, dc->pc); + gen_store_gpr(dc, 15, o7); target += dc->pc; gen_mov_pc_npc(dc); #ifdef TARGET_SPARC64 @@ -2689,22 +2687,17 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) /* Signal that the trap value is fully constant. */ mask = 0; } else { - TCGv t1 = tcg_temp_new(); - gen_movl_reg_TN(rs1, t1); + TCGv t1 = gen_load_gpr(dc, rs1); tcg_gen_trunc_tl_i32(trap, t1); - tcg_temp_free(t1); tcg_gen_addi_i32(trap, trap, rs2); } } else { - TCGv t1 = tcg_temp_new(); - TCGv t2 = tcg_temp_new(); + TCGv t1, t2; rs2 = GET_FIELD_SP(insn, 0, 4); - gen_movl_reg_TN(rs1, t1); - gen_movl_reg_TN(rs2, t2); + t1 = gen_load_gpr(dc, rs1); + t2 = gen_load_gpr(dc, rs2); tcg_gen_add_tl(t1, t1, t2); tcg_gen_trunc_tl_i32(trap, t1); - tcg_temp_free(t1); - tcg_temp_free(t2); } if (mask != 0) { tcg_gen_andi_i32(trap, trap, mask); @@ -2738,27 +2731,24 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) microSPARC II */ /* Read Asr17 */ if (rs1 == 0x11 && dc->def->features & CPU_FEATURE_ASR17) { - TCGv r_const; - + TCGv t = gen_dest_gpr(dc, rd); /* Read Asr17 for a Leon3 monoprocessor */ - r_const = tcg_const_tl((1 << 8) - | (dc->def->nwindows - 1)); - gen_movl_TN_reg(rd, r_const); - tcg_temp_free(r_const); + tcg_gen_movi_tl(t, (1 << 8) | (dc->def->nwindows - 1)); + gen_store_gpr(dc, rd, t); break; } #endif - gen_movl_TN_reg(rd, cpu_y); + gen_store_gpr(dc, rd, cpu_y); break; #ifdef TARGET_SPARC64 case 0x2: /* V9 rdccr */ update_psr(dc); gen_helper_rdccr(cpu_dst, cpu_env); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x3: /* V9 rdasi */ tcg_gen_ext_i32_tl(cpu_dst, cpu_asi); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x4: /* V9 rdtick */ { @@ -2769,25 +2759,23 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) offsetof(CPUSPARCState, tick)); gen_helper_tick_get_count(cpu_dst, r_tickptr); tcg_temp_free_ptr(r_tickptr); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); } break; case 0x5: /* V9 rdpc */ { - TCGv r_const; - + TCGv t = gen_dest_gpr(dc, rd); if (unlikely(AM_CHECK(dc))) { - r_const = tcg_const_tl(dc->pc & 0xffffffffULL); + tcg_gen_movi_tl(t, dc->pc & 0xffffffffULL); } else { - r_const = tcg_const_tl(dc->pc); + tcg_gen_movi_tl(t, dc->pc); } - gen_movl_TN_reg(rd, r_const); - tcg_temp_free(r_const); + gen_store_gpr(dc, rd, t); } break; case 0x6: /* V9 rdfprs */ tcg_gen_ext_i32_tl(cpu_dst, cpu_fprs); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0xf: /* V9 membar */ break; /* no effect */ @@ -2795,14 +2783,14 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } - gen_movl_TN_reg(rd, cpu_gsr); + gen_store_gpr(dc, rd, cpu_gsr); break; case 0x16: /* Softint */ tcg_gen_ext_i32_tl(cpu_dst, cpu_softint); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x17: /* Tick compare */ - gen_movl_TN_reg(rd, cpu_tick_cmpr); + gen_store_gpr(dc, rd, cpu_tick_cmpr); break; case 0x18: /* System tick */ { @@ -2813,11 +2801,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) offsetof(CPUSPARCState, stick)); gen_helper_tick_get_count(cpu_dst, r_tickptr); tcg_temp_free_ptr(r_tickptr); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); } break; case 0x19: /* System tick compare */ - gen_movl_TN_reg(rd, cpu_stick_cmpr); + gen_store_gpr(dc, rd, cpu_stick_cmpr); break; case 0x10: /* Performance Control */ case 0x11: /* Performance Instrumentation Counter */ @@ -2864,7 +2852,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto illegal_insn; } #endif - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; } else if (xop == 0x2a) { /* rdwim / V9 rdpr */ if (!supervisor(dc)) @@ -2925,7 +2913,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_ld_ptr(r_tickptr, cpu_env, offsetof(CPUSPARCState, tick)); gen_helper_tick_get_count(cpu_tmp0, r_tickptr); - gen_movl_TN_reg(rd, cpu_tmp0); tcg_temp_free_ptr(r_tickptr); } break; @@ -2997,7 +2984,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #else tcg_gen_ext_i32_tl(cpu_tmp0, cpu_wim); #endif - gen_movl_TN_reg(rd, cpu_tmp0); + gen_store_gpr(dc, rd, cpu_tmp0); break; } else if (xop == 0x2b) { /* rdtbr / V9 flushw */ #ifdef TARGET_SPARC64 @@ -3006,7 +2993,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #else if (!supervisor(dc)) goto priv_insn; - gen_movl_TN_reg(rd, cpu_tbr); + gen_store_gpr(dc, rd, cpu_tbr); #endif break; #endif @@ -3338,38 +3325,40 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto illegal_insn; } } else if (xop == 0x2) { - // clr/mov shortcut - + TCGv dst = gen_dest_gpr(dc, rd); rs1 = GET_FIELD(insn, 13, 17); if (rs1 == 0) { - // or %g0, x, y -> mov T0, x; mov y, T0 + /* clr/mov shortcut : or %g0, x, y -> mov x, y */ if (IS_IMM) { /* immediate */ - TCGv r_const; - simm = GET_FIELDs(insn, 19, 31); - r_const = tcg_const_tl(simm); - gen_movl_TN_reg(rd, r_const); - tcg_temp_free(r_const); + tcg_gen_movi_tl(dst, simm); + gen_store_gpr(dc, rd, dst); } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); - gen_movl_reg_TN(rs2, cpu_dst); - gen_movl_TN_reg(rd, cpu_dst); + if (rs2 == 0) { + tcg_gen_movi_tl(dst, 0); + gen_store_gpr(dc, rd, dst); + } else { + cpu_src2 = gen_load_gpr(dc, rs2); + gen_store_gpr(dc, rd, cpu_src2); + } } } else { cpu_src1 = get_src1(insn, cpu_src1); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); - tcg_gen_ori_tl(cpu_dst, cpu_src1, simm); - gen_movl_TN_reg(rd, cpu_dst); + tcg_gen_ori_tl(dst, cpu_src1, simm); + gen_store_gpr(dc, rd, dst); } else { /* register */ - // or x, %g0, y -> mov T1, x; mov y, T1 rs2 = GET_FIELD(insn, 27, 31); - if (rs2 != 0) { - gen_movl_reg_TN(rs2, cpu_src2); - tcg_gen_or_tl(cpu_dst, cpu_src1, cpu_src2); - gen_movl_TN_reg(rd, cpu_dst); - } else - gen_movl_TN_reg(rd, cpu_src1); + if (rs2 == 0) { + /* mov shortcut: or x, %g0, y -> mov x, y */ + gen_store_gpr(dc, rd, cpu_src1); + } else { + cpu_src2 = gen_load_gpr(dc, rs2); + tcg_gen_or_tl(dst, cpu_src1, cpu_src2); + gen_store_gpr(dc, rd, dst); + } } } #ifdef TARGET_SPARC64 @@ -3384,7 +3373,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src2 = gen_load_gpr(dc, rs2); if (insn & (1 << 12)) { tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f); } else { @@ -3392,7 +3381,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } tcg_gen_shl_i64(cpu_dst, cpu_src1, cpu_tmp0); } - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); } else if (xop == 0x26) { /* srl, V9 srlx */ cpu_src1 = get_src1(insn, cpu_src1); if (IS_IMM) { /* immediate */ @@ -3405,7 +3394,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src2 = gen_load_gpr(dc, rs2); if (insn & (1 << 12)) { tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f); tcg_gen_shr_i64(cpu_dst, cpu_src1, cpu_tmp0); @@ -3415,7 +3404,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_shr_i64(cpu_dst, cpu_dst, cpu_tmp0); } } - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); } else if (xop == 0x27) { /* sra, V9 srax */ cpu_src1 = get_src1(insn, cpu_src1); if (IS_IMM) { /* immediate */ @@ -3423,24 +3412,22 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (insn & (1 << 12)) { tcg_gen_sari_i64(cpu_dst, cpu_src1, simm & 0x3f); } else { - tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL); - tcg_gen_ext32s_i64(cpu_dst, cpu_dst); + tcg_gen_ext32s_i64(cpu_dst, cpu_src1); tcg_gen_sari_i64(cpu_dst, cpu_dst, simm & 0x1f); } } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src2 = gen_load_gpr(dc, rs2); if (insn & (1 << 12)) { tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f); tcg_gen_sar_i64(cpu_dst, cpu_src1, cpu_tmp0); } else { tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f); - tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL); - tcg_gen_ext32s_i64(cpu_dst, cpu_dst); + tcg_gen_ext32s_i64(cpu_dst, cpu_src1); tcg_gen_sar_i64(cpu_dst, cpu_dst, cpu_tmp0); } } - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); #endif } else if (xop < 0x36) { if (xop < 0x20) { @@ -3448,32 +3435,16 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) cpu_src2 = get_src2(insn, cpu_src2); switch (xop & ~0x10) { case 0x0: /* add */ - if (IS_IMM) { - simm = GET_FIELDs(insn, 19, 31); - if (xop & 0x10) { - gen_op_addi_cc(cpu_dst, cpu_src1, simm); - tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD); - dc->cc_op = CC_OP_ADD; - } else { - tcg_gen_addi_tl(cpu_dst, cpu_src1, simm); - } + if (xop & 0x10) { + gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2); + tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD); + dc->cc_op = CC_OP_ADD; } else { - if (xop & 0x10) { - gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2); - tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD); - dc->cc_op = CC_OP_ADD; - } else { - tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2); - } + tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2); } break; case 0x1: /* and */ - if (IS_IMM) { - simm = GET_FIELDs(insn, 19, 31); - tcg_gen_andi_tl(cpu_dst, cpu_src1, simm); - } else { - tcg_gen_and_tl(cpu_dst, cpu_src1, cpu_src2); - } + tcg_gen_and_tl(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) { tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); @@ -3481,12 +3452,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } break; case 0x2: /* or */ - if (IS_IMM) { - simm = GET_FIELDs(insn, 19, 31); - tcg_gen_ori_tl(cpu_dst, cpu_src1, simm); - } else { - tcg_gen_or_tl(cpu_dst, cpu_src1, cpu_src2); - } + tcg_gen_or_tl(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) { tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); @@ -3494,12 +3460,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } break; case 0x3: /* xor */ - if (IS_IMM) { - simm = GET_FIELDs(insn, 19, 31); - tcg_gen_xori_tl(cpu_dst, cpu_src1, simm); - } else { - tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2); - } + tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) { tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); @@ -3507,30 +3468,16 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } break; case 0x4: /* sub */ - if (IS_IMM) { - simm = GET_FIELDs(insn, 19, 31); - if (xop & 0x10) { - gen_op_subi_cc(cpu_dst, cpu_src1, simm, dc); - } else { - tcg_gen_subi_tl(cpu_dst, cpu_src1, simm); - } + if (xop & 0x10) { + gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2); + tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB); + dc->cc_op = CC_OP_SUB; } else { - if (xop & 0x10) { - gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2); - tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB); - dc->cc_op = CC_OP_SUB; - } else { - tcg_gen_sub_tl(cpu_dst, cpu_src1, cpu_src2); - } + tcg_gen_sub_tl(cpu_dst, cpu_src1, cpu_src2); } break; case 0x5: /* andn */ - if (IS_IMM) { - simm = GET_FIELDs(insn, 19, 31); - tcg_gen_andi_tl(cpu_dst, cpu_src1, ~simm); - } else { - tcg_gen_andc_tl(cpu_dst, cpu_src1, cpu_src2); - } + tcg_gen_andc_tl(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) { tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); @@ -3538,12 +3485,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } break; case 0x6: /* orn */ - if (IS_IMM) { - simm = GET_FIELDs(insn, 19, 31); - tcg_gen_ori_tl(cpu_dst, cpu_src1, ~simm); - } else { - tcg_gen_orc_tl(cpu_dst, cpu_src1, cpu_src2); - } + tcg_gen_orc_tl(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) { tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); @@ -3551,13 +3493,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } break; case 0x7: /* xorn */ - if (IS_IMM) { - simm = GET_FIELDs(insn, 19, 31); - tcg_gen_xori_tl(cpu_dst, cpu_src1, ~simm); - } else { - tcg_gen_not_tl(cpu_tmp0, cpu_src2); - tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_tmp0); - } + tcg_gen_eqv_tl(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) { tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); @@ -3570,12 +3506,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; #ifdef TARGET_SPARC64 case 0x9: /* V9 mulx */ - if (IS_IMM) { - simm = GET_FIELDs(insn, 19, 31); - tcg_gen_muli_i64(cpu_dst, cpu_src1, simm); - } else { - tcg_gen_mul_i64(cpu_dst, cpu_src1, cpu_src2); - } + tcg_gen_mul_i64(cpu_dst, cpu_src1, cpu_src2); break; #endif case 0xa: /* umul */ @@ -3630,39 +3561,39 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) default: goto illegal_insn; } - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); } else { cpu_src1 = get_src1(insn, cpu_src1); cpu_src2 = get_src2(insn, cpu_src2); switch (xop) { case 0x20: /* taddcc */ gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADD); dc->cc_op = CC_OP_TADD; break; case 0x21: /* tsubcc */ gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUB); dc->cc_op = CC_OP_TSUB; break; case 0x22: /* taddcctv */ gen_helper_taddcctv(cpu_dst, cpu_env, cpu_src1, cpu_src2); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); dc->cc_op = CC_OP_TADDTV; break; case 0x23: /* tsubcctv */ gen_helper_tsubcctv(cpu_dst, cpu_env, cpu_src1, cpu_src2); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); dc->cc_op = CC_OP_TSUBTV; break; case 0x24: /* mulscc */ update_psr(dc); gen_op_mulscc(cpu_dst, cpu_src1, cpu_src2); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD); dc->cc_op = CC_OP_ADD; break; @@ -3675,7 +3606,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f); tcg_gen_shl_tl(cpu_dst, cpu_src1, cpu_tmp0); } - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x26: /* srl */ if (IS_IMM) { /* immediate */ @@ -3685,7 +3616,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f); tcg_gen_shr_tl(cpu_dst, cpu_src1, cpu_tmp0); } - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x27: /* sra */ if (IS_IMM) { /* immediate */ @@ -3695,7 +3626,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f); tcg_gen_sar_tl(cpu_dst, cpu_src1, cpu_tmp0); } - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; #endif case 0x30: @@ -4059,6 +3990,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) int cc = GET_FIELD_SP(insn, 11, 12); int cond = GET_FIELD_SP(insn, 14, 17); DisasCompare cmp; + TCGv dst; if (insn & (1 << 18)) { if (cc == 0) { @@ -4080,28 +4012,27 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_movi_tl(cpu_src2, simm); } - gen_movl_reg_TN(rd, cpu_dst); - tcg_gen_movcond_tl(cmp.cond, cpu_dst, + dst = gen_load_gpr(dc, rd); + tcg_gen_movcond_tl(cmp.cond, dst, cmp.c1, cmp.c2, - cpu_src2, cpu_dst); + cpu_src2, dst); free_compare(&cmp); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, dst); break; } case 0x2d: /* V9 sdivx */ gen_helper_sdivx(cpu_dst, cpu_env, cpu_src1, cpu_src2); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x2e: /* V9 popc */ - { - cpu_src2 = get_src2(insn, cpu_src2); - gen_helper_popc(cpu_dst, cpu_src2); - gen_movl_TN_reg(rd, cpu_dst); - } + gen_helper_popc(cpu_dst, cpu_src2); + gen_store_gpr(dc, rd, cpu_dst); + break; case 0x2f: /* V9 movr */ { int cond = GET_FIELD_SP(insn, 10, 12); DisasCompare cmp; + TCGv dst; gen_compare_reg(&cmp, cond, cpu_src1); @@ -4113,12 +4044,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_movi_tl(cpu_src2, simm); } - gen_movl_reg_TN(rd, cpu_dst); - tcg_gen_movcond_tl(cmp.cond, cpu_dst, + dst = gen_load_gpr(dc, rd); + tcg_gen_movcond_tl(cmp.cond, dst, cmp.c1, cmp.c2, - cpu_src2, cpu_dst); + cpu_src2, dst); free_compare(&cmp); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, dst); break; } #endif @@ -4138,188 +4069,188 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) switch (opf) { case 0x000: /* VIS I edge8cc */ CHECK_FPU_FEATURE(dc, VIS1); - gen_movl_reg_TN(rs1, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src1 = gen_load_gpr(dc, rs1); + cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 0); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x001: /* VIS II edge8n */ CHECK_FPU_FEATURE(dc, VIS2); - gen_movl_reg_TN(rs1, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src1 = gen_load_gpr(dc, rs1); + cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 0); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x002: /* VIS I edge8lcc */ CHECK_FPU_FEATURE(dc, VIS1); - gen_movl_reg_TN(rs1, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src1 = gen_load_gpr(dc, rs1); + cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 1); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x003: /* VIS II edge8ln */ CHECK_FPU_FEATURE(dc, VIS2); - gen_movl_reg_TN(rs1, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src1 = gen_load_gpr(dc, rs1); + cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 1); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x004: /* VIS I edge16cc */ CHECK_FPU_FEATURE(dc, VIS1); - gen_movl_reg_TN(rs1, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src1 = gen_load_gpr(dc, rs1); + cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 0); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x005: /* VIS II edge16n */ CHECK_FPU_FEATURE(dc, VIS2); - gen_movl_reg_TN(rs1, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src1 = gen_load_gpr(dc, rs1); + cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 0); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x006: /* VIS I edge16lcc */ CHECK_FPU_FEATURE(dc, VIS1); - gen_movl_reg_TN(rs1, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src1 = gen_load_gpr(dc, rs1); + cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 1); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x007: /* VIS II edge16ln */ CHECK_FPU_FEATURE(dc, VIS2); - gen_movl_reg_TN(rs1, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src1 = gen_load_gpr(dc, rs1); + cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 1); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x008: /* VIS I edge32cc */ CHECK_FPU_FEATURE(dc, VIS1); - gen_movl_reg_TN(rs1, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src1 = gen_load_gpr(dc, rs1); + cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 0); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x009: /* VIS II edge32n */ CHECK_FPU_FEATURE(dc, VIS2); - gen_movl_reg_TN(rs1, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src1 = gen_load_gpr(dc, rs1); + cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 0); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x00a: /* VIS I edge32lcc */ CHECK_FPU_FEATURE(dc, VIS1); - gen_movl_reg_TN(rs1, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src1 = gen_load_gpr(dc, rs1); + cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 1); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x00b: /* VIS II edge32ln */ CHECK_FPU_FEATURE(dc, VIS2); - gen_movl_reg_TN(rs1, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src1 = gen_load_gpr(dc, rs1); + cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 1); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x010: /* VIS I array8 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = get_src1(insn, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src2 = gen_load_gpr(dc, rs2); gen_helper_array8(cpu_dst, cpu_src1, cpu_src2); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x012: /* VIS I array16 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = get_src1(insn, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src2 = gen_load_gpr(dc, rs2); gen_helper_array8(cpu_dst, cpu_src1, cpu_src2); tcg_gen_shli_i64(cpu_dst, cpu_dst, 1); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x014: /* VIS I array32 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = get_src1(insn, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src2 = gen_load_gpr(dc, rs2); gen_helper_array8(cpu_dst, cpu_src1, cpu_src2); tcg_gen_shli_i64(cpu_dst, cpu_dst, 2); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x018: /* VIS I alignaddr */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = get_src1(insn, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src2 = gen_load_gpr(dc, rs2); gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 0); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x01a: /* VIS I alignaddrl */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = get_src1(insn, cpu_src1); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src2 = gen_load_gpr(dc, rs2); gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 1); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x019: /* VIS II bmask */ CHECK_FPU_FEATURE(dc, VIS2); cpu_src1 = get_src1(insn, cpu_src1); - cpu_src2 = get_src1(insn, cpu_src2); + cpu_src2 = get_src2(insn, cpu_src2); tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2); tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, cpu_dst, 32, 32); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x020: /* VIS I fcmple16 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_helper_fcmple16(cpu_dst, cpu_src1_64, cpu_src2_64); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x022: /* VIS I fcmpne16 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_helper_fcmpne16(cpu_dst, cpu_src1_64, cpu_src2_64); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x024: /* VIS I fcmple32 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_helper_fcmple32(cpu_dst, cpu_src1_64, cpu_src2_64); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x026: /* VIS I fcmpne32 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_helper_fcmpne32(cpu_dst, cpu_src1_64, cpu_src2_64); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x028: /* VIS I fcmpgt16 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_helper_fcmpgt16(cpu_dst, cpu_src1_64, cpu_src2_64); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x02a: /* VIS I fcmpeq16 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_helper_fcmpeq16(cpu_dst, cpu_src1_64, cpu_src2_64); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x02c: /* VIS I fcmpgt32 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_helper_fcmpgt32(cpu_dst, cpu_src1_64, cpu_src2_64); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x02e: /* VIS I fcmpeq32 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_helper_fcmpeq32(cpu_dst, cpu_src1_64, cpu_src2_64); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x031: /* VIS I fmul8x16 */ CHECK_FPU_FEATURE(dc, VIS1); @@ -4587,10 +4518,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); if (rs2) { - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src2 = gen_load_gpr(dc, rs2); tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2); - } else + } else { tcg_gen_mov_tl(cpu_dst, cpu_src1); + } } gen_helper_restore(cpu_env); gen_mov_pc_npc(dc); @@ -4609,20 +4541,21 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); if (rs2) { - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src2 = gen_load_gpr(dc, rs2); tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2); - } else + } else { tcg_gen_mov_tl(cpu_dst, cpu_src1); + } } switch (xop) { case 0x38: /* jmpl */ { - TCGv r_pc; + TCGv t; TCGv_i32 r_const; - r_pc = tcg_const_tl(dc->pc); - gen_movl_TN_reg(rd, r_pc); - tcg_temp_free(r_pc); + t = gen_dest_gpr(dc, rd); + tcg_gen_movi_tl(t, dc->pc); + gen_store_gpr(dc, rd, t); gen_mov_pc_npc(dc); r_const = tcg_const_i32(3); gen_helper_check_align(cpu_env, cpu_dst, r_const); @@ -4657,12 +4590,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x3c: /* save */ save_state(dc); gen_helper_save(cpu_env); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; case 0x3d: /* restore */ save_state(dc); gen_helper_restore(cpu_env); - gen_movl_TN_reg(rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_dst); break; #if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64) case 0x3e: /* V9 done/retry */ @@ -4702,7 +4635,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) cpu_src1 = get_src1(insn, cpu_src1); if (xop == 0x3c || xop == 0x3e) { // V9 casa/casxa rs2 = GET_FIELD(insn, 27, 31); - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src2 = gen_load_gpr(dc, rs2); tcg_gen_mov_tl(cpu_addr, cpu_src1); } else if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); @@ -4710,10 +4643,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); if (rs2 != 0) { - gen_movl_reg_TN(rs2, cpu_src2); + cpu_src2 = gen_load_gpr(dc, rs2); tcg_gen_add_tl(cpu_addr, cpu_src1, cpu_src2); - } else + } else { tcg_gen_mov_tl(cpu_addr, cpu_src1); + } } if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) || (xop > 0x17 && xop <= 0x1d ) || @@ -4746,7 +4680,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx); tcg_gen_trunc_i64_tl(cpu_tmp0, cpu_tmp64); tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffffULL); - gen_movl_TN_reg(rd + 1, cpu_tmp0); + gen_store_gpr(dc, rd + 1, cpu_tmp0); tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32); tcg_gen_trunc_i64_tl(cpu_val, cpu_tmp64); tcg_gen_andi_tl(cpu_val, cpu_val, 0xffffffffULL); @@ -4924,7 +4858,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) default: goto illegal_insn; } - gen_movl_TN_reg(rd, cpu_val); + gen_store_gpr(dc, rd, cpu_val); #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) skip_move: ; #endif @@ -5169,11 +5103,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; case 0x3c: /* V9 casa */ gen_cas_asi(cpu_val, cpu_addr, cpu_src2, insn, rd); - gen_movl_TN_reg(rd, cpu_val); + gen_store_gpr(dc, rd, cpu_val); break; case 0x3e: /* V9 casxa */ gen_casx_asi(cpu_val, cpu_addr, cpu_src2, insn, rd); - gen_movl_TN_reg(rd, cpu_val); + gen_store_gpr(dc, rd, cpu_val); break; #else case 0x34: /* stc */ From 9d1d4e342cb154a0f801eabd9758e90599893073 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:14 +1000 Subject: [PATCH 1009/2270] target-sparc: Use gen_load_gpr in get_src[12] This means we can avoid the incoming temporary, though the cleanup of the existing temporaries is not performed in this patch. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 75 ++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 46 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 0ec3d488c8..760cfd60c6 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2248,40 +2248,23 @@ static inline void gen_ldstub_asi(TCGv dst, TCGv addr, int insn) } #endif -static inline TCGv get_src1(unsigned int insn, TCGv def) +static TCGv get_src1(DisasContext *dc, unsigned int insn) { - TCGv r_rs1 = def; - unsigned int rs1; - - rs1 = GET_FIELD(insn, 13, 17); - if (rs1 == 0) { - tcg_gen_movi_tl(def, 0); - } else if (rs1 < 8) { - r_rs1 = cpu_gregs[rs1]; - } else { - tcg_gen_ld_tl(def, cpu_regwptr, (rs1 - 8) * sizeof(target_ulong)); - } - return r_rs1; + unsigned int rs1 = GET_FIELD(insn, 13, 17); + return gen_load_gpr(dc, rs1); } -static inline TCGv get_src2(unsigned int insn, TCGv def) +static TCGv get_src2(DisasContext *dc, unsigned int insn) { - TCGv r_rs2 = def; - if (IS_IMM) { /* immediate */ target_long simm = GET_FIELDs(insn, 19, 31); - tcg_gen_movi_tl(def, simm); - } else { /* register */ + TCGv t = get_temp_tl(dc); + tcg_gen_movi_tl(t, simm); + return t; + } else { /* register */ unsigned int rs2 = GET_FIELD(insn, 27, 31); - if (rs2 == 0) { - tcg_gen_movi_tl(def, 0); - } else if (rs2 < 8) { - r_rs2 = cpu_gregs[rs2]; - } else { - tcg_gen_ld_tl(def, cpu_regwptr, (rs2 - 8) * sizeof(target_ulong)); - } + return gen_load_gpr(dc, rs2); } - return r_rs2; } #ifdef TARGET_SPARC64 @@ -2560,7 +2543,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) (GET_FIELD_SP(insn, 20, 21) << 14); target = sign_extend(target, 16); target <<= 2; - cpu_src1 = get_src1(insn, cpu_src1); + cpu_src1 = get_src1(dc, insn); do_branch_reg(dc, target, insn, cpu_src1); goto jmp_insn; } @@ -3187,7 +3170,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) do { \ DisasCompare cmp; \ cond = GET_FIELD_SP(insn, 14, 17); \ - cpu_src1 = get_src1(insn, cpu_src1); \ + cpu_src1 = get_src1(dc, insn); \ gen_compare_reg(&cmp, cond, cpu_src1); \ gen_fmov##sz(dc, &cmp, rd, rs2); \ free_compare(&cmp); \ @@ -3344,7 +3327,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } } } else { - cpu_src1 = get_src1(insn, cpu_src1); + cpu_src1 = get_src1(dc, insn); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); tcg_gen_ori_tl(dst, cpu_src1, simm); @@ -3363,7 +3346,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } #ifdef TARGET_SPARC64 } else if (xop == 0x25) { /* sll, V9 sllx */ - cpu_src1 = get_src1(insn, cpu_src1); + cpu_src1 = get_src1(dc, insn); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 20, 31); if (insn & (1 << 12)) { @@ -3383,7 +3366,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } gen_store_gpr(dc, rd, cpu_dst); } else if (xop == 0x26) { /* srl, V9 srlx */ - cpu_src1 = get_src1(insn, cpu_src1); + cpu_src1 = get_src1(dc, insn); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 20, 31); if (insn & (1 << 12)) { @@ -3406,7 +3389,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } gen_store_gpr(dc, rd, cpu_dst); } else if (xop == 0x27) { /* sra, V9 srax */ - cpu_src1 = get_src1(insn, cpu_src1); + cpu_src1 = get_src1(dc, insn); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 20, 31); if (insn & (1 << 12)) { @@ -3431,8 +3414,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #endif } else if (xop < 0x36) { if (xop < 0x20) { - cpu_src1 = get_src1(insn, cpu_src1); - cpu_src2 = get_src2(insn, cpu_src2); + cpu_src1 = get_src1(dc, insn); + cpu_src2 = get_src2(dc, insn); switch (xop & ~0x10) { case 0x0: /* add */ if (xop & 0x10) { @@ -3563,8 +3546,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } gen_store_gpr(dc, rd, cpu_dst); } else { - cpu_src1 = get_src1(insn, cpu_src1); - cpu_src2 = get_src2(insn, cpu_src2); + cpu_src1 = get_src1(dc, insn); + cpu_src2 = get_src2(dc, insn); switch (xop) { case 0x20: /* taddcc */ gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2); @@ -4153,14 +4136,14 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; case 0x010: /* VIS I array8 */ CHECK_FPU_FEATURE(dc, VIS1); - cpu_src1 = get_src1(insn, cpu_src1); + cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_helper_array8(cpu_dst, cpu_src1, cpu_src2); gen_store_gpr(dc, rd, cpu_dst); break; case 0x012: /* VIS I array16 */ CHECK_FPU_FEATURE(dc, VIS1); - cpu_src1 = get_src1(insn, cpu_src1); + cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_helper_array8(cpu_dst, cpu_src1, cpu_src2); tcg_gen_shli_i64(cpu_dst, cpu_dst, 1); @@ -4168,7 +4151,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; case 0x014: /* VIS I array32 */ CHECK_FPU_FEATURE(dc, VIS1); - cpu_src1 = get_src1(insn, cpu_src1); + cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_helper_array8(cpu_dst, cpu_src1, cpu_src2); tcg_gen_shli_i64(cpu_dst, cpu_dst, 2); @@ -4176,22 +4159,22 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; case 0x018: /* VIS I alignaddr */ CHECK_FPU_FEATURE(dc, VIS1); - cpu_src1 = get_src1(insn, cpu_src1); + cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 0); gen_store_gpr(dc, rd, cpu_dst); break; case 0x01a: /* VIS I alignaddrl */ CHECK_FPU_FEATURE(dc, VIS1); - cpu_src1 = get_src1(insn, cpu_src1); + cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 1); gen_store_gpr(dc, rd, cpu_dst); break; case 0x019: /* VIS II bmask */ CHECK_FPU_FEATURE(dc, VIS2); - cpu_src1 = get_src1(insn, cpu_src1); - cpu_src2 = get_src2(insn, cpu_src2); + cpu_src1 = gen_load_gpr(dc, rs1); + cpu_src2 = gen_load_gpr(dc, rs2); tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2); tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, cpu_dst, 32, 32); gen_store_gpr(dc, rd, cpu_dst); @@ -4511,7 +4494,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) TCGv_i32 r_const; save_state(dc); - cpu_src1 = get_src1(insn, cpu_src1); + cpu_src1 = get_src1(dc, insn); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); tcg_gen_addi_tl(cpu_dst, cpu_src1, simm); @@ -4534,7 +4517,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto jmp_insn; #endif } else { - cpu_src1 = get_src1(insn, cpu_src1); + cpu_src1 = get_src1(dc, insn); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); tcg_gen_addi_tl(cpu_dst, cpu_src1, simm); @@ -4632,7 +4615,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) { unsigned int xop = GET_FIELD(insn, 7, 12); - cpu_src1 = get_src1(insn, cpu_src1); + cpu_src1 = get_src1(dc, insn); if (xop == 0x3c || xop == 0x3e) { // V9 casa/casxa rs2 = GET_FIELD(insn, 27, 31); cpu_src2 = gen_load_gpr(dc, rs2); From c7785e1682405d8ec7002918c76857aaebd812b2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:15 +1000 Subject: [PATCH 1010/2270] target-sparc: Convert asi helpers to gen_*_gpr Push the DisasContext down so that we can use gen_load/store_gpr in sode gen_ldda_asi, gen_stda_ast, gen_cas_asi, gen_casx_asi. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 61 +++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 760cfd60c6..f4ab6ccc92 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2101,7 +2101,8 @@ static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn) tcg_gen_trunc_i64_tl(dst, cpu_tmp64); } -static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd) +static inline void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr, + int insn, int rd) { TCGv_i32 r_asi, r_rd; @@ -2112,12 +2113,13 @@ static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd) tcg_temp_free_i32(r_asi); } -static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd) +static inline void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr, + int insn, int rd) { TCGv_i32 r_asi, r_size; + TCGv lo = gen_load_gpr(dc, rd + 1); - gen_movl_reg_TN(rd + 1, cpu_tmp0); - tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, hi); + tcg_gen_concat_tl_i64(cpu_tmp64, lo, hi); r_asi = gen_get_asi(insn, addr); r_size = tcg_const_i32(8); gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size); @@ -2125,28 +2127,23 @@ static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd) tcg_temp_free_i32(r_asi); } -static inline void gen_cas_asi(TCGv dst, TCGv addr, TCGv val2, int insn, - int rd) +static inline void gen_cas_asi(DisasContext *dc, TCGv dst, TCGv addr, + TCGv val2, int insn, int rd) { - TCGv r_val1; - TCGv_i32 r_asi; + TCGv r_val1 = gen_load_gpr(dc, rd); + TCGv_i32 r_asi = gen_get_asi(insn, addr); - r_val1 = tcg_temp_new(); - gen_movl_reg_TN(rd, r_val1); - r_asi = gen_get_asi(insn, addr); gen_helper_cas_asi(dst, cpu_env, addr, r_val1, val2, r_asi); tcg_temp_free_i32(r_asi); - tcg_temp_free(r_val1); } -static inline void gen_casx_asi(TCGv dst, TCGv addr, TCGv val2, int insn, - int rd) +static inline void gen_casx_asi(DisasContext *dc, TCGv dst, TCGv addr, + TCGv val2, int insn, int rd) { - TCGv_i32 r_asi; + TCGv r_val1 = gen_load_gpr(dc, rd); + TCGv_i32 r_asi = gen_get_asi(insn, addr); - gen_movl_reg_TN(rd, cpu_tmp64); - r_asi = gen_get_asi(insn, addr); - gen_helper_casx_asi(dst, cpu_env, addr, cpu_tmp64, val2, r_asi); + gen_helper_casx_asi(dst, cpu_env, addr, r_val1, val2, r_asi); tcg_temp_free_i32(r_asi); } @@ -2198,9 +2195,11 @@ static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn) tcg_gen_trunc_i64_tl(dst, cpu_tmp64); } -static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd) +static inline void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr, + int insn, int rd) { TCGv_i32 r_asi, r_size, r_sign; + TCGv t; r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26)); r_size = tcg_const_i32(8); @@ -2209,19 +2208,23 @@ static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd) tcg_temp_free(r_sign); tcg_temp_free(r_size); tcg_temp_free(r_asi); - tcg_gen_trunc_i64_tl(cpu_tmp0, cpu_tmp64); - gen_movl_TN_reg(rd + 1, cpu_tmp0); + + t = gen_dest_gpr(dc, rd + 1); + tcg_gen_trunc_i64_tl(t, cpu_tmp64); + gen_store_gpr(dc, rd + 1, t); + tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32); tcg_gen_trunc_i64_tl(hi, cpu_tmp64); - gen_movl_TN_reg(rd, hi); + gen_store_gpr(dc, rd, hi); } -static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd) +static inline void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr, + int insn, int rd) { TCGv_i32 r_asi, r_size; + TCGv lo = gen_load_gpr(dc, rd + 1); - gen_movl_reg_TN(rd + 1, cpu_tmp0); - tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, hi); + tcg_gen_concat_tl_i64(cpu_tmp64, lo, hi); r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26)); r_size = tcg_const_i32(8); gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size); @@ -4738,7 +4741,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (rd & 1) goto illegal_insn; save_state(dc); - gen_ldda_asi(cpu_val, cpu_addr, insn, rd); + gen_ldda_asi(dc, cpu_val, cpu_addr, insn, rd); goto skip_move; case 0x19: /* ldsba, load signed byte alternate */ #ifndef TARGET_SPARC64 @@ -4976,7 +4979,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto illegal_insn; else { save_state(dc); - gen_stda_asi(cpu_val, cpu_addr, insn, rd); + gen_stda_asi(dc, cpu_val, cpu_addr, insn, rd); } break; #endif @@ -5085,11 +5088,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd)); break; case 0x3c: /* V9 casa */ - gen_cas_asi(cpu_val, cpu_addr, cpu_src2, insn, rd); + gen_cas_asi(dc, cpu_val, cpu_addr, cpu_src2, insn, rd); gen_store_gpr(dc, rd, cpu_val); break; case 0x3e: /* V9 casxa */ - gen_casx_asi(cpu_val, cpu_addr, cpu_src2, insn, rd); + gen_casx_asi(dc, cpu_val, cpu_addr, cpu_src2, insn, rd); gen_store_gpr(dc, rd, cpu_val); break; #else From 06828032e3f88710b3135ff55ecf1c0308027900 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:16 +1000 Subject: [PATCH 1011/2270] target-sparc: Convert swap to gen_load/store_gpr Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index f4ab6ccc92..8a2e91439f 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2086,7 +2086,7 @@ static inline void gen_stf_asi(TCGv addr, int insn, int size, int rd) tcg_temp_free_i32(r_asi); } -static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn) +static inline void gen_swap_asi(TCGv dst, TCGv src, TCGv addr, int insn) { TCGv_i32 r_asi, r_size, r_sign; @@ -2095,7 +2095,7 @@ static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn) r_sign = tcg_const_i32(0); gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign); tcg_temp_free_i32(r_sign); - gen_helper_st_asi(cpu_env, addr, dst, r_asi, r_size); + gen_helper_st_asi(cpu_env, addr, src, r_asi, r_size); tcg_temp_free_i32(r_size); tcg_temp_free_i32(r_asi); tcg_gen_trunc_i64_tl(dst, cpu_tmp64); @@ -2176,7 +2176,7 @@ static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size) tcg_temp_free(r_asi); } -static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn) +static inline void gen_swap_asi(TCGv dst, TCGv src, TCGv addr, int insn) { TCGv_i32 r_asi, r_size, r_sign; TCGv_i64 r_val; @@ -2187,7 +2187,7 @@ static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn) gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign); tcg_temp_free(r_sign); r_val = tcg_temp_new_i64(); - tcg_gen_extu_tl_i64(r_val, dst); + tcg_gen_extu_tl_i64(r_val, src); gen_helper_st_asi(cpu_env, addr, r_val, r_asi, r_size); tcg_temp_free_i64(r_val); tcg_temp_free(r_size); @@ -4694,10 +4694,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x0f: /* swap, swap register with memory. Also atomically */ CHECK_IU_FEATURE(dc, SWAP); - gen_movl_reg_TN(rd, cpu_val); + cpu_src1 = gen_load_gpr(dc, rd); gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx); - tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx); + tcg_gen_qemu_st32(cpu_src1, cpu_addr, dc->mem_idx); tcg_gen_mov_tl(cpu_val, cpu_tmp0); break; #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) @@ -4783,8 +4783,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto priv_insn; #endif save_state(dc); - gen_movl_reg_TN(rd, cpu_val); - gen_swap_asi(cpu_val, cpu_addr, insn); + cpu_src1 = gen_load_gpr(dc, rd); + gen_swap_asi(cpu_val, cpu_src1, cpu_addr, insn); break; #ifndef TARGET_SPARC64 From 81634eea3d5dada203848f89ebd97d6a05aa4cce Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:17 +1000 Subject: [PATCH 1012/2270] target-sparc: Finish conversion to gen_load_gpr All users of gen_movl_{reg_TN,TN_reg} are removed. At the same time, make cpu_val a local variable for load/store disassembly. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 58 ++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 38 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 8a2e91439f..3c9b0e3412 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -48,7 +48,7 @@ static TCGv cpu_y; #ifndef CONFIG_USER_ONLY static TCGv cpu_tbr; #endif -static TCGv cpu_cond, cpu_dst, cpu_addr, cpu_val; +static TCGv cpu_cond, cpu_dst, cpu_addr; #ifdef TARGET_SPARC64 static TCGv_i32 cpu_xcc, cpu_asi, cpu_fprs; static TCGv cpu_gsr; @@ -308,28 +308,6 @@ static inline TCGv gen_dest_gpr(DisasContext *dc, int reg) } } -static inline void gen_movl_reg_TN(int reg, TCGv tn) -{ - if (reg == 0) - tcg_gen_movi_tl(tn, 0); - else if (reg < 8) - tcg_gen_mov_tl(tn, cpu_gregs[reg]); - else { - tcg_gen_ld_tl(tn, cpu_regwptr, (reg - 8) * sizeof(target_ulong)); - } -} - -static inline void gen_movl_TN_reg(int reg, TCGv tn) -{ - if (reg == 0) - return; - else if (reg < 8) - tcg_gen_mov_tl(cpu_gregs[reg], tn); - else { - tcg_gen_st_tl(tn, cpu_regwptr, (reg - 8) * sizeof(target_ulong)); - } -} - static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong pc, target_ulong npc) { @@ -2127,24 +2105,28 @@ static inline void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr, tcg_temp_free_i32(r_asi); } -static inline void gen_cas_asi(DisasContext *dc, TCGv dst, TCGv addr, +static inline void gen_cas_asi(DisasContext *dc, TCGv addr, TCGv val2, int insn, int rd) { - TCGv r_val1 = gen_load_gpr(dc, rd); + TCGv val1 = gen_load_gpr(dc, rd); + TCGv dst = gen_dest_gpr(dc, rd); TCGv_i32 r_asi = gen_get_asi(insn, addr); - gen_helper_cas_asi(dst, cpu_env, addr, r_val1, val2, r_asi); + gen_helper_cas_asi(dst, cpu_env, addr, val1, val2, r_asi); tcg_temp_free_i32(r_asi); + gen_store_gpr(dc, rd, dst); } -static inline void gen_casx_asi(DisasContext *dc, TCGv dst, TCGv addr, +static inline void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv val2, int insn, int rd) { - TCGv r_val1 = gen_load_gpr(dc, rd); + TCGv val1 = gen_load_gpr(dc, rd); + TCGv dst = gen_dest_gpr(dc, rd); TCGv_i32 r_asi = gen_get_asi(insn, addr); - gen_helper_casx_asi(dst, cpu_env, addr, r_val1, val2, r_asi); + gen_helper_casx_asi(dst, cpu_env, addr, val1, val2, r_asi); tcg_temp_free_i32(r_asi); + gen_store_gpr(dc, rd, dst); } #elif !defined(CONFIG_USER_ONLY) @@ -4638,6 +4620,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) || (xop > 0x17 && xop <= 0x1d ) || (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) { + TCGv cpu_val = gen_dest_gpr(dc, rd); + switch (xop) { case 0x0: /* ld, V9 lduw, load unsigned word */ gen_address_mask(dc, cpu_addr); @@ -4903,7 +4887,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) || xop == 0xe || xop == 0x1e) { - gen_movl_reg_TN(rd, cpu_val); + TCGv cpu_val = gen_load_gpr(dc, rd); + switch (xop) { case 0x4: /* st, store word */ gen_address_mask(dc, cpu_addr); @@ -4922,6 +4907,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto illegal_insn; else { TCGv_i32 r_const; + TCGv lo; save_state(dc); gen_address_mask(dc, cpu_addr); @@ -4929,8 +4915,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) /* XXX remove alignment check */ gen_helper_check_align(cpu_env, cpu_addr, r_const); tcg_temp_free_i32(r_const); - gen_movl_reg_TN(rd + 1, cpu_tmp0); - tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, cpu_val); + lo = gen_load_gpr(dc, rd + 1); + tcg_gen_concat_tl_i64(cpu_tmp64, lo, cpu_val); tcg_gen_qemu_st64(cpu_tmp64, cpu_addr, dc->mem_idx); } break; @@ -5088,12 +5074,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd)); break; case 0x3c: /* V9 casa */ - gen_cas_asi(dc, cpu_val, cpu_addr, cpu_src2, insn, rd); - gen_store_gpr(dc, rd, cpu_val); + gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd); break; case 0x3e: /* V9 casxa */ - gen_casx_asi(dc, cpu_val, cpu_addr, cpu_src2, insn, rd); - gen_store_gpr(dc, rd, cpu_val); + gen_casx_asi(dc, cpu_addr, cpu_src2, insn, rd); break; #else case 0x34: /* stc */ @@ -5269,14 +5253,12 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, cpu_tmp32 = tcg_temp_new_i32(); cpu_tmp64 = tcg_temp_new_i64(); cpu_dst = tcg_temp_new(); - cpu_val = tcg_temp_new(); cpu_addr = tcg_temp_new(); disas_sparc_insn(dc, insn); num_insns++; tcg_temp_free(cpu_addr); - tcg_temp_free(cpu_val); tcg_temp_free(cpu_dst); tcg_temp_free_i64(cpu_tmp64); tcg_temp_free_i32(cpu_tmp32); From a4273524875a960e8ef22ed676853e5988fefbea Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:18 +1000 Subject: [PATCH 1013/2270] target-sparc: Cleanup cpu_src[12] allocation Now that get_temp_tl is used for get_src[12], we don't need to pre-allocate these temporaries. Fallout from this is moving some assignments around cas/casx to avoid uninitialized variable warnings. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 3c9b0e3412..2a95c1fdeb 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2483,7 +2483,7 @@ static void gen_faligndata(TCGv dst, TCGv gsr, TCGv s1, TCGv s2) static void disas_sparc_insn(DisasContext * dc, unsigned int insn) { unsigned int opc, rs1, rs2, rd; - TCGv cpu_src1, cpu_src2, cpu_tmp1, cpu_tmp2; + TCGv cpu_src1, cpu_src2; TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32; TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64; target_long simm; @@ -2496,9 +2496,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) rd = GET_FIELD(insn, 2, 6); - cpu_tmp1 = cpu_src1 = tcg_temp_new(); - cpu_tmp2 = cpu_src2 = tcg_temp_new(); - switch (opc) { case 0: /* branches/sethi */ { @@ -4602,8 +4599,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) cpu_src1 = get_src1(dc, insn); if (xop == 0x3c || xop == 0x3e) { // V9 casa/casxa - rs2 = GET_FIELD(insn, 27, 31); - cpu_src2 = gen_load_gpr(dc, rs2); tcg_gen_mov_tl(cpu_addr, cpu_src1); } else if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); @@ -5074,9 +5069,13 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd)); break; case 0x3c: /* V9 casa */ + rs2 = GET_FIELD(insn, 27, 31); + cpu_src2 = gen_load_gpr(dc, rs2); gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd); break; case 0x3e: /* V9 casxa */ + rs2 = GET_FIELD(insn, 27, 31); + cpu_src2 = gen_load_gpr(dc, rs2); gen_casx_asi(dc, cpu_addr, cpu_src2, insn, rd); break; #else @@ -5089,8 +5088,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) default: goto illegal_insn; } - } else + } else { goto illegal_insn; + } } break; } @@ -5169,8 +5169,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto egress; #endif egress: - tcg_temp_free(cpu_tmp1); - tcg_temp_free(cpu_tmp2); if (dc->n_t32 != 0) { int i; for (i = dc->n_t32 - 1; i >= 0; --i) { From 5e6ed43923830b09989a9a2fa2255dadadee67f2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:19 +1000 Subject: [PATCH 1014/2270] target-sparc: Make the cpu_addr variable local to load/store handling Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 2a95c1fdeb..e3e4256f1e 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -48,7 +48,7 @@ static TCGv cpu_y; #ifndef CONFIG_USER_ONLY static TCGv cpu_tbr; #endif -static TCGv cpu_cond, cpu_dst, cpu_addr; +static TCGv cpu_cond, cpu_dst; #ifdef TARGET_SPARC64 static TCGv_i32 cpu_xcc, cpu_asi, cpu_fprs; static TCGv cpu_gsr; @@ -4596,20 +4596,22 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 3: /* load/store instructions */ { unsigned int xop = GET_FIELD(insn, 7, 12); + /* ??? gen_address_mask prevents us from using a source + register directly. Always generate a temporary. */ + TCGv cpu_addr = get_temp_tl(dc); - cpu_src1 = get_src1(dc, insn); - if (xop == 0x3c || xop == 0x3e) { // V9 casa/casxa - tcg_gen_mov_tl(cpu_addr, cpu_src1); + tcg_gen_mov_tl(cpu_addr, get_src1(dc, insn)); + if (xop == 0x3c || xop == 0x3e) { + /* V9 casa/casxa : no offset */ } else if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); - tcg_gen_addi_tl(cpu_addr, cpu_src1, simm); + if (simm != 0) { + tcg_gen_addi_tl(cpu_addr, cpu_addr, simm); + } } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); if (rs2 != 0) { - cpu_src2 = gen_load_gpr(dc, rs2); - tcg_gen_add_tl(cpu_addr, cpu_src1, cpu_src2); - } else { - tcg_gen_mov_tl(cpu_addr, cpu_src1); + tcg_gen_add_tl(cpu_addr, cpu_addr, gen_load_gpr(dc, rs2)); } } if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) || @@ -5251,12 +5253,10 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, cpu_tmp32 = tcg_temp_new_i32(); cpu_tmp64 = tcg_temp_new_i64(); cpu_dst = tcg_temp_new(); - cpu_addr = tcg_temp_new(); disas_sparc_insn(dc, insn); num_insns++; - tcg_temp_free(cpu_addr); tcg_temp_free(cpu_dst); tcg_temp_free_i64(cpu_tmp64); tcg_temp_free_i32(cpu_tmp32); From 2ae23e178263ecb7faebd37d9706f36a5cba9791 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:20 +1000 Subject: [PATCH 1015/2270] target-sparc: Split out get_temp_i32 Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index e3e4256f1e..5296a37240 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -125,6 +125,22 @@ static int sign_extend(int x, int len) #define IS_IMM (insn & (1<<13)) +static inline TCGv_i32 get_temp_i32(DisasContext *dc) +{ + TCGv_i32 t; + assert(dc->n_t32 < ARRAY_SIZE(dc->t32)); + dc->t32[dc->n_t32++] = t = tcg_temp_new_i32(); + return t; +} + +static inline TCGv get_temp_tl(DisasContext *dc) +{ + TCGv t; + assert(dc->n_ttl < ARRAY_SIZE(dc->ttl)); + dc->ttl[dc->n_ttl++] = t = tcg_temp_new(); + return t; +} + static inline void gen_update_fprs_dirty(int rd) { #if defined(TARGET_SPARC64) @@ -145,16 +161,13 @@ static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src) if (src & 1) { return MAKE_TCGV_I32(GET_TCGV_I64(cpu_fpr[src / 2])); } else { - TCGv_i32 ret = tcg_temp_new_i32(); + TCGv_i32 ret = get_temp_i32(dc); TCGv_i64 t = tcg_temp_new_i64(); tcg_gen_shri_i64(t, cpu_fpr[src / 2], 32); tcg_gen_trunc_i64_i32(ret, t); tcg_temp_free_i64(t); - dc->t32[dc->n_t32++] = ret; - assert(dc->n_t32 <= ARRAY_SIZE(dc->t32)); - return ret; } #endif @@ -265,14 +278,6 @@ static inline void gen_address_mask(DisasContext *dc, TCGv addr) #endif } -static inline TCGv get_temp_tl(DisasContext *dc) -{ - TCGv t; - assert(dc->n_ttl < ARRAY_SIZE(dc->ttl)); - dc->ttl[dc->n_ttl++] = t = tcg_temp_new(); - return t; -} - static inline TCGv gen_load_gpr(DisasContext *dc, int reg) { if (reg == 0 || reg >= 8) { From ba5f5179f2c27c7e9891e404f526d3463e3f4a15 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:21 +1000 Subject: [PATCH 1016/2270] target-sparc: Use get_temp_i32 in gen_dest_fpr_F Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 5296a37240..5013aeeed2 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -189,9 +189,9 @@ static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v) gen_update_fprs_dirty(dst); } -static TCGv_i32 gen_dest_fpr_F(void) +static TCGv_i32 gen_dest_fpr_F(DisasContext *dc) { - return cpu_tmp32; + return get_temp_i32(dc); } static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src) @@ -1703,7 +1703,7 @@ static inline void gen_fop_FF(DisasContext *dc, int rd, int rs, TCGv_i32 dst, src; src = gen_load_fpr_F(dc, rs); - dst = gen_dest_fpr_F(); + dst = gen_dest_fpr_F(dc); gen(dst, cpu_env, src); @@ -1716,7 +1716,7 @@ static inline void gen_ne_fop_FF(DisasContext *dc, int rd, int rs, TCGv_i32 dst, src; src = gen_load_fpr_F(dc, rs); - dst = gen_dest_fpr_F(); + dst = gen_dest_fpr_F(dc); gen(dst, src); @@ -1730,7 +1730,7 @@ static inline void gen_fop_FFF(DisasContext *dc, int rd, int rs1, int rs2, src1 = gen_load_fpr_F(dc, rs1); src2 = gen_load_fpr_F(dc, rs2); - dst = gen_dest_fpr_F(); + dst = gen_dest_fpr_F(dc); gen(dst, cpu_env, src1, src2); @@ -1745,7 +1745,7 @@ static inline void gen_ne_fop_FFF(DisasContext *dc, int rd, int rs1, int rs2, src1 = gen_load_fpr_F(dc, rs1); src2 = gen_load_fpr_F(dc, rs2); - dst = gen_dest_fpr_F(); + dst = gen_dest_fpr_F(dc); gen(dst, src1, src2); @@ -1942,7 +1942,7 @@ static inline void gen_fop_FD(DisasContext *dc, int rd, int rs, TCGv_i64 src; src = gen_load_fpr_D(dc, rs); - dst = gen_dest_fpr_F(); + dst = gen_dest_fpr_F(dc); gen(dst, cpu_env, src); @@ -1955,7 +1955,7 @@ static inline void gen_fop_FQ(DisasContext *dc, int rd, int rs, TCGv_i32 dst; gen_op_load_fpr_QT1(QFPREG(rs)); - dst = gen_dest_fpr_F(); + dst = gen_dest_fpr_F(dc); gen(dst, cpu_env); @@ -2277,7 +2277,7 @@ static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs) s1 = gen_load_fpr_F(dc, rs); s2 = gen_load_fpr_F(dc, rd); - dst = gen_dest_fpr_F(); + dst = gen_dest_fpr_F(dc); zero = tcg_const_i32(0); tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2); @@ -4257,14 +4257,14 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x03b: /* VIS I fpack16 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs2); - cpu_dst_32 = gen_dest_fpr_F(); + cpu_dst_32 = gen_dest_fpr_F(dc); gen_helper_fpack16(cpu_dst_32, cpu_gsr, cpu_src1_64); gen_store_fpr_F(dc, rd, cpu_dst_32); break; case 0x03d: /* VIS I fpackfix */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs2); - cpu_dst_32 = gen_dest_fpr_F(); + cpu_dst_32 = gen_dest_fpr_F(dc); gen_helper_fpackfix(cpu_dst_32, cpu_gsr, cpu_src1_64); gen_store_fpr_F(dc, rd, cpu_dst_32); break; @@ -4328,7 +4328,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; case 0x061: /* VIS I fzeros */ CHECK_FPU_FEATURE(dc, VIS1); - cpu_dst_32 = gen_dest_fpr_F(); + cpu_dst_32 = gen_dest_fpr_F(dc); tcg_gen_movi_i32(cpu_dst_32, 0); gen_store_fpr_F(dc, rd, cpu_dst_32); break; @@ -4456,7 +4456,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; case 0x07f: /* VIS I fones */ CHECK_FPU_FEATURE(dc, VIS1); - cpu_dst_32 = gen_dest_fpr_F(); + cpu_dst_32 = gen_dest_fpr_F(dc); tcg_gen_movi_i32(cpu_dst_32, -1); gen_store_fpr_F(dc, rd, cpu_dst_32); break; @@ -4843,7 +4843,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x20: /* ldf, load fpreg */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx); - cpu_dst_32 = gen_dest_fpr_F(); + cpu_dst_32 = gen_dest_fpr_F(dc); tcg_gen_trunc_tl_i32(cpu_dst_32, cpu_tmp0); gen_store_fpr_F(dc, rd, cpu_dst_32); break; From 45778f99f0fb088af1f92d9a92759b760dceef2a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:22 +1000 Subject: [PATCH 1017/2270] target-sparc: Avoid cpu_tmp32 in Read Priv Register We don't need another temporary here. Load directly into the register we want to set. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 53 ++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 5013aeeed2..43e44d55de 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2865,14 +2865,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; case 3: // tt { - TCGv_ptr r_tsptr; + TCGv_ptr r_tsptr = tcg_temp_new_ptr(); - r_tsptr = tcg_temp_new_ptr(); gen_load_trap_state_at_tl(r_tsptr, cpu_env); - tcg_gen_ld_i32(cpu_tmp32, r_tsptr, - offsetof(trap_state, tt)); + tcg_gen_ld32s_tl(cpu_tmp0, r_tsptr, + offsetof(trap_state, tt)); tcg_temp_free_ptr(r_tsptr); - tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32); } break; case 4: // tick @@ -2890,53 +2888,44 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_mov_tl(cpu_tmp0, cpu_tbr); break; case 6: // pstate - tcg_gen_ld_i32(cpu_tmp32, cpu_env, - offsetof(CPUSPARCState, pstate)); - tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32); + tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, + offsetof(CPUSPARCState, pstate)); break; case 7: // tl - tcg_gen_ld_i32(cpu_tmp32, cpu_env, - offsetof(CPUSPARCState, tl)); - tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32); + tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, + offsetof(CPUSPARCState, tl)); break; case 8: // pil - tcg_gen_ld_i32(cpu_tmp32, cpu_env, - offsetof(CPUSPARCState, psrpil)); - tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32); + tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, + offsetof(CPUSPARCState, psrpil)); break; case 9: // cwp gen_helper_rdcwp(cpu_tmp0, cpu_env); break; case 10: // cansave - tcg_gen_ld_i32(cpu_tmp32, cpu_env, - offsetof(CPUSPARCState, cansave)); - tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32); + tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, + offsetof(CPUSPARCState, cansave)); break; case 11: // canrestore - tcg_gen_ld_i32(cpu_tmp32, cpu_env, - offsetof(CPUSPARCState, canrestore)); - tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32); + tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, + offsetof(CPUSPARCState, canrestore)); break; case 12: // cleanwin - tcg_gen_ld_i32(cpu_tmp32, cpu_env, - offsetof(CPUSPARCState, cleanwin)); - tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32); + tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, + offsetof(CPUSPARCState, cleanwin)); break; case 13: // otherwin - tcg_gen_ld_i32(cpu_tmp32, cpu_env, - offsetof(CPUSPARCState, otherwin)); - tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32); + tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, + offsetof(CPUSPARCState, otherwin)); break; case 14: // wstate - tcg_gen_ld_i32(cpu_tmp32, cpu_env, - offsetof(CPUSPARCState, wstate)); - tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32); + tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, + offsetof(CPUSPARCState, wstate)); break; case 16: // UA2005 gl CHECK_IU_FEATURE(dc, GL); - tcg_gen_ld_i32(cpu_tmp32, cpu_env, - offsetof(CPUSPARCState, gl)); - tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32); + tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, + offsetof(CPUSPARCState, gl)); break; case 26: // UA2005 strand status CHECK_IU_FEATURE(dc, HYPV); From 7b9e066b67c1f8839a1ca63efebcbaf48cc60104 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:23 +1000 Subject: [PATCH 1018/2270] target-sparc: Avoid cpu_tmp32 in Write Priv Register No need to copy to a temporary to store 32 bits. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 56 +++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 43e44d55de..353ebc60a4 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -3801,9 +3801,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) r_tsptr = tcg_temp_new_ptr(); gen_load_trap_state_at_tl(r_tsptr, cpu_env); - tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0); - tcg_gen_st_i32(cpu_tmp32, r_tsptr, - offsetof(trap_state, tt)); + tcg_gen_st32_tl(cpu_tmp0, r_tsptr, + offsetof(trap_state, tt)); tcg_temp_free_ptr(r_tsptr); } break; @@ -3829,8 +3828,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; case 7: // tl save_state(dc); - tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0); - tcg_gen_st_i32(cpu_tmp32, cpu_env, + tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, tl)); dc->npc = DYNAMIC_PC; break; @@ -3841,40 +3839,34 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_helper_wrcwp(cpu_env, cpu_tmp0); break; case 10: // cansave - tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0); - tcg_gen_st_i32(cpu_tmp32, cpu_env, - offsetof(CPUSPARCState, - cansave)); + tcg_gen_st32_tl(cpu_tmp0, cpu_env, + offsetof(CPUSPARCState, + cansave)); break; case 11: // canrestore - tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0); - tcg_gen_st_i32(cpu_tmp32, cpu_env, - offsetof(CPUSPARCState, - canrestore)); + tcg_gen_st32_tl(cpu_tmp0, cpu_env, + offsetof(CPUSPARCState, + canrestore)); break; case 12: // cleanwin - tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0); - tcg_gen_st_i32(cpu_tmp32, cpu_env, - offsetof(CPUSPARCState, - cleanwin)); + tcg_gen_st32_tl(cpu_tmp0, cpu_env, + offsetof(CPUSPARCState, + cleanwin)); break; case 13: // otherwin - tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0); - tcg_gen_st_i32(cpu_tmp32, cpu_env, - offsetof(CPUSPARCState, - otherwin)); + tcg_gen_st32_tl(cpu_tmp0, cpu_env, + offsetof(CPUSPARCState, + otherwin)); break; case 14: // wstate - tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0); - tcg_gen_st_i32(cpu_tmp32, cpu_env, - offsetof(CPUSPARCState, - wstate)); + tcg_gen_st32_tl(cpu_tmp0, cpu_env, + offsetof(CPUSPARCState, + wstate)); break; case 16: // UA2005 gl CHECK_IU_FEATURE(dc, GL); - tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0); - tcg_gen_st_i32(cpu_tmp32, cpu_env, - offsetof(CPUSPARCState, gl)); + tcg_gen_st32_tl(cpu_tmp0, cpu_env, + offsetof(CPUSPARCState, gl)); break; case 26: // UA2005 strand status CHECK_IU_FEATURE(dc, HYPV); @@ -3886,11 +3878,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto illegal_insn; } #else - tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0); - if (dc->def->nwindows != 32) - tcg_gen_andi_tl(cpu_tmp32, cpu_tmp32, + tcg_gen_trunc_tl_i32(cpu_wim, cpu_tmp0); + if (dc->def->nwindows != 32) { + tcg_gen_andi_tl(cpu_wim, cpu_wim, (1 << dc->def->nwindows) - 1); - tcg_gen_mov_i32(cpu_wim, cpu_tmp32); + } #endif } break; From f8641947c2268eab6e73f16883c08ae14432280c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:24 +1000 Subject: [PATCH 1019/2270] target-sparc: Tidy ldfsr, stfsr Remove the last uses of cpu_tmp32. Unify the code between sparc64 and sparc32 by using the proper "tl" functions. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 353ebc60a4..ed341b896f 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -60,7 +60,6 @@ static TCGv cpu_wim; #endif /* local register indexes (only used inside old micro ops) */ static TCGv cpu_tmp0; -static TCGv_i32 cpu_tmp32; static TCGv_i64 cpu_tmp64; /* Floating point registers */ static TCGv_i64 cpu_fpr[TARGET_DPREGS]; @@ -4834,17 +4833,15 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (rd == 1) { tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx); gen_helper_ldxfsr(cpu_env, cpu_tmp64); - } else { - tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx); - tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0); - gen_helper_ldfsr(cpu_env, cpu_tmp32); - } -#else - { - tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx); - gen_helper_ldfsr(cpu_env, cpu_tmp32); + break; } #endif + { + TCGv_i32 t32 = get_temp_i32(dc); + tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx); + tcg_gen_trunc_tl_i32(t32, cpu_tmp0); + gen_helper_ldfsr(cpu_env, t32); + } break; case 0x22: /* ldqf, load quad fpreg */ { @@ -4979,17 +4976,19 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_qemu_st32(cpu_tmp0, cpu_addr, dc->mem_idx); break; case 0x25: /* stfsr, V9 stxfsr */ + { + TCGv t = get_temp_tl(dc); + + tcg_gen_ld_tl(t, cpu_env, offsetof(CPUSPARCState, fsr)); #ifdef TARGET_SPARC64 - gen_address_mask(dc, cpu_addr); - tcg_gen_ld_i64(cpu_tmp64, cpu_env, offsetof(CPUSPARCState, fsr)); - if (rd == 1) - tcg_gen_qemu_st64(cpu_tmp64, cpu_addr, dc->mem_idx); - else - tcg_gen_qemu_st32(cpu_tmp64, cpu_addr, dc->mem_idx); -#else - tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fsr)); - tcg_gen_qemu_st32(cpu_tmp32, cpu_addr, dc->mem_idx); + gen_address_mask(dc, cpu_addr); + if (rd == 1) { + tcg_gen_qemu_st64(t, cpu_addr, dc->mem_idx); + break; + } #endif + tcg_gen_qemu_st32(t, cpu_addr, dc->mem_idx); + } break; case 0x26: #ifdef TARGET_SPARC64 @@ -5236,7 +5235,6 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, insn = cpu_ldl_code(env, dc->pc); cpu_tmp0 = tcg_temp_new(); - cpu_tmp32 = tcg_temp_new_i32(); cpu_tmp64 = tcg_temp_new_i64(); cpu_dst = tcg_temp_new(); @@ -5245,7 +5243,6 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, tcg_temp_free(cpu_dst); tcg_temp_free_i64(cpu_tmp64); - tcg_temp_free_i32(cpu_tmp32); tcg_temp_free(cpu_tmp0); if (dc->is_br) From 1ec789ab68a9eabb5de8b1ba732d60a8fcb00446 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:25 +1000 Subject: [PATCH 1020/2270] target-sparc: Remove usage of cpu_tmp64 from most helper functions Use a locally allocated temporary instead. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 73 ++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 29 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index ed341b896f..9b7bbef1ae 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2071,16 +2071,18 @@ static inline void gen_stf_asi(TCGv addr, int insn, int size, int rd) static inline void gen_swap_asi(TCGv dst, TCGv src, TCGv addr, int insn) { TCGv_i32 r_asi, r_size, r_sign; + TCGv_i64 t64 = tcg_temp_new_i64(); r_asi = gen_get_asi(insn, addr); r_size = tcg_const_i32(4); r_sign = tcg_const_i32(0); - gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign); + gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign); tcg_temp_free_i32(r_sign); gen_helper_st_asi(cpu_env, addr, src, r_asi, r_size); tcg_temp_free_i32(r_size); tcg_temp_free_i32(r_asi); - tcg_gen_trunc_i64_tl(dst, cpu_tmp64); + tcg_gen_trunc_i64_tl(dst, t64); + tcg_temp_free_i64(t64); } static inline void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr, @@ -2100,13 +2102,15 @@ static inline void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr, { TCGv_i32 r_asi, r_size; TCGv lo = gen_load_gpr(dc, rd + 1); + TCGv_i64 t64 = tcg_temp_new_i64(); - tcg_gen_concat_tl_i64(cpu_tmp64, lo, hi); + tcg_gen_concat_tl_i64(t64, lo, hi); r_asi = gen_get_asi(insn, addr); r_size = tcg_const_i32(8); - gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size); + gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size); tcg_temp_free_i32(r_size); tcg_temp_free_i32(r_asi); + tcg_temp_free_i64(t64); } static inline void gen_cas_asi(DisasContext *dc, TCGv addr, @@ -2139,46 +2143,52 @@ static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size, int sign) { TCGv_i32 r_asi, r_size, r_sign; + TCGv_i64 t64 = tcg_temp_new_i64(); r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26)); r_size = tcg_const_i32(size); r_sign = tcg_const_i32(sign); - gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign); - tcg_temp_free(r_sign); - tcg_temp_free(r_size); - tcg_temp_free(r_asi); - tcg_gen_trunc_i64_tl(dst, cpu_tmp64); + gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign); + tcg_temp_free_i32(r_sign); + tcg_temp_free_i32(r_size); + tcg_temp_free_i32(r_asi); + tcg_gen_trunc_i64_tl(dst, t64); + tcg_temp_free_i64(t64); } static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size) { TCGv_i32 r_asi, r_size; + TCGv_i64 t64 = tcg_temp_new_i64(); - tcg_gen_extu_tl_i64(cpu_tmp64, src); + tcg_gen_extu_tl_i64(t64, src); r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26)); r_size = tcg_const_i32(size); - gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size); - tcg_temp_free(r_size); - tcg_temp_free(r_asi); + gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size); + tcg_temp_free_i32(r_size); + tcg_temp_free_i32(r_asi); + tcg_temp_free_i64(t64); } static inline void gen_swap_asi(TCGv dst, TCGv src, TCGv addr, int insn) { TCGv_i32 r_asi, r_size, r_sign; - TCGv_i64 r_val; + TCGv_i64 r_val, t64; r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26)); r_size = tcg_const_i32(4); r_sign = tcg_const_i32(0); - gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign); + t64 = tcg_temp_new_i64(); + gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign); tcg_temp_free(r_sign); r_val = tcg_temp_new_i64(); tcg_gen_extu_tl_i64(r_val, src); gen_helper_st_asi(cpu_env, addr, r_val, r_asi, r_size); tcg_temp_free_i64(r_val); - tcg_temp_free(r_size); - tcg_temp_free(r_asi); - tcg_gen_trunc_i64_tl(dst, cpu_tmp64); + tcg_temp_free_i32(r_size); + tcg_temp_free_i32(r_asi); + tcg_gen_trunc_i64_tl(dst, t64); + tcg_temp_free_i64(t64); } static inline void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr, @@ -2186,21 +2196,24 @@ static inline void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr, { TCGv_i32 r_asi, r_size, r_sign; TCGv t; + TCGv_i64 t64; r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26)); r_size = tcg_const_i32(8); r_sign = tcg_const_i32(0); - gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign); - tcg_temp_free(r_sign); - tcg_temp_free(r_size); - tcg_temp_free(r_asi); + t64 = tcg_temp_new_i64(); + gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign); + tcg_temp_free_i32(r_sign); + tcg_temp_free_i32(r_size); + tcg_temp_free_i32(r_asi); t = gen_dest_gpr(dc, rd + 1); - tcg_gen_trunc_i64_tl(t, cpu_tmp64); + tcg_gen_trunc_i64_tl(t, t64); gen_store_gpr(dc, rd + 1, t); - tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32); - tcg_gen_trunc_i64_tl(hi, cpu_tmp64); + tcg_gen_shri_i64(t64, t64, 32); + tcg_gen_trunc_i64_tl(hi, t64); + tcg_temp_free_i64(t64); gen_store_gpr(dc, rd, hi); } @@ -2209,13 +2222,15 @@ static inline void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr, { TCGv_i32 r_asi, r_size; TCGv lo = gen_load_gpr(dc, rd + 1); + TCGv_i64 t64 = tcg_temp_new_i64(); - tcg_gen_concat_tl_i64(cpu_tmp64, lo, hi); + tcg_gen_concat_tl_i64(t64, lo, hi); r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26)); r_size = tcg_const_i32(8); - gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size); - tcg_temp_free(r_size); - tcg_temp_free(r_asi); + gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size); + tcg_temp_free_i32(r_size); + tcg_temp_free_i32(r_asi); + tcg_temp_free_i64(t64); } #endif From 3886b8a32029a88111140dfe81f6ef02d6b85e23 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:26 +1000 Subject: [PATCH 1021/2270] target-sparc: Don't use a temporary for gen_dest_fpr_D In all cases we don't have write-before-read problems. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 9b7bbef1ae..00ceb9debe 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -206,9 +206,9 @@ static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v) gen_update_fprs_dirty(dst); } -static TCGv_i64 gen_dest_fpr_D(void) +static TCGv_i64 gen_dest_fpr_D(DisasContext *dc, unsigned int dst) { - return cpu_tmp64; + return cpu_fpr[DFPREG(dst) / 2]; } static void gen_op_load_fpr_QT0(unsigned int src) @@ -1758,7 +1758,7 @@ static inline void gen_fop_DD(DisasContext *dc, int rd, int rs, TCGv_i64 dst, src; src = gen_load_fpr_D(dc, rs); - dst = gen_dest_fpr_D(); + dst = gen_dest_fpr_D(dc, rd); gen(dst, cpu_env, src); @@ -1772,7 +1772,7 @@ static inline void gen_ne_fop_DD(DisasContext *dc, int rd, int rs, TCGv_i64 dst, src; src = gen_load_fpr_D(dc, rs); - dst = gen_dest_fpr_D(); + dst = gen_dest_fpr_D(dc, rd); gen(dst, src); @@ -1787,7 +1787,7 @@ static inline void gen_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2, src1 = gen_load_fpr_D(dc, rs1); src2 = gen_load_fpr_D(dc, rs2); - dst = gen_dest_fpr_D(); + dst = gen_dest_fpr_D(dc, rd); gen(dst, cpu_env, src1, src2); @@ -1802,7 +1802,7 @@ static inline void gen_ne_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2, src1 = gen_load_fpr_D(dc, rs1); src2 = gen_load_fpr_D(dc, rs2); - dst = gen_dest_fpr_D(); + dst = gen_dest_fpr_D(dc, rd); gen(dst, src1, src2); @@ -1816,7 +1816,7 @@ static inline void gen_gsr_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2, src1 = gen_load_fpr_D(dc, rs1); src2 = gen_load_fpr_D(dc, rs2); - dst = gen_dest_fpr_D(); + dst = gen_dest_fpr_D(dc, rd); gen(dst, cpu_gsr, src1, src2); @@ -1831,7 +1831,7 @@ static inline void gen_ne_fop_DDDD(DisasContext *dc, int rd, int rs1, int rs2, src1 = gen_load_fpr_D(dc, rs1); src2 = gen_load_fpr_D(dc, rs2); src0 = gen_load_fpr_D(dc, rd); - dst = gen_dest_fpr_D(); + dst = gen_dest_fpr_D(dc, rd); gen(dst, src0, src1, src2); @@ -1883,7 +1883,7 @@ static inline void gen_fop_DFF(DisasContext *dc, int rd, int rs1, int rs2, src1 = gen_load_fpr_F(dc, rs1); src2 = gen_load_fpr_F(dc, rs2); - dst = gen_dest_fpr_D(); + dst = gen_dest_fpr_D(dc, rd); gen(dst, cpu_env, src1, src2); @@ -1912,7 +1912,7 @@ static inline void gen_fop_DF(DisasContext *dc, int rd, int rs, TCGv_i32 src; src = gen_load_fpr_F(dc, rs); - dst = gen_dest_fpr_D(); + dst = gen_dest_fpr_D(dc, rd); gen(dst, cpu_env, src); @@ -1927,7 +1927,7 @@ static inline void gen_ne_fop_DF(DisasContext *dc, int rd, int rs, TCGv_i32 src; src = gen_load_fpr_F(dc, rs); - dst = gen_dest_fpr_D(); + dst = gen_dest_fpr_D(dc, rd); gen(dst, cpu_env, src); @@ -1967,7 +1967,7 @@ static inline void gen_fop_DQ(DisasContext *dc, int rd, int rs, TCGv_i64 dst; gen_op_load_fpr_QT1(QFPREG(rs)); - dst = gen_dest_fpr_D(); + dst = gen_dest_fpr_D(dc, rd); gen(dst, cpu_env); @@ -2303,7 +2303,7 @@ static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs) static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs) { - TCGv_i64 dst = gen_dest_fpr_D(); + TCGv_i64 dst = gen_dest_fpr_D(dc, rd); tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, cmp->c2, gen_load_fpr_D(dc, rs), gen_load_fpr_D(dc, rd)); @@ -4317,7 +4317,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; case 0x060: /* VIS I fzero */ CHECK_FPU_FEATURE(dc, VIS1); - cpu_dst_64 = gen_dest_fpr_D(); + cpu_dst_64 = gen_dest_fpr_D(dc, rd); tcg_gen_movi_i64(cpu_dst_64, 0); gen_store_fpr_D(dc, rd, cpu_dst_64); break; @@ -4445,7 +4445,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; case 0x07e: /* VIS I fone */ CHECK_FPU_FEATURE(dc, VIS1); - cpu_dst_64 = gen_dest_fpr_D(); + cpu_dst_64 = gen_dest_fpr_D(dc, rd); tcg_gen_movi_i64(cpu_dst_64, -1); gen_store_fpr_D(dc, rd, cpu_dst_64); break; @@ -4873,7 +4873,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; case 0x23: /* lddf, load double fpreg */ gen_address_mask(dc, cpu_addr); - cpu_dst_64 = gen_dest_fpr_D(); + cpu_dst_64 = gen_dest_fpr_D(dc, rd); tcg_gen_qemu_ld64(cpu_dst_64, cpu_addr, dc->mem_idx); gen_store_fpr_D(dc, rd, cpu_dst_64); break; From aeff993cc59ea043c8d33e3dc3584c61aa31f347 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:27 +1000 Subject: [PATCH 1022/2270] target-sparc: Remove cpu_tmp64 use from softint insns The use of "tl" functions and a tmp64 is logically incompatible. Use cpu_tmp0 instead. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 00ceb9debe..64feaa326d 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -3655,20 +3655,20 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x14: /* Softint set */ if (!supervisor(dc)) goto illegal_insn; - tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2); - gen_helper_set_softint(cpu_env, cpu_tmp64); + tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); + gen_helper_set_softint(cpu_env, cpu_tmp0); break; case 0x15: /* Softint clear */ if (!supervisor(dc)) goto illegal_insn; - tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2); - gen_helper_clear_softint(cpu_env, cpu_tmp64); + tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); + gen_helper_clear_softint(cpu_env, cpu_tmp0); break; case 0x16: /* Softint write */ if (!supervisor(dc)) goto illegal_insn; - tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2); - gen_helper_write_softint(cpu_env, cpu_tmp64); + tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); + gen_helper_write_softint(cpu_env, cpu_tmp0); break; case 0x17: /* Tick compare */ #if !defined(CONFIG_USER_ONLY) From abcc71919c65747af7615c8770754c0ea071a2d2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:28 +1000 Subject: [PATCH 1023/2270] target-sparc: Remove last uses of cpu_tmp64 Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 64feaa326d..16cf8de9ce 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -60,7 +60,6 @@ static TCGv cpu_wim; #endif /* local register indexes (only used inside old micro ops) */ static TCGv cpu_tmp0; -static TCGv_i64 cpu_tmp64; /* Floating point registers */ static TCGv_i64 cpu_fpr[TARGET_DPREGS]; @@ -4637,6 +4636,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto illegal_insn; else { TCGv_i32 r_const; + TCGv_i64 t64; save_state(dc); r_const = tcg_const_i32(7); @@ -4644,12 +4644,14 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_helper_check_align(cpu_env, cpu_addr, r_const); tcg_temp_free_i32(r_const); gen_address_mask(dc, cpu_addr); - tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx); - tcg_gen_trunc_i64_tl(cpu_tmp0, cpu_tmp64); + t64 = tcg_temp_new_i64(); + tcg_gen_qemu_ld64(t64, cpu_addr, dc->mem_idx); + tcg_gen_trunc_i64_tl(cpu_tmp0, t64); tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffffULL); gen_store_gpr(dc, rd + 1, cpu_tmp0); - tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32); - tcg_gen_trunc_i64_tl(cpu_val, cpu_tmp64); + tcg_gen_shri_i64(t64, t64, 32); + tcg_gen_trunc_i64_tl(cpu_val, t64); + tcg_temp_free_i64(t64); tcg_gen_andi_tl(cpu_val, cpu_val, 0xffffffffULL); } break; @@ -4846,8 +4848,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #ifdef TARGET_SPARC64 gen_address_mask(dc, cpu_addr); if (rd == 1) { - tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx); - gen_helper_ldxfsr(cpu_env, cpu_tmp64); + TCGv_i64 t64 = tcg_temp_new_i64(); + tcg_gen_qemu_ld64(t64, cpu_addr, dc->mem_idx); + gen_helper_ldxfsr(cpu_env, t64); + tcg_temp_free_i64(t64); break; } #endif @@ -4902,6 +4906,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto illegal_insn; else { TCGv_i32 r_const; + TCGv_i64 t64; TCGv lo; save_state(dc); @@ -4911,8 +4916,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_helper_check_align(cpu_env, cpu_addr, r_const); tcg_temp_free_i32(r_const); lo = gen_load_gpr(dc, rd + 1); - tcg_gen_concat_tl_i64(cpu_tmp64, lo, cpu_val); - tcg_gen_qemu_st64(cpu_tmp64, cpu_addr, dc->mem_idx); + + t64 = tcg_temp_new_i64(); + tcg_gen_concat_tl_i64(t64, lo, cpu_val); + tcg_gen_qemu_st64(t64, cpu_addr, dc->mem_idx); + tcg_temp_free_i64(t64); } break; #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) @@ -5250,14 +5258,12 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, insn = cpu_ldl_code(env, dc->pc); cpu_tmp0 = tcg_temp_new(); - cpu_tmp64 = tcg_temp_new_i64(); cpu_dst = tcg_temp_new(); disas_sparc_insn(dc, insn); num_insns++; tcg_temp_free(cpu_dst); - tcg_temp_free_i64(cpu_tmp64); tcg_temp_free(cpu_tmp0); if (dc->is_br) From 7b04bd5ccabf61d5ad8a616ecbe2282c4e2656c4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:29 +1000 Subject: [PATCH 1024/2270] target-sparc: Only use cpu_dst for eventual writes to a gpr Use cpu_tmp0 for other stuff, like Write Priv Register. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 52 ++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 16cf8de9ce..5b7e82b1f7 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -3620,19 +3620,19 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; #else case 0x2: /* V9 wrccr */ - tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2); - gen_helper_wrccr(cpu_env, cpu_dst); + tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); + gen_helper_wrccr(cpu_env, cpu_tmp0); tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS); dc->cc_op = CC_OP_FLAGS; break; case 0x3: /* V9 wrasi */ - tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2); - tcg_gen_andi_tl(cpu_dst, cpu_dst, 0xff); - tcg_gen_trunc_tl_i32(cpu_asi, cpu_dst); + tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); + tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xff); + tcg_gen_trunc_tl_i32(cpu_asi, cpu_tmp0); break; case 0x6: /* V9 wrfprs */ - tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2); - tcg_gen_trunc_tl_i32(cpu_fprs, cpu_dst); + tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); + tcg_gen_trunc_tl_i32(cpu_fprs, cpu_tmp0); save_state(dc); gen_op_next_insn(); tcg_gen_exit_tb(0); @@ -3695,13 +3695,13 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) { TCGv_ptr r_tickptr; - tcg_gen_xor_tl(cpu_dst, cpu_src1, + tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); r_tickptr = tcg_temp_new_ptr(); tcg_gen_ld_ptr(r_tickptr, cpu_env, offsetof(CPUSPARCState, stick)); gen_helper_tick_set_count(r_tickptr, - cpu_dst); + cpu_tmp0); tcg_temp_free_ptr(r_tickptr); } break; @@ -3756,8 +3756,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto illegal_insn; } #else - tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2); - gen_helper_wrpsr(cpu_env, cpu_dst); + tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); + gen_helper_wrpsr(cpu_env, cpu_tmp0); tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS); dc->cc_op = CC_OP_FLAGS; save_state(dc); @@ -4478,22 +4478,22 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) cpu_src1 = get_src1(dc, insn); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); - tcg_gen_addi_tl(cpu_dst, cpu_src1, simm); + tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm); } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); if (rs2) { cpu_src2 = gen_load_gpr(dc, rs2); - tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2); + tcg_gen_add_tl(cpu_tmp0, cpu_src1, cpu_src2); } else { - tcg_gen_mov_tl(cpu_dst, cpu_src1); + tcg_gen_mov_tl(cpu_tmp0, cpu_src1); } } gen_helper_restore(cpu_env); gen_mov_pc_npc(dc); r_const = tcg_const_i32(3); - gen_helper_check_align(cpu_env, cpu_dst, r_const); + gen_helper_check_align(cpu_env, cpu_tmp0, r_const); tcg_temp_free_i32(r_const); - tcg_gen_mov_tl(cpu_npc, cpu_dst); + tcg_gen_mov_tl(cpu_npc, cpu_tmp0); dc->npc = DYNAMIC_PC; goto jmp_insn; #endif @@ -4501,14 +4501,14 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) cpu_src1 = get_src1(dc, insn); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); - tcg_gen_addi_tl(cpu_dst, cpu_src1, simm); + tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm); } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); if (rs2) { cpu_src2 = gen_load_gpr(dc, rs2); - tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2); + tcg_gen_add_tl(cpu_tmp0, cpu_src1, cpu_src2); } else { - tcg_gen_mov_tl(cpu_dst, cpu_src1); + tcg_gen_mov_tl(cpu_tmp0, cpu_src1); } } switch (xop) { @@ -4522,10 +4522,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_store_gpr(dc, rd, t); gen_mov_pc_npc(dc); r_const = tcg_const_i32(3); - gen_helper_check_align(cpu_env, cpu_dst, r_const); + gen_helper_check_align(cpu_env, cpu_tmp0, r_const); tcg_temp_free_i32(r_const); - gen_address_mask(dc, cpu_dst); - tcg_gen_mov_tl(cpu_npc, cpu_dst); + gen_address_mask(dc, cpu_tmp0); + tcg_gen_mov_tl(cpu_npc, cpu_tmp0); dc->npc = DYNAMIC_PC; } goto jmp_insn; @@ -4538,9 +4538,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto priv_insn; gen_mov_pc_npc(dc); r_const = tcg_const_i32(3); - gen_helper_check_align(cpu_env, cpu_dst, r_const); + gen_helper_check_align(cpu_env, cpu_tmp0, r_const); tcg_temp_free_i32(r_const); - tcg_gen_mov_tl(cpu_npc, cpu_dst); + tcg_gen_mov_tl(cpu_npc, cpu_tmp0); dc->npc = DYNAMIC_PC; gen_helper_rett(cpu_env); } @@ -4554,12 +4554,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x3c: /* save */ save_state(dc); gen_helper_save(cpu_env); - gen_store_gpr(dc, rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_tmp0); break; case 0x3d: /* restore */ save_state(dc); gen_helper_restore(cpu_env); - gen_store_gpr(dc, rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_tmp0); break; #if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64) case 0x3e: /* V9 done/retry */ From 5793f2a47e201d251856c7956d6f7907ec0d9f1f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:30 +1000 Subject: [PATCH 1025/2270] target-sparc: Make cpu_dst local to OP=2 insns And initialize it such that it (may) write directly to rd. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 5b7e82b1f7..8559cc3507 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -48,7 +48,7 @@ static TCGv cpu_y; #ifndef CONFIG_USER_ONLY static TCGv cpu_tbr; #endif -static TCGv cpu_cond, cpu_dst; +static TCGv cpu_cond; #ifdef TARGET_SPARC64 static TCGv_i32 cpu_xcc, cpu_asi, cpu_fprs; static TCGv cpu_gsr; @@ -2511,7 +2511,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } opc = GET_FIELD(insn, 0, 1); - rd = GET_FIELD(insn, 2, 6); switch (opc) { @@ -2620,6 +2619,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 2: /* FPU & Logical Operations */ { unsigned int xop = GET_FIELD(insn, 7, 12); + TCGv cpu_dst = gen_dest_gpr(dc, rd); + if (xop == 0x3a) { /* generate trap */ int cond = GET_FIELD(insn, 3, 6); TCGv_i32 trap; @@ -5258,12 +5259,10 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, insn = cpu_ldl_code(env, dc->pc); cpu_tmp0 = tcg_temp_new(); - cpu_dst = tcg_temp_new(); disas_sparc_insn(dc, insn); num_insns++; - tcg_temp_free(cpu_dst); tcg_temp_free(cpu_tmp0); if (dc->is_br) From de9e9d9f17a36ff76c1a02a5348835e5e0a081b0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Oct 2012 19:32:31 +1000 Subject: [PATCH 1026/2270] target-sparc: Remove cpu_tmp0 as a global Subroutines do their own local temporary management. Within disas_sparc_insn we limit the existance of the variable to OP=2 insns, and delay initialization as late as is reasonable for the specific XOP. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- target-sparc/translate.c | 203 +++++++++++++++++++++++---------------- 1 file changed, 118 insertions(+), 85 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 8559cc3507..5df287629e 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -58,8 +58,6 @@ static TCGv_i32 cpu_softint; #else static TCGv cpu_wim; #endif -/* local register indexes (only used inside old micro ops) */ -static TCGv cpu_tmp0; /* Floating point registers */ static TCGv_i64 cpu_fpr[TARGET_DPREGS]; @@ -608,9 +606,10 @@ static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1, static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2) { - TCGv r_temp, zero; + TCGv r_temp, zero, t0; r_temp = tcg_temp_new(); + t0 = tcg_temp_new(); /* old op: if (!(env->y & 1)) @@ -628,22 +627,23 @@ static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2) // env->y = (b2 << 31) | (env->y >> 1); tcg_gen_andi_tl(r_temp, cpu_cc_src, 0x1); tcg_gen_shli_tl(r_temp, r_temp, 31); - tcg_gen_shri_tl(cpu_tmp0, cpu_y, 1); - tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0x7fffffff); - tcg_gen_or_tl(cpu_tmp0, cpu_tmp0, r_temp); - tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff); + tcg_gen_shri_tl(t0, cpu_y, 1); + tcg_gen_andi_tl(t0, t0, 0x7fffffff); + tcg_gen_or_tl(t0, t0, r_temp); + tcg_gen_andi_tl(cpu_y, t0, 0xffffffff); // b1 = N ^ V; - gen_mov_reg_N(cpu_tmp0, cpu_psr); + gen_mov_reg_N(t0, cpu_psr); gen_mov_reg_V(r_temp, cpu_psr); - tcg_gen_xor_tl(cpu_tmp0, cpu_tmp0, r_temp); + tcg_gen_xor_tl(t0, t0, r_temp); tcg_temp_free(r_temp); // T0 = (b1 << 31) | (T0 >> 1); // src1 = T0; - tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, 31); + tcg_gen_shli_tl(t0, t0, 31); tcg_gen_shri_tl(cpu_cc_src, cpu_cc_src, 1); - tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_tmp0); + tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t0); + tcg_temp_free(t0); tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2); @@ -675,9 +675,9 @@ static inline void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext) tcg_gen_mul_i64(r_temp2, r_temp, r_temp2); tcg_gen_shri_i64(r_temp, r_temp2, 32); - tcg_gen_trunc_i64_tl(cpu_tmp0, r_temp); + tcg_gen_trunc_i64_tl(cpu_y, r_temp); tcg_temp_free_i64(r_temp); - tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff); + tcg_gen_andi_tl(cpu_y, cpu_y, 0xffffffff); tcg_gen_trunc_i64_tl(dst, r_temp2); @@ -714,27 +714,33 @@ static inline void gen_op_eval_be(TCGv dst, TCGv_i32 src) // Z | (N ^ V) static inline void gen_op_eval_ble(TCGv dst, TCGv_i32 src) { - gen_mov_reg_N(cpu_tmp0, src); + TCGv t0 = tcg_temp_new(); + gen_mov_reg_N(t0, src); gen_mov_reg_V(dst, src); - tcg_gen_xor_tl(dst, dst, cpu_tmp0); - gen_mov_reg_Z(cpu_tmp0, src); - tcg_gen_or_tl(dst, dst, cpu_tmp0); + tcg_gen_xor_tl(dst, dst, t0); + gen_mov_reg_Z(t0, src); + tcg_gen_or_tl(dst, dst, t0); + tcg_temp_free(t0); } // N ^ V static inline void gen_op_eval_bl(TCGv dst, TCGv_i32 src) { - gen_mov_reg_V(cpu_tmp0, src); + TCGv t0 = tcg_temp_new(); + gen_mov_reg_V(t0, src); gen_mov_reg_N(dst, src); - tcg_gen_xor_tl(dst, dst, cpu_tmp0); + tcg_gen_xor_tl(dst, dst, t0); + tcg_temp_free(t0); } // C | Z static inline void gen_op_eval_bleu(TCGv dst, TCGv_i32 src) { - gen_mov_reg_Z(cpu_tmp0, src); + TCGv t0 = tcg_temp_new(); + gen_mov_reg_Z(t0, src); gen_mov_reg_C(dst, src); - tcg_gen_or_tl(dst, dst, cpu_tmp0); + tcg_gen_or_tl(dst, dst, t0); + tcg_temp_free(t0); } // C @@ -771,29 +777,21 @@ static inline void gen_op_eval_bne(TCGv dst, TCGv_i32 src) // !(Z | (N ^ V)) static inline void gen_op_eval_bg(TCGv dst, TCGv_i32 src) { - gen_mov_reg_N(cpu_tmp0, src); - gen_mov_reg_V(dst, src); - tcg_gen_xor_tl(dst, dst, cpu_tmp0); - gen_mov_reg_Z(cpu_tmp0, src); - tcg_gen_or_tl(dst, dst, cpu_tmp0); + gen_op_eval_ble(dst, src); tcg_gen_xori_tl(dst, dst, 0x1); } // !(N ^ V) static inline void gen_op_eval_bge(TCGv dst, TCGv_i32 src) { - gen_mov_reg_V(cpu_tmp0, src); - gen_mov_reg_N(dst, src); - tcg_gen_xor_tl(dst, dst, cpu_tmp0); + gen_op_eval_bl(dst, src); tcg_gen_xori_tl(dst, dst, 0x1); } // !(C | Z) static inline void gen_op_eval_bgu(TCGv dst, TCGv_i32 src) { - gen_mov_reg_Z(cpu_tmp0, src); - gen_mov_reg_C(dst, src); - tcg_gen_or_tl(dst, dst, cpu_tmp0); + gen_op_eval_bleu(dst, src); tcg_gen_xori_tl(dst, dst, 0x1); } @@ -843,18 +841,22 @@ static inline void gen_mov_reg_FCC1(TCGv reg, TCGv src, static inline void gen_op_eval_fbne(TCGv dst, TCGv src, unsigned int fcc_offset) { + TCGv t0 = tcg_temp_new(); gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset); - tcg_gen_or_tl(dst, dst, cpu_tmp0); + gen_mov_reg_FCC1(t0, src, fcc_offset); + tcg_gen_or_tl(dst, dst, t0); + tcg_temp_free(t0); } // 1 or 2: FCC0 ^ FCC1 static inline void gen_op_eval_fblg(TCGv dst, TCGv src, unsigned int fcc_offset) { + TCGv t0 = tcg_temp_new(); gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset); - tcg_gen_xor_tl(dst, dst, cpu_tmp0); + gen_mov_reg_FCC1(t0, src, fcc_offset); + tcg_gen_xor_tl(dst, dst, t0); + tcg_temp_free(t0); } // 1 or 3: FCC0 @@ -868,10 +870,11 @@ static inline void gen_op_eval_fbul(TCGv dst, TCGv src, static inline void gen_op_eval_fbl(TCGv dst, TCGv src, unsigned int fcc_offset) { + TCGv t0 = tcg_temp_new(); gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset); - tcg_gen_xori_tl(cpu_tmp0, cpu_tmp0, 0x1); - tcg_gen_and_tl(dst, dst, cpu_tmp0); + gen_mov_reg_FCC1(t0, src, fcc_offset); + tcg_gen_andc_tl(dst, dst, t0); + tcg_temp_free(t0); } // 2 or 3: FCC1 @@ -885,39 +888,46 @@ static inline void gen_op_eval_fbug(TCGv dst, TCGv src, static inline void gen_op_eval_fbg(TCGv dst, TCGv src, unsigned int fcc_offset) { + TCGv t0 = tcg_temp_new(); gen_mov_reg_FCC0(dst, src, fcc_offset); - tcg_gen_xori_tl(dst, dst, 0x1); - gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset); - tcg_gen_and_tl(dst, dst, cpu_tmp0); + gen_mov_reg_FCC1(t0, src, fcc_offset); + tcg_gen_andc_tl(dst, t0, dst); + tcg_temp_free(t0); } // 3: FCC0 & FCC1 static inline void gen_op_eval_fbu(TCGv dst, TCGv src, unsigned int fcc_offset) { + TCGv t0 = tcg_temp_new(); gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset); - tcg_gen_and_tl(dst, dst, cpu_tmp0); + gen_mov_reg_FCC1(t0, src, fcc_offset); + tcg_gen_and_tl(dst, dst, t0); + tcg_temp_free(t0); } // 0: !(FCC0 | FCC1) static inline void gen_op_eval_fbe(TCGv dst, TCGv src, unsigned int fcc_offset) { + TCGv t0 = tcg_temp_new(); gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset); - tcg_gen_or_tl(dst, dst, cpu_tmp0); + gen_mov_reg_FCC1(t0, src, fcc_offset); + tcg_gen_or_tl(dst, dst, t0); tcg_gen_xori_tl(dst, dst, 0x1); + tcg_temp_free(t0); } // 0 or 3: !(FCC0 ^ FCC1) static inline void gen_op_eval_fbue(TCGv dst, TCGv src, unsigned int fcc_offset) { + TCGv t0 = tcg_temp_new(); gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset); - tcg_gen_xor_tl(dst, dst, cpu_tmp0); + gen_mov_reg_FCC1(t0, src, fcc_offset); + tcg_gen_xor_tl(dst, dst, t0); tcg_gen_xori_tl(dst, dst, 0x1); + tcg_temp_free(t0); } // 0 or 2: !FCC0 @@ -932,11 +942,12 @@ static inline void gen_op_eval_fbge(TCGv dst, TCGv src, static inline void gen_op_eval_fbuge(TCGv dst, TCGv src, unsigned int fcc_offset) { + TCGv t0 = tcg_temp_new(); gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset); - tcg_gen_xori_tl(cpu_tmp0, cpu_tmp0, 0x1); - tcg_gen_and_tl(dst, dst, cpu_tmp0); + gen_mov_reg_FCC1(t0, src, fcc_offset); + tcg_gen_andc_tl(dst, dst, t0); tcg_gen_xori_tl(dst, dst, 0x1); + tcg_temp_free(t0); } // 0 or 1: !FCC1 @@ -951,21 +962,24 @@ static inline void gen_op_eval_fble(TCGv dst, TCGv src, static inline void gen_op_eval_fbule(TCGv dst, TCGv src, unsigned int fcc_offset) { + TCGv t0 = tcg_temp_new(); gen_mov_reg_FCC0(dst, src, fcc_offset); + gen_mov_reg_FCC1(t0, src, fcc_offset); + tcg_gen_andc_tl(dst, t0, dst); tcg_gen_xori_tl(dst, dst, 0x1); - gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset); - tcg_gen_and_tl(dst, dst, cpu_tmp0); - tcg_gen_xori_tl(dst, dst, 0x1); + tcg_temp_free(t0); } // !3: !(FCC0 & FCC1) static inline void gen_op_eval_fbo(TCGv dst, TCGv src, unsigned int fcc_offset) { + TCGv t0 = tcg_temp_new(); gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(cpu_tmp0, src, fcc_offset); - tcg_gen_and_tl(dst, dst, cpu_tmp0); + gen_mov_reg_FCC1(t0, src, fcc_offset); + tcg_gen_and_tl(dst, dst, t0); tcg_gen_xori_tl(dst, dst, 0x1); + tcg_temp_free(t0); } static inline void gen_branch2(DisasContext *dc, target_ulong pc1, @@ -2620,6 +2634,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) { unsigned int xop = GET_FIELD(insn, 7, 12); TCGv cpu_dst = gen_dest_gpr(dc, rd); + TCGv cpu_tmp0; if (xop == 0x3a) { /* generate trap */ int cond = GET_FIELD(insn, 3, 6); @@ -2839,8 +2854,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_store_gpr(dc, rd, cpu_dst); break; } else if (xop == 0x2a) { /* rdwim / V9 rdpr */ - if (!supervisor(dc)) + if (!supervisor(dc)) { goto priv_insn; + } + cpu_tmp0 = get_temp_tl(dc); #ifdef TARGET_SPARC64 rs1 = GET_FIELD(insn, 13, 17); switch (rs1) { @@ -3347,6 +3364,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); cpu_src2 = gen_load_gpr(dc, rs2); + cpu_tmp0 = get_temp_tl(dc); if (insn & (1 << 12)) { tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f); } else { @@ -3368,6 +3386,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); cpu_src2 = gen_load_gpr(dc, rs2); + cpu_tmp0 = get_temp_tl(dc); if (insn & (1 << 12)) { tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f); tcg_gen_shr_i64(cpu_dst, cpu_src1, cpu_tmp0); @@ -3391,6 +3410,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); cpu_src2 = gen_load_gpr(dc, rs2); + cpu_tmp0 = get_temp_tl(dc); if (insn & (1 << 12)) { tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f); tcg_gen_sar_i64(cpu_dst, cpu_src1, cpu_tmp0); @@ -3576,6 +3596,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) simm = GET_FIELDs(insn, 20, 31); tcg_gen_shli_tl(cpu_dst, cpu_src1, simm & 0x1f); } else { /* register */ + cpu_tmp0 = get_temp_tl(dc); tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f); tcg_gen_shl_tl(cpu_dst, cpu_src1, cpu_tmp0); } @@ -3586,6 +3607,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) simm = GET_FIELDs(insn, 20, 31); tcg_gen_shri_tl(cpu_dst, cpu_src1, simm & 0x1f); } else { /* register */ + cpu_tmp0 = get_temp_tl(dc); tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f); tcg_gen_shr_tl(cpu_dst, cpu_src1, cpu_tmp0); } @@ -3596,6 +3618,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) simm = GET_FIELDs(insn, 20, 31); tcg_gen_sari_tl(cpu_dst, cpu_src1, simm & 0x1f); } else { /* register */ + cpu_tmp0 = get_temp_tl(dc); tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f); tcg_gen_sar_tl(cpu_dst, cpu_src1, cpu_tmp0); } @@ -3604,6 +3627,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #endif case 0x30: { + cpu_tmp0 = get_temp_tl(dc); switch(rd) { case 0: /* wry */ tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); @@ -3757,6 +3781,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) goto illegal_insn; } #else + cpu_tmp0 = get_temp_tl(dc); tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); gen_helper_wrpsr(cpu_env, cpu_tmp0); tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS); @@ -3772,6 +3797,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) { if (!supervisor(dc)) goto priv_insn; + cpu_tmp0 = get_temp_tl(dc); tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); #ifdef TARGET_SPARC64 switch (rd) { @@ -3910,6 +3936,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) CHECK_IU_FEATURE(dc, HYPV); if (!hypervisor(dc)) goto priv_insn; + cpu_tmp0 = get_temp_tl(dc); tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); switch (rd) { case 0: // hpstate @@ -4477,6 +4504,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) save_state(dc); cpu_src1 = get_src1(dc, insn); + cpu_tmp0 = get_temp_tl(dc); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm); @@ -4500,6 +4528,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #endif } else { cpu_src1 = get_src1(dc, insn); + cpu_tmp0 = get_temp_tl(dc); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm); @@ -4647,13 +4676,13 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_address_mask(dc, cpu_addr); t64 = tcg_temp_new_i64(); tcg_gen_qemu_ld64(t64, cpu_addr, dc->mem_idx); - tcg_gen_trunc_i64_tl(cpu_tmp0, t64); - tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffffULL); - gen_store_gpr(dc, rd + 1, cpu_tmp0); + tcg_gen_trunc_i64_tl(cpu_val, t64); + tcg_gen_ext32u_tl(cpu_val, cpu_val); + gen_store_gpr(dc, rd + 1, cpu_val); tcg_gen_shri_i64(t64, t64, 32); tcg_gen_trunc_i64_tl(cpu_val, t64); tcg_temp_free_i64(t64); - tcg_gen_andi_tl(cpu_val, cpu_val, 0xffffffffULL); + tcg_gen_ext32u_tl(cpu_val, cpu_val); } break; case 0x9: /* ldsb, load signed byte */ @@ -4675,14 +4704,17 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_temp_free(r_const); } break; - case 0x0f: /* swap, swap register with memory. Also - atomically */ - CHECK_IU_FEATURE(dc, SWAP); - cpu_src1 = gen_load_gpr(dc, rd); - gen_address_mask(dc, cpu_addr); - tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx); - tcg_gen_qemu_st32(cpu_src1, cpu_addr, dc->mem_idx); - tcg_gen_mov_tl(cpu_val, cpu_tmp0); + case 0x0f: + /* swap, swap register with memory. Also atomically */ + { + TCGv t0 = get_temp_tl(dc); + CHECK_IU_FEATURE(dc, SWAP); + cpu_src1 = gen_load_gpr(dc, rd); + gen_address_mask(dc, cpu_addr); + tcg_gen_qemu_ld32u(t0, cpu_addr, dc->mem_idx); + tcg_gen_qemu_st32(cpu_src1, cpu_addr, dc->mem_idx); + tcg_gen_mov_tl(cpu_val, t0); + } break; #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) case 0x10: /* lda, V9 lduwa, load word alternate */ @@ -4833,6 +4865,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) skip_move: ; #endif } else if (xop >= 0x20 && xop < 0x24) { + TCGv t0; + if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } @@ -4840,9 +4874,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) switch (xop) { case 0x20: /* ldf, load fpreg */ gen_address_mask(dc, cpu_addr); - tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx); + t0 = get_temp_tl(dc); + tcg_gen_qemu_ld32u(t0, cpu_addr, dc->mem_idx); cpu_dst_32 = gen_dest_fpr_F(dc); - tcg_gen_trunc_tl_i32(cpu_dst_32, cpu_tmp0); + tcg_gen_trunc_tl_i32(cpu_dst_32, t0); gen_store_fpr_F(dc, rd, cpu_dst_32); break; case 0x21: /* ldfsr, V9 ldxfsr */ @@ -4856,12 +4891,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; } #endif - { - TCGv_i32 t32 = get_temp_i32(dc); - tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx); - tcg_gen_trunc_tl_i32(t32, cpu_tmp0); - gen_helper_ldfsr(cpu_env, t32); - } + cpu_dst_32 = get_temp_i32(dc); + t0 = get_temp_tl(dc); + tcg_gen_qemu_ld32u(t0, cpu_addr, dc->mem_idx); + tcg_gen_trunc_tl_i32(cpu_dst_32, t0); + gen_helper_ldfsr(cpu_env, cpu_dst_32); break; case 0x22: /* ldqf, load quad fpreg */ { @@ -4994,10 +5028,13 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) save_state(dc); switch (xop) { case 0x24: /* stf, store fpreg */ - gen_address_mask(dc, cpu_addr); - cpu_src1_32 = gen_load_fpr_F(dc, rd); - tcg_gen_ext_i32_tl(cpu_tmp0, cpu_src1_32); - tcg_gen_qemu_st32(cpu_tmp0, cpu_addr, dc->mem_idx); + { + TCGv t = get_temp_tl(dc); + gen_address_mask(dc, cpu_addr); + cpu_src1_32 = gen_load_fpr_F(dc, rd); + tcg_gen_ext_i32_tl(t, cpu_src1_32); + tcg_gen_qemu_st32(t, cpu_addr, dc->mem_idx); + } break; case 0x25: /* stfsr, V9 stxfsr */ { @@ -5258,13 +5295,9 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, last_pc = dc->pc; insn = cpu_ldl_code(env, dc->pc); - cpu_tmp0 = tcg_temp_new(); - disas_sparc_insn(dc, insn); num_insns++; - tcg_temp_free(cpu_tmp0); - if (dc->is_br) break; /* if the next PC is different, we abort now */ From e54eba1986f6c4bac2951e7f90a849cd842e25e4 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Oct 2012 14:11:35 +0100 Subject: [PATCH 1027/2270] qemu-log: Add new log category for guest bugs Add a new category for device models to log guest behaviour which is likely to be a guest bug of some kind (accessing nonexistent registers, reading 32 bit wide registers with a byte access, etc). Making this its own log category allows those who care (mostly guest OS authors) to see the complaints without bothering most users. Signed-off-by: Peter Maydell Signed-off-by: Blue Swirl --- qemu-log.c | 3 +++ qemu-log.h | 1 + 2 files changed, 4 insertions(+) diff --git a/qemu-log.c b/qemu-log.c index 396aafdf62..a4c3d1f2e3 100644 --- a/qemu-log.c +++ b/qemu-log.c @@ -116,6 +116,9 @@ const CPULogItem cpu_log_items[] = { "show all i/o ports accesses" }, { LOG_UNIMP, "unimp", "log unimplemented functionality" }, + { LOG_GUEST_ERROR, "guest_errors", + "log when the guest OS does something invalid (eg accessing a\n" + "non-existent register)" }, { 0, NULL, NULL }, }; diff --git a/qemu-log.h b/qemu-log.h index 5ccecf30af..ce6bb095b3 100644 --- a/qemu-log.h +++ b/qemu-log.h @@ -35,6 +35,7 @@ static inline bool qemu_log_enabled(void) #define CPU_LOG_TB_CPU (1 << 8) #define CPU_LOG_RESET (1 << 9) #define LOG_UNIMP (1 << 10) +#define LOG_GUEST_ERROR (1 << 11) /* Returns true if a bit is set in the current loglevel mask */ From 051c02b6c9c8ab5527f8775808625f9de8346006 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Oct 2012 14:11:36 +0100 Subject: [PATCH 1028/2270] hw/hw.h: Add include of qemu-log.h Add an include of qemu-log.h to hw.h, so that device model code has access to these logging functions without the need to directly include qemu-log.h. Signed-off-by: Peter Maydell Signed-off-by: Blue Swirl --- hw/hw.h | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/hw.h b/hw/hw.h index 16101de3ce..b337ee3042 100644 --- a/hw/hw.h +++ b/hw/hw.h @@ -12,6 +12,7 @@ #include "irq.h" #include "qemu-file.h" #include "vmstate.h" +#include "qemu-log.h" #ifdef NEED_CPU_H #if TARGET_LONG_BITS == 64 From 9351d70829c6ef2b6e27b4ca89aaca2eab4780ed Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Oct 2012 14:11:37 +0100 Subject: [PATCH 1029/2270] hw/pl181: Use LOG_UNIMP and LOG_GUEST_ERROR Rather than a mix of direct printing to stderr and aborting via hw_error(), use LOG_UNIMP and LOG_GUEST_ERROR. Signed-off-by: Peter Maydell Signed-off-by: Blue Swirl --- hw/pl181.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/hw/pl181.c b/hw/pl181.c index 7d91fbba1d..5a734735f0 100644 --- a/hw/pl181.c +++ b/hw/pl181.c @@ -352,7 +352,7 @@ static uint64_t pl181_read(void *opaque, target_phys_addr_t offset, case 0xa0: case 0xa4: case 0xa8: case 0xac: case 0xb0: case 0xb4: case 0xb8: case 0xbc: if (s->fifo_len == 0) { - fprintf(stderr, "pl181: Unexpected FIFO read\n"); + qemu_log_mask(LOG_GUEST_ERROR, "pl181: Unexpected FIFO read\n"); return 0; } else { uint32_t value; @@ -363,7 +363,8 @@ static uint64_t pl181_read(void *opaque, target_phys_addr_t offset, return value; } default: - hw_error("pl181_read: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl181_read: Bad offset %x\n", (int)offset); return 0; } } @@ -387,11 +388,11 @@ static void pl181_write(void *opaque, target_phys_addr_t offset, s->cmd = value; if (s->cmd & PL181_CMD_ENABLE) { if (s->cmd & PL181_CMD_INTERRUPT) { - fprintf(stderr, "pl181: Interrupt mode not implemented\n"); - abort(); + qemu_log_mask(LOG_UNIMP, + "pl181: Interrupt mode not implemented\n"); } if (s->cmd & PL181_CMD_PENDING) { - fprintf(stderr, "pl181: Pending commands not implemented\n"); - abort(); + qemu_log_mask(LOG_UNIMP, + "pl181: Pending commands not implemented\n"); } else { pl181_send_command(s); pl181_fifo_run(s); @@ -427,14 +428,15 @@ static void pl181_write(void *opaque, target_phys_addr_t offset, case 0xa0: case 0xa4: case 0xa8: case 0xac: case 0xb0: case 0xb4: case 0xb8: case 0xbc: if (s->datacnt == 0) { - fprintf(stderr, "pl181: Unexpected FIFO write\n"); + qemu_log_mask(LOG_GUEST_ERROR, "pl181: Unexpected FIFO write\n"); } else { pl181_fifo_push(s, value); pl181_fifo_run(s); } break; default: - hw_error("pl181_write: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl181_write: Bad offset %x\n", (int)offset); } pl181_update(s); } From b1d9df90212984f8e78abc75152527a00d899f89 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Oct 2012 14:11:38 +0100 Subject: [PATCH 1030/2270] hw/pl041: Use LOG_UNIMP Use the new LOG_UNIMP tracing to report unimplemented features. Signed-off-by: Peter Maydell Signed-off-by: Blue Swirl --- hw/pl041.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/pl041.c b/hw/pl041.c index b6723be0a9..9a6db1b6e2 100644 --- a/hw/pl041.c +++ b/hw/pl041.c @@ -536,8 +536,9 @@ static int pl041_init(SysBusDevice *dev) default: /* NC FIFO depth of 16 is not allowed because its id bits in AACIPERIPHID3 overlap with the id for the default NC FIFO depth */ - fprintf(stderr, "pl041: unsupported non-compact fifo depth [%i]\n", - s->fifo_depth); + qemu_log_mask(LOG_UNIMP, + "pl041: unsupported non-compact fifo depth [%i]\n", + s->fifo_depth); return -1; } From fd271e81aa7334b973285f5c94a4f8ab265df683 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Oct 2012 14:11:39 +0100 Subject: [PATCH 1031/2270] hw/pl190: Use LOG_GUEST_ERROR If the guest attempts an offset to a nonexistent register, just log this via LOG_GUEST_ERROR rather than killing QEMU with a hw_error. Signed-off-by: Peter Maydell Signed-off-by: Blue Swirl --- hw/pl190.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/pl190.c b/hw/pl190.c index 7332f4dbae..961da5b3af 100644 --- a/hw/pl190.c +++ b/hw/pl190.c @@ -143,7 +143,8 @@ static uint64_t pl190_read(void *opaque, target_phys_addr_t offset, case 13: /* DEFVECTADDR */ return s->vect_addr[16]; default: - hw_error("pl190_read: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl190_read: Bad offset %x\n", (int)offset); return 0; } } @@ -202,7 +203,8 @@ static void pl190_write(void *opaque, target_phys_addr_t offset, } break; default: - hw_error("pl190_write: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl190_write: Bad offset %x\n", (int)offset); return; } pl190_update(s); From 6d5433e00a73f96dd5cbf93874dd8122672144b6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Oct 2012 14:11:40 +0100 Subject: [PATCH 1032/2270] hw/pl011: Use LOG_UNIMP and LOG_GUEST_ERROR Use the new LOG_UNIMP and LOG_GUEST_ERROR logging types rather than hw_error(). Signed-off-by: Peter Maydell Signed-off-by: Blue Swirl --- hw/pl011.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/hw/pl011.c b/hw/pl011.c index 3245702df0..fb22736b6a 100644 --- a/hw/pl011.c +++ b/hw/pl011.c @@ -107,7 +107,8 @@ static uint64_t pl011_read(void *opaque, target_phys_addr_t offset, case 18: /* UARTDMACR */ return s->dmacr; default: - hw_error("pl011_read: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl011_read: Bad offset %x\n", (int)offset); return 0; } } @@ -178,11 +179,13 @@ static void pl011_write(void *opaque, target_phys_addr_t offset, break; case 18: /* UARTDMACR */ s->dmacr = value; - if (value & 3) - hw_error("PL011: DMA not implemented\n"); + if (value & 3) { + qemu_log_mask(LOG_UNIMP, "pl011: DMA not implemented\n"); + } break; default: - hw_error("pl011_write: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl011_write: Bad offset %x\n", (int)offset); } } From af83c32bd44b6594db301b4ac8cb44e5eb85d4bf Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Oct 2012 14:11:41 +0100 Subject: [PATCH 1033/2270] hw/pl022: Use LOG_UNIMP and LOG_GUEST_ERROR Use LOG_UNIMP and LOG_GUEST_ERROR where appropriate rather than hw_error(). Signed-off-by: Peter Maydell Signed-off-by: Blue Swirl --- hw/pl022.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/pl022.c b/hw/pl022.c index 60e35daeb5..e2ae315efb 100644 --- a/hw/pl022.c +++ b/hw/pl022.c @@ -168,7 +168,8 @@ static uint64_t pl022_read(void *opaque, target_phys_addr_t offset, /* Not implemented. */ return 0; default: - hw_error("pl022_read: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl022_read: Bad offset %x\n", (int)offset); return 0; } } @@ -211,11 +212,12 @@ static void pl022_write(void *opaque, target_phys_addr_t offset, break; case 0x20: /* DMACR */ if (value) { - hw_error("pl022: DMA not implemented\n"); + qemu_log_mask(LOG_UNIMP, "pl022: DMA not implemented\n"); } break; default: - hw_error("pl022_write: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl022_write: Bad offset %x\n", (int)offset); } } From a5089c050138933631b8755a664cfd275763b223 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Oct 2012 14:11:42 +0100 Subject: [PATCH 1034/2270] hw/pl031: Use LOG_GUEST_ERROR Use LOG_GUEST_ERROR rather than hw_error or direct fprintf. Signed-off-by: Peter Maydell Signed-off-by: Blue Swirl --- hw/pl031.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/hw/pl031.c b/hw/pl031.c index 9602664da6..6cbaf2386f 100644 --- a/hw/pl031.c +++ b/hw/pl031.c @@ -120,11 +120,13 @@ static uint64_t pl031_read(void *opaque, target_phys_addr_t offset, case RTC_MIS: return s->is & s->im; case RTC_ICR: - fprintf(stderr, "qemu: pl031_read: Unexpected offset 0x%x\n", - (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl031: read of write-only register at offset 0x%x\n", + (int)offset); break; default: - hw_error("pl031_read: Bad offset 0x%x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl031_read: Bad offset 0x%x\n", (int)offset); break; } @@ -167,12 +169,14 @@ static void pl031_write(void * opaque, target_phys_addr_t offset, case RTC_DR: case RTC_MIS: case RTC_RIS: - fprintf(stderr, "qemu: pl031_write: Unexpected offset 0x%x\n", - (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl031: write to read-only register at offset 0x%x\n", + (int)offset); break; default: - hw_error("pl031_write: Bad offset 0x%x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl031_write: Bad offset 0x%x\n", (int)offset); break; } } From e7c8afb9058f9d46a089a9fb75cccf996886249c Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Wed, 17 Oct 2012 01:28:35 +0200 Subject: [PATCH 1035/2270] target-sparc: fix FMOVr instruction Like the MOVr instruction, the FMOVr instruction has the condition encoded between bits 10 and 12. Cc: Blue Swirl Signed-off-by: Aurelien Jarno Signed-off-by: Blue Swirl --- target-sparc/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 5df287629e..4321393688 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -3176,7 +3176,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #define FMOVR(sz) \ do { \ DisasCompare cmp; \ - cond = GET_FIELD_SP(insn, 14, 17); \ + cond = GET_FIELD_SP(insn, 10, 12); \ cpu_src1 = get_src1(dc, insn); \ gen_compare_reg(&cmp, cond, cpu_src1); \ gen_fmov##sz(dc, &cmp, rd, rs2); \ From f354b1a1ee7a1c72d51b42808724a2b10eec315f Mon Sep 17 00:00:00 2001 From: Michael Tokarev Date: Sun, 21 Oct 2012 22:52:54 +0400 Subject: [PATCH 1036/2270] fix CONFIG_QEMU_HELPERDIR generation again commit 38f419f35225 fixed a breakage with CONFIG_QEMU_HELPERDIR which has been introduced by 8bf188aa18ef7a8. But while techinically that fix has been correct, all other similar variables are handled differently. Make it consistent, and let scripts/create_config expand and capitalize the variable properly like for all other qemu_*dir variables. Signed-off-by: Michael Tokarev --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 9f33c7d723..fa5657f6bc 100755 --- a/configure +++ b/configure @@ -3200,7 +3200,7 @@ echo "qemu_confdir=$qemu_confdir" >> $config_host_mak echo "qemu_datadir=$qemu_datadir" >> $config_host_mak echo "qemu_docdir=$qemu_docdir" >> $config_host_mak echo "qemu_localstatedir=$local_statedir" >> $config_host_mak -echo "CONFIG_QEMU_HELPERDIR=\"`eval echo $libexecdir`\"" >> $config_host_mak +echo "qemu_helperdir=$libexecdir" >> $config_host_mak echo "ARCH=$ARCH" >> $config_host_mak if test "$debug_tcg" = "yes" ; then From 95d2994a2f756c9c8684709421d40c45e63e4e04 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 18:21:54 +0200 Subject: [PATCH 1037/2270] memory: manage coalesced mmio via a MemoryListener Instead of calling a global function on coalesced mmio changes, which routes the call to kvm if enabled, add coalesced mmio hooks to MemoryListener and make kvm use that instead. The motivation is support for multiple address spaces (which means we we need to filter the call on the right address space) but the result is cleaner as well. Signed-off-by: Avi Kivity --- exec.c | 13 ------------- kvm-all.c | 20 ++++++++++---------- kvm-stub.c | 10 ---------- kvm.h | 2 -- memory.c | 17 +++++++++++++---- memory.h | 4 ++++ 6 files changed, 27 insertions(+), 39 deletions(-) diff --git a/exec.c b/exec.c index 6558728d09..5d5d9e33c9 100644 --- a/exec.c +++ b/exec.c @@ -2305,19 +2305,6 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section, } } - -void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size) -{ - if (kvm_enabled()) - kvm_coalesce_mmio_region(addr, size); -} - -void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size) -{ - if (kvm_enabled()) - kvm_uncoalesce_mmio_region(addr, size); -} - void qemu_flush_coalesced_mmio_buffer(void) { if (kvm_enabled()) diff --git a/kvm-all.c b/kvm-all.c index 46cf7e9ec4..677dd2d99f 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -454,9 +454,10 @@ static int kvm_physical_sync_dirty_bitmap(MemoryRegionSection *section) return ret; } -int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) +static void kvm_coalesce_mmio_region(MemoryListener *listener, + MemoryRegionSection *secion, + target_phys_addr_t start, target_phys_addr_t size) { - int ret = -ENOSYS; KVMState *s = kvm_state; if (s->coalesced_mmio) { @@ -466,15 +467,14 @@ int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) zone.size = size; zone.pad = 0; - ret = kvm_vm_ioctl(s, KVM_REGISTER_COALESCED_MMIO, &zone); + (void)kvm_vm_ioctl(s, KVM_REGISTER_COALESCED_MMIO, &zone); } - - return ret; } -int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) +static void kvm_uncoalesce_mmio_region(MemoryListener *listener, + MemoryRegionSection *secion, + target_phys_addr_t start, target_phys_addr_t size) { - int ret = -ENOSYS; KVMState *s = kvm_state; if (s->coalesced_mmio) { @@ -484,10 +484,8 @@ int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) zone.size = size; zone.pad = 0; - ret = kvm_vm_ioctl(s, KVM_UNREGISTER_COALESCED_MMIO, &zone); + (void)kvm_vm_ioctl(s, KVM_UNREGISTER_COALESCED_MMIO, &zone); } - - return ret; } int kvm_check_extension(KVMState *s, unsigned int extension) @@ -817,6 +815,8 @@ static MemoryListener kvm_memory_listener = { .log_global_stop = kvm_log_global_stop, .eventfd_add = kvm_mem_ioeventfd_add, .eventfd_del = kvm_mem_ioeventfd_del, + .coalesced_mmio_add = kvm_coalesce_mmio_region, + .coalesced_mmio_del = kvm_uncoalesce_mmio_region, .priority = 10, }; diff --git a/kvm-stub.c b/kvm-stub.c index 3c52eb5bc6..a3455e2203 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -29,16 +29,6 @@ int kvm_init_vcpu(CPUArchState *env) return -ENOSYS; } -int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) -{ - return -ENOSYS; -} - -int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) -{ - return -ENOSYS; -} - int kvm_init(void) { return -ENOSYS; diff --git a/kvm.h b/kvm.h index dea2998fd4..eefcb492f0 100644 --- a/kvm.h +++ b/kvm.h @@ -129,8 +129,6 @@ void *kvm_vmalloc(ram_addr_t size); void *kvm_arch_vmalloc(ram_addr_t size); void kvm_setup_guest_memory(void *start, size_t size); -int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); -int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); void kvm_flush_coalesced_mmio_buffer(void); #endif diff --git a/memory.c b/memory.c index 269af3f6b0..d829f67419 100644 --- a/memory.c +++ b/memory.c @@ -1136,11 +1136,19 @@ static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa FlatRange *fr; CoalescedMemoryRange *cmr; AddrRange tmp; + MemoryRegionSection section; FOR_EACH_FLAT_RANGE(fr, as->current_map) { if (fr->mr == mr) { - qemu_unregister_coalesced_mmio(int128_get64(fr->addr.start), - int128_get64(fr->addr.size)); + section = (MemoryRegionSection) { + .address_space = as->root, + .offset_within_address_space = int128_get64(fr->addr.start), + .size = int128_get64(fr->addr.size), + }; + + MEMORY_LISTENER_CALL(coalesced_mmio_del, Reverse, §ion, + int128_get64(fr->addr.start), + int128_get64(fr->addr.size)); QTAILQ_FOREACH(cmr, &mr->coalesced, link) { tmp = addrrange_shift(cmr->addr, int128_sub(fr->addr.start, @@ -1149,8 +1157,9 @@ static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa continue; } tmp = addrrange_intersection(tmp, fr->addr); - qemu_register_coalesced_mmio(int128_get64(tmp.start), - int128_get64(tmp.size)); + MEMORY_LISTENER_CALL(coalesced_mmio_add, Forward, §ion, + int128_get64(tmp.start), + int128_get64(tmp.size)); } } } diff --git a/memory.h b/memory.h index 46bc5e1cfd..64d2b341b6 100644 --- a/memory.h +++ b/memory.h @@ -217,6 +217,10 @@ struct MemoryListener { bool match_data, uint64_t data, EventNotifier *e); void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section, bool match_data, uint64_t data, EventNotifier *e); + void (*coalesced_mmio_add)(MemoryListener *listener, MemoryRegionSection *section, + target_phys_addr_t addr, target_phys_addr_t len); + void (*coalesced_mmio_del)(MemoryListener *listener, MemoryRegionSection *section, + target_phys_addr_t addr, target_phys_addr_t len); /* Lower = earlier (during add), later (during del) */ unsigned priority; MemoryRegion *address_space_filter; From 2673a5da25ea9005e562c20a18cf469ed4f21060 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 18:49:28 +0200 Subject: [PATCH 1038/2270] memory: move address_space_memory and address_space_io out of memory core With this change, memory.c no longer knows anything about special address spaces, so it is prepared for AddressSpace based DMA. Reviewed-by: Anthony Liguori Signed-off-by: Avi Kivity --- exec-memory.h | 6 ------ exec.c | 9 +++++++-- memory.c | 16 ---------------- 3 files changed, 7 insertions(+), 24 deletions(-) diff --git a/exec-memory.h b/exec-memory.h index 1cd92eec71..6707e40b2f 100644 --- a/exec-memory.h +++ b/exec-memory.h @@ -33,12 +33,6 @@ MemoryRegion *get_system_memory(void); */ MemoryRegion *get_system_io(void); -/* Set the root memory region. This region is the system memory map. */ -void set_system_memory_map(MemoryRegion *mr); - -/* Set the I/O memory region. This region is the I/O memory map. */ -void set_system_io_map(MemoryRegion *mr); - #endif #endif diff --git a/exec.c b/exec.c index 5d5d9e33c9..dfc0a784f3 100644 --- a/exec.c +++ b/exec.c @@ -116,6 +116,9 @@ RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks) }; static MemoryRegion *system_memory; static MemoryRegion *system_io; +static AddressSpace address_space_io; +static AddressSpace address_space_memory; + MemoryRegion io_mem_ram, io_mem_rom, io_mem_unassigned, io_mem_notdirty; static MemoryRegion io_mem_subpage_ram; @@ -3235,11 +3238,13 @@ static void memory_map_init(void) { system_memory = g_malloc(sizeof(*system_memory)); memory_region_init(system_memory, "system", INT64_MAX); - set_system_memory_map(system_memory); + address_space_init(&address_space_memory, system_memory); + address_space_memory.name = "memory"; system_io = g_malloc(sizeof(*system_io)); memory_region_init(system_io, "io", 65536); - set_system_io_map(system_io); + address_space_init(&address_space_io, system_io); + address_space_io.name = "I/O"; memory_listener_register(&core_memory_listener, system_memory); memory_listener_register(&io_memory_listener, system_io); diff --git a/memory.c b/memory.c index d829f67419..49a6ecc6c8 100644 --- a/memory.c +++ b/memory.c @@ -364,8 +364,6 @@ static void access_with_adjusted_size(target_phys_addr_t addr, } } -static AddressSpace address_space_memory; - static const MemoryRegionPortio *find_portio(MemoryRegion *mr, uint64_t offset, unsigned width, bool write) { @@ -454,8 +452,6 @@ const IORangeOps memory_region_iorange_ops = { .destructor = memory_region_iorange_destructor, }; -static AddressSpace address_space_io; - static AddressSpace *memory_region_to_address_space(MemoryRegion *mr) { AddressSpace *as; @@ -1545,18 +1541,6 @@ void address_space_init(AddressSpace *as, MemoryRegion *root) memory_region_transaction_commit(); } -void set_system_memory_map(MemoryRegion *mr) -{ - address_space_init(&address_space_memory, mr); - address_space_memory.name = "memory"; -} - -void set_system_io_map(MemoryRegion *mr) -{ - address_space_init(&address_space_io, mr); - address_space_io.name = "I/O"; -} - uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size) { return memory_region_dispatch_read(mr, addr, size); From 1d71148eace669827ba15101819b54b20fcca616 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 18:54:45 +0200 Subject: [PATCH 1039/2270] memory: move tcg flush into a tcg memory listener We plan to make the core listener listen to all address spaces; this will cause many more flushes than necessary. Prepare for that by moving the flush into a tcg-specific listener. Later we can avoid registering the listener if tcg is disabled. Signed-off-by: Avi Kivity --- exec.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/exec.c b/exec.c index dfc0a784f3..6a7ba0cea6 100644 --- a/exec.c +++ b/exec.c @@ -3166,7 +3166,7 @@ static void core_begin(MemoryListener *listener) phys_section_watch = dummy_section(&io_mem_watch); } -static void core_commit(MemoryListener *listener) +static void tcg_commit(MemoryListener *listener) { CPUArchState *env; @@ -3220,7 +3220,6 @@ static void io_region_del(MemoryListener *listener, static MemoryListener core_memory_listener = { .begin = core_begin, - .commit = core_commit, .region_add = core_region_add, .region_nop = core_region_nop, .log_global_start = core_log_global_start, @@ -3234,6 +3233,10 @@ static MemoryListener io_memory_listener = { .priority = 0, }; +static MemoryListener tcg_memory_listener = { + .commit = tcg_commit, +}; + static void memory_map_init(void) { system_memory = g_malloc(sizeof(*system_memory)); @@ -3248,6 +3251,7 @@ static void memory_map_init(void) memory_listener_register(&core_memory_listener, system_memory); memory_listener_register(&io_memory_listener, system_io); + memory_listener_register(&tcg_memory_listener, system_memory); } MemoryRegion *get_system_memory(void) From f6790af6bcfa35fa9ea3c565a0a2aed54337aef5 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 20:13:51 +0200 Subject: [PATCH 1040/2270] memory: use AddressSpace for MemoryListener filtering Using the AddressSpace type reduces confusion, as you can't accidentally supply the MemoryRegion you're interested in. Reviewed-by: Anthony Liguori Signed-off-by: Avi Kivity --- exec-memory.h | 3 +++ exec.c | 10 +++++----- hw/vfio_pci.c | 3 +-- hw/vhost.c | 2 +- hw/xen_pt.c | 4 ++-- kvm-all.c | 4 ++-- memory.c | 14 +++++++------- memory.h | 6 +++--- xen-all.c | 2 +- 9 files changed, 25 insertions(+), 23 deletions(-) diff --git a/exec-memory.h b/exec-memory.h index 6707e40b2f..ac1d07dfe4 100644 --- a/exec-memory.h +++ b/exec-memory.h @@ -33,6 +33,9 @@ MemoryRegion *get_system_memory(void); */ MemoryRegion *get_system_io(void); +extern AddressSpace address_space_memory; +extern AddressSpace address_space_io; + #endif #endif diff --git a/exec.c b/exec.c index 6a7ba0cea6..e732b5285e 100644 --- a/exec.c +++ b/exec.c @@ -116,8 +116,8 @@ RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks) }; static MemoryRegion *system_memory; static MemoryRegion *system_io; -static AddressSpace address_space_io; -static AddressSpace address_space_memory; +AddressSpace address_space_io; +AddressSpace address_space_memory; MemoryRegion io_mem_ram, io_mem_rom, io_mem_unassigned, io_mem_notdirty; static MemoryRegion io_mem_subpage_ram; @@ -3249,9 +3249,9 @@ static void memory_map_init(void) address_space_init(&address_space_io, system_io); address_space_io.name = "I/O"; - memory_listener_register(&core_memory_listener, system_memory); - memory_listener_register(&io_memory_listener, system_io); - memory_listener_register(&tcg_memory_listener, system_memory); + memory_listener_register(&core_memory_listener, &address_space_memory); + memory_listener_register(&io_memory_listener, &address_space_io); + memory_listener_register(&tcg_memory_listener, &address_space_memory); } MemoryRegion *get_system_memory(void) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 49e11e7db3..f5db4a8567 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -1507,8 +1507,7 @@ static int vfio_connect_container(VFIOGroup *group) container->iommu_data.listener = vfio_memory_listener; container->iommu_data.release = vfio_listener_release; - memory_listener_register(&container->iommu_data.listener, - get_system_memory()); + memory_listener_register(&container->iommu_data.listener, &address_space_memory); } else { error_report("vfio: No available IOMMU models\n"); g_free(container); diff --git a/hw/vhost.c b/hw/vhost.c index 100f7659a0..0b4ac3f1df 100644 --- a/hw/vhost.c +++ b/hw/vhost.c @@ -792,7 +792,7 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, const char *devpath, hdev->log_size = 0; hdev->log_enabled = false; hdev->started = false; - memory_listener_register(&hdev->memory_listener, get_system_memory()); + memory_listener_register(&hdev->memory_listener, &address_space_memory); hdev->force = force; return 0; fail: diff --git a/hw/xen_pt.c b/hw/xen_pt.c index d5dc11e582..d3d7c8bc3c 100644 --- a/hw/xen_pt.c +++ b/hw/xen_pt.c @@ -749,8 +749,8 @@ static int xen_pt_initfn(PCIDevice *d) } out: - memory_listener_register(&s->memory_listener, get_system_memory()); - memory_listener_register(&s->io_listener, get_system_io()); + memory_listener_register(&s->memory_listener, &address_space_memory); + memory_listener_register(&s->io_listener, &address_space_io); XEN_PT_LOG(d, "Real physical device %02x:%02x.%d registered successfuly!\n", bus, slot, func); diff --git a/kvm-all.c b/kvm-all.c index 677dd2d99f..c2c69093ec 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1375,8 +1375,8 @@ int kvm_init(void) } kvm_state = s; - memory_listener_register(&kvm_memory_listener, get_system_memory()); - memory_listener_register(&kvm_io_listener, get_system_io()); + memory_listener_register(&kvm_memory_listener, &address_space_memory); + memory_listener_register(&kvm_io_listener, &address_space_io); s->many_ioeventfds = kvm_check_many_ioeventfds(); diff --git a/memory.c b/memory.c index 49a6ecc6c8..0cf0177f43 100644 --- a/memory.c +++ b/memory.c @@ -147,7 +147,7 @@ static bool memory_listener_match(MemoryListener *listener, #define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback) \ MEMORY_LISTENER_CALL(callback, dir, (&(MemoryRegionSection) { \ .mr = (fr)->mr, \ - .address_space = (as)->root, \ + .address_space = (as), \ .offset_within_region = (fr)->offset_in_region, \ .size = int128_get64((fr)->addr.size), \ .offset_within_address_space = int128_get64((fr)->addr.start), \ @@ -593,7 +593,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as, fds_new[inew]))) { fd = &fds_old[iold]; section = (MemoryRegionSection) { - .address_space = as->root, + .address_space = as, .offset_within_address_space = int128_get64(fd->addr.start), .size = int128_get64(fd->addr.size), }; @@ -606,7 +606,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as, fds_old[iold]))) { fd = &fds_new[inew]; section = (MemoryRegionSection) { - .address_space = as->root, + .address_space = as, .offset_within_address_space = int128_get64(fd->addr.start), .size = int128_get64(fd->addr.size), }; @@ -1137,7 +1137,7 @@ static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa FOR_EACH_FLAT_RANGE(fr, as->current_map) { if (fr->mr == mr) { section = (MemoryRegionSection) { - .address_space = as->root, + .address_space = as, .offset_within_address_space = int128_get64(fr->addr.start), .size = int128_get64(fr->addr.size), }; @@ -1476,7 +1476,7 @@ static void listener_add_address_space(MemoryListener *listener, FlatRange *fr; if (listener->address_space_filter - && listener->address_space_filter != as->root) { + && listener->address_space_filter != as) { return; } @@ -1489,7 +1489,7 @@ static void listener_add_address_space(MemoryListener *listener, FOR_EACH_FLAT_RANGE(fr, as->current_map) { MemoryRegionSection section = { .mr = fr->mr, - .address_space = as->root, + .address_space = as, .offset_within_region = fr->offset_in_region, .size = int128_get64(fr->addr.size), .offset_within_address_space = int128_get64(fr->addr.start), @@ -1501,7 +1501,7 @@ static void listener_add_address_space(MemoryListener *listener, } } -void memory_listener_register(MemoryListener *listener, MemoryRegion *filter) +void memory_listener_register(MemoryListener *listener, AddressSpace *filter) { MemoryListener *other = NULL; AddressSpace *as; diff --git a/memory.h b/memory.h index 64d2b341b6..f5a13a4db6 100644 --- a/memory.h +++ b/memory.h @@ -187,7 +187,7 @@ typedef struct MemoryRegionSection MemoryRegionSection; */ struct MemoryRegionSection { MemoryRegion *mr; - MemoryRegion *address_space; + AddressSpace *address_space; target_phys_addr_t offset_within_region; uint64_t size; target_phys_addr_t offset_within_address_space; @@ -223,7 +223,7 @@ struct MemoryListener { target_phys_addr_t addr, target_phys_addr_t len); /* Lower = earlier (during add), later (during del) */ unsigned priority; - MemoryRegion *address_space_filter; + AddressSpace *address_space_filter; QTAILQ_ENTRY(MemoryListener) link; }; @@ -774,7 +774,7 @@ void memory_region_transaction_commit(void); * @listener: an object containing the callbacks to be called * @filter: if non-%NULL, only regions in this address space will be observed */ -void memory_listener_register(MemoryListener *listener, MemoryRegion *filter); +void memory_listener_register(MemoryListener *listener, AddressSpace *filter); /** * memory_listener_unregister: undo the effect of memory_listener_register() diff --git a/xen-all.c b/xen-all.c index 8731e1165b..9d1e168826 100644 --- a/xen-all.c +++ b/xen-all.c @@ -1141,7 +1141,7 @@ int xen_hvm_init(void) state->memory_listener = xen_memory_listener; QLIST_INIT(&state->physmap); - memory_listener_register(&state->memory_listener, get_system_memory()); + memory_listener_register(&state->memory_listener, &address_space_memory); state->log_for_dirtybit = NULL; /* Initialize backend core & drivers */ From 0e8a6d47afcc88564079387928f2da45736d36e8 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 3 Oct 2012 16:14:23 +0200 Subject: [PATCH 1041/2270] s390: avoid reaching into memory core internals use cpu_physical_memory_is_io() instead. Signed-off-by: Avi Kivity --- target-s390x/misc_helper.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index e9b3caed49..fdccd58e3d 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -20,7 +20,6 @@ #include "cpu.h" #include "memory.h" -#include "cputlb.h" #include "host-utils.h" #include "helper.h" #include @@ -81,7 +80,7 @@ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code) #endif /* basic checks */ - if (!memory_region_is_ram(phys_page_find(sccb >> TARGET_PAGE_BITS)->mr)) { + if (cpu_physical_memory_is_io(sccb)) { return -PGM_ADDRESSING; } if (sccb & ~0x7ffffff8ul) { From ac1970fbe8ad5a70174f462109ac0f6c7bf1bc43 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 3 Oct 2012 16:22:53 +0200 Subject: [PATCH 1042/2270] memory: per-AddressSpace dispatch Currently we use a global radix tree to dispatch memory access. This only works with a single address space; to support multiple address spaces we make the radix tree a member of AddressSpace (via an intermediate structure AddressSpaceDispatch to avoid exposing too many internals). A side effect is that address_space_io also gains a dispatch table. When we remove all the pre-memory-API I/O registrations, we can use that for dispatching I/O and get rid of the original I/O dispatch. Signed-off-by: Avi Kivity --- cputlb.c | 3 +- cputlb.h | 3 +- exec.c | 174 ++++++++++++++++++++++++++++------------------ memory-internal.h | 22 +++++- memory.c | 1 + memory.h | 62 +++++++++++++++++ 6 files changed, 194 insertions(+), 71 deletions(-) diff --git a/cputlb.c b/cputlb.c index 0627f32e35..9027557604 100644 --- a/cputlb.c +++ b/cputlb.c @@ -21,6 +21,7 @@ #include "cpu.h" #include "exec-all.h" #include "memory.h" +#include "exec-memory.h" #include "cputlb.h" @@ -251,7 +252,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr, if (size != TARGET_PAGE_SIZE) { tlb_add_large_page(env, vaddr, size); } - section = phys_page_find(paddr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, paddr >> TARGET_PAGE_BITS); #if defined(DEBUG_TLB) printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx " prot=%x idx=%d pd=0x%08lx\n", diff --git a/cputlb.h b/cputlb.h index 2dc2c96cd8..d537b7740f 100644 --- a/cputlb.h +++ b/cputlb.h @@ -26,7 +26,8 @@ void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr, target_ulong vaddr); void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, uintptr_t start, uintptr_t length); -MemoryRegionSection *phys_page_find(target_phys_addr_t index); +MemoryRegionSection *phys_page_find(struct AddressSpaceDispatch *d, + target_phys_addr_t index); void cpu_tlb_reset_dirty_all(ram_addr_t start1, ram_addr_t length); void tlb_set_dirty(CPUArchState *env, target_ulong vaddr); extern int tlb_flush_count; diff --git a/exec.c b/exec.c index e732b5285e..bfc4acc206 100644 --- a/exec.c +++ b/exec.c @@ -187,7 +187,6 @@ uintptr_t qemu_host_page_mask; static void *l1_map[V_L1_SIZE]; #if !defined(CONFIG_USER_ONLY) -typedef struct PhysPageEntry PhysPageEntry; static MemoryRegionSection *phys_sections; static unsigned phys_sections_nb, phys_sections_nb_alloc; @@ -196,22 +195,12 @@ static uint16_t phys_section_notdirty; static uint16_t phys_section_rom; static uint16_t phys_section_watch; -struct PhysPageEntry { - uint16_t is_leaf : 1; - /* index into phys_sections (is_leaf) or phys_map_nodes (!is_leaf) */ - uint16_t ptr : 15; -}; - /* Simple allocator for PhysPageEntry nodes */ static PhysPageEntry (*phys_map_nodes)[L2_SIZE]; static unsigned phys_map_nodes_nb, phys_map_nodes_nb_alloc; #define PHYS_MAP_NODE_NIL (((uint16_t)~0) >> 1) -/* This is a multi-level map on the physical address space. - The bottom level has pointers to MemoryRegionSections. */ -static PhysPageEntry phys_map = { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 }; - static void io_mem_init(void); static void memory_map_init(void); @@ -459,18 +448,19 @@ static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t *index, } } -static void phys_page_set(target_phys_addr_t index, target_phys_addr_t nb, +static void phys_page_set(AddressSpaceDispatch *d, + target_phys_addr_t index, target_phys_addr_t nb, uint16_t leaf) { /* Wildly overreserve - it doesn't matter much. */ phys_map_node_reserve(3 * P_L2_LEVELS); - phys_page_set_level(&phys_map, &index, &nb, leaf, P_L2_LEVELS - 1); + phys_page_set_level(&d->phys_map, &index, &nb, leaf, P_L2_LEVELS - 1); } -MemoryRegionSection *phys_page_find(target_phys_addr_t index) +MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, target_phys_addr_t index) { - PhysPageEntry lp = phys_map; + PhysPageEntry lp = d->phys_map; PhysPageEntry *p; int i; uint16_t s_index = phys_section_unassigned; @@ -1472,7 +1462,7 @@ void tb_invalidate_phys_addr(target_phys_addr_t addr) ram_addr_t ram_addr; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + 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))) { return; @@ -2210,9 +2200,9 @@ static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level) lp->ptr = PHYS_MAP_NODE_NIL; } -static void destroy_all_mappings(void) +static void destroy_all_mappings(AddressSpaceDispatch *d) { - destroy_l2_mapping(&phys_map, P_L2_LEVELS - 1); + destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1); phys_map_nodes_reset(); } @@ -2232,12 +2222,12 @@ static void phys_sections_clear(void) phys_sections_nb = 0; } -static void register_subpage(MemoryRegionSection *section) +static void register_subpage(AddressSpaceDispatch *d, MemoryRegionSection *section) { subpage_t *subpage; target_phys_addr_t base = section->offset_within_address_space & TARGET_PAGE_MASK; - MemoryRegionSection *existing = phys_page_find(base >> TARGET_PAGE_BITS); + MemoryRegionSection *existing = phys_page_find(d, base >> TARGET_PAGE_BITS); MemoryRegionSection subsection = { .offset_within_address_space = base, .size = TARGET_PAGE_SIZE, @@ -2249,7 +2239,7 @@ static void register_subpage(MemoryRegionSection *section) if (!(existing->mr->subpage)) { subpage = subpage_init(base); subsection.mr = &subpage->iomem; - phys_page_set(base >> TARGET_PAGE_BITS, 1, + phys_page_set(d, base >> TARGET_PAGE_BITS, 1, phys_section_add(&subsection)); } else { subpage = container_of(existing->mr, subpage_t, iomem); @@ -2260,7 +2250,7 @@ static void register_subpage(MemoryRegionSection *section) } -static void register_multipage(MemoryRegionSection *section) +static void register_multipage(AddressSpaceDispatch *d, MemoryRegionSection *section) { target_phys_addr_t start_addr = section->offset_within_address_space; ram_addr_t size = section->size; @@ -2270,13 +2260,13 @@ static void register_multipage(MemoryRegionSection *section) assert(size); addr = start_addr; - phys_page_set(addr >> TARGET_PAGE_BITS, size >> TARGET_PAGE_BITS, + phys_page_set(d, addr >> TARGET_PAGE_BITS, size >> TARGET_PAGE_BITS, section_index); } -void cpu_register_physical_memory_log(MemoryRegionSection *section, - bool readonly) +static void mem_add(MemoryListener *listener, MemoryRegionSection *section) { + AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener); MemoryRegionSection now = *section, remain = *section; if ((now.offset_within_address_space & ~TARGET_PAGE_MASK) @@ -2284,7 +2274,7 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section, now.size = MIN(TARGET_PAGE_ALIGN(now.offset_within_address_space) - now.offset_within_address_space, now.size); - register_subpage(&now); + register_subpage(d, &now); remain.size -= now.size; remain.offset_within_address_space += now.size; remain.offset_within_region += now.size; @@ -2293,10 +2283,10 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section, now = remain; if (remain.offset_within_region & ~TARGET_PAGE_MASK) { now.size = TARGET_PAGE_SIZE; - register_subpage(&now); + register_subpage(d, &now); } else { now.size &= TARGET_PAGE_MASK; - register_multipage(&now); + register_multipage(d, &now); } remain.size -= now.size; remain.offset_within_address_space += now.size; @@ -2304,7 +2294,7 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section, } now = remain; if (now.size) { - register_subpage(&now); + register_subpage(d, &now); } } @@ -3155,11 +3145,17 @@ static void io_mem_init(void) "watch", UINT64_MAX); } +static void mem_begin(MemoryListener *listener) +{ + AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener); + + destroy_all_mappings(d); + d->phys_map.ptr = PHYS_MAP_NODE_NIL; +} + static void core_begin(MemoryListener *listener) { - destroy_all_mappings(); phys_sections_clear(); - phys_map.ptr = PHYS_MAP_NODE_NIL; phys_section_unassigned = dummy_section(&io_mem_unassigned); phys_section_notdirty = dummy_section(&io_mem_notdirty); phys_section_rom = dummy_section(&io_mem_rom); @@ -3178,18 +3174,6 @@ static void tcg_commit(MemoryListener *listener) } } -static void core_region_add(MemoryListener *listener, - MemoryRegionSection *section) -{ - cpu_register_physical_memory_log(section, section->readonly); -} - -static void core_region_nop(MemoryListener *listener, - MemoryRegionSection *section) -{ - cpu_register_physical_memory_log(section, section->readonly); -} - static void core_log_global_start(MemoryListener *listener) { cpu_physical_memory_set_dirty_tracking(1); @@ -3220,11 +3204,9 @@ static void io_region_del(MemoryListener *listener, static MemoryListener core_memory_listener = { .begin = core_begin, - .region_add = core_region_add, - .region_nop = core_region_nop, .log_global_start = core_log_global_start, .log_global_stop = core_log_global_stop, - .priority = 0, + .priority = 1, }; static MemoryListener io_memory_listener = { @@ -3237,6 +3219,21 @@ static MemoryListener tcg_memory_listener = { .commit = tcg_commit, }; +void address_space_init_dispatch(AddressSpace *as) +{ + AddressSpaceDispatch *d = g_new(AddressSpaceDispatch, 1); + + d->phys_map = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 }; + d->listener = (MemoryListener) { + .begin = mem_begin, + .region_add = mem_add, + .region_nop = mem_add, + .priority = 0, + }; + as->dispatch = d; + memory_listener_register(&d->listener, as); +} + static void memory_map_init(void) { system_memory = g_malloc(sizeof(*system_memory)); @@ -3321,9 +3318,10 @@ static void invalidate_and_set_dirty(target_phys_addr_t addr, xen_modified_memory(addr, length); } -void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, - int len, int is_write) +void address_space_rw(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, + int len, bool is_write) { + AddressSpaceDispatch *d = as->dispatch; int l; uint8_t *ptr; uint32_t val; @@ -3335,7 +3333,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, l = (page + TARGET_PAGE_SIZE) - addr; if (l > len) l = len; - section = phys_page_find(page >> TARGET_PAGE_BITS); + section = phys_page_find(d, page >> TARGET_PAGE_BITS); if (is_write) { if (!memory_region_is_ram(section->mr)) { @@ -3406,10 +3404,36 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, } } +void address_space_write(AddressSpace *as, target_phys_addr_t addr, + const uint8_t *buf, int len) +{ + address_space_rw(as, addr, (uint8_t *)buf, len, true); +} + +/** + * address_space_read: read from an address space. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + */ +void address_space_read(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, int len) +{ + address_space_rw(as, addr, buf, len, false); +} + + +void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, + int len, int is_write) +{ + return address_space_rw(&address_space_memory, addr, buf, len, is_write); +} + /* used for ROM loading : can write in RAM and ROM */ void cpu_physical_memory_write_rom(target_phys_addr_t addr, const uint8_t *buf, int len) { + AddressSpaceDispatch *d = address_space_memory.dispatch; int l; uint8_t *ptr; target_phys_addr_t page; @@ -3420,7 +3444,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr, l = (page + TARGET_PAGE_SIZE) - addr; if (l > len) l = len; - section = phys_page_find(page >> TARGET_PAGE_BITS); + section = phys_page_find(d, page >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr))) { @@ -3494,10 +3518,12 @@ static void cpu_notify_map_clients(void) * Use cpu_register_map_client() to know when retrying the map operation is * likely to succeed. */ -void *cpu_physical_memory_map(target_phys_addr_t addr, - target_phys_addr_t *plen, - int is_write) +void *address_space_map(AddressSpace *as, + target_phys_addr_t addr, + target_phys_addr_t *plen, + bool is_write) { + AddressSpaceDispatch *d = as->dispatch; target_phys_addr_t len = *plen; target_phys_addr_t todo = 0; int l; @@ -3512,7 +3538,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, l = (page + TARGET_PAGE_SIZE) - addr; if (l > len) l = len; - section = phys_page_find(page >> TARGET_PAGE_BITS); + section = phys_page_find(d, page >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) && !section->readonly)) { if (todo || bounce.buffer) { @@ -3522,7 +3548,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, bounce.addr = addr; bounce.len = l; if (!is_write) { - cpu_physical_memory_read(addr, bounce.buffer, l); + address_space_read(as, addr, bounce.buffer, l); } *plen = l; @@ -3543,12 +3569,12 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, return ret; } -/* Unmaps a memory region previously mapped by cpu_physical_memory_map(). +/* Unmaps a memory region previously mapped by address_space_map(). * Will also mark the memory as dirty if is_write == 1. access_len gives * the amount of memory that was actually read or written by the caller. */ -void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, - int is_write, target_phys_addr_t access_len) +void address_space_unmap(AddressSpace *as, void *buffer, target_phys_addr_t len, + int is_write, target_phys_addr_t access_len) { if (buffer != bounce.buffer) { if (is_write) { @@ -3569,13 +3595,26 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, return; } if (is_write) { - cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len); + address_space_write(as, bounce.addr, bounce.buffer, access_len); } qemu_vfree(bounce.buffer); bounce.buffer = NULL; cpu_notify_map_clients(); } +void *cpu_physical_memory_map(target_phys_addr_t addr, + target_phys_addr_t *plen, + int is_write) +{ + return address_space_map(&address_space_memory, addr, plen, is_write); +} + +void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, + int is_write, target_phys_addr_t access_len) +{ + return address_space_unmap(&address_space_memory, buffer, len, is_write, access_len); +} + /* warning: addr must be aligned */ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr, enum device_endian endian) @@ -3584,7 +3623,7 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr, uint32_t val; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr))) { @@ -3643,7 +3682,7 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr, uint64_t val; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr))) { @@ -3710,7 +3749,7 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr, uint64_t val; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr))) { @@ -3769,7 +3808,7 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val) uint8_t *ptr; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + 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); @@ -3801,7 +3840,7 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val) uint8_t *ptr; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + 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); @@ -3830,7 +3869,7 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val, uint8_t *ptr; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + 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); @@ -3897,7 +3936,7 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val, uint8_t *ptr; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + 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); @@ -4133,7 +4172,8 @@ bool cpu_physical_memory_is_io(target_phys_addr_t phys_addr) { MemoryRegionSection *section; - section = phys_page_find(phys_addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, + phys_addr >> TARGET_PAGE_BITS); return !(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr)); diff --git a/memory-internal.h b/memory-internal.h index 43fa886264..6d8711bb1f 100644 --- a/memory-internal.h +++ b/memory-internal.h @@ -22,6 +22,26 @@ #ifndef CONFIG_USER_ONLY #include "hw/xen.h" +typedef struct PhysPageEntry PhysPageEntry; + +struct PhysPageEntry { + uint16_t is_leaf : 1; + /* index into phys_sections (is_leaf) or phys_map_nodes (!is_leaf) */ + uint16_t ptr : 15; +}; + +typedef struct AddressSpaceDispatch AddressSpaceDispatch; + +struct AddressSpaceDispatch { + /* This is a multi-level map on the physical address space. + * The bottom level has pointers to MemoryRegionSections. + */ + PhysPageEntry phys_map; + MemoryListener listener; +}; + +void address_space_init_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); @@ -30,8 +50,6 @@ void qemu_ram_free_from_ptr(ram_addr_t addr); struct MemoryRegion; struct MemoryRegionSection; -void cpu_register_physical_memory_log(struct MemoryRegionSection *section, - bool readonly); void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size); void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size); diff --git a/memory.c b/memory.c index 0cf0177f43..13be84849c 100644 --- a/memory.c +++ b/memory.c @@ -1539,6 +1539,7 @@ void address_space_init(AddressSpace *as, MemoryRegion *root) QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link); as->name = NULL; memory_region_transaction_commit(); + address_space_init_dispatch(as); } uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size) diff --git a/memory.h b/memory.h index f5a13a4db6..d36c2baa23 100644 --- a/memory.h +++ b/memory.h @@ -169,6 +169,7 @@ struct AddressSpace { struct FlatView *current_map; int ioeventfd_nb; struct MemoryRegionIoeventfd *ioeventfds; + struct AddressSpaceDispatch *dispatch; QTAILQ_ENTRY(AddressSpace) address_spaces_link; }; @@ -803,6 +804,67 @@ void mtree_info(fprintf_function mon_printf, void *f); */ void address_space_init(AddressSpace *as, MemoryRegion *root); +/** + * address_space_rw: read from or write to an address space. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + * @is_write: indicates the transfer direction + */ +void address_space_rw(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, + int len, bool is_write); + +/** + * address_space_write: write to address space. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + */ +void address_space_write(AddressSpace *as, target_phys_addr_t addr, + const uint8_t *buf, int len); + +/** + * address_space_read: read from an address space. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + */ +void address_space_read(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, int len); + +/* address_space_map: map a physical memory region into a host virtual address + * + * May map a subset of the requested range, given by and returned in @plen. + * May return %NULL if resources needed to perform the mapping are exhausted. + * Use only for reads OR writes - not for read-modify-write operations. + * Use cpu_register_map_client() to know when retrying the map operation is + * likely to succeed. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @plen: pointer to length of buffer; updated on return + * @is_write: indicates the transfer direction + */ +void *address_space_map(AddressSpace *as, target_phys_addr_t addr, + target_phys_addr_t *plen, bool is_write); + +/* address_space_unmap: Unmaps a memory region previously mapped by address_space_map() + * + * Will also mark the memory as dirty if @is_write == %true. @access_len gives + * the amount of memory that was actually read or written by the caller. + * + * @as: #AddressSpace used + * @addr: address within that address space + * @len: buffer length as returned by address_space_map() + * @access_len: amount of data actually transferred + * @is_write: indicates the transfer direction + */ +void address_space_unmap(AddressSpace *as, void *buffer, target_phys_addr_t len, + int is_write, target_phys_addr_t access_len); + + #endif #endif From b90600eed3c0efe5f3260853c873caf51c0677b1 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 3 Oct 2012 16:42:37 +0200 Subject: [PATCH 1043/2270] dma: make dma access its own address space Instead of accessing the cpu address space, use an address space configured by the caller. Eventually all dma functionality will be folded into AddressSpace, but we have to start from something. Reviewed-by: Anthony Liguori Signed-off-by: Avi Kivity --- dma-helpers.c | 25 ++++++++++++------------- dma.h | 17 ++++++++--------- hw/spapr_iommu.c | 3 ++- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/dma-helpers.c b/dma-helpers.c index 433d8b21b3..3f09dcb072 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -14,7 +14,8 @@ /* #define DEBUG_IOMMU */ -static void do_dma_memory_set(dma_addr_t addr, uint8_t c, dma_addr_t len) +static void do_dma_memory_set(AddressSpace *as, + dma_addr_t addr, uint8_t c, dma_addr_t len) { #define FILLBUF_SIZE 512 uint8_t fillbuf[FILLBUF_SIZE]; @@ -23,7 +24,7 @@ static void do_dma_memory_set(dma_addr_t addr, uint8_t c, dma_addr_t len) memset(fillbuf, c, FILLBUF_SIZE); while (len > 0) { l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE; - cpu_physical_memory_rw(addr, fillbuf, l, true); + address_space_rw(as, addr, fillbuf, l, true); len -= l; addr += l; } @@ -36,7 +37,7 @@ int dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c, dma_addr_t len) if (dma_has_iommu(dma)) { return iommu_dma_memory_set(dma, addr, c, len); } - do_dma_memory_set(addr, c, len); + do_dma_memory_set(dma->as, addr, c, len); return 0; } @@ -332,8 +333,7 @@ int iommu_dma_memory_rw(DMAContext *dma, dma_addr_t addr, plen = len; } - cpu_physical_memory_rw(paddr, buf, plen, - dir == DMA_DIRECTION_FROM_DEVICE); + address_space_rw(dma->as, paddr, buf, plen, dir == DMA_DIRECTION_FROM_DEVICE); len -= plen; addr += plen; @@ -366,7 +366,7 @@ int iommu_dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c, plen = len; } - do_dma_memory_set(paddr, c, plen); + do_dma_memory_set(dma->as, paddr, c, plen); len -= plen; addr += plen; @@ -375,13 +375,14 @@ int iommu_dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c, return 0; } -void dma_context_init(DMAContext *dma, DMATranslateFunc translate, +void dma_context_init(DMAContext *dma, AddressSpace *as, DMATranslateFunc translate, DMAMapFunc map, DMAUnmapFunc unmap) { #ifdef DEBUG_IOMMU fprintf(stderr, "dma_context_init(%p, %p, %p, %p)\n", dma, translate, map, unmap); #endif + dma->as = as; dma->translate = translate; dma->map = map; dma->unmap = unmap; @@ -407,14 +408,13 @@ void *iommu_dma_memory_map(DMAContext *dma, dma_addr_t addr, dma_addr_t *len, /* * If this is true, the virtual region is contiguous, * but the translated physical region isn't. We just - * clamp *len, much like cpu_physical_memory_map() does. + * clamp *len, much like address_space_map() does. */ if (plen < *len) { *len = plen; } - buf = cpu_physical_memory_map(paddr, &plen, - dir == DMA_DIRECTION_FROM_DEVICE); + buf = address_space_map(dma->as, paddr, &plen, dir == DMA_DIRECTION_FROM_DEVICE); *len = plen; return buf; @@ -428,8 +428,7 @@ void iommu_dma_memory_unmap(DMAContext *dma, void *buffer, dma_addr_t len, return; } - cpu_physical_memory_unmap(buffer, len, - dir == DMA_DIRECTION_FROM_DEVICE, - access_len); + address_space_unmap(dma->as, buffer, len, dir == DMA_DIRECTION_FROM_DEVICE, + access_len); } diff --git a/dma.h b/dma.h index 1a33603f22..1bd6f4a651 100644 --- a/dma.h +++ b/dma.h @@ -11,6 +11,7 @@ #define DMA_H #include +#include "memory.h" #include "hw/hw.h" #include "block.h" #include "kvm.h" @@ -61,6 +62,7 @@ typedef void DMAUnmapFunc(DMAContext *dma, dma_addr_t access_len); struct DMAContext { + AddressSpace *as; DMATranslateFunc *translate; DMAMapFunc *map; DMAUnmapFunc *unmap; @@ -93,7 +95,7 @@ static inline void dma_barrier(DMAContext *dma, DMADirection dir) static inline bool dma_has_iommu(DMAContext *dma) { - return !!dma; + return dma && dma->translate; } /* Checks that the given range of addresses is valid for DMA. This is @@ -120,8 +122,7 @@ static inline int dma_memory_rw_relaxed(DMAContext *dma, dma_addr_t addr, { if (!dma_has_iommu(dma)) { /* Fast-path for no IOMMU */ - cpu_physical_memory_rw(addr, buf, len, - dir == DMA_DIRECTION_FROM_DEVICE); + address_space_rw(dma->as, addr, buf, len, dir == DMA_DIRECTION_FROM_DEVICE); return 0; } else { return iommu_dma_memory_rw(dma, addr, buf, len, dir); @@ -179,8 +180,7 @@ static inline void *dma_memory_map(DMAContext *dma, target_phys_addr_t xlen = *len; void *p; - p = cpu_physical_memory_map(addr, &xlen, - dir == DMA_DIRECTION_FROM_DEVICE); + p = address_space_map(dma->as, addr, &xlen, dir == DMA_DIRECTION_FROM_DEVICE); *len = xlen; return p; } else { @@ -196,9 +196,8 @@ static inline void dma_memory_unmap(DMAContext *dma, DMADirection dir, dma_addr_t access_len) { if (!dma_has_iommu(dma)) { - cpu_physical_memory_unmap(buffer, (target_phys_addr_t)len, - dir == DMA_DIRECTION_FROM_DEVICE, - access_len); + address_space_unmap(dma->as, buffer, (target_phys_addr_t)len, + dir == DMA_DIRECTION_FROM_DEVICE, access_len); } else { iommu_dma_memory_unmap(dma, buffer, len, dir, access_len); } @@ -242,7 +241,7 @@ DEFINE_LDST_DMA(q, q, 64, be); #undef DEFINE_LDST_DMA -void dma_context_init(DMAContext *dma, DMATranslateFunc translate, +void dma_context_init(DMAContext *dma, AddressSpace *as, DMATranslateFunc translate, DMAMapFunc map, DMAUnmapFunc unmap); struct ScatterGatherEntry { diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c index 38034c07bd..33f84e27aa 100644 --- a/hw/spapr_iommu.c +++ b/hw/spapr_iommu.c @@ -21,6 +21,7 @@ #include "qdev.h" #include "kvm_ppc.h" #include "dma.h" +#include "exec-memory.h" #include "hw/spapr.h" @@ -124,7 +125,7 @@ DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size) } tcet = g_malloc0(sizeof(*tcet)); - dma_context_init(&tcet->dma, spapr_tce_translate, NULL, NULL); + dma_context_init(&tcet->dma, &address_space_memory, spapr_tce_translate, NULL, NULL); tcet->liobn = liobn; tcet->window_size = window_size; From 83f3c251422b0724044f976a7ff26b2e8a47c374 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 7 Oct 2012 12:59:55 +0200 Subject: [PATCH 1044/2270] memory: add address_space_destroy() Since address spaces can be created dynamically by device hotplug, they can also be destroyed dynamically. Signed-off-by: Avi Kivity --- exec.c | 10 ++++++++++ memory-internal.h | 1 + memory.c | 18 ++++++++++++++++-- memory.h | 12 ++++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/exec.c b/exec.c index bfc4acc206..17e8ba21d4 100644 --- a/exec.c +++ b/exec.c @@ -3234,6 +3234,16 @@ void address_space_init_dispatch(AddressSpace *as) memory_listener_register(&d->listener, as); } +void address_space_destroy_dispatch(AddressSpace *as) +{ + AddressSpaceDispatch *d = as->dispatch; + + memory_listener_unregister(&d->listener); + destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1); + g_free(d); + as->dispatch = NULL; +} + static void memory_map_init(void) { system_memory = g_malloc(sizeof(*system_memory)); diff --git a/memory-internal.h b/memory-internal.h index 6d8711bb1f..4d33cc9530 100644 --- a/memory-internal.h +++ b/memory-internal.h @@ -41,6 +41,7 @@ struct AddressSpaceDispatch { }; void address_space_init_dispatch(AddressSpace *as); +void address_space_destroy_dispatch(AddressSpace *as); ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, MemoryRegion *mr); diff --git a/memory.c b/memory.c index 13be84849c..2f68d67c21 100644 --- a/memory.c +++ b/memory.c @@ -564,8 +564,10 @@ static FlatView generate_memory_topology(MemoryRegion *mr) flatview_init(&view); - render_memory_region(&view, mr, int128_zero(), - addrrange_make(int128_zero(), int128_2_64()), false); + if (mr) { + render_memory_region(&view, mr, int128_zero(), + addrrange_make(int128_zero(), int128_2_64()), false); + } flatview_simplify(&view); return view; @@ -1542,6 +1544,18 @@ void address_space_init(AddressSpace *as, MemoryRegion *root) address_space_init_dispatch(as); } +void address_space_destroy(AddressSpace *as) +{ + /* Flush out anything from MemoryListeners listening in on this */ + memory_region_transaction_begin(); + as->root = NULL; + memory_region_transaction_commit(); + QTAILQ_REMOVE(&address_spaces, as, address_spaces_link); + address_space_destroy_dispatch(as); + flatview_destroy(as->current_map); + g_free(as->current_map); +} + uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size) { return memory_region_dispatch_read(mr, addr, size); diff --git a/memory.h b/memory.h index d36c2baa23..79393f1a76 100644 --- a/memory.h +++ b/memory.h @@ -804,6 +804,18 @@ void mtree_info(fprintf_function mon_printf, void *f); */ void address_space_init(AddressSpace *as, MemoryRegion *root); + +/** + * address_space_destroy: destroy an address space + * + * Releases all resources associated with an address space. After an address space + * is destroyed, its root memory region (given by address_space_init()) may be destroyed + * as well. + * + * @as: address space to be destroyed + */ +void address_space_destroy(AddressSpace *as); + /** * address_space_rw: read from or write to an address space. * From 817dcc5368988b023c5e1d3f1444fd370c77c6a9 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 3 Oct 2012 17:17:27 +0200 Subject: [PATCH 1045/2270] pci: give each device its own address space Accesses from different devices can resolve differently (depending on bridge settings, iommus, and PCI_COMMAND_MASTER), so set up an address space for each device. Currently iommus are expressed outside the memory API, so this doesn't work if an iommu is present. Signed-off-by: Avi Kivity --- hw/pci.c | 14 ++++++++++++++ hw/pci.h | 1 + 2 files changed, 15 insertions(+) diff --git a/hw/pci.c b/hw/pci.c index 2ca6ff6fec..b1415dbce6 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -33,6 +33,7 @@ #include "qmp-commands.h" #include "msi.h" #include "msix.h" +#include "exec-memory.h" //#define DEBUG_PCI #ifdef DEBUG_PCI @@ -777,6 +778,13 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, pci_dev->bus = bus; if (bus->dma_context_fn) { pci_dev->dma = bus->dma_context_fn(bus, bus->dma_context_opaque, devfn); + } else { + /* FIXME: Make dma_context_fn use MemoryRegions instead, so this path is + * taken unconditionally */ + /* FIXME: inherit memory region from bus creator */ + address_space_init(&pci_dev->bus_master_as, get_system_memory()); + pci_dev->dma = g_new(DMAContext, 1); + dma_context_init(pci_dev->dma, &pci_dev->bus_master_as, NULL, NULL, NULL); } pci_dev->devfn = devfn; pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); @@ -830,6 +838,12 @@ static void do_pci_unregister_device(PCIDevice *pci_dev) qemu_free_irqs(pci_dev->irq); pci_dev->bus->devices[pci_dev->devfn] = NULL; pci_config_free(pci_dev); + + if (!pci_dev->bus->dma_context_fn) { + address_space_destroy(&pci_dev->bus_master_as); + g_free(pci_dev->dma); + pci_dev->dma = NULL; + } } static void pci_unregister_io_regions(PCIDevice *pci_dev) diff --git a/hw/pci.h b/hw/pci.h index d50d26c8ac..f9207ca062 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -211,6 +211,7 @@ struct PCIDevice { int32_t devfn; char name[64]; PCIIORegion io_regions[PCI_NUM_REGIONS]; + AddressSpace bus_master_as; DMAContext *dma; /* do not access the following fields */ From 1c380f9460522f32c8dd2577b2a53d518ec91c6d Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 3 Oct 2012 17:42:58 +0200 Subject: [PATCH 1046/2270] pci: honor PCI_COMMAND_MASTER Currently we ignore PCI_COMMAND_MASTER completely: DMA succeeds even when the bit is clear. Honor PCI_COMMAND_MASTER by inserting a memory region into the device's bus master address space, and tying its enable status to PCI_COMMAND_MASTER. Tested using setpci -s 03 COMMAND=3 while a ping was running on a NIC in slot 3. The kernel (Linux) detected the stall and recovered after the command setpci -s 03 COMMAND=7 was issued. Signed-off-by: Avi Kivity --- hw/pci.c | 13 +++++++++++-- hw/pci.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index b1415dbce6..7eeaac0d3d 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -782,7 +782,11 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, /* FIXME: Make dma_context_fn use MemoryRegions instead, so this path is * taken unconditionally */ /* FIXME: inherit memory region from bus creator */ - address_space_init(&pci_dev->bus_master_as, get_system_memory()); + memory_region_init_alias(&pci_dev->bus_master_enable_region, "bus master", + get_system_memory(), 0, + memory_region_size(get_system_memory())); + memory_region_set_enabled(&pci_dev->bus_master_enable_region, false); + address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region); pci_dev->dma = g_new(DMAContext, 1); dma_context_init(pci_dev->dma, &pci_dev->bus_master_as, NULL, NULL, NULL); } @@ -841,6 +845,7 @@ static void do_pci_unregister_device(PCIDevice *pci_dev) if (!pci_dev->bus->dma_context_fn) { address_space_destroy(&pci_dev->bus_master_as); + memory_region_destroy(&pci_dev->bus_master_enable_region); g_free(pci_dev->dma); pci_dev->dma = NULL; } @@ -1065,8 +1070,12 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l) range_covers_byte(addr, l, PCI_COMMAND)) pci_update_mappings(d); - if (range_covers_byte(addr, l, PCI_COMMAND)) + if (range_covers_byte(addr, l, PCI_COMMAND)) { pci_update_irq_disabled(d, was_irq_disabled); + memory_region_set_enabled(&d->bus_master_enable_region, + pci_get_word(d->config + PCI_COMMAND) + & PCI_COMMAND_MASTER); + } msi_write_config(d, addr, val, l); msix_write_config(d, addr, val, l); diff --git a/hw/pci.h b/hw/pci.h index f9207ca062..1f902f5b59 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -212,6 +212,7 @@ struct PCIDevice { char name[64]; PCIIORegion io_regions[PCI_NUM_REGIONS]; AddressSpace bus_master_as; + MemoryRegion bus_master_enable_region; DMAContext *dma; /* do not access the following fields */ From ad0b5321f1f797274603ebbe20108b0750baee94 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Fri, 5 Oct 2012 16:47:57 -0300 Subject: [PATCH 1047/2270] Call MADV_HUGEPAGE for guest RAM allocations This makes it possible for QEMU to use transparent huge pages (THP) when transparent_hugepage/enabled=madvise. Otherwise THP is only used when it's enabled system wide. Signed-off-by: Luiz Capitulino Signed-off-by: Anthony Liguori --- exec.c | 1 + osdep.h | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/exec.c b/exec.c index c4ed6fdef1..750008c4e1 100644 --- a/exec.c +++ b/exec.c @@ -2571,6 +2571,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, cpu_physical_memory_set_dirty_range(new_block->offset, size, 0xff); qemu_ram_setup_dump(new_block->host, size); + qemu_madvise(new_block->host, size, QEMU_MADV_HUGEPAGE); if (kvm_enabled()) kvm_setup_guest_memory(new_block->host, size); diff --git a/osdep.h b/osdep.h index cb213e0295..c5fd3d91ff 100644 --- a/osdep.h +++ b/osdep.h @@ -108,6 +108,11 @@ void qemu_vfree(void *ptr); #else #define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID #endif +#ifdef MADV_HUGEPAGE +#define QEMU_MADV_HUGEPAGE MADV_HUGEPAGE +#else +#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID +#endif #elif defined(CONFIG_POSIX_MADVISE) From 488cb996cd8d8eaa5ecfdc6ba5f6cbd23a13271b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 17 Oct 2012 09:54:19 +0200 Subject: [PATCH 1048/2270] serial: split serial.c Split serial.c into serial.c, serial.h and serial-isa.c. While being at creating a serial.h header file move the serial prototypes from pc.h to the new serial.h. The latter leads to s/pc.h/serial.h/ in tons of boards which just want the serial bits from pc.h Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- hw/Makefile.objs | 2 +- hw/alpha_dp264.c | 1 + hw/kzm.c | 2 +- hw/mips_fulong2e.c | 1 + hw/mips_jazz.c | 1 + hw/mips_malta.c | 1 + hw/mips_mipssim.c | 2 +- hw/mips_r4k.c | 1 + hw/musicpal.c | 2 +- hw/omap_uart.c | 3 +- hw/openrisc_sim.c | 3 +- hw/pc.c | 1 + hw/pc.h | 27 -------- hw/petalogix_ml605_mmu.c | 2 +- hw/ppc/e500.c | 2 +- hw/ppc405_uc.c | 2 +- hw/ppc440_bamboo.c | 2 +- hw/ppc_prep.c | 1 + hw/pxa2xx.c | 2 +- hw/serial-isa.c | 130 +++++++++++++++++++++++++++++++++++ hw/serial.c | 143 ++------------------------------------- hw/serial.h | 98 +++++++++++++++++++++++++++ hw/sm501.c | 2 +- hw/sun4u.c | 1 + hw/virtex_ml507.c | 2 +- hw/xtensa_lx60.c | 3 +- 26 files changed, 257 insertions(+), 180 deletions(-) create mode 100644 hw/serial-isa.c create mode 100644 hw/serial.h diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 854faa9b5b..16e7a1e6f3 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -20,7 +20,7 @@ common-obj-$(CONFIG_M48T59) += m48t59.o common-obj-$(CONFIG_ESCC) += escc.o common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o -common-obj-$(CONFIG_SERIAL) += serial.o +common-obj-$(CONFIG_SERIAL) += serial.o serial-isa.o common-obj-$(CONFIG_PARALLEL) += parallel.o common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o common-obj-$(CONFIG_PCSPK) += pcspk.o diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c index 8f082a6656..76d8ae8a84 100644 --- a/hw/alpha_dp264.c +++ b/hw/alpha_dp264.c @@ -15,6 +15,7 @@ #include "mc146818rtc.h" #include "ide.h" #include "i8254.h" +#include "serial.h" #define MAX_IDE_BUS 2 diff --git a/hw/kzm.c b/hw/kzm.c index d1266d9305..687daf3b2c 100644 --- a/hw/kzm.c +++ b/hw/kzm.c @@ -21,7 +21,7 @@ #include "net.h" #include "sysemu.h" #include "boards.h" -#include "pc.h" /* for the FPGA UART that emulates a 16550 */ +#include "serial.h" #include "imx.h" /* Memory map for Kzm Emulation Baseboard: diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c index fb50a1f67b..5fcf900e04 100644 --- a/hw/mips_fulong2e.c +++ b/hw/mips_fulong2e.c @@ -20,6 +20,7 @@ #include "hw.h" #include "pc.h" +#include "serial.h" #include "fdc.h" #include "net.h" #include "boards.h" diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c index 14df4d7745..6bd231dc9b 100644 --- a/hw/mips_jazz.c +++ b/hw/mips_jazz.c @@ -26,6 +26,7 @@ #include "mips.h" #include "mips_cpudevs.h" #include "pc.h" +#include "serial.h" #include "isa.h" #include "fdc.h" #include "sysemu.h" diff --git a/hw/mips_malta.c b/hw/mips_malta.c index ad4910ff66..22ec8b9efa 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -24,6 +24,7 @@ #include "hw.h" #include "pc.h" +#include "serial.h" #include "fdc.h" #include "net.h" #include "boards.h" diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c index a1d3945cbb..a95a3c1f11 100644 --- a/hw/mips_mipssim.c +++ b/hw/mips_mipssim.c @@ -27,7 +27,7 @@ #include "hw.h" #include "mips.h" #include "mips_cpudevs.h" -#include "pc.h" +#include "serial.h" #include "isa.h" #include "net.h" #include "sysemu.h" diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index b73cdc38ec..539577b761 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -11,6 +11,7 @@ #include "mips.h" #include "mips_cpudevs.h" #include "pc.h" +#include "serial.h" #include "isa.h" #include "net.h" #include "sysemu.h" diff --git a/hw/musicpal.c b/hw/musicpal.c index f06814c83b..159d3c3c39 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -15,7 +15,7 @@ #include "net.h" #include "sysemu.h" #include "boards.h" -#include "pc.h" +#include "serial.h" #include "qemu-timer.h" #include "ptimer.h" #include "block.h" diff --git a/hw/omap_uart.c b/hw/omap_uart.c index 167d5c4e50..1c16a54306 100644 --- a/hw/omap_uart.c +++ b/hw/omap_uart.c @@ -20,8 +20,7 @@ #include "qemu-char.h" #include "hw.h" #include "omap.h" -/* We use pc-style serial ports. */ -#include "pc.h" +#include "serial.h" #include "exec-memory.h" /* UARTs */ diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c index e96a94492b..7327740764 100644 --- a/hw/openrisc_sim.c +++ b/hw/openrisc_sim.c @@ -21,7 +21,8 @@ #include "hw.h" #include "boards.h" #include "elf.h" -#include "pc.h" +#include "serial.h" +#include "net.h" #include "loader.h" #include "exec-memory.h" #include "sysemu.h" diff --git a/hw/pc.c b/hw/pc.c index 6c0722db5c..805e8cabcf 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -23,6 +23,7 @@ */ #include "hw.h" #include "pc.h" +#include "serial.h" #include "apic.h" #include "fdc.h" #include "ide.h" diff --git a/hw/pc.h b/hw/pc.h index 9923d96027..6cba7ce7d6 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -12,33 +12,6 @@ /* PC-style peripherals (also used by other machines). */ -/* serial.c */ - -SerialState *serial_init(int base, qemu_irq irq, int baudbase, - CharDriverState *chr); -SerialState *serial_mm_init(MemoryRegion *address_space, - target_phys_addr_t base, int it_shift, - qemu_irq irq, int baudbase, - CharDriverState *chr, enum device_endian); -static inline bool serial_isa_init(ISABus *bus, int index, - CharDriverState *chr) -{ - ISADevice *dev; - - dev = isa_try_create(bus, "isa-serial"); - if (!dev) { - return false; - } - qdev_prop_set_uint32(&dev->qdev, "index", index); - qdev_prop_set_chr(&dev->qdev, "chardev", chr); - if (qdev_init(&dev->qdev) < 0) { - return false; - } - return true; -} - -void serial_set_frequency(SerialState *s, uint32_t frequency); - /* parallel.c */ static inline bool parallel_init(ISABus *bus, int index, CharDriverState *chr) { diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c index 39df25175b..5b45809d74 100644 --- a/hw/petalogix_ml605_mmu.c +++ b/hw/petalogix_ml605_mmu.c @@ -34,7 +34,7 @@ #include "boards.h" #include "xilinx.h" #include "blockdev.h" -#include "pc.h" +#include "serial.h" #include "exec-memory.h" #include "ssi.h" diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index d23f9b2f60..846f53a8d9 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -19,7 +19,7 @@ #include "e500.h" #include "net.h" #include "hw/hw.h" -#include "hw/pc.h" +#include "hw/serial.h" #include "hw/pci.h" #include "hw/boards.h" #include "sysemu.h" diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c index b52ab2f179..e81409dc0f 100644 --- a/hw/ppc405_uc.c +++ b/hw/ppc405_uc.c @@ -24,7 +24,7 @@ #include "hw.h" #include "ppc.h" #include "ppc405.h" -#include "pc.h" +#include "serial.h" #include "qemu-timer.h" #include "sysemu.h" #include "qemu-log.h" diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c index 78e7985305..5616a26b38 100644 --- a/hw/ppc440_bamboo.c +++ b/hw/ppc440_bamboo.c @@ -23,7 +23,7 @@ #include "loader.h" #include "elf.h" #include "exec-memory.h" -#include "pc.h" +#include "serial.h" #include "ppc.h" #include "ppc405.h" #include "sysemu.h" diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index b426891e29..a0d1c3d75d 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -24,6 +24,7 @@ #include "hw.h" #include "nvram.h" #include "pc.h" +#include "serial.h" #include "fdc.h" #include "net.h" #include "sysemu.h" diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c index d5f1420ed9..4ec904ff20 100644 --- a/hw/pxa2xx.c +++ b/hw/pxa2xx.c @@ -10,7 +10,7 @@ #include "sysbus.h" #include "pxa.h" #include "sysemu.h" -#include "pc.h" +#include "serial.h" #include "i2c.h" #include "ssi.h" #include "qemu-char.h" diff --git a/hw/serial-isa.c b/hw/serial-isa.c new file mode 100644 index 0000000000..96c78f7f8d --- /dev/null +++ b/hw/serial-isa.c @@ -0,0 +1,130 @@ +/* + * QEMU 16550A UART emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * Copyright (c) 2008 Citrix Systems, Inc. + * + * 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 "serial.h" +#include "isa.h" + +typedef struct ISASerialState { + ISADevice dev; + uint32_t index; + uint32_t iobase; + uint32_t isairq; + SerialState state; +} ISASerialState; + +static const int isa_serial_io[MAX_SERIAL_PORTS] = { + 0x3f8, 0x2f8, 0x3e8, 0x2e8 +}; +static const int isa_serial_irq[MAX_SERIAL_PORTS] = { + 4, 3, 4, 3 +}; + +static int serial_isa_initfn(ISADevice *dev) +{ + static int index; + ISASerialState *isa = DO_UPCAST(ISASerialState, dev, dev); + SerialState *s = &isa->state; + + if (isa->index == -1) { + isa->index = index; + } + if (isa->index >= MAX_SERIAL_PORTS) { + return -1; + } + if (isa->iobase == -1) { + isa->iobase = isa_serial_io[isa->index]; + } + if (isa->isairq == -1) { + isa->isairq = isa_serial_irq[isa->index]; + } + index++; + + s->baudbase = 115200; + isa_init_irq(dev, &s->irq, isa->isairq); + serial_init_core(s); + qdev_set_legacy_instance_id(&dev->qdev, isa->iobase, 3); + + memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8); + isa_register_ioport(dev, &s->io, isa->iobase); + return 0; +} + +static const VMStateDescription vmstate_isa_serial = { + .name = "serial", + .version_id = 3, + .minimum_version_id = 2, + .fields = (VMStateField[]) { + VMSTATE_STRUCT(state, ISASerialState, 0, vmstate_serial, SerialState), + VMSTATE_END_OF_LIST() + } +}; + +static Property serial_isa_properties[] = { + DEFINE_PROP_UINT32("index", ISASerialState, index, -1), + DEFINE_PROP_HEX32("iobase", ISASerialState, iobase, -1), + DEFINE_PROP_UINT32("irq", ISASerialState, isairq, -1), + DEFINE_PROP_CHR("chardev", ISASerialState, state.chr), + DEFINE_PROP_UINT32("wakeup", ISASerialState, state.wakeup, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void serial_isa_class_initfn(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = serial_isa_initfn; + dc->vmsd = &vmstate_isa_serial; + dc->props = serial_isa_properties; +} + +static TypeInfo serial_isa_info = { + .name = "isa-serial", + .parent = TYPE_ISA_DEVICE, + .instance_size = sizeof(ISASerialState), + .class_init = serial_isa_class_initfn, +}; + +static void serial_register_types(void) +{ + type_register_static(&serial_isa_info); +} + +type_init(serial_register_types) + +bool serial_isa_init(ISABus *bus, int index, CharDriverState *chr) +{ + ISADevice *dev; + + dev = isa_try_create(bus, "isa-serial"); + if (!dev) { + return false; + } + qdev_prop_set_uint32(&dev->qdev, "index", index); + qdev_prop_set_chr(&dev->qdev, "chardev", chr); + if (qdev_init(&dev->qdev) < 0) { + return false; + } + return true; +} diff --git a/hw/serial.c b/hw/serial.c index a421d1e7bc..78e219df5c 100644 --- a/hw/serial.c +++ b/hw/serial.c @@ -22,12 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "hw.h" + +#include "serial.h" #include "qemu-char.h" -#include "isa.h" -#include "pc.h" #include "qemu-timer.h" -#include "sysemu.h" //#define DEBUG_SERIAL @@ -93,8 +91,6 @@ #define UART_FCR_RFR 0x02 /* RCVR Fifo Reset */ #define UART_FCR_FE 0x01 /* FIFO Enable */ -#define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */ - #define XMIT_FIFO 0 #define RECV_FIFO 1 #define MAX_XMIT_RETRY 4 @@ -107,64 +103,6 @@ do { fprintf(stderr, "serial: " fmt , ## __VA_ARGS__); } while (0) do {} while (0) #endif -typedef struct SerialFIFO { - uint8_t data[UART_FIFO_LENGTH]; - uint8_t count; - uint8_t itl; /* Interrupt Trigger Level */ - uint8_t tail; - uint8_t head; -} SerialFIFO; - -struct SerialState { - uint16_t divider; - uint8_t rbr; /* receive register */ - uint8_t thr; /* transmit holding register */ - uint8_t tsr; /* transmit shift register */ - uint8_t ier; - uint8_t iir; /* read only */ - uint8_t lcr; - uint8_t mcr; - uint8_t lsr; /* read only */ - uint8_t msr; /* read only */ - uint8_t scr; - uint8_t fcr; - uint8_t fcr_vmstate; /* we can't write directly this value - it has side effects */ - /* NOTE: this hidden state is necessary for tx irq generation as - it can be reset while reading iir */ - int thr_ipending; - qemu_irq irq; - CharDriverState *chr; - int last_break_enable; - int it_shift; - int baudbase; - int tsr_retry; - uint32_t wakeup; - - uint64_t last_xmit_ts; /* Time when the last byte was successfully sent out of the tsr */ - SerialFIFO recv_fifo; - SerialFIFO xmit_fifo; - - struct QEMUTimer *fifo_timeout_timer; - int timeout_ipending; /* timeout interrupt pending state */ - struct QEMUTimer *transmit_timer; - - - uint64_t char_transmit_time; /* time to transmit a char in ticks*/ - int poll_msl; - - struct QEMUTimer *modem_status_poll; - MemoryRegion io; -}; - -typedef struct ISASerialState { - ISADevice dev; - uint32_t index; - uint32_t iobase; - uint32_t isairq; - SerialState state; -} ISASerialState; - static void serial_receive1(void *opaque, const uint8_t *buf, int size); static void fifo_clear(SerialState *s, int fifo) @@ -687,7 +625,7 @@ static int serial_post_load(void *opaque, int version_id) return 0; } -static const VMStateDescription vmstate_serial = { +const VMStateDescription vmstate_serial = { .name = "serial", .version_id = 3, .minimum_version_id = 2, @@ -736,7 +674,7 @@ static void serial_reset(void *opaque) qemu_irq_lower(s->irq); } -static void serial_init_core(SerialState *s) +void serial_init_core(SerialState *s) { if (!s->chr) { fprintf(stderr, "Can't create serial device, empty char device\n"); @@ -761,54 +699,15 @@ void serial_set_frequency(SerialState *s, uint32_t frequency) serial_update_parameters(s); } -static const int isa_serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; -static const int isa_serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 }; - static const MemoryRegionPortio serial_portio[] = { { 0, 8, 1, .read = serial_ioport_read, .write = serial_ioport_write }, PORTIO_END_OF_LIST() }; -static const MemoryRegionOps serial_io_ops = { +const MemoryRegionOps serial_io_ops = { .old_portio = serial_portio }; -static int serial_isa_initfn(ISADevice *dev) -{ - static int index; - ISASerialState *isa = DO_UPCAST(ISASerialState, dev, dev); - SerialState *s = &isa->state; - - if (isa->index == -1) - isa->index = index; - if (isa->index >= MAX_SERIAL_PORTS) - return -1; - if (isa->iobase == -1) - isa->iobase = isa_serial_io[isa->index]; - if (isa->isairq == -1) - isa->isairq = isa_serial_irq[isa->index]; - index++; - - s->baudbase = 115200; - isa_init_irq(dev, &s->irq, isa->isairq); - serial_init_core(s); - qdev_set_legacy_instance_id(&dev->qdev, isa->iobase, 3); - - memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8); - isa_register_ioport(dev, &s->io, isa->iobase); - return 0; -} - -static const VMStateDescription vmstate_isa_serial = { - .name = "serial", - .version_id = 3, - .minimum_version_id = 2, - .fields = (VMStateField []) { - VMSTATE_STRUCT(state, ISASerialState, 0, vmstate_serial, SerialState), - VMSTATE_END_OF_LIST() - } -}; - SerialState *serial_init(int base, qemu_irq irq, int baudbase, CharDriverState *chr) { @@ -886,35 +785,3 @@ SerialState *serial_mm_init(MemoryRegion *address_space, serial_update_msl(s); return s; } - -static Property serial_isa_properties[] = { - DEFINE_PROP_UINT32("index", ISASerialState, index, -1), - DEFINE_PROP_HEX32("iobase", ISASerialState, iobase, -1), - DEFINE_PROP_UINT32("irq", ISASerialState, isairq, -1), - DEFINE_PROP_CHR("chardev", ISASerialState, state.chr), - DEFINE_PROP_UINT32("wakeup", ISASerialState, state.wakeup, 0), - DEFINE_PROP_END_OF_LIST(), -}; - -static void serial_isa_class_initfn(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); - ic->init = serial_isa_initfn; - dc->vmsd = &vmstate_isa_serial; - dc->props = serial_isa_properties; -} - -static TypeInfo serial_isa_info = { - .name = "isa-serial", - .parent = TYPE_ISA_DEVICE, - .instance_size = sizeof(ISASerialState), - .class_init = serial_isa_class_initfn, -}; - -static void serial_register_types(void) -{ - type_register_static(&serial_isa_info); -} - -type_init(serial_register_types) diff --git a/hw/serial.h b/hw/serial.h new file mode 100644 index 0000000000..6f5293b202 --- /dev/null +++ b/hw/serial.h @@ -0,0 +1,98 @@ +/* + * QEMU 16550A UART emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * Copyright (c) 2008 Citrix Systems, Inc. + * + * 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.h" +#include "sysemu.h" +#include "memory.h" + +#define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */ + +typedef struct SerialFIFO { + uint8_t data[UART_FIFO_LENGTH]; + uint8_t count; + uint8_t itl; /* Interrupt Trigger Level */ + uint8_t tail; + uint8_t head; +} SerialFIFO; + +struct SerialState { + uint16_t divider; + uint8_t rbr; /* receive register */ + uint8_t thr; /* transmit holding register */ + uint8_t tsr; /* transmit shift register */ + uint8_t ier; + uint8_t iir; /* read only */ + uint8_t lcr; + uint8_t mcr; + uint8_t lsr; /* read only */ + uint8_t msr; /* read only */ + uint8_t scr; + uint8_t fcr; + uint8_t fcr_vmstate; /* we can't write directly this value + it has side effects */ + /* NOTE: this hidden state is necessary for tx irq generation as + it can be reset while reading iir */ + int thr_ipending; + qemu_irq irq; + CharDriverState *chr; + int last_break_enable; + int it_shift; + int baudbase; + int tsr_retry; + uint32_t wakeup; + + /* Time when the last byte was successfully sent out of the tsr */ + uint64_t last_xmit_ts; + SerialFIFO recv_fifo; + SerialFIFO xmit_fifo; + + struct QEMUTimer *fifo_timeout_timer; + int timeout_ipending; /* timeout interrupt pending state */ + struct QEMUTimer *transmit_timer; + + + uint64_t char_transmit_time; /* time to transmit a char in ticks */ + int poll_msl; + + struct QEMUTimer *modem_status_poll; + MemoryRegion io; +}; + +extern const VMStateDescription vmstate_serial; +extern const MemoryRegionOps serial_io_ops; + +void serial_init_core(SerialState *s); +void serial_set_frequency(SerialState *s, uint32_t frequency); + +/* legacy pre qom */ +SerialState *serial_init(int base, qemu_irq irq, int baudbase, + CharDriverState *chr); +SerialState *serial_mm_init(MemoryRegion *address_space, + target_phys_addr_t base, int it_shift, + qemu_irq irq, int baudbase, + CharDriverState *chr, enum device_endian end); + +/* serial-isa.c */ +bool serial_isa_init(ISABus *bus, int index, CharDriverState *chr); diff --git a/hw/sm501.c b/hw/sm501.c index 786e07629c..050d096533 100644 --- a/hw/sm501.c +++ b/hw/sm501.c @@ -24,7 +24,7 @@ #include #include "hw.h" -#include "pc.h" +#include "serial.h" #include "console.h" #include "devices.h" #include "sysbus.h" diff --git a/hw/sun4u.c b/hw/sun4u.c index abf68cf50f..eeb6496092 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -25,6 +25,7 @@ #include "pci.h" #include "apb_pci.h" #include "pc.h" +#include "serial.h" #include "nvram.h" #include "fdc.h" #include "net.h" diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c index a09b27a346..c59e1cb4e4 100644 --- a/hw/virtex_ml507.c +++ b/hw/virtex_ml507.c @@ -24,7 +24,7 @@ #include "sysbus.h" #include "hw.h" -#include "pc.h" +#include "serial.h" #include "net.h" #include "flash.h" #include "sysemu.h" diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c index 1fd2c47ac5..0c407d37b7 100644 --- a/hw/xtensa_lx60.c +++ b/hw/xtensa_lx60.c @@ -31,7 +31,8 @@ #include "elf.h" #include "memory.h" #include "exec-memory.h" -#include "pc.h" +#include "serial.h" +#include "net.h" #include "sysbus.h" #include "flash.h" #include "blockdev.h" From 419ad67208a37367932a5bf88d3860f85e06282c Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 17 Oct 2012 09:54:20 +0200 Subject: [PATCH 1049/2270] serial: add pci variant So we get a hot-pluggable 16550 uart. Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- default-configs/pci.mak | 2 + hw/Makefile.objs | 1 + hw/pci_ids.h | 1 + hw/serial-pci.c | 101 ++++++++++++++++++++++++++++++++++++++++ hw/serial.c | 6 +++ hw/serial.h | 1 + 6 files changed, 112 insertions(+) create mode 100644 hw/serial-pci.c diff --git a/default-configs/pci.mak b/default-configs/pci.mak index 69e18f1428..ae9d1eb487 100644 --- a/default-configs/pci.mak +++ b/default-configs/pci.mak @@ -19,3 +19,5 @@ CONFIG_IDE_PCI=y CONFIG_AHCI=y CONFIG_ESP=y CONFIG_ESP_PCI=y +CONFIG_SERIAL=y +CONFIG_SERIAL_PCI=y diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 16e7a1e6f3..af4ab0c735 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -21,6 +21,7 @@ common-obj-$(CONFIG_ESCC) += escc.o common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o common-obj-$(CONFIG_SERIAL) += serial.o serial-isa.o +common-obj-$(CONFIG_SERIAL_PCI) += serial-pci.o common-obj-$(CONFIG_PARALLEL) += parallel.o common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o common-obj-$(CONFIG_PCSPK) += pcspk.o diff --git a/hw/pci_ids.h b/hw/pci_ids.h index 301bf1cd86..c017a79998 100644 --- a/hw/pci_ids.h +++ b/hw/pci_ids.h @@ -37,6 +37,7 @@ #define PCI_CLASS_BRIDGE_PCI 0x0604 #define PCI_CLASS_BRIDGE_OTHER 0x0680 +#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700 #define PCI_CLASS_COMMUNICATION_OTHER 0x0780 #define PCI_CLASS_PROCESSOR_CO 0x0b40 diff --git a/hw/serial-pci.c b/hw/serial-pci.c new file mode 100644 index 0000000000..6fcf1170b3 --- /dev/null +++ b/hw/serial-pci.c @@ -0,0 +1,101 @@ +/* + * QEMU 16550A UART emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * Copyright (c) 2008 Citrix Systems, Inc. + * + * 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 "serial.h" +#include "pci.h" + +typedef struct PCISerialState { + PCIDevice dev; + SerialState state; +} PCISerialState; + +static int serial_pci_init(PCIDevice *dev) +{ + PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev); + SerialState *s = &pci->state; + + s->baudbase = 115200; + serial_init_core(s); + + pci->dev.config[PCI_INTERRUPT_PIN] = 0x01; + s->irq = pci->dev.irq[0]; + + memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8); + pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io); + return 0; +} + +static void serial_pci_exit(PCIDevice *dev) +{ + PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev); + SerialState *s = &pci->state; + + serial_exit_core(s); + memory_region_destroy(&s->io); +} + +static const VMStateDescription vmstate_pci_serial = { + .name = "pci-serial", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE(dev, PCISerialState), + VMSTATE_STRUCT(state, PCISerialState, 0, vmstate_serial, SerialState), + VMSTATE_END_OF_LIST() + } +}; + +static Property serial_pci_properties[] = { + DEFINE_PROP_CHR("chardev", PCISerialState, state.chr), + DEFINE_PROP_END_OF_LIST(), +}; + +static void serial_pci_class_initfn(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass); + pc->init = serial_pci_init; + pc->exit = serial_pci_exit; + pc->vendor_id = 0x1b36; /* Red Hat */ + pc->device_id = 0x0002; + pc->revision = 1; + pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL; + dc->vmsd = &vmstate_pci_serial; + dc->props = serial_pci_properties; +} + +static TypeInfo serial_pci_info = { + .name = "pci-serial", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(PCISerialState), + .class_init = serial_pci_class_initfn, +}; + +static void serial_pci_register_types(void) +{ + type_register_static(&serial_pci_info); +} + +type_init(serial_pci_register_types) diff --git a/hw/serial.c b/hw/serial.c index 78e219df5c..5adbfafde5 100644 --- a/hw/serial.c +++ b/hw/serial.c @@ -692,6 +692,12 @@ void serial_init_core(SerialState *s) serial_event, s); } +void serial_exit_core(SerialState *s) +{ + qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL); + qemu_unregister_reset(serial_reset, s); +} + /* Change the main reference oscillator frequency. */ void serial_set_frequency(SerialState *s, uint32_t frequency) { diff --git a/hw/serial.h b/hw/serial.h index 6f5293b202..55a1ac5e9b 100644 --- a/hw/serial.h +++ b/hw/serial.h @@ -84,6 +84,7 @@ extern const VMStateDescription vmstate_serial; extern const MemoryRegionOps serial_io_ops; void serial_init_core(SerialState *s); +void serial_exit_core(SerialState *s); void serial_set_frequency(SerialState *s, uint32_t frequency); /* legacy pre qom */ From fe4f1793a6bd9fdd008a17aa695a2670ff438bb5 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 17 Oct 2012 09:54:21 +0200 Subject: [PATCH 1050/2270] serial: add windows inf file for the pci card to docs Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- docs/qemupciserial.inf | 109 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 docs/qemupciserial.inf diff --git a/docs/qemupciserial.inf b/docs/qemupciserial.inf new file mode 100644 index 0000000000..3474310a4b --- /dev/null +++ b/docs/qemupciserial.inf @@ -0,0 +1,109 @@ +; qemupciserial.inf for QEMU, based on MSPORTS.INF + +; The driver itself is shipped with Windows (serial.sys). This is +; just a inf file to tell windows which pci id the serial pci card +; emulated by qemu has, and to apply a name tag to it which windows +; will show in the device manager. + +; Installing the driver: Go to device manager. You should find a "pci +; serial card" tagged with a yellow question mark. Open properties. +; Pick "update driver". Then "select driver manually". Pick "Ports +; (Com+Lpt)" from the list. Click "Have a disk". Select this file. +; Procedure may vary a bit depending on the windows version. + +; FIXME: This file covers the single port version only. + +[Version] +Signature="$CHICAGO$" +Class=Ports +ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} +Provider=%QEMU% +DriverVer=09/24/2012,1.3.0 + +[SourceDisksNames] +3426=windows cd + +[SourceDisksFiles] +serial.sys = 3426 +serenum.sys = 3426 + +[DestinationDirs] +DefaultDestDir = 11 ;LDID_SYS +ComPort.NT.Copy = 12 ;DIRID_DRIVERS +SerialEnumerator.NT.Copy=12 ;DIRID_DRIVERS + +; Drivers +;---------------------------------------------------------- +[Manufacturer] +%QEMU%=QEMU,NTx86 + +[QEMU.NTx86] +%QEMU-PCI_SERIAL.DeviceDesc% = ComPort, "PCI\VEN_1b36&DEV_0002&CC_0700" + +; COM sections +;---------------------------------------------------------- +[ComPort.AddReg] +HKR,,PortSubClass,1,01 + +[ComPort.NT] +AddReg=ComPort.AddReg, ComPort.NT.AddReg +LogConfig=caa +SyssetupPnPFlags = 1 + +[ComPort.NT.HW] +AddReg=ComPort.NT.HW.AddReg + +[ComPort.NT.AddReg] +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[ComPort.NT.HW.AddReg] +HKR,,"UpperFilters",0x00010000,"serenum" + +;-------------- Service installation +; Port Driver (function driver for this device) +[ComPort.NT.Services] +AddService = Serial, 0x00000002, Serial_Service_Inst, Serial_EventLog_Inst +AddService = Serenum,,Serenum_Service_Inst + +; -------------- Serial Port Driver install sections +[Serial_Service_Inst] +DisplayName = %Serial.SVCDESC% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 1 ; SERVICE_SYSTEM_START (this driver may do detection) +ErrorControl = 0 ; SERVICE_ERROR_IGNORE +ServiceBinary = %12%\serial.sys +LoadOrderGroup = Extended base + +; -------------- Serenum Driver install section +[Serenum_Service_Inst] +DisplayName = %Serenum.SVCDESC% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %12%\serenum.sys +LoadOrderGroup = PNP Filter + +[Serial_EventLog_Inst] +AddReg = Serial_EventLog_AddReg + +[Serial_EventLog_AddReg] +HKR,,EventMessageFile,0x00020000,"%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot%%\System32\drivers\serial.sys" +HKR,,TypesSupported,0x00010001,7 + +; The following sections are COM port resource configs. +; Section name format means: +; Char 1 = c (COM port) +; Char 2 = I/O config: 1 (3f8), 2 (2f8), 3 (3e8), 4 (2e8), a (any) +; Char 3 = IRQ config: #, a (any) + +[caa] ; Any base, any IRQ +ConfigPriority=HARDRECONFIG +IOConfig=8@100-ffff%fff8(3ff::) +IRQConfig=S:3,4,5,7,9,10,11,12,14,15 + +[Strings] +QEMU="QEMU" +QEMU-PCI_SERIAL.DeviceDesc="QEMU Serial PCI Card" + +Serial.SVCDESC = "Serial port driver" +Serenum.SVCDESC = "Serenum Filter Driver" From d66bbea4e0d3faec69e8aa73789a2d1dc3b8312f Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 17 Oct 2012 09:54:22 +0200 Subject: [PATCH 1051/2270] serial: add 2x + 4x pci variant Add multiport serial card implementation, with two variants, one featuring two and one featuring four ports. Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- hw/serial-pci.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/hw/serial-pci.c b/hw/serial-pci.c index 6fcf1170b3..badd297220 100644 --- a/hw/serial-pci.c +++ b/hw/serial-pci.c @@ -26,11 +26,23 @@ #include "serial.h" #include "pci.h" +#define PCI_SERIAL_MAX_PORTS 4 + typedef struct PCISerialState { PCIDevice dev; SerialState state; } PCISerialState; +typedef struct PCIMultiSerialState { + PCIDevice dev; + MemoryRegion iobar; + uint32_t ports; + char *name[PCI_SERIAL_MAX_PORTS]; + SerialState state[PCI_SERIAL_MAX_PORTS]; + uint32_t level[PCI_SERIAL_MAX_PORTS]; + qemu_irq *irqs; +} PCIMultiSerialState; + static int serial_pci_init(PCIDevice *dev) { PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev); @@ -47,6 +59,56 @@ static int serial_pci_init(PCIDevice *dev) return 0; } +static void multi_serial_irq_mux(void *opaque, int n, int level) +{ + PCIMultiSerialState *pci = opaque; + int i, pending = 0; + + pci->level[n] = level; + for (i = 0; i < pci->ports; i++) { + if (pci->level[i]) { + pending = 1; + } + } + qemu_set_irq(pci->dev.irq[0], pending); +} + +static int multi_serial_pci_init(PCIDevice *dev) +{ + PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); + PCIMultiSerialState *pci = DO_UPCAST(PCIMultiSerialState, dev, dev); + SerialState *s; + int i; + + switch (pc->device_id) { + case 0x0003: + pci->ports = 2; + break; + case 0x0004: + pci->ports = 4; + break; + } + assert(pci->ports > 0); + assert(pci->ports <= PCI_SERIAL_MAX_PORTS); + + pci->dev.config[PCI_INTERRUPT_PIN] = 0x01; + memory_region_init(&pci->iobar, "multiserial", 8 * pci->ports); + pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->iobar); + pci->irqs = qemu_allocate_irqs(multi_serial_irq_mux, pci, + pci->ports); + + for (i = 0; i < pci->ports; i++) { + s = pci->state + i; + s->baudbase = 115200; + serial_init_core(s); + s->irq = pci->irqs[i]; + pci->name[i] = g_strdup_printf("uart #%d", i+1); + memory_region_init_io(&s->io, &serial_io_ops, s, pci->name[i], 8); + memory_region_add_subregion(&pci->iobar, 8 * i, &s->io); + } + return 0; +} + static void serial_pci_exit(PCIDevice *dev) { PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev); @@ -56,6 +118,22 @@ static void serial_pci_exit(PCIDevice *dev) memory_region_destroy(&s->io); } +static void multi_serial_pci_exit(PCIDevice *dev) +{ + PCIMultiSerialState *pci = DO_UPCAST(PCIMultiSerialState, dev, dev); + SerialState *s; + int i; + + for (i = 0; i < pci->ports; i++) { + s = pci->state + i; + serial_exit_core(s); + memory_region_destroy(&s->io); + g_free(pci->name[i]); + } + memory_region_destroy(&pci->iobar); + qemu_free_irqs(pci->irqs); +} + static const VMStateDescription vmstate_pci_serial = { .name = "pci-serial", .version_id = 1, @@ -67,11 +145,38 @@ static const VMStateDescription vmstate_pci_serial = { } }; +static const VMStateDescription vmstate_pci_multi_serial = { + .name = "pci-serial-multi", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE(dev, PCIMultiSerialState), + VMSTATE_STRUCT_ARRAY(state, PCIMultiSerialState, PCI_SERIAL_MAX_PORTS, + 0, vmstate_serial, SerialState), + VMSTATE_UINT32_ARRAY(level, PCIMultiSerialState, PCI_SERIAL_MAX_PORTS), + VMSTATE_END_OF_LIST() + } +}; + static Property serial_pci_properties[] = { DEFINE_PROP_CHR("chardev", PCISerialState, state.chr), DEFINE_PROP_END_OF_LIST(), }; +static Property multi_2x_serial_pci_properties[] = { + DEFINE_PROP_CHR("chardev1", PCIMultiSerialState, state[0].chr), + DEFINE_PROP_CHR("chardev2", PCIMultiSerialState, state[1].chr), + DEFINE_PROP_END_OF_LIST(), +}; + +static Property multi_4x_serial_pci_properties[] = { + DEFINE_PROP_CHR("chardev1", PCIMultiSerialState, state[0].chr), + DEFINE_PROP_CHR("chardev2", PCIMultiSerialState, state[1].chr), + DEFINE_PROP_CHR("chardev3", PCIMultiSerialState, state[2].chr), + DEFINE_PROP_CHR("chardev4", PCIMultiSerialState, state[3].chr), + DEFINE_PROP_END_OF_LIST(), +}; + static void serial_pci_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -86,6 +191,34 @@ static void serial_pci_class_initfn(ObjectClass *klass, void *data) dc->props = serial_pci_properties; } +static void multi_2x_serial_pci_class_initfn(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass); + pc->init = multi_serial_pci_init; + pc->exit = multi_serial_pci_exit; + pc->vendor_id = 0x1b36; /* Red Hat */ + pc->device_id = 0x0003; + pc->revision = 1; + pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL; + dc->vmsd = &vmstate_pci_multi_serial; + dc->props = multi_2x_serial_pci_properties; +} + +static void multi_4x_serial_pci_class_initfn(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass); + pc->init = multi_serial_pci_init; + pc->exit = multi_serial_pci_exit; + pc->vendor_id = 0x1b36; /* Red Hat */ + pc->device_id = 0x0004; + pc->revision = 1; + pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL; + dc->vmsd = &vmstate_pci_multi_serial; + dc->props = multi_4x_serial_pci_properties; +} + static TypeInfo serial_pci_info = { .name = "pci-serial", .parent = TYPE_PCI_DEVICE, @@ -93,9 +226,25 @@ static TypeInfo serial_pci_info = { .class_init = serial_pci_class_initfn, }; +static TypeInfo multi_2x_serial_pci_info = { + .name = "pci-serial-2x", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(PCIMultiSerialState), + .class_init = multi_2x_serial_pci_class_initfn, +}; + +static TypeInfo multi_4x_serial_pci_info = { + .name = "pci-serial-4x", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(PCIMultiSerialState), + .class_init = multi_4x_serial_pci_class_initfn, +}; + static void serial_pci_register_types(void) { type_register_static(&serial_pci_info); + type_register_static(&multi_2x_serial_pci_info); + type_register_static(&multi_4x_serial_pci_info); } type_init(serial_pci_register_types) From 90734e02bd2fb137346d4184cec6c5d26e68f29b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 17 Oct 2012 09:54:23 +0200 Subject: [PATCH 1052/2270] serial: add pci-serial documentation Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- docs/specs/pci-serial.txt | 34 ++++++++++++++++++++++++++++++++++ hw/serial-pci.c | 2 ++ 2 files changed, 36 insertions(+) create mode 100644 docs/specs/pci-serial.txt diff --git a/docs/specs/pci-serial.txt b/docs/specs/pci-serial.txt new file mode 100644 index 0000000000..66c761f2b4 --- /dev/null +++ b/docs/specs/pci-serial.txt @@ -0,0 +1,34 @@ + +QEMU pci serial devices +======================= + +There is one single-port variant and two muliport-variants. Linux +guests out-of-the box with all cards. There is a Windows inf file +(docs/qemupciserial.inf) to setup the single-port card in Windows +guests. + + +single-port card +---------------- + +Name: pci-serial +PCI ID: 1b36:0002 + +PCI Region 0: + IO bar, 8 bytes long, with the 16550 uart mapped to it. + Interrupt is wired to pin A. + + +multiport cards +--------------- + +Name: pci-serial-2x +PCI ID: 1b36:0003 + +Name: pci-serial-4x +PCI ID: 1b36:0004 + +PCI Region 0: + IO bar, with two/four 16550 uart mapped after each other. + The first is at offset 0, second at offset 8, ... + Interrupt is wired to pin A. diff --git a/hw/serial-pci.c b/hw/serial-pci.c index badd297220..95dc5c8d2f 100644 --- a/hw/serial-pci.c +++ b/hw/serial-pci.c @@ -23,6 +23,8 @@ * THE SOFTWARE. */ +/* see docs/specs/pci-serial.txt */ + #include "serial.h" #include "pci.h" From 70330fb3daa2ee295cc5c6f40133e8f8db47856d Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 17 Oct 2012 09:54:24 +0200 Subject: [PATCH 1053/2270] usb-serial: don't magically zap chardev on umplug Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- hw/usb/dev-serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 69b6e48d5a..43214cdd9c 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -421,7 +421,7 @@ static void usb_serial_handle_destroy(USBDevice *dev) { USBSerialState *s = (USBSerialState *)dev; - qemu_chr_delete(s->cs); + qemu_chr_add_handlers(s->cs, NULL, NULL, NULL, NULL); } static int usb_serial_can_read(void *opaque) From da124e62de2109a312e21d85d6a3419774c58948 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 17 Oct 2012 09:54:25 +0200 Subject: [PATCH 1054/2270] usb-serial: only expose device in guest when the chardev is open Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- hw/usb/dev-serial.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 43214cdd9c..a466f9929c 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -427,6 +427,10 @@ static void usb_serial_handle_destroy(USBDevice *dev) static int usb_serial_can_read(void *opaque) { USBSerialState *s = opaque; + + if (!s->dev.attached) { + return 0; + } return RECV_BUF - s->recv_used; } @@ -469,8 +473,14 @@ static void usb_serial_event(void *opaque, int event) case CHR_EVENT_FOCUS: break; case CHR_EVENT_OPENED: - usb_serial_reset(s); - /* TODO: Reset USB port */ + if (!s->dev.attached) { + usb_device_attach(&s->dev); + } + break; + case CHR_EVENT_CLOSED: + if (s->dev.attached) { + usb_device_detach(&s->dev); + } break; } } @@ -481,6 +491,7 @@ static int usb_serial_initfn(USBDevice *dev) usb_desc_create_serial(dev); usb_desc_init(dev); + dev->auto_attach = 0; if (!s->cs) { error_report("Property chardev is required"); @@ -490,6 +501,10 @@ static int usb_serial_initfn(USBDevice *dev) qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read, usb_serial_event, s); usb_serial_handle_reset(dev); + + if (s->cs->opened && !dev->attached) { + usb_device_attach(dev); + } return 0; } From 680d16dcb79f999fad3a652c5190d6a5c6ea10dd Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 2 Oct 2012 09:00:45 +0200 Subject: [PATCH 1055/2270] error: add error_set_errno and error_setg_errno These functions help maintaining homogeneous formatting of error messages that include strerror values. Acked-by: Luiz Capitulino Signed-off-by: Paolo Bonzini --- error.c | 28 ++++++++++++++++++++++++++++ error.h | 9 +++++++++ 2 files changed, 37 insertions(+) diff --git a/error.c b/error.c index 1f05fc466e..128d88cd91 100644 --- a/error.c +++ b/error.c @@ -43,6 +43,34 @@ void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...) *errp = err; } +void error_set_errno(Error **errp, int os_errno, ErrorClass err_class, + const char *fmt, ...) +{ + Error *err; + char *msg1; + va_list ap; + + if (errp == NULL) { + return; + } + assert(*errp == NULL); + + err = g_malloc0(sizeof(*err)); + + va_start(ap, fmt); + msg1 = g_strdup_vprintf(fmt, ap); + if (os_errno != 0) { + err->msg = g_strdup_printf("%s: %s", msg1, strerror(os_errno)); + g_free(msg1); + } else { + err->msg = msg1; + } + va_end(ap); + err->err_class = err_class; + + *errp = err; +} + Error *error_copy(const Error *err) { Error *err_new; diff --git a/error.h b/error.h index da7fed399e..4d52e7369e 100644 --- a/error.h +++ b/error.h @@ -29,11 +29,20 @@ typedef struct Error Error; */ void error_set(Error **err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(3, 4); +/** + * Set an indirect pointer to an error given a ErrorClass value and a + * printf-style human message, followed by a strerror() string if + * @os_error is not zero. + */ +void error_set_errno(Error **err, int os_error, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(4, 5); + /** * Same as error_set(), but sets a generic error */ #define error_setg(err, fmt, ...) \ error_set(err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__) +#define error_setg_errno(err, os_error, fmt, ...) \ + error_set_errno(err, os_error, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__) /** * Returns true if an indirect pointer to an error is pointing to a valid From 7fc4e63ec018a0ef6d420ddb7f6cbf68387d4995 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 2 Oct 2012 09:35:32 +0200 Subject: [PATCH 1056/2270] qemu-sockets: add Error ** to all functions This lets me adjust the clients to do proper error propagation first, thus avoiding temporary regressions in the quality of the error messages. Reviewed-by: Luiz Capitulino Signed-off-by: Paolo Bonzini --- nbd.c | 4 ++-- qemu-char.c | 6 +++--- qemu-sockets.c | 22 +++++++++++----------- qemu_socket.h | 10 +++++----- qga/channel-posix.c | 2 +- ui/vnc.c | 4 ++-- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/nbd.c b/nbd.c index 6f0db62deb..f61a288369 100644 --- a/nbd.c +++ b/nbd.c @@ -230,12 +230,12 @@ int unix_socket_incoming(const char *path) char *ostr = NULL; int olen = 0; - return unix_listen(path, ostr, olen); + return unix_listen(path, ostr, olen, NULL); } int unix_socket_outgoing(const char *path) { - return unix_connect(path); + return unix_connect(path, NULL); } /* Basic flow for negotiation diff --git a/qemu-char.c b/qemu-char.c index b082bae11b..3cc6cb52ee 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2102,7 +2102,7 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts) chr = g_malloc0(sizeof(CharDriverState)); s = g_malloc0(sizeof(NetCharDriver)); - fd = inet_dgram_opts(opts); + fd = inet_dgram_opts(opts, NULL); if (fd < 0) { fprintf(stderr, "inet_dgram_opts failed\n"); goto return_err; @@ -2448,9 +2448,9 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) if (is_unix) { if (is_listen) { - fd = unix_listen_opts(opts); + fd = unix_listen_opts(opts, NULL); } else { - fd = unix_connect_opts(opts); + fd = unix_connect_opts(opts, NULL); } } else { if (is_listen) { diff --git a/qemu-sockets.c b/qemu-sockets.c index 2b1ed2f0e9..7f0d4be323 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -403,7 +403,7 @@ int inet_connect_opts(QemuOpts *opts, Error **errp, return sock; } -int inet_dgram_opts(QemuOpts *opts) +int inet_dgram_opts(QemuOpts *opts, Error **errp) { struct addrinfo ai, *peer = NULL, *local = NULL; const char *addr; @@ -653,7 +653,7 @@ int inet_nonblocking_connect(const char *str, #ifndef _WIN32 -int unix_listen_opts(QemuOpts *opts) +int unix_listen_opts(QemuOpts *opts, Error **errp) { struct sockaddr_un un; const char *path = qemu_opt_get(opts, "path"); @@ -701,7 +701,7 @@ err: return -1; } -int unix_connect_opts(QemuOpts *opts) +int unix_connect_opts(QemuOpts *opts, Error **errp) { struct sockaddr_un un; const char *path = qemu_opt_get(opts, "path"); @@ -731,7 +731,7 @@ int unix_connect_opts(QemuOpts *opts) } /* compatibility wrapper */ -int unix_listen(const char *str, char *ostr, int olen) +int unix_listen(const char *str, char *ostr, int olen, Error **errp) { QemuOpts *opts; char *path, *optstr; @@ -752,7 +752,7 @@ int unix_listen(const char *str, char *ostr, int olen) qemu_opt_set(opts, "path", str); } - sock = unix_listen_opts(opts); + sock = unix_listen_opts(opts, errp); if (sock != -1 && ostr) snprintf(ostr, olen, "%s%s", qemu_opt_get(opts, "path"), optstr ? optstr : ""); @@ -760,42 +760,42 @@ int unix_listen(const char *str, char *ostr, int olen) return sock; } -int unix_connect(const char *path) +int unix_connect(const char *path, Error **errp) { QemuOpts *opts; int sock; opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); qemu_opt_set(opts, "path", path); - sock = unix_connect_opts(opts); + sock = unix_connect_opts(opts, errp); qemu_opts_del(opts); return sock; } #else -int unix_listen_opts(QemuOpts *opts) +int unix_listen_opts(QemuOpts *opts, Error **errp) { fprintf(stderr, "unix sockets are not available on windows\n"); errno = ENOTSUP; return -1; } -int unix_connect_opts(QemuOpts *opts) +int unix_connect_opts(QemuOpts *opts, Error **errp) { fprintf(stderr, "unix sockets are not available on windows\n"); errno = ENOTSUP; return -1; } -int unix_listen(const char *path, char *ostr, int olen) +int unix_listen(const char *path, char *ostr, int olen, Error **errp) { fprintf(stderr, "unix sockets are not available on windows\n"); errno = ENOTSUP; return -1; } -int unix_connect(const char *path) +int unix_connect(const char *path, Error **errp) { fprintf(stderr, "unix sockets are not available on windows\n"); errno = ENOTSUP; diff --git a/qemu_socket.h b/qemu_socket.h index 3e8aee9cad..ff979b5cd6 100644 --- a/qemu_socket.h +++ b/qemu_socket.h @@ -53,13 +53,13 @@ int inet_nonblocking_connect(const char *str, NonBlockingConnectHandler *callback, void *opaque, Error **errp); -int inet_dgram_opts(QemuOpts *opts); +int inet_dgram_opts(QemuOpts *opts, Error **errp); const char *inet_strfamily(int family); -int unix_listen_opts(QemuOpts *opts); -int unix_listen(const char *path, char *ostr, int olen); -int unix_connect_opts(QemuOpts *opts); -int unix_connect(const char *path); +int unix_listen_opts(QemuOpts *opts, Error **errp); +int unix_listen(const char *path, char *ostr, int olen, Error **errp); +int unix_connect_opts(QemuOpts *opts, Error **errp); +int unix_connect(const char *path, Error **errp); /* Old, ipv4 only bits. Don't use for new code. */ int parse_host_port(struct sockaddr_in *saddr, const char *str); diff --git a/qga/channel-posix.c b/qga/channel-posix.c index 57eea06c47..e22eee6f67 100644 --- a/qga/channel-posix.c +++ b/qga/channel-posix.c @@ -181,7 +181,7 @@ static gboolean ga_channel_open(GAChannel *c, const gchar *path, GAChannelMethod break; } case GA_CHANNEL_UNIX_LISTEN: { - int fd = unix_listen(path, NULL, strlen(path)); + int fd = unix_listen(path, NULL, strlen(path), NULL); if (fd == -1) { g_critical("error opening path: %s", strerror(errno)); return false; diff --git a/ui/vnc.c b/ui/vnc.c index 66ae93010f..ceade57ce3 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -3065,7 +3065,7 @@ int vnc_display_open(DisplayState *ds, const char *display) if (reverse) { /* connect to viewer */ if (strncmp(display, "unix:", 5) == 0) - vs->lsock = unix_connect(display+5); + vs->lsock = unix_connect(display+5, NULL); else vs->lsock = inet_connect(display, NULL); if (-1 == vs->lsock) { @@ -3085,7 +3085,7 @@ int vnc_display_open(DisplayState *ds, const char *display) dpy = g_malloc(256); if (strncmp(display, "unix:", 5) == 0) { pstrcpy(dpy, 256, "unix:"); - vs->lsock = unix_listen(display+5, dpy+5, 256-5); + vs->lsock = unix_listen(display+5, dpy+5, 256-5, NULL); } else { vs->lsock = inet_listen(display, dpy, 256, SOCK_STREAM, 5900, NULL); From 0c814709471ac8a9617406e1e2cbd7015e97bfe9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Oct 2012 08:44:00 +0200 Subject: [PATCH 1057/2270] qemu-sockets: unix_listen and unix_connect are portable They are just wrappers and do not need a Win32-specific version. Reviewed-by: Luiz Capitulino Signed-off-by: Paolo Bonzini --- qemu-sockets.c | 49 +++++++++++++++++-------------------------------- 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/qemu-sockets.c b/qemu-sockets.c index 7f0d4be323..7bf756d07e 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -730,6 +730,23 @@ int unix_connect_opts(QemuOpts *opts, Error **errp) return sock; } +#else + +int unix_listen_opts(QemuOpts *opts, Error **errp) +{ + fprintf(stderr, "unix sockets are not available on windows\n"); + errno = ENOTSUP; + return -1; +} + +int unix_connect_opts(QemuOpts *opts, Error **errp) +{ + fprintf(stderr, "unix sockets are not available on windows\n"); + errno = ENOTSUP; + return -1; +} +#endif + /* compatibility wrapper */ int unix_listen(const char *str, char *ostr, int olen, Error **errp) { @@ -772,38 +789,6 @@ int unix_connect(const char *path, Error **errp) return sock; } -#else - -int unix_listen_opts(QemuOpts *opts, Error **errp) -{ - fprintf(stderr, "unix sockets are not available on windows\n"); - errno = ENOTSUP; - return -1; -} - -int unix_connect_opts(QemuOpts *opts, Error **errp) -{ - fprintf(stderr, "unix sockets are not available on windows\n"); - errno = ENOTSUP; - return -1; -} - -int unix_listen(const char *path, char *ostr, int olen, Error **errp) -{ - fprintf(stderr, "unix sockets are not available on windows\n"); - errno = ENOTSUP; - return -1; -} - -int unix_connect(const char *path, Error **errp) -{ - fprintf(stderr, "unix sockets are not available on windows\n"); - errno = ENOTSUP; - return -1; -} - -#endif - #ifdef _WIN32 static void socket_cleanup(void) { From 1fc05adfa0f79a1268f7c2b7fb324f15eb63dceb Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 3 Oct 2012 13:37:46 +0200 Subject: [PATCH 1058/2270] qemu-sockets: add nonblocking connect for Unix sockets This patch mostly mimics what was done to TCP sockets, but simpler because there is only one address to try. It also includes a free EINTR bug fix. Signed-off-by: Paolo Bonzini --- qemu-char.c | 2 +- qemu-sockets.c | 81 ++++++++++++++++++++++++++++++++++++++++---------- qemu_socket.h | 6 +++- 3 files changed, 72 insertions(+), 17 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 3cc6cb52ee..8ebd5827d9 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2450,7 +2450,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) if (is_listen) { fd = unix_listen_opts(opts, NULL); } else { - fd = unix_connect_opts(opts, NULL); + fd = unix_connect_opts(opts, NULL, NULL, NULL); } } else { if (is_listen) { diff --git a/qemu-sockets.c b/qemu-sockets.c index 7bf756d07e..d510ad1332 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -252,16 +252,19 @@ static void wait_for_connect(void *opaque) } /* try to connect to the next address on the list */ - while (s->current_addr->ai_next != NULL && s->fd < 0) { - s->current_addr = s->current_addr->ai_next; - s->fd = inet_connect_addr(s->current_addr, &in_progress, s); - /* connect in progress */ - if (in_progress) { - return; + if (s->current_addr) { + while (s->current_addr->ai_next != NULL && s->fd < 0) { + s->current_addr = s->current_addr->ai_next; + s->fd = inet_connect_addr(s->current_addr, &in_progress, s); + /* connect in progress */ + if (in_progress) { + return; + } } + + freeaddrinfo(s->addr_list); } - freeaddrinfo(s->addr_list); if (s->callback) { s->callback(s->fd, s->opaque); } @@ -701,11 +704,13 @@ err: return -1; } -int unix_connect_opts(QemuOpts *opts, Error **errp) +int unix_connect_opts(QemuOpts *opts, Error **errp, + NonBlockingConnectHandler *callback, void *opaque) { struct sockaddr_un un; const char *path = qemu_opt_get(opts, "path"); - int sock; + ConnectState *connect_state = NULL; + int sock, rc; if (NULL == path) { fprintf(stderr, "unix connect: no path specified\n"); @@ -717,16 +722,44 @@ int unix_connect_opts(QemuOpts *opts, Error **errp) perror("socket(unix)"); return -1; } + if (callback != NULL) { + connect_state = g_malloc0(sizeof(*connect_state)); + connect_state->callback = callback; + connect_state->opaque = opaque; + socket_set_nonblock(sock); + } memset(&un, 0, sizeof(un)); un.sun_family = AF_UNIX; snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); - if (connect(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { - fprintf(stderr, "connect(unix:%s): %s\n", path, strerror(errno)); - close(sock); - return -1; + + /* connect to peer */ + do { + rc = 0; + if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) { + rc = -socket_error(); + } + } while (rc == -EINTR); + + if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { + connect_state->fd = sock; + qemu_set_fd_handler2(sock, NULL, NULL, wait_for_connect, + connect_state); + return sock; + } else if (rc >= 0) { + /* non blocking socket immediate success, call callback */ + if (callback != NULL) { + callback(sock, opaque); + } } + if (rc < 0) { + fprintf(stderr, "connect(unix:%s): %s\n", path, strerror(errno)); + close(sock); + sock = -1; + } + + g_free(connect_state); return sock; } @@ -739,7 +772,8 @@ int unix_listen_opts(QemuOpts *opts, Error **errp) return -1; } -int unix_connect_opts(QemuOpts *opts, Error **errp) +int unix_connect_opts(QemuOpts *opts, Error **errp, + NonBlockingConnectHandler *callback, void *opaque) { fprintf(stderr, "unix sockets are not available on windows\n"); errno = ENOTSUP; @@ -784,7 +818,24 @@ int unix_connect(const char *path, Error **errp) opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); qemu_opt_set(opts, "path", path); - sock = unix_connect_opts(opts, errp); + sock = unix_connect_opts(opts, errp, NULL, NULL); + qemu_opts_del(opts); + return sock; +} + + +int unix_nonblocking_connect(const char *path, + NonBlockingConnectHandler *callback, + void *opaque, Error **errp) +{ + QemuOpts *opts; + int sock = -1; + + g_assert(callback != NULL); + + opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); + qemu_opt_set(opts, "path", path); + sock = unix_connect_opts(opts, errp, callback, opaque); qemu_opts_del(opts); return sock; } diff --git a/qemu_socket.h b/qemu_socket.h index ff979b5cd6..89a5feb7ec 100644 --- a/qemu_socket.h +++ b/qemu_socket.h @@ -58,8 +58,12 @@ const char *inet_strfamily(int family); int unix_listen_opts(QemuOpts *opts, Error **errp); int unix_listen(const char *path, char *ostr, int olen, Error **errp); -int unix_connect_opts(QemuOpts *opts, Error **errp); +int unix_connect_opts(QemuOpts *opts, Error **errp, + NonBlockingConnectHandler *callback, void *opaque); int unix_connect(const char *path, Error **errp); +int unix_nonblocking_connect(const char *str, + NonBlockingConnectHandler *callback, + void *opaque, Error **errp); /* Old, ipv4 only bits. Don't use for new code. */ int parse_host_port(struct sockaddr_in *saddr, const char *str); From be7059cd7f8998d41f0b44ec13907359d04c63d2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 3 Oct 2012 14:34:33 +0200 Subject: [PATCH 1059/2270] migration: avoid using error_is_set and thus relying on errp != NULL The migration code is using errp to detect "internal" errors, this means that it relies on errp being non-NULL. No impact so far because our only QMP clients (the QMP marshaller and HMP) never pass a NULL Error **. But if we had others, this patch would make sure that migration can work with a NULL Error **. Signed-off-by: Paolo Bonzini --- migration-tcp.c | 8 +++++--- migration.c | 13 +++++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/migration-tcp.c b/migration-tcp.c index a15c2b87a1..78337a3e29 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -71,14 +71,16 @@ static void tcp_wait_for_connect(int fd, void *opaque) int tcp_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp) { + Error *local_err = NULL; + s->get_error = socket_errno; s->write = socket_write; s->close = tcp_close; - s->fd = inet_nonblocking_connect(host_port, tcp_wait_for_connect, s, - errp); - if (error_is_set(errp)) { + s->fd = inet_nonblocking_connect(host_port, tcp_wait_for_connect, s, &local_err); + if (local_err != NULL) { migrate_fd_error(s); + error_propagate(errp, local_err); return -1; } diff --git a/migration.c b/migration.c index 62e030487d..b332dae3a4 100644 --- a/migration.c +++ b/migration.c @@ -483,6 +483,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, bool has_inc, bool inc, bool has_detach, bool detach, Error **errp) { + Error *local_err = NULL; MigrationState *s = migrate_get_current(); MigrationParams params; const char *p; @@ -508,7 +509,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, s = migrate_init(¶ms); if (strstart(uri, "tcp:", &p)) { - ret = tcp_start_outgoing_migration(s, p, errp); + ret = tcp_start_outgoing_migration(s, p, &local_err); #if !defined(WIN32) } else if (strstart(uri, "exec:", &p)) { ret = exec_start_outgoing_migration(s, p); @@ -522,11 +523,11 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, return; } - if (ret < 0) { - if (!error_is_set(errp)) { - DPRINTF("migration failed: %s\n", strerror(-ret)); - /* FIXME: we should return meaningful errors */ - error_set(errp, QERR_UNDEFINED_ERROR); + if (ret < 0 || local_err) { + if (!local_err) { + error_set_errno(errp, -ret, QERR_UNDEFINED_ERROR); + } else { + error_propagate(errp, local_err); } return; } From 342ab8d1e4f8650a22a3a1c9fade31df3fd9c1c1 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 2 Oct 2012 09:59:38 +0200 Subject: [PATCH 1060/2270] migration: centralize call to migrate_fd_error() The call to migrate_fd_error() was missing for non-socket backends, so centralize it in qmp_migrate(). Before: (qemu) migrate fd:ffff migrate: An undefined error has occurred (qemu) info migrate (qemu) After: (qemu) migrate fd:ffff migrate: An undefined error has occurred (qemu) info migrate capabilities: xbzrle: off Migration status: failed total time: 0 milliseconds (The awful error message will be fixed later in the series). Reviewed-by: Luiz Capitulino Signed-off-by: Paolo Bonzini --- migration-tcp.c | 1 - migration-unix.c | 1 - migration.c | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/migration-tcp.c b/migration-tcp.c index 78337a3e29..e8bc76acc6 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -79,7 +79,6 @@ int tcp_start_outgoing_migration(MigrationState *s, const char *host_port, s->fd = inet_nonblocking_connect(host_port, tcp_wait_for_connect, s, &local_err); if (local_err != NULL) { - migrate_fd_error(s); error_propagate(errp, local_err); return -1; } diff --git a/migration-unix.c b/migration-unix.c index 169de88677..d349662498 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -111,7 +111,6 @@ int unix_start_outgoing_migration(MigrationState *s, const char *path) if (ret < 0) { DPRINTF("connect failed\n"); - migrate_fd_error(s); return ret; } migrate_fd_connect(s); diff --git a/migration.c b/migration.c index b332dae3a4..efea21983a 100644 --- a/migration.c +++ b/migration.c @@ -524,6 +524,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, } if (ret < 0 || local_err) { + migrate_fd_error(s); if (!local_err) { error_set_errno(errp, -ret, QERR_UNDEFINED_ERROR); } else { From e08c95ce8d66276198704f21ed9df6d99b3477e0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 3 Oct 2012 14:05:49 +0200 Subject: [PATCH 1061/2270] migration: use qemu-sockets to establish Unix sockets This makes migration-unix.c again a cut-and-paste job from migration-tcp.c, exactly as it was in the beginning. :) Signed-off-by: Paolo Bonzini --- migration-unix.c | 94 +++++++++--------------------------------------- migration.c | 4 +-- migration.h | 4 +-- 3 files changed, 21 insertions(+), 81 deletions(-) diff --git a/migration-unix.c b/migration-unix.c index d349662498..5387c213ef 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -53,67 +53,34 @@ static int unix_close(MigrationState *s) return r; } -static void unix_wait_for_connect(void *opaque) +static void unix_wait_for_connect(int fd, void *opaque) { MigrationState *s = opaque; - int val, ret; - socklen_t valsize = sizeof(val); - DPRINTF("connect completed\n"); - do { - ret = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (void *) &val, &valsize); - } while (ret == -1 && errno == EINTR); - - if (ret < 0) { + if (fd < 0) { + DPRINTF("migrate connect error\n"); + s->fd = -1; migrate_fd_error(s); - return; - } - - qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); - - if (val == 0) + } else { + DPRINTF("migrate connect success\n"); + s->fd = fd; migrate_fd_connect(s); - else { - DPRINTF("error connecting %d\n", val); - migrate_fd_error(s); } } -int unix_start_outgoing_migration(MigrationState *s, const char *path) +int unix_start_outgoing_migration(MigrationState *s, const char *path, Error **errp) { - struct sockaddr_un addr; - int ret; + Error *local_err = NULL; - addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path); s->get_error = unix_errno; s->write = unix_write; s->close = unix_close; - s->fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0); - if (s->fd == -1) { - DPRINTF("Unable to open socket"); - return -errno; + s->fd = unix_nonblocking_connect(path, unix_wait_for_connect, s, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return -1; } - - socket_set_nonblock(s->fd); - - do { - ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr)); - if (ret == -1) { - ret = -errno; - } - if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) { - qemu_set_fd_handler2(s->fd, NULL, NULL, unix_wait_for_connect, s); - return 0; - } - } while (ret == -EINTR); - - if (ret < 0) { - DPRINTF("connect failed\n"); - return ret; - } - migrate_fd_connect(s); return 0; } @@ -151,43 +118,16 @@ out2: close(s); } -int unix_start_incoming_migration(const char *path) +int unix_start_incoming_migration(const char *path, Error **errp) { - struct sockaddr_un addr; int s; - int ret; - DPRINTF("Attempting to start an incoming migration\n"); - - s = qemu_socket(PF_UNIX, SOCK_STREAM, 0); - if (s == -1) { - fprintf(stderr, "Could not open unix socket: %s\n", strerror(errno)); - return -errno; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path); - - unlink(addr.sun_path); - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - ret = -errno; - fprintf(stderr, "bind(unix:%s): %s\n", addr.sun_path, strerror(errno)); - goto err; - } - if (listen(s, 1) == -1) { - fprintf(stderr, "listen(unix:%s): %s\n", addr.sun_path, - strerror(errno)); - ret = -errno; - goto err; + s = unix_listen(path, NULL, 0, errp); + if (s < 0) { + return -1; } qemu_set_fd_handler2(s, NULL, unix_accept_incoming_migration, NULL, (void *)(intptr_t)s); - return 0; - -err: - close(s); - return ret; } diff --git a/migration.c b/migration.c index efea21983a..e631f1837f 100644 --- a/migration.c +++ b/migration.c @@ -75,7 +75,7 @@ int qemu_start_incoming_migration(const char *uri, Error **errp) else if (strstart(uri, "exec:", &p)) ret = exec_start_incoming_migration(p); else if (strstart(uri, "unix:", &p)) - ret = unix_start_incoming_migration(p); + ret = unix_start_incoming_migration(p, errp); else if (strstart(uri, "fd:", &p)) ret = fd_start_incoming_migration(p); #endif @@ -514,7 +514,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, } else if (strstart(uri, "exec:", &p)) { ret = exec_start_outgoing_migration(s, p); } else if (strstart(uri, "unix:", &p)) { - ret = unix_start_outgoing_migration(s, p); + ret = unix_start_outgoing_migration(s, p, &local_err); } else if (strstart(uri, "fd:", &p)) { ret = fd_start_outgoing_migration(s, p); #endif diff --git a/migration.h b/migration.h index 1c3e9b750e..92e0aa9e72 100644 --- a/migration.h +++ b/migration.h @@ -66,9 +66,9 @@ int tcp_start_incoming_migration(const char *host_port, Error **errp); int tcp_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp); -int unix_start_incoming_migration(const char *path); +int unix_start_incoming_migration(const char *path, Error **errp); -int unix_start_outgoing_migration(MigrationState *s, const char *path); +int unix_start_outgoing_migration(MigrationState *s, const char *path, Error **errp); int fd_start_incoming_migration(const char *path); From f37afb5ab1921f42043b5527a517eef95c36acf8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 2 Oct 2012 10:02:46 +0200 Subject: [PATCH 1062/2270] migration (outgoing): add error propagation for all protocols Error propagation is already there for socket backends. Add it to other protocols, simplifying code that tests for errors that will never happen. With all protocols understanding Error, the code can be simplified further by removing the return value. Unfortunately, the quality of error messages varies depending on where the error is detected, because no Error is passed to the NonBlockingConnectHandler. Thus, the exact error message still cannot be sent to the user if the OS reports it asynchronously via SO_ERROR. If NonBlockingConnectHandler received an Error**, we could for example report the error class and/or message via a new field of the query-migration command even if it is reported asynchronously. Before: (qemu) migrate fd:ffff migrate: An undefined error has occurred (qemu) info migrate (qemu) After: (qemu) migrate fd:ffff migrate: File descriptor named 'ffff' has not been found (qemu) info migrate capabilities: xbzrle: off Migration status: failed total time: 0 milliseconds Signed-off-by: Paolo Bonzini --- migration-exec.c | 18 ++++-------------- migration-fd.c | 19 ++++--------------- migration-tcp.c | 13 ++----------- migration-unix.c | 11 ++--------- migration.c | 17 ++++++----------- migration.h | 9 ++++----- 6 files changed, 22 insertions(+), 65 deletions(-) diff --git a/migration-exec.c b/migration-exec.c index 6c97db973c..5f3f4b2c86 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -60,22 +60,18 @@ static int exec_close(MigrationState *s) return ret; } -int exec_start_outgoing_migration(MigrationState *s, const char *command) +void exec_start_outgoing_migration(MigrationState *s, const char *command, Error **errp) { FILE *f; f = popen(command, "w"); if (f == NULL) { - DPRINTF("Unable to popen exec target\n"); - goto err_after_popen; + error_setg_errno(errp, errno, "failed to popen the migration target"); + return; } s->fd = fileno(f); - if (s->fd == -1) { - DPRINTF("Unable to retrieve file descriptor for popen'd handle\n"); - goto err_after_open; - } - + assert(s->fd != -1); socket_set_nonblock(s->fd); s->opaque = qemu_popen(f, "w"); @@ -85,12 +81,6 @@ int exec_start_outgoing_migration(MigrationState *s, const char *command) s->write = file_write; migrate_fd_connect(s); - return 0; - -err_after_open: - pclose(f); -err_after_popen: - return -1; } static void exec_accept_incoming_migration(void *opaque) diff --git a/migration-fd.c b/migration-fd.c index 73351678e0..a7c800a852 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -73,30 +73,19 @@ static int fd_close(MigrationState *s) return 0; } -int fd_start_outgoing_migration(MigrationState *s, const char *fdname) +void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp) { - s->fd = monitor_get_fd(cur_mon, fdname, NULL); + s->fd = monitor_get_fd(cur_mon, fdname, errp); if (s->fd == -1) { - DPRINTF("fd_migration: invalid file descriptor identifier\n"); - goto err_after_get_fd; - } - - if (fcntl(s->fd, F_SETFL, O_NONBLOCK) == -1) { - DPRINTF("Unable to set nonblocking mode on file descriptor\n"); - goto err_after_open; + return; } + fcntl(s->fd, F_SETFL, O_NONBLOCK); s->get_error = fd_errno; s->write = fd_write; s->close = fd_close; migrate_fd_connect(s); - return 0; - -err_after_open: - close(s->fd); -err_after_get_fd: - return -1; } static void fd_accept_incoming_migration(void *opaque) diff --git a/migration-tcp.c b/migration-tcp.c index e8bc76acc6..5e54e68360 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -68,22 +68,13 @@ static void tcp_wait_for_connect(int fd, void *opaque) } } -int tcp_start_outgoing_migration(MigrationState *s, const char *host_port, - Error **errp) +void tcp_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp) { - Error *local_err = NULL; - s->get_error = socket_errno; s->write = socket_write; s->close = tcp_close; - s->fd = inet_nonblocking_connect(host_port, tcp_wait_for_connect, s, &local_err); - if (local_err != NULL) { - error_propagate(errp, local_err); - return -1; - } - - return 0; + s->fd = inet_nonblocking_connect(host_port, tcp_wait_for_connect, s, errp); } static void tcp_accept_incoming_migration(void *opaque) diff --git a/migration-unix.c b/migration-unix.c index 5387c213ef..34a413ab46 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -68,20 +68,13 @@ static void unix_wait_for_connect(int fd, void *opaque) } } -int unix_start_outgoing_migration(MigrationState *s, const char *path, Error **errp) +void unix_start_outgoing_migration(MigrationState *s, const char *path, Error **errp) { - Error *local_err = NULL; - s->get_error = unix_errno; s->write = unix_write; s->close = unix_close; - s->fd = unix_nonblocking_connect(path, unix_wait_for_connect, s, &local_err); - if (local_err != NULL) { - error_propagate(errp, local_err); - return -1; - } - return 0; + s->fd = unix_nonblocking_connect(path, unix_wait_for_connect, s, errp); } static void unix_accept_incoming_migration(void *opaque) diff --git a/migration.c b/migration.c index e631f1837f..ef171d2b39 100644 --- a/migration.c +++ b/migration.c @@ -487,7 +487,6 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, MigrationState *s = migrate_get_current(); MigrationParams params; const char *p; - int ret; params.blk = blk; params.shared = inc; @@ -509,27 +508,23 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, s = migrate_init(¶ms); if (strstart(uri, "tcp:", &p)) { - ret = tcp_start_outgoing_migration(s, p, &local_err); + tcp_start_outgoing_migration(s, p, &local_err); #if !defined(WIN32) } else if (strstart(uri, "exec:", &p)) { - ret = exec_start_outgoing_migration(s, p); + exec_start_outgoing_migration(s, p, &local_err); } else if (strstart(uri, "unix:", &p)) { - ret = unix_start_outgoing_migration(s, p, &local_err); + unix_start_outgoing_migration(s, p, &local_err); } else if (strstart(uri, "fd:", &p)) { - ret = fd_start_outgoing_migration(s, p); + fd_start_outgoing_migration(s, p, &local_err); #endif } else { error_set(errp, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol"); return; } - if (ret < 0 || local_err) { + if (local_err) { migrate_fd_error(s); - if (!local_err) { - error_set_errno(errp, -ret, QERR_UNDEFINED_ERROR); - } else { - error_propagate(errp, local_err); - } + error_propagate(errp, local_err); return; } diff --git a/migration.h b/migration.h index 92e0aa9e72..c805e2885e 100644 --- a/migration.h +++ b/migration.h @@ -59,20 +59,19 @@ void do_info_migrate(Monitor *mon, QObject **ret_data); int exec_start_incoming_migration(const char *host_port); -int exec_start_outgoing_migration(MigrationState *s, const char *host_port); +void exec_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp); int tcp_start_incoming_migration(const char *host_port, Error **errp); -int tcp_start_outgoing_migration(MigrationState *s, const char *host_port, - Error **errp); +void tcp_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp); int unix_start_incoming_migration(const char *path, Error **errp); -int unix_start_outgoing_migration(MigrationState *s, const char *path, Error **errp); +void unix_start_outgoing_migration(MigrationState *s, const char *path, Error **errp); int fd_start_incoming_migration(const char *path); -int fd_start_outgoing_migration(MigrationState *s, const char *fdname); +void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp); void migrate_fd_error(MigrationState *s); From 43eaae28e0394f8fb80848fb40aa5d28c6360321 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 2 Oct 2012 18:21:18 +0200 Subject: [PATCH 1063/2270] migration (incoming): add error propagation to fd and exec protocols And remove the superfluous integer return value. Reviewed-by: Luiz Capitulino Signed-off-by: Paolo Bonzini --- migration-exec.c | 8 +++----- migration-fd.c | 8 +++----- migration-tcp.c | 7 ++----- migration-unix.c | 5 ++--- migration.c | 15 ++++++--------- migration.h | 10 +++++----- vl.c | 16 ++++++---------- 7 files changed, 27 insertions(+), 42 deletions(-) diff --git a/migration-exec.c b/migration-exec.c index 5f3f4b2c86..519af57ac7 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -92,19 +92,17 @@ static void exec_accept_incoming_migration(void *opaque) qemu_fclose(f); } -int exec_start_incoming_migration(const char *command) +void exec_start_incoming_migration(const char *command, Error **errp) { QEMUFile *f; DPRINTF("Attempting to start an incoming migration\n"); f = qemu_popen_cmd(command, "r"); if(f == NULL) { - DPRINTF("Unable to apply qemu wrapper to popen file\n"); - return -errno; + error_setg_errno(errp, errno, "failed to popen the migration source"); + return; } qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, exec_accept_incoming_migration, NULL, f); - - return 0; } diff --git a/migration-fd.c b/migration-fd.c index a7c800a852..ce6932d7c3 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -97,7 +97,7 @@ static void fd_accept_incoming_migration(void *opaque) qemu_fclose(f); } -int fd_start_incoming_migration(const char *infd) +void fd_start_incoming_migration(const char *infd, Error **errp) { int fd; QEMUFile *f; @@ -107,11 +107,9 @@ int fd_start_incoming_migration(const char *infd) fd = strtol(infd, NULL, 0); f = qemu_fdopen(fd, "rb"); if(f == NULL) { - DPRINTF("Unable to apply qemu wrapper to file descriptor\n"); - return -errno; + error_setg_errno(errp, errno, "failed to open the source descriptor"); + return; } qemu_set_fd_handler2(fd, NULL, fd_accept_incoming_migration, NULL, f); - - return 0; } diff --git a/migration-tcp.c b/migration-tcp.c index 5e54e68360..46f6ac545c 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -111,18 +111,15 @@ out2: close(s); } -int tcp_start_incoming_migration(const char *host_port, Error **errp) +void tcp_start_incoming_migration(const char *host_port, Error **errp) { int s; s = inet_listen(host_port, NULL, 256, SOCK_STREAM, 0, errp); - if (s < 0) { - return -1; + return; } qemu_set_fd_handler2(s, NULL, tcp_accept_incoming_migration, NULL, (void *)(intptr_t)s); - - return 0; } diff --git a/migration-unix.c b/migration-unix.c index 34a413ab46..ed3db3a39a 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -111,16 +111,15 @@ out2: close(s); } -int unix_start_incoming_migration(const char *path, Error **errp) +void unix_start_incoming_migration(const char *path, Error **errp) { int s; s = unix_listen(path, NULL, 0, errp); if (s < 0) { - return -1; + return; } qemu_set_fd_handler2(s, NULL, unix_accept_incoming_migration, NULL, (void *)(intptr_t)s); - return 0; } diff --git a/migration.c b/migration.c index ef171d2b39..bd55a15f82 100644 --- a/migration.c +++ b/migration.c @@ -64,26 +64,23 @@ MigrationState *migrate_get_current(void) return ¤t_migration; } -int qemu_start_incoming_migration(const char *uri, Error **errp) +void qemu_start_incoming_migration(const char *uri, Error **errp) { const char *p; - int ret; if (strstart(uri, "tcp:", &p)) - ret = tcp_start_incoming_migration(p, errp); + tcp_start_incoming_migration(p, errp); #if !defined(WIN32) else if (strstart(uri, "exec:", &p)) - ret = exec_start_incoming_migration(p); + exec_start_incoming_migration(p, errp); else if (strstart(uri, "unix:", &p)) - ret = unix_start_incoming_migration(p, errp); + unix_start_incoming_migration(p, errp); else if (strstart(uri, "fd:", &p)) - ret = fd_start_incoming_migration(p); + fd_start_incoming_migration(p, errp); #endif else { - fprintf(stderr, "unknown migration protocol: %s\n", uri); - ret = -EPROTONOSUPPORT; + error_setg(errp, "unknown migration protocol: %s\n", uri); } - return ret; } void process_incoming_migration(QEMUFile *f) diff --git a/migration.h b/migration.h index c805e2885e..c3a23cc6c8 100644 --- a/migration.h +++ b/migration.h @@ -49,7 +49,7 @@ struct MigrationState void process_incoming_migration(QEMUFile *f); -int qemu_start_incoming_migration(const char *uri, Error **errp); +void qemu_start_incoming_migration(const char *uri, Error **errp); uint64_t migrate_max_downtime(void); @@ -57,19 +57,19 @@ void do_info_migrate_print(Monitor *mon, const QObject *data); void do_info_migrate(Monitor *mon, QObject **ret_data); -int exec_start_incoming_migration(const char *host_port); +void exec_start_incoming_migration(const char *host_port, Error **errp); void exec_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp); -int tcp_start_incoming_migration(const char *host_port, Error **errp); +void tcp_start_incoming_migration(const char *host_port, Error **errp); void tcp_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp); -int unix_start_incoming_migration(const char *path, Error **errp); +void unix_start_incoming_migration(const char *path, Error **errp); void unix_start_outgoing_migration(MigrationState *s, const char *path, Error **errp); -int fd_start_incoming_migration(const char *path); +void fd_start_incoming_migration(const char *path, Error **errp); void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp); diff --git a/vl.c b/vl.c index ee3c43ae2f..0597888449 100644 --- a/vl.c +++ b/vl.c @@ -3766,16 +3766,12 @@ int main(int argc, char **argv, char **envp) } if (incoming) { - Error *errp = NULL; - int ret = qemu_start_incoming_migration(incoming, &errp); - if (ret < 0) { - if (error_is_set(&errp)) { - fprintf(stderr, "Migrate: %s\n", error_get_pretty(errp)); - error_free(errp); - } - fprintf(stderr, "Migration failed. Exit code %s(%d), exiting.\n", - incoming, ret); - exit(ret); + Error *local_err = NULL; + qemu_start_incoming_migration(incoming, &local_err); + if (local_err) { + fprintf(stderr, "-incoming %s: %s\n", incoming, error_get_pretty(local_err)); + error_free(local_err); + exit(1); } } else if (autostart) { vm_start(); From 87d5f24f3f5edc4b69d071d5966cea0aec7b571d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 2 Oct 2012 09:16:49 +0200 Subject: [PATCH 1064/2270] qemu-char: ask and print error information from qemu-sockets Before: $ qemu-system-x86_64 -monitor tcp:localhost:6000 (starts despite error) $ qemu-system-x86_64 -monitor tcp:foo.bar:12345 getaddrinfo(foo.bar,12345): Name or service not known chardev: opening backend "socket" failed $ qemu-system-x86_64 -monitor tcp:localhost:443,server=on inet_listen_opts: bind(ipv4,127.0.0.1,443): Permission denied inet_listen_opts: FAILED chardev: opening backend "socket" failed After: $ x86_64-softmmu/qemu-system-x86_64 -monitor tcp:localhost:6000 x86_64-softmmu/qemu-system-x86_64: -monitor tcp:localhost:6000: Failed to connect to socket: Connection refused chardev: opening backend "socket" failed $ x86_64-softmmu/qemu-system-x86_64 -monitor tcp:foo.bar:12345 qemu-system-x86_64: -monitor tcp:foo.bar:12345: address resolution failed for foo.bar:12345: Name or service not known chardev: opening backend "socket" failed $ x86_64-softmmu/qemu-system-x86_64 -monitor tcp:localhost:443,server=on qemu-system-x86_64: -monitor tcp:localhost:443,server=on: Failed to bind socket: Permission denied chardev: opening backend "socket" failed Reviewed-by: Luiz Capitulino Signed-off-by: Paolo Bonzini --- qemu-char.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 8ebd5827d9..04b5c236df 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2097,12 +2097,13 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts) { CharDriverState *chr = NULL; NetCharDriver *s = NULL; + Error *local_err = NULL; int fd = -1; chr = g_malloc0(sizeof(CharDriverState)); s = g_malloc0(sizeof(NetCharDriver)); - fd = inet_dgram_opts(opts, NULL); + fd = inet_dgram_opts(opts, &local_err); if (fd < 0) { fprintf(stderr, "inet_dgram_opts failed\n"); goto return_err; @@ -2118,6 +2119,10 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts) return chr; return_err: + if (local_err) { + qerror_report_err(local_err); + error_free(local_err); + } g_free(chr); g_free(s); if (fd >= 0) { @@ -2428,6 +2433,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) { CharDriverState *chr = NULL; TCPCharDriver *s = NULL; + Error *local_err = NULL; int fd = -1; int is_listen; int is_waitconnect; @@ -2448,15 +2454,15 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) if (is_unix) { if (is_listen) { - fd = unix_listen_opts(opts, NULL); + fd = unix_listen_opts(opts, &local_err); } else { - fd = unix_connect_opts(opts, NULL, NULL, NULL); + fd = unix_connect_opts(opts, &local_err, NULL, NULL); } } else { if (is_listen) { - fd = inet_listen_opts(opts, 0, NULL); + fd = inet_listen_opts(opts, 0, &local_err); } else { - fd = inet_connect_opts(opts, NULL, NULL, NULL); + fd = inet_connect_opts(opts, &local_err, NULL, NULL); } } if (fd < 0) { @@ -2517,8 +2523,13 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) return chr; fail: - if (fd >= 0) + if (local_err) { + qerror_report_err(local_err); + error_free(local_err); + } + if (fd >= 0) { closesocket(fd); + } g_free(s); g_free(chr); return NULL; From f8430e7621b3319f6b94c735c811b2a2448cd6ea Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 2 Oct 2012 10:07:21 +0200 Subject: [PATCH 1065/2270] nbd: ask and print error information from qemu-sockets Before: $ qemu-system-x86_64 nbd:localhost:12345 inet_connect_opts: connect(ipv4,yakj.usersys.redhat.com,127.0.0.1,12345): Connection refused qemu-system-x86_64: could not open disk image nbd:localhost:12345: Connection refused After: $ x86_64-softmmu/qemu-system-x86_64 nbd:localhost:12345 qemu-system-x86_64: Failed to connect to socket: Connection refused qemu-system-x86_64: could not open disk image nbd:localhost:12345: Connection refused Signed-off-by: Paolo Bonzini --- nbd.c | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/nbd.c b/nbd.c index f61a288369..cec5a9449b 100644 --- a/nbd.c +++ b/nbd.c @@ -208,7 +208,14 @@ int tcp_socket_outgoing(const char *address, uint16_t port) int tcp_socket_outgoing_spec(const char *address_and_port) { - return inet_connect(address_and_port, NULL); + Error *local_err = NULL; + int fd = inet_connect(address_and_port, &local_err); + + if (local_err != NULL) { + qerror_report_err(local_err); + error_free(local_err); + } + return fd; } int tcp_socket_incoming(const char *address, uint16_t port) @@ -220,22 +227,38 @@ int tcp_socket_incoming(const char *address, uint16_t port) int tcp_socket_incoming_spec(const char *address_and_port) { - char *ostr = NULL; - int olen = 0; - return inet_listen(address_and_port, ostr, olen, SOCK_STREAM, 0, NULL); + Error *local_err = NULL; + int fd = inet_listen(address_and_port, NULL, 0, SOCK_STREAM, 0, &local_err); + + if (local_err != NULL) { + qerror_report_err(local_err); + error_free(local_err); + } + return fd; } int unix_socket_incoming(const char *path) { - char *ostr = NULL; - int olen = 0; + Error *local_err = NULL; + int fd = unix_listen(path, NULL, 0, &local_err); - return unix_listen(path, ostr, olen, NULL); + if (local_err != NULL) { + qerror_report_err(local_err); + error_free(local_err); + } + return fd; } int unix_socket_outgoing(const char *path) { - return unix_connect(path, NULL); + Error *local_err = NULL; + int fd = unix_connect(path, &local_err); + + if (local_err != NULL) { + qerror_report_err(local_err); + error_free(local_err); + } + return fd; } /* Basic flow for negotiation From 90119816e36ba019650214e7efeccdac1d4a9e32 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 2 Oct 2012 10:09:14 +0200 Subject: [PATCH 1066/2270] qemu-ga: ask and print error information from qemu-sockets Reviewed-by: Luiz Capitulino Signed-off-by: Paolo Bonzini --- qga/channel-posix.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/qga/channel-posix.c b/qga/channel-posix.c index e22eee6f67..d152827bcf 100644 --- a/qga/channel-posix.c +++ b/qga/channel-posix.c @@ -181,9 +181,11 @@ static gboolean ga_channel_open(GAChannel *c, const gchar *path, GAChannelMethod break; } case GA_CHANNEL_UNIX_LISTEN: { - int fd = unix_listen(path, NULL, strlen(path), NULL); - if (fd == -1) { - g_critical("error opening path: %s", strerror(errno)); + Error *local_err = NULL; + int fd = unix_listen(path, NULL, strlen(path), &local_err); + if (local_err != NULL) { + g_critical("%s", error_get_pretty(local_err)); + error_free(local_err); return false; } ga_channel_listen_add(c, fd, true); From c1c1619c8b100f675bc97198218f3fcb0a740921 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Oct 2012 09:06:21 +0200 Subject: [PATCH 1067/2270] vnc: avoid Yoda conditionals Signed-off-by: Paolo Bonzini --- ui/vnc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/vnc.c b/ui/vnc.c index ceade57ce3..64c4092f1f 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -3068,7 +3068,7 @@ int vnc_display_open(DisplayState *ds, const char *display) vs->lsock = unix_connect(display+5, NULL); else vs->lsock = inet_connect(display, NULL); - if (-1 == vs->lsock) { + if (vs->lsock < 0) { g_free(vs->display); vs->display = NULL; return -1; @@ -3090,7 +3090,7 @@ int vnc_display_open(DisplayState *ds, const char *display) vs->lsock = inet_listen(display, dpy, 256, SOCK_STREAM, 5900, NULL); } - if (-1 == vs->lsock) { + if (vs->lsock < 0) { g_free(dpy); return -1; } else { From 1ce52c78ab90c4303bcb110f2c614410386d79a2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Oct 2012 09:07:05 +0200 Subject: [PATCH 1068/2270] vnc: introduce a single label for error returns Signed-off-by: Paolo Bonzini --- ui/vnc.c | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/ui/vnc.c b/ui/vnc.c index 64c4092f1f..72d6f68897 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -2874,8 +2874,7 @@ int vnc_display_open(DisplayState *ds, const char *display) if (strcmp(display, "none") == 0) return 0; - if (!(vs->display = strdup(display))) - return -1; + vs->display = g_strdup(display); vs->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE; options = display; @@ -2887,9 +2886,7 @@ int vnc_display_open(DisplayState *ds, const char *display) "VNC password auth disabled due to FIPS mode, " "consider using the VeNCrypt or SASL authentication " "methods as an alternative\n"); - g_free(vs->display); - vs->display = NULL; - return -1; + goto fail; } password = 1; /* Require password auth */ } else if (strncmp(options, "reverse", 7) == 0) { @@ -2921,16 +2918,12 @@ int vnc_display_open(DisplayState *ds, const char *display) if (vnc_tls_set_x509_creds_dir(vs, path) < 0) { fprintf(stderr, "Failed to find x509 certificates/keys in %s\n", path); g_free(path); - g_free(vs->display); - vs->display = NULL; - return -1; + goto fail; } g_free(path); } else { fprintf(stderr, "No certificate path provided\n"); - g_free(vs->display); - vs->display = NULL; - return -1; + goto fail; } #endif #if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL) @@ -2950,9 +2943,7 @@ int vnc_display_open(DisplayState *ds, const char *display) vs->share_policy = VNC_SHARE_POLICY_FORCE_SHARED; } else { fprintf(stderr, "unknown vnc share= option\n"); - g_free(vs->display); - vs->display = NULL; - return -1; + goto fail; } } } @@ -3055,9 +3046,7 @@ int vnc_display_open(DisplayState *ds, const char *display) if ((saslErr = sasl_server_init(NULL, "qemu")) != SASL_OK) { fprintf(stderr, "Failed to initialize SASL auth %s", sasl_errstring(saslErr, NULL, NULL)); - g_free(vs->display); - vs->display = NULL; - return -1; + goto fail; } #endif vs->lock_key_sync = lock_key_sync; @@ -3069,9 +3058,7 @@ int vnc_display_open(DisplayState *ds, const char *display) else vs->lsock = inet_connect(display, NULL); if (vs->lsock < 0) { - g_free(vs->display); - vs->display = NULL; - return -1; + goto fail; } else { int csock = vs->lsock; vs->lsock = -1; @@ -3092,13 +3079,18 @@ int vnc_display_open(DisplayState *ds, const char *display) } if (vs->lsock < 0) { g_free(dpy); - return -1; - } else { - g_free(vs->display); - vs->display = dpy; + goto fail; } + g_free(vs->display); + vs->display = dpy; + qemu_set_fd_handler2(vs->lsock, NULL, vnc_listen_read, NULL, vs); } - return qemu_set_fd_handler2(vs->lsock, NULL, vnc_listen_read, NULL, vs); + return 0; + +fail: + g_free(vs->display); + vs->display = NULL; + return -1; } void vnc_display_add_client(DisplayState *ds, int csock, int skipauth) From 007fcd3ee9673b3d00baacf3765bd501296155cd Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Oct 2012 09:01:01 +0200 Subject: [PATCH 1069/2270] vnc: reorganize code for reverse mode Avoid the dance between csock and vs->lsock. Signed-off-by: Paolo Bonzini --- console.h | 2 +- qmp.c | 6 ++---- ui/vnc.c | 20 +++++++++----------- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/console.h b/console.h index f990684ef4..6099d8d710 100644 --- a/console.h +++ b/console.h @@ -378,7 +378,7 @@ void cocoa_display_init(DisplayState *ds, int full_screen); /* vnc.c */ void vnc_display_init(DisplayState *ds); void vnc_display_close(DisplayState *ds); -int vnc_display_open(DisplayState *ds, const char *display); +void vnc_display_open(DisplayState *ds, const char *display, Error **errp); void vnc_display_add_client(DisplayState *ds, int csock, int skipauth); int vnc_display_disable_login(DisplayState *ds); char *vnc_display_local_addr(DisplayState *ds); diff --git a/qmp.c b/qmp.c index 36c54c57cf..31bc3bfdd1 100644 --- a/qmp.c +++ b/qmp.c @@ -349,11 +349,9 @@ void qmp_change_vnc_password(const char *password, Error **errp) } } -static void qmp_change_vnc_listen(const char *target, Error **err) +static void qmp_change_vnc_listen(const char *target, Error **errp) { - if (vnc_display_open(NULL, target) < 0) { - error_set(err, QERR_VNC_SERVER_FAILED, target); - } + vnc_display_open(NULL, target, errp); } static void qmp_change_vnc(const char *target, bool has_arg, const char *arg, diff --git a/ui/vnc.c b/ui/vnc.c index 72d6f68897..46de820c80 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -3053,19 +3053,17 @@ int vnc_display_open(DisplayState *ds, const char *display) if (reverse) { /* connect to viewer */ - if (strncmp(display, "unix:", 5) == 0) - vs->lsock = unix_connect(display+5, NULL); - else - vs->lsock = inet_connect(display, NULL); - if (vs->lsock < 0) { - goto fail; + int csock; + vs->lsock = -1; + if (strncmp(display, "unix:", 5) == 0) { + csock = unix_connect(display+5, NULL); } else { - int csock = vs->lsock; - vs->lsock = -1; - vnc_connect(vs, csock, 0); + csock = inet_connect(display, NULL); } - return 0; - + if (csock < 0) { + goto fail; + } + vnc_connect(vs, csock, 0); } else { /* listen for connects */ char *dpy; From 2d55f0e817b6fa260282f5b5c533bcd470c75a32 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 2 Oct 2012 10:17:21 +0200 Subject: [PATCH 1070/2270] vnc: add error propagation to vnc_display_open Before: $ qemu-system-x86_64 -vnc foo.bar:12345 getaddrinfo(foo.bar,18245): Name or service not known Failed to start VNC server on `foo.bar:12345' $ qemu-system-x86_64 -vnc localhost:12345,reverse=on inet_connect_opts: connect(ipv4,yakj.usersys.redhat.com,127.0.0.1,12345): Connection refused Failed to start VNC server on `localhost:12345,reverse=on' After: $ x86_64-softmmu/qemu-system-x86_64 -vnc foo.bar:12345 Failed to start VNC server on `foo.bar:12345': address resolution failed for foo.bar:18245: Name or service not known $ x86_64-softmmu/qemu-system-x86_64 -vnc localhost:12345,reverse=on Failed to start VNC server on `localhost:12345,reverse=on': Failed to connect to socket: Connection refused Signed-off-by: Paolo Bonzini --- ui/vnc.c | 42 +++++++++++++++++++++++------------------- vl.c | 9 ++++++--- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/ui/vnc.c b/ui/vnc.c index 46de820c80..93775694b2 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -2850,7 +2850,7 @@ char *vnc_display_local_addr(DisplayState *ds) return vnc_socket_local_addr("%s:%s", vs->lsock); } -int vnc_display_open(DisplayState *ds, const char *display) +void vnc_display_open(DisplayState *ds, const char *display, Error **errp) { VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; const char *options; @@ -2868,11 +2868,13 @@ int vnc_display_open(DisplayState *ds, const char *display) #endif int lock_key_sync = 1; - if (!vnc_display) - return -1; + if (!vnc_display) { + error_setg(errp, "VNC display not active"); + return; + } vnc_display_close(ds); if (strcmp(display, "none") == 0) - return 0; + return; vs->display = g_strdup(display); vs->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE; @@ -2882,10 +2884,10 @@ int vnc_display_open(DisplayState *ds, const char *display) options++; if (strncmp(options, "password", 8) == 0) { if (fips_get_state()) { - fprintf(stderr, - "VNC password auth disabled due to FIPS mode, " - "consider using the VeNCrypt or SASL authentication " - "methods as an alternative\n"); + error_setg(errp, + "VNC password auth disabled due to FIPS mode, " + "consider using the VeNCrypt or SASL authentication " + "methods as an alternative"); goto fail; } password = 1; /* Require password auth */ @@ -2916,13 +2918,13 @@ int vnc_display_open(DisplayState *ds, const char *display) VNC_DEBUG("Trying certificate path '%s'\n", path); if (vnc_tls_set_x509_creds_dir(vs, path) < 0) { - fprintf(stderr, "Failed to find x509 certificates/keys in %s\n", path); + error_setg(errp, "Failed to find x509 certificates/keys in %s", path); g_free(path); goto fail; } g_free(path); } else { - fprintf(stderr, "No certificate path provided\n"); + error_setg(errp, "No certificate path provided"); goto fail; } #endif @@ -2942,7 +2944,7 @@ int vnc_display_open(DisplayState *ds, const char *display) } else if (strncmp(options+6, "force-shared", 12) == 0) { vs->share_policy = VNC_SHARE_POLICY_FORCE_SHARED; } else { - fprintf(stderr, "unknown vnc share= option\n"); + error_setg(errp, "unknown vnc share= option"); goto fail; } } @@ -3044,8 +3046,8 @@ int vnc_display_open(DisplayState *ds, const char *display) #ifdef CONFIG_VNC_SASL if ((saslErr = sasl_server_init(NULL, "qemu")) != SASL_OK) { - fprintf(stderr, "Failed to initialize SASL auth %s", - sasl_errstring(saslErr, NULL, NULL)); + error_setg(errp, "Failed to initialize SASL auth: %s", + sasl_errstring(saslErr, NULL, NULL)); goto fail; } #endif @@ -3056,9 +3058,9 @@ int vnc_display_open(DisplayState *ds, const char *display) int csock; vs->lsock = -1; if (strncmp(display, "unix:", 5) == 0) { - csock = unix_connect(display+5, NULL); + csock = unix_connect(display+5, errp); } else { - csock = inet_connect(display, NULL); + csock = inet_connect(display, errp); } if (csock < 0) { goto fail; @@ -3070,10 +3072,10 @@ int vnc_display_open(DisplayState *ds, const char *display) dpy = g_malloc(256); if (strncmp(display, "unix:", 5) == 0) { pstrcpy(dpy, 256, "unix:"); - vs->lsock = unix_listen(display+5, dpy+5, 256-5, NULL); + vs->lsock = unix_listen(display+5, dpy+5, 256-5, errp); } else { vs->lsock = inet_listen(display, dpy, 256, - SOCK_STREAM, 5900, NULL); + SOCK_STREAM, 5900, errp); } if (vs->lsock < 0) { g_free(dpy); @@ -3083,12 +3085,14 @@ int vnc_display_open(DisplayState *ds, const char *display) vs->display = dpy; qemu_set_fd_handler2(vs->lsock, NULL, vnc_listen_read, NULL, vs); } - return 0; + return; fail: + if (!error_is_set(errp)) { + error_set(errp, QERR_VNC_SERVER_FAILED, display); + } g_free(vs->display); vs->display = NULL; - return -1; } void vnc_display_add_client(DisplayState *ds, int csock, int skipauth) diff --git a/vl.c b/vl.c index 0597888449..9f99ef4763 100644 --- a/vl.c +++ b/vl.c @@ -3711,10 +3711,13 @@ int main(int argc, char **argv, char **envp) #ifdef CONFIG_VNC /* init remote displays */ if (vnc_display) { + Error *local_err = NULL; vnc_display_init(ds); - if (vnc_display_open(ds, vnc_display) < 0) { - fprintf(stderr, "Failed to start VNC server on `%s'\n", - vnc_display); + vnc_display_open(ds, vnc_display, &local_err); + if (local_err != NULL) { + fprintf(stderr, "Failed to start VNC server on `%s': %s\n", + vnc_display, error_get_pretty(local_err)); + error_free(local_err); exit(1); } From a12fb8ad5b444174ecf3c3270f93ec59ad177bf3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 2 Oct 2012 09:18:02 +0200 Subject: [PATCH 1071/2270] qemu-sockets: include strerror or gai_strerror output in error messages Among others, before: $ qemu-system-x86_64 -chardev socket,port=12345,id=char inet_connect: host and/or port not specified chardev: opening backend "socket" failed After: $ x86_64-softmmu/qemu-system-x86_64 -chardev socket,port=12345,id=char qemu-system-x86_64: -chardev socket,port=12345,id=char: host and/or port not specified chardev: opening backend "socket" failed perror and fprintf can be removed because all clients can now consume Errors properly. Reviewed-by: Paolo Bonzini Signed-off-by: Paolo Bonzini --- qemu-sockets.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/qemu-sockets.c b/qemu-sockets.c index d510ad1332..9e3d233624 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -120,8 +120,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp) if ((qemu_opt_get(opts, "host") == NULL) || (qemu_opt_get(opts, "port") == NULL)) { - fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__); - error_set(errp, QERR_SOCKET_CREATE_FAILED); + error_setg(errp, "host and/or port not specified"); return -1; } pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port")); @@ -138,9 +137,8 @@ int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp) snprintf(port, sizeof(port), "%d", atoi(port) + port_offset); rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res); if (rc != 0) { - fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port, - gai_strerror(rc)); - error_set(errp, QERR_SOCKET_CREATE_FAILED); + error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, + gai_strerror(rc)); return -1; } @@ -151,10 +149,8 @@ int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp) NI_NUMERICHOST | NI_NUMERICSERV); slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); if (slisten < 0) { - fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, - inet_strfamily(e->ai_family), strerror(errno)); if (!e->ai_next) { - error_set(errp, QERR_SOCKET_CREATE_FAILED); + error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); } continue; } @@ -176,24 +172,19 @@ int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp) goto listen; } if (p == port_max) { - fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__, - inet_strfamily(e->ai_family), uaddr, inet_getport(e), - strerror(errno)); if (!e->ai_next) { - error_set(errp, QERR_SOCKET_BIND_FAILED); + error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED); } } } closesocket(slisten); } - fprintf(stderr, "%s: FAILED\n", __FUNCTION__); freeaddrinfo(res); return -1; listen: if (listen(slisten,1) != 0) { - error_set(errp, QERR_SOCKET_LISTEN_FAILED); - perror("listen"); + error_set_errno(errp, errno, QERR_SOCKET_LISTEN_FAILED); closesocket(slisten); freeaddrinfo(res); return -1; @@ -324,9 +315,7 @@ static struct addrinfo *inet_parse_connect_opts(QemuOpts *opts, Error **errp) addr = qemu_opt_get(opts, "host"); port = qemu_opt_get(opts, "port"); if (addr == NULL || port == NULL) { - fprintf(stderr, - "inet_parse_connect_opts: host and/or port not specified\n"); - error_set(errp, QERR_SOCKET_CREATE_FAILED); + error_setg(errp, "host and/or port not specified"); return NULL; } @@ -340,9 +329,8 @@ static struct addrinfo *inet_parse_connect_opts(QemuOpts *opts, Error **errp) /* lookup */ rc = getaddrinfo(addr, port, &ai, &res); if (rc != 0) { - fprintf(stderr, "getaddrinfo(%s,%s): %s\n", addr, port, - gai_strerror(rc)); - error_set(errp, QERR_SOCKET_CREATE_FAILED); + error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, + gai_strerror(rc)); return NULL; } return res; From 11663b553b0815b266b6a9060ab9702cf7a5334c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 2 Oct 2012 09:19:01 +0200 Subject: [PATCH 1072/2270] qemu-sockets: add error propagation to inet_connect_addr perror and fprintf can be removed because all clients can now consume Errors properly. However, we'll need to change the non-blocking connect handlers to take an Error, in order to improve error handling for migration with the TCP protocol. This is a minor degradation in error reporting for outgoing migration. However, until 1.2 this case just failed without even attempting to connect, so it is still an improvement as far as overall QoI is concerned. Reviewed-by: Luiz Capitulino Signed-off-by: Paolo Bonzini --- qemu-sockets.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/qemu-sockets.c b/qemu-sockets.c index 9e3d233624..88d58fe70c 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -216,7 +216,7 @@ typedef struct ConnectState { } ConnectState; static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, - ConnectState *connect_state); + ConnectState *connect_state, Error **errp); static void wait_for_connect(void *opaque) { @@ -246,7 +246,7 @@ static void wait_for_connect(void *opaque) if (s->current_addr) { while (s->current_addr->ai_next != NULL && s->fd < 0) { s->current_addr = s->current_addr->ai_next; - s->fd = inet_connect_addr(s->current_addr, &in_progress, s); + s->fd = inet_connect_addr(s->current_addr, &in_progress, s, NULL); /* connect in progress */ if (in_progress) { return; @@ -263,7 +263,7 @@ static void wait_for_connect(void *opaque) } static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, - ConnectState *connect_state) + ConnectState *connect_state, Error **errp) { int sock, rc; @@ -271,8 +271,7 @@ static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if (sock < 0) { - fprintf(stderr, "%s: socket(%s): %s\n", __func__, - inet_strfamily(addr->ai_family), strerror(errno)); + error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); return -1; } qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); @@ -293,6 +292,7 @@ static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, connect_state); *in_progress = true; } else if (rc < 0) { + error_set_errno(errp, errno, QERR_SOCKET_CONNECT_FAILED); closesocket(sock); return -1; } @@ -375,7 +375,7 @@ int inet_connect_opts(QemuOpts *opts, Error **errp, if (connect_state != NULL) { connect_state->current_addr = e; } - sock = inet_connect_addr(e, &in_progress, connect_state); + sock = inet_connect_addr(e, &in_progress, connect_state, errp); if (in_progress) { return sock; } else if (sock >= 0) { @@ -386,9 +386,6 @@ int inet_connect_opts(QemuOpts *opts, Error **errp, break; } } - if (sock < 0) { - error_set(errp, QERR_SOCKET_CONNECT_FAILED); - } g_free(connect_state); freeaddrinfo(res); return sock; From 4f085c822947068c785be8c1f27d1ad4e3215149 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 2 Oct 2012 09:25:14 +0200 Subject: [PATCH 1073/2270] qemu-sockets: add error propagation to inet_dgram_opts Before: $ qemu-system-x86_64 -monitor udp:localhost:631@localhost:631 inet_dgram_opts: bind(ipv4,127.0.0.1,631): OK inet_dgram_opts failed chardev: opening backend "udp" failed After: $ x86_64-softmmu/qemu-system-x86_64 -monitor udp:localhost:631@localhost:631 qemu-system-x86_64: -monitor udp:localhost:631@localhost:631: Failed to bind socket: Address already in use chardev: opening backend "udp" failed Reviewed-by: Paolo Bonzini Signed-off-by: Paolo Bonzini --- qemu-char.c | 1 - qemu-sockets.c | 34 ++++++++-------------------------- 2 files changed, 8 insertions(+), 27 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 04b5c236df..afe2bfb4dd 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2105,7 +2105,6 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts) fd = inet_dgram_opts(opts, &local_err); if (fd < 0) { - fprintf(stderr, "inet_dgram_opts failed\n"); goto return_err; } diff --git a/qemu-sockets.c b/qemu-sockets.c index 88d58fe70c..078f7c17c3 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -396,8 +396,6 @@ int inet_dgram_opts(QemuOpts *opts, Error **errp) struct addrinfo ai, *peer = NULL, *local = NULL; const char *addr; const char *port; - char uaddr[INET6_ADDRSTRLEN+1]; - char uport[33]; int sock = -1, rc; /* lookup peer addr */ @@ -412,7 +410,7 @@ int inet_dgram_opts(QemuOpts *opts, Error **errp) addr = "localhost"; } if (port == NULL || strlen(port) == 0) { - fprintf(stderr, "inet_dgram: port not specified\n"); + error_setg(errp, "remote port not specified"); return -1; } @@ -422,8 +420,8 @@ int inet_dgram_opts(QemuOpts *opts, Error **errp) ai.ai_family = PF_INET6; if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) { - fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port, - gai_strerror(rc)); + error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, + gai_strerror(rc)); return -1; } @@ -442,44 +440,28 @@ int inet_dgram_opts(QemuOpts *opts, Error **errp) port = "0"; if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) { - fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port, - gai_strerror(rc)); + error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, + gai_strerror(rc)); goto err; } /* create socket */ sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); if (sock < 0) { - fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, - inet_strfamily(peer->ai_family), strerror(errno)); + error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); goto err; } setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on)); /* bind socket */ - if (getnameinfo((struct sockaddr*)local->ai_addr,local->ai_addrlen, - uaddr,INET6_ADDRSTRLEN,uport,32, - NI_NUMERICHOST | NI_NUMERICSERV) != 0) { - fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__); - goto err; - } if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) { - fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__, - inet_strfamily(local->ai_family), uaddr, inet_getport(local)); + error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED); goto err; } /* connect to peer */ - if (getnameinfo((struct sockaddr*)peer->ai_addr, peer->ai_addrlen, - uaddr, INET6_ADDRSTRLEN, uport, 32, - NI_NUMERICHOST | NI_NUMERICSERV) != 0) { - fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__); - goto err; - } if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) { - fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__, - inet_strfamily(peer->ai_family), - peer->ai_canonname, uaddr, uport, strerror(errno)); + error_set_errno(errp, errno, QERR_SOCKET_CONNECT_FAILED); goto err; } From 2f002c43ebded28604c26787c9215c4d3594f0ec Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 19 Sep 2012 13:22:21 +0200 Subject: [PATCH 1074/2270] qemu-sockets: add error propagation to inet_parse Reviewed-by: Luiz Capitulino Signed-off-by: Paolo Bonzini --- qemu-sockets.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/qemu-sockets.c b/qemu-sockets.c index 078f7c17c3..fb9c4c9587 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -480,7 +480,7 @@ err: } /* compatibility wrapper */ -static int inet_parse(QemuOpts *opts, const char *str) +static void inet_parse(QemuOpts *opts, const char *str, Error **errp) { const char *optstr, *h; char addr[64]; @@ -492,32 +492,28 @@ static int inet_parse(QemuOpts *opts, const char *str) /* no host given */ addr[0] = '\0'; if (1 != sscanf(str,":%32[^,]%n",port,&pos)) { - fprintf(stderr, "%s: portonly parse error (%s)\n", - __FUNCTION__, str); - return -1; + error_setg(errp, "error parsing port in address '%s'", str); + return; } } else if (str[0] == '[') { /* IPv6 addr */ if (2 != sscanf(str,"[%64[^]]]:%32[^,]%n",addr,port,&pos)) { - fprintf(stderr, "%s: ipv6 parse error (%s)\n", - __FUNCTION__, str); - return -1; + error_setg(errp, "error parsing IPv6 address '%s'", str); + return; } qemu_opt_set(opts, "ipv6", "on"); } else if (qemu_isdigit(str[0])) { /* IPv4 addr */ if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) { - fprintf(stderr, "%s: ipv4 parse error (%s)\n", - __FUNCTION__, str); - return -1; + error_setg(errp, "error parsing IPv4 address '%s'", str); + return; } qemu_opt_set(opts, "ipv4", "on"); } else { /* hostname */ if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) { - fprintf(stderr, "%s: hostname parse error (%s)\n", - __FUNCTION__, str); - return -1; + error_setg(errp, "error parsing address '%s'", str); + return; } } qemu_opt_set(opts, "host", addr); @@ -532,7 +528,6 @@ static int inet_parse(QemuOpts *opts, const char *str) qemu_opt_set(opts, "ipv4", "on"); if (strstr(optstr, ",ipv6")) qemu_opt_set(opts, "ipv6", "on"); - return 0; } int inet_listen(const char *str, char *ostr, int olen, @@ -541,9 +536,11 @@ int inet_listen(const char *str, char *ostr, int olen, QemuOpts *opts; char *optstr; int sock = -1; + Error *local_err = NULL; opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); - if (inet_parse(opts, str) == 0) { + inet_parse(opts, str, &local_err); + if (local_err == NULL) { sock = inet_listen_opts(opts, port_offset, errp); if (sock != -1 && ostr) { optstr = strchr(str, ','); @@ -560,7 +557,7 @@ int inet_listen(const char *str, char *ostr, int olen, } } } else { - error_set(errp, QERR_SOCKET_CREATE_FAILED); + error_propagate(errp, local_err); } qemu_opts_del(opts); return sock; @@ -578,12 +575,14 @@ int inet_connect(const char *str, Error **errp) { QemuOpts *opts; int sock = -1; + Error *local_err = NULL; opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); - if (inet_parse(opts, str) == 0) { + inet_parse(opts, str, &local_err); + if (local_err == NULL) { sock = inet_connect_opts(opts, errp, NULL, NULL); } else { - error_set(errp, QERR_SOCKET_CREATE_FAILED); + error_propagate(errp, local_err); } qemu_opts_del(opts); return sock; @@ -608,14 +607,16 @@ int inet_nonblocking_connect(const char *str, { QemuOpts *opts; int sock = -1; + Error *local_err = NULL; g_assert(callback != NULL); opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); - if (inet_parse(opts, str) == 0) { + inet_parse(opts, str, &local_err); + if (local_err == NULL) { sock = inet_connect_opts(opts, errp, callback, opaque); } else { - error_set(errp, QERR_SOCKET_CREATE_FAILED); + error_propagate(errp, local_err); } qemu_opts_del(opts); return sock; From 58899664de29c250229f8d306fcf04f852cf5cc6 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 19 Sep 2012 13:54:39 +0200 Subject: [PATCH 1075/2270] qemu-sockets: add error propagation to Unix socket functions Before: $ qemu-system-x86_64 -monitor unix:/vvv,server=off connect(unix:/vvv): No such file or directory chardev: opening backend "socket" failed After: $ x86_64-softmmu/qemu-system-x86_64 -monitor unix:/vvv,server=off qemu-system-x86_64: -monitor unix:/vvv,server=off: Failed to connect to socket: No such file or directory chardev: opening backend "socket" failed Reviewed-by: Paolo Bonzini Signed-off-by: Paolo Bonzini --- qemu-sockets.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/qemu-sockets.c b/qemu-sockets.c index fb9c4c9587..daff8e6a39 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -632,7 +632,7 @@ int unix_listen_opts(QemuOpts *opts, Error **errp) sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); if (sock < 0) { - perror("socket(unix)"); + error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); return -1; } @@ -657,11 +657,11 @@ int unix_listen_opts(QemuOpts *opts, Error **errp) unlink(un.sun_path); if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { - fprintf(stderr, "bind(unix:%s): %s\n", un.sun_path, strerror(errno)); + error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED); goto err; } if (listen(sock, 1) < 0) { - fprintf(stderr, "listen(unix:%s): %s\n", un.sun_path, strerror(errno)); + error_set_errno(errp, errno, QERR_SOCKET_LISTEN_FAILED); goto err; } @@ -681,13 +681,13 @@ int unix_connect_opts(QemuOpts *opts, Error **errp, int sock, rc; if (NULL == path) { - fprintf(stderr, "unix connect: no path specified\n"); + error_setg(errp, "unix connect: no path specified\n"); return -1; } sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); if (sock < 0) { - perror("socket(unix)"); + error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); return -1; } if (callback != NULL) { @@ -722,7 +722,7 @@ int unix_connect_opts(QemuOpts *opts, Error **errp, } if (rc < 0) { - fprintf(stderr, "connect(unix:%s): %s\n", path, strerror(errno)); + error_set_errno(errp, -rc, QERR_SOCKET_CONNECT_FAILED); close(sock); sock = -1; } @@ -735,7 +735,7 @@ int unix_connect_opts(QemuOpts *opts, Error **errp, int unix_listen_opts(QemuOpts *opts, Error **errp) { - fprintf(stderr, "unix sockets are not available on windows\n"); + error_setg(errp, "unix sockets are not available on windows"); errno = ENOTSUP; return -1; } @@ -743,7 +743,7 @@ int unix_listen_opts(QemuOpts *opts, Error **errp) int unix_connect_opts(QemuOpts *opts, Error **errp, NonBlockingConnectHandler *callback, void *opaque) { - fprintf(stderr, "unix sockets are not available on windows\n"); + error_setg(errp, "unix sockets are not available on windows"); errno = ENOTSUP; return -1; } From 3f8b11bc7d86a1952311565f089063d544d5a2f7 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 19 Oct 2012 11:34:18 +0200 Subject: [PATCH 1076/2270] vnc: drop QERR_VNC_SERVER_FAILED We now always return "nice" error messages in errp when we goto fail. Drop the default error message. Signed-off-by: Paolo Bonzini --- qerror.h | 3 --- ui/vnc.c | 3 --- 2 files changed, 6 deletions(-) diff --git a/qerror.h b/qerror.h index c91708cc3c..f23b97892d 100644 --- a/qerror.h +++ b/qerror.h @@ -237,9 +237,6 @@ void assert_no_error(Error *err); #define QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION \ ERROR_CLASS_GENERIC_ERROR, "Migration is disabled when VirtFS export path '%s' is mounted in the guest using mount_tag '%s'" -#define QERR_VNC_SERVER_FAILED \ - ERROR_CLASS_GENERIC_ERROR, "Could not start VNC server on %s" - #define QERR_SOCKET_CONNECT_FAILED \ ERROR_CLASS_GENERIC_ERROR, "Failed to connect to socket" diff --git a/ui/vnc.c b/ui/vnc.c index 93775694b2..d0ffcc54af 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -3088,9 +3088,6 @@ void vnc_display_open(DisplayState *ds, const char *display, Error **errp) return; fail: - if (!error_is_set(errp)) { - error_set(errp, QERR_VNC_SERVER_FAILED, display); - } g_free(vs->display); vs->display = NULL; } From a8170e5e97ad17ca169c64ba87ae2f53850dab4c Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 23 Oct 2012 12:30:10 +0200 Subject: [PATCH 1077/2270] Rename target_phys_addr_t to hwaddr target_phys_addr_t is unwieldly, violates the C standard (_t suffixes are reserved) and its purpose doesn't match the name (most target_phys_addr_t addresses are not target specific). Replace it with a finger-friendly, standards conformant hwaddr. Outstanding patchsets can be fixed up with the command git rebase -i --exec 'find -name "*.[ch]" | xargs s/target_phys_addr_t/hwaddr/g' origin Signed-off-by: Avi Kivity Signed-off-by: Anthony Liguori --- HACKING | 2 +- cpu-all.h | 2 +- cpu-common.h | 68 ++++++------- cpu-defs.h | 4 +- cputlb.c | 4 +- cputlb.h | 6 +- disas.h | 2 +- dma-helpers.c | 8 +- dma.h | 8 +- dump.c | 18 ++-- exec-all.h | 10 +- exec.c | 162 +++++++++++++++--------------- hw/a9mpcore.c | 4 +- hw/alpha_pci.c | 12 +-- hw/alpha_typhoon.c | 12 +-- hw/an5206.c | 2 +- hw/apb_pci.c | 24 ++--- hw/apb_pci.h | 4 +- hw/apic.c | 14 +-- hw/apic_common.c | 2 +- hw/apic_internal.h | 4 +- hw/arm-misc.h | 12 +-- hw/arm11mpcore.c | 8 +- hw/arm_boot.c | 14 +-- hw/arm_gic.c | 20 ++-- hw/arm_l2x0.c | 4 +- hw/arm_mptimer.c | 12 +-- hw/arm_sysctl.c | 4 +- hw/arm_timer.c | 12 +-- hw/armv7m.c | 12 +-- hw/armv7m_nvic.c | 4 +- hw/axis_dev88.c | 8 +- hw/bonito.c | 38 +++---- hw/cadence_gem.c | 8 +- hw/cadence_ttc.c | 8 +- hw/cadence_uart.c | 4 +- hw/cirrus_vga.c | 16 +-- hw/cris-boot.h | 2 +- hw/cs4231.c | 4 +- hw/cs4231a.c | 4 +- hw/cuda.c | 12 +-- hw/dma.c | 4 +- hw/dp8393x.c | 18 ++-- hw/ds1225y.c | 4 +- hw/dummy_m68k.c | 2 +- hw/e1000.c | 8 +- hw/eccmemctl.c | 8 +- hw/eepro100.c | 4 +- hw/elf_ops.h | 4 +- hw/empty_slot.c | 6 +- hw/empty_slot.h | 2 +- hw/escc.c | 8 +- hw/escc.h | 4 +- hw/esp-pci.c | 4 +- hw/esp.c | 8 +- hw/esp.h | 2 +- hw/etraxfs.h | 2 +- hw/etraxfs_dma.c | 22 ++-- hw/etraxfs_dma.h | 2 +- hw/etraxfs_eth.c | 4 +- hw/etraxfs_pic.c | 4 +- hw/etraxfs_ser.c | 4 +- hw/etraxfs_timer.c | 4 +- hw/exynos4210.h | 2 +- hw/exynos4210_combiner.c | 4 +- hw/exynos4210_fimd.c | 10 +- hw/exynos4210_i2c.c | 4 +- hw/exynos4210_mct.c | 4 +- hw/exynos4210_pmu.c | 4 +- hw/exynos4210_pwm.c | 4 +- hw/exynos4210_rtc.c | 4 +- hw/exynos4210_uart.c | 12 +-- hw/fdc.c | 8 +- hw/fdc.h | 4 +- hw/flash.h | 8 +- hw/framebuffer.c | 4 +- hw/framebuffer.h | 2 +- hw/fw_cfg.c | 16 +-- hw/fw_cfg.h | 2 +- hw/g364fb.c | 4 +- hw/grlib.h | 6 +- hw/grlib_apbuart.c | 4 +- hw/grlib_gptimer.c | 8 +- hw/grlib_irqmp.c | 4 +- hw/gt64xxx.c | 20 ++-- hw/heathrow_pic.c | 4 +- hw/highbank.c | 4 +- hw/hpet.c | 8 +- hw/i82378.c | 8 +- hw/i8259.c | 8 +- hw/ide.h | 2 +- hw/ide/ahci.c | 10 +- hw/ide/cmd646.c | 12 +-- hw/ide/macio.c | 12 +-- hw/ide/mmio.c | 10 +- hw/ide/pci.c | 4 +- hw/ide/piix.c | 4 +- hw/ide/via.c | 4 +- hw/imx.h | 6 +- hw/imx_avic.c | 4 +- hw/imx_ccm.c | 4 +- hw/imx_serial.c | 8 +- hw/imx_timer.c | 12 +-- hw/integratorcp.c | 14 +-- hw/intel-hda.c | 26 ++--- hw/ioapic.c | 4 +- hw/isa-bus.c | 2 +- hw/isa.h | 6 +- hw/isa_mmio.c | 16 +-- hw/ivshmem.c | 4 +- hw/jazz_led.c | 4 +- hw/kvm/apic.c | 4 +- hw/kvm/pci-assign.c | 24 ++--- hw/kvmvapic.c | 18 ++-- hw/lan9118.c | 12 +-- hw/lance.c | 4 +- hw/lm32_boards.c | 38 +++---- hw/lm32_hwsetup.h | 2 +- hw/lm32_sys.c | 4 +- hw/lm32_timer.c | 4 +- hw/lm32_uart.c | 4 +- hw/lm4549.c | 4 +- hw/lm4549.h | 4 +- hw/loader.c | 30 +++--- hw/loader.h | 22 ++-- hw/lsi53c895a.c | 12 +-- hw/m48t59.c | 14 +-- hw/mac_dbdma.c | 4 +- hw/mac_dbdma.h | 2 +- hw/mac_nvram.c | 8 +- hw/mainstone.c | 2 +- hw/marvell_88w8618_audio.c | 4 +- hw/mcf.h | 10 +- hw/mcf5206.c | 20 ++-- hw/mcf5208.c | 10 +- hw/mcf_fec.c | 6 +- hw/mcf_intc.c | 6 +- hw/mcf_uart.c | 6 +- hw/megasas.c | 28 +++--- hw/microblaze_boot.c | 6 +- hw/microblaze_boot.h | 2 +- hw/milkymist-ac97.c | 4 +- hw/milkymist-hpdmc.c | 4 +- hw/milkymist-hw.h | 24 ++--- hw/milkymist-memcard.c | 4 +- hw/milkymist-minimac2.c | 6 +- hw/milkymist-pfpu.c | 8 +- hw/milkymist-softusb.c | 4 +- hw/milkymist-sysctl.c | 4 +- hw/milkymist-tmu2.c | 8 +- hw/milkymist-uart.c | 4 +- hw/milkymist-vgafb.c | 4 +- hw/milkymist.c | 16 +-- hw/mips.h | 6 +- hw/mips_jazz.c | 8 +- hw/mips_malta.c | 6 +- hw/mips_r4k.c | 4 +- hw/mipsnet.c | 4 +- hw/mpc8544_guts.c | 4 +- hw/msix.c | 6 +- hw/mst_fpga.c | 4 +- hw/multiboot.c | 16 +-- hw/musicpal.c | 32 +++--- hw/ne2000.c | 4 +- hw/nvram.h | 2 +- hw/omap.h | 58 +++++------ hw/omap1.c | 148 +++++++++++++-------------- hw/omap2.c | 28 +++--- hw/omap_dma.c | 24 ++--- hw/omap_dss.c | 36 +++---- hw/omap_gpio.c | 16 +-- hw/omap_gpmc.c | 16 +-- hw/omap_gptimer.c | 8 +- hw/omap_i2c.c | 6 +- hw/omap_intc.c | 8 +- hw/omap_l4.c | 16 +-- hw/omap_lcdc.c | 8 +- hw/omap_mmc.c | 6 +- hw/omap_sdrc.c | 6 +- hw/omap_spi.c | 4 +- hw/omap_sx1.c | 4 +- hw/omap_synctimer.c | 6 +- hw/omap_tap.c | 4 +- hw/omap_uart.c | 10 +- hw/onenand.c | 8 +- hw/opencores_eth.c | 8 +- hw/openpic.c | 52 +++++----- hw/openpic.h | 2 +- hw/openrisc_sim.c | 6 +- hw/palm.c | 8 +- hw/parallel.c | 14 +-- hw/pc.c | 4 +- hw/pc.h | 16 +-- hw/pc_piix.c | 2 +- hw/pc_sysfw.c | 2 +- hw/pci.c | 2 +- hw/pci_host.c | 8 +- hw/pcie_host.c | 10 +- hw/pcie_host.h | 8 +- hw/pckbd.c | 8 +- hw/pcnet-pci.c | 20 ++-- hw/pcnet.c | 34 +++---- hw/pcnet.h | 4 +- hw/pcspk.c | 4 +- hw/petalogix_ml605_mmu.c | 2 +- hw/petalogix_s3adsp1800_mmu.c | 2 +- hw/pflash_cfi01.c | 48 ++++----- hw/pflash_cfi02.c | 40 ++++---- hw/piix_pci.c | 16 +-- hw/pl011.c | 4 +- hw/pl022.c | 4 +- hw/pl031.c | 4 +- hw/pl041.c | 6 +- hw/pl050.c | 4 +- hw/pl061.c | 4 +- hw/pl080.c | 4 +- hw/pl110.c | 4 +- hw/pl181.c | 4 +- hw/pl190.c | 4 +- hw/ppc/e500.c | 14 +-- hw/ppc405.h | 12 +-- hw/ppc405_boards.c | 28 +++--- hw/ppc405_uc.c | 64 ++++++------ hw/ppc440_bamboo.c | 16 +-- hw/ppc4xx.h | 16 +-- hw/ppc4xx_devs.c | 28 +++--- hw/ppc4xx_pci.c | 8 +- hw/ppc_mac.h | 4 +- hw/ppc_newworld.c | 8 +- hw/ppc_oldworld.c | 2 +- hw/ppc_prep.c | 30 +++--- hw/ppce500_pci.c | 4 +- hw/ppce500_spin.c | 16 +-- hw/prep_pci.c | 8 +- hw/puv3_dma.c | 4 +- hw/puv3_gpio.c | 4 +- hw/puv3_intc.c | 4 +- hw/puv3_ost.c | 4 +- hw/puv3_pm.c | 4 +- hw/pxa.h | 24 ++--- hw/pxa2xx.c | 42 ++++---- hw/pxa2xx_dma.c | 10 +- hw/pxa2xx_gpio.c | 6 +- hw/pxa2xx_keypad.c | 6 +- hw/pxa2xx_lcd.c | 20 ++-- hw/pxa2xx_mmci.c | 18 ++-- hw/pxa2xx_pcmcia.c | 14 +-- hw/pxa2xx_pic.c | 6 +- hw/pxa2xx_timer.c | 4 +- hw/qdev-addr.c | 16 +-- hw/qdev-addr.h | 4 +- hw/qxl.c | 4 +- hw/r2d.c | 6 +- hw/rc4030.c | 34 +++---- hw/realview.c | 2 +- hw/rtl8139.c | 14 +-- hw/s390-virtio-bus.c | 4 +- hw/s390-virtio.c | 4 +- hw/sbi.c | 4 +- hw/serial.c | 6 +- hw/serial.h | 2 +- hw/sh.h | 4 +- hw/sh7750.c | 24 ++--- hw/sh_intc.c | 4 +- hw/sh_pci.c | 4 +- hw/sh_serial.c | 10 +- hw/sh_timer.c | 10 +- hw/sharpsl.h | 2 +- hw/shpc.c | 4 +- hw/slavio_intctl.c | 8 +- hw/slavio_misc.c | 32 +++--- hw/slavio_timer.c | 4 +- hw/sm501.c | 18 ++-- hw/smc91c111.c | 12 +-- hw/soc_dma.c | 8 +- hw/soc_dma.h | 10 +- hw/spapr.c | 16 +-- hw/spapr.h | 10 +- hw/spapr_iommu.c | 6 +- hw/spapr_pci.c | 8 +- hw/spapr_pci.h | 4 +- hw/spapr_rtas.c | 4 +- hw/sparc32_dma.c | 8 +- hw/sparc32_dma.h | 4 +- hw/spitz.c | 4 +- hw/stellaris.c | 16 +-- hw/stellaris_enet.c | 4 +- hw/strongarm.c | 28 +++--- hw/sun4c_intctl.c | 4 +- hw/sun4m.c | 84 ++++++++-------- hw/sun4m.h | 6 +- hw/sun4m_iommu.c | 26 ++--- hw/sun4u.c | 6 +- hw/sysbus.c | 20 ++-- hw/sysbus.h | 18 ++-- hw/tc6393xb.c | 16 +-- hw/tcx.c | 10 +- hw/tusb6010.c | 12 +-- hw/unin_pci.c | 4 +- hw/usb/hcd-ehci.c | 20 ++-- hw/usb/hcd-musb.c | 12 +-- hw/usb/hcd-ohci.c | 4 +- hw/usb/hcd-xhci.c | 18 ++-- hw/versatile_i2c.c | 4 +- hw/versatile_pci.c | 6 +- hw/versatilepb.c | 4 +- hw/vexpress.c | 12 +-- hw/vfio_pci.c | 36 +++---- hw/vga-isa-mm.c | 20 ++-- hw/vga-pci.c | 8 +- hw/vga.c | 10 +- hw/vga_int.h | 4 +- hw/vhost.c | 16 +-- hw/virtex_ml507.c | 12 +-- hw/virtio-pci.c | 4 +- hw/virtio-scsi.c | 2 +- hw/virtio.c | 76 +++++++------- hw/virtio.h | 28 +++--- hw/vmware_vga.c | 4 +- hw/wdt_i6300esb.c | 12 +-- hw/xen_apic.c | 4 +- hw/xen_platform.c | 4 +- hw/xen_pt.c | 4 +- hw/xen_pt_msi.c | 4 +- hw/xgmac.c | 4 +- hw/xilinx.h | 10 +- hw/xilinx_axidma.c | 10 +- hw/xilinx_axienet.c | 4 +- hw/xilinx_ethlite.c | 4 +- hw/xilinx_intc.c | 4 +- hw/xilinx_spi.c | 4 +- hw/xilinx_spips.c | 4 +- hw/xilinx_timer.c | 6 +- hw/xilinx_uartlite.c | 4 +- hw/xtensa_lx60.c | 12 +-- hw/zaurus.c | 6 +- hw/zynq_slcr.c | 6 +- hwaddr.h | 24 +++++ kvm-all.c | 28 +++--- kvm.h | 2 +- memory-internal.h | 4 +- memory.c | 68 ++++++------- memory.h | 70 ++++++------- memory_mapping.c | 20 ++-- memory_mapping.h | 6 +- monitor.c | 38 +++---- softmmu_template.h | 12 +-- target-alpha/cpu.h | 2 +- target-alpha/helper.c | 2 +- target-alpha/mem_helper.c | 2 +- target-arm/helper.c | 28 +++--- target-cris/helper.c | 2 +- target-i386/arch_memory_mapping.c | 34 +++---- target-i386/helper.c | 6 +- target-i386/kvm.c | 6 +- target-i386/svm_helper.c | 6 +- target-lm32/helper.c | 2 +- target-m68k/helper.c | 2 +- target-microblaze/cpu.h | 2 +- target-microblaze/helper.c | 2 +- target-microblaze/op_helper.c | 2 +- target-mips/cpu.h | 12 +-- target-mips/helper.c | 18 ++-- target-mips/op_helper.c | 6 +- target-openrisc/cpu.h | 10 +- target-openrisc/mmu.c | 14 +-- target-ppc/cpu.h | 24 ++--- target-ppc/mmu_helper.c | 52 +++++----- target-s390x/cpu.h | 2 +- target-s390x/helper.c | 8 +- target-s390x/mem_helper.c | 10 +- target-sh4/cpu.h | 16 +-- target-sh4/helper.c | 18 ++-- target-sparc/cpu.h | 4 +- target-sparc/ldst_helper.c | 36 +++---- target-sparc/mmu_helper.c | 38 +++---- target-unicore32/softmmu.c | 2 +- target-xtensa/helper.c | 2 +- target-xtensa/xtensa-semi.c | 6 +- targphys.h | 24 ----- xen-all.c | 36 +++---- xen-mapcache.c | 32 +++--- xen-mapcache.h | 8 +- 383 files changed, 2240 insertions(+), 2240 deletions(-) create mode 100644 hwaddr.h delete mode 100644 targphys.h diff --git a/HACKING b/HACKING index dddd617a6b..89a6b3ad44 100644 --- a/HACKING +++ b/HACKING @@ -32,7 +32,7 @@ mandatory for VMState fields. Don't use Linux kernel internal types like u32, __u32 or __le32. -Use target_phys_addr_t for guest physical addresses except pcibus_t +Use hwaddr for guest physical addresses except pcibus_t for PCI addresses. In addition, ram_addr_t is a QEMU internal address space that maps guest RAM physical addresses into an intermediate address space that can map to host virtual address spaces. Generally diff --git a/cpu-all.h b/cpu-all.h index 6aa7e58cb1..6606432944 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -474,7 +474,7 @@ void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data); /* Return the physical page corresponding to a virtual one. Use it only for debugging because no protection checks are done. Return -1 if no page found. */ -target_phys_addr_t cpu_get_phys_page_debug(CPUArchState *env, target_ulong addr); +hwaddr cpu_get_phys_page_debug(CPUArchState *env, target_ulong addr); /* memory API */ diff --git a/cpu-common.h b/cpu-common.h index c0d27afd82..5f9308933c 100644 --- a/cpu-common.h +++ b/cpu-common.h @@ -3,7 +3,7 @@ /* CPU interfaces that are target independent. */ -#include "targphys.h" +#include "hwaddr.h" #ifndef NEED_CPU_H #include "poison.h" @@ -33,8 +33,8 @@ typedef uintptr_t ram_addr_t; /* memory API */ -typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value); -typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr); +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. */ @@ -49,27 +49,27 @@ int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr); ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr); void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev); -void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, +void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf, int len, int is_write); -static inline void cpu_physical_memory_read(target_phys_addr_t addr, +static inline void cpu_physical_memory_read(hwaddr addr, void *buf, int len) { cpu_physical_memory_rw(addr, buf, len, 0); } -static inline void cpu_physical_memory_write(target_phys_addr_t addr, +static inline void cpu_physical_memory_write(hwaddr addr, const void *buf, int len) { cpu_physical_memory_rw(addr, (void *)buf, len, 1); } -void *cpu_physical_memory_map(target_phys_addr_t addr, - target_phys_addr_t *plen, +void *cpu_physical_memory_map(hwaddr addr, + hwaddr *plen, int is_write); -void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, - int is_write, target_phys_addr_t access_len); +void cpu_physical_memory_unmap(void *buffer, hwaddr len, + int is_write, hwaddr access_len); void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque)); void cpu_unregister_map_client(void *cookie); -bool cpu_physical_memory_is_io(target_phys_addr_t phys_addr); +bool cpu_physical_memory_is_io(hwaddr phys_addr); /* Coalesced MMIO regions are areas where write operations can be reordered. * This usually implies that write operations are side-effect free. This allows @@ -78,33 +78,33 @@ bool cpu_physical_memory_is_io(target_phys_addr_t phys_addr); */ void qemu_flush_coalesced_mmio_buffer(void); -uint32_t ldub_phys(target_phys_addr_t addr); -uint32_t lduw_le_phys(target_phys_addr_t addr); -uint32_t lduw_be_phys(target_phys_addr_t addr); -uint32_t ldl_le_phys(target_phys_addr_t addr); -uint32_t ldl_be_phys(target_phys_addr_t addr); -uint64_t ldq_le_phys(target_phys_addr_t addr); -uint64_t ldq_be_phys(target_phys_addr_t addr); -void stb_phys(target_phys_addr_t addr, uint32_t val); -void stw_le_phys(target_phys_addr_t addr, uint32_t val); -void stw_be_phys(target_phys_addr_t addr, uint32_t val); -void stl_le_phys(target_phys_addr_t addr, uint32_t val); -void stl_be_phys(target_phys_addr_t addr, uint32_t val); -void stq_le_phys(target_phys_addr_t addr, uint64_t val); -void stq_be_phys(target_phys_addr_t addr, uint64_t val); +uint32_t ldub_phys(hwaddr addr); +uint32_t lduw_le_phys(hwaddr addr); +uint32_t lduw_be_phys(hwaddr addr); +uint32_t ldl_le_phys(hwaddr addr); +uint32_t ldl_be_phys(hwaddr addr); +uint64_t ldq_le_phys(hwaddr addr); +uint64_t ldq_be_phys(hwaddr addr); +void stb_phys(hwaddr addr, uint32_t val); +void stw_le_phys(hwaddr addr, uint32_t val); +void stw_be_phys(hwaddr addr, uint32_t val); +void stl_le_phys(hwaddr addr, uint32_t val); +void stl_be_phys(hwaddr addr, uint32_t val); +void stq_le_phys(hwaddr addr, uint64_t val); +void stq_be_phys(hwaddr addr, uint64_t val); #ifdef NEED_CPU_H -uint32_t lduw_phys(target_phys_addr_t addr); -uint32_t ldl_phys(target_phys_addr_t addr); -uint64_t ldq_phys(target_phys_addr_t addr); -void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val); -void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val); -void stw_phys(target_phys_addr_t addr, uint32_t val); -void stl_phys(target_phys_addr_t addr, uint32_t val); -void stq_phys(target_phys_addr_t addr, uint64_t val); +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); #endif -void cpu_physical_memory_write_rom(target_phys_addr_t addr, +void cpu_physical_memory_write_rom(hwaddr addr, const uint8_t *buf, int len); extern struct MemoryRegion io_mem_ram; diff --git a/cpu-defs.h b/cpu-defs.h index 4018b88a1a..a7965775b2 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -29,7 +29,7 @@ #include #include "osdep.h" #include "qemu-queue.h" -#include "targphys.h" +#include "hwaddr.h" #ifndef TARGET_LONG_BITS #error TARGET_LONG_BITS must be defined before including this header @@ -111,7 +111,7 @@ extern int CPUTLBEntry_wrong_size[sizeof(CPUTLBEntry) == (1 << CPU_TLB_ENTRY_BIT #define CPU_COMMON_TLB \ /* The meaning of the MMU modes is defined in the target code. */ \ CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \ - target_phys_addr_t iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \ + hwaddr iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \ target_ulong tlb_flush_addr; \ target_ulong tlb_flush_mask; diff --git a/cputlb.c b/cputlb.c index 9027557604..d6d0372615 100644 --- a/cputlb.c +++ b/cputlb.c @@ -237,7 +237,7 @@ static void tlb_add_large_page(CPUArchState *env, target_ulong vaddr, is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the supplied size is only used by tlb_flush_page. */ void tlb_set_page(CPUArchState *env, target_ulong vaddr, - target_phys_addr_t paddr, int prot, + hwaddr paddr, int prot, int mmu_idx, target_ulong size) { MemoryRegionSection *section; @@ -246,7 +246,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr, target_ulong code_address; uintptr_t addend; CPUTLBEntry *te; - target_phys_addr_t iotlb; + hwaddr iotlb; assert(size >= TARGET_PAGE_SIZE); if (size != TARGET_PAGE_SIZE) { diff --git a/cputlb.h b/cputlb.h index d537b7740f..733c885a1f 100644 --- a/cputlb.h +++ b/cputlb.h @@ -27,17 +27,17 @@ void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr, void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, uintptr_t start, uintptr_t length); MemoryRegionSection *phys_page_find(struct AddressSpaceDispatch *d, - target_phys_addr_t index); + hwaddr index); void cpu_tlb_reset_dirty_all(ram_addr_t start1, ram_addr_t length); void tlb_set_dirty(CPUArchState *env, target_ulong vaddr); extern int tlb_flush_count; /* exec.c */ void tb_flush_jmp_cache(CPUArchState *env, target_ulong addr); -target_phys_addr_t memory_region_section_get_iotlb(CPUArchState *env, +hwaddr memory_region_section_get_iotlb(CPUArchState *env, MemoryRegionSection *section, target_ulong vaddr, - target_phys_addr_t paddr, + hwaddr paddr, int prot, target_ulong *address); bool memory_region_is_unassigned(MemoryRegion *mr); diff --git a/disas.h b/disas.h index 3ab42af0b5..a8a09740db 100644 --- a/disas.h +++ b/disas.h @@ -22,7 +22,7 @@ struct elf64_sym; #if defined(CONFIG_USER_ONLY) typedef const char *(*lookup_symbol_t)(struct syminfo *s, target_ulong orig_addr); #else -typedef const char *(*lookup_symbol_t)(struct syminfo *s, target_phys_addr_t orig_addr); +typedef const char *(*lookup_symbol_t)(struct syminfo *s, hwaddr orig_addr); #endif struct syminfo { diff --git a/dma-helpers.c b/dma-helpers.c index 3f09dcb072..0c18e9e4d8 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -281,7 +281,7 @@ void dma_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie, bool iommu_dma_memory_valid(DMAContext *dma, dma_addr_t addr, dma_addr_t len, DMADirection dir) { - target_phys_addr_t paddr, plen; + hwaddr paddr, plen; #ifdef DEBUG_IOMMU fprintf(stderr, "dma_memory_check context=%p addr=0x" DMA_ADDR_FMT @@ -308,7 +308,7 @@ bool iommu_dma_memory_valid(DMAContext *dma, dma_addr_t addr, dma_addr_t len, int iommu_dma_memory_rw(DMAContext *dma, dma_addr_t addr, void *buf, dma_addr_t len, DMADirection dir) { - target_phys_addr_t paddr, plen; + hwaddr paddr, plen; int err; #ifdef DEBUG_IOMMU @@ -346,7 +346,7 @@ int iommu_dma_memory_rw(DMAContext *dma, dma_addr_t addr, int iommu_dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c, dma_addr_t len) { - target_phys_addr_t paddr, plen; + hwaddr paddr, plen; int err; #ifdef DEBUG_IOMMU @@ -392,7 +392,7 @@ void *iommu_dma_memory_map(DMAContext *dma, dma_addr_t addr, dma_addr_t *len, DMADirection dir) { int err; - target_phys_addr_t paddr, plen; + hwaddr paddr, plen; void *buf; if (dma->map) { diff --git a/dma.h b/dma.h index 1bd6f4a651..91ccdb5eac 100644 --- a/dma.h +++ b/dma.h @@ -48,8 +48,8 @@ typedef uint64_t dma_addr_t; typedef int DMATranslateFunc(DMAContext *dma, dma_addr_t addr, - target_phys_addr_t *paddr, - target_phys_addr_t *len, + hwaddr *paddr, + hwaddr *len, DMADirection dir); typedef void* DMAMapFunc(DMAContext *dma, dma_addr_t addr, @@ -177,7 +177,7 @@ static inline void *dma_memory_map(DMAContext *dma, DMADirection dir) { if (!dma_has_iommu(dma)) { - target_phys_addr_t xlen = *len; + hwaddr xlen = *len; void *p; p = address_space_map(dma->as, addr, &xlen, dir == DMA_DIRECTION_FROM_DEVICE); @@ -196,7 +196,7 @@ static inline void dma_memory_unmap(DMAContext *dma, DMADirection dir, dma_addr_t access_len) { if (!dma_has_iommu(dma)) { - address_space_unmap(dma->as, buffer, (target_phys_addr_t)len, + address_space_unmap(dma->as, buffer, (hwaddr)len, dir == DMA_DIRECTION_FROM_DEVICE, access_len); } else { iommu_dma_memory_unmap(dma, buffer, len, dir, access_len); diff --git a/dump.c b/dump.c index 6b7c127906..5640c2c2ff 100644 --- a/dump.c +++ b/dump.c @@ -15,7 +15,7 @@ #include "elf.h" #include "cpu.h" #include "cpu-all.h" -#include "targphys.h" +#include "hwaddr.h" #include "monitor.h" #include "kvm.h" #include "dump.h" @@ -66,7 +66,7 @@ typedef struct DumpState { bool have_section; bool resume; size_t note_size; - target_phys_addr_t memory_offset; + hwaddr memory_offset; int fd; RAMBlock *block; @@ -187,7 +187,7 @@ static int write_elf32_header(DumpState *s) } static int write_elf64_load(DumpState *s, MemoryMapping *memory_mapping, - int phdr_index, target_phys_addr_t offset) + int phdr_index, hwaddr offset) { Elf64_Phdr phdr; int ret; @@ -216,7 +216,7 @@ static int write_elf64_load(DumpState *s, MemoryMapping *memory_mapping, } static int write_elf32_load(DumpState *s, MemoryMapping *memory_mapping, - int phdr_index, target_phys_addr_t offset) + int phdr_index, hwaddr offset) { Elf32_Phdr phdr; int ret; @@ -248,7 +248,7 @@ static int write_elf64_note(DumpState *s) { Elf64_Phdr phdr; int endian = s->dump_info.d_endian; - target_phys_addr_t begin = s->memory_offset - s->note_size; + hwaddr begin = s->memory_offset - s->note_size; int ret; memset(&phdr, 0, sizeof(Elf64_Phdr)); @@ -296,7 +296,7 @@ static int write_elf64_notes(DumpState *s) static int write_elf32_note(DumpState *s) { - target_phys_addr_t begin = s->memory_offset - s->note_size; + hwaddr begin = s->memory_offset - s->note_size; Elf32_Phdr phdr; int endian = s->dump_info.d_endian; int ret; @@ -414,11 +414,11 @@ static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start, } /* get the memory's offset in the vmcore */ -static target_phys_addr_t get_offset(target_phys_addr_t phys_addr, +static hwaddr get_offset(hwaddr phys_addr, DumpState *s) { RAMBlock *block; - target_phys_addr_t offset = s->memory_offset; + hwaddr offset = s->memory_offset; int64_t size_in_block, start; if (s->has_filter) { @@ -463,7 +463,7 @@ static target_phys_addr_t get_offset(target_phys_addr_t phys_addr, static int write_elf_loads(DumpState *s) { - target_phys_addr_t offset; + hwaddr offset; MemoryMapping *memory_mapping; uint32_t phdr_index = 1; int ret; diff --git a/exec-all.h b/exec-all.h index 16caf49db7..2ea0e4fc24 100644 --- a/exec-all.h +++ b/exec-all.h @@ -103,9 +103,9 @@ void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end, void tlb_flush_page(CPUArchState *env, target_ulong addr); void tlb_flush(CPUArchState *env, int flush_global); void tlb_set_page(CPUArchState *env, target_ulong vaddr, - target_phys_addr_t paddr, int prot, + hwaddr paddr, int prot, int mmu_idx, target_ulong size); -void tb_invalidate_phys_addr(target_phys_addr_t addr); +void tb_invalidate_phys_addr(hwaddr addr); #else static inline void tlb_flush_page(CPUArchState *env, target_ulong addr) { @@ -312,10 +312,10 @@ extern uintptr_t tci_tb_ptr; #if !defined(CONFIG_USER_ONLY) -struct MemoryRegion *iotlb_to_region(target_phys_addr_t index); -uint64_t io_mem_read(struct MemoryRegion *mr, target_phys_addr_t addr, +struct MemoryRegion *iotlb_to_region(hwaddr index); +uint64_t io_mem_read(struct MemoryRegion *mr, hwaddr addr, unsigned size); -void io_mem_write(struct MemoryRegion *mr, target_phys_addr_t addr, +void io_mem_write(struct MemoryRegion *mr, hwaddr addr, uint64_t value, unsigned size); void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx, diff --git a/exec.c b/exec.c index 750008c4e1..b0ed5939e9 100644 --- a/exec.c +++ b/exec.c @@ -398,13 +398,13 @@ static void phys_map_nodes_reset(void) } -static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t *index, - target_phys_addr_t *nb, uint16_t leaf, +static void phys_page_set_level(PhysPageEntry *lp, hwaddr *index, + hwaddr *nb, uint16_t leaf, int level) { PhysPageEntry *p; int i; - target_phys_addr_t step = (target_phys_addr_t)1 << (level * L2_BITS); + hwaddr step = (hwaddr)1 << (level * L2_BITS); if (!lp->is_leaf && lp->ptr == PHYS_MAP_NODE_NIL) { lp->ptr = phys_map_node_alloc(); @@ -434,7 +434,7 @@ static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t *index, } static void phys_page_set(AddressSpaceDispatch *d, - target_phys_addr_t index, target_phys_addr_t nb, + hwaddr index, hwaddr nb, uint16_t leaf) { /* Wildly overreserve - it doesn't matter much. */ @@ -443,7 +443,7 @@ static void phys_page_set(AddressSpaceDispatch *d, phys_page_set_level(&d->phys_map, &index, &nb, leaf, P_L2_LEVELS - 1); } -MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, target_phys_addr_t index) +MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index) { PhysPageEntry lp = d->phys_map; PhysPageEntry *p; @@ -1473,7 +1473,7 @@ static void breakpoint_invalidate(CPUArchState *env, target_ulong pc) tb_invalidate_phys_page_range(pc, pc + 1, 0); } #else -void tb_invalidate_phys_addr(target_phys_addr_t addr) +void tb_invalidate_phys_addr(hwaddr addr) { ram_addr_t ram_addr; MemoryRegionSection *section; @@ -1866,14 +1866,14 @@ int cpu_physical_memory_set_dirty_tracking(int enable) return ret; } -target_phys_addr_t memory_region_section_get_iotlb(CPUArchState *env, +hwaddr memory_region_section_get_iotlb(CPUArchState *env, MemoryRegionSection *section, target_ulong vaddr, - target_phys_addr_t paddr, + hwaddr paddr, int prot, target_ulong *address) { - target_phys_addr_t iotlb; + hwaddr iotlb; CPUWatchpoint *wp; if (memory_region_is_ram(section->mr)) { @@ -2176,13 +2176,13 @@ int page_unprotect(target_ulong address, uintptr_t pc, void *puc) #define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK) typedef struct subpage_t { MemoryRegion iomem; - target_phys_addr_t base; + hwaddr base; uint16_t sub_section[TARGET_PAGE_SIZE]; } subpage_t; static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, uint16_t section); -static subpage_t *subpage_init(target_phys_addr_t base); +static subpage_t *subpage_init(hwaddr base); static void destroy_page_desc(uint16_t section_index) { MemoryRegionSection *section = &phys_sections[section_index]; @@ -2241,14 +2241,14 @@ static void phys_sections_clear(void) static void register_subpage(AddressSpaceDispatch *d, MemoryRegionSection *section) { subpage_t *subpage; - target_phys_addr_t base = section->offset_within_address_space + hwaddr base = section->offset_within_address_space & TARGET_PAGE_MASK; MemoryRegionSection *existing = phys_page_find(d, base >> TARGET_PAGE_BITS); MemoryRegionSection subsection = { .offset_within_address_space = base, .size = TARGET_PAGE_SIZE, }; - target_phys_addr_t start, end; + hwaddr start, end; assert(existing->mr->subpage || existing->mr == &io_mem_unassigned); @@ -2268,9 +2268,9 @@ static void register_subpage(AddressSpaceDispatch *d, MemoryRegionSection *secti static void register_multipage(AddressSpaceDispatch *d, MemoryRegionSection *section) { - target_phys_addr_t start_addr = section->offset_within_address_space; + hwaddr start_addr = section->offset_within_address_space; ram_addr_t size = section->size; - target_phys_addr_t addr; + hwaddr addr; uint16_t section_index = phys_section_add(section); assert(size); @@ -2836,7 +2836,7 @@ ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr) return ram_addr; } -static uint64_t unassigned_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t unassigned_mem_read(void *opaque, hwaddr addr, unsigned size) { #ifdef DEBUG_UNASSIGNED @@ -2848,7 +2848,7 @@ static uint64_t unassigned_mem_read(void *opaque, target_phys_addr_t addr, return 0; } -static void unassigned_mem_write(void *opaque, target_phys_addr_t addr, +static void unassigned_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { #ifdef DEBUG_UNASSIGNED @@ -2865,13 +2865,13 @@ static const MemoryRegionOps unassigned_mem_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint64_t error_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t error_mem_read(void *opaque, hwaddr addr, unsigned size) { abort(); } -static void error_mem_write(void *opaque, target_phys_addr_t addr, +static void error_mem_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { abort(); @@ -2889,7 +2889,7 @@ static const MemoryRegionOps rom_mem_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void notdirty_mem_write(void *opaque, target_phys_addr_t ram_addr, +static void notdirty_mem_write(void *opaque, hwaddr ram_addr, uint64_t val, unsigned size) { int dirty_flags; @@ -2976,7 +2976,7 @@ static void check_watchpoint(int offset, int len_mask, int flags) /* Watchpoint access routines. Watchpoints are inserted using TLB tricks, so these check for a hit then pass through to the normal out-of-line phys routines. */ -static uint64_t watch_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t watch_mem_read(void *opaque, hwaddr addr, unsigned size) { check_watchpoint(addr & ~TARGET_PAGE_MASK, ~(size - 1), BP_MEM_READ); @@ -2988,7 +2988,7 @@ static uint64_t watch_mem_read(void *opaque, target_phys_addr_t addr, } } -static void watch_mem_write(void *opaque, target_phys_addr_t addr, +static void watch_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { check_watchpoint(addr & ~TARGET_PAGE_MASK, ~(size - 1), BP_MEM_WRITE); @@ -3012,7 +3012,7 @@ static const MemoryRegionOps watch_mem_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint64_t subpage_read(void *opaque, target_phys_addr_t addr, +static uint64_t subpage_read(void *opaque, hwaddr addr, unsigned len) { subpage_t *mmio = opaque; @@ -3030,7 +3030,7 @@ static uint64_t subpage_read(void *opaque, target_phys_addr_t addr, return io_mem_read(section->mr, addr, len); } -static void subpage_write(void *opaque, target_phys_addr_t addr, +static void subpage_write(void *opaque, hwaddr addr, uint64_t value, unsigned len) { subpage_t *mmio = opaque; @@ -3055,7 +3055,7 @@ static const MemoryRegionOps subpage_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint64_t subpage_ram_read(void *opaque, target_phys_addr_t addr, +static uint64_t subpage_ram_read(void *opaque, hwaddr addr, unsigned size) { ram_addr_t raddr = addr; @@ -3068,7 +3068,7 @@ static uint64_t subpage_ram_read(void *opaque, target_phys_addr_t addr, } } -static void subpage_ram_write(void *opaque, target_phys_addr_t addr, +static void subpage_ram_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { ram_addr_t raddr = addr; @@ -3112,7 +3112,7 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, return 0; } -static subpage_t *subpage_init(target_phys_addr_t base) +static subpage_t *subpage_init(hwaddr base) { subpage_t *mmio; @@ -3143,7 +3143,7 @@ static uint16_t dummy_section(MemoryRegion *mr) return phys_section_add(§ion); } -MemoryRegion *iotlb_to_region(target_phys_addr_t index) +MemoryRegion *iotlb_to_region(hwaddr index) { return phys_sections[index & ~TARGET_PAGE_MASK].mr; } @@ -3333,8 +3333,8 @@ int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr, #else -static void invalidate_and_set_dirty(target_phys_addr_t addr, - target_phys_addr_t length) +static void invalidate_and_set_dirty(hwaddr addr, + hwaddr length) { if (!cpu_physical_memory_is_dirty(addr)) { /* invalidate code */ @@ -3345,14 +3345,14 @@ static void invalidate_and_set_dirty(target_phys_addr_t addr, xen_modified_memory(addr, length); } -void address_space_rw(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, +void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf, int len, bool is_write) { AddressSpaceDispatch *d = as->dispatch; int l; uint8_t *ptr; uint32_t val; - target_phys_addr_t page; + hwaddr page; MemoryRegionSection *section; while (len > 0) { @@ -3364,7 +3364,7 @@ void address_space_rw(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, if (is_write) { if (!memory_region_is_ram(section->mr)) { - target_phys_addr_t addr1; + hwaddr addr1; addr1 = memory_region_section_addr(section, addr); /* XXX: could force cpu_single_env to NULL to avoid potential bugs */ @@ -3397,7 +3397,7 @@ void address_space_rw(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, } else { if (!(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr))) { - target_phys_addr_t addr1; + hwaddr addr1; /* I/O case */ addr1 = memory_region_section_addr(section, addr); if (l >= 4 && ((addr1 & 3) == 0)) { @@ -3431,7 +3431,7 @@ void address_space_rw(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, } } -void address_space_write(AddressSpace *as, target_phys_addr_t addr, +void address_space_write(AddressSpace *as, hwaddr addr, const uint8_t *buf, int len) { address_space_rw(as, addr, (uint8_t *)buf, len, true); @@ -3444,26 +3444,26 @@ void address_space_write(AddressSpace *as, target_phys_addr_t addr, * @addr: address within that address space * @buf: buffer with the data transferred */ -void address_space_read(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, int len) +void address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len) { address_space_rw(as, addr, buf, len, false); } -void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, +void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf, int len, int is_write) { return address_space_rw(&address_space_memory, addr, buf, len, is_write); } /* used for ROM loading : can write in RAM and ROM */ -void cpu_physical_memory_write_rom(target_phys_addr_t addr, +void cpu_physical_memory_write_rom(hwaddr addr, const uint8_t *buf, int len) { AddressSpaceDispatch *d = address_space_memory.dispatch; int l; uint8_t *ptr; - target_phys_addr_t page; + hwaddr page; MemoryRegionSection *section; while (len > 0) { @@ -3494,8 +3494,8 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr, typedef struct { void *buffer; - target_phys_addr_t addr; - target_phys_addr_t len; + hwaddr addr; + hwaddr len; } BounceBuffer; static BounceBuffer bounce; @@ -3546,15 +3546,15 @@ static void cpu_notify_map_clients(void) * likely to succeed. */ void *address_space_map(AddressSpace *as, - target_phys_addr_t addr, - target_phys_addr_t *plen, + hwaddr addr, + hwaddr *plen, bool is_write) { AddressSpaceDispatch *d = as->dispatch; - target_phys_addr_t len = *plen; - target_phys_addr_t todo = 0; + hwaddr len = *plen; + hwaddr todo = 0; int l; - target_phys_addr_t page; + hwaddr page; MemoryRegionSection *section; ram_addr_t raddr = RAM_ADDR_MAX; ram_addr_t rlen; @@ -3600,8 +3600,8 @@ void *address_space_map(AddressSpace *as, * Will also mark the memory as dirty if is_write == 1. access_len gives * the amount of memory that was actually read or written by the caller. */ -void address_space_unmap(AddressSpace *as, void *buffer, target_phys_addr_t len, - int is_write, target_phys_addr_t access_len) +void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, + int is_write, hwaddr access_len) { if (buffer != bounce.buffer) { if (is_write) { @@ -3629,21 +3629,21 @@ void address_space_unmap(AddressSpace *as, void *buffer, target_phys_addr_t len, cpu_notify_map_clients(); } -void *cpu_physical_memory_map(target_phys_addr_t addr, - target_phys_addr_t *plen, +void *cpu_physical_memory_map(hwaddr addr, + hwaddr *plen, int is_write) { return address_space_map(&address_space_memory, addr, plen, is_write); } -void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, - int is_write, target_phys_addr_t access_len) +void cpu_physical_memory_unmap(void *buffer, hwaddr len, + int is_write, hwaddr access_len) { return address_space_unmap(&address_space_memory, buffer, len, is_write, access_len); } /* warning: addr must be aligned */ -static inline uint32_t ldl_phys_internal(target_phys_addr_t addr, +static inline uint32_t ldl_phys_internal(hwaddr addr, enum device_endian endian) { uint8_t *ptr; @@ -3686,23 +3686,23 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr, return val; } -uint32_t ldl_phys(target_phys_addr_t addr) +uint32_t ldl_phys(hwaddr addr) { return ldl_phys_internal(addr, DEVICE_NATIVE_ENDIAN); } -uint32_t ldl_le_phys(target_phys_addr_t addr) +uint32_t ldl_le_phys(hwaddr addr) { return ldl_phys_internal(addr, DEVICE_LITTLE_ENDIAN); } -uint32_t ldl_be_phys(target_phys_addr_t addr) +uint32_t ldl_be_phys(hwaddr addr) { return ldl_phys_internal(addr, DEVICE_BIG_ENDIAN); } /* warning: addr must be aligned */ -static inline uint64_t ldq_phys_internal(target_phys_addr_t addr, +static inline uint64_t ldq_phys_internal(hwaddr addr, enum device_endian endian) { uint8_t *ptr; @@ -3745,23 +3745,23 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr, return val; } -uint64_t ldq_phys(target_phys_addr_t addr) +uint64_t ldq_phys(hwaddr addr) { return ldq_phys_internal(addr, DEVICE_NATIVE_ENDIAN); } -uint64_t ldq_le_phys(target_phys_addr_t addr) +uint64_t ldq_le_phys(hwaddr addr) { return ldq_phys_internal(addr, DEVICE_LITTLE_ENDIAN); } -uint64_t ldq_be_phys(target_phys_addr_t addr) +uint64_t ldq_be_phys(hwaddr addr) { return ldq_phys_internal(addr, DEVICE_BIG_ENDIAN); } /* XXX: optimize */ -uint32_t ldub_phys(target_phys_addr_t addr) +uint32_t ldub_phys(hwaddr addr) { uint8_t val; cpu_physical_memory_read(addr, &val, 1); @@ -3769,7 +3769,7 @@ uint32_t ldub_phys(target_phys_addr_t addr) } /* warning: addr must be aligned */ -static inline uint32_t lduw_phys_internal(target_phys_addr_t addr, +static inline uint32_t lduw_phys_internal(hwaddr addr, enum device_endian endian) { uint8_t *ptr; @@ -3812,17 +3812,17 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr, return val; } -uint32_t lduw_phys(target_phys_addr_t addr) +uint32_t lduw_phys(hwaddr addr) { return lduw_phys_internal(addr, DEVICE_NATIVE_ENDIAN); } -uint32_t lduw_le_phys(target_phys_addr_t addr) +uint32_t lduw_le_phys(hwaddr addr) { return lduw_phys_internal(addr, DEVICE_LITTLE_ENDIAN); } -uint32_t lduw_be_phys(target_phys_addr_t addr) +uint32_t lduw_be_phys(hwaddr addr) { return lduw_phys_internal(addr, DEVICE_BIG_ENDIAN); } @@ -3830,7 +3830,7 @@ uint32_t lduw_be_phys(target_phys_addr_t addr) /* warning: addr must be aligned. The ram page is not masked as dirty and the code inside is not invalidated. It is useful if the dirty bits are used to track modified PTEs */ -void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val) +void stl_phys_notdirty(hwaddr addr, uint32_t val) { uint8_t *ptr; MemoryRegionSection *section; @@ -3862,7 +3862,7 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val) } } -void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val) +void stq_phys_notdirty(hwaddr addr, uint64_t val) { uint8_t *ptr; MemoryRegionSection *section; @@ -3890,7 +3890,7 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val) } /* warning: addr must be aligned */ -static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val, +static inline void stl_phys_internal(hwaddr addr, uint32_t val, enum device_endian endian) { uint8_t *ptr; @@ -3934,30 +3934,30 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val, } } -void stl_phys(target_phys_addr_t addr, uint32_t val) +void stl_phys(hwaddr addr, uint32_t val) { stl_phys_internal(addr, val, DEVICE_NATIVE_ENDIAN); } -void stl_le_phys(target_phys_addr_t addr, uint32_t val) +void stl_le_phys(hwaddr addr, uint32_t val) { stl_phys_internal(addr, val, DEVICE_LITTLE_ENDIAN); } -void stl_be_phys(target_phys_addr_t addr, uint32_t val) +void stl_be_phys(hwaddr addr, uint32_t val) { stl_phys_internal(addr, val, DEVICE_BIG_ENDIAN); } /* XXX: optimize */ -void stb_phys(target_phys_addr_t addr, uint32_t val) +void stb_phys(hwaddr addr, uint32_t val) { uint8_t v = val; cpu_physical_memory_write(addr, &v, 1); } /* warning: addr must be aligned */ -static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val, +static inline void stw_phys_internal(hwaddr addr, uint32_t val, enum device_endian endian) { uint8_t *ptr; @@ -4001,35 +4001,35 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val, } } -void stw_phys(target_phys_addr_t addr, uint32_t val) +void stw_phys(hwaddr addr, uint32_t val) { stw_phys_internal(addr, val, DEVICE_NATIVE_ENDIAN); } -void stw_le_phys(target_phys_addr_t addr, uint32_t val) +void stw_le_phys(hwaddr addr, uint32_t val) { stw_phys_internal(addr, val, DEVICE_LITTLE_ENDIAN); } -void stw_be_phys(target_phys_addr_t addr, uint32_t val) +void stw_be_phys(hwaddr addr, uint32_t val) { stw_phys_internal(addr, val, DEVICE_BIG_ENDIAN); } /* XXX: optimize */ -void stq_phys(target_phys_addr_t addr, uint64_t val) +void stq_phys(hwaddr addr, uint64_t val) { val = tswap64(val); cpu_physical_memory_write(addr, &val, 8); } -void stq_le_phys(target_phys_addr_t addr, uint64_t val) +void stq_le_phys(hwaddr addr, uint64_t val) { val = cpu_to_le64(val); cpu_physical_memory_write(addr, &val, 8); } -void stq_be_phys(target_phys_addr_t addr, uint64_t val) +void stq_be_phys(hwaddr addr, uint64_t val) { val = cpu_to_be64(val); cpu_physical_memory_write(addr, &val, 8); @@ -4040,7 +4040,7 @@ int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr, uint8_t *buf, int len, int is_write) { int l; - target_phys_addr_t phys_addr; + hwaddr phys_addr; target_ulong page; while (len > 0) { @@ -4195,7 +4195,7 @@ bool virtio_is_big_endian(void) #endif #ifndef CONFIG_USER_ONLY -bool cpu_physical_memory_is_io(target_phys_addr_t phys_addr) +bool cpu_physical_memory_is_io(hwaddr phys_addr) { MemoryRegionSection *section; diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c index ebd5b29173..824ff0a4de 100644 --- a/hw/a9mpcore.c +++ b/hw/a9mpcore.c @@ -26,7 +26,7 @@ typedef struct a9mp_priv_state { uint32_t num_irq; } a9mp_priv_state; -static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset, +static uint64_t a9_scu_read(void *opaque, hwaddr offset, unsigned size) { a9mp_priv_state *s = (a9mp_priv_state *)opaque; @@ -57,7 +57,7 @@ static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset, } } -static void a9_scu_write(void *opaque, target_phys_addr_t offset, +static void a9_scu_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { a9mp_priv_state *s = (a9mp_priv_state *)opaque; diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c index 8079a46ae0..7e7b1d27d2 100644 --- a/hw/alpha_pci.c +++ b/hw/alpha_pci.c @@ -15,7 +15,7 @@ /* PCI IO reads/writes, to byte-word addressable memory. */ /* ??? Doesn't handle multiple PCI busses. */ -static uint64_t bw_io_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t bw_io_read(void *opaque, hwaddr addr, unsigned size) { switch (size) { case 1: @@ -28,7 +28,7 @@ static uint64_t bw_io_read(void *opaque, target_phys_addr_t addr, unsigned size) abort(); } -static void bw_io_write(void *opaque, target_phys_addr_t addr, +static void bw_io_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { switch (size) { @@ -57,14 +57,14 @@ const MemoryRegionOps alpha_pci_bw_io_ops = { }; /* PCI config space reads/writes, to byte-word addressable memory. */ -static uint64_t bw_conf1_read(void *opaque, target_phys_addr_t addr, +static uint64_t bw_conf1_read(void *opaque, hwaddr addr, unsigned size) { PCIBus *b = opaque; return pci_data_read(b, addr, size); } -static void bw_conf1_write(void *opaque, target_phys_addr_t addr, +static void bw_conf1_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { PCIBus *b = opaque; @@ -83,12 +83,12 @@ const MemoryRegionOps alpha_pci_conf1_ops = { /* PCI/EISA Interrupt Acknowledge Cycle. */ -static uint64_t iack_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t iack_read(void *opaque, hwaddr addr, unsigned size) { return pic_read_irq(isa_pic); } -static void special_write(void *opaque, target_phys_addr_t addr, +static void special_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { qemu_log("pci: special write cycle"); diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c index b7cf4e2900..9b16d96612 100644 --- a/hw/alpha_typhoon.c +++ b/hw/alpha_typhoon.c @@ -70,7 +70,7 @@ static void cpu_irq_change(CPUAlphaState *env, uint64_t req) } } -static uint64_t cchip_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size) { CPUAlphaState *env = cpu_single_env; TyphoonState *s = opaque; @@ -203,13 +203,13 @@ static uint64_t cchip_read(void *opaque, target_phys_addr_t addr, unsigned size) return ret; } -static uint64_t dchip_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t dchip_read(void *opaque, hwaddr addr, unsigned size) { /* Skip this. It's all related to DRAM timing and setup. */ return 0; } -static uint64_t pchip_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size) { TyphoonState *s = opaque; uint64_t ret = 0; @@ -306,7 +306,7 @@ static uint64_t pchip_read(void *opaque, target_phys_addr_t addr, unsigned size) return ret; } -static void cchip_write(void *opaque, target_phys_addr_t addr, +static void cchip_write(void *opaque, hwaddr addr, uint64_t v32, unsigned size) { TyphoonState *s = opaque; @@ -463,13 +463,13 @@ static void cchip_write(void *opaque, target_phys_addr_t addr, } } -static void dchip_write(void *opaque, target_phys_addr_t addr, +static void dchip_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { /* Skip this. It's all related to DRAM timing and setup. */ } -static void pchip_write(void *opaque, target_phys_addr_t addr, +static void pchip_write(void *opaque, hwaddr addr, uint64_t v32, unsigned size) { TyphoonState *s = opaque; diff --git a/hw/an5206.c b/hw/an5206.c index 042c5fcd14..d887c0e7eb 100644 --- a/hw/an5206.c +++ b/hw/an5206.c @@ -27,7 +27,7 @@ static void an5206_init(QEMUMachineInitArgs *args) CPUM68KState *env; int kernel_size; uint64_t elf_entry; - target_phys_addr_t entry; + hwaddr entry; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *sram = g_new(MemoryRegion, 1); diff --git a/hw/apb_pci.c b/hw/apb_pci.c index c28411a460..054814fd4b 100644 --- a/hw/apb_pci.c +++ b/hw/apb_pci.c @@ -87,7 +87,7 @@ typedef struct APBState { static void pci_apb_set_irq(void *opaque, int irq_num, int level); -static void apb_config_writel (void *opaque, target_phys_addr_t addr, +static void apb_config_writel (void *opaque, hwaddr addr, uint64_t val, unsigned size) { APBState *s = opaque; @@ -152,7 +152,7 @@ static void apb_config_writel (void *opaque, target_phys_addr_t addr, } static uint64_t apb_config_readl (void *opaque, - target_phys_addr_t addr, unsigned size) + hwaddr addr, unsigned size) { APBState *s = opaque; uint32_t val; @@ -212,7 +212,7 @@ static const MemoryRegionOps apb_config_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void apb_pci_config_write(void *opaque, target_phys_addr_t addr, +static void apb_pci_config_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { APBState *s = opaque; @@ -222,7 +222,7 @@ static void apb_pci_config_write(void *opaque, target_phys_addr_t addr, pci_data_write(s->bus, addr, val, size); } -static uint64_t apb_pci_config_read(void *opaque, target_phys_addr_t addr, +static uint64_t apb_pci_config_read(void *opaque, hwaddr addr, unsigned size) { uint32_t ret; @@ -234,25 +234,25 @@ static uint64_t apb_pci_config_read(void *opaque, target_phys_addr_t addr, return ret; } -static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr, +static void pci_apb_iowriteb (void *opaque, hwaddr addr, uint32_t val) { cpu_outb(addr & IOPORTS_MASK, val); } -static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr, +static void pci_apb_iowritew (void *opaque, hwaddr addr, uint32_t val) { cpu_outw(addr & IOPORTS_MASK, bswap16(val)); } -static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr, +static void pci_apb_iowritel (void *opaque, hwaddr addr, uint32_t val) { cpu_outl(addr & IOPORTS_MASK, bswap32(val)); } -static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr) +static uint32_t pci_apb_ioreadb (void *opaque, hwaddr addr) { uint32_t val; @@ -260,7 +260,7 @@ static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr) return val; } -static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr) +static uint32_t pci_apb_ioreadw (void *opaque, hwaddr addr) { uint32_t val; @@ -268,7 +268,7 @@ static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr) return val; } -static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr) +static uint32_t pci_apb_ioreadl (void *opaque, hwaddr addr) { uint32_t val; @@ -351,8 +351,8 @@ static int apb_pci_bridge_initfn(PCIDevice *dev) return 0; } -PCIBus *pci_apb_init(target_phys_addr_t special_base, - target_phys_addr_t mem_base, +PCIBus *pci_apb_init(hwaddr special_base, + hwaddr mem_base, qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3, qemu_irq **pbm_irqs) { diff --git a/hw/apb_pci.h b/hw/apb_pci.h index 55f7c4c3b2..736db6118e 100644 --- a/hw/apb_pci.h +++ b/hw/apb_pci.h @@ -3,8 +3,8 @@ #include "qemu-common.h" -PCIBus *pci_apb_init(target_phys_addr_t special_base, - target_phys_addr_t mem_base, +PCIBus *pci_apb_init(hwaddr special_base, + hwaddr mem_base, qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3, qemu_irq **pbm_irqs); #endif diff --git a/hw/apic.c b/hw/apic.c index 385555eb43..49f00152ae 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -630,25 +630,25 @@ static void apic_timer(void *opaque) apic_timer_update(s, s->next_time); } -static uint32_t apic_mem_readb(void *opaque, target_phys_addr_t addr) +static uint32_t apic_mem_readb(void *opaque, hwaddr addr) { return 0; } -static uint32_t apic_mem_readw(void *opaque, target_phys_addr_t addr) +static uint32_t apic_mem_readw(void *opaque, hwaddr addr) { return 0; } -static void apic_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +static void apic_mem_writeb(void *opaque, hwaddr addr, uint32_t val) { } -static void apic_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +static void apic_mem_writew(void *opaque, hwaddr addr, uint32_t val) { } -static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr) +static uint32_t apic_mem_readl(void *opaque, hwaddr addr) { DeviceState *d; APICCommonState *s; @@ -732,7 +732,7 @@ static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr) return val; } -static void apic_send_msi(target_phys_addr_t addr, uint32_t data) +static void apic_send_msi(hwaddr addr, uint32_t data) { uint8_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT; uint8_t vector = (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT; @@ -743,7 +743,7 @@ static void apic_send_msi(target_phys_addr_t addr, uint32_t data) apic_deliver_irq(dest, dest_mode, delivery, vector, trigger_mode); } -static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val) { DeviceState *d; APICCommonState *s; diff --git a/hw/apic_common.c b/hw/apic_common.c index 371f95d909..d68116d490 100644 --- a/hw/apic_common.c +++ b/hw/apic_common.c @@ -89,7 +89,7 @@ void apic_enable_tpr_access_reporting(DeviceState *d, bool enable) } } -void apic_enable_vapic(DeviceState *d, target_phys_addr_t paddr) +void apic_enable_vapic(DeviceState *d, hwaddr paddr) { APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); APICCommonClass *info = APIC_COMMON_GET_CLASS(s); diff --git a/hw/apic_internal.h b/hw/apic_internal.h index 4d8ff490ce..30932a303a 100644 --- a/hw/apic_internal.h +++ b/hw/apic_internal.h @@ -124,7 +124,7 @@ struct APICCommonState { uint32_t vapic_control; DeviceState *vapic; - target_phys_addr_t vapic_paddr; /* note: persistence via kvmvapic */ + hwaddr vapic_paddr; /* note: persistence via kvmvapic */ }; typedef struct VAPICState { @@ -140,7 +140,7 @@ extern bool apic_report_tpr_access; void apic_report_irq_delivered(int delivered); bool apic_next_timer(APICCommonState *s, int64_t current_time); void apic_enable_tpr_access_reporting(DeviceState *d, bool enable); -void apic_enable_vapic(DeviceState *d, target_phys_addr_t paddr); +void apic_enable_vapic(DeviceState *d, hwaddr paddr); void vapic_report_tpr_access(DeviceState *dev, void *cpu, target_ulong ip, TPRAccess access); diff --git a/hw/arm-misc.h b/hw/arm-misc.h index bdd8fecc99..d02f7f08c8 100644 --- a/hw/arm-misc.h +++ b/hw/arm-misc.h @@ -30,15 +30,15 @@ struct arm_boot_info { const char *kernel_cmdline; const char *initrd_filename; const char *dtb_filename; - target_phys_addr_t loader_start; + hwaddr loader_start; /* multicore boards that use the default secondary core boot functions * need to put the address of the secondary boot code, the boot reg, * and the GIC address in the next 3 values, respectively. boards that * have their own boot functions can use these values as they want. */ - target_phys_addr_t smp_loader_start; - target_phys_addr_t smp_bootreg_addr; - target_phys_addr_t gic_cpu_if_addr; + hwaddr smp_loader_start; + hwaddr smp_bootreg_addr; + hwaddr gic_cpu_if_addr; int nb_cpus; int board_id; int (*atag_board)(const struct arm_boot_info *info, void *p); @@ -56,8 +56,8 @@ struct arm_boot_info { const struct arm_boot_info *info); /* Used internally by arm_boot.c */ int is_linux; - target_phys_addr_t initrd_size; - target_phys_addr_t entry; + hwaddr initrd_size; + hwaddr entry; }; void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info); diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c index 1bff3d3282..105f158fd4 100644 --- a/hw/arm11mpcore.c +++ b/hw/arm11mpcore.c @@ -27,7 +27,7 @@ typedef struct mpcore_priv_state { /* Per-CPU private memory mapped IO. */ -static uint64_t mpcore_scu_read(void *opaque, target_phys_addr_t offset, +static uint64_t mpcore_scu_read(void *opaque, hwaddr offset, unsigned size) { mpcore_priv_state *s = (mpcore_priv_state *)opaque; @@ -48,7 +48,7 @@ static uint64_t mpcore_scu_read(void *opaque, target_phys_addr_t offset, } } -static void mpcore_scu_write(void *opaque, target_phys_addr_t offset, +static void mpcore_scu_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { mpcore_priv_state *s = (mpcore_priv_state *)opaque; @@ -89,7 +89,7 @@ static void mpcore_priv_map_setup(mpcore_priv_state *s) * at 0x200, 0x300... */ for (i = 0; i < (s->num_cpu + 1); i++) { - target_phys_addr_t offset = 0x100 + (i * 0x100); + hwaddr offset = 0x100 + (i * 0x100); memory_region_add_subregion(&s->container, offset, sysbus_mmio_get_region(gicbusdev, i + 1)); } @@ -98,7 +98,7 @@ static void mpcore_priv_map_setup(mpcore_priv_state *s) */ for (i = 0; i < (s->num_cpu + 1) * 2; i++) { /* Timers at 0x600, 0x700, ...; watchdogs at 0x620, 0x720, ... */ - target_phys_addr_t offset = 0x600 + (i >> 1) * 0x100 + (i & 1) * 0x20; + hwaddr offset = 0x600 + (i >> 1) * 0x100 + (i & 1) * 0x20; memory_region_add_subregion(&s->container, offset, sysbus_mmio_get_region(busdev, i)); } diff --git a/hw/arm_boot.c b/hw/arm_boot.c index a6e9143662..09bf6c5cdc 100644 --- a/hw/arm_boot.c +++ b/hw/arm_boot.c @@ -89,8 +89,8 @@ static void default_reset_secondary(ARMCPU *cpu, static void set_kernel_args(const struct arm_boot_info *info) { int initrd_size = info->initrd_size; - target_phys_addr_t base = info->loader_start; - target_phys_addr_t p; + hwaddr base = info->loader_start; + hwaddr p; p = base + KERNEL_ARGS_ADDR; /* ATAG_CORE */ @@ -142,10 +142,10 @@ static void set_kernel_args(const struct arm_boot_info *info) static void set_kernel_args_old(const struct arm_boot_info *info) { - target_phys_addr_t p; + hwaddr p; const char *s; int initrd_size = info->initrd_size; - target_phys_addr_t base = info->loader_start; + hwaddr base = info->loader_start; /* see linux/include/asm-arm/setup.h */ p = base + KERNEL_ARGS_ADDR; @@ -213,7 +213,7 @@ static void set_kernel_args_old(const struct arm_boot_info *info) } } -static int load_dtb(target_phys_addr_t addr, const struct arm_boot_info *binfo) +static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo) { #ifdef CONFIG_FDT uint32_t *mem_reg_property; @@ -342,7 +342,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) int n; int is_linux = 0; uint64_t elf_entry; - target_phys_addr_t entry; + hwaddr entry; int big_endian; QemuOpts *machine_opts; @@ -419,7 +419,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) */ if (info->dtb_filename) { /* Place the DTB after the initrd in memory */ - target_phys_addr_t dtb_start = TARGET_PAGE_ALIGN(info->loader_start + hwaddr dtb_start = TARGET_PAGE_ALIGN(info->loader_start + INITRD_LOAD_ADDR + initrd_size); if (load_dtb(dtb_start, info)) { diff --git a/hw/arm_gic.c b/hw/arm_gic.c index 56376c0d75..ce16e8367f 100644 --- a/hw/arm_gic.c +++ b/hw/arm_gic.c @@ -212,7 +212,7 @@ void gic_complete_irq(GICState *s, int cpu, int irq) } } -static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset) +static uint32_t gic_dist_readb(void *opaque, hwaddr offset) { GICState *s = (GICState *)opaque; uint32_t res; @@ -328,7 +328,7 @@ bad_reg: return 0; } -static uint32_t gic_dist_readw(void *opaque, target_phys_addr_t offset) +static uint32_t gic_dist_readw(void *opaque, hwaddr offset) { uint32_t val; val = gic_dist_readb(opaque, offset); @@ -336,7 +336,7 @@ static uint32_t gic_dist_readw(void *opaque, target_phys_addr_t offset) return val; } -static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset) +static uint32_t gic_dist_readl(void *opaque, hwaddr offset) { uint32_t val; val = gic_dist_readw(opaque, offset); @@ -344,7 +344,7 @@ static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset) return val; } -static void gic_dist_writeb(void *opaque, target_phys_addr_t offset, +static void gic_dist_writeb(void *opaque, hwaddr offset, uint32_t value) { GICState *s = (GICState *)opaque; @@ -490,14 +490,14 @@ bad_reg: hw_error("gic_dist_writeb: Bad offset %x\n", (int)offset); } -static void gic_dist_writew(void *opaque, target_phys_addr_t offset, +static void gic_dist_writew(void *opaque, hwaddr offset, uint32_t value) { gic_dist_writeb(opaque, offset, value & 0xff); gic_dist_writeb(opaque, offset + 1, value >> 8); } -static void gic_dist_writel(void *opaque, target_phys_addr_t offset, +static void gic_dist_writel(void *opaque, hwaddr offset, uint32_t value) { GICState *s = (GICState *)opaque; @@ -584,14 +584,14 @@ static void gic_cpu_write(GICState *s, int cpu, int offset, uint32_t value) } /* Wrappers to read/write the GIC CPU interface for the current CPU */ -static uint64_t gic_thiscpu_read(void *opaque, target_phys_addr_t addr, +static uint64_t gic_thiscpu_read(void *opaque, hwaddr addr, unsigned size) { GICState *s = (GICState *)opaque; return gic_cpu_read(s, gic_get_current_cpu(s), addr); } -static void gic_thiscpu_write(void *opaque, target_phys_addr_t addr, +static void gic_thiscpu_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { GICState *s = (GICState *)opaque; @@ -601,7 +601,7 @@ static void gic_thiscpu_write(void *opaque, target_phys_addr_t addr, /* Wrappers to read/write the GIC CPU interface for a specific CPU. * These just decode the opaque pointer into GICState* + cpu id. */ -static uint64_t gic_do_cpu_read(void *opaque, target_phys_addr_t addr, +static uint64_t gic_do_cpu_read(void *opaque, hwaddr addr, unsigned size) { GICState **backref = (GICState **)opaque; @@ -610,7 +610,7 @@ static uint64_t gic_do_cpu_read(void *opaque, target_phys_addr_t addr, return gic_cpu_read(s, id, addr); } -static void gic_do_cpu_write(void *opaque, target_phys_addr_t addr, +static void gic_do_cpu_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { GICState **backref = (GICState **)opaque; diff --git a/hw/arm_l2x0.c b/hw/arm_l2x0.c index de6a0863d8..8f5921c3a6 100644 --- a/hw/arm_l2x0.c +++ b/hw/arm_l2x0.c @@ -51,7 +51,7 @@ static const VMStateDescription vmstate_l2x0 = { }; -static uint64_t l2x0_priv_read(void *opaque, target_phys_addr_t offset, +static uint64_t l2x0_priv_read(void *opaque, hwaddr offset, unsigned size) { uint32_t cache_data; @@ -93,7 +93,7 @@ static uint64_t l2x0_priv_read(void *opaque, target_phys_addr_t offset, return 0; } -static void l2x0_priv_write(void *opaque, target_phys_addr_t offset, +static void l2x0_priv_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { l2x0_state *s = (l2x0_state *)opaque; diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c index fe43cbb5f1..6790832236 100644 --- a/hw/arm_mptimer.c +++ b/hw/arm_mptimer.c @@ -92,7 +92,7 @@ static void timerblock_tick(void *opaque) timerblock_update_irq(tb); } -static uint64_t timerblock_read(void *opaque, target_phys_addr_t addr, +static uint64_t timerblock_read(void *opaque, hwaddr addr, unsigned size) { timerblock *tb = (timerblock *)opaque; @@ -120,7 +120,7 @@ static uint64_t timerblock_read(void *opaque, target_phys_addr_t addr, } } -static void timerblock_write(void *opaque, target_phys_addr_t addr, +static void timerblock_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { timerblock *tb = (timerblock *)opaque; @@ -159,7 +159,7 @@ static void timerblock_write(void *opaque, target_phys_addr_t addr, /* Wrapper functions to implement the "read timer/watchdog for * the current CPU" memory regions. */ -static uint64_t arm_thistimer_read(void *opaque, target_phys_addr_t addr, +static uint64_t arm_thistimer_read(void *opaque, hwaddr addr, unsigned size) { arm_mptimer_state *s = (arm_mptimer_state *)opaque; @@ -167,7 +167,7 @@ static uint64_t arm_thistimer_read(void *opaque, target_phys_addr_t addr, return timerblock_read(&s->timerblock[id * 2], addr, size); } -static void arm_thistimer_write(void *opaque, target_phys_addr_t addr, +static void arm_thistimer_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { arm_mptimer_state *s = (arm_mptimer_state *)opaque; @@ -175,7 +175,7 @@ static void arm_thistimer_write(void *opaque, target_phys_addr_t addr, timerblock_write(&s->timerblock[id * 2], addr, value, size); } -static uint64_t arm_thiswdog_read(void *opaque, target_phys_addr_t addr, +static uint64_t arm_thiswdog_read(void *opaque, hwaddr addr, unsigned size) { arm_mptimer_state *s = (arm_mptimer_state *)opaque; @@ -183,7 +183,7 @@ static uint64_t arm_thiswdog_read(void *opaque, target_phys_addr_t addr, return timerblock_read(&s->timerblock[id * 2 + 1], addr, size); } -static void arm_thiswdog_write(void *opaque, target_phys_addr_t addr, +static void arm_thiswdog_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { arm_mptimer_state *s = (arm_mptimer_state *)opaque; diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c index 5f1237b8c2..26318e14d5 100644 --- a/hw/arm_sysctl.c +++ b/hw/arm_sysctl.c @@ -92,7 +92,7 @@ static void arm_sysctl_reset(DeviceState *d) } } -static uint64_t arm_sysctl_read(void *opaque, target_phys_addr_t offset, +static uint64_t arm_sysctl_read(void *opaque, hwaddr offset, unsigned size) { arm_sysctl_state *s = (arm_sysctl_state *)opaque; @@ -189,7 +189,7 @@ static uint64_t arm_sysctl_read(void *opaque, target_phys_addr_t offset, } } -static void arm_sysctl_write(void *opaque, target_phys_addr_t offset, +static void arm_sysctl_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { arm_sysctl_state *s = (arm_sysctl_state *)opaque; diff --git a/hw/arm_timer.c b/hw/arm_timer.c index e3ecce29f0..2e136216c6 100644 --- a/hw/arm_timer.c +++ b/hw/arm_timer.c @@ -45,7 +45,7 @@ static void arm_timer_update(arm_timer_state *s) } } -static uint32_t arm_timer_read(void *opaque, target_phys_addr_t offset) +static uint32_t arm_timer_read(void *opaque, hwaddr offset) { arm_timer_state *s = (arm_timer_state *)opaque; @@ -87,7 +87,7 @@ static void arm_timer_recalibrate(arm_timer_state *s, int reload) ptimer_set_limit(s->timer, limit, reload); } -static void arm_timer_write(void *opaque, target_phys_addr_t offset, +static void arm_timer_write(void *opaque, hwaddr offset, uint32_t value) { arm_timer_state *s = (arm_timer_state *)opaque; @@ -202,7 +202,7 @@ static void sp804_set_irq(void *opaque, int irq, int level) qemu_set_irq(s->irq, s->level[0] || s->level[1]); } -static uint64_t sp804_read(void *opaque, target_phys_addr_t offset, +static uint64_t sp804_read(void *opaque, hwaddr offset, unsigned size) { sp804_state *s = (sp804_state *)opaque; @@ -230,7 +230,7 @@ static uint64_t sp804_read(void *opaque, target_phys_addr_t offset, return 0; } -static void sp804_write(void *opaque, target_phys_addr_t offset, +static void sp804_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { sp804_state *s = (sp804_state *)opaque; @@ -291,7 +291,7 @@ typedef struct { arm_timer_state *timer[3]; } icp_pit_state; -static uint64_t icp_pit_read(void *opaque, target_phys_addr_t offset, +static uint64_t icp_pit_read(void *opaque, hwaddr offset, unsigned size) { icp_pit_state *s = (icp_pit_state *)opaque; @@ -306,7 +306,7 @@ static uint64_t icp_pit_read(void *opaque, target_phys_addr_t offset, return arm_timer_read(s->timer[n], offset & 0xff); } -static void icp_pit_write(void *opaque, target_phys_addr_t offset, +static void icp_pit_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { icp_pit_state *s = (icp_pit_state *)opaque; diff --git a/hw/armv7m.c b/hw/armv7m.c index 9f66667c6d..ce2ec9b4dc 100644 --- a/hw/armv7m.c +++ b/hw/armv7m.c @@ -25,14 +25,14 @@ static inline uint32_t bitband_addr(void * opaque, uint32_t addr) } -static uint32_t bitband_readb(void *opaque, target_phys_addr_t offset) +static uint32_t bitband_readb(void *opaque, hwaddr offset) { uint8_t v; cpu_physical_memory_read(bitband_addr(opaque, offset), &v, 1); return (v & (1 << ((offset >> 2) & 7))) != 0; } -static void bitband_writeb(void *opaque, target_phys_addr_t offset, +static void bitband_writeb(void *opaque, hwaddr offset, uint32_t value) { uint32_t addr; @@ -48,7 +48,7 @@ static void bitband_writeb(void *opaque, target_phys_addr_t offset, cpu_physical_memory_write(addr, &v, 1); } -static uint32_t bitband_readw(void *opaque, target_phys_addr_t offset) +static uint32_t bitband_readw(void *opaque, hwaddr offset) { uint32_t addr; uint16_t mask; @@ -60,7 +60,7 @@ static uint32_t bitband_readw(void *opaque, target_phys_addr_t offset) return (v & mask) != 0; } -static void bitband_writew(void *opaque, target_phys_addr_t offset, +static void bitband_writew(void *opaque, hwaddr offset, uint32_t value) { uint32_t addr; @@ -77,7 +77,7 @@ static void bitband_writew(void *opaque, target_phys_addr_t offset, cpu_physical_memory_write(addr, (uint8_t *)&v, 2); } -static uint32_t bitband_readl(void *opaque, target_phys_addr_t offset) +static uint32_t bitband_readl(void *opaque, hwaddr offset) { uint32_t addr; uint32_t mask; @@ -89,7 +89,7 @@ static uint32_t bitband_readl(void *opaque, target_phys_addr_t offset) return (v & mask) != 0; } -static void bitband_writel(void *opaque, target_phys_addr_t offset, +static void bitband_writel(void *opaque, hwaddr offset, uint32_t value) { uint32_t addr; diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c index c449e08089..35c1aa67e2 100644 --- a/hw/armv7m_nvic.c +++ b/hw/armv7m_nvic.c @@ -392,7 +392,7 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value) } } -static uint64_t nvic_sysreg_read(void *opaque, target_phys_addr_t addr, +static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr, unsigned size) { /* At the moment we only support the ID registers for byte/word access. @@ -412,7 +412,7 @@ static uint64_t nvic_sysreg_read(void *opaque, target_phys_addr_t addr, hw_error("NVIC: Bad read of size %d at offset 0x%x\n", size, offset); } -static void nvic_sysreg_write(void *opaque, target_phys_addr_t addr, +static void nvic_sysreg_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { uint32_t offset = addr; diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c index 2fd7356fce..aa1ac9e479 100644 --- a/hw/axis_dev88.c +++ b/hw/axis_dev88.c @@ -47,7 +47,7 @@ struct nand_state_t }; static struct nand_state_t nand_state; -static uint64_t nand_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t nand_read(void *opaque, hwaddr addr, unsigned size) { struct nand_state_t *s = opaque; uint32_t r; @@ -62,7 +62,7 @@ static uint64_t nand_read(void *opaque, target_phys_addr_t addr, unsigned size) } static void -nand_write(void *opaque, target_phys_addr_t addr, uint64_t value, +nand_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct nand_state_t *s = opaque; @@ -166,7 +166,7 @@ static struct gpio_state_t uint32_t regs[0x5c / 4]; } gpio_state; -static uint64_t gpio_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t gpio_read(void *opaque, hwaddr addr, unsigned size) { struct gpio_state_t *s = opaque; uint32_t r = 0; @@ -195,7 +195,7 @@ static uint64_t gpio_read(void *opaque, target_phys_addr_t addr, unsigned size) D(printf("%s %x=%x\n", __func__, addr, r)); } -static void gpio_write(void *opaque, target_phys_addr_t addr, uint64_t value, +static void gpio_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct gpio_state_t *s = opaque; diff --git a/hw/bonito.c b/hw/bonito.c index 6084ac48fa..0bf6d4aa5f 100644 --- a/hw/bonito.c +++ b/hw/bonito.c @@ -211,12 +211,12 @@ typedef struct PCIBonitoState MemoryRegion iomem_ldma; MemoryRegion iomem_cop; - target_phys_addr_t bonito_pciio_start; - target_phys_addr_t bonito_pciio_length; + hwaddr bonito_pciio_start; + hwaddr bonito_pciio_length; int bonito_pciio_handle; - target_phys_addr_t bonito_localio_start; - target_phys_addr_t bonito_localio_length; + hwaddr bonito_localio_start; + hwaddr bonito_localio_length; int bonito_localio_handle; } PCIBonitoState; @@ -232,7 +232,7 @@ struct BonitoState { PCIBonitoState *pci_dev; }; -static void bonito_writel(void *opaque, target_phys_addr_t addr, +static void bonito_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size) { PCIBonitoState *s = opaque; @@ -295,7 +295,7 @@ static void bonito_writel(void *opaque, target_phys_addr_t addr, } } -static uint64_t bonito_readl(void *opaque, target_phys_addr_t addr, +static uint64_t bonito_readl(void *opaque, hwaddr addr, unsigned size) { PCIBonitoState *s = opaque; @@ -322,7 +322,7 @@ static const MemoryRegionOps bonito_ops = { }, }; -static void bonito_pciconf_writel(void *opaque, target_phys_addr_t addr, +static void bonito_pciconf_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size) { PCIBonitoState *s = opaque; @@ -332,7 +332,7 @@ static void bonito_pciconf_writel(void *opaque, target_phys_addr_t addr, d->config_write(d, addr, val, 4); } -static uint64_t bonito_pciconf_readl(void *opaque, target_phys_addr_t addr, +static uint64_t bonito_pciconf_readl(void *opaque, hwaddr addr, unsigned size) { @@ -355,7 +355,7 @@ static const MemoryRegionOps bonito_pciconf_ops = { }, }; -static uint64_t bonito_ldma_readl(void *opaque, target_phys_addr_t addr, +static uint64_t bonito_ldma_readl(void *opaque, hwaddr addr, unsigned size) { uint32_t val; @@ -366,7 +366,7 @@ static uint64_t bonito_ldma_readl(void *opaque, target_phys_addr_t addr, return val; } -static void bonito_ldma_writel(void *opaque, target_phys_addr_t addr, +static void bonito_ldma_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size) { PCIBonitoState *s = opaque; @@ -384,7 +384,7 @@ static const MemoryRegionOps bonito_ldma_ops = { }, }; -static uint64_t bonito_cop_readl(void *opaque, target_phys_addr_t addr, +static uint64_t bonito_cop_readl(void *opaque, hwaddr addr, unsigned size) { uint32_t val; @@ -395,7 +395,7 @@ static uint64_t bonito_cop_readl(void *opaque, target_phys_addr_t addr, return val; } -static void bonito_cop_writel(void *opaque, target_phys_addr_t addr, +static void bonito_cop_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size) { PCIBonitoState *s = opaque; @@ -413,7 +413,7 @@ static const MemoryRegionOps bonito_cop_ops = { }, }; -static uint32_t bonito_sbridge_pciaddr(void *opaque, target_phys_addr_t addr) +static uint32_t bonito_sbridge_pciaddr(void *opaque, hwaddr addr) { PCIBonitoState *s = opaque; PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost); @@ -449,7 +449,7 @@ static uint32_t bonito_sbridge_pciaddr(void *opaque, target_phys_addr_t addr) return pciaddr; } -static void bonito_spciconf_writeb(void *opaque, target_phys_addr_t addr, +static void bonito_spciconf_writeb(void *opaque, hwaddr addr, uint32_t val) { PCIBonitoState *s = opaque; @@ -475,7 +475,7 @@ static void bonito_spciconf_writeb(void *opaque, target_phys_addr_t addr, pci_set_word(d->config + PCI_STATUS, status); } -static void bonito_spciconf_writew(void *opaque, target_phys_addr_t addr, +static void bonito_spciconf_writew(void *opaque, hwaddr addr, uint32_t val) { PCIBonitoState *s = opaque; @@ -503,7 +503,7 @@ static void bonito_spciconf_writew(void *opaque, target_phys_addr_t addr, pci_set_word(d->config + PCI_STATUS, status); } -static void bonito_spciconf_writel(void *opaque, target_phys_addr_t addr, +static void bonito_spciconf_writel(void *opaque, hwaddr addr, uint32_t val) { PCIBonitoState *s = opaque; @@ -531,7 +531,7 @@ static void bonito_spciconf_writel(void *opaque, target_phys_addr_t addr, pci_set_word(d->config + PCI_STATUS, status); } -static uint32_t bonito_spciconf_readb(void *opaque, target_phys_addr_t addr) +static uint32_t bonito_spciconf_readb(void *opaque, hwaddr addr) { PCIBonitoState *s = opaque; PCIDevice *d = PCI_DEVICE(s); @@ -557,7 +557,7 @@ static uint32_t bonito_spciconf_readb(void *opaque, target_phys_addr_t addr) return pci_data_read(phb->bus, phb->config_reg, 1); } -static uint32_t bonito_spciconf_readw(void *opaque, target_phys_addr_t addr) +static uint32_t bonito_spciconf_readw(void *opaque, hwaddr addr) { PCIBonitoState *s = opaque; PCIDevice *d = PCI_DEVICE(s); @@ -585,7 +585,7 @@ static uint32_t bonito_spciconf_readw(void *opaque, target_phys_addr_t addr) return pci_data_read(phb->bus, phb->config_reg, 2); } -static uint32_t bonito_spciconf_readl(void *opaque, target_phys_addr_t addr) +static uint32_t bonito_spciconf_readl(void *opaque, hwaddr addr) { PCIBonitoState *s = opaque; PCIDevice *d = PCI_DEVICE(s); diff --git a/hw/cadence_gem.c b/hw/cadence_gem.c index 967f62513e..0c037a2993 100644 --- a/hw/cadence_gem.c +++ b/hw/cadence_gem.c @@ -605,7 +605,7 @@ static int gem_mac_address_filter(GemState *s, const uint8_t *packet) static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) { unsigned desc[2]; - target_phys_addr_t packet_desc_addr, last_desc_addr; + hwaddr packet_desc_addr, last_desc_addr; GemState *s; unsigned rxbufsize, bytes_to_copy; unsigned rxbuf_offset; @@ -824,7 +824,7 @@ static void gem_transmit_updatestats(GemState *s, const uint8_t *packet, static void gem_transmit(GemState *s) { unsigned desc[2]; - target_phys_addr_t packet_desc_addr; + hwaddr packet_desc_addr; uint8_t tx_packet[2048]; uint8_t *p; unsigned total_bytes; @@ -1021,7 +1021,7 @@ static void gem_phy_write(GemState *s, unsigned reg_num, uint16_t val) * gem_read32: * Read a GEM register. */ -static uint64_t gem_read(void *opaque, target_phys_addr_t offset, unsigned size) +static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size) { GemState *s; uint32_t retval; @@ -1067,7 +1067,7 @@ static uint64_t gem_read(void *opaque, target_phys_addr_t offset, unsigned size) * gem_write32: * Write a GEM register. */ -static void gem_write(void *opaque, target_phys_addr_t offset, uint64_t val, +static void gem_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { GemState *s = (GemState *)opaque; diff --git a/hw/cadence_ttc.c b/hw/cadence_ttc.c index 77b6976eda..ec78a52180 100644 --- a/hw/cadence_ttc.c +++ b/hw/cadence_ttc.c @@ -76,7 +76,7 @@ static void cadence_timer_update(CadenceTimerState *s) } static CadenceTimerState *cadence_timer_from_addr(void *opaque, - target_phys_addr_t offset) + hwaddr offset) { unsigned int index; CadenceTTCState *s = (CadenceTTCState *)opaque; @@ -224,7 +224,7 @@ static void cadence_timer_tick(void *opaque) cadence_timer_run(s); } -static uint32_t cadence_ttc_read_imp(void *opaque, target_phys_addr_t offset) +static uint32_t cadence_ttc_read_imp(void *opaque, hwaddr offset) { CadenceTimerState *s = cadence_timer_from_addr(opaque, offset); uint32_t value; @@ -297,7 +297,7 @@ static uint32_t cadence_ttc_read_imp(void *opaque, target_phys_addr_t offset) } } -static uint64_t cadence_ttc_read(void *opaque, target_phys_addr_t offset, +static uint64_t cadence_ttc_read(void *opaque, hwaddr offset, unsigned size) { uint32_t ret = cadence_ttc_read_imp(opaque, offset); @@ -306,7 +306,7 @@ static uint64_t cadence_ttc_read(void *opaque, target_phys_addr_t offset, return ret; } -static void cadence_ttc_write(void *opaque, target_phys_addr_t offset, +static void cadence_ttc_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { CadenceTimerState *s = cadence_timer_from_addr(opaque, offset); diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c index f8afc4ed26..a7d0504c58 100644 --- a/hw/cadence_uart.c +++ b/hw/cadence_uart.c @@ -354,7 +354,7 @@ static void uart_read_rx_fifo(UartState *s, uint32_t *c) uart_update_status(s); } -static void uart_write(void *opaque, target_phys_addr_t offset, +static void uart_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { UartState *s = (UartState *)opaque; @@ -397,7 +397,7 @@ static void uart_write(void *opaque, target_phys_addr_t offset, } } -static uint64_t uart_read(void *opaque, target_phys_addr_t offset, +static uint64_t uart_read(void *opaque, hwaddr offset, unsigned size) { UartState *s = (UartState *)opaque; diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index a10132953c..e4af2e9ded 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -1952,7 +1952,7 @@ static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s, ***************************************/ static uint64_t cirrus_vga_mem_read(void *opaque, - target_phys_addr_t addr, + hwaddr addr, uint32_t size) { CirrusVGAState *s = opaque; @@ -1996,7 +1996,7 @@ static uint64_t cirrus_vga_mem_read(void *opaque, } static void cirrus_vga_mem_write(void *opaque, - target_phys_addr_t addr, + hwaddr addr, uint64_t mem_value, uint32_t size) { @@ -2255,7 +2255,7 @@ static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y) * ***************************************/ -static uint64_t cirrus_linear_read(void *opaque, target_phys_addr_t addr, +static uint64_t cirrus_linear_read(void *opaque, hwaddr addr, unsigned size) { CirrusVGAState *s = opaque; @@ -2284,7 +2284,7 @@ static uint64_t cirrus_linear_read(void *opaque, target_phys_addr_t addr, return ret; } -static void cirrus_linear_write(void *opaque, target_phys_addr_t addr, +static void cirrus_linear_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { CirrusVGAState *s = opaque; @@ -2333,7 +2333,7 @@ static void cirrus_linear_write(void *opaque, target_phys_addr_t addr, static uint64_t cirrus_linear_bitblt_read(void *opaque, - target_phys_addr_t addr, + hwaddr addr, unsigned size) { CirrusVGAState *s = opaque; @@ -2346,7 +2346,7 @@ static uint64_t cirrus_linear_bitblt_read(void *opaque, } static void cirrus_linear_bitblt_write(void *opaque, - target_phys_addr_t addr, + hwaddr addr, uint64_t val, unsigned size) { @@ -2640,7 +2640,7 @@ static void cirrus_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) * ***************************************/ -static uint64_t cirrus_mmio_read(void *opaque, target_phys_addr_t addr, +static uint64_t cirrus_mmio_read(void *opaque, hwaddr addr, unsigned size) { CirrusVGAState *s = opaque; @@ -2652,7 +2652,7 @@ static uint64_t cirrus_mmio_read(void *opaque, target_phys_addr_t addr, } } -static void cirrus_mmio_write(void *opaque, target_phys_addr_t addr, +static void cirrus_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { CirrusVGAState *s = opaque; diff --git a/hw/cris-boot.h b/hw/cris-boot.h index 0a2c242411..5b17d83cbb 100644 --- a/hw/cris-boot.h +++ b/hw/cris-boot.h @@ -5,7 +5,7 @@ struct cris_load_info const char *cmdline; int image_size; - target_phys_addr_t entry; + hwaddr entry; }; void cris_load_image(CRISCPU *cpu, struct cris_load_info *li); diff --git a/hw/cs4231.c b/hw/cs4231.c index cfec1d9cd1..23570d5b41 100644 --- a/hw/cs4231.c +++ b/hw/cs4231.c @@ -55,7 +55,7 @@ static void cs_reset(DeviceState *d) s->dregs[25] = CS_VER; } -static uint64_t cs_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t cs_mem_read(void *opaque, hwaddr addr, unsigned size) { CSState *s = opaque; @@ -82,7 +82,7 @@ static uint64_t cs_mem_read(void *opaque, target_phys_addr_t addr, return ret; } -static void cs_mem_write(void *opaque, target_phys_addr_t addr, +static void cs_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { CSState *s = opaque; diff --git a/hw/cs4231a.c b/hw/cs4231a.c index e07b9d6237..0257fd8d2a 100644 --- a/hw/cs4231a.c +++ b/hw/cs4231a.c @@ -346,7 +346,7 @@ static void cs_reset_voices (CSState *s, uint32_t val) } } -static uint64_t cs_read (void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t cs_read (void *opaque, hwaddr addr, unsigned size) { CSState *s = opaque; uint32_t saddr, iaddr, ret; @@ -383,7 +383,7 @@ static uint64_t cs_read (void *opaque, target_phys_addr_t addr, unsigned size) return ret; } -static void cs_write (void *opaque, target_phys_addr_t addr, +static void cs_write (void *opaque, hwaddr addr, uint64_t val64, unsigned size) { CSState *s = opaque; diff --git a/hw/cuda.c b/hw/cuda.c index 233ab666da..f1f408b839 100644 --- a/hw/cuda.c +++ b/hw/cuda.c @@ -252,7 +252,7 @@ static void cuda_timer1(void *opaque) cuda_update_irq(s); } -static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr) +static uint32_t cuda_readb(void *opaque, hwaddr addr) { CUDAState *s = opaque; uint32_t val; @@ -325,7 +325,7 @@ static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr) return val; } -static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +static void cuda_writeb(void *opaque, hwaddr addr, uint32_t val) { CUDAState *s = opaque; @@ -616,20 +616,20 @@ static void cuda_receive_packet_from_host(CUDAState *s, } } -static void cuda_writew (void *opaque, target_phys_addr_t addr, uint32_t value) +static void cuda_writew (void *opaque, hwaddr addr, uint32_t value) { } -static void cuda_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +static void cuda_writel (void *opaque, hwaddr addr, uint32_t value) { } -static uint32_t cuda_readw (void *opaque, target_phys_addr_t addr) +static uint32_t cuda_readw (void *opaque, hwaddr addr) { return 0; } -static uint32_t cuda_readl (void *opaque, target_phys_addr_t addr) +static uint32_t cuda_readl (void *opaque, hwaddr addr) { return 0; } diff --git a/hw/dma.c b/hw/dma.c index 0a9322daa3..d6aeac2834 100644 --- a/hw/dma.c +++ b/hw/dma.c @@ -411,7 +411,7 @@ void DMA_register_channel (int nchan, int DMA_read_memory (int nchan, void *buf, int pos, int len) { struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3]; - target_phys_addr_t addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR]; + hwaddr addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR]; if (r->mode & 0x20) { int i; @@ -433,7 +433,7 @@ int DMA_read_memory (int nchan, void *buf, int pos, int len) int DMA_write_memory (int nchan, void *buf, int pos, int len) { struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3]; - target_phys_addr_t addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR]; + hwaddr addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR]; if (r->mode & 0x20) { int i; diff --git a/hw/dp8393x.c b/hw/dp8393x.c index 4fa6eccba4..3f6386eee8 100644 --- a/hw/dp8393x.c +++ b/hw/dp8393x.c @@ -168,7 +168,7 @@ typedef struct dp8393xState { int loopback_packet; /* Memory access */ - void (*memory_rw)(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write); + void (*memory_rw)(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write); void* mem_opaque; } dp8393xState; @@ -603,7 +603,7 @@ static void dp8393x_watchdog(void *opaque) dp8393x_update_irq(s); } -static uint32_t dp8393x_readw(void *opaque, target_phys_addr_t addr) +static uint32_t dp8393x_readw(void *opaque, hwaddr addr) { dp8393xState *s = opaque; int reg; @@ -616,13 +616,13 @@ static uint32_t dp8393x_readw(void *opaque, target_phys_addr_t addr) return read_register(s, reg); } -static uint32_t dp8393x_readb(void *opaque, target_phys_addr_t addr) +static uint32_t dp8393x_readb(void *opaque, hwaddr addr) { uint16_t v = dp8393x_readw(opaque, addr & ~0x1); return (v >> (8 * (addr & 0x1))) & 0xff; } -static uint32_t dp8393x_readl(void *opaque, target_phys_addr_t addr) +static uint32_t dp8393x_readl(void *opaque, hwaddr addr) { uint32_t v; v = dp8393x_readw(opaque, addr); @@ -630,7 +630,7 @@ static uint32_t dp8393x_readl(void *opaque, target_phys_addr_t addr) return v; } -static void dp8393x_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +static void dp8393x_writew(void *opaque, hwaddr addr, uint32_t val) { dp8393xState *s = opaque; int reg; @@ -644,7 +644,7 @@ static void dp8393x_writew(void *opaque, target_phys_addr_t addr, uint32_t val) write_register(s, reg, (uint16_t)val); } -static void dp8393x_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +static void dp8393x_writeb(void *opaque, hwaddr addr, uint32_t val) { uint16_t old_val = dp8393x_readw(opaque, addr & ~0x1); @@ -659,7 +659,7 @@ static void dp8393x_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) dp8393x_writew(opaque, addr & ~0x1, val); } -static void dp8393x_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +static void dp8393x_writel(void *opaque, hwaddr addr, uint32_t val) { dp8393x_writew(opaque, addr, val & 0xffff); dp8393x_writew(opaque, addr + 2, (val >> 16) & 0xffff); @@ -879,10 +879,10 @@ static NetClientInfo net_dp83932_info = { .cleanup = nic_cleanup, }; -void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift, +void dp83932_init(NICInfo *nd, hwaddr base, int it_shift, MemoryRegion *address_space, qemu_irq irq, void* mem_opaque, - void (*memory_rw)(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write)) + void (*memory_rw)(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write)) { dp8393xState *s; diff --git a/hw/ds1225y.c b/hw/ds1225y.c index 2cd355bd0a..4b3f69bc67 100644 --- a/hw/ds1225y.c +++ b/hw/ds1225y.c @@ -34,7 +34,7 @@ typedef struct { uint8_t *contents; } NvRamState; -static uint64_t nvram_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t nvram_read(void *opaque, hwaddr addr, unsigned size) { NvRamState *s = opaque; uint32_t val; @@ -44,7 +44,7 @@ static uint64_t nvram_read(void *opaque, target_phys_addr_t addr, unsigned size) return val; } -static void nvram_write(void *opaque, target_phys_addr_t addr, uint64_t val, +static void nvram_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { NvRamState *s = opaque; diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c index f436a0cbc6..20f790b1a6 100644 --- a/hw/dummy_m68k.c +++ b/hw/dummy_m68k.c @@ -26,7 +26,7 @@ static void dummy_m68k_init(QEMUMachineInitArgs *args) MemoryRegion *ram = g_new(MemoryRegion, 1); int kernel_size; uint64_t elf_entry; - target_phys_addr_t entry; + hwaddr entry; if (!cpu_model) cpu_model = "cfv4e"; diff --git a/hw/e1000.c b/hw/e1000.c index 63fee10794..e4f1ffef74 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -1011,7 +1011,7 @@ static void (*macreg_writeops[])(E1000State *, int, uint32_t) = { enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) }; static void -e1000_mmio_write(void *opaque, target_phys_addr_t addr, uint64_t val, +e1000_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { E1000State *s = opaque; @@ -1028,7 +1028,7 @@ e1000_mmio_write(void *opaque, target_phys_addr_t addr, uint64_t val, } static uint64_t -e1000_mmio_read(void *opaque, target_phys_addr_t addr, unsigned size) +e1000_mmio_read(void *opaque, hwaddr addr, unsigned size) { E1000State *s = opaque; unsigned int index = (addr & 0x1ffff) >> 2; @@ -1051,7 +1051,7 @@ static const MemoryRegionOps e1000_mmio_ops = { }, }; -static uint64_t e1000_io_read(void *opaque, target_phys_addr_t addr, +static uint64_t e1000_io_read(void *opaque, hwaddr addr, unsigned size) { E1000State *s = opaque; @@ -1060,7 +1060,7 @@ static uint64_t e1000_io_read(void *opaque, target_phys_addr_t addr, return 0; } -static void e1000_io_write(void *opaque, target_phys_addr_t addr, +static void e1000_io_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { E1000State *s = opaque; diff --git a/hw/eccmemctl.c b/hw/eccmemctl.c index fe1cd90007..000bd08dee 100644 --- a/hw/eccmemctl.c +++ b/hw/eccmemctl.c @@ -129,7 +129,7 @@ typedef struct ECCState { uint32_t version; } ECCState; -static void ecc_mem_write(void *opaque, target_phys_addr_t addr, uint64_t val, +static void ecc_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { ECCState *s = opaque; @@ -172,7 +172,7 @@ static void ecc_mem_write(void *opaque, target_phys_addr_t addr, uint64_t val, } } -static uint64_t ecc_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t ecc_mem_read(void *opaque, hwaddr addr, unsigned size) { ECCState *s = opaque; @@ -229,7 +229,7 @@ static const MemoryRegionOps ecc_mem_ops = { }, }; -static void ecc_diag_mem_write(void *opaque, target_phys_addr_t addr, +static void ecc_diag_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { ECCState *s = opaque; @@ -238,7 +238,7 @@ static void ecc_diag_mem_write(void *opaque, target_phys_addr_t addr, s->diag[addr & ECC_DIAG_MASK] = val; } -static uint64_t ecc_diag_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t ecc_diag_mem_read(void *opaque, hwaddr addr, unsigned size) { ECCState *s = opaque; diff --git a/hw/eepro100.c b/hw/eepro100.c index 5b231163d8..a189474d31 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -1578,7 +1578,7 @@ static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val) } } -static uint64_t eepro100_read(void *opaque, target_phys_addr_t addr, +static uint64_t eepro100_read(void *opaque, hwaddr addr, unsigned size) { EEPRO100State *s = opaque; @@ -1591,7 +1591,7 @@ static uint64_t eepro100_read(void *opaque, target_phys_addr_t addr, } } -static void eepro100_write(void *opaque, target_phys_addr_t addr, +static void eepro100_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { EEPRO100State *s = opaque; diff --git a/hw/elf_ops.h b/hw/elf_ops.h index 731a983854..531a42553b 100644 --- a/hw/elf_ops.h +++ b/hw/elf_ops.h @@ -62,7 +62,7 @@ static struct elf_shdr *glue(find_section, SZ)(struct elf_shdr *shdr_table, static int glue(symfind, SZ)(const void *s0, const void *s1) { - target_phys_addr_t addr = *(target_phys_addr_t *)s0; + hwaddr addr = *(hwaddr *)s0; struct elf_sym *sym = (struct elf_sym *)s1; int result = 0; if (addr < sym->st_value) { @@ -74,7 +74,7 @@ static int glue(symfind, SZ)(const void *s0, const void *s1) } static const char *glue(lookup_symbol, SZ)(struct syminfo *s, - target_phys_addr_t orig_addr) + hwaddr orig_addr) { struct elf_sym *syms = glue(s->disas_symtab.elf, SZ); struct elf_sym *sym; diff --git a/hw/empty_slot.c b/hw/empty_slot.c index 099c85e583..23978eb149 100644 --- a/hw/empty_slot.c +++ b/hw/empty_slot.c @@ -28,14 +28,14 @@ typedef struct EmptySlot { uint64_t size; } EmptySlot; -static uint64_t empty_slot_read(void *opaque, target_phys_addr_t addr, +static uint64_t empty_slot_read(void *opaque, hwaddr addr, unsigned size) { DPRINTF("read from " TARGET_FMT_plx "\n", addr); return 0; } -static void empty_slot_write(void *opaque, target_phys_addr_t addr, +static void empty_slot_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { DPRINTF("write 0x%x to " TARGET_FMT_plx "\n", (unsigned)val, addr); @@ -47,7 +47,7 @@ static const MemoryRegionOps empty_slot_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -void empty_slot_init(target_phys_addr_t addr, uint64_t slot_size) +void empty_slot_init(hwaddr addr, uint64_t slot_size) { if (slot_size > 0) { /* Only empty slots larger than 0 byte need handling. */ diff --git a/hw/empty_slot.h b/hw/empty_slot.h index 78dc91de10..4e9e460485 100644 --- a/hw/empty_slot.h +++ b/hw/empty_slot.h @@ -1,2 +1,2 @@ /* empty_slot.c */ -void empty_slot_init(target_phys_addr_t addr, uint64_t slot_size); +void empty_slot_init(hwaddr addr, uint64_t slot_size); diff --git a/hw/escc.c b/hw/escc.c index e1f5e73ba2..a356613b06 100644 --- a/hw/escc.c +++ b/hw/escc.c @@ -463,7 +463,7 @@ static void escc_update_parameters(ChannelState *s) qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp); } -static void escc_mem_write(void *opaque, target_phys_addr_t addr, +static void escc_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { SerialState *serial = opaque; @@ -565,7 +565,7 @@ static void escc_mem_write(void *opaque, target_phys_addr_t addr, } } -static uint64_t escc_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t escc_mem_read(void *opaque, hwaddr addr, unsigned size) { SerialState *serial = opaque; @@ -683,7 +683,7 @@ static const VMStateDescription vmstate_escc = { } }; -MemoryRegion *escc_init(target_phys_addr_t base, qemu_irq irqA, qemu_irq irqB, +MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB, CharDriverState *chrA, CharDriverState *chrB, int clock, int it_shift) { @@ -846,7 +846,7 @@ static void sunmouse_event(void *opaque, put_queue(s, 0); } -void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq, +void slavio_serial_ms_kbd_init(hwaddr base, qemu_irq irq, int disabled, int clock, int it_shift) { DeviceState *dev; diff --git a/hw/escc.h b/hw/escc.h index d1da46fd06..def28947a0 100644 --- a/hw/escc.h +++ b/hw/escc.h @@ -1,8 +1,8 @@ /* escc.c */ #define ESCC_SIZE 4 -MemoryRegion *escc_init(target_phys_addr_t base, qemu_irq irqA, qemu_irq irqB, +MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB, CharDriverState *chrA, CharDriverState *chrB, int clock, int it_shift); -void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq, +void slavio_serial_ms_kbd_init(hwaddr base, qemu_irq irq, int disabled, int clock, int it_shift); diff --git a/hw/esp-pci.c b/hw/esp-pci.c index 170e007be9..d9a8e59c98 100644 --- a/hw/esp-pci.c +++ b/hw/esp-pci.c @@ -159,7 +159,7 @@ static uint32_t esp_pci_dma_read(PCIESPState *pci, uint32_t saddr) return val; } -static void esp_pci_io_write(void *opaque, target_phys_addr_t addr, +static void esp_pci_io_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { PCIESPState *pci = opaque; @@ -202,7 +202,7 @@ static void esp_pci_io_write(void *opaque, target_phys_addr_t addr, } } -static uint64_t esp_pci_io_read(void *opaque, target_phys_addr_t addr, +static uint64_t esp_pci_io_read(void *opaque, hwaddr addr, unsigned int size) { PCIESPState *pci = opaque; diff --git a/hw/esp.c b/hw/esp.c index 84a4e74e25..6d01624a49 100644 --- a/hw/esp.c +++ b/hw/esp.c @@ -550,7 +550,7 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val) s->wregs[saddr] = val; } -static bool esp_mem_accepts(void *opaque, target_phys_addr_t addr, +static bool esp_mem_accepts(void *opaque, hwaddr addr, unsigned size, bool is_write) { return (size == 1) || (is_write && size == 4); @@ -585,7 +585,7 @@ typedef struct { ESPState esp; } SysBusESPState; -static void sysbus_esp_mem_write(void *opaque, target_phys_addr_t addr, +static void sysbus_esp_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { SysBusESPState *sysbus = opaque; @@ -595,7 +595,7 @@ static void sysbus_esp_mem_write(void *opaque, target_phys_addr_t addr, esp_reg_write(&sysbus->esp, saddr, val); } -static uint64_t sysbus_esp_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t sysbus_esp_mem_read(void *opaque, hwaddr addr, unsigned int size) { SysBusESPState *sysbus = opaque; @@ -612,7 +612,7 @@ static const MemoryRegionOps sysbus_esp_mem_ops = { .valid.accepts = esp_mem_accepts, }; -void esp_init(target_phys_addr_t espaddr, int it_shift, +void esp_init(hwaddr espaddr, int it_shift, ESPDMAMemoryReadWriteFunc dma_memory_read, ESPDMAMemoryReadWriteFunc dma_memory_write, void *dma_opaque, qemu_irq irq, qemu_irq *reset, diff --git a/hw/esp.h b/hw/esp.h index fa855e2fdf..f15cc7b5bd 100644 --- a/hw/esp.h +++ b/hw/esp.h @@ -6,7 +6,7 @@ /* esp.c */ #define ESP_MAX_DEVS 7 typedef void (*ESPDMAMemoryReadWriteFunc)(void *opaque, uint8_t *buf, int len); -void esp_init(target_phys_addr_t espaddr, int it_shift, +void esp_init(hwaddr espaddr, int it_shift, ESPDMAMemoryReadWriteFunc dma_memory_read, ESPDMAMemoryReadWriteFunc dma_memory_write, void *dma_opaque, qemu_irq irq, qemu_irq *reset, diff --git a/hw/etraxfs.h b/hw/etraxfs.h index c62f94b7b7..725bb9e142 100644 --- a/hw/etraxfs.h +++ b/hw/etraxfs.h @@ -29,7 +29,7 @@ qemu_irq *cris_pic_init_cpu(CPUCRISState *env); /* Instantiate an ETRAXFS Ethernet MAC. */ static inline DeviceState * -etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr, +etraxfs_eth_init(NICInfo *nd, hwaddr base, int phyaddr, void *dma_out, void *dma_in) { DeviceState *dev; diff --git a/hw/etraxfs_dma.c b/hw/etraxfs_dma.c index 332525cab1..49221abc1a 100644 --- a/hw/etraxfs_dma.c +++ b/hw/etraxfs_dma.c @@ -212,7 +212,7 @@ static inline int channel_en(struct fs_dma_ctrl *ctrl, int c) && ctrl->channels[c].client; } -static inline int fs_channel(target_phys_addr_t addr) +static inline int fs_channel(hwaddr addr) { /* Every channel has a 0x2000 ctrl register map. */ return addr >> 13; @@ -221,7 +221,7 @@ static inline int fs_channel(target_phys_addr_t addr) #ifdef USE_THIS_DEAD_CODE static void channel_load_g(struct fs_dma_ctrl *ctrl, int c) { - target_phys_addr_t addr = channel_reg(ctrl, c, RW_GROUP); + hwaddr addr = channel_reg(ctrl, c, RW_GROUP); /* Load and decode. FIXME: handle endianness. */ cpu_physical_memory_read (addr, @@ -253,7 +253,7 @@ static void dump_d(int ch, struct dma_descr_data *d) static void channel_load_c(struct fs_dma_ctrl *ctrl, int c) { - target_phys_addr_t addr = channel_reg(ctrl, c, RW_GROUP_DOWN); + hwaddr addr = channel_reg(ctrl, c, RW_GROUP_DOWN); /* Load and decode. FIXME: handle endianness. */ cpu_physical_memory_read (addr, @@ -270,7 +270,7 @@ static void channel_load_c(struct fs_dma_ctrl *ctrl, int c) static void channel_load_d(struct fs_dma_ctrl *ctrl, int c) { - target_phys_addr_t addr = channel_reg(ctrl, c, RW_SAVED_DATA); + hwaddr addr = channel_reg(ctrl, c, RW_SAVED_DATA); /* Load and decode. FIXME: handle endianness. */ D(printf("%s ch=%d addr=" TARGET_FMT_plx "\n", __func__, c, addr)); @@ -284,7 +284,7 @@ static void channel_load_d(struct fs_dma_ctrl *ctrl, int c) static void channel_store_c(struct fs_dma_ctrl *ctrl, int c) { - target_phys_addr_t addr = channel_reg(ctrl, c, RW_GROUP_DOWN); + hwaddr addr = channel_reg(ctrl, c, RW_GROUP_DOWN); /* Encode and store. FIXME: handle endianness. */ D(printf("%s ch=%d addr=" TARGET_FMT_plx "\n", __func__, c, addr)); @@ -296,7 +296,7 @@ static void channel_store_c(struct fs_dma_ctrl *ctrl, int c) static void channel_store_d(struct fs_dma_ctrl *ctrl, int c) { - target_phys_addr_t addr = channel_reg(ctrl, c, RW_SAVED_DATA); + hwaddr addr = channel_reg(ctrl, c, RW_SAVED_DATA); /* Encode and store. FIXME: handle endianness. */ D(printf("%s ch=%d addr=" TARGET_FMT_plx "\n", __func__, c, addr)); @@ -573,14 +573,14 @@ static inline int channel_in_run(struct fs_dma_ctrl *ctrl, int c) return 0; } -static uint32_t dma_rinvalid (void *opaque, target_phys_addr_t addr) +static uint32_t dma_rinvalid (void *opaque, hwaddr addr) { hw_error("Unsupported short raccess. reg=" TARGET_FMT_plx "\n", addr); return 0; } static uint64_t -dma_read(void *opaque, target_phys_addr_t addr, unsigned int size) +dma_read(void *opaque, hwaddr addr, unsigned int size) { struct fs_dma_ctrl *ctrl = opaque; int c; @@ -612,7 +612,7 @@ dma_read(void *opaque, target_phys_addr_t addr, unsigned int size) } static void -dma_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value) +dma_winvalid (void *opaque, hwaddr addr, uint32_t value) { hw_error("Unsupported short waccess. reg=" TARGET_FMT_plx "\n", addr); } @@ -627,7 +627,7 @@ dma_update_state(struct fs_dma_ctrl *ctrl, int c) } static void -dma_write(void *opaque, target_phys_addr_t addr, +dma_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { struct fs_dma_ctrl *ctrl = opaque; @@ -762,7 +762,7 @@ static void DMA_run(void *opaque) qemu_bh_schedule_idle(etraxfs_dmac->bh); } -void *etraxfs_dmac_init(target_phys_addr_t base, int nr_channels) +void *etraxfs_dmac_init(hwaddr base, int nr_channels) { struct fs_dma_ctrl *ctrl = NULL; diff --git a/hw/etraxfs_dma.h b/hw/etraxfs_dma.h index 021c52ae7d..3fef80fae1 100644 --- a/hw/etraxfs_dma.h +++ b/hw/etraxfs_dma.h @@ -20,7 +20,7 @@ struct etraxfs_dma_client } client; }; -void *etraxfs_dmac_init(target_phys_addr_t base, int nr_channels); +void *etraxfs_dmac_init(hwaddr base, int nr_channels); void etraxfs_dmac_connect(void *opaque, int channel, qemu_irq *line, int input); void etraxfs_dmac_connect_client(void *opaque, int c, diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c index b124f5bb3a..3d42426823 100644 --- a/hw/etraxfs_eth.c +++ b/hw/etraxfs_eth.c @@ -374,7 +374,7 @@ static void eth_validate_duplex(struct fs_eth *eth) } static uint64_t -eth_read(void *opaque, target_phys_addr_t addr, unsigned int size) +eth_read(void *opaque, hwaddr addr, unsigned int size) { struct fs_eth *eth = opaque; uint32_t r = 0; @@ -418,7 +418,7 @@ static void eth_update_ma(struct fs_eth *eth, int ma) } static void -eth_write(void *opaque, target_phys_addr_t addr, +eth_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { struct fs_eth *eth = opaque; diff --git a/hw/etraxfs_pic.c b/hw/etraxfs_pic.c index dc27f88ac9..62a62a36af 100644 --- a/hw/etraxfs_pic.c +++ b/hw/etraxfs_pic.c @@ -79,7 +79,7 @@ static void pic_update(struct etrax_pic *fs) } static uint64_t -pic_read(void *opaque, target_phys_addr_t addr, unsigned int size) +pic_read(void *opaque, hwaddr addr, unsigned int size) { struct etrax_pic *fs = opaque; uint32_t rval; @@ -89,7 +89,7 @@ pic_read(void *opaque, target_phys_addr_t addr, unsigned int size) return rval; } -static void pic_write(void *opaque, target_phys_addr_t addr, +static void pic_write(void *opaque, hwaddr addr, uint64_t value, unsigned int size) { struct etrax_pic *fs = opaque; diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c index 5f16b17835..ee0d72bf87 100644 --- a/hw/etraxfs_ser.c +++ b/hw/etraxfs_ser.c @@ -75,7 +75,7 @@ static void ser_update_irq(struct etrax_serial *s) } static uint64_t -ser_read(void *opaque, target_phys_addr_t addr, unsigned int size) +ser_read(void *opaque, hwaddr addr, unsigned int size) { struct etrax_serial *s = opaque; D(CPUCRISState *env = s->env); @@ -110,7 +110,7 @@ ser_read(void *opaque, target_phys_addr_t addr, unsigned int size) } static void -ser_write(void *opaque, target_phys_addr_t addr, +ser_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { struct etrax_serial *s = opaque; diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c index 9076a49884..f5601dc7a5 100644 --- a/hw/etraxfs_timer.c +++ b/hw/etraxfs_timer.c @@ -75,7 +75,7 @@ struct etrax_timer { }; static uint64_t -timer_read(void *opaque, target_phys_addr_t addr, unsigned int size) +timer_read(void *opaque, hwaddr addr, unsigned int size) { struct etrax_timer *t = opaque; uint32_t r = 0; @@ -242,7 +242,7 @@ static inline void timer_watchdog_update(struct etrax_timer *t, uint32_t value) } static void -timer_write(void *opaque, target_phys_addr_t addr, +timer_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { struct etrax_timer *t = opaque; diff --git a/hw/exynos4210.h b/hw/exynos4210.h index a43ba3aedc..777f0f5b2f 100644 --- a/hw/exynos4210.h +++ b/hw/exynos4210.h @@ -128,7 +128,7 @@ void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev, /* * exynos4210 UART */ -DeviceState *exynos4210_uart_create(target_phys_addr_t addr, +DeviceState *exynos4210_uart_create(hwaddr addr, int fifo_size, int channel, CharDriverState *chr, diff --git a/hw/exynos4210_combiner.c b/hw/exynos4210_combiner.c index 60b33c7886..84d36ed11f 100644 --- a/hw/exynos4210_combiner.c +++ b/hw/exynos4210_combiner.c @@ -174,7 +174,7 @@ void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev, } static uint64_t -exynos4210_combiner_read(void *opaque, target_phys_addr_t offset, unsigned size) +exynos4210_combiner_read(void *opaque, hwaddr offset, unsigned size) { struct Exynos4210CombinerState *s = (struct Exynos4210CombinerState *)opaque; @@ -266,7 +266,7 @@ static void exynos4210_combiner_update(void *opaque, uint8_t group_n) } } -static void exynos4210_combiner_write(void *opaque, target_phys_addr_t offset, +static void exynos4210_combiner_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { struct Exynos4210CombinerState *s = diff --git a/hw/exynos4210_fimd.c b/hw/exynos4210_fimd.c index 3313f00a71..7cb2c31bee 100644 --- a/hw/exynos4210_fimd.c +++ b/hw/exynos4210_fimd.c @@ -290,7 +290,7 @@ struct Exynos4210fimdWindow { uint16_t virtpage_offsize; /* VIDWADD2 register */ MemoryRegionSection mem_section; /* RAM fragment containing framebuffer */ uint8_t *host_fb_addr; /* Host pointer to window's framebuffer */ - target_phys_addr_t fb_len; /* Framebuffer length */ + hwaddr fb_len; /* Framebuffer length */ }; typedef struct { @@ -1110,7 +1110,7 @@ static inline int fimd_get_buffer_id(Exynos4210fimdWindow *w) static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win) { Exynos4210fimdWindow *w = &s->window[win]; - target_phys_addr_t fb_start_addr, fb_mapped_len; + hwaddr fb_start_addr, fb_mapped_len; if (!s->enabled || !(w->wincon & FIMD_WINCON_ENWIN) || FIMD_WINDOW_PROTECTED(s->shadowcon, win)) { @@ -1243,7 +1243,7 @@ static void exynos4210_fimd_update(void *opaque) Exynos4210fimdState *s = (Exynos4210fimdState *)opaque; Exynos4210fimdWindow *w; int i, line; - target_phys_addr_t fb_line_addr, inc_size; + hwaddr fb_line_addr, inc_size; int scrn_height; int first_line = -1, last_line = -1, scrn_width; bool blend = false; @@ -1348,7 +1348,7 @@ static void exynos4210_fimd_reset(DeviceState *d) s->hueoffset = 0x01800080; } -static void exynos4210_fimd_write(void *opaque, target_phys_addr_t offset, +static void exynos4210_fimd_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { Exynos4210fimdState *s = (Exynos4210fimdState *)opaque; @@ -1649,7 +1649,7 @@ static void exynos4210_fimd_write(void *opaque, target_phys_addr_t offset, } } -static uint64_t exynos4210_fimd_read(void *opaque, target_phys_addr_t offset, +static uint64_t exynos4210_fimd_read(void *opaque, hwaddr offset, unsigned size) { Exynos4210fimdState *s = (Exynos4210fimdState *)opaque; diff --git a/hw/exynos4210_i2c.c b/hw/exynos4210_i2c.c index 3f72a5c464..1e11d9b48c 100644 --- a/hw/exynos4210_i2c.c +++ b/hw/exynos4210_i2c.c @@ -129,7 +129,7 @@ static void exynos4210_i2c_data_send(void *opaque) exynos4210_i2c_raise_interrupt(s); } -static uint64_t exynos4210_i2c_read(void *opaque, target_phys_addr_t offset, +static uint64_t exynos4210_i2c_read(void *opaque, hwaddr offset, unsigned size) { Exynos4210I2CState *s = (Exynos4210I2CState *)opaque; @@ -168,7 +168,7 @@ static uint64_t exynos4210_i2c_read(void *opaque, target_phys_addr_t offset, return value; } -static void exynos4210_i2c_write(void *opaque, target_phys_addr_t offset, +static void exynos4210_i2c_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { Exynos4210I2CState *s = (Exynos4210I2CState *)opaque; diff --git a/hw/exynos4210_mct.c b/hw/exynos4210_mct.c index 6f94ce230c..e79cd6ac01 100644 --- a/hw/exynos4210_mct.c +++ b/hw/exynos4210_mct.c @@ -985,7 +985,7 @@ static void exynos4210_mct_reset(DeviceState *d) } /* Multi Core Timer read */ -static uint64_t exynos4210_mct_read(void *opaque, target_phys_addr_t offset, +static uint64_t exynos4210_mct_read(void *opaque, hwaddr offset, unsigned size) { Exynos4210MCTState *s = (Exynos4210MCTState *)opaque; @@ -1098,7 +1098,7 @@ static uint64_t exynos4210_mct_read(void *opaque, target_phys_addr_t offset, } /* MCT write */ -static void exynos4210_mct_write(void *opaque, target_phys_addr_t offset, +static void exynos4210_mct_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { Exynos4210MCTState *s = (Exynos4210MCTState *)opaque; diff --git a/hw/exynos4210_pmu.c b/hw/exynos4210_pmu.c index c12d7501cc..a22b8f181a 100644 --- a/hw/exynos4210_pmu.c +++ b/hw/exynos4210_pmu.c @@ -392,7 +392,7 @@ typedef struct Exynos4210PmuState { uint32_t reg[PMU_NUM_OF_REGISTERS]; } Exynos4210PmuState; -static uint64_t exynos4210_pmu_read(void *opaque, target_phys_addr_t offset, +static uint64_t exynos4210_pmu_read(void *opaque, hwaddr offset, unsigned size) { Exynos4210PmuState *s = (Exynos4210PmuState *)opaque; @@ -411,7 +411,7 @@ static uint64_t exynos4210_pmu_read(void *opaque, target_phys_addr_t offset, return 0; } -static void exynos4210_pmu_write(void *opaque, target_phys_addr_t offset, +static void exynos4210_pmu_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { Exynos4210PmuState *s = (Exynos4210PmuState *)opaque; diff --git a/hw/exynos4210_pwm.c b/hw/exynos4210_pwm.c index 0c228280a9..5e2872f8f7 100644 --- a/hw/exynos4210_pwm.c +++ b/hw/exynos4210_pwm.c @@ -208,7 +208,7 @@ static void exynos4210_pwm_tick(void *opaque) /* * PWM Read */ -static uint64_t exynos4210_pwm_read(void *opaque, target_phys_addr_t offset, +static uint64_t exynos4210_pwm_read(void *opaque, hwaddr offset, unsigned size) { Exynos4210PWMState *s = (Exynos4210PWMState *)opaque; @@ -259,7 +259,7 @@ static uint64_t exynos4210_pwm_read(void *opaque, target_phys_addr_t offset, /* * PWM Write */ -static void exynos4210_pwm_write(void *opaque, target_phys_addr_t offset, +static void exynos4210_pwm_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { Exynos4210PWMState *s = (Exynos4210PWMState *)opaque; diff --git a/hw/exynos4210_rtc.c b/hw/exynos4210_rtc.c index 42a4ddc327..c4fbd49461 100644 --- a/hw/exynos4210_rtc.c +++ b/hw/exynos4210_rtc.c @@ -299,7 +299,7 @@ static void exynos4210_rtc_1Hz_tick(void *opaque) /* * RTC Read */ -static uint64_t exynos4210_rtc_read(void *opaque, target_phys_addr_t offset, +static uint64_t exynos4210_rtc_read(void *opaque, hwaddr offset, unsigned size) { uint32_t value = 0; @@ -376,7 +376,7 @@ static uint64_t exynos4210_rtc_read(void *opaque, target_phys_addr_t offset, /* * RTC Write */ -static void exynos4210_rtc_write(void *opaque, target_phys_addr_t offset, +static void exynos4210_rtc_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { Exynos4210RTCState *s = (Exynos4210RTCState *)opaque; diff --git a/hw/exynos4210_uart.c b/hw/exynos4210_uart.c index ccc47804f9..20dcd9fb57 100644 --- a/hw/exynos4210_uart.c +++ b/hw/exynos4210_uart.c @@ -96,7 +96,7 @@ typedef struct Exynos4210UartReg { const char *name; /* the only reason is the debug output */ - target_phys_addr_t offset; + hwaddr offset; uint32_t reset_value; } Exynos4210UartReg; @@ -184,7 +184,7 @@ typedef struct { #if DEBUG_UART /* Used only for debugging inside PRINT_DEBUG_... macros */ -static const char *exynos4210_uart_regname(target_phys_addr_t offset) +static const char *exynos4210_uart_regname(hwaddr offset) { int regs_number = sizeof(exynos4210_uart_regs) / sizeof(Exynos4210UartReg); @@ -348,7 +348,7 @@ static void exynos4210_uart_update_parameters(Exynos4210UartState *s) s->channel, speed, parity, data_bits, stop_bits); } -static void exynos4210_uart_write(void *opaque, target_phys_addr_t offset, +static void exynos4210_uart_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { Exynos4210UartState *s = (Exynos4210UartState *)opaque; @@ -423,7 +423,7 @@ static void exynos4210_uart_write(void *opaque, target_phys_addr_t offset, break; } } -static uint64_t exynos4210_uart_read(void *opaque, target_phys_addr_t offset, +static uint64_t exynos4210_uart_read(void *opaque, hwaddr offset, unsigned size) { Exynos4210UartState *s = (Exynos4210UartState *)opaque; @@ -581,7 +581,7 @@ static const VMStateDescription vmstate_exynos4210_uart = { } }; -DeviceState *exynos4210_uart_create(target_phys_addr_t addr, +DeviceState *exynos4210_uart_create(hwaddr addr, int fifo_size, int channel, CharDriverState *chr, @@ -617,7 +617,7 @@ DeviceState *exynos4210_uart_create(target_phys_addr_t addr, bus = sysbus_from_qdev(dev); qdev_init_nofail(dev); - if (addr != (target_phys_addr_t)-1) { + if (addr != (hwaddr)-1) { sysbus_mmio_map(bus, 0, addr); } sysbus_connect_irq(bus, 0, irq); diff --git a/hw/fdc.c b/hw/fdc.c index 25a49e350c..bf8c1d9f13 100644 --- a/hw/fdc.c +++ b/hw/fdc.c @@ -626,13 +626,13 @@ static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value) } } -static uint64_t fdctrl_read_mem (void *opaque, target_phys_addr_t reg, +static uint64_t fdctrl_read_mem (void *opaque, hwaddr reg, unsigned ize) { return fdctrl_read(opaque, (uint32_t)reg); } -static void fdctrl_write_mem (void *opaque, target_phys_addr_t reg, +static void fdctrl_write_mem (void *opaque, hwaddr reg, uint64_t value, unsigned size) { fdctrl_write(opaque, (uint32_t)reg, value); @@ -2032,7 +2032,7 @@ ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds) } void fdctrl_init_sysbus(qemu_irq irq, int dma_chann, - target_phys_addr_t mmio_base, DriveInfo **fds) + hwaddr mmio_base, DriveInfo **fds) { FDCtrl *fdctrl; DeviceState *dev; @@ -2053,7 +2053,7 @@ void fdctrl_init_sysbus(qemu_irq irq, int dma_chann, sysbus_mmio_map(&sys->busdev, 0, mmio_base); } -void sun4m_fdctrl_init(qemu_irq irq, target_phys_addr_t io_base, +void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base, DriveInfo **fds, qemu_irq *fdc_tc) { DeviceState *dev; diff --git a/hw/fdc.h b/hw/fdc.h index b5c9f31074..a8f6f7c850 100644 --- a/hw/fdc.h +++ b/hw/fdc.h @@ -15,8 +15,8 @@ typedef enum FDriveType { ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds); void fdctrl_init_sysbus(qemu_irq irq, int dma_chann, - target_phys_addr_t mmio_base, DriveInfo **fds); -void sun4m_fdctrl_init(qemu_irq irq, target_phys_addr_t io_base, + hwaddr mmio_base, DriveInfo **fds); +void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base, DriveInfo **fds, qemu_irq *fdc_tc); FDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i); diff --git a/hw/flash.h b/hw/flash.h index 9c9e5265b7..d790f3c92d 100644 --- a/hw/flash.h +++ b/hw/flash.h @@ -5,18 +5,18 @@ typedef struct pflash_t pflash_t; /* pflash_cfi01.c */ -pflash_t *pflash_cfi01_register(target_phys_addr_t base, +pflash_t *pflash_cfi01_register(hwaddr base, DeviceState *qdev, const char *name, - target_phys_addr_t size, + hwaddr size, BlockDriverState *bs, uint32_t sector_len, int nb_blocs, int width, uint16_t id0, uint16_t id1, uint16_t id2, uint16_t id3, int be); /* pflash_cfi02.c */ -pflash_t *pflash_cfi02_register(target_phys_addr_t base, +pflash_t *pflash_cfi02_register(hwaddr base, DeviceState *qdev, const char *name, - target_phys_addr_t size, + hwaddr size, BlockDriverState *bs, uint32_t sector_len, int nb_blocs, int nb_mappings, int width, uint16_t id0, uint16_t id1, diff --git a/hw/framebuffer.c b/hw/framebuffer.c index 27fa6f51fb..fa0f7863c4 100644 --- a/hw/framebuffer.c +++ b/hw/framebuffer.c @@ -26,7 +26,7 @@ void framebuffer_update_display( DisplayState *ds, MemoryRegion *address_space, - target_phys_addr_t base, + hwaddr base, int cols, /* Width in pixels. */ int rows, /* Height in pixels. */ int src_width, /* Length of source line, in bytes. */ @@ -38,7 +38,7 @@ void framebuffer_update_display( int *first_row, /* Input and output. */ int *last_row /* Output only */) { - target_phys_addr_t src_len; + hwaddr src_len; uint8_t *dest; uint8_t *src; uint8_t *src_base; diff --git a/hw/framebuffer.h b/hw/framebuffer.h index 527a6b85f8..46e375b5ec 100644 --- a/hw/framebuffer.h +++ b/hw/framebuffer.h @@ -10,7 +10,7 @@ typedef void (*drawfn)(void *, uint8_t *, const uint8_t *, int, int); void framebuffer_update_display( DisplayState *ds, MemoryRegion *address_space, - target_phys_addr_t base, + hwaddr base, int cols, int rows, int src_width, diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c index dcde1a943c..2b92cda98a 100644 --- a/hw/fw_cfg.c +++ b/hw/fw_cfg.c @@ -258,37 +258,37 @@ static uint8_t fw_cfg_read(FWCfgState *s) return ret; } -static uint64_t fw_cfg_data_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t fw_cfg_data_mem_read(void *opaque, hwaddr addr, unsigned size) { return fw_cfg_read(opaque); } -static void fw_cfg_data_mem_write(void *opaque, target_phys_addr_t addr, +static void fw_cfg_data_mem_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { fw_cfg_write(opaque, (uint8_t)value); } -static void fw_cfg_ctl_mem_write(void *opaque, target_phys_addr_t addr, +static void fw_cfg_ctl_mem_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { fw_cfg_select(opaque, (uint16_t)value); } -static bool fw_cfg_ctl_mem_valid(void *opaque, target_phys_addr_t addr, +static bool fw_cfg_ctl_mem_valid(void *opaque, hwaddr addr, unsigned size, bool is_write) { return is_write && size == 2; } -static uint64_t fw_cfg_comb_read(void *opaque, target_phys_addr_t addr, +static uint64_t fw_cfg_comb_read(void *opaque, hwaddr addr, unsigned size) { return fw_cfg_read(opaque); } -static void fw_cfg_comb_write(void *opaque, target_phys_addr_t addr, +static void fw_cfg_comb_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { switch (size) { @@ -301,7 +301,7 @@ static void fw_cfg_comb_write(void *opaque, target_phys_addr_t addr, } } -static bool fw_cfg_comb_valid(void *opaque, target_phys_addr_t addr, +static bool fw_cfg_comb_valid(void *opaque, hwaddr addr, unsigned size, bool is_write) { return (size == 1) || (is_write && size == 2); @@ -494,7 +494,7 @@ static void fw_cfg_machine_ready(struct Notifier *n, void *data) } FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port, - target_phys_addr_t ctl_addr, target_phys_addr_t data_addr) + hwaddr ctl_addr, hwaddr data_addr) { DeviceState *dev; SysBusDevice *d; diff --git a/hw/fw_cfg.h b/hw/fw_cfg.h index 856bf9199d..619a39432a 100644 --- a/hw/fw_cfg.h +++ b/hw/fw_cfg.h @@ -63,7 +63,7 @@ int fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback, int fw_cfg_add_file(FWCfgState *s, const char *filename, uint8_t *data, uint32_t len); FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port, - target_phys_addr_t crl_addr, target_phys_addr_t data_addr); + hwaddr crl_addr, hwaddr data_addr); #endif /* NO_QEMU_PROTOS */ diff --git a/hw/g364fb.c b/hw/g364fb.c index 059e6220e0..f7b4bf5ae2 100644 --- a/hw/g364fb.c +++ b/hw/g364fb.c @@ -362,7 +362,7 @@ write_err: /* called for accesses to io ports */ static uint64_t g364fb_ctrl_read(void *opaque, - target_phys_addr_t addr, + hwaddr addr, unsigned int size) { G364State *s = opaque; @@ -424,7 +424,7 @@ static void g364_invalidate_cursor_position(G364State *s) } static void g364fb_ctrl_write(void *opaque, - target_phys_addr_t addr, + hwaddr addr, uint64_t val, unsigned int size) { diff --git a/hw/grlib.h b/hw/grlib.h index e1c41378d4..35c22f5994 100644 --- a/hw/grlib.h +++ b/hw/grlib.h @@ -41,7 +41,7 @@ void grlib_irqmp_set_irq(void *opaque, int irq, int level); void grlib_irqmp_ack(DeviceState *dev, int intno); static inline -DeviceState *grlib_irqmp_create(target_phys_addr_t base, +DeviceState *grlib_irqmp_create(hwaddr base, CPUSPARCState *env, qemu_irq **cpu_irqs, uint32_t nr_irqs, @@ -73,7 +73,7 @@ DeviceState *grlib_irqmp_create(target_phys_addr_t base, /* GPTimer */ static inline -DeviceState *grlib_gptimer_create(target_phys_addr_t base, +DeviceState *grlib_gptimer_create(hwaddr base, uint32_t nr_timers, uint32_t freq, qemu_irq *cpu_irqs, @@ -103,7 +103,7 @@ DeviceState *grlib_gptimer_create(target_phys_addr_t base, /* APB UART */ static inline -DeviceState *grlib_apbuart_create(target_phys_addr_t base, +DeviceState *grlib_apbuart_create(hwaddr base, CharDriverState *serial, qemu_irq irq) { diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c index 73fc9894db..0865764deb 100644 --- a/hw/grlib_apbuart.c +++ b/hw/grlib_apbuart.c @@ -151,7 +151,7 @@ static void grlib_apbuart_event(void *opaque, int event) } -static uint64_t grlib_apbuart_read(void *opaque, target_phys_addr_t addr, +static uint64_t grlib_apbuart_read(void *opaque, hwaddr addr, unsigned size) { UART *uart = opaque; @@ -181,7 +181,7 @@ static uint64_t grlib_apbuart_read(void *opaque, target_phys_addr_t addr, } } -static void grlib_apbuart_write(void *opaque, target_phys_addr_t addr, +static void grlib_apbuart_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { UART *uart = opaque; diff --git a/hw/grlib_gptimer.c b/hw/grlib_gptimer.c index 41770a9e6c..2fdccfba06 100644 --- a/hw/grlib_gptimer.c +++ b/hw/grlib_gptimer.c @@ -155,11 +155,11 @@ static void grlib_gptimer_hit(void *opaque) } } -static uint64_t grlib_gptimer_read(void *opaque, target_phys_addr_t addr, +static uint64_t grlib_gptimer_read(void *opaque, hwaddr addr, unsigned size) { GPTimerUnit *unit = opaque; - target_phys_addr_t timer_addr; + hwaddr timer_addr; int id; uint32_t value = 0; @@ -214,11 +214,11 @@ static uint64_t grlib_gptimer_read(void *opaque, target_phys_addr_t addr, return 0; } -static void grlib_gptimer_write(void *opaque, target_phys_addr_t addr, +static void grlib_gptimer_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { GPTimerUnit *unit = opaque; - target_phys_addr_t timer_addr; + hwaddr timer_addr; int id; addr &= 0xff; diff --git a/hw/grlib_irqmp.c b/hw/grlib_irqmp.c index 0f6e65cf20..23a6a02bc5 100644 --- a/hw/grlib_irqmp.c +++ b/hw/grlib_irqmp.c @@ -162,7 +162,7 @@ void grlib_irqmp_set_irq(void *opaque, int irq, int level) } } -static uint64_t grlib_irqmp_read(void *opaque, target_phys_addr_t addr, +static uint64_t grlib_irqmp_read(void *opaque, hwaddr addr, unsigned size) { IRQMP *irqmp = opaque; @@ -226,7 +226,7 @@ static uint64_t grlib_irqmp_read(void *opaque, target_phys_addr_t addr, return 0; } -static void grlib_irqmp_write(void *opaque, target_phys_addr_t addr, +static void grlib_irqmp_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { IRQMP *irqmp = opaque; diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c index e95e664833..95d491d932 100644 --- a/hw/gt64xxx.c +++ b/hw/gt64xxx.c @@ -225,8 +225,8 @@ #define GT_PCI1_SERR1MASK (0xca8 >> 2) #define PCI_MAPPING_ENTRY(regname) \ - target_phys_addr_t regname ##_start; \ - target_phys_addr_t regname ##_length; \ + hwaddr regname ##_start; \ + hwaddr regname ##_length; \ MemoryRegion regname ##_mem #define TYPE_GT64120_PCI_HOST_BRIDGE "gt64120" @@ -245,11 +245,11 @@ typedef struct GT64120State { /* Adjust range to avoid touching space which isn't mappable via PCI */ /* XXX: Hardcoded values for Malta: 0x1e000000 - 0x1f100000 0x1fc00000 - 0x1fd00000 */ -static void check_reserved_space (target_phys_addr_t *start, - target_phys_addr_t *length) +static void check_reserved_space (hwaddr *start, + hwaddr *length) { - target_phys_addr_t begin = *start; - target_phys_addr_t end = *start + *length; + hwaddr begin = *start; + hwaddr end = *start + *length; if (end >= 0x1e000000LL && end < 0x1f100000LL) end = 0x1e000000LL; @@ -271,8 +271,8 @@ static void check_reserved_space (target_phys_addr_t *start, static void gt64120_isd_mapping(GT64120State *s) { - target_phys_addr_t start = s->regs[GT_ISD] << 21; - target_phys_addr_t length = 0x1000; + hwaddr start = s->regs[GT_ISD] << 21; + hwaddr length = 0x1000; if (s->ISD_length) { memory_region_del_subregion(get_system_memory(), &s->ISD_mem); @@ -311,7 +311,7 @@ static void gt64120_pci_mapping(GT64120State *s) } } -static void gt64120_writel (void *opaque, target_phys_addr_t addr, +static void gt64120_writel (void *opaque, hwaddr addr, uint64_t val, unsigned size) { GT64120State *s = opaque; @@ -594,7 +594,7 @@ static void gt64120_writel (void *opaque, target_phys_addr_t addr, } static uint64_t gt64120_readl (void *opaque, - target_phys_addr_t addr, unsigned size) + hwaddr addr, unsigned size) { GT64120State *s = opaque; PCIHostState *phb = PCI_HOST_BRIDGE(s); diff --git a/hw/heathrow_pic.c b/hw/heathrow_pic.c index 16f48d12e1..b9ec8e7b4d 100644 --- a/hw/heathrow_pic.c +++ b/hw/heathrow_pic.c @@ -63,7 +63,7 @@ static void heathrow_pic_update(HeathrowPICS *s) } } -static void pic_write(void *opaque, target_phys_addr_t addr, +static void pic_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { HeathrowPICS *s = opaque; @@ -91,7 +91,7 @@ static void pic_write(void *opaque, target_phys_addr_t addr, } } -static uint64_t pic_read(void *opaque, target_phys_addr_t addr, +static uint64_t pic_read(void *opaque, hwaddr addr, unsigned size) { HeathrowPICS *s = opaque; diff --git a/hw/highbank.c b/hw/highbank.c index 15036b6390..afbb005422 100644 --- a/hw/highbank.c +++ b/hw/highbank.c @@ -79,7 +79,7 @@ static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info) } #define NUM_REGS 0x200 -static void hb_regs_write(void *opaque, target_phys_addr_t offset, +static void hb_regs_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { uint32_t *regs = opaque; @@ -95,7 +95,7 @@ static void hb_regs_write(void *opaque, target_phys_addr_t offset, regs[offset/4] = value; } -static uint64_t hb_regs_read(void *opaque, target_phys_addr_t offset, +static uint64_t hb_regs_read(void *opaque, hwaddr offset, unsigned size) { uint32_t *regs = opaque; diff --git a/hw/hpet.c b/hw/hpet.c index fd3ddca7f7..50ac067ece 100644 --- a/hw/hpet.c +++ b/hw/hpet.c @@ -370,20 +370,20 @@ static void hpet_del_timer(HPETTimer *t) } #ifdef HPET_DEBUG -static uint32_t hpet_ram_readb(void *opaque, target_phys_addr_t addr) +static uint32_t hpet_ram_readb(void *opaque, hwaddr addr) { printf("qemu: hpet_read b at %" PRIx64 "\n", addr); return 0; } -static uint32_t hpet_ram_readw(void *opaque, target_phys_addr_t addr) +static uint32_t hpet_ram_readw(void *opaque, hwaddr addr) { printf("qemu: hpet_read w at %" PRIx64 "\n", addr); return 0; } #endif -static uint64_t hpet_ram_read(void *opaque, target_phys_addr_t addr, +static uint64_t hpet_ram_read(void *opaque, hwaddr addr, unsigned size) { HPETState *s = opaque; @@ -455,7 +455,7 @@ static uint64_t hpet_ram_read(void *opaque, target_phys_addr_t addr, return 0; } -static void hpet_ram_write(void *opaque, target_phys_addr_t addr, +static void hpet_ram_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { int i; diff --git a/hw/i82378.c b/hw/i82378.c index 2123c142aa..99f35d41ef 100644 --- a/hw/i82378.c +++ b/hw/i82378.c @@ -59,7 +59,7 @@ static const VMStateDescription vmstate_pci_i82378 = { }, }; -static void i82378_io_write(void *opaque, target_phys_addr_t addr, +static void i82378_io_write(void *opaque, hwaddr addr, uint64_t value, unsigned int size) { switch (size) { @@ -83,7 +83,7 @@ static void i82378_io_write(void *opaque, target_phys_addr_t addr, } } -static uint64_t i82378_io_read(void *opaque, target_phys_addr_t addr, +static uint64_t i82378_io_read(void *opaque, hwaddr addr, unsigned int size) { DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr); @@ -105,7 +105,7 @@ static const MemoryRegionOps i82378_io_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static void i82378_mem_write(void *opaque, target_phys_addr_t addr, +static void i82378_mem_write(void *opaque, hwaddr addr, uint64_t value, unsigned int size) { switch (size) { @@ -129,7 +129,7 @@ static void i82378_mem_write(void *opaque, target_phys_addr_t addr, } } -static uint64_t i82378_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t i82378_mem_read(void *opaque, hwaddr addr, unsigned int size) { DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr); diff --git a/hw/i8259.c b/hw/i8259.c index 53daf78652..af0ba4d7c6 100644 --- a/hw/i8259.c +++ b/hw/i8259.c @@ -235,7 +235,7 @@ static void pic_reset(DeviceState *dev) pic_init_reset(s); } -static void pic_ioport_write(void *opaque, target_phys_addr_t addr64, +static void pic_ioport_write(void *opaque, hwaddr addr64, uint64_t val64, unsigned size) { PICCommonState *s = opaque; @@ -329,7 +329,7 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64, } } -static uint64_t pic_ioport_read(void *opaque, target_phys_addr_t addr, +static uint64_t pic_ioport_read(void *opaque, hwaddr addr, unsigned size) { PICCommonState *s = opaque; @@ -366,14 +366,14 @@ int pic_get_output(DeviceState *d) return (pic_get_irq(s) >= 0); } -static void elcr_ioport_write(void *opaque, target_phys_addr_t addr, +static void elcr_ioport_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { PICCommonState *s = opaque; s->elcr = val & s->elcr_mask; } -static uint64_t elcr_ioport_read(void *opaque, target_phys_addr_t addr, +static uint64_t elcr_ioport_read(void *opaque, hwaddr addr, unsigned size) { PICCommonState *s = opaque; diff --git a/hw/ide.h b/hw/ide.h index 2db4079f68..add742c4a8 100644 --- a/hw/ide.h +++ b/hw/ide.h @@ -24,7 +24,7 @@ MemoryRegion *pmac_ide_init (DriveInfo **hd_table, qemu_irq irq, void *dbdma, int channel, qemu_irq dma_irq); /* ide-mmio.c */ -void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2, +void mmio_ide_init (hwaddr membase, hwaddr membase2, MemoryRegion *address_space, qemu_irq irq, int shift, DriveInfo *hd0, DriveInfo *hd1); diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 68671bc4de..67562db041 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -174,7 +174,7 @@ static void ahci_trigger_irq(AHCIState *s, AHCIDevice *d, static void map_page(uint8_t **ptr, uint64_t addr, uint32_t wanted) { - target_phys_addr_t len = wanted; + hwaddr len = wanted; if (*ptr) { cpu_physical_memory_unmap(*ptr, len, 1, len); @@ -279,7 +279,7 @@ static void ahci_port_write(AHCIState *s, int port, int offset, uint32_t val) } } -static uint64_t ahci_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t ahci_mem_read(void *opaque, hwaddr addr, unsigned size) { AHCIState *s = opaque; @@ -317,7 +317,7 @@ static uint64_t ahci_mem_read(void *opaque, target_phys_addr_t addr, -static void ahci_mem_write(void *opaque, target_phys_addr_t addr, +static void ahci_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { AHCIState *s = opaque; @@ -373,7 +373,7 @@ static const MemoryRegionOps ahci_mem_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static uint64_t ahci_idp_read(void *opaque, target_phys_addr_t addr, +static uint64_t ahci_idp_read(void *opaque, hwaddr addr, unsigned size) { AHCIState *s = opaque; @@ -389,7 +389,7 @@ static uint64_t ahci_idp_read(void *opaque, target_phys_addr_t addr, } } -static void ahci_idp_write(void *opaque, target_phys_addr_t addr, +static void ahci_idp_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { AHCIState *s = opaque; diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index e0b9443496..804db60ffe 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -43,7 +43,7 @@ static void cmd646_update_irq(PCIIDEState *d); -static uint64_t cmd646_cmd_read(void *opaque, target_phys_addr_t addr, +static uint64_t cmd646_cmd_read(void *opaque, hwaddr addr, unsigned size) { CMD646BAR *cmd646bar = opaque; @@ -54,7 +54,7 @@ static uint64_t cmd646_cmd_read(void *opaque, target_phys_addr_t addr, return ide_status_read(cmd646bar->bus, addr + 2); } -static void cmd646_cmd_write(void *opaque, target_phys_addr_t addr, +static void cmd646_cmd_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { CMD646BAR *cmd646bar = opaque; @@ -71,7 +71,7 @@ static const MemoryRegionOps cmd646_cmd_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static uint64_t cmd646_data_read(void *opaque, target_phys_addr_t addr, +static uint64_t cmd646_data_read(void *opaque, hwaddr addr, unsigned size) { CMD646BAR *cmd646bar = opaque; @@ -88,7 +88,7 @@ static uint64_t cmd646_data_read(void *opaque, target_phys_addr_t addr, return ((uint64_t)1 << (size * 8)) - 1; } -static void cmd646_data_write(void *opaque, target_phys_addr_t addr, +static void cmd646_data_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { CMD646BAR *cmd646bar = opaque; @@ -121,7 +121,7 @@ static void setup_cmd646_bar(PCIIDEState *d, int bus_num) memory_region_init_io(&bar->data, &cmd646_data_ops, bar, "cmd646-data", 8); } -static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr, +static uint64_t bmdma_read(void *opaque, hwaddr addr, unsigned size) { BMDMAState *bm = opaque; @@ -159,7 +159,7 @@ static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr, return val; } -static void bmdma_write(void *opaque, target_phys_addr_t addr, +static void bmdma_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { BMDMAState *bm = opaque; diff --git a/hw/ide/macio.c b/hw/ide/macio.c index f228725142..720af6ed9b 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -198,7 +198,7 @@ static void pmac_ide_flush(DBDMA_io *io) /* PowerMac IDE memory IO */ static void pmac_ide_writeb (void *opaque, - target_phys_addr_t addr, uint32_t val) + hwaddr addr, uint32_t val) { MACIOIDEState *d = opaque; @@ -216,7 +216,7 @@ static void pmac_ide_writeb (void *opaque, } } -static uint32_t pmac_ide_readb (void *opaque,target_phys_addr_t addr) +static uint32_t pmac_ide_readb (void *opaque,hwaddr addr) { uint8_t retval; MACIOIDEState *d = opaque; @@ -238,7 +238,7 @@ static uint32_t pmac_ide_readb (void *opaque,target_phys_addr_t addr) } static void pmac_ide_writew (void *opaque, - target_phys_addr_t addr, uint32_t val) + hwaddr addr, uint32_t val) { MACIOIDEState *d = opaque; @@ -249,7 +249,7 @@ static void pmac_ide_writew (void *opaque, } } -static uint32_t pmac_ide_readw (void *opaque,target_phys_addr_t addr) +static uint32_t pmac_ide_readw (void *opaque,hwaddr addr) { uint16_t retval; MACIOIDEState *d = opaque; @@ -265,7 +265,7 @@ static uint32_t pmac_ide_readw (void *opaque,target_phys_addr_t addr) } static void pmac_ide_writel (void *opaque, - target_phys_addr_t addr, uint32_t val) + hwaddr addr, uint32_t val) { MACIOIDEState *d = opaque; @@ -276,7 +276,7 @@ static void pmac_ide_writel (void *opaque, } } -static uint32_t pmac_ide_readl (void *opaque,target_phys_addr_t addr) +static uint32_t pmac_ide_readl (void *opaque,hwaddr addr) { uint32_t retval; MACIOIDEState *d = opaque; diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c index fcfb09eeab..bcb26c8b64 100644 --- a/hw/ide/mmio.c +++ b/hw/ide/mmio.c @@ -47,7 +47,7 @@ static void mmio_ide_reset(void *opaque) ide_bus_reset(&s->bus); } -static uint64_t mmio_ide_read(void *opaque, target_phys_addr_t addr, +static uint64_t mmio_ide_read(void *opaque, hwaddr addr, unsigned size) { MMIOState *s = opaque; @@ -58,7 +58,7 @@ static uint64_t mmio_ide_read(void *opaque, target_phys_addr_t addr, return ide_data_readw(&s->bus, 0); } -static void mmio_ide_write(void *opaque, target_phys_addr_t addr, +static void mmio_ide_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { MMIOState *s = opaque; @@ -75,14 +75,14 @@ static const MemoryRegionOps mmio_ide_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint64_t mmio_ide_status_read(void *opaque, target_phys_addr_t addr, +static uint64_t mmio_ide_status_read(void *opaque, hwaddr addr, unsigned size) { MMIOState *s= opaque; return ide_status_read(&s->bus, 0); } -static void mmio_ide_cmd_write(void *opaque, target_phys_addr_t addr, +static void mmio_ide_cmd_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { MMIOState *s = opaque; @@ -107,7 +107,7 @@ static const VMStateDescription vmstate_ide_mmio = { } }; -void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2, +void mmio_ide_init (hwaddr membase, hwaddr membase2, MemoryRegion *address_space, qemu_irq irq, int shift, DriveInfo *hd0, DriveInfo *hd1) diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 644533f777..bcdd70e450 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -327,7 +327,7 @@ void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val) bm->cmd = val & 0x09; } -static uint64_t bmdma_addr_read(void *opaque, target_phys_addr_t addr, +static uint64_t bmdma_addr_read(void *opaque, hwaddr addr, unsigned width) { BMDMAState *bm = opaque; @@ -341,7 +341,7 @@ static uint64_t bmdma_addr_read(void *opaque, target_phys_addr_t addr, return data; } -static void bmdma_addr_write(void *opaque, target_phys_addr_t addr, +static void bmdma_addr_write(void *opaque, hwaddr addr, uint64_t data, unsigned width) { BMDMAState *bm = opaque; diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 4ded9ee13d..9431badadf 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -33,7 +33,7 @@ #include -static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t bmdma_read(void *opaque, hwaddr addr, unsigned size) { BMDMAState *bm = opaque; uint32_t val; @@ -59,7 +59,7 @@ static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr, unsigned size) return val; } -static void bmdma_write(void *opaque, target_phys_addr_t addr, +static void bmdma_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { BMDMAState *bm = opaque; diff --git a/hw/ide/via.c b/hw/ide/via.c index b20e4f094e..efda1733d9 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -33,7 +33,7 @@ #include -static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr, +static uint64_t bmdma_read(void *opaque, hwaddr addr, unsigned size) { BMDMAState *bm = opaque; @@ -60,7 +60,7 @@ static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr, return val; } -static void bmdma_write(void *opaque, target_phys_addr_t addr, +static void bmdma_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { BMDMAState *bm = opaque; diff --git a/hw/imx.h b/hw/imx.h index ccf586fefe..ea9e093277 100644 --- a/hw/imx.h +++ b/hw/imx.h @@ -11,7 +11,7 @@ #ifndef IMX_H #define IMX_H -void imx_serial_create(int uart, const target_phys_addr_t addr, qemu_irq irq); +void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq); typedef enum { NOCLK, @@ -23,10 +23,10 @@ typedef enum { uint32_t imx_clock_frequency(DeviceState *s, IMXClk clock); -void imx_timerp_create(const target_phys_addr_t addr, +void imx_timerp_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm); -void imx_timerg_create(const target_phys_addr_t addr, +void imx_timerg_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm); diff --git a/hw/imx_avic.c b/hw/imx_avic.c index b1a8fe6d4c..810979366d 100644 --- a/hw/imx_avic.c +++ b/hw/imx_avic.c @@ -152,7 +152,7 @@ static void imx_avic_set_irq(void *opaque, int irq, int level) static uint64_t imx_avic_read(void *opaque, - target_phys_addr_t offset, unsigned size) + hwaddr offset, unsigned size) { IMXAVICState *s = (IMXAVICState *)opaque; @@ -259,7 +259,7 @@ static uint64_t imx_avic_read(void *opaque, } } -static void imx_avic_write(void *opaque, target_phys_addr_t offset, +static void imx_avic_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { IMXAVICState *s = (IMXAVICState *)opaque; diff --git a/hw/imx_ccm.c b/hw/imx_ccm.c index 10952c6ea1..f2e623cd29 100644 --- a/hw/imx_ccm.c +++ b/hw/imx_ccm.c @@ -191,7 +191,7 @@ static void imx_ccm_reset(DeviceState *dev) update_clocks(s); } -static uint64_t imx_ccm_read(void *opaque, target_phys_addr_t offset, +static uint64_t imx_ccm_read(void *opaque, hwaddr offset, unsigned size) { IMXCCMState *s = (IMXCCMState *)opaque; @@ -232,7 +232,7 @@ static uint64_t imx_ccm_read(void *opaque, target_phys_addr_t offset, return 0; } -static void imx_ccm_write(void *opaque, target_phys_addr_t offset, +static void imx_ccm_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { IMXCCMState *s = (IMXCCMState *)opaque; diff --git a/hw/imx_serial.c b/hw/imx_serial.c index d4eae430f5..dcd125fd25 100644 --- a/hw/imx_serial.c +++ b/hw/imx_serial.c @@ -183,7 +183,7 @@ static void imx_serial_reset_at_boot(DeviceState *dev) } -static uint64_t imx_serial_read(void *opaque, target_phys_addr_t offset, +static uint64_t imx_serial_read(void *opaque, hwaddr offset, unsigned size) { IMXSerialState *s = (IMXSerialState *)opaque; @@ -244,7 +244,7 @@ static uint64_t imx_serial_read(void *opaque, target_phys_addr_t offset, } } -static void imx_serial_write(void *opaque, target_phys_addr_t offset, +static void imx_serial_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { IMXSerialState *s = (IMXSerialState *)opaque; @@ -401,7 +401,7 @@ static int imx_serial_init(SysBusDevice *dev) return 0; } -void imx_serial_create(int uart, const target_phys_addr_t addr, qemu_irq irq) +void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq) { DeviceState *dev; SysBusDevice *bus; @@ -427,7 +427,7 @@ void imx_serial_create(int uart, const target_phys_addr_t addr, qemu_irq irq) qdev_prop_set_chr(dev, "chardev", chr); bus = sysbus_from_qdev(dev); qdev_init_nofail(dev); - if (addr != (target_phys_addr_t)-1) { + if (addr != (hwaddr)-1) { sysbus_mmio_map(bus, 0, addr); } sysbus_connect_irq(bus, 0, irq); diff --git a/hw/imx_timer.c b/hw/imx_timer.c index c28c53725a..33f33fb41e 100644 --- a/hw/imx_timer.c +++ b/hw/imx_timer.c @@ -194,7 +194,7 @@ static void imx_timerg_reload(IMXTimerGState *s, uint32_t timeout) ptimer_set_count(s->timer, diff_cnt); } -static uint64_t imx_timerg_read(void *opaque, target_phys_addr_t offset, +static uint64_t imx_timerg_read(void *opaque, hwaddr offset, unsigned size) { IMXTimerGState *s = (IMXTimerGState *)opaque; @@ -251,7 +251,7 @@ static void imx_timerg_reset(DeviceState *dev) imx_timerg_set_freq(s); } -static void imx_timerg_write(void *opaque, target_phys_addr_t offset, +static void imx_timerg_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { IMXTimerGState *s = (IMXTimerGState *)opaque; @@ -468,7 +468,7 @@ static void imx_timerp_reset(DeviceState *dev) ptimer_set_count(s->timer, TIMER_MAX); } -static uint64_t imx_timerp_read(void *opaque, target_phys_addr_t offset, +static uint64_t imx_timerp_read(void *opaque, hwaddr offset, unsigned size) { IMXTimerPState *s = (IMXTimerPState *)opaque; @@ -517,7 +517,7 @@ static void set_timerp_freq(IMXTimerPState *s) } } -static void imx_timerp_write(void *opaque, target_phys_addr_t offset, +static void imx_timerp_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { IMXTimerPState *s = (IMXTimerPState *)opaque; @@ -580,7 +580,7 @@ static void imx_timerp_tick(void *opaque) imx_timerp_update(s); } -void imx_timerp_create(const target_phys_addr_t addr, +void imx_timerp_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm) { @@ -634,7 +634,7 @@ static int imx_timerp_init(SysBusDevice *dev) } -void imx_timerg_create(const target_phys_addr_t addr, +void imx_timerg_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm) { diff --git a/hw/integratorcp.c b/hw/integratorcp.c index ac0ea83492..77807c39e3 100644 --- a/hw/integratorcp.c +++ b/hw/integratorcp.c @@ -38,7 +38,7 @@ static uint8_t integrator_spd[128] = { 0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40 }; -static uint64_t integratorcm_read(void *opaque, target_phys_addr_t offset, +static uint64_t integratorcm_read(void *opaque, hwaddr offset, unsigned size) { integratorcm_state *s = (integratorcm_state *)opaque; @@ -141,7 +141,7 @@ static void integratorcm_update(integratorcm_state *s) hw_error("Core module interrupt\n"); } -static void integratorcm_write(void *opaque, target_phys_addr_t offset, +static void integratorcm_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { integratorcm_state *s = (integratorcm_state *)opaque; @@ -295,7 +295,7 @@ static void icp_pic_set_irq(void *opaque, int irq, int level) icp_pic_update(s); } -static uint64_t icp_pic_read(void *opaque, target_phys_addr_t offset, +static uint64_t icp_pic_read(void *opaque, hwaddr offset, unsigned size) { icp_pic_state *s = (icp_pic_state *)opaque; @@ -324,7 +324,7 @@ static uint64_t icp_pic_read(void *opaque, target_phys_addr_t offset, } } -static void icp_pic_write(void *opaque, target_phys_addr_t offset, +static void icp_pic_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { icp_pic_state *s = (icp_pic_state *)opaque; @@ -381,7 +381,7 @@ static int icp_pic_init(SysBusDevice *dev) /* CP control registers. */ -static uint64_t icp_control_read(void *opaque, target_phys_addr_t offset, +static uint64_t icp_control_read(void *opaque, hwaddr offset, unsigned size) { switch (offset >> 2) { @@ -399,7 +399,7 @@ static uint64_t icp_control_read(void *opaque, target_phys_addr_t offset, } } -static void icp_control_write(void *opaque, target_phys_addr_t offset, +static void icp_control_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { switch (offset >> 2) { @@ -419,7 +419,7 @@ static const MemoryRegionOps icp_control_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void icp_control_init(target_phys_addr_t base) +static void icp_control_init(hwaddr base) { MemoryRegion *io; diff --git a/hw/intel-hda.c b/hw/intel-hda.c index d8e1b23a60..a68c3685e3 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -206,9 +206,9 @@ static void intel_hda_reset(DeviceState *dev); /* --------------------------------------------------------------------- */ -static target_phys_addr_t intel_hda_addr(uint32_t lbase, uint32_t ubase) +static hwaddr intel_hda_addr(uint32_t lbase, uint32_t ubase) { - target_phys_addr_t addr; + hwaddr addr; addr = ((uint64_t)ubase << 32) | lbase; return addr; @@ -295,7 +295,7 @@ static int intel_hda_send_command(IntelHDAState *d, uint32_t verb) static void intel_hda_corb_run(IntelHDAState *d) { - target_phys_addr_t addr; + hwaddr addr; uint32_t rp, verb; if (d->ics & ICH6_IRS_BUSY) { @@ -332,7 +332,7 @@ static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t res { HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, dev->qdev.parent_bus); IntelHDAState *d = container_of(bus, IntelHDAState, codecs); - target_phys_addr_t addr; + hwaddr addr; uint32_t wp, ex; if (d->ics & ICH6_IRS_BUSY) { @@ -381,7 +381,7 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output, { HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, dev->qdev.parent_bus); IntelHDAState *d = container_of(bus, IntelHDAState, codecs); - target_phys_addr_t addr; + hwaddr addr; uint32_t s, copy, left; IntelHDAStream *st; bool irq = false; @@ -453,7 +453,7 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output, static void intel_hda_parse_bdl(IntelHDAState *d, IntelHDAStream *st) { - target_phys_addr_t addr; + hwaddr addr; uint8_t buf[16]; uint32_t i; @@ -890,7 +890,7 @@ static const struct IntelHDAReg regtab[] = { }; -static const IntelHDAReg *intel_hda_reg_find(IntelHDAState *d, target_phys_addr_t addr) +static const IntelHDAReg *intel_hda_reg_find(IntelHDAState *d, hwaddr addr) { const IntelHDAReg *reg; @@ -1033,7 +1033,7 @@ static void intel_hda_regs_reset(IntelHDAState *d) /* --------------------------------------------------------------------- */ -static void intel_hda_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +static void intel_hda_mmio_writeb(void *opaque, hwaddr addr, uint32_t val) { IntelHDAState *d = opaque; const IntelHDAReg *reg = intel_hda_reg_find(d, addr); @@ -1041,7 +1041,7 @@ static void intel_hda_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_ intel_hda_reg_write(d, reg, val, 0xff); } -static void intel_hda_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +static void intel_hda_mmio_writew(void *opaque, hwaddr addr, uint32_t val) { IntelHDAState *d = opaque; const IntelHDAReg *reg = intel_hda_reg_find(d, addr); @@ -1049,7 +1049,7 @@ static void intel_hda_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_ intel_hda_reg_write(d, reg, val, 0xffff); } -static void intel_hda_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +static void intel_hda_mmio_writel(void *opaque, hwaddr addr, uint32_t val) { IntelHDAState *d = opaque; const IntelHDAReg *reg = intel_hda_reg_find(d, addr); @@ -1057,7 +1057,7 @@ static void intel_hda_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_ intel_hda_reg_write(d, reg, val, 0xffffffff); } -static uint32_t intel_hda_mmio_readb(void *opaque, target_phys_addr_t addr) +static uint32_t intel_hda_mmio_readb(void *opaque, hwaddr addr) { IntelHDAState *d = opaque; const IntelHDAReg *reg = intel_hda_reg_find(d, addr); @@ -1065,7 +1065,7 @@ static uint32_t intel_hda_mmio_readb(void *opaque, target_phys_addr_t addr) return intel_hda_reg_read(d, reg, 0xff); } -static uint32_t intel_hda_mmio_readw(void *opaque, target_phys_addr_t addr) +static uint32_t intel_hda_mmio_readw(void *opaque, hwaddr addr) { IntelHDAState *d = opaque; const IntelHDAReg *reg = intel_hda_reg_find(d, addr); @@ -1073,7 +1073,7 @@ static uint32_t intel_hda_mmio_readw(void *opaque, target_phys_addr_t addr) return intel_hda_reg_read(d, reg, 0xffff); } -static uint32_t intel_hda_mmio_readl(void *opaque, target_phys_addr_t addr) +static uint32_t intel_hda_mmio_readl(void *opaque, hwaddr addr) { IntelHDAState *d = opaque; const IntelHDAReg *reg = intel_hda_reg_find(d, addr); diff --git a/hw/ioapic.c b/hw/ioapic.c index e2e4796bb5..72730951a6 100644 --- a/hw/ioapic.c +++ b/hw/ioapic.c @@ -139,7 +139,7 @@ void ioapic_eoi_broadcast(int vector) } static uint64_t -ioapic_mem_read(void *opaque, target_phys_addr_t addr, unsigned int size) +ioapic_mem_read(void *opaque, hwaddr addr, unsigned int size) { IOAPICCommonState *s = opaque; int index; @@ -181,7 +181,7 @@ ioapic_mem_read(void *opaque, target_phys_addr_t addr, unsigned int size) } static void -ioapic_mem_write(void *opaque, target_phys_addr_t addr, uint64_t val, +ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { IOAPICCommonState *s = opaque; diff --git a/hw/isa-bus.c b/hw/isa-bus.c index 214f19457d..685fdc0f82 100644 --- a/hw/isa-bus.c +++ b/hw/isa-bus.c @@ -24,7 +24,7 @@ #include "exec-memory.h" static ISABus *isabus; -target_phys_addr_t isa_mem_base = 0; +hwaddr isa_mem_base = 0; static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent); static char *isabus_get_fw_dev_path(DeviceState *dev); diff --git a/hw/isa.h b/hw/isa.h index 8fb498aa8d..f9382e8367 100644 --- a/hw/isa.h +++ b/hw/isa.h @@ -84,10 +84,10 @@ static inline ISABus *isa_bus_from_device(ISADevice *d) return DO_UPCAST(ISABus, qbus, d->qdev.parent_bus); } -extern target_phys_addr_t isa_mem_base; +extern hwaddr isa_mem_base; -void isa_mmio_setup(MemoryRegion *mr, target_phys_addr_t size); -void isa_mmio_init(target_phys_addr_t base, target_phys_addr_t size); +void isa_mmio_setup(MemoryRegion *mr, hwaddr size); +void isa_mmio_init(hwaddr base, hwaddr size); /* dma.c */ int DMA_get_channel_mode (int nchan); diff --git a/hw/isa_mmio.c b/hw/isa_mmio.c index fd755ab4a8..14053960cb 100644 --- a/hw/isa_mmio.c +++ b/hw/isa_mmio.c @@ -26,35 +26,35 @@ #include "isa.h" #include "exec-memory.h" -static void isa_mmio_writeb (void *opaque, target_phys_addr_t addr, +static void isa_mmio_writeb (void *opaque, hwaddr addr, uint32_t val) { cpu_outb(addr & IOPORTS_MASK, val); } -static void isa_mmio_writew(void *opaque, target_phys_addr_t addr, +static void isa_mmio_writew(void *opaque, hwaddr addr, uint32_t val) { cpu_outw(addr & IOPORTS_MASK, val); } -static void isa_mmio_writel(void *opaque, target_phys_addr_t addr, +static void isa_mmio_writel(void *opaque, hwaddr addr, uint32_t val) { cpu_outl(addr & IOPORTS_MASK, val); } -static uint32_t isa_mmio_readb (void *opaque, target_phys_addr_t addr) +static uint32_t isa_mmio_readb (void *opaque, hwaddr addr) { return cpu_inb(addr & IOPORTS_MASK); } -static uint32_t isa_mmio_readw(void *opaque, target_phys_addr_t addr) +static uint32_t isa_mmio_readw(void *opaque, hwaddr addr) { return cpu_inw(addr & IOPORTS_MASK); } -static uint32_t isa_mmio_readl(void *opaque, target_phys_addr_t addr) +static uint32_t isa_mmio_readl(void *opaque, hwaddr addr) { return cpu_inl(addr & IOPORTS_MASK); } @@ -67,12 +67,12 @@ static const MemoryRegionOps isa_mmio_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -void isa_mmio_setup(MemoryRegion *mr, target_phys_addr_t size) +void isa_mmio_setup(MemoryRegion *mr, hwaddr size) { memory_region_init_io(mr, &isa_mmio_ops, NULL, "isa-mmio", size); } -void isa_mmio_init(target_phys_addr_t base, target_phys_addr_t size) +void isa_mmio_init(hwaddr base, hwaddr size) { MemoryRegion *mr = g_malloc(sizeof(*mr)); diff --git a/hw/ivshmem.c b/hw/ivshmem.c index 5c4ccb85f0..f6dbb212f2 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -163,7 +163,7 @@ static uint32_t ivshmem_IntrStatus_read(IVShmemState *s) return ret; } -static void ivshmem_io_write(void *opaque, target_phys_addr_t addr, +static void ivshmem_io_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { IVShmemState *s = opaque; @@ -202,7 +202,7 @@ static void ivshmem_io_write(void *opaque, target_phys_addr_t addr, } } -static uint64_t ivshmem_io_read(void *opaque, target_phys_addr_t addr, +static uint64_t ivshmem_io_read(void *opaque, hwaddr addr, unsigned size) { diff --git a/hw/jazz_led.c b/hw/jazz_led.c index 648652302a..a6a90ab283 100644 --- a/hw/jazz_led.c +++ b/hw/jazz_led.c @@ -39,7 +39,7 @@ typedef struct LedState { screen_state_t state; } LedState; -static uint64_t jazz_led_read(void *opaque, target_phys_addr_t addr, +static uint64_t jazz_led_read(void *opaque, hwaddr addr, unsigned int size) { LedState *s = opaque; @@ -51,7 +51,7 @@ static uint64_t jazz_led_read(void *opaque, target_phys_addr_t addr, return val; } -static void jazz_led_write(void *opaque, target_phys_addr_t addr, +static void jazz_led_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { LedState *s = opaque; diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c index 80e3e48333..dbac7fff50 100644 --- a/hw/kvm/apic.c +++ b/hw/kvm/apic.c @@ -146,13 +146,13 @@ static void kvm_apic_external_nmi(APICCommonState *s) run_on_cpu(s->cpu_env, do_inject_external_nmi, s); } -static uint64_t kvm_apic_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t kvm_apic_mem_read(void *opaque, hwaddr addr, unsigned size) { return ~(uint64_t)0; } -static void kvm_apic_mem_write(void *opaque, target_phys_addr_t addr, +static void kvm_apic_mem_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { MSIMessage msg = { .address = addr, .data = data }; diff --git a/hw/kvm/pci-assign.c b/hw/kvm/pci-assign.c index 7a0998c518..bfffbab1b3 100644 --- a/hw/kvm/pci-assign.c +++ b/hw/kvm/pci-assign.c @@ -133,7 +133,7 @@ typedef struct AssignedDevice { int msi_virq_nr; int *msi_virq; MSIXTableEntry *msix_table; - target_phys_addr_t msix_table_addr; + hwaddr msix_table_addr; uint16_t msix_max; MemoryRegion mmio; char *configfd_name; @@ -147,7 +147,7 @@ static void assigned_dev_load_option_rom(AssignedDevice *dev); static void assigned_dev_unregister_msix_mmio(AssignedDevice *dev); static uint64_t assigned_dev_ioport_rw(AssignedDevRegion *dev_region, - target_phys_addr_t addr, int size, + hwaddr addr, int size, uint64_t *data) { uint64_t val = 0; @@ -206,19 +206,19 @@ static uint64_t assigned_dev_ioport_rw(AssignedDevRegion *dev_region, return val; } -static void assigned_dev_ioport_write(void *opaque, target_phys_addr_t addr, +static void assigned_dev_ioport_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { assigned_dev_ioport_rw(opaque, addr, size, &data); } static uint64_t assigned_dev_ioport_read(void *opaque, - target_phys_addr_t addr, unsigned size) + hwaddr addr, unsigned size) { return assigned_dev_ioport_rw(opaque, addr, size, NULL); } -static uint32_t slow_bar_readb(void *opaque, target_phys_addr_t addr) +static uint32_t slow_bar_readb(void *opaque, hwaddr addr) { AssignedDevRegion *d = opaque; uint8_t *in = d->u.r_virtbase + addr; @@ -230,7 +230,7 @@ static uint32_t slow_bar_readb(void *opaque, target_phys_addr_t addr) return r; } -static uint32_t slow_bar_readw(void *opaque, target_phys_addr_t addr) +static uint32_t slow_bar_readw(void *opaque, hwaddr addr) { AssignedDevRegion *d = opaque; uint16_t *in = (uint16_t *)(d->u.r_virtbase + addr); @@ -242,7 +242,7 @@ static uint32_t slow_bar_readw(void *opaque, target_phys_addr_t addr) return r; } -static uint32_t slow_bar_readl(void *opaque, target_phys_addr_t addr) +static uint32_t slow_bar_readl(void *opaque, hwaddr addr) { AssignedDevRegion *d = opaque; uint32_t *in = (uint32_t *)(d->u.r_virtbase + addr); @@ -254,7 +254,7 @@ static uint32_t slow_bar_readl(void *opaque, target_phys_addr_t addr) return r; } -static void slow_bar_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +static void slow_bar_writeb(void *opaque, hwaddr addr, uint32_t val) { AssignedDevRegion *d = opaque; uint8_t *out = d->u.r_virtbase + addr; @@ -263,7 +263,7 @@ static void slow_bar_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) *out = val; } -static void slow_bar_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +static void slow_bar_writew(void *opaque, hwaddr addr, uint32_t val) { AssignedDevRegion *d = opaque; uint16_t *out = (uint16_t *)(d->u.r_virtbase + addr); @@ -272,7 +272,7 @@ static void slow_bar_writew(void *opaque, target_phys_addr_t addr, uint32_t val) *out = val; } -static void slow_bar_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +static void slow_bar_writel(void *opaque, hwaddr addr, uint32_t val) { AssignedDevRegion *d = opaque; uint32_t *out = (uint32_t *)(d->u.r_virtbase + addr); @@ -1499,7 +1499,7 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev) } static uint64_t -assigned_dev_msix_mmio_read(void *opaque, target_phys_addr_t addr, +assigned_dev_msix_mmio_read(void *opaque, hwaddr addr, unsigned size) { AssignedDevice *adev = opaque; @@ -1510,7 +1510,7 @@ assigned_dev_msix_mmio_read(void *opaque, target_phys_addr_t addr, return val; } -static void assigned_dev_msix_mmio_write(void *opaque, target_phys_addr_t addr, +static void assigned_dev_msix_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { AssignedDevice *adev = opaque; diff --git a/hw/kvmvapic.c b/hw/kvmvapic.c index 5d83625f4a..5e0a7c9384 100644 --- a/hw/kvmvapic.c +++ b/hw/kvmvapic.c @@ -144,7 +144,7 @@ static void update_guest_rom_state(VAPICROMState *s) static int find_real_tpr_addr(VAPICROMState *s, CPUX86State *env) { - target_phys_addr_t paddr; + hwaddr paddr; target_ulong addr; if (s->state == VAPIC_ACTIVE) { @@ -269,7 +269,7 @@ instruction_ok: static int update_rom_mapping(VAPICROMState *s, CPUX86State *env, target_ulong ip) { - target_phys_addr_t paddr; + hwaddr paddr; uint32_t rom_state_vaddr; uint32_t pos, patch, offset; @@ -350,14 +350,14 @@ static int get_kpcr_number(CPUX86State *env) static int vapic_enable(VAPICROMState *s, CPUX86State *env) { int cpu_number = get_kpcr_number(env); - target_phys_addr_t vapic_paddr; + hwaddr vapic_paddr; static const uint8_t enabled = 1; if (cpu_number < 0) { return -1; } vapic_paddr = s->vapic_paddr + - (((target_phys_addr_t)cpu_number) << VAPIC_CPU_SHIFT); + (((hwaddr)cpu_number) << VAPIC_CPU_SHIFT); cpu_physical_memory_rw(vapic_paddr + offsetof(VAPICState, enabled), (void *)&enabled, sizeof(enabled), 1); apic_enable_vapic(env->apic_state, vapic_paddr); @@ -384,7 +384,7 @@ static void patch_call(VAPICROMState *s, CPUX86State *env, target_ulong ip, static void patch_instruction(VAPICROMState *s, CPUX86State *env, target_ulong ip) { - target_phys_addr_t paddr; + hwaddr paddr; VAPICHandlers *handlers; uint8_t opcode[2]; uint32_t imm32; @@ -500,7 +500,7 @@ static void vapic_reset(DeviceState *dev) */ static int patch_hypercalls(VAPICROMState *s) { - target_phys_addr_t rom_paddr = s->rom_state_paddr & ROM_BLOCK_MASK; + hwaddr rom_paddr = s->rom_state_paddr & ROM_BLOCK_MASK; static const uint8_t vmcall_pattern[] = { /* vmcall */ 0xb8, 0x1, 0, 0, 0, 0xf, 0x1, 0xc1 }; @@ -557,7 +557,7 @@ static int patch_hypercalls(VAPICROMState *s) */ static void vapic_map_rom_writable(VAPICROMState *s) { - target_phys_addr_t rom_paddr = s->rom_state_paddr & ROM_BLOCK_MASK; + hwaddr rom_paddr = s->rom_state_paddr & ROM_BLOCK_MASK; MemoryRegionSection section; MemoryRegion *as; size_t rom_size; @@ -603,11 +603,11 @@ static int vapic_prepare(VAPICROMState *s) return 0; } -static void vapic_write(void *opaque, target_phys_addr_t addr, uint64_t data, +static void vapic_write(void *opaque, hwaddr addr, uint64_t data, unsigned int size) { CPUX86State *env = cpu_single_env; - target_phys_addr_t rom_paddr; + hwaddr rom_paddr; VAPICROMState *s = opaque; cpu_synchronize_state(env); diff --git a/hw/lan9118.c b/hw/lan9118.c index ceaf96fc3e..f724e1c301 100644 --- a/hw/lan9118.c +++ b/hw/lan9118.c @@ -1000,7 +1000,7 @@ static void lan9118_tick(void *opaque) lan9118_update(s); } -static void lan9118_writel(void *opaque, target_phys_addr_t offset, +static void lan9118_writel(void *opaque, hwaddr offset, uint64_t val, unsigned size) { lan9118_state *s = (lan9118_state *)opaque; @@ -1134,7 +1134,7 @@ static void lan9118_writel(void *opaque, target_phys_addr_t offset, lan9118_update(s); } -static void lan9118_writew(void *opaque, target_phys_addr_t offset, +static void lan9118_writew(void *opaque, hwaddr offset, uint32_t val) { lan9118_state *s = (lan9118_state *)opaque; @@ -1161,7 +1161,7 @@ static void lan9118_writew(void *opaque, target_phys_addr_t offset, } } -static void lan9118_16bit_mode_write(void *opaque, target_phys_addr_t offset, +static void lan9118_16bit_mode_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { switch (size) { @@ -1176,7 +1176,7 @@ static void lan9118_16bit_mode_write(void *opaque, target_phys_addr_t offset, hw_error("lan9118_write: Bad size 0x%x\n", size); } -static uint64_t lan9118_readl(void *opaque, target_phys_addr_t offset, +static uint64_t lan9118_readl(void *opaque, hwaddr offset, unsigned size) { lan9118_state *s = (lan9118_state *)opaque; @@ -1250,7 +1250,7 @@ static uint64_t lan9118_readl(void *opaque, target_phys_addr_t offset, return 0; } -static uint32_t lan9118_readw(void *opaque, target_phys_addr_t offset) +static uint32_t lan9118_readw(void *opaque, hwaddr offset) { lan9118_state *s = (lan9118_state *)opaque; uint32_t val; @@ -1278,7 +1278,7 @@ static uint32_t lan9118_readw(void *opaque, target_phys_addr_t offset) return val; } -static uint64_t lan9118_16bit_mode_read(void *opaque, target_phys_addr_t offset, +static uint64_t lan9118_16bit_mode_read(void *opaque, hwaddr offset, unsigned size) { switch (size) { diff --git a/hw/lance.c b/hw/lance.c index 9b98bb849a..a3e6dd91d5 100644 --- a/hw/lance.c +++ b/hw/lance.c @@ -55,7 +55,7 @@ static void parent_lance_reset(void *opaque, int irq, int level) pcnet_h_reset(&d->state); } -static void lance_mem_write(void *opaque, target_phys_addr_t addr, +static void lance_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { SysBusPCNetState *d = opaque; @@ -64,7 +64,7 @@ static void lance_mem_write(void *opaque, target_phys_addr_t addr, pcnet_ioport_writew(&d->state, addr, val & 0xffff); } -static uint64_t lance_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t lance_mem_read(void *opaque, hwaddr addr, unsigned size) { SysBusPCNetState *d = opaque; diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c index c5a62c8264..772cb8b053 100644 --- a/hw/lm32_boards.c +++ b/hw/lm32_boards.c @@ -32,12 +32,12 @@ typedef struct { LM32CPU *cpu; - target_phys_addr_t bootstrap_pc; - target_phys_addr_t flash_base; - target_phys_addr_t hwsetup_base; - target_phys_addr_t initrd_base; + hwaddr bootstrap_pc; + hwaddr flash_base; + hwaddr hwsetup_base; + hwaddr initrd_base; size_t initrd_size; - target_phys_addr_t cmdline_base; + hwaddr cmdline_base; } ResetInfo; static void cpu_irq_handler(void *opaque, int irq, int level) @@ -83,14 +83,14 @@ static void lm32_evr_init(QEMUMachineInitArgs *args) int i; /* memory map */ - target_phys_addr_t flash_base = 0x04000000; + hwaddr flash_base = 0x04000000; size_t flash_sector_size = 256 * 1024; size_t flash_size = 32 * 1024 * 1024; - target_phys_addr_t ram_base = 0x08000000; + hwaddr ram_base = 0x08000000; size_t ram_size = 64 * 1024 * 1024; - target_phys_addr_t timer0_base = 0x80002000; - target_phys_addr_t uart0_base = 0x80006000; - target_phys_addr_t timer1_base = 0x8000a000; + hwaddr timer0_base = 0x80002000; + hwaddr uart0_base = 0x80006000; + hwaddr timer1_base = 0x8000a000; int uart0_irq = 0; int timer0_irq = 1; int timer1_irq = 3; @@ -174,22 +174,22 @@ static void lm32_uclinux_init(QEMUMachineInitArgs *args) int i; /* memory map */ - target_phys_addr_t flash_base = 0x04000000; + hwaddr flash_base = 0x04000000; size_t flash_sector_size = 256 * 1024; size_t flash_size = 32 * 1024 * 1024; - target_phys_addr_t ram_base = 0x08000000; + hwaddr ram_base = 0x08000000; size_t ram_size = 64 * 1024 * 1024; - target_phys_addr_t uart0_base = 0x80000000; - target_phys_addr_t timer0_base = 0x80002000; - target_phys_addr_t timer1_base = 0x80010000; - target_phys_addr_t timer2_base = 0x80012000; + hwaddr uart0_base = 0x80000000; + hwaddr timer0_base = 0x80002000; + hwaddr timer1_base = 0x80010000; + hwaddr timer2_base = 0x80012000; int uart0_irq = 0; int timer0_irq = 1; int timer1_irq = 20; int timer2_irq = 21; - target_phys_addr_t hwsetup_base = 0x0bffe000; - target_phys_addr_t cmdline_base = 0x0bfff000; - target_phys_addr_t initrd_base = 0x08400000; + hwaddr hwsetup_base = 0x0bffe000; + hwaddr cmdline_base = 0x0bfff000; + hwaddr initrd_base = 0x08400000; size_t initrd_max = 0x01000000; reset_info = g_malloc0(sizeof(ResetInfo)); diff --git a/hw/lm32_hwsetup.h b/hw/lm32_hwsetup.h index 70dc61f9e7..853e9abc7b 100644 --- a/hw/lm32_hwsetup.h +++ b/hw/lm32_hwsetup.h @@ -71,7 +71,7 @@ static inline void hwsetup_free(HWSetup *hw) } static inline void hwsetup_create_rom(HWSetup *hw, - target_phys_addr_t base) + hwaddr base) { rom_add_blob("hwsetup", hw->data, TARGET_PAGE_SIZE, base); } diff --git a/hw/lm32_sys.c b/hw/lm32_sys.c index bbe03c41d5..a7887d14f6 100644 --- a/hw/lm32_sys.c +++ b/hw/lm32_sys.c @@ -61,7 +61,7 @@ static void copy_testname(LM32SysState *s) s->testname[MAX_TESTNAME_LEN - 1] = '\0'; } -static void sys_write(void *opaque, target_phys_addr_t addr, +static void sys_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { LM32SysState *s = opaque; @@ -91,7 +91,7 @@ static void sys_write(void *opaque, target_phys_addr_t addr, } } -static bool sys_ops_accepts(void *opaque, target_phys_addr_t addr, +static bool sys_ops_accepts(void *opaque, hwaddr addr, unsigned size, bool is_write) { return is_write && size == 4; diff --git a/hw/lm32_timer.c b/hw/lm32_timer.c index e9450a0ce1..a8be9cc168 100644 --- a/hw/lm32_timer.c +++ b/hw/lm32_timer.c @@ -72,7 +72,7 @@ static void timer_update_irq(LM32TimerState *s) qemu_set_irq(s->irq, state); } -static uint64_t timer_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size) { LM32TimerState *s = opaque; uint32_t r = 0; @@ -97,7 +97,7 @@ static uint64_t timer_read(void *opaque, target_phys_addr_t addr, unsigned size) return r; } -static void timer_write(void *opaque, target_phys_addr_t addr, +static void timer_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { LM32TimerState *s = opaque; diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c index 57066e28c6..adb9287568 100644 --- a/hw/lm32_uart.c +++ b/hw/lm32_uart.c @@ -125,7 +125,7 @@ static void uart_update_irq(LM32UartState *s) qemu_set_irq(s->irq, irq); } -static uint64_t uart_read(void *opaque, target_phys_addr_t addr, +static uint64_t uart_read(void *opaque, hwaddr addr, unsigned size) { LM32UartState *s = opaque; @@ -160,7 +160,7 @@ static uint64_t uart_read(void *opaque, target_phys_addr_t addr, return r; } -static void uart_write(void *opaque, target_phys_addr_t addr, +static void uart_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { LM32UartState *s = opaque; diff --git a/hw/lm4549.c b/hw/lm4549.c index e0137d54b6..b3c2d5f25d 100644 --- a/hw/lm4549.c +++ b/hw/lm4549.c @@ -150,7 +150,7 @@ static void lm4549_audio_out_callback(void *opaque, int free) } } -uint32_t lm4549_read(lm4549_state *s, target_phys_addr_t offset) +uint32_t lm4549_read(lm4549_state *s, hwaddr offset) { uint16_t *regfile = s->regfile; uint32_t value = 0; @@ -165,7 +165,7 @@ uint32_t lm4549_read(lm4549_state *s, target_phys_addr_t offset) } void lm4549_write(lm4549_state *s, - target_phys_addr_t offset, uint32_t value) + hwaddr offset, uint32_t value) { uint16_t *regfile = s->regfile; diff --git a/hw/lm4549.h b/hw/lm4549.h index 5948780e00..812a7a4440 100644 --- a/hw/lm4549.h +++ b/hw/lm4549.h @@ -36,8 +36,8 @@ extern const VMStateDescription vmstate_lm4549_state; void lm4549_init(lm4549_state *s, lm4549_callback data_req, void *opaque); -uint32_t lm4549_read(lm4549_state *s, target_phys_addr_t offset); -void lm4549_write(lm4549_state *s, target_phys_addr_t offset, uint32_t value); +uint32_t lm4549_read(lm4549_state *s, hwaddr offset); +void lm4549_write(lm4549_state *s, hwaddr offset, uint32_t value); uint32_t lm4549_write_samples(lm4549_state *s, uint32_t left, uint32_t right); #endif /* #ifndef HW_LM4549_H */ diff --git a/hw/loader.c b/hw/loader.c index 33acc2fdab..ba01ca6638 100644 --- a/hw/loader.c +++ b/hw/loader.c @@ -88,7 +88,7 @@ int load_image(const char *filename, uint8_t *addr) /* read()-like version */ ssize_t read_targphys(const char *name, - int fd, target_phys_addr_t dst_addr, size_t nbytes) + int fd, hwaddr dst_addr, size_t nbytes) { uint8_t *buf; ssize_t did; @@ -103,7 +103,7 @@ ssize_t read_targphys(const char *name, /* return the size or -1 if error */ int load_image_targphys(const char *filename, - target_phys_addr_t addr, uint64_t max_sz) + hwaddr addr, uint64_t max_sz) { int size; @@ -117,7 +117,7 @@ int load_image_targphys(const char *filename, return size; } -void pstrcpy_targphys(const char *name, target_phys_addr_t dest, int buf_size, +void pstrcpy_targphys(const char *name, hwaddr dest, int buf_size, const char *source) { const char *nulp; @@ -179,8 +179,8 @@ static void bswap_ahdr(struct exec *e) : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x, target_page_size), target_page_size))) -int load_aout(const char *filename, target_phys_addr_t addr, int max_sz, - int bswap_needed, target_phys_addr_t target_page_size) +int load_aout(const char *filename, hwaddr addr, int max_sz, + int bswap_needed, hwaddr target_page_size) { int fd; ssize_t size, ret; @@ -434,8 +434,8 @@ static ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, } /* Load a U-Boot image. */ -int load_uimage(const char *filename, target_phys_addr_t *ep, - target_phys_addr_t *loadaddr, int *is_linux) +int load_uimage(const char *filename, hwaddr *ep, + hwaddr *loadaddr, int *is_linux) { int fd; int size; @@ -539,7 +539,7 @@ struct Rom { char *fw_dir; char *fw_file; - target_phys_addr_t addr; + hwaddr addr; QTAILQ_ENTRY(Rom) next; }; @@ -565,7 +565,7 @@ static void rom_insert(Rom *rom) } int rom_add_file(const char *file, const char *fw_dir, - target_phys_addr_t addr, int32_t bootindex) + hwaddr addr, int32_t bootindex) { Rom *rom; int rc, fd = -1; @@ -633,7 +633,7 @@ err: } int rom_add_blob(const char *name, const void *blob, size_t len, - target_phys_addr_t addr) + hwaddr addr) { Rom *rom; @@ -679,7 +679,7 @@ static void rom_reset(void *unused) int rom_load_all(void) { - target_phys_addr_t addr = 0; + hwaddr addr = 0; MemoryRegionSection section; Rom *rom; @@ -709,7 +709,7 @@ void rom_set_fw(void *f) fw_cfg = f; } -static Rom *find_rom(target_phys_addr_t addr) +static Rom *find_rom(hwaddr addr) { Rom *rom; @@ -733,9 +733,9 @@ static Rom *find_rom(target_phys_addr_t addr) * a ROM between addr and addr + size is copied. Note that this can involve * multiple ROMs, which need not start at addr and need not end at addr + size. */ -int rom_copy(uint8_t *dest, target_phys_addr_t addr, size_t size) +int rom_copy(uint8_t *dest, hwaddr addr, size_t size) { - target_phys_addr_t end = addr + size; + hwaddr end = addr + size; uint8_t *s, *d = dest; size_t l = 0; Rom *rom; @@ -768,7 +768,7 @@ int rom_copy(uint8_t *dest, target_phys_addr_t addr, size_t size) return (d + l) - dest; } -void *rom_ptr(target_phys_addr_t addr) +void *rom_ptr(hwaddr addr) { Rom *rom; diff --git a/hw/loader.h b/hw/loader.h index 6da291e31f..26480ad8dd 100644 --- a/hw/loader.h +++ b/hw/loader.h @@ -4,32 +4,32 @@ /* loader.c */ int get_image_size(const char *filename); int load_image(const char *filename, uint8_t *addr); /* deprecated */ -int load_image_targphys(const char *filename, target_phys_addr_t, +int load_image_targphys(const char *filename, hwaddr, uint64_t max_sz); int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t), void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr, int big_endian, int elf_machine, int clear_lsb); -int load_aout(const char *filename, target_phys_addr_t addr, int max_sz, - int bswap_needed, target_phys_addr_t target_page_size); -int load_uimage(const char *filename, target_phys_addr_t *ep, - target_phys_addr_t *loadaddr, int *is_linux); +int load_aout(const char *filename, hwaddr addr, int max_sz, + int bswap_needed, hwaddr target_page_size); +int load_uimage(const char *filename, hwaddr *ep, + hwaddr *loadaddr, int *is_linux); ssize_t read_targphys(const char *name, - int fd, target_phys_addr_t dst_addr, size_t nbytes); + int fd, hwaddr dst_addr, size_t nbytes); void pstrcpy_targphys(const char *name, - target_phys_addr_t dest, int buf_size, + hwaddr dest, int buf_size, const char *source); int rom_add_file(const char *file, const char *fw_dir, - target_phys_addr_t addr, int32_t bootindex); + hwaddr addr, int32_t bootindex); int rom_add_blob(const char *name, const void *blob, size_t len, - target_phys_addr_t addr); + hwaddr addr); int rom_load_all(void); void rom_set_fw(void *f); -int rom_copy(uint8_t *dest, target_phys_addr_t addr, size_t size); -void *rom_ptr(target_phys_addr_t addr); +int rom_copy(uint8_t *dest, hwaddr addr, size_t size); +void *rom_ptr(hwaddr addr); void do_info_roms(Monitor *mon); #define rom_add_file_fixed(_f, _a, _i) \ diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index 34afe96742..04f2faef42 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -1878,7 +1878,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) #undef CASE_SET_REG32 } -static void lsi_mmio_write(void *opaque, target_phys_addr_t addr, +static void lsi_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { LSIState *s = opaque; @@ -1886,7 +1886,7 @@ static void lsi_mmio_write(void *opaque, target_phys_addr_t addr, lsi_reg_writeb(s, addr & 0xff, val); } -static uint64_t lsi_mmio_read(void *opaque, target_phys_addr_t addr, +static uint64_t lsi_mmio_read(void *opaque, hwaddr addr, unsigned size) { LSIState *s = opaque; @@ -1904,7 +1904,7 @@ static const MemoryRegionOps lsi_mmio_ops = { }, }; -static void lsi_ram_write(void *opaque, target_phys_addr_t addr, +static void lsi_ram_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { LSIState *s = opaque; @@ -1920,7 +1920,7 @@ static void lsi_ram_write(void *opaque, target_phys_addr_t addr, s->script_ram[addr >> 2] = newval; } -static uint64_t lsi_ram_read(void *opaque, target_phys_addr_t addr, +static uint64_t lsi_ram_read(void *opaque, hwaddr addr, unsigned size) { LSIState *s = opaque; @@ -1939,14 +1939,14 @@ static const MemoryRegionOps lsi_ram_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint64_t lsi_io_read(void *opaque, target_phys_addr_t addr, +static uint64_t lsi_io_read(void *opaque, hwaddr addr, unsigned size) { LSIState *s = opaque; return lsi_reg_readb(s, addr & 0xff); } -static void lsi_io_write(void *opaque, target_phys_addr_t addr, +static void lsi_io_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { LSIState *s = opaque; diff --git a/hw/m48t59.c b/hw/m48t59.c index dd6cb37ba6..9eb1a0968a 100644 --- a/hw/m48t59.c +++ b/hw/m48t59.c @@ -522,14 +522,14 @@ static uint32_t NVRAM_readb (void *opaque, uint32_t addr) return retval; } -static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) +static void nvram_writeb (void *opaque, hwaddr addr, uint32_t value) { M48t59State *NVRAM = opaque; m48t59_write(NVRAM, addr, value & 0xff); } -static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value) +static void nvram_writew (void *opaque, hwaddr addr, uint32_t value) { M48t59State *NVRAM = opaque; @@ -537,7 +537,7 @@ static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value) m48t59_write(NVRAM, addr + 1, value & 0xff); } -static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +static void nvram_writel (void *opaque, hwaddr addr, uint32_t value) { M48t59State *NVRAM = opaque; @@ -547,7 +547,7 @@ static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value) m48t59_write(NVRAM, addr + 3, value & 0xff); } -static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr) +static uint32_t nvram_readb (void *opaque, hwaddr addr) { M48t59State *NVRAM = opaque; uint32_t retval; @@ -556,7 +556,7 @@ static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr) return retval; } -static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr) +static uint32_t nvram_readw (void *opaque, hwaddr addr) { M48t59State *NVRAM = opaque; uint32_t retval; @@ -566,7 +566,7 @@ static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr) return retval; } -static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr) +static uint32_t nvram_readl (void *opaque, hwaddr addr) { M48t59State *NVRAM = opaque; uint32_t retval; @@ -636,7 +636,7 @@ static const MemoryRegionOps m48t59_io_ops = { }; /* Initialisation routine */ -M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base, +M48t59State *m48t59_init(qemu_irq IRQ, hwaddr mem_base, uint32_t io_base, uint16_t size, int model) { DeviceState *dev; diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c index 1791ec12e1..e551156af9 100644 --- a/hw/mac_dbdma.c +++ b/hw/mac_dbdma.c @@ -699,7 +699,7 @@ dbdma_control_write(DBDMA_channel *ch) ch->flush(&ch->io); } -static void dbdma_write(void *opaque, target_phys_addr_t addr, +static void dbdma_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { int channel = addr >> DBDMA_CHANNEL_SHIFT; @@ -749,7 +749,7 @@ static void dbdma_write(void *opaque, target_phys_addr_t addr, } } -static uint64_t dbdma_read(void *opaque, target_phys_addr_t addr, +static uint64_t dbdma_read(void *opaque, hwaddr addr, unsigned size) { uint32_t value; diff --git a/hw/mac_dbdma.h b/hw/mac_dbdma.h index 6d1abe6aae..bfdb0ddc68 100644 --- a/hw/mac_dbdma.h +++ b/hw/mac_dbdma.h @@ -30,7 +30,7 @@ typedef void (*DBDMA_end)(DBDMA_io *io); struct DBDMA_io { void *opaque; void *channel; - target_phys_addr_t addr; + hwaddr addr; int len; int is_last; int is_dma_out; diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c index ed0a2b7ef2..a0d14dd3c5 100644 --- a/hw/mac_nvram.c +++ b/hw/mac_nvram.c @@ -71,7 +71,7 @@ void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val) } /* macio style NVRAM device */ -static void macio_nvram_writeb(void *opaque, target_phys_addr_t addr, +static void macio_nvram_writeb(void *opaque, hwaddr addr, uint64_t value, unsigned size) { MacIONVRAMState *s = opaque; @@ -81,7 +81,7 @@ static void macio_nvram_writeb(void *opaque, target_phys_addr_t addr, NVR_DPRINTF("writeb addr %04x val %x\n", (int)addr, value); } -static uint64_t macio_nvram_readb(void *opaque, target_phys_addr_t addr, +static uint64_t macio_nvram_readb(void *opaque, hwaddr addr, unsigned size) { MacIONVRAMState *s = opaque; @@ -116,7 +116,7 @@ static void macio_nvram_reset(void *opaque) { } -MacIONVRAMState *macio_nvram_init (target_phys_addr_t size, +MacIONVRAMState *macio_nvram_init (hwaddr size, unsigned int it_shift) { MacIONVRAMState *s; @@ -135,7 +135,7 @@ MacIONVRAMState *macio_nvram_init (target_phys_addr_t size, } void macio_nvram_setup_bar(MacIONVRAMState *s, MemoryRegion *bar, - target_phys_addr_t mem_base) + hwaddr mem_base) { memory_region_add_subregion(bar, mem_base, &s->mem); } diff --git a/hw/mainstone.c b/hw/mainstone.c index c0d6034147..3266946954 100644 --- a/hw/mainstone.c +++ b/hw/mainstone.c @@ -101,7 +101,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem, const char *cpu_model, enum mainstone_model_e model, int arm_id) { uint32_t sector_len = 256 * 1024; - target_phys_addr_t mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 }; + hwaddr mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 }; PXA2xxState *mpu; DeviceState *mst_irq; DriveInfo *dinfo; diff --git a/hw/marvell_88w8618_audio.c b/hw/marvell_88w8618_audio.c index f6f1937442..de16cfa090 100644 --- a/hw/marvell_88w8618_audio.c +++ b/hw/marvell_88w8618_audio.c @@ -138,7 +138,7 @@ static void mv88w8618_audio_clock_update(mv88w8618_audio_state *s) wm8750_set_bclk_in(s->wm, rate); } -static uint64_t mv88w8618_audio_read(void *opaque, target_phys_addr_t offset, +static uint64_t mv88w8618_audio_read(void *opaque, hwaddr offset, unsigned size) { mv88w8618_audio_state *s = opaque; @@ -164,7 +164,7 @@ static uint64_t mv88w8618_audio_read(void *opaque, target_phys_addr_t offset, } } -static void mv88w8618_audio_write(void *opaque, target_phys_addr_t offset, +static void mv88w8618_audio_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { mv88w8618_audio_state *s = opaque; diff --git a/hw/mcf.h b/hw/mcf.h index 19a8b54778..f929910f02 100644 --- a/hw/mcf.h +++ b/hw/mcf.h @@ -5,23 +5,23 @@ struct MemoryRegion; /* mcf_uart.c */ -uint64_t mcf_uart_read(void *opaque, target_phys_addr_t addr, +uint64_t mcf_uart_read(void *opaque, hwaddr addr, unsigned size); -void mcf_uart_write(void *opaque, target_phys_addr_t addr, +void mcf_uart_write(void *opaque, hwaddr addr, uint64_t val, unsigned size); void *mcf_uart_init(qemu_irq irq, CharDriverState *chr); void mcf_uart_mm_init(struct MemoryRegion *sysmem, - target_phys_addr_t base, + hwaddr base, qemu_irq irq, CharDriverState *chr); /* mcf_intc.c */ qemu_irq *mcf_intc_init(struct MemoryRegion *sysmem, - target_phys_addr_t base, + hwaddr base, CPUM68KState *env); /* mcf_fec.c */ void mcf_fec_init(struct MemoryRegion *sysmem, NICInfo *nd, - target_phys_addr_t base, qemu_irq *irq); + hwaddr base, qemu_irq *irq); /* mcf5206.c */ qemu_irq *mcf5206_init(struct MemoryRegion *sysmem, diff --git a/hw/mcf5206.c b/hw/mcf5206.c index 27753e2717..510d77047e 100644 --- a/hw/mcf5206.c +++ b/hw/mcf5206.c @@ -371,10 +371,10 @@ static const int m5206_mbar_width[] = /* 1c0-200 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; -static uint32_t m5206_mbar_readw(void *opaque, target_phys_addr_t offset); -static uint32_t m5206_mbar_readl(void *opaque, target_phys_addr_t offset); +static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset); +static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset); -static uint32_t m5206_mbar_readb(void *opaque, target_phys_addr_t offset) +static uint32_t m5206_mbar_readb(void *opaque, hwaddr offset) { m5206_mbar_state *s = (m5206_mbar_state *)opaque; offset &= 0x3ff; @@ -392,7 +392,7 @@ static uint32_t m5206_mbar_readb(void *opaque, target_phys_addr_t offset) return m5206_mbar_read(s, offset, 1); } -static uint32_t m5206_mbar_readw(void *opaque, target_phys_addr_t offset) +static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset) { m5206_mbar_state *s = (m5206_mbar_state *)opaque; int width; @@ -416,7 +416,7 @@ static uint32_t m5206_mbar_readw(void *opaque, target_phys_addr_t offset) return m5206_mbar_read(s, offset, 2); } -static uint32_t m5206_mbar_readl(void *opaque, target_phys_addr_t offset) +static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset) { m5206_mbar_state *s = (m5206_mbar_state *)opaque; int width; @@ -434,12 +434,12 @@ static uint32_t m5206_mbar_readl(void *opaque, target_phys_addr_t offset) return m5206_mbar_read(s, offset, 4); } -static void m5206_mbar_writew(void *opaque, target_phys_addr_t offset, +static void m5206_mbar_writew(void *opaque, hwaddr offset, uint32_t value); -static void m5206_mbar_writel(void *opaque, target_phys_addr_t offset, +static void m5206_mbar_writel(void *opaque, hwaddr offset, uint32_t value); -static void m5206_mbar_writeb(void *opaque, target_phys_addr_t offset, +static void m5206_mbar_writeb(void *opaque, hwaddr offset, uint32_t value) { m5206_mbar_state *s = (m5206_mbar_state *)opaque; @@ -463,7 +463,7 @@ static void m5206_mbar_writeb(void *opaque, target_phys_addr_t offset, m5206_mbar_write(s, offset, value, 1); } -static void m5206_mbar_writew(void *opaque, target_phys_addr_t offset, +static void m5206_mbar_writew(void *opaque, hwaddr offset, uint32_t value) { m5206_mbar_state *s = (m5206_mbar_state *)opaque; @@ -491,7 +491,7 @@ static void m5206_mbar_writew(void *opaque, target_phys_addr_t offset, m5206_mbar_write(s, offset, value, 2); } -static void m5206_mbar_writel(void *opaque, target_phys_addr_t offset, +static void m5206_mbar_writel(void *opaque, hwaddr offset, uint32_t value) { m5206_mbar_state *s = (m5206_mbar_state *)opaque; diff --git a/hw/mcf5208.c b/hw/mcf5208.c index 688bc3c1a6..b1db54937e 100644 --- a/hw/mcf5208.c +++ b/hw/mcf5208.c @@ -45,7 +45,7 @@ static void m5208_timer_update(m5208_timer_state *s) qemu_irq_lower(s->irq); } -static void m5208_timer_write(void *opaque, target_phys_addr_t offset, +static void m5208_timer_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { m5208_timer_state *s = (m5208_timer_state *)opaque; @@ -107,7 +107,7 @@ static void m5208_timer_trigger(void *opaque) m5208_timer_update(s); } -static uint64_t m5208_timer_read(void *opaque, target_phys_addr_t addr, +static uint64_t m5208_timer_read(void *opaque, hwaddr addr, unsigned size) { m5208_timer_state *s = (m5208_timer_state *)opaque; @@ -130,7 +130,7 @@ static const MemoryRegionOps m5208_timer_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint64_t m5208_sys_read(void *opaque, target_phys_addr_t addr, +static uint64_t m5208_sys_read(void *opaque, hwaddr addr, unsigned size) { switch (addr) { @@ -152,7 +152,7 @@ static uint64_t m5208_sys_read(void *opaque, target_phys_addr_t addr, } } -static void m5208_sys_write(void *opaque, target_phys_addr_t addr, +static void m5208_sys_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { hw_error("m5208_sys_write: Bad offset 0x%x\n", (int)addr); @@ -195,7 +195,7 @@ static void mcf5208evb_init(QEMUMachineInitArgs *args) CPUM68KState *env; int kernel_size; uint64_t elf_entry; - target_phys_addr_t entry; + hwaddr entry; qemu_irq *pic; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c index 2fec5bc73e..1ed193c5db 100644 --- a/hw/mcf_fec.c +++ b/hw/mcf_fec.c @@ -216,7 +216,7 @@ static void mcf_fec_reset(mcf_fec_state *s) s->rfsr = 0x500; } -static uint64_t mcf_fec_read(void *opaque, target_phys_addr_t addr, +static uint64_t mcf_fec_read(void *opaque, hwaddr addr, unsigned size) { mcf_fec_state *s = (mcf_fec_state *)opaque; @@ -254,7 +254,7 @@ static uint64_t mcf_fec_read(void *opaque, target_phys_addr_t addr, } } -static void mcf_fec_write(void *opaque, target_phys_addr_t addr, +static void mcf_fec_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { mcf_fec_state *s = (mcf_fec_state *)opaque; @@ -458,7 +458,7 @@ static NetClientInfo net_mcf_fec_info = { }; void mcf_fec_init(MemoryRegion *sysmem, NICInfo *nd, - target_phys_addr_t base, qemu_irq *irq) + hwaddr base, qemu_irq *irq) { mcf_fec_state *s; diff --git a/hw/mcf_intc.c b/hw/mcf_intc.c index cc1a5f3763..6ef6dac931 100644 --- a/hw/mcf_intc.c +++ b/hw/mcf_intc.c @@ -43,7 +43,7 @@ static void mcf_intc_update(mcf_intc_state *s) m68k_set_irq_level(s->env, best_level, s->active_vector); } -static uint64_t mcf_intc_read(void *opaque, target_phys_addr_t addr, +static uint64_t mcf_intc_read(void *opaque, hwaddr addr, unsigned size) { int offset; @@ -76,7 +76,7 @@ static uint64_t mcf_intc_read(void *opaque, target_phys_addr_t addr, } } -static void mcf_intc_write(void *opaque, target_phys_addr_t addr, +static void mcf_intc_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { int offset; @@ -138,7 +138,7 @@ static const MemoryRegionOps mcf_intc_ops = { }; qemu_irq *mcf_intc_init(MemoryRegion *sysmem, - target_phys_addr_t base, + hwaddr base, CPUM68KState *env) { mcf_intc_state *s; diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c index ec6a87f238..d1655f8f2c 100644 --- a/hw/mcf_uart.c +++ b/hw/mcf_uart.c @@ -66,7 +66,7 @@ static void mcf_uart_update(mcf_uart_state *s) qemu_set_irq(s->irq, (s->isr & s->imr) != 0); } -uint64_t mcf_uart_read(void *opaque, target_phys_addr_t addr, +uint64_t mcf_uart_read(void *opaque, hwaddr addr, unsigned size) { mcf_uart_state *s = (mcf_uart_state *)opaque; @@ -185,7 +185,7 @@ static void mcf_do_command(mcf_uart_state *s, uint8_t cmd) } } -void mcf_uart_write(void *opaque, target_phys_addr_t addr, +void mcf_uart_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { mcf_uart_state *s = (mcf_uart_state *)opaque; @@ -294,7 +294,7 @@ static const MemoryRegionOps mcf_uart_ops = { }; void mcf_uart_mm_init(MemoryRegion *sysmem, - target_phys_addr_t base, + hwaddr base, qemu_irq irq, CharDriverState *chr) { diff --git a/hw/megasas.c b/hw/megasas.c index 0e57740fd2..7a2036eb76 100644 --- a/hw/megasas.c +++ b/hw/megasas.c @@ -59,8 +59,8 @@ typedef struct MegasasCmd { uint16_t count; uint64_t context; - target_phys_addr_t pa; - target_phys_addr_t pa_size; + hwaddr pa; + hwaddr pa_size; union mfi_frame *frame; SCSIRequest *req; QEMUSGList qsg; @@ -277,7 +277,7 @@ static int megasas_build_sense(MegasasCmd *cmd, uint8_t *sense_ptr, uint8_t sense_len) { uint32_t pa_hi = 0, pa_lo; - target_phys_addr_t pa; + hwaddr pa; if (sense_len > cmd->frame->header.sense_len) { sense_len = cmd->frame->header.sense_len; @@ -404,7 +404,7 @@ static int megasas_next_index(MegasasState *s, int index, int limit) } static MegasasCmd *megasas_lookup_frame(MegasasState *s, - target_phys_addr_t frame) + hwaddr frame) { MegasasCmd *cmd = NULL; int num = 0, index; @@ -424,7 +424,7 @@ static MegasasCmd *megasas_lookup_frame(MegasasState *s, } static MegasasCmd *megasas_next_frame(MegasasState *s, - target_phys_addr_t frame) + hwaddr frame) { MegasasCmd *cmd = NULL; int num = 0, index; @@ -452,11 +452,11 @@ static MegasasCmd *megasas_next_frame(MegasasState *s, } static MegasasCmd *megasas_enqueue_frame(MegasasState *s, - target_phys_addr_t frame, uint64_t context, int count) + hwaddr frame, uint64_t context, int count) { MegasasCmd *cmd = NULL; int frame_size = MFI_FRAME_SIZE * 16; - target_phys_addr_t frame_size_p = frame_size; + hwaddr frame_size_p = frame_size; cmd = megasas_next_frame(s, frame); /* All frames busy */ @@ -561,7 +561,7 @@ static void megasas_abort_command(MegasasCmd *cmd) static int megasas_init_firmware(MegasasState *s, MegasasCmd *cmd) { uint32_t pa_hi, pa_lo; - target_phys_addr_t iq_pa, initq_size; + hwaddr iq_pa, initq_size; struct mfi_init_qinfo *initq; uint32_t flags; int ret = MFI_STAT_OK; @@ -1771,7 +1771,7 @@ static void megasas_command_cancel(SCSIRequest *req) static int megasas_handle_abort(MegasasState *s, MegasasCmd *cmd) { uint64_t abort_ctx = le64_to_cpu(cmd->frame->abort.abort_context); - target_phys_addr_t abort_addr, addr_hi, addr_lo; + hwaddr abort_addr, addr_hi, addr_lo; MegasasCmd *abort_cmd; addr_hi = le32_to_cpu(cmd->frame->abort.abort_mfi_addr_hi); @@ -1861,7 +1861,7 @@ static void megasas_handle_frame(MegasasState *s, uint64_t frame_addr, } } -static uint64_t megasas_mmio_read(void *opaque, target_phys_addr_t addr, +static uint64_t megasas_mmio_read(void *opaque, hwaddr addr, unsigned size) { MegasasState *s = opaque; @@ -1897,7 +1897,7 @@ static uint64_t megasas_mmio_read(void *opaque, target_phys_addr_t addr, return retval; } -static void megasas_mmio_write(void *opaque, target_phys_addr_t addr, +static void megasas_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { MegasasState *s = opaque; @@ -1977,13 +1977,13 @@ static const MemoryRegionOps megasas_mmio_ops = { } }; -static uint64_t megasas_port_read(void *opaque, target_phys_addr_t addr, +static uint64_t megasas_port_read(void *opaque, hwaddr addr, unsigned size) { return megasas_mmio_read(opaque, addr & 0xff, size); } -static void megasas_port_write(void *opaque, target_phys_addr_t addr, +static void megasas_port_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { megasas_mmio_write(opaque, addr & 0xff, val, size); @@ -1999,7 +1999,7 @@ static const MemoryRegionOps megasas_port_ops = { } }; -static uint64_t megasas_queue_read(void *opaque, target_phys_addr_t addr, +static uint64_t megasas_queue_read(void *opaque, hwaddr addr, unsigned size) { return 0; diff --git a/hw/microblaze_boot.c b/hw/microblaze_boot.c index 1030e9c8ed..02c349c189 100644 --- a/hw/microblaze_boot.c +++ b/hw/microblaze_boot.c @@ -55,7 +55,7 @@ static void main_cpu_reset(void *opaque) } } -static int microblaze_load_dtb(target_phys_addr_t addr, +static int microblaze_load_dtb(hwaddr addr, uint32_t ramsize, const char *kernel_cmdline, const char *dtb_filename) @@ -100,7 +100,7 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr) return addr - 0x30000000LL; } -void microblaze_load_kernel(MicroBlazeCPU *cpu, target_phys_addr_t ddr_base, +void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, uint32_t ramsize, const char *dtb_filename, void (*machine_cpu_reset)(MicroBlazeCPU *)) { @@ -149,7 +149,7 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, target_phys_addr_t ddr_base, /* If it wasn't an ELF image, try an u-boot image. */ if (kernel_size < 0) { - target_phys_addr_t uentry, loadaddr; + hwaddr uentry, loadaddr; kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0); boot_info.bootstrap_pc = uentry; diff --git a/hw/microblaze_boot.h b/hw/microblaze_boot.h index c9a3064d27..c1cf836b99 100644 --- a/hw/microblaze_boot.h +++ b/hw/microblaze_boot.h @@ -3,7 +3,7 @@ #include "hw.h" -void microblaze_load_kernel(MicroBlazeCPU *cpu, target_phys_addr_t ddr_base, +void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, uint32_t ramsize, const char *dtb_filename, void (*machine_cpu_reset)(MicroBlazeCPU *)); diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c index 4414f39734..d87656c9ac 100644 --- a/hw/milkymist-ac97.c +++ b/hw/milkymist-ac97.c @@ -83,7 +83,7 @@ static void update_voices(MilkymistAC97State *s) } } -static uint64_t ac97_read(void *opaque, target_phys_addr_t addr, +static uint64_t ac97_read(void *opaque, hwaddr addr, unsigned size) { MilkymistAC97State *s = opaque; @@ -115,7 +115,7 @@ static uint64_t ac97_read(void *opaque, target_phys_addr_t addr, return r; } -static void ac97_write(void *opaque, target_phys_addr_t addr, uint64_t value, +static void ac97_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { MilkymistAC97State *s = opaque; diff --git a/hw/milkymist-hpdmc.c b/hw/milkymist-hpdmc.c index 2da0293683..5d120a497f 100644 --- a/hw/milkymist-hpdmc.c +++ b/hw/milkymist-hpdmc.c @@ -48,7 +48,7 @@ struct MilkymistHpdmcState { }; typedef struct MilkymistHpdmcState MilkymistHpdmcState; -static uint64_t hpdmc_read(void *opaque, target_phys_addr_t addr, +static uint64_t hpdmc_read(void *opaque, hwaddr addr, unsigned size) { MilkymistHpdmcState *s = opaque; @@ -74,7 +74,7 @@ static uint64_t hpdmc_read(void *opaque, target_phys_addr_t addr, return r; } -static void hpdmc_write(void *opaque, target_phys_addr_t addr, uint64_t value, +static void hpdmc_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { MilkymistHpdmcState *s = opaque; diff --git a/hw/milkymist-hw.h b/hw/milkymist-hw.h index 9f358a7d69..96b2a7f863 100644 --- a/hw/milkymist-hw.h +++ b/hw/milkymist-hw.h @@ -4,7 +4,7 @@ #include "qdev.h" #include "qdev-addr.h" -static inline DeviceState *milkymist_uart_create(target_phys_addr_t base, +static inline DeviceState *milkymist_uart_create(hwaddr base, qemu_irq irq) { DeviceState *dev; @@ -17,7 +17,7 @@ static inline DeviceState *milkymist_uart_create(target_phys_addr_t base, return dev; } -static inline DeviceState *milkymist_hpdmc_create(target_phys_addr_t base) +static inline DeviceState *milkymist_hpdmc_create(hwaddr base) { DeviceState *dev; @@ -28,7 +28,7 @@ static inline DeviceState *milkymist_hpdmc_create(target_phys_addr_t base) return dev; } -static inline DeviceState *milkymist_memcard_create(target_phys_addr_t base) +static inline DeviceState *milkymist_memcard_create(hwaddr base) { DeviceState *dev; @@ -39,7 +39,7 @@ static inline DeviceState *milkymist_memcard_create(target_phys_addr_t base) return dev; } -static inline DeviceState *milkymist_vgafb_create(target_phys_addr_t base, +static inline DeviceState *milkymist_vgafb_create(hwaddr base, uint32_t fb_offset, uint32_t fb_mask) { DeviceState *dev; @@ -53,7 +53,7 @@ static inline DeviceState *milkymist_vgafb_create(target_phys_addr_t base, return dev; } -static inline DeviceState *milkymist_sysctl_create(target_phys_addr_t base, +static inline DeviceState *milkymist_sysctl_create(hwaddr base, qemu_irq gpio_irq, qemu_irq timer0_irq, qemu_irq timer1_irq, uint32_t freq_hz, uint32_t system_id, uint32_t capabilities, uint32_t gpio_strappings) @@ -74,7 +74,7 @@ static inline DeviceState *milkymist_sysctl_create(target_phys_addr_t base, return dev; } -static inline DeviceState *milkymist_pfpu_create(target_phys_addr_t base, +static inline DeviceState *milkymist_pfpu_create(hwaddr base, qemu_irq irq) { DeviceState *dev; @@ -97,7 +97,7 @@ static const int glx_fbconfig_attr[] = { }; #endif -static inline DeviceState *milkymist_tmu2_create(target_phys_addr_t base, +static inline DeviceState *milkymist_tmu2_create(hwaddr base, qemu_irq irq) { #ifdef CONFIG_OPENGL @@ -152,7 +152,7 @@ static inline DeviceState *milkymist_tmu2_create(target_phys_addr_t base, #endif } -static inline DeviceState *milkymist_ac97_create(target_phys_addr_t base, +static inline DeviceState *milkymist_ac97_create(hwaddr base, qemu_irq crrequest_irq, qemu_irq crreply_irq, qemu_irq dmar_irq, qemu_irq dmaw_irq) { @@ -169,7 +169,7 @@ static inline DeviceState *milkymist_ac97_create(target_phys_addr_t base, return dev; } -static inline DeviceState *milkymist_minimac_create(target_phys_addr_t base, +static inline DeviceState *milkymist_minimac_create(hwaddr base, qemu_irq rx_irq, qemu_irq tx_irq) { DeviceState *dev; @@ -185,8 +185,8 @@ static inline DeviceState *milkymist_minimac_create(target_phys_addr_t base, return dev; } -static inline DeviceState *milkymist_minimac2_create(target_phys_addr_t base, - target_phys_addr_t buffers_base, qemu_irq rx_irq, qemu_irq tx_irq) +static inline DeviceState *milkymist_minimac2_create(hwaddr base, + hwaddr buffers_base, qemu_irq rx_irq, qemu_irq tx_irq) { DeviceState *dev; @@ -202,7 +202,7 @@ static inline DeviceState *milkymist_minimac2_create(target_phys_addr_t base, return dev; } -static inline DeviceState *milkymist_softusb_create(target_phys_addr_t base, +static inline DeviceState *milkymist_softusb_create(hwaddr base, qemu_irq irq, uint32_t pmem_base, uint32_t pmem_size, uint32_t dmem_base, uint32_t dmem_size) { diff --git a/hw/milkymist-memcard.c b/hw/milkymist-memcard.c index 3515c3cd9a..ca5df56290 100644 --- a/hw/milkymist-memcard.c +++ b/hw/milkymist-memcard.c @@ -117,7 +117,7 @@ static void memcard_sd_command(MilkymistMemcardState *s) } } -static uint64_t memcard_read(void *opaque, target_phys_addr_t addr, +static uint64_t memcard_read(void *opaque, hwaddr addr, unsigned size) { MilkymistMemcardState *s = opaque; @@ -166,7 +166,7 @@ static uint64_t memcard_read(void *opaque, target_phys_addr_t addr, return r; } -static void memcard_write(void *opaque, target_phys_addr_t addr, uint64_t value, +static void memcard_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { MilkymistMemcardState *s = opaque; diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c index b483a02f21..b204e5f890 100644 --- a/hw/milkymist-minimac2.c +++ b/hw/milkymist-minimac2.c @@ -96,7 +96,7 @@ struct MilkymistMinimac2State { NICState *nic; NICConf conf; char *phy_model; - target_phys_addr_t buffers_base; + hwaddr buffers_base; MemoryRegion buffers; MemoryRegion regs_region; @@ -323,7 +323,7 @@ static ssize_t minimac2_rx(NetClientState *nc, const uint8_t *buf, size_t size) } static uint64_t -minimac2_read(void *opaque, target_phys_addr_t addr, unsigned size) +minimac2_read(void *opaque, hwaddr addr, unsigned size) { MilkymistMinimac2State *s = opaque; uint32_t r = 0; @@ -352,7 +352,7 @@ minimac2_read(void *opaque, target_phys_addr_t addr, unsigned size) } static void -minimac2_write(void *opaque, target_phys_addr_t addr, uint64_t value, +minimac2_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { MilkymistMinimac2State *s = opaque; diff --git a/hw/milkymist-pfpu.c b/hw/milkymist-pfpu.c index 0f9ff4a13d..450bab921f 100644 --- a/hw/milkymist-pfpu.c +++ b/hw/milkymist-pfpu.c @@ -131,7 +131,7 @@ struct MilkymistPFPUState { }; typedef struct MilkymistPFPUState MilkymistPFPUState; -static inline target_phys_addr_t +static inline hwaddr get_dma_address(uint32_t base, uint32_t x, uint32_t y) { return base + 8 * (128 * y + x); @@ -225,7 +225,7 @@ static int pfpu_decode_insn(MilkymistPFPUState *s) { uint32_t a = cpu_to_be32(s->gp_regs[reg_a]); uint32_t b = cpu_to_be32(s->gp_regs[reg_b]); - target_phys_addr_t dma_ptr = + hwaddr dma_ptr = get_dma_address(s->regs[R_MESHBASE], s->gp_regs[GPR_X], s->gp_regs[GPR_Y]); cpu_physical_memory_write(dma_ptr, (uint8_t *)&a, 4); @@ -380,7 +380,7 @@ static inline int get_microcode_address(MilkymistPFPUState *s, uint32_t addr) return (512 * s->regs[R_CODEPAGE]) + addr - MICROCODE_BEGIN; } -static uint64_t pfpu_read(void *opaque, target_phys_addr_t addr, +static uint64_t pfpu_read(void *opaque, hwaddr addr, unsigned size) { MilkymistPFPUState *s = opaque; @@ -420,7 +420,7 @@ static uint64_t pfpu_read(void *opaque, target_phys_addr_t addr, return r; } -static void pfpu_write(void *opaque, target_phys_addr_t addr, uint64_t value, +static void pfpu_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { MilkymistPFPUState *s = opaque; diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c index ecc2be9225..b162b88db7 100644 --- a/hw/milkymist-softusb.c +++ b/hw/milkymist-softusb.c @@ -71,7 +71,7 @@ struct MilkymistSoftUsbState { }; typedef struct MilkymistSoftUsbState MilkymistSoftUsbState; -static uint64_t softusb_read(void *opaque, target_phys_addr_t addr, +static uint64_t softusb_read(void *opaque, hwaddr addr, unsigned size) { MilkymistSoftUsbState *s = opaque; @@ -95,7 +95,7 @@ static uint64_t softusb_read(void *opaque, target_phys_addr_t addr, } static void -softusb_write(void *opaque, target_phys_addr_t addr, uint64_t value, +softusb_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { MilkymistSoftUsbState *s = opaque; diff --git a/hw/milkymist-sysctl.c b/hw/milkymist-sysctl.c index 8878d2bd17..f951ef9ca8 100644 --- a/hw/milkymist-sysctl.c +++ b/hw/milkymist-sysctl.c @@ -89,7 +89,7 @@ static void sysctl_icap_write(MilkymistSysctlState *s, uint32_t value) } } -static uint64_t sysctl_read(void *opaque, target_phys_addr_t addr, +static uint64_t sysctl_read(void *opaque, hwaddr addr, unsigned size) { MilkymistSysctlState *s = opaque; @@ -134,7 +134,7 @@ static uint64_t sysctl_read(void *opaque, target_phys_addr_t addr, return r; } -static void sysctl_write(void *opaque, target_phys_addr_t addr, uint64_t value, +static void sysctl_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { MilkymistSysctlState *s = opaque; diff --git a/hw/milkymist-tmu2.c b/hw/milkymist-tmu2.c index 210ceede2a..3f9a684eda 100644 --- a/hw/milkymist-tmu2.c +++ b/hw/milkymist-tmu2.c @@ -182,9 +182,9 @@ static void tmu2_start(MilkymistTMU2State *s) GLXPbuffer pbuffer; GLuint texture; void *fb; - target_phys_addr_t fb_len; + hwaddr fb_len; void *mesh; - target_phys_addr_t mesh_len; + hwaddr mesh_len; float m; trace_milkymist_tmu2_start(); @@ -310,7 +310,7 @@ static void tmu2_start(MilkymistTMU2State *s) qemu_irq_pulse(s->irq); } -static uint64_t tmu2_read(void *opaque, target_phys_addr_t addr, +static uint64_t tmu2_read(void *opaque, hwaddr addr, unsigned size) { MilkymistTMU2State *s = opaque; @@ -372,7 +372,7 @@ static void tmu2_check_registers(MilkymistTMU2State *s) } } -static void tmu2_write(void *opaque, target_phys_addr_t addr, uint64_t value, +static void tmu2_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { MilkymistTMU2State *s = opaque; diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c index 291fe3c57b..aefa8c7f1c 100644 --- a/hw/milkymist-uart.c +++ b/hw/milkymist-uart.c @@ -78,7 +78,7 @@ static void uart_update_irq(MilkymistUartState *s) } } -static uint64_t uart_read(void *opaque, target_phys_addr_t addr, +static uint64_t uart_read(void *opaque, hwaddr addr, unsigned size) { MilkymistUartState *s = opaque; @@ -107,7 +107,7 @@ static uint64_t uart_read(void *opaque, target_phys_addr_t addr, return r; } -static void uart_write(void *opaque, target_phys_addr_t addr, uint64_t value, +static void uart_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { MilkymistUartState *s = opaque; diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c index cd4365d64b..8d36bc10f6 100644 --- a/hw/milkymist-vgafb.c +++ b/hw/milkymist-vgafb.c @@ -155,7 +155,7 @@ static void vgafb_resize(MilkymistVgafbState *s) s->invalidate = 1; } -static uint64_t vgafb_read(void *opaque, target_phys_addr_t addr, +static uint64_t vgafb_read(void *opaque, hwaddr addr, unsigned size) { MilkymistVgafbState *s = opaque; @@ -193,7 +193,7 @@ static uint64_t vgafb_read(void *opaque, target_phys_addr_t addr, return r; } -static void vgafb_write(void *opaque, target_phys_addr_t addr, uint64_t value, +static void vgafb_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { MilkymistVgafbState *s = opaque; diff --git a/hw/milkymist.c b/hw/milkymist.c index ca9ed43d99..4c8111a74d 100644 --- a/hw/milkymist.c +++ b/hw/milkymist.c @@ -38,11 +38,11 @@ typedef struct { LM32CPU *cpu; - target_phys_addr_t bootstrap_pc; - target_phys_addr_t flash_base; - target_phys_addr_t initrd_base; + hwaddr bootstrap_pc; + hwaddr flash_base; + hwaddr initrd_base; size_t initrd_size; - target_phys_addr_t cmdline_base; + hwaddr cmdline_base; } ResetInfo; static void cpu_irq_handler(void *opaque, int irq, int level) @@ -91,14 +91,14 @@ milkymist_init(QEMUMachineInitArgs *args) ResetInfo *reset_info; /* memory map */ - target_phys_addr_t flash_base = 0x00000000; + hwaddr flash_base = 0x00000000; size_t flash_sector_size = 128 * 1024; size_t flash_size = 32 * 1024 * 1024; - target_phys_addr_t sdram_base = 0x40000000; + hwaddr sdram_base = 0x40000000; size_t sdram_size = 128 * 1024 * 1024; - target_phys_addr_t initrd_base = sdram_base + 0x1002000; - target_phys_addr_t cmdline_base = sdram_base + 0x1000000; + hwaddr initrd_base = sdram_base + 0x1002000; + hwaddr cmdline_base = sdram_base + 0x1000000; size_t initrd_max = sdram_size - 0x1002000; reset_info = g_malloc0(sizeof(ResetInfo)); diff --git a/hw/mips.h b/hw/mips.h index a7e6d4cc62..f7e9b7e2c1 100644 --- a/hw/mips.h +++ b/hw/mips.h @@ -12,7 +12,7 @@ PCIBus *bonito_init(qemu_irq *pic); /* rc4030.c */ typedef struct rc4030DMAState *rc4030_dma; -void rc4030_dma_memory_rw(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write); +void rc4030_dma_memory_rw(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write); void rc4030_dma_read(void *dma, uint8_t *buf, int len); void rc4030_dma_write(void *dma, uint8_t *buf, int len); @@ -21,9 +21,9 @@ void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus, MemoryRegion *sysmem); /* dp8393x.c */ -void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift, +void dp83932_init(NICInfo *nd, hwaddr base, int it_shift, MemoryRegion *address_space, qemu_irq irq, void* mem_opaque, - void (*memory_rw)(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write)); + void (*memory_rw)(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write)); #endif diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c index 6bd231dc9b..0847427241 100644 --- a/hw/mips_jazz.c +++ b/hw/mips_jazz.c @@ -56,12 +56,12 @@ static void main_cpu_reset(void *opaque) cpu_reset(CPU(cpu)); } -static uint64_t rtc_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t rtc_read(void *opaque, hwaddr addr, unsigned size) { return cpu_inw(0x71); } -static void rtc_write(void *opaque, target_phys_addr_t addr, +static void rtc_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { cpu_outw(0x71, val & 0xff); @@ -73,7 +73,7 @@ static const MemoryRegionOps rtc_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint64_t dma_dummy_read(void *opaque, target_phys_addr_t addr, +static uint64_t dma_dummy_read(void *opaque, hwaddr addr, unsigned size) { /* Nothing to do. That is only to ensure that @@ -81,7 +81,7 @@ static uint64_t dma_dummy_read(void *opaque, target_phys_addr_t addr, return 0xff; } -static void dma_dummy_write(void *opaque, target_phys_addr_t addr, +static void dma_dummy_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { /* Nothing to do. That is only to ensure that diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 22ec8b9efa..0571d58908 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -231,7 +231,7 @@ static void eeprom24c0x_write(int scl, int sda) eeprom.sda = sda; } -static uint64_t malta_fpga_read(void *opaque, target_phys_addr_t addr, +static uint64_t malta_fpga_read(void *opaque, hwaddr addr, unsigned size) { MaltaFPGAState *s = opaque; @@ -319,7 +319,7 @@ static uint64_t malta_fpga_read(void *opaque, target_phys_addr_t addr, return val; } -static void malta_fpga_write(void *opaque, target_phys_addr_t addr, +static void malta_fpga_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { MaltaFPGAState *s = opaque; @@ -441,7 +441,7 @@ static void malta_fpga_led_init(CharDriverState *chr) } static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space, - target_phys_addr_t base, qemu_irq uart_irq, CharDriverState *uart_chr) + hwaddr base, qemu_irq uart_irq, CharDriverState *uart_chr) { MaltaFPGAState *s; diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index 539577b761..325098a43a 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -44,7 +44,7 @@ static struct _loaderparams { const char *initrd_filename; } loaderparams; -static void mips_qemu_write (void *opaque, target_phys_addr_t addr, +static void mips_qemu_write (void *opaque, hwaddr addr, uint64_t val, unsigned size) { if ((addr & 0xffff) == 0 && val == 42) @@ -53,7 +53,7 @@ static void mips_qemu_write (void *opaque, target_phys_addr_t addr, qemu_system_shutdown_request (); } -static uint64_t mips_qemu_read (void *opaque, target_phys_addr_t addr, +static uint64_t mips_qemu_read (void *opaque, hwaddr addr, unsigned size) { return 0; diff --git a/hw/mipsnet.c b/hw/mipsnet.c index 28063b1106..bece332c4e 100644 --- a/hw/mipsnet.c +++ b/hw/mipsnet.c @@ -96,7 +96,7 @@ static ssize_t mipsnet_receive(NetClientState *nc, const uint8_t *buf, size_t si return size; } -static uint64_t mipsnet_ioport_read(void *opaque, target_phys_addr_t addr, +static uint64_t mipsnet_ioport_read(void *opaque, hwaddr addr, unsigned int size) { MIPSnetState *s = opaque; @@ -142,7 +142,7 @@ static uint64_t mipsnet_ioport_read(void *opaque, target_phys_addr_t addr, return ret; } -static void mipsnet_ioport_write(void *opaque, target_phys_addr_t addr, +static void mipsnet_ioport_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { MIPSnetState *s = opaque; diff --git a/hw/mpc8544_guts.c b/hw/mpc8544_guts.c index 13b0dddc1e..873cb8cbfc 100644 --- a/hw/mpc8544_guts.c +++ b/hw/mpc8544_guts.c @@ -58,7 +58,7 @@ struct GutsState { typedef struct GutsState GutsState; -static uint64_t mpc8544_guts_read(void *opaque, target_phys_addr_t addr, +static uint64_t mpc8544_guts_read(void *opaque, hwaddr addr, unsigned size) { uint32_t value = 0; @@ -80,7 +80,7 @@ static uint64_t mpc8544_guts_read(void *opaque, target_phys_addr_t addr, return value; } -static void mpc8544_guts_write(void *opaque, target_phys_addr_t addr, +static void mpc8544_guts_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { addr &= MPC8544_GUTS_MMIO_SIZE - 1; diff --git a/hw/msix.c b/hw/msix.c index b623cb597c..136ef09373 100644 --- a/hw/msix.c +++ b/hw/msix.c @@ -157,7 +157,7 @@ void msix_write_config(PCIDevice *dev, uint32_t addr, } } -static uint64_t msix_table_mmio_read(void *opaque, target_phys_addr_t addr, +static uint64_t msix_table_mmio_read(void *opaque, hwaddr addr, unsigned size) { PCIDevice *dev = opaque; @@ -165,7 +165,7 @@ static uint64_t msix_table_mmio_read(void *opaque, target_phys_addr_t addr, return pci_get_long(dev->msix_table + addr); } -static void msix_table_mmio_write(void *opaque, target_phys_addr_t addr, +static void msix_table_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { PCIDevice *dev = opaque; @@ -188,7 +188,7 @@ static const MemoryRegionOps msix_table_mmio_ops = { }, }; -static uint64_t msix_pba_mmio_read(void *opaque, target_phys_addr_t addr, +static uint64_t msix_pba_mmio_read(void *opaque, hwaddr addr, unsigned size) { PCIDevice *dev = opaque; diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c index 024192d135..fb4b739c7c 100644 --- a/hw/mst_fpga.c +++ b/hw/mst_fpga.c @@ -91,7 +91,7 @@ mst_fpga_set_irq(void *opaque, int irq, int level) static uint64_t -mst_fpga_readb(void *opaque, target_phys_addr_t addr, unsigned size) +mst_fpga_readb(void *opaque, hwaddr addr, unsigned size) { mst_irq_state *s = (mst_irq_state *) opaque; @@ -128,7 +128,7 @@ mst_fpga_readb(void *opaque, target_phys_addr_t addr, unsigned size) } static void -mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint64_t value, +mst_fpga_writeb(void *opaque, hwaddr addr, uint64_t value, unsigned size) { mst_irq_state *s = (mst_irq_state *) opaque; diff --git a/hw/multiboot.c b/hw/multiboot.c index b1e04c5718..09ec5b2539 100644 --- a/hw/multiboot.c +++ b/hw/multiboot.c @@ -80,15 +80,15 @@ typedef struct { /* buffer holding kernel, cmdlines and mb_infos */ void *mb_buf; /* address in target */ - target_phys_addr_t mb_buf_phys; + hwaddr mb_buf_phys; /* size of mb_buf in bytes */ unsigned mb_buf_size; /* offset of mb-info's in bytes */ - target_phys_addr_t offset_mbinfo; + hwaddr offset_mbinfo; /* offset in buffer for cmdlines in bytes */ - target_phys_addr_t offset_cmdlines; + hwaddr offset_cmdlines; /* offset of modules in bytes */ - target_phys_addr_t offset_mods; + hwaddr offset_mods; /* available slots for mb modules infos */ int mb_mods_avail; /* currently used slots of mb modules */ @@ -97,7 +97,7 @@ typedef struct { static uint32_t mb_add_cmdline(MultibootState *s, const char *cmdline) { - target_phys_addr_t p = s->offset_cmdlines; + hwaddr p = s->offset_cmdlines; char *b = (char *)s->mb_buf + p; get_opt_value(b, strlen(cmdline) + 1, cmdline); @@ -106,8 +106,8 @@ static uint32_t mb_add_cmdline(MultibootState *s, const char *cmdline) } static void mb_add_mod(MultibootState *s, - target_phys_addr_t start, target_phys_addr_t end, - target_phys_addr_t cmdline_phys) + hwaddr start, hwaddr end, + hwaddr cmdline_phys) { char *p; assert(s->mb_mods_count < s->mb_mods_avail); @@ -276,7 +276,7 @@ int load_multiboot(void *fw_cfg, *next_initrd = '\0'; /* if a space comes after the module filename, treat everything after that as parameters */ - target_phys_addr_t c = mb_add_cmdline(&mbs, initrd_filename); + hwaddr c = mb_add_cmdline(&mbs, initrd_filename); if ((next_space = strchr(initrd_filename, ' '))) *next_space = '\0'; mb_debug("multiboot loading module: %s\n", initrd_filename); diff --git a/hw/musicpal.c b/hw/musicpal.c index 159d3c3c39..beec76bf38 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -266,7 +266,7 @@ static void eth_send(mv88w8618_eth_state *s, int queue_index) } while (desc_addr != s->tx_queue[queue_index]); } -static uint64_t mv88w8618_eth_read(void *opaque, target_phys_addr_t offset, +static uint64_t mv88w8618_eth_read(void *opaque, hwaddr offset, unsigned size) { mv88w8618_eth_state *s = opaque; @@ -308,7 +308,7 @@ static uint64_t mv88w8618_eth_read(void *opaque, target_phys_addr_t offset, } } -static void mv88w8618_eth_write(void *opaque, target_phys_addr_t offset, +static void mv88w8618_eth_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { mv88w8618_eth_state *s = opaque; @@ -540,7 +540,7 @@ static void musicpal_lcd_gpio_brigthness_in(void *opaque, int irq, int level) s->brightness |= level << irq; } -static uint64_t musicpal_lcd_read(void *opaque, target_phys_addr_t offset, +static uint64_t musicpal_lcd_read(void *opaque, hwaddr offset, unsigned size) { musicpal_lcd_state *s = opaque; @@ -554,7 +554,7 @@ static uint64_t musicpal_lcd_read(void *opaque, target_phys_addr_t offset, } } -static void musicpal_lcd_write(void *opaque, target_phys_addr_t offset, +static void musicpal_lcd_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { musicpal_lcd_state *s = opaque; @@ -682,7 +682,7 @@ static void mv88w8618_pic_set_irq(void *opaque, int irq, int level) mv88w8618_pic_update(s); } -static uint64_t mv88w8618_pic_read(void *opaque, target_phys_addr_t offset, +static uint64_t mv88w8618_pic_read(void *opaque, hwaddr offset, unsigned size) { mv88w8618_pic_state *s = opaque; @@ -696,7 +696,7 @@ static uint64_t mv88w8618_pic_read(void *opaque, target_phys_addr_t offset, } } -static void mv88w8618_pic_write(void *opaque, target_phys_addr_t offset, +static void mv88w8618_pic_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { mv88w8618_pic_state *s = opaque; @@ -815,7 +815,7 @@ static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s, s->ptimer = ptimer_init(bh); } -static uint64_t mv88w8618_pit_read(void *opaque, target_phys_addr_t offset, +static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset, unsigned size) { mv88w8618_pit_state *s = opaque; @@ -831,7 +831,7 @@ static uint64_t mv88w8618_pit_read(void *opaque, target_phys_addr_t offset, } } -static void mv88w8618_pit_write(void *opaque, target_phys_addr_t offset, +static void mv88w8618_pit_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { mv88w8618_pit_state *s = opaque; @@ -957,7 +957,7 @@ typedef struct mv88w8618_flashcfg_state { } mv88w8618_flashcfg_state; static uint64_t mv88w8618_flashcfg_read(void *opaque, - target_phys_addr_t offset, + hwaddr offset, unsigned size) { mv88w8618_flashcfg_state *s = opaque; @@ -971,7 +971,7 @@ static uint64_t mv88w8618_flashcfg_read(void *opaque, } } -static void mv88w8618_flashcfg_write(void *opaque, target_phys_addr_t offset, +static void mv88w8618_flashcfg_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { mv88w8618_flashcfg_state *s = opaque; @@ -1032,7 +1032,7 @@ static TypeInfo mv88w8618_flashcfg_info = { #define MP_BOARD_REVISION 0x31 -static uint64_t musicpal_misc_read(void *opaque, target_phys_addr_t offset, +static uint64_t musicpal_misc_read(void *opaque, hwaddr offset, unsigned size) { switch (offset) { @@ -1044,7 +1044,7 @@ static uint64_t musicpal_misc_read(void *opaque, target_phys_addr_t offset, } } -static void musicpal_misc_write(void *opaque, target_phys_addr_t offset, +static void musicpal_misc_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { } @@ -1068,7 +1068,7 @@ static void musicpal_misc_init(SysBusDevice *dev) #define MP_WLAN_MAGIC1 0x11c #define MP_WLAN_MAGIC2 0x124 -static uint64_t mv88w8618_wlan_read(void *opaque, target_phys_addr_t offset, +static uint64_t mv88w8618_wlan_read(void *opaque, hwaddr offset, unsigned size) { switch (offset) { @@ -1084,7 +1084,7 @@ static uint64_t mv88w8618_wlan_read(void *opaque, target_phys_addr_t offset, } } -static void mv88w8618_wlan_write(void *opaque, target_phys_addr_t offset, +static void mv88w8618_wlan_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { } @@ -1202,7 +1202,7 @@ static void musicpal_gpio_pin_event(void *opaque, int pin, int level) } } -static uint64_t musicpal_gpio_read(void *opaque, target_phys_addr_t offset, +static uint64_t musicpal_gpio_read(void *opaque, hwaddr offset, unsigned size) { musicpal_gpio_state *s = opaque; @@ -1241,7 +1241,7 @@ static uint64_t musicpal_gpio_read(void *opaque, target_phys_addr_t offset, } } -static void musicpal_gpio_write(void *opaque, target_phys_addr_t offset, +static void musicpal_gpio_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { musicpal_gpio_state *s = opaque; diff --git a/hw/ne2000.c b/hw/ne2000.c index 15605c478f..d3dd9a6f26 100644 --- a/hw/ne2000.c +++ b/hw/ne2000.c @@ -652,7 +652,7 @@ static const VMStateDescription vmstate_pci_ne2000 = { } }; -static uint64_t ne2000_read(void *opaque, target_phys_addr_t addr, +static uint64_t ne2000_read(void *opaque, hwaddr addr, unsigned size) { NE2000State *s = opaque; @@ -671,7 +671,7 @@ static uint64_t ne2000_read(void *opaque, target_phys_addr_t addr, return ((uint64_t)1 << (size * 8)) - 1; } -static void ne2000_write(void *opaque, target_phys_addr_t addr, +static void ne2000_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { NE2000State *s = opaque; diff --git a/hw/nvram.h b/hw/nvram.h index 8924da47d8..a4a1db4976 100644 --- a/hw/nvram.h +++ b/hw/nvram.h @@ -36,7 +36,7 @@ uint32_t m48t59_read (void *private, uint32_t addr); void m48t59_toggle_lock (void *private, int lock); M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size, int type); -M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base, +M48t59State *m48t59_init(qemu_irq IRQ, hwaddr mem_base, uint32_t io_base, uint16_t size, int type); void m48t59_set_addr (void *opaque, uint32_t addr); diff --git a/hw/omap.h b/hw/omap.h index 413851bc34..8bd7c73cf6 100644 --- a/hw/omap.h +++ b/hw/omap.h @@ -65,7 +65,7 @@ void omap_clk_reparent(omap_clk clk, omap_clk parent); /* OMAP2 l4 Interconnect */ struct omap_l4_s; struct omap_l4_region_s { - target_phys_addr_t offset; + hwaddr offset; size_t size; int access; }; @@ -80,13 +80,13 @@ struct omap_target_agent_s { struct omap_l4_s *bus; int regions; const struct omap_l4_region_s *start; - target_phys_addr_t base; + hwaddr base; uint32_t component; uint32_t control; uint32_t status; }; struct omap_l4_s *omap_l4_init(MemoryRegion *address_space, - target_phys_addr_t base, int ta_num); + hwaddr base, int ta_num); struct omap_target_agent_s; struct omap_target_agent_s *omap_l4ta_get( @@ -94,23 +94,23 @@ struct omap_target_agent_s *omap_l4ta_get( const struct omap_l4_region_s *regions, const struct omap_l4_agent_info_s *agents, int cs); -target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, +hwaddr omap_l4_attach(struct omap_target_agent_s *ta, int region, MemoryRegion *mr); -target_phys_addr_t omap_l4_region_base(struct omap_target_agent_s *ta, +hwaddr omap_l4_region_base(struct omap_target_agent_s *ta, int region); -target_phys_addr_t omap_l4_region_size(struct omap_target_agent_s *ta, +hwaddr omap_l4_region_size(struct omap_target_agent_s *ta, int region); /* OMAP2 SDRAM controller */ struct omap_sdrc_s; struct omap_sdrc_s *omap_sdrc_init(MemoryRegion *sysmem, - target_phys_addr_t base); + hwaddr base); void omap_sdrc_reset(struct omap_sdrc_s *s); /* OMAP2 general purpose memory controller */ struct omap_gpmc_s; struct omap_gpmc_s *omap_gpmc_init(struct omap_mpu_state_s *mpu, - target_phys_addr_t base, + hwaddr base, qemu_irq irq, qemu_irq drq); void omap_gpmc_reset(struct omap_gpmc_s *s); void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, MemoryRegion *iomem); @@ -433,11 +433,11 @@ enum omap_dma_model { }; struct soc_dma_s; -struct soc_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs, +struct soc_dma_s *omap_dma_init(hwaddr base, qemu_irq *irqs, MemoryRegion *sysmem, qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk, enum omap_dma_model model); -struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs, +struct soc_dma_s *omap_dma4_init(hwaddr base, qemu_irq *irqs, MemoryRegion *sysmem, struct omap_mpu_state_s *mpu, int fifo, int chans, omap_clk iclk, omap_clk fclk); @@ -469,10 +469,10 @@ typedef enum { /* Only used in OMAP DMA 3.x gigacells */ struct omap_dma_lcd_channel_s { enum omap_dma_port src; - target_phys_addr_t src_f1_top; - target_phys_addr_t src_f1_bottom; - target_phys_addr_t src_f2_top; - target_phys_addr_t src_f2_bottom; + hwaddr src_f1_top; + hwaddr src_f1_bottom; + hwaddr src_f2_top; + hwaddr src_f2_bottom; /* Used in OMAP DMA 3.2 gigacell */ unsigned char brust_f1; @@ -508,7 +508,7 @@ struct omap_dma_lcd_channel_s { int dual; int current_frame; - target_phys_addr_t phys_framebuffer[2]; + hwaddr phys_framebuffer[2]; qemu_irq irq; struct omap_mpu_state_s *mpu; } *omap_dma_get_lcdch(struct soc_dma_s *s); @@ -659,7 +659,7 @@ struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta, void omap_synctimer_reset(struct omap_synctimer_s *s); struct omap_uart_s; -struct omap_uart_s *omap_uart_init(target_phys_addr_t base, +struct omap_uart_s *omap_uart_init(hwaddr base, qemu_irq irq, omap_clk fclk, omap_clk iclk, qemu_irq txdma, qemu_irq rxdma, const char *label, CharDriverState *chr); @@ -728,7 +728,7 @@ void omap_tap_init(struct omap_target_agent_s *ta, struct omap_lcd_panel_s; void omap_lcdc_reset(struct omap_lcd_panel_s *s); struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem, - target_phys_addr_t base, + hwaddr base, qemu_irq irq, struct omap_dma_lcd_channel_s *dma, omap_clk clk); @@ -744,7 +744,7 @@ struct omap_dss_s; void omap_dss_reset(struct omap_dss_s *s); struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta, MemoryRegion *sysmem, - target_phys_addr_t l3_base, + hwaddr l3_base, qemu_irq irq, qemu_irq drq, omap_clk fck1, omap_clk fck2, omap_clk ck54m, omap_clk ick1, omap_clk ick2); @@ -752,7 +752,7 @@ void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip); /* omap_mmc.c */ struct omap_mmc_s; -struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base, +struct omap_mmc_s *omap_mmc_init(hwaddr base, MemoryRegion *sysmem, BlockDriverState *bd, qemu_irq irq, qemu_irq dma[], omap_clk clk); @@ -829,11 +829,11 @@ struct omap_mpu_state_s { struct omap_dma_port_if_s { uint32_t (*read[3])(struct omap_mpu_state_s *s, - target_phys_addr_t offset); + hwaddr offset); void (*write[3])(struct omap_mpu_state_s *s, - target_phys_addr_t offset, uint32_t value); + hwaddr offset, uint32_t value); int (*addr_valid)(struct omap_mpu_state_s *s, - target_phys_addr_t addr); + hwaddr addr); } port[__omap_dma_port_last]; unsigned long sdram_size; @@ -942,16 +942,16 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem, unsigned long sdram_size, const char *core); -#define OMAP_FMT_plx "%#08" TARGET_PRIxPHYS +#define OMAP_FMT_plx "%#08" HWADDR_PRIx -uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr); -void omap_badwidth_write8(void *opaque, target_phys_addr_t addr, +uint32_t omap_badwidth_read8(void *opaque, hwaddr addr); +void omap_badwidth_write8(void *opaque, hwaddr addr, uint32_t value); -uint32_t omap_badwidth_read16(void *opaque, target_phys_addr_t addr); -void omap_badwidth_write16(void *opaque, target_phys_addr_t addr, +uint32_t omap_badwidth_read16(void *opaque, hwaddr addr); +void omap_badwidth_write16(void *opaque, hwaddr addr, uint32_t value); -uint32_t omap_badwidth_read32(void *opaque, target_phys_addr_t addr); -void omap_badwidth_write32(void *opaque, target_phys_addr_t addr, +uint32_t omap_badwidth_read32(void *opaque, hwaddr addr); +void omap_badwidth_write32(void *opaque, hwaddr addr, uint32_t value); void omap_mpu_wakeup(void *opaque, int irq, int req); diff --git a/hw/omap1.c b/hw/omap1.c index ad60cc4919..4d5815eb08 100644 --- a/hw/omap1.c +++ b/hw/omap1.c @@ -26,7 +26,7 @@ #include "sysbus.h" /* Should signal the TCMI/GPMC */ -uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr) +uint32_t omap_badwidth_read8(void *opaque, hwaddr addr) { uint8_t ret; @@ -35,7 +35,7 @@ uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr) return ret; } -void omap_badwidth_write8(void *opaque, target_phys_addr_t addr, +void omap_badwidth_write8(void *opaque, hwaddr addr, uint32_t value) { uint8_t val8 = value; @@ -44,7 +44,7 @@ void omap_badwidth_write8(void *opaque, target_phys_addr_t addr, cpu_physical_memory_write(addr, (void *) &val8, 1); } -uint32_t omap_badwidth_read16(void *opaque, target_phys_addr_t addr) +uint32_t omap_badwidth_read16(void *opaque, hwaddr addr) { uint16_t ret; @@ -53,7 +53,7 @@ uint32_t omap_badwidth_read16(void *opaque, target_phys_addr_t addr) return ret; } -void omap_badwidth_write16(void *opaque, target_phys_addr_t addr, +void omap_badwidth_write16(void *opaque, hwaddr addr, uint32_t value) { uint16_t val16 = value; @@ -62,7 +62,7 @@ void omap_badwidth_write16(void *opaque, target_phys_addr_t addr, cpu_physical_memory_write(addr, (void *) &val16, 2); } -uint32_t omap_badwidth_read32(void *opaque, target_phys_addr_t addr) +uint32_t omap_badwidth_read32(void *opaque, hwaddr addr) { uint32_t ret; @@ -71,7 +71,7 @@ uint32_t omap_badwidth_read32(void *opaque, target_phys_addr_t addr) return ret; } -void omap_badwidth_write32(void *opaque, target_phys_addr_t addr, +void omap_badwidth_write32(void *opaque, hwaddr addr, uint32_t value) { OMAP_32B_REG(addr); @@ -176,7 +176,7 @@ static void omap_timer_clk_setup(struct omap_mpu_timer_s *timer) timer->rate = omap_clk_getrate(timer->clk); } -static uint64_t omap_mpu_timer_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_mpu_timer_read(void *opaque, hwaddr addr, unsigned size) { struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque; @@ -200,7 +200,7 @@ static uint64_t omap_mpu_timer_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_mpu_timer_write(void *opaque, target_phys_addr_t addr, +static void omap_mpu_timer_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque; @@ -251,7 +251,7 @@ static void omap_mpu_timer_reset(struct omap_mpu_timer_s *s) } static struct omap_mpu_timer_s *omap_mpu_timer_init(MemoryRegion *system_memory, - target_phys_addr_t base, + hwaddr base, qemu_irq irq, omap_clk clk) { struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) @@ -282,7 +282,7 @@ struct omap_watchdog_timer_s { int reset; }; -static uint64_t omap_wd_timer_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_wd_timer_read(void *opaque, hwaddr addr, unsigned size) { struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque; @@ -307,7 +307,7 @@ static uint64_t omap_wd_timer_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_wd_timer_write(void *opaque, target_phys_addr_t addr, +static void omap_wd_timer_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque; @@ -380,7 +380,7 @@ static void omap_wd_timer_reset(struct omap_watchdog_timer_s *s) } static struct omap_watchdog_timer_s *omap_wd_timer_init(MemoryRegion *memory, - target_phys_addr_t base, + hwaddr base, qemu_irq irq, omap_clk clk) { struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) @@ -405,7 +405,7 @@ struct omap_32khz_timer_s { MemoryRegion iomem; }; -static uint64_t omap_os_timer_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_os_timer_read(void *opaque, hwaddr addr, unsigned size) { struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque; @@ -432,7 +432,7 @@ static uint64_t omap_os_timer_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_os_timer_write(void *opaque, target_phys_addr_t addr, +static void omap_os_timer_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque; @@ -486,7 +486,7 @@ static void omap_os_timer_reset(struct omap_32khz_timer_s *s) } static struct omap_32khz_timer_s *omap_os_timer_init(MemoryRegion *memory, - target_phys_addr_t base, + hwaddr base, qemu_irq irq, omap_clk clk) { struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) @@ -506,7 +506,7 @@ static struct omap_32khz_timer_s *omap_os_timer_init(MemoryRegion *memory, } /* Ultra Low-Power Device Module */ -static uint64_t omap_ulpd_pm_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_ulpd_pm_read(void *opaque, hwaddr addr, unsigned size) { struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; @@ -573,7 +573,7 @@ static inline void omap_ulpd_req_update(struct omap_mpu_state_s *s, omap_clk_canidle(omap_findclk(s, "usb_clk0"), (~value >> 3) & 1); } -static void omap_ulpd_pm_write(void *opaque, target_phys_addr_t addr, +static void omap_ulpd_pm_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; @@ -726,7 +726,7 @@ static void omap_ulpd_pm_reset(struct omap_mpu_state_s *mpu) } static void omap_ulpd_pm_init(MemoryRegion *system_memory, - target_phys_addr_t base, + hwaddr base, struct omap_mpu_state_s *mpu) { memory_region_init_io(&mpu->ulpd_pm_iomem, &omap_ulpd_pm_ops, mpu, @@ -736,7 +736,7 @@ static void omap_ulpd_pm_init(MemoryRegion *system_memory, } /* OMAP Pin Configuration */ -static uint64_t omap_pin_cfg_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_pin_cfg_read(void *opaque, hwaddr addr, unsigned size) { struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; @@ -843,7 +843,7 @@ static inline void omap_pin_modconf1_update(struct omap_mpu_state_s *s, omap_clk_onoff(omap_findclk(s, "usb_hhc_ck"), (value >> 9) & 1); } -static void omap_pin_cfg_write(void *opaque, target_phys_addr_t addr, +static void omap_pin_cfg_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; @@ -944,7 +944,7 @@ static void omap_pin_cfg_reset(struct omap_mpu_state_s *mpu) } static void omap_pin_cfg_init(MemoryRegion *system_memory, - target_phys_addr_t base, + hwaddr base, struct omap_mpu_state_s *mpu) { memory_region_init_io(&mpu->pin_cfg_iomem, &omap_pin_cfg_ops, mpu, @@ -954,7 +954,7 @@ static void omap_pin_cfg_init(MemoryRegion *system_memory, } /* Device Identification, Die Identification */ -static uint64_t omap_id_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_id_read(void *opaque, hwaddr addr, unsigned size) { struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; @@ -1001,7 +1001,7 @@ static uint64_t omap_id_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_id_write(void *opaque, target_phys_addr_t addr, +static void omap_id_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { if (size != 4) { @@ -1035,7 +1035,7 @@ static void omap_id_init(MemoryRegion *memory, struct omap_mpu_state_s *mpu) } /* MPUI Control (Dummy) */ -static uint64_t omap_mpui_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_mpui_read(void *opaque, hwaddr addr, unsigned size) { struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; @@ -1068,7 +1068,7 @@ static uint64_t omap_mpui_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_mpui_write(void *opaque, target_phys_addr_t addr, +static void omap_mpui_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; @@ -1109,7 +1109,7 @@ static void omap_mpui_reset(struct omap_mpu_state_s *s) s->mpui_ctrl = 0x0003ff1b; } -static void omap_mpui_init(MemoryRegion *memory, target_phys_addr_t base, +static void omap_mpui_init(MemoryRegion *memory, hwaddr base, struct omap_mpu_state_s *mpu) { memory_region_init_io(&mpu->mpui_iomem, &omap_mpui_ops, mpu, @@ -1131,7 +1131,7 @@ struct omap_tipb_bridge_s { uint16_t enh_control; }; -static uint64_t omap_tipb_bridge_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_tipb_bridge_read(void *opaque, hwaddr addr, unsigned size) { struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque; @@ -1161,7 +1161,7 @@ static uint64_t omap_tipb_bridge_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_tipb_bridge_write(void *opaque, target_phys_addr_t addr, +static void omap_tipb_bridge_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque; @@ -1215,7 +1215,7 @@ static void omap_tipb_bridge_reset(struct omap_tipb_bridge_s *s) } static struct omap_tipb_bridge_s *omap_tipb_bridge_init( - MemoryRegion *memory, target_phys_addr_t base, + MemoryRegion *memory, hwaddr base, qemu_irq abort_irq, omap_clk clk) { struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) @@ -1232,7 +1232,7 @@ static struct omap_tipb_bridge_s *omap_tipb_bridge_init( } /* Dummy Traffic Controller's Memory Interface */ -static uint64_t omap_tcmi_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_tcmi_read(void *opaque, hwaddr addr, unsigned size) { struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; @@ -1270,7 +1270,7 @@ static uint64_t omap_tcmi_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_tcmi_write(void *opaque, target_phys_addr_t addr, +static void omap_tcmi_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; @@ -1330,7 +1330,7 @@ static void omap_tcmi_reset(struct omap_mpu_state_s *mpu) mpu->tcmi_regs[0x40 >> 2] = 0x00000000; } -static void omap_tcmi_init(MemoryRegion *memory, target_phys_addr_t base, +static void omap_tcmi_init(MemoryRegion *memory, hwaddr base, struct omap_mpu_state_s *mpu) { memory_region_init_io(&mpu->tcmi_iomem, &omap_tcmi_ops, mpu, @@ -1346,7 +1346,7 @@ struct dpll_ctl_s { omap_clk dpll; }; -static uint64_t omap_dpll_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_dpll_read(void *opaque, hwaddr addr, unsigned size) { struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque; @@ -1362,7 +1362,7 @@ static uint64_t omap_dpll_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_dpll_write(void *opaque, target_phys_addr_t addr, +static void omap_dpll_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque; @@ -1412,7 +1412,7 @@ static void omap_dpll_reset(struct dpll_ctl_s *s) } static struct dpll_ctl_s *omap_dpll_init(MemoryRegion *memory, - target_phys_addr_t base, omap_clk clk) + hwaddr base, omap_clk clk) { struct dpll_ctl_s *s = g_malloc0(sizeof(*s)); memory_region_init_io(&s->iomem, &omap_dpll_ops, s, "omap-dpll", 0x100); @@ -1425,7 +1425,7 @@ static struct dpll_ctl_s *omap_dpll_init(MemoryRegion *memory, } /* MPU Clock/Reset/Power Mode Control */ -static uint64_t omap_clkm_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_clkm_read(void *opaque, hwaddr addr, unsigned size) { struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; @@ -1627,7 +1627,7 @@ static inline void omap_clkm_ckout1_update(struct omap_mpu_state_s *s, } } -static void omap_clkm_write(void *opaque, target_phys_addr_t addr, +static void omap_clkm_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; @@ -1714,7 +1714,7 @@ static const MemoryRegionOps omap_clkm_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint64_t omap_clkdsp_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_clkdsp_read(void *opaque, hwaddr addr, unsigned size) { struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; @@ -1758,7 +1758,7 @@ static inline void omap_clkdsp_idlect2_update(struct omap_mpu_state_s *s, SET_ONOFF("dspxor_ck", 1); /* EN_XORPCK */ } -static void omap_clkdsp_write(void *opaque, target_phys_addr_t addr, +static void omap_clkdsp_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; @@ -1823,8 +1823,8 @@ static void omap_clkm_reset(struct omap_mpu_state_s *s) s->clkm.dsp_rstct2 = 0x0000; } -static void omap_clkm_init(MemoryRegion *memory, target_phys_addr_t mpu_base, - target_phys_addr_t dsp_base, struct omap_mpu_state_s *s) +static void omap_clkm_init(MemoryRegion *memory, hwaddr mpu_base, + hwaddr dsp_base, struct omap_mpu_state_s *s) { memory_region_init_io(&s->clkm_iomem, &omap_clkm_ops, s, "omap-clkm", 0x100); @@ -1903,7 +1903,7 @@ static void omap_mpuio_kbd_update(struct omap_mpuio_s *s) s->row_latch = ~rows; } -static uint64_t omap_mpuio_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_mpuio_read(void *opaque, hwaddr addr, unsigned size) { struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque; @@ -1963,7 +1963,7 @@ static uint64_t omap_mpuio_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_mpuio_write(void *opaque, target_phys_addr_t addr, +static void omap_mpuio_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque; @@ -2072,7 +2072,7 @@ static void omap_mpuio_onoff(void *opaque, int line, int on) } static struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *memory, - target_phys_addr_t base, + hwaddr base, qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup, omap_clk clk) { @@ -2159,7 +2159,7 @@ static void omap_uwire_transfer_start(struct omap_uwire_s *s) } } -static uint64_t omap_uwire_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_uwire_read(void *opaque, hwaddr addr, unsigned size) { struct omap_uwire_s *s = (struct omap_uwire_s *) opaque; @@ -2193,7 +2193,7 @@ static uint64_t omap_uwire_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_uwire_write(void *opaque, target_phys_addr_t addr, +static void omap_uwire_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_uwire_s *s = (struct omap_uwire_s *) opaque; @@ -2263,7 +2263,7 @@ static void omap_uwire_reset(struct omap_uwire_s *s) } static struct omap_uwire_s *omap_uwire_init(MemoryRegion *system_memory, - target_phys_addr_t base, + hwaddr base, qemu_irq txirq, qemu_irq rxirq, qemu_irq dma, omap_clk clk) @@ -2312,7 +2312,7 @@ static void omap_pwl_update(struct omap_pwl_s *s) } } -static uint64_t omap_pwl_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_pwl_read(void *opaque, hwaddr addr, unsigned size) { struct omap_pwl_s *s = (struct omap_pwl_s *) opaque; @@ -2332,7 +2332,7 @@ static uint64_t omap_pwl_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_pwl_write(void *opaque, target_phys_addr_t addr, +static void omap_pwl_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_pwl_s *s = (struct omap_pwl_s *) opaque; @@ -2381,7 +2381,7 @@ static void omap_pwl_clk_update(void *opaque, int line, int on) } static struct omap_pwl_s *omap_pwl_init(MemoryRegion *system_memory, - target_phys_addr_t base, + hwaddr base, omap_clk clk) { struct omap_pwl_s *s = g_malloc0(sizeof(*s)); @@ -2405,7 +2405,7 @@ struct omap_pwt_s { omap_clk clk; }; -static uint64_t omap_pwt_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_pwt_read(void *opaque, hwaddr addr, unsigned size) { struct omap_pwt_s *s = (struct omap_pwt_s *) opaque; @@ -2427,7 +2427,7 @@ static uint64_t omap_pwt_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_pwt_write(void *opaque, target_phys_addr_t addr, +static void omap_pwt_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_pwt_s *s = (struct omap_pwt_s *) opaque; @@ -2488,7 +2488,7 @@ static void omap_pwt_reset(struct omap_pwt_s *s) } static struct omap_pwt_s *omap_pwt_init(MemoryRegion *system_memory, - target_phys_addr_t base, + hwaddr base, omap_clk clk) { struct omap_pwt_s *s = g_malloc0(sizeof(*s)); @@ -2536,7 +2536,7 @@ static void omap_rtc_alarm_update(struct omap_rtc_s *s) printf("%s: conversion failed\n", __FUNCTION__); } -static uint64_t omap_rtc_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_rtc_read(void *opaque, hwaddr addr, unsigned size) { struct omap_rtc_s *s = (struct omap_rtc_s *) opaque; @@ -2618,7 +2618,7 @@ static uint64_t omap_rtc_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_rtc_write(void *opaque, target_phys_addr_t addr, +static void omap_rtc_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_rtc_s *s = (struct omap_rtc_s *) opaque; @@ -2901,7 +2901,7 @@ static void omap_rtc_reset(struct omap_rtc_s *s) } static struct omap_rtc_s *omap_rtc_init(MemoryRegion *system_memory, - target_phys_addr_t base, + hwaddr base, qemu_irq timerirq, qemu_irq alarmirq, omap_clk clk) { @@ -3129,7 +3129,7 @@ static void omap_mcbsp_req_update(struct omap_mcbsp_s *s) omap_mcbsp_rx_stop(s); } -static uint64_t omap_mcbsp_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_mcbsp_read(void *opaque, hwaddr addr, unsigned size) { struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque; @@ -3227,7 +3227,7 @@ static uint64_t omap_mcbsp_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_mcbsp_writeh(void *opaque, target_phys_addr_t addr, +static void omap_mcbsp_writeh(void *opaque, hwaddr addr, uint32_t value) { struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque; @@ -3365,7 +3365,7 @@ static void omap_mcbsp_writeh(void *opaque, target_phys_addr_t addr, OMAP_BAD_REG(addr); } -static void omap_mcbsp_writew(void *opaque, target_phys_addr_t addr, +static void omap_mcbsp_writew(void *opaque, hwaddr addr, uint32_t value) { struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque; @@ -3396,7 +3396,7 @@ static void omap_mcbsp_writew(void *opaque, target_phys_addr_t addr, omap_badwidth_write16(opaque, addr, value); } -static void omap_mcbsp_write(void *opaque, target_phys_addr_t addr, +static void omap_mcbsp_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { switch (size) { @@ -3432,7 +3432,7 @@ static void omap_mcbsp_reset(struct omap_mcbsp_s *s) } static struct omap_mcbsp_s *omap_mcbsp_init(MemoryRegion *system_memory, - target_phys_addr_t base, + hwaddr base, qemu_irq txirq, qemu_irq rxirq, qemu_irq *dma, omap_clk clk) { @@ -3547,7 +3547,7 @@ static void omap_lpg_reset(struct omap_lpg_s *s) omap_lpg_update(s); } -static uint64_t omap_lpg_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_lpg_read(void *opaque, hwaddr addr, unsigned size) { struct omap_lpg_s *s = (struct omap_lpg_s *) opaque; @@ -3569,7 +3569,7 @@ static uint64_t omap_lpg_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_lpg_write(void *opaque, target_phys_addr_t addr, +static void omap_lpg_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_lpg_s *s = (struct omap_lpg_s *) opaque; @@ -3613,7 +3613,7 @@ static void omap_lpg_clk_update(void *opaque, int line, int on) } static struct omap_lpg_s *omap_lpg_init(MemoryRegion *system_memory, - target_phys_addr_t base, omap_clk clk) + hwaddr base, omap_clk clk) { struct omap_lpg_s *s = (struct omap_lpg_s *) g_malloc0(sizeof(struct omap_lpg_s)); @@ -3631,7 +3631,7 @@ static struct omap_lpg_s *omap_lpg_init(MemoryRegion *system_memory, } /* MPUI Peripheral Bridge configuration */ -static uint64_t omap_mpui_io_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_mpui_io_read(void *opaque, hwaddr addr, unsigned size) { if (size != 2) { @@ -3645,7 +3645,7 @@ static uint64_t omap_mpui_io_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_mpui_io_write(void *opaque, target_phys_addr_t addr, +static void omap_mpui_io_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { /* FIXME: infinite loop */ @@ -3706,8 +3706,8 @@ static void omap1_mpu_reset(void *opaque) } static const struct omap_map_s { - target_phys_addr_t phys_dsp; - target_phys_addr_t phys_mpu; + hwaddr phys_dsp; + hwaddr phys_mpu; uint32_t size; const char *name; } omap15xx_dsp_mm[] = { @@ -3778,38 +3778,38 @@ static const struct dma_irq_map omap1_dma_irq_map[] = { /* DMA ports for OMAP1 */ static int omap_validate_emiff_addr(struct omap_mpu_state_s *s, - target_phys_addr_t addr) + hwaddr addr) { return range_covers_byte(OMAP_EMIFF_BASE, s->sdram_size, addr); } static int omap_validate_emifs_addr(struct omap_mpu_state_s *s, - target_phys_addr_t addr) + hwaddr addr) { return range_covers_byte(OMAP_EMIFS_BASE, OMAP_EMIFF_BASE - OMAP_EMIFS_BASE, addr); } static int omap_validate_imif_addr(struct omap_mpu_state_s *s, - target_phys_addr_t addr) + hwaddr addr) { return range_covers_byte(OMAP_IMIF_BASE, s->sram_size, addr); } static int omap_validate_tipb_addr(struct omap_mpu_state_s *s, - target_phys_addr_t addr) + hwaddr addr) { return range_covers_byte(0xfffb0000, 0xffff0000 - 0xfffb0000, addr); } static int omap_validate_local_addr(struct omap_mpu_state_s *s, - target_phys_addr_t addr) + hwaddr addr) { return range_covers_byte(OMAP_LOCALBUS_BASE, 0x1000000, addr); } static int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s, - target_phys_addr_t addr) + hwaddr addr) { return range_covers_byte(0xe1010000, 0xe1020004 - 0xe1010000, addr); } diff --git a/hw/omap2.c b/hw/omap2.c index 4278dd19c4..96aba71052 100644 --- a/hw/omap2.c +++ b/hw/omap2.c @@ -324,7 +324,7 @@ static void omap_eac_reset(struct omap_eac_s *s) omap_eac_interrupt_update(s); } -static uint64_t omap_eac_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_eac_read(void *opaque, hwaddr addr, unsigned size) { struct omap_eac_s *s = (struct omap_eac_s *) opaque; @@ -440,7 +440,7 @@ static uint64_t omap_eac_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_eac_write(void *opaque, target_phys_addr_t addr, +static void omap_eac_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_eac_s *s = (struct omap_eac_s *) opaque; @@ -644,7 +644,7 @@ static void omap_sti_reset(struct omap_sti_s *s) omap_sti_interrupt_update(s); } -static uint64_t omap_sti_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_sti_read(void *opaque, hwaddr addr, unsigned size) { struct omap_sti_s *s = (struct omap_sti_s *) opaque; @@ -685,7 +685,7 @@ static uint64_t omap_sti_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_sti_write(void *opaque, target_phys_addr_t addr, +static void omap_sti_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_sti_s *s = (struct omap_sti_s *) opaque; @@ -741,14 +741,14 @@ static const MemoryRegionOps omap_sti_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint64_t omap_sti_fifo_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_sti_fifo_read(void *opaque, hwaddr addr, unsigned size) { OMAP_BAD_REG(addr); return 0; } -static void omap_sti_fifo_write(void *opaque, target_phys_addr_t addr, +static void omap_sti_fifo_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_sti_s *s = (struct omap_sti_s *) opaque; @@ -780,7 +780,7 @@ static const MemoryRegionOps omap_sti_fifo_ops = { static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta, MemoryRegion *sysmem, - target_phys_addr_t channel_base, qemu_irq irq, omap_clk clk, + hwaddr channel_base, qemu_irq irq, omap_clk clk, CharDriverState *chr) { struct omap_sti_s *s = (struct omap_sti_s *) @@ -1040,7 +1040,7 @@ static void omap_prcm_int_update(struct omap_prcm_s *s, int dom) /* XXX or is the mask applied before PRCM_IRQSTATUS_* ? */ } -static uint64_t omap_prcm_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_prcm_read(void *opaque, hwaddr addr, unsigned size) { struct omap_prcm_s *s = (struct omap_prcm_s *) opaque; @@ -1352,7 +1352,7 @@ static void omap_prcm_dpll_update(struct omap_prcm_s *s) } } -static void omap_prcm_write(void *opaque, target_phys_addr_t addr, +static void omap_prcm_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_prcm_s *s = (struct omap_prcm_s *) opaque; @@ -1832,7 +1832,7 @@ struct omap_sysctl_s { uint32_t msuspendmux[5]; }; -static uint32_t omap_sysctl_read8(void *opaque, target_phys_addr_t addr) +static uint32_t omap_sysctl_read8(void *opaque, hwaddr addr) { struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque; @@ -1857,7 +1857,7 @@ static uint32_t omap_sysctl_read8(void *opaque, target_phys_addr_t addr) return 0; } -static uint32_t omap_sysctl_read(void *opaque, target_phys_addr_t addr) +static uint32_t omap_sysctl_read(void *opaque, hwaddr addr) { struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque; @@ -1957,7 +1957,7 @@ static uint32_t omap_sysctl_read(void *opaque, target_phys_addr_t addr) return 0; } -static void omap_sysctl_write8(void *opaque, target_phys_addr_t addr, +static void omap_sysctl_write8(void *opaque, hwaddr addr, uint32_t value) { struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque; @@ -1981,7 +1981,7 @@ static void omap_sysctl_write8(void *opaque, target_phys_addr_t addr, } } -static void omap_sysctl_write(void *opaque, target_phys_addr_t addr, +static void omap_sysctl_write(void *opaque, hwaddr addr, uint32_t value) { struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque; @@ -2226,7 +2226,7 @@ static void omap2_mpu_reset(void *opaque) } static int omap2_validate_addr(struct omap_mpu_state_s *s, - target_phys_addr_t addr) + hwaddr addr) { return 1; } diff --git a/hw/omap_dma.c b/hw/omap_dma.c index 389cb78dee..e619c7b7de 100644 --- a/hw/omap_dma.c +++ b/hw/omap_dma.c @@ -31,7 +31,7 @@ struct omap_dma_channel_s { int endian_lock[2]; int translate[2]; enum omap_dma_port port[2]; - target_phys_addr_t addr[2]; + hwaddr addr[2]; omap_dma_addressing_t mode[2]; uint32_t elements; uint16_t frames; @@ -78,7 +78,7 @@ struct omap_dma_channel_s { struct omap_dma_channel_s *sibling; struct omap_dma_reg_set_s { - target_phys_addr_t src, dest; + hwaddr src, dest; int frame; int element; int pck_element; @@ -914,7 +914,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, break; case 0x06: /* SYS_DMA_CSR_CH0 */ - OMAP_RO_REG((target_phys_addr_t) reg); + OMAP_RO_REG((hwaddr) reg); break; case 0x08: /* SYS_DMA_CSSA_L_CH0 */ @@ -954,7 +954,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, break; case 0x18: /* SYS_DMA_CPC_CH0 or DMA_CSAC */ - OMAP_RO_REG((target_phys_addr_t) reg); + OMAP_RO_REG((hwaddr) reg); break; case 0x1c: /* DMA_CDEI */ @@ -1446,7 +1446,7 @@ static int omap_dma_sys_read(struct omap_dma_s *s, int offset, return 0; } -static uint64_t omap_dma_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_dma_read(void *opaque, hwaddr addr, unsigned size) { struct omap_dma_s *s = (struct omap_dma_s *) opaque; @@ -1494,7 +1494,7 @@ static uint64_t omap_dma_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_dma_write(void *opaque, target_phys_addr_t addr, +static void omap_dma_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_dma_s *s = (struct omap_dma_s *) opaque; @@ -1618,7 +1618,7 @@ static void omap_dma_setcaps(struct omap_dma_s *s) } } -struct soc_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs, +struct soc_dma_s *omap_dma_init(hwaddr base, qemu_irq *irqs, MemoryRegion *sysmem, qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk, enum omap_dma_model model) @@ -1692,7 +1692,7 @@ static void omap_dma_interrupts_4_update(struct omap_dma_s *s) qemu_irq_raise(s->irq[3]); } -static uint64_t omap_dma4_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_dma4_read(void *opaque, hwaddr addr, unsigned size) { struct omap_dma_s *s = (struct omap_dma_s *) opaque; @@ -1842,7 +1842,7 @@ static uint64_t omap_dma4_read(void *opaque, target_phys_addr_t addr, } } -static void omap_dma4_write(void *opaque, target_phys_addr_t addr, +static void omap_dma4_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_dma_s *s = (struct omap_dma_s *) opaque; @@ -1988,12 +1988,12 @@ static void omap_dma4_write(void *opaque, target_phys_addr_t addr, break; case 0x1c: /* DMA4_CSSA */ - ch->addr[0] = (target_phys_addr_t) (uint32_t) value; + ch->addr[0] = (hwaddr) (uint32_t) value; ch->set_update = 1; break; case 0x20: /* DMA4_CDSA */ - ch->addr[1] = (target_phys_addr_t) (uint32_t) value; + ch->addr[1] = (hwaddr) (uint32_t) value; ch->set_update = 1; break; @@ -2040,7 +2040,7 @@ static const MemoryRegionOps omap_dma4_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs, +struct soc_dma_s *omap_dma4_init(hwaddr base, qemu_irq *irqs, MemoryRegion *sysmem, struct omap_mpu_state_s *mpu, int fifo, int chans, omap_clk iclk, omap_clk fclk) diff --git a/hw/omap_dss.c b/hw/omap_dss.c index 86ed6ea5d9..1e83726d3b 100644 --- a/hw/omap_dss.c +++ b/hw/omap_dss.c @@ -60,7 +60,7 @@ struct omap_dss_s { int nx; int ny; - target_phys_addr_t addr[3]; + hwaddr addr[3]; uint32_t attr; uint32_t tresh; @@ -168,7 +168,7 @@ void omap_dss_reset(struct omap_dss_s *s) omap_dispc_interrupt_update(s); } -static uint64_t omap_diss_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_diss_read(void *opaque, hwaddr addr, unsigned size) { struct omap_dss_s *s = (struct omap_dss_s *) opaque; @@ -206,7 +206,7 @@ static uint64_t omap_diss_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_diss_write(void *opaque, target_phys_addr_t addr, +static void omap_diss_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_dss_s *s = (struct omap_dss_s *) opaque; @@ -246,7 +246,7 @@ static const MemoryRegionOps omap_diss_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint64_t omap_disc_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_disc_read(void *opaque, hwaddr addr, unsigned size) { struct omap_dss_s *s = (struct omap_dss_s *) opaque; @@ -371,7 +371,7 @@ static uint64_t omap_disc_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_disc_write(void *opaque, target_phys_addr_t addr, +static void omap_disc_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_dss_s *s = (struct omap_dss_s *) opaque; @@ -502,11 +502,11 @@ static void omap_disc_write(void *opaque, target_phys_addr_t addr, s->dispc.invalidate = 1; break; case 0x080: /* DISPC_GFX_BA0 */ - s->dispc.l[0].addr[0] = (target_phys_addr_t) value; + s->dispc.l[0].addr[0] = (hwaddr) value; s->dispc.invalidate = 1; break; case 0x084: /* DISPC_GFX_BA1 */ - s->dispc.l[0].addr[1] = (target_phys_addr_t) value; + s->dispc.l[0].addr[1] = (hwaddr) value; s->dispc.invalidate = 1; break; case 0x088: /* DISPC_GFX_POSITION */ @@ -543,7 +543,7 @@ static void omap_disc_write(void *opaque, target_phys_addr_t addr, s->dispc.l[0].wininc = value; break; case 0x0b8: /* DISPC_GFX_TABLE_BA */ - s->dispc.l[0].addr[2] = (target_phys_addr_t) value; + s->dispc.l[0].addr[2] = (hwaddr) value; s->dispc.invalidate = 1; break; @@ -602,11 +602,11 @@ static void omap_rfbi_transfer_stop(struct omap_dss_s *s) static void omap_rfbi_transfer_start(struct omap_dss_s *s) { void *data; - target_phys_addr_t len; - target_phys_addr_t data_addr; + hwaddr len; + hwaddr data_addr; int pitch; static void *bounce_buffer; - static target_phys_addr_t bounce_len; + static hwaddr bounce_len; if (!s->rfbi.enable || s->rfbi.busy) return; @@ -663,7 +663,7 @@ static void omap_rfbi_transfer_start(struct omap_dss_s *s) omap_dispc_interrupt_update(s); } -static uint64_t omap_rfbi_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_rfbi_read(void *opaque, hwaddr addr, unsigned size) { struct omap_dss_s *s = (struct omap_dss_s *) opaque; @@ -730,7 +730,7 @@ static uint64_t omap_rfbi_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_rfbi_write(void *opaque, target_phys_addr_t addr, +static void omap_rfbi_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_dss_s *s = (struct omap_dss_s *) opaque; @@ -864,7 +864,7 @@ static const MemoryRegionOps omap_rfbi_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint64_t omap_venc_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_venc_read(void *opaque, hwaddr addr, unsigned size) { if (size != 4) { @@ -924,7 +924,7 @@ static uint64_t omap_venc_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_venc_write(void *opaque, target_phys_addr_t addr, +static void omap_venc_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { if (size != 4) { @@ -986,7 +986,7 @@ static const MemoryRegionOps omap_venc_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint64_t omap_im3_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_im3_read(void *opaque, hwaddr addr, unsigned size) { if (size != 4) { @@ -1012,7 +1012,7 @@ static uint64_t omap_im3_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_im3_write(void *opaque, target_phys_addr_t addr, +static void omap_im3_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { if (size != 4) { @@ -1041,7 +1041,7 @@ static const MemoryRegionOps omap_im3_ops = { struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta, MemoryRegion *sysmem, - target_phys_addr_t l3_base, + hwaddr l3_base, qemu_irq irq, qemu_irq drq, omap_clk fck1, omap_clk fck2, omap_clk ck54m, omap_clk ick1, omap_clk ick2) diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c index 201ff77c36..25655325d0 100644 --- a/hw/omap_gpio.c +++ b/hw/omap_gpio.c @@ -61,7 +61,7 @@ static void omap_gpio_set(void *opaque, int line, int level) } } -static uint64_t omap_gpio_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_gpio_read(void *opaque, hwaddr addr, unsigned size) { struct omap_gpio_s *s = (struct omap_gpio_s *) opaque; @@ -99,7 +99,7 @@ static uint64_t omap_gpio_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_gpio_write(void *opaque, target_phys_addr_t addr, +static void omap_gpio_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_gpio_s *s = (struct omap_gpio_s *) opaque; @@ -300,7 +300,7 @@ static void omap2_gpio_module_reset(struct omap2_gpio_s *s) s->delay = 0; } -static uint32_t omap2_gpio_module_read(void *opaque, target_phys_addr_t addr) +static uint32_t omap2_gpio_module_read(void *opaque, hwaddr addr) { struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque; @@ -372,7 +372,7 @@ static uint32_t omap2_gpio_module_read(void *opaque, target_phys_addr_t addr) return 0; } -static void omap2_gpio_module_write(void *opaque, target_phys_addr_t addr, +static void omap2_gpio_module_write(void *opaque, hwaddr addr, uint32_t value) { struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque; @@ -514,12 +514,12 @@ static void omap2_gpio_module_write(void *opaque, target_phys_addr_t addr, } } -static uint32_t omap2_gpio_module_readp(void *opaque, target_phys_addr_t addr) +static uint32_t omap2_gpio_module_readp(void *opaque, hwaddr addr) { return omap2_gpio_module_read(opaque, addr & ~3) >> ((addr & 3) << 3); } -static void omap2_gpio_module_writep(void *opaque, target_phys_addr_t addr, +static void omap2_gpio_module_writep(void *opaque, hwaddr addr, uint32_t value) { uint32_t cur = 0; @@ -604,7 +604,7 @@ static void omap2_gpif_reset(DeviceState *dev) s->gpo = 0; } -static uint64_t omap2_gpif_top_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap2_gpif_top_read(void *opaque, hwaddr addr, unsigned size) { struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque; @@ -633,7 +633,7 @@ static uint64_t omap2_gpif_top_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap2_gpif_top_write(void *opaque, target_phys_addr_t addr, +static void omap2_gpif_top_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque; diff --git a/hw/omap_gpmc.c b/hw/omap_gpmc.c index 2fc4137203..1f7c5bc5f3 100644 --- a/hw/omap_gpmc.c +++ b/hw/omap_gpmc.c @@ -121,7 +121,7 @@ static void omap_gpmc_dma_update(struct omap_gpmc_s *s, int value) * all addresses in the region behave like accesses to the relevant * GPMC_NAND_DATA_i register (which is actually implemented to call these) */ -static uint64_t omap_nand_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_nand_read(void *opaque, hwaddr addr, unsigned size) { struct omap_gpmc_cs_file_s *f = (struct omap_gpmc_cs_file_s *)opaque; @@ -200,7 +200,7 @@ static void omap_nand_setio(DeviceState *dev, uint64_t value, } } -static void omap_nand_write(void *opaque, target_phys_addr_t addr, +static void omap_nand_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_gpmc_cs_file_s *f = (struct omap_gpmc_cs_file_s *)opaque; @@ -281,7 +281,7 @@ static void fill_prefetch_fifo(struct omap_gpmc_s *s) * engine is enabled -- all addresses in the region behave alike: * data is read or written to the FIFO. */ -static uint64_t omap_gpmc_prefetch_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_gpmc_prefetch_read(void *opaque, hwaddr addr, unsigned size) { struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque; @@ -311,7 +311,7 @@ static uint64_t omap_gpmc_prefetch_read(void *opaque, target_phys_addr_t addr, return data; } -static void omap_gpmc_prefetch_write(void *opaque, target_phys_addr_t addr, +static void omap_gpmc_prefetch_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque; @@ -484,7 +484,7 @@ void omap_gpmc_reset(struct omap_gpmc_s *s) ecc_reset(&s->ecc[i]); } -static int gpmc_wordaccess_only(target_phys_addr_t addr) +static int gpmc_wordaccess_only(hwaddr addr) { /* Return true if the register offset is to a register that * only permits word width accesses. @@ -502,7 +502,7 @@ static int gpmc_wordaccess_only(target_phys_addr_t addr) return 1; } -static uint64_t omap_gpmc_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_gpmc_read(void *opaque, hwaddr addr, unsigned size) { struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque; @@ -614,7 +614,7 @@ static uint64_t omap_gpmc_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_gpmc_write(void *opaque, target_phys_addr_t addr, +static void omap_gpmc_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque; @@ -819,7 +819,7 @@ static const MemoryRegionOps omap_gpmc_ops = { }; struct omap_gpmc_s *omap_gpmc_init(struct omap_mpu_state_s *mpu, - target_phys_addr_t base, + hwaddr base, qemu_irq irq, qemu_irq drq) { int cs; diff --git a/hw/omap_gptimer.c b/hw/omap_gptimer.c index 7a145198a4..e39da74067 100644 --- a/hw/omap_gptimer.c +++ b/hw/omap_gptimer.c @@ -258,7 +258,7 @@ void omap_gp_timer_reset(struct omap_gp_timer_s *s) omap_gp_timer_update(s); } -static uint32_t omap_gp_timer_readw(void *opaque, target_phys_addr_t addr) +static uint32_t omap_gp_timer_readw(void *opaque, hwaddr addr) { struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque; @@ -324,7 +324,7 @@ static uint32_t omap_gp_timer_readw(void *opaque, target_phys_addr_t addr) return 0; } -static uint32_t omap_gp_timer_readh(void *opaque, target_phys_addr_t addr) +static uint32_t omap_gp_timer_readh(void *opaque, hwaddr addr) { struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque; uint32_t ret; @@ -338,7 +338,7 @@ static uint32_t omap_gp_timer_readh(void *opaque, target_phys_addr_t addr) } } -static void omap_gp_timer_write(void *opaque, target_phys_addr_t addr, +static void omap_gp_timer_write(void *opaque, hwaddr addr, uint32_t value) { struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque; @@ -438,7 +438,7 @@ static void omap_gp_timer_write(void *opaque, target_phys_addr_t addr, } } -static void omap_gp_timer_writeh(void *opaque, target_phys_addr_t addr, +static void omap_gp_timer_writeh(void *opaque, hwaddr addr, uint32_t value) { struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque; diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c index 20bc82e3b8..ba08e6400c 100644 --- a/hw/omap_i2c.c +++ b/hw/omap_i2c.c @@ -149,7 +149,7 @@ static void omap_i2c_reset(DeviceState *dev) s->test = 0; } -static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr) +static uint32_t omap_i2c_read(void *opaque, hwaddr addr) { OMAPI2CState *s = opaque; int offset = addr & OMAP_MPUI_REG_MASK; @@ -248,7 +248,7 @@ static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr) return 0; } -static void omap_i2c_write(void *opaque, target_phys_addr_t addr, +static void omap_i2c_write(void *opaque, hwaddr addr, uint32_t value) { OMAPI2CState *s = opaque; @@ -390,7 +390,7 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr, } } -static void omap_i2c_writeb(void *opaque, target_phys_addr_t addr, +static void omap_i2c_writeb(void *opaque, hwaddr addr, uint32_t value) { OMAPI2CState *s = opaque; diff --git a/hw/omap_intc.c b/hw/omap_intc.c index 5076e07ed5..61e0dafbdd 100644 --- a/hw/omap_intc.c +++ b/hw/omap_intc.c @@ -145,7 +145,7 @@ static void omap_set_intr_noedge(void *opaque, int irq, int req) bank->irqs = (bank->inputs &= ~(1 << n)) | bank->swi; } -static uint64_t omap_inth_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_inth_read(void *opaque, hwaddr addr, unsigned size) { struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; @@ -223,7 +223,7 @@ static uint64_t omap_inth_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_inth_write(void *opaque, target_phys_addr_t addr, +static void omap_inth_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; @@ -396,7 +396,7 @@ static TypeInfo omap_intc_info = { .class_init = omap_intc_class_init, }; -static uint64_t omap2_inth_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap2_inth_read(void *opaque, hwaddr addr, unsigned size) { struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; @@ -477,7 +477,7 @@ static uint64_t omap2_inth_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap2_inth_write(void *opaque, target_phys_addr_t addr, +static void omap2_inth_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; diff --git a/hw/omap_l4.c b/hw/omap_l4.c index dbad7f67a8..09e983f319 100644 --- a/hw/omap_l4.c +++ b/hw/omap_l4.c @@ -22,13 +22,13 @@ struct omap_l4_s { MemoryRegion *address_space; - target_phys_addr_t base; + hwaddr base; int ta_num; struct omap_target_agent_s ta[0]; }; struct omap_l4_s *omap_l4_init(MemoryRegion *address_space, - target_phys_addr_t base, int ta_num) + hwaddr base, int ta_num) { struct omap_l4_s *bus = g_malloc0( sizeof(*bus) + ta_num * sizeof(*bus->ta)); @@ -40,19 +40,19 @@ struct omap_l4_s *omap_l4_init(MemoryRegion *address_space, return bus; } -target_phys_addr_t omap_l4_region_base(struct omap_target_agent_s *ta, +hwaddr omap_l4_region_base(struct omap_target_agent_s *ta, int region) { return ta->bus->base + ta->start[region].offset; } -target_phys_addr_t omap_l4_region_size(struct omap_target_agent_s *ta, +hwaddr omap_l4_region_size(struct omap_target_agent_s *ta, int region) { return ta->start[region].size; } -static uint64_t omap_l4ta_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_l4ta_read(void *opaque, hwaddr addr, unsigned size) { struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque; @@ -76,7 +76,7 @@ static uint64_t omap_l4ta_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_l4ta_write(void *opaque, target_phys_addr_t addr, +static void omap_l4ta_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque; @@ -143,10 +143,10 @@ struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, return ta; } -target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, +hwaddr omap_l4_attach(struct omap_target_agent_s *ta, int region, MemoryRegion *mr) { - target_phys_addr_t base; + hwaddr base; if (region < 0 || region >= ta->regions) { fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region); diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c index e2ba10834e..bf177c22dd 100644 --- a/hw/omap_lcdc.c +++ b/hw/omap_lcdc.c @@ -117,7 +117,7 @@ static void omap_update_display(void *opaque) draw_line_func draw_line; int size, height, first, last; int width, linesize, step, bpp, frame_offset; - target_phys_addr_t frame_base; + hwaddr frame_base; if (!omap_lcd || omap_lcd->plm == 1 || !omap_lcd->enable || !ds_get_bits_per_pixel(omap_lcd->state)) @@ -359,7 +359,7 @@ static void omap_lcd_update(struct omap_lcd_panel_s *s) { } } -static uint64_t omap_lcdc_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_lcdc_read(void *opaque, hwaddr addr, unsigned size) { struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *) opaque; @@ -392,7 +392,7 @@ static uint64_t omap_lcdc_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_lcdc_write(void *opaque, target_phys_addr_t addr, +static void omap_lcdc_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *) opaque; @@ -465,7 +465,7 @@ void omap_lcdc_reset(struct omap_lcd_panel_s *s) } struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem, - target_phys_addr_t base, + hwaddr base, qemu_irq irq, struct omap_dma_lcd_channel_s *dma, omap_clk clk) diff --git a/hw/omap_mmc.c b/hw/omap_mmc.c index aec0285675..7ecd9bd4ca 100644 --- a/hw/omap_mmc.c +++ b/hw/omap_mmc.c @@ -306,7 +306,7 @@ void omap_mmc_reset(struct omap_mmc_s *host) host->clkdiv = 0; } -static uint64_t omap_mmc_read(void *opaque, target_phys_addr_t offset, +static uint64_t omap_mmc_read(void *opaque, hwaddr offset, unsigned size) { uint16_t i; @@ -399,7 +399,7 @@ static uint64_t omap_mmc_read(void *opaque, target_phys_addr_t offset, return 0; } -static void omap_mmc_write(void *opaque, target_phys_addr_t offset, +static void omap_mmc_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { int i; @@ -572,7 +572,7 @@ static void omap_mmc_cover_cb(void *opaque, int line, int level) } } -struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base, +struct omap_mmc_s *omap_mmc_init(hwaddr base, MemoryRegion *sysmem, BlockDriverState *bd, qemu_irq irq, qemu_irq dma[], omap_clk clk) diff --git a/hw/omap_sdrc.c b/hw/omap_sdrc.c index 784e326105..b0f3b8e675 100644 --- a/hw/omap_sdrc.c +++ b/hw/omap_sdrc.c @@ -31,7 +31,7 @@ void omap_sdrc_reset(struct omap_sdrc_s *s) s->config = 0x10; } -static uint64_t omap_sdrc_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_sdrc_read(void *opaque, hwaddr addr, unsigned size) { struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque; @@ -86,7 +86,7 @@ static uint64_t omap_sdrc_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_sdrc_write(void *opaque, target_phys_addr_t addr, +static void omap_sdrc_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque; @@ -154,7 +154,7 @@ static const MemoryRegionOps omap_sdrc_ops = { }; struct omap_sdrc_s *omap_sdrc_init(MemoryRegion *sysmem, - target_phys_addr_t base) + hwaddr base) { struct omap_sdrc_s *s = (struct omap_sdrc_s *) g_malloc0(sizeof(struct omap_sdrc_s)); diff --git a/hw/omap_spi.c b/hw/omap_spi.c index 8f2b697d2d..42d5149a2b 100644 --- a/hw/omap_spi.c +++ b/hw/omap_spi.c @@ -130,7 +130,7 @@ void omap_mcspi_reset(struct omap_mcspi_s *s) omap_mcspi_interrupt_update(s); } -static uint64_t omap_mcspi_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_mcspi_read(void *opaque, hwaddr addr, unsigned size) { struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque; @@ -204,7 +204,7 @@ static uint64_t omap_mcspi_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_mcspi_write(void *opaque, target_phys_addr_t addr, +static void omap_mcspi_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque; diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c index ad17487fd2..eb2bf0569c 100644 --- a/hw/omap_sx1.c +++ b/hw/omap_sx1.c @@ -59,7 +59,7 @@ * - 1 RTC */ -static uint64_t static_read(void *opaque, target_phys_addr_t offset, +static uint64_t static_read(void *opaque, hwaddr offset, unsigned size) { uint32_t *val = (uint32_t *) opaque; @@ -68,7 +68,7 @@ static uint64_t static_read(void *opaque, target_phys_addr_t offset, return *val >> ((offset & mask) << 3); } -static void static_write(void *opaque, target_phys_addr_t offset, +static void static_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { #ifdef SPY diff --git a/hw/omap_synctimer.c b/hw/omap_synctimer.c index 367f26e3a1..7031a88531 100644 --- a/hw/omap_synctimer.c +++ b/hw/omap_synctimer.c @@ -36,7 +36,7 @@ void omap_synctimer_reset(struct omap_synctimer_s *s) s->val = omap_synctimer_read(s); } -static uint32_t omap_synctimer_readw(void *opaque, target_phys_addr_t addr) +static uint32_t omap_synctimer_readw(void *opaque, hwaddr addr) { struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque; @@ -52,7 +52,7 @@ static uint32_t omap_synctimer_readw(void *opaque, target_phys_addr_t addr) return 0; } -static uint32_t omap_synctimer_readh(void *opaque, target_phys_addr_t addr) +static uint32_t omap_synctimer_readh(void *opaque, hwaddr addr) { struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque; uint32_t ret; @@ -66,7 +66,7 @@ static uint32_t omap_synctimer_readh(void *opaque, target_phys_addr_t addr) } } -static void omap_synctimer_write(void *opaque, target_phys_addr_t addr, +static void omap_synctimer_write(void *opaque, hwaddr addr, uint32_t value) { OMAP_BAD_REG(addr); diff --git a/hw/omap_tap.c b/hw/omap_tap.c index 0277c73652..e273e971ed 100644 --- a/hw/omap_tap.c +++ b/hw/omap_tap.c @@ -22,7 +22,7 @@ #include "omap.h" /* TEST-Chip-level TAP */ -static uint64_t omap_tap_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_tap_read(void *opaque, hwaddr addr, unsigned size) { struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; @@ -91,7 +91,7 @@ static uint64_t omap_tap_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_tap_write(void *opaque, target_phys_addr_t addr, +static void omap_tap_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { if (size != 4) { diff --git a/hw/omap_uart.c b/hw/omap_uart.c index 1c16a54306..92f27021bb 100644 --- a/hw/omap_uart.c +++ b/hw/omap_uart.c @@ -26,7 +26,7 @@ /* UARTs */ struct omap_uart_s { MemoryRegion iomem; - target_phys_addr_t base; + hwaddr base; SerialState *serial; /* TODO */ struct omap_target_agent_s *ta; omap_clk fclk; @@ -50,7 +50,7 @@ void omap_uart_reset(struct omap_uart_s *s) s->clksel = 0; } -struct omap_uart_s *omap_uart_init(target_phys_addr_t base, +struct omap_uart_s *omap_uart_init(hwaddr base, qemu_irq irq, omap_clk fclk, omap_clk iclk, qemu_irq txdma, qemu_irq rxdma, const char *label, CharDriverState *chr) @@ -68,7 +68,7 @@ struct omap_uart_s *omap_uart_init(target_phys_addr_t base, return s; } -static uint64_t omap_uart_read(void *opaque, target_phys_addr_t addr, +static uint64_t omap_uart_read(void *opaque, hwaddr addr, unsigned size) { struct omap_uart_s *s = (struct omap_uart_s *) opaque; @@ -106,7 +106,7 @@ static uint64_t omap_uart_read(void *opaque, target_phys_addr_t addr, return 0; } -static void omap_uart_write(void *opaque, target_phys_addr_t addr, +static void omap_uart_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct omap_uart_s *s = (struct omap_uart_s *) opaque; @@ -164,7 +164,7 @@ struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem, qemu_irq txdma, qemu_irq rxdma, const char *label, CharDriverState *chr) { - target_phys_addr_t base = omap_l4_attach(ta, 0, NULL); + hwaddr base = omap_l4_attach(ta, 0, NULL); struct omap_uart_s *s = omap_uart_init(base, irq, fclk, iclk, txdma, rxdma, label, chr); diff --git a/hw/onenand.c b/hw/onenand.c index 0f7b755a6d..1803e4c264 100644 --- a/hw/onenand.c +++ b/hw/onenand.c @@ -42,7 +42,7 @@ typedef struct { uint16_t ver; } id; int shift; - target_phys_addr_t base; + hwaddr base; qemu_irq intr; qemu_irq rdy; BlockDriverState *bdrv; @@ -588,7 +588,7 @@ static void onenand_command(OneNANDState *s) onenand_intr_update(s); } -static uint64_t onenand_read(void *opaque, target_phys_addr_t addr, +static uint64_t onenand_read(void *opaque, hwaddr addr, unsigned size) { OneNANDState *s = (OneNANDState *) opaque; @@ -653,7 +653,7 @@ static uint64_t onenand_read(void *opaque, target_phys_addr_t addr, return 0; } -static void onenand_write(void *opaque, target_phys_addr_t addr, +static void onenand_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { OneNANDState *s = (OneNANDState *) opaque; @@ -760,7 +760,7 @@ static int onenand_initfn(SysBusDevice *dev) OneNANDState *s = (OneNANDState *)dev; uint32_t size = 1 << (24 + ((s->id.dev >> 4) & 7)); void *ram; - s->base = (target_phys_addr_t)-1; + s->base = (hwaddr)-1; s->rdy = NULL; s->blocks = size >> BLOCK_SHIFT; s->secs = size >> 9; diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c index 8c15969e2b..b2780b9334 100644 --- a/hw/opencores_eth.c +++ b/hw/opencores_eth.c @@ -528,7 +528,7 @@ static void open_eth_check_start_xmit(OpenEthState *s) } static uint64_t open_eth_reg_read(void *opaque, - target_phys_addr_t addr, unsigned int size) + hwaddr addr, unsigned int size) { static uint32_t (*reg_read[REG_MAX])(OpenEthState *s) = { }; @@ -620,7 +620,7 @@ static void open_eth_mii_tx_host_write(OpenEthState *s, uint32_t val) } static void open_eth_reg_write(void *opaque, - target_phys_addr_t addr, uint64_t val, unsigned int size) + hwaddr addr, uint64_t val, unsigned int size) { static void (*reg_write[REG_MAX])(OpenEthState *s, uint32_t val) = { [MODER] = open_eth_moder_host_write, @@ -644,7 +644,7 @@ static void open_eth_reg_write(void *opaque, } static uint64_t open_eth_desc_read(void *opaque, - target_phys_addr_t addr, unsigned int size) + hwaddr addr, unsigned int size) { OpenEthState *s = opaque; uint64_t v = 0; @@ -656,7 +656,7 @@ static uint64_t open_eth_desc_read(void *opaque, } static void open_eth_desc_write(void *opaque, - target_phys_addr_t addr, uint64_t val, unsigned int size) + hwaddr addr, uint64_t val, unsigned int size) { OpenEthState *s = opaque; diff --git a/hw/openpic.c b/hw/openpic.c index b9d856830a..8b3784a6bd 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -178,9 +178,9 @@ static int get_current_cpu(void) return cpu_single_env->cpu_index; } -static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr, +static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr, int idx); -static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr, +static void openpic_cpu_write_internal(void *opaque, hwaddr addr, uint32_t val, int idx); enum { @@ -596,7 +596,7 @@ static void write_mailbox_register (openpic_t *opp, int n_mbx, #endif #endif /* 0 : Code provision for Intel model */ -static void openpic_gbl_write (void *opaque, target_phys_addr_t addr, uint32_t val) +static void openpic_gbl_write (void *opaque, hwaddr addr, uint32_t val) { openpic_t *opp = opaque; IRQ_dst_t *dst; @@ -662,7 +662,7 @@ static void openpic_gbl_write (void *opaque, target_phys_addr_t addr, uint32_t v } } -static uint32_t openpic_gbl_read (void *opaque, target_phys_addr_t addr) +static uint32_t openpic_gbl_read (void *opaque, hwaddr addr) { openpic_t *opp = opaque; uint32_t retval; @@ -826,7 +826,7 @@ static uint32_t openpic_src_read (void *opaque, uint32_t addr) return retval; } -static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr, +static void openpic_cpu_write_internal(void *opaque, hwaddr addr, uint32_t val, int idx) { openpic_t *opp = opaque; @@ -886,12 +886,12 @@ static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr, } } -static void openpic_cpu_write(void *opaque, target_phys_addr_t addr, uint32_t val) +static void openpic_cpu_write(void *opaque, hwaddr addr, uint32_t val) { openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12); } -static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr, +static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr, int idx) { openpic_t *opp = opaque; @@ -970,18 +970,18 @@ static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr, return retval; } -static uint32_t openpic_cpu_read(void *opaque, target_phys_addr_t addr) +static uint32_t openpic_cpu_read(void *opaque, hwaddr addr) { return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12); } static void openpic_buggy_write (void *opaque, - target_phys_addr_t addr, uint32_t val) + hwaddr addr, uint32_t val) { printf("Invalid OPENPIC write access !\n"); } -static uint32_t openpic_buggy_read (void *opaque, target_phys_addr_t addr) +static uint32_t openpic_buggy_read (void *opaque, hwaddr addr) { printf("Invalid OPENPIC read access !\n"); @@ -989,7 +989,7 @@ static uint32_t openpic_buggy_read (void *opaque, target_phys_addr_t addr) } static void openpic_writel (void *opaque, - target_phys_addr_t addr, uint32_t val) + hwaddr addr, uint32_t val) { openpic_t *opp = opaque; @@ -1010,7 +1010,7 @@ static void openpic_writel (void *opaque, } } -static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr) +static uint32_t openpic_readl (void *opaque,hwaddr addr) { openpic_t *opp = opaque; uint32_t retval; @@ -1034,7 +1034,7 @@ static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr) return retval; } -static uint64_t openpic_read(void *opaque, target_phys_addr_t addr, +static uint64_t openpic_read(void *opaque, hwaddr addr, unsigned size) { openpic_t *opp = opaque; @@ -1045,7 +1045,7 @@ static uint64_t openpic_read(void *opaque, target_phys_addr_t addr, } } -static void openpic_write(void *opaque, target_phys_addr_t addr, +static void openpic_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { openpic_t *opp = opaque; @@ -1300,7 +1300,7 @@ static void mpic_reset (void *opaque) mpp->glbc = 0x00000000; } -static void mpic_timer_write (void *opaque, target_phys_addr_t addr, uint32_t val) +static void mpic_timer_write (void *opaque, hwaddr addr, uint32_t val) { openpic_t *mpp = opaque; int idx, cpu; @@ -1333,7 +1333,7 @@ static void mpic_timer_write (void *opaque, target_phys_addr_t addr, uint32_t va } } -static uint32_t mpic_timer_read (void *opaque, target_phys_addr_t addr) +static uint32_t mpic_timer_read (void *opaque, hwaddr addr) { openpic_t *mpp = opaque; uint32_t retval; @@ -1368,7 +1368,7 @@ static uint32_t mpic_timer_read (void *opaque, target_phys_addr_t addr) return retval; } -static void mpic_src_ext_write (void *opaque, target_phys_addr_t addr, +static void mpic_src_ext_write (void *opaque, hwaddr addr, uint32_t val) { openpic_t *mpp = opaque; @@ -1390,7 +1390,7 @@ static void mpic_src_ext_write (void *opaque, target_phys_addr_t addr, } } -static uint32_t mpic_src_ext_read (void *opaque, target_phys_addr_t addr) +static uint32_t mpic_src_ext_read (void *opaque, hwaddr addr) { openpic_t *mpp = opaque; uint32_t retval; @@ -1416,7 +1416,7 @@ static uint32_t mpic_src_ext_read (void *opaque, target_phys_addr_t addr) return retval; } -static void mpic_src_int_write (void *opaque, target_phys_addr_t addr, +static void mpic_src_int_write (void *opaque, hwaddr addr, uint32_t val) { openpic_t *mpp = opaque; @@ -1438,7 +1438,7 @@ static void mpic_src_int_write (void *opaque, target_phys_addr_t addr, } } -static uint32_t mpic_src_int_read (void *opaque, target_phys_addr_t addr) +static uint32_t mpic_src_int_read (void *opaque, hwaddr addr) { openpic_t *mpp = opaque; uint32_t retval; @@ -1464,7 +1464,7 @@ static uint32_t mpic_src_int_read (void *opaque, target_phys_addr_t addr) return retval; } -static void mpic_src_msg_write (void *opaque, target_phys_addr_t addr, +static void mpic_src_msg_write (void *opaque, hwaddr addr, uint32_t val) { openpic_t *mpp = opaque; @@ -1486,7 +1486,7 @@ static void mpic_src_msg_write (void *opaque, target_phys_addr_t addr, } } -static uint32_t mpic_src_msg_read (void *opaque, target_phys_addr_t addr) +static uint32_t mpic_src_msg_read (void *opaque, hwaddr addr) { openpic_t *mpp = opaque; uint32_t retval; @@ -1512,7 +1512,7 @@ static uint32_t mpic_src_msg_read (void *opaque, target_phys_addr_t addr) return retval; } -static void mpic_src_msi_write (void *opaque, target_phys_addr_t addr, +static void mpic_src_msi_write (void *opaque, hwaddr addr, uint32_t val) { openpic_t *mpp = opaque; @@ -1533,7 +1533,7 @@ static void mpic_src_msi_write (void *opaque, target_phys_addr_t addr, } } } -static uint32_t mpic_src_msi_read (void *opaque, target_phys_addr_t addr) +static uint32_t mpic_src_msi_read (void *opaque, hwaddr addr) { openpic_t *mpp = opaque; uint32_t retval; @@ -1657,7 +1657,7 @@ static const MemoryRegionOps mpic_msi_ops = { .endianness = DEVICE_BIG_ENDIAN, }; -qemu_irq *mpic_init (MemoryRegion *address_space, target_phys_addr_t base, +qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, int nb_cpus, qemu_irq **irqs, qemu_irq irq_out) { openpic_t *mpp; @@ -1665,7 +1665,7 @@ qemu_irq *mpic_init (MemoryRegion *address_space, target_phys_addr_t base, struct { const char *name; MemoryRegionOps const *ops; - target_phys_addr_t start_addr; + hwaddr start_addr; ram_addr_t size; } const list[] = { {"glb", &mpic_glb_ops, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE}, diff --git a/hw/openpic.h b/hw/openpic.h index 855603026b..f50a1e42bd 100644 --- a/hw/openpic.h +++ b/hw/openpic.h @@ -13,6 +13,6 @@ enum { qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, qemu_irq **irqs, qemu_irq irq_out); -qemu_irq *mpic_init (MemoryRegion *address_space, target_phys_addr_t base, +qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, int nb_cpus, qemu_irq **irqs, qemu_irq irq_out); #endif /* __OPENPIC_H__ */ diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c index 7327740764..23c66df1fb 100644 --- a/hw/openrisc_sim.c +++ b/hw/openrisc_sim.c @@ -39,8 +39,8 @@ static void main_cpu_reset(void *opaque) } static void openrisc_sim_net_init(MemoryRegion *address_space, - target_phys_addr_t base, - target_phys_addr_t descriptors, + hwaddr base, + hwaddr descriptors, qemu_irq irq, NICInfo *nd) { DeviceState *dev; @@ -64,7 +64,7 @@ static void cpu_openrisc_load_kernel(ram_addr_t ram_size, { long kernel_size; uint64_t elf_entry; - target_phys_addr_t entry; + hwaddr entry; if (kernel_filename && !qtest_enabled()) { kernel_size = load_elf(kernel_filename, NULL, NULL, diff --git a/hw/palm.c b/hw/palm.c index 032b8d6510..d26305159d 100644 --- a/hw/palm.c +++ b/hw/palm.c @@ -27,25 +27,25 @@ #include "loader.h" #include "exec-memory.h" -static uint32_t static_readb(void *opaque, target_phys_addr_t offset) +static uint32_t static_readb(void *opaque, hwaddr offset) { uint32_t *val = (uint32_t *) opaque; return *val >> ((offset & 3) << 3); } -static uint32_t static_readh(void *opaque, target_phys_addr_t offset) +static uint32_t static_readh(void *opaque, hwaddr offset) { uint32_t *val = (uint32_t *) opaque; return *val >> ((offset & 1) << 3); } -static uint32_t static_readw(void *opaque, target_phys_addr_t offset) +static uint32_t static_readw(void *opaque, hwaddr offset) { uint32_t *val = (uint32_t *) opaque; return *val >> ((offset & 0) << 3); } -static void static_write(void *opaque, target_phys_addr_t offset, +static void static_write(void *opaque, hwaddr offset, uint32_t value) { #ifdef SPY diff --git a/hw/parallel.c b/hw/parallel.c index 219f38436f..c4705bc89d 100644 --- a/hw/parallel.c +++ b/hw/parallel.c @@ -511,7 +511,7 @@ static int parallel_isa_initfn(ISADevice *dev) } /* Memory mapped interface */ -static uint32_t parallel_mm_readb (void *opaque, target_phys_addr_t addr) +static uint32_t parallel_mm_readb (void *opaque, hwaddr addr) { ParallelState *s = opaque; @@ -519,14 +519,14 @@ static uint32_t parallel_mm_readb (void *opaque, target_phys_addr_t addr) } static void parallel_mm_writeb (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { ParallelState *s = opaque; parallel_ioport_write_sw(s, addr >> s->it_shift, value & 0xFF); } -static uint32_t parallel_mm_readw (void *opaque, target_phys_addr_t addr) +static uint32_t parallel_mm_readw (void *opaque, hwaddr addr) { ParallelState *s = opaque; @@ -534,14 +534,14 @@ static uint32_t parallel_mm_readw (void *opaque, target_phys_addr_t addr) } static void parallel_mm_writew (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { ParallelState *s = opaque; parallel_ioport_write_sw(s, addr >> s->it_shift, value & 0xFFFF); } -static uint32_t parallel_mm_readl (void *opaque, target_phys_addr_t addr) +static uint32_t parallel_mm_readl (void *opaque, hwaddr addr) { ParallelState *s = opaque; @@ -549,7 +549,7 @@ static uint32_t parallel_mm_readl (void *opaque, target_phys_addr_t addr) } static void parallel_mm_writel (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { ParallelState *s = opaque; @@ -566,7 +566,7 @@ static const MemoryRegionOps parallel_mm_ops = { /* If fd is zero, it means that the parallel device uses the console */ bool parallel_mm_init(MemoryRegion *address_space, - target_phys_addr_t base, int it_shift, qemu_irq irq, + hwaddr base, int it_shift, qemu_irq irq, CharDriverState *chr) { ParallelState *s; diff --git a/hw/pc.c b/hw/pc.c index 805e8cabcf..16de04c4b7 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -638,13 +638,13 @@ static void load_linux(void *fw_cfg, const char *kernel_filename, const char *initrd_filename, const char *kernel_cmdline, - target_phys_addr_t max_ram_size) + hwaddr max_ram_size) { uint16_t protocol; int setup_size, kernel_size, initrd_size = 0, cmdline_size; uint32_t initrd_max; uint8_t header[8192], *setup, *kernel, *initrd_data; - target_phys_addr_t real_addr, prot_addr, cmdline_addr, initrd_addr = 0; + hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0; FILE *f; char *vmode; diff --git a/hw/pc.h b/hw/pc.h index 6cba7ce7d6..e7993ca5d9 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -30,7 +30,7 @@ static inline bool parallel_init(ISABus *bus, int index, CharDriverState *chr) } bool parallel_mm_init(MemoryRegion *address_space, - target_phys_addr_t base, int it_shift, qemu_irq irq, + hwaddr base, int it_shift, qemu_irq irq, CharDriverState *chr); /* i8259.c */ @@ -68,7 +68,7 @@ void vmmouse_set_data(const uint32_t *data); void i8042_init(qemu_irq kbd_irq, qemu_irq mouse_irq, uint32_t io_base); void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, MemoryRegion *region, ram_addr_t size, - target_phys_addr_t mask); + hwaddr mask); void i8042_isa_mouse_fake_event(void *opaque); void i8042_setup_a20_line(ISADevice *dev, qemu_irq *a20_out); @@ -130,10 +130,10 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, MemoryRegion *address_space_mem, MemoryRegion *address_space_io, ram_addr_t ram_size, - target_phys_addr_t pci_hole_start, - target_phys_addr_t pci_hole_size, - target_phys_addr_t pci_hole64_start, - target_phys_addr_t pci_hole64_size, + hwaddr pci_hole_start, + hwaddr pci_hole_size, + hwaddr pci_hole64_start, + hwaddr pci_hole64_size, MemoryRegion *pci_memory, MemoryRegion *ram_memory); @@ -149,8 +149,8 @@ enum vga_retrace_method { extern enum vga_retrace_method vga_retrace_method; -int isa_vga_mm_init(target_phys_addr_t vram_base, - target_phys_addr_t ctrl_base, int it_shift, +int isa_vga_mm_init(hwaddr vram_base, + hwaddr ctrl_base, int it_shift, MemoryRegion *address_space); /* ne2000.c */ diff --git a/hw/pc_piix.c b/hw/pc_piix.c index bf04a42da5..47ebc1ac04 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -195,7 +195,7 @@ static void pc_init1(MemoryRegion *system_memory, below_4g_mem_size, 0x100000000ULL - below_4g_mem_size, 0x100000000ULL + above_4g_mem_size, - (sizeof(target_phys_addr_t) == 4 + (sizeof(hwaddr) == 4 ? 0 : ((uint64_t)1 << 62)), pci_memory, ram_memory); diff --git a/hw/pc_sysfw.c b/hw/pc_sysfw.c index b45f0acc7d..9d7c5f4003 100644 --- a/hw/pc_sysfw.c +++ b/hw/pc_sysfw.c @@ -106,7 +106,7 @@ static void pc_system_flash_init(MemoryRegion *rom_memory, { BlockDriverState *bdrv; int64_t size; - target_phys_addr_t phys_addr; + hwaddr phys_addr; int sector_bits, sector_size; pflash_t *system_flash; MemoryRegion *flash_mem; diff --git a/hw/pci.c b/hw/pci.c index 7eeaac0d3d..d44fd0e10a 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -987,7 +987,7 @@ static pcibus_t pci_bar_address(PCIDevice *d, * to >4G. Check it. TODO: we might need to support * it in the future for e.g. PAE. */ - if (last_addr >= TARGET_PHYS_ADDR_MAX) { + if (last_addr >= HWADDR_MAX) { return PCI_BAR_UNMAPPED; } diff --git a/hw/pci_host.c b/hw/pci_host.c index 3950e943c0..68e328cd23 100644 --- a/hw/pci_host.c +++ b/hw/pci_host.c @@ -94,7 +94,7 @@ uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len) return val; } -static void pci_host_config_write(void *opaque, target_phys_addr_t addr, +static void pci_host_config_write(void *opaque, hwaddr addr, uint64_t val, unsigned len) { PCIHostState *s = opaque; @@ -107,7 +107,7 @@ static void pci_host_config_write(void *opaque, target_phys_addr_t addr, s->config_reg = val; } -static uint64_t pci_host_config_read(void *opaque, target_phys_addr_t addr, +static uint64_t pci_host_config_read(void *opaque, hwaddr addr, unsigned len) { PCIHostState *s = opaque; @@ -118,7 +118,7 @@ static uint64_t pci_host_config_read(void *opaque, target_phys_addr_t addr, return val; } -static void pci_host_data_write(void *opaque, target_phys_addr_t addr, +static void pci_host_data_write(void *opaque, hwaddr addr, uint64_t val, unsigned len) { PCIHostState *s = opaque; @@ -129,7 +129,7 @@ static void pci_host_data_write(void *opaque, target_phys_addr_t addr, } static uint64_t pci_host_data_read(void *opaque, - target_phys_addr_t addr, unsigned len) + hwaddr addr, unsigned len) { PCIHostState *s = opaque; uint32_t val; diff --git a/hw/pcie_host.c b/hw/pcie_host.c index 28bbe72b37..9f7f3d3b1e 100644 --- a/hw/pcie_host.c +++ b/hw/pcie_host.c @@ -53,7 +53,7 @@ static inline PCIDevice *pcie_dev_find_by_mmcfg_addr(PCIBus *s, PCIE_MMCFG_DEVFN(mmcfg_addr)); } -static void pcie_mmcfg_data_write(void *opaque, target_phys_addr_t mmcfg_addr, +static void pcie_mmcfg_data_write(void *opaque, hwaddr mmcfg_addr, uint64_t val, unsigned len) { PCIExpressHost *e = opaque; @@ -76,7 +76,7 @@ static void pcie_mmcfg_data_write(void *opaque, target_phys_addr_t mmcfg_addr, } static uint64_t pcie_mmcfg_data_read(void *opaque, - target_phys_addr_t mmcfg_addr, + hwaddr mmcfg_addr, unsigned len) { PCIExpressHost *e = opaque; @@ -105,7 +105,7 @@ static const MemoryRegionOps pcie_mmcfg_ops = { }; /* pcie_host::base_addr == PCIE_BASE_ADDR_UNMAPPED when it isn't mapped. */ -#define PCIE_BASE_ADDR_UNMAPPED ((target_phys_addr_t)-1ULL) +#define PCIE_BASE_ADDR_UNMAPPED ((hwaddr)-1ULL) int pcie_host_init(PCIExpressHost *e, uint32_t size) { @@ -127,7 +127,7 @@ void pcie_host_mmcfg_unmap(PCIExpressHost *e) } } -void pcie_host_mmcfg_map(PCIExpressHost *e, target_phys_addr_t addr) +void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr) { e->base_addr = addr; memory_region_add_subregion(get_system_memory(), e->base_addr, &e->mmio); @@ -135,7 +135,7 @@ void pcie_host_mmcfg_map(PCIExpressHost *e, target_phys_addr_t addr) void pcie_host_mmcfg_update(PCIExpressHost *e, int enable, - target_phys_addr_t addr) + hwaddr addr) { pcie_host_mmcfg_unmap(e); if (enable) { diff --git a/hw/pcie_host.h b/hw/pcie_host.h index 0074508b43..9978b9f2f1 100644 --- a/hw/pcie_host.h +++ b/hw/pcie_host.h @@ -30,10 +30,10 @@ struct PCIExpressHost { /* express part */ /* base address where MMCONFIG area is mapped. */ - target_phys_addr_t base_addr; + hwaddr base_addr; /* the size of MMCONFIG area. It's host bridge dependent */ - target_phys_addr_t size; + hwaddr size; /* MMCONFIG mmio area */ MemoryRegion mmio; @@ -41,9 +41,9 @@ struct PCIExpressHost { int pcie_host_init(PCIExpressHost *e, uint32_t size); void pcie_host_mmcfg_unmap(PCIExpressHost *e); -void pcie_host_mmcfg_map(PCIExpressHost *e, target_phys_addr_t addr); +void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr); void pcie_host_mmcfg_update(PCIExpressHost *e, int enable, - target_phys_addr_t addr); + hwaddr addr); #endif /* PCIE_HOST_H */ diff --git a/hw/pckbd.c b/hw/pckbd.c index 69857bade9..000c7f00fd 100644 --- a/hw/pckbd.c +++ b/hw/pckbd.c @@ -139,7 +139,7 @@ typedef struct KBDState { qemu_irq irq_kbd; qemu_irq irq_mouse; qemu_irq *a20_out; - target_phys_addr_t mask; + hwaddr mask; } KBDState; /* update irq and KBD_STAT_[MOUSE_]OBF */ @@ -380,7 +380,7 @@ static const VMStateDescription vmstate_kbd = { }; /* Memory mapped interface */ -static uint32_t kbd_mm_readb (void *opaque, target_phys_addr_t addr) +static uint32_t kbd_mm_readb (void *opaque, hwaddr addr) { KBDState *s = opaque; @@ -390,7 +390,7 @@ static uint32_t kbd_mm_readb (void *opaque, target_phys_addr_t addr) return kbd_read_data(s, 0) & 0xff; } -static void kbd_mm_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) +static void kbd_mm_writeb (void *opaque, hwaddr addr, uint32_t value) { KBDState *s = opaque; @@ -410,7 +410,7 @@ static const MemoryRegionOps i8042_mmio_ops = { void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, MemoryRegion *region, ram_addr_t size, - target_phys_addr_t mask) + hwaddr mask) { KBDState *s = g_malloc0(sizeof(KBDState)); diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c index 48fd447996..0bf438ffee 100644 --- a/hw/pcnet-pci.c +++ b/hw/pcnet-pci.c @@ -71,7 +71,7 @@ static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr) return val; } -static uint64_t pcnet_ioport_read(void *opaque, target_phys_addr_t addr, +static uint64_t pcnet_ioport_read(void *opaque, hwaddr addr, unsigned size) { PCNetState *d = opaque; @@ -98,7 +98,7 @@ static uint64_t pcnet_ioport_read(void *opaque, target_phys_addr_t addr, return ((uint64_t)1 << (size * 8)) - 1; } -static void pcnet_ioport_write(void *opaque, target_phys_addr_t addr, +static void pcnet_ioport_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { PCNetState *d = opaque; @@ -130,7 +130,7 @@ static const MemoryRegionOps pcnet_io_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +static void pcnet_mmio_writeb(void *opaque, hwaddr addr, uint32_t val) { PCNetState *d = opaque; #ifdef PCNET_DEBUG_IO @@ -141,7 +141,7 @@ static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t va pcnet_aprom_writeb(d, addr & 0x0f, val); } -static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr) +static uint32_t pcnet_mmio_readb(void *opaque, hwaddr addr) { PCNetState *d = opaque; uint32_t val = -1; @@ -154,7 +154,7 @@ static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr) return val; } -static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +static void pcnet_mmio_writew(void *opaque, hwaddr addr, uint32_t val) { PCNetState *d = opaque; #ifdef PCNET_DEBUG_IO @@ -170,7 +170,7 @@ static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t va } } -static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr) +static uint32_t pcnet_mmio_readw(void *opaque, hwaddr addr) { PCNetState *d = opaque; uint32_t val = -1; @@ -189,7 +189,7 @@ static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr) return val; } -static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +static void pcnet_mmio_writel(void *opaque, hwaddr addr, uint32_t val) { PCNetState *d = opaque; #ifdef PCNET_DEBUG_IO @@ -207,7 +207,7 @@ static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t va } } -static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr) +static uint32_t pcnet_mmio_readl(void *opaque, hwaddr addr) { PCNetState *d = opaque; uint32_t val; @@ -252,13 +252,13 @@ static const MemoryRegionOps pcnet_mmio_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr, +static void pci_physical_memory_write(void *dma_opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap) { pci_dma_write(dma_opaque, addr, buf, len); } -static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr, +static void pci_physical_memory_read(void *dma_opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap) { pci_dma_read(dma_opaque, addr, buf, len); diff --git a/hw/pcnet.c b/hw/pcnet.c index 40820b3632..54eecd01d3 100644 --- a/hw/pcnet.c +++ b/hw/pcnet.c @@ -293,7 +293,7 @@ struct pcnet_RMD { GET_FIELD((R)->msg_length, RMDM, ZEROS)) static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd, - target_phys_addr_t addr) + hwaddr addr) { if (!BCR_SSIZE32(s)) { struct { @@ -323,7 +323,7 @@ static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd, } static inline void pcnet_tmd_store(PCNetState *s, const struct pcnet_TMD *tmd, - target_phys_addr_t addr) + hwaddr addr) { if (!BCR_SSIZE32(s)) { struct { @@ -359,7 +359,7 @@ static inline void pcnet_tmd_store(PCNetState *s, const struct pcnet_TMD *tmd, } static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd, - target_phys_addr_t addr) + hwaddr addr) { if (!BCR_SSIZE32(s)) { struct { @@ -389,7 +389,7 @@ static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd, } static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, - target_phys_addr_t addr) + hwaddr addr) { if (!BCR_SSIZE32(s)) { struct { @@ -660,7 +660,7 @@ static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size) return 0; } -static inline target_phys_addr_t pcnet_rdra_addr(PCNetState *s, int idx) +static inline hwaddr pcnet_rdra_addr(PCNetState *s, int idx) { while (idx < 1) idx += CSR_RCVRL(s); return s->rdra + ((CSR_RCVRL(s) - idx) * (BCR_SWSTYLE(s) ? 16 : 8)); @@ -898,19 +898,19 @@ static void pcnet_rdte_poll(PCNetState *s) if (s->rdra) { int bad = 0; #if 1 - target_phys_addr_t crda = pcnet_rdra_addr(s, CSR_RCVRC(s)); - target_phys_addr_t nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s)); - target_phys_addr_t nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s)); + hwaddr crda = pcnet_rdra_addr(s, CSR_RCVRC(s)); + hwaddr nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s)); + hwaddr nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s)); #else - target_phys_addr_t crda = s->rdra + + hwaddr crda = s->rdra + (CSR_RCVRL(s) - CSR_RCVRC(s)) * (BCR_SWSTYLE(s) ? 16 : 8 ); int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1; - target_phys_addr_t nrda = s->rdra + + hwaddr nrda = s->rdra + (CSR_RCVRL(s) - nrdc) * (BCR_SWSTYLE(s) ? 16 : 8 ); int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1; - target_phys_addr_t nnrd = s->rdra + + hwaddr nnrd = s->rdra + (CSR_RCVRL(s) - nnrc) * (BCR_SWSTYLE(s) ? 16 : 8 ); #endif @@ -970,7 +970,7 @@ static int pcnet_tdte_poll(PCNetState *s) { s->csr[34] = s->csr[35] = 0; if (s->tdra) { - target_phys_addr_t cxda = s->tdra + + hwaddr cxda = s->tdra + (CSR_XMTRL(s) - CSR_XMTRC(s)) * (BCR_SWSTYLE(s) ? 16 : 8); int bad = 0; @@ -1050,7 +1050,7 @@ ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_) if (!(CSR_CRST(s) & 0x8000) && s->rdra) { struct pcnet_RMD rmd; int rcvrc = CSR_RCVRC(s)-1,i; - target_phys_addr_t nrda; + hwaddr nrda; for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) { if (rcvrc <= 1) rcvrc = CSR_RCVRL(s); @@ -1078,7 +1078,7 @@ ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_) CSR_MISSC(s)++; } else { uint8_t *src = s->buffer; - target_phys_addr_t crda = CSR_CRDA(s); + hwaddr crda = CSR_CRDA(s); struct pcnet_RMD rmd; int pktcount = 0; @@ -1118,7 +1118,7 @@ ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_) #define PCNET_RECV_STORE() do { \ int count = MIN(4096 - GET_FIELD(rmd.buf_length, RMDL, BCNT),remaining); \ - target_phys_addr_t rbadr = PHYSADDR(s, rmd.rbadr); \ + hwaddr rbadr = PHYSADDR(s, rmd.rbadr); \ s->phys_mem_write(s->dma_opaque, rbadr, src, count, CSR_BSWP(s)); \ src += count; remaining -= count; \ SET_FIELD(&rmd.status, RMDS, OWN, 0); \ @@ -1129,7 +1129,7 @@ ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_) remaining = size; PCNET_RECV_STORE(); if ((remaining > 0) && CSR_NRDA(s)) { - target_phys_addr_t nrda = CSR_NRDA(s); + hwaddr nrda = CSR_NRDA(s); #ifdef PCNET_DEBUG_RMD PRINT_RMD(&rmd); #endif @@ -1206,7 +1206,7 @@ void pcnet_set_link_status(NetClientState *nc) static void pcnet_transmit(PCNetState *s) { - target_phys_addr_t xmit_cxda = 0; + hwaddr xmit_cxda = 0; int count = CSR_XMTRL(s)-1; int add_crc = 0; diff --git a/hw/pcnet.h b/hw/pcnet.h index d0af54a46a..da8c3bde7b 100644 --- a/hw/pcnet.h +++ b/hw/pcnet.h @@ -42,9 +42,9 @@ struct PCNetState_st { MemoryRegion mmio; uint8_t buffer[4096]; qemu_irq irq; - void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr, + void (*phys_mem_read)(void *dma_opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap); - void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr, + void (*phys_mem_write)(void *dma_opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap); void *dma_opaque; int tx_busy; diff --git a/hw/pcspk.c b/hw/pcspk.c index e4303247d4..ad6491b0f4 100644 --- a/hw/pcspk.c +++ b/hw/pcspk.c @@ -121,7 +121,7 @@ int pcspk_audio_init(ISABus *bus) return 0; } -static uint64_t pcspk_io_read(void *opaque, target_phys_addr_t addr, +static uint64_t pcspk_io_read(void *opaque, hwaddr addr, unsigned size) { PCSpkState *s = opaque; @@ -135,7 +135,7 @@ static uint64_t pcspk_io_read(void *opaque, target_phys_addr_t addr, (ch.out << 5); } -static void pcspk_io_write(void *opaque, target_phys_addr_t addr, uint64_t val, +static void pcspk_io_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { PCSpkState *s = opaque; diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c index 5b45809d74..3589a4bc7f 100644 --- a/hw/petalogix_ml605_mmu.c +++ b/hw/petalogix_ml605_mmu.c @@ -84,7 +84,7 @@ petalogix_ml605_init(QEMUMachineInitArgs *args) CPUMBState *env; DriveInfo *dinfo; int i; - target_phys_addr_t ddr_base = MEMORY_BASEADDR; + hwaddr ddr_base = MEMORY_BASEADDR; MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1); MemoryRegion *phys_ram = g_new(MemoryRegion, 1); qemu_irq irq[32], *cpu_irq; diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c index 71c32ce889..c5fd5e793a 100644 --- a/hw/petalogix_s3adsp1800_mmu.c +++ b/hw/petalogix_s3adsp1800_mmu.c @@ -66,7 +66,7 @@ petalogix_s3adsp1800_init(QEMUMachineInitArgs *args) CPUMBState *env; DriveInfo *dinfo; int i; - target_phys_addr_t ddr_base = MEMORY_BASEADDR; + hwaddr ddr_base = MEMORY_BASEADDR; MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1); MemoryRegion *phys_ram = g_new(MemoryRegion, 1); qemu_irq irq[32], *cpu_irq; diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index 3b437da9c3..5e3a409c2b 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -61,9 +61,9 @@ do { \ struct pflash_t { BlockDriverState *bs; - target_phys_addr_t base; - target_phys_addr_t sector_len; - target_phys_addr_t total_len; + hwaddr base; + hwaddr sector_len; + hwaddr total_len; int width; int wcycle; /* if 0, the flash is read normally */ int bypass; @@ -73,7 +73,7 @@ struct pflash_t { uint16_t ident[4]; uint8_t cfi_len; uint8_t cfi_table[0x52]; - target_phys_addr_t counter; + hwaddr counter; unsigned int writeblock_size; QEMUTimer *timer; MemoryRegion mem; @@ -96,10 +96,10 @@ static void pflash_timer (void *opaque) pfl->cmd = 0; } -static uint32_t pflash_read (pflash_t *pfl, target_phys_addr_t offset, +static uint32_t pflash_read (pflash_t *pfl, hwaddr offset, int width, int be) { - target_phys_addr_t boff; + hwaddr boff; uint32_t ret; uint8_t *p; @@ -211,7 +211,7 @@ static void pflash_update(pflash_t *pfl, int offset, } } -static inline void pflash_data_write(pflash_t *pfl, target_phys_addr_t offset, +static inline void pflash_data_write(pflash_t *pfl, hwaddr offset, uint32_t value, int width, int be) { uint8_t *p = pfl->storage; @@ -249,7 +249,7 @@ static inline void pflash_data_write(pflash_t *pfl, target_phys_addr_t offset, } -static void pflash_write(pflash_t *pfl, target_phys_addr_t offset, +static void pflash_write(pflash_t *pfl, hwaddr offset, uint32_t value, int width, int be) { uint8_t *p; @@ -389,7 +389,7 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset, pfl->status |= 0x80; if (!pfl->counter) { - target_phys_addr_t mask = pfl->writeblock_size - 1; + hwaddr mask = pfl->writeblock_size - 1; mask = ~mask; DPRINTF("%s: block write finished\n", __func__); @@ -445,57 +445,57 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset, } -static uint32_t pflash_readb_be(void *opaque, target_phys_addr_t addr) +static uint32_t pflash_readb_be(void *opaque, hwaddr addr) { return pflash_read(opaque, addr, 1, 1); } -static uint32_t pflash_readb_le(void *opaque, target_phys_addr_t addr) +static uint32_t pflash_readb_le(void *opaque, hwaddr addr) { return pflash_read(opaque, addr, 1, 0); } -static uint32_t pflash_readw_be(void *opaque, target_phys_addr_t addr) +static uint32_t pflash_readw_be(void *opaque, hwaddr addr) { pflash_t *pfl = opaque; return pflash_read(pfl, addr, 2, 1); } -static uint32_t pflash_readw_le(void *opaque, target_phys_addr_t addr) +static uint32_t pflash_readw_le(void *opaque, hwaddr addr) { pflash_t *pfl = opaque; return pflash_read(pfl, addr, 2, 0); } -static uint32_t pflash_readl_be(void *opaque, target_phys_addr_t addr) +static uint32_t pflash_readl_be(void *opaque, hwaddr addr) { pflash_t *pfl = opaque; return pflash_read(pfl, addr, 4, 1); } -static uint32_t pflash_readl_le(void *opaque, target_phys_addr_t addr) +static uint32_t pflash_readl_le(void *opaque, hwaddr addr) { pflash_t *pfl = opaque; return pflash_read(pfl, addr, 4, 0); } -static void pflash_writeb_be(void *opaque, target_phys_addr_t addr, +static void pflash_writeb_be(void *opaque, hwaddr addr, uint32_t value) { pflash_write(opaque, addr, value, 1, 1); } -static void pflash_writeb_le(void *opaque, target_phys_addr_t addr, +static void pflash_writeb_le(void *opaque, hwaddr addr, uint32_t value) { pflash_write(opaque, addr, value, 1, 0); } -static void pflash_writew_be(void *opaque, target_phys_addr_t addr, +static void pflash_writew_be(void *opaque, hwaddr addr, uint32_t value) { pflash_t *pfl = opaque; @@ -503,7 +503,7 @@ static void pflash_writew_be(void *opaque, target_phys_addr_t addr, pflash_write(pfl, addr, value, 2, 1); } -static void pflash_writew_le(void *opaque, target_phys_addr_t addr, +static void pflash_writew_le(void *opaque, hwaddr addr, uint32_t value) { pflash_t *pfl = opaque; @@ -511,7 +511,7 @@ static void pflash_writew_le(void *opaque, target_phys_addr_t addr, pflash_write(pfl, addr, value, 2, 0); } -static void pflash_writel_be(void *opaque, target_phys_addr_t addr, +static void pflash_writel_be(void *opaque, hwaddr addr, uint32_t value) { pflash_t *pfl = opaque; @@ -519,7 +519,7 @@ static void pflash_writel_be(void *opaque, target_phys_addr_t addr, pflash_write(pfl, addr, value, 4, 1); } -static void pflash_writel_le(void *opaque, target_phys_addr_t addr, +static void pflash_writel_le(void *opaque, hwaddr addr, uint32_t value) { pflash_t *pfl = opaque; @@ -543,16 +543,16 @@ static const MemoryRegionOps pflash_cfi01_ops_le = { .endianness = DEVICE_NATIVE_ENDIAN, }; -pflash_t *pflash_cfi01_register(target_phys_addr_t base, +pflash_t *pflash_cfi01_register(hwaddr base, DeviceState *qdev, const char *name, - target_phys_addr_t size, + hwaddr size, BlockDriverState *bs, uint32_t sector_len, int nb_blocs, int width, uint16_t id0, uint16_t id1, uint16_t id2, uint16_t id3, int be) { pflash_t *pfl; - target_phys_addr_t total_len; + hwaddr total_len; int ret; total_len = sector_len * nb_blocs; diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c index 39337ec304..9f94c0623d 100644 --- a/hw/pflash_cfi02.c +++ b/hw/pflash_cfi02.c @@ -56,7 +56,7 @@ do { \ struct pflash_t { BlockDriverState *bs; - target_phys_addr_t base; + hwaddr base; uint32_t sector_len; uint32_t chip_len; int mappings; @@ -89,7 +89,7 @@ struct pflash_t { static void pflash_setup_mappings(pflash_t *pfl) { unsigned i; - target_phys_addr_t size = memory_region_size(&pfl->orig_mem); + hwaddr size = memory_region_size(&pfl->orig_mem); memory_region_init(&pfl->mem, "pflash", pfl->mappings * size); pfl->mem_mappings = g_new(MemoryRegion, pfl->mappings); @@ -122,10 +122,10 @@ static void pflash_timer (void *opaque) pfl->cmd = 0; } -static uint32_t pflash_read (pflash_t *pfl, target_phys_addr_t offset, +static uint32_t pflash_read (pflash_t *pfl, hwaddr offset, int width, int be) { - target_phys_addr_t boff; + hwaddr boff; uint32_t ret; uint8_t *p; @@ -242,10 +242,10 @@ static void pflash_update(pflash_t *pfl, int offset, } } -static void pflash_write (pflash_t *pfl, target_phys_addr_t offset, +static void pflash_write (pflash_t *pfl, hwaddr offset, uint32_t value, int width, int be) { - target_phys_addr_t boff; + hwaddr boff; uint8_t *p; uint8_t cmd; @@ -477,57 +477,57 @@ static void pflash_write (pflash_t *pfl, target_phys_addr_t offset, } -static uint32_t pflash_readb_be(void *opaque, target_phys_addr_t addr) +static uint32_t pflash_readb_be(void *opaque, hwaddr addr) { return pflash_read(opaque, addr, 1, 1); } -static uint32_t pflash_readb_le(void *opaque, target_phys_addr_t addr) +static uint32_t pflash_readb_le(void *opaque, hwaddr addr) { return pflash_read(opaque, addr, 1, 0); } -static uint32_t pflash_readw_be(void *opaque, target_phys_addr_t addr) +static uint32_t pflash_readw_be(void *opaque, hwaddr addr) { pflash_t *pfl = opaque; return pflash_read(pfl, addr, 2, 1); } -static uint32_t pflash_readw_le(void *opaque, target_phys_addr_t addr) +static uint32_t pflash_readw_le(void *opaque, hwaddr addr) { pflash_t *pfl = opaque; return pflash_read(pfl, addr, 2, 0); } -static uint32_t pflash_readl_be(void *opaque, target_phys_addr_t addr) +static uint32_t pflash_readl_be(void *opaque, hwaddr addr) { pflash_t *pfl = opaque; return pflash_read(pfl, addr, 4, 1); } -static uint32_t pflash_readl_le(void *opaque, target_phys_addr_t addr) +static uint32_t pflash_readl_le(void *opaque, hwaddr addr) { pflash_t *pfl = opaque; return pflash_read(pfl, addr, 4, 0); } -static void pflash_writeb_be(void *opaque, target_phys_addr_t addr, +static void pflash_writeb_be(void *opaque, hwaddr addr, uint32_t value) { pflash_write(opaque, addr, value, 1, 1); } -static void pflash_writeb_le(void *opaque, target_phys_addr_t addr, +static void pflash_writeb_le(void *opaque, hwaddr addr, uint32_t value) { pflash_write(opaque, addr, value, 1, 0); } -static void pflash_writew_be(void *opaque, target_phys_addr_t addr, +static void pflash_writew_be(void *opaque, hwaddr addr, uint32_t value) { pflash_t *pfl = opaque; @@ -535,7 +535,7 @@ static void pflash_writew_be(void *opaque, target_phys_addr_t addr, pflash_write(pfl, addr, value, 2, 1); } -static void pflash_writew_le(void *opaque, target_phys_addr_t addr, +static void pflash_writew_le(void *opaque, hwaddr addr, uint32_t value) { pflash_t *pfl = opaque; @@ -543,7 +543,7 @@ static void pflash_writew_le(void *opaque, target_phys_addr_t addr, pflash_write(pfl, addr, value, 2, 0); } -static void pflash_writel_be(void *opaque, target_phys_addr_t addr, +static void pflash_writel_be(void *opaque, hwaddr addr, uint32_t value) { pflash_t *pfl = opaque; @@ -551,7 +551,7 @@ static void pflash_writel_be(void *opaque, target_phys_addr_t addr, pflash_write(pfl, addr, value, 4, 1); } -static void pflash_writel_le(void *opaque, target_phys_addr_t addr, +static void pflash_writel_le(void *opaque, hwaddr addr, uint32_t value) { pflash_t *pfl = opaque; @@ -575,9 +575,9 @@ static const MemoryRegionOps pflash_cfi02_ops_le = { .endianness = DEVICE_NATIVE_ENDIAN, }; -pflash_t *pflash_cfi02_register(target_phys_addr_t base, +pflash_t *pflash_cfi02_register(hwaddr base, DeviceState *qdev, const char *name, - target_phys_addr_t size, + hwaddr size, BlockDriverState *bs, uint32_t sector_len, int nb_blocs, int nb_mappings, int width, uint16_t id0, uint16_t id1, diff --git a/hw/piix_pci.c b/hw/piix_pci.c index 5bca41d67b..9af5847690 100644 --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@ -255,10 +255,10 @@ static PCIBus *i440fx_common_init(const char *device_name, MemoryRegion *address_space_mem, MemoryRegion *address_space_io, ram_addr_t ram_size, - target_phys_addr_t pci_hole_start, - target_phys_addr_t pci_hole_size, - target_phys_addr_t pci_hole64_start, - target_phys_addr_t pci_hole64_size, + hwaddr pci_hole_start, + hwaddr pci_hole_size, + hwaddr pci_hole64_start, + hwaddr pci_hole64_size, MemoryRegion *pci_address_space, MemoryRegion *ram_memory) { @@ -342,10 +342,10 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, MemoryRegion *address_space_mem, MemoryRegion *address_space_io, ram_addr_t ram_size, - target_phys_addr_t pci_hole_start, - target_phys_addr_t pci_hole_size, - target_phys_addr_t pci_hole64_start, - target_phys_addr_t pci_hole64_size, + hwaddr pci_hole_start, + hwaddr pci_hole_size, + hwaddr pci_hole64_start, + hwaddr pci_hole64_size, MemoryRegion *pci_memory, MemoryRegion *ram_memory) { diff --git a/hw/pl011.c b/hw/pl011.c index fb22736b6a..1f7ce2f94c 100644 --- a/hw/pl011.c +++ b/hw/pl011.c @@ -54,7 +54,7 @@ static void pl011_update(pl011_state *s) qemu_set_irq(s->irq, flags != 0); } -static uint64_t pl011_read(void *opaque, target_phys_addr_t offset, +static uint64_t pl011_read(void *opaque, hwaddr offset, unsigned size) { pl011_state *s = (pl011_state *)opaque; @@ -127,7 +127,7 @@ static void pl011_set_read_trigger(pl011_state *s) s->read_trigger = 1; } -static void pl011_write(void *opaque, target_phys_addr_t offset, +static void pl011_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { pl011_state *s = (pl011_state *)opaque; diff --git a/hw/pl022.c b/hw/pl022.c index e2ae315efb..fbd7ded0cf 100644 --- a/hw/pl022.c +++ b/hw/pl022.c @@ -130,7 +130,7 @@ static void pl022_xfer(pl022_state *s) pl022_update(s); } -static uint64_t pl022_read(void *opaque, target_phys_addr_t offset, +static uint64_t pl022_read(void *opaque, hwaddr offset, unsigned size) { pl022_state *s = (pl022_state *)opaque; @@ -174,7 +174,7 @@ static uint64_t pl022_read(void *opaque, target_phys_addr_t offset, } } -static void pl022_write(void *opaque, target_phys_addr_t offset, +static void pl022_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { pl022_state *s = (pl022_state *)opaque; diff --git a/hw/pl031.c b/hw/pl031.c index 6cbaf2386f..8bf0183289 100644 --- a/hw/pl031.c +++ b/hw/pl031.c @@ -95,7 +95,7 @@ static void pl031_set_alarm(pl031_state *s) } } -static uint64_t pl031_read(void *opaque, target_phys_addr_t offset, +static uint64_t pl031_read(void *opaque, hwaddr offset, unsigned size) { pl031_state *s = (pl031_state *)opaque; @@ -133,7 +133,7 @@ static uint64_t pl031_read(void *opaque, target_phys_addr_t offset, return 0; } -static void pl031_write(void * opaque, target_phys_addr_t offset, +static void pl031_write(void * opaque, hwaddr offset, uint64_t value, unsigned size) { pl031_state *s = (pl031_state *)opaque; diff --git a/hw/pl041.c b/hw/pl041.c index 9a6db1b6e2..4436d97c50 100644 --- a/hw/pl041.c +++ b/hw/pl041.c @@ -97,7 +97,7 @@ static const char *pl041_regs_name[] = { #if defined(PL041_DEBUG_LEVEL) -static const char *get_reg_name(target_phys_addr_t offset) +static const char *get_reg_name(hwaddr offset) { if (offset <= PL041_dr1_7) { return pl041_regs_name[offset >> 2]; @@ -327,7 +327,7 @@ static void pl041_request_data(void *opaque) pl041_isr1_update(s); } -static uint64_t pl041_read(void *opaque, target_phys_addr_t offset, +static uint64_t pl041_read(void *opaque, hwaddr offset, unsigned size) { pl041_state *s = (pl041_state *)opaque; @@ -361,7 +361,7 @@ static uint64_t pl041_read(void *opaque, target_phys_addr_t offset, return value; } -static void pl041_write(void *opaque, target_phys_addr_t offset, +static void pl041_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { pl041_state *s = (pl041_state *)opaque; diff --git a/hw/pl050.c b/hw/pl050.c index b13924a160..470572eabb 100644 --- a/hw/pl050.c +++ b/hw/pl050.c @@ -58,7 +58,7 @@ static void pl050_update(void *opaque, int level) qemu_set_irq(s->irq, raise); } -static uint64_t pl050_read(void *opaque, target_phys_addr_t offset, +static uint64_t pl050_read(void *opaque, hwaddr offset, unsigned size) { pl050_state *s = (pl050_state *)opaque; @@ -100,7 +100,7 @@ static uint64_t pl050_read(void *opaque, target_phys_addr_t offset, } } -static void pl050_write(void *opaque, target_phys_addr_t offset, +static void pl050_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { pl050_state *s = (pl050_state *)opaque; diff --git a/hw/pl061.c b/hw/pl061.c index 2aac7e8e9e..7d182e7cdf 100644 --- a/hw/pl061.c +++ b/hw/pl061.c @@ -113,7 +113,7 @@ static void pl061_update(pl061_state *s) /* FIXME: Implement input interrupts. */ } -static uint64_t pl061_read(void *opaque, target_phys_addr_t offset, +static uint64_t pl061_read(void *opaque, hwaddr offset, unsigned size) { pl061_state *s = (pl061_state *)opaque; @@ -169,7 +169,7 @@ static uint64_t pl061_read(void *opaque, target_phys_addr_t offset, } } -static void pl061_write(void *opaque, target_phys_addr_t offset, +static void pl061_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { pl061_state *s = (pl061_state *)opaque; diff --git a/hw/pl080.c b/hw/pl080.c index b3cf651ab7..6abe52857e 100644 --- a/hw/pl080.c +++ b/hw/pl080.c @@ -218,7 +218,7 @@ again: } } -static uint64_t pl080_read(void *opaque, target_phys_addr_t offset, +static uint64_t pl080_read(void *opaque, hwaddr offset, unsigned size) { pl080_state *s = (pl080_state *)opaque; @@ -286,7 +286,7 @@ static uint64_t pl080_read(void *opaque, target_phys_addr_t offset, } } -static void pl080_write(void *opaque, target_phys_addr_t offset, +static void pl080_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { pl080_state *s = (pl080_state *)opaque; diff --git a/hw/pl110.c b/hw/pl110.c index a5826407ab..82486b0c14 100644 --- a/hw/pl110.c +++ b/hw/pl110.c @@ -305,7 +305,7 @@ static void pl110_update(pl110_state *s) /* TODO: Implement interrupts. */ } -static uint64_t pl110_read(void *opaque, target_phys_addr_t offset, +static uint64_t pl110_read(void *opaque, hwaddr offset, unsigned size) { pl110_state *s = (pl110_state *)opaque; @@ -354,7 +354,7 @@ static uint64_t pl110_read(void *opaque, target_phys_addr_t offset, } } -static void pl110_write(void *opaque, target_phys_addr_t offset, +static void pl110_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { pl110_state *s = (pl110_state *)opaque; diff --git a/hw/pl181.c b/hw/pl181.c index 5a734735f0..8a2895ce1b 100644 --- a/hw/pl181.c +++ b/hw/pl181.c @@ -285,7 +285,7 @@ static void pl181_fifo_run(pl181_state *s) } } -static uint64_t pl181_read(void *opaque, target_phys_addr_t offset, +static uint64_t pl181_read(void *opaque, hwaddr offset, unsigned size) { pl181_state *s = (pl181_state *)opaque; @@ -369,7 +369,7 @@ static uint64_t pl181_read(void *opaque, target_phys_addr_t offset, } } -static void pl181_write(void *opaque, target_phys_addr_t offset, +static void pl181_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { pl181_state *s = (pl181_state *)opaque; diff --git a/hw/pl190.c b/hw/pl190.c index 961da5b3af..213229b566 100644 --- a/hw/pl190.c +++ b/hw/pl190.c @@ -85,7 +85,7 @@ static void pl190_update_vectors(pl190_state *s) pl190_update(s); } -static uint64_t pl190_read(void *opaque, target_phys_addr_t offset, +static uint64_t pl190_read(void *opaque, hwaddr offset, unsigned size) { pl190_state *s = (pl190_state *)opaque; @@ -149,7 +149,7 @@ static uint64_t pl190_read(void *opaque, target_phys_addr_t offset, } } -static void pl190_write(void *opaque, target_phys_addr_t offset, +static void pl190_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { pl190_state *s = (pl190_state *)opaque; diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 846f53a8d9..d655e3f46f 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -108,9 +108,9 @@ static void dt_serial_create(void *fdt, unsigned long long offset, static int ppce500_load_device_tree(CPUPPCState *env, PPCE500Params *params, - target_phys_addr_t addr, - target_phys_addr_t initrd_base, - target_phys_addr_t initrd_size) + hwaddr addr, + hwaddr initrd_base, + hwaddr initrd_size) { int ret = -1; uint64_t mem_reg_property[] = { 0, cpu_to_be64(params->ram_size) }; @@ -346,7 +346,7 @@ out: } /* Create -kernel TLB entries for BookE. */ -static inline target_phys_addr_t booke206_page_size_to_tlb(uint64_t size) +static inline hwaddr booke206_page_size_to_tlb(uint64_t size) { return 63 - clz64(size >> 10); } @@ -355,7 +355,7 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env) { struct boot_info *bi = env->load_info; ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0); - target_phys_addr_t size, dt_end; + hwaddr size, dt_end; int ps; /* Our initial TLB entry needs to cover everything from 0 to @@ -412,8 +412,8 @@ void ppce500_init(PPCE500Params *params) CPUPPCState *env = NULL; uint64_t elf_entry; uint64_t elf_lowaddr; - target_phys_addr_t entry=0; - target_phys_addr_t loadaddr=UIMAGE_LOAD_BASE; + hwaddr entry=0; + hwaddr loadaddr=UIMAGE_LOAD_BASE; target_long kernel_size=0; target_ulong dt_base = 0; target_ulong initrd_base = 0; diff --git a/hw/ppc405.h b/hw/ppc405.h index 1f5dc5fd36..535cbfb339 100644 --- a/hw/ppc405.h +++ b/hw/ppc405.h @@ -61,20 +61,20 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd, CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem, MemoryRegion ram_memories[4], - target_phys_addr_t ram_bases[4], - target_phys_addr_t ram_sizes[4], + hwaddr ram_bases[4], + hwaddr ram_sizes[4], uint32_t sysclk, qemu_irq **picp, int do_init); CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem, MemoryRegion ram_memories[2], - target_phys_addr_t ram_bases[2], - target_phys_addr_t ram_sizes[2], + hwaddr ram_bases[2], + hwaddr ram_sizes[2], uint32_t sysclk, qemu_irq **picp, int do_init); /* IBM STBxxx microcontrollers */ CPUPPCState *ppc_stb025_init (MemoryRegion ram_memories[2], - target_phys_addr_t ram_bases[2], - target_phys_addr_t ram_sizes[2], + hwaddr ram_bases[2], + hwaddr ram_sizes[2], uint32_t sysclk, qemu_irq **picp, ram_addr_t *offsetp); diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c index e848cb0b5c..8dc693f050 100644 --- a/hw/ppc405_boards.c +++ b/hw/ppc405_boards.c @@ -60,7 +60,7 @@ struct ref405ep_fpga_t { uint8_t reg1; }; -static uint32_t ref405ep_fpga_readb (void *opaque, target_phys_addr_t addr) +static uint32_t ref405ep_fpga_readb (void *opaque, hwaddr addr) { ref405ep_fpga_t *fpga; uint32_t ret; @@ -82,7 +82,7 @@ static uint32_t ref405ep_fpga_readb (void *opaque, target_phys_addr_t addr) } static void ref405ep_fpga_writeb (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { ref405ep_fpga_t *fpga; @@ -99,7 +99,7 @@ static void ref405ep_fpga_writeb (void *opaque, } } -static uint32_t ref405ep_fpga_readw (void *opaque, target_phys_addr_t addr) +static uint32_t ref405ep_fpga_readw (void *opaque, hwaddr addr) { uint32_t ret; @@ -110,13 +110,13 @@ static uint32_t ref405ep_fpga_readw (void *opaque, target_phys_addr_t addr) } static void ref405ep_fpga_writew (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { ref405ep_fpga_writeb(opaque, addr, (value >> 8) & 0xFF); ref405ep_fpga_writeb(opaque, addr + 1, value & 0xFF); } -static uint32_t ref405ep_fpga_readl (void *opaque, target_phys_addr_t addr) +static uint32_t ref405ep_fpga_readl (void *opaque, hwaddr addr) { uint32_t ret; @@ -129,7 +129,7 @@ static uint32_t ref405ep_fpga_readl (void *opaque, target_phys_addr_t addr) } static void ref405ep_fpga_writel (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { ref405ep_fpga_writeb(opaque, addr, (value >> 24) & 0xFF); ref405ep_fpga_writeb(opaque, addr + 1, (value >> 16) & 0xFF); @@ -184,7 +184,7 @@ static void ref405ep_init(QEMUMachineInitArgs *args) MemoryRegion *sram = g_new(MemoryRegion, 1); ram_addr_t bdloc; MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories)); - target_phys_addr_t ram_bases[2], ram_sizes[2]; + hwaddr ram_bases[2], ram_sizes[2]; target_ulong sram_size; long bios_size; //int phy_addr = 0; @@ -389,7 +389,7 @@ struct taihu_cpld_t { uint8_t reg1; }; -static uint32_t taihu_cpld_readb (void *opaque, target_phys_addr_t addr) +static uint32_t taihu_cpld_readb (void *opaque, hwaddr addr) { taihu_cpld_t *cpld; uint32_t ret; @@ -411,7 +411,7 @@ static uint32_t taihu_cpld_readb (void *opaque, target_phys_addr_t addr) } static void taihu_cpld_writeb (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { taihu_cpld_t *cpld; @@ -428,7 +428,7 @@ static void taihu_cpld_writeb (void *opaque, } } -static uint32_t taihu_cpld_readw (void *opaque, target_phys_addr_t addr) +static uint32_t taihu_cpld_readw (void *opaque, hwaddr addr) { uint32_t ret; @@ -439,13 +439,13 @@ static uint32_t taihu_cpld_readw (void *opaque, target_phys_addr_t addr) } static void taihu_cpld_writew (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { taihu_cpld_writeb(opaque, addr, (value >> 8) & 0xFF); taihu_cpld_writeb(opaque, addr + 1, value & 0xFF); } -static uint32_t taihu_cpld_readl (void *opaque, target_phys_addr_t addr) +static uint32_t taihu_cpld_readl (void *opaque, hwaddr addr) { uint32_t ret; @@ -458,7 +458,7 @@ static uint32_t taihu_cpld_readl (void *opaque, target_phys_addr_t addr) } static void taihu_cpld_writel (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { taihu_cpld_writel(opaque, addr, (value >> 24) & 0xFF); taihu_cpld_writel(opaque, addr + 1, (value >> 16) & 0xFF); @@ -504,7 +504,7 @@ static void taihu_405ep_init(QEMUMachineInitArgs *args) MemoryRegion *sysmem = get_system_memory(); MemoryRegion *bios; MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories)); - target_phys_addr_t ram_bases[2], ram_sizes[2]; + hwaddr ram_bases[2], ram_sizes[2]; long bios_size; target_ulong kernel_base, initrd_base; long kernel_size, initrd_size; diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c index e81409dc0f..0f458ef772 100644 --- a/hw/ppc405_uc.c +++ b/hw/ppc405_uc.c @@ -271,7 +271,7 @@ struct ppc4xx_opba_t { uint8_t pr; }; -static uint32_t opba_readb (void *opaque, target_phys_addr_t addr) +static uint32_t opba_readb (void *opaque, hwaddr addr) { ppc4xx_opba_t *opba; uint32_t ret; @@ -296,7 +296,7 @@ static uint32_t opba_readb (void *opaque, target_phys_addr_t addr) } static void opba_writeb (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { ppc4xx_opba_t *opba; @@ -317,7 +317,7 @@ static void opba_writeb (void *opaque, } } -static uint32_t opba_readw (void *opaque, target_phys_addr_t addr) +static uint32_t opba_readw (void *opaque, hwaddr addr) { uint32_t ret; @@ -331,7 +331,7 @@ static uint32_t opba_readw (void *opaque, target_phys_addr_t addr) } static void opba_writew (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { #ifdef DEBUG_OPBA printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr, @@ -341,7 +341,7 @@ static void opba_writew (void *opaque, opba_writeb(opaque, addr + 1, value); } -static uint32_t opba_readl (void *opaque, target_phys_addr_t addr) +static uint32_t opba_readl (void *opaque, hwaddr addr) { uint32_t ret; @@ -355,7 +355,7 @@ static uint32_t opba_readl (void *opaque, target_phys_addr_t addr) } static void opba_writel (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { #ifdef DEBUG_OPBA printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr, @@ -382,7 +382,7 @@ static void ppc4xx_opba_reset (void *opaque) opba->pr = 0x11; } -static void ppc4xx_opba_init(target_phys_addr_t base) +static void ppc4xx_opba_init(hwaddr base) { ppc4xx_opba_t *opba; @@ -738,7 +738,7 @@ struct ppc405_gpio_t { uint32_t isr1l; }; -static uint32_t ppc405_gpio_readb (void *opaque, target_phys_addr_t addr) +static uint32_t ppc405_gpio_readb (void *opaque, hwaddr addr) { #ifdef DEBUG_GPIO printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); @@ -748,7 +748,7 @@ static uint32_t ppc405_gpio_readb (void *opaque, target_phys_addr_t addr) } static void ppc405_gpio_writeb (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { #ifdef DEBUG_GPIO printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr, @@ -756,7 +756,7 @@ static void ppc405_gpio_writeb (void *opaque, #endif } -static uint32_t ppc405_gpio_readw (void *opaque, target_phys_addr_t addr) +static uint32_t ppc405_gpio_readw (void *opaque, hwaddr addr) { #ifdef DEBUG_GPIO printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); @@ -766,7 +766,7 @@ static uint32_t ppc405_gpio_readw (void *opaque, target_phys_addr_t addr) } static void ppc405_gpio_writew (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { #ifdef DEBUG_GPIO printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr, @@ -774,7 +774,7 @@ static void ppc405_gpio_writew (void *opaque, #endif } -static uint32_t ppc405_gpio_readl (void *opaque, target_phys_addr_t addr) +static uint32_t ppc405_gpio_readl (void *opaque, hwaddr addr) { #ifdef DEBUG_GPIO printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); @@ -784,7 +784,7 @@ static uint32_t ppc405_gpio_readl (void *opaque, target_phys_addr_t addr) } static void ppc405_gpio_writel (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { #ifdef DEBUG_GPIO printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr, @@ -804,7 +804,7 @@ static void ppc405_gpio_reset (void *opaque) { } -static void ppc405_gpio_init(target_phys_addr_t base) +static void ppc405_gpio_init(hwaddr base) { ppc405_gpio_t *gpio; @@ -1010,7 +1010,7 @@ struct ppc4xx_i2c_t { uint8_t directcntl; }; -static uint32_t ppc4xx_i2c_readb (void *opaque, target_phys_addr_t addr) +static uint32_t ppc4xx_i2c_readb (void *opaque, hwaddr addr) { ppc4xx_i2c_t *i2c; uint32_t ret; @@ -1078,7 +1078,7 @@ static uint32_t ppc4xx_i2c_readb (void *opaque, target_phys_addr_t addr) } static void ppc4xx_i2c_writeb (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { ppc4xx_i2c_t *i2c; @@ -1137,7 +1137,7 @@ static void ppc4xx_i2c_writeb (void *opaque, } } -static uint32_t ppc4xx_i2c_readw (void *opaque, target_phys_addr_t addr) +static uint32_t ppc4xx_i2c_readw (void *opaque, hwaddr addr) { uint32_t ret; @@ -1151,7 +1151,7 @@ static uint32_t ppc4xx_i2c_readw (void *opaque, target_phys_addr_t addr) } static void ppc4xx_i2c_writew (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { #ifdef DEBUG_I2C printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr, @@ -1161,7 +1161,7 @@ static void ppc4xx_i2c_writew (void *opaque, ppc4xx_i2c_writeb(opaque, addr + 1, value); } -static uint32_t ppc4xx_i2c_readl (void *opaque, target_phys_addr_t addr) +static uint32_t ppc4xx_i2c_readl (void *opaque, hwaddr addr) { uint32_t ret; @@ -1177,7 +1177,7 @@ static uint32_t ppc4xx_i2c_readl (void *opaque, target_phys_addr_t addr) } static void ppc4xx_i2c_writel (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { #ifdef DEBUG_I2C printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr, @@ -1213,7 +1213,7 @@ static void ppc4xx_i2c_reset (void *opaque) i2c->directcntl = 0x0F; } -static void ppc405_i2c_init(target_phys_addr_t base, qemu_irq irq) +static void ppc405_i2c_init(hwaddr base, qemu_irq irq) { ppc4xx_i2c_t *i2c; @@ -1245,7 +1245,7 @@ struct ppc4xx_gpt_t { uint32_t mask[5]; }; -static uint32_t ppc4xx_gpt_readb (void *opaque, target_phys_addr_t addr) +static uint32_t ppc4xx_gpt_readb (void *opaque, hwaddr addr) { #ifdef DEBUG_GPT printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); @@ -1255,7 +1255,7 @@ static uint32_t ppc4xx_gpt_readb (void *opaque, target_phys_addr_t addr) } static void ppc4xx_gpt_writeb (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { #ifdef DEBUG_I2C printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr, @@ -1264,7 +1264,7 @@ static void ppc4xx_gpt_writeb (void *opaque, /* XXX: generate a bus fault */ } -static uint32_t ppc4xx_gpt_readw (void *opaque, target_phys_addr_t addr) +static uint32_t ppc4xx_gpt_readw (void *opaque, hwaddr addr) { #ifdef DEBUG_GPT printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); @@ -1274,7 +1274,7 @@ static uint32_t ppc4xx_gpt_readw (void *opaque, target_phys_addr_t addr) } static void ppc4xx_gpt_writew (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { #ifdef DEBUG_I2C printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr, @@ -1335,7 +1335,7 @@ static void ppc4xx_gpt_compute_timer (ppc4xx_gpt_t *gpt) /* XXX: TODO */ } -static uint32_t ppc4xx_gpt_readl (void *opaque, target_phys_addr_t addr) +static uint32_t ppc4xx_gpt_readl (void *opaque, hwaddr addr) { ppc4xx_gpt_t *gpt; uint32_t ret; @@ -1391,7 +1391,7 @@ static uint32_t ppc4xx_gpt_readl (void *opaque, target_phys_addr_t addr) } static void ppc4xx_gpt_writel (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { ppc4xx_gpt_t *gpt; int idx; @@ -1488,7 +1488,7 @@ static void ppc4xx_gpt_reset (void *opaque) } } -static void ppc4xx_gpt_init(target_phys_addr_t base, qemu_irq irqs[5]) +static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5]) { ppc4xx_gpt_t *gpt; int i; @@ -2104,8 +2104,8 @@ static void ppc405cr_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[7], CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem, MemoryRegion ram_memories[4], - target_phys_addr_t ram_bases[4], - target_phys_addr_t ram_sizes[4], + hwaddr ram_bases[4], + hwaddr ram_sizes[4], uint32_t sysclk, qemu_irq **picp, int do_init) { @@ -2453,8 +2453,8 @@ static void ppc405ep_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[8], CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem, MemoryRegion ram_memories[2], - target_phys_addr_t ram_bases[2], - target_phys_addr_t ram_sizes[2], + hwaddr ram_bases[2], + hwaddr ram_sizes[2], uint32_t sysclk, qemu_irq **picp, int do_init) { diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c index 5616a26b38..a6b1d51fae 100644 --- a/hw/ppc440_bamboo.c +++ b/hw/ppc440_bamboo.c @@ -49,12 +49,12 @@ static const unsigned int ppc440ep_sdram_bank_sizes[] = { 256<<20, 128<<20, 64<<20, 32<<20, 16<<20, 8<<20, 0 }; -static target_phys_addr_t entry; +static hwaddr entry; -static int bamboo_load_device_tree(target_phys_addr_t addr, +static int bamboo_load_device_tree(hwaddr addr, uint32_t ramsize, - target_phys_addr_t initrd_base, - target_phys_addr_t initrd_size, + hwaddr initrd_base, + hwaddr initrd_size, const char *kernel_cmdline) { int ret = -1; @@ -123,7 +123,7 @@ out: /* Create reset TLB entries for BookE, spanning the 32bit addr space. */ static void mmubooke_create_initial_mapping(CPUPPCState *env, target_ulong va, - target_phys_addr_t pa) + hwaddr pa) { ppcemb_tlb_t *tlb = &env->tlb.tlbe[0]; @@ -168,8 +168,8 @@ static void bamboo_init(QEMUMachineInitArgs *args) MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram_memories = g_malloc(PPC440EP_SDRAM_NR_BANKS * sizeof(*ram_memories)); - target_phys_addr_t ram_bases[PPC440EP_SDRAM_NR_BANKS]; - target_phys_addr_t ram_sizes[PPC440EP_SDRAM_NR_BANKS]; + hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS]; + hwaddr ram_sizes[PPC440EP_SDRAM_NR_BANKS]; qemu_irq *pic; qemu_irq *irqs; PCIBus *pcibus; @@ -177,7 +177,7 @@ static void bamboo_init(QEMUMachineInitArgs *args) CPUPPCState *env; uint64_t elf_entry; uint64_t elf_lowaddr; - target_phys_addr_t loadaddr = 0; + hwaddr loadaddr = 0; target_long initrd_size = 0; DeviceState *dev; int success; diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h index 5cd78b6291..d795ced57e 100644 --- a/hw/ppc4xx.h +++ b/hw/ppc4xx.h @@ -43,22 +43,22 @@ qemu_irq *ppcuic_init (CPUPPCState *env, qemu_irq *irqs, ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks, MemoryRegion ram_memories[], - target_phys_addr_t ram_bases[], - target_phys_addr_t ram_sizes[], + hwaddr ram_bases[], + hwaddr ram_sizes[], const unsigned int sdram_bank_sizes[]); void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks, MemoryRegion ram_memories[], - target_phys_addr_t *ram_bases, - target_phys_addr_t *ram_sizes, + hwaddr *ram_bases, + hwaddr *ram_sizes, int do_init); #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost" PCIBus *ppc4xx_pci_init(CPUPPCState *env, qemu_irq pci_irqs[4], - target_phys_addr_t config_space, - target_phys_addr_t int_ack, - target_phys_addr_t special_cycle, - target_phys_addr_t registers); + hwaddr config_space, + hwaddr int_ack, + hwaddr special_cycle, + hwaddr registers); #endif /* !defined(PPC_4XX_H) */ diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c index 41163e607d..bac8d8769a 100644 --- a/hw/ppc4xx_devs.c +++ b/hw/ppc4xx_devs.c @@ -326,8 +326,8 @@ struct ppc4xx_sdram_t { int nbanks; MemoryRegion containers[4]; /* used for clipping */ MemoryRegion *ram_memories; - target_phys_addr_t ram_bases[4]; - target_phys_addr_t ram_sizes[4]; + hwaddr ram_bases[4]; + hwaddr ram_sizes[4]; uint32_t besr0; uint32_t besr1; uint32_t bear; @@ -348,11 +348,11 @@ enum { }; /* XXX: TOFIX: some patches have made this code become inconsistent: - * there are type inconsistencies, mixing target_phys_addr_t, target_ulong + * there are type inconsistencies, mixing hwaddr, target_ulong * and uint32_t */ -static uint32_t sdram_bcr (target_phys_addr_t ram_base, - target_phys_addr_t ram_size) +static uint32_t sdram_bcr (hwaddr ram_base, + hwaddr ram_size) { uint32_t bcr; @@ -389,7 +389,7 @@ static uint32_t sdram_bcr (target_phys_addr_t ram_base, return bcr; } -static inline target_phys_addr_t sdram_base(uint32_t bcr) +static inline hwaddr sdram_base(uint32_t bcr) { return bcr & 0xFF800000; } @@ -646,8 +646,8 @@ static void sdram_reset (void *opaque) void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks, MemoryRegion *ram_memories, - target_phys_addr_t *ram_bases, - target_phys_addr_t *ram_sizes, + hwaddr *ram_bases, + hwaddr *ram_sizes, int do_init) { ppc4xx_sdram_t *sdram; @@ -656,12 +656,12 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks, sdram->irq = irq; sdram->nbanks = nbanks; sdram->ram_memories = ram_memories; - memset(sdram->ram_bases, 0, 4 * sizeof(target_phys_addr_t)); + memset(sdram->ram_bases, 0, 4 * sizeof(hwaddr)); memcpy(sdram->ram_bases, ram_bases, - nbanks * sizeof(target_phys_addr_t)); - memset(sdram->ram_sizes, 0, 4 * sizeof(target_phys_addr_t)); + nbanks * sizeof(hwaddr)); + memset(sdram->ram_sizes, 0, 4 * sizeof(hwaddr)); memcpy(sdram->ram_sizes, ram_sizes, - nbanks * sizeof(target_phys_addr_t)); + nbanks * sizeof(hwaddr)); qemu_register_reset(&sdram_reset, sdram); ppc_dcr_register(env, SDRAM0_CFGADDR, sdram, &dcr_read_sdram, &dcr_write_sdram); @@ -680,8 +680,8 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks, * sizes varies by SoC. */ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks, MemoryRegion ram_memories[], - target_phys_addr_t ram_bases[], - target_phys_addr_t ram_sizes[], + hwaddr ram_bases[], + hwaddr ram_sizes[], const unsigned int sdram_bank_sizes[]) { ram_addr_t size_left = ram_size; diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c index a14fd426c1..d3ad6a0b79 100644 --- a/hw/ppc4xx_pci.c +++ b/hw/ppc4xx_pci.c @@ -92,7 +92,7 @@ typedef struct PPC4xxPCIState PPC4xxPCIState; #define PCI_ALL_SIZE (PCI_REG_BASE + PCI_REG_SIZE) -static uint64_t pci4xx_cfgaddr_read(void *opaque, target_phys_addr_t addr, +static uint64_t pci4xx_cfgaddr_read(void *opaque, hwaddr addr, unsigned size) { PPC4xxPCIState *ppc4xx_pci = opaque; @@ -101,7 +101,7 @@ static uint64_t pci4xx_cfgaddr_read(void *opaque, target_phys_addr_t addr, return phb->config_reg; } -static void pci4xx_cfgaddr_write(void *opaque, target_phys_addr_t addr, +static void pci4xx_cfgaddr_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { PPC4xxPCIState *ppc4xx_pci = opaque; @@ -116,7 +116,7 @@ static const MemoryRegionOps pci4xx_cfgaddr_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static void ppc4xx_pci_reg_write4(void *opaque, target_phys_addr_t offset, +static void ppc4xx_pci_reg_write4(void *opaque, hwaddr offset, uint64_t value, unsigned size) { struct PPC4xxPCIState *pci = opaque; @@ -184,7 +184,7 @@ static void ppc4xx_pci_reg_write4(void *opaque, target_phys_addr_t offset, } } -static uint64_t ppc4xx_pci_reg_read4(void *opaque, target_phys_addr_t offset, +static uint64_t ppc4xx_pci_reg_read4(void *opaque, hwaddr offset, unsigned size) { struct PPC4xxPCIState *pci = opaque; diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h index 7d084184fc..524b2368a4 100644 --- a/hw/ppc_mac.h +++ b/hw/ppc_mac.h @@ -71,10 +71,10 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic, /* Mac NVRAM */ typedef struct MacIONVRAMState MacIONVRAMState; -MacIONVRAMState *macio_nvram_init (target_phys_addr_t size, +MacIONVRAMState *macio_nvram_init (hwaddr size, unsigned int it_shift); void macio_nvram_setup_bar(MacIONVRAMState *s, MemoryRegion *bar, - target_phys_addr_t mem_base); + hwaddr mem_base); void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len); uint32_t macio_nvram_read (void *opaque, uint32_t addr); void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val); diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index a265445b70..15f74f95fd 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -82,13 +82,13 @@ #endif /* UniN device */ -static void unin_write(void *opaque, target_phys_addr_t addr, uint64_t value, +static void unin_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { UNIN_DPRINTF("write addr " TARGET_FMT_plx " val %"PRIx64"\n", addr, value); } -static uint64_t unin_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t unin_read(void *opaque, hwaddr addr, unsigned size) { uint32_t value; @@ -115,7 +115,7 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr) return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR; } -static target_phys_addr_t round_page(target_phys_addr_t addr) +static hwaddr round_page(hwaddr addr) { return (addr + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK; } @@ -143,7 +143,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) MemoryRegion *unin_memory = g_new(MemoryRegion, 1); int linux_boot, i; MemoryRegion *ram = g_new(MemoryRegion, 1), *bios = g_new(MemoryRegion, 1); - target_phys_addr_t kernel_base, initrd_base, cmdline_base = 0; + hwaddr kernel_base, initrd_base, cmdline_base = 0; long kernel_size, initrd_size; PCIBus *pci_bus; MacIONVRAMState *nvr; diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index de334080ff..a4f899d889 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -59,7 +59,7 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr) return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR; } -static target_phys_addr_t round_page(target_phys_addr_t addr) +static hwaddr round_page(hwaddr addr) { return (addr + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK; } diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index a0d1c3d75d..085851a3e6 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -115,27 +115,27 @@ static struct { } XCSR; static void PPC_XCSR_writeb (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { printf("%s: 0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", __func__, addr, value); } static void PPC_XCSR_writew (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { printf("%s: 0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", __func__, addr, value); } static void PPC_XCSR_writel (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { printf("%s: 0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", __func__, addr, value); } -static uint32_t PPC_XCSR_readb (void *opaque, target_phys_addr_t addr) +static uint32_t PPC_XCSR_readb (void *opaque, hwaddr addr) { uint32_t retval = 0; @@ -145,7 +145,7 @@ static uint32_t PPC_XCSR_readb (void *opaque, target_phys_addr_t addr) return retval; } -static uint32_t PPC_XCSR_readw (void *opaque, target_phys_addr_t addr) +static uint32_t PPC_XCSR_readw (void *opaque, hwaddr addr) { uint32_t retval = 0; @@ -155,7 +155,7 @@ static uint32_t PPC_XCSR_readw (void *opaque, target_phys_addr_t addr) return retval; } -static uint32_t PPC_XCSR_readl (void *opaque, target_phys_addr_t addr) +static uint32_t PPC_XCSR_readl (void *opaque, hwaddr addr) { uint32_t retval = 0; @@ -343,8 +343,8 @@ static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr) return retval; } -static inline target_phys_addr_t prep_IO_address(sysctrl_t *sysctrl, - target_phys_addr_t addr) +static inline hwaddr prep_IO_address(sysctrl_t *sysctrl, + hwaddr addr) { if (sysctrl->contiguous_map == 0) { /* 64 KB contiguous space for IOs */ @@ -357,7 +357,7 @@ static inline target_phys_addr_t prep_IO_address(sysctrl_t *sysctrl, return addr; } -static void PPC_prep_io_writeb (void *opaque, target_phys_addr_t addr, +static void PPC_prep_io_writeb (void *opaque, hwaddr addr, uint32_t value) { sysctrl_t *sysctrl = opaque; @@ -366,7 +366,7 @@ static void PPC_prep_io_writeb (void *opaque, target_phys_addr_t addr, cpu_outb(addr, value); } -static uint32_t PPC_prep_io_readb (void *opaque, target_phys_addr_t addr) +static uint32_t PPC_prep_io_readb (void *opaque, hwaddr addr) { sysctrl_t *sysctrl = opaque; uint32_t ret; @@ -377,7 +377,7 @@ static uint32_t PPC_prep_io_readb (void *opaque, target_phys_addr_t addr) return ret; } -static void PPC_prep_io_writew (void *opaque, target_phys_addr_t addr, +static void PPC_prep_io_writew (void *opaque, hwaddr addr, uint32_t value) { sysctrl_t *sysctrl = opaque; @@ -387,7 +387,7 @@ static void PPC_prep_io_writew (void *opaque, target_phys_addr_t addr, cpu_outw(addr, value); } -static uint32_t PPC_prep_io_readw (void *opaque, target_phys_addr_t addr) +static uint32_t PPC_prep_io_readw (void *opaque, hwaddr addr) { sysctrl_t *sysctrl = opaque; uint32_t ret; @@ -399,7 +399,7 @@ static uint32_t PPC_prep_io_readw (void *opaque, target_phys_addr_t addr) return ret; } -static void PPC_prep_io_writel (void *opaque, target_phys_addr_t addr, +static void PPC_prep_io_writel (void *opaque, hwaddr addr, uint32_t value) { sysctrl_t *sysctrl = opaque; @@ -409,7 +409,7 @@ static void PPC_prep_io_writel (void *opaque, target_phys_addr_t addr, cpu_outl(addr, value); } -static uint32_t PPC_prep_io_readl (void *opaque, target_phys_addr_t addr) +static uint32_t PPC_prep_io_readl (void *opaque, hwaddr addr) { sysctrl_t *sysctrl = opaque; uint32_t ret; @@ -525,7 +525,7 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) bios_size = -1; } if (bios_size > 0 && bios_size <= BIOS_SIZE) { - target_phys_addr_t bios_addr; + hwaddr bios_addr; bios_size = (bios_size + 0xfff) & ~0xfff; bios_addr = (uint32_t)(-bios_size); bios_size = load_image_targphys(filename, bios_addr, bios_size); diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 92b1dc0534..332748a6de 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -91,7 +91,7 @@ struct PPCE500PCIState { typedef struct PPCE500PCIState PPCE500PCIState; -static uint64_t pci_reg_read4(void *opaque, target_phys_addr_t addr, +static uint64_t pci_reg_read4(void *opaque, hwaddr addr, unsigned size) { PPCE500PCIState *pci = opaque; @@ -160,7 +160,7 @@ static uint64_t pci_reg_read4(void *opaque, target_phys_addr_t addr, return value; } -static void pci_reg_write4(void *opaque, target_phys_addr_t addr, +static void pci_reg_write4(void *opaque, hwaddr addr, uint64_t value, unsigned size) { PPCE500PCIState *pci = opaque; diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c index c5b8e051ec..55aa9dc8a2 100644 --- a/hw/ppce500_spin.c +++ b/hw/ppce500_spin.c @@ -68,18 +68,18 @@ static void spin_reset(void *opaque) } /* Create -kernel TLB entries for BookE, linearly spanning 256MB. */ -static inline target_phys_addr_t booke206_page_size_to_tlb(uint64_t size) +static inline hwaddr booke206_page_size_to_tlb(uint64_t size) { return (ffs(size >> 10) - 1) >> 1; } static void mmubooke_create_initial_mapping(CPUPPCState *env, target_ulong va, - target_phys_addr_t pa, - target_phys_addr_t len) + hwaddr pa, + hwaddr len) { ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 1); - target_phys_addr_t size; + hwaddr size; size = (booke206_page_size_to_tlb(len) << MAS1_TSIZE_SHIFT); tlb->mas1 = MAS1_VALID | size; @@ -94,8 +94,8 @@ static void spin_kick(void *data) SpinKick *kick = data; CPUPPCState *env = kick->env; SpinInfo *curspin = kick->spin; - target_phys_addr_t map_size = 64 * 1024 * 1024; - target_phys_addr_t map_start; + hwaddr map_size = 64 * 1024 * 1024; + hwaddr map_start; cpu_synchronize_state(env); stl_p(&curspin->pir, env->spr[SPR_PIR]); @@ -117,7 +117,7 @@ static void spin_kick(void *data) qemu_cpu_kick(env); } -static void spin_write(void *opaque, target_phys_addr_t addr, uint64_t value, +static void spin_write(void *opaque, hwaddr addr, uint64_t value, unsigned len) { SpinState *s = opaque; @@ -166,7 +166,7 @@ static void spin_write(void *opaque, target_phys_addr_t addr, uint64_t value, } } -static uint64_t spin_read(void *opaque, target_phys_addr_t addr, unsigned len) +static uint64_t spin_read(void *opaque, hwaddr addr, unsigned len) { SpinState *s = opaque; uint8_t *spin_p = &((uint8_t*)s->spin)[addr]; diff --git a/hw/prep_pci.c b/hw/prep_pci.c index cc44e61987..0bc479cd1f 100644 --- a/hw/prep_pci.c +++ b/hw/prep_pci.c @@ -44,7 +44,7 @@ typedef struct RavenPCIState { PCIDevice dev; } RavenPCIState; -static inline uint32_t PPC_PCIIO_config(target_phys_addr_t addr) +static inline uint32_t PPC_PCIIO_config(hwaddr addr) { int i; @@ -56,7 +56,7 @@ static inline uint32_t PPC_PCIIO_config(target_phys_addr_t addr) return (addr & 0x7ff) | (i << 11); } -static void ppc_pci_io_write(void *opaque, target_phys_addr_t addr, +static void ppc_pci_io_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { PREPPCIState *s = opaque; @@ -64,7 +64,7 @@ static void ppc_pci_io_write(void *opaque, target_phys_addr_t addr, pci_data_write(phb->bus, PPC_PCIIO_config(addr), val, size); } -static uint64_t ppc_pci_io_read(void *opaque, target_phys_addr_t addr, +static uint64_t ppc_pci_io_read(void *opaque, hwaddr addr, unsigned int size) { PREPPCIState *s = opaque; @@ -78,7 +78,7 @@ static const MemoryRegionOps PPC_PCIIO_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static uint64_t ppc_intack_read(void *opaque, target_phys_addr_t addr, +static uint64_t ppc_intack_read(void *opaque, hwaddr addr, unsigned int size) { return pic_read_irq(isa_pic); diff --git a/hw/puv3_dma.c b/hw/puv3_dma.c index 85b97bfdeb..9de63b4c34 100644 --- a/hw/puv3_dma.c +++ b/hw/puv3_dma.c @@ -24,7 +24,7 @@ typedef struct { uint32_t reg_CFG[PUV3_DMA_CH_NR]; } PUV3DMAState; -static uint64_t puv3_dma_read(void *opaque, target_phys_addr_t offset, +static uint64_t puv3_dma_read(void *opaque, hwaddr offset, unsigned size) { PUV3DMAState *s = opaque; @@ -44,7 +44,7 @@ static uint64_t puv3_dma_read(void *opaque, target_phys_addr_t offset, return ret; } -static void puv3_dma_write(void *opaque, target_phys_addr_t offset, +static void puv3_dma_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PUV3DMAState *s = opaque; diff --git a/hw/puv3_gpio.c b/hw/puv3_gpio.c index 9436e6c62c..152248d291 100644 --- a/hw/puv3_gpio.c +++ b/hw/puv3_gpio.c @@ -24,7 +24,7 @@ typedef struct { uint32_t reg_GPIR; } PUV3GPIOState; -static uint64_t puv3_gpio_read(void *opaque, target_phys_addr_t offset, +static uint64_t puv3_gpio_read(void *opaque, hwaddr offset, unsigned size) { PUV3GPIOState *s = opaque; @@ -48,7 +48,7 @@ static uint64_t puv3_gpio_read(void *opaque, target_phys_addr_t offset, return ret; } -static void puv3_gpio_write(void *opaque, target_phys_addr_t offset, +static void puv3_gpio_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PUV3GPIOState *s = opaque; diff --git a/hw/puv3_intc.c b/hw/puv3_intc.c index 9e0b975ea2..07f5649065 100644 --- a/hw/puv3_intc.c +++ b/hw/puv3_intc.c @@ -46,7 +46,7 @@ static void puv3_intc_handler(void *opaque, int irq, int level) puv3_intc_update(s); } -static uint64_t puv3_intc_read(void *opaque, target_phys_addr_t offset, +static uint64_t puv3_intc_read(void *opaque, hwaddr offset, unsigned size) { PUV3INTCState *s = opaque; @@ -66,7 +66,7 @@ static uint64_t puv3_intc_read(void *opaque, target_phys_addr_t offset, return ret; } -static void puv3_intc_write(void *opaque, target_phys_addr_t offset, +static void puv3_intc_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PUV3INTCState *s = opaque; diff --git a/hw/puv3_ost.c b/hw/puv3_ost.c index dd30cad0e2..14c6f21a75 100644 --- a/hw/puv3_ost.c +++ b/hw/puv3_ost.c @@ -28,7 +28,7 @@ typedef struct { uint32_t reg_OIER; } PUV3OSTState; -static uint64_t puv3_ost_read(void *opaque, target_phys_addr_t offset, +static uint64_t puv3_ost_read(void *opaque, hwaddr offset, unsigned size) { PUV3OSTState *s = opaque; @@ -51,7 +51,7 @@ static uint64_t puv3_ost_read(void *opaque, target_phys_addr_t offset, return ret; } -static void puv3_ost_write(void *opaque, target_phys_addr_t offset, +static void puv3_ost_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PUV3OSTState *s = opaque; diff --git a/hw/puv3_pm.c b/hw/puv3_pm.c index 621c96875c..87a687afae 100644 --- a/hw/puv3_pm.c +++ b/hw/puv3_pm.c @@ -26,7 +26,7 @@ typedef struct { uint32_t reg_DIVCFG; } PUV3PMState; -static uint64_t puv3_pm_read(void *opaque, target_phys_addr_t offset, +static uint64_t puv3_pm_read(void *opaque, hwaddr offset, unsigned size) { PUV3PMState *s = opaque; @@ -74,7 +74,7 @@ static uint64_t puv3_pm_read(void *opaque, target_phys_addr_t offset, return ret; } -static void puv3_pm_write(void *opaque, target_phys_addr_t offset, +static void puv3_pm_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PUV3PMState *s = opaque; diff --git a/hw/pxa.h b/hw/pxa.h index 6a2120555f..49ac820ea2 100644 --- a/hw/pxa.h +++ b/hw/pxa.h @@ -65,28 +65,28 @@ # define PXA2XX_INTERNAL_SIZE 0x40000 /* pxa2xx_pic.c */ -DeviceState *pxa2xx_pic_init(target_phys_addr_t base, ARMCPU *cpu); +DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu); /* pxa2xx_gpio.c */ -DeviceState *pxa2xx_gpio_init(target_phys_addr_t base, +DeviceState *pxa2xx_gpio_init(hwaddr base, CPUARMState *env, DeviceState *pic, int lines); void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler); /* pxa2xx_dma.c */ -DeviceState *pxa255_dma_init(target_phys_addr_t base, qemu_irq irq); -DeviceState *pxa27x_dma_init(target_phys_addr_t base, qemu_irq irq); +DeviceState *pxa255_dma_init(hwaddr base, qemu_irq irq); +DeviceState *pxa27x_dma_init(hwaddr base, qemu_irq irq); /* pxa2xx_lcd.c */ typedef struct PXA2xxLCDState PXA2xxLCDState; PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem, - target_phys_addr_t base, qemu_irq irq); + hwaddr base, qemu_irq irq); void pxa2xx_lcd_vsync_notifier(PXA2xxLCDState *s, qemu_irq handler); void pxa2xx_lcdc_oritentation(void *opaque, int angle); /* pxa2xx_mmci.c */ typedef struct PXA2xxMMCIState PXA2xxMMCIState; PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, - target_phys_addr_t base, + hwaddr base, BlockDriverState *bd, qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma); void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly, @@ -95,7 +95,7 @@ void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly, /* pxa2xx_pcmcia.c */ typedef struct PXA2xxPCMCIAState PXA2xxPCMCIAState; PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, - target_phys_addr_t base); + hwaddr base); int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card); int pxa2xx_pcmcia_dettach(void *opaque); void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq); @@ -107,14 +107,14 @@ struct keymap { }; typedef struct PXA2xxKeyPadState PXA2xxKeyPadState; PXA2xxKeyPadState *pxa27x_keypad_init(MemoryRegion *sysmem, - target_phys_addr_t base, + hwaddr base, qemu_irq irq); void pxa27x_register_keypad(PXA2xxKeyPadState *kp, struct keymap *map, int size); /* pxa2xx.c */ typedef struct PXA2xxI2CState PXA2xxI2CState; -PXA2xxI2CState *pxa2xx_i2c_init(target_phys_addr_t base, +PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base, qemu_irq irq, uint32_t page_size); i2c_bus *pxa2xx_i2c_bus(PXA2xxI2CState *s); @@ -142,16 +142,16 @@ typedef struct { PXA2xxKeyPadState *kp; /* Power management */ - target_phys_addr_t pm_base; + hwaddr pm_base; uint32_t pm_regs[0x40]; /* Clock management */ - target_phys_addr_t cm_base; + hwaddr cm_base; uint32_t cm_regs[4]; uint32_t clkcfg; /* Memory management */ - target_phys_addr_t mm_base; + hwaddr mm_base; uint32_t mm_regs[0x1a]; /* Performance monitoring */ diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c index 4ec904ff20..0fb2179baf 100644 --- a/hw/pxa2xx.c +++ b/hw/pxa2xx.c @@ -17,7 +17,7 @@ #include "blockdev.h" static struct { - target_phys_addr_t io_base; + hwaddr io_base; int irqn; } pxa255_serial[] = { { 0x40100000, PXA2XX_PIC_FFUART }, @@ -33,7 +33,7 @@ static struct { }; typedef struct PXASSPDef { - target_phys_addr_t io_base; + hwaddr io_base; int irqn; } PXASSPDef; @@ -88,7 +88,7 @@ static PXASSPDef pxa27x_ssp[] = { #define PCMD0 0x80 /* Power Manager I2C Command register File 0 */ #define PCMD31 0xfc /* Power Manager I2C Command register File 31 */ -static uint64_t pxa2xx_pm_read(void *opaque, target_phys_addr_t addr, +static uint64_t pxa2xx_pm_read(void *opaque, hwaddr addr, unsigned size) { PXA2xxState *s = (PXA2xxState *) opaque; @@ -107,7 +107,7 @@ static uint64_t pxa2xx_pm_read(void *opaque, target_phys_addr_t addr, return 0; } -static void pxa2xx_pm_write(void *opaque, target_phys_addr_t addr, +static void pxa2xx_pm_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { PXA2xxState *s = (PXA2xxState *) opaque; @@ -160,7 +160,7 @@ static const VMStateDescription vmstate_pxa2xx_pm = { #define OSCC 0x08 /* Oscillator Configuration register */ #define CCSR 0x0c /* Core Clock Status register */ -static uint64_t pxa2xx_cm_read(void *opaque, target_phys_addr_t addr, +static uint64_t pxa2xx_cm_read(void *opaque, hwaddr addr, unsigned size) { PXA2xxState *s = (PXA2xxState *) opaque; @@ -181,7 +181,7 @@ static uint64_t pxa2xx_cm_read(void *opaque, target_phys_addr_t addr, return 0; } -static void pxa2xx_cm_write(void *opaque, target_phys_addr_t addr, +static void pxa2xx_cm_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { PXA2xxState *s = (PXA2xxState *) opaque; @@ -405,7 +405,7 @@ static void pxa2xx_setup_cp14(PXA2xxState *s) #define BSCNTR3 0x60 /* Memory Buffer Strength Control register 3 */ #define SA1110 0x64 /* SA-1110 Memory Compatibility register */ -static uint64_t pxa2xx_mm_read(void *opaque, target_phys_addr_t addr, +static uint64_t pxa2xx_mm_read(void *opaque, hwaddr addr, unsigned size) { PXA2xxState *s = (PXA2xxState *) opaque; @@ -422,7 +422,7 @@ static uint64_t pxa2xx_mm_read(void *opaque, target_phys_addr_t addr, return 0; } -static void pxa2xx_mm_write(void *opaque, target_phys_addr_t addr, +static void pxa2xx_mm_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { PXA2xxState *s = (PXA2xxState *) opaque; @@ -567,7 +567,7 @@ static void pxa2xx_ssp_fifo_update(PXA2xxSSPState *s) pxa2xx_ssp_int_update(s); } -static uint64_t pxa2xx_ssp_read(void *opaque, target_phys_addr_t addr, +static uint64_t pxa2xx_ssp_read(void *opaque, hwaddr addr, unsigned size) { PXA2xxSSPState *s = (PXA2xxSSPState *) opaque; @@ -613,7 +613,7 @@ static uint64_t pxa2xx_ssp_read(void *opaque, target_phys_addr_t addr, return 0; } -static void pxa2xx_ssp_write(void *opaque, target_phys_addr_t addr, +static void pxa2xx_ssp_write(void *opaque, hwaddr addr, uint64_t value64, unsigned size) { PXA2xxSSPState *s = (PXA2xxSSPState *) opaque; @@ -943,7 +943,7 @@ static inline void pxa2xx_rtc_pi_tick(void *opaque) pxa2xx_rtc_int_update(s); } -static uint64_t pxa2xx_rtc_read(void *opaque, target_phys_addr_t addr, +static uint64_t pxa2xx_rtc_read(void *opaque, hwaddr addr, unsigned size) { PXA2xxRTCState *s = (PXA2xxRTCState *) opaque; @@ -989,7 +989,7 @@ static uint64_t pxa2xx_rtc_read(void *opaque, target_phys_addr_t addr, return 0; } -static void pxa2xx_rtc_write(void *opaque, target_phys_addr_t addr, +static void pxa2xx_rtc_write(void *opaque, hwaddr addr, uint64_t value64, unsigned size) { PXA2xxRTCState *s = (PXA2xxRTCState *) opaque; @@ -1294,7 +1294,7 @@ static int pxa2xx_i2c_tx(I2CSlave *i2c, uint8_t data) return 1; } -static uint64_t pxa2xx_i2c_read(void *opaque, target_phys_addr_t addr, +static uint64_t pxa2xx_i2c_read(void *opaque, hwaddr addr, unsigned size) { PXA2xxI2CState *s = (PXA2xxI2CState *) opaque; @@ -1322,7 +1322,7 @@ static uint64_t pxa2xx_i2c_read(void *opaque, target_phys_addr_t addr, return 0; } -static void pxa2xx_i2c_write(void *opaque, target_phys_addr_t addr, +static void pxa2xx_i2c_write(void *opaque, hwaddr addr, uint64_t value64, unsigned size) { PXA2xxI2CState *s = (PXA2xxI2CState *) opaque; @@ -1449,7 +1449,7 @@ static TypeInfo pxa2xx_i2c_slave_info = { .class_init = pxa2xx_i2c_slave_class_init, }; -PXA2xxI2CState *pxa2xx_i2c_init(target_phys_addr_t base, +PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base, qemu_irq irq, uint32_t region_size) { DeviceState *dev; @@ -1572,7 +1572,7 @@ static inline void pxa2xx_i2s_update(PXA2xxI2SState *i2s) #define SADIV 0x60 /* Serial Audio Clock Divider register */ #define SADR 0x80 /* Serial Audio Data register */ -static uint64_t pxa2xx_i2s_read(void *opaque, target_phys_addr_t addr, +static uint64_t pxa2xx_i2s_read(void *opaque, hwaddr addr, unsigned size) { PXA2xxI2SState *s = (PXA2xxI2SState *) opaque; @@ -1604,7 +1604,7 @@ static uint64_t pxa2xx_i2s_read(void *opaque, target_phys_addr_t addr, return 0; } -static void pxa2xx_i2s_write(void *opaque, target_phys_addr_t addr, +static void pxa2xx_i2s_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { PXA2xxI2SState *s = (PXA2xxI2SState *) opaque; @@ -1706,7 +1706,7 @@ static void pxa2xx_i2s_data_req(void *opaque, int tx, int rx) } static PXA2xxI2SState *pxa2xx_i2s_init(MemoryRegion *sysmem, - target_phys_addr_t base, + hwaddr base, qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma) { PXA2xxI2SState *s = (PXA2xxI2SState *) @@ -1801,7 +1801,7 @@ static inline void pxa2xx_fir_update(PXA2xxFIrState *s) #define ICSR1 0x18 /* FICP Status register 1 */ #define ICFOR 0x1c /* FICP FIFO Occupancy Status register */ -static uint64_t pxa2xx_fir_read(void *opaque, target_phys_addr_t addr, +static uint64_t pxa2xx_fir_read(void *opaque, hwaddr addr, unsigned size) { PXA2xxFIrState *s = (PXA2xxFIrState *) opaque; @@ -1839,7 +1839,7 @@ static uint64_t pxa2xx_fir_read(void *opaque, target_phys_addr_t addr, return 0; } -static void pxa2xx_fir_write(void *opaque, target_phys_addr_t addr, +static void pxa2xx_fir_write(void *opaque, hwaddr addr, uint64_t value64, unsigned size) { PXA2xxFIrState *s = (PXA2xxFIrState *) opaque; @@ -1963,7 +1963,7 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id) } static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem, - target_phys_addr_t base, + hwaddr base, qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma, CharDriverState *chr) { diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c index 031015400b..dbea1d2098 100644 --- a/hw/pxa2xx_dma.c +++ b/hw/pxa2xx_dma.c @@ -147,7 +147,7 @@ static inline void pxa2xx_dma_descriptor_fetch( PXA2xxDMAState *s, int ch) { uint32_t desc[4]; - target_phys_addr_t daddr = s->chan[ch].descr & ~0xf; + hwaddr daddr = s->chan[ch].descr & ~0xf; if ((s->chan[ch].descr & DDADR_BREN) && (s->chan[ch].state & DCSR_CMPST)) daddr += 32; @@ -251,7 +251,7 @@ static void pxa2xx_dma_run(PXA2xxDMAState *s) } } -static uint64_t pxa2xx_dma_read(void *opaque, target_phys_addr_t offset, +static uint64_t pxa2xx_dma_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxDMAState *s = (PXA2xxDMAState *) opaque; @@ -310,7 +310,7 @@ static uint64_t pxa2xx_dma_read(void *opaque, target_phys_addr_t offset, return 7; } -static void pxa2xx_dma_write(void *opaque, target_phys_addr_t offset, +static void pxa2xx_dma_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PXA2xxDMAState *s = (PXA2xxDMAState *) opaque; @@ -473,7 +473,7 @@ static int pxa2xx_dma_init(SysBusDevice *dev) return 0; } -DeviceState *pxa27x_dma_init(target_phys_addr_t base, qemu_irq irq) +DeviceState *pxa27x_dma_init(hwaddr base, qemu_irq irq) { DeviceState *dev; @@ -487,7 +487,7 @@ DeviceState *pxa27x_dma_init(target_phys_addr_t base, qemu_irq irq) return dev; } -DeviceState *pxa255_dma_init(target_phys_addr_t base, qemu_irq irq) +DeviceState *pxa255_dma_init(hwaddr base, qemu_irq irq) { DeviceState *dev; diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c index 3c90c9c4e0..7aaf4092df 100644 --- a/hw/pxa2xx_gpio.c +++ b/hw/pxa2xx_gpio.c @@ -139,7 +139,7 @@ static void pxa2xx_gpio_handler_update(PXA2xxGPIOInfo *s) { } } -static uint64_t pxa2xx_gpio_read(void *opaque, target_phys_addr_t offset, +static uint64_t pxa2xx_gpio_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque; @@ -191,7 +191,7 @@ static uint64_t pxa2xx_gpio_read(void *opaque, target_phys_addr_t offset, return 0; } -static void pxa2xx_gpio_write(void *opaque, target_phys_addr_t offset, +static void pxa2xx_gpio_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque; @@ -249,7 +249,7 @@ static const MemoryRegionOps pxa_gpio_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -DeviceState *pxa2xx_gpio_init(target_phys_addr_t base, +DeviceState *pxa2xx_gpio_init(hwaddr base, CPUARMState *env, DeviceState *pic, int lines) { DeviceState *dev; diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c index 1a997c9c83..257984c427 100644 --- a/hw/pxa2xx_keypad.c +++ b/hw/pxa2xx_keypad.c @@ -174,7 +174,7 @@ static void pxa27x_keyboard_event (PXA2xxKeyPadState *kp, int keycode) } } -static uint64_t pxa2xx_keypad_read(void *opaque, target_phys_addr_t offset, +static uint64_t pxa2xx_keypad_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxKeyPadState *s = (PXA2xxKeyPadState *) opaque; @@ -236,7 +236,7 @@ static uint64_t pxa2xx_keypad_read(void *opaque, target_phys_addr_t offset, return 0; } -static void pxa2xx_keypad_write(void *opaque, target_phys_addr_t offset, +static void pxa2xx_keypad_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PXA2xxKeyPadState *s = (PXA2xxKeyPadState *) opaque; @@ -305,7 +305,7 @@ static const VMStateDescription vmstate_pxa2xx_keypad = { }; PXA2xxKeyPadState *pxa27x_keypad_init(MemoryRegion *sysmem, - target_phys_addr_t base, + hwaddr base, qemu_irq irq) { PXA2xxKeyPadState *s; diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c index ee8bf577cb..38c38890c9 100644 --- a/hw/pxa2xx_lcd.c +++ b/hw/pxa2xx_lcd.c @@ -23,7 +23,7 @@ struct DMAChannel { uint8_t up; uint8_t palette[1024]; uint8_t pbuffer[1024]; - void (*redraw)(PXA2xxLCDState *s, target_phys_addr_t addr, + void (*redraw)(PXA2xxLCDState *s, hwaddr addr, int *miny, int *maxy); uint32_t descriptor; @@ -291,7 +291,7 @@ static inline void pxa2xx_dma_rdst_set(PXA2xxLCDState *s) static void pxa2xx_descriptor_load(PXA2xxLCDState *s) { PXAFrameDescriptor desc; - target_phys_addr_t descptr; + hwaddr descptr; int i; for (i = 0; i < PXA_LCDDMA_CHANS; i ++) { @@ -323,7 +323,7 @@ static void pxa2xx_descriptor_load(PXA2xxLCDState *s) } } -static uint64_t pxa2xx_lcdc_read(void *opaque, target_phys_addr_t offset, +static uint64_t pxa2xx_lcdc_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxLCDState *s = (PXA2xxLCDState *) opaque; @@ -417,7 +417,7 @@ static uint64_t pxa2xx_lcdc_read(void *opaque, target_phys_addr_t offset, return 0; } -static void pxa2xx_lcdc_write(void *opaque, target_phys_addr_t offset, +static void pxa2xx_lcdc_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PXA2xxLCDState *s = (PXA2xxLCDState *) opaque; @@ -674,7 +674,7 @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp) } static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s, - target_phys_addr_t addr, int *miny, int *maxy) + hwaddr addr, int *miny, int *maxy) { int src_width, dest_width; drawfn fn = NULL; @@ -701,7 +701,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s, } static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s, - target_phys_addr_t addr, int *miny, int *maxy) + hwaddr addr, int *miny, int *maxy) { int src_width, dest_width; drawfn fn = NULL; @@ -729,7 +729,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s, } static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s, - target_phys_addr_t addr, int *miny, int *maxy) + hwaddr addr, int *miny, int *maxy) { int src_width, dest_width; drawfn fn = NULL; @@ -759,7 +759,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s, } static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s, - target_phys_addr_t addr, int *miny, int *maxy) + hwaddr addr, int *miny, int *maxy) { int src_width, dest_width; drawfn fn = NULL; @@ -813,7 +813,7 @@ static void pxa2xx_lcdc_resize(PXA2xxLCDState *s) static void pxa2xx_update_display(void *opaque) { PXA2xxLCDState *s = (PXA2xxLCDState *) opaque; - target_phys_addr_t fbptr; + hwaddr fbptr; int miny, maxy; int ch; if (!(s->control[0] & LCCR0_ENB)) @@ -987,7 +987,7 @@ static const VMStateDescription vmstate_pxa2xx_lcdc = { #include "pxa2xx_template.h" PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem, - target_phys_addr_t base, qemu_irq irq) + hwaddr base, qemu_irq irq) { PXA2xxLCDState *s; diff --git a/hw/pxa2xx_mmci.c b/hw/pxa2xx_mmci.c index b505a4cc98..3589968712 100644 --- a/hw/pxa2xx_mmci.c +++ b/hw/pxa2xx_mmci.c @@ -215,7 +215,7 @@ static void pxa2xx_mmci_wakequeues(PXA2xxMMCIState *s) pxa2xx_mmci_fifo_update(s); } -static uint32_t pxa2xx_mmci_read(void *opaque, target_phys_addr_t offset) +static uint32_t pxa2xx_mmci_read(void *opaque, hwaddr offset) { PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque; uint32_t ret; @@ -277,7 +277,7 @@ static uint32_t pxa2xx_mmci_read(void *opaque, target_phys_addr_t offset) } static void pxa2xx_mmci_write(void *opaque, - target_phys_addr_t offset, uint32_t value) + hwaddr offset, uint32_t value) { PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque; @@ -386,21 +386,21 @@ static void pxa2xx_mmci_write(void *opaque, } } -static uint32_t pxa2xx_mmci_readb(void *opaque, target_phys_addr_t offset) +static uint32_t pxa2xx_mmci_readb(void *opaque, hwaddr offset) { PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque; s->ac_width = 1; return pxa2xx_mmci_read(opaque, offset); } -static uint32_t pxa2xx_mmci_readh(void *opaque, target_phys_addr_t offset) +static uint32_t pxa2xx_mmci_readh(void *opaque, hwaddr offset) { PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque; s->ac_width = 2; return pxa2xx_mmci_read(opaque, offset); } -static uint32_t pxa2xx_mmci_readw(void *opaque, target_phys_addr_t offset) +static uint32_t pxa2xx_mmci_readw(void *opaque, hwaddr offset) { PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque; s->ac_width = 4; @@ -408,7 +408,7 @@ static uint32_t pxa2xx_mmci_readw(void *opaque, target_phys_addr_t offset) } static void pxa2xx_mmci_writeb(void *opaque, - target_phys_addr_t offset, uint32_t value) + hwaddr offset, uint32_t value) { PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque; s->ac_width = 1; @@ -416,7 +416,7 @@ static void pxa2xx_mmci_writeb(void *opaque, } static void pxa2xx_mmci_writeh(void *opaque, - target_phys_addr_t offset, uint32_t value) + hwaddr offset, uint32_t value) { PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque; s->ac_width = 2; @@ -424,7 +424,7 @@ static void pxa2xx_mmci_writeh(void *opaque, } static void pxa2xx_mmci_writew(void *opaque, - target_phys_addr_t offset, uint32_t value) + hwaddr offset, uint32_t value) { PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque; s->ac_width = 4; @@ -522,7 +522,7 @@ static int pxa2xx_mmci_load(QEMUFile *f, void *opaque, int version_id) } PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, - target_phys_addr_t base, + hwaddr base, BlockDriverState *bd, qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma) { diff --git a/hw/pxa2xx_pcmcia.c b/hw/pxa2xx_pcmcia.c index b15872a9d9..3a79c728ab 100644 --- a/hw/pxa2xx_pcmcia.c +++ b/hw/pxa2xx_pcmcia.c @@ -27,7 +27,7 @@ struct PXA2xxPCMCIAState { }; static uint64_t pxa2xx_pcmcia_common_read(void *opaque, - target_phys_addr_t offset, unsigned size) + hwaddr offset, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; @@ -38,7 +38,7 @@ static uint64_t pxa2xx_pcmcia_common_read(void *opaque, return 0; } -static void pxa2xx_pcmcia_common_write(void *opaque, target_phys_addr_t offset, +static void pxa2xx_pcmcia_common_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; @@ -49,7 +49,7 @@ static void pxa2xx_pcmcia_common_write(void *opaque, target_phys_addr_t offset, } static uint64_t pxa2xx_pcmcia_attr_read(void *opaque, - target_phys_addr_t offset, unsigned size) + hwaddr offset, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; @@ -60,7 +60,7 @@ static uint64_t pxa2xx_pcmcia_attr_read(void *opaque, return 0; } -static void pxa2xx_pcmcia_attr_write(void *opaque, target_phys_addr_t offset, +static void pxa2xx_pcmcia_attr_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; @@ -71,7 +71,7 @@ static void pxa2xx_pcmcia_attr_write(void *opaque, target_phys_addr_t offset, } static uint64_t pxa2xx_pcmcia_io_read(void *opaque, - target_phys_addr_t offset, unsigned size) + hwaddr offset, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; @@ -82,7 +82,7 @@ static uint64_t pxa2xx_pcmcia_io_read(void *opaque, return 0; } -static void pxa2xx_pcmcia_io_write(void *opaque, target_phys_addr_t offset, +static void pxa2xx_pcmcia_io_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; @@ -120,7 +120,7 @@ static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level) } PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, - target_phys_addr_t base) + hwaddr base) { PXA2xxPCMCIAState *s; diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c index e1e8830ff0..70b2b79d07 100644 --- a/hw/pxa2xx_pic.c +++ b/hw/pxa2xx_pic.c @@ -119,7 +119,7 @@ static inline uint32_t pxa2xx_pic_highest(PXA2xxPICState *s) { return ichp; } -static uint64_t pxa2xx_pic_mem_read(void *opaque, target_phys_addr_t offset, +static uint64_t pxa2xx_pic_mem_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxPICState *s = (PXA2xxPICState *) opaque; @@ -159,7 +159,7 @@ static uint64_t pxa2xx_pic_mem_read(void *opaque, target_phys_addr_t offset, } } -static void pxa2xx_pic_mem_write(void *opaque, target_phys_addr_t offset, +static void pxa2xx_pic_mem_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PXA2xxPICState *s = (PXA2xxPICState *) opaque; @@ -257,7 +257,7 @@ static int pxa2xx_pic_post_load(void *opaque, int version_id) return 0; } -DeviceState *pxa2xx_pic_init(target_phys_addr_t base, ARMCPU *cpu) +DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu) { CPUARMState *env = &cpu->env; DeviceState *dev = qdev_create(NULL, "pxa2xx_pic"); diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c index 77b033b541..8242d26c37 100644 --- a/hw/pxa2xx_timer.c +++ b/hw/pxa2xx_timer.c @@ -149,7 +149,7 @@ static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n) qemu_mod_timer(s->tm4[n].tm.qtimer, new_qemu); } -static uint64_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset, +static uint64_t pxa2xx_timer_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque; @@ -227,7 +227,7 @@ static uint64_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset, return 0; } -static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset, +static void pxa2xx_timer_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { int i, tm = 0; diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c index b711b6bf96..de0ba8726e 100644 --- a/hw/qdev-addr.c +++ b/hw/qdev-addr.c @@ -1,12 +1,12 @@ #include "qdev.h" #include "qdev-addr.h" -#include "targphys.h" +#include "hwaddr.h" /* --- target physical address --- */ static int parse_taddr(DeviceState *dev, Property *prop, const char *str) { - target_phys_addr_t *ptr = qdev_get_prop_ptr(dev, prop); + hwaddr *ptr = qdev_get_prop_ptr(dev, prop); *ptr = strtoull(str, NULL, 16); return 0; @@ -14,7 +14,7 @@ static int parse_taddr(DeviceState *dev, Property *prop, const char *str) static int print_taddr(DeviceState *dev, Property *prop, char *dest, size_t len) { - target_phys_addr_t *ptr = qdev_get_prop_ptr(dev, prop); + hwaddr *ptr = qdev_get_prop_ptr(dev, prop); return snprintf(dest, len, "0x" TARGET_FMT_plx, *ptr); } @@ -23,7 +23,7 @@ static void get_taddr(Object *obj, Visitor *v, void *opaque, { DeviceState *dev = DEVICE(obj); Property *prop = opaque; - target_phys_addr_t *ptr = qdev_get_prop_ptr(dev, prop); + hwaddr *ptr = qdev_get_prop_ptr(dev, prop); int64_t value; value = *ptr; @@ -35,7 +35,7 @@ static void set_taddr(Object *obj, Visitor *v, void *opaque, { DeviceState *dev = DEVICE(obj); Property *prop = opaque; - target_phys_addr_t *ptr = qdev_get_prop_ptr(dev, prop); + hwaddr *ptr = qdev_get_prop_ptr(dev, prop); Error *local_err = NULL; int64_t value; @@ -49,12 +49,12 @@ static void set_taddr(Object *obj, Visitor *v, void *opaque, error_propagate(errp, local_err); return; } - if ((uint64_t)value <= (uint64_t) ~(target_phys_addr_t)0) { + if ((uint64_t)value <= (uint64_t) ~(hwaddr)0) { *ptr = value; } else { error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, dev->id?:"", name, value, (uint64_t) 0, - (uint64_t) ~(target_phys_addr_t)0); + (uint64_t) ~(hwaddr)0); } } @@ -67,7 +67,7 @@ PropertyInfo qdev_prop_taddr = { .set = set_taddr, }; -void qdev_prop_set_taddr(DeviceState *dev, const char *name, target_phys_addr_t value) +void qdev_prop_set_taddr(DeviceState *dev, const char *name, hwaddr value) { Error *errp = NULL; object_property_set_int(OBJECT(dev), value, name, &errp); diff --git a/hw/qdev-addr.h b/hw/qdev-addr.h index a0ddf3863c..ea5ecb4d78 100644 --- a/hw/qdev-addr.h +++ b/hw/qdev-addr.h @@ -1,5 +1,5 @@ #define DEFINE_PROP_TADDR(_n, _s, _f, _d) \ - DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_taddr, target_phys_addr_t) + DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_taddr, hwaddr) extern PropertyInfo qdev_prop_taddr; -void qdev_prop_set_taddr(DeviceState *dev, const char *name, target_phys_addr_t value); +void qdev_prop_set_taddr(DeviceState *dev, const char *name, hwaddr value); diff --git a/hw/qxl.c b/hw/qxl.c index 1d16863c5e..d54daf6d3b 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1428,7 +1428,7 @@ static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm) qxl_rom_set_dirty(d); } -static void ioport_write(void *opaque, target_phys_addr_t addr, +static void ioport_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { PCIQXLDevice *d = opaque; @@ -1653,7 +1653,7 @@ cancel_async: } } -static uint64_t ioport_read(void *opaque, target_phys_addr_t addr, +static uint64_t ioport_read(void *opaque, hwaddr addr, unsigned size) { PCIQXLDevice *qxl = opaque; diff --git a/hw/r2d.c b/hw/r2d.c index 3cb6942056..66212e9cda 100644 --- a/hw/r2d.c +++ b/hw/r2d.c @@ -127,7 +127,7 @@ static void r2d_fpga_irq_set(void *opaque, int n, int level) update_irl(fpga); } -static uint32_t r2d_fpga_read(void *opaque, target_phys_addr_t addr) +static uint32_t r2d_fpga_read(void *opaque, hwaddr addr) { r2d_fpga_t *s = opaque; @@ -146,7 +146,7 @@ static uint32_t r2d_fpga_read(void *opaque, target_phys_addr_t addr) } static void -r2d_fpga_write(void *opaque, target_phys_addr_t addr, uint32_t value) +r2d_fpga_write(void *opaque, hwaddr addr, uint32_t value) { r2d_fpga_t *s = opaque; @@ -178,7 +178,7 @@ static const MemoryRegionOps r2d_fpga_ops = { }; static qemu_irq *r2d_fpga_init(MemoryRegion *sysmem, - target_phys_addr_t base, qemu_irq irl) + hwaddr base, qemu_irq irl) { r2d_fpga_t *s; diff --git a/hw/rc4030.c b/hw/rc4030.c index 9f39b30505..e0024c87e8 100644 --- a/hw/rc4030.c +++ b/hw/rc4030.c @@ -112,7 +112,7 @@ static void set_next_tick(rc4030State *s) } /* called for accesses to rc4030 */ -static uint32_t rc4030_readl(void *opaque, target_phys_addr_t addr) +static uint32_t rc4030_readl(void *opaque, hwaddr addr) { rc4030State *s = opaque; uint32_t val; @@ -250,7 +250,7 @@ static uint32_t rc4030_readl(void *opaque, target_phys_addr_t addr) return val; } -static uint32_t rc4030_readw(void *opaque, target_phys_addr_t addr) +static uint32_t rc4030_readw(void *opaque, hwaddr addr) { uint32_t v = rc4030_readl(opaque, addr & ~0x3); if (addr & 0x2) @@ -259,13 +259,13 @@ static uint32_t rc4030_readw(void *opaque, target_phys_addr_t addr) return v & 0xffff; } -static uint32_t rc4030_readb(void *opaque, target_phys_addr_t addr) +static uint32_t rc4030_readb(void *opaque, hwaddr addr) { uint32_t v = rc4030_readl(opaque, addr & ~0x3); return (v >> (8 * (addr & 0x3))) & 0xff; } -static void rc4030_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +static void rc4030_writel(void *opaque, hwaddr addr, uint32_t val) { rc4030State *s = opaque; addr &= 0x3fff; @@ -308,7 +308,7 @@ static void rc4030_writel(void *opaque, target_phys_addr_t addr, uint32_t val) case 0x0060: /* HACK */ if (s->cache_ltag == 0x80000001 && s->cache_bmask == 0xf0f0f0f) { - target_phys_addr_t dest = s->cache_ptag & ~0x1; + hwaddr dest = s->cache_ptag & ~0x1; dest += (s->cache_maint & 0x3) << 3; cpu_physical_memory_write(dest, &val, 4); } @@ -390,7 +390,7 @@ static void rc4030_writel(void *opaque, target_phys_addr_t addr, uint32_t val) } } -static void rc4030_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +static void rc4030_writew(void *opaque, hwaddr addr, uint32_t val) { uint32_t old_val = rc4030_readl(opaque, addr & ~0x3); @@ -401,7 +401,7 @@ static void rc4030_writew(void *opaque, target_phys_addr_t addr, uint32_t val) rc4030_writel(opaque, addr & ~0x3, val); } -static void rc4030_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +static void rc4030_writeb(void *opaque, hwaddr addr, uint32_t val) { uint32_t old_val = rc4030_readl(opaque, addr & ~0x3); @@ -479,7 +479,7 @@ static void rc4030_periodic_timer(void *opaque) qemu_irq_raise(s->timer_irq); } -static uint32_t jazzio_readw(void *opaque, target_phys_addr_t addr) +static uint32_t jazzio_readw(void *opaque, hwaddr addr) { rc4030State *s = opaque; uint32_t val; @@ -517,14 +517,14 @@ static uint32_t jazzio_readw(void *opaque, target_phys_addr_t addr) return val; } -static uint32_t jazzio_readb(void *opaque, target_phys_addr_t addr) +static uint32_t jazzio_readb(void *opaque, hwaddr addr) { uint32_t v; v = jazzio_readw(opaque, addr & ~0x1); return (v >> (8 * (addr & 0x1))) & 0xff; } -static uint32_t jazzio_readl(void *opaque, target_phys_addr_t addr) +static uint32_t jazzio_readl(void *opaque, hwaddr addr) { uint32_t v; v = jazzio_readw(opaque, addr); @@ -532,7 +532,7 @@ static uint32_t jazzio_readl(void *opaque, target_phys_addr_t addr) return v; } -static void jazzio_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +static void jazzio_writew(void *opaque, hwaddr addr, uint32_t val) { rc4030State *s = opaque; addr &= 0xfff; @@ -551,7 +551,7 @@ static void jazzio_writew(void *opaque, target_phys_addr_t addr, uint32_t val) } } -static void jazzio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +static void jazzio_writeb(void *opaque, hwaddr addr, uint32_t val) { uint32_t old_val = jazzio_readw(opaque, addr & ~0x1); @@ -566,7 +566,7 @@ static void jazzio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) jazzio_writew(opaque, addr & ~0x1, val); } -static void jazzio_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +static void jazzio_writel(void *opaque, hwaddr addr, uint32_t val) { jazzio_writew(opaque, addr, val & 0xffff); jazzio_writew(opaque, addr + 2, (val >> 16) & 0xffff); @@ -672,11 +672,11 @@ static void rc4030_save(QEMUFile *f, void *opaque) qemu_put_be32(f, s->itr); } -void rc4030_dma_memory_rw(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write) +void rc4030_dma_memory_rw(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write) { rc4030State *s = opaque; - target_phys_addr_t entry_addr; - target_phys_addr_t phys_addr; + hwaddr entry_addr; + hwaddr phys_addr; dma_pagetable_entry entry; int index; int ncpy, i; @@ -713,7 +713,7 @@ void rc4030_dma_memory_rw(void *opaque, target_phys_addr_t addr, uint8_t *buf, i static void rc4030_do_dma(void *opaque, int n, uint8_t *buf, int len, int is_write) { rc4030State *s = opaque; - target_phys_addr_t dma_addr; + hwaddr dma_addr; int dev_to_mem; s->dma_regs[n][DMA_REG_ENABLE] &= ~(DMA_FLAG_TC_INTR | DMA_FLAG_MEM_INTR | DMA_FLAG_ADDR_INTR); diff --git a/hw/realview.c b/hw/realview.c index 8dc4be6ae0..baa92d42fd 100644 --- a/hw/realview.c +++ b/hw/realview.c @@ -145,7 +145,7 @@ static void realview_init(ram_addr_t ram_size, sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000); if (is_mpcore) { - target_phys_addr_t periphbase; + hwaddr periphbase; dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore"); qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); qdev_init_nofail(dev); diff --git a/hw/rtl8139.c b/hw/rtl8139.c index 6b28fea96a..10ced8ba7d 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -2455,7 +2455,7 @@ static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32 if (descriptor == 0 && (val & 0x8)) { - target_phys_addr_t tc_addr = rtl8139_addr64(s->TxStatus[0] & ~0x3f, s->TxStatus[1]); + hwaddr tc_addr = rtl8139_addr64(s->TxStatus[0] & ~0x3f, s->TxStatus[1]); /* dump tally counters to specified memory location */ RTL8139TallyCounters_dma_write(s, tc_addr); @@ -3219,33 +3219,33 @@ static uint32_t rtl8139_ioport_readl(void *opaque, uint32_t addr) /* */ -static void rtl8139_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +static void rtl8139_mmio_writeb(void *opaque, hwaddr addr, uint32_t val) { rtl8139_io_writeb(opaque, addr & 0xFF, val); } -static void rtl8139_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +static void rtl8139_mmio_writew(void *opaque, hwaddr addr, uint32_t val) { rtl8139_io_writew(opaque, addr & 0xFF, val); } -static void rtl8139_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +static void rtl8139_mmio_writel(void *opaque, hwaddr addr, uint32_t val) { rtl8139_io_writel(opaque, addr & 0xFF, val); } -static uint32_t rtl8139_mmio_readb(void *opaque, target_phys_addr_t addr) +static uint32_t rtl8139_mmio_readb(void *opaque, hwaddr addr) { return rtl8139_io_readb(opaque, addr & 0xFF); } -static uint32_t rtl8139_mmio_readw(void *opaque, target_phys_addr_t addr) +static uint32_t rtl8139_mmio_readw(void *opaque, hwaddr addr) { uint32_t val = rtl8139_io_readw(opaque, addr & 0xFF); return val; } -static uint32_t rtl8139_mmio_readl(void *opaque, target_phys_addr_t addr) +static uint32_t rtl8139_mmio_readl(void *opaque, hwaddr addr) { uint32_t val = rtl8139_io_readl(opaque, addr & 0xFF); return val; diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index a245684692..5849a964a4 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -56,7 +56,7 @@ static const VirtIOBindings virtio_s390_bindings; static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev); /* length of VirtIO device pages */ -const target_phys_addr_t virtio_size = S390_DEVICE_PAGES * TARGET_PAGE_SIZE; +const hwaddr virtio_size = S390_DEVICE_PAGES * TARGET_PAGE_SIZE; static void s390_virtio_bus_reset(void *opaque) { @@ -67,7 +67,7 @@ static void s390_virtio_bus_reset(void *opaque) void s390_virtio_reset_idx(VirtIOS390Device *dev) { int i; - target_phys_addr_t idx_addr; + hwaddr idx_addr; uint8_t num_vq; num_vq = s390_virtio_device_num_vq(dev); diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index 39ff17828b..85bd13e06f 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -168,8 +168,8 @@ static void s390_init(QEMUMachineInitArgs *args) int shift = 0; uint8_t *storage_keys; void *virtio_region; - target_phys_addr_t virtio_region_len; - target_phys_addr_t virtio_region_start; + hwaddr virtio_region_len; + hwaddr virtio_region_start; int i; /* s390x ram size detection needs a 16bit multiplier + an increment. So diff --git a/hw/sbi.c b/hw/sbi.c index 52982a9a3e..ca78a384c7 100644 --- a/hw/sbi.c +++ b/hw/sbi.c @@ -52,7 +52,7 @@ static void sbi_set_irq(void *opaque, int irq, int level) { } -static uint64_t sbi_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t sbi_mem_read(void *opaque, hwaddr addr, unsigned size) { SBIState *s = opaque; @@ -69,7 +69,7 @@ static uint64_t sbi_mem_read(void *opaque, target_phys_addr_t addr, return ret; } -static void sbi_mem_write(void *opaque, target_phys_addr_t addr, +static void sbi_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned dize) { SBIState *s = opaque; diff --git a/hw/serial.c b/hw/serial.c index 5adbfafde5..ae84b22f35 100644 --- a/hw/serial.c +++ b/hw/serial.c @@ -734,14 +734,14 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase, } /* Memory mapped interface */ -static uint64_t serial_mm_read(void *opaque, target_phys_addr_t addr, +static uint64_t serial_mm_read(void *opaque, hwaddr addr, unsigned size) { SerialState *s = opaque; return serial_ioport_read(s, addr >> s->it_shift); } -static void serial_mm_write(void *opaque, target_phys_addr_t addr, +static void serial_mm_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { SerialState *s = opaque; @@ -768,7 +768,7 @@ static const MemoryRegionOps serial_mm_ops[3] = { }; SerialState *serial_mm_init(MemoryRegion *address_space, - target_phys_addr_t base, int it_shift, + hwaddr base, int it_shift, qemu_irq irq, int baudbase, CharDriverState *chr, enum device_endian end) { diff --git a/hw/serial.h b/hw/serial.h index 55a1ac5e9b..f1e3c4aaa7 100644 --- a/hw/serial.h +++ b/hw/serial.h @@ -91,7 +91,7 @@ void serial_set_frequency(SerialState *s, uint32_t frequency); SerialState *serial_init(int base, qemu_irq irq, int baudbase, CharDriverState *chr); SerialState *serial_mm_init(MemoryRegion *address_space, - target_phys_addr_t base, int it_shift, + hwaddr base, int it_shift, qemu_irq irq, int baudbase, CharDriverState *chr, enum device_endian end); diff --git a/hw/sh.h b/hw/sh.h index 40df18c5dc..77bf8aad2c 100644 --- a/hw/sh.h +++ b/hw/sh.h @@ -31,7 +31,7 @@ int sh7750_register_io_device(struct SH7750State *s, #define TMU012_FEAT_TOCR (1 << 0) #define TMU012_FEAT_3CHAN (1 << 1) #define TMU012_FEAT_EXTCLK (1 << 2) -void tmu012_init(struct MemoryRegion *sysmem, target_phys_addr_t base, +void tmu012_init(struct MemoryRegion *sysmem, hwaddr base, int feat, uint32_t freq, qemu_irq ch0_irq, qemu_irq ch1_irq, qemu_irq ch2_irq0, qemu_irq ch2_irq1); @@ -40,7 +40,7 @@ void tmu012_init(struct MemoryRegion *sysmem, target_phys_addr_t base, /* sh_serial.c */ #define SH_SERIAL_FEAT_SCIF (1 << 0) void sh_serial_init(MemoryRegion *sysmem, - target_phys_addr_t base, int feat, + hwaddr base, int feat, uint32_t freq, CharDriverState *chr, qemu_irq eri_source, qemu_irq rxi_source, diff --git a/hw/sh7750.c b/hw/sh7750.c index e7129283d1..8bcf0df96f 100644 --- a/hw/sh7750.c +++ b/hw/sh7750.c @@ -197,19 +197,19 @@ static void portb_changed(SH7750State * s, uint16_t prev) Memory **********************************************************************/ -static void error_access(const char *kind, target_phys_addr_t addr) +static void error_access(const char *kind, hwaddr addr) { fprintf(stderr, "%s to %s (0x" TARGET_FMT_plx ") not supported\n", kind, regname(addr), addr); } -static void ignore_access(const char *kind, target_phys_addr_t addr) +static void ignore_access(const char *kind, hwaddr addr) { fprintf(stderr, "%s to %s (0x" TARGET_FMT_plx ") ignored\n", kind, regname(addr), addr); } -static uint32_t sh7750_mem_readb(void *opaque, target_phys_addr_t addr) +static uint32_t sh7750_mem_readb(void *opaque, hwaddr addr) { switch (addr) { default: @@ -218,7 +218,7 @@ static uint32_t sh7750_mem_readb(void *opaque, target_phys_addr_t addr) } } -static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr) +static uint32_t sh7750_mem_readw(void *opaque, hwaddr addr) { SH7750State *s = opaque; @@ -252,7 +252,7 @@ static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr) } } -static uint32_t sh7750_mem_readl(void *opaque, target_phys_addr_t addr) +static uint32_t sh7750_mem_readl(void *opaque, hwaddr addr) { SH7750State *s = opaque; @@ -301,7 +301,7 @@ static uint32_t sh7750_mem_readl(void *opaque, target_phys_addr_t addr) #define is_in_sdrmx(a, x) (a >= SH7750_SDMR ## x ## _A7 \ && a <= (SH7750_SDMR ## x ## _A7 + SH7750_SDMR ## x ## _REGNB)) -static void sh7750_mem_writeb(void *opaque, target_phys_addr_t addr, +static void sh7750_mem_writeb(void *opaque, hwaddr addr, uint32_t mem_value) { @@ -314,7 +314,7 @@ static void sh7750_mem_writeb(void *opaque, target_phys_addr_t addr, abort(); } -static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr, +static void sh7750_mem_writew(void *opaque, hwaddr addr, uint32_t mem_value) { SH7750State *s = opaque; @@ -366,7 +366,7 @@ static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr, } } -static void sh7750_mem_writel(void *opaque, target_phys_addr_t addr, +static void sh7750_mem_writel(void *opaque, hwaddr addr, uint32_t mem_value) { SH7750State *s = opaque; @@ -624,14 +624,14 @@ static struct intc_group groups_irl[] = { #define MM_UTLB_DATA (7) #define MM_REGION_TYPE(addr) ((addr & MM_REGION_MASK) >> 24) -static uint64_t invalid_read(void *opaque, target_phys_addr_t addr) +static uint64_t invalid_read(void *opaque, hwaddr addr) { abort(); return 0; } -static uint64_t sh7750_mmct_read(void *opaque, target_phys_addr_t addr, +static uint64_t sh7750_mmct_read(void *opaque, hwaddr addr, unsigned size) { SH7750State *s = opaque; @@ -669,13 +669,13 @@ static uint64_t sh7750_mmct_read(void *opaque, target_phys_addr_t addr, return ret; } -static void invalid_write(void *opaque, target_phys_addr_t addr, +static void invalid_write(void *opaque, hwaddr addr, uint64_t mem_value) { abort(); } -static void sh7750_mmct_write(void *opaque, target_phys_addr_t addr, +static void sh7750_mmct_write(void *opaque, hwaddr addr, uint64_t mem_value, unsigned size) { SH7750State *s = opaque; diff --git a/hw/sh_intc.c b/hw/sh_intc.c index 7d31ced858..c3f77d5092 100644 --- a/hw/sh_intc.c +++ b/hw/sh_intc.c @@ -219,7 +219,7 @@ static void sh_intc_toggle_mask(struct intc_desc *desc, intc_enum id, #endif } -static uint64_t sh_intc_read(void *opaque, target_phys_addr_t offset, +static uint64_t sh_intc_read(void *opaque, hwaddr offset, unsigned size) { struct intc_desc *desc = opaque; @@ -238,7 +238,7 @@ static uint64_t sh_intc_read(void *opaque, target_phys_addr_t offset, return *valuep; } -static void sh_intc_write(void *opaque, target_phys_addr_t offset, +static void sh_intc_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { struct intc_desc *desc = opaque; diff --git a/hw/sh_pci.c b/hw/sh_pci.c index 0cfac46f7f..fdec71b9e8 100644 --- a/hw/sh_pci.c +++ b/hw/sh_pci.c @@ -41,7 +41,7 @@ typedef struct SHPCIState { uint32_t iobr; } SHPCIState; -static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint64_t val, +static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t val, unsigned size) { SHPCIState *pcic = p; @@ -69,7 +69,7 @@ static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint64_t val, } } -static uint64_t sh_pci_reg_read (void *p, target_phys_addr_t addr, +static uint64_t sh_pci_reg_read (void *p, hwaddr addr, unsigned size) { SHPCIState *pcic = p; diff --git a/hw/sh_serial.c b/hw/sh_serial.c index 1d1883dd20..9da5d08fee 100644 --- a/hw/sh_serial.c +++ b/hw/sh_serial.c @@ -78,7 +78,7 @@ static void sh_serial_clear_fifo(sh_serial_state * s) s->rx_tail = 0; } -static void sh_serial_write(void *opaque, target_phys_addr_t offs, +static void sh_serial_write(void *opaque, hwaddr offs, uint64_t val, unsigned size) { sh_serial_state *s = opaque; @@ -187,11 +187,11 @@ static void sh_serial_write(void *opaque, target_phys_addr_t offs, } fprintf(stderr, "sh_serial: unsupported write to 0x%02" - TARGET_PRIxPHYS "\n", offs); + HWADDR_PRIx "\n", offs); abort(); } -static uint64_t sh_serial_read(void *opaque, target_phys_addr_t offs, +static uint64_t sh_serial_read(void *opaque, hwaddr offs, unsigned size) { sh_serial_state *s = opaque; @@ -289,7 +289,7 @@ static uint64_t sh_serial_read(void *opaque, target_phys_addr_t offs, if (ret & ~((1 << 16) - 1)) { fprintf(stderr, "sh_serial: unsupported read from 0x%02" - TARGET_PRIxPHYS "\n", offs); + HWADDR_PRIx "\n", offs); abort(); } @@ -353,7 +353,7 @@ static const MemoryRegionOps sh_serial_ops = { }; void sh_serial_init(MemoryRegion *sysmem, - target_phys_addr_t base, int feat, + hwaddr base, int feat, uint32_t freq, CharDriverState *chr, qemu_irq eri_source, qemu_irq rxi_source, diff --git a/hw/sh_timer.c b/hw/sh_timer.c index 64bf604ba4..c0365b1142 100644 --- a/hw/sh_timer.c +++ b/hw/sh_timer.c @@ -59,7 +59,7 @@ static void sh_timer_update(sh_timer_state *s) s->int_level = new_level; } -static uint32_t sh_timer_read(void *opaque, target_phys_addr_t offset) +static uint32_t sh_timer_read(void *opaque, hwaddr offset) { sh_timer_state *s = (sh_timer_state *)opaque; @@ -79,7 +79,7 @@ static uint32_t sh_timer_read(void *opaque, target_phys_addr_t offset) } } -static void sh_timer_write(void *opaque, target_phys_addr_t offset, +static void sh_timer_write(void *opaque, hwaddr offset, uint32_t value) { sh_timer_state *s = (sh_timer_state *)opaque; @@ -222,7 +222,7 @@ typedef struct { int feat; } tmu012_state; -static uint64_t tmu012_read(void *opaque, target_phys_addr_t offset, +static uint64_t tmu012_read(void *opaque, hwaddr offset, unsigned size) { tmu012_state *s = (tmu012_state *)opaque; @@ -253,7 +253,7 @@ static uint64_t tmu012_read(void *opaque, target_phys_addr_t offset, return 0; } -static void tmu012_write(void *opaque, target_phys_addr_t offset, +static void tmu012_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { tmu012_state *s = (tmu012_state *)opaque; @@ -303,7 +303,7 @@ static const MemoryRegionOps tmu012_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -void tmu012_init(MemoryRegion *sysmem, target_phys_addr_t base, +void tmu012_init(MemoryRegion *sysmem, hwaddr base, int feat, uint32_t freq, qemu_irq ch0_irq, qemu_irq ch1_irq, qemu_irq ch2_irq0, qemu_irq ch2_irq1) diff --git a/hw/sharpsl.h b/hw/sharpsl.h index 0b3a774f2f..13981a6d03 100644 --- a/hw/sharpsl.h +++ b/hw/sharpsl.h @@ -12,6 +12,6 @@ /* zaurus.c */ #define SL_PXA_PARAM_BASE 0xa0000a00 -void sl_bootparam_write(target_phys_addr_t ptr); +void sl_bootparam_write(hwaddr ptr); #endif diff --git a/hw/shpc.c b/hw/shpc.c index a5baf246f1..4597bbde75 100644 --- a/hw/shpc.c +++ b/hw/shpc.c @@ -466,13 +466,13 @@ static int shpc_cap_add_config(PCIDevice *d) return 0; } -static uint64_t shpc_mmio_read(void *opaque, target_phys_addr_t addr, +static uint64_t shpc_mmio_read(void *opaque, hwaddr addr, unsigned size) { return shpc_read(opaque, addr, size); } -static void shpc_mmio_write(void *opaque, target_phys_addr_t addr, +static void shpc_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { shpc_write(opaque, addr, val, size); diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c index 7fdc3be086..6aafa8b233 100644 --- a/hw/slavio_intctl.c +++ b/hw/slavio_intctl.c @@ -78,7 +78,7 @@ typedef struct SLAVIO_INTCTLState { static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs); // per-cpu interrupt controller -static uint64_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr, +static uint64_t slavio_intctl_mem_readl(void *opaque, hwaddr addr, unsigned size) { SLAVIO_CPUINTCTLState *s = opaque; @@ -98,7 +98,7 @@ static uint64_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr, return ret; } -static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr, +static void slavio_intctl_mem_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size) { SLAVIO_CPUINTCTLState *s = opaque; @@ -135,7 +135,7 @@ static const MemoryRegionOps slavio_intctl_mem_ops = { }; // master system interrupt controller -static uint64_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr, +static uint64_t slavio_intctlm_mem_readl(void *opaque, hwaddr addr, unsigned size) { SLAVIO_INTCTLState *s = opaque; @@ -161,7 +161,7 @@ static uint64_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr, return ret; } -static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr, +static void slavio_intctlm_mem_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size) { SLAVIO_INTCTLState *s = opaque; diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c index 944835e880..682fb457f5 100644 --- a/hw/slavio_misc.c +++ b/hw/slavio_misc.c @@ -107,7 +107,7 @@ static void slavio_set_power_fail(void *opaque, int irq, int power_failing) slavio_misc_update_irq(s); } -static void slavio_cfg_mem_writeb(void *opaque, target_phys_addr_t addr, +static void slavio_cfg_mem_writeb(void *opaque, hwaddr addr, uint64_t val, unsigned size) { MiscState *s = opaque; @@ -117,7 +117,7 @@ static void slavio_cfg_mem_writeb(void *opaque, target_phys_addr_t addr, slavio_misc_update_irq(s); } -static uint64_t slavio_cfg_mem_readb(void *opaque, target_phys_addr_t addr, +static uint64_t slavio_cfg_mem_readb(void *opaque, hwaddr addr, unsigned size) { MiscState *s = opaque; @@ -138,7 +138,7 @@ static const MemoryRegionOps slavio_cfg_mem_ops = { }, }; -static void slavio_diag_mem_writeb(void *opaque, target_phys_addr_t addr, +static void slavio_diag_mem_writeb(void *opaque, hwaddr addr, uint64_t val, unsigned size) { MiscState *s = opaque; @@ -147,7 +147,7 @@ static void slavio_diag_mem_writeb(void *opaque, target_phys_addr_t addr, s->diag = val & 0xff; } -static uint64_t slavio_diag_mem_readb(void *opaque, target_phys_addr_t addr, +static uint64_t slavio_diag_mem_readb(void *opaque, hwaddr addr, unsigned size) { MiscState *s = opaque; @@ -168,7 +168,7 @@ static const MemoryRegionOps slavio_diag_mem_ops = { }, }; -static void slavio_mdm_mem_writeb(void *opaque, target_phys_addr_t addr, +static void slavio_mdm_mem_writeb(void *opaque, hwaddr addr, uint64_t val, unsigned size) { MiscState *s = opaque; @@ -177,7 +177,7 @@ static void slavio_mdm_mem_writeb(void *opaque, target_phys_addr_t addr, s->mctrl = val & 0xff; } -static uint64_t slavio_mdm_mem_readb(void *opaque, target_phys_addr_t addr, +static uint64_t slavio_mdm_mem_readb(void *opaque, hwaddr addr, unsigned size) { MiscState *s = opaque; @@ -198,7 +198,7 @@ static const MemoryRegionOps slavio_mdm_mem_ops = { }, }; -static void slavio_aux1_mem_writeb(void *opaque, target_phys_addr_t addr, +static void slavio_aux1_mem_writeb(void *opaque, hwaddr addr, uint64_t val, unsigned size) { MiscState *s = opaque; @@ -215,7 +215,7 @@ static void slavio_aux1_mem_writeb(void *opaque, target_phys_addr_t addr, s->aux1 = val & 0xff; } -static uint64_t slavio_aux1_mem_readb(void *opaque, target_phys_addr_t addr, +static uint64_t slavio_aux1_mem_readb(void *opaque, hwaddr addr, unsigned size) { MiscState *s = opaque; @@ -236,7 +236,7 @@ static const MemoryRegionOps slavio_aux1_mem_ops = { }, }; -static void slavio_aux2_mem_writeb(void *opaque, target_phys_addr_t addr, +static void slavio_aux2_mem_writeb(void *opaque, hwaddr addr, uint64_t val, unsigned size) { MiscState *s = opaque; @@ -252,7 +252,7 @@ static void slavio_aux2_mem_writeb(void *opaque, target_phys_addr_t addr, slavio_misc_update_irq(s); } -static uint64_t slavio_aux2_mem_readb(void *opaque, target_phys_addr_t addr, +static uint64_t slavio_aux2_mem_readb(void *opaque, hwaddr addr, unsigned size) { MiscState *s = opaque; @@ -273,7 +273,7 @@ static const MemoryRegionOps slavio_aux2_mem_ops = { }, }; -static void apc_mem_writeb(void *opaque, target_phys_addr_t addr, +static void apc_mem_writeb(void *opaque, hwaddr addr, uint64_t val, unsigned size) { APCState *s = opaque; @@ -282,7 +282,7 @@ static void apc_mem_writeb(void *opaque, target_phys_addr_t addr, qemu_irq_raise(s->cpu_halt); } -static uint64_t apc_mem_readb(void *opaque, target_phys_addr_t addr, +static uint64_t apc_mem_readb(void *opaque, hwaddr addr, unsigned size) { uint32_t ret = 0; @@ -301,7 +301,7 @@ static const MemoryRegionOps apc_mem_ops = { } }; -static uint64_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr, +static uint64_t slavio_sysctrl_mem_readl(void *opaque, hwaddr addr, unsigned size) { MiscState *s = opaque; @@ -318,7 +318,7 @@ static uint64_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr, return ret; } -static void slavio_sysctrl_mem_writel(void *opaque, target_phys_addr_t addr, +static void slavio_sysctrl_mem_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size) { MiscState *s = opaque; @@ -346,7 +346,7 @@ static const MemoryRegionOps slavio_sysctrl_mem_ops = { }, }; -static uint64_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr, +static uint64_t slavio_led_mem_readw(void *opaque, hwaddr addr, unsigned size) { MiscState *s = opaque; @@ -363,7 +363,7 @@ static uint64_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr, return ret; } -static void slavio_led_mem_writew(void *opaque, target_phys_addr_t addr, +static void slavio_led_mem_writew(void *opaque, hwaddr addr, uint64_t val, unsigned size) { MiscState *s = opaque; diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c index 97edebb3ba..c07ceb1de0 100644 --- a/hw/slavio_timer.c +++ b/hw/slavio_timer.c @@ -130,7 +130,7 @@ static void slavio_timer_irq(void *opaque) } } -static uint64_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr, +static uint64_t slavio_timer_mem_readl(void *opaque, hwaddr addr, unsigned size) { TimerContext *tc = opaque; @@ -190,7 +190,7 @@ static uint64_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr, return ret; } -static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, +static void slavio_timer_mem_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size) { TimerContext *tc = opaque; diff --git a/hw/sm501.c b/hw/sm501.c index 050d096533..4aafe49cce 100644 --- a/hw/sm501.c +++ b/hw/sm501.c @@ -456,7 +456,7 @@ typedef struct SM501State { DisplayState *ds; /* status & internal resources */ - target_phys_addr_t base; + hwaddr base; uint32_t local_mem_size_index; uint8_t * local_mem; MemoryRegion local_mem_region; @@ -726,7 +726,7 @@ static void sm501_2d_operation(SM501State * s) } } -static uint64_t sm501_system_config_read(void *opaque, target_phys_addr_t addr, +static uint64_t sm501_system_config_read(void *opaque, hwaddr addr, unsigned size) { SM501State * s = (SM501State *)opaque; @@ -779,7 +779,7 @@ static uint64_t sm501_system_config_read(void *opaque, target_phys_addr_t addr, return ret; } -static void sm501_system_config_write(void *opaque, target_phys_addr_t addr, +static void sm501_system_config_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { SM501State * s = (SM501State *)opaque; @@ -837,7 +837,7 @@ static const MemoryRegionOps sm501_system_config_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint32_t sm501_palette_read(void *opaque, target_phys_addr_t addr) +static uint32_t sm501_palette_read(void *opaque, hwaddr addr) { SM501State * s = (SM501State *)opaque; SM501_DPRINTF("sm501 palette read addr=%x\n", (int)addr); @@ -850,7 +850,7 @@ static uint32_t sm501_palette_read(void *opaque, target_phys_addr_t addr) } static void sm501_palette_write(void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { SM501State * s = (SM501State *)opaque; SM501_DPRINTF("sm501 palette write addr=%x, val=%x\n", @@ -863,7 +863,7 @@ static void sm501_palette_write(void *opaque, *(uint32_t*)&s->dc_palette[addr] = value; } -static uint64_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr, +static uint64_t sm501_disp_ctrl_read(void *opaque, hwaddr addr, unsigned size) { SM501State * s = (SM501State *)opaque; @@ -958,7 +958,7 @@ static uint64_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr, return ret; } -static void sm501_disp_ctrl_write(void *opaque, target_phys_addr_t addr, +static void sm501_disp_ctrl_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { SM501State * s = (SM501State *)opaque; @@ -1073,7 +1073,7 @@ static const MemoryRegionOps sm501_disp_ctrl_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint64_t sm501_2d_engine_read(void *opaque, target_phys_addr_t addr, +static uint64_t sm501_2d_engine_read(void *opaque, hwaddr addr, unsigned size) { SM501State * s = (SM501State *)opaque; @@ -1093,7 +1093,7 @@ static uint64_t sm501_2d_engine_read(void *opaque, target_phys_addr_t addr, return ret; } -static void sm501_2d_engine_write(void *opaque, target_phys_addr_t addr, +static void sm501_2d_engine_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { SM501State * s = (SM501State *)opaque; diff --git a/hw/smc91c111.c b/hw/smc91c111.c index d6ef302c6d..4ceed01a1a 100644 --- a/hw/smc91c111.c +++ b/hw/smc91c111.c @@ -276,7 +276,7 @@ static void smc91c111_reset(DeviceState *dev) #define SET_LOW(name, val) s->name = (s->name & 0xff00) | val #define SET_HIGH(name, val) s->name = (s->name & 0xff) | (val << 8) -static void smc91c111_writeb(void *opaque, target_phys_addr_t offset, +static void smc91c111_writeb(void *opaque, hwaddr offset, uint32_t value) { smc91c111_state *s = (smc91c111_state *)opaque; @@ -451,7 +451,7 @@ static void smc91c111_writeb(void *opaque, target_phys_addr_t offset, hw_error("smc91c111_write: Bad reg %d:%x\n", s->bank, (int)offset); } -static uint32_t smc91c111_readb(void *opaque, target_phys_addr_t offset) +static uint32_t smc91c111_readb(void *opaque, hwaddr offset) { smc91c111_state *s = (smc91c111_state *)opaque; @@ -595,14 +595,14 @@ static uint32_t smc91c111_readb(void *opaque, target_phys_addr_t offset) return 0; } -static void smc91c111_writew(void *opaque, target_phys_addr_t offset, +static void smc91c111_writew(void *opaque, hwaddr offset, uint32_t value) { smc91c111_writeb(opaque, offset, value & 0xff); smc91c111_writeb(opaque, offset + 1, value >> 8); } -static void smc91c111_writel(void *opaque, target_phys_addr_t offset, +static void smc91c111_writel(void *opaque, hwaddr offset, uint32_t value) { /* 32-bit writes to offset 0xc only actually write to the bank select @@ -612,7 +612,7 @@ static void smc91c111_writel(void *opaque, target_phys_addr_t offset, smc91c111_writew(opaque, offset + 2, value >> 16); } -static uint32_t smc91c111_readw(void *opaque, target_phys_addr_t offset) +static uint32_t smc91c111_readw(void *opaque, hwaddr offset) { uint32_t val; val = smc91c111_readb(opaque, offset); @@ -620,7 +620,7 @@ static uint32_t smc91c111_readw(void *opaque, target_phys_addr_t offset) return val; } -static uint32_t smc91c111_readl(void *opaque, target_phys_addr_t offset) +static uint32_t smc91c111_readl(void *opaque, hwaddr offset) { uint32_t val; val = smc91c111_readw(opaque, offset); diff --git a/hw/soc_dma.c b/hw/soc_dma.c index 03bc8468dd..50d5f84b4e 100644 --- a/hw/soc_dma.c +++ b/hw/soc_dma.c @@ -64,7 +64,7 @@ struct dma_s { struct memmap_entry_s { enum soc_dma_port_type type; - target_phys_addr_t addr; + hwaddr addr; union { struct { void *opaque; @@ -105,7 +105,7 @@ static void soc_dma_ch_run(void *opaque) } static inline struct memmap_entry_s *soc_dma_lookup(struct dma_s *dma, - target_phys_addr_t addr) + hwaddr addr) { struct memmap_entry_s *lo; int hi; @@ -255,7 +255,7 @@ struct soc_dma_s *soc_dma_init(int n) return &s->soc; } -void soc_dma_port_add_fifo(struct soc_dma_s *soc, target_phys_addr_t virt_base, +void soc_dma_port_add_fifo(struct soc_dma_s *soc, hwaddr virt_base, soc_dma_io_t fn, void *opaque, int out) { struct memmap_entry_s *entry; @@ -308,7 +308,7 @@ void soc_dma_port_add_fifo(struct soc_dma_s *soc, target_phys_addr_t virt_base, } void soc_dma_port_add_mem(struct soc_dma_s *soc, uint8_t *phys_base, - target_phys_addr_t virt_base, size_t size) + hwaddr virt_base, size_t size) { struct memmap_entry_s *entry; struct dma_s *dma = (struct dma_s *) soc; diff --git a/hw/soc_dma.h b/hw/soc_dma.h index 904b26c5a8..9340b8f38e 100644 --- a/hw/soc_dma.h +++ b/hw/soc_dma.h @@ -51,7 +51,7 @@ struct soc_dma_ch_s { int bytes; /* Initialised by the DMA module, call soc_dma_ch_update after writing. */ enum soc_dma_access_type type[2]; - target_phys_addr_t vaddr[2]; /* Updated by .transfer_fn(). */ + hwaddr vaddr[2]; /* Updated by .transfer_fn(). */ /* Private */ void *paddr[2]; soc_dma_io_t io_fn[2]; @@ -91,19 +91,19 @@ void soc_dma_ch_update(struct soc_dma_ch_s *ch); void soc_dma_reset(struct soc_dma_s *s); struct soc_dma_s *soc_dma_init(int n); -void soc_dma_port_add_fifo(struct soc_dma_s *dma, target_phys_addr_t virt_base, +void soc_dma_port_add_fifo(struct soc_dma_s *dma, hwaddr virt_base, soc_dma_io_t fn, void *opaque, int out); void soc_dma_port_add_mem(struct soc_dma_s *dma, uint8_t *phys_base, - target_phys_addr_t virt_base, size_t size); + hwaddr virt_base, size_t size); static inline void soc_dma_port_add_fifo_in(struct soc_dma_s *dma, - target_phys_addr_t virt_base, soc_dma_io_t fn, void *opaque) + hwaddr virt_base, soc_dma_io_t fn, void *opaque) { return soc_dma_port_add_fifo(dma, virt_base, fn, opaque, 0); } static inline void soc_dma_port_add_fifo_out(struct soc_dma_s *dma, - target_phys_addr_t virt_base, soc_dma_io_t fn, void *opaque) + hwaddr virt_base, soc_dma_io_t fn, void *opaque) { return soc_dma_port_add_fifo(dma, virt_base, fn, opaque, 1); } diff --git a/hw/spapr.c b/hw/spapr.c index 637b3fb718..73d75e818c 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -228,9 +228,9 @@ static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop, static void *spapr_create_fdt_skel(const char *cpu_model, - target_phys_addr_t initrd_base, - target_phys_addr_t initrd_size, - target_phys_addr_t kernel_size, + hwaddr initrd_base, + hwaddr initrd_size, + hwaddr kernel_size, const char *boot_device, const char *kernel_cmdline) { @@ -445,7 +445,7 @@ static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt) cpu_to_be32(0x0), cpu_to_be32(0x0), cpu_to_be32(0x0)}; char mem_name[32]; - target_phys_addr_t node0_size, mem_start; + hwaddr node0_size, mem_start; uint64_t mem_reg_property[2]; int i, off; @@ -502,9 +502,9 @@ static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt) } static void spapr_finalize_fdt(sPAPREnvironment *spapr, - target_phys_addr_t fdt_addr, - target_phys_addr_t rtas_addr, - target_phys_addr_t rtas_size) + hwaddr fdt_addr, + hwaddr rtas_addr, + hwaddr rtas_size) { int ret; void *fdt; @@ -679,7 +679,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args) int i; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); - target_phys_addr_t rma_alloc_size; + hwaddr rma_alloc_size; uint32_t initrd_base = 0; long kernel_size = 0, initrd_size = 0; long load_limit, rtas_limit, fw_size; diff --git a/hw/spapr.h b/hw/spapr.h index e984e3fc3c..8ee69bdec8 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -13,12 +13,12 @@ typedef struct sPAPREnvironment { QLIST_HEAD(, sPAPRPHBState) phbs; struct icp_state *icp; - target_phys_addr_t ram_limit; + hwaddr ram_limit; void *htab; long htab_shift; - target_phys_addr_t rma_size; + hwaddr rma_size; int vrma_adjust; - target_phys_addr_t fdt_addr, rtas_addr; + hwaddr fdt_addr, rtas_addr; long rtas_size; void *fdt_skel; target_ulong entry_point; @@ -321,8 +321,8 @@ void spapr_rtas_register(const char *name, spapr_rtas_fn fn); target_ulong spapr_rtas_call(sPAPREnvironment *spapr, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets); -int spapr_rtas_device_tree_setup(void *fdt, target_phys_addr_t rtas_addr, - target_phys_addr_t rtas_size); +int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr, + hwaddr rtas_size); #define SPAPR_TCE_PAGE_SHIFT 12 #define SPAPR_TCE_PAGE_SIZE (1ULL << SPAPR_TCE_PAGE_SHIFT) diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c index 33f84e27aa..86dc8f92e2 100644 --- a/hw/spapr_iommu.c +++ b/hw/spapr_iommu.c @@ -66,8 +66,8 @@ static sPAPRTCETable *spapr_tce_find_by_liobn(uint32_t liobn) static int spapr_tce_translate(DMAContext *dma, dma_addr_t addr, - target_phys_addr_t *paddr, - target_phys_addr_t *len, + hwaddr *paddr, + hwaddr *len, DMADirection dir) { sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma); @@ -82,7 +82,7 @@ static int spapr_tce_translate(DMAContext *dma, if (tcet->bypass) { *paddr = addr; - *len = (target_phys_addr_t)-1; + *len = (hwaddr)-1; return 0; } diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index b628f89a02..a08ed11166 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -258,7 +258,7 @@ static int spapr_msicfg_find(sPAPRPHBState *phb, uint32_t config_addr, * This is required for msi_notify()/msix_notify() which * will write at the addresses via spapr_msi_write(). */ -static void spapr_msi_setmsg(PCIDevice *pdev, target_phys_addr_t addr, +static void spapr_msi_setmsg(PCIDevice *pdev, hwaddr addr, bool msix, unsigned req_num) { unsigned i; @@ -439,7 +439,7 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level) qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level); } -static uint64_t spapr_io_read(void *opaque, target_phys_addr_t addr, +static uint64_t spapr_io_read(void *opaque, hwaddr addr, unsigned size) { switch (size) { @@ -453,7 +453,7 @@ static uint64_t spapr_io_read(void *opaque, target_phys_addr_t addr, assert(0); } -static void spapr_io_write(void *opaque, target_phys_addr_t addr, +static void spapr_io_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { switch (size) { @@ -483,7 +483,7 @@ static const MemoryRegionOps spapr_io_ops = { * data is set to 0. * For MSI, the vector number is encoded in least bits in data. */ -static void spapr_msi_write(void *opaque, target_phys_addr_t addr, +static void spapr_msi_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { sPAPRPHBState *phb = opaque; diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index 670dc62a19..e307ac8035 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -42,8 +42,8 @@ typedef struct sPAPRPHBState { char *dtbusname; MemoryRegion memspace, iospace; - target_phys_addr_t mem_win_addr, mem_win_size, io_win_addr, io_win_size; - target_phys_addr_t msi_win_addr; + hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size; + hwaddr msi_win_addr; MemoryRegion memwindow, iowindow, msiwindow; uint32_t dma_liobn; diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c index b808f80017..67da27ba51 100644 --- a/hw/spapr_rtas.c +++ b/hw/spapr_rtas.c @@ -249,8 +249,8 @@ void spapr_rtas_register(const char *name, spapr_rtas_fn fn) rtas_next++; } -int spapr_rtas_device_tree_setup(void *fdt, target_phys_addr_t rtas_addr, - target_phys_addr_t rtas_size) +int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr, + hwaddr rtas_size) { int ret; int i; diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c index 1dbf69e808..d11a302f20 100644 --- a/hw/sparc32_dma.c +++ b/hw/sparc32_dma.c @@ -78,7 +78,7 @@ enum { }; /* Note: on sparc, the lance 16 bit bus is swapped */ -void ledma_memory_read(void *opaque, target_phys_addr_t addr, +void ledma_memory_read(void *opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap) { DMAState *s = opaque; @@ -98,7 +98,7 @@ void ledma_memory_read(void *opaque, target_phys_addr_t addr, } } -void ledma_memory_write(void *opaque, target_phys_addr_t addr, +void ledma_memory_write(void *opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap) { DMAState *s = opaque; @@ -165,7 +165,7 @@ void espdma_memory_write(void *opaque, uint8_t *buf, int len) s->dmaregs[1] += len; } -static uint64_t dma_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t dma_mem_read(void *opaque, hwaddr addr, unsigned size) { DMAState *s = opaque; @@ -182,7 +182,7 @@ static uint64_t dma_mem_read(void *opaque, target_phys_addr_t addr, return s->dmaregs[saddr]; } -static void dma_mem_write(void *opaque, target_phys_addr_t addr, +static void dma_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { DMAState *s = opaque; diff --git a/hw/sparc32_dma.h b/hw/sparc32_dma.h index 8b72c37a98..9497b13d34 100644 --- a/hw/sparc32_dma.h +++ b/hw/sparc32_dma.h @@ -2,9 +2,9 @@ #define SPARC32_DMA_H /* sparc32_dma.c */ -void ledma_memory_read(void *opaque, target_phys_addr_t addr, +void ledma_memory_read(void *opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap); -void ledma_memory_write(void *opaque, target_phys_addr_t addr, +void ledma_memory_write(void *opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap); void espdma_memory_read(void *opaque, uint8_t *buf, int len); void espdma_memory_write(void *opaque, uint8_t *buf, int len); diff --git a/hw/spitz.c b/hw/spitz.c index 29426266b1..944c274a82 100644 --- a/hw/spitz.c +++ b/hw/spitz.c @@ -60,7 +60,7 @@ typedef struct { ECCState ecc; } SLNANDState; -static uint64_t sl_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t sl_read(void *opaque, hwaddr addr, unsigned size) { SLNANDState *s = (SLNANDState *) opaque; int ryby; @@ -102,7 +102,7 @@ static uint64_t sl_read(void *opaque, target_phys_addr_t addr, unsigned size) return 0; } -static void sl_write(void *opaque, target_phys_addr_t addr, +static void sl_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { SLNANDState *s = (SLNANDState *) opaque; diff --git a/hw/stellaris.c b/hw/stellaris.c index bfb18b014e..b038f10f3a 100644 --- a/hw/stellaris.c +++ b/hw/stellaris.c @@ -141,7 +141,7 @@ static void gptm_tick(void *opaque) gptm_update_irq(s); } -static uint64_t gptm_read(void *opaque, target_phys_addr_t offset, +static uint64_t gptm_read(void *opaque, hwaddr offset, unsigned size) { gptm_state *s = (gptm_state *)opaque; @@ -190,7 +190,7 @@ static uint64_t gptm_read(void *opaque, target_phys_addr_t offset, } } -static void gptm_write(void *opaque, target_phys_addr_t offset, +static void gptm_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { gptm_state *s = (gptm_state *)opaque; @@ -410,7 +410,7 @@ static int ssys_board_class(const ssys_state *s) } } -static uint64_t ssys_read(void *opaque, target_phys_addr_t offset, +static uint64_t ssys_read(void *opaque, hwaddr offset, unsigned size) { ssys_state *s = (ssys_state *)opaque; @@ -515,7 +515,7 @@ static void ssys_calculate_system_clock(ssys_state *s) } } -static void ssys_write(void *opaque, target_phys_addr_t offset, +static void ssys_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { ssys_state *s = (ssys_state *)opaque; @@ -701,7 +701,7 @@ typedef struct { #define STELLARIS_I2C_MCS_IDLE 0x20 #define STELLARIS_I2C_MCS_BUSBSY 0x40 -static uint64_t stellaris_i2c_read(void *opaque, target_phys_addr_t offset, +static uint64_t stellaris_i2c_read(void *opaque, hwaddr offset, unsigned size) { stellaris_i2c_state *s = (stellaris_i2c_state *)opaque; @@ -738,7 +738,7 @@ static void stellaris_i2c_update(stellaris_i2c_state *s) qemu_set_irq(s->irq, level); } -static void stellaris_i2c_write(void *opaque, target_phys_addr_t offset, +static void stellaris_i2c_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { stellaris_i2c_state *s = (stellaris_i2c_state *)opaque; @@ -989,7 +989,7 @@ static void stellaris_adc_reset(stellaris_adc_state *s) } } -static uint64_t stellaris_adc_read(void *opaque, target_phys_addr_t offset, +static uint64_t stellaris_adc_read(void *opaque, hwaddr offset, unsigned size) { stellaris_adc_state *s = (stellaris_adc_state *)opaque; @@ -1037,7 +1037,7 @@ static uint64_t stellaris_adc_read(void *opaque, target_phys_addr_t offset, } } -static void stellaris_adc_write(void *opaque, target_phys_addr_t offset, +static void stellaris_adc_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { stellaris_adc_state *s = (stellaris_adc_state *)opaque; diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c index bc97280cca..a530b10598 100644 --- a/hw/stellaris_enet.c +++ b/hw/stellaris_enet.c @@ -130,7 +130,7 @@ static int stellaris_enet_can_receive(NetClientState *nc) return (s->np < 31); } -static uint64_t stellaris_enet_read(void *opaque, target_phys_addr_t offset, +static uint64_t stellaris_enet_read(void *opaque, hwaddr offset, unsigned size) { stellaris_enet_state *s = (stellaris_enet_state *)opaque; @@ -198,7 +198,7 @@ static uint64_t stellaris_enet_read(void *opaque, target_phys_addr_t offset, } } -static void stellaris_enet_write(void *opaque, target_phys_addr_t offset, +static void stellaris_enet_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { stellaris_enet_state *s = (stellaris_enet_state *)opaque; diff --git a/hw/strongarm.c b/hw/strongarm.c index 7150eeb2db..43855151ce 100644 --- a/hw/strongarm.c +++ b/hw/strongarm.c @@ -59,7 +59,7 @@ #endif static struct { - target_phys_addr_t io_base; + hwaddr io_base; int irq; } sa_serial[] = { { 0x80010000, SA_PIC_UART1 }, @@ -113,7 +113,7 @@ static void strongarm_pic_set_irq(void *opaque, int irq, int level) strongarm_pic_update(s); } -static uint64_t strongarm_pic_mem_read(void *opaque, target_phys_addr_t offset, +static uint64_t strongarm_pic_mem_read(void *opaque, hwaddr offset, unsigned size) { StrongARMPICState *s = opaque; @@ -138,7 +138,7 @@ static uint64_t strongarm_pic_mem_read(void *opaque, target_phys_addr_t offset, } } -static void strongarm_pic_mem_write(void *opaque, target_phys_addr_t offset, +static void strongarm_pic_mem_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { StrongARMPICState *s = opaque; @@ -294,7 +294,7 @@ static inline void strongarm_rtc_hz_tick(void *opaque) strongarm_rtc_int_update(s); } -static uint64_t strongarm_rtc_read(void *opaque, target_phys_addr_t addr, +static uint64_t strongarm_rtc_read(void *opaque, hwaddr addr, unsigned size) { StrongARMRTCState *s = opaque; @@ -316,7 +316,7 @@ static uint64_t strongarm_rtc_read(void *opaque, target_phys_addr_t addr, } } -static void strongarm_rtc_write(void *opaque, target_phys_addr_t addr, +static void strongarm_rtc_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { StrongARMRTCState *s = opaque; @@ -517,7 +517,7 @@ static void strongarm_gpio_handler_update(StrongARMGPIOInfo *s) s->prev_level = level; } -static uint64_t strongarm_gpio_read(void *opaque, target_phys_addr_t offset, +static uint64_t strongarm_gpio_read(void *opaque, hwaddr offset, unsigned size) { StrongARMGPIOInfo *s = opaque; @@ -559,7 +559,7 @@ static uint64_t strongarm_gpio_read(void *opaque, target_phys_addr_t offset, return 0; } -static void strongarm_gpio_write(void *opaque, target_phys_addr_t offset, +static void strongarm_gpio_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { StrongARMGPIOInfo *s = opaque; @@ -609,7 +609,7 @@ static const MemoryRegionOps strongarm_gpio_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static DeviceState *strongarm_gpio_init(target_phys_addr_t base, +static DeviceState *strongarm_gpio_init(hwaddr base, DeviceState *pic) { DeviceState *dev; @@ -729,7 +729,7 @@ static void strongarm_ppc_handler_update(StrongARMPPCInfo *s) s->prev_level = level; } -static uint64_t strongarm_ppc_read(void *opaque, target_phys_addr_t offset, +static uint64_t strongarm_ppc_read(void *opaque, hwaddr offset, unsigned size) { StrongARMPPCInfo *s = opaque; @@ -759,7 +759,7 @@ static uint64_t strongarm_ppc_read(void *opaque, target_phys_addr_t offset, return 0; } -static void strongarm_ppc_write(void *opaque, target_phys_addr_t offset, +static void strongarm_ppc_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { StrongARMPPCInfo *s = opaque; @@ -1095,7 +1095,7 @@ static void strongarm_uart_tx(void *opaque) strongarm_uart_update_int_status(s); } -static uint64_t strongarm_uart_read(void *opaque, target_phys_addr_t addr, +static uint64_t strongarm_uart_read(void *opaque, hwaddr addr, unsigned size) { StrongARMUARTState *s = opaque; @@ -1137,7 +1137,7 @@ static uint64_t strongarm_uart_read(void *opaque, target_phys_addr_t addr, } } -static void strongarm_uart_write(void *opaque, target_phys_addr_t addr, +static void strongarm_uart_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { StrongARMUARTState *s = opaque; @@ -1376,7 +1376,7 @@ static void strongarm_ssp_fifo_update(StrongARMSSPState *s) strongarm_ssp_int_update(s); } -static uint64_t strongarm_ssp_read(void *opaque, target_phys_addr_t addr, +static uint64_t strongarm_ssp_read(void *opaque, hwaddr addr, unsigned size) { StrongARMSSPState *s = opaque; @@ -1409,7 +1409,7 @@ static uint64_t strongarm_ssp_read(void *opaque, target_phys_addr_t addr, return 0; } -static void strongarm_ssp_write(void *opaque, target_phys_addr_t addr, +static void strongarm_ssp_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { StrongARMSSPState *s = opaque; diff --git a/hw/sun4c_intctl.c b/hw/sun4c_intctl.c index 8dfa5ecab6..8cd70ab64c 100644 --- a/hw/sun4c_intctl.c +++ b/hw/sun4c_intctl.c @@ -61,7 +61,7 @@ typedef struct Sun4c_INTCTLState { static void sun4c_check_interrupts(void *opaque); -static uint64_t sun4c_intctl_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t sun4c_intctl_mem_read(void *opaque, hwaddr addr, unsigned size) { Sun4c_INTCTLState *s = opaque; @@ -73,7 +73,7 @@ static uint64_t sun4c_intctl_mem_read(void *opaque, target_phys_addr_t addr, return ret; } -static void sun4c_intctl_mem_write(void *opaque, target_phys_addr_t addr, +static void sun4c_intctl_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { Sun4c_INTCTLState *s = opaque; diff --git a/hw/sun4m.c b/hw/sun4m.c index dbe93f9eb9..02673b228e 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -87,16 +87,16 @@ #define ESCC_CLOCK 4915200 struct sun4m_hwdef { - target_phys_addr_t iommu_base, iommu_pad_base, iommu_pad_len, slavio_base; - target_phys_addr_t intctl_base, counter_base, nvram_base, ms_kb_base; - target_phys_addr_t serial_base, fd_base; - target_phys_addr_t afx_base, idreg_base, dma_base, esp_base, le_base; - target_phys_addr_t tcx_base, cs_base, apc_base, aux1_base, aux2_base; - target_phys_addr_t bpp_base, dbri_base, sx_base; + hwaddr iommu_base, iommu_pad_base, iommu_pad_len, slavio_base; + hwaddr intctl_base, counter_base, nvram_base, ms_kb_base; + hwaddr serial_base, fd_base; + hwaddr afx_base, idreg_base, dma_base, esp_base, le_base; + hwaddr tcx_base, cs_base, apc_base, aux1_base, aux2_base; + hwaddr bpp_base, dbri_base, sx_base; struct { - target_phys_addr_t reg_base, vram_base; + hwaddr reg_base, vram_base; } vsimm[MAX_VSIMMS]; - target_phys_addr_t ecc_base; + hwaddr ecc_base; uint64_t max_mem; const char * const default_cpu_model; uint32_t ecc_version; @@ -108,13 +108,13 @@ struct sun4m_hwdef { #define MAX_IOUNITS 5 struct sun4d_hwdef { - target_phys_addr_t iounit_bases[MAX_IOUNITS], slavio_base; - target_phys_addr_t counter_base, nvram_base, ms_kb_base; - target_phys_addr_t serial_base; - target_phys_addr_t espdma_base, esp_base; - target_phys_addr_t ledma_base, le_base; - target_phys_addr_t tcx_base; - target_phys_addr_t sbi_base; + 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; @@ -123,11 +123,11 @@ struct sun4d_hwdef { }; struct sun4c_hwdef { - target_phys_addr_t iommu_base, slavio_base; - target_phys_addr_t intctl_base, counter_base, nvram_base, ms_kb_base; - target_phys_addr_t serial_base, fd_base; - target_phys_addr_t idreg_base, dma_base, esp_base, le_base; - target_phys_addr_t tcx_base, aux1_base; + 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; @@ -373,7 +373,7 @@ static unsigned long sun4m_load_kernel(const char *kernel_filename, return kernel_size; } -static void *iommu_init(target_phys_addr_t addr, uint32_t version, qemu_irq irq) +static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq) { DeviceState *dev; SysBusDevice *s; @@ -388,7 +388,7 @@ static void *iommu_init(target_phys_addr_t addr, uint32_t version, qemu_irq irq) return s; } -static void *sparc32_dma_init(target_phys_addr_t daddr, qemu_irq parent_irq, +static void *sparc32_dma_init(hwaddr daddr, qemu_irq parent_irq, void *iommu, qemu_irq *dev_irq, int is_ledma) { DeviceState *dev; @@ -406,7 +406,7 @@ static void *sparc32_dma_init(target_phys_addr_t daddr, qemu_irq parent_irq, return s; } -static void lance_init(NICInfo *nd, target_phys_addr_t leaddr, +static void lance_init(NICInfo *nd, hwaddr leaddr, void *dma_opaque, qemu_irq irq) { DeviceState *dev; @@ -426,8 +426,8 @@ static void lance_init(NICInfo *nd, target_phys_addr_t leaddr, qdev_connect_gpio_out(dma_opaque, 0, reset); } -static DeviceState *slavio_intctl_init(target_phys_addr_t addr, - target_phys_addr_t addrg, +static DeviceState *slavio_intctl_init(hwaddr addr, + hwaddr addrg, qemu_irq **parent_irq) { DeviceState *dev; @@ -455,7 +455,7 @@ static DeviceState *slavio_intctl_init(target_phys_addr_t addr, #define SYS_TIMER_OFFSET 0x10000ULL #define CPU_TIMER_OFFSET(cpu) (0x1000ULL * cpu) -static void slavio_timer_init_all(target_phys_addr_t addr, qemu_irq master_irq, +static void slavio_timer_init_all(hwaddr addr, qemu_irq master_irq, qemu_irq *cpu_irqs, unsigned int num_cpus) { DeviceState *dev; @@ -470,7 +470,7 @@ static void slavio_timer_init_all(target_phys_addr_t addr, qemu_irq master_irq, sysbus_mmio_map(s, 0, addr + SYS_TIMER_OFFSET); for (i = 0; i < MAX_CPUS; i++) { - sysbus_mmio_map(s, i + 1, addr + (target_phys_addr_t)CPU_TIMER_OFFSET(i)); + sysbus_mmio_map(s, i + 1, addr + (hwaddr)CPU_TIMER_OFFSET(i)); sysbus_connect_irq(s, i + 1, cpu_irqs[i]); } } @@ -492,9 +492,9 @@ static Notifier slavio_system_powerdown_notifier = { #define MISC_MDM 0x01b00000 #define MISC_SYS 0x01f00000 -static void slavio_misc_init(target_phys_addr_t base, - target_phys_addr_t aux1_base, - target_phys_addr_t aux2_base, qemu_irq irq, +static void slavio_misc_init(hwaddr base, + hwaddr aux1_base, + hwaddr aux2_base, qemu_irq irq, qemu_irq fdc_tc) { DeviceState *dev; @@ -532,7 +532,7 @@ static void slavio_misc_init(target_phys_addr_t base, qemu_register_powerdown_notifier(&slavio_system_powerdown_notifier); } -static void ecc_init(target_phys_addr_t base, qemu_irq irq, uint32_t version) +static void ecc_init(hwaddr base, qemu_irq irq, uint32_t version) { DeviceState *dev; SysBusDevice *s; @@ -548,7 +548,7 @@ static void ecc_init(target_phys_addr_t base, qemu_irq irq, uint32_t version) } } -static void apc_init(target_phys_addr_t power_base, qemu_irq cpu_halt) +static void apc_init(hwaddr power_base, qemu_irq cpu_halt) { DeviceState *dev; SysBusDevice *s; @@ -561,7 +561,7 @@ static void apc_init(target_phys_addr_t power_base, qemu_irq cpu_halt) sysbus_connect_irq(s, 0, cpu_halt); } -static void tcx_init(target_phys_addr_t addr, int vram_size, int width, +static void tcx_init(hwaddr addr, int vram_size, int width, int height, int depth) { DeviceState *dev; @@ -597,7 +597,7 @@ static void tcx_init(target_phys_addr_t addr, int vram_size, int width, /* NCR89C100/MACIO Internal ID register */ static const uint8_t idreg_data[] = { 0xfe, 0x81, 0x01, 0x03 }; -static void idreg_init(target_phys_addr_t addr) +static void idreg_init(hwaddr addr) { DeviceState *dev; SysBusDevice *s; @@ -646,7 +646,7 @@ typedef struct AFXState { } AFXState; /* SS-5 TCX AFX register */ -static void afx_init(target_phys_addr_t addr) +static void afx_init(hwaddr addr) { DeviceState *dev; SysBusDevice *s; @@ -690,11 +690,11 @@ typedef struct PROMState { /* Boot PROM (OpenBIOS) */ static uint64_t translate_prom_address(void *opaque, uint64_t addr) { - target_phys_addr_t *base_addr = (target_phys_addr_t *)opaque; + hwaddr *base_addr = (hwaddr *)opaque; return addr + *base_addr - PROM_VADDR; } -static void prom_init(target_phys_addr_t addr, const char *bios_name) +static void prom_init(hwaddr addr, const char *bios_name) { DeviceState *dev; SysBusDevice *s; @@ -777,7 +777,7 @@ static int ram_init1(SysBusDevice *dev) return 0; } -static void ram_init(target_phys_addr_t addr, ram_addr_t RAM_size, +static void ram_init(hwaddr addr, ram_addr_t RAM_size, uint64_t max_mem) { DeviceState *dev; @@ -1544,7 +1544,7 @@ static const struct sun4d_hwdef sun4d_hwdefs[] = { }, }; -static DeviceState *sbi_init(target_phys_addr_t addr, qemu_irq **parent_irq) +static DeviceState *sbi_init(hwaddr addr, qemu_irq **parent_irq) { DeviceState *dev; SysBusDevice *s; @@ -1605,7 +1605,7 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size, } for (i = 0; i < MAX_IOUNITS; i++) - if (hwdef->iounit_bases[i] != (target_phys_addr_t)-1) + if (hwdef->iounit_bases[i] != (hwaddr)-1) iounits[i] = iommu_init(hwdef->iounit_bases[i], hwdef->iounit_version, sbi_irq[0]); @@ -1744,7 +1744,7 @@ static const struct sun4c_hwdef sun4c_hwdefs[] = { }, }; -static DeviceState *sun4c_intctl_init(target_phys_addr_t addr, +static DeviceState *sun4c_intctl_init(hwaddr addr, qemu_irq *parent_irq) { DeviceState *dev; @@ -1825,7 +1825,7 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size, slavio_irq[1], serial_hds[0], serial_hds[1], ESCC_CLOCK, 1); - if (hwdef->fd_base != (target_phys_addr_t)-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); diff --git a/hw/sun4m.h b/hw/sun4m.h index 504c3af413..a8c3133703 100644 --- a/hw/sun4m.h +++ b/hw/sun4m.h @@ -6,17 +6,17 @@ /* Devices used by sparc32 system. */ /* iommu.c */ -void sparc_iommu_memory_rw(void *opaque, target_phys_addr_t addr, +void sparc_iommu_memory_rw(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write); static inline void sparc_iommu_memory_read(void *opaque, - target_phys_addr_t addr, + hwaddr addr, uint8_t *buf, int len) { sparc_iommu_memory_rw(opaque, addr, buf, len, 0); } static inline void sparc_iommu_memory_write(void *opaque, - target_phys_addr_t addr, + hwaddr addr, uint8_t *buf, int len) { sparc_iommu_memory_rw(opaque, addr, buf, len, 1); diff --git a/hw/sun4m_iommu.c b/hw/sun4m_iommu.c index ebefa91b7a..ce6819e10b 100644 --- a/hw/sun4m_iommu.c +++ b/hw/sun4m_iommu.c @@ -130,16 +130,16 @@ typedef struct IOMMUState { SysBusDevice busdev; MemoryRegion iomem; uint32_t regs[IOMMU_NREGS]; - target_phys_addr_t iostart; + hwaddr iostart; qemu_irq irq; uint32_t version; } IOMMUState; -static uint64_t iommu_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t iommu_mem_read(void *opaque, hwaddr addr, unsigned size) { IOMMUState *s = opaque; - target_phys_addr_t saddr; + hwaddr saddr; uint32_t ret; saddr = addr >> 2; @@ -157,11 +157,11 @@ static uint64_t iommu_mem_read(void *opaque, target_phys_addr_t addr, return ret; } -static void iommu_mem_write(void *opaque, target_phys_addr_t addr, +static void iommu_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { IOMMUState *s = opaque; - target_phys_addr_t saddr; + hwaddr saddr; saddr = addr >> 2; trace_sun4m_iommu_mem_writel(saddr, val); @@ -249,11 +249,11 @@ static const MemoryRegionOps iommu_mem_ops = { }, }; -static uint32_t iommu_page_get_flags(IOMMUState *s, target_phys_addr_t addr) +static uint32_t iommu_page_get_flags(IOMMUState *s, hwaddr addr) { uint32_t ret; - target_phys_addr_t iopte; - target_phys_addr_t pa = addr; + hwaddr iopte; + hwaddr pa = addr; iopte = s->regs[IOMMU_BASE] << 4; addr &= ~s->iostart; @@ -264,17 +264,17 @@ static uint32_t iommu_page_get_flags(IOMMUState *s, target_phys_addr_t addr) return ret; } -static target_phys_addr_t iommu_translate_pa(target_phys_addr_t addr, +static hwaddr iommu_translate_pa(hwaddr addr, uint32_t pte) { - target_phys_addr_t pa; + hwaddr pa; pa = ((pte & IOPTE_PAGE) << 4) + (addr & ~IOMMU_PAGE_MASK); trace_sun4m_iommu_translate_pa(addr, pa, pte); return pa; } -static void iommu_bad_addr(IOMMUState *s, target_phys_addr_t addr, +static void iommu_bad_addr(IOMMUState *s, hwaddr addr, int is_write) { trace_sun4m_iommu_bad_addr(addr); @@ -286,12 +286,12 @@ static void iommu_bad_addr(IOMMUState *s, target_phys_addr_t addr, qemu_irq_raise(s->irq); } -void sparc_iommu_memory_rw(void *opaque, target_phys_addr_t addr, +void sparc_iommu_memory_rw(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write) { int l; uint32_t flags; - target_phys_addr_t page, phys_addr; + hwaddr page, phys_addr; while (len > 0) { page = addr & IOMMU_PAGE_MASK; diff --git a/hw/sun4u.c b/hw/sun4u.c index eeb6496092..162117129c 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -632,12 +632,12 @@ typedef struct PROMState { static uint64_t translate_prom_address(void *opaque, uint64_t addr) { - target_phys_addr_t *base_addr = (target_phys_addr_t *)opaque; + hwaddr *base_addr = (hwaddr *)opaque; return addr + *base_addr - PROM_VADDR; } /* Boot PROM (OpenBIOS) */ -static void prom_init(target_phys_addr_t addr, const char *bios_name) +static void prom_init(hwaddr addr, const char *bios_name) { DeviceState *dev; SysBusDevice *s; @@ -721,7 +721,7 @@ static int ram_init1(SysBusDevice *dev) return 0; } -static void ram_init(target_phys_addr_t addr, ram_addr_t RAM_size) +static void ram_init(hwaddr addr, ram_addr_t RAM_size) { DeviceState *dev; SysBusDevice *s; diff --git a/hw/sysbus.c b/hw/sysbus.c index c1738403dd..4969f06a66 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -48,7 +48,7 @@ void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq) } } -void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr) +void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr) { assert(n >= 0 && n < dev->num_mmio); @@ -56,7 +56,7 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr) /* ??? region already mapped here. */ return; } - if (dev->mmio[n].addr != (target_phys_addr_t)-1) { + if (dev->mmio[n].addr != (hwaddr)-1) { /* Unregister previous mapping. */ memory_region_del_subregion(get_system_memory(), dev->mmio[n].memory); } @@ -122,7 +122,7 @@ static int sysbus_device_init(DeviceState *dev) } DeviceState *sysbus_create_varargs(const char *name, - target_phys_addr_t addr, ...) + hwaddr addr, ...) { DeviceState *dev; SysBusDevice *s; @@ -133,7 +133,7 @@ DeviceState *sysbus_create_varargs(const char *name, dev = qdev_create(NULL, name); s = sysbus_from_qdev(dev); qdev_init_nofail(dev); - if (addr != (target_phys_addr_t)-1) { + if (addr != (hwaddr)-1) { sysbus_mmio_map(s, 0, addr); } va_start(va, addr); @@ -151,7 +151,7 @@ DeviceState *sysbus_create_varargs(const char *name, } DeviceState *sysbus_try_create_varargs(const char *name, - target_phys_addr_t addr, ...) + hwaddr addr, ...) { DeviceState *dev; SysBusDevice *s; @@ -165,7 +165,7 @@ DeviceState *sysbus_try_create_varargs(const char *name, } s = sysbus_from_qdev(dev); qdev_init_nofail(dev); - if (addr != (target_phys_addr_t)-1) { + if (addr != (hwaddr)-1) { sysbus_mmio_map(s, 0, addr); } va_start(va, addr); @@ -185,7 +185,7 @@ DeviceState *sysbus_try_create_varargs(const char *name, static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent) { SysBusDevice *s = sysbus_from_qdev(dev); - target_phys_addr_t size; + hwaddr size; int i; monitor_printf(mon, "%*sirq %d\n", indent, "", s->num_irq); @@ -214,13 +214,13 @@ static char *sysbus_get_fw_dev_path(DeviceState *dev) return g_strdup(path); } -void sysbus_add_memory(SysBusDevice *dev, target_phys_addr_t addr, +void sysbus_add_memory(SysBusDevice *dev, hwaddr addr, MemoryRegion *mem) { memory_region_add_subregion(get_system_memory(), addr, mem); } -void sysbus_add_memory_overlap(SysBusDevice *dev, target_phys_addr_t addr, +void sysbus_add_memory_overlap(SysBusDevice *dev, hwaddr addr, MemoryRegion *mem, unsigned priority) { memory_region_add_subregion_overlap(get_system_memory(), addr, mem, @@ -232,7 +232,7 @@ void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem) memory_region_del_subregion(get_system_memory(), mem); } -void sysbus_add_io(SysBusDevice *dev, target_phys_addr_t addr, +void sysbus_add_io(SysBusDevice *dev, hwaddr addr, MemoryRegion *mem) { memory_region_add_subregion(get_system_io(), addr, mem); diff --git a/hw/sysbus.h b/hw/sysbus.h index acfbcfba52..e58baaae36 100644 --- a/hw/sysbus.h +++ b/hw/sysbus.h @@ -36,7 +36,7 @@ struct SysBusDevice { qemu_irq *irqp[QDEV_MAX_IRQ]; int num_mmio; struct { - target_phys_addr_t addr; + hwaddr addr; MemoryRegion *memory; } mmio[QDEV_MAX_MMIO]; int num_pio; @@ -56,31 +56,31 @@ void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size); void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq); -void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr); -void sysbus_add_memory(SysBusDevice *dev, target_phys_addr_t addr, +void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr); +void sysbus_add_memory(SysBusDevice *dev, hwaddr addr, MemoryRegion *mem); -void sysbus_add_memory_overlap(SysBusDevice *dev, target_phys_addr_t addr, +void sysbus_add_memory_overlap(SysBusDevice *dev, hwaddr addr, MemoryRegion *mem, unsigned priority); void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem); -void sysbus_add_io(SysBusDevice *dev, target_phys_addr_t addr, +void sysbus_add_io(SysBusDevice *dev, hwaddr addr, MemoryRegion *mem); void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem); MemoryRegion *sysbus_address_space(SysBusDevice *dev); /* Legacy helper function for creating devices. */ DeviceState *sysbus_create_varargs(const char *name, - target_phys_addr_t addr, ...); + hwaddr addr, ...); DeviceState *sysbus_try_create_varargs(const char *name, - target_phys_addr_t addr, ...); + hwaddr addr, ...); static inline DeviceState *sysbus_create_simple(const char *name, - target_phys_addr_t addr, + hwaddr addr, qemu_irq irq) { return sysbus_create_varargs(name, addr, irq, NULL); } static inline DeviceState *sysbus_try_create_simple(const char *name, - target_phys_addr_t addr, + hwaddr addr, qemu_irq irq) { return sysbus_try_create_varargs(name, addr, irq, NULL); diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c index 420925ccb3..31d4f26629 100644 --- a/hw/tc6393xb.c +++ b/hw/tc6393xb.c @@ -215,7 +215,7 @@ static void tc6393xb_sub_irq(void *opaque, int line, int level) { case SCR_ ##N(1): return s->scr.N[1]; \ case SCR_ ##N(2): return s->scr.N[2] -static uint32_t tc6393xb_scr_readb(TC6393xbState *s, target_phys_addr_t addr) +static uint32_t tc6393xb_scr_readb(TC6393xbState *s, hwaddr addr) { switch (addr) { case SCR_REVID: @@ -276,7 +276,7 @@ static uint32_t tc6393xb_scr_readb(TC6393xbState *s, target_phys_addr_t addr) case SCR_ ##N(1): s->scr.N[1] = value; return; \ case SCR_ ##N(2): s->scr.N[2] = value; return -static void tc6393xb_scr_writeb(TC6393xbState *s, target_phys_addr_t addr, uint32_t value) +static void tc6393xb_scr_writeb(TC6393xbState *s, hwaddr addr, uint32_t value) { switch (addr) { SCR_REG_B(ISR); @@ -327,7 +327,7 @@ static void tc6393xb_nand_irq(TC6393xbState *s) { (s->nand.imr & 0x80) && (s->nand.imr & s->nand.isr)); } -static uint32_t tc6393xb_nand_cfg_readb(TC6393xbState *s, target_phys_addr_t addr) { +static uint32_t tc6393xb_nand_cfg_readb(TC6393xbState *s, hwaddr addr) { switch (addr) { case NAND_CFG_COMMAND: return s->nand_enable ? 2 : 0; @@ -340,7 +340,7 @@ static uint32_t tc6393xb_nand_cfg_readb(TC6393xbState *s, target_phys_addr_t add fprintf(stderr, "tc6393xb_nand_cfg: unhandled read at %08x\n", (uint32_t) addr); return 0; } -static void tc6393xb_nand_cfg_writeb(TC6393xbState *s, target_phys_addr_t addr, uint32_t value) { +static void tc6393xb_nand_cfg_writeb(TC6393xbState *s, hwaddr addr, uint32_t value) { switch (addr) { case NAND_CFG_COMMAND: s->nand_enable = (value & 0x2); @@ -357,7 +357,7 @@ static void tc6393xb_nand_cfg_writeb(TC6393xbState *s, target_phys_addr_t addr, (uint32_t) addr, value & 0xff); } -static uint32_t tc6393xb_nand_readb(TC6393xbState *s, target_phys_addr_t addr) { +static uint32_t tc6393xb_nand_readb(TC6393xbState *s, hwaddr addr) { switch (addr) { case NAND_DATA + 0: case NAND_DATA + 1: @@ -376,7 +376,7 @@ static uint32_t tc6393xb_nand_readb(TC6393xbState *s, target_phys_addr_t addr) { fprintf(stderr, "tc6393xb_nand: unhandled read at %08x\n", (uint32_t) addr); return 0; } -static void tc6393xb_nand_writeb(TC6393xbState *s, target_phys_addr_t addr, uint32_t value) { +static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value) { // fprintf(stderr, "tc6393xb_nand: write at %08x: %02x\n", // (uint32_t) addr, value & 0xff); switch (addr) { @@ -499,7 +499,7 @@ static void tc6393xb_update_display(void *opaque) } -static uint64_t tc6393xb_readb(void *opaque, target_phys_addr_t addr, +static uint64_t tc6393xb_readb(void *opaque, hwaddr addr, unsigned size) { TC6393xbState *s = opaque; @@ -522,7 +522,7 @@ static uint64_t tc6393xb_readb(void *opaque, target_phys_addr_t addr, return 0; } -static void tc6393xb_writeb(void *opaque, target_phys_addr_t addr, +static void tc6393xb_writeb(void *opaque, hwaddr addr, uint64_t value, unsigned size) { TC6393xbState *s = opaque; diff --git a/hw/tcx.c b/hw/tcx.c index 2db2db1235..7abe865e3f 100644 --- a/hw/tcx.c +++ b/hw/tcx.c @@ -36,7 +36,7 @@ typedef struct TCXState { SysBusDevice busdev; - target_phys_addr_t addr; + hwaddr addr; DisplayState *ds; uint8_t *vram; uint32_t *vram24, *cplane; @@ -432,13 +432,13 @@ static void tcx_reset(DeviceState *d) s->dac_state = 0; } -static uint64_t tcx_dac_readl(void *opaque, target_phys_addr_t addr, +static uint64_t tcx_dac_readl(void *opaque, hwaddr addr, unsigned size) { return 0; } -static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint64_t val, +static void tcx_dac_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size) { TCXState *s = opaque; @@ -484,13 +484,13 @@ static const MemoryRegionOps tcx_dac_ops = { }, }; -static uint64_t dummy_readl(void *opaque, target_phys_addr_t addr, +static uint64_t dummy_readl(void *opaque, hwaddr addr, unsigned size) { return 0; } -static void dummy_writel(void *opaque, target_phys_addr_t addr, +static void dummy_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size) { } diff --git a/hw/tusb6010.c b/hw/tusb6010.c index 5ba8da6d6a..325200bd34 100644 --- a/hw/tusb6010.c +++ b/hw/tusb6010.c @@ -281,7 +281,7 @@ static void tusb_gpio_intr_update(TUSBState *s) extern CPUReadMemoryFunc * const musb_read[]; extern CPUWriteMemoryFunc * const musb_write[]; -static uint32_t tusb_async_readb(void *opaque, target_phys_addr_t addr) +static uint32_t tusb_async_readb(void *opaque, hwaddr addr) { TUSBState *s = (TUSBState *) opaque; @@ -298,7 +298,7 @@ static uint32_t tusb_async_readb(void *opaque, target_phys_addr_t addr) return 0; } -static uint32_t tusb_async_readh(void *opaque, target_phys_addr_t addr) +static uint32_t tusb_async_readh(void *opaque, hwaddr addr) { TUSBState *s = (TUSBState *) opaque; @@ -315,7 +315,7 @@ static uint32_t tusb_async_readh(void *opaque, target_phys_addr_t addr) return 0; } -static uint32_t tusb_async_readw(void *opaque, target_phys_addr_t addr) +static uint32_t tusb_async_readw(void *opaque, hwaddr addr) { TUSBState *s = (TUSBState *) opaque; int offset = addr & 0xfff; @@ -438,7 +438,7 @@ static uint32_t tusb_async_readw(void *opaque, target_phys_addr_t addr) return 0; } -static void tusb_async_writeb(void *opaque, target_phys_addr_t addr, +static void tusb_async_writeb(void *opaque, hwaddr addr, uint32_t value) { TUSBState *s = (TUSBState *) opaque; @@ -459,7 +459,7 @@ static void tusb_async_writeb(void *opaque, target_phys_addr_t addr, } } -static void tusb_async_writeh(void *opaque, target_phys_addr_t addr, +static void tusb_async_writeh(void *opaque, hwaddr addr, uint32_t value) { TUSBState *s = (TUSBState *) opaque; @@ -480,7 +480,7 @@ static void tusb_async_writeh(void *opaque, target_phys_addr_t addr, } } -static void tusb_async_writew(void *opaque, target_phys_addr_t addr, +static void tusb_async_writew(void *opaque, hwaddr addr, uint32_t value) { TUSBState *s = (TUSBState *) opaque; diff --git a/hw/unin_pci.c b/hw/unin_pci.c index d1cc68062b..9981d949d2 100644 --- a/hw/unin_pci.c +++ b/hw/unin_pci.c @@ -111,7 +111,7 @@ static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr) return retval; } -static void unin_data_write(void *opaque, target_phys_addr_t addr, +static void unin_data_write(void *opaque, hwaddr addr, uint64_t val, unsigned len) { UNINState *s = opaque; @@ -123,7 +123,7 @@ static void unin_data_write(void *opaque, target_phys_addr_t addr, val, len); } -static uint64_t unin_data_read(void *opaque, target_phys_addr_t addr, +static uint64_t unin_data_read(void *opaque, hwaddr addr, unsigned len) { UNINState *s = opaque; diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 8bdb806b9b..6c65a734c8 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -503,7 +503,7 @@ static const char *state2str(uint32_t state) return nr2str(ehci_state_names, ARRAY_SIZE(ehci_state_names), state); } -static const char *addr2str(target_phys_addr_t addr) +static const char *addr2str(hwaddr addr) { return nr2str(ehci_mmio_names, ARRAY_SIZE(ehci_mmio_names), addr + OPREGBASE); @@ -663,7 +663,7 @@ static int ehci_get_fetch_addr(EHCIState *s, int async) return async ? s->a_fetch_addr : s->p_fetch_addr; } -static void ehci_trace_qh(EHCIQueue *q, target_phys_addr_t addr, EHCIqh *qh) +static void ehci_trace_qh(EHCIQueue *q, hwaddr addr, EHCIqh *qh) { /* need three here due to argument count limits */ trace_usb_ehci_qh_ptrs(q, addr, qh->next, @@ -681,7 +681,7 @@ static void ehci_trace_qh(EHCIQueue *q, target_phys_addr_t addr, EHCIqh *qh) (bool)(qh->epchar & QH_EPCHAR_I)); } -static void ehci_trace_qtd(EHCIQueue *q, target_phys_addr_t addr, EHCIqtd *qtd) +static void ehci_trace_qtd(EHCIQueue *q, hwaddr addr, EHCIqtd *qtd) { /* need three here due to argument count limits */ trace_usb_ehci_qtd_ptrs(q, addr, qtd->next, qtd->altnext); @@ -698,7 +698,7 @@ static void ehci_trace_qtd(EHCIQueue *q, target_phys_addr_t addr, EHCIqtd *qtd) (bool)(qtd->token & QTD_TOKEN_XACTERR)); } -static void ehci_trace_itd(EHCIState *s, target_phys_addr_t addr, EHCIitd *itd) +static void ehci_trace_itd(EHCIState *s, hwaddr addr, EHCIitd *itd) { trace_usb_ehci_itd(addr, itd->next, get_field(itd->bufptr[1], ITD_BUFPTR_MAXPKT), @@ -707,7 +707,7 @@ static void ehci_trace_itd(EHCIState *s, target_phys_addr_t addr, EHCIitd *itd) get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR)); } -static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr, +static void ehci_trace_sitd(EHCIState *s, hwaddr addr, EHCIsitd *sitd) { trace_usb_ehci_sitd(addr, sitd->next, @@ -1100,14 +1100,14 @@ static void ehci_reset(void *opaque) qemu_bh_cancel(s->async_bh); } -static uint64_t ehci_caps_read(void *ptr, target_phys_addr_t addr, +static uint64_t ehci_caps_read(void *ptr, hwaddr addr, unsigned size) { EHCIState *s = ptr; return s->caps[addr]; } -static uint64_t ehci_opreg_read(void *ptr, target_phys_addr_t addr, +static uint64_t ehci_opreg_read(void *ptr, hwaddr addr, unsigned size) { EHCIState *s = ptr; @@ -1118,7 +1118,7 @@ static uint64_t ehci_opreg_read(void *ptr, target_phys_addr_t addr, return val; } -static uint64_t ehci_port_read(void *ptr, target_phys_addr_t addr, +static uint64_t ehci_port_read(void *ptr, hwaddr addr, unsigned size) { EHCIState *s = ptr; @@ -1157,7 +1157,7 @@ static void handle_port_owner_write(EHCIState *s, int port, uint32_t owner) } } -static void ehci_port_write(void *ptr, target_phys_addr_t addr, +static void ehci_port_write(void *ptr, hwaddr addr, uint64_t val, unsigned size) { EHCIState *s = ptr; @@ -1202,7 +1202,7 @@ static void ehci_port_write(void *ptr, target_phys_addr_t addr, trace_usb_ehci_portsc_change(addr + PORTSC_BEGIN, addr >> 2, *portsc, old); } -static void ehci_opreg_write(void *ptr, target_phys_addr_t addr, +static void ehci_opreg_write(void *ptr, hwaddr addr, uint64_t val, unsigned size) { EHCIState *s = ptr; diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c index 0bb5c7b19e..dc114fed2a 100644 --- a/hw/usb/hcd-musb.c +++ b/hw/usb/hcd-musb.c @@ -1236,7 +1236,7 @@ static void musb_ep_writeh(void *opaque, int ep, int addr, uint16_t value) } /* Generic control */ -static uint32_t musb_readb(void *opaque, target_phys_addr_t addr) +static uint32_t musb_readb(void *opaque, hwaddr addr) { MUSBState *s = (MUSBState *) opaque; int ep, i; @@ -1298,7 +1298,7 @@ static uint32_t musb_readb(void *opaque, target_phys_addr_t addr) }; } -static void musb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value) +static void musb_writeb(void *opaque, hwaddr addr, uint32_t value) { MUSBState *s = (MUSBState *) opaque; int ep; @@ -1385,7 +1385,7 @@ static void musb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value) }; } -static uint32_t musb_readh(void *opaque, target_phys_addr_t addr) +static uint32_t musb_readh(void *opaque, hwaddr addr) { MUSBState *s = (MUSBState *) opaque; int ep, i; @@ -1439,7 +1439,7 @@ static uint32_t musb_readh(void *opaque, target_phys_addr_t addr) }; } -static void musb_writeh(void *opaque, target_phys_addr_t addr, uint32_t value) +static void musb_writeh(void *opaque, hwaddr addr, uint32_t value) { MUSBState *s = (MUSBState *) opaque; int ep; @@ -1495,7 +1495,7 @@ static void musb_writeh(void *opaque, target_phys_addr_t addr, uint32_t value) }; } -static uint32_t musb_readw(void *opaque, target_phys_addr_t addr) +static uint32_t musb_readw(void *opaque, hwaddr addr) { MUSBState *s = (MUSBState *) opaque; int ep; @@ -1513,7 +1513,7 @@ static uint32_t musb_readw(void *opaque, target_phys_addr_t addr) }; } -static void musb_writew(void *opaque, target_phys_addr_t addr, uint32_t value) +static void musb_writew(void *opaque, hwaddr addr, uint32_t value) { MUSBState *s = (MUSBState *) opaque; int ep; diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 59c7055cb5..0cc1e5de85 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -1473,7 +1473,7 @@ static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val) } static uint64_t ohci_mem_read(void *opaque, - target_phys_addr_t addr, + hwaddr addr, unsigned size) { OHCIState *ohci = opaque; @@ -1596,7 +1596,7 @@ static uint64_t ohci_mem_read(void *opaque, } static void ohci_mem_write(void *opaque, - target_phys_addr_t addr, + hwaddr addr, uint64_t val, unsigned size) { diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 3a41b067c4..37b3dbbcb6 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2364,7 +2364,7 @@ static void xhci_reset(DeviceState *dev) xhci_mfwrap_update(xhci); } -static uint64_t xhci_cap_read(void *ptr, target_phys_addr_t reg, unsigned size) +static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size) { XHCIState *xhci = ptr; uint32_t ret; @@ -2431,7 +2431,7 @@ static uint64_t xhci_cap_read(void *ptr, target_phys_addr_t reg, unsigned size) return ret; } -static uint64_t xhci_port_read(void *ptr, target_phys_addr_t reg, unsigned size) +static uint64_t xhci_port_read(void *ptr, hwaddr reg, unsigned size) { XHCIPort *port = ptr; uint32_t ret; @@ -2455,7 +2455,7 @@ static uint64_t xhci_port_read(void *ptr, target_phys_addr_t reg, unsigned size) return ret; } -static void xhci_port_write(void *ptr, target_phys_addr_t reg, +static void xhci_port_write(void *ptr, hwaddr reg, uint64_t val, unsigned size) { XHCIPort *port = ptr; @@ -2493,7 +2493,7 @@ static void xhci_port_write(void *ptr, target_phys_addr_t reg, } } -static uint64_t xhci_oper_read(void *ptr, target_phys_addr_t reg, unsigned size) +static uint64_t xhci_oper_read(void *ptr, hwaddr reg, unsigned size) { XHCIState *xhci = ptr; uint32_t ret; @@ -2535,7 +2535,7 @@ static uint64_t xhci_oper_read(void *ptr, target_phys_addr_t reg, unsigned size) return ret; } -static void xhci_oper_write(void *ptr, target_phys_addr_t reg, +static void xhci_oper_write(void *ptr, hwaddr reg, uint64_t val, unsigned size) { XHCIState *xhci = ptr; @@ -2596,7 +2596,7 @@ static void xhci_oper_write(void *ptr, target_phys_addr_t reg, } } -static uint64_t xhci_runtime_read(void *ptr, target_phys_addr_t reg, +static uint64_t xhci_runtime_read(void *ptr, hwaddr reg, unsigned size) { XHCIState *xhci = ptr; @@ -2644,7 +2644,7 @@ static uint64_t xhci_runtime_read(void *ptr, target_phys_addr_t reg, return ret; } -static void xhci_runtime_write(void *ptr, target_phys_addr_t reg, +static void xhci_runtime_write(void *ptr, hwaddr reg, uint64_t val, unsigned size) { XHCIState *xhci = ptr; @@ -2700,7 +2700,7 @@ static void xhci_runtime_write(void *ptr, target_phys_addr_t reg, } } -static uint64_t xhci_doorbell_read(void *ptr, target_phys_addr_t reg, +static uint64_t xhci_doorbell_read(void *ptr, hwaddr reg, unsigned size) { /* doorbells always read as 0 */ @@ -2708,7 +2708,7 @@ static uint64_t xhci_doorbell_read(void *ptr, target_phys_addr_t reg, return 0; } -static void xhci_doorbell_write(void *ptr, target_phys_addr_t reg, +static void xhci_doorbell_write(void *ptr, hwaddr reg, uint64_t val, unsigned size) { XHCIState *xhci = ptr; diff --git a/hw/versatile_i2c.c b/hw/versatile_i2c.c index 88f530aefc..44e7e40f2f 100644 --- a/hw/versatile_i2c.c +++ b/hw/versatile_i2c.c @@ -32,7 +32,7 @@ typedef struct { int in; } VersatileI2CState; -static uint64_t versatile_i2c_read(void *opaque, target_phys_addr_t offset, +static uint64_t versatile_i2c_read(void *opaque, hwaddr offset, unsigned size) { VersatileI2CState *s = (VersatileI2CState *)opaque; @@ -45,7 +45,7 @@ static uint64_t versatile_i2c_read(void *opaque, target_phys_addr_t offset, } } -static void versatile_i2c_write(void *opaque, target_phys_addr_t offset, +static void versatile_i2c_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { VersatileI2CState *s = (VersatileI2CState *)opaque; diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c index ae53a8b37b..e0c3ee36a5 100644 --- a/hw/versatile_pci.c +++ b/hw/versatile_pci.c @@ -21,18 +21,18 @@ typedef struct { MemoryRegion isa; } PCIVPBState; -static inline uint32_t vpb_pci_config_addr(target_phys_addr_t addr) +static inline uint32_t vpb_pci_config_addr(hwaddr addr) { return addr & 0xffffff; } -static void pci_vpb_config_write(void *opaque, target_phys_addr_t addr, +static void pci_vpb_config_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { pci_data_write(opaque, vpb_pci_config_addr(addr), val, size); } -static uint64_t pci_vpb_config_read(void *opaque, target_phys_addr_t addr, +static uint64_t pci_vpb_config_read(void *opaque, hwaddr addr, unsigned size) { uint32_t val; diff --git a/hw/versatilepb.c b/hw/versatilepb.c index 756ec29da5..f55bd0ca1d 100644 --- a/hw/versatilepb.c +++ b/hw/versatilepb.c @@ -81,7 +81,7 @@ static void vpb_sic_set_irq(void *opaque, int irq, int level) vpb_sic_update(s); } -static uint64_t vpb_sic_read(void *opaque, target_phys_addr_t offset, +static uint64_t vpb_sic_read(void *opaque, hwaddr offset, unsigned size) { vpb_sic_state *s = (vpb_sic_state *)opaque; @@ -103,7 +103,7 @@ static uint64_t vpb_sic_read(void *opaque, target_phys_addr_t offset, } } -static void vpb_sic_write(void *opaque, target_phys_addr_t offset, +static void vpb_sic_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { vpb_sic_state *s = (vpb_sic_state *)opaque; diff --git a/hw/vexpress.c b/hw/vexpress.c index 36503d69fa..3f7cb66a6b 100644 --- a/hw/vexpress.c +++ b/hw/vexpress.c @@ -74,7 +74,7 @@ enum { VE_DAPROM, }; -static target_phys_addr_t motherboard_legacy_map[] = { +static hwaddr motherboard_legacy_map[] = { /* CS7: 0x10000000 .. 0x10020000 */ [VE_SYSREGS] = 0x10000000, [VE_SP810] = 0x10001000, @@ -106,7 +106,7 @@ static target_phys_addr_t motherboard_legacy_map[] = { [VE_USB] = 0x4f000000, }; -static target_phys_addr_t motherboard_aseries_map[] = { +static hwaddr motherboard_aseries_map[] = { /* CS0: 0x08000000 .. 0x0c000000 */ [VE_NORFLASH0] = 0x08000000, /* CS4: 0x0c000000 .. 0x10000000 */ @@ -150,9 +150,9 @@ typedef void DBoardInitFn(const VEDBoardInfo *daughterboard, qemu_irq *pic, uint32_t *proc_id); struct VEDBoardInfo { - const target_phys_addr_t *motherboard_map; - target_phys_addr_t loader_start; - const target_phys_addr_t gic_cpu_if_addr; + const hwaddr *motherboard_map; + hwaddr loader_start; + const hwaddr gic_cpu_if_addr; DBoardInitFn *init; }; @@ -364,7 +364,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, MemoryRegion *sysmem = get_system_memory(); MemoryRegion *vram = g_new(MemoryRegion, 1); MemoryRegion *sram = g_new(MemoryRegion, 1); - const target_phys_addr_t *map = daughterboard->motherboard_map; + const hwaddr *map = daughterboard->motherboard_map; daughterboard->init(daughterboard, ram_size, cpu_model, pic, &proc_id); diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index e49de0d41b..0473ae866c 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -678,7 +678,7 @@ static void vfio_disable_msi(VFIODevice *vdev) /* * IO Port/MMIO - Beware of the endians, VFIO is always little endian */ -static void vfio_bar_write(void *opaque, target_phys_addr_t addr, +static void vfio_bar_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { VFIOBAR *bar = opaque; @@ -705,11 +705,11 @@ static void vfio_bar_write(void *opaque, target_phys_addr_t addr, } if (pwrite(bar->fd, &buf, size, bar->fd_offset + addr) != size) { - error_report("%s(,0x%"TARGET_PRIxPHYS", 0x%"PRIx64", %d) failed: %m\n", + error_report("%s(,0x%"HWADDR_PRIx", 0x%"PRIx64", %d) failed: %m\n", __func__, addr, data, size); } - DPRINTF("%s(BAR%d+0x%"TARGET_PRIxPHYS", 0x%"PRIx64", %d)\n", + DPRINTF("%s(BAR%d+0x%"HWADDR_PRIx", 0x%"PRIx64", %d)\n", __func__, bar->nr, addr, data, size); /* @@ -724,7 +724,7 @@ static void vfio_bar_write(void *opaque, target_phys_addr_t addr, } static uint64_t vfio_bar_read(void *opaque, - target_phys_addr_t addr, unsigned size) + hwaddr addr, unsigned size) { VFIOBAR *bar = opaque; union { @@ -736,7 +736,7 @@ static uint64_t vfio_bar_read(void *opaque, uint64_t data = 0; if (pread(bar->fd, &buf, size, bar->fd_offset + addr) != size) { - error_report("%s(,0x%"TARGET_PRIxPHYS", %d) failed: %m\n", + error_report("%s(,0x%"HWADDR_PRIx", %d) failed: %m\n", __func__, addr, size); return (uint64_t)-1; } @@ -756,7 +756,7 @@ static uint64_t vfio_bar_read(void *opaque, break; } - DPRINTF("%s(BAR%d+0x%"TARGET_PRIxPHYS", %d) = 0x%"PRIx64"\n", + DPRINTF("%s(BAR%d+0x%"HWADDR_PRIx", %d) = 0x%"PRIx64"\n", __func__, bar->nr, addr, size, data); /* Same as write above */ @@ -882,7 +882,7 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr, * DMA - Mapping and unmapping for the "type1" IOMMU interface used on x86 */ static int vfio_dma_unmap(VFIOContainer *container, - target_phys_addr_t iova, ram_addr_t size) + hwaddr iova, ram_addr_t size) { struct vfio_iommu_type1_dma_unmap unmap = { .argsz = sizeof(unmap), @@ -899,7 +899,7 @@ static int vfio_dma_unmap(VFIOContainer *container, return 0; } -static int vfio_dma_map(VFIOContainer *container, target_phys_addr_t iova, +static int vfio_dma_map(VFIOContainer *container, hwaddr iova, ram_addr_t size, void *vaddr, bool readonly) { struct vfio_iommu_type1_dma_map map = { @@ -939,12 +939,12 @@ static void vfio_listener_region_add(MemoryListener *listener, { VFIOContainer *container = container_of(listener, VFIOContainer, iommu_data.listener); - target_phys_addr_t iova, end; + hwaddr iova, end; void *vaddr; int ret; if (vfio_listener_skipped_section(section)) { - DPRINTF("vfio: SKIPPING region_add %"TARGET_PRIxPHYS" - %"PRIx64"\n", + DPRINTF("vfio: SKIPPING region_add %"HWADDR_PRIx" - %"PRIx64"\n", section->offset_within_address_space, section->offset_within_address_space + section->size - 1); return; @@ -968,13 +968,13 @@ static void vfio_listener_region_add(MemoryListener *listener, section->offset_within_region + (iova - section->offset_within_address_space); - DPRINTF("vfio: region_add %"TARGET_PRIxPHYS" - %"TARGET_PRIxPHYS" [%p]\n", + DPRINTF("vfio: region_add %"HWADDR_PRIx" - %"HWADDR_PRIx" [%p]\n", iova, end - 1, vaddr); ret = vfio_dma_map(container, iova, end - iova, vaddr, section->readonly); if (ret) { - error_report("vfio_dma_map(%p, 0x%"TARGET_PRIxPHYS", " - "0x%"TARGET_PRIxPHYS", %p) = %d (%m)\n", + error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", " + "0x%"HWADDR_PRIx", %p) = %d (%m)\n", container, iova, end - iova, vaddr, ret); } } @@ -984,11 +984,11 @@ static void vfio_listener_region_del(MemoryListener *listener, { VFIOContainer *container = container_of(listener, VFIOContainer, iommu_data.listener); - target_phys_addr_t iova, end; + hwaddr iova, end; int ret; if (vfio_listener_skipped_section(section)) { - DPRINTF("vfio: SKIPPING region_del %"TARGET_PRIxPHYS" - %"PRIx64"\n", + DPRINTF("vfio: SKIPPING region_del %"HWADDR_PRIx" - %"PRIx64"\n", section->offset_within_address_space, section->offset_within_address_space + section->size - 1); return; @@ -1008,13 +1008,13 @@ static void vfio_listener_region_del(MemoryListener *listener, return; } - DPRINTF("vfio: region_del %"TARGET_PRIxPHYS" - %"TARGET_PRIxPHYS"\n", + DPRINTF("vfio: region_del %"HWADDR_PRIx" - %"HWADDR_PRIx"\n", iova, end - 1); ret = vfio_dma_unmap(container, iova, end - iova); if (ret) { - error_report("vfio_dma_unmap(%p, 0x%"TARGET_PRIxPHYS", " - "0x%"TARGET_PRIxPHYS") = %d (%m)\n", + error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", " + "0x%"HWADDR_PRIx") = %d (%m)\n", container, iova, end - iova, ret); } } diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c index 306e6ba443..8ef4320d05 100644 --- a/hw/vga-isa-mm.c +++ b/hw/vga-isa-mm.c @@ -36,7 +36,7 @@ typedef struct ISAVGAMMState { } ISAVGAMMState; /* Memory mapped interface */ -static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr) +static uint32_t vga_mm_readb (void *opaque, hwaddr addr) { ISAVGAMMState *s = opaque; @@ -44,14 +44,14 @@ static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr) } static void vga_mm_writeb (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { ISAVGAMMState *s = opaque; vga_ioport_write(&s->vga, addr >> s->it_shift, value & 0xff); } -static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr) +static uint32_t vga_mm_readw (void *opaque, hwaddr addr) { ISAVGAMMState *s = opaque; @@ -59,14 +59,14 @@ static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr) } static void vga_mm_writew (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { ISAVGAMMState *s = opaque; vga_ioport_write(&s->vga, addr >> s->it_shift, value & 0xffff); } -static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr) +static uint32_t vga_mm_readl (void *opaque, hwaddr addr) { ISAVGAMMState *s = opaque; @@ -74,7 +74,7 @@ static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr) } static void vga_mm_writel (void *opaque, - target_phys_addr_t addr, uint32_t value) + hwaddr addr, uint32_t value) { ISAVGAMMState *s = opaque; @@ -97,8 +97,8 @@ static const MemoryRegionOps vga_mm_ctrl_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void vga_mm_init(ISAVGAMMState *s, target_phys_addr_t vram_base, - target_phys_addr_t ctrl_base, int it_shift, +static void vga_mm_init(ISAVGAMMState *s, hwaddr vram_base, + hwaddr ctrl_base, int it_shift, MemoryRegion *address_space) { MemoryRegion *s_ioport_ctrl, *vga_io_memory; @@ -123,8 +123,8 @@ static void vga_mm_init(ISAVGAMMState *s, target_phys_addr_t vram_base, memory_region_set_coalescing(vga_io_memory); } -int isa_vga_mm_init(target_phys_addr_t vram_base, - target_phys_addr_t ctrl_base, int it_shift, +int isa_vga_mm_init(hwaddr vram_base, + hwaddr ctrl_base, int it_shift, MemoryRegion *address_space) { ISAVGAMMState *s; diff --git a/hw/vga-pci.c b/hw/vga-pci.c index 5c4daee397..ec29cac7f4 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -62,7 +62,7 @@ static const VMStateDescription vmstate_vga_pci = { } }; -static uint64_t pci_vga_ioport_read(void *ptr, target_phys_addr_t addr, +static uint64_t pci_vga_ioport_read(void *ptr, hwaddr addr, unsigned size) { PCIVGAState *d = ptr; @@ -80,7 +80,7 @@ static uint64_t pci_vga_ioport_read(void *ptr, target_phys_addr_t addr, return ret; } -static void pci_vga_ioport_write(void *ptr, target_phys_addr_t addr, +static void pci_vga_ioport_write(void *ptr, hwaddr addr, uint64_t val, unsigned size) { PCIVGAState *d = ptr; @@ -110,7 +110,7 @@ static const MemoryRegionOps pci_vga_ioport_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static uint64_t pci_vga_bochs_read(void *ptr, target_phys_addr_t addr, +static uint64_t pci_vga_bochs_read(void *ptr, hwaddr addr, unsigned size) { PCIVGAState *d = ptr; @@ -120,7 +120,7 @@ static uint64_t pci_vga_bochs_read(void *ptr, target_phys_addr_t addr, return vbe_ioport_read_data(&d->vga, 0); } -static void pci_vga_bochs_write(void *ptr, target_phys_addr_t addr, +static void pci_vga_bochs_write(void *ptr, hwaddr addr, uint64_t val, unsigned size) { PCIVGAState *d = ptr; diff --git a/hw/vga.c b/hw/vga.c index a07a6fb1ca..e4220df25e 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -172,7 +172,7 @@ static void vga_screen_dump(void *opaque, const char *filename, bool cswitch, static void vga_update_memory_access(VGACommonState *s) { MemoryRegion *region, *old_region = s->chain4_alias; - target_phys_addr_t base, offset, size; + hwaddr base, offset, size; s->chain4_alias = NULL; @@ -785,7 +785,7 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) } /* called for accesses between 0xa0000 and 0xc0000 */ -uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr) +uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr) { int memory_map_mode, plane; uint32_t ret; @@ -842,7 +842,7 @@ uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr) } /* called for accesses between 0xa0000 and 0xc0000 */ -void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val) +void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) { int memory_map_mode, plane, write_mode, b, func_select, mask; uint32_t write_mask, bit_mask, set_mask; @@ -2152,7 +2152,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) dpy_update(s->ds, 0, 0, s->last_width, height); } -static uint64_t vga_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t vga_mem_read(void *opaque, hwaddr addr, unsigned size) { VGACommonState *s = opaque; @@ -2160,7 +2160,7 @@ static uint64_t vga_mem_read(void *opaque, target_phys_addr_t addr, return vga_mem_readb(s, addr); } -static void vga_mem_write(void *opaque, target_phys_addr_t addr, +static void vga_mem_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { VGACommonState *s = opaque; diff --git a/hw/vga_int.h b/hw/vga_int.h index 144e7d3c35..22f1706adf 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -190,8 +190,8 @@ void vga_dirty_log_stop(VGACommonState *s); extern const VMStateDescription vmstate_vga_common; uint32_t vga_ioport_read(void *opaque, uint32_t addr); void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val); -uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr); -void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val); +uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr); +void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val); void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2); void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp); diff --git a/hw/vhost.c b/hw/vhost.c index 0b4ac3f1df..16322a14f4 100644 --- a/hw/vhost.c +++ b/hw/vhost.c @@ -65,8 +65,8 @@ static void vhost_dev_sync_region(struct vhost_dev *dev, static int vhost_sync_dirty_bitmap(struct vhost_dev *dev, MemoryRegionSection *section, - target_phys_addr_t start_addr, - target_phys_addr_t end_addr) + hwaddr start_addr, + hwaddr end_addr) { int i; @@ -93,8 +93,8 @@ static void vhost_log_sync(MemoryListener *listener, { struct vhost_dev *dev = container_of(listener, struct vhost_dev, memory_listener); - target_phys_addr_t start_addr = section->offset_within_address_space; - target_phys_addr_t end_addr = start_addr + section->size; + hwaddr start_addr = section->offset_within_address_space; + hwaddr end_addr = start_addr + section->size; vhost_sync_dirty_bitmap(dev, section, start_addr, end_addr); } @@ -296,7 +296,7 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev, int i; for (i = 0; i < dev->nvqs; ++i) { struct vhost_virtqueue *vq = dev->vqs + i; - target_phys_addr_t l; + hwaddr l; void *p; if (!ranges_overlap(start_addr, size, vq->ring_phys, vq->ring_size)) { @@ -362,7 +362,7 @@ static void vhost_set_memory(MemoryListener *listener, { struct vhost_dev *dev = container_of(listener, struct vhost_dev, memory_listener); - target_phys_addr_t start_addr = section->offset_within_address_space; + hwaddr start_addr = section->offset_within_address_space; ram_addr_t size = section->size; bool log_dirty = memory_region_is_logging(section->mr); int s = offsetof(struct vhost_memory, regions) + @@ -617,7 +617,7 @@ static int vhost_virtqueue_init(struct vhost_dev *dev, struct vhost_virtqueue *vq, unsigned idx) { - target_phys_addr_t s, l, a; + hwaddr s, l, a; int r; struct vhost_vring_file file = { .index = idx, @@ -948,7 +948,7 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) } for (i = 0; i < hdev->n_mem_sections; ++i) { vhost_sync_dirty_bitmap(hdev, &hdev->mem_sections[i], - 0, (target_phys_addr_t)~0x0ull); + 0, (hwaddr)~0x0ull); } r = vdev->binding->set_guest_notifiers(vdev->binding_opaque, false); if (r < 0) { diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c index c59e1cb4e4..6ab8fee0c1 100644 --- a/hw/virtex_ml507.c +++ b/hw/virtex_ml507.c @@ -58,7 +58,7 @@ static struct boot_info /* Create reset TLB entries for BookE, spanning the 32bit addr space. */ static void mmubooke_create_initial_mapping(CPUPPCState *env, target_ulong va, - target_phys_addr_t pa) + hwaddr pa) { ppcemb_tlb_t *tlb = &env->tlb.tlbe[0]; @@ -134,10 +134,10 @@ static void main_cpu_reset(void *opaque) } #define BINARY_DEVICE_TREE_FILE "virtex-ml507.dtb" -static int xilinx_load_device_tree(target_phys_addr_t addr, +static int xilinx_load_device_tree(hwaddr addr, uint32_t ramsize, - target_phys_addr_t initrd_base, - target_phys_addr_t initrd_size, + hwaddr initrd_base, + hwaddr initrd_size, const char *kernel_cmdline) { char *path; @@ -193,7 +193,7 @@ static void virtex_init(QEMUMachineInitArgs *args) DeviceState *dev; PowerPCCPU *cpu; CPUPPCState *env; - target_phys_addr_t ram_base = 0; + hwaddr ram_base = 0; DriveInfo *dinfo; MemoryRegion *phys_ram = g_new(MemoryRegion, 1); qemu_irq irq[32], *cpu_irq; @@ -233,7 +233,7 @@ static void virtex_init(QEMUMachineInitArgs *args) if (kernel_filename) { uint64_t entry, low, high; - target_phys_addr_t boot_offset; + hwaddr boot_offset; /* Boots a kernel elf binary. */ kernel_size = load_elf(kernel_filename, NULL, NULL, diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 400f3c26b6..c7f20c36a2 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -255,7 +255,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) { VirtIOPCIProxy *proxy = opaque; VirtIODevice *vdev = proxy->vdev; - target_phys_addr_t pa; + hwaddr pa; switch (addr) { case VIRTIO_PCI_GUEST_FEATURES: @@ -266,7 +266,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) virtio_set_features(vdev, val); break; case VIRTIO_PCI_QUEUE_PFN: - pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT; + pa = (hwaddr)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT; if (pa == 0) { virtio_pci_stop_ioeventfd(proxy); virtio_reset(proxy->vdev); diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c index c1b47a8f4d..b54c7895fc 100644 --- a/hw/virtio-scsi.c +++ b/hw/virtio-scsi.c @@ -202,7 +202,7 @@ static void virtio_scsi_bad_req(void) } static void qemu_sgl_init_external(QEMUSGList *qsgl, struct iovec *sg, - target_phys_addr_t *addr, int num) + hwaddr *addr, int num) { memset(qsgl, 0, sizeof(*qsgl)); while (num--) { diff --git a/hw/virtio.c b/hw/virtio.c index 6821092df2..ec8b7d8463 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -53,15 +53,15 @@ typedef struct VRingUsed typedef struct VRing { unsigned int num; - target_phys_addr_t desc; - target_phys_addr_t avail; - target_phys_addr_t used; + hwaddr desc; + hwaddr avail; + hwaddr used; } VRing; struct VirtQueue { VRing vring; - target_phys_addr_t pa; + hwaddr pa; uint16_t last_avail_idx; /* Last used index value we have signalled on */ uint16_t signalled_used; @@ -84,7 +84,7 @@ struct VirtQueue /* virt queue functions */ static void virtqueue_init(VirtQueue *vq) { - target_phys_addr_t pa = vq->pa; + hwaddr pa = vq->pa; vq->vring.desc = pa; vq->vring.avail = pa + vq->vring.num * sizeof(VRingDesc); @@ -93,51 +93,51 @@ static void virtqueue_init(VirtQueue *vq) VIRTIO_PCI_VRING_ALIGN); } -static inline uint64_t vring_desc_addr(target_phys_addr_t desc_pa, int i) +static inline uint64_t vring_desc_addr(hwaddr desc_pa, int i) { - target_phys_addr_t pa; + hwaddr pa; pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, addr); return ldq_phys(pa); } -static inline uint32_t vring_desc_len(target_phys_addr_t desc_pa, int i) +static inline uint32_t vring_desc_len(hwaddr desc_pa, int i) { - target_phys_addr_t pa; + hwaddr pa; pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, len); return ldl_phys(pa); } -static inline uint16_t vring_desc_flags(target_phys_addr_t desc_pa, int i) +static inline uint16_t vring_desc_flags(hwaddr desc_pa, int i) { - target_phys_addr_t pa; + hwaddr pa; pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, flags); return lduw_phys(pa); } -static inline uint16_t vring_desc_next(target_phys_addr_t desc_pa, int i) +static inline uint16_t vring_desc_next(hwaddr desc_pa, int i) { - target_phys_addr_t pa; + hwaddr pa; pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, next); return lduw_phys(pa); } static inline uint16_t vring_avail_flags(VirtQueue *vq) { - target_phys_addr_t pa; + hwaddr pa; pa = vq->vring.avail + offsetof(VRingAvail, flags); return lduw_phys(pa); } static inline uint16_t vring_avail_idx(VirtQueue *vq) { - target_phys_addr_t pa; + hwaddr pa; pa = vq->vring.avail + offsetof(VRingAvail, idx); return lduw_phys(pa); } static inline uint16_t vring_avail_ring(VirtQueue *vq, int i) { - target_phys_addr_t pa; + hwaddr pa; pa = vq->vring.avail + offsetof(VRingAvail, ring[i]); return lduw_phys(pa); } @@ -149,49 +149,49 @@ static inline uint16_t vring_used_event(VirtQueue *vq) static inline void vring_used_ring_id(VirtQueue *vq, int i, uint32_t val) { - target_phys_addr_t pa; + hwaddr pa; pa = vq->vring.used + offsetof(VRingUsed, ring[i].id); stl_phys(pa, val); } static inline void vring_used_ring_len(VirtQueue *vq, int i, uint32_t val) { - target_phys_addr_t pa; + hwaddr pa; pa = vq->vring.used + offsetof(VRingUsed, ring[i].len); stl_phys(pa, val); } static uint16_t vring_used_idx(VirtQueue *vq) { - target_phys_addr_t pa; + hwaddr pa; pa = vq->vring.used + offsetof(VRingUsed, idx); return lduw_phys(pa); } static inline void vring_used_idx_set(VirtQueue *vq, uint16_t val) { - target_phys_addr_t pa; + hwaddr pa; pa = vq->vring.used + offsetof(VRingUsed, idx); stw_phys(pa, val); } static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask) { - target_phys_addr_t pa; + hwaddr pa; pa = vq->vring.used + offsetof(VRingUsed, flags); stw_phys(pa, lduw_phys(pa) | mask); } static inline void vring_used_flags_unset_bit(VirtQueue *vq, int mask) { - target_phys_addr_t pa; + hwaddr pa; pa = vq->vring.used + offsetof(VRingUsed, flags); stw_phys(pa, lduw_phys(pa) & ~mask); } static inline void vring_avail_event(VirtQueue *vq, uint16_t val) { - target_phys_addr_t pa; + hwaddr pa; if (!vq->notification) { return; } @@ -313,7 +313,7 @@ static unsigned int virtqueue_get_head(VirtQueue *vq, unsigned int idx) return head; } -static unsigned virtqueue_next_desc(target_phys_addr_t desc_pa, +static unsigned virtqueue_next_desc(hwaddr desc_pa, unsigned int i, unsigned int max) { unsigned int next; @@ -346,7 +346,7 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes, total_bufs = in_total = out_total = 0; while (virtqueue_num_heads(vq, idx)) { unsigned int max, num_bufs, indirect = 0; - target_phys_addr_t desc_pa; + hwaddr desc_pa; int i; max = vq->vring.num; @@ -413,11 +413,11 @@ int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes, return 0; } -void virtqueue_map_sg(struct iovec *sg, target_phys_addr_t *addr, +void virtqueue_map_sg(struct iovec *sg, hwaddr *addr, size_t num_sg, int is_write) { unsigned int i; - target_phys_addr_t len; + hwaddr len; for (i = 0; i < num_sg; i++) { len = sg[i].iov_len; @@ -432,7 +432,7 @@ void virtqueue_map_sg(struct iovec *sg, target_phys_addr_t *addr, int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) { unsigned int i, head, max; - target_phys_addr_t desc_pa = vq->vring.desc; + hwaddr desc_pa = vq->vring.desc; if (!virtqueue_num_heads(vq, vq->last_avail_idx)) return 0; @@ -631,13 +631,13 @@ void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data) vdev->set_config(vdev, vdev->config); } -void virtio_queue_set_addr(VirtIODevice *vdev, int n, target_phys_addr_t addr) +void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr) { vdev->vq[n].pa = addr; virtqueue_init(&vdev->vq[n]); } -target_phys_addr_t virtio_queue_get_addr(VirtIODevice *vdev, int n) +hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n) { return vdev->vq[n].pa; } @@ -940,44 +940,44 @@ void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding, vdev->binding_opaque = opaque; } -target_phys_addr_t virtio_queue_get_desc_addr(VirtIODevice *vdev, int n) +hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n) { return vdev->vq[n].vring.desc; } -target_phys_addr_t virtio_queue_get_avail_addr(VirtIODevice *vdev, int n) +hwaddr virtio_queue_get_avail_addr(VirtIODevice *vdev, int n) { return vdev->vq[n].vring.avail; } -target_phys_addr_t virtio_queue_get_used_addr(VirtIODevice *vdev, int n) +hwaddr virtio_queue_get_used_addr(VirtIODevice *vdev, int n) { return vdev->vq[n].vring.used; } -target_phys_addr_t virtio_queue_get_ring_addr(VirtIODevice *vdev, int n) +hwaddr virtio_queue_get_ring_addr(VirtIODevice *vdev, int n) { return vdev->vq[n].vring.desc; } -target_phys_addr_t virtio_queue_get_desc_size(VirtIODevice *vdev, int n) +hwaddr virtio_queue_get_desc_size(VirtIODevice *vdev, int n) { return sizeof(VRingDesc) * vdev->vq[n].vring.num; } -target_phys_addr_t virtio_queue_get_avail_size(VirtIODevice *vdev, int n) +hwaddr virtio_queue_get_avail_size(VirtIODevice *vdev, int n) { return offsetof(VRingAvail, ring) + sizeof(uint64_t) * vdev->vq[n].vring.num; } -target_phys_addr_t virtio_queue_get_used_size(VirtIODevice *vdev, int n) +hwaddr virtio_queue_get_used_size(VirtIODevice *vdev, int n) { return offsetof(VRingUsed, ring) + sizeof(VRingUsedElem) * vdev->vq[n].vring.num; } -target_phys_addr_t virtio_queue_get_ring_size(VirtIODevice *vdev, int n) +hwaddr virtio_queue_get_ring_size(VirtIODevice *vdev, int n) { return vdev->vq[n].vring.used - vdev->vq[n].vring.desc + virtio_queue_get_used_size(vdev, n); diff --git a/hw/virtio.h b/hw/virtio.h index 80de3757e3..ac482be24c 100644 --- a/hw/virtio.h +++ b/hw/virtio.h @@ -69,7 +69,7 @@ struct VirtQueue; -static inline target_phys_addr_t vring_align(target_phys_addr_t addr, +static inline hwaddr vring_align(hwaddr addr, unsigned long align) { return (addr + align - 1) & ~(align - 1); @@ -84,8 +84,8 @@ typedef struct VirtQueueElement unsigned int index; unsigned int out_num; unsigned int in_num; - target_phys_addr_t in_addr[VIRTQUEUE_MAX_SIZE]; - target_phys_addr_t out_addr[VIRTQUEUE_MAX_SIZE]; + hwaddr in_addr[VIRTQUEUE_MAX_SIZE]; + hwaddr out_addr[VIRTQUEUE_MAX_SIZE]; struct iovec in_sg[VIRTQUEUE_MAX_SIZE]; struct iovec out_sg[VIRTQUEUE_MAX_SIZE]; } VirtQueueElement; @@ -144,7 +144,7 @@ void virtqueue_flush(VirtQueue *vq, unsigned int count); void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, unsigned int len, unsigned int idx); -void virtqueue_map_sg(struct iovec *sg, target_phys_addr_t *addr, +void virtqueue_map_sg(struct iovec *sg, hwaddr *addr, size_t num_sg, int is_write); int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem); int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes, @@ -178,8 +178,8 @@ uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr); void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data); void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data); void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data); -void virtio_queue_set_addr(VirtIODevice *vdev, int n, target_phys_addr_t addr); -target_phys_addr_t virtio_queue_get_addr(VirtIODevice *vdev, int n); +void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr); +hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n); int virtio_queue_get_num(VirtIODevice *vdev, int n); void virtio_queue_notify(VirtIODevice *vdev, int n); uint16_t virtio_queue_vector(VirtIODevice *vdev, int n); @@ -220,14 +220,14 @@ void virtio_scsi_exit(VirtIODevice *vdev); DEFINE_PROP_BIT("event_idx", _state, _field, \ VIRTIO_RING_F_EVENT_IDX, true) -target_phys_addr_t virtio_queue_get_desc_addr(VirtIODevice *vdev, int n); -target_phys_addr_t virtio_queue_get_avail_addr(VirtIODevice *vdev, int n); -target_phys_addr_t virtio_queue_get_used_addr(VirtIODevice *vdev, int n); -target_phys_addr_t virtio_queue_get_ring_addr(VirtIODevice *vdev, int n); -target_phys_addr_t virtio_queue_get_desc_size(VirtIODevice *vdev, int n); -target_phys_addr_t virtio_queue_get_avail_size(VirtIODevice *vdev, int n); -target_phys_addr_t virtio_queue_get_used_size(VirtIODevice *vdev, int n); -target_phys_addr_t virtio_queue_get_ring_size(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_avail_addr(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_used_addr(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_ring_addr(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_desc_size(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_avail_size(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_used_size(VirtIODevice *vdev, int n); +hwaddr virtio_queue_get_ring_size(VirtIODevice *vdev, int n); uint16_t virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n); void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx); VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n); diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 6f7074e55f..badaf7cef4 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -1130,7 +1130,7 @@ static void vmsvga_init(struct vmsvga_state_s *s, } } -static uint64_t vmsvga_io_read(void *opaque, target_phys_addr_t addr, +static uint64_t vmsvga_io_read(void *opaque, hwaddr addr, unsigned size) { struct vmsvga_state_s *s = opaque; @@ -1143,7 +1143,7 @@ static uint64_t vmsvga_io_read(void *opaque, target_phys_addr_t addr, } } -static void vmsvga_io_write(void *opaque, target_phys_addr_t addr, +static void vmsvga_io_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { struct vmsvga_state_s *s = opaque; diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c index 4a83474906..da15c73918 100644 --- a/hw/wdt_i6300esb.c +++ b/hw/wdt_i6300esb.c @@ -257,14 +257,14 @@ static uint32_t i6300esb_config_read(PCIDevice *dev, uint32_t addr, int len) } } -static uint32_t i6300esb_mem_readb(void *vp, target_phys_addr_t addr) +static uint32_t i6300esb_mem_readb(void *vp, hwaddr addr) { i6300esb_debug ("addr = %x\n", (int) addr); return 0; } -static uint32_t i6300esb_mem_readw(void *vp, target_phys_addr_t addr) +static uint32_t i6300esb_mem_readw(void *vp, hwaddr addr) { uint32_t data = 0; I6300State *d = vp; @@ -282,14 +282,14 @@ static uint32_t i6300esb_mem_readw(void *vp, target_phys_addr_t addr) return data; } -static uint32_t i6300esb_mem_readl(void *vp, target_phys_addr_t addr) +static uint32_t i6300esb_mem_readl(void *vp, hwaddr addr) { i6300esb_debug("addr = %x\n", (int) addr); return 0; } -static void i6300esb_mem_writeb(void *vp, target_phys_addr_t addr, uint32_t val) +static void i6300esb_mem_writeb(void *vp, hwaddr addr, uint32_t val) { I6300State *d = vp; @@ -301,7 +301,7 @@ static void i6300esb_mem_writeb(void *vp, target_phys_addr_t addr, uint32_t val) d->unlock_state = 2; } -static void i6300esb_mem_writew(void *vp, target_phys_addr_t addr, uint32_t val) +static void i6300esb_mem_writew(void *vp, hwaddr addr, uint32_t val) { I6300State *d = vp; @@ -334,7 +334,7 @@ static void i6300esb_mem_writew(void *vp, target_phys_addr_t addr, uint32_t val) } } -static void i6300esb_mem_writel(void *vp, target_phys_addr_t addr, uint32_t val) +static void i6300esb_mem_writel(void *vp, hwaddr addr, uint32_t val) { I6300State *d = vp; diff --git a/hw/xen_apic.c b/hw/xen_apic.c index a9e101f315..fc4536651a 100644 --- a/hw/xen_apic.c +++ b/hw/xen_apic.c @@ -13,13 +13,13 @@ #include "hw/msi.h" #include "xen.h" -static uint64_t xen_apic_mem_read(void *opaque, target_phys_addr_t addr, +static uint64_t xen_apic_mem_read(void *opaque, hwaddr addr, unsigned size) { return ~(uint64_t)0; } -static void xen_apic_mem_write(void *opaque, target_phys_addr_t addr, +static void xen_apic_mem_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { if (size != sizeof(uint32_t)) { diff --git a/hw/xen_platform.c b/hw/xen_platform.c index 956dbfeae4..890eb72f20 100644 --- a/hw/xen_platform.c +++ b/hw/xen_platform.c @@ -292,7 +292,7 @@ static void platform_ioport_bar_setup(PCIXenPlatformState *d) memory_region_init_io(&d->bar, &xen_pci_io_ops, d, "xen-pci", 0x100); } -static uint64_t platform_mmio_read(void *opaque, target_phys_addr_t addr, +static uint64_t platform_mmio_read(void *opaque, hwaddr addr, unsigned size) { DPRINTF("Warning: attempted read from physical address " @@ -301,7 +301,7 @@ static uint64_t platform_mmio_read(void *opaque, target_phys_addr_t addr, return 0; } -static void platform_mmio_write(void *opaque, target_phys_addr_t addr, +static void platform_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { DPRINTF("Warning: attempted write of 0x%"PRIx64" to physical " diff --git a/hw/xen_pt.c b/hw/xen_pt.c index d3d7c8bc3c..7a3846e649 100644 --- a/hw/xen_pt.c +++ b/hw/xen_pt.c @@ -363,7 +363,7 @@ out: /* register regions */ -static uint64_t xen_pt_bar_read(void *o, target_phys_addr_t addr, +static uint64_t xen_pt_bar_read(void *o, hwaddr addr, unsigned size) { PCIDevice *d = o; @@ -373,7 +373,7 @@ static uint64_t xen_pt_bar_read(void *o, target_phys_addr_t addr, addr); return 0; } -static void xen_pt_bar_write(void *o, target_phys_addr_t addr, uint64_t val, +static void xen_pt_bar_write(void *o, hwaddr addr, uint64_t val, unsigned size) { PCIDevice *d = o; diff --git a/hw/xen_pt_msi.c b/hw/xen_pt_msi.c index 2299cc7772..680767229b 100644 --- a/hw/xen_pt_msi.c +++ b/hw/xen_pt_msi.c @@ -427,7 +427,7 @@ static void set_entry_value(XenPTMSIXEntry *e, int offset, uint32_t val) } } -static void pci_msix_write(void *opaque, target_phys_addr_t addr, +static void pci_msix_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { XenPCIPassthroughState *s = opaque; @@ -475,7 +475,7 @@ static void pci_msix_write(void *opaque, target_phys_addr_t addr, } } -static uint64_t pci_msix_read(void *opaque, target_phys_addr_t addr, +static uint64_t pci_msix_read(void *opaque, hwaddr addr, unsigned size) { XenPCIPassthroughState *s = opaque; diff --git a/hw/xgmac.c b/hw/xgmac.c index a91ef608f1..ec50c745d0 100644 --- a/hw/xgmac.c +++ b/hw/xgmac.c @@ -252,7 +252,7 @@ static void enet_update_irq(struct XgmacState *s) qemu_set_irq(s->sbd_irq, !!stat); } -static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t enet_read(void *opaque, hwaddr addr, unsigned size) { struct XgmacState *s = opaque; uint64_t r = 0; @@ -271,7 +271,7 @@ static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size) return r; } -static void enet_write(void *opaque, target_phys_addr_t addr, +static void enet_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct XgmacState *s = opaque; diff --git a/hw/xilinx.h b/hw/xilinx.h index 98300477ab..9323fd07c6 100644 --- a/hw/xilinx.h +++ b/hw/xilinx.h @@ -3,7 +3,7 @@ #include "net.h" static inline DeviceState * -xilinx_intc_create(target_phys_addr_t base, qemu_irq irq, int kind_of_intr) +xilinx_intc_create(hwaddr base, qemu_irq irq, int kind_of_intr) { DeviceState *dev; @@ -17,7 +17,7 @@ xilinx_intc_create(target_phys_addr_t base, qemu_irq irq, int kind_of_intr) /* OPB Timer/Counter. */ static inline DeviceState * -xilinx_timer_create(target_phys_addr_t base, qemu_irq irq, int oto, int freq) +xilinx_timer_create(hwaddr base, qemu_irq irq, int oto, int freq) { DeviceState *dev; @@ -32,7 +32,7 @@ xilinx_timer_create(target_phys_addr_t base, qemu_irq irq, int oto, int freq) /* XPS Ethernet Lite MAC. */ static inline DeviceState * -xilinx_ethlite_create(NICInfo *nd, target_phys_addr_t base, qemu_irq irq, +xilinx_ethlite_create(NICInfo *nd, hwaddr base, qemu_irq irq, int txpingpong, int rxpingpong) { DeviceState *dev; @@ -51,7 +51,7 @@ xilinx_ethlite_create(NICInfo *nd, target_phys_addr_t base, qemu_irq irq, static inline DeviceState * xilinx_axiethernet_create(NICInfo *nd, StreamSlave *peer, - target_phys_addr_t base, qemu_irq irq, + hwaddr base, qemu_irq irq, int txmem, int rxmem) { DeviceState *dev; @@ -75,7 +75,7 @@ xilinx_axiethernet_create(NICInfo *nd, StreamSlave *peer, static inline void xilinx_axiethernetdma_init(DeviceState *dev, StreamSlave *peer, - target_phys_addr_t base, qemu_irq irq, + hwaddr base, qemu_irq irq, qemu_irq irq2, int freqhz) { Error *errp = NULL; diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c index 0e28c51738..4575da1765 100644 --- a/hw/xilinx_axidma.c +++ b/hw/xilinx_axidma.c @@ -140,7 +140,7 @@ static void stream_reset(struct Stream *s) } /* Map an offset addr into a channel index. */ -static inline int streamid_from_addr(target_phys_addr_t addr) +static inline int streamid_from_addr(hwaddr addr) { int sid; @@ -159,7 +159,7 @@ static void stream_desc_show(struct SDesc *d) } #endif -static void stream_desc_load(struct Stream *s, target_phys_addr_t addr) +static void stream_desc_load(struct Stream *s, hwaddr addr) { struct SDesc *d = &s->desc; int i; @@ -176,7 +176,7 @@ static void stream_desc_load(struct Stream *s, target_phys_addr_t addr) } } -static void stream_desc_store(struct Stream *s, target_phys_addr_t addr) +static void stream_desc_store(struct Stream *s, hwaddr addr) { struct SDesc *d = &s->desc; int i; @@ -364,7 +364,7 @@ axidma_push(StreamSlave *obj, unsigned char *buf, size_t len, uint32_t *app) stream_update_irq(s); } -static uint64_t axidma_read(void *opaque, target_phys_addr_t addr, +static uint64_t axidma_read(void *opaque, hwaddr addr, unsigned size) { struct XilinxAXIDMA *d = opaque; @@ -399,7 +399,7 @@ static uint64_t axidma_read(void *opaque, target_phys_addr_t addr, } -static void axidma_write(void *opaque, target_phys_addr_t addr, +static void axidma_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct XilinxAXIDMA *d = opaque; diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c index eec155d440..baae02bd66 100644 --- a/hw/xilinx_axienet.c +++ b/hw/xilinx_axienet.c @@ -412,7 +412,7 @@ static void enet_update_irq(struct XilinxAXIEnet *s) qemu_set_irq(s->irq, !!s->regs[R_IP]); } -static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t enet_read(void *opaque, hwaddr addr, unsigned size) { struct XilinxAXIEnet *s = opaque; uint32_t r = 0; @@ -503,7 +503,7 @@ static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size) return r; } -static void enet_write(void *opaque, target_phys_addr_t addr, +static void enet_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { struct XilinxAXIEnet *s = opaque; diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c index 56ca620dd7..13bd45613d 100644 --- a/hw/xilinx_ethlite.c +++ b/hw/xilinx_ethlite.c @@ -72,7 +72,7 @@ static inline void eth_pulse_irq(struct xlx_ethlite *s) } static uint64_t -eth_read(void *opaque, target_phys_addr_t addr, unsigned int size) +eth_read(void *opaque, hwaddr addr, unsigned int size) { struct xlx_ethlite *s = opaque; uint32_t r = 0; @@ -100,7 +100,7 @@ eth_read(void *opaque, target_phys_addr_t addr, unsigned int size) } static void -eth_write(void *opaque, target_phys_addr_t addr, +eth_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { struct xlx_ethlite *s = opaque; diff --git a/hw/xilinx_intc.c b/hw/xilinx_intc.c index 386fd30743..7765079802 100644 --- a/hw/xilinx_intc.c +++ b/hw/xilinx_intc.c @@ -74,7 +74,7 @@ static void update_irq(struct xlx_pic *p) } static uint64_t -pic_read(void *opaque, target_phys_addr_t addr, unsigned int size) +pic_read(void *opaque, hwaddr addr, unsigned int size) { struct xlx_pic *p = opaque; uint32_t r = 0; @@ -93,7 +93,7 @@ pic_read(void *opaque, target_phys_addr_t addr, unsigned int size) } static void -pic_write(void *opaque, target_phys_addr_t addr, +pic_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { struct xlx_pic *p = opaque; diff --git a/hw/xilinx_spi.c b/hw/xilinx_spi.c index 5cdf967c20..039027442c 100644 --- a/hw/xilinx_spi.c +++ b/hw/xilinx_spi.c @@ -193,7 +193,7 @@ static void spi_flush_txfifo(XilinxSPI *s) } static uint64_t -spi_read(void *opaque, target_phys_addr_t addr, unsigned int size) +spi_read(void *opaque, hwaddr addr, unsigned int size) { XilinxSPI *s = opaque; uint32_t r = 0; @@ -230,7 +230,7 @@ spi_read(void *opaque, target_phys_addr_t addr, unsigned int size) } static void -spi_write(void *opaque, target_phys_addr_t addr, +spi_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { XilinxSPI *s = opaque; diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c index f64a7828fe..93a4957010 100644 --- a/hw/xilinx_spips.c +++ b/hw/xilinx_spips.c @@ -183,7 +183,7 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s) xilinx_spips_update_ixr(s); } -static uint64_t xilinx_spips_read(void *opaque, target_phys_addr_t addr, +static uint64_t xilinx_spips_read(void *opaque, hwaddr addr, unsigned size) { XilinxSPIPS *s = opaque; @@ -224,7 +224,7 @@ static uint64_t xilinx_spips_read(void *opaque, target_phys_addr_t addr, } -static void xilinx_spips_write(void *opaque, target_phys_addr_t addr, +static void xilinx_spips_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { int mask = ~0; diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c index 2e48ca2bee..2b01dc2869 100644 --- a/hw/xilinx_timer.c +++ b/hw/xilinx_timer.c @@ -72,7 +72,7 @@ static inline unsigned int num_timers(struct timerblock *t) return 2 - t->one_timer_only; } -static inline unsigned int timer_from_addr(target_phys_addr_t addr) +static inline unsigned int timer_from_addr(hwaddr addr) { /* Timers get a 4x32bit control reg area each. */ return addr >> 2; @@ -93,7 +93,7 @@ static void timer_update_irq(struct timerblock *t) } static uint64_t -timer_read(void *opaque, target_phys_addr_t addr, unsigned int size) +timer_read(void *opaque, hwaddr addr, unsigned int size) { struct timerblock *t = opaque; struct xlx_timer *xt; @@ -142,7 +142,7 @@ static void timer_enable(struct xlx_timer *xt) } static void -timer_write(void *opaque, target_phys_addr_t addr, +timer_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { struct timerblock *t = opaque; diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c index d0f32db2c6..d20fc4124b 100644 --- a/hw/xilinx_uartlite.c +++ b/hw/xilinx_uartlite.c @@ -84,7 +84,7 @@ static void uart_update_status(struct xlx_uartlite *s) } static uint64_t -uart_read(void *opaque, target_phys_addr_t addr, unsigned int size) +uart_read(void *opaque, hwaddr addr, unsigned int size) { struct xlx_uartlite *s = opaque; uint32_t r = 0; @@ -109,7 +109,7 @@ uart_read(void *opaque, target_phys_addr_t addr, unsigned int size) } static void -uart_write(void *opaque, target_phys_addr_t addr, +uart_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { struct xlx_uartlite *s = opaque; diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c index 0c407d37b7..5dd2e08332 100644 --- a/hw/xtensa_lx60.c +++ b/hw/xtensa_lx60.c @@ -58,7 +58,7 @@ static void lx60_fpga_reset(void *opaque) s->switches = 0; } -static uint64_t lx60_fpga_read(void *opaque, target_phys_addr_t addr, +static uint64_t lx60_fpga_read(void *opaque, hwaddr addr, unsigned size) { Lx60FpgaState *s = opaque; @@ -79,7 +79,7 @@ static uint64_t lx60_fpga_read(void *opaque, target_phys_addr_t addr, return 0; } -static void lx60_fpga_write(void *opaque, target_phys_addr_t addr, +static void lx60_fpga_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { Lx60FpgaState *s = opaque; @@ -104,7 +104,7 @@ static const MemoryRegionOps lx60_fpga_ops = { }; static Lx60FpgaState *lx60_fpga_init(MemoryRegion *address_space, - target_phys_addr_t base) + hwaddr base) { Lx60FpgaState *s = g_malloc(sizeof(Lx60FpgaState)); @@ -117,9 +117,9 @@ static Lx60FpgaState *lx60_fpga_init(MemoryRegion *address_space, } static void lx60_net_init(MemoryRegion *address_space, - target_phys_addr_t base, - target_phys_addr_t descriptors, - target_phys_addr_t buffers, + hwaddr base, + hwaddr descriptors, + hwaddr buffers, qemu_irq irq, NICInfo *nd) { DeviceState *dev; diff --git a/hw/zaurus.c b/hw/zaurus.c index 72838ec440..d77b34ecce 100644 --- a/hw/zaurus.c +++ b/hw/zaurus.c @@ -68,7 +68,7 @@ static inline void scoop_gpio_handler_update(ScoopInfo *s) { s->prev_level = level; } -static uint64_t scoop_read(void *opaque, target_phys_addr_t addr, +static uint64_t scoop_read(void *opaque, hwaddr addr, unsigned size) { ScoopInfo *s = (ScoopInfo *) opaque; @@ -102,7 +102,7 @@ static uint64_t scoop_read(void *opaque, target_phys_addr_t addr, return 0; } -static void scoop_write(void *opaque, target_phys_addr_t addr, +static void scoop_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { ScoopInfo *s = (ScoopInfo *) opaque; @@ -285,7 +285,7 @@ static struct QEMU_PACKED sl_param_info { .phadadj = 0x01, }; -void sl_bootparam_write(target_phys_addr_t ptr) +void sl_bootparam_write(hwaddr ptr) { cpu_physical_memory_write(ptr, (void *)&zaurus_bootparam, sizeof(struct sl_param_info)); diff --git a/hw/zynq_slcr.c b/hw/zynq_slcr.c index 8acba01c3a..dde4306195 100644 --- a/hw/zynq_slcr.c +++ b/hw/zynq_slcr.c @@ -246,7 +246,7 @@ static void zynq_slcr_reset(DeviceState *d) } static inline uint32_t zynq_slcr_read_imp(void *opaque, - target_phys_addr_t offset) + hwaddr offset) { ZynqSLCRState *s = (ZynqSLCRState *)opaque; @@ -329,7 +329,7 @@ static inline uint32_t zynq_slcr_read_imp(void *opaque, } } -static uint64_t zynq_slcr_read(void *opaque, target_phys_addr_t offset, +static uint64_t zynq_slcr_read(void *opaque, hwaddr offset, unsigned size) { uint32_t ret = zynq_slcr_read_imp(opaque, offset); @@ -338,7 +338,7 @@ static uint64_t zynq_slcr_read(void *opaque, target_phys_addr_t offset, return ret; } -static void zynq_slcr_write(void *opaque, target_phys_addr_t offset, +static void zynq_slcr_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { ZynqSLCRState *s = (ZynqSLCRState *)opaque; diff --git a/hwaddr.h b/hwaddr.h new file mode 100644 index 0000000000..251cf9216f --- /dev/null +++ b/hwaddr.h @@ -0,0 +1,24 @@ +/* Define hwaddr if it exists. */ + +#ifndef HWADDR_H +#define HWADDR_H + +#ifndef CONFIG_USER_ONLY + +#define HWADDR_BITS 64 +/* hwaddr is the type of a physical address (its size can + be different from 'target_ulong'). */ + +typedef uint64_t hwaddr; +#define HWADDR_MAX UINT64_MAX +#define TARGET_FMT_plx "%016" PRIx64 +#define HWADDR_PRId PRId64 +#define HWADDR_PRIi PRIi64 +#define HWADDR_PRIo PRIo64 +#define HWADDR_PRIu PRIu64 +#define HWADDR_PRIx PRIx64 +#define HWADDR_PRIX PRIX64 + +#endif + +#endif diff --git a/kvm-all.c b/kvm-all.c index c2c69093ec..961e1dbb71 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -60,7 +60,7 @@ typedef struct KVMSlot { - target_phys_addr_t start_addr; + hwaddr start_addr; ram_addr_t memory_size; void *ram; int slot; @@ -131,8 +131,8 @@ static KVMSlot *kvm_alloc_slot(KVMState *s) } static KVMSlot *kvm_lookup_matching_slot(KVMState *s, - target_phys_addr_t start_addr, - target_phys_addr_t end_addr) + hwaddr start_addr, + hwaddr end_addr) { int i; @@ -152,8 +152,8 @@ static KVMSlot *kvm_lookup_matching_slot(KVMState *s, * Find overlapping slot with lowest start address */ static KVMSlot *kvm_lookup_overlapping_slot(KVMState *s, - target_phys_addr_t start_addr, - target_phys_addr_t end_addr) + hwaddr start_addr, + hwaddr end_addr) { KVMSlot *found = NULL; int i; @@ -176,7 +176,7 @@ static KVMSlot *kvm_lookup_overlapping_slot(KVMState *s, } int kvm_physical_memory_addr_from_host(KVMState *s, void *ram, - target_phys_addr_t *phys_addr) + hwaddr *phys_addr) { int i; @@ -293,7 +293,7 @@ static int kvm_slot_dirty_pages_log_change(KVMSlot *mem, bool log_dirty) return kvm_set_user_memory_region(s, mem); } -static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr, +static int kvm_dirty_pages_log_change(hwaddr phys_addr, ram_addr_t size, bool log_dirty) { KVMState *s = kvm_state; @@ -302,7 +302,7 @@ static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr, if (mem == NULL) { fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-" TARGET_FMT_plx "\n", __func__, phys_addr, - (target_phys_addr_t)(phys_addr + size - 1)); + (hwaddr)(phys_addr + size - 1)); return -EINVAL; } return kvm_slot_dirty_pages_log_change(mem, log_dirty); @@ -363,7 +363,7 @@ static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section, { unsigned int i, j; unsigned long page_number, c; - target_phys_addr_t addr, addr1; + hwaddr addr, addr1; unsigned int len = ((section->size / TARGET_PAGE_SIZE) + HOST_LONG_BITS - 1) / HOST_LONG_BITS; unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE; @@ -406,8 +406,8 @@ static int kvm_physical_sync_dirty_bitmap(MemoryRegionSection *section) KVMDirtyLog d; KVMSlot *mem; int ret = 0; - target_phys_addr_t start_addr = section->offset_within_address_space; - target_phys_addr_t end_addr = start_addr + section->size; + hwaddr start_addr = section->offset_within_address_space; + hwaddr end_addr = start_addr + section->size; d.dirty_bitmap = NULL; while (start_addr < end_addr) { @@ -456,7 +456,7 @@ static int kvm_physical_sync_dirty_bitmap(MemoryRegionSection *section) static void kvm_coalesce_mmio_region(MemoryListener *listener, MemoryRegionSection *secion, - target_phys_addr_t start, target_phys_addr_t size) + hwaddr start, hwaddr size) { KVMState *s = kvm_state; @@ -473,7 +473,7 @@ static void kvm_coalesce_mmio_region(MemoryListener *listener, static void kvm_uncoalesce_mmio_region(MemoryListener *listener, MemoryRegionSection *secion, - target_phys_addr_t start, target_phys_addr_t size) + hwaddr start, hwaddr size) { KVMState *s = kvm_state; @@ -556,7 +556,7 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add) int err; MemoryRegion *mr = section->mr; bool log_dirty = memory_region_is_logging(mr); - target_phys_addr_t start_addr = section->offset_within_address_space; + hwaddr start_addr = section->offset_within_address_space; ram_addr_t size = section->size; void *ram = NULL; unsigned delta; diff --git a/kvm.h b/kvm.h index eefcb492f0..2b26dcb9bb 100644 --- a/kvm.h +++ b/kvm.h @@ -259,7 +259,7 @@ static inline void cpu_synchronize_post_init(CPUArchState *env) #if !defined(CONFIG_USER_ONLY) int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr, - target_phys_addr_t *phys_addr); + hwaddr *phys_addr); #endif #endif diff --git a/memory-internal.h b/memory-internal.h index b33a99da8b..1c34b9751c 100644 --- a/memory-internal.h +++ b/memory-internal.h @@ -52,8 +52,8 @@ void qemu_ram_free_from_ptr(ram_addr_t addr); struct MemoryRegion; struct MemoryRegionSection; -void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size); -void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size); +void qemu_register_coalesced_mmio(hwaddr addr, ram_addr_t size); +void qemu_unregister_coalesced_mmio(hwaddr addr, ram_addr_t size); int cpu_physical_memory_set_dirty_tracking(int enable); diff --git a/memory.c b/memory.c index 714ec43ec0..36bb9a59ae 100644 --- a/memory.c +++ b/memory.c @@ -209,7 +209,7 @@ typedef struct FlatView FlatView; /* Range of memory in the global map. Addresses are absolute. */ struct FlatRange { MemoryRegion *mr; - target_phys_addr_t offset_in_region; + hwaddr offset_in_region; AddrRange addr; uint8_t dirty_log_mask; bool readable; @@ -300,7 +300,7 @@ static void flatview_simplify(FlatView *view) } static void memory_region_read_accessor(void *opaque, - target_phys_addr_t addr, + hwaddr addr, uint64_t *value, unsigned size, unsigned shift, @@ -317,7 +317,7 @@ static void memory_region_read_accessor(void *opaque, } static void memory_region_write_accessor(void *opaque, - target_phys_addr_t addr, + hwaddr addr, uint64_t *value, unsigned size, unsigned shift, @@ -333,13 +333,13 @@ static void memory_region_write_accessor(void *opaque, mr->ops->write(mr->opaque, addr, tmp, size); } -static void access_with_adjusted_size(target_phys_addr_t addr, +static void access_with_adjusted_size(hwaddr addr, uint64_t *value, unsigned size, unsigned access_size_min, unsigned access_size_max, void (*access)(void *opaque, - target_phys_addr_t addr, + hwaddr addr, uint64_t *value, unsigned size, unsigned shift, @@ -478,7 +478,7 @@ static void render_memory_region(FlatView *view, { MemoryRegion *subregion; unsigned i; - target_phys_addr_t offset_in_region; + hwaddr offset_in_region; Int128 remain; Int128 now; FlatRange fr; @@ -817,7 +817,7 @@ void memory_region_init(MemoryRegion *mr, } static bool memory_region_access_valid(MemoryRegion *mr, - target_phys_addr_t addr, + hwaddr addr, unsigned size, bool is_write) { @@ -843,7 +843,7 @@ static bool memory_region_access_valid(MemoryRegion *mr, } static uint64_t memory_region_dispatch_read1(MemoryRegion *mr, - target_phys_addr_t addr, + hwaddr addr, unsigned size) { uint64_t data = 0; @@ -884,7 +884,7 @@ static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size) } static uint64_t memory_region_dispatch_read(MemoryRegion *mr, - target_phys_addr_t addr, + hwaddr addr, unsigned size) { uint64_t ret; @@ -895,7 +895,7 @@ static uint64_t memory_region_dispatch_read(MemoryRegion *mr, } static void memory_region_dispatch_write(MemoryRegion *mr, - target_phys_addr_t addr, + hwaddr addr, uint64_t data, unsigned size) { @@ -957,7 +957,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr, void memory_region_init_alias(MemoryRegion *mr, const char *name, MemoryRegion *orig, - target_phys_addr_t offset, + hwaddr offset, uint64_t size) { memory_region_init(mr, name, size); @@ -980,7 +980,7 @@ void memory_region_init_rom_device(MemoryRegion *mr, mr->ram_addr = qemu_ram_alloc(size, mr); } -static uint64_t invalid_read(void *opaque, target_phys_addr_t addr, +static uint64_t invalid_read(void *opaque, hwaddr addr, unsigned size) { MemoryRegion *mr = opaque; @@ -992,7 +992,7 @@ static uint64_t invalid_read(void *opaque, target_phys_addr_t addr, return -1U; } -static void invalid_write(void *opaque, target_phys_addr_t addr, uint64_t data, +static void invalid_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { MemoryRegion *mr = opaque; @@ -1063,16 +1063,16 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client) memory_region_transaction_commit(); } -bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr, - target_phys_addr_t size, unsigned client) +bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr, + hwaddr size, unsigned client) { assert(mr->terminates); return cpu_physical_memory_get_dirty(mr->ram_addr + addr, size, 1 << client); } -void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr, - target_phys_addr_t size) +void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr, + hwaddr size) { assert(mr->terminates); return cpu_physical_memory_set_dirty_range(mr->ram_addr + addr, size, -1); @@ -1110,8 +1110,8 @@ void memory_region_rom_device_set_readable(MemoryRegion *mr, bool readable) } } -void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr, - target_phys_addr_t size, unsigned client) +void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr, + hwaddr size, unsigned client) { assert(mr->terminates); cpu_physical_memory_reset_dirty(mr->ram_addr + addr, @@ -1180,7 +1180,7 @@ void memory_region_set_coalescing(MemoryRegion *mr) } void memory_region_add_coalescing(MemoryRegion *mr, - target_phys_addr_t offset, + hwaddr offset, uint64_t size) { CoalescedMemoryRange *cmr = g_malloc(sizeof(*cmr)); @@ -1220,7 +1220,7 @@ void memory_region_clear_flush_coalesced(MemoryRegion *mr) } void memory_region_add_eventfd(MemoryRegion *mr, - target_phys_addr_t addr, + hwaddr addr, unsigned size, bool match_data, uint64_t data, @@ -1252,7 +1252,7 @@ void memory_region_add_eventfd(MemoryRegion *mr, } void memory_region_del_eventfd(MemoryRegion *mr, - target_phys_addr_t addr, + hwaddr addr, unsigned size, bool match_data, uint64_t data, @@ -1284,7 +1284,7 @@ void memory_region_del_eventfd(MemoryRegion *mr, } static void memory_region_add_subregion_common(MemoryRegion *mr, - target_phys_addr_t offset, + hwaddr offset, MemoryRegion *subregion) { MemoryRegion *other; @@ -1328,7 +1328,7 @@ done: void memory_region_add_subregion(MemoryRegion *mr, - target_phys_addr_t offset, + hwaddr offset, MemoryRegion *subregion) { subregion->may_overlap = false; @@ -1337,7 +1337,7 @@ void memory_region_add_subregion(MemoryRegion *mr, } void memory_region_add_subregion_overlap(MemoryRegion *mr, - target_phys_addr_t offset, + hwaddr offset, MemoryRegion *subregion, unsigned priority) { @@ -1366,7 +1366,7 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled) memory_region_transaction_commit(); } -void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr) +void memory_region_set_address(MemoryRegion *mr, hwaddr addr) { MemoryRegion *parent = mr->parent; unsigned priority = mr->priority; @@ -1387,7 +1387,7 @@ void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr) memory_region_transaction_commit(); } -void memory_region_set_alias_offset(MemoryRegion *mr, target_phys_addr_t offset) +void memory_region_set_alias_offset(MemoryRegion *mr, hwaddr offset) { assert(mr->alias); @@ -1425,7 +1425,7 @@ static FlatRange *address_space_lookup(AddressSpace *as, AddrRange addr) } MemoryRegionSection memory_region_find(MemoryRegion *address_space, - target_phys_addr_t addr, uint64_t size) + hwaddr addr, uint64_t size) { AddressSpace *as = memory_region_to_address_space(address_space); AddrRange range = addrrange_make(int128_make64(addr), @@ -1559,12 +1559,12 @@ void address_space_destroy(AddressSpace *as) g_free(as->current_map); } -uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size) +uint64_t io_mem_read(MemoryRegion *mr, hwaddr addr, unsigned size) { return memory_region_dispatch_read(mr, addr, size); } -void io_mem_write(MemoryRegion *mr, target_phys_addr_t addr, +void io_mem_write(MemoryRegion *mr, hwaddr addr, uint64_t val, unsigned size) { memory_region_dispatch_write(mr, addr, val, size); @@ -1582,7 +1582,7 @@ typedef QTAILQ_HEAD(queue, MemoryRegionList) MemoryRegionListHead; static void mtree_print_mr(fprintf_function mon_printf, void *f, const MemoryRegion *mr, unsigned int level, - target_phys_addr_t base, + hwaddr base, MemoryRegionListHead *alias_print_queue) { MemoryRegionList *new_ml, *ml, *next_ml; @@ -1620,7 +1620,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, "-" TARGET_FMT_plx "\n", base + mr->addr, base + mr->addr - + (target_phys_addr_t)int128_get64(mr->size) - 1, + + (hwaddr)int128_get64(mr->size) - 1, mr->priority, mr->readable ? 'R' : '-', !mr->readonly && !(mr->rom_device && mr->readable) ? 'W' @@ -1629,13 +1629,13 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, mr->alias->name, mr->alias_offset, mr->alias_offset - + (target_phys_addr_t)int128_get64(mr->size) - 1); + + (hwaddr)int128_get64(mr->size) - 1); } else { mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %c%c): %s\n", base + mr->addr, base + mr->addr - + (target_phys_addr_t)int128_get64(mr->size) - 1, + + (hwaddr)int128_get64(mr->size) - 1, mr->priority, mr->readable ? 'R' : '-', !mr->readonly && !(mr->rom_device && mr->readable) ? 'W' diff --git a/memory.h b/memory.h index 79393f1a76..9462bfd3ad 100644 --- a/memory.h +++ b/memory.h @@ -20,7 +20,7 @@ #include #include "qemu-common.h" #include "cpu-common.h" -#include "targphys.h" +#include "hwaddr.h" #include "qemu-queue.h" #include "iorange.h" #include "ioport.h" @@ -48,7 +48,7 @@ typedef struct MemoryRegionIORange MemoryRegionIORange; struct MemoryRegionIORange { IORange iorange; MemoryRegion *mr; - target_phys_addr_t offset; + hwaddr offset; }; /* @@ -58,12 +58,12 @@ struct MemoryRegionOps { /* Read from the memory region. @addr is relative to @mr; @size is * in bytes. */ uint64_t (*read)(void *opaque, - target_phys_addr_t addr, + hwaddr addr, unsigned size); /* Write to the memory region. @addr is relative to @mr; @size is * in bytes. */ void (*write)(void *opaque, - target_phys_addr_t addr, + hwaddr addr, uint64_t data, unsigned size); @@ -84,7 +84,7 @@ struct MemoryRegionOps { * by the device (and results in machine dependent behaviour such * as a machine check exception). */ - bool (*accepts)(void *opaque, target_phys_addr_t addr, + bool (*accepts)(void *opaque, hwaddr addr, unsigned size, bool is_write); } valid; /* Internal implementation constraints: */ @@ -122,7 +122,7 @@ struct MemoryRegion { void *opaque; MemoryRegion *parent; Int128 size; - target_phys_addr_t addr; + hwaddr addr; void (*destructor)(MemoryRegion *mr); ram_addr_t ram_addr; bool subpage; @@ -135,7 +135,7 @@ struct MemoryRegion { bool warning_printed; /* For reservations */ bool flush_coalesced_mmio; MemoryRegion *alias; - target_phys_addr_t alias_offset; + hwaddr alias_offset; unsigned priority; bool may_overlap; QTAILQ_HEAD(subregions, MemoryRegion) subregions; @@ -189,9 +189,9 @@ typedef struct MemoryRegionSection MemoryRegionSection; struct MemoryRegionSection { MemoryRegion *mr; AddressSpace *address_space; - target_phys_addr_t offset_within_region; + hwaddr offset_within_region; uint64_t size; - target_phys_addr_t offset_within_address_space; + hwaddr offset_within_address_space; bool readonly; }; @@ -219,9 +219,9 @@ struct MemoryListener { void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section, bool match_data, uint64_t data, EventNotifier *e); void (*coalesced_mmio_add)(MemoryListener *listener, MemoryRegionSection *section, - target_phys_addr_t addr, target_phys_addr_t len); + hwaddr addr, hwaddr len); void (*coalesced_mmio_del)(MemoryListener *listener, MemoryRegionSection *section, - target_phys_addr_t addr, target_phys_addr_t len); + hwaddr addr, hwaddr len); /* Lower = earlier (during add), later (during del) */ unsigned priority; AddressSpace *address_space_filter; @@ -301,7 +301,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr, void memory_region_init_alias(MemoryRegion *mr, const char *name, MemoryRegion *orig, - target_phys_addr_t offset, + hwaddr offset, uint64_t size); /** @@ -437,8 +437,8 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client); * @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or * %DIRTY_MEMORY_VGA. */ -bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr, - target_phys_addr_t size, unsigned client); +bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr, + hwaddr size, unsigned client); /** * memory_region_set_dirty: Mark a range of bytes as dirty in a memory region. @@ -450,8 +450,8 @@ bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr, * @addr: the address (relative to the start of the region) being dirtied. * @size: size of the range being dirtied. */ -void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr, - target_phys_addr_t size); +void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr, + hwaddr size); /** * memory_region_sync_dirty_bitmap: Synchronize a region's dirty bitmap with @@ -476,8 +476,8 @@ void memory_region_sync_dirty_bitmap(MemoryRegion *mr); * @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or * %DIRTY_MEMORY_VGA. */ -void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr, - target_phys_addr_t size, unsigned client); +void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr, + hwaddr size, unsigned client); /** * memory_region_set_readonly: Turn a memory region read-only (or read-write) @@ -527,7 +527,7 @@ void memory_region_set_coalescing(MemoryRegion *mr); * @size: the size of the subrange to be coalesced. */ void memory_region_add_coalescing(MemoryRegion *mr, - target_phys_addr_t offset, + hwaddr offset, uint64_t size); /** @@ -583,7 +583,7 @@ void memory_region_clear_flush_coalesced(MemoryRegion *mr); * @fd: the eventfd to be triggered when @addr, @size, and @data all match. **/ void memory_region_add_eventfd(MemoryRegion *mr, - target_phys_addr_t addr, + hwaddr addr, unsigned size, bool match_data, uint64_t data, @@ -603,7 +603,7 @@ void memory_region_add_eventfd(MemoryRegion *mr, * @fd: the eventfd to be triggered when @addr, @size, and @data all match. */ void memory_region_del_eventfd(MemoryRegion *mr, - target_phys_addr_t addr, + hwaddr addr, unsigned size, bool match_data, uint64_t data, @@ -624,7 +624,7 @@ void memory_region_del_eventfd(MemoryRegion *mr, * @subregion: the subregion to be added. */ void memory_region_add_subregion(MemoryRegion *mr, - target_phys_addr_t offset, + hwaddr offset, MemoryRegion *subregion); /** * memory_region_add_subregion_overlap: Add a subregion to a container @@ -644,7 +644,7 @@ void memory_region_add_subregion(MemoryRegion *mr, * @priority: used for resolving overlaps; highest priority wins. */ void memory_region_add_subregion_overlap(MemoryRegion *mr, - target_phys_addr_t offset, + hwaddr offset, MemoryRegion *subregion, unsigned priority); @@ -692,7 +692,7 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled); * @mr: the region to be updated * @addr: new address, relative to parent region */ -void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr); +void memory_region_set_address(MemoryRegion *mr, hwaddr addr); /* * memory_region_set_alias_offset: dynamically update a memory alias's offset @@ -704,7 +704,7 @@ void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr); * @offset: the new offset into the target memory region */ void memory_region_set_alias_offset(MemoryRegion *mr, - target_phys_addr_t offset); + hwaddr offset); /** * memory_region_find: locate a MemoryRegion in an address space @@ -725,7 +725,7 @@ void memory_region_set_alias_offset(MemoryRegion *mr, * @size: size of the area to be searched */ MemoryRegionSection memory_region_find(MemoryRegion *address_space, - target_phys_addr_t addr, uint64_t size); + hwaddr addr, uint64_t size); /** * memory_region_section_addr: get offset within MemoryRegionSection @@ -735,9 +735,9 @@ MemoryRegionSection memory_region_find(MemoryRegion *address_space, * @section: the memory region section being queried * @addr: address in address space */ -static inline target_phys_addr_t +static inline hwaddr memory_region_section_addr(MemoryRegionSection *section, - target_phys_addr_t addr) + hwaddr addr) { addr -= section->offset_within_address_space; addr += section->offset_within_region; @@ -824,7 +824,7 @@ void address_space_destroy(AddressSpace *as); * @buf: buffer with the data transferred * @is_write: indicates the transfer direction */ -void address_space_rw(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, +void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf, int len, bool is_write); /** @@ -834,7 +834,7 @@ void address_space_rw(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, * @addr: address within that address space * @buf: buffer with the data transferred */ -void address_space_write(AddressSpace *as, target_phys_addr_t addr, +void address_space_write(AddressSpace *as, hwaddr addr, const uint8_t *buf, int len); /** @@ -844,7 +844,7 @@ void address_space_write(AddressSpace *as, target_phys_addr_t addr, * @addr: address within that address space * @buf: buffer with the data transferred */ -void address_space_read(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, int len); +void address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len); /* address_space_map: map a physical memory region into a host virtual address * @@ -859,8 +859,8 @@ void address_space_read(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, * @plen: pointer to length of buffer; updated on return * @is_write: indicates the transfer direction */ -void *address_space_map(AddressSpace *as, target_phys_addr_t addr, - target_phys_addr_t *plen, bool is_write); +void *address_space_map(AddressSpace *as, hwaddr addr, + hwaddr *plen, bool is_write); /* address_space_unmap: Unmaps a memory region previously mapped by address_space_map() * @@ -873,8 +873,8 @@ void *address_space_map(AddressSpace *as, target_phys_addr_t addr, * @access_len: amount of data actually transferred * @is_write: indicates the transfer direction */ -void address_space_unmap(AddressSpace *as, void *buffer, target_phys_addr_t len, - int is_write, target_phys_addr_t access_len); +void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, + int is_write, hwaddr access_len); #endif diff --git a/memory_mapping.c b/memory_mapping.c index 6f5a2e3f71..a82e190cab 100644 --- a/memory_mapping.c +++ b/memory_mapping.c @@ -30,8 +30,8 @@ static void memory_mapping_list_add_mapping_sorted(MemoryMappingList *list, } static void create_new_memory_mapping(MemoryMappingList *list, - target_phys_addr_t phys_addr, - target_phys_addr_t virt_addr, + hwaddr phys_addr, + hwaddr virt_addr, ram_addr_t length) { MemoryMapping *memory_mapping; @@ -46,8 +46,8 @@ static void create_new_memory_mapping(MemoryMappingList *list, } static inline bool mapping_contiguous(MemoryMapping *map, - target_phys_addr_t phys_addr, - target_phys_addr_t virt_addr) + hwaddr phys_addr, + hwaddr virt_addr) { return phys_addr == map->phys_addr + map->length && virt_addr == map->virt_addr + map->length; @@ -58,7 +58,7 @@ static inline bool mapping_contiguous(MemoryMapping *map, * [phys_addr, phys_addr + length) have intersection? */ static inline bool mapping_have_same_region(MemoryMapping *map, - target_phys_addr_t phys_addr, + hwaddr phys_addr, ram_addr_t length) { return !(phys_addr + length < map->phys_addr || @@ -71,8 +71,8 @@ static inline bool mapping_have_same_region(MemoryMapping *map, * intersection are the same? */ static inline bool mapping_conflict(MemoryMapping *map, - target_phys_addr_t phys_addr, - target_phys_addr_t virt_addr) + hwaddr phys_addr, + hwaddr virt_addr) { return virt_addr - map->virt_addr != phys_addr - map->phys_addr; } @@ -83,7 +83,7 @@ static inline bool mapping_conflict(MemoryMapping *map, * in the intersection are the same. */ static inline void mapping_merge(MemoryMapping *map, - target_phys_addr_t virt_addr, + hwaddr virt_addr, ram_addr_t length) { if (virt_addr < map->virt_addr) { @@ -98,8 +98,8 @@ static inline void mapping_merge(MemoryMapping *map, } void memory_mapping_list_add_merge_sorted(MemoryMappingList *list, - target_phys_addr_t phys_addr, - target_phys_addr_t virt_addr, + hwaddr phys_addr, + hwaddr virt_addr, ram_addr_t length) { MemoryMapping *memory_mapping, *last_mapping; diff --git a/memory_mapping.h b/memory_mapping.h index ef72b0abad..d5ba46c7e7 100644 --- a/memory_mapping.h +++ b/memory_mapping.h @@ -18,7 +18,7 @@ /* The physical and virtual address in the memory mapping are contiguous. */ typedef struct MemoryMapping { - target_phys_addr_t phys_addr; + hwaddr phys_addr; target_ulong virt_addr; ram_addr_t length; QTAILQ_ENTRY(MemoryMapping) next; @@ -39,8 +39,8 @@ bool cpu_paging_enabled(CPUArchState *env); * and is contiguous. The list is sorted by phys_addr. */ void memory_mapping_list_add_merge_sorted(MemoryMappingList *list, - target_phys_addr_t phys_addr, - target_phys_addr_t virt_addr, + hwaddr phys_addr, + hwaddr virt_addr, ram_addr_t length); void memory_mapping_list_free(MemoryMappingList *list); diff --git a/monitor.c b/monitor.c index 131b325f1b..d17ae2d3b1 100644 --- a/monitor.c +++ b/monitor.c @@ -1059,7 +1059,7 @@ static void monitor_printc(Monitor *mon, int c) } static void memory_dump(Monitor *mon, int count, int format, int wsize, - target_phys_addr_t addr, int is_physical) + hwaddr addr, int is_physical) { CPUArchState *env; int l, line_size, i, max_digits, len; @@ -1193,7 +1193,7 @@ static void do_physical_memory_dump(Monitor *mon, const QDict *qdict) int count = qdict_get_int(qdict, "count"); int format = qdict_get_int(qdict, "format"); int size = qdict_get_int(qdict, "size"); - target_phys_addr_t addr = qdict_get_int(qdict, "addr"); + hwaddr addr = qdict_get_int(qdict, "addr"); memory_dump(mon, count, format, size, addr, 1); } @@ -1201,21 +1201,21 @@ static void do_physical_memory_dump(Monitor *mon, const QDict *qdict) static void do_print(Monitor *mon, const QDict *qdict) { int format = qdict_get_int(qdict, "format"); - target_phys_addr_t val = qdict_get_int(qdict, "val"); + hwaddr val = qdict_get_int(qdict, "val"); switch(format) { case 'o': - monitor_printf(mon, "%#" TARGET_PRIoPHYS, val); + monitor_printf(mon, "%#" HWADDR_PRIo, val); break; case 'x': - monitor_printf(mon, "%#" TARGET_PRIxPHYS, val); + monitor_printf(mon, "%#" HWADDR_PRIx, val); break; case 'u': - monitor_printf(mon, "%" TARGET_PRIuPHYS, val); + monitor_printf(mon, "%" HWADDR_PRIu, val); break; default: case 'd': - monitor_printf(mon, "%" TARGET_PRIdPHYS, val); + monitor_printf(mon, "%" HWADDR_PRId, val); break; case 'c': monitor_printc(mon, val); @@ -1337,9 +1337,9 @@ static void do_boot_set(Monitor *mon, const QDict *qdict) } #if defined(TARGET_I386) -static void print_pte(Monitor *mon, target_phys_addr_t addr, - target_phys_addr_t pte, - target_phys_addr_t mask) +static void print_pte(Monitor *mon, hwaddr addr, + hwaddr pte, + hwaddr mask) { #ifdef TARGET_X86_64 if (addr & (1ULL << 47)) { @@ -1408,7 +1408,7 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env) if (pde & PG_PSE_MASK) { /* 2M pages with PAE, CR4.PSE is ignored */ print_pte(mon, (l1 << 30 ) + (l2 << 21), pde, - ~((target_phys_addr_t)(1 << 20) - 1)); + ~((hwaddr)(1 << 20) - 1)); } else { pt_addr = pde & 0x3fffffffff000ULL; for (l3 = 0; l3 < 512; l3++) { @@ -1418,7 +1418,7 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env) print_pte(mon, (l1 << 30 ) + (l2 << 21) + (l3 << 12), pte & ~PG_PSE_MASK, - ~(target_phys_addr_t)0xfff); + ~(hwaddr)0xfff); } } } @@ -1510,9 +1510,9 @@ static void tlb_info(Monitor *mon) } } -static void mem_print(Monitor *mon, target_phys_addr_t *pstart, +static void mem_print(Monitor *mon, hwaddr *pstart, int *plast_prot, - target_phys_addr_t end, int prot) + hwaddr end, int prot) { int prot1; prot1 = *plast_prot; @@ -1538,7 +1538,7 @@ static void mem_info_32(Monitor *mon, CPUArchState *env) unsigned int l1, l2; int prot, last_prot; uint32_t pgd, pde, pte; - target_phys_addr_t start, end; + hwaddr start, end; pgd = env->cr[3] & ~0xfff; last_prot = 0; @@ -1571,7 +1571,7 @@ static void mem_info_32(Monitor *mon, CPUArchState *env) } } /* Flush last range */ - mem_print(mon, &start, &last_prot, (target_phys_addr_t)1 << 32, 0); + mem_print(mon, &start, &last_prot, (hwaddr)1 << 32, 0); } static void mem_info_pae32(Monitor *mon, CPUArchState *env) @@ -1580,7 +1580,7 @@ static void mem_info_pae32(Monitor *mon, CPUArchState *env) int prot, last_prot; uint64_t pdpe, pde, pte; uint64_t pdp_addr, pd_addr, pt_addr; - target_phys_addr_t start, end; + hwaddr start, end; pdp_addr = env->cr[3] & ~0x1f; last_prot = 0; @@ -1626,7 +1626,7 @@ static void mem_info_pae32(Monitor *mon, CPUArchState *env) } } /* Flush last range */ - mem_print(mon, &start, &last_prot, (target_phys_addr_t)1 << 32, 0); + mem_print(mon, &start, &last_prot, (hwaddr)1 << 32, 0); } @@ -1705,7 +1705,7 @@ static void mem_info_64(Monitor *mon, CPUArchState *env) } } /* Flush last range */ - mem_print(mon, &start, &last_prot, (target_phys_addr_t)1 << 48, 0); + mem_print(mon, &start, &last_prot, (hwaddr)1 << 48, 0); } #endif diff --git a/softmmu_template.h b/softmmu_template.h index e2490f03a7..20d6baba68 100644 --- a/softmmu_template.h +++ b/softmmu_template.h @@ -59,7 +59,7 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, int mmu_idx, uintptr_t retaddr); static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env, - target_phys_addr_t physaddr, + hwaddr physaddr, target_ulong addr, uintptr_t retaddr) { @@ -98,7 +98,7 @@ glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr, DATA_TYPE res; int index; target_ulong tlb_addr; - target_phys_addr_t ioaddr; + hwaddr ioaddr; uintptr_t retaddr; /* test if there is match for unaligned or IO access */ @@ -158,7 +158,7 @@ glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, { DATA_TYPE res, res1, res2; int index, shift; - target_phys_addr_t ioaddr; + hwaddr ioaddr; target_ulong tlb_addr, addr1, addr2; index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); @@ -210,7 +210,7 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, uintptr_t retaddr); static inline void glue(io_write, SUFFIX)(CPUArchState *env, - target_phys_addr_t physaddr, + hwaddr physaddr, DATA_TYPE val, target_ulong addr, uintptr_t retaddr) @@ -244,7 +244,7 @@ void glue(glue(helper_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr, DATA_TYPE val, int mmu_idx) { - target_phys_addr_t ioaddr; + hwaddr ioaddr; target_ulong tlb_addr; uintptr_t retaddr; int index; @@ -300,7 +300,7 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, int mmu_idx, uintptr_t retaddr) { - target_phys_addr_t ioaddr; + hwaddr ioaddr; target_ulong tlb_addr; int index, i; diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 5689760cef..8f131b7325 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -454,7 +454,7 @@ void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val); #ifndef CONFIG_USER_ONLY void swap_shadow_regs(CPUAlphaState *env); QEMU_NORETURN void cpu_unassigned_access(CPUAlphaState *env1, - target_phys_addr_t addr, int is_write, + hwaddr addr, int is_write, int is_exec, int unused, int size); #endif diff --git a/target-alpha/helper.c b/target-alpha/helper.c index 81d4763b49..d9d7f75b58 100644 --- a/target-alpha/helper.c +++ b/target-alpha/helper.c @@ -315,7 +315,7 @@ static int get_physical_address(CPUAlphaState *env, target_ulong addr, return ret; } -target_phys_addr_t cpu_get_phys_page_debug(CPUAlphaState *env, target_ulong addr) +hwaddr cpu_get_phys_page_debug(CPUAlphaState *env, target_ulong addr) { target_ulong phys; int prot, fail; diff --git a/target-alpha/mem_helper.c b/target-alpha/mem_helper.c index 87cada48f9..617836cc6c 100644 --- a/target-alpha/mem_helper.c +++ b/target-alpha/mem_helper.c @@ -107,7 +107,7 @@ static void do_unaligned_access(CPUAlphaState *env, target_ulong addr, cpu_loop_exit(env); } -void cpu_unassigned_access(CPUAlphaState *env, target_phys_addr_t addr, +void cpu_unassigned_access(CPUAlphaState *env, hwaddr addr, int is_write, int is_exec, int unused, int size) { env->trap_arg0 = addr; diff --git a/target-arm/helper.c b/target-arm/helper.c index 58340bd9e6..8f2cba6c1d 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -8,7 +8,7 @@ #ifndef CONFIG_USER_ONLY static inline int get_phys_addr(CPUARMState *env, uint32_t address, int access_type, int is_user, - target_phys_addr_t *phys_ptr, int *prot, + hwaddr *phys_ptr, int *prot, target_ulong *page_size); #endif @@ -517,7 +517,7 @@ static inline bool extended_addresses_enabled(CPUARMState *env) static int ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - target_phys_addr_t phys_addr; + hwaddr phys_addr; target_ulong page_size; int prot; int ret, is_user = ri->opc2 & 2; @@ -1980,7 +1980,7 @@ static uint32_t get_level1_table_address(CPUARMState *env, uint32_t address) } static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type, - int is_user, target_phys_addr_t *phys_ptr, + int is_user, hwaddr *phys_ptr, int *prot, target_ulong *page_size) { int code; @@ -1990,7 +1990,7 @@ static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type, int ap; int domain; int domain_prot; - target_phys_addr_t phys_addr; + hwaddr phys_addr; /* Pagetable walk. */ /* Lookup l1 descriptor. */ @@ -2075,7 +2075,7 @@ do_fault: } static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type, - int is_user, target_phys_addr_t *phys_ptr, + int is_user, hwaddr *phys_ptr, int *prot, target_ulong *page_size) { int code; @@ -2087,7 +2087,7 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type, int ap; int domain = 0; int domain_prot; - target_phys_addr_t phys_addr; + hwaddr phys_addr; /* Pagetable walk. */ /* Lookup l1 descriptor. */ @@ -2197,7 +2197,7 @@ typedef enum { static int get_phys_addr_lpae(CPUARMState *env, uint32_t address, int access_type, int is_user, - target_phys_addr_t *phys_ptr, int *prot, + hwaddr *phys_ptr, int *prot, target_ulong *page_size_ptr) { /* Read an LPAE long-descriptor translation table. */ @@ -2208,7 +2208,7 @@ static int get_phys_addr_lpae(CPUARMState *env, uint32_t address, uint64_t ttbr; int ttbr_select; int n; - target_phys_addr_t descaddr; + hwaddr descaddr; uint32_t tableattrs; target_ulong page_size; uint32_t attrs; @@ -2366,7 +2366,7 @@ do_fault: static int get_phys_addr_mpu(CPUARMState *env, uint32_t address, int access_type, int is_user, - target_phys_addr_t *phys_ptr, int *prot) + hwaddr *phys_ptr, int *prot) { int n; uint32_t mask; @@ -2450,7 +2450,7 @@ static int get_phys_addr_mpu(CPUARMState *env, uint32_t address, */ static inline int get_phys_addr(CPUARMState *env, uint32_t address, int access_type, int is_user, - target_phys_addr_t *phys_ptr, int *prot, + hwaddr *phys_ptr, int *prot, target_ulong *page_size) { /* Fast Context Switch Extension. */ @@ -2482,7 +2482,7 @@ static inline int get_phys_addr(CPUARMState *env, uint32_t address, int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int access_type, int mmu_idx) { - target_phys_addr_t phys_addr; + hwaddr phys_addr; target_ulong page_size; int prot; int ret, is_user; @@ -2492,7 +2492,7 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, &page_size); if (ret == 0) { /* Map a single [sub]page. */ - phys_addr &= ~(target_phys_addr_t)0x3ff; + phys_addr &= ~(hwaddr)0x3ff; address &= ~(uint32_t)0x3ff; tlb_set_page (env, address, phys_addr, prot, mmu_idx, page_size); return 0; @@ -2512,9 +2512,9 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, return 1; } -target_phys_addr_t cpu_get_phys_page_debug(CPUARMState *env, target_ulong addr) +hwaddr cpu_get_phys_page_debug(CPUARMState *env, target_ulong addr) { - target_phys_addr_t phys_addr; + hwaddr phys_addr; target_ulong page_size; int prot; int ret; diff --git a/target-cris/helper.c b/target-cris/helper.c index 1bdb7e26b7..324fe052f5 100644 --- a/target-cris/helper.c +++ b/target-cris/helper.c @@ -246,7 +246,7 @@ void do_interrupt(CPUCRISState *env) env->pregs[PR_ERP]); } -target_phys_addr_t cpu_get_phys_page_debug(CPUCRISState * env, target_ulong addr) +hwaddr cpu_get_phys_page_debug(CPUCRISState * env, target_ulong addr) { uint32_t phy = addr; struct cris_mmu_result res; diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c index 8e5a56a3a8..41f9d1c3e3 100644 --- a/target-i386/arch_memory_mapping.c +++ b/target-i386/arch_memory_mapping.c @@ -16,10 +16,10 @@ #include "memory_mapping.h" /* PAE Paging or IA-32e Paging */ -static void walk_pte(MemoryMappingList *list, target_phys_addr_t pte_start_addr, +static void walk_pte(MemoryMappingList *list, hwaddr pte_start_addr, int32_t a20_mask, target_ulong start_line_addr) { - target_phys_addr_t pte_addr, start_paddr; + hwaddr pte_addr, start_paddr; uint64_t pte; target_ulong start_vaddr; int i; @@ -46,10 +46,10 @@ static void walk_pte(MemoryMappingList *list, target_phys_addr_t pte_start_addr, /* 32-bit Paging */ static void walk_pte2(MemoryMappingList *list, - target_phys_addr_t pte_start_addr, int32_t a20_mask, + hwaddr pte_start_addr, int32_t a20_mask, target_ulong start_line_addr) { - target_phys_addr_t pte_addr, start_paddr; + hwaddr pte_addr, start_paddr; uint32_t pte; target_ulong start_vaddr; int i; @@ -75,10 +75,10 @@ static void walk_pte2(MemoryMappingList *list, } /* PAE Paging or IA-32e Paging */ -static void walk_pde(MemoryMappingList *list, target_phys_addr_t pde_start_addr, +static void walk_pde(MemoryMappingList *list, hwaddr pde_start_addr, int32_t a20_mask, target_ulong start_line_addr) { - target_phys_addr_t pde_addr, pte_start_addr, start_paddr; + hwaddr pde_addr, pte_start_addr, start_paddr; uint64_t pde; target_ulong line_addr, start_vaddr; int i; @@ -112,10 +112,10 @@ static void walk_pde(MemoryMappingList *list, target_phys_addr_t pde_start_addr, /* 32-bit Paging */ static void walk_pde2(MemoryMappingList *list, - target_phys_addr_t pde_start_addr, int32_t a20_mask, + hwaddr pde_start_addr, int32_t a20_mask, bool pse) { - target_phys_addr_t pde_addr, pte_start_addr, start_paddr; + hwaddr pde_addr, pte_start_addr, start_paddr; uint32_t pde; target_ulong line_addr, start_vaddr; int i; @@ -149,9 +149,9 @@ static void walk_pde2(MemoryMappingList *list, /* PAE Paging */ static void walk_pdpe2(MemoryMappingList *list, - target_phys_addr_t pdpe_start_addr, int32_t a20_mask) + hwaddr pdpe_start_addr, int32_t a20_mask) { - target_phys_addr_t pdpe_addr, pde_start_addr; + hwaddr pdpe_addr, pde_start_addr; uint64_t pdpe; target_ulong line_addr; int i; @@ -173,10 +173,10 @@ static void walk_pdpe2(MemoryMappingList *list, #ifdef TARGET_X86_64 /* IA-32e Paging */ static void walk_pdpe(MemoryMappingList *list, - target_phys_addr_t pdpe_start_addr, int32_t a20_mask, + hwaddr pdpe_start_addr, int32_t a20_mask, target_ulong start_line_addr) { - target_phys_addr_t pdpe_addr, pde_start_addr, start_paddr; + hwaddr pdpe_addr, pde_start_addr, start_paddr; uint64_t pdpe; target_ulong line_addr, start_vaddr; int i; @@ -210,9 +210,9 @@ static void walk_pdpe(MemoryMappingList *list, /* IA-32e Paging */ static void walk_pml4e(MemoryMappingList *list, - target_phys_addr_t pml4e_start_addr, int32_t a20_mask) + hwaddr pml4e_start_addr, int32_t a20_mask) { - target_phys_addr_t pml4e_addr, pdpe_start_addr; + hwaddr pml4e_addr, pdpe_start_addr; uint64_t pml4e; target_ulong line_addr; int i; @@ -242,20 +242,20 @@ int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env) if (env->cr[4] & CR4_PAE_MASK) { #ifdef TARGET_X86_64 if (env->hflags & HF_LMA_MASK) { - target_phys_addr_t pml4e_addr; + hwaddr pml4e_addr; pml4e_addr = (env->cr[3] & ~0xfff) & env->a20_mask; walk_pml4e(list, pml4e_addr, env->a20_mask); } else #endif { - target_phys_addr_t pdpe_addr; + hwaddr pdpe_addr; pdpe_addr = (env->cr[3] & ~0x1f) & env->a20_mask; walk_pdpe2(list, pdpe_addr, env->a20_mask); } } else { - target_phys_addr_t pde_addr; + hwaddr pde_addr; bool pse; pde_addr = (env->cr[3] & ~0xfff) & env->a20_mask; diff --git a/target-i386/helper.c b/target-i386/helper.c index 2ee7c6d1b1..c5d42c5916 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -503,7 +503,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, uint64_t ptep, pte; target_ulong pde_addr, pte_addr; int error_code, is_dirty, prot, page_size, is_write, is_user; - target_phys_addr_t paddr; + hwaddr paddr; uint32_t page_offset; target_ulong vaddr, virt_addr; @@ -869,11 +869,11 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, return 1; } -target_phys_addr_t cpu_get_phys_page_debug(CPUX86State *env, target_ulong addr) +hwaddr cpu_get_phys_page_debug(CPUX86State *env, target_ulong addr) { target_ulong pde_addr, pte_addr; uint64_t pte; - target_phys_addr_t paddr; + hwaddr paddr; uint32_t page_offset; int page_size; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 5b18383d8f..3aa62b20ff 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -229,7 +229,7 @@ static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap, return -ENOSYS; } -static void kvm_mce_inject(CPUX86State *env, target_phys_addr_t paddr, int code) +static void kvm_mce_inject(CPUX86State *env, hwaddr paddr, int code) { uint64_t status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S; @@ -257,7 +257,7 @@ static void hardware_memory_error(void) int kvm_arch_on_sigbus_vcpu(CPUX86State *env, int code, void *addr) { ram_addr_t ram_addr; - target_phys_addr_t paddr; + hwaddr paddr; if ((env->mcg_cap & MCG_SER_P) && addr && (code == BUS_MCEERR_AR || code == BUS_MCEERR_AO)) { @@ -290,7 +290,7 @@ int kvm_arch_on_sigbus(int code, void *addr) { if ((first_cpu->mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) { ram_addr_t ram_addr; - target_phys_addr_t paddr; + hwaddr paddr; /* Hope we are lucky for AO MCE */ if (qemu_ram_addr_from_host(addr, &ram_addr) || diff --git a/target-i386/svm_helper.c b/target-i386/svm_helper.c index 4943c37fee..a238d95a55 100644 --- a/target-i386/svm_helper.c +++ b/target-i386/svm_helper.c @@ -85,7 +85,7 @@ void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param, } #else -static inline void svm_save_seg(CPUX86State *env, target_phys_addr_t addr, +static inline void svm_save_seg(CPUX86State *env, hwaddr addr, const SegmentCache *sc) { stw_phys(addr + offsetof(struct vmcb_seg, selector), @@ -98,7 +98,7 @@ static inline void svm_save_seg(CPUX86State *env, target_phys_addr_t addr, ((sc->flags >> 8) & 0xff) | ((sc->flags >> 12) & 0x0f00)); } -static inline void svm_load_seg(CPUX86State *env, target_phys_addr_t addr, +static inline void svm_load_seg(CPUX86State *env, hwaddr addr, SegmentCache *sc) { unsigned int flags; @@ -110,7 +110,7 @@ static inline void svm_load_seg(CPUX86State *env, target_phys_addr_t addr, sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12); } -static inline void svm_load_seg_cache(CPUX86State *env, target_phys_addr_t addr, +static inline void svm_load_seg_cache(CPUX86State *env, hwaddr addr, int seg_reg) { SegmentCache sc1, *sc = &sc1; diff --git a/target-lm32/helper.c b/target-lm32/helper.c index 1ea477fea3..0ed7cfda18 100644 --- a/target-lm32/helper.c +++ b/target-lm32/helper.c @@ -37,7 +37,7 @@ int cpu_lm32_handle_mmu_fault(CPULM32State *env, target_ulong address, int rw, return 0; } -target_phys_addr_t cpu_get_phys_page_debug(CPULM32State *env, target_ulong addr) +hwaddr cpu_get_phys_page_debug(CPULM32State *env, target_ulong addr) { return addr & TARGET_PAGE_MASK; } diff --git a/target-m68k/helper.c b/target-m68k/helper.c index eac0053c5d..a5d0100473 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -289,7 +289,7 @@ int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw, /* MMU */ /* TODO: This will need fixing once the MMU is implemented. */ -target_phys_addr_t cpu_get_phys_page_debug(CPUM68KState *env, target_ulong addr) +hwaddr cpu_get_phys_page_debug(CPUM68KState *env, target_ulong addr) { return addr; } diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h index 88430b5057..37bbdf1591 100644 --- a/target-microblaze/cpu.h +++ b/target-microblaze/cpu.h @@ -370,7 +370,7 @@ static inline void cpu_get_tb_cpu_state(CPUMBState *env, target_ulong *pc, } #if !defined(CONFIG_USER_ONLY) -void cpu_unassigned_access(CPUMBState *env1, target_phys_addr_t addr, +void cpu_unassigned_access(CPUMBState *env1, hwaddr addr, int is_write, int is_exec, int is_asi, int size); #endif diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c index 74fce26827..efaa123a14 100644 --- a/target-microblaze/helper.c +++ b/target-microblaze/helper.c @@ -258,7 +258,7 @@ void do_interrupt(CPUMBState *env) } } -target_phys_addr_t cpu_get_phys_page_debug(CPUMBState * env, target_ulong addr) +hwaddr cpu_get_phys_page_debug(CPUMBState * env, target_ulong addr) { target_ulong vaddr, paddr = 0; struct microblaze_mmu_lookup lu; diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c index c9789f44c7..210296b30b 100644 --- a/target-microblaze/op_helper.c +++ b/target-microblaze/op_helper.c @@ -501,7 +501,7 @@ void helper_mmu_write(CPUMBState *env, uint32_t rn, uint32_t v) mmu_write(env, rn, v); } -void cpu_unassigned_access(CPUMBState *env, target_phys_addr_t addr, +void cpu_unassigned_access(CPUMBState *env, hwaddr addr, int is_write, int is_exec, int is_asi, int size) { qemu_log_mask(CPU_LOG_INT, "Unassigned " TARGET_FMT_plx " wr=%d exe=%d\n", diff --git a/target-mips/cpu.h b/target-mips/cpu.h index b7a5112b7b..c4ca2855df 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -37,7 +37,7 @@ typedef struct CPUMIPSTLBContext CPUMIPSTLBContext; struct CPUMIPSTLBContext { uint32_t nb_tlb; uint32_t tlb_in_use; - int (*map_address) (struct CPUMIPSState *env, target_phys_addr_t *physical, int *prot, target_ulong address, int rw, int access_type); + int (*map_address) (struct CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong address, int rw, int access_type); void (*helper_tlbwi)(struct CPUMIPSState *env); void (*helper_tlbwr)(struct CPUMIPSState *env); void (*helper_tlbp)(struct CPUMIPSState *env); @@ -479,18 +479,18 @@ struct CPUMIPSState { #include "cpu-qom.h" #if !defined(CONFIG_USER_ONLY) -int no_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot, +int no_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong address, int rw, int access_type); -int fixed_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot, +int fixed_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong address, int rw, int access_type); -int r4k_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot, +int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong address, int rw, int access_type); void r4k_helper_tlbwi(CPUMIPSState *env); void r4k_helper_tlbwr(CPUMIPSState *env); void r4k_helper_tlbp(CPUMIPSState *env); void r4k_helper_tlbr(CPUMIPSState *env); -void cpu_unassigned_access(CPUMIPSState *env, target_phys_addr_t addr, +void cpu_unassigned_access(CPUMIPSState *env, hwaddr addr, int is_write, int is_exec, int unused, int size); #endif @@ -658,7 +658,7 @@ int cpu_mips_handle_mmu_fault (CPUMIPSState *env, target_ulong address, int rw, void do_interrupt (CPUMIPSState *env); #if !defined(CONFIG_USER_ONLY) void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra); -target_phys_addr_t cpu_mips_translate_address (CPUMIPSState *env, target_ulong address, +hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address, int rw); #endif diff --git a/target-mips/helper.c b/target-mips/helper.c index 4208bb20c8..3b8c696a9e 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -36,7 +36,7 @@ enum { #if !defined(CONFIG_USER_ONLY) /* no MMU emulation */ -int no_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot, +int no_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong address, int rw, int access_type) { *physical = address; @@ -45,7 +45,7 @@ int no_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *pr } /* fixed mapping MMU emulation */ -int fixed_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot, +int fixed_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong address, int rw, int access_type) { if (address <= (int32_t)0x7FFFFFFFUL) { @@ -63,7 +63,7 @@ int fixed_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int } /* MIPS32/MIPS64 R4000-style MMU emulation */ -int r4k_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot, +int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong address, int rw, int access_type) { uint8_t ASID = env->CP0_EntryHi & 0xFF; @@ -99,7 +99,7 @@ int r4k_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot, return TLBRET_NOMATCH; } -static int get_physical_address (CPUMIPSState *env, target_phys_addr_t *physical, +static int get_physical_address (CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong address, int rw, int access_type) { @@ -254,9 +254,9 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address, } #if !defined(CONFIG_USER_ONLY) -target_phys_addr_t cpu_get_phys_page_debug(CPUMIPSState *env, target_ulong addr) +hwaddr cpu_get_phys_page_debug(CPUMIPSState *env, target_ulong addr) { - target_phys_addr_t phys_addr; + hwaddr phys_addr; int prot; if (get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT) != 0) @@ -269,7 +269,7 @@ int cpu_mips_handle_mmu_fault (CPUMIPSState *env, target_ulong address, int rw, int mmu_idx) { #if !defined(CONFIG_USER_ONLY) - target_phys_addr_t physical; + hwaddr physical; int prot; int access_type; #endif @@ -308,9 +308,9 @@ int cpu_mips_handle_mmu_fault (CPUMIPSState *env, target_ulong address, int rw, } #if !defined(CONFIG_USER_ONLY) -target_phys_addr_t cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int rw) +hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int rw) { - target_phys_addr_t physical; + hwaddr physical; int prot; int access_type; int ret = 0; diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 05b7730987..d50334f45f 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -273,11 +273,11 @@ void helper_dmultu(CPUMIPSState *env, target_ulong arg1, target_ulong arg2) #ifndef CONFIG_USER_ONLY -static inline target_phys_addr_t do_translate_address(CPUMIPSState *env, +static inline hwaddr do_translate_address(CPUMIPSState *env, target_ulong address, int rw) { - target_phys_addr_t lladdr; + hwaddr lladdr; lladdr = cpu_mips_translate_address(env, address, rw); @@ -2320,7 +2320,7 @@ void tlb_fill(CPUMIPSState *env, target_ulong addr, int is_write, int mmu_idx, } } -void cpu_unassigned_access(CPUMIPSState *env, target_phys_addr_t addr, +void cpu_unassigned_access(CPUMIPSState *env, hwaddr addr, int is_write, int is_exec, int unused, int size) { if (is_exec) diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h index de21a877d3..a701d364a5 100644 --- a/target-openrisc/cpu.h +++ b/target-openrisc/cpu.h @@ -279,11 +279,11 @@ typedef struct CPUOpenRISCTLBContext { OpenRISCTLBEntry dtlb[DTLB_WAYS][DTLB_SIZE]; int (*cpu_openrisc_map_address_code)(struct OpenRISCCPU *cpu, - target_phys_addr_t *physical, + hwaddr *physical, int *prot, target_ulong address, int rw); int (*cpu_openrisc_map_address_data)(struct OpenRISCCPU *cpu, - target_phys_addr_t *physical, + hwaddr *physical, int *prot, target_ulong address, int rw); } CPUOpenRISCTLBContext; @@ -387,13 +387,13 @@ void cpu_openrisc_count_stop(OpenRISCCPU *cpu); void cpu_openrisc_mmu_init(OpenRISCCPU *cpu); int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu, - target_phys_addr_t *physical, + hwaddr *physical, int *prot, target_ulong address, int rw); int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu, - target_phys_addr_t *physical, + hwaddr *physical, int *prot, target_ulong address, int rw); int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu, - target_phys_addr_t *physical, + hwaddr *physical, int *prot, target_ulong address, int rw); #endif diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c index 0be1d413c9..f2a6523cfb 100644 --- a/target-openrisc/mmu.c +++ b/target-openrisc/mmu.c @@ -28,7 +28,7 @@ #ifndef CONFIG_USER_ONLY int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu, - target_phys_addr_t *physical, + hwaddr *physical, int *prot, target_ulong address, int rw) { *physical = address; @@ -37,7 +37,7 @@ int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu, } int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu, - target_phys_addr_t *physical, + hwaddr *physical, int *prot, target_ulong address, int rw) { int vpn = address >> TARGET_PAGE_BITS; @@ -72,7 +72,7 @@ int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu, } int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu, - target_phys_addr_t *physical, + hwaddr *physical, int *prot, target_ulong address, int rw) { int vpn = address >> TARGET_PAGE_BITS; @@ -116,7 +116,7 @@ int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu, } static int cpu_openrisc_get_phys_addr(OpenRISCCPU *cpu, - target_phys_addr_t *physical, + hwaddr *physical, int *prot, target_ulong address, int rw) { @@ -185,7 +185,7 @@ int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env, target_ulong address, int rw, int mmu_idx) { int ret = 0; - target_phys_addr_t physical = 0; + hwaddr physical = 0; int prot = 0; OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); @@ -219,10 +219,10 @@ int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env, #endif #ifndef CONFIG_USER_ONLY -target_phys_addr_t cpu_get_phys_page_debug(CPUOpenRISCState *env, +hwaddr cpu_get_phys_page_debug(CPUOpenRISCState *env, target_ulong addr) { - target_phys_addr_t phys_addr; + hwaddr phys_addr; int prot; OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index faf4404078..3f114c983b 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -355,7 +355,7 @@ struct ppc6xx_tlb_t { typedef struct ppcemb_tlb_t ppcemb_tlb_t; struct ppcemb_tlb_t { - target_phys_addr_t RPN; + hwaddr RPN; target_ulong EPN; target_ulong PID; target_ulong size; @@ -983,8 +983,8 @@ struct CPUPPCState { int slb_nr; #endif /* segment registers */ - target_phys_addr_t htab_base; - target_phys_addr_t htab_mask; + hwaddr htab_base; + hwaddr htab_mask; target_ulong sr[32]; /* externally stored hash table */ uint8_t *external_htab; @@ -1045,9 +1045,9 @@ struct CPUPPCState { #endif #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) - target_phys_addr_t vpa; - target_phys_addr_t slb_shadow; - target_phys_addr_t dispatch_trace_log; + hwaddr vpa; + hwaddr slb_shadow; + hwaddr dispatch_trace_log; uint32_t dtl_size; #endif /* TARGET_PPC64 */ @@ -1066,7 +1066,7 @@ struct CPUPPCState { target_ulong ivor_mask; target_ulong ivpr_mask; target_ulong hreset_vector; - target_phys_addr_t mpic_cpu_base; + hwaddr mpic_cpu_base; #endif /* Those resources are used only during code translation */ @@ -1117,10 +1117,10 @@ do { \ /* Context used internally during MMU translations */ typedef struct mmu_ctx_t mmu_ctx_t; struct mmu_ctx_t { - target_phys_addr_t raddr; /* Real address */ - target_phys_addr_t eaddr; /* Effective address */ + hwaddr raddr; /* Real address */ + hwaddr eaddr; /* Effective address */ int prot; /* Protection bits */ - target_phys_addr_t hash[2]; /* Pagetable hash values */ + hwaddr hash[2]; /* Pagetable hash values */ target_ulong ptem; /* Virtual segment ID | API */ int key; /* Access key */ int nx; /* Non-execute area */ @@ -1191,9 +1191,9 @@ void store_40x_sler (CPUPPCState *env, uint32_t val); void store_booke_tcr (CPUPPCState *env, target_ulong val); void store_booke_tsr (CPUPPCState *env, target_ulong val); void booke206_flush_tlb(CPUPPCState *env, int flags, const int check_iprot); -target_phys_addr_t booke206_tlb_to_page_size(CPUPPCState *env, ppcmas_tlb_t *tlb); +hwaddr booke206_tlb_to_page_size(CPUPPCState *env, ppcmas_tlb_t *tlb); int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, - target_phys_addr_t *raddrp, target_ulong address, + hwaddr *raddrp, target_ulong address, uint32_t pid); void ppc_tlb_invalidate_all (CPUPPCState *env); void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr); diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c index 532b114aed..4a9bb5b965 100644 --- a/target-ppc/mmu_helper.c +++ b/target-ppc/mmu_helper.c @@ -215,7 +215,7 @@ static inline int pte_check(mmu_ctx_t *ctx, int is_64b, target_ulong pte0, pp = pte1 & 0x00000003; } if (ptem == ctx->ptem) { - if (ctx->raddr != (target_phys_addr_t)-1ULL) { + if (ctx->raddr != (hwaddr)-1ULL) { /* all matches should have equal RPN, WIMG & PP */ if ((ctx->raddr & mmask) != (pte1 & mmask)) { qemu_log("Bad RPN/WIMG/PP\n"); @@ -556,8 +556,8 @@ static inline int get_bat(CPUPPCState *env, mmu_ctx_t *ctx, return ret; } -static inline target_phys_addr_t get_pteg_offset(CPUPPCState *env, - target_phys_addr_t hash, +static inline hwaddr get_pteg_offset(CPUPPCState *env, + hwaddr hash, int pte_size) { return (hash * pte_size * 8) & env->htab_mask; @@ -567,7 +567,7 @@ static inline target_phys_addr_t get_pteg_offset(CPUPPCState *env, static inline int find_pte2(CPUPPCState *env, mmu_ctx_t *ctx, int is_64b, int h, int rw, int type, int target_page_bits) { - target_phys_addr_t pteg_off; + hwaddr pteg_off; target_ulong pte0, pte1; int i, good = -1; int ret, r; @@ -817,7 +817,7 @@ static int ppc_load_slb_vsid(CPUPPCState *env, target_ulong rb, static inline int get_segment(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr, int rw, int type) { - target_phys_addr_t hash; + hwaddr hash; target_ulong vsid; int ds, pr, target_page_bits; int ret, ret2; @@ -896,7 +896,7 @@ static inline int get_segment(CPUPPCState *env, mmu_ctx_t *ctx, ctx->hash[1] = ~hash; /* Initialize real address with an invalid value */ - ctx->raddr = (target_phys_addr_t)-1ULL; + ctx->raddr = (hwaddr)-1ULL; if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx || env->mmu_model == POWERPC_MMU_SOFT_74xx)) { /* Software TLB search */ @@ -926,7 +926,7 @@ static inline int get_segment(CPUPPCState *env, mmu_ctx_t *ctx, } #if defined(DUMP_PAGE_TABLES) if (qemu_log_enabled()) { - target_phys_addr_t curaddr; + hwaddr curaddr; uint32_t a0, a1, a2, a3; qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx @@ -1009,7 +1009,7 @@ static inline int get_segment(CPUPPCState *env, mmu_ctx_t *ctx, /* Generic TLB check function for embedded PowerPC implementations */ static int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb, - target_phys_addr_t *raddrp, + hwaddr *raddrp, target_ulong address, uint32_t pid, int ext, int i) { @@ -1045,7 +1045,7 @@ static int ppcemb_tlb_search(CPUPPCState *env, target_ulong address, uint32_t pid) { ppcemb_tlb_t *tlb; - target_phys_addr_t raddr; + hwaddr raddr; int i, ret; /* Default return value is no match */ @@ -1079,7 +1079,7 @@ static inline void ppc4xx_tlb_invalidate_virt(CPUPPCState *env, { #if !defined(FLUSH_ALL_TLBS) ppcemb_tlb_t *tlb; - target_phys_addr_t raddr; + hwaddr raddr; target_ulong page, end; int i; @@ -1104,11 +1104,11 @@ static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, int access_type) { ppcemb_tlb_t *tlb; - target_phys_addr_t raddr; + hwaddr raddr; int i, ret, zsel, zpr, pr; ret = -1; - raddr = (target_phys_addr_t)-1ULL; + raddr = (hwaddr)-1ULL; pr = msr_pr; for (i = 0; i < env->nb_tlb; i++) { tlb = &env->tlb.tlbe[i]; @@ -1175,7 +1175,7 @@ void store_40x_sler(CPUPPCState *env, uint32_t val) } static inline int mmubooke_check_tlb(CPUPPCState *env, ppcemb_tlb_t *tlb, - target_phys_addr_t *raddr, int *prot, + hwaddr *raddr, int *prot, target_ulong address, int rw, int access_type, int i) { @@ -1249,11 +1249,11 @@ static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, int access_type) { ppcemb_tlb_t *tlb; - target_phys_addr_t raddr; + hwaddr raddr; int i, ret; ret = -1; - raddr = (target_phys_addr_t)-1ULL; + raddr = (hwaddr)-1ULL; for (i = 0; i < env->nb_tlb; i++) { tlb = &env->tlb.tlbe[i]; ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw, @@ -1297,7 +1297,7 @@ void booke206_flush_tlb(CPUPPCState *env, int flags, const int check_iprot) tlb_flush(env, 1); } -target_phys_addr_t booke206_tlb_to_page_size(CPUPPCState *env, +hwaddr booke206_tlb_to_page_size(CPUPPCState *env, ppcmas_tlb_t *tlb) { int tlbm_size; @@ -1309,7 +1309,7 @@ target_phys_addr_t booke206_tlb_to_page_size(CPUPPCState *env, /* TLB check function for MAS based SoftTLBs */ int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, - target_phys_addr_t *raddrp, + hwaddr *raddrp, target_ulong address, uint32_t pid) { target_ulong mask; @@ -1345,7 +1345,7 @@ int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, } static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb, - target_phys_addr_t *raddr, int *prot, + hwaddr *raddr, int *prot, target_ulong address, int rw, int access_type) { @@ -1435,11 +1435,11 @@ static int mmubooke206_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, int access_type) { ppcmas_tlb_t *tlb; - target_phys_addr_t raddr; + hwaddr raddr; int i, j, ret; ret = -1; - raddr = (target_phys_addr_t)-1ULL; + raddr = (hwaddr)-1ULL; for (i = 0; i < BOOKE206_MAX_TLBN; i++) { int ways = booke206_tlb_ways(env, i); @@ -1496,7 +1496,7 @@ static void mmubooke_dump_mmu(FILE *f, fprintf_function cpu_fprintf, entry = &env->tlb.tlbe[0]; for (i = 0; i < env->nb_tlb; i++, entry++) { - target_phys_addr_t ea, pa; + hwaddr ea, pa; target_ulong mask; uint64_t size = (uint64_t)entry->size; char size_buf[20]; @@ -1509,9 +1509,9 @@ static void mmubooke_dump_mmu(FILE *f, fprintf_function cpu_fprintf, mask = ~(entry->size - 1); ea = entry->EPN & mask; pa = entry->RPN & mask; -#if (TARGET_PHYS_ADDR_BITS >= 36) +#if (TARGET_PHYS_ADDR_SPACE_BITS >= 36) /* Extend the physical address to 36 bits */ - pa |= (target_phys_addr_t)(entry->RPN & 0xF) << 32; + pa |= (hwaddr)(entry->RPN & 0xF) << 32; #endif size /= 1024; if (size >= 1024) { @@ -1539,7 +1539,7 @@ static void mmubooke206_dump_one_tlb(FILE *f, fprintf_function cpu_fprintf, entry = &env->tlb.tlbm[offset]; for (i = 0; i < tlbsize; i++, entry++) { - target_phys_addr_t ea, pa, size; + hwaddr ea, pa, size; int tsize; if (!(entry->mas1 & MAS1_VALID)) { @@ -1785,7 +1785,7 @@ int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr, return ret; } -target_phys_addr_t cpu_get_phys_page_debug(CPUPPCState *env, target_ulong addr) +hwaddr cpu_get_phys_page_debug(CPUPPCState *env, target_ulong addr) { mmu_ctx_t ctx; @@ -3145,7 +3145,7 @@ void helper_booke206_tlbsx(CPUPPCState *env, target_ulong address) { ppcmas_tlb_t *tlb = NULL; int i, j; - target_phys_addr_t raddr; + hwaddr raddr; uint32_t spid, sas; spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT; diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index ed81af33a1..9997765dd1 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -324,7 +324,7 @@ unsigned s390_del_running_cpu(CPUS390XState *env); void s390_sclp_extint(uint32_t parm); /* from s390-virtio-bus */ -extern const target_phys_addr_t virtio_size; +extern const hwaddr virtio_size; #else static inline void s390_add_running_cpu(CPUS390XState *env) diff --git a/target-s390x/helper.c b/target-s390x/helper.c index 22256b057d..b7b812a7e6 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -419,7 +419,7 @@ int cpu_s390x_handle_mmu_fault(CPUS390XState *env, target_ulong orig_vaddr, return 0; } -target_phys_addr_t cpu_get_phys_page_debug(CPUS390XState *env, +hwaddr cpu_get_phys_page_debug(CPUS390XState *env, target_ulong vaddr) { target_ulong raddr; @@ -474,7 +474,7 @@ static void do_svc_interrupt(CPUS390XState *env) { uint64_t mask, addr; LowCore *lowcore; - target_phys_addr_t len = TARGET_PAGE_SIZE; + hwaddr len = TARGET_PAGE_SIZE; lowcore = cpu_physical_memory_map(env->psa, &len, 1); @@ -494,7 +494,7 @@ static void do_program_interrupt(CPUS390XState *env) { uint64_t mask, addr; LowCore *lowcore; - target_phys_addr_t len = TARGET_PAGE_SIZE; + hwaddr len = TARGET_PAGE_SIZE; int ilc = env->int_pgm_ilc; switch (ilc) { @@ -538,7 +538,7 @@ static void do_ext_interrupt(CPUS390XState *env) { uint64_t mask, addr; LowCore *lowcore; - target_phys_addr_t len = TARGET_PAGE_SIZE; + hwaddr len = TARGET_PAGE_SIZE; ExtQueue *q; if (!(env->psw.mask & PSW_MASK_EXT)) { diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c index b21b37c5e7..6ebc22dd11 100644 --- a/target-s390x/mem_helper.c +++ b/target-s390x/mem_helper.c @@ -78,8 +78,8 @@ void tlb_fill(CPUS390XState *env, target_ulong addr, int is_write, int mmu_idx, static void mvc_fast_memset(CPUS390XState *env, uint32_t l, uint64_t dest, uint8_t byte) { - target_phys_addr_t dest_phys; - target_phys_addr_t len = l; + hwaddr dest_phys; + hwaddr len = l; void *dest_p; uint64_t asc = env->psw.mask & PSW_MASK_ASC; int flags; @@ -100,9 +100,9 @@ static void mvc_fast_memset(CPUS390XState *env, uint32_t l, uint64_t dest, static void mvc_fast_memmove(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) { - target_phys_addr_t dest_phys; - target_phys_addr_t src_phys; - target_phys_addr_t len = l; + hwaddr dest_phys; + hwaddr src_phys; + hwaddr len = l; void *dest_p; void *src_p; uint64_t asc = env->psw.mask & PSW_MASK_ASC; diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index bf592227ee..782159e8ba 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -204,20 +204,20 @@ void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf); #if !defined(CONFIG_USER_ONLY) void cpu_sh4_invalidate_tlb(CPUSH4State *s); uint32_t cpu_sh4_read_mmaped_itlb_addr(CPUSH4State *s, - target_phys_addr_t addr); -void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr, + hwaddr addr); +void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, hwaddr addr, uint32_t mem_value); uint32_t cpu_sh4_read_mmaped_itlb_data(CPUSH4State *s, - target_phys_addr_t addr); -void cpu_sh4_write_mmaped_itlb_data(CPUSH4State *s, target_phys_addr_t addr, + hwaddr addr); +void cpu_sh4_write_mmaped_itlb_data(CPUSH4State *s, hwaddr addr, uint32_t mem_value); uint32_t cpu_sh4_read_mmaped_utlb_addr(CPUSH4State *s, - target_phys_addr_t addr); -void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, + hwaddr addr); +void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, hwaddr addr, uint32_t mem_value); uint32_t cpu_sh4_read_mmaped_utlb_data(CPUSH4State *s, - target_phys_addr_t addr); -void cpu_sh4_write_mmaped_utlb_data(CPUSH4State *s, target_phys_addr_t addr, + hwaddr addr); +void cpu_sh4_write_mmaped_utlb_data(CPUSH4State *s, hwaddr addr, uint32_t mem_value); #endif diff --git a/target-sh4/helper.c b/target-sh4/helper.c index 5c57380f12..ddebc78964 100644 --- a/target-sh4/helper.c +++ b/target-sh4/helper.c @@ -503,7 +503,7 @@ int cpu_sh4_handle_mmu_fault(CPUSH4State * env, target_ulong address, int rw, return 0; } -target_phys_addr_t cpu_get_phys_page_debug(CPUSH4State * env, target_ulong addr) +hwaddr cpu_get_phys_page_debug(CPUSH4State * env, target_ulong addr) { target_ulong physical; int prot; @@ -574,7 +574,7 @@ void cpu_load_tlb(CPUSH4State * env) } uint32_t cpu_sh4_read_mmaped_itlb_addr(CPUSH4State *s, - target_phys_addr_t addr) + hwaddr addr) { int index = (addr & 0x00000300) >> 8; tlb_t * entry = &s->itlb[index]; @@ -584,7 +584,7 @@ uint32_t cpu_sh4_read_mmaped_itlb_addr(CPUSH4State *s, (entry->asid); } -void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr, +void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, hwaddr addr, uint32_t mem_value) { uint32_t vpn = (mem_value & 0xfffffc00) >> 10; @@ -604,7 +604,7 @@ void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr, } uint32_t cpu_sh4_read_mmaped_itlb_data(CPUSH4State *s, - target_phys_addr_t addr) + hwaddr addr) { int array = (addr & 0x00800000) >> 23; int index = (addr & 0x00000300) >> 8; @@ -626,7 +626,7 @@ uint32_t cpu_sh4_read_mmaped_itlb_data(CPUSH4State *s, } } -void cpu_sh4_write_mmaped_itlb_data(CPUSH4State *s, target_phys_addr_t addr, +void cpu_sh4_write_mmaped_itlb_data(CPUSH4State *s, hwaddr addr, uint32_t mem_value) { int array = (addr & 0x00800000) >> 23; @@ -655,7 +655,7 @@ void cpu_sh4_write_mmaped_itlb_data(CPUSH4State *s, target_phys_addr_t addr, } uint32_t cpu_sh4_read_mmaped_utlb_addr(CPUSH4State *s, - target_phys_addr_t addr) + hwaddr addr) { int index = (addr & 0x00003f00) >> 8; tlb_t * entry = &s->utlb[index]; @@ -667,7 +667,7 @@ uint32_t cpu_sh4_read_mmaped_utlb_addr(CPUSH4State *s, (entry->asid); } -void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, +void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, hwaddr addr, uint32_t mem_value) { int associate = addr & 0x0000080; @@ -740,7 +740,7 @@ void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, } uint32_t cpu_sh4_read_mmaped_utlb_data(CPUSH4State *s, - target_phys_addr_t addr) + hwaddr addr) { int array = (addr & 0x00800000) >> 23; int index = (addr & 0x00003f00) >> 8; @@ -766,7 +766,7 @@ uint32_t cpu_sh4_read_mmaped_utlb_data(CPUSH4State *s, } } -void cpu_sh4_write_mmaped_utlb_data(CPUSH4State *s, target_phys_addr_t addr, +void cpu_sh4_write_mmaped_utlb_data(CPUSH4State *s, hwaddr addr, uint32_t mem_value) { int array = (addr & 0x00800000) >> 23; diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 214d01dd71..a55fe08d36 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -583,10 +583,10 @@ static inline int tlb_compare_context(const SparcTLBEntry *tlb, /* cpu-exec.c */ #if !defined(CONFIG_USER_ONLY) -void cpu_unassigned_access(CPUSPARCState *env1, target_phys_addr_t addr, +void cpu_unassigned_access(CPUSPARCState *env1, hwaddr addr, int is_write, int is_exec, int is_asi, int size); #if defined(TARGET_SPARC64) -target_phys_addr_t cpu_get_phys_page_nofault(CPUSPARCState *env, target_ulong addr, +hwaddr cpu_get_phys_page_nofault(CPUSPARCState *env, target_ulong addr, int mmu_idx); #endif #endif diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c index 2ca9a5c4a9..356144a5c0 100644 --- a/target-sparc/ldst_helper.c +++ b/target-sparc/ldst_helper.c @@ -619,21 +619,21 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size, case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */ switch (size) { case 1: - ret = ldub_phys((target_phys_addr_t)addr - | ((target_phys_addr_t)(asi & 0xf) << 32)); + ret = ldub_phys((hwaddr)addr + | ((hwaddr)(asi & 0xf) << 32)); break; case 2: - ret = lduw_phys((target_phys_addr_t)addr - | ((target_phys_addr_t)(asi & 0xf) << 32)); + ret = lduw_phys((hwaddr)addr + | ((hwaddr)(asi & 0xf) << 32)); break; default: case 4: - ret = ldl_phys((target_phys_addr_t)addr - | ((target_phys_addr_t)(asi & 0xf) << 32)); + ret = ldl_phys((hwaddr)addr + | ((hwaddr)(asi & 0xf) << 32)); break; case 8: - ret = ldq_phys((target_phys_addr_t)addr - | ((target_phys_addr_t)(asi & 0xf) << 32)); + ret = ldq_phys((hwaddr)addr + | ((hwaddr)(asi & 0xf) << 32)); break; } break; @@ -1015,21 +1015,21 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi, { switch (size) { case 1: - stb_phys((target_phys_addr_t)addr - | ((target_phys_addr_t)(asi & 0xf) << 32), val); + stb_phys((hwaddr)addr + | ((hwaddr)(asi & 0xf) << 32), val); break; case 2: - stw_phys((target_phys_addr_t)addr - | ((target_phys_addr_t)(asi & 0xf) << 32), val); + stw_phys((hwaddr)addr + | ((hwaddr)(asi & 0xf) << 32), val); break; case 4: default: - stl_phys((target_phys_addr_t)addr - | ((target_phys_addr_t)(asi & 0xf) << 32), val); + stl_phys((hwaddr)addr + | ((hwaddr)(asi & 0xf) << 32), val); break; case 8: - stq_phys((target_phys_addr_t)addr - | ((target_phys_addr_t)(asi & 0xf) << 32), val); + stq_phys((hwaddr)addr + | ((hwaddr)(asi & 0xf) << 32), val); break; } } @@ -2313,7 +2313,7 @@ void helper_stqf(CPUSPARCState *env, target_ulong addr, int mem_idx) #if !defined(CONFIG_USER_ONLY) #ifndef TARGET_SPARC64 -void cpu_unassigned_access(CPUSPARCState *env, target_phys_addr_t addr, +void cpu_unassigned_access(CPUSPARCState *env, hwaddr addr, int is_write, int is_exec, int is_asi, int size) { int fault_type; @@ -2373,7 +2373,7 @@ void cpu_unassigned_access(CPUSPARCState *env, target_phys_addr_t addr, } } #else -void cpu_unassigned_access(CPUSPARCState *env, target_phys_addr_t addr, +void cpu_unassigned_access(CPUSPARCState *env, hwaddr addr, int is_write, int is_exec, int is_asi, int size) { #ifdef DEBUG_UNASSIGNED diff --git a/target-sparc/mmu_helper.c b/target-sparc/mmu_helper.c index cb73c449f0..2c89b20b68 100644 --- a/target-sparc/mmu_helper.c +++ b/target-sparc/mmu_helper.c @@ -76,13 +76,13 @@ static const int perm_table[2][8] = { } }; -static int get_physical_address(CPUSPARCState *env, target_phys_addr_t *physical, +static int get_physical_address(CPUSPARCState *env, hwaddr *physical, int *prot, int *access_index, target_ulong address, int rw, int mmu_idx, target_ulong *page_size) { int access_perms = 0; - target_phys_addr_t pde_ptr; + hwaddr pde_ptr; uint32_t pde; int error_code = 0, is_dirty, is_user; unsigned long page_offset; @@ -192,7 +192,7 @@ static int get_physical_address(CPUSPARCState *env, target_phys_addr_t *physical /* Even if large ptes, we map only one 4KB page in the cache to avoid filling it too fast */ - *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset; + *physical = ((hwaddr)(pde & PTE_ADDR_MASK) << 4) + page_offset; return error_code; } @@ -200,7 +200,7 @@ static int get_physical_address(CPUSPARCState *env, target_phys_addr_t *physical int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw, int mmu_idx) { - target_phys_addr_t paddr; + hwaddr paddr; target_ulong vaddr; target_ulong page_size; int error_code = 0, prot, access_index; @@ -244,11 +244,11 @@ int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw, target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev) { - target_phys_addr_t pde_ptr; + hwaddr pde_ptr; uint32_t pde; /* Context base + context number */ - pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) + + pde_ptr = (hwaddr)(env->mmuregs[1] << 4) + (env->mmuregs[2] << 2); pde = ldl_phys(pde_ptr); @@ -312,13 +312,13 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUSPARCState *env) { target_ulong va, va1, va2; unsigned int n, m, o; - target_phys_addr_t pde_ptr, pa; + hwaddr pde_ptr, pa; uint32_t pde; pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2); pde = ldl_phys(pde_ptr); (*cpu_fprintf)(f, "Root ptr: " TARGET_FMT_plx ", ctx: %d\n", - (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]); + (hwaddr)env->mmuregs[1] << 4, env->mmuregs[2]); for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) { pde = mmu_probe(env, va, 2); if (pde) { @@ -431,7 +431,7 @@ int target_memory_rw_debug(CPUSPARCState *env, target_ulong addr, #else /* !TARGET_SPARC64 */ /* 41 bit physical address space */ -static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x) +static inline hwaddr ultrasparc_truncate_physical(uint64_t x) { return x & 0x1ffffffffffULL; } @@ -445,7 +445,7 @@ static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x) entry size */ static inline int ultrasparc_tag_match(SparcTLBEntry *tlb, uint64_t address, uint64_t context, - target_phys_addr_t *physical) + hwaddr *physical) { uint64_t mask; @@ -478,7 +478,7 @@ static inline int ultrasparc_tag_match(SparcTLBEntry *tlb, } static int get_physical_address_data(CPUSPARCState *env, - target_phys_addr_t *physical, int *prot, + hwaddr *physical, int *prot, target_ulong address, int rw, int mmu_idx) { unsigned int i; @@ -597,7 +597,7 @@ static int get_physical_address_data(CPUSPARCState *env, } static int get_physical_address_code(CPUSPARCState *env, - target_phys_addr_t *physical, int *prot, + hwaddr *physical, int *prot, target_ulong address, int mmu_idx) { unsigned int i; @@ -665,7 +665,7 @@ static int get_physical_address_code(CPUSPARCState *env, return 1; } -static int get_physical_address(CPUSPARCState *env, target_phys_addr_t *physical, +static int get_physical_address(CPUSPARCState *env, hwaddr *physical, int *prot, int *access_index, target_ulong address, int rw, int mmu_idx, target_ulong *page_size) @@ -703,7 +703,7 @@ int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw, int mmu_idx) { target_ulong vaddr; - target_phys_addr_t paddr; + hwaddr paddr; target_ulong page_size; int error_code = 0, prot, access_index; @@ -810,7 +810,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUSPARCState *env) #endif /* TARGET_SPARC64 */ -static int cpu_sparc_get_phys_page(CPUSPARCState *env, target_phys_addr_t *phys, +static int cpu_sparc_get_phys_page(CPUSPARCState *env, hwaddr *phys, target_ulong addr, int rw, int mmu_idx) { target_ulong page_size; @@ -821,10 +821,10 @@ static int cpu_sparc_get_phys_page(CPUSPARCState *env, target_phys_addr_t *phys, } #if defined(TARGET_SPARC64) -target_phys_addr_t cpu_get_phys_page_nofault(CPUSPARCState *env, target_ulong addr, +hwaddr cpu_get_phys_page_nofault(CPUSPARCState *env, target_ulong addr, int mmu_idx) { - target_phys_addr_t phys_addr; + hwaddr phys_addr; if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 4, mmu_idx) != 0) { return -1; @@ -833,9 +833,9 @@ target_phys_addr_t cpu_get_phys_page_nofault(CPUSPARCState *env, target_ulong ad } #endif -target_phys_addr_t cpu_get_phys_page_debug(CPUSPARCState *env, target_ulong addr) +hwaddr cpu_get_phys_page_debug(CPUSPARCState *env, target_ulong addr) { - target_phys_addr_t phys_addr; + hwaddr phys_addr; int mmu_idx = cpu_mmu_index(env); MemoryRegionSection section; diff --git a/target-unicore32/softmmu.c b/target-unicore32/softmmu.c index 373f94b274..9c2c54cbc8 100644 --- a/target-unicore32/softmmu.c +++ b/target-unicore32/softmmu.c @@ -259,7 +259,7 @@ int uc32_cpu_handle_mmu_fault(CPUUniCore32State *env, target_ulong address, return ret; } -target_phys_addr_t cpu_get_phys_page_debug(CPUUniCore32State *env, +hwaddr cpu_get_phys_page_debug(CPUUniCore32State *env, target_ulong addr) { cpu_abort(env, "%s not supported yet\n", __func__); diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c index d5bb171fcd..d94bae210d 100644 --- a/target-xtensa/helper.c +++ b/target-xtensa/helper.c @@ -118,7 +118,7 @@ void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf) } } -target_phys_addr_t cpu_get_phys_page_debug(CPUXtensaState *env, target_ulong addr) +hwaddr cpu_get_phys_page_debug(CPUXtensaState *env, target_ulong addr) { uint32_t paddr; uint32_t page_size; diff --git a/target-xtensa/xtensa-semi.c b/target-xtensa/xtensa-semi.c index 52be07a368..851ff546f0 100644 --- a/target-xtensa/xtensa-semi.c +++ b/target-xtensa/xtensa-semi.c @@ -169,12 +169,12 @@ void HELPER(simcall)(CPUXtensaState *env) uint32_t len = regs[5]; while (len > 0) { - target_phys_addr_t paddr = + hwaddr paddr = cpu_get_phys_page_debug(env, vaddr); uint32_t page_left = TARGET_PAGE_SIZE - (vaddr & (TARGET_PAGE_SIZE - 1)); uint32_t io_sz = page_left < len ? page_left : len; - target_phys_addr_t sz = io_sz; + hwaddr sz = io_sz; void *buf = cpu_physical_memory_map(paddr, &sz, is_write); if (buf) { @@ -295,7 +295,7 @@ void HELPER(simcall)(CPUXtensaState *env) uint32_t sz = regs[5]; while (sz) { - target_phys_addr_t len = sz; + hwaddr len = sz; void *buf = cpu_physical_memory_map(base, &len, 1); if (buf && len) { diff --git a/targphys.h b/targphys.h deleted file mode 100644 index 50911fd12f..0000000000 --- a/targphys.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Define target_phys_addr_t if it exists. */ - -#ifndef TARGPHYS_H -#define TARGPHYS_H - -#ifndef CONFIG_USER_ONLY - -#define TARGET_PHYS_ADDR_BITS 64 -/* target_phys_addr_t is the type of a physical address (its size can - be different from 'target_ulong'). */ - -typedef uint64_t target_phys_addr_t; -#define TARGET_PHYS_ADDR_MAX UINT64_MAX -#define TARGET_FMT_plx "%016" PRIx64 -#define TARGET_PRIdPHYS PRId64 -#define TARGET_PRIiPHYS PRIi64 -#define TARGET_PRIoPHYS PRIo64 -#define TARGET_PRIuPHYS PRIu64 -#define TARGET_PRIxPHYS PRIx64 -#define TARGET_PRIXPHYS PRIX64 - -#endif - -#endif diff --git a/xen-all.c b/xen-all.c index 9d1e168826..046cc2ac37 100644 --- a/xen-all.c +++ b/xen-all.c @@ -68,10 +68,10 @@ static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu) #define BUFFER_IO_MAX_DELAY 100 typedef struct XenPhysmap { - target_phys_addr_t start_addr; + hwaddr start_addr; ram_addr_t size; char *name; - target_phys_addr_t phys_offset; + hwaddr phys_offset; QLIST_ENTRY(XenPhysmap) list; } XenPhysmap; @@ -92,7 +92,7 @@ typedef struct XenIOState { struct xs_handle *xenstore; MemoryListener memory_listener; QLIST_HEAD(, XenPhysmap) physmap; - target_phys_addr_t free_phys_offset; + hwaddr free_phys_offset; const XenPhysmap *log_for_dirtybit; Notifier exit; @@ -231,7 +231,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr) } static XenPhysmap *get_physmapping(XenIOState *state, - target_phys_addr_t start_addr, ram_addr_t size) + hwaddr start_addr, ram_addr_t size) { XenPhysmap *physmap = NULL; @@ -245,10 +245,10 @@ static XenPhysmap *get_physmapping(XenIOState *state, return NULL; } -static target_phys_addr_t xen_phys_offset_to_gaddr(target_phys_addr_t start_addr, +static hwaddr xen_phys_offset_to_gaddr(hwaddr start_addr, ram_addr_t size, void *opaque) { - target_phys_addr_t addr = start_addr & TARGET_PAGE_MASK; + hwaddr addr = start_addr & TARGET_PAGE_MASK; XenIOState *xen_io_state = opaque; XenPhysmap *physmap = NULL; @@ -263,16 +263,16 @@ static target_phys_addr_t xen_phys_offset_to_gaddr(target_phys_addr_t start_addr #if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 340 static int xen_add_to_physmap(XenIOState *state, - target_phys_addr_t start_addr, + hwaddr start_addr, ram_addr_t size, MemoryRegion *mr, - target_phys_addr_t offset_within_region) + hwaddr offset_within_region) { unsigned long i = 0; int rc = 0; XenPhysmap *physmap = NULL; - target_phys_addr_t pfn, start_gpfn; - target_phys_addr_t phys_offset = memory_region_get_ram_addr(mr); + hwaddr pfn, start_gpfn; + hwaddr phys_offset = memory_region_get_ram_addr(mr); char path[80], value[17]; if (get_physmapping(state, start_addr, size)) { @@ -349,13 +349,13 @@ go_physmap: } static int xen_remove_from_physmap(XenIOState *state, - target_phys_addr_t start_addr, + hwaddr start_addr, ram_addr_t size) { unsigned long i = 0; int rc = 0; XenPhysmap *physmap = NULL; - target_phys_addr_t phys_offset = 0; + hwaddr phys_offset = 0; physmap = get_physmapping(state, start_addr, size); if (physmap == NULL) { @@ -394,16 +394,16 @@ static int xen_remove_from_physmap(XenIOState *state, #else static int xen_add_to_physmap(XenIOState *state, - target_phys_addr_t start_addr, + hwaddr start_addr, ram_addr_t size, MemoryRegion *mr, - target_phys_addr_t offset_within_region) + hwaddr offset_within_region) { return -ENOSYS; } static int xen_remove_from_physmap(XenIOState *state, - target_phys_addr_t start_addr, + hwaddr start_addr, ram_addr_t size) { return -ENOSYS; @@ -415,7 +415,7 @@ static void xen_set_memory(struct MemoryListener *listener, bool add) { XenIOState *state = container_of(listener, XenIOState, memory_listener); - target_phys_addr_t start_addr = section->offset_within_address_space; + hwaddr start_addr = section->offset_within_address_space; ram_addr_t size = section->size; bool log_dirty = memory_region_is_logging(section->mr); hvmmem_type_t mem_type; @@ -467,10 +467,10 @@ static void xen_region_del(MemoryListener *listener, } static void xen_sync_dirty_bitmap(XenIOState *state, - target_phys_addr_t start_addr, + hwaddr start_addr, ram_addr_t size) { - target_phys_addr_t npages = size >> TARGET_PAGE_BITS; + hwaddr npages = size >> TARGET_PAGE_BITS; const int width = sizeof(unsigned long) * 8; unsigned long bitmap[(npages + width - 1) / width]; int rc, i, j; diff --git a/xen-mapcache.c b/xen-mapcache.c index 9cd6db3d7b..31c06dc950 100644 --- a/xen-mapcache.c +++ b/xen-mapcache.c @@ -53,18 +53,18 @@ #define mapcache_unlock() ((void)0) typedef struct MapCacheEntry { - target_phys_addr_t paddr_index; + hwaddr paddr_index; uint8_t *vaddr_base; unsigned long *valid_mapping; uint8_t lock; - target_phys_addr_t size; + hwaddr size; struct MapCacheEntry *next; } MapCacheEntry; typedef struct MapCacheRev { uint8_t *vaddr_req; - target_phys_addr_t paddr_index; - target_phys_addr_t size; + hwaddr paddr_index; + hwaddr size; QTAILQ_ENTRY(MapCacheRev) next; } MapCacheRev; @@ -74,7 +74,7 @@ typedef struct MapCache { QTAILQ_HEAD(map_cache_head, MapCacheRev) locked_entries; /* For most cases (>99.9%), the page address is the same. */ - target_phys_addr_t last_address_index; + hwaddr last_address_index; uint8_t *last_address_vaddr; unsigned long max_mcache_size; unsigned int mcache_bucket_shift; @@ -142,14 +142,14 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque) } static void xen_remap_bucket(MapCacheEntry *entry, - target_phys_addr_t size, - target_phys_addr_t address_index) + hwaddr size, + hwaddr address_index) { uint8_t *vaddr_base; xen_pfn_t *pfns; int *err; unsigned int i; - target_phys_addr_t nb_pfn = size >> XC_PAGE_SHIFT; + hwaddr nb_pfn = size >> XC_PAGE_SHIFT; trace_xen_remap_bucket(address_index); @@ -195,13 +195,13 @@ static void xen_remap_bucket(MapCacheEntry *entry, g_free(err); } -uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, +uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size, uint8_t lock) { MapCacheEntry *entry, *pentry = NULL; - target_phys_addr_t address_index; - target_phys_addr_t address_offset; - target_phys_addr_t __size = size; + hwaddr address_index; + hwaddr address_offset; + hwaddr __size = size; bool translated = false; tryagain: @@ -278,8 +278,8 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr) { MapCacheEntry *entry = NULL; MapCacheRev *reventry; - target_phys_addr_t paddr_index; - target_phys_addr_t size; + hwaddr paddr_index; + hwaddr size; int found = 0; QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) { @@ -316,8 +316,8 @@ void xen_invalidate_map_cache_entry(uint8_t *buffer) { MapCacheEntry *entry = NULL, *pentry = NULL; MapCacheRev *reventry; - target_phys_addr_t paddr_index; - target_phys_addr_t size; + hwaddr paddr_index; + hwaddr size; int found = 0; QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) { diff --git a/xen-mapcache.h b/xen-mapcache.h index 70301a57e4..c59804060b 100644 --- a/xen-mapcache.h +++ b/xen-mapcache.h @@ -11,14 +11,14 @@ #include -typedef target_phys_addr_t (*phys_offset_to_gaddr_t)(target_phys_addr_t start_addr, +typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr start_addr, ram_addr_t size, void *opaque); #ifdef CONFIG_XEN void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque); -uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, +uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size, uint8_t lock); ram_addr_t xen_ram_addr_from_mapcache(void *ptr); void xen_invalidate_map_cache_entry(uint8_t *buffer); @@ -31,8 +31,8 @@ static inline void xen_map_cache_init(phys_offset_to_gaddr_t f, { } -static inline uint8_t *xen_map_cache(target_phys_addr_t phys_addr, - target_phys_addr_t size, +static inline uint8_t *xen_map_cache(hwaddr phys_addr, + hwaddr size, uint8_t lock) { abort(); From 69758c22e0814f77c7a286ce65a68270ce71284e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 19 Sep 2012 15:11:05 +0200 Subject: [PATCH 1078/2270] build: add QAPI files to the tools We need them because qemu-sockets will soon be using SocketAddress. Acked-by: Luiz Capitulino Signed-off-by: Paolo Bonzini --- Makefile | 3 +-- Makefile.objs | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 88285a474b..9f599bc255 100644 --- a/Makefile +++ b/Makefile @@ -164,8 +164,7 @@ tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \ iohandler.o cutils.o iov.o async.o tools-obj-$(CONFIG_POSIX) += compatfd.o -qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y) $(qapi-obj-y) \ - qapi-visit.o qapi-types.o +qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y) qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y) qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y) diff --git a/Makefile.objs b/Makefile.objs index 74b35422ce..3f16d67dac 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -48,6 +48,7 @@ block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y) block-obj-$(CONFIG_POSIX) += posix-aio-compat.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o block-obj-y += block/ +block-obj-y += $(qapi-obj-y) qapi-types.o qapi-visit.o ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy) # Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add. @@ -239,9 +240,9 @@ QEMU_CFLAGS+=$(GLIB_CFLAGS) nested-vars += \ qga-obj-y \ - block-obj-y \ qom-obj-y \ qapi-obj-y \ + block-obj-y \ user-obj-y \ common-obj-y \ extra-obj-y From 5be8c759f008947514fbf7d8df9a30eebe496b6d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 19 Sep 2012 14:03:35 +0200 Subject: [PATCH 1079/2270] qapi: add socket address types Acked-by: Luiz Capitulino Signed-off-by: Paolo Bonzini --- qapi-schema.json | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/qapi-schema.json b/qapi-schema.json index c615ee212d..8468567bfb 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2518,6 +2518,59 @@ 'id': 'str', 'opts': 'NetClientOptions' } } +## +# @InetSocketAddress +# +# Captures a socket address or address range in the Internet namespace. +# +# @host: host part of the address +# +# @port: port part of the address, or lowest port if @to is present +# +# @to: highest port to try +# +# @ipv4: whether to accept IPv4 addresses, default try both IPv4 and IPv6 +# #optional +# +# @ipv6: whether to accept IPv6 addresses, default try both IPv4 and IPv6 +# #optional +# +# Since 1.3 +## +{ 'type': 'InetSocketAddress', + 'data': { + 'host': 'str', + 'port': 'str', + '*to': 'uint16', + '*ipv4': 'bool', + '*ipv6': 'bool' } } + +## +# @UnixSocketAddress +# +# Captures a socket address in the local ("Unix socket") namespace. +# +# @path: filesystem path to use +# +# Since 1.3 +## +{ 'type': 'UnixSocketAddress', + 'data': { + 'path': 'str' } } + +## +# @SocketAddress +# +# Captures the address of a socket, which could also be a named file descriptor +# +# Since 1.3 +## +{ 'union': 'SocketAddress', + 'data': { + 'inet': 'InetSocketAddress', + 'unix': 'UnixSocketAddress', + 'fd': 'String' } } + ## # @getfd: # From 879e45c72da1569e07fbbc6a1aa2a708ea796044 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 19 Sep 2012 13:51:46 +0200 Subject: [PATCH 1080/2270] qemu-sockets: return InetSocketAddress from inet_parse Reviewed-by: Luiz Capitulino Signed-off-by: Paolo Bonzini --- qemu-sockets.c | 121 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 79 insertions(+), 42 deletions(-) diff --git a/qemu-sockets.c b/qemu-sockets.c index daff8e6a39..909c65f3fb 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -480,54 +480,91 @@ err: } /* compatibility wrapper */ -static void inet_parse(QemuOpts *opts, const char *str, Error **errp) +static InetSocketAddress *inet_parse(const char *str, Error **errp) { + InetSocketAddress *addr; const char *optstr, *h; - char addr[64]; + char host[64]; char port[33]; + int to; int pos; + addr = g_new0(InetSocketAddress, 1); + /* parse address */ if (str[0] == ':') { /* no host given */ - addr[0] = '\0'; - if (1 != sscanf(str,":%32[^,]%n",port,&pos)) { + host[0] = '\0'; + if (1 != sscanf(str, ":%32[^,]%n", port, &pos)) { error_setg(errp, "error parsing port in address '%s'", str); - return; + goto fail; } } else if (str[0] == '[') { /* IPv6 addr */ - if (2 != sscanf(str,"[%64[^]]]:%32[^,]%n",addr,port,&pos)) { + if (2 != sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, &pos)) { error_setg(errp, "error parsing IPv6 address '%s'", str); - return; + goto fail; } - qemu_opt_set(opts, "ipv6", "on"); + addr->ipv6 = addr->has_ipv6 = true; } else if (qemu_isdigit(str[0])) { /* IPv4 addr */ - if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) { + if (2 != sscanf(str, "%64[0-9.]:%32[^,]%n", host, port, &pos)) { error_setg(errp, "error parsing IPv4 address '%s'", str); - return; + goto fail; } - qemu_opt_set(opts, "ipv4", "on"); + addr->ipv4 = addr->has_ipv4 = true; } else { /* hostname */ - if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) { + if (2 != sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos)) { error_setg(errp, "error parsing address '%s'", str); - return; + goto fail; } } - qemu_opt_set(opts, "host", addr); - qemu_opt_set(opts, "port", port); + + addr->host = g_strdup(host); + addr->port = g_strdup(port); /* parse options */ optstr = str + pos; h = strstr(optstr, ",to="); - if (h) - qemu_opt_set(opts, "to", h+4); - if (strstr(optstr, ",ipv4")) - qemu_opt_set(opts, "ipv4", "on"); - if (strstr(optstr, ",ipv6")) - qemu_opt_set(opts, "ipv6", "on"); + if (h) { + if (1 != sscanf(str, "%d%n", &to, &pos) || + (str[pos] != '\0' && str[pos] != ',')) { + error_setg(errp, "error parsing to= argument"); + goto fail; + } + addr->has_to = true; + addr->to = to; + } + if (strstr(optstr, ",ipv4")) { + addr->ipv4 = addr->has_ipv4 = true; + } + if (strstr(optstr, ",ipv6")) { + addr->ipv6 = addr->has_ipv6 = true; + } + return addr; + +fail: + qapi_free_InetSocketAddress(addr); + return NULL; +} + +static void inet_addr_to_opts(QemuOpts *opts, InetSocketAddress *addr) +{ + bool ipv4 = addr->ipv4 || !addr->has_ipv4; + bool ipv6 = addr->ipv6 || !addr->has_ipv6; + + if (!ipv4 || !ipv6) { + qemu_opt_set_bool(opts, "ipv4", ipv4); + qemu_opt_set_bool(opts, "ipv6", ipv6); + } + if (addr->has_to) { + char to[20]; + snprintf(to, sizeof(to), "%d", addr->to); + qemu_opt_set(opts, "to", to); + } + qemu_opt_set(opts, "host", addr->host); + qemu_opt_set(opts, "port", addr->port); } int inet_listen(const char *str, char *ostr, int olen, @@ -536,11 +573,13 @@ int inet_listen(const char *str, char *ostr, int olen, QemuOpts *opts; char *optstr; int sock = -1; - Error *local_err = NULL; + InetSocketAddress *addr; - opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); - inet_parse(opts, str, &local_err); - if (local_err == NULL) { + addr = inet_parse(str, errp); + if (addr != NULL) { + opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); + inet_addr_to_opts(opts, addr); + qapi_free_InetSocketAddress(addr); sock = inet_listen_opts(opts, port_offset, errp); if (sock != -1 && ostr) { optstr = strchr(str, ','); @@ -556,10 +595,8 @@ int inet_listen(const char *str, char *ostr, int olen, optstr ? optstr : ""); } } - } else { - error_propagate(errp, local_err); + qemu_opts_del(opts); } - qemu_opts_del(opts); return sock; } @@ -575,16 +612,16 @@ int inet_connect(const char *str, Error **errp) { QemuOpts *opts; int sock = -1; - Error *local_err = NULL; + InetSocketAddress *addr; - opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); - inet_parse(opts, str, &local_err); - if (local_err == NULL) { + addr = inet_parse(str, errp); + if (addr != NULL) { + opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); + inet_addr_to_opts(opts, addr); + qapi_free_InetSocketAddress(addr); sock = inet_connect_opts(opts, errp, NULL, NULL); - } else { - error_propagate(errp, local_err); + qemu_opts_del(opts); } - qemu_opts_del(opts); return sock; } @@ -607,18 +644,18 @@ int inet_nonblocking_connect(const char *str, { QemuOpts *opts; int sock = -1; - Error *local_err = NULL; + InetSocketAddress *addr; g_assert(callback != NULL); - opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); - inet_parse(opts, str, &local_err); - if (local_err == NULL) { + addr = inet_parse(str, errp); + if (addr != NULL) { + opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); + inet_addr_to_opts(opts, addr); + qapi_free_InetSocketAddress(addr); sock = inet_connect_opts(opts, errp, callback, opaque); - } else { - error_propagate(errp, local_err); + qemu_opts_del(opts); } - qemu_opts_del(opts); return sock; } From 0ef3dd6c2de1fa4f80c5aa71fb5fdada0f35cc9a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 23 Oct 2012 22:36:08 +0200 Subject: [PATCH 1081/2270] tests: do not include tools-obj-y Signed-off-by: Paolo Bonzini --- tests/Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 26a67ce6f5..86c9b79ebe 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -42,11 +42,11 @@ test-qapi-obj-y += module.o $(test-obj-y): QEMU_INCLUDES += -Itests -tests/check-qint$(EXESUF): tests/check-qint.o qint.o $(tools-obj-y) -tests/check-qstring$(EXESUF): tests/check-qstring.o qstring.o $(tools-obj-y) -tests/check-qdict$(EXESUF): tests/check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(tools-obj-y) -tests/check-qlist$(EXESUF): tests/check-qlist.o qlist.o qint.o $(tools-obj-y) -tests/check-qfloat$(EXESUF): tests/check-qfloat.o qfloat.o $(tools-obj-y) +tests/check-qint$(EXESUF): tests/check-qint.o qint.o +tests/check-qstring$(EXESUF): tests/check-qstring.o qstring.o +tests/check-qdict$(EXESUF): tests/check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o +tests/check-qlist$(EXESUF): tests/check-qlist.o qlist.o qint.o +tests/check-qfloat$(EXESUF): tests/check-qfloat.o qfloat.o tests/check-qjson$(EXESUF): tests/check-qjson.o $(qobject-obj-y) $(tools-obj-y) tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y) tests/test-iov$(EXESUF): tests/test-iov.o iov.o From 101f9cbc2b73340197ec610c095fd69f0b1413ed Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 23 Oct 2012 21:31:53 +0200 Subject: [PATCH 1082/2270] qemu-sockets: add socket_listen, socket_connect, socket_parse These are QAPI-friendly versions of the qemu-sockets functions. They support IP sockets, Unix sockets, and named file descriptors, using a QAPI union to dispatch to the correct function. Reviewed-by: Luiz Capitulino Signed-off-by: Paolo Bonzini --- Makefile | 2 +- qemu-sockets.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-tool.c | 6 +++ qemu_socket.h | 5 +++ 4 files changed, 111 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9f599bc255..17e2d58ce5 100644 --- a/Makefile +++ b/Makefile @@ -161,7 +161,7 @@ qemu-img.o: qemu-img-cmds.h tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \ qemu-timer-common.o main-loop.o notify.o \ - iohandler.o cutils.o iov.o async.o + iohandler.o cutils.o iov.o async.o error.o tools-obj-$(CONFIG_POSIX) += compatfd.o qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y) diff --git a/qemu-sockets.c b/qemu-sockets.c index 909c65f3fb..cfed9c5a5b 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -22,6 +22,7 @@ #include #include +#include "monitor.h" #include "qemu_socket.h" #include "qemu-common.h" /* for qemu_isdigit */ #include "main-loop.h" @@ -845,6 +846,104 @@ int unix_nonblocking_connect(const char *path, return sock; } +SocketAddress *socket_parse(const char *str, Error **errp) +{ + SocketAddress *addr = NULL; + + addr = g_new(SocketAddress, 1); + if (strstart(str, "unix:", NULL)) { + if (str[5] == '\0') { + error_setg(errp, "invalid Unix socket address\n"); + goto fail; + } else { + addr->kind = SOCKET_ADDRESS_KIND_UNIX; + addr->q_unix = g_new(UnixSocketAddress, 1); + addr->q_unix->path = g_strdup(str + 5); + } + } else if (strstart(str, "fd:", NULL)) { + if (str[3] == '\0') { + error_setg(errp, "invalid file descriptor address\n"); + goto fail; + } else { + addr->kind = SOCKET_ADDRESS_KIND_FD; + addr->fd = g_new(String, 1); + addr->fd->str = g_strdup(str + 3); + } + } else { + addr->kind = SOCKET_ADDRESS_KIND_INET; + addr->inet = g_new(InetSocketAddress, 1); + addr->inet = inet_parse(str, errp); + if (addr->inet == NULL) { + goto fail; + } + } + return addr; + +fail: + qapi_free_SocketAddress(addr); + return NULL; +} + +int socket_connect(SocketAddress *addr, Error **errp, + NonBlockingConnectHandler *callback, void *opaque) +{ + QemuOpts *opts; + int fd; + + opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); + switch (addr->kind) { + case SOCKET_ADDRESS_KIND_INET: + inet_addr_to_opts(opts, addr->inet); + fd = inet_connect_opts(opts, errp, callback, opaque); + break; + + case SOCKET_ADDRESS_KIND_UNIX: + qemu_opt_set(opts, "path", addr->q_unix->path); + fd = unix_connect_opts(opts, errp, callback, opaque); + break; + + case SOCKET_ADDRESS_KIND_FD: + fd = monitor_get_fd(cur_mon, addr->fd->str, errp); + if (callback) { + callback(fd, opaque); + } + break; + + default: + abort(); + } + qemu_opts_del(opts); + return fd; +} + +int socket_listen(SocketAddress *addr, Error **errp) +{ + QemuOpts *opts; + int fd; + + opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); + switch (addr->kind) { + case SOCKET_ADDRESS_KIND_INET: + inet_addr_to_opts(opts, addr->inet); + fd = inet_listen_opts(opts, 0, errp); + break; + + case SOCKET_ADDRESS_KIND_UNIX: + qemu_opt_set(opts, "path", addr->q_unix->path); + fd = unix_listen_opts(opts, errp); + break; + + case SOCKET_ADDRESS_KIND_FD: + fd = monitor_get_fd(cur_mon, addr->fd->str, errp); + break; + + default: + abort(); + } + qemu_opts_del(opts); + return fd; +} + #ifdef _WIN32 static void socket_cleanup(void) { diff --git a/qemu-tool.c b/qemu-tool.c index f2f98138ce..da4c05aaf7 100644 --- a/qemu-tool.c +++ b/qemu-tool.c @@ -38,6 +38,12 @@ const char *qemu_get_vm_name(void) Monitor *cur_mon; +int monitor_get_fd(Monitor *mon, const char *name, Error **errp) +{ + error_setg(errp, "only QEMU supports file descriptor passing"); + return -1; +} + void vm_stop(RunState state) { abort(); diff --git a/qemu_socket.h b/qemu_socket.h index 89a5feb7ec..02490ad06c 100644 --- a/qemu_socket.h +++ b/qemu_socket.h @@ -65,6 +65,11 @@ int unix_nonblocking_connect(const char *str, NonBlockingConnectHandler *callback, void *opaque, Error **errp); +SocketAddress *socket_parse(const char *str, Error **errp); +int socket_connect(SocketAddress *addr, Error **errp, + NonBlockingConnectHandler *callback, void *opaque); +int socket_listen(SocketAddress *addr, Error **errp); + /* Old, ipv4 only bits. Don't use for new code. */ int parse_host_port(struct sockaddr_in *saddr, const char *str); int socket_init(void); From 3cbc002c34aa85ea952ee9b169a3ff97d350516a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 19 Oct 2012 11:36:48 +0200 Subject: [PATCH 1083/2270] block: prepare code for adding block notifiers There is no reason in principle to skip job cancellation and draining of pending I/O when there is no medium in the disk. Do these unconditionally, which also prepares the code for the next patch. Signed-off-by: Paolo Bonzini --- block.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/block.c b/block.c index e95f613aa4..2e4ddea222 100644 --- a/block.c +++ b/block.c @@ -1098,12 +1098,12 @@ void bdrv_reopen_abort(BDRVReopenState *reopen_state) void bdrv_close(BlockDriverState *bs) { bdrv_flush(bs); - if (bs->drv) { - if (bs->job) { - block_job_cancel_sync(bs->job); - } - bdrv_drain_all(); + if (bs->job) { + block_job_cancel_sync(bs->job); + } + bdrv_drain_all(); + if (bs->drv) { if (bs == bs_snapshots) { bs_snapshots = NULL; } From d7d512f60979681c27597f1b1277e03505c1de08 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 23 Aug 2012 11:20:36 +0200 Subject: [PATCH 1084/2270] block: add close notifiers The first user of close notifiers will be the embedded NBD server. It would be possible to use them to do some of the ad hoc processing (e.g. for block jobs and I/O limits) that is currently done by bdrv_close. Acked-by: Kevin Wolf Signed-off-by: Paolo Bonzini --- Makefile.objs | 4 ++-- block.c | 9 +++++++++ block.h | 1 + block_int.h | 2 ++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Makefile.objs b/Makefile.objs index 3f16d67dac..ca67885778 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -43,7 +43,7 @@ coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o block-obj-y = cutils.o iov.o cache-utils.o qemu-option.o module.o async.o block-obj-y += nbd.o block.o blockjob.o aio.o aes.o qemu-config.o -block-obj-y += qemu-progress.o qemu-sockets.o uri.o +block-obj-y += qemu-progress.o qemu-sockets.o uri.o notify.o block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y) block-obj-$(CONFIG_POSIX) += posix-aio-compat.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o @@ -94,7 +94,7 @@ common-obj-y += bt-host.o bt-vhci.o common-obj-y += dma-helpers.o common-obj-y += iov.o acl.o common-obj-$(CONFIG_POSIX) += compatfd.o -common-obj-y += notify.o event_notifier.o +common-obj-y += event_notifier.o common-obj-y += qemu-timer.o qemu-timer-common.o common-obj-y += qtest.o common-obj-y += vl.o diff --git a/block.c b/block.c index 2e4ddea222..56426a936a 100644 --- a/block.c +++ b/block.c @@ -30,6 +30,7 @@ #include "module.h" #include "qjson.h" #include "sysemu.h" +#include "notify.h" #include "qemu-coroutine.h" #include "qmp-commands.h" #include "qemu-timer.h" @@ -312,9 +313,16 @@ BlockDriverState *bdrv_new(const char *device_name) QTAILQ_INSERT_TAIL(&bdrv_states, bs, list); } bdrv_iostatus_disable(bs); + notifier_list_init(&bs->close_notifiers); + return bs; } +void bdrv_add_close_notifier(BlockDriverState *bs, Notifier *notify) +{ + notifier_list_add(&bs->close_notifiers, notify); +} + BlockDriver *bdrv_find_format(const char *format_name) { BlockDriver *drv1; @@ -1102,6 +1110,7 @@ void bdrv_close(BlockDriverState *bs) block_job_cancel_sync(bs->job); } bdrv_drain_all(); + notifier_list_notify(&bs->close_notifiers, bs); if (bs->drv) { if (bs == bs_snapshots) { diff --git a/block.h b/block.h index e2d89d7bc1..aa608a8c99 100644 --- a/block.h +++ b/block.h @@ -144,6 +144,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, void bdrv_reopen_commit(BDRVReopenState *reopen_state); void bdrv_reopen_abort(BDRVReopenState *reopen_state); void bdrv_close(BlockDriverState *bs); +void bdrv_add_close_notifier(BlockDriverState *bs, Notifier *notify); int bdrv_attach_dev(BlockDriverState *bs, void *dev); void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev); void bdrv_detach_dev(BlockDriverState *bs, void *dev); diff --git a/block_int.h b/block_int.h index f4bae04401..cedabbdd13 100644 --- a/block_int.h +++ b/block_int.h @@ -233,6 +233,8 @@ struct BlockDriverState { BlockDriverState *backing_hd; BlockDriverState *file; + NotifierList close_notifiers; + /* number of in-flight copy-on-read requests */ unsigned int copy_on_read_in_flight; From 6dd844db4a49a367cc15cd0e8bfb72cfc6652766 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 22 Aug 2012 16:43:07 +0200 Subject: [PATCH 1085/2270] qmp: add NBD server commands Adding an NBD server inside QEMU is trivial, since all the logic is in nbd.c and can be shared easily between qemu-nbd and QEMU itself. The main difference is that qemu-nbd serves a single unnamed export, while QEMU serves named exports. Acked-by: Luiz Capitulino Signed-off-by: Paolo Bonzini --- Makefile.objs | 2 +- blockdev-nbd.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++ qapi-schema.json | 43 +++++++++++++++++ qmp-commands.hx | 16 +++++++ 4 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 blockdev-nbd.c diff --git a/Makefile.objs b/Makefile.objs index ca67885778..9eca179903 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -61,7 +61,7 @@ endif # suppress *all* target specific code in case of system emulation, i.e. a # single QEMU executable should support all CPUs and machines. -common-obj-y = $(block-obj-y) blockdev.o block/ +common-obj-y = $(block-obj-y) blockdev.o blockdev-nbd.o block/ common-obj-y += net.o net/ common-obj-y += qom/ common-obj-y += readline.o console.o cursor.o diff --git a/blockdev-nbd.c b/blockdev-nbd.c new file mode 100644 index 0000000000..8031813071 --- /dev/null +++ b/blockdev-nbd.c @@ -0,0 +1,119 @@ +/* + * Serving QEMU block devices via NBD + * + * Copyright (c) 2012 Red Hat, Inc. + * + * Author: Paolo Bonzini + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later. See the COPYING file in the top-level directory. + */ + +#include "blockdev.h" +#include "hw/block-common.h" +#include "monitor.h" +#include "qerror.h" +#include "sysemu.h" +#include "qmp-commands.h" +#include "trace.h" +#include "nbd.h" +#include "qemu_socket.h" + +static int server_fd = -1; + +static void nbd_accept(void *opaque) +{ + struct sockaddr_in addr; + socklen_t addr_len = sizeof(addr); + + int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len); + if (fd >= 0) { + nbd_client_new(NULL, fd, nbd_client_put); + } +} + +void qmp_nbd_server_start(SocketAddress *addr, Error **errp) +{ + if (server_fd != -1) { + error_setg(errp, "NBD server already running"); + return; + } + + server_fd = socket_listen(addr, errp); + if (server_fd != -1) { + qemu_set_fd_handler2(server_fd, NULL, nbd_accept, NULL, NULL); + } +} + +/* Hook into the BlockDriverState notifiers to close the export when + * the file is closed. + */ +typedef struct NBDCloseNotifier { + Notifier n; + NBDExport *exp; + QTAILQ_ENTRY(NBDCloseNotifier) next; +} NBDCloseNotifier; + +static QTAILQ_HEAD(, NBDCloseNotifier) close_notifiers = + QTAILQ_HEAD_INITIALIZER(close_notifiers); + +static void nbd_close_notifier(Notifier *n, void *data) +{ + NBDCloseNotifier *cn = DO_UPCAST(NBDCloseNotifier, n, n); + + notifier_remove(&cn->n); + QTAILQ_REMOVE(&close_notifiers, cn, next); + + nbd_export_close(cn->exp); + nbd_export_put(cn->exp); + g_free(cn); +} + +static void nbd_server_put_ref(NBDExport *exp) +{ + BlockDriverState *bs = nbd_export_get_blockdev(exp); + drive_put_ref(drive_get_by_blockdev(bs)); +} + +void qmp_nbd_server_add(const char *device, bool has_writable, bool writable, + Error **errp) +{ + BlockDriverState *bs; + NBDExport *exp; + NBDCloseNotifier *n; + + if (nbd_export_find(device)) { + error_setg(errp, "NBD server already exporting device '%s'", device); + return; + } + + bs = bdrv_find(device); + if (!bs) { + error_set(errp, QERR_DEVICE_NOT_FOUND, device); + return; + } + + exp = nbd_export_new(bs, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY, + nbd_server_put_ref); + + nbd_export_set_name(exp, device); + drive_get_ref(drive_get_by_blockdev(bs)); + + n = g_malloc0(sizeof(NBDCloseNotifier)); + n->n.notify = nbd_close_notifier; + n->exp = exp; + bdrv_add_close_notifier(bs, &n->n); + QTAILQ_INSERT_TAIL(&close_notifiers, n, next); +} + +void qmp_nbd_server_stop(Error **errp) +{ + while (!QTAILQ_EMPTY(&close_notifiers)) { + NBDCloseNotifier *cn = QTAILQ_FIRST(&close_notifiers); + nbd_close_notifier(&cn->n, nbd_export_get_blockdev(cn->exp)); + } + + qemu_set_fd_handler2(server_fd, NULL, NULL, NULL, NULL); + close(server_fd); + server_fd = -1; +} diff --git a/qapi-schema.json b/qapi-schema.json index 8468567bfb..6fd263e646 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2863,3 +2863,46 @@ # Since: 0.14.0 ## { 'command': 'screendump', 'data': {'filename': 'str'} } + +## +# @nbd-server-start: +# +# Start an NBD server listening on the given host and port. Block +# devices can then be exported using @nbd-server-add. The NBD +# server will present them as named exports; for example, another +# QEMU instance could refer to them as "nbd:HOST:PORT:exportname=NAME". +# +# @addr: Address on which to listen. +# +# Returns: error if the server is already running. +# +# Since: 1.3.0 +## +{ 'command': 'nbd-server-start', + 'data': { 'addr': 'SocketAddress' } } + +## +# @nbd-server-add: +# +# Export a device to QEMU's embedded NBD server. +# +# @device: Block device to be exported +# +# @writable: Whether clients should be able to write to the device via the +# NBD connection (default false). #optional +# +# Returns: error if the device is already marked for export. +# +# Since: 1.3.0 +## +{ 'command': 'nbd-server-add', 'data': {'device': 'str', '*writable': 'bool'} } + +## +# @nbd-server-stop: +# +# Stop QEMU's embedded NBD server, and unregister all devices previously +# added via @nbd-server-add. +# +# Since: 1.3.0 +## +{ 'command': 'nbd-server-stop' } diff --git a/qmp-commands.hx b/qmp-commands.hx index 5ba8c48cb4..ebe9a78ca9 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -2551,6 +2551,22 @@ EQMP .mhandler.cmd_new = qmp_qom_get, }, + { + .name = "nbd-server-start", + .args_type = "addr:q", + .mhandler.cmd_new = qmp_marshal_input_nbd_server_start, + }, + { + .name = "nbd-server-add", + .args_type = "device:B,writable:b?", + .mhandler.cmd_new = qmp_marshal_input_nbd_server_add, + }, + { + .name = "nbd-server-stop", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_nbd_server_stop, + }, + { .name = "change-vnc-password", .args_type = "password:s", From 1f71049523f4fc0738f96c74bfcce012521fa0f0 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 12 Oct 2012 14:29:18 +0200 Subject: [PATCH 1086/2270] qemu-img: Fix division by zero for zero size images Signed-off-by: Kevin Wolf Reviewed-by: Paolo Bonzini --- qemu-img.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index f17f1872d6..849eb41883 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -674,7 +674,7 @@ static int img_convert(int argc, char **argv) QEMUOptionParameter *out_baseimg_param; char *options = NULL; const char *snapshot_name = NULL; - float local_progress; + float local_progress = 0; int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */ fmt = NULL; @@ -914,8 +914,10 @@ static int img_convert(int argc, char **argv) sector_num = 0; nb_sectors = total_sectors; - local_progress = (float)100 / - (nb_sectors / MIN(nb_sectors, cluster_sectors)); + if (nb_sectors != 0) { + local_progress = (float)100 / + (nb_sectors / MIN(nb_sectors, cluster_sectors)); + } for(;;) { int64_t bs_num; @@ -986,8 +988,10 @@ static int img_convert(int argc, char **argv) sector_num = 0; // total number of sectors converted so far nb_sectors = total_sectors - sector_num; - local_progress = (float)100 / - (nb_sectors / MIN(nb_sectors, IO_BUF_SIZE / 512)); + if (nb_sectors != 0) { + local_progress = (float)100 / + (nb_sectors / MIN(nb_sectors, IO_BUF_SIZE / 512)); + } for(;;) { nb_sectors = total_sectors - sector_num; @@ -1585,7 +1589,7 @@ static int img_rebase(int argc, char **argv) int n; uint8_t * buf_old; uint8_t * buf_new; - float local_progress; + float local_progress = 0; buf_old = qemu_blockalign(bs, IO_BUF_SIZE); buf_new = qemu_blockalign(bs, IO_BUF_SIZE); @@ -1594,8 +1598,11 @@ static int img_rebase(int argc, char **argv) bdrv_get_geometry(bs_old_backing, &old_backing_num_sectors); bdrv_get_geometry(bs_new_backing, &new_backing_num_sectors); - local_progress = (float)100 / - (num_sectors / MIN(num_sectors, IO_BUF_SIZE / 512)); + if (num_sectors != 0) { + local_progress = (float)100 / + (num_sectors / MIN(num_sectors, IO_BUF_SIZE / 512)); + } + for (sector = 0; sector < num_sectors; sector += n) { /* How many sectors can we handle with the next read? */ From ee17f9d5fd44fba950ab2290dd30f38d1cd2b625 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 12 Oct 2012 14:24:42 +0200 Subject: [PATCH 1087/2270] qemu-iotests: Test qemu-img operation on zero size image Signed-off-by: Kevin Wolf Reviewed-by: Paolo Bonzini --- tests/qemu-iotests/042 | 78 ++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/042.out | 15 ++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 94 insertions(+) create mode 100755 tests/qemu-iotests/042 create mode 100644 tests/qemu-iotests/042.out diff --git a/tests/qemu-iotests/042 b/tests/qemu-iotests/042 new file mode 100755 index 0000000000..c3c3ca8d02 --- /dev/null +++ b/tests/qemu-iotests/042 @@ -0,0 +1,78 @@ +#!/bin/bash +# +# Test qemu-img operation on zero size images +# +# Copyright (C) 2012 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 . +# + +# 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 qcow qed vmdk +_supported_proto file +_supported_os Linux + +echo +echo "== Creating zero size image ==" + +_make_test_img 0 +_check_test_img + +mv $TEST_IMG $TEST_IMG.orig + +echo +echo "== Converting the image ==" + +$QEMU_IMG convert -O $IMGFMT $TEST_IMG.orig $TEST_IMG +_check_test_img + +echo +echo "== Converting the image, compressed ==" + +if [ "$IMGFMT" == "qcow2" ]; then + $QEMU_IMG convert -c -O $IMGFMT $TEST_IMG.orig $TEST_IMG +fi +_check_test_img + +echo +echo "== Rebasing the image ==" + +$QEMU_IMG rebase -u -b $TEST_IMG.orig $TEST_IMG +$QEMU_IMG rebase -b $TEST_IMG.orig $TEST_IMG +_check_test_img + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 + diff --git a/tests/qemu-iotests/042.out b/tests/qemu-iotests/042.out new file mode 100644 index 0000000000..dc80f4b5b3 --- /dev/null +++ b/tests/qemu-iotests/042.out @@ -0,0 +1,15 @@ +QA output created by 042 + +== Creating zero size image == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0 +No errors were found on the image. + +== Converting the image == +No errors were found on the image. + +== Converting the image, compressed == +No errors were found on the image. + +== Rebasing the image == +No errors were found on the image. +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 66d2ba9689..d5f9ab0d7d 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -47,3 +47,4 @@ 038 rw auto backing 039 rw auto 040 rw auto +042 rw auto quick From b3d0380ec245d73e5233366f541497ef92b2e283 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Mon, 15 Oct 2012 16:58:02 -0400 Subject: [PATCH 1088/2270] qmp: fix __accept() in qmp.py In QEMUMonitorProtocol, commit e9d17b6 removed the __sockfile creation from __negotiate_capabilities(), which breaks _accept(). This causes failures in qemu-io python based tests (i.e. tests 030 and 040). This patch creates the sockfile in __accept() as well. Signed-off-by: Jeff Cody Reviewed-by: Stefan Hajnoczi Acked-by: Luiz Capitulino Signed-off-by: Kevin Wolf --- QMP/qmp.py | 1 + 1 file changed, 1 insertion(+) diff --git a/QMP/qmp.py b/QMP/qmp.py index 33c7d36d9b..32510a176a 100644 --- a/QMP/qmp.py +++ b/QMP/qmp.py @@ -96,6 +96,7 @@ class QEMUMonitorProtocol: @raise QMPCapabilitiesError if fails to negotiate capabilities """ self.__sock, _ = self.__sock.accept() + self.__sockfile = self.__sock.makefile() return self.__negotiate_capabilities() def cmd_obj(self, qmp_cmd): From a616673dd1c2e00db5e3458d2ba4b6619b78876a Mon Sep 17 00:00:00 2001 From: Alex Bligh Date: Tue, 16 Oct 2012 13:46:18 +0100 Subject: [PATCH 1089/2270] qemu-img rebase: use empty string to rebase without backing file This patch allows an empty filename to be passed as the new base image name for qemu-img rebase to mean base the image on no backing file (i.e. independent of any backing file). According to Eric Blake, qemu-img rebase already supports this when '-u' is used; this adds support when -u is not used. Signed-off-by: Alex Bligh Signed-off-by: Kevin Wolf --- qemu-img.c | 29 +++++++++++++++++++---------- qemu-img.texi | 4 +++- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index 849eb41883..c092ccfbcd 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1562,13 +1562,15 @@ static int img_rebase(int argc, char **argv) error_report("Could not open old backing file '%s'", backing_name); goto out; } - - bs_new_backing = bdrv_new("new_backing"); - ret = bdrv_open(bs_new_backing, out_baseimg, BDRV_O_FLAGS, + if (out_baseimg[0]) { + bs_new_backing = bdrv_new("new_backing"); + ret = bdrv_open(bs_new_backing, out_baseimg, BDRV_O_FLAGS, new_backing_drv); - if (ret) { - error_report("Could not open new backing file '%s'", out_baseimg); - goto out; + if (ret) { + error_report("Could not open new backing file '%s'", + out_baseimg); + goto out; + } } } @@ -1584,7 +1586,7 @@ static int img_rebase(int argc, char **argv) if (!unsafe) { uint64_t num_sectors; uint64_t old_backing_num_sectors; - uint64_t new_backing_num_sectors; + uint64_t new_backing_num_sectors = 0; uint64_t sector; int n; uint8_t * buf_old; @@ -1596,7 +1598,9 @@ static int img_rebase(int argc, char **argv) bdrv_get_geometry(bs, &num_sectors); bdrv_get_geometry(bs_old_backing, &old_backing_num_sectors); - bdrv_get_geometry(bs_new_backing, &new_backing_num_sectors); + if (bs_new_backing) { + bdrv_get_geometry(bs_new_backing, &new_backing_num_sectors); + } if (num_sectors != 0) { local_progress = (float)100 / @@ -1636,7 +1640,7 @@ static int img_rebase(int argc, char **argv) } } - if (sector >= new_backing_num_sectors) { + if (sector >= new_backing_num_sectors || !bs_new_backing) { memset(buf_new, 0, n * BDRV_SECTOR_SIZE); } else { if (sector + n > new_backing_num_sectors) { @@ -1682,7 +1686,12 @@ static int img_rebase(int argc, char **argv) * backing file are overwritten in the COW file now, so the visible content * doesn't change when we switch the backing file. */ - ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt); + if (out_baseimg && *out_baseimg) { + ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt); + } else { + ret = bdrv_change_backing_file(bs, NULL, NULL); + } + if (ret == -ENOSPC) { error_report("Could not change the backing file to '%s': No " "space left in the file header", out_baseimg); diff --git a/qemu-img.texi b/qemu-img.texi index 8b05f2c428..42ec392c36 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -148,7 +148,9 @@ Changes the backing file of an image. Only the formats @code{qcow2} and The backing file is changed to @var{backing_file} and (if the image format of @var{filename} supports this) the backing file format is changed to -@var{backing_fmt}. +@var{backing_fmt}. If @var{backing_file} is specified as ``'' (the empty +string), then the image is rebased onto no backing file (i.e. it will exist +independently of any backing file). There are two different modes in which @code{rebase} can operate: @table @option From b1b1d783eabdb6ac4e4578b2c04b0c24483dce77 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Tue, 16 Oct 2012 15:49:09 -0400 Subject: [PATCH 1090/2270] block: make bdrv_find_backing_image compare canonical filenames Currently, bdrv_find_backing_image compares bs->backing_file with what is passed in as a backing_file name. Mismatches may occur, however, when bs->backing_file and backing_file are not both absolute or relative. Use path_combine() to make sure any relative backing filenames are relative to the current image filename being searched, and then use realpath() to make all comparisons based on absolute filenames. If either backing_file or bs->backing_file is determine to be a protocol, then no filename normalization is performed. This also changes bdrv_find_backing_image to no longer be recursive, but iterative. Signed-off-by: Jeff Cody Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- block.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/block.c b/block.c index e95f613aa4..5e7fc9eb27 100644 --- a/block.c +++ b/block.c @@ -3123,22 +3123,70 @@ int bdrv_snapshot_load_tmp(BlockDriverState *bs, return -ENOTSUP; } +/* backing_file can either be relative, or absolute, or a protocol. If it is + * relative, it must be relative to the chain. So, passing in bs->filename + * from a BDS as backing_file should not be done, as that may be relative to + * the CWD rather than the chain. */ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, const char *backing_file) { - if (!bs->drv) { + char *filename_full = NULL; + char *backing_file_full = NULL; + char *filename_tmp = NULL; + int is_protocol = 0; + BlockDriverState *curr_bs = NULL; + BlockDriverState *retval = NULL; + + if (!bs || !bs->drv || !backing_file) { return NULL; } - if (bs->backing_hd) { - if (strcmp(bs->backing_file, backing_file) == 0) { - return bs->backing_hd; + filename_full = g_malloc(PATH_MAX); + backing_file_full = g_malloc(PATH_MAX); + filename_tmp = g_malloc(PATH_MAX); + + is_protocol = path_has_protocol(backing_file); + + for (curr_bs = bs; curr_bs->backing_hd; curr_bs = curr_bs->backing_hd) { + + /* If either of the filename paths is actually a protocol, then + * compare unmodified paths; otherwise make paths relative */ + if (is_protocol || path_has_protocol(curr_bs->backing_file)) { + if (strcmp(backing_file, curr_bs->backing_file) == 0) { + retval = curr_bs->backing_hd; + break; + } } else { - return bdrv_find_backing_image(bs->backing_hd, backing_file); + /* If not an absolute filename path, make it relative to the current + * image's filename path */ + path_combine(filename_tmp, PATH_MAX, curr_bs->filename, + backing_file); + + /* We are going to compare absolute pathnames */ + if (!realpath(filename_tmp, filename_full)) { + continue; + } + + /* We need to make sure the backing filename we are comparing against + * is relative to the current image filename (or absolute) */ + path_combine(filename_tmp, PATH_MAX, curr_bs->filename, + curr_bs->backing_file); + + if (!realpath(filename_tmp, backing_file_full)) { + continue; + } + + if (strcmp(backing_file_full, filename_full) == 0) { + retval = curr_bs->backing_hd; + break; + } } } - return NULL; + g_free(filename_full); + g_free(backing_file_full); + g_free(filename_tmp); + return retval; } int bdrv_get_backing_file_depth(BlockDriverState *bs) From d5208c45be38ab858db6ec5a5097aa1c1a8ebbc9 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Tue, 16 Oct 2012 15:49:10 -0400 Subject: [PATCH 1091/2270] block: in commit, determine base image from the top image This simplifies some code and error checking, and also fixes a bug. bdrv_find_backing_image() should only be passed absolute filenames, or filenames relative to the chain. In the QMP message handler for block commit, when looking up the base do so from the determined top image, so we know it is reachable from top. Some of the error messages put out by block-commit have changed slightly, which causes 2 tests cases for block-commit to fail. This patch updates the test cases to look for the correct error output. Signed-off-by: Jeff Cody Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- block/commit.c | 9 --------- blockdev.c | 21 +++++++++++---------- tests/qemu-iotests/040 | 4 ++-- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/block/commit.c b/block/commit.c index 733c91403c..13d9e82471 100644 --- a/block/commit.c +++ b/block/commit.c @@ -211,15 +211,6 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base, return; } - /* top and base may be valid, but let's make sure that base is reachable - * from top */ - if (bdrv_find_backing_image(top, base->filename) != base) { - error_setg(errp, - "Base (%s) is not reachable from top (%s)", - base->filename, top->filename); - return; - } - overlay_bs = bdrv_find_overlay(bs, top); if (overlay_bs == NULL) { diff --git a/blockdev.c b/blockdev.c index 99828ad2bd..46e4bbd8d9 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1157,16 +1157,6 @@ void qmp_block_commit(const char *device, error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } - if (base && has_base) { - base_bs = bdrv_find_backing_image(bs, base); - } else { - base_bs = bdrv_find_base(bs); - } - - if (base_bs == NULL) { - error_set(errp, QERR_BASE_NOT_FOUND, base ? base : "NULL"); - return; - } /* default top_bs is the active layer */ top_bs = bs; @@ -1182,6 +1172,17 @@ void qmp_block_commit(const char *device, return; } + if (has_base && base) { + base_bs = bdrv_find_backing_image(top_bs, base); + } else { + base_bs = bdrv_find_base(top_bs); + } + + if (base_bs == NULL) { + error_set(errp, QERR_BASE_NOT_FOUND, base ? base : "NULL"); + return; + } + commit_start(bs, base_bs, top_bs, speed, on_error, block_job_cb, bs, &local_err); if (local_err != NULL) { diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040 index 258e7eae38..0fa6441a53 100755 --- a/tests/qemu-iotests/040 +++ b/tests/qemu-iotests/040 @@ -111,7 +111,7 @@ class TestSingleDrive(ImageCommitTestCase): self.assert_no_active_commit() result = self.vm.qmp('block-commit', device='drive0', top='%s' % backing_img, base='%s' % backing_img) self.assert_qmp(result, 'error/class', 'GenericError') - self.assert_qmp(result, 'error/desc', 'Invalid files for merge: top and base are the same') + self.assert_qmp(result, 'error/desc', 'Base \'%s\' not found' % backing_img) def test_top_invalid(self): self.assert_no_active_commit() @@ -135,7 +135,7 @@ class TestSingleDrive(ImageCommitTestCase): self.assert_no_active_commit() result = self.vm.qmp('block-commit', device='drive0', top='%s' % backing_img, base='%s' % mid_img) self.assert_qmp(result, 'error/class', 'GenericError') - self.assert_qmp(result, 'error/desc', 'Base (%(1)s) is not reachable from top (%(2)s)' % {"1" : mid_img, "2" : backing_img}) + self.assert_qmp(result, 'error/desc', 'Base \'%s\' not found' % mid_img) def test_top_omitted(self): self.assert_no_active_commit() From 6bf0d1f478a5a425c0c024994375592805d591c0 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Tue, 16 Oct 2012 15:49:12 -0400 Subject: [PATCH 1092/2270] qemu-iotests: add relative backing file tests for block-commit (040) The previous block commit used absolute filenames for all block-commit images and commands; this adds relative filenames for the same tests. Signed-off-by: Jeff Cody Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- tests/qemu-iotests/040 | 102 +++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/040.out | 4 +- 2 files changed, 104 insertions(+), 2 deletions(-) diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040 index 0fa6441a53..aad535a74b 100755 --- a/tests/qemu-iotests/040 +++ b/tests/qemu-iotests/040 @@ -26,6 +26,7 @@ import os import iotests from iotests import qemu_img, qemu_io import struct +import errno backing_img = os.path.join(iotests.test_dir, 'backing.img') mid_img = os.path.join(iotests.test_dir, 'mid.img') @@ -143,6 +144,107 @@ class TestSingleDrive(ImageCommitTestCase): self.assert_qmp(result, 'error/class', 'GenericError') self.assert_qmp(result, 'error/desc', "Parameter 'top' is missing") +class TestRelativePaths(ImageCommitTestCase): + image_len = 1 * 1024 * 1024 + test_len = 1 * 1024 * 256 + + dir1 = "dir1" + dir2 = "dir2/" + dir3 = "dir2/dir3/" + + test_img = os.path.join(iotests.test_dir, dir3, 'test.img') + mid_img = "../mid.img" + backing_img = "../dir1/backing.img" + + backing_img_abs = os.path.join(iotests.test_dir, dir1, 'backing.img') + mid_img_abs = os.path.join(iotests.test_dir, dir2, 'mid.img') + + def setUp(self): + try: + os.mkdir(os.path.join(iotests.test_dir, self.dir1)) + os.mkdir(os.path.join(iotests.test_dir, self.dir2)) + os.mkdir(os.path.join(iotests.test_dir, self.dir3)) + except OSError as exception: + if exception.errno != errno.EEXIST: + raise + self.create_image(self.backing_img_abs, TestRelativePaths.image_len) + qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % self.backing_img_abs, self.mid_img_abs) + qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % self.mid_img_abs, self.test_img) + qemu_img('rebase', '-u', '-b', self.backing_img, self.mid_img_abs) + qemu_img('rebase', '-u', '-b', self.mid_img, self.test_img) + qemu_io('-c', 'write -P 0xab 0 524288', self.backing_img_abs) + qemu_io('-c', 'write -P 0xef 524288 524288', self.mid_img_abs) + self.vm = iotests.VM().add_drive(self.test_img) + self.vm.launch() + + def tearDown(self): + self.vm.shutdown() + os.remove(self.test_img) + os.remove(self.mid_img_abs) + os.remove(self.backing_img_abs) + try: + os.rmdir(os.path.join(iotests.test_dir, self.dir1)) + os.rmdir(os.path.join(iotests.test_dir, self.dir3)) + os.rmdir(os.path.join(iotests.test_dir, self.dir2)) + except OSError as exception: + if exception.errno != errno.EEXIST and exception.errno != errno.ENOTEMPTY: + raise + + def test_commit(self): + self.assert_no_active_commit() + result = self.vm.qmp('block-commit', device='drive0', top='%s' % self.mid_img) + self.assert_qmp(result, 'return', {}) + + completed = False + while not completed: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_COMPLETED': + self.assert_qmp(event, 'data/type', 'commit') + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/offset', self.image_len) + self.assert_qmp(event, 'data/len', self.image_len) + completed = True + + self.assert_no_active_commit() + self.vm.shutdown() + + self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', self.backing_img_abs).find("verification failed")) + self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', self.backing_img_abs).find("verification failed")) + + def test_device_not_found(self): + result = self.vm.qmp('block-commit', device='nonexistent', top='%s' % self.mid_img) + self.assert_qmp(result, 'error/class', 'DeviceNotFound') + + def test_top_same_base(self): + self.assert_no_active_commit() + result = self.vm.qmp('block-commit', device='drive0', top='%s' % self.mid_img, base='%s' % self.mid_img) + self.assert_qmp(result, 'error/class', 'GenericError') + self.assert_qmp(result, 'error/desc', 'Base \'%s\' not found' % self.mid_img) + + def test_top_invalid(self): + self.assert_no_active_commit() + result = self.vm.qmp('block-commit', device='drive0', top='badfile', base='%s' % self.backing_img) + self.assert_qmp(result, 'error/class', 'GenericError') + self.assert_qmp(result, 'error/desc', 'Top image file badfile not found') + + def test_base_invalid(self): + self.assert_no_active_commit() + result = self.vm.qmp('block-commit', device='drive0', top='%s' % self.mid_img, base='badfile') + self.assert_qmp(result, 'error/class', 'GenericError') + self.assert_qmp(result, 'error/desc', 'Base \'badfile\' not found') + + def test_top_is_active(self): + self.assert_no_active_commit() + result = self.vm.qmp('block-commit', device='drive0', top='%s' % self.test_img, base='%s' % self.backing_img) + self.assert_qmp(result, 'error/class', 'GenericError') + self.assert_qmp(result, 'error/desc', 'Top image as the active layer is currently unsupported') + + def test_top_and_base_reversed(self): + self.assert_no_active_commit() + result = self.vm.qmp('block-commit', device='drive0', top='%s' % self.backing_img, base='%s' % self.mid_img) + self.assert_qmp(result, 'error/class', 'GenericError') + self.assert_qmp(result, 'error/desc', 'Base \'%s\' not found' % self.mid_img) + class TestSetSpeed(ImageCommitTestCase): image_len = 80 * 1024 * 1024 # MB diff --git a/tests/qemu-iotests/040.out b/tests/qemu-iotests/040.out index dae404e278..b6f257674e 100644 --- a/tests/qemu-iotests/040.out +++ b/tests/qemu-iotests/040.out @@ -1,5 +1,5 @@ -......... +................ ---------------------------------------------------------------------- -Ran 9 tests +Ran 16 tests OK From 9699bf0d06eb42625779216586a28d19d8fc005d Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 17 Oct 2012 14:02:31 +0200 Subject: [PATCH 1093/2270] qemu-img: Add --backing-chain option to info command The qemu-img info --backing-chain option enumerates the backing file chain. For example, for base.qcow2 <- snap1.qcow2 <- snap2.qcow2 the output becomes: $ qemu-img info --backing-chain snap2.qcow2 image: snap2.qcow2 file format: qcow2 virtual size: 100M (104857600 bytes) disk size: 196K cluster_size: 65536 backing file: snap1.qcow2 backing file format: qcow2 image: snap1.qcow2 file format: qcow2 virtual size: 100M (104857600 bytes) disk size: 196K cluster_size: 65536 backing file: base.qcow2 backing file format: qcow2 image: base.qcow2 file format: qcow2 virtual size: 100M (104857600 bytes) disk size: 136K cluster_size: 65536 Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- qemu-img.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 153 insertions(+), 14 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index c092ccfbcd..b17bddd25c 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1112,6 +1112,23 @@ static void dump_snapshots(BlockDriverState *bs) g_free(sn_tab); } +static void dump_json_image_info_list(ImageInfoList *list) +{ + Error *errp = NULL; + QString *str; + QmpOutputVisitor *ov = qmp_output_visitor_new(); + QObject *obj; + visit_type_ImageInfoList(qmp_output_get_visitor(ov), + &list, NULL, &errp); + obj = qmp_output_get_qobject(ov); + str = qobject_to_json_pretty(obj); + assert(str != NULL); + printf("%s\n", qstring_get_str(str)); + qobject_decref(obj); + qmp_output_visitor_cleanup(ov); + QDECREF(str); +} + static void collect_snapshots(BlockDriverState *bs , ImageInfo *info) { int i, sn_count; @@ -1251,9 +1268,129 @@ static void dump_human_image_info(ImageInfo *info) printf("backing file format: %s\n", info->backing_filename_format); } } + + if (info->has_snapshots) { + SnapshotInfoList *elem; + char buf[256]; + + printf("Snapshot list:\n"); + printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL)); + + /* Ideally bdrv_snapshot_dump() would operate on SnapshotInfoList but + * we convert to the block layer's native QEMUSnapshotInfo for now. + */ + for (elem = info->snapshots; elem; elem = elem->next) { + QEMUSnapshotInfo sn = { + .vm_state_size = elem->value->vm_state_size, + .date_sec = elem->value->date_sec, + .date_nsec = elem->value->date_nsec, + .vm_clock_nsec = elem->value->vm_clock_sec * 1000000000ULL + + elem->value->vm_clock_nsec, + }; + + pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id); + pstrcpy(sn.name, sizeof(sn.name), elem->value->name); + printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), &sn)); + } + } } -enum {OPTION_OUTPUT = 256}; +static void dump_human_image_info_list(ImageInfoList *list) +{ + ImageInfoList *elem; + bool delim = false; + + for (elem = list; elem; elem = elem->next) { + if (delim) { + printf("\n"); + } + delim = true; + + dump_human_image_info(elem->value); + } +} + +static gboolean str_equal_func(gconstpointer a, gconstpointer b) +{ + return strcmp(a, b) == 0; +} + +/** + * Open an image file chain and return an ImageInfoList + * + * @filename: topmost image filename + * @fmt: topmost image format (may be NULL to autodetect) + * @chain: true - enumerate entire backing file chain + * false - only topmost image file + * + * Returns a list of ImageInfo objects or NULL if there was an error opening an + * image file. If there was an error a message will have been printed to + * stderr. + */ +static ImageInfoList *collect_image_info_list(const char *filename, + const char *fmt, + bool chain) +{ + ImageInfoList *head = NULL; + ImageInfoList **last = &head; + GHashTable *filenames; + + filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL); + + while (filename) { + BlockDriverState *bs; + ImageInfo *info; + ImageInfoList *elem; + + if (g_hash_table_lookup_extended(filenames, filename, NULL, NULL)) { + error_report("Backing file '%s' creates an infinite loop.", + filename); + goto err; + } + g_hash_table_insert(filenames, (gpointer)filename, NULL); + + bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING, + false); + if (!bs) { + goto err; + } + + info = g_new0(ImageInfo, 1); + collect_image_info(bs, info, filename, fmt); + collect_snapshots(bs, info); + + elem = g_new0(ImageInfoList, 1); + elem->value = info; + *last = elem; + last = &elem->next; + + bdrv_delete(bs); + + filename = fmt = NULL; + if (chain) { + if (info->has_full_backing_filename) { + filename = info->full_backing_filename; + } else if (info->has_backing_filename) { + filename = info->backing_filename; + } + if (info->has_backing_filename_format) { + fmt = info->backing_filename_format; + } + } + } + g_hash_table_destroy(filenames); + return head; + +err: + qapi_free_ImageInfoList(head); + g_hash_table_destroy(filenames); + return NULL; +} + +enum { + OPTION_OUTPUT = 256, + OPTION_BACKING_CHAIN = 257, +}; typedef enum OutputFormat { OFORMAT_JSON, @@ -1264,9 +1401,9 @@ static int img_info(int argc, char **argv) { int c; OutputFormat output_format = OFORMAT_HUMAN; + bool chain = false; const char *filename, *fmt, *output; - BlockDriverState *bs; - ImageInfo *info; + ImageInfoList *list; fmt = NULL; output = NULL; @@ -1276,6 +1413,7 @@ static int img_info(int argc, char **argv) {"help", no_argument, 0, 'h'}, {"format", required_argument, 0, 'f'}, {"output", required_argument, 0, OPTION_OUTPUT}, + {"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, "f:h", @@ -1294,6 +1432,9 @@ static int img_info(int argc, char **argv) case OPTION_OUTPUT: output = optarg; break; + case OPTION_BACKING_CHAIN: + chain = true; + break; } } if (optind >= argc) { @@ -1310,27 +1451,25 @@ static int img_info(int argc, char **argv) return 1; } - bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING, false); - if (!bs) { + list = collect_image_info_list(filename, fmt, chain); + if (!list) { return 1; } - info = g_new0(ImageInfo, 1); - collect_image_info(bs, info, filename, fmt); - switch (output_format) { case OFORMAT_HUMAN: - dump_human_image_info(info); - dump_snapshots(bs); + dump_human_image_info_list(list); break; case OFORMAT_JSON: - collect_snapshots(bs, info); - dump_json_image_info(info); + if (chain) { + dump_json_image_info_list(list); + } else { + dump_json_image_info(list->value); + } break; } - qapi_free_ImageInfo(info); - bdrv_delete(bs); + qapi_free_ImageInfoList(list); return 0; } From 514d9da5a9a820b43a2cb90b439dd570a7835114 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 17 Oct 2012 14:02:32 +0200 Subject: [PATCH 1094/2270] qemu-iotests: Add 043 backing file chain infinite loop test This new test verifies that qemu-img info --backing-chain safely aborts when an image file has a backing file infinite loop. Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- tests/qemu-iotests/043 | 95 ++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/043.out | 66 +++++++++++++++++++++++++ tests/qemu-iotests/common.rc | 10 ++++ tests/qemu-iotests/group | 1 + 4 files changed, 172 insertions(+) create mode 100755 tests/qemu-iotests/043 create mode 100644 tests/qemu-iotests/043.out diff --git a/tests/qemu-iotests/043 b/tests/qemu-iotests/043 new file mode 100755 index 0000000000..3ba08dc94e --- /dev/null +++ b/tests/qemu-iotests/043 @@ -0,0 +1,95 @@ +#!/bin/bash +# +# Test that qemu-img info --backing-chain detects infinite loops +# +# Copyright (C) 2012 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 . +# + +# creator +owner=stefanha@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 + rm -f $TEST_IMG.[123].base +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +# Any format supporting backing files +_supported_fmt qcow qcow2 vmdk qed +_supported_proto generic +_supported_os Linux + + +size=128M +_make_test_img $size +$QEMU_IMG rebase -u -b $TEST_IMG $TEST_IMG + +echo +echo "== backing file references self ==" +_img_info --backing-chain + +_make_test_img $size +mv $TEST_IMG $TEST_IMG.base +_make_test_img -b $TEST_IMG.base $size +$QEMU_IMG rebase -u -b $TEST_IMG $TEST_IMG.base + +echo +echo "== parent references self ==" +_img_info --backing-chain + +_make_test_img $size +mv $TEST_IMG $TEST_IMG.1.base +_make_test_img -b $TEST_IMG.1.base $size +mv $TEST_IMG $TEST_IMG.2.base +_make_test_img -b $TEST_IMG.2.base $size +mv $TEST_IMG $TEST_IMG.3.base +_make_test_img -b $TEST_IMG.3.base $size +$QEMU_IMG rebase -u -b $TEST_IMG.2.base $TEST_IMG.1.base + +echo +echo "== ancestor references another ancestor ==" +_img_info --backing-chain + +_make_test_img $size +mv $TEST_IMG $TEST_IMG.1.base +_make_test_img -b $TEST_IMG.1.base $size +mv $TEST_IMG $TEST_IMG.2.base +_make_test_img -b $TEST_IMG.2.base $size + +echo +echo "== finite chain of length 3 (human) ==" +_img_info --backing-chain + +echo +echo "== finite chain of length 3 (json) ==" +_img_info --backing-chain --output=json + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/043.out b/tests/qemu-iotests/043.out new file mode 100644 index 0000000000..ad23337db5 --- /dev/null +++ b/tests/qemu-iotests/043.out @@ -0,0 +1,66 @@ +QA output created by 043 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 + +== backing file references self == +qemu-img: Backing file 'TEST_DIR/t.IMGFMT' creates an infinite loop. +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base' + +== parent references self == +qemu-img: Backing file 'TEST_DIR/t.IMGFMT' creates an infinite loop. +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.1.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.2.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.3.base' + +== ancestor references another ancestor == +qemu-img: Backing file 'TEST_DIR/t.IMGFMT.2.base' creates an infinite loop. +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.1.base' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.2.base' + +== finite chain of length 3 (human) == +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 128M (134217728 bytes) +cluster_size: 65536 +backing file: TEST_DIR/t.IMGFMT.2.base + +image: TEST_DIR/t.IMGFMT.2.base +file format: IMGFMT +virtual size: 128M (134217728 bytes) +cluster_size: 65536 +backing file: TEST_DIR/t.IMGFMT.1.base + +image: TEST_DIR/t.IMGFMT.1.base +file format: IMGFMT +virtual size: 128M (134217728 bytes) +cluster_size: 65536 + +== finite chain of length 3 (json) == +[ + { + "virtual-size": 134217728, + "filename": "TEST_DIR/t.IMGFMT", + "cluster-size": 65536, + "format": "IMGFMT", + "backing-filename": "TEST_DIR/t.IMGFMT.2.base", + "dirty-flag": false + }, + { + "virtual-size": 134217728, + "filename": "TEST_DIR/t.IMGFMT.2.base", + "cluster-size": 65536, + "format": "IMGFMT", + "backing-filename": "TEST_DIR/t.IMGFMT.1.base", + "dirty-flag": false + }, + { + "virtual-size": 134217728, + "filename": "TEST_DIR/t.IMGFMT.1.base", + "cluster-size": 65536, + "format": "IMGFMT", + "dirty-flag": false + } +] +*** done diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index d534e9466d..334534f22c 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -145,6 +145,16 @@ _check_test_img() sed -e 's/qemu-img\: This image format does not support checks/No errors were found on the image./' } +_img_info() +{ + $QEMU_IMG info "$@" $TEST_IMG 2>&1 | \ + sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ + -e "s#$TEST_DIR#TEST_DIR#g" \ + -e "s#$IMGFMT#IMGFMT#g" \ + -e "/^disk size:/ D" \ + -e "/actual-size/ D" +} + _get_pids_by_name() { if [ $# -ne 1 ] diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index d5f9ab0d7d..7407492099 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -48,3 +48,4 @@ 039 rw auto 040 rw auto 042 rw auto quick +043 rw auto backing From e53575606aa5567bde3246cdc3af1fdc757f77c8 Mon Sep 17 00:00:00 2001 From: Kashyap Chamarthy Date: Thu, 18 Oct 2012 11:25:34 +0530 Subject: [PATCH 1095/2270] qemu-img: document 'info --backing-chain' Signed-off-by: Kashyap Chamarthy Reviewed-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- qemu-img-cmds.hx | 4 ++-- qemu-img.texi | 21 ++++++++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx index 0ef82e9ac7..a18136302d 100644 --- a/qemu-img-cmds.hx +++ b/qemu-img-cmds.hx @@ -34,9 +34,9 @@ STEXI ETEXI DEF("info", img_info, - "info [-f fmt] [--output=ofmt] filename") + "info [-f fmt] [--output=ofmt] [--backing-chain] filename") STEXI -@item info [-f @var{fmt}] [--output=@var{ofmt}] @var{filename} +@item info [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename} ETEXI DEF("snapshot", img_snapshot, diff --git a/qemu-img.texi b/qemu-img.texi index 42ec392c36..60b83fc11a 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -28,6 +28,10 @@ Command parameters: is the disk image format. It is guessed automatically in most cases. See below for a description of the supported disk formats. +@item --backing-chain +will enumerate information about backing files in a disk image chain. Refer +below for further description. + @item size is the disk image size in bytes. Optional suffixes @code{k} or @code{K} (kilobyte, 1024) @code{M} (megabyte, 1024k) and @code{G} (gigabyte, 1024M) @@ -129,7 +133,7 @@ created as a copy on write image of the specified base image; the @var{backing_file} should have the same content as the input's base image, however the path, image format, etc may differ. -@item info [-f @var{fmt}] [--output=@var{ofmt}] @var{filename} +@item info [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename} Give information about the disk image @var{filename}. Use it in particular to know the size reserved on disk which can be different @@ -137,6 +141,21 @@ from the displayed size. If VM snapshots are stored in the disk image, they are displayed too. The command can output in the format @var{ofmt} which is either @code{human} or @code{json}. +If a disk image has a backing file chain, information about each disk image in +the chain can be recursively enumerated by using the option @code{--backing-chain}. + +For instance, if you have an image chain like: + +@example +base.qcow2 <- snap1.qcow2 <- snap2.qcow2 +@end example + +To enumerate information about each disk image in the above chain, starting from top to base, do: + +@example +qemu-img info --backing-chain snap2.qcow2 +@end example + @item snapshot [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot} ] @var{filename} List, apply, create or delete snapshots in image @var{filename}. From 80168bff43760bde98388480dc7c93f94693421c Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 17 Oct 2012 16:45:25 -0300 Subject: [PATCH 1096/2270] block: bdrv_create(): don't leak cco.filename on error Signed-off-by: Luiz Capitulino Reviewed-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- block.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/block.c b/block.c index 5e7fc9eb27..7e26b6fa4f 100644 --- a/block.c +++ b/block.c @@ -379,7 +379,8 @@ int bdrv_create(BlockDriver *drv, const char* filename, }; if (!drv->bdrv_create) { - return -ENOTSUP; + ret = -ENOTSUP; + goto out; } if (qemu_in_coroutine()) { @@ -394,8 +395,9 @@ int bdrv_create(BlockDriver *drv, const char* filename, } ret = cco.ret; - g_free(cco.filename); +out: + g_free(cco.filename); return ret; } From 9ac54af0c35d3f931653efae5698ef0f465eac7c Mon Sep 17 00:00:00 2001 From: Corey Bryant Date: Thu, 18 Oct 2012 15:19:31 -0400 Subject: [PATCH 1097/2270] monitor: Allow add-fd to any specified fd set The first call to add an fd to an fd set was previously not allowed to choose the fd set ID. The ID was generated as the first available and ensuing calls could add more fds by specifying the fd set ID. This change allows users to choose the fd set ID on the first call. Signed-off-by: Corey Bryant Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- monitor.c | 54 +++++++++++++++++++++++++++++++++--------------- qapi-schema.json | 2 +- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/monitor.c b/monitor.c index d17ae2d3b1..3519b397ae 100644 --- a/monitor.c +++ b/monitor.c @@ -2135,7 +2135,7 @@ AddfdInfo *qmp_add_fd(bool has_fdset_id, int64_t fdset_id, bool has_opaque, { int fd; Monitor *mon = cur_mon; - MonFdset *mon_fdset; + MonFdset *mon_fdset = NULL; MonFdsetFd *mon_fdset_fd; AddfdInfo *fdinfo; @@ -2147,34 +2147,54 @@ AddfdInfo *qmp_add_fd(bool has_fdset_id, int64_t fdset_id, bool has_opaque, if (has_fdset_id) { QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { - if (mon_fdset->id == fdset_id) { + /* Break if match found or match impossible due to ordering by ID */ + if (fdset_id <= mon_fdset->id) { + if (fdset_id < mon_fdset->id) { + mon_fdset = NULL; + } break; } } - if (mon_fdset == NULL) { - error_set(errp, QERR_INVALID_PARAMETER_VALUE, "fdset-id", - "an existing fdset-id"); - goto error; - } - } else { + } + + if (mon_fdset == NULL) { int64_t fdset_id_prev = -1; MonFdset *mon_fdset_cur = QLIST_FIRST(&mon_fdsets); - /* Use first available fdset ID */ - QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { - mon_fdset_cur = mon_fdset; - if (fdset_id_prev == mon_fdset_cur->id - 1) { - fdset_id_prev = mon_fdset_cur->id; - continue; + if (has_fdset_id) { + if (fdset_id < 0) { + error_set(errp, QERR_INVALID_PARAMETER_VALUE, "fdset-id", + "a non-negative value"); + goto error; + } + /* Use specified fdset ID */ + QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { + mon_fdset_cur = mon_fdset; + if (fdset_id < mon_fdset_cur->id) { + break; + } + } + } else { + /* Use first available fdset ID */ + QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { + mon_fdset_cur = mon_fdset; + if (fdset_id_prev == mon_fdset_cur->id - 1) { + fdset_id_prev = mon_fdset_cur->id; + continue; + } + break; } - break; } mon_fdset = g_malloc0(sizeof(*mon_fdset)); - mon_fdset->id = fdset_id_prev + 1; + if (has_fdset_id) { + mon_fdset->id = fdset_id; + } else { + mon_fdset->id = fdset_id_prev + 1; + } /* The fdset list is ordered by fdset ID */ - if (mon_fdset->id == 0) { + if (!mon_fdset_cur) { QLIST_INSERT_HEAD(&mon_fdsets, mon_fdset, next); } else if (mon_fdset->id < mon_fdset_cur->id) { QLIST_INSERT_BEFORE(mon_fdset_cur, mon_fdset, next); diff --git a/qapi-schema.json b/qapi-schema.json index c615ee212d..36278cc8df 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2625,7 +2625,7 @@ # # Returns: @AddfdInfo on success # If file descriptor was not received, FdNotSupplied -# If @fdset-id does not exist, InvalidParameterValue +# If @fdset-id is a negative value, InvalidParameterValue # # Notes: The list of fd sets is shared by all monitor connections. # From e446f70d54b4920e8ca5af509271b69eab86e37b Mon Sep 17 00:00:00 2001 From: Corey Bryant Date: Thu, 18 Oct 2012 15:19:32 -0400 Subject: [PATCH 1098/2270] monitor: Enable adding an inherited fd to an fd set qmp_add_fd() gets an fd that was received over a socket with SCM_RIGHTS and adds it to an fd set. This patch adds support that will enable adding an fd that was inherited on the command line to an fd set. Note: All of the code added to monitor_fdset_add_fd(), with the exception of the error path for non-valid fdset-id, is code motion from qmp_add_fd(). Signed-off-by: Corey Bryant Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- monitor.c | 157 +++++++++++++++++++++++++++++------------------------- monitor.h | 3 ++ 2 files changed, 88 insertions(+), 72 deletions(-) diff --git a/monitor.c b/monitor.c index 3519b397ae..6e990496a8 100644 --- a/monitor.c +++ b/monitor.c @@ -2135,8 +2135,6 @@ AddfdInfo *qmp_add_fd(bool has_fdset_id, int64_t fdset_id, bool has_opaque, { int fd; Monitor *mon = cur_mon; - MonFdset *mon_fdset = NULL; - MonFdsetFd *mon_fdset_fd; AddfdInfo *fdinfo; fd = qemu_chr_fe_get_msgfd(mon->chr); @@ -2145,78 +2143,12 @@ AddfdInfo *qmp_add_fd(bool has_fdset_id, int64_t fdset_id, bool has_opaque, goto error; } - if (has_fdset_id) { - QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { - /* Break if match found or match impossible due to ordering by ID */ - if (fdset_id <= mon_fdset->id) { - if (fdset_id < mon_fdset->id) { - mon_fdset = NULL; - } - break; - } - } + fdinfo = monitor_fdset_add_fd(fd, has_fdset_id, fdset_id, + has_opaque, opaque, errp); + if (fdinfo) { + return fdinfo; } - if (mon_fdset == NULL) { - int64_t fdset_id_prev = -1; - MonFdset *mon_fdset_cur = QLIST_FIRST(&mon_fdsets); - - if (has_fdset_id) { - if (fdset_id < 0) { - error_set(errp, QERR_INVALID_PARAMETER_VALUE, "fdset-id", - "a non-negative value"); - goto error; - } - /* Use specified fdset ID */ - QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { - mon_fdset_cur = mon_fdset; - if (fdset_id < mon_fdset_cur->id) { - break; - } - } - } else { - /* Use first available fdset ID */ - QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { - mon_fdset_cur = mon_fdset; - if (fdset_id_prev == mon_fdset_cur->id - 1) { - fdset_id_prev = mon_fdset_cur->id; - continue; - } - break; - } - } - - mon_fdset = g_malloc0(sizeof(*mon_fdset)); - if (has_fdset_id) { - mon_fdset->id = fdset_id; - } else { - mon_fdset->id = fdset_id_prev + 1; - } - - /* The fdset list is ordered by fdset ID */ - if (!mon_fdset_cur) { - QLIST_INSERT_HEAD(&mon_fdsets, mon_fdset, next); - } else if (mon_fdset->id < mon_fdset_cur->id) { - QLIST_INSERT_BEFORE(mon_fdset_cur, mon_fdset, next); - } else { - QLIST_INSERT_AFTER(mon_fdset_cur, mon_fdset, next); - } - } - - mon_fdset_fd = g_malloc0(sizeof(*mon_fdset_fd)); - mon_fdset_fd->fd = fd; - mon_fdset_fd->removed = false; - if (has_opaque) { - mon_fdset_fd->opaque = g_strdup(opaque); - } - QLIST_INSERT_HEAD(&mon_fdset->fds, mon_fdset_fd, next); - - fdinfo = g_malloc0(sizeof(*fdinfo)); - fdinfo->fdset_id = mon_fdset->id; - fdinfo->fd = mon_fdset_fd->fd; - - return fdinfo; - error: if (fd != -1) { close(fd); @@ -2301,6 +2233,87 @@ FdsetInfoList *qmp_query_fdsets(Error **errp) return fdset_list; } +AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id, + bool has_opaque, const char *opaque, + Error **errp) +{ + MonFdset *mon_fdset = NULL; + MonFdsetFd *mon_fdset_fd; + AddfdInfo *fdinfo; + + if (has_fdset_id) { + QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { + /* Break if match found or match impossible due to ordering by ID */ + if (fdset_id <= mon_fdset->id) { + if (fdset_id < mon_fdset->id) { + mon_fdset = NULL; + } + break; + } + } + } + + if (mon_fdset == NULL) { + int64_t fdset_id_prev = -1; + MonFdset *mon_fdset_cur = QLIST_FIRST(&mon_fdsets); + + if (has_fdset_id) { + if (fdset_id < 0) { + error_set(errp, QERR_INVALID_PARAMETER_VALUE, "fdset-id", + "a non-negative value"); + return NULL; + } + /* Use specified fdset ID */ + QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { + mon_fdset_cur = mon_fdset; + if (fdset_id < mon_fdset_cur->id) { + break; + } + } + } else { + /* Use first available fdset ID */ + QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { + mon_fdset_cur = mon_fdset; + if (fdset_id_prev == mon_fdset_cur->id - 1) { + fdset_id_prev = mon_fdset_cur->id; + continue; + } + break; + } + } + + mon_fdset = g_malloc0(sizeof(*mon_fdset)); + if (has_fdset_id) { + mon_fdset->id = fdset_id; + } else { + mon_fdset->id = fdset_id_prev + 1; + } + + /* The fdset list is ordered by fdset ID */ + if (!mon_fdset_cur) { + QLIST_INSERT_HEAD(&mon_fdsets, mon_fdset, next); + } else if (mon_fdset->id < mon_fdset_cur->id) { + QLIST_INSERT_BEFORE(mon_fdset_cur, mon_fdset, next); + } else { + QLIST_INSERT_AFTER(mon_fdset_cur, mon_fdset, next); + } + } + + mon_fdset_fd = g_malloc0(sizeof(*mon_fdset_fd)); + mon_fdset_fd->fd = fd; + mon_fdset_fd->removed = false; + if (has_opaque) { + mon_fdset_fd->opaque = g_strdup(opaque); + } + QLIST_INSERT_HEAD(&mon_fdset->fds, mon_fdset_fd, next); + + fdinfo = g_malloc0(sizeof(*fdinfo)); + fdinfo->fdset_id = mon_fdset->id; + fdinfo->fd = mon_fdset_fd->fd; + + return fdinfo; +} + int monitor_fdset_get_fd(int64_t fdset_id, int flags) { #ifndef _WIN32 diff --git a/monitor.h b/monitor.h index b6e7d95a30..d4c017e496 100644 --- a/monitor.h +++ b/monitor.h @@ -90,6 +90,9 @@ int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret); int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret); +AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id, + bool has_opaque, const char *opaque, + Error **errp); int monitor_fdset_get_fd(int64_t fdset_id, int flags); int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd); int monitor_fdset_dup_fd_remove(int dup_fd); From ebe52b592dd5867fce7238f49b8c0416c3eedb6c Mon Sep 17 00:00:00 2001 From: Corey Bryant Date: Thu, 18 Oct 2012 15:19:33 -0400 Subject: [PATCH 1099/2270] monitor: Prevent removing fd from set during init If an fd is added to an fd set via the command line, and it is not referenced by another command line option (ie. -drive), then clean it up after QEMU initialization is complete. Signed-off-by: Corey Bryant Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- monitor.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/monitor.c b/monitor.c index 6e990496a8..1d3dd9aac1 100644 --- a/monitor.c +++ b/monitor.c @@ -2105,8 +2105,9 @@ static void monitor_fdset_cleanup(MonFdset *mon_fdset) MonFdsetFd *mon_fdset_fd_next; QLIST_FOREACH_SAFE(mon_fdset_fd, &mon_fdset->fds, next, mon_fdset_fd_next) { - if (mon_fdset_fd->removed || - (QLIST_EMPTY(&mon_fdset->dup_fds) && mon_refcount == 0)) { + if ((mon_fdset_fd->removed || + (QLIST_EMPTY(&mon_fdset->dup_fds) && mon_refcount == 0)) && + runstate_is_running()) { close(mon_fdset_fd->fd); g_free(mon_fdset_fd->opaque); QLIST_REMOVE(mon_fdset_fd, next); From 587ed6be0b6331b11169da8846b8442840d5428c Mon Sep 17 00:00:00 2001 From: Corey Bryant Date: Thu, 18 Oct 2012 15:19:34 -0400 Subject: [PATCH 1100/2270] qemu-config: Add new -add-fd command line option This option can be used for passing file descriptors on the command line. It mirrors the existing add-fd QMP command which allows an fd to be passed to QEMU via SCM_RIGHTS and added to an fd set. This can be combined with commands such as -drive to link file descriptors in an fd set to a drive: qemu-kvm -add-fd fd=3,set=2,opaque="rdwr:/path/to/file" -add-fd fd=4,set=2,opaque="rdonly:/path/to/file" -drive file=/dev/fdset/2,index=0,media=disk This example adds dups of fds 3 and 4, and the accompanying opaque strings to the fd set with ID=2. qemu_open() already knows how to handle a filename of this format. qemu_open() searches the corresponding fd set for an fd and when it finds a match, QEMU goes on to use a dup of that fd just like it would have used an fd that it opened itself. Signed-off-by: Corey Bryant Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- qemu-config.c | 22 ++++++++++++ qemu-options.hx | 36 +++++++++++++++++++ vl.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+) diff --git a/qemu-config.c b/qemu-config.c index cd1ec2165a..601237db9d 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -653,6 +653,27 @@ QemuOptsList qemu_boot_opts = { }, }; +static QemuOptsList qemu_add_fd_opts = { + .name = "add-fd", + .head = QTAILQ_HEAD_INITIALIZER(qemu_add_fd_opts.head), + .desc = { + { + .name = "fd", + .type = QEMU_OPT_NUMBER, + .help = "file descriptor of which a duplicate is added to fd set", + },{ + .name = "set", + .type = QEMU_OPT_NUMBER, + .help = "ID of the fd set to add fd to", + },{ + .name = "opaque", + .type = QEMU_OPT_STRING, + .help = "free-form string used to describe fd", + }, + { /* end of list */ } + }, +}; + static QemuOptsList *vm_config_groups[32] = { &qemu_drive_opts, &qemu_chardev_opts, @@ -669,6 +690,7 @@ static QemuOptsList *vm_config_groups[32] = { &qemu_boot_opts, &qemu_iscsi_opts, &qemu_sandbox_opts, + &qemu_add_fd_opts, NULL, }; diff --git a/qemu-options.hx b/qemu-options.hx index 46f0539182..a67a2551e5 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -253,6 +253,14 @@ qemu-system-i386 -drive file=file,index=2,media=disk qemu-system-i386 -drive file=file,index=3,media=disk @end example +You can open an image using pre-opened file descriptors from an fd set: +@example +qemu-system-i386 +-add-fd fd=3,set=2,opaque="rdwr:/path/to/file" +-add-fd fd=4,set=2,opaque="rdonly:/path/to/file" +-drive file=/dev/fdset/2,index=0,media=disk +@end example + You can connect a CDROM to the slave of ide0: @example qemu-system-i386 -drive file=file,if=ide,index=1,media=cdrom @@ -285,6 +293,34 @@ qemu-system-i386 -hda a -hdb b @end example ETEXI +DEF("add-fd", HAS_ARG, QEMU_OPTION_add_fd, + "-add-fd fd=fd,set=set[,opaque=opaque]\n" + " Add 'fd' to fd 'set'\n", QEMU_ARCH_ALL) +STEXI +@item -add-fd fd=@var{fd},set=@var{set}[,opaque=@var{opaque}] +@findex -add-fd + +Add a file descriptor to an fd set. Valid options are: + +@table @option +@item fd=@var{fd} +This option defines the file descriptor of which a duplicate is added to fd set. +The file descriptor cannot be stdin, stdout, or stderr. +@item set=@var{set} +This option defines the ID of the fd set to add the file descriptor to. +@item opaque=@var{opaque} +This option defines a free-form string that can be used to describe @var{fd}. +@end table + +You can open an image using pre-opened file descriptors from an fd set: +@example +qemu-system-i386 +-add-fd fd=3,set=2,opaque="rdwr:/path/to/file" +-add-fd fd=4,set=2,opaque="rdonly:/path/to/file" +-drive file=/dev/fdset/2,index=0,media=disk +@end example +ETEXI + DEF("set", HAS_ARG, QEMU_OPTION_set, "-set group.id.arg=value\n" " set parameter for item of type \n" diff --git a/vl.c b/vl.c index ee3c43ae2f..b870caf2c8 100644 --- a/vl.c +++ b/vl.c @@ -790,6 +790,78 @@ static int parse_sandbox(QemuOpts *opts, void *opaque) return 0; } +#ifndef _WIN32 +static int parse_add_fd(QemuOpts *opts, void *opaque) +{ + int fd, dupfd, flags; + int64_t fdset_id; + const char *fd_opaque = NULL; + + fd = qemu_opt_get_number(opts, "fd", -1); + fdset_id = qemu_opt_get_number(opts, "set", -1); + fd_opaque = qemu_opt_get(opts, "opaque"); + + if (fd < 0) { + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "fd option is required and must be non-negative"); + return -1; + } + + if (fd <= STDERR_FILENO) { + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "fd cannot be a standard I/O stream"); + return -1; + } + + /* + * All fds inherited across exec() necessarily have FD_CLOEXEC + * clear, while qemu sets FD_CLOEXEC on all other fds used internally. + */ + flags = fcntl(fd, F_GETFD); + if (flags == -1 || (flags & FD_CLOEXEC)) { + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "fd is not valid or already in use"); + return -1; + } + + if (fdset_id < 0) { + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "set option is required and must be non-negative"); + return -1; + } + +#ifdef F_DUPFD_CLOEXEC + dupfd = fcntl(fd, F_DUPFD_CLOEXEC, 0); +#else + dupfd = dup(fd); + if (dupfd != -1) { + qemu_set_cloexec(dupfd); + } +#endif + if (dupfd == -1) { + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "Error duplicating fd: %s", strerror(errno)); + return -1; + } + + /* add the duplicate fd, and optionally the opaque string, to the fd set */ + monitor_fdset_add_fd(dupfd, true, fdset_id, fd_opaque ? true : false, + fd_opaque, NULL); + + return 0; +} + +static int cleanup_add_fd(QemuOpts *opts, void *opaque) +{ + int fd; + + fd = qemu_opt_get_number(opts, "fd", -1); + close(fd); + + return 0; +} +#endif + /***********************************************************/ /* QEMU Block devices */ @@ -3309,6 +3381,18 @@ int main(int argc, char **argv, char **envp) exit(0); } break; + case QEMU_OPTION_add_fd: +#ifndef _WIN32 + opts = qemu_opts_parse(qemu_find_opts("add-fd"), optarg, 0); + if (!opts) { + exit(0); + } +#else + error_report("File descriptor passing is disabled on this " + "platform"); + exit(1); +#endif + break; default: os_parse_cmd_args(popt->index, optarg); } @@ -3320,6 +3404,16 @@ int main(int argc, char **argv, char **envp) exit(1); } +#ifndef _WIN32 + if (qemu_opts_foreach(qemu_find_opts("add-fd"), parse_add_fd, NULL, 1)) { + exit(1); + } + + if (qemu_opts_foreach(qemu_find_opts("add-fd"), cleanup_add_fd, NULL, 1)) { + exit(1); + } +#endif + if (machine == NULL) { fprintf(stderr, "No machine found.\n"); exit(1); From ac84adac48963653638a1c95dd7c6ab8b4d5a4f3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Oct 2012 16:49:15 +0200 Subject: [PATCH 1101/2270] block: add bdrv_query_info Extract it out of the implementation of "info block". Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- block.c | 112 ++++++++++++++++++++++++++++---------------------------- block.h | 1 + 2 files changed, 57 insertions(+), 56 deletions(-) diff --git a/block.c b/block.c index 7e26b6fa4f..2ba83db279 100644 --- a/block.c +++ b/block.c @@ -2799,69 +2799,69 @@ int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top, return 0; } +BlockInfo *bdrv_query_info(BlockDriverState *bs) +{ + BlockInfo *info = g_malloc0(sizeof(*info)); + info->device = g_strdup(bs->device_name); + info->type = g_strdup("unknown"); + info->locked = bdrv_dev_is_medium_locked(bs); + info->removable = bdrv_dev_has_removable_media(bs); + + if (bdrv_dev_has_removable_media(bs)) { + info->has_tray_open = true; + info->tray_open = bdrv_dev_is_tray_open(bs); + } + + if (bdrv_iostatus_is_enabled(bs)) { + info->has_io_status = true; + info->io_status = bs->iostatus; + } + + if (bs->drv) { + info->has_inserted = true; + info->inserted = g_malloc0(sizeof(*info->inserted)); + info->inserted->file = g_strdup(bs->filename); + info->inserted->ro = bs->read_only; + info->inserted->drv = g_strdup(bs->drv->format_name); + info->inserted->encrypted = bs->encrypted; + info->inserted->encryption_key_missing = bdrv_key_required(bs); + + if (bs->backing_file[0]) { + info->inserted->has_backing_file = true; + info->inserted->backing_file = g_strdup(bs->backing_file); + } + + info->inserted->backing_file_depth = bdrv_get_backing_file_depth(bs); + + if (bs->io_limits_enabled) { + info->inserted->bps = + bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL]; + info->inserted->bps_rd = + bs->io_limits.bps[BLOCK_IO_LIMIT_READ]; + info->inserted->bps_wr = + bs->io_limits.bps[BLOCK_IO_LIMIT_WRITE]; + info->inserted->iops = + bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL]; + info->inserted->iops_rd = + bs->io_limits.iops[BLOCK_IO_LIMIT_READ]; + info->inserted->iops_wr = + bs->io_limits.iops[BLOCK_IO_LIMIT_WRITE]; + } + } + return info; +} + BlockInfoList *qmp_query_block(Error **errp) { - BlockInfoList *head = NULL, *cur_item = NULL; + BlockInfoList *head = NULL, **p_next = &head; BlockDriverState *bs; QTAILQ_FOREACH(bs, &bdrv_states, list) { BlockInfoList *info = g_malloc0(sizeof(*info)); + info->value = bdrv_query_info(bs); - info->value = g_malloc0(sizeof(*info->value)); - info->value->device = g_strdup(bs->device_name); - info->value->type = g_strdup("unknown"); - info->value->locked = bdrv_dev_is_medium_locked(bs); - info->value->removable = bdrv_dev_has_removable_media(bs); - - if (bdrv_dev_has_removable_media(bs)) { - info->value->has_tray_open = true; - info->value->tray_open = bdrv_dev_is_tray_open(bs); - } - - if (bdrv_iostatus_is_enabled(bs)) { - info->value->has_io_status = true; - info->value->io_status = bs->iostatus; - } - - if (bs->drv) { - info->value->has_inserted = true; - info->value->inserted = g_malloc0(sizeof(*info->value->inserted)); - info->value->inserted->file = g_strdup(bs->filename); - info->value->inserted->ro = bs->read_only; - info->value->inserted->drv = g_strdup(bs->drv->format_name); - info->value->inserted->encrypted = bs->encrypted; - info->value->inserted->encryption_key_missing = bdrv_key_required(bs); - if (bs->backing_file[0]) { - info->value->inserted->has_backing_file = true; - info->value->inserted->backing_file = g_strdup(bs->backing_file); - } - - info->value->inserted->backing_file_depth = - bdrv_get_backing_file_depth(bs); - - if (bs->io_limits_enabled) { - info->value->inserted->bps = - bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL]; - info->value->inserted->bps_rd = - bs->io_limits.bps[BLOCK_IO_LIMIT_READ]; - info->value->inserted->bps_wr = - bs->io_limits.bps[BLOCK_IO_LIMIT_WRITE]; - info->value->inserted->iops = - bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL]; - info->value->inserted->iops_rd = - bs->io_limits.iops[BLOCK_IO_LIMIT_READ]; - info->value->inserted->iops_wr = - bs->io_limits.iops[BLOCK_IO_LIMIT_WRITE]; - } - } - - /* XXX: waiting for the qapi to support GSList */ - if (!cur_item) { - head = cur_item = info; - } else { - cur_item->next = info; - cur_item = info; - } + *p_next = info; + p_next = &info->next; } return head; diff --git a/block.h b/block.h index e2d89d7bc1..2ede16d638 100644 --- a/block.h +++ b/block.h @@ -313,6 +313,7 @@ void bdrv_get_backing_filename(BlockDriverState *bs, char *filename, int filename_size); void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz); +BlockInfo *bdrv_query_info(BlockDriverState *s); int bdrv_can_snapshot(BlockDriverState *bs); int bdrv_is_snapshot(BlockDriverState *bs); BlockDriverState *bdrv_snapshots(void); From 9887b616619f62977682e76927a9b5a6134cc8bf Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Oct 2012 16:49:16 +0200 Subject: [PATCH 1102/2270] block: add bdrv_query_stats qmp_query_blockstat cannot have errors, remove the Error argument and create a new public function bdrv_query_stats out of it. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- block.c | 18 ++++++------------ block.h | 1 + 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/block.c b/block.c index 2ba83db279..a723be22f3 100644 --- a/block.c +++ b/block.c @@ -2867,8 +2867,7 @@ BlockInfoList *qmp_query_block(Error **errp) return head; } -/* Consider exposing this as a full fledged QMP command */ -static BlockStats *qmp_query_blockstat(const BlockDriverState *bs, Error **errp) +BlockStats *bdrv_query_stats(const BlockDriverState *bs) { BlockStats *s; @@ -2892,7 +2891,7 @@ static BlockStats *qmp_query_blockstat(const BlockDriverState *bs, Error **errp) if (bs->file) { s->has_parent = true; - s->parent = qmp_query_blockstat(bs->file, NULL); + s->parent = bdrv_query_stats(bs->file); } return s; @@ -2900,20 +2899,15 @@ static BlockStats *qmp_query_blockstat(const BlockDriverState *bs, Error **errp) BlockStatsList *qmp_query_blockstats(Error **errp) { - BlockStatsList *head = NULL, *cur_item = NULL; + BlockStatsList *head = NULL, **p_next = &head; BlockDriverState *bs; QTAILQ_FOREACH(bs, &bdrv_states, list) { BlockStatsList *info = g_malloc0(sizeof(*info)); - info->value = qmp_query_blockstat(bs, NULL); + info->value = bdrv_query_stats(bs); - /* XXX: waiting for the qapi to support GSList */ - if (!cur_item) { - head = cur_item = info; - } else { - cur_item->next = info; - cur_item = info; - } + *p_next = info; + p_next = &info->next; } return head; diff --git a/block.h b/block.h index 2ede16d638..ed4b90d64c 100644 --- a/block.h +++ b/block.h @@ -314,6 +314,7 @@ void bdrv_get_backing_filename(BlockDriverState *bs, void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz); BlockInfo *bdrv_query_info(BlockDriverState *s); +BlockStats *bdrv_query_stats(const BlockDriverState *bs); int bdrv_can_snapshot(BlockDriverState *bs); int bdrv_is_snapshot(BlockDriverState *bs); BlockDriverState *bdrv_snapshots(void); From 9156df12a4f3b3db63d1b292d081d814f02e311a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Oct 2012 16:49:17 +0200 Subject: [PATCH 1103/2270] block: add bdrv_open_backing_file Mirroring runs without the backing file so that it can be copied outside QEMU. However, we need to add it at the time the job is completed and QEMU switches to the target. Factor out the common bits of opening an image and completing a mirroring operation. The new function does not assume that the file is closed immediately after it returns failure, so it keeps the BDRV_O_NO_BACKING flag up-to-date. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- block.c | 56 ++++++++++++++++++++++++++++++++++++++------------------ block.h | 1 + 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/block.c b/block.c index a723be22f3..e06d78fe7b 100644 --- a/block.c +++ b/block.c @@ -736,6 +736,42 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags) return 0; } +int bdrv_open_backing_file(BlockDriverState *bs) +{ + char backing_filename[PATH_MAX]; + int back_flags, ret; + BlockDriver *back_drv = NULL; + + if (bs->backing_hd != NULL) { + return 0; + } + + bs->open_flags &= ~BDRV_O_NO_BACKING; + if (bs->backing_file[0] == '\0') { + return 0; + } + + bs->backing_hd = bdrv_new(""); + bdrv_get_full_backing_filename(bs, backing_filename, + sizeof(backing_filename)); + + if (bs->backing_format[0] != '\0') { + back_drv = bdrv_find_format(bs->backing_format); + } + + /* backing files always opened read-only */ + back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT); + + ret = bdrv_open(bs->backing_hd, backing_filename, back_flags, back_drv); + if (ret < 0) { + bdrv_delete(bs->backing_hd); + bs->backing_hd = NULL; + bs->open_flags |= BDRV_O_NO_BACKING; + return ret; + } + return 0; +} + /* * Opens a disk image (raw, qcow2, vmdk, ...) */ @@ -823,24 +859,8 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, } /* If there is a backing file, use it */ - if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') { - char backing_filename[PATH_MAX]; - int back_flags; - BlockDriver *back_drv = NULL; - - bs->backing_hd = bdrv_new(""); - bdrv_get_full_backing_filename(bs, backing_filename, - sizeof(backing_filename)); - - if (bs->backing_format[0] != '\0') { - back_drv = bdrv_find_format(bs->backing_format); - } - - /* backing files always opened read-only */ - back_flags = - flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); - - ret = bdrv_open(bs->backing_hd, backing_filename, back_flags, back_drv); + if ((flags & BDRV_O_NO_BACKING) == 0) { + ret = bdrv_open_backing_file(bs); if (ret < 0) { bdrv_close(bs); return ret; diff --git a/block.h b/block.h index ed4b90d64c..096fa09373 100644 --- a/block.h +++ b/block.h @@ -133,6 +133,7 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top); void bdrv_delete(BlockDriverState *bs); int bdrv_parse_cache_flags(const char *mode, int *flags); int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags); +int bdrv_open_backing_file(BlockDriverState *bs); int bdrv_open(BlockDriverState *bs, const char *filename, int flags, BlockDriver *drv); BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue, From 1755da16e32c15b22a521e8a38539e4b5cf367f3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Oct 2012 16:49:18 +0200 Subject: [PATCH 1104/2270] block: introduce new dirty bitmap functionality Assert that write_compressed is never used with the dirty bitmap. Setting the bits early is wrong, because a coroutine might concurrently examine them and copy incomplete data from the source. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- block.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------ block.h | 5 +++-- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/block.c b/block.c index e06d78fe7b..2c3d3dadd9 100644 --- a/block.c +++ b/block.c @@ -2391,7 +2391,7 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs, } if (bs->dirty_bitmap) { - set_dirty_bitmap(bs, sector_num, nb_sectors, 1); + bdrv_set_dirty(bs, sector_num, nb_sectors); } if (bs->wr_highest_sector < sector_num + nb_sectors - 1) { @@ -2960,9 +2960,7 @@ int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, if (bdrv_check_request(bs, sector_num, nb_sectors)) return -EIO; - if (bs->dirty_bitmap) { - set_dirty_bitmap(bs, sector_num, nb_sectors, 1); - } + assert(!bs->dirty_bitmap); return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors); } @@ -4269,13 +4267,54 @@ int bdrv_get_dirty(BlockDriverState *bs, int64_t sector) if (bs->dirty_bitmap && (sector << BDRV_SECTOR_BITS) < bdrv_getlength(bs)) { - return !!(bs->dirty_bitmap[chunk / (sizeof(unsigned long) * 8)] & - (1UL << (chunk % (sizeof(unsigned long) * 8)))); + return !!(bs->dirty_bitmap[chunk / BITS_PER_LONG] & + (1UL << (chunk % BITS_PER_LONG))); } else { return 0; } } +int64_t bdrv_get_next_dirty(BlockDriverState *bs, int64_t sector) +{ + int64_t chunk; + int bit, elem; + + /* Avoid an infinite loop. */ + assert(bs->dirty_count > 0); + + sector = (sector | (BDRV_SECTORS_PER_DIRTY_CHUNK - 1)) + 1; + chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK; + + QEMU_BUILD_BUG_ON(sizeof(bs->dirty_bitmap[0]) * 8 != BITS_PER_LONG); + elem = chunk / BITS_PER_LONG; + bit = chunk % BITS_PER_LONG; + for (;;) { + if (sector >= bs->total_sectors) { + sector = 0; + bit = elem = 0; + } + if (bit == 0 && bs->dirty_bitmap[elem] == 0) { + sector += BDRV_SECTORS_PER_DIRTY_CHUNK * BITS_PER_LONG; + elem++; + } else { + if (bs->dirty_bitmap[elem] & (1UL << bit)) { + return sector; + } + sector += BDRV_SECTORS_PER_DIRTY_CHUNK; + if (++bit == BITS_PER_LONG) { + bit = 0; + elem++; + } + } + } +} + +void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, + int nr_sectors) +{ + set_dirty_bitmap(bs, cur_sector, nr_sectors, 1); +} + void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors) { diff --git a/block.h b/block.h index 096fa09373..27b8f80bc6 100644 --- a/block.h +++ b/block.h @@ -353,8 +353,9 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size); void bdrv_set_dirty_tracking(BlockDriverState *bs, int enable); int bdrv_get_dirty(BlockDriverState *bs, int64_t sector); -void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, - int nr_sectors); +void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors); +void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors); +int64_t bdrv_get_next_dirty(BlockDriverState *bs, int64_t sector); int64_t bdrv_get_dirty_count(BlockDriverState *bs); void bdrv_enable_copy_on_read(BlockDriverState *bs); From b9a9b3a4626aa099f829e2a6036bfaa0c8e47700 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 1 Aug 2012 15:23:44 +0200 Subject: [PATCH 1105/2270] block: export dirty bitmap information in query-block Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- block.c | 7 +++++++ qapi-schema.json | 18 +++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/block.c b/block.c index 2c3d3dadd9..ad5e2405e3 100644 --- a/block.c +++ b/block.c @@ -2837,6 +2837,13 @@ BlockInfo *bdrv_query_info(BlockDriverState *bs) info->io_status = bs->iostatus; } + if (bs->dirty_bitmap) { + info->has_dirty = true; + info->dirty = g_malloc0(sizeof(*info->dirty)); + info->dirty->count = bdrv_get_dirty_count(bs) * + BDRV_SECTORS_PER_DIRTY_CHUNK * BDRV_SECTOR_SIZE; + } + if (bs->drv) { info->has_inserted = true; info->inserted = g_malloc0(sizeof(*info->inserted)); diff --git a/qapi-schema.json b/qapi-schema.json index 36278cc8df..dfcbb674af 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -660,6 +660,18 @@ ## { 'enum': 'BlockDeviceIoStatus', 'data': [ 'ok', 'failed', 'nospace' ] } +## +# @BlockDirtyInfo: +# +# Block dirty bitmap information. +# +# @count: number of dirty bytes according to the dirty bitmap +# +# Since: 1.3 +## +{ 'type': 'BlockDirtyInfo', + 'data': {'count': 'int'} } + ## # @BlockInfo: # @@ -679,6 +691,9 @@ # @tray_open: #optional True if the device has a tray and it is open # (only present if removable is true) # +# @dirty: #optional dirty bitmap information (only present if the dirty +# bitmap is enabled) +# # @io-status: #optional @BlockDeviceIoStatus. Only present if the device # supports it and the VM is configured to stop on errors # @@ -690,7 +705,8 @@ { 'type': 'BlockInfo', 'data': {'device': 'str', 'type': 'str', 'removable': 'bool', 'locked': 'bool', '*inserted': 'BlockDeviceInfo', - '*tray_open': 'bool', '*io-status': 'BlockDeviceIoStatus'} } + '*tray_open': 'bool', '*io-status': 'BlockDeviceIoStatus', + '*dirty': 'BlockDirtyInfo' } } ## # @query-block: From 65f4632243f526958aa1f6b3911add98329c3796 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Oct 2012 16:49:20 +0200 Subject: [PATCH 1106/2270] block: rename block_job_complete to block_job_completed The imperative will be used for the QMP command. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- block/commit.c | 2 +- block/stream.c | 4 ++-- blockjob.c | 2 +- blockjob.h | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/block/commit.c b/block/commit.c index 13d9e82471..fae79582d4 100644 --- a/block/commit.c +++ b/block/commit.c @@ -160,7 +160,7 @@ exit_restore_reopen: bdrv_reopen(overlay_bs, s->orig_overlay_flags, NULL); } - block_job_complete(&s->common, ret); + block_job_completed(&s->common, ret); } static void commit_set_speed(BlockJob *job, int64_t speed, Error **errp) diff --git a/block/stream.c b/block/stream.c index 792665276e..0c0fc7a13b 100644 --- a/block/stream.c +++ b/block/stream.c @@ -86,7 +86,7 @@ static void coroutine_fn stream_run(void *opaque) s->common.len = bdrv_getlength(bs); if (s->common.len < 0) { - block_job_complete(&s->common, s->common.len); + block_job_completed(&s->common, s->common.len); return; } @@ -184,7 +184,7 @@ wait: } qemu_vfree(buf); - block_job_complete(&s->common, ret); + block_job_completed(&s->common, ret); } static void stream_set_speed(BlockJob *job, int64_t speed, Error **errp) diff --git a/blockjob.c b/blockjob.c index f55f55a193..b5c16f3766 100644 --- a/blockjob.c +++ b/blockjob.c @@ -71,7 +71,7 @@ void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs, return job; } -void block_job_complete(BlockJob *job, int ret) +void block_job_completed(BlockJob *job, int ret) { BlockDriverState *bs = job->bs; diff --git a/blockjob.h b/blockjob.h index 930cc3c46a..c2261a91f4 100644 --- a/blockjob.h +++ b/blockjob.h @@ -135,14 +135,14 @@ void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs, void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns); /** - * block_job_complete: + * block_job_completed: * @job: The job being completed. * @ret: The status code. * * Call the completion function that was registered at creation time, and * free @job. */ -void block_job_complete(BlockJob *job, int ret); +void block_job_completed(BlockJob *job, int ret); /** * block_job_set_speed: From aeae883baf2377b714a41529f94905046fa058f3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Oct 2012 16:49:21 +0200 Subject: [PATCH 1107/2270] block: add block-job-complete While streaming can be dropped as soon as it progressed through the whole image, mirroring needs to be completed manually for two reasons: 1) so that management knows exactly when the VM switches to the target; 2) because for other use cases such as replication, we may leave the operation running for the whole life of the virtual machine. Add a new block job command that manually completes background operations. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- blockdev.c | 13 +++++++++++++ blockjob.c | 10 ++++++++++ blockjob.h | 15 +++++++++++++++ hmp-commands.hx | 17 ++++++++++++++++- hmp.c | 10 ++++++++++ hmp.h | 1 + qapi-schema.json | 25 +++++++++++++++++++++++++ qerror.h | 3 +++ qmp-commands.hx | 5 +++++ trace-events | 1 + 10 files changed, 99 insertions(+), 1 deletion(-) diff --git a/blockdev.c b/blockdev.c index 46e4bbd8d9..02d3e0b698 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1266,6 +1266,19 @@ void qmp_block_job_resume(const char *device, Error **errp) block_job_resume(job); } +void qmp_block_job_complete(const char *device, Error **errp) +{ + BlockJob *job = find_block_job(device); + + if (!job) { + error_set(errp, QERR_BLOCK_JOB_NOT_ACTIVE, device); + return; + } + + trace_qmp_block_job_complete(job); + block_job_complete(job, errp); +} + static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs) { BlockJobInfoList **prev = opaque; diff --git a/blockjob.c b/blockjob.c index b5c16f3766..c93a0e0187 100644 --- a/blockjob.c +++ b/blockjob.c @@ -99,6 +99,16 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) job->speed = speed; } +void block_job_complete(BlockJob *job, Error **errp) +{ + if (job->paused || job->cancelled || !job->job_type->complete) { + error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name); + return; + } + + job->job_type->complete(job, errp); +} + void block_job_pause(BlockJob *job) { job->paused = true; diff --git a/blockjob.h b/blockjob.h index c2261a91f4..c44e2ea57b 100644 --- a/blockjob.h +++ b/blockjob.h @@ -41,6 +41,12 @@ typedef struct BlockJobType { /** Optional callback for job types that support setting a speed limit */ void (*set_speed)(BlockJob *job, int64_t speed, Error **errp); + + /** + * Optional callback for job types whose completion must be triggered + * manually. + */ + void (*complete)(BlockJob *job, Error **errp); } BlockJobType; /** @@ -163,6 +169,15 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp); */ void block_job_cancel(BlockJob *job); +/** + * block_job_complete: + * @job: The job to be completed. + * @errp: Error object. + * + * Asynchronously complete the specified job. + */ +void block_job_complete(BlockJob *job, Error **errp); + /** * block_job_is_cancelled: * @job: The job being queried. diff --git a/hmp-commands.hx b/hmp-commands.hx index e0b537d0cc..fb2f2372c0 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -109,7 +109,22 @@ ETEXI STEXI @item block_job_cancel @findex block_job_cancel -Stop an active block streaming operation. +Stop an active background block operation (streaming, mirroring). +ETEXI + + { + .name = "block_job_complete", + .args_type = "device:B", + .params = "device", + .help = "stop an active background block operation", + .mhandler.cmd = hmp_block_job_complete, + }, + +STEXI +@item block_job_complete +@findex block_job_complete +Manually trigger completion of an active background block operation. +For mirroring, this will switch the device to the destination path. ETEXI { diff --git a/hmp.c b/hmp.c index 2b979826ee..574517a17f 100644 --- a/hmp.c +++ b/hmp.c @@ -990,6 +990,16 @@ void hmp_block_job_resume(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, &error); } +void hmp_block_job_complete(Monitor *mon, const QDict *qdict) +{ + Error *error = NULL; + const char *device = qdict_get_str(qdict, "device"); + + qmp_block_job_complete(device, &error); + + hmp_handle_error(mon, &error); +} + typedef struct MigrationStatus { QEMUTimer *timer; diff --git a/hmp.h b/hmp.h index 71ea384523..7bdd23c23f 100644 --- a/hmp.h +++ b/hmp.h @@ -66,6 +66,7 @@ void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict); void hmp_block_job_cancel(Monitor *mon, const QDict *qdict); void hmp_block_job_pause(Monitor *mon, const QDict *qdict); void hmp_block_job_resume(Monitor *mon, const QDict *qdict); +void hmp_block_job_complete(Monitor *mon, const QDict *qdict); void hmp_migrate(Monitor *mon, const QDict *qdict); void hmp_device_del(Monitor *mon, const QDict *qdict); void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict); diff --git a/qapi-schema.json b/qapi-schema.json index dfcbb674af..9482976943 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2032,6 +2032,31 @@ ## { 'command': 'block-job-resume', 'data': { 'device': 'str' } } +## +# @block-job-complete: +# +# Manually trigger completion of an active background block operation. This +# is supported for drive mirroring, where it also switches the device to +# write to the target path only. +# +# This command completes an active background block operation synchronously. +# The ordering of this command's return with the BLOCK_JOB_COMPLETED event +# is not defined. Note that if an I/O error occurs during the processing of +# this command: 1) the command itself will fail; 2) the error will be processed +# according to the rerror/werror arguments that were specified when starting +# the operation. +# +# A cancelled or paused job cannot be completed. +# +# @device: the device name +# +# Returns: Nothing on success +# If no background operation is active on this device, DeviceNotActive +# +# Since: 1.3 +## +{ 'command': 'block-job-complete', 'data': { 'device': 'str' } } + ## # @ObjectTypeInfo: # diff --git a/qerror.h b/qerror.h index c91708cc3c..dacac52cf4 100644 --- a/qerror.h +++ b/qerror.h @@ -54,6 +54,9 @@ void assert_no_error(Error *err); #define QERR_BLOCK_JOB_PAUSED \ ERROR_CLASS_GENERIC_ERROR, "The block job for device '%s' is currently paused" +#define QERR_BLOCK_JOB_NOT_READY \ + ERROR_CLASS_GENERIC_ERROR, "The active block job for device '%s' cannot be completed" + #define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \ ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by device '%s' does not support feature '%s'" diff --git a/qmp-commands.hx b/qmp-commands.hx index 5ba8c48cb4..4f9c711585 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -842,6 +842,11 @@ EQMP .args_type = "device:B", .mhandler.cmd_new = qmp_marshal_input_block_job_resume, }, + { + .name = "block-job-complete", + .args_type = "device:B", + .mhandler.cmd_new = qmp_marshal_input_block_job_complete, + }, { .name = "transaction", .args_type = "actions:q", diff --git a/trace-events b/trace-events index e2d4580d4c..9ab8e2781a 100644 --- a/trace-events +++ b/trace-events @@ -81,6 +81,7 @@ commit_start(void *bs, void *base, void *top, void *s, void *co, void *opaque) " qmp_block_job_cancel(void *job) "job %p" qmp_block_job_pause(void *job) "job %p" qmp_block_job_resume(void *job) "job %p" +qmp_block_job_complete(void *job) "job %p" block_job_cb(void *bs, void *job, int ret) "bs %p job %p ret %d" qmp_block_stream(void *bs, void *job) "bs %p job %p" From a66a2a368383e627b929bf42d1b972822491404b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Jul 2012 15:15:47 +0200 Subject: [PATCH 1108/2270] block: introduce BLOCK_JOB_READY event Even for jobs that need to be manually completed, management may want to take care itself of the completion, not requiring the user to issue a command to terminate the job. In this case we want to avoid that they poll us continuously, waiting for completion to become available. Thus, add a new event that signals the phase switch and the availability of the block-job-complete command. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- QMP/qmp-events.txt | 18 ++++++++++++++++++ blockdev.c | 14 -------------- blockjob.c | 21 +++++++++++++++++++++ blockjob.h | 16 ++++++++++++++++ monitor.c | 1 + monitor.h | 1 + qapi-schema.json | 3 ++- 7 files changed, 59 insertions(+), 15 deletions(-) diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt index 987c5756b3..b2698e4153 100644 --- a/QMP/qmp-events.txt +++ b/QMP/qmp-events.txt @@ -118,6 +118,24 @@ Example: "action": "stop" }, "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +BLOCK_JOB_READY +--------------- + +Emitted when a block job is ready to complete. + +Data: + +- "device": device name (json-string) + +Example: + +{ "event": "BLOCK_JOB_READY", + "data": { "device": "ide0-hd1" }, + "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } + +Note: The "ready to complete" status is always reset by a BLOCK_JOB_ERROR +event. + DEVICE_TRAY_MOVED ----------------- diff --git a/blockdev.c b/blockdev.c index 02d3e0b698..248d5f62c0 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1056,20 +1056,6 @@ void qmp_block_resize(const char *device, int64_t size, Error **errp) } } -static QObject *qobject_from_block_job(BlockJob *job) -{ - return qobject_from_jsonf("{ 'type': %s," - "'device': %s," - "'len': %" PRId64 "," - "'offset': %" PRId64 "," - "'speed': %" PRId64 " }", - job->job_type->job_type, - bdrv_get_device_name(job->bs), - job->len, - job->offset, - job->speed); -} - static void block_job_cb(void *opaque, int ret) { BlockDriverState *bs = opaque; diff --git a/blockjob.c b/blockjob.c index c93a0e0187..fbb7e1cd58 100644 --- a/blockjob.c +++ b/blockjob.c @@ -225,6 +225,27 @@ static void block_job_iostatus_set_err(BlockJob *job, int error) } +QObject *qobject_from_block_job(BlockJob *job) +{ + return qobject_from_jsonf("{ 'type': %s," + "'device': %s," + "'len': %" PRId64 "," + "'offset': %" PRId64 "," + "'speed': %" PRId64 " }", + job->job_type->job_type, + bdrv_get_device_name(job->bs), + job->len, + job->offset, + job->speed); +} + +void block_job_ready(BlockJob *job) +{ + QObject *data = qobject_from_block_job(job); + monitor_protocol_event(QEVENT_BLOCK_JOB_READY, data); + qobject_decref(data); +} + BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs, BlockdevOnError on_err, int is_read, int error) diff --git a/blockjob.h b/blockjob.h index c44e2ea57b..fb2392efc0 100644 --- a/blockjob.h +++ b/blockjob.h @@ -210,6 +210,22 @@ void block_job_pause(BlockJob *job); */ void block_job_resume(BlockJob *job); +/** + * qobject_from_block_job: + * @job: The job whose information is requested. + * + * Return a QDict corresponding to @job's query-block-jobs entry. + */ +QObject *qobject_from_block_job(BlockJob *job); + +/** + * block_job_ready: + * @job: The job which is now ready to complete. + * + * Send a BLOCK_JOB_READY event for the specified job. + */ +void block_job_ready(BlockJob *job); + /** * block_job_is_paused: * @job: The job being queried. diff --git a/monitor.c b/monitor.c index 1d3dd9aac1..eeef32e38b 100644 --- a/monitor.c +++ b/monitor.c @@ -451,6 +451,7 @@ static const char *monitor_event_names[] = { [QEVENT_BLOCK_JOB_COMPLETED] = "BLOCK_JOB_COMPLETED", [QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED", [QEVENT_BLOCK_JOB_ERROR] = "BLOCK_JOB_ERROR", + [QEVENT_BLOCK_JOB_READY] = "BLOCK_JOB_READY", [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED", [QEVENT_SUSPEND] = "SUSPEND", [QEVENT_SUSPEND_DISK] = "SUSPEND_DISK", diff --git a/monitor.h b/monitor.h index d4c017e496..b4ef9559dc 100644 --- a/monitor.h +++ b/monitor.h @@ -39,6 +39,7 @@ typedef enum MonitorEvent { QEVENT_BLOCK_JOB_COMPLETED, QEVENT_BLOCK_JOB_CANCELLED, QEVENT_BLOCK_JOB_ERROR, + QEVENT_BLOCK_JOB_READY, QEVENT_DEVICE_TRAY_MOVED, QEVENT_SUSPEND, QEVENT_SUSPEND_DISK, diff --git a/qapi-schema.json b/qapi-schema.json index 9482976943..37bbecab60 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2037,7 +2037,8 @@ # # Manually trigger completion of an active background block operation. This # is supported for drive mirroring, where it also switches the device to -# write to the target path only. +# write to the target path only. The ability to complete is signaled with +# a BLOCK_JOB_READY event. # # This command completes an active background block operation synchronously. # The ordering of this command's return with the BLOCK_JOB_COMPLETED event From 893f7ebafe4e8afc0ce4dbd9e64b3752f3036bbb Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Oct 2012 16:49:23 +0200 Subject: [PATCH 1109/2270] mirror: introduce mirror job This patch adds the implementation of a new job that mirrors a disk to a new image while letting the guest continue using the old image. The target is treated as a "black box" and data is copied from the source to the target in the background. This can be used for several purposes, including storage migration, continuous replication, and observation of the guest I/O in an external program. It is also a first step in replacing the inefficient block migration code that is part of QEMU. The job is possibly never-ending, but it is logically structured into two phases: 1) copy all data as fast as possible until the target first gets in sync with the source; 2) keep target in sync and ensure that reopening to the target gets a correct (full) copy of the source data. The second phase is indicated by the progress in "info block-jobs" reporting the current offset to be equal to the length of the file. When the job is cancelled in the second phase, QEMU will run the job until the source is clean and quiescent, then it will report successful completion of the job. In other words, the BLOCK_JOB_CANCELLED event means that the target may _not_ be consistent with a past state of the source; the BLOCK_JOB_COMPLETED event means that the target is consistent with a past state of the source. (Note that it could already happen that management lost the race against QEMU and got a completion event instead of cancellation). It is not yet possible to complete the job and switch over to the target disk. The next patches will fix this and add many refinements to the basic idea introduced here. These include improved error management, some tunable knobs and performance optimizations. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- block/Makefile.objs | 1 + block/mirror.c | 235 ++++++++++++++++++++++++++++++++++++++++++++ block_int.h | 20 ++++ qapi-schema.json | 17 ++++ trace-events | 7 ++ 5 files changed, 280 insertions(+) create mode 100644 block/mirror.c diff --git a/block/Makefile.objs b/block/Makefile.objs index 554f429d05..806e526eb4 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -12,3 +12,4 @@ block-obj-$(CONFIG_GLUSTERFS) += gluster.o common-obj-y += stream.o common-obj-y += commit.o +common-obj-y += mirror.o diff --git a/block/mirror.c b/block/mirror.c new file mode 100644 index 0000000000..b353798e8f --- /dev/null +++ b/block/mirror.c @@ -0,0 +1,235 @@ +/* + * Image mirroring + * + * Copyright Red Hat, Inc. 2012 + * + * Authors: + * Paolo Bonzini + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "trace.h" +#include "blockjob.h" +#include "block_int.h" +#include "qemu/ratelimit.h" + +enum { + /* + * Size of data buffer for populating the image file. This should be large + * enough to process multiple clusters in a single call, so that populating + * contiguous regions of the image is efficient. + */ + BLOCK_SIZE = 512 * BDRV_SECTORS_PER_DIRTY_CHUNK, /* in bytes */ +}; + +#define SLICE_TIME 100000000ULL /* ns */ + +typedef struct MirrorBlockJob { + BlockJob common; + RateLimit limit; + BlockDriverState *target; + MirrorSyncMode mode; + int64_t sector_num; + uint8_t *buf; +} MirrorBlockJob; + +static int coroutine_fn mirror_iteration(MirrorBlockJob *s) +{ + BlockDriverState *source = s->common.bs; + BlockDriverState *target = s->target; + QEMUIOVector qiov; + int ret, nb_sectors; + int64_t end; + struct iovec iov; + + end = s->common.len >> BDRV_SECTOR_BITS; + s->sector_num = bdrv_get_next_dirty(source, s->sector_num); + nb_sectors = MIN(BDRV_SECTORS_PER_DIRTY_CHUNK, end - s->sector_num); + bdrv_reset_dirty(source, s->sector_num, nb_sectors); + + /* Copy the dirty cluster. */ + iov.iov_base = s->buf; + iov.iov_len = nb_sectors * 512; + qemu_iovec_init_external(&qiov, &iov, 1); + + trace_mirror_one_iteration(s, s->sector_num, nb_sectors); + ret = bdrv_co_readv(source, s->sector_num, nb_sectors, &qiov); + if (ret < 0) { + return ret; + } + return bdrv_co_writev(target, s->sector_num, nb_sectors, &qiov); +} + +static void coroutine_fn mirror_run(void *opaque) +{ + MirrorBlockJob *s = opaque; + BlockDriverState *bs = s->common.bs; + int64_t sector_num, end; + int ret = 0; + int n; + bool synced = false; + + if (block_job_is_cancelled(&s->common)) { + goto immediate_exit; + } + + s->common.len = bdrv_getlength(bs); + if (s->common.len < 0) { + block_job_completed(&s->common, s->common.len); + return; + } + + end = s->common.len >> BDRV_SECTOR_BITS; + s->buf = qemu_blockalign(bs, BLOCK_SIZE); + + if (s->mode != MIRROR_SYNC_MODE_NONE) { + /* First part, loop on the sectors and initialize the dirty bitmap. */ + BlockDriverState *base; + base = s->mode == MIRROR_SYNC_MODE_FULL ? NULL : bs->backing_hd; + for (sector_num = 0; sector_num < end; ) { + int64_t next = (sector_num | (BDRV_SECTORS_PER_DIRTY_CHUNK - 1)) + 1; + ret = bdrv_co_is_allocated_above(bs, base, + sector_num, next - sector_num, &n); + + if (ret < 0) { + goto immediate_exit; + } + + assert(n > 0); + if (ret == 1) { + bdrv_set_dirty(bs, sector_num, n); + sector_num = next; + } else { + sector_num += n; + } + } + } + + s->sector_num = -1; + for (;;) { + uint64_t delay_ns; + int64_t cnt; + bool should_complete; + + cnt = bdrv_get_dirty_count(bs); + if (cnt != 0) { + ret = mirror_iteration(s); + if (ret < 0) { + goto immediate_exit; + } + cnt = bdrv_get_dirty_count(bs); + } + + should_complete = false; + if (cnt == 0) { + trace_mirror_before_flush(s); + ret = bdrv_flush(s->target); + if (ret < 0) { + goto immediate_exit; + } + + /* We're out of the streaming phase. From now on, if the job + * is cancelled we will actually complete all pending I/O and + * report completion. This way, block-job-cancel will leave + * the target in a consistent state. + */ + synced = true; + s->common.offset = end * BDRV_SECTOR_SIZE; + should_complete = block_job_is_cancelled(&s->common); + cnt = bdrv_get_dirty_count(bs); + } + + if (cnt == 0 && should_complete) { + /* The dirty bitmap is not updated while operations are pending. + * If we're about to exit, wait for pending operations before + * calling bdrv_get_dirty_count(bs), or we may exit while the + * source has dirty data to copy! + * + * Note that I/O can be submitted by the guest while + * mirror_populate runs. + */ + trace_mirror_before_drain(s, cnt); + bdrv_drain_all(); + cnt = bdrv_get_dirty_count(bs); + } + + ret = 0; + trace_mirror_before_sleep(s, cnt, synced); + if (!synced) { + /* Publish progress */ + s->common.offset = end * BDRV_SECTOR_SIZE - cnt * BLOCK_SIZE; + + if (s->common.speed) { + delay_ns = ratelimit_calculate_delay(&s->limit, BDRV_SECTORS_PER_DIRTY_CHUNK); + } else { + delay_ns = 0; + } + + /* Note that even when no rate limit is applied we need to yield + * with no pending I/O here so that qemu_aio_flush() returns. + */ + block_job_sleep_ns(&s->common, rt_clock, delay_ns); + if (block_job_is_cancelled(&s->common)) { + break; + } + } else if (!should_complete) { + delay_ns = (cnt == 0 ? SLICE_TIME : 0); + block_job_sleep_ns(&s->common, rt_clock, delay_ns); + } else if (cnt == 0) { + /* The two disks are in sync. Exit and report successful + * completion. + */ + assert(QLIST_EMPTY(&bs->tracked_requests)); + s->common.cancelled = false; + break; + } + } + +immediate_exit: + g_free(s->buf); + bdrv_set_dirty_tracking(bs, false); + bdrv_close(s->target); + bdrv_delete(s->target); + block_job_completed(&s->common, ret); +} + +static void mirror_set_speed(BlockJob *job, int64_t speed, Error **errp) +{ + MirrorBlockJob *s = container_of(job, MirrorBlockJob, common); + + if (speed < 0) { + error_set(errp, QERR_INVALID_PARAMETER, "speed"); + return; + } + ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE, SLICE_TIME); +} + +static BlockJobType mirror_job_type = { + .instance_size = sizeof(MirrorBlockJob), + .job_type = "mirror", + .set_speed = mirror_set_speed, +}; + +void mirror_start(BlockDriverState *bs, BlockDriverState *target, + int64_t speed, MirrorSyncMode mode, + BlockDriverCompletionFunc *cb, + void *opaque, Error **errp) +{ + MirrorBlockJob *s; + + s = block_job_create(&mirror_job_type, bs, speed, cb, opaque, errp); + if (!s) { + return; + } + + s->target = target; + s->mode = mode; + bdrv_set_dirty_tracking(bs, true); + bdrv_set_enable_write_cache(s->target, true); + s->common.co = qemu_coroutine_create(mirror_run); + trace_mirror_start(bs, s, s->common.co, opaque); + qemu_coroutine_enter(s->common.co, s); +} diff --git a/block_int.h b/block_int.h index f4bae04401..aaa46a83b0 100644 --- a/block_int.h +++ b/block_int.h @@ -331,4 +331,24 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base, BlockdevOnError on_error, BlockDriverCompletionFunc *cb, void *opaque, Error **errp); +/* + * mirror_start: + * @bs: Block device to operate on. + * @target: Block device to write to. + * @speed: The maximum speed, in bytes per second, or 0 for unlimited. + * @mode: Whether to collapse all images in the chain to the target. + * @cb: Completion function for the job. + * @opaque: Opaque pointer value passed to @cb. + * @errp: Error object. + * + * Start a mirroring operation on @bs. Clusters that are allocated + * in @bs will be written to @bs until the job is cancelled or + * manually completed. At the end of a successful mirroring job, + * @bs will be switched to read from @target. + */ +void mirror_start(BlockDriverState *bs, BlockDriverState *target, + int64_t speed, MirrorSyncMode mode, + BlockDriverCompletionFunc *cb, + void *opaque, Error **errp); + #endif /* BLOCK_INT_H */ diff --git a/qapi-schema.json b/qapi-schema.json index 37bbecab60..8c4b7c808b 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1165,6 +1165,23 @@ { 'enum': 'BlockdevOnError', 'data': ['report', 'ignore', 'enospc', 'stop'] } +## +# @MirrorSyncMode: +# +# An enumeration of possible behaviors for the initial synchronization +# phase of storage mirroring. +# +# @top: copies data in the topmost image to the destination +# +# @full: copies data from all images to the destination +# +# @none: only copy data written from now on +# +# Since: 1.3 +## +{ 'enum': 'MirrorSyncMode', + 'data': ['top', 'full', 'none'] } + ## # @BlockJobInfo: # diff --git a/trace-events b/trace-events index 9ab8e2781a..09b5d558c6 100644 --- a/trace-events +++ b/trace-events @@ -77,6 +77,13 @@ stream_start(void *bs, void *base, void *s, void *co, void *opaque) "bs %p base commit_one_iteration(void *s, int64_t sector_num, int nb_sectors, int is_allocated) "s %p sector_num %"PRId64" nb_sectors %d is_allocated %d" commit_start(void *bs, void *base, void *top, void *s, void *co, void *opaque) "bs %p base %p top %p s %p co %p opaque %p" +# block/mirror.c +mirror_start(void *bs, void *s, void *co, void *opaque) "bs %p s %p co %p opaque %p" +mirror_before_flush(void *s) "s %p" +mirror_before_drain(void *s, int64_t cnt) "s %p dirty count %"PRId64 +mirror_before_sleep(void *s, int64_t cnt, int synced) "s %p dirty count %"PRId64" synced %d" +mirror_one_iteration(void *s, int64_t sector_num, int nb_sectors) "s %p sector_num %"PRId64" nb_sectors %d" + # blockdev.c qmp_block_job_cancel(void *job) "job %p" qmp_block_job_pause(void *job) "job %p" From d9b902db3fb71fdcdfbb2aa9cc94a410dee864e5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Oct 2012 16:49:24 +0200 Subject: [PATCH 1110/2270] qmp: add drive-mirror command This adds the monitor commands that start the mirroring job. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- blockdev.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++ hmp-commands.hx | 21 ++++++++ hmp.c | 28 +++++++++++ hmp.h | 1 + qapi-schema.json | 34 +++++++++++++ qmp-commands.hx | 42 ++++++++++++++++ 6 files changed, 250 insertions(+) diff --git a/blockdev.c b/blockdev.c index 248d5f62c0..431c678f8f 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1181,6 +1181,130 @@ void qmp_block_commit(const char *device, drive_get_ref(drive_get_by_blockdev(bs)); } +void qmp_drive_mirror(const char *device, const char *target, + bool has_format, const char *format, + enum MirrorSyncMode sync, + bool has_mode, enum NewImageMode mode, + bool has_speed, int64_t speed, Error **errp) +{ + BlockDriverInfo bdi; + BlockDriverState *bs; + BlockDriverState *source, *target_bs; + BlockDriver *proto_drv; + BlockDriver *drv = NULL; + Error *local_err = NULL; + int flags; + uint64_t size; + int ret; + + if (!has_speed) { + speed = 0; + } + if (!has_mode) { + mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; + } + + bs = bdrv_find(device); + if (!bs) { + error_set(errp, QERR_DEVICE_NOT_FOUND, device); + return; + } + + if (!bdrv_is_inserted(bs)) { + error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); + return; + } + + if (!has_format) { + format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs->drv->format_name; + } + if (format) { + drv = bdrv_find_format(format); + if (!drv) { + error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); + return; + } + } + + if (bdrv_in_use(bs)) { + error_set(errp, QERR_DEVICE_IN_USE, device); + return; + } + + flags = bs->open_flags | BDRV_O_RDWR; + source = bs->backing_hd; + if (!source && sync == MIRROR_SYNC_MODE_TOP) { + sync = MIRROR_SYNC_MODE_FULL; + } + + proto_drv = bdrv_find_protocol(target); + if (!proto_drv) { + error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); + return; + } + + if (sync == MIRROR_SYNC_MODE_FULL && mode != NEW_IMAGE_MODE_EXISTING) { + /* create new image w/o backing file */ + assert(format && drv); + bdrv_get_geometry(bs, &size); + size *= 512; + ret = bdrv_img_create(target, format, + NULL, NULL, NULL, size, flags); + } else { + switch (mode) { + case NEW_IMAGE_MODE_EXISTING: + ret = 0; + break; + case NEW_IMAGE_MODE_ABSOLUTE_PATHS: + /* create new image with backing file */ + ret = bdrv_img_create(target, format, + source->filename, + source->drv->format_name, + NULL, -1, flags); + break; + default: + abort(); + } + } + + if (ret) { + error_set(errp, QERR_OPEN_FILE_FAILED, target); + return; + } + + target_bs = bdrv_new(""); + ret = bdrv_open(target_bs, target, flags | BDRV_O_NO_BACKING, drv); + + if (ret < 0) { + bdrv_delete(target_bs); + error_set(errp, QERR_OPEN_FILE_FAILED, target); + return; + } + + /* We need a backing file if we will copy parts of a cluster. */ + if (bdrv_get_info(target_bs, &bdi) >= 0 && bdi.cluster_size != 0 && + bdi.cluster_size >= BDRV_SECTORS_PER_DIRTY_CHUNK * 512) { + ret = bdrv_open_backing_file(target_bs); + if (ret < 0) { + bdrv_delete(target_bs); + error_set(errp, QERR_OPEN_FILE_FAILED, target); + return; + } + } + + mirror_start(bs, target_bs, speed, sync, block_job_cb, bs, &local_err); + if (local_err != NULL) { + bdrv_delete(target_bs); + error_propagate(errp, local_err); + return; + } + + /* Grab a reference so hotplug does not delete the BlockDriverState from + * underneath us. + */ + drive_get_ref(drive_get_by_blockdev(bs)); +} + static BlockJob *find_block_job(const char *device) { BlockDriverState *bs; diff --git a/hmp-commands.hx b/hmp-commands.hx index fb2f2372c0..f916385c0a 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1001,6 +1001,27 @@ STEXI @item snapshot_blkdev @findex snapshot_blkdev Snapshot device, using snapshot file as target if provided +ETEXI + + { + .name = "drive_mirror", + .args_type = "reuse:-n,full:-f,device:B,target:s,format:s?", + .params = "[-n] [-f] device target [format]", + .help = "initiates live storage\n\t\t\t" + "migration for a device. The device's contents are\n\t\t\t" + "copied to the new image file, including data that\n\t\t\t" + "is written after the command is started.\n\t\t\t" + "The -n flag requests QEMU to reuse the image found\n\t\t\t" + "in new-image-file, instead of recreating it from scratch.\n\t\t\t" + "The -f flag requests QEMU to copy the whole disk,\n\t\t\t" + "so that the result does not need a backing file.\n\t\t\t", + .mhandler.cmd = hmp_drive_mirror, + }, +STEXI +@item drive_mirror +@findex drive_mirror +Start mirroring a block device's writes to a new destination, +using the specified target. ETEXI { diff --git a/hmp.c b/hmp.c index 574517a17f..e53025306a 100644 --- a/hmp.c +++ b/hmp.c @@ -771,6 +771,34 @@ void hmp_block_resize(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, &errp); } +void hmp_drive_mirror(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *filename = qdict_get_str(qdict, "target"); + const char *format = qdict_get_try_str(qdict, "format"); + int reuse = qdict_get_try_bool(qdict, "reuse", 0); + int full = qdict_get_try_bool(qdict, "full", 0); + enum NewImageMode mode; + Error *errp = NULL; + + if (!filename) { + error_set(&errp, QERR_MISSING_PARAMETER, "target"); + hmp_handle_error(mon, &errp); + return; + } + + if (reuse) { + mode = NEW_IMAGE_MODE_EXISTING; + } else { + mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; + } + + qmp_drive_mirror(device, filename, !!format, format, + full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP, + true, mode, false, 0, &errp); + hmp_handle_error(mon, &errp); +} + void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict) { const char *device = qdict_get_str(qdict, "device"); diff --git a/hmp.h b/hmp.h index 7bdd23c23f..34eb2b36f3 100644 --- a/hmp.h +++ b/hmp.h @@ -51,6 +51,7 @@ void hmp_block_passwd(Monitor *mon, const QDict *qdict); void hmp_balloon(Monitor *mon, const QDict *qdict); void hmp_block_resize(Monitor *mon, const QDict *qdict); void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict); +void hmp_drive_mirror(Monitor *mon, const QDict *qdict); void hmp_migrate_cancel(Monitor *mon, const QDict *qdict); void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict); void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict); diff --git a/qapi-schema.json b/qapi-schema.json index 8c4b7c808b..a066cd5ca2 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1606,6 +1606,40 @@ 'data': { 'device': 'str', '*base': 'str', 'top': 'str', '*speed': 'int' } } +## +# @drive-mirror +# +# Start mirroring a block device's writes to a new destination. +# +# @device: the name of the device whose writes should be mirrored. +# +# @target: the target of the new image. If the file exists, or if it +# is a device, the existing file/device will be used as the new +# destination. If it does not exist, a new file will be created. +# +# @format: #optional the format of the new destination, default is to +# probe if @mode is 'existing', else the format of the source +# +# @mode: #optional whether and how QEMU should create a new image, default is +# 'absolute-paths'. +# +# @speed: #optional the maximum speed, in bytes per second +# +# @sync: what parts of the disk image should be copied to the destination +# (all the disk, only the sectors allocated in the topmost image, or +# only new I/O). +# +# Returns: nothing on success +# If @device is not a valid block device, DeviceNotFound +# +# Since 1.3 +## +{ 'command': 'drive-mirror', + 'data': { 'device': 'str', 'target': 'str', '*format': 'str', + 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode', + '*speed': 'int' } } + +## # @migrate_cancel # # Cancel the current executing migration process. diff --git a/qmp-commands.hx b/qmp-commands.hx index 4f9c711585..614baea784 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -933,6 +933,48 @@ Example: "format": "qcow2" } } <- { "return": {} } +EQMP + + { + .name = "drive-mirror", + .args_type = "sync:s,device:B,target:s,speed:i?,mode:s?,format:s?", + .mhandler.cmd_new = qmp_marshal_input_drive_mirror, + }, + +SQMP +drive-mirror +------------ + +Start mirroring a block device's writes to a new destination. target +specifies the target of the new image. If the file exists, or if it is +a device, it will be used as the new destination for writes. If it does not +exist, a new file will be created. format specifies the format of the +mirror image, default is to probe if mode='existing', else the format +of the source. + +Arguments: + +- "device": device name to operate on (json-string) +- "target": name of new image file (json-string) +- "format": format of new image (json-string, optional) +- "mode": how an image file should be created into the target + file/device (NewImageMode, optional, default 'absolute-paths') +- "speed": maximum speed of the streaming job, in bytes per second + (json-int) +- "sync": what parts of the disk image should be copied to the destination; + possibilities include "full" for all the disk, "top" for only the sectors + allocated in the topmost image, or "none" to only replicate new I/O + (MirrorSyncMode). + + +Example: + +-> { "execute": "drive-mirror", "arguments": { "device": "ide-hd0", + "target": "/some/place/my-image", + "sync": "full", + "format": "qcow2" } } +<- { "return": {} } + EQMP { From d63ffd87acad618a4a64b8812b64ad88577ae9b1 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Oct 2012 16:49:25 +0200 Subject: [PATCH 1111/2270] mirror: implement completion Switching to the target of the migration is done mostly asynchronously, and reported to management via the BLOCK_JOB_COMPLETED event; the only synchronous phase is opening the backing files. bdrv_open_backing_file can always be done, even for migration of the full image (aka sync: 'full'). In this case, qmp_drive_mirror will create the target disk with no backing file at all, and bdrv_open_backing_file will be a no-op. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- block/mirror.c | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index b353798e8f..6320f6a2e5 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -32,6 +32,8 @@ typedef struct MirrorBlockJob { RateLimit limit; BlockDriverState *target; MirrorSyncMode mode; + bool synced; + bool should_complete; int64_t sector_num; uint8_t *buf; } MirrorBlockJob; @@ -70,7 +72,6 @@ static void coroutine_fn mirror_run(void *opaque) int64_t sector_num, end; int ret = 0; int n; - bool synced = false; if (block_job_is_cancelled(&s->common)) { goto immediate_exit; @@ -136,9 +137,14 @@ static void coroutine_fn mirror_run(void *opaque) * report completion. This way, block-job-cancel will leave * the target in a consistent state. */ - synced = true; s->common.offset = end * BDRV_SECTOR_SIZE; - should_complete = block_job_is_cancelled(&s->common); + if (!s->synced) { + block_job_ready(&s->common); + s->synced = true; + } + + should_complete = s->should_complete || + block_job_is_cancelled(&s->common); cnt = bdrv_get_dirty_count(bs); } @@ -157,8 +163,8 @@ static void coroutine_fn mirror_run(void *opaque) } ret = 0; - trace_mirror_before_sleep(s, cnt, synced); - if (!synced) { + trace_mirror_before_sleep(s, cnt, s->synced); + if (!s->synced) { /* Publish progress */ s->common.offset = end * BDRV_SECTOR_SIZE - cnt * BLOCK_SIZE; @@ -191,6 +197,12 @@ static void coroutine_fn mirror_run(void *opaque) immediate_exit: g_free(s->buf); bdrv_set_dirty_tracking(bs, false); + if (s->should_complete && ret == 0) { + if (bdrv_get_flags(s->target) != bdrv_get_flags(s->common.bs)) { + bdrv_reopen(s->target, bdrv_get_flags(s->common.bs), NULL); + } + bdrv_swap(s->target, s->common.bs); + } bdrv_close(s->target); bdrv_delete(s->target); block_job_completed(&s->common, ret); @@ -207,10 +219,33 @@ static void mirror_set_speed(BlockJob *job, int64_t speed, Error **errp) ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE, SLICE_TIME); } +static void mirror_complete(BlockJob *job, Error **errp) +{ + MirrorBlockJob *s = container_of(job, MirrorBlockJob, common); + int ret; + + ret = bdrv_open_backing_file(s->target); + if (ret < 0) { + char backing_filename[PATH_MAX]; + bdrv_get_full_backing_filename(s->target, backing_filename, + sizeof(backing_filename)); + error_set(errp, QERR_OPEN_FILE_FAILED, backing_filename); + return; + } + if (!s->synced) { + error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name); + return; + } + + s->should_complete = true; + block_job_resume(job); +} + static BlockJobType mirror_job_type = { .instance_size = sizeof(MirrorBlockJob), .job_type = "mirror", .set_speed = mirror_set_speed, + .complete = mirror_complete, }; void mirror_start(BlockDriverState *bs, BlockDriverState *target, From 44c7ca5ebfb20c8086ac78f72a1bc6566828f956 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 23 Oct 2012 16:39:22 +0200 Subject: [PATCH 1112/2270] qemu-iotests: add mirroring test case Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- tests/qemu-iotests/041 | 362 +++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/041.out | 5 + tests/qemu-iotests/group | 1 + 3 files changed, 368 insertions(+) create mode 100755 tests/qemu-iotests/041 create mode 100644 tests/qemu-iotests/041.out diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 new file mode 100755 index 0000000000..fd9760a1d9 --- /dev/null +++ b/tests/qemu-iotests/041 @@ -0,0 +1,362 @@ +#!/usr/bin/env python +# +# Tests for image mirroring. +# +# Copyright (C) 2012 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 . +# + +import time +import os +import iotests +from iotests import qemu_img, qemu_io +import struct + +backing_img = os.path.join(iotests.test_dir, 'backing.img') +target_backing_img = os.path.join(iotests.test_dir, 'target-backing.img') +test_img = os.path.join(iotests.test_dir, 'test.img') +target_img = os.path.join(iotests.test_dir, 'target.img') + +class ImageMirroringTestCase(iotests.QMPTestCase): + '''Abstract base class for image mirroring test cases''' + + def assert_no_active_mirrors(self): + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return', []) + + def cancel_and_wait(self, drive='drive0', wait_ready=True): + '''Cancel a block job and wait for it to finish''' + if wait_ready: + ready = False + while not ready: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_READY': + self.assert_qmp(event, 'data/type', 'mirror') + self.assert_qmp(event, 'data/device', drive) + ready = True + + result = self.vm.qmp('block-job-cancel', device=drive, + force=not wait_ready) + self.assert_qmp(result, 'return', {}) + + cancelled = False + while not cancelled: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_COMPLETED' or \ + event['event'] == 'BLOCK_JOB_CANCELLED': + self.assert_qmp(event, 'data/type', 'mirror') + self.assert_qmp(event, 'data/device', drive) + if wait_ready: + self.assertEquals(event['event'], 'BLOCK_JOB_COMPLETED') + self.assert_qmp(event, 'data/offset', self.image_len) + self.assert_qmp(event, 'data/len', self.image_len) + cancelled = True + + self.assert_no_active_mirrors() + + def complete_and_wait(self, drive='drive0', wait_ready=True): + '''Complete a block job and wait for it to finish''' + if wait_ready: + ready = False + while not ready: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_READY': + self.assert_qmp(event, 'data/type', 'mirror') + self.assert_qmp(event, 'data/device', drive) + ready = True + + result = self.vm.qmp('block-job-complete', device=drive) + self.assert_qmp(result, 'return', {}) + + completed = False + while not completed: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_COMPLETED': + self.assert_qmp(event, 'data/type', 'mirror') + self.assert_qmp(event, 'data/device', drive) + self.assert_qmp_absent(event, 'data/error') + self.assert_qmp(event, 'data/offset', self.image_len) + self.assert_qmp(event, 'data/len', self.image_len) + completed = True + + self.assert_no_active_mirrors() + + def create_image(self, name, size): + file = open(name, 'w') + i = 0 + while i < size: + sector = struct.pack('>l504xl', i / 512, i / 512) + file.write(sector) + i = i + 512 + file.close() + + def compare_images(self, img1, img2): + try: + qemu_img('convert', '-f', iotests.imgfmt, '-O', 'raw', img1, img1 + '.raw') + qemu_img('convert', '-f', iotests.imgfmt, '-O', 'raw', img2, img2 + '.raw') + file1 = open(img1 + '.raw', 'r') + file2 = open(img2 + '.raw', 'r') + return file1.read() == file2.read() + finally: + if file1 is not None: + file1.close() + if file2 is not None: + file2.close() + try: + os.remove(img1 + '.raw') + except OSError: + pass + try: + os.remove(img2 + '.raw') + except OSError: + pass + +class TestSingleDrive(ImageMirroringTestCase): + image_len = 1 * 1024 * 1024 # MB + + def setUp(self): + self.create_image(backing_img, TestSingleDrive.image_len) + qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) + self.vm = iotests.VM().add_drive(test_img) + self.vm.launch() + + def tearDown(self): + self.vm.shutdown() + os.remove(test_img) + os.remove(backing_img) + try: + os.remove(target_img) + except OSError: + pass + + def test_complete(self): + self.assert_no_active_mirrors() + + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + target=target_img) + self.assert_qmp(result, 'return', {}) + + self.complete_and_wait() + result = self.vm.qmp('query-block') + self.assert_qmp(result, 'return[0]/inserted/file', target_img) + self.vm.shutdown() + self.assertTrue(self.compare_images(test_img, target_img), + 'target image does not match source after mirroring') + + def test_cancel(self): + self.assert_no_active_mirrors() + + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + target=target_img) + self.assert_qmp(result, 'return', {}) + + self.cancel_and_wait(wait_ready=False) + result = self.vm.qmp('query-block') + self.assert_qmp(result, 'return[0]/inserted/file', test_img) + self.vm.shutdown() + + def test_cancel_after_ready(self): + self.assert_no_active_mirrors() + + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + target=target_img) + self.assert_qmp(result, 'return', {}) + + self.cancel_and_wait() + result = self.vm.qmp('query-block') + self.assert_qmp(result, 'return[0]/inserted/file', test_img) + self.vm.shutdown() + self.assertTrue(self.compare_images(test_img, target_img), + 'target image does not match source after mirroring') + + def test_pause(self): + self.assert_no_active_mirrors() + + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + target=target_img) + self.assert_qmp(result, 'return', {}) + + result = self.vm.qmp('block-job-pause', device='drive0') + self.assert_qmp(result, 'return', {}) + + time.sleep(1) + result = self.vm.qmp('query-block-jobs') + offset = self.dictpath(result, 'return[0]/offset') + + time.sleep(1) + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/offset', offset) + + result = self.vm.qmp('block-job-resume', device='drive0') + self.assert_qmp(result, 'return', {}) + + self.complete_and_wait() + self.vm.shutdown() + self.assertTrue(self.compare_images(test_img, target_img), + 'target image does not match source after mirroring') + + def test_large_cluster(self): + self.assert_no_active_mirrors() + + qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=%d,backing_file=%s' + % (TestSingleDrive.image_len, backing_img), target_img) + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + mode='existing', target=target_img) + self.assert_qmp(result, 'return', {}) + + self.complete_and_wait() + result = self.vm.qmp('query-block') + self.assert_qmp(result, 'return[0]/inserted/file', target_img) + self.vm.shutdown() + self.assertTrue(self.compare_images(test_img, target_img), + 'target image does not match source after mirroring') + + def test_medium_not_found(self): + result = self.vm.qmp('drive-mirror', device='ide1-cd0', sync='full', + target=target_img) + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_image_not_found(self): + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + mode='existing', target=target_img) + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_device_not_found(self): + result = self.vm.qmp('drive-mirror', device='nonexistent', sync='full', + target=target_img) + self.assert_qmp(result, 'error/class', 'DeviceNotFound') + +class TestMirrorNoBacking(ImageMirroringTestCase): + image_len = 2 * 1024 * 1024 # MB + + def complete_and_wait(self, drive='drive0', wait_ready=True): + self.create_image(target_backing_img, TestMirrorNoBacking.image_len) + return ImageMirroringTestCase.complete_and_wait(self, drive, wait_ready) + + def compare_images(self, img1, img2): + self.create_image(target_backing_img, TestMirrorNoBacking.image_len) + return ImageMirroringTestCase.compare_images(self, img1, img2) + + def setUp(self): + self.create_image(backing_img, TestMirrorNoBacking.image_len) + qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) + self.vm = iotests.VM().add_drive(test_img) + self.vm.launch() + + def tearDown(self): + self.vm.shutdown() + os.remove(test_img) + os.remove(backing_img) + os.remove(target_backing_img) + os.remove(target_img) + + def test_complete(self): + self.assert_no_active_mirrors() + + qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, target_img) + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + mode='existing', target=target_img) + self.assert_qmp(result, 'return', {}) + + self.complete_and_wait() + result = self.vm.qmp('query-block') + self.assert_qmp(result, 'return[0]/inserted/file', target_img) + self.vm.shutdown() + self.assertTrue(self.compare_images(test_img, target_img), + 'target image does not match source after mirroring') + + def test_cancel(self): + self.assert_no_active_mirrors() + + qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, target_img) + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + mode='existing', target=target_img) + self.assert_qmp(result, 'return', {}) + + self.cancel_and_wait() + result = self.vm.qmp('query-block') + self.assert_qmp(result, 'return[0]/inserted/file', test_img) + self.vm.shutdown() + self.assertTrue(self.compare_images(test_img, target_img), + 'target image does not match source after mirroring') + +class TestSetSpeed(ImageMirroringTestCase): + image_len = 80 * 1024 * 1024 # MB + + def setUp(self): + qemu_img('create', backing_img, str(TestSetSpeed.image_len)) + qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) + self.vm = iotests.VM().add_drive(test_img) + self.vm.launch() + + def tearDown(self): + self.vm.shutdown() + os.remove(test_img) + os.remove(backing_img) + os.remove(target_img) + + def test_set_speed(self): + self.assert_no_active_mirrors() + + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + target=target_img) + self.assert_qmp(result, 'return', {}) + + # Default speed is 0 + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/device', 'drive0') + self.assert_qmp(result, 'return[0]/speed', 0) + + result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024) + self.assert_qmp(result, 'return', {}) + + # Ensure the speed we set was accepted + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/device', 'drive0') + self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024) + + self.cancel_and_wait() + + # Check setting speed in drive-mirror works + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + target=target_img, speed=4*1024*1024) + self.assert_qmp(result, 'return', {}) + + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/device', 'drive0') + self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024) + + self.cancel_and_wait() + + def test_set_speed_invalid(self): + self.assert_no_active_mirrors() + + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + target=target_img, speed=-1) + self.assert_qmp(result, 'error/class', 'GenericError') + + self.assert_no_active_mirrors() + + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + target=target_img) + self.assert_qmp(result, 'return', {}) + + result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1) + self.assert_qmp(result, 'error/class', 'GenericError') + + self.cancel_and_wait() + +if __name__ == '__main__': + iotests.main(supported_fmts=['qcow2', 'qed']) diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out new file mode 100644 index 0000000000..281b69efea --- /dev/null +++ b/tests/qemu-iotests/041.out @@ -0,0 +1,5 @@ +............ +---------------------------------------------------------------------- +Ran 12 tests + +OK diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 7407492099..ac86f54ae3 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -47,5 +47,6 @@ 038 rw auto backing 039 rw auto 040 rw auto +041 rw auto backing 042 rw auto quick 043 rw auto backing From 3bd293c3fdc8b4052b9fc357e0b28cba20e73099 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Oct 2012 16:49:27 +0200 Subject: [PATCH 1113/2270] iostatus: forward block_job_iostatus_reset to block job Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- block.c | 3 +++ blockjob.c | 3 +++ blockjob.h | 6 +++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/block.c b/block.c index ad5e2405e3..1564137fd8 100644 --- a/block.c +++ b/block.c @@ -4369,6 +4369,9 @@ void bdrv_iostatus_reset(BlockDriverState *bs) { if (bdrv_iostatus_is_enabled(bs)) { bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK; + if (bs->job) { + block_job_iostatus_reset(bs->job); + } } } diff --git a/blockjob.c b/blockjob.c index fbb7e1cd58..cda12c6933 100644 --- a/blockjob.c +++ b/blockjob.c @@ -142,6 +142,9 @@ bool block_job_is_cancelled(BlockJob *job) void block_job_iostatus_reset(BlockJob *job) { job->iostatus = BLOCK_DEVICE_IO_STATUS_OK; + if (job->job_type->iostatus_reset) { + job->job_type->iostatus_reset(job); + } } struct BlockCancelData { diff --git a/blockjob.h b/blockjob.h index fb2392efc0..3792b73e52 100644 --- a/blockjob.h +++ b/blockjob.h @@ -42,6 +42,9 @@ typedef struct BlockJobType { /** Optional callback for job types that support setting a speed limit */ void (*set_speed)(BlockJob *job, int64_t speed, Error **errp); + /** Optional callback for job types that need to forward I/O status reset */ + void (*iostatus_reset)(BlockJob *job); + /** * Optional callback for job types whose completion must be triggered * manually. @@ -253,7 +256,8 @@ int block_job_cancel_sync(BlockJob *job); * block_job_iostatus_reset: * @job: The job whose I/O status should be reset. * - * Reset I/O status on @job. + * Reset I/O status on @job and on BlockDriverState objects it uses, + * other than job->bs. */ void block_job_iostatus_reset(BlockJob *job); From b952b5589a36114e06201c0d2e82c293dbad2b1f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Oct 2012 16:49:28 +0200 Subject: [PATCH 1114/2270] mirror: add support for on-source-error/on-target-error Error management is important for mirroring; otherwise, an error on the target (even something as "innocent" as ENOSPC) requires to start again with a full copy. Similar to on_read_error/on_write_error, two separate knobs are provided for on_source_error (reads) and on_target_error (writes). The default is 'report' for both. The 'ignore' policy will leave the sector dirty, so that it will be retried later. Thus, it will not cause corruption. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- block/mirror.c | 92 +++++++++++++++++++++++++++++++++++++----------- block_int.h | 4 +++ blockdev.c | 14 ++++++-- hmp.c | 3 +- qapi-schema.json | 11 +++++- qmp-commands.hx | 8 ++++- 6 files changed, 107 insertions(+), 25 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index 6320f6a2e5..d6618a4b34 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -32,13 +32,28 @@ typedef struct MirrorBlockJob { RateLimit limit; BlockDriverState *target; MirrorSyncMode mode; + BlockdevOnError on_source_error, on_target_error; bool synced; bool should_complete; int64_t sector_num; uint8_t *buf; } MirrorBlockJob; -static int coroutine_fn mirror_iteration(MirrorBlockJob *s) +static BlockErrorAction mirror_error_action(MirrorBlockJob *s, bool read, + int error) +{ + s->synced = false; + if (read) { + return block_job_error_action(&s->common, s->common.bs, + s->on_source_error, true, error); + } else { + return block_job_error_action(&s->common, s->target, + s->on_target_error, false, error); + } +} + +static int coroutine_fn mirror_iteration(MirrorBlockJob *s, + BlockErrorAction *p_action) { BlockDriverState *source = s->common.bs; BlockDriverState *target = s->target; @@ -60,9 +75,21 @@ static int coroutine_fn mirror_iteration(MirrorBlockJob *s) trace_mirror_one_iteration(s, s->sector_num, nb_sectors); ret = bdrv_co_readv(source, s->sector_num, nb_sectors, &qiov); if (ret < 0) { - return ret; + *p_action = mirror_error_action(s, true, -ret); + goto fail; } - return bdrv_co_writev(target, s->sector_num, nb_sectors, &qiov); + ret = bdrv_co_writev(target, s->sector_num, nb_sectors, &qiov); + if (ret < 0) { + *p_action = mirror_error_action(s, false, -ret); + s->synced = false; + goto fail; + } + return 0; + +fail: + /* Try again later. */ + bdrv_set_dirty(source, s->sector_num, nb_sectors); + return ret; } static void coroutine_fn mirror_run(void *opaque) @@ -117,8 +144,9 @@ static void coroutine_fn mirror_run(void *opaque) cnt = bdrv_get_dirty_count(bs); if (cnt != 0) { - ret = mirror_iteration(s); - if (ret < 0) { + BlockErrorAction action = BDRV_ACTION_REPORT; + ret = mirror_iteration(s, &action); + if (ret < 0 && action == BDRV_ACTION_REPORT) { goto immediate_exit; } cnt = bdrv_get_dirty_count(bs); @@ -129,23 +157,25 @@ static void coroutine_fn mirror_run(void *opaque) trace_mirror_before_flush(s); ret = bdrv_flush(s->target); if (ret < 0) { - goto immediate_exit; - } + if (mirror_error_action(s, false, -ret) == BDRV_ACTION_REPORT) { + goto immediate_exit; + } + } else { + /* We're out of the streaming phase. From now on, if the job + * is cancelled we will actually complete all pending I/O and + * report completion. This way, block-job-cancel will leave + * the target in a consistent state. + */ + s->common.offset = end * BDRV_SECTOR_SIZE; + if (!s->synced) { + block_job_ready(&s->common); + s->synced = true; + } - /* We're out of the streaming phase. From now on, if the job - * is cancelled we will actually complete all pending I/O and - * report completion. This way, block-job-cancel will leave - * the target in a consistent state. - */ - s->common.offset = end * BDRV_SECTOR_SIZE; - if (!s->synced) { - block_job_ready(&s->common); - s->synced = true; + should_complete = s->should_complete || + block_job_is_cancelled(&s->common); + cnt = bdrv_get_dirty_count(bs); } - - should_complete = s->should_complete || - block_job_is_cancelled(&s->common); - cnt = bdrv_get_dirty_count(bs); } if (cnt == 0 && should_complete) { @@ -197,6 +227,7 @@ static void coroutine_fn mirror_run(void *opaque) immediate_exit: g_free(s->buf); bdrv_set_dirty_tracking(bs, false); + bdrv_iostatus_disable(s->target); if (s->should_complete && ret == 0) { if (bdrv_get_flags(s->target) != bdrv_get_flags(s->common.bs)) { bdrv_reopen(s->target, bdrv_get_flags(s->common.bs), NULL); @@ -219,6 +250,13 @@ static void mirror_set_speed(BlockJob *job, int64_t speed, Error **errp) ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE, SLICE_TIME); } +static void mirror_iostatus_reset(BlockJob *job) +{ + MirrorBlockJob *s = container_of(job, MirrorBlockJob, common); + + bdrv_iostatus_reset(s->target); +} + static void mirror_complete(BlockJob *job, Error **errp) { MirrorBlockJob *s = container_of(job, MirrorBlockJob, common); @@ -245,25 +283,39 @@ static BlockJobType mirror_job_type = { .instance_size = sizeof(MirrorBlockJob), .job_type = "mirror", .set_speed = mirror_set_speed, + .iostatus_reset= mirror_iostatus_reset, .complete = mirror_complete, }; void mirror_start(BlockDriverState *bs, BlockDriverState *target, int64_t speed, MirrorSyncMode mode, + BlockdevOnError on_source_error, + BlockdevOnError on_target_error, BlockDriverCompletionFunc *cb, void *opaque, Error **errp) { MirrorBlockJob *s; + if ((on_source_error == BLOCKDEV_ON_ERROR_STOP || + on_source_error == BLOCKDEV_ON_ERROR_ENOSPC) && + !bdrv_iostatus_is_enabled(bs)) { + error_set(errp, QERR_INVALID_PARAMETER, "on-source-error"); + return; + } + s = block_job_create(&mirror_job_type, bs, speed, cb, opaque, errp); if (!s) { return; } + s->on_source_error = on_source_error; + s->on_target_error = on_target_error; s->target = target; s->mode = mode; bdrv_set_dirty_tracking(bs, true); bdrv_set_enable_write_cache(s->target, true); + bdrv_set_on_error(s->target, on_target_error, on_target_error); + bdrv_iostatus_enable(s->target); s->common.co = qemu_coroutine_create(mirror_run); trace_mirror_start(bs, s, s->common.co, opaque); qemu_coroutine_enter(s->common.co, s); diff --git a/block_int.h b/block_int.h index aaa46a83b0..00204eb82e 100644 --- a/block_int.h +++ b/block_int.h @@ -337,6 +337,8 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base, * @target: Block device to write to. * @speed: The maximum speed, in bytes per second, or 0 for unlimited. * @mode: Whether to collapse all images in the chain to the target. + * @on_source_error: The action to take upon error reading from the source. + * @on_target_error: The action to take upon error writing to the target. * @cb: Completion function for the job. * @opaque: Opaque pointer value passed to @cb. * @errp: Error object. @@ -348,6 +350,8 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base, */ void mirror_start(BlockDriverState *bs, BlockDriverState *target, int64_t speed, MirrorSyncMode mode, + BlockdevOnError on_source_error, + BlockdevOnError on_target_error, BlockDriverCompletionFunc *cb, void *opaque, Error **errp); diff --git a/blockdev.c b/blockdev.c index 431c678f8f..a068a4b669 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1185,7 +1185,10 @@ void qmp_drive_mirror(const char *device, const char *target, bool has_format, const char *format, enum MirrorSyncMode sync, bool has_mode, enum NewImageMode mode, - bool has_speed, int64_t speed, Error **errp) + bool has_speed, int64_t speed, + bool has_on_source_error, BlockdevOnError on_source_error, + bool has_on_target_error, BlockdevOnError on_target_error, + Error **errp) { BlockDriverInfo bdi; BlockDriverState *bs; @@ -1200,6 +1203,12 @@ void qmp_drive_mirror(const char *device, const char *target, if (!has_speed) { speed = 0; } + if (!has_on_source_error) { + on_source_error = BLOCKDEV_ON_ERROR_REPORT; + } + if (!has_on_target_error) { + on_target_error = BLOCKDEV_ON_ERROR_REPORT; + } if (!has_mode) { mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; } @@ -1292,7 +1301,8 @@ void qmp_drive_mirror(const char *device, const char *target, } } - mirror_start(bs, target_bs, speed, sync, block_job_cb, bs, &local_err); + mirror_start(bs, target_bs, speed, sync, on_source_error, on_target_error, + block_job_cb, bs, &local_err); if (local_err != NULL) { bdrv_delete(target_bs); error_propagate(errp, local_err); diff --git a/hmp.c b/hmp.c index e53025306a..4a458ac0e8 100644 --- a/hmp.c +++ b/hmp.c @@ -795,7 +795,8 @@ void hmp_drive_mirror(Monitor *mon, const QDict *qdict) qmp_drive_mirror(device, filename, !!format, format, full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP, - true, mode, false, 0, &errp); + true, mode, false, 0, + false, 0, false, 0, &errp); hmp_handle_error(mon, &errp); } diff --git a/qapi-schema.json b/qapi-schema.json index a066cd5ca2..6aa443e90e 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1629,6 +1629,14 @@ # (all the disk, only the sectors allocated in the topmost image, or # only new I/O). # +# @on-source-error: #optional the action to take on an error on the source, +# default 'report'. 'stop' and 'enospc' can only be used +# if the block device supports io-status (see BlockInfo). +# +# @on-target-error: #optional the action to take on an error on the target, +# default 'report' (no limitations, since this applies to +# a different block device than @device). +# # Returns: nothing on success # If @device is not a valid block device, DeviceNotFound # @@ -1637,7 +1645,8 @@ { 'command': 'drive-mirror', 'data': { 'device': 'str', 'target': 'str', '*format': 'str', 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode', - '*speed': 'int' } } + '*speed': 'int', '*on-source-error': 'BlockdevOnError', + '*on-target-error': 'BlockdevOnError' } } ## # @migrate_cancel diff --git a/qmp-commands.hx b/qmp-commands.hx index 614baea784..c31312f8ef 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -937,7 +937,8 @@ EQMP { .name = "drive-mirror", - .args_type = "sync:s,device:B,target:s,speed:i?,mode:s?,format:s?", + .args_type = "sync:s,device:B,target:s,speed:i?,mode:s?,format:s?," + "on-source-error:s?,on-target-error:s?", .mhandler.cmd_new = qmp_marshal_input_drive_mirror, }, @@ -965,6 +966,11 @@ Arguments: possibilities include "full" for all the disk, "top" for only the sectors allocated in the topmost image, or "none" to only replicate new I/O (MirrorSyncMode). +- "on-source-error": the action to take on an error on the source + (BlockdevOnError, default 'report') +- "on-target-error": the action to take on an error on the target + (BlockdevOnError, default 'report') + Example: From 9eb80eadd498fae2ad9eecbb89646b0cc4929cac Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Oct 2012 16:49:29 +0200 Subject: [PATCH 1115/2270] qmp: add pull_event function This function is unlike get_events in that it makes it easy to process one event at a time. This is useful in the mirroring test cases, where we want to process just one event (BLOCK_JOB_ERROR) and leave the others to a helper function. Acked-by: Luiz Capitulino Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- QMP/qmp.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/QMP/qmp.py b/QMP/qmp.py index 32510a176a..c551df1ed7 100644 --- a/QMP/qmp.py +++ b/QMP/qmp.py @@ -136,6 +136,26 @@ class QEMUMonitorProtocol: raise Exception(ret['error']['desc']) return ret['return'] + def pull_event(self, wait=False): + """ + Get and delete the first available QMP event. + + @param wait: block until an event is available (bool) + """ + self.__sock.setblocking(0) + try: + self.__json_read() + except socket.error, err: + if err[0] == errno.EAGAIN: + # No data available + pass + self.__sock.setblocking(1) + if not self.__events and wait: + self.__json_read(only_event=True) + event = self.__events[0] + del self.__events[0] + return event + def get_events(self, wait=False): """ Get a list of available QMP events. From 9dfa9f593045d70572ebfd94f59cd33ec99e847c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 23 Oct 2012 16:39:23 +0200 Subject: [PATCH 1116/2270] qemu-iotests: add testcases for mirroring on-source-error/on-target-error The new options are tested with blkdebug on both the source and the target. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- tests/qemu-iotests/041 | 253 ++++++++++++++++++++++++++++++++++ tests/qemu-iotests/041.out | 4 +- tests/qemu-iotests/iotests.py | 4 + 3 files changed, 259 insertions(+), 2 deletions(-) diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 index fd9760a1d9..c6eb851871 100755 --- a/tests/qemu-iotests/041 +++ b/tests/qemu-iotests/041 @@ -292,6 +292,259 @@ class TestMirrorNoBacking(ImageMirroringTestCase): self.assertTrue(self.compare_images(test_img, target_img), 'target image does not match source after mirroring') +class TestReadErrors(ImageMirroringTestCase): + image_len = 2 * 1024 * 1024 # MB + + # this should be a multiple of twice the default granularity + # so that we hit this offset first in state 1 + MIRROR_GRANULARITY = 1024 * 1024 + + def create_blkdebug_file(self, name, event, errno): + file = open(name, 'w') + file.write(''' +[inject-error] +state = "1" +event = "%s" +errno = "%d" +immediately = "off" +once = "on" +sector = "%d" + +[set-state] +state = "1" +event = "%s" +new_state = "2" + +[set-state] +state = "2" +event = "%s" +new_state = "1" +''' % (event, errno, self.MIRROR_GRANULARITY / 512, event, event)) + file.close() + + def setUp(self): + self.blkdebug_file = backing_img + ".blkdebug" + self.create_image(backing_img, TestReadErrors.image_len) + self.create_blkdebug_file(self.blkdebug_file, "read_aio", 5) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw' + % (self.blkdebug_file, backing_img), + test_img) + self.vm = iotests.VM().add_drive(test_img) + self.vm.launch() + + def tearDown(self): + self.vm.shutdown() + os.remove(test_img) + os.remove(backing_img) + os.remove(self.blkdebug_file) + + def test_report_read(self): + self.assert_no_active_mirrors() + + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + target=target_img) + self.assert_qmp(result, 'return', {}) + + completed = False + error = False + while not completed: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_ERROR': + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/operation', 'read') + error = True + elif event['event'] == 'BLOCK_JOB_READY': + self.assertTrue(False, 'job completed unexpectedly') + elif event['event'] == 'BLOCK_JOB_COMPLETED': + self.assertTrue(error, 'job completed unexpectedly') + self.assert_qmp(event, 'data/type', 'mirror') + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/error', 'Input/output error') + self.assert_qmp(event, 'data/len', self.image_len) + completed = True + + self.assert_no_active_mirrors() + self.vm.shutdown() + + def test_ignore_read(self): + self.assert_no_active_mirrors() + + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + target=target_img, on_source_error='ignore') + self.assert_qmp(result, 'return', {}) + + event = self.vm.get_qmp_event(wait=True) + self.assertEquals(event['event'], 'BLOCK_JOB_ERROR') + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/operation', 'read') + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/paused', False) + self.complete_and_wait() + self.vm.shutdown() + + def test_stop_read(self): + self.assert_no_active_mirrors() + + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + target=target_img, on_source_error='stop') + self.assert_qmp(result, 'return', {}) + + error = False + ready = False + while not ready: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_ERROR': + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/operation', 'read') + + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/paused', True) + self.assert_qmp(result, 'return[0]/io-status', 'failed') + + result = self.vm.qmp('block-job-resume', device='drive0') + self.assert_qmp(result, 'return', {}) + error = True + elif event['event'] == 'BLOCK_JOB_READY': + self.assertTrue(error, 'job completed unexpectedly') + self.assert_qmp(event, 'data/device', 'drive0') + ready = True + + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/paused', False) + self.assert_qmp(result, 'return[0]/io-status', 'ok') + + self.complete_and_wait(wait_ready=False) + self.assert_no_active_mirrors() + self.vm.shutdown() + +class TestWriteErrors(ImageMirroringTestCase): + image_len = 2 * 1024 * 1024 # MB + + # this should be a multiple of twice the default granularity + # so that we hit this offset first in state 1 + MIRROR_GRANULARITY = 1024 * 1024 + + def create_blkdebug_file(self, name, event, errno): + file = open(name, 'w') + file.write(''' +[inject-error] +state = "1" +event = "%s" +errno = "%d" +immediately = "off" +once = "on" +sector = "%d" + +[set-state] +state = "1" +event = "%s" +new_state = "2" + +[set-state] +state = "2" +event = "%s" +new_state = "1" +''' % (event, errno, self.MIRROR_GRANULARITY / 512, event, event)) + file.close() + + def setUp(self): + self.blkdebug_file = target_img + ".blkdebug" + self.create_image(backing_img, TestWriteErrors.image_len) + self.create_blkdebug_file(self.blkdebug_file, "write_aio", 5) + qemu_img('create', '-f', iotests.imgfmt, '-obacking_file=%s' %(backing_img), test_img) + self.vm = iotests.VM().add_drive(test_img) + self.target_img = 'blkdebug:%s:%s' % (self.blkdebug_file, target_img) + qemu_img('create', '-f', iotests.imgfmt, '-osize=%d' %(TestWriteErrors.image_len), target_img) + self.vm.launch() + + def tearDown(self): + self.vm.shutdown() + os.remove(test_img) + os.remove(backing_img) + os.remove(self.blkdebug_file) + + def test_report_write(self): + self.assert_no_active_mirrors() + + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + mode='existing', target=self.target_img) + self.assert_qmp(result, 'return', {}) + + completed = False + error = False + while not completed: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_ERROR': + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/operation', 'write') + error = True + elif event['event'] == 'BLOCK_JOB_READY': + self.assertTrue(False, 'job completed unexpectedly') + elif event['event'] == 'BLOCK_JOB_COMPLETED': + self.assertTrue(error, 'job completed unexpectedly') + self.assert_qmp(event, 'data/type', 'mirror') + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/error', 'Input/output error') + self.assert_qmp(event, 'data/len', self.image_len) + completed = True + + self.assert_no_active_mirrors() + self.vm.shutdown() + + def test_ignore_write(self): + self.assert_no_active_mirrors() + + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + mode='existing', target=self.target_img, + on_target_error='ignore') + self.assert_qmp(result, 'return', {}) + + event = self.vm.get_qmp_event(wait=True) + self.assertEquals(event['event'], 'BLOCK_JOB_ERROR') + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/operation', 'write') + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/paused', False) + self.complete_and_wait() + self.vm.shutdown() + + def test_stop_write(self): + self.assert_no_active_mirrors() + + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + mode='existing', target=self.target_img, + on_target_error='stop') + self.assert_qmp(result, 'return', {}) + + error = False + ready = False + while not ready: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_ERROR': + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/operation', 'write') + + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/paused', True) + self.assert_qmp(result, 'return[0]/io-status', 'failed') + + result = self.vm.qmp('block-job-resume', device='drive0') + self.assert_qmp(result, 'return', {}) + + result = self.vm.qmp('query-block-jobs') + self.assert_qmp(result, 'return[0]/paused', False) + self.assert_qmp(result, 'return[0]/io-status', 'ok') + error = True + elif event['event'] == 'BLOCK_JOB_READY': + self.assertTrue(error, 'job completed unexpectedly') + self.assert_qmp(event, 'data/device', 'drive0') + ready = True + + self.complete_and_wait(wait_ready=False) + self.assert_no_active_mirrors() + self.vm.shutdown() + class TestSetSpeed(ImageMirroringTestCase): image_len = 80 * 1024 * 1024 # MB diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out index 281b69efea..71009c239f 100644 --- a/tests/qemu-iotests/041.out +++ b/tests/qemu-iotests/041.out @@ -1,5 +1,5 @@ -............ +.................. ---------------------------------------------------------------------- -Ran 12 tests +Ran 18 tests OK diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index 3c60b2d163..735c6745d7 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -106,6 +106,10 @@ class VM(object): return self._qmp.cmd(cmd, args=qmp_args) + def get_qmp_event(self, wait=False): + '''Poll for one queued QMP events and return it''' + return self._qmp.pull_event(wait=wait) + def get_qmp_events(self, wait=False): '''Poll for queued QMP events and return a list of dicts''' events = self._qmp.get_events(wait=wait) From 3b6eda2f57a5b7ed047077b6272c2b5a9e3531ca Mon Sep 17 00:00:00 2001 From: Corey Bryant Date: Thu, 18 Oct 2012 16:41:04 -0400 Subject: [PATCH 1117/2270] osdep: Less restrictive F_SEFL in qemu_dup_flags() qemu_dup_flags() currently limits the flags that can be set on the fcntl() F_SETFL call to those that we currently know can be set with fcntl() F_SETFL. The problem with this is that it will prevent use of new flags in the future without a code update. This patch relaxes the checking and lets fcntl() determine the flags it can set. Signed-off-by: Corey Bryant Signed-off-by: Kevin Wolf --- osdep.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/osdep.c b/osdep.c index 3b25297a25..c822a01c04 100644 --- a/osdep.c +++ b/osdep.c @@ -88,7 +88,6 @@ static int qemu_dup_flags(int fd, int flags) int ret; int serrno; int dup_flags; - int setfl_flags; #ifdef F_DUPFD_CLOEXEC ret = fcntl(fd, F_DUPFD_CLOEXEC, 0); @@ -113,16 +112,7 @@ static int qemu_dup_flags(int fd, int flags) } /* Set/unset flags that we can with fcntl */ - setfl_flags = O_APPEND | O_ASYNC | O_NONBLOCK; -#ifdef O_NOATIME - setfl_flags |= O_NOATIME; -#endif -#ifdef O_DIRECT - setfl_flags |= O_DIRECT; -#endif - dup_flags &= ~setfl_flags; - dup_flags |= (flags & setfl_flags); - if (fcntl(ret, F_SETFL, dup_flags) == -1) { + if (fcntl(ret, F_SETFL, flags) == -1) { goto fail; } From f296c0d172735612cad8af5fafb8dedeaaa2a109 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 14 Oct 2012 09:52:27 +0000 Subject: [PATCH 1118/2270] arm-semi.c: Handle get/put_user() failure accessing arguments Rework the handling of arguments to ARM semihosting calls so that we handle a possible failure return from get_user_ual() or put_user_ual(). (This incidentally silences a lot of warnings from clang about "expression result unused"). Signed-off-by: Peter Maydell --- target-arm/arm-semi.c | 167 +++++++++++++++++++++++++++--------------- 1 file changed, 106 insertions(+), 61 deletions(-) diff --git a/target-arm/arm-semi.c b/target-arm/arm-semi.c index 73bde584ab..7743d67010 100644 --- a/target-arm/arm-semi.c +++ b/target-arm/arm-semi.c @@ -166,17 +166,20 @@ static void arm_semi_flen_cb(CPUARMState *env, target_ulong ret, target_ulong er #endif } -#define ARG(n) \ -({ \ - target_ulong __arg; \ - /* FIXME - handle get_user() failure */ \ - get_user_ual(__arg, args + (n) * 4); \ - __arg; \ -}) +/* Read the input value from the argument block; fail the semihosting + * call if the memory read fails. + */ +#define GET_ARG(n) do { \ + if (get_user_ual(arg ## n, args + (n) * 4)) { \ + return (uint32_t)-1; \ + } \ +} while (0) + #define SET_ARG(n, val) put_user_ual(val, args + (n) * 4) uint32_t do_arm_semihosting(CPUARMState *env) { target_ulong args; + target_ulong arg0, arg1, arg2, arg3; char * s; int nr; uint32_t ret; @@ -191,33 +194,39 @@ uint32_t do_arm_semihosting(CPUARMState *env) args = env->regs[1]; switch (nr) { case TARGET_SYS_OPEN: - if (!(s = lock_user_string(ARG(0)))) + GET_ARG(0); + GET_ARG(1); + GET_ARG(2); + s = lock_user_string(arg0); + if (!s) { /* FIXME - should this error code be -TARGET_EFAULT ? */ return (uint32_t)-1; - if (ARG(1) >= 12) { - unlock_user(s, ARG(0), 0); + } + if (arg1 >= 12) { + unlock_user(s, arg0, 0); return (uint32_t)-1; } if (strcmp(s, ":tt") == 0) { - int result_fileno = ARG(1) < 4 ? STDIN_FILENO : STDOUT_FILENO; - unlock_user(s, ARG(0), 0); + int result_fileno = arg1 < 4 ? STDIN_FILENO : STDOUT_FILENO; + unlock_user(s, arg0, 0); return result_fileno; } if (use_gdb_syscalls()) { - gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0), - (int)ARG(2)+1, gdb_open_modeflags[ARG(1)]); + gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", arg0, + (int)arg2+1, gdb_open_modeflags[arg1]); ret = env->regs[0]; } else { - ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644)); + ret = set_swi_errno(ts, open(s, open_modeflags[arg1], 0644)); } - unlock_user(s, ARG(0), 0); + unlock_user(s, arg0, 0); return ret; case TARGET_SYS_CLOSE: + GET_ARG(0); if (use_gdb_syscalls()) { - gdb_do_syscall(arm_semi_cb, "close,%x", ARG(0)); + gdb_do_syscall(arm_semi_cb, "close,%x", arg0); return env->regs[0]; } else { - return set_swi_errno(ts, close(ARG(0))); + return set_swi_errno(ts, close(arg0)); } case TARGET_SYS_WRITEC: { @@ -248,35 +257,45 @@ uint32_t do_arm_semihosting(CPUARMState *env) unlock_user(s, args, 0); return ret; case TARGET_SYS_WRITE: - len = ARG(2); + GET_ARG(0); + GET_ARG(1); + GET_ARG(2); + len = arg2; if (use_gdb_syscalls()) { arm_semi_syscall_len = len; - gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", ARG(0), ARG(1), len); + gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", arg0, arg1, len); return env->regs[0]; } else { - if (!(s = lock_user(VERIFY_READ, ARG(1), len, 1))) + s = lock_user(VERIFY_READ, arg1, len, 1); + if (!s) { /* FIXME - should this error code be -TARGET_EFAULT ? */ return (uint32_t)-1; - ret = set_swi_errno(ts, write(ARG(0), s, len)); - unlock_user(s, ARG(1), 0); + } + ret = set_swi_errno(ts, write(arg0, s, len)); + unlock_user(s, arg1, 0); if (ret == (uint32_t)-1) return -1; return len - ret; } case TARGET_SYS_READ: - len = ARG(2); + GET_ARG(0); + GET_ARG(1); + GET_ARG(2); + len = arg2; if (use_gdb_syscalls()) { arm_semi_syscall_len = len; - gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", ARG(0), ARG(1), len); + gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", arg0, arg1, len); return env->regs[0]; } else { - if (!(s = lock_user(VERIFY_WRITE, ARG(1), len, 0))) + s = lock_user(VERIFY_WRITE, arg1, len, 0); + if (!s) { /* FIXME - should this error code be -TARGET_EFAULT ? */ return (uint32_t)-1; - do - ret = set_swi_errno(ts, read(ARG(0), s, len)); - while (ret == -1 && errno == EINTR); - unlock_user(s, ARG(1), len); + } + do { + ret = set_swi_errno(ts, read(arg0, s, len)); + } while (ret == -1 && errno == EINTR); + unlock_user(s, arg1, len); if (ret == (uint32_t)-1) return -1; return len - ret; @@ -285,30 +304,34 @@ uint32_t do_arm_semihosting(CPUARMState *env) /* XXX: Read from debug console. Not implemented. */ return 0; case TARGET_SYS_ISTTY: + GET_ARG(0); if (use_gdb_syscalls()) { - gdb_do_syscall(arm_semi_cb, "isatty,%x", ARG(0)); + gdb_do_syscall(arm_semi_cb, "isatty,%x", arg0); return env->regs[0]; } else { - return isatty(ARG(0)); + return isatty(arg0); } case TARGET_SYS_SEEK: + GET_ARG(0); + GET_ARG(1); if (use_gdb_syscalls()) { - gdb_do_syscall(arm_semi_cb, "lseek,%x,%x,0", ARG(0), ARG(1)); + gdb_do_syscall(arm_semi_cb, "lseek,%x,%x,0", arg0, arg1); return env->regs[0]; } else { - ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET)); + ret = set_swi_errno(ts, lseek(arg0, arg1, SEEK_SET)); if (ret == (uint32_t)-1) return -1; return 0; } case TARGET_SYS_FLEN: + GET_ARG(0); if (use_gdb_syscalls()) { gdb_do_syscall(arm_semi_flen_cb, "fstat,%x,%x", - ARG(0), env->regs[13]-64); + arg0, env->regs[13]-64); return env->regs[0]; } else { struct stat buf; - ret = set_swi_errno(ts, fstat(ARG(0), &buf)); + ret = set_swi_errno(ts, fstat(arg0, &buf)); if (ret == (uint32_t)-1) return -1; return buf.st_size; @@ -317,35 +340,43 @@ uint32_t do_arm_semihosting(CPUARMState *env) /* XXX: Not implemented. */ return -1; case TARGET_SYS_REMOVE: + GET_ARG(0); + GET_ARG(1); if (use_gdb_syscalls()) { - gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1)+1); + gdb_do_syscall(arm_semi_cb, "unlink,%s", arg0, (int)arg1+1); ret = env->regs[0]; } else { - if (!(s = lock_user_string(ARG(0)))) + s = lock_user_string(arg0); + if (!s) { /* FIXME - should this error code be -TARGET_EFAULT ? */ return (uint32_t)-1; + } ret = set_swi_errno(ts, remove(s)); - unlock_user(s, ARG(0), 0); + unlock_user(s, arg0, 0); } return ret; case TARGET_SYS_RENAME: + GET_ARG(0); + GET_ARG(1); + GET_ARG(2); + GET_ARG(3); if (use_gdb_syscalls()) { gdb_do_syscall(arm_semi_cb, "rename,%s,%s", - ARG(0), (int)ARG(1)+1, ARG(2), (int)ARG(3)+1); + arg0, (int)arg1+1, arg2, (int)arg3+1); return env->regs[0]; } else { char *s2; - s = lock_user_string(ARG(0)); - s2 = lock_user_string(ARG(2)); + s = lock_user_string(arg0); + s2 = lock_user_string(arg2); if (!s || !s2) /* FIXME - should this error code be -TARGET_EFAULT ? */ ret = (uint32_t)-1; else ret = set_swi_errno(ts, rename(s, s2)); if (s2) - unlock_user(s2, ARG(2), 0); + unlock_user(s2, arg2, 0); if (s) - unlock_user(s, ARG(0), 0); + unlock_user(s, arg0, 0); return ret; } case TARGET_SYS_CLOCK: @@ -353,15 +384,19 @@ uint32_t do_arm_semihosting(CPUARMState *env) case TARGET_SYS_TIME: return set_swi_errno(ts, time(NULL)); case TARGET_SYS_SYSTEM: + GET_ARG(0); + GET_ARG(1); if (use_gdb_syscalls()) { - gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1)+1); + gdb_do_syscall(arm_semi_cb, "system,%s", arg0, (int)arg1+1); return env->regs[0]; } else { - if (!(s = lock_user_string(ARG(0)))) + s = lock_user_string(arg0); + if (!s) { /* FIXME - should this error code be -TARGET_EFAULT ? */ return (uint32_t)-1; + } ret = set_swi_errno(ts, system(s)); - unlock_user(s, ARG(0), 0); + unlock_user(s, arg0, 0); return ret; } case TARGET_SYS_ERRNO: @@ -375,22 +410,24 @@ uint32_t do_arm_semihosting(CPUARMState *env) /* Build a command-line from the original argv. * * The inputs are: - * * ARG(0), pointer to a buffer of at least the size - * specified in ARG(1). - * * ARG(1), size of the buffer pointed to by ARG(0) in + * * arg0, pointer to a buffer of at least the size + * specified in arg1. + * * arg1, size of the buffer pointed to by arg0 in * bytes. * * The outputs are: - * * ARG(0), pointer to null-terminated string of the + * * arg0, pointer to null-terminated string of the * command line. - * * ARG(1), length of the string pointed to by ARG(0). + * * arg1, length of the string pointed to by arg0. */ char *output_buffer; - size_t input_size = ARG(1); + size_t input_size; size_t output_size; int status = 0; - + GET_ARG(0); + GET_ARG(1); + input_size = arg1; /* Compute the size of the output string. */ #if !defined(CONFIG_USER_ONLY) output_size = strlen(ts->boot_info->kernel_filename) @@ -414,10 +451,13 @@ uint32_t do_arm_semihosting(CPUARMState *env) } /* Adjust the command-line length. */ - SET_ARG(1, output_size - 1); + if (SET_ARG(1, output_size - 1)) { + /* Couldn't write back to argument block */ + return -1; + } /* Lock the buffer on the ARM side. */ - output_buffer = lock_user(VERIFY_WRITE, ARG(0), output_size, 0); + output_buffer = lock_user(VERIFY_WRITE, arg0, output_size, 0); if (!output_buffer) { return -1; } @@ -449,7 +489,7 @@ uint32_t do_arm_semihosting(CPUARMState *env) out: #endif /* Unlock the buffer on the ARM side. */ - unlock_user(output_buffer, ARG(0), output_size); + unlock_user(output_buffer, arg0, output_size); return status; } @@ -457,6 +497,7 @@ uint32_t do_arm_semihosting(CPUARMState *env) { uint32_t *ptr; uint32_t limit; + GET_ARG(0); #ifdef CONFIG_USER_ONLY /* Some C libraries assume the heap immediately follows .bss, so @@ -477,25 +518,29 @@ uint32_t do_arm_semihosting(CPUARMState *env) ts->heap_limit = limit; } - if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0))) + ptr = lock_user(VERIFY_WRITE, arg0, 16, 0); + if (!ptr) { /* FIXME - should this error code be -TARGET_EFAULT ? */ return (uint32_t)-1; + } ptr[0] = tswap32(ts->heap_base); ptr[1] = tswap32(ts->heap_limit); ptr[2] = tswap32(ts->stack_base); ptr[3] = tswap32(0); /* Stack limit. */ - unlock_user(ptr, ARG(0), 16); + unlock_user(ptr, arg0, 16); #else limit = ram_size; - if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0))) + ptr = lock_user(VERIFY_WRITE, arg0, 16, 0); + if (!ptr) { /* FIXME - should this error code be -TARGET_EFAULT ? */ return (uint32_t)-1; + } /* TODO: Make this use the limit of the loaded application. */ ptr[0] = tswap32(limit / 2); ptr[1] = tswap32(limit); ptr[2] = tswap32(limit); /* Stack base */ ptr[3] = tswap32(0); /* Stack limit. */ - unlock_user(ptr, ARG(0), 16); + unlock_user(ptr, arg0, 16); #endif return 0; } From ee6fa5593ebfc437cbedaf28de8b66b2e7d44e70 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Oct 2012 16:58:52 +0100 Subject: [PATCH 1119/2270] target-arm: Use TCG operation for Neon 64 bit negation Use the TCG operation to do Neon 64 bit negations rather than calling a helper routine for it. Reviewed-by: Aurelien Jarno Signed-off-by: Peter Maydell --- target-arm/helper.h | 1 - target-arm/neon_helper.c | 6 ------ target-arm/translate.c | 4 +++- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/target-arm/helper.h b/target-arm/helper.h index 8b9adf1311..fa3472f0b9 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -339,7 +339,6 @@ DEF_HELPER_2(neon_mull_s16, i64, i32, i32) DEF_HELPER_1(neon_negl_u16, i64, i64) DEF_HELPER_1(neon_negl_u32, i64, i64) -DEF_HELPER_1(neon_negl_u64, i64, i64) DEF_HELPER_2(neon_qabs_s8, i32, env, i32) DEF_HELPER_2(neon_qabs_s16, i32, env, i32) diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c index 9aa920d2ac..89280b6eeb 100644 --- a/target-arm/neon_helper.c +++ b/target-arm/neon_helper.c @@ -1664,12 +1664,6 @@ uint64_t HELPER(neon_negl_u32)(uint64_t x) return low | ((uint64_t)high << 32); } -/* FIXME: There should be a native op for this. */ -uint64_t HELPER(neon_negl_u64)(uint64_t x) -{ - return -x; -} - /* Saturating sign manipulation. */ /* ??? Make these use NEON_VOP1 */ #define DO_QABS8(x) do { \ diff --git a/target-arm/translate.c b/target-arm/translate.c index daccb15c23..d33f94c0fd 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -4184,7 +4184,9 @@ static inline void gen_neon_negl(TCGv_i64 var, int size) switch (size) { case 0: gen_helper_neon_negl_u16(var, var); break; case 1: gen_helper_neon_negl_u32(var, var); break; - case 2: gen_helper_neon_negl_u64(var, var); break; + case 2: + tcg_gen_neg_i64(var, var); + break; default: abort(); } } From 36c91fd115a5920a35d4cb0e7a1903281469e0db Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Oct 2012 17:40:41 +0100 Subject: [PATCH 1120/2270] target-arm: Implement abs_i32 inline rather than as a helper Implement abs_i32 inline (with movcond) rather than using a helper function. Reviewed-by: Aurelien Jarno Signed-off-by: Peter Maydell --- target-arm/helper.c | 5 ----- target-arm/helper.h | 1 - target-arm/translate.c | 11 +++++++++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index 8f2cba6c1d..ab8b734933 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1562,11 +1562,6 @@ uint32_t HELPER(rbit)(uint32_t x) return x; } -uint32_t HELPER(abs)(uint32_t x) -{ - return ((int32_t)x < 0) ? -x : x; -} - #if defined(CONFIG_USER_ONLY) void do_interrupt (CPUARMState *env) diff --git a/target-arm/helper.h b/target-arm/helper.h index fa3472f0b9..60812de80b 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -13,7 +13,6 @@ DEF_HELPER_2(double_saturate, i32, env, s32) DEF_HELPER_FLAGS_2(sdiv, TCG_CALL_CONST | TCG_CALL_PURE, s32, s32, s32) DEF_HELPER_FLAGS_2(udiv, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32) DEF_HELPER_FLAGS_1(rbit, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) -DEF_HELPER_FLAGS_1(abs, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) #define PAS_OP(pfx) \ DEF_HELPER_3(pfx ## add8, i32, i32, i32, ptr) \ diff --git a/target-arm/translate.c b/target-arm/translate.c index d33f94c0fd..25433da037 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -462,8 +462,15 @@ static void gen_sar(TCGv dest, TCGv t0, TCGv t1) tcg_temp_free_i32(tmp1); } -/* FIXME: Implement this natively. */ -#define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1) +static void tcg_gen_abs_i32(TCGv dest, TCGv src) +{ + TCGv c0 = tcg_const_i32(0); + TCGv 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) { From 8b279a60dc3ca53923701dfec6e54bea9d13cfb7 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 19 Oct 2012 04:23:05 +0000 Subject: [PATCH 1121/2270] target-arm: Remove out of date FIXME regarding saturating arithmetic Remove an out of date FIXME regarding the saturating arithmetic helpers: we now do pass a pointer to CPUARMState to these helpers, and since the AREG0 changes went in there is no difference between helper.c and op_helper.c and therefore no point in moving the functions. Signed-off-by: Peter Maydell --- target-arm/op_helper.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index aef592ab8d..6e3ab90e3b 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -93,8 +93,6 @@ void tlb_fill(CPUARMState *env, target_ulong addr, int is_write, int mmu_idx, } #endif -/* FIXME: Pass an explicit pointer to QF to CPUARMState, and move saturating - instructions into helper.c */ uint32_t HELPER(add_setq)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t res = a + b; From 852bef0e0c03e2de9d6441471219cd3bc1bf45b5 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 19 Oct 2012 23:19:19 +0200 Subject: [PATCH 1122/2270] hmp: fix info cpus for sparc targets On sparc targets, info cpus returns this kind of output: | info cpus | * CPU #0: pc=0x0000000000424d18pc=0x0000000000424d18npc=0x0000000000424d1c thread_id=19460 pc is printed twice, there is no space between pc, pc and npc. With this patch, pc is not printed anymore when has_npc is set. In addition the space is printed before pc/nip/npc/PC instead of after the colon so that multiple prints are possible. This result on the following kind of input on sparc targets: | info cpus | * CPU #0: pc=0x0000000000424d18 npc=0x0000000000424d1c thread_id=19460 Cc: Luiz Capitulino Cc: Markus Armbruster Cc: Blue Swirl Signed-off-by: Aurelien Jarno Signed-off-by: Luiz Capitulino --- hmp.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/hmp.c b/hmp.c index 2b979826ee..9df84e3e22 100644 --- a/hmp.c +++ b/hmp.c @@ -245,20 +245,19 @@ void hmp_info_cpus(Monitor *mon) active = '*'; } - monitor_printf(mon, "%c CPU #%" PRId64 ": ", active, cpu->value->CPU); + monitor_printf(mon, "%c CPU #%" PRId64 ":", active, cpu->value->CPU); if (cpu->value->has_pc) { - monitor_printf(mon, "pc=0x%016" PRIx64, cpu->value->pc); + monitor_printf(mon, " pc=0x%016" PRIx64, cpu->value->pc); } if (cpu->value->has_nip) { - monitor_printf(mon, "nip=0x%016" PRIx64, cpu->value->nip); + monitor_printf(mon, " nip=0x%016" PRIx64, cpu->value->nip); } if (cpu->value->has_npc) { - monitor_printf(mon, "pc=0x%016" PRIx64, cpu->value->pc); - monitor_printf(mon, "npc=0x%016" PRIx64, cpu->value->npc); + monitor_printf(mon, " npc=0x%016" PRIx64, cpu->value->npc); } if (cpu->value->has_PC) { - monitor_printf(mon, "PC=0x%016" PRIx64, cpu->value->PC); + monitor_printf(mon, " PC=0x%016" PRIx64, cpu->value->PC); } if (cpu->value->halted) { From 1e9981465f05a0f103d7e09afd975c9c0ff6d132 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 23 Oct 2012 14:54:21 +0200 Subject: [PATCH 1123/2270] qmp: handle stop/cont in INMIGRATE state Right now, stop followed by an incoming migration will let the virtual machine start. cont before an incoming migration instead will fail. This is bad because the actual behavior is not predictable; it is racy with respect to the start of the incoming migration. That's because incoming migration is blocking, and thus will delay the processing of stop/cont until the end of the migration. In addition, there's nothing that really prevents the user from typing the block device's passwords before incoming migration is done, so returning the DeviceEncrypted error is also helpful in the QMP case. Both things can be fixed by just toggling the autostart variable when stop/cont are called in INMIGRATE state. Note that libvirt is currently working around the race by looping if the MigrationExpected answer is returned. After this patch, the command will return right away without ever raising an error. Signed-off-by: Paolo Bonzini Signed-off-by: Luiz Capitulino --- qapi-schema.json | 23 ++++++++++++++--------- qerror.h | 3 --- qmp.c | 17 +++++++++++------ 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/qapi-schema.json b/qapi-schema.json index c615ee212d..6b14edcc98 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -22,15 +22,11 @@ # @KVMMissingCap: the requested operation can't be fulfilled because a # required KVM capability is missing # -# @MigrationExpected: the requested operation can't be fulfilled because a -# migration process is expected -# # Since: 1.2 ## { 'enum': 'ErrorClass', 'data': [ 'GenericError', 'CommandNotFound', 'DeviceEncrypted', - 'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap', - 'MigrationExpected' ] } + 'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap' ] } ## # @add_client @@ -149,7 +145,11 @@ # # @finish-migrate: guest is paused to finish the migration process # -# @inmigrate: guest is paused waiting for an incoming migration +# @inmigrate: guest is paused waiting for an incoming migration. Note +# that this state does not tell whether the machine will start at the +# end of the migration. This depends on the command-line -S option and +# any invocation of 'stop' or 'cont' that has happened since QEMU was +# started. # # @internal-error: An internal error that prevents further guest execution # has occurred @@ -1210,7 +1210,9 @@ # Since: 0.14.0 # # Notes: This function will succeed even if the guest is already in the stopped -# state +# state. In "inmigrate" state, it will ensure that the guest +# remains paused once migration finishes, as if the -S option was +# passed on the command line. ## { 'command': 'stop' } @@ -1299,11 +1301,14 @@ # Since: 0.14.0 # # Returns: If successful, nothing -# If the QEMU is waiting for an incoming migration, MigrationExpected # If QEMU was started with an encrypted block device and a key has # not yet been set, DeviceEncrypted. # -# Notes: This command will succeed if the guest is currently running. +# Notes: This command will succeed if the guest is currently running. It +# will also succeed if the guest is in the "inmigrate" state; in +# this case, the effect of the command is to make sure the guest +# starts once migration finishes, removing the effect of the -S +# command line option if it was passed. ## { 'command': 'cont' } diff --git a/qerror.h b/qerror.h index c91708cc3c..5e98a39ae1 100644 --- a/qerror.h +++ b/qerror.h @@ -165,9 +165,6 @@ void assert_no_error(Error *err); #define QERR_MIGRATION_NOT_SUPPORTED \ ERROR_CLASS_GENERIC_ERROR, "State blocked by non-migratable device '%s'" -#define QERR_MIGRATION_EXPECTED \ - ERROR_CLASS_MIGRATION_EXPECTED, "An incoming migration is expected before this command can be executed" - #define QERR_MISSING_PARAMETER \ ERROR_CLASS_GENERIC_ERROR, "Parameter '%s' is missing" diff --git a/qmp.c b/qmp.c index 36c54c57cf..2c8d559609 100644 --- a/qmp.c +++ b/qmp.c @@ -85,7 +85,11 @@ void qmp_quit(Error **err) void qmp_stop(Error **errp) { - vm_stop(RUN_STATE_PAUSED); + if (runstate_check(RUN_STATE_INMIGRATE)) { + autostart = 0; + } else { + vm_stop(RUN_STATE_PAUSED); + } } void qmp_system_reset(Error **errp) @@ -144,10 +148,7 @@ void qmp_cont(Error **errp) { Error *local_err = NULL; - if (runstate_check(RUN_STATE_INMIGRATE)) { - error_set(errp, QERR_MIGRATION_EXPECTED); - return; - } else if (runstate_check(RUN_STATE_INTERNAL_ERROR) || + if (runstate_check(RUN_STATE_INTERNAL_ERROR) || runstate_check(RUN_STATE_SHUTDOWN)) { error_set(errp, QERR_RESET_REQUIRED); return; @@ -162,7 +163,11 @@ void qmp_cont(Error **errp) return; } - vm_start(); + if (runstate_check(RUN_STATE_INMIGRATE)) { + autostart = 1; + } else { + vm_start(); + } } void qmp_system_wakeup(Error **errp) From 29ed72f15a4c8fd3ac106d874f76cc27b654fd25 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 19 Oct 2012 16:45:24 +0200 Subject: [PATCH 1124/2270] migration: go to paused state after finishing incoming migration with -S At the end of migration the machine has started already, and cannot be destroyed without losing the guest's data. Hence, prelaunch is the wrong state. Go to the paused state instead. QEMU would reach that state anyway (after running the guest for the blink of an eye) if the "stop" command had been received after the start of migration. Signed-off-by: Paolo Bonzini Signed-off-by: Luiz Capitulino --- migration.c | 2 +- vl.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/migration.c b/migration.c index 62e030487d..e9a58228e9 100644 --- a/migration.c +++ b/migration.c @@ -102,7 +102,7 @@ void process_incoming_migration(QEMUFile *f) if (autostart) { vm_start(); } else { - runstate_set(RUN_STATE_PRELAUNCH); + runstate_set(RUN_STATE_PAUSED); } } diff --git a/vl.c b/vl.c index ee3c43ae2f..188af45869 100644 --- a/vl.c +++ b/vl.c @@ -341,7 +341,7 @@ static const RunStateTransition runstate_transitions_def[] = { { RUN_STATE_DEBUG, RUN_STATE_RUNNING }, { RUN_STATE_INMIGRATE, RUN_STATE_RUNNING }, - { RUN_STATE_INMIGRATE, RUN_STATE_PRELAUNCH }, + { RUN_STATE_INMIGRATE, RUN_STATE_PAUSED }, { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED }, { RUN_STATE_INTERNAL_ERROR, RUN_STATE_FINISH_MIGRATE }, From 8473f377393219390ea6f2d8d450a2b054bb823e Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 24 Oct 2012 14:12:15 -0200 Subject: [PATCH 1125/2270] win32: fix broken build due to missing QEMU_MADV_HUGEPAGE Commit ad0b5321f1f797274603ebbe20108b0750baee94 forgot to add QEMU_MADV_HUGEPAGE macros for when CONFIG_MADVISE is not defined. This broke the build for Windows. Fix it. Signed-off-by: Luiz Capitulino Signed-off-by: Anthony Liguori --- osdep.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osdep.h b/osdep.h index c5fd3d91ff..585e2c1787 100644 --- a/osdep.h +++ b/osdep.h @@ -121,6 +121,7 @@ void qemu_vfree(void *ptr); #define QEMU_MADV_DONTFORK QEMU_MADV_INVALID #define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID #define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID +#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID #else /* no-op */ @@ -129,6 +130,7 @@ void qemu_vfree(void *ptr); #define QEMU_MADV_DONTFORK QEMU_MADV_INVALID #define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID #define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID +#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID #endif From 00a0770de3ddb803a0f81f6aea40b0f945154a68 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:13:57 +0200 Subject: [PATCH 1126/2270] uhci: Properly unmap packets on cancel / invalid pid Packets with an invalid pid, or which were cancelled have usb_packet_map() called on them on init, but not usb_packet_unmap() before being freed. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index c2f08e3735..671c712112 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -236,6 +236,7 @@ static void uhci_async_cancel(UHCIAsync *async) trace_usb_uhci_packet_cancel(async->queue->token, async->td, async->done); if (!async->done) usb_cancel_packet(&async->packet); + usb_packet_unmap(&async->packet, &async->sgl); uhci_async_free(async); } @@ -887,6 +888,7 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, default: /* invalid pid : frame interrupted */ + usb_packet_unmap(&async->packet, &async->sgl); uhci_async_free(async); s->status |= UHCI_STS_HCPERR; uhci_update_irq(s); From 7c2eaca4efa46e02caaec4ca7ddf05a6e461da94 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:13:58 +0200 Subject: [PATCH 1127/2270] uhci: Move checks to continue queuing to uhci_fill_queue() Rather then having a special check to start queuing after the first packet, and then another check for the other packets in uhci_fill_queue(), simply check the previous packet beforehand in uhci_fill_queue() Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 671c712112..600d095573 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -991,7 +991,8 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td) UHCI_TD ptd; int ret; - while (is_valid(plink)) { + ptd.ctrl = td->ctrl; + while (is_valid(plink) && !(ptd.ctrl & TD_CTRL_SPD)) { pci_dma_read(&s->dev, plink & ~0xf, &ptd, sizeof(ptd)); le32_to_cpus(&ptd.link); le32_to_cpus(&ptd.ctrl); @@ -1010,9 +1011,6 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td) } assert(ret == TD_RESULT_ASYNC_START); assert(int_mask == 0); - if (ptd.ctrl & TD_CTRL_SPD) { - break; - } plink = ptd.link; } } @@ -1110,9 +1108,7 @@ static void uhci_process_frame(UHCIState *s) case TD_RESULT_ASYNC_START: trace_usb_uhci_td_async(curr_qh & ~0xf, link & ~0xf); - if (is_valid(td.link) && !(td.ctrl & TD_CTRL_SPD)) { - uhci_fill_queue(s, &td); - } + uhci_fill_queue(s, &td); link = curr_qh ? qh.link : td.link; continue; From 549a3c3d9665bdc0246fb6594b6e36ce3afadd21 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:13:59 +0200 Subject: [PATCH 1128/2270] ehci: Get rid of packet tbytes field This field is used in some places to track the tbytes field of the token, but in other places the field is used directly, use it directly everywhere for consistency. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 6c65a734c8..82f4dbd15a 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -362,7 +362,6 @@ struct EHCIPacket { USBPacket packet; QEMUSGList sgl; int pid; - uint32_t tbytes; enum async_state async; int usb_status; }; @@ -1505,15 +1504,16 @@ static void ehci_execute_complete(EHCIQueue *q) } } else { // TODO check 4.12 for splits + uint32_t tbytes = get_field(q->qh.token, QTD_TOKEN_TBYTES); - if (p->tbytes && p->pid == USB_TOKEN_IN) { - p->tbytes -= p->usb_status; + if (tbytes && p->pid == USB_TOKEN_IN) { + tbytes -= p->usb_status; } else { - p->tbytes = 0; + tbytes = 0; } - DPRINTF("updating tbytes to %d\n", p->tbytes); - set_field(&q->qh.token, p->tbytes, QTD_TOKEN_TBYTES); + DPRINTF("updating tbytes to %d\n", tbytes); + set_field(&q->qh.token, tbytes, QTD_TOKEN_TBYTES); } ehci_finish_transfer(q, p->usb_status); usb_packet_unmap(&p->packet, &p->sgl); @@ -1544,8 +1544,7 @@ static int ehci_execute(EHCIPacket *p, const char *action) return USB_RET_PROCERR; } - p->tbytes = (p->qtd.token & QTD_TOKEN_TBYTES_MASK) >> QTD_TOKEN_TBYTES_SH; - if (p->tbytes > BUFF_SIZE) { + if (get_field(p->qtd.token, QTD_TOKEN_TBYTES) > BUFF_SIZE) { ehci_trace_guest_bug(p->queue->ehci, "guest requested more bytes than allowed"); return USB_RET_PROCERR; @@ -1582,10 +1581,9 @@ static int ehci_execute(EHCIPacket *p, const char *action) trace_usb_ehci_packet_action(p->queue, p, action); ret = usb_handle_packet(p->queue->dev, &p->packet); - DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd " - "(total %d) endp %x ret %d\n", + DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd endp %x ret %d\n", q->qhaddr, q->qh.next, q->qtdaddr, q->pid, - q->packet.iov.size, q->tbytes, endp, ret); + q->packet.iov.size, endp, ret); if (ret > BUFF_SIZE) { fprintf(stderr, "ret from usb_handle_packet > BUFF_SIZE\n"); From cf08a8a1f600b2ac25f72cf5736247f3e95cc43d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:14:00 +0200 Subject: [PATCH 1129/2270] ehci: Set int flag on a short input packet According to 4.15.1.2 an interrupt must be raised when a short packet is received. If we don't do this it may take a significant time for the guest to notice a short trasnfer has completed, since only the last td will have its IOC flag set, and a short transfer may complete in an earlier packet. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 82f4dbd15a..8b4e3c859e 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1508,6 +1508,10 @@ static void ehci_execute_complete(EHCIQueue *q) if (tbytes && p->pid == USB_TOKEN_IN) { tbytes -= p->usb_status; + if (tbytes) { + /* 4.15.1.2 must raise int on a short input packet */ + ehci_raise_irq(q->ehci, USBSTS_INT); + } } else { tbytes = 0; } From 0262f65aaae49d582e7d4e4b1b5c8cfe4cd19d6d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:14:01 +0200 Subject: [PATCH 1130/2270] ehci: Improve latency of interrupt delivery and async schedule scanning While doing various performance tests of reading from USB mass storage devices I noticed the following:: 1) When an async handled packet completes, we don't immediately report an interrupt to the guest, instead we wait for the frame-timer to run and report it from there 2) If 1) has been fixed and an async handled packet takes a while to complete, then async_stepdown will become a high value, which means that there will be a large latency before any new packets queued by the guest in response to the interrupt get seen 1) was done deliberately as part of commit f0ad01f92: http://www.kraxel.org/cgit/qemu/commit/?h=usb.57&id=f0ad01f92ca02eee7cadbfd225c5de753ebd5fce Since setting the interrupt immediately on async packet completion was causing issues with Linux guests, I believe this recently fixed Linux bug explains why this is happening: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commitdiff;h=361aabf395e4a23cf554cf4ec0c0c6963b8beb01 Note that we can *not* count on this fix being present in all Linux guests! I was hoping that the recently added support for Interrupt Threshold Control would fix the issues with Linux guests, but adding a simple ehci_commit_irq() call to ehci_async_bh() still caused problems with Linux guests. The problem is, that when doing ehci_commit_irq() from ehci_async_bh(), the "old" frindex value is used to calculate usbsts_frindex, and when the frame-timer then runs possibly very shortly after ehci_async_bh(), it increases the frame-timer, and thus any interrupts raised from that frame-timer run, will also get reported to the guest immediately, rather then being delayed to the next frame-timer run. Luckily the solution for this is simple, this means that we need to increase frindex before calling ehci_commit_irq() from ehci_async_bh(), which in the end boils down to simple calling ehci_frame_timer() instead of ehci_async_bh() from the bh. This may seem like it causes a lot of extra work to be done, but this is not true. Any work done from the frame-timer processing the periodic schedule is work which then does not need to be done the next time the frame timer runs, also the frame-timer will re-arm itself at (possibly) a later time then it was armed for saving a vmexit at that time. As an additional advantage moving to simply calling the frame-timer also fixes 2) as the packet completion will set async_stepdown to 0, and the re-arming of the timer with an async_stepdown of 0 ensures that any newly queued up packets get seen in a reasonable amount of time. This improves the speed (MB/s) of a Linux guest reading from a USB mass storage device by a factor of 1.5 - 1.7 with input pipelining disabled, and by a factor of 1.8 with input pipelining enabled. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 8b4e3c859e..f9ae05e71d 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1244,7 +1244,7 @@ static void ehci_opreg_write(void *ptr, hwaddr addr, s->usbcmd = val; /* Set usbcmd for ehci_update_halt() */ ehci_update_halt(s); s->async_stepdown = 0; - qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock)); + qemu_bh_schedule(s->async_bh); } break; @@ -2510,12 +2510,6 @@ static void ehci_frame_timer(void *opaque) } } -static void ehci_async_bh(void *opaque) -{ - EHCIState *ehci = opaque; - ehci_advance_async_state(ehci); -} - static const MemoryRegionOps ehci_mmio_caps_ops = { .read = ehci_caps_read, .valid.min_access_size = 1, @@ -2744,7 +2738,7 @@ static int usb_ehci_initfn(PCIDevice *dev) } s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s); - s->async_bh = qemu_bh_new(ehci_async_bh, s); + s->async_bh = qemu_bh_new(ehci_frame_timer, s); QTAILQ_INIT(&s->aqueues); QTAILQ_INIT(&s->pqueues); usb_packet_init(&s->ipacket); From 44272b0f88247e2d2960c0ef19b546c206a10080 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:14:02 +0200 Subject: [PATCH 1131/2270] ehci: Speed up the timer of raising int from the async schedule Often the guest will queue up new packets in response to a packet, in the async schedule with its IOC flag set, completing. By speeding up the frame-timer, we notice these new packets earlier. This increases the speed (MB/s) of a Linux guest reading from a USB mass storage device by a factor of 1.15 on top of the "Improve latency of interrupt delivery" speed-ups, both with and without input pipelining enabled. I've not tested the speed-up of this patch without the "Improve latency of interrupt delivery" patch. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index f9ae05e71d..d600f08f6b 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -443,6 +443,7 @@ struct EHCIState { uint64_t last_run_ns; uint32_t async_stepdown; + bool int_req_by_async; }; #define SET_LAST_RUN_CLOCK(s) \ @@ -1529,6 +1530,9 @@ static void ehci_execute_complete(EHCIQueue *q) if (q->qh.token & QTD_TOKEN_IOC) { ehci_raise_irq(q->ehci, USBSTS_INT); + if (q->async) { + q->ehci->int_req_by_async = true; + } } } @@ -2504,8 +2508,15 @@ static void ehci_frame_timer(void *opaque) } if (need_timer) { - expire_time = t_now + (get_ticks_per_sec() + /* If we've raised int, we speed up the timer, so that we quickly + * notice any new packets queued up in response */ + if (ehci->int_req_by_async && (ehci->usbsts & USBSTS_INT)) { + expire_time = t_now + get_ticks_per_sec() / (FRAME_TIMER_FREQ * 2); + ehci->int_req_by_async = false; + } else { + expire_time = t_now + (get_ticks_per_sec() * (ehci->async_stepdown+1) / FRAME_TIMER_FREQ); + } qemu_mod_timer(ehci->frame_timer, expire_time); } } From e3a36bce1d0123d003855f7731494e6d6f550fcc Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:14:03 +0200 Subject: [PATCH 1132/2270] ehci: Detect going in circles when filling the queue For ctrl endpoints Windows (atleast Win7) creates circular td lists, so far these were not a problem because we would stop filling the queue if altnext was set. Since further patches in this patchset remove the altnext check this does become a problem and we need detection for going in circles. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index d600f08f6b..8bd87c76d5 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -2073,7 +2073,7 @@ static int ehci_fill_queue(EHCIPacket *p) { EHCIQueue *q = p->queue; EHCIqtd qtd = p->qtd; - uint32_t qtdaddr; + uint32_t qtdaddr, start_addr = p->qtdaddr; for (;;) { if (NLPTR_TBIT(qtd.altnext) == 0) { @@ -2083,6 +2083,13 @@ static int ehci_fill_queue(EHCIPacket *p) break; } qtdaddr = qtd.next; + /* + * Detect circular td lists, Windows creates these, counting on the + * active bit going low after execution to make the queue stop. + */ + if (qtdaddr == start_addr) { + break; + } get_dwords(q->ehci, NLPTR_GET(qtdaddr), (uint32_t *) &qtd, sizeof(EHCIqtd) >> 2); ehci_trace_qtd(q, NLPTR_GET(qtdaddr), &qtd); From b4ea86649915eca5551a5166f76e7a9d9032de50 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:14:04 +0200 Subject: [PATCH 1133/2270] ehci: Retry to fill the queue while waiting for td completion If the guest is using multiple transfers to try and keep the usb bus busy / used at maximum efficiency, currently we would see / do the following: 1) submit transfer 1 to the device 2) submit transfer 2 to the device 3) report transfer 1 completion to guest 4) report transfer 2 completion to guest 5) submit transfer 1 to the device 6) report transfer 1 completion to guest 7) submit transfer 2 to the device 8) report transfer 2 completion to guest etc. So after the initial submission we would effectively only have 1 transfer in flight, rather then 2. This is caused by us not checking the queue for addition of new transfers by the guest (ie the resubmission of a recently finished transfer), while waiting for a pending transfer to complete. This patch does add a check for this, changing the sequence to: 1) submit transfer 1 to the device 2) submit transfer 2 to the device 3) report transfer 1 completion to guest 4) submit transfer 1 to the device 5) report transfer 2 completion to guest 6) submit transfer 2 to the device etc. Thus keeping 2 transfers in flight (most of the time, and always 1), as intended by the guest. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 8bd87c76d5..a02fe9642f 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -381,7 +381,7 @@ struct EHCIQueue { uint32_t qhaddr; /* address QH read from */ uint32_t qtdaddr; /* address QTD read from */ USBDevice *dev; - QTAILQ_HEAD(, EHCIPacket) packets; + QTAILQ_HEAD(pkts_head, EHCIPacket) packets; }; typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead; @@ -488,6 +488,7 @@ static const char *ehci_mmio_names[] = { static int ehci_state_executing(EHCIQueue *q); static int ehci_state_writeback(EHCIQueue *q); +static int ehci_fill_queue(EHCIPacket *p); static const char *nr2str(const char **n, size_t len, uint32_t nr) { @@ -1994,7 +1995,7 @@ static int ehci_state_fetchqtd(EHCIQueue *q) { EHCIqtd qtd; EHCIPacket *p; - int again = 0; + int again = 1; get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &qtd, sizeof(EHCIqtd) >> 2); @@ -2022,7 +2023,6 @@ static int ehci_state_fetchqtd(EHCIQueue *q) p = NULL; } ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); - again = 1; } else if (p != NULL) { switch (p->async) { case EHCI_ASYNC_NONE: @@ -2031,6 +2031,9 @@ static int ehci_state_fetchqtd(EHCIQueue *q) ehci_set_state(q->ehci, q->async, EST_EXECUTE); break; case EHCI_ASYNC_INFLIGHT: + /* Check if the guest has added new tds to the queue */ + again = (ehci_fill_queue(QTAILQ_LAST(&q->packets, pkts_head)) == + USB_RET_PROCERR) ? -1 : 1; /* Unfinished async handled packet, go horizontal */ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); break; @@ -2042,13 +2045,11 @@ static int ehci_state_fetchqtd(EHCIQueue *q) ehci_set_state(q->ehci, q->async, EST_EXECUTING); break; } - again = 1; } else { p = ehci_alloc_packet(q); p->qtdaddr = q->qtdaddr; p->qtd = qtd; ehci_set_state(q->ehci, q->async, EST_EXECUTE); - again = 1; } return again; From 3151f2096dd676dc42e81ef0d55ae80780fd8769 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:14:05 +0200 Subject: [PATCH 1134/2270] xhci: Add a xhci_ep_nuke_one_xfer helper function Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 49 +++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 37b3dbbcb6..47d5702d1e 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1082,6 +1082,35 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, return CC_SUCCESS; } +static int xhci_ep_nuke_one_xfer(XHCITransfer *t) +{ + int killed = 0; + + if (t->running_async) { + usb_cancel_packet(&t->packet); + t->running_async = 0; + t->cancelled = 1; + DPRINTF("xhci: cancelling transfer, waiting for it to complete\n"); + killed = 1; + } + if (t->running_retry) { + XHCIEPContext *epctx = t->xhci->slots[t->slotid-1].eps[t->epid-1]; + if (epctx) { + epctx->retry = NULL; + qemu_del_timer(epctx->kick_timer); + } + t->running_retry = 0; + } + if (t->trbs) { + g_free(t->trbs); + } + + t->trbs = NULL; + t->trb_count = t->trb_alloced = 0; + + return killed; +} + static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid, unsigned int epid) { @@ -1103,25 +1132,7 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid, xferi = epctx->next_xfer; for (i = 0; i < TD_QUEUE; i++) { - XHCITransfer *t = &epctx->transfers[xferi]; - if (t->running_async) { - usb_cancel_packet(&t->packet); - t->running_async = 0; - t->cancelled = 1; - DPRINTF("xhci: cancelling transfer %d, waiting for it to complete...\n", i); - killed++; - } - if (t->running_retry) { - t->running_retry = 0; - epctx->retry = NULL; - qemu_del_timer(epctx->kick_timer); - } - if (t->trbs) { - g_free(t->trbs); - } - - t->trbs = NULL; - t->trb_count = t->trb_alloced = 0; + killed += xhci_ep_nuke_one_xfer(&epctx->transfers[xferi]); xferi = (xferi + 1) % TD_QUEUE; } return killed; From d0ff81b871af3c6cf31c807dfdd480b9d1032780 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:14:06 +0200 Subject: [PATCH 1135/2270] usb: Rename __usb_packet_complete to usb_packet_complete_one And make it available for use outside of core.c Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb.h | 1 + hw/usb/core.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/usb.h b/hw/usb.h index 48c8926a76..01dd423629 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -370,6 +370,7 @@ USBDevice *usb_find_device(USBPort *port, uint8_t addr); int usb_handle_packet(USBDevice *dev, USBPacket *p); void usb_packet_complete(USBDevice *dev, USBPacket *p); +void usb_packet_complete_one(USBDevice *dev, USBPacket *p); void usb_cancel_packet(USBPacket * p); void usb_ep_init(USBDevice *dev); diff --git a/hw/usb/core.c b/hw/usb/core.c index b9f1f7a8be..e2e31ca439 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -412,10 +412,11 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) return ret; } -static void __usb_packet_complete(USBDevice *dev, USBPacket *p) +void usb_packet_complete_one(USBDevice *dev, USBPacket *p) { USBEndpoint *ep = p->ep; + assert(QTAILQ_FIRST(&ep->queue) == p); assert(p->result != USB_RET_ASYNC && p->result != USB_RET_NAK); if (p->result < 0) { @@ -435,8 +436,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p) int ret; usb_packet_check_state(p, USB_PACKET_ASYNC); - assert(QTAILQ_FIRST(&ep->queue) == p); - __usb_packet_complete(dev, p); + usb_packet_complete_one(dev, p); while (!ep->halted && !QTAILQ_EMPTY(&ep->queue)) { p = QTAILQ_FIRST(&ep->queue); @@ -450,7 +450,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p) break; } p->result = ret; - __usb_packet_complete(ep->dev, p); + usb_packet_complete_one(ep->dev, p); } } From 36dfe324fd4b5efd9ef1a5b4c352bbb158952e24 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:14:07 +0200 Subject: [PATCH 1136/2270] usb: Add USB_RET_ADD_TO_QUEUE packet result code This can be used by usb-device code which wishes to process an entire endpoint queue at once, to do this the usb-device code returns USB_RET_ADD_TO_QUEUE from its handle_data class method and defines a flush_ep_queue class method to call when the hcd is done queuing up packets. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb.h | 21 +++++++++++++++------ hw/usb/bus.c | 8 ++++++++ hw/usb/core.c | 4 ++++ hw/usb/hcd-ehci.c | 4 ++++ hw/usb/hcd-musb.c | 1 + hw/usb/hcd-ohci.c | 2 ++ hw/usb/hcd-uhci.c | 16 +++++++++++----- hw/usb/hcd-xhci.c | 6 ++++++ 8 files changed, 51 insertions(+), 11 deletions(-) diff --git a/hw/usb.h b/hw/usb.h index 01dd423629..435cd42a03 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -38,12 +38,13 @@ #define USB_TOKEN_IN 0x69 /* device -> host */ #define USB_TOKEN_OUT 0xe1 /* host -> device */ -#define USB_RET_NODEV (-1) -#define USB_RET_NAK (-2) -#define USB_RET_STALL (-3) -#define USB_RET_BABBLE (-4) -#define USB_RET_IOERROR (-5) -#define USB_RET_ASYNC (-6) +#define USB_RET_NODEV (-1) +#define USB_RET_NAK (-2) +#define USB_RET_STALL (-3) +#define USB_RET_BABBLE (-4) +#define USB_RET_IOERROR (-5) +#define USB_RET_ASYNC (-6) +#define USB_RET_ADD_TO_QUEUE (-7) #define USB_SPEED_LOW 0 #define USB_SPEED_FULL 1 @@ -293,6 +294,12 @@ typedef struct USBDeviceClass { void (*set_interface)(USBDevice *dev, int interface, int alt_old, int alt_new); + /* + * Called when the hcd is done queuing packets for an endpoint, only + * necessary for devices which can return USB_RET_ADD_TO_QUEUE. + */ + void (*flush_ep_queue)(USBDevice *dev, USBEndpoint *ep); + const char *product_desc; const USBDesc *usb_desc; } USBDeviceClass; @@ -507,6 +514,8 @@ int usb_device_handle_data(USBDevice *dev, USBPacket *p); void usb_device_set_interface(USBDevice *dev, int interface, int alt_old, int alt_new); +void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep); + const char *usb_device_get_product_desc(USBDevice *dev); const USBDesc *usb_device_get_usb_desc(USBDevice *dev); diff --git a/hw/usb/bus.c b/hw/usb/bus.c index b649360dd3..8066291b34 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -181,6 +181,14 @@ void usb_device_set_interface(USBDevice *dev, int interface, } } +void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep) +{ + USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); + if (klass->flush_ep_queue) { + klass->flush_ep_queue(dev, ep); + } +} + static int usb_qdev_init(DeviceState *qdev) { USBDevice *dev = USB_DEVICE(qdev); diff --git a/hw/usb/core.c b/hw/usb/core.c index e2e31ca439..014e3ac090 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -393,6 +393,10 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) if (ret == USB_RET_ASYNC) { usb_packet_set_state(p, USB_PACKET_ASYNC); QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue); + } else if (ret == USB_RET_ADD_TO_QUEUE) { + usb_packet_set_state(p, USB_PACKET_QUEUED); + QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue); + ret = USB_RET_ASYNC; } else { /* * When pipelining is enabled usb-devices must always return async, diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index a02fe9642f..d11311e87f 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -2072,6 +2072,7 @@ static int ehci_state_horizqh(EHCIQueue *q) static int ehci_fill_queue(EHCIPacket *p) { + USBEndpoint *ep = p->packet.ep; EHCIQueue *q = p->queue; EHCIqtd qtd = p->qtd; uint32_t qtdaddr, start_addr = p->qtdaddr; @@ -2107,6 +2108,9 @@ static int ehci_fill_queue(EHCIPacket *p) assert(p->usb_status == USB_RET_ASYNC); p->async = EHCI_ASYNC_INFLIGHT; } + if (p->usb_status != USB_RET_PROCERR) { + usb_device_flush_ep_queue(ep->dev, ep); + } return p->usb_status; } diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c index dc114fed2a..212dd12fc7 100644 --- a/hw/usb/hcd-musb.c +++ b/hw/usb/hcd-musb.c @@ -635,6 +635,7 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep, ret = usb_handle_packet(dev, &ep->packey[dir].p); if (ret == USB_RET_ASYNC) { + usb_device_flush_ep_queue(dev, uep); ep->status[dir] = len; return; } diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 0cc1e5de85..31dcfbb0c6 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -816,6 +816,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len); ret = usb_handle_packet(dev, &ohci->usb_packet); if (ret == USB_RET_ASYNC) { + usb_device_flush_ep_queue(dev, ep); return 1; } } @@ -1018,6 +1019,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) DPRINTF("ret=%d\n", ret); #endif if (ret == USB_RET_ASYNC) { + usb_device_flush_ep_queue(dev, ep); ohci->async_td = addr; return 1; } diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 600d095573..46e544b910 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -818,7 +818,8 @@ out: } static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, - uint32_t *int_mask, bool queuing) + uint32_t *int_mask, bool queuing, + struct USBEndpoint **ep_ret) { UHCIAsync *async; int len = 0, max_len; @@ -870,6 +871,9 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, dev = uhci_find_device(s, (td->token >> 8) & 0x7f); ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf); + if (ep_ret) { + *ep_ret = ep; + } usb_packet_setup(&async->packet, pid, ep, addr); qemu_sglist_add(&async->sgl, td->buffer, max_len); usb_packet_map(&async->packet, &async->sgl); @@ -983,7 +987,7 @@ static int qhdb_insert(QhDb *db, uint32_t addr) return 0; } -static void uhci_fill_queue(UHCIState *s, UHCI_TD *td) +static void uhci_fill_queue(UHCIState *s, UHCI_TD *td, struct USBEndpoint *ep) { uint32_t int_mask = 0; uint32_t plink = td->link; @@ -1005,7 +1009,7 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td) break; } trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token); - ret = uhci_handle_td(s, plink, &ptd, &int_mask, true); + ret = uhci_handle_td(s, plink, &ptd, &int_mask, true, NULL); if (ret == TD_RESULT_ASYNC_CONT) { break; } @@ -1013,12 +1017,14 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td) assert(int_mask == 0); plink = ptd.link; } + usb_device_flush_ep_queue(ep->dev, ep); } static void uhci_process_frame(UHCIState *s) { uint32_t frame_addr, link, old_td_ctrl, val, int_mask; uint32_t curr_qh, td_count = 0; + struct USBEndpoint *curr_ep; int cnt, ret; UHCI_TD td; UHCI_QH qh; @@ -1089,7 +1095,7 @@ static void uhci_process_frame(UHCIState *s) trace_usb_uhci_td_load(curr_qh & ~0xf, link & ~0xf, td.ctrl, td.token); old_td_ctrl = td.ctrl; - ret = uhci_handle_td(s, link, &td, &int_mask, false); + ret = uhci_handle_td(s, link, &td, &int_mask, false, &curr_ep); if (old_td_ctrl != td.ctrl) { /* update the status bits of the TD */ val = cpu_to_le32(td.ctrl); @@ -1108,7 +1114,7 @@ static void uhci_process_frame(UHCIState *s) case TD_RESULT_ASYNC_START: trace_usb_uhci_td_async(curr_qh & ~0xf, link & ~0xf); - uhci_fill_queue(s, &td); + uhci_fill_queue(s, &td, curr_ep); link = curr_qh ? qh.link : td.link; continue; diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 47d5702d1e..e8929a0785 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1652,6 +1652,7 @@ static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid) { XHCIEPContext *epctx; + USBEndpoint *ep = NULL; uint64_t mfindex; int length; int i; @@ -1745,12 +1746,14 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid if (epid == 1) { if (xhci_fire_ctl_transfer(xhci, xfer) >= 0) { epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE; + ep = xfer->packet.ep; } else { fprintf(stderr, "xhci: error firing CTL transfer\n"); } } else { if (xhci_fire_transfer(xhci, xfer, epctx) >= 0) { epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE; + ep = xfer->packet.ep; } else { if (!xfer->iso_xfer) { fprintf(stderr, "xhci: error firing data transfer\n"); @@ -1767,6 +1770,9 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid break; } } + if (ep) { + usb_device_flush_ep_queue(ep->dev, ep); + } } static TRBCCode xhci_enable_slot(XHCIState *xhci, unsigned int slotid) From 0cae7b1a004d6857e3bde3d511d7efa39d3cb48a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:14:08 +0200 Subject: [PATCH 1137/2270] usb: Move clearing of queue on halt to the core hcds which queue up more then one packet at once (uhci, ehci and xhci), must clear the queue after an error which has caused the queue to halt. Currently this is handled as a special case inside the hcd code, this patch instead adds an USB_RET_REMOVE_FROM_QUEUE packet result code, teaches the 3 hcds about this and moves the clearing of the queue on a halt into the USB core. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb.h | 1 + hw/usb/core.c | 8 +++++++- hw/usb/hcd-ehci.c | 22 ++++++++-------------- hw/usb/hcd-uhci.c | 22 ++++++---------------- hw/usb/hcd-xhci.c | 4 ++++ 5 files changed, 26 insertions(+), 31 deletions(-) diff --git a/hw/usb.h b/hw/usb.h index 435cd42a03..ead03c9f6b 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -45,6 +45,7 @@ #define USB_RET_IOERROR (-5) #define USB_RET_ASYNC (-6) #define USB_RET_ADD_TO_QUEUE (-7) +#define USB_RET_REMOVE_FROM_QUEUE (-8) #define USB_SPEED_LOW 0 #define USB_SPEED_FULL 1 diff --git a/hw/usb/core.c b/hw/usb/core.c index 014e3ac090..5a97a0e412 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -442,8 +442,14 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p) usb_packet_check_state(p, USB_PACKET_ASYNC); usb_packet_complete_one(dev, p); - while (!ep->halted && !QTAILQ_EMPTY(&ep->queue)) { + while (!QTAILQ_EMPTY(&ep->queue)) { p = QTAILQ_FIRST(&ep->queue); + if (ep->halted) { + /* Empty the queue on a halt */ + p->result = USB_RET_REMOVE_FROM_QUEUE; + dev->port->ops->complete(dev->port, p); + continue; + } if (p->state == USB_PACKET_ASYNC) { break; } diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index d11311e87f..74a2587eba 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1457,8 +1457,15 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet) } p = container_of(packet, EHCIPacket, packet); - trace_usb_ehci_packet_action(p->queue, p, "wakeup"); assert(p->async == EHCI_ASYNC_INFLIGHT); + + if (packet->result == USB_RET_REMOVE_FROM_QUEUE) { + trace_usb_ehci_packet_action(p->queue, p, "remove"); + ehci_free_packet(p); + return; + } + + trace_usb_ehci_packet_action(p->queue, p, "wakeup"); p->async = EHCI_ASYNC_FINISHED; p->usb_status = packet->result; @@ -2216,19 +2223,6 @@ static int ehci_state_writeback(EHCIQueue *q) * bit is clear. */ if (q->qh.token & QTD_TOKEN_HALT) { - /* - * We should not do any further processing on a halted queue! - * This is esp. important for bulk endpoints with pipelining enabled - * (redirection to a real USB device), where we must cancel all the - * transfers after this one so that: - * 1) If they've completed already, they are not processed further - * causing more stalls, originating from the same failed transfer - * 2) If still in flight, they are cancelled before the guest does - * a clear stall, otherwise the guest and device can loose sync! - */ - while ((p = QTAILQ_FIRST(&q->packets)) != NULL) { - ehci_free_packet(p); - } ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); again = 1; } else { diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 46e544b910..00dc9d538f 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -744,22 +744,6 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_ return TD_RESULT_COMPLETE; out: - /* - * We should not do any further processing on a queue with errors! - * This is esp. important for bulk endpoints with pipelining enabled - * (redirection to a real USB device), where we must cancel all the - * transfers after this one so that: - * 1) If they've completed already, they are not processed further - * causing more stalls, originating from the same failed transfer - * 2) If still in flight, they are cancelled before the guest does - * a clear stall, otherwise the guest and device can loose sync! - */ - while (!QTAILQ_EMPTY(&async->queue->asyncs)) { - UHCIAsync *as = QTAILQ_FIRST(&async->queue->asyncs); - uhci_async_unlink(as); - uhci_async_cancel(as); - } - switch(ret) { case USB_RET_STALL: td->ctrl |= TD_CTRL_STALL; @@ -918,6 +902,12 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet) UHCIAsync *async = container_of(packet, UHCIAsync, packet); UHCIState *s = async->queue->uhci; + if (packet->result == USB_RET_REMOVE_FROM_QUEUE) { + uhci_async_unlink(async); + uhci_async_cancel(async); + return; + } + if (async->isoc) { UHCI_TD td; uint32_t link = async->td; diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index e8929a0785..1f437cc15f 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2839,6 +2839,10 @@ static void xhci_complete(USBPort *port, USBPacket *packet) { XHCITransfer *xfer = container_of(packet, XHCITransfer, packet); + if (packet->result == USB_RET_REMOVE_FROM_QUEUE) { + xhci_ep_nuke_one_xfer(xfer); + return; + } xhci_complete_packet(xfer, packet->result); xhci_kick_ep(xfer->xhci, xfer->slotid, xfer->epid); } From 6ba43f1f6b60159e731b1f37ffb53ab9ab59efa9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:14:09 +0200 Subject: [PATCH 1138/2270] usb: Move short-not-ok handling to the core After a short-not-ok packet ending short, we should not advance the queue. Move enforcing this to the core, rather then handling it in the hcd code. This may result in the queue now actually containing multiple input packets (which would not happen before), and this requires special handling in combination with pipelining, so disable pipleining for input endpoints (for now). Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb.h | 4 +++- hw/usb/core.c | 6 ++++-- hw/usb/hcd-ehci.c | 9 ++++----- hw/usb/hcd-musb.c | 2 +- hw/usb/hcd-ohci.c | 4 ++-- hw/usb/hcd-uhci.c | 7 ++++--- hw/usb/hcd-xhci.c | 2 +- hw/usb/host-linux.c | 3 ++- hw/usb/redirect.c | 18 ++++++++++++------ 9 files changed, 33 insertions(+), 22 deletions(-) diff --git a/hw/usb.h b/hw/usb.h index ead03c9f6b..1fcf79c72f 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -351,6 +351,7 @@ struct USBPacket { USBEndpoint *ep; QEMUIOVector iov; uint64_t parameter; /* control transfers */ + bool short_not_ok; int result; /* transfer length or USB_RET_* status code */ /* Internal use by the USB layer. */ USBPacketState state; @@ -360,7 +361,8 @@ struct USBPacket { void usb_packet_init(USBPacket *p); void usb_packet_set_state(USBPacket *p, USBPacketState state); void usb_packet_check_state(USBPacket *p, USBPacketState expected); -void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id); +void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id, + bool short_not_ok); void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len); int usb_packet_map(USBPacket *p, QEMUSGList *sgl); void usb_packet_unmap(USBPacket *p, QEMUSGList *sgl); diff --git a/hw/usb/core.c b/hw/usb/core.c index 5a97a0e412..f4a5ad2333 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -423,7 +423,7 @@ void usb_packet_complete_one(USBDevice *dev, USBPacket *p) assert(QTAILQ_FIRST(&ep->queue) == p); assert(p->result != USB_RET_ASYNC && p->result != USB_RET_NAK); - if (p->result < 0) { + if (p->result < 0 || (p->short_not_ok && (p->result < p->iov.size))) { ep->halted = true; } usb_packet_set_state(p, USB_PACKET_COMPLETE); @@ -532,7 +532,8 @@ void usb_packet_set_state(USBPacket *p, USBPacketState state) p->state = state; } -void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id) +void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id, + bool short_not_ok) { assert(!usb_packet_is_inflight(p)); assert(p->iov.iov != NULL); @@ -541,6 +542,7 @@ void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id) p->ep = ep; p->result = 0; p->parameter = 0; + p->short_not_ok = short_not_ok; qemu_iovec_reset(&p->iov); usb_packet_set_state(p, USB_PACKET_SETUP); } diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 74a2587eba..8e8ec6b6c5 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1551,6 +1551,7 @@ static int ehci_execute(EHCIPacket *p, const char *action) USBEndpoint *ep; int ret; int endp; + bool spd; assert(p->async == EHCI_ASYNC_NONE || p->async == EHCI_ASYNC_INITIALIZED); @@ -1590,7 +1591,8 @@ static int ehci_execute(EHCIPacket *p, const char *action) return USB_RET_PROCERR; } - usb_packet_setup(&p->packet, p->pid, ep, p->qtdaddr); + spd = (p->pid == USB_TOKEN_IN && NLPTR_TBIT(p->qtd.altnext) == 0); + usb_packet_setup(&p->packet, p->pid, ep, p->qtdaddr, spd); usb_packet_map(&p->packet, &p->sgl); p->async = EHCI_ASYNC_INITIALIZED; } @@ -1660,7 +1662,7 @@ static int ehci_process_itd(EHCIState *ehci, dev = ehci_find_device(ehci, devaddr); ep = usb_ep_get(dev, pid, endp); if (ep && ep->type == USB_ENDPOINT_XFER_ISOC) { - usb_packet_setup(&ehci->ipacket, pid, ep, addr); + usb_packet_setup(&ehci->ipacket, pid, ep, addr, false); usb_packet_map(&ehci->ipacket, &ehci->isgl); ret = usb_handle_packet(dev, &ehci->ipacket); assert(ret != USB_RET_ASYNC); @@ -2085,9 +2087,6 @@ static int ehci_fill_queue(EHCIPacket *p) uint32_t qtdaddr, start_addr = p->qtdaddr; for (;;) { - if (NLPTR_TBIT(qtd.altnext) == 0) { - break; - } if (NLPTR_TBIT(qtd.next) != 0) { break; } diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c index 212dd12fc7..c4309a4e6b 100644 --- a/hw/usb/hcd-musb.c +++ b/hw/usb/hcd-musb.c @@ -627,7 +627,7 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep, dev = usb_find_device(&s->port, ep->faddr[idx]); uep = usb_ep_get(dev, pid, ep->type[idx] & 0xf); usb_packet_setup(&ep->packey[dir].p, pid, uep, - (dev->addr << 16) | (uep->nr << 8) | pid); + (dev->addr << 16) | (uep->nr << 8) | pid, false); usb_packet_addbuf(&ep->packey[dir].p, ep->buf[idx], len); ep->packey[dir].ep = ep; ep->packey[dir].dir = dir; diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 31dcfbb0c6..00e2e1acac 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -812,7 +812,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, } else { dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); - usb_packet_setup(&ohci->usb_packet, pid, ep, addr); + usb_packet_setup(&ohci->usb_packet, pid, ep, addr, false); usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len); ret = usb_handle_packet(dev, &ohci->usb_packet); if (ret == USB_RET_ASYNC) { @@ -1012,7 +1012,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) } dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); - usb_packet_setup(&ohci->usb_packet, pid, ep, addr); + usb_packet_setup(&ohci->usb_packet, pid, ep, addr, !flag_r); usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen); ret = usb_handle_packet(dev, &ohci->usb_packet); #ifdef DEBUG_PACKET diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 00dc9d538f..953897b64c 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -808,6 +808,7 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, UHCIAsync *async; int len = 0, max_len; uint8_t pid; + bool spd; USBDevice *dev; USBEndpoint *ep; @@ -852,13 +853,14 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, max_len = ((td->token >> 21) + 1) & 0x7ff; pid = td->token & 0xff; + spd = (pid == USB_TOKEN_IN && (td->ctrl & TD_CTRL_SPD) != 0); dev = uhci_find_device(s, (td->token >> 8) & 0x7f); ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf); if (ep_ret) { *ep_ret = ep; } - usb_packet_setup(&async->packet, pid, ep, addr); + usb_packet_setup(&async->packet, pid, ep, addr, spd); qemu_sglist_add(&async->sgl, td->buffer, max_len); usb_packet_map(&async->packet, &async->sgl); @@ -985,8 +987,7 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td, struct USBEndpoint *ep) UHCI_TD ptd; int ret; - ptd.ctrl = td->ctrl; - while (is_valid(plink) && !(ptd.ctrl & TD_CTRL_SPD)) { + while (is_valid(plink)) { pci_dma_read(&s->dev, plink & ~0xf, &ptd, sizeof(ptd)); le32_to_cpus(&ptd.link); le32_to_cpus(&ptd.ctrl); diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 1f437cc15f..ebfc5b892f 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1446,7 +1446,7 @@ static int xhci_setup_packet(XHCITransfer *xfer) ep = usb_ep_get(dev, dir, xfer->epid >> 1); } - usb_packet_setup(&xfer->packet, dir, ep, xfer->trbs[0].addr); + usb_packet_setup(&xfer->packet, dir, ep, xfer->trbs[0].addr, false); xhci_xfer_map(xfer); DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n", xfer->packet.pid, dev->addr, ep->nr); diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c index 44f1a64b35..3a258b4bd4 100644 --- a/hw/usb/host-linux.c +++ b/hw/usb/host-linux.c @@ -1224,7 +1224,8 @@ static int usb_linux_update_endp_table(USBHostDevice *s) usb_ep_set_type(&s->dev, pid, ep, type); usb_ep_set_ifnum(&s->dev, pid, ep, interface); if ((s->options & (1 << USB_HOST_OPT_PIPELINE)) && - (type == USB_ENDPOINT_XFER_BULK)) { + (type == USB_ENDPOINT_XFER_BULK) && + (pid == USB_TOKEN_OUT)) { usb_ep_set_pipeline(&s->dev, pid, ep, true); } diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 2283565b0c..22f671b3b1 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1270,6 +1270,16 @@ static void usbredir_interface_info(void *priv, } } +static void usbredir_set_pipeline(USBRedirDevice *dev, struct USBEndpoint *uep) +{ + if (uep->type != USB_ENDPOINT_XFER_BULK) { + return; + } + if (uep->pid == USB_TOKEN_OUT) { + uep->pipeline = true; + } +} + static void usbredir_ep_info(void *priv, struct usb_redir_ep_info_header *ep_info) { @@ -1311,9 +1321,7 @@ static void usbredir_ep_info(void *priv, dev->endpoint[i].max_packet_size = usb_ep->max_packet_size = ep_info->max_packet_size[i]; } - if (ep_info->type[i] == usb_redir_type_bulk) { - usb_ep->pipeline = true; - } + usbredir_set_pipeline(dev, usb_ep); } } @@ -1574,9 +1582,7 @@ static int usbredir_post_load(void *priv, int version_id) usb_ep->type = dev->endpoint[i].type; usb_ep->ifnum = dev->endpoint[i].interface; usb_ep->max_packet_size = dev->endpoint[i].max_packet_size; - if (dev->endpoint[i].type == usb_redir_type_bulk) { - usb_ep->pipeline = true; - } + usbredir_set_pipeline(dev, usb_ep); } return 0; } From a6fb2ddb1417fcc2d24f3231c84035fcbd90123a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:14:10 +0200 Subject: [PATCH 1139/2270] usb: Add an int_req flag to USBPacket Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb.h | 3 ++- hw/usb/core.c | 3 ++- hw/usb/hcd-ehci.c | 6 ++++-- hw/usb/hcd-musb.c | 2 +- hw/usb/hcd-ohci.c | 7 +++++-- hw/usb/hcd-uhci.c | 3 ++- hw/usb/hcd-xhci.c | 16 +++++++++++----- 7 files changed, 27 insertions(+), 13 deletions(-) diff --git a/hw/usb.h b/hw/usb.h index 1fcf79c72f..3a6cc8444a 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -352,6 +352,7 @@ struct USBPacket { QEMUIOVector iov; uint64_t parameter; /* control transfers */ bool short_not_ok; + bool int_req; int result; /* transfer length or USB_RET_* status code */ /* Internal use by the USB layer. */ USBPacketState state; @@ -362,7 +363,7 @@ void usb_packet_init(USBPacket *p); void usb_packet_set_state(USBPacket *p, USBPacketState state); void usb_packet_check_state(USBPacket *p, USBPacketState expected); void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id, - bool short_not_ok); + bool short_not_ok, bool int_req); void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len); int usb_packet_map(USBPacket *p, QEMUSGList *sgl); void usb_packet_unmap(USBPacket *p, QEMUSGList *sgl); diff --git a/hw/usb/core.c b/hw/usb/core.c index f4a5ad2333..87a513fa7e 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -533,7 +533,7 @@ void usb_packet_set_state(USBPacket *p, USBPacketState state) } void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id, - bool short_not_ok) + bool short_not_ok, bool int_req) { assert(!usb_packet_is_inflight(p)); assert(p->iov.iov != NULL); @@ -543,6 +543,7 @@ void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id, p->result = 0; p->parameter = 0; p->short_not_ok = short_not_ok; + p->int_req = int_req; qemu_iovec_reset(&p->iov); usb_packet_set_state(p, USB_PACKET_SETUP); } diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 8e8ec6b6c5..8ac78adf95 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1592,7 +1592,8 @@ static int ehci_execute(EHCIPacket *p, const char *action) } spd = (p->pid == USB_TOKEN_IN && NLPTR_TBIT(p->qtd.altnext) == 0); - usb_packet_setup(&p->packet, p->pid, ep, p->qtdaddr, spd); + usb_packet_setup(&p->packet, p->pid, ep, p->qtdaddr, spd, + (p->qtd.token & QTD_TOKEN_IOC) != 0); usb_packet_map(&p->packet, &p->sgl); p->async = EHCI_ASYNC_INITIALIZED; } @@ -1662,7 +1663,8 @@ static int ehci_process_itd(EHCIState *ehci, dev = ehci_find_device(ehci, devaddr); ep = usb_ep_get(dev, pid, endp); if (ep && ep->type == USB_ENDPOINT_XFER_ISOC) { - usb_packet_setup(&ehci->ipacket, pid, ep, addr, false); + usb_packet_setup(&ehci->ipacket, pid, ep, addr, false, + (itd->transact[i] & ITD_XACT_IOC) != 0); usb_packet_map(&ehci->ipacket, &ehci->isgl); ret = usb_handle_packet(dev, &ehci->ipacket); assert(ret != USB_RET_ASYNC); diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c index c4309a4e6b..4f5539020b 100644 --- a/hw/usb/hcd-musb.c +++ b/hw/usb/hcd-musb.c @@ -627,7 +627,7 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep, dev = usb_find_device(&s->port, ep->faddr[idx]); uep = usb_ep_get(dev, pid, ep->type[idx] & 0xf); usb_packet_setup(&ep->packey[dir].p, pid, uep, - (dev->addr << 16) | (uep->nr << 8) | pid, false); + (dev->addr << 16) | (uep->nr << 8) | pid, false, true); usb_packet_addbuf(&ep->packey[dir].p, ep->buf[idx], len); ep->packey[dir].ep = ep; ep->packey[dir].dir = dir; diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 00e2e1acac..7571e9e44a 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -810,9 +810,11 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, if (completion) { ret = ohci->usb_packet.result; } else { + bool int_req = relative_frame_number == frame_count && + OHCI_BM(iso_td.flags, TD_DI) == 0; dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); - usb_packet_setup(&ohci->usb_packet, pid, ep, addr, false); + usb_packet_setup(&ohci->usb_packet, pid, ep, addr, false, int_req); usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len); ret = usb_handle_packet(dev, &ohci->usb_packet); if (ret == USB_RET_ASYNC) { @@ -1012,7 +1014,8 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) } dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); - usb_packet_setup(&ohci->usb_packet, pid, ep, addr, !flag_r); + usb_packet_setup(&ohci->usb_packet, pid, ep, addr, !flag_r, + OHCI_BM(td.flags, TD_DI) == 0); usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen); ret = usb_handle_packet(dev, &ohci->usb_packet); #ifdef DEBUG_PACKET diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 953897b64c..4a1ea6b436 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -860,7 +860,8 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, if (ep_ret) { *ep_ret = ep; } - usb_packet_setup(&async->packet, pid, ep, addr, spd); + usb_packet_setup(&async->packet, pid, ep, addr, spd, + (td->ctrl & TD_CTRL_IOC) != 0); qemu_sglist_add(&async->sgl, td->buffer, max_len); usb_packet_map(&async->packet, &async->sgl); diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index ebfc5b892f..caa5f3e36a 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -322,6 +322,7 @@ typedef struct XHCITransfer { bool running_retry; bool cancelled; bool complete; + bool int_req; unsigned int iso_pkts; unsigned int slotid; unsigned int epid; @@ -1292,18 +1293,22 @@ static TRBCCode xhci_set_ep_dequeue(XHCIState *xhci, unsigned int slotid, return CC_SUCCESS; } -static int xhci_xfer_map(XHCITransfer *xfer) +static int xhci_xfer_create_sgl(XHCITransfer *xfer, int in_xfer) { - int in_xfer = (xfer->packet.pid == USB_TOKEN_IN); XHCIState *xhci = xfer->xhci; int i; + xfer->int_req = false; pci_dma_sglist_init(&xfer->sgl, &xhci->pci_dev, xfer->trb_count); for (i = 0; i < xfer->trb_count; i++) { XHCITRB *trb = &xfer->trbs[i]; dma_addr_t addr; unsigned int chunk = 0; + if (trb->control & TRB_TR_IOC) { + xfer->int_req = true; + } + switch (TRB_TYPE(*trb)) { case TR_DATA: if ((!(trb->control & TRB_TR_DIR)) != (!in_xfer)) { @@ -1328,7 +1333,6 @@ static int xhci_xfer_map(XHCITransfer *xfer) } } - usb_packet_map(&xfer->packet, &xfer->sgl); return 0; err: @@ -1446,8 +1450,10 @@ static int xhci_setup_packet(XHCITransfer *xfer) ep = usb_ep_get(dev, dir, xfer->epid >> 1); } - usb_packet_setup(&xfer->packet, dir, ep, xfer->trbs[0].addr, false); - xhci_xfer_map(xfer); + xhci_xfer_create_sgl(xfer, dir == USB_TOKEN_IN); /* Also sets int_req */ + usb_packet_setup(&xfer->packet, dir, ep, xfer->trbs[0].addr, false, + xfer->int_req); + usb_packet_map(&xfer->packet, &xfer->sgl); DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n", xfer->packet.pid, dev->addr, ep->nr); return 0; From aaac74343d761947e57a1b0cbaa7f2dd0c6a40ca Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:04 +0200 Subject: [PATCH 1140/2270] usb: Enforce iso endpoints never returing USB_RET_ASYNC ehci was already testing for this, and we depend in various places on no devices doing this, so lets move the check for this to the usb core. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/core.c | 1 + hw/usb/hcd-ehci.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb/core.c b/hw/usb/core.c index 87a513fa7e..632a8efe47 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -391,6 +391,7 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) { ret = usb_process_one(p); if (ret == USB_RET_ASYNC) { + assert(p->ep->type != USB_ENDPOINT_XFER_ISOC); usb_packet_set_state(p, USB_PACKET_ASYNC); QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue); } else if (ret == USB_RET_ADD_TO_QUEUE) { diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 8ac78adf95..f14f9d7018 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1667,7 +1667,6 @@ static int ehci_process_itd(EHCIState *ehci, (itd->transact[i] & ITD_XACT_IOC) != 0); usb_packet_map(&ehci->ipacket, &ehci->isgl); ret = usb_handle_packet(dev, &ehci->ipacket); - assert(ret != USB_RET_ASYNC); usb_packet_unmap(&ehci->ipacket, &ehci->isgl); } else { DPRINTF("ISOCH: attempt to addess non-iso endpoint\n"); From 5b352ed537e31a6b5f9e33e26429ba8b909af234 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:05 +0200 Subject: [PATCH 1141/2270] uhci: No need to handle async completion of isoc packets No devices ever return async for isoc endpoints and the core already enforces this. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 4a1ea6b436..129792b662 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -101,7 +101,6 @@ struct UHCIAsync { UHCIQueue *queue; QTAILQ_ENTRY(UHCIAsync) next; uint32_t td; - uint8_t isoc; uint8_t done; }; @@ -849,7 +848,6 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, * for initial isochronous requests */ async->queue->valid = 32; - async->isoc = td->ctrl & TD_CTRL_IOS; max_len = ((td->token >> 21) + 1) & 0x7ff; pid = td->token & 0xff; @@ -911,30 +909,9 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet) return; } - if (async->isoc) { - UHCI_TD td; - uint32_t link = async->td; - uint32_t int_mask = 0, val; - - pci_dma_read(&s->dev, link & ~0xf, &td, sizeof(td)); - le32_to_cpus(&td.link); - le32_to_cpus(&td.ctrl); - le32_to_cpus(&td.token); - le32_to_cpus(&td.buffer); - - uhci_async_unlink(async); - uhci_complete_td(s, &td, async, &int_mask); - s->pending_int_mask |= int_mask; - - /* update the status bits of the TD */ - val = cpu_to_le32(td.ctrl); - pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val)); - uhci_async_free(async); - } else { - async->done = 1; - if (s->frame_bytes < s->frame_bandwidth) { - qemu_bh_schedule(s->bh); - } + async->done = 1; + if (s->frame_bytes < s->frame_bandwidth) { + qemu_bh_schedule(s->bh); } } From 2f2ee2689ffe8a784a86bf10fb946772748632c7 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:06 +0200 Subject: [PATCH 1142/2270] uhci: cleanup: Add an unlink call to uhci_async_cancel() All callers of uhci_async_cancel() call uhci_async_unlink() first, so lets move the unlink call to uhci_async_cancel() Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 129792b662..82dd5c2358 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -232,6 +232,7 @@ static void uhci_async_unlink(UHCIAsync *async) static void uhci_async_cancel(UHCIAsync *async) { + uhci_async_unlink(async); trace_usb_uhci_packet_cancel(async->queue->token, async->td, async->done); if (!async->done) usb_cancel_packet(&async->packet); @@ -266,7 +267,6 @@ static void uhci_async_validate_end(UHCIState *s) } while (!QTAILQ_EMPTY(&queue->asyncs)) { async = QTAILQ_FIRST(&queue->asyncs); - uhci_async_unlink(async); uhci_async_cancel(async); } uhci_queue_free(queue); @@ -284,7 +284,6 @@ static void uhci_async_cancel_device(UHCIState *s, USBDevice *dev) curr->packet.ep->dev != dev) { continue; } - uhci_async_unlink(curr); uhci_async_cancel(curr); } } @@ -297,7 +296,6 @@ static void uhci_async_cancel_all(UHCIState *s) QTAILQ_FOREACH_SAFE(queue, &s->queues, next, nq) { QTAILQ_FOREACH_SAFE(curr, &queue->asyncs, next, n) { - uhci_async_unlink(curr); uhci_async_cancel(curr); } uhci_queue_free(queue); From a89e255b0cbe7c5b56348201e1c0f6d427c98fc8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:07 +0200 Subject: [PATCH 1143/2270] uhci: Don't retry on error Since we are either dealing with emulated devices, where retrying is not going to help, or with redirected devices where the host OS will have already retried, don't bother retrying on failed transfers. Also move some common/indentical code out of all the error cases into the generic error path. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 62 +++++++++++++++-------------------------------- 1 file changed, 19 insertions(+), 43 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 82dd5c2358..eecd291f3d 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -696,10 +696,6 @@ static USBDevice *uhci_find_device(UHCIState *s, uint8_t addr) static void uhci_async_complete(USBPort *port, USBPacket *packet); static void uhci_process_frame(UHCIState *s); -/* return -1 if fatal error (frame must be stopped) - 0 if TD successful - 1 if TD unsuccessful or inactive -*/ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_t *int_mask) { int len = 0, max_len, err, ret; @@ -742,60 +738,40 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_ out: switch(ret) { + case USB_RET_NAK: + td->ctrl |= TD_CTRL_NAK; + return TD_RESULT_NEXT_QH; + case USB_RET_STALL: td->ctrl |= TD_CTRL_STALL; - td->ctrl &= ~TD_CTRL_ACTIVE; - s->status |= UHCI_STS_USBERR; - if (td->ctrl & TD_CTRL_IOC) { - *int_mask |= 0x01; - } - uhci_update_irq(s); trace_usb_uhci_packet_complete_stall(async->queue->token, async->td); - return TD_RESULT_NEXT_QH; + err = TD_RESULT_NEXT_QH; + break; case USB_RET_BABBLE: td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL; - td->ctrl &= ~TD_CTRL_ACTIVE; - s->status |= UHCI_STS_USBERR; - if (td->ctrl & TD_CTRL_IOC) { - *int_mask |= 0x01; - } - uhci_update_irq(s); /* frame interrupted */ trace_usb_uhci_packet_complete_babble(async->queue->token, async->td); - return TD_RESULT_STOP_FRAME; - - case USB_RET_NAK: - td->ctrl |= TD_CTRL_NAK; - if (pid == USB_TOKEN_SETUP) - break; - return TD_RESULT_NEXT_QH; + err = TD_RESULT_STOP_FRAME; + break; case USB_RET_IOERROR: case USB_RET_NODEV: default: - break; + td->ctrl |= TD_CTRL_TIMEOUT; + td->ctrl &= ~(3 << TD_CTRL_ERROR_SHIFT); + trace_usb_uhci_packet_complete_error(async->queue->token, async->td); + err = TD_RESULT_NEXT_QH; + break; } - /* Retry the TD if error count is not zero */ - - td->ctrl |= TD_CTRL_TIMEOUT; - err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3; - if (err != 0) { - err--; - if (err == 0) { - td->ctrl &= ~TD_CTRL_ACTIVE; - s->status |= UHCI_STS_USBERR; - if (td->ctrl & TD_CTRL_IOC) - *int_mask |= 0x01; - uhci_update_irq(s); - trace_usb_uhci_packet_complete_error(async->queue->token, - async->td); - } + td->ctrl &= ~TD_CTRL_ACTIVE; + s->status |= UHCI_STS_USBERR; + if (td->ctrl & TD_CTRL_IOC) { + *int_mask |= 0x01; } - td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) | - (err << TD_CTRL_ERROR_SHIFT); - return TD_RESULT_NEXT_QH; + uhci_update_irq(s); + return err; } static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, From 3c87c76d1a0e9ce1dde6f919e3b1b9bcabb69985 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:08 +0200 Subject: [PATCH 1144/2270] uhci: Drop unnecessary forward declaration of some static functions Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index eecd291f3d..7dfedef5b2 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -693,9 +693,6 @@ static USBDevice *uhci_find_device(UHCIState *s, uint8_t addr) return NULL; } -static void uhci_async_complete(USBPort *port, USBPacket *packet); -static void uhci_process_frame(UHCIState *s); - static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_t *int_mask) { int len = 0, max_len, err, ret; From 40507377261250fe19e441300788c77b748688cb Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:09 +0200 Subject: [PATCH 1145/2270] uhci: Move emptying of the queue's asyncs' queue to uhci_queue_free Cleanup: all callers of uhci_queue_free first unconditionally cancel all remaining asyncs in the queue, so lets move this to uhci_queue_free(). Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 7dfedef5b2..0335f3c490 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -160,6 +160,8 @@ typedef struct UHCI_QH { uint32_t el_link; } UHCI_QH; +static void uhci_async_cancel(UHCIAsync *async); + static inline int32_t uhci_queue_token(UHCI_TD *td) { /* covers ep, dev, pid -> identifies the endpoint */ @@ -189,6 +191,12 @@ static UHCIQueue *uhci_queue_get(UHCIState *s, UHCI_TD *td) static void uhci_queue_free(UHCIQueue *queue) { UHCIState *s = queue->uhci; + UHCIAsync *async; + + while (!QTAILQ_EMPTY(&queue->asyncs)) { + async = QTAILQ_FIRST(&queue->asyncs); + uhci_async_cancel(async); + } trace_usb_uhci_queue_del(queue->token); QTAILQ_REMOVE(&s->queues, queue, next); @@ -259,17 +267,11 @@ static void uhci_async_validate_begin(UHCIState *s) static void uhci_async_validate_end(UHCIState *s) { UHCIQueue *queue, *n; - UHCIAsync *async; QTAILQ_FOREACH_SAFE(queue, &s->queues, next, n) { - if (queue->valid > 0) { - continue; + if (!queue->valid) { + uhci_queue_free(queue); } - while (!QTAILQ_EMPTY(&queue->asyncs)) { - async = QTAILQ_FIRST(&queue->asyncs); - uhci_async_cancel(async); - } - uhci_queue_free(queue); } } @@ -292,12 +294,8 @@ static void uhci_async_cancel_device(UHCIState *s, USBDevice *dev) static void uhci_async_cancel_all(UHCIState *s) { UHCIQueue *queue, *nq; - UHCIAsync *curr, *n; QTAILQ_FOREACH_SAFE(queue, &s->queues, next, nq) { - QTAILQ_FOREACH_SAFE(curr, &queue->asyncs, next, n) { - uhci_async_cancel(curr); - } uhci_queue_free(queue); } } From 1f250cc77224f9b950c867e47d9f47e4cd46d7d4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:10 +0200 Subject: [PATCH 1146/2270] uhci: Rename UHCIAsync->td to UHCIAsync->td_addr We use the name td both to refer to a UHCI_TD read from guest memory as well as to refer to the guest address where a td is stored, switch over to always use td_addr in the second case for consistency. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 0335f3c490..7589a5b2d6 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -100,7 +100,7 @@ struct UHCIAsync { QEMUSGList sgl; UHCIQueue *queue; QTAILQ_ENTRY(UHCIAsync) next; - uint32_t td; + uint32_t td_addr; uint8_t done; }; @@ -203,22 +203,22 @@ static void uhci_queue_free(UHCIQueue *queue) g_free(queue); } -static UHCIAsync *uhci_async_alloc(UHCIQueue *queue, uint32_t addr) +static UHCIAsync *uhci_async_alloc(UHCIQueue *queue, uint32_t td_addr) { UHCIAsync *async = g_new0(UHCIAsync, 1); async->queue = queue; - async->td = addr; + async->td_addr = td_addr; usb_packet_init(&async->packet); pci_dma_sglist_init(&async->sgl, &queue->uhci->dev, 1); - trace_usb_uhci_packet_add(async->queue->token, async->td); + trace_usb_uhci_packet_add(async->queue->token, async->td_addr); return async; } static void uhci_async_free(UHCIAsync *async) { - trace_usb_uhci_packet_del(async->queue->token, async->td); + trace_usb_uhci_packet_del(async->queue->token, async->td_addr); usb_packet_cleanup(&async->packet); qemu_sglist_destroy(&async->sgl); g_free(async); @@ -228,20 +228,21 @@ static void uhci_async_link(UHCIAsync *async) { UHCIQueue *queue = async->queue; QTAILQ_INSERT_TAIL(&queue->asyncs, async, next); - trace_usb_uhci_packet_link_async(async->queue->token, async->td); + trace_usb_uhci_packet_link_async(async->queue->token, async->td_addr); } static void uhci_async_unlink(UHCIAsync *async) { UHCIQueue *queue = async->queue; QTAILQ_REMOVE(&queue->asyncs, async, next); - trace_usb_uhci_packet_unlink_async(async->queue->token, async->td); + trace_usb_uhci_packet_unlink_async(async->queue->token, async->td_addr); } static void uhci_async_cancel(UHCIAsync *async) { uhci_async_unlink(async); - trace_usb_uhci_packet_cancel(async->queue->token, async->td, async->done); + trace_usb_uhci_packet_cancel(async->queue->token, async->td_addr, + async->done); if (!async->done) usb_cancel_packet(&async->packet); usb_packet_unmap(&async->packet, &async->sgl); @@ -300,7 +301,8 @@ static void uhci_async_cancel_all(UHCIState *s) } } -static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, UHCI_TD *td) +static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t td_addr, + UHCI_TD *td) { uint32_t token = uhci_queue_token(td); UHCIQueue *queue; @@ -316,7 +318,7 @@ static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, UHCI_TD *td) } QTAILQ_FOREACH(async, &queue->asyncs, next) { - if (async->td == addr) { + if (async->td_addr == td_addr) { return async; } } @@ -722,13 +724,14 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_ *int_mask |= 0x02; /* short packet: do not update QH */ trace_usb_uhci_packet_complete_shortxfer(async->queue->token, - async->td); + async->td_addr); return TD_RESULT_NEXT_QH; } } /* success */ - trace_usb_uhci_packet_complete_success(async->queue->token, async->td); + trace_usb_uhci_packet_complete_success(async->queue->token, + async->td_addr); return TD_RESULT_COMPLETE; out: @@ -739,14 +742,16 @@ out: case USB_RET_STALL: td->ctrl |= TD_CTRL_STALL; - trace_usb_uhci_packet_complete_stall(async->queue->token, async->td); + trace_usb_uhci_packet_complete_stall(async->queue->token, + async->td_addr); err = TD_RESULT_NEXT_QH; break; case USB_RET_BABBLE: td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL; /* frame interrupted */ - trace_usb_uhci_packet_complete_babble(async->queue->token, async->td); + trace_usb_uhci_packet_complete_babble(async->queue->token, + async->td_addr); err = TD_RESULT_STOP_FRAME; break; @@ -755,7 +760,8 @@ out: default: td->ctrl |= TD_CTRL_TIMEOUT; td->ctrl &= ~(3 << TD_CTRL_ERROR_SHIFT); - trace_usb_uhci_packet_complete_error(async->queue->token, async->td); + trace_usb_uhci_packet_complete_error(async->queue->token, + async->td_addr); err = TD_RESULT_NEXT_QH; break; } @@ -769,7 +775,7 @@ out: return err; } -static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, +static int uhci_handle_td(UHCIState *s, uint32_t td_addr, UHCI_TD *td, uint32_t *int_mask, bool queuing, struct USBEndpoint **ep_ret) { @@ -792,7 +798,7 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, return TD_RESULT_NEXT_QH; } - async = uhci_async_find_td(s, addr, td); + async = uhci_async_find_td(s, td_addr, td); if (async) { /* Already submitted */ async->queue->valid = 32; @@ -811,7 +817,7 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, } /* Allocate new packet */ - async = uhci_async_alloc(uhci_queue_get(s, td), addr); + async = uhci_async_alloc(uhci_queue_get(s, td), td_addr); /* valid needs to be large enough to handle 10 frame delay * for initial isochronous requests @@ -827,7 +833,7 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, if (ep_ret) { *ep_ret = ep; } - usb_packet_setup(&async->packet, pid, ep, addr, spd, + usb_packet_setup(&async->packet, pid, ep, td_addr, spd, (td->ctrl & TD_CTRL_IOC) != 0); qemu_sglist_add(&async->sgl, td->buffer, max_len); usb_packet_map(&async->packet, &async->sgl); From 963a68b54f8f4e5dcc7cc2c6ec8d047557ac5feb Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:11 +0200 Subject: [PATCH 1147/2270] uhci: Add uhci_read_td() helper function Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 7589a5b2d6..6d2db7ffdb 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -693,6 +693,15 @@ static USBDevice *uhci_find_device(UHCIState *s, uint8_t addr) return NULL; } +static void uhci_read_td(UHCIState *s, UHCI_TD *td, uint32_t link) +{ + pci_dma_read(&s->dev, link & ~0xf, td, sizeof(*td)); + le32_to_cpus(&td->link); + le32_to_cpus(&td->ctrl); + le32_to_cpus(&td->token); + le32_to_cpus(&td->buffer); +} + static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_t *int_mask) { int len = 0, max_len, err, ret; @@ -941,11 +950,7 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td, struct USBEndpoint *ep) int ret; while (is_valid(plink)) { - pci_dma_read(&s->dev, plink & ~0xf, &ptd, sizeof(ptd)); - le32_to_cpus(&ptd.link); - le32_to_cpus(&ptd.ctrl); - le32_to_cpus(&ptd.token); - le32_to_cpus(&ptd.buffer); + uhci_read_td(s, &ptd, plink); if (!(ptd.ctrl & TD_CTRL_ACTIVE)) { break; } @@ -1031,11 +1036,7 @@ static void uhci_process_frame(UHCIState *s) } /* TD */ - pci_dma_read(&s->dev, link & ~0xf, &td, sizeof(td)); - le32_to_cpus(&td.link); - le32_to_cpus(&td.ctrl); - le32_to_cpus(&td.token); - le32_to_cpus(&td.buffer); + uhci_read_td(s, &td, link); trace_usb_uhci_td_load(curr_qh & ~0xf, link & ~0xf, td.ctrl, td.token); old_td_ctrl = td.ctrl; From a4f30cd766888e69e1d75cd87d251c04e829688e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:12 +0200 Subject: [PATCH 1148/2270] uhci: Make uhci_fill_queue() actually operate on an UHCIQueue And move its calling point to handle_td, this removes the ep_ret ugliness, and prepates the way for further cleanups in the follow-up patches in this patch-set. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 6d2db7ffdb..2bbc6fbc96 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -161,6 +161,7 @@ typedef struct UHCI_QH { } UHCI_QH; static void uhci_async_cancel(UHCIAsync *async); +static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td, struct USBEndpoint *ep); static inline int32_t uhci_queue_token(UHCI_TD *td) { @@ -784,9 +785,8 @@ out: return err; } -static int uhci_handle_td(UHCIState *s, uint32_t td_addr, UHCI_TD *td, - uint32_t *int_mask, bool queuing, - struct USBEndpoint **ep_ret) +static int uhci_handle_td(UHCIState *s, UHCIQueue *q, + UHCI_TD *td, uint32_t td_addr, uint32_t *int_mask) { UHCIAsync *async; int len = 0, max_len; @@ -794,6 +794,7 @@ static int uhci_handle_td(UHCIState *s, uint32_t td_addr, UHCI_TD *td, bool spd; USBDevice *dev; USBEndpoint *ep; + bool queuing = (q != NULL); /* Is active ? */ if (!(td->ctrl & TD_CTRL_ACTIVE)) { @@ -826,7 +827,10 @@ static int uhci_handle_td(UHCIState *s, uint32_t td_addr, UHCI_TD *td, } /* Allocate new packet */ - async = uhci_async_alloc(uhci_queue_get(s, td), td_addr); + if (q == NULL) { + q = uhci_queue_get(s, td); + } + async = uhci_async_alloc(q, td_addr); /* valid needs to be large enough to handle 10 frame delay * for initial isochronous requests @@ -839,9 +843,6 @@ static int uhci_handle_td(UHCIState *s, uint32_t td_addr, UHCI_TD *td, dev = uhci_find_device(s, (td->token >> 8) & 0x7f); ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf); - if (ep_ret) { - *ep_ret = ep; - } usb_packet_setup(&async->packet, pid, ep, td_addr, spd, (td->ctrl & TD_CTRL_IOC) != 0); qemu_sglist_add(&async->sgl, td->buffer, max_len); @@ -870,6 +871,9 @@ static int uhci_handle_td(UHCIState *s, uint32_t td_addr, UHCI_TD *td, if (len == USB_RET_ASYNC) { uhci_async_link(async); + if (!queuing) { + uhci_queue_fill(q, td, ep); + } return TD_RESULT_ASYNC_START; } @@ -941,24 +945,23 @@ static int qhdb_insert(QhDb *db, uint32_t addr) return 0; } -static void uhci_fill_queue(UHCIState *s, UHCI_TD *td, struct USBEndpoint *ep) +static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td, struct USBEndpoint *ep) { uint32_t int_mask = 0; uint32_t plink = td->link; - uint32_t token = uhci_queue_token(td); UHCI_TD ptd; int ret; while (is_valid(plink)) { - uhci_read_td(s, &ptd, plink); + uhci_read_td(q->uhci, &ptd, plink); if (!(ptd.ctrl & TD_CTRL_ACTIVE)) { break; } - if (uhci_queue_token(&ptd) != token) { + if (uhci_queue_token(&ptd) != q->token) { break; } trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token); - ret = uhci_handle_td(s, plink, &ptd, &int_mask, true, NULL); + ret = uhci_handle_td(q->uhci, q, &ptd, plink, &int_mask); if (ret == TD_RESULT_ASYNC_CONT) { break; } @@ -973,7 +976,6 @@ static void uhci_process_frame(UHCIState *s) { uint32_t frame_addr, link, old_td_ctrl, val, int_mask; uint32_t curr_qh, td_count = 0; - struct USBEndpoint *curr_ep; int cnt, ret; UHCI_TD td; UHCI_QH qh; @@ -1040,7 +1042,7 @@ static void uhci_process_frame(UHCIState *s) trace_usb_uhci_td_load(curr_qh & ~0xf, link & ~0xf, td.ctrl, td.token); old_td_ctrl = td.ctrl; - ret = uhci_handle_td(s, link, &td, &int_mask, false, &curr_ep); + ret = uhci_handle_td(s, NULL, &td, link, &int_mask); if (old_td_ctrl != td.ctrl) { /* update the status bits of the TD */ val = cpu_to_le32(td.ctrl); @@ -1059,7 +1061,6 @@ static void uhci_process_frame(UHCIState *s) case TD_RESULT_ASYNC_START: trace_usb_uhci_td_async(curr_qh & ~0xf, link & ~0xf); - uhci_fill_queue(s, &td, curr_ep); link = curr_qh ? qh.link : td.link; continue; From 11d15e402beec122fb11104e36c35d1a46f650ff Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:13 +0200 Subject: [PATCH 1149/2270] uhci: Store ep in UHCIQueue This avoids the need to repeatedly lookup the device, and ep. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 2bbc6fbc96..8214a21a7a 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -107,6 +107,7 @@ struct UHCIAsync { struct UHCIQueue { uint32_t token; UHCIState *uhci; + USBEndpoint *ep; QTAILQ_ENTRY(UHCIQueue) next; QTAILQ_HEAD(, UHCIAsync) asyncs; int8_t valid; @@ -161,7 +162,7 @@ typedef struct UHCI_QH { } UHCI_QH; static void uhci_async_cancel(UHCIAsync *async); -static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td, struct USBEndpoint *ep); +static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td); static inline int32_t uhci_queue_token(UHCI_TD *td) { @@ -169,7 +170,7 @@ static inline int32_t uhci_queue_token(UHCI_TD *td) return td->token & 0x7ffff; } -static UHCIQueue *uhci_queue_get(UHCIState *s, UHCI_TD *td) +static UHCIQueue *uhci_queue_get(UHCIState *s, UHCI_TD *td, USBEndpoint *ep) { uint32_t token = uhci_queue_token(td); UHCIQueue *queue; @@ -183,6 +184,7 @@ static UHCIQueue *uhci_queue_get(UHCIState *s, UHCI_TD *td) queue = g_new0(UHCIQueue, 1); queue->uhci = s; queue->token = token; + queue->ep = ep; QTAILQ_INIT(&queue->asyncs); QTAILQ_INSERT_HEAD(&s->queues, queue, next); trace_usb_uhci_queue_add(queue->token); @@ -790,11 +792,9 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, { UHCIAsync *async; int len = 0, max_len; - uint8_t pid; bool spd; - USBDevice *dev; - USBEndpoint *ep; bool queuing = (q != NULL); + uint8_t pid = td->token & 0xff; /* Is active ? */ if (!(td->ctrl & TD_CTRL_ACTIVE)) { @@ -828,7 +828,9 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, /* Allocate new packet */ if (q == NULL) { - q = uhci_queue_get(s, td); + USBDevice *dev = uhci_find_device(s, (td->token >> 8) & 0x7f); + USBEndpoint *ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf); + q = uhci_queue_get(s, td, ep); } async = uhci_async_alloc(q, td_addr); @@ -838,12 +840,8 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, async->queue->valid = 32; max_len = ((td->token >> 21) + 1) & 0x7ff; - pid = td->token & 0xff; spd = (pid == USB_TOKEN_IN && (td->ctrl & TD_CTRL_SPD) != 0); - - dev = uhci_find_device(s, (td->token >> 8) & 0x7f); - ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf); - usb_packet_setup(&async->packet, pid, ep, td_addr, spd, + usb_packet_setup(&async->packet, pid, q->ep, td_addr, spd, (td->ctrl & TD_CTRL_IOC) != 0); qemu_sglist_add(&async->sgl, td->buffer, max_len); usb_packet_map(&async->packet, &async->sgl); @@ -851,13 +849,13 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, switch(pid) { case USB_TOKEN_OUT: case USB_TOKEN_SETUP: - len = usb_handle_packet(dev, &async->packet); + len = usb_handle_packet(q->ep->dev, &async->packet); if (len >= 0) len = max_len; break; case USB_TOKEN_IN: - len = usb_handle_packet(dev, &async->packet); + len = usb_handle_packet(q->ep->dev, &async->packet); break; default: @@ -872,7 +870,7 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, if (len == USB_RET_ASYNC) { uhci_async_link(async); if (!queuing) { - uhci_queue_fill(q, td, ep); + uhci_queue_fill(q, td); } return TD_RESULT_ASYNC_START; } @@ -945,7 +943,7 @@ static int qhdb_insert(QhDb *db, uint32_t addr) return 0; } -static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td, struct USBEndpoint *ep) +static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td) { uint32_t int_mask = 0; uint32_t plink = td->link; @@ -969,7 +967,7 @@ static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td, struct USBEndpoint *ep) assert(int_mask == 0); plink = ptd.link; } - usb_device_flush_ep_queue(ep->dev, ep); + usb_device_flush_ep_queue(q->ep->dev, q->ep); } static void uhci_process_frame(UHCIState *s) From 5ad23e873c858292dc58b9296261365312b8f683 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:14 +0200 Subject: [PATCH 1150/2270] uhci: Immediately free queues on device disconnect There is no need to just cancel any in-flight packets, and then wait for validate-end to clean things up, we can simply clean things up immediately on device removal. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 8214a21a7a..a8b74bdb66 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -281,16 +281,11 @@ static void uhci_async_validate_end(UHCIState *s) static void uhci_async_cancel_device(UHCIState *s, USBDevice *dev) { - UHCIQueue *queue; - UHCIAsync *curr, *n; + UHCIQueue *queue, *n; - QTAILQ_FOREACH(queue, &s->queues, next) { - QTAILQ_FOREACH_SAFE(curr, &queue->asyncs, next, n) { - if (!usb_packet_is_inflight(&curr->packet) || - curr->packet.ep->dev != dev) { - continue; - } - uhci_async_cancel(curr); + QTAILQ_FOREACH_SAFE(queue, &s->queues, next, n) { + if (queue->ep->dev == dev) { + uhci_queue_free(queue, "cancel-device"); } } } From 66a08cbe6ad1aebec8eecf58b3ba042e19dd1649 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:15 +0200 Subject: [PATCH 1151/2270] uhci: Verify queue has not been changed by guest According to the spec a guest can unlink a qh, and then as soon as frindex has changed by 1 since the unlink, assume it is idle and re-use it. However for various reasons, we cannot simply consider a qh as unlinked if we've not seen it for 1 frame. This means that it is possible for a guest to re-use / restart the queue while we still see its old state. This patch adds a safety check for this, and "early" retires queues when they were changed by the guest. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 62 ++++++++++++++++++++++++++++++++++------------- trace-events | 2 +- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index a8b74bdb66..0984bee4f3 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -105,6 +105,7 @@ struct UHCIAsync { }; struct UHCIQueue { + uint32_t qh_addr; uint32_t token; UHCIState *uhci; USBEndpoint *ep; @@ -170,20 +171,15 @@ static inline int32_t uhci_queue_token(UHCI_TD *td) return td->token & 0x7ffff; } -static UHCIQueue *uhci_queue_get(UHCIState *s, UHCI_TD *td, USBEndpoint *ep) +static UHCIQueue *uhci_queue_new(UHCIState *s, uint32_t qh_addr, UHCI_TD *td, + USBEndpoint *ep) { - uint32_t token = uhci_queue_token(td); UHCIQueue *queue; - QTAILQ_FOREACH(queue, &s->queues, next) { - if (queue->token == token) { - return queue; - } - } - queue = g_new0(UHCIQueue, 1); queue->uhci = s; - queue->token = token; + queue->qh_addr = qh_addr; + queue->token = uhci_queue_token(td); queue->ep = ep; QTAILQ_INIT(&queue->asyncs); QTAILQ_INSERT_HEAD(&s->queues, queue, next); @@ -191,7 +187,7 @@ static UHCIQueue *uhci_queue_get(UHCIState *s, UHCI_TD *td, USBEndpoint *ep) return queue; } -static void uhci_queue_free(UHCIQueue *queue) +static void uhci_queue_free(UHCIQueue *queue, const char *reason) { UHCIState *s = queue->uhci; UHCIAsync *async; @@ -201,11 +197,35 @@ static void uhci_queue_free(UHCIQueue *queue) uhci_async_cancel(async); } - trace_usb_uhci_queue_del(queue->token); + trace_usb_uhci_queue_del(queue->token, reason); QTAILQ_REMOVE(&s->queues, queue, next); g_free(queue); } +static UHCIQueue *uhci_queue_find(UHCIState *s, UHCI_TD *td) +{ + uint32_t token = uhci_queue_token(td); + UHCIQueue *queue; + + QTAILQ_FOREACH(queue, &s->queues, next) { + if (queue->token == token) { + return queue; + } + } + return NULL; +} + +static bool uhci_queue_verify(UHCIQueue *queue, uint32_t qh_addr, UHCI_TD *td, + uint32_t td_addr, bool queuing) +{ + UHCIAsync *first = QTAILQ_FIRST(&queue->asyncs); + + return queue->qh_addr == qh_addr && + queue->token == uhci_queue_token(td) && + (queuing || !(td->ctrl & TD_CTRL_ACTIVE) || first == NULL || + first->td_addr == td_addr); +} + static UHCIAsync *uhci_async_alloc(UHCIQueue *queue, uint32_t td_addr) { UHCIAsync *async = g_new0(UHCIAsync, 1); @@ -274,7 +294,7 @@ static void uhci_async_validate_end(UHCIState *s) QTAILQ_FOREACH_SAFE(queue, &s->queues, next, n) { if (!queue->valid) { - uhci_queue_free(queue); + uhci_queue_free(queue, "validate-end"); } } } @@ -295,7 +315,7 @@ static void uhci_async_cancel_all(UHCIState *s) UHCIQueue *queue, *nq; QTAILQ_FOREACH_SAFE(queue, &s->queues, next, nq) { - uhci_queue_free(queue); + uhci_queue_free(queue, "cancel-all"); } } @@ -782,7 +802,7 @@ out: return err; } -static int uhci_handle_td(UHCIState *s, UHCIQueue *q, +static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr, UHCI_TD *td, uint32_t td_addr, uint32_t *int_mask) { UHCIAsync *async; @@ -791,6 +811,14 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, bool queuing = (q != NULL); uint8_t pid = td->token & 0xff; + if (q == NULL) { + q = uhci_queue_find(s, td); + if (q && !uhci_queue_verify(q, qh_addr, td, td_addr, queuing)) { + uhci_queue_free(q, "guest re-used qh"); + q = NULL; + } + } + /* Is active ? */ if (!(td->ctrl & TD_CTRL_ACTIVE)) { /* @@ -825,7 +853,7 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, if (q == NULL) { USBDevice *dev = uhci_find_device(s, (td->token >> 8) & 0x7f); USBEndpoint *ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf); - q = uhci_queue_get(s, td, ep); + q = uhci_queue_new(s, qh_addr, td, ep); } async = uhci_async_alloc(q, td_addr); @@ -954,7 +982,7 @@ static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td) break; } trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token); - ret = uhci_handle_td(q->uhci, q, &ptd, plink, &int_mask); + ret = uhci_handle_td(q->uhci, q, q->qh_addr, &ptd, plink, &int_mask); if (ret == TD_RESULT_ASYNC_CONT) { break; } @@ -1035,7 +1063,7 @@ static void uhci_process_frame(UHCIState *s) trace_usb_uhci_td_load(curr_qh & ~0xf, link & ~0xf, td.ctrl, td.token); old_td_ctrl = td.ctrl; - ret = uhci_handle_td(s, NULL, &td, link, &int_mask); + ret = uhci_handle_td(s, NULL, curr_qh, &td, link, &int_mask); if (old_td_ctrl != td.ctrl) { /* update the status bits of the TD */ val = cpu_to_le32(td.ctrl); diff --git a/trace-events b/trace-events index e2d4580d4c..ed136a56a1 100644 --- a/trace-events +++ b/trace-events @@ -287,7 +287,7 @@ usb_uhci_mmio_writew(uint32_t addr, uint32_t val) "addr 0x%04x, val 0x%04x" usb_uhci_mmio_readl(uint32_t addr, uint32_t val) "addr 0x%04x, ret 0x%08x" usb_uhci_mmio_writel(uint32_t addr, uint32_t val) "addr 0x%04x, val 0x%08x" usb_uhci_queue_add(uint32_t token) "token 0x%x" -usb_uhci_queue_del(uint32_t token) "token 0x%x" +usb_uhci_queue_del(uint32_t token, const char *reason) "token 0x%x: %s" usb_uhci_packet_add(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x" usb_uhci_packet_link_async(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x" usb_uhci_packet_unlink_async(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x" From 8c75a899f85dda9f8305d25f0cc453a79115fd90 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:16 +0200 Subject: [PATCH 1152/2270] uhci: Detect guest td re-use A td can be reused by the guest in a different queue, before we notice the original queue has been unlinked. So search for tds by addr only, detect guest td reuse, and cancel the original queue, this is necessary to keep our packet ids unique. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 0984bee4f3..c4f2f98f17 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -319,28 +319,18 @@ static void uhci_async_cancel_all(UHCIState *s) } } -static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t td_addr, - UHCI_TD *td) +static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t td_addr) { - uint32_t token = uhci_queue_token(td); UHCIQueue *queue; UHCIAsync *async; QTAILQ_FOREACH(queue, &s->queues, next) { - if (queue->token == token) { - break; + QTAILQ_FOREACH(async, &queue->asyncs, next) { + if (async->td_addr == td_addr) { + return async; + } } } - if (queue == NULL) { - return NULL; - } - - QTAILQ_FOREACH(async, &queue->asyncs, next) { - if (async->td_addr == td_addr) { - return async; - } - } - return NULL; } @@ -805,11 +795,21 @@ out: static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr, UHCI_TD *td, uint32_t td_addr, uint32_t *int_mask) { - UHCIAsync *async; int len = 0, max_len; bool spd; bool queuing = (q != NULL); uint8_t pid = td->token & 0xff; + UHCIAsync *async = uhci_async_find_td(s, td_addr); + + if (async) { + if (uhci_queue_verify(async->queue, qh_addr, td, td_addr, queuing)) { + assert(q == NULL || q == async->queue); + q = async->queue; + } else { + uhci_queue_free(async->queue, "guest re-used pending td"); + async = NULL; + } + } if (q == NULL) { q = uhci_queue_find(s, td); @@ -831,7 +831,6 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr, return TD_RESULT_NEXT_QH; } - async = uhci_async_find_td(s, td_addr, td); if (async) { /* Already submitted */ async->queue->valid = 32; From 420ca987d5d14fabacdec86c568832d6b0056ca3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:17 +0200 Subject: [PATCH 1153/2270] uhci: When the guest marks a pending td non-active, cancel the queue Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index c4f2f98f17..592ad8d3e7 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -821,6 +821,10 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr, /* Is active ? */ if (!(td->ctrl & TD_CTRL_ACTIVE)) { + if (async) { + /* Guest marked a pending td non-active, cancel the queue */ + uhci_queue_free(async->queue, "pending td non-active"); + } /* * ehci11d spec page 22: "Even if the Active bit in the TD is already * cleared when the TD is fetched ... an IOC interrupt is generated" From 3905097ea8ea0e1b3dd1556f3ef74a123fe8622a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:18 +0200 Subject: [PATCH 1154/2270] uhci: Always mark a queue valid when we encounter it Before this patch we would not mark a queue valid when its head was a non-active td. This causes us to misbehave in the following scenario: 1) queue with multiple input transfers queued 2) We hit some latency issue, causing qemu to get behind processing frames 3) When qemu gets to run again, it notices the first transfer ends short, marking the head td non-active 4) It now processes 32+ frames in a row without giving the guest a chance to run since it is behind 5) valid is decreased to 0, causing the queue to get cancelled also cancelling already queued up further input transfers 6) guest gets to run, notices the inactive td, cleanups up further tds from the short transfer, and lets the queue continue at the first td of the next input transfer 7) we re-start the queue, issuing the second input transfer for the *second* time, and any data read by the first time we issued it has been lost Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 592ad8d3e7..beeb3fd7b0 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -183,6 +183,9 @@ static UHCIQueue *uhci_queue_new(UHCIState *s, uint32_t qh_addr, UHCI_TD *td, queue->ep = ep; QTAILQ_INIT(&queue->asyncs); QTAILQ_INSERT_HEAD(&s->queues, queue, next); + /* valid needs to be large enough to handle 10 frame delay + * for initial isochronous requests */ + queue->valid = 32; trace_usb_uhci_queue_add(queue->token); return queue; } @@ -819,6 +822,10 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr, } } + if (q) { + q->valid = 32; + } + /* Is active ? */ if (!(td->ctrl & TD_CTRL_ACTIVE)) { if (async) { @@ -836,9 +843,6 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr, } if (async) { - /* Already submitted */ - async->queue->valid = 32; - if (!async->done) return TD_RESULT_ASYNC_CONT; if (queuing) { @@ -860,11 +864,6 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr, } async = uhci_async_alloc(q, td_addr); - /* valid needs to be large enough to handle 10 frame delay - * for initial isochronous requests - */ - async->queue->valid = 32; - max_len = ((td->token >> 21) + 1) & 0x7ff; spd = (pid == USB_TOKEN_IN && (td->ctrl & TD_CTRL_SPD) != 0); usb_packet_setup(&async->packet, pid, q->ep, td_addr, spd, From 8928c9c43df1a0eeda1ae2e9582beb34dce49330 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:19 +0200 Subject: [PATCH 1155/2270] uhci: Retry to fill the queue while waiting for td completion If the guest is using multiple transfers to try and keep the usb bus busy / used at maximum efficiency, currently we would see / do the following: 1) submit transfer 1 to the device 2) submit transfer 2 to the device 3) report transfer 1 completion to guest 4) report transfer 2 completion to guest 5) submit transfer 1 to the device 6) report transfer 1 completion to guest 7) submit transfer 2 to the device 8) report transfer 2 completion to guest etc. So after the initial submission we would effectively only have 1 transfer in flight, rather then 2. This is caused by us not checking the queue for addition of new transfers by the guest (ie the resubmission of a recently finished transfer), while waiting for a pending transfer to complete. This patch does add a check for this, changing the sequence to: 1) submit transfer 1 to the device 2) submit transfer 2 to the device 3) report transfer 1 completion to guest 4) submit transfer 1 to the device 5) report transfer 2 completion to guest 6) submit transfer 2 to the device etc. Thus keeping 2 transfers in flight (most of the time, and always 1), as intended by the guest. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index beeb3fd7b0..a9e06ef5aa 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -110,7 +110,7 @@ struct UHCIQueue { UHCIState *uhci; USBEndpoint *ep; QTAILQ_ENTRY(UHCIQueue) next; - QTAILQ_HEAD(, UHCIAsync) asyncs; + QTAILQ_HEAD(asyncs_head, UHCIAsync) asyncs; int8_t valid; }; @@ -843,15 +843,25 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr, } if (async) { - if (!async->done) - return TD_RESULT_ASYNC_CONT; if (queuing) { /* we are busy filling the queue, we are not prepared to consume completed packages then, just leave them in async state */ return TD_RESULT_ASYNC_CONT; } + if (!async->done) { + UHCI_TD last_td; + UHCIAsync *last = QTAILQ_LAST(&async->queue->asyncs, asyncs_head); + /* + * While we are waiting for the current td to complete, the guest + * may have added more tds to the queue. Note we re-read the td + * rather then caching it, as we want to see guest made changes! + */ + uhci_read_td(s, &last_td, last->td_addr); + uhci_queue_fill(async->queue, &last_td); + return TD_RESULT_ASYNC_CONT; + } uhci_async_unlink(async); goto done; } From 6fe30910abd7e0f4af69f8e522ccfe6b5125abbb Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Oct 2012 18:31:20 +0200 Subject: [PATCH 1156/2270] uhci: Use only one queue for ctrl endpoints ctrl endpoints use different pids for different phases of a control transfer, this patch makes us use only one queue for a ctrl ep, rather then 3. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index a9e06ef5aa..b6b972fa92 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -167,8 +167,13 @@ static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td); static inline int32_t uhci_queue_token(UHCI_TD *td) { - /* covers ep, dev, pid -> identifies the endpoint */ - return td->token & 0x7ffff; + if ((td->token & (0xf << 15)) == 0) { + /* ctrl ep, cover ep and dev, not pid! */ + return td->token & 0x7ff00; + } else { + /* covers ep, dev, pid -> identifies the endpoint */ + return td->token & 0x7ffff; + } } static UHCIQueue *uhci_queue_new(UHCIState *s, uint32_t qh_addr, UHCI_TD *td, From 79a8af3509151dd1b650c996defdda13e02a7e38 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 24 Oct 2012 09:36:55 +0200 Subject: [PATCH 1157/2270] xhci: fix function name in error message Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index caa5f3e36a..8345fa34a2 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2676,7 +2676,7 @@ static void xhci_runtime_write(void *ptr, hwaddr reg, trace_usb_xhci_runtime_write(reg, val); if (reg < 0x20) { - fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", (int)reg); + fprintf(stderr, "%s: reg 0x%x unimplemented\n", __func__, (int)reg); return; } From 3f973ee84ef51e448566c08ec5cfe746c9640269 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 24 Oct 2012 10:14:16 +0200 Subject: [PATCH 1158/2270] xhci: flush endpoint context unconditinally Not updating the endpoint context in case the state didn't change is wrong. Other context fields might have changed, for example the dequeue pointer in response to a CR_SET_TR_DEQUEUE command. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 8345fa34a2..d8d1226a5b 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1009,9 +1009,6 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx, uint32_t state) { uint32_t ctx[5]; - if (epctx->state == state) { - return; - } pci_dma_read(&xhci->pci_dev, epctx->pctx, ctx, sizeof(ctx)); ctx[0] &= ~EP_STATE_MASK; From e099ad4b7e9ca7debdd624a0d465a33198a6844f Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 24 Oct 2012 09:38:08 +0200 Subject: [PATCH 1159/2270] xhci: allow disabling interrupters For secondary interrupters this is explicitly allowed in the specs. For the primary interrupter behavior is undefined, lets be friendly and allow disabling too. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index d8d1226a5b..bd8d4a5b39 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -964,6 +964,12 @@ static void xhci_er_reset(XHCIState *xhci, int v) XHCIInterrupter *intr = &xhci->intr[v]; XHCIEvRingSeg seg; + if (intr->erstsz == 0) { + /* disabled */ + intr->er_start = 0; + intr->er_size = 0; + return; + } /* cache the (sole) event ring segment location */ if (intr->erstsz != 1) { fprintf(stderr, "xhci: invalid value for ERSTSZ: %d\n", intr->erstsz); From 91062ae00fd4a88a40c28288e8ac7fe50ee83adf Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 24 Oct 2012 11:49:30 +0200 Subject: [PATCH 1160/2270] xhci: make number of interrupters and slots configurable Add properties to tweak the numbers of available interrupters and slots. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 79 ++++++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index bd8d4a5b39..25b04cd11b 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -417,6 +417,8 @@ struct XHCIState { /* properties */ uint32_t numports_2; uint32_t numports_3; + uint32_t numintrs; + uint32_t numslots; uint32_t flags; /* Operational Registers */ @@ -816,8 +818,8 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v) dma_addr_t erdp; unsigned int dp_idx; - if (v >= MAXINTRS) { - DPRINTF("intr nr out of range (%d >= %d)\n", v, MAXINTRS); + if (v >= xhci->numintrs) { + DPRINTF("intr nr out of range (%d >= %d)\n", v, xhci->numintrs); return; } intr = &xhci->intr[v]; @@ -1043,7 +1045,7 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, int i; trace_usb_xhci_ep_enable(slotid, epid); - assert(slotid >= 1 && slotid <= MAXSLOTS); + assert(slotid >= 1 && slotid <= xhci->numslots); assert(epid >= 1 && epid <= 31); slot = &xhci->slots[slotid-1]; @@ -1121,7 +1123,7 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid, XHCISlot *slot; XHCIEPContext *epctx; int i, xferi, killed = 0; - assert(slotid >= 1 && slotid <= MAXSLOTS); + assert(slotid >= 1 && slotid <= xhci->numslots); assert(epid >= 1 && epid <= 31); DPRINTF("xhci_ep_nuke_xfers(%d, %d)\n", slotid, epid); @@ -1149,7 +1151,7 @@ static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid, XHCIEPContext *epctx; trace_usb_xhci_ep_disable(slotid, epid); - assert(slotid >= 1 && slotid <= MAXSLOTS); + assert(slotid >= 1 && slotid <= xhci->numslots); assert(epid >= 1 && epid <= 31); slot = &xhci->slots[slotid-1]; @@ -1179,7 +1181,7 @@ static TRBCCode xhci_stop_ep(XHCIState *xhci, unsigned int slotid, XHCIEPContext *epctx; trace_usb_xhci_ep_stop(slotid, epid); - assert(slotid >= 1 && slotid <= MAXSLOTS); + assert(slotid >= 1 && slotid <= xhci->numslots); if (epid < 1 || epid > 31) { fprintf(stderr, "xhci: bad ep %d\n", epid); @@ -1213,7 +1215,7 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid, USBDevice *dev; trace_usb_xhci_ep_reset(slotid, epid); - assert(slotid >= 1 && slotid <= MAXSLOTS); + assert(slotid >= 1 && slotid <= xhci->numslots); if (epid < 1 || epid > 31) { fprintf(stderr, "xhci: bad ep %d\n", epid); @@ -1263,7 +1265,7 @@ static TRBCCode xhci_set_ep_dequeue(XHCIState *xhci, unsigned int slotid, XHCIEPContext *epctx; dma_addr_t dequeue; - assert(slotid >= 1 && slotid <= MAXSLOTS); + assert(slotid >= 1 && slotid <= xhci->numslots); if (epid < 1 || epid > 31) { fprintf(stderr, "xhci: bad ep %d\n", epid); @@ -1667,7 +1669,7 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid int i; trace_usb_xhci_ep_kick(slotid, epid); - assert(slotid >= 1 && slotid <= MAXSLOTS); + assert(slotid >= 1 && slotid <= xhci->numslots); assert(epid >= 1 && epid <= 31); if (!xhci->slots[slotid-1].enabled) { @@ -1787,7 +1789,7 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid static TRBCCode xhci_enable_slot(XHCIState *xhci, unsigned int slotid) { trace_usb_xhci_slot_enable(slotid); - assert(slotid >= 1 && slotid <= MAXSLOTS); + assert(slotid >= 1 && slotid <= xhci->numslots); xhci->slots[slotid-1].enabled = 1; xhci->slots[slotid-1].uport = NULL; memset(xhci->slots[slotid-1].eps, 0, sizeof(XHCIEPContext*)*31); @@ -1800,7 +1802,7 @@ static TRBCCode xhci_disable_slot(XHCIState *xhci, unsigned int slotid) int i; trace_usb_xhci_slot_disable(slotid); - assert(slotid >= 1 && slotid <= MAXSLOTS); + assert(slotid >= 1 && slotid <= xhci->numslots); for (i = 1; i <= 31; i++) { if (xhci->slots[slotid-1].eps[i-1]) { @@ -1852,7 +1854,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, TRBCCode res; trace_usb_xhci_slot_address(slotid); - assert(slotid >= 1 && slotid <= MAXSLOTS); + assert(slotid >= 1 && slotid <= xhci->numslots); dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high); pci_dma_read(&xhci->pci_dev, dcbaap + 8*slotid, &poctx, sizeof(poctx)); @@ -1891,7 +1893,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, return CC_USB_TRANSACTION_ERROR; } - for (i = 0; i < MAXSLOTS; i++) { + for (i = 0; i < xhci->numslots; i++) { if (xhci->slots[i].uport == uport) { fprintf(stderr, "xhci: port %s already assigned to slot %d\n", uport->path, i+1); @@ -1940,7 +1942,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, TRBCCode res; trace_usb_xhci_slot_configure(slotid); - assert(slotid >= 1 && slotid <= MAXSLOTS); + assert(slotid >= 1 && slotid <= xhci->numslots); ictx = xhci_mask64(pictx); octx = xhci->slots[slotid-1].ctx; @@ -2028,7 +2030,7 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, uint32_t slot_ctx[4]; trace_usb_xhci_slot_evaluate(slotid); - assert(slotid >= 1 && slotid <= MAXSLOTS); + assert(slotid >= 1 && slotid <= xhci->numslots); ictx = xhci_mask64(pictx); octx = xhci->slots[slotid-1].ctx; @@ -2091,7 +2093,7 @@ static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid) int i; trace_usb_xhci_slot_reset(slotid); - assert(slotid >= 1 && slotid <= MAXSLOTS); + assert(slotid >= 1 && slotid <= xhci->numslots); octx = xhci->slots[slotid-1].ctx; @@ -2117,7 +2119,7 @@ static unsigned int xhci_get_slot(XHCIState *xhci, XHCIEvent *event, XHCITRB *tr { unsigned int slotid; slotid = (trb->control >> TRB_CR_SLOTID_SHIFT) & TRB_CR_SLOTID_MASK; - if (slotid < 1 || slotid > MAXSLOTS) { + if (slotid < 1 || slotid > xhci->numslots) { fprintf(stderr, "xhci: bad slot id %d\n", slotid); event->ccode = CC_TRB_ERROR; return 0; @@ -2209,12 +2211,12 @@ static void xhci_process_commands(XHCIState *xhci) event.ptr = addr; switch (type) { case CR_ENABLE_SLOT: - for (i = 0; i < MAXSLOTS; i++) { + for (i = 0; i < xhci->numslots; i++) { if (!xhci->slots[i].enabled) { break; } } - if (i >= MAXSLOTS) { + if (i >= xhci->numslots) { fprintf(stderr, "xhci: no device slots available\n"); event.ccode = CC_NO_SLOTS_ERROR; } else { @@ -2361,7 +2363,7 @@ static void xhci_reset(DeviceState *dev) xhci->config = 0; xhci->devaddr = 2; - for (i = 0; i < MAXSLOTS; i++) { + for (i = 0; i < xhci->numslots; i++) { xhci_disable_slot(xhci, i+1); } @@ -2369,7 +2371,7 @@ static void xhci_reset(DeviceState *dev) xhci_update_port(xhci, xhci->ports + i, 0); } - for (i = 0; i < MAXINTRS; i++) { + for (i = 0; i < xhci->numintrs; i++) { xhci->intr[i].iman = 0; xhci->intr[i].imod = 0; xhci->intr[i].erstsz = 0; @@ -2401,7 +2403,7 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size) break; case 0x04: /* HCSPARAMS 1 */ ret = ((xhci->numports_2+xhci->numports_3)<<24) - | (MAXINTRS<<8) | MAXSLOTS; + | (xhci->numintrs<<8) | xhci->numslots; break; case 0x08: /* HCSPARAMS 2 */ ret = 0x0000000f; @@ -2756,7 +2758,7 @@ static void xhci_doorbell_write(void *ptr, hwaddr reg, (uint32_t)val); } } else { - if (reg > MAXSLOTS) { + if (reg > xhci->numslots) { fprintf(stderr, "xhci: bad doorbell %d\n", (int)reg); } else if (val > 31) { fprintf(stderr, "xhci: bad doorbell %d write: 0x%x\n", @@ -2862,7 +2864,7 @@ static void xhci_child_detach(USBPort *uport, USBDevice *child) XHCIState *xhci = container_of(bus, XHCIState, bus); int i; - for (i = 0; i < MAXSLOTS; i++) { + for (i = 0; i < xhci->numslots; i++) { if (xhci->slots[i].uport == uport) { xhci->slots[i].uport = NULL; } @@ -2882,7 +2884,7 @@ static int xhci_find_slotid(XHCIState *xhci, USBDevice *dev) XHCISlot *slot; int slotid; - for (slotid = 1; slotid <= MAXSLOTS; slotid++) { + for (slotid = 1; slotid <= xhci->numslots; slotid++) { slot = &xhci->slots[slotid-1]; if (slot->devaddr == dev->addr) { return slotid; @@ -2978,6 +2980,19 @@ static int usb_xhci_initfn(struct PCIDevice *dev) usb_xhci_init(xhci, &dev->qdev); + if (xhci->numintrs > MAXINTRS) { + xhci->numintrs = MAXINTRS; + } + if (xhci->numintrs < 1) { + xhci->numintrs = 1; + } + if (xhci->numslots > MAXSLOTS) { + xhci->numslots = MAXSLOTS; + } + if (xhci->numslots < 1) { + xhci->numslots = 1; + } + xhci->mfwrap_timer = qemu_new_timer_ns(vm_clock, xhci_mfwrap_timer, xhci); xhci->irq = xhci->pci_dev.irq[0]; @@ -3014,10 +3029,10 @@ static int usb_xhci_initfn(struct PCIDevice *dev) assert(ret >= 0); if (xhci->flags & (1 << XHCI_FLAG_USE_MSI)) { - msi_init(&xhci->pci_dev, 0x70, MAXINTRS, true, false); + msi_init(&xhci->pci_dev, 0x70, xhci->numintrs, true, false); } if (xhci->flags & (1 << XHCI_FLAG_USE_MSI_X)) { - msix_init(&xhci->pci_dev, MAXINTRS, + msix_init(&xhci->pci_dev, xhci->numintrs, &xhci->mem, 0, OFF_MSIX_TABLE, &xhci->mem, 0, OFF_MSIX_PBA, 0x90); @@ -3032,10 +3047,12 @@ static const VMStateDescription vmstate_xhci = { }; static Property xhci_properties[] = { - DEFINE_PROP_BIT("msi", XHCIState, flags, XHCI_FLAG_USE_MSI, true), - DEFINE_PROP_BIT("msix", XHCIState, flags, XHCI_FLAG_USE_MSI_X, true), - DEFINE_PROP_UINT32("p2", XHCIState, numports_2, 4), - DEFINE_PROP_UINT32("p3", XHCIState, numports_3, 4), + DEFINE_PROP_BIT("msi", XHCIState, flags, XHCI_FLAG_USE_MSI, true), + DEFINE_PROP_BIT("msix", XHCIState, flags, XHCI_FLAG_USE_MSI_X, true), + DEFINE_PROP_UINT32("intrs", XHCIState, numintrs, MAXINTRS), + DEFINE_PROP_UINT32("slots", XHCIState, numslots, MAXSLOTS), + DEFINE_PROP_UINT32("p2", XHCIState, numports_2, 4), + DEFINE_PROP_UINT32("p3", XHCIState, numports_3, 4), DEFINE_PROP_END_OF_LIST(), }; From 0ebfb144e8ad3f2da436d630fdcc5aa9ab646341 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 24 Oct 2012 16:19:21 +0200 Subject: [PATCH 1161/2270] xhci: fix usb name in caps Used to be "UTB" not "USB". Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 25b04cd11b..7b65741dd5 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2430,7 +2430,7 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size) ret = 0x02000402; /* USB 2.0 */ break; case 0x24: /* Supported Protocol:04 */ - ret = 0x20425455; /* "USB " */ + ret = 0x20425355; /* "USB " */ break; case 0x28: /* Supported Protocol:08 */ ret = 0x00000001 | (xhci->numports_2<<8); @@ -2442,7 +2442,7 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size) ret = 0x03000002; /* USB 3.0 */ break; case 0x34: /* Supported Protocol:04 */ - ret = 0x20425455; /* "USB " */ + ret = 0x20425355; /* "USB " */ break; case 0x38: /* Supported Protocol:08 */ ret = 0x00000000 | (xhci->numports_2+1) | (xhci->numports_3<<8); From c1556a812a16023894e53c7b2215929741a5bf17 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 14 Oct 2012 21:00:39 +0100 Subject: [PATCH 1162/2270] configure: Disable (clang) initializer-overrides warnings Disable clang's initializer-overrides warnings, as QEMU makes significant use of the pattern of initializing an array with a range-based default entry like [0 ... 0x1ff] = { GPIO_NONE, 0 } followed by specific entries which override that default, and clang would otherwise warn "initializer overrides prior initialization of this subobject" when it encountered the specific entry. Signed-off-by: Peter Maydell Signed-off-by: Blue Swirl --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index fa5657f6bc..34ba9c7199 100755 --- a/configure +++ b/configure @@ -1160,6 +1160,7 @@ gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits" gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags" gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags" gcc_flags="-fstack-protector-all -Wendif-labels $gcc_flags" +gcc_flags="-Wno-initializer-overrides $gcc_flags" # Note that we do not add -Werror to gcc_flags here, because that would # enable it for all configure tests. If a configure test failed due # to -Werror this would just silently disable some features, From 9bca81624ef9299b9a06013fd29cd6899079aab4 Mon Sep 17 00:00:00 2001 From: Bruce Rogers Date: Mon, 20 Aug 2012 12:45:08 -0600 Subject: [PATCH 1163/2270] configure: avoid compiler warning in pipe2 detection When building qemu-kvm for openSUSE:Factory, I am getting a warning in the pipe2 detection performed by configure, which prevents using --enable-werror. Change detection code to use return value of pipe2. Signed-off-by: Bruce Rogers Reviewed-by: Peter Maydell Signed-off-by: Blue Swirl --- configure | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configure b/configure index 34ba9c7199..37f712d475 100755 --- a/configure +++ b/configure @@ -2399,8 +2399,7 @@ cat > $TMPC << EOF int main(void) { int pipefd[2]; - pipe2(pipefd, O_CLOEXEC); - return 0; + return pipe2(pipefd, O_CLOEXEC); } EOF if compile_prog "" "" ; then From 0356404b0f1da939657cad1efeb556745cd430d5 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Mon, 22 Oct 2012 00:50:58 +0200 Subject: [PATCH 1164/2270] target-sparc64: disable VGA cirrus OpenBIOS on sparc64 only support Standard VGA and not Cirrus VGA. Don't build Cirrus VGA support so that it can't be selected. This fixes the breakage introduced by commit f2898771. Reported-by: Richard Henderson Cc: Blue Swirl Signed-off-by: Aurelien Jarno Tested-by: Richard Henderson Signed-off-by: Blue Swirl --- default-configs/sparc64-softmmu.mak | 1 - 1 file changed, 1 deletion(-) diff --git a/default-configs/sparc64-softmmu.mak b/default-configs/sparc64-softmmu.mak index c9a36c1e46..03e8b42712 100644 --- a/default-configs/sparc64-softmmu.mak +++ b/default-configs/sparc64-softmmu.mak @@ -6,7 +6,6 @@ CONFIG_M48T59=y CONFIG_PTIMER=y CONFIG_VGA=y CONFIG_VGA_PCI=y -CONFIG_VGA_CIRRUS=y CONFIG_SERIAL=y CONFIG_PARALLEL=y CONFIG_PCKBD=y From 49cdaea18b6a827fbe9555efef12821909e59229 Mon Sep 17 00:00:00 2001 From: Catalin Patulea Date: Mon, 22 Oct 2012 19:18:35 -0400 Subject: [PATCH 1165/2270] tests/tcg: fix a few warnings Signed-off-by: Catalin Patulea Signed-off-by: Blue Swirl --- tests/tcg/hello-i386.c | 3 ++- tests/tcg/test-i386.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/tcg/hello-i386.c b/tests/tcg/hello-i386.c index 86afc34fb1..fa00380de2 100644 --- a/tests/tcg/hello-i386.c +++ b/tests/tcg/hello-i386.c @@ -1,6 +1,6 @@ #include -static inline volatile void exit(int status) +static inline void exit(int status) { int __res; __asm__ volatile ("movl %%ecx,%%ebx\n"\ @@ -17,6 +17,7 @@ static inline int write(int fd, const char * buf, int len) "popl %%ebx\n"\ : "=a" (status) \ : "0" (__NR_write),"S" ((long)(fd)),"c" ((long)(buf)),"d" ((long)(len))); + return status; } void _start(void) diff --git a/tests/tcg/test-i386.c b/tests/tcg/test-i386.c index 64d929e482..40392ac51d 100644 --- a/tests/tcg/test-i386.c +++ b/tests/tcg/test-i386.c @@ -785,7 +785,7 @@ void fpu_clear_exceptions(void) long double fpregs[8]; } float_env32; - asm volatile ("fnstenv %0\n" : : "m" (float_env32)); + asm volatile ("fnstenv %0\n" : "=m" (float_env32)); float_env32.fpus &= ~0x7f; asm volatile ("fldenv %0\n" : : "m" (float_env32)); } From d1bd2423a90a144576cd140dc84b1fe8c7c8fda0 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 19 Oct 2012 14:54:23 +0100 Subject: [PATCH 1166/2270] Makefile: Forbid out-of-tree build from a source tree that has been built in If we try to do an out-of-tree build but the source tree we're building from has been used in the past for an in-tree build then things will go confusingly wrong. Specifically, some parts of the build process will pull in generated files from the old in-tree build (because SRC_PATH is on the vpath). Diagnose this situation so we can produce a useful error message and tell the user how to fix it (run distclean in the source tree). Signed-off-by: Peter Maydell Signed-off-by: Blue Swirl --- Makefile | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Makefile b/Makefile index 17e2d58ce5..b522b10195 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,17 @@ ifneq ($(wildcard config-host.mak),) # Put the all: rule here so that config-host.mak can contain dependencies. all: include config-host.mak + +# Check that we're not trying to do an out-of-tree build from +# a tree that's been used for an in-tree build. +ifneq ($(realpath $(SRC_PATH)),$(realpath .)) +ifneq ($(wildcard $(SRC_PATH)/config-host.mak),) +$(error This is an out of tree build but your source tree ($(SRC_PATH)) \ +seems to have been used for an in-tree build. You can fix this by running \ +"make distclean && rm -rf *-linux-user *-softmmu" in your source tree) +endif +endif + include $(SRC_PATH)/rules.mak config-host.mak: $(SRC_PATH)/configure @echo $@ is out-of-date, running configure From d64ed08eeca9587d28d573d81692721cea3273ca Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 25 Oct 2012 15:37:51 +0400 Subject: [PATCH 1167/2270] hw/xtensa_lx60: don't prematurely explode QEMUMachineInitArgs Don't explode QEMUMachineInitArgs before passing it to lx_init. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl --- hw/xtensa_lx60.c | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c index 5dd2e08332..4c42edc4ea 100644 --- a/hw/xtensa_lx60.c +++ b/hw/xtensa_lx60.c @@ -155,10 +155,7 @@ static void lx60_reset(void *opaque) cpu_reset(CPU(cpu)); } -static void lx_init(const LxBoardDesc *board, - 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) +static void lx_init(const LxBoardDesc *board, QEMUMachineInitArgs *args) { #ifdef TARGET_WORDS_BIGENDIAN int be = 1; @@ -171,6 +168,9 @@ static void lx_init(const LxBoardDesc *board, MemoryRegion *ram, *rom, *system_io; DriveInfo *dinfo; pflash_t *flash = NULL; + const char *cpu_model = args->cpu_model; + const char *kernel_filename = args->kernel_filename; + const char *kernel_cmdline = args->kernel_cmdline; int n; if (!cpu_model) { @@ -194,7 +194,7 @@ static void lx_init(const LxBoardDesc *board, } ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, "lx60.dram", ram_size); + memory_region_init_ram(ram, "lx60.dram", args->ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(system_memory, 0, ram); @@ -271,38 +271,22 @@ static void lx_init(const LxBoardDesc *board, static void xtensa_lx60_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; static const LxBoardDesc lx60_board = { .flash_size = 0x400000, .flash_sector_size = 0x10000, .sram_size = 0x20000, }; - lx_init(&lx60_board, ram_size, boot_device, - kernel_filename, kernel_cmdline, - initrd_filename, cpu_model); + lx_init(&lx60_board, args); } static void xtensa_lx200_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; static const LxBoardDesc lx200_board = { .flash_size = 0x1000000, .flash_sector_size = 0x20000, .sram_size = 0x2000000, }; - lx_init(&lx200_board, ram_size, boot_device, - kernel_filename, kernel_cmdline, - initrd_filename, cpu_model); + lx_init(&lx200_board, args); } static QEMUMachine xtensa_lx60_machine = { From 50cd72148211c5e5f22ea2519d19ce024226e61f Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 25 Oct 2012 15:37:52 +0400 Subject: [PATCH 1168/2270] hw/xtensa_sim: get rid of intermediate xtensa_sim_init Remove xtensa_sim_init that only explodes machine init args, rename sim_init to xtensa_sim_init. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl --- hw/xtensa_sim.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c index 2e846d8aa6..0d633e4724 100644 --- a/hw/xtensa_sim.c +++ b/hw/xtensa_sim.c @@ -44,16 +44,20 @@ static void sim_reset(void *opaque) cpu_reset(CPU(cpu)); } -static void sim_init(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) +static void xtensa_sim_init(QEMUMachineInitArgs *args) { XtensaCPU *cpu = NULL; CPUXtensaState *env = NULL; MemoryRegion *ram, *rom; + ram_addr_t ram_size = args->ram_size; + const char *cpu_model = args->cpu_model; + const char *kernel_filename = args->kernel_filename; int n; + if (!cpu_model) { + cpu_model = XTENSA_DEFAULT_CPU_MODEL; + } + for (n = 0; n < smp_cpus; n++) { cpu = cpu_xtensa_init(cpu_model); if (cpu == NULL) { @@ -96,21 +100,6 @@ static void sim_init(ram_addr_t ram_size, } } -static void xtensa_sim_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; - if (!cpu_model) { - cpu_model = XTENSA_DEFAULT_CPU_MODEL; - } - sim_init(ram_size, boot_device, kernel_filename, kernel_cmdline, - initrd_filename, cpu_model); -} - static QEMUMachine xtensa_sim_machine = { .name = "sim", .desc = "sim machine (" XTENSA_DEFAULT_CPU_MODEL ")", From 166792f7bbe2cad120b75062ff6f8f1b67366f18 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 20 Oct 2012 17:31:44 +0200 Subject: [PATCH 1169/2270] tcg/i386: remove suboptimal register shifting Now that CONFIG_TCG_PASS_AREG0 has been removed, it's easier to get an optimal code for the load/store functions. First swap the two registers used in tcg_out_tlb_load() so that the address end-up in the second register instead of the first one. Adjust tcg_out_qemu_ld() and tcg_out_qemu_st() to respectively call tcg_out_qemu_ld_direct() and tcg_out_qemu_st_direct() with the correct registers. Then replace the register shifting by direct load of the arguments. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/i386/tcg-target.c | 75 ++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 43 deletions(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 4952c057b3..4c59e339f5 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -1016,12 +1016,12 @@ static const void *qemu_st_helpers[4] = { LABEL_PTRS is filled with 1 (32-bit addresses) or 2 (64-bit addresses) positions of the displacements of forward jumps to the TLB miss case. - First argument register is loaded with the low part of the address. + Second argument register is loaded with the low part of the address. In the TLB hit case, it has been adjusted as indicated by the TLB and so is a host address. In the TLB miss case, it continues to hold a guest address. - Second argument register is clobbered. */ + First argument register is clobbered. */ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx, int mem_index, int s_bits, @@ -1039,25 +1039,25 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx, rexw = P_REXW; } - tcg_out_mov(s, type, r1, addrlo); tcg_out_mov(s, type, r0, addrlo); + tcg_out_mov(s, type, r1, addrlo); - tcg_out_shifti(s, SHIFT_SHR + rexw, r1, + tcg_out_shifti(s, SHIFT_SHR + rexw, r0, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); - tgen_arithi(s, ARITH_AND + rexw, r0, - TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0); tgen_arithi(s, ARITH_AND + rexw, r1, + TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0); + tgen_arithi(s, ARITH_AND + rexw, r0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0); - tcg_out_modrm_sib_offset(s, OPC_LEA + P_REXW, r1, TCG_AREG0, r1, 0, + tcg_out_modrm_sib_offset(s, OPC_LEA + P_REXW, r0, TCG_AREG0, r0, 0, offsetof(CPUArchState, tlb_table[mem_index][0]) + which); - /* cmp 0(r1), r0 */ - tcg_out_modrm_offset(s, OPC_CMP_GvEv + rexw, r0, r1, 0); + /* cmp 0(r0), r1 */ + tcg_out_modrm_offset(s, OPC_CMP_GvEv + rexw, r1, r0, 0); - tcg_out_mov(s, type, r0, addrlo); + tcg_out_mov(s, type, r1, addrlo); /* jne label1 */ tcg_out8(s, OPC_JCC_short + JCC_JNE); @@ -1065,8 +1065,8 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx, s->code_ptr++; if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) { - /* cmp 4(r1), addrhi */ - tcg_out_modrm_offset(s, OPC_CMP_GvEv, args[addrlo_idx+1], r1, 4); + /* cmp 4(r0), addrhi */ + tcg_out_modrm_offset(s, OPC_CMP_GvEv, args[addrlo_idx+1], r0, 4); /* jne label1 */ tcg_out8(s, OPC_JCC_short + JCC_JNE); @@ -1076,8 +1076,8 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx, /* TLB Hit. */ - /* add addend(r1), r0 */ - tcg_out_modrm_offset(s, OPC_ADD_GvEv + P_REXW, r0, r1, + /* add addend(r0), r1 */ + tcg_out_modrm_offset(s, OPC_ADD_GvEv + P_REXW, r1, r0, offsetof(CPUTLBEntry, addend) - which); } #endif @@ -1169,9 +1169,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int addrlo_idx; #if defined(CONFIG_SOFTMMU) int mem_index, s_bits; -#if TCG_TARGET_REG_BITS == 64 - int arg_idx; -#else +#if TCG_TARGET_REG_BITS == 32 int stack_adjust; #endif uint8_t *label_ptr[3]; @@ -1192,7 +1190,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, label_ptr, offsetof(CPUTLBEntry, addr_read)); /* TLB Hit. */ - tcg_out_qemu_ld_direct(s, data_reg, data_reg2, TCG_REG_L0, 0, opc); + tcg_out_qemu_ld_direct(s, data_reg, data_reg2, TCG_REG_L1, 0, opc); /* jmp label2 */ tcg_out8(s, OPC_JMP_short); @@ -1220,15 +1218,9 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, tcg_out_push(s, TCG_AREG0); stack_adjust += 4; #else - /* The first argument is already loaded with addrlo. */ - arg_idx = 1; - tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx], - mem_index); - /* XXX/FIXME: suboptimal */ - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3], TCG_REG_L2); - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], TCG_REG_L1); - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1], TCG_REG_L0); tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0); + /* The second argument is already loaded with addrlo. */ + tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], mem_index); #endif tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]); @@ -1294,9 +1286,9 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, use the ADDR32 prefix. For now, do nothing. */ if (offset != GUEST_BASE) { - tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L0, GUEST_BASE); - tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L0, base); - base = TCG_REG_L0; + tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L1, GUEST_BASE); + tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L1, base); + base = TCG_REG_L1; offset = 0; } } @@ -1317,8 +1309,8 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi, /* ??? Ideally we wouldn't need a scratch register. For user-only, we could perform the bswap twice to restore the original value instead of moving to the scratch. But as it is, the L constraint - means that TCG_REG_L1 is definitely free here. */ - const int scratch = TCG_REG_L1; + means that TCG_REG_L0 is definitely free here. */ + const int scratch = TCG_REG_L0; switch (sizeop) { case 0: @@ -1391,7 +1383,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, label_ptr, offsetof(CPUTLBEntry, addr_write)); /* TLB Hit. */ - tcg_out_qemu_st_direct(s, data_reg, data_reg2, TCG_REG_L0, 0, opc); + tcg_out_qemu_st_direct(s, data_reg, data_reg2, TCG_REG_L1, 0, opc); /* jmp label2 */ tcg_out8(s, OPC_JMP_short); @@ -1425,15 +1417,12 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, tcg_out_push(s, TCG_AREG0); stack_adjust += 4; #else - tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32), - TCG_REG_L1, data_reg); - tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_L2, mem_index); - stack_adjust = 0; - /* XXX/FIXME: suboptimal */ - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3], TCG_REG_L2); - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], TCG_REG_L1); - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1], TCG_REG_L0); tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0); + /* The second argument is already loaded with addrlo. */ + tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32), + tcg_target_call_iarg_regs[2], data_reg); + tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3], mem_index); + stack_adjust = 0; #endif tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]); @@ -1460,9 +1449,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, use the ADDR32 prefix. For now, do nothing. */ if (offset != GUEST_BASE) { - tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L0, GUEST_BASE); - tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L0, base); - base = TCG_REG_L0; + tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L1, GUEST_BASE); + tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L1, base); + base = TCG_REG_L1; offset = 0; } } From 17b914912d6175a5405d472832d6eba6187b6beb Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 20 Oct 2012 17:31:44 +0200 Subject: [PATCH 1170/2270] tcg/i386: remove ld/st third argument register constraint On x86_64, remove the constraint on the third argument register which is not needed: - For loads the helper arguments are env, addr, mem_idx. The addr value should not be in the two first argument registers as they are used in tcg_out_tlb_load(). - For stores the helper arguments are env, addr, data, mem_idx. The addr and data values should not be in the two first argument registers as they are used in tcg_out_tlb_load(). The data value should also not be in the two first argument registers, but could be in the third argument register in which case it would be already loaded at the right location. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/i386/tcg-target.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 4c59e339f5..9c8f69ae6b 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -92,7 +92,6 @@ static const int tcg_target_call_oarg_regs[] = { #if TCG_TARGET_REG_BITS == 64 # define TCG_REG_L0 tcg_target_call_iarg_regs[0] # define TCG_REG_L1 tcg_target_call_iarg_regs[1] -# define TCG_REG_L2 tcg_target_call_iarg_regs[2] #else # define TCG_REG_L0 TCG_REG_EAX # define TCG_REG_L1 TCG_REG_EDX @@ -181,14 +180,11 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) ct->ct |= TCG_CT_REG; #if TCG_TARGET_REG_BITS == 64 tcg_regset_set32(ct->u.regs, 0, 0xffff); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_L0); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_L1); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_L2); #else tcg_regset_set32(ct->u.regs, 0, 0xff); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_L0); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_L1); #endif + tcg_regset_reset_reg(ct->u.regs, TCG_REG_L0); + tcg_regset_reset_reg(ct->u.regs, TCG_REG_L1); break; case 'e': From 639368dd685f89b0567b56304c62937ad0ef8248 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:06 +0200 Subject: [PATCH 1171/2270] tcg: add temp_dead() A lot of code is duplicated to mark a temporary as dead. Replace it by temp_dead(), which in addition marks the temp as saved in memory for globals and local temps, instead of doing this a posteriori in temp_save(). Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg.c | 67 +++++++++++++++++++++++++------------------------------ 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 5faaca5ebf..2f84287746 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1564,6 +1564,24 @@ static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2) tcg_abort(); } +/* mark a temporary as dead. */ +static inline void temp_dead(TCGContext *s, int temp) +{ + TCGTemp *ts; + + ts = &s->temps[temp]; + if (!ts->fixed_reg) { + if (ts->val_type == TEMP_VAL_REG) { + s->reg_to_temp[ts->reg] = -1; + } + if (temp < s->nb_globals || (ts->temp_local && ts->mem_allocated)) { + ts->val_type = TEMP_VAL_MEM; + } else { + ts->val_type = TEMP_VAL_DEAD; + } + } +} + /* save a temporary to memory. 'allocated_regs' is used in case a temporary registers needs to be allocated to store a constant. */ static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs) @@ -1621,10 +1639,7 @@ static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs) if (ts->temp_local) { temp_save(s, i, allocated_regs); } else { - if (ts->val_type == TEMP_VAL_REG) { - s->reg_to_temp[ts->reg] = -1; - } - ts->val_type = TEMP_VAL_DEAD; + temp_dead(s, i); } } @@ -1673,8 +1688,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def, if (ots->val_type == TEMP_VAL_REG) s->reg_to_temp[ots->reg] = -1; reg = ts->reg; - s->reg_to_temp[reg] = -1; - ts->val_type = TEMP_VAL_DEAD; + temp_dead(s, args[1]); } else { if (ots->val_type == TEMP_VAL_REG) { reg = ots->reg; @@ -1801,14 +1815,8 @@ static void tcg_reg_alloc_op(TCGContext *s, } else { /* mark dead temporaries and free the associated registers */ for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) { - arg = args[i]; if (IS_DEAD_ARG(i)) { - ts = &s->temps[arg]; - if (!ts->fixed_reg) { - if (ts->val_type == TEMP_VAL_REG) - s->reg_to_temp[ts->reg] = -1; - ts->val_type = TEMP_VAL_DEAD; - } + temp_dead(s, args[i]); } } @@ -1848,11 +1856,12 @@ static void tcg_reg_alloc_op(TCGContext *s, tcg_regset_set_reg(allocated_regs, reg); /* if a fixed register is used, then a move will be done afterwards */ if (!ts->fixed_reg) { - if (ts->val_type == TEMP_VAL_REG) - s->reg_to_temp[ts->reg] = -1; if (IS_DEAD_ARG(i)) { - ts->val_type = TEMP_VAL_DEAD; + temp_dead(s, args[i]); } else { + if (ts->val_type == TEMP_VAL_REG) { + s->reg_to_temp[ts->reg] = -1; + } ts->val_type = TEMP_VAL_REG; ts->reg = reg; /* temp value is modified, so the value kept in memory is @@ -2011,14 +2020,8 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, /* mark dead temporaries and free the associated registers */ for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) { - arg = args[i]; if (IS_DEAD_ARG(i)) { - ts = &s->temps[arg]; - if (!ts->fixed_reg) { - if (ts->val_type == TEMP_VAL_REG) - s->reg_to_temp[ts->reg] = -1; - ts->val_type = TEMP_VAL_DEAD; - } + temp_dead(s, args[i]); } } @@ -2048,11 +2051,12 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, tcg_out_mov(s, ts->type, ts->reg, reg); } } else { - if (ts->val_type == TEMP_VAL_REG) - s->reg_to_temp[ts->reg] = -1; if (IS_DEAD_ARG(i)) { - ts->val_type = TEMP_VAL_DEAD; + temp_dead(s, args[i]); } else { + if (ts->val_type == TEMP_VAL_REG) { + s->reg_to_temp[ts->reg] = -1; + } ts->val_type = TEMP_VAL_REG; ts->reg = reg; ts->mem_coherent = 0; @@ -2167,16 +2171,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, args += args[0]; goto next; case INDEX_op_discard: - { - TCGTemp *ts; - ts = &s->temps[args[0]]; - /* mark the temporary as dead */ - if (!ts->fixed_reg) { - if (ts->val_type == TEMP_VAL_REG) - s->reg_to_temp[ts->reg] = -1; - ts->val_type = TEMP_VAL_DEAD; - } - } + temp_dead(s, args[0]); break; case INDEX_op_set_label: tcg_reg_alloc_bb_end(s, s->reserved_regs); From 7f6ceedf9c5da96ee2b1fe42573b781243bc2828 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:06 +0200 Subject: [PATCH 1172/2270] tcg: add tcg_reg_sync() Add a new function tcg_reg_sync() to synchronize the canonical location of a temp with the value in the associated register, but without freeing it. Rewrite tcg_reg_free() to first call tcg_reg_sync() and then to free the register. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 2f84287746..7141ebb235 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1517,22 +1517,33 @@ static void temp_allocate_frame(TCGContext *s, int temp) s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long); } -/* free register 'reg' by spilling the corresponding temporary if necessary */ -static void tcg_reg_free(TCGContext *s, int reg) +/* sync register 'reg' by saving it to the corresponding temporary */ +static inline void tcg_reg_sync(TCGContext *s, int reg) { TCGTemp *ts; int temp; temp = s->reg_to_temp[reg]; - if (temp != -1) { - ts = &s->temps[temp]; - assert(ts->val_type == TEMP_VAL_REG); - if (!ts->mem_coherent) { - if (!ts->mem_allocated) - temp_allocate_frame(s, temp); - tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset); + ts = &s->temps[temp]; + assert(ts->val_type == TEMP_VAL_REG); + if (!ts->mem_coherent && !ts->fixed_reg) { + if (!ts->mem_allocated) { + temp_allocate_frame(s, temp); } - ts->val_type = TEMP_VAL_MEM; + tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset); + } + ts->mem_coherent = 1; +} + +/* free register 'reg' by spilling the corresponding temporary if necessary */ +static void tcg_reg_free(TCGContext *s, int reg) +{ + int temp; + + temp = s->reg_to_temp[reg]; + if (temp != -1) { + tcg_reg_sync(s, reg); + s->temps[temp].val_type = TEMP_VAL_MEM; s->reg_to_temp[reg] = -1; } } From 1ad80729bea3d8ed1b67b457af44cbf9bbd8c3ec Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:06 +0200 Subject: [PATCH 1173/2270] tcg: add temp_sync() Add a new function temp_sync() to synchronize the canonical location of a temp with the value in the corresponding register, but without freeing the associated register. Rewrite temp_save() to call temp_sync() followed by temp_dead(). Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 7141ebb235..fabf3cf706 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1593,31 +1593,27 @@ static inline void temp_dead(TCGContext *s, int temp) } } -/* save a temporary to memory. 'allocated_regs' is used in case a +/* sync a temporary to memory. 'allocated_regs' is used in case a temporary registers needs to be allocated to store a constant. */ -static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs) +static inline void temp_sync(TCGContext *s, int temp, TCGRegSet allocated_regs) { TCGTemp *ts; - int reg; ts = &s->temps[temp]; if (!ts->fixed_reg) { switch(ts->val_type) { + case TEMP_VAL_CONST: + ts->reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], + allocated_regs); + ts->val_type = TEMP_VAL_REG; + s->reg_to_temp[ts->reg] = temp; + ts->mem_coherent = 0; + tcg_out_movi(s, ts->type, ts->reg, ts->val); + /* fallthrough*/ case TEMP_VAL_REG: - tcg_reg_free(s, ts->reg); + tcg_reg_sync(s, ts->reg); break; case TEMP_VAL_DEAD: - ts->val_type = TEMP_VAL_MEM; - break; - case TEMP_VAL_CONST: - reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], - allocated_regs); - if (!ts->mem_allocated) - temp_allocate_frame(s, temp); - tcg_out_movi(s, ts->type, reg, ts->val); - tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset); - ts->val_type = TEMP_VAL_MEM; - break; case TEMP_VAL_MEM: break; default: @@ -1626,6 +1622,14 @@ static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs) } } +/* save a temporary to memory. 'allocated_regs' is used in case a + temporary registers needs to be allocated to store a constant. */ +static inline void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs) +{ + temp_sync(s, temp, allocated_regs); + temp_dead(s, temp); +} + /* save globals to their canonical location and assume they can be modified be the following code. 'allocated_regs' is used in case a temporary registers needs to be allocated to store a constant. */ From ec7a869d31a1f82fe5b7750d8952c26753ea1df8 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:07 +0200 Subject: [PATCH 1174/2270] tcg: sync output arguments on liveness request Synchronize an output argument when requested by the liveness analysis. This is needed so that the temp can be declared dead later. For that, add a new op_sync_args table in which each bit tells if the corresponding output argument needs to be synchronized with the memory. Pass it to the tcg_reg_alloc_* functions, and honor this bit. We need to synchronize the argument before marking it as dead, and we have to make sure all the infos about the temp are correctly filled. At the same time change some types from unsigned int to uint16_t when passing op_dead_args. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg.c | 97 ++++++++++++++++++++++++++++++++++--------------------- tcg/tcg.h | 3 ++ 2 files changed, 64 insertions(+), 36 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index fabf3cf706..cfeeaf1e44 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1218,13 +1218,15 @@ static void tcg_liveness_analysis(TCGContext *s) TCGArg *args; const TCGOpDef *def; uint8_t *dead_temps; - unsigned int dead_args; + uint16_t dead_args; + uint8_t sync_args; gen_opc_ptr++; /* skip end */ nb_ops = gen_opc_ptr - gen_opc_buf; s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t)); + s->op_sync_args = tcg_malloc(nb_ops * sizeof(uint8_t)); dead_temps = tcg_malloc(s->nb_temps); memset(dead_temps, 1, s->nb_temps); @@ -1261,6 +1263,7 @@ static void tcg_liveness_analysis(TCGContext *s) /* output args are dead */ dead_args = 0; + sync_args = 0; for(i = 0; i < nb_oargs; i++) { arg = args[i]; if (dead_temps[arg]) { @@ -1285,6 +1288,7 @@ static void tcg_liveness_analysis(TCGContext *s) } } s->op_dead_args[op_index] = dead_args; + s->op_sync_args[op_index] = sync_args; } args--; } @@ -1378,6 +1382,7 @@ static void tcg_liveness_analysis(TCGContext *s) /* output args are dead */ dead_args = 0; + sync_args = 0; for(i = 0; i < nb_oargs; i++) { arg = args[i]; if (dead_temps[arg]) { @@ -1403,6 +1408,7 @@ static void tcg_liveness_analysis(TCGContext *s) dead_temps[arg] = 0; } s->op_dead_args[op_index] = dead_args; + s->op_sync_args[op_index] = sync_args; } break; } @@ -1421,6 +1427,8 @@ static void tcg_liveness_analysis(TCGContext *s) s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t)); memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t)); + s->op_sync_args = tcg_malloc(nb_ops * sizeof(uint8_t)); + memset(s->op_sync_args, 0, nb_ops * sizeof(uint8_t)); } #endif @@ -1662,8 +1670,10 @@ static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs) } #define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1) +#define NEED_SYNC_ARG(n) ((sync_args >> (n)) & 1) -static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args) +static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args, + uint16_t dead_args, uint8_t sync_args) { TCGTemp *ots; tcg_target_ulong val; @@ -1682,11 +1692,14 @@ static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args) ots->val_type = TEMP_VAL_CONST; ots->val = val; } + if (NEED_SYNC_ARG(0)) { + temp_sync(s, args[0], s->reserved_regs); + } } static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def, - const TCGArg *args, - unsigned int dead_args) + const TCGArg *args, uint16_t dead_args, + uint8_t sync_args) { TCGTemp *ts, *ots; int reg; @@ -1731,6 +1744,9 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def, s->reg_to_temp[ots->reg] = -1; ots->val_type = TEMP_VAL_CONST; ots->val = ts->val; + if (NEED_SYNC_ARG(0)) { + temp_sync(s, args[0], s->reserved_regs); + } return; } } else { @@ -1740,12 +1756,16 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def, ots->reg = reg; ots->val_type = TEMP_VAL_REG; ots->mem_coherent = 0; + + if (NEED_SYNC_ARG(0)) { + tcg_reg_sync(s, reg); + } } static void tcg_reg_alloc_op(TCGContext *s, const TCGOpDef *def, TCGOpcode opc, - const TCGArg *args, - unsigned int dead_args) + const TCGArg *args, uint16_t dead_args, + uint8_t sync_args) { TCGRegSet allocated_regs; int i, k, nb_iargs, nb_oargs, reg; @@ -1871,19 +1891,15 @@ static void tcg_reg_alloc_op(TCGContext *s, tcg_regset_set_reg(allocated_regs, reg); /* if a fixed register is used, then a move will be done afterwards */ if (!ts->fixed_reg) { - if (IS_DEAD_ARG(i)) { - temp_dead(s, args[i]); - } else { - if (ts->val_type == TEMP_VAL_REG) { - s->reg_to_temp[ts->reg] = -1; - } - ts->val_type = TEMP_VAL_REG; - ts->reg = reg; - /* temp value is modified, so the value kept in memory is - potentially not the same */ - ts->mem_coherent = 0; - s->reg_to_temp[reg] = arg; - } + if (ts->val_type == TEMP_VAL_REG) { + s->reg_to_temp[ts->reg] = -1; + } + ts->val_type = TEMP_VAL_REG; + ts->reg = reg; + /* temp value is modified, so the value kept in memory is + potentially not the same */ + ts->mem_coherent = 0; + s->reg_to_temp[reg] = arg; } oarg_end: new_args[i] = reg; @@ -1900,6 +1916,12 @@ static void tcg_reg_alloc_op(TCGContext *s, if (ts->fixed_reg && ts->reg != reg) { tcg_out_mov(s, ts->type, ts->reg, reg); } + if (NEED_SYNC_ARG(i)) { + tcg_reg_sync(s, reg); + } + if (IS_DEAD_ARG(i)) { + temp_dead(s, args[i]); + } } } @@ -1911,7 +1933,7 @@ static void tcg_reg_alloc_op(TCGContext *s, static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, TCGOpcode opc, const TCGArg *args, - unsigned int dead_args) + uint16_t dead_args, uint8_t sync_args) { int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params; TCGArg arg, func_arg; @@ -2066,16 +2088,18 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, tcg_out_mov(s, ts->type, ts->reg, reg); } } else { + if (ts->val_type == TEMP_VAL_REG) { + s->reg_to_temp[ts->reg] = -1; + } + ts->val_type = TEMP_VAL_REG; + ts->reg = reg; + ts->mem_coherent = 0; + s->reg_to_temp[reg] = arg; + if (NEED_SYNC_ARG(i)) { + tcg_reg_sync(s, reg); + } if (IS_DEAD_ARG(i)) { temp_dead(s, args[i]); - } else { - if (ts->val_type == TEMP_VAL_REG) { - s->reg_to_temp[ts->reg] = -1; - } - ts->val_type = TEMP_VAL_REG; - ts->reg = reg; - ts->mem_coherent = 0; - s->reg_to_temp[reg] = arg; } } } @@ -2106,7 +2130,6 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, TCGOpcode opc; int op_index; const TCGOpDef *def; - unsigned int dead_args; const TCGArg *args; #ifdef DEBUG_DISAS @@ -2167,12 +2190,13 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, switch(opc) { case INDEX_op_mov_i32: case INDEX_op_mov_i64: - dead_args = s->op_dead_args[op_index]; - tcg_reg_alloc_mov(s, def, args, dead_args); + tcg_reg_alloc_mov(s, def, args, s->op_dead_args[op_index], + s->op_sync_args[op_index]); break; case INDEX_op_movi_i32: case INDEX_op_movi_i64: - tcg_reg_alloc_movi(s, args); + tcg_reg_alloc_movi(s, args, s->op_dead_args[op_index], + s->op_sync_args[op_index]); break; case INDEX_op_debug_insn_start: /* debug instruction */ @@ -2193,8 +2217,9 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, tcg_out_label(s, args[0], s->code_ptr); break; case INDEX_op_call: - dead_args = s->op_dead_args[op_index]; - args += tcg_reg_alloc_call(s, def, opc, args, dead_args); + args += tcg_reg_alloc_call(s, def, opc, args, + s->op_dead_args[op_index], + s->op_sync_args[op_index]); goto next; case INDEX_op_end: goto the_end; @@ -2206,8 +2231,8 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, /* Note: in order to speed up the code, it would be much faster to have specialized register allocator functions for some common argument patterns */ - dead_args = s->op_dead_args[op_index]; - tcg_reg_alloc_op(s, def, opc, args, dead_args); + tcg_reg_alloc_op(s, def, opc, args, s->op_dead_args[op_index], + s->op_sync_args[op_index]); break; } args += def->nb_args; diff --git a/tcg/tcg.h b/tcg/tcg.h index 45e94f536c..cd5bf005f9 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -381,6 +381,9 @@ struct TCGContext { /* liveness analysis */ uint16_t *op_dead_args; /* for each operation, each bit tells if the corresponding argument is dead */ + uint8_t *op_sync_args; /* for each operation, each bit tells if the + corresponding output argument needs to be + sync to memory. */ /* tells in which temporary a given register is. It does not take into account fixed registers */ From 9c43b68de628a1e2cba556adfb71c17028eb802e Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:07 +0200 Subject: [PATCH 1175/2270] tcg: rework liveness analysis Rework the liveness analysis by tracking temps that need to go back to memory in addition to dead temps tracking. This allows to mark output arguments as "need sync", and to synchronize them back to memory as soon as they are not written anymore. This way even arguments mapping to globals can be marked as "dead", avoiding moves to a new register when input and outputs are aliased. In addition it means that registers are freed as soon as temps are not used anymore, instead of waiting for a basic block end or an op with side effects. This reduces register spilling especially on CPUs with few registers, and spread the mov over all the TB, increasing the performances on in-order CPUs. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg.c | 64 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index cfeeaf1e44..567ec87dad 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1180,31 +1180,27 @@ static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, } } -/* liveness analysis: end of function: globals are live, temps are - dead. */ -/* XXX: at this stage, not used as there would be little gains because - most TBs end with a conditional jump. */ -static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps) +/* liveness analysis: end of function: all temps are dead, and globals + should be in memory. */ +static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps, + uint8_t *mem_temps) { - memset(dead_temps, 0, s->nb_globals); - memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals); + memset(dead_temps, 1, s->nb_temps); + memset(mem_temps, 1, s->nb_globals); + memset(mem_temps + s->nb_globals, 0, s->nb_temps - s->nb_globals); } -/* liveness analysis: end of basic block: globals are live, temps are - dead, local temps are live. */ -static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps) +/* liveness analysis: end of basic block: all temps are dead, globals + and local temps should be in memory. */ +static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps, + uint8_t *mem_temps) { int i; - TCGTemp *ts; - memset(dead_temps, 0, s->nb_globals); - ts = &s->temps[s->nb_globals]; + memset(dead_temps, 1, s->nb_temps); + memset(mem_temps, 1, s->nb_globals); for(i = s->nb_globals; i < s->nb_temps; i++) { - if (ts->temp_local) - dead_temps[i] = 0; - else - dead_temps[i] = 1; - ts++; + mem_temps[i] = s->temps[i].temp_local; } } @@ -1217,7 +1213,7 @@ static void tcg_liveness_analysis(TCGContext *s) TCGOpcode op; TCGArg *args; const TCGOpDef *def; - uint8_t *dead_temps; + uint8_t *dead_temps, *mem_temps; uint16_t dead_args; uint8_t sync_args; @@ -1229,7 +1225,8 @@ static void tcg_liveness_analysis(TCGContext *s) s->op_sync_args = tcg_malloc(nb_ops * sizeof(uint8_t)); dead_temps = tcg_malloc(s->nb_temps); - memset(dead_temps, 1, s->nb_temps); + mem_temps = tcg_malloc(s->nb_temps); + tcg_la_func_end(s, dead_temps, mem_temps); args = gen_opparam_ptr; op_index = nb_ops - 1; @@ -1253,8 +1250,9 @@ static void tcg_liveness_analysis(TCGContext *s) if (call_flags & TCG_CALL_PURE) { for(i = 0; i < nb_oargs; i++) { arg = args[i]; - if (!dead_temps[arg]) + if (!dead_temps[arg] || mem_temps[arg]) { goto do_not_remove_call; + } } tcg_set_nop(s, gen_opc_buf + op_index, args - 1, nb_args); @@ -1269,12 +1267,17 @@ static void tcg_liveness_analysis(TCGContext *s) if (dead_temps[arg]) { dead_args |= (1 << i); } + if (mem_temps[arg]) { + sync_args |= (1 << i); + } dead_temps[arg] = 1; + mem_temps[arg] = 0; } if (!(call_flags & TCG_CALL_CONST)) { - /* globals are live (they may be used by the call) */ - memset(dead_temps, 0, s->nb_globals); + /* globals should go back to memory */ + memset(dead_temps, 1, s->nb_globals); + memset(mem_temps, 1, s->nb_globals); } /* input args are live */ @@ -1304,6 +1307,7 @@ static void tcg_liveness_analysis(TCGContext *s) args--; /* mark the temporary as dead */ dead_temps[args[0]] = 1; + mem_temps[args[0]] = 0; break; case INDEX_op_end: break; @@ -1369,8 +1373,9 @@ static void tcg_liveness_analysis(TCGContext *s) if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) { for(i = 0; i < nb_oargs; i++) { arg = args[i]; - if (!dead_temps[arg]) + if (!dead_temps[arg] || mem_temps[arg]) { goto do_not_remove; + } } do_remove: tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args); @@ -1388,15 +1393,20 @@ static void tcg_liveness_analysis(TCGContext *s) if (dead_temps[arg]) { dead_args |= (1 << i); } + if (mem_temps[arg]) { + sync_args |= (1 << i); + } dead_temps[arg] = 1; + mem_temps[arg] = 0; } /* if end of basic block, update */ if (def->flags & TCG_OPF_BB_END) { - tcg_la_bb_end(s, dead_temps); + tcg_la_bb_end(s, dead_temps, mem_temps); } else if (def->flags & TCG_OPF_CALL_CLOBBER) { - /* globals are live */ - memset(dead_temps, 0, s->nb_globals); + /* globals should go back to memory */ + memset(dead_temps, 1, s->nb_globals); + memset(mem_temps, 1, s->nb_globals); } /* input args are live */ From 4c4e1ab26bfc9b3f9b3097ecd0643bc20d0e2f0d Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:07 +0200 Subject: [PATCH 1176/2270] tcg: improve tcg_reg_alloc_movi() Now that the liveness analysis might mark some output temps as dead, call temp_dead() if needed. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tcg/tcg.c b/tcg/tcg.c index 567ec87dad..6586385168 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1705,6 +1705,9 @@ static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args, if (NEED_SYNC_ARG(0)) { temp_sync(s, args[0], s->reserved_regs); } + if (IS_DEAD_ARG(0)) { + temp_dead(s, args[0]); + } } static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def, From c29c1d7edfc57fc4ab15e30b3cea990a5685dd7a Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:07 +0200 Subject: [PATCH 1177/2270] tcg: rewrite tcg_reg_alloc_mov() Now that the liveness analysis provides more information, rewrite tcg_reg_alloc_mov(). This changes the behaviour about propagating constants and memory accesses. We now take the assumption that once a value is loaded into a register (from memory or from a constant), it's better to keep it there than to reload it later. This assumption is now always almost correct given that we are now sure the corresponding temp is going to be used later (otherwise it would have been synchronized and marked as dead already). The assumption is wrong if one of the op after clobbers some registers including the one of the holding the temp (this can be avoided by allocating clobbered registers last, which is what most TCG target do), or in case of lack of available register. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg.c | 106 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 61 insertions(+), 45 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 6586385168..b219a6d227 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1714,64 +1714,80 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def, const TCGArg *args, uint16_t dead_args, uint8_t sync_args) { + TCGRegSet allocated_regs; TCGTemp *ts, *ots; - int reg; - const TCGArgConstraint *arg_ct; + const TCGArgConstraint *arg_ct, *oarg_ct; + tcg_regset_set(allocated_regs, s->reserved_regs); ots = &s->temps[args[0]]; ts = &s->temps[args[1]]; - arg_ct = &def->args_ct[0]; + oarg_ct = &def->args_ct[0]; + arg_ct = &def->args_ct[1]; - /* XXX: always mark arg dead if IS_DEAD_ARG(1) */ - if (ts->val_type == TEMP_VAL_REG) { + /* If the source value is not in a register, and we're going to be + forced to have it in a register in order to perform the copy, + then copy the SOURCE value into its own register first. That way + we don't have to reload SOURCE the next time it is used. */ + if (((NEED_SYNC_ARG(0) || ots->fixed_reg) && ts->val_type != TEMP_VAL_REG) + || ts->val_type == TEMP_VAL_MEM) { + ts->reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs); + if (ts->val_type == TEMP_VAL_MEM) { + tcg_out_ld(s, ts->type, ts->reg, ts->mem_reg, ts->mem_offset); + ts->mem_coherent = 1; + } else if (ts->val_type == TEMP_VAL_CONST) { + tcg_out_movi(s, ts->type, ts->reg, ts->val); + } + s->reg_to_temp[ts->reg] = args[1]; + ts->val_type = TEMP_VAL_REG; + } + + if (IS_DEAD_ARG(0) && !ots->fixed_reg) { + /* mov to a non-saved dead register makes no sense (even with + liveness analysis disabled). */ + assert(NEED_SYNC_ARG(0)); + /* The code above should have moved the temp to a register. */ + assert(ts->val_type == TEMP_VAL_REG); + if (!ots->mem_allocated) { + temp_allocate_frame(s, args[0]); + } + tcg_out_st(s, ots->type, ts->reg, ots->mem_reg, ots->mem_offset); + if (IS_DEAD_ARG(1)) { + temp_dead(s, args[1]); + } + temp_dead(s, args[0]); + } else if (ts->val_type == TEMP_VAL_CONST) { + /* propagate constant */ + if (ots->val_type == TEMP_VAL_REG) { + s->reg_to_temp[ots->reg] = -1; + } + ots->val_type = TEMP_VAL_CONST; + ots->val = ts->val; + } else { + /* The code in the first if block should have moved the + temp to a register. */ + assert(ts->val_type == TEMP_VAL_REG); if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) { /* the mov can be suppressed */ - if (ots->val_type == TEMP_VAL_REG) + if (ots->val_type == TEMP_VAL_REG) { s->reg_to_temp[ots->reg] = -1; - reg = ts->reg; + } + ots->reg = ts->reg; temp_dead(s, args[1]); } else { - if (ots->val_type == TEMP_VAL_REG) { - reg = ots->reg; - } else { - reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs); - } - if (ts->reg != reg) { - tcg_out_mov(s, ots->type, reg, ts->reg); + if (ots->val_type != TEMP_VAL_REG) { + /* When allocating a new register, make sure to not spill the + input one. */ + tcg_regset_set_reg(allocated_regs, ts->reg); + ots->reg = tcg_reg_alloc(s, oarg_ct->u.regs, allocated_regs); } + tcg_out_mov(s, ots->type, ots->reg, ts->reg); } - } else if (ts->val_type == TEMP_VAL_MEM) { - if (ots->val_type == TEMP_VAL_REG) { - reg = ots->reg; - } else { - reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs); + ots->val_type = TEMP_VAL_REG; + ots->mem_coherent = 0; + s->reg_to_temp[ots->reg] = args[0]; + if (NEED_SYNC_ARG(0)) { + tcg_reg_sync(s, ots->reg); } - tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset); - } else if (ts->val_type == TEMP_VAL_CONST) { - if (ots->fixed_reg) { - reg = ots->reg; - tcg_out_movi(s, ots->type, reg, ts->val); - } else { - /* propagate constant */ - if (ots->val_type == TEMP_VAL_REG) - s->reg_to_temp[ots->reg] = -1; - ots->val_type = TEMP_VAL_CONST; - ots->val = ts->val; - if (NEED_SYNC_ARG(0)) { - temp_sync(s, args[0], s->reserved_regs); - } - return; - } - } else { - tcg_abort(); - } - s->reg_to_temp[reg] = args[0]; - ots->reg = reg; - ots->val_type = TEMP_VAL_REG; - ots->mem_coherent = 0; - - if (NEED_SYNC_ARG(0)) { - tcg_reg_sync(s, reg); } } From a52ad07e7cde61c799ca3351ccd58c04d6f7474f Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:07 +0200 Subject: [PATCH 1178/2270] tcg: always mark dead input arguments as dead Always mark dead input arguments as dead, even if the op is at the basic block end. This will allow to check that all temps are correctly saved. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index b219a6d227..d81b62883a 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1874,16 +1874,16 @@ static void tcg_reg_alloc_op(TCGContext *s, iarg_end: ; } + /* mark dead temporaries and free the associated registers */ + for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) { + if (IS_DEAD_ARG(i)) { + temp_dead(s, args[i]); + } + } + if (def->flags & TCG_OPF_BB_END) { tcg_reg_alloc_bb_end(s, allocated_regs); } else { - /* mark dead temporaries and free the associated registers */ - for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) { - if (IS_DEAD_ARG(i)) { - temp_dead(s, args[i]); - } - } - if (def->flags & TCG_OPF_CALL_CLOBBER) { /* XXX: permit generic clobber register list ? */ for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) { From 7dfd8c6aa1d0691d03c5ccc9b0c5a93bcf00f768 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:07 +0200 Subject: [PATCH 1179/2270] tcg: start with local temps in TEMP_VAL_MEM state Start with local temps in TEMP_VAL_MEM state, to make possible a later check that all the temps are correctly saved back to memory. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index d81b62883a..83336673aa 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -776,7 +776,11 @@ static void tcg_reg_alloc_start(TCGContext *s) } for(i = s->nb_globals; i < s->nb_temps; i++) { ts = &s->temps[i]; - ts->val_type = TEMP_VAL_DEAD; + if (ts->temp_local) { + ts->val_type = TEMP_VAL_MEM; + } else { + ts->val_type = TEMP_VAL_DEAD; + } ts->mem_allocated = 0; ts->fixed_reg = 0; } From 2c0366f036cbb7b2565ba8185a9daee98d709edb Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:07 +0200 Subject: [PATCH 1180/2270] tcg: don't explicitly save globals and temps The liveness analysis ensures that globals and temps are at the correct state at a basic block end or with an op with side effects. Avoid looping on all temps, this can be time consuming on targets with a lot of globals. Keep an assert in debug mode. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tcg/tcg.c b/tcg/tcg.c index 83336673aa..840e2525ec 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1648,8 +1648,14 @@ static inline void temp_sync(TCGContext *s, int temp, TCGRegSet allocated_regs) temporary registers needs to be allocated to store a constant. */ static inline void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs) { +#ifdef USE_LIVENESS_ANALYSIS + /* The liveness analysis already ensures that globals are back + in memory. Keep an assert for safety. */ + assert(s->temps[temp].val_type == TEMP_VAL_MEM || s->temps[temp].fixed_reg); +#else temp_sync(s, temp, allocated_regs); temp_dead(s, temp); +#endif } /* save globals to their canonical location and assume they can be @@ -1676,7 +1682,13 @@ static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs) if (ts->temp_local) { temp_save(s, i, allocated_regs); } else { +#ifdef USE_LIVENESS_ANALYSIS + /* The liveness analysis already ensures that temps are dead. + Keep an assert for safety. */ + assert(ts->val_type == TEMP_VAL_DEAD); +#else temp_dead(s, i); +#endif } } From 344028ba0f63b31c30723d2c1064d3539aa0f070 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:08 +0200 Subject: [PATCH 1181/2270] tcg: fix some op flags Some branch related ops are marked with TCG_OPF_SIDE_EFFECTS, some other not. In practice they don't need to, as they are all marked with TCG_OPF_BB_END, which is handled specifically in all the code. The call op is marked as TCG_OPF_SIDE_EFFECTS, which might be not true as there is are specific flags (TCG_CALL_CONST and TCG_CALL_PURE) for specifying that. On the other hand it always clobber arguments, so mark it as such even if the call op is handled in a different code path. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg-opc.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h index 04cb7ca038..2072281103 100644 --- a/tcg/tcg-opc.h +++ b/tcg/tcg-opc.h @@ -37,8 +37,8 @@ DEF(nopn, 0, 0, 1, 0) /* variable number of parameters */ DEF(discard, 1, 0, 0, 0) DEF(set_label, 0, 0, 1, TCG_OPF_BB_END) -DEF(call, 0, 1, 2, TCG_OPF_SIDE_EFFECTS) /* variable number of parameters */ -DEF(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) +DEF(call, 0, 1, 2, TCG_OPF_CALL_CLOBBER) /* variable number of parameters */ +DEF(br, 0, 0, 1, TCG_OPF_BB_END) #define IMPL(X) (X ? 0 : TCG_OPF_NOT_PRESENT) #if TCG_TARGET_REG_BITS == 32 @@ -81,12 +81,11 @@ DEF(rotl_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rot_i32)) DEF(rotr_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rot_i32)) DEF(deposit_i32, 1, 2, 2, IMPL(TCG_TARGET_HAS_deposit_i32)) -DEF(brcond_i32, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) +DEF(brcond_i32, 0, 2, 2, TCG_OPF_BB_END) DEF(add2_i32, 2, 4, 0, IMPL(TCG_TARGET_REG_BITS == 32)) DEF(sub2_i32, 2, 4, 0, IMPL(TCG_TARGET_REG_BITS == 32)) -DEF(brcond2_i32, 0, 4, 2, - TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS | IMPL(TCG_TARGET_REG_BITS == 32)) +DEF(brcond2_i32, 0, 4, 2, TCG_OPF_BB_END | IMPL(TCG_TARGET_REG_BITS == 32)) DEF(mulu2_i32, 2, 2, 0, IMPL(TCG_TARGET_REG_BITS == 32)) DEF(setcond2_i32, 1, 4, 1, IMPL(TCG_TARGET_REG_BITS == 32)) @@ -141,7 +140,7 @@ DEF(rotl_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rot_i64)) DEF(rotr_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rot_i64)) DEF(deposit_i64, 1, 2, 2, IMPL64 | IMPL(TCG_TARGET_HAS_deposit_i64)) -DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS | IMPL64) +DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | IMPL64) DEF(ext8s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext8s_i64)) DEF(ext16s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext16s_i64)) DEF(ext32s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext32s_i64)) @@ -165,8 +164,8 @@ DEF(debug_insn_start, 0, 0, 2, 0) #else DEF(debug_insn_start, 0, 0, 1, 0) #endif -DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) -DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) +DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END) +DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END) /* Note: even if TARGET_LONG_BITS is not defined, the INDEX_op constants must be defined */ #if TCG_TARGET_REG_BITS == 32 From b202d41ee705a7a6152d03eb362e2e2147505022 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:08 +0200 Subject: [PATCH 1182/2270] tcg: forbid ld/st function to modify globals Mapping a memory address using a global and accessing it through ld/st operations is currently broken. As it doesn't make any sense to do that performance wise, let's forbid that. Update the TCG documentation, and remove partial support for that. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/README | 3 +++ tcg/tcg-opc.h | 14 +++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/tcg/README b/tcg/README index aa86992bca..9d1b100613 100644 --- a/tcg/README +++ b/tcg/README @@ -349,6 +349,9 @@ st32_i64 t0, t1, offset write(t0, t1 + offset) Write 8, 16, 32 or 64 bits to host memory. +All this opcodes assume that the pointed host memory doesn't correspond +to a global. In the latter case the behaviour is unpredictable. + ********* 64-bit target on 32-bit host support The following opcodes are internal to TCG. Thus they are to be implemented by diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h index 2072281103..9651063414 100644 --- a/tcg/tcg-opc.h +++ b/tcg/tcg-opc.h @@ -57,9 +57,9 @@ DEF(ld8s_i32, 1, 1, 1, 0) DEF(ld16u_i32, 1, 1, 1, 0) DEF(ld16s_i32, 1, 1, 1, 0) DEF(ld_i32, 1, 1, 1, 0) -DEF(st8_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS) -DEF(st16_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS) -DEF(st_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS) +DEF(st8_i32, 0, 2, 1, 0) +DEF(st16_i32, 0, 2, 1, 0) +DEF(st_i32, 0, 2, 1, 0) /* arith */ DEF(add_i32, 1, 2, 0, 0) DEF(sub_i32, 1, 2, 0, 0) @@ -115,10 +115,10 @@ DEF(ld16s_i64, 1, 1, 1, IMPL64) DEF(ld32u_i64, 1, 1, 1, IMPL64) DEF(ld32s_i64, 1, 1, 1, IMPL64) DEF(ld_i64, 1, 1, 1, IMPL64) -DEF(st8_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS | IMPL64) -DEF(st16_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS | IMPL64) -DEF(st32_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS | IMPL64) -DEF(st_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS | IMPL64) +DEF(st8_i64, 0, 2, 1, IMPL64) +DEF(st16_i64, 0, 2, 1, IMPL64) +DEF(st32_i64, 0, 2, 1, IMPL64) +DEF(st_i64, 0, 2, 1, IMPL64) /* arith */ DEF(add_i64, 1, 2, 0, IMPL64) DEF(sub_i64, 1, 2, 0, IMPL64) From 3d5c5f876d171983d614925eebe4f0edccbb75be Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:08 +0200 Subject: [PATCH 1183/2270] tcg: synchronize globals for ops with side effects Operations with side effects (in practice qemu_ld/st ops), only need to synchronize globals to make sure the CPU state is consistent in case of exception. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg.c | 33 ++++++++++++++++++++++++--------- tcg/tcg.h | 4 ++-- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 840e2525ec..c9c642300d 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1407,9 +1407,8 @@ static void tcg_liveness_analysis(TCGContext *s) /* if end of basic block, update */ if (def->flags & TCG_OPF_BB_END) { tcg_la_bb_end(s, dead_temps, mem_temps); - } else if (def->flags & TCG_OPF_CALL_CLOBBER) { - /* globals should go back to memory */ - memset(dead_temps, 1, s->nb_globals); + } else if (def->flags & TCG_OPF_SIDE_EFFECTS) { + /* globals should be synced to memory */ memset(mem_temps, 1, s->nb_globals); } @@ -1670,6 +1669,23 @@ static void save_globals(TCGContext *s, TCGRegSet allocated_regs) } } +/* sync globals to their canonical location and assume they can be + read by the following code. 'allocated_regs' is used in case a + temporary registers needs to be allocated to store a constant. */ +static void sync_globals(TCGContext *s, TCGRegSet allocated_regs) +{ + int i; + + for (i = 0; i < s->nb_globals; i++) { +#ifdef USE_LIVENESS_ANALYSIS + assert(s->temps[i].val_type != TEMP_VAL_REG || s->temps[i].fixed_reg || + s->temps[i].mem_coherent); +#else + temp_sync(s, i, allocated_regs); +#endif + } +} + /* at the end of a basic block, we assume all temporaries are dead and all globals are stored at their canonical location. */ static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs) @@ -1907,12 +1923,11 @@ static void tcg_reg_alloc_op(TCGContext *s, tcg_reg_free(s, reg); } } - /* XXX: for load/store we could do that only for the slow path - (i.e. when a memory callback is called) */ - - /* store globals and free associated registers (we assume the insn - can modify any global. */ - save_globals(s, allocated_regs); + } + if (def->flags & TCG_OPF_SIDE_EFFECTS) { + /* sync globals if the op has side effects and might trigger + an exception. */ + sync_globals(s, allocated_regs); } /* satisfy the output constraints */ diff --git a/tcg/tcg.h b/tcg/tcg.h index cd5bf005f9..4b44ecdccb 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -530,8 +530,8 @@ enum { TCG_OPF_BB_END = 0x01, /* Instruction clobbers call registers and potentially update globals. */ TCG_OPF_CALL_CLOBBER = 0x02, - /* Instruction has side effects: it cannot be removed - if its outputs are not used. */ + /* Instruction has side effects: it cannot be removed if its outputs + are not used, and might trigger exceptions. */ TCG_OPF_SIDE_EFFECTS = 0x04, /* Instruction operands are 64-bits (otherwise 32-bits). */ TCG_OPF_64BIT = 0x08, From 78505279665e64d28e4a308818b69e6f77ecc5d2 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:08 +0200 Subject: [PATCH 1184/2270] tcg: rework TCG helper flags The current helper flags, TCG_CALL_CONST and TCG_CALL_PURE might be confusing and doesn't provide enough granularity for some helpers (FP helpers for example). This patch changes them into the following helpers flags: - TCG_CALL_NO_READ_GLOBALS means that the helper does not read globals, either directly or via an exception. They will not be saved to their canonical location before calling the helper. - TCG_CALL_NO_WRITE_GLOBALS means that the helper does not modify any globals. They will only be saved to their canonical locations before calling helpers, but they won't be reloaded afterwise. - TCG_CALL_NO_SIDE_EFFECTS means that the call to the function is removed if the return value is not used. It provides convenience flags, to avoid helper definitions longer than 80 characters. It also provides compatibility flags, and updates the documentation. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/README | 19 ++++++++++++++----- tcg/optimize.c | 3 ++- tcg/tcg-op.h | 18 ++++++++++-------- tcg/tcg.c | 24 ++++++++++++++++-------- tcg/tcg.h | 26 ++++++++++++++++++-------- 5 files changed, 60 insertions(+), 30 deletions(-) diff --git a/tcg/README b/tcg/README index 9d1b100613..ec1ac79375 100644 --- a/tcg/README +++ b/tcg/README @@ -77,11 +77,20 @@ destroyed, but local temporaries and globals are preserved. Using the tcg_gen_helper_x_y it is possible to call any function taking i32, i64 or pointer types. By default, before calling a helper, all globals are stored at their canonical location and it is assumed -that the function can modify them. This can be overridden by the -TCG_CALL_CONST function modifier. By default, the helper is allowed to -modify the CPU state or raise an exception. This can be overridden by -the TCG_CALL_PURE function modifier, in which case the call to the -function is removed if the return value is not used. +that the function can modify them. By default, the helper is allowed to +modify the CPU state or raise an exception. + +This can be overridden using the following function modifiers: +- TCG_CALL_NO_READ_GLOBALS means that the helper does not read globals, + either directly or via an exception. They will not be saved to their + canonical locations before calling the helper. +- TCG_CALL_NO_WRITE_GLOBALS means that the helper does not modify any globals. + They will only be saved to their canonical location before calling helpers, + but they won't be reloaded afterwise. +- TCG_CALL_NO_SIDE_EFFECTS means that the call to the function is removed if + the return value is not used. + +Note that TCG_CALL_NO_READ_GLOBALS implies TCG_CALL_NO_WRITE_GLOBALS. On some TCG targets (e.g. x86), several calling conventions are supported. diff --git a/tcg/optimize.c b/tcg/optimize.c index a06c8eb43e..8e5d918030 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -915,7 +915,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, case INDEX_op_call: nb_call_args = (args[0] >> 16) + (args[0] & 0xffff); - if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) { + if (!(args[nb_call_args + 1] & (TCG_CALL_NO_READ_GLOBALS | + TCG_CALL_NO_WRITE_GLOBALS))) { for (i = 0; i < nb_globals; i++) { reset_temp(i); } diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 8100a5a2e0..8d1da2b670 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -401,10 +401,10 @@ static inline void tcg_gen_helperN(void *func, int flags, int sizemask, } /* Note: Both tcg_gen_helper32() and tcg_gen_helper64() are currently - reserved for helpers in tcg-runtime.c. These helpers are all const - and pure, hence the call to tcg_gen_callN() with TCG_CALL_CONST | - TCG_CALL_PURE. This may need to be adjusted if these functions - start to be used with other helpers. */ + reserved for helpers in tcg-runtime.c. These helpers all do not read + globals and do not have side effects, hence the call to tcg_gen_callN() + with TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_SIDE_EFFECTS. This may need + to be adjusted if these functions start to be used with other helpers. */ static inline void tcg_gen_helper32(void *func, int sizemask, TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) { @@ -413,8 +413,9 @@ static inline void tcg_gen_helper32(void *func, int sizemask, TCGv_i32 ret, fn = tcg_const_ptr(func); args[0] = GET_TCGV_I32(a); args[1] = GET_TCGV_I32(b); - tcg_gen_callN(&tcg_ctx, fn, TCG_CALL_CONST | TCG_CALL_PURE, sizemask, - GET_TCGV_I32(ret), 2, args); + tcg_gen_callN(&tcg_ctx, fn, + TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_SIDE_EFFECTS, + sizemask, GET_TCGV_I32(ret), 2, args); tcg_temp_free_ptr(fn); } @@ -426,8 +427,9 @@ static inline void tcg_gen_helper64(void *func, int sizemask, TCGv_i64 ret, fn = tcg_const_ptr(func); args[0] = GET_TCGV_I64(a); args[1] = GET_TCGV_I64(b); - tcg_gen_callN(&tcg_ctx, fn, TCG_CALL_CONST | TCG_CALL_PURE, sizemask, - GET_TCGV_I64(ret), 2, args); + tcg_gen_callN(&tcg_ctx, fn, + TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_SIDE_EFFECTS, + sizemask, GET_TCGV_I64(ret), 2, args); tcg_temp_free_ptr(fn); } diff --git a/tcg/tcg.c b/tcg/tcg.c index c9c642300d..c3a7f19bd7 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1251,7 +1251,7 @@ static void tcg_liveness_analysis(TCGContext *s) /* pure functions can be removed if their result is not used */ - if (call_flags & TCG_CALL_PURE) { + if (call_flags & TCG_CALL_NO_SIDE_EFFECTS) { for(i = 0; i < nb_oargs; i++) { arg = args[i]; if (!dead_temps[arg] || mem_temps[arg]) { @@ -1277,11 +1277,15 @@ static void tcg_liveness_analysis(TCGContext *s) dead_temps[arg] = 1; mem_temps[arg] = 0; } - - if (!(call_flags & TCG_CALL_CONST)) { + + if (!(call_flags & TCG_CALL_NO_READ_GLOBALS)) { + /* globals should be synced to memory */ + memset(mem_temps, 1, s->nb_globals); + } + if (!(call_flags & (TCG_CALL_NO_WRITE_GLOBALS | + TCG_CALL_NO_READ_GLOBALS))) { /* globals should go back to memory */ memset(dead_temps, 1, s->nb_globals); - memset(mem_temps, 1, s->nb_globals); } /* input args are live */ @@ -2128,10 +2132,14 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, tcg_reg_free(s, reg); } } - - /* store globals and free associated registers (we assume the call - can modify any global. */ - if (!(flags & TCG_CALL_CONST)) { + + /* Save globals if they might be written by the helper, sync them if + they might be read. */ + if (flags & TCG_CALL_NO_READ_GLOBALS) { + /* Nothing to do */ + } else if (flags & TCG_CALL_NO_WRITE_GLOBALS) { + sync_globals(s, allocated_regs); + } else { save_globals(s, allocated_regs); } diff --git a/tcg/tcg.h b/tcg/tcg.h index 4b44ecdccb..96b62229c2 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -253,14 +253,24 @@ typedef int TCGv_i64; #define TCGV_UNUSED_I64(x) x = MAKE_TCGV_I64(-1) /* call flags */ -/* A pure function only reads its arguments and TCG global variables - and cannot raise exceptions. Hence a call to a pure function can be - safely suppressed if the return value is not used. */ -#define TCG_CALL_PURE 0x0010 -/* A const function only reads its arguments and does not use TCG - global variables. Hence a call to such a function does not - save TCG global variables back to their canonical location. */ -#define TCG_CALL_CONST 0x0020 +/* Helper does not read globals (either directly or through an exception). It + implies TCG_CALL_NO_WRITE_GLOBALS. */ +#define TCG_CALL_NO_READ_GLOBALS 0x0010 +/* Helper does not write globals */ +#define TCG_CALL_NO_WRITE_GLOBALS 0x0020 +/* Helper can be safely suppressed if the return value is not used. */ +#define TCG_CALL_NO_SIDE_EFFECTS 0x0040 + +/* convenience version of most used call flags */ +#define TCG_CALL_NO_RWG TCG_CALL_NO_READ_GLOBALS +#define TCG_CALL_NO_WG TCG_CALL_NO_WRITE_GLOBALS +#define TCG_CALL_NO_SE TCG_CALL_NO_SIDE_EFFECTS +#define TCG_CALL_NO_RWG_SE (TCG_CALL_NO_RWG | TCG_CALL_NO_SE) +#define TCG_CALL_NO_WG_SE (TCG_CALL_NO_WG | TCG_CALL_NO_SE) + +/* compatibility call flags, they should be eventually be removed */ +#define TCG_CALL_PURE TCG_CALL_NO_SIDE_EFFECTS +#define TCG_CALL_CONST TCG_CALL_NO_READ_GLOBALS /* used to align parameters */ #define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-1) From 0c0dcdfed0833539ed03560d251c31463c0eb9f9 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:08 +0200 Subject: [PATCH 1185/2270] target-alpha: rename helper flags Rename helper flags to the new ones. This is purely a mechanical change, it's possible to use better flags by looking at the helpers. Acked-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-alpha/helper.h | 150 +++++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 75 deletions(-) diff --git a/target-alpha/helper.h b/target-alpha/helper.h index a184def3e9..162816fa73 100644 --- a/target-alpha/helper.h +++ b/target-alpha/helper.h @@ -1,7 +1,7 @@ #include "def-helper.h" DEF_HELPER_3(excp, noreturn, env, int, int) -DEF_HELPER_FLAGS_1(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64, env) +DEF_HELPER_FLAGS_1(load_pcc, TCG_CALL_NO_RWG_SE, i64, env) DEF_HELPER_3(addqv, i64, env, i64, i64) DEF_HELPER_3(addlv, i64, env, i64, i64) @@ -9,89 +9,89 @@ DEF_HELPER_3(subqv, i64, env, i64, i64) DEF_HELPER_3(sublv, i64, env, i64, i64) DEF_HELPER_3(mullv, i64, env, i64, i64) DEF_HELPER_3(mulqv, i64, env, i64, i64) -DEF_HELPER_FLAGS_2(umulh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(umulh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_1(ctpop, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64) -DEF_HELPER_FLAGS_1(ctlz, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64) -DEF_HELPER_FLAGS_1(cttz, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64) +DEF_HELPER_FLAGS_1(ctpop, TCG_CALL_NO_RWG_SE, i64, i64) +DEF_HELPER_FLAGS_1(ctlz, TCG_CALL_NO_RWG_SE, i64, i64) +DEF_HELPER_FLAGS_1(cttz, TCG_CALL_NO_RWG_SE, i64, i64) -DEF_HELPER_FLAGS_2(zap, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(zapnot, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(zap, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(zapnot, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(cmpbge, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(cmpbge, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(minub8, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(minsb8, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(minuw4, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(minsw4, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(maxub8, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(maxsb8, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(maxuw4, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(maxsw4, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(perr, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_1(pklb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64) -DEF_HELPER_FLAGS_1(pkwb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64) -DEF_HELPER_FLAGS_1(unpkbl, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64) -DEF_HELPER_FLAGS_1(unpkbw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64) +DEF_HELPER_FLAGS_2(minub8, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(minsb8, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(minuw4, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(minsw4, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(maxub8, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(maxsb8, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(maxuw4, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(maxsw4, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(perr, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_1(pklb, TCG_CALL_NO_RWG_SE, i64, i64) +DEF_HELPER_FLAGS_1(pkwb, TCG_CALL_NO_RWG_SE, i64, i64) +DEF_HELPER_FLAGS_1(unpkbl, TCG_CALL_NO_RWG_SE, i64, i64) +DEF_HELPER_FLAGS_1(unpkbw, TCG_CALL_NO_RWG_SE, i64, i64) -DEF_HELPER_FLAGS_1(load_fpcr, TCG_CALL_CONST | TCG_CALL_PURE, i64, env) -DEF_HELPER_FLAGS_2(store_fpcr, TCG_CALL_CONST, void, env, i64) +DEF_HELPER_FLAGS_1(load_fpcr, TCG_CALL_NO_RWG_SE, i64, env) +DEF_HELPER_FLAGS_2(store_fpcr, TCG_CALL_NO_RWG, void, env, i64) -DEF_HELPER_FLAGS_1(f_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64) -DEF_HELPER_FLAGS_1(memory_to_f, TCG_CALL_CONST | TCG_CALL_PURE, i64, i32) -DEF_HELPER_FLAGS_3(addf, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(subf, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(mulf, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(divf, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_2(sqrtf, TCG_CALL_CONST, i64, env, i64) +DEF_HELPER_FLAGS_1(f_to_memory, TCG_CALL_NO_RWG_SE, i32, i64) +DEF_HELPER_FLAGS_1(memory_to_f, TCG_CALL_NO_RWG_SE, i64, i32) +DEF_HELPER_FLAGS_3(addf, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(subf, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(mulf, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(divf, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_2(sqrtf, TCG_CALL_NO_RWG, i64, env, i64) -DEF_HELPER_FLAGS_1(g_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64) -DEF_HELPER_FLAGS_1(memory_to_g, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64) -DEF_HELPER_FLAGS_3(addg, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(subg, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(mulg, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(divg, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_2(sqrtg, TCG_CALL_CONST, i64, env, i64) +DEF_HELPER_FLAGS_1(g_to_memory, TCG_CALL_NO_RWG_SE, i64, i64) +DEF_HELPER_FLAGS_1(memory_to_g, TCG_CALL_NO_RWG_SE, i64, i64) +DEF_HELPER_FLAGS_3(addg, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(subg, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(mulg, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(divg, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_2(sqrtg, TCG_CALL_NO_RWG, i64, env, i64) -DEF_HELPER_FLAGS_1(s_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64) -DEF_HELPER_FLAGS_1(memory_to_s, TCG_CALL_CONST | TCG_CALL_PURE, i64, i32) -DEF_HELPER_FLAGS_3(adds, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(subs, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(muls, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(divs, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_2(sqrts, TCG_CALL_CONST, i64, env, i64) +DEF_HELPER_FLAGS_1(s_to_memory, TCG_CALL_NO_RWG_SE, i32, i64) +DEF_HELPER_FLAGS_1(memory_to_s, TCG_CALL_NO_RWG_SE, i64, i32) +DEF_HELPER_FLAGS_3(adds, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(subs, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(muls, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(divs, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_2(sqrts, TCG_CALL_NO_RWG, i64, env, i64) -DEF_HELPER_FLAGS_3(addt, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(subt, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(mult, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(divt, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_2(sqrtt, TCG_CALL_CONST, i64, env, i64) +DEF_HELPER_FLAGS_3(addt, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(subt, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(mult, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(divt, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_2(sqrtt, TCG_CALL_NO_RWG, i64, env, i64) -DEF_HELPER_FLAGS_3(cmptun, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(cmpteq, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(cmptle, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(cmptlt, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(cmpgeq, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(cmpgle, TCG_CALL_CONST, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(cmpglt, TCG_CALL_CONST, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(cmptun, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(cmpteq, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(cmptle, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(cmptlt, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(cmpgeq, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(cmpgle, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(cmpglt, TCG_CALL_NO_RWG, i64, env, i64, i64) -DEF_HELPER_FLAGS_2(cvtts, TCG_CALL_CONST, i64, env, i64) -DEF_HELPER_FLAGS_2(cvtst, TCG_CALL_CONST, i64, env, i64) -DEF_HELPER_FLAGS_2(cvtqs, TCG_CALL_CONST, i64, env, i64) -DEF_HELPER_FLAGS_2(cvtqt, TCG_CALL_CONST, i64, env, i64) -DEF_HELPER_FLAGS_2(cvtqf, TCG_CALL_CONST, i64, env, i64) -DEF_HELPER_FLAGS_2(cvtgf, TCG_CALL_CONST, i64, env, i64) -DEF_HELPER_FLAGS_2(cvtgq, TCG_CALL_CONST, i64, env, i64) -DEF_HELPER_FLAGS_2(cvtqg, TCG_CALL_CONST, i64, env, i64) +DEF_HELPER_FLAGS_2(cvtts, TCG_CALL_NO_RWG, i64, env, i64) +DEF_HELPER_FLAGS_2(cvtst, TCG_CALL_NO_RWG, i64, env, i64) +DEF_HELPER_FLAGS_2(cvtqs, TCG_CALL_NO_RWG, i64, env, i64) +DEF_HELPER_FLAGS_2(cvtqt, TCG_CALL_NO_RWG, i64, env, i64) +DEF_HELPER_FLAGS_2(cvtqf, TCG_CALL_NO_RWG, i64, env, i64) +DEF_HELPER_FLAGS_2(cvtgf, TCG_CALL_NO_RWG, i64, env, i64) +DEF_HELPER_FLAGS_2(cvtgq, TCG_CALL_NO_RWG, i64, env, i64) +DEF_HELPER_FLAGS_2(cvtqg, TCG_CALL_NO_RWG, i64, env, i64) -DEF_HELPER_FLAGS_2(cvttq, TCG_CALL_CONST, i64, env, i64) -DEF_HELPER_FLAGS_2(cvttq_c, TCG_CALL_CONST, i64, env, i64) -DEF_HELPER_FLAGS_2(cvttq_svic, TCG_CALL_CONST, i64, env, i64) +DEF_HELPER_FLAGS_2(cvttq, TCG_CALL_NO_RWG, i64, env, i64) +DEF_HELPER_FLAGS_2(cvttq_c, TCG_CALL_NO_RWG, i64, env, i64) +DEF_HELPER_FLAGS_2(cvttq_svic, TCG_CALL_NO_RWG, i64, env, i64) -DEF_HELPER_FLAGS_2(setroundmode, TCG_CALL_CONST, void, env, i32) -DEF_HELPER_FLAGS_2(setflushzero, TCG_CALL_CONST, void, env, i32) -DEF_HELPER_FLAGS_1(fp_exc_clear, TCG_CALL_CONST, void, env) -DEF_HELPER_FLAGS_1(fp_exc_get, TCG_CALL_CONST | TCG_CALL_PURE, i32, env) +DEF_HELPER_FLAGS_2(setroundmode, TCG_CALL_NO_RWG, void, env, i32) +DEF_HELPER_FLAGS_2(setflushzero, TCG_CALL_NO_RWG, void, env, i32) +DEF_HELPER_FLAGS_1(fp_exc_clear, TCG_CALL_NO_RWG, void, env) +DEF_HELPER_FLAGS_1(fp_exc_get, TCG_CALL_NO_RWG_SE, i32, env) DEF_HELPER_3(fp_exc_raise, void, env, i32, i32) DEF_HELPER_3(fp_exc_raise_s, void, env, i32, i32) @@ -110,13 +110,13 @@ DEF_HELPER_2(stq_phys, void, i64, i64) DEF_HELPER_3(stl_c_phys, i64, env, i64, i64) DEF_HELPER_3(stq_c_phys, i64, env, i64, i64) -DEF_HELPER_FLAGS_1(tbia, TCG_CALL_CONST, void, env) -DEF_HELPER_FLAGS_2(tbis, TCG_CALL_CONST, void, env, i64) +DEF_HELPER_FLAGS_1(tbia, TCG_CALL_NO_RWG, void, env) +DEF_HELPER_FLAGS_2(tbis, TCG_CALL_NO_RWG, void, env, i64) DEF_HELPER_1(halt, void, i64); -DEF_HELPER_FLAGS_0(get_time, TCG_CALL_CONST, i64) -DEF_HELPER_FLAGS_2(set_alarm, TCG_CALL_CONST, void, env, i64) +DEF_HELPER_FLAGS_0(get_time, TCG_CALL_NO_RWG, i64) +DEF_HELPER_FLAGS_2(set_alarm, TCG_CALL_NO_RWG, void, env, i64) #endif #include "def-helper.h" From 4b3d4829abfdeb5078195898997e73724898c41e Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:08 +0200 Subject: [PATCH 1186/2270] target-arm: rename helper flags Rename helper flags to the new ones. This is purely a mechanical change, it's possible to use better flags by looking at the helpers. Cc: Paul Brook Cc: Peter Maydell Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-arm/helper.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/target-arm/helper.h b/target-arm/helper.h index 60812de80b..3d23ceb257 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -1,8 +1,8 @@ #include "def-helper.h" -DEF_HELPER_FLAGS_1(clz, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) -DEF_HELPER_FLAGS_1(sxtb16, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) -DEF_HELPER_FLAGS_1(uxtb16, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) +DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, i32, i32) +DEF_HELPER_FLAGS_1(sxtb16, TCG_CALL_NO_RWG_SE, i32, i32) +DEF_HELPER_FLAGS_1(uxtb16, TCG_CALL_NO_RWG_SE, i32, i32) DEF_HELPER_3(add_setq, i32, env, i32, i32) DEF_HELPER_3(add_saturate, i32, env, i32, i32) @@ -10,9 +10,9 @@ DEF_HELPER_3(sub_saturate, i32, env, i32, i32) DEF_HELPER_3(add_usaturate, i32, env, i32, i32) DEF_HELPER_3(sub_usaturate, i32, env, i32, i32) DEF_HELPER_2(double_saturate, i32, env, s32) -DEF_HELPER_FLAGS_2(sdiv, TCG_CALL_CONST | TCG_CALL_PURE, s32, s32, s32) -DEF_HELPER_FLAGS_2(udiv, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32) -DEF_HELPER_FLAGS_1(rbit, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) +DEF_HELPER_FLAGS_2(sdiv, TCG_CALL_NO_RWG_SE, s32, s32, s32) +DEF_HELPER_FLAGS_2(udiv, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_1(rbit, TCG_CALL_NO_RWG_SE, i32, i32) #define PAS_OP(pfx) \ DEF_HELPER_3(pfx ## add8, i32, i32, i32, ptr) \ @@ -44,11 +44,11 @@ DEF_HELPER_3(usat, i32, env, i32, i32) DEF_HELPER_3(ssat16, i32, env, i32, i32) DEF_HELPER_3(usat16, i32, env, i32, i32) -DEF_HELPER_FLAGS_2(usad8, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32) +DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_1(logicq_cc, i32, i64) -DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_CONST | TCG_CALL_PURE, +DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_2(exception, void, env, i32) DEF_HELPER_1(wfi, void, env) From 3e2bed86a24e13970bcc50527e21fe75f409f7ad Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:08 +0200 Subject: [PATCH 1187/2270] target-cris: rename helper flags Rename helper flags to the new ones. This is purely a mechanical change, it's possible to use better flags by looking at the helpers. Acked-by: Edgar E. Iglesias Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-cris/helper.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/target-cris/helper.h b/target-cris/helper.h index 99fb326a85..fe12083a16 100644 --- a/target-cris/helper.h +++ b/target-cris/helper.h @@ -10,19 +10,19 @@ DEF_HELPER_1(rfn, void, env); DEF_HELPER_3(movl_sreg_reg, void, env, i32, i32) DEF_HELPER_3(movl_reg_sreg, void, env, i32, i32) -DEF_HELPER_FLAGS_1(lz, TCG_CALL_PURE, i32, i32); -DEF_HELPER_FLAGS_4(btst, TCG_CALL_PURE, i32, env, i32, i32, i32); +DEF_HELPER_FLAGS_1(lz, TCG_CALL_NO_SE, i32, i32); +DEF_HELPER_FLAGS_4(btst, TCG_CALL_NO_SE, i32, env, i32, i32, i32); -DEF_HELPER_FLAGS_4(evaluate_flags_muls, TCG_CALL_PURE, i32, env, i32, i32, i32) -DEF_HELPER_FLAGS_4(evaluate_flags_mulu, TCG_CALL_PURE, i32, env, i32, i32, i32) -DEF_HELPER_FLAGS_5(evaluate_flags_mcp, TCG_CALL_PURE, i32, env, +DEF_HELPER_FLAGS_4(evaluate_flags_muls, TCG_CALL_NO_SE, i32, env, i32, i32, i32) +DEF_HELPER_FLAGS_4(evaluate_flags_mulu, TCG_CALL_NO_SE, i32, env, i32, i32, i32) +DEF_HELPER_FLAGS_5(evaluate_flags_mcp, TCG_CALL_NO_SE, i32, env, i32, i32, i32, i32) -DEF_HELPER_FLAGS_5(evaluate_flags_alu_4, TCG_CALL_PURE, i32, env, +DEF_HELPER_FLAGS_5(evaluate_flags_alu_4, TCG_CALL_NO_SE, i32, env, i32, i32, i32, i32) -DEF_HELPER_FLAGS_5(evaluate_flags_sub_4, TCG_CALL_PURE, i32, env, +DEF_HELPER_FLAGS_5(evaluate_flags_sub_4, TCG_CALL_NO_SE, i32, env, i32, i32, i32, i32) -DEF_HELPER_FLAGS_3(evaluate_flags_move_4, TCG_CALL_PURE, i32, env, i32, i32) -DEF_HELPER_FLAGS_3(evaluate_flags_move_2, TCG_CALL_PURE, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(evaluate_flags_move_4, TCG_CALL_NO_SE, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(evaluate_flags_move_2, TCG_CALL_NO_SE, i32, env, i32, i32) DEF_HELPER_1(evaluate_flags, void, env) DEF_HELPER_1(top_evaluate_flags, void, env) From 95b638a29214173d4de04567b8d08f4064580abd Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:08 +0200 Subject: [PATCH 1188/2270] target-i386: rename helper flags Rename helper flags to the new ones. This is purely a mechanical change, it's possible to use better flags by looking at the helpers. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-i386/helper.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-i386/helper.h b/target-i386/helper.h index 93850ceecd..970fcd98ff 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -1,7 +1,7 @@ #include "def-helper.h" -DEF_HELPER_FLAGS_2(cc_compute_all, TCG_CALL_PURE, i32, env, int) -DEF_HELPER_FLAGS_2(cc_compute_c, TCG_CALL_PURE, i32, env, int) +DEF_HELPER_FLAGS_2(cc_compute_all, TCG_CALL_NO_SE, i32, env, int) +DEF_HELPER_FLAGS_2(cc_compute_c, TCG_CALL_NO_SE, i32, env, int) DEF_HELPER_0(lock, void) DEF_HELPER_0(unlock, void) From 2a997687b867d3fa005ae6abca01121e68e5c02e Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:09 +0200 Subject: [PATCH 1189/2270] target-microblaze: rename helper flags Rename helper flags to the new ones. This is purely a mechanical change, it's possible to use better flags by looking at the helpers. Acked-by: Edgar E. Iglesias Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-microblaze/helper.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h index a1a732cfdc..a667122e91 100644 --- a/target-microblaze/helper.h +++ b/target-microblaze/helper.h @@ -2,10 +2,10 @@ DEF_HELPER_2(raise_exception, void, env, i32) DEF_HELPER_1(debug, void, env) -DEF_HELPER_FLAGS_3(carry, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32) +DEF_HELPER_FLAGS_3(carry, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_2(cmp, i32, i32, i32) DEF_HELPER_2(cmpu, i32, i32, i32) -DEF_HELPER_FLAGS_1(clz, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32) +DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, i32, i32) DEF_HELPER_3(divs, i32, env, i32, i32) DEF_HELPER_3(divu, i32, env, i32, i32) @@ -26,7 +26,7 @@ DEF_HELPER_3(fcmp_gt, i32, env, i32, i32) DEF_HELPER_3(fcmp_ne, i32, env, i32, i32) DEF_HELPER_3(fcmp_ge, i32, env, i32, i32) -DEF_HELPER_FLAGS_2(pcmpbf, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32) +DEF_HELPER_FLAGS_2(pcmpbf, TCG_CALL_NO_RWG_SE, i32, i32, i32) #if !defined(CONFIG_USER_ONLY) DEF_HELPER_2(mmu_read, i32, env, i32) DEF_HELPER_3(mmu_write, void, env, i32, i32) From 95bf787e40adead611f79cae6e8a57cc175df95e Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:09 +0200 Subject: [PATCH 1190/2270] target-mips: rename helper flags Rename helper flags to the new ones. This is purely a mechanical change, it's possible to use better flags by looking at the helpers. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/helper.h | 106 +++++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index f35ed78c16..43ac39ff41 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -23,11 +23,11 @@ DEF_HELPER_4(scd, tl, env, tl, tl, int) #endif #endif -DEF_HELPER_FLAGS_1(clo, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) -DEF_HELPER_FLAGS_1(clz, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) +DEF_HELPER_FLAGS_1(clo, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, tl, tl) #ifdef TARGET_MIPS64 -DEF_HELPER_FLAGS_1(dclo, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) -DEF_HELPER_FLAGS_1(dclz, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) +DEF_HELPER_FLAGS_1(dclo, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(dclz, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_3(dmult, void, env, tl, tl) DEF_HELPER_3(dmultu, void, env, tl, tl) #endif @@ -304,62 +304,62 @@ DEF_HELPER_2(pmon, void, env, int) DEF_HELPER_1(wait, void, env) /* Loongson multimedia functions. */ -DEF_HELPER_FLAGS_2(paddsh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddush, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddsb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddusb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddush, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddsb, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddusb, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubsh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubush, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubsb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubusb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubush, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubsb, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubusb, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psubb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pshufh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(packsswh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(packsshb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(packushb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pshufh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(packsswh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(packsshb, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(packushb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(punpcklhw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(punpckhhw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(punpcklbh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(punpckhbh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(punpcklwd, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(punpckhwd, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(punpcklhw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(punpckhhw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(punpcklbh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(punpckhbh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(punpcklwd, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(punpckhwd, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pavgh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pavgb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pmaxsh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pminsh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pmaxub, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pminub, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pavgh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pavgb, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pmaxsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pminsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pmaxub, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pminub, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pcmpeqw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pcmpgtw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pcmpeqh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pcmpgth, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pcmpeqb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pcmpgtb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pcmpeqw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pcmpgtw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pcmpeqh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pcmpgth, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pcmpeqb, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pcmpgtb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psllw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psllh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psrlw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psrlh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psraw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psrah, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psllw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psllh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psrlw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psrlh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psraw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(psrah, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pmullh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pmulhh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pmulhuh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pmaddhw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pmullh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pmulhh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pmulhuh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(pmaddhw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pasubub, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_1(biadd, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64) -DEF_HELPER_FLAGS_1(pmovmskb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64) +DEF_HELPER_FLAGS_2(pasubub, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_1(biadd, TCG_CALL_NO_RWG_SE, i64, i64) +DEF_HELPER_FLAGS_1(pmovmskb, TCG_CALL_NO_RWG_SE, i64, i64) #include "def-helper.h" From 8f885ef88a3fa26c26e98150219884da607d46ed Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:09 +0200 Subject: [PATCH 1191/2270] target-ppc: rename helper flags Rename helper flags to the new ones. This is purely a mechanical change, it's possible to use better flags by looking at the helpers. Cc: Alexander Graf Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-ppc/helper.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index fd04c063e2..e588370e29 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -31,24 +31,24 @@ DEF_HELPER_2(icbi, void, env, tl) DEF_HELPER_5(lscbx, tl, env, tl, i32, i32, i32) #if defined(TARGET_PPC64) -DEF_HELPER_FLAGS_2(mulhd, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(mulhdu, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) +DEF_HELPER_FLAGS_2(mulhd, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(mulhdu, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_3(mulldo, i64, env, i64, i64) #endif -DEF_HELPER_FLAGS_1(cntlzw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) -DEF_HELPER_FLAGS_1(popcntb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) -DEF_HELPER_FLAGS_1(popcntw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) +DEF_HELPER_FLAGS_1(cntlzw, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(popcntb, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(popcntw, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_3(sraw, tl, env, tl, tl) #if defined(TARGET_PPC64) -DEF_HELPER_FLAGS_1(cntlzd, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) -DEF_HELPER_FLAGS_1(popcntd, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) +DEF_HELPER_FLAGS_1(cntlzd, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(popcntd, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_3(srad, tl, env, tl, tl) #endif -DEF_HELPER_FLAGS_1(cntlsw32, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) -DEF_HELPER_FLAGS_1(cntlzw32, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) -DEF_HELPER_FLAGS_2(brinc, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl) +DEF_HELPER_FLAGS_1(cntlsw32, TCG_CALL_NO_RWG_SE, i32, i32) +DEF_HELPER_FLAGS_1(cntlzw32, TCG_CALL_NO_RWG_SE, i32, i32) +DEF_HELPER_FLAGS_2(brinc, TCG_CALL_NO_RWG_SE, tl, tl, tl) DEF_HELPER_1(float_check_status, void, env) DEF_HELPER_1(reset_fpstatus, void, env) @@ -345,25 +345,25 @@ DEF_HELPER_2(6xx_tlbd, void, env, tl) DEF_HELPER_2(6xx_tlbi, void, env, tl) DEF_HELPER_2(74xx_tlbd, void, env, tl) DEF_HELPER_2(74xx_tlbi, void, env, tl) -DEF_HELPER_FLAGS_1(tlbia, TCG_CALL_CONST, void, env) -DEF_HELPER_FLAGS_2(tlbie, TCG_CALL_CONST, void, env, tl) +DEF_HELPER_FLAGS_1(tlbia, TCG_CALL_NO_RWG, void, env) +DEF_HELPER_FLAGS_2(tlbie, TCG_CALL_NO_RWG, void, env, tl) #if defined(TARGET_PPC64) -DEF_HELPER_FLAGS_3(store_slb, TCG_CALL_CONST, void, env, tl, tl) +DEF_HELPER_FLAGS_3(store_slb, TCG_CALL_NO_RWG, void, env, tl, tl) DEF_HELPER_2(load_slb_esid, tl, env, tl) DEF_HELPER_2(load_slb_vsid, tl, env, tl) -DEF_HELPER_FLAGS_1(slbia, TCG_CALL_CONST, void, env) -DEF_HELPER_FLAGS_2(slbie, TCG_CALL_CONST, void, env, tl) +DEF_HELPER_FLAGS_1(slbia, TCG_CALL_NO_RWG, void, env) +DEF_HELPER_FLAGS_2(slbie, TCG_CALL_NO_RWG, void, env, tl) #endif -DEF_HELPER_FLAGS_2(load_sr, TCG_CALL_CONST, tl, env, tl); -DEF_HELPER_FLAGS_3(store_sr, TCG_CALL_CONST, void, env, tl, tl) +DEF_HELPER_FLAGS_2(load_sr, TCG_CALL_NO_RWG, tl, env, tl); +DEF_HELPER_FLAGS_3(store_sr, TCG_CALL_NO_RWG, void, env, tl, tl) -DEF_HELPER_FLAGS_1(602_mfrom, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) +DEF_HELPER_FLAGS_1(602_mfrom, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_1(msgsnd, void, tl) DEF_HELPER_2(msgclr, void, env, tl) #endif DEF_HELPER_4(dlmzb, tl, env, tl, tl, i32) -DEF_HELPER_FLAGS_2(clcs, TCG_CALL_CONST | TCG_CALL_PURE, tl, env, i32) +DEF_HELPER_FLAGS_2(clcs, TCG_CALL_NO_RWG_SE, tl, env, i32) #if !defined(CONFIG_USER_ONLY) DEF_HELPER_2(rac, tl, env, tl) #endif From 9995567b3ecef5e0edd7d7301b722949320f89be Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:09 +0200 Subject: [PATCH 1192/2270] target-s390x: rename helper flags Rename helper flags to the new ones. This is purely a mechanical change, it's possible to use better flags by looking at the helpers. Cc: Alexander Graf Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-s390x/helper.h | 76 +++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/target-s390x/helper.h b/target-s390x/helper.h index 5419f37dca..ac44eabd53 100644 --- a/target-s390x/helper.h +++ b/target-s390x/helper.h @@ -7,21 +7,21 @@ DEF_HELPER_4(xc, i32, env, i32, i64, i64) DEF_HELPER_4(mvc, void, env, i32, i64, i64) DEF_HELPER_4(clc, i32, env, i32, i64, i64) DEF_HELPER_3(mvcl, i32, env, i32, i32) -DEF_HELPER_FLAGS_1(set_cc_comp_s32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32) -DEF_HELPER_FLAGS_1(set_cc_comp_s64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64) -DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32) +DEF_HELPER_FLAGS_1(set_cc_comp_s32, TCG_CALL_NO_RWG_SE, i32, s32) +DEF_HELPER_FLAGS_1(set_cc_comp_s64, TCG_CALL_NO_RWG_SE, i32, s64) +DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_4(clm, i32, env, i32, i32, i64) DEF_HELPER_4(stcm, void, env, i32, i32, i64) DEF_HELPER_3(mlg, void, env, i32, i64) DEF_HELPER_3(dlg, void, env, i32, i64) -DEF_HELPER_FLAGS_3(set_cc_add64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64) -DEF_HELPER_FLAGS_3(set_cc_addu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64) -DEF_HELPER_FLAGS_3(set_cc_add32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32) -DEF_HELPER_FLAGS_3(set_cc_addu32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32) -DEF_HELPER_FLAGS_3(set_cc_sub64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64) -DEF_HELPER_FLAGS_3(set_cc_subu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64) -DEF_HELPER_FLAGS_3(set_cc_sub32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32) -DEF_HELPER_FLAGS_3(set_cc_subu32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32) +DEF_HELPER_FLAGS_3(set_cc_add64, TCG_CALL_NO_RWG_SE, i32, s64, s64, s64) +DEF_HELPER_FLAGS_3(set_cc_addu64, TCG_CALL_NO_RWG_SE, i32, i64, i64, i64) +DEF_HELPER_FLAGS_3(set_cc_add32, TCG_CALL_NO_RWG_SE, i32, s32, s32, s32) +DEF_HELPER_FLAGS_3(set_cc_addu32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) +DEF_HELPER_FLAGS_3(set_cc_sub64, TCG_CALL_NO_RWG_SE, i32, s64, s64, s64) +DEF_HELPER_FLAGS_3(set_cc_subu64, TCG_CALL_NO_RWG_SE, i32, i64, i64, i64) +DEF_HELPER_FLAGS_3(set_cc_sub32, TCG_CALL_NO_RWG_SE, i32, s32, s32, s32) +DEF_HELPER_FLAGS_3(set_cc_subu32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_4(srst, i32, env, i32, i32, i32) DEF_HELPER_4(clst, i32, env, i32, i32, i32) DEF_HELPER_4(mvpg, void, env, i64, i64, i64) @@ -30,15 +30,15 @@ DEF_HELPER_4(csg, i32, env, i32, i64, i32) DEF_HELPER_4(cdsg, i32, env, i32, i64, i32) DEF_HELPER_4(cs, i32, env, i32, i64, i32) DEF_HELPER_5(ex, i32, env, i32, i64, i64, i64) -DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32) -DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_PURE|TCG_CALL_CONST, s32, s32) -DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_PURE|TCG_CALL_CONST, i64, s64) -DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_PURE|TCG_CALL_CONST, s64, s64) +DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_NO_RWG_SE, i32, s32) +DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_NO_RWG_SE, s32, s32) +DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_NO_RWG_SE, i64, s64) +DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_NO_RWG_SE, s64, s64) DEF_HELPER_4(stcmh, void, env, i32, i64, i32) DEF_HELPER_4(icmh, i32, env, i32, i64, i32) DEF_HELPER_3(ipm, void, env, i32, i32) -DEF_HELPER_FLAGS_3(addc_u32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32) -DEF_HELPER_FLAGS_3(set_cc_addc_u64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64) +DEF_HELPER_FLAGS_3(addc_u32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) +DEF_HELPER_FLAGS_3(set_cc_addc_u64, TCG_CALL_NO_RWG_SE, i32, i64, i64, i64) DEF_HELPER_4(stam, void, env, i32, i64, i32) DEF_HELPER_4(lam, void, env, i32, i64, i32) DEF_HELPER_4(mvcle, i32, env, i32, i64, i32) @@ -82,9 +82,9 @@ DEF_HELPER_3(seb, void, env, i32, i32) DEF_HELPER_3(sdb, i32, env, i32, i64) DEF_HELPER_3(mdb, void, env, i32, i64) DEF_HELPER_3(ddb, void, env, i32, i64) -DEF_HELPER_FLAGS_3(cebr, TCG_CALL_PURE, i32, env, i32, i32) -DEF_HELPER_FLAGS_3(cdbr, TCG_CALL_PURE, i32, env, i32, i32) -DEF_HELPER_FLAGS_3(cxbr, TCG_CALL_PURE, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(cebr, TCG_CALL_NO_SE, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(cdbr, TCG_CALL_NO_SE, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(cxbr, TCG_CALL_NO_SE, i32, env, i32, i32) DEF_HELPER_4(cgebr, i32, env, i32, i32, i32) DEF_HELPER_4(cgdbr, i32, env, i32, i32, i32) DEF_HELPER_4(cgxbr, i32, env, i32, i32, i32) @@ -104,12 +104,12 @@ DEF_HELPER_4(madbr, void, env, i32, i32, i32) DEF_HELPER_4(msdbr, void, env, i32, i32, i32) DEF_HELPER_3(ldeb, void, env, i32, i64) DEF_HELPER_3(lxdb, void, env, i32, i64) -DEF_HELPER_FLAGS_3(tceb, TCG_CALL_PURE, i32, env, i32, i64) -DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_PURE, i32, env, i32, i64) -DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE, i32, env, i32, i64) +DEF_HELPER_FLAGS_3(tceb, TCG_CALL_NO_SE, i32, env, i32, i64) +DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_NO_SE, i32, env, i32, i64) +DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_NO_SE, i32, env, i32, i64) DEF_HELPER_3(flogr, i32, env, i32, i64) DEF_HELPER_3(sqdbr, void, env, i32, i32) -DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32) +DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32) DEF_HELPER_4(unpk, void, env, i32, i64, i64) DEF_HELPER_4(tr, void, env, i32, i64, i64) @@ -117,36 +117,36 @@ DEF_HELPER_3(servc, i32, env, i32, i64) DEF_HELPER_4(diag, i64, env, i32, i64, i64) DEF_HELPER_3(load_psw, void, env, i64, i64) DEF_HELPER_1(program_interrupt, void, i32) -DEF_HELPER_FLAGS_2(stidp, TCG_CALL_CONST, void, env, i64) -DEF_HELPER_FLAGS_2(spx, TCG_CALL_CONST, void, env, i64) -DEF_HELPER_FLAGS_1(sck, TCG_CALL_CONST, i32, i64) +DEF_HELPER_FLAGS_2(stidp, TCG_CALL_NO_RWG, void, env, i64) +DEF_HELPER_FLAGS_2(spx, TCG_CALL_NO_RWG, void, env, i64) +DEF_HELPER_FLAGS_1(sck, TCG_CALL_NO_RWG, i32, i64) DEF_HELPER_2(stck, i32, env, i64) DEF_HELPER_2(stcke, i32, env, i64) -DEF_HELPER_FLAGS_2(sckc, TCG_CALL_CONST, void, env, i64) -DEF_HELPER_FLAGS_2(stckc, TCG_CALL_CONST, void, env, i64) -DEF_HELPER_FLAGS_2(spt, TCG_CALL_CONST, void, env, i64) -DEF_HELPER_FLAGS_2(stpt, TCG_CALL_CONST, void, env, i64) +DEF_HELPER_FLAGS_2(sckc, TCG_CALL_NO_RWG, void, env, i64) +DEF_HELPER_FLAGS_2(stckc, TCG_CALL_NO_RWG, void, env, i64) +DEF_HELPER_FLAGS_2(spt, TCG_CALL_NO_RWG, void, env, i64) +DEF_HELPER_FLAGS_2(stpt, TCG_CALL_NO_RWG, void, env, i64) DEF_HELPER_4(stsi, i32, env, i64, i32, i32) DEF_HELPER_4(lctl, void, env, i32, i64, i32) DEF_HELPER_4(lctlg, void, env, i32, i64, i32) DEF_HELPER_4(stctl, void, env, i32, i64, i32) DEF_HELPER_4(stctg, void, env, i32, i64, i32) -DEF_HELPER_FLAGS_2(tprot, TCG_CALL_CONST, i32, i64, i64) -DEF_HELPER_FLAGS_2(iske, TCG_CALL_PURE|TCG_CALL_CONST, i64, env, i64) -DEF_HELPER_FLAGS_3(sske, TCG_CALL_CONST, void, env, i32, i64) -DEF_HELPER_FLAGS_3(rrbe, TCG_CALL_CONST, i32, env, i32, i64) +DEF_HELPER_FLAGS_2(tprot, TCG_CALL_NO_RWG, i32, i64, i64) +DEF_HELPER_FLAGS_2(iske, TCG_CALL_NO_RWG_SE, i64, env, i64) +DEF_HELPER_FLAGS_3(sske, TCG_CALL_NO_RWG, void, env, i32, i64) +DEF_HELPER_FLAGS_3(rrbe, TCG_CALL_NO_RWG, i32, env, i32, i64) DEF_HELPER_3(csp, i32, env, i32, i32) DEF_HELPER_4(mvcs, i32, env, i64, i64, i64) DEF_HELPER_4(mvcp, i32, env, i64, i64, i64) DEF_HELPER_4(sigp, i32, env, i64, i32, i64) DEF_HELPER_2(sacf, void, env, i64) -DEF_HELPER_FLAGS_3(ipte, TCG_CALL_CONST, void, env, i64, i64) -DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_CONST, void, env) +DEF_HELPER_FLAGS_3(ipte, TCG_CALL_NO_RWG, void, env, i64, i64) +DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env) DEF_HELPER_3(lra, i32, env, i64, i32) DEF_HELPER_3(stura, void, env, i64, i32) DEF_HELPER_3(cksm, void, env, i32, i32) -DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST, +DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64) #include "def-helper.h" From 76ab687946b31c8ca5308bed1d85391f4f5c599c Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:09 +0200 Subject: [PATCH 1193/2270] target-sh4: rename helper flags Rename helper flags to the new ones. This is purely a mechanical change, it's possible to use better flags by looking at the helpers. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-sh4/helper.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target-sh4/helper.h b/target-sh4/helper.h index 6c1a47da9f..304b77ba3f 100644 --- a/target-sh4/helper.h +++ b/target-sh4/helper.h @@ -19,8 +19,8 @@ DEF_HELPER_3(macw, void, env, i32, i32) DEF_HELPER_2(ld_fpscr, void, env, i32) -DEF_HELPER_FLAGS_1(fabs_FT, TCG_CALL_CONST | TCG_CALL_PURE, f32, f32) -DEF_HELPER_FLAGS_1(fabs_DT, TCG_CALL_CONST | TCG_CALL_PURE, f64, f64) +DEF_HELPER_FLAGS_1(fabs_FT, TCG_CALL_NO_RWG_SE, f32, f32) +DEF_HELPER_FLAGS_1(fabs_DT, TCG_CALL_NO_RWG_SE, f64, f64) DEF_HELPER_3(fadd_FT, f32, env, f32, f32) DEF_HELPER_3(fadd_DT, f64, env, f64, f64) DEF_HELPER_2(fcnvsd_FT_DT, f64, env, f32) @@ -37,7 +37,7 @@ DEF_HELPER_2(float_DT, f64, env, i32) DEF_HELPER_4(fmac_FT, f32, env, f32, f32, f32) DEF_HELPER_3(fmul_FT, f32, env, f32, f32) DEF_HELPER_3(fmul_DT, f64, env, f64, f64) -DEF_HELPER_FLAGS_1(fneg_T, TCG_CALL_CONST | TCG_CALL_PURE, f32, f32) +DEF_HELPER_FLAGS_1(fneg_T, TCG_CALL_NO_RWG_SE, f32, f32) DEF_HELPER_3(fsub_FT, f32, env, f32, f32) DEF_HELPER_3(fsub_DT, f64, env, f64, f64) DEF_HELPER_2(fsqrt_FT, f32, env, f32) From c33b235358a4c385abe36b3082ee9437bc86c2f5 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:09 +0200 Subject: [PATCH 1194/2270] target-sparc: rename helper flags Rename helper flags to the new ones. This is purely a mechanical change, it's possible to use better flags by looking at the helpers. Acked-by: Blue Swirl Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-sparc/helper.h | 50 +++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/target-sparc/helper.h b/target-sparc/helper.h index e1ae3c7086..098c482216 100644 --- a/target-sparc/helper.h +++ b/target-sparc/helper.h @@ -16,7 +16,7 @@ DEF_HELPER_1(rdccr, tl, env) DEF_HELPER_2(wrccr, void, env, tl) DEF_HELPER_1(rdcwp, tl, env) DEF_HELPER_2(wrcwp, void, env, tl) -DEF_HELPER_FLAGS_2(array8, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl) +DEF_HELPER_FLAGS_2(array8, TCG_CALL_NO_RWG_SE, tl, tl, tl) DEF_HELPER_1(popc, tl, tl) DEF_HELPER_4(ldda_asi, void, env, tl, int, int) DEF_HELPER_5(ldf_asi, void, env, tl, int, int, int) @@ -51,7 +51,7 @@ DEF_HELPER_5(ld_asi, i64, env, tl, int, int, int) DEF_HELPER_5(st_asi, void, env, tl, i64, int, int) #endif DEF_HELPER_2(ldfsr, void, env, i32) -DEF_HELPER_FLAGS_1(fabss, TCG_CALL_CONST | TCG_CALL_PURE, f32, f32) +DEF_HELPER_FLAGS_1(fabss, TCG_CALL_NO_RWG_SE, f32, f32) DEF_HELPER_2(fsqrts, f32, env, f32) DEF_HELPER_2(fsqrtd, f64, env, f64) DEF_HELPER_3(fcmps, void, env, f32, f32) @@ -63,7 +63,7 @@ DEF_HELPER_1(fcmpq, void, env) DEF_HELPER_1(fcmpeq, void, env) #ifdef TARGET_SPARC64 DEF_HELPER_2(ldxfsr, void, env, i64) -DEF_HELPER_FLAGS_1(fabsd, TCG_CALL_CONST | TCG_CALL_PURE, f64, f64) +DEF_HELPER_FLAGS_1(fabsd, TCG_CALL_NO_RWG_SE, f64, f64) DEF_HELPER_3(fcmps_fcc1, void, env, f32, f32) DEF_HELPER_3(fcmps_fcc2, void, env, f32, f32) DEF_HELPER_3(fcmps_fcc3, void, env, f32, f32) @@ -104,14 +104,14 @@ DEF_HELPER_3(fdivs, f32, env, f32, f32) DEF_HELPER_3(fsmuld, f64, env, f32, f32) DEF_HELPER_3(fdmulq, void, env, f64, f64); -DEF_HELPER_FLAGS_1(fnegs, TCG_CALL_CONST | TCG_CALL_PURE, f32, f32) +DEF_HELPER_FLAGS_1(fnegs, TCG_CALL_NO_RWG_SE, f32, f32) DEF_HELPER_2(fitod, f64, env, s32) DEF_HELPER_2(fitoq, void, env, s32) DEF_HELPER_2(fitos, f32, env, s32) #ifdef TARGET_SPARC64 -DEF_HELPER_FLAGS_1(fnegd, TCG_CALL_CONST | TCG_CALL_PURE, f64, f64) +DEF_HELPER_FLAGS_1(fnegd, TCG_CALL_NO_RWG_SE, f64, f64) DEF_HELPER_1(fnegq, void, env) DEF_HELPER_2(fxtos, f32, env, s64) DEF_HELPER_2(fxtod, f64, env, s64) @@ -131,36 +131,36 @@ DEF_HELPER_2(fstox, s64, env, f32) DEF_HELPER_2(fdtox, s64, env, f64) DEF_HELPER_1(fqtox, s64, env) -DEF_HELPER_FLAGS_2(fpmerge, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(fmul8x16, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(fmul8x16al, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(fmul8x16au, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(fmul8sux16, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(fmul8ulx16, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(fmuld8sux16, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(fmuld8ulx16, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_2(fexpand, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64) -DEF_HELPER_FLAGS_3(pdist, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64, i64) -DEF_HELPER_FLAGS_2(fpack16, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64, i64) -DEF_HELPER_FLAGS_3(fpack32, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64, i64) -DEF_HELPER_FLAGS_2(fpackfix, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64, i64) -DEF_HELPER_FLAGS_3(bshuffle, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64, i64) +DEF_HELPER_FLAGS_2(fpmerge, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(fmul8x16, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(fmul8x16al, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(fmul8x16au, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(fmul8sux16, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(fmul8ulx16, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(fmuld8sux16, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(fmuld8ulx16, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(fexpand, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_3(pdist, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64) +DEF_HELPER_FLAGS_2(fpack16, TCG_CALL_NO_RWG_SE, i32, i64, i64) +DEF_HELPER_FLAGS_3(fpack32, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64) +DEF_HELPER_FLAGS_2(fpackfix, TCG_CALL_NO_RWG_SE, i32, i64, i64) +DEF_HELPER_FLAGS_3(bshuffle, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64) #define VIS_HELPER(name) \ - DEF_HELPER_FLAGS_2(f ## name ## 16, TCG_CALL_CONST | TCG_CALL_PURE, \ + DEF_HELPER_FLAGS_2(f ## name ## 16, TCG_CALL_NO_RWG_SE, \ i64, i64, i64) \ - DEF_HELPER_FLAGS_2(f ## name ## 16s, TCG_CALL_CONST | TCG_CALL_PURE, \ + DEF_HELPER_FLAGS_2(f ## name ## 16s, TCG_CALL_NO_RWG_SE, \ i32, i32, i32) \ - DEF_HELPER_FLAGS_2(f ## name ## 32, TCG_CALL_CONST | TCG_CALL_PURE, \ + DEF_HELPER_FLAGS_2(f ## name ## 32, TCG_CALL_NO_RWG_SE, \ i64, i64, i64) \ - DEF_HELPER_FLAGS_2(f ## name ## 32s, TCG_CALL_CONST | TCG_CALL_PURE, \ + DEF_HELPER_FLAGS_2(f ## name ## 32s, TCG_CALL_NO_RWG_SE, \ i32, i32, i32) VIS_HELPER(padd); VIS_HELPER(psub); #define VIS_CMPHELPER(name) \ - DEF_HELPER_FLAGS_2(f##name##16, TCG_CALL_CONST | TCG_CALL_PURE, \ + DEF_HELPER_FLAGS_2(f##name##16, TCG_CALL_NO_RWG_SE, \ i64, i64, i64) \ - DEF_HELPER_FLAGS_2(f##name##32, TCG_CALL_CONST | TCG_CALL_PURE, \ + DEF_HELPER_FLAGS_2(f##name##32, TCG_CALL_NO_RWG_SE, \ i64, i64, i64) VIS_CMPHELPER(cmpgt); VIS_CMPHELPER(cmpeq); From f0de41325a195503d352d8e154c1015290f4c87c Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:09 +0200 Subject: [PATCH 1195/2270] target-xtensa: rename helper flags Rename helper flags to the new ones. This is purely a mechanical change, it's possible to use better flags by looking at the helpers. Cc: Max Filippov Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-xtensa/helper.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/target-xtensa/helper.h b/target-xtensa/helper.h index 4cc0088c36..1163c09836 100644 --- a/target-xtensa/helper.h +++ b/target-xtensa/helper.h @@ -5,8 +5,8 @@ DEF_HELPER_3(exception_cause, noreturn, env, i32, i32) DEF_HELPER_4(exception_cause_vaddr, noreturn, env, i32, i32, i32) DEF_HELPER_3(debug_exception, noreturn, env, i32, i32) -DEF_HELPER_FLAGS_1(nsa, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) -DEF_HELPER_FLAGS_1(nsau, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) +DEF_HELPER_FLAGS_1(nsa, TCG_CALL_NO_RWG_SE, i32, i32) +DEF_HELPER_FLAGS_1(nsau, TCG_CALL_NO_RWG_SE, i32, i32) DEF_HELPER_2(wsr_windowbase, void, env, i32) DEF_HELPER_4(entry, void, env, i32, i32, i32) DEF_HELPER_2(retw, i32, env, i32) @@ -25,8 +25,8 @@ DEF_HELPER_2(advance_ccount, void, env, i32) DEF_HELPER_1(check_interrupts, void, env) DEF_HELPER_2(wsr_rasid, void, env, i32) -DEF_HELPER_FLAGS_3(rtlb0, TCG_CALL_CONST | TCG_CALL_PURE, i32, env, i32, i32) -DEF_HELPER_FLAGS_3(rtlb1, TCG_CALL_CONST | TCG_CALL_PURE, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(rtlb0, TCG_CALL_NO_RWG_SE, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(rtlb1, TCG_CALL_NO_RWG_SE, i32, env, i32, i32) DEF_HELPER_3(itlb, void, env, i32, i32) DEF_HELPER_3(ptlb, i32, env, i32, i32) DEF_HELPER_4(wtlb, void, env, i32, i32, i32) @@ -37,15 +37,15 @@ DEF_HELPER_3(wsr_dbreaka, void, env, i32, i32) DEF_HELPER_3(wsr_dbreakc, void, env, i32, i32) DEF_HELPER_2(wur_fcr, void, env, i32) -DEF_HELPER_FLAGS_1(abs_s, TCG_CALL_CONST | TCG_CALL_PURE, f32, f32) -DEF_HELPER_FLAGS_1(neg_s, TCG_CALL_CONST | TCG_CALL_PURE, f32, f32) +DEF_HELPER_FLAGS_1(abs_s, TCG_CALL_NO_RWG_SE, f32, f32) +DEF_HELPER_FLAGS_1(neg_s, TCG_CALL_NO_RWG_SE, f32, f32) DEF_HELPER_3(add_s, f32, env, f32, f32) DEF_HELPER_3(sub_s, f32, env, f32, f32) DEF_HELPER_3(mul_s, f32, env, f32, f32) DEF_HELPER_4(madd_s, f32, env, f32, f32, f32) DEF_HELPER_4(msub_s, f32, env, f32, f32, f32) -DEF_HELPER_FLAGS_3(ftoi, TCG_CALL_CONST | TCG_CALL_PURE, i32, f32, i32, i32) -DEF_HELPER_FLAGS_3(ftoui, TCG_CALL_CONST | TCG_CALL_PURE, i32, f32, i32, i32) +DEF_HELPER_FLAGS_3(ftoi, TCG_CALL_NO_RWG_SE, i32, f32, i32, i32) +DEF_HELPER_FLAGS_3(ftoui, TCG_CALL_NO_RWG_SE, i32, f32, i32, i32) DEF_HELPER_3(itof, f32, env, i32, i32) DEF_HELPER_3(uitof, f32, env, i32, i32) From b393ab4228adc9338c17340d825f7a60e5f6820d Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:09 +0200 Subject: [PATCH 1196/2270] tcg: remove compatiblity call flags Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/tcg.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tcg/tcg.h b/tcg/tcg.h index 96b62229c2..a6c9256f8b 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -268,10 +268,6 @@ typedef int TCGv_i64; #define TCG_CALL_NO_RWG_SE (TCG_CALL_NO_RWG | TCG_CALL_NO_SE) #define TCG_CALL_NO_WG_SE (TCG_CALL_NO_WG | TCG_CALL_NO_SE) -/* compatibility call flags, they should be eventually be removed */ -#define TCG_CALL_PURE TCG_CALL_NO_SIDE_EFFECTS -#define TCG_CALL_CONST TCG_CALL_NO_READ_GLOBALS - /* used to align parameters */ #define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-1) #define TCG_CALL_DUMMY_ARG ((TCGArg)(-1)) From d73ee8a2b5267adae41ecb464cae06a185d2b0f9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 9 Oct 2012 21:53:19 +0200 Subject: [PATCH 1197/2270] target-mips: Use TCG registers for the FPU. With normal FP, this doesn't have much affect on the generated code, because most of the FP operations are not CONST/PURE, and so we spill registers in about the same frequency as the explicit load/stores. But with Loongson multimedia instructions, which are all integral and whose helpers are in fact CONST+PURE, this greatly improves the code. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 96 +++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 42 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 454e5cc818..ed55e260ac 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -575,6 +575,7 @@ static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC]; static TCGv cpu_dspctrl, btarget, bcond; static TCGv_i32 hflags; static TCGv_i32 fpu_fcr0, fpu_fcr31; +static TCGv_i64 fpu_f64[32]; static uint32_t gen_opc_hflags[OPC_BUF_SIZE]; @@ -642,26 +643,31 @@ enum { BS_EXCP = 3, /* We reached an exception condition */ }; -static const char *regnames[] = - { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", - "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", - "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", - "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", }; +static const char * const regnames[] = { + "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", +}; -static const char *regnames_HI[] = - { "HI0", "HI1", "HI2", "HI3", }; +static const char * const regnames_HI[] = { + "HI0", "HI1", "HI2", "HI3", +}; -static const char *regnames_LO[] = - { "LO0", "LO1", "LO2", "LO3", }; +static const char * const regnames_LO[] = { + "LO0", "LO1", "LO2", "LO3", +}; -static const char *regnames_ACX[] = - { "ACX0", "ACX1", "ACX2", "ACX3", }; +static const char * const regnames_ACX[] = { + "ACX0", "ACX1", "ACX2", "ACX3", +}; -static const char *fregnames[] = - { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", - "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", - "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", - "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", }; +static const char * const fregnames[] = { + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", +}; #define MIPS_DEBUG(fmt, ...) \ do { \ @@ -758,54 +764,54 @@ static inline void gen_store_srsgpr (int from, int to) } /* Floating point register moves. */ -static inline void gen_load_fpr32 (TCGv_i32 t, int reg) +static void gen_load_fpr32(TCGv_i32 t, int reg) { - tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX])); + tcg_gen_trunc_i64_i32(t, fpu_f64[reg]); } -static inline void gen_store_fpr32 (TCGv_i32 t, int reg) +static void gen_store_fpr32(TCGv_i32 t, int reg) { - tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX])); + TCGv_i64 t64 = tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(t64, t); + tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32); + tcg_temp_free_i64(t64); } -static inline void gen_load_fpr32h (TCGv_i32 t, int reg) +static void gen_load_fpr32h(TCGv_i32 t, int reg) { - tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX])); + TCGv_i64 t64 = tcg_temp_new_i64(); + tcg_gen_shri_i64(t64, fpu_f64[reg], 32); + tcg_gen_trunc_i64_i32(t, t64); + tcg_temp_free_i64(t64); } -static inline void gen_store_fpr32h (TCGv_i32 t, int reg) +static void gen_store_fpr32h(TCGv_i32 t, int reg) { - tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX])); + TCGv_i64 t64 = tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(t64, t); + tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32); + tcg_temp_free_i64(t64); } -static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg) +static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg) { if (ctx->hflags & MIPS_HFLAG_F64) { - tcg_gen_ld_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d)); + tcg_gen_mov_i64(t, fpu_f64[reg]); } else { - TCGv_i32 t0 = tcg_temp_new_i32(); - TCGv_i32 t1 = tcg_temp_new_i32(); - gen_load_fpr32(t0, reg & ~1); - gen_load_fpr32(t1, reg | 1); - tcg_gen_concat_i32_i64(t, t0, t1); - tcg_temp_free_i32(t0); - tcg_temp_free_i32(t1); + tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]); } } -static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg) +static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg) { if (ctx->hflags & MIPS_HFLAG_F64) { - tcg_gen_st_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d)); + tcg_gen_mov_i64(fpu_f64[reg], t); } else { - TCGv_i64 t0 = tcg_temp_new_i64(); - TCGv_i32 t1 = tcg_temp_new_i32(); - tcg_gen_trunc_i64_i32(t1, t); - gen_store_fpr32(t1, reg & ~1); + TCGv_i64 t0; + tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32); + t0 = tcg_temp_new_i64(); tcg_gen_shri_i64(t0, t, 32); - tcg_gen_trunc_i64_i32(t1, t0); - gen_store_fpr32(t1, reg | 1); - tcg_temp_free_i32(t1); + tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32); tcg_temp_free_i64(t0); } } @@ -13073,6 +13079,12 @@ static void mips_tcg_init(void) cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0, offsetof(CPUMIPSState, active_tc.gpr[i]), regnames[i]); + + for (i = 0; i < 32; i++) { + int off = offsetof(CPUMIPSState, active_fpu.fpr[i]); + fpu_f64[i] = tcg_global_mem_new_i64(TCG_AREG0, off, fregnames[i]); + } + cpu_PC = tcg_global_mem_new(TCG_AREG0, offsetof(CPUMIPSState, active_tc.PC), "PC"); for (i = 0; i < MIPS_DSP_ACC; i++) { From 44b37ace0636cd229e956c5000a1bb6a49e274e7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Oct 2012 12:11:07 +1000 Subject: [PATCH 1198/2270] tcg-i386: Use %gs prefixes for x86_64 GUEST_BASE When we allocate a reserved_va for the guest, the kernel will likely choose an address well above 4G. At which point we must use a pair of movabsq+addq to form the host address. If we have OS support, set up a segment register to point to guest_base instead. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/i386/tcg-target.c | 149 +++++++++++++++++++++++++++--------------- 1 file changed, 95 insertions(+), 54 deletions(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 9c8f69ae6b..e45a5a0426 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -232,11 +232,13 @@ static inline int tcg_target_const_match(tcg_target_long val, # define P_REXW 0x800 /* Set REX.W = 1 */ # define P_REXB_R 0x1000 /* REG field as byte register */ # define P_REXB_RM 0x2000 /* R/M field as byte register */ +# define P_GS 0x4000 /* gs segment override */ #else # define P_ADDR32 0 # define P_REXW 0 # define P_REXB_R 0 # define P_REXB_RM 0 +# define P_GS 0 #endif #define OPC_ARITH_EvIz (0x81) @@ -352,6 +354,9 @@ static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x) { int rex; + if (opc & P_GS) { + tcg_out8(s, 0x65); + } if (opc & P_DATA16) { /* We should never be asking for both 16 and 64-bit operation. */ assert((opc & P_REXW) == 0); @@ -1076,10 +1081,27 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx, tcg_out_modrm_offset(s, OPC_ADD_GvEv + P_REXW, r1, r0, offsetof(CPUTLBEntry, addend) - which); } -#endif +#elif defined(__x86_64__) && defined(__linux__) +# include +# include + +int arch_prctl(int code, unsigned long addr); + +static int guest_base_flags; +static inline void setup_guest_base_seg(void) +{ + if (arch_prctl(ARCH_SET_GS, GUEST_BASE) == 0) { + guest_base_flags = P_GS; + } +} +#else +# define guest_base_flags 0 +static inline void setup_guest_base_seg(void) { } +#endif /* SOFTMMU */ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi, - int base, tcg_target_long ofs, int sizeop) + int base, tcg_target_long ofs, int seg, + int sizeop) { #ifdef TARGET_WORDS_BIGENDIAN const int bswap = 1; @@ -1088,28 +1110,29 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi, #endif switch (sizeop) { case 0: - tcg_out_modrm_offset(s, OPC_MOVZBL, datalo, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVZBL + seg, datalo, base, ofs); break; case 0 | 4: - tcg_out_modrm_offset(s, OPC_MOVSBL + P_REXW, datalo, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVSBL + P_REXW + seg, datalo, base, ofs); break; case 1: - tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVZWL + seg, datalo, base, ofs); if (bswap) { tcg_out_rolw_8(s, datalo); } break; case 1 | 4: if (bswap) { - tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVZWL + seg, datalo, base, ofs); tcg_out_rolw_8(s, datalo); tcg_out_modrm(s, OPC_MOVSWL + P_REXW, datalo, datalo); } else { - tcg_out_modrm_offset(s, OPC_MOVSWL + P_REXW, datalo, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVSWL + P_REXW + seg, + datalo, base, ofs); } break; case 2: - tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg, datalo, base, ofs); if (bswap) { tcg_out_bswap32(s, datalo); } @@ -1117,17 +1140,18 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi, #if TCG_TARGET_REG_BITS == 64 case 2 | 4: if (bswap) { - tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg, datalo, base, ofs); tcg_out_bswap32(s, datalo); tcg_out_ext32s(s, datalo, datalo); } else { - tcg_out_modrm_offset(s, OPC_MOVSLQ, datalo, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVSLQ + seg, datalo, base, ofs); } break; #endif case 3: if (TCG_TARGET_REG_BITS == 64) { - tcg_out_ld(s, TCG_TYPE_I64, datalo, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVL_GvEv + P_REXW + seg, + datalo, base, ofs); if (bswap) { tcg_out_bswap64(s, datalo); } @@ -1138,11 +1162,15 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi, datahi = t; } if (base != datalo) { - tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs); - tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4); + tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg, + datalo, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg, + datahi, base, ofs + 4); } else { - tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4); - tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg, + datahi, base, ofs + 4); + tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg, + datalo, base, ofs); } if (bswap) { tcg_out_bswap32(s, datalo); @@ -1186,7 +1214,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, label_ptr, offsetof(CPUTLBEntry, addr_read)); /* TLB Hit. */ - tcg_out_qemu_ld_direct(s, data_reg, data_reg2, TCG_REG_L1, 0, opc); + tcg_out_qemu_ld_direct(s, data_reg, data_reg2, TCG_REG_L1, 0, 0, opc); /* jmp label2 */ tcg_out8(s, OPC_JMP_short); @@ -1273,29 +1301,31 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, { int32_t offset = GUEST_BASE; int base = args[addrlo_idx]; + int seg = 0; - if (TCG_TARGET_REG_BITS == 64) { - /* ??? We assume all operations have left us with register - contents that are zero extended. So far this appears to - be true. If we want to enforce this, we can either do - an explicit zero-extension here, or (if GUEST_BASE == 0) - use the ADDR32 prefix. For now, do nothing. */ - - if (offset != GUEST_BASE) { - tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L1, GUEST_BASE); - tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L1, base); - base = TCG_REG_L1; - offset = 0; - } + /* ??? We assume all operations have left us with register contents + that are zero extended. So far this appears to be true. If we + want to enforce this, we can either do an explicit zero-extension + here, or (if GUEST_BASE == 0, or a segment register is in use) + use the ADDR32 prefix. For now, do nothing. */ + if (GUEST_BASE && guest_base_flags) { + seg = guest_base_flags; + offset = 0; + } else if (TCG_TARGET_REG_BITS == 64 && offset != GUEST_BASE) { + tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L1, GUEST_BASE); + tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L1, base); + base = TCG_REG_L1; + offset = 0; } - tcg_out_qemu_ld_direct(s, data_reg, data_reg2, base, offset, opc); + tcg_out_qemu_ld_direct(s, data_reg, data_reg2, base, offset, seg, opc); } #endif } static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi, - int base, tcg_target_long ofs, int sizeop) + int base, tcg_target_long ofs, int seg, + int sizeop) { #ifdef TARGET_WORDS_BIGENDIAN const int bswap = 1; @@ -1310,7 +1340,8 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi, switch (sizeop) { case 0: - tcg_out_modrm_offset(s, OPC_MOVB_EvGv + P_REXB_R, datalo, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVB_EvGv + P_REXB_R + seg, + datalo, base, ofs); break; case 1: if (bswap) { @@ -1318,7 +1349,8 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi, tcg_out_rolw_8(s, scratch); datalo = scratch; } - tcg_out_modrm_offset(s, OPC_MOVL_EvGv + P_DATA16, datalo, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVL_EvGv + P_DATA16 + seg, + datalo, base, ofs); break; case 2: if (bswap) { @@ -1326,7 +1358,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi, tcg_out_bswap32(s, scratch); datalo = scratch; } - tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, datalo, base, ofs); break; case 3: if (TCG_TARGET_REG_BITS == 64) { @@ -1335,17 +1367,18 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi, tcg_out_bswap64(s, scratch); datalo = scratch; } - tcg_out_st(s, TCG_TYPE_I64, datalo, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVL_EvGv + P_REXW + seg, + datalo, base, ofs); } else if (bswap) { tcg_out_mov(s, TCG_TYPE_I32, scratch, datahi); tcg_out_bswap32(s, scratch); - tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, scratch, base, ofs); tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo); tcg_out_bswap32(s, scratch); - tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs + 4); + tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, scratch, base, ofs+4); } else { - tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs); - tcg_out_st(s, TCG_TYPE_I32, datahi, base, ofs + 4); + tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, datalo, base, ofs); + tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, datahi, base, ofs+4); } break; default: @@ -1379,7 +1412,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, label_ptr, offsetof(CPUTLBEntry, addr_write)); /* TLB Hit. */ - tcg_out_qemu_st_direct(s, data_reg, data_reg2, TCG_REG_L1, 0, opc); + tcg_out_qemu_st_direct(s, data_reg, data_reg2, TCG_REG_L1, 0, 0, opc); /* jmp label2 */ tcg_out8(s, OPC_JMP_short); @@ -1436,23 +1469,24 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, { int32_t offset = GUEST_BASE; int base = args[addrlo_idx]; + int seg = 0; - if (TCG_TARGET_REG_BITS == 64) { - /* ??? We assume all operations have left us with register - contents that are zero extended. So far this appears to - be true. If we want to enforce this, we can either do - an explicit zero-extension here, or (if GUEST_BASE == 0) - use the ADDR32 prefix. For now, do nothing. */ - - if (offset != GUEST_BASE) { - tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L1, GUEST_BASE); - tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L1, base); - base = TCG_REG_L1; - offset = 0; - } + /* ??? We assume all operations have left us with register contents + that are zero extended. So far this appears to be true. If we + want to enforce this, we can either do an explicit zero-extension + here, or (if GUEST_BASE == 0, or a segment register is in use) + use the ADDR32 prefix. For now, do nothing. */ + if (GUEST_BASE && guest_base_flags) { + seg = guest_base_flags; + offset = 0; + } else if (TCG_TARGET_REG_BITS == 64 && offset != GUEST_BASE) { + tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L1, GUEST_BASE); + tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L1, base); + base = TCG_REG_L1; + offset = 0; } - tcg_out_qemu_st_direct(s, data_reg, data_reg2, base, offset, opc); + tcg_out_qemu_st_direct(s, data_reg, data_reg2, base, offset, seg, opc); } #endif } @@ -2046,6 +2080,13 @@ static void tcg_target_qemu_prologue(TCGContext *s) tcg_out_pop(s, tcg_target_callee_save_regs[i]); } tcg_out_opc(s, OPC_RET, 0, 0, 0); + +#if !defined(CONFIG_SOFTMMU) + /* Try to set up a segment register to point to GUEST_BASE. */ + if (GUEST_BASE) { + setup_guest_base_seg(); + } +#endif } static void tcg_target_init(TCGContext *s) From 1e9737da4aafb54681203931dfe8f8eea21fcef7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 23 Oct 2012 07:33:00 +1000 Subject: [PATCH 1199/2270] qemu-timer: Check for usable fields for SIGEV_THREAD_ID Older glibc (RHEL 5.x, Debian 5.x) does not have the _sigev_un._tid member in its structure definition, while the accompanying kernel headers do define SIGEV_THREAD_ID. We need configure to check for both before using it. Signed-off-by: Richard Henderson Signed-off-by: Aurelien Jarno --- configure | 22 ++++++++++++++++++++++ qemu-timer.c | 4 ++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 37f712d475..3685020ffa 100755 --- a/configure +++ b/configure @@ -2812,6 +2812,24 @@ if compile_prog "" "" ; then posix_madvise=yes fi +########################################## +# check if we have usable SIGEV_THREAD_ID + +sigev_thread_id=no +cat > $TMPC << EOF +#include +int main(void) { + struct sigevent ev; + ev.sigev_notify = SIGEV_THREAD_ID; + ev._sigev_un._tid = 0; + asm volatile("" : : "g"(&ev)); + return 0; +} +EOF +if compile_prog "" "" ; then + sigev_thread_id=yes +fi + ########################################## # check if trace backend exists @@ -3159,6 +3177,7 @@ echo "preadv support $preadv" echo "fdatasync $fdatasync" echo "madvise $madvise" echo "posix_madvise $posix_madvise" +echo "sigev_thread_id $sigev_thread_id" echo "uuid support $uuid" echo "libcap-ng support $cap_ng" echo "vhost-net support $vhost_net" @@ -3443,6 +3462,9 @@ fi if test "$posix_madvise" = "yes" ; then echo "CONFIG_POSIX_MADVISE=y" >> $config_host_mak fi +if test "$sigev_thread_id" = "yes" ; then + echo "CONFIG_SIGEV_THREAD_ID=y" >> $config_host_mak +fi if test "$spice" = "yes" ; then echo "CONFIG_SPICE=y" >> $config_host_mak diff --git a/qemu-timer.c b/qemu-timer.c index 908a1030b6..ede84ffd56 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -494,12 +494,12 @@ static int dynticks_start_timer(struct qemu_alarm_timer *t) memset(&ev, 0, sizeof(ev)); ev.sigev_value.sival_int = 0; ev.sigev_notify = SIGEV_SIGNAL; -#ifdef SIGEV_THREAD_ID +#ifdef CONFIG_SIGEV_THREAD_ID if (qemu_signalfd_available()) { ev.sigev_notify = SIGEV_THREAD_ID; ev._sigev_un._tid = qemu_get_thread_id(); } -#endif /* SIGEV_THREAD_ID */ +#endif /* CONFIG_SIGEV_THREAD_ID */ ev.sigev_signo = SIGALRM; if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) { From 01f590d5a3385c3d79c6afda7acd66edf4bf48d3 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 24 Oct 2012 12:10:33 -0200 Subject: [PATCH 1200/2270] target-i386: cpu: recover items 28-31 of ext2_feature_name I removed a line by mistake on commit 3b671a40cab2404bc63e57db8cd3afa4ec70bfab, containing the flags lm/i64, 3dnow, and 3dnowext. This patch restores the removed line. Reviewed-by: Don Slutz Signed-off-by: Eduardo Habkost Signed-off-by: Aurelien Jarno --- target-i386/cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index f3708e63b7..6411042b79 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -74,6 +74,7 @@ static const char *ext2_feature_name[] = { NULL /* pat */, NULL /* pse36 */, NULL, NULL /* Linux mp */, "nx|xd", NULL, "mmxext", NULL /* mmx */, NULL /* fxsr */, "fxsr_opt|ffxsr", "pdpe1gb" /* AMD Page1GB */, "rdtscp", + NULL, "lm|i64", "3dnowext", "3dnow", }; static const char *ext3_feature_name[] = { "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, From 419336a9f934d6a6c7098648bc833137a5db2015 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Mon, 15 Oct 2012 14:34:37 +1000 Subject: [PATCH 1201/2270] m25p80: Support for Quad SPI Added the Quad mode read and write commands. Data remains serialized on a single wire, i.e. the quad mode instructions just behave the same as single mode, with the expection of modelling the varying number of dummy/mode bytes between the address bytes and the first data word. Signed-off-by: Peter Crosthwaite --- hw/m25p80.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/hw/m25p80.c b/hw/m25p80.c index 9a56de8023..3895e73957 100644 --- a/hw/m25p80.c +++ b/hw/m25p80.c @@ -72,6 +72,10 @@ typedef struct FlashPartInfo { .page_size = 256,\ .flags = (_flags),\ +#define JEDEC_NUMONYX 0x20 +#define JEDEC_WINBOND 0xEF +#define JEDEC_SPANSION 0x01 + static const FlashPartInfo known_devices[] = { /* Atmel -- some are (confusingly) marketed as "DataFlash" */ { INFO("at25fs010", 0x1f6601, 0, 32 << 10, 4, ER_4K) }, @@ -180,17 +184,26 @@ static const FlashPartInfo known_devices[] = { typedef enum { NOP = 0, - PP = 0x2, - READ = 0x3, WRDI = 0x4, RDSR = 0x5, WREN = 0x6, + JEDEC_READ = 0x9f, + BULK_ERASE = 0xc7, + + READ = 0x3, FAST_READ = 0xb, + DOR = 0x3b, + QOR = 0x6b, + DIOR = 0xbb, + QIOR = 0xeb, + + PP = 0x2, + DPP = 0xa2, + QPP = 0x32, + ERASE_4K = 0x20, ERASE_32K = 0x52, ERASE_SECTOR = 0xd8, - JEDEC_READ = 0x9f, - BULK_ERASE = 0xc7, } FlashCMD; typedef enum { @@ -346,11 +359,17 @@ static void complete_collecting_data(Flash *s) s->cur_addr |= s->data[2]; switch (s->cmd_in_progress) { + case DPP: + case QPP: case PP: s->state = STATE_PAGE_PROGRAM; break; case READ: case FAST_READ: + case DOR: + case QOR: + case DIOR: + case QIOR: s->state = STATE_READ; break; case ERASE_4K: @@ -374,6 +393,8 @@ static void decode_new_cmd(Flash *s, uint32_t value) case ERASE_32K: case ERASE_SECTOR: case READ: + case DPP: + case QPP: case PP: s->needed_bytes = 3; s->pos = 0; @@ -382,12 +403,44 @@ static void decode_new_cmd(Flash *s, uint32_t value) break; case FAST_READ: + case DOR: + case QOR: s->needed_bytes = 4; s->pos = 0; s->len = 0; s->state = STATE_COLLECTING_DATA; break; + case DIOR: + switch ((s->pi->jedec >> 16) & 0xFF) { + case JEDEC_WINBOND: + case JEDEC_SPANSION: + s->needed_bytes = 4; + break; + case JEDEC_NUMONYX: + default: + s->needed_bytes = 5; + } + s->pos = 0; + s->len = 0; + s->state = STATE_COLLECTING_DATA; + break; + + case QIOR: + switch ((s->pi->jedec >> 16) & 0xFF) { + case JEDEC_WINBOND: + case JEDEC_SPANSION: + s->needed_bytes = 6; + break; + case JEDEC_NUMONYX: + default: + s->needed_bytes = 8; + } + s->pos = 0; + s->len = 0; + s->state = STATE_COLLECTING_DATA; + break; + case WRDI: s->write_enable = false; break; From f12411440b5d9e96af0720dd47b484c1440f4d62 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Mon, 15 Oct 2012 14:37:04 +1000 Subject: [PATCH 1202/2270] xilinx_spips: Generalised to model QSPI Extended the xilinx spips controller to model QSPI as well. Paremeterised the operational difference with the normal spi controller (num_ss_bits, width of the tx/rx fifo heads etc.). Multiple bus functionality is modelled (needed for QSPI dual parallel mode. LQSPI is modelled. Signed-off-by: Peter Crosthwaite --- hw/xilinx_spips.c | 291 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 256 insertions(+), 35 deletions(-) diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c index 93a4957010..ee7656d7d8 100644 --- a/hw/xilinx_spips.c +++ b/hw/xilinx_spips.c @@ -28,6 +28,7 @@ #include "qemu-log.h" #include "fifo.h" #include "ssi.h" +#include "bitops.h" #ifdef XILINX_SPIPS_ERR_DEBUG #define DB_PRINT(...) do { \ @@ -40,6 +41,8 @@ /* config register */ #define R_CONFIG (0x00 / 4) +#define IFMODE (1 << 31) +#define ENDIAN (1 << 26) #define MODEFAIL_GEN_EN (1 << 17) #define MAN_START_COM (1 << 16) #define MAN_START_EN (1 << 15) @@ -75,45 +78,101 @@ #define R_SLAVE_IDLE_COUNT (0x24 / 4) #define R_TX_THRES (0x28 / 4) #define R_RX_THRES (0x2C / 4) +#define R_TXD1 (0x80 / 4) +#define R_TXD2 (0x84 / 4) +#define R_TXD3 (0x88 / 4) + +#define R_LQSPI_CFG (0xa0 / 4) +#define R_LQSPI_CFG_RESET 0x03A002EB +#define LQSPI_CFG_LQ_MODE (1 << 31) +#define LQSPI_CFG_TWO_MEM (1 << 30) +#define LQSPI_CFG_SEP_BUS (1 << 30) +#define LQSPI_CFG_U_PAGE (1 << 28) +#define LQSPI_CFG_MODE_EN (1 << 25) +#define LQSPI_CFG_MODE_WIDTH 8 +#define LQSPI_CFG_MODE_SHIFT 16 +#define LQSPI_CFG_DUMMY_WIDTH 3 +#define LQSPI_CFG_DUMMY_SHIFT 8 +#define LQSPI_CFG_INST_CODE 0xFF + +#define R_LQSPI_STS (0xA4 / 4) +#define LQSPI_STS_WR_RECVD (1 << 1) + #define R_MOD_ID (0xFC / 4) #define R_MAX (R_MOD_ID+1) /* size of TXRX FIFOs */ -#define NUM_CS_LINES 4 #define RXFF_A 32 #define TXFF_A 32 +/* 16MB per linear region */ +#define LQSPI_ADDRESS_BITS 24 +/* Bite off 4k chunks at a time */ +#define LQSPI_CACHE_SIZE 1024 + +#define SNOOP_CHECKING 0xFF +#define SNOOP_NONE 0xFE +#define SNOOP_STRIPING 0 + typedef struct { SysBusDevice busdev; MemoryRegion iomem; + MemoryRegion mmlqspi; + qemu_irq irq; int irqline; - qemu_irq cs_lines[NUM_CS_LINES]; - SSIBus *spi; + uint8_t num_cs; + uint8_t num_busses; + + uint8_t snoop_state; + qemu_irq *cs_lines; + SSIBus **spi; Fifo8 rx_fifo; Fifo8 tx_fifo; + uint8_t num_txrx_bytes; + uint32_t regs[R_MAX]; + + uint32_t lqspi_buf[LQSPI_CACHE_SIZE]; + hwaddr lqspi_cached_addr; } XilinxSPIPS; +static inline int num_effective_busses(XilinxSPIPS *s) +{ + return (s->regs[R_LQSPI_STS] & LQSPI_CFG_SEP_BUS && + s->regs[R_LQSPI_STS] & LQSPI_CFG_TWO_MEM) ? s->num_busses : 1; +} + static void xilinx_spips_update_cs_lines(XilinxSPIPS *s) { - int i; + int i, j; bool found = false; int field = s->regs[R_CONFIG] >> CS_SHIFT; - for (i = 0; i < NUM_CS_LINES; i++) { - if (~field & (1 << i) && !found) { - found = true; - DB_PRINT("selecting slave %d\n", i); - qemu_set_irq(s->cs_lines[i], 0); - } else { - qemu_set_irq(s->cs_lines[i], 1); + for (i = 0; i < s->num_cs; i++) { + for (j = 0; j < num_effective_busses(s); j++) { + int upage = !!(s->regs[R_LQSPI_STS] & LQSPI_CFG_U_PAGE); + int cs_to_set = (j * s->num_cs + i + upage) % + (s->num_cs * s->num_busses); + + if (~field & (1 << i) && !found) { + DB_PRINT("selecting slave %d\n", i); + qemu_set_irq(s->cs_lines[cs_to_set], 0); + } else { + qemu_set_irq(s->cs_lines[cs_to_set], 1); + } } - } + if (~field & (1 << i)) { + found = true; + } + } + if (!found) { + s->snoop_state = SNOOP_CHECKING; + } } static void xilinx_spips_update_ixr(XilinxSPIPS *s) @@ -154,6 +213,8 @@ static void xilinx_spips_reset(DeviceState *d) s->regs[R_RX_THRES] = 1; /* FIXME: move magic number definition somewhere sensible */ s->regs[R_MOD_ID] = 0x01090106; + s->regs[R_LQSPI_CFG] = R_LQSPI_CFG_RESET; + s->snoop_state = SNOOP_CHECKING; xilinx_spips_update_ixr(s); xilinx_spips_update_cs_lines(s); } @@ -161,26 +222,68 @@ static void xilinx_spips_reset(DeviceState *d) static void xilinx_spips_flush_txfifo(XilinxSPIPS *s) { for (;;) { - uint32_t r; - uint8_t value; + int i; + uint8_t rx; + uint8_t tx = 0; - if (fifo8_is_empty(&s->tx_fifo)) { - s->regs[R_INTR_STATUS] |= IXR_TX_FIFO_UNDERFLOW; - break; - } else { - value = fifo8_pop(&s->tx_fifo); + for (i = 0; i < num_effective_busses(s); ++i) { + if (!i || s->snoop_state == SNOOP_STRIPING) { + if (fifo8_is_empty(&s->tx_fifo)) { + s->regs[R_INTR_STATUS] |= IXR_TX_FIFO_UNDERFLOW; + xilinx_spips_update_ixr(s); + return; + } else { + tx = fifo8_pop(&s->tx_fifo); + } + } + rx = ssi_transfer(s->spi[i], (uint32_t)tx); + DB_PRINT("tx = %02x rx = %02x\n", tx, rx); + if (!i || s->snoop_state == SNOOP_STRIPING) { + if (fifo8_is_full(&s->rx_fifo)) { + s->regs[R_INTR_STATUS] |= IXR_RX_FIFO_OVERFLOW; + DB_PRINT("rx FIFO overflow"); + } else { + fifo8_push(&s->rx_fifo, (uint8_t)rx); + } + } } - r = ssi_transfer(s->spi, (uint32_t)value); - DB_PRINT("tx = %02x rx = %02x\n", value, r); - if (fifo8_is_full(&s->rx_fifo)) { - s->regs[R_INTR_STATUS] |= IXR_RX_FIFO_OVERFLOW; - DB_PRINT("rx FIFO overflow"); - } else { - fifo8_push(&s->rx_fifo, (uint8_t)r); + switch (s->snoop_state) { + case (SNOOP_CHECKING): + switch (tx) { /* new instruction code */ + case 0x0b: /* dual/quad output read DOR/QOR */ + case 0x6b: + s->snoop_state = 4; + break; + /* FIXME: these vary between vendor - set to spansion */ + case 0xbb: /* high performance dual read DIOR */ + s->snoop_state = 4; + break; + case 0xeb: /* high performance quad read QIOR */ + s->snoop_state = 6; + break; + default: + s->snoop_state = SNOOP_NONE; + } + break; + case (SNOOP_STRIPING): + case (SNOOP_NONE): + break; + default: + s->snoop_state--; } } - xilinx_spips_update_ixr(s); +} + +static inline void rx_data_bytes(XilinxSPIPS *s, uint32_t *value, int max) +{ + int i; + + *value = 0; + for (i = 0; i < max && !fifo8_is_empty(&s->rx_fifo); ++i) { + uint32_t next = fifo8_pop(&s->rx_fifo) & 0xFF; + *value |= next << 8 * (s->regs[R_CONFIG] & ENDIAN ? 3-i : i); + } } static uint64_t xilinx_spips_read(void *opaque, hwaddr addr, @@ -214,7 +317,7 @@ static uint64_t xilinx_spips_read(void *opaque, hwaddr addr, mask = 0; break; case R_RX_DATA: - ret = (uint32_t)fifo8_pop(&s->rx_fifo); + rx_data_bytes(s, &ret, s->num_txrx_bytes); DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, ret); xilinx_spips_update_ixr(s); return ret; @@ -224,6 +327,20 @@ static uint64_t xilinx_spips_read(void *opaque, hwaddr addr, } +static inline void tx_data_bytes(XilinxSPIPS *s, uint32_t value, int num) +{ + int i; + for (i = 0; i < num && !fifo8_is_full(&s->tx_fifo); ++i) { + if (s->regs[R_CONFIG] & ENDIAN) { + fifo8_push(&s->tx_fifo, (uint8_t)(value >> 24)); + value <<= 8; + } else { + fifo8_push(&s->tx_fifo, (uint8_t)value); + value >>= 8; + } + } +} + static void xilinx_spips_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { @@ -264,7 +381,16 @@ static void xilinx_spips_write(void *opaque, hwaddr addr, mask = 0; break; case R_TX_DATA: - fifo8_push(&s->tx_fifo, (uint8_t)value); + tx_data_bytes(s, (uint32_t)value, s->num_txrx_bytes); + goto no_reg_update; + case R_TXD1: + tx_data_bytes(s, (uint32_t)value, 1); + goto no_reg_update; + case R_TXD2: + tx_data_bytes(s, (uint32_t)value, 2); + goto no_reg_update; + case R_TXD3: + tx_data_bytes(s, (uint32_t)value, 3); goto no_reg_update; } s->regs[addr] = (s->regs[addr] & ~mask) | (value & mask); @@ -282,6 +408,81 @@ static const MemoryRegionOps spips_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; +#define LQSPI_CACHE_SIZE 1024 + +static uint64_t +lqspi_read(void *opaque, hwaddr addr, unsigned int size) +{ + int i; + XilinxSPIPS *s = opaque; + + if (addr >= s->lqspi_cached_addr && + addr <= s->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) { + return s->lqspi_buf[(addr - s->lqspi_cached_addr) >> 2]; + } else { + int flash_addr = (addr / num_effective_busses(s)); + int slave = flash_addr >> LQSPI_ADDRESS_BITS; + int cache_entry = 0; + + DB_PRINT("config reg status: %08x\n", s->regs[R_LQSPI_CFG]); + + fifo8_reset(&s->tx_fifo); + fifo8_reset(&s->rx_fifo); + + s->regs[R_CONFIG] &= ~CS; + s->regs[R_CONFIG] |= (~(1 << slave) << CS_SHIFT) & CS; + xilinx_spips_update_cs_lines(s); + + /* instruction */ + DB_PRINT("pushing read instruction: %02x\n", + (uint8_t)(s->regs[R_LQSPI_CFG] & LQSPI_CFG_INST_CODE)); + fifo8_push(&s->tx_fifo, s->regs[R_LQSPI_CFG] & LQSPI_CFG_INST_CODE); + /* read address */ + DB_PRINT("pushing read address %06x\n", flash_addr); + fifo8_push(&s->tx_fifo, (uint8_t)(flash_addr >> 16)); + fifo8_push(&s->tx_fifo, (uint8_t)(flash_addr >> 8)); + fifo8_push(&s->tx_fifo, (uint8_t)flash_addr); + /* mode bits */ + if (s->regs[R_LQSPI_CFG] & LQSPI_CFG_MODE_EN) { + fifo8_push(&s->tx_fifo, extract32(s->regs[R_LQSPI_CFG], + LQSPI_CFG_MODE_SHIFT, + LQSPI_CFG_MODE_WIDTH)); + } + /* dummy bytes */ + for (i = 0; i < (extract32(s->regs[R_LQSPI_CFG], LQSPI_CFG_DUMMY_SHIFT, + LQSPI_CFG_DUMMY_WIDTH)); ++i) { + DB_PRINT("pushing dummy byte\n"); + fifo8_push(&s->tx_fifo, 0); + } + xilinx_spips_flush_txfifo(s); + fifo8_reset(&s->rx_fifo); + + DB_PRINT("starting QSPI data read\n"); + + for (i = 0; i < LQSPI_CACHE_SIZE / 4; ++i) { + tx_data_bytes(s, 0, 4); + xilinx_spips_flush_txfifo(s); + rx_data_bytes(s, &s->lqspi_buf[cache_entry], 4); + cache_entry++; + } + + s->regs[R_CONFIG] |= CS; + xilinx_spips_update_cs_lines(s); + + s->lqspi_cached_addr = addr; + return lqspi_read(opaque, addr, size); + } +} + +static const MemoryRegionOps lqspi_ops = { + .read = lqspi_read, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } +}; + static int xilinx_spips_init(SysBusDevice *dev) { XilinxSPIPS *s = FROM_SYSBUS(typeof(*s), dev); @@ -289,18 +490,30 @@ static int xilinx_spips_init(SysBusDevice *dev) DB_PRINT("inited device model\n"); - s->spi = ssi_create_bus(&dev->qdev, "spi"); + s->spi = g_new(SSIBus *, s->num_busses); + for (i = 0; i < s->num_busses; ++i) { + char bus_name[16]; + snprintf(bus_name, 16, "spi%d", i); + s->spi[i] = ssi_create_bus(&dev->qdev, bus_name); + } - ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi); + s->cs_lines = g_new(qemu_irq, s->num_cs * s->num_busses); + ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[0]); + ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[1]); sysbus_init_irq(dev, &s->irq); - for (i = 0; i < NUM_CS_LINES; ++i) { + for (i = 0; i < s->num_cs * s->num_busses; ++i) { sysbus_init_irq(dev, &s->cs_lines[i]); } memory_region_init_io(&s->iomem, &spips_ops, s, "spi", R_MAX*4); sysbus_init_mmio(dev, &s->iomem); + memory_region_init_io(&s->mmlqspi, &lqspi_ops, s, "lqspi", + (1 << LQSPI_ADDRESS_BITS) * 2); + sysbus_init_mmio(dev, &s->mmlqspi); + s->irqline = -1; + s->lqspi_cached_addr = ~0ULL; fifo8_create(&s->rx_fifo, RXFF_A); fifo8_create(&s->tx_fifo, TXFF_A); @@ -317,18 +530,25 @@ static int xilinx_spips_post_load(void *opaque, int version_id) static const VMStateDescription vmstate_xilinx_spips = { .name = "xilinx_spips", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, + .version_id = 2, + .minimum_version_id = 2, + .minimum_version_id_old = 2, .post_load = xilinx_spips_post_load, .fields = (VMStateField[]) { VMSTATE_FIFO8(tx_fifo, XilinxSPIPS), VMSTATE_FIFO8(rx_fifo, XilinxSPIPS), VMSTATE_UINT32_ARRAY(regs, XilinxSPIPS, R_MAX), + VMSTATE_UINT8(snoop_state, XilinxSPIPS), VMSTATE_END_OF_LIST() } }; +static Property xilinx_spips_properties[] = { + DEFINE_PROP_UINT8("num-busses", XilinxSPIPS, num_busses, 1), + DEFINE_PROP_UINT8("num-ss-bits", XilinxSPIPS, num_cs, 4), + DEFINE_PROP_UINT8("num-txrx-bytes", XilinxSPIPS, num_txrx_bytes, 1), + DEFINE_PROP_END_OF_LIST(), +}; static void xilinx_spips_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -336,6 +556,7 @@ static void xilinx_spips_class_init(ObjectClass *klass, void *data) sdc->init = xilinx_spips_init; dc->reset = xilinx_spips_reset; + dc->props = xilinx_spips_properties; dc->vmsd = &vmstate_xilinx_spips; } From 7b482bcfa9ca1a65d8a5c154f385399e58fc5498 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Mon, 15 Oct 2012 14:40:21 +1000 Subject: [PATCH 1203/2270] xilinx_zynq: added QSPI controller Added the QSPI controller to the Zynq. 4 SPI devices are attached to allow modelling of the different geometries. E.G. Dual parallel and dual stacked mode can both be tested with this one arrangement. Signed-off-by: Peter Crosthwaite --- hw/xilinx_zynq.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c index c55dafba6b..00262350b6 100644 --- a/hw/xilinx_zynq.c +++ b/hw/xilinx_zynq.c @@ -27,6 +27,8 @@ #include "ssi.h" #define NUM_SPI_FLASHES 4 +#define NUM_QSPI_FLASHES 2 +#define NUM_QSPI_BUSSES 2 #define FLASH_SIZE (64 * 1024 * 1024) #define FLASH_SECTOR_SIZE (128 * 1024) @@ -49,30 +51,43 @@ static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq) sysbus_connect_irq(s, 0, irq); } -static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq) +static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq, + bool is_qspi) { DeviceState *dev; SysBusDevice *busdev; SSIBus *spi; - int i; + int i, j; + int num_busses = is_qspi ? NUM_QSPI_BUSSES : 1; + int num_ss = is_qspi ? NUM_QSPI_FLASHES : NUM_SPI_FLASHES; dev = qdev_create(NULL, "xilinx,spips"); + qdev_prop_set_uint8(dev, "num-txrx-bytes", is_qspi ? 4 : 1); + qdev_prop_set_uint8(dev, "num-ss-bits", num_ss); + qdev_prop_set_uint8(dev, "num-busses", num_busses); qdev_init_nofail(dev); busdev = sysbus_from_qdev(dev); sysbus_mmio_map(busdev, 0, base_addr); + if (is_qspi) { + sysbus_mmio_map(busdev, 1, 0xFC000000); + } sysbus_connect_irq(busdev, 0, irq); - spi = (SSIBus *)qdev_get_child_bus(dev, "spi"); - - for (i = 0; i < NUM_SPI_FLASHES; ++i) { + for (i = 0; i < num_busses; ++i) { + char bus_name[16]; qemu_irq cs_line; - dev = ssi_create_slave_no_init(spi, "m25p80"); - qdev_prop_set_string(dev, "partname", "n25q128"); - qdev_init_nofail(dev); + snprintf(bus_name, 16, "spi%d", i); + spi = (SSIBus *)qdev_get_child_bus(dev, bus_name); - cs_line = qdev_get_gpio_in(dev, 0); - sysbus_connect_irq(busdev, i+1, cs_line); + for (j = 0; j < num_ss; ++j) { + dev = ssi_create_slave_no_init(spi, "m25p80"); + qdev_prop_set_string(dev, "partname", "n25q128"); + qdev_init_nofail(dev); + + cs_line = qdev_get_gpio_in(dev, 0); + sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line); + } } } @@ -147,8 +162,9 @@ static void zynq_init(QEMUMachineInitArgs *args) pic[n] = qdev_get_gpio_in(dev, n); } - zynq_init_spi_flashes(0xE0006000, pic[58-IRQ_OFFSET]); - zynq_init_spi_flashes(0xE0007000, pic[81-IRQ_OFFSET]); + zynq_init_spi_flashes(0xE0006000, pic[58-IRQ_OFFSET], false); + zynq_init_spi_flashes(0xE0007000, pic[81-IRQ_OFFSET], false); + zynq_init_spi_flashes(0xE000D000, pic[51-IRQ_OFFSET], true); sysbus_create_simple("cadence_uart", 0xE0000000, pic[59-IRQ_OFFSET]); sysbus_create_simple("cadence_uart", 0xE0001000, pic[82-IRQ_OFFSET]); From 21b2f13ae21974e0fd7f8da99d84628a8000d1d7 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 5 Oct 2012 07:09:02 +0000 Subject: [PATCH 1204/2270] Drop unnecessary check of TARGET_PHYS_ADDR_SPACE_BITS For all our PPC targets the physical address space is at least 36 bits, so drop an unnecessary preprocessor conditional check on TARGET_PHYS_ADDR_SPACE_BITS (erroneously introduced as part of the change from target_phys_addr_t to hwaddr). This brings this bit of code into line with the way we handle the other cases which were originally checking TARGET_PHYS_ADDR_BITS in order to avoid compiler complaints about overflowing a 32 bit type. Signed-off-by: Peter Maydell Signed-off-by: Alexander Graf --- target-ppc/mmu_helper.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c index 4a9bb5b965..811f47f309 100644 --- a/target-ppc/mmu_helper.c +++ b/target-ppc/mmu_helper.c @@ -1509,10 +1509,8 @@ static void mmubooke_dump_mmu(FILE *f, fprintf_function cpu_fprintf, mask = ~(entry->size - 1); ea = entry->EPN & mask; pa = entry->RPN & mask; -#if (TARGET_PHYS_ADDR_SPACE_BITS >= 36) /* Extend the physical address to 36 bits */ pa |= (hwaddr)(entry->RPN & 0xF) << 32; -#endif size /= 1024; if (size >= 1024) { snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / 1024); From 5232fa59b17b45c04bd24e0d38224964816bf391 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 6 Oct 2012 02:02:05 +0200 Subject: [PATCH 1205/2270] PPC: Bamboo: Fix memory size DT property Device tree properties need to be specified in big endian. Fix the bamboo memory size property accordingly. Signed-off-by: Alexander Graf CC: qemu-stable@nongnu.org --- hw/ppc440_bamboo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c index a6b1d51fae..cc85607cb7 100644 --- a/hw/ppc440_bamboo.c +++ b/hw/ppc440_bamboo.c @@ -59,7 +59,7 @@ static int bamboo_load_device_tree(hwaddr addr, { int ret = -1; #ifdef CONFIG_FDT - uint32_t mem_reg_property[] = { 0, 0, ramsize }; + uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) }; char *filename; int fdt_size; void *fdt; From e598a9c56badd00eaa732c4e0e69def4e5e6614b Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 6 Oct 2012 22:54:25 +0200 Subject: [PATCH 1206/2270] PPC: 440: Emulate DCBR0 The DCBR0 register on 440 is used to implement system reset. The same register is used on 405 as well, so just reuse the code. Signed-off-by: Alexander Graf --- target-ppc/translate_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index a972287035..ad54985059 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -1498,7 +1498,7 @@ static void gen_spr_BookE (CPUPPCState *env, uint64_t ivor_mask) /* XXX : not implemented */ spr_register(env, SPR_BOOKE_DBCR0, "DBCR0", SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, + &spr_read_generic, &spr_write_40x_dbcr0, 0x00000000); /* XXX : not implemented */ spr_register(env, SPR_BOOKE_DBCR1, "DBCR1", From 59de4f98d14fb84f04181a6f816ef6dd8b82dd79 Mon Sep 17 00:00:00 2001 From: Bharat Bhushan Date: Mon, 8 Oct 2012 06:46:54 +0000 Subject: [PATCH 1207/2270] e500: Fix serial initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit it was wrongly using serial_hds[0] instead of serial_hds[1] Signed-off-by: Bharat Bhushan Reviewed-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/ppc/e500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index d655e3f46f..90d88ebc74 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -496,7 +496,7 @@ void ppce500_init(PPCE500Params *params) if (serial_hds[1]) { serial_mm_init(address_space_mem, MPC8544_SERIAL1_REGS_BASE, 0, mpic[12+26], 399193, - serial_hds[0], DEVICE_BIG_ENDIAN); + serial_hds[1], DEVICE_BIG_ENDIAN); } /* General Utility device */ From 094b287f0b3b79d1e68df8f3a63cb144ec9cdfb6 Mon Sep 17 00:00:00 2001 From: "zhlcindy@gmail.com" Date: Sun, 2 Sep 2012 19:25:28 +0000 Subject: [PATCH 1208/2270] Add USB option in machine options When -usb option is used, global varible usb_enabled is set. And all the plaform will create one USB controller according to this variable. In fact, global varibles make code hard to read. So this patch is to remove global variable usb_enabled and add USB option in machine options. All the plaforms will get USB option value from machine options. USB option of machine options will be set either by: * -usb * -machine type=pseries,usb=on Both these ways can work now. They both set USB option in machine options. In the future, the first way will be removed. Signed-off-by: Li Zhang Acked-by: Alexander Graf Signed-off-by: Alexander Graf --- hw/nseries.c | 3 ++- hw/pc_piix.c | 2 +- hw/ppc_newworld.c | 19 +++++++------------ hw/ppc_oldworld.c | 2 +- hw/ppc_prep.c | 2 +- hw/pxa2xx.c | 4 ++-- hw/realview.c | 2 +- hw/spapr.c | 2 +- hw/versatilepb.c | 2 +- qemu-config.c | 4 ++++ sysemu.h | 4 +++- vl.c | 30 ++++++++++++++++++++++++------ 12 files changed, 48 insertions(+), 28 deletions(-) diff --git a/hw/nseries.c b/hw/nseries.c index 7ada90d280..9306aa15a7 100644 --- a/hw/nseries.c +++ b/hw/nseries.c @@ -1334,8 +1334,9 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device, n8x0_dss_setup(s); n8x0_cbus_setup(s); n8x0_uart_setup(s); - if (usb_enabled) + if (usb_enabled(false)) { n8x0_usb_setup(s); + } if (kernel_filename) { /* Or at the linux loader. */ diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 47ebc1ac04..c7dd75b0c0 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -267,7 +267,7 @@ static void pc_init1(MemoryRegion *system_memory, pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, floppy, idebus[0], idebus[1], rtc_state); - if (pci_enabled && usb_enabled) { + if (pci_enabled && usb_enabled(false)) { pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci"); } diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index 15f74f95fd..664747ead3 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -348,10 +348,6 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) ide_mem[1] = pmac_ide_init(hd, pic[0x0d], dbdma, 0x16, pic[0x02]); ide_mem[2] = pmac_ide_init(&hd[MAX_IDE_DEVS], pic[0x0e], dbdma, 0x1a, pic[0x02]); - /* cuda also initialize ADB */ - if (machine_arch == ARCH_MAC99_U3) { - usb_enabled = 1; - } cuda_init(&cuda_mem, pic[0x19]); adb_kbd_init(&adb_bus); @@ -360,15 +356,14 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) macio_init(pci_bus, PCI_DEVICE_ID_APPLE_UNI_N_KEYL, 0, pic_mem, dbdma_mem, cuda_mem, NULL, 3, ide_mem, escc_bar); - if (usb_enabled) { + if (usb_enabled(machine_arch == ARCH_MAC99_U3)) { pci_create_simple(pci_bus, -1, "pci-ohci"); - } - - /* U3 needs to use USB for input because Linux doesn't support via-cuda - on PPC64 */ - if (machine_arch == ARCH_MAC99_U3) { - usbdevice_create("keyboard"); - usbdevice_create("mouse"); + /* U3 needs to use USB for input because Linux doesn't support via-cuda + on PPC64 */ + if (machine_arch == ARCH_MAC99_U3) { + usbdevice_create("keyboard"); + usbdevice_create("mouse"); + } } if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8) diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index a4f899d889..e8138c091e 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -286,7 +286,7 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) macio_init(pci_bus, PCI_DEVICE_ID_APPLE_343S1201, 1, pic_mem, dbdma_mem, cuda_mem, nvr, 2, ide_mem, escc_bar); - if (usb_enabled) { + if (usb_enabled(false)) { pci_create_simple(pci_bus, -1, "pci-ohci"); } diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index 085851a3e6..bf15730d8b 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -661,7 +661,7 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) memory_region_add_subregion(sysmem, 0xFEFF0000, xcsr); #endif - if (usb_enabled) { + if (usb_enabled(false)) { pci_create_simple(pci_bus, -1, "pci-ohci"); } diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c index 0fb2179baf..e616979207 100644 --- a/hw/pxa2xx.c +++ b/hw/pxa2xx.c @@ -2108,7 +2108,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space, s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi"); } - if (usb_enabled) { + if (usb_enabled(false)) { sysbus_create_simple("sysbus-ohci", 0x4c000000, qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1)); } @@ -2239,7 +2239,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size) s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi"); } - if (usb_enabled) { + if (usb_enabled(false)) { sysbus_create_simple("sysbus-ohci", 0x4c000000, qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1)); } diff --git a/hw/realview.c b/hw/realview.c index baa92d42fd..b5cb08cb84 100644 --- a/hw/realview.c +++ b/hw/realview.c @@ -227,7 +227,7 @@ static void realview_init(ram_addr_t ram_size, sysbus_connect_irq(busdev, 2, pic[50]); sysbus_connect_irq(busdev, 3, pic[51]); pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci"); - if (usb_enabled) { + if (usb_enabled(false)) { pci_create_simple(pci_bus, -1, "pci-ohci"); } n = drive_get_max_bus(IF_SCSI); diff --git a/hw/spapr.c b/hw/spapr.c index 73d75e818c..1587bc3e03 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -840,7 +840,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args) spapr->has_graphics = true; } - if (usb_enabled) { + if (usb_enabled(spapr->has_graphics)) { pci_create_simple(phb->bus, -1, "pci-ohci"); if (spapr->has_graphics) { usbdevice_create("keyboard"); diff --git a/hw/versatilepb.c b/hw/versatilepb.c index f55bd0ca1d..e85f982897 100644 --- a/hw/versatilepb.c +++ b/hw/versatilepb.c @@ -248,7 +248,7 @@ static void versatile_init(ram_addr_t ram_size, pci_nic_init_nofail(nd, "rtl8139", NULL); } } - if (usb_enabled) { + if (usb_enabled(false)) { pci_create_simple(pci_bus, -1, "pci-ohci"); } n = drive_get_max_bus(IF_SCSI); diff --git a/qemu-config.c b/qemu-config.c index cd1ec2165a..97ffb97a87 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -619,6 +619,10 @@ static QemuOptsList qemu_machine_opts = { .name = "mem-merge", .type = QEMU_OPT_BOOL, .help = "enable/disable memory merge support", + },{ + .name = "usb", + .type = QEMU_OPT_BOOL, + .help = "Set on/off to enable/disable usb", }, { /* End of list */ } }, diff --git a/sysemu.h b/sysemu.h index 0c39a3ac1a..f72b4ce125 100644 --- a/sysemu.h +++ b/sysemu.h @@ -116,7 +116,6 @@ extern const char *keyboard_layout; extern int win2k_install_hack; extern int alt_grab; extern int ctrl_grab; -extern int usb_enabled; extern int smp_cpus; extern int max_cpus; extern int cursor_hide; @@ -186,4 +185,7 @@ void register_devices(void); void add_boot_device_path(int32_t bootindex, DeviceState *dev, const char *suffix); char *get_boot_devices_list(uint32_t *size); + +bool usb_enabled(bool default_usb); + #endif diff --git a/vl.c b/vl.c index 9f99ef4763..eb533b290c 100644 --- a/vl.c +++ b/vl.c @@ -203,7 +203,6 @@ CharDriverState *serial_hds[MAX_SERIAL_PORTS]; CharDriverState *parallel_hds[MAX_PARALLEL_PORTS]; CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES]; int win2k_install_hack = 0; -int usb_enabled = 0; int singlestep = 0; int smp_cpus = 1; int max_cpus = 0; @@ -790,6 +789,17 @@ static int parse_sandbox(QemuOpts *opts, void *opaque) return 0; } +/*********QEMU USB setting******/ +bool usb_enabled(bool default_usb) +{ + QemuOpts *mach_opts; + mach_opts = qemu_opts_find(qemu_find_opts("machine"), 0); + if (mach_opts) { + return qemu_opt_get_bool(mach_opts, "usb", default_usb); + } + return default_usb; +} + /***********************************************************/ /* QEMU Block devices */ @@ -1077,8 +1087,9 @@ static int usb_device_add(const char *devname) const char *p; USBDevice *dev = NULL; - if (!usb_enabled) + if (!usb_enabled(false)) { return -1; + } /* drivers with .usbdevice_name entry in USBDeviceInfo */ dev = usbdevice_create(devname); @@ -1114,8 +1125,9 @@ static int usb_device_del(const char *devname) if (strstart(devname, "host:", &p)) return usb_host_device_close(p); - if (!usb_enabled) + if (!usb_enabled(false)) { return -1; + } p = strchr(devname, '.'); if (!p) @@ -3083,10 +3095,16 @@ int main(int argc, char **argv, char **envp) } break; case QEMU_OPTION_usb: - usb_enabled = 1; + machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); + if (machine_opts) { + qemu_opt_set_bool(machine_opts, "usb", true); + } break; case QEMU_OPTION_usbdevice: - usb_enabled = 1; + machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); + if (machine_opts) { + qemu_opt_set_bool(machine_opts, "usb", true); + } add_device_config(DEV_USB, optarg); break; case QEMU_OPTION_device: @@ -3653,7 +3671,7 @@ int main(int argc, char **argv, char **envp) current_machine = machine; /* init USB devices */ - if (usb_enabled) { + if (usb_enabled(false)) { if (foreach_device_config(DEV_USB, usb_parse) < 0) exit(1); } From c89d52997cf4849a9ee16b5d2cf462d0cd137634 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 8 Oct 2012 18:17:36 +0000 Subject: [PATCH 1209/2270] pseries: Don't allow duplicate registration of hcalls or RTAS calls Currently the pseries machine code allows a callback to be registered for a hypercall number twice, as long as it's the same callback the second time. We don't test for duplicate registrations of RTAS callbacks at all so it will effectively be last registratiojn wins. This was originally done because it was awkward to ensure that the registration happened exactly once, but the code has since been restructured so that's no longer the case. Duplicate registration of a hypercall or RTAS call could well suggest a duplicate initialization which could cause other problems, so this patch makes duplicate registrations a bug, to prevent the old behaviour from hiding other bugs. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_hcall.c | 3 +-- hw/spapr_rtas.c | 9 +++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c index 194d9c24b5..762493a0f7 100644 --- a/hw/spapr_hcall.c +++ b/hw/spapr_hcall.c @@ -670,11 +670,10 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn) } else { assert((opcode >= KVMPPC_HCALL_BASE) && (opcode <= KVMPPC_HCALL_MAX)); - slot = &kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE]; } - assert(!(*slot) || (fn == *slot)); + assert(!(*slot)); *slot = fn; } diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c index 67da27ba51..ce76c5856a 100644 --- a/hw/spapr_rtas.c +++ b/hw/spapr_rtas.c @@ -241,6 +241,15 @@ target_ulong spapr_rtas_call(sPAPREnvironment *spapr, void spapr_rtas_register(const char *name, spapr_rtas_fn fn) { + int i; + + for (i = 0; i < (rtas_next - rtas_table); i++) { + if (strcmp(name, rtas_table[i].name) == 0) { + fprintf(stderr, "RTAS call \"%s\" registered twice\n", name); + exit(1); + } + } + assert(rtas_next < (rtas_table + TOKEN_MAX)); rtas_next->name = name; From 1bfb37d1e077705de14f0f7fdc7b21749dbe4bc9 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 8 Oct 2012 18:17:38 +0000 Subject: [PATCH 1210/2270] target-ppc: Rework storage of VPA registration state With PAPR guests, hypercalls allow registration of the Virtual Processor Area (VPA), SLB shadow and dispatch trace log (DTL), each of which allow for certain communication between the guest and hypervisor. Currently, we store the addresses of the three areas and the size of the dtl in CPUPPCState. The SLB shadow and DTL are variable sized, with the size being retrieved from within the registered memory area at the hypercall time. This size can later be overwritten with other information, however, so we need to save the size as of registration time. We already do this for the DTL, but not for the SLB shadow, so this patch fixes that. In addition, we change the storage of the VPA information to use fixed size integer types which will make life easier for syncing this data with KVM, which we will need in future. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_hcall.c | 26 ++++++++++++++------------ target-ppc/cpu.h | 7 +++---- target-ppc/translate_init.c | 7 ++++--- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c index 762493a0f7..621dabdfb1 100644 --- a/hw/spapr_hcall.c +++ b/hw/spapr_hcall.c @@ -366,26 +366,26 @@ static target_ulong register_vpa(CPUPPCState *env, target_ulong vpa) return H_PARAMETER; } - env->vpa = vpa; + env->vpa_addr = vpa; - tmp = ldub_phys(env->vpa + VPA_SHARED_PROC_OFFSET); + tmp = ldub_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET); tmp |= VPA_SHARED_PROC_VAL; - stb_phys(env->vpa + VPA_SHARED_PROC_OFFSET, tmp); + stb_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET, tmp); return H_SUCCESS; } static target_ulong deregister_vpa(CPUPPCState *env, target_ulong vpa) { - if (env->slb_shadow) { + if (env->slb_shadow_addr) { return H_RESOURCE; } - if (env->dispatch_trace_log) { + if (env->dtl_addr) { return H_RESOURCE; } - env->vpa = 0; + env->vpa_addr = 0; return H_SUCCESS; } @@ -407,18 +407,20 @@ static target_ulong register_slb_shadow(CPUPPCState *env, target_ulong addr) return H_PARAMETER; } - if (!env->vpa) { + if (!env->vpa_addr) { return H_RESOURCE; } - env->slb_shadow = addr; + env->slb_shadow_addr = addr; + env->slb_shadow_size = size; return H_SUCCESS; } static target_ulong deregister_slb_shadow(CPUPPCState *env, target_ulong addr) { - env->slb_shadow = 0; + env->slb_shadow_addr = 0; + env->slb_shadow_size = 0; return H_SUCCESS; } @@ -437,11 +439,11 @@ static target_ulong register_dtl(CPUPPCState *env, target_ulong addr) return H_PARAMETER; } - if (!env->vpa) { + if (!env->vpa_addr) { return H_RESOURCE; } - env->dispatch_trace_log = addr; + env->dtl_addr = addr; env->dtl_size = size; return H_SUCCESS; @@ -449,7 +451,7 @@ static target_ulong register_dtl(CPUPPCState *env, target_ulong addr) static target_ulong deregister_dtl(CPUPPCState *env, target_ulong addr) { - env->dispatch_trace_log = 0; + env->dtl_addr = 0; env->dtl_size = 0; return H_SUCCESS; diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 3f114c983b..286f42a808 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1045,10 +1045,9 @@ struct CPUPPCState { #endif #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) - hwaddr vpa; - hwaddr slb_shadow; - hwaddr dispatch_trace_log; - uint32_t dtl_size; + hwaddr vpa_addr; + hwaddr slb_shadow_addr, slb_shadow_size; + hwaddr dtl_addr, dtl_size; #endif /* TARGET_PPC64 */ int error_code; diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index ad54985059..e63627cac1 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -10425,9 +10425,10 @@ static void ppc_cpu_reset(CPUState *s) env->error_code = 0; #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) - env->vpa = 0; - env->slb_shadow = 0; - env->dispatch_trace_log = 0; + env->vpa_addr = 0; + env->slb_shadow_addr = 0; + env->slb_shadow_size = 0; + env->dtl_addr = 0; env->dtl_size = 0; #endif /* TARGET_PPC64 */ From 74d042e5cec78090194669a8a4417c0a49d46a3d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 8 Oct 2012 18:17:39 +0000 Subject: [PATCH 1211/2270] pseries: Implement qemu initiated shutdowns using EPOW events At present, using 'system_powerdown' from the monitor or otherwise instructing qemu to (cleanly) shut down a pseries guest will not work, because we did not have a method of signalling the shutdown request to the guest. PAPR does include a usable mechanism for this, though it is rather more involved than the equivalent on x86. This involves sending an EPOW (Environmental and POwer Warning) event through the PAPR event and error logging mechanism, which also has a number of other functions. This patch implements just enough of the event/error logging functionality to be able to send a shutdown event to the guest. At least with modern guest kernels and a userspace that is up and running, this means that system_powerdown from the qemu monitor should now work correctly on pseries guests. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/ppc/Makefile.objs | 1 + hw/spapr.c | 14 +- hw/spapr.h | 8 ++ hw/spapr_events.c | 321 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 342 insertions(+), 2 deletions(-) create mode 100644 hw/spapr_events.c diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index 951e407f14..8fe21235f0 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -11,6 +11,7 @@ obj-y += ppc_newworld.o obj-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o obj-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o obj-$(CONFIG_PSERIES) += spapr_pci.o pci-hotplug.o spapr_iommu.o +obj-$(CONFIG_PSERIES) += spapr_events.o # PowerPC 4xx boards obj-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o obj-y += ppc440_bamboo.o diff --git a/hw/spapr.c b/hw/spapr.c index 1587bc3e03..8d0ad3cfe9 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -232,7 +232,8 @@ static void *spapr_create_fdt_skel(const char *cpu_model, hwaddr initrd_size, hwaddr kernel_size, const char *boot_device, - const char *kernel_cmdline) + const char *kernel_cmdline, + uint32_t epow_irq) { void *fdt; CPUPPCState *env; @@ -403,6 +404,8 @@ static void *spapr_create_fdt_skel(const char *cpu_model, _FDT((fdt_property(fdt, "ibm,associativity-reference-points", refpoints, sizeof(refpoints)))); + _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX))); + _FDT((fdt_end_node(fdt))); /* interrupt controller */ @@ -433,6 +436,9 @@ static void *spapr_create_fdt_skel(const char *cpu_model, _FDT((fdt_end_node(fdt))); + /* event-sources */ + spapr_events_fdt_skel(fdt, epow_irq); + _FDT((fdt_end_node(fdt))); /* close root node */ _FDT((fdt_finish(fdt))); @@ -795,6 +801,9 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args) spapr->icp = xics_system_init(XICS_IRQS); spapr->next_irq = 16; + /* Set up EPOW events infrastructure */ + spapr_events_init(spapr); + /* Set up IOMMU */ spapr_iommu_init(); @@ -903,7 +912,8 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args) spapr->fdt_skel = spapr_create_fdt_skel(cpu_model, initrd_base, initrd_size, kernel_size, - boot_device, kernel_cmdline); + boot_device, kernel_cmdline, + spapr->epow_irq); assert(spapr->fdt_skel != NULL); } diff --git a/hw/spapr.h b/hw/spapr.h index 8ee69bdec8..51c709ea10 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -26,6 +26,9 @@ typedef struct sPAPREnvironment { int rtc_offset; char *cpu_model; bool has_graphics; + + uint32_t epow_irq; + Notifier epow_notifier; } sPAPREnvironment; #define H_SUCCESS 0 @@ -335,7 +338,12 @@ typedef struct sPAPRTCE { #define SPAPR_VIO_BASE_LIOBN 0x00000000 #define SPAPR_PCI_BASE_LIOBN 0x80000000 +#define RTAS_ERROR_LOG_MAX 2048 + + void spapr_iommu_init(void); +void spapr_events_init(sPAPREnvironment *spapr); +void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq); DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size); void spapr_tce_free(DMAContext *dma); void spapr_tce_reset(DMAContext *dma); diff --git a/hw/spapr_events.c b/hw/spapr_events.c new file mode 100644 index 0000000000..18ccd4a9e0 --- /dev/null +++ b/hw/spapr_events.c @@ -0,0 +1,321 @@ +/* + * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator + * + * RTAS events handling + * + * Copyright (c) 2012 David Gibson, IBM Corporation. + * + * 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 "cpu.h" +#include "sysemu.h" +#include "qemu-char.h" +#include "hw/qdev.h" +#include "device_tree.h" + +#include "hw/spapr.h" +#include "hw/spapr_vio.h" + +#include + +struct rtas_error_log { + uint32_t summary; +#define RTAS_LOG_VERSION_MASK 0xff000000 +#define RTAS_LOG_VERSION_6 0x06000000 +#define RTAS_LOG_SEVERITY_MASK 0x00e00000 +#define RTAS_LOG_SEVERITY_ALREADY_REPORTED 0x00c00000 +#define RTAS_LOG_SEVERITY_FATAL 0x00a00000 +#define RTAS_LOG_SEVERITY_ERROR 0x00800000 +#define RTAS_LOG_SEVERITY_ERROR_SYNC 0x00600000 +#define RTAS_LOG_SEVERITY_WARNING 0x00400000 +#define RTAS_LOG_SEVERITY_EVENT 0x00200000 +#define RTAS_LOG_SEVERITY_NO_ERROR 0x00000000 +#define RTAS_LOG_DISPOSITION_MASK 0x00180000 +#define RTAS_LOG_DISPOSITION_FULLY_RECOVERED 0x00000000 +#define RTAS_LOG_DISPOSITION_LIMITED_RECOVERY 0x00080000 +#define RTAS_LOG_DISPOSITION_NOT_RECOVERED 0x00100000 +#define RTAS_LOG_OPTIONAL_PART_PRESENT 0x00040000 +#define RTAS_LOG_INITIATOR_MASK 0x0000f000 +#define RTAS_LOG_INITIATOR_UNKNOWN 0x00000000 +#define RTAS_LOG_INITIATOR_CPU 0x00001000 +#define RTAS_LOG_INITIATOR_PCI 0x00002000 +#define RTAS_LOG_INITIATOR_MEMORY 0x00004000 +#define RTAS_LOG_INITIATOR_HOTPLUG 0x00006000 +#define RTAS_LOG_TARGET_MASK 0x00000f00 +#define RTAS_LOG_TARGET_UNKNOWN 0x00000000 +#define RTAS_LOG_TARGET_CPU 0x00000100 +#define RTAS_LOG_TARGET_PCI 0x00000200 +#define RTAS_LOG_TARGET_MEMORY 0x00000400 +#define RTAS_LOG_TARGET_HOTPLUG 0x00000600 +#define RTAS_LOG_TYPE_MASK 0x000000ff +#define RTAS_LOG_TYPE_OTHER 0x00000000 +#define RTAS_LOG_TYPE_RETRY 0x00000001 +#define RTAS_LOG_TYPE_TCE_ERR 0x00000002 +#define RTAS_LOG_TYPE_INTERN_DEV_FAIL 0x00000003 +#define RTAS_LOG_TYPE_TIMEOUT 0x00000004 +#define RTAS_LOG_TYPE_DATA_PARITY 0x00000005 +#define RTAS_LOG_TYPE_ADDR_PARITY 0x00000006 +#define RTAS_LOG_TYPE_CACHE_PARITY 0x00000007 +#define RTAS_LOG_TYPE_ADDR_INVALID 0x00000008 +#define RTAS_LOG_TYPE_ECC_UNCORR 0x00000009 +#define RTAS_LOG_TYPE_ECC_CORR 0x0000000a +#define RTAS_LOG_TYPE_EPOW 0x00000040 + uint32_t extended_length; +} QEMU_PACKED; + +struct rtas_event_log_v6 { + uint8_t b0; +#define RTAS_LOG_V6_B0_VALID 0x80 +#define RTAS_LOG_V6_B0_UNRECOVERABLE_ERROR 0x40 +#define RTAS_LOG_V6_B0_RECOVERABLE_ERROR 0x20 +#define RTAS_LOG_V6_B0_DEGRADED_OPERATION 0x10 +#define RTAS_LOG_V6_B0_PREDICTIVE_ERROR 0x08 +#define RTAS_LOG_V6_B0_NEW_LOG 0x04 +#define RTAS_LOG_V6_B0_BIGENDIAN 0x02 + uint8_t _resv1; + uint8_t b2; +#define RTAS_LOG_V6_B2_POWERPC_FORMAT 0x80 +#define RTAS_LOG_V6_B2_LOG_FORMAT_MASK 0x0f +#define RTAS_LOG_V6_B2_LOG_FORMAT_PLATFORM_EVENT 0x0e + uint8_t _resv2[9]; + uint32_t company; +#define RTAS_LOG_V6_COMPANY_IBM 0x49424d00 /* IBM */ +} QEMU_PACKED; + +struct rtas_event_log_v6_section_header { + uint16_t section_id; + uint16_t section_length; + uint8_t section_version; + uint8_t section_subtype; + uint16_t creator_component_id; +} QEMU_PACKED; + +struct rtas_event_log_v6_maina { +#define RTAS_LOG_V6_SECTION_ID_MAINA 0x5048 /* PH */ + struct rtas_event_log_v6_section_header hdr; + uint32_t creation_date; /* BCD: YYYYMMDD */ + uint32_t creation_time; /* BCD: HHMMSS00 */ + uint8_t _platform1[8]; + char creator_id; + uint8_t _resv1[2]; + uint8_t section_count; + uint8_t _resv2[4]; + uint8_t _platform2[8]; + uint32_t plid; + uint8_t _platform3[4]; +} QEMU_PACKED; + +struct rtas_event_log_v6_mainb { +#define RTAS_LOG_V6_SECTION_ID_MAINB 0x5548 /* UH */ + struct rtas_event_log_v6_section_header hdr; + uint8_t subsystem_id; + uint8_t _platform1; + uint8_t event_severity; + uint8_t event_subtype; + uint8_t _platform2[4]; + uint8_t _resv1[2]; + uint16_t action_flags; + uint8_t _resv2[4]; +} QEMU_PACKED; + +struct rtas_event_log_v6_epow { +#define RTAS_LOG_V6_SECTION_ID_EPOW 0x4550 /* EP */ + struct rtas_event_log_v6_section_header hdr; + uint8_t sensor_value; +#define RTAS_LOG_V6_EPOW_ACTION_RESET 0 +#define RTAS_LOG_V6_EPOW_ACTION_WARN_COOLING 1 +#define RTAS_LOG_V6_EPOW_ACTION_WARN_POWER 2 +#define RTAS_LOG_V6_EPOW_ACTION_SYSTEM_SHUTDOWN 3 +#define RTAS_LOG_V6_EPOW_ACTION_SYSTEM_HALT 4 +#define RTAS_LOG_V6_EPOW_ACTION_MAIN_ENCLOSURE 5 +#define RTAS_LOG_V6_EPOW_ACTION_POWER_OFF 7 + uint8_t event_modifier; +#define RTAS_LOG_V6_EPOW_MODIFIER_NORMAL 1 +#define RTAS_LOG_V6_EPOW_MODIFIER_ON_UPS 2 +#define RTAS_LOG_V6_EPOW_MODIFIER_CRITICAL 3 +#define RTAS_LOG_V6_EPOW_MODIFIER_TEMPERATURE 4 + uint8_t extended_modifier; +#define RTAS_LOG_V6_EPOW_XMODIFIER_SYSTEM_WIDE 0 +#define RTAS_LOG_V6_EPOW_XMODIFIER_PARTITION_SPECIFIC 1 + uint8_t _resv; + uint64_t reason_code; +} QEMU_PACKED; + +struct epow_log_full { + struct rtas_error_log hdr; + struct rtas_event_log_v6 v6hdr; + struct rtas_event_log_v6_maina maina; + struct rtas_event_log_v6_mainb mainb; + struct rtas_event_log_v6_epow epow; +} QEMU_PACKED; + +#define EVENT_MASK_INTERNAL_ERRORS 0x80000000 +#define EVENT_MASK_EPOW 0x40000000 +#define EVENT_MASK_HOTPLUG 0x10000000 +#define EVENT_MASK_IO 0x08000000 + +#define _FDT(exp) \ + do { \ + int ret = (exp); \ + if (ret < 0) { \ + fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \ + #exp, fdt_strerror(ret)); \ + exit(1); \ + } \ + } while (0) + +void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq) +{ + uint32_t epow_irq_ranges[] = {cpu_to_be32(epow_irq), cpu_to_be32(1)}; + uint32_t epow_interrupts[] = {cpu_to_be32(epow_irq), 0}; + + _FDT((fdt_begin_node(fdt, "event-sources"))); + + _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0))); + _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2))); + _FDT((fdt_property(fdt, "interrupt-ranges", + epow_irq_ranges, sizeof(epow_irq_ranges)))); + + _FDT((fdt_begin_node(fdt, "epow-events"))); + _FDT((fdt_property(fdt, "interrupts", + epow_interrupts, sizeof(epow_interrupts)))); + _FDT((fdt_end_node(fdt))); + + _FDT((fdt_end_node(fdt))); +} + +static struct epow_log_full *pending_epow; +static uint32_t next_plid; + +static void spapr_powerdown_req(Notifier *n, void *opaque) +{ + sPAPREnvironment *spapr = container_of(n, sPAPREnvironment, epow_notifier); + struct rtas_error_log *hdr; + struct rtas_event_log_v6 *v6hdr; + struct rtas_event_log_v6_maina *maina; + struct rtas_event_log_v6_mainb *mainb; + struct rtas_event_log_v6_epow *epow; + struct tm tm; + int year; + + if (pending_epow) { + /* For now, we just throw away earlier events if two come + * along before any are consumed. This is sufficient for our + * powerdown messages, but we'll need more if we do more + * general error/event logging */ + g_free(pending_epow); + } + pending_epow = g_malloc0(sizeof(*pending_epow)); + hdr = &pending_epow->hdr; + v6hdr = &pending_epow->v6hdr; + maina = &pending_epow->maina; + mainb = &pending_epow->mainb; + epow = &pending_epow->epow; + + hdr->summary = cpu_to_be32(RTAS_LOG_VERSION_6 + | RTAS_LOG_SEVERITY_EVENT + | RTAS_LOG_DISPOSITION_NOT_RECOVERED + | RTAS_LOG_OPTIONAL_PART_PRESENT + | RTAS_LOG_TYPE_EPOW); + hdr->extended_length = cpu_to_be32(sizeof(*pending_epow) + - sizeof(pending_epow->hdr)); + + v6hdr->b0 = RTAS_LOG_V6_B0_VALID | RTAS_LOG_V6_B0_NEW_LOG + | RTAS_LOG_V6_B0_BIGENDIAN; + v6hdr->b2 = RTAS_LOG_V6_B2_POWERPC_FORMAT + | RTAS_LOG_V6_B2_LOG_FORMAT_PLATFORM_EVENT; + v6hdr->company = cpu_to_be32(RTAS_LOG_V6_COMPANY_IBM); + + maina->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINA); + maina->hdr.section_length = cpu_to_be16(sizeof(*maina)); + /* FIXME: section version, subtype and creator id? */ + qemu_get_timedate(&tm, spapr->rtc_offset); + year = tm.tm_year + 1900; + maina->creation_date = cpu_to_be32((to_bcd(year / 100) << 24) + | (to_bcd(year % 100) << 16) + | (to_bcd(tm.tm_mon + 1) << 8) + | to_bcd(tm.tm_mday)); + maina->creation_time = cpu_to_be32((to_bcd(tm.tm_hour) << 24) + | (to_bcd(tm.tm_min) << 16) + | (to_bcd(tm.tm_sec) << 8)); + maina->creator_id = 'H'; /* Hypervisor */ + maina->section_count = 3; /* Main-A, Main-B and EPOW */ + maina->plid = next_plid++; + + mainb->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINB); + mainb->hdr.section_length = cpu_to_be16(sizeof(*mainb)); + /* FIXME: section version, subtype and creator id? */ + mainb->subsystem_id = 0xa0; /* External environment */ + mainb->event_severity = 0x00; /* Informational / non-error */ + mainb->event_subtype = 0xd0; /* Normal shutdown */ + + epow->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_EPOW); + epow->hdr.section_length = cpu_to_be16(sizeof(*epow)); + epow->hdr.section_version = 2; /* includes extended modifier */ + /* FIXME: section subtype and creator id? */ + epow->sensor_value = RTAS_LOG_V6_EPOW_ACTION_SYSTEM_SHUTDOWN; + epow->event_modifier = RTAS_LOG_V6_EPOW_MODIFIER_NORMAL; + epow->extended_modifier = RTAS_LOG_V6_EPOW_XMODIFIER_PARTITION_SPECIFIC; + + qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->epow_irq)); +} + +static void check_exception(sPAPREnvironment *spapr, + uint32_t token, uint32_t nargs, + target_ulong args, + uint32_t nret, target_ulong rets) +{ + uint32_t mask, buf, len; + uint64_t xinfo; + + if ((nargs < 6) || (nargs > 7) || nret != 1) { + rtas_st(rets, 0, -3); + return; + } + + xinfo = rtas_ld(args, 1); + mask = rtas_ld(args, 2); + buf = rtas_ld(args, 4); + len = rtas_ld(args, 5); + if (nargs == 7) { + xinfo |= (uint64_t)rtas_ld(args, 6) << 32; + } + + if ((mask & EVENT_MASK_EPOW) && pending_epow) { + if (sizeof(*pending_epow) < len) { + len = sizeof(*pending_epow); + } + + cpu_physical_memory_write(buf, pending_epow, len); + g_free(pending_epow); + pending_epow = NULL; + rtas_st(rets, 0, 0); + } else { + rtas_st(rets, 0, 1); + } +} + +void spapr_events_init(sPAPREnvironment *spapr) +{ + spapr->epow_irq = spapr_allocate_msi(0); + spapr->epow_notifier.notify = spapr_powerdown_req; + qemu_register_powerdown_notifier(&spapr->epow_notifier); + spapr_rtas_register("check-exception", check_exception); +} From d6a6d362aa291686d3111aed59ab57badaaef463 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 8 Oct 2012 13:02:20 +0200 Subject: [PATCH 1212/2270] ac97: convert PIO to new memory api read/write Signed-off-by: Alexander Graf --- hw/ac97.c | 109 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 20 deletions(-) diff --git a/hw/ac97.c b/hw/ac97.c index 0f561fa5c1..ce6a1dc609 100644 --- a/hw/ac97.c +++ b/hw/ac97.c @@ -1226,32 +1226,101 @@ static const VMStateDescription vmstate_ac97 = { } }; -static const MemoryRegionPortio nam_portio[] = { - { 0, 256 * 1, 1, .read = nam_readb, }, - { 0, 256 * 2, 2, .read = nam_readw, }, - { 0, 256 * 4, 4, .read = nam_readl, }, - { 0, 256 * 1, 1, .write = nam_writeb, }, - { 0, 256 * 2, 2, .write = nam_writew, }, - { 0, 256 * 4, 4, .write = nam_writel, }, - PORTIO_END_OF_LIST (), -}; +static uint64_t nam_read(void *opaque, hwaddr addr, unsigned size) +{ + if ((addr / size) > 256) { + return -1; + } + + switch (size) { + case 1: + return nam_readb(opaque, addr); + case 2: + return nam_readw(opaque, addr); + case 4: + return nam_readl(opaque, addr); + default: + return -1; + } +} + +static void nam_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + if ((addr / size) > 256) { + return; + } + + switch (size) { + case 1: + nam_writeb(opaque, addr, val); + break; + case 2: + nam_writew(opaque, addr, val); + break; + case 4: + nam_writel(opaque, addr, val); + break; + } +} static const MemoryRegionOps ac97_io_nam_ops = { - .old_portio = nam_portio, + .read = nam_read, + .write = nam_write, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, + .endianness = DEVICE_LITTLE_ENDIAN, }; -static const MemoryRegionPortio nabm_portio[] = { - { 0, 64 * 1, 1, .read = nabm_readb, }, - { 0, 64 * 2, 2, .read = nabm_readw, }, - { 0, 64 * 4, 4, .read = nabm_readl, }, - { 0, 64 * 1, 1, .write = nabm_writeb, }, - { 0, 64 * 2, 2, .write = nabm_writew, }, - { 0, 64 * 4, 4, .write = nabm_writel, }, - PORTIO_END_OF_LIST () -}; +static uint64_t nabm_read(void *opaque, hwaddr addr, unsigned size) +{ + if ((addr / size) > 64) { + return -1; + } + + switch (size) { + case 1: + return nabm_readb(opaque, addr); + case 2: + return nabm_readw(opaque, addr); + case 4: + return nabm_readl(opaque, addr); + default: + return -1; + } +} + +static void nabm_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + if ((addr / size) > 64) { + return; + } + + switch (size) { + case 1: + nabm_writeb(opaque, addr, val); + break; + case 2: + nabm_writew(opaque, addr, val); + break; + case 4: + nabm_writel(opaque, addr, val); + break; + } +} + static const MemoryRegionOps ac97_io_nabm_ops = { - .old_portio = nabm_portio, + .read = nabm_read, + .write = nabm_write, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, + .endianness = DEVICE_LITTLE_ENDIAN, }; static void ac97_on_reset (void *opaque) From df6db5b32ab776a1d23bd32ae75c0e5284a01234 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 8 Oct 2012 13:02:30 +0200 Subject: [PATCH 1213/2270] virtio-pci: convert PIO to new memory api read/write Signed-off-by: Alexander Graf --- hw/virtio-pci.c | 128 +++++++++++++++++++----------------------------- 1 file changed, 50 insertions(+), 78 deletions(-) diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index c7f20c36a2..96031500ee 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -374,52 +374,39 @@ static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr) return ret; } -static uint32_t virtio_pci_config_readb(void *opaque, uint32_t addr) +static uint64_t virtio_pci_config_read(void *opaque, hwaddr addr, + unsigned size) { VirtIOPCIProxy *proxy = opaque; uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev); - if (addr < config) + uint64_t val = 0; + if (addr < config) { return virtio_ioport_read(proxy, addr); + } addr -= config; - return virtio_config_readb(proxy->vdev, addr); -} -static uint32_t virtio_pci_config_readw(void *opaque, uint32_t addr) -{ - VirtIOPCIProxy *proxy = opaque; - uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev); - uint16_t val; - if (addr < config) - return virtio_ioport_read(proxy, addr); - addr -= config; - val = virtio_config_readw(proxy->vdev, addr); - if (virtio_is_big_endian()) { - /* - * virtio is odd, ioports are LE but config space is target native - * endian. However, in qemu, all PIO is LE, so we need to re-swap - * on BE targets - */ - val = bswap16(val); + switch (size) { + case 1: + val = virtio_config_readb(proxy->vdev, addr); + break; + case 2: + val = virtio_config_readw(proxy->vdev, addr); + if (virtio_is_big_endian()) { + val = bswap16(val); + } + break; + case 4: + val = virtio_config_readl(proxy->vdev, addr); + if (virtio_is_big_endian()) { + val = bswap32(val); + } + break; } return val; } -static uint32_t virtio_pci_config_readl(void *opaque, uint32_t addr) -{ - VirtIOPCIProxy *proxy = opaque; - uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev); - uint32_t val; - if (addr < config) - return virtio_ioport_read(proxy, addr); - addr -= config; - val = virtio_config_readl(proxy->vdev, addr); - if (virtio_is_big_endian()) { - val = bswap32(val); - } - return val; -} - -static void virtio_pci_config_writeb(void *opaque, uint32_t addr, uint32_t val) +static void virtio_pci_config_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) { VirtIOPCIProxy *proxy = opaque; uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev); @@ -428,51 +415,36 @@ static void virtio_pci_config_writeb(void *opaque, uint32_t addr, uint32_t val) return; } addr -= config; - virtio_config_writeb(proxy->vdev, addr, val); + /* + * Virtio-PCI is odd. Ioports are LE but config space is target native + * endian. + */ + switch (size) { + case 1: + virtio_config_writeb(proxy->vdev, addr, val); + break; + case 2: + if (virtio_is_big_endian()) { + val = bswap16(val); + } + virtio_config_writew(proxy->vdev, addr, val); + break; + case 4: + if (virtio_is_big_endian()) { + val = bswap32(val); + } + virtio_config_writel(proxy->vdev, addr, val); + break; + } } -static void virtio_pci_config_writew(void *opaque, uint32_t addr, uint32_t val) -{ - VirtIOPCIProxy *proxy = opaque; - uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev); - if (addr < config) { - virtio_ioport_write(proxy, addr, val); - return; - } - addr -= config; - if (virtio_is_big_endian()) { - val = bswap16(val); - } - virtio_config_writew(proxy->vdev, addr, val); -} - -static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val) -{ - VirtIOPCIProxy *proxy = opaque; - uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev); - if (addr < config) { - virtio_ioport_write(proxy, addr, val); - return; - } - addr -= config; - if (virtio_is_big_endian()) { - val = bswap32(val); - } - virtio_config_writel(proxy->vdev, addr, val); -} - -static const MemoryRegionPortio virtio_portio[] = { - { 0, 0x10000, 1, .write = virtio_pci_config_writeb, }, - { 0, 0x10000, 2, .write = virtio_pci_config_writew, }, - { 0, 0x10000, 4, .write = virtio_pci_config_writel, }, - { 0, 0x10000, 1, .read = virtio_pci_config_readb, }, - { 0, 0x10000, 2, .read = virtio_pci_config_readw, }, - { 0, 0x10000, 4, .read = virtio_pci_config_readl, }, - PORTIO_END_OF_LIST() -}; - static const MemoryRegionOps virtio_pci_config_ops = { - .old_portio = virtio_portio, + .read = virtio_pci_config_read, + .write = virtio_pci_config_write, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, .endianness = DEVICE_LITTLE_ENDIAN, }; From f3726fd78d79693b73c1ac41cc8ca0f1bb90082b Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 8 Oct 2012 13:09:44 +0200 Subject: [PATCH 1214/2270] es1370: convert PIO to new memory api read/write Signed-off-by: Alexander Graf --- hw/es1370.c | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/hw/es1370.c b/hw/es1370.c index e34234c350..e0c9729dc9 100644 --- a/hw/es1370.c +++ b/hw/es1370.c @@ -908,18 +908,44 @@ static void es1370_adc_callback (void *opaque, int avail) es1370_run_channel (s, ADC_CHANNEL, avail); } -static const MemoryRegionPortio es1370_portio[] = { - { 0, 0x40 * 4, 1, .write = es1370_writeb, }, - { 0, 0x40 * 2, 2, .write = es1370_writew, }, - { 0, 0x40, 4, .write = es1370_writel, }, - { 0, 0x40 * 4, 1, .read = es1370_readb, }, - { 0, 0x40 * 2, 2, .read = es1370_readw, }, - { 0, 0x40, 4, .read = es1370_readl, }, - PORTIO_END_OF_LIST () -}; +static uint64_t es1370_read(void *opaque, hwaddr addr, + unsigned size) +{ + switch (size) { + case 1: + return es1370_readb(opaque, addr); + case 2: + return es1370_readw(opaque, addr); + case 4: + return es1370_readl(opaque, addr); + default: + return -1; + } +} + +static void es1370_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + switch (size) { + case 1: + es1370_writeb(opaque, addr, val); + break; + case 2: + es1370_writew(opaque, addr, val); + break; + case 4: + es1370_writel(opaque, addr, val); + break; + } +} static const MemoryRegionOps es1370_io_ops = { - .old_portio = es1370_portio, + .read = es1370_read, + .write = es1370_write, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, .endianness = DEVICE_LITTLE_ENDIAN, }; From 0505bcdec8228d8de39ab1a02644e71999e7c052 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 8 Oct 2012 13:12:31 +0200 Subject: [PATCH 1215/2270] i8254: convert PIO to new memory api read/write Signed-off-by: Alexander Graf --- hw/i8254.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/hw/i8254.c b/hw/i8254.c index 77bd5e8222..bea5f92fd2 100644 --- a/hw/i8254.c +++ b/hw/i8254.c @@ -111,7 +111,8 @@ static void pit_latch_count(PITChannelState *s) } } -static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val) +static void pit_ioport_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) { PITCommonState *pit = opaque; int channel, access; @@ -178,7 +179,8 @@ static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val) } } -static uint32_t pit_ioport_read(void *opaque, uint32_t addr) +static uint64_t pit_ioport_read(void *opaque, hwaddr addr, + unsigned size) { PITCommonState *pit = opaque; int ret, count; @@ -290,14 +292,14 @@ static void pit_irq_control(void *opaque, int n, int enable) } } -static const MemoryRegionPortio pit_portio[] = { - { 0, 4, 1, .write = pit_ioport_write }, - { 0, 3, 1, .read = pit_ioport_read }, - PORTIO_END_OF_LIST() -}; - static const MemoryRegionOps pit_ioport_ops = { - .old_portio = pit_portio + .read = pit_ioport_read, + .write = pit_ioport_write, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, + .endianness = DEVICE_LITTLE_ENDIAN, }; static void pit_post_load(PITCommonState *s) From 087bd055acf29e838908a9e6bfad73f12c49bc4c Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 8 Oct 2012 13:19:48 +0200 Subject: [PATCH 1216/2270] m48t59: convert PIO to new memory api read/write Signed-off-by: Alexander Graf --- hw/m48t59.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/hw/m48t59.c b/hw/m48t59.c index 9eb1a0968a..9e8e692669 100644 --- a/hw/m48t59.c +++ b/hw/m48t59.c @@ -27,6 +27,7 @@ #include "sysemu.h" #include "sysbus.h" #include "isa.h" +#include "exec-memory.h" //#define DEBUG_NVRAM @@ -80,6 +81,7 @@ typedef struct M48t59ISAState { typedef struct M48t59SysBusState { SysBusDevice busdev; M48t59State state; + MemoryRegion io; } M48t59SysBusState; /* Fake timer functions */ @@ -481,7 +483,8 @@ void m48t59_toggle_lock (void *opaque, int lock) } /* IO access to NVRAM */ -static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val) +static void NVRAM_writeb(void *opaque, hwaddr addr, uint64_t val, + unsigned size) { M48t59State *NVRAM = opaque; @@ -504,7 +507,7 @@ static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val) } } -static uint32_t NVRAM_readb (void *opaque, uint32_t addr) +static uint64_t NVRAM_readb(void *opaque, hwaddr addr, unsigned size) { M48t59State *NVRAM = opaque; uint32_t retval; @@ -626,13 +629,14 @@ static void m48t59_reset_sysbus(DeviceState *d) m48t59_reset_common(NVRAM); } -static const MemoryRegionPortio m48t59_portio[] = { - {0, 4, 1, .read = NVRAM_readb, .write = NVRAM_writeb }, - PORTIO_END_OF_LIST(), -}; - static const MemoryRegionOps m48t59_io_ops = { - .old_portio = m48t59_portio, + .read = NVRAM_readb, + .write = NVRAM_writeb, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, + .endianness = DEVICE_LITTLE_ENDIAN, }; /* Initialisation routine */ @@ -653,9 +657,9 @@ M48t59State *m48t59_init(qemu_irq IRQ, hwaddr mem_base, d = FROM_SYSBUS(M48t59SysBusState, s); state = &d->state; sysbus_connect_irq(s, 0, IRQ); + memory_region_init_io(&d->io, &m48t59_io_ops, state, "m48t59", 4); if (io_base != 0) { - register_ioport_read(io_base, 0x04, 1, NVRAM_readb, state); - register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, state); + memory_region_add_subregion(get_system_io(), io_base, &d->io); } if (mem_base != 0) { sysbus_mmio_map(s, 0, mem_base); From 0da8c842b73924fb54ed75fb8850be5f7e978df9 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 8 Oct 2012 13:22:28 +0200 Subject: [PATCH 1217/2270] mc146818rtc: convert PIO to new memory api read/write Signed-off-by: Alexander Graf --- hw/mc146818rtc.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index 332a77d4dc..98839f278d 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -383,7 +383,8 @@ static void rtc_update_timer(void *opaque) check_update_timer(s); } -static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) +static void cmos_ioport_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) { RTCState *s = opaque; @@ -595,7 +596,8 @@ static int update_in_progress(RTCState *s) return 0; } -static uint32_t cmos_ioport_read(void *opaque, uint32_t addr) +static uint64_t cmos_ioport_read(void *opaque, hwaddr addr, + unsigned size) { RTCState *s = opaque; int ret; @@ -769,13 +771,14 @@ static void rtc_reset(void *opaque) #endif } -static const MemoryRegionPortio cmos_portio[] = { - {0, 2, 1, .read = cmos_ioport_read, .write = cmos_ioport_write }, - PORTIO_END_OF_LIST(), -}; - static const MemoryRegionOps cmos_ops = { - .old_portio = cmos_portio + .read = cmos_ioport_read, + .write = cmos_ioport_write, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, + .endianness = DEVICE_LITTLE_ENDIAN, }; static void rtc_get_date(Object *obj, Visitor *v, void *opaque, From 93ef41928299efbd7879bc63f329893e65e6e1de Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 8 Oct 2012 13:24:52 +0200 Subject: [PATCH 1218/2270] pc port92: convert PIO to new memory api read/write Signed-off-by: Alexander Graf --- hw/pc.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/hw/pc.c b/hw/pc.c index 16de04c4b7..a02b397a24 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -421,7 +421,8 @@ typedef struct Port92State { qemu_irq *a20_out; } Port92State; -static void port92_write(void *opaque, uint32_t addr, uint32_t val) +static void port92_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) { Port92State *s = opaque; @@ -433,7 +434,8 @@ static void port92_write(void *opaque, uint32_t addr, uint32_t val) } } -static uint32_t port92_read(void *opaque, uint32_t addr) +static uint64_t port92_read(void *opaque, hwaddr addr, + unsigned size) { Port92State *s = opaque; uint32_t ret; @@ -468,13 +470,14 @@ static void port92_reset(DeviceState *d) s->outport &= ~1; } -static const MemoryRegionPortio port92_portio[] = { - { 0, 1, 1, .read = port92_read, .write = port92_write }, - PORTIO_END_OF_LIST(), -}; - static const MemoryRegionOps port92_ops = { - .old_portio = port92_portio + .read = port92_read, + .write = port92_write, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, + .endianness = DEVICE_LITTLE_ENDIAN, }; static int port92_initfn(ISADevice *dev) From d540bfe0e730ac0b18f58ed5a8355c8ee014f35d Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 8 Oct 2012 13:30:08 +0200 Subject: [PATCH 1219/2270] pckbd: convert PIO to new memory api read/write Signed-off-by: Alexander Graf --- hw/pckbd.c | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/hw/pckbd.c b/hw/pckbd.c index 000c7f00fd..5bb3e0abf3 100644 --- a/hw/pckbd.c +++ b/hw/pckbd.c @@ -194,7 +194,8 @@ static void kbd_update_aux_irq(void *opaque, int level) kbd_update_irq(s); } -static uint32_t kbd_read_status(void *opaque, uint32_t addr) +static uint64_t kbd_read_status(void *opaque, hwaddr addr, + unsigned size) { KBDState *s = opaque; int val; @@ -223,7 +224,8 @@ static void outport_write(KBDState *s, uint32_t val) } } -static void kbd_write_command(void *opaque, uint32_t addr, uint32_t val) +static void kbd_write_command(void *opaque, hwaddr addr, + uint64_t val, unsigned size) { KBDState *s = opaque; @@ -303,12 +305,13 @@ static void kbd_write_command(void *opaque, uint32_t addr, uint32_t val) /* ignore that */ break; default: - fprintf(stderr, "qemu: unsupported keyboard cmd=0x%02x\n", val); + fprintf(stderr, "qemu: unsupported keyboard cmd=0x%02x\n", (int)val); break; } } -static uint32_t kbd_read_data(void *opaque, uint32_t addr) +static uint64_t kbd_read_data(void *opaque, hwaddr addr, + unsigned size) { KBDState *s = opaque; uint32_t val; @@ -322,7 +325,8 @@ static uint32_t kbd_read_data(void *opaque, uint32_t addr) return val; } -static void kbd_write_data(void *opaque, uint32_t addr, uint32_t val) +static void kbd_write_data(void *opaque, hwaddr addr, + uint64_t val, unsigned size) { KBDState *s = opaque; @@ -385,9 +389,9 @@ static uint32_t kbd_mm_readb (void *opaque, hwaddr addr) KBDState *s = opaque; if (addr & s->mask) - return kbd_read_status(s, 0) & 0xff; + return kbd_read_status(s, 0, 1) & 0xff; else - return kbd_read_data(s, 0) & 0xff; + return kbd_read_data(s, 0, 1) & 0xff; } static void kbd_mm_writeb (void *opaque, hwaddr addr, uint32_t value) @@ -395,9 +399,9 @@ static void kbd_mm_writeb (void *opaque, hwaddr addr, uint32_t value) KBDState *s = opaque; if (addr & s->mask) - kbd_write_command(s, 0, value & 0xff); + kbd_write_command(s, 0, value & 0xff, 1); else - kbd_write_data(s, 0, value & 0xff); + kbd_write_data(s, 0, value & 0xff, 1); } static const MemoryRegionOps i8042_mmio_ops = { @@ -459,22 +463,24 @@ static const VMStateDescription vmstate_kbd_isa = { } }; -static const MemoryRegionPortio i8042_data_portio[] = { - { 0, 1, 1, .read = kbd_read_data, .write = kbd_write_data }, - PORTIO_END_OF_LIST() -}; - -static const MemoryRegionPortio i8042_cmd_portio[] = { - { 0, 1, 1, .read = kbd_read_status, .write = kbd_write_command }, - PORTIO_END_OF_LIST() -}; - static const MemoryRegionOps i8042_data_ops = { - .old_portio = i8042_data_portio + .read = kbd_read_data, + .write = kbd_write_data, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, + .endianness = DEVICE_LITTLE_ENDIAN, }; static const MemoryRegionOps i8042_cmd_ops = { - .old_portio = i8042_cmd_portio + .read = kbd_read_status, + .write = kbd_write_command, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, + .endianness = DEVICE_LITTLE_ENDIAN, }; static int i8042_initfn(ISADevice *dev) From 1bebb0ad17dc56f66ad09f35d0ab8a3a6357f548 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 8 Oct 2012 13:35:24 +0200 Subject: [PATCH 1220/2270] rtl8139: convert PIO to new memory api read/write Signed-off-by: Alexander Graf --- hw/rtl8139.c | 78 ++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 42 deletions(-) diff --git a/hw/rtl8139.c b/hw/rtl8139.c index 10ced8ba7d..e3aa8bfb11 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -3187,38 +3187,6 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr) /* */ -static void rtl8139_ioport_writeb(void *opaque, uint32_t addr, uint32_t val) -{ - rtl8139_io_writeb(opaque, addr & 0xFF, val); -} - -static void rtl8139_ioport_writew(void *opaque, uint32_t addr, uint32_t val) -{ - rtl8139_io_writew(opaque, addr & 0xFF, val); -} - -static void rtl8139_ioport_writel(void *opaque, uint32_t addr, uint32_t val) -{ - rtl8139_io_writel(opaque, addr & 0xFF, val); -} - -static uint32_t rtl8139_ioport_readb(void *opaque, uint32_t addr) -{ - return rtl8139_io_readb(opaque, addr & 0xFF); -} - -static uint32_t rtl8139_ioport_readw(void *opaque, uint32_t addr) -{ - return rtl8139_io_readw(opaque, addr & 0xFF); -} - -static uint32_t rtl8139_ioport_readl(void *opaque, uint32_t addr) -{ - return rtl8139_io_readl(opaque, addr & 0xFF); -} - -/* */ - static void rtl8139_mmio_writeb(void *opaque, hwaddr addr, uint32_t val) { rtl8139_io_writeb(opaque, addr & 0xFF, val); @@ -3386,18 +3354,44 @@ static const VMStateDescription vmstate_rtl8139 = { /***********************************************************/ /* PCI RTL8139 definitions */ -static const MemoryRegionPortio rtl8139_portio[] = { - { 0, 0x100, 1, .read = rtl8139_ioport_readb, }, - { 0, 0x100, 1, .write = rtl8139_ioport_writeb, }, - { 0, 0x100, 2, .read = rtl8139_ioport_readw, }, - { 0, 0x100, 2, .write = rtl8139_ioport_writew, }, - { 0, 0x100, 4, .read = rtl8139_ioport_readl, }, - { 0, 0x100, 4, .write = rtl8139_ioport_writel, }, - PORTIO_END_OF_LIST() -}; +static void rtl8139_ioport_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + switch (size) { + case 1: + rtl8139_io_writeb(opaque, addr, val); + break; + case 2: + rtl8139_io_writew(opaque, addr, val); + break; + case 4: + rtl8139_io_writel(opaque, addr, val); + break; + } +} + +static uint64_t rtl8139_ioport_read(void *opaque, hwaddr addr, + unsigned size) +{ + switch (size) { + case 1: + return rtl8139_io_readb(opaque, addr); + case 2: + return rtl8139_io_readw(opaque, addr); + case 4: + return rtl8139_io_readl(opaque, addr); + } + + return -1; +} static const MemoryRegionOps rtl8139_io_ops = { - .old_portio = rtl8139_portio, + .read = rtl8139_ioport_read, + .write = rtl8139_ioport_write, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, .endianness = DEVICE_LITTLE_ENDIAN, }; From 5ec3a23e6c8303c51a244411c57f2456a24799c9 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 8 Oct 2012 13:40:29 +0200 Subject: [PATCH 1221/2270] serial: convert PIO to new memory api read/write Signed-off-by: Alexander Graf --- hw/serial.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/hw/serial.c b/hw/serial.c index ae84b22f35..60283eab91 100644 --- a/hw/serial.c +++ b/hw/serial.c @@ -26,6 +26,7 @@ #include "serial.h" #include "qemu-char.h" #include "qemu-timer.h" +#include "exec-memory.h" //#define DEBUG_SERIAL @@ -305,7 +306,8 @@ static void serial_xmit(void *opaque) } -static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val) +static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) { SerialState *s = opaque; @@ -451,7 +453,7 @@ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val) } } -static uint32_t serial_ioport_read(void *opaque, uint32_t addr) +static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size) { SerialState *s = opaque; uint32_t ret; @@ -620,7 +622,7 @@ static int serial_post_load(void *opaque, int version_id) s->fcr_vmstate = 0; } /* Initialize fcr via setter to perform essential side-effects */ - serial_ioport_write(s, 0x02, s->fcr_vmstate); + serial_ioport_write(s, 0x02, s->fcr_vmstate, 1); serial_update_parameters(s); return 0; } @@ -705,13 +707,14 @@ void serial_set_frequency(SerialState *s, uint32_t frequency) serial_update_parameters(s); } -static const MemoryRegionPortio serial_portio[] = { - { 0, 8, 1, .read = serial_ioport_read, .write = serial_ioport_write }, - PORTIO_END_OF_LIST() -}; - const MemoryRegionOps serial_io_ops = { - .old_portio = serial_portio + .read = serial_ioport_read, + .write = serial_ioport_write, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, + .endianness = DEVICE_LITTLE_ENDIAN, }; SerialState *serial_init(int base, qemu_irq irq, int baudbase, @@ -728,8 +731,9 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase, vmstate_register(NULL, base, &vmstate_serial, s); - register_ioport_write(base, 8, 1, serial_ioport_write, s); - register_ioport_read(base, 8, 1, serial_ioport_read, s); + memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8); + memory_region_add_subregion(get_system_io(), base, &s->io); + return s; } @@ -738,7 +742,7 @@ static uint64_t serial_mm_read(void *opaque, hwaddr addr, unsigned size) { SerialState *s = opaque; - return serial_ioport_read(s, addr >> s->it_shift); + return serial_ioport_read(s, addr >> s->it_shift, 1); } static void serial_mm_write(void *opaque, hwaddr addr, @@ -746,7 +750,7 @@ static void serial_mm_write(void *opaque, hwaddr addr, { SerialState *s = opaque; value &= ~0u >> (32 - (size * 8)); - serial_ioport_write(s, addr >> s->it_shift, value); + serial_ioport_write(s, addr >> s->it_shift, value, 1); } static const MemoryRegionOps serial_mm_ops[3] = { From 360d613e528df695fc0ac89f4069d8877d39ebea Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 8 Oct 2012 13:44:24 +0200 Subject: [PATCH 1222/2270] vmport: convert PIO to new memory api read/write Signed-off-by: Alexander Graf --- hw/vmport.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/hw/vmport.c b/hw/vmport.c index a4f52ee5bb..3ab3a1405c 100644 --- a/hw/vmport.c +++ b/hw/vmport.c @@ -54,7 +54,8 @@ void vmport_register(unsigned char command, IOPortReadFunc *func, void *opaque) port_state->opaque[command] = opaque; } -static uint32_t vmport_ioport_read(void *opaque, uint32_t addr) +static uint64_t vmport_ioport_read(void *opaque, hwaddr addr, + unsigned size) { VMPortState *s = opaque; CPUX86State *env = cpu_single_env; @@ -81,11 +82,12 @@ static uint32_t vmport_ioport_read(void *opaque, uint32_t addr) return s->func[command](s->opaque[command], addr); } -static void vmport_ioport_write(void *opaque, uint32_t addr, uint32_t val) +static void vmport_ioport_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) { CPUX86State *env = cpu_single_env; - env->regs[R_EAX] = vmport_ioport_read(opaque, addr); + env->regs[R_EAX] = vmport_ioport_read(opaque, addr, 4); } static uint32_t vmport_cmd_get_version(void *opaque, uint32_t addr) @@ -121,13 +123,14 @@ void vmmouse_set_data(const uint32_t *data) env->regs[R_ESI] = data[4]; env->regs[R_EDI] = data[5]; } -static const MemoryRegionPortio vmport_portio[] = { - {0, 1, 4, .read = vmport_ioport_read, .write = vmport_ioport_write }, - PORTIO_END_OF_LIST(), -}; - static const MemoryRegionOps vmport_ops = { - .old_portio = vmport_portio + .read = vmport_ioport_read, + .write = vmport_ioport_write, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, + .endianness = DEVICE_LITTLE_ENDIAN, }; static int vmport_initfn(ISADevice *dev) From 626c7a171e644fbe1579516b8b794d611c295d2f Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 8 Oct 2012 13:47:30 +0200 Subject: [PATCH 1223/2270] xen_platform: convert PIO to new memory api read/write Signed-off-by: Alexander Graf --- hw/xen_platform.c | 48 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/hw/xen_platform.c b/hw/xen_platform.c index 890eb72f20..a54e7a2cdb 100644 --- a/hw/xen_platform.c +++ b/hw/xen_platform.c @@ -228,18 +228,46 @@ static void platform_fixed_ioport_reset(void *opaque) platform_fixed_ioport_writeb(s, 0, 0); } -const MemoryRegionPortio xen_platform_ioport[] = { - { 0, 16, 4, .write = platform_fixed_ioport_writel, }, - { 0, 16, 2, .write = platform_fixed_ioport_writew, }, - { 0, 16, 1, .write = platform_fixed_ioport_writeb, }, - { 0, 16, 2, .read = platform_fixed_ioport_readw, }, - { 0, 16, 1, .read = platform_fixed_ioport_readb, }, - PORTIO_END_OF_LIST() -}; +static uint64_t platform_fixed_ioport_read(void *opaque, + hwaddr addr, + unsigned size) +{ + switch (size) { + case 1: + return platform_fixed_ioport_readb(opaque, addr); + case 2: + return platform_fixed_ioport_readw(opaque, addr); + default: + return -1; + } +} + +static void platform_fixed_ioport_write(void *opaque, hwaddr addr, + + uint64_t val, unsigned size) +{ + switch (size) { + case 1: + platform_fixed_ioport_writeb(opaque, addr, val); + break; + case 2: + platform_fixed_ioport_writew(opaque, addr, val); + break; + case 4: + platform_fixed_ioport_writel(opaque, addr, val); + break; + } +} + static const MemoryRegionOps platform_fixed_io_ops = { - .old_portio = xen_platform_ioport, - .endianness = DEVICE_NATIVE_ENDIAN, + .read = platform_fixed_ioport_read, + .write = platform_fixed_ioport_write, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, + .endianness = DEVICE_LITTLE_ENDIAN, }; static void platform_fixed_ioport_init(PCIXenPlatformState* s) From a1bc20dfbb012ea2a5fb1228cb77abd04490fd79 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 8 Oct 2012 12:21:30 +0200 Subject: [PATCH 1224/2270] PPC: e500: Map PIO space into core memory region On PPC, we don't have PIO. So usually PIO space behind a PCI bridge is accessible via MMIO. Do this mapping explicitly by mapping the PIO space of our PCI bus into a memory region that lives in memory space. Signed-off-by: Alexander Graf --- hw/ppc/e500.c | 3 +-- hw/ppce500_pci.c | 9 +++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 90d88ebc74..6749ffffb3 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -52,7 +52,6 @@ #define MPC8544_PCI_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x8000ULL) #define MPC8544_PCI_REGS_SIZE 0x1000ULL #define MPC8544_PCI_IO 0xE1000000ULL -#define MPC8544_PCI_IOLEN 0x10000ULL #define MPC8544_UTIL_BASE (MPC8544_CCSRBAR_BASE + 0xe0000ULL) #define MPC8544_SPIN_BASE 0xEF000000ULL @@ -511,7 +510,7 @@ void ppce500_init(PPCE500Params *params) if (!pci_bus) printf("couldn't create PCI controller!\n"); - isa_mmio_init(MPC8544_PCI_IO, MPC8544_PCI_IOLEN); + sysbus_mmio_map(sysbus_from_qdev(dev), 1, MPC8544_PCI_IO); if (pci_bus) { /* Register network interfaces. */ diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 332748a6de..2ff7438d09 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -31,6 +31,8 @@ #define PCIE500_ALL_SIZE 0x1000 #define PCIE500_REG_SIZE (PCIE500_ALL_SIZE - PCIE500_REG_BASE) +#define PCIE500_PCI_IOLEN 0x10000ULL + #define PPCE500_PCI_CONFIG_ADDR 0x0 #define PPCE500_PCI_CONFIG_DATA 0x4 #define PPCE500_PCI_INTACK 0x8 @@ -87,6 +89,7 @@ struct PPCE500PCIState { /* mmio maps */ MemoryRegion container; MemoryRegion iomem; + MemoryRegion pio; }; typedef struct PPCE500PCIState PPCE500PCIState; @@ -314,7 +317,6 @@ static int e500_pcihost_initfn(SysBusDevice *dev) PCIBus *b; int i; MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *address_space_io = get_system_io(); h = PCI_HOST_BRIDGE(dev); s = PPC_E500_PCI_HOST_BRIDGE(dev); @@ -323,9 +325,11 @@ static int e500_pcihost_initfn(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq[i]); } + memory_region_init(&s->pio, "pci-pio", PCIE500_PCI_IOLEN); + b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq, mpc85xx_pci_map_irq, s->irq, address_space_mem, - address_space_io, PCI_DEVFN(0x11, 0), 4); + &s->pio, PCI_DEVFN(0x11, 0), 4); h->bus = b; pci_create_simple(b, 0, "e500-host-bridge"); @@ -341,6 +345,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev) memory_region_add_subregion(&s->container, PCIE500_CFGDATA, &h->data_mem); memory_region_add_subregion(&s->container, PCIE500_REG_BASE, &s->iomem); sysbus_init_mmio(dev, &s->container); + sysbus_init_mmio(dev, &s->pio); return 0; } From a178274efabcbbc5d44805b51def874e47051325 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 8 Oct 2012 13:54:18 +0200 Subject: [PATCH 1225/2270] PPC: pseries: Remove hack for PIO window Now that all users of old_portio are gone, we can remove the hack that enabled us to support them. Signed-off-by: Alexander Graf --- hw/spapr_pci.c | 44 +------------------------------------------- hw/spapr_pci.h | 2 +- 2 files changed, 2 insertions(+), 44 deletions(-) diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index a08ed11166..c2c3079d21 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -439,43 +439,6 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level) qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level); } -static uint64_t spapr_io_read(void *opaque, hwaddr addr, - unsigned size) -{ - switch (size) { - case 1: - return cpu_inb(addr); - case 2: - return cpu_inw(addr); - case 4: - return cpu_inl(addr); - } - assert(0); -} - -static void spapr_io_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size) -{ - switch (size) { - case 1: - cpu_outb(addr, data); - return; - case 2: - cpu_outw(addr, data); - return; - case 4: - cpu_outl(addr, data); - return; - } - assert(0); -} - -static const MemoryRegionOps spapr_io_ops = { - .endianness = DEVICE_LITTLE_ENDIAN, - .read = spapr_io_read, - .write = spapr_io_write -}; - /* * MSI/MSIX memory region implementation. * The handler handles both MSI and MSIX. @@ -545,14 +508,9 @@ static int spapr_phb_init(SysBusDevice *s) * old_portion are updated */ sprintf(namebuf, "%s.io", sphb->dtbusname); memory_region_init(&sphb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE); - /* FIXME: fix to support multiple PHBs */ - memory_region_add_subregion(get_system_io(), 0, &sphb->iospace); - sprintf(namebuf, "%s.io-alias", sphb->dtbusname); - memory_region_init_io(&sphb->iowindow, &spapr_io_ops, sphb, - namebuf, SPAPR_PCI_IO_WIN_SIZE); memory_region_add_subregion(get_system_memory(), sphb->io_win_addr, - &sphb->iowindow); + &sphb->iospace); /* As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors, * we need to allocate some memory to catch those writes coming diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index e307ac8035..a77d7d5448 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -44,7 +44,7 @@ typedef struct sPAPRPHBState { MemoryRegion memspace, iospace; hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size; hwaddr msi_win_addr; - MemoryRegion memwindow, iowindow, msiwindow; + MemoryRegion memwindow, msiwindow; uint32_t dma_liobn; uint64_t dma_window_start; From d6e65d54f0fa980f891aa3166d85b6ffd7d541eb Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 2 Oct 2012 13:21:54 -0600 Subject: [PATCH 1226/2270] pci: Helper function for testing if an INTx route changed Signed-off-by: Alex Williamson Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 5 +++++ hw/pci.h | 1 + 2 files changed, 6 insertions(+) diff --git a/hw/pci.c b/hw/pci.c index d44fd0e10a..8c6b3d19ae 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1121,6 +1121,11 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) return bus->route_intx_to_irq(bus->irq_opaque, pin); } +bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new) +{ + return old->mode != new->mode || old->irq != new->irq; +} + void pci_bus_fire_intx_routing_notifier(PCIBus *bus) { PCIDevice *dev; diff --git a/hw/pci.h b/hw/pci.h index 1f902f5b59..a852941a5c 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -326,6 +326,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name, uint8_t devfn_min, int nirq); void pci_bus_set_route_irq_fn(PCIBus *, pci_route_irq_fn); PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin); +bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new); void pci_bus_fire_intx_routing_notifier(PCIBus *bus); void pci_device_set_intx_routing_notifier(PCIDevice *dev, PCIINTxRoutingNotifier notifier); From 4774d7b258e0c4a6595a7b0bc6960c1751365bbf Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 2 Oct 2012 13:22:01 -0600 Subject: [PATCH 1227/2270] pci-assign: Use pci_intx_route_changed() Replace open coded version Signed-off-by: Alex Williamson Signed-off-by: Michael S. Tsirkin --- hw/kvm/pci-assign.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/kvm/pci-assign.c b/hw/kvm/pci-assign.c index bfffbab1b3..ab01205666 100644 --- a/hw/kvm/pci-assign.c +++ b/hw/kvm/pci-assign.c @@ -882,8 +882,7 @@ static int assign_intx(AssignedDevice *dev) intx_route = pci_device_route_intx_to_irq(&dev->dev, dev->intpin); assert(intx_route.mode != PCI_INTX_INVERTED); - if (dev->intx_route.mode == intx_route.mode && - dev->intx_route.irq == intx_route.irq) { + if (!pci_intx_route_changed(&dev->intx_route, &intx_route)) { return 0; } From 39b9bc626a436837f0068cb600aaf91c0e8aa937 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 2 Oct 2012 13:22:07 -0600 Subject: [PATCH 1228/2270] msi: Add msi_get_message() vfio-pci and pci-assign both do this on their own for setting up direct MSI injection through KVM. Provide a helper function for this in MSI code. Signed-off-by: Alex Williamson Signed-off-by: Michael S. Tsirkin --- hw/msi.c | 45 +++++++++++++++++++++++++++++---------------- hw/msi.h | 1 + 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/hw/msi.c b/hw/msi.c index e2273a09ae..33037a80e9 100644 --- a/hw/msi.c +++ b/hw/msi.c @@ -122,6 +122,31 @@ void msi_set_message(PCIDevice *dev, MSIMessage msg) pci_set_word(dev->config + msi_data_off(dev, msi64bit), msg.data); } +MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector) +{ + uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev)); + bool msi64bit = flags & PCI_MSI_FLAGS_64BIT; + unsigned int nr_vectors = msi_nr_vectors(flags); + MSIMessage msg; + + assert(vector < nr_vectors); + + if (msi64bit) { + msg.address = pci_get_quad(dev->config + msi_address_lo_off(dev)); + } else { + msg.address = pci_get_long(dev->config + msi_address_lo_off(dev)); + } + + /* upper bit 31:16 is zero */ + msg.data = pci_get_word(dev->config + msi_data_off(dev, msi64bit)); + if (nr_vectors > 1) { + msg.data &= ~(nr_vectors - 1); + msg.data |= vector; + } + + return msg; +} + bool msi_enabled(const PCIDevice *dev) { return msi_present(dev) && @@ -249,8 +274,7 @@ void msi_notify(PCIDevice *dev, unsigned int vector) uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev)); bool msi64bit = flags & PCI_MSI_FLAGS_64BIT; unsigned int nr_vectors = msi_nr_vectors(flags); - uint64_t address; - uint32_t data; + MSIMessage msg; assert(vector < nr_vectors); if (msi_is_masked(dev, vector)) { @@ -261,24 +285,13 @@ void msi_notify(PCIDevice *dev, unsigned int vector) return; } - if (msi64bit) { - address = pci_get_quad(dev->config + msi_address_lo_off(dev)); - } else { - address = pci_get_long(dev->config + msi_address_lo_off(dev)); - } - - /* upper bit 31:16 is zero */ - data = pci_get_word(dev->config + msi_data_off(dev, msi64bit)); - if (nr_vectors > 1) { - data &= ~(nr_vectors - 1); - data |= vector; - } + msg = msi_get_message(dev, vector); MSI_DEV_PRINTF(dev, "notify vector 0x%x" " address: 0x%"PRIx64" data: 0x%"PRIx32"\n", - vector, address, data); - stl_le_phys(address, data); + vector, msg.address, msg.data); + stl_le_phys(msg.address, msg.data); } /* Normally called by pci_default_write_config(). */ diff --git a/hw/msi.h b/hw/msi.h index 6ec1f99f80..150b09a19d 100644 --- a/hw/msi.h +++ b/hw/msi.h @@ -32,6 +32,7 @@ struct MSIMessage { extern bool msi_supported; void msi_set_message(PCIDevice *dev, MSIMessage msg); +MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector); bool msi_enabled(const PCIDevice *dev); int msi_init(struct PCIDevice *dev, uint8_t offset, unsigned int nr_vectors, bool msi64bit, bool msi_per_vector_mask); From 2b199f9318ec698dfced65f5d4ad9729f166e37c Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 2 Oct 2012 13:22:14 -0600 Subject: [PATCH 1229/2270] pci-assign: Use msi_get_message() pci-assign only uses a subset of the flexibility msi_get_message() provides, but it's still worthwhile to use it. Signed-off-by: Alex Williamson Signed-off-by: Michael S. Tsirkin --- hw/kvm/pci-assign.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/hw/kvm/pci-assign.c b/hw/kvm/pci-assign.c index ab01205666..e80dad009c 100644 --- a/hw/kvm/pci-assign.c +++ b/hw/kvm/pci-assign.c @@ -996,12 +996,9 @@ static void assigned_dev_update_msi(PCIDevice *pci_dev) } if (ctrl_byte & PCI_MSI_FLAGS_ENABLE) { - uint8_t *pos = pci_dev->config + pci_dev->msi_cap; - MSIMessage msg; + MSIMessage msg = msi_get_message(pci_dev, 0); int virq; - msg.address = pci_get_long(pos + PCI_MSI_ADDRESS_LO); - msg.data = pci_get_word(pos + PCI_MSI_DATA_32); virq = kvm_irqchip_add_msi_route(kvm_state, msg); if (virq < 0) { perror("assigned_dev_update_msi: kvm_irqchip_add_msi_route"); From 05c0621e64b425d9f89bef542f0b85e61dc57ff8 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 17 Oct 2012 16:13:12 -0600 Subject: [PATCH 1230/2270] pci: Return PCI_INTX_DISABLED when no bus INTx routing support Rather than assert, simply return PCI_INTX_DISABLED when we don't have a pci_route_irq_fn. PIIX already returns DISABLED for an invalid pin, so users already deal with this state. Users of this interface should only be acting on an ENABLED or INVERTED return value (though we really have no support for INVERTED). Also complain loudly when we hit this so we don't forget it's missing. Signed-off-by: Alex Williamson Signed-off-by: Michael S. Tsirkin Acked-by: Jan Kiszka --- hw/pci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hw/pci.c b/hw/pci.c index 8c6b3d19ae..70b5fd965b 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1117,7 +1117,13 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) pin = bus->map_irq(dev, pin); dev = bus->parent_dev; } while (dev); - assert(bus->route_intx_to_irq); + + if (!bus->route_intx_to_irq) { + error_report("PCI: Bug - unimplemented PCI INTx routing (%s)\n", + object_get_typename(OBJECT(bus->qbus.parent))); + return (PCIINTxRoute) { PCI_INTX_DISABLED, -1 }; + } + return bus->route_intx_to_irq(bus->irq_opaque, pin); } From dc59944bc9a5ad784572eea57610de60e4a2f4e5 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 18 Oct 2012 00:15:48 +0200 Subject: [PATCH 1231/2270] qemu: enable PV EOI for qemu 1.3 Enable KVM PV EOI by default. You can still disable it with -kvm_pv_eoi cpu flag. To avoid breaking cross-version migration, enable only for qemu 1.3 (or in the future, newer) machine type. Signed-off-by: Michael S. Tsirkin --- hw/pc_piix.c | 9 ++++++++- target-i386/cpu.c | 33 ++++++++++++++++++++------------- target-i386/cpu.h | 2 ++ 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index c7dd75b0c0..85529b2cea 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -43,6 +43,7 @@ #include "xen.h" #include "memory.h" #include "exec-memory.h" +#include "cpu.h" #ifdef CONFIG_XEN # include #endif @@ -302,6 +303,12 @@ static void pc_init_pci(QEMUMachineInitArgs *args) initrd_filename, cpu_model, 1, 1); } +static void pc_init_pci_1_3(QEMUMachineInitArgs *args) +{ + enable_kvm_pv_eoi(); + pc_init_pci(args); +} + static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args) { ram_addr_t ram_size = args->ram_size; @@ -349,7 +356,7 @@ static QEMUMachine pc_machine_v1_3 = { .name = "pc-1.3", .alias = "pc", .desc = "Standard PC", - .init = pc_init_pci, + .init = pc_init_pci_1_3, .max_cpus = 255, .is_default = 1, }; diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 6411042b79..d4f2e65cd9 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -125,6 +125,25 @@ typedef struct model_features_t { int check_cpuid = 0; int enforce_cpuid = 0; +#if defined(CONFIG_KVM) +static uint32_t kvm_default_features = (1 << KVM_FEATURE_CLOCKSOURCE) | + (1 << KVM_FEATURE_NOP_IO_DELAY) | + (1 << KVM_FEATURE_MMU_OP) | + (1 << KVM_FEATURE_CLOCKSOURCE2) | + (1 << KVM_FEATURE_ASYNC_PF) | + (1 << KVM_FEATURE_STEAL_TIME) | + (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT); +static const uint32_t kvm_pv_eoi_features = (0x1 << KVM_FEATURE_PV_EOI); +#else +static uint32_t kvm_default_features = 0; +static const uint32_t kvm_pv_eoi_features = 0; +#endif + +void enable_kvm_pv_eoi(void) +{ + kvm_default_features |= kvm_pv_eoi_features; +} + void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { @@ -1108,7 +1127,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) /* Features to be added*/ uint32_t plus_features = 0, plus_ext_features = 0; uint32_t plus_ext2_features = 0, plus_ext3_features = 0; - uint32_t plus_kvm_features = 0, plus_svm_features = 0; + uint32_t plus_kvm_features = kvm_default_features, plus_svm_features = 0; uint32_t plus_7_0_ebx_features = 0; /* Features to be removed */ uint32_t minus_features = 0, minus_ext_features = 0; @@ -1128,18 +1147,6 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) memcpy(x86_cpu_def, def, sizeof(*def)); } -#if defined(CONFIG_KVM) - plus_kvm_features = (1 << KVM_FEATURE_CLOCKSOURCE) | - (1 << KVM_FEATURE_NOP_IO_DELAY) | - (1 << KVM_FEATURE_MMU_OP) | - (1 << KVM_FEATURE_CLOCKSOURCE2) | - (1 << KVM_FEATURE_ASYNC_PF) | - (1 << KVM_FEATURE_STEAL_TIME) | - (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT); -#else - plus_kvm_features = 0; -#endif - add_flagname_to_bitmaps("hypervisor", &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features, &plus_kvm_features, &plus_svm_features, &plus_7_0_ebx_features); diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 871c270116..de33303dea 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1188,4 +1188,6 @@ void do_smm_enter(CPUX86State *env1); void cpu_report_tpr_access(CPUX86State *env, TPRAccess access); +void enable_kvm_pv_eoi(void); + #endif /* CPU_I386_H */ From e26631b74663f59b5873a84ed5b92ee4ddf48255 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 22 Oct 2012 12:35:00 +0200 Subject: [PATCH 1232/2270] pci: make each capability DWORD aligned PCI spec (see e.g. 6.7 Capabilities List in spec rev 3.0) requires that each capability is DWORD aligned. Ensure this when allocating space by rounding size up to 4. Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index 70b5fd965b..35cb374845 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1906,7 +1906,7 @@ int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, config[PCI_CAP_LIST_NEXT] = pdev->config[PCI_CAPABILITY_LIST]; pdev->config[PCI_CAPABILITY_LIST] = offset; pdev->config[PCI_STATUS] |= PCI_STATUS_CAP_LIST; - memset(pdev->used + offset, 0xFF, size); + memset(pdev->used + offset, 0xFF, QEMU_ALIGN_UP(size, 4)); /* Make capability read-only by default */ memset(pdev->wmask + offset, 0, size); /* Check capability by default */ @@ -1926,7 +1926,7 @@ void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size) memset(pdev->w1cmask + offset, 0, size); /* Clear cmask as device-specific registers can't be checked */ memset(pdev->cmask + offset, 0, size); - memset(pdev->used + offset, 0, size); + memset(pdev->used + offset, 0, QEMU_ALIGN_UP(size, 4)); if (!pdev->config[PCI_CAPABILITY_LIST]) pdev->config[PCI_STATUS] &= ~PCI_STATUS_CAP_LIST; From b56d701f1d1f1828c9fabea535b3460857546dd0 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Fri, 19 Oct 2012 16:43:28 -0400 Subject: [PATCH 1233/2270] pci: pci capability must be in PCI space pci capability must be in PCI space. It can't lay in PCIe extended config space. Reviewed-by: Paolo Bonzini Signed-off-by: Isaku Yamahata Signed-off-by: Jason Baron Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index 35cb374845..82c971a17d 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1678,16 +1678,16 @@ PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name) return pci_create_simple_multifunction(bus, devfn, false, name); } -static int pci_find_space(PCIDevice *pdev, uint8_t size) +static uint8_t pci_find_space(PCIDevice *pdev, uint8_t size) { - int config_size = pci_config_size(pdev); int offset = PCI_CONFIG_HEADER_SIZE; int i; - for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i) + for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i) { if (pdev->used[i]) offset = i + 1; else if (i - offset + 1 == size) return offset; + } return 0; } From 9e38f56183c52e06fc29c64691f59a46d246eec5 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Fri, 19 Oct 2012 16:43:31 -0400 Subject: [PATCH 1234/2270] pci_ids: add intel 82801BA pci-to-pci bridge id Adds pci id constants which will be used by q35. Reviewed-by: Paolo Bonzini Signed-off-by: Isaku Yamahata Signed-off-by: Jason Baron Signed-off-by: Michael S. Tsirkin --- hw/pci_ids.h | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/pci_ids.h b/hw/pci_ids.h index c017a79998..0bfc28f7fb 100644 --- a/hw/pci_ids.h +++ b/hw/pci_ids.h @@ -105,6 +105,7 @@ #define PCI_DEVICE_ID_INTEL_82378 0x0484 #define PCI_DEVICE_ID_INTEL_82441 0x1237 #define PCI_DEVICE_ID_INTEL_82801AA_5 0x2415 +#define PCI_DEVICE_ID_INTEL_82801BA_11 0x244e #define PCI_DEVICE_ID_INTEL_82801D 0x24CD #define PCI_DEVICE_ID_INTEL_ESB_9 0x25ab #define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000 From 91e5615984c1fd5674caad343e750bb5ecd17995 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Fri, 19 Oct 2012 16:43:28 -0400 Subject: [PATCH 1235/2270] pci: introduce pci_swizzle_map_irq_fn() for standardized interrupt pin swizzle Introduce pci_swizzle_map_irq_fn() for interrupt pin swizzle which is standardized. PCI bridge swizzle is common logic, by introducing this function duplicated swizzle logic will be avoided later. [jbaron@redhat.com: drop opaque argument] Reviewed-by: Paolo Bonzini Signed-off-by: Isaku Yamahata Signed-off-by: Jason Baron Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 18 ++++++++++++++++++ hw/pci.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/hw/pci.c b/hw/pci.c index 82c971a17d..63b1857f88 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1155,6 +1155,24 @@ void pci_device_set_intx_routing_notifier(PCIDevice *dev, dev->intx_routing_notifier = notifier; } +/* + * PCI-to-PCI bridge specification + * 9.1: Interrupt routing. Table 9-1 + * + * the PCI Express Base Specification, Revision 2.1 + * 2.2.8.1: INTx interrutp signaling - Rules + * the Implementation Note + * Table 2-20 + */ +/* + * 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD + * 0-origin unlike PCI interrupt pin register. + */ +int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin) +{ + return (pin + PCI_SLOT(pci_dev->devfn)) % PCI_NUM_PINS; +} + /***********************************************************/ /* monitor info on PCI */ diff --git a/hw/pci.h b/hw/pci.h index a852941a5c..241c1d8905 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -318,6 +318,8 @@ void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, void *irq_opaque, int nirq); int pci_bus_get_irq_level(PCIBus *bus, int irq_num); void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev); +/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */ +int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin); PCIBus *pci_register_bus(DeviceState *parent, const char *name, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, void *irq_opaque, From f7748569902f4854ac1223c143edbde4f588040f Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 19 Oct 2012 16:43:31 -0400 Subject: [PATCH 1236/2270] pci: Add class 0xc05 as 'SMBus' [jbaron@redhat.com: add PCI_CLASS_SERIAL_SMBUS definition] Reviewed-by: Paolo Bonzini Signed-off-by: Jan Kiszka Signed-off-by: Jason Baron Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 1 + hw/pci_ids.h | 1 + 2 files changed, 2 insertions(+) diff --git a/hw/pci.c b/hw/pci.c index 63b1857f88..dceda0bdc5 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1237,6 +1237,7 @@ static const pci_class_desc pci_class_descriptions[] = { 0x0c02, "SSA controller", "ssa"}, { 0x0c03, "USB controller", "usb"}, { 0x0c04, "Fibre channel controller", "fibre-channel"}, + { 0x0c05, "SMBus"}, { 0, NULL} }; diff --git a/hw/pci_ids.h b/hw/pci_ids.h index 0bfc28f7fb..41f3570fb9 100644 --- a/hw/pci_ids.h +++ b/hw/pci_ids.h @@ -31,6 +31,7 @@ #define PCI_CLASS_SYSTEM_OTHER 0x0880 #define PCI_CLASS_SERIAL_USB 0x0c03 +#define PCI_CLASS_SERIAL_SMBUS 0x0c05 #define PCI_CLASS_BRIDGE_HOST 0x0600 #define PCI_CLASS_BRIDGE_ISA 0x0601 From c702ddb8daece08b16fce9d6654b38304d385f93 Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Fri, 19 Oct 2012 16:43:32 -0400 Subject: [PATCH 1237/2270] pcie: pass pcie window size to pcie_host_mmcfg_update() This allows q35 to pass/set the size of the pcie window in its update routine. Reviewed-by: Paolo Bonzini Signed-off-by: Jason Baron Signed-off-by: Michael S. Tsirkin --- hw/pcie_host.c | 21 ++++++++++++--------- hw/pcie_host.h | 7 ++++--- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/hw/pcie_host.c b/hw/pcie_host.c index 9f7f3d3b1e..2231d28ec3 100644 --- a/hw/pcie_host.c +++ b/hw/pcie_host.c @@ -107,14 +107,9 @@ static const MemoryRegionOps pcie_mmcfg_ops = { /* pcie_host::base_addr == PCIE_BASE_ADDR_UNMAPPED when it isn't mapped. */ #define PCIE_BASE_ADDR_UNMAPPED ((hwaddr)-1ULL) -int pcie_host_init(PCIExpressHost *e, uint32_t size) +int pcie_host_init(PCIExpressHost *e) { - assert(!(size & (size - 1))); /* power of 2 */ - assert(size >= PCIE_MMCFG_SIZE_MIN); - assert(size <= PCIE_MMCFG_SIZE_MAX); e->base_addr = PCIE_BASE_ADDR_UNMAPPED; - e->size = size; - memory_region_init_io(&e->mmio, &pcie_mmcfg_ops, e, "pcie-mmcfg", e->size); return 0; } @@ -123,22 +118,30 @@ void pcie_host_mmcfg_unmap(PCIExpressHost *e) { if (e->base_addr != PCIE_BASE_ADDR_UNMAPPED) { memory_region_del_subregion(get_system_memory(), &e->mmio); + memory_region_destroy(&e->mmio); e->base_addr = PCIE_BASE_ADDR_UNMAPPED; } } -void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr) +void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr, + uint32_t size) { + assert(!(size & (size - 1))); /* power of 2 */ + assert(size >= PCIE_MMCFG_SIZE_MIN); + assert(size <= PCIE_MMCFG_SIZE_MAX); + e->size = size; + memory_region_init_io(&e->mmio, &pcie_mmcfg_ops, e, "pcie-mmcfg", e->size); e->base_addr = addr; memory_region_add_subregion(get_system_memory(), e->base_addr, &e->mmio); } void pcie_host_mmcfg_update(PCIExpressHost *e, int enable, - hwaddr addr) + hwaddr addr, + uint32_t size) { pcie_host_mmcfg_unmap(e); if (enable) { - pcie_host_mmcfg_map(e, addr); + pcie_host_mmcfg_map(e, addr, size); } } diff --git a/hw/pcie_host.h b/hw/pcie_host.h index 9978b9f2f1..73e88db73e 100644 --- a/hw/pcie_host.h +++ b/hw/pcie_host.h @@ -39,11 +39,12 @@ struct PCIExpressHost { MemoryRegion mmio; }; -int pcie_host_init(PCIExpressHost *e, uint32_t size); +int pcie_host_init(PCIExpressHost *e); void pcie_host_mmcfg_unmap(PCIExpressHost *e); -void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr); +void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr, uint32_t size); void pcie_host_mmcfg_update(PCIExpressHost *e, int enable, - hwaddr addr); + hwaddr addr, + uint32_t size); #endif /* PCIE_HOST_H */ From bc927e488c040c8ef2faed323e8a1a3d0ebbfb62 Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Fri, 19 Oct 2012 16:43:33 -0400 Subject: [PATCH 1238/2270] pcie: Convert PCIExpressHost to use the QOM. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's use PCIExpressHost with QOM. Reviewed-by: Paolo Bonzini Acked-by: Andreas Färber Signed-off-by: Jason Baron Signed-off-by: Michael S. Tsirkin --- hw/pcie_host.c | 14 ++++++++++++++ hw/pcie_host.h | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/hw/pcie_host.c b/hw/pcie_host.c index 2231d28ec3..c257fb43ca 100644 --- a/hw/pcie_host.c +++ b/hw/pcie_host.c @@ -145,3 +145,17 @@ void pcie_host_mmcfg_update(PCIExpressHost *e, pcie_host_mmcfg_map(e, addr, size); } } + +static const TypeInfo pcie_host_type_info = { + .name = TYPE_PCIE_HOST_BRIDGE, + .parent = TYPE_PCI_HOST_BRIDGE, + .abstract = true, + .instance_size = sizeof(PCIExpressHost), +}; + +static void pcie_host_register_types(void) +{ + type_register_static(&pcie_host_type_info); +} + +type_init(pcie_host_register_types) diff --git a/hw/pcie_host.h b/hw/pcie_host.h index 73e88db73e..392193530d 100644 --- a/hw/pcie_host.h +++ b/hw/pcie_host.h @@ -24,6 +24,10 @@ #include "pci_host.h" #include "memory.h" +#define TYPE_PCIE_HOST_BRIDGE "pcie-host-bridge" +#define PCIE_HOST_BRIDGE(obj) \ + OBJECT_CHECK(PCIExpressHost, (obj), TYPE_PCIE_HOST_BRIDGE) + struct PCIExpressHost { PCIHostState pci; From b308c82cbda44e138ef990af64d44a5613c16092 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 25 Oct 2012 12:37:57 +0200 Subject: [PATCH 1239/2270] pci: avoid destroying bridge address space windows in a transaction Calling memory_region_destroy() in a transaction is illegal (and aborts), as until the transaction is committed, the region remains live. Fix by moving destruction until after the transaction commits. This requires having an extra set of regions, so the new and old regions can coexist. Signed-off-by: Avi Kivity Signed-off-by: Anthony Liguori --- hw/pci_bridge.c | 50 ++++++++++++++++++++++++++-------------------- hw/pci_internals.h | 24 ++++++++++++++-------- 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c index 5c6455f6fa..4680501e4e 100644 --- a/hw/pci_bridge.c +++ b/hw/pci_bridge.c @@ -151,58 +151,63 @@ static void pci_bridge_init_alias(PCIBridge *bridge, MemoryRegion *alias, memory_region_add_subregion_overlap(parent_space, base, alias, 1); } -static void pci_bridge_cleanup_alias(MemoryRegion *alias, - MemoryRegion *parent_space) -{ - memory_region_del_subregion(parent_space, alias); - memory_region_destroy(alias); -} - -static void pci_bridge_region_init(PCIBridge *br) +static PCIBridgeWindows *pci_bridge_region_init(PCIBridge *br) { PCIBus *parent = br->dev.bus; + PCIBridgeWindows *w = g_new(PCIBridgeWindows, 1); uint16_t cmd = pci_get_word(br->dev.config + PCI_COMMAND); - pci_bridge_init_alias(br, &br->alias_pref_mem, + pci_bridge_init_alias(br, &w->alias_pref_mem, PCI_BASE_ADDRESS_MEM_PREFETCH, "pci_bridge_pref_mem", &br->address_space_mem, parent->address_space_mem, cmd & PCI_COMMAND_MEMORY); - pci_bridge_init_alias(br, &br->alias_mem, + pci_bridge_init_alias(br, &w->alias_mem, PCI_BASE_ADDRESS_SPACE_MEMORY, "pci_bridge_mem", &br->address_space_mem, parent->address_space_mem, cmd & PCI_COMMAND_MEMORY); - pci_bridge_init_alias(br, &br->alias_io, + pci_bridge_init_alias(br, &w->alias_io, PCI_BASE_ADDRESS_SPACE_IO, "pci_bridge_io", &br->address_space_io, parent->address_space_io, cmd & PCI_COMMAND_IO); /* TODO: optinal VGA and VGA palette snooping support. */ + + return w; } -static void pci_bridge_region_cleanup(PCIBridge *br) +static void pci_bridge_region_del(PCIBridge *br, PCIBridgeWindows *w) { PCIBus *parent = br->dev.bus; - pci_bridge_cleanup_alias(&br->alias_io, - parent->address_space_io); - pci_bridge_cleanup_alias(&br->alias_mem, - parent->address_space_mem); - pci_bridge_cleanup_alias(&br->alias_pref_mem, - parent->address_space_mem); + + memory_region_del_subregion(parent->address_space_io, &w->alias_io); + memory_region_del_subregion(parent->address_space_mem, &w->alias_mem); + memory_region_del_subregion(parent->address_space_mem, &w->alias_pref_mem); +} + +static void pci_bridge_region_cleanup(PCIBridge *br, PCIBridgeWindows *w) +{ + memory_region_destroy(&w->alias_io); + memory_region_destroy(&w->alias_mem); + memory_region_destroy(&w->alias_pref_mem); + g_free(w); } static void pci_bridge_update_mappings(PCIBridge *br) { + PCIBridgeWindows *w = br->windows; + /* Make updates atomic to: handle the case of one VCPU updating the bridge * while another accesses an unaffected region. */ memory_region_transaction_begin(); - pci_bridge_region_cleanup(br); - pci_bridge_region_init(br); + pci_bridge_region_del(br, br->windows); + br->windows = pci_bridge_region_init(br); memory_region_transaction_commit(); + pci_bridge_region_cleanup(br, w); } /* default write_config function for PCI-to-PCI bridge */ @@ -326,7 +331,7 @@ int pci_bridge_initfn(PCIDevice *dev) memory_region_init(&br->address_space_mem, "pci_bridge_pci", INT64_MAX); sec_bus->address_space_io = &br->address_space_io; memory_region_init(&br->address_space_io, "pci_bridge_io", 65536); - pci_bridge_region_init(br); + br->windows = pci_bridge_region_init(br); QLIST_INIT(&sec_bus->child); QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling); return 0; @@ -338,7 +343,8 @@ void pci_bridge_exitfn(PCIDevice *pci_dev) PCIBridge *s = DO_UPCAST(PCIBridge, dev, pci_dev); assert(QLIST_EMPTY(&s->sec_bus.child)); QLIST_REMOVE(&s->sec_bus, sibling); - pci_bridge_region_cleanup(s); + pci_bridge_region_del(s, s->windows); + pci_bridge_region_cleanup(s, s->windows); memory_region_destroy(&s->address_space_mem); memory_region_destroy(&s->address_space_io); /* qbus_free() is called automatically by qdev_free() */ diff --git a/hw/pci_internals.h b/hw/pci_internals.h index c931b64b46..21d0ce6973 100644 --- a/hw/pci_internals.h +++ b/hw/pci_internals.h @@ -40,6 +40,19 @@ struct PCIBus { int *irq_count; }; +typedef struct PCIBridgeWindows PCIBridgeWindows; + +/* + * Aliases for each of the address space windows that the bridge + * can forward. Mapped into the bridge's parent's address space, + * as subregions. + */ +struct PCIBridgeWindows { + MemoryRegion alias_pref_mem; + MemoryRegion alias_mem; + MemoryRegion alias_io; +}; + struct PCIBridge { PCIDevice dev; @@ -55,14 +68,9 @@ struct PCIBridge { */ MemoryRegion address_space_mem; MemoryRegion address_space_io; - /* - * Aliases for each of the address space windows that the bridge - * can forward. Mapped into the bridge's parent's address space, - * as subregions. - */ - MemoryRegion alias_pref_mem; - MemoryRegion alias_mem; - MemoryRegion alias_io; + + PCIBridgeWindows *windows; + pci_map_irq_fn map_irq; const char *bus_name; }; From e35e23f655fb120a2b4d0695bdee86fafd9caabf Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 24 Sep 2012 12:12:25 +0200 Subject: [PATCH 1240/2270] virtio-net: track host/guest header length Tracking these in device state instead of re-calculating on each packet. No functional changes. Signed-off-by: Michael S. Tsirkin --- hw/virtio-net.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 50ba728c02..a0c79e1d1b 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -41,6 +41,8 @@ typedef struct VirtIONet int32_t tx_burst; int tx_waiting; uint32_t has_vnet_hdr; + size_t host_hdr_len; + size_t guest_hdr_len; uint8_t has_ufo; struct { VirtQueueElement elem; @@ -231,6 +233,7 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features) if (peer_has_vnet_hdr(n)) { tap_using_vnet_hdr(n->nic->nc.peer, 1); + n->host_hdr_len = sizeof(struct virtio_net_hdr); } else { features &= ~(0x1 << VIRTIO_NET_F_CSUM); features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO4); @@ -278,6 +281,8 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) VirtIONet *n = to_virtio_net(vdev); n->mergeable_rx_bufs = !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF)); + n->guest_hdr_len = n->mergeable_rx_bufs ? + sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr); if (n->has_vnet_hdr) { tap_set_offload(n->nic->nc.peer, @@ -593,18 +598,13 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t { VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque; struct virtio_net_hdr_mrg_rxbuf *mhdr = NULL; - size_t guest_hdr_len, offset, i, host_hdr_len; + size_t offset, i; if (!virtio_net_can_receive(&n->nic->nc)) return -1; /* hdr_len refers to the header we supply to the guest */ - guest_hdr_len = n->mergeable_rx_bufs ? - sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr); - - - host_hdr_len = n->has_vnet_hdr ? sizeof(struct virtio_net_hdr) : 0; - if (!virtio_net_has_buffers(n, size + guest_hdr_len - host_hdr_len)) + if (!virtio_net_has_buffers(n, size + n->guest_hdr_len - n->host_hdr_len)) return 0; if (!receive_filter(n, buf, size)) @@ -626,7 +626,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t "i %zd mergeable %d offset %zd, size %zd, " "guest hdr len %zd, host hdr len %zd guest features 0x%x", i, n->mergeable_rx_bufs, offset, size, - guest_hdr_len, host_hdr_len, n->vdev.guest_features); + n->guest_hdr_len, n->host_hdr_len, n->vdev.guest_features); exit(1); } @@ -635,7 +635,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t exit(1); } - if (!n->mergeable_rx_bufs && elem.in_sg[0].iov_len != guest_hdr_len) { + if (!n->mergeable_rx_bufs && elem.in_sg[0].iov_len != n->guest_hdr_len) { error_report("virtio-net header not in first element"); exit(1); } @@ -647,8 +647,9 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t mhdr = (struct virtio_net_hdr_mrg_rxbuf *)sg[0].iov_base; offset += receive_header(n, sg, elem.in_num, - buf + offset, size - offset, guest_hdr_len); - total += guest_hdr_len; + buf + offset, size - offset, + n->guest_hdr_len); + total += n->guest_hdr_len; } /* copy in packet. ugh */ @@ -665,7 +666,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t "i %zd mergeable %d offset %zd, size %zd, " "guest hdr len %zd, host hdr len %zd", i, n->mergeable_rx_bufs, - offset, size, guest_hdr_len, host_hdr_len); + offset, size, n->guest_hdr_len, n->host_hdr_len); #endif return size; } @@ -900,6 +901,8 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) qemu_get_buffer(f, n->mac, ETH_ALEN); n->tx_waiting = qemu_get_be32(f); n->mergeable_rx_bufs = qemu_get_be32(f); + n->guest_hdr_len = n->mergeable_rx_bufs ? + sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr); if (version_id >= 3) n->status = qemu_get_be16(f); @@ -940,6 +943,7 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) if (n->has_vnet_hdr) { tap_using_vnet_hdr(n->nic->nc.peer, 1); + n->host_hdr_len = sizeof(struct virtio_net_hdr); tap_set_offload(n->nic->nc.peer, (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_CSUM) & 1, (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_TSO4) & 1, @@ -1044,6 +1048,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf, n->tx_waiting = 0; n->tx_burst = net->txburst; n->mergeable_rx_bufs = 0; + n->guest_hdr_len = sizeof(struct virtio_net_hdr); n->promisc = 1; /* for compatibility */ n->mac_table.macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN); From d336336c8164859e4527cbb9f3df189f8bb406de Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 24 Sep 2012 13:02:52 +0200 Subject: [PATCH 1241/2270] iov: add iov_cpy Add API to copy part of iovec safely. Signed-off-by: Michael S. Tsirkin --- iov.c | 23 +++++++++++++++++++++++ iov.h | 9 +++++++++ 2 files changed, 32 insertions(+) diff --git a/iov.c b/iov.c index c6a66f0afe..b7378bf7ce 100644 --- a/iov.c +++ b/iov.c @@ -228,3 +228,26 @@ void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt, fprintf(fp, "\n"); } } + +unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt, + const struct iovec *iov, unsigned int iov_cnt, + size_t offset, size_t bytes) +{ + size_t len; + unsigned int i, j; + for (i = 0, j = 0; i < iov_cnt && j < dst_iov_cnt && bytes; i++) { + if (offset >= iov[i].iov_len) { + offset -= iov[i].iov_len; + continue; + } + len = MIN(bytes, iov[i].iov_len - offset); + + dst_iov[j].iov_base = iov[i].iov_base + offset; + dst_iov[j].iov_len = len; + j++; + bytes -= len; + offset = 0; + } + assert(offset == 0); + return j; +} diff --git a/iov.h b/iov.h index a73569f94e..34c8ec9faa 100644 --- a/iov.h +++ b/iov.h @@ -86,3 +86,12 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt, */ void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt, FILE *fp, const char *prefix, size_t limit); + +/* + * Partial copy of vector from iov to dst_iov (data is not copied). + * dst_iov overlaps iov at a specified offset. + * size of dst_iov is at most bytes. dst vector count is returned. + */ +unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt, + const struct iovec *iov, unsigned int iov_cnt, + size_t offset, size_t bytes); From 22cc84db6e42bef8646b8cd671f4c999e9c0a38f Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 24 Sep 2012 13:14:16 +0200 Subject: [PATCH 1242/2270] virtio-net: avoid sg copy Avoid tweaking iovec during receive. This removes the need to copy the vector. Note: we currently have an evil cast in work_around_broken_dhclient and unfortunately this patch does not fix it - just pushes the evil cast to another place. Signed-off-by: Michael S. Tsirkin --- hw/virtio-net.c | 48 +++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index a0c79e1d1b..84615869cb 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -504,40 +504,37 @@ static int virtio_net_has_buffers(VirtIONet *n, int bufsize) * cache. */ static void work_around_broken_dhclient(struct virtio_net_hdr *hdr, - const uint8_t *buf, size_t size) + uint8_t *buf, size_t size) { if ((hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && /* missing csum */ (size > 27 && size < 1500) && /* normal sized MTU */ (buf[12] == 0x08 && buf[13] == 0x00) && /* ethertype == IPv4 */ (buf[23] == 17) && /* ip.protocol == UDP */ (buf[34] == 0 && buf[35] == 67)) { /* udp.srcport == bootps */ - /* FIXME this cast is evil */ - net_checksum_calculate((uint8_t *)buf, size); + net_checksum_calculate(buf, size); hdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM; } } -static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt, - const void *buf, size_t size, size_t hdr_len) +static int receive_header(VirtIONet *n, const struct iovec *iov, int iov_cnt, + const void *buf, size_t size) { - struct virtio_net_hdr *hdr = (struct virtio_net_hdr *)iov[0].iov_base; int offset = 0; - hdr->flags = 0; - hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE; - if (n->has_vnet_hdr) { - memcpy(hdr, buf, sizeof(*hdr)); - offset = sizeof(*hdr); - work_around_broken_dhclient(hdr, buf + offset, size - offset); + /* FIXME this cast is evil */ + void *wbuf = (void *)buf; + work_around_broken_dhclient(wbuf, wbuf + offset, size - offset); + offset = sizeof(struct virtio_net_hdr); + iov_from_buf(iov, iov_cnt, 0, buf, offset); + } else { + struct virtio_net_hdr hdr = { + .flags = 0, + .gso_type = VIRTIO_NET_HDR_GSO_NONE + }; + iov_from_buf(iov, iov_cnt, 0, &hdr, sizeof hdr); } - /* We only ever receive a struct virtio_net_hdr from the tapfd, - * but we may be passing along a larger header to the guest. - */ - iov[0].iov_base += hdr_len; - iov[0].iov_len -= hdr_len; - return offset; } @@ -598,7 +595,8 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t { VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque; struct virtio_net_hdr_mrg_rxbuf *mhdr = NULL; - size_t offset, i; + const struct iovec *sg = elem.in_sg; + size_t offset, i, guest_offset; if (!virtio_net_can_receive(&n->nic->nc)) return -1; @@ -615,7 +613,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t while (offset < size) { VirtQueueElement elem; int len, total; - struct iovec sg[VIRTQUEUE_MAX_SIZE]; + const struct iovec *sg = elem.in_sg; total = 0; @@ -640,20 +638,20 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t exit(1); } - memcpy(&sg, &elem.in_sg[0], sizeof(sg[0]) * elem.in_num); - if (i == 0) { if (n->mergeable_rx_bufs) mhdr = (struct virtio_net_hdr_mrg_rxbuf *)sg[0].iov_base; offset += receive_header(n, sg, elem.in_num, - buf + offset, size - offset, - n->guest_hdr_len); + buf + offset, size - offset); total += n->guest_hdr_len; + guest_offset = n->guest_hdr_len; + } else { + guest_offset = 0; } /* copy in packet. ugh */ - len = iov_from_buf(sg, elem.in_num, 0, + len = iov_from_buf(sg, elem.in_num, guest_offset, buf + offset, size - offset); total += len; offset += len; From 63c5872873de8d7d994a589eed7bfe6a70cc8e06 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 24 Sep 2012 13:17:13 +0200 Subject: [PATCH 1243/2270] virtio-net: use safe iov operations for rx Avoid magling iov manually: use safe iov operations for processing packets incoming to guest. This also removes the requirement for virtio header to fit the first s/g entry exactly. Signed-off-by: Michael S. Tsirkin --- hw/virtio-net.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 84615869cb..d315fdf0a4 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -594,8 +594,9 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t size) { VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque; - struct virtio_net_hdr_mrg_rxbuf *mhdr = NULL; - const struct iovec *sg = elem.in_sg; + struct iovec mhdr_sg[VIRTQUEUE_MAX_SIZE]; + struct virtio_net_hdr_mrg_rxbuf mhdr; + unsigned mhdr_cnt = 0; size_t offset, i, guest_offset; if (!virtio_net_can_receive(&n->nic->nc)) @@ -633,14 +634,13 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t exit(1); } - if (!n->mergeable_rx_bufs && elem.in_sg[0].iov_len != n->guest_hdr_len) { - error_report("virtio-net header not in first element"); - exit(1); - } - if (i == 0) { - if (n->mergeable_rx_bufs) - mhdr = (struct virtio_net_hdr_mrg_rxbuf *)sg[0].iov_base; + if (n->mergeable_rx_bufs) { + mhdr_cnt = iov_copy(mhdr_sg, ARRAY_SIZE(mhdr_sg), + sg, elem.in_num, + offsetof(typeof(mhdr), num_buffers), + sizeof(mhdr.num_buffers)); + } offset += receive_header(n, sg, elem.in_num, buf + offset, size - offset); @@ -673,8 +673,11 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t virtqueue_fill(n->rx_vq, &elem, total, i++); } - if (mhdr) { - stw_p(&mhdr->num_buffers, i); + if (mhdr_cnt) { + stw_p(&mhdr.num_buffers, i); + iov_from_buf(mhdr_sg, mhdr_cnt, + 0, + &mhdr.num_buffers, sizeof mhdr.num_buffers); } virtqueue_flush(n->rx_vq, i); From 280598b7a5fdf96fb79d87a2129750bad5dbf24b Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 24 Sep 2012 13:24:17 +0200 Subject: [PATCH 1244/2270] virtio-net: refactor receive_hdr Now that we know host hdr length, we don't need to duplicate the logic in receive_hdr: caller can figure out the offset itself. Signed-off-by: Michael S. Tsirkin --- hw/virtio-net.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index d315fdf0a4..5128a2a8ba 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -516,17 +516,15 @@ static void work_around_broken_dhclient(struct virtio_net_hdr *hdr, } } -static int receive_header(VirtIONet *n, const struct iovec *iov, int iov_cnt, - const void *buf, size_t size) +static void receive_header(VirtIONet *n, const struct iovec *iov, int iov_cnt, + const void *buf, size_t size) { - int offset = 0; - if (n->has_vnet_hdr) { /* FIXME this cast is evil */ void *wbuf = (void *)buf; - work_around_broken_dhclient(wbuf, wbuf + offset, size - offset); - offset = sizeof(struct virtio_net_hdr); - iov_from_buf(iov, iov_cnt, 0, buf, offset); + work_around_broken_dhclient(wbuf, wbuf + n->host_hdr_len, + size - n->host_hdr_len); + iov_from_buf(iov, iov_cnt, 0, buf, sizeof(struct virtio_net_hdr)); } else { struct virtio_net_hdr hdr = { .flags = 0, @@ -534,8 +532,6 @@ static int receive_header(VirtIONet *n, const struct iovec *iov, int iov_cnt, }; iov_from_buf(iov, iov_cnt, 0, &hdr, sizeof hdr); } - - return offset; } static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) @@ -642,8 +638,8 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t sizeof(mhdr.num_buffers)); } - offset += receive_header(n, sg, elem.in_num, - buf + offset, size - offset); + receive_header(n, sg, elem.in_num, buf + offset, size - offset); + offset += n->host_hdr_len; total += n->guest_hdr_len; guest_offset = n->guest_hdr_len; } else { From c8d28e7e336869524d166d88f08ad476eadedccb Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 24 Sep 2012 13:26:55 +0200 Subject: [PATCH 1245/2270] virtio-net: first s/g is always at start of buf We know offset is 0, assert that. Signed-off-by: Michael S. Tsirkin --- hw/virtio-net.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 5128a2a8ba..59ab6746f0 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -631,6 +631,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t } if (i == 0) { + assert(offset == 0); if (n->mergeable_rx_bufs) { mhdr_cnt = iov_copy(mhdr_sg, ARRAY_SIZE(mhdr_sg), sg, elem.in_num, @@ -638,8 +639,8 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t sizeof(mhdr.num_buffers)); } - receive_header(n, sg, elem.in_num, buf + offset, size - offset); - offset += n->host_hdr_len; + receive_header(n, sg, elem.in_num, buf, size); + offset = n->host_hdr_len; total += n->guest_hdr_len; guest_offset = n->guest_hdr_len; } else { From 14761f9cf7fbc6d058c1e51c313a139066eab256 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 24 Sep 2012 14:52:28 +0200 Subject: [PATCH 1246/2270] virtio-net: switch tx to safe iov functions Avoid mangling iovec manually: use safe iov_* functions. Signed-off-by: Michael S. Tsirkin --- hw/virtio-net.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 59ab6746f0..5206648271 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -715,10 +715,10 @@ static int32_t virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq) } while (virtqueue_pop(vq, &elem)) { - ssize_t ret, len = 0; + ssize_t ret, len; unsigned int out_num = elem.out_num; struct iovec *out_sg = &elem.out_sg[0]; - unsigned hdr_len; + struct iovec sg[VIRTQUEUE_MAX_SIZE]; /* hdr_len refers to the header received from the guest */ hdr_len = n->mergeable_rx_bufs ? @@ -730,18 +730,25 @@ static int32_t virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq) exit(1); } - /* ignore the header if GSO is not supported */ - if (!n->has_vnet_hdr) { - out_num--; - out_sg++; - len += hdr_len; - } else if (n->mergeable_rx_bufs) { - /* tapfd expects a struct virtio_net_hdr */ - hdr_len -= sizeof(struct virtio_net_hdr); - out_sg->iov_len -= hdr_len; - len += hdr_len; + /* + * If host wants to see the guest header as is, we can + * pass it on unchanged. Otherwise, copy just the parts + * that host is interested in. + */ + assert(n->host_hdr_len <= n->guest_hdr_len); + if (n->host_hdr_len != n->guest_hdr_len) { + unsigned sg_num = iov_copy(sg, ARRAY_SIZE(sg), + out_sg, out_num, + 0, n->host_hdr_len); + sg_num += iov_copy(sg + sg_num, ARRAY_SIZE(sg) - sg_num, + out_sg, out_num, + n->guest_hdr_len, -1); + out_num = sg_num; + out_sg = sg; } + len = hdr_len; + ret = qemu_sendv_packet_async(&n->nic->nc, out_sg, out_num, virtio_net_tx_complete); if (ret == 0) { From 7b80d08efc36fd6c7881e98302f00148b5fd908a Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 24 Sep 2012 14:54:44 +0200 Subject: [PATCH 1247/2270] virtio-net: simplify rx code Remove code duplication using guest header length that we track. Drop specific layout requirement for rx buffers: things work using generic iovec functions in any case. Signed-off-by: Michael S. Tsirkin --- hw/virtio-net.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 5206648271..dc4a26cbd6 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -720,12 +720,7 @@ static int32_t virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq) struct iovec *out_sg = &elem.out_sg[0]; struct iovec sg[VIRTQUEUE_MAX_SIZE]; - /* hdr_len refers to the header received from the guest */ - hdr_len = n->mergeable_rx_bufs ? - sizeof(struct virtio_net_hdr_mrg_rxbuf) : - sizeof(struct virtio_net_hdr); - - if (out_num < 1 || out_sg->iov_len != hdr_len) { + if (out_num < 1) { error_report("virtio-net header not in first element"); exit(1); } @@ -747,7 +742,7 @@ static int32_t virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq) out_sg = sg; } - len = hdr_len; + len = n->guest_hdr_len; ret = qemu_sendv_packet_async(&n->nic->nc, out_sg, out_num, virtio_net_tx_complete); From e043ebc6f9a093c1fd1b677191ad9fbeefe22d1e Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 24 Sep 2012 16:27:27 +0200 Subject: [PATCH 1248/2270] virtio-net: minor code simplification During packet filtering, we can now use host hdr len to offset incoming buffer unconditionally. Signed-off-by: Michael S. Tsirkin --- hw/virtio-net.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index dc4a26cbd6..c94521e0fe 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -544,9 +544,7 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) if (n->promisc) return 1; - if (n->has_vnet_hdr) { - ptr += sizeof(struct virtio_net_hdr); - } + ptr += n->host_hdr_len; if (!memcmp(&ptr[12], vlan, sizeof(vlan))) { int vid = be16_to_cpup((uint16_t *)(ptr + 14)) & 0xfff; From 6e371ab867d48c16e6a9ee32cefcea48692a4deb Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 24 Sep 2012 17:04:21 +0200 Subject: [PATCH 1249/2270] virtio-net: test peer header support at init time There's no reason to query header support at random times: at load or feature query. Driver also might not query functions. Cleaner to do it at device init. Signed-off-by: Michael S. Tsirkin --- hw/virtio-net.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index c94521e0fe..1180b51ac6 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -202,16 +202,19 @@ static void virtio_net_reset(VirtIODevice *vdev) memset(n->vlans, 0, MAX_VLAN >> 3); } -static int peer_has_vnet_hdr(VirtIONet *n) +static void peer_test_vnet_hdr(VirtIONet *n) { if (!n->nic->nc.peer) - return 0; + return; if (n->nic->nc.peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) - return 0; + return; n->has_vnet_hdr = tap_has_vnet_hdr(n->nic->nc.peer); +} +static int peer_has_vnet_hdr(VirtIONet *n) +{ return n->has_vnet_hdr; } @@ -231,10 +234,7 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features) features |= (1 << VIRTIO_NET_F_MAC); - if (peer_has_vnet_hdr(n)) { - tap_using_vnet_hdr(n->nic->nc.peer, 1); - n->host_hdr_len = sizeof(struct virtio_net_hdr); - } else { + if (!peer_has_vnet_hdr(n)) { features &= ~(0x1 << VIRTIO_NET_F_CSUM); features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO4); features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO6); @@ -940,8 +940,6 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) } if (n->has_vnet_hdr) { - tap_using_vnet_hdr(n->nic->nc.peer, 1); - n->host_hdr_len = sizeof(struct virtio_net_hdr); tap_set_offload(n->nic->nc.peer, (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_CSUM) & 1, (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_TSO4) & 1, @@ -1040,6 +1038,13 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf, n->status = VIRTIO_NET_S_LINK_UP; n->nic = qemu_new_nic(&net_virtio_info, conf, object_get_typename(OBJECT(dev)), dev->id, n); + peer_test_vnet_hdr(n); + if (peer_has_vnet_hdr(n)) { + tap_using_vnet_hdr(n->nic->nc.peer, 1); + n->host_hdr_len = sizeof(struct virtio_net_hdr); + } else { + n->host_hdr_len = 0; + } qemu_format_nic_info_str(&n->nic->nc, conf->macaddr.a); From ff3a8066e651230d255e6eea340e2d48e7da4aeb Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 24 Sep 2012 21:05:03 +0200 Subject: [PATCH 1250/2270] virtio-net: enable mrg buf header in tap on linux Modern linux supports arbitrary header size, which makes it possible to pass mrg buf header to tap directly without iovec mangling. Use this capability when it is there. This removes the need to deal with it in vhost-net as we do now. Signed-off-by: Michael S. Tsirkin --- hw/vhost_net.c | 13 ------------- hw/virtio-net.c | 26 ++++++++++++++++++-------- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/hw/vhost_net.c b/hw/vhost_net.c index df2c4a30a2..8241601539 100644 --- a/hw/vhost_net.c +++ b/hw/vhost_net.c @@ -150,10 +150,6 @@ int vhost_net_start(struct vhost_net *net, if (r < 0) { goto fail_notifiers; } - if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { - tap_set_vnet_hdr_len(net->nc, - sizeof(struct virtio_net_hdr_mrg_rxbuf)); - } r = vhost_dev_start(&net->dev, dev); if (r < 0) { @@ -179,9 +175,6 @@ fail: } net->nc->info->poll(net->nc, true); vhost_dev_stop(&net->dev, dev); - if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { - tap_set_vnet_hdr_len(net->nc, sizeof(struct virtio_net_hdr)); - } fail_start: vhost_dev_disable_notifiers(&net->dev, dev); fail_notifiers: @@ -199,18 +192,12 @@ void vhost_net_stop(struct vhost_net *net, } net->nc->info->poll(net->nc, true); vhost_dev_stop(&net->dev, dev); - if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { - tap_set_vnet_hdr_len(net->nc, sizeof(struct virtio_net_hdr)); - } vhost_dev_disable_notifiers(&net->dev, dev); } void vhost_net_cleanup(struct vhost_net *net) { vhost_dev_cleanup(&net->dev); - if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { - tap_set_vnet_hdr_len(net->nc, sizeof(struct virtio_net_hdr)); - } g_free(net); } #else diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 1180b51ac6..108ce07cfc 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -228,6 +228,20 @@ static int peer_has_ufo(VirtIONet *n) return n->has_ufo; } +static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs) +{ + n->mergeable_rx_bufs = mergeable_rx_bufs; + + n->guest_hdr_len = n->mergeable_rx_bufs ? + sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr); + + if (peer_has_vnet_hdr(n) && + tap_has_vnet_hdr_len(n->nic->nc.peer, n->guest_hdr_len)) { + tap_set_vnet_hdr_len(n->nic->nc.peer, n->guest_hdr_len); + n->host_hdr_len = n->guest_hdr_len; + } +} + static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features) { VirtIONet *n = to_virtio_net(vdev); @@ -280,9 +294,7 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) { VirtIONet *n = to_virtio_net(vdev); - n->mergeable_rx_bufs = !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF)); - n->guest_hdr_len = n->mergeable_rx_bufs ? - sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr); + virtio_net_set_mrg_rx_bufs(n, !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF))); if (n->has_vnet_hdr) { tap_set_offload(n->nic->nc.peer, @@ -898,9 +910,8 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) qemu_get_buffer(f, n->mac, ETH_ALEN); n->tx_waiting = qemu_get_be32(f); - n->mergeable_rx_bufs = qemu_get_be32(f); - n->guest_hdr_len = n->mergeable_rx_bufs ? - sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr); + + virtio_net_set_mrg_rx_bufs(n, qemu_get_be32(f)); if (version_id >= 3) n->status = qemu_get_be16(f); @@ -1050,8 +1061,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf, n->tx_waiting = 0; n->tx_burst = net->txburst; - n->mergeable_rx_bufs = 0; - n->guest_hdr_len = sizeof(struct virtio_net_hdr); + virtio_net_set_mrg_rx_bufs(n, 0); n->promisc = 1; /* for compatibility */ n->mac_table.macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN); From 523a59f596a3e62f5a28eb171adba35e71310040 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 25 Oct 2012 12:37:57 +0200 Subject: [PATCH 1251/2270] pci: avoid destroying bridge address space windows in a transaction Calling memory_region_destroy() in a transaction is illegal (and aborts), as until the transaction is committed, the region remains live. Fix by moving destruction until after the transaction commits. This requires having an extra set of regions, so the new and old regions can coexist. Signed-off-by: Avi Kivity Signed-off-by: Michael S. Tsirkin --- hw/pci_bridge.c | 50 ++++++++++++++++++++++++++-------------------- hw/pci_internals.h | 24 ++++++++++++++-------- 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c index 5c6455f6fa..4680501e4e 100644 --- a/hw/pci_bridge.c +++ b/hw/pci_bridge.c @@ -151,58 +151,63 @@ static void pci_bridge_init_alias(PCIBridge *bridge, MemoryRegion *alias, memory_region_add_subregion_overlap(parent_space, base, alias, 1); } -static void pci_bridge_cleanup_alias(MemoryRegion *alias, - MemoryRegion *parent_space) -{ - memory_region_del_subregion(parent_space, alias); - memory_region_destroy(alias); -} - -static void pci_bridge_region_init(PCIBridge *br) +static PCIBridgeWindows *pci_bridge_region_init(PCIBridge *br) { PCIBus *parent = br->dev.bus; + PCIBridgeWindows *w = g_new(PCIBridgeWindows, 1); uint16_t cmd = pci_get_word(br->dev.config + PCI_COMMAND); - pci_bridge_init_alias(br, &br->alias_pref_mem, + pci_bridge_init_alias(br, &w->alias_pref_mem, PCI_BASE_ADDRESS_MEM_PREFETCH, "pci_bridge_pref_mem", &br->address_space_mem, parent->address_space_mem, cmd & PCI_COMMAND_MEMORY); - pci_bridge_init_alias(br, &br->alias_mem, + pci_bridge_init_alias(br, &w->alias_mem, PCI_BASE_ADDRESS_SPACE_MEMORY, "pci_bridge_mem", &br->address_space_mem, parent->address_space_mem, cmd & PCI_COMMAND_MEMORY); - pci_bridge_init_alias(br, &br->alias_io, + pci_bridge_init_alias(br, &w->alias_io, PCI_BASE_ADDRESS_SPACE_IO, "pci_bridge_io", &br->address_space_io, parent->address_space_io, cmd & PCI_COMMAND_IO); /* TODO: optinal VGA and VGA palette snooping support. */ + + return w; } -static void pci_bridge_region_cleanup(PCIBridge *br) +static void pci_bridge_region_del(PCIBridge *br, PCIBridgeWindows *w) { PCIBus *parent = br->dev.bus; - pci_bridge_cleanup_alias(&br->alias_io, - parent->address_space_io); - pci_bridge_cleanup_alias(&br->alias_mem, - parent->address_space_mem); - pci_bridge_cleanup_alias(&br->alias_pref_mem, - parent->address_space_mem); + + memory_region_del_subregion(parent->address_space_io, &w->alias_io); + memory_region_del_subregion(parent->address_space_mem, &w->alias_mem); + memory_region_del_subregion(parent->address_space_mem, &w->alias_pref_mem); +} + +static void pci_bridge_region_cleanup(PCIBridge *br, PCIBridgeWindows *w) +{ + memory_region_destroy(&w->alias_io); + memory_region_destroy(&w->alias_mem); + memory_region_destroy(&w->alias_pref_mem); + g_free(w); } static void pci_bridge_update_mappings(PCIBridge *br) { + PCIBridgeWindows *w = br->windows; + /* Make updates atomic to: handle the case of one VCPU updating the bridge * while another accesses an unaffected region. */ memory_region_transaction_begin(); - pci_bridge_region_cleanup(br); - pci_bridge_region_init(br); + pci_bridge_region_del(br, br->windows); + br->windows = pci_bridge_region_init(br); memory_region_transaction_commit(); + pci_bridge_region_cleanup(br, w); } /* default write_config function for PCI-to-PCI bridge */ @@ -326,7 +331,7 @@ int pci_bridge_initfn(PCIDevice *dev) memory_region_init(&br->address_space_mem, "pci_bridge_pci", INT64_MAX); sec_bus->address_space_io = &br->address_space_io; memory_region_init(&br->address_space_io, "pci_bridge_io", 65536); - pci_bridge_region_init(br); + br->windows = pci_bridge_region_init(br); QLIST_INIT(&sec_bus->child); QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling); return 0; @@ -338,7 +343,8 @@ void pci_bridge_exitfn(PCIDevice *pci_dev) PCIBridge *s = DO_UPCAST(PCIBridge, dev, pci_dev); assert(QLIST_EMPTY(&s->sec_bus.child)); QLIST_REMOVE(&s->sec_bus, sibling); - pci_bridge_region_cleanup(s); + pci_bridge_region_del(s, s->windows); + pci_bridge_region_cleanup(s, s->windows); memory_region_destroy(&s->address_space_mem); memory_region_destroy(&s->address_space_io); /* qbus_free() is called automatically by qdev_free() */ diff --git a/hw/pci_internals.h b/hw/pci_internals.h index c931b64b46..21d0ce6973 100644 --- a/hw/pci_internals.h +++ b/hw/pci_internals.h @@ -40,6 +40,19 @@ struct PCIBus { int *irq_count; }; +typedef struct PCIBridgeWindows PCIBridgeWindows; + +/* + * Aliases for each of the address space windows that the bridge + * can forward. Mapped into the bridge's parent's address space, + * as subregions. + */ +struct PCIBridgeWindows { + MemoryRegion alias_pref_mem; + MemoryRegion alias_mem; + MemoryRegion alias_io; +}; + struct PCIBridge { PCIDevice dev; @@ -55,14 +68,9 @@ struct PCIBridge { */ MemoryRegion address_space_mem; MemoryRegion address_space_io; - /* - * Aliases for each of the address space windows that the bridge - * can forward. Mapped into the bridge's parent's address space, - * as subregions. - */ - MemoryRegion alias_pref_mem; - MemoryRegion alias_mem; - MemoryRegion alias_io; + + PCIBridgeWindows *windows; + pci_map_irq_fn map_irq; const char *bus_name; }; From 235a3f0bed3584fe65079ffa07c7a842971f261e Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 19 Sep 2012 17:24:46 +0200 Subject: [PATCH 1252/2270] s390x: fix -initrd in virtio machine When using -initrd in the virtio machine, we need to indicate the initrd start and size inside the kernel image. These parameters need to be stored in native endianness. Signed-off-by: Alexander Graf Acked-by: Richard Henderson Acked-by: Christian Borntraeger --- hw/s390-virtio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index 85bd13e06f..52fad37526 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -285,8 +285,8 @@ static void s390_init(QEMUMachineInitArgs *args) } /* we have to overwrite values in the kernel image, which are "rom" */ - memcpy(rom_ptr(INITRD_PARM_START), &initrd_offset, 8); - memcpy(rom_ptr(INITRD_PARM_SIZE), &initrd_size, 8); + stq_p(rom_ptr(INITRD_PARM_START), initrd_offset); + stq_p(rom_ptr(INITRD_PARM_SIZE), initrd_size); } if (rom_ptr(KERN_PARM_AREA)) { From 1b3e6f88dc151578acb6158e22570cf3ee7cbb69 Mon Sep 17 00:00:00 2001 From: Heinz Graalfs Date: Mon, 29 Oct 2012 02:13:20 +0000 Subject: [PATCH 1253/2270] s390/kvm_stat: correct sys_perf_event_open syscall number Correct sys_perf_event_open syscall number for s390 architecture - the hardcoded syscall number 298 is for x86 but should be different for other architectures. In case we figure out via /proc/cpuinfo that we are running on s390 the appropriate syscall number is used from map syscall_numbers; other architectures can extend this. Signed-off-by: Heinz Graalfs Signed-off-by: Jens Freimann Signed-off-by: Alexander Graf --- scripts/kvm/kvm_stat | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scripts/kvm/kvm_stat b/scripts/kvm/kvm_stat index e8d68f05ca..762544b197 100755 --- a/scripts/kvm/kvm_stat +++ b/scripts/kvm/kvm_stat @@ -170,6 +170,12 @@ vendor_exit_reasons = { 'IBM/S390': s390_exit_reasons, } +syscall_numbers = { + 'IBM/S390': 331, +} + +sc_perf_evt_open = 298 + exit_reasons = None for line in file('/proc/cpuinfo').readlines(): @@ -177,7 +183,8 @@ for line in file('/proc/cpuinfo').readlines(): for flag in line.split(): if flag in vendor_exit_reasons: exit_reasons = vendor_exit_reasons[flag] - + if flag in syscall_numbers: + sc_perf_evt_open = syscall_numbers[flag] filters = { 'kvm_exit': ('exit_reason', exit_reasons) } @@ -206,7 +213,7 @@ class perf_event_attr(ctypes.Structure): ('bp_len', ctypes.c_uint64), ] def _perf_event_open(attr, pid, cpu, group_fd, flags): - return syscall(298, ctypes.pointer(attr), ctypes.c_int(pid), + return syscall(sc_perf_evt_open, ctypes.pointer(attr), ctypes.c_int(pid), ctypes.c_int(cpu), ctypes.c_int(group_fd), ctypes.c_long(flags)) From 5b08b344bf581a266071389ceeb445e943e01ba1 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Mon, 29 Oct 2012 02:13:21 +0000 Subject: [PATCH 1254/2270] s390: use sync regs for register transfer Newer kernels provide the guest registers in kvm_run. Lets use those if available (i.e. the capability is set). This avoids ioctls on cpu_synchronize_state making intercepts faster. In addition, we have now the prefix register, the access registers the control registers up to date. This helps in certain cases, e.g. for resolving kernel module addresses with gdb on a guest. On return, we update the registers according to the level statement, i.e. we put all registers for KVM_PUT_FULL_STATE and _RESET_STATE. Signed-off-by: Christian Borntraeger Signed-off-by: Jens Freimann Signed-off-by: Alexander Graf --- target-s390x/kvm.c | 122 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 97 insertions(+), 25 deletions(-) diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 07edf93690..e19a44d637 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -67,8 +67,11 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_LAST_INFO }; +static int cap_sync_regs; + int kvm_arch_init(KVMState *s) { + cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS); return 0; } @@ -90,48 +93,117 @@ void kvm_arch_reset_vcpu(CPUS390XState *env) int kvm_arch_put_registers(CPUS390XState *env, int level) { + struct kvm_sregs sregs; struct kvm_regs regs; int ret; int i; - ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); - if (ret < 0) { - return ret; - } - - for (i = 0; i < 16; i++) { - regs.gprs[i] = env->regs[i]; - } - - ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s); - if (ret < 0) { - return ret; - } - + /* always save the PSW and the GPRS*/ env->kvm_run->psw_addr = env->psw.addr; env->kvm_run->psw_mask = env->psw.mask; - return ret; + if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_GPRS) { + for (i = 0; i < 16; i++) { + env->kvm_run->s.regs.gprs[i] = env->regs[i]; + env->kvm_run->kvm_dirty_regs |= KVM_SYNC_GPRS; + } + } else { + for (i = 0; i < 16; i++) { + regs.gprs[i] = env->regs[i]; + } + ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s); + if (ret < 0) { + return ret; + } + } + + /* Do we need to save more than that? */ + if (level == KVM_PUT_RUNTIME_STATE) { + return 0; + } + + if (cap_sync_regs && + env->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS && + env->kvm_run->kvm_valid_regs & KVM_SYNC_CRS) { + for (i = 0; i < 16; i++) { + env->kvm_run->s.regs.acrs[i] = env->aregs[i]; + env->kvm_run->s.regs.crs[i] = env->cregs[i]; + } + env->kvm_run->kvm_dirty_regs |= KVM_SYNC_ACRS; + env->kvm_run->kvm_dirty_regs |= KVM_SYNC_CRS; + } else { + for (i = 0; i < 16; i++) { + sregs.acrs[i] = env->aregs[i]; + sregs.crs[i] = env->cregs[i]; + } + ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs); + if (ret < 0) { + return ret; + } + } + + /* Finally the prefix */ + if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) { + env->kvm_run->s.regs.prefix = env->psa; + env->kvm_run->kvm_dirty_regs |= KVM_SYNC_PREFIX; + } else { + /* prefix is only supported via sync regs */ + } + return 0; } int kvm_arch_get_registers(CPUS390XState *env) { - int ret; + struct kvm_sregs sregs; struct kvm_regs regs; + int ret; int i; - ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); - if (ret < 0) { - return ret; - } - - for (i = 0; i < 16; i++) { - env->regs[i] = regs.gprs[i]; - } - + /* get the PSW */ env->psw.addr = env->kvm_run->psw_addr; env->psw.mask = env->kvm_run->psw_mask; + /* the GPRS */ + if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_GPRS) { + for (i = 0; i < 16; i++) { + env->regs[i] = env->kvm_run->s.regs.gprs[i]; + } + } else { + ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); + if (ret < 0) { + return ret; + } + for (i = 0; i < 16; i++) { + env->regs[i] = regs.gprs[i]; + } + } + + /* The ACRS and CRS */ + if (cap_sync_regs && + env->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS && + env->kvm_run->kvm_valid_regs & KVM_SYNC_CRS) { + for (i = 0; i < 16; i++) { + env->aregs[i] = env->kvm_run->s.regs.acrs[i]; + env->cregs[i] = env->kvm_run->s.regs.crs[i]; + } + } else { + ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs); + if (ret < 0) { + return ret; + } + for (i = 0; i < 16; i++) { + env->aregs[i] = sregs.acrs[i]; + env->cregs[i] = sregs.crs[i]; + } + } + + /* Finally the prefix */ + if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) { + env->psa = env->kvm_run->s.regs.prefix; + } else { + /* no prefix without sync regs */ + } + return 0; } From f6c98f9286c69cafe108b7e9fb22c2ff5da7d6a9 Mon Sep 17 00:00:00 2001 From: Heinz Graalfs Date: Mon, 29 Oct 2012 02:13:22 +0000 Subject: [PATCH 1255/2270] s390: sclp base support This adds a more generic infrastructure for handling Service-Call requests on s390. Currently we only support a small subset of Read SCP Info directly in target-s390x. This patch provides the base infrastructure for supporting more commands and moves Read SCP Info. In the future we could add additional commands for hotplug, call home and event handling. Signed-off-by: Heinz Graalfs Signed-off-by: Christian Borntraeger Signed-off-by: Jens Freimann Signed-off-by: Alexander Graf --- hw/s390x/Makefile.objs | 1 + hw/s390x/sclp.c | 118 +++++++++++++++++++++++++++++++++++++ hw/s390x/sclp.h | 76 ++++++++++++++++++++++++ target-s390x/cpu.h | 13 +--- target-s390x/kvm.c | 5 +- target-s390x/misc_helper.c | 45 +------------- 6 files changed, 198 insertions(+), 60 deletions(-) create mode 100644 hw/s390x/sclp.c create mode 100644 hw/s390x/sclp.h diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index dcdcac8a81..1c14b96687 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -1,3 +1,4 @@ obj-y = s390-virtio-bus.o s390-virtio.o obj-y := $(addprefix ../,$(obj-y)) +obj-y += sclp.o diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c new file mode 100644 index 0000000000..d902a66261 --- /dev/null +++ b/hw/s390x/sclp.c @@ -0,0 +1,118 @@ +/* + * SCLP Support + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Christian Borntraeger + * Heinz Graalfs + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. + * + */ + +#include "cpu.h" +#include "kvm.h" +#include "memory.h" + +#include "sclp.h" + +/* Provide information about the configuration, CPUs and storage */ +static void read_SCP_info(SCCB *sccb) +{ + ReadInfo *read_info = (ReadInfo *) sccb; + int shift = 0; + + while ((ram_size >> (20 + shift)) > 65535) { + shift++; + } + read_info->rnmax = cpu_to_be16(ram_size >> (20 + shift)); + read_info->rnsize = 1 << shift; + sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION); +} + +static void sclp_execute(SCCB *sccb, uint64_t code) +{ + switch (code) { + case SCLP_CMDW_READ_SCP_INFO: + case SCLP_CMDW_READ_SCP_INFO_FORCED: + read_SCP_info(sccb); + break; + default: + sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND); + break; + } +} + +int sclp_service_call(uint32_t sccb, uint64_t code) +{ + int r = 0; + SCCB work_sccb; + + hwaddr sccb_len = sizeof(SCCB); + + /* first some basic checks on program checks */ + if (cpu_physical_memory_is_io(sccb)) { + r = -PGM_ADDRESSING; + goto out; + } + if (sccb & ~0x7ffffff8ul) { + r = -PGM_SPECIFICATION; + goto out; + } + + /* + * we want to work on a private copy of the sccb, to prevent guests + * from playing dirty tricks by modifying the memory content after + * the host has checked the values + */ + cpu_physical_memory_read(sccb, &work_sccb, sccb_len); + + /* Valid sccb sizes */ + if (be16_to_cpu(work_sccb.h.length) < sizeof(SCCBHeader) || + be16_to_cpu(work_sccb.h.length) > SCCB_SIZE) { + r = -PGM_SPECIFICATION; + goto out; + } + + sclp_execute((SCCB *)&work_sccb, code); + + cpu_physical_memory_write(sccb, &work_sccb, + be16_to_cpu(work_sccb.h.length)); + + sclp_service_interrupt(sccb); + +out: + return r; +} + +void sclp_service_interrupt(uint32_t sccb) +{ + s390_sclp_extint(sccb & ~3); +} + +/* qemu object creation and initialization functions */ + +static void s390_sclp_device_class_init(ObjectClass *klass, void *data) +{ + SysBusDeviceClass *dc = SYS_BUS_DEVICE_CLASS(klass); + + dc->init = s390_sclp_dev_init; +} + +static TypeInfo s390_sclp_device_info = { + .name = TYPE_DEVICE_S390_SCLP, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(S390SCLPDevice), + .class_init = s390_sclp_device_class_init, + .class_size = sizeof(S390SCLPDeviceClass), + .abstract = true, +}; + +static void s390_sclp_register_types(void) +{ + type_register_static(&s390_sclp_device_info); +} + +type_init(s390_sclp_register_types) diff --git a/hw/s390x/sclp.h b/hw/s390x/sclp.h new file mode 100644 index 0000000000..e9ad42bec2 --- /dev/null +++ b/hw/s390x/sclp.h @@ -0,0 +1,76 @@ +/* + * SCLP Support + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Christian Borntraeger + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. + * + */ + +#ifndef HW_S390_SCLP_H +#define HW_S390_SCLP_H + +#include +#include + +/* SCLP command codes */ +#define SCLP_CMDW_READ_SCP_INFO 0x00020001 +#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 + +/* SCLP response codes */ +#define SCLP_RC_NORMAL_READ_COMPLETION 0x0010 +#define SCLP_RC_INVALID_SCLP_COMMAND 0x01f0 + +/* Service Call Control Block (SCCB) and its elements */ + +#define SCCB_SIZE 4096 + +/* + * Normally packed structures are not the right thing to do, since all code + * must take care of endianess. We cant use ldl_phys and friends for two + * reasons, though: + * - some of the embedded structures below the SCCB can appear multiple times + * at different locations, so there is no fixed offset + * - we work on a private copy of the SCCB, since there are several length + * fields, that would cause a security nightmare if we allow the guest to + * alter the structure while we parse it. We cannot use ldl_p and friends + * either without doing pointer arithmetics + * So we have to double check that all users of sclp data structures use the + * right endianess wrappers. + */ +typedef struct SCCBHeader { + uint16_t length; + uint8_t function_code; + uint8_t control_mask[3]; + uint16_t response_code; +} QEMU_PACKED SCCBHeader; + +#define SCCB_DATA_LEN (SCCB_SIZE - sizeof(SCCBHeader)) + +typedef struct ReadInfo { + SCCBHeader h; + uint16_t rnmax; + uint8_t rnsize; +} QEMU_PACKED ReadInfo; + +typedef struct SCCB { + SCCBHeader h; + char data[SCCB_DATA_LEN]; + } QEMU_PACKED SCCB; + +typedef struct S390SCLPDevice { + SysBusDevice busdev; +} S390SCLPDevice; + +typedef struct S390SCLPDeviceClass { + DeviceClass qdev; + int (*init)(S390SCLPDevice *sdev); +} S390SCLPDeviceClass; + +void sclp_service_interrupt(uint32_t sccb); + +#endif diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 9997765dd1..5be6e83528 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -596,17 +596,6 @@ static inline const char *cc_name(int cc_op) return cc_names[cc_op]; } -/* SCLP PV interface defines */ -#define SCLP_CMDW_READ_SCP_INFO 0x00020001 -#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 - -#define SCP_LENGTH 0x00 -#define SCP_FUNCTION_CODE 0x02 -#define SCP_CONTROL_MASK 0x03 -#define SCP_RESPONSE_CODE 0x06 -#define SCP_MEM_CODE 0x08 -#define SCP_INCREMENT 0x0a - typedef struct LowCore { /* prefix area: defined by architecture */ @@ -955,7 +944,7 @@ static inline void ebcdic_put(uint8_t *p, const char *ascii, int len) void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr); int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc, target_ulong *raddr, int *flags); -int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code); +int sclp_service_call(uint32_t sccb, uint64_t code); uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst, uint64_t vr); diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index e19a44d637..a66ac4341c 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -60,9 +60,6 @@ #define SIGP_STORE_STATUS_ADDR 0x0e #define SIGP_SET_ARCH 0x12 -#define SCLP_CMDW_READ_SCP_INFO 0x00020001 -#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 - const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_LAST_INFO }; @@ -344,7 +341,7 @@ static int kvm_sclp_service_call(CPUS390XState *env, struct kvm_run *run, sccb = env->regs[ipbh0 & 0xf]; code = env->regs[(ipbh0 & 0xf0) >> 4]; - r = sclp_service_call(env, sccb, code); + r = sclp_service_call(sccb, code); if (r < 0) { enter_pgmcheck(env, -r); } diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index fdccd58e3d..38d8f2a627 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -67,55 +67,12 @@ void program_interrupt(CPUS390XState *env, uint32_t code, int ilc) } } -/* - * ret < 0 indicates program check, ret = 0, 1, 2, 3 -> cc - */ -int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code) -{ - int r = 0; - int shift = 0; - -#ifdef DEBUG_HELPER - printf("sclp(0x%x, 0x%" PRIx64 ")\n", sccb, code); -#endif - - /* basic checks */ - if (cpu_physical_memory_is_io(sccb)) { - return -PGM_ADDRESSING; - } - if (sccb & ~0x7ffffff8ul) { - return -PGM_SPECIFICATION; - } - - switch (code) { - case SCLP_CMDW_READ_SCP_INFO: - case SCLP_CMDW_READ_SCP_INFO_FORCED: - while ((ram_size >> (20 + shift)) > 65535) { - shift++; - } - stw_phys(sccb + SCP_MEM_CODE, ram_size >> (20 + shift)); - stb_phys(sccb + SCP_INCREMENT, 1 << shift); - stw_phys(sccb + SCP_RESPONSE_CODE, 0x10); - - s390_sclp_extint(sccb & ~3); - break; - default: -#ifdef DEBUG_HELPER - printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code); -#endif - r = 3; - break; - } - - return r; -} - /* SCLP service call */ uint32_t HELPER(servc)(CPUS390XState *env, uint32_t r1, uint64_t r2) { int r; - r = sclp_service_call(env, r1, r2); + r = sclp_service_call(r1, r2); if (r < 0) { program_interrupt(env, -r, 4); return 0; From 559a17a1439e34a95dcab47ef99022bcd0e8f8e7 Mon Sep 17 00:00:00 2001 From: Heinz Graalfs Date: Mon, 29 Oct 2012 02:13:23 +0000 Subject: [PATCH 1256/2270] s390: sclp event support Several SCLP features are considered to be events. Those events don't provide SCLP commands on their own, instead they are all based on Read Event Data, Write Event Data, Write Event Mask and the service interrupt. Follow-on patches will provide SCLP's Signal Quiesce (via system_powerdown) and the ASCII console. Further down the road the sclp line mode console and configuration change events (e.g. cpu hotplug) can be implemented. Signed-off-by: Heinz Graalfs Signed-off-by: Christian Borntraeger Signed-off-by: Jens Freimann Signed-off-by: Alexander Graf --- hw/s390-virtio.c | 2 + hw/s390x/Makefile.objs | 1 + hw/s390x/event-facility.c | 391 ++++++++++++++++++++++++++++++++++++++ hw/s390x/event-facility.h | 96 ++++++++++ hw/s390x/sclp.c | 49 ++++- hw/s390x/sclp.h | 42 ++++ 6 files changed, 579 insertions(+), 2 deletions(-) create mode 100644 hw/s390x/event-facility.c create mode 100644 hw/s390x/event-facility.h diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index 52fad37526..685cb5413e 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -32,6 +32,7 @@ #include "exec-memory.h" #include "hw/s390-virtio-bus.h" +#include "hw/s390x/sclp.h" //#define DEBUG_S390 @@ -184,6 +185,7 @@ static void s390_init(QEMUMachineInitArgs *args) /* get a BUS */ s390_bus = s390_virtio_bus_init(&my_ram_size); + s390_sclp_init(); /* allocate RAM */ memory_region_init_ram(ram, "s390.ram", my_ram_size); diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index 1c14b96687..b32fc52fd1 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -2,3 +2,4 @@ obj-y = s390-virtio-bus.o s390-virtio.o obj-y := $(addprefix ../,$(obj-y)) obj-y += sclp.o +obj-y += event-facility.o diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c new file mode 100644 index 0000000000..1108e2d246 --- /dev/null +++ b/hw/s390x/event-facility.c @@ -0,0 +1,391 @@ +/* + * SCLP + * Event Facility + * handles SCLP event types + * - Signal Quiesce - system power down + * - ASCII Console Data - VT220 read and write + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Heinz Graalfs + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. + * + */ + +#include "monitor.h" +#include "sysemu.h" + +#include "sclp.h" +#include "event-facility.h" + +typedef struct EventTypesBus { + BusState qbus; +} EventTypesBus; + +struct SCLPEventFacility { + EventTypesBus sbus; + DeviceState *qdev; + /* guest' receive mask */ + unsigned int receive_mask; +}; + +/* return true if any child has event pending set */ +static bool event_pending(SCLPEventFacility *ef) +{ + BusChild *kid; + SCLPEvent *event; + SCLPEventClass *event_class; + + QTAILQ_FOREACH(kid, &ef->sbus.qbus.children, sibling) { + DeviceState *qdev = kid->child; + event = DO_UPCAST(SCLPEvent, qdev, qdev); + event_class = SCLP_EVENT_GET_CLASS(event); + if (event->event_pending && + event_class->get_send_mask() & ef->receive_mask) { + return true; + } + } + return false; +} + +static unsigned int get_host_send_mask(SCLPEventFacility *ef) +{ + unsigned int mask; + BusChild *kid; + SCLPEventClass *child; + + mask = 0; + + QTAILQ_FOREACH(kid, &ef->sbus.qbus.children, sibling) { + DeviceState *qdev = kid->child; + child = SCLP_EVENT_GET_CLASS((SCLPEvent *) qdev); + mask |= child->get_send_mask(); + } + return mask; +} + +static unsigned int get_host_receive_mask(SCLPEventFacility *ef) +{ + unsigned int mask; + BusChild *kid; + SCLPEventClass *child; + + mask = 0; + + QTAILQ_FOREACH(kid, &ef->sbus.qbus.children, sibling) { + DeviceState *qdev = kid->child; + child = SCLP_EVENT_GET_CLASS((SCLPEvent *) qdev); + mask |= child->get_receive_mask(); + } + return mask; +} + +static uint16_t write_event_length_check(SCCB *sccb) +{ + int slen; + unsigned elen = 0; + EventBufferHeader *event; + WriteEventData *wed = (WriteEventData *) sccb; + + event = (EventBufferHeader *) &wed->ebh; + for (slen = sccb_data_len(sccb); slen > 0; slen -= elen) { + elen = be16_to_cpu(event->length); + if (elen < sizeof(*event) || elen > slen) { + return SCLP_RC_EVENT_BUFFER_SYNTAX_ERROR; + } + event = (void *) event + elen; + } + if (slen) { + return SCLP_RC_INCONSISTENT_LENGTHS; + } + return SCLP_RC_NORMAL_COMPLETION; +} + +static uint16_t handle_write_event_buf(SCLPEventFacility *ef, + EventBufferHeader *event_buf, SCCB *sccb) +{ + uint16_t rc; + BusChild *kid; + SCLPEvent *event; + SCLPEventClass *ec; + + QTAILQ_FOREACH(kid, &ef->sbus.qbus.children, sibling) { + DeviceState *qdev = kid->child; + event = (SCLPEvent *) qdev; + ec = SCLP_EVENT_GET_CLASS(event); + + rc = SCLP_RC_INVALID_FUNCTION; + if (ec->write_event_data && + ec->event_type() == event_buf->type) { + rc = ec->write_event_data(event, event_buf); + break; + } + } + return rc; +} + +static uint16_t handle_sccb_write_events(SCLPEventFacility *ef, SCCB *sccb) +{ + uint16_t rc; + int slen; + unsigned elen = 0; + EventBufferHeader *event_buf; + WriteEventData *wed = (WriteEventData *) sccb; + + event_buf = &wed->ebh; + rc = SCLP_RC_NORMAL_COMPLETION; + + /* loop over all contained event buffers */ + for (slen = sccb_data_len(sccb); slen > 0; slen -= elen) { + elen = be16_to_cpu(event_buf->length); + + /* in case of a previous error mark all trailing buffers + * as not accepted */ + if (rc != SCLP_RC_NORMAL_COMPLETION) { + event_buf->flags &= ~(SCLP_EVENT_BUFFER_ACCEPTED); + } else { + rc = handle_write_event_buf(ef, event_buf, sccb); + } + event_buf = (void *) event_buf + elen; + } + return rc; +} + +static void write_event_data(SCLPEventFacility *ef, SCCB *sccb) +{ + if (sccb->h.function_code != SCLP_FC_NORMAL_WRITE) { + sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_FUNCTION); + goto out; + } + if (be16_to_cpu(sccb->h.length) < 8) { + sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH); + goto out; + } + /* first do a sanity check of the write events */ + sccb->h.response_code = cpu_to_be16(write_event_length_check(sccb)); + + /* if no early error, then execute */ + if (sccb->h.response_code == be16_to_cpu(SCLP_RC_NORMAL_COMPLETION)) { + sccb->h.response_code = + cpu_to_be16(handle_sccb_write_events(ef, sccb)); + } + +out: + return; +} + +static uint16_t handle_sccb_read_events(SCLPEventFacility *ef, SCCB *sccb, + unsigned int mask) +{ + uint16_t rc; + int slen; + unsigned elen = 0; + BusChild *kid; + SCLPEvent *event; + SCLPEventClass *ec; + EventBufferHeader *event_buf; + ReadEventData *red = (ReadEventData *) sccb; + + event_buf = &red->ebh; + event_buf->length = 0; + slen = sizeof(sccb->data); + + rc = SCLP_RC_NO_EVENT_BUFFERS_STORED; + + QTAILQ_FOREACH(kid, &ef->sbus.qbus.children, sibling) { + DeviceState *qdev = kid->child; + event = (SCLPEvent *) qdev; + ec = SCLP_EVENT_GET_CLASS(event); + + if (mask & ec->get_send_mask()) { + if (ec->read_event_data(event, event_buf, &slen)) { + rc = SCLP_RC_NORMAL_COMPLETION; + } + } + elen = be16_to_cpu(event_buf->length); + event_buf = (void *) event_buf + elen; + } + + if (sccb->h.control_mask[2] & SCLP_VARIABLE_LENGTH_RESPONSE) { + /* architecture suggests to reset variable-length-response bit */ + sccb->h.control_mask[2] &= ~SCLP_VARIABLE_LENGTH_RESPONSE; + /* with a new length value */ + sccb->h.length = cpu_to_be16(SCCB_SIZE - slen); + } + return rc; +} + +static void read_event_data(SCLPEventFacility *ef, SCCB *sccb) +{ + unsigned int sclp_active_selection_mask; + unsigned int sclp_cp_receive_mask; + + ReadEventData *red = (ReadEventData *) sccb; + + if (be16_to_cpu(sccb->h.length) != SCCB_SIZE) { + sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH); + goto out; + } + + sclp_cp_receive_mask = ef->receive_mask; + + /* get active selection mask */ + switch (sccb->h.function_code) { + case SCLP_UNCONDITIONAL_READ: + sclp_active_selection_mask = sclp_cp_receive_mask; + break; + case SCLP_SELECTIVE_READ: + if (!(sclp_cp_receive_mask & be32_to_cpu(red->mask))) { + sccb->h.response_code = + cpu_to_be16(SCLP_RC_INVALID_SELECTION_MASK); + goto out; + } + sclp_active_selection_mask = be32_to_cpu(red->mask); + break; + default: + sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_FUNCTION); + goto out; + } + sccb->h.response_code = cpu_to_be16( + handle_sccb_read_events(ef, sccb, sclp_active_selection_mask)); + +out: + return; +} + +static void write_event_mask(SCLPEventFacility *ef, SCCB *sccb) +{ + WriteEventMask *we_mask = (WriteEventMask *) sccb; + + /* Attention: We assume that Linux uses 4-byte masks, what it actually + does. Architecture allows for masks of variable size, though */ + if (be16_to_cpu(we_mask->mask_length) != 4) { + sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_MASK_LENGTH); + goto out; + } + + /* keep track of the guest's capability masks */ + ef->receive_mask = be32_to_cpu(we_mask->cp_receive_mask); + + /* return the SCLP's capability masks to the guest */ + we_mask->send_mask = cpu_to_be32(get_host_send_mask(ef)); + we_mask->receive_mask = cpu_to_be32(get_host_receive_mask(ef)); + + sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_COMPLETION); + +out: + return; +} + +/* qemu object creation and initialization functions */ + +#define TYPE_SCLP_EVENTS_BUS "s390-sclp-events-bus" + +static void sclp_events_bus_class_init(ObjectClass *klass, void *data) +{ +} + +static const TypeInfo s390_sclp_events_bus_info = { + .name = TYPE_SCLP_EVENTS_BUS, + .parent = TYPE_BUS, + .class_init = sclp_events_bus_class_init, +}; + +static void command_handler(SCLPEventFacility *ef, SCCB *sccb, uint64_t code) +{ + switch (code) { + case SCLP_CMD_READ_EVENT_DATA: + read_event_data(ef, sccb); + break; + case SCLP_CMD_WRITE_EVENT_DATA: + write_event_data(ef, sccb); + break; + case SCLP_CMD_WRITE_EVENT_MASK: + write_event_mask(ef, sccb); + break; + default: + sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND); + break; + } +} + +static int init_event_facility(S390SCLPDevice *sdev) +{ + SCLPEventFacility *event_facility; + + event_facility = g_malloc0(sizeof(SCLPEventFacility)); + sdev->ef = event_facility; + sdev->sclp_command_handler = command_handler; + sdev->event_pending = event_pending; + + /* Spawn a new sclp-events facility */ + qbus_create_inplace(&event_facility->sbus.qbus, + TYPE_SCLP_EVENTS_BUS, (DeviceState *)sdev, NULL); + event_facility->sbus.qbus.allow_hotplug = 0; + event_facility->qdev = (DeviceState *) sdev; + + return 0; +} + +static void init_event_facility_class(ObjectClass *klass, void *data) +{ + S390SCLPDeviceClass *k = SCLP_S390_DEVICE_CLASS(klass); + + k->init = init_event_facility; +} + +static TypeInfo s390_sclp_event_facility_info = { + .name = "s390-sclp-event-facility", + .parent = TYPE_DEVICE_S390_SCLP, + .instance_size = sizeof(S390SCLPDevice), + .class_init = init_event_facility_class, +}; + +static int event_qdev_init(DeviceState *qdev) +{ + SCLPEvent *event = DO_UPCAST(SCLPEvent, qdev, qdev); + SCLPEventClass *child = SCLP_EVENT_GET_CLASS(event); + + return child->init(event); +} + +static int event_qdev_exit(DeviceState *qdev) +{ + SCLPEvent *event = DO_UPCAST(SCLPEvent, qdev, qdev); + SCLPEventClass *child = SCLP_EVENT_GET_CLASS(event); + if (child->exit) { + child->exit(event); + } + return 0; +} + +static void event_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->bus_type = TYPE_SCLP_EVENTS_BUS; + dc->unplug = qdev_simple_unplug_cb; + dc->init = event_qdev_init; + dc->exit = event_qdev_exit; +} + +static TypeInfo s390_sclp_event_type_info = { + .name = TYPE_SCLP_EVENT, + .parent = TYPE_DEVICE, + .instance_size = sizeof(SCLPEvent), + .class_init = event_class_init, + .class_size = sizeof(SCLPEventClass), + .abstract = true, +}; + +static void register_types(void) +{ + type_register_static(&s390_sclp_events_bus_info); + type_register_static(&s390_sclp_event_facility_info); + type_register_static(&s390_sclp_event_type_info); +} + +type_init(register_types) diff --git a/hw/s390x/event-facility.h b/hw/s390x/event-facility.h new file mode 100644 index 0000000000..30af0a76a7 --- /dev/null +++ b/hw/s390x/event-facility.h @@ -0,0 +1,96 @@ +/* + * SCLP + * Event Facility definitions + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Heinz Graalfs + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. + * + */ + +#ifndef HW_S390_SCLP_EVENT_FACILITY_H +#define HW_S390_SCLP_EVENT_FACILITY_H + +#include +#include "qemu-thread.h" + +/* SCLP event types */ +#define SCLP_EVENT_ASCII_CONSOLE_DATA 0x1a +#define SCLP_EVENT_SIGNAL_QUIESCE 0x1d + +/* SCLP event masks */ +#define SCLP_EVENT_MASK_SIGNAL_QUIESCE 0x00000008 +#define SCLP_EVENT_MASK_MSG_ASCII 0x00000040 + +#define SCLP_UNCONDITIONAL_READ 0x00 +#define SCLP_SELECTIVE_READ 0x01 + +#define TYPE_SCLP_EVENT "s390-sclp-event-type" +#define SCLP_EVENT(obj) \ + OBJECT_CHECK(SCLPEvent, (obj), TYPE_SCLP_EVENT) +#define SCLP_EVENT_CLASS(klass) \ + OBJECT_CLASS_CHECK(SCLPEventClass, (klass), TYPE_SCLP_EVENT) +#define SCLP_EVENT_GET_CLASS(obj) \ + OBJECT_GET_CLASS(SCLPEventClass, (obj), TYPE_SCLP_EVENT) + +typedef struct WriteEventMask { + SCCBHeader h; + uint16_t _reserved; + uint16_t mask_length; + uint32_t cp_receive_mask; + uint32_t cp_send_mask; + uint32_t send_mask; + uint32_t receive_mask; +} QEMU_PACKED WriteEventMask; + +typedef struct EventBufferHeader { + uint16_t length; + uint8_t type; + uint8_t flags; + uint16_t _reserved; +} QEMU_PACKED EventBufferHeader; + +typedef struct WriteEventData { + SCCBHeader h; + EventBufferHeader ebh; +} QEMU_PACKED WriteEventData; + +typedef struct ReadEventData { + SCCBHeader h; + EventBufferHeader ebh; + uint32_t mask; +} QEMU_PACKED ReadEventData; + +typedef struct SCLPEvent { + DeviceState qdev; + bool event_pending; + uint32_t event_type; + char *name; +} SCLPEvent; + +typedef struct SCLPEventClass { + DeviceClass parent_class; + int (*init)(SCLPEvent *event); + int (*exit)(SCLPEvent *event); + + /* get SCLP's send mask */ + unsigned int (*get_send_mask)(void); + + /* get SCLP's receive mask */ + unsigned int (*get_receive_mask)(void); + + int (*read_event_data)(SCLPEvent *event, EventBufferHeader *evt_buf_hdr, + int *slen); + + int (*write_event_data)(SCLPEvent *event, EventBufferHeader *evt_buf_hdr); + + /* returns the supported event type */ + int (*event_type)(void); + +} SCLPEventClass; + +#endif diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c index d902a66261..5c274fa03d 100644 --- a/hw/s390x/sclp.c +++ b/hw/s390x/sclp.c @@ -18,6 +18,15 @@ #include "sclp.h" +static inline S390SCLPDevice *get_event_facility(void) +{ + ObjectProperty *op = object_property_find(qdev_get_machine(), + "s390-sclp-event-facility", + NULL); + assert(op); + return op->opaque; +} + /* Provide information about the configuration, CPUs and storage */ static void read_SCP_info(SCCB *sccb) { @@ -34,13 +43,15 @@ static void read_SCP_info(SCCB *sccb) static void sclp_execute(SCCB *sccb, uint64_t code) { + S390SCLPDevice *sdev = get_event_facility(); + switch (code) { case SCLP_CMDW_READ_SCP_INFO: case SCLP_CMDW_READ_SCP_INFO_FORCED: read_SCP_info(sccb); break; default: - sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND); + sdev->sclp_command_handler(sdev->ef, sccb, code); break; } } @@ -89,11 +100,45 @@ out: void sclp_service_interrupt(uint32_t sccb) { - s390_sclp_extint(sccb & ~3); + S390SCLPDevice *sdev = get_event_facility(); + uint32_t param = sccb & ~3; + + /* Indicate whether an event is still pending */ + param |= sdev->event_pending(sdev->ef) ? 1 : 0; + + if (!param) { + /* No need to send an interrupt, there's nothing to be notified about */ + return; + } + s390_sclp_extint(param); } /* qemu object creation and initialization functions */ +void s390_sclp_init(void) +{ + DeviceState *dev = qdev_create(NULL, "s390-sclp-event-facility"); + + object_property_add_child(qdev_get_machine(), "s390-sclp-event-facility", + OBJECT(dev), NULL); + qdev_init_nofail(dev); +} + +static int s390_sclp_dev_init(SysBusDevice *dev) +{ + int r; + S390SCLPDevice *sdev = (S390SCLPDevice *)dev; + S390SCLPDeviceClass *sclp = SCLP_S390_DEVICE_GET_CLASS(dev); + + r = sclp->init(sdev); + if (!r) { + assert(sdev->event_pending); + assert(sdev->sclp_command_handler); + } + + return r; +} + static void s390_sclp_device_class_init(ObjectClass *klass, void *data) { SysBusDeviceClass *dc = SYS_BUS_DEVICE_CLASS(klass); diff --git a/hw/s390x/sclp.h b/hw/s390x/sclp.h index e9ad42bec2..fe89dadd68 100644 --- a/hw/s390x/sclp.h +++ b/hw/s390x/sclp.h @@ -20,15 +20,35 @@ /* SCLP command codes */ #define SCLP_CMDW_READ_SCP_INFO 0x00020001 #define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 +#define SCLP_CMD_READ_EVENT_DATA 0x00770005 +#define SCLP_CMD_WRITE_EVENT_DATA 0x00760005 +#define SCLP_CMD_READ_EVENT_DATA 0x00770005 +#define SCLP_CMD_WRITE_EVENT_DATA 0x00760005 +#define SCLP_CMD_WRITE_EVENT_MASK 0x00780005 /* SCLP response codes */ #define SCLP_RC_NORMAL_READ_COMPLETION 0x0010 +#define SCLP_RC_NORMAL_COMPLETION 0x0020 #define SCLP_RC_INVALID_SCLP_COMMAND 0x01f0 +#define SCLP_RC_CONTAINED_EQUIPMENT_CHECK 0x0340 +#define SCLP_RC_INSUFFICIENT_SCCB_LENGTH 0x0300 +#define SCLP_RC_INVALID_FUNCTION 0x40f0 +#define SCLP_RC_NO_EVENT_BUFFERS_STORED 0x60f0 +#define SCLP_RC_INVALID_SELECTION_MASK 0x70f0 +#define SCLP_RC_INCONSISTENT_LENGTHS 0x72f0 +#define SCLP_RC_EVENT_BUFFER_SYNTAX_ERROR 0x73f0 +#define SCLP_RC_INVALID_MASK_LENGTH 0x74f0 + /* Service Call Control Block (SCCB) and its elements */ #define SCCB_SIZE 4096 +#define SCLP_VARIABLE_LENGTH_RESPONSE 0x80 +#define SCLP_EVENT_BUFFER_ACCEPTED 0x80 + +#define SCLP_FC_NORMAL_WRITE 0 + /* * Normally packed structures are not the right thing to do, since all code * must take care of endianess. We cant use ldl_phys and friends for two @@ -62,8 +82,29 @@ typedef struct SCCB { char data[SCCB_DATA_LEN]; } QEMU_PACKED SCCB; +static inline int sccb_data_len(SCCB *sccb) +{ + return be16_to_cpu(sccb->h.length) - sizeof(sccb->h); +} + +#define TYPE_DEVICE_S390_SCLP "s390-sclp-device" +#define SCLP_S390_DEVICE(obj) \ + OBJECT_CHECK(S390SCLPDevice, (obj), TYPE_DEVICE_S390_SCLP) +#define SCLP_S390_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(S390SCLPDeviceClass, (klass), \ + TYPE_DEVICE_S390_SCLP) +#define SCLP_S390_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(S390SCLPDeviceClass, (obj), \ + TYPE_DEVICE_S390_SCLP) + +typedef struct SCLPEventFacility SCLPEventFacility; + typedef struct S390SCLPDevice { SysBusDevice busdev; + SCLPEventFacility *ef; + void (*sclp_command_handler)(SCLPEventFacility *ef, SCCB *sccb, + uint64_t code); + bool (*event_pending)(SCLPEventFacility *ef); } S390SCLPDevice; typedef struct S390SCLPDeviceClass { @@ -71,6 +112,7 @@ typedef struct S390SCLPDeviceClass { int (*init)(S390SCLPDevice *sdev); } S390SCLPDeviceClass; +void s390_sclp_init(void); void sclp_service_interrupt(uint32_t sccb); #endif From ab9074b559823a22822db9e299198c53169c34ea Mon Sep 17 00:00:00 2001 From: Heinz Graalfs Date: Mon, 29 Oct 2012 02:13:24 +0000 Subject: [PATCH 1257/2270] s390: sclp signal quiesce support This implements the sclp signal quiesce event via the SCLP Event Facility. This allows to gracefully shutdown a guest by using system_powerdown notifiers. It creates a service interrupt that will trigger a Read Event Data command from the guest. This code will then add an event that is interpreted by linux guests as ctrl-alt-del. Signed-off-by: Heinz Graalfs Signed-off-by: Christian Borntraeger Signed-off-by: Jens Freimann Signed-off-by: Alexander Graf --- hw/s390x/Makefile.objs | 1 + hw/s390x/event-facility.c | 7 +++ hw/s390x/sclpquiesce.c | 123 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 hw/s390x/sclpquiesce.c diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index b32fc52fd1..ed4e61a795 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -3,3 +3,4 @@ obj-y = s390-virtio-bus.o s390-virtio.o obj-y := $(addprefix ../,$(obj-y)) obj-y += sclp.o obj-y += event-facility.o +obj-y += sclpquiesce.o diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c index 1108e2d246..93676602a7 100644 --- a/hw/s390x/event-facility.c +++ b/hw/s390x/event-facility.c @@ -315,6 +315,7 @@ static void command_handler(SCLPEventFacility *ef, SCCB *sccb, uint64_t code) static int init_event_facility(S390SCLPDevice *sdev) { SCLPEventFacility *event_facility; + DeviceState *quiesce; event_facility = g_malloc0(sizeof(SCLPEventFacility)); sdev->ef = event_facility; @@ -327,6 +328,12 @@ static int init_event_facility(S390SCLPDevice *sdev) event_facility->sbus.qbus.allow_hotplug = 0; event_facility->qdev = (DeviceState *) sdev; + quiesce = qdev_create(&event_facility->sbus.qbus, "sclpquiesce"); + if (!quiesce) { + return -1; + } + qdev_init_nofail(quiesce); + return 0; } diff --git a/hw/s390x/sclpquiesce.c b/hw/s390x/sclpquiesce.c new file mode 100644 index 0000000000..9a773b87ff --- /dev/null +++ b/hw/s390x/sclpquiesce.c @@ -0,0 +1,123 @@ +/* + * SCLP event type + * Signal Quiesce - trigger system powerdown request + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Heinz Graalfs + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. + * + */ +#include +#include "sysemu.h" +#include "sclp.h" +#include "event-facility.h" + +typedef struct SignalQuiesce { + EventBufferHeader ebh; + uint16_t timeout; + uint8_t unit; +} QEMU_PACKED SignalQuiesce; + +static int event_type(void) +{ + return SCLP_EVENT_SIGNAL_QUIESCE; +} + +static unsigned int send_mask(void) +{ + return SCLP_EVENT_MASK_SIGNAL_QUIESCE; +} + +static unsigned int receive_mask(void) +{ + return 0; +} + +static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr, + int *slen) +{ + SignalQuiesce *sq = (SignalQuiesce *) evt_buf_hdr; + + if (*slen < sizeof(SignalQuiesce)) { + return 0; + } + + if (!event->event_pending) { + return 0; + } + event->event_pending = false; + + sq->ebh.length = cpu_to_be16(sizeof(SignalQuiesce)); + sq->ebh.type = SCLP_EVENT_SIGNAL_QUIESCE; + sq->ebh.flags |= SCLP_EVENT_BUFFER_ACCEPTED; + /* + * system_powerdown does not have a timeout. Fortunately the + * timeout value is currently ignored by Linux, anyway + */ + sq->timeout = cpu_to_be16(0); + sq->unit = cpu_to_be16(0); + *slen -= sizeof(SignalQuiesce); + + return 1; +} + +typedef struct QuiesceNotifier QuiesceNotifier; + +static struct QuiesceNotifier { + Notifier notifier; + SCLPEvent *event; +} qn; + +static void quiesce_powerdown_req(Notifier *n, void *opaque) +{ + QuiesceNotifier *qn = container_of(n, QuiesceNotifier, notifier); + SCLPEvent *event = qn->event; + + event->event_pending = true; + /* trigger SCLP read operation */ + sclp_service_interrupt(0); +} + +static int quiesce_init(SCLPEvent *event) +{ + event->event_type = SCLP_EVENT_SIGNAL_QUIESCE; + + qn.notifier.notify = quiesce_powerdown_req; + qn.event = event; + + qemu_register_powerdown_notifier(&qn.notifier); + + return 0; +} + +static void quiesce_class_init(ObjectClass *klass, void *data) +{ + SCLPEventClass *k = SCLP_EVENT_CLASS(klass); + + k->init = quiesce_init; + + k->get_send_mask = send_mask; + k->get_receive_mask = receive_mask; + k->event_type = event_type; + k->read_event_data = read_event_data; + k->write_event_data = NULL; +} + +static TypeInfo sclp_quiesce_info = { + .name = "sclpquiesce", + .parent = TYPE_SCLP_EVENT, + .instance_size = sizeof(SCLPEvent), + .class_init = quiesce_class_init, + .class_size = sizeof(SCLPEventClass), +}; + +static void register_types(void) +{ + type_register_static(&sclp_quiesce_info); +} + +type_init(register_types) From 130c57c036fdc2eba8936da1b1dad39e78d5ea32 Mon Sep 17 00:00:00 2001 From: Heinz Graalfs Date: Mon, 29 Oct 2012 02:13:25 +0000 Subject: [PATCH 1258/2270] s390: sclp ascii console support This code adds console support by implementing SCLP's ASCII Console Data event. This is the same console as LPARs ASCII console or z/VMs sysascii. The console can be specified manually with something like -chardev stdio,id=charconsole0 -device sclpconsole,chardev=charconsole0,id=console0 Newer kernels will autodetect that console and prefer that over virtio console. When data is received from the character layer it creates a service interrupt to trigger a Read Event Data command from the guest that will pick up the received character byte-stream. When characters are echo'ed by the linux guest a Write Event Data occurs which is forwarded by the Event Facility to the console that supports a corresponding mask value. Console resizing is not supported. The character layer byte-stream is buffered using a fixed size iov buffer. Signed-off-by: Heinz Graalfs Signed-off-by: Christian Borntraeger Signed-off-by: Jens Freimann Signed-off-by: Alexander Graf --- hw/s390x/Makefile.objs | 2 +- hw/s390x/sclpconsole.c | 306 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 hw/s390x/sclpconsole.c diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index ed4e61a795..096dfcd6a1 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -3,4 +3,4 @@ obj-y = s390-virtio-bus.o s390-virtio.o obj-y := $(addprefix ../,$(obj-y)) obj-y += sclp.o obj-y += event-facility.o -obj-y += sclpquiesce.o +obj-y += sclpquiesce.o sclpconsole.o diff --git a/hw/s390x/sclpconsole.c b/hw/s390x/sclpconsole.c new file mode 100644 index 0000000000..0ec5623f57 --- /dev/null +++ b/hw/s390x/sclpconsole.c @@ -0,0 +1,306 @@ +/* + * SCLP event type + * Ascii Console Data (VT220 Console) + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Heinz Graalfs + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. + * + */ + +#include +#include "qemu-thread.h" + +#include "sclp.h" +#include "event-facility.h" + +typedef struct ASCIIConsoleData { + EventBufferHeader ebh; + char data[0]; +} QEMU_PACKED ASCIIConsoleData; + +/* max size for ASCII data in 4K SCCB page */ +#define SIZE_BUFFER_VT220 4080 + +typedef struct SCLPConsole { + SCLPEvent event; + CharDriverState *chr; + /* io vector */ + uint8_t *iov; /* iov buffer pointer */ + uint8_t *iov_sclp; /* pointer to SCLP read offset */ + uint8_t *iov_bs; /* pointer byte stream read offset */ + uint32_t iov_data_len; /* length of byte stream in buffer */ + uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP */ + qemu_irq irq_read_vt220; +} SCLPConsole; + +/* character layer call-back functions */ + +/* Return number of bytes that fit into iov buffer */ +static int chr_can_read(void *opaque) +{ + int can_read; + SCLPConsole *scon = opaque; + + can_read = SIZE_BUFFER_VT220 - scon->iov_data_len; + + return can_read; +} + +/* Receive n bytes from character layer, save in iov buffer, + * and set event pending */ +static void receive_from_chr_layer(SCLPConsole *scon, const uint8_t *buf, + int size) +{ + assert(scon->iov); + + /* read data must fit into current buffer */ + assert(size <= SIZE_BUFFER_VT220 - scon->iov_data_len); + + /* put byte-stream from character layer into buffer */ + memcpy(scon->iov_bs, buf, size); + scon->iov_data_len += size; + scon->iov_sclp_rest += size; + scon->iov_bs += size; + scon->event.event_pending = true; +} + +/* Send data from a char device over to the guest */ +static void chr_read(void *opaque, const uint8_t *buf, int size) +{ + SCLPConsole *scon = opaque; + + assert(scon); + + receive_from_chr_layer(scon, buf, size); + /* trigger SCLP read operation */ + qemu_irq_raise(scon->irq_read_vt220); +} + +static void chr_event(void *opaque, int event) +{ + SCLPConsole *scon = opaque; + + switch (event) { + case CHR_EVENT_OPENED: + if (!scon->iov) { + scon->iov = g_malloc0(SIZE_BUFFER_VT220); + scon->iov_sclp = scon->iov; + scon->iov_bs = scon->iov; + scon->iov_data_len = 0; + scon->iov_sclp_rest = 0; + } + break; + case CHR_EVENT_CLOSED: + if (scon->iov) { + g_free(scon->iov); + scon->iov = NULL; + } + break; + } +} + +/* functions to be called by event facility */ + +static int event_type(void) +{ + return SCLP_EVENT_ASCII_CONSOLE_DATA; +} + +static unsigned int send_mask(void) +{ + return SCLP_EVENT_MASK_MSG_ASCII; +} + +static unsigned int receive_mask(void) +{ + return SCLP_EVENT_MASK_MSG_ASCII; +} + +/* triggered by SCLP's read_event_data - + * copy console data byte-stream into provided (SCLP) buffer + */ +static void get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size, + int avail) +{ + SCLPConsole *cons = DO_UPCAST(SCLPConsole, event, event); + + /* first byte is hex 0 saying an ascii string follows */ + *buf++ = '\0'; + avail--; + /* if all data fit into provided SCLP buffer */ + if (avail >= cons->iov_sclp_rest) { + /* copy character byte-stream to SCLP buffer */ + memcpy(buf, cons->iov_sclp, cons->iov_sclp_rest); + *size = cons->iov_sclp_rest + 1; + cons->iov_sclp = cons->iov; + cons->iov_bs = cons->iov; + cons->iov_data_len = 0; + cons->iov_sclp_rest = 0; + event->event_pending = false; + /* data provided and no more data pending */ + } else { + /* if provided buffer is too small, just copy part */ + memcpy(buf, cons->iov_sclp, avail); + *size = avail + 1; + cons->iov_sclp_rest -= avail; + cons->iov_sclp += avail; + /* more data pending */ + } +} + +static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr, + int *slen) +{ + int avail; + size_t src_len; + uint8_t *to; + ASCIIConsoleData *acd = (ASCIIConsoleData *) evt_buf_hdr; + + if (!event->event_pending) { + /* no data pending */ + return 0; + } + + to = (uint8_t *)&acd->data; + avail = *slen - sizeof(ASCIIConsoleData); + get_console_data(event, to, &src_len, avail); + + acd->ebh.length = cpu_to_be16(sizeof(ASCIIConsoleData) + src_len); + acd->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA; + acd->ebh.flags |= SCLP_EVENT_BUFFER_ACCEPTED; + *slen = avail - src_len; + + return 1; +} + +/* triggered by SCLP's write_event_data + * - write console data into character layer + * returns < 0 if an error occured + */ +static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf, + size_t len) +{ + ssize_t ret = 0; + const uint8_t *iov_offset; + SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event); + + if (!scon->chr) { + /* If there's no backend, we can just say we consumed all data. */ + return len; + } + + iov_offset = buf; + while (len > 0) { + ret = qemu_chr_fe_write(scon->chr, buf, len); + if (ret == 0) { + /* a pty doesn't seem to be connected - no error */ + len = 0; + } else if (ret == -EAGAIN || (ret > 0 && ret < len)) { + len -= ret; + iov_offset += ret; + } else { + len = 0; + } + } + + return ret; +} + +static int write_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr) +{ + int rc; + int length; + ssize_t written; + ASCIIConsoleData *acd = (ASCIIConsoleData *) evt_buf_hdr; + + length = be16_to_cpu(evt_buf_hdr->length) - sizeof(EventBufferHeader); + written = write_console_data(event, (uint8_t *)acd->data, length); + + rc = SCLP_RC_NORMAL_COMPLETION; + /* set event buffer accepted flag */ + evt_buf_hdr->flags |= SCLP_EVENT_BUFFER_ACCEPTED; + + /* written will be zero if a pty is not connected - don't treat as error */ + if (written < 0) { + /* event buffer not accepted due to error in character layer */ + evt_buf_hdr->flags &= ~(SCLP_EVENT_BUFFER_ACCEPTED); + rc = SCLP_RC_CONTAINED_EQUIPMENT_CHECK; + } + + return rc; +} + +static void trigger_ascii_console_data(void *env, int n, int level) +{ + sclp_service_interrupt(0); +} + +/* qemu object creation and initialization functions */ + +/* tell character layer our call-back functions */ +static int console_init(SCLPEvent *event) +{ + static bool console_available; + + SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event); + + if (console_available) { + error_report("Multiple VT220 operator consoles are not supported"); + return -1; + } + console_available = true; + event->event_type = SCLP_EVENT_ASCII_CONSOLE_DATA; + if (scon->chr) { + qemu_chr_add_handlers(scon->chr, chr_can_read, + chr_read, chr_event, scon); + } + scon->irq_read_vt220 = *qemu_allocate_irqs(trigger_ascii_console_data, + NULL, 1); + + return 0; +} + +static int console_exit(SCLPEvent *event) +{ + return 0; +} + +static Property console_properties[] = { + DEFINE_PROP_CHR("chardev", SCLPConsole, chr), + DEFINE_PROP_END_OF_LIST(), +}; + +static void console_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SCLPEventClass *ec = SCLP_EVENT_CLASS(klass); + + dc->props = console_properties; + ec->init = console_init; + ec->exit = console_exit; + ec->get_send_mask = send_mask; + ec->get_receive_mask = receive_mask; + ec->event_type = event_type; + ec->read_event_data = read_event_data; + ec->write_event_data = write_event_data; +} + +static TypeInfo sclp_console_info = { + .name = "sclpconsole", + .parent = TYPE_SCLP_EVENT, + .instance_size = sizeof(SCLPConsole), + .class_init = console_class_init, + .class_size = sizeof(SCLPEventClass), +}; + +static void register_types(void) +{ + type_register_static(&sclp_console_info); +} + +type_init(register_types) From d26a8caea3f160782841efb87b5e8bea606b512b Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Mon, 29 Oct 2012 18:22:36 +0200 Subject: [PATCH 1259/2270] memory: fix rendering of a region obscured by another The memory core drops regions that are hidden by another region (for example, during BAR sizing), but it doesn't do so correctly if the lower address of the existing range is below the lower address of the new range. Example (qemu-system-mips -M malta -kernel vmlinux-2.6.32-5-4kc-malta -append "console=ttyS0" -nographic -vga cirrus): Existing range: 10000000-107fffff New range: 100a0000-100bffff Correct behaviour: drop new range Incorrect behaviour: add new range Fix by taking this case into account (previously we only considered equal lower boundaries). Tested-by: Aurelien Jarno Signed-off-by: Avi Kivity Signed-off-by: Anthony Liguori --- memory.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/memory.c b/memory.c index 36bb9a59ae..243cb23969 100644 --- a/memory.c +++ b/memory.c @@ -539,12 +539,12 @@ static void render_memory_region(FlatView *view, offset_in_region += int128_get64(now); int128_subfrom(&remain, now); } - if (int128_eq(base, view->ranges[i].addr.start)) { - now = int128_min(remain, view->ranges[i].addr.size); - int128_addto(&base, now); - offset_in_region += int128_get64(now); - int128_subfrom(&remain, now); - } + now = int128_sub(int128_min(int128_add(base, remain), + addrrange_end(view->ranges[i].addr)), + base); + int128_addto(&base, now); + offset_in_region += int128_get64(now); + int128_subfrom(&remain, now); } if (int128_nz(remain)) { fr.mr = mr; From 3585317f6fdff0e3ae082f88afb2784d815a07e2 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 19 Oct 2012 23:48:13 +0200 Subject: [PATCH 1260/2270] tcg/mips: use MUL instead of MULT on MIPS32 and above MIPS32 and later instruction sets have a multiplication instruction directly operating on GPRs. It only produces a 32-bit result but it is exactly what is needed by QEMU. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- tcg/mips/tcg-target.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index 7e4013e1e6..ae2b274d85 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -323,6 +323,9 @@ enum { OPC_BLTZ = OPC_REGIMM | (0x00 << 16), OPC_BGEZ = OPC_REGIMM | (0x01 << 16), + OPC_SPECIAL2 = 0x1c << 26, + OPC_MUL = OPC_SPECIAL2 | 0x002, + OPC_SPECIAL3 = 0x1f << 26, OPC_INS = OPC_SPECIAL3 | 0x004, OPC_WSBH = OPC_SPECIAL3 | 0x0a0, @@ -1403,8 +1406,12 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT); break; case INDEX_op_mul_i32: +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 1) + tcg_out_opc_reg(s, OPC_MUL, args[0], args[1], args[2]); +#else tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]); tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0); +#endif break; case INDEX_op_mulu2_i32: tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]); From 0e8153dde7824e672127765914db30eb301f1aa4 Mon Sep 17 00:00:00 2001 From: Andre Beckus Date: Tue, 30 Oct 2012 07:45:07 +0000 Subject: [PATCH 1261/2270] hw/armv7m_nvic: Implement byte/halfword access for NVIC SCB_SHPRx registers Implement byte/halfword read and write for the NVIC SCB_SHPRx (System Handler Priority Registers). Do this by removing SHPR word access from nvic_readl/writel and adding common code to hande all access sizes in nvic_sysreg_read/write. Because the "nvic_state *s" variable now needs to be declared in nvic_sysreg_read/write, the "void *opaque" parameter of nvic_readl/writel is changed to "nvic_state *s". Signed-off-by: Andre Beckus Signed-off-by: Peter Maydell --- hw/armv7m_nvic.c | 58 +++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c index 35c1aa67e2..8d8d0a4e8b 100644 --- a/hw/armv7m_nvic.c +++ b/hw/armv7m_nvic.c @@ -138,9 +138,8 @@ void armv7m_nvic_complete_irq(void *opaque, int irq) gic_complete_irq(&s->gic, 0, irq); } -static uint32_t nvic_readl(void *opaque, uint32_t offset) +static uint32_t nvic_readl(nvic_state *s, uint32_t offset) { - nvic_state *s = (nvic_state *)opaque; uint32_t val; int irq; @@ -216,14 +215,6 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset) case 0xd14: /* Configuration Control. */ /* TODO: Implement Configuration Control bits. */ return 0; - case 0xd18: case 0xd1c: case 0xd20: /* System Handler Priority. */ - irq = offset - 0xd14; - val = 0; - val |= s->gic.priority1[irq++][0]; - val |= s->gic.priority1[irq++][0] << 8; - val |= s->gic.priority1[irq++][0] << 16; - val |= s->gic.priority1[irq][0] << 24; - return val; case 0xd24: /* System Handler Status. */ val = 0; if (s->gic.irq_state[ARMV7M_EXCP_MEM].active) val |= (1 << 0); @@ -285,9 +276,8 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset) } } -static void nvic_writel(void *opaque, uint32_t offset, uint32_t value) +static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value) { - nvic_state *s = (nvic_state *)opaque; uint32_t oldval; switch (offset) { case 0x10: /* SysTick Control and Status. */ @@ -356,17 +346,6 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value) case 0xd14: /* Configuration Control. */ /* TODO: Implement control registers. */ goto bad_reg; - case 0xd18: case 0xd1c: case 0xd20: /* System Handler Priority. */ - { - int irq; - irq = offset - 0xd14; - s->gic.priority1[irq++][0] = value & 0xff; - s->gic.priority1[irq++][0] = (value >> 8) & 0xff; - s->gic.priority1[irq++][0] = (value >> 16) & 0xff; - s->gic.priority1[irq][0] = (value >> 24) & 0xff; - gic_update(&s->gic); - } - break; case 0xd24: /* System Handler Control. */ /* TODO: Real hardware allows you to set/clear the active bits under some circumstances. We don't implement this. */ @@ -395,19 +374,26 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value) static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr, unsigned size) { - /* At the moment we only support the ID registers for byte/word access. - * This is not strictly correct as a few of the other registers also - * allow byte access. - */ + nvic_state *s = (nvic_state *)opaque; uint32_t offset = addr; - if (offset >= 0xfe0) { + int i; + uint32_t val; + + switch (offset) { + case 0xd18 ... 0xd23: /* System Handler Priority. */ + val = 0; + for (i = 0; i < size; i++) { + val |= s->gic.priority1[(offset - 0xd14) + i][0] << (i * 8); + } + return val; + case 0xfe0 ... 0xfff: /* ID. */ if (offset & 3) { return 0; } return nvic_id[(offset - 0xfe0) >> 2]; } if (size == 4) { - return nvic_readl(opaque, offset); + return nvic_readl(s, offset); } hw_error("NVIC: Bad read of size %d at offset 0x%x\n", size, offset); } @@ -415,9 +401,21 @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr, static void nvic_sysreg_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { + nvic_state *s = (nvic_state *)opaque; uint32_t offset = addr; + int i; + + switch (offset) { + case 0xd18 ... 0xd23: /* System Handler Priority. */ + for (i = 0; i < size; i++) { + s->gic.priority1[(offset - 0xd14) + i][0] = + (value >> (i * 8)) & 0xff; + } + gic_update(&s->gic); + return; + } if (size == 4) { - nvic_writel(opaque, offset, value); + nvic_writel(s, offset, value); return; } hw_error("NVIC: Bad write of size %d at offset 0x%x\n", size, offset); From f3cdbc329fa7621ece7e673f23c3101e6b0c952b Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:07 +0000 Subject: [PATCH 1262/2270] hw/vexpress.c: Don't prematurely explode QEMUMachineInitArgs Don't explode QEMUMachineInitArgs before passing it to the vexpress common init function. Signed-off-by: Peter Maydell --- hw/vexpress.c | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/hw/vexpress.c b/hw/vexpress.c index 3f7cb66a6b..d93f057bff 100644 --- a/hw/vexpress.c +++ b/hw/vexpress.c @@ -348,12 +348,7 @@ static const VEDBoardInfo a15_daughterboard = { }; static void vexpress_common_init(const VEDBoardInfo *daughterboard, - 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) + QEMUMachineInitArgs *args) { DeviceState *dev, *sysctl, *pl041; qemu_irq pic[64]; @@ -366,7 +361,8 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, MemoryRegion *sram = g_new(MemoryRegion, 1); const hwaddr *map = daughterboard->motherboard_map; - daughterboard->init(daughterboard, ram_size, cpu_model, pic, &proc_id); + daughterboard->init(daughterboard, args->ram_size, args->cpu_model, + pic, &proc_id); /* Motherboard peripherals: the wiring is the same but the * addresses vary between the legacy and A-Series memory maps. @@ -454,10 +450,10 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, /* VE_DAPROM: not modelled */ - vexpress_binfo.ram_size = ram_size; - vexpress_binfo.kernel_filename = kernel_filename; - vexpress_binfo.kernel_cmdline = kernel_cmdline; - vexpress_binfo.initrd_filename = initrd_filename; + vexpress_binfo.ram_size = args->ram_size; + vexpress_binfo.kernel_filename = args->kernel_filename; + vexpress_binfo.kernel_cmdline = args->kernel_cmdline; + vexpress_binfo.initrd_filename = args->initrd_filename; vexpress_binfo.nb_cpus = smp_cpus; vexpress_binfo.board_id = VEXPRESS_BOARD_ID; vexpress_binfo.loader_start = daughterboard->loader_start; @@ -469,28 +465,12 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, static void vexpress_a9_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; - vexpress_common_init(&a9_daughterboard, - ram_size, boot_device, kernel_filename, - kernel_cmdline, initrd_filename, cpu_model); + vexpress_common_init(&a9_daughterboard, args); } static void vexpress_a15_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; - vexpress_common_init(&a15_daughterboard, - ram_size, boot_device, kernel_filename, - kernel_cmdline, initrd_filename, cpu_model); + vexpress_common_init(&a15_daughterboard, args); } static QEMUMachine vexpress_a9_machine = { From db4ff6f111c42e2b33eddcf5f20cc53cceda60a2 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:07 +0000 Subject: [PATCH 1263/2270] hw/realview.c: Don't prematurely explode QEMUMachineInitArgs Don't explode QEMUMachineInitArgs in every realview init function; just pass it to the common realview_init() code instead. Signed-off-by: Peter Maydell --- hw/realview.c | 68 ++++++++++++++------------------------------------- 1 file changed, 19 insertions(+), 49 deletions(-) diff --git a/hw/realview.c b/hw/realview.c index b5cb08cb84..e789c159a9 100644 --- a/hw/realview.c +++ b/hw/realview.c @@ -44,11 +44,8 @@ static const int realview_board_id[] = { 0x76d }; -static void realview_init(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, - enum realview_board_type board_type) +static void realview_init(QEMUMachineInitArgs *args, + enum realview_board_type board_type) { ARMCPU *cpu = NULL; CPUARMState *env; @@ -73,6 +70,7 @@ static void realview_init(ram_addr_t ram_size, uint32_t proc_id = 0; uint32_t sys_id; ram_addr_t low_ram_size; + ram_addr_t ram_size = args->ram_size; switch (board_type) { case BOARD_EB: @@ -89,7 +87,7 @@ static void realview_init(ram_addr_t ram_size, break; } for (n = 0; n < smp_cpus; n++) { - cpu = cpu_arm_init(cpu_model); + cpu = cpu_arm_init(args->cpu_model); if (!cpu) { fprintf(stderr, "Unable to find CPU definition\n"); exit(1); @@ -321,9 +319,9 @@ static void realview_init(ram_addr_t ram_size, memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack); realview_binfo.ram_size = ram_size; - realview_binfo.kernel_filename = kernel_filename; - realview_binfo.kernel_cmdline = kernel_cmdline; - realview_binfo.initrd_filename = initrd_filename; + realview_binfo.kernel_filename = args->kernel_filename; + realview_binfo.kernel_cmdline = args->kernel_cmdline; + realview_binfo.initrd_filename = args->initrd_filename; realview_binfo.nb_cpus = smp_cpus; realview_binfo.board_id = realview_board_id[board_type]; realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0); @@ -332,62 +330,34 @@ static void realview_init(ram_addr_t ram_size, static void realview_eb_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; - if (!cpu_model) { - cpu_model = "arm926"; + if (!args->cpu_model) { + args->cpu_model = "arm926"; } - realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, - initrd_filename, cpu_model, BOARD_EB); + realview_init(args, BOARD_EB); } static void realview_eb_mpcore_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; - if (!cpu_model) { - cpu_model = "arm11mpcore"; + if (!args->cpu_model) { + args->cpu_model = "arm11mpcore"; } - realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, - initrd_filename, cpu_model, BOARD_EB_MPCORE); + realview_init(args, BOARD_EB_MPCORE); } static void realview_pb_a8_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; - if (!cpu_model) { - cpu_model = "cortex-a8"; + if (!args->cpu_model) { + args->cpu_model = "cortex-a8"; } - realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, - initrd_filename, cpu_model, BOARD_PB_A8); + realview_init(args, BOARD_PB_A8); } static void realview_pbx_a9_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; - if (!cpu_model) { - cpu_model = "cortex-a9"; + if (!args->cpu_model) { + args->cpu_model = "cortex-a9"; } - realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, - initrd_filename, cpu_model, BOARD_PBX_A9); + realview_init(args, BOARD_PBX_A9); } static QEMUMachine realview_eb_machine = { From 1b523b5bfc83b4d7e3c1971e0a8d34aff0a9ecf6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:07 +0000 Subject: [PATCH 1264/2270] hw/versatilepb: Don't prematurely explode QEMUMachineInitArgs Don't explode QEMUMachineInitArgs before passing it to the common versatile init function. Signed-off-by: Peter Maydell --- hw/versatilepb.c | 44 +++++++++++--------------------------------- 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/hw/versatilepb.c b/hw/versatilepb.c index e85f982897..25e652b1aa 100644 --- a/hw/versatilepb.c +++ b/hw/versatilepb.c @@ -167,11 +167,7 @@ static int vpb_sic_init(SysBusDevice *dev) static struct arm_boot_info versatile_binfo; -static void versatile_init(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, - int board_id) +static void versatile_init(QEMUMachineInitArgs *args, int board_id) { ARMCPU *cpu; MemoryRegion *sysmem = get_system_memory(); @@ -189,15 +185,15 @@ static void versatile_init(ram_addr_t ram_size, int done_smc = 0; DriveInfo *dinfo; - if (!cpu_model) { - cpu_model = "arm926"; + if (!args->cpu_model) { + args->cpu_model = "arm926"; } - cpu = cpu_arm_init(cpu_model); + cpu = cpu_arm_init(args->cpu_model); if (!cpu) { fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } - memory_region_init_ram(ram, "versatile.ram", ram_size); + memory_region_init_ram(ram, "versatile.ram", args->ram_size); vmstate_register_ram_global(ram); /* ??? RAM should repeat to fill physical memory space. */ /* SDRAM at address zero. */ @@ -340,40 +336,22 @@ static void versatile_init(ram_addr_t ram_size, fprintf(stderr, "qemu: Error registering flash memory.\n"); } - versatile_binfo.ram_size = ram_size; - versatile_binfo.kernel_filename = kernel_filename; - versatile_binfo.kernel_cmdline = kernel_cmdline; - versatile_binfo.initrd_filename = initrd_filename; + versatile_binfo.ram_size = args->ram_size; + versatile_binfo.kernel_filename = args->kernel_filename; + versatile_binfo.kernel_cmdline = args->kernel_cmdline; + versatile_binfo.initrd_filename = args->initrd_filename; versatile_binfo.board_id = board_id; arm_load_kernel(cpu, &versatile_binfo); } static void vpb_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; - versatile_init(ram_size, - boot_device, - kernel_filename, kernel_cmdline, - initrd_filename, cpu_model, 0x183); + versatile_init(args, 0x183); } static void vab_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; - versatile_init(ram_size, - boot_device, - kernel_filename, kernel_cmdline, - initrd_filename, cpu_model, 0x25e); + versatile_init(args, 0x25e); } static QEMUMachine versatilepb_machine = { From 72a9f5b7c33dfe8832951af1f1e67de10be1a0ce Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:07 +0000 Subject: [PATCH 1265/2270] hw/spitz: Don't prematurely explode QEMUMachineInitArgs Don't explode QEMUMachineInitArgs before calling common init function. Signed-off-by: Peter Maydell --- hw/spitz.c | 45 ++++++++++----------------------------------- 1 file changed, 10 insertions(+), 35 deletions(-) diff --git a/hw/spitz.c b/hw/spitz.c index 944c274a82..12e2815221 100644 --- a/hw/spitz.c +++ b/hw/spitz.c @@ -879,15 +879,14 @@ static struct arm_boot_info spitz_binfo = { .ram_size = 0x04000000, }; -static void spitz_common_init(ram_addr_t ram_size, - const char *kernel_filename, - const char *kernel_cmdline, const char *initrd_filename, - const char *cpu_model, enum spitz_model_e model, int arm_id) +static void spitz_common_init(QEMUMachineInitArgs *args, + enum spitz_model_e model, int arm_id) { PXA2xxState *mpu; DeviceState *scp0, *scp1 = NULL; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *rom = g_new(MemoryRegion, 1); + const char *cpu_model = args->cpu_model; if (!cpu_model) cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0"; @@ -928,9 +927,9 @@ static void spitz_common_init(ram_addr_t ram_size, /* A 4.0 GB microdrive is permanently sitting in CF slot 0. */ spitz_microdrive_attach(mpu, 0); - spitz_binfo.kernel_filename = kernel_filename; - spitz_binfo.kernel_cmdline = kernel_cmdline; - spitz_binfo.initrd_filename = initrd_filename; + spitz_binfo.kernel_filename = args->kernel_filename; + spitz_binfo.kernel_cmdline = args->kernel_cmdline; + spitz_binfo.initrd_filename = args->initrd_filename; spitz_binfo.board_id = arm_id; arm_load_kernel(mpu->cpu, &spitz_binfo); sl_bootparam_write(SL_PXA_PARAM_BASE); @@ -938,46 +937,22 @@ static void spitz_common_init(ram_addr_t ram_size, static void spitz_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; - spitz_common_init(ram_size, kernel_filename, - kernel_cmdline, initrd_filename, cpu_model, spitz, 0x2c9); + spitz_common_init(args, spitz, 0x2c9); } static void borzoi_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; - spitz_common_init(ram_size, kernel_filename, - kernel_cmdline, initrd_filename, cpu_model, borzoi, 0x33f); + spitz_common_init(args, borzoi, 0x33f); } static void akita_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; - spitz_common_init(ram_size, kernel_filename, - kernel_cmdline, initrd_filename, cpu_model, akita, 0x2e8); + spitz_common_init(args, akita, 0x2e8); } static void terrier_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; - spitz_common_init(ram_size, kernel_filename, - kernel_cmdline, initrd_filename, cpu_model, terrier, 0x33f); + spitz_common_init(args, terrier, 0x33f); } static QEMUMachine akitapda_machine = { From 6952625da87175ca9170335803633f91de7f2f2a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:08 +0000 Subject: [PATCH 1266/2270] hw/omap_sx1: Don't prematurely explode QEMUMachineInitArgs Don't explode QEMUMachineInitArgs before passing it to the omap_sx1 common init function. Signed-off-by: Peter Maydell --- hw/omap_sx1.c | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c index eb2bf0569c..21a5bbb006 100644 --- a/hw/omap_sx1.c +++ b/hw/omap_sx1.c @@ -97,11 +97,7 @@ static struct arm_boot_info sx1_binfo = { .board_id = 0x265, }; -static void sx1_init(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, - const int version) +static void sx1_init(QEMUMachineInitArgs *args, const int version) { struct omap_mpu_state_s *mpu; MemoryRegion *address_space = get_system_memory(); @@ -121,7 +117,7 @@ static void sx1_init(ram_addr_t ram_size, flash_size = flash2_size; } - mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, cpu_model); + mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, args->cpu_model); /* External Flash (EMIFS) */ memory_region_init_ram(flash, "omap_sx1.flash0-0", flash_size); @@ -192,16 +188,16 @@ static void sx1_init(ram_addr_t ram_size, OMAP_CS1_BASE, &cs[1]); } - if (!kernel_filename && !fl_idx) { + if (!args->kernel_filename && !fl_idx) { fprintf(stderr, "Kernel or Flash image must be specified\n"); exit(1); } /* Load the kernel. */ - if (kernel_filename) { - sx1_binfo.kernel_filename = kernel_filename; - sx1_binfo.kernel_cmdline = kernel_cmdline; - sx1_binfo.initrd_filename = initrd_filename; + if (args->kernel_filename) { + sx1_binfo.kernel_filename = args->kernel_filename; + sx1_binfo.kernel_cmdline = args->kernel_cmdline; + sx1_binfo.initrd_filename = args->initrd_filename; arm_load_kernel(mpu->cpu, &sx1_binfo); } @@ -211,26 +207,12 @@ static void sx1_init(ram_addr_t ram_size, static void sx1_init_v1(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; - sx1_init(ram_size, boot_device, kernel_filename, - kernel_cmdline, initrd_filename, cpu_model, 1); + sx1_init(args, 1); } static void sx1_init_v2(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; - sx1_init(ram_size, boot_device, kernel_filename, - kernel_cmdline, initrd_filename, cpu_model, 2); + sx1_init(args, 2); } static QEMUMachine sx1_machine_v2 = { From 462b69bba32e35c546b6b588f299f1f794409d22 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:08 +0000 Subject: [PATCH 1267/2270] hw/nseries: Don't prematurely explode QEMUMachineInitArgs Don't explode QEMUMachineInitArgs before passing it to n8x0_init(). Signed-off-by: Peter Maydell --- hw/nseries.c | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/hw/nseries.c b/hw/nseries.c index 9306aa15a7..652d9da333 100644 --- a/hw/nseries.c +++ b/hw/nseries.c @@ -1284,17 +1284,15 @@ static int n810_atag_setup(const struct arm_boot_info *info, void *p) return n8x0_atag_setup(p, 810); } -static void n8x0_init(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, struct arm_boot_info *binfo, int model) +static void n8x0_init(QEMUMachineInitArgs *args, + struct arm_boot_info *binfo, int model) { MemoryRegion *sysmem = get_system_memory(); struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s)); int sdram_size = binfo->ram_size; DisplayState *ds; - s->mpu = omap2420_mpu_init(sysmem, sdram_size, cpu_model); + s->mpu = omap2420_mpu_init(sysmem, sdram_size, args->cpu_model); /* Setup peripherals * @@ -1338,17 +1336,18 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device, n8x0_usb_setup(s); } - if (kernel_filename) { + if (args->kernel_filename) { /* Or at the linux loader. */ - binfo->kernel_filename = kernel_filename; - binfo->kernel_cmdline = kernel_cmdline; - binfo->initrd_filename = initrd_filename; + binfo->kernel_filename = args->kernel_filename; + binfo->kernel_cmdline = args->kernel_cmdline; + binfo->initrd_filename = args->initrd_filename; arm_load_kernel(s->mpu->cpu, binfo); qemu_register_reset(n8x0_boot_init, s); } - if (option_rom[0].name && (boot_device[0] == 'n' || !kernel_filename)) { + if (option_rom[0].name && + (args->boot_device[0] == 'n' || !args->kernel_filename)) { int rom_size; uint8_t nolo_tags[0x10000]; /* No, wait, better start at the ROM. */ @@ -1400,28 +1399,12 @@ static struct arm_boot_info n810_binfo = { static void n800_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; - return n8x0_init(ram_size, boot_device, - kernel_filename, kernel_cmdline, initrd_filename, - cpu_model, &n800_binfo, 800); + return n8x0_init(args, &n800_binfo, 800); } static void n810_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; - return n8x0_init(ram_size, boot_device, - kernel_filename, kernel_cmdline, initrd_filename, - cpu_model, &n810_binfo, 810); + return n8x0_init(args, &n810_binfo, 810); } static QEMUMachine n800_machine = { From 6efa6d50387f5f1401c6f1612fb80cba31f7dca4 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:08 +0000 Subject: [PATCH 1268/2270] hw/mainstone: Don't prematurely explode QEMUMachineInitArgs Don't explode QEMUMachineInitArgs before passing it to mainstone_init(). Signed-off-by: Peter Maydell --- hw/mainstone.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/hw/mainstone.c b/hw/mainstone.c index 3266946954..5bbecb7304 100644 --- a/hw/mainstone.c +++ b/hw/mainstone.c @@ -95,10 +95,8 @@ static struct arm_boot_info mainstone_binfo = { }; static void mainstone_common_init(MemoryRegion *address_space_mem, - ram_addr_t ram_size, - const char *kernel_filename, - const char *kernel_cmdline, const char *initrd_filename, - const char *cpu_model, enum mainstone_model_e model, int arm_id) + QEMUMachineInitArgs *args, + enum mainstone_model_e model, int arm_id) { uint32_t sector_len = 256 * 1024; hwaddr mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 }; @@ -108,6 +106,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem, int i; int be; MemoryRegion *rom = g_new(MemoryRegion, 1); + const char *cpu_model = args->cpu_model; if (!cpu_model) cpu_model = "pxa270-c5"; @@ -164,22 +163,16 @@ static void mainstone_common_init(MemoryRegion *address_space_mem, smc91c111_init(&nd_table[0], MST_ETH_PHYS, qdev_get_gpio_in(mst_irq, ETHERNET_IRQ)); - mainstone_binfo.kernel_filename = kernel_filename; - mainstone_binfo.kernel_cmdline = kernel_cmdline; - mainstone_binfo.initrd_filename = initrd_filename; + mainstone_binfo.kernel_filename = args->kernel_filename; + mainstone_binfo.kernel_cmdline = args->kernel_cmdline; + mainstone_binfo.initrd_filename = args->initrd_filename; mainstone_binfo.board_id = arm_id; arm_load_kernel(mpu->cpu, &mainstone_binfo); } static void mainstone_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; - mainstone_common_init(get_system_memory(), ram_size, kernel_filename, - kernel_cmdline, initrd_filename, cpu_model, mainstone, 0x196); + mainstone_common_init(get_system_memory(), args, mainstone, 0x196); } static QEMUMachine mainstone2_machine = { From 7f0f774003e4c6885b34d4c0006f7beff2b529eb Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:08 +0000 Subject: [PATCH 1269/2270] hw/exynos4_boards: Don't prematurely explode QEMUMachineInitArgs Don't explode QEMUMachineInitArgs before passing it to exynos4_boards_init_common(). Signed-off-by: Peter Maydell --- hw/exynos4_boards.c | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/hw/exynos4_boards.c b/hw/exynos4_boards.c index 4951064c3f..bc815bbae3 100644 --- a/hw/exynos4_boards.c +++ b/hw/exynos4_boards.c @@ -93,11 +93,8 @@ static void lan9215_init(uint32_t base, qemu_irq irq) } } -static Exynos4210State *exynos4_boards_init_common( - const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename, - Exynos4BoardType board_type) +static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args, + Exynos4BoardType board_type) { if (smp_cpus != EXYNOS4210_NCPUS) { fprintf(stderr, "%s board supports only %d CPU cores. Ignoring smp_cpus" @@ -110,9 +107,9 @@ static Exynos4210State *exynos4_boards_init_common( exynos4_board_binfo.board_id = exynos4_board_id[board_type]; exynos4_board_binfo.smp_bootreg_addr = exynos4_board_smp_bootreg_addr[board_type]; - exynos4_board_binfo.kernel_filename = kernel_filename; - exynos4_board_binfo.initrd_filename = initrd_filename; - exynos4_board_binfo.kernel_cmdline = kernel_cmdline; + exynos4_board_binfo.kernel_filename = args->kernel_filename; + exynos4_board_binfo.initrd_filename = args->initrd_filename; + exynos4_board_binfo.kernel_cmdline = args->kernel_cmdline; exynos4_board_binfo.gic_cpu_if_addr = EXYNOS4210_SMP_PRIVATE_BASE_ADDR + 0x100; @@ -122,9 +119,9 @@ static Exynos4210State *exynos4_boards_init_common( " initrd_filename: %s\n", exynos4_board_ram_size[board_type] / 1048576, exynos4_board_ram_size[board_type], - kernel_filename, - kernel_cmdline, - initrd_filename); + args->kernel_filename, + args->kernel_cmdline, + args->initrd_filename); return exynos4210_init(get_system_memory(), exynos4_board_ram_size[board_type]); @@ -132,22 +129,15 @@ static Exynos4210State *exynos4_boards_init_common( static void nuri_init(QEMUMachineInitArgs *args) { - const char *kernel_filename = args->kernel_filename; - const char *kernel_cmdline = args->kernel_cmdline; - const char *initrd_filename = args->initrd_filename; - exynos4_boards_init_common(kernel_filename, kernel_cmdline, - initrd_filename, EXYNOS4_BOARD_NURI); + exynos4_boards_init_common(args, EXYNOS4_BOARD_NURI); arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo); } static void smdkc210_init(QEMUMachineInitArgs *args) { - const char *kernel_filename = args->kernel_filename; - const char *kernel_cmdline = args->kernel_cmdline; - const char *initrd_filename = args->initrd_filename; - Exynos4210State *s = exynos4_boards_init_common(kernel_filename, - kernel_cmdline, initrd_filename, EXYNOS4_BOARD_SMDKC210); + Exynos4210State *s = exynos4_boards_init_common(args, + EXYNOS4_BOARD_SMDKC210); lan9215_init(SMDK_LAN9118_BASE_ADDR, qemu_irq_invert(s->irq_table[exynos4210_get_irq(37, 1)])); From fbfecf43e9d354cfae04496563f7bb87d2ccde46 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:08 +0000 Subject: [PATCH 1270/2270] hw/pl050: Use LOG_GUEST_ERROR Use LOG_GUEST_ERROR for reporting guest attempts to access invalid register offsets. Signed-off-by: Peter Maydell --- hw/pl050.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/pl050.c b/hw/pl050.c index 470572eabb..47032f1260 100644 --- a/hw/pl050.c +++ b/hw/pl050.c @@ -95,7 +95,8 @@ static uint64_t pl050_read(void *opaque, hwaddr offset, case 4: /* KMIIR */ return s->pending | 2; default: - hw_error("pl050_read: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl050_read: Bad offset %x\n", (int)offset); return 0; } } @@ -123,7 +124,8 @@ static void pl050_write(void *opaque, hwaddr offset, s->clk = value; return; default: - hw_error("pl050_write: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl050_write: Bad offset %x\n", (int)offset); } } static const MemoryRegionOps pl050_ops = { From abff909c9456103b54277318675fff8997fd71af Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:09 +0000 Subject: [PATCH 1271/2270] hw/pl061: Use LOG_GUEST_ERROR Use LOG_GUEST_ERROR to report guest attempts to access bad register offsets. Signed-off-by: Peter Maydell --- hw/pl061.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/pl061.c b/hw/pl061.c index 7d182e7cdf..f1ed5ced1d 100644 --- a/hw/pl061.c +++ b/hw/pl061.c @@ -164,7 +164,8 @@ static uint64_t pl061_read(void *opaque, hwaddr offset, case 0x528: /* Analog mode select */ return s->amsel; default: - hw_error("pl061_read: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl061_read: Bad offset %x\n", (int)offset); return 0; } } @@ -239,7 +240,8 @@ static void pl061_write(void *opaque, hwaddr offset, s->amsel = value & 0xff; break; default: - hw_error("pl061_write: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl061_write: Bad offset %x\n", (int)offset); } pl061_update(s); } From df37416218a91a4ae962dfafbc8208af8087ebc0 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:09 +0000 Subject: [PATCH 1272/2270] hw/pl080: Use LOG_GUEST_ERROR and LOG_UNIMP Use LOG_GUEST_ERROR and LOG_UNIMP in preference to hw_error(). Signed-off-by: Peter Maydell --- hw/pl080.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/hw/pl080.c b/hw/pl080.c index 6abe52857e..26150af757 100644 --- a/hw/pl080.c +++ b/hw/pl080.c @@ -281,7 +281,8 @@ static uint64_t pl080_read(void *opaque, hwaddr offset, return s->sync; default: bad_offset: - hw_error("pl080_read: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl080_read: Bad offset %x\n", (int)offset); return 0; } } @@ -327,12 +328,13 @@ static void pl080_write(void *opaque, hwaddr offset, case 10: /* SoftLBReq */ case 11: /* SoftLSReq */ /* ??? Implement these. */ - hw_error("pl080_write: Soft DMA not implemented\n"); + qemu_log_mask(LOG_UNIMP, "pl080_write: Soft DMA not implemented\n"); break; case 12: /* Configuration */ s->conf = value; if (s->conf & (PL080_CONF_M1 | PL080_CONF_M1)) { - hw_error("pl080_write: Big-endian DMA not implemented\n"); + qemu_log_mask(LOG_UNIMP, + "pl080_write: Big-endian DMA not implemented\n"); } pl080_run(s); break; @@ -341,7 +343,8 @@ static void pl080_write(void *opaque, hwaddr offset, break; default: bad_offset: - hw_error("pl080_write: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl080_write: Bad offset %x\n", (int)offset); } pl080_update(s); } From 375cb560295484b88898262ebf400eff9a011206 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:09 +0000 Subject: [PATCH 1273/2270] hw/pl110: Use LOG_GUEST_ERROR rather than hw_error() Use LOG_GUEST_ERROR to report guest accesses to invalid register offsets. Signed-off-by: Peter Maydell --- hw/pl110.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/pl110.c b/hw/pl110.c index 82486b0c14..d5472f4cce 100644 --- a/hw/pl110.c +++ b/hw/pl110.c @@ -349,7 +349,8 @@ static uint64_t pl110_read(void *opaque, hwaddr offset, case 12: /* LCDLPCURR */ return s->lpbase; default: - hw_error("pl110_read: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl110_read: Bad offset %x\n", (int)offset); return 0; } } @@ -417,7 +418,8 @@ static void pl110_write(void *opaque, hwaddr offset, pl110_update(s); break; default: - hw_error("pl110_write: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pl110_write: Bad offset %x\n", (int)offset); } } From 2d746989bf5e146df9205de3fd4ad0d48a318165 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:09 +0000 Subject: [PATCH 1274/2270] hw/pl190: Use LOG_UNIMP rather than hw_error() Use LOG_UNIMP to report attempts to use the unimplemented test mode. Signed-off-by: Peter Maydell --- hw/pl190.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/pl190.c b/hw/pl190.c index 213229b566..40199302a9 100644 --- a/hw/pl190.c +++ b/hw/pl190.c @@ -199,7 +199,7 @@ static void pl190_write(void *opaque, hwaddr offset, break; case 0xc0: /* ITCR */ if (val) { - hw_error("pl190: Test mode not implemented\n"); + qemu_log_mask(LOG_UNIMP, "pl190: Test mode not implemented\n"); } break; default: From f9fe7bdad82a1262e9352393b03d7f4586366209 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:09 +0000 Subject: [PATCH 1275/2270] hw/arm11mpcore: Use LOG_GUEST_ERROR rather than hw_error() Use LOG_GUEST_ERROR to report guest accesses to bad offsets. Signed-off-by: Peter Maydell --- hw/arm11mpcore.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c index 105f158fd4..640ed20a61 100644 --- a/hw/arm11mpcore.c +++ b/hw/arm11mpcore.c @@ -44,7 +44,9 @@ static uint64_t mpcore_scu_read(void *opaque, hwaddr offset, case 0x0c: /* Invalidate all. */ return 0; default: - hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "mpcore_priv_read: Bad offset %x\n", (int)offset); + return 0; } } @@ -61,7 +63,8 @@ static void mpcore_scu_write(void *opaque, hwaddr offset, /* This is a no-op as cache is not emulated. */ break; default: - hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "mpcore_priv_read: Bad offset %x\n", (int)offset); } } From 8c8dc39fa60f782f988bc08113f3abfddebbfebd Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:10 +0000 Subject: [PATCH 1276/2270] hw/arm_gic: Use LOG_GUEST_ERROR Use LOG_GUEST_ERROR to report guest accesses to bad offsets. Signed-off-by: Peter Maydell --- hw/arm_gic.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/arm_gic.c b/hw/arm_gic.c index ce16e8367f..f9e423f152 100644 --- a/hw/arm_gic.c +++ b/hw/arm_gic.c @@ -324,7 +324,8 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset) } return res; bad_reg: - hw_error("gic_dist_readb: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "gic_dist_readb: Bad offset %x\n", (int)offset); return 0; } @@ -487,7 +488,8 @@ static void gic_dist_writeb(void *opaque, hwaddr offset, gic_update(s); return; bad_reg: - hw_error("gic_dist_writeb: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "gic_dist_writeb: Bad offset %x\n", (int)offset); } static void gic_dist_writew(void *opaque, hwaddr offset, @@ -556,7 +558,8 @@ static uint32_t gic_cpu_read(GICState *s, int cpu, int offset) case 0x18: /* Highest Pending Interrupt */ return s->current_pending[cpu]; default: - hw_error("gic_cpu_read: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "gic_cpu_read: Bad offset %x\n", (int)offset); return 0; } } @@ -577,7 +580,8 @@ static void gic_cpu_write(GICState *s, int cpu, int offset, uint32_t value) case 0x10: /* End Of Interrupt */ return gic_complete_irq(s, cpu, value & 0x3ff); default: - hw_error("gic_cpu_write: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "gic_cpu_write: Bad offset %x\n", (int)offset); return; } gic_update(s); From edb94a41e30f1b2ca241bfdfd7f7e90badfa6192 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:10 +0000 Subject: [PATCH 1277/2270] hw/arm_timer: Use LOG_GUEST_ERROR and LOG_UNIMP Use LOG_GUEST_ERROR to report guest accesses to bad register offsets, and LOG_UNIMP for access to the unimplemented test registers. Signed-off-by: Peter Maydell --- hw/arm_timer.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/hw/arm_timer.c b/hw/arm_timer.c index 2e136216c6..af339d3d19 100644 --- a/hw/arm_timer.c +++ b/hw/arm_timer.c @@ -64,7 +64,8 @@ static uint32_t arm_timer_read(void *opaque, hwaddr offset) return 0; return s->int_level; default: - hw_error("%s: Bad offset %x\n", __func__, (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset %x\n", __func__, (int)offset); return 0; } } @@ -131,7 +132,8 @@ static void arm_timer_write(void *opaque, hwaddr offset, arm_timer_recalibrate(s, 0); break; default: - hw_error("%s: Bad offset %x\n", __func__, (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset %x\n", __func__, (int)offset); } arm_timer_update(s); } @@ -223,10 +225,14 @@ static uint64_t sp804_read(void *opaque, hwaddr offset, /* Integration Test control registers, which we won't support */ case 0xf00: /* TimerITCR */ case 0xf04: /* TimerITOP (strictly write only but..) */ + qemu_log_mask(LOG_UNIMP, + "%s: integration test registers unimplemented\n", + __func__); return 0; } - hw_error("%s: Bad offset %x\n", __func__, (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset %x\n", __func__, (int)offset); return 0; } @@ -246,7 +252,8 @@ static void sp804_write(void *opaque, hwaddr offset, } /* Technically we could be writing to the Test Registers, but not likely */ - hw_error("%s: Bad offset %x\n", __func__, (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %x\n", + __func__, (int)offset); } static const MemoryRegionOps sp804_ops = { @@ -300,7 +307,7 @@ static uint64_t icp_pit_read(void *opaque, hwaddr offset, /* ??? Don't know the PrimeCell ID for this device. */ n = offset >> 8; if (n > 2) { - hw_error("%s: Bad timer %d\n", __func__, n); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n); } return arm_timer_read(s->timer[n], offset & 0xff); @@ -314,7 +321,7 @@ static void icp_pit_write(void *opaque, hwaddr offset, n = offset >> 8; if (n > 2) { - hw_error("%s: Bad timer %d\n", __func__, n); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n); } arm_timer_write(s->timer[n], offset & 0xff, value); From e72e3ffc3d13176c44eb21af0c6468867458cb4a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:10 +0000 Subject: [PATCH 1278/2270] hw/armv7m_nvic: Use LOG_GUEST_ERROR and LOG_UNIMP Use LOG_GUEST_ERROR and LOG_UNIMP rather than hw_error() where appropriate. Signed-off-by: Peter Maydell --- hw/armv7m_nvic.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c index 8d8d0a4e8b..f0a2e7b5d2 100644 --- a/hw/armv7m_nvic.c +++ b/hw/armv7m_nvic.c @@ -234,7 +234,7 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset) return val; case 0xd28: /* Configurable Fault Status. */ /* TODO: Implement Fault Status. */ - hw_error("Not implemented: Configurable Fault Status."); + qemu_log_mask(LOG_UNIMP, "Configurable Fault Status unimplemented\n"); return 0; case 0xd2c: /* Hard Fault Status. */ case 0xd30: /* Debug Fault Status. */ @@ -242,7 +242,8 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset) case 0xd38: /* Bus Fault Address. */ case 0xd3c: /* Aux Fault Status. */ /* TODO: Implement fault status registers. */ - goto bad_reg; + qemu_log_mask(LOG_UNIMP, "Fault status registers unimplemented\n"); + return 0; case 0xd40: /* PFR0. */ return 0x00000030; case 0xd44: /* PRF1. */ @@ -271,8 +272,8 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset) return 0x01310102; /* TODO: Implement debug registers. */ default: - bad_reg: - hw_error("NVIC: Bad read offset 0x%x\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset); + return 0; } } @@ -335,17 +336,18 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value) case 0xd0c: /* Application Interrupt/Reset Control. */ if ((value >> 16) == 0x05fa) { if (value & 2) { - hw_error("VECTCLRACTIVE not implemented"); + qemu_log_mask(LOG_UNIMP, "VECTCLRACTIVE unimplemented\n"); } if (value & 5) { - hw_error("System reset"); + qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n"); } } break; case 0xd10: /* System Control. */ case 0xd14: /* Configuration Control. */ /* TODO: Implement control registers. */ - goto bad_reg; + qemu_log_mask(LOG_UNIMP, "NVIC: SCR and CCR unimplemented\n"); + break; case 0xd24: /* System Handler Control. */ /* TODO: Real hardware allows you to set/clear the active bits under some circumstances. We don't implement this. */ @@ -359,15 +361,17 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value) case 0xd34: /* Mem Manage Address. */ case 0xd38: /* Bus Fault Address. */ case 0xd3c: /* Aux Fault Status. */ - goto bad_reg; + qemu_log_mask(LOG_UNIMP, + "NVIC: fault status registers unimplemented\n"); + break; case 0xf00: /* Software Triggered Interrupt Register */ if ((value & 0x1ff) < s->num_irq) { gic_set_pending_private(&s->gic, 0, value & 0x1ff); } break; default: - bad_reg: - hw_error("NVIC: Bad write offset 0x%x\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, + "NVIC: Bad write offset 0x%x\n", offset); } } @@ -395,7 +399,9 @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr, if (size == 4) { return nvic_readl(s, offset); } - hw_error("NVIC: Bad read of size %d at offset 0x%x\n", size, offset); + qemu_log_mask(LOG_GUEST_ERROR, + "NVIC: Bad read of size %d at offset 0x%x\n", size, offset); + return 0; } static void nvic_sysreg_write(void *opaque, hwaddr addr, @@ -418,7 +424,8 @@ static void nvic_sysreg_write(void *opaque, hwaddr addr, nvic_writel(s, offset, value); return; } - hw_error("NVIC: Bad write of size %d at offset 0x%x\n", size, offset); + qemu_log_mask(LOG_GUEST_ERROR, + "NVIC: Bad write of size %d at offset 0x%x\n", size, offset); } static const MemoryRegionOps nvic_sysreg_ops = { From 0c896f066213fcb06063f68ad7bfc75800591846 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:10 +0000 Subject: [PATCH 1279/2270] hw/arm_sysctl: Use LOG_GUEST_ERROR Use LOG_GUEST_ERROR to report bad guest accesses. Signed-off-by: Peter Maydell --- hw/arm_sysctl.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c index 26318e14d5..58eb98216d 100644 --- a/hw/arm_sysctl.c +++ b/hw/arm_sysctl.c @@ -184,7 +184,9 @@ static uint64_t arm_sysctl_read(void *opaque, hwaddr offset, return s->sys_cfgstat; default: bad_reg: - printf ("arm_sysctl_read: Bad register offset 0x%x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "arm_sysctl_read: Bad register offset 0x%x\n", + (int)offset); return 0; } } @@ -339,7 +341,9 @@ static void arm_sysctl_write(void *opaque, hwaddr offset, return; default: bad_reg: - printf ("arm_sysctl_write: Bad register offset 0x%x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "arm_sysctl_write: Bad register offset 0x%x\n", + (int)offset); return; } } From a35d4e422328eeb770b7b0c08bb073e8940b158e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:10 +0000 Subject: [PATCH 1280/2270] hw/arm_l2x0: Use LOG_GUEST_ERROR Use LOG_GUEST_ERROR to report bad guest accesses. Signed-off-by: Peter Maydell --- hw/arm_l2x0.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/arm_l2x0.c b/hw/arm_l2x0.c index 8f5921c3a6..6abf0ee160 100644 --- a/hw/arm_l2x0.c +++ b/hw/arm_l2x0.c @@ -87,7 +87,8 @@ static uint64_t l2x0_priv_read(void *opaque, hwaddr offset, case 0xF80: return 0; default: - fprintf(stderr, "l2x0_priv_read: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "l2x0_priv_read: Bad offset %x\n", (int)offset); break; } return 0; @@ -128,7 +129,8 @@ static void l2x0_priv_write(void *opaque, hwaddr offset, case 0xF80: return; default: - fprintf(stderr, "l2x0_priv_write: Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "l2x0_priv_write: Bad offset %x\n", (int)offset); break; } } From 5170d661dc1a2a28e1a242f6814bea4dcc29ad23 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:11 +0000 Subject: [PATCH 1281/2270] hw/versatile_i2c: Use LOG_GUEST_ERROR Use LOG_GUEST_ERROR to report bad guest accesses. Signed-off-by: Peter Maydell --- hw/versatile_i2c.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/versatile_i2c.c b/hw/versatile_i2c.c index 44e7e40f2f..ad71e9d92d 100644 --- a/hw/versatile_i2c.c +++ b/hw/versatile_i2c.c @@ -40,7 +40,8 @@ static uint64_t versatile_i2c_read(void *opaque, hwaddr offset, if (offset == 0) { return (s->out & 1) | (s->in << 1); } else { - hw_error("%s: Bad offset 0x%x\n", __func__, (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%x\n", __func__, (int)offset); return -1; } } @@ -58,7 +59,8 @@ static void versatile_i2c_write(void *opaque, hwaddr offset, s->out &= ~value; break; default: - hw_error("%s: Bad offset 0x%x\n", __func__, (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%x\n", __func__, (int)offset); } bitbang_i2c_set(s->bitbang, BITBANG_I2C_SCL, (s->out & 1) != 0); s->in = bitbang_i2c_set(s->bitbang, BITBANG_I2C_SDA, (s->out & 2) != 0); From b7dff23a487fffccd7c395da95e9b02bebe48bee Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 30 Oct 2012 07:45:11 +0000 Subject: [PATCH 1282/2270] pflash_cfi0x: remove unused base field This field is completely unused. The base address should also be abstracted away from the device anyway. Removed. Signed-off-by: Peter Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/pflash_cfi01.c | 2 -- hw/pflash_cfi02.c | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index 5e3a409c2b..2e29f8a38a 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -61,7 +61,6 @@ do { \ struct pflash_t { BlockDriverState *bs; - hwaddr base; hwaddr sector_len; hwaddr total_len; int width; @@ -594,7 +593,6 @@ pflash_t *pflash_cfi01_register(hwaddr base, } pfl->timer = qemu_new_timer_ns(vm_clock, pflash_timer, pfl); - pfl->base = base; pfl->sector_len = sector_len; pfl->total_len = total_len; pfl->width = width; diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c index 9f94c0623d..083718bad3 100644 --- a/hw/pflash_cfi02.c +++ b/hw/pflash_cfi02.c @@ -56,7 +56,6 @@ do { \ struct pflash_t { BlockDriverState *bs; - hwaddr base; uint32_t sector_len; uint32_t chip_len; int mappings; @@ -602,7 +601,6 @@ pflash_t *pflash_cfi02_register(hwaddr base, name, size); vmstate_register_ram(&pfl->orig_mem, qdev); pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem); - pfl->base = base; pfl->chip_len = chip_len; pfl->mappings = nb_mappings; pfl->bs = bs; @@ -618,7 +616,7 @@ pflash_t *pflash_cfi02_register(hwaddr base, pflash_setup_mappings(pfl); pfl->rom_mode = 1; - memory_region_add_subregion(get_system_memory(), pfl->base, &pfl->mem); + memory_region_add_subregion(get_system_memory(), base, &pfl->mem); if (pfl->bs) { pfl->ro = bdrv_is_read_only(pfl->bs); From be65f89992afd1366ce51db95f26b63cc90e309d Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 30 Oct 2012 07:45:11 +0000 Subject: [PATCH 1283/2270] pflash_cfi01: remove unused total_len field This field is completely unused. Signed-off-by: Peter Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/pflash_cfi01.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index 2e29f8a38a..b532054c53 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -62,7 +62,6 @@ do { \ struct pflash_t { BlockDriverState *bs; hwaddr sector_len; - hwaddr total_len; int width; int wcycle; /* if 0, the flash is read normally */ int bypass; @@ -594,7 +593,6 @@ pflash_t *pflash_cfi01_register(hwaddr base, pfl->timer = qemu_new_timer_ns(vm_clock, pflash_timer, pfl); pfl->sector_len = sector_len; - pfl->total_len = total_len; pfl->width = width; pfl->wcycle = 0; pfl->cmd = 0; From 368a354f02b7c3845d8b4bcdebc0840a515e953b Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 30 Oct 2012 07:45:11 +0000 Subject: [PATCH 1284/2270] pflash_cfi0x: QOMified QOMified the pflash_cfi0x so machine models can connect them up in custom ways. Kept the pflash_cfi0x_register functions as is. They can still be used to create a flash straight onto system memory. Signed-off-by: Peter Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/pflash_cfi01.c | 141 ++++++++++++++++++++++++++++------------ hw/pflash_cfi02.c | 160 +++++++++++++++++++++++++++++++++------------- 2 files changed, 214 insertions(+), 87 deletions(-) diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index b532054c53..d30d43c318 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -42,6 +42,7 @@ #include "qemu-timer.h" #include "exec-memory.h" #include "host-utils.h" +#include "sysbus.h" #define PFLASH_BUG(fmt, ...) \ do { \ @@ -60,21 +61,28 @@ do { \ #endif struct pflash_t { + SysBusDevice busdev; BlockDriverState *bs; - hwaddr sector_len; - int width; + uint32_t nb_blocs; + uint64_t sector_len; + uint8_t width; + uint8_t be; int wcycle; /* if 0, the flash is read normally */ int bypass; int ro; uint8_t cmd; uint8_t status; - uint16_t ident[4]; + uint16_t ident0; + uint16_t ident1; + uint16_t ident2; + uint16_t ident3; uint8_t cfi_len; uint8_t cfi_table[0x52]; hwaddr counter; unsigned int writeblock_size; QEMUTimer *timer; MemoryRegion mem; + char *name; void *storage; }; @@ -166,11 +174,11 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset, case 0x90: switch (boff) { case 0: - ret = pfl->ident[0] << 8 | pfl->ident[1]; + ret = pfl->ident0 << 8 | pfl->ident1; DPRINTF("%s: Manufacturer Code %04x\n", __func__, ret); break; case 1: - ret = pfl->ident[2] << 8 | pfl->ident[3]; + ret = pfl->ident2 << 8 | pfl->ident3; DPRINTF("%s: Device ID Code %04x\n", __func__, ret); break; default: @@ -277,9 +285,8 @@ static void pflash_write(pflash_t *pfl, hwaddr offset, p = pfl->storage; offset &= ~(pfl->sector_len - 1); - DPRINTF("%s: block erase at " TARGET_FMT_plx " bytes " - TARGET_FMT_plx "\n", - __func__, offset, pfl->sector_len); + DPRINTF("%s: block erase at " TARGET_FMT_plx " bytes %x\n", + __func__, offset, (unsigned)pfl->sector_len); if (!pfl->ro) { memset(p + offset, 0xff, pfl->sector_len); @@ -541,19 +548,13 @@ static const MemoryRegionOps pflash_cfi01_ops_le = { .endianness = DEVICE_NATIVE_ENDIAN, }; -pflash_t *pflash_cfi01_register(hwaddr base, - DeviceState *qdev, const char *name, - hwaddr size, - BlockDriverState *bs, uint32_t sector_len, - int nb_blocs, int width, - uint16_t id0, uint16_t id1, - uint16_t id2, uint16_t id3, int be) +static int pflash_cfi01_init(SysBusDevice *dev) { - pflash_t *pfl; - hwaddr total_len; + pflash_t *pfl = FROM_SYSBUS(typeof(*pfl), dev); + uint64_t total_len; int ret; - total_len = sector_len * nb_blocs; + total_len = pfl->sector_len * pfl->nb_blocs; /* XXX: to be fixed */ #if 0 @@ -562,27 +563,22 @@ pflash_t *pflash_cfi01_register(hwaddr base, return NULL; #endif - pfl = g_malloc0(sizeof(pflash_t)); - memory_region_init_rom_device( - &pfl->mem, be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl, - name, size); - vmstate_register_ram(&pfl->mem, qdev); + &pfl->mem, pfl->be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl, + pfl->name, total_len); + vmstate_register_ram(&pfl->mem, DEVICE(pfl)); pfl->storage = memory_region_get_ram_ptr(&pfl->mem); - memory_region_add_subregion(get_system_memory(), base, &pfl->mem); + sysbus_init_mmio(dev, &pfl->mem); - pfl->bs = bs; if (pfl->bs) { /* read the initial flash content */ ret = bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9); + if (ret < 0) { - memory_region_del_subregion(get_system_memory(), &pfl->mem); - vmstate_unregister_ram(&pfl->mem, qdev); + vmstate_unregister_ram(&pfl->mem, DEVICE(pfl)); memory_region_destroy(&pfl->mem); - g_free(pfl); - return NULL; + return 1; } - bdrv_attach_dev_nofail(pfl->bs, pfl); } if (pfl->bs) { @@ -592,15 +588,9 @@ pflash_t *pflash_cfi01_register(hwaddr base, } pfl->timer = qemu_new_timer_ns(vm_clock, pflash_timer, pfl); - pfl->sector_len = sector_len; - pfl->width = width; pfl->wcycle = 0; pfl->cmd = 0; pfl->status = 0; - pfl->ident[0] = id0; - pfl->ident[1] = id1; - pfl->ident[2] = id2; - pfl->ident[3] = id3; /* Hardcoded CFI table */ pfl->cfi_len = 0x52; /* Standard "QRY" string */ @@ -649,7 +639,7 @@ pflash_t *pflash_cfi01_register(hwaddr base, pfl->cfi_table[0x28] = 0x02; pfl->cfi_table[0x29] = 0x00; /* Max number of bytes in multi-bytes write */ - if (width == 1) { + if (pfl->width == 1) { pfl->cfi_table[0x2A] = 0x08; } else { pfl->cfi_table[0x2A] = 0x0B; @@ -660,10 +650,10 @@ pflash_t *pflash_cfi01_register(hwaddr base, /* Number of erase block regions (uniform) */ pfl->cfi_table[0x2C] = 0x01; /* Erase block region 1 */ - pfl->cfi_table[0x2D] = nb_blocs - 1; - pfl->cfi_table[0x2E] = (nb_blocs - 1) >> 8; - pfl->cfi_table[0x2F] = sector_len >> 8; - pfl->cfi_table[0x30] = sector_len >> 16; + pfl->cfi_table[0x2D] = pfl->nb_blocs - 1; + pfl->cfi_table[0x2E] = (pfl->nb_blocs - 1) >> 8; + pfl->cfi_table[0x2F] = pfl->sector_len >> 8; + pfl->cfi_table[0x30] = pfl->sector_len >> 16; /* Extended */ pfl->cfi_table[0x31] = 'P'; @@ -685,6 +675,75 @@ pflash_t *pflash_cfi01_register(hwaddr base, pfl->cfi_table[0x3f] = 0x01; /* Number of protection fields */ + return 0; +} + +static Property pflash_cfi01_properties[] = { + DEFINE_PROP_DRIVE("drive", struct pflash_t, bs), + DEFINE_PROP_UINT32("num-blocks", struct pflash_t, nb_blocs, 0), + DEFINE_PROP_UINT64("sector-length", struct pflash_t, sector_len, 0), + DEFINE_PROP_UINT8("width", struct pflash_t, width, 0), + DEFINE_PROP_UINT8("big-endian", struct pflash_t, be, 0), + DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0), + DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0), + DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0), + DEFINE_PROP_UINT16("id3", struct pflash_t, ident3, 0), + DEFINE_PROP_STRING("name", struct pflash_t, name), + DEFINE_PROP_END_OF_LIST(), +}; + +static void pflash_cfi01_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pflash_cfi01_init; + dc->props = pflash_cfi01_properties; +} + + +static const TypeInfo pflash_cfi01_info = { + .name = "cfi.pflash01", + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(struct pflash_t), + .class_init = pflash_cfi01_class_init, +}; + +static void pflash_cfi01_register_types(void) +{ + type_register_static(&pflash_cfi01_info); +} + +type_init(pflash_cfi01_register_types) + +pflash_t *pflash_cfi01_register(hwaddr base, + DeviceState *qdev, const char *name, + hwaddr size, + BlockDriverState *bs, + uint32_t sector_len, int nb_blocs, int width, + uint16_t id0, uint16_t id1, + uint16_t id2, uint16_t id3, int be) +{ + DeviceState *dev = qdev_create(NULL, "cfi.pflash01"); + SysBusDevice *busdev = sysbus_from_qdev(dev); + pflash_t *pfl = (pflash_t *)object_dynamic_cast(OBJECT(dev), + "cfi.pflash01"); + + if (bs && qdev_prop_set_drive(dev, "drive", bs)) { + abort(); + } + qdev_prop_set_uint32(dev, "num-blocks", nb_blocs); + qdev_prop_set_uint64(dev, "sector-length", sector_len); + qdev_prop_set_uint8(dev, "width", width); + qdev_prop_set_uint8(dev, "big-endian", !!be); + qdev_prop_set_uint16(dev, "id0", id0); + qdev_prop_set_uint16(dev, "id1", id1); + qdev_prop_set_uint16(dev, "id2", id2); + qdev_prop_set_uint16(dev, "id3", id3); + qdev_prop_set_string(dev, "name", name); + qdev_init_nofail(dev); + + sysbus_mmio_map(busdev, 0, base); return pfl; } diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c index 083718bad3..f918e36580 100644 --- a/hw/pflash_cfi02.c +++ b/hw/pflash_cfi02.c @@ -41,6 +41,7 @@ #include "block.h" #include "exec-memory.h" #include "host-utils.h" +#include "sysbus.h" //#define PFLASH_DEBUG #ifdef PFLASH_DEBUG @@ -55,18 +56,26 @@ do { \ #define PFLASH_LAZY_ROMD_THRESHOLD 42 struct pflash_t { + SysBusDevice busdev; BlockDriverState *bs; uint32_t sector_len; + uint32_t nb_blocs; uint32_t chip_len; - int mappings; - int width; + uint8_t mappings; + uint8_t width; + uint8_t be; int wcycle; /* if 0, the flash is read normally */ int bypass; int ro; uint8_t cmd; uint8_t status; - uint16_t ident[4]; - uint16_t unlock_addr[2]; + /* FIXME: implement array device properties */ + uint16_t ident0; + uint16_t ident1; + uint16_t ident2; + uint16_t ident3; + uint16_t unlock_addr0; + uint16_t unlock_addr1; uint8_t cfi_len; uint8_t cfi_table[0x52]; QEMUTimer *timer; @@ -79,6 +88,7 @@ struct pflash_t { MemoryRegion orig_mem; int rom_mode; int read_counter; /* used for lazy switch-back to rom mode */ + char *name; void *storage; }; @@ -189,16 +199,17 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset, switch (boff) { case 0x00: case 0x01: - ret = pfl->ident[boff & 0x01]; + ret = boff & 0x01 ? pfl->ident1 : pfl->ident0; break; case 0x02: ret = 0x00; /* Pretend all sectors are unprotected */ break; case 0x0E: case 0x0F: - if (pfl->ident[2 + (boff & 0x01)] == (uint8_t)-1) + ret = boff & 0x01 ? pfl->ident3 : pfl->ident2; + if (ret == (uint8_t)-1) { goto flash_read; - ret = pfl->ident[2 + (boff & 0x01)]; + } break; default: goto flash_read; @@ -282,9 +293,9 @@ static void pflash_write (pflash_t *pfl, hwaddr offset, pfl->cmd = 0x98; return; } - if (boff != pfl->unlock_addr[0] || cmd != 0xAA) { + if (boff != pfl->unlock_addr0 || cmd != 0xAA) { DPRINTF("%s: unlock0 failed " TARGET_FMT_plx " %02x %04x\n", - __func__, boff, cmd, pfl->unlock_addr[0]); + __func__, boff, cmd, pfl->unlock_addr0); goto reset_flash; } DPRINTF("%s: unlock sequence started\n", __func__); @@ -292,7 +303,7 @@ static void pflash_write (pflash_t *pfl, hwaddr offset, case 1: /* We started an unlock sequence */ check_unlock1: - if (boff != pfl->unlock_addr[1] || cmd != 0x55) { + if (boff != pfl->unlock_addr1 || cmd != 0x55) { DPRINTF("%s: unlock1 failed " TARGET_FMT_plx " %02x\n", __func__, boff, cmd); goto reset_flash; @@ -301,7 +312,7 @@ static void pflash_write (pflash_t *pfl, hwaddr offset, break; case 2: /* We finished an unlock sequence */ - if (!pfl->bypass && boff != pfl->unlock_addr[0]) { + if (!pfl->bypass && boff != pfl->unlock_addr0) { DPRINTF("%s: command failed " TARGET_FMT_plx " %02x\n", __func__, boff, cmd); goto reset_flash; @@ -399,7 +410,7 @@ static void pflash_write (pflash_t *pfl, hwaddr offset, case 5: switch (cmd) { case 0x10: - if (boff != pfl->unlock_addr[0]) { + if (boff != pfl->unlock_addr0) { DPRINTF("%s: chip erase: invalid address " TARGET_FMT_plx "\n", __func__, offset); goto reset_flash; @@ -574,49 +585,38 @@ static const MemoryRegionOps pflash_cfi02_ops_le = { .endianness = DEVICE_NATIVE_ENDIAN, }; -pflash_t *pflash_cfi02_register(hwaddr base, - DeviceState *qdev, const char *name, - hwaddr size, - BlockDriverState *bs, uint32_t sector_len, - int nb_blocs, int nb_mappings, int width, - uint16_t id0, uint16_t id1, - uint16_t id2, uint16_t id3, - uint16_t unlock_addr0, uint16_t unlock_addr1, - int be) +static int pflash_cfi02_init(SysBusDevice *dev) { - pflash_t *pfl; - int32_t chip_len; + pflash_t *pfl = FROM_SYSBUS(typeof(*pfl), dev); + uint32_t chip_len; int ret; - chip_len = sector_len * nb_blocs; + chip_len = pfl->sector_len * pfl->nb_blocs; /* XXX: to be fixed */ #if 0 if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) && total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024)) return NULL; #endif - pfl = g_malloc0(sizeof(pflash_t)); - memory_region_init_rom_device( - &pfl->orig_mem, be ? &pflash_cfi02_ops_be : &pflash_cfi02_ops_le, pfl, - name, size); - vmstate_register_ram(&pfl->orig_mem, qdev); + + memory_region_init_rom_device(&pfl->orig_mem, pfl->be ? + &pflash_cfi02_ops_be : &pflash_cfi02_ops_le, + pfl, pfl->name, chip_len); + vmstate_register_ram(&pfl->orig_mem, DEVICE(pfl)); pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem); pfl->chip_len = chip_len; - pfl->mappings = nb_mappings; - pfl->bs = bs; if (pfl->bs) { /* read the initial flash content */ ret = bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9); if (ret < 0) { g_free(pfl); - return NULL; + return 1; } - bdrv_attach_dev_nofail(pfl->bs, pfl); } pflash_setup_mappings(pfl); pfl->rom_mode = 1; - memory_region_add_subregion(get_system_memory(), base, &pfl->mem); + sysbus_init_mmio(dev, &pfl->mem); if (pfl->bs) { pfl->ro = bdrv_is_read_only(pfl->bs); @@ -625,17 +625,9 @@ pflash_t *pflash_cfi02_register(hwaddr base, } pfl->timer = qemu_new_timer_ns(vm_clock, pflash_timer, pfl); - pfl->sector_len = sector_len; - pfl->width = width; pfl->wcycle = 0; pfl->cmd = 0; pfl->status = 0; - pfl->ident[0] = id0; - pfl->ident[1] = id1; - pfl->ident[2] = id2; - pfl->ident[3] = id3; - pfl->unlock_addr[0] = unlock_addr0; - pfl->unlock_addr[1] = unlock_addr1; /* Hardcoded CFI table (mostly from SG29 Spansion flash) */ pfl->cfi_len = 0x52; /* Standard "QRY" string */ @@ -691,10 +683,10 @@ pflash_t *pflash_cfi02_register(hwaddr base, /* Number of erase block regions (uniform) */ pfl->cfi_table[0x2C] = 0x01; /* Erase block region 1 */ - pfl->cfi_table[0x2D] = nb_blocs - 1; - pfl->cfi_table[0x2E] = (nb_blocs - 1) >> 8; - pfl->cfi_table[0x2F] = sector_len >> 8; - pfl->cfi_table[0x30] = sector_len >> 16; + pfl->cfi_table[0x2D] = pfl->nb_blocs - 1; + pfl->cfi_table[0x2E] = (pfl->nb_blocs - 1) >> 8; + pfl->cfi_table[0x2F] = pfl->sector_len >> 8; + pfl->cfi_table[0x30] = pfl->sector_len >> 16; /* Extended */ pfl->cfi_table[0x31] = 'P'; @@ -714,5 +706,81 @@ pflash_t *pflash_cfi02_register(hwaddr base, pfl->cfi_table[0x3b] = 0x00; pfl->cfi_table[0x3c] = 0x00; + return 0; +} + +static Property pflash_cfi02_properties[] = { + DEFINE_PROP_DRIVE("drive", struct pflash_t, bs), + DEFINE_PROP_UINT32("num-blocks", struct pflash_t, nb_blocs, 0), + DEFINE_PROP_UINT32("sector-length", struct pflash_t, sector_len, 0), + DEFINE_PROP_UINT8("width", struct pflash_t, width, 0), + DEFINE_PROP_UINT8("mappings", struct pflash_t, mappings, 0), + DEFINE_PROP_UINT8("big-endian", struct pflash_t, be, 0), + DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0), + DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0), + DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0), + DEFINE_PROP_UINT16("id3", struct pflash_t, ident3, 0), + DEFINE_PROP_UINT16("unlock-addr0", struct pflash_t, unlock_addr0, 0), + DEFINE_PROP_UINT16("unlock-addr1", struct pflash_t, unlock_addr1, 0), + DEFINE_PROP_STRING("name", struct pflash_t, name), + DEFINE_PROP_END_OF_LIST(), +}; + +static void pflash_cfi02_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pflash_cfi02_init; + dc->props = pflash_cfi02_properties; +} + +static const TypeInfo pflash_cfi02_info = { + .name = "cfi.pflash02", + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(struct pflash_t), + .class_init = pflash_cfi02_class_init, +}; + +static void pflash_cfi02_register_types(void) +{ + type_register_static(&pflash_cfi02_info); +} + +type_init(pflash_cfi02_register_types) + +pflash_t *pflash_cfi02_register(hwaddr base, + DeviceState *qdev, const char *name, + hwaddr size, + BlockDriverState *bs, uint32_t sector_len, + int nb_blocs, int nb_mappings, int width, + uint16_t id0, uint16_t id1, + uint16_t id2, uint16_t id3, + uint16_t unlock_addr0, uint16_t unlock_addr1, + int be) +{ + DeviceState *dev = qdev_create(NULL, "cfi.pflash02"); + SysBusDevice *busdev = sysbus_from_qdev(dev); + pflash_t *pfl = (pflash_t *)object_dynamic_cast(OBJECT(dev), + "cfi.pflash02"); + + if (bs && qdev_prop_set_drive(dev, "drive", bs)) { + abort(); + } + qdev_prop_set_uint32(dev, "num-blocks", nb_blocs); + qdev_prop_set_uint32(dev, "sector-length", sector_len); + qdev_prop_set_uint8(dev, "width", width); + qdev_prop_set_uint8(dev, "mappings", nb_mappings); + qdev_prop_set_uint8(dev, "big-endian", !!be); + qdev_prop_set_uint16(dev, "id0", id0); + qdev_prop_set_uint16(dev, "id1", id1); + qdev_prop_set_uint16(dev, "id2", id2); + qdev_prop_set_uint16(dev, "id3", id3); + qdev_prop_set_uint16(dev, "unlock-addr0", unlock_addr0); + qdev_prop_set_uint16(dev, "unlock-addr1", unlock_addr1); + qdev_prop_set_string(dev, "name", name); + qdev_init_nofail(dev); + + sysbus_mmio_map(busdev, 0, base); return pfl; } From fc5b64d0829297c7a525ddf6c0bb08ef0a9af5b6 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 30 Oct 2012 07:45:11 +0000 Subject: [PATCH 1285/2270] pflash_cfi01: Fix debug mode printfery This DPRINTF was throwing a warning due to a missing cast. Signed-off-by: Peter Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/pflash_cfi01.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index d30d43c318..7d040b508a 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -182,7 +182,8 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset, DPRINTF("%s: Device ID Code %04x\n", __func__, ret); break; default: - DPRINTF("%s: Read Device Information boff=%x\n", __func__, boff); + DPRINTF("%s: Read Device Information boff=%x\n", __func__, + (unsigned)boff); ret = 0; break; } From f2d189d38436a8ccdedd94de01673b04aa008e11 Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Tue, 30 Oct 2012 07:45:12 +0000 Subject: [PATCH 1286/2270] hw/sd.c: Fix erase for high capacity cards Standard capacity cards SDSC use byte unit address while SDHC and SDXC cards use block unit address (512 bytes) when setting ERASE_START and ERASE_END with CMD32 and CMD33, we have to account for this. Signed-off-by: Igor Mitsyanko Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/sd.c | 17 +++++++++++++---- hw/sd.h | 1 + 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/hw/sd.c b/hw/sd.c index 297580aabe..b2f211c13a 100644 --- a/hw/sd.c +++ b/hw/sd.c @@ -476,19 +476,28 @@ void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert) static void sd_erase(SDState *sd) { - int i, start, end; + int i; + uint64_t erase_start = sd->erase_start; + uint64_t erase_end = sd->erase_end; + if (!sd->erase_start || !sd->erase_end) { sd->card_status |= ERASE_SEQ_ERROR; return; } - start = sd_addr_to_wpnum(sd->erase_start); - end = sd_addr_to_wpnum(sd->erase_end); + if (extract32(sd->ocr, OCR_CCS_BITN, 1)) { + /* High capacity memory card: erase units are 512 byte blocks */ + erase_start *= 512; + erase_end *= 512; + } + + erase_start = sd_addr_to_wpnum(erase_start); + erase_end = sd_addr_to_wpnum(erase_end); sd->erase_start = 0; sd->erase_end = 0; sd->csd[14] |= 0x40; - for (i = start; i <= end; i++) { + for (i = erase_start; i <= erase_end; i++) { if (test_bit(i, sd->wp_groups)) { sd->card_status |= WP_ERASE_SKIP; } diff --git a/hw/sd.h b/hw/sd.h index 4eb9679acd..d9b97e4466 100644 --- a/hw/sd.h +++ b/hw/sd.h @@ -50,6 +50,7 @@ #define READY_FOR_DATA (1 << 8) #define APP_CMD (1 << 5) #define AKE_SEQ_ERROR (1 << 3) +#define OCR_CCS_BITN 30 typedef enum { sd_none = -1, From 08e99e296fbe695d13c8ac944867d9def7f7c5d0 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2012 07:45:12 +0000 Subject: [PATCH 1287/2270] vmstate: Add support for saving/loading bitmaps Add support for saving/loading bitmap.h bitmaps in vmstate. Signed-off-by: Peter Maydell Tested-by: Igor Mitsyanko Reviewed-by: Juan Quintela --- savevm.c | 41 +++++++++++++++++++++++++++++++++++++++++ vmstate.h | 13 +++++++++++++ 2 files changed, 54 insertions(+) diff --git a/savevm.c b/savevm.c index b080d37258..43d3d1bbeb 100644 --- a/savevm.c +++ b/savevm.c @@ -86,6 +86,7 @@ #include "memory.h" #include "qmp-commands.h" #include "trace.h" +#include "bitops.h" #define SELF_ANNOUNCE_ROUNDS 5 @@ -1132,6 +1133,46 @@ const VMStateInfo vmstate_info_unused_buffer = { .put = put_unused_buffer, }; +/* bitmaps (as defined by bitmap.h). Note that size here is the size + * of the bitmap in bits. The on-the-wire format of a bitmap is 64 + * bit words with the bits in big endian order. The in-memory format + * is an array of 'unsigned long', which may be either 32 or 64 bits. + */ +/* This is the number of 64 bit words sent over the wire */ +#define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64) +static int get_bitmap(QEMUFile *f, void *pv, size_t size) +{ + unsigned long *bmp = pv; + int i, idx = 0; + for (i = 0; i < BITS_TO_U64S(size); i++) { + uint64_t w = qemu_get_be64(f); + bmp[idx++] = w; + if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) { + bmp[idx++] = w >> 32; + } + } + return 0; +} + +static void put_bitmap(QEMUFile *f, void *pv, size_t size) +{ + unsigned long *bmp = pv; + int i, idx = 0; + for (i = 0; i < BITS_TO_U64S(size); i++) { + uint64_t w = bmp[idx++]; + if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) { + w |= ((uint64_t)bmp[idx++]) << 32; + } + qemu_put_be64(f, w); + } +} + +const VMStateInfo vmstate_info_bitmap = { + .name = "bitmap", + .get = get_bitmap, + .put = put_bitmap, +}; + typedef struct CompatEntry { char idstr[256]; int instance_id; diff --git a/vmstate.h b/vmstate.h index c9c320e62e..623af0a29a 100644 --- a/vmstate.h +++ b/vmstate.h @@ -139,6 +139,7 @@ extern const VMStateInfo vmstate_info_uint64; extern const VMStateInfo vmstate_info_timer; extern const VMStateInfo vmstate_info_buffer; extern const VMStateInfo vmstate_info_unused_buffer; +extern const VMStateInfo vmstate_info_bitmap; #define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0) #define type_check_pointer(t1,t2) ((t1**)0 - (t2*)0) @@ -411,6 +412,18 @@ extern const VMStateInfo vmstate_info_unused_buffer; .flags = VMS_BUFFER, \ } +/* _field_size should be a int32_t field in the _state struct giving the + * size of the bitmap _field in bits. + */ +#define VMSTATE_BITMAP(_field, _state, _version, _field_size) { \ + .name = (stringify(_field)), \ + .version_id = (_version), \ + .size_offset = vmstate_offset_value(_state, _field_size, int32_t),\ + .info = &vmstate_info_bitmap, \ + .flags = VMS_VBUFFER|VMS_POINTER, \ + .offset = offsetof(_state, _field), \ +} + /* _f : field name _f_n : num of elements field_name _n : num of elements From 50a5be6c3d50c7684a417da4eb5f9587dace0a44 Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Tue, 30 Oct 2012 07:45:12 +0000 Subject: [PATCH 1288/2270] hw/sd.c: add SD card save/load support This patch updates SD card model to support save/load of card's state. Signed-off-by: Igor Mitsyanko Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/sd.c | 89 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 25 deletions(-) diff --git a/hw/sd.c b/hw/sd.c index b2f211c13a..3c34d43ad4 100644 --- a/hw/sd.c +++ b/hw/sd.c @@ -55,24 +55,28 @@ typedef enum { sd_illegal = -2, } sd_rsp_type_t; +enum SDCardModes { + sd_inactive, + sd_card_identification_mode, + sd_data_transfer_mode, +}; + +enum SDCardStates { + sd_inactive_state = -1, + sd_idle_state = 0, + sd_ready_state, + sd_identification_state, + sd_standby_state, + sd_transfer_state, + sd_sendingdata_state, + sd_receivingdata_state, + sd_programming_state, + sd_disconnect_state, +}; + struct SDState { - enum { - sd_inactive, - sd_card_identification_mode, - sd_data_transfer_mode, - } mode; - enum { - sd_inactive_state = -1, - sd_idle_state = 0, - sd_ready_state, - sd_identification_state, - sd_standby_state, - sd_transfer_state, - sd_sendingdata_state, - sd_receivingdata_state, - sd_programming_state, - sd_disconnect_state, - } state; + uint32_t mode; /* current card mode, one of SDCardModes */ + int32_t state; /* current card state, one of SDCardStates */ uint32_t ocr; uint8_t scr[8]; uint8_t cid[16]; @@ -83,21 +87,22 @@ struct SDState { uint32_t vhs; bool wp_switch; unsigned long *wp_groups; + int32_t wpgrps_size; uint64_t size; - int blk_len; + uint32_t blk_len; uint32_t erase_start; uint32_t erase_end; uint8_t pwd[16]; - int pwd_len; - int function_group[6]; + uint32_t pwd_len; + uint8_t function_group[6]; bool spi; - int current_cmd; + uint8_t current_cmd; /* True if we will handle the next command as an ACMD. Note that this does * *not* track the APP_CMD status bit! */ bool expecting_acmd; - int blk_written; + uint32_t blk_written; uint64_t data_start; uint32_t data_offset; uint8_t data[512]; @@ -421,8 +426,9 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv) if (sd->wp_groups) g_free(sd->wp_groups); sd->wp_switch = bdrv ? bdrv_is_read_only(bdrv) : false; - sd->wp_groups = bitmap_new(sect); - memset(sd->function_group, 0, sizeof(int) * 6); + sd->wpgrps_size = sect; + sd->wp_groups = bitmap_new(sd->wpgrps_size); + memset(sd->function_group, 0, sizeof(sd->function_group)); sd->erase_start = 0; sd->erase_end = 0; sd->size = size; @@ -446,6 +452,38 @@ static const BlockDevOps sd_block_ops = { .change_media_cb = sd_cardchange, }; +static const VMStateDescription sd_vmstate = { + .name = "sd-card", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(mode, SDState), + VMSTATE_INT32(state, SDState), + VMSTATE_UINT8_ARRAY(cid, SDState, 16), + VMSTATE_UINT8_ARRAY(csd, SDState, 16), + VMSTATE_UINT16(rca, SDState), + VMSTATE_UINT32(card_status, SDState), + VMSTATE_PARTIAL_BUFFER(sd_status, SDState, 1), + VMSTATE_UINT32(vhs, SDState), + VMSTATE_BITMAP(wp_groups, SDState, 0, wpgrps_size), + VMSTATE_UINT32(blk_len, SDState), + VMSTATE_UINT32(erase_start, SDState), + VMSTATE_UINT32(erase_end, SDState), + VMSTATE_UINT8_ARRAY(pwd, SDState, 16), + VMSTATE_UINT32(pwd_len, SDState), + VMSTATE_UINT8_ARRAY(function_group, SDState, 6), + VMSTATE_UINT8(current_cmd, SDState), + VMSTATE_BOOL(expecting_acmd, SDState), + VMSTATE_UINT32(blk_written, SDState), + VMSTATE_UINT64(data_start, SDState), + VMSTATE_UINT32(data_offset, SDState), + VMSTATE_UINT8_ARRAY(data, SDState, 512), + VMSTATE_BUFFER_UNSAFE(buf, SDState, 1, 512), + VMSTATE_BOOL(enable, SDState), + VMSTATE_END_OF_LIST() + } +}; + /* We do not model the chip select pin, so allow the board to select whether card should be in SSI or MMC/SD mode. It is also up to the board to ensure that ssi transfers only occur when the chip select @@ -463,6 +501,7 @@ SDState *sd_init(BlockDriverState *bs, bool is_spi) bdrv_attach_dev_nofail(sd->bdrv, sd); bdrv_set_dev_ops(sd->bdrv, &sd_block_ops, sd); } + vmstate_register(NULL, -1, &sd_vmstate, sd); return sd; } @@ -576,7 +615,7 @@ static void sd_lock_command(SDState *sd) sd->card_status |= LOCK_UNLOCK_FAILED; return; } - bitmap_zero(sd->wp_groups, sd_addr_to_wpnum(sd->size) + 1); + bitmap_zero(sd->wp_groups, sd->wpgrps_size); sd->csd[14] &= ~0x10; sd->card_status &= ~CARD_IS_LOCKED; sd->pwd_len = 0; From 0191253ceaf442e595cdd12ce80233b9de28cd13 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 24 Oct 2012 14:58:39 +0200 Subject: [PATCH 1289/2270] janitor: move iovector functions out of cutils.c This removes the dependency of cutils.c on iov.c, and lets us remove iov.o from several builds. Signed-off-by: Paolo Bonzini --- Makefile | 2 +- Makefile.objs | 4 +- cutils.c | 103 ------------------------------------------------- iov.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/Makefile | 2 +- 5 files changed, 107 insertions(+), 107 deletions(-) diff --git a/Makefile b/Makefile index 17e2d58ce5..ca716017cf 100644 --- a/Makefile +++ b/Makefile @@ -161,7 +161,7 @@ qemu-img.o: qemu-img-cmds.h tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \ qemu-timer-common.o main-loop.o notify.o \ - iohandler.o cutils.o iov.o async.o error.o + iohandler.o cutils.o async.o error.o tools-obj-$(CONFIG_POSIX) += compatfd.o qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y) diff --git a/Makefile.objs b/Makefile.objs index 9eca179903..99a268e7bf 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -92,7 +92,7 @@ common-obj-y += ui/ common-obj-y += bt-host.o bt-vhci.o common-obj-y += dma-helpers.o -common-obj-y += iov.o acl.o +common-obj-y += acl.o common-obj-$(CONFIG_POSIX) += compatfd.o common-obj-y += event_notifier.o common-obj-y += qemu-timer.o qemu-timer-common.o @@ -113,7 +113,7 @@ endif user-obj-y = user-obj-y += envlist.o path.o user-obj-y += tcg-runtime.o host-utils.o -user-obj-y += cutils.o iov.o cache-utils.o +user-obj-y += cutils.o cache-utils.o user-obj-y += module.o user-obj-y += qemu-user.o user-obj-y += $(trace-obj-y) diff --git a/cutils.c b/cutils.c index 8edd8fa13c..6f9f799bd3 100644 --- a/cutils.c +++ b/cutils.c @@ -142,109 +142,6 @@ int qemu_fdatasync(int fd) #endif } -/* io vectors */ - -void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint) -{ - qiov->iov = g_malloc(alloc_hint * sizeof(struct iovec)); - qiov->niov = 0; - qiov->nalloc = alloc_hint; - qiov->size = 0; -} - -void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov) -{ - int i; - - qiov->iov = iov; - qiov->niov = niov; - qiov->nalloc = -1; - qiov->size = 0; - for (i = 0; i < niov; i++) - qiov->size += iov[i].iov_len; -} - -void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len) -{ - assert(qiov->nalloc != -1); - - if (qiov->niov == qiov->nalloc) { - qiov->nalloc = 2 * qiov->nalloc + 1; - qiov->iov = g_realloc(qiov->iov, qiov->nalloc * sizeof(struct iovec)); - } - qiov->iov[qiov->niov].iov_base = base; - qiov->iov[qiov->niov].iov_len = len; - qiov->size += len; - ++qiov->niov; -} - -/* - * Concatenates (partial) iovecs from src to the end of dst. - * It starts copying after skipping `soffset' bytes at the - * beginning of src and adds individual vectors from src to - * dst copies up to `sbytes' bytes total, or up to the end - * of src if it comes first. This way, it is okay to specify - * very large value for `sbytes' to indicate "up to the end - * of src". - * Only vector pointers are processed, not the actual data buffers. - */ -void qemu_iovec_concat(QEMUIOVector *dst, - QEMUIOVector *src, size_t soffset, size_t sbytes) -{ - int i; - size_t done; - struct iovec *siov = src->iov; - assert(dst->nalloc != -1); - assert(src->size >= soffset); - for (i = 0, done = 0; done < sbytes && i < src->niov; i++) { - if (soffset < siov[i].iov_len) { - size_t len = MIN(siov[i].iov_len - soffset, sbytes - done); - qemu_iovec_add(dst, siov[i].iov_base + soffset, len); - done += len; - soffset = 0; - } else { - soffset -= siov[i].iov_len; - } - } - /* return done; */ -} - -void qemu_iovec_destroy(QEMUIOVector *qiov) -{ - assert(qiov->nalloc != -1); - - qemu_iovec_reset(qiov); - g_free(qiov->iov); - qiov->nalloc = 0; - qiov->iov = NULL; -} - -void qemu_iovec_reset(QEMUIOVector *qiov) -{ - assert(qiov->nalloc != -1); - - qiov->niov = 0; - qiov->size = 0; -} - -size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset, - void *buf, size_t bytes) -{ - return iov_to_buf(qiov->iov, qiov->niov, offset, buf, bytes); -} - -size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset, - const void *buf, size_t bytes) -{ - return iov_from_buf(qiov->iov, qiov->niov, offset, buf, bytes); -} - -size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset, - int fillc, size_t bytes) -{ - return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes); -} - /* * Checks if a buffer is all zeroes * diff --git a/iov.c b/iov.c index c6a66f0afe..ae17e7dff6 100644 --- a/iov.c +++ b/iov.c @@ -228,3 +228,106 @@ void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt, fprintf(fp, "\n"); } } + +/* io vectors */ + +void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint) +{ + qiov->iov = g_malloc(alloc_hint * sizeof(struct iovec)); + qiov->niov = 0; + qiov->nalloc = alloc_hint; + qiov->size = 0; +} + +void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov) +{ + int i; + + qiov->iov = iov; + qiov->niov = niov; + qiov->nalloc = -1; + qiov->size = 0; + for (i = 0; i < niov; i++) + qiov->size += iov[i].iov_len; +} + +void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len) +{ + assert(qiov->nalloc != -1); + + if (qiov->niov == qiov->nalloc) { + qiov->nalloc = 2 * qiov->nalloc + 1; + qiov->iov = g_realloc(qiov->iov, qiov->nalloc * sizeof(struct iovec)); + } + qiov->iov[qiov->niov].iov_base = base; + qiov->iov[qiov->niov].iov_len = len; + qiov->size += len; + ++qiov->niov; +} + +/* + * Concatenates (partial) iovecs from src to the end of dst. + * It starts copying after skipping `soffset' bytes at the + * beginning of src and adds individual vectors from src to + * dst copies up to `sbytes' bytes total, or up to the end + * of src if it comes first. This way, it is okay to specify + * very large value for `sbytes' to indicate "up to the end + * of src". + * Only vector pointers are processed, not the actual data buffers. + */ +void qemu_iovec_concat(QEMUIOVector *dst, + QEMUIOVector *src, size_t soffset, size_t sbytes) +{ + int i; + size_t done; + struct iovec *siov = src->iov; + assert(dst->nalloc != -1); + assert(src->size >= soffset); + for (i = 0, done = 0; done < sbytes && i < src->niov; i++) { + if (soffset < siov[i].iov_len) { + size_t len = MIN(siov[i].iov_len - soffset, sbytes - done); + qemu_iovec_add(dst, siov[i].iov_base + soffset, len); + done += len; + soffset = 0; + } else { + soffset -= siov[i].iov_len; + } + } + /* return done; */ +} + +void qemu_iovec_destroy(QEMUIOVector *qiov) +{ + assert(qiov->nalloc != -1); + + qemu_iovec_reset(qiov); + g_free(qiov->iov); + qiov->nalloc = 0; + qiov->iov = NULL; +} + +void qemu_iovec_reset(QEMUIOVector *qiov) +{ + assert(qiov->nalloc != -1); + + qiov->niov = 0; + qiov->size = 0; +} + +size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset, + void *buf, size_t bytes) +{ + return iov_to_buf(qiov->iov, qiov->niov, offset, buf, bytes); +} + +size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset, + const void *buf, size_t bytes) +{ + return iov_from_buf(qiov->iov, qiov->niov, offset, buf, bytes); +} + +size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset, + int fillc, size_t bytes) +{ + return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes); +} diff --git a/tests/Makefile b/tests/Makefile index 86c9b79ebe..945c82311e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -48,7 +48,7 @@ tests/check-qdict$(EXESUF): tests/check-qdict.o qdict.o qfloat.o qint.o qstring. tests/check-qlist$(EXESUF): tests/check-qlist.o qlist.o qint.o tests/check-qfloat$(EXESUF): tests/check-qfloat.o qfloat.o tests/check-qjson$(EXESUF): tests/check-qjson.o $(qobject-obj-y) $(tools-obj-y) -tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y) +tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y) iov.o tests/test-iov$(EXESUF): tests/test-iov.o iov.o tests/test-qapi-types.c tests/test-qapi-types.h :\ From f3192e8fb28529dd4fd777f916c437f49098ad39 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 29 Oct 2012 15:40:03 +0100 Subject: [PATCH 1290/2270] build: move cutils.o and qemu-timer-common.o to oslib-obj-y Signed-off-by: Paolo Bonzini --- Makefile | 3 +-- Makefile.objs | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index ca716017cf..4bfeeab80f 100644 --- a/Makefile +++ b/Makefile @@ -160,8 +160,7 @@ endif qemu-img.o: qemu-img-cmds.h tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \ - qemu-timer-common.o main-loop.o notify.o \ - iohandler.o cutils.o async.o error.o + main-loop.o notify.o iohandler.o async.o error.o tools-obj-$(CONFIG_POSIX) += compatfd.o qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y) diff --git a/Makefile.objs b/Makefile.objs index 99a268e7bf..9e36166e8b 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -19,7 +19,7 @@ universal-obj-y += $(qom-obj-y) ####################################################################### # oslib-obj-y is code depending on the OS (win32 vs posix) -oslib-obj-y = osdep.o +oslib-obj-y = osdep.o cutils.o qemu-timer-common.o oslib-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o oslib-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o @@ -41,7 +41,7 @@ coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o ####################################################################### # block-obj-y is code used by both qemu system emulation and qemu-img -block-obj-y = cutils.o iov.o cache-utils.o qemu-option.o module.o async.o +block-obj-y = iov.o cache-utils.o qemu-option.o module.o async.o block-obj-y += nbd.o block.o blockjob.o aio.o aes.o qemu-config.o block-obj-y += qemu-progress.o qemu-sockets.o uri.o notify.o block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y) @@ -113,7 +113,7 @@ endif user-obj-y = user-obj-y += envlist.o path.o user-obj-y += tcg-runtime.o host-utils.o -user-obj-y += cutils.o cache-utils.o +user-obj-y += cache-utils.o user-obj-y += module.o user-obj-y += qemu-user.o user-obj-y += $(trace-obj-y) From 67d223be90178f7142b4f566358cea446af8df74 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 29 Oct 2012 15:11:30 +0100 Subject: [PATCH 1291/2270] compiler: use weak aliases to provide default definitions This is simpler and more portable. Signed-off-by: Paolo Bonzini --- arch_init.h | 2 +- compiler.h | 11 ++++------- qmp.c | 3 ++- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/arch_init.h b/arch_init.h index d9c572aee8..5fc780c63d 100644 --- a/arch_init.h +++ b/arch_init.h @@ -34,6 +34,6 @@ int tcg_available(void); int kvm_available(void); int xen_available(void); -CpuDefinitionInfoList GCC_WEAK_DECL *arch_query_cpu_definitions(Error **errp); +CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp); #endif diff --git a/compiler.h b/compiler.h index c734a71c67..58865d65e8 100644 --- a/compiler.h +++ b/compiler.h @@ -50,16 +50,13 @@ # define __printf__ __gnu_printf__ # endif # endif -#if defined(_WIN32) -#define GCC_WEAK __attribute__((weak)) -#define GCC_WEAK_DECL GCC_WEAK -#else -#define GCC_WEAK __attribute__((weak)) -#define GCC_WEAK_DECL -#endif +# define QEMU_WEAK_ALIAS(newname, oldname) \ + typeof(oldname) newname __attribute__((weak, alias (#oldname))) #else #define GCC_ATTR /**/ #define GCC_FMT_ATTR(n, m) +#define QEMU_WEAK_ALIAS(newname, oldname) \ + _Pragma("weak " #newname "=" #oldname) #endif #endif /* COMPILER_H */ diff --git a/qmp.c b/qmp.c index 31bc3bfdd1..df952b60bc 100644 --- a/qmp.c +++ b/qmp.c @@ -466,11 +466,12 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename, return prop_list; } -CpuDefinitionInfoList GCC_WEAK *arch_query_cpu_definitions(Error **errp) +static CpuDefinitionInfoList *default_arch_query_cpu_definitions(Error **errp) { error_set(errp, QERR_NOT_SUPPORTED); return NULL; } +QEMU_WEAK_ALIAS(arch_query_cpu_definitions, default_arch_query_cpu_definitions); CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) { From d249e1fc4fda57399fe64b3c0290d5d585fdf2e5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 29 Oct 2012 15:15:15 +0100 Subject: [PATCH 1292/2270] sockets: use weak aliases instead of qemu-tool.c qemu-tool.c has its own (largeish) set of dependencies. Weak aliases can be placed directly where people use them, and do not contribute to increasing the dependencies of generic utility files. Signed-off-by: Paolo Bonzini --- qemu-sockets.c | 7 +++++++ qemu-tool.c | 6 ------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/qemu-sockets.c b/qemu-sockets.c index cfed9c5a5b..225cd0c162 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -967,3 +967,10 @@ int socket_init(void) #endif return 0; } + +static int default_monitor_get_fd(Monitor *mon, const char *name, Error **errp) +{ + error_setg(errp, "only QEMU supports file descriptor passing"); + return -1; +} +QEMU_WEAK_ALIAS(monitor_get_fd, default_monitor_get_fd); diff --git a/qemu-tool.c b/qemu-tool.c index da4c05aaf7..f2f98138ce 100644 --- a/qemu-tool.c +++ b/qemu-tool.c @@ -38,12 +38,6 @@ const char *qemu_get_vm_name(void) Monitor *cur_mon; -int monitor_get_fd(Monitor *mon, const char *name, Error **errp) -{ - error_setg(errp, "only QEMU supports file descriptor passing"); - return -1; -} - void vm_stop(RunState state) { abort(); From 0100fbbe73f1455ac66ec172627ff251a1f25302 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 29 Oct 2012 15:19:18 +0100 Subject: [PATCH 1293/2270] fdsets: use weak aliases instead of qemu-tool.c/qemu-user.c Signed-off-by: Paolo Bonzini --- cutils.c | 5 ----- osdep.c | 30 ++++++++++++++++++++++++++++++ qemu-common.h | 1 - qemu-tool.c | 20 -------------------- qemu-user.c | 20 -------------------- 5 files changed, 30 insertions(+), 46 deletions(-) diff --git a/cutils.c b/cutils.c index 6f9f799bd3..4f0692f78e 100644 --- a/cutils.c +++ b/cutils.c @@ -280,11 +280,6 @@ int qemu_parse_fd(const char *param) return fd; } -int qemu_parse_fdset(const char *param) -{ - return qemu_parse_fd(param); -} - /* round down to the nearest power of 2*/ int64_t pow2floor(int64_t value) { diff --git a/osdep.c b/osdep.c index 3b25297a25..0061f7473f 100644 --- a/osdep.c +++ b/osdep.c @@ -144,6 +144,11 @@ fail: errno = serrno; return -1; } + +static int qemu_parse_fdset(const char *param) +{ + return qemu_parse_fd(param); +} #endif /* @@ -404,3 +409,28 @@ bool fips_get_state(void) { return fips_enabled; } + + +static int default_fdset_get_fd(int64_t fdset_id, int flags) +{ + return -1; +} +QEMU_WEAK_ALIAS(monitor_fdset_get_fd, default_fdset_get_fd); + +static int default_fdset_dup_fd_add(int64_t fdset_id, int dup_fd) +{ + return -1; +} +QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_add, default_fdset_dup_fd_add); + +static int default_fdset_dup_fd_remove(int dup_fd) +{ + return -1; +} +QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_remove, default_fdset_dup_fd_remove); + +static int default_fdset_dup_fd_find(int dup_fd) +{ + return -1; +} +QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_find, default_fdset_dup_fd_find); diff --git a/qemu-common.h b/qemu-common.h index b54612b1a5..36ce522066 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -167,7 +167,6 @@ int qemu_fls(int i); int qemu_fdatasync(int fd); int fcntl_setfl(int fd, int flag); int qemu_parse_fd(const char *param); -int qemu_parse_fdset(const char *param); /* * strtosz() suffixes used to specify the default treatment of an diff --git a/qemu-tool.c b/qemu-tool.c index f2f98138ce..84273ae077 100644 --- a/qemu-tool.c +++ b/qemu-tool.c @@ -68,26 +68,6 @@ void monitor_protocol_event(MonitorEvent event, QObject *data) { } -int monitor_fdset_get_fd(int64_t fdset_id, int flags) -{ - return -1; -} - -int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd) -{ - return -1; -} - -int monitor_fdset_dup_fd_remove(int dup_fd) -{ - return -1; -} - -int monitor_fdset_dup_fd_find(int dup_fd) -{ - return -1; -} - int64_t cpu_get_clock(void) { return qemu_get_clock_ns(rt_clock); diff --git a/qemu-user.c b/qemu-user.c index 13fb9ae77b..08ccb0fe8e 100644 --- a/qemu-user.c +++ b/qemu-user.c @@ -35,23 +35,3 @@ void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) void monitor_set_error(Monitor *mon, QError *qerror) { } - -int monitor_fdset_get_fd(int64_t fdset_id, int flags) -{ - return -1; -} - -int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd) -{ - return -1; -} - -int monitor_fdset_dup_fd_remove(int dup_fd) -{ - return -1; -} - -int monitor_fdset_dup_fd_find(int dup_fd) -{ - return -1; -} From 462016d2da393b743ba97552521378e7de2a4c7f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 29 Oct 2012 15:23:16 +0100 Subject: [PATCH 1294/2270] iohandler: add weak alias in qemu-sockets.c, for qemu-ga Signed-off-by: Paolo Bonzini --- qemu-sockets.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/qemu-sockets.c b/qemu-sockets.c index 225cd0c162..f2a637165b 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -974,3 +974,14 @@ static int default_monitor_get_fd(Monitor *mon, const char *name, Error **errp) return -1; } QEMU_WEAK_ALIAS(monitor_get_fd, default_monitor_get_fd); + +static int default_qemu_set_fd_handler2(int fd, + IOCanReadHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque) + +{ + abort(); +} +QEMU_WEAK_ALIAS(qemu_set_fd_handler2, default_qemu_set_fd_handler2); From dbb5f3802e20af9a9971aa98d27c58839ea79a94 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 29 Oct 2012 18:55:03 +0100 Subject: [PATCH 1295/2270] win32: add weak version of qemu_fd_register Signed-off-by: Paolo Bonzini --- oslib-win32.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/oslib-win32.c b/oslib-win32.c index 51b33e8b20..9ca83df011 100644 --- a/oslib-win32.c +++ b/oslib-win32.c @@ -150,3 +150,8 @@ int qemu_get_thread_id(void) { return GetCurrentThreadId(); } + +static void default_qemu_fd_register(int fd) +{ +} +QEMU_WEAK_ALIAS(qemu_fd_register, default_qemu_fd_register); From 744ca8e3754e6808c6b5331d287adc533fca0ad3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 29 Oct 2012 15:26:28 +0100 Subject: [PATCH 1296/2270] qemu-timer: make initialization functions idempotent Signed-off-by: Paolo Bonzini --- qemu-timer.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/qemu-timer.c b/qemu-timer.c index 908a1030b6..b71e9a6e62 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -430,9 +430,11 @@ void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier) void init_clocks(void) { - rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME); - vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL); - host_clock = qemu_new_clock(QEMU_CLOCK_HOST); + if (!rt_clock) { + rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME); + vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL); + host_clock = qemu_new_clock(QEMU_CLOCK_HOST); + } } uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts) @@ -745,6 +747,10 @@ int init_timer_alarm(void) struct qemu_alarm_timer *t = NULL; int i, err = -1; + if (alarm_timer) { + return 0; + } + for (i = 0; alarm_timers[i].name; i++) { t = &alarm_timers[i]; From 172061a0a0d98c974ea8d5ed715195237bc44225 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 29 Oct 2012 15:28:36 +0100 Subject: [PATCH 1297/2270] main-loop: unify qemu_init_main_loop between QEMU and tools Signed-off-by: Paolo Bonzini --- main-loop.c | 5 ++++- main-loop.h | 10 ---------- qemu-tool.c | 7 ------- vl.c | 5 ----- 4 files changed, 4 insertions(+), 23 deletions(-) diff --git a/main-loop.c b/main-loop.c index eb3b6e6253..baefe413d1 100644 --- a/main-loop.c +++ b/main-loop.c @@ -199,10 +199,13 @@ static int qemu_signal_init(void) } #endif -int main_loop_init(void) +int qemu_init_main_loop(void) { int ret; + init_clocks(); + init_timer_alarm(); + qemu_mutex_lock_iothread(); ret = qemu_signal_init(); if (ret) { diff --git a/main-loop.h b/main-loop.h index dce1cd9d7c..91a0aff9c7 100644 --- a/main-loop.h +++ b/main-loop.h @@ -42,16 +42,6 @@ */ int qemu_init_main_loop(void); -/** - * main_loop_init: Initializes main loop - * - * Internal (but shared for compatibility reasons) initialization routine - * for the main loop. This should not be used by applications directly, - * use qemu_init_main_loop() instead. - * - */ -int main_loop_init(void); - /** * main_loop_wait: Run one iteration of the main loop. * diff --git a/qemu-tool.c b/qemu-tool.c index 84273ae077..28a4e8d42a 100644 --- a/qemu-tool.c +++ b/qemu-tool.c @@ -92,13 +92,6 @@ void qemu_clock_warp(QEMUClock *clock) { } -int qemu_init_main_loop(void) -{ - init_clocks(); - init_timer_alarm(); - return main_loop_init(); -} - void slirp_update_timeout(uint32_t *timeout) { } diff --git a/vl.c b/vl.c index 9f99ef4763..b3186fa425 100644 --- a/vl.c +++ b/vl.c @@ -2357,11 +2357,6 @@ static void free_and_trace(gpointer mem) free(mem); } -int qemu_init_main_loop(void) -{ - return main_loop_init(); -} - int main(int argc, char **argv, char **envp) { int i; From 3f4cdf151145f7eaa3480aea5d81d7def2f85a68 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 29 Oct 2012 18:03:10 +0100 Subject: [PATCH 1298/2270] qemu-tool: do not depend on qemu-timer.c Signed-off-by: Paolo Bonzini --- qemu-tool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu-tool.c b/qemu-tool.c index 28a4e8d42a..b46631e422 100644 --- a/qemu-tool.c +++ b/qemu-tool.c @@ -70,7 +70,7 @@ void monitor_protocol_event(MonitorEvent event, QObject *data) int64_t cpu_get_clock(void) { - return qemu_get_clock_ns(rt_clock); + return get_clock_realtime(); } int64_t cpu_get_icount(void) From 63186e56c8b5f1c988bfb0d707e76f0f0dceef90 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 30 Oct 2012 09:30:17 +0100 Subject: [PATCH 1299/2270] build: opts-visitor is not really part of QAPI It is only used by QEMU itself, do not build it into the tests. Signed-off-by: Paolo Bonzini --- qapi/Makefile.objs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs index 5f5846e767..f9bd3b9910 100644 --- a/qapi/Makefile.objs +++ b/qapi/Makefile.objs @@ -1,3 +1,5 @@ qapi-obj-y = qapi-visit-core.o qapi-dealloc-visitor.o qmp-input-visitor.o qapi-obj-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o -qapi-obj-y += string-input-visitor.o string-output-visitor.o opts-visitor.o +qapi-obj-y += string-input-visitor.o string-output-visitor.o + +common-obj-y += opts-visitor.o From 136594f19aa6370e77a50bd9bba5db77def6ec8f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 29 Oct 2012 15:46:15 +0100 Subject: [PATCH 1300/2270] build: do not include main loop where it is not actually used Signed-off-by: Paolo Bonzini --- Makefile | 6 +++--- Makefile.objs | 5 ++--- tests/Makefile | 8 ++++---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 4bfeeab80f..3ff63df732 100644 --- a/Makefile +++ b/Makefile @@ -160,7 +160,7 @@ endif qemu-img.o: qemu-img-cmds.h tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \ - main-loop.o notify.o iohandler.o async.o error.o + main-loop.o iohandler.o error.o tools-obj-$(CONFIG_POSIX) += compatfd.o qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y) @@ -169,7 +169,7 @@ qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y) qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o -vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) $(tools-obj-y) qemu-timer-common.o libcacard/vscclient.o +vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) libcacard/vscclient.o $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^ $(libcacard_libs) $(LIBS)," LINK $@") fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o oslib-posix.o $(trace-obj-y) @@ -212,7 +212,7 @@ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h) $(qga-obj-y) qemu-ga.o: $(QGALIB_GEN) -qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(tools-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y) +qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(oslib-obj-y) $(trace-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y) QEMULIBS=libuser libdis libdis-user diff --git a/Makefile.objs b/Makefile.objs index 9e36166e8b..54daa9f110 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -228,9 +228,8 @@ universal-obj-y += $(qapi-obj-y) ###################################################################### # guest agent -qga-obj-y = qga/ qemu-ga.o module.o -qga-obj-$(CONFIG_WIN32) += oslib-win32.o -qga-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-sockets.o qemu-option.o +qga-obj-y = qga/ qemu-ga.o module.o qemu-tool.o +qga-obj-$(CONFIG_POSIX) += qemu-sockets.o qemu-option.o vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS) diff --git a/tests/Makefile b/tests/Makefile index 945c82311e..9bf0765de3 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -36,7 +36,7 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \ tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \ tests/test-qmp-commands.o tests/test-visitor-serialization.o -test-qapi-obj-y = $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) +test-qapi-obj-y = $(qobject-obj-y) $(qapi-obj-y) qemu-tool.o test-qapi-obj-y += tests/test-qapi-visit.o tests/test-qapi-types.o test-qapi-obj-y += module.o @@ -47,8 +47,8 @@ tests/check-qstring$(EXESUF): tests/check-qstring.o qstring.o tests/check-qdict$(EXESUF): tests/check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o tests/check-qlist$(EXESUF): tests/check-qlist.o qlist.o qint.o tests/check-qfloat$(EXESUF): tests/check-qfloat.o qfloat.o -tests/check-qjson$(EXESUF): tests/check-qjson.o $(qobject-obj-y) $(tools-obj-y) -tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y) iov.o +tests/check-qjson$(EXESUF): tests/check-qjson.o $(qobject-obj-y) qemu-tool.o +tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y) $(block-obj-y) iov.o tests/test-iov$(EXESUF): tests/test-iov.o iov.o tests/test-qapi-types.c tests/test-qapi-types.h :\ @@ -81,7 +81,7 @@ TARGETS=$(patsubst %-softmmu,%, $(filter %-softmmu,$(TARGET_DIRS))) QTEST_TARGETS=$(foreach TARGET,$(TARGETS), $(if $(check-qtest-$(TARGET)-y), $(TARGET),)) check-qtest-$(CONFIG_POSIX)=$(foreach TARGET,$(TARGETS), $(check-qtest-$(TARGET)-y)) -qtest-obj-y = tests/libqtest.o $(oslib-obj-y) $(tools-obj-y) +qtest-obj-y = tests/libqtest.o $(oslib-obj-y) $(check-qtest-y): $(qtest-obj-y) .PHONY: check-help From fc97a652de3e54394ca4d0e5e5d689fd8aba8b6f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 24 May 2010 17:26:13 +0200 Subject: [PATCH 1301/2270] event_notifier: add Win32 implementation Signed-off-by: Paolo Bonzini --- Makefile.objs | 3 +- event_notifier.c => event_notifier-posix.c | 0 event_notifier-win32.c | 59 ++++++++++++++++++++++ event_notifier.h | 17 ++++++- qemu-os-win32.h | 1 - 5 files changed, 76 insertions(+), 4 deletions(-) rename event_notifier.c => event_notifier-posix.c (100%) create mode 100644 event_notifier-win32.c diff --git a/Makefile.objs b/Makefile.objs index 54daa9f110..5b39c33560 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -94,7 +94,8 @@ common-obj-y += bt-host.o bt-vhci.o common-obj-y += dma-helpers.o common-obj-y += acl.o common-obj-$(CONFIG_POSIX) += compatfd.o -common-obj-y += event_notifier.o +common-obj-$(CONFIG_POSIX) += event_notifier-posix.o +common-obj-$(CONFIG_WIN32) += event_notifier-win32.o common-obj-y += qemu-timer.o qemu-timer-common.o common-obj-y += qtest.o common-obj-y += vl.o diff --git a/event_notifier.c b/event_notifier-posix.c similarity index 100% rename from event_notifier.c rename to event_notifier-posix.c diff --git a/event_notifier-win32.c b/event_notifier-win32.c new file mode 100644 index 0000000000..c723dadf31 --- /dev/null +++ b/event_notifier-win32.c @@ -0,0 +1,59 @@ +/* + * event notifier support + * + * Copyright Red Hat, Inc. 2010 + * + * Authors: + * Michael S. Tsirkin + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu-common.h" +#include "event_notifier.h" +#include "main-loop.h" + +int event_notifier_init(EventNotifier *e, int active) +{ + e->event = CreateEvent(NULL, FALSE, FALSE, NULL); + assert(e->event); + return 0; +} + +void event_notifier_cleanup(EventNotifier *e) +{ + CloseHandle(e->event); +} + +HANDLE event_notifier_get_handle(EventNotifier *e) +{ + return e->event; +} + +int event_notifier_set_handler(EventNotifier *e, + EventNotifierHandler *handler) +{ + if (handler) { + return qemu_add_wait_object(e->event, (IOHandler *)handler, e); + } else { + qemu_del_wait_object(e->event, (IOHandler *)handler, e); + return 0; + } +} + +int event_notifier_set(EventNotifier *e) +{ + SetEvent(e->event); + return 0; +} + +int event_notifier_test_and_clear(EventNotifier *e) +{ + int ret = WaitForSingleObject(e->event, 0); + if (ret == WAIT_OBJECT_0) { + ResetEvent(e->event); + return true; + } + return false; +} diff --git a/event_notifier.h b/event_notifier.h index f0ec2f2171..b283a497ce 100644 --- a/event_notifier.h +++ b/event_notifier.h @@ -15,18 +15,31 @@ #include "qemu-common.h" +#ifdef _WIN32 +#include +#endif + struct EventNotifier { +#ifdef _WIN32 + HANDLE event; +#else int fd; +#endif }; typedef void EventNotifierHandler(EventNotifier *); -void event_notifier_init_fd(EventNotifier *, int fd); int event_notifier_init(EventNotifier *, int active); void event_notifier_cleanup(EventNotifier *); -int event_notifier_get_fd(EventNotifier *); int event_notifier_set(EventNotifier *); int event_notifier_test_and_clear(EventNotifier *); int event_notifier_set_handler(EventNotifier *, EventNotifierHandler *); +#ifdef CONFIG_POSIX +void event_notifier_init_fd(EventNotifier *, int fd); +int event_notifier_get_fd(EventNotifier *); +#else +HANDLE event_notifier_get_handle(EventNotifier *); +#endif + #endif diff --git a/qemu-os-win32.h b/qemu-os-win32.h index 8ba466dbfb..d0e9234d24 100644 --- a/qemu-os-win32.h +++ b/qemu-os-win32.h @@ -28,7 +28,6 @@ #include #include -#include "main-loop.h" /* Workaround for older versions of MinGW. */ #ifndef ECONNREFUSED From d0cc2fbfa607678866475383c508be84818ceb64 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 24 May 2010 17:17:04 +0200 Subject: [PATCH 1302/2270] event_notifier: enable it to use pipes This takes the eventfd emulation code from the main loop. When the EventNotifier is used for the main loop too, we need this compatibility code. Without CONFIG_EVENTFD, event_notifier_get_fd is only usable for the "read" side of the notifier, for example to set a select() handler. The return value of event_notifier_set changes to the cleaner 0/-errno. No caller is actually checking the return value. Reviewed-by: Anthony Liguori Signed-off-by: Paolo Bonzini --- event_notifier-posix.c | 85 ++++++++++++++++++++++++++++++++++-------- event_notifier.h | 3 +- 2 files changed, 71 insertions(+), 17 deletions(-) diff --git a/event_notifier-posix.c b/event_notifier-posix.c index 2c207e1399..6f3239a3fc 100644 --- a/event_notifier-posix.c +++ b/event_notifier-posix.c @@ -20,48 +20,101 @@ void event_notifier_init_fd(EventNotifier *e, int fd) { - e->fd = fd; + e->rfd = fd; + e->wfd = fd; } int event_notifier_init(EventNotifier *e, int active) { + int fds[2]; + int ret; + #ifdef CONFIG_EVENTFD - int fd = eventfd(!!active, EFD_NONBLOCK | EFD_CLOEXEC); - if (fd < 0) - return -errno; - e->fd = fd; - return 0; + ret = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); #else - return -ENOSYS; + ret = -1; + errno = ENOSYS; #endif + if (ret >= 0) { + e->rfd = e->wfd = ret; + } else { + if (errno != ENOSYS) { + return -errno; + } + if (qemu_pipe(fds) < 0) { + return -errno; + } + ret = fcntl_setfl(fds[0], O_NONBLOCK); + if (ret < 0) { + ret = -errno; + goto fail; + } + ret = fcntl_setfl(fds[1], O_NONBLOCK); + if (ret < 0) { + ret = -errno; + goto fail; + } + e->rfd = fds[0]; + e->wfd = fds[1]; + } + if (active) { + event_notifier_set(e); + } + return 0; + +fail: + close(fds[0]); + close(fds[1]); + return ret; } void event_notifier_cleanup(EventNotifier *e) { - close(e->fd); + if (e->rfd != e->wfd) { + close(e->rfd); + } + close(e->wfd); } int event_notifier_get_fd(EventNotifier *e) { - return e->fd; + return e->rfd; } int event_notifier_set_handler(EventNotifier *e, EventNotifierHandler *handler) { - return qemu_set_fd_handler(e->fd, (IOHandler *)handler, NULL, e); + return qemu_set_fd_handler(e->rfd, (IOHandler *)handler, NULL, e); } int event_notifier_set(EventNotifier *e) { - uint64_t value = 1; - int r = write(e->fd, &value, sizeof(value)); - return r == sizeof(value); + static const uint64_t value = 1; + ssize_t ret; + + do { + ret = write(e->wfd, &value, sizeof(value)); + } while (ret < 0 && errno == EINTR); + + /* EAGAIN is fine, a read must be pending. */ + if (ret < 0 && errno != EAGAIN) { + return -errno; + } + return 0; } int event_notifier_test_and_clear(EventNotifier *e) { - uint64_t value; - int r = read(e->fd, &value, sizeof(value)); - return r == sizeof(value); + int value; + ssize_t len; + char buffer[512]; + + /* Drain the notify pipe. For eventfd, only 8 bytes will be read. */ + value = 0; + do { + len = read(e->rfd, buffer, sizeof(buffer)); + value |= (len > 0); + } while ((len == -1 && errno == EINTR) || len == sizeof(buffer)); + + return value; } diff --git a/event_notifier.h b/event_notifier.h index b283a497ce..88b57af7ce 100644 --- a/event_notifier.h +++ b/event_notifier.h @@ -23,7 +23,8 @@ struct EventNotifier { #ifdef _WIN32 HANDLE event; #else - int fd; + int rfd; + int wfd; #endif }; From 1c53786fbdbdf20a3a6c556e09abb4d63ee7843e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 30 Oct 2012 00:17:12 +0100 Subject: [PATCH 1303/2270] vl: init main loop earlier Otherwise, chardevs will not be able to create a bottom half as soon as that will require an AioContext. Signed-off-by: Paolo Bonzini --- vl.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/vl.c b/vl.c index b3186fa425..f84e969a03 100644 --- a/vl.c +++ b/vl.c @@ -3311,6 +3311,12 @@ int main(int argc, char **argv, char **envp) } loc_set_none(); + qemu_init_cpu_loop(); + if (qemu_init_main_loop()) { + fprintf(stderr, "qemu_init_main_loop failed\n"); + exit(1); + } + if (qemu_opts_foreach(qemu_find_opts("sandbox"), parse_sandbox, NULL, 0)) { exit(1); } @@ -3463,12 +3469,6 @@ int main(int argc, char **argv, char **envp) configure_accelerator(); - qemu_init_cpu_loop(); - if (qemu_init_main_loop()) { - fprintf(stderr, "qemu_init_main_loop failed\n"); - exit(1); - } - machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); if (machine_opts) { kernel_filename = qemu_opt_get(machine_opts, "kernel"); From b078dc3cfec2d6d037caef91204ebf0a78e7ac06 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 13 Sep 2012 13:43:38 +0200 Subject: [PATCH 1304/2270] aio: change qemu_aio_set_fd_handler to return void Reviewed-by: Anthony Liguori Signed-off-by: Paolo Bonzini --- aio.c | 12 +++++------- qemu-aio.h | 10 +++++----- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/aio.c b/aio.c index c738a4e15d..e062aab2af 100644 --- a/aio.c +++ b/aio.c @@ -53,11 +53,11 @@ static AioHandler *find_aio_handler(int fd) return NULL; } -int qemu_aio_set_fd_handler(int fd, - IOHandler *io_read, - IOHandler *io_write, - AioFlushHandler *io_flush, - void *opaque) +void qemu_aio_set_fd_handler(int fd, + IOHandler *io_read, + IOHandler *io_write, + AioFlushHandler *io_flush, + void *opaque) { AioHandler *node; @@ -93,8 +93,6 @@ int qemu_aio_set_fd_handler(int fd, } qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque); - - return 0; } void qemu_aio_flush(void) diff --git a/qemu-aio.h b/qemu-aio.h index bfdd35f02c..27a7e21220 100644 --- a/qemu-aio.h +++ b/qemu-aio.h @@ -60,10 +60,10 @@ bool qemu_aio_wait(void); * Code that invokes AIO completion functions should rely on this function * instead of qemu_set_fd_handler[2]. */ -int qemu_aio_set_fd_handler(int fd, - IOHandler *io_read, - IOHandler *io_write, - AioFlushHandler *io_flush, - void *opaque); +void qemu_aio_set_fd_handler(int fd, + IOHandler *io_read, + IOHandler *io_write, + AioFlushHandler *io_flush, + void *opaque); #endif From 9958c351eee5b34051fd8061fe24f490ceca1334 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 9 Jun 2012 03:44:00 +0200 Subject: [PATCH 1305/2270] aio: provide platform-independent API This adds to aio.c a platform-independent API based on EventNotifiers, that can be used by both POSIX and Win32. Reviewed-by: Anthony Liguori Signed-off-by: Paolo Bonzini --- Makefile.objs | 4 ++-- aio.c | 9 +++++++++ qemu-aio.h | 19 ++++++++++++++++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/Makefile.objs b/Makefile.objs index 5b39c33560..98046fc64a 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -46,6 +46,8 @@ block-obj-y += nbd.o block.o blockjob.o aio.o aes.o qemu-config.o block-obj-y += qemu-progress.o qemu-sockets.o uri.o notify.o block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y) block-obj-$(CONFIG_POSIX) += posix-aio-compat.o +block-obj-$(CONFIG_POSIX) += event_notifier-posix.o +block-obj-$(CONFIG_WIN32) += event_notifier-win32.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o block-obj-y += block/ block-obj-y += $(qapi-obj-y) qapi-types.o qapi-visit.o @@ -94,8 +96,6 @@ common-obj-y += bt-host.o bt-vhci.o common-obj-y += dma-helpers.o common-obj-y += acl.o common-obj-$(CONFIG_POSIX) += compatfd.o -common-obj-$(CONFIG_POSIX) += event_notifier-posix.o -common-obj-$(CONFIG_WIN32) += event_notifier-win32.o common-obj-y += qemu-timer.o qemu-timer-common.o common-obj-y += qtest.o common-obj-y += vl.o diff --git a/aio.c b/aio.c index e062aab2af..44214e1ffc 100644 --- a/aio.c +++ b/aio.c @@ -95,6 +95,15 @@ void qemu_aio_set_fd_handler(int fd, qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque); } +void qemu_aio_set_event_notifier(EventNotifier *notifier, + EventNotifierHandler *io_read, + AioFlushEventNotifierHandler *io_flush) +{ + qemu_aio_set_fd_handler(event_notifier_get_fd(notifier), + (IOHandler *)io_read, NULL, + (AioFlushHandler *)io_flush, notifier); +} + void qemu_aio_flush(void) { while (qemu_aio_wait()); diff --git a/qemu-aio.h b/qemu-aio.h index 27a7e21220..dc416a5239 100644 --- a/qemu-aio.h +++ b/qemu-aio.h @@ -16,6 +16,7 @@ #include "qemu-common.h" #include "qemu-char.h" +#include "event_notifier.h" typedef struct BlockDriverAIOCB BlockDriverAIOCB; typedef void BlockDriverCompletionFunc(void *opaque, int ret); @@ -39,7 +40,7 @@ void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs, void qemu_aio_release(void *p); /* Returns 1 if there are still outstanding AIO requests; 0 otherwise */ -typedef int (AioFlushHandler)(void *opaque); +typedef int (AioFlushEventNotifierHandler)(EventNotifier *e); /* Flush any pending AIO operation. This function will block until all * outstanding AIO operations have been completed or cancelled. */ @@ -53,6 +54,10 @@ void qemu_aio_flush(void); * Return whether there is still any pending AIO operation. */ bool qemu_aio_wait(void); +#ifdef CONFIG_POSIX +/* Returns 1 if there are still outstanding AIO requests; 0 otherwise */ +typedef int (AioFlushHandler)(void *opaque); + /* Register a file descriptor and associated callbacks. Behaves very similarly * to qemu_set_fd_handler2. Unlike qemu_set_fd_handler2, these callbacks will * be invoked when using either qemu_aio_wait() or qemu_aio_flush(). @@ -65,5 +70,17 @@ void qemu_aio_set_fd_handler(int fd, IOHandler *io_write, AioFlushHandler *io_flush, void *opaque); +#endif + +/* Register an event notifier and associated callbacks. Behaves very similarly + * to event_notifier_set_handler. Unlike event_notifier_set_handler, these callbacks + * will be invoked when using either qemu_aio_wait() or qemu_aio_flush(). + * + * Code that invokes AIO completion functions should rely on this function + * instead of event_notifier_set_handler. + */ +void qemu_aio_set_event_notifier(EventNotifier *notifier, + EventNotifierHandler *io_read, + AioFlushEventNotifierHandler *io_flush); #endif From f627aab1ccea119fd94ca9e9df120cea6aab0c67 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 29 Oct 2012 23:45:23 +0100 Subject: [PATCH 1306/2270] aio: introduce AioContext, move bottom halves there Start introducing AioContext, which will let us remove globals from aio.c/async.c, and introduce multiple I/O threads. The bottom half functions now take an additional AioContext argument. A bottom half is created with a specific AioContext that remains the same throughout the lifetime. qemu_bh_new is just a wrapper that uses a global context. Signed-off-by: Paolo Bonzini --- aio.c | 2 -- async.c | 30 ++++++++-------- hw/hw.h | 1 + iohandler.c | 1 + linux-aio.c | 1 + main-loop.c | 18 +++++++++- main-loop.h | 55 ++---------------------------- qemu-aio.h | 79 ++++++++++++++++++++++++++++++++++++++++++- qemu-char.h | 1 + qemu-common.h | 1 + qemu-coroutine-lock.c | 2 +- 11 files changed, 119 insertions(+), 72 deletions(-) diff --git a/aio.c b/aio.c index 44214e1ffc..7e3fe708d2 100644 --- a/aio.c +++ b/aio.c @@ -18,8 +18,6 @@ #include "qemu-queue.h" #include "qemu_socket.h" -typedef struct AioHandler AioHandler; - /* The list of registered AIO handlers */ static QLIST_HEAD(, AioHandler) aio_handlers; diff --git a/async.c b/async.c index 85cc6410c5..189ee1beb5 100644 --- a/async.c +++ b/async.c @@ -26,9 +26,6 @@ #include "qemu-aio.h" #include "main-loop.h" -/* Anchor of the list of Bottom Halves belonging to the context */ -static struct QEMUBH *first_bh; - /***********************************************************/ /* bottom halves (can be seen as timers which expire ASAP) */ @@ -41,27 +38,26 @@ struct QEMUBH { bool deleted; }; -QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque) +QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque) { QEMUBH *bh; bh = g_malloc0(sizeof(QEMUBH)); bh->cb = cb; bh->opaque = opaque; - bh->next = first_bh; - first_bh = bh; + bh->next = ctx->first_bh; + ctx->first_bh = bh; return bh; } -int qemu_bh_poll(void) +int aio_bh_poll(AioContext *ctx) { QEMUBH *bh, **bhp, *next; int ret; - static int nesting = 0; - nesting++; + ctx->walking_bh++; ret = 0; - for (bh = first_bh; bh; bh = next) { + for (bh = ctx->first_bh; bh; bh = next) { next = bh->next; if (!bh->deleted && bh->scheduled) { bh->scheduled = 0; @@ -72,11 +68,11 @@ int qemu_bh_poll(void) } } - nesting--; + ctx->walking_bh--; /* remove deleted bhs */ - if (!nesting) { - bhp = &first_bh; + if (!ctx->walking_bh) { + bhp = &ctx->first_bh; while (*bhp) { bh = *bhp; if (bh->deleted) { @@ -120,11 +116,11 @@ void qemu_bh_delete(QEMUBH *bh) bh->deleted = 1; } -void qemu_bh_update_timeout(uint32_t *timeout) +void aio_bh_update_timeout(AioContext *ctx, uint32_t *timeout) { QEMUBH *bh; - for (bh = first_bh; bh; bh = bh->next) { + for (bh = ctx->first_bh; bh; bh = bh->next) { if (!bh->deleted && bh->scheduled) { if (bh->idle) { /* idle bottom halves will be polled at least @@ -140,3 +136,7 @@ void qemu_bh_update_timeout(uint32_t *timeout) } } +AioContext *aio_context_new(void) +{ + return g_new0(AioContext, 1); +} diff --git a/hw/hw.h b/hw/hw.h index b337ee3042..f530f6f41a 100644 --- a/hw/hw.h +++ b/hw/hw.h @@ -10,6 +10,7 @@ #include "ioport.h" #include "irq.h" +#include "qemu-aio.h" #include "qemu-file.h" #include "vmstate.h" #include "qemu-log.h" diff --git a/iohandler.c b/iohandler.c index a2d871bb91..60460a6f88 100644 --- a/iohandler.c +++ b/iohandler.c @@ -26,6 +26,7 @@ #include "qemu-common.h" #include "qemu-char.h" #include "qemu-queue.h" +#include "qemu-aio.h" #include "main-loop.h" #ifndef _WIN32 diff --git a/linux-aio.c b/linux-aio.c index ce9b5d4be8..f3d8ef33ca 100644 --- a/linux-aio.c +++ b/linux-aio.c @@ -9,6 +9,7 @@ */ #include "qemu-common.h" #include "qemu-aio.h" +#include "qemu-queue.h" #include "block/raw-posix-aio.h" #include diff --git a/main-loop.c b/main-loop.c index baefe413d1..40fdbd3770 100644 --- a/main-loop.c +++ b/main-loop.c @@ -26,6 +26,7 @@ #include "qemu-timer.h" #include "slirp/slirp.h" #include "main-loop.h" +#include "qemu-aio.h" #ifndef _WIN32 @@ -199,6 +200,8 @@ static int qemu_signal_init(void) } #endif +static AioContext *qemu_aio_context; + int qemu_init_main_loop(void) { int ret; @@ -218,6 +221,7 @@ int qemu_init_main_loop(void) return ret; } + qemu_aio_context = aio_context_new(); return 0; } @@ -481,7 +485,7 @@ int main_loop_wait(int nonblocking) if (nonblocking) { timeout = 0; } else { - qemu_bh_update_timeout(&timeout); + aio_bh_update_timeout(qemu_aio_context, &timeout); } /* poll any events */ @@ -510,3 +514,15 @@ int main_loop_wait(int nonblocking) return ret; } + +/* Functions to operate on the main QEMU AioContext. */ + +QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque) +{ + return aio_bh_new(qemu_aio_context, cb, opaque); +} + +int qemu_bh_poll(void) +{ + return aio_bh_poll(qemu_aio_context); +} diff --git a/main-loop.h b/main-loop.h index 91a0aff9c7..1d1a56b858 100644 --- a/main-loop.h +++ b/main-loop.h @@ -25,6 +25,8 @@ #ifndef QEMU_MAIN_LOOP_H #define QEMU_MAIN_LOOP_H 1 +#include "qemu-aio.h" + #define SIG_IPI SIGUSR1 /** @@ -163,7 +165,6 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque); typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size); typedef int IOCanReadHandler(void *opaque); -typedef void IOHandler(void *opaque); /** * qemu_set_fd_handler2: Register a file descriptor with the main loop @@ -244,56 +245,6 @@ int qemu_set_fd_handler(int fd, IOHandler *fd_write, void *opaque); -typedef struct QEMUBH QEMUBH; -typedef void QEMUBHFunc(void *opaque); - -/** - * qemu_bh_new: Allocate a new bottom half structure. - * - * Bottom halves are lightweight callbacks whose invocation is guaranteed - * to be wait-free, thread-safe and signal-safe. The #QEMUBH structure - * is opaque and must be allocated prior to its use. - */ -QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque); - -/** - * qemu_bh_schedule: Schedule a bottom half. - * - * Scheduling a bottom half interrupts the main loop and causes the - * execution of the callback that was passed to qemu_bh_new. - * - * Bottom halves that are scheduled from a bottom half handler are instantly - * invoked. This can create an infinite loop if a bottom half handler - * schedules itself. - * - * @bh: The bottom half to be scheduled. - */ -void qemu_bh_schedule(QEMUBH *bh); - -/** - * qemu_bh_cancel: Cancel execution of a bottom half. - * - * Canceling execution of a bottom half undoes the effect of calls to - * qemu_bh_schedule without freeing its resources yet. While cancellation - * itself is also wait-free and thread-safe, it can of course race with the - * loop that executes bottom halves unless you are holding the iothread - * mutex. This makes it mostly useless if you are not holding the mutex. - * - * @bh: The bottom half to be canceled. - */ -void qemu_bh_cancel(QEMUBH *bh); - -/** - *qemu_bh_delete: Cancel execution of a bottom half and free its resources. - * - * Deleting a bottom half frees the memory that was allocated for it by - * qemu_bh_new. It also implies canceling the bottom half if it was - * scheduled. - * - * @bh: The bottom half to be deleted. - */ -void qemu_bh_delete(QEMUBH *bh); - #ifdef CONFIG_POSIX /** * qemu_add_child_watch: Register a child process for reaping. @@ -349,8 +300,8 @@ void qemu_fd_register(int fd); void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds); void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc); +QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque); void qemu_bh_schedule_idle(QEMUBH *bh); int qemu_bh_poll(void); -void qemu_bh_update_timeout(uint32_t *timeout); #endif diff --git a/qemu-aio.h b/qemu-aio.h index dc416a5239..2ed6ad3723 100644 --- a/qemu-aio.h +++ b/qemu-aio.h @@ -15,7 +15,6 @@ #define QEMU_AIO_H #include "qemu-common.h" -#include "qemu-char.h" #include "event_notifier.h" typedef struct BlockDriverAIOCB BlockDriverAIOCB; @@ -39,9 +38,87 @@ void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque); void qemu_aio_release(void *p); +typedef struct AioHandler AioHandler; +typedef void QEMUBHFunc(void *opaque); +typedef void IOHandler(void *opaque); + +typedef struct AioContext { + /* Anchor of the list of Bottom Halves belonging to the context */ + struct QEMUBH *first_bh; + + /* A simple lock used to protect the first_bh list, and ensure that + * no callbacks are removed while we're walking and dispatching callbacks. + */ + int walking_bh; +} AioContext; + /* Returns 1 if there are still outstanding AIO requests; 0 otherwise */ typedef int (AioFlushEventNotifierHandler)(EventNotifier *e); +/** + * aio_context_new: Allocate a new AioContext. + * + * AioContext provide a mini event-loop that can be waited on synchronously. + * They also provide bottom halves, a service to execute a piece of code + * as soon as possible. + */ +AioContext *aio_context_new(void); + +/** + * aio_bh_new: Allocate a new bottom half structure. + * + * Bottom halves are lightweight callbacks whose invocation is guaranteed + * to be wait-free, thread-safe and signal-safe. The #QEMUBH structure + * is opaque and must be allocated prior to its use. + */ +QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque); + +/** + * aio_bh_poll: Poll bottom halves for an AioContext. + * + * These are internal functions used by the QEMU main loop. + */ +int aio_bh_poll(AioContext *ctx); +void aio_bh_update_timeout(AioContext *ctx, uint32_t *timeout); + +/** + * qemu_bh_schedule: Schedule a bottom half. + * + * Scheduling a bottom half interrupts the main loop and causes the + * execution of the callback that was passed to qemu_bh_new. + * + * Bottom halves that are scheduled from a bottom half handler are instantly + * invoked. This can create an infinite loop if a bottom half handler + * schedules itself. + * + * @bh: The bottom half to be scheduled. + */ +void qemu_bh_schedule(QEMUBH *bh); + +/** + * qemu_bh_cancel: Cancel execution of a bottom half. + * + * Canceling execution of a bottom half undoes the effect of calls to + * qemu_bh_schedule without freeing its resources yet. While cancellation + * itself is also wait-free and thread-safe, it can of course race with the + * loop that executes bottom halves unless you are holding the iothread + * mutex. This makes it mostly useless if you are not holding the mutex. + * + * @bh: The bottom half to be canceled. + */ +void qemu_bh_cancel(QEMUBH *bh); + +/** + *qemu_bh_delete: Cancel execution of a bottom half and free its resources. + * + * Deleting a bottom half frees the memory that was allocated for it by + * qemu_bh_new. It also implies canceling the bottom half if it was + * scheduled. + * + * @bh: The bottom half to be deleted. + */ +void qemu_bh_delete(QEMUBH *bh); + /* Flush any pending AIO operation. This function will block until all * outstanding AIO operations have been completed or cancelled. */ void qemu_aio_flush(void); diff --git a/qemu-char.h b/qemu-char.h index 486644b3bd..5087168bd7 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -5,6 +5,7 @@ #include "qemu-queue.h" #include "qemu-option.h" #include "qemu-config.h" +#include "qemu-aio.h" #include "qobject.h" #include "qstring.h" #include "main-loop.h" diff --git a/qemu-common.h b/qemu-common.h index 36ce522066..24e13ccb5e 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -14,6 +14,7 @@ typedef struct QEMUTimer QEMUTimer; typedef struct QEMUFile QEMUFile; +typedef struct QEMUBH QEMUBH; typedef struct DeviceState DeviceState; struct Monitor; diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c index 26ad76bf50..9dda3f86c9 100644 --- a/qemu-coroutine-lock.c +++ b/qemu-coroutine-lock.c @@ -26,7 +26,7 @@ #include "qemu-coroutine.h" #include "qemu-coroutine-int.h" #include "qemu-queue.h" -#include "main-loop.h" +#include "qemu-aio.h" #include "trace.h" static QTAILQ_HEAD(, Coroutine) unlock_bh_queue = From a915f4bc977c4f3aab08a78023c1303664d1c606 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 13 Sep 2012 12:28:51 +0200 Subject: [PATCH 1307/2270] aio: add I/O handlers to the AioContext interface With this patch, I/O handlers (including event notifier handlers) can be attached to a single AioContext. Signed-off-by: Paolo Bonzini --- aio.c | 68 +++++++++++++++++++++-------------------------------- async.c | 6 +++++ main-loop.c | 33 ++++++++++++++++++++++++++ qemu-aio.h | 42 +++++++++++++++++++++++++++------ 4 files changed, 101 insertions(+), 48 deletions(-) diff --git a/aio.c b/aio.c index 7e3fe708d2..c89f1e95c1 100644 --- a/aio.c +++ b/aio.c @@ -18,15 +18,6 @@ #include "qemu-queue.h" #include "qemu_socket.h" -/* The list of registered AIO handlers */ -static QLIST_HEAD(, AioHandler) aio_handlers; - -/* This is a simple lock used to protect the aio_handlers list. Specifically, - * it's used to ensure that no callbacks are removed while we're walking and - * dispatching callbacks. - */ -static int walking_handlers; - struct AioHandler { int fd; @@ -38,11 +29,11 @@ struct AioHandler QLIST_ENTRY(AioHandler) node; }; -static AioHandler *find_aio_handler(int fd) +static AioHandler *find_aio_handler(AioContext *ctx, int fd) { AioHandler *node; - QLIST_FOREACH(node, &aio_handlers, node) { + QLIST_FOREACH(node, &ctx->aio_handlers, node) { if (node->fd == fd) if (!node->deleted) return node; @@ -51,21 +42,22 @@ static AioHandler *find_aio_handler(int fd) return NULL; } -void qemu_aio_set_fd_handler(int fd, - IOHandler *io_read, - IOHandler *io_write, - AioFlushHandler *io_flush, - void *opaque) +void aio_set_fd_handler(AioContext *ctx, + int fd, + IOHandler *io_read, + IOHandler *io_write, + AioFlushHandler *io_flush, + void *opaque) { AioHandler *node; - node = find_aio_handler(fd); + node = find_aio_handler(ctx, fd); /* Are we deleting the fd handler? */ if (!io_read && !io_write) { if (node) { /* If the lock is held, just mark the node as deleted */ - if (walking_handlers) + if (ctx->walking_handlers) node->deleted = 1; else { /* Otherwise, delete it for real. We can't just mark it as @@ -81,7 +73,7 @@ void qemu_aio_set_fd_handler(int fd, /* Alloc and insert if it's not already there */ node = g_malloc0(sizeof(AioHandler)); node->fd = fd; - QLIST_INSERT_HEAD(&aio_handlers, node, node); + QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); } /* Update handler with latest information */ node->io_read = io_read; @@ -89,25 +81,19 @@ void qemu_aio_set_fd_handler(int fd, node->io_flush = io_flush; node->opaque = opaque; } - - qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque); } -void qemu_aio_set_event_notifier(EventNotifier *notifier, - EventNotifierHandler *io_read, - AioFlushEventNotifierHandler *io_flush) +void aio_set_event_notifier(AioContext *ctx, + EventNotifier *notifier, + EventNotifierHandler *io_read, + AioFlushEventNotifierHandler *io_flush) { - qemu_aio_set_fd_handler(event_notifier_get_fd(notifier), - (IOHandler *)io_read, NULL, - (AioFlushHandler *)io_flush, notifier); + aio_set_fd_handler(ctx, event_notifier_get_fd(notifier), + (IOHandler *)io_read, NULL, + (AioFlushHandler *)io_flush, notifier); } -void qemu_aio_flush(void) -{ - while (qemu_aio_wait()); -} - -bool qemu_aio_wait(void) +bool aio_wait(AioContext *ctx) { AioHandler *node; fd_set rdfds, wrfds; @@ -120,18 +106,18 @@ bool qemu_aio_wait(void) * Do not call select in this case, because it is possible that the caller * does not need a complete flush (as is the case for qemu_aio_wait loops). */ - if (qemu_bh_poll()) { + if (aio_bh_poll(ctx)) { return true; } - walking_handlers++; + ctx->walking_handlers++; FD_ZERO(&rdfds); FD_ZERO(&wrfds); /* fill fd sets */ busy = false; - QLIST_FOREACH(node, &aio_handlers, node) { + QLIST_FOREACH(node, &ctx->aio_handlers, node) { /* If there aren't pending AIO operations, don't invoke callbacks. * Otherwise, if there are no AIO requests, qemu_aio_wait() would * wait indefinitely. @@ -152,7 +138,7 @@ bool qemu_aio_wait(void) } } - walking_handlers--; + ctx->walking_handlers--; /* No AIO operations? Get us out of here */ if (!busy) { @@ -166,11 +152,11 @@ bool qemu_aio_wait(void) if (ret > 0) { /* we have to walk very carefully in case * qemu_aio_set_fd_handler is called while we're walking */ - node = QLIST_FIRST(&aio_handlers); + node = QLIST_FIRST(&ctx->aio_handlers); while (node) { AioHandler *tmp; - walking_handlers++; + ctx->walking_handlers++; if (!node->deleted && FD_ISSET(node->fd, &rdfds) && @@ -186,9 +172,9 @@ bool qemu_aio_wait(void) tmp = node; node = QLIST_NEXT(node, node); - walking_handlers--; + ctx->walking_handlers--; - if (!walking_handlers && tmp->deleted) { + if (!ctx->walking_handlers && tmp->deleted) { QLIST_REMOVE(tmp, node); g_free(tmp); } diff --git a/async.c b/async.c index 189ee1beb5..c99db79ac7 100644 --- a/async.c +++ b/async.c @@ -136,7 +136,13 @@ void aio_bh_update_timeout(AioContext *ctx, uint32_t *timeout) } } + AioContext *aio_context_new(void) { return g_new0(AioContext, 1); } + +void aio_flush(AioContext *ctx) +{ + while (aio_wait(ctx)); +} diff --git a/main-loop.c b/main-loop.c index 40fdbd3770..8f0117e7aa 100644 --- a/main-loop.c +++ b/main-loop.c @@ -526,3 +526,36 @@ int qemu_bh_poll(void) { return aio_bh_poll(qemu_aio_context); } + +void qemu_aio_flush(void) +{ + aio_flush(qemu_aio_context); +} + +bool qemu_aio_wait(void) +{ + return aio_wait(qemu_aio_context); +} + +void qemu_aio_set_fd_handler(int fd, + IOHandler *io_read, + IOHandler *io_write, + AioFlushHandler *io_flush, + void *opaque) +{ + aio_set_fd_handler(qemu_aio_context, fd, io_read, io_write, io_flush, + opaque); + + qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque); +} + +#ifdef CONFIG_POSIX +void qemu_aio_set_event_notifier(EventNotifier *notifier, + EventNotifierHandler *io_read, + AioFlushEventNotifierHandler *io_flush) +{ + qemu_aio_set_fd_handler(event_notifier_get_fd(notifier), + (IOHandler *)io_read, NULL, + (AioFlushHandler *)io_flush, notifier); +} +#endif diff --git a/qemu-aio.h b/qemu-aio.h index 2ed6ad3723..f8a93d8fb9 100644 --- a/qemu-aio.h +++ b/qemu-aio.h @@ -15,6 +15,7 @@ #define QEMU_AIO_H #include "qemu-common.h" +#include "qemu-queue.h" #include "event_notifier.h" typedef struct BlockDriverAIOCB BlockDriverAIOCB; @@ -43,6 +44,15 @@ typedef void QEMUBHFunc(void *opaque); typedef void IOHandler(void *opaque); typedef struct AioContext { + /* The list of registered AIO handlers */ + QLIST_HEAD(, AioHandler) aio_handlers; + + /* This is a simple lock used to protect the aio_handlers list. + * Specifically, it's used to ensure that no callbacks are removed while + * we're walking and dispatching callbacks. + */ + int walking_handlers; + /* Anchor of the list of Bottom Halves belonging to the context */ struct QEMUBH *first_bh; @@ -121,7 +131,7 @@ void qemu_bh_delete(QEMUBH *bh); /* Flush any pending AIO operation. This function will block until all * outstanding AIO operations have been completed or cancelled. */ -void qemu_aio_flush(void); +void aio_flush(AioContext *ctx); /* Wait for a single AIO completion to occur. This function will wait * until a single AIO event has completed and it will ensure something @@ -129,7 +139,7 @@ void qemu_aio_flush(void); * result of executing I/O completion or bh callbacks. * * Return whether there is still any pending AIO operation. */ -bool qemu_aio_wait(void); +bool aio_wait(AioContext *ctx); #ifdef CONFIG_POSIX /* Returns 1 if there are still outstanding AIO requests; 0 otherwise */ @@ -142,11 +152,12 @@ typedef int (AioFlushHandler)(void *opaque); * Code that invokes AIO completion functions should rely on this function * instead of qemu_set_fd_handler[2]. */ -void qemu_aio_set_fd_handler(int fd, - IOHandler *io_read, - IOHandler *io_write, - AioFlushHandler *io_flush, - void *opaque); +void aio_set_fd_handler(AioContext *ctx, + int fd, + IOHandler *io_read, + IOHandler *io_write, + AioFlushHandler *io_flush, + void *opaque); #endif /* Register an event notifier and associated callbacks. Behaves very similarly @@ -156,8 +167,25 @@ void qemu_aio_set_fd_handler(int fd, * Code that invokes AIO completion functions should rely on this function * instead of event_notifier_set_handler. */ +void aio_set_event_notifier(AioContext *ctx, + EventNotifier *notifier, + EventNotifierHandler *io_read, + AioFlushEventNotifierHandler *io_flush); + +/* Functions to operate on the main QEMU AioContext. */ + +void qemu_aio_flush(void); +bool qemu_aio_wait(void); void qemu_aio_set_event_notifier(EventNotifier *notifier, EventNotifierHandler *io_read, AioFlushEventNotifierHandler *io_flush); +#ifdef CONFIG_POSIX +void qemu_aio_set_fd_handler(int fd, + IOHandler *io_read, + IOHandler *io_write, + AioFlushHandler *io_flush, + void *opaque); +#endif + #endif From 4231c88d27d9e46e6ad6e6b7bbb6e442bcf9cd05 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 26 Sep 2012 15:21:36 +0200 Subject: [PATCH 1308/2270] aio: test node->deleted before calling io_flush Otherwise, there could be a case where io_flush accesses freed memory because it should not have been called. Signed-off-by: Paolo Bonzini --- aio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aio.c b/aio.c index c89f1e95c1..734d2cfa0b 100644 --- a/aio.c +++ b/aio.c @@ -122,7 +122,7 @@ bool aio_wait(AioContext *ctx) * Otherwise, if there are no AIO requests, qemu_aio_wait() would * wait indefinitely. */ - if (node->io_flush) { + if (!node->deleted && node->io_flush) { if (node->io_flush(node->opaque) == 0) { continue; } From 7c0628b20e7c56b7e04abb8b5f8d7da3f7cb87e8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 24 Sep 2012 14:37:53 +0200 Subject: [PATCH 1309/2270] aio: add non-blocking variant of aio_wait This will be used when polling the GSource attached to an AioContext. Reviewed-by: Anthony Liguori Signed-off-by: Paolo Bonzini --- aio.c | 20 +++++++++++++++----- async.c | 2 +- main-loop.c | 2 +- qemu-aio.h | 21 +++++++++++++++------ 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/aio.c b/aio.c index 734d2cfa0b..1d5e0c62ce 100644 --- a/aio.c +++ b/aio.c @@ -93,13 +93,16 @@ void aio_set_event_notifier(AioContext *ctx, (AioFlushHandler *)io_flush, notifier); } -bool aio_wait(AioContext *ctx) +bool aio_poll(AioContext *ctx, bool blocking) { + static struct timeval tv0; AioHandler *node; fd_set rdfds, wrfds; int max_fd = -1; int ret; - bool busy; + bool busy, progress; + + progress = false; /* * If there are callbacks left that have been queued, we need to call then. @@ -107,6 +110,11 @@ bool aio_wait(AioContext *ctx) * does not need a complete flush (as is the case for qemu_aio_wait loops). */ if (aio_bh_poll(ctx)) { + blocking = false; + progress = true; + } + + if (progress && !blocking) { return true; } @@ -142,11 +150,11 @@ bool aio_wait(AioContext *ctx) /* No AIO operations? Get us out of here */ if (!busy) { - return false; + return progress; } /* wait until next event */ - ret = select(max_fd, &rdfds, &wrfds, NULL, NULL); + ret = select(max_fd, &rdfds, &wrfds, NULL, blocking ? NULL : &tv0); /* if we have any readable fds, dispatch event */ if (ret > 0) { @@ -161,11 +169,13 @@ bool aio_wait(AioContext *ctx) if (!node->deleted && FD_ISSET(node->fd, &rdfds) && node->io_read) { + progress = true; node->io_read(node->opaque); } if (!node->deleted && FD_ISSET(node->fd, &wrfds) && node->io_write) { + progress = true; node->io_write(node->opaque); } @@ -181,5 +191,5 @@ bool aio_wait(AioContext *ctx) } } - return true; + return progress; } diff --git a/async.c b/async.c index c99db79ac7..513bdd7aa2 100644 --- a/async.c +++ b/async.c @@ -144,5 +144,5 @@ AioContext *aio_context_new(void) void aio_flush(AioContext *ctx) { - while (aio_wait(ctx)); + while (aio_poll(ctx, true)); } diff --git a/main-loop.c b/main-loop.c index 8f0117e7aa..1fdc3bdf2e 100644 --- a/main-loop.c +++ b/main-loop.c @@ -534,7 +534,7 @@ void qemu_aio_flush(void) bool qemu_aio_wait(void) { - return aio_wait(qemu_aio_context); + return aio_poll(qemu_aio_context, true); } void qemu_aio_set_fd_handler(int fd, diff --git a/qemu-aio.h b/qemu-aio.h index f8a93d8fb9..f19201e7ca 100644 --- a/qemu-aio.h +++ b/qemu-aio.h @@ -133,13 +133,22 @@ void qemu_bh_delete(QEMUBH *bh); * outstanding AIO operations have been completed or cancelled. */ void aio_flush(AioContext *ctx); -/* Wait for a single AIO completion to occur. This function will wait - * until a single AIO event has completed and it will ensure something - * has moved before returning. This can issue new pending aio as - * result of executing I/O completion or bh callbacks. +/* Progress in completing AIO work to occur. This can issue new pending + * aio as a result of executing I/O completion or bh callbacks. * - * Return whether there is still any pending AIO operation. */ -bool aio_wait(AioContext *ctx); + * If there is no pending AIO operation or completion (bottom half), + * return false. If there are pending bottom halves, return true. + * + * If there are no pending bottom halves, but there are pending AIO + * operations, it may not be possible to make any progress without + * blocking. If @blocking is true, this function will wait until one + * or more AIO events have completed, to ensure something has moved + * before returning. + * + * If @blocking is false, this function will also return false if the + * function cannot make any progress without blocking. + */ +bool aio_poll(AioContext *ctx, bool blocking); #ifdef CONFIG_POSIX /* Returns 1 if there are still outstanding AIO requests; 0 otherwise */ From cd9ba1ebcf0439457f22b75b38533f6634f23c5f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 24 Sep 2012 14:57:22 +0200 Subject: [PATCH 1310/2270] aio: prepare for introducing GSource-based dispatch This adds a GPollFD to each AioHandler. It will then be possible to attach these GPollFDs to a GSource, and from there to the main loop. aio_wait examines the GPollFDs and avoids calling select() if any is set (similar to what it does if bottom halves are available). Signed-off-by: Paolo Bonzini --- aio.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++-------- qemu-aio.h | 7 ++++ 2 files changed, 87 insertions(+), 13 deletions(-) diff --git a/aio.c b/aio.c index 1d5e0c62ce..44247224e2 100644 --- a/aio.c +++ b/aio.c @@ -20,7 +20,7 @@ struct AioHandler { - int fd; + GPollFD pfd; IOHandler *io_read; IOHandler *io_write; AioFlushHandler *io_flush; @@ -34,7 +34,7 @@ static AioHandler *find_aio_handler(AioContext *ctx, int fd) AioHandler *node; QLIST_FOREACH(node, &ctx->aio_handlers, node) { - if (node->fd == fd) + if (node->pfd.fd == fd) if (!node->deleted) return node; } @@ -57,9 +57,10 @@ void aio_set_fd_handler(AioContext *ctx, if (!io_read && !io_write) { if (node) { /* If the lock is held, just mark the node as deleted */ - if (ctx->walking_handlers) + if (ctx->walking_handlers) { node->deleted = 1; - else { + node->pfd.revents = 0; + } else { /* Otherwise, delete it for real. We can't just mark it as * deleted because deleted nodes are only cleaned up after * releasing the walking_handlers lock. @@ -72,7 +73,7 @@ void aio_set_fd_handler(AioContext *ctx, if (node == NULL) { /* Alloc and insert if it's not already there */ node = g_malloc0(sizeof(AioHandler)); - node->fd = fd; + node->pfd.fd = fd; QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); } /* Update handler with latest information */ @@ -80,6 +81,9 @@ void aio_set_fd_handler(AioContext *ctx, node->io_write = io_write; node->io_flush = io_flush; node->opaque = opaque; + + node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP : 0); + node->pfd.events |= (io_write ? G_IO_OUT : 0); } } @@ -93,6 +97,32 @@ void aio_set_event_notifier(AioContext *ctx, (AioFlushHandler *)io_flush, notifier); } +bool aio_pending(AioContext *ctx) +{ + AioHandler *node; + + QLIST_FOREACH(node, &ctx->aio_handlers, node) { + int revents; + + /* + * FIXME: right now we cannot get G_IO_HUP and G_IO_ERR because + * main-loop.c is still select based (due to the slirp legacy). + * If main-loop.c ever switches to poll, G_IO_ERR should be + * tested too. Dispatching G_IO_ERR to both handlers should be + * okay, since handlers need to be ready for spurious wakeups. + */ + revents = node->pfd.revents & node->pfd.events; + if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) { + return true; + } + if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) { + return true; + } + } + + return false; +} + bool aio_poll(AioContext *ctx, bool blocking) { static struct timeval tv0; @@ -114,6 +144,43 @@ bool aio_poll(AioContext *ctx, bool blocking) progress = true; } + /* + * Then dispatch any pending callbacks from the GSource. + * + * We have to walk very carefully in case qemu_aio_set_fd_handler is + * called while we're walking. + */ + node = QLIST_FIRST(&ctx->aio_handlers); + while (node) { + AioHandler *tmp; + int revents; + + ctx->walking_handlers++; + + revents = node->pfd.revents & node->pfd.events; + node->pfd.revents = 0; + + /* See comment in aio_pending. */ + if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) { + node->io_read(node->opaque); + progress = true; + } + if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) { + node->io_write(node->opaque); + progress = true; + } + + tmp = node; + node = QLIST_NEXT(node, node); + + ctx->walking_handlers--; + + if (!ctx->walking_handlers && tmp->deleted) { + QLIST_REMOVE(tmp, node); + g_free(tmp); + } + } + if (progress && !blocking) { return true; } @@ -137,12 +204,12 @@ bool aio_poll(AioContext *ctx, bool blocking) busy = true; } if (!node->deleted && node->io_read) { - FD_SET(node->fd, &rdfds); - max_fd = MAX(max_fd, node->fd + 1); + FD_SET(node->pfd.fd, &rdfds); + max_fd = MAX(max_fd, node->pfd.fd + 1); } if (!node->deleted && node->io_write) { - FD_SET(node->fd, &wrfds); - max_fd = MAX(max_fd, node->fd + 1); + FD_SET(node->pfd.fd, &wrfds); + max_fd = MAX(max_fd, node->pfd.fd + 1); } } @@ -167,16 +234,16 @@ bool aio_poll(AioContext *ctx, bool blocking) ctx->walking_handlers++; if (!node->deleted && - FD_ISSET(node->fd, &rdfds) && + FD_ISSET(node->pfd.fd, &rdfds) && node->io_read) { - progress = true; node->io_read(node->opaque); + progress = true; } if (!node->deleted && - FD_ISSET(node->fd, &wrfds) && + FD_ISSET(node->pfd.fd, &wrfds) && node->io_write) { - progress = true; node->io_write(node->opaque); + progress = true; } tmp = node; diff --git a/qemu-aio.h b/qemu-aio.h index f19201e7ca..ac248962fe 100644 --- a/qemu-aio.h +++ b/qemu-aio.h @@ -133,6 +133,13 @@ void qemu_bh_delete(QEMUBH *bh); * outstanding AIO operations have been completed or cancelled. */ void aio_flush(AioContext *ctx); +/* Return whether there are any pending callbacks from the GSource + * attached to the AioContext. + * + * This is used internally in the implementation of the GSource. + */ +bool aio_pending(AioContext *ctx); + /* Progress in completing AIO work to occur. This can issue new pending * aio as a result of executing I/O completion or bh callbacks. * From f42b22077bc63a482d7a8755b54e33475ab78541 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 9 Jun 2012 04:01:51 +0200 Subject: [PATCH 1311/2270] aio: add Win32 implementation The Win32 implementation will only accept EventNotifiers, thus a few drivers are disabled under Windows. EventNotifiers are a good match for the GSource implementation, too, because the Win32 port of glib allows to place their HANDLEs in a GPollFD. Signed-off-by: Paolo Bonzini --- Makefile.objs | 6 +- aio.c => aio-posix.c | 0 aio-win32.c | 209 +++++++++++++++++++++++++++++++++++++++++++ block/Makefile.objs | 6 +- main-loop.c | 2 +- 5 files changed, 218 insertions(+), 5 deletions(-) rename aio.c => aio-posix.c (100%) create mode 100644 aio-win32.c diff --git a/Makefile.objs b/Makefile.objs index 98046fc64a..a8ade04c02 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -42,12 +42,12 @@ coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o # block-obj-y is code used by both qemu system emulation and qemu-img block-obj-y = iov.o cache-utils.o qemu-option.o module.o async.o -block-obj-y += nbd.o block.o blockjob.o aio.o aes.o qemu-config.o +block-obj-y += nbd.o block.o blockjob.o aes.o qemu-config.o block-obj-y += qemu-progress.o qemu-sockets.o uri.o notify.o block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y) block-obj-$(CONFIG_POSIX) += posix-aio-compat.o -block-obj-$(CONFIG_POSIX) += event_notifier-posix.o -block-obj-$(CONFIG_WIN32) += event_notifier-win32.o +block-obj-$(CONFIG_POSIX) += event_notifier-posix.o aio-posix.o +block-obj-$(CONFIG_WIN32) += event_notifier-win32.o aio-win32.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o block-obj-y += block/ block-obj-y += $(qapi-obj-y) qapi-types.o qapi-visit.o diff --git a/aio.c b/aio-posix.c similarity index 100% rename from aio.c rename to aio-posix.c diff --git a/aio-win32.c b/aio-win32.c new file mode 100644 index 0000000000..9881fdbca7 --- /dev/null +++ b/aio-win32.c @@ -0,0 +1,209 @@ +/* + * QEMU aio implementation + * + * Copyright IBM Corp., 2008 + * Copyright Red Hat Inc., 2012 + * + * Authors: + * Anthony Liguori + * Paolo Bonzini + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ + +#include "qemu-common.h" +#include "block.h" +#include "qemu-queue.h" +#include "qemu_socket.h" + +struct AioHandler { + EventNotifier *e; + EventNotifierHandler *io_notify; + AioFlushEventNotifierHandler *io_flush; + GPollFD pfd; + int deleted; + QLIST_ENTRY(AioHandler) node; +}; + +void aio_set_event_notifier(AioContext *ctx, + EventNotifier *e, + EventNotifierHandler *io_notify, + AioFlushEventNotifierHandler *io_flush) +{ + AioHandler *node; + + QLIST_FOREACH(node, &ctx->aio_handlers, node) { + if (node->e == e && !node->deleted) { + break; + } + } + + /* Are we deleting the fd handler? */ + if (!io_notify) { + if (node) { + /* If the lock is held, just mark the node as deleted */ + if (ctx->walking_handlers) { + node->deleted = 1; + node->pfd.revents = 0; + } else { + /* Otherwise, delete it for real. We can't just mark it as + * deleted because deleted nodes are only cleaned up after + * releasing the walking_handlers lock. + */ + QLIST_REMOVE(node, node); + g_free(node); + } + } + } else { + if (node == NULL) { + /* Alloc and insert if it's not already there */ + node = g_malloc0(sizeof(AioHandler)); + node->e = e; + node->pfd.fd = (uintptr_t)event_notifier_get_handle(e); + node->pfd.events = G_IO_IN; + QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); + } + /* Update handler with latest information */ + node->io_notify = io_notify; + node->io_flush = io_flush; + } +} + +bool aio_pending(AioContext *ctx) +{ + AioHandler *node; + + QLIST_FOREACH(node, &ctx->aio_handlers, node) { + if (node->pfd.revents && node->io_notify) { + return true; + } + } + + return false; +} + +bool aio_poll(AioContext *ctx, bool blocking) +{ + AioHandler *node; + HANDLE events[MAXIMUM_WAIT_OBJECTS + 1]; + bool busy, progress; + int count; + + progress = false; + + /* + * If there are callbacks left that have been queued, we need to call then. + * Do not call select in this case, because it is possible that the caller + * does not need a complete flush (as is the case for qemu_aio_wait loops). + */ + if (aio_bh_poll(ctx)) { + blocking = false; + progress = true; + } + + /* + * Then dispatch any pending callbacks from the GSource. + * + * We have to walk very carefully in case qemu_aio_set_fd_handler is + * called while we're walking. + */ + node = QLIST_FIRST(&ctx->aio_handlers); + while (node) { + AioHandler *tmp; + + ctx->walking_handlers++; + + if (node->pfd.revents && node->io_notify) { + node->pfd.revents = 0; + node->io_notify(node->e); + progress = true; + } + + tmp = node; + node = QLIST_NEXT(node, node); + + ctx->walking_handlers--; + + if (!ctx->walking_handlers && tmp->deleted) { + QLIST_REMOVE(tmp, node); + g_free(tmp); + } + } + + if (progress && !blocking) { + return true; + } + + ctx->walking_handlers++; + + /* fill fd sets */ + busy = false; + count = 0; + QLIST_FOREACH(node, &ctx->aio_handlers, node) { + /* If there aren't pending AIO operations, don't invoke callbacks. + * Otherwise, if there are no AIO requests, qemu_aio_wait() would + * wait indefinitely. + */ + if (!node->deleted && node->io_flush) { + if (node->io_flush(node->e) == 0) { + continue; + } + busy = true; + } + if (!node->deleted && node->io_notify) { + events[count++] = event_notifier_get_handle(node->e); + } + } + + ctx->walking_handlers--; + + /* No AIO operations? Get us out of here */ + if (!busy) { + return progress; + } + + /* wait until next event */ + for (;;) { + int timeout = blocking ? INFINITE : 0; + int ret = WaitForMultipleObjects(count, events, FALSE, timeout); + + /* if we have any signaled events, dispatch event */ + if ((DWORD) (ret - WAIT_OBJECT_0) >= count) { + break; + } + + blocking = false; + + /* we have to walk very carefully in case + * qemu_aio_set_fd_handler is called while we're walking */ + node = QLIST_FIRST(&ctx->aio_handlers); + while (node) { + AioHandler *tmp; + + ctx->walking_handlers++; + + if (!node->deleted && + event_notifier_get_handle(node->e) == events[ret - WAIT_OBJECT_0] && + node->io_notify) { + node->io_notify(node->e); + progress = true; + } + + tmp = node; + node = QLIST_NEXT(node, node); + + ctx->walking_handlers--; + + if (!ctx->walking_handlers && tmp->deleted) { + QLIST_REMOVE(tmp, node); + g_free(tmp); + } + } + } + + return progress; +} diff --git a/block/Makefile.objs b/block/Makefile.objs index 554f429d05..684765bf63 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -2,13 +2,17 @@ block-obj-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o block-obj-y += qed-check.o -block-obj-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o +block-obj-y += parallels.o blkdebug.o blkverify.o block-obj-$(CONFIG_WIN32) += raw-win32.o block-obj-$(CONFIG_POSIX) += raw-posix.o + +ifeq ($(CONFIG_POSIX),y) +block-obj-y += nbd.o sheepdog.o block-obj-$(CONFIG_LIBISCSI) += iscsi.o block-obj-$(CONFIG_CURL) += curl.o block-obj-$(CONFIG_RBD) += rbd.o block-obj-$(CONFIG_GLUSTERFS) += gluster.o +endif common-obj-y += stream.o common-obj-y += commit.o diff --git a/main-loop.c b/main-loop.c index 1fdc3bdf2e..a86c275149 100644 --- a/main-loop.c +++ b/main-loop.c @@ -537,6 +537,7 @@ bool qemu_aio_wait(void) return aio_poll(qemu_aio_context, true); } +#ifdef CONFIG_POSIX void qemu_aio_set_fd_handler(int fd, IOHandler *io_read, IOHandler *io_write, @@ -549,7 +550,6 @@ void qemu_aio_set_fd_handler(int fd, qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque); } -#ifdef CONFIG_POSIX void qemu_aio_set_event_notifier(EventNotifier *notifier, EventNotifierHandler *io_read, AioFlushEventNotifierHandler *io_flush) From e3713e001fb7d4d82f6de82800c1463e758e4289 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 24 Sep 2012 14:57:41 +0200 Subject: [PATCH 1312/2270] aio: make AioContexts GSources This lets AioContexts be used (optionally) with a glib main loop. Signed-off-by: Paolo Bonzini --- aio-posix.c | 4 ++++ aio-win32.c | 4 ++++ async.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++- qemu-aio.h | 23 +++++++++++++++++++ 4 files changed, 95 insertions(+), 1 deletion(-) diff --git a/aio-posix.c b/aio-posix.c index 44247224e2..65b26073f0 100644 --- a/aio-posix.c +++ b/aio-posix.c @@ -56,6 +56,8 @@ void aio_set_fd_handler(AioContext *ctx, /* Are we deleting the fd handler? */ if (!io_read && !io_write) { if (node) { + g_source_remove_poll(&ctx->source, &node->pfd); + /* If the lock is held, just mark the node as deleted */ if (ctx->walking_handlers) { node->deleted = 1; @@ -75,6 +77,8 @@ void aio_set_fd_handler(AioContext *ctx, node = g_malloc0(sizeof(AioHandler)); node->pfd.fd = fd; QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); + + g_source_add_poll(&ctx->source, &node->pfd); } /* Update handler with latest information */ node->io_read = io_read; diff --git a/aio-win32.c b/aio-win32.c index 9881fdbca7..e460bd848a 100644 --- a/aio-win32.c +++ b/aio-win32.c @@ -45,6 +45,8 @@ void aio_set_event_notifier(AioContext *ctx, /* Are we deleting the fd handler? */ if (!io_notify) { if (node) { + g_source_remove_poll(&ctx->source, &node->pfd); + /* If the lock is held, just mark the node as deleted */ if (ctx->walking_handlers) { node->deleted = 1; @@ -66,6 +68,8 @@ void aio_set_event_notifier(AioContext *ctx, node->pfd.fd = (uintptr_t)event_notifier_get_handle(e); node->pfd.events = G_IO_IN; QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); + + g_source_add_poll(&ctx->source, &node->pfd); } /* Update handler with latest information */ node->io_notify = io_notify; diff --git a/async.c b/async.c index 513bdd7aa2..4ffdd986f1 100644 --- a/async.c +++ b/async.c @@ -136,10 +136,73 @@ void aio_bh_update_timeout(AioContext *ctx, uint32_t *timeout) } } +static gboolean +aio_ctx_prepare(GSource *source, gint *timeout) +{ + AioContext *ctx = (AioContext *) source; + uint32_t wait = -1; + aio_bh_update_timeout(ctx, &wait); + + if (wait != -1) { + *timeout = MIN(*timeout, wait); + return wait == 0; + } + + return false; +} + +static gboolean +aio_ctx_check(GSource *source) +{ + AioContext *ctx = (AioContext *) source; + QEMUBH *bh; + + for (bh = ctx->first_bh; bh; bh = bh->next) { + if (!bh->deleted && bh->scheduled) { + return true; + } + } + return aio_pending(ctx); +} + +static gboolean +aio_ctx_dispatch(GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + AioContext *ctx = (AioContext *) source; + + assert(callback == NULL); + aio_poll(ctx, false); + return true; +} + +static GSourceFuncs aio_source_funcs = { + aio_ctx_prepare, + aio_ctx_check, + aio_ctx_dispatch, + NULL +}; + +GSource *aio_get_g_source(AioContext *ctx) +{ + g_source_ref(&ctx->source); + return &ctx->source; +} AioContext *aio_context_new(void) { - return g_new0(AioContext, 1); + return (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext)); +} + +void aio_context_ref(AioContext *ctx) +{ + g_source_ref(&ctx->source); +} + +void aio_context_unref(AioContext *ctx) +{ + g_source_unref(&ctx->source); } void aio_flush(AioContext *ctx) diff --git a/qemu-aio.h b/qemu-aio.h index ac248962fe..aedf66cfa1 100644 --- a/qemu-aio.h +++ b/qemu-aio.h @@ -44,6 +44,8 @@ typedef void QEMUBHFunc(void *opaque); typedef void IOHandler(void *opaque); typedef struct AioContext { + GSource source; + /* The list of registered AIO handlers */ QLIST_HEAD(, AioHandler) aio_handlers; @@ -74,6 +76,22 @@ typedef int (AioFlushEventNotifierHandler)(EventNotifier *e); */ AioContext *aio_context_new(void); +/** + * aio_context_ref: + * @ctx: The AioContext to operate on. + * + * Add a reference to an AioContext. + */ +void aio_context_ref(AioContext *ctx); + +/** + * aio_context_unref: + * @ctx: The AioContext to operate on. + * + * Drop a reference to an AioContext. + */ +void aio_context_unref(AioContext *ctx); + /** * aio_bh_new: Allocate a new bottom half structure. * @@ -188,6 +206,11 @@ void aio_set_event_notifier(AioContext *ctx, EventNotifierHandler *io_read, AioFlushEventNotifierHandler *io_flush); +/* Return a GSource that lets the main loop poll the file descriptors attached + * to this AioContext. + */ +GSource *aio_get_g_source(AioContext *ctx); + /* Functions to operate on the main QEMU AioContext. */ void qemu_aio_flush(void); From 2f4dc3c1b2a453a8255d9b97c7cb87860123e495 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 24 Sep 2012 18:44:14 +0200 Subject: [PATCH 1313/2270] aio: add aio_notify With this change async.c does not rely anymore on any service from main-loop.c, i.e. it is completely self-contained. Reviewed-by: Anthony Liguori Signed-off-by: Paolo Bonzini --- async.c | 30 ++++++++++++++++++++++++++---- qemu-aio.h | 18 ++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/async.c b/async.c index 4ffdd986f1..564526f57f 100644 --- a/async.c +++ b/async.c @@ -30,6 +30,7 @@ /* bottom halves (can be seen as timers which expire ASAP) */ struct QEMUBH { + AioContext *ctx; QEMUBHFunc *cb; void *opaque; QEMUBH *next; @@ -42,6 +43,7 @@ QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque) { QEMUBH *bh; bh = g_malloc0(sizeof(QEMUBH)); + bh->ctx = ctx; bh->cb = cb; bh->opaque = opaque; bh->next = ctx->first_bh; @@ -101,8 +103,7 @@ void qemu_bh_schedule(QEMUBH *bh) return; bh->scheduled = 1; bh->idle = 0; - /* stop the currently executing CPU to execute the BH ASAP */ - qemu_notify_event(); + aio_notify(bh->ctx); } void qemu_bh_cancel(QEMUBH *bh) @@ -177,11 +178,20 @@ aio_ctx_dispatch(GSource *source, return true; } +static void +aio_ctx_finalize(GSource *source) +{ + AioContext *ctx = (AioContext *) source; + + aio_set_event_notifier(ctx, &ctx->notifier, NULL, NULL); + event_notifier_cleanup(&ctx->notifier); +} + static GSourceFuncs aio_source_funcs = { aio_ctx_prepare, aio_ctx_check, aio_ctx_dispatch, - NULL + aio_ctx_finalize }; GSource *aio_get_g_source(AioContext *ctx) @@ -190,9 +200,21 @@ GSource *aio_get_g_source(AioContext *ctx) return &ctx->source; } +void aio_notify(AioContext *ctx) +{ + event_notifier_set(&ctx->notifier); +} + AioContext *aio_context_new(void) { - return (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext)); + AioContext *ctx; + ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext)); + event_notifier_init(&ctx->notifier, false); + aio_set_event_notifier(ctx, &ctx->notifier, + (EventNotifierHandler *) + event_notifier_test_and_clear, NULL); + + return ctx; } void aio_context_ref(AioContext *ctx) diff --git a/qemu-aio.h b/qemu-aio.h index aedf66cfa1..2354617ed1 100644 --- a/qemu-aio.h +++ b/qemu-aio.h @@ -62,6 +62,9 @@ typedef struct AioContext { * no callbacks are removed while we're walking and dispatching callbacks. */ int walking_bh; + + /* Used for aio_notify. */ + EventNotifier notifier; } AioContext; /* Returns 1 if there are still outstanding AIO requests; 0 otherwise */ @@ -101,6 +104,21 @@ void aio_context_unref(AioContext *ctx); */ QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque); +/** + * aio_notify: Force processing of pending events. + * + * Similar to signaling a condition variable, aio_notify forces + * aio_wait to exit, so that the next call will re-examine pending events. + * The caller of aio_notify will usually call aio_wait again very soon, + * or go through another iteration of the GLib main loop. Hence, aio_notify + * also has the side effect of recalculating the sets of file descriptors + * that the main loop waits for. + * + * Calling aio_notify is rarely necessary, because for example scheduling + * a bottom half calls it already. + */ +void aio_notify(AioContext *ctx); + /** * aio_bh_poll: Poll bottom halves for an AioContext. * From 7ed2b24ce17f8fb7e36e4e8d113f2a30cbea142f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 25 Sep 2012 10:22:39 +0200 Subject: [PATCH 1314/2270] aio: call aio_notify after setting I/O handlers In the current code, this is done by qemu_set_fd_handler2, which is called by qemu_aio_set_fd_handler. We need to keep the same behavior even after removing the call to qemu_set_fd_handler2. Reviewed-by: Anthony Liguori Signed-off-by: Paolo Bonzini --- aio-posix.c | 2 ++ aio-win32.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/aio-posix.c b/aio-posix.c index 65b26073f0..05cc84e121 100644 --- a/aio-posix.c +++ b/aio-posix.c @@ -89,6 +89,8 @@ void aio_set_fd_handler(AioContext *ctx, node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP : 0); node->pfd.events |= (io_write ? G_IO_OUT : 0); } + + aio_notify(ctx); } void aio_set_event_notifier(AioContext *ctx, diff --git a/aio-win32.c b/aio-win32.c index e460bd848a..a84eb71246 100644 --- a/aio-win32.c +++ b/aio-win32.c @@ -75,6 +75,8 @@ void aio_set_event_notifier(AioContext *ctx, node->io_notify = io_notify; node->io_flush = io_flush; } + + aio_notify(ctx); } bool aio_pending(AioContext *ctx) From 82cbbdc6a0958b49c77639a60906e30d02e6bb7b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 24 Sep 2012 15:07:08 +0200 Subject: [PATCH 1315/2270] main-loop: use GSource to poll AIO file descriptors This lets us remove the hooks for the main loop in async.c. Reviewed-by: Anthony Liguori Signed-off-by: Paolo Bonzini --- main-loop.c | 23 ++++++----------------- main-loop.h | 1 - 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/main-loop.c b/main-loop.c index a86c275149..365c9d3261 100644 --- a/main-loop.c +++ b/main-loop.c @@ -205,6 +205,7 @@ static AioContext *qemu_aio_context; int qemu_init_main_loop(void) { int ret; + GSource *src; init_clocks(); init_timer_alarm(); @@ -222,6 +223,9 @@ int qemu_init_main_loop(void) } qemu_aio_context = aio_context_new(); + src = aio_get_g_source(qemu_aio_context); + g_source_attach(src, NULL); + g_source_unref(src); return 0; } @@ -484,8 +488,6 @@ int main_loop_wait(int nonblocking) if (nonblocking) { timeout = 0; - } else { - aio_bh_update_timeout(qemu_aio_context, &timeout); } /* poll any events */ @@ -508,10 +510,6 @@ int main_loop_wait(int nonblocking) qemu_run_all_timers(); - /* Check bottom-halves last in case any of the earlier events triggered - them. */ - qemu_bh_poll(); - return ret; } @@ -522,11 +520,6 @@ QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque) return aio_bh_new(qemu_aio_context, cb, opaque); } -int qemu_bh_poll(void) -{ - return aio_bh_poll(qemu_aio_context); -} - void qemu_aio_flush(void) { aio_flush(qemu_aio_context); @@ -546,16 +539,12 @@ void qemu_aio_set_fd_handler(int fd, { aio_set_fd_handler(qemu_aio_context, fd, io_read, io_write, io_flush, opaque); - - qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque); } +#endif void qemu_aio_set_event_notifier(EventNotifier *notifier, EventNotifierHandler *io_read, AioFlushEventNotifierHandler *io_flush) { - qemu_aio_set_fd_handler(event_notifier_get_fd(notifier), - (IOHandler *)io_read, NULL, - (AioFlushHandler *)io_flush, notifier); + aio_set_event_notifier(qemu_aio_context, notifier, io_read, io_flush); } -#endif diff --git a/main-loop.h b/main-loop.h index 1d1a56b858..326c74269c 100644 --- a/main-loop.h +++ b/main-loop.h @@ -302,6 +302,5 @@ void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque); void qemu_bh_schedule_idle(QEMUBH *bh); -int qemu_bh_poll(void); #endif From 4c8d0d27676778febad3802a95218d5ceaca171e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 24 May 2010 17:27:14 +0200 Subject: [PATCH 1316/2270] main-loop: use aio_notify for qemu_notify_event Reviewed-by: Anthony Liguori Signed-off-by: Paolo Bonzini --- main-loop.c | 110 +++++----------------------------------------------- 1 file changed, 10 insertions(+), 100 deletions(-) diff --git a/main-loop.c b/main-loop.c index 365c9d3261..e43c7c8e8d 100644 --- a/main-loop.c +++ b/main-loop.c @@ -32,70 +32,6 @@ #include "compatfd.h" -static int io_thread_fd = -1; - -void qemu_notify_event(void) -{ - /* Write 8 bytes to be compatible with eventfd. */ - static const uint64_t val = 1; - ssize_t ret; - - if (io_thread_fd == -1) { - return; - } - do { - ret = write(io_thread_fd, &val, sizeof(val)); - } while (ret < 0 && errno == EINTR); - - /* EAGAIN is fine, a read must be pending. */ - if (ret < 0 && errno != EAGAIN) { - fprintf(stderr, "qemu_notify_event: write() failed: %s\n", - strerror(errno)); - exit(1); - } -} - -static void qemu_event_read(void *opaque) -{ - int fd = (intptr_t)opaque; - ssize_t len; - char buffer[512]; - - /* Drain the notify pipe. For eventfd, only 8 bytes will be read. */ - do { - len = read(fd, buffer, sizeof(buffer)); - } while ((len == -1 && errno == EINTR) || len == sizeof(buffer)); -} - -static int qemu_event_init(void) -{ - int err; - int fds[2]; - - err = qemu_eventfd(fds); - if (err == -1) { - return -errno; - } - err = fcntl_setfl(fds[0], O_NONBLOCK); - if (err < 0) { - goto fail; - } - err = fcntl_setfl(fds[1], O_NONBLOCK); - if (err < 0) { - goto fail; - } - qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL, - (void *)(intptr_t)fds[0]); - - io_thread_fd = fds[1]; - return 0; - -fail: - close(fds[0]); - close(fds[1]); - return err; -} - /* If we have signalfd, we mask out the signals we want to handle and then * use signalfd to listen for them. We rely on whatever the current signal * handler is to dispatch the signals when we receive them. @@ -165,35 +101,6 @@ static int qemu_signal_init(void) #else /* _WIN32 */ -static HANDLE qemu_event_handle = NULL; - -static void dummy_event_handler(void *opaque) -{ -} - -static int qemu_event_init(void) -{ - qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL); - if (!qemu_event_handle) { - fprintf(stderr, "Failed CreateEvent: %ld\n", GetLastError()); - return -1; - } - qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL); - return 0; -} - -void qemu_notify_event(void) -{ - if (!qemu_event_handle) { - return; - } - if (!SetEvent(qemu_event_handle)) { - fprintf(stderr, "qemu_notify_event: SetEvent failed: %ld\n", - GetLastError()); - exit(1); - } -} - static int qemu_signal_init(void) { return 0; @@ -202,6 +109,14 @@ static int qemu_signal_init(void) static AioContext *qemu_aio_context; +void qemu_notify_event(void) +{ + if (!qemu_aio_context) { + return; + } + aio_notify(qemu_aio_context); +} + int qemu_init_main_loop(void) { int ret; @@ -216,12 +131,6 @@ int qemu_init_main_loop(void) return ret; } - /* Note eventfd must be drained before signalfd handlers run */ - ret = qemu_event_init(); - if (ret) { - return ret; - } - qemu_aio_context = aio_context_new(); src = aio_get_g_source(qemu_aio_context); g_source_attach(src, NULL); @@ -411,7 +320,8 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) void qemu_fd_register(int fd) { - WSAEventSelect(fd, qemu_event_handle, FD_READ | FD_ACCEPT | FD_CLOSE | + WSAEventSelect(fd, event_notifier_get_handle(&qemu_aio_context->notifier), + FD_READ | FD_ACCEPT | FD_CLOSE | FD_CONNECT | FD_WRITE | FD_OOB); } From 22bfa75eafc21522afbb265091faa9cc0649e9fb Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 24 Sep 2012 15:11:48 +0200 Subject: [PATCH 1317/2270] aio: clean up now-unused functions Some cleanups can now be made, now that the main loop does not anymore need hooks into the bottom half code. Reviewed-by: Anthony Liguori Signed-off-by: Paolo Bonzini --- async.c | 23 +++++++---------------- oslib-posix.c | 31 ------------------------------- qemu-aio.h | 1 - qemu-common.h | 1 - 4 files changed, 7 insertions(+), 49 deletions(-) diff --git a/async.c b/async.c index 564526f57f..04f9dcbb4d 100644 --- a/async.c +++ b/async.c @@ -117,16 +117,20 @@ void qemu_bh_delete(QEMUBH *bh) bh->deleted = 1; } -void aio_bh_update_timeout(AioContext *ctx, uint32_t *timeout) +static gboolean +aio_ctx_prepare(GSource *source, gint *timeout) { + AioContext *ctx = (AioContext *) source; QEMUBH *bh; + bool scheduled = false; for (bh = ctx->first_bh; bh; bh = bh->next) { if (!bh->deleted && bh->scheduled) { + scheduled = true; if (bh->idle) { /* idle bottom halves will be polled at least * every 10ms */ - *timeout = MIN(10, *timeout); + *timeout = 10; } else { /* non-idle bottom halves will be executed * immediately */ @@ -135,21 +139,8 @@ void aio_bh_update_timeout(AioContext *ctx, uint32_t *timeout) } } } -} -static gboolean -aio_ctx_prepare(GSource *source, gint *timeout) -{ - AioContext *ctx = (AioContext *) source; - uint32_t wait = -1; - aio_bh_update_timeout(ctx, &wait); - - if (wait != -1) { - *timeout = MIN(*timeout, wait); - return wait == 0; - } - - return false; + return scheduled; } static gboolean diff --git a/oslib-posix.c b/oslib-posix.c index dbeb6272b8..9db9c3d8af 100644 --- a/oslib-posix.c +++ b/oslib-posix.c @@ -61,9 +61,6 @@ static int running_on_valgrind = -1; #ifdef CONFIG_LINUX #include #endif -#ifdef CONFIG_EVENTFD -#include -#endif int qemu_get_thread_id(void) { @@ -183,34 +180,6 @@ int qemu_pipe(int pipefd[2]) return ret; } -/* - * Creates an eventfd that looks like a pipe and has EFD_CLOEXEC set. - */ -int qemu_eventfd(int fds[2]) -{ -#ifdef CONFIG_EVENTFD - int ret; - - ret = eventfd(0, 0); - if (ret >= 0) { - fds[0] = ret; - fds[1] = dup(ret); - if (fds[1] == -1) { - close(ret); - return -1; - } - qemu_set_cloexec(ret); - qemu_set_cloexec(fds[1]); - return 0; - } - if (errno != ENOSYS) { - return -1; - } -#endif - - return qemu_pipe(fds); -} - int qemu_utimens(const char *path, const struct timespec *times) { struct timeval tv[2], tv_now; diff --git a/qemu-aio.h b/qemu-aio.h index 2354617ed1..1b7eb6ef5b 100644 --- a/qemu-aio.h +++ b/qemu-aio.h @@ -125,7 +125,6 @@ void aio_notify(AioContext *ctx); * These are internal functions used by the QEMU main loop. */ int aio_bh_poll(AioContext *ctx); -void aio_bh_update_timeout(AioContext *ctx, uint32_t *timeout); /** * qemu_bh_schedule: Schedule a bottom half. diff --git a/qemu-common.h b/qemu-common.h index 24e13ccb5e..c3328d230a 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -218,7 +218,6 @@ ssize_t qemu_recv_full(int fd, void *buf, size_t count, int flags) QEMU_WARN_UNUSED_RESULT; #ifndef _WIN32 -int qemu_eventfd(int pipefd[2]); int qemu_pipe(int pipefd[2]); #endif From c90caf25e2b6945ae13560476a5ecd7992e9f945 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 24 Feb 2012 08:39:02 +0100 Subject: [PATCH 1318/2270] linux-aio: use event notifiers Since linux-aio already uses an eventfd, converting it to use the EventNotifier-based API simplifies the code even though it is not meant to be portable. Reviewed-by: Anthony Liguori Signed-off-by: Paolo Bonzini --- linux-aio.c | 49 +++++++++++++++++++------------------------------ 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/linux-aio.c b/linux-aio.c index f3d8ef33ca..d1afb460c2 100644 --- a/linux-aio.c +++ b/linux-aio.c @@ -11,8 +11,8 @@ #include "qemu-aio.h" #include "qemu-queue.h" #include "block/raw-posix-aio.h" +#include "event_notifier.h" -#include #include /* @@ -38,7 +38,7 @@ struct qemu_laiocb { struct qemu_laio_state { io_context_t ctx; - int efd; + EventNotifier e; int count; }; @@ -77,29 +77,17 @@ static void qemu_laio_process_completion(struct qemu_laio_state *s, qemu_aio_release(laiocb); } -static void qemu_laio_completion_cb(void *opaque) +static void qemu_laio_completion_cb(EventNotifier *e) { - struct qemu_laio_state *s = opaque; + struct qemu_laio_state *s = container_of(e, struct qemu_laio_state, e); - while (1) { + while (event_notifier_test_and_clear(&s->e)) { struct io_event events[MAX_EVENTS]; - uint64_t val; - ssize_t ret; struct timespec ts = { 0 }; int nevents, i; do { - ret = read(s->efd, &val, sizeof(val)); - } while (ret == -1 && errno == EINTR); - - if (ret == -1 && errno == EAGAIN) - break; - - if (ret != 8) - break; - - do { - nevents = io_getevents(s->ctx, val, MAX_EVENTS, events, &ts); + nevents = io_getevents(s->ctx, MAX_EVENTS, MAX_EVENTS, events, &ts); } while (nevents == -EINTR); for (i = 0; i < nevents; i++) { @@ -113,9 +101,9 @@ static void qemu_laio_completion_cb(void *opaque) } } -static int qemu_laio_flush_cb(void *opaque) +static int qemu_laio_flush_cb(EventNotifier *e) { - struct qemu_laio_state *s = opaque; + struct qemu_laio_state *s = container_of(e, struct qemu_laio_state, e); return (s->count > 0) ? 1 : 0; } @@ -147,8 +135,9 @@ static void laio_cancel(BlockDriverAIOCB *blockacb) * We might be able to do this slightly more optimal by removing the * O_NONBLOCK flag. */ - while (laiocb->ret == -EINPROGRESS) - qemu_laio_completion_cb(laiocb->ctx); + while (laiocb->ret == -EINPROGRESS) { + qemu_laio_completion_cb(&laiocb->ctx->e); + } } static AIOPool laio_pool = { @@ -187,7 +176,7 @@ BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, __func__, type); goto out_free_aiocb; } - io_set_eventfd(&laiocb->iocb, s->efd); + io_set_eventfd(&laiocb->iocb, event_notifier_get_fd(&s->e)); s->count++; if (io_submit(s->ctx, 1, &iocbs) < 0) @@ -206,21 +195,21 @@ void *laio_init(void) struct qemu_laio_state *s; s = g_malloc0(sizeof(*s)); - s->efd = eventfd(0, 0); - if (s->efd == -1) + if (event_notifier_init(&s->e, false) < 0) { goto out_free_state; - fcntl(s->efd, F_SETFL, O_NONBLOCK); + } - if (io_setup(MAX_EVENTS, &s->ctx) != 0) + if (io_setup(MAX_EVENTS, &s->ctx) != 0) { goto out_close_efd; + } - qemu_aio_set_fd_handler(s->efd, qemu_laio_completion_cb, NULL, - qemu_laio_flush_cb, s); + qemu_aio_set_event_notifier(&s->e, qemu_laio_completion_cb, + qemu_laio_flush_cb); return s; out_close_efd: - close(s->efd); + event_notifier_cleanup(&s->e); out_free_state: g_free(s); return NULL; From e7d51b3450893dfcef4af4238c48baf2d4b0ed31 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Oct 2012 15:50:20 +1100 Subject: [PATCH 1319/2270] target-sparc: Revert setting cpu_dst to gen_dest_gpr There is some read-after-write error within the OP=2 insns which prevents setting cpu_dst to the real output register. Until this is found and fixed, always write to a temporary first. Cc: Blue Swirl Cc: Aurelien Jarno Signed-off-by: Richard Henderson Tested-by: Aurelien Jarno Signed-off-by: Blue Swirl --- target-sparc/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 4321393688..9e46f1424b 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2633,7 +2633,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 2: /* FPU & Logical Operations */ { unsigned int xop = GET_FIELD(insn, 7, 12); - TCGv cpu_dst = gen_dest_gpr(dc, rd); + TCGv cpu_dst = get_temp_tl(dc); TCGv cpu_tmp0; if (xop == 0x3a) { /* generate trap */ From a1d29d6c1d4002a5c7b19eda61d794f4c22538dd Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sat, 27 Oct 2012 22:19:07 +0100 Subject: [PATCH 1320/2270] configure: use -Wwombat to test whether gcc recognizes -Wno-wombat gcc will silently accept unrecognized -Wno-wombat warning suppression options (it only mentions them if it has to print a compiler warning for some other reason). Since we already run a check for whether gcc recognizes the warning options we use, we can easily make this use the positive sense of the option when checking for support for the suppression option. This doesn't have any effect except that it avoids gcc emitting extra messages about unrecognized command line options when it is printing other warning messages. Signed-off-by: Peter Maydell Reviewed-by: Stefan Weil Reviewed-by: Igor Mitsyanko Signed-off-by: Blue Swirl --- configure | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 3685020ffa..9c6ac875a5 100755 --- a/configure +++ b/configure @@ -1169,7 +1169,11 @@ cat > $TMPC << EOF int main(void) { return 0; } EOF for flag in $gcc_flags; do - if compile_prog "-Werror $flag" "" ; then + # Use the positive sense of the flag when testing for -Wno-wombat + # support (gcc will happily accept the -Wno- form of unknown + # warning options). + optflag="$(echo $flag | sed -e 's/^-Wno-/-W/')" + if compile_prog "-Werror $optflag" "" ; then QEMU_CFLAGS="$QEMU_CFLAGS $flag" fi done From f71d61216ea8eb914ee79459a58dc5343d95ddec Mon Sep 17 00:00:00 2001 From: Catalin Patulea Date: Mon, 29 Oct 2012 14:01:07 -0400 Subject: [PATCH 1321/2270] tests/tcg: fix unused result warnings With i386-linux-user target on x86_64 host, this does not introduce any new test failures. Signed-off-by: Catalin Patulea Signed-off-by: Blue Swirl --- tests/tcg/test-mmap.c | 18 +++++++++++++----- tests/tcg/testthread.c | 11 +++++++++-- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/tests/tcg/test-mmap.c b/tests/tcg/test-mmap.c index c418b67660..3982fa2c72 100644 --- a/tests/tcg/test-mmap.c +++ b/tests/tcg/test-mmap.c @@ -429,6 +429,12 @@ void check_file_fixed_mmaps(void) fprintf (stderr, " passed\n"); } +void checked_write(int fd, const void *buf, size_t count) +{ + ssize_t rc = write(fd, buf, count); + fail_unless(rc == count); +} + int main(int argc, char **argv) { char tempname[] = "/tmp/.cmmapXXXXXX"; @@ -450,13 +456,15 @@ int main(int argc, char **argv) unlink(tempname); /* Fill the file with int's counting from zero and up. */ - for (i = 0; i < (pagesize * 4) / sizeof i; i++) - write (test_fd, &i, sizeof i); + for (i = 0; i < (pagesize * 4) / sizeof i; i++) { + checked_write(test_fd, &i, sizeof i); + } + /* Append a few extra writes to make the file end at non page boundary. */ - write (test_fd, &i, sizeof i); i++; - write (test_fd, &i, sizeof i); i++; - write (test_fd, &i, sizeof i); i++; + checked_write(test_fd, &i, sizeof i); i++; + checked_write(test_fd, &i, sizeof i); i++; + checked_write(test_fd, &i, sizeof i); i++; test_fsize = lseek(test_fd, 0, SEEK_CUR); diff --git a/tests/tcg/testthread.c b/tests/tcg/testthread.c index 27e4825bc6..2679af119a 100644 --- a/tests/tcg/testthread.c +++ b/tests/tcg/testthread.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -8,6 +9,12 @@ #include #include +void checked_write(int fd, const void *buf, size_t count) +{ + ssize_t rc = write(fd, buf, count); + assert(rc == count); +} + void *thread1_func(void *arg) { int i; @@ -15,7 +22,7 @@ void *thread1_func(void *arg) for(i=0;i<10;i++) { snprintf(buf, sizeof(buf), "thread1: %d %s\n", i, (char *)arg); - write(1, buf, strlen(buf)); + checked_write(1, buf, strlen(buf)); usleep(100 * 1000); } return NULL; @@ -27,7 +34,7 @@ void *thread2_func(void *arg) char buf[512]; for(i=0;i<20;i++) { snprintf(buf, sizeof(buf), "thread2: %d %s\n", i, (char *)arg); - write(1, buf, strlen(buf)); + checked_write(1, buf, strlen(buf)); usleep(150 * 1000); } return NULL; From aee0bf7d8d7564f8f2c40e4501695c492b7dd8d1 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 30 Oct 2012 16:04:50 +0200 Subject: [PATCH 1322/2270] tap-win32: stubs to fix win32 build Add missing stubs to win32 to fix link failure. Signed-off-by: Michael S. Tsirkin Reported-by: Paolo Bonzini Signed-off-by: Blue Swirl --- net/tap-win32.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/net/tap-win32.c b/net/tap-win32.c index 22dad3f8fb..8d2d32b1c3 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -752,3 +752,13 @@ struct vhost_net *tap_get_vhost_net(NetClientState *nc) { return NULL; } + +int tap_has_vnet_hdr_len(NetClientState *nc, int len) +{ + return 0; +} + +void tap_set_vnet_hdr_len(NetClientState *nc, int len) +{ + assert(0); +} From 18eb473f892642ae869f77403289167f30de2022 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 2 Oct 2012 17:36:54 +0200 Subject: [PATCH 1323/2270] target-i386: cpu_x86_register(): report error from property setter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Reviewed-by: Eduardo Habkost Signed-off-by: Andreas Färber --- target-i386/cpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index d4f2e65cd9..f3a31212eb 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1427,7 +1427,8 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) env->cpuid_svm_features &= TCG_SVM_FEATURES; } object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error); - if (error_is_set(&error)) { + if (error) { + fprintf(stderr, "%s\n", error_get_pretty(error)); error_free(error); return -1; } From ff287bbdda016b37990be7ed52339750aaa8a5e4 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 2 Oct 2012 17:36:55 +0200 Subject: [PATCH 1324/2270] target-i386: If x86_cpu_realize() failed, report error and do cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- target-i386/helper.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/target-i386/helper.c b/target-i386/helper.c index c5d42c5916..0424ccf6fb 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1243,6 +1243,7 @@ X86CPU *cpu_x86_init(const char *cpu_model) { X86CPU *cpu; CPUX86State *env; + Error *error = NULL; cpu = X86_CPU(object_new(TYPE_X86_CPU)); env = &cpu->env; @@ -1253,8 +1254,12 @@ X86CPU *cpu_x86_init(const char *cpu_model) return NULL; } - x86_cpu_realize(OBJECT(cpu), NULL); - + x86_cpu_realize(OBJECT(cpu), &error); + if (error) { + error_free(error); + object_delete(OBJECT(cpu)); + return NULL; + } return cpu; } From bdeec802170d5dc9f0f8a01235c3488dca3ff83b Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Sat, 13 Oct 2012 22:35:39 +0200 Subject: [PATCH 1325/2270] target-i386: Initialize APIC at CPU level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (L)APIC is a part of cpu [1] so move APIC initialization inside of x86_cpu object. Since cpu_model and override flags currently specify whether APIC should be created or not, APIC creation&initialization is moved into x86_cpu_apic_init() which is called from x86_cpu_realize(). [1] - all x86 cpus have integrated APIC if we overlook existence of i486, and it's more convenient to model after majority of them. Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- hw/pc.c | 56 +++++----------------------------------------- target-i386/cpu.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 51 deletions(-) diff --git a/hw/pc.c b/hw/pc.c index a02b397a24..4aca4986dd 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -71,8 +71,6 @@ #define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3) #define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4) -#define MSI_ADDR_BASE 0xfee00000 - #define E820_NR_ENTRIES 16 struct e820_entry { @@ -849,35 +847,6 @@ DeviceState *cpu_get_current_apic(void) } } -static DeviceState *apic_init(void *env, uint8_t apic_id) -{ - DeviceState *dev; - static int apic_mapped; - - if (kvm_irqchip_in_kernel()) { - dev = qdev_create(NULL, "kvm-apic"); - } else if (xen_enabled()) { - dev = qdev_create(NULL, "xen-apic"); - } else { - dev = qdev_create(NULL, "apic"); - } - - qdev_prop_set_uint8(dev, "id", apic_id); - qdev_prop_set_ptr(dev, "cpu_env", env); - qdev_init_nofail(dev); - - /* XXX: mapping more APICs at the same memory location */ - if (apic_mapped == 0) { - /* NOTE: the APIC is directly connected to the CPU - it is not - on the global memory bus. */ - /* XXX: what if the base changes? */ - sysbus_mmio_map(sysbus_from_qdev(dev), 0, MSI_ADDR_BASE); - apic_mapped = 1; - } - - return dev; -} - void pc_acpi_smi_interrupt(void *opaque, int irq, int level) { CPUX86State *s = opaque; @@ -887,24 +856,6 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } -static X86CPU *pc_new_cpu(const char *cpu_model) -{ - X86CPU *cpu; - CPUX86State *env; - - cpu = cpu_x86_init(cpu_model); - if (cpu == NULL) { - fprintf(stderr, "Unable to find x86 CPU definition\n"); - exit(1); - } - env = &cpu->env; - if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) { - env->apic_state = apic_init(env, env->cpuid_apic_id); - } - cpu_reset(CPU(cpu)); - return cpu; -} - void pc_cpus_init(const char *cpu_model) { int i; @@ -918,8 +869,11 @@ void pc_cpus_init(const char *cpu_model) #endif } - for(i = 0; i < smp_cpus; i++) { - pc_new_cpu(cpu_model); + for (i = 0; i < smp_cpus; i++) { + if (!cpu_x86_init(cpu_model)) { + fprintf(stderr, "Unable to find x86 CPU definition\n"); + exit(1); + } } } diff --git a/target-i386/cpu.c b/target-i386/cpu.c index f3a31212eb..18b8549a6f 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -37,6 +37,12 @@ #include #endif +#include "sysemu.h" +#ifndef CONFIG_USER_ONLY +#include "hw/xen.h" +#include "hw/sysbus.h" +#endif + /* feature flags taken from "Intel Processor Identification and the CPUID * Instruction" and AMD's "CPUID Specification". In cases of disagreement * between feature naming conventions, aliases may be added. @@ -1879,12 +1885,63 @@ static void mce_init(X86CPU *cpu) } } +#define MSI_ADDR_BASE 0xfee00000 + +#ifndef CONFIG_USER_ONLY +static void x86_cpu_apic_init(X86CPU *cpu, Error **errp) +{ + static int apic_mapped; + CPUX86State *env = &cpu->env; + const char *apic_type = "apic"; + + if (kvm_irqchip_in_kernel()) { + apic_type = "kvm-apic"; + } else if (xen_enabled()) { + apic_type = "xen-apic"; + } + + env->apic_state = qdev_try_create(NULL, apic_type); + if (env->apic_state == NULL) { + error_setg(errp, "APIC device '%s' could not be created", apic_type); + return; + } + + object_property_add_child(OBJECT(cpu), "apic", + OBJECT(env->apic_state), NULL); + qdev_prop_set_uint8(env->apic_state, "id", env->cpuid_apic_id); + /* TODO: convert to link<> */ + qdev_prop_set_ptr(env->apic_state, "cpu_env", env); + + if (qdev_init(env->apic_state)) { + error_setg(errp, "APIC device '%s' could not be initialized", + object_get_typename(OBJECT(env->apic_state))); + return; + } + + /* XXX: mapping more APICs at the same memory location */ + if (apic_mapped == 0) { + /* NOTE: the APIC is directly connected to the CPU - it is not + on the global memory bus. */ + /* XXX: what if the base changes? */ + sysbus_mmio_map(sysbus_from_qdev(env->apic_state), 0, MSI_ADDR_BASE); + apic_mapped = 1; + } +} +#endif + void x86_cpu_realize(Object *obj, Error **errp) { X86CPU *cpu = X86_CPU(obj); #ifndef CONFIG_USER_ONLY qemu_register_reset(x86_cpu_machine_reset_cb, cpu); + + if (cpu->env.cpuid_features & CPUID_APIC || smp_cpus > 1) { + x86_cpu_apic_init(cpu, errp); + if (error_is_set(errp)) { + return; + } + } #endif mce_init(cpu); From 449994eb58a4175a2e7656175b18c65ead6c09ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 10 Oct 2012 12:18:02 +0200 Subject: [PATCH 1326/2270] target-i386: Inline APIC cpu_env property setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This prepares for changing the variable type from void*. Signed-off-by: Andreas Färber Reviewed-by: Igor Mammedov --- hw/apic_common.c | 1 - target-i386/cpu.c | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/apic_common.c b/hw/apic_common.c index d68116d490..b13f23c991 100644 --- a/hw/apic_common.c +++ b/hw/apic_common.c @@ -368,7 +368,6 @@ static const VMStateDescription vmstate_apic_common = { static Property apic_properties_common[] = { DEFINE_PROP_UINT8("id", APICCommonState, id, -1), - DEFINE_PROP_PTR("cpu_env", APICCommonState, cpu_env), DEFINE_PROP_BIT("vapic", APICCommonState, vapic_control, VAPIC_ENABLE_BIT, true), DEFINE_PROP_END_OF_LIST(), diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 18b8549a6f..c30cc799de 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -41,6 +41,7 @@ #ifndef CONFIG_USER_ONLY #include "hw/xen.h" #include "hw/sysbus.h" +#include "hw/apic_internal.h" #endif /* feature flags taken from "Intel Processor Identification and the CPUID @@ -1892,6 +1893,7 @@ static void x86_cpu_apic_init(X86CPU *cpu, Error **errp) { static int apic_mapped; CPUX86State *env = &cpu->env; + APICCommonState *apic; const char *apic_type = "apic"; if (kvm_irqchip_in_kernel()) { @@ -1910,7 +1912,8 @@ static void x86_cpu_apic_init(X86CPU *cpu, Error **errp) OBJECT(env->apic_state), NULL); qdev_prop_set_uint8(env->apic_state, "id", env->cpuid_apic_id); /* TODO: convert to link<> */ - qdev_prop_set_ptr(env->apic_state, "cpu_env", env); + apic = APIC_COMMON(env->apic_state); + apic->cpu_env = env; if (qdev_init(env->apic_state)) { error_setg(errp, "APIC device '%s' could not be initialized", From 60671e583c2bfb09746f59268fdc7d88eaa24deb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 10 Oct 2012 14:10:07 +0200 Subject: [PATCH 1327/2270] apic: Store X86CPU in APICCommonState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepares for using a link<> property to connect APIC with CPU and for changing the CPU APIs to CPUState. Resolve Coding Style warnings by moving the closing parenthesis of foreach_apic() macro to next line. Signed-off-by: Andreas Färber Reviewed-by: Igor Mammedov --- hw/apic.c | 38 +++++++++++++++++++++----------------- hw/apic_common.c | 4 ++-- hw/apic_internal.h | 3 ++- hw/kvm/apic.c | 8 ++++---- target-i386/cpu.c | 2 +- 5 files changed, 30 insertions(+), 25 deletions(-) diff --git a/hw/apic.c b/hw/apic.c index 49f00152ae..99e84f948b 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -107,7 +107,7 @@ static void apic_sync_vapic(APICCommonState *s, int sync_type) length = offsetof(VAPICState, enabled) - offsetof(VAPICState, isr); if (sync_type & SYNC_TO_VAPIC) { - assert(qemu_cpu_is_self(s->cpu_env)); + assert(qemu_cpu_is_self(&s->cpu->env)); vapic_state.tpr = s->tpr; vapic_state.enabled = 1; @@ -151,15 +151,15 @@ static void apic_local_deliver(APICCommonState *s, int vector) switch ((lvt >> 8) & 7) { case APIC_DM_SMI: - cpu_interrupt(s->cpu_env, CPU_INTERRUPT_SMI); + cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_SMI); break; case APIC_DM_NMI: - cpu_interrupt(s->cpu_env, CPU_INTERRUPT_NMI); + cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_NMI); break; case APIC_DM_EXTINT: - cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD); + cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD); break; case APIC_DM_FIXED: @@ -187,7 +187,7 @@ void apic_deliver_pic_intr(DeviceState *d, int level) reset_bit(s->irr, lvt & 0xff); /* fall through */ case APIC_DM_EXTINT: - cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_HARD); + cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD); break; } } @@ -248,18 +248,22 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask, case APIC_DM_SMI: foreach_apic(apic_iter, deliver_bitmask, - cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_SMI) ); + cpu_interrupt(&apic_iter->cpu->env, CPU_INTERRUPT_SMI) + ); return; case APIC_DM_NMI: foreach_apic(apic_iter, deliver_bitmask, - cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_NMI) ); + cpu_interrupt(&apic_iter->cpu->env, CPU_INTERRUPT_NMI) + ); return; case APIC_DM_INIT: /* normal INIT IPI sent to processors */ foreach_apic(apic_iter, deliver_bitmask, - cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_INIT) ); + cpu_interrupt(&apic_iter->cpu->env, + CPU_INTERRUPT_INIT) + ); return; case APIC_DM_EXTINT: @@ -293,7 +297,7 @@ static void apic_set_base(APICCommonState *s, uint64_t val) /* if disabled, cannot be enabled again */ if (!(val & MSR_IA32_APICBASE_ENABLE)) { s->apicbase &= ~MSR_IA32_APICBASE_ENABLE; - cpu_clear_apic_feature(s->cpu_env); + cpu_clear_apic_feature(&s->cpu->env); s->spurious_vec &= ~APIC_SV_ENABLE; } } @@ -362,10 +366,10 @@ static void apic_update_irq(APICCommonState *s) if (!(s->spurious_vec & APIC_SV_ENABLE)) { return; } - if (!qemu_cpu_is_self(s->cpu_env)) { - cpu_interrupt(s->cpu_env, CPU_INTERRUPT_POLL); + if (!qemu_cpu_is_self(&s->cpu->env)) { + cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_POLL); } else if (apic_irq_pending(s) > 0) { - cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD); + cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD); } } @@ -472,18 +476,18 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, static void apic_startup(APICCommonState *s, int vector_num) { s->sipi_vector = vector_num; - cpu_interrupt(s->cpu_env, CPU_INTERRUPT_SIPI); + cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_SIPI); } void apic_sipi(DeviceState *d) { APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); - cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_SIPI); + cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_SIPI); if (!s->wait_for_sipi) return; - cpu_x86_load_seg_cache_sipi(s->cpu_env, s->sipi_vector); + cpu_x86_load_seg_cache_sipi(&s->cpu->env, s->sipi_vector); s->wait_for_sipi = 0; } @@ -672,7 +676,7 @@ static uint32_t apic_mem_readl(void *opaque, hwaddr addr) case 0x08: apic_sync_vapic(s, SYNC_FROM_VAPIC); if (apic_report_tpr_access) { - cpu_report_tpr_access(s->cpu_env, TPR_ACCESS_READ); + cpu_report_tpr_access(&s->cpu->env, TPR_ACCESS_READ); } val = s->tpr; break; @@ -774,7 +778,7 @@ static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val) break; case 0x08: if (apic_report_tpr_access) { - cpu_report_tpr_access(s->cpu_env, TPR_ACCESS_WRITE); + cpu_report_tpr_access(&s->cpu->env, TPR_ACCESS_WRITE); } s->tpr = val; apic_sync_vapic(s, SYNC_TO_VAPIC); diff --git a/hw/apic_common.c b/hw/apic_common.c index b13f23c991..5f542764eb 100644 --- a/hw/apic_common.c +++ b/hw/apic_common.c @@ -103,7 +103,7 @@ void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip, { APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); - vapic_report_tpr_access(s->vapic, s->cpu_env, ip, access); + vapic_report_tpr_access(s->vapic, &s->cpu->env, ip, access); } void apic_report_irq_delivered(int delivered) @@ -217,7 +217,7 @@ static void apic_reset_common(DeviceState *d) APICCommonClass *info = APIC_COMMON_GET_CLASS(s); bool bsp; - bsp = cpu_is_bsp(x86_env_get_cpu(s->cpu_env)); + bsp = cpu_is_bsp(s->cpu); s->apicbase = 0xfee00000 | (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE; diff --git a/hw/apic_internal.h b/hw/apic_internal.h index 30932a303a..79e2de2243 100644 --- a/hw/apic_internal.h +++ b/hw/apic_internal.h @@ -95,8 +95,9 @@ typedef struct APICCommonClass struct APICCommonState { SysBusDevice busdev; + MemoryRegion io_memory; - void *cpu_env; + X86CPU *cpu; uint32_t apicbase; uint8_t id; uint8_t arb_id; diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c index dbac7fff50..e4a7307ca5 100644 --- a/hw/kvm/apic.c +++ b/hw/kvm/apic.c @@ -104,7 +104,7 @@ static void kvm_apic_enable_tpr_reporting(APICCommonState *s, bool enable) .enabled = enable }; - kvm_vcpu_ioctl(s->cpu_env, KVM_TPR_ACCESS_REPORTING, &ctl); + kvm_vcpu_ioctl(&s->cpu->env, KVM_TPR_ACCESS_REPORTING, &ctl); } static void kvm_apic_vapic_base_update(APICCommonState *s) @@ -114,7 +114,7 @@ static void kvm_apic_vapic_base_update(APICCommonState *s) }; int ret; - ret = kvm_vcpu_ioctl(s->cpu_env, KVM_SET_VAPIC_ADDR, &vapid_addr); + ret = kvm_vcpu_ioctl(&s->cpu->env, KVM_SET_VAPIC_ADDR, &vapid_addr); if (ret < 0) { fprintf(stderr, "KVM: setting VAPIC address failed (%s)\n", strerror(-ret)); @@ -125,7 +125,7 @@ static void kvm_apic_vapic_base_update(APICCommonState *s) static void do_inject_external_nmi(void *data) { APICCommonState *s = data; - CPUX86State *env = s->cpu_env; + CPUX86State *env = &s->cpu->env; uint32_t lvt; int ret; @@ -143,7 +143,7 @@ static void do_inject_external_nmi(void *data) static void kvm_apic_external_nmi(APICCommonState *s) { - run_on_cpu(s->cpu_env, do_inject_external_nmi, s); + run_on_cpu(&s->cpu->env, do_inject_external_nmi, s); } static uint64_t kvm_apic_mem_read(void *opaque, hwaddr addr, diff --git a/target-i386/cpu.c b/target-i386/cpu.c index c30cc799de..156e9199ed 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1913,7 +1913,7 @@ static void x86_cpu_apic_init(X86CPU *cpu, Error **errp) qdev_prop_set_uint8(env->apic_state, "id", env->cpuid_apic_id); /* TODO: convert to link<> */ apic = APIC_COMMON(env->apic_state); - apic->cpu_env = env; + apic->cpu = cpu; if (qdev_init(env->apic_state)) { error_setg(errp, "APIC device '%s' could not be initialized", From e9f9d6b16510776ae3d07e91b1cfb4d412701270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 15:37:01 +0200 Subject: [PATCH 1328/2270] target-i386: Pass X86CPU to cpu_x86_load_seg_cache_sipi() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplifies the call in apic_sipi() again and needed for moving halted field to CPUState. Signed-off-by: Andreas Färber Reviewed-by: Igor Mammedov --- hw/apic.c | 2 +- target-i386/cpu.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/apic.c b/hw/apic.c index 99e84f948b..4bc14e0c36 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -487,7 +487,7 @@ void apic_sipi(DeviceState *d) if (!s->wait_for_sipi) return; - cpu_x86_load_seg_cache_sipi(&s->cpu->env, s->sipi_vector); + cpu_x86_load_seg_cache_sipi(s->cpu, s->sipi_vector); s->wait_for_sipi = 0; } diff --git a/target-i386/cpu.h b/target-i386/cpu.h index de33303dea..d840914ebf 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -907,9 +907,11 @@ static inline void cpu_x86_load_seg_cache(CPUX86State *env, } } -static inline void cpu_x86_load_seg_cache_sipi(CPUX86State *env, +static inline void cpu_x86_load_seg_cache_sipi(X86CPU *cpu, int sipi_vector) { + CPUX86State *env = &cpu->env; + env->eip = 0; cpu_x86_load_seg_cache(env, R_CS, sipi_vector << 8, sipi_vector << 12, From 60e82579c75068cb49af95595aa99d727e657a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 2 May 2012 22:23:49 +0200 Subject: [PATCH 1329/2270] cpus: Pass CPUState to qemu_cpu_is_self() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change return type to bool, move to include/qemu/cpu.h and add documentation. Signed-off-by: Andreas Färber Reviewed-by: Igor Mammedov [AF: Updated new caller qemu_in_vcpu_thread()] --- cpus.c | 12 +++++------- exec.c | 3 ++- hw/apic.c | 6 ++++-- include/qemu/cpu.h | 10 ++++++++++ kvm-all.c | 4 +++- qemu-common.h | 1 - target-i386/kvm.c | 6 ++++-- 7 files changed, 28 insertions(+), 14 deletions(-) diff --git a/cpus.c b/cpus.c index 191cbf5f6d..1f3ac9177c 100644 --- a/cpus.c +++ b/cpus.c @@ -638,9 +638,10 @@ void qemu_init_cpu_loop(void) void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data) { + CPUState *cpu = ENV_GET_CPU(env); struct qemu_work_item wi; - if (qemu_cpu_is_self(env)) { + if (qemu_cpu_is_self(cpu)) { func(data); return; } @@ -855,7 +856,7 @@ static void qemu_cpu_kick_thread(CPUArchState *env) exit(1); } #else /* _WIN32 */ - if (!qemu_cpu_is_self(env)) { + if (!qemu_cpu_is_self(cpu)) { SuspendThread(cpu->hThread); cpu_signal(0); ResumeThread(cpu->hThread); @@ -890,17 +891,14 @@ void qemu_cpu_kick_self(void) #endif } -int qemu_cpu_is_self(void *_env) +bool qemu_cpu_is_self(CPUState *cpu) { - CPUArchState *env = _env; - CPUState *cpu = ENV_GET_CPU(env); - return qemu_thread_is_self(cpu->thread); } static bool qemu_in_vcpu_thread(void) { - return cpu_single_env && qemu_cpu_is_self(cpu_single_env); + return cpu_single_env && qemu_cpu_is_self(ENV_GET_CPU(cpu_single_env)); } void qemu_mutex_lock_iothread(void) diff --git a/exec.c b/exec.c index b0ed5939e9..a85a9b1fd2 100644 --- a/exec.c +++ b/exec.c @@ -1693,6 +1693,7 @@ static void cpu_unlink_tb(CPUArchState *env) /* mask must never be zero, except for A20 change call */ static void tcg_handle_interrupt(CPUArchState *env, int mask) { + CPUState *cpu = ENV_GET_CPU(env); int old_mask; old_mask = env->interrupt_request; @@ -1702,7 +1703,7 @@ static void tcg_handle_interrupt(CPUArchState *env, int mask) * If called from iothread context, wake the target cpu in * case its halted. */ - if (!qemu_cpu_is_self(env)) { + if (!qemu_cpu_is_self(cpu)) { qemu_cpu_kick(env); return; } diff --git a/hw/apic.c b/hw/apic.c index 4bc14e0c36..f73fc877aa 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -107,7 +107,7 @@ static void apic_sync_vapic(APICCommonState *s, int sync_type) length = offsetof(VAPICState, enabled) - offsetof(VAPICState, isr); if (sync_type & SYNC_TO_VAPIC) { - assert(qemu_cpu_is_self(&s->cpu->env)); + assert(qemu_cpu_is_self(CPU(s->cpu))); vapic_state.tpr = s->tpr; vapic_state.enabled = 1; @@ -363,10 +363,12 @@ static int apic_irq_pending(APICCommonState *s) /* signal the CPU if an irq is pending */ static void apic_update_irq(APICCommonState *s) { + CPUState *cpu = CPU(s->cpu); + if (!(s->spurious_vec & APIC_SV_ENABLE)) { return; } - if (!qemu_cpu_is_self(&s->cpu->env)) { + if (!qemu_cpu_is_self(cpu)) { cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_POLL); } else if (apic_irq_pending(s) > 0) { cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD); diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h index ad706a6dbd..7be983d89c 100644 --- a/include/qemu/cpu.h +++ b/include/qemu/cpu.h @@ -78,5 +78,15 @@ struct CPUState { */ void cpu_reset(CPUState *cpu); +/** + * qemu_cpu_is_self: + * @cpu: The vCPU to check against. + * + * Checks whether the caller is executing on the vCPU thread. + * + * Returns: %true if called from @cpu's thread, %false otherwise. + */ +bool qemu_cpu_is_self(CPUState *cpu); + #endif diff --git a/kvm-all.c b/kvm-all.c index 961e1dbb71..74d2652f02 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -828,9 +828,11 @@ static MemoryListener kvm_io_listener = { static void kvm_handle_interrupt(CPUArchState *env, int mask) { + CPUState *cpu = ENV_GET_CPU(env); + env->interrupt_request |= mask; - if (!qemu_cpu_is_self(env)) { + if (!qemu_cpu_is_self(cpu)) { qemu_cpu_kick(env); } } diff --git a/qemu-common.h b/qemu-common.h index b54612b1a5..2094742f2b 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -326,7 +326,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id); /* Unblock cpu */ void qemu_cpu_kick(void *env); void qemu_cpu_kick_self(void); -int qemu_cpu_is_self(void *env); /* work queue */ struct qemu_work_item { diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 3aa62b20ff..c13f196e05 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1552,9 +1552,10 @@ static int kvm_get_debugregs(CPUX86State *env) int kvm_arch_put_registers(CPUX86State *env, int level) { + CPUState *cpu = ENV_GET_CPU(env); int ret; - assert(cpu_is_stopped(env) || qemu_cpu_is_self(env)); + assert(cpu_is_stopped(env) || qemu_cpu_is_self(cpu)); ret = kvm_getput_regs(env, 1); if (ret < 0) { @@ -1609,9 +1610,10 @@ int kvm_arch_put_registers(CPUX86State *env, int level) int kvm_arch_get_registers(CPUX86State *env) { + CPUState *cpu = ENV_GET_CPU(env); int ret; - assert(cpu_is_stopped(env) || qemu_cpu_is_self(env)); + assert(cpu_is_stopped(env) || qemu_cpu_is_self(cpu)); ret = kvm_getput_regs(env, 0); if (ret < 0) { From 2ff09a40a8399a6f9807ebdb72423ec0a581c3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 00:23:30 +0200 Subject: [PATCH 1330/2270] cpus: Pass CPUState to qemu_cpu_kick_thread() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPUArchState is no longer needed there. Signed-off-by: Andreas Färber Reviewed-by: Igor Mammedov --- cpus.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cpus.c b/cpus.c index 1f3ac9177c..3946d49cff 100644 --- a/cpus.c +++ b/cpus.c @@ -844,9 +844,8 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) return NULL; } -static void qemu_cpu_kick_thread(CPUArchState *env) +static void qemu_cpu_kick_thread(CPUState *cpu) { - CPUState *cpu = ENV_GET_CPU(env); #ifndef _WIN32 int err; @@ -871,7 +870,7 @@ void qemu_cpu_kick(void *_env) qemu_cond_broadcast(env->halt_cond); if (!tcg_enabled() && !cpu->thread_kicked) { - qemu_cpu_kick_thread(env); + qemu_cpu_kick_thread(cpu); cpu->thread_kicked = true; } } @@ -883,7 +882,7 @@ void qemu_cpu_kick_self(void) CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env); if (!cpu_single_cpu->thread_kicked) { - qemu_cpu_kick_thread(cpu_single_env); + qemu_cpu_kick_thread(cpu_single_cpu); cpu_single_cpu->thread_kicked = true; } #else @@ -908,7 +907,7 @@ void qemu_mutex_lock_iothread(void) } else { iothread_requesting_mutex = true; if (qemu_mutex_trylock(&qemu_global_mutex)) { - qemu_cpu_kick_thread(first_cpu); + qemu_cpu_kick_thread(ENV_GET_CPU(first_cpu)); qemu_mutex_lock(&qemu_global_mutex); } iothread_requesting_mutex = false; From 61a4621784a808f5ad7d63f60e2c5e8b2488c213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 2 May 2012 22:49:36 +0200 Subject: [PATCH 1331/2270] cpu: Move created field to CPUState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change its type to bool. Signed-off-by: Andreas Färber --- cpu-defs.h | 1 - cpus.c | 13 +++++++------ include/qemu/cpu.h | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/cpu-defs.h b/cpu-defs.h index a7965775b2..3b8bc20329 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -205,7 +205,6 @@ typedef struct CPUWatchpoint { /* user data */ \ void *opaque; \ \ - uint32_t created; \ uint32_t stop; /* Stop request */ \ uint32_t stopped; /* Artificially stopped */ \ struct QemuCond *halt_cond; \ diff --git a/cpus.c b/cpus.c index 3946d49cff..8abaa69d41 100644 --- a/cpus.c +++ b/cpus.c @@ -746,7 +746,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg) qemu_kvm_init_cpu_signals(env); /* signal CPU creation */ - env->created = 1; + cpu->created = true; qemu_cond_signal(&qemu_cpu_cond); while (1) { @@ -781,7 +781,7 @@ static void *qemu_dummy_cpu_thread_fn(void *arg) sigaddset(&waitset, SIG_IPI); /* signal CPU creation */ - env->created = 1; + cpu->created = true; qemu_cond_signal(&qemu_cpu_cond); cpu_single_env = env; @@ -818,8 +818,9 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) /* signal CPU creation */ qemu_mutex_lock(&qemu_global_mutex); for (env = first_cpu; env != NULL; env = env->next_cpu) { + cpu = ENV_GET_CPU(env); env->thread_id = qemu_get_thread_id(); - env->created = 1; + cpu->created = true; } qemu_cond_signal(&qemu_cpu_cond); @@ -996,7 +997,7 @@ static void qemu_tcg_init_vcpu(void *_env) #ifdef _WIN32 cpu->hThread = qemu_thread_get_handle(cpu->thread); #endif - while (env->created == 0) { + while (!cpu->created) { qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex); } tcg_cpu_thread = cpu->thread; @@ -1015,7 +1016,7 @@ static void qemu_kvm_start_vcpu(CPUArchState *env) qemu_cond_init(env->halt_cond); qemu_thread_create(cpu->thread, qemu_kvm_cpu_thread_fn, env, QEMU_THREAD_JOINABLE); - while (env->created == 0) { + while (!cpu->created) { qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex); } } @@ -1029,7 +1030,7 @@ static void qemu_dummy_start_vcpu(CPUArchState *env) qemu_cond_init(env->halt_cond); qemu_thread_create(cpu->thread, qemu_dummy_cpu_thread_fn, env, QEMU_THREAD_JOINABLE); - while (env->created == 0) { + while (!cpu->created) { qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex); } } diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h index 7be983d89c..3ab2e2567f 100644 --- a/include/qemu/cpu.h +++ b/include/qemu/cpu.h @@ -54,6 +54,7 @@ typedef struct CPUClass { /** * CPUState: + * @created: Indicates whether the CPU thread has been successfully created. * * State of one CPU core or thread. */ @@ -67,6 +68,7 @@ struct CPUState { HANDLE hThread; #endif bool thread_kicked; + bool created; /* TODO Move common fields from CPUArchState here. */ }; From 4fdeee7cd4c8f90ef765537b9346a195d9483ab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 2 May 2012 23:10:09 +0200 Subject: [PATCH 1332/2270] cpu: Move stop field to CPUState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change its type to bool. Signed-off-by: Andreas Färber --- cpu-defs.h | 1 - cpus.c | 27 ++++++++++++++++++--------- include/qemu/cpu.h | 2 ++ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/cpu-defs.h b/cpu-defs.h index 3b8bc20329..7a6378c5a1 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -205,7 +205,6 @@ typedef struct CPUWatchpoint { /* user data */ \ void *opaque; \ \ - uint32_t stop; /* Stop request */ \ uint32_t stopped; /* Artificially stopped */ \ struct QemuCond *halt_cond; \ struct qemu_work_item *queued_work_first, *queued_work_last; \ diff --git a/cpus.c b/cpus.c index 8abaa69d41..2341ebb68c 100644 --- a/cpus.c +++ b/cpus.c @@ -64,7 +64,9 @@ static CPUArchState *next_cpu; static bool cpu_thread_is_idle(CPUArchState *env) { - if (env->stop || env->queued_work_first) { + CPUState *cpu = ENV_GET_CPU(env); + + if (cpu->stop || env->queued_work_first) { return false; } if (env->stopped || !runstate_is_running()) { @@ -448,7 +450,9 @@ static void do_vm_stop(RunState state) static int cpu_can_run(CPUArchState *env) { - if (env->stop) { + CPUState *cpu = ENV_GET_CPU(env); + + if (cpu->stop) { return 0; } if (env->stopped || !runstate_is_running()) { @@ -687,8 +691,8 @@ static void qemu_wait_io_event_common(CPUArchState *env) { CPUState *cpu = ENV_GET_CPU(env); - if (env->stop) { - env->stop = 0; + if (cpu->stop) { + cpu->stop = false; env->stopped = 1; qemu_cond_signal(&qemu_pause_cond); } @@ -941,7 +945,8 @@ void pause_all_vcpus(void) qemu_clock_enable(vm_clock, false); while (penv) { - penv->stop = 1; + CPUState *pcpu = ENV_GET_CPU(penv); + pcpu->stop = true; qemu_cpu_kick(penv); penv = penv->next_cpu; } @@ -950,7 +955,8 @@ void pause_all_vcpus(void) cpu_stop_current(); if (!kvm_enabled()) { while (penv) { - penv->stop = 0; + CPUState *pcpu = ENV_GET_CPU(penv); + pcpu->stop = 0; penv->stopped = 1; penv = penv->next_cpu; } @@ -974,7 +980,8 @@ void resume_all_vcpus(void) qemu_clock_enable(vm_clock, true); while (penv) { - penv->stop = 0; + CPUState *pcpu = ENV_GET_CPU(penv); + pcpu->stop = false; penv->stopped = 0; qemu_cpu_kick(penv); penv = penv->next_cpu; @@ -1054,7 +1061,8 @@ void qemu_init_vcpu(void *_env) void cpu_stop_current(void) { if (cpu_single_env) { - cpu_single_env->stop = 0; + CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env); + cpu_single_cpu->stop = false; cpu_single_env->stopped = 1; cpu_exit(cpu_single_env); qemu_cond_signal(&qemu_pause_cond); @@ -1136,6 +1144,7 @@ static void tcg_exec_all(void) } for (; next_cpu != NULL && !exit_request; next_cpu = next_cpu->next_cpu) { CPUArchState *env = next_cpu; + CPUState *cpu = ENV_GET_CPU(env); qemu_clock_enable(vm_clock, (env->singlestep_enabled & SSTEP_NOTIMER) == 0); @@ -1146,7 +1155,7 @@ static void tcg_exec_all(void) cpu_handle_guest_debug(env); break; } - } else if (env->stop || env->stopped) { + } else if (cpu->stop || env->stopped) { break; } } diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h index 3ab2e2567f..04c7848b8f 100644 --- a/include/qemu/cpu.h +++ b/include/qemu/cpu.h @@ -55,6 +55,7 @@ typedef struct CPUClass { /** * CPUState: * @created: Indicates whether the CPU thread has been successfully created. + * @stop: Indicates a pending stop request. * * State of one CPU core or thread. */ @@ -69,6 +70,7 @@ struct CPUState { #endif bool thread_kicked; bool created; + bool stop; /* TODO Move common fields from CPUArchState here. */ }; From b6444a42c06371d5abba78d2553a088a8490a65b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 00:34:15 +0200 Subject: [PATCH 1333/2270] ppce500_spin: Store PowerPCCPU in SpinKick MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for moving stopped field to CPUState. Signed-off-by: Andreas Färber --- hw/ppce500_spin.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c index 55aa9dc8a2..04e7e65d44 100644 --- a/hw/ppce500_spin.c +++ b/hw/ppce500_spin.c @@ -49,7 +49,7 @@ typedef struct spin_state { } SpinState; typedef struct spin_kick { - CPUPPCState *env; + PowerPCCPU *cpu; SpinInfo *spin; } SpinKick; @@ -92,7 +92,7 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env, static void spin_kick(void *data) { SpinKick *kick = data; - CPUPPCState *env = kick->env; + CPUPPCState *env = &kick->cpu->env; SpinInfo *curspin = kick->spin; hwaddr map_size = 64 * 1024 * 1024; hwaddr map_start; @@ -158,7 +158,7 @@ static void spin_write(void *opaque, hwaddr addr, uint64_t value, if (!(ldq_p(&curspin->addr) & 1)) { /* run CPU */ SpinKick kick = { - .env = env, + .cpu = ppc_env_get_cpu(env), .spin = curspin, }; From f324e7667a3c1f1aed9a5169a63aaac628feef47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 2 May 2012 23:26:21 +0200 Subject: [PATCH 1334/2270] cpu: Move stopped field to CPUState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change its type to bool. Signed-off-by: Andreas Färber --- cpu-defs.h | 1 - cpus.c | 30 ++++++++++++++++++------------ hw/ppce500_spin.c | 3 ++- include/qemu/cpu.h | 2 ++ 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/cpu-defs.h b/cpu-defs.h index 7a6378c5a1..83bf1089a6 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -205,7 +205,6 @@ typedef struct CPUWatchpoint { /* user data */ \ void *opaque; \ \ - uint32_t stopped; /* Artificially stopped */ \ struct QemuCond *halt_cond; \ struct qemu_work_item *queued_work_first, *queued_work_last; \ const char *cpu_model_str; \ diff --git a/cpus.c b/cpus.c index 2341ebb68c..4654f0878b 100644 --- a/cpus.c +++ b/cpus.c @@ -69,7 +69,7 @@ static bool cpu_thread_is_idle(CPUArchState *env) if (cpu->stop || env->queued_work_first) { return false; } - if (env->stopped || !runstate_is_running()) { + if (cpu->stopped || !runstate_is_running()) { return true; } if (!env->halted || qemu_cpu_has_work(env) || @@ -432,7 +432,9 @@ void cpu_synchronize_all_post_init(void) int cpu_is_stopped(CPUArchState *env) { - return !runstate_is_running() || env->stopped; + CPUState *cpu = ENV_GET_CPU(env); + + return !runstate_is_running() || cpu->stopped; } static void do_vm_stop(RunState state) @@ -455,7 +457,7 @@ static int cpu_can_run(CPUArchState *env) if (cpu->stop) { return 0; } - if (env->stopped || !runstate_is_running()) { + if (cpu->stopped || !runstate_is_running()) { return 0; } return 1; @@ -463,9 +465,11 @@ static int cpu_can_run(CPUArchState *env) static void cpu_handle_guest_debug(CPUArchState *env) { + CPUState *cpu = ENV_GET_CPU(env); + gdb_set_stop_cpu(env); qemu_system_debug_request(); - env->stopped = 1; + cpu->stopped = true; } static void cpu_signal(int sig) @@ -693,7 +697,7 @@ static void qemu_wait_io_event_common(CPUArchState *env) if (cpu->stop) { cpu->stop = false; - env->stopped = 1; + cpu->stopped = true; qemu_cond_signal(&qemu_pause_cond); } flush_queued_work(env); @@ -829,7 +833,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) qemu_cond_signal(&qemu_cpu_cond); /* wait for initial kick-off after machine start */ - while (first_cpu->stopped) { + while (ENV_GET_CPU(first_cpu)->stopped) { qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex); /* process any pending work */ @@ -930,7 +934,8 @@ static int all_vcpus_paused(void) CPUArchState *penv = first_cpu; while (penv) { - if (!penv->stopped) { + CPUState *pcpu = ENV_GET_CPU(penv); + if (!pcpu->stopped) { return 0; } penv = penv->next_cpu; @@ -957,7 +962,7 @@ void pause_all_vcpus(void) while (penv) { CPUState *pcpu = ENV_GET_CPU(penv); pcpu->stop = 0; - penv->stopped = 1; + pcpu->stopped = true; penv = penv->next_cpu; } return; @@ -982,7 +987,7 @@ void resume_all_vcpus(void) while (penv) { CPUState *pcpu = ENV_GET_CPU(penv); pcpu->stop = false; - penv->stopped = 0; + pcpu->stopped = false; qemu_cpu_kick(penv); penv = penv->next_cpu; } @@ -1045,10 +1050,11 @@ static void qemu_dummy_start_vcpu(CPUArchState *env) void qemu_init_vcpu(void *_env) { CPUArchState *env = _env; + CPUState *cpu = ENV_GET_CPU(env); env->nr_cores = smp_cores; env->nr_threads = smp_threads; - env->stopped = 1; + cpu->stopped = true; if (kvm_enabled()) { qemu_kvm_start_vcpu(env); } else if (tcg_enabled()) { @@ -1063,7 +1069,7 @@ void cpu_stop_current(void) if (cpu_single_env) { CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env); cpu_single_cpu->stop = false; - cpu_single_env->stopped = 1; + cpu_single_cpu->stopped = true; cpu_exit(cpu_single_env); qemu_cond_signal(&qemu_pause_cond); } @@ -1155,7 +1161,7 @@ static void tcg_exec_all(void) cpu_handle_guest_debug(env); break; } - } else if (cpu->stop || env->stopped) { + } else if (cpu->stop || cpu->stopped) { break; } } diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c index 04e7e65d44..fb5461d588 100644 --- a/hw/ppce500_spin.c +++ b/hw/ppce500_spin.c @@ -92,6 +92,7 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env, static void spin_kick(void *data) { SpinKick *kick = data; + CPUState *cpu = CPU(kick->cpu); CPUPPCState *env = &kick->cpu->env; SpinInfo *curspin = kick->spin; hwaddr map_size = 64 * 1024 * 1024; @@ -113,7 +114,7 @@ static void spin_kick(void *data) env->halted = 0; env->exception_index = -1; - env->stopped = 0; + cpu->stopped = false; qemu_cpu_kick(env); } diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h index 04c7848b8f..83378c54ae 100644 --- a/include/qemu/cpu.h +++ b/include/qemu/cpu.h @@ -56,6 +56,7 @@ typedef struct CPUClass { * CPUState: * @created: Indicates whether the CPU thread has been successfully created. * @stop: Indicates a pending stop request. + * @stopped: Indicates the CPU has been artificially stopped. * * State of one CPU core or thread. */ @@ -71,6 +72,7 @@ struct CPUState { bool thread_kicked; bool created; bool stop; + bool stopped; /* TODO Move common fields from CPUArchState here. */ }; From 2fa45344a92444439c081cad2342ffc048c381ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 2 May 2012 23:38:39 +0200 Subject: [PATCH 1335/2270] cpus: Pass CPUState to cpu_is_stopped() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPUArchState is no longer needed there. Also change the return type to bool. Signed-off-by: Andreas Färber --- cpu-all.h | 1 - cpus.c | 4 +--- include/qemu/cpu.h | 11 +++++++++++ target-i386/kvm.c | 4 ++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index 6606432944..d19ec127e1 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -466,7 +466,6 @@ void cpu_watchpoint_remove_all(CPUArchState *env, int mask); #define SSTEP_NOTIMER 0x4 /* Do not Timers while single stepping */ void cpu_single_step(CPUArchState *env, int enabled); -int cpu_is_stopped(CPUArchState *env); void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data); #if !defined(CONFIG_USER_ONLY) diff --git a/cpus.c b/cpus.c index 4654f0878b..0721a96831 100644 --- a/cpus.c +++ b/cpus.c @@ -430,10 +430,8 @@ void cpu_synchronize_all_post_init(void) } } -int cpu_is_stopped(CPUArchState *env) +bool cpu_is_stopped(CPUState *cpu) { - CPUState *cpu = ENV_GET_CPU(env); - return !runstate_is_running() || cpu->stopped; } diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h index 83378c54ae..4e62032463 100644 --- a/include/qemu/cpu.h +++ b/include/qemu/cpu.h @@ -94,5 +94,16 @@ void cpu_reset(CPUState *cpu); */ bool qemu_cpu_is_self(CPUState *cpu); +/** + * cpu_is_stopped: + * @cpu: The CPU to check. + * + * Checks whether the CPU is stopped. + * + * Returns: %true if run state is not running or if artificially stopped; + * %false otherwise. + */ +bool cpu_is_stopped(CPUState *cpu); + #endif diff --git a/target-i386/kvm.c b/target-i386/kvm.c index c13f196e05..a3491a4fa1 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1555,7 +1555,7 @@ int kvm_arch_put_registers(CPUX86State *env, int level) CPUState *cpu = ENV_GET_CPU(env); int ret; - assert(cpu_is_stopped(env) || qemu_cpu_is_self(cpu)); + assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); ret = kvm_getput_regs(env, 1); if (ret < 0) { @@ -1613,7 +1613,7 @@ int kvm_arch_get_registers(CPUX86State *env) CPUState *cpu = ENV_GET_CPU(env); int ret; - assert(cpu_is_stopped(env) || qemu_cpu_is_self(cpu)); + assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); ret = kvm_getput_regs(env, 0); if (ret < 0) { From a1fcaa73b1be5d8f0c6682d0f8d268f6e3194ead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 2 May 2012 23:42:26 +0200 Subject: [PATCH 1336/2270] cpus: Pass CPUState to cpu_can_run() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPUArchState is no longer needed there. Also change its return type to bool. Signed-off-by: Andreas Färber --- cpus.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/cpus.c b/cpus.c index 0721a96831..45877ee838 100644 --- a/cpus.c +++ b/cpus.c @@ -448,17 +448,15 @@ static void do_vm_stop(RunState state) } } -static int cpu_can_run(CPUArchState *env) +static bool cpu_can_run(CPUState *cpu) { - CPUState *cpu = ENV_GET_CPU(env); - if (cpu->stop) { - return 0; + return false; } if (cpu->stopped || !runstate_is_running()) { - return 0; + return false; } - return 1; + return true; } static void cpu_handle_guest_debug(CPUArchState *env) @@ -756,7 +754,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg) qemu_cond_signal(&qemu_cpu_cond); while (1) { - if (cpu_can_run(env)) { + if (cpu_can_run(cpu)) { r = kvm_cpu_exec(env); if (r == EXCP_DEBUG) { cpu_handle_guest_debug(env); @@ -1153,7 +1151,7 @@ static void tcg_exec_all(void) qemu_clock_enable(vm_clock, (env->singlestep_enabled & SSTEP_NOTIMER) == 0); - if (cpu_can_run(env)) { + if (cpu_can_run(cpu)) { r = tcg_cpu_exec(env); if (r == EXCP_DEBUG) { cpu_handle_guest_debug(env); From f5c121b85832f69fde5ad8939274e04ad21c1bd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 01:22:49 +0200 Subject: [PATCH 1337/2270] cpu: Move halt_cond to CPUState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- cpu-defs.h | 1 - cpus.c | 22 ++++++++++++---------- include/qemu/cpu.h | 1 + 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/cpu-defs.h b/cpu-defs.h index 83bf1089a6..76c76f6c62 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -205,7 +205,6 @@ typedef struct CPUWatchpoint { /* user data */ \ void *opaque; \ \ - struct QemuCond *halt_cond; \ struct qemu_work_item *queued_work_first, *queued_work_last; \ const char *cpu_model_str; \ struct KVMState *kvm_state; \ diff --git a/cpus.c b/cpus.c index 45877ee838..5a80bfa984 100644 --- a/cpus.c +++ b/cpus.c @@ -722,8 +722,10 @@ static void qemu_tcg_wait_io_event(void) static void qemu_kvm_wait_io_event(CPUArchState *env) { + CPUState *cpu = ENV_GET_CPU(env); + while (cpu_thread_is_idle(env)) { - qemu_cond_wait(env->halt_cond, &qemu_global_mutex); + qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex); } qemu_kvm_eat_signals(env); @@ -873,7 +875,7 @@ void qemu_cpu_kick(void *_env) CPUArchState *env = _env; CPUState *cpu = ENV_GET_CPU(env); - qemu_cond_broadcast(env->halt_cond); + qemu_cond_broadcast(cpu->halt_cond); if (!tcg_enabled() && !cpu->thread_kicked) { qemu_cpu_kick_thread(cpu); cpu->thread_kicked = true; @@ -997,9 +999,9 @@ static void qemu_tcg_init_vcpu(void *_env) /* share a single thread for all cpus with TCG */ if (!tcg_cpu_thread) { cpu->thread = g_malloc0(sizeof(QemuThread)); - env->halt_cond = g_malloc0(sizeof(QemuCond)); - qemu_cond_init(env->halt_cond); - tcg_halt_cond = env->halt_cond; + cpu->halt_cond = g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); + tcg_halt_cond = cpu->halt_cond; qemu_thread_create(cpu->thread, qemu_tcg_cpu_thread_fn, env, QEMU_THREAD_JOINABLE); #ifdef _WIN32 @@ -1011,7 +1013,7 @@ static void qemu_tcg_init_vcpu(void *_env) tcg_cpu_thread = cpu->thread; } else { cpu->thread = tcg_cpu_thread; - env->halt_cond = tcg_halt_cond; + cpu->halt_cond = tcg_halt_cond; } } @@ -1020,8 +1022,8 @@ static void qemu_kvm_start_vcpu(CPUArchState *env) CPUState *cpu = ENV_GET_CPU(env); cpu->thread = g_malloc0(sizeof(QemuThread)); - env->halt_cond = g_malloc0(sizeof(QemuCond)); - qemu_cond_init(env->halt_cond); + cpu->halt_cond = g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); qemu_thread_create(cpu->thread, qemu_kvm_cpu_thread_fn, env, QEMU_THREAD_JOINABLE); while (!cpu->created) { @@ -1034,8 +1036,8 @@ static void qemu_dummy_start_vcpu(CPUArchState *env) CPUState *cpu = ENV_GET_CPU(env); cpu->thread = g_malloc0(sizeof(QemuThread)); - env->halt_cond = g_malloc0(sizeof(QemuCond)); - qemu_cond_init(env->halt_cond); + cpu->halt_cond = g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); qemu_thread_create(cpu->thread, qemu_dummy_cpu_thread_fn, env, QEMU_THREAD_JOINABLE); while (!cpu->created) { diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h index 4e62032463..75e0f8dc68 100644 --- a/include/qemu/cpu.h +++ b/include/qemu/cpu.h @@ -69,6 +69,7 @@ struct CPUState { #ifdef _WIN32 HANDLE hThread; #endif + struct QemuCond *halt_cond; bool thread_kicked; bool created; bool stop; From c3586ba73fd4523a38c658f730cc38ec17b60491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 01:41:24 +0200 Subject: [PATCH 1338/2270] cpus: Pass CPUState to qemu_tcg_cpu_thread_fn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPUArchState is no longer needed except for iterating the CPUs. Needed for qemu_tcg_init_vcpu(). KVM and dummy threads still need CPUArchState for cpu_single_env. Signed-off-by: Andreas Färber --- cpus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpus.c b/cpus.c index 5a80bfa984..068fa12287 100644 --- a/cpus.c +++ b/cpus.c @@ -815,8 +815,8 @@ static void tcg_exec_all(void); static void *qemu_tcg_cpu_thread_fn(void *arg) { - CPUArchState *env = arg; - CPUState *cpu = ENV_GET_CPU(env); + CPUState *cpu = arg; + CPUArchState *env; qemu_tcg_init_cpu_signals(); qemu_thread_get_self(cpu->thread); @@ -1002,7 +1002,7 @@ static void qemu_tcg_init_vcpu(void *_env) cpu->halt_cond = g_malloc0(sizeof(QemuCond)); qemu_cond_init(cpu->halt_cond); tcg_halt_cond = cpu->halt_cond; - qemu_thread_create(cpu->thread, qemu_tcg_cpu_thread_fn, env, + qemu_thread_create(cpu->thread, qemu_tcg_cpu_thread_fn, cpu, QEMU_THREAD_JOINABLE); #ifdef _WIN32 cpu->hThread = qemu_thread_get_handle(cpu->thread); From e5ab30a2e6ee5f649af0639f93b6e8f6587e7ba1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 01:50:44 +0200 Subject: [PATCH 1339/2270] cpus: Pass CPUState to qemu_tcg_init_vcpu() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPUArchState is no longer needed. Signed-off-by: Andreas Färber --- cpus.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cpus.c b/cpus.c index 068fa12287..5f915239ac 100644 --- a/cpus.c +++ b/cpus.c @@ -991,11 +991,8 @@ void resume_all_vcpus(void) } } -static void qemu_tcg_init_vcpu(void *_env) +static void qemu_tcg_init_vcpu(CPUState *cpu) { - CPUArchState *env = _env; - CPUState *cpu = ENV_GET_CPU(env); - /* share a single thread for all cpus with TCG */ if (!tcg_cpu_thread) { cpu->thread = g_malloc0(sizeof(QemuThread)); @@ -1056,7 +1053,7 @@ void qemu_init_vcpu(void *_env) if (kvm_enabled()) { qemu_kvm_start_vcpu(env); } else if (tcg_enabled()) { - qemu_tcg_init_vcpu(env); + qemu_tcg_init_vcpu(cpu); } else { qemu_dummy_start_vcpu(env); } From a096124571b71f02d49a97ca99f4bf7b97b6912a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 02:48:44 +0200 Subject: [PATCH 1340/2270] ppc: Pass PowerPCCPU to {ppc6xx,ppc970,power7,ppc40x,ppce500}_set_irq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for changing qemu_cpu_kick() argument type to CPUState and for moving halted field into CPUState. Signed-off-by: Andreas Färber --- hw/ppc.c | 55 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/hw/ppc.c b/hw/ppc.c index 98546de991..ada100b1c5 100644 --- a/hw/ppc.c +++ b/hw/ppc.c @@ -75,9 +75,10 @@ void ppc_set_irq(CPUPPCState *env, int n_IRQ, int level) } /* PowerPC 6xx / 7xx internal IRQ controller */ -static void ppc6xx_set_irq (void *opaque, int pin, int level) +static void ppc6xx_set_irq(void *opaque, int pin, int level) { - CPUPPCState *env = opaque; + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; int cur_level; LOG_IRQ("%s: env %p pin %d level %d\n", __func__, @@ -151,17 +152,20 @@ static void ppc6xx_set_irq (void *opaque, int pin, int level) } } -void ppc6xx_irq_init (CPUPPCState *env) +void ppc6xx_irq_init(CPUPPCState *env) { - env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, + PowerPCCPU *cpu = ppc_env_get_cpu(env); + + env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, cpu, PPC6xx_INPUT_NB); } #if defined(TARGET_PPC64) /* PowerPC 970 internal IRQ controller */ -static void ppc970_set_irq (void *opaque, int pin, int level) +static void ppc970_set_irq(void *opaque, int pin, int level) { - CPUPPCState *env = opaque; + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; int cur_level; LOG_IRQ("%s: env %p pin %d level %d\n", __func__, @@ -233,16 +237,19 @@ static void ppc970_set_irq (void *opaque, int pin, int level) } } -void ppc970_irq_init (CPUPPCState *env) +void ppc970_irq_init(CPUPPCState *env) { - env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env, + PowerPCCPU *cpu = ppc_env_get_cpu(env); + + env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, cpu, PPC970_INPUT_NB); } /* POWER7 internal IRQ controller */ -static void power7_set_irq (void *opaque, int pin, int level) +static void power7_set_irq(void *opaque, int pin, int level) { - CPUPPCState *env = opaque; + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; LOG_IRQ("%s: env %p pin %d level %d\n", __func__, env, pin, level); @@ -266,17 +273,20 @@ static void power7_set_irq (void *opaque, int pin, int level) } } -void ppcPOWER7_irq_init (CPUPPCState *env) +void ppcPOWER7_irq_init(CPUPPCState *env) { - env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, env, + PowerPCCPU *cpu = ppc_env_get_cpu(env); + + env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, cpu, POWER7_INPUT_NB); } #endif /* defined(TARGET_PPC64) */ /* PowerPC 40x internal IRQ controller */ -static void ppc40x_set_irq (void *opaque, int pin, int level) +static void ppc40x_set_irq(void *opaque, int pin, int level) { - CPUPPCState *env = opaque; + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; int cur_level; LOG_IRQ("%s: env %p pin %d level %d\n", __func__, @@ -346,16 +356,19 @@ static void ppc40x_set_irq (void *opaque, int pin, int level) } } -void ppc40x_irq_init (CPUPPCState *env) +void ppc40x_irq_init(CPUPPCState *env) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); + env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq, - env, PPC40x_INPUT_NB); + cpu, PPC40x_INPUT_NB); } /* PowerPC E500 internal IRQ controller */ -static void ppce500_set_irq (void *opaque, int pin, int level) +static void ppce500_set_irq(void *opaque, int pin, int level) { - CPUPPCState *env = opaque; + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; int cur_level; LOG_IRQ("%s: env %p pin %d level %d\n", __func__, @@ -407,10 +420,12 @@ static void ppce500_set_irq (void *opaque, int pin, int level) } } -void ppce500_irq_init (CPUPPCState *env) +void ppce500_irq_init(CPUPPCState *env) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); + env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq, - env, PPCE500_INPUT_NB); + cpu, PPCE500_INPUT_NB); } /*****************************************************************************/ /* PowerPC time base and decrementer emulation */ From d5a6814697014561dd0a2e2871df0e6c62a0ce59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 04:02:03 +0200 Subject: [PATCH 1341/2270] target-ppc: Rename kvm_kick_{env => cpu} and pass PowerPCCPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for changing qemu_cpu_kick() argument type to CPUState. Signed-off-by: Andreas Färber --- target-ppc/kvm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 5cbe98a164..d7d8e8fef0 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -73,8 +73,11 @@ static int cap_hior; */ static QEMUTimer *idle_timer; -static void kvm_kick_env(void *env) +static void kvm_kick_cpu(void *opaque) { + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; + qemu_cpu_kick(env); } @@ -375,6 +378,7 @@ static inline void kvm_fixup_page_sizes(CPUPPCState *env) int kvm_arch_init_vcpu(CPUPPCState *cenv) { + PowerPCCPU *cpu = ppc_env_get_cpu(cenv); int ret; /* Gather server mmu info from KVM and update the CPU state */ @@ -386,7 +390,7 @@ int kvm_arch_init_vcpu(CPUPPCState *cenv) return ret; } - idle_timer = qemu_new_timer_ns(vm_clock, kvm_kick_env, cenv); + idle_timer = qemu_new_timer_ns(vm_clock, kvm_kick_cpu, cpu); /* Some targets support access to KVM's guest TLB. */ switch (cenv->mmu_model) { From c08d7424d600dce915a5506e95d55a359c243c66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 04:34:15 +0200 Subject: [PATCH 1342/2270] cpus: Pass CPUState to qemu_cpu_kick() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPUArchState is no longer needed there. Signed-off-by: Andreas Färber --- cpus.c | 13 +++++-------- exec.c | 2 +- hw/ppc.c | 4 ++-- hw/ppce500_spin.c | 2 +- hw/spapr_rtas.c | 5 ++++- hw/sun4m.c | 2 +- hw/sun4u.c | 2 +- include/qemu/cpu.h | 8 ++++++++ kvm-all.c | 2 +- qemu-common.h | 1 - target-ppc/kvm.c | 3 +-- target-s390x/kvm.c | 2 +- 12 files changed, 26 insertions(+), 20 deletions(-) diff --git a/cpus.c b/cpus.c index 5f915239ac..b802d38885 100644 --- a/cpus.c +++ b/cpus.c @@ -661,7 +661,7 @@ void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data) wi.next = NULL; wi.done = false; - qemu_cpu_kick(env); + qemu_cpu_kick(cpu); while (!wi.done) { CPUArchState *self_env = cpu_single_env; @@ -870,11 +870,8 @@ static void qemu_cpu_kick_thread(CPUState *cpu) #endif } -void qemu_cpu_kick(void *_env) +void qemu_cpu_kick(CPUState *cpu) { - CPUArchState *env = _env; - CPUState *cpu = ENV_GET_CPU(env); - qemu_cond_broadcast(cpu->halt_cond); if (!tcg_enabled() && !cpu->thread_kicked) { qemu_cpu_kick_thread(cpu); @@ -950,7 +947,7 @@ void pause_all_vcpus(void) while (penv) { CPUState *pcpu = ENV_GET_CPU(penv); pcpu->stop = true; - qemu_cpu_kick(penv); + qemu_cpu_kick(pcpu); penv = penv->next_cpu; } @@ -971,7 +968,7 @@ void pause_all_vcpus(void) qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex); penv = first_cpu; while (penv) { - qemu_cpu_kick(penv); + qemu_cpu_kick(ENV_GET_CPU(penv)); penv = penv->next_cpu; } } @@ -986,7 +983,7 @@ void resume_all_vcpus(void) CPUState *pcpu = ENV_GET_CPU(penv); pcpu->stop = false; pcpu->stopped = false; - qemu_cpu_kick(penv); + qemu_cpu_kick(pcpu); penv = penv->next_cpu; } } diff --git a/exec.c b/exec.c index a85a9b1fd2..038e40d09b 100644 --- a/exec.c +++ b/exec.c @@ -1704,7 +1704,7 @@ static void tcg_handle_interrupt(CPUArchState *env, int mask) * case its halted. */ if (!qemu_cpu_is_self(cpu)) { - qemu_cpu_kick(env); + qemu_cpu_kick(cpu); return; } diff --git a/hw/ppc.c b/hw/ppc.c index ada100b1c5..fa7ae74f0d 100644 --- a/hw/ppc.c +++ b/hw/ppc.c @@ -206,7 +206,7 @@ static void ppc970_set_irq(void *opaque, int pin, int level) } else { LOG_IRQ("%s: restart the CPU\n", __func__); env->halted = 0; - qemu_cpu_kick(env); + qemu_cpu_kick(CPU(cpu)); } break; case PPC970_INPUT_HRESET: @@ -335,7 +335,7 @@ static void ppc40x_set_irq(void *opaque, int pin, int level) } else { LOG_IRQ("%s: restart the CPU\n", __func__); env->halted = 0; - qemu_cpu_kick(env); + qemu_cpu_kick(CPU(cpu)); } break; case PPC40x_INPUT_DEBUG: diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c index fb5461d588..7f8c8428b6 100644 --- a/hw/ppce500_spin.c +++ b/hw/ppce500_spin.c @@ -115,7 +115,7 @@ static void spin_kick(void *data) env->halted = 0; env->exception_index = -1; cpu->stopped = false; - qemu_cpu_kick(env); + qemu_cpu_kick(cpu); } static void spin_write(void *opaque, hwaddr addr, uint64_t value, diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c index ce76c5856a..6d5c48a740 100644 --- a/hw/spapr_rtas.c +++ b/hw/spapr_rtas.c @@ -163,6 +163,7 @@ static void rtas_start_cpu(sPAPREnvironment *spapr, uint32_t nret, target_ulong rets) { target_ulong id, start, r3; + CPUState *cpu; CPUPPCState *env; if (nargs != 3 || nret != 1) { @@ -175,6 +176,8 @@ static void rtas_start_cpu(sPAPREnvironment *spapr, r3 = rtas_ld(args, 2); for (env = first_cpu; env; env = env->next_cpu) { + cpu = ENV_GET_CPU(env); + if (env->cpu_index != id) { continue; } @@ -194,7 +197,7 @@ static void rtas_start_cpu(sPAPREnvironment *spapr, env->gpr[3] = r3; env->halted = 0; - qemu_cpu_kick(env); + qemu_cpu_kick(cpu); rtas_st(rets, 0, 0); return; diff --git a/hw/sun4m.c b/hw/sun4m.c index 02673b228e..1a786762aa 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -259,7 +259,7 @@ static void cpu_kick_irq(SPARCCPU *cpu) env->halted = 0; cpu_check_irqs(env); - qemu_cpu_kick(env); + qemu_cpu_kick(CPU(cpu)); } static void cpu_set_irq(void *opaque, int irq, int level) diff --git a/hw/sun4u.c b/hw/sun4u.c index 162117129c..b2b51e30c2 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -317,7 +317,7 @@ static void cpu_kick_irq(SPARCCPU *cpu) env->halted = 0; cpu_check_irqs(env); - qemu_cpu_kick(env); + qemu_cpu_kick(CPU(cpu)); } static void cpu_set_ivec_irq(void *opaque, int irq, int level) diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h index 75e0f8dc68..bfeb2245ab 100644 --- a/include/qemu/cpu.h +++ b/include/qemu/cpu.h @@ -95,6 +95,14 @@ void cpu_reset(CPUState *cpu); */ bool qemu_cpu_is_self(CPUState *cpu); +/** + * qemu_cpu_kick: + * @cpu: The vCPU to kick. + * + * Kicks @cpu's thread. + */ +void qemu_cpu_kick(CPUState *cpu); + /** * cpu_is_stopped: * @cpu: The CPU to check. diff --git a/kvm-all.c b/kvm-all.c index 74d2652f02..e41e1c9531 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -833,7 +833,7 @@ static void kvm_handle_interrupt(CPUArchState *env, int mask) env->interrupt_request |= mask; if (!qemu_cpu_is_self(cpu)) { - qemu_cpu_kick(env); + qemu_cpu_kick(cpu); } } diff --git a/qemu-common.h b/qemu-common.h index 2094742f2b..2011c00fe2 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -324,7 +324,6 @@ void cpu_save(QEMUFile *f, void *opaque); int cpu_load(QEMUFile *f, void *opaque, int version_id); /* Unblock cpu */ -void qemu_cpu_kick(void *env); void qemu_cpu_kick_self(void); /* work queue */ diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index d7d8e8fef0..6aacff0624 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -76,9 +76,8 @@ static QEMUTimer *idle_timer; static void kvm_kick_cpu(void *opaque) { PowerPCCPU *cpu = opaque; - CPUPPCState *env = &cpu->env; - qemu_cpu_kick(env); + qemu_cpu_kick(CPU(cpu)); } int kvm_arch_init(KVMState *s) diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index a66ac4341c..94de764264 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -403,7 +403,7 @@ static int s390_cpu_restart(S390CPU *cpu) kvm_s390_interrupt(env, KVM_S390_RESTART, 0); s390_add_running_cpu(env); - qemu_cpu_kick(env); + qemu_cpu_kick(CPU(cpu)); dprintf("DONE: SIGP cpu restart: %p\n", env); return 0; } From c64ca8140e9c21cd0d44c10fbe1247cb4ade8e6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 02:11:45 +0200 Subject: [PATCH 1343/2270] cpu: Move queued_work_{first,last} to CPUState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- cpu-defs.h | 1 - cpus.c | 19 ++++++++++--------- include/qemu/cpu.h | 1 + 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/cpu-defs.h b/cpu-defs.h index 76c76f6c62..b30a8e91bb 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -205,7 +205,6 @@ typedef struct CPUWatchpoint { /* user data */ \ void *opaque; \ \ - struct qemu_work_item *queued_work_first, *queued_work_last; \ const char *cpu_model_str; \ struct KVMState *kvm_state; \ struct kvm_run *kvm_run; \ diff --git a/cpus.c b/cpus.c index b802d38885..307c1f286c 100644 --- a/cpus.c +++ b/cpus.c @@ -66,7 +66,7 @@ static bool cpu_thread_is_idle(CPUArchState *env) { CPUState *cpu = ENV_GET_CPU(env); - if (cpu->stop || env->queued_work_first) { + if (cpu->stop || cpu->queued_work_first) { return false; } if (cpu->stopped || !runstate_is_running()) { @@ -652,12 +652,12 @@ void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data) wi.func = func; wi.data = data; - if (!env->queued_work_first) { - env->queued_work_first = &wi; + if (cpu->queued_work_first == NULL) { + cpu->queued_work_first = &wi; } else { - env->queued_work_last->next = &wi; + cpu->queued_work_last->next = &wi; } - env->queued_work_last = &wi; + cpu->queued_work_last = &wi; wi.next = NULL; wi.done = false; @@ -672,18 +672,19 @@ void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data) static void flush_queued_work(CPUArchState *env) { + CPUState *cpu = ENV_GET_CPU(env); struct qemu_work_item *wi; - if (!env->queued_work_first) { + if (cpu->queued_work_first == NULL) { return; } - while ((wi = env->queued_work_first)) { - env->queued_work_first = wi->next; + while ((wi = cpu->queued_work_first)) { + cpu->queued_work_first = wi->next; wi->func(wi->data); wi->done = true; } - env->queued_work_last = NULL; + cpu->queued_work_last = NULL; qemu_cond_broadcast(&qemu_work_cond); } diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h index bfeb2245ab..eea6175cb9 100644 --- a/include/qemu/cpu.h +++ b/include/qemu/cpu.h @@ -70,6 +70,7 @@ struct CPUState { HANDLE hThread; #endif struct QemuCond *halt_cond; + struct qemu_work_item *queued_work_first, *queued_work_last; bool thread_kicked; bool created; bool stop; From 6d45b109a6869084abd0f9aba01fa5107e926b60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 02:13:22 +0200 Subject: [PATCH 1344/2270] cpus: Pass CPUState to flush_queued_work() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPUArchState is no longer needed there. Signed-off-by: Andreas Färber --- cpus.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cpus.c b/cpus.c index 307c1f286c..e40823c6f1 100644 --- a/cpus.c +++ b/cpus.c @@ -670,9 +670,8 @@ void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data) } } -static void flush_queued_work(CPUArchState *env) +static void flush_queued_work(CPUState *cpu) { - CPUState *cpu = ENV_GET_CPU(env); struct qemu_work_item *wi; if (cpu->queued_work_first == NULL) { @@ -697,7 +696,7 @@ static void qemu_wait_io_event_common(CPUArchState *env) cpu->stopped = true; qemu_cond_signal(&qemu_pause_cond); } - flush_queued_work(env); + flush_queued_work(cpu); cpu->thread_kicked = false; } From 509a0d78c7c3927b9ec8e176abef09ddd28ff0b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 02:18:09 +0200 Subject: [PATCH 1345/2270] cpus: Pass CPUState to qemu_wait_io_event_common() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPUArchState is no longer needed there. Signed-off-by: Andreas Färber --- cpus.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/cpus.c b/cpus.c index e40823c6f1..6baf2bcb35 100644 --- a/cpus.c +++ b/cpus.c @@ -687,10 +687,8 @@ static void flush_queued_work(CPUState *cpu) qemu_cond_broadcast(&qemu_work_cond); } -static void qemu_wait_io_event_common(CPUArchState *env) +static void qemu_wait_io_event_common(CPUState *cpu) { - CPUState *cpu = ENV_GET_CPU(env); - if (cpu->stop) { cpu->stop = false; cpu->stopped = true; @@ -716,7 +714,7 @@ static void qemu_tcg_wait_io_event(void) } for (env = first_cpu; env != NULL; env = env->next_cpu) { - qemu_wait_io_event_common(env); + qemu_wait_io_event_common(ENV_GET_CPU(env)); } } @@ -729,7 +727,7 @@ static void qemu_kvm_wait_io_event(CPUArchState *env) } qemu_kvm_eat_signals(env); - qemu_wait_io_event_common(env); + qemu_wait_io_event_common(cpu); } static void *qemu_kvm_cpu_thread_fn(void *arg) @@ -804,7 +802,7 @@ static void *qemu_dummy_cpu_thread_fn(void *arg) } qemu_mutex_lock_iothread(); cpu_single_env = env; - qemu_wait_io_event_common(env); + qemu_wait_io_event_common(cpu); } return NULL; @@ -836,7 +834,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) /* process any pending work */ for (env = first_cpu; env != NULL; env = env->next_cpu) { - qemu_wait_io_event_common(env); + qemu_wait_io_event_common(ENV_GET_CPU(env)); } } From 79bbf20bcaf2ee5d8e3f93a5151d992fc9a5fd89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 06:41:02 +0200 Subject: [PATCH 1346/2270] xtensa_pic: Pass XtensaCPU to xtensa_ccompare_cb() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for changing cpu_has_work() argument type to CPUState. Signed-off-by: Andreas Färber Acked-by: Max Filippov --- hw/xtensa_pic.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c index 653ded6820..8b9c0510f9 100644 --- a/hw/xtensa_pic.c +++ b/hw/xtensa_pic.c @@ -125,7 +125,8 @@ void xtensa_rearm_ccompare_timer(CPUXtensaState *env) static void xtensa_ccompare_cb(void *opaque) { - CPUXtensaState *env = opaque; + XtensaCPU *cpu = opaque; + CPUXtensaState *env = &cpu->env; if (env->halted) { env->halt_clock = qemu_get_clock_ns(vm_clock); @@ -139,12 +140,14 @@ static void xtensa_ccompare_cb(void *opaque) void xtensa_irq_init(CPUXtensaState *env) { + XtensaCPU *cpu = xtensa_env_get_cpu(env); + env->irq_inputs = (void **)qemu_allocate_irqs( xtensa_set_irq, env, env->config->ninterrupt); if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT) && env->config->nccompare > 0) { env->ccompare_timer = - qemu_new_timer_ns(vm_clock, &xtensa_ccompare_cb, env); + qemu_new_timer_ns(vm_clock, &xtensa_ccompare_cb, cpu); } } From 5c26a5b3033fbbbfc033f7d8d0b50713c31517d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 05:55:58 +0200 Subject: [PATCH 1347/2270] target-ppc: Pass PowerPCCPU to powerpc_excp() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for changing cpu_ppc_hypercall() argument type to PowerPCCPU. Signed-off-by: Andreas Färber --- target-ppc/excp_helper.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c index 1a593f6f3f..d19a46b364 100644 --- a/target-ppc/excp_helper.c +++ b/target-ppc/excp_helper.c @@ -63,8 +63,9 @@ static inline void dump_syscall(CPUPPCState *env) /* Note that this function should be greatly optimized * when called with a constant excp, from ppc_hw_interrupt */ -static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) +static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) { + CPUPPCState *env = &cpu->env; target_ulong msr, new_msr, vector; int srr0, srr1, asrr0, asrr1; int lpes0, lpes1, lev; @@ -643,11 +644,14 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) void do_interrupt(CPUPPCState *env) { - powerpc_excp(env, env->excp_model, env->exception_index); + PowerPCCPU *cpu = ppc_env_get_cpu(env); + + powerpc_excp(cpu, env->excp_model, env->exception_index); } void ppc_hw_interrupt(CPUPPCState *env) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); int hdice; #if 0 @@ -658,20 +662,20 @@ void ppc_hw_interrupt(CPUPPCState *env) /* External reset */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); return; } /* Machine check exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK); return; } #if 0 /* TODO */ /* External debug exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG); return; } #endif @@ -685,7 +689,7 @@ void ppc_hw_interrupt(CPUPPCState *env) /* Hypervisor decrementer exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR); return; } } @@ -698,7 +702,7 @@ void ppc_hw_interrupt(CPUPPCState *env) #if 0 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT); #endif - powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL); return; } } @@ -706,30 +710,30 @@ void ppc_hw_interrupt(CPUPPCState *env) /* Watchdog timer on embedded PowerPC */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT); return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI); return; } /* Fixed interval timer on embedded PowerPC */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT); return; } /* Programmable interval timer on embedded PowerPC */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT); return; } /* Decrementer exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR); return; } /* External interrupt */ @@ -740,23 +744,23 @@ void ppc_hw_interrupt(CPUPPCState *env) #if 0 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT); #endif - powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL); return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI); return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM); return; } /* Thermal interrupt */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM); return; } } From 1b14670a38a2265d3dd573b5e2d611621a5929f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 06:03:45 +0200 Subject: [PATCH 1348/2270] target-ppc: Pass PowerPCCPU to cpu_ppc_hypercall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adapt emulate_spapr_hypercall() accordingly. Needed for changing spapr_hypercall() argument type to PowerPCCPU. Signed-off-by: Andreas Färber --- hw/spapr.c | 4 +++- target-ppc/cpu.h | 2 +- target-ppc/excp_helper.c | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 8d0ad3cfe9..30707eecaf 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -576,8 +576,10 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr) return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR; } -static void emulate_spapr_hypercall(CPUPPCState *env) +static void emulate_spapr_hypercall(PowerPCCPU *cpu) { + CPUPPCState *env = &cpu->env; + if (msr_pr) { hcall_dprintf("Hypercall made with MSR[PR]=1\n"); env->gpr[3] = H_PRIVILEGE; diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 286f42a808..5574042a87 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -2220,7 +2220,7 @@ static inline bool msr_is_64bit(CPUPPCState *env, target_ulong msr) return msr & (1ULL << MSR_SF); } -extern void (*cpu_ppc_hypercall)(CPUPPCState *); +extern void (*cpu_ppc_hypercall)(PowerPCCPU *); static inline bool cpu_has_work(CPUPPCState *env) { diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c index d19a46b364..5e34ad08a8 100644 --- a/target-ppc/excp_helper.c +++ b/target-ppc/excp_helper.c @@ -33,7 +33,7 @@ /*****************************************************************************/ /* PowerPC Hypercall emulation */ -void (*cpu_ppc_hypercall)(CPUPPCState *); +void (*cpu_ppc_hypercall)(PowerPCCPU *); /*****************************************************************************/ /* Exception processing */ @@ -239,7 +239,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) dump_syscall(env); lev = env->error_code; if ((lev == 1) && cpu_ppc_hypercall) { - cpu_ppc_hypercall(env); + cpu_ppc_hypercall(cpu); return; } if (lev == 1 || (lpes0 == 0 && lpes1 == 0)) { From aa100fa4c9901c6a88d24f48d485dbe0147b317d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 06:13:14 +0200 Subject: [PATCH 1349/2270] spapr: Pass PowerPCCPU to spapr_hypercall() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for changing the hypercall handlers' argument type to PowerPCCPU. Signed-off-by: Andreas Färber --- hw/spapr.c | 2 +- hw/spapr.h | 2 +- hw/spapr_hcall.c | 4 +++- target-ppc/kvm.c | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 30707eecaf..ad3f0ea7fc 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -584,7 +584,7 @@ static void emulate_spapr_hypercall(PowerPCCPU *cpu) hcall_dprintf("Hypercall made with MSR[PR]=1\n"); env->gpr[3] = H_PRIVILEGE; } else { - env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]); + env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]); } } diff --git a/hw/spapr.h b/hw/spapr.h index 51c709ea10..f11028de9a 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -291,7 +291,7 @@ typedef target_ulong (*spapr_hcall_fn)(CPUPPCState *env, sPAPREnvironment *spapr target_ulong *args); void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn); -target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode, +target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode, target_ulong *args); int spapr_allocate_irq(int hint, bool lsi); diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c index 621dabdfb1..b1e8704775 100644 --- a/hw/spapr_hcall.c +++ b/hw/spapr_hcall.c @@ -679,9 +679,11 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn) *slot = fn; } -target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode, +target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode, target_ulong *args) { + CPUPPCState *env = &cpu->env; + if ((opcode <= MAX_HCALL_OPCODE) && ((opcode & 0x3) == 0)) { spapr_hcall_fn fn = papr_hypercall_table[opcode / 4]; diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 6aacff0624..3f5df5772f 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -817,7 +817,8 @@ int kvm_arch_handle_exit(CPUPPCState *env, struct kvm_run *run) #ifdef CONFIG_PSERIES case KVM_EXIT_PAPR_HCALL: dprintf("handle PAPR hypercall\n"); - run->papr_hcall.ret = spapr_hypercall(env, run->papr_hcall.nr, + run->papr_hcall.ret = spapr_hypercall(ppc_env_get_cpu(env), + run->papr_hcall.nr, run->papr_hcall.args); ret = 0; break; From b13ce26d3e8c6682044ae84920f2417b30ce356b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 06:23:01 +0200 Subject: [PATCH 1350/2270] spapr: Pass PowerPCCPU to hypercalls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for changing cpu_has_work() argument type to CPUState, used in h_cede(). Signed-off-by: Andreas Färber --- hw/spapr.h | 2 +- hw/spapr_hcall.c | 38 +++++++++++++++++++++----------------- hw/spapr_iommu.c | 2 +- hw/spapr_llan.c | 10 +++++----- hw/spapr_vio.c | 10 +++++----- hw/spapr_vty.c | 4 ++-- hw/xics.c | 11 +++++++---- 7 files changed, 42 insertions(+), 35 deletions(-) diff --git a/hw/spapr.h b/hw/spapr.h index f11028de9a..efe7f5758f 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -286,7 +286,7 @@ extern sPAPREnvironment *spapr; do { } while (0) #endif -typedef target_ulong (*spapr_hcall_fn)(CPUPPCState *env, sPAPREnvironment *spapr, +typedef target_ulong (*spapr_hcall_fn)(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args); diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c index b1e8704775..c6d55da7a6 100644 --- a/hw/spapr_hcall.c +++ b/hw/spapr_hcall.c @@ -75,9 +75,10 @@ static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r, return rb; } -static target_ulong h_enter(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { + CPUPPCState *env = &cpu->env; target_ulong flags = args[0]; target_ulong pte_index = args[1]; target_ulong pteh = args[2]; @@ -192,9 +193,10 @@ static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex, return REMOVE_SUCCESS; } -static target_ulong h_remove(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { + CPUPPCState *env = &cpu->env; target_ulong flags = args[0]; target_ulong pte_index = args[1]; target_ulong avpn = args[2]; @@ -238,9 +240,10 @@ static target_ulong h_remove(CPUPPCState *env, sPAPREnvironment *spapr, #define H_BULK_REMOVE_MAX_BATCH 4 -static target_ulong h_bulk_remove(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { + CPUPPCState *env = &cpu->env; int i; for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) { @@ -284,9 +287,10 @@ static target_ulong h_bulk_remove(CPUPPCState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -static target_ulong h_protect(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { + CPUPPCState *env = &cpu->env; target_ulong flags = args[0]; target_ulong pte_index = args[1]; target_ulong avpn = args[2]; @@ -321,7 +325,7 @@ static target_ulong h_protect(CPUPPCState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -static target_ulong h_set_dabr(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_set_dabr(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { /* FIXME: actually implement this */ @@ -457,7 +461,7 @@ static target_ulong deregister_dtl(CPUPPCState *env, target_ulong addr) return H_SUCCESS; } -static target_ulong h_register_vpa(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_register_vpa(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong flags = args[0]; @@ -505,9 +509,11 @@ static target_ulong h_register_vpa(CPUPPCState *env, sPAPREnvironment *spapr, return ret; } -static target_ulong h_cede(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { + CPUPPCState *env = &cpu->env; + env->msr |= (1ULL << MSR_EE); hreg_compute_hflags(env); if (!cpu_has_work(env)) { @@ -518,7 +524,7 @@ static target_ulong h_cede(CPUPPCState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -static target_ulong h_rtas(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_rtas(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong rtas_r3 = args[0]; @@ -530,7 +536,7 @@ static target_ulong h_rtas(CPUPPCState *env, sPAPREnvironment *spapr, nret, rtas_r3 + 12 + 4*nargs); } -static target_ulong h_logical_load(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_logical_load(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong size = args[0]; @@ -553,7 +559,7 @@ static target_ulong h_logical_load(CPUPPCState *env, sPAPREnvironment *spapr, return H_PARAMETER; } -static target_ulong h_logical_store(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_logical_store(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong size = args[0]; @@ -577,7 +583,7 @@ static target_ulong h_logical_store(CPUPPCState *env, sPAPREnvironment *spapr, return H_PARAMETER; } -static target_ulong h_logical_memop(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_logical_memop(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong dst = args[0]; /* Destination address */ @@ -644,14 +650,14 @@ static target_ulong h_logical_memop(CPUPPCState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -static target_ulong h_logical_icbi(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_logical_icbi(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { /* Nothing to do on emulation, KVM will trap this in the kernel */ return H_SUCCESS; } -static target_ulong h_logical_dcbf(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { /* Nothing to do on emulation, KVM will trap this in the kernel */ @@ -682,21 +688,19 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn) target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode, target_ulong *args) { - CPUPPCState *env = &cpu->env; - if ((opcode <= MAX_HCALL_OPCODE) && ((opcode & 0x3) == 0)) { spapr_hcall_fn fn = papr_hypercall_table[opcode / 4]; if (fn) { - return fn(env, spapr, opcode, args); + return fn(cpu, spapr, opcode, args); } } else if ((opcode >= KVMPPC_HCALL_BASE) && (opcode <= KVMPPC_HCALL_MAX)) { spapr_hcall_fn fn = kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE]; if (fn) { - return fn(env, spapr, opcode, args); + return fn(cpu, spapr, opcode, args); } } diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c index 86dc8f92e2..02d78ccf28 100644 --- a/hw/spapr_iommu.c +++ b/hw/spapr_iommu.c @@ -204,7 +204,7 @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba, return H_SUCCESS; } -static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_put_tce(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong liobn = args[0]; diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c index bd3f131d7e..09ad69f6b5 100644 --- a/hw/spapr_llan.c +++ b/hw/spapr_llan.c @@ -264,7 +264,7 @@ static int check_bd(VIOsPAPRVLANDevice *dev, vlan_bd_t bd, return 0; } -static target_ulong h_register_logical_lan(CPUPPCState *env, +static target_ulong h_register_logical_lan(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) @@ -328,7 +328,7 @@ static target_ulong h_register_logical_lan(CPUPPCState *env, } -static target_ulong h_free_logical_lan(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_free_logical_lan(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; @@ -349,7 +349,7 @@ static target_ulong h_free_logical_lan(CPUPPCState *env, sPAPREnvironment *spapr return H_SUCCESS; } -static target_ulong h_add_logical_lan_buffer(CPUPPCState *env, +static target_ulong h_add_logical_lan_buffer(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) @@ -398,7 +398,7 @@ static target_ulong h_add_logical_lan_buffer(CPUPPCState *env, return H_SUCCESS; } -static target_ulong h_send_logical_lan(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_send_logical_lan(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; @@ -467,7 +467,7 @@ static target_ulong h_send_logical_lan(CPUPPCState *env, sPAPREnvironment *spapr return H_SUCCESS; } -static target_ulong h_multicast_ctrl(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_multicast_ctrl(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index 848806d3f1..1f19fedd0e 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -161,7 +161,7 @@ static int vio_make_devnode(VIOsPAPRDevice *dev, /* * CRQ handling */ -static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_reg_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; @@ -219,7 +219,7 @@ static target_ulong free_crq(VIOsPAPRDevice *dev) return H_SUCCESS; } -static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_free_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; @@ -233,7 +233,7 @@ static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr, return free_crq(dev); } -static target_ulong h_send_crq(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_send_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; @@ -256,7 +256,7 @@ static target_ulong h_send_crq(CPUPPCState *env, sPAPREnvironment *spapr, return H_HARDWARE; } -static target_ulong h_enable_crq(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_enable_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; @@ -463,7 +463,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev) return pc->init(dev); } -static target_ulong h_vio_signal(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_vio_signal(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c index 5da17a3ff4..14f862fba1 100644 --- a/hw/spapr_vty.c +++ b/hw/spapr_vty.c @@ -70,7 +70,7 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev) } /* Forward declaration */ -static target_ulong h_put_term_char(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_put_term_char(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; @@ -97,7 +97,7 @@ static target_ulong h_put_term_char(CPUPPCState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -static target_ulong h_get_term_char(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_get_term_char(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; diff --git a/hw/xics.c b/hw/xics.c index ce88aa750b..91e4e6bbf5 100644 --- a/hw/xics.c +++ b/hw/xics.c @@ -342,16 +342,17 @@ void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi) icp->ics->irqs[irq - icp->ics->offset].lsi = lsi; } -static target_ulong h_cppr(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { + CPUPPCState *env = &cpu->env; target_ulong cppr = args[0]; icp_set_cppr(spapr->icp, env->cpu_index, cppr); return H_SUCCESS; } -static target_ulong h_ipi(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_ipi(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong server = args[0]; @@ -366,18 +367,20 @@ static target_ulong h_ipi(CPUPPCState *env, sPAPREnvironment *spapr, } -static target_ulong h_xirr(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_xirr(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { + CPUPPCState *env = &cpu->env; uint32_t xirr = icp_accept(spapr->icp->ss + env->cpu_index); args[0] = xirr; return H_SUCCESS; } -static target_ulong h_eoi(CPUPPCState *env, sPAPREnvironment *spapr, +static target_ulong h_eoi(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { + CPUPPCState *env = &cpu->env; target_ulong xirr = args[0]; icp_eoi(spapr->icp, env->cpu_index, xirr); From 7b46e5ce81d5107927685e7645b1bd39a1e1cd63 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:48:53 -0300 Subject: [PATCH 1351/2270] i386: kvm: kvm_arch_get_supported_cpuid: move R_EDX hack outside of for loop The for loop will become a separate function, so clean it up so it can become independent from the bit hacking for R_EDX. No behavior change[1], just code movement. [1] Well, only if the kernel returned CPUID leafs 1 or 0x80000001 as unsupported, but there's no kernel version that does that. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 3aa62b20ff..b7490f92d9 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -155,24 +155,29 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, break; case R_EDX: ret = cpuid->entries[i].edx; - switch (function) { - case 1: - /* KVM before 2.6.30 misreports the following features */ - ret |= CPUID_MTRR | CPUID_PAT | CPUID_MCE | CPUID_MCA; - break; - case 0x80000001: - /* On Intel, kvm returns cpuid according to the Intel spec, - * so add missing bits according to the AMD spec: - */ - cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); - ret |= cpuid_1_edx & CPUID_EXT2_AMD_ALIASES; - break; - } break; } } } + /* Fixups for the data returned by KVM, below */ + + if (reg == R_EDX) { + switch (function) { + case 1: + /* KVM before 2.6.30 misreports the following features */ + ret |= CPUID_MTRR | CPUID_PAT | CPUID_MCE | CPUID_MCA; + break; + case 0x80000001: + /* On Intel, kvm returns cpuid according to the Intel spec, + * so add missing bits according to the AMD spec: + */ + cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); + ret |= cpuid_1_edx & CPUID_EXT2_AMD_ALIASES; + break; + } + } + g_free(cpuid); /* fallback for older kernels */ From 8c723b7958127b8f204dd4b278ad3c8f6f48ae17 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:48:54 -0300 Subject: [PATCH 1352/2270] i386: kvm: kvm_arch_get_supported_cpuid: clean up has_kvm_features check Instead of a function-specific has_kvm_features variable, simply use a "found" variable that will be checked in case we have to use the legacy get_para_features() interface. No behavior change, just code cleanup. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index b7490f92d9..56addf1866 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -130,7 +130,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, int i, max; uint32_t ret = 0; uint32_t cpuid_1_edx; - int has_kvm_features = 0; + bool found = false; max = 1; while ((cpuid = try_get_cpuid(s, max)) == NULL) { @@ -140,9 +140,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, for (i = 0; i < cpuid->nent; ++i) { if (cpuid->entries[i].function == function && cpuid->entries[i].index == index) { - if (cpuid->entries[i].function == KVM_CPUID_FEATURES) { - has_kvm_features = 1; - } + found = true; switch (reg) { case R_EAX: ret = cpuid->entries[i].eax; @@ -181,7 +179,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, g_free(cpuid); /* fallback for older kernels */ - if (!has_kvm_features && (function == KVM_CPUID_FEATURES)) { + if ((function == KVM_CPUID_FEATURES) && !found) { ret = get_para_features(s); } From 47111e2cfa1a83a99ac10ed19c7c8b02be4fe973 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:48:55 -0300 Subject: [PATCH 1353/2270] i386: kvm: kvm_arch_get_supported_cpuid: use 'entry' variable The reg switch will be moved to a separate function, so store the entry pointer in a variable. No behavior change, just code movement. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 56addf1866..18782e49db 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -140,19 +140,20 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, for (i = 0; i < cpuid->nent; ++i) { if (cpuid->entries[i].function == function && cpuid->entries[i].index == index) { + struct kvm_cpuid_entry2 *entry = &cpuid->entries[i]; found = true; switch (reg) { case R_EAX: - ret = cpuid->entries[i].eax; + ret = entry->eax; break; case R_EBX: - ret = cpuid->entries[i].ebx; + ret = entry->ebx; break; case R_ECX: - ret = cpuid->entries[i].ecx; + ret = entry->ecx; break; case R_EDX: - ret = cpuid->entries[i].edx; + ret = entry->edx; break; } } From 829ae2f9fa37bf026de556f50d58ef14a7dab9b3 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:48:56 -0300 Subject: [PATCH 1354/2270] i386: kvm: extract register switch to cpuid_entry_get_reg() function No behavior change: just code movement. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 18782e49db..695deb9f93 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -123,6 +123,28 @@ static int get_para_features(KVMState *s) } +/* Returns the value for a specific register on the cpuid entry + */ +static uint32_t cpuid_entry_get_reg(struct kvm_cpuid_entry2 *entry, int reg) +{ + uint32_t ret = 0; + switch (reg) { + case R_EAX: + ret = entry->eax; + break; + case R_EBX: + ret = entry->ebx; + break; + case R_ECX: + ret = entry->ecx; + break; + case R_EDX: + ret = entry->edx; + break; + } + return ret; +} + uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, uint32_t index, int reg) { @@ -142,20 +164,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, cpuid->entries[i].index == index) { struct kvm_cpuid_entry2 *entry = &cpuid->entries[i]; found = true; - switch (reg) { - case R_EAX: - ret = entry->eax; - break; - case R_EBX: - ret = entry->ebx; - break; - case R_ECX: - ret = entry->ecx; - break; - case R_EDX: - ret = entry->edx; - break; - } + ret = cpuid_entry_get_reg(entry, reg); } } From 4fb73f1d3be285caeb52a58fa5eaea49bd918650 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:48:57 -0300 Subject: [PATCH 1355/2270] i386: kvm: extract CPUID entry lookup to cpuid_find_entry() function No behavior change, just code movement. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 695deb9f93..c94897f5d3 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -145,11 +145,28 @@ static uint32_t cpuid_entry_get_reg(struct kvm_cpuid_entry2 *entry, int reg) return ret; } +/* Find matching entry for function/index on kvm_cpuid2 struct + */ +static struct kvm_cpuid_entry2 *cpuid_find_entry(struct kvm_cpuid2 *cpuid, + uint32_t function, + uint32_t index) +{ + int i; + for (i = 0; i < cpuid->nent; ++i) { + if (cpuid->entries[i].function == function && + cpuid->entries[i].index == index) { + return &cpuid->entries[i]; + } + } + /* not found: */ + return NULL; +} + uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, uint32_t index, int reg) { struct kvm_cpuid2 *cpuid; - int i, max; + int max; uint32_t ret = 0; uint32_t cpuid_1_edx; bool found = false; @@ -159,13 +176,10 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, max *= 2; } - for (i = 0; i < cpuid->nent; ++i) { - if (cpuid->entries[i].function == function && - cpuid->entries[i].index == index) { - struct kvm_cpuid_entry2 *entry = &cpuid->entries[i]; - found = true; - ret = cpuid_entry_get_reg(entry, reg); - } + struct kvm_cpuid_entry2 *entry = cpuid_find_entry(cpuid, function, index); + if (entry) { + found = true; + ret = cpuid_entry_get_reg(entry, reg); } /* Fixups for the data returned by KVM, below */ From dd87f8a690330777363f9a8680fce8f2ec544414 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:48:58 -0300 Subject: [PATCH 1356/2270] i386: kvm: extract try_get_cpuid() loop to get_supported_cpuid() function No behavior change, just code movement. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index c94897f5d3..d74dbc152c 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -98,6 +98,19 @@ static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max) return cpuid; } +/* Run KVM_GET_SUPPORTED_CPUID ioctl(), allocating a buffer large enough + * for all entries. + */ +static struct kvm_cpuid2 *get_supported_cpuid(KVMState *s) +{ + struct kvm_cpuid2 *cpuid; + int max = 1; + while ((cpuid = try_get_cpuid(s, max)) == NULL) { + max *= 2; + } + return cpuid; +} + struct kvm_para_features { int cap; int feature; @@ -166,15 +179,11 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, uint32_t index, int reg) { struct kvm_cpuid2 *cpuid; - int max; uint32_t ret = 0; uint32_t cpuid_1_edx; bool found = false; - max = 1; - while ((cpuid = try_get_cpuid(s, max)) == NULL) { - max *= 2; - } + cpuid = get_supported_cpuid(s); struct kvm_cpuid_entry2 *entry = cpuid_find_entry(cpuid, function, index); if (entry) { From c2acb022c83fbaf7fdd7ab9538d44ae6e0e94f94 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:48:59 -0300 Subject: [PATCH 1357/2270] i386: kvm: kvm_arch_get_supported_cpuid: replace if+switch with single 'if' Additional fixups will be added, and making them a single 'if/else if' chain makes it clearer than two nested switch statements. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index d74dbc152c..1f943c5c5a 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -193,20 +193,15 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, /* Fixups for the data returned by KVM, below */ - if (reg == R_EDX) { - switch (function) { - case 1: - /* KVM before 2.6.30 misreports the following features */ - ret |= CPUID_MTRR | CPUID_PAT | CPUID_MCE | CPUID_MCA; - break; - case 0x80000001: - /* On Intel, kvm returns cpuid according to the Intel spec, - * so add missing bits according to the AMD spec: - */ - cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); - ret |= cpuid_1_edx & CPUID_EXT2_AMD_ALIASES; - break; - } + if (function == 1 && reg == R_EDX) { + /* KVM before 2.6.30 misreports the following features */ + ret |= CPUID_MTRR | CPUID_PAT | CPUID_MCE | CPUID_MCA; + } else if (function == 0x80000001 && reg == R_EDX) { + /* On Intel, kvm returns cpuid according to the Intel spec, + * so add missing bits according to the AMD spec: + */ + cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); + ret |= cpuid_1_edx & CPUID_EXT2_AMD_ALIASES; } g_free(cpuid); From 84bd945cf298650096691509e7e9170036605e02 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:49:00 -0300 Subject: [PATCH 1358/2270] i386: kvm: set CPUID_EXT_HYPERVISOR on kvm_arch_get_supported_cpuid() Full grep for kvm_arch_get_supported_cpuid: kvm.h:uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, target-i386/cpu.c: x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX); target-i386/cpu.c: *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX); target-i386/cpu.c: *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX); target-i386/cpu.c: *ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX); target-i386/cpu.c: *edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX); target-i386/cpu.c: *eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX); target-i386/cpu.c: *ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX); target-i386/cpu.c: *ecx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_ECX); target-i386/cpu.c: *edx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EDX); target-i386/kvm.c:uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, target-i386/kvm.c: cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); target-i386/kvm.c: env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); * target-i386/kvm.c: env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); target-i386/kvm.c: env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, target-i386/kvm.c: env->cpuid_ext3_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, target-i386/kvm.c: env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A, target-i386/kvm.c: kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); target-i386/kvm.c: kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX); Note that there is only one call for CPUID[1].ECX above (*), and it is the one that gets hacked to include CPUID_EXT_HYPERVISOR, so we can simply make kvm_arch_get_supported_cpuid() set it, to let the rest of the code automatically know that the flag can be safely set by QEMU. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 1f943c5c5a..aabac72a66 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -196,6 +196,11 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, if (function == 1 && reg == R_EDX) { /* KVM before 2.6.30 misreports the following features */ ret |= CPUID_MTRR | CPUID_PAT | CPUID_MCE | CPUID_MCA; + } else if (function == 1 && reg == R_ECX) { + /* We can set the hypervisor flag, even if KVM does not return it on + * GET_SUPPORTED_CPUID + */ + ret |= CPUID_EXT_HYPERVISOR; } else if (function == 0x80000001 && reg == R_EDX) { /* On Intel, kvm returns cpuid according to the Intel spec, * so add missing bits according to the AMD spec: @@ -399,10 +404,8 @@ int kvm_arch_init_vcpu(CPUX86State *env) env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); - i = env->cpuid_ext_features & CPUID_EXT_HYPERVISOR; j = env->cpuid_ext_features & CPUID_EXT_TSC_DEADLINE_TIMER; env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); - env->cpuid_ext_features |= i; if (j && kvm_irqchip_in_kernel() && kvm_check_extension(s, KVM_CAP_TSC_DEADLINE_TIMER)) { env->cpuid_ext_features |= CPUID_EXT_TSC_DEADLINE_TIMER; From ac67ee260ae8e353314b6995ed5dccf1bb94fa9d Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:49:01 -0300 Subject: [PATCH 1359/2270] i386: kvm: set CPUID_EXT_TSC_DEADLINE_TIMER on kvm_arch_get_supported_cpuid() This moves the CPUID_EXT_TSC_DEADLINE_TIMER CPUID flag hacking from kvm_arch_init_vcpu() to kvm_arch_get_supported_cpuid(). Full git grep for kvm_arch_get_supported_cpuid: kvm.h:uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, target-i386/cpu.c: x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX); target-i386/cpu.c: *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX); target-i386/cpu.c: *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX); target-i386/cpu.c: *ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX); target-i386/cpu.c: *edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX); target-i386/cpu.c: *eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX); target-i386/cpu.c: *ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX); target-i386/cpu.c: *ecx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_ECX); target-i386/cpu.c: *edx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EDX); target-i386/kvm.c:uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, target-i386/kvm.c: cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); target-i386/kvm.c: env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); * target-i386/kvm.c: env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); target-i386/kvm.c: env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, target-i386/kvm.c: env->cpuid_ext3_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, target-i386/kvm.c: env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A, target-i386/kvm.c: kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); target-i386/kvm.c: kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX); Note that there is only one call for CPUID[1].ECX above (*), and it is the one that gets hacked to include CPUID_EXT_TSC_DEADLINE_TIMER, so we can simply make kvm_arch_get_supported_cpuid() set it, to let the rest of the code know the flag can be safely set by QEMU. One thing I was worrying about when doing this is that now kvm_arch_get_supported_cpuid() depends on kvm_irqchip_in_kernel(). But the 'kvm_kernel_irqchip' global variable is initialized during kvm_init(), that is called very early, and kvm_init() is already a requirement to run the GET_SUPPORTED_CPUID ioctl() (as kvm_init() is the function that initializes the 'kvm_state' global variable). Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index aabac72a66..aae8af22dd 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -201,6 +201,14 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, * GET_SUPPORTED_CPUID */ ret |= CPUID_EXT_HYPERVISOR; + /* tsc-deadline flag is not returned by GET_SUPPORTED_CPUID, but it + * can be enabled if the kernel has KVM_CAP_TSC_DEADLINE_TIMER, + * and the irqchip is in the kernel. + */ + if (kvm_irqchip_in_kernel() && + kvm_check_extension(s, KVM_CAP_TSC_DEADLINE_TIMER)) { + ret |= CPUID_EXT_TSC_DEADLINE_TIMER; + } } else if (function == 0x80000001 && reg == R_EDX) { /* On Intel, kvm returns cpuid according to the Intel spec, * so add missing bits according to the AMD spec: @@ -404,12 +412,7 @@ int kvm_arch_init_vcpu(CPUX86State *env) env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); - j = env->cpuid_ext_features & CPUID_EXT_TSC_DEADLINE_TIMER; env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); - if (j && kvm_irqchip_in_kernel() && - kvm_check_extension(s, KVM_CAP_TSC_DEADLINE_TIMER)) { - env->cpuid_ext_features |= CPUID_EXT_TSC_DEADLINE_TIMER; - } env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX); From 41e5e76db07b52591d9c9b88826278b8a5112258 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:49:02 -0300 Subject: [PATCH 1360/2270] i386: kvm: x2apic is not supported without in-kernel irqchip This is necessary so that x2apic is not improperly enabled when the in-kernel irqchip is disabled. This won't generate a warning with "-cpu ...,check" because the current check/enforce code is broken (it checks the host CPU data directly, instead of using kvm_arch_get_supported_cpuid()), but it will be eventually fixed to properly report the missing x2apic flag. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index aae8af22dd..4e96b046da 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -209,6 +209,13 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, kvm_check_extension(s, KVM_CAP_TSC_DEADLINE_TIMER)) { ret |= CPUID_EXT_TSC_DEADLINE_TIMER; } + + /* x2apic is reported by GET_SUPPORTED_CPUID, but it can't be enabled + * without the in-kernel irqchip + */ + if (!kvm_irqchip_in_kernel()) { + ret &= ~CPUID_EXT_X2APIC; + } } else if (function == 0x80000001 && reg == R_EDX) { /* On Intel, kvm returns cpuid according to the Intel spec, * so add missing bits according to the AMD spec: From ea85c9e45655c5e3a665a5295e5338b995e4a29c Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:49:03 -0300 Subject: [PATCH 1361/2270] i386: kvm: mask cpuid_kvm_features earlier Instead of masking the KVM feature bits very late (while building the KVM_SET_CPUID2 data), mask it out on env->cpuid_kvm_features, at the same point where the other feature words are masked out. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 4e96b046da..8eb61a02e7 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -428,6 +428,9 @@ int kvm_arch_init_vcpu(CPUX86State *env) env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A, 0, R_EDX); + env->cpuid_kvm_features &= + kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); + cpuid_i = 0; /* Paravirtualization CPUIDs */ @@ -448,8 +451,7 @@ int kvm_arch_init_vcpu(CPUX86State *env) c = &cpuid_data.entries[cpuid_i++]; memset(c, 0, sizeof(*c)); c->function = KVM_CPUID_FEATURES; - c->eax = env->cpuid_kvm_features & - kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); + c->eax = env->cpuid_kvm_features; if (hyperv_enabled()) { memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12); From c9da8382c1432fbafb8705e7faecdf783c0b1821 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:49:04 -0300 Subject: [PATCH 1362/2270] i386: kvm: mask cpuid_ext4_features bits earlier This way all the filtering by GET_SUPPORTED_CPUID is being done at the same place in the code. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 8eb61a02e7..be37a1f7ba 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -431,6 +431,9 @@ int kvm_arch_init_vcpu(CPUX86State *env) env->cpuid_kvm_features &= kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); + env->cpuid_ext4_features &= kvm_arch_get_supported_cpuid(s, 0xC0000001, + 0, R_EDX); + cpuid_i = 0; /* Paravirtualization CPUIDs */ @@ -572,8 +575,6 @@ int kvm_arch_init_vcpu(CPUX86State *env) /* Call Centaur's CPUID instructions they are supported. */ if (env->cpuid_xlevel2 > 0) { - env->cpuid_ext4_features &= - kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX); cpu_x86_cpuid(env, 0xC0000000, 0, &limit, &unused, &unused, &unused); for (i = 0xC0000000; i <= limit; i++) { From bc74b7db86bc84d3e027ac7b536e8e39140d984f Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:49:05 -0300 Subject: [PATCH 1363/2270] i386: kvm: filter CPUID feature words earlier, on cpu.c cpu.c contains the code that will check if all requested CPU features are available, so the filtering of KVM features must be there, so we can implement "check" and "enforce" properly. The only point where kvm_arch_init_vcpu() is called on i386 is: - cpu_x86_init() - x86_cpu_realize() (after cpu_x86_register() is called) - qemu_init_vcpu() - qemu_kvm_start_vcpu() - qemu_kvm_thread_fn() (on a new thread) - kvm_init_vcpu() - kvm_arch_init_vcpu() With this patch, the filtering will be done earlier, at: - cpu_x86_init() - cpu_x86_register() (before x86_cpu_realize() is called) Also, the KVM CPUID filtering will now be done at the same place where the TCG CPUID feature filtering is done. Later, the code can be changed to use the same filtering code for the "check" and "enforce" modes, as now the cpu.c code knows exactly which CPU features are going to be exposed to the guest (and much earlier). One thing I was worrying about when doing this is that kvm_arch_get_supported_cpuid() depends on kvm_irqchip_in_kernel(), and maybe the 'kvm_kernel_irqchip' global variable wasn't initialized yet at CPU creation time. But kvm_kernel_irqchip is initialized during kvm_init(), that is called very early (much earlier than the machine init function), and kvm_init() is already a requirement to run the GET_SUPPORTED_CPUID ioctl() (as kvm_init() initializes the kvm_state global variable). Side note: it would be nice to keep KVM-specific code inside kvm.c. The problem is that properly implementing -cpu check/enforce code (that's inside cpu.c) depends directly on the feature bit filtering done using kvm_arch_get_supported_cpuid(). Currently -cpu check/enforce is broken because it simply uses the host CPU feature bits instead of GET_SUPPORTED_CPUID, and we need to fix that. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- kvm.h | 1 + target-i386/cpu.c | 30 ++++++++++++++++++++++++++++++ target-i386/kvm.c | 18 ------------------ 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/kvm.h b/kvm.h index 2b26dcb9bb..1e7f244561 100644 --- a/kvm.h +++ b/kvm.h @@ -20,6 +20,7 @@ #ifdef CONFIG_KVM #include +#include #endif extern int kvm_allowed; diff --git a/target-i386/cpu.c b/target-i386/cpu.c index d4f2e65cd9..78876f632b 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1368,6 +1368,32 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) return cpu_list; } +#ifdef CONFIG_KVM +static void filter_features_for_kvm(X86CPU *cpu) +{ + CPUX86State *env = &cpu->env; + KVMState *s = kvm_state; + + env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); + + env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); + + env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, + 0, R_EDX); + env->cpuid_ext3_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, + 0, R_ECX); + env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A, + 0, R_EDX); + + env->cpuid_kvm_features &= + kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); + + env->cpuid_ext4_features &= kvm_arch_get_supported_cpuid(s, 0xC0000001, + 0, R_EDX); + +} +#endif + int cpu_x86_register(X86CPU *cpu, const char *cpu_model) { CPUX86State *env = &cpu->env; @@ -1425,6 +1451,10 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) ); env->cpuid_ext3_features &= TCG_EXT3_FEATURES; env->cpuid_svm_features &= TCG_SVM_FEATURES; + } else { +#ifdef CONFIG_KVM + filter_features_for_kvm(cpu); +#endif } object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error); if (error_is_set(&error)) { diff --git a/target-i386/kvm.c b/target-i386/kvm.c index be37a1f7ba..593e9d3e0f 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -410,30 +410,12 @@ int kvm_arch_init_vcpu(CPUX86State *env) struct kvm_cpuid2 cpuid; struct kvm_cpuid_entry2 entries[100]; } QEMU_PACKED cpuid_data; - KVMState *s = env->kvm_state; uint32_t limit, i, j, cpuid_i; uint32_t unused; struct kvm_cpuid_entry2 *c; uint32_t signature[3]; int r; - env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); - - env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); - - env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, - 0, R_EDX); - env->cpuid_ext3_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, - 0, R_ECX); - env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A, - 0, R_EDX); - - env->cpuid_kvm_features &= - kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); - - env->cpuid_ext4_features &= kvm_arch_get_supported_cpuid(s, 0xC0000001, - 0, R_EDX); - cpuid_i = 0; /* Paravirtualization CPUIDs */ From b8091f245d36da604219db42552cc28400698446 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:49:06 -0300 Subject: [PATCH 1364/2270] i386: kvm: reformat filter_features_for_kvm() code Cosmetic, but it will also help to make futher patches easier to review. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/cpu.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 78876f632b..be16898e37 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1374,22 +1374,20 @@ static void filter_features_for_kvm(X86CPU *cpu) CPUX86State *env = &cpu->env; KVMState *s = kvm_state; - env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); - - env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); - - env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, - 0, R_EDX); - env->cpuid_ext3_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, - 0, R_ECX); - env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A, - 0, R_EDX); - + env->cpuid_features &= + kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); + env->cpuid_ext_features &= + kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); + env->cpuid_ext2_features &= + kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX); + env->cpuid_ext3_features &= + kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_ECX); + env->cpuid_svm_features &= + kvm_arch_get_supported_cpuid(s, 0x8000000A, 0, R_EDX); env->cpuid_kvm_features &= - kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); - - env->cpuid_ext4_features &= kvm_arch_get_supported_cpuid(s, 0xC0000001, - 0, R_EDX); + kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); + env->cpuid_ext4_features &= + kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX); } #endif From ffa8c11f0bbf47e1b7a3a62f97bc1da591c6734a Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:49:07 -0300 Subject: [PATCH 1365/2270] i386: kvm: filter CPUID leaf 7 based on GET_SUPPORTED_CPUID, too Now that CPUID leaf 7 features can be enabled/disabled on the command-line, we need to filter them properly using GET_SUPPORTED_CPUID, at the same place where other features are filtered out. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index be16898e37..22d91ed074 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1384,6 +1384,8 @@ static void filter_features_for_kvm(X86CPU *cpu) kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_ECX); env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A, 0, R_EDX); + env->cpuid_7_0_ebx_features &= + kvm_arch_get_supported_cpuid(s, 7, 0, R_EBX); env->cpuid_kvm_features &= kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); env->cpuid_ext4_features &= From 811a8ae09e179d0a4d8cde13ba9f72e7c782c9ff Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Tue, 9 Oct 2012 11:03:59 -0300 Subject: [PATCH 1366/2270] i386: cpu: add missing CPUID[EAX=7,ECX=0] flag names This makes QEMU recognize the following CPU flag names: Flags | Corresponding KVM kernel commit -----------------+---------------------------------------- FSGSBASE | 176f61da82435eae09cc96f70b530d1ba0746b8b AVX2, BMI1, BMI2 | fb215366b3c7320ac25dca766a0152df16534932 HLE, RTM | 83c529151ab0d4a813e3f6a3e293fff75d468519 INVPCID | ad756a1603c5fac207758faaac7f01c34c9d0b7b ERMS | a01c8f9b4e266df1d7166d23216f2060648f862d Reviewed-by: Don Slutz Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 22d91ed074..7c726fc0b1 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -106,8 +106,8 @@ static const char *svm_feature_name[] = { }; static const char *cpuid_7_0_ebx_feature_name[] = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, "smep", - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "fsgsbase", NULL, NULL, "bmi1", "hle", "avx2", NULL, "smep", + "bmi2", "erms", "invpcid", "rtm", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "smap", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; From c3d3980794124508e0bd4eaa406d7fa0e832a221 Mon Sep 17 00:00:00 2001 From: Don Slutz Date: Fri, 12 Oct 2012 15:43:23 -0400 Subject: [PATCH 1367/2270] target-i386: Add missing kvm cpuid feature name Currently "-cpu host,-kvmclock,-kvm_nopiodelay,-kvm_mmu" does not turn off all bits in CPUID 0x40000001 EAX. The missing ones is KVM_FEATURE_STEAL_TIME. This adds the name kvm_steal_time. Signed-off-by: Don Slutz Signed-off-by: Marcelo Tosatti --- target-i386/cpu.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 7c726fc0b1..4417d6abed 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -88,10 +88,14 @@ static const char *ext3_feature_name[] = { }; static const char *kvm_feature_name[] = { - "kvmclock", "kvm_nopiodelay", "kvm_mmu", "kvmclock", "kvm_asyncpf", NULL, "kvm_pv_eoi", NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "kvmclock", "kvm_nopiodelay", "kvm_mmu", "kvmclock", + "kvm_asyncpf", "kvm_steal_time", "kvm_pv_eoi", NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, }; static const char *svm_feature_name[] = { From 19403a68fb8eaefb2e1245b6a8384d3a3ffa7ca0 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Fri, 5 Oct 2012 14:51:39 -0300 Subject: [PATCH 1368/2270] cirrus_vga: allow configurable vram size Allow RAM size to be configurable for cirrus, to allow migration compatibility from qemu-kvm. Acked-by: Gerd Hoffmann Signed-off-by: Marcelo Tosatti --- hw/cirrus_vga.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index e4af2e9ded..9bef96e6d7 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -42,8 +42,6 @@ //#define DEBUG_CIRRUS //#define DEBUG_BITBLT -#define VGA_RAM_SIZE (8192 * 1024) - /*************************************** * * definitions @@ -2856,7 +2854,8 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci, /* I/O handler for LFB */ memory_region_init_io(&s->cirrus_linear_io, &cirrus_linear_io_ops, s, - "cirrus-linear-io", VGA_RAM_SIZE); + "cirrus-linear-io", s->vga.vram_size_mb + * 1024 * 1024); memory_region_set_flush_coalesced(&s->cirrus_linear_io); /* I/O handler for LFB */ @@ -2899,7 +2898,6 @@ static int vga_initfn(ISADevice *dev) ISACirrusVGAState *d = DO_UPCAST(ISACirrusVGAState, dev, dev); VGACommonState *s = &d->cirrus_vga.vga; - s->vram_size_mb = VGA_RAM_SIZE >> 20; vga_common_init(s); cirrus_init_common(&d->cirrus_vga, CIRRUS_ID_CLGD5430, 0, isa_address_space(dev)); @@ -2912,6 +2910,12 @@ static int vga_initfn(ISADevice *dev) return 0; } +static Property isa_vga_cirrus_properties[] = { + DEFINE_PROP_UINT32("vgamem_mb", struct ISACirrusVGAState, + cirrus_vga.vga.vram_size_mb, 8), + DEFINE_PROP_END_OF_LIST(), +}; + static void isa_cirrus_vga_class_init(ObjectClass *klass, void *data) { ISADeviceClass *k = ISA_DEVICE_CLASS(klass); @@ -2919,6 +2923,7 @@ static void isa_cirrus_vga_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_cirrus_vga; k->init = vga_initfn; + dc->props = isa_vga_cirrus_properties; } static TypeInfo isa_cirrus_vga_info = { @@ -2942,7 +2947,6 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev) int16_t device_id = pc->device_id; /* setup VGA */ - s->vga.vram_size_mb = VGA_RAM_SIZE >> 20; vga_common_init(&s->vga); cirrus_init_common(s, device_id, 1, pci_address_space(dev)); s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate, @@ -2969,6 +2973,12 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev) return 0; } +static Property pci_vga_cirrus_properties[] = { + DEFINE_PROP_UINT32("vgamem_mb", struct PCICirrusVGAState, + cirrus_vga.vga.vram_size_mb, 8), + DEFINE_PROP_END_OF_LIST(), +}; + static void cirrus_vga_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -2982,6 +2992,7 @@ static void cirrus_vga_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_DISPLAY_VGA; dc->desc = "Cirrus CLGD 54xx VGA"; dc->vmsd = &vmstate_pci_cirrus_vga; + dc->props = pci_vga_cirrus_properties; } static TypeInfo cirrus_vga_info = { From e43d594ee55038442d59d301eb34fdf0c378d3a4 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 5 Oct 2012 14:51:40 -0300 Subject: [PATCH 1369/2270] Use machine options to emulate -no-kvm-irqchip Releases of qemu-kvm will be interrupted at qemu 1.3.0. Users should switch to plain qemu releases. To avoid breaking scenarios which are setup with command line options specific to qemu-kvm, port these switches from qemu-kvm to qemu.git. Port -no-kvm-irqchip option. Signed-off-by: Marcelo Tosatti --- qemu-options.hx | 3 +++ vl.c | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/qemu-options.hx b/qemu-options.hx index a67a2551e5..d813755ccb 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2888,6 +2888,9 @@ STEXI Enable FIPS 140-2 compliance mode. ETEXI +HXCOMM Deprecated by -machine kernel_irqchip=on|off property +DEF("no-kvm-irqchip", HAS_ARG, QEMU_OPTION_no_kvm_irqchip, "", QEMU_ARCH_I386) + HXCOMM This is the last statement. Insert new options before this line! STEXI @end table diff --git a/vl.c b/vl.c index 5a3d316980..7d0708afcd 100644 --- a/vl.c +++ b/vl.c @@ -2574,6 +2574,11 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_M: machine = machine_parse(optarg); break; + case QEMU_OPTION_no_kvm_irqchip: { + olist = qemu_find_opts("machine"); + qemu_opts_parse(olist, "kernel_irqchip=off", 0); + break; + } case QEMU_OPTION_cpu: /* hw initialization will check this */ cpu_model = optarg; From 4086bde8c08746913d7ca6dcbc5e18a49a627cdc Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 5 Oct 2012 14:51:41 -0300 Subject: [PATCH 1370/2270] Issue warning when deprecated -no-kvm-pit is used Releases of qemu-kvm will be interrupted at qemu 1.3.0. Users should switch to plain qemu releases. To avoid breaking scenarios which are setup with command line options specific to qemu-kvm, port these switches from qemu-kvm to qemu.git. Port -no-kvm-pit option. Signed-off-by: Marcelo Tosatti --- qemu-options.hx | 3 +++ vl.c | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/qemu-options.hx b/qemu-options.hx index d813755ccb..42e642c65b 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2888,6 +2888,9 @@ STEXI Enable FIPS 140-2 compliance mode. ETEXI +HXCOMM Deprecated (ignored) +DEF("no-kvm-pit", HAS_ARG, QEMU_OPTION_no_kvm_pit, "", QEMU_ARCH_I386) + HXCOMM Deprecated by -machine kernel_irqchip=on|off property DEF("no-kvm-irqchip", HAS_ARG, QEMU_OPTION_no_kvm_irqchip, "", QEMU_ARCH_I386) diff --git a/vl.c b/vl.c index 7d0708afcd..37717b4559 100644 --- a/vl.c +++ b/vl.c @@ -3171,6 +3171,11 @@ int main(int argc, char **argv, char **envp) machine = machine_parse(optarg); } break; + case QEMU_OPTION_no_kvm_pit: { + fprintf(stderr, "Warning: KVM PIT can no longer be disabled " + "separately.\n"); + break; + } case QEMU_OPTION_usb: machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); if (machine_opts) { From c21fb4f8b802108697f9353a8f807079507b586c Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 5 Oct 2012 14:51:42 -0300 Subject: [PATCH 1371/2270] Use global properties to emulate -no-kvm-pit-reinjection Releases of qemu-kvm will be interrupted at qemu 1.3.0. Users should switch to plain qemu releases. To avoid breaking scenarios which are setup with command line options specific to qemu-kvm, port these switches from qemu-kvm to qemu.git. Port -no-kvm-pit-reinjection. Signed-off-by: Marcelo Tosatti --- qemu-options.hx | 4 ++++ vl.c | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/qemu-options.hx b/qemu-options.hx index 42e642c65b..4403c9c718 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2888,6 +2888,10 @@ STEXI Enable FIPS 140-2 compliance mode. ETEXI +HXCOMM Deprecated by kvm-pit driver properties +DEF("no-kvm-pit-reinjection", HAS_ARG, QEMU_OPTION_no_kvm_pit_reinjection, + "", QEMU_ARCH_I386) + HXCOMM Deprecated (ignored) DEF("no-kvm-pit", HAS_ARG, QEMU_OPTION_no_kvm_pit, "", QEMU_ARCH_I386) diff --git a/vl.c b/vl.c index 37717b4559..3068b4bc59 100644 --- a/vl.c +++ b/vl.c @@ -3176,6 +3176,21 @@ int main(int argc, char **argv, char **envp) "separately.\n"); break; } + case QEMU_OPTION_no_kvm_pit_reinjection: { + static GlobalProperty kvm_pit_lost_tick_policy[] = { + { + .driver = "kvm-pit", + .property = "lost_tick_policy", + .value = "discard", + }, + { /* end of list */ } + }; + + fprintf(stderr, "Warning: option deprecated, use " + "lost_tick_policy property of kvm-pit instead.\n"); + qdev_prop_register_global_list(kvm_pit_lost_tick_policy); + break; + } case QEMU_OPTION_usb: machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); if (machine_opts) { From 0d92d17a6d0d65af8cb905bdd5f9e04e210564ff Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 5 Oct 2012 14:51:43 -0300 Subject: [PATCH 1372/2270] Issue warning when deprecated drive parameter boot=on|off is used Releases of qemu-kvm will be interrupted at qemu 1.3.0. Users should switch to plain qemu releases. To avoid breaking scenarios which are setup with command line options specific to qemu-kvm, port these switches from qemu-kvm to qemu.git. Port drive boot option. From the qemu-kvm original commit message: We do not want to maintain this option forever. It will be removed after a grace period of a few releases. So warn the user that this option has no effect and will become invalid soon. Signed-off-by: Marcelo Tosatti --- blockdev.c | 6 ++++++ qemu-config.c | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/blockdev.c b/blockdev.c index a068a4b669..e73fd6e388 100644 --- a/blockdev.c +++ b/blockdev.c @@ -433,6 +433,12 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) return NULL; } + if (qemu_opt_get(opts, "boot") != NULL) { + fprintf(stderr, "qemu-kvm: boot=on|off is deprecated and will be " + "ignored. Future versions will reject this parameter. Please " + "update your scripts.\n"); + } + on_write_error = BLOCKDEV_ON_ERROR_ENOSPC; if ((buf = qemu_opt_get(opts, "werror")) != NULL) { if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) { diff --git a/qemu-config.c b/qemu-config.c index e854fffe19..3154cac10f 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -114,6 +114,10 @@ static QemuOptsList qemu_drive_opts = { .name = "copy-on-read", .type = QEMU_OPT_BOOL, .help = "copy read data from backing file into image file", + },{ + .name = "boot", + .type = QEMU_OPT_BOOL, + .help = "(deprecated, ignored)", }, { /* end of list */ } }, From 88eed34a6b3eba46397de5aaf24ed66ea290794b Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 5 Oct 2012 14:51:44 -0300 Subject: [PATCH 1373/2270] Issue warning when deprecated -tdf option is used Releases of qemu-kvm will be interrupted at qemu 1.3.0. Users should switch to plain qemu releases. To avoid breaking scenarios which are setup with command line options specific to qemu-kvm, port these switches from qemu-kvm to qemu.git. Port -tdf option. Signed-off-by: Marcelo Tosatti --- qemu-options.hx | 3 +++ vl.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/qemu-options.hx b/qemu-options.hx index 4403c9c718..628bd44591 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2898,6 +2898,9 @@ DEF("no-kvm-pit", HAS_ARG, QEMU_OPTION_no_kvm_pit, "", QEMU_ARCH_I386) HXCOMM Deprecated by -machine kernel_irqchip=on|off property DEF("no-kvm-irqchip", HAS_ARG, QEMU_OPTION_no_kvm_irqchip, "", QEMU_ARCH_I386) +HXCOMM Deprecated (ignored) +DEF("tdf", 0, QEMU_OPTION_tdf,"", QEMU_ARCH_ALL) + HXCOMM This is the last statement. Insert new options before this line! STEXI @end table diff --git a/vl.c b/vl.c index 3068b4bc59..cd7c0fbd52 100644 --- a/vl.c +++ b/vl.c @@ -3280,6 +3280,10 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_semihosting: semihosting_enabled = 1; break; + case QEMU_OPTION_tdf: + fprintf(stderr, "Warning: user space PIT time drift fix " + "is no longer supported.\n"); + break; case QEMU_OPTION_name: qemu_name = g_strdup(optarg); { From a0dac021fa4b8b87160192c1f60ee26fc6c5ce2e Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 5 Oct 2012 14:51:45 -0300 Subject: [PATCH 1374/2270] Emulate qemu-kvms -no-kvm option Releases of qemu-kvm will be interrupted at qemu 1.3.0. Users should switch to plain qemu releases. To avoid breaking scenarios which are setup with command line options specific to qemu-kvm, port these switches from qemu-kvm to qemu.git. Port -no-kvm option. Signed-off-by: Marcelo Tosatti --- qemu-options.hx | 3 +++ vl.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/qemu-options.hx b/qemu-options.hx index 628bd44591..fe8f15c541 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2888,6 +2888,9 @@ STEXI Enable FIPS 140-2 compliance mode. ETEXI +HXCOMM Deprecated by -machine accel=tcg property +DEF("no-kvm", HAS_ARG, QEMU_OPTION_no_kvm, "", QEMU_ARCH_I386) + HXCOMM Deprecated by kvm-pit driver properties DEF("no-kvm-pit-reinjection", HAS_ARG, QEMU_OPTION_no_kvm_pit_reinjection, "", QEMU_ARCH_I386) diff --git a/vl.c b/vl.c index cd7c0fbd52..b39f22ed35 100644 --- a/vl.c +++ b/vl.c @@ -3171,6 +3171,10 @@ int main(int argc, char **argv, char **envp) machine = machine_parse(optarg); } break; + case QEMU_OPTION_no_kvm: + olist = qemu_find_opts("machine"); + qemu_opts_parse(olist, "accel=tcg", 0); + break; case QEMU_OPTION_no_kvm_pit: { fprintf(stderr, "Warning: KVM PIT can no longer be disabled " "separately.\n"); From 1aefc6b8cbe66e5adb3e6b160f6790171e0a7785 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 24 Oct 2012 19:44:05 -0200 Subject: [PATCH 1375/2270] target-i386: make cpu_x86_fill_host() void The return value of that function is always 0, and is always ignored. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/cpu.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 4417d6abed..6575834885 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -766,7 +766,7 @@ static int cpu_x86_fill_model_id(char *str) return 0; } -static int cpu_x86_fill_host(x86_def_t *x86_cpu_def) +static void cpu_x86_fill_host(x86_def_t *x86_cpu_def) { uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; @@ -819,8 +819,6 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def) * unsupported ones later. */ x86_cpu_def->svm_features = -1; - - return 0; } static int unavailable_host_feature(struct model_features_t *f, uint32_t mask) From 6e746f30558cb1331598575918c2a8808be2a75b Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 24 Oct 2012 19:44:06 -0200 Subject: [PATCH 1376/2270] target-i386: cpu: make -cpu host/check/enforce code KVM-specific Rationale: * "-cpu host" is available only when using KVM * The current implementation of -cpu check/enforce (check_features_against_host()) makes sense only when using KVM. So this makes the functions check_features_against_host() and cpu_x86_fill_host() KVM-specific, document them as such, and rename them to kvm_check_features_against_host() and kvm_cpu_fill_host(). Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/cpu.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 6575834885..390ed4771d 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -766,10 +766,17 @@ static int cpu_x86_fill_model_id(char *str) return 0; } -static void cpu_x86_fill_host(x86_def_t *x86_cpu_def) +/* Fill a x86_def_t struct with information about the host CPU, and + * the CPU features supported by the host hardware + host kernel + * + * This function may be called only if KVM is enabled. + */ +static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) { uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; + assert(kvm_enabled()); + x86_cpu_def->name = "host"; host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); x86_cpu_def->level = eax; @@ -784,7 +791,7 @@ static void cpu_x86_fill_host(x86_def_t *x86_cpu_def) x86_cpu_def->ext_features = ecx; x86_cpu_def->features = edx; - if (kvm_enabled() && x86_cpu_def->level >= 7) { + if (x86_cpu_def->level >= 7) { x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX); } else { x86_cpu_def->cpuid_7_0_ebx_features = 0; @@ -839,8 +846,10 @@ static int unavailable_host_feature(struct model_features_t *f, uint32_t mask) /* best effort attempt to inform user requested cpu flags aren't making * their way to the guest. Note: ft[].check_feat ideally should be * specified via a guest_def field to suppress report of extraneous flags. + * + * This function may be called only if KVM is enabled. */ -static int check_features_against_host(x86_def_t *guest_def) +static int kvm_check_features_against_host(x86_def_t *guest_def) { x86_def_t host_def; uint32_t mask; @@ -855,7 +864,9 @@ static int check_features_against_host(x86_def_t *guest_def) {&guest_def->ext3_features, &host_def.ext3_features, ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}}; - cpu_x86_fill_host(&host_def); + assert(kvm_enabled()); + + kvm_cpu_fill_host(&host_def); for (rv = 0, i = 0; i < ARRAY_SIZE(ft); ++i) for (mask = 1; mask; mask <<= 1) if (ft[i].check_feat & mask && *ft[i].guest_feat & mask && @@ -1142,7 +1153,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) if (name && !strcmp(name, def->name)) break; if (kvm_enabled() && name && strcmp(name, "host") == 0) { - cpu_x86_fill_host(x86_cpu_def); + kvm_cpu_fill_host(x86_cpu_def); } else if (!def) { goto error; } else { @@ -1280,8 +1291,8 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) x86_cpu_def->kvm_features &= ~minus_kvm_features; x86_cpu_def->svm_features &= ~minus_svm_features; x86_cpu_def->cpuid_7_0_ebx_features &= ~minus_7_0_ebx_features; - if (check_cpuid) { - if (check_features_against_host(x86_cpu_def) && enforce_cpuid) + if (check_cpuid && kvm_enabled()) { + if (kvm_check_features_against_host(x86_cpu_def) && enforce_cpuid) goto error; } if (x86_cpu_def->cpuid_7_0_ebx_features && x86_cpu_def->level < 7) { From 12869995ea4f436ab76af5059fd2e9ae83c6cf9d Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 24 Oct 2012 19:44:07 -0200 Subject: [PATCH 1377/2270] target-i386: kvm_cpu_fill_host: use GET_SUPPORTED_CPUID Change the kvm_cpu_fill_host() function to use kvm_arch_get_supported_cpuid() instead of running the CPUID instruction directly, when checking for supported CPUID features. This should solve two problems at the same time: * "-cpu host" was not enabling features that don't need support on the host CPU (e.g. x2apic); * "check" and "enforce" options were not detecting problems when the host CPU did support a feature, but the KVM kernel code didn't support it. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/cpu.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 390ed4771d..4c84e9fbc4 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -773,13 +773,13 @@ static int cpu_x86_fill_model_id(char *str) */ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) { + KVMState *s = kvm_state; uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; assert(kvm_enabled()); x86_cpu_def->name = "host"; host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); - x86_cpu_def->level = eax; x86_cpu_def->vendor1 = ebx; x86_cpu_def->vendor2 = edx; x86_cpu_def->vendor3 = ecx; @@ -788,21 +788,24 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF); x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12); x86_cpu_def->stepping = eax & 0x0F; - x86_cpu_def->ext_features = ecx; - x86_cpu_def->features = edx; + + x86_cpu_def->level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX); + x86_cpu_def->features = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_EDX); + x86_cpu_def->ext_features = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_ECX); if (x86_cpu_def->level >= 7) { - x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX); + x86_cpu_def->cpuid_7_0_ebx_features = + kvm_arch_get_supported_cpuid(s, 0x7, 0, R_EBX); } else { x86_cpu_def->cpuid_7_0_ebx_features = 0; } - host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx); - x86_cpu_def->xlevel = eax; + x86_cpu_def->xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX); + x86_cpu_def->ext2_features = + kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX); + x86_cpu_def->ext3_features = + kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_ECX); - host_cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx); - x86_cpu_def->ext2_features = edx; - x86_cpu_def->ext3_features = ecx; cpu_x86_fill_model_id(x86_cpu_def->model_id); x86_cpu_def->vendor_override = 0; @@ -811,11 +814,13 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) x86_cpu_def->vendor2 == CPUID_VENDOR_VIA_2 && x86_cpu_def->vendor3 == CPUID_VENDOR_VIA_3) { host_cpuid(0xC0000000, 0, &eax, &ebx, &ecx, &edx); + eax = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX); if (eax >= 0xC0000001) { /* Support VIA max extended level */ x86_cpu_def->xlevel2 = eax; host_cpuid(0xC0000001, 0, &eax, &ebx, &ecx, &edx); - x86_cpu_def->ext4_features = edx; + x86_cpu_def->ext4_features = + kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX); } } From b55f546eefe79cb6e6b15ebb23f352a736bafc39 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Oct 2012 12:54:39 +0100 Subject: [PATCH 1378/2270] update-linux-headers.sh: Handle new kernel uapi/ directories Recent kernels have moved to keeping the userspace headers in uapi/ subdirectories. This breaks the detection of whether an architecture has KVM support in the kernel because kvm.h has moved in the kernel source tree. Update the check to support both the old and new locations. Signed-off-by: Peter Maydell Signed-off-by: Marcelo Tosatti --- scripts/update-linux-headers.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh index 67be2efecd..4c7b566fdf 100755 --- a/scripts/update-linux-headers.sh +++ b/scripts/update-linux-headers.sh @@ -34,7 +34,8 @@ ARCHLIST=$(cd "$linux/arch" && echo *) for arch in $ARCHLIST; do # Discard anything which isn't a KVM-supporting architecture - if ! [ -e "$linux/arch/$arch/include/asm/kvm.h" ]; then + if ! [ -e "$linux/arch/$arch/include/asm/kvm.h" ] && + ! [ -e "$linux/arch/$arch/include/uapi/asm/kvm.h" ] ; then continue fi From 3993c6bddf6da21977349ba1b14b86294ef4f7ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 06:43:49 +0200 Subject: [PATCH 1379/2270] cpus: Pass CPUState to [qemu_]cpu_has_work() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For target-mips also change the return type to bool. Make include paths for cpu-qom.h consistent for alpha and unicore32. Signed-off-by: Andreas Färber [AF: Updated new target-openrisc function accordingly] Acked-by: Richard Henderson (for alpha) --- cpu-all.h | 2 -- cpu-exec.c | 8 +++----- cpus.c | 2 +- hw/spapr_hcall.c | 2 +- hw/xtensa_pic.c | 2 +- include/qemu/cpu.h | 10 ++++++++++ target-alpha/cpu.c | 2 +- target-alpha/cpu.h | 4 +++- target-arm/cpu.h | 4 +++- target-cris/cpu.h | 4 +++- target-i386/cpu.h | 4 +++- target-lm32/cpu.h | 4 +++- target-m68k/cpu.h | 4 +++- target-microblaze/cpu.h | 4 +++- target-mips/cpu.h | 11 ++++++----- target-openrisc/cpu.h | 4 +++- target-ppc/cpu.h | 4 +++- target-s390x/cpu.h | 4 +++- target-sh4/cpu.h | 4 +++- target-sparc/cpu.h | 4 +++- target-unicore32/cpu.c | 2 +- target-unicore32/cpu.h | 4 +++- target-xtensa/cpu.h | 4 +++- 23 files changed, 66 insertions(+), 31 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index d19ec127e1..0356684e2f 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -438,8 +438,6 @@ void cpu_reset_interrupt(CPUArchState *env, int mask); void cpu_exit(CPUArchState *s); -bool qemu_cpu_has_work(CPUArchState *env); - /* Breakpoint/watchpoint flags */ #define BP_MEM_READ 0x01 #define BP_MEM_WRITE 0x02 diff --git a/cpu-exec.c b/cpu-exec.c index 252da86882..904ee73c7b 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -27,9 +27,9 @@ int tb_invalidated_flag; //#define CONFIG_DEBUG_EXEC -bool qemu_cpu_has_work(CPUArchState *env) +bool qemu_cpu_has_work(CPUState *cpu) { - return cpu_has_work(env); + return cpu_has_work(cpu); } void cpu_loop_exit(CPUArchState *env) @@ -181,16 +181,14 @@ volatile sig_atomic_t exit_request; int cpu_exec(CPUArchState *env) { -#ifdef TARGET_PPC CPUState *cpu = ENV_GET_CPU(env); -#endif int ret, interrupt_request; TranslationBlock *tb; uint8_t *tc_ptr; tcg_target_ulong next_tb; if (env->halted) { - if (!cpu_has_work(env)) { + if (!cpu_has_work(cpu)) { return EXCP_HALTED; } diff --git a/cpus.c b/cpus.c index 6baf2bcb35..76f32fc050 100644 --- a/cpus.c +++ b/cpus.c @@ -72,7 +72,7 @@ static bool cpu_thread_is_idle(CPUArchState *env) if (cpu->stopped || !runstate_is_running()) { return true; } - if (!env->halted || qemu_cpu_has_work(env) || + if (!env->halted || qemu_cpu_has_work(cpu) || kvm_async_interrupts_enabled()) { return false; } diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c index c6d55da7a6..63cadb8d92 100644 --- a/hw/spapr_hcall.c +++ b/hw/spapr_hcall.c @@ -516,7 +516,7 @@ static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr, env->msr |= (1ULL << MSR_EE); hreg_compute_hflags(env); - if (!cpu_has_work(env)) { + if (!cpu_has_work(CPU(cpu))) { env->halted = 1; env->exception_index = EXCP_HLT; env->exit_request = 1; diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c index 8b9c0510f9..1ec70cd969 100644 --- a/hw/xtensa_pic.c +++ b/hw/xtensa_pic.c @@ -131,7 +131,7 @@ static void xtensa_ccompare_cb(void *opaque) if (env->halted) { env->halt_clock = qemu_get_clock_ns(vm_clock); xtensa_advance_ccount(env, env->wake_ccount - env->sregs[CCOUNT]); - if (!cpu_has_work(env)) { + if (!cpu_has_work(CPU(cpu))) { env->sregs[CCOUNT] = env->wake_ccount + 1; xtensa_rearm_ccompare_timer(env); } diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h index eea6175cb9..f04da6ec4f 100644 --- a/include/qemu/cpu.h +++ b/include/qemu/cpu.h @@ -86,6 +86,16 @@ struct CPUState { */ void cpu_reset(CPUState *cpu); +/** + * qemu_cpu_has_work: + * @cpu: The vCPU to check. + * + * Checks whether the CPU has work to do. + * + * Returns: %true if the CPU has work, %false otherwise. + */ +bool qemu_cpu_has_work(CPUState *cpu); + /** * qemu_cpu_is_self: * @cpu: The vCPU to check against. diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c index 62d2a669a9..11a19ebc87 100644 --- a/target-alpha/cpu.c +++ b/target-alpha/cpu.c @@ -19,7 +19,7 @@ * */ -#include "cpu-qom.h" +#include "cpu.h" #include "qemu-common.h" diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 8f131b7325..34221fb184 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -510,8 +510,10 @@ static inline void cpu_set_tls(CPUAlphaState *env, target_ulong newtls) } #endif -static inline bool cpu_has_work(CPUAlphaState *env) +static inline bool cpu_has_work(CPUState *cpu) { + CPUAlphaState *env = &ALPHA_CPU(cpu)->env; + /* Here we are checking to see if the CPU should wake up from HALT. We will have gotten into this state only for WTINT from PALmode. */ /* ??? I'm not sure how the IPL state works with WTINT to keep a CPU diff --git a/target-arm/cpu.h b/target-arm/cpu.h index ff4de10f12..e4ff918fa4 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -718,8 +718,10 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, } } -static inline bool cpu_has_work(CPUARMState *env) +static inline bool cpu_has_work(CPUState *cpu) { + CPUARMState *env = &ARM_CPU(cpu)->env; + return env->interrupt_request & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB); } diff --git a/target-cris/cpu.h b/target-cris/cpu.h index 4f4df6d9b5..2c27506d0d 100644 --- a/target-cris/cpu.h +++ b/target-cris/cpu.h @@ -285,8 +285,10 @@ static inline void cpu_get_tb_cpu_state(CPUCRISState *env, target_ulong *pc, #define cpu_list cris_cpu_list void cris_cpu_list(FILE *f, fprintf_function cpu_fprintf); -static inline bool cpu_has_work(CPUCRISState *env) +static inline bool cpu_has_work(CPUState *cpu) { + CPUCRISState *env = &CRIS_CPU(cpu)->env; + return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI); } diff --git a/target-i386/cpu.h b/target-i386/cpu.h index d840914ebf..2d7b4c3b56 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1100,8 +1100,10 @@ static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp) #include "hw/apic.h" #endif -static inline bool cpu_has_work(CPUX86State *env) +static inline bool cpu_has_work(CPUState *cpu) { + CPUX86State *env = &X86_CPU(cpu)->env; + return ((env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_POLL)) && (env->eflags & IF_MASK)) || diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h index da80469f51..7243b4f7c7 100644 --- a/target-lm32/cpu.h +++ b/target-lm32/cpu.h @@ -253,8 +253,10 @@ static inline void cpu_get_tb_cpu_state(CPULM32State *env, target_ulong *pc, *flags = 0; } -static inline bool cpu_has_work(CPULM32State *env) +static inline bool cpu_has_work(CPUState *cpu) { + CPULM32State *env = &LM32_CPU(cpu)->env; + return env->interrupt_request & CPU_INTERRUPT_HARD; } diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index 5e6ee50969..780e2c94e7 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -257,8 +257,10 @@ static inline void cpu_get_tb_cpu_state(CPUM68KState *env, target_ulong *pc, | ((env->macsr >> 4) & 0xf); /* Bits 0-3 */ } -static inline bool cpu_has_work(CPUM68KState *env) +static inline bool cpu_has_work(CPUState *cpu) { + CPUM68KState *env = &M68K_CPU(cpu)->env; + return env->interrupt_request & CPU_INTERRUPT_HARD; } diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h index 37bbdf1591..585bbd6dbc 100644 --- a/target-microblaze/cpu.h +++ b/target-microblaze/cpu.h @@ -374,8 +374,10 @@ void cpu_unassigned_access(CPUMBState *env1, hwaddr addr, int is_write, int is_exec, int is_asi, int size); #endif -static inline bool cpu_has_work(CPUMBState *env) +static inline bool cpu_has_work(CPUState *cpu) { + CPUMBState *env = &MICROBLAZE_CPU(cpu)->env; + return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI); } diff --git a/target-mips/cpu.h b/target-mips/cpu.h index c4ca2855df..38943dec10 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -706,16 +706,17 @@ static inline int mips_vpe_active(CPUMIPSState *env) return active; } -static inline int cpu_has_work(CPUMIPSState *env) +static inline bool cpu_has_work(CPUState *cpu) { - int has_work = 0; + CPUMIPSState *env = &MIPS_CPU(cpu)->env; + bool has_work = false; /* It is implementation dependent if non-enabled interrupts wake-up the CPU, however most of the implementations only check for interrupts that can be taken. */ if ((env->interrupt_request & CPU_INTERRUPT_HARD) && cpu_mips_hw_interrupts_pending(env)) { - has_work = 1; + has_work = true; } /* MIPS-MT has the ability to halt the CPU. */ @@ -723,11 +724,11 @@ static inline int cpu_has_work(CPUMIPSState *env) /* The QEMU model will issue an _WAKE request whenever the CPUs should be woken up. */ if (env->interrupt_request & CPU_INTERRUPT_WAKE) { - has_work = 1; + has_work = true; } if (!mips_vpe_active(env)) { - has_work = 0; + has_work = false; } } return has_work; diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h index a701d364a5..d42ffb09b6 100644 --- a/target-openrisc/cpu.h +++ b/target-openrisc/cpu.h @@ -437,8 +437,10 @@ static inline int cpu_mmu_index(CPUOpenRISCState *env) } #define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_INT_0 -static inline bool cpu_has_work(CPUOpenRISCState *env) +static inline bool cpu_has_work(CPUState *cpu) { + CPUOpenRISCState *env = &OPENRISC_CPU(cpu)->env; + return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER); } diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 5574042a87..ed491d2ed2 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -2222,8 +2222,10 @@ static inline bool msr_is_64bit(CPUPPCState *env, target_ulong msr) extern void (*cpu_ppc_hypercall)(PowerPCCPU *); -static inline bool cpu_has_work(CPUPPCState *env) +static inline bool cpu_has_work(CPUState *cpu) { + CPUPPCState *env = &POWERPC_CPU(cpu)->env; + return msr_ee && (env->interrupt_request & CPU_INTERRUPT_HARD); } diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 5be6e83528..0f9a1f7340 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -977,8 +977,10 @@ static inline void cpu_inject_ext(CPUS390XState *env, uint32_t code, uint32_t pa cpu_interrupt(env, CPU_INTERRUPT_HARD); } -static inline bool cpu_has_work(CPUS390XState *env) +static inline bool cpu_has_work(CPUState *cpu) { + CPUS390XState *env = &S390_CPU(cpu)->env; + return (env->interrupt_request & CPU_INTERRUPT_HARD) && (env->psw.mask & PSW_MASK_EXT); } diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index 782159e8ba..9a0e72b1fb 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -371,8 +371,10 @@ static inline void cpu_get_tb_cpu_state(CPUSH4State *env, target_ulong *pc, | (env->movcal_backup ? TB_FLAG_PENDING_MOVCA : 0); /* Bit 4 */ } -static inline bool cpu_has_work(CPUSH4State *env) +static inline bool cpu_has_work(CPUState *cpu) { + CPUSH4State *env = &SUPERH_CPU(cpu)->env; + return env->interrupt_request & CPU_INTERRUPT_HARD; } diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index a55fe08d36..6aa82b371a 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -764,8 +764,10 @@ static inline bool tb_am_enabled(int tb_flags) #endif } -static inline bool cpu_has_work(CPUSPARCState *env1) +static inline bool cpu_has_work(CPUState *cpu) { + CPUSPARCState *env1 = &SPARC_CPU(cpu)->env; + return (env1->interrupt_request & CPU_INTERRUPT_HARD) && cpu_interrupts_enabled(env1); } diff --git a/target-unicore32/cpu.c b/target-unicore32/cpu.c index 3425bbeac9..884c101010 100644 --- a/target-unicore32/cpu.c +++ b/target-unicore32/cpu.c @@ -12,7 +12,7 @@ * or (at your option) any later version. */ -#include "cpu-qom.h" +#include "cpu.h" #include "qemu-common.h" static inline void set_feature(CPUUniCore32State *env, int feature) diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h index 06508a1278..676c5d9d99 100644 --- a/target-unicore32/cpu.h +++ b/target-unicore32/cpu.h @@ -181,8 +181,10 @@ void uc32_translate_init(void); void do_interrupt(CPUUniCore32State *); void switch_mode(CPUUniCore32State *, int); -static inline bool cpu_has_work(CPUUniCore32State *env) +static inline bool cpu_has_work(CPUState *cpu) { + CPUUniCore32State *env = &UNICORE32_CPU(cpu)->env; + return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB); } diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h index 7348277edc..74e98883bf 100644 --- a/target-xtensa/cpu.h +++ b/target-xtensa/cpu.h @@ -501,8 +501,10 @@ static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc, #include "cpu-all.h" #include "exec-all.h" -static inline int cpu_has_work(CPUXtensaState *env) +static inline int cpu_has_work(CPUState *cpu) { + CPUXtensaState *env = &XTENSA_CPU(cpu)->env; + return env->pending_irq_level; } From bee615d4b945e6d88dc37a39e40be9f105622f8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 15:13:58 +0200 Subject: [PATCH 1380/2270] target-i386: Pass X86CPU to kvm_mce_inject() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for changing cpu_x86_inject_mce() argument to X86CPU. Signed-off-by: Andreas Färber [AF: Rebased onto hwaddr] --- target-i386/kvm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index a3491a4fa1..5bf2f89c13 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -229,8 +229,9 @@ static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap, return -ENOSYS; } -static void kvm_mce_inject(CPUX86State *env, hwaddr paddr, int code) +static void kvm_mce_inject(X86CPU *cpu, hwaddr paddr, int code) { + CPUX86State *env = &cpu->env; uint64_t status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S; uint64_t mcg_status = MCG_STATUS_MCIP; @@ -256,6 +257,7 @@ static void hardware_memory_error(void) int kvm_arch_on_sigbus_vcpu(CPUX86State *env, int code, void *addr) { + X86CPU *cpu = x86_env_get_cpu(env); ram_addr_t ram_addr; hwaddr paddr; @@ -273,7 +275,7 @@ int kvm_arch_on_sigbus_vcpu(CPUX86State *env, int code, void *addr) } } kvm_hwpoison_page_add(ram_addr); - kvm_mce_inject(env, paddr, code); + kvm_mce_inject(cpu, paddr, code); } else { if (code == BUS_MCEERR_AO) { return 0; @@ -301,7 +303,7 @@ int kvm_arch_on_sigbus(int code, void *addr) return 0; } kvm_hwpoison_page_add(ram_addr); - kvm_mce_inject(first_cpu, paddr, code); + kvm_mce_inject(x86_env_get_cpu(first_cpu), paddr, code); } else { if (code == BUS_MCEERR_AO) { return 0; From 8c5cf3b6219d5d5fb61a9d6e59022fc72dab8f85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 15:22:54 +0200 Subject: [PATCH 1381/2270] target-i386: Pass X86CPU to cpu_x86_inject_mce() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for changing run_on_cpu() argument to CPUState. Signed-off-by: Andreas Färber --- monitor.c | 6 ++++-- target-i386/cpu.h | 2 +- target-i386/helper.c | 3 ++- target-i386/kvm.c | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/monitor.c b/monitor.c index eeef32e38b..c0e32d60c3 100644 --- a/monitor.c +++ b/monitor.c @@ -1988,7 +1988,8 @@ static void do_acl_remove(Monitor *mon, const QDict *qdict) #if defined(TARGET_I386) static void do_inject_mce(Monitor *mon, const QDict *qdict) { - CPUArchState *cenv; + X86CPU *cpu; + CPUX86State *cenv; int cpu_index = qdict_get_int(qdict, "cpu_index"); int bank = qdict_get_int(qdict, "bank"); uint64_t status = qdict_get_int(qdict, "status"); @@ -2001,8 +2002,9 @@ static void do_inject_mce(Monitor *mon, const QDict *qdict) flags |= MCE_INJECT_BROADCAST; } for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) { + cpu = x86_env_get_cpu(cenv); if (cenv->cpu_index == cpu_index) { - cpu_x86_inject_mce(mon, cenv, bank, status, mcg_status, addr, misc, + cpu_x86_inject_mce(mon, cpu, bank, status, mcg_status, addr, misc, flags); break; } diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 2d7b4c3b56..cdc59dc0ca 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1135,7 +1135,7 @@ void do_cpu_sipi(X86CPU *cpu); #define MCE_INJECT_BROADCAST 1 #define MCE_INJECT_UNCOND_AO 2 -void cpu_x86_inject_mce(Monitor *mon, CPUX86State *cenv, int bank, +void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank, uint64_t status, uint64_t mcg_status, uint64_t addr, uint64_t misc, int flags); diff --git a/target-i386/helper.c b/target-i386/helper.c index 0424ccf6fb..45f4bed57f 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1141,10 +1141,11 @@ static void do_inject_x86_mce(void *data) } } -void cpu_x86_inject_mce(Monitor *mon, CPUX86State *cenv, int bank, +void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank, uint64_t status, uint64_t mcg_status, uint64_t addr, uint64_t misc, int flags) { + CPUX86State *cenv = &cpu->env; MCEInjectionParams params = { .mon = mon, .env = cenv, diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 5bf2f89c13..64b837b570 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -243,7 +243,7 @@ static void kvm_mce_inject(X86CPU *cpu, hwaddr paddr, int code) status |= 0xc0; mcg_status |= MCG_STATUS_RIPV; } - cpu_x86_inject_mce(NULL, env, 9, status, mcg_status, paddr, + cpu_x86_inject_mce(NULL, cpu, 9, status, mcg_status, paddr, (MCM_ADDR_PHYS << 6) | 0xc, cpu_x86_support_mca_broadcast(env) ? MCE_INJECT_BROADCAST : 0); From f100f0b38fe43c683f437a8fa3e449d6752f6a58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 14:58:47 +0200 Subject: [PATCH 1382/2270] cpus: Pass CPUState to run_on_cpu() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPUArchState is no longer needed. Move the declaration to include/qemu/cpu.h and add documentation. Signed-off-by: Andreas Färber --- cpu-all.h | 1 - cpus.c | 3 +-- hw/kvm/apic.c | 2 +- hw/kvmvapic.c | 6 ++++-- hw/ppce500_spin.c | 2 +- include/qemu/cpu.h | 10 ++++++++++ kvm-all.c | 7 +++++-- target-i386/helper.c | 4 ++-- 8 files changed, 24 insertions(+), 11 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index 0356684e2f..c9c51b83ac 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -464,7 +464,6 @@ void cpu_watchpoint_remove_all(CPUArchState *env, int mask); #define SSTEP_NOTIMER 0x4 /* Do not Timers while single stepping */ void cpu_single_step(CPUArchState *env, int enabled); -void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data); #if !defined(CONFIG_USER_ONLY) diff --git a/cpus.c b/cpus.c index 76f32fc050..bee09b996f 100644 --- a/cpus.c +++ b/cpus.c @@ -640,9 +640,8 @@ void qemu_init_cpu_loop(void) qemu_thread_get_self(&io_thread); } -void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data) +void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data) { - CPUState *cpu = ENV_GET_CPU(env); struct qemu_work_item wi; if (qemu_cpu_is_self(cpu)) { diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c index e4a7307ca5..8b65d513db 100644 --- a/hw/kvm/apic.c +++ b/hw/kvm/apic.c @@ -143,7 +143,7 @@ static void do_inject_external_nmi(void *data) static void kvm_apic_external_nmi(APICCommonState *s) { - run_on_cpu(&s->cpu->env, do_inject_external_nmi, s); + run_on_cpu(CPU(s->cpu), do_inject_external_nmi, s); } static uint64_t kvm_apic_mem_read(void *opaque, hwaddr addr, diff --git a/hw/kvmvapic.c b/hw/kvmvapic.c index 5e0a7c9384..dc111ee8e6 100644 --- a/hw/kvmvapic.c +++ b/hw/kvmvapic.c @@ -475,11 +475,13 @@ static void vapic_enable_tpr_reporting(bool enable) VAPICEnableTPRReporting info = { .enable = enable, }; + X86CPU *cpu; CPUX86State *env; for (env = first_cpu; env != NULL; env = env->next_cpu) { + cpu = x86_env_get_cpu(env); info.apic = env->apic_state; - run_on_cpu(env, vapic_do_enable_tpr_reporting, &info); + run_on_cpu(CPU(cpu), vapic_do_enable_tpr_reporting, &info); } } @@ -717,7 +719,7 @@ static int vapic_post_load(void *opaque, int version_id) } if (s->state == VAPIC_ACTIVE) { if (smp_cpus == 1) { - run_on_cpu(first_cpu, do_vapic_enable, s); + run_on_cpu(ENV_GET_CPU(first_cpu), do_vapic_enable, s); } else { zero = g_malloc0(s->rom_state.vapic_size); cpu_physical_memory_rw(s->vapic_paddr, zero, diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c index 7f8c8428b6..c1a155bd31 100644 --- a/hw/ppce500_spin.c +++ b/hw/ppce500_spin.c @@ -163,7 +163,7 @@ static void spin_write(void *opaque, hwaddr addr, uint64_t value, .spin = curspin, }; - run_on_cpu(env, spin_kick, &kick); + run_on_cpu(CPU(kick.cpu), spin_kick, &kick); } } diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h index f04da6ec4f..33f01d9a6f 100644 --- a/include/qemu/cpu.h +++ b/include/qemu/cpu.h @@ -125,5 +125,15 @@ void qemu_cpu_kick(CPUState *cpu); */ bool cpu_is_stopped(CPUState *cpu); +/** + * run_on_cpu: + * @cpu: The vCPU to run on. + * @func: The function to be executed. + * @data: Data to pass to the function. + * + * Schedules the function @func for execution on the vCPU @cpu. + */ +void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data); + #endif diff --git a/kvm-all.c b/kvm-all.c index e41e1c9531..b6d0483576 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1500,8 +1500,10 @@ static void do_kvm_cpu_synchronize_state(void *_env) void kvm_cpu_synchronize_state(CPUArchState *env) { + CPUState *cpu = ENV_GET_CPU(env); + if (!env->kvm_vcpu_dirty) { - run_on_cpu(env, do_kvm_cpu_synchronize_state, env); + run_on_cpu(cpu, do_kvm_cpu_synchronize_state, env); } } @@ -1787,6 +1789,7 @@ static void kvm_invoke_set_guest_debug(void *data) int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap) { + CPUState *cpu = ENV_GET_CPU(env); struct kvm_set_guest_debug_data data; data.dbg.control = reinject_trap; @@ -1797,7 +1800,7 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap) kvm_arch_update_guest_debug(env, &data.dbg); data.env = env; - run_on_cpu(env, kvm_invoke_set_guest_debug, &data); + run_on_cpu(cpu, kvm_invoke_set_guest_debug, &data); return data.err; } diff --git a/target-i386/helper.c b/target-i386/helper.c index 45f4bed57f..bf206cfa97 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1177,7 +1177,7 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank, return; } - run_on_cpu(cenv, do_inject_x86_mce, ¶ms); + run_on_cpu(CPU(cpu), do_inject_x86_mce, ¶ms); if (flags & MCE_INJECT_BROADCAST) { params.bank = 1; params.status = MCI_STATUS_VAL | MCI_STATUS_UC; @@ -1189,7 +1189,7 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank, continue; } params.env = env; - run_on_cpu(cenv, do_inject_x86_mce, ¶ms); + run_on_cpu(CPU(cpu), do_inject_x86_mce, ¶ms); } } } From 9f09e18a6df39ab11cd80e203c5736af1823f3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 06:59:07 +0200 Subject: [PATCH 1383/2270] cpu: Move thread_id to CPUState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- cpu-defs.h | 1 - cpus.c | 11 ++++++----- exec.c | 5 ++++- include/qemu/cpu.h | 1 + 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/cpu-defs.h b/cpu-defs.h index b30a8e91bb..3669241faf 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -201,7 +201,6 @@ typedef struct CPUWatchpoint { int nr_cores; /* number of cores within this CPU package */ \ int nr_threads;/* number of threads within this CPU */ \ int running; /* Nonzero if cpu is currently running(usermode). */ \ - int thread_id; \ /* user data */ \ void *opaque; \ \ diff --git a/cpus.c b/cpus.c index bee09b996f..d9c332fcb8 100644 --- a/cpus.c +++ b/cpus.c @@ -737,7 +737,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg) qemu_mutex_lock(&qemu_global_mutex); qemu_thread_get_self(cpu->thread); - env->thread_id = qemu_get_thread_id(); + cpu->thread_id = qemu_get_thread_id(); cpu_single_env = env; r = kvm_init_vcpu(env); @@ -778,7 +778,7 @@ static void *qemu_dummy_cpu_thread_fn(void *arg) qemu_mutex_lock_iothread(); qemu_thread_get_self(cpu->thread); - env->thread_id = qemu_get_thread_id(); + cpu->thread_id = qemu_get_thread_id(); sigemptyset(&waitset); sigaddset(&waitset, SIG_IPI); @@ -822,7 +822,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) qemu_mutex_lock(&qemu_global_mutex); for (env = first_cpu; env != NULL; env = env->next_cpu) { cpu = ENV_GET_CPU(env); - env->thread_id = qemu_get_thread_id(); + cpu->thread_id = qemu_get_thread_id(); cpu->created = true; } qemu_cond_signal(&qemu_cpu_cond); @@ -1205,7 +1205,8 @@ CpuInfoList *qmp_query_cpus(Error **errp) CpuInfoList *head = NULL, *cur_item = NULL; CPUArchState *env; - for(env = first_cpu; env != NULL; env = env->next_cpu) { + for (env = first_cpu; env != NULL; env = env->next_cpu) { + CPUState *cpu = ENV_GET_CPU(env); CpuInfoList *info; cpu_synchronize_state(env); @@ -1215,7 +1216,7 @@ CpuInfoList *qmp_query_cpus(Error **errp) info->value->CPU = env->cpu_index; info->value->current = (env == first_cpu); info->value->halted = env->halted; - info->value->thread_id = env->thread_id; + info->value->thread_id = cpu->thread_id; #if defined(TARGET_I386) info->value->has_pc = true; info->value->pc = env->eip + env->segs[R_CS].base; diff --git a/exec.c b/exec.c index 038e40d09b..df6793812f 100644 --- a/exec.c +++ b/exec.c @@ -689,6 +689,9 @@ CPUArchState *qemu_get_cpu(int cpu) void cpu_exec_init(CPUArchState *env) { +#ifndef CONFIG_USER_ONLY + CPUState *cpu = ENV_GET_CPU(env); +#endif CPUArchState **penv; int cpu_index; @@ -707,7 +710,7 @@ void cpu_exec_init(CPUArchState *env) QTAILQ_INIT(&env->breakpoints); QTAILQ_INIT(&env->watchpoints); #ifndef CONFIG_USER_ONLY - env->thread_id = qemu_get_thread_id(); + cpu->thread_id = qemu_get_thread_id(); #endif *penv = env; #if defined(CONFIG_USER_ONLY) diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h index 33f01d9a6f..61b76982f1 100644 --- a/include/qemu/cpu.h +++ b/include/qemu/cpu.h @@ -69,6 +69,7 @@ struct CPUState { #ifdef _WIN32 HANDLE hThread; #endif + int thread_id; struct QemuCond *halt_cond; struct qemu_work_item *queued_work_first, *queued_work_last; bool thread_kicked; From 23d02d9b4bbe362a5b9cfc3ce1e5cc106eff5664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 16:56:46 +0200 Subject: [PATCH 1384/2270] target-i386: Pass X86CPU to kvm_get_mp_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for moving halted field to CPUState. Signed-off-by: Andreas Färber --- target-i386/kvm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 64b837b570..7da816f484 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1367,8 +1367,9 @@ static int kvm_put_mp_state(CPUX86State *env) return kvm_vcpu_ioctl(env, KVM_SET_MP_STATE, &mp_state); } -static int kvm_get_mp_state(CPUX86State *env) +static int kvm_get_mp_state(X86CPU *cpu) { + CPUX86State *env = &cpu->env; struct kvm_mp_state mp_state; int ret; @@ -1612,10 +1613,10 @@ int kvm_arch_put_registers(CPUX86State *env, int level) int kvm_arch_get_registers(CPUX86State *env) { - CPUState *cpu = ENV_GET_CPU(env); + X86CPU *cpu = x86_env_get_cpu(env); int ret; - assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); + assert(cpu_is_stopped(CPU(cpu)) || qemu_cpu_is_self(CPU(cpu))); ret = kvm_getput_regs(env, 0); if (ret < 0) { @@ -1637,7 +1638,7 @@ int kvm_arch_get_registers(CPUX86State *env) if (ret < 0) { return ret; } - ret = kvm_get_mp_state(env); + ret = kvm_get_mp_state(cpu); if (ret < 0) { return ret; } From 839b5630cd4f49ce10618a7bf0b705b76f3a01ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 3 May 2012 17:00:31 +0200 Subject: [PATCH 1385/2270] target-i386: Pass X86CPU to kvm_handle_halt() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for moving interrupt_request and halted fields to CPUState. Signed-off-by: Andreas Färber --- target-i386/kvm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 7da816f484..9ccbcb5be5 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1786,8 +1786,10 @@ int kvm_arch_process_async_events(CPUX86State *env) return env->halted; } -static int kvm_handle_halt(CPUX86State *env) +static int kvm_handle_halt(X86CPU *cpu) { + CPUX86State *env = &cpu->env; + if (!((env->interrupt_request & CPU_INTERRUPT_HARD) && (env->eflags & IF_MASK)) && !(env->interrupt_request & CPU_INTERRUPT_NMI)) { @@ -2001,13 +2003,14 @@ static bool host_supports_vmx(void) int kvm_arch_handle_exit(CPUX86State *env, struct kvm_run *run) { + X86CPU *cpu = x86_env_get_cpu(env); uint64_t code; int ret; switch (run->exit_reason) { case KVM_EXIT_HLT: DPRINTF("handle_hlt\n"); - ret = kvm_handle_halt(env); + ret = kvm_handle_halt(cpu); break; case KVM_EXIT_SET_TPR: ret = 0; From 38b14db34e16bb0ae1f28b7ddccb6aa11a2a96a1 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 8 Aug 2011 14:36:41 +0200 Subject: [PATCH 1386/2270] qemu-thread: add QemuSemaphore The new thread pool will use semaphores instead of condition variables, because QemuCond does not have qemu_cond_timedwait. (I also like it more this way). Signed-off-by: Paolo Bonzini --- qemu-thread-posix.c | 80 +++++++++++++++++++++++++++++++++++++++++++++ qemu-thread-posix.h | 5 +++ qemu-thread-win32.c | 35 ++++++++++++++++++++ qemu-thread-win32.h | 4 +++ qemu-thread.h | 7 ++++ 5 files changed, 131 insertions(+) diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c index 8fbabdac36..6a3d3a12a8 100644 --- a/qemu-thread-posix.c +++ b/qemu-thread-posix.c @@ -17,6 +17,9 @@ #include #include #include +#include +#include +#include #include "qemu-thread.h" static void error_exit(int err, const char *msg) @@ -115,6 +118,83 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex) error_exit(err, __func__); } +void qemu_sem_init(QemuSemaphore *sem, int init) +{ + int rc; + + rc = sem_init(&sem->sem, 0, init); + if (rc < 0) { + error_exit(errno, __func__); + } +} + +void qemu_sem_destroy(QemuSemaphore *sem) +{ + int rc; + + rc = sem_destroy(&sem->sem); + if (rc < 0) { + error_exit(errno, __func__); + } +} + +void qemu_sem_post(QemuSemaphore *sem) +{ + int rc; + + rc = sem_post(&sem->sem); + if (rc < 0) { + error_exit(errno, __func__); + } +} + +int qemu_sem_timedwait(QemuSemaphore *sem, int ms) +{ + int rc; + + if (ms <= 0) { + /* This is cheaper than sem_timedwait. */ + do { + rc = sem_trywait(&sem->sem); + } while (rc == -1 && errno == EINTR); + if (rc == -1 && errno == EAGAIN) { + return -1; + } + } else { + struct timeval tv; + struct timespec ts; + gettimeofday(&tv, NULL); + ts.tv_nsec = tv.tv_usec * 1000 + (ms % 1000) * 1000000; + ts.tv_sec = tv.tv_sec + ms / 1000; + if (ts.tv_nsec >= 1000000000) { + ts.tv_sec++; + ts.tv_nsec -= 1000000000; + } + do { + rc = sem_timedwait(&sem->sem, &ts); + } while (rc == -1 && errno == EINTR); + if (rc == -1 && errno == ETIMEDOUT) { + return -1; + } + } + if (rc < 0) { + error_exit(errno, __func__); + } + return 0; +} + +void qemu_sem_wait(QemuSemaphore *sem) +{ + int rc; + + do { + rc = sem_wait(&sem->sem); + } while (rc == -1 && errno == EINTR); + if (rc < 0) { + error_exit(errno, __func__); + } +} + void qemu_thread_create(QemuThread *thread, void *(*start_routine)(void*), void *arg, int mode) diff --git a/qemu-thread-posix.h b/qemu-thread-posix.h index ee4618e620..2542c15200 100644 --- a/qemu-thread-posix.h +++ b/qemu-thread-posix.h @@ -1,6 +1,7 @@ #ifndef __QEMU_THREAD_POSIX_H #define __QEMU_THREAD_POSIX_H 1 #include "pthread.h" +#include struct QemuMutex { pthread_mutex_t lock; @@ -10,6 +11,10 @@ struct QemuCond { pthread_cond_t cond; }; +struct QemuSemaphore { + sem_t sem; +}; + struct QemuThread { pthread_t thread; }; diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c index 177b398cc4..4b3db60f5c 100644 --- a/qemu-thread-win32.c +++ b/qemu-thread-win32.c @@ -192,6 +192,41 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex) qemu_mutex_lock(mutex); } +void qemu_sem_init(QemuSemaphore *sem, int init) +{ + /* Manual reset. */ + sem->sema = CreateSemaphore(NULL, init, LONG_MAX, NULL); +} + +void qemu_sem_destroy(QemuSemaphore *sem) +{ + CloseHandle(sem->sema); +} + +void qemu_sem_post(QemuSemaphore *sem) +{ + ReleaseSemaphore(sem->sema, 1, NULL); +} + +int qemu_sem_timedwait(QemuSemaphore *sem, int ms) +{ + int rc = WaitForSingleObject(sem->sema, ms); + if (rc == WAIT_OBJECT_0) { + return 0; + } + if (rc != WAIT_TIMEOUT) { + error_exit(GetLastError(), __func__); + } + return -1; +} + +void qemu_sem_wait(QemuSemaphore *sem) +{ + if (WaitForSingleObject(sem->sema, INFINITE) != WAIT_OBJECT_0) { + error_exit(GetLastError(), __func__); + } +} + struct QemuThreadData { /* Passed to win32_start_routine. */ void *(*start_routine)(void *); diff --git a/qemu-thread-win32.h b/qemu-thread-win32.h index b9d1be8478..13adb958f0 100644 --- a/qemu-thread-win32.h +++ b/qemu-thread-win32.h @@ -13,6 +13,10 @@ struct QemuCond { HANDLE continue_event; }; +struct QemuSemaphore { + HANDLE sema; +}; + typedef struct QemuThreadData QemuThreadData; struct QemuThread { QemuThreadData *data; diff --git a/qemu-thread.h b/qemu-thread.h index 05fdaaf50e..3ee2f6b1f9 100644 --- a/qemu-thread.h +++ b/qemu-thread.h @@ -6,6 +6,7 @@ typedef struct QemuMutex QemuMutex; typedef struct QemuCond QemuCond; +typedef struct QemuSemaphore QemuSemaphore; typedef struct QemuThread QemuThread; #ifdef _WIN32 @@ -38,6 +39,12 @@ void qemu_cond_signal(QemuCond *cond); void qemu_cond_broadcast(QemuCond *cond); void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex); +void qemu_sem_init(QemuSemaphore *sem, int init); +void qemu_sem_post(QemuSemaphore *sem); +void qemu_sem_wait(QemuSemaphore *sem); +int qemu_sem_timedwait(QemuSemaphore *sem, int ms); +void qemu_sem_destroy(QemuSemaphore *sem); + void qemu_thread_create(QemuThread *thread, void *(*start_routine)(void *), void *arg, int mode); From d354c7eccf5466ec2715a03d3f33dbfd6680dcc5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 23 Feb 2012 13:23:34 +0100 Subject: [PATCH 1387/2270] aio: add generic thread-pool facility Add a generic thread-pool. The code is roughly based on posix-aio-compat.c, with some changes, especially the following: - use QemuSemaphore instead of QemuCond; - separate the state of the thread from the return code of the worker function. The return code is totally opaque for the thread pool; - do not busy wait when doing cancellation. A more generic threadpool (but still specific to I/O so that in the future it can use special scheduling classes or PI mutexes) can have many uses: it allows more flexibility in raw-posix.c and can more easily be extended to Win32, and it will also be used to do an msync of the persistent bitmap. Signed-off-by: Paolo Bonzini --- Makefile.objs | 2 +- thread-pool.c | 282 ++++++++++++++++++++++++++++++++++++++++++++++++++ thread-pool.h | 34 ++++++ trace-events | 5 + 4 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 thread-pool.c create mode 100644 thread-pool.h diff --git a/Makefile.objs b/Makefile.objs index a8ade04c02..f8ae0316b8 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -43,7 +43,7 @@ coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o block-obj-y = iov.o cache-utils.o qemu-option.o module.o async.o block-obj-y += nbd.o block.o blockjob.o aes.o qemu-config.o -block-obj-y += qemu-progress.o qemu-sockets.o uri.o notify.o +block-obj-y += thread-pool.o qemu-progress.o qemu-sockets.o uri.o notify.o block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y) block-obj-$(CONFIG_POSIX) += posix-aio-compat.o block-obj-$(CONFIG_POSIX) += event_notifier-posix.o aio-posix.o diff --git a/thread-pool.c b/thread-pool.c new file mode 100644 index 0000000000..80749b77e0 --- /dev/null +++ b/thread-pool.c @@ -0,0 +1,282 @@ +/* + * QEMU block layer thread pool + * + * Copyright IBM, Corp. 2008 + * Copyright Red Hat, Inc. 2012 + * + * Authors: + * Anthony Liguori + * Paolo Bonzini + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ +#include "qemu-common.h" +#include "qemu-queue.h" +#include "qemu-thread.h" +#include "osdep.h" +#include "qemu-coroutine.h" +#include "trace.h" +#include "block_int.h" +#include "event_notifier.h" +#include "thread-pool.h" + +static void do_spawn_thread(void); + +typedef struct ThreadPoolElement ThreadPoolElement; + +enum ThreadState { + THREAD_QUEUED, + THREAD_ACTIVE, + THREAD_DONE, + THREAD_CANCELED, +}; + +struct ThreadPoolElement { + BlockDriverAIOCB common; + ThreadPoolFunc *func; + void *arg; + enum ThreadState state; + int ret; + + /* Access to this list is protected by lock. */ + QTAILQ_ENTRY(ThreadPoolElement) reqs; + + /* Access to this list is protected by the global mutex. */ + QLIST_ENTRY(ThreadPoolElement) all; +}; + +static EventNotifier notifier; +static QemuMutex lock; +static QemuCond check_cancel; +static QemuSemaphore sem; +static int max_threads = 64; +static QEMUBH *new_thread_bh; + +/* The following variables are protected by the global mutex. */ +static QLIST_HEAD(, ThreadPoolElement) head; + +/* The following variables are protected by lock. */ +static QTAILQ_HEAD(, ThreadPoolElement) request_list; +static int cur_threads; +static int idle_threads; +static int new_threads; /* backlog of threads we need to create */ +static int pending_threads; /* threads created but not running yet */ +static int pending_cancellations; /* whether we need a cond_broadcast */ + +static void *worker_thread(void *unused) +{ + qemu_mutex_lock(&lock); + pending_threads--; + do_spawn_thread(); + + while (1) { + ThreadPoolElement *req; + int ret; + + do { + idle_threads++; + qemu_mutex_unlock(&lock); + ret = qemu_sem_timedwait(&sem, 10000); + qemu_mutex_lock(&lock); + idle_threads--; + } while (ret == -1 && !QTAILQ_EMPTY(&request_list)); + if (ret == -1) { + break; + } + + req = QTAILQ_FIRST(&request_list); + QTAILQ_REMOVE(&request_list, req, reqs); + req->state = THREAD_ACTIVE; + qemu_mutex_unlock(&lock); + + ret = req->func(req->arg); + + qemu_mutex_lock(&lock); + req->state = THREAD_DONE; + req->ret = ret; + if (pending_cancellations) { + qemu_cond_broadcast(&check_cancel); + } + + event_notifier_set(¬ifier); + } + + cur_threads--; + qemu_mutex_unlock(&lock); + return NULL; +} + +static void do_spawn_thread(void) +{ + QemuThread t; + + /* Runs with lock taken. */ + if (!new_threads) { + return; + } + + new_threads--; + pending_threads++; + + qemu_thread_create(&t, worker_thread, NULL, QEMU_THREAD_DETACHED); +} + +static void spawn_thread_bh_fn(void *opaque) +{ + qemu_mutex_lock(&lock); + do_spawn_thread(); + qemu_mutex_unlock(&lock); +} + +static void spawn_thread(void) +{ + cur_threads++; + new_threads++; + /* If there are threads being created, they will spawn new workers, so + * we don't spend time creating many threads in a loop holding a mutex or + * starving the current vcpu. + * + * If there are no idle threads, ask the main thread to create one, so we + * inherit the correct affinity instead of the vcpu affinity. + */ + if (!pending_threads) { + qemu_bh_schedule(new_thread_bh); + } +} + +static void event_notifier_ready(EventNotifier *notifier) +{ + ThreadPoolElement *elem, *next; + + event_notifier_test_and_clear(notifier); +restart: + QLIST_FOREACH_SAFE(elem, &head, all, next) { + if (elem->state != THREAD_CANCELED && elem->state != THREAD_DONE) { + continue; + } + if (elem->state == THREAD_DONE) { + trace_thread_pool_complete(elem, elem->common.opaque, elem->ret); + } + if (elem->state == THREAD_DONE && elem->common.cb) { + qemu_mutex_lock(&lock); + int ret = elem->ret; + qemu_mutex_unlock(&lock); + QLIST_REMOVE(elem, all); + elem->common.cb(elem->common.opaque, ret); + qemu_aio_release(elem); + goto restart; + } else { + /* remove the request */ + QLIST_REMOVE(elem, all); + qemu_aio_release(elem); + } + } +} + +static int thread_pool_active(EventNotifier *notifier) +{ + return !QLIST_EMPTY(&head); +} + +static void thread_pool_cancel(BlockDriverAIOCB *acb) +{ + ThreadPoolElement *elem = (ThreadPoolElement *)acb; + + trace_thread_pool_cancel(elem, elem->common.opaque); + + qemu_mutex_lock(&lock); + if (elem->state == THREAD_QUEUED && + /* No thread has yet started working on elem. we can try to "steal" + * the item from the worker if we can get a signal from the + * semaphore. Because this is non-blocking, we can do it with + * the lock taken and ensure that elem will remain THREAD_QUEUED. + */ + qemu_sem_timedwait(&sem, 0) == 0) { + QTAILQ_REMOVE(&request_list, elem, reqs); + elem->state = THREAD_CANCELED; + event_notifier_set(¬ifier); + } else { + pending_cancellations++; + while (elem->state != THREAD_CANCELED && elem->state != THREAD_DONE) { + qemu_cond_wait(&check_cancel, &lock); + } + pending_cancellations--; + } + qemu_mutex_unlock(&lock); +} + +static AIOPool thread_pool_cb_pool = { + .aiocb_size = sizeof(ThreadPoolElement), + .cancel = thread_pool_cancel, +}; + +BlockDriverAIOCB *thread_pool_submit_aio(ThreadPoolFunc *func, void *arg, + BlockDriverCompletionFunc *cb, void *opaque) +{ + ThreadPoolElement *req; + + req = qemu_aio_get(&thread_pool_cb_pool, NULL, cb, opaque); + req->func = func; + req->arg = arg; + req->state = THREAD_QUEUED; + + QLIST_INSERT_HEAD(&head, req, all); + + trace_thread_pool_submit(req, arg); + + qemu_mutex_lock(&lock); + if (idle_threads == 0 && cur_threads < max_threads) { + spawn_thread(); + } + QTAILQ_INSERT_TAIL(&request_list, req, reqs); + qemu_mutex_unlock(&lock); + qemu_sem_post(&sem); + return &req->common; +} + +typedef struct ThreadPoolCo { + Coroutine *co; + int ret; +} ThreadPoolCo; + +static void thread_pool_co_cb(void *opaque, int ret) +{ + ThreadPoolCo *co = opaque; + + co->ret = ret; + qemu_coroutine_enter(co->co, NULL); +} + +int coroutine_fn thread_pool_submit_co(ThreadPoolFunc *func, void *arg) +{ + ThreadPoolCo tpc = { .co = qemu_coroutine_self(), .ret = -EINPROGRESS }; + assert(qemu_in_coroutine()); + thread_pool_submit_aio(func, arg, thread_pool_co_cb, &tpc); + qemu_coroutine_yield(); + return tpc.ret; +} + +void thread_pool_submit(ThreadPoolFunc *func, void *arg) +{ + thread_pool_submit_aio(func, arg, NULL, NULL); +} + +static void thread_pool_init(void) +{ + QLIST_INIT(&head); + event_notifier_init(¬ifier, false); + qemu_mutex_init(&lock); + qemu_cond_init(&check_cancel); + qemu_sem_init(&sem, 0); + qemu_aio_set_event_notifier(¬ifier, event_notifier_ready, + thread_pool_active); + + QTAILQ_INIT(&request_list); + new_thread_bh = qemu_bh_new(spawn_thread_bh_fn, NULL); +} + +block_init(thread_pool_init) diff --git a/thread-pool.h b/thread-pool.h new file mode 100644 index 0000000000..378a4ac9f9 --- /dev/null +++ b/thread-pool.h @@ -0,0 +1,34 @@ +/* + * QEMU block layer thread pool + * + * Copyright IBM, Corp. 2008 + * Copyright Red Hat, Inc. 2012 + * + * Authors: + * Anthony Liguori + * Paolo Bonzini + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ + +#ifndef QEMU_THREAD_POOL_H +#define QEMU_THREAD_POOL_H 1 + +#include "qemu-common.h" +#include "qemu-queue.h" +#include "qemu-thread.h" +#include "qemu-coroutine.h" +#include "block_int.h" + +typedef int ThreadPoolFunc(void *opaque); + +BlockDriverAIOCB *thread_pool_submit_aio(ThreadPoolFunc *func, void *arg, + BlockDriverCompletionFunc *cb, void *opaque); +int coroutine_fn thread_pool_submit_co(ThreadPoolFunc *func, void *arg); +void thread_pool_submit(ThreadPoolFunc *func, void *arg); + +#endif diff --git a/trace-events b/trace-events index e2d4580d4c..58c18ebb6c 100644 --- a/trace-events +++ b/trace-events @@ -90,6 +90,11 @@ virtio_blk_rw_complete(void *req, int ret) "req %p ret %d" virtio_blk_handle_write(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu" virtio_blk_handle_read(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu" +# thread-pool.c +thread_pool_submit(void *req, void *opaque) "req %p opaque %p" +thread_pool_complete(void *req, void *opaque, int ret) "req %p opaque %p ret %d" +thread_pool_cancel(void *req, void *opaque) "req %p opaque %p" + # posix-aio-compat.c paio_submit(void *acb, void *opaque, int64_t sector_num, int nb_sectors, int type) "acb %p opaque %p sector_num %"PRId64" nb_sectors %d type %d" paio_complete(void *acb, void *opaque, int ret) "acb %p opaque %p ret %d" From 19d092cf9ba3c01b0e22ef65c499ae7ddc28d0e8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 31 Oct 2012 10:09:11 +0100 Subject: [PATCH 1388/2270] threadpool: do not take lock in event_notifier_ready The ordering is: worker thread consumer thread ------------------------------------------------------------------- write ret event_notifier_test_and_clear wmb() read state write state rmb() event_notifier_set read ret Signed-off-by: Paolo Bonzini --- thread-pool.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/thread-pool.c b/thread-pool.c index 80749b77e0..651b32419b 100644 --- a/thread-pool.c +++ b/thread-pool.c @@ -39,6 +39,11 @@ struct ThreadPoolElement { BlockDriverAIOCB common; ThreadPoolFunc *func; void *arg; + + /* Moving state out of THREAD_QUEUED is protected by lock. After + * that, only the worker thread can write to it. Reads and writes + * of state and ret are ordered with memory barriers. + */ enum ThreadState state; int ret; @@ -95,9 +100,12 @@ static void *worker_thread(void *unused) ret = req->func(req->arg); - qemu_mutex_lock(&lock); - req->state = THREAD_DONE; req->ret = ret; + /* Write ret before state. */ + smp_wmb(); + req->state = THREAD_DONE; + + qemu_mutex_lock(&lock); if (pending_cancellations) { qemu_cond_broadcast(&check_cancel); } @@ -162,11 +170,10 @@ restart: trace_thread_pool_complete(elem, elem->common.opaque, elem->ret); } if (elem->state == THREAD_DONE && elem->common.cb) { - qemu_mutex_lock(&lock); - int ret = elem->ret; - qemu_mutex_unlock(&lock); QLIST_REMOVE(elem, all); - elem->common.cb(elem->common.opaque, ret); + /* Read state before ret. */ + smp_rmb(); + elem->common.cb(elem->common.opaque, elem->ret); qemu_aio_release(elem); goto restart; } else { From 47e6b251a5e9a47c406f2f2c0b01bb88854c98ec Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 24 May 2012 18:03:13 +0200 Subject: [PATCH 1389/2270] block: switch posix-aio-compat to threadpool This is not meant for portability, but to remove code duplication. Signed-off-by: Paolo Bonzini --- block/raw-posix-aio.h | 1 - block/raw-posix.c | 12 +- posix-aio-compat.c | 425 ++++-------------------------------------- 3 files changed, 40 insertions(+), 398 deletions(-) diff --git a/block/raw-posix-aio.h b/block/raw-posix-aio.h index ba118f616b..6725135dd4 100644 --- a/block/raw-posix-aio.h +++ b/block/raw-posix-aio.h @@ -28,7 +28,6 @@ /* posix-aio-compat.c - thread pool based implementation */ -int paio_init(void); BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque, int type); diff --git a/block/raw-posix.c b/block/raw-posix.c index 28d439fa81..9ae2c505a8 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -266,14 +266,10 @@ static int raw_open_common(BlockDriverState *bs, const char *filename, } s->fd = fd; - /* We're falling back to POSIX AIO in some cases so init always */ - if (paio_init() < 0) { - goto out_close; - } - #ifdef CONFIG_LINUX_AIO if (raw_set_aio(&s->aio_ctx, &s->use_aio, bdrv_flags)) { - goto out_close; + qemu_close(fd); + return -errno; } #endif @@ -284,10 +280,6 @@ static int raw_open_common(BlockDriverState *bs, const char *filename, #endif return 0; - -out_close: - qemu_close(fd); - return -errno; } static int raw_open(BlockDriverState *bs, const char *filename, int flags) diff --git a/posix-aio-compat.c b/posix-aio-compat.c index 96e4daf505..4a1e3d3662 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -28,13 +28,12 @@ #include "sysemu.h" #include "qemu-common.h" #include "trace.h" +#include "thread-pool.h" #include "block_int.h" #include "iov.h" #include "block/raw-posix-aio.h" -static void do_spawn_thread(void); - struct qemu_paiocb { BlockDriverAIOCB common; int aio_fildes; @@ -46,82 +45,15 @@ struct qemu_paiocb { size_t aio_nbytes; #define aio_ioctl_cmd aio_nbytes /* for QEMU_AIO_IOCTL */ off_t aio_offset; - - QTAILQ_ENTRY(qemu_paiocb) node; int aio_type; - ssize_t ret; - int active; - struct qemu_paiocb *next; }; -typedef struct PosixAioState { - int rfd, wfd; - struct qemu_paiocb *first_aio; -} PosixAioState; - - -static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; -static pthread_t thread_id; -static pthread_attr_t attr; -static int max_threads = 64; -static int cur_threads = 0; -static int idle_threads = 0; -static int new_threads = 0; /* backlog of threads we need to create */ -static int pending_threads = 0; /* threads created but not running yet */ -static QEMUBH *new_thread_bh; -static QTAILQ_HEAD(, qemu_paiocb) request_list; - #ifdef CONFIG_PREADV static int preadv_present = 1; #else static int preadv_present = 0; #endif -static void die2(int err, const char *what) -{ - fprintf(stderr, "%s failed: %s\n", what, strerror(err)); - abort(); -} - -static void die(const char *what) -{ - die2(errno, what); -} - -static void mutex_lock(pthread_mutex_t *mutex) -{ - int ret = pthread_mutex_lock(mutex); - if (ret) die2(ret, "pthread_mutex_lock"); -} - -static void mutex_unlock(pthread_mutex_t *mutex) -{ - int ret = pthread_mutex_unlock(mutex); - if (ret) die2(ret, "pthread_mutex_unlock"); -} - -static int cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, - struct timespec *ts) -{ - int ret = pthread_cond_timedwait(cond, mutex, ts); - if (ret && ret != ETIMEDOUT) die2(ret, "pthread_cond_timedwait"); - return ret; -} - -static void cond_signal(pthread_cond_t *cond) -{ - int ret = pthread_cond_signal(cond); - if (ret) die2(ret, "pthread_cond_signal"); -} - -static void thread_create(pthread_t *thread, pthread_attr_t *attr, - void *(*start_routine)(void*), void *arg) -{ - int ret = pthread_create(thread, attr, start_routine, arg); - if (ret) die2(ret, "pthread_create"); -} - static ssize_t handle_aiocb_ioctl(struct qemu_paiocb *aiocb) { int ret; @@ -310,286 +242,54 @@ static ssize_t handle_aiocb_rw(struct qemu_paiocb *aiocb) return nbytes; } -static void posix_aio_notify_event(void); - -static void *aio_thread(void *unused) +static int aio_worker(void *arg) { - mutex_lock(&lock); - pending_threads--; - mutex_unlock(&lock); - do_spawn_thread(); + struct qemu_paiocb *aiocb = arg; + ssize_t ret = 0; - while (1) { - struct qemu_paiocb *aiocb; - ssize_t ret = 0; - qemu_timeval tv; - struct timespec ts; + switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) { + case QEMU_AIO_READ: + ret = handle_aiocb_rw(aiocb); + if (ret >= 0 && ret < aiocb->aio_nbytes && aiocb->common.bs->growable) { + /* A short read means that we have reached EOF. Pad the buffer + * with zeros for bytes after EOF. */ + iov_memset(aiocb->aio_iov, aiocb->aio_niov, ret, + 0, aiocb->aio_nbytes - ret); - qemu_gettimeofday(&tv); - ts.tv_sec = tv.tv_sec + 10; - ts.tv_nsec = 0; - - mutex_lock(&lock); - - while (QTAILQ_EMPTY(&request_list) && - !(ret == ETIMEDOUT)) { - idle_threads++; - ret = cond_timedwait(&cond, &lock, &ts); - idle_threads--; + ret = aiocb->aio_nbytes; } - - if (QTAILQ_EMPTY(&request_list)) - break; - - aiocb = QTAILQ_FIRST(&request_list); - QTAILQ_REMOVE(&request_list, aiocb, node); - aiocb->active = 1; - mutex_unlock(&lock); - - switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) { - case QEMU_AIO_READ: - ret = handle_aiocb_rw(aiocb); - if (ret >= 0 && ret < aiocb->aio_nbytes && aiocb->common.bs->growable) { - /* A short read means that we have reached EOF. Pad the buffer - * with zeros for bytes after EOF. */ - iov_memset(aiocb->aio_iov, aiocb->aio_niov, ret, - 0, aiocb->aio_nbytes - ret); - - ret = aiocb->aio_nbytes; - } - break; - case QEMU_AIO_WRITE: - ret = handle_aiocb_rw(aiocb); - break; - case QEMU_AIO_FLUSH: - ret = handle_aiocb_flush(aiocb); - break; - case QEMU_AIO_IOCTL: - ret = handle_aiocb_ioctl(aiocb); - break; - default: - fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type); + if (ret == aiocb->aio_nbytes) { + ret = 0; + } else if (ret >= 0 && ret < aiocb->aio_nbytes) { ret = -EINVAL; - break; } - - mutex_lock(&lock); - aiocb->ret = ret; - mutex_unlock(&lock); - - posix_aio_notify_event(); - } - - cur_threads--; - mutex_unlock(&lock); - - return NULL; -} - -static void do_spawn_thread(void) -{ - sigset_t set, oldset; - - mutex_lock(&lock); - if (!new_threads) { - mutex_unlock(&lock); - return; - } - - new_threads--; - pending_threads++; - - mutex_unlock(&lock); - - /* block all signals */ - if (sigfillset(&set)) die("sigfillset"); - if (sigprocmask(SIG_SETMASK, &set, &oldset)) die("sigprocmask"); - - thread_create(&thread_id, &attr, aio_thread, NULL); - - if (sigprocmask(SIG_SETMASK, &oldset, NULL)) die("sigprocmask restore"); -} - -static void spawn_thread_bh_fn(void *opaque) -{ - do_spawn_thread(); -} - -static void spawn_thread(void) -{ - cur_threads++; - new_threads++; - /* If there are threads being created, they will spawn new workers, so - * we don't spend time creating many threads in a loop holding a mutex or - * starving the current vcpu. - * - * If there are no idle threads, ask the main thread to create one, so we - * inherit the correct affinity instead of the vcpu affinity. - */ - if (!pending_threads) { - qemu_bh_schedule(new_thread_bh); - } -} - -static void qemu_paio_submit(struct qemu_paiocb *aiocb) -{ - aiocb->ret = -EINPROGRESS; - aiocb->active = 0; - mutex_lock(&lock); - if (idle_threads == 0 && cur_threads < max_threads) - spawn_thread(); - QTAILQ_INSERT_TAIL(&request_list, aiocb, node); - mutex_unlock(&lock); - cond_signal(&cond); -} - -static ssize_t qemu_paio_return(struct qemu_paiocb *aiocb) -{ - ssize_t ret; - - mutex_lock(&lock); - ret = aiocb->ret; - mutex_unlock(&lock); - - return ret; -} - -static int qemu_paio_error(struct qemu_paiocb *aiocb) -{ - ssize_t ret = qemu_paio_return(aiocb); - - if (ret < 0) - ret = -ret; - else - ret = 0; - - return ret; -} - -static void posix_aio_read(void *opaque) -{ - PosixAioState *s = opaque; - struct qemu_paiocb *acb, **pacb; - int ret; - ssize_t len; - - /* read all bytes from signal pipe */ - for (;;) { - char bytes[16]; - - len = read(s->rfd, bytes, sizeof(bytes)); - if (len == -1 && errno == EINTR) - continue; /* try again */ - if (len == sizeof(bytes)) - continue; /* more to read */ + break; + case QEMU_AIO_WRITE: + ret = handle_aiocb_rw(aiocb); + if (ret == aiocb->aio_nbytes) { + ret = 0; + } else if (ret >= 0 && ret < aiocb->aio_nbytes) { + ret = -EINVAL; + } + break; + case QEMU_AIO_FLUSH: + ret = handle_aiocb_flush(aiocb); + break; + case QEMU_AIO_IOCTL: + ret = handle_aiocb_ioctl(aiocb); + break; + default: + fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type); + ret = -EINVAL; break; } - for(;;) { - pacb = &s->first_aio; - for(;;) { - acb = *pacb; - if (!acb) - return; - - ret = qemu_paio_error(acb); - if (ret == ECANCELED) { - /* remove the request */ - *pacb = acb->next; - qemu_aio_release(acb); - } else if (ret != EINPROGRESS) { - /* end of aio */ - if (ret == 0) { - ret = qemu_paio_return(acb); - if (ret == acb->aio_nbytes) - ret = 0; - else - ret = -EINVAL; - } else { - ret = -ret; - } - - trace_paio_complete(acb, acb->common.opaque, ret); - - /* remove the request */ - *pacb = acb->next; - /* call the callback */ - acb->common.cb(acb->common.opaque, ret); - qemu_aio_release(acb); - break; - } else { - pacb = &acb->next; - } - } - } -} - -static int posix_aio_flush(void *opaque) -{ - PosixAioState *s = opaque; - return !!s->first_aio; -} - -static PosixAioState *posix_aio_state; - -static void posix_aio_notify_event(void) -{ - char byte = 0; - ssize_t ret; - - ret = write(posix_aio_state->wfd, &byte, sizeof(byte)); - if (ret < 0 && errno != EAGAIN) - die("write()"); -} - -static void paio_remove(struct qemu_paiocb *acb) -{ - struct qemu_paiocb **pacb; - - /* remove the callback from the queue */ - pacb = &posix_aio_state->first_aio; - for(;;) { - if (*pacb == NULL) { - fprintf(stderr, "paio_remove: aio request not found!\n"); - break; - } else if (*pacb == acb) { - *pacb = acb->next; - qemu_aio_release(acb); - break; - } - pacb = &(*pacb)->next; - } -} - -static void paio_cancel(BlockDriverAIOCB *blockacb) -{ - struct qemu_paiocb *acb = (struct qemu_paiocb *)blockacb; - int active = 0; - - trace_paio_cancel(acb, acb->common.opaque); - - mutex_lock(&lock); - if (!acb->active) { - QTAILQ_REMOVE(&request_list, acb, node); - acb->ret = -ECANCELED; - } else if (acb->ret == -EINPROGRESS) { - active = 1; - } - mutex_unlock(&lock); - - if (active) { - /* fail safe: if the aio could not be canceled, we wait for - it */ - while (qemu_paio_error(acb) == EINPROGRESS) - ; - } - - paio_remove(acb); + qemu_aio_release(aiocb); + return ret; } static AIOPool raw_aio_pool = { .aiocb_size = sizeof(struct qemu_paiocb), - .cancel = paio_cancel, }; BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd, @@ -609,12 +309,8 @@ BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd, acb->aio_nbytes = nb_sectors * 512; acb->aio_offset = sector_num * 512; - acb->next = posix_aio_state->first_aio; - posix_aio_state->first_aio = acb; - trace_paio_submit(acb, opaque, sector_num, nb_sectors, type); - qemu_paio_submit(acb); - return &acb->common; + return thread_pool_submit_aio(aio_worker, acb, cb, opaque); } BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd, @@ -630,50 +326,5 @@ BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd, acb->aio_ioctl_buf = buf; acb->aio_ioctl_cmd = req; - acb->next = posix_aio_state->first_aio; - posix_aio_state->first_aio = acb; - - qemu_paio_submit(acb); - return &acb->common; -} - -int paio_init(void) -{ - PosixAioState *s; - int fds[2]; - int ret; - - if (posix_aio_state) - return 0; - - s = g_malloc(sizeof(PosixAioState)); - - s->first_aio = NULL; - if (qemu_pipe(fds) == -1) { - fprintf(stderr, "failed to create pipe\n"); - g_free(s); - return -1; - } - - s->rfd = fds[0]; - s->wfd = fds[1]; - - fcntl(s->rfd, F_SETFL, O_NONBLOCK); - fcntl(s->wfd, F_SETFL, O_NONBLOCK); - - qemu_aio_set_fd_handler(s->rfd, posix_aio_read, NULL, posix_aio_flush, s); - - ret = pthread_attr_init(&attr); - if (ret) - die2(ret, "pthread_attr_init"); - - ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - if (ret) - die2(ret, "pthread_attr_setdetachstate"); - - QTAILQ_INIT(&request_list); - new_thread_bh = qemu_bh_new(spawn_thread_bh_fn, NULL); - - posix_aio_state = s; - return 0; + return thread_pool_submit_aio(aio_worker, acb, cb, opaque); } From de81a169366c2e3e0c47d0be637cc450b71aac67 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 25 May 2012 11:46:27 +0200 Subject: [PATCH 1390/2270] raw: merge posix-aio-compat.c into block/raw-posix.c Making the qemu_paiocb specific to raw devices will let us access members of the BDRVRawState arbitrarily. Signed-off-by: Paolo Bonzini --- Makefile.objs | 1 - block/raw-posix-aio.h | 8 - block/raw-posix.c | 294 +++++++++++++++++++++++++++++++++++++ posix-aio-compat.c | 330 ------------------------------------------ 4 files changed, 294 insertions(+), 339 deletions(-) delete mode 100644 posix-aio-compat.c diff --git a/Makefile.objs b/Makefile.objs index f8ae0316b8..35c2355e82 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -45,7 +45,6 @@ block-obj-y = iov.o cache-utils.o qemu-option.o module.o async.o block-obj-y += nbd.o block.o blockjob.o aes.o qemu-config.o block-obj-y += thread-pool.o qemu-progress.o qemu-sockets.o uri.o notify.o block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y) -block-obj-$(CONFIG_POSIX) += posix-aio-compat.o block-obj-$(CONFIG_POSIX) += event_notifier-posix.o aio-posix.o block-obj-$(CONFIG_WIN32) += event_notifier-win32.o aio-win32.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o diff --git a/block/raw-posix-aio.h b/block/raw-posix-aio.h index 6725135dd4..c714367401 100644 --- a/block/raw-posix-aio.h +++ b/block/raw-posix-aio.h @@ -27,14 +27,6 @@ #define QEMU_AIO_MISALIGNED 0x1000 -/* posix-aio-compat.c - thread pool based implementation */ -BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque, int type); -BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd, - unsigned long int req, void *buf, - BlockDriverCompletionFunc *cb, void *opaque); - /* linux-aio.c - Linux native implementation */ void *laio_init(void); BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, diff --git a/block/raw-posix.c b/block/raw-posix.c index 9ae2c505a8..4d6d5df5bc 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -27,6 +27,9 @@ #include "qemu-log.h" #include "block_int.h" #include "module.h" +#include "trace.h" +#include "thread-pool.h" +#include "iov.h" #include "block/raw-posix-aio.h" #if defined(__APPLE__) && (__MACH__) @@ -149,6 +152,20 @@ typedef struct BDRVRawReopenState { static int fd_open(BlockDriverState *bs); static int64_t raw_getlength(BlockDriverState *bs); +typedef struct RawPosixAIOData { + BlockDriverState *bs; + int aio_fildes; + union { + struct iovec *aio_iov; + void *aio_ioctl_buf; + }; + int aio_niov; + size_t aio_nbytes; +#define aio_ioctl_cmd aio_nbytes /* for QEMU_AIO_IOCTL */ + off_t aio_offset; + int aio_type; +} RawPosixAIOData; + #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) static int cdrom_reopen(BlockDriverState *bs); #endif @@ -426,6 +443,283 @@ static int qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov) return 1; } +static ssize_t handle_aiocb_ioctl(RawPosixAIOData *aiocb) +{ + int ret; + + ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_ioctl_buf); + if (ret == -1) { + return -errno; + } + + /* + * This looks weird, but the aio code only considers a request + * successful if it has written the full number of bytes. + * + * Now we overload aio_nbytes as aio_ioctl_cmd for the ioctl command, + * so in fact we return the ioctl command here to make posix_aio_read() + * happy.. + */ + return aiocb->aio_nbytes; +} + +static ssize_t handle_aiocb_flush(RawPosixAIOData *aiocb) +{ + int ret; + + ret = qemu_fdatasync(aiocb->aio_fildes); + if (ret == -1) { + return -errno; + } + return 0; +} + +#ifdef CONFIG_PREADV + +static bool preadv_present = true; + +static ssize_t +qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset) +{ + return preadv(fd, iov, nr_iov, offset); +} + +static ssize_t +qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset) +{ + return pwritev(fd, iov, nr_iov, offset); +} + +#else + +static bool preadv_present = false; + +static ssize_t +qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset) +{ + return -ENOSYS; +} + +static ssize_t +qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset) +{ + return -ENOSYS; +} + +#endif + +static ssize_t handle_aiocb_rw_vector(RawPosixAIOData *aiocb) +{ + ssize_t len; + + do { + if (aiocb->aio_type & QEMU_AIO_WRITE) + len = qemu_pwritev(aiocb->aio_fildes, + aiocb->aio_iov, + aiocb->aio_niov, + aiocb->aio_offset); + else + len = qemu_preadv(aiocb->aio_fildes, + aiocb->aio_iov, + aiocb->aio_niov, + aiocb->aio_offset); + } while (len == -1 && errno == EINTR); + + if (len == -1) { + return -errno; + } + return len; +} + +/* + * Read/writes the data to/from a given linear buffer. + * + * Returns the number of bytes handles or -errno in case of an error. Short + * reads are only returned if the end of the file is reached. + */ +static ssize_t handle_aiocb_rw_linear(RawPosixAIOData *aiocb, char *buf) +{ + ssize_t offset = 0; + ssize_t len; + + while (offset < aiocb->aio_nbytes) { + if (aiocb->aio_type & QEMU_AIO_WRITE) { + len = pwrite(aiocb->aio_fildes, + (const char *)buf + offset, + aiocb->aio_nbytes - offset, + aiocb->aio_offset + offset); + } else { + len = pread(aiocb->aio_fildes, + buf + offset, + aiocb->aio_nbytes - offset, + aiocb->aio_offset + offset); + } + if (len == -1 && errno == EINTR) { + continue; + } else if (len == -1) { + offset = -errno; + break; + } else if (len == 0) { + break; + } + offset += len; + } + + return offset; +} + +static ssize_t handle_aiocb_rw(RawPosixAIOData *aiocb) +{ + ssize_t nbytes; + char *buf; + + if (!(aiocb->aio_type & QEMU_AIO_MISALIGNED)) { + /* + * If there is just a single buffer, and it is properly aligned + * we can just use plain pread/pwrite without any problems. + */ + if (aiocb->aio_niov == 1) { + return handle_aiocb_rw_linear(aiocb, aiocb->aio_iov->iov_base); + } + /* + * We have more than one iovec, and all are properly aligned. + * + * Try preadv/pwritev first and fall back to linearizing the + * buffer if it's not supported. + */ + if (preadv_present) { + nbytes = handle_aiocb_rw_vector(aiocb); + if (nbytes == aiocb->aio_nbytes || + (nbytes < 0 && nbytes != -ENOSYS)) { + return nbytes; + } + preadv_present = false; + } + + /* + * XXX(hch): short read/write. no easy way to handle the reminder + * using these interfaces. For now retry using plain + * pread/pwrite? + */ + } + + /* + * Ok, we have to do it the hard way, copy all segments into + * a single aligned buffer. + */ + buf = qemu_blockalign(aiocb->bs, aiocb->aio_nbytes); + if (aiocb->aio_type & QEMU_AIO_WRITE) { + char *p = buf; + int i; + + for (i = 0; i < aiocb->aio_niov; ++i) { + memcpy(p, aiocb->aio_iov[i].iov_base, aiocb->aio_iov[i].iov_len); + p += aiocb->aio_iov[i].iov_len; + } + } + + nbytes = handle_aiocb_rw_linear(aiocb, buf); + if (!(aiocb->aio_type & QEMU_AIO_WRITE)) { + char *p = buf; + size_t count = aiocb->aio_nbytes, copy; + int i; + + for (i = 0; i < aiocb->aio_niov && count; ++i) { + copy = count; + if (copy > aiocb->aio_iov[i].iov_len) { + copy = aiocb->aio_iov[i].iov_len; + } + memcpy(aiocb->aio_iov[i].iov_base, p, copy); + p += copy; + count -= copy; + } + } + qemu_vfree(buf); + + return nbytes; +} + +static int aio_worker(void *arg) +{ + RawPosixAIOData *aiocb = arg; + ssize_t ret = 0; + + switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) { + case QEMU_AIO_READ: + ret = handle_aiocb_rw(aiocb); + if (ret >= 0 && ret < aiocb->aio_nbytes && aiocb->bs->growable) { + iov_memset(aiocb->aio_iov, aiocb->aio_niov, ret, + 0, aiocb->aio_nbytes - ret); + + ret = aiocb->aio_nbytes; + } + if (ret == aiocb->aio_nbytes) { + ret = 0; + } else if (ret >= 0 && ret < aiocb->aio_nbytes) { + ret = -EINVAL; + } + break; + case QEMU_AIO_WRITE: + ret = handle_aiocb_rw(aiocb); + if (ret == aiocb->aio_nbytes) { + ret = 0; + } else if (ret >= 0 && ret < aiocb->aio_nbytes) { + ret = -EINVAL; + } + break; + case QEMU_AIO_FLUSH: + ret = handle_aiocb_flush(aiocb); + break; + case QEMU_AIO_IOCTL: + ret = handle_aiocb_ioctl(aiocb); + break; + default: + fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type); + ret = -EINVAL; + break; + } + + g_slice_free(RawPosixAIOData, aiocb); + return ret; +} + +static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque, int type) +{ + RawPosixAIOData *acb = g_slice_new(RawPosixAIOData); + + acb->bs = bs; + acb->aio_type = type; + acb->aio_fildes = fd; + + if (qiov) { + acb->aio_iov = qiov->iov; + acb->aio_niov = qiov->niov; + } + acb->aio_nbytes = nb_sectors * 512; + acb->aio_offset = sector_num * 512; + + trace_paio_submit(acb, opaque, sector_num, nb_sectors, type); + return thread_pool_submit_aio(aio_worker, acb, cb, opaque); +} + +static BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd, + unsigned long int req, void *buf, + BlockDriverCompletionFunc *cb, void *opaque) +{ + RawPosixAIOData *acb = g_slice_new(RawPosixAIOData); + + acb->bs = bs; + acb->aio_type = QEMU_AIO_IOCTL; + acb->aio_fildes = fd; + acb->aio_offset = 0; + acb->aio_ioctl_buf = buf; + acb->aio_ioctl_cmd = req; + + return thread_pool_submit_aio(aio_worker, acb, cb, opaque); +} + static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque, int type) diff --git a/posix-aio-compat.c b/posix-aio-compat.c deleted file mode 100644 index 4a1e3d3662..0000000000 --- a/posix-aio-compat.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * QEMU posix-aio emulation - * - * Copyright IBM, Corp. 2008 - * - * Authors: - * Anthony Liguori - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "qemu-queue.h" -#include "osdep.h" -#include "sysemu.h" -#include "qemu-common.h" -#include "trace.h" -#include "thread-pool.h" -#include "block_int.h" -#include "iov.h" - -#include "block/raw-posix-aio.h" - -struct qemu_paiocb { - BlockDriverAIOCB common; - int aio_fildes; - union { - struct iovec *aio_iov; - void *aio_ioctl_buf; - }; - int aio_niov; - size_t aio_nbytes; -#define aio_ioctl_cmd aio_nbytes /* for QEMU_AIO_IOCTL */ - off_t aio_offset; - int aio_type; -}; - -#ifdef CONFIG_PREADV -static int preadv_present = 1; -#else -static int preadv_present = 0; -#endif - -static ssize_t handle_aiocb_ioctl(struct qemu_paiocb *aiocb) -{ - int ret; - - ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_ioctl_buf); - if (ret == -1) - return -errno; - - /* - * This looks weird, but the aio code only considers a request - * successful if it has written the full number of bytes. - * - * Now we overload aio_nbytes as aio_ioctl_cmd for the ioctl command, - * so in fact we return the ioctl command here to make posix_aio_read() - * happy.. - */ - return aiocb->aio_nbytes; -} - -static ssize_t handle_aiocb_flush(struct qemu_paiocb *aiocb) -{ - int ret; - - ret = qemu_fdatasync(aiocb->aio_fildes); - if (ret == -1) - return -errno; - return 0; -} - -#ifdef CONFIG_PREADV - -static ssize_t -qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset) -{ - return preadv(fd, iov, nr_iov, offset); -} - -static ssize_t -qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset) -{ - return pwritev(fd, iov, nr_iov, offset); -} - -#else - -static ssize_t -qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset) -{ - return -ENOSYS; -} - -static ssize_t -qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset) -{ - return -ENOSYS; -} - -#endif - -static ssize_t handle_aiocb_rw_vector(struct qemu_paiocb *aiocb) -{ - ssize_t len; - - do { - if (aiocb->aio_type & QEMU_AIO_WRITE) - len = qemu_pwritev(aiocb->aio_fildes, - aiocb->aio_iov, - aiocb->aio_niov, - aiocb->aio_offset); - else - len = qemu_preadv(aiocb->aio_fildes, - aiocb->aio_iov, - aiocb->aio_niov, - aiocb->aio_offset); - } while (len == -1 && errno == EINTR); - - if (len == -1) - return -errno; - return len; -} - -/* - * Read/writes the data to/from a given linear buffer. - * - * Returns the number of bytes handles or -errno in case of an error. Short - * reads are only returned if the end of the file is reached. - */ -static ssize_t handle_aiocb_rw_linear(struct qemu_paiocb *aiocb, char *buf) -{ - ssize_t offset = 0; - ssize_t len; - - while (offset < aiocb->aio_nbytes) { - if (aiocb->aio_type & QEMU_AIO_WRITE) - len = pwrite(aiocb->aio_fildes, - (const char *)buf + offset, - aiocb->aio_nbytes - offset, - aiocb->aio_offset + offset); - else - len = pread(aiocb->aio_fildes, - buf + offset, - aiocb->aio_nbytes - offset, - aiocb->aio_offset + offset); - - if (len == -1 && errno == EINTR) - continue; - else if (len == -1) { - offset = -errno; - break; - } else if (len == 0) - break; - - offset += len; - } - - return offset; -} - -static ssize_t handle_aiocb_rw(struct qemu_paiocb *aiocb) -{ - ssize_t nbytes; - char *buf; - - if (!(aiocb->aio_type & QEMU_AIO_MISALIGNED)) { - /* - * If there is just a single buffer, and it is properly aligned - * we can just use plain pread/pwrite without any problems. - */ - if (aiocb->aio_niov == 1) - return handle_aiocb_rw_linear(aiocb, aiocb->aio_iov->iov_base); - - /* - * We have more than one iovec, and all are properly aligned. - * - * Try preadv/pwritev first and fall back to linearizing the - * buffer if it's not supported. - */ - if (preadv_present) { - nbytes = handle_aiocb_rw_vector(aiocb); - if (nbytes == aiocb->aio_nbytes) - return nbytes; - if (nbytes < 0 && nbytes != -ENOSYS) - return nbytes; - preadv_present = 0; - } - - /* - * XXX(hch): short read/write. no easy way to handle the reminder - * using these interfaces. For now retry using plain - * pread/pwrite? - */ - } - - /* - * Ok, we have to do it the hard way, copy all segments into - * a single aligned buffer. - */ - buf = qemu_blockalign(aiocb->common.bs, aiocb->aio_nbytes); - if (aiocb->aio_type & QEMU_AIO_WRITE) { - char *p = buf; - int i; - - for (i = 0; i < aiocb->aio_niov; ++i) { - memcpy(p, aiocb->aio_iov[i].iov_base, aiocb->aio_iov[i].iov_len); - p += aiocb->aio_iov[i].iov_len; - } - } - - nbytes = handle_aiocb_rw_linear(aiocb, buf); - if (!(aiocb->aio_type & QEMU_AIO_WRITE)) { - char *p = buf; - size_t count = aiocb->aio_nbytes, copy; - int i; - - for (i = 0; i < aiocb->aio_niov && count; ++i) { - copy = count; - if (copy > aiocb->aio_iov[i].iov_len) - copy = aiocb->aio_iov[i].iov_len; - memcpy(aiocb->aio_iov[i].iov_base, p, copy); - p += copy; - count -= copy; - } - } - qemu_vfree(buf); - - return nbytes; -} - -static int aio_worker(void *arg) -{ - struct qemu_paiocb *aiocb = arg; - ssize_t ret = 0; - - switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) { - case QEMU_AIO_READ: - ret = handle_aiocb_rw(aiocb); - if (ret >= 0 && ret < aiocb->aio_nbytes && aiocb->common.bs->growable) { - /* A short read means that we have reached EOF. Pad the buffer - * with zeros for bytes after EOF. */ - iov_memset(aiocb->aio_iov, aiocb->aio_niov, ret, - 0, aiocb->aio_nbytes - ret); - - ret = aiocb->aio_nbytes; - } - if (ret == aiocb->aio_nbytes) { - ret = 0; - } else if (ret >= 0 && ret < aiocb->aio_nbytes) { - ret = -EINVAL; - } - break; - case QEMU_AIO_WRITE: - ret = handle_aiocb_rw(aiocb); - if (ret == aiocb->aio_nbytes) { - ret = 0; - } else if (ret >= 0 && ret < aiocb->aio_nbytes) { - ret = -EINVAL; - } - break; - case QEMU_AIO_FLUSH: - ret = handle_aiocb_flush(aiocb); - break; - case QEMU_AIO_IOCTL: - ret = handle_aiocb_ioctl(aiocb); - break; - default: - fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type); - ret = -EINVAL; - break; - } - - qemu_aio_release(aiocb); - return ret; -} - -static AIOPool raw_aio_pool = { - .aiocb_size = sizeof(struct qemu_paiocb), -}; - -BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque, int type) -{ - struct qemu_paiocb *acb; - - acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque); - acb->aio_type = type; - acb->aio_fildes = fd; - - if (qiov) { - acb->aio_iov = qiov->iov; - acb->aio_niov = qiov->niov; - } - acb->aio_nbytes = nb_sectors * 512; - acb->aio_offset = sector_num * 512; - - trace_paio_submit(acb, opaque, sector_num, nb_sectors, type); - return thread_pool_submit_aio(aio_worker, acb, cb, opaque); -} - -BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd, - unsigned long int req, void *buf, - BlockDriverCompletionFunc *cb, void *opaque) -{ - struct qemu_paiocb *acb; - - acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque); - acb->aio_type = QEMU_AIO_IOCTL; - acb->aio_fildes = fd; - acb->aio_offset = 0; - acb->aio_ioctl_buf = buf; - acb->aio_ioctl_cmd = req; - - return thread_pool_submit_aio(aio_worker, acb, cb, opaque); -} From 9f8540ecef6fc5ededa825d766c8bcd1987884dd Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 9 Jun 2012 10:57:37 +0200 Subject: [PATCH 1391/2270] raw-posix: rename raw-posix-aio.h, hide unavailable prototypes Signed-off-by: Paolo Bonzini --- block/{raw-posix-aio.h => raw-aio.h} | 10 ++++++---- block/raw-posix.c | 2 +- linux-aio.c | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) rename block/{raw-posix-aio.h => raw-aio.h} (86%) diff --git a/block/raw-posix-aio.h b/block/raw-aio.h similarity index 86% rename from block/raw-posix-aio.h rename to block/raw-aio.h index c714367401..b3bb07377e 100644 --- a/block/raw-posix-aio.h +++ b/block/raw-aio.h @@ -1,5 +1,5 @@ /* - * QEMU Posix block I/O backend AIO support + * Declarations for AIO in the raw protocol * * Copyright IBM, Corp. 2008 * @@ -12,8 +12,8 @@ * Contributions after 2012-01-13 are licensed under the terms of the * GNU GPL, version 2 or (at your option) any later version. */ -#ifndef QEMU_RAW_POSIX_AIO_H -#define QEMU_RAW_POSIX_AIO_H +#ifndef QEMU_RAW_AIO_H +#define QEMU_RAW_AIO_H /* AIO request types */ #define QEMU_AIO_READ 0x0001 @@ -28,9 +28,11 @@ /* linux-aio.c - Linux native implementation */ +#ifdef CONFIG_LINUX_AIO void *laio_init(void); BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque, int type); +#endif -#endif /* QEMU_RAW_POSIX_AIO_H */ +#endif /* QEMU_RAW_AIO_H */ diff --git a/block/raw-posix.c b/block/raw-posix.c index 4d6d5df5bc..f2f0404f6f 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -30,7 +30,7 @@ #include "trace.h" #include "thread-pool.h" #include "iov.h" -#include "block/raw-posix-aio.h" +#include "raw-aio.h" #if defined(__APPLE__) && (__MACH__) #include diff --git a/linux-aio.c b/linux-aio.c index d1afb460c2..6ca984dbe8 100644 --- a/linux-aio.c +++ b/linux-aio.c @@ -10,7 +10,7 @@ #include "qemu-common.h" #include "qemu-aio.h" #include "qemu-queue.h" -#include "block/raw-posix-aio.h" +#include "block/raw-aio.h" #include "event_notifier.h" #include From fc4edb84bfc49e4ed6c1a54c8ac037e9a7479fc8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 9 Jun 2012 04:48:28 +0200 Subject: [PATCH 1392/2270] raw-win32: add emulated AIO support Signed-off-by: Paolo Bonzini --- block/raw-win32.c | 187 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 138 insertions(+), 49 deletions(-) diff --git a/block/raw-win32.c b/block/raw-win32.c index 78c830648b..ffd86e3f38 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -25,6 +25,10 @@ #include "qemu-timer.h" #include "block_int.h" #include "module.h" +#include "raw-aio.h" +#include "trace.h" +#include "thread-pool.h" +#include "iov.h" #include #include @@ -32,12 +36,127 @@ #define FTYPE_CD 1 #define FTYPE_HARDDISK 2 +typedef struct RawWin32AIOData { + BlockDriverState *bs; + HANDLE hfile; + struct iovec *aio_iov; + int aio_niov; + size_t aio_nbytes; + off64_t aio_offset; + int aio_type; +} RawWin32AIOData; + typedef struct BDRVRawState { HANDLE hfile; int type; char drive_path[16]; /* format: "d:\" */ } BDRVRawState; +/* + * Read/writes the data to/from a given linear buffer. + * + * Returns the number of bytes handles or -errno in case of an error. Short + * reads are only returned if the end of the file is reached. + */ +static size_t handle_aiocb_rw(RawWin32AIOData *aiocb) +{ + size_t offset = 0; + int i; + + for (i = 0; i < aiocb->aio_niov; i++) { + OVERLAPPED ov; + DWORD ret, ret_count, len; + + memset(&ov, 0, sizeof(ov)); + ov.Offset = (aiocb->aio_offset + offset); + ov.OffsetHigh = (aiocb->aio_offset + offset) >> 32; + len = aiocb->aio_iov[i].iov_len; + if (aiocb->aio_type & QEMU_AIO_WRITE) { + ret = WriteFile(aiocb->hfile, aiocb->aio_iov[i].iov_base, + len, &ret_count, &ov); + } else { + ret = ReadFile(aiocb->hfile, aiocb->aio_iov[i].iov_base, + len, &ret_count, &ov); + } + if (!ret) { + ret_count = 0; + } + if (ret_count != len) { + break; + } + offset += len; + } + + return offset; +} + +static int aio_worker(void *arg) +{ + RawWin32AIOData *aiocb = arg; + ssize_t ret = 0; + size_t count; + + switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) { + case QEMU_AIO_READ: + count = handle_aiocb_rw(aiocb); + if (count < aiocb->aio_nbytes && aiocb->bs->growable) { + /* A short read means that we have reached EOF. Pad the buffer + * with zeros for bytes after EOF. */ + iov_memset(aiocb->aio_iov, aiocb->aio_niov, count, + 0, aiocb->aio_nbytes - count); + + count = aiocb->aio_nbytes; + } + if (count == aiocb->aio_nbytes) { + ret = 0; + } else { + ret = -EINVAL; + } + break; + case QEMU_AIO_WRITE: + count = handle_aiocb_rw(aiocb); + if (count == aiocb->aio_nbytes) { + count = 0; + } else { + count = -EINVAL; + } + break; + case QEMU_AIO_FLUSH: + if (!FlushFileBuffers(aiocb->hfile)) { + return -EIO; + } + break; + default: + fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type); + ret = -EINVAL; + break; + } + + g_slice_free(RawWin32AIOData, aiocb); + return ret; +} + +static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque, int type) +{ + RawWin32AIOData *acb = g_slice_new(RawWin32AIOData); + + acb->bs = bs; + acb->hfile = hfile; + acb->aio_type = type; + + if (qiov) { + acb->aio_iov = qiov->iov; + acb->aio_niov = qiov->niov; + } + acb->aio_nbytes = nb_sectors * 512; + acb->aio_offset = sector_num * 512; + + trace_paio_submit(acb, opaque, sector_num, nb_sectors, type); + return thread_pool_submit_aio(aio_worker, acb, cb, opaque); +} + int qemu_ftruncate64(int fd, int64_t length) { LARGE_INTEGER li; @@ -117,59 +236,29 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags) return 0; } -static int raw_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) +static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { BDRVRawState *s = bs->opaque; - OVERLAPPED ov; - DWORD ret_count; - int ret; - int64_t offset = sector_num * 512; - int count = nb_sectors * 512; - - memset(&ov, 0, sizeof(ov)); - ov.Offset = offset; - ov.OffsetHigh = offset >> 32; - ret = ReadFile(s->hfile, buf, count, &ret_count, &ov); - if (!ret) - return ret_count; - if (ret_count == count) - ret_count = 0; - return ret_count; + return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors, + cb, opaque, QEMU_AIO_READ); } -static int raw_write(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors) +static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { BDRVRawState *s = bs->opaque; - OVERLAPPED ov; - DWORD ret_count; - int ret; - int64_t offset = sector_num * 512; - int count = nb_sectors * 512; - - memset(&ov, 0, sizeof(ov)); - ov.Offset = offset; - ov.OffsetHigh = offset >> 32; - ret = WriteFile(s->hfile, buf, count, &ret_count, &ov); - if (!ret) - return ret_count; - if (ret_count == count) - ret_count = 0; - return ret_count; + return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors, + cb, opaque, QEMU_AIO_WRITE); } -static int raw_flush(BlockDriverState *bs) +static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs, + BlockDriverCompletionFunc *cb, void *opaque) { BDRVRawState *s = bs->opaque; - int ret; - - ret = FlushFileBuffers(s->hfile); - if (ret == 0) { - return -EIO; - } - - return 0; + return paio_submit(bs, s->hfile, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH); } static void raw_close(BlockDriverState *bs) @@ -290,9 +379,9 @@ static BlockDriver bdrv_file = { .bdrv_close = raw_close, .bdrv_create = raw_create, - .bdrv_read = raw_read, - .bdrv_write = raw_write, - .bdrv_co_flush_to_disk = raw_flush, + .bdrv_aio_readv = raw_aio_readv, + .bdrv_aio_writev = raw_aio_writev, + .bdrv_aio_flush = raw_aio_flush, .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, @@ -413,9 +502,9 @@ static BlockDriver bdrv_host_device = { .bdrv_close = raw_close, .bdrv_has_zero_init = hdev_has_zero_init, - .bdrv_read = raw_read, - .bdrv_write = raw_write, - .bdrv_co_flush_to_disk = raw_flush, + .bdrv_aio_readv = raw_aio_readv, + .bdrv_aio_writev = raw_aio_writev, + .bdrv_aio_flush = raw_aio_flush, .bdrv_getlength = raw_getlength, .bdrv_get_allocated_file_size From 10fb6e06825743bd517d4b5bb0e7b9e05e0fe92c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 26 Oct 2012 11:27:45 +0200 Subject: [PATCH 1393/2270] raw-posix: move linux-aio.c to block/ Signed-off-by: Paolo Bonzini --- Makefile.objs | 1 - block/Makefile.objs | 1 + linux-aio.c => block/linux-aio.c | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename linux-aio.c => block/linux-aio.c (100%) diff --git a/Makefile.objs b/Makefile.objs index 35c2355e82..2b5427ee5f 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -47,7 +47,6 @@ block-obj-y += thread-pool.o qemu-progress.o qemu-sockets.o uri.o notify.o block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y) block-obj-$(CONFIG_POSIX) += event_notifier-posix.o aio-posix.o block-obj-$(CONFIG_WIN32) += event_notifier-win32.o aio-win32.o -block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o block-obj-y += block/ block-obj-y += $(qapi-obj-y) qapi-types.o qapi-visit.o diff --git a/block/Makefile.objs b/block/Makefile.objs index 684765bf63..771d3414d9 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -5,6 +5,7 @@ block-obj-y += qed-check.o block-obj-y += parallels.o blkdebug.o blkverify.o block-obj-$(CONFIG_WIN32) += raw-win32.o block-obj-$(CONFIG_POSIX) += raw-posix.o +block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o ifeq ($(CONFIG_POSIX),y) block-obj-y += nbd.o sheepdog.o diff --git a/linux-aio.c b/block/linux-aio.c similarity index 100% rename from linux-aio.c rename to block/linux-aio.c From a27365265cc2fed1178bf25a205e8ee02a9c0caf Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 26 Oct 2012 11:43:58 +0200 Subject: [PATCH 1394/2270] raw-win32: implement native asynchronous I/O With the new support for EventNotifiers in the AIO event loop, we can hook a completion port to every opened file and use asynchronous I/O on them. Wine's support is extremely inefficient, also because it really does the I/O synchronously on regular files. (!) But it works, and it is good to keep the Win32 and POSIX ports as similar as possible. Signed-off-by: Paolo Bonzini --- block/Makefile.objs | 2 +- block/raw-aio.h | 10 ++ block/raw-win32.c | 42 +++++++- block/win32-aio.c | 226 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 274 insertions(+), 6 deletions(-) create mode 100644 block/win32-aio.c diff --git a/block/Makefile.objs b/block/Makefile.objs index 771d3414d9..30ef6aec03 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -3,7 +3,7 @@ block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-c block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o block-obj-y += qed-check.o block-obj-y += parallels.o blkdebug.o blkverify.o -block-obj-$(CONFIG_WIN32) += raw-win32.o +block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o block-obj-$(CONFIG_POSIX) += raw-posix.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o diff --git a/block/raw-aio.h b/block/raw-aio.h index b3bb07377e..e77f361148 100644 --- a/block/raw-aio.h +++ b/block/raw-aio.h @@ -35,4 +35,14 @@ BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, BlockDriverCompletionFunc *cb, void *opaque, int type); #endif +#ifdef _WIN32 +typedef struct QEMUWin32AIOState QEMUWin32AIOState; +QEMUWin32AIOState *win32_aio_init(void); +int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile); +BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs, + QEMUWin32AIOState *aio, HANDLE hfile, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque, int type); +#endif + #endif /* QEMU_RAW_AIO_H */ diff --git a/block/raw-win32.c b/block/raw-win32.c index ffd86e3f38..0c05c58c5a 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -36,6 +36,8 @@ #define FTYPE_CD 1 #define FTYPE_HARDDISK 2 +static QEMUWin32AIOState *aio; + typedef struct RawWin32AIOData { BlockDriverState *bs; HANDLE hfile; @@ -50,6 +52,7 @@ typedef struct BDRVRawState { HANDLE hfile; int type; char drive_path[16]; /* format: "d:\" */ + QEMUWin32AIOState *aio; } BDRVRawState; /* @@ -208,6 +211,9 @@ static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped) } *overlapped = FILE_ATTRIBUTE_NORMAL; + if (flags & BDRV_O_NATIVE_AIO) { + *overlapped |= FILE_FLAG_OVERLAPPED; + } if (flags & BDRV_O_NOCACHE) { *overlapped |= FILE_FLAG_NO_BUFFERING; } @@ -222,6 +228,13 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags) s->type = FTYPE_FILE; raw_parse_flags(flags, &access_flags, &overlapped); + + if ((flags & BDRV_O_NATIVE_AIO) && aio == NULL) { + aio = win32_aio_init(); + if (aio == NULL) { + return -EINVAL; + } + } s->hfile = CreateFile(filename, access_flags, FILE_SHARE_READ, NULL, @@ -231,7 +244,16 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags) if (err == ERROR_ACCESS_DENIED) return -EACCES; - return -1; + return -EINVAL; + } + + if (flags & BDRV_O_NATIVE_AIO) { + int ret = win32_aio_attach(aio, s->hfile); + if (ret < 0) { + CloseHandle(s->hfile); + return ret; + } + s->aio = aio; } return 0; } @@ -241,8 +263,13 @@ static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { BDRVRawState *s = bs->opaque; - return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors, - cb, opaque, QEMU_AIO_READ); + if (s->aio) { + return win32_aio_submit(bs, s->aio, s->hfile, sector_num, qiov, + nb_sectors, cb, opaque, QEMU_AIO_READ); + } else { + return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors, + cb, opaque, QEMU_AIO_READ); + } } static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs, @@ -250,8 +277,13 @@ static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { BDRVRawState *s = bs->opaque; - return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors, - cb, opaque, QEMU_AIO_WRITE); + if (s->aio) { + return win32_aio_submit(bs, s->aio, s->hfile, sector_num, qiov, + nb_sectors, cb, opaque, QEMU_AIO_WRITE); + } else { + return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors, + cb, opaque, QEMU_AIO_WRITE); + } } static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs, diff --git a/block/win32-aio.c b/block/win32-aio.c new file mode 100644 index 0000000000..c34dc73b6c --- /dev/null +++ b/block/win32-aio.c @@ -0,0 +1,226 @@ +/* + * Block driver for RAW files (win32) + * + * Copyright (c) 2006 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 "qemu-common.h" +#include "qemu-timer.h" +#include "block_int.h" +#include "module.h" +#include "qemu-common.h" +#include "qemu-aio.h" +#include "raw-aio.h" +#include "event_notifier.h" +#include +#include + +#define FTYPE_FILE 0 +#define FTYPE_CD 1 +#define FTYPE_HARDDISK 2 + +struct QEMUWin32AIOState { + HANDLE hIOCP; + EventNotifier e; + int count; +}; + +typedef struct QEMUWin32AIOCB { + BlockDriverAIOCB common; + struct QEMUWin32AIOState *ctx; + int nbytes; + OVERLAPPED ov; + QEMUIOVector *qiov; + void *buf; + bool is_read; + bool is_linear; +} QEMUWin32AIOCB; + +/* + * Completes an AIO request (calls the callback and frees the ACB). + */ +static void win32_aio_process_completion(QEMUWin32AIOState *s, + QEMUWin32AIOCB *waiocb, DWORD count) +{ + int ret; + s->count--; + + if (waiocb->ov.Internal != 0) { + ret = -EIO; + } else { + ret = 0; + if (count < waiocb->nbytes) { + /* Short reads mean EOF, pad with zeros. */ + if (waiocb->is_read) { + qemu_iovec_memset(waiocb->qiov, count, 0, + waiocb->qiov->size - count); + } else { + ret = -EINVAL; + } + } + } + + if (!waiocb->is_linear) { + if (ret == 0 && waiocb->is_read) { + QEMUIOVector *qiov = waiocb->qiov; + char *p = waiocb->buf; + int i; + + for (i = 0; i < qiov->niov; ++i) { + memcpy(p, qiov->iov[i].iov_base, qiov->iov[i].iov_len); + p += qiov->iov[i].iov_len; + } + g_free(waiocb->buf); + } + } + + + waiocb->common.cb(waiocb->common.opaque, ret); + qemu_aio_release(waiocb); +} + +static void win32_aio_completion_cb(EventNotifier *e) +{ + QEMUWin32AIOState *s = container_of(e, QEMUWin32AIOState, e); + DWORD count; + ULONG_PTR key; + OVERLAPPED *ov; + + event_notifier_test_and_clear(&s->e); + while (GetQueuedCompletionStatus(s->hIOCP, &count, &key, &ov, 0)) { + QEMUWin32AIOCB *waiocb = container_of(ov, QEMUWin32AIOCB, ov); + + win32_aio_process_completion(s, waiocb, count); + } +} + +static int win32_aio_flush_cb(EventNotifier *e) +{ + QEMUWin32AIOState *s = container_of(e, QEMUWin32AIOState, e); + + return (s->count > 0) ? 1 : 0; +} + +static void win32_aio_cancel(BlockDriverAIOCB *blockacb) +{ + QEMUWin32AIOCB *waiocb = (QEMUWin32AIOCB *)blockacb; + + /* + * CancelIoEx is only supported in Vista and newer. For now, just + * wait for completion. + */ + while (!HasOverlappedIoCompleted(&waiocb->ov)) { + qemu_aio_wait(); + } +} + +static AIOPool win32_aio_pool = { + .aiocb_size = sizeof(QEMUWin32AIOCB), + .cancel = win32_aio_cancel, +}; + +BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs, + QEMUWin32AIOState *aio, HANDLE hfile, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque, int type) +{ + struct QEMUWin32AIOCB *waiocb; + uint64_t offset = sector_num * 512; + DWORD rc; + + waiocb = qemu_aio_get(&win32_aio_pool, bs, cb, opaque); + waiocb->nbytes = nb_sectors * 512; + waiocb->qiov = qiov; + waiocb->is_read = (type == QEMU_AIO_READ); + + if (qiov->niov > 1) { + waiocb->buf = qemu_blockalign(bs, qiov->size); + if (type & QEMU_AIO_WRITE) { + char *p = waiocb->buf; + int i; + + for (i = 0; i < qiov->niov; ++i) { + memcpy(p, qiov->iov[i].iov_base, qiov->iov[i].iov_len); + p += qiov->iov[i].iov_len; + } + } + waiocb->is_linear = false; + } else { + waiocb->buf = qiov->iov[0].iov_base; + waiocb->is_linear = true; + } + + waiocb->ov = (OVERLAPPED) { + .Offset = (DWORD) offset, + .OffsetHigh = (DWORD) (offset >> 32), + .hEvent = event_notifier_get_handle(&aio->e) + }; + aio->count++; + + if (type & QEMU_AIO_READ) { + rc = ReadFile(hfile, waiocb->buf, waiocb->nbytes, NULL, &waiocb->ov); + } else { + rc = WriteFile(hfile, waiocb->buf, waiocb->nbytes, NULL, &waiocb->ov); + } + if(rc == 0 && GetLastError() != ERROR_IO_PENDING) { + goto out_dec_count; + } + return &waiocb->common; + +out_dec_count: + aio->count--; + qemu_aio_release(waiocb); + return NULL; +} + +int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile) +{ + if (CreateIoCompletionPort(hfile, aio->hIOCP, (ULONG_PTR) 0, 0) == NULL) { + return -EINVAL; + } else { + return 0; + } +} + +QEMUWin32AIOState *win32_aio_init(void) +{ + QEMUWin32AIOState *s; + + s = g_malloc0(sizeof(*s)); + if (event_notifier_init(&s->e, false) < 0) { + goto out_free_state; + } + + s->hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); + if (s->hIOCP == NULL) { + goto out_close_efd; + } + + qemu_aio_set_event_notifier(&s->e, win32_aio_completion_cb, + win32_aio_flush_cb); + + return s; + +out_close_efd: + event_notifier_cleanup(&s->e); +out_free_state: + g_free(s); + return NULL; +} From 235eb0158cfb31bb8a7cad7296e2327d7f7349fc Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Wed, 24 Oct 2012 22:17:01 +0800 Subject: [PATCH 1395/2270] target-mips: Add ASE DSP internal functions Add internal functions using by MIPS ASE DSP instructions. Signed-off-by: Jia Liu Signed-off-by: Aurelien Jarno --- target-mips/Makefile.objs | 2 +- target-mips/dsp_helper.c | 1063 +++++++++++++++++++++++++++++++++++++ 2 files changed, 1064 insertions(+), 1 deletion(-) create mode 100644 target-mips/dsp_helper.c diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs index 3eeeeac8b8..119c816518 100644 --- a/target-mips/Makefile.objs +++ b/target-mips/Makefile.objs @@ -1,2 +1,2 @@ -obj-y += translate.o op_helper.o lmi_helper.o helper.o cpu.o +obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o obj-$(CONFIG_SOFTMMU) += machine.o diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c new file mode 100644 index 0000000000..55ea9236fa --- /dev/null +++ b/target-mips/dsp_helper.c @@ -0,0 +1,1063 @@ +/* + * MIPS ASE DSP Instruction emulation helpers for QEMU. + * + * Copyright (c) 2012 Jia Liu + * Dongxue Zhang + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "cpu.h" +#include "helper.h" + +/*** MIPS DSP internal functions begin ***/ +#define MIPSDSP_ABS(x) (((x) >= 0) ? x : -x) +#define MIPSDSP_OVERFLOW(a, b, c, d) (!(!((a ^ b ^ -1) & (a ^ c) & d))) + +static inline void set_DSPControl_overflow_flag(uint32_t flag, int position, + CPUMIPSState *env) +{ + env->active_tc.DSPControl |= (target_ulong)flag << position; +} + +static inline void set_DSPControl_carryflag(uint32_t flag, CPUMIPSState *env) +{ + env->active_tc.DSPControl |= (target_ulong)flag << 13; +} + +static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env) +{ + return (env->active_tc.DSPControl >> 13) & 0x01; +} + +static inline void set_DSPControl_24(uint32_t flag, int len, CPUMIPSState *env) +{ + uint32_t filter; + + filter = ((0x01 << len) - 1) << 24; + filter = ~filter; + + env->active_tc.DSPControl &= filter; + env->active_tc.DSPControl |= (target_ulong)flag << 24; +} + +static inline uint32_t get_DSPControl_24(int len, CPUMIPSState *env) +{ + uint32_t filter; + + filter = (0x01 << len) - 1; + + return (env->active_tc.DSPControl >> 24) & filter; +} + +static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env) +{ + target_ulong dspc; + + dspc = env->active_tc.DSPControl; +#ifndef TARGET_MIPS64 + dspc = dspc & 0xFFFFFFC0; + dspc |= pos; +#else + dspc = dspc & 0xFFFFFF80; + dspc |= pos; +#endif + env->active_tc.DSPControl = dspc; +} + +static inline uint32_t get_DSPControl_pos(CPUMIPSState *env) +{ + target_ulong dspc; + uint32_t pos; + + dspc = env->active_tc.DSPControl; + +#ifndef TARGET_MIPS64 + pos = dspc & 0x3F; +#else + pos = dspc & 0x7F; +#endif + + return pos; +} + +static inline void set_DSPControl_efi(uint32_t flag, CPUMIPSState *env) +{ + env->active_tc.DSPControl &= 0xFFFFBFFF; + env->active_tc.DSPControl |= (target_ulong)flag << 14; +} + +#define DO_MIPS_SAT_ABS(size) \ +static inline int##size##_t mipsdsp_sat_abs##size(int##size##_t a, \ + CPUMIPSState *env) \ +{ \ + if (a == INT##size##_MIN) { \ + set_DSPControl_overflow_flag(1, 20, env); \ + return INT##size##_MAX; \ + } else { \ + return MIPSDSP_ABS(a); \ + } \ +} +DO_MIPS_SAT_ABS(8) +DO_MIPS_SAT_ABS(16) +DO_MIPS_SAT_ABS(32) +#undef DO_MIPS_SAT_ABS + +/* get sum value */ +static inline int16_t mipsdsp_add_i16(int16_t a, int16_t b, CPUMIPSState *env) +{ + int16_t tempI; + + tempI = a + b; + + if (MIPSDSP_OVERFLOW(a, b, tempI, 0x8000)) { + set_DSPControl_overflow_flag(1, 20, env); + } + + return tempI; +} + +static inline int16_t mipsdsp_sat_add_i16(int16_t a, int16_t b, + CPUMIPSState *env) +{ + int16_t tempS; + + tempS = a + b; + + if (MIPSDSP_OVERFLOW(a, b, tempS, 0x8000)) { + if (a > 0) { + tempS = 0x7FFF; + } else { + tempS = 0x8000; + } + set_DSPControl_overflow_flag(1, 20, env); + } + + return tempS; +} + +static inline int32_t mipsdsp_sat_add_i32(int32_t a, int32_t b, + CPUMIPSState *env) +{ + int32_t tempI; + + tempI = a + b; + + if (MIPSDSP_OVERFLOW(a, b, tempI, 0x80000000)) { + if (a > 0) { + tempI = 0x7FFFFFFF; + } else { + tempI = 0x80000000; + } + set_DSPControl_overflow_flag(1, 20, env); + } + + return tempI; +} + +static inline uint8_t mipsdsp_add_u8(uint8_t a, uint8_t b, CPUMIPSState *env) +{ + uint16_t temp; + + temp = (uint16_t)a + (uint16_t)b; + + if (temp & 0x0100) { + set_DSPControl_overflow_flag(1, 20, env); + } + + return temp & 0xFF; +} + +static inline uint16_t mipsdsp_add_u16(uint16_t a, uint16_t b, + CPUMIPSState *env) +{ + uint32_t temp; + + temp = (uint32_t)a + (uint32_t)b; + + if (temp & 0x00010000) { + set_DSPControl_overflow_flag(1, 20, env); + } + + return temp & 0xFFFF; +} + +static inline uint8_t mipsdsp_sat_add_u8(uint8_t a, uint8_t b, + CPUMIPSState *env) +{ + uint8_t result; + uint16_t temp; + + temp = (uint16_t)a + (uint16_t)b; + result = temp & 0xFF; + + if (0x0100 & temp) { + result = 0xFF; + set_DSPControl_overflow_flag(1, 20, env); + } + + return result; +} + +static inline uint16_t mipsdsp_sat_add_u16(uint16_t a, uint16_t b, + CPUMIPSState *env) +{ + uint16_t result; + uint32_t temp; + + temp = (uint32_t)a + (uint32_t)b; + result = temp & 0xFFFF; + + if (0x00010000 & temp) { + result = 0xFFFF; + set_DSPControl_overflow_flag(1, 20, env); + } + + return result; +} + +static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a, + CPUMIPSState *env) +{ + int64_t temp; + int32_t temp32, temp31, result; + int64_t temp_sum; + +#ifndef TARGET_MIPS64 + temp = ((uint64_t)env->active_tc.HI[acc] << 32) | + (uint64_t)env->active_tc.LO[acc]; +#else + temp = (uint64_t)env->active_tc.LO[acc]; +#endif + + temp_sum = (int64_t)a + temp; + + temp32 = (temp_sum >> 32) & 0x01; + temp31 = (temp_sum >> 31) & 0x01; + result = temp_sum & 0xFFFFFFFF; + + /* FIXME + This sat function may wrong, because user manual wrote: + temp127..0 ← temp + ( (signA) || a31..0 + if ( temp32 ≠ temp31 ) then + if ( temp32 = 0 ) then + temp31..0 ← 0x80000000 + else + temp31..0 ← 0x7FFFFFFF + endif + DSPControlouflag:16+acc ← 1 + endif + */ + if (temp32 != temp31) { + if (temp32 == 0) { + result = 0x7FFFFFFF; + } else { + result = 0x80000000; + } + set_DSPControl_overflow_flag(1, 16 + acc, env); + } + + return result; +} + +/* a[0] is LO, a[1] is HI. */ +static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret, + int32_t ac, + int64_t *a, + CPUMIPSState *env) +{ + bool temp64; + + ret[0] = env->active_tc.LO[ac] + a[0]; + ret[1] = env->active_tc.HI[ac] + a[1]; + + if (((uint64_t)ret[0] < (uint64_t)env->active_tc.LO[ac]) && + ((uint64_t)ret[0] < (uint64_t)a[0])) { + ret[1] += 1; + } + temp64 = ret[1] & 1; + if (temp64 != ((ret[0] >> 63) & 0x01)) { + if (temp64) { + ret[0] = (0x01ull << 63); + ret[1] = ~0ull; + } else { + ret[0] = (0x01ull << 63) - 1; + ret[1] = 0x00; + } + set_DSPControl_overflow_flag(1, 16 + ac, env); + } +} + +static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret, + int32_t ac, + int64_t *a, + CPUMIPSState *env) +{ + bool temp64; + + ret[0] = env->active_tc.LO[ac] - a[0]; + ret[1] = env->active_tc.HI[ac] - a[1]; + + if ((uint64_t)ret[0] > (uint64_t)env->active_tc.LO[ac]) { + ret[1] -= 1; + } + temp64 = ret[1] & 1; + if (temp64 != ((ret[0] >> 63) & 0x01)) { + if (temp64) { + ret[0] = (0x01ull << 63); + ret[1] = ~0ull; + } else { + ret[0] = (0x01ull << 63) - 1; + ret[1] = 0x00; + } + set_DSPControl_overflow_flag(1, 16 + ac, env); + } +} + +static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b, + CPUMIPSState *env) +{ + int32_t temp; + + temp = (int32_t)a * (int32_t)b; + + if ((temp > (int)0x7FFF) || (temp < (int)0xFFFF8000)) { + set_DSPControl_overflow_flag(1, 21, env); + } + temp &= 0x0000FFFF; + + return temp; +} + +static inline int32_t mipsdsp_mul_u16_u16(int32_t a, int32_t b) +{ + return a * b; +} + +static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b) +{ + return a * b; +} + +static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b, + CPUMIPSState *env) +{ + int32_t temp; + + temp = (int32_t)a * (int32_t)b; + + if (temp > (int)0x7FFF) { + temp = 0x00007FFF; + set_DSPControl_overflow_flag(1, 21, env); + } else if (temp < (int)0xffff8000) { + temp = 0xFFFF8000; + set_DSPControl_overflow_flag(1, 21, env); + } + temp &= 0x0000FFFF; + + return temp; +} + +static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(uint16_t a, uint16_t b, + CPUMIPSState *env) +{ + int32_t temp; + + if ((a == 0x8000) && (b == 0x8000)) { + temp = 0x7FFFFFFF; + set_DSPControl_overflow_flag(1, 21, env); + } else { + temp = ((int32_t)(int16_t)a * (int32_t)(int16_t)b) << 1; + } + + return temp; +} + +/* right shift */ +static inline uint8_t mipsdsp_rshift_u8(uint8_t a, target_ulong mov) +{ + return a >> mov; +} + +static inline uint16_t mipsdsp_rshift_u16(uint16_t a, target_ulong mov) +{ + return a >> mov; +} + +static inline int8_t mipsdsp_rashift8(int8_t a, target_ulong mov) +{ + return a >> mov; +} + +static inline int16_t mipsdsp_rashift16(int16_t a, target_ulong mov) +{ + return a >> mov; +} + +static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov) +{ + return a >> mov; +} + +static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b) +{ + int32_t temp; + + temp = (int32_t)a + (int32_t)b; + + return (temp >> 1) & 0xFFFF; +} + +/* round right shift */ +static inline int16_t mipsdsp_rrshift1_add_q16(int16_t a, int16_t b) +{ + int32_t temp; + + temp = (int32_t)a + (int32_t)b; + temp += 1; + + return (temp >> 1) & 0xFFFF; +} + +static inline int32_t mipsdsp_rshift1_add_q32(int32_t a, int32_t b) +{ + int64_t temp; + + temp = (int64_t)a + (int64_t)b; + + return (temp >> 1) & 0xFFFFFFFF; +} + +static inline int32_t mipsdsp_rrshift1_add_q32(int32_t a, int32_t b) +{ + int64_t temp; + + temp = (int64_t)a + (int64_t)b; + temp += 1; + + return (temp >> 1) & 0xFFFFFFFF; +} + +static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a, uint8_t b) +{ + uint16_t temp; + + temp = (uint16_t)a + (uint16_t)b; + + return (temp >> 1) & 0x00FF; +} + +static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b) +{ + uint16_t temp; + + temp = (uint16_t)a + (uint16_t)b + 1; + + return (temp >> 1) & 0x00FF; +} + +static inline uint8_t mipsdsp_rshift1_sub_u8(uint8_t a, uint8_t b) +{ + uint16_t temp; + + temp = (uint16_t)a - (uint16_t)b; + + return (temp >> 1) & 0x00FF; +} + +static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b) +{ + uint16_t temp; + + temp = (uint16_t)a - (uint16_t)b + 1; + + return (temp >> 1) & 0x00FF; +} + +static inline int64_t mipsdsp_rashift_short_acc(int32_t ac, + int32_t shift, + CPUMIPSState *env) +{ + int32_t sign, temp31; + int64_t temp, acc; + + sign = (env->active_tc.HI[ac] >> 31) & 0x01; + acc = ((int64_t)env->active_tc.HI[ac] << 32) | + ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF); + if (shift == 0) { + temp = acc; + } else { + if (sign == 0) { + temp = (((int64_t)0x01 << (32 - shift + 1)) - 1) & (acc >> shift); + } else { + temp = ((((int64_t)0x01 << (shift + 1)) - 1) << (32 - shift)) | + (acc >> shift); + } + } + + temp31 = (temp >> 31) & 0x01; + if (sign != temp31) { + set_DSPControl_overflow_flag(1, 23, env); + } + + return temp; +} + +/* 128 bits long. p[0] is LO, p[1] is HI. */ +static inline void mipsdsp_rndrashift_short_acc(int64_t *p, + int32_t ac, + int32_t shift, + CPUMIPSState *env) +{ + int64_t acc; + + acc = ((int64_t)env->active_tc.HI[ac] << 32) | + ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF); + if (shift == 0) { + p[0] = acc << 1; + p[1] = (acc >> 63) & 0x01; + } else { + p[0] = acc >> (shift - 1); + p[1] = 0; + } +} + +/* 128 bits long. p[0] is LO, p[1] is HI */ +static inline void mipsdsp_rashift_acc(uint64_t *p, + uint32_t ac, + uint32_t shift, + CPUMIPSState *env) +{ + uint64_t tempB, tempA; + + tempB = env->active_tc.HI[ac]; + tempA = env->active_tc.LO[ac]; + shift = shift & 0x1F; + + if (shift == 0) { + p[1] = tempB; + p[0] = tempA; + } else { + p[0] = (tempB << (64 - shift)) | (tempA >> shift); + p[1] = (int64_t)tempB >> shift; + } +} + +/* 128 bits long. p[0] is LO, p[1] is HI , p[2] is sign of HI.*/ +static inline void mipsdsp_rndrashift_acc(uint64_t *p, + uint32_t ac, + uint32_t shift, + CPUMIPSState *env) +{ + int64_t tempB, tempA; + + tempB = env->active_tc.HI[ac]; + tempA = env->active_tc.LO[ac]; + shift = shift & 0x3F; + + if (shift == 0) { + p[2] = tempB >> 63; + p[1] = (tempB << 1) | (tempA >> 63); + p[0] = tempA << 1; + } else { + p[0] = (tempB << (65 - shift)) | (tempA >> (shift - 1)); + p[1] = (int64_t)tempB >> (shift - 1); + if (tempB >= 0) { + p[2] = 0x0; + } else { + p[2] = ~0ull; + } + } +} + +static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b, + CPUMIPSState *env) +{ + int32_t temp; + + if ((a == 0x8000) && (b == 0x8000)) { + temp = 0x7FFFFFFF; + set_DSPControl_overflow_flag(1, 16 + ac, env); + } else { + temp = ((uint32_t)a * (uint32_t)b) << 1; + } + + return temp; +} + +static inline int64_t mipsdsp_mul_q31_q31(int32_t ac, uint32_t a, uint32_t b, + CPUMIPSState *env) +{ + uint64_t temp; + + if ((a == 0x80000000) && (b == 0x80000000)) { + temp = (0x01ull << 63) - 1; + set_DSPControl_overflow_flag(1, 16 + ac, env); + } else { + temp = ((uint64_t)a * (uint64_t)b) << 1; + } + + return temp; +} + +static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b) +{ + return (uint16_t)a * (uint16_t)b; +} + +static inline uint16_t mipsdsp_mul_u8_u16(uint8_t a, uint16_t b, + CPUMIPSState *env) +{ + uint32_t tempI; + + tempI = (uint32_t)a * (uint32_t)b; + if (tempI > 0x0000FFFF) { + tempI = 0x0000FFFF; + set_DSPControl_overflow_flag(1, 21, env); + } + + return tempI & 0x0000FFFF; +} + +static inline uint64_t mipsdsp_mul_u32_u32(uint32_t a, uint32_t b) +{ + return (uint64_t)a * (uint64_t)b; +} + +static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b, + CPUMIPSState *env) +{ + uint32_t temp; + + if ((a == 0x8000) && (b == 0x8000)) { + temp = 0x7FFF0000; + set_DSPControl_overflow_flag(1, 21, env); + } else { + temp = (a * b) << 1; + temp = temp + 0x00008000; + } + + return (temp & 0xFFFF0000) >> 16; +} + +static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b, + CPUMIPSState *env) +{ + int32_t temp; + + if ((a == 0x8000) && (b == 0x8000)) { + temp = 0x7FFF0000; + set_DSPControl_overflow_flag(1, 21, env); + } else { + temp = ((uint32_t)a * (uint32_t)b); + temp = temp << 1; + } + + return (temp >> 16) & 0x0000FFFF; +} + +static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a, + CPUMIPSState *env) +{ + int64_t temp; + + temp = (int32_t)a + 0x00008000; + + if (a > (int)0x7fff8000) { + temp = 0x7FFFFFFF; + set_DSPControl_overflow_flag(1, 22, env); + } + + return (temp >> 16) & 0xFFFF; +} + +static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a, + CPUMIPSState *env) +{ + uint16_t mag; + uint32_t sign; + + sign = (a >> 15) & 0x01; + mag = a & 0x7FFF; + + if (sign == 0) { + if (mag > 0x7F80) { + set_DSPControl_overflow_flag(1, 22, env); + return 0xFF; + } else { + return (mag >> 7) & 0xFFFF; + } + } else { + set_DSPControl_overflow_flag(1, 22, env); + return 0x00; + } +} + +static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env) +{ + uint8_t sign; + uint8_t discard; + + if (s == 0) { + return a; + } else { + sign = (a >> 7) & 0x01; + if (sign != 0) { + discard = (((0x01 << (8 - s)) - 1) << s) | + ((a >> (6 - (s - 1))) & ((0x01 << s) - 1)); + } else { + discard = a >> (6 - (s - 1)); + } + + if (discard != 0x00) { + set_DSPControl_overflow_flag(1, 22, env); + } + return a << s; + } +} + +static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s, + CPUMIPSState *env) +{ + uint8_t sign; + uint16_t discard; + + if (s == 0) { + return a; + } else { + sign = (a >> 15) & 0x01; + if (sign != 0) { + discard = (((0x01 << (16 - s)) - 1) << s) | + ((a >> (14 - (s - 1))) & ((0x01 << s) - 1)); + } else { + discard = a >> (14 - (s - 1)); + } + + if ((discard != 0x0000) && (discard != 0xFFFF)) { + set_DSPControl_overflow_flag(1, 22, env); + } + return a << s; + } +} + + +static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s, + CPUMIPSState *env) +{ + uint32_t discard; + + if (s == 0) { + return a; + } else { + discard = (int32_t)a >> (31 - (s - 1)); + + if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) { + set_DSPControl_overflow_flag(1, 22, env); + } + return a << s; + } +} + +static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s, + CPUMIPSState *env) +{ + uint8_t sign; + uint16_t discard; + + if (s == 0) { + return a; + } else { + sign = (a >> 15) & 0x01; + if (sign != 0) { + discard = (((0x01 << (16 - s)) - 1) << s) | + ((a >> (14 - (s - 1))) & ((0x01 << s) - 1)); + } else { + discard = a >> (14 - (s - 1)); + } + + if ((discard != 0x0000) && (discard != 0xFFFF)) { + set_DSPControl_overflow_flag(1, 22, env); + return (sign == 0) ? 0x7FFF : 0x8000; + } else { + return a << s; + } + } +} + +static inline uint32_t mipsdsp_sat32_lshift(uint32_t a, uint8_t s, + CPUMIPSState *env) +{ + uint8_t sign; + uint32_t discard; + + if (s == 0) { + return a; + } else { + sign = (a >> 31) & 0x01; + if (sign != 0) { + discard = (((0x01 << (32 - s)) - 1) << s) | + ((a >> (30 - (s - 1))) & ((0x01 << s) - 1)); + } else { + discard = a >> (30 - (s - 1)); + } + + if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) { + set_DSPControl_overflow_flag(1, 22, env); + return (sign == 0) ? 0x7FFFFFFF : 0x80000000; + } else { + return a << s; + } + } +} + +static inline uint8_t mipsdsp_rnd8_rashift(uint8_t a, uint8_t s) +{ + uint32_t temp; + + if (s == 0) { + temp = (uint32_t)a << 1; + } else { + temp = (int32_t)(int8_t)a >> (s - 1); + } + + return (temp + 1) >> 1; +} + +static inline uint16_t mipsdsp_rnd16_rashift(uint16_t a, uint8_t s) +{ + uint32_t temp; + + if (s == 0) { + temp = (uint32_t)a << 1; + } else { + temp = (int32_t)(int16_t)a >> (s - 1); + } + + return (temp + 1) >> 1; +} + +static inline uint32_t mipsdsp_rnd32_rashift(uint32_t a, uint8_t s) +{ + int64_t temp; + + if (s == 0) { + temp = (uint64_t)a << 1; + } else { + temp = (int64_t)(int32_t)a >> (s - 1); + } + temp += 1; + + return (temp >> 1) & 0xFFFFFFFFull; +} + +static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b, CPUMIPSState *env) +{ + int16_t temp; + + temp = a - b; + if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) { + set_DSPControl_overflow_flag(1, 20, env); + } + + return temp; +} + +static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b, + CPUMIPSState *env) +{ + int16_t temp; + + temp = a - b; + if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) { + if (a > 0) { + temp = 0x7FFF; + } else { + temp = 0x8000; + } + set_DSPControl_overflow_flag(1, 20, env); + } + + return temp; +} + +static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b, + CPUMIPSState *env) +{ + int32_t temp; + + temp = a - b; + if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) { + if (a > 0) { + temp = 0x7FFFFFFF; + } else { + temp = 0x80000000; + } + set_DSPControl_overflow_flag(1, 20, env); + } + + return temp & 0xFFFFFFFFull; +} + +static inline uint16_t mipsdsp_rshift1_sub_q16(int16_t a, int16_t b) +{ + int32_t temp; + + temp = (int32_t)a - (int32_t)b; + + return (temp >> 1) & 0x0000FFFF; +} + +static inline uint16_t mipsdsp_rrshift1_sub_q16(int16_t a, int16_t b) +{ + int32_t temp; + + temp = (int32_t)a - (int32_t)b; + temp += 1; + + return (temp >> 1) & 0x0000FFFF; +} + +static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a, int32_t b) +{ + int64_t temp; + + temp = (int64_t)a - (int64_t)b; + + return (temp >> 1) & 0xFFFFFFFFull; +} + +static inline uint32_t mipsdsp_rrshift1_sub_q32(int32_t a, int32_t b) +{ + int64_t temp; + + temp = (int64_t)a - (int64_t)b; + temp += 1; + + return (temp >> 1) & 0xFFFFFFFFull; +} + +static inline uint16_t mipsdsp_sub_u16_u16(uint16_t a, uint16_t b, + CPUMIPSState *env) +{ + uint8_t temp16; + uint32_t temp; + + temp = (uint32_t)a - (uint32_t)b; + temp16 = (temp >> 16) & 0x01; + if (temp16 == 1) { + set_DSPControl_overflow_flag(1, 20, env); + } + return temp & 0x0000FFFF; +} + +static inline uint16_t mipsdsp_satu16_sub_u16_u16(uint16_t a, uint16_t b, + CPUMIPSState *env) +{ + uint8_t temp16; + uint32_t temp; + + temp = (uint32_t)a - (uint32_t)b; + temp16 = (temp >> 16) & 0x01; + + if (temp16 == 1) { + temp = 0x0000; + set_DSPControl_overflow_flag(1, 20, env); + } + + return temp & 0x0000FFFF; +} + +static inline uint8_t mipsdsp_sub_u8(uint8_t a, uint8_t b, CPUMIPSState *env) +{ + uint8_t temp8; + uint16_t temp; + + temp = (uint16_t)a - (uint16_t)b; + temp8 = (temp >> 8) & 0x01; + if (temp8 == 1) { + set_DSPControl_overflow_flag(1, 20, env); + } + + return temp & 0x00FF; +} + +static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b, CPUMIPSState *env) +{ + uint8_t temp8; + uint16_t temp; + + temp = (uint16_t)a - (uint16_t)b; + temp8 = (temp >> 8) & 0x01; + if (temp8 == 1) { + temp = 0x00; + set_DSPControl_overflow_flag(1, 20, env); + } + + return temp & 0x00FF; +} + +static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env) +{ + int32_t temp; + + temp = a - b; + if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) { + set_DSPControl_overflow_flag(1, 20, env); + } + + return temp; +} + +static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env) +{ + int32_t temp; + + temp = a + b; + + if (MIPSDSP_OVERFLOW(a, b, temp, 0x80000000)) { + set_DSPControl_overflow_flag(1, 20, env); + } + + return temp; +} + +static inline int32_t mipsdsp_cmp_eq(int32_t a, int32_t b) +{ + return a == b; +} + +static inline int32_t mipsdsp_cmp_le(int32_t a, int32_t b) +{ + return a <= b; +} + +static inline int32_t mipsdsp_cmp_lt(int32_t a, int32_t b) +{ + return a < b; +} + +static inline int32_t mipsdsp_cmpu_eq(uint32_t a, uint32_t b) +{ + return a == b; +} + +static inline int32_t mipsdsp_cmpu_le(uint32_t a, uint32_t b) +{ + return a <= b; +} + +static inline int32_t mipsdsp_cmpu_lt(uint32_t a, uint32_t b) +{ + return a < b; +} +/*** MIPS DSP internal functions end ***/ From 853c3240c0753735b82fe80a86123e09234f5448 Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Wed, 24 Oct 2012 22:17:02 +0800 Subject: [PATCH 1396/2270] target-mips: Add ASE DSP resources access check Add MIPS ASE DSP resources access check. Signed-off-by: Jia Liu Signed-off-by: Aurelien Jarno --- linux-user/main.c | 6 ++++++ target-mips/cpu.h | 23 +++++++++++++++++++++-- target-mips/helper.c | 3 +++ target-mips/translate.c | 23 +++++++++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 5d20abd3e5..25e35cd3dc 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -2286,6 +2286,12 @@ done_syscall: queue_signal(env, info.si_signo, &info); } break; + case EXCP_DSPDIS: + info.si_signo = TARGET_SIGILL; + info.si_errno = 0; + info.si_code = TARGET_ILL_ILLOPC; + queue_signal(env, info.si_signo, &info); + break; default: // error: fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", diff --git a/target-mips/cpu.h b/target-mips/cpu.h index c4ca2855df..4c012d503f 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -415,7 +415,7 @@ struct CPUMIPSState { int error_code; uint32_t hflags; /* CPU State */ /* TMASK defines different execution modes */ -#define MIPS_HFLAG_TMASK 0x007FF +#define MIPS_HFLAG_TMASK 0xC07FF #define MIPS_HFLAG_MODE 0x00007 /* execution modes */ /* The KSU flags must be the lowest bits in hflags. The flag order must be the same as defined for CP0 Status. This allows to use @@ -453,6 +453,9 @@ struct CPUMIPSState { #define MIPS_HFLAG_BDS32 0x10000 /* branch requires 32-bit delay slot */ #define MIPS_HFLAG_BX 0x20000 /* branch exchanges execution mode */ #define MIPS_HFLAG_BMASK (MIPS_HFLAG_BMASK_BASE | MIPS_HFLAG_BMASK_EXT) + /* MIPS DSP resources access. */ +#define MIPS_HFLAG_DSP 0x40000 /* Enable access to MIPS DSP resources. */ +#define MIPS_HFLAG_DSPR2 0x80000 /* Enable access to MIPS DSPR2 resources. */ target_ulong btarget; /* Jump / branch target */ target_ulong bcond; /* Branch condition (if needed) */ @@ -610,8 +613,9 @@ enum { EXCP_MDMX, EXCP_C2E, EXCP_CACHE, /* 32 */ + EXCP_DSPDIS, - EXCP_LAST = EXCP_CACHE, + EXCP_LAST = EXCP_DSPDIS, }; /* Dummy exception for conditional stores. */ #define EXCP_SC 0x100 @@ -772,6 +776,21 @@ static inline void compute_hflags(CPUMIPSState *env) if (env->CP0_Status & (1 << CP0St_FR)) { env->hflags |= MIPS_HFLAG_F64; } + if (env->insn_flags & ASE_DSPR2) { + /* Enables access MIPS DSP resources, now our cpu is DSP ASER2, + so enable to access DSPR2 resources. */ + if (env->CP0_Status & (1 << CP0St_MX)) { + env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2; + } + + } else if (env->insn_flags & ASE_DSP) { + /* Enables access MIPS DSP resources, now our cpu is DSP ASE, + so enable to access DSP resources. */ + if (env->CP0_Status & (1 << CP0St_MX)) { + env->hflags |= MIPS_HFLAG_DSP; + } + + } if (env->insn_flags & ISA_MIPS32R2) { if (env->active_fpu.fcr0 & (1 << FCR0_F64)) { env->hflags |= MIPS_HFLAG_COP1X; diff --git a/target-mips/helper.c b/target-mips/helper.c index 3b8c696a9e..e877b8db78 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -592,6 +592,9 @@ void do_interrupt (CPUMIPSState *env) case EXCP_THREAD: cause = 25; goto set_EPC; + case EXCP_DSPDIS: + cause = 26; + goto set_EPC; case EXCP_CACHE: cause = 30; if (env->CP0_Status & (1 << CP0St_BEV)) { diff --git a/target-mips/translate.c b/target-mips/translate.c index ed55e260ac..586f564e27 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -948,6 +948,24 @@ static inline void check_cp1_registers(DisasContext *ctx, int regs) generate_exception(ctx, EXCP_RI); } +/* Verify that the processor is running with DSP instructions enabled. + This is enabled by CP0 Status register MX(24) bit. + */ + +static inline void check_dsp(DisasContext *ctx) +{ + if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) { + generate_exception(ctx, EXCP_DSPDIS); + } +} + +static inline void check_dspr2(DisasContext *ctx) +{ + if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) { + generate_exception(ctx, EXCP_DSPDIS); + } +} + /* This code generates a "reserved instruction" exception if the CPU does not support the instruction set corresponding to flags. */ static inline void check_insn(CPUMIPSState *env, DisasContext *ctx, int flags) @@ -13209,6 +13227,11 @@ void cpu_state_reset(CPUMIPSState *env) if (env->CP0_Config1 & (1 << CP0C1_FP)) { env->CP0_Status |= (1 << CP0St_CU1); } + if (env->cpu_model->insn_flags & ASE_DSPR2) { + env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2; + } else if (env->cpu_model->insn_flags & ASE_DSP) { + env->hflags |= MIPS_HFLAG_DSP; + } #else if (env->hflags & MIPS_HFLAG_BMASK) { /* If the exception was raised from a delay slot, From 4133498f8e532f9a32dae2153ef5e14433626e9f Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Wed, 24 Oct 2012 22:17:03 +0800 Subject: [PATCH 1397/2270] Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number Signed-off-by: Jia Liu Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 122 +++++++++++++++++++++++++++++++--------- 1 file changed, 95 insertions(+), 27 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 586f564e27..134d06f9f0 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -5,6 +5,7 @@ * Copyright (c) 2006 Marius Groeger (FPU operations) * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -2119,33 +2120,75 @@ static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg) { const char *opn = "hilo"; + unsigned int acc; if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) { /* Treat as NOP. */ MIPS_DEBUG("NOP"); return; } + + if (opc == OPC_MFHI || opc == OPC_MFLO) { + acc = ((ctx->opcode) >> 21) & 0x03; + } else { + acc = ((ctx->opcode) >> 11) & 0x03; + } + + if (acc != 0) { + check_dsp(ctx); + } + switch (opc) { case OPC_MFHI: - tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]); +#if defined(TARGET_MIPS64) + if (acc != 0) { + tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]); + } else +#endif + { + tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]); + } opn = "mfhi"; break; case OPC_MFLO: - tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]); +#if defined(TARGET_MIPS64) + if (acc != 0) { + tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]); + } else +#endif + { + tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]); + } opn = "mflo"; break; case OPC_MTHI: - if (reg != 0) - tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]); - else - tcg_gen_movi_tl(cpu_HI[0], 0); + if (reg != 0) { +#if defined(TARGET_MIPS64) + if (acc != 0) { + tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]); + } else +#endif + { + tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]); + } + } else { + tcg_gen_movi_tl(cpu_HI[acc], 0); + } opn = "mthi"; break; case OPC_MTLO: - if (reg != 0) - tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]); - else - tcg_gen_movi_tl(cpu_LO[0], 0); + if (reg != 0) { +#if defined(TARGET_MIPS64) + if (acc != 0) { + tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]); + } else +#endif + { + tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]); + } + } else { + tcg_gen_movi_tl(cpu_LO[acc], 0); + } opn = "mtlo"; break; } @@ -2158,6 +2201,7 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, { const char *opn = "mul/div"; TCGv t0, t1; + unsigned int acc; switch (opc) { case OPC_DIV: @@ -2220,6 +2264,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, { TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i64 t3 = tcg_temp_new_i64(); + acc = ((ctx->opcode) >> 11) & 0x03; + if (acc != 0) { + check_dsp(ctx); + } tcg_gen_ext_tl_i64(t2, t0); tcg_gen_ext_tl_i64(t3, t1); @@ -2229,8 +2277,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, tcg_gen_shri_i64(t2, t2, 32); tcg_gen_trunc_i64_tl(t1, t2); tcg_temp_free_i64(t2); - tcg_gen_ext32s_tl(cpu_LO[0], t0); - tcg_gen_ext32s_tl(cpu_HI[0], t1); + tcg_gen_ext32s_tl(cpu_LO[acc], t0); + tcg_gen_ext32s_tl(cpu_HI[acc], t1); } opn = "mult"; break; @@ -2238,6 +2286,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, { TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i64 t3 = tcg_temp_new_i64(); + acc = ((ctx->opcode) >> 11) & 0x03; + if (acc != 0) { + check_dsp(ctx); + } tcg_gen_ext32u_tl(t0, t0); tcg_gen_ext32u_tl(t1, t1); @@ -2249,8 +2301,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, tcg_gen_shri_i64(t2, t2, 32); tcg_gen_trunc_i64_tl(t1, t2); tcg_temp_free_i64(t2); - tcg_gen_ext32s_tl(cpu_LO[0], t0); - tcg_gen_ext32s_tl(cpu_HI[0], t1); + tcg_gen_ext32s_tl(cpu_LO[acc], t0); + tcg_gen_ext32s_tl(cpu_HI[acc], t1); } opn = "multu"; break; @@ -2297,41 +2349,49 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, { TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i64 t3 = tcg_temp_new_i64(); + acc = ((ctx->opcode) >> 11) & 0x03; + if (acc != 0) { + check_dsp(ctx); + } tcg_gen_ext_tl_i64(t2, t0); tcg_gen_ext_tl_i64(t3, t1); tcg_gen_mul_i64(t2, t2, t3); - tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]); + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); tcg_gen_add_i64(t2, t2, t3); tcg_temp_free_i64(t3); tcg_gen_trunc_i64_tl(t0, t2); tcg_gen_shri_i64(t2, t2, 32); tcg_gen_trunc_i64_tl(t1, t2); tcg_temp_free_i64(t2); - tcg_gen_ext32s_tl(cpu_LO[0], t0); - tcg_gen_ext32s_tl(cpu_HI[0], t1); + tcg_gen_ext32s_tl(cpu_LO[acc], t0); + tcg_gen_ext32s_tl(cpu_HI[acc], t1); } opn = "madd"; break; case OPC_MADDU: - { + { TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i64 t3 = tcg_temp_new_i64(); + acc = ((ctx->opcode) >> 11) & 0x03; + if (acc != 0) { + check_dsp(ctx); + } tcg_gen_ext32u_tl(t0, t0); tcg_gen_ext32u_tl(t1, t1); tcg_gen_extu_tl_i64(t2, t0); tcg_gen_extu_tl_i64(t3, t1); tcg_gen_mul_i64(t2, t2, t3); - tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]); + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); tcg_gen_add_i64(t2, t2, t3); tcg_temp_free_i64(t3); tcg_gen_trunc_i64_tl(t0, t2); tcg_gen_shri_i64(t2, t2, 32); tcg_gen_trunc_i64_tl(t1, t2); tcg_temp_free_i64(t2); - tcg_gen_ext32s_tl(cpu_LO[0], t0); - tcg_gen_ext32s_tl(cpu_HI[0], t1); + tcg_gen_ext32s_tl(cpu_LO[acc], t0); + tcg_gen_ext32s_tl(cpu_HI[acc], t1); } opn = "maddu"; break; @@ -2339,19 +2399,23 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, { TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i64 t3 = tcg_temp_new_i64(); + acc = ((ctx->opcode) >> 11) & 0x03; + if (acc != 0) { + check_dsp(ctx); + } tcg_gen_ext_tl_i64(t2, t0); tcg_gen_ext_tl_i64(t3, t1); tcg_gen_mul_i64(t2, t2, t3); - tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]); + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); tcg_gen_sub_i64(t2, t3, t2); tcg_temp_free_i64(t3); tcg_gen_trunc_i64_tl(t0, t2); tcg_gen_shri_i64(t2, t2, 32); tcg_gen_trunc_i64_tl(t1, t2); tcg_temp_free_i64(t2); - tcg_gen_ext32s_tl(cpu_LO[0], t0); - tcg_gen_ext32s_tl(cpu_HI[0], t1); + tcg_gen_ext32s_tl(cpu_LO[acc], t0); + tcg_gen_ext32s_tl(cpu_HI[acc], t1); } opn = "msub"; break; @@ -2359,21 +2423,25 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, { TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i64 t3 = tcg_temp_new_i64(); + acc = ((ctx->opcode) >> 11) & 0x03; + if (acc != 0) { + check_dsp(ctx); + } tcg_gen_ext32u_tl(t0, t0); tcg_gen_ext32u_tl(t1, t1); tcg_gen_extu_tl_i64(t2, t0); tcg_gen_extu_tl_i64(t3, t1); tcg_gen_mul_i64(t2, t2, t3); - tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]); + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); tcg_gen_sub_i64(t2, t3, t2); tcg_temp_free_i64(t3); tcg_gen_trunc_i64_tl(t0, t2); tcg_gen_shri_i64(t2, t2, 32); tcg_gen_trunc_i64_tl(t1, t2); tcg_temp_free_i64(t2); - tcg_gen_ext32s_tl(cpu_LO[0], t0); - tcg_gen_ext32s_tl(cpu_HI[0], t1); + tcg_gen_ext32s_tl(cpu_LO[acc], t0); + tcg_gen_ext32s_tl(cpu_HI[acc], t1); } opn = "msubu"; break; From e45a93e2590051e77a3d944a0feb3360a1ff1841 Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Wed, 24 Oct 2012 22:17:04 +0800 Subject: [PATCH 1398/2270] target-mips: Add ASE DSP branch instructions Add MIPS ASE DSP Branch instructions. Signed-off-by: Jia Liu Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/target-mips/translate.c b/target-mips/translate.c index 134d06f9f0..6677d2b531 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -332,6 +332,14 @@ enum { OPC_DSHD = (0x05 << 6) | OPC_DBSHFL, }; +/* MIPS DSP REGIMM opcodes */ +enum { + OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM, +#if defined(TARGET_MIPS64) + OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM, +#endif +}; + /* Coprocessor 0 (rs field) */ #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) @@ -3230,6 +3238,16 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, } btgt = ctx->pc + insn_bytes + offset; break; + case OPC_BPOSGE32: +#if defined(TARGET_MIPS64) + case OPC_BPOSGE64: + tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F); +#else + tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F); +#endif + bcond_compute = 1; + btgt = ctx->pc + insn_bytes + offset; + break; case OPC_J: case OPC_JAL: case OPC_JALX: @@ -3418,6 +3436,16 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0); MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt); goto likely; + case OPC_BPOSGE32: + tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32); + MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt); + goto not_likely; +#if defined(TARGET_MIPS64) + case OPC_BPOSGE64: + tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64); + MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt); + goto not_likely; +#endif case OPC_BLTZALS: case OPC_BLTZAL: ctx->hflags |= (opc == OPC_BLTZALS @@ -12589,6 +12617,14 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) check_insn(env, ctx, ISA_MIPS32R2); /* Treat as NOP. */ break; + case OPC_BPOSGE32: /* MIPS DSP branch */ +#if defined(TARGET_MIPS64) + case OPC_BPOSGE64: +#endif + check_dsp(ctx); + gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2); + *is_branch = 1; + break; default: /* Invalid */ MIPS_INVAL("regimm"); generate_exception(ctx, EXCP_RI); From 9b1a1d68d0411cf67502b2adb3daae2eb157b704 Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Wed, 24 Oct 2012 22:17:05 +0800 Subject: [PATCH 1399/2270] target-mips: Add ASE DSP load instructions Add MIPS ASE DSP Load instructions. Signed-off-by: Jia Liu Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 88 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/target-mips/translate.c b/target-mips/translate.c index 6677d2b531..fdff3273ad 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -313,6 +313,9 @@ enum { OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3, OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3, OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3, + + /* MIPS DSP Load */ + OPC_LX_DSP = 0x0A | OPC_SPECIAL3, }; /* BSHFL opcodes */ @@ -340,6 +343,17 @@ enum { #endif }; +#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +/* MIPS DSP Load */ +enum { + OPC_LBUX = (0x06 << 6) | OPC_LX_DSP, + OPC_LHX = (0x04 << 6) | OPC_LX_DSP, + OPC_LWX = (0x00 << 6) | OPC_LX_DSP, +#if defined(TARGET_MIPS64) + OPC_LDX = (0x08 << 6) | OPC_LX_DSP, +#endif +}; + /* Coprocessor 0 (rs field) */ #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) @@ -12219,6 +12233,63 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b #endif +/* MIPSDSP functions. */ +static void gen_mipsdsp_ld(CPUMIPSState *env, DisasContext *ctx, uint32_t opc, + int rd, int base, int offset) +{ + const char *opn = "ldx"; + TCGv t0; + + if (rd == 0) { + MIPS_DEBUG("NOP"); + return; + } + + check_dsp(ctx); + t0 = tcg_temp_new(); + + if (base == 0) { + gen_load_gpr(t0, offset); + } else if (offset == 0) { + gen_load_gpr(t0, base); + } else { + gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]); + } + + save_cpu_state(ctx, 0); + switch (opc) { + case OPC_LBUX: + op_ld_lbu(t0, t0, ctx); + gen_store_gpr(t0, rd); + opn = "lbux"; + break; + case OPC_LHX: + op_ld_lh(t0, t0, ctx); + gen_store_gpr(t0, rd); + opn = "lhx"; + break; + case OPC_LWX: + op_ld_lw(t0, t0, ctx); + gen_store_gpr(t0, rd); + opn = "lwx"; + break; +#if defined(TARGET_MIPS64) + case OPC_LDX: + op_ld_ld(t0, t0, ctx); + gen_store_gpr(t0, rd); + opn = "ldx"; + break; +#endif + } + (void)opn; /* avoid a compiler warning */ + MIPS_DEBUG("%s %s, %s(%s)", opn, + regnames[rd], regnames[offset], regnames[base]); + tcg_temp_free(t0); +} + + +/* End MIPSDSP functions. */ + static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) { int32_t offset; @@ -12575,6 +12646,23 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) check_insn(env, ctx, INSN_LOONGSON2E); gen_loongson_integer(ctx, op1, rd, rs, rt); break; + case OPC_LX_DSP: + op2 = MASK_LX(ctx->opcode); + switch (op2) { +#if defined(TARGET_MIPS64) + case OPC_LDX: +#endif + case OPC_LBUX: + case OPC_LHX: + case OPC_LWX: + gen_mipsdsp_ld(env, ctx, op2, rd, rs, rt); + break; + default: /* Invalid */ + MIPS_INVAL("MASK LX"); + generate_exception(ctx, EXCP_RI); + break; + } + break; #if defined(TARGET_MIPS64) case OPC_DEXTM ... OPC_DEXT: case OPC_DINSM ... OPC_DINS: From 461c08df75d8564a3ef8582bfcda398e9b09c0ff Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Wed, 24 Oct 2012 22:17:06 +0800 Subject: [PATCH 1400/2270] target-mips: Add ASE DSP arithmetic instructions Add MIPS ASE DSP Arithmetic instructions. Signed-off-by: Jia Liu Signed-off-by: Aurelien Jarno --- target-mips/dsp_helper.c | 894 +++++++++++++++++++++++++++++++++++++++ target-mips/helper.h | 126 ++++++ target-mips/translate.c | 795 +++++++++++++++++++++++++++++++++- 3 files changed, 1812 insertions(+), 3 deletions(-) diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index 55ea9236fa..7ddad34d10 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -1061,3 +1061,897 @@ static inline int32_t mipsdsp_cmpu_lt(uint32_t a, uint32_t b) return a < b; } /*** MIPS DSP internal functions end ***/ + +#define MIPSDSP_LHI 0xFFFFFFFF00000000ull +#define MIPSDSP_LLO 0x00000000FFFFFFFFull +#define MIPSDSP_HI 0xFFFF0000 +#define MIPSDSP_LO 0x0000FFFF +#define MIPSDSP_Q3 0xFF000000 +#define MIPSDSP_Q2 0x00FF0000 +#define MIPSDSP_Q1 0x0000FF00 +#define MIPSDSP_Q0 0x000000FF + +#define MIPSDSP_SPLIT32_8(num, a, b, c, d) \ + do { \ + a = (num >> 24) & MIPSDSP_Q0; \ + b = (num >> 16) & MIPSDSP_Q0; \ + c = (num >> 8) & MIPSDSP_Q0; \ + d = num & MIPSDSP_Q0; \ + } while (0) + +#define MIPSDSP_SPLIT32_16(num, a, b) \ + do { \ + a = (num >> 16) & MIPSDSP_LO; \ + b = num & MIPSDSP_LO; \ + } while (0) + +#define MIPSDSP_RETURN32(a) ((target_long)(int32_t)a) +#define MIPSDSP_RETURN32_8(a, b, c, d) ((target_long)(int32_t) \ + (((uint32_t)a << 24) | \ + (((uint32_t)b << 16) | \ + (((uint32_t)c << 8) | \ + ((uint32_t)d & 0xFF))))) +#define MIPSDSP_RETURN32_16(a, b) ((target_long)(int32_t) \ + (((uint32_t)a << 16) | \ + ((uint32_t)b & 0xFFFF))) + +#ifdef TARGET_MIPS64 +#define MIPSDSP_SPLIT64_16(num, a, b, c, d) \ + do { \ + a = (num >> 48) & MIPSDSP_LO; \ + b = (num >> 32) & MIPSDSP_LO; \ + c = (num >> 16) & MIPSDSP_LO; \ + d = num & MIPSDSP_LO; \ + } while (0) + +#define MIPSDSP_SPLIT64_32(num, a, b) \ + do { \ + a = (num >> 32) & MIPSDSP_LLO; \ + b = num & MIPSDSP_LLO; \ + } while (0) + +#define MIPSDSP_RETURN64_16(a, b, c, d) (((uint64_t)a << 48) | \ + ((uint64_t)b << 32) | \ + ((uint64_t)c << 16) | \ + (uint64_t)d) +#define MIPSDSP_RETURN64_32(a, b) (((uint64_t)a << 32) | (uint64_t)b) +#endif + +/** DSP Arithmetic Sub-class insns **/ +#define ARITH_PH(name, func) \ +target_ulong helper_##name##_ph(target_ulong rs, target_ulong rt) \ +{ \ + uint16_t rsh, rsl, rth, rtl, temph, templ; \ + \ + MIPSDSP_SPLIT32_16(rs, rsh, rsl); \ + MIPSDSP_SPLIT32_16(rt, rth, rtl); \ + \ + temph = mipsdsp_##func(rsh, rth); \ + templ = mipsdsp_##func(rsl, rtl); \ + \ + return MIPSDSP_RETURN32_16(temph, templ); \ +} + +#define ARITH_PH_ENV(name, func) \ +target_ulong helper_##name##_ph(target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + uint16_t rsh, rsl, rth, rtl, temph, templ; \ + \ + MIPSDSP_SPLIT32_16(rs, rsh, rsl); \ + MIPSDSP_SPLIT32_16(rt, rth, rtl); \ + \ + temph = mipsdsp_##func(rsh, rth, env); \ + templ = mipsdsp_##func(rsl, rtl, env); \ + \ + return MIPSDSP_RETURN32_16(temph, templ); \ +} + + +ARITH_PH_ENV(addq, add_i16); +ARITH_PH_ENV(addq_s, sat_add_i16); +ARITH_PH_ENV(addu, add_u16); +ARITH_PH_ENV(addu_s, sat_add_u16); + +ARITH_PH(addqh, rshift1_add_q16); +ARITH_PH(addqh_r, rrshift1_add_q16); + +ARITH_PH_ENV(subq, sub_i16); +ARITH_PH_ENV(subq_s, sat16_sub); +ARITH_PH_ENV(subu, sub_u16_u16); +ARITH_PH_ENV(subu_s, satu16_sub_u16_u16); + +ARITH_PH(subqh, rshift1_sub_q16); +ARITH_PH(subqh_r, rrshift1_sub_q16); + +#undef ARITH_PH +#undef ARITH_PH_ENV + +#ifdef TARGET_MIPS64 +#define ARITH_QH_ENV(name, func) \ +target_ulong helper_##name##_qh(target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + uint16_t rs3, rs2, rs1, rs0; \ + uint16_t rt3, rt2, rt1, rt0; \ + uint16_t tempD, tempC, tempB, tempA; \ + \ + MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \ + MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ + \ + tempD = mipsdsp_##func(rs3, rt3, env); \ + tempC = mipsdsp_##func(rs2, rt2, env); \ + tempB = mipsdsp_##func(rs1, rt1, env); \ + tempA = mipsdsp_##func(rs0, rt0, env); \ + \ + return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ +} + +ARITH_QH_ENV(addq, add_i16); +ARITH_QH_ENV(addq_s, sat_add_i16); +ARITH_QH_ENV(addu, add_u16); +ARITH_QH_ENV(addu_s, sat_add_u16); + +ARITH_QH_ENV(subq, sub_i16); +ARITH_QH_ENV(subq_s, sat16_sub); +ARITH_QH_ENV(subu, sub_u16_u16); +ARITH_QH_ENV(subu_s, satu16_sub_u16_u16); + +#undef ARITH_QH_ENV + +#endif + +#define ARITH_W(name, func) \ +target_ulong helper_##name##_w(target_ulong rs, target_ulong rt) \ +{ \ + uint32_t rd; \ + rd = mipsdsp_##func(rs, rt); \ + return MIPSDSP_RETURN32(rd); \ +} + +#define ARITH_W_ENV(name, func) \ +target_ulong helper_##name##_w(target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + uint32_t rd; \ + rd = mipsdsp_##func(rs, rt, env); \ + return MIPSDSP_RETURN32(rd); \ +} + +ARITH_W_ENV(addq_s, sat_add_i32); + +ARITH_W(addqh, rshift1_add_q32); +ARITH_W(addqh_r, rrshift1_add_q32); + +ARITH_W_ENV(subq_s, sat32_sub); + +ARITH_W(subqh, rshift1_sub_q32); +ARITH_W(subqh_r, rrshift1_sub_q32); + +#undef ARITH_W +#undef ARITH_W_ENV + +target_ulong helper_absq_s_w(target_ulong rt, CPUMIPSState *env) +{ + uint32_t rd; + + rd = mipsdsp_sat_abs32(rt, env); + + return (target_ulong)rd; +} + + +#if defined(TARGET_MIPS64) + +#define ARITH_PW_ENV(name, func) \ +target_ulong helper_##name##_pw(target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + uint32_t rs1, rs0; \ + uint32_t rt1, rt0; \ + uint32_t tempB, tempA; \ + \ + MIPSDSP_SPLIT64_32(rs, rs1, rs0); \ + MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ + \ + tempB = mipsdsp_##func(rs1, rt1, env); \ + tempA = mipsdsp_##func(rs0, rt0, env); \ + \ + return MIPSDSP_RETURN64_32(tempB, tempA); \ +} + +ARITH_PW_ENV(addq, add_i32); +ARITH_PW_ENV(addq_s, sat_add_i32); +ARITH_PW_ENV(subq, sub32); +ARITH_PW_ENV(subq_s, sat32_sub); + +#undef ARITH_PW_ENV + +#endif + +#define ARITH_QB(name, func) \ +target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \ +{ \ + uint8_t rs0, rs1, rs2, rs3; \ + uint8_t rt0, rt1, rt2, rt3; \ + uint8_t temp0, temp1, temp2, temp3; \ + \ + MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0); \ + MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ + \ + temp0 = mipsdsp_##func(rs0, rt0); \ + temp1 = mipsdsp_##func(rs1, rt1); \ + temp2 = mipsdsp_##func(rs2, rt2); \ + temp3 = mipsdsp_##func(rs3, rt3); \ + \ + return MIPSDSP_RETURN32_8(temp3, temp2, temp1, temp0); \ +} + +#define ARITH_QB_ENV(name, func) \ +target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + uint8_t rs0, rs1, rs2, rs3; \ + uint8_t rt0, rt1, rt2, rt3; \ + uint8_t temp0, temp1, temp2, temp3; \ + \ + MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0); \ + MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ + \ + temp0 = mipsdsp_##func(rs0, rt0, env); \ + temp1 = mipsdsp_##func(rs1, rt1, env); \ + temp2 = mipsdsp_##func(rs2, rt2, env); \ + temp3 = mipsdsp_##func(rs3, rt3, env); \ + \ + return MIPSDSP_RETURN32_8(temp3, temp2, temp1, temp0); \ +} + +ARITH_QB(adduh, rshift1_add_u8); +ARITH_QB(adduh_r, rrshift1_add_u8); + +ARITH_QB_ENV(addu, add_u8); +ARITH_QB_ENV(addu_s, sat_add_u8); + +#undef ADDU_QB +#undef ADDU_QB_ENV + +#if defined(TARGET_MIPS64) +#define ARITH_OB(name, func) \ +target_ulong helper_##name##_ob(target_ulong rs, target_ulong rt) \ +{ \ + int i; \ + uint8_t rs_t[8], rt_t[8]; \ + uint8_t temp[8]; \ + uint64_t result; \ + \ + result = 0; \ + \ + for (i = 0; i < 8; i++) { \ + rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0; \ + rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0; \ + temp[i] = mipsdsp_##func(rs_t[i], rt_t[i]); \ + result |= (uint64_t)temp[i] << (8 * i); \ + } \ + \ + return result; \ +} + +#define ARITH_OB_ENV(name, func) \ +target_ulong helper_##name##_ob(target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + int i; \ + uint8_t rs_t[8], rt_t[8]; \ + uint8_t temp[8]; \ + uint64_t result; \ + \ + result = 0; \ + \ + for (i = 0; i < 8; i++) { \ + rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0; \ + rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0; \ + temp[i] = mipsdsp_##func(rs_t[i], rt_t[i], env); \ + result |= (uint64_t)temp[i] << (8 * i); \ + } \ + \ + return result; \ +} + +ARITH_OB_ENV(addu, add_u8); +ARITH_OB_ENV(addu_s, sat_add_u8); + +ARITH_OB(adduh, rshift1_add_u8); +ARITH_OB(adduh_r, rrshift1_add_u8); + +ARITH_OB_ENV(subu, sub_u8); +ARITH_OB_ENV(subu_s, satu8_sub); + +ARITH_OB(subuh, rshift1_sub_u8); +ARITH_OB(subuh_r, rrshift1_sub_u8); + +#undef ARITH_OB +#undef ARITH_OB_ENV + +#endif + +#define SUBU_QB(name, func) \ +target_ulong helper_##name##_qb(target_ulong rs, \ + target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + uint8_t rs3, rs2, rs1, rs0; \ + uint8_t rt3, rt2, rt1, rt0; \ + uint8_t tempD, tempC, tempB, tempA; \ + \ + MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0); \ + MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ + \ + tempD = mipsdsp_##func(rs3, rt3, env); \ + tempC = mipsdsp_##func(rs2, rt2, env); \ + tempB = mipsdsp_##func(rs1, rt1, env); \ + tempA = mipsdsp_##func(rs0, rt0, env); \ + \ + return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA); \ +} + +SUBU_QB(subu, sub_u8); +SUBU_QB(subu_s, satu8_sub); + +#undef SUBU_QB + +#define SUBUH_QB(name, var) \ +target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \ +{ \ + uint8_t rs3, rs2, rs1, rs0; \ + uint8_t rt3, rt2, rt1, rt0; \ + uint8_t tempD, tempC, tempB, tempA; \ + \ + MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0); \ + MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ + \ + tempD = ((uint16_t)rs3 - (uint16_t)rt3 + var) >> 1; \ + tempC = ((uint16_t)rs2 - (uint16_t)rt2 + var) >> 1; \ + tempB = ((uint16_t)rs1 - (uint16_t)rt1 + var) >> 1; \ + tempA = ((uint16_t)rs0 - (uint16_t)rt0 + var) >> 1; \ + \ + return ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \ + ((uint32_t)tempB << 8) | ((uint32_t)tempA); \ +} + +SUBUH_QB(subuh, 0); +SUBUH_QB(subuh_r, 1); + +#undef SUBUH_QB + +target_ulong helper_addsc(target_ulong rs, target_ulong rt, CPUMIPSState *env) +{ + uint64_t temp, tempRs, tempRt; + int32_t flag; + + tempRs = (uint64_t)rs & MIPSDSP_LLO; + tempRt = (uint64_t)rt & MIPSDSP_LLO; + + temp = tempRs + tempRt; + flag = (temp & 0x0100000000ull) >> 32; + set_DSPControl_carryflag(flag, env); + + return (target_long)(int32_t)(temp & MIPSDSP_LLO); +} + +target_ulong helper_addwc(target_ulong rs, target_ulong rt, CPUMIPSState *env) +{ + uint32_t rd; + int32_t temp32, temp31; + int64_t tempL; + + tempL = (int64_t)(int32_t)rs + (int64_t)(int32_t)rt + + get_DSPControl_carryflag(env); + temp31 = (tempL >> 31) & 0x01; + temp32 = (tempL >> 32) & 0x01; + + if (temp31 != temp32) { + set_DSPControl_overflow_flag(1, 20, env); + } + + rd = tempL & MIPSDSP_LLO; + + return (target_long)(int32_t)rd; +} + +target_ulong helper_modsub(target_ulong rs, target_ulong rt) +{ + int32_t decr; + uint16_t lastindex; + target_ulong rd; + + decr = rt & MIPSDSP_Q0; + lastindex = (rt >> 8) & MIPSDSP_LO; + + if ((rs & MIPSDSP_LLO) == 0x00000000) { + rd = (target_ulong)lastindex; + } else { + rd = rs - decr; + } + + return rd; +} + +target_ulong helper_raddu_w_qb(target_ulong rs) +{ + uint8_t rs3, rs2, rs1, rs0; + uint16_t temp; + + MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0); + + temp = (uint16_t)rs3 + (uint16_t)rs2 + (uint16_t)rs1 + (uint16_t)rs0; + + return (target_ulong)temp; +} + +#if defined(TARGET_MIPS64) +target_ulong helper_raddu_l_ob(target_ulong rs) +{ + int i; + uint16_t rs_t[8]; + uint64_t temp; + + temp = 0; + + for (i = 0; i < 8; i++) { + rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0; + temp += (uint64_t)rs_t[i]; + } + + return temp; +} +#endif + +target_ulong helper_absq_s_qb(target_ulong rt, CPUMIPSState *env) +{ + uint8_t tempD, tempC, tempB, tempA; + + MIPSDSP_SPLIT32_8(rt, tempD, tempC, tempB, tempA); + + tempD = mipsdsp_sat_abs8(tempD, env); + tempC = mipsdsp_sat_abs8(tempC, env); + tempB = mipsdsp_sat_abs8(tempB, env); + tempA = mipsdsp_sat_abs8(tempA, env); + + return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA); +} + +target_ulong helper_absq_s_ph(target_ulong rt, CPUMIPSState *env) +{ + uint16_t tempB, tempA; + + MIPSDSP_SPLIT32_16(rt, tempB, tempA); + + tempB = mipsdsp_sat_abs16 (tempB, env); + tempA = mipsdsp_sat_abs16 (tempA, env); + + return MIPSDSP_RETURN32_16(tempB, tempA); +} + +#if defined(TARGET_MIPS64) +target_ulong helper_absq_s_ob(target_ulong rt, CPUMIPSState *env) +{ + int i; + int8_t temp[8]; + uint64_t result; + + for (i = 0; i < 8; i++) { + temp[i] = (rt >> (8 * i)) & MIPSDSP_Q0; + temp[i] = mipsdsp_sat_abs8(temp[i], env); + } + + for (i = 0; i < 8; i++) { + result = (uint64_t)(uint8_t)temp[i] << (8 * i); + } + + return result; +} + +target_ulong helper_absq_s_qh(target_ulong rt, CPUMIPSState *env) +{ + int16_t tempD, tempC, tempB, tempA; + + MIPSDSP_SPLIT64_16(rt, tempD, tempC, tempB, tempA); + + tempD = mipsdsp_sat_abs16(tempD, env); + tempC = mipsdsp_sat_abs16(tempC, env); + tempB = mipsdsp_sat_abs16(tempB, env); + tempA = mipsdsp_sat_abs16(tempA, env); + + return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); +} + +target_ulong helper_absq_s_pw(target_ulong rt, CPUMIPSState *env) +{ + int32_t tempB, tempA; + + MIPSDSP_SPLIT64_32(rt, tempB, tempA); + + tempB = mipsdsp_sat_abs32(tempB, env); + tempA = mipsdsp_sat_abs32(tempA, env); + + return MIPSDSP_RETURN64_32(tempB, tempA); +} +#endif + +#define PRECR_QB_PH(name, a, b)\ +target_ulong helper_##name##_qb_ph(target_ulong rs, target_ulong rt) \ +{ \ + uint8_t tempD, tempC, tempB, tempA; \ + \ + tempD = (rs >> a) & MIPSDSP_Q0; \ + tempC = (rs >> b) & MIPSDSP_Q0; \ + tempB = (rt >> a) & MIPSDSP_Q0; \ + tempA = (rt >> b) & MIPSDSP_Q0; \ + \ + return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA); \ +} + +PRECR_QB_PH(precr, 16, 0); +PRECR_QB_PH(precrq, 24, 8); + +#undef PRECR_QB_OH + +target_ulong helper_precr_sra_ph_w(uint32_t sa, target_ulong rs, + target_ulong rt) +{ + uint16_t tempB, tempA; + + tempB = ((int32_t)rt >> sa) & MIPSDSP_LO; + tempA = ((int32_t)rs >> sa) & MIPSDSP_LO; + + return MIPSDSP_RETURN32_16(tempB, tempA); +} + +target_ulong helper_precr_sra_r_ph_w(uint32_t sa, + target_ulong rs, target_ulong rt) +{ + uint64_t tempB, tempA; + + /* If sa = 0, then (sa - 1) = -1 will case shift error, so we need else. */ + if (sa == 0) { + tempB = (rt & MIPSDSP_LO) << 1; + tempA = (rs & MIPSDSP_LO) << 1; + } else { + tempB = ((int32_t)rt >> (sa - 1)) + 1; + tempA = ((int32_t)rs >> (sa - 1)) + 1; + } + rt = (((tempB >> 1) & MIPSDSP_LO) << 16) | ((tempA >> 1) & MIPSDSP_LO); + + return (target_long)(int32_t)rt; +} + +target_ulong helper_precrq_ph_w(target_ulong rs, target_ulong rt) +{ + uint16_t tempB, tempA; + + tempB = (rs & MIPSDSP_HI) >> 16; + tempA = (rt & MIPSDSP_HI) >> 16; + + return MIPSDSP_RETURN32_16(tempB, tempA); +} + +target_ulong helper_precrq_rs_ph_w(target_ulong rs, target_ulong rt, + CPUMIPSState *env) +{ + uint16_t tempB, tempA; + + tempB = mipsdsp_trunc16_sat16_round(rs, env); + tempA = mipsdsp_trunc16_sat16_round(rt, env); + + return MIPSDSP_RETURN32_16(tempB, tempA); +} + +#if defined(TARGET_MIPS64) +target_ulong helper_precr_ob_qh(target_ulong rs, target_ulong rt) +{ + uint8_t rs6, rs4, rs2, rs0; + uint8_t rt6, rt4, rt2, rt0; + uint64_t temp; + + rs6 = (rs >> 48) & MIPSDSP_Q0; + rs4 = (rs >> 32) & MIPSDSP_Q0; + rs2 = (rs >> 16) & MIPSDSP_Q0; + rs0 = rs & MIPSDSP_Q0; + rt6 = (rt >> 48) & MIPSDSP_Q0; + rt4 = (rt >> 32) & MIPSDSP_Q0; + rt2 = (rt >> 16) & MIPSDSP_Q0; + rt0 = rt & MIPSDSP_Q0; + + temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) | + ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) | + ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) | + ((uint64_t)rt2 << 8) | (uint64_t)rt0; + + return temp; +} + +#define PRECR_QH_PW(name, var) \ +target_ulong helper_precr_##name##_qh_pw(target_ulong rs, target_ulong rt, \ + uint32_t sa) \ +{ \ + uint16_t rs3, rs2, rs1, rs0; \ + uint16_t rt3, rt2, rt1, rt0; \ + uint16_t tempD, tempC, tempB, tempA; \ + \ + MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \ + MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ + \ + /* When sa = 0, we use rt2, rt0, rs2, rs0; \ + * when sa != 0, we use rt3, rt1, rs3, rs1. */ \ + if (sa == 0) { \ + tempD = rt2 << var; \ + tempC = rt0 << var; \ + tempB = rs2 << var; \ + tempA = rs0 << var; \ + } else { \ + tempD = (((int16_t)rt3 >> sa) + var) >> var; \ + tempC = (((int16_t)rt1 >> sa) + var) >> var; \ + tempB = (((int16_t)rs3 >> sa) + var) >> var; \ + tempA = (((int16_t)rs1 >> sa) + var) >> var; \ + } \ + \ + return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ +} + +PRECR_QH_PW(sra, 0); +PRECR_QH_PW(sra_r, 1); + +#undef PRECR_QH_PW + +target_ulong helper_precrq_ob_qh(target_ulong rs, target_ulong rt) +{ + uint8_t rs6, rs4, rs2, rs0; + uint8_t rt6, rt4, rt2, rt0; + uint64_t temp; + + rs6 = (rs >> 56) & MIPSDSP_Q0; + rs4 = (rs >> 40) & MIPSDSP_Q0; + rs2 = (rs >> 24) & MIPSDSP_Q0; + rs0 = (rs >> 8) & MIPSDSP_Q0; + rt6 = (rt >> 56) & MIPSDSP_Q0; + rt4 = (rt >> 40) & MIPSDSP_Q0; + rt2 = (rt >> 24) & MIPSDSP_Q0; + rt0 = (rt >> 8) & MIPSDSP_Q0; + + temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) | + ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) | + ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) | + ((uint64_t)rt2 << 8) | (uint64_t)rt0; + + return temp; +} + +target_ulong helper_precrq_qh_pw(target_ulong rs, target_ulong rt) +{ + uint16_t tempD, tempC, tempB, tempA; + + tempD = (rs >> 48) & MIPSDSP_LO; + tempC = (rs >> 16) & MIPSDSP_LO; + tempB = (rt >> 48) & MIPSDSP_LO; + tempA = (rt >> 16) & MIPSDSP_LO; + + return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); +} + +target_ulong helper_precrq_rs_qh_pw(target_ulong rs, target_ulong rt, + CPUMIPSState *env) +{ + uint32_t rs2, rs0; + uint32_t rt2, rt0; + uint16_t tempD, tempC, tempB, tempA; + + rs2 = (rs >> 32) & MIPSDSP_LLO; + rs0 = rs & MIPSDSP_LLO; + rt2 = (rt >> 32) & MIPSDSP_LLO; + rt0 = rt & MIPSDSP_LLO; + + tempD = mipsdsp_trunc16_sat16_round(rs2, env); + tempC = mipsdsp_trunc16_sat16_round(rs0, env); + tempB = mipsdsp_trunc16_sat16_round(rt2, env); + tempA = mipsdsp_trunc16_sat16_round(rt0, env); + + return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); +} + +target_ulong helper_precrq_pw_l(target_ulong rs, target_ulong rt) +{ + uint32_t tempB, tempA; + + tempB = (rs >> 32) & MIPSDSP_LLO; + tempA = (rt >> 32) & MIPSDSP_LLO; + + return MIPSDSP_RETURN64_32(tempB, tempA); +} +#endif + +target_ulong helper_precrqu_s_qb_ph(target_ulong rs, target_ulong rt, + CPUMIPSState *env) +{ + uint8_t tempD, tempC, tempB, tempA; + uint16_t rsh, rsl, rth, rtl; + + rsh = (rs & MIPSDSP_HI) >> 16; + rsl = rs & MIPSDSP_LO; + rth = (rt & MIPSDSP_HI) >> 16; + rtl = rt & MIPSDSP_LO; + + tempD = mipsdsp_sat8_reduce_precision(rsh, env); + tempC = mipsdsp_sat8_reduce_precision(rsl, env); + tempB = mipsdsp_sat8_reduce_precision(rth, env); + tempA = mipsdsp_sat8_reduce_precision(rtl, env); + + return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA); +} + +#if defined(TARGET_MIPS64) +target_ulong helper_precrqu_s_ob_qh(target_ulong rs, target_ulong rt, + CPUMIPSState *env) +{ + int i; + uint16_t rs3, rs2, rs1, rs0; + uint16_t rt3, rt2, rt1, rt0; + uint8_t temp[8]; + uint64_t result; + + result = 0; + + MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); + MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); + + temp[7] = mipsdsp_sat8_reduce_precision(rs3, env); + temp[6] = mipsdsp_sat8_reduce_precision(rs2, env); + temp[5] = mipsdsp_sat8_reduce_precision(rs1, env); + temp[4] = mipsdsp_sat8_reduce_precision(rs0, env); + temp[3] = mipsdsp_sat8_reduce_precision(rt3, env); + temp[2] = mipsdsp_sat8_reduce_precision(rt2, env); + temp[1] = mipsdsp_sat8_reduce_precision(rt1, env); + temp[0] = mipsdsp_sat8_reduce_precision(rt0, env); + + for (i = 0; i < 8; i++) { + result |= (uint64_t)temp[i] << (8 * i); + } + + return result; +} + +#define PRECEQ_PW(name, a, b) \ +target_ulong helper_preceq_pw_##name(target_ulong rt) \ +{ \ + uint16_t tempB, tempA; \ + uint32_t tempBI, tempAI; \ + \ + tempB = (rt >> a) & MIPSDSP_LO; \ + tempA = (rt >> b) & MIPSDSP_LO; \ + \ + tempBI = (uint32_t)tempB << 16; \ + tempAI = (uint32_t)tempA << 16; \ + \ + return MIPSDSP_RETURN64_32(tempBI, tempAI); \ +} + +PRECEQ_PW(qhl, 48, 32); +PRECEQ_PW(qhr, 16, 0); +PRECEQ_PW(qhla, 48, 16); +PRECEQ_PW(qhra, 32, 0); + +#undef PRECEQ_PW + +#endif + +#define PRECEQU_PH(name, a, b) \ +target_ulong helper_precequ_ph_##name(target_ulong rt) \ +{ \ + uint16_t tempB, tempA; \ + \ + tempB = (rt >> a) & MIPSDSP_Q0; \ + tempA = (rt >> b) & MIPSDSP_Q0; \ + \ + tempB = tempB << 7; \ + tempA = tempA << 7; \ + \ + return MIPSDSP_RETURN32_16(tempB, tempA); \ +} + +PRECEQU_PH(qbl, 24, 16); +PRECEQU_PH(qbr, 8, 0); +PRECEQU_PH(qbla, 24, 8); +PRECEQU_PH(qbra, 16, 0); + +#undef PRECEQU_PH + +#if defined(TARGET_MIPS64) +#define PRECEQU_QH(name, a, b, c, d) \ +target_ulong helper_precequ_qh_##name(target_ulong rt) \ +{ \ + uint16_t tempD, tempC, tempB, tempA; \ + \ + tempD = (rt >> a) & MIPSDSP_Q0; \ + tempC = (rt >> b) & MIPSDSP_Q0; \ + tempB = (rt >> c) & MIPSDSP_Q0; \ + tempA = (rt >> d) & MIPSDSP_Q0; \ + \ + tempD = tempD << 7; \ + tempC = tempC << 7; \ + tempB = tempB << 7; \ + tempA = tempA << 7; \ + \ + return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ +} + +PRECEQU_QH(obl, 56, 48, 40, 32); +PRECEQU_QH(obr, 24, 16, 8, 0); +PRECEQU_QH(obla, 56, 40, 24, 8); +PRECEQU_QH(obra, 48, 32, 16, 0); + +#undef PRECEQU_QH + +#endif + +#define PRECEU_PH(name, a, b) \ +target_ulong helper_preceu_ph_##name(target_ulong rt) \ +{ \ + uint16_t tempB, tempA; \ + \ + tempB = (rt >> a) & MIPSDSP_Q0; \ + tempA = (rt >> b) & MIPSDSP_Q0; \ + \ + return MIPSDSP_RETURN32_16(tempB, tempA); \ +} + +PRECEU_PH(qbl, 24, 16); +PRECEU_PH(qbr, 8, 0); +PRECEU_PH(qbla, 24, 8); +PRECEU_PH(qbra, 16, 0); + +#undef PRECEU_PH + +#if defined(TARGET_MIPS64) +#define PRECEU_QH(name, a, b, c, d) \ +target_ulong helper_preceu_qh_##name(target_ulong rt) \ +{ \ + uint16_t tempD, tempC, tempB, tempA; \ + \ + tempD = (rt >> a) & MIPSDSP_Q0; \ + tempC = (rt >> b) & MIPSDSP_Q0; \ + tempB = (rt >> c) & MIPSDSP_Q0; \ + tempA = (rt >> d) & MIPSDSP_Q0; \ + \ + return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ +} + +PRECEU_QH(obl, 56, 48, 40, 32); +PRECEU_QH(obr, 24, 16, 8, 0); +PRECEU_QH(obla, 56, 40, 24, 8); +PRECEU_QH(obra, 48, 32, 16, 0); + +#undef PRECEU_QH + +#endif + +#undef MIPSDSP_LHI +#undef MIPSDSP_LLO +#undef MIPSDSP_HI +#undef MIPSDSP_LO +#undef MIPSDSP_Q3 +#undef MIPSDSP_Q2 +#undef MIPSDSP_Q1 +#undef MIPSDSP_Q0 + +#undef MIPSDSP_SPLIT32_8 +#undef MIPSDSP_SPLIT32_16 + +#undef MIPSDSP_RETURN32 +#undef MIPSDSP_RETURN32_8 +#undef MIPSDSP_RETURN32_16 + +#ifdef TARGET_MIPS64 +#undef MIPSDSP_SPLIT64_16 +#undef MIPSDSP_SPLIT64_32 +#undef MIPSDSP_RETURN64_16 +#undef MIPSDSP_RETURN64_32 +#endif diff --git a/target-mips/helper.h b/target-mips/helper.h index 43ac39ff41..3325ed6164 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -362,4 +362,130 @@ DEF_HELPER_FLAGS_2(pasubub, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_1(biadd, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_FLAGS_1(pmovmskb, TCG_CALL_NO_RWG_SE, i64, i64) +/*** MIPS DSP ***/ +/* DSP Arithmetic Sub-class insns */ +DEF_HELPER_FLAGS_3(addq_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(addq_s_ph, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(addq_qh, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(addq_s_qh, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(addq_s_w, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(addq_pw, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(addq_s_pw, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(addu_qb, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(addu_s_qb, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(adduh_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(adduh_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(addu_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(addu_s_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(addqh_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(addqh_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(addqh_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(addqh_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(addu_ob, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(addu_s_ob, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(adduh_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(adduh_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(addu_qh, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(addu_s_qh, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(subq_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(subq_s_ph, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(subq_qh, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(subq_s_qh, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(subq_s_w, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(subq_pw, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(subq_s_pw, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(subu_qb, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(subu_s_qb, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(subuh_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(subuh_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(subu_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(subu_s_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(subqh_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(subqh_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(subqh_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(subqh_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(subu_ob, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(subu_s_ob, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(subuh_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(subuh_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(subu_qh, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(subu_s_qh, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(addsc, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(addwc, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(modsub, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_1(raddu_w_qb, TCG_CALL_NO_RWG_SE, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_1(raddu_l_ob, TCG_CALL_NO_RWG_SE, tl, tl) +#endif +DEF_HELPER_FLAGS_2(absq_s_qb, 0, tl, tl, env) +DEF_HELPER_FLAGS_2(absq_s_ph, 0, tl, tl, env) +DEF_HELPER_FLAGS_2(absq_s_w, 0, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_2(absq_s_ob, 0, tl, tl, env) +DEF_HELPER_FLAGS_2(absq_s_qh, 0, tl, tl, env) +DEF_HELPER_FLAGS_2(absq_s_pw, 0, tl, tl, env) +#endif +DEF_HELPER_FLAGS_2(precr_qb_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(precrq_qb_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(precr_sra_ph_w, TCG_CALL_NO_RWG_SE, + tl, i32, tl, tl) +DEF_HELPER_FLAGS_3(precr_sra_r_ph_w, TCG_CALL_NO_RWG_SE, + tl, i32, tl, tl) +DEF_HELPER_FLAGS_2(precrq_ph_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(precrq_rs_ph_w, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_2(precr_ob_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(precr_sra_qh_pw, + TCG_CALL_NO_RWG_SE, tl, tl, tl, i32) +DEF_HELPER_FLAGS_3(precr_sra_r_qh_pw, + TCG_CALL_NO_RWG_SE, tl, tl, tl, i32) +DEF_HELPER_FLAGS_2(precrq_ob_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(precrq_qh_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(precrq_rs_qh_pw, + TCG_CALL_NO_RWG_SE, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(precrq_pw_l, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#endif +DEF_HELPER_FLAGS_3(precrqu_s_qb_ph, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(precrqu_s_ob_qh, + TCG_CALL_NO_RWG_SE, tl, tl, tl, env) + +DEF_HELPER_FLAGS_1(preceq_pw_qhl, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceq_pw_qhr, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceq_pw_qhla, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceq_pw_qhra, TCG_CALL_NO_RWG_SE, tl, tl) +#endif +DEF_HELPER_FLAGS_1(precequ_ph_qbl, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(precequ_ph_qbr, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(precequ_ph_qbla, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(precequ_ph_qbra, TCG_CALL_NO_RWG_SE, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_1(precequ_qh_obl, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(precequ_qh_obr, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(precequ_qh_obla, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(precequ_qh_obra, TCG_CALL_NO_RWG_SE, tl, tl) +#endif +DEF_HELPER_FLAGS_1(preceu_ph_qbl, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceu_ph_qbr, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceu_ph_qbla, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceu_ph_qbra, TCG_CALL_NO_RWG_SE, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_1(preceu_qh_obl, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceu_qh_obr, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceu_qh_obla, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(preceu_qh_obra, TCG_CALL_NO_RWG_SE, tl, tl) +#endif + #include "def-helper.h" diff --git a/target-mips/translate.c b/target-mips/translate.c index fdff3273ad..b1fd02b806 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -316,6 +316,21 @@ enum { /* MIPS DSP Load */ OPC_LX_DSP = 0x0A | OPC_SPECIAL3, + /* MIPS DSP Arithmetic */ + OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3, +#if defined(TARGET_MIPS64) + OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3, +#endif + OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3, +#if defined(TARGET_MIPS64) + OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3, +#endif + /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */ + /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */ + OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3, +#if defined(TARGET_MIPS64) + OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3, +#endif }; /* BSHFL opcodes */ @@ -354,6 +369,144 @@ enum { #endif }; +#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Arithmetic Sub-class */ + OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP, + OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP, + OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP, + OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP, + OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP, + OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP, + OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP, + OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP, + OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP, + OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP, + OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP, + OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP, + OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP, + OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP, + OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP, + OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP, + OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP, + OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP, +}; + +#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E +#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Arithmetic Sub-class */ + OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP, + OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP, + OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP, + OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP, + OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP, + OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP, + OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP, + OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP, + OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP, + OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP, + OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP, + OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP, +}; + +#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Arithmetic Sub-class */ + OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP, + OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP, +}; + +#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Arithmetic Sub-class */ + OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP, +}; + +#if defined(TARGET_MIPS64) +#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Arithmetic Sub-class */ + OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP, + OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP, + OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP, +}; +#endif + +#if defined(TARGET_MIPS64) +#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Arithmetic Sub-class */ + OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP, + OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP, + OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP, + OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP, + OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP, + OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP, + OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP, + OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP, + OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP, + OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP, + OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP, + OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP, + OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP, + OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP, + OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP, + OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP, + OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP, + OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP, + OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP, + OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP, + OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP, +}; +#endif + +#if defined(TARGET_MIPS64) +#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Arithmetic Sub-class */ + OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP, +}; +#endif + /* Coprocessor 0 (rs field) */ #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) @@ -12287,6 +12440,459 @@ static void gen_mipsdsp_ld(CPUMIPSState *env, DisasContext *ctx, uint32_t opc, tcg_temp_free(t0); } +static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2, + int ret, int v1, int v2) +{ + const char *opn = "mipsdsp arith"; + TCGv v1_t; + TCGv v2_t; + + if (ret == 0) { + /* Treat as NOP. */ + MIPS_DEBUG("NOP"); + return; + } + + v1_t = tcg_temp_new(); + v2_t = tcg_temp_new(); + + gen_load_gpr(v1_t, v1); + gen_load_gpr(v2_t, v2); + + switch (op1) { + /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */ + case OPC_MULT_G_2E: + check_dspr2(ctx); + switch (op2) { + case OPC_ADDUH_QB: + gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_ADDUH_R_QB: + gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_ADDQH_PH: + gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_ADDQH_R_PH: + gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_ADDQH_W: + gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_ADDQH_R_W: + gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SUBUH_QB: + gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SUBUH_R_QB: + gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SUBQH_PH: + gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SUBQH_R_PH: + gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SUBQH_W: + gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SUBQH_R_W: + gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t); + break; + } + break; + case OPC_ABSQ_S_PH_DSP: + switch (op2) { + case OPC_ABSQ_S_QB: + check_dspr2(ctx); + gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env); + break; + case OPC_ABSQ_S_PH: + check_dsp(ctx); + gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env); + break; + case OPC_ABSQ_S_W: + check_dsp(ctx); + gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env); + break; + case OPC_PRECEQ_W_PHL: + check_dsp(ctx); + tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000); + tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); + break; + case OPC_PRECEQ_W_PHR: + check_dsp(ctx); + tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF); + tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16); + tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); + break; + case OPC_PRECEQU_PH_QBL: + check_dsp(ctx); + gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQU_PH_QBR: + check_dsp(ctx); + gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQU_PH_QBLA: + check_dsp(ctx); + gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQU_PH_QBRA: + check_dsp(ctx); + gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEU_PH_QBL: + check_dsp(ctx); + gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEU_PH_QBR: + check_dsp(ctx); + gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEU_PH_QBLA: + check_dsp(ctx); + gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEU_PH_QBRA: + check_dsp(ctx); + gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t); + break; + } + break; + case OPC_ADDU_QB_DSP: + switch (op2) { + case OPC_ADDQ_PH: + check_dsp(ctx); + gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDQ_S_PH: + check_dsp(ctx); + gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDQ_S_W: + check_dsp(ctx); + gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDU_QB: + check_dsp(ctx); + gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDU_S_QB: + check_dsp(ctx); + gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDU_PH: + check_dspr2(ctx); + gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDU_S_PH: + check_dspr2(ctx); + gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBQ_PH: + check_dsp(ctx); + gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBQ_S_PH: + check_dsp(ctx); + gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBQ_S_W: + check_dsp(ctx); + gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBU_QB: + check_dsp(ctx); + gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBU_S_QB: + check_dsp(ctx); + gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBU_PH: + check_dspr2(ctx); + gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBU_S_PH: + check_dspr2(ctx); + gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDSC: + check_dsp(ctx); + gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDWC: + check_dsp(ctx); + gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MODSUB: + check_dsp(ctx); + gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_RADDU_W_QB: + check_dsp(ctx); + gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t); + break; + } + break; + case OPC_CMPU_EQ_QB_DSP: + switch (op2) { + case OPC_PRECR_QB_PH: + check_dspr2(ctx); + gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_PRECRQ_QB_PH: + check_dsp(ctx); + gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_PRECR_SRA_PH_W: + check_dspr2(ctx); + { + TCGv_i32 sa_t = tcg_const_i32(v2); + gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t, + cpu_gpr[ret]); + tcg_temp_free_i32(sa_t); + break; + } + case OPC_PRECR_SRA_R_PH_W: + check_dspr2(ctx); + { + TCGv_i32 sa_t = tcg_const_i32(v2); + gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t, + cpu_gpr[ret]); + tcg_temp_free_i32(sa_t); + break; + } + case OPC_PRECRQ_PH_W: + check_dsp(ctx); + gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_PRECRQ_RS_PH_W: + check_dsp(ctx); + gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_PRECRQU_S_QB_PH: + check_dsp(ctx); + gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + } + break; +#ifdef TARGET_MIPS64 + case OPC_ABSQ_S_QH_DSP: + switch (op2) { + case OPC_PRECEQ_L_PWL: + check_dsp(ctx); + tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull); + break; + case OPC_PRECEQ_L_PWR: + check_dsp(ctx); + tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32); + break; + case OPC_PRECEQ_PW_QHL: + check_dsp(ctx); + gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQ_PW_QHR: + check_dsp(ctx); + gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQ_PW_QHLA: + check_dsp(ctx); + gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQ_PW_QHRA: + check_dsp(ctx); + gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQU_QH_OBL: + check_dsp(ctx); + gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQU_QH_OBR: + check_dsp(ctx); + gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQU_QH_OBLA: + check_dsp(ctx); + gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEQU_QH_OBRA: + check_dsp(ctx); + gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEU_QH_OBL: + check_dsp(ctx); + gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEU_QH_OBR: + check_dsp(ctx); + gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEU_QH_OBLA: + check_dsp(ctx); + gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t); + break; + case OPC_PRECEU_QH_OBRA: + check_dsp(ctx); + gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t); + break; + case OPC_ABSQ_S_OB: + check_dspr2(ctx); + gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env); + break; + case OPC_ABSQ_S_PW: + check_dsp(ctx); + gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env); + break; + case OPC_ABSQ_S_QH: + check_dsp(ctx); + gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env); + break; + } + break; + case OPC_ADDU_OB_DSP: + switch (op2) { + case OPC_RADDU_L_OB: + check_dsp(ctx); + gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t); + break; + case OPC_SUBQ_PW: + check_dsp(ctx); + gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBQ_S_PW: + check_dsp(ctx); + gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBQ_QH: + check_dsp(ctx); + gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBQ_S_QH: + check_dsp(ctx); + gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBU_OB: + check_dsp(ctx); + gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBU_S_OB: + check_dsp(ctx); + gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBU_QH: + check_dspr2(ctx); + gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBU_S_QH: + check_dspr2(ctx); + gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SUBUH_OB: + check_dspr2(ctx); + gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SUBUH_R_OB: + check_dspr2(ctx); + gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_ADDQ_PW: + check_dsp(ctx); + gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDQ_S_PW: + check_dsp(ctx); + gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDQ_QH: + check_dsp(ctx); + gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDQ_S_QH: + check_dsp(ctx); + gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDU_OB: + check_dsp(ctx); + gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDU_S_OB: + check_dsp(ctx); + gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDU_QH: + check_dspr2(ctx); + gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDU_S_QH: + check_dspr2(ctx); + gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_ADDUH_OB: + check_dspr2(ctx); + gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_ADDUH_R_OB: + check_dspr2(ctx); + gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t); + break; + } + break; + case OPC_CMPU_EQ_OB_DSP: + switch (op2) { + case OPC_PRECR_OB_QH: + check_dspr2(ctx); + gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_PRECR_SRA_QH_PW: + check_dspr2(ctx); + { + TCGv_i32 ret_t = tcg_const_i32(ret); + gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t); + tcg_temp_free_i32(ret_t); + break; + } + case OPC_PRECR_SRA_R_QH_PW: + check_dspr2(ctx); + { + TCGv_i32 sa_v = tcg_const_i32(ret); + gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v); + tcg_temp_free_i32(sa_v); + break; + } + case OPC_PRECRQ_OB_QH: + check_dsp(ctx); + gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_PRECRQ_PW_L: + check_dsp(ctx); + gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_PRECRQ_QH_PW: + check_dsp(ctx); + gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_PRECRQ_RS_QH_PW: + check_dsp(ctx); + gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_PRECRQU_S_OB_QH: + check_dsp(ctx); + gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + } + break; +#endif + } + + tcg_temp_free(v1_t); + tcg_temp_free(v2_t); + + (void)opn; /* avoid a compiler warning */ + MIPS_DEBUG("%s", opn); +} /* End MIPSDSP functions. */ @@ -12641,10 +13247,37 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) } break; case OPC_DIV_G_2E ... OPC_DIVU_G_2E: - case OPC_MULT_G_2E ... OPC_MULTU_G_2E: case OPC_MOD_G_2E ... OPC_MODU_G_2E: - check_insn(env, ctx, INSN_LOONGSON2E); - gen_loongson_integer(ctx, op1, rd, rs, rt); + case OPC_MULT_G_2E ... OPC_MULTU_G_2E: + /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have + * the same mask and op1. */ + if ((env->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) { + op2 = MASK_ADDUH_QB(ctx->opcode); + switch (op2) { + case OPC_ADDUH_QB: + case OPC_ADDUH_R_QB: + case OPC_ADDQH_PH: + case OPC_ADDQH_R_PH: + case OPC_ADDQH_W: + case OPC_ADDQH_R_W: + case OPC_SUBUH_QB: + case OPC_SUBUH_R_QB: + case OPC_SUBQH_PH: + case OPC_SUBQH_R_PH: + case OPC_SUBQH_W: + case OPC_SUBQH_R_W: + gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); + break; + default: + MIPS_INVAL("MASK ADDUH.QB"); + generate_exception(ctx, EXCP_RI); + break; + } + } else if (env->insn_flags & INSN_LOONGSON2E) { + gen_loongson_integer(ctx, op1, rd, rs, rt); + } else { + generate_exception(ctx, EXCP_RI); + } break; case OPC_LX_DSP: op2 = MASK_LX(ctx->opcode); @@ -12663,6 +13296,80 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) break; } break; + case OPC_ABSQ_S_PH_DSP: + op2 = MASK_ABSQ_S_PH(ctx->opcode); + switch (op2) { + case OPC_ABSQ_S_QB: + case OPC_ABSQ_S_PH: + case OPC_ABSQ_S_W: + case OPC_PRECEQ_W_PHL: + case OPC_PRECEQ_W_PHR: + case OPC_PRECEQU_PH_QBL: + case OPC_PRECEQU_PH_QBR: + case OPC_PRECEQU_PH_QBLA: + case OPC_PRECEQU_PH_QBRA: + case OPC_PRECEU_PH_QBL: + case OPC_PRECEU_PH_QBR: + case OPC_PRECEU_PH_QBLA: + case OPC_PRECEU_PH_QBRA: + gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); + break; + default: + MIPS_INVAL("MASK ABSQ_S.PH"); + generate_exception(ctx, EXCP_RI); + break; + } + break; + case OPC_ADDU_QB_DSP: + op2 = MASK_ADDU_QB(ctx->opcode); + switch (op2) { + case OPC_ADDQ_PH: + case OPC_ADDQ_S_PH: + case OPC_ADDQ_S_W: + case OPC_ADDU_QB: + case OPC_ADDU_S_QB: + case OPC_ADDU_PH: + case OPC_ADDU_S_PH: + case OPC_SUBQ_PH: + case OPC_SUBQ_S_PH: + case OPC_SUBQ_S_W: + case OPC_SUBU_QB: + case OPC_SUBU_S_QB: + case OPC_SUBU_PH: + case OPC_SUBU_S_PH: + case OPC_ADDSC: + case OPC_ADDWC: + case OPC_MODSUB: + case OPC_RADDU_W_QB: + gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); + break; + default: /* Invalid */ + MIPS_INVAL("MASK ADDU.QB"); + generate_exception(ctx, EXCP_RI); + break; + + } + break; + case OPC_CMPU_EQ_QB_DSP: + op2 = MASK_CMPU_EQ_QB(ctx->opcode); + switch (op2) { + case OPC_PRECR_SRA_PH_W: + case OPC_PRECR_SRA_R_PH_W: + gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd); + break; + case OPC_PRECR_QB_PH: + case OPC_PRECRQ_QB_PH: + case OPC_PRECRQ_PH_W: + case OPC_PRECRQ_RS_PH_W: + case OPC_PRECRQU_S_QB_PH: + gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); + break; + default: /* Invalid */ + MIPS_INVAL("MASK CMPU.EQ.QB"); + generate_exception(ctx, EXCP_RI); + break; + } + break; #if defined(TARGET_MIPS64) case OPC_DEXTM ... OPC_DEXT: case OPC_DINSM ... OPC_DINS: @@ -12682,6 +13389,88 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) check_insn(env, ctx, INSN_LOONGSON2E); gen_loongson_integer(ctx, op1, rd, rs, rt); break; + case OPC_ABSQ_S_QH_DSP: + op2 = MASK_ABSQ_S_QH(ctx->opcode); + switch (op2) { + case OPC_PRECEQ_L_PWL: + case OPC_PRECEQ_L_PWR: + case OPC_PRECEQ_PW_QHL: + case OPC_PRECEQ_PW_QHR: + case OPC_PRECEQ_PW_QHLA: + case OPC_PRECEQ_PW_QHRA: + case OPC_PRECEQU_QH_OBL: + case OPC_PRECEQU_QH_OBR: + case OPC_PRECEQU_QH_OBLA: + case OPC_PRECEQU_QH_OBRA: + case OPC_PRECEU_QH_OBL: + case OPC_PRECEU_QH_OBR: + case OPC_PRECEU_QH_OBLA: + case OPC_PRECEU_QH_OBRA: + case OPC_ABSQ_S_OB: + case OPC_ABSQ_S_PW: + case OPC_ABSQ_S_QH: + gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); + break; + default: /* Invalid */ + MIPS_INVAL("MASK ABSQ_S.QH"); + generate_exception(ctx, EXCP_RI); + break; + } + break; + case OPC_ADDU_OB_DSP: + op2 = MASK_ADDU_OB(ctx->opcode); + switch (op2) { + case OPC_RADDU_L_OB: + case OPC_SUBQ_PW: + case OPC_SUBQ_S_PW: + case OPC_SUBQ_QH: + case OPC_SUBQ_S_QH: + case OPC_SUBU_OB: + case OPC_SUBU_S_OB: + case OPC_SUBU_QH: + case OPC_SUBU_S_QH: + case OPC_SUBUH_OB: + case OPC_SUBUH_R_OB: + case OPC_ADDQ_PW: + case OPC_ADDQ_S_PW: + case OPC_ADDQ_QH: + case OPC_ADDQ_S_QH: + case OPC_ADDU_OB: + case OPC_ADDU_S_OB: + case OPC_ADDU_QH: + case OPC_ADDU_S_QH: + case OPC_ADDUH_OB: + case OPC_ADDUH_R_OB: + gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); + break; + default: /* Invalid */ + MIPS_INVAL("MASK ADDU.OB"); + generate_exception(ctx, EXCP_RI); + break; + } + break; + case OPC_CMPU_EQ_OB_DSP: + op2 = MASK_CMPU_EQ_OB(ctx->opcode); + switch (op2) { + case OPC_PRECR_SRA_QH_PW: + case OPC_PRECR_SRA_R_QH_PW: + /* Return value is rt. */ + gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd); + break; + case OPC_PRECR_OB_QH: + case OPC_PRECRQ_OB_QH: + case OPC_PRECRQ_PW_L: + case OPC_PRECRQ_QH_PW: + case OPC_PRECRQ_RS_QH_PW: + case OPC_PRECRQU_S_OB_QH: + gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); + break; + default: /* Invalid */ + MIPS_INVAL("MASK CMPU_EQ.OB"); + generate_exception(ctx, EXCP_RI); + break; + } + break; #endif default: /* Invalid */ MIPS_INVAL("special3"); From 77c5fa8b55adbd277dfa272752b4e99836ee4702 Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Wed, 24 Oct 2012 22:17:07 +0800 Subject: [PATCH 1401/2270] target-mips: Add ASE DSP GPR-based shift instructions Add MIPS ASE DSP GPR-Based Shift instructions. Signed-off-by: Jia Liu Signed-off-by: Aurelien Jarno --- target-mips/dsp_helper.c | 256 +++++++++++++++++++++++++++++++ target-mips/helper.h | 38 +++++ target-mips/translate.c | 324 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 618 insertions(+) diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index 7ddad34d10..3c79ceb1a7 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -1933,6 +1933,262 @@ PRECEU_QH(obra, 48, 32, 16, 0); #endif +/** DSP GPR-Based Shift Sub-class insns **/ +#define SHIFT_QB(name, func) \ +target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt) \ +{ \ + uint8_t rt3, rt2, rt1, rt0; \ + \ + sa = sa & 0x07; \ + \ + MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ + \ + rt3 = mipsdsp_##func(rt3, sa); \ + rt2 = mipsdsp_##func(rt2, sa); \ + rt1 = mipsdsp_##func(rt1, sa); \ + rt0 = mipsdsp_##func(rt0, sa); \ + \ + return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0); \ +} + +#define SHIFT_QB_ENV(name, func) \ +target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt,\ + CPUMIPSState *env) \ +{ \ + uint8_t rt3, rt2, rt1, rt0; \ + \ + sa = sa & 0x07; \ + \ + MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ + \ + rt3 = mipsdsp_##func(rt3, sa, env); \ + rt2 = mipsdsp_##func(rt2, sa, env); \ + rt1 = mipsdsp_##func(rt1, sa, env); \ + rt0 = mipsdsp_##func(rt0, sa, env); \ + \ + return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0); \ +} + +SHIFT_QB_ENV(shll, lshift8); +SHIFT_QB(shrl, rshift_u8); + +SHIFT_QB(shra, rashift8); +SHIFT_QB(shra_r, rnd8_rashift); + +#undef SHIFT_QB +#undef SHIFT_QB_ENV + +#if defined(TARGET_MIPS64) +#define SHIFT_OB(name, func) \ +target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa) \ +{ \ + int i; \ + uint8_t rt_t[8]; \ + uint64_t temp; \ + \ + sa = sa & 0x07; \ + temp = 0; \ + \ + for (i = 0; i < 8; i++) { \ + rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0; \ + rt_t[i] = mipsdsp_##func(rt_t[i], sa); \ + temp |= (uint64_t)rt_t[i] << (8 * i); \ + } \ + \ + return temp; \ +} + +#define SHIFT_OB_ENV(name, func) \ +target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa, \ + CPUMIPSState *env) \ +{ \ + int i; \ + uint8_t rt_t[8]; \ + uint64_t temp; \ + \ + sa = sa & 0x07; \ + temp = 0; \ + \ + for (i = 0; i < 8; i++) { \ + rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0; \ + rt_t[i] = mipsdsp_##func(rt_t[i], sa, env); \ + temp |= (uint64_t)rt_t[i] << (8 * i); \ + } \ + \ + return temp; \ +} + +SHIFT_OB_ENV(shll, lshift8); +SHIFT_OB(shrl, rshift_u8); + +SHIFT_OB(shra, rashift8); +SHIFT_OB(shra_r, rnd8_rashift); + +#undef SHIFT_OB +#undef SHIFT_OB_ENV + +#endif + +#define SHIFT_PH(name, func) \ +target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + uint16_t rth, rtl; \ + \ + sa = sa & 0x0F; \ + \ + MIPSDSP_SPLIT32_16(rt, rth, rtl); \ + \ + rth = mipsdsp_##func(rth, sa, env); \ + rtl = mipsdsp_##func(rtl, sa, env); \ + \ + return MIPSDSP_RETURN32_16(rth, rtl); \ +} + +SHIFT_PH(shll, lshift16); +SHIFT_PH(shll_s, sat16_lshift); + +#undef SHIFT_PH + +#if defined(TARGET_MIPS64) +#define SHIFT_QH(name, func) \ +target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa) \ +{ \ + uint16_t rt3, rt2, rt1, rt0; \ + \ + sa = sa & 0x0F; \ + \ + MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ + \ + rt3 = mipsdsp_##func(rt3, sa); \ + rt2 = mipsdsp_##func(rt2, sa); \ + rt1 = mipsdsp_##func(rt1, sa); \ + rt0 = mipsdsp_##func(rt0, sa); \ + \ + return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0); \ +} + +#define SHIFT_QH_ENV(name, func) \ +target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa, \ + CPUMIPSState *env) \ +{ \ + uint16_t rt3, rt2, rt1, rt0; \ + \ + sa = sa & 0x0F; \ + \ + MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ + \ + rt3 = mipsdsp_##func(rt3, sa, env); \ + rt2 = mipsdsp_##func(rt2, sa, env); \ + rt1 = mipsdsp_##func(rt1, sa, env); \ + rt0 = mipsdsp_##func(rt0, sa, env); \ + \ + return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0); \ +} + +SHIFT_QH_ENV(shll, lshift16); +SHIFT_QH_ENV(shll_s, sat16_lshift); + +SHIFT_QH(shrl, rshift_u16); +SHIFT_QH(shra, rashift16); +SHIFT_QH(shra_r, rnd16_rashift); + +#undef SHIFT_QH +#undef SHIFT_QH_ENV + +#endif + +#define SHIFT_W(name, func) \ +target_ulong helper_##name##_w(target_ulong sa, target_ulong rt) \ +{ \ + uint32_t temp; \ + \ + sa = sa & 0x1F; \ + temp = mipsdsp_##func(rt, sa); \ + \ + return (target_long)(int32_t)temp; \ +} + +#define SHIFT_W_ENV(name, func) \ +target_ulong helper_##name##_w(target_ulong sa, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + uint32_t temp; \ + \ + sa = sa & 0x1F; \ + temp = mipsdsp_##func(rt, sa, env); \ + \ + return (target_long)(int32_t)temp; \ +} + +SHIFT_W_ENV(shll_s, sat32_lshift); +SHIFT_W(shra_r, rnd32_rashift); + +#undef SHIFT_W +#undef SHIFT_W_ENV + +#if defined(TARGET_MIPS64) +#define SHIFT_PW(name, func) \ +target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa) \ +{ \ + uint32_t rt1, rt0; \ + \ + sa = sa & 0x1F; \ + MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ + \ + rt1 = mipsdsp_##func(rt1, sa); \ + rt0 = mipsdsp_##func(rt0, sa); \ + \ + return MIPSDSP_RETURN64_32(rt1, rt0); \ +} + +#define SHIFT_PW_ENV(name, func) \ +target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa, \ + CPUMIPSState *env) \ +{ \ + uint32_t rt1, rt0; \ + \ + sa = sa & 0x1F; \ + MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ + \ + rt1 = mipsdsp_##func(rt1, sa, env); \ + rt0 = mipsdsp_##func(rt0, sa, env); \ + \ + return MIPSDSP_RETURN64_32(rt1, rt0); \ +} + +SHIFT_PW_ENV(shll, lshift32); +SHIFT_PW_ENV(shll_s, sat32_lshift); + +SHIFT_PW(shra, rashift32); +SHIFT_PW(shra_r, rnd32_rashift); + +#undef SHIFT_PW +#undef SHIFT_PW_ENV + +#endif + +#define SHIFT_PH(name, func) \ +target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt) \ +{ \ + uint16_t rth, rtl; \ + \ + sa = sa & 0x0F; \ + \ + MIPSDSP_SPLIT32_16(rt, rth, rtl); \ + \ + rth = mipsdsp_##func(rth, sa); \ + rtl = mipsdsp_##func(rtl, sa); \ + \ + return MIPSDSP_RETURN32_16(rth, rtl); \ +} + +SHIFT_PH(shrl, rshift_u16); +SHIFT_PH(shra, rashift16); +SHIFT_PH(shra_r, rnd16_rashift); + +#undef SHIFT_PH + #undef MIPSDSP_LHI #undef MIPSDSP_LLO #undef MIPSDSP_HI diff --git a/target-mips/helper.h b/target-mips/helper.h index 3325ed6164..c1a0fead5b 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -488,4 +488,42 @@ DEF_HELPER_FLAGS_1(preceu_qh_obla, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_1(preceu_qh_obra, TCG_CALL_NO_RWG_SE, tl, tl) #endif +/* DSP GPR-Based Shift Sub-class insns */ +DEF_HELPER_FLAGS_3(shll_qb, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(shll_ob, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(shll_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(shll_s_ph, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(shll_qh, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(shll_s_qh, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(shll_s_w, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(shll_pw, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(shll_s_pw, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_2(shrl_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shrl_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_2(shrl_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shrl_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#endif +DEF_HELPER_FLAGS_2(shra_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shra_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_2(shra_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shra_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#endif +DEF_HELPER_FLAGS_2(shra_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shra_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shra_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_2(shra_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shra_r_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shra_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(shra_r_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#endif + #include "def-helper.h" diff --git a/target-mips/translate.c b/target-mips/translate.c index b1fd02b806..044fde95aa 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -330,6 +330,18 @@ enum { OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3, #if defined(TARGET_MIPS64) OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3, +#endif + /* MIPS DSP GPR-Based Shift Sub-class */ + OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3, +#if defined(TARGET_MIPS64) + OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3, +#endif + /* MIPS DSP Multiply Sub-class insns */ + /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */ + /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */ + OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3, +#if defined(TARGET_MIPS64) + OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3, #endif }; @@ -439,6 +451,32 @@ enum { OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP, OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP, }; +#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP GPR-Based Shift Sub-class */ + OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP, + OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP, + OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP, + OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP, + OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP, + OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP, + OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP, + OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP, + OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP, + OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP, + OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP, + OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP, + OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP, +}; #if defined(TARGET_MIPS64) #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) @@ -507,6 +545,39 @@ enum { }; #endif +#if defined(TARGET_MIPS64) +#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP GPR-Based Shift Sub-class */ + OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP, + OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP, + OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP, + OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP, + OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP, + OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP, + OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP, + OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP, + OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP, + OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP, + OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP, + OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP, + OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP, + OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP, + OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP, + OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP, +}; +#endif + /* Coprocessor 0 (rs field) */ #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) @@ -12894,6 +12965,253 @@ static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2, MIPS_DEBUG("%s", opn); } +static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc, + int ret, int v1, int v2) +{ + uint32_t op2; + const char *opn = "mipsdsp shift"; + TCGv t0; + TCGv v1_t; + TCGv v2_t; + + if (ret == 0) { + /* Treat as NOP. */ + MIPS_DEBUG("NOP"); + return; + } + + t0 = tcg_temp_new(); + v1_t = tcg_temp_new(); + v2_t = tcg_temp_new(); + + tcg_gen_movi_tl(t0, v1); + gen_load_gpr(v1_t, v1); + gen_load_gpr(v2_t, v2); + + switch (opc) { + case OPC_SHLL_QB_DSP: + { + op2 = MASK_SHLL_QB(ctx->opcode); + switch (op2) { + case OPC_SHLL_QB: + check_dsp(ctx); + gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env); + break; + case OPC_SHLLV_QB: + check_dsp(ctx); + gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SHLL_PH: + check_dsp(ctx); + gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env); + break; + case OPC_SHLLV_PH: + check_dsp(ctx); + gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SHLL_S_PH: + check_dsp(ctx); + gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env); + break; + case OPC_SHLLV_S_PH: + check_dsp(ctx); + gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SHLL_S_W: + check_dsp(ctx); + gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env); + break; + case OPC_SHLLV_S_W: + check_dsp(ctx); + gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_SHRL_QB: + check_dsp(ctx); + gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t); + break; + case OPC_SHRLV_QB: + check_dsp(ctx); + gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SHRL_PH: + check_dspr2(ctx); + gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t); + break; + case OPC_SHRLV_PH: + check_dspr2(ctx); + gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SHRA_QB: + check_dspr2(ctx); + gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t); + break; + case OPC_SHRA_R_QB: + check_dspr2(ctx); + gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t); + break; + case OPC_SHRAV_QB: + check_dspr2(ctx); + gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SHRAV_R_QB: + check_dspr2(ctx); + gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SHRA_PH: + check_dsp(ctx); + gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t); + break; + case OPC_SHRA_R_PH: + check_dsp(ctx); + gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t); + break; + case OPC_SHRAV_PH: + check_dsp(ctx); + gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SHRAV_R_PH: + check_dsp(ctx); + gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_SHRA_R_W: + check_dsp(ctx); + gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t); + break; + case OPC_SHRAV_R_W: + check_dsp(ctx); + gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t); + break; + default: /* Invalid */ + MIPS_INVAL("MASK SHLL.QB"); + generate_exception(ctx, EXCP_RI); + break; + } + break; + } +#ifdef TARGET_MIPS64 + case OPC_SHLL_OB_DSP: + op2 = MASK_SHLL_OB(ctx->opcode); + switch (op2) { + case OPC_SHLL_PW: + check_dsp(ctx); + gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env); + break; + case OPC_SHLLV_PW: + check_dsp(ctx); + gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env); + break; + case OPC_SHLL_S_PW: + check_dsp(ctx); + gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env); + break; + case OPC_SHLLV_S_PW: + check_dsp(ctx); + gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env); + break; + case OPC_SHLL_OB: + check_dsp(ctx); + gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env); + break; + case OPC_SHLLV_OB: + check_dsp(ctx); + gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env); + break; + case OPC_SHLL_QH: + check_dsp(ctx); + gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env); + break; + case OPC_SHLLV_QH: + check_dsp(ctx); + gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env); + break; + case OPC_SHLL_S_QH: + check_dsp(ctx); + gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env); + break; + case OPC_SHLLV_S_QH: + check_dsp(ctx); + gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env); + break; + case OPC_SHRA_OB: + check_dspr2(ctx); + gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0); + break; + case OPC_SHRAV_OB: + check_dspr2(ctx); + gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t); + break; + case OPC_SHRA_R_OB: + check_dspr2(ctx); + gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0); + break; + case OPC_SHRAV_R_OB: + check_dspr2(ctx); + gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t); + break; + case OPC_SHRA_PW: + check_dsp(ctx); + gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0); + break; + case OPC_SHRAV_PW: + check_dsp(ctx); + gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t); + break; + case OPC_SHRA_R_PW: + check_dsp(ctx); + gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0); + break; + case OPC_SHRAV_R_PW: + check_dsp(ctx); + gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t); + break; + case OPC_SHRA_QH: + check_dsp(ctx); + gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0); + break; + case OPC_SHRAV_QH: + check_dsp(ctx); + gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t); + break; + case OPC_SHRA_R_QH: + check_dsp(ctx); + gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0); + break; + case OPC_SHRAV_R_QH: + check_dsp(ctx); + gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t); + break; + case OPC_SHRL_OB: + check_dsp(ctx); + gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0); + break; + case OPC_SHRLV_OB: + check_dsp(ctx); + gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t); + break; + case OPC_SHRL_QH: + check_dspr2(ctx); + gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0); + break; + case OPC_SHRLV_QH: + check_dspr2(ctx); + gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t); + break; + default: /* Invalid */ + MIPS_INVAL("MASK SHLL.OB"); + generate_exception(ctx, EXCP_RI); + break; + } + break; +#endif + } + + tcg_temp_free(t0); + tcg_temp_free(v1_t); + tcg_temp_free(v2_t); + (void)opn; /* avoid a compiler warning */ + MIPS_DEBUG("%s", opn); +} + /* End MIPSDSP functions. */ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) @@ -13370,6 +13688,9 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) break; } break; + case OPC_SHLL_QB_DSP: + gen_mipsdsp_shift(ctx, op1, rd, rs, rt); + break; #if defined(TARGET_MIPS64) case OPC_DEXTM ... OPC_DEXT: case OPC_DINSM ... OPC_DINS: @@ -13471,6 +13792,9 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) break; } break; + case OPC_SHLL_OB_DSP: + gen_mipsdsp_shift(ctx, op1, rd, rs, rt); + break; #endif default: /* Invalid */ MIPS_INVAL("special3"); From a22260ae380fa6abb546479cfc2962ba4c40382d Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Wed, 24 Oct 2012 22:17:08 +0800 Subject: [PATCH 1402/2270] target-mips: Add ASE DSP multiply instructions Add MIPS ASE DSP Multiply instructions. Signed-off-by: Jia Liu Signed-off-by: Aurelien Jarno --- target-mips/dsp_helper.c | 923 +++++++++++++++++++++++++++++++++++++++ target-mips/helper.h | 91 ++++ target-mips/translate.c | 485 ++++++++++++++++++++ 3 files changed, 1499 insertions(+) diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index 3c79ceb1a7..86c27ec0e8 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -2189,6 +2189,929 @@ SHIFT_PH(shra_r, rnd16_rashift); #undef SHIFT_PH +/** DSP Multiply Sub-class insns **/ +/* Return value made up by two 16bits value. + * FIXME give the macro a better name. + */ +#define MUL_RETURN32_16_PH(name, func, \ + rsmov1, rsmov2, rsfilter, \ + rtmov1, rtmov2, rtfilter) \ +target_ulong helper_##name(target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + uint16_t rsB, rsA, rtB, rtA; \ + \ + rsB = (rs >> rsmov1) & rsfilter; \ + rsA = (rs >> rsmov2) & rsfilter; \ + rtB = (rt >> rtmov1) & rtfilter; \ + rtA = (rt >> rtmov2) & rtfilter; \ + \ + rsB = mipsdsp_##func(rsB, rtB, env); \ + rsA = mipsdsp_##func(rsA, rtA, env); \ + \ + return MIPSDSP_RETURN32_16(rsB, rsA); \ +} + +MUL_RETURN32_16_PH(muleu_s_ph_qbl, mul_u8_u16, \ + 24, 16, MIPSDSP_Q0, \ + 16, 0, MIPSDSP_LO); +MUL_RETURN32_16_PH(muleu_s_ph_qbr, mul_u8_u16, \ + 8, 0, MIPSDSP_Q0, \ + 16, 0, MIPSDSP_LO); +MUL_RETURN32_16_PH(mulq_rs_ph, rndq15_mul_q15_q15, \ + 16, 0, MIPSDSP_LO, \ + 16, 0, MIPSDSP_LO); +MUL_RETURN32_16_PH(mul_ph, mul_i16_i16, \ + 16, 0, MIPSDSP_LO, \ + 16, 0, MIPSDSP_LO); +MUL_RETURN32_16_PH(mul_s_ph, sat16_mul_i16_i16, \ + 16, 0, MIPSDSP_LO, \ + 16, 0, MIPSDSP_LO); +MUL_RETURN32_16_PH(mulq_s_ph, sat16_mul_q15_q15, \ + 16, 0, MIPSDSP_LO, \ + 16, 0, MIPSDSP_LO); + +#undef MUL_RETURN32_16_PH + +#define MUL_RETURN32_32_ph(name, func, movbits) \ +target_ulong helper_##name(target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + int16_t rsh, rth; \ + int32_t temp; \ + \ + rsh = (rs >> movbits) & MIPSDSP_LO; \ + rth = (rt >> movbits) & MIPSDSP_LO; \ + temp = mipsdsp_##func(rsh, rth, env); \ + \ + return (target_long)(int32_t)temp; \ +} + +MUL_RETURN32_32_ph(muleq_s_w_phl, mul_q15_q15_overflowflag21, 16); +MUL_RETURN32_32_ph(muleq_s_w_phr, mul_q15_q15_overflowflag21, 0); + +#undef MUL_RETURN32_32_ph + +#define MUL_VOID_PH(name, use_ac_env) \ +void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + int16_t rsh, rsl, rth, rtl; \ + int32_t tempB, tempA; \ + int64_t acc, dotp; \ + \ + MIPSDSP_SPLIT32_16(rs, rsh, rsl); \ + MIPSDSP_SPLIT32_16(rt, rth, rtl); \ + \ + if (use_ac_env == 1) { \ + tempB = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \ + tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl, env); \ + } else { \ + tempB = mipsdsp_mul_u16_u16(rsh, rth); \ + tempA = mipsdsp_mul_u16_u16(rsl, rtl); \ + } \ + \ + dotp = (int64_t)tempB - (int64_t)tempA; \ + acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ + ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ + dotp = dotp + acc; \ + env->active_tc.HI[ac] = (target_long)(int32_t) \ + ((dotp & MIPSDSP_LHI) >> 32); \ + env->active_tc.LO[ac] = (target_long)(int32_t)(dotp & MIPSDSP_LLO); \ +} + +MUL_VOID_PH(mulsaq_s_w_ph, 1); +MUL_VOID_PH(mulsa_w_ph, 0); + +#undef MUL_VOID_PH + +#if defined(TARGET_MIPS64) +#define MUL_RETURN64_16_QH(name, func, \ + rsmov1, rsmov2, rsmov3, rsmov4, rsfilter, \ + rtmov1, rtmov2, rtmov3, rtmov4, rtfilter) \ +target_ulong helper_##name(target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + uint16_t rs3, rs2, rs1, rs0; \ + uint16_t rt3, rt2, rt1, rt0; \ + uint16_t tempD, tempC, tempB, tempA; \ + \ + rs3 = (rs >> rsmov1) & rsfilter; \ + rs2 = (rs >> rsmov2) & rsfilter; \ + rs1 = (rs >> rsmov3) & rsfilter; \ + rs0 = (rs >> rsmov4) & rsfilter; \ + rt3 = (rt >> rtmov1) & rtfilter; \ + rt2 = (rt >> rtmov2) & rtfilter; \ + rt1 = (rt >> rtmov3) & rtfilter; \ + rt0 = (rt >> rtmov4) & rtfilter; \ + \ + tempD = mipsdsp_##func(rs3, rt3, env); \ + tempC = mipsdsp_##func(rs2, rt2, env); \ + tempB = mipsdsp_##func(rs1, rt1, env); \ + tempA = mipsdsp_##func(rs0, rt0, env); \ + \ + return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ +} + +MUL_RETURN64_16_QH(muleu_s_qh_obl, mul_u8_u16, \ + 56, 48, 40, 32, MIPSDSP_Q0, \ + 48, 32, 16, 0, MIPSDSP_LO); +MUL_RETURN64_16_QH(muleu_s_qh_obr, mul_u8_u16, \ + 24, 16, 8, 0, MIPSDSP_Q0, \ + 48, 32, 16, 0, MIPSDSP_LO); +MUL_RETURN64_16_QH(mulq_rs_qh, rndq15_mul_q15_q15, \ + 48, 32, 16, 0, MIPSDSP_LO, \ + 48, 32, 16, 0, MIPSDSP_LO); + +#undef MUL_RETURN64_16_QH + +#define MUL_RETURN64_32_QH(name, \ + rsmov1, rsmov2, \ + rtmov1, rtmov2) \ +target_ulong helper_##name(target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + uint16_t rsB, rsA; \ + uint16_t rtB, rtA; \ + uint32_t tempB, tempA; \ + \ + rsB = (rs >> rsmov1) & MIPSDSP_LO; \ + rsA = (rs >> rsmov2) & MIPSDSP_LO; \ + rtB = (rt >> rtmov1) & MIPSDSP_LO; \ + rtA = (rt >> rtmov2) & MIPSDSP_LO; \ + \ + tempB = mipsdsp_mul_q15_q15(5, rsB, rtB, env); \ + tempA = mipsdsp_mul_q15_q15(5, rsA, rtA, env); \ + \ + return ((uint64_t)tempB << 32) | (uint64_t)tempA; \ +} + +MUL_RETURN64_32_QH(muleq_s_pw_qhl, 48, 32, 48, 32); +MUL_RETURN64_32_QH(muleq_s_pw_qhr, 16, 0, 16, 0); + +#undef MUL_RETURN64_32_QH + +void helper_mulsaq_s_w_qh(target_ulong rs, target_ulong rt, uint32_t ac, + CPUMIPSState *env) +{ + int16_t rs3, rs2, rs1, rs0; + int16_t rt3, rt2, rt1, rt0; + int32_t tempD, tempC, tempB, tempA; + int64_t acc[2]; + int64_t temp[2]; + int64_t temp_sum; + + MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); + MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); + + tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env); + tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env); + tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env); + tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env); + + temp[0] = ((int32_t)tempD - (int32_t)tempC) + + ((int32_t)tempB - (int32_t)tempA); + temp[0] = (int64_t)(temp[0] << 30) >> 30; + if (((temp[0] >> 33) & 0x01) == 0) { + temp[1] = 0x00; + } else { + temp[1] = ~0ull; + } + + acc[0] = env->active_tc.LO[ac]; + acc[1] = env->active_tc.HI[ac]; + + temp_sum = acc[0] + temp[0]; + if (((uint64_t)temp_sum < (uint64_t)acc[0]) && + ((uint64_t)temp_sum < (uint64_t)temp[0])) { + acc[1] += 1; + } + acc[0] = temp_sum; + acc[1] += temp[1]; + + env->active_tc.HI[ac] = acc[1]; + env->active_tc.LO[ac] = acc[0]; +} +#endif + +#define DP_QB(name, func, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \ +void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + uint8_t rs3, rs2; \ + uint8_t rt3, rt2; \ + uint16_t tempB, tempA; \ + uint64_t tempC, dotp; \ + \ + rs3 = (rs >> rsmov1) & MIPSDSP_Q0; \ + rs2 = (rs >> rsmov2) & MIPSDSP_Q0; \ + rt3 = (rt >> rtmov1) & MIPSDSP_Q0; \ + rt2 = (rt >> rtmov2) & MIPSDSP_Q0; \ + tempB = mipsdsp_##func(rs3, rt3); \ + tempA = mipsdsp_##func(rs2, rt2); \ + dotp = (int64_t)tempB + (int64_t)tempA; \ + if (is_add) { \ + tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \ + ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) \ + + dotp; \ + } else { \ + tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \ + ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) \ + - dotp; \ + } \ + \ + env->active_tc.HI[ac] = (target_long)(int32_t) \ + ((tempC & MIPSDSP_LHI) >> 32); \ + env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO); \ +} + +DP_QB(dpau_h_qbl, mul_u8_u8, 1, 24, 16, 24, 16); +DP_QB(dpau_h_qbr, mul_u8_u8, 1, 8, 0, 8, 0); +DP_QB(dpsu_h_qbl, mul_u8_u8, 0, 24, 16, 24, 16); +DP_QB(dpsu_h_qbr, mul_u8_u8, 0, 8, 0, 8, 0); + +#undef DP_QB + +#if defined(TARGET_MIPS64) +#define DP_OB(name, add_sub, \ + rsmov1, rsmov2, rsmov3, rsmov4, \ + rtmov1, rtmov2, rtmov3, rtmov4) \ +void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ + CPUMIPSState *env) \ +{ \ + uint8_t rsD, rsC, rsB, rsA; \ + uint8_t rtD, rtC, rtB, rtA; \ + uint16_t tempD, tempC, tempB, tempA; \ + uint64_t temp[2]; \ + uint64_t acc[2]; \ + uint64_t temp_sum; \ + \ + temp[0] = 0; \ + temp[1] = 0; \ + \ + rsD = (rs >> rsmov1) & MIPSDSP_Q0; \ + rsC = (rs >> rsmov2) & MIPSDSP_Q0; \ + rsB = (rs >> rsmov3) & MIPSDSP_Q0; \ + rsA = (rs >> rsmov4) & MIPSDSP_Q0; \ + rtD = (rt >> rtmov1) & MIPSDSP_Q0; \ + rtC = (rt >> rtmov2) & MIPSDSP_Q0; \ + rtB = (rt >> rtmov3) & MIPSDSP_Q0; \ + rtA = (rt >> rtmov4) & MIPSDSP_Q0; \ + \ + tempD = mipsdsp_mul_u8_u8(rsD, rtD); \ + tempC = mipsdsp_mul_u8_u8(rsC, rtC); \ + tempB = mipsdsp_mul_u8_u8(rsB, rtB); \ + tempA = mipsdsp_mul_u8_u8(rsA, rtA); \ + \ + temp[0] = (uint64_t)tempD + (uint64_t)tempC + \ + (uint64_t)tempB + (uint64_t)tempA; \ + \ + acc[0] = env->active_tc.LO[ac]; \ + acc[1] = env->active_tc.HI[ac]; \ + \ + if (add_sub) { \ + temp_sum = acc[0] + temp[0]; \ + if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ + ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ + acc[1] += 1; \ + } \ + temp[0] = temp_sum; \ + temp[1] = acc[1] + temp[1]; \ + } else { \ + temp_sum = acc[0] - temp[0]; \ + if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \ + acc[1] -= 1; \ + } \ + temp[0] = temp_sum; \ + temp[1] = acc[1] - temp[1]; \ + } \ + \ + env->active_tc.HI[ac] = temp[1]; \ + env->active_tc.LO[ac] = temp[0]; \ +} + +DP_OB(dpau_h_obl, 1, 56, 48, 40, 32, 56, 48, 40, 32); +DP_OB(dpau_h_obr, 1, 24, 16, 8, 0, 24, 16, 8, 0); +DP_OB(dpsu_h_obl, 0, 56, 48, 40, 32, 56, 48, 40, 32); +DP_OB(dpsu_h_obr, 0, 24, 16, 8, 0, 24, 16, 8, 0); + +#undef DP_OB +#endif + +#define DP_NOFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \ +void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + uint16_t rsB, rsA, rtB, rtA; \ + int32_t tempA, tempB; \ + int64_t acc; \ + \ + rsB = (rs >> rsmov1) & MIPSDSP_LO; \ + rsA = (rs >> rsmov2) & MIPSDSP_LO; \ + rtB = (rt >> rtmov1) & MIPSDSP_LO; \ + rtA = (rt >> rtmov2) & MIPSDSP_LO; \ + \ + tempB = (int32_t)rsB * (int32_t)rtB; \ + tempA = (int32_t)rsA * (int32_t)rtA; \ + \ + acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ + ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ + \ + if (is_add) { \ + acc = acc + ((int64_t)tempB + (int64_t)tempA); \ + } else { \ + acc = acc - ((int64_t)tempB + (int64_t)tempA); \ + } \ + \ + env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32); \ + env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO); \ +} + +DP_NOFUNC_PH(dpa_w_ph, 1, 16, 0, 16, 0); +DP_NOFUNC_PH(dpax_w_ph, 1, 16, 0, 0, 16); +DP_NOFUNC_PH(dps_w_ph, 0, 16, 0, 16, 0); +DP_NOFUNC_PH(dpsx_w_ph, 0, 16, 0, 0, 16); +#undef DP_NOFUNC_PH + +#define DP_HASFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \ +void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + int16_t rsB, rsA, rtB, rtA; \ + int32_t tempB, tempA; \ + int64_t acc, dotp; \ + \ + rsB = (rs >> rsmov1) & MIPSDSP_LO; \ + rsA = (rs >> rsmov2) & MIPSDSP_LO; \ + rtB = (rt >> rtmov1) & MIPSDSP_LO; \ + rtA = (rt >> rtmov2) & MIPSDSP_LO; \ + \ + tempB = mipsdsp_mul_q15_q15(ac, rsB, rtB, env); \ + tempA = mipsdsp_mul_q15_q15(ac, rsA, rtA, env); \ + \ + dotp = (int64_t)tempB + (int64_t)tempA; \ + acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ + ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ + \ + if (is_add) { \ + acc = acc + dotp; \ + } else { \ + acc = acc - dotp; \ + } \ + \ + env->active_tc.HI[ac] = (target_long)(int32_t) \ + ((acc & MIPSDSP_LHI) >> 32); \ + env->active_tc.LO[ac] = (target_long)(int32_t) \ + (acc & MIPSDSP_LLO); \ +} + +DP_HASFUNC_PH(dpaq_s_w_ph, 1, 16, 0, 16, 0); +DP_HASFUNC_PH(dpaqx_s_w_ph, 1, 16, 0, 0, 16); +DP_HASFUNC_PH(dpsq_s_w_ph, 0, 16, 0, 16, 0); +DP_HASFUNC_PH(dpsqx_s_w_ph, 0, 16, 0, 0, 16); + +#undef DP_HASFUNC_PH + +#define DP_128OPERATION_PH(name, is_add) \ +void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + int16_t rsh, rsl, rth, rtl; \ + int32_t tempB, tempA, tempC62_31, tempC63; \ + int64_t acc, dotp, tempC; \ + \ + MIPSDSP_SPLIT32_16(rs, rsh, rsl); \ + MIPSDSP_SPLIT32_16(rt, rth, rtl); \ + \ + tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl, env); \ + tempA = mipsdsp_mul_q15_q15(ac, rsl, rth, env); \ + \ + dotp = (int64_t)tempB + (int64_t)tempA; \ + acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ + ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ + if (is_add) { \ + tempC = acc + dotp; \ + } else { \ + tempC = acc - dotp; \ + } \ + tempC63 = (tempC >> 63) & 0x01; \ + tempC62_31 = (tempC >> 31) & 0xFFFFFFFF; \ + \ + if ((tempC63 == 0) && (tempC62_31 != 0x00000000)) { \ + tempC = 0x7FFFFFFF; \ + set_DSPControl_overflow_flag(1, 16 + ac, env); \ + } \ + \ + if ((tempC63 == 1) && (tempC62_31 != 0xFFFFFFFF)) { \ + tempC = (int64_t)(int32_t)0x80000000; \ + set_DSPControl_overflow_flag(1, 16 + ac, env); \ + } \ + \ + env->active_tc.HI[ac] = (target_long)(int32_t) \ + ((tempC & MIPSDSP_LHI) >> 32); \ + env->active_tc.LO[ac] = (target_long)(int32_t) \ + (tempC & MIPSDSP_LLO); \ +} + +DP_128OPERATION_PH(dpaqx_sa_w_ph, 1); +DP_128OPERATION_PH(dpsqx_sa_w_ph, 0); + +#undef DP_128OPERATION_HP + +#if defined(TARGET_MIPS64) +#define DP_QH(name, is_add, use_ac_env) \ +void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ + CPUMIPSState *env) \ +{ \ + int32_t rs3, rs2, rs1, rs0; \ + int32_t rt3, rt2, rt1, rt0; \ + int32_t tempD, tempC, tempB, tempA; \ + int64_t acc[2]; \ + int64_t temp[2]; \ + int64_t temp_sum; \ + \ + MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \ + MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ + \ + if (use_ac_env) { \ + tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env); \ + tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env); \ + tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env); \ + tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env); \ + } else { \ + tempD = mipsdsp_mul_u16_u16(rs3, rt3); \ + tempC = mipsdsp_mul_u16_u16(rs2, rt2); \ + tempB = mipsdsp_mul_u16_u16(rs1, rt1); \ + tempA = mipsdsp_mul_u16_u16(rs0, rt0); \ + } \ + \ + temp[0] = (int64_t)tempD + (int64_t)tempC + \ + (int64_t)tempB + (int64_t)tempA; \ + \ + if (temp[0] >= 0) { \ + temp[1] = 0; \ + } else { \ + temp[1] = ~0ull; \ + } \ + \ + acc[1] = env->active_tc.HI[ac]; \ + acc[0] = env->active_tc.LO[ac]; \ + \ + if (is_add) { \ + temp_sum = acc[0] + temp[0]; \ + if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ + ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ + acc[1] = acc[1] + 1; \ + } \ + temp[0] = temp_sum; \ + temp[1] = acc[1] + temp[1]; \ + } else { \ + temp_sum = acc[0] - temp[0]; \ + if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \ + acc[1] = acc[1] - 1; \ + } \ + temp[0] = temp_sum; \ + temp[1] = acc[1] - temp[1]; \ + } \ + \ + env->active_tc.HI[ac] = temp[1]; \ + env->active_tc.LO[ac] = temp[0]; \ +} + +DP_QH(dpa_w_qh, 1, 0); +DP_QH(dpaq_s_w_qh, 1, 1); +DP_QH(dps_w_qh, 0, 0); +DP_QH(dpsq_s_w_qh, 0, 1); + +#undef DP_QH + +#endif + +#define DP_L_W(name, is_add) \ +void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + int32_t temp63; \ + int64_t dotp, acc; \ + uint64_t temp; \ + \ + dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env); \ + acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ + ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ + if (!is_add) { \ + dotp = -dotp; \ + } \ + \ + temp = acc + dotp; \ + if (MIPSDSP_OVERFLOW((uint64_t)acc, (uint64_t)dotp, temp, \ + (0x01ull << 63))) { \ + temp63 = (temp >> 63) & 0x01; \ + if (temp63 == 1) { \ + temp = (0x01ull << 63) - 1; \ + } else { \ + temp = 0x01ull << 63; \ + } \ + \ + set_DSPControl_overflow_flag(1, 16 + ac, env); \ + } \ + \ + env->active_tc.HI[ac] = (target_long)(int32_t) \ + ((temp & MIPSDSP_LHI) >> 32); \ + env->active_tc.LO[ac] = (target_long)(int32_t) \ + (temp & MIPSDSP_LLO); \ +} + +DP_L_W(dpaq_sa_l_w, 1); +DP_L_W(dpsq_sa_l_w, 0); + +#undef DP_L_W + +#if defined(TARGET_MIPS64) +#define DP_L_PW(name, func) \ +void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ + CPUMIPSState *env) \ +{ \ + int32_t rs1, rs0; \ + int32_t rt1, rt0; \ + int64_t tempB[2], tempA[2]; \ + int64_t temp[2]; \ + int64_t acc[2]; \ + int64_t temp_sum; \ + \ + temp[0] = 0; \ + temp[1] = 0; \ + \ + MIPSDSP_SPLIT64_32(rs, rs1, rs0); \ + MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ + \ + tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env); \ + tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env); \ + \ + if (tempB[0] >= 0) { \ + tempB[1] = 0x00; \ + } else { \ + tempB[1] = ~0ull; \ + } \ + \ + if (tempA[0] >= 0) { \ + tempA[1] = 0x00; \ + } else { \ + tempA[1] = ~0ull; \ + } \ + \ + temp_sum = tempB[0] + tempA[0]; \ + if (((uint64_t)temp_sum < (uint64_t)tempB[0]) && \ + ((uint64_t)temp_sum < (uint64_t)tempA[0])) { \ + temp[1] += 1; \ + } \ + temp[0] = temp_sum; \ + temp[1] += tempB[1] + tempA[1]; \ + \ + mipsdsp_##func(acc, ac, temp, env); \ + \ + env->active_tc.HI[ac] = acc[1]; \ + env->active_tc.LO[ac] = acc[0]; \ +} + +DP_L_PW(dpaq_sa_l_pw, sat64_acc_add_q63); +DP_L_PW(dpsq_sa_l_pw, sat64_acc_sub_q63); + +#undef DP_L_PW + +void helper_mulsaq_s_l_pw(target_ulong rs, target_ulong rt, uint32_t ac, + CPUMIPSState *env) +{ + int32_t rs1, rs0; + int32_t rt1, rt0; + int64_t tempB[2], tempA[2]; + int64_t temp[2]; + int64_t acc[2]; + int64_t temp_sum; + + rs1 = (rs >> 32) & MIPSDSP_LLO; + rs0 = rs & MIPSDSP_LLO; + rt1 = (rt >> 32) & MIPSDSP_LLO; + rt0 = rt & MIPSDSP_LLO; + + tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env); + tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env); + + if (tempB[0] >= 0) { + tempB[1] = 0x00; + } else { + tempB[1] = ~0ull; + } + + if (tempA[0] >= 0) { + tempA[1] = 0x00; + } else { + tempA[1] = ~0ull; + } + + acc[0] = env->active_tc.LO[ac]; + acc[1] = env->active_tc.HI[ac]; + + temp_sum = tempB[0] - tempA[0]; + if ((uint64_t)temp_sum > (uint64_t)tempB[0]) { + tempB[1] -= 1; + } + temp[0] = temp_sum; + temp[1] = tempB[1] - tempA[1]; + + if ((temp[1] & 0x01) == 0) { + temp[1] = 0x00; + } else { + temp[1] = ~0ull; + } + + temp_sum = acc[0] + temp[0]; + if (((uint64_t)temp_sum < (uint64_t)acc[0]) && + ((uint64_t)temp_sum < (uint64_t)temp[0])) { + acc[1] += 1; + } + acc[0] = temp_sum; + acc[1] += temp[1]; + + env->active_tc.HI[ac] = acc[1]; + env->active_tc.LO[ac] = acc[0]; +} +#endif + +#define MAQ_S_W(name, mov) \ +void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + int16_t rsh, rth; \ + int32_t tempA; \ + int64_t tempL, acc; \ + \ + rsh = (rs >> mov) & MIPSDSP_LO; \ + rth = (rt >> mov) & MIPSDSP_LO; \ + tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \ + acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ + ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ + tempL = (int64_t)tempA + acc; \ + env->active_tc.HI[ac] = (target_long)(int32_t) \ + ((tempL & MIPSDSP_LHI) >> 32); \ + env->active_tc.LO[ac] = (target_long)(int32_t) \ + (tempL & MIPSDSP_LLO); \ +} + +MAQ_S_W(maq_s_w_phl, 16); +MAQ_S_W(maq_s_w_phr, 0); + +#undef MAQ_S_W + +#define MAQ_SA_W(name, mov) \ +void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + int16_t rsh, rth; \ + int32_t tempA; \ + \ + rsh = (rs >> mov) & MIPSDSP_LO; \ + rth = (rt >> mov) & MIPSDSP_LO; \ + tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \ + tempA = mipsdsp_sat32_acc_q31(ac, tempA, env); \ + \ + env->active_tc.HI[ac] = (target_long)(int32_t)(((int64_t)tempA & \ + MIPSDSP_LHI) >> 32); \ + env->active_tc.LO[ac] = (target_long)(int32_t)((int64_t)tempA & \ + MIPSDSP_LLO); \ +} + +MAQ_SA_W(maq_sa_w_phl, 16); +MAQ_SA_W(maq_sa_w_phr, 0); + +#undef MAQ_SA_W + +#define MULQ_W(name, addvar) \ +target_ulong helper_##name(target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + uint32_t rs_t, rt_t; \ + int32_t tempI; \ + int64_t tempL; \ + \ + rs_t = rs & MIPSDSP_LLO; \ + rt_t = rt & MIPSDSP_LLO; \ + \ + if ((rs_t == 0x80000000) && (rt_t == 0x80000000)) { \ + tempL = 0x7FFFFFFF00000000ull; \ + set_DSPControl_overflow_flag(1, 21, env); \ + } else { \ + tempL = ((int64_t)rs_t * (int64_t)rt_t) << 1; \ + tempL += addvar; \ + } \ + tempI = (tempL & MIPSDSP_LHI) >> 32; \ + \ + return (target_long)(int32_t)tempI; \ +} + +MULQ_W(mulq_s_w, 0); +MULQ_W(mulq_rs_w, 0x80000000ull); + +#undef MULQ_W + +#if defined(TARGET_MIPS64) + +#define MAQ_S_W_QH(name, mov) \ +void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ + CPUMIPSState *env) \ +{ \ + int16_t rs_t, rt_t; \ + int32_t temp_mul; \ + int64_t temp[2]; \ + int64_t acc[2]; \ + int64_t temp_sum; \ + \ + temp[0] = 0; \ + temp[1] = 0; \ + \ + rs_t = (rs >> mov) & MIPSDSP_LO; \ + rt_t = (rt >> mov) & MIPSDSP_LO; \ + temp_mul = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env); \ + \ + temp[0] = (int64_t)temp_mul; \ + if (temp[0] >= 0) { \ + temp[1] = 0x00; \ + } else { \ + temp[1] = ~0ull; \ + } \ + \ + acc[0] = env->active_tc.LO[ac]; \ + acc[1] = env->active_tc.HI[ac]; \ + \ + temp_sum = acc[0] + temp[0]; \ + if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ + ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ + acc[1] += 1; \ + } \ + acc[0] = temp_sum; \ + acc[1] += temp[1]; \ + \ + env->active_tc.HI[ac] = acc[1]; \ + env->active_tc.LO[ac] = acc[0]; \ +} + +MAQ_S_W_QH(maq_s_w_qhll, 48); +MAQ_S_W_QH(maq_s_w_qhlr, 32); +MAQ_S_W_QH(maq_s_w_qhrl, 16); +MAQ_S_W_QH(maq_s_w_qhrr, 0); + +#undef MAQ_S_W_QH + +#define MAQ_SA_W(name, mov) \ +void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ + CPUMIPSState *env) \ +{ \ + int16_t rs_t, rt_t; \ + int32_t temp; \ + int64_t acc[2]; \ + \ + rs_t = (rs >> mov) & MIPSDSP_LO; \ + rt_t = (rt >> mov) & MIPSDSP_LO; \ + temp = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env); \ + temp = mipsdsp_sat32_acc_q31(ac, temp, env); \ + \ + acc[0] = (int64_t)(int32_t)temp; \ + if (acc[0] >= 0) { \ + acc[1] = 0x00; \ + } else { \ + acc[1] = ~0ull; \ + } \ + \ + env->active_tc.HI[ac] = acc[1]; \ + env->active_tc.LO[ac] = acc[0]; \ +} + +MAQ_SA_W(maq_sa_w_qhll, 48); +MAQ_SA_W(maq_sa_w_qhlr, 32); +MAQ_SA_W(maq_sa_w_qhrl, 16); +MAQ_SA_W(maq_sa_w_qhrr, 0); + +#undef MAQ_SA_W + +#define MAQ_S_L_PW(name, mov) \ +void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ + CPUMIPSState *env) \ +{ \ + int32_t rs_t, rt_t; \ + int64_t temp[2]; \ + int64_t acc[2]; \ + int64_t temp_sum; \ + \ + temp[0] = 0; \ + temp[1] = 0; \ + \ + rs_t = (rs >> mov) & MIPSDSP_LLO; \ + rt_t = (rt >> mov) & MIPSDSP_LLO; \ + \ + temp[0] = mipsdsp_mul_q31_q31(ac, rs_t, rt_t, env); \ + if (temp[0] >= 0) { \ + temp[1] = 0x00; \ + } else { \ + temp[1] = ~0ull; \ + } \ + \ + acc[0] = env->active_tc.LO[ac]; \ + acc[1] = env->active_tc.HI[ac]; \ + \ + temp_sum = acc[0] + temp[0]; \ + if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ + ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ + acc[1] += 1; \ + } \ + acc[0] = temp_sum; \ + acc[1] += temp[1]; \ + \ + env->active_tc.HI[ac] = acc[1]; \ + env->active_tc.LO[ac] = acc[0]; \ +} + +MAQ_S_L_PW(maq_s_l_pwl, 32); +MAQ_S_L_PW(maq_s_l_pwr, 0); + +#undef MAQ_S_L_PW + +#define DM_OPERATE(name, func, is_add, sigext) \ +void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ + CPUMIPSState *env) \ +{ \ + int32_t rs1, rs0; \ + int32_t rt1, rt0; \ + int64_t tempBL[2], tempAL[2]; \ + int64_t acc[2]; \ + int64_t temp[2]; \ + int64_t temp_sum; \ + \ + temp[0] = 0x00; \ + temp[1] = 0x00; \ + \ + MIPSDSP_SPLIT64_32(rs, rs1, rs0); \ + MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ + \ + if (sigext) { \ + tempBL[0] = (int64_t)mipsdsp_##func(rs1, rt1); \ + tempAL[0] = (int64_t)mipsdsp_##func(rs0, rt0); \ + \ + if (tempBL[0] >= 0) { \ + tempBL[1] = 0x0; \ + } else { \ + tempBL[1] = ~0ull; \ + } \ + \ + if (tempAL[0] >= 0) { \ + tempAL[1] = 0x0; \ + } else { \ + tempAL[1] = ~0ull; \ + } \ + } else { \ + tempBL[0] = mipsdsp_##func(rs1, rt1); \ + tempAL[0] = mipsdsp_##func(rs0, rt0); \ + tempBL[1] = 0; \ + tempAL[1] = 0; \ + } \ + \ + acc[1] = env->active_tc.HI[ac]; \ + acc[0] = env->active_tc.LO[ac]; \ + \ + temp_sum = tempBL[0] + tempAL[0]; \ + if (((uint64_t)temp_sum < (uint64_t)tempBL[0]) && \ + ((uint64_t)temp_sum < (uint64_t)tempAL[0])) { \ + temp[1] += 1; \ + } \ + temp[0] = temp_sum; \ + temp[1] += tempBL[1] + tempAL[1]; \ + \ + if (is_add) { \ + temp_sum = acc[0] + temp[0]; \ + if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ + ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ + acc[1] += 1; \ + } \ + temp[0] = temp_sum; \ + temp[1] = acc[1] + temp[1]; \ + } else { \ + temp_sum = acc[0] - temp[0]; \ + if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \ + acc[1] -= 1; \ + } \ + temp[0] = temp_sum; \ + temp[1] = acc[1] - temp[1]; \ + } \ + \ + env->active_tc.HI[ac] = temp[1]; \ + env->active_tc.LO[ac] = temp[0]; \ +} + +DM_OPERATE(dmadd, mul_i32_i32, 1, 1); +DM_OPERATE(dmaddu, mul_u32_u32, 1, 0); +DM_OPERATE(dmsub, mul_i32_i32, 0, 1); +DM_OPERATE(dmsubu, mul_u32_u32, 0, 0); +#undef DM_OPERATE +#endif + #undef MIPSDSP_LHI #undef MIPSDSP_LLO #undef MIPSDSP_HI diff --git a/target-mips/helper.h b/target-mips/helper.h index c1a0fead5b..139bb1e464 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -526,4 +526,95 @@ DEF_HELPER_FLAGS_2(shra_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl) DEF_HELPER_FLAGS_2(shra_r_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl) #endif +/* DSP Multiply Sub-class insns */ +DEF_HELPER_FLAGS_3(muleu_s_ph_qbl, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(muleu_s_ph_qbr, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(muleu_s_qh_obl, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(muleu_s_qh_obr, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(mulq_rs_ph, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(mulq_rs_qh, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(muleq_s_w_phl, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(muleq_s_w_phr, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(muleq_s_pw_qhl, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(muleq_s_pw_qhr, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_4(dpau_h_qbl, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(dpau_h_qbr, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(dpau_h_obl, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(dpau_h_obr, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(dpsu_h_qbl, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(dpsu_h_qbr, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(dpsu_h_obl, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(dpsu_h_obr, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(dpa_w_ph, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(dpa_w_qh, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(dpax_w_ph, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(dpaq_s_w_ph, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(dpaq_s_w_qh, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(dpaqx_s_w_ph, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(dpaqx_sa_w_ph, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(dps_w_ph, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(dps_w_qh, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(dpsx_w_ph, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(dpsq_s_w_ph, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(dpsq_s_w_qh, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(dpsqx_s_w_ph, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(dpsqx_sa_w_ph, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(mulsaq_s_w_ph, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(mulsaq_s_w_qh, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(dpaq_sa_l_w, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(dpaq_sa_l_pw, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(dpsq_sa_l_w, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(dpsq_sa_l_pw, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(mulsaq_s_l_pw, 0, void, tl, tl, i32, env) +#endif +DEF_HELPER_FLAGS_4(maq_s_w_phl, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(maq_s_w_phr, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(maq_sa_w_phl, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_4(maq_sa_w_phr, 0, void, i32, tl, tl, env) +DEF_HELPER_FLAGS_3(mul_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(mul_s_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(mulq_s_ph, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(mulq_s_w, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(mulq_rs_w, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_4(mulsa_w_ph, 0, void, i32, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_4(maq_s_w_qhll, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_s_w_qhlr, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_s_w_qhrl, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_s_w_qhrr, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_sa_w_qhll, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_sa_w_qhlr, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_sa_w_qhrl, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_sa_w_qhrr, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_s_l_pwl, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(maq_s_l_pwr, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(dmadd, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(dmaddu, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(dmsub, 0, void, tl, tl, i32, env) +DEF_HELPER_FLAGS_4(dmsubu, 0, void, tl, tl, i32, env) +#endif + #include "def-helper.h" diff --git a/target-mips/translate.c b/target-mips/translate.c index 044fde95aa..5d374c4c37 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -402,6 +402,13 @@ enum { OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP, OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP, OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP, + /* MIPS DSP Multiply Sub-class insns */ + OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP, + OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP, + OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP, + OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP, + OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP, + OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP, }; #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E @@ -420,6 +427,11 @@ enum { OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP, OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP, OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP, + /* MIPS DSP Multiply Sub-class insns */ + OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP, + OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP, + OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP, + OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP, }; #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) @@ -451,6 +463,7 @@ enum { OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP, OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP, }; + #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { /* MIPS DSP GPR-Based Shift Sub-class */ @@ -478,6 +491,33 @@ enum { OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP, }; +#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Multiply Sub-class insns */ + OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP, + OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP, + OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP, + OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP, + OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP, + OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP, + OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP, + OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP, + OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP, + OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP, + OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP, + OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP, +}; + #if defined(TARGET_MIPS64) #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { @@ -505,6 +545,12 @@ enum { #if defined(TARGET_MIPS64) #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { + /* MIPS DSP Multiply Sub-class insns */ + OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP, + OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP, + OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP, + OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP, + OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP, /* MIPS DSP Arithmetic Sub-class */ OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP, OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP, @@ -545,6 +591,39 @@ enum { }; #endif +#if defined(TARGET_MIPS64) +#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Multiply Sub-class insns */ + OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP, + OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP, + OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP, +}; +#endif + #if defined(TARGET_MIPS64) #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { @@ -13212,6 +13291,319 @@ static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc, MIPS_DEBUG("%s", opn); } +static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2, + int ret, int v1, int v2, int check_ret) +{ + const char *opn = "mipsdsp multiply"; + TCGv_i32 t0; + TCGv v1_t; + TCGv v2_t; + + if ((ret == 0) && (check_ret == 1)) { + /* Treat as NOP. */ + MIPS_DEBUG("NOP"); + return; + } + + t0 = tcg_temp_new_i32(); + v1_t = tcg_temp_new(); + v2_t = tcg_temp_new(); + + tcg_gen_movi_i32(t0, ret); + gen_load_gpr(v1_t, v1); + gen_load_gpr(v2_t, v2); + + switch (op1) { + /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have + * the same mask and op1. */ + case OPC_MULT_G_2E: + switch (op2) { + case OPC_MUL_PH: + gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MUL_S_PH: + gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULQ_S_W: + gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULQ_RS_W: + gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + } + break; + case OPC_DPA_W_PH_DSP: + switch (op2) { + case OPC_DPAU_H_QBL: + check_dsp(ctx); + gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPAU_H_QBR: + check_dsp(ctx); + gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPSU_H_QBL: + check_dsp(ctx); + gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPSU_H_QBR: + check_dsp(ctx); + gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPA_W_PH: + check_dspr2(ctx); + gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPAX_W_PH: + check_dspr2(ctx); + gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPAQ_S_W_PH: + check_dsp(ctx); + gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPAQX_S_W_PH: + check_dspr2(ctx); + gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPAQX_SA_W_PH: + check_dspr2(ctx); + gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPS_W_PH: + check_dspr2(ctx); + gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPSX_W_PH: + check_dspr2(ctx); + gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPSQ_S_W_PH: + check_dsp(ctx); + gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPSQX_S_W_PH: + check_dspr2(ctx); + gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPSQX_SA_W_PH: + check_dspr2(ctx); + gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_MULSAQ_S_W_PH: + check_dsp(ctx); + gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPAQ_SA_L_W: + check_dsp(ctx); + gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env); + break; + case OPC_DPSQ_SA_L_W: + check_dsp(ctx); + gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env); + break; + case OPC_MAQ_S_W_PHL: + check_dsp(ctx); + gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env); + break; + case OPC_MAQ_S_W_PHR: + check_dsp(ctx); + gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env); + break; + case OPC_MAQ_SA_W_PHL: + check_dsp(ctx); + gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env); + break; + case OPC_MAQ_SA_W_PHR: + check_dsp(ctx); + gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env); + break; + case OPC_MULSA_W_PH: + check_dspr2(ctx); + gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env); + break; + } + break; +#ifdef TARGET_MIPS64 + case OPC_DPAQ_W_QH_DSP: + { + int ac = ret & 0x03; + tcg_gen_movi_i32(t0, ac); + + switch (op2) { + case OPC_DMADD: + check_dsp(ctx); + gen_helper_dmadd(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DMADDU: + check_dsp(ctx); + gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DMSUB: + check_dsp(ctx); + gen_helper_dmsub(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DMSUBU: + check_dsp(ctx); + gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPA_W_QH: + check_dspr2(ctx); + gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPAQ_S_W_QH: + check_dsp(ctx); + gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPAQ_SA_L_PW: + check_dsp(ctx); + gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPAU_H_OBL: + check_dsp(ctx); + gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPAU_H_OBR: + check_dsp(ctx); + gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPS_W_QH: + check_dspr2(ctx); + gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPSQ_S_W_QH: + check_dsp(ctx); + gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPSQ_SA_L_PW: + check_dsp(ctx); + gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPSU_H_OBL: + check_dsp(ctx); + gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env); + break; + case OPC_DPSU_H_OBR: + check_dsp(ctx); + gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_S_L_PWL: + check_dsp(ctx); + gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_S_L_PWR: + check_dsp(ctx); + gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_S_W_QHLL: + check_dsp(ctx); + gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_SA_W_QHLL: + check_dsp(ctx); + gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_S_W_QHLR: + check_dsp(ctx); + gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_SA_W_QHLR: + check_dsp(ctx); + gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_S_W_QHRL: + check_dsp(ctx); + gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_SA_W_QHRL: + check_dsp(ctx); + gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_S_W_QHRR: + check_dsp(ctx); + gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MAQ_SA_W_QHRR: + check_dsp(ctx); + gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MULSAQ_S_L_PW: + check_dsp(ctx); + gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env); + break; + case OPC_MULSAQ_S_W_QH: + check_dsp(ctx); + gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env); + break; + } + } + break; +#endif + case OPC_ADDU_QB_DSP: + switch (op2) { + case OPC_MULEU_S_PH_QBL: + check_dsp(ctx); + gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULEU_S_PH_QBR: + check_dsp(ctx); + gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULQ_RS_PH: + check_dsp(ctx); + gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULEQ_S_W_PHL: + check_dsp(ctx); + gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULEQ_S_W_PHR: + check_dsp(ctx); + gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULQ_S_PH: + check_dspr2(ctx); + gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + } + break; +#ifdef TARGET_MIPS64 + case OPC_ADDU_OB_DSP: + switch (op2) { + case OPC_MULEQ_S_PW_QHL: + check_dsp(ctx); + gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULEQ_S_PW_QHR: + check_dsp(ctx); + gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULEU_S_QH_OBL: + check_dsp(ctx); + gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULEU_S_QH_OBR: + check_dsp(ctx); + gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_MULQ_RS_QH: + check_dsp(ctx); + gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + } + break; +#endif + } + + tcg_temp_free_i32(t0); + tcg_temp_free(v1_t); + tcg_temp_free(v2_t); + + (void)opn; /* avoid a compiler warning */ + MIPS_DEBUG("%s", opn); + +} + /* End MIPSDSP functions. */ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) @@ -13586,6 +13978,12 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_SUBQH_R_W: gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); break; + case OPC_MUL_PH: + case OPC_MUL_S_PH: + case OPC_MULQ_S_W: + case OPC_MULQ_RS_W: + gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1); + break; default: MIPS_INVAL("MASK ADDUH.QB"); generate_exception(ctx, EXCP_RI); @@ -13661,6 +14059,14 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_RADDU_W_QB: gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); break; + case OPC_MULEU_S_PH_QBL: + case OPC_MULEU_S_PH_QBR: + case OPC_MULQ_RS_PH: + case OPC_MULEQ_S_W_PHL: + case OPC_MULEQ_S_W_PHR: + case OPC_MULQ_S_PH: + gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1); + break; default: /* Invalid */ MIPS_INVAL("MASK ADDU.QB"); generate_exception(ctx, EXCP_RI); @@ -13691,6 +14097,39 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_SHLL_QB_DSP: gen_mipsdsp_shift(ctx, op1, rd, rs, rt); break; + case OPC_DPA_W_PH_DSP: + op2 = MASK_DPA_W_PH(ctx->opcode); + switch (op2) { + case OPC_DPAU_H_QBL: + case OPC_DPAU_H_QBR: + case OPC_DPSU_H_QBL: + case OPC_DPSU_H_QBR: + case OPC_DPA_W_PH: + case OPC_DPAX_W_PH: + case OPC_DPAQ_S_W_PH: + case OPC_DPAQX_S_W_PH: + case OPC_DPAQX_SA_W_PH: + case OPC_DPS_W_PH: + case OPC_DPSX_W_PH: + case OPC_DPSQ_S_W_PH: + case OPC_DPSQX_S_W_PH: + case OPC_DPSQX_SA_W_PH: + case OPC_MULSAQ_S_W_PH: + case OPC_DPAQ_SA_L_W: + case OPC_DPSQ_SA_L_W: + case OPC_MAQ_S_W_PHL: + case OPC_MAQ_S_W_PHR: + case OPC_MAQ_SA_W_PHL: + case OPC_MAQ_SA_W_PHR: + case OPC_MULSA_W_PH: + gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0); + break; + default: /* Invalid */ + MIPS_INVAL("MASK DPAW.PH"); + generate_exception(ctx, EXCP_RI); + break; + } + break; #if defined(TARGET_MIPS64) case OPC_DEXTM ... OPC_DEXT: case OPC_DINSM ... OPC_DINS: @@ -13764,6 +14203,13 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_ADDUH_R_OB: gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); break; + case OPC_MULEQ_S_PW_QHL: + case OPC_MULEQ_S_PW_QHR: + case OPC_MULEU_S_QH_OBL: + case OPC_MULEU_S_QH_OBR: + case OPC_MULQ_RS_QH: + gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1); + break; default: /* Invalid */ MIPS_INVAL("MASK ADDU.OB"); generate_exception(ctx, EXCP_RI); @@ -13792,6 +14238,45 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) break; } break; + case OPC_DPAQ_W_QH_DSP: + op2 = MASK_DPAQ_W_QH(ctx->opcode); + switch (op2) { + case OPC_DPAU_H_OBL: + case OPC_DPAU_H_OBR: + case OPC_DPSU_H_OBL: + case OPC_DPSU_H_OBR: + case OPC_DPA_W_QH: + case OPC_DPAQ_S_W_QH: + case OPC_DPS_W_QH: + case OPC_DPSQ_S_W_QH: + case OPC_MULSAQ_S_W_QH: + case OPC_DPAQ_SA_L_PW: + case OPC_DPSQ_SA_L_PW: + case OPC_MULSAQ_S_L_PW: + gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0); + break; + case OPC_MAQ_S_W_QHLL: + case OPC_MAQ_S_W_QHLR: + case OPC_MAQ_S_W_QHRL: + case OPC_MAQ_S_W_QHRR: + case OPC_MAQ_SA_W_QHLL: + case OPC_MAQ_SA_W_QHLR: + case OPC_MAQ_SA_W_QHRL: + case OPC_MAQ_SA_W_QHRR: + case OPC_MAQ_S_L_PWL: + case OPC_MAQ_S_L_PWR: + case OPC_DMADD: + case OPC_DMADDU: + case OPC_DMSUB: + case OPC_DMSUBU: + gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0); + break; + default: /* Invalid */ + MIPS_INVAL("MASK DPAQ.W.QH"); + generate_exception(ctx, EXCP_RI); + break; + } + break; case OPC_SHLL_OB_DSP: gen_mipsdsp_shift(ctx, op1, rd, rs, rt); break; From 1cb6686cf926e0efc2056405a0a76dd41eb65d89 Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Wed, 24 Oct 2012 22:17:09 +0800 Subject: [PATCH 1403/2270] target-mips: Add ASE DSP bit/manipulation instructions Add MIPS ASE DSP Bit/Manipulation instructions. Signed-off-by: Jia Liu Signed-off-by: Aurelien Jarno --- target-mips/dsp_helper.c | 55 +++++++++ target-mips/helper.h | 7 ++ target-mips/translate.c | 249 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 311 insertions(+) diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index 86c27ec0e8..919ff299f6 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -3112,6 +3112,61 @@ DM_OPERATE(dmsubu, mul_u32_u32, 0, 0); #undef DM_OPERATE #endif +/** DSP Bit/Manipulation Sub-class insns **/ +target_ulong helper_bitrev(target_ulong rt) +{ + int32_t temp; + uint32_t rd; + int i; + + temp = rt & MIPSDSP_LO; + rd = 0; + for (i = 0; i < 16; i++) { + rd = (rd << 1) | (temp & 1); + temp = temp >> 1; + } + + return (target_ulong)rd; +} + +#define BIT_INSV(name, posfilter, sizefilter, 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; \ + target_ulong dspc; \ + \ + dspc = env->active_tc.DSPControl; \ + \ + pos = dspc & posfilter; \ + size = (dspc >> 7) & sizefilter; \ + \ + msb = pos + size - 1; \ + lsb = pos; \ + \ + if (lsb > msb || (msb > TARGET_LONG_BITS)) { \ + return rt; \ + } \ + \ + filter = ((int32_t)0x01 << size) - 1; \ + filter = filter << pos; \ + temprs = rs & filter; \ + temprt = rt & ~filter; \ + temp = temprs | temprt; \ + \ + return (target_long)(ret_type)temp; \ +} + +BIT_INSV(insv, 0x1F, 0x1F, int32_t); +#ifdef TARGET_MIPS64 +BIT_INSV(dinsv, 0x7F, 0x3F, target_long); +#endif + +#undef BIT_INSV + + #undef MIPSDSP_LHI #undef MIPSDSP_LLO #undef MIPSDSP_HI diff --git a/target-mips/helper.h b/target-mips/helper.h index 139bb1e464..5380adbdb6 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -617,4 +617,11 @@ DEF_HELPER_FLAGS_4(dmsub, 0, void, tl, tl, i32, env) DEF_HELPER_FLAGS_4(dmsubu, 0, void, tl, tl, i32, env) #endif +/* DSP Bit/Manipulation Sub-class insns */ +DEF_HELPER_FLAGS_1(bitrev, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_3(insv, 0, tl, env, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(dinsv, 0, tl, env, tl, tl); +#endif + #include "def-helper.h" diff --git a/target-mips/translate.c b/target-mips/translate.c index 5d374c4c37..0947007c99 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -342,6 +342,11 @@ enum { OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3, #if defined(TARGET_MIPS64) OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3, +#endif + /* DSP Bit/Manipulation Sub-class */ + OPC_INSV_DSP = 0x0C | OPC_SPECIAL3, +#if defined(TARGET_MIPS64) + OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3, #endif }; @@ -450,6 +455,12 @@ enum { OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP, OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP, OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP, + /* DSP Bit/Manipulation Sub-class */ + OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP, + OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP, + OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP, }; #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) @@ -518,6 +529,12 @@ enum { OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP, }; +#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* DSP Bit/Manipulation Sub-class */ + OPC_INSV = (0x00 << 6) | OPC_INSV_DSP, +}; + #if defined(TARGET_MIPS64) #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { @@ -539,6 +556,13 @@ enum { OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP, OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP, OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP, + /* DSP Bit/Manipulation Sub-class */ + OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP, + OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP, + OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP, }; #endif @@ -591,6 +615,14 @@ enum { }; #endif +#if defined(TARGET_MIPS64) +#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* DSP Bit/Manipulation Sub-class */ + OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP, +}; +#endif + #if defined(TARGET_MIPS64) #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { @@ -13604,6 +13636,149 @@ static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2, } +static void gen_mipsdsp_bitinsn(CPUMIPSState *env, DisasContext *ctx, + uint32_t op1, uint32_t op2, + int ret, int val) +{ + const char *opn = "mipsdsp Bit/ Manipulation"; + int16_t imm; + TCGv t0; + TCGv val_t; + + if (ret == 0) { + /* Treat as NOP. */ + MIPS_DEBUG("NOP"); + return; + } + + t0 = tcg_temp_new(); + val_t = tcg_temp_new(); + gen_load_gpr(val_t, val); + + switch (op1) { + case OPC_ABSQ_S_PH_DSP: + switch (op2) { + case OPC_BITREV: + check_dsp(ctx); + gen_helper_bitrev(cpu_gpr[ret], val_t); + break; + case OPC_REPL_QB: + check_dsp(ctx); + { + target_long result; + imm = (ctx->opcode >> 16) & 0xFF; + result = (uint32_t)imm << 24 | + (uint32_t)imm << 16 | + (uint32_t)imm << 8 | + (uint32_t)imm; + result = (int32_t)result; + tcg_gen_movi_tl(cpu_gpr[ret], result); + } + break; + case OPC_REPLV_QB: + check_dsp(ctx); + tcg_gen_ext8u_tl(cpu_gpr[ret], val_t); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 8); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 16); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); + break; + case OPC_REPL_PH: + check_dsp(ctx); + { + imm = (ctx->opcode >> 16) & 0x03FF; + tcg_gen_movi_tl(cpu_gpr[ret], \ + (target_long)((int32_t)imm << 16 | \ + (uint32_t)(uint16_t)imm)); + } + break; + case OPC_REPLV_PH: + check_dsp(ctx); + tcg_gen_ext16u_tl(cpu_gpr[ret], val_t); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 16); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); + break; + } + break; +#ifdef TARGET_MIPS64 + case OPC_ABSQ_S_QH_DSP: + switch (op2) { + case OPC_REPL_OB: + check_dsp(ctx); + { + target_long temp; + + imm = (ctx->opcode >> 16) & 0xFF; + temp = ((uint64_t)imm << 8) | (uint64_t)imm; + temp = (temp << 16) | temp; + temp = (temp << 32) | temp; + tcg_gen_movi_tl(cpu_gpr[ret], temp); + break; + } + case OPC_REPL_PW: + check_dsp(ctx); + { + target_long temp; + + imm = (ctx->opcode >> 16) & 0x03FF; + imm = (int16_t)(imm << 6) >> 6; + temp = ((target_long)imm << 32) \ + | ((target_long)imm & 0xFFFFFFFF); + tcg_gen_movi_tl(cpu_gpr[ret], temp); + break; + } + case OPC_REPL_QH: + check_dsp(ctx); + { + target_long temp; + + imm = (ctx->opcode >> 16) & 0x03FF; + imm = (int16_t)(imm << 6) >> 6; + + temp = ((uint64_t)(uint16_t)imm << 48) | + ((uint64_t)(uint16_t)imm << 32) | + ((uint64_t)(uint16_t)imm << 16) | + (uint64_t)(uint16_t)imm; + tcg_gen_movi_tl(cpu_gpr[ret], temp); + break; + } + case OPC_REPLV_OB: + check_dsp(ctx); + tcg_gen_ext8u_tl(cpu_gpr[ret], val_t); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 8); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 16); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 32); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + break; + case OPC_REPLV_PW: + check_dsp(ctx); + tcg_gen_ext32u_i64(cpu_gpr[ret], val_t); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 32); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + break; + case OPC_REPLV_QH: + check_dsp(ctx); + tcg_gen_ext16u_tl(cpu_gpr[ret], val_t); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 16); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + tcg_gen_shli_tl(t0, cpu_gpr[ret], 32); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + break; + } + break; +#endif + } + tcg_temp_free(t0); + tcg_temp_free(val_t); + + (void)opn; /* avoid a compiler warning */ + MIPS_DEBUG("%s", opn); +} + /* End MIPSDSP functions. */ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) @@ -14030,6 +14205,13 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_PRECEU_PH_QBRA: gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); break; + case OPC_BITREV: + case OPC_REPL_QB: + case OPC_REPLV_QB: + case OPC_REPL_PH: + case OPC_REPLV_PH: + gen_mipsdsp_bitinsn(env, ctx, op1, op2, rd, rt); + break; default: MIPS_INVAL("MASK ABSQ_S.PH"); generate_exception(ctx, EXCP_RI); @@ -14130,6 +14312,37 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) break; } break; + case OPC_INSV_DSP: + op2 = MASK_INSV(ctx->opcode); + switch (op2) { + case OPC_INSV: + check_dsp(ctx); + { + TCGv t0, t1; + + if (rt == 0) { + MIPS_DEBUG("NOP"); + break; + } + + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + + gen_load_gpr(t0, rt); + gen_load_gpr(t1, rs); + + gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0); + + tcg_temp_free(t0); + tcg_temp_free(t1); + break; + } + default: /* Invalid */ + MIPS_INVAL("MASK INSV"); + generate_exception(ctx, EXCP_RI); + break; + } + break; #if defined(TARGET_MIPS64) case OPC_DEXTM ... OPC_DEXT: case OPC_DINSM ... OPC_DINS: @@ -14171,6 +14384,14 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_ABSQ_S_QH: gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); break; + case OPC_REPL_OB: + case OPC_REPL_PW: + case OPC_REPL_QH: + case OPC_REPLV_OB: + case OPC_REPLV_PW: + case OPC_REPLV_QH: + gen_mipsdsp_bitinsn(env, ctx, op1, op2, rd, rt); + break; default: /* Invalid */ MIPS_INVAL("MASK ABSQ_S.QH"); generate_exception(ctx, EXCP_RI); @@ -14277,6 +14498,34 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) break; } break; + case OPC_DINSV_DSP: + op2 = MASK_INSV(ctx->opcode); + switch (op2) { + case OPC_DINSV: + { + TCGv t0, t1; + + if (rt == 0) { + MIPS_DEBUG("NOP"); + break; + } + check_dsp(ctx); + + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + + gen_load_gpr(t0, rt); + gen_load_gpr(t1, rs); + + gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0); + break; + } + default: /* Invalid */ + MIPS_INVAL("MASK DINSV"); + generate_exception(ctx, EXCP_RI); + break; + } + break; case OPC_SHLL_OB_DSP: gen_mipsdsp_shift(ctx, op1, rd, rs, rt); break; From 266905602401e4aa849372bc50a71b2987157727 Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Wed, 24 Oct 2012 22:17:10 +0800 Subject: [PATCH 1404/2270] target-mips: Add ASE DSP compare-pick instructions Add MIPS ASE DSP Compare-Pick instructions. Signed-off-by: Jia Liu Signed-off-by: Aurelien Jarno --- target-mips/dsp_helper.c | 233 ++++++++++++++++++++++++++ target-mips/helper.h | 52 ++++++ target-mips/translate.c | 350 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 635 insertions(+) diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index 919ff299f6..fcdc1bbcb9 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -3167,6 +3167,239 @@ BIT_INSV(dinsv, 0x7F, 0x3F, target_long); #undef BIT_INSV +/** DSP Compare-Pick Sub-class insns **/ +#define CMP_HAS_RET(name, func, split_num, filter, bit_size) \ +target_ulong helper_##name(target_ulong rs, target_ulong rt) \ +{ \ + uint32_t rs_t, rt_t; \ + uint8_t cc; \ + uint32_t temp = 0; \ + int i; \ + \ + for (i = 0; i < split_num; i++) { \ + rs_t = (rs >> (bit_size * i)) & filter; \ + rt_t = (rt >> (bit_size * i)) & filter; \ + cc = mipsdsp_##func(rs_t, rt_t); \ + temp |= cc << i; \ + } \ + \ + return (target_ulong)temp; \ +} + +CMP_HAS_RET(cmpgu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8); +CMP_HAS_RET(cmpgu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8); +CMP_HAS_RET(cmpgu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8); + +#ifdef TARGET_MIPS64 +CMP_HAS_RET(cmpgu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8); +CMP_HAS_RET(cmpgu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8); +CMP_HAS_RET(cmpgu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8); +#endif + +#undef CMP_HAS_RET + + +#define CMP_NO_RET(name, func, split_num, filter, bit_size) \ +void helper_##name(target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + int##bit_size##_t rs_t, rt_t; \ + int##bit_size##_t flag = 0; \ + int##bit_size##_t cc; \ + int i; \ + \ + for (i = 0; i < split_num; i++) { \ + rs_t = (rs >> (bit_size * i)) & filter; \ + rt_t = (rt >> (bit_size * i)) & filter; \ + \ + cc = mipsdsp_##func((int32_t)rs_t, (int32_t)rt_t); \ + flag |= cc << i; \ + } \ + \ + set_DSPControl_24(flag, split_num, env); \ +} + +CMP_NO_RET(cmpu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8); +CMP_NO_RET(cmpu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8); +CMP_NO_RET(cmpu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8); + +CMP_NO_RET(cmp_eq_ph, cmp_eq, 2, MIPSDSP_LO, 16); +CMP_NO_RET(cmp_lt_ph, cmp_lt, 2, MIPSDSP_LO, 16); +CMP_NO_RET(cmp_le_ph, cmp_le, 2, MIPSDSP_LO, 16); + +#ifdef TARGET_MIPS64 +CMP_NO_RET(cmpu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8); +CMP_NO_RET(cmpu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8); +CMP_NO_RET(cmpu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8); + +CMP_NO_RET(cmp_eq_qh, cmp_eq, 4, MIPSDSP_LO, 16); +CMP_NO_RET(cmp_lt_qh, cmp_lt, 4, MIPSDSP_LO, 16); +CMP_NO_RET(cmp_le_qh, cmp_le, 4, MIPSDSP_LO, 16); + +CMP_NO_RET(cmp_eq_pw, cmp_eq, 2, MIPSDSP_LLO, 32); +CMP_NO_RET(cmp_lt_pw, cmp_lt, 2, MIPSDSP_LLO, 32); +CMP_NO_RET(cmp_le_pw, cmp_le, 2, MIPSDSP_LLO, 32); +#endif +#undef CMP_NO_RET + +#if defined(TARGET_MIPS64) + +#define CMPGDU_OB(name) \ +target_ulong helper_cmpgdu_##name##_ob(target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + int i; \ + uint8_t rs_t, rt_t; \ + uint32_t cond; \ + \ + cond = 0; \ + \ + for (i = 0; i < 8; i++) { \ + rs_t = (rs >> (8 * i)) & MIPSDSP_Q0; \ + rt_t = (rt >> (8 * i)) & MIPSDSP_Q0; \ + \ + if (mipsdsp_cmpu_##name(rs_t, rt_t)) { \ + cond |= 0x01 << i; \ + } \ + } \ + \ + set_DSPControl_24(cond, 8, env); \ + \ + return (uint64_t)cond; \ +} + +CMPGDU_OB(eq) +CMPGDU_OB(lt) +CMPGDU_OB(le) +#undef CMPGDU_OB +#endif + +#define PICK_INSN(name, split_num, filter, bit_size, ret32bit) \ +target_ulong helper_##name(target_ulong rs, target_ulong rt, \ + CPUMIPSState *env) \ +{ \ + uint32_t rs_t, rt_t; \ + uint32_t cc; \ + target_ulong dsp; \ + int i; \ + target_ulong result = 0; \ + \ + dsp = env->active_tc.DSPControl; \ + for (i = 0; i < split_num; i++) { \ + rs_t = (rs >> (bit_size * i)) & filter; \ + rt_t = (rt >> (bit_size * i)) & filter; \ + cc = (dsp >> (24 + i)) & 0x01; \ + cc = cc == 1 ? rs_t : rt_t; \ + \ + result |= (target_ulong)cc << (bit_size * i); \ + } \ + \ + if (ret32bit) { \ + result = (target_long)(int32_t)(result & MIPSDSP_LLO); \ + } \ + \ + return result; \ +} + +PICK_INSN(pick_qb, 4, MIPSDSP_Q0, 8, 1); +PICK_INSN(pick_ph, 2, MIPSDSP_LO, 16, 1); + +#ifdef TARGET_MIPS64 +PICK_INSN(pick_ob, 8, MIPSDSP_Q0, 8, 0); +PICK_INSN(pick_qh, 4, MIPSDSP_LO, 16, 0); +PICK_INSN(pick_pw, 2, MIPSDSP_LLO, 32, 0); +#endif +#undef PICK_INSN + +#define APPEND_INSN(name, ret_32) \ +target_ulong helper_##name(target_ulong rt, target_ulong rs, uint32_t sa) \ +{ \ + target_ulong temp; \ + \ + if (ret_32) { \ + temp = ((rt & MIPSDSP_LLO) << sa) | \ + ((rs & MIPSDSP_LLO) & ((0x01 << sa) - 1)); \ + temp = (target_long)(int32_t)(temp & MIPSDSP_LLO); \ + } else { \ + temp = (rt << sa) | (rs & ((0x01 << sa) - 1)); \ + } \ + \ + return temp; \ +} + +APPEND_INSN(append, 1); +#ifdef TARGET_MIPS64 +APPEND_INSN(dappend, 0); +#endif +#undef APPEND_INSN + +#define PREPEND_INSN(name, or_val, ret_32) \ +target_ulong helper_##name(target_ulong rs, target_ulong rt, \ + uint32_t sa) \ +{ \ + sa |= or_val; \ + \ + if (1) { \ + return (target_long)(int32_t)(uint32_t) \ + (((rs & MIPSDSP_LLO) << (32 - sa)) | \ + ((rt & MIPSDSP_LLO) >> sa)); \ + } else { \ + return (rs << (64 - sa)) | (rt >> sa); \ + } \ +} + +PREPEND_INSN(prepend, 0, 1); +#ifdef TARGET_MIPS64 +PREPEND_INSN(prependw, 0, 0); +PREPEND_INSN(prependd, 0x20, 0); +#endif +#undef PREPEND_INSN + +#define BALIGN_INSN(name, filter, ret32) \ +target_ulong helper_##name(target_ulong rs, target_ulong rt, uint32_t bp) \ +{ \ + bp = bp & 0x03; \ + \ + if ((bp & 1) == 0) { \ + return rt; \ + } else { \ + if (ret32) { \ + return (target_long)(int32_t)((rt << (8 * bp)) | \ + (rs >> (8 * (4 - bp)))); \ + } else { \ + return (rt << (8 * bp)) | (rs >> (8 * (8 - bp))); \ + } \ + } \ +} + +BALIGN_INSN(balign, 0x03, 1); +#if defined(TARGET_MIPS64) +BALIGN_INSN(dbalign, 0x07, 0); +#endif +#undef BALIGN_INSN + +target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt) +{ + uint32_t rsl, rth; + + rsl = rs & MIPSDSP_LO; + rth = (rt & MIPSDSP_HI) >> 16; + + return (target_long)(int32_t)((rsl << 16) | rth); +} + +#if defined(TARGET_MIPS64) +target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt) +{ + uint32_t rs0, rt1; + + rs0 = rs & MIPSDSP_LLO; + rt1 = (rt >> 32) & MIPSDSP_LLO; + + return ((uint64_t)rs0 << 32) | (uint64_t)rt1; +} +#endif + #undef MIPSDSP_LHI #undef MIPSDSP_LLO #undef MIPSDSP_HI diff --git a/target-mips/helper.h b/target-mips/helper.h index 5380adbdb6..a821326b26 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -624,4 +624,56 @@ DEF_HELPER_FLAGS_3(insv, 0, tl, env, tl, tl) DEF_HELPER_FLAGS_3(dinsv, 0, tl, env, tl, tl); #endif +/* DSP Compare-Pick Sub-class insns */ +DEF_HELPER_FLAGS_3(cmpu_eq_qb, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmpu_lt_qb, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmpu_le_qb, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_2(cmpgu_eq_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(cmpgu_lt_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(cmpgu_le_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(cmp_eq_ph, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmp_lt_ph, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmp_le_ph, 0, void, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(cmpu_eq_ob, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmpu_lt_ob, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmpu_le_ob, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmpgdu_eq_ob, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(cmpgdu_lt_ob, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(cmpgdu_le_ob, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_2(cmpgu_eq_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(cmpgu_lt_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(cmpgu_le_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_3(cmp_eq_qh, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmp_lt_qh, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmp_le_qh, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmp_eq_pw, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmp_lt_pw, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_3(cmp_le_pw, 0, void, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(pick_qb, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(pick_ph, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(pick_ob, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(pick_qh, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(pick_pw, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(append, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(dappend, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32) +#endif +DEF_HELPER_FLAGS_3(prepend, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(prependd, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32) +DEF_HELPER_FLAGS_3(prependw, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32) +#endif +DEF_HELPER_FLAGS_3(balign, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(dbalign, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32) +#endif +DEF_HELPER_FLAGS_2(packrl_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_2(packrl_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl) +#endif + #include "def-helper.h" diff --git a/target-mips/translate.c b/target-mips/translate.c index 0947007c99..69ef90a5aa 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -347,6 +347,11 @@ enum { OPC_INSV_DSP = 0x0C | OPC_SPECIAL3, #if defined(TARGET_MIPS64) OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3, +#endif + /* MIPS DSP Compare-Pick Sub-class */ + OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3, +#if defined(TARGET_MIPS64) + OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3, #endif }; @@ -473,6 +478,22 @@ enum { OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP, OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP, OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP, + /* DSP Compare-Pick Sub-class */ + OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP, + OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP, }; #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) @@ -535,6 +556,14 @@ enum { OPC_INSV = (0x00 << 6) | OPC_INSV_DSP, }; +#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Compare-Pick Sub-class */ + OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP, + OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP, + OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP, +}; + #if defined(TARGET_MIPS64) #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { @@ -603,6 +632,26 @@ enum { #if defined(TARGET_MIPS64) #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { + /* DSP Compare-Pick Sub-class */ + OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP, + OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP, /* MIPS DSP Arithmetic Sub-class */ OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP, OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP, @@ -615,6 +664,17 @@ enum { }; #endif +#if defined(TARGET_MIPS64) +#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* DSP Compare-Pick Sub-class */ + OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP, + OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP, + OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP, + OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP, +}; +#endif + #if defined(TARGET_MIPS64) #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { @@ -13779,6 +13839,244 @@ static void gen_mipsdsp_bitinsn(CPUMIPSState *env, DisasContext *ctx, MIPS_DEBUG("%s", opn); } +static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx, + uint32_t op1, uint32_t op2, + int ret, int v1, int v2, int check_ret) +{ + const char *opn = "mipsdsp add compare pick"; + TCGv_i32 t0; + TCGv t1; + TCGv v1_t; + TCGv v2_t; + + if ((ret == 0) && (check_ret == 1)) { + /* Treat as NOP. */ + MIPS_DEBUG("NOP"); + return; + } + + t0 = tcg_temp_new_i32(); + t1 = tcg_temp_new(); + v1_t = tcg_temp_new(); + v2_t = tcg_temp_new(); + + gen_load_gpr(v1_t, v1); + gen_load_gpr(v2_t, v2); + + switch (op1) { + case OPC_APPEND_DSP: + switch (op2) { + case OPC_APPEND: + tcg_gen_movi_i32(t0, v2); + gen_helper_append(cpu_gpr[ret], cpu_gpr[ret], v1_t, t0); + break; + case OPC_PREPEND: + tcg_gen_movi_i32(t0, v2); + gen_helper_prepend(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0); + break; + case OPC_BALIGN: + tcg_gen_movi_i32(t0, v2); + gen_helper_balign(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0); + break; + default: /* Invid */ + MIPS_INVAL("MASK APPEND"); + generate_exception(ctx, EXCP_RI); + break; + } + break; + case OPC_CMPU_EQ_QB_DSP: + switch (op2) { + case OPC_CMPU_EQ_QB: + check_dsp(ctx); + gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env); + break; + case OPC_CMPU_LT_QB: + check_dsp(ctx); + gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env); + break; + case OPC_CMPU_LE_QB: + check_dsp(ctx); + gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env); + break; + case OPC_CMPGU_EQ_QB: + check_dsp(ctx); + gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_CMPGU_LT_QB: + check_dsp(ctx); + gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_CMPGU_LE_QB: + check_dsp(ctx); + gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_CMPGDU_EQ_QB: + check_dspr2(ctx); + gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t); + tcg_gen_mov_tl(cpu_gpr[ret], t1); + tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF); + tcg_gen_shli_tl(t1, t1, 24); + tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1); + break; + case OPC_CMPGDU_LT_QB: + check_dspr2(ctx); + gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t); + tcg_gen_mov_tl(cpu_gpr[ret], t1); + tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF); + tcg_gen_shli_tl(t1, t1, 24); + tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1); + break; + case OPC_CMPGDU_LE_QB: + check_dspr2(ctx); + gen_helper_cmpgu_le_qb(t1, v1_t, v2_t); + tcg_gen_mov_tl(cpu_gpr[ret], t1); + tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF); + tcg_gen_shli_tl(t1, t1, 24); + tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1); + break; + case OPC_CMP_EQ_PH: + check_dsp(ctx); + gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env); + break; + case OPC_CMP_LT_PH: + check_dsp(ctx); + gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env); + break; + case OPC_CMP_LE_PH: + check_dsp(ctx); + gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env); + break; + case OPC_PICK_QB: + check_dsp(ctx); + gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_PICK_PH: + check_dsp(ctx); + gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_PACKRL_PH: + check_dsp(ctx); + gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t); + break; + } + break; +#ifdef TARGET_MIPS64 + case OPC_CMPU_EQ_OB_DSP: + switch (op2) { + case OPC_CMP_EQ_PW: + check_dsp(ctx); + gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env); + break; + case OPC_CMP_LT_PW: + check_dsp(ctx); + gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env); + break; + case OPC_CMP_LE_PW: + check_dsp(ctx); + gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env); + break; + case OPC_CMP_EQ_QH: + check_dsp(ctx); + gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env); + break; + case OPC_CMP_LT_QH: + check_dsp(ctx); + gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env); + break; + case OPC_CMP_LE_QH: + check_dsp(ctx); + gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env); + break; + case OPC_CMPGDU_EQ_OB: + check_dspr2(ctx); + gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_CMPGDU_LT_OB: + check_dspr2(ctx); + gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_CMPGDU_LE_OB: + check_dspr2(ctx); + gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_CMPGU_EQ_OB: + check_dsp(ctx); + gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_CMPGU_LT_OB: + check_dsp(ctx); + gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_CMPGU_LE_OB: + check_dsp(ctx); + gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_CMPU_EQ_OB: + check_dsp(ctx); + gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env); + break; + case OPC_CMPU_LT_OB: + check_dsp(ctx); + gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env); + break; + case OPC_CMPU_LE_OB: + check_dsp(ctx); + gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env); + break; + case OPC_PACKRL_PW: + check_dsp(ctx); + gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t); + break; + case OPC_PICK_OB: + check_dsp(ctx); + gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_PICK_PW: + check_dsp(ctx); + gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + case OPC_PICK_QH: + check_dsp(ctx); + gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env); + break; + } + break; + case OPC_DAPPEND_DSP: + switch (op2) { + case OPC_DAPPEND: + tcg_gen_movi_i32(t0, v2); + gen_helper_dappend(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0); + break; + case OPC_PREPENDD: + tcg_gen_movi_i32(t0, v2); + gen_helper_prependd(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0); + break; + case OPC_PREPENDW: + tcg_gen_movi_i32(t0, v2); + gen_helper_prependw(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0); + break; + case OPC_DBALIGN: + tcg_gen_movi_i32(t0, v2); + gen_helper_dbalign(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0); + break; + default: /* Invalid */ + MIPS_INVAL("MASK DAPPEND"); + generate_exception(ctx, EXCP_RI); + break; + } + break; +#endif + } + + tcg_temp_free_i32(t0); + tcg_temp_free(t1); + tcg_temp_free(v1_t); + tcg_temp_free(v2_t); + + (void)opn; /* avoid a compiler warning */ + MIPS_DEBUG("%s", opn); +} + /* End MIPSDSP functions. */ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) @@ -14270,6 +14568,25 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_PRECRQU_S_QB_PH: gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); break; + case OPC_CMPU_EQ_QB: + case OPC_CMPU_LT_QB: + case OPC_CMPU_LE_QB: + case OPC_CMP_EQ_PH: + case OPC_CMP_LT_PH: + case OPC_CMP_LE_PH: + gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0); + break; + case OPC_CMPGU_EQ_QB: + case OPC_CMPGU_LT_QB: + case OPC_CMPGU_LE_QB: + case OPC_CMPGDU_EQ_QB: + case OPC_CMPGDU_LT_QB: + case OPC_CMPGDU_LE_QB: + case OPC_PICK_QB: + case OPC_PICK_PH: + case OPC_PACKRL_PH: + gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1); + break; default: /* Invalid */ MIPS_INVAL("MASK CMPU.EQ.QB"); generate_exception(ctx, EXCP_RI); @@ -14343,6 +14660,11 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) break; } break; + case OPC_APPEND_DSP: + check_dspr2(ctx); + op2 = MASK_APPEND(ctx->opcode); + gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1); + break; #if defined(TARGET_MIPS64) case OPC_DEXTM ... OPC_DEXT: case OPC_DINSM ... OPC_DINS: @@ -14453,12 +14775,40 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_PRECRQU_S_OB_QH: gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt); break; + case OPC_CMPU_EQ_OB: + case OPC_CMPU_LT_OB: + case OPC_CMPU_LE_OB: + case OPC_CMP_EQ_QH: + case OPC_CMP_LT_QH: + case OPC_CMP_LE_QH: + case OPC_CMP_EQ_PW: + case OPC_CMP_LT_PW: + case OPC_CMP_LE_PW: + gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0); + break; + case OPC_CMPGDU_EQ_OB: + case OPC_CMPGDU_LT_OB: + case OPC_CMPGDU_LE_OB: + case OPC_CMPGU_EQ_OB: + case OPC_CMPGU_LT_OB: + case OPC_CMPGU_LE_OB: + case OPC_PACKRL_PW: + case OPC_PICK_OB: + case OPC_PICK_PW: + case OPC_PICK_QH: + gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1); + break; default: /* Invalid */ MIPS_INVAL("MASK CMPU_EQ.OB"); generate_exception(ctx, EXCP_RI); break; } break; + case OPC_DAPPEND_DSP: + check_dspr2(ctx); + op2 = MASK_DAPPEND(ctx->opcode); + gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1); + break; case OPC_DPAQ_W_QH_DSP: op2 = MASK_DPAQ_W_QH(ctx->opcode); switch (op2) { From b53371ed5d4b6a678bf524d381f80746739b7fc0 Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Wed, 24 Oct 2012 22:17:11 +0800 Subject: [PATCH 1405/2270] target-mips: Add ASE DSP accumulator instructions Add MIPS ASE DSP Accumulator and DSPControl Access instructions. Signed-off-by: Jia Liu Signed-off-by: Aurelien Jarno --- target-mips/dsp_helper.c | 609 +++++++++++++++++++++++++++++++++++++++ target-mips/helper.h | 35 +++ target-mips/translate.c | 351 ++++++++++++++++++++++ 3 files changed, 995 insertions(+) diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index fcdc1bbcb9..b59133ea8f 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -3400,6 +3400,615 @@ target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt) } #endif +/** DSP Accumulator and DSPControl Access Sub-class insns **/ +target_ulong helper_extr_w(target_ulong ac, target_ulong shift, + CPUMIPSState *env) +{ + int32_t tempI; + int64_t tempDL[2]; + + shift = shift & 0x0F; + + mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env); + if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && + (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { + set_DSPControl_overflow_flag(1, 23, env); + } + + tempI = (tempDL[0] >> 1) & MIPSDSP_LLO; + + tempDL[0] += 1; + if (tempDL[0] == 0) { + tempDL[1] += 1; + } + + if ((!(tempDL[1] == 0 && (tempDL[0] & MIPSDSP_LHI) == 0x00)) && + (!(tempDL[1] == 1 && (tempDL[0] & MIPSDSP_LHI) == MIPSDSP_LHI))) { + set_DSPControl_overflow_flag(1, 23, env); + } + + return (target_long)tempI; +} + +target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift, + CPUMIPSState *env) +{ + int64_t tempDL[2]; + + shift = shift & 0x0F; + + mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env); + if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && + (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { + set_DSPControl_overflow_flag(1, 23, env); + } + + tempDL[0] += 1; + if (tempDL[0] == 0) { + tempDL[1] += 1; + } + + if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && + (tempDL[1] != 1 && (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { + set_DSPControl_overflow_flag(1, 23, env); + } + + return (target_long)(int32_t)(tempDL[0] >> 1); +} + +target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift, + CPUMIPSState *env) +{ + int32_t tempI, temp64; + int64_t tempDL[2]; + + shift = shift & 0x0F; + + mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env); + if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && + (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { + set_DSPControl_overflow_flag(1, 23, env); + } + tempDL[0] += 1; + if (tempDL[0] == 0) { + tempDL[1] += 1; + } + tempI = tempDL[0] >> 1; + + if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && + (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { + temp64 = tempDL[1]; + if (temp64 == 0) { + tempI = 0x7FFFFFFF; + } else { + tempI = 0x80000000; + } + set_DSPControl_overflow_flag(1, 23, env); + } + + return (target_long)tempI; +} + +#if defined(TARGET_MIPS64) +target_ulong helper_dextr_w(target_ulong ac, target_ulong shift, + CPUMIPSState *env) +{ + uint64_t temp[3]; + + shift = shift & 0x3F; + + mipsdsp_rndrashift_acc(temp, ac, shift, env); + + return (int64_t)(int32_t)(temp[0] >> 1); +} + +target_ulong helper_dextr_r_w(target_ulong ac, target_ulong shift, + CPUMIPSState *env) +{ + uint64_t temp[3]; + uint32_t temp128; + + shift = shift & 0x3F; + mipsdsp_rndrashift_acc(temp, ac, shift, env); + + temp[0] += 1; + if (temp[0] == 0) { + temp[1] += 1; + if (temp[1] == 0) { + temp[2] += 1; + } + } + + temp128 = temp[2] & 0x01; + + if ((temp128 != 0 || temp[1] != 0) && + (temp128 != 1 || temp[1] != ~0ull)) { + set_DSPControl_overflow_flag(1, 23, env); + } + + return (int64_t)(int32_t)(temp[0] >> 1); +} + +target_ulong helper_dextr_rs_w(target_ulong ac, target_ulong shift, + CPUMIPSState *env) +{ + uint64_t temp[3]; + uint32_t temp128; + + shift = shift & 0x3F; + mipsdsp_rndrashift_acc(temp, ac, shift, env); + + temp[0] += 1; + if (temp[0] == 0) { + temp[1] += 1; + if (temp[1] == 0) { + temp[2] += 1; + } + } + + temp128 = temp[2] & 0x01; + + if ((temp128 != 0 || temp[1] != 0) && + (temp128 != 1 || temp[1] != ~0ull)) { + if (temp128 == 0) { + temp[0] = 0x0FFFFFFFF; + } else { + temp[0] = 0x0100000000; + } + set_DSPControl_overflow_flag(1, 23, env); + } + + return (int64_t)(int32_t)(temp[0] >> 1); +} + +target_ulong helper_dextr_l(target_ulong ac, target_ulong shift, + CPUMIPSState *env) +{ + uint64_t temp[3]; + target_ulong result; + + shift = shift & 0x3F; + + mipsdsp_rndrashift_acc(temp, ac, shift, env); + result = (temp[1] << 63) | (temp[0] >> 1); + + return result; +} + +target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift, + CPUMIPSState *env) +{ + uint64_t temp[3]; + uint32_t temp128; + target_ulong result; + + shift = shift & 0x3F; + mipsdsp_rndrashift_acc(temp, ac, shift, env); + + temp[0] += 1; + if (temp[0] == 0) { + temp[1] += 1; + if (temp[1] == 0) { + temp[2] += 1; + } + } + + temp128 = temp[2] & 0x01; + + if ((temp128 != 0 || temp[1] != 0) && + (temp128 != 1 || temp[1] != ~0ull)) { + set_DSPControl_overflow_flag(1, 23, env); + } + + result = (temp[1] << 63) | (temp[0] >> 1); + + return result; +} + +target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift, + CPUMIPSState *env) +{ + uint64_t temp[3]; + uint32_t temp128; + target_ulong result; + + shift = shift & 0x3F; + mipsdsp_rndrashift_acc(temp, ac, shift, env); + + temp[0] += 1; + if (temp[0] == 0) { + temp[1] += 1; + if (temp[1] == 0) { + temp[2] += 1; + } + } + + temp128 = temp[2] & 0x01; + + if ((temp128 != 0 || temp[1] != 0) && + (temp128 != 1 || temp[1] != ~0ull)) { + if (temp128 == 0) { + temp[1] &= ~0x00ull - 1; + temp[0] |= ~0x00ull - 1; + } else { + temp[1] |= 0x01; + temp[0] &= 0x01; + } + set_DSPControl_overflow_flag(1, 23, env); + } + result = (temp[1] << 63) | (temp[0] >> 1); + + return result; +} +#endif + +target_ulong helper_extr_s_h(target_ulong ac, target_ulong shift, + CPUMIPSState *env) +{ + int64_t temp; + + shift = shift & 0x0F; + + temp = mipsdsp_rashift_short_acc(ac, shift, env); + if (temp > (int64_t)0x7FFF) { + temp = 0x00007FFF; + set_DSPControl_overflow_flag(1, 23, env); + } else if (temp < (int64_t)0xFFFFFFFFFFFF8000) { + temp = 0xFFFF8000; + set_DSPControl_overflow_flag(1, 23, env); + } + + return (target_long)(int32_t)(temp & 0xFFFFFFFF); +} + + +#if defined(TARGET_MIPS64) +target_ulong helper_dextr_s_h(target_ulong ac, target_ulong shift, + CPUMIPSState *env) +{ + int64_t temp[2]; + uint32_t temp127; + + shift = shift & 0x1F; + + mipsdsp_rashift_acc((uint64_t *)temp, ac, shift, env); + + temp127 = (temp[1] >> 63) & 0x01; + + if ((temp127 == 0) && (temp[1] > 0 || temp[0] > 32767)) { + temp[0] &= 0xFFFF0000; + temp[0] |= 0x00007FFF; + set_DSPControl_overflow_flag(1, 23, env); + } else if ((temp127 == 1) && + (temp[1] < 0xFFFFFFFFFFFFFFFFll + || temp[0] < 0xFFFFFFFFFFFF1000ll)) { + temp[0] &= 0xFFFF0000; + temp[0] |= 0x00008000; + set_DSPControl_overflow_flag(1, 23, env); + } + + return (int64_t)(int16_t)(temp[0] & MIPSDSP_LO); +} + +#endif + +target_ulong helper_extp(target_ulong ac, target_ulong size, CPUMIPSState *env) +{ + int32_t start_pos; + int sub; + uint32_t temp; + uint64_t acc; + + size = size & 0x1F; + + temp = 0; + start_pos = get_DSPControl_pos(env); + sub = start_pos - (size + 1); + if (sub >= -1) { + acc = ((uint64_t)env->active_tc.HI[ac] << 32) | + ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); + temp = (acc >> (start_pos - size)) & + (((uint32_t)0x01 << (size + 1)) - 1); + set_DSPControl_efi(0, env); + } else { + set_DSPControl_efi(1, env); + } + + return (target_ulong)temp; +} + +target_ulong helper_extpdp(target_ulong ac, target_ulong size, + CPUMIPSState *env) +{ + int32_t start_pos; + int sub; + uint32_t temp; + uint64_t acc; + + size = size & 0x1F; + temp = 0; + start_pos = get_DSPControl_pos(env); + sub = start_pos - (size + 1); + if (sub >= -1) { + acc = ((uint64_t)env->active_tc.HI[ac] << 32) | + ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); + temp = (acc >> (start_pos - size)) & + (((uint32_t)0x01 << (size + 1)) - 1); + + set_DSPControl_pos(start_pos - (size + 1), env); + set_DSPControl_efi(0, env); + } else { + set_DSPControl_efi(1, env); + } + + return (target_ulong)temp; +} + + +#if defined(TARGET_MIPS64) +target_ulong helper_dextp(target_ulong ac, target_ulong size, CPUMIPSState *env) +{ + int start_pos; + int len; + int sub; + uint64_t tempB, tempA; + uint64_t temp; + + temp = 0; + + size = size & 0x3F; + start_pos = get_DSPControl_pos(env); + len = start_pos - size; + tempB = env->active_tc.HI[ac]; + tempA = env->active_tc.LO[ac]; + + sub = start_pos - (size + 1); + + if (sub >= -1) { + temp = (tempB << (64 - len)) | (tempA >> len); + temp = temp & ((0x01 << (size + 1)) - 1); + set_DSPControl_efi(0, env); + } else { + set_DSPControl_efi(1, env); + } + + return temp; +} + +target_ulong helper_dextpdp(target_ulong ac, target_ulong size, + CPUMIPSState *env) +{ + int start_pos; + int len; + int sub; + uint64_t tempB, tempA; + uint64_t temp; + + temp = 0; + size = size & 0x3F; + start_pos = get_DSPControl_pos(env); + len = start_pos - size; + tempB = env->active_tc.HI[ac]; + tempA = env->active_tc.LO[ac]; + + sub = start_pos - (size + 1); + + if (sub >= -1) { + temp = (tempB << (64 - len)) | (tempA >> len); + temp = temp & ((0x01 << (size + 1)) - 1); + set_DSPControl_pos(sub, env); + set_DSPControl_efi(0, env); + } else { + set_DSPControl_efi(1, env); + } + + return temp; +} + +#endif + +void helper_shilo(target_ulong ac, target_ulong rs, CPUMIPSState *env) +{ + int8_t rs5_0; + uint64_t temp, acc; + + rs5_0 = rs & 0x3F; + rs5_0 = (int8_t)(rs5_0 << 2) >> 2; + rs5_0 = MIPSDSP_ABS(rs5_0); + acc = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) | + ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); + if (rs5_0 == 0) { + temp = acc; + } else { + if (rs5_0 > 0) { + temp = acc >> rs5_0; + } else { + temp = acc << rs5_0; + } + } + + env->active_tc.HI[ac] = (target_ulong)(int32_t)((temp & MIPSDSP_LHI) >> 32); + env->active_tc.LO[ac] = (target_ulong)(int32_t)(temp & MIPSDSP_LLO); +} + +#if defined(TARGET_MIPS64) +void helper_dshilo(target_ulong shift, target_ulong ac, CPUMIPSState *env) +{ + int8_t shift_t; + uint64_t tempB, tempA; + + shift_t = (int8_t)(shift << 1) >> 1; + + tempB = env->active_tc.HI[ac]; + tempA = env->active_tc.LO[ac]; + + if (shift_t != 0) { + if (shift_t >= 0) { + tempA = (tempB << (64 - shift_t)) | (tempA >> shift_t); + tempB = tempB >> shift_t; + } else { + shift_t = -shift_t; + tempB = (tempB << shift_t) | (tempA >> (64 - shift_t)); + tempA = tempA << shift_t; + } + } + + env->active_tc.HI[ac] = tempB; + env->active_tc.LO[ac] = tempA; +} + +#endif +void helper_mthlip(target_ulong ac, target_ulong rs, CPUMIPSState *env) +{ + int32_t tempA, tempB, pos; + + tempA = rs; + tempB = env->active_tc.LO[ac]; + env->active_tc.HI[ac] = (target_long)tempB; + env->active_tc.LO[ac] = (target_long)tempA; + pos = get_DSPControl_pos(env); + + if (pos > 32) { + return; + } else { + set_DSPControl_pos(pos + 32, env); + } +} + +#if defined(TARGET_MIPS64) +void helper_dmthlip(target_ulong rs, target_ulong ac, CPUMIPSState *env) +{ + uint8_t ac_t; + uint8_t pos; + uint64_t tempB, tempA; + + ac_t = ac & 0x3; + + tempA = rs; + tempB = env->active_tc.LO[ac_t]; + + env->active_tc.HI[ac_t] = tempB; + env->active_tc.LO[ac_t] = tempA; + + pos = get_DSPControl_pos(env); + + if (pos <= 64) { + pos = pos + 64; + set_DSPControl_pos(pos, env); + } +} +#endif + +void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env) +{ + uint8_t mask[6]; + uint8_t i; + uint32_t newbits, overwrite; + target_ulong dsp; + + newbits = 0x00; + overwrite = 0xFFFFFFFF; + dsp = env->active_tc.DSPControl; + + for (i = 0; i < 6; i++) { + mask[i] = (mask_num >> i) & 0x01; + } + + if (mask[0] == 1) { +#if defined(TARGET_MIPS64) + overwrite &= 0xFFFFFF80; + newbits &= 0xFFFFFF80; + newbits |= 0x0000007F & rs; +#else + overwrite &= 0xFFFFFFC0; + newbits &= 0xFFFFFFC0; + newbits |= 0x0000003F & rs; +#endif + } + + if (mask[1] == 1) { + overwrite &= 0xFFFFE07F; + newbits &= 0xFFFFE07F; + newbits |= 0x00001F80 & rs; + } + + if (mask[2] == 1) { + overwrite &= 0xFFFFDFFF; + newbits &= 0xFFFFDFFF; + newbits |= 0x00002000 & rs; + } + + if (mask[3] == 1) { + overwrite &= 0xFF00FFFF; + newbits &= 0xFF00FFFF; + newbits |= 0x00FF0000 & rs; + } + + if (mask[4] == 1) { + overwrite &= 0x00FFFFFF; + newbits &= 0x00FFFFFF; + newbits |= 0xFF000000 & rs; + } + + if (mask[5] == 1) { + overwrite &= 0xFFFFBFFF; + newbits &= 0xFFFFBFFF; + newbits |= 0x00004000 & rs; + } + + dsp = dsp & overwrite; + dsp = dsp | newbits; + env->active_tc.DSPControl = dsp; +} + +target_ulong helper_rddsp(target_ulong masknum, CPUMIPSState *env) +{ + uint8_t mask[6]; + uint32_t ruler, i; + target_ulong temp; + target_ulong dsp; + + ruler = 0x01; + for (i = 0; i < 6; i++) { + mask[i] = (masknum & ruler) >> i ; + ruler = ruler << 1; + } + + temp = 0x00; + dsp = env->active_tc.DSPControl; + + if (mask[0] == 1) { +#if defined(TARGET_MIPS64) + temp |= dsp & 0x7F; +#else + temp |= dsp & 0x3F; +#endif + } + + if (mask[1] == 1) { + temp |= dsp & 0x1F80; + } + + if (mask[2] == 1) { + temp |= dsp & 0x2000; + } + + if (mask[3] == 1) { + temp |= dsp & 0x00FF0000; + } + + if (mask[4] == 1) { + temp |= dsp & 0xFF000000; + } + + if (mask[5] == 1) { + temp |= dsp & 0x4000; + } + + return temp; +} + + #undef MIPSDSP_LHI #undef MIPSDSP_LLO #undef MIPSDSP_HI diff --git a/target-mips/helper.h b/target-mips/helper.h index a821326b26..36a2e8da07 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -676,4 +676,39 @@ DEF_HELPER_FLAGS_2(packrl_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) DEF_HELPER_FLAGS_2(packrl_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl) #endif +/* DSP Accumulator and DSPControl Access Sub-class insns */ +DEF_HELPER_FLAGS_3(extr_w, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(extr_r_w, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(extr_rs_w, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(dextr_w, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(dextr_r_w, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(dextr_rs_w, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(dextr_l, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(dextr_r_l, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(dextr_rs_l, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(extr_s_h, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(dextr_s_h, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(extp, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(extpdp, 0, tl, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(dextp, 0, tl, tl, tl, env) +DEF_HELPER_FLAGS_3(dextpdp, 0, tl, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(shilo, 0, void, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(dshilo, 0, void, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(mthlip, 0, void, tl, tl, env) +#if defined(TARGET_MIPS64) +DEF_HELPER_FLAGS_3(dmthlip, 0, void, tl, tl, env) +#endif +DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env) +DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env) + + + #include "def-helper.h" diff --git a/target-mips/translate.c b/target-mips/translate.c index 69ef90a5aa..fea4113092 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -352,6 +352,11 @@ enum { OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3, #if defined(TARGET_MIPS64) OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3, +#endif + /* MIPS DSP Accumulator and DSPControl Access Sub-class */ + OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3, +#if defined(TARGET_MIPS64) + OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3, #endif }; @@ -564,6 +569,30 @@ enum { OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP, }; +#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Accumulator and DSPControl Access Sub-class */ + OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP, + OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP, + OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP, + OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP, + OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP, + OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP, + OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP, + OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP, + OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP, + OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP, + OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP, + OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP, + OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP, + OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP, + OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP, + OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP, + OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP, +}; + + + #if defined(TARGET_MIPS64) #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { @@ -676,6 +705,32 @@ enum { #endif #if defined(TARGET_MIPS64) +#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* MIPS DSP Accumulator and DSPControl Access Sub-class */ + OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP, + OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP, + OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP, + OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP, +}; + #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { /* DSP Bit/Manipulation Sub-class */ @@ -14077,6 +14132,236 @@ static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx, MIPS_DEBUG("%s", opn); } +static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2, + int ret, int v1, int v2, int check_ret) + +{ + const char *opn = "mipsdsp accumulator"; + TCGv t0; + TCGv t1; + TCGv v1_t; + TCGv v2_t; + int16_t imm; + + if ((ret == 0) && (check_ret == 1)) { + /* Treat as NOP. */ + MIPS_DEBUG("NOP"); + return; + } + + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + v1_t = tcg_temp_new(); + v2_t = tcg_temp_new(); + + gen_load_gpr(v1_t, v1); + gen_load_gpr(v2_t, v2); + + switch (op1) { + case OPC_EXTR_W_DSP: + check_dsp(ctx); + switch (op2) { + case OPC_EXTR_W: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_EXTR_R_W: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_EXTR_RS_W: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_EXTR_S_H: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_EXTRV_S_H: + tcg_gen_movi_tl(t0, v2); + gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_EXTRV_W: + tcg_gen_movi_tl(t0, v2); + gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_EXTRV_R_W: + tcg_gen_movi_tl(t0, v2); + gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_EXTRV_RS_W: + tcg_gen_movi_tl(t0, v2); + gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_EXTP: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_EXTPV: + tcg_gen_movi_tl(t0, v2); + gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_EXTPDP: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_EXTPDPV: + tcg_gen_movi_tl(t0, v2); + gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_SHILO: + imm = (ctx->opcode >> 20) & 0x3F; + tcg_gen_movi_tl(t0, ret); + tcg_gen_movi_tl(t1, imm); + gen_helper_shilo(t0, t1, cpu_env); + break; + case OPC_SHILOV: + tcg_gen_movi_tl(t0, ret); + gen_helper_shilo(t0, v1_t, cpu_env); + break; + case OPC_MTHLIP: + tcg_gen_movi_tl(t0, ret); + gen_helper_mthlip(t0, v1_t, cpu_env); + break; + case OPC_WRDSP: + imm = (ctx->opcode >> 11) & 0x3FF; + tcg_gen_movi_tl(t0, imm); + gen_helper_wrdsp(v1_t, t0, cpu_env); + break; + case OPC_RDDSP: + imm = (ctx->opcode >> 16) & 0x03FF; + tcg_gen_movi_tl(t0, imm); + gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env); + break; + } + break; +#ifdef TARGET_MIPS64 + case OPC_DEXTR_W_DSP: + check_dsp(ctx); + switch (op2) { + case OPC_DMTHLIP: + tcg_gen_movi_tl(t0, ret); + gen_helper_dmthlip(v1_t, t0, cpu_env); + break; + case OPC_DSHILO: + { + int shift = (ctx->opcode >> 19) & 0x7F; + int ac = (ctx->opcode >> 11) & 0x03; + tcg_gen_movi_tl(t0, shift); + tcg_gen_movi_tl(t1, ac); + gen_helper_dshilo(t0, t1, cpu_env); + break; + } + case OPC_DSHILOV: + { + int ac = (ctx->opcode >> 11) & 0x03; + tcg_gen_movi_tl(t0, ac); + gen_helper_dshilo(v1_t, t0, cpu_env); + break; + } + case OPC_DEXTP: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + + gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTPV: + tcg_gen_movi_tl(t0, v2); + gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_DEXTPDP: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTPDPV: + tcg_gen_movi_tl(t0, v2); + gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_DEXTR_L: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTR_R_L: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTR_RS_L: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTR_W: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTR_R_W: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTR_RS_W: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTR_S_H: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTRV_S_H: + tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t1, v1); + gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env); + break; + case OPC_DEXTRV_L: + tcg_gen_movi_tl(t0, v2); + gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_DEXTRV_R_L: + tcg_gen_movi_tl(t0, v2); + gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_DEXTRV_RS_L: + tcg_gen_movi_tl(t0, v2); + gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_DEXTRV_W: + tcg_gen_movi_tl(t0, v2); + gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_DEXTRV_R_W: + tcg_gen_movi_tl(t0, v2); + gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + case OPC_DEXTRV_RS_W: + tcg_gen_movi_tl(t0, v2); + gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env); + break; + } + break; +#endif + } + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(v1_t); + tcg_temp_free(v2_t); + + (void)opn; /* avoid a compiler warning */ + MIPS_DEBUG("%s", opn); +} + /* End MIPSDSP functions. */ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) @@ -14665,6 +14950,38 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) op2 = MASK_APPEND(ctx->opcode); gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1); break; + case OPC_EXTR_W_DSP: + op2 = MASK_EXTR_W(ctx->opcode); + switch (op2) { + case OPC_EXTR_W: + case OPC_EXTR_R_W: + case OPC_EXTR_RS_W: + case OPC_EXTR_S_H: + case OPC_EXTRV_S_H: + case OPC_EXTRV_W: + case OPC_EXTRV_R_W: + case OPC_EXTRV_RS_W: + case OPC_EXTP: + case OPC_EXTPV: + case OPC_EXTPDP: + case OPC_EXTPDPV: + gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1); + break; + case OPC_RDDSP: + gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1); + break; + case OPC_SHILO: + case OPC_SHILOV: + case OPC_MTHLIP: + case OPC_WRDSP: + gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0); + break; + default: /* Invalid */ + MIPS_INVAL("MASK EXTR.W"); + generate_exception(ctx, EXCP_RI); + break; + } + break; #if defined(TARGET_MIPS64) case OPC_DEXTM ... OPC_DEXT: case OPC_DINSM ... OPC_DINS: @@ -14809,6 +15126,40 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) op2 = MASK_DAPPEND(ctx->opcode); gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1); break; + case OPC_DEXTR_W_DSP: + op2 = MASK_DEXTR_W(ctx->opcode); + switch (op2) { + case OPC_DEXTP: + case OPC_DEXTPDP: + case OPC_DEXTPDPV: + case OPC_DEXTPV: + case OPC_DEXTR_L: + case OPC_DEXTR_R_L: + case OPC_DEXTR_RS_L: + case OPC_DEXTR_W: + case OPC_DEXTR_R_W: + case OPC_DEXTR_RS_W: + case OPC_DEXTR_S_H: + case OPC_DEXTRV_L: + case OPC_DEXTRV_R_L: + case OPC_DEXTRV_RS_L: + case OPC_DEXTRV_S_H: + case OPC_DEXTRV_W: + case OPC_DEXTRV_R_W: + case OPC_DEXTRV_RS_W: + gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1); + break; + case OPC_DMTHLIP: + case OPC_DSHILO: + case OPC_DSHILOV: + gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0); + break; + default: /* Invalid */ + MIPS_INVAL("MASK EXTR.W"); + generate_exception(ctx, EXCP_RI); + break; + } + break; case OPC_DPAQ_W_QH_DSP: op2 = MASK_DPAQ_W_QH(ctx->opcode); switch (op2) { From af13ae03f8dbc02974d53b11b80b3ae4dd9f30b4 Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Wed, 24 Oct 2012 22:17:12 +0800 Subject: [PATCH 1406/2270] target-mips: Add ASE DSP processors Add 74kf and mips64dspr2-generic-cpu model for test. Signed-off-by: Jia Liu Signed-off-by: Aurelien Jarno --- target-mips/translate_init.c | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index c39138f3c5..7cf238f34b 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -311,6 +311,29 @@ static const mips_def_t mips_defs[] = .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_MT, .mmu_type = MMU_TYPE_R4000, }, + { + .name = "74Kf", + .CP0_PRid = 0x00019700, + .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | + (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) | + (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | + (1 << CP0C1_CA), + .CP0_Config2 = MIPS_CONFIG2, + .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt) | (1 << CP0C3_DSPP), + .CP0_LLAddr_rw_bitmask = 0, + .CP0_LLAddr_shift = 4, + .SYNCI_Step = 32, + .CCRes = 2, + .CP0_Status_rw_bitmask = 0x3778FF1F, + .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | + (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID), + .SEGBITS = 32, + .PABITS = 32, + .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2, + .mmu_type = MMU_TYPE_R4000, + }, #if defined(TARGET_MIPS64) { .name = "R4000", @@ -484,6 +507,35 @@ static const mips_def_t mips_defs[] = .insn_flags = CPU_LOONGSON2F, .mmu_type = MMU_TYPE_R4000, }, + { + /* A generic CPU providing MIPS64 ASE DSP 2 features. + FIXME: Eventually this should be replaced by a real CPU model. */ + .name = "mips64dspr2", + .CP0_PRid = 0x00010000, + .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) | + (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) | + (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) | + (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) | + (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP), + .CP0_Config2 = MIPS_CONFIG2, + .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_LPA), + .CP0_LLAddr_rw_bitmask = 0, + .CP0_LLAddr_shift = 0, + .SYNCI_Step = 32, + .CCRes = 2, + .CP0_Status_rw_bitmask = 0x37FBFFFF, + .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) | + (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | + (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV), + .SEGBITS = 42, + /* The architectural limit is 59, but we have hardcoded 36 bit + in some places... + .PABITS = 59, */ /* the architectural limit */ + .PABITS = 36, + .insn_flags = CPU_MIPS64R2 | ASE_DSP | ASE_DSPR2, + .mmu_type = MMU_TYPE_R4000, + }, #endif }; From d70080c4e37fc533fa10904b286f29449decc6f8 Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Wed, 24 Oct 2012 22:17:13 +0800 Subject: [PATCH 1407/2270] target-mips: Add ASE DSP testcases Add MIPS ASE DSP testcases. Signed-off-by: Jia Liu Signed-off-by: Aurelien Jarno --- tests/tcg/mips/mips32-dsp/Makefile | 136 ++++++++ tests/tcg/mips/mips32-dsp/absq_s_ph.c | 31 ++ tests/tcg/mips/mips32-dsp/absq_s_w.c | 37 +++ tests/tcg/mips/mips32-dsp/addq_ph.c | 46 +++ tests/tcg/mips/mips32-dsp/addq_s_ph.c | 69 ++++ tests/tcg/mips/mips32-dsp/addq_s_w.c | 44 +++ tests/tcg/mips/mips32-dsp/addsc.c | 33 ++ tests/tcg/mips/mips32-dsp/addu_qb.c | 35 ++ tests/tcg/mips/mips32-dsp/addu_s_qb.c | 35 ++ tests/tcg/mips/mips32-dsp/addwc.c | 49 +++ tests/tcg/mips/mips32-dsp/bitrev.c | 20 ++ tests/tcg/mips/mips32-dsp/bposge32.c | 44 +++ tests/tcg/mips/mips32-dsp/cmp_eq_ph.c | 35 ++ tests/tcg/mips/mips32-dsp/cmp_le_ph.c | 35 ++ tests/tcg/mips/mips32-dsp/cmp_lt_ph.c | 35 ++ tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c | 31 ++ tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c | 31 ++ tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c | 31 ++ tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c | 35 ++ tests/tcg/mips/mips32-dsp/cmpu_le_qb.c | 35 ++ tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c | 35 ++ tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c | 31 ++ tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c | 77 +++++ tests/tcg/mips/mips32-dsp/dpau_h_qbl.c | 27 ++ tests/tcg/mips/mips32-dsp/dpau_h_qbr.c | 27 ++ tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c | 45 +++ tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c | 55 ++++ tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c | 27 ++ tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c | 27 ++ tests/tcg/mips/mips32-dsp/extp.c | 44 +++ tests/tcg/mips/mips32-dsp/extpdp.c | 46 +++ tests/tcg/mips/mips32-dsp/extpdpv.c | 47 +++ tests/tcg/mips/mips32-dsp/extpv.c | 45 +++ tests/tcg/mips/mips32-dsp/extr_r_w.c | 48 +++ tests/tcg/mips/mips32-dsp/extr_rs_w.c | 48 +++ tests/tcg/mips/mips32-dsp/extr_s_h.c | 63 ++++ tests/tcg/mips/mips32-dsp/extr_w.c | 48 +++ tests/tcg/mips/mips32-dsp/extrv_r_w.c | 54 ++++ tests/tcg/mips/mips32-dsp/extrv_rs_w.c | 52 +++ tests/tcg/mips/mips32-dsp/extrv_s_h.c | 71 ++++ tests/tcg/mips/mips32-dsp/extrv_w.c | 54 ++++ tests/tcg/mips/mips32-dsp/insv.c | 23 ++ tests/tcg/mips/mips32-dsp/lbux.c | 25 ++ tests/tcg/mips/mips32-dsp/lhx.c | 25 ++ tests/tcg/mips/mips32-dsp/lwx.c | 25 ++ tests/tcg/mips/mips32-dsp/madd.c | 31 ++ tests/tcg/mips/mips32-dsp/maddu.c | 31 ++ tests/tcg/mips/mips32-dsp/main.c | 6 + tests/tcg/mips/mips32-dsp/maq_s_w_phl.c | 55 ++++ tests/tcg/mips/mips32-dsp/maq_s_w_phr.c | 55 ++++ tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c | 55 ++++ tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c | 55 ++++ tests/tcg/mips/mips32-dsp/mfhi.c | 21 ++ tests/tcg/mips/mips32-dsp/mflo.c | 21 ++ tests/tcg/mips/mips32-dsp/modsub.c | 30 ++ tests/tcg/mips/mips32-dsp/msub.c | 30 ++ tests/tcg/mips/mips32-dsp/msubu.c | 30 ++ tests/tcg/mips/mips32-dsp/mthi.c | 21 ++ tests/tcg/mips/mips32-dsp/mthlip.c | 58 ++++ tests/tcg/mips/mips32-dsp/mtlo.c | 21 ++ tests/tcg/mips/mips32-dsp/muleq_s_w_phl.c | 41 +++ tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c | 40 +++ tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c | 25 ++ tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c | 25 ++ tests/tcg/mips/mips32-dsp/mulq_rs_ph.c | 25 ++ tests/tcg/mips/mips32-dsp/mult.c | 24 ++ tests/tcg/mips/mips32-dsp/multu.c | 24 ++ tests/tcg/mips/mips32-dsp/packrl_ph.c | 21 ++ tests/tcg/mips/mips32-dsp/pick_ph.c | 49 +++ tests/tcg/mips/mips32-dsp/pick_qb.c | 36 +++ tests/tcg/mips/mips32-dsp/preceq_w_phl.c | 20 ++ tests/tcg/mips/mips32-dsp/preceq_w_phr.c | 20 ++ tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c | 20 ++ tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c | 20 ++ tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c | 20 ++ tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c | 20 ++ tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c | 20 ++ tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c | 20 ++ tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c | 20 ++ tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c | 20 ++ tests/tcg/mips/mips32-dsp/precrq_ph_w.c | 21 ++ tests/tcg/mips/mips32-dsp/precrq_qb_ph.c | 21 ++ tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c | 35 ++ tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c | 24 ++ tests/tcg/mips/mips32-dsp/raddu_w_qb.c | 20 ++ tests/tcg/mips/mips32-dsp/rddsp.c | 54 ++++ tests/tcg/mips/mips32-dsp/repl_ph.c | 23 ++ tests/tcg/mips/mips32-dsp/repl_qb.c | 16 + tests/tcg/mips/mips32-dsp/replv_ph.c | 19 ++ tests/tcg/mips/mips32-dsp/replv_qb.c | 19 ++ tests/tcg/mips/mips32-dsp/shilo.c | 27 ++ tests/tcg/mips/mips32-dsp/shilov.c | 29 ++ tests/tcg/mips/mips32-dsp/shll_ph.c | 24 ++ tests/tcg/mips/mips32-dsp/shll_qb.c | 36 +++ tests/tcg/mips/mips32-dsp/shll_s_ph.c | 24 ++ tests/tcg/mips/mips32-dsp/shll_s_w.c | 52 +++ tests/tcg/mips/mips32-dsp/shllv_ph.c | 40 +++ tests/tcg/mips/mips32-dsp/shllv_qb.c | 38 +++ tests/tcg/mips/mips32-dsp/shllv_s_ph.c | 40 +++ tests/tcg/mips/mips32-dsp/shllv_s_w.c | 40 +++ tests/tcg/mips/mips32-dsp/shra_ph.c | 30 ++ tests/tcg/mips/mips32-dsp/shra_r_ph.c | 30 ++ tests/tcg/mips/mips32-dsp/shra_r_w.c | 30 ++ tests/tcg/mips/mips32-dsp/shrav_ph.c | 32 ++ tests/tcg/mips/mips32-dsp/shrav_r_ph.c | 32 ++ tests/tcg/mips/mips32-dsp/shrav_r_w.c | 32 ++ tests/tcg/mips/mips32-dsp/shrl_qb.c | 31 ++ tests/tcg/mips/mips32-dsp/shrlv_qb.c | 32 ++ tests/tcg/mips/mips32-dsp/subq_ph.c | 40 +++ tests/tcg/mips/mips32-dsp/subq_s_ph.c | 40 +++ tests/tcg/mips/mips32-dsp/subq_s_w.c | 58 ++++ tests/tcg/mips/mips32-dsp/subu_qb.c | 25 ++ tests/tcg/mips/mips32-dsp/subu_s_qb.c | 25 ++ tests/tcg/mips/mips32-dsp/wrdsp.c | 54 ++++ tests/tcg/mips/mips32-dspr2/Makefile | 71 ++++ tests/tcg/mips/mips32-dspr2/absq_s_qb.c | 35 ++ tests/tcg/mips/mips32-dspr2/addqh_ph.c | 30 ++ tests/tcg/mips/mips32-dspr2/addqh_r_ph.c | 30 ++ tests/tcg/mips/mips32-dspr2/addqh_r_w.c | 34 ++ tests/tcg/mips/mips32-dspr2/addqh_w.c | 34 ++ tests/tcg/mips/mips32-dspr2/addu_ph.c | 33 ++ tests/tcg/mips/mips32-dspr2/addu_s_ph.c | 33 ++ tests/tcg/mips/mips32-dspr2/adduh_qb.c | 30 ++ tests/tcg/mips/mips32-dspr2/adduh_r_qb.c | 30 ++ tests/tcg/mips/mips32-dspr2/append.c | 30 ++ tests/tcg/mips/mips32-dspr2/balign.c | 30 ++ tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c | 37 +++ tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c | 37 +++ tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c | 37 +++ tests/tcg/mips/mips32-dspr2/dpa_w_ph.c | 44 +++ tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c | 79 +++++ tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c | 53 +++ tests/tcg/mips/mips32-dspr2/dpax_w_ph.c | 27 ++ tests/tcg/mips/mips32-dspr2/dps_w_ph.c | 27 ++ tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c | 54 ++++ tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c | 53 +++ tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c | 27 ++ tests/tcg/mips/mips32-dspr2/mul_ph.c | 47 +++ tests/tcg/mips/mips32-dspr2/mul_s_ph.c | 62 ++++ tests/tcg/mips/mips32-dspr2/mulq_rs_w.c | 36 +++ tests/tcg/mips/mips32-dspr2/mulq_s_ph.c | 25 ++ tests/tcg/mips/mips32-dspr2/mulq_s_w.c | 36 +++ tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c | 29 ++ tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c | 29 ++ tests/tcg/mips/mips32-dspr2/precr_qb_ph.c | 21 ++ tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c | 32 ++ .../tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c | 32 ++ tests/tcg/mips/mips32-dspr2/prepend.c | 30 ++ tests/tcg/mips/mips32-dspr2/shra_qb.c | 30 ++ tests/tcg/mips/mips32-dspr2/shra_r_qb.c | 30 ++ tests/tcg/mips/mips32-dspr2/shrav_qb.c | 32 ++ tests/tcg/mips/mips32-dspr2/shrav_r_qb.c | 32 ++ tests/tcg/mips/mips32-dspr2/shrl_ph.c | 20 ++ tests/tcg/mips/mips32-dspr2/shrlv_ph.c | 21 ++ tests/tcg/mips/mips32-dspr2/subqh_ph.c | 21 ++ tests/tcg/mips/mips32-dspr2/subqh_r_ph.c | 21 ++ tests/tcg/mips/mips32-dspr2/subqh_r_w.c | 21 ++ tests/tcg/mips/mips32-dspr2/subqh_w.c | 21 ++ tests/tcg/mips/mips32-dspr2/subu_ph.c | 40 +++ tests/tcg/mips/mips32-dspr2/subu_s_ph.c | 25 ++ tests/tcg/mips/mips32-dspr2/subuh_qb.c | 21 ++ tests/tcg/mips/mips32-dspr2/subuh_r_qb.c | 32 ++ tests/tcg/mips/mips64-dsp/Makefile | 306 ++++++++++++++++++ tests/tcg/mips/mips64-dsp/absq_s_ob.c | 63 ++++ tests/tcg/mips/mips64-dsp/absq_s_ph.c | 37 +++ tests/tcg/mips/mips64-dsp/absq_s_pw.c | 66 ++++ tests/tcg/mips/mips64-dsp/absq_s_qh.c | 40 +++ tests/tcg/mips/mips64-dsp/absq_s_w.c | 48 +++ tests/tcg/mips/mips64-dsp/addq_ph.c | 57 ++++ tests/tcg/mips/mips64-dsp/addq_pw.c | 46 +++ tests/tcg/mips/mips64-dsp/addq_qh.c | 28 ++ tests/tcg/mips/mips64-dsp/addq_s_ph.c | 84 +++++ tests/tcg/mips/mips64-dsp/addq_s_pw.c | 45 +++ tests/tcg/mips/mips64-dsp/addq_s_qh.c | 26 ++ tests/tcg/mips/mips64-dsp/addq_s_w.c | 48 +++ tests/tcg/mips/mips64-dsp/addsc.c | 39 +++ tests/tcg/mips/mips64-dsp/addu_ob.c | 28 ++ tests/tcg/mips/mips64-dsp/addu_qb.c | 40 +++ tests/tcg/mips/mips64-dsp/addu_s_ob.c | 27 ++ tests/tcg/mips/mips64-dsp/addu_s_qb.c | 40 +++ tests/tcg/mips/mips64-dsp/addwc.c | 59 ++++ tests/tcg/mips/mips64-dsp/bitrev.c | 23 ++ tests/tcg/mips/mips64-dsp/bposge32.c | 50 +++ tests/tcg/mips/mips64-dsp/bposge64.c | 50 +++ tests/tcg/mips/mips64-dsp/cmp_eq_ph.c | 42 +++ tests/tcg/mips/mips64-dsp/cmp_eq_pw.c | 46 +++ tests/tcg/mips/mips64-dsp/cmp_eq_qh.c | 46 +++ tests/tcg/mips/mips64-dsp/cmp_le_ph.c | 40 +++ tests/tcg/mips/mips64-dsp/cmp_le_pw.c | 46 +++ tests/tcg/mips/mips64-dsp/cmp_le_qh.c | 46 +++ tests/tcg/mips/mips64-dsp/cmp_lt_ph.c | 41 +++ tests/tcg/mips/mips64-dsp/cmp_lt_pw.c | 46 +++ tests/tcg/mips/mips64-dsp/cmp_lt_qh.c | 46 +++ tests/tcg/mips/mips64-dsp/cmpgu_eq_ob.c | 40 +++ tests/tcg/mips/mips64-dsp/cmpgu_eq_qb.c | 38 +++ tests/tcg/mips/mips64-dsp/cmpgu_le_ob.c | 40 +++ tests/tcg/mips/mips64-dsp/cmpgu_le_qb.c | 37 +++ tests/tcg/mips/mips64-dsp/cmpgu_lt_ob.c | 40 +++ tests/tcg/mips/mips64-dsp/cmpgu_lt_qb.c | 38 +++ tests/tcg/mips/mips64-dsp/cmpu_eq_ob.c | 46 +++ tests/tcg/mips/mips64-dsp/cmpu_eq_qb.c | 42 +++ tests/tcg/mips/mips64-dsp/cmpu_le_ob.c | 44 +++ tests/tcg/mips/mips64-dsp/cmpu_le_qb.c | 41 +++ tests/tcg/mips/mips64-dsp/cmpu_lt_ob.c | 44 +++ tests/tcg/mips/mips64-dsp/cmpu_lt_qb.c | 42 +++ tests/tcg/mips/mips64-dsp/dappend.c | 37 +++ tests/tcg/mips/mips64-dsp/dextp.c | 54 ++++ tests/tcg/mips/mips64-dsp/dextpdp.c | 59 ++++ tests/tcg/mips/mips64-dsp/dextpdpv.c | 63 ++++ tests/tcg/mips/mips64-dsp/dextpv.c | 58 ++++ tests/tcg/mips/mips64-dsp/dextr_l.c | 44 +++ tests/tcg/mips/mips64-dsp/dextr_r_l.c | 54 ++++ tests/tcg/mips/mips64-dsp/dextr_r_w.c | 54 ++++ tests/tcg/mips/mips64-dsp/dextr_rs_l.c | 52 +++ tests/tcg/mips/mips64-dsp/dextr_rs_w.c | 52 +++ tests/tcg/mips/mips64-dsp/dextr_s_h.c | 73 +++++ tests/tcg/mips/mips64-dsp/dextr_w.c | 44 +++ tests/tcg/mips/mips64-dsp/dextrv_l.c | 46 +++ tests/tcg/mips/mips64-dsp/dextrv_r_l.c | 56 ++++ tests/tcg/mips/mips64-dsp/dextrv_r_w.c | 56 ++++ tests/tcg/mips/mips64-dsp/dextrv_rs_l.c | 54 ++++ tests/tcg/mips/mips64-dsp/dextrv_rs_w.c | 54 ++++ tests/tcg/mips/mips64-dsp/dextrv_s_h.c | 32 ++ tests/tcg/mips/mips64-dsp/dextrv_w.c | 46 +++ tests/tcg/mips/mips64-dsp/dinsv.c | 26 ++ tests/tcg/mips/mips64-dsp/dmadd.c | 57 ++++ tests/tcg/mips/mips64-dsp/dmaddu.c | 56 ++++ tests/tcg/mips/mips64-dsp/dmsub.c | 59 ++++ tests/tcg/mips/mips64-dsp/dmsubu.c | 59 ++++ tests/tcg/mips/mips64-dsp/dmthlip.c | 41 +++ tests/tcg/mips/mips64-dsp/dpaq_s_w_ph.c | 32 ++ tests/tcg/mips/mips64-dsp/dpaq_s_w_qh.c | 57 ++++ tests/tcg/mips/mips64-dsp/dpaq_sa_l_pw.c | 88 +++++ tests/tcg/mips/mips64-dsp/dpaq_sa_l_w.c | 82 +++++ tests/tcg/mips/mips64-dsp/dpau_h_obl.c | 59 ++++ tests/tcg/mips/mips64-dsp/dpau_h_obr.c | 59 ++++ tests/tcg/mips/mips64-dsp/dpau_h_qbl.c | 29 ++ tests/tcg/mips/mips64-dsp/dpau_h_qbr.c | 29 ++ tests/tcg/mips/mips64-dsp/dpsq_s_w_ph.c | 51 +++ tests/tcg/mips/mips64-dsp/dpsq_s_w_qh.c | 56 ++++ tests/tcg/mips/mips64-dsp/dpsq_sa_l_pw.c | 76 +++++ tests/tcg/mips/mips64-dsp/dpsq_sa_l_w.c | 59 ++++ tests/tcg/mips/mips64-dsp/dpsu_h_obl.c | 32 ++ tests/tcg/mips/mips64-dsp/dpsu_h_obr.c | 32 ++ tests/tcg/mips/mips64-dsp/dpsu_h_qbl.c | 29 ++ tests/tcg/mips/mips64-dsp/dpsu_h_qbr.c | 29 ++ tests/tcg/mips/mips64-dsp/dshilo.c | 52 +++ tests/tcg/mips/mips64-dsp/dshilov.c | 54 ++++ tests/tcg/mips/mips64-dsp/extp.c | 50 +++ tests/tcg/mips/mips64-dsp/extpdp.c | 51 +++ tests/tcg/mips/mips64-dsp/extpdpv.c | 52 +++ tests/tcg/mips/mips64-dsp/extpv.c | 51 +++ tests/tcg/mips/mips64-dsp/extr_r_w.c | 53 +++ tests/tcg/mips/mips64-dsp/extr_rs_w.c | 53 +++ tests/tcg/mips/mips64-dsp/extr_s_h.c | 71 ++++ tests/tcg/mips/mips64-dsp/extr_w.c | 53 +++ tests/tcg/mips/mips64-dsp/extrv_r_w.c | 59 ++++ tests/tcg/mips/mips64-dsp/extrv_rs_w.c | 59 ++++ tests/tcg/mips/mips64-dsp/extrv_s_h.c | 79 +++++ tests/tcg/mips/mips64-dsp/extrv_w.c | 59 ++++ tests/tcg/mips/mips64-dsp/head.S | 16 + tests/tcg/mips/mips64-dsp/insv.c | 26 ++ tests/tcg/mips/mips64-dsp/io.h | 22 ++ tests/tcg/mips/mips64-dsp/lbux.c | 27 ++ tests/tcg/mips/mips64-dsp/ldx.c | 27 ++ tests/tcg/mips/mips64-dsp/lhx.c | 27 ++ tests/tcg/mips/mips64-dsp/lwx.c | 27 ++ tests/tcg/mips/mips64-dsp/madd.c | 33 ++ tests/tcg/mips/mips64-dsp/maddu.c | 33 ++ tests/tcg/mips/mips64-dsp/maq_s_l_pwl.c | 56 ++++ tests/tcg/mips/mips64-dsp/maq_s_l_pwr.c | 56 ++++ tests/tcg/mips/mips64-dsp/maq_s_w_phl.c | 60 ++++ tests/tcg/mips/mips64-dsp/maq_s_w_phr.c | 60 ++++ tests/tcg/mips/mips64-dsp/maq_s_w_qhll.c | 62 ++++ tests/tcg/mips/mips64-dsp/maq_s_w_qhlr.c | 62 ++++ tests/tcg/mips/mips64-dsp/maq_s_w_qhrl.c | 63 ++++ tests/tcg/mips/mips64-dsp/maq_s_w_qhrr.c | 63 ++++ tests/tcg/mips/mips64-dsp/maq_sa_w_phl.c | 60 ++++ tests/tcg/mips/mips64-dsp/maq_sa_w_phr.c | 60 ++++ tests/tcg/mips/mips64-dsp/maq_sa_w_qhll.c | 62 ++++ tests/tcg/mips/mips64-dsp/maq_sa_w_qhlr.c | 64 ++++ tests/tcg/mips/mips64-dsp/maq_sa_w_qhrl.c | 64 ++++ tests/tcg/mips/mips64-dsp/maq_sa_w_qhrr.c | 64 ++++ tests/tcg/mips/mips64-dsp/mfhi.c | 24 ++ tests/tcg/mips/mips64-dsp/mflo.c | 24 ++ tests/tcg/mips/mips64-dsp/mips_boot.lds | 31 ++ tests/tcg/mips/mips64-dsp/modsub.c | 37 +++ tests/tcg/mips/mips64-dsp/msub.c | 32 ++ tests/tcg/mips/mips64-dsp/msubu.c | 32 ++ tests/tcg/mips/mips64-dsp/mthi.c | 24 ++ tests/tcg/mips/mips64-dsp/mthlip.c | 61 ++++ tests/tcg/mips/mips64-dsp/mtlo.c | 22 ++ tests/tcg/mips/mips64-dsp/muleq_s_pw_qhl.c | 56 ++++ tests/tcg/mips/mips64-dsp/muleq_s_pw_qhr.c | 57 ++++ tests/tcg/mips/mips64-dsp/muleq_s_w_phl.c | 46 +++ tests/tcg/mips/mips64-dsp/muleq_s_w_phr.c | 45 +++ tests/tcg/mips/mips64-dsp/muleu_s_ph_qbl.c | 27 ++ tests/tcg/mips/mips64-dsp/muleu_s_ph_qbr.c | 27 ++ tests/tcg/mips/mips64-dsp/muleu_s_qh_obl.c | 30 ++ tests/tcg/mips/mips64-dsp/muleu_s_qh_obr.c | 31 ++ tests/tcg/mips/mips64-dsp/mulq_rs_ph.c | 27 ++ tests/tcg/mips/mips64-dsp/mulq_rs_qh.c | 33 ++ tests/tcg/mips/mips64-dsp/mulsaq_s_l_pw.c | 59 ++++ tests/tcg/mips/mips64-dsp/mulsaq_s_w_qh.c | 57 ++++ tests/tcg/mips/mips64-dsp/mult.c | 26 ++ tests/tcg/mips/mips64-dsp/multu.c | 26 ++ tests/tcg/mips/mips64-dsp/packrl_ph.c | 24 ++ tests/tcg/mips/mips64-dsp/packrl_pw.c | 24 ++ tests/tcg/mips/mips64-dsp/pick_ob.c | 66 ++++ tests/tcg/mips/mips64-dsp/pick_ph.c | 60 ++++ tests/tcg/mips/mips64-dsp/pick_pw.c | 48 +++ tests/tcg/mips/mips64-dsp/pick_qb.c | 43 +++ tests/tcg/mips/mips64-dsp/pick_qh.c | 48 +++ tests/tcg/mips/mips64-dsp/preceq_l_pwl.c | 24 ++ tests/tcg/mips/mips64-dsp/preceq_l_pwr.c | 24 ++ tests/tcg/mips/mips64-dsp/preceq_pw_qhl.c | 21 ++ tests/tcg/mips/mips64-dsp/preceq_pw_qhla.c | 23 ++ tests/tcg/mips/mips64-dsp/preceq_pw_qhr.c | 21 ++ tests/tcg/mips/mips64-dsp/preceq_pw_qhra.c | 23 ++ tests/tcg/mips/mips64-dsp/preceq_w_phl.c | 23 ++ tests/tcg/mips/mips64-dsp/preceq_w_phr.c | 23 ++ tests/tcg/mips/mips64-dsp/precequ_ph_qbl.c | 23 ++ tests/tcg/mips/mips64-dsp/precequ_ph_qbla.c | 23 ++ tests/tcg/mips/mips64-dsp/precequ_ph_qbr.c | 23 ++ tests/tcg/mips/mips64-dsp/precequ_ph_qbra.c | 23 ++ tests/tcg/mips/mips64-dsp/precequ_qh_obl.c | 22 ++ tests/tcg/mips/mips64-dsp/precequ_qh_obla.c | 22 ++ tests/tcg/mips/mips64-dsp/precequ_qh_obr.c | 24 ++ tests/tcg/mips/mips64-dsp/precequ_qh_obra.c | 24 ++ tests/tcg/mips/mips64-dsp/preceu_ph_qbl.c | 23 ++ tests/tcg/mips/mips64-dsp/preceu_ph_qbla.c | 23 ++ tests/tcg/mips/mips64-dsp/preceu_ph_qbr.c | 23 ++ tests/tcg/mips/mips64-dsp/preceu_ph_qbra.c | 23 ++ tests/tcg/mips/mips64-dsp/preceu_qh_obl.c | 22 ++ tests/tcg/mips/mips64-dsp/preceu_qh_obla.c | 22 ++ tests/tcg/mips/mips64-dsp/preceu_qh_obr.c | 23 ++ tests/tcg/mips/mips64-dsp/preceu_qh_obra.c | 23 ++ tests/tcg/mips/mips64-dsp/precr_ob_qh.c | 25 ++ tests/tcg/mips/mips64-dsp/precr_sra_qh_pw.c | 40 +++ tests/tcg/mips/mips64-dsp/precr_sra_r_qh_pw.c | 40 +++ tests/tcg/mips/mips64-dsp/precrq_ob_qh.c | 25 ++ tests/tcg/mips/mips64-dsp/precrq_ph_w.c | 24 ++ tests/tcg/mips/mips64-dsp/precrq_pw_l.c | 25 ++ tests/tcg/mips/mips64-dsp/precrq_qb_ph.c | 24 ++ tests/tcg/mips/mips64-dsp/precrq_qh_pw.c | 25 ++ tests/tcg/mips/mips64-dsp/precrq_rs_ph_w.c | 41 +++ tests/tcg/mips/mips64-dsp/precrq_rs_qh_pw.c | 43 +++ tests/tcg/mips/mips64-dsp/precrqu_s_ob_qh.c | 27 ++ tests/tcg/mips/mips64-dsp/precrqu_s_qb_ph.c | 26 ++ tests/tcg/mips/mips64-dsp/prependd.c | 37 +++ tests/tcg/mips/mips64-dsp/prependw.c | 37 +++ tests/tcg/mips/mips64-dsp/printf.c | 266 +++++++++++++++ tests/tcg/mips/mips64-dsp/raddu_l_ob.c | 22 ++ tests/tcg/mips/mips64-dsp/raddu_w_qb.c | 23 ++ tests/tcg/mips/mips64-dsp/rddsp.c | 53 +++ tests/tcg/mips/mips64-dsp/repl_ob.c | 21 ++ tests/tcg/mips/mips64-dsp/repl_ph.c | 30 ++ tests/tcg/mips/mips64-dsp/repl_pw.c | 34 ++ tests/tcg/mips/mips64-dsp/repl_qb.c | 19 ++ tests/tcg/mips/mips64-dsp/repl_qh.c | 34 ++ tests/tcg/mips/mips64-dsp/replv_ob.c | 23 ++ tests/tcg/mips/mips64-dsp/replv_ph.c | 22 ++ tests/tcg/mips/mips64-dsp/replv_pw.c | 23 ++ tests/tcg/mips/mips64-dsp/replv_qb.c | 22 ++ tests/tcg/mips/mips64-dsp/shilo.c | 29 ++ tests/tcg/mips/mips64-dsp/shilov.c | 31 ++ tests/tcg/mips/mips64-dsp/shll_ob.c | 43 +++ tests/tcg/mips/mips64-dsp/shll_ph.c | 43 +++ tests/tcg/mips/mips64-dsp/shll_pw.c | 43 +++ tests/tcg/mips/mips64-dsp/shll_qb.c | 26 ++ tests/tcg/mips/mips64-dsp/shll_qh.c | 42 +++ tests/tcg/mips/mips64-dsp/shll_s_ph.c | 43 +++ tests/tcg/mips/mips64-dsp/shll_s_pw.c | 43 +++ tests/tcg/mips/mips64-dsp/shll_s_qh.c | 43 +++ tests/tcg/mips/mips64-dsp/shll_s_w.c | 26 ++ tests/tcg/mips/mips64-dsp/shllv_ob.c | 45 +++ tests/tcg/mips/mips64-dsp/shllv_ph.c | 27 ++ tests/tcg/mips/mips64-dsp/shllv_pw.c | 45 +++ tests/tcg/mips/mips64-dsp/shllv_qb.c | 27 ++ tests/tcg/mips/mips64-dsp/shllv_qh.c | 45 +++ tests/tcg/mips/mips64-dsp/shllv_s_ph.c | 27 ++ tests/tcg/mips/mips64-dsp/shllv_s_pw.c | 45 +++ tests/tcg/mips/mips64-dsp/shllv_s_qh.c | 45 +++ tests/tcg/mips/mips64-dsp/shllv_s_w.c | 27 ++ tests/tcg/mips/mips64-dsp/shra_ob.c | 23 ++ tests/tcg/mips/mips64-dsp/shra_ph.c | 23 ++ tests/tcg/mips/mips64-dsp/shra_pw.c | 36 +++ tests/tcg/mips/mips64-dsp/shra_qh.c | 37 +++ tests/tcg/mips/mips64-dsp/shra_r_ob.c | 22 ++ tests/tcg/mips/mips64-dsp/shra_r_ph.c | 23 ++ tests/tcg/mips/mips64-dsp/shra_r_pw.c | 36 +++ tests/tcg/mips/mips64-dsp/shra_r_qh.c | 37 +++ tests/tcg/mips/mips64-dsp/shra_r_w.c | 23 ++ tests/tcg/mips/mips64-dsp/shrav_ph.c | 24 ++ tests/tcg/mips/mips64-dsp/shrav_pw.c | 38 +++ tests/tcg/mips/mips64-dsp/shrav_qh.c | 39 +++ tests/tcg/mips/mips64-dsp/shrav_r_ph.c | 24 ++ tests/tcg/mips/mips64-dsp/shrav_r_pw.c | 37 +++ tests/tcg/mips/mips64-dsp/shrav_r_qh.c | 39 +++ tests/tcg/mips/mips64-dsp/shrav_r_w.c | 24 ++ tests/tcg/mips/mips64-dsp/shrl_ob.c | 38 +++ tests/tcg/mips/mips64-dsp/shrl_qb.c | 23 ++ tests/tcg/mips/mips64-dsp/shrl_qh.c | 22 ++ tests/tcg/mips/mips64-dsp/shrlv_ob.c | 39 +++ tests/tcg/mips/mips64-dsp/shrlv_qb.c | 24 ++ tests/tcg/mips/mips64-dsp/shrlv_qh.c | 23 ++ tests/tcg/mips/mips64-dsp/subq_ph.c | 27 ++ tests/tcg/mips/mips64-dsp/subq_pw.c | 44 +++ tests/tcg/mips/mips64-dsp/subq_qh.c | 26 ++ tests/tcg/mips/mips64-dsp/subq_s_ph.c | 27 ++ tests/tcg/mips/mips64-dsp/subq_s_pw.c | 63 ++++ tests/tcg/mips/mips64-dsp/subq_s_qh.c | 61 ++++ tests/tcg/mips/mips64-dsp/subq_s_w.c | 27 ++ tests/tcg/mips/mips64-dsp/subu_ob.c | 26 ++ tests/tcg/mips/mips64-dsp/subu_qb.c | 27 ++ tests/tcg/mips/mips64-dsp/subu_s_ob.c | 26 ++ tests/tcg/mips/mips64-dsp/subu_s_qb.c | 27 ++ tests/tcg/mips/mips64-dsp/wrdsp.c | 48 +++ tests/tcg/mips/mips64-dspr2/.directory | 2 + tests/tcg/mips/mips64-dspr2/Makefile | 116 +++++++ tests/tcg/mips/mips64-dspr2/absq_s_qb.c | 42 +++ tests/tcg/mips/mips64-dspr2/addqh_ph.c | 35 ++ tests/tcg/mips/mips64-dspr2/addqh_r_ph.c | 35 ++ tests/tcg/mips/mips64-dspr2/addqh_r_w.c | 38 +++ tests/tcg/mips/mips64-dspr2/addqh_w.c | 39 +++ tests/tcg/mips/mips64-dspr2/addu_ph.c | 37 +++ tests/tcg/mips/mips64-dspr2/addu_qh.c | 43 +++ tests/tcg/mips/mips64-dspr2/addu_s_ph.c | 37 +++ tests/tcg/mips/mips64-dspr2/addu_s_qh.c | 43 +++ tests/tcg/mips/mips64-dspr2/adduh_ob.c | 35 ++ tests/tcg/mips/mips64-dspr2/adduh_qb.c | 35 ++ tests/tcg/mips/mips64-dspr2/adduh_r_ob.c | 35 ++ tests/tcg/mips/mips64-dspr2/adduh_r_qb.c | 35 ++ tests/tcg/mips/mips64-dspr2/append.c | 35 ++ tests/tcg/mips/mips64-dspr2/balign.c | 35 ++ tests/tcg/mips/mips64-dspr2/cmpgdu_eq_ob.c | 44 +++ tests/tcg/mips/mips64-dspr2/cmpgdu_eq_qb.c | 41 +++ tests/tcg/mips/mips64-dspr2/cmpgdu_le_ob.c | 44 +++ tests/tcg/mips/mips64-dspr2/cmpgdu_le_qb.c | 48 +++ tests/tcg/mips/mips64-dspr2/cmpgdu_lt_ob.c | 44 +++ tests/tcg/mips/mips64-dspr2/cmpgdu_lt_qb.c | 48 +++ tests/tcg/mips/mips64-dspr2/dbalign.c | 39 +++ tests/tcg/mips/mips64-dspr2/dpa_w_ph.c | 47 +++ tests/tcg/mips/mips64-dspr2/dpa_w_qh.c | 56 ++++ tests/tcg/mips/mips64-dspr2/dpaqx_s_w_ph.c | 97 ++++++ tests/tcg/mips/mips64-dspr2/dpaqx_sa_w_ph.c | 54 ++++ tests/tcg/mips/mips64-dspr2/dpax_w_ph.c | 32 ++ tests/tcg/mips/mips64-dspr2/dps_w_ph.c | 28 ++ tests/tcg/mips/mips64-dspr2/dps_w_qh.c | 55 ++++ tests/tcg/mips/mips64-dspr2/dpsqx_s_w_ph.c | 55 ++++ tests/tcg/mips/mips64-dspr2/dpsqx_sa_w_ph.c | 53 +++ tests/tcg/mips/mips64-dspr2/dpsx_w_ph.c | 28 ++ tests/tcg/mips/mips64-dspr2/head.S | 16 + tests/tcg/mips/mips64-dspr2/io.h | 22 ++ tests/tcg/mips/mips64-dspr2/mips_boot.lds | 31 ++ tests/tcg/mips/mips64-dspr2/mul_ph.c | 50 +++ tests/tcg/mips/mips64-dspr2/mul_s_ph.c | 67 ++++ tests/tcg/mips/mips64-dspr2/mulq_rs_w.c | 40 +++ tests/tcg/mips/mips64-dspr2/mulq_s_ph.c | 26 ++ tests/tcg/mips/mips64-dspr2/mulq_s_w.c | 40 +++ tests/tcg/mips/mips64-dspr2/mulsa_w_ph.c | 30 ++ tests/tcg/mips/mips64-dspr2/mulsaq_s_w_ph.c | 30 ++ tests/tcg/mips/mips64-dspr2/precr_qb_ph.c | 23 ++ tests/tcg/mips/mips64-dspr2/precr_sra_ph_w.c | 37 +++ .../tcg/mips/mips64-dspr2/precr_sra_r_ph_w.c | 37 +++ tests/tcg/mips/mips64-dspr2/prepend.c | 35 ++ tests/tcg/mips/mips64-dspr2/printf.c | 266 +++++++++++++++ tests/tcg/mips/mips64-dspr2/shra_qb.c | 35 ++ tests/tcg/mips/mips64-dspr2/shra_r_qb.c | 35 ++ tests/tcg/mips/mips64-dspr2/shrav_ob.c | 22 ++ tests/tcg/mips/mips64-dspr2/shrav_qb.c | 37 +++ tests/tcg/mips/mips64-dspr2/shrav_r_ob.c | 22 ++ tests/tcg/mips/mips64-dspr2/shrav_r_qb.c | 37 +++ tests/tcg/mips/mips64-dspr2/shrl_ph.c | 22 ++ tests/tcg/mips/mips64-dspr2/shrlv_ph.c | 23 ++ tests/tcg/mips/mips64-dspr2/subqh_ph.c | 23 ++ tests/tcg/mips/mips64-dspr2/subqh_r_ph.c | 23 ++ tests/tcg/mips/mips64-dspr2/subqh_r_w.c | 23 ++ tests/tcg/mips/mips64-dspr2/subqh_w.c | 23 ++ tests/tcg/mips/mips64-dspr2/subu_ph.c | 26 ++ tests/tcg/mips/mips64-dspr2/subu_qh.c | 24 ++ tests/tcg/mips/mips64-dspr2/subu_s_ph.c | 25 ++ tests/tcg/mips/mips64-dspr2/subu_s_qh.c | 42 +++ tests/tcg/mips/mips64-dspr2/subuh_ob.c | 36 +++ tests/tcg/mips/mips64-dspr2/subuh_qb.c | 23 ++ tests/tcg/mips/mips64-dspr2/subuh_r_ob.c | 23 ++ tests/tcg/mips/mips64-dspr2/subuh_r_qb.c | 37 +++ 487 files changed, 19151 insertions(+) create mode 100644 tests/tcg/mips/mips32-dsp/Makefile create mode 100644 tests/tcg/mips/mips32-dsp/absq_s_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/absq_s_w.c create mode 100644 tests/tcg/mips/mips32-dsp/addq_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/addq_s_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/addq_s_w.c create mode 100644 tests/tcg/mips/mips32-dsp/addsc.c create mode 100644 tests/tcg/mips/mips32-dsp/addu_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/addu_s_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/addwc.c create mode 100644 tests/tcg/mips/mips32-dsp/bitrev.c create mode 100644 tests/tcg/mips/mips32-dsp/bposge32.c create mode 100644 tests/tcg/mips/mips32-dsp/cmp_eq_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/cmp_le_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/cmp_lt_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/cmpu_le_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c create mode 100644 tests/tcg/mips/mips32-dsp/dpau_h_qbl.c create mode 100644 tests/tcg/mips/mips32-dsp/dpau_h_qbr.c create mode 100644 tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c create mode 100644 tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c create mode 100644 tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c create mode 100644 tests/tcg/mips/mips32-dsp/extp.c create mode 100644 tests/tcg/mips/mips32-dsp/extpdp.c create mode 100644 tests/tcg/mips/mips32-dsp/extpdpv.c create mode 100644 tests/tcg/mips/mips32-dsp/extpv.c create mode 100644 tests/tcg/mips/mips32-dsp/extr_r_w.c create mode 100644 tests/tcg/mips/mips32-dsp/extr_rs_w.c create mode 100644 tests/tcg/mips/mips32-dsp/extr_s_h.c create mode 100644 tests/tcg/mips/mips32-dsp/extr_w.c create mode 100644 tests/tcg/mips/mips32-dsp/extrv_r_w.c create mode 100644 tests/tcg/mips/mips32-dsp/extrv_rs_w.c create mode 100644 tests/tcg/mips/mips32-dsp/extrv_s_h.c create mode 100644 tests/tcg/mips/mips32-dsp/extrv_w.c create mode 100644 tests/tcg/mips/mips32-dsp/insv.c create mode 100644 tests/tcg/mips/mips32-dsp/lbux.c create mode 100644 tests/tcg/mips/mips32-dsp/lhx.c create mode 100644 tests/tcg/mips/mips32-dsp/lwx.c create mode 100644 tests/tcg/mips/mips32-dsp/madd.c create mode 100644 tests/tcg/mips/mips32-dsp/maddu.c create mode 100644 tests/tcg/mips/mips32-dsp/main.c create mode 100644 tests/tcg/mips/mips32-dsp/maq_s_w_phl.c create mode 100644 tests/tcg/mips/mips32-dsp/maq_s_w_phr.c create mode 100644 tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c create mode 100644 tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c create mode 100644 tests/tcg/mips/mips32-dsp/mfhi.c create mode 100644 tests/tcg/mips/mips32-dsp/mflo.c create mode 100644 tests/tcg/mips/mips32-dsp/modsub.c create mode 100644 tests/tcg/mips/mips32-dsp/msub.c create mode 100644 tests/tcg/mips/mips32-dsp/msubu.c create mode 100644 tests/tcg/mips/mips32-dsp/mthi.c create mode 100644 tests/tcg/mips/mips32-dsp/mthlip.c create mode 100644 tests/tcg/mips/mips32-dsp/mtlo.c create mode 100644 tests/tcg/mips/mips32-dsp/muleq_s_w_phl.c create mode 100644 tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c create mode 100644 tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c create mode 100644 tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c create mode 100644 tests/tcg/mips/mips32-dsp/mulq_rs_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/mult.c create mode 100644 tests/tcg/mips/mips32-dsp/multu.c create mode 100644 tests/tcg/mips/mips32-dsp/packrl_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/pick_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/pick_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/preceq_w_phl.c create mode 100644 tests/tcg/mips/mips32-dsp/preceq_w_phr.c create mode 100644 tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c create mode 100644 tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c create mode 100644 tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c create mode 100644 tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c create mode 100644 tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c create mode 100644 tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c create mode 100644 tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c create mode 100644 tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c create mode 100644 tests/tcg/mips/mips32-dsp/precrq_ph_w.c create mode 100644 tests/tcg/mips/mips32-dsp/precrq_qb_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c create mode 100644 tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/raddu_w_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/rddsp.c create mode 100644 tests/tcg/mips/mips32-dsp/repl_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/repl_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/replv_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/replv_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/shilo.c create mode 100644 tests/tcg/mips/mips32-dsp/shilov.c create mode 100644 tests/tcg/mips/mips32-dsp/shll_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/shll_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/shll_s_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/shll_s_w.c create mode 100644 tests/tcg/mips/mips32-dsp/shllv_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/shllv_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/shllv_s_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/shllv_s_w.c create mode 100644 tests/tcg/mips/mips32-dsp/shra_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/shra_r_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/shra_r_w.c create mode 100644 tests/tcg/mips/mips32-dsp/shrav_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/shrav_r_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/shrav_r_w.c create mode 100644 tests/tcg/mips/mips32-dsp/shrl_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/shrlv_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/subq_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/subq_s_ph.c create mode 100644 tests/tcg/mips/mips32-dsp/subq_s_w.c create mode 100644 tests/tcg/mips/mips32-dsp/subu_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/subu_s_qb.c create mode 100644 tests/tcg/mips/mips32-dsp/wrdsp.c create mode 100644 tests/tcg/mips/mips32-dspr2/Makefile create mode 100644 tests/tcg/mips/mips32-dspr2/absq_s_qb.c create mode 100644 tests/tcg/mips/mips32-dspr2/addqh_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/addqh_r_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/addqh_r_w.c create mode 100644 tests/tcg/mips/mips32-dspr2/addqh_w.c create mode 100644 tests/tcg/mips/mips32-dspr2/addu_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/addu_s_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/adduh_qb.c create mode 100644 tests/tcg/mips/mips32-dspr2/adduh_r_qb.c create mode 100644 tests/tcg/mips/mips32-dspr2/append.c create mode 100644 tests/tcg/mips/mips32-dspr2/balign.c create mode 100644 tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c create mode 100644 tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c create mode 100644 tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c create mode 100644 tests/tcg/mips/mips32-dspr2/dpa_w_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/dpax_w_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/dps_w_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/mul_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/mul_s_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/mulq_rs_w.c create mode 100644 tests/tcg/mips/mips32-dspr2/mulq_s_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/mulq_s_w.c create mode 100644 tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/precr_qb_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c create mode 100644 tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c create mode 100644 tests/tcg/mips/mips32-dspr2/prepend.c create mode 100644 tests/tcg/mips/mips32-dspr2/shra_qb.c create mode 100644 tests/tcg/mips/mips32-dspr2/shra_r_qb.c create mode 100644 tests/tcg/mips/mips32-dspr2/shrav_qb.c create mode 100644 tests/tcg/mips/mips32-dspr2/shrav_r_qb.c create mode 100644 tests/tcg/mips/mips32-dspr2/shrl_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/shrlv_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/subqh_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/subqh_r_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/subqh_r_w.c create mode 100644 tests/tcg/mips/mips32-dspr2/subqh_w.c create mode 100644 tests/tcg/mips/mips32-dspr2/subu_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/subu_s_ph.c create mode 100644 tests/tcg/mips/mips32-dspr2/subuh_qb.c create mode 100644 tests/tcg/mips/mips32-dspr2/subuh_r_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/Makefile create mode 100644 tests/tcg/mips/mips64-dsp/absq_s_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/absq_s_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/absq_s_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/absq_s_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/absq_s_w.c create mode 100644 tests/tcg/mips/mips64-dsp/addq_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/addq_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/addq_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/addq_s_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/addq_s_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/addq_s_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/addq_s_w.c create mode 100644 tests/tcg/mips/mips64-dsp/addsc.c create mode 100644 tests/tcg/mips/mips64-dsp/addu_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/addu_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/addu_s_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/addu_s_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/addwc.c create mode 100644 tests/tcg/mips/mips64-dsp/bitrev.c create mode 100644 tests/tcg/mips/mips64-dsp/bposge32.c create mode 100644 tests/tcg/mips/mips64-dsp/bposge64.c create mode 100644 tests/tcg/mips/mips64-dsp/cmp_eq_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/cmp_eq_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/cmp_eq_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/cmp_le_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/cmp_le_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/cmp_le_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/cmp_lt_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/cmp_lt_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/cmp_lt_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_eq_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_eq_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_le_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_le_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_lt_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_lt_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_eq_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_eq_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_le_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_le_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_lt_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_lt_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/dappend.c create mode 100644 tests/tcg/mips/mips64-dsp/dextp.c create mode 100644 tests/tcg/mips/mips64-dsp/dextpdp.c create mode 100644 tests/tcg/mips/mips64-dsp/dextpdpv.c create mode 100644 tests/tcg/mips/mips64-dsp/dextpv.c create mode 100644 tests/tcg/mips/mips64-dsp/dextr_l.c create mode 100644 tests/tcg/mips/mips64-dsp/dextr_r_l.c create mode 100644 tests/tcg/mips/mips64-dsp/dextr_r_w.c create mode 100644 tests/tcg/mips/mips64-dsp/dextr_rs_l.c create mode 100644 tests/tcg/mips/mips64-dsp/dextr_rs_w.c create mode 100644 tests/tcg/mips/mips64-dsp/dextr_s_h.c create mode 100644 tests/tcg/mips/mips64-dsp/dextr_w.c create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_l.c create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_r_l.c create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_r_w.c create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_rs_l.c create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_rs_w.c create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_s_h.c create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_w.c create mode 100644 tests/tcg/mips/mips64-dsp/dinsv.c create mode 100644 tests/tcg/mips/mips64-dsp/dmadd.c create mode 100644 tests/tcg/mips/mips64-dsp/dmaddu.c create mode 100644 tests/tcg/mips/mips64-dsp/dmsub.c create mode 100644 tests/tcg/mips/mips64-dsp/dmsubu.c create mode 100644 tests/tcg/mips/mips64-dsp/dmthlip.c create mode 100644 tests/tcg/mips/mips64-dsp/dpaq_s_w_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/dpaq_s_w_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/dpaq_sa_l_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/dpaq_sa_l_w.c create mode 100644 tests/tcg/mips/mips64-dsp/dpau_h_obl.c create mode 100644 tests/tcg/mips/mips64-dsp/dpau_h_obr.c create mode 100644 tests/tcg/mips/mips64-dsp/dpau_h_qbl.c create mode 100644 tests/tcg/mips/mips64-dsp/dpau_h_qbr.c create mode 100644 tests/tcg/mips/mips64-dsp/dpsq_s_w_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/dpsq_s_w_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/dpsq_sa_l_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/dpsq_sa_l_w.c create mode 100644 tests/tcg/mips/mips64-dsp/dpsu_h_obl.c create mode 100644 tests/tcg/mips/mips64-dsp/dpsu_h_obr.c create mode 100644 tests/tcg/mips/mips64-dsp/dpsu_h_qbl.c create mode 100644 tests/tcg/mips/mips64-dsp/dpsu_h_qbr.c create mode 100644 tests/tcg/mips/mips64-dsp/dshilo.c create mode 100644 tests/tcg/mips/mips64-dsp/dshilov.c create mode 100644 tests/tcg/mips/mips64-dsp/extp.c create mode 100644 tests/tcg/mips/mips64-dsp/extpdp.c create mode 100644 tests/tcg/mips/mips64-dsp/extpdpv.c create mode 100644 tests/tcg/mips/mips64-dsp/extpv.c create mode 100644 tests/tcg/mips/mips64-dsp/extr_r_w.c create mode 100644 tests/tcg/mips/mips64-dsp/extr_rs_w.c create mode 100644 tests/tcg/mips/mips64-dsp/extr_s_h.c create mode 100644 tests/tcg/mips/mips64-dsp/extr_w.c create mode 100644 tests/tcg/mips/mips64-dsp/extrv_r_w.c create mode 100644 tests/tcg/mips/mips64-dsp/extrv_rs_w.c create mode 100644 tests/tcg/mips/mips64-dsp/extrv_s_h.c create mode 100644 tests/tcg/mips/mips64-dsp/extrv_w.c create mode 100644 tests/tcg/mips/mips64-dsp/head.S create mode 100644 tests/tcg/mips/mips64-dsp/insv.c create mode 100644 tests/tcg/mips/mips64-dsp/io.h create mode 100644 tests/tcg/mips/mips64-dsp/lbux.c create mode 100644 tests/tcg/mips/mips64-dsp/ldx.c create mode 100644 tests/tcg/mips/mips64-dsp/lhx.c create mode 100644 tests/tcg/mips/mips64-dsp/lwx.c create mode 100644 tests/tcg/mips/mips64-dsp/madd.c create mode 100644 tests/tcg/mips/mips64-dsp/maddu.c create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_l_pwl.c create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_l_pwr.c create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_phl.c create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_phr.c create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_qhll.c create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_qhlr.c create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_qhrl.c create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_qhrr.c create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_phl.c create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_phr.c create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_qhll.c create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_qhlr.c create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_qhrl.c create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_qhrr.c create mode 100644 tests/tcg/mips/mips64-dsp/mfhi.c create mode 100644 tests/tcg/mips/mips64-dsp/mflo.c create mode 100644 tests/tcg/mips/mips64-dsp/mips_boot.lds create mode 100644 tests/tcg/mips/mips64-dsp/modsub.c create mode 100644 tests/tcg/mips/mips64-dsp/msub.c create mode 100644 tests/tcg/mips/mips64-dsp/msubu.c create mode 100644 tests/tcg/mips/mips64-dsp/mthi.c create mode 100644 tests/tcg/mips/mips64-dsp/mthlip.c create mode 100644 tests/tcg/mips/mips64-dsp/mtlo.c create mode 100644 tests/tcg/mips/mips64-dsp/muleq_s_pw_qhl.c create mode 100644 tests/tcg/mips/mips64-dsp/muleq_s_pw_qhr.c create mode 100644 tests/tcg/mips/mips64-dsp/muleq_s_w_phl.c create mode 100644 tests/tcg/mips/mips64-dsp/muleq_s_w_phr.c create mode 100644 tests/tcg/mips/mips64-dsp/muleu_s_ph_qbl.c create mode 100644 tests/tcg/mips/mips64-dsp/muleu_s_ph_qbr.c create mode 100644 tests/tcg/mips/mips64-dsp/muleu_s_qh_obl.c create mode 100644 tests/tcg/mips/mips64-dsp/muleu_s_qh_obr.c create mode 100644 tests/tcg/mips/mips64-dsp/mulq_rs_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/mulq_rs_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/mulsaq_s_l_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/mulsaq_s_w_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/mult.c create mode 100644 tests/tcg/mips/mips64-dsp/multu.c create mode 100644 tests/tcg/mips/mips64-dsp/packrl_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/packrl_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/pick_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/pick_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/pick_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/pick_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/pick_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/preceq_l_pwl.c create mode 100644 tests/tcg/mips/mips64-dsp/preceq_l_pwr.c create mode 100644 tests/tcg/mips/mips64-dsp/preceq_pw_qhl.c create mode 100644 tests/tcg/mips/mips64-dsp/preceq_pw_qhla.c create mode 100644 tests/tcg/mips/mips64-dsp/preceq_pw_qhr.c create mode 100644 tests/tcg/mips/mips64-dsp/preceq_pw_qhra.c create mode 100644 tests/tcg/mips/mips64-dsp/preceq_w_phl.c create mode 100644 tests/tcg/mips/mips64-dsp/preceq_w_phr.c create mode 100644 tests/tcg/mips/mips64-dsp/precequ_ph_qbl.c create mode 100644 tests/tcg/mips/mips64-dsp/precequ_ph_qbla.c create mode 100644 tests/tcg/mips/mips64-dsp/precequ_ph_qbr.c create mode 100644 tests/tcg/mips/mips64-dsp/precequ_ph_qbra.c create mode 100644 tests/tcg/mips/mips64-dsp/precequ_qh_obl.c create mode 100644 tests/tcg/mips/mips64-dsp/precequ_qh_obla.c create mode 100644 tests/tcg/mips/mips64-dsp/precequ_qh_obr.c create mode 100644 tests/tcg/mips/mips64-dsp/precequ_qh_obra.c create mode 100644 tests/tcg/mips/mips64-dsp/preceu_ph_qbl.c create mode 100644 tests/tcg/mips/mips64-dsp/preceu_ph_qbla.c create mode 100644 tests/tcg/mips/mips64-dsp/preceu_ph_qbr.c create mode 100644 tests/tcg/mips/mips64-dsp/preceu_ph_qbra.c create mode 100644 tests/tcg/mips/mips64-dsp/preceu_qh_obl.c create mode 100644 tests/tcg/mips/mips64-dsp/preceu_qh_obla.c create mode 100644 tests/tcg/mips/mips64-dsp/preceu_qh_obr.c create mode 100644 tests/tcg/mips/mips64-dsp/preceu_qh_obra.c create mode 100644 tests/tcg/mips/mips64-dsp/precr_ob_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/precr_sra_qh_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/precr_sra_r_qh_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/precrq_ob_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/precrq_ph_w.c create mode 100644 tests/tcg/mips/mips64-dsp/precrq_pw_l.c create mode 100644 tests/tcg/mips/mips64-dsp/precrq_qb_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/precrq_qh_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/precrq_rs_ph_w.c create mode 100644 tests/tcg/mips/mips64-dsp/precrq_rs_qh_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/precrqu_s_ob_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/precrqu_s_qb_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/prependd.c create mode 100644 tests/tcg/mips/mips64-dsp/prependw.c create mode 100644 tests/tcg/mips/mips64-dsp/printf.c create mode 100644 tests/tcg/mips/mips64-dsp/raddu_l_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/raddu_w_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/rddsp.c create mode 100644 tests/tcg/mips/mips64-dsp/repl_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/repl_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/repl_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/repl_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/repl_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/replv_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/replv_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/replv_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/replv_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/shilo.c create mode 100644 tests/tcg/mips/mips64-dsp/shilov.c create mode 100644 tests/tcg/mips/mips64-dsp/shll_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/shll_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/shll_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/shll_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/shll_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/shll_s_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/shll_s_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/shll_s_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/shll_s_w.c create mode 100644 tests/tcg/mips/mips64-dsp/shllv_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/shllv_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/shllv_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/shllv_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/shllv_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/shllv_s_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/shllv_s_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/shllv_s_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/shllv_s_w.c create mode 100644 tests/tcg/mips/mips64-dsp/shra_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/shra_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/shra_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/shra_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/shra_r_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/shra_r_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/shra_r_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/shra_r_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/shra_r_w.c create mode 100644 tests/tcg/mips/mips64-dsp/shrav_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/shrav_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/shrav_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/shrav_r_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/shrav_r_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/shrav_r_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/shrav_r_w.c create mode 100644 tests/tcg/mips/mips64-dsp/shrl_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/shrl_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/shrl_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/shrlv_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/shrlv_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/shrlv_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/subq_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/subq_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/subq_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/subq_s_ph.c create mode 100644 tests/tcg/mips/mips64-dsp/subq_s_pw.c create mode 100644 tests/tcg/mips/mips64-dsp/subq_s_qh.c create mode 100644 tests/tcg/mips/mips64-dsp/subq_s_w.c create mode 100644 tests/tcg/mips/mips64-dsp/subu_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/subu_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/subu_s_ob.c create mode 100644 tests/tcg/mips/mips64-dsp/subu_s_qb.c create mode 100644 tests/tcg/mips/mips64-dsp/wrdsp.c create mode 100644 tests/tcg/mips/mips64-dspr2/.directory create mode 100644 tests/tcg/mips/mips64-dspr2/Makefile create mode 100644 tests/tcg/mips/mips64-dspr2/absq_s_qb.c create mode 100644 tests/tcg/mips/mips64-dspr2/addqh_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/addqh_r_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/addqh_r_w.c create mode 100644 tests/tcg/mips/mips64-dspr2/addqh_w.c create mode 100644 tests/tcg/mips/mips64-dspr2/addu_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/addu_qh.c create mode 100644 tests/tcg/mips/mips64-dspr2/addu_s_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/addu_s_qh.c create mode 100644 tests/tcg/mips/mips64-dspr2/adduh_ob.c create mode 100644 tests/tcg/mips/mips64-dspr2/adduh_qb.c create mode 100644 tests/tcg/mips/mips64-dspr2/adduh_r_ob.c create mode 100644 tests/tcg/mips/mips64-dspr2/adduh_r_qb.c create mode 100644 tests/tcg/mips/mips64-dspr2/append.c create mode 100644 tests/tcg/mips/mips64-dspr2/balign.c create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_eq_ob.c create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_eq_qb.c create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_le_ob.c create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_le_qb.c create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_lt_ob.c create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_lt_qb.c create mode 100644 tests/tcg/mips/mips64-dspr2/dbalign.c create mode 100644 tests/tcg/mips/mips64-dspr2/dpa_w_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/dpa_w_qh.c create mode 100644 tests/tcg/mips/mips64-dspr2/dpaqx_s_w_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/dpaqx_sa_w_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/dpax_w_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/dps_w_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/dps_w_qh.c create mode 100644 tests/tcg/mips/mips64-dspr2/dpsqx_s_w_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/dpsqx_sa_w_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/dpsx_w_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/head.S create mode 100644 tests/tcg/mips/mips64-dspr2/io.h create mode 100644 tests/tcg/mips/mips64-dspr2/mips_boot.lds create mode 100644 tests/tcg/mips/mips64-dspr2/mul_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/mul_s_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/mulq_rs_w.c create mode 100644 tests/tcg/mips/mips64-dspr2/mulq_s_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/mulq_s_w.c create mode 100644 tests/tcg/mips/mips64-dspr2/mulsa_w_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/mulsaq_s_w_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/precr_qb_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/precr_sra_ph_w.c create mode 100644 tests/tcg/mips/mips64-dspr2/precr_sra_r_ph_w.c create mode 100644 tests/tcg/mips/mips64-dspr2/prepend.c create mode 100644 tests/tcg/mips/mips64-dspr2/printf.c create mode 100644 tests/tcg/mips/mips64-dspr2/shra_qb.c create mode 100644 tests/tcg/mips/mips64-dspr2/shra_r_qb.c create mode 100644 tests/tcg/mips/mips64-dspr2/shrav_ob.c create mode 100644 tests/tcg/mips/mips64-dspr2/shrav_qb.c create mode 100644 tests/tcg/mips/mips64-dspr2/shrav_r_ob.c create mode 100644 tests/tcg/mips/mips64-dspr2/shrav_r_qb.c create mode 100644 tests/tcg/mips/mips64-dspr2/shrl_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/shrlv_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/subqh_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/subqh_r_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/subqh_r_w.c create mode 100644 tests/tcg/mips/mips64-dspr2/subqh_w.c create mode 100644 tests/tcg/mips/mips64-dspr2/subu_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/subu_qh.c create mode 100644 tests/tcg/mips/mips64-dspr2/subu_s_ph.c create mode 100644 tests/tcg/mips/mips64-dspr2/subu_s_qh.c create mode 100644 tests/tcg/mips/mips64-dspr2/subuh_ob.c create mode 100644 tests/tcg/mips/mips64-dspr2/subuh_qb.c create mode 100644 tests/tcg/mips/mips64-dspr2/subuh_r_ob.c create mode 100644 tests/tcg/mips/mips64-dspr2/subuh_r_qb.c diff --git a/tests/tcg/mips/mips32-dsp/Makefile b/tests/tcg/mips/mips32-dsp/Makefile new file mode 100644 index 0000000000..c3a0a00944 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/Makefile @@ -0,0 +1,136 @@ +-include ../../config-host.mak + +CROSS=mips64el-unknown-linux-gnu- + +SIM=qemu-mipsel +SIM_FLAGS=-cpu 74Kf + +CC = $(CROSS)gcc +CFLAGS = -mabi=32 -march=mips32r2 -mgp32 -mdsp -static + +TESTCASES = absq_s_ph.tst +TESTCASES += absq_s_w.tst +TESTCASES += addq_ph.tst +TESTCASES += addq_s_ph.tst +TESTCASES += addq_s_w.tst +TESTCASES += addsc.tst +TESTCASES += addu_qb.tst +TESTCASES += addu_s_qb.tst +TESTCASES += addwc.tst +TESTCASES += bitrev.tst +TESTCASES += bposge32.tst +TESTCASES += cmp_eq_ph.tst +TESTCASES += cmpgu_eq_qb.tst +TESTCASES += cmpgu_le_qb.tst +TESTCASES += cmpgu_lt_qb.tst +TESTCASES += cmp_le_ph.tst +TESTCASES += cmp_lt_ph.tst +TESTCASES += cmpu_eq_qb.tst +TESTCASES += cmpu_le_qb.tst +TESTCASES += cmpu_lt_qb.tst +TESTCASES += dpaq_sa_l_w.tst +TESTCASES += dpaq_s_w_ph.tst +TESTCASES += dpau_h_qbl.tst +TESTCASES += dpau_h_qbr.tst +TESTCASES += dpsq_sa_l_w.tst +TESTCASES += dpsq_s_w_ph.tst +TESTCASES += dpsu_h_qbl.tst +TESTCASES += dpsu_h_qbr.tst +TESTCASES += extp.tst +TESTCASES += extpdp.tst +TESTCASES += extpdpv.tst +TESTCASES += extpv.tst +TESTCASES += extr_rs_w.tst +TESTCASES += extr_r_w.tst +TESTCASES += extr_s_h.tst +TESTCASES += extrv_rs_w.tst +TESTCASES += extrv_r_w.tst +TESTCASES += extrv_s_h.tst +TESTCASES += extrv_w.tst +TESTCASES += extr_w.tst +TESTCASES += insv.tst +TESTCASES += lbux.tst +TESTCASES += lhx.tst +TESTCASES += lwx.tst +TESTCASES += madd.tst +TESTCASES += maddu.tst +TESTCASES += maq_sa_w_phl.tst +TESTCASES += maq_sa_w_phr.tst +TESTCASES += maq_s_w_phl.tst +TESTCASES += maq_s_w_phr.tst +TESTCASES += mfhi.tst +TESTCASES += mflo.tst +TESTCASES += modsub.tst +TESTCASES += msub.tst +TESTCASES += msubu.tst +TESTCASES += mthi.tst +TESTCASES += mthlip.tst +TESTCASES += mtlo.tst +TESTCASES += muleq_s_w_phl.tst +TESTCASES += muleq_s_w_phr.tst +TESTCASES += muleu_s_ph_qbl.tst +TESTCASES += muleu_s_ph_qbr.tst +TESTCASES += mulq_rs_ph.tst +TESTCASES += mult.tst +TESTCASES += multu.tst +TESTCASES += packrl_ph.tst +TESTCASES += pick_ph.tst +TESTCASES += pick_qb.tst +TESTCASES += precequ_ph_qbla.tst +TESTCASES += precequ_ph_qbl.tst +TESTCASES += precequ_ph_qbra.tst +TESTCASES += precequ_ph_qbr.tst +TESTCASES += preceq_w_phl.tst +TESTCASES += preceq_w_phr.tst +TESTCASES += preceu_ph_qbla.tst +TESTCASES += preceu_ph_qbl.tst +TESTCASES += preceu_ph_qbra.tst +TESTCASES += preceu_ph_qbr.tst +TESTCASES += precrq_ph_w.tst +TESTCASES += precrq_qb_ph.tst +TESTCASES += precrq_rs_ph_w.tst +TESTCASES += precrqu_s_qb_ph.tst +TESTCASES += raddu_w_qb.tst +TESTCASES += rddsp.tst +TESTCASES += repl_ph.tst +TESTCASES += repl_qb.tst +TESTCASES += replv_ph.tst +TESTCASES += replv_qb.tst +TESTCASES += shilo.tst +TESTCASES += shilov.tst +TESTCASES += shll_ph.tst +TESTCASES += shll_qb.tst +TESTCASES += shll_s_ph.tst +TESTCASES += shll_s_w.tst +TESTCASES += shllv_ph.tst +TESTCASES += shllv_qb.tst +TESTCASES += shllv_s_ph.tst +TESTCASES += shllv_s_w.tst +TESTCASES += shra_ph.tst +TESTCASES += shra_r_ph.tst +TESTCASES += shra_r_w.tst +TESTCASES += shrav_ph.tst +TESTCASES += shrav_r_ph.tst +TESTCASES += shrav_r_w.tst +TESTCASES += shrl_qb.tst +TESTCASES += shrlv_qb.tst +TESTCASES += subq_ph.tst +TESTCASES += subq_s_ph.tst +TESTCASES += subq_s_w.tst +TESTCASES += subu_qb.tst +TESTCASES += subu_s_qb.tst +TESTCASES += wrdsp.tst + +all: $(TESTCASES) + +%.tst: %.c + $(CC) $(CFLAGS) $< -o $@ + +check: $(TESTCASES) + @for case in $(TESTCASES); do \ + echo $(SIM) $(SIM_FLAGS) ./$$case;\ + $(SIM) $(SIM_FLAGS) ./$$case; \ + done + +clean: + $(RM) -rf $(TESTCASES) diff --git a/tests/tcg/mips/mips32-dsp/absq_s_ph.c b/tests/tcg/mips/mips32-dsp/absq_s_ph.c new file mode 100644 index 0000000000..aa8411202e --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/absq_s_ph.c @@ -0,0 +1,31 @@ +#include +#include + + +int main() +{ + int rd, rt; + int result; + + rt = 0x10017EFD; + result = 0x10017EFD; + + __asm + ("absq_s.ph %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + rt = 0x8000A536; + result = 0x7FFF5ACA; + + __asm + ("absq_s.ph %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/absq_s_w.c b/tests/tcg/mips/mips32-dsp/absq_s_w.c new file mode 100644 index 0000000000..3f52a48039 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/absq_s_w.c @@ -0,0 +1,37 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x80000000; + result = 0x7FFFFFFF; + __asm + ("absq_s.w %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + rt = 0x80030000; + result = 0x7FFD0000; + __asm + ("absq_s.w %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + rt = 0x31036080; + result = 0x31036080; + __asm + ("absq_s.w %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/addq_ph.c b/tests/tcg/mips/mips32-dsp/addq_ph.c new file mode 100644 index 0000000000..96a549637b --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/addq_ph.c @@ -0,0 +1,46 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int dsp; + int result; + + rs = 0xFFFFFFFF; + rt = 0x10101010; + result = 0x100F100F; + __asm + ("addq.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(result == rd); + + rs = 0x3712847D; + rt = 0x0031AF2D; + result = 0x374333AA; + __asm + ("addq.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(result == rd); + + rs = 0x7fff847D; + rt = 0x0031AF2D; + result = 0x803033AA; + __asm + ("addq.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(result == rd); + + __asm("rddsp %0\n\t" + : "=r"(dsp) + ); + assert(((dsp >> 20) & 0x01) == 1); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/addq_s_ph.c b/tests/tcg/mips/mips32-dsp/addq_s_ph.c new file mode 100644 index 0000000000..5f865f6cff --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/addq_s_ph.c @@ -0,0 +1,69 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int dsp; + int result; + + rs = 0xFFFFFFFF; + rt = 0x10101010; + result = 0x100F100F; + __asm + ("addq_s.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(result == rd); + + rs = 0x3712847D; + rt = 0x0031AF2D; + result = 0x37438000; + __asm + ("addq_s.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(result == rd); + + __asm + ("rddsp %0\n\t" + : "=r"(dsp) + ); + assert(((dsp >> 20) & 0x01) == 1); + + rs = 0x7fff847D; + rt = 0x0031AF2D; + result = 0x7fff8000; + __asm + ("addq_s.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(result == rd); + + __asm + ("rddsp %0\n\t" + : "=r"(dsp) + ); + assert(((dsp >> 20) & 0x01) == 1); + + rs = 0x8030847D; + rt = 0x8a00AF2D; + result = 0x80008000; + __asm + ("addq_s.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(result == rd); + + __asm + ("rddsp %0\n\t" + : "=r"(dsp) + ); + assert(((dsp >> 20) & 0x01) == 1); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/addq_s_w.c b/tests/tcg/mips/mips32-dsp/addq_s_w.c new file mode 100644 index 0000000000..1e13acf68f --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/addq_s_w.c @@ -0,0 +1,44 @@ +#include +#include + + +int main() +{ + int rd, rs, rt; + int result; + + rt = 0x10017EFD; + rs = 0x11111111; + result = 0x2112900e; + + __asm + ("addq_s.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + rt = 0x80017EFD; + rs = 0x81111111; + result = 0x80000000; + + __asm + ("addq_s.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + rt = 0x7fffffff; + rs = 0x01111111; + result = 0x7fffffff; + + __asm + ("addq_s.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/addsc.c b/tests/tcg/mips/mips32-dsp/addsc.c new file mode 100644 index 0000000000..ace749f667 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/addsc.c @@ -0,0 +1,33 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int dsp; + int result; + + rs = 0x0000000F; + rt = 0x00000001; + result = 0x00000010; + __asm + ("addsc %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + rs = 0xFFFF0FFF; + rt = 0x00010111; + result = 0x00001110; + __asm + ("addsc %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + assert(((dsp >> 13) & 0x01) == 1); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/addu_qb.c b/tests/tcg/mips/mips32-dsp/addu_qb.c new file mode 100644 index 0000000000..23ba2e90d1 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/addu_qb.c @@ -0,0 +1,35 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int dsp; + int result; + + rs = 0x00FF00FF; + rt = 0x00010001; + result = 0x00000000; + __asm + ("addu.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + assert(((dsp >> 20) & 0x01) == 1); + + rs = 0xFFFF1111; + rt = 0x00020001; + result = 0xFF011112; + __asm + ("addu.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + assert(((dsp >> 20) & 0x01) == 1); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/addu_s_qb.c b/tests/tcg/mips/mips32-dsp/addu_s_qb.c new file mode 100644 index 0000000000..fe7fd3e6aa --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/addu_s_qb.c @@ -0,0 +1,35 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int dsp; + int result; + + rs = 0x10FF01FF; + rt = 0x10010001; + result = 0x20FF01FF; + __asm + ("addu_s.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + assert(((dsp >> 20) & 0x1) == 1); + + rs = 0xFFFF1111; + rt = 0x00020001; + result = 0xFFFF1112; + __asm + ("addu_s.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + assert(((dsp >> 20) & 0x1) == 1); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/addwc.c b/tests/tcg/mips/mips32-dsp/addwc.c new file mode 100644 index 0000000000..8a8d81fab4 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/addwc.c @@ -0,0 +1,49 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int dspi, dspo; + int result; + + rs = 0x10FF01FF; + rt = 0x10010001; + dspi = 0x00002000; + result = 0x21000201; + __asm + ("wrdsp %3\n" + "addwc %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt), "r"(dspi) + ); + assert(rd == result); + + rs = 0xFFFF1111; + rt = 0x00020001; + dspi = 0x00; + result = 0x00011112; + __asm + ("wrdsp %3\n" + "addwc %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt), "r"(dspi) + ); + assert(rd == result); + + rs = 0x8FFF1111; + rt = 0x80020001; + dspi = 0x00; + result = 0x10011112; + __asm + ("wrdsp %4\n" + "addwc %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspo) + : "r"(rs), "r"(rt), "r"(dspi) + ); + assert(rd == result); + assert(((dspo >> 20) & 0x01) == 1); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/bitrev.c b/tests/tcg/mips/mips32-dsp/bitrev.c new file mode 100644 index 0000000000..04d8a3844e --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/bitrev.c @@ -0,0 +1,20 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x12345678; + result = 0x00001E6A; + + __asm + ("bitrev %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/bposge32.c b/tests/tcg/mips/mips32-dsp/bposge32.c new file mode 100644 index 0000000000..d25417ea77 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/bposge32.c @@ -0,0 +1,44 @@ +#include +#include + +int main() +{ + int dsp, sum; + int result; + + dsp = 0x20; + sum = 0x01; + result = 0x02; + + __asm + ("wrdsp %1\n\t" + "bposge32 test1\n\t" + "nop\n\t" + "addi %0, 0xA2\n\t" + "nop\n\t" + "test1:\n\t" + "addi %0, 0x01\n\t" + : "+r"(sum) + : "r"(dsp) + ); + assert(sum == result); + + dsp = 0x10; + sum = 0x01; + result = 0xA4; + + __asm + ("wrdsp %1\n\t" + "bposge32 test2\n\t" + "nop\n\t" + "addi %0, 0xA2\n\t" + "nop\n\t" + "test2:\n\t" + "addi %0, 0x01\n\t" + : "+r"(sum) + : "r"(dsp) + ); + assert(sum == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/cmp_eq_ph.c b/tests/tcg/mips/mips32-dsp/cmp_eq_ph.c new file mode 100644 index 0000000000..957bd88ce0 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/cmp_eq_ph.c @@ -0,0 +1,35 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x11777066; + rt = 0x55AA33FF; + result = 0x00; + __asm + ("cmp.eq.ph %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + rd = (rd >> 24) & 0x03; + assert(rd == result); + + rs = 0x11777066; + rt = 0x11777066; + result = 0x03; + __asm + ("cmp.eq.ph %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + rd = (rd >> 24) & 0x03; + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/cmp_le_ph.c b/tests/tcg/mips/mips32-dsp/cmp_le_ph.c new file mode 100644 index 0000000000..356f156c5d --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/cmp_le_ph.c @@ -0,0 +1,35 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x11777066; + rt = 0x55AA33FF; + result = 0x02; + __asm + ("cmp.le.ph %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + rd = (rd >> 24) & 0x03; + assert(rd == result); + + rs = 0x11777066; + rt = 0x11777066; + result = 0x03; + __asm + ("cmp.le.ph %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + rd = (rd >> 24) & 0x03; + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/cmp_lt_ph.c b/tests/tcg/mips/mips32-dsp/cmp_lt_ph.c new file mode 100644 index 0000000000..3fb4827ad7 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/cmp_lt_ph.c @@ -0,0 +1,35 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x11777066; + rt = 0x55AA33FF; + result = 0x02; + __asm + ("cmp.lt.ph %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + rd = (rd >> 24) & 0x03; + assert(rd == result); + + rs = 0x11777066; + rt = 0x11777066; + result = 0x00; + __asm + ("cmp.lt.ph %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + rd = (rd >> 24) & 0x03; + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c b/tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c new file mode 100644 index 0000000000..2615c84c75 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c @@ -0,0 +1,31 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x02; + __asm + ("cmpgu.eq.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + assert(rd == result); + + rs = 0x11777066; + rt = 0x11777066; + result = 0x0F; + __asm + ("cmpgu.eq.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c b/tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c new file mode 100644 index 0000000000..65d0813c3b --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c @@ -0,0 +1,31 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x0F; + __asm + ("cmpgu.le.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + assert(rd == result); + + rs = 0x11777066; + rt = 0x11766066; + result = 0x09; + __asm + ("cmpgu.le.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c b/tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c new file mode 100644 index 0000000000..7dddad9853 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c @@ -0,0 +1,31 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x0D; + __asm + ("cmpgu.lt.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + assert(rd == result); + + rs = 0x11777066; + rt = 0x11766066; + result = 0x00; + __asm + ("cmpgu.lt.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c b/tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c new file mode 100644 index 0000000000..680f2a1999 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c @@ -0,0 +1,35 @@ +#include +#include + +int main() +{ + int rs, rt; + int dsp; + int result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x02; + __asm + ("cmpu.eq.qb %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + assert(dsp == result); + + rs = 0x11777066; + rt = 0x11777066; + result = 0x0F; + __asm + ("cmpu.eq.qb %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + assert(dsp == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/cmpu_le_qb.c b/tests/tcg/mips/mips32-dsp/cmpu_le_qb.c new file mode 100644 index 0000000000..43cfa509ca --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/cmpu_le_qb.c @@ -0,0 +1,35 @@ +#include +#include + +int main() +{ + int rs, rt; + int dsp; + int result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x0F; + __asm + ("cmpu.le.qb %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + assert(dsp == result); + + rs = 0x11777066; + rt = 0x11777066; + result = 0x0F; + __asm + ("cmpu.le.qb %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + assert(dsp == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c b/tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c new file mode 100644 index 0000000000..074ca5b402 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c @@ -0,0 +1,35 @@ +#include +#include + +int main() +{ + int rs, rt; + int dsp; + int result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x0D; + __asm + ("cmpu.lt.qb %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + assert(dsp == result); + + rs = 0x11777066; + rt = 0x11777066; + result = 0x00; + __asm + ("cmpu.lt.qb %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + assert(dsp == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c b/tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c new file mode 100644 index 0000000000..a6425b6edc --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c @@ -0,0 +1,31 @@ +#include +#include + +int main() +{ + int rs, rt, dsp; + int ach = 0, acl = 0; + int resulth, resultl, resultdsp; + + rs = 0x800000FF; + rt = 0x80000002; + resulth = 0x00; + resultl = 0x800003FB; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpaq_s.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = dsp >> 17 & 0x01; + assert(dsp == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c b/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c new file mode 100644 index 0000000000..ce864844d9 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c @@ -0,0 +1,77 @@ +#include +#include + +int main() +{ + int rs, rt, dsp; + int ach = 0, acl = 0; + int resulth, resultl, resultdsp; + + rs = 0x80000000; + rt = 0x80000000; + resulth = 0x7FFFFFFF; + resultl = 0xFFFFFFFF; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %0, $ac1\n\t" + "dpaq_sa.l.w $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + assert(dsp == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + ach = 0x12; + acl = 0x48; + rs = 0x80000000; + rt = 0x80000000; + + resulth = 0x7FFFFFFF; + resultl = 0xFFFFFFFF; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %0, $ac1\n\t" + "dpaq_sa.l.w $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + assert(dsp == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + ach = 0x741532A0; + acl = 0xfceabb08; + rs = 0x80000000; + rt = 0x80000000; + + resulth = 0x7fffffff; + resultl = 0xffffffff; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %0, $ac1\n\t" + "dpaq_sa.l.w $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + assert(dsp == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/dpau_h_qbl.c b/tests/tcg/mips/mips32-dsp/dpau_h_qbl.c new file mode 100644 index 0000000000..6017b5e73a --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/dpau_h_qbl.c @@ -0,0 +1,27 @@ +#include +#include + +int main() +{ + int rs, rt; + int ach = 5, acl = 3; + int resulth, resultl; + + rs = 0x800000FF; + rt = 0x80000002; + resulth = 0x05; + resultl = 0x4003; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpau.h.qbl $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/dpau_h_qbr.c b/tests/tcg/mips/mips32-dsp/dpau_h_qbr.c new file mode 100644 index 0000000000..e4abb2e2af --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/dpau_h_qbr.c @@ -0,0 +1,27 @@ +#include +#include + +int main() +{ + int rs, rt; + int ach = 5, acl = 3; + int resulth, resultl; + + rs = 0x800000FF; + rt = 0x80000002; + resulth = 0x05; + resultl = 0x0201; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpau.h.qbr $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c b/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c new file mode 100644 index 0000000000..22ab4d57ba --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c @@ -0,0 +1,45 @@ +#include +#include + +int main() +{ + int rs, rt; + int ach = 5, acl = 5; + int resulth, resultl; + + rs = 0xBC0123AD; + rt = 0x01643721; + resulth = 0x04; + resultl = 0xEE9794A3; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsq_s.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + + ach = 0x1424Ef1f; + acl = 0x1035219A; + rs = 0x800083AD; + rt = 0x80003721; + resulth = 0x1424ef1e; + resultl = 0x577ed901; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsq_s.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c b/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c new file mode 100644 index 0000000000..b7b73fdb66 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c @@ -0,0 +1,55 @@ +#include +#include + +int main() +{ + int rs, rt, dsp; + int ach = 5, acl = 5; + int resulth, resultl, resultdsp; + + rs = 0xBC0123AD; + rt = 0x01643721; + resulth = 0xfdf4cbe0; + resultl = 0xd138776b; + resultdsp = 0x00; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsq_sa.l.w $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + assert(dsp == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + ach = 0x54321123; + acl = 5; + rs = 0x80000000; + rt = 0x80000000; + + resulth = 0xd4321123; + resultl = 0x06; + resultdsp = 0x01; + + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsq_sa.l.w $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + assert(dsp == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c b/tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c new file mode 100644 index 0000000000..94e2bf6254 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c @@ -0,0 +1,27 @@ +#include +#include + +int main() +{ + int rs, rt; + int ach = 5, acl = 5; + int resulth, resultl; + + rs = 0xBC0123AD; + rt = 0x01643721; + resulth = 0x04; + resultl = 0xFFFFFEE5; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsu.h.qbl $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c b/tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c new file mode 100644 index 0000000000..a1e6635631 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c @@ -0,0 +1,27 @@ +#include +#include + +int main() +{ + int rs, rt; + int ach = 5, acl = 5; + int resulth, resultl; + + rs = 0xBC0123AD; + rt = 0x01643721; + resulth = 0x04; + resultl = 0xFFFFE233; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsu.h.qbr $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/extp.c b/tests/tcg/mips/mips32-dsp/extp.c new file mode 100644 index 0000000000..21a67af216 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/extp.c @@ -0,0 +1,44 @@ +#include +#include + +int main() +{ + int rt, ach, acl, dsp; + int result; + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x07; + result = 0x000C; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extp %0, $ac1, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 14) & 0x01; + assert(dsp == 0); + assert(result == rt); + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x01; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extp %0, $ac1, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 14) & 0x01; + assert(dsp == 1); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/extpdp.c b/tests/tcg/mips/mips32-dsp/extpdp.c new file mode 100644 index 0000000000..15ba0828fb --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/extpdp.c @@ -0,0 +1,46 @@ +#include +#include + +int main() +{ + int rt, ach, acl, dsp, pos, efi; + int result; + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x07; + result = 0x000C; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extpdp %0, $ac1, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(ach), "r"(acl) + ); + pos = dsp & 0x3F; + efi = (dsp >> 14) & 0x01; + assert(pos == 3); + assert(efi == 0); + assert(result == rt); + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x01; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extpdp %0, $ac1, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(ach), "r"(acl) + ); + efi = (dsp >> 14) & 0x01; + assert(efi == 1); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/extpdpv.c b/tests/tcg/mips/mips32-dsp/extpdpv.c new file mode 100644 index 0000000000..f5774eed3c --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/extpdpv.c @@ -0,0 +1,47 @@ +#include +#include + +int main() +{ + int rt, rs, ach, acl, dsp, pos, efi; + int result; + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x07; + rs = 0x03; + result = 0x000C; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extpdpv %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(ach), "r"(acl), "r"(rs) + ); + pos = dsp & 0x3F; + efi = (dsp >> 14) & 0x01; + assert(pos == 3); + assert(efi == 0); + assert(result == rt); + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x01; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extpdpv %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(ach), "r"(acl), "r"(rs) + ); + efi = (dsp >> 14) & 0x01; + assert(efi == 1); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/extpv.c b/tests/tcg/mips/mips32-dsp/extpv.c new file mode 100644 index 0000000000..401b94afad --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/extpv.c @@ -0,0 +1,45 @@ +#include +#include + +int main() +{ + int rt, ac, ach, acl, dsp; + int result; + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x07; + ac = 0x03; + result = 0x000C; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extpv %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(ach), "r"(acl), "r"(ac) + ); + dsp = (dsp >> 14) & 0x01; + assert(dsp == 0); + assert(result == rt); + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x01; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extpv %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(ach), "r"(acl), "r"(ac) + ); + dsp = (dsp >> 14) & 0x01; + assert(dsp == 1); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/extr_r_w.c b/tests/tcg/mips/mips32-dsp/extr_r_w.c new file mode 100644 index 0000000000..0beeefd366 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/extr_r_w.c @@ -0,0 +1,48 @@ +#include +#include + +int main() +{ + int rt, ach, acl, dsp; + int result; + + ach = 0x05; + acl = 0xB4CB; + result = 0xA0001699; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_r.w %0, $ac1, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 1); + assert(result == rt); + + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + ach = 0x01; + acl = 0xB4CB; + result = 0x10000B4D; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_r.w %0, $ac1, 0x04\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/extr_rs_w.c b/tests/tcg/mips/mips32-dsp/extr_rs_w.c new file mode 100644 index 0000000000..24c748db20 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/extr_rs_w.c @@ -0,0 +1,48 @@ +#include +#include + +int main() +{ + int rt, ach, acl, dsp; + int result; + + ach = 0x05; + acl = 0xB4CB; + result = 0x7FFFFFFF; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_rs.w %0, $ac1, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 1); + assert(result == rt); + + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + ach = 0x01; + acl = 0xB4CB; + result = 0x10000B4D; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_rs.w %0, $ac1, 0x04\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/extr_s_h.c b/tests/tcg/mips/mips32-dsp/extr_s_h.c new file mode 100644 index 0000000000..b2129134c8 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/extr_s_h.c @@ -0,0 +1,63 @@ +#include +#include + +int main() +{ + int rt, ach, acl, dsp; + int result; + + ach = 0x05; + acl = 0xB4CB; + result = 0x00007FFF; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_s.h %0, $ac1, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 1); + assert(result == rt); + + ach = 0xffffffff; + acl = 0x12344321; + result = 0xFFFF8000; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_s.h %0, $ac1, 0x08\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 1); + assert(result == rt); + + /* Clear dsp */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + ach = 0x00; + acl = 0x4321; + result = 0x432; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_s.h %0, $ac1, 0x04\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/extr_w.c b/tests/tcg/mips/mips32-dsp/extr_w.c new file mode 100644 index 0000000000..02ab9ecaae --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/extr_w.c @@ -0,0 +1,48 @@ +#include +#include + +int main() +{ + int rt, ach, acl, dsp; + int result; + + ach = 0x05; + acl = 0xB4CB; + result = 0xA0001699; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr.w %0, $ac1, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 1); + assert(result == rt); + + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + ach = 0x01; + acl = 0xB4CB; + result = 0x10000B4C; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr.w %0, $ac1, 0x04\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/extrv_r_w.c b/tests/tcg/mips/mips32-dsp/extrv_r_w.c new file mode 100644 index 0000000000..005807b142 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/extrv_r_w.c @@ -0,0 +1,54 @@ +#include +#include + +int main() +{ + int rt, rs, ach, acl, dsp; + int result; + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x07; + rs = 0x03; + result = 0xA0001699; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_r.w %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 1); + assert(result == rt); + + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + rs = 4; + ach = 0x01; + acl = 0xB4CB; + result = 0x10000B4D; + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_r.w %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/extrv_rs_w.c b/tests/tcg/mips/mips32-dsp/extrv_rs_w.c new file mode 100644 index 0000000000..c2d8513bb6 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/extrv_rs_w.c @@ -0,0 +1,52 @@ +#include +#include + +int main() +{ + int rt, rs, ach, acl, dsp; + int result; + + rs = 0x03; + ach = 0x05; + acl = 0xB4CB; + result = 0x7FFFFFFF; + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_rs.w %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 1); + assert(result == rt); + + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + rs = 0x04; + ach = 0x01; + acl = 0xB4CB; + result = 0x10000B4D; + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_rs.w %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/extrv_s_h.c b/tests/tcg/mips/mips32-dsp/extrv_s_h.c new file mode 100644 index 0000000000..8c13b5eda5 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/extrv_s_h.c @@ -0,0 +1,71 @@ +#include +#include + +int main() +{ + int rt, rs, ach, acl, dsp; + int result; + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x07; + rs = 0x03; + result = 0x00007FFF; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_s.h %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 1); + assert(result == rt); + + rs = 0x08; + ach = 0xffffffff; + acl = 0x12344321; + result = 0xFFFF8000; + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_s.h %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 1); + assert(result == rt); + + /* Clear dsp */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + rs = 0x04; + ach = 0x00; + acl = 0x4321; + result = 0x432; + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_s.h %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/extrv_w.c b/tests/tcg/mips/mips32-dsp/extrv_w.c new file mode 100644 index 0000000000..9cb493df39 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/extrv_w.c @@ -0,0 +1,54 @@ +#include +#include + +int main() +{ + int rt, rs, ach, acl, dsp; + int result; + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x07; + rs = 0x03; + result = 0xA0001699; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv.w %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 1); + assert(result == rt); + + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + rs = 4; + ach = 0x01; + acl = 0xB4CB; + result = 0x10000B4C; + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv.w %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/insv.c b/tests/tcg/mips/mips32-dsp/insv.c new file mode 100644 index 0000000000..7e3b047606 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/insv.c @@ -0,0 +1,23 @@ +#include +#include + +int main() +{ + int rt, rs, dsp; + int result; + + /* msb = 10, lsb = 5 */ + dsp = 0x305; + rt = 0x12345678; + rs = 0x87654321; + result = 0x12345338; + __asm + ("wrdsp %2, 0x03\n\t" + "insv %0, %1\n\t" + : "+r"(rt) + : "r"(rs), "r"(dsp) + ); + assert(rt == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/lbux.c b/tests/tcg/mips/mips32-dsp/lbux.c new file mode 100644 index 0000000000..2337abea2a --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/lbux.c @@ -0,0 +1,25 @@ +#include +#include + +int main(void) +{ + int value, rd; + int *p; + unsigned long addr, index; + int result; + + value = 0xBCDEF389; + p = &value; + addr = (unsigned long)p; + index = 0; + result = value & 0xFF; + __asm + ("lbux %0, %1(%2)\n\t" + : "=r"(rd) + : "r"(index), "r"(addr) + ); + + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/lhx.c b/tests/tcg/mips/mips32-dsp/lhx.c new file mode 100644 index 0000000000..10be3b385f --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/lhx.c @@ -0,0 +1,25 @@ +#include +#include + +int main(void) +{ + int value, rd; + int *p; + unsigned long addr, index; + int result; + + value = 0xBCDEF389; + p = &value; + addr = (unsigned long)p; + index = 0; + result = 0xFFFFF389; + __asm + ("lhx %0, %1(%2)\n\t" + : "=r"(rd) + : "r"(index), "r"(addr) + ); + + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/lwx.c b/tests/tcg/mips/mips32-dsp/lwx.c new file mode 100644 index 0000000000..e6543c9e7e --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/lwx.c @@ -0,0 +1,25 @@ +#include +#include + +int main(void) +{ + int value, rd; + int *p; + unsigned long addr, index; + int result; + + value = 0xBCDEF389; + p = &value; + addr = (unsigned long)p; + index = 0; + result = 0xBCDEF389; + __asm + ("lwx %0, %1(%2)\n\t" + : "=r"(rd) + : "r"(index), "r"(addr) + ); + + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/madd.c b/tests/tcg/mips/mips32-dsp/madd.c new file mode 100644 index 0000000000..af4bfcfe9d --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/madd.c @@ -0,0 +1,31 @@ +#include +#include + +int main() +{ + int rt, rs; + int achi, acli; + int acho, aclo; + int resulth, resultl; + + achi = 0x05; + acli = 0xB4CB; + rs = 0x01; + rt = 0x01; + resulth = 0x05; + resultl = 0xB4CC; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "madd $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + assert(resulth == acho); + assert(resultl == aclo); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/maddu.c b/tests/tcg/mips/mips32-dsp/maddu.c new file mode 100644 index 0000000000..af4bfcfe9d --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/maddu.c @@ -0,0 +1,31 @@ +#include +#include + +int main() +{ + int rt, rs; + int achi, acli; + int acho, aclo; + int resulth, resultl; + + achi = 0x05; + acli = 0xB4CB; + rs = 0x01; + rt = 0x01; + resulth = 0x05; + resultl = 0xB4CC; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "madd $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + assert(resulth == acho); + assert(resultl == aclo); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/main.c b/tests/tcg/mips/mips32-dsp/main.c new file mode 100644 index 0000000000..b296b20c92 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/main.c @@ -0,0 +1,6 @@ +#include + +int main() +{ + printf("hello world\n"); +} diff --git a/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c b/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c new file mode 100644 index 0000000000..292d68566d --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c @@ -0,0 +1,55 @@ +#include +#include + +int main() +{ + int rt, rs; + int achi, acli; + int dsp; + int acho, aclo; + int resulth, resultl; + int resdsp; + + achi = 0x05; + acli = 0xB4CB; + rs = 0xFF060000; + rt = 0xCB000000; + resulth = 0x04; + resultl = 0x947438CB; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "maq_s.w.phl $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + assert(resulth == acho); + assert(resultl == aclo); + + achi = 0x06; + acli = 0xB4CB; + rs = 0x80000000; + rt = 0x80000000; + resulth = 0x6; + resultl = 0x8000b4ca; + resdsp = 1; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_s.w.phl $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + assert(resulth == acho); + assert(resultl == aclo); + assert(((dsp >> 17) & 0x01) == resdsp); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c b/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c new file mode 100644 index 0000000000..7b2ef2ab71 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c @@ -0,0 +1,55 @@ +#include +#include + +int main() +{ + int rt, rs; + int achi, acli; + int dsp; + int acho, aclo; + int resulth, resultl; + int resdsp; + + achi = 0x05; + acli = 0xB4CB; + rs = 0xFF06; + rt = 0xCB00; + resulth = 0x04; + resultl = 0x947438CB; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "maq_s.w.phr $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + assert(resulth == acho); + assert(resultl == aclo); + + achi = 0x06; + acli = 0xB4CB; + rs = 0x8000; + rt = 0x8000; + resulth = 0x6; + resultl = 0x8000b4ca; + resdsp = 1; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_s.w.phr $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + assert(resulth == acho); + assert(resultl == aclo); + assert(((dsp >> 17) & 0x01) == resdsp); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c b/tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c new file mode 100644 index 0000000000..a756991723 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c @@ -0,0 +1,55 @@ +#include +#include + +int main() +{ + int rt, rs; + int achi, acli; + int dsp; + int acho, aclo; + int resulth, resultl; + int resdsp; + + achi = 0x05; + acli = 0xB4CB; + rs = 0xFF060000; + rt = 0xCB000000; + resulth = 0x00; + resultl = 0x7FFFFFFF; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "maq_sa.w.phl $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + assert(resulth == acho); + assert(resultl == aclo); + + achi = 0x06; + acli = 0xB4CB; + rs = 0x80000000; + rt = 0x80000000; + resulth = 0x00; + resultl = 0x7fffffff; + resdsp = 0x01; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_sa.w.phl $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + assert(resulth == acho); + assert(resultl == aclo); + assert(((dsp >> 17) & 0x01) == 0x01); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c b/tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c new file mode 100644 index 0000000000..d6498f8dfd --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c @@ -0,0 +1,55 @@ +#include +#include + +int main() +{ + int rt, rs; + int achi, acli; + int dsp; + int acho, aclo; + int resulth, resultl; + int resdsp; + + achi = 0x05; + acli = 0xB4CB; + rs = 0xFF06; + rt = 0xCB00; + resulth = 0x00; + resultl = 0x7FFFFFFF; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "maq_sa.w.phr $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + assert(resulth == acho); + assert(resultl == aclo); + + achi = 0x06; + acli = 0xB4CB; + rs = 0x8000; + rt = 0x8000; + resulth = 0x00; + resultl = 0x7fffffff; + resdsp = 0x01; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_sa.w.phr $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + assert(resulth == acho); + assert(resultl == aclo); + assert(((dsp >> 17) & 0x01) == 0x01); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/mfhi.c b/tests/tcg/mips/mips32-dsp/mfhi.c new file mode 100644 index 0000000000..43a80669d1 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/mfhi.c @@ -0,0 +1,21 @@ +#include +#include + +int main() +{ + int achi, acho; + int result; + + achi = 0x004433; + result = 0x004433; + + __asm + ("mthi %1, $ac1\n\t" + "mfhi %0, $ac1\n\t" + : "=r"(acho) + : "r"(achi) + ); + assert(result == acho); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/mflo.c b/tests/tcg/mips/mips32-dsp/mflo.c new file mode 100644 index 0000000000..caeafdb05c --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/mflo.c @@ -0,0 +1,21 @@ +#include +#include + +int main() +{ + int acli, aclo; + int result; + + acli = 0x004433; + result = 0x004433; + + __asm + ("mthi %1, $ac1\n\t" + "mfhi %0, $ac1\n\t" + : "=r"(aclo) + : "r"(acli) + ); + assert(result == aclo); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/modsub.c b/tests/tcg/mips/mips32-dsp/modsub.c new file mode 100644 index 0000000000..c294eebb51 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/modsub.c @@ -0,0 +1,30 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0xFFFFFFFF; + rt = 0x000000FF; + result = 0xFFFFFF00; + __asm + ("modsub %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(result == rd); + + rs = 0x00000000; + rt = 0x00CD1FFF; + result = 0x0000CD1F; + __asm + ("modsub %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(result == rd); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/msub.c b/tests/tcg/mips/mips32-dsp/msub.c new file mode 100644 index 0000000000..5779e6f47a --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/msub.c @@ -0,0 +1,30 @@ +#include +#include + +int main() +{ + int achi, acli, rs, rt; + int acho, aclo; + int resulth, resultl; + + rs = 0x00BBAACC; + rt = 0x0B1C3D2F; + achi = 0x00004433; + acli = 0xFFCC0011; + resulth = 0xFFF81F29; + resultl = 0xB355089D; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "msub $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + assert(acho == resulth); + assert(aclo == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/msubu.c b/tests/tcg/mips/mips32-dsp/msubu.c new file mode 100644 index 0000000000..e0f9b5a77a --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/msubu.c @@ -0,0 +1,30 @@ +#include +#include + +int main() +{ + int achi, acli, rs, rt; + int acho, aclo; + int resulth, resultl; + + rs = 0x00BBAACC; + rt = 0x0B1C3D2F; + achi = 0x00004433; + acli = 0xFFCC0011; + resulth = 0xFFF81F29; + resultl = 0xB355089D; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "msubu $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + assert(acho == resulth); + assert(aclo == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/mthi.c b/tests/tcg/mips/mips32-dsp/mthi.c new file mode 100644 index 0000000000..43a80669d1 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/mthi.c @@ -0,0 +1,21 @@ +#include +#include + +int main() +{ + int achi, acho; + int result; + + achi = 0x004433; + result = 0x004433; + + __asm + ("mthi %1, $ac1\n\t" + "mfhi %0, $ac1\n\t" + : "=r"(acho) + : "r"(achi) + ); + assert(result == acho); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/mthlip.c b/tests/tcg/mips/mips32-dsp/mthlip.c new file mode 100644 index 0000000000..9549aae36a --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/mthlip.c @@ -0,0 +1,58 @@ +#include +#include + +int main() +{ + int rs, ach, acl, dsp; + int result, resulth, resultl; + + dsp = 0x07; + ach = 0x05; + acl = 0xB4CB; + rs = 0x00FFBBAA; + resulth = 0xB4CB; + resultl = 0x00FFBBAA; + result = 0x27; + + __asm + ("wrdsp %0, 0x01\n\t" + "mthi %1, $ac1\n\t" + "mtlo %2, $ac1\n\t" + "mthlip %3, $ac1\n\t" + "mfhi %1, $ac1\n\t" + "mflo %2, $ac1\n\t" + "rddsp %0\n\t" + : "+r"(dsp), "+r"(ach), "+r"(acl) + : "r"(rs) + ); + dsp = dsp & 0x3F; + assert(dsp == result); + assert(ach == resulth); + assert(acl == resultl); + + dsp = 0x3f; + ach = 0x05; + acl = 0xB4CB; + rs = 0x00FFBBAA; + resulth = 0xB4CB; + resultl = 0x00FFBBAA; + result = 0x3f; + + __asm + ("wrdsp %0, 0x01\n\t" + "mthi %1, $ac1\n\t" + "mtlo %2, $ac1\n\t" + "mthlip %3, $ac1\n\t" + "mfhi %1, $ac1\n\t" + "mflo %2, $ac1\n\t" + "rddsp %0\n\t" + : "+r"(dsp), "+r"(ach), "+r"(acl) + : "r"(rs) + ); + dsp = dsp & 0x3F; + assert(dsp == result); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/mtlo.c b/tests/tcg/mips/mips32-dsp/mtlo.c new file mode 100644 index 0000000000..caeafdb05c --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/mtlo.c @@ -0,0 +1,21 @@ +#include +#include + +int main() +{ + int acli, aclo; + int result; + + acli = 0x004433; + result = 0x004433; + + __asm + ("mthi %1, $ac1\n\t" + "mfhi %0, $ac1\n\t" + : "=r"(aclo) + : "r"(acli) + ); + assert(result == aclo); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/muleq_s_w_phl.c b/tests/tcg/mips/mips32-dsp/muleq_s_w_phl.c new file mode 100644 index 0000000000..b3a5370fe5 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/muleq_s_w_phl.c @@ -0,0 +1,41 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x80001234; + rt = 0x80001234; + result = 0x7FFFFFFF; + resultdsp = 1; + + __asm + ("muleq_s.w.phl %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + assert(rd == result); + assert(dsp == resultdsp); + + rs = 0x12349988; + rt = 0x43219988; + result = 0x98be968; + resultdsp = 1; + + __asm + ("muleq_s.w.phl %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + assert(rd == result); + assert(dsp == resultdsp); + + return 0; +} + diff --git a/tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c b/tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c new file mode 100644 index 0000000000..8066d7d02a --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c @@ -0,0 +1,40 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x8000; + rt = 0x8000; + result = 0x7FFFFFFF; + resultdsp = 1; + + __asm + ("muleq_s.w.phr %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + assert(rd == result); + assert(dsp == resultdsp); + + rs = 0x1234; + rt = 0x4321; + result = 0x98be968; + resultdsp = 1; + + __asm + ("muleq_s.w.phr %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + assert(rd == result); + assert(dsp == resultdsp); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c b/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c new file mode 100644 index 0000000000..66a382806a --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c @@ -0,0 +1,25 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x80001234; + rt = 0x80004321; + result = 0xFFFF0000; + resultdsp = 1; + + __asm + ("muleu_s.ph.qbl %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + assert(rd == result); + assert(dsp == resultdsp); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c b/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c new file mode 100644 index 0000000000..4cc6c8f7cf --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c @@ -0,0 +1,25 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x8000; + rt = 0x80004321; + result = 0xFFFF0000; + resultdsp = 1; + + __asm + ("muleu_s.ph.qbr %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + assert(rd == result); + assert(dsp == resultdsp); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c b/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c new file mode 100644 index 0000000000..c7206039ea --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c @@ -0,0 +1,25 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x80001234; + rt = 0x80004321; + result = 0x7FFF098C; + resultdsp = 1; + + __asm + ("mulq_rs.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + assert(rd == result); + assert(dsp == resultdsp); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/mult.c b/tests/tcg/mips/mips32-dsp/mult.c new file mode 100644 index 0000000000..15e6fde92c --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/mult.c @@ -0,0 +1,24 @@ +#include +#include + +int main() +{ + int rs, rt, ach, acl; + int result, resulth, resultl; + + rs = 0x00FFBBAA; + rt = 0x4B231000; + resulth = 0x4b0f01; + resultl = 0x71f8a000; + __asm + ("mult $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(ach), "=r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/multu.c b/tests/tcg/mips/mips32-dsp/multu.c new file mode 100644 index 0000000000..85d36c1b62 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/multu.c @@ -0,0 +1,24 @@ +#include +#include + +int main() +{ + int rs, rt, ach, acl; + int result, resulth, resultl; + + rs = 0x00FFBBAA; + rt = 0x4B231000; + resulth = 0x4b0f01; + resultl = 0x71f8a000; + __asm + ("multu $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(ach), "=r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/packrl_ph.c b/tests/tcg/mips/mips32-dsp/packrl_ph.c new file mode 100644 index 0000000000..1f8e699925 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/packrl_ph.c @@ -0,0 +1,21 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x56788765; + + __asm + ("packrl.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(result == rd); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/pick_ph.c b/tests/tcg/mips/mips32-dsp/pick_ph.c new file mode 100644 index 0000000000..929a002e75 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/pick_ph.c @@ -0,0 +1,49 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result; + + rs = 0x12345678; + rt = 0x87654321; + dsp = 0x0A000000; + result = 0x12344321; + + __asm + ("wrdsp %3, 0x10\n\t" + "pick.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt), "r"(dsp) + ); + assert(rd == result); + + rs = 0x12345678; + rt = 0x87654321; + dsp = 0x03000000; + result = 0x12345678; + + __asm + ("wrdsp %3, 0x10\n\t" + "pick.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt), "r"(dsp) + ); + assert(rd == result); + + rs = 0x12345678; + rt = 0x87654321; + dsp = 0x00000000; + result = 0x87654321; + + __asm + ("wrdsp %3, 0x10\n\t" + "pick.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt), "r"(dsp) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/pick_qb.c b/tests/tcg/mips/mips32-dsp/pick_qb.c new file mode 100644 index 0000000000..a790475246 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/pick_qb.c @@ -0,0 +1,36 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result; + + rs = 0x12345678; + rt = 0x87654321; + dsp = 0x0f000000; + result = 0x12345678; + + __asm + ("wrdsp %3, 0x10\n\t" + "pick.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt), "r"(dsp) + ); + assert(rd == result); + + rs = 0x12345678; + rt = 0x87654321; + dsp = 0x00000000; + result = 0x87654321; + + __asm + ("wrdsp %3, 0x10\n\t" + "pick.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt), "r"(dsp) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/preceq_w_phl.c b/tests/tcg/mips/mips32-dsp/preceq_w_phl.c new file mode 100644 index 0000000000..bf70bf7d3a --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/preceq_w_phl.c @@ -0,0 +1,20 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x87654321; + result = 0x87650000; + + __asm + ("preceq.w.phl %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(result == rd); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/preceq_w_phr.c b/tests/tcg/mips/mips32-dsp/preceq_w_phr.c new file mode 100644 index 0000000000..3f885ef584 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/preceq_w_phr.c @@ -0,0 +1,20 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x87654321; + result = 0x43210000; + + __asm + ("preceq.w.phr %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(result == rd); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c b/tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c new file mode 100644 index 0000000000..63b7a95683 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c @@ -0,0 +1,20 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x87654321; + result = 0x43803280; + + __asm + ("precequ.ph.qbl %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(result == rd); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c b/tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c new file mode 100644 index 0000000000..31627f0bd6 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c @@ -0,0 +1,20 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x87654321; + result = 0x43802180; + + __asm + ("precequ.ph.qbla %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(result == rd); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c b/tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c new file mode 100644 index 0000000000..b6f72d3cbf --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c @@ -0,0 +1,20 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x87654321; + result = 0x21801080; + + __asm + ("precequ.ph.qbr %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(result == rd); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c b/tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c new file mode 100644 index 0000000000..4764fd031d --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c @@ -0,0 +1,20 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x87654321; + result = 0x32801080; + + __asm + ("precequ.ph.qbra %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(result == rd); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c b/tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c new file mode 100644 index 0000000000..fa95c26cc4 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c @@ -0,0 +1,20 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x87654321; + result = 0x00870065; + + __asm + ("preceu.ph.qbl %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(result == rd); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c b/tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c new file mode 100644 index 0000000000..021f21a744 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c @@ -0,0 +1,20 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x87654321; + result = 0x00870043; + + __asm + ("preceu.ph.qbla %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(result == rd); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c b/tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c new file mode 100644 index 0000000000..03df18c72c --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c @@ -0,0 +1,20 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x87654321; + result = 0x00430021; + + __asm + ("preceu.ph.qbr %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(result == rd); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c b/tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c new file mode 100644 index 0000000000..634327618c --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c @@ -0,0 +1,20 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x87654321; + result = 0x00650021; + + __asm + ("preceu.ph.qbra %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(result == rd); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/precrq_ph_w.c b/tests/tcg/mips/mips32-dsp/precrq_ph_w.c new file mode 100644 index 0000000000..25d45f1a9a --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/precrq_ph_w.c @@ -0,0 +1,21 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x12348765; + + __asm + ("precrq.ph.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(result == rd); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/precrq_qb_ph.c b/tests/tcg/mips/mips32-dsp/precrq_qb_ph.c new file mode 100644 index 0000000000..fe23acce8c --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/precrq_qb_ph.c @@ -0,0 +1,21 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x12568743; + + __asm + ("precrq.qb.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(result == rd); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c b/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c new file mode 100644 index 0000000000..3535b37a58 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c @@ -0,0 +1,35 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int dsp; + int result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x12348765; + + __asm + ("precrq_rs.ph.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(result == rd); + + rs = 0x7fffC678; + rt = 0x865432A0; + result = 0x7fff8654; + + __asm + ("precrq_rs.ph.w %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + assert(((dsp >> 22) & 0x01) == 1); + assert(result == rd); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c b/tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c new file mode 100644 index 0000000000..7481d5af3a --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c @@ -0,0 +1,24 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int dsp; + int result; + + rs = 0x12345678; + rt = 0x87657FFF; + result = 0x24AC00FF; + + __asm + ("precrqu_s.qb.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + assert(result == rd); + assert(((dsp >> 22) & 0x01) == 0x01); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/raddu_w_qb.c b/tests/tcg/mips/mips32-dsp/raddu_w_qb.c new file mode 100644 index 0000000000..77a983c0d2 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/raddu_w_qb.c @@ -0,0 +1,20 @@ +#include +#include + +int main() +{ + int rd, rs; + int result; + + rs = 0x12345678; + result = 0x114; + + __asm + ("raddu.w.qb %0, %1\n\t" + : "=r"(rd) + : "r"(rs) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/rddsp.c b/tests/tcg/mips/mips32-dsp/rddsp.c new file mode 100644 index 0000000000..e8948ec1d9 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/rddsp.c @@ -0,0 +1,54 @@ +#include +#include + +int main() +{ + int dsp_i, dsp_o; + int ccond_i, outflag_i, efi_i, c_i, scount_i, pos_i; + int ccond_o, outflag_o, efi_o, c_o, scount_o, pos_o; + int ccond_r, outflag_r, efi_r, c_r, scount_r, pos_r; + + ccond_i = 0x000000BC;/* 4 */ + outflag_i = 0x0000001B;/* 3 */ + efi_i = 0x00000001;/* 5 */ + c_i = 0x00000001;/* 2 */ + scount_i = 0x0000000F;/* 1 */ + pos_i = 0x0000000C;/* 0 */ + + dsp_i = (ccond_i << 24) | \ + (outflag_i << 16) | \ + (efi_i << 14) | \ + (c_i << 13) | \ + (scount_i << 7) | \ + pos_i; + + ccond_r = ccond_i; + outflag_r = outflag_i; + efi_r = efi_i; + c_r = c_i; + scount_r = scount_i; + pos_r = pos_i; + + __asm + ("wrdsp %1, 0x3F\n\t" + "rddsp %0, 0x3F\n\t" + : "=r"(dsp_o) + : "r"(dsp_i) + ); + + ccond_o = (dsp_o >> 24) & 0xFF; + outflag_o = (dsp_o >> 16) & 0xFF; + efi_o = (dsp_o >> 14) & 0x01; + c_o = (dsp_o >> 14) & 0x01; + scount_o = (dsp_o >> 7) & 0x3F; + pos_o = dsp_o & 0x1F; + + assert(ccond_o == ccond_r); + assert(outflag_o == outflag_r); + assert(efi_o == efi_r); + assert(c_o == c_r); + assert(scount_o == scount_r); + assert(pos_o == pos_r); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/repl_ph.c b/tests/tcg/mips/mips32-dsp/repl_ph.c new file mode 100644 index 0000000000..21074953bd --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/repl_ph.c @@ -0,0 +1,23 @@ +#include +#include + +int main() +{ + int rd, result; + + result = 0x01BF01BF; + __asm + ("repl.ph %0, 0x1BF\n\t" + : "=r"(rd) + ); + assert(rd == result); + + result = 0x01FF01FF; + __asm + ("repl.ph %0, 0x01FF\n\t" + : "=r"(rd) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/repl_qb.c b/tests/tcg/mips/mips32-dsp/repl_qb.c new file mode 100644 index 0000000000..6631393ea1 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/repl_qb.c @@ -0,0 +1,16 @@ +#include +#include + +int main() +{ + int rd, result; + + result = 0xBFBFBFBF; + __asm + ("repl.qb %0, 0xBF\n\t" + : "=r"(rd) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/replv_ph.c b/tests/tcg/mips/mips32-dsp/replv_ph.c new file mode 100644 index 0000000000..07fb15f1f7 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/replv_ph.c @@ -0,0 +1,19 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x12345678; + result = 0x56785678; + __asm + ("replv.ph %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/replv_qb.c b/tests/tcg/mips/mips32-dsp/replv_qb.c new file mode 100644 index 0000000000..dd1271fedf --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/replv_qb.c @@ -0,0 +1,19 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x12345678; + result = 0x78787878; + __asm + ("replv.qb %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shilo.c b/tests/tcg/mips/mips32-dsp/shilo.c new file mode 100644 index 0000000000..b686616d80 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shilo.c @@ -0,0 +1,27 @@ +#include +#include + +int main() +{ + int ach, acl; + int resulth, resultl; + + ach = 0xBBAACCFF; + acl = 0x1C3B001D; + + resulth = 0x17755; + resultl = 0x99fe3876; + + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "shilo $ac1, 0x0F\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + ); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shilov.c b/tests/tcg/mips/mips32-dsp/shilov.c new file mode 100644 index 0000000000..f186032a14 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shilov.c @@ -0,0 +1,29 @@ +#include +#include + +int main() +{ + int rs, ach, acl; + int resulth, resultl; + + rs = 0x0F; + ach = 0xBBAACCFF; + acl = 0x1C3B001D; + + resulth = 0x17755; + resultl = 0x99fe3876; + + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "shilov $ac1, %2\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs) + ); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shll_ph.c b/tests/tcg/mips/mips32-dsp/shll_ph.c new file mode 100644 index 0000000000..b8f1ff5285 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shll_ph.c @@ -0,0 +1,24 @@ +#include +#include + +int main() +{ + int rd, rt, dsp; + int result, resultdsp; + + rt = 0x12345678; + result = 0xA000C000; + resultdsp = 1; + + __asm + ("shll.ph %0, %2, 0x0B\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + dsp = (dsp >> 22) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shll_qb.c b/tests/tcg/mips/mips32-dsp/shll_qb.c new file mode 100644 index 0000000000..8c1b91c635 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shll_qb.c @@ -0,0 +1,36 @@ +#include +#include + +int main() +{ + int rd, rt, dsp; + int result, resultdsp; + + rt = 0x87654321; + result = 0x87654321; + resultdsp = 0x00; + + __asm + ("shll.qb %0, %2, 0x00\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + dsp = (dsp >> 22) & 0x01; + assert(rd == result); + + rt = 0x87654321; + result = 0x38281808; + resultdsp = 0x01; + + __asm + ("shll.qb %0, %2, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + dsp = (dsp >> 22) & 0x01; + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shll_s_ph.c b/tests/tcg/mips/mips32-dsp/shll_s_ph.c new file mode 100644 index 0000000000..910fea3b31 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shll_s_ph.c @@ -0,0 +1,24 @@ +#include +#include + +int main() +{ + int rd, rt, dsp; + int result, resultdsp; + + rt = 0x12345678; + result = 0x7FFF7FFF; + resultdsp = 0x01; + + __asm + ("shll_s.ph %0, %2, 0x0B\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + dsp = (dsp >> 22) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shll_s_w.c b/tests/tcg/mips/mips32-dsp/shll_s_w.c new file mode 100644 index 0000000000..628c752102 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shll_s_w.c @@ -0,0 +1,52 @@ +#include +#include + +int main() +{ + int rd, rt, dsp; + int result, resultdsp; + + rt = 0x82345678; + result = 0x82345678; + resultdsp = 0x00; + + __asm + ("shll_s.w %0, %2, 0x0\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + dsp = (dsp >> 22) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + rt = 0x82345678; + result = 0x80000000; + resultdsp = 0x01; + + __asm + ("shll_s.w %0, %2, 0x0B\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + dsp = (dsp >> 22) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + rt = 0x12345678; + result = 0x7FFFFFFF; + resultdsp = 0x01; + + __asm + ("shll_s.w %0, %2, 0x0B\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + dsp = (dsp >> 22) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shllv_ph.c b/tests/tcg/mips/mips32-dsp/shllv_ph.c new file mode 100644 index 0000000000..f98a6322dc --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shllv_ph.c @@ -0,0 +1,40 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x0; + rt = 0x12345678; + result = 0x12345678; + resultdsp = 0; + + __asm + ("shllv.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + dsp = (dsp >> 22) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + rs = 0x0B; + rt = 0x12345678; + result = 0xA000C000; + resultdsp = 1; + + __asm + ("shllv.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + dsp = (dsp >> 22) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shllv_qb.c b/tests/tcg/mips/mips32-dsp/shllv_qb.c new file mode 100644 index 0000000000..6d8ff4a259 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shllv_qb.c @@ -0,0 +1,38 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x03; + rt = 0x87654321; + result = 0x38281808; + resultdsp = 0x01; + + __asm + ("shllv.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + dsp = (dsp >> 22) & 0x01; + assert(rd == result); + + rs = 0x00; + rt = 0x87654321; + result = 0x87654321; + resultdsp = 0x01; + + __asm + ("shllv.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + dsp = (dsp >> 22) & 0x01; + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shllv_s_ph.c b/tests/tcg/mips/mips32-dsp/shllv_s_ph.c new file mode 100644 index 0000000000..fc9bd32765 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shllv_s_ph.c @@ -0,0 +1,40 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x0; + rt = 0x12345678; + result = 0x12345678; + resultdsp = 0x0; + + __asm + ("shllv_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + dsp = (dsp >> 22) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + rs = 0x0B; + rt = 0x12345678; + result = 0x7FFF7FFF; + resultdsp = 0x01; + + __asm + ("shllv_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + dsp = (dsp >> 22) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shllv_s_w.c b/tests/tcg/mips/mips32-dsp/shllv_s_w.c new file mode 100644 index 0000000000..350c25617a --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shllv_s_w.c @@ -0,0 +1,40 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x0B; + rt = 0x12345678; + result = 0x7FFFFFFF; + resultdsp = 0x01; + + __asm + ("shllv_s.w %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + dsp = (dsp >> 22) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + rs = 0x0; + rt = 0x12345678; + result = 0x12345678; + resultdsp = 0x01; + + __asm + ("shllv_s.w %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + dsp = (dsp >> 22) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shra_ph.c b/tests/tcg/mips/mips32-dsp/shra_ph.c new file mode 100644 index 0000000000..5b2d840a6b --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shra_ph.c @@ -0,0 +1,30 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x87654321; + result = 0xF0EC0864; + + __asm + ("shra.ph %0, %1, 0x03\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + rt = 0x87654321; + result = 0x87654321; + + __asm + ("shra.ph %0, %1, 0x00\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shra_r_ph.c b/tests/tcg/mips/mips32-dsp/shra_r_ph.c new file mode 100644 index 0000000000..adc4ae68bd --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shra_r_ph.c @@ -0,0 +1,30 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x87654321; + result = 0xF0ED0864; + + __asm + ("shra_r.ph %0, %1, 0x03\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + rt = 0x87654321; + result = 0x87654321; + + __asm + ("shra_r.ph %0, %1, 0x00\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shra_r_w.c b/tests/tcg/mips/mips32-dsp/shra_r_w.c new file mode 100644 index 0000000000..ec0cf2c72c --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shra_r_w.c @@ -0,0 +1,30 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x87654321; + result = 0xF0ECA864; + + __asm + ("shra_r.w %0, %1, 0x03\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + rt = 0x87654321; + result = 0x87654321; + + __asm + ("shra_r.w %0, %1, 0x0\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shrav_ph.c b/tests/tcg/mips/mips32-dsp/shrav_ph.c new file mode 100644 index 0000000000..6e42aaf8e1 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shrav_ph.c @@ -0,0 +1,32 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x03; + rt = 0x87654321; + result = 0xF0EC0864; + + __asm + ("shrav.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + assert(rd == result); + + rs = 0x00; + rt = 0x87654321; + result = 0x87654321; + + __asm + ("shrav.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shrav_r_ph.c b/tests/tcg/mips/mips32-dsp/shrav_r_ph.c new file mode 100644 index 0000000000..f03b978d05 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shrav_r_ph.c @@ -0,0 +1,32 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x03; + rt = 0x87654321; + result = 0xF0ED0864; + + __asm + ("shrav_r.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + assert(rd == result); + + rs = 0x00; + rt = 0x87654321; + result = 0x87654321; + + __asm + ("shrav_r.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shrav_r_w.c b/tests/tcg/mips/mips32-dsp/shrav_r_w.c new file mode 100644 index 0000000000..2ab03bb5da --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shrav_r_w.c @@ -0,0 +1,32 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x03; + rt = 0x87654321; + result = 0xF0ECA864; + + __asm + ("shrav_r.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + assert(rd == result); + + rs = 0x00; + rt = 0x40000000; + result = 0x40000000; + + __asm + ("shrav_r.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + + assert(rd == result); + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shrl_qb.c b/tests/tcg/mips/mips32-dsp/shrl_qb.c new file mode 100644 index 0000000000..a7e4e6a5e4 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shrl_qb.c @@ -0,0 +1,31 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x12345678; + result = 0x00010203; + + __asm + ("shrl.qb %0, %1, 0x05\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + rt = 0x12345678; + result = 0x12345678; + + __asm + ("shrl.qb %0, %1, 0x0\n\t" + : "=r"(rd) + : "r"(rt) + ); + + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/shrlv_qb.c b/tests/tcg/mips/mips32-dsp/shrlv_qb.c new file mode 100644 index 0000000000..db77f6d0e1 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/shrlv_qb.c @@ -0,0 +1,32 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x05; + rt = 0x12345678; + result = 0x00010203; + + __asm + ("shrlv.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + assert(rd == result); + + rs = 0x00; + rt = 0x12345678; + result = 0x12345678; + + __asm + ("shrlv.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/subq_ph.c b/tests/tcg/mips/mips32-dsp/subq_ph.c new file mode 100644 index 0000000000..fdd7b38b64 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/subq_ph.c @@ -0,0 +1,40 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x77777777; + rt = 0x67654321; + result = 0x10123456; + resultdsp = 0x0; + + __asm + ("subq.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + rs = 0x12345678; + rt = 0x87654321; + result = 0x8ACF1357; + resultdsp = 0x01; + + __asm + ("subq.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/subq_s_ph.c b/tests/tcg/mips/mips32-dsp/subq_s_ph.c new file mode 100644 index 0000000000..8e36dadef9 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/subq_s_ph.c @@ -0,0 +1,40 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x7FFF1357; + resultdsp = 0x01; + + __asm + ("subq_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + rs = 0x12348000; + rt = 0x87657000; + result = 0x7FFF8000; + resultdsp = 0x01; + + __asm + ("subq_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/subq_s_w.c b/tests/tcg/mips/mips32-dsp/subq_s_w.c new file mode 100644 index 0000000000..09022e9c85 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/subq_s_w.c @@ -0,0 +1,58 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x7FFFFFFF; + resultdsp = 0x01; + + __asm + ("subq_s.w %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + rs = 0x66666; + rt = 0x55555; + result = 0x11111; + resultdsp = 0x01; + + __asm + ("subq_s.w %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + +#if 0 + rs = 0x35555555; + rt = 0xf5555555; + result = 0x80000000; + resultdsp = 0x01; + + __asm + ("subq_s.w %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + + dsp = (dsp >> 20) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); +#endif + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/subu_qb.c b/tests/tcg/mips/mips32-dsp/subu_qb.c new file mode 100644 index 0000000000..4209096155 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/subu_qb.c @@ -0,0 +1,25 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x8BCF1357; + resultdsp = 0x01; + + __asm + ("subu.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/subu_s_qb.c b/tests/tcg/mips/mips32-dsp/subu_s_qb.c new file mode 100644 index 0000000000..3d650533d1 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/subu_s_qb.c @@ -0,0 +1,25 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x00001357; + resultdsp = 0x01; + + __asm + ("subu_s.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dsp/wrdsp.c b/tests/tcg/mips/mips32-dsp/wrdsp.c new file mode 100644 index 0000000000..e8948ec1d9 --- /dev/null +++ b/tests/tcg/mips/mips32-dsp/wrdsp.c @@ -0,0 +1,54 @@ +#include +#include + +int main() +{ + int dsp_i, dsp_o; + int ccond_i, outflag_i, efi_i, c_i, scount_i, pos_i; + int ccond_o, outflag_o, efi_o, c_o, scount_o, pos_o; + int ccond_r, outflag_r, efi_r, c_r, scount_r, pos_r; + + ccond_i = 0x000000BC;/* 4 */ + outflag_i = 0x0000001B;/* 3 */ + efi_i = 0x00000001;/* 5 */ + c_i = 0x00000001;/* 2 */ + scount_i = 0x0000000F;/* 1 */ + pos_i = 0x0000000C;/* 0 */ + + dsp_i = (ccond_i << 24) | \ + (outflag_i << 16) | \ + (efi_i << 14) | \ + (c_i << 13) | \ + (scount_i << 7) | \ + pos_i; + + ccond_r = ccond_i; + outflag_r = outflag_i; + efi_r = efi_i; + c_r = c_i; + scount_r = scount_i; + pos_r = pos_i; + + __asm + ("wrdsp %1, 0x3F\n\t" + "rddsp %0, 0x3F\n\t" + : "=r"(dsp_o) + : "r"(dsp_i) + ); + + ccond_o = (dsp_o >> 24) & 0xFF; + outflag_o = (dsp_o >> 16) & 0xFF; + efi_o = (dsp_o >> 14) & 0x01; + c_o = (dsp_o >> 14) & 0x01; + scount_o = (dsp_o >> 7) & 0x3F; + pos_o = dsp_o & 0x1F; + + assert(ccond_o == ccond_r); + assert(outflag_o == outflag_r); + assert(efi_o == efi_r); + assert(c_o == c_r); + assert(scount_o == scount_r); + assert(pos_o == pos_r); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/Makefile b/tests/tcg/mips/mips32-dspr2/Makefile new file mode 100644 index 0000000000..ed19581c7e --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/Makefile @@ -0,0 +1,71 @@ +-include ../../config-host.mak + +CROSS=mips64el-unknown-linux-gnu- + +SIM=qemu-mipsel +SIM_FLAGS=-cpu 74Kf + +CC = $(CROSS)gcc +CFLAGS = -mabi=32 -march=mips32r2 -mgp32 -mdspr2 -static + +TESTCASES = absq_s_qb.tst +TESTCASES += addqh_ph.tst +TESTCASES += addqh_r_ph.tst +TESTCASES += addqh_r_w.tst +TESTCASES += addqh_w.tst +TESTCASES += adduh_qb.tst +TESTCASES += adduh_r_qb.tst +TESTCASES += addu_ph.tst +TESTCASES += addu_s_ph.tst +TESTCASES += append.tst +TESTCASES += balign.tst +TESTCASES += cmpgdu_eq_qb.tst +TESTCASES += cmpgdu_le_qb.tst +TESTCASES += cmpgdu_lt_qb.tst +TESTCASES += dpaqx_sa_w_ph.tst +TESTCASES += dpa_w_ph.tst +TESTCASES += dpax_w_ph.tst +TESTCASES += dpaqx_s_w_ph.tst +TESTCASES += dpsqx_sa_w_ph.tst +TESTCASES += dpsqx_s_w_ph.tst +TESTCASES += dps_w_ph.tst +TESTCASES += dpsx_w_ph.tst +TESTCASES += mul_ph.tst +TESTCASES += mulq_rs_w.tst +TESTCASES += mulq_s_ph.tst +TESTCASES += mulq_s_w.tst +TESTCASES += mulsaq_s_w_ph.tst +TESTCASES += mulsa_w_ph.tst +TESTCASES += mul_s_ph.tst +TESTCASES += precr_qb_ph.tst +TESTCASES += precr_sra_ph_w.tst +TESTCASES += precr_sra_r_ph_w.tst +TESTCASES += prepend.tst +TESTCASES += shra_qb.tst +TESTCASES += shra_r_qb.tst +TESTCASES += shrav_qb.tst +TESTCASES += shrav_r_qb.tst +TESTCASES += shrl_ph.tst +TESTCASES += shrlv_ph.tst +TESTCASES += subqh_ph.tst +TESTCASES += subqh_r_ph.tst +TESTCASES += subqh_r_w.tst +TESTCASES += subqh_w.tst +TESTCASES += subuh_qb.tst +TESTCASES += subuh_r_qb.tst +TESTCASES += subu_ph.tst +TESTCASES += subu_s_ph.tst + +all: $(TESTCASES) + +%.tst: %.c + $(CC) $(CFLAGS) $< -o $@ + +check: $(TESTCASES) + @for case in $(TESTCASES); do \ + echo $(SIM) $(SIM_FLAGS) ./$$case;\ + $(SIM) $(SIM_FLAGS) ./$$case; \ + done + +clean: + $(RM) -rf $(TESTCASES) diff --git a/tests/tcg/mips/mips32-dspr2/absq_s_qb.c b/tests/tcg/mips/mips32-dspr2/absq_s_qb.c new file mode 100644 index 0000000000..af4683f304 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/absq_s_qb.c @@ -0,0 +1,35 @@ +#include +#include + +int main() +{ + int input, result, dsp; + int hope; + + input = 0x701BA35E; + hope = 0x701B5D5E; + + __asm + ("absq_s.qb %0, %1\n\t" + : "=r"(result) + : "r"(input) + ); + assert(result == hope); + + + input = 0x801BA35E; + hope = 0x7F1B5D5E; + + __asm + ("absq_s.qb %0, %2\n\t" + "rddsp %1\n\t" + : "=r"(result), "=r"(dsp) + : "r"(input) + ); + dsp = dsp >> 20; + dsp &= 0x01; + assert(dsp == 1); + assert(result == hope); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/addqh_ph.c b/tests/tcg/mips/mips32-dspr2/addqh_ph.c new file mode 100644 index 0000000000..921f0eaf33 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/addqh_ph.c @@ -0,0 +1,30 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x706A13FE; + rt = 0x13065174; + result = 0x41B832B9; + __asm + ("addqh.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + rs = 0x81000100; + rt = 0xc2000100; + result = 0xa1800100; + __asm + ("addqh.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/addqh_r_ph.c b/tests/tcg/mips/mips32-dspr2/addqh_r_ph.c new file mode 100644 index 0000000000..213ba37250 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/addqh_r_ph.c @@ -0,0 +1,30 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x706A13FE; + rt = 0x13065174; + result = 0x41B832B9; + __asm + ("addqh_r.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + rs = 0x81010100; + rt = 0xc2000100; + result = 0xa1810100; + __asm + ("addqh_r.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/addqh_r_w.c b/tests/tcg/mips/mips32-dspr2/addqh_r_w.c new file mode 100644 index 0000000000..75a75c50f3 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/addqh_r_w.c @@ -0,0 +1,34 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x00000010; + rt = 0x00000001; + result = 0x00000009; + + __asm + ("addqh_r.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + assert(rd == result); + + rs = 0xFFFFFFFE; + rt = 0x00000001; + result = 0x00000000; + + __asm + ("addqh_r.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/addqh_w.c b/tests/tcg/mips/mips32-dspr2/addqh_w.c new file mode 100644 index 0000000000..de6926ebbb --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/addqh_w.c @@ -0,0 +1,34 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x00000010; + rt = 0x00000001; + result = 0x00000008; + + __asm + ("addqh.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + assert(rd == result); + + rs = 0xFFFFFFFE; + rt = 0x00000001; + result = 0xFFFFFFFF; + + __asm + ("addqh.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/addu_ph.c b/tests/tcg/mips/mips32-dspr2/addu_ph.c new file mode 100644 index 0000000000..1d7a25a2a7 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/addu_ph.c @@ -0,0 +1,33 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int dsp; + int result; + + rs = 0x00FF00FF; + rt = 0x00010001; + result = 0x01000100; + __asm + ("addu.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + rs = 0xFFFF1111; + rt = 0x00020001; + result = 0x00011112; + __asm + ("addu.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + assert(((dsp >> 20) & 0x01) == 1); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/addu_s_ph.c b/tests/tcg/mips/mips32-dspr2/addu_s_ph.c new file mode 100644 index 0000000000..979651bfc9 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/addu_s_ph.c @@ -0,0 +1,33 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int dsp; + int result; + + rs = 0x00FE00FE; + rt = 0x00020001; + result = 0x010000FF; + __asm + ("addu_s.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + rs = 0xFFFF1111; + rt = 0x00020001; + result = 0xFFFF1112; + __asm + ("addu_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + assert(((dsp >> 20) & 0x01) == 1); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/adduh_qb.c b/tests/tcg/mips/mips32-dspr2/adduh_qb.c new file mode 100644 index 0000000000..a1f5d631b5 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/adduh_qb.c @@ -0,0 +1,30 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0xFF0055AA; + rt = 0x0113421B; + result = 0x80094B62; + __asm + ("adduh.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + rs = 0xFFFF0FFF; + rt = 0x00010111; + result = 0x7F800888; + __asm + ("adduh.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/adduh_r_qb.c b/tests/tcg/mips/mips32-dspr2/adduh_r_qb.c new file mode 100644 index 0000000000..81e98c190d --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/adduh_r_qb.c @@ -0,0 +1,30 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0xFF0055AA; + rt = 0x01112211; + result = 0x80093C5E; + __asm + ("adduh_r.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + rs = 0xFFFF0FFF; + rt = 0x00010111; + result = 0x80800888; + __asm + ("adduh_r.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/append.c b/tests/tcg/mips/mips32-dspr2/append.c new file mode 100644 index 0000000000..9a91e1650d --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/append.c @@ -0,0 +1,30 @@ +#include +#include + +int main() +{ + int rs, rt; + int result; + + rs = 0xFF0055AA; + rt = 0x0113421B; + result = 0x02268436; + __asm + ("append %0, %1, 0x01\n\t" + : "+r"(rt) + : "r"(rs) + ); + assert(rt == result); + + rs = 0xFFFF0FFF; + rt = 0x00010111; + result = 0x0010111F; + __asm + ("append %0, %1, 0x04\n\t" + : "+r"(rt) + : "r"(rs) + ); + assert(rt == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/balign.c b/tests/tcg/mips/mips32-dspr2/balign.c new file mode 100644 index 0000000000..537cf0451c --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/balign.c @@ -0,0 +1,30 @@ +#include +#include + +int main() +{ + int rs, rt; + int result; + + rs = 0xFF0055AA; + rt = 0x0113421B; + result = 0x13421BFF; + __asm + ("balign %0, %1, 0x01\n\t" + : "+r"(rt) + : "r"(rs) + ); + assert(rt == result); + + rs = 0xFFFF0FFF; + rt = 0x00010111; + result = 0x11FFFF0F; + __asm + ("balign %0, %1, 0x03\n\t" + : "+r"(rt) + : "r"(rs) + ); + assert(rt == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c b/tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c new file mode 100644 index 0000000000..2d6340d6fb --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c @@ -0,0 +1,37 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int dsp; + int result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x02; + __asm + ("cmpgdu.eq.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + assert(rd == result); + assert(dsp == result); + + rs = 0x11777066; + rt = 0x11777066; + result = 0x0F; + __asm + ("cmpgdu.eq.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + assert(rd == result); + assert(dsp == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c b/tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c new file mode 100644 index 0000000000..a0ecdca2ac --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c @@ -0,0 +1,37 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int dsp; + int result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x0F; + __asm + ("cmpgdu.le.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + assert(rd == result); + assert(dsp == result); + + rs = 0x11777066; + rt = 0x11707066; + result = 0x0B; + __asm + ("cmpgdu.le.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + assert(rd == result); + assert(dsp == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c b/tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c new file mode 100644 index 0000000000..dba99e392c --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c @@ -0,0 +1,37 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int dsp; + int result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x0D; + __asm + ("cmpgdu.lt.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + assert(rd == result); + assert(dsp == result); + + rs = 0x11777066; + rt = 0x11777066; + result = 0x00; + __asm + ("cmpgdu.lt.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + assert(rd == result); + assert(dsp == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c new file mode 100644 index 0000000000..1cfbdb080f --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c @@ -0,0 +1,44 @@ +#include +#include + +int main() +{ + int rs, rt; + int ach = 5, acl = 5; + int resulth, resultl; + + rs = 0x00FF00FF; + rt = 0x00010002; + resulth = 0x05; + resultl = 0x0302; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpa.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + + ach = 6, acl = 7; + rs = 0xFFFF00FF; + rt = 0xFFFF0002; + resulth = 0x05; + resultl = 0xfffe0206; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpa.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c new file mode 100644 index 0000000000..ce87830246 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c @@ -0,0 +1,79 @@ +#include +#include + +int main() +{ + int rs, rt, dsp; + int ach = 5, acl = 5; + int resulth, resultl, resultdsp; + + rs = 0x800000FF; + rt = 0x00018000; + resulth = 0x05; + resultl = 0x80000202; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpaqx_s.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + assert(dsp == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + ach = 5; + acl = 5; + rs = 0x00FF00FF; + rt = 0x00010002; + resulth = 0x05; + resultl = 0x05FF; + /*********************************************************** + * Because of we set outflag at last time, although this + * time we set nothing, but it is stay the last time value. + **********************************************************/ + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpaqx_s.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + assert(dsp == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + ach = 5; + acl = 5; + rs = 0x800000FF; + rt = 0x00028000; + resulth = 0x05; + resultl = 0x80000400; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpaqx_s.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + assert(dsp == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c new file mode 100644 index 0000000000..798c4da5ca --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c @@ -0,0 +1,53 @@ +#include +#include + +int main() +{ + int rs, rt, dsp; + int ach = 5, acl = 5; + int resulth, resultl, resultdsp; + + rs = 0x00FF00FF; + rt = 0x00010002; + resulth = 0x00; + resultl = 0x7FFFFFFF; + resultdsp = 0x01; + __asm + ("wrdsp %2\n\t" + "mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpaqx_sa.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "+r"(dsp) + : "r"(rs), "r"(rt) + ); + assert(dsp >> (16 + 1) == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + ach = 9; + acl = 0xb; + rs = 0x800000FF; + rt = 0x00018000; + resulth = 0x00; + resultl = 0x7fffffff; + resultdsp = 0x01; + __asm + ("wrdsp %2\n\t" + "mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpaqx_sa.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "+r"(dsp) + : "r"(rs), "r"(rt) + ); + assert(dsp >> (16 + 1) == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c new file mode 100644 index 0000000000..f75699755c --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c @@ -0,0 +1,27 @@ +#include +#include + +int main() +{ + int rs, rt; + int ach = 5, acl = 5; + int resulth, resultl; + + rs = 0x00FF00FF; + rt = 0x00010002; + resulth = 0x05; + resultl = 0x0302; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpax.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/dps_w_ph.c b/tests/tcg/mips/mips32-dspr2/dps_w_ph.c new file mode 100644 index 0000000000..8303643d18 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/dps_w_ph.c @@ -0,0 +1,27 @@ +#include +#include + +int main() +{ + int rs, rt; + int ach = 5, acl = 5; + int resulth, resultl; + + rs = 0x00FF00FF; + rt = 0x00010002; + resulth = 0x04; + resultl = 0xFFFFFD08; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dps.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c new file mode 100644 index 0000000000..14cdd7c0f5 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c @@ -0,0 +1,54 @@ +#include +#include + +int main() +{ + int rs, rt, dsp; + int ach = 5, acl = 5; + int resulth, resultl, resultdsp; + + rs = 0xBC0123AD; + rt = 0x01643721; + resulth = 0x04; + resultl = 0xAEA3E09B; + resultdsp = 0x00; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsqx_s.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + assert(dsp == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + ach = 0x99f13005; + acl = 0x51730062; + rs = 0x80008000; + rt = 0x80008000; + + resulth = 0x99f13004; + resultl = 0x51730064; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsqx_s.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + assert(dsp == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c new file mode 100644 index 0000000000..7da278eacc --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c @@ -0,0 +1,53 @@ +#include +#include + +int main() +{ + int rs, rt, dsp; + int ach = 5, acl = 5; + int resulth, resultl, resultdsp; + + rs = 0xBC0123AD; + rt = 0x01643721; + resulth = 0x00; + resultl = 0x7FFFFFFF; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsqx_sa.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + assert(dsp == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + ach = 0x8c0b354A; + acl = 0xbbc02249; + rs = 0x800023AD; + rt = 0x01648000; + resulth = 0xffffffff; + resultl = 0x80000000; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsqx_sa.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + assert(dsp == resultdsp); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c new file mode 100644 index 0000000000..6db59a4ccd --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c @@ -0,0 +1,27 @@ +#include +#include + +int main() +{ + int rs, rt; + int ach = 5, acl = 5; + int resulth, resultl; + + rs = 0xBC0123AD; + rt = 0x01643721; + resulth = 0x04; + resultl = 0xD751F050; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsx.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/mul_ph.c b/tests/tcg/mips/mips32-dspr2/mul_ph.c new file mode 100644 index 0000000000..c7e9d60d12 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/mul_ph.c @@ -0,0 +1,47 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x03FB1234; + rt = 0x0BCC4321; + result = 0xF504F4B4; + resultdsp = 1; + + __asm + ("mul.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + assert(rd == result); + assert(dsp == resultdsp); + + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + rs = 0x00210010; + rt = 0x00110005; + result = 0x2310050; + resultdsp = 0; + + __asm + ("mul.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + assert(rd == result); + assert(dsp == resultdsp); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/mul_s_ph.c b/tests/tcg/mips/mips32-dspr2/mul_s_ph.c new file mode 100644 index 0000000000..33da110de8 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/mul_s_ph.c @@ -0,0 +1,62 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x03FB1234; + rt = 0x0BCC4321; + result = 0x7fff7FFF; + resultdsp = 1; + + __asm + ("mul_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + assert(rd == result); + assert(dsp == resultdsp); + + rs = 0x7fffff00; + rt = 0xff007fff; + result = 0x80008000; + resultdsp = 1; + + __asm + ("mul_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + assert(rd == result); + assert(dsp == resultdsp); + + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + rs = 0x00320001; + rt = 0x00210002; + result = 0x06720002; + resultdsp = 0; + + __asm + ("mul_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + assert(rd == result); + assert(dsp == resultdsp); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/mulq_rs_w.c b/tests/tcg/mips/mips32-dspr2/mulq_rs_w.c new file mode 100644 index 0000000000..669405faf1 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/mulq_rs_w.c @@ -0,0 +1,36 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x80001234; + rt = 0x80004321; + result = 0x80005555; + + __asm + ("mulq_rs.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + rs = 0x80000000; + rt = 0x80000000; + result = 0x7FFFFFFF; + resultdsp = 1; + + __asm + ("mulq_rs.w %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + assert(rd == result); + assert(dsp == resultdsp); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/mulq_s_ph.c b/tests/tcg/mips/mips32-dspr2/mulq_s_ph.c new file mode 100644 index 0000000000..d0f7674a38 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/mulq_s_ph.c @@ -0,0 +1,25 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x80001234; + rt = 0x80004321; + result = 0x7FFF098B; + resultdsp = 1; + + __asm + ("mulq_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + assert(rd == result); + assert(dsp == resultdsp); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/mulq_s_w.c b/tests/tcg/mips/mips32-dspr2/mulq_s_w.c new file mode 100644 index 0000000000..df148b7ffb --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/mulq_s_w.c @@ -0,0 +1,36 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x80001234; + rt = 0x80004321; + result = 0x80005555; + + __asm + ("mulq_s.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + rs = 0x80000000; + rt = 0x80000000; + result = 0x7FFFFFFF; + resultdsp = 1; + + __asm + ("mulq_s.w %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + assert(rd == result); + assert(dsp == resultdsp); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c b/tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c new file mode 100644 index 0000000000..a6940939ca --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c @@ -0,0 +1,29 @@ +#include +#include + +int main() +{ + int rs, rt, ach, acl; + int resulth, resultl; + + ach = 0x05; + acl = 0x00BBDDCC; + rs = 0x80001234; + rt = 0x80004321; + resulth = 0x05; + resultl = 0x3BF5E918; + + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "mulsa.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c b/tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c new file mode 100644 index 0000000000..06c91a43e7 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c @@ -0,0 +1,29 @@ +#include +#include + +int main() +{ + int rs, rt, ach, acl; + int resulth, resultl; + + ach = 0x05; + acl = 0x00BBDDCC; + rs = 0x80001234; + rt = 0x80004321; + resulth = 0x05; + resultl = 0x772ff463; + + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "mulsaq_s.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/precr_qb_ph.c b/tests/tcg/mips/mips32-dspr2/precr_qb_ph.c new file mode 100644 index 0000000000..3a2b3fde05 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/precr_qb_ph.c @@ -0,0 +1,21 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x34786521; + + __asm + ("precr.qb.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(result == rd); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c b/tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c new file mode 100644 index 0000000000..5c9baab03d --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c @@ -0,0 +1,32 @@ +#include +#include + +int main() +{ + int rs, rt; + int result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x43215678; + + __asm + ("precr_sra.ph.w %0, %1, 0x00\n\t" + : "+r"(rt) + : "r"(rs) + ); + assert(result == rt); + + rs = 0x12345678; + rt = 0x87654321; + result = 0xFFFF0000; + + __asm + ("precr_sra.ph.w %0, %1, 0x1F\n\t" + : "+r"(rt) + : "r"(rs) + ); + assert(result == rt); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c b/tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c new file mode 100644 index 0000000000..6474a108c0 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c @@ -0,0 +1,32 @@ +#include +#include + +int main() +{ + int rs, rt; + int result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x43215678; + + __asm + ("precr_sra_r.ph.w %0, %1, 0x00\n\t" + : "+r"(rt) + : "r"(rs) + ); + assert(result == rt); + + rs = 0x12345678; + rt = 0x87654321; + result = 0xFFFF0000; + + __asm + ("precr_sra_r.ph.w %0, %1, 0x1F\n\t" + : "+r"(rt) + : "r"(rs) + ); + assert(result == rt); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/prepend.c b/tests/tcg/mips/mips32-dspr2/prepend.c new file mode 100644 index 0000000000..f6bcd47b2d --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/prepend.c @@ -0,0 +1,30 @@ +#include +#include + +int main() +{ + int rs, rt; + int result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x87654321; + __asm + ("prepend %0, %1, 0x00\n\t" + : "+r"(rt) + : "r"(rs) + ); + assert(rt == result); + + rs = 0x12345678; + rt = 0x87654321; + result = 0xACF10ECA; + __asm + ("prepend %0, %1, 0x0F\n\t" + : "+r"(rt) + : "r"(rs) + ); + assert(rt == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/shra_qb.c b/tests/tcg/mips/mips32-dspr2/shra_qb.c new file mode 100644 index 0000000000..48193de87a --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/shra_qb.c @@ -0,0 +1,30 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x12345678; + result = 0x02060A0F; + + __asm + ("shra.qb %0, %1, 0x03\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + rt = 0x87654321; + result = 0xF00C0804; + + __asm + ("shra.qb %0, %1, 0x03\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/shra_r_qb.c b/tests/tcg/mips/mips32-dspr2/shra_r_qb.c new file mode 100644 index 0000000000..29afa0e4b0 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/shra_r_qb.c @@ -0,0 +1,30 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x12345678; + result = 0x02070B0F; + + __asm + ("shra_r.qb %0, %1, 0x03\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + rt = 0x87654321; + result = 0xF10D0804; + + __asm + ("shra_r.qb %0, %1, 0x03\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/shrav_qb.c b/tests/tcg/mips/mips32-dspr2/shrav_qb.c new file mode 100644 index 0000000000..b21e1b7ca6 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/shrav_qb.c @@ -0,0 +1,32 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x03; + rt = 0x12345678; + result = 0x02060A0F; + + __asm + ("shrav.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + assert(rd == result); + + rs = 0x03; + rt = 0x87654321; + result = 0xF00C0804; + + __asm + ("shrav.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/shrav_r_qb.c b/tests/tcg/mips/mips32-dspr2/shrav_r_qb.c new file mode 100644 index 0000000000..9ea8aa0cbb --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/shrav_r_qb.c @@ -0,0 +1,32 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x03; + rt = 0x12345678; + result = 0x02070B0F; + + __asm + ("shrav_r.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + assert(rd == result); + + rs = 0x03; + rt = 0x87654321; + result = 0xF10D0804; + + __asm + ("shrav_r.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/shrl_ph.c b/tests/tcg/mips/mips32-dspr2/shrl_ph.c new file mode 100644 index 0000000000..724b9a7a46 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/shrl_ph.c @@ -0,0 +1,20 @@ +#include +#include + +int main() +{ + int rd, rt; + int result; + + rt = 0x12345678; + result = 0x009102B3; + + __asm + ("shrl.ph %0, %1, 0x05\n\t" + : "=r"(rd) + : "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/shrlv_ph.c b/tests/tcg/mips/mips32-dspr2/shrlv_ph.c new file mode 100644 index 0000000000..ac79aa69ac --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/shrlv_ph.c @@ -0,0 +1,21 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x05; + rt = 0x12345678; + result = 0x009102B3; + + __asm + ("shrlv.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/subqh_ph.c b/tests/tcg/mips/mips32-dspr2/subqh_ph.c new file mode 100644 index 0000000000..dbc096734c --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/subqh_ph.c @@ -0,0 +1,21 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x456709AB; + + __asm + ("subqh.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/subqh_r_ph.c b/tests/tcg/mips/mips32-dspr2/subqh_r_ph.c new file mode 100644 index 0000000000..24ef0f1aeb --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/subqh_r_ph.c @@ -0,0 +1,21 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x456809AC; + + __asm + ("subqh_r.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/subqh_r_w.c b/tests/tcg/mips/mips32-dspr2/subqh_r_w.c new file mode 100644 index 0000000000..d460f8630f --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/subqh_r_w.c @@ -0,0 +1,21 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x456789AC; + + __asm + ("subqh_r.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/subqh_w.c b/tests/tcg/mips/mips32-dspr2/subqh_w.c new file mode 100644 index 0000000000..42be3deb80 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/subqh_w.c @@ -0,0 +1,21 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x456789AB; + + __asm + ("subqh.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/subu_ph.c b/tests/tcg/mips/mips32-dspr2/subu_ph.c new file mode 100644 index 0000000000..0d39a017c7 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/subu_ph.c @@ -0,0 +1,40 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x87654321; + rt = 0x11111111; + result = 0x76543210; + resultdsp = 0x00; + + __asm + ("subu.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + rs = 0x87654321; + rt = 0x12345678; + result = 0x7531ECA9; + resultdsp = 0x01; + + __asm + ("subu.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/subu_s_ph.c b/tests/tcg/mips/mips32-dspr2/subu_s_ph.c new file mode 100644 index 0000000000..8e4da4f3e5 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/subu_s_ph.c @@ -0,0 +1,25 @@ +#include +#include + +int main() +{ + int rd, rs, rt, dsp; + int result, resultdsp; + + rs = 0x87654321; + rt = 0x12345678; + result = 0x75310000; + resultdsp = 0x01; + + __asm + ("subu_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + assert(dsp == resultdsp); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/subuh_qb.c b/tests/tcg/mips/mips32-dspr2/subuh_qb.c new file mode 100644 index 0000000000..92cfc764b8 --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/subuh_qb.c @@ -0,0 +1,21 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0xC5E7092B; + + __asm + ("subuh.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips32-dspr2/subuh_r_qb.c b/tests/tcg/mips/mips32-dspr2/subuh_r_qb.c new file mode 100644 index 0000000000..dac81d47db --- /dev/null +++ b/tests/tcg/mips/mips32-dspr2/subuh_r_qb.c @@ -0,0 +1,32 @@ +#include +#include + +int main() +{ + int rd, rs, rt; + int result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0xC6E80A2C; + + __asm + ("subuh_r.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + rs = 0xBEFC292A; + rt = 0x9205C1B4; + result = 0x167cb4bb; + + __asm + ("subuh_r.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + assert(rd == result); + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/Makefile b/tests/tcg/mips/mips64-dsp/Makefile new file mode 100644 index 0000000000..b2ac6b3ffd --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/Makefile @@ -0,0 +1,306 @@ + +CROSS_COMPILE ?= mips64el-unknown-linux-gnu- + +SIM = qemu-system-mips64el +SIMFLAGS = -nographic -cpu mips64dspr2 -kernel + +AS = $(CROSS_COMPILE)as +LD = $(CROSS_COMPILE)ld +CC = $(CROSS_COMPILE)gcc +AR = $(CROSS_COMPILE)ar +NM = $(CROSS_COMPILE)nm +STRIP = $(CROSS_COMPILE)strip +RANLIB = $(CROSS_COMPILE)ranlib +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump + +VECTORS_OBJ ?= ./head.o ./printf.o + +HEAD_FLAGS ?= -nostdinc -mabi=64 -G 0 -mno-abicalls -fno-pic -pipe \ + -msoft-float -march=mips64 -Wa,-mips64 -Wa,--trap \ + -msym32 -DKBUILD_64BIT_SYM32 -I./ + +CFLAGS ?= -nostdinc -mabi=64 -G 0 -mno-abicalls -fno-pic -fno-builtin \ + -pipe -march=mips64r2 -mgp64 -mdsp -static -Wa,--trap -msym32 \ + -DKBUILD_64BIT_SYM32 -I./ + +LDFLAGS = -T./mips_boot.lds -L./ +FLAGS = -nostdlib -mabi=64 -march=mips64r2 -mgp64 -mdsp + + +#TESTCASES = absq_s_ob.tst +TESTCASES = absq_s_ph.tst +TESTCASES += absq_s_pw.tst +TESTCASES += absq_s_qh.tst +TESTCASES += absq_s_w.tst +TESTCASES += addq_ph.tst +TESTCASES += addq_pw.tst +TESTCASES += addq_qh.tst +TESTCASES += addq_s_ph.tst +TESTCASES += addq_s_pw.tst +TESTCASES += addq_s_qh.tst +TESTCASES += addq_s_w.tst +TESTCASES += addsc.tst +TESTCASES += addu_ob.tst +TESTCASES += addu_qb.tst +TESTCASES += addu_s_ob.tst +TESTCASES += addu_s_qb.tst +TESTCASES += addwc.tst +TESTCASES += bitrev.tst +TESTCASES += bposge32.tst +TESTCASES += bposge64.tst +TESTCASES += cmp_eq_ph.tst +TESTCASES += cmp_eq_pw.tst +TESTCASES += cmp_eq_qh.tst +TESTCASES += cmpgu_eq_ob.tst +TESTCASES += cmpgu_eq_qb.tst +TESTCASES += cmpgu_le_ob.tst +TESTCASES += cmpgu_le_qb.tst +TESTCASES += cmpgu_lt_ob.tst +TESTCASES += cmpgu_lt_qb.tst +TESTCASES += cmp_le_ph.tst +TESTCASES += cmp_le_pw.tst +TESTCASES += cmp_le_qh.tst +TESTCASES += cmp_lt_ph.tst +TESTCASES += cmp_lt_pw.tst +TESTCASES += cmp_lt_qh.tst +TESTCASES += cmpu_eq_ob.tst +TESTCASES += cmpu_eq_qb.tst +TESTCASES += cmpu_le_ob.tst +TESTCASES += cmpu_le_qb.tst +TESTCASES += cmpu_lt_ob.tst +TESTCASES += cmpu_lt_qb.tst +#TESTCASES += dappend.tst +TESTCASES += dextp.tst +TESTCASES += dextpdp.tst +TESTCASES += dextpdpv.tst +TESTCASES += dextpv.tst +TESTCASES += dextr_l.tst +TESTCASES += dextr_r_l.tst +TESTCASES += dextr_rs_l.tst +TESTCASES += dextr_rs_w.tst +TESTCASES += dextr_r_w.tst +TESTCASES += dextr_s_h.tst +TESTCASES += dextrv_l.tst +TESTCASES += dextrv_r_l.tst +TESTCASES += dextrv_rs_l.tst +TESTCASES += dextrv_rs_w.tst +TESTCASES += dextrv_r_w.tst +TESTCASES += dextrv_s_h.tst +TESTCASES += dextrv_w.tst +TESTCASES += dextr_w.tst +TESTCASES += dinsv.tst +TESTCASES += dmadd.tst +TESTCASES += dmaddu.tst +TESTCASES += dmsub.tst +TESTCASES += dmsubu.tst +TESTCASES += dmthlip.tst +TESTCASES += dpaq_sa_l_pw.tst +TESTCASES += dpaq_sa_l_w.tst +TESTCASES += dpaq_s_w_ph.tst +TESTCASES += dpaq_s_w_qh.tst +TESTCASES += dpau_h_obl.tst +TESTCASES += dpau_h_obr.tst +TESTCASES += dpau_h_qbl.tst +TESTCASES += dpau_h_qbr.tst +TESTCASES += dpsq_sa_l_pw.tst +TESTCASES += dpsq_sa_l_w.tst +TESTCASES += dpsq_s_w_ph.tst +TESTCASES += dpsq_s_w_qh.tst +TESTCASES += dpsu_h_obl.tst +TESTCASES += dpsu_h_obr.tst +TESTCASES += dpsu_h_qbl.tst +TESTCASES += dpsu_h_qbr.tst +TESTCASES += dshilo.tst +TESTCASES += dshilov.tst +TESTCASES += extp.tst +TESTCASES += extpdp.tst +TESTCASES += extpdpv.tst +TESTCASES += extpv.tst +TESTCASES += extr_rs_w.tst +TESTCASES += extr_r_w.tst +TESTCASES += extr_s_h.tst +TESTCASES += extrv_rs_w.tst +TESTCASES += extrv_r_w.tst +TESTCASES += extrv_s_h.tst +TESTCASES += extrv_w.tst +TESTCASES += extr_w.tst +TESTCASES += insv.tst +TESTCASES += lbux.tst +TESTCASES += lhx.tst +TESTCASES += lwx.tst +TESTCASES += ldx.tst +TESTCASES += madd.tst +TESTCASES += maddu.tst +TESTCASES += maq_sa_w_phl.tst +TESTCASES += maq_sa_w_phr.tst +TESTCASES += maq_sa_w_qhll.tst +TESTCASES += maq_sa_w_qhlr.tst +TESTCASES += maq_sa_w_qhrl.tst +TESTCASES += maq_sa_w_qhrr.tst +TESTCASES += maq_s_l_pwl.tst +TESTCASES += maq_s_l_pwr.tst +TESTCASES += maq_s_w_phl.tst +TESTCASES += maq_s_w_phr.tst +TESTCASES += maq_s_w_qhll.tst +TESTCASES += maq_s_w_qhlr.tst +TESTCASES += maq_s_w_qhrl.tst +TESTCASES += maq_s_w_qhrr.tst +TESTCASES += mfhi.tst +TESTCASES += mflo.tst +TESTCASES += modsub.tst +TESTCASES += msub.tst +TESTCASES += msubu.tst +TESTCASES += mthi.tst +TESTCASES += mthlip.tst +TESTCASES += mtlo.tst +TESTCASES += muleq_s_pw_qhl.tst +TESTCASES += muleq_s_pw_qhr.tst +TESTCASES += muleq_s_w_phl.tst +TESTCASES += muleq_s_w_phr.tst +TESTCASES += muleu_s_ph_qbl.tst +TESTCASES += muleu_s_ph_qbr.tst +TESTCASES += muleu_s_qh_obl.tst +TESTCASES += muleu_s_qh_obr.tst +TESTCASES += mulq_rs_ph.tst +TESTCASES += mulq_rs_qh.tst +TESTCASES += mulsaq_s_l_pw.tst +TESTCASES += mulsaq_s_w_qh.tst +TESTCASES += mult.tst +TESTCASES += multu.tst +TESTCASES += packrl_ph.tst +TESTCASES += packrl_pw.tst +TESTCASES += pick_ob.tst +TESTCASES += pick_ph.tst +TESTCASES += pick_pw.tst +TESTCASES += pick_qb.tst +TESTCASES += pick_qh.tst +#TESTCASES += preceq_l_pwl.tst +#TESTCASES += preceq_l_pwr.tst +TESTCASES += preceq_pw_qhla.tst +TESTCASES += preceq_pw_qhl.tst +TESTCASES += preceq_pw_qhra.tst +TESTCASES += preceq_pw_qhr.tst +TESTCASES += precequ_ph_qbla.tst +TESTCASES += precequ_ph_qbl.tst +TESTCASES += precequ_ph_qbra.tst +TESTCASES += precequ_ph_qbr.tst +#TESTCASES += precequ_qh_obla.tst +#TESTCASES += precequ_qh_obl.tst +#TESTCASES += precequ_qh_obra.tst +#TESTCASES += precequ_qh_obr.tst +TESTCASES += preceq_w_phl.tst +TESTCASES += preceq_w_phr.tst +TESTCASES += preceu_ph_qbla.tst +TESTCASES += preceu_ph_qbl.tst +TESTCASES += preceu_ph_qbra.tst +TESTCASES += preceu_ph_qbr.tst +TESTCASES += preceu_qh_obla.tst +TESTCASES += preceu_qh_obl.tst +TESTCASES += preceu_qh_obra.tst +TESTCASES += preceu_qh_obr.tst +#TESTCASES += precr_ob_qh.tst +TESTCASES += precrq_ob_qh.tst +TESTCASES += precrq_ph_w.tst +TESTCASES += precrq_pw_l.tst +TESTCASES += precrq_qb_ph.tst +TESTCASES += precrq_qh_pw.tst +TESTCASES += precrq_rs_ph_w.tst +TESTCASES += precrq_rs_qh_pw.tst +TESTCASES += precrqu_s_ob_qh.tst +TESTCASES += precrqu_s_qb_ph.tst +#TESTCASES += precr_sra_qh_pw.tst +#TESTCASES += precr_sra_r_qh_pw.tst +#TESTCASES += prependd.tst +#TESTCASES += prependw.tst +#TESTCASES += raddu_l_ob.tst +TESTCASES += raddu_w_qb.tst +TESTCASES += rddsp.tst +TESTCASES += repl_ob.tst +TESTCASES += repl_ph.tst +TESTCASES += repl_pw.tst +TESTCASES += repl_qb.tst +TESTCASES += repl_qh.tst +TESTCASES += replv_ob.tst +TESTCASES += replv_ph.tst +TESTCASES += replv_pw.tst +TESTCASES += replv_qb.tst +TESTCASES += shilo.tst +TESTCASES += shilov.tst +TESTCASES += shll_ob.tst +TESTCASES += shll_ph.tst +TESTCASES += shll_pw.tst +TESTCASES += shll_qb.tst +TESTCASES += shll_qh.tst +TESTCASES += shll_s_ph.tst +TESTCASES += shll_s_pw.tst +TESTCASES += shll_s_qh.tst +TESTCASES += shll_s_w.tst +TESTCASES += shllv_ob.tst +TESTCASES += shllv_ph.tst +TESTCASES += shllv_pw.tst +TESTCASES += shllv_qb.tst +TESTCASES += shllv_qh.tst +TESTCASES += shllv_s_ph.tst +TESTCASES += shllv_s_pw.tst +TESTCASES += shllv_s_qh.tst +TESTCASES += shllv_s_w.tst +#TESTCASES += shra_ob.tst +TESTCASES += shra_ph.tst +TESTCASES += shra_pw.tst +TESTCASES += shra_qh.tst +#TESTCASES += shra_r_ob.tst +TESTCASES += shra_r_ph.tst +TESTCASES += shra_r_pw.tst +TESTCASES += shra_r_qh.tst +TESTCASES += shra_r_w.tst +TESTCASES += shrav_ph.tst +TESTCASES += shrav_pw.tst +TESTCASES += shrav_qh.tst +TESTCASES += shrav_r_ph.tst +TESTCASES += shrav_r_pw.tst +TESTCASES += shrav_r_qh.tst +TESTCASES += shrav_r_w.tst +TESTCASES += shrl_ob.tst +TESTCASES += shrl_qb.tst +#TESTCASES += shrl_qh.tst +TESTCASES += shrlv_ob.tst +TESTCASES += shrlv_qb.tst +#TESTCASES += shrlv_qh.tst +TESTCASES += subq_ph.tst +TESTCASES += subq_pw.tst +TESTCASES += subq_qh.tst +TESTCASES += subq_s_ph.tst +TESTCASES += subq_s_pw.tst +TESTCASES += subq_s_qh.tst +TESTCASES += subq_s_w.tst +TESTCASES += subu_ob.tst +TESTCASES += subu_qb.tst +TESTCASES += subu_s_ob.tst +TESTCASES += subu_s_qb.tst +TESTCASES += wrdsp.tst + +all: build + +head.o : head.S + $(Q)$(CC) $(HEAD_FLAGS) -D"STACK_TOP=0xffffffff80200000" -c $< -o $@ + +%.o : %.S + $(CC) $(CFLAGS) -c $< -o $@ + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +%.tst: %.o $(VECTORS_OBJ) + $(CC) $(VECTORS_OBJ) $(FLAGS) $(LDFLAGS) $< -o $@ + +build: $(VECTORS_OBJ) $(MIPSSOC_LIB) $(TESTCASES) + +check: $(VECTORS_OBJ) $(MIPSSOC_LIB) $(TESTCASES) + @for case in $(TESTCASES); do \ + echo $(SIM) $(SIMFLAGS) ./$$case; \ + $(SIM) $(SIMFLAGS) ./$$case & (sleep 1; killall $(SIM)); \ + done + +clean: + $(Q)rm -f *.o *.tst *.a diff --git a/tests/tcg/mips/mips64-dsp/absq_s_ob.c b/tests/tcg/mips/mips64-dsp/absq_s_ob.c new file mode 100644 index 0000000000..6214031578 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/absq_s_ob.c @@ -0,0 +1,63 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result, dspcontrol; + rt = 0x7F7F7F7F7F7F7F7F; + result = 0x7F7F7F7F7F7F7F7F; + + + __asm + (".set mips64\n\t" + "absq_s.ob %0 %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("absq_s.ob test 1 error\n"); + + return -1; + } + + __asm + ("rddsp %0\n\t" + : "=r"(rd) + ); + rd >> 20; + rd = rd & 0x1; + if (rd != 0) { + printf("absq_s.ob test 1 dspcontrol overflow flag error\n"); + + return -1; + } + + rt = 0x80FFFFFFFFFFFFFF; + result = 0x7F01010101010101; + + __asm + ("absq_s.ob %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (result != rd) { + printf("absq_s.ob test 2 error\n"); + + return -1; + } + + __asm + ("rddsp %0\n\t" + : "=r"(rd) + ); + rd = rd >> 20; + rd = rd & 0x1; + if (rd != 1) { + printf("absq_s.ob test 2 dspcontrol overflow flag error\n"); + + return -1; + } + + return 0; +} + diff --git a/tests/tcg/mips/mips64-dsp/absq_s_ph.c b/tests/tcg/mips/mips64-dsp/absq_s_ph.c new file mode 100644 index 0000000000..238416d438 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/absq_s_ph.c @@ -0,0 +1,37 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x10017EFD; + result = 0x10017EFD; + + __asm + ("absq_s.ph %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("absq_s.ph wrong\n"); + + return -1; + } + + rt = 0x8000A536; + result = 0x7FFF5ACA; + + __asm + ("absq_s.ph %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("absq_s.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/absq_s_pw.c b/tests/tcg/mips/mips64-dsp/absq_s_pw.c new file mode 100644 index 0000000000..48fc763b4f --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/absq_s_pw.c @@ -0,0 +1,66 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result, dspcontrol; + rd = 0; + rt = 0x7F7F7F7F7F7F7F7F; + result = 0x7F7F7F7F7F7F7F7F; + + + __asm + ("absq_s.pw %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("absq_s.pw test 1 error\n"); + + return -1; + } + + rd = 0; + __asm + ("rddsp %0\n\t" + : "=r"(rd) + ); + rd >> 20; + rd = rd & 0x1; + if (rd != 0) { + printf("absq_s.pw test 1 dspcontrol overflow flag error\n"); + + return -1; + } + + rd = 0; + rt = 0x80000000FFFFFFFF; + result = 0x7FFFFFFF00000001; + + __asm + ("absq_s.pw %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (result != rd) { + printf("absq_s.pw test 2 error\n"); + + return -1; + } + + rd = 0; + __asm + ("rddsp %0\n\t" + : "=r"(rd) + ); + rd = rd >> 20; + rd = rd & 0x1; + if (rd != 1) { + printf("absq_s.pw test 2 dspcontrol overflow flag error\n"); + + return -1; + } + + return 0; +} + diff --git a/tests/tcg/mips/mips64-dsp/absq_s_qh.c b/tests/tcg/mips/mips64-dsp/absq_s_qh.c new file mode 100644 index 0000000000..9001a9e164 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/absq_s_qh.c @@ -0,0 +1,40 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result, dspcontrol; + rd = 0; + rt = 0x7F7F7F7F7F7F7F7F; + result = 0x7F7F7F7F7F7F7F7F; + + + __asm + ("absq_s.qh %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("absq_s.qh test 1 error\n"); + + return -1; + } + + rd = 0; + rt = 0x8000FFFFFFFFFFFF; + result = 0x7FFF000100000001; + + __asm + ("absq_s.pw %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (result != rd) { + printf("absq_s.rw test 2 error\n"); + + return -1; + } + + return 0; +} + diff --git a/tests/tcg/mips/mips64-dsp/absq_s_w.c b/tests/tcg/mips/mips64-dsp/absq_s_w.c new file mode 100644 index 0000000000..414c8bd3f6 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/absq_s_w.c @@ -0,0 +1,48 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x80000000; + result = 0x7FFFFFFF; + __asm + ("absq_s.w %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("absq_s_w.ph wrong\n"); + + return -1; + } + + rt = 0x80030000; + result = 0x7FFD0000; + __asm + ("absq_s.w %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("absq_s_w.ph wrong\n"); + + return -1; + } + + rt = 0x31036080; + result = 0x31036080; + __asm + ("absq_s.w %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("absq_s_w.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/addq_ph.c b/tests/tcg/mips/mips64-dsp/addq_ph.c new file mode 100644 index 0000000000..22a36d9805 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/addq_ph.c @@ -0,0 +1,57 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long dsp; + long long result; + + rs = 0xFFFFFFFF; + rt = 0x10101010; + result = 0x100F100F; + __asm + ("addq.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("1 addq.ph wrong\n"); + + return -1; + } + + rs = 0x3712847D; + rt = 0x0031AF2D; + result = 0x374333AA; + __asm + ("addq.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("2 addq.ph wrong\n"); + + return -1; + } + + rs = 0x7fff847D; + rt = 0x0031AF2D; + result = 0xffffffff803033AA; + __asm + ("addq.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + __asm("rddsp %0\n\t" + : "=r"(dsp) + ); + + if (rd != result || (((dsp >> 20) & 0x01) != 1)) { + printf("3 addq.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/addq_pw.c b/tests/tcg/mips/mips64-dsp/addq_pw.c new file mode 100644 index 0000000000..99a7668c0c --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/addq_pw.c @@ -0,0 +1,46 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result, dspreg, dspresult; + + rs = 0x123456787FFFFFFF; + rt = 0x1111111100000101; + result = 0x2345678980000100; + dspresult = 0x1; + + __asm + ("addq.pw %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 20) & 0x01); + if ((rd != result) || (dspreg != dspresult)) { + printf("addq.pw error\n"); + + return -1; + } + + rs = 0x1234567880FFFFFF; + rt = 0x1111111180000001; + result = 0x2345678901000000; + dspresult = 0x1; + + __asm + ("addq.pw %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 20) & 0x01); + if ((rd != result) || (dspreg != dspresult)) { + printf("addq.pw error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/addq_qh.c b/tests/tcg/mips/mips64-dsp/addq_qh.c new file mode 100644 index 0000000000..4b874afb8a --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/addq_qh.c @@ -0,0 +1,28 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result, dspreg, dspresult; + + rs = 0x123456787FFF8010; + rt = 0x1111111100018000; + result = 0x2345678980000010; + dspresult = 0x1; + + __asm + ("addq.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 20) & 0x01); + + if ((rd != result) || (dspreg != dspresult)) { + printf("addq.qh error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/addq_s_ph.c b/tests/tcg/mips/mips64-dsp/addq_s_ph.c new file mode 100644 index 0000000000..ad84cdcfe0 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/addq_s_ph.c @@ -0,0 +1,84 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long dsp; + long long result; + + rs = 0xFFFFFFFF; + rt = 0x10101010; + result = 0x100F100F; + __asm + ("addq_s.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("1 addq_s.ph wrong\n"); + + return -1; + } + + rs = 0x3712847D; + rt = 0x0031AF2D; + result = 0x37438000; + __asm + ("addq_s.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + __asm + ("rddsp %0\n\t" + : "=r"(dsp) + ); + + if ((rd != result) || (((dsp >> 20) & 0x01) != 1)) { + printf("2 addq_s.ph wrong\n"); + + return -1; + } + + rs = 0x7fff847D; + rt = 0x0031AF2D; + result = 0x7fff8000; + __asm + ("addq_s.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + __asm + ("rddsp %0\n\t" + : "=r"(dsp) + ); + + if ((rd != result) || (((dsp >> 20) & 0x01) != 1)) { + printf("3 addq_s.ph wrong\n"); + + return -1; + } + + rs = 0x8030847D; + rt = 0x8a00AF2D; + result = 0xffffffff80008000; + __asm + ("addq_s.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + __asm + ("rddsp %0\n\t" + : "=r"(dsp) + ); + + if ((rd != result) || (((dsp >> 20) & 0x01) != 1)) { + printf("4 addq_s.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/addq_s_pw.c b/tests/tcg/mips/mips64-dsp/addq_s_pw.c new file mode 100644 index 0000000000..2e380bbfc5 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/addq_s_pw.c @@ -0,0 +1,45 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result, dspreg, dspresult; + rs = 0x123456787FFFFFFF; + rt = 0x1111111100000001; + result = 0x234567897FFFFFFF; + dspresult = 0x1; + + __asm + ("addq_s.pw %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 20) & 0x01); + if ((rd != result) || (dspreg != dspresult)) { + printf("addq_s.pw error\n"); + + return -1; + } + + rs = 0x80FFFFFFE00000FF; + rt = 0x80000001200000DD; + result = 0x80000000000001DC; + dspresult = 0x01; + + __asm + ("addq_s.pw %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 20) & 0x01); + if ((rd != result) || (dspreg != dspresult)) { + printf("addq_s.pw error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/addq_s_qh.c b/tests/tcg/mips/mips64-dsp/addq_s_qh.c new file mode 100644 index 0000000000..b638a2b93a --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/addq_s_qh.c @@ -0,0 +1,26 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result, dspreg, dspresult; + rs = 0x123456787FFF8000; + rt = 0x1111111100028000; + result = 0x234567897FFF8000; + dspresult = 0x1; + + __asm + ("addq_s.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 20) & 0x01); + if ((rd != result) || (dspreg != dspresult)) { + printf("addq_s.qh error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/addq_s_w.c b/tests/tcg/mips/mips64-dsp/addq_s_w.c new file mode 100644 index 0000000000..3e08f5d482 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/addq_s_w.c @@ -0,0 +1,48 @@ +#include "io.h" + +int main() +{ + long long rd, rs, rt; + long long result; + + rt = 0x10017EFD; + rs = 0x11111111; + result = 0x2112900e; + + __asm + ("addq_s.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("addq_s.w error\n"); + } + + rt = 0x80017EFD; + rs = 0x81111111; + result = 0xffffffff80000000; + + __asm + ("addq_s.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("addq_s.w error\n"); + } + + rt = 0x7fffffff; + rs = 0x01111111; + result = 0x7fffffff; + + __asm + ("addq_s.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("addq_s.w error\n"); + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/addsc.c b/tests/tcg/mips/mips64-dsp/addsc.c new file mode 100644 index 0000000000..4b684b9b99 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/addsc.c @@ -0,0 +1,39 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long dsp; + long long result; + + rs = 0x0000000F; + rt = 0x00000001; + result = 0x00000010; + __asm + ("addsc %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("1 addsc wrong\n"); + + return -1; + } + + rs = 0xFFFF0FFF; + rt = 0x00010111; + result = 0x00001110; + __asm + ("addsc %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + if ((rd != result) || (((dsp >> 13) & 0x01) != 1)) { + printf("2 addsc wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/addu_ob.c b/tests/tcg/mips/mips64-dsp/addu_ob.c new file mode 100644 index 0000000000..17f9c668c0 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/addu_ob.c @@ -0,0 +1,28 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result, dspreg, dspresult; + + rs = 0x123456789ABCDEF0; + rt = 0x3456123498DEF390; + result = 0x468A68AC329AD180; + dspresult = 0x01; + + __asm + ("addu.ob %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 20) & 0x01); + + if ((rd != result) || (dspreg != dspresult)) { + printf("addu.ob error\n\t"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/addu_qb.c b/tests/tcg/mips/mips64-dsp/addu_qb.c new file mode 100644 index 0000000000..3b9b5fc5bb --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/addu_qb.c @@ -0,0 +1,40 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long dsp; + long long result; + + rs = 0x00FF00FF; + rt = 0x00010001; + result = 0x00000000; + __asm + ("addu.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + if ((rd != result) || (((dsp >> 20) & 0x01) != 1)) { + printf("1 addu.qb wrong\n"); + + return -1; + } + + rs = 0xFFFF1111; + rt = 0x00020001; + result = 0xFFFFFFFFFF011112; + __asm + ("addu.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + if ((rd != result) || (((dsp >> 20) & 0x01) != 1)) { + printf("2 addu.qb wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/addu_s_ob.c b/tests/tcg/mips/mips64-dsp/addu_s_ob.c new file mode 100644 index 0000000000..e89a4638b7 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/addu_s_ob.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result, dspreg, dspresult; + rs = 0x123456789ABCDEF0; + rt = 0x3456123498DEF390; + result = 0x468A68ACFFFFFFFF; + dspresult = 0x01; + + __asm + ("addu_s.ob %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 20) & 0x01); + + if ((rd != result) || (dspreg != dspresult)) { + printf("addu_s.ob error\n\t"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/addu_s_qb.c b/tests/tcg/mips/mips64-dsp/addu_s_qb.c new file mode 100644 index 0000000000..cb84293ade --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/addu_s_qb.c @@ -0,0 +1,40 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long dsp; + long long result; + + rs = 0x10FF01FF; + rt = 0x10010001; + result = 0x20FF01FF; + __asm + ("addu_s.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + if ((rd != result) || (((dsp >> 20) & 0x1) != 1)) { + printf("1 addu_s.qb error 1\n"); + + return -1; + } + + rs = 0xFFFFFFFFFFFF1111; + rt = 0x00020001; + result = 0xFFFFFFFFFFFF1112; + __asm + ("addu_s.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + if ((rd != result) || (((dsp >> 20) & 0x1) != 1)) { + printf("2 addu_s.qb error 2\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/addwc.c b/tests/tcg/mips/mips64-dsp/addwc.c new file mode 100644 index 0000000000..5929cd2f5c --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/addwc.c @@ -0,0 +1,59 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long dspi, dspo; + long long result; + + rs = 0x10FF01FF; + rt = 0x10010001; + dspi = 0x00002000; + result = 0x21000201; + __asm + ("wrdsp %3\n" + "addwc %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt), "r"(dspi) + ); + if (rd != result) { + printf("1 addwc wrong\n"); + + return -1; + } + + rs = 0xFFFF1111; + rt = 0x00020001; + dspi = 0x00; + result = 0x00011112; + __asm + ("wrdsp %3\n" + "addwc %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt), "r"(dspi) + ); + if (rd != result) { + printf("2 addwc wrong\n"); + + return -1; + } + + rs = 0x8FFF1111; + rt = 0x80020001; + dspi = 0x00; + result = 0x10011112; + __asm + ("wrdsp %4\n" + "addwc %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspo) + : "r"(rs), "r"(rt), "r"(dspi) + ); + if ((rd != result) || (((dspo >> 20) & 0x01) != 1)) { + printf("3 addwc wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/bitrev.c b/tests/tcg/mips/mips64-dsp/bitrev.c new file mode 100644 index 0000000000..ac24ef3f5c --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/bitrev.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x12345678; + result = 0x00001E6A; + + __asm + ("bitrev %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("bitrev wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/bposge32.c b/tests/tcg/mips/mips64-dsp/bposge32.c new file mode 100644 index 0000000000..97bce44602 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/bposge32.c @@ -0,0 +1,50 @@ +#include "io.h" + +int main(void) +{ + long long dsp, sum; + long long result; + + dsp = 0x20; + sum = 0x01; + result = 0x02; + + __asm + ("wrdsp %1\n\t" + "bposge32 test1\n\t" + "nop\n\t" + "addi %0, 0xA2\n\t" + "nop\n\t" + "test1:\n\t" + "addi %0, 0x01\n\t" + : "+r"(sum) + : "r"(dsp) + ); + if (sum != result) { + printf("bposge32 wrong\n"); + + return -1; + } + + dsp = 0x10; + sum = 0x01; + result = 0xA4; + + __asm + ("wrdsp %1\n\t" + "bposge32 test2\n\t" + "nop\n\t" + "addi %0, 0xA2\n\t" + "nop\n\t" + "test2:\n\t" + "addi %0, 0x01\n\t" + : "+r"(sum) + : "r"(dsp) + ); + if (sum != result) { + printf("bposge32 wrong\n"); + + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/bposge64.c b/tests/tcg/mips/mips64-dsp/bposge64.c new file mode 100644 index 0000000000..36161ad852 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/bposge64.c @@ -0,0 +1,50 @@ +#include "io.h" + +int main(void) +{ + long long dsp, sum; + long long result; + + dsp = 0x40; + sum = 0x01; + result = 0x02; + + __asm + ("wrdsp %1\n\t" + "bposge64 test1\n\t" + "nop\n\t" + "addi %0, 0xA2\n\t" + "nop\n\t" + "test1:\n\t" + "addi %0, 0x01\n\t" + : "+r"(sum) + : "r"(dsp) + ); + if (sum != result) { + printf("bposge64 wrong\n"); + + return -1; + } + + dsp = 0x10; + sum = 0x01; + result = 0xA4; + + __asm + ("wrdsp %1\n\t" + "bposge64 test2\n\t" + "nop\n\t" + "addi %0, 0xA2\n\t" + "nop\n\t" + "test2:\n\t" + "addi %0, 0x01\n\t" + : "+r"(sum) + : "r"(dsp) + ); + if (sum != result) { + printf("bposge64 wrong\n"); + + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmp_eq_ph.c b/tests/tcg/mips/mips64-dsp/cmp_eq_ph.c new file mode 100644 index 0000000000..63069d0dab --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmp_eq_ph.c @@ -0,0 +1,42 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x11777066; + rt = 0x55AA33FF; + result = 0x00; + __asm + ("cmp.eq.ph %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + rd = (rd >> 24) & 0x03; + if (rd != result) { + printf("cmp.eq.ph wrong\n"); + + return -1; + } + + rs = 0x11777066; + rt = 0x11777066; + result = 0x03; + __asm + ("cmp.eq.ph %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + rd = (rd >> 24) & 0x03; + if (rd != result) { + printf("cmp.eq.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmp_eq_pw.c b/tests/tcg/mips/mips64-dsp/cmp_eq_pw.c new file mode 100644 index 0000000000..bae4c06ccb --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmp_eq_pw.c @@ -0,0 +1,46 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, dspreg, dspresult; + + rs = 0x123456789ABCDEFF; + rt = 0x123456789ABCDEFF; + dspresult = 0x03; + + __asm + ("cmp.eq.pw %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0x03); + + if (dspreg != dspresult) { + printf("1 cmp.eq.pw error\n"); + + return -1; + } + + rs = 0x123456799ABCDEFe; + rt = 0x123456789ABCDEFF; + dspresult = 0x00; + + __asm + ("cmp.eq.pw %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0x03); + + if (dspreg != dspresult) { + printf("2 cmp.eq.pw error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmp_eq_qh.c b/tests/tcg/mips/mips64-dsp/cmp_eq_qh.c new file mode 100644 index 0000000000..49ea271003 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmp_eq_qh.c @@ -0,0 +1,46 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, dspreg, dspresult; + + rs = 0x123456789ABCDEF0; + rt = 0x123456789ABCDEFF; + dspresult = 0x0E; + + __asm + ("cmp.eq.qh %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0x0F); + + if (dspreg != dspresult) { + printf("cmp.eq.qh error\n"); + + return -1; + } + + rs = 0x12355a789A4CD3F0; + rt = 0x123456789ABCDEFF; + dspresult = 0x00; + + __asm + ("cmp.eq.qh %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0x0F); + + if (dspreg != dspresult) { + printf("cmp.eq.qh error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmp_le_ph.c b/tests/tcg/mips/mips64-dsp/cmp_le_ph.c new file mode 100644 index 0000000000..12d24f1783 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmp_le_ph.c @@ -0,0 +1,40 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x11777066; + rt = 0x55AA33FF; + result = 0x02; + __asm + ("cmp.le.ph %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + rd = (rd >> 24) & 0x03; + if (rd != result) { + printf("cmp.le.ph wrong\n"); + + return -1; + } + rs = 0x11777066; + rt = 0x11777066; + result = 0x03; + __asm + ("cmp.le.ph %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + rd = (rd >> 24) & 0x03; + if (rd != result) { + printf("cmp.le.ph wrong\n"); + + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmp_le_pw.c b/tests/tcg/mips/mips64-dsp/cmp_le_pw.c new file mode 100644 index 0000000000..6acc43cd5b --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmp_le_pw.c @@ -0,0 +1,46 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, dspreg, dspresult; + + rs = 0x123456789ABCDEF0; + rt = 0x123456789ABCDEFF; + dspresult = 0x03; + + __asm + ("cmp.le.pw %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0x03); + + if (dspreg != dspresult) { + printf("1 cmp.le.pw error\n"); + + return -1; + } + + rs = 0x123456799ABCEEFF; + rt = 0x123456789ABCDEFF; + dspresult = 0x00; + + __asm + ("cmp.le.pw %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0x03); + + if (dspreg != dspresult) { + printf("2 cmp.le.pw error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmp_le_qh.c b/tests/tcg/mips/mips64-dsp/cmp_le_qh.c new file mode 100644 index 0000000000..c9ce21667f --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmp_le_qh.c @@ -0,0 +1,46 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, dspreg, dspresult; + + rs = 0x123456789ABCDEF0; + rt = 0x123456789ABCDEFF; + dspresult = 0x0F; + + __asm + ("cmp.le.qh %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0x0F); + + if (dspreg != dspresult) { + printf("cmp.le.qh error\n"); + + return -1; + } + + rs = 0x823456789ABCDEF0; + rt = 0x123456789ABCDEFF; + dspresult = 0x0f; + + __asm + ("cmp.le.qh %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0x0F); + + if (dspreg != dspresult) { + printf("cmp.le.qh error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmp_lt_ph.c b/tests/tcg/mips/mips64-dsp/cmp_lt_ph.c new file mode 100644 index 0000000000..1d91228c3a --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmp_lt_ph.c @@ -0,0 +1,41 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x11777066; + rt = 0x55AA33FF; + result = 0x02; + __asm + ("cmp.lt.ph %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + rd = (rd >> 24) & 0x03; + if (rd != result) { + printf("cmp.lt.ph wrong\n"); + + return -1; + } + rs = 0x11777066; + rt = 0x11777066; + result = 0x00; + __asm + ("cmp.lt.ph %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + rd = (rd >> 24) & 0x03; + if (rd != result) { + printf("cmp.lt.ph2 wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmp_lt_pw.c b/tests/tcg/mips/mips64-dsp/cmp_lt_pw.c new file mode 100644 index 0000000000..87e74caf38 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmp_lt_pw.c @@ -0,0 +1,46 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, dspreg, dspresult; + + rs = 0x123456789ABCDEF0; + rt = 0x123456789ABCDEFF; + dspresult = 0x01; + + __asm + ("cmp.lt.pw %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0x03); + + if (dspreg != dspresult) { + printf("cmp.lt.pw error\n"); + + return -1; + } + + rs = 0x123456779ABCDEFf; + rt = 0x123456789ABCDEFF; + dspresult = 0x02; + + __asm + ("cmp.lt.pw %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0x03); + + if (dspreg != dspresult) { + printf("cmp.lt.pw error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmp_lt_qh.c b/tests/tcg/mips/mips64-dsp/cmp_lt_qh.c new file mode 100644 index 0000000000..0a13a5eaae --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmp_lt_qh.c @@ -0,0 +1,46 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, dspreg, dspresult; + + rs = 0x123558789ABCDEF0; + rt = 0x123456789ABCDEFF; + dspresult = 0x01; + + __asm + ("cmp.lt.qh %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0x0F); + + if (dspreg != dspresult) { + printf("cmp.lt.qh error\n"); + + return -1; + } + + rs = 0x123356779ABbDEF0; + rt = 0x123456789ABCDEFF; + dspresult = 0x0f; + + __asm + ("cmp.lt.qh %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0x0F); + + if (dspreg != dspresult) { + printf("cmp.lt.qh error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmpgu_eq_ob.c b/tests/tcg/mips/mips64-dsp/cmpgu_eq_ob.c new file mode 100644 index 0000000000..697d73dd1a --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmpgu_eq_ob.c @@ -0,0 +1,40 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result; + + rs = 0x123456789ABCDEF0; + rt = 0x123456789ABCDEFF; + result = 0xFE; + + __asm + ("cmpgu.eq.ob %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("cmpgu.eq.ob error\n"); + + return -1; + } + + rs = 0x133456789ABCDEF0; + rt = 0x123556789ABCDEFF; + result = 0x3E; + + __asm + ("cmpgu.eq.ob %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("cmpgu.eq.ob error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmpgu_eq_qb.c b/tests/tcg/mips/mips64-dsp/cmpgu_eq_qb.c new file mode 100644 index 0000000000..b41c4430fd --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmpgu_eq_qb.c @@ -0,0 +1,38 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x02; + __asm + ("cmpgu.eq.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("cmpgu.eq.ph wrong\n"); + + return -1; + } + + rs = 0x11777066; + rt = 0x11777066; + result = 0x0F; + __asm + ("cmpgu.eq.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("cmpgu.eq.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmpgu_le_ob.c b/tests/tcg/mips/mips64-dsp/cmpgu_le_ob.c new file mode 100644 index 0000000000..8b65f18c00 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmpgu_le_ob.c @@ -0,0 +1,40 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result; + + rs = 0x123456789ABCDEF0; + rt = 0x123456789ABCDEFF; + result = 0xFF; + + __asm + ("cmpgu.le.ob %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("cmpgu.le.ob error\n"); + + return -1; + } + + rs = 0x823556789ABCDEF0; + rt = 0x123456789ABCDEFF; + result = 0x3F; + + __asm + ("cmpgu.le.ob %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("cmpgu.le.ob error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmpgu_le_qb.c b/tests/tcg/mips/mips64-dsp/cmpgu_le_qb.c new file mode 100644 index 0000000000..dd2b091f61 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmpgu_le_qb.c @@ -0,0 +1,37 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x0F; + __asm + ("cmpgu.le.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("cmpgu.le.qb wrong\n"); + + return -1; + } + + rs = 0x11777066; + rt = 0x11766066; + result = 0x09; + __asm + ("cmpgu.le.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("cmpgu.le.qb wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmpgu_lt_ob.c b/tests/tcg/mips/mips64-dsp/cmpgu_lt_ob.c new file mode 100644 index 0000000000..3e5c9dd6da --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmpgu_lt_ob.c @@ -0,0 +1,40 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result; + + rs = 0x123456789ABCDEF0; + rt = 0x123456789ABCDEFF; + result = 0x01; + + __asm + ("cmpgu.lt.ob %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("cmpgu.lt.ob error\n"); + + return -1; + } + + rs = 0x823455789ABCDEF0; + rt = 0x123356789ABCDEFF; + result = 0x21; + + __asm + ("cmpgu.lt.ob %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("cmpgu.lt.ob error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmpgu_lt_qb.c b/tests/tcg/mips/mips64-dsp/cmpgu_lt_qb.c new file mode 100644 index 0000000000..a467cb78db --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmpgu_lt_qb.c @@ -0,0 +1,38 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x0D; + __asm + ("cmpgu.lt.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("cmpgu.lt.qb wrong\n"); + + return -1; + } + + rs = 0x11777066; + rt = 0x11766066; + result = 0x00; + __asm + ("cmpgu.lt.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("cmpgu.lt.qb wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmpu_eq_ob.c b/tests/tcg/mips/mips64-dsp/cmpu_eq_ob.c new file mode 100644 index 0000000000..4d1983e5ea --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmpu_eq_ob.c @@ -0,0 +1,46 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dspreg, dspresult; + + rs = 0x123456789ABCDEF0; + rt = 0x123456789ABCDEFF; + dspresult = 0xFE; + + __asm + ("cmpu.eq.ob %1, %2\n\t" + "rddsp %0" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0xFF); + + if (dspreg != dspresult) { + printf("cmpu.eq.ob error\n"); + + return -1; + } + + rs = 0x133516713A0CD1F0; + rt = 0x123456789ABCDEFF; + dspresult = 0x00; + + __asm + ("cmpu.eq.ob %1, %2\n\t" + "rddsp %0" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0xFF); + + if (dspreg != dspresult) { + printf("cmpu.eq.ob error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmpu_eq_qb.c b/tests/tcg/mips/mips64-dsp/cmpu_eq_qb.c new file mode 100644 index 0000000000..28f3bec252 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmpu_eq_qb.c @@ -0,0 +1,42 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long dsp; + long long result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x02; + __asm + ("cmpu.eq.qb %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + if (dsp != result) { + printf("cmpu.eq.qb wrong\n"); + + return -1; + } + + rs = 0x11777066; + rt = 0x11777066; + result = 0x0F; + __asm + ("cmpu.eq.qb %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + if (dsp != result) { + printf("cmpu.eq.qb wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmpu_le_ob.c b/tests/tcg/mips/mips64-dsp/cmpu_le_ob.c new file mode 100644 index 0000000000..8acbd1c4ba --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmpu_le_ob.c @@ -0,0 +1,44 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, dspreg, dspresult; + + rs = 0x123456789ABCDEF0; + rt = 0x123456789ABCDEFF; + dspresult = 0xFF; + + __asm + ("cmpu.le.ob %1, %2\n\t" + "rddsp %0" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = dspreg >> 24; + if (dspreg != dspresult) { + printf("cmpu.le.ob error\n"); + + return -1; + } + + rs = 0x823656789ABCDEF0; + rt = 0x123456789ABCDEFF; + dspresult = 0x3F; + + __asm + ("cmpu.le.ob %1, %2\n\t" + "rddsp %0" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = dspreg >> 24; + if (dspreg != dspresult) { + printf("cmpu.le.ob error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmpu_le_qb.c b/tests/tcg/mips/mips64-dsp/cmpu_le_qb.c new file mode 100644 index 0000000000..8a17a08513 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmpu_le_qb.c @@ -0,0 +1,41 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long dsp; + long long result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x0F; + __asm + ("cmpu.le.qb %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + if (dsp != result) { + printf("cmpu.le.qb wrong\n"); + + return -1; + } + + rs = 0x11777066; + rt = 0x11777066; + result = 0x0F; + __asm + ("cmpu.le.qb %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + if (dsp != result) { + printf("cmpu.le.qb wrong\n"); + + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmpu_lt_ob.c b/tests/tcg/mips/mips64-dsp/cmpu_lt_ob.c new file mode 100644 index 0000000000..34e312d818 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmpu_lt_ob.c @@ -0,0 +1,44 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, dspreg, dspresult; + + rs = 0x123456789ABCDEF0; + rt = 0x123456789ABCDEFF; + dspresult = 0x01; + + __asm + ("cmpu.lt.ob %1, %2\n\t" + "rddsp %0" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = dspreg >> 24; + if (dspreg != dspresult) { + printf("cmpu.lt.ob error\n"); + + return -1; + } + + rs = 0x823156789ABCDEF0; + rt = 0x123456789ABCDEFF; + dspresult = 0x41; + + __asm + ("cmpu.lt.ob %1, %2\n\t" + "rddsp %0" + : "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = dspreg >> 24; + if (dspreg != dspresult) { + printf("cmpu.lt.ob error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/cmpu_lt_qb.c b/tests/tcg/mips/mips64-dsp/cmpu_lt_qb.c new file mode 100644 index 0000000000..adb75eed52 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/cmpu_lt_qb.c @@ -0,0 +1,42 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long dsp; + long long result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x0D; + __asm + ("cmpu.lt.qb %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + if (dsp != result) { + printf("cmpu.lt.qb wrong\n"); + + return -1; + } + + rs = 0x11777066; + rt = 0x11777066; + result = 0x00; + __asm + ("cmpu.lt.qb %1, %2\n\t" + "rddsp %0\n\t" + : "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + if (dsp != result) { + printf("cmpu.lt.qb wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dappend.c b/tests/tcg/mips/mips64-dsp/dappend.c new file mode 100644 index 0000000000..ba8e12182e --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dappend.c @@ -0,0 +1,37 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs; + long long res; + rt = 0x1234567887654321; + rs = 0xabcd1234abcd8765; + + res = 0x1234567887654321; + __asm + ("dappend %0, %1, 0x0\n\t" + : "=r"(rt) + : "r"(rs) + ); + + if (rt != res) { + printf("dappend error\n"); + return -1; + } + + rt = 0x1234567887654321; + rs = 0xabcd1234abcd8765; + + res = 0x2345678876543215; + __asm + ("dappend %0, %1, 0x4\n\t" + : "=r"(rt) + : "r"(rs) + ); + + if (rt != res) { + printf("dappend error\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextp.c b/tests/tcg/mips/mips64-dsp/dextp.c new file mode 100644 index 0000000000..a469cc0366 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextp.c @@ -0,0 +1,54 @@ +#include "io.h" + +int main(void) +{ + long long rt, dsp; + long long achi, acli; + long long res, resdsp; + int rs; + + rs = 0xabcd1234; + + achi = 0x12345678; + acli = 0x87654321; + res = 0xff; + resdsp = 0x0; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "wrdsp %4\n\t" + "dextp %0, $ac1, 0x7\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs) + ); + dsp = (dsp >> 14) & 0x1; + if ((dsp != resdsp) || (rt != res)) { + printf("dextp error\n"); + return -1; + } + + rs = 0xabcd1200; + + achi = 0x12345678; + acli = 0x87654321; + resdsp = 0x1; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "wrdsp %4\n\t" + "dextp %0, $ac1, 0x7\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs) + ); + dsp = (dsp >> 14) & 0x1; + if (dsp != resdsp) { + printf("dextp error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextpdp.c b/tests/tcg/mips/mips64-dsp/dextpdp.c new file mode 100644 index 0000000000..a2361e2d42 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextpdp.c @@ -0,0 +1,59 @@ +#include "io.h" + +int main(void) +{ + long long rt, dsp; + long long achi, acli; + long long res, resdsp, resdsppos; + int rs; + int tmp1, tmp2; + + rs = 0xabcd1234; + + achi = 0x12345678; + acli = 0x87654321; + res = 0xff; + resdsp = 0x0; + resdsppos = 0x2c; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "wrdsp %4\n\t" + "dextpdp %0, $ac1, 0x7\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs) + ); + tmp1 = (dsp >> 14) & 0x1; + tmp2 = dsp & 0x3f; + + if ((tmp1 != resdsp) || (rt != res) || (tmp2 != resdsppos)) { + printf("dextpdp error\n"); + return -1; + } + + rs = 0xabcd1200; + + achi = 0x12345678; + acli = 0x87654321; + resdsp = 0x1; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "wrdsp %4\n\t" + "dextpdp %0, $ac1, 0x7\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs) + ); + tmp1 = (dsp >> 14) & 0x1; + + if (tmp1 != resdsp) { + printf("dextpdp error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextpdpv.c b/tests/tcg/mips/mips64-dsp/dextpdpv.c new file mode 100644 index 0000000000..09c0b5b412 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextpdpv.c @@ -0,0 +1,63 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long achi, acli; + long long res, resdsp, resdsppos; + int rsdsp; + int tmp1, tmp2; + + rsdsp = 0xabcd1234; + rs = 0x7; + achi = 0x12345678; + acli = 0x87654321; + res = 0xff; + resdsp = 0x0; + resdsppos = 0x2c; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "wrdsp %4, 0x1\n\t" + "wrdsp %4\n\t" + "dextpdpv %0, $ac1, %5\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rsdsp), "r"(rs) + ); + + tmp1 = (dsp >> 14) & 0x1; + tmp2 = dsp & 0x3f; + + if ((tmp1 != resdsp) || (rt != res) || (tmp2 != resdsppos)) { + printf("dextpdpv error\n"); + return -1; + } + + rsdsp = 0xabcd1200; + rs = 0x7; + achi = 0x12345678; + acli = 0x87654321; + resdsp = 0x1; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "wrdsp %4, 0x1\n\t" + "wrdsp %4\n\t" + "dextpdpv %0, $ac1, %5\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rsdsp), "r"(rs) + ); + + tmp1 = (dsp >> 14) & 0x1; + + if (tmp1 != resdsp) { + printf("dextpdpv error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextpv.c b/tests/tcg/mips/mips64-dsp/dextpv.c new file mode 100644 index 0000000000..2626f3d98c --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextpv.c @@ -0,0 +1,58 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long achi, acli; + long long res, resdsp; + int rsdsp; + + rsdsp = 0xabcd1234; + rs = 0x7; + + achi = 0x12345678; + acli = 0x87654321; + res = 0xff; + resdsp = 0x0; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "wrdsp %4, 0x1\n\t" + "wrdsp %4\n\t" + "dextpv %0, $ac1, %5\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rsdsp), "r"(rs) + ); + dsp = (dsp >> 14) & 0x1; + if ((dsp != resdsp) || (rt != res)) { + printf("dextpv error\n"); + return -1; + } + + rsdsp = 0xabcd1200; + rs = 0x7; + + achi = 0x12345678; + acli = 0x87654321; + resdsp = 0x1; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "wrdsp %4, 0x1\n\t" + "wrdsp %4\n\t" + "dextpv %0, $ac1, %5\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rsdsp), "r"(rs) + ); + dsp = (dsp >> 14) & 0x1; + if (dsp != resdsp) { + printf("dextpv error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextr_l.c b/tests/tcg/mips/mips64-dsp/dextr_l.c new file mode 100644 index 0000000000..538846df18 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextr_l.c @@ -0,0 +1,44 @@ +#include "io.h" + +int main(void) +{ + long long rt; + long long achi, acli; + long long res; + + achi = 0x87654321; + acli = 0x12345678; + + res = 0x2100000000123456; + + __asm + ("mthi %1, $ac1\n\t" + "mtlo %2, $ac1\n\t" + "dextr.l %0, $ac1, 0x8\n\t" + : "=r"(rt) + : "r"(achi), "r"(acli) + ); + if (rt != res) { + printf("dextr.l error\n"); + return -1; + } + + achi = 0x87654321; + acli = 0x12345678; + + res = 0x12345678; + + __asm + ("mthi %1, $ac1\n\t" + "mtlo %2, $ac1\n\t" + "dextr.l %0, $ac1, 0x0\n\t" + : "=r"(rt) + : "r"(achi), "r"(acli) + ); + if (rt != res) { + printf("dextr.l error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextr_r_l.c b/tests/tcg/mips/mips64-dsp/dextr_r_l.c new file mode 100644 index 0000000000..a10a9ab40e --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextr_r_l.c @@ -0,0 +1,54 @@ +#include "io.h" + +int main(void) +{ + long long rt, dsp; + long long achi, acli; + long long res, resdsp; + + achi = 0x87654321; + acli = 0x12345678; + + res = 0x2100000000123456; + resdsp = 0x01; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextr_r.l %0, $ac1, 0x8\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli) + ); + + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextr_r.l error\n"); + return -1; + } + + achi = 0x87654321; + acli = 0x12345678; + + res = 0x12345678; + resdsp = 0x01; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextr_r.l %0, $ac1, 0x0\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli) + ); + + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextr_r.l error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextr_r_w.c b/tests/tcg/mips/mips64-dsp/dextr_r_w.c new file mode 100644 index 0000000000..2774e9bfcc --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextr_r_w.c @@ -0,0 +1,54 @@ +#include "io.h" + +int main(void) +{ + long long rt, dsp; + long long achi, acli; + long long res, resdsp; + + achi = 0x87654321; + acli = 0x12345678; + + res = 0x123456; + resdsp = 0x01; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextr_r.w %0, $ac1, 0x8\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli) + ); + + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextr_r.w error\n"); + return -1; + } + + achi = 0x87654321; + acli = 0x12345678; + + res = 0x12345678; + resdsp = 0x01; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextr_r.w %0, $ac1, 0x0\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli) + ); + + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextr_r.w error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextr_rs_l.c b/tests/tcg/mips/mips64-dsp/dextr_rs_l.c new file mode 100644 index 0000000000..1a202fefa2 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextr_rs_l.c @@ -0,0 +1,52 @@ +#include "io.h" + +int main(void) +{ + long long rt, dsp; + long long achi, acli; + long long res, resdsp; + + achi = 0x87654321; + acli = 0x12345678; + + res = 0x8000000000000000; + resdsp = 0x1; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextr_rs.l %0, $ac1, 0x8\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli) + ); + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextr_rs.l error\n"); + return -1; + } + + achi = 0x00; + acli = 0x12345678; + + res = 0x12345678; + resdsp = 0x1; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextr_rs.l %0, $ac1, 0x0\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli) + ); + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextr_rs.l error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextr_rs_w.c b/tests/tcg/mips/mips64-dsp/dextr_rs_w.c new file mode 100644 index 0000000000..ebe5f99db0 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextr_rs_w.c @@ -0,0 +1,52 @@ +#include "io.h" + +int main(void) +{ + long long rt, dsp; + long long achi, acli; + long long res, resdsp; + + achi = 0x87654321; + acli = 0x12345678; + + res = 0xffffffff80000000; + resdsp = 0x1; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextr_rs.w %0, $ac1, 0x8\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli) + ); + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextr_rs.w error\n"); + return -1; + } + + achi = 0x00; + acli = 0x12345678; + + res = 0x123456; + resdsp = 0x1; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextr_rs.w %0, $ac1, 0x8\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli) + ); + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextr_rs.w error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextr_s_h.c b/tests/tcg/mips/mips64-dsp/dextr_s_h.c new file mode 100644 index 0000000000..1adb5549a9 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextr_s_h.c @@ -0,0 +1,73 @@ +#include "io.h" + +int main(void) +{ + long long rt, dsp; + long long achi, acli; + long long res, resdsp; + + achi = 0x87654321; + acli = 0x12345678; + + res = 0xffffffffffff8000; + resdsp = 0x1; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextr_s.h %0, $ac1, 0x8\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli) + ); + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("1 dextr_s.h error\n"); + return -1; + } + + achi = 0x77654321; + acli = 0x12345678; + + res = 0x7fff; + resdsp = 0x1; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextr_s.h %0, $ac1, 0x8\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli) + ); + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("2 dextr_s.h error\n"); + return -1; + } + + achi = 0x00; + acli = 0x78; + + res = 0x7; + resdsp = 0x1; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextr_s.h %0, $ac1, 0x4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli) + ); + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("3 dextr_s.h error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextr_w.c b/tests/tcg/mips/mips64-dsp/dextr_w.c new file mode 100644 index 0000000000..79bed5da35 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextr_w.c @@ -0,0 +1,44 @@ +#include "io.h" + +int main(void) +{ + long long rt; + long long achi, acli; + long long res; + + achi = 0x87654321; + acli = 0x12345678; + + res = 0x123456; + + __asm + ("mthi %1, $ac1\n\t" + "mtlo %2, $ac1\n\t" + "dextr.w %0, $ac1, 0x8\n\t" + : "=r"(rt) + : "r"(achi), "r"(acli) + ); + if (rt != res) { + printf("dextr.w error\n"); + return -1; + } + + achi = 0x87654321; + acli = 0x12345678; + + res = 0x12345678; + + __asm + ("mthi %1, $ac1\n\t" + "mtlo %2, $ac1\n\t" + "dextr.w %0, $ac1, 0x0\n\t" + : "=r"(rt) + : "r"(achi), "r"(acli) + ); + if (rt != res) { + printf("dextr.w error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextrv_l.c b/tests/tcg/mips/mips64-dsp/dextrv_l.c new file mode 100644 index 0000000000..2e6187f729 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextrv_l.c @@ -0,0 +1,46 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs; + long long achi, acli; + long long res; + + achi = 0x87654321; + acli = 0x12345678; + rs = 0x8; + + res = 0x2100000000123456; + + __asm + ("mthi %1, $ac1\n\t" + "mtlo %2, $ac1\n\t" + "dextrv.l %0, $ac1, %3\n\t" + : "=r"(rt) + : "r"(achi), "r"(acli), "r"(rs) + ); + if (rt != res) { + printf("dextrv.l error\n"); + return -1; + } + + achi = 0x87654321; + acli = 0x12345678; + rs = 0x0; + + res = 0x12345678; + + __asm + ("mthi %1, $ac1\n\t" + "mtlo %2, $ac1\n\t" + "dextrv.l %0, $ac1, %3\n\t" + : "=r"(rt) + : "r"(achi), "r"(acli), "r"(rs) + ); + if (rt != res) { + printf("dextrv.l error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextrv_r_l.c b/tests/tcg/mips/mips64-dsp/dextrv_r_l.c new file mode 100644 index 0000000000..b47a0177d4 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextrv_r_l.c @@ -0,0 +1,56 @@ +#include "io.h" + +int main(void) +{ + long long rt, dsp, rs; + long long achi, acli; + long long res, resdsp; + + achi = 0x87654321; + acli = 0x12345678; + rs = 0x8; + + res = 0x2100000000123456; + resdsp = 0x01; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextrv_r.l %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs) + ); + + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextrv_r.l error\n"); + return -1; + } + + achi = 0x87654321; + acli = 0x12345678; + rs = 0x0; + + res = 0x12345678; + resdsp = 0x01; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextrv_r.l %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs) + ); + + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextrv_r.l error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextrv_r_w.c b/tests/tcg/mips/mips64-dsp/dextrv_r_w.c new file mode 100644 index 0000000000..cd201deb21 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextrv_r_w.c @@ -0,0 +1,56 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long achi, acli; + long long res, resdsp; + + achi = 0x87654321; + acli = 0x12345678; + rs = 0x8; + + res = 0x123456; + resdsp = 0x01; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextrv_r.w %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs) + ); + + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextrv_r.w error\n"); + return -1; + } + + achi = 0x87654321; + acli = 0x12345678; + rs = 0x0; + + res = 0x12345678; + resdsp = 0x01; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextrv_r.w %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs) + ); + + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextrv_r.w error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextrv_rs_l.c b/tests/tcg/mips/mips64-dsp/dextrv_rs_l.c new file mode 100644 index 0000000000..6ce4185462 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextrv_rs_l.c @@ -0,0 +1,54 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long achi, acli; + long long res, resdsp; + + achi = 0x87654321; + acli = 0x12345678; + rs = 0x8; + + res = 0x8000000000000000; + resdsp = 0x1; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextrv_rs.l %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs) + ); + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextrv_rs.l error\n"); + return -1; + } + + achi = 0x00; + acli = 0x12345678; + rs = 0x0; + + res = 0x12345678; + resdsp = 0x1; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextrv_rs.l %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs) + ); + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextrv_rs.l error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextrv_rs_w.c b/tests/tcg/mips/mips64-dsp/dextrv_rs_w.c new file mode 100644 index 0000000000..a65183c030 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextrv_rs_w.c @@ -0,0 +1,54 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long achi, acli; + long long res, resdsp; + + achi = 0x87654321; + acli = 0x12345678; + rs = 0x8; + + res = 0xffffffff80000000; + resdsp = 0x1; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextrv_rs.w %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs) + ); + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextrv_rs.w error\n"); + return -1; + } + + achi = 0x00; + acli = 0x12345678; + rs = 0x8; + + res = 0x123456; + resdsp = 0x1; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextrv_rs.w %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs) + ); + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextrv_rs.w error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextrv_s_h.c b/tests/tcg/mips/mips64-dsp/dextrv_s_h.c new file mode 100644 index 0000000000..87d3aeedce --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextrv_s_h.c @@ -0,0 +1,32 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long achi, acli; + long long res, resdsp; + + achi = 0x87654321; + acli = 0x12345678; + rs = 0x8; + + res = 0xffffffffffff8000; + resdsp = 0x1; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dextrv_s.h %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs) + ); + dsp = (dsp >> 23) & 0x1; + + if ((dsp != resdsp) || (rt != res)) { + printf("dextrv_s.h error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dextrv_w.c b/tests/tcg/mips/mips64-dsp/dextrv_w.c new file mode 100644 index 0000000000..973765c1c0 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dextrv_w.c @@ -0,0 +1,46 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs; + long long achi, acli; + long long res; + + achi = 0x87654321; + acli = 0x12345678; + rs = 0x8; + + res = 0x123456; + + __asm + ("mthi %1, $ac1\n\t" + "mtlo %2, $ac1\n\t" + "dextrv.w %0, $ac1, %3\n\t" + : "=r"(rt) + : "r"(achi), "r"(acli), "r"(rs) + ); + if (rt != res) { + printf("dextrv.w error\n"); + return -1; + } + + achi = 0x87654321; + acli = 0x12345678; + rs = 0x0; + + res = 0x12345678; + + __asm + ("mthi %1, $ac1\n\t" + "mtlo %2, $ac1\n\t" + "dextrv.w %0, $ac1, %3\n\t" + : "=r"(rt) + : "r"(achi), "r"(acli), "r"(rs) + ); + if (rt != res) { + printf("dextrv.w error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dinsv.c b/tests/tcg/mips/mips64-dsp/dinsv.c new file mode 100644 index 0000000000..f6192188c0 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dinsv.c @@ -0,0 +1,26 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, dsp; + long long res; + + rs = 0x1234567887654321; + rt = 0x1234567812345678; + dsp = 0x2222; + res = 0x1234567812345678; + __asm + ("wrdsp %1, 0x3\n\t" + "wrdsp %1\n\t" + "dinsv %0, %2\n\t" + : "+r"(rt) + : "r"(dsp), "r"(rs) + ); + + if (rt != res) { + printf("dinsv error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dmadd.c b/tests/tcg/mips/mips64-dsp/dmadd.c new file mode 100644 index 0000000000..fb22614725 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dmadd.c @@ -0,0 +1,57 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs; + long long achi, acli; + long long acho, aclo; + long long resh, resl; + + achi = 0x1; + acli = 0x1; + + rs = 0x0000000100000001; + rt = 0x0000000200000002; + + resh = 0x1; + resl = 0x5; + __asm + ("mthi %2, $ac1 \t\n" + "mtlo %3, $ac1 \t\n" + "dmadd $ac1, %4, %5\t\n" + "mfhi %0, $ac1 \t\n" + "mflo %1, $ac1 \t\n" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((acho != resh) || (aclo != resl)) { + printf("1 dmadd error\n"); + + return -1; + } + + achi = 0x1; + acli = 0x1; + + rs = 0xaaaabbbbccccdddd; + rt = 0xaaaabbbbccccdddd; + + resh = 0x0000000000000000; + resl = 0xffffffffca860b63; + + __asm + ("mthi %2, $ac1 \t\n" + "mtlo %3, $ac1 \t\n" + "dmadd $ac1, %4, %5\t\n" + "mfhi %0, $ac1 \t\n" + "mflo %1, $ac1 \t\n" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((acho != resh) || (aclo != resl)) { + printf("2 dmadd error\n"); + + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dmaddu.c b/tests/tcg/mips/mips64-dsp/dmaddu.c new file mode 100644 index 0000000000..39ab0c10db --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dmaddu.c @@ -0,0 +1,56 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs; + long long achi, acli; + long long acho, aclo; + long long resh, resl; + achi = 0x1; + acli = 0x2; + + rs = 0x0000000200000002; + rt = 0x0000000200000002; + resh = 0x1; + resl = 0xa; + __asm + ("mthi %2, $ac1 \t\n" + "mtlo %3, $ac1 \t\n" + "dmaddu $ac1, %4, %5\t\n" + "mfhi %0, $ac1 \t\n" + "mflo %1, $ac1 \t\n" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((acho != resh) || (aclo != resl)) { + printf("1 dmaddu error\n"); + + return -1; + } + + achi = 0x1; + acli = 0x1; + + rs = 0xaaaabbbbccccdddd; + rt = 0xaaaabbbbccccdddd; + + resh = 0x0000000000000002; + resl = 0xffffffffca860b63; + + __asm + ("mthi %2, $ac1 \t\n" + "mtlo %3, $ac1 \t\n" + "dmaddu $ac1, %4, %5\t\n" + "mfhi %0, $ac1 \t\n" + "mflo %1, $ac1 \t\n" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((acho != resh) || (aclo != resl)) { + printf("2 dmaddu error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dmsub.c b/tests/tcg/mips/mips64-dsp/dmsub.c new file mode 100644 index 0000000000..16be6170e4 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dmsub.c @@ -0,0 +1,59 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs; + long long achi, acli; + long long acho, aclo; + long long resh, resl; + achi = 0x1; + acli = 0x8; + + rs = 0x0000000100000001; + rt = 0x0000000200000002; + + resh = 0x1; + resl = 0x4; + + __asm + ("mthi %2, $ac1 \t\n" + "mtlo %3, $ac1 \t\n" + "dmsub $ac1, %4, %5\t\n" + "mfhi %0, $ac1 \t\n" + "mflo %1, $ac1 \t\n" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((acho != resh) || (aclo != resl)) { + printf("1 dmsub error\n"); + + return -1; + } + + achi = 0xfffffffF; + acli = 0xfffffffF; + + rs = 0x8888999977776666; + rt = 0x9999888877776666; + + resh = 0xffffffffffffffff; + resl = 0x789aae13; + + __asm + ("mthi %2, $ac1 \t\n" + "mtlo %3, $ac1 \t\n" + "dmsub $ac1, %4, %5\t\n" + "mfhi %0, $ac1 \t\n" + "mflo %1, $ac1 \t\n" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((acho != resh) || (aclo != resl)) { + printf("2 dmsub error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dmsubu.c b/tests/tcg/mips/mips64-dsp/dmsubu.c new file mode 100644 index 0000000000..cc4838ad5f --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dmsubu.c @@ -0,0 +1,59 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs; + long long achi, acli; + long long acho, aclo; + long long resh, resl; + achi = 0x1; + acli = 0x8; + + rs = 0x0000000100000001; + rt = 0x0000000200000002; + + resh = 0x1; + resl = 0x4; + + __asm + ("mthi %2, $ac1 \t\n" + "mtlo %3, $ac1 \t\n" + "dmsubu $ac1, %4, %5\t\n" + "mfhi %0, $ac1 \t\n" + "mflo %1, $ac1 \t\n" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((acho != resh) || (aclo != resl)) { + printf("1 dmsubu error\n"); + + return -1; + } + + achi = 0xfffffffF; + acli = 0xfffffffF; + + rs = 0x8888999977776666; + rt = 0x9999888877776666; + + resh = 0xffffffffffffffff; + resl = 0x789aae13; + + __asm + ("mthi %2, $ac1 \t\n" + "mtlo %3, $ac1 \t\n" + "dmsubu $ac1, %4, %5\t\n" + "mfhi %0, $ac1 \t\n" + "mflo %1, $ac1 \t\n" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((acho != resh) || (aclo != resl)) { + printf("2 dmsubu error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dmthlip.c b/tests/tcg/mips/mips64-dsp/dmthlip.c new file mode 100644 index 0000000000..027555fb53 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dmthlip.c @@ -0,0 +1,41 @@ +#include "io.h" + +int main(void) +{ + long long rs, dsp; + long long achi, acli; + + long long rsdsp; + long long acho, aclo; + + long long res; + long long reshi, reslo; + + + rs = 0xaaaabbbbccccdddd; + achi = 0x87654321; + acli = 0x12345678; + dsp = 0x22; + + res = 0x62; + reshi = 0x12345678; + reslo = 0xffffffffccccdddd; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "wrdsp %5\n\t" + "dmthlip %6, $ac1\n\t" + "rddsp %0\n\t" + "mfhi %1, $ac1\n\t" + "mflo %2, $ac1\n\t" + : "=r"(rsdsp), "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(dsp), "r"(rs) + ); + if ((rsdsp != res) || (acho != reshi) || (aclo != reslo)) { + printf("dmthlip error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dpaq_s_w_ph.c b/tests/tcg/mips/mips64-dsp/dpaq_s_w_ph.c new file mode 100644 index 0000000000..1bca935008 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dpaq_s_w_ph.c @@ -0,0 +1,32 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, dsp; + long long ach = 0, acl = 0; + long long resulth, resultl, resultdsp; + + rs = 0x800000FF; + rt = 0x80000002; + resulth = 0x00; + resultl = 0xFFFFFFFF800003FB; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpaq_s.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = dsp >> 17 & 0x01; + if ((dsp != resultdsp) || (ach != resulth) || (acl != resultl)) { + printf("dpaq_w.w.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dpaq_s_w_qh.c b/tests/tcg/mips/mips64-dsp/dpaq_s_w_qh.c new file mode 100644 index 0000000000..844a347429 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dpaq_s_w_qh.c @@ -0,0 +1,57 @@ +#include"io.h" +int main(void) +{ + long long rt, rs; + long long achi, acli; + long long acho, aclo; + long long resh, resl; + + achi = 0x1; + acli = 0x1; + rs = 0x0001000100010001; + rt = 0x0002000200020002; + resh = 0x1; + resl = 0x11; + + __asm + ("mthi %2, $ac1\t\n" + "mtlo %3, $ac1\t\n" + "dpaq_s.w.qh $ac1, %4, %5\t\n" + "mfhi %0, $ac1\t\n" + "mflo %1, $ac1\t\n" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((acho != resh) || (aclo != resl)) { + printf("1 dpaq_s.w.qh error\n"); + + return -1; + } + + achi = 0xffffffff; + acli = 0xaaaaaaaa; + + rs = 0x1111222233334444; + rt = 0xffffeeeeddddcccc; + + resh = 0x00; + resl = 0xffffffffd27ad82e; + + __asm + ("mthi %2, $ac1\t\n" + "mtlo %3, $ac1\t\n" + "dpaq_s.w.qh $ac1, %4, %5\t\n" + "mfhi %0, $ac1\t\n" + "mflo %1, $ac1\t\n" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((acho != resh) || (aclo != resl)) { + printf("2 dpaq_s.w.qh error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dpaq_sa_l_pw.c b/tests/tcg/mips/mips64-dsp/dpaq_sa_l_pw.c new file mode 100644 index 0000000000..1bb2ec2f26 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dpaq_sa_l_pw.c @@ -0,0 +1,88 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long achi, acli; + long long acho, aclo; + long long dsp; + long long resh, resl; + long long resdsp; + + rs = 0x0000000100000001; + rt = 0x0000000200000002; + achi = 0x1; + acli = 0x1; + resh = 0xffffffffffffffff; + resl = 0x0; + resdsp = 0x01; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "dpaq_sa.l.pw $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((acho != resh) || (aclo != resl) || ((dsp >> (16 + 1)) != resdsp)) { + printf("1 dpaq_sa_l_pw error\n"); + + return -1; + } + + rs = 0xaaaabbbbccccdddd; + rt = 0x3333444455556666; + achi = 0x88888888; + acli = 0x66666666; + + resh = 0xffffffff88888887; + resl = 0xffffffff9e2661da; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dpaq_sa.l.pw $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((acho != resh) || (aclo != resl)) { + printf("2 dpaq_sa_l_pw error\n"); + + return -1; + } + + rs = 0x8000000080000000; + rt = 0x8000000080000000; + achi = 0x88888888; + acli = 0x66666666; + + resh = 0xffffffffffffffff; + resl = 0x00; + resdsp = 0x01; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "dpaq_sa.l.pw $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((acho != resh) || (aclo != resl) || ((dsp >> (16 + 1)) != resdsp)) { + printf("2 dpaq_sa_l_pw error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dpaq_sa_l_w.c b/tests/tcg/mips/mips64-dsp/dpaq_sa_l_w.c new file mode 100644 index 0000000000..f840cdd761 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dpaq_sa_l_w.c @@ -0,0 +1,82 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, dsp; + long long ach = 0, acl = 0; + long long resulth, resultl, resultdsp; + + rs = 0x80000000; + rt = 0x80000000; + resulth = 0x7FFFFFFF; + resultl = 0xffffffffFFFFFFFF; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %0, $ac1\n\t" + "dpaq_sa.l.w $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + if ((dsp != resultdsp) || (ach != resulth) || (acl != resultl)) { + printf("dpaq_sa.l.w error\n"); + + return -1; + } + + ach = 0x12; + acl = 0x48; + rs = 0x80000000; + rt = 0x80000000; + + resulth = 0x7FFFFFFF; + resultl = 0xffffffffFFFFFFFF; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %0, $ac1\n\t" + "dpaq_sa.l.w $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + if ((dsp != resultdsp) || (ach != resulth) || (acl != resultl)) { + printf("dpaq_sa.l.w error\n"); + + return -1; + } + + ach = 0x741532A0; + acl = 0xfceabb08; + rs = 0x80000000; + rt = 0x80000000; + + resulth = 0x7fffffff; + resultl = 0xffffffffffffffff; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %0, $ac1\n\t" + "dpaq_sa.l.w $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + if ((dsp != resultdsp) || (ach != resulth) || (acl != resultl)) { + printf("dpaq_sa.l.w error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dpau_h_obl.c b/tests/tcg/mips/mips64-dsp/dpau_h_obl.c new file mode 100644 index 0000000000..54905e8f93 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dpau_h_obl.c @@ -0,0 +1,59 @@ + +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long achi, acli; + long long acho, aclo; + long long resh, resl; + + rs = 0x0000000100000001; + rt = 0x0000000200000002; + achi = 0x1; + acli = 0x1; + resh = 0x1; + resl = 0x3; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dpau.h.obl $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((acho != resh) || (aclo != resl)) { + printf("1 dpau.h.obl error\n"); + + return -1; + } + + rs = 0xaaaabbbbccccdddd; + rt = 0x3333444455556666; + achi = 0x88888888; + acli = 0x66666666; + + resh = 0xffffffff88888888; + resl = 0x66670d7a; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dpau.h.obl $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((acho != resh) || (aclo != resl)) { + printf("1 dpau.h.obl error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dpau_h_obr.c b/tests/tcg/mips/mips64-dsp/dpau_h_obr.c new file mode 100644 index 0000000000..d7aa60b4b1 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dpau_h_obr.c @@ -0,0 +1,59 @@ + +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long achi, acli; + long long acho, aclo; + long long resh, resl; + + rs = 0x0000000100000001; + rt = 0x0000000200000002; + achi = 0x1; + acli = 0x1; + resh = 0x1; + resl = 0x3; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dpau.h.obr $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((acho != resh) || (aclo != resl)) { + printf("1 dpau.h.obr error\n"); + + return -1; + } + + rs = 0xccccddddaaaabbbb; + rt = 0x5555666633334444; + achi = 0x88888888; + acli = 0x66666666; + + resh = 0xffffffff88888888; + resl = 0x66670d7a; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dpau.h.obr $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((acho != resh) || (aclo != resl)) { + printf("1 dpau.h.obr error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dpau_h_qbl.c b/tests/tcg/mips/mips64-dsp/dpau_h_qbl.c new file mode 100644 index 0000000000..fcfd764310 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dpau_h_qbl.c @@ -0,0 +1,29 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long ach = 5, acl = 3; + long long resulth, resultl; + + rs = 0x800000FF; + rt = 0x80000002; + resulth = 0x05; + resultl = 0x4003; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpau.h.qbl $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + if ((ach != resulth) || (acl != resultl)) { + printf("dpau.h.qbl wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dpau_h_qbr.c b/tests/tcg/mips/mips64-dsp/dpau_h_qbr.c new file mode 100644 index 0000000000..3282461a7d --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dpau_h_qbr.c @@ -0,0 +1,29 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long ach = 5, acl = 3; + long long resulth, resultl; + + rs = 0x800000FF; + rt = 0x80000002; + resulth = 0x05; + resultl = 0x0201; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpau.h.qbr $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + if ((ach != resulth) || (acl != resultl)) { + printf("dpau.h.qbr wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dpsq_s_w_ph.c b/tests/tcg/mips/mips64-dsp/dpsq_s_w_ph.c new file mode 100644 index 0000000000..7660f037da --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dpsq_s_w_ph.c @@ -0,0 +1,51 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long ach = 5, acl = 5; + long long resulth, resultl; + + rs = 0xBC0123AD; + rt = 0x01643721; + resulth = 0x04; + resultl = 0xFFFFFFFFEE9794A3; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsq_s.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + if ((ach != resulth) || (acl != resultl)) { + printf("1 dpsq_s.w.ph wrong\n"); + + return -1; + } + + ach = 0x1424Ef1f; + acl = 0x1035219A; + rs = 0x800083AD; + rt = 0x80003721; + resulth = 0x1424ef1e; + resultl = 0x577ed901; + + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsq_s.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + if ((ach != resulth) || (acl != resultl)) { + printf("2 dpsq_s.w.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dpsq_s_w_qh.c b/tests/tcg/mips/mips64-dsp/dpsq_s_w_qh.c new file mode 100644 index 0000000000..2cc50c577e --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dpsq_s_w_qh.c @@ -0,0 +1,56 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long achi, acli; + long long acho, aclo; + long long resh, resl; + + rs = 0xffffeeeeddddcccc; + rt = 0x9999888877776666; + achi = 0x67576; + acli = 0x98878; + + resh = 0x67576; + resl = 0x5b1682c4; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dpsq_s.w.qh $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((acho != resh) || (aclo != resl)) { + printf("1 dpsq_s.w.qh wrong\n"); + + return -1; + } + + rs = 0x8000800080008000; + rt = 0x8000800080008000; + achi = 0x67576; + acli = 0x98878; + + resh = 0x67575; + resl = 0x0009887c; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dpsq_s.w.qh $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((acho != resh) || (aclo != resl)) { + printf("2 dpsq_s.w.qh wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dpsq_sa_l_pw.c b/tests/tcg/mips/mips64-dsp/dpsq_sa_l_pw.c new file mode 100644 index 0000000000..7fc2503fc5 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dpsq_sa_l_pw.c @@ -0,0 +1,76 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, dsp; + long long achi, acli; + long long resh, resl, resdsp; + + rs = 0x89789BC0123AD; + rt = 0x5467591643721; + + achi = 0x98765437; + acli = 0x65489709; + + resh = 0xffffffffffffffff; + resl = 0x00; + + resdsp = 0x01; + + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsq_sa.l.pw $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(achi), "+r"(acli), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + + dsp = (dsp >> 17) & 0x01; + if ((dsp != resdsp) || (achi != resh) || (acli != resl)) { + printf("1 dpsq_sa.l.pw wrong\n"); + + return -1; + } + + /* clear dspcontrol reg for next test use. */ + dsp = 0; + __asm + ("wrdsp %0" + : + : "r"(dsp) + ); + + rs = 0x8B78980000000; + rt = 0x5867580000000; + + achi = 0x98765437; + acli = 0x65489709; + + resh = 0xffffffff98765436; + resl = 0x11d367d0; + + resdsp = 0x01; + + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsq_sa.l.pw $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(achi), "+r"(acli), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + + dsp = (dsp >> 17) & 0x01; + if ((dsp != resdsp) || (achi != resh) || (acli != resl)) { + printf("2 dpsq_sa.l.pw wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dpsq_sa_l_w.c b/tests/tcg/mips/mips64-dsp/dpsq_sa_l_w.c new file mode 100644 index 0000000000..f55afc9095 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dpsq_sa_l_w.c @@ -0,0 +1,59 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, dsp; + long long ach = 5, acl = 5; + long long resulth, resultl, resultdsp; + + rs = 0xBC0123AD; + rt = 0x01643721; + + resulth = 0xfffffffffdf4cbe0; + resultl = 0xFFFFFFFFd138776b; + resultdsp = 0x00; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsq_sa.l.w $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + if ((dsp != resultdsp) || (ach != resulth) || (acl != resultl)) { + printf("1 dpsq_sa.l.w wrong\n"); + + return -1; + } + + ach = 0x54321123; + acl = 5; + rs = 0x80000000; + rt = 0x80000000; + + resulth = 0xffffffffd4321123; + resultl = 0x06; + resultdsp = 0x01; + + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsq_sa.l.w $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + if ((dsp != resultdsp) || (ach != resulth) || (acl != resultl)) { + printf("2 dpsq_sa.l.w wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dpsu_h_obl.c b/tests/tcg/mips/mips64-dsp/dpsu_h_obl.c new file mode 100644 index 0000000000..c0a8f4d7aa --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dpsu_h_obl.c @@ -0,0 +1,32 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long ach = 5, acl = 5; + long long resulth, resultl; + + rs = 0x88886666BC0123AD; + rt = 0x9999888801643721; + + resulth = 0x04; + resultl = 0xFFFFFFFFFFFEF115; + + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsu.h.obl $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + + if ((ach != resulth) || (acl != resultl)) { + printf("dpsu.h.obl wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dpsu_h_obr.c b/tests/tcg/mips/mips64-dsp/dpsu_h_obr.c new file mode 100644 index 0000000000..aa0d47a065 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dpsu_h_obr.c @@ -0,0 +1,32 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long ach = 5, acl = 5; + long long resulth, resultl; + + rs = 0x7878878888886666; + rt = 0x9865454399998888; + + resulth = 0x04; + resultl = 0xFFFFFFFFFFFeF115; + + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsu.h.obr $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + + if ((ach != resulth) || (acl != resultl)) { + printf("dpsu.h.qbr wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dpsu_h_qbl.c b/tests/tcg/mips/mips64-dsp/dpsu_h_qbl.c new file mode 100644 index 0000000000..da6dbb6154 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dpsu_h_qbl.c @@ -0,0 +1,29 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long ach = 5, acl = 5; + long long resulth, resultl; + + rs = 0xBC0123AD; + rt = 0x01643721; + resulth = 0x04; + resultl = 0xFFFFFFFFFFFFFEE5; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsu.h.qbl $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + if ((ach != resulth) || (acl != resultl)) { + printf("dpsu.h.qbl wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dpsu_h_qbr.c b/tests/tcg/mips/mips64-dsp/dpsu_h_qbr.c new file mode 100644 index 0000000000..bf00b70aa7 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dpsu_h_qbr.c @@ -0,0 +1,29 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long ach = 5, acl = 5; + long long resulth, resultl; + + rs = 0xBC0123AD; + rt = 0x01643721; + resulth = 0x04; + resultl = 0xFFFFFFFFFFFFE233; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsu.h.qbr $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + if ((ach != resulth) || (acl != resultl)) { + printf("dpsu.h.qbr wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dshilo.c b/tests/tcg/mips/mips64-dsp/dshilo.c new file mode 100644 index 0000000000..f50584b9c4 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dshilo.c @@ -0,0 +1,52 @@ +#include "io.h" + +int main(void) +{ + long long achi, acli; + long long acho, aclo; + long long reshi, reslo; + + achi = 0x87654321; + acli = 0x12345678; + + reshi = 0xfffffffff8765432; + reslo = 0x1234567; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dshilo $ac1, 0x4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli) + ); + + if ((acho != reshi) || (aclo != reslo)) { + printf("1 dshilo error\n"); + return -1; + } + + achi = 0x87654321; + acli = 0x12345678; + + reshi = 0x1234567; + reslo = 0x00; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dshilo $ac1, -60\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli) + ); + + if ((acho != reshi) || (aclo != reslo)) { + printf("2 dshilo error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/dshilov.c b/tests/tcg/mips/mips64-dsp/dshilov.c new file mode 100644 index 0000000000..792bd23730 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/dshilov.c @@ -0,0 +1,54 @@ +#include "io.h" + +int main(void) +{ + long long achi, acli, rs; + long long acho, aclo; + long long reshi, reslo; + + achi = 0x87654321; + acli = 0x12345678; + rs = 0x4; + + reshi = 0xfffffffff8765432; + reslo = 0x1234567; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dshilov $ac1, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs) + ); + + if ((acho != reshi) || (aclo != reslo)) { + printf("dshilov error\n"); + return -1; + } + + rs = 0x44; + achi = 0x87654321; + acli = 0x12345678; + + reshi = 0x1234567; + reslo = 0x00; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "dshilov $ac1, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs) + ); + + if ((acho != reshi) || (aclo != reslo)) { + printf("dshilov error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/extp.c b/tests/tcg/mips/mips64-dsp/extp.c new file mode 100644 index 0000000000..c72f54bace --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/extp.c @@ -0,0 +1,50 @@ +#include "io.h" + +int main(void) +{ + long long rt, ach, acl, dsp; + long long result; + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x07; + result = 0x000C; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extp %0, $ac1, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 14) & 0x01; + if ((dsp != 0) || (result != rt)) { + printf("extp wrong\n"); + + return -1; + } + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x01; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extp %0, $ac1, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 14) & 0x01; + if (dsp != 1) { + printf("extp wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/extpdp.c b/tests/tcg/mips/mips64-dsp/extpdp.c new file mode 100644 index 0000000000..f430193841 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/extpdp.c @@ -0,0 +1,51 @@ +#include "io.h" + +int main(void) +{ + long long rt, ach, acl, dsp, pos, efi; + long long result; + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x07; + result = 0x000C; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extpdp %0, $ac1, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(ach), "r"(acl) + ); + pos = dsp & 0x3F; + efi = (dsp >> 14) & 0x01; + if ((pos != 3) || (efi != 0) || (result != rt)) { + printf("extpdp wrong\n"); + + return -1; + } + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x01; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extpdp %0, $ac1, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(ach), "r"(acl) + ); + efi = (dsp >> 14) & 0x01; + if (efi != 1) { + printf("extpdp wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/extpdpv.c b/tests/tcg/mips/mips64-dsp/extpdpv.c new file mode 100644 index 0000000000..ba57426d22 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/extpdpv.c @@ -0,0 +1,52 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, ach, acl, dsp, pos, efi; + long long result; + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x07; + rs = 0x03; + result = 0x000C; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extpdpv %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(ach), "r"(acl), "r"(rs) + ); + pos = dsp & 0x3F; + efi = (dsp >> 14) & 0x01; + if ((pos != 3) || (efi != 0) || (result != rt)) { + printf("extpdpv wrong\n"); + + return -1; + } + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x01; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extpdpv %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(ach), "r"(acl), "r"(rs) + ); + efi = (dsp >> 14) & 0x01; + if (efi != 1) { + printf("extpdpv wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/extpv.c b/tests/tcg/mips/mips64-dsp/extpv.c new file mode 100644 index 0000000000..158472bf93 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/extpv.c @@ -0,0 +1,51 @@ +#include "io.h" + +int main(void) +{ + long long rt, ac, ach, acl, dsp; + long long result; + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x07; + ac = 0x03; + result = 0x000C; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extpv %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(ach), "r"(acl), "r"(ac) + ); + dsp = (dsp >> 14) & 0x01; + if ((dsp != 0) || (result != rt)) { + printf("extpv wrong\n"); + + return -1; + } + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x01; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extpv %0, $ac1, %4\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(ach), "r"(acl), "r"(ac) + ); + dsp = (dsp >> 14) & 0x01; + if (dsp != 1) { + printf("extpv wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/extr_r_w.c b/tests/tcg/mips/mips64-dsp/extr_r_w.c new file mode 100644 index 0000000000..94572ad154 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/extr_r_w.c @@ -0,0 +1,53 @@ +#include "io.h" + +int main(void) +{ + long long rt, ach, acl, dsp; + long long result; + + ach = 0x05; + acl = 0xB4CB; + result = 0xFFFFFFFFA0001699; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_r.w %0, $ac1, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 1) || (result != rt)) { + printf("1 extr_r.w wrong\n"); + + return -1; + } + + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + ach = 0x01; + acl = 0xB4CB; + result = 0x10000B4D; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_r.w %0, $ac1, 0x04\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 0) || (result != rt)) { + printf("2 extr_r.w wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/extr_rs_w.c b/tests/tcg/mips/mips64-dsp/extr_rs_w.c new file mode 100644 index 0000000000..73551f96b3 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/extr_rs_w.c @@ -0,0 +1,53 @@ +#include "io.h" + +int main(void) +{ + long long rt, ach, acl, dsp; + long long result; + + ach = 0x05; + acl = 0xB4CB; + result = 0x7FFFFFFF; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_rs.w %0, $ac1, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 1) || (result != rt)) { + printf("1 extr_rs.w wrong\n"); + + return -1; + } + + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + ach = 0x01; + acl = 0xB4CB; + result = 0x10000B4D; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_rs.w %0, $ac1, 0x04\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 0) || (result != rt)) { + printf("2 extr_rs.w wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/extr_s_h.c b/tests/tcg/mips/mips64-dsp/extr_s_h.c new file mode 100644 index 0000000000..de10cb57a5 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/extr_s_h.c @@ -0,0 +1,71 @@ +#include "io.h" + +int main(void) +{ + long long rt, ach, acl, dsp; + long long result; + + ach = 0x05; + acl = 0xB4CB; + result = 0x00007FFF; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_s.h %0, $ac1, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 1) || (result != rt)) { + printf("extr_s.h wrong\n"); + + return -1; + } + + ach = 0xffffffff; + acl = 0x12344321; + result = 0xffffffffFFFF8000; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_s.h %0, $ac1, 0x08\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 1) || (result != rt)) { + printf("extr_s.h wrong\n"); + + return -1; + } + + /* Clear dsp */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + ach = 0x00; + acl = 0x4321; + result = 0x432; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_s.h %0, $ac1, 0x04\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 0) || (result != rt)) { + printf("extr_s.h wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/extr_w.c b/tests/tcg/mips/mips64-dsp/extr_w.c new file mode 100644 index 0000000000..bd69576687 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/extr_w.c @@ -0,0 +1,53 @@ +#include "io.h" + +int main(void) +{ + long long rt, ach, acl, dsp; + long long result; + + ach = 0x05; + acl = 0xB4CB; + result = 0xFFFFFFFFA0001699; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr.w %0, $ac1, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 1) || (result != rt)) { + printf("extr.w wrong\n"); + + return -1; + } + + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + ach = 0x01; + acl = 0xB4CB; + result = 0x10000B4C; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr.w %0, $ac1, 0x04\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 0) || (result != rt)) { + printf("extr.w wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/extrv_r_w.c b/tests/tcg/mips/mips64-dsp/extrv_r_w.c new file mode 100644 index 0000000000..8379729787 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/extrv_r_w.c @@ -0,0 +1,59 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, ach, acl, dsp; + long long result; + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x07; + rs = 0x03; + result = 0xFFFFFFFFA0001699; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_r.w %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 1) || (result != rt)) { + printf("extrv_r.w wrong\n"); + + return -1; + } + + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + rs = 4; + ach = 0x01; + acl = 0xB4CB; + result = 0x10000B4D; + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_r.w %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 0) || (result != rt)) { + printf("extrv_r.w wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/extrv_rs_w.c b/tests/tcg/mips/mips64-dsp/extrv_rs_w.c new file mode 100644 index 0000000000..8707cd1174 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/extrv_rs_w.c @@ -0,0 +1,59 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, ach, acl, dsp; + long long result; + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x07; + rs = 0x03; + result = 0x7FFFFFFF; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_rs.w %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 1) || (result != rt)) { + printf("1 extrv_rs.w wrong\n"); + + return -1; + } + + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + rs = 4; + ach = 0x01; + acl = 0xB4CB; + result = 0x10000B4D; + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_rs.w %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 0) || (result != rt)) { + printf("2 extrv_rs.w wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/extrv_s_h.c b/tests/tcg/mips/mips64-dsp/extrv_s_h.c new file mode 100644 index 0000000000..b6dcaebcbc --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/extrv_s_h.c @@ -0,0 +1,79 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, ach, acl, dsp; + long long result; + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x07; + rs = 0x03; + result = 0x00007FFF; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_s.h %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 1) || (result != rt)) { + printf("extrv_s.h wrong\n"); + + return -1; + } + + rs = 0x08; + ach = 0xffffffff; + acl = 0x12344321; + result = 0xffffffffFFFF8000; + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_s.h %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 1) || (result != rt)) { + printf("extrv_s.h wrong\n"); + + return -1; + } + + /* Clear dsp */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + rs = 0x04; + ach = 0x00; + acl = 0x4321; + result = 0x432; + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_s.h %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 0) || (result != rt)) { + printf("extrv_s.h wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/extrv_w.c b/tests/tcg/mips/mips64-dsp/extrv_w.c new file mode 100644 index 0000000000..8adffb3954 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/extrv_w.c @@ -0,0 +1,59 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, ach, acl, dsp; + long long result; + + ach = 0x05; + acl = 0xB4CB; + dsp = 0x07; + rs = 0x03; + result = 0xFFFFFFFFA0001699; + + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv.w %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 1) || (result != rt)) { + printf("extrv.w wrong\n"); + + return -1; + } + + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + rs = 4; + ach = 0x01; + acl = 0xB4CB; + result = 0x10000B4C; + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv.w %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + if ((dsp != 0) || (result != rt)) { + printf("extrv.w wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/head.S b/tests/tcg/mips/mips64-dsp/head.S new file mode 100644 index 0000000000..9a099ae42f --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/head.S @@ -0,0 +1,16 @@ +/* + * Startup Code for MIPS64 CPU-core + * + */ +.text +.globl _start +.align 4 +_start: + ori $2, $2, 0xffff + sll $2, $2, 16 + ori $2, $2, 0xffff + mtc0 $2, $12, 0 + jal main + +end: + b end diff --git a/tests/tcg/mips/mips64-dsp/insv.c b/tests/tcg/mips/mips64-dsp/insv.c new file mode 100644 index 0000000000..fc5696f4c4 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/insv.c @@ -0,0 +1,26 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long result; + + /* msb = 10, lsb = 5 */ + dsp = 0x305; + rt = 0x12345678; + rs = 0xffffffff87654321; + result = 0x12345338; + __asm + ("wrdsp %2, 0x03\n\t" + "insv %0, %1\n\t" + : "+r"(rt) + : "r"(rs), "r"(dsp) + ); + if (rt != result) { + printf("insv wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/io.h b/tests/tcg/mips/mips64-dsp/io.h new file mode 100644 index 0000000000..b7db61d7c1 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/io.h @@ -0,0 +1,22 @@ +#ifndef _ASM_IO_H +#define _ASM_IO_H +extern int printf(const char *fmt, ...); +extern unsigned long get_ticks(void); + +#define _read(source) \ +({ unsigned long __res; \ + __asm__ __volatile__( \ + "mfc0\t%0, " #source "\n\t" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __read(source) \ +({ unsigned long __res; \ + __asm__ __volatile__( \ + "move\t%0, " #source "\n\t" \ + : "=r" (__res)); \ + __res; \ +}) + +#endif diff --git a/tests/tcg/mips/mips64-dsp/lbux.c b/tests/tcg/mips/mips64-dsp/lbux.c new file mode 100644 index 0000000000..dbdc87bffe --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/lbux.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long value, rd; + long long *p; + unsigned long long addr, index; + long long result; + + value = 0xBCDEF389; + p = &value; + addr = (unsigned long long)p; + index = 0; + result = value & 0xFF; + __asm + ("lbux %0, %1(%2)\n\t" + : "=r"(rd) + : "r"(index), "r"(addr) + ); + if (rd != result) { + printf("lbux wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/ldx.c b/tests/tcg/mips/mips64-dsp/ldx.c new file mode 100644 index 0000000000..787d9f00b4 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/ldx.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long value, rd; + long long *p; + unsigned long long addr, index; + long long result; + + value = 0xBCDEF389; + p = &value; + addr = (unsigned long long)p; + index = 0; + result = 0xBCDEF389; + __asm + ("ldx %0, %1(%2)\n\t" + : "=r"(rd) + : "r"(index), "r"(addr) + ); + if (rd != result) { + printf("lwx wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/lhx.c b/tests/tcg/mips/mips64-dsp/lhx.c new file mode 100644 index 0000000000..2020e56866 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/lhx.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long value, rd; + long long *p; + unsigned long long addr, index; + long long result; + + value = 0xBCDEF389; + p = &value; + addr = (unsigned long long)p; + index = 0; + result = 0xFFFFFFFFFFFFF389; + __asm + ("lhx %0, %1(%2)\n\t" + : "=r"(rd) + : "r"(index), "r"(addr) + ); + if (rd != result) { + printf("lhx wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/lwx.c b/tests/tcg/mips/mips64-dsp/lwx.c new file mode 100644 index 0000000000..6a81414d65 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/lwx.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long value, rd; + long long *p; + unsigned long long addr, index; + long long result; + + value = 0xBCDEF389; + p = &value; + addr = (unsigned long long)p; + index = 0; + result = 0xFFFFFFFFBCDEF389; + __asm + ("lwx %0, %1(%2)\n\t" + : "=r"(rd) + : "r"(index), "r"(addr) + ); + if (rd != result) { + printf("lwx wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/madd.c b/tests/tcg/mips/mips64-dsp/madd.c new file mode 100644 index 0000000000..de6e44fbc5 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/madd.c @@ -0,0 +1,33 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs; + long long achi, acli; + long long acho, aclo; + long long resulth, resultl; + + achi = 0x05; + acli = 0xB4CB; + rs = 0x01; + rt = 0x01; + resulth = 0x05; + resultl = 0xB4CC; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "madd $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((resulth != acho) || (resultl != aclo)) { + printf("madd wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/maddu.c b/tests/tcg/mips/mips64-dsp/maddu.c new file mode 100644 index 0000000000..e9f426a374 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/maddu.c @@ -0,0 +1,33 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs; + long long achi, acli; + long long acho, aclo; + long long resulth, resultl; + + achi = 0x05; + acli = 0xB4CB; + rs = 0x01; + rt = 0x01; + resulth = 0x05; + resultl = 0xB4CC; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "madd $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((resulth != acho) || (resultl != aclo)) { + printf("maddu wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/maq_s_l_pwl.c b/tests/tcg/mips/mips64-dsp/maq_s_l_pwl.c new file mode 100644 index 0000000000..c196b43537 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/maq_s_l_pwl.c @@ -0,0 +1,56 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long achi, acli; + long long acho, aclo; + long long resulth, resultl; + + achi = 0x05; + acli = 0xB4CB; + rs = 0x98765432FF060000; + rt = 0xfdeca987CB000000; + resulth = 0x05; + resultl = 0x18278587; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "maq_s.l.pwl $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((resulth != acho) || (resultl != aclo)) { + printf("maq_s_l.w.pwl wrong 1\n"); + + return -1; + } + + achi = 0x05; + acli = 0xB4CB; + rs = 0x80000000FF060000; + rt = 0x80000000CB000000; + resulth = 0x05; + resultl = 0xb4ca; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_s.l.pwl $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x1; + if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) { + printf("maq_s_l.w.pwl wrong 2\n"); + + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/maq_s_l_pwr.c b/tests/tcg/mips/mips64-dsp/maq_s_l_pwr.c new file mode 100644 index 0000000000..e2af69fe2c --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/maq_s_l_pwr.c @@ -0,0 +1,56 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long achi, acli; + long long acho, aclo; + long long resulth, resultl; + + achi = 0x05; + acli = 0xB4CB; + rs = 0x87898765432; + rt = 0x7878fdeca987; + resulth = 0x05; + resultl = 0x18278587; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "maq_s.l.pwr $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((resulth != acho) || (resultl != aclo)) { + printf("maq_s.w.pwr wrong\n"); + + return -1; + } + + achi = 0x05; + acli = 0xB4CB; + rs = 0x89899980000000; + rt = 0x88780000000; + resulth = 0x05; + resultl = 0xb4ca; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_s.l.pwr $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x1; + if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) { + printf("maq_s.w.pwr wrong\n"); + + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/maq_s_w_phl.c b/tests/tcg/mips/mips64-dsp/maq_s_w_phl.c new file mode 100644 index 0000000000..7dba8746e5 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/maq_s_w_phl.c @@ -0,0 +1,60 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs; + long long achi, acli; + long long dsp; + long long acho, aclo; + long long resulth, resultl; + long long resdsp; + + achi = 0x05; + acli = 0xB4CB; + rs = 0xFF060000; + rt = 0xCB000000; + resulth = 0x04; + resultl = 0xffffffff947438CB; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "maq_s.w.phl $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((resulth != acho) || (resultl != aclo)) { + printf("1 maq_s.w.phl error\n"); + + return -1; + } + + achi = 0x06; + acli = 0xB4CB; + rs = 0x80000000; + rt = 0x80000000; + resulth = 0x6; + resultl = 0xffffffff8000b4ca; + resdsp = 1; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_s.w.phl $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((resulth != acho) || (resultl != aclo) || + (((dsp >> 17) & 0x01) != resdsp)) { + printf("2 maq_s.w.phl error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/maq_s_w_phr.c b/tests/tcg/mips/mips64-dsp/maq_s_w_phr.c new file mode 100644 index 0000000000..138ee2a691 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/maq_s_w_phr.c @@ -0,0 +1,60 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs; + long long achi, acli; + long long dsp; + long long acho, aclo; + long long resulth, resultl; + long long resdsp; + + achi = 0x05; + acli = 0xB4CB; + rs = 0xFF06; + rt = 0xCB00; + resulth = 0x04; + resultl = 0xffffffff947438CB; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "maq_s.w.phr $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((resulth != acho) || (resultl != aclo)) { + printf("1 maq_s.w.phr error\n"); + + return -1; + } + + achi = 0x06; + acli = 0xB4CB; + rs = 0x8000; + rt = 0x8000; + resulth = 0x6; + resultl = 0xffffffff8000b4ca; + resdsp = 1; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_s.w.phr $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((resulth != acho) || (resultl != aclo) || + (((dsp >> 17) & 0x01) != resdsp)) { + printf("2 maq_s.w.phr error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/maq_s_w_qhll.c b/tests/tcg/mips/mips64-dsp/maq_s_w_qhll.c new file mode 100644 index 0000000000..234a0af293 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/maq_s_w_qhll.c @@ -0,0 +1,62 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long achi, acli; + long long acho, aclo; + long long resulth, resultl; + + achi = 0x05; + acli = 0x05; + + rs = 0x1234888899990000; + rt = 0x9876888899990000; + + resulth = 0x05; + resultl = 0x15ae87f5; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "maq_s.w.qhll $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((resulth != acho) || (resultl != aclo)) { + printf("maq_s.w.qhll wrong\n"); + + return -1; + } + + + achi = 0x04; + acli = 0x06; + rs = 0x8000888899990000; + rt = 0x8000888899990000; + + resulth = 0x04; + resultl = 0xffffffff80000005; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_s.w.qhll $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + dsp = (dsp >> 17) & 0x1; + if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) { + printf("maq_s.w.qhll wrong\n"); + + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/maq_s_w_qhlr.c b/tests/tcg/mips/mips64-dsp/maq_s_w_qhlr.c new file mode 100644 index 0000000000..8768cbaa3d --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/maq_s_w_qhlr.c @@ -0,0 +1,62 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long achi, acli; + long long acho, aclo; + long long resulth, resultl; + + achi = 0x05; + acli = 0x05; + + rs = 0x1234123412340000; + rt = 0x9876987698760000; + + resulth = 0x05; + resultl = 0x15ae87f5; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "maq_s.w.qhlr $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((resulth != acho) || (resultl != aclo)) { + printf("1 maq_s.w.qhlr wrong\n"); + + return -1; + } + + + achi = 0x04; + acli = 0x06; + rs = 0x8000800080000000; + rt = 0x8000800080000000; + + resulth = 0x04; + resultl = 0xffffffff80000005; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_s.w.qhlr $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + dsp = (dsp >> 17) & 0x1; + if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) { + printf("2 maq_s.w.qhlr wrong\n"); + + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/maq_s_w_qhrl.c b/tests/tcg/mips/mips64-dsp/maq_s_w_qhrl.c new file mode 100644 index 0000000000..5006e2be34 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/maq_s_w_qhrl.c @@ -0,0 +1,63 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long achi, acli; + long long acho, aclo; + long long resulth, resultl; + + achi = 0x05; + acli = 0x05; + + rs = 0x1234888812340000; + rt = 0x9876888898760000; + + resulth = 0x05; + resultl = 0x15ae87f5; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "maq_s.w.qhrl $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((resulth != acho) || (resultl != aclo)) { + printf("1 maq_s.w.qhrl wrong\n"); + + return -1; + } + + + achi = 0x04; + acli = 0x06; + rs = 0x8888999980000000; + rt = 0x8888999980000000; + + resulth = 0x04; + resultl = 0xffffffff80000005; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_s.w.qhrl $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + dsp = (dsp >> 17) & 0x1; + if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) { + printf("2 maq_s.w.qhrl wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/maq_s_w_qhrr.c b/tests/tcg/mips/mips64-dsp/maq_s_w_qhrr.c new file mode 100644 index 0000000000..1d213a51b5 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/maq_s_w_qhrr.c @@ -0,0 +1,63 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long achi, acli; + long long acho, aclo; + long long resulth, resultl; + + achi = 0x05; + acli = 0x05; + + rs = 0x1234888812341234; + rt = 0x9876888898769876; + + resulth = 0x05; + resultl = 0x15ae87f5; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "maq_s.w.qhrr $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((resulth != acho) || (resultl != aclo)) { + printf("1 maq_s.w.qhrr wrong\n"); + + return -1; + } + + + achi = 0x04; + acli = 0x06; + rs = 0x8000888899998000; + rt = 0x8000888899998000; + + resulth = 0x04; + resultl = 0xffffffff80000005; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_s.w.qhrr $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + dsp = (dsp >> 17) & 0x1; + if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) { + printf("2 maq_s.w.qhrr wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/maq_sa_w_phl.c b/tests/tcg/mips/mips64-dsp/maq_sa_w_phl.c new file mode 100644 index 0000000000..5530ffbe69 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/maq_sa_w_phl.c @@ -0,0 +1,60 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs; + long long achi, acli; + long long dsp; + long long acho, aclo; + long long resulth, resultl; + long long resdsp; + + achi = 0x05; + acli = 0xB4CB; + rs = 0xFF060000; + rt = 0xCB000000; + resulth = 0xffffffffffffffff; + resultl = 0xffffffff947438cb; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "maq_sa.w.phl $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((resulth != acho) || (resultl != aclo)) { + printf("1 maq_sa.w.phl error\n"); + + return -1; + } + + achi = 0x06; + acli = 0xB4CB; + rs = 0x80000000; + rt = 0x80000000; + resulth = 0x00; + resultl = 0x7fffffff; + resdsp = 0x01; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_sa.w.phl $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((resulth != acho) || (resultl != aclo) || + (((dsp >> 17) & 0x01) != 0x01)) { + printf("2 maq_sa.w.phl error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/maq_sa_w_phr.c b/tests/tcg/mips/mips64-dsp/maq_sa_w_phr.c new file mode 100644 index 0000000000..b611cfa91a --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/maq_sa_w_phr.c @@ -0,0 +1,60 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs; + long long achi, acli; + long long dsp; + long long acho, aclo; + long long resulth, resultl; + long long resdsp; + + achi = 0x05; + acli = 0xB4CB; + rs = 0xFF06; + rt = 0xCB00; + resulth = 0xffffffffffffffff; + resultl = 0xffffffff947438cb; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "maq_sa.w.phr $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((resulth != acho) || (resultl != aclo)) { + printf("1 maq_sa.w.phr error\n"); + + return -1; + } + + achi = 0x06; + acli = 0xB4CB; + rs = 0x8000; + rt = 0x8000; + resulth = 0x00; + resultl = 0x7fffffff; + resdsp = 0x01; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_sa.w.phr $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((resulth != acho) || (resultl != aclo) || + (((dsp >> 17) & 0x01) != 0x01)) { + printf("2 maq_sa.w.phr error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/maq_sa_w_qhll.c b/tests/tcg/mips/mips64-dsp/maq_sa_w_qhll.c new file mode 100644 index 0000000000..136ff2d77b --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/maq_sa_w_qhll.c @@ -0,0 +1,62 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long achi, acli; + long long acho, aclo; + long long resulth, resultl; + + achi = 0x05; + acli = 0x05; + + rs = 0x1234888899990000; + rt = 0x9876888899990000; + + resulth = 0x00; + resultl = 0x15ae87f5; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "maq_sa.w.qhll $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((resulth != acho) || (resultl != aclo)) { + printf("1 maq_sa.w.qhll wrong\n"); + + return -1; + } + + + achi = 0x04; + acli = 0x06; + rs = 0x8000888899990000; + rt = 0x8000888899990000; + + resulth = 0x00; + resultl = 0x7fffffff; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_sa.w.qhll $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + dsp = (dsp >> 17) & 0x1; + if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) { + printf("2 maq_sa.w.qhll wrong\n"); + + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/maq_sa_w_qhlr.c b/tests/tcg/mips/mips64-dsp/maq_sa_w_qhlr.c new file mode 100644 index 0000000000..dd0ae1cca2 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/maq_sa_w_qhlr.c @@ -0,0 +1,64 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long achi, acli; + long long acho, aclo; + long long resulth, resultl; + + achi = 0x05; + acli = 0x05; + + rs = 0x1234123412340000; + rt = 0x9876987699990000; + + resulth = 0x0; + resultl = 0x15ae87f5; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_sa.w.qhlr $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + dsp = (dsp >> 17) & 0x1; + if ((dsp != 0x0) || (resulth != acho) || (resultl != aclo)) { + printf("maq_sa.w.qhlr wrong\n"); + + return -1; + } + + + achi = 0x04; + acli = 0x06; + rs = 0x8000800099990000; + rt = 0x8000800099990000; + + resulth = 0x00; + resultl = 0x7fffffff; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_sa.w.qhlr $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + dsp = (dsp >> 17) & 0x1; + if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) { + printf("maq_sa.w.qhlr wrong\n"); + + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrl.c b/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrl.c new file mode 100644 index 0000000000..a3de6f8e2e --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrl.c @@ -0,0 +1,64 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long achi, acli; + long long acho, aclo; + long long resulth, resultl; + + achi = 0x05; + acli = 0x05; + + rs = 0x1234123412340000; + rt = 0x9876987698760000; + + resulth = 0x0; + resultl = 0x15ae87f5; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_sa.w.qhrl $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + dsp = (dsp >> 17) & 0x1; + if ((dsp != 0x0) || (resulth != acho) || (resultl != aclo)) { + printf("1 maq_sa.w.qhrl wrong\n"); + + return -1; + } + + + achi = 0x04; + acli = 0x06; + rs = 0x8000800080000000; + rt = 0x8000800080000000; + + resulth = 0x00; + resultl = 0x7fffffff; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_sa.w.qhrl $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + dsp = (dsp >> 17) & 0x1; + if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) { + printf("2 maq_sa.w.qhrl wrong\n"); + + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrr.c b/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrr.c new file mode 100644 index 0000000000..f02173736a --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrr.c @@ -0,0 +1,64 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs, dsp; + long long achi, acli; + long long acho, aclo; + long long resulth, resultl; + + achi = 0x05; + acli = 0x05; + + rs = 0x1234123412341234; + rt = 0x9876987698769876; + + resulth = 0x0; + resultl = 0x15ae87f5; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_sa.w.qhrr $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + dsp = (dsp >> 17) & 0x1; + if ((dsp != 0x0) || (resulth != acho) || (resultl != aclo)) { + printf("1 maq_sa.w.qhrr wrong\n"); + + return -1; + } + + + achi = 0x04; + acli = 0x06; + rs = 0x8000800080008000; + rt = 0x8000800080008000; + + resulth = 0x00; + resultl = 0x7fffffff; + + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "maq_sa.w.qhrr $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + dsp = (dsp >> 17) & 0x1; + if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) { + printf("2 maq_sa.w.qhrr wrong\n"); + + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/mfhi.c b/tests/tcg/mips/mips64-dsp/mfhi.c new file mode 100644 index 0000000000..ee915f796e --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/mfhi.c @@ -0,0 +1,24 @@ +#include "io.h" + +int main(void) +{ + long long achi, acho; + long long result; + + achi = 0x004433; + result = 0x004433; + + __asm + ("mthi %1, $ac1\n\t" + "mfhi %0, $ac1\n\t" + : "=r"(acho) + : "r"(achi) + ); + if (result != acho) { + printf("mfhi wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/mflo.c b/tests/tcg/mips/mips64-dsp/mflo.c new file mode 100644 index 0000000000..cdc646b5fc --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/mflo.c @@ -0,0 +1,24 @@ +#include "io.h" + +int main(void) +{ + long long acli, aclo; + long long result; + + acli = 0x004433; + result = 0x004433; + + __asm + ("mtlo %1, $ac1\n\t" + "mflo %0, $ac1\n\t" + : "=r"(aclo) + : "r"(acli) + ); + if (result != aclo) { + printf("mflo wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/mips_boot.lds b/tests/tcg/mips/mips64-dsp/mips_boot.lds new file mode 100644 index 0000000000..bd7c0c0f3f --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/mips_boot.lds @@ -0,0 +1,31 @@ +OUTPUT_ARCH(mips) +SECTIONS +{ + . = 0xffffffff80100000; + . = ALIGN((1 << 13)); + .text : + { + *(.text) + *(.rodata) + *(.rodata.*) + } + + __init_begin = .; + . = ALIGN((1 << 12)); + .init.text : AT(ADDR(.init.text) - 0) + { + *(.init.text) + } + .init.data : AT(ADDR(.init.data) - 0) + { + *(.init.data) + } + . = ALIGN((1 << 12)); + __init_end = .; + + . = ALIGN((1 << 13)); + .data : + { + *(.data) + } +} diff --git a/tests/tcg/mips/mips64-dsp/modsub.c b/tests/tcg/mips/mips64-dsp/modsub.c new file mode 100644 index 0000000000..2c91cb4c59 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/modsub.c @@ -0,0 +1,37 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0xFFFFFFFF; + rt = 0x000000FF; + result = 0xFFFFFF00; + __asm + ("modsub %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (result != rd) { + printf("modsub wrong\n"); + + return -1; + } + + rs = 0x00000000; + rt = 0x00CD1FFF; + result = 0x0000CD1F; + __asm + ("modsub %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (result != rd) { + printf("modsub wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/msub.c b/tests/tcg/mips/mips64-dsp/msub.c new file mode 100644 index 0000000000..75066b5916 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/msub.c @@ -0,0 +1,32 @@ +#include "io.h" + +int main(void) +{ + long long achi, acli, rs, rt; + long long acho, aclo; + long long resulth, resultl; + + rs = 0x00BBAACC; + rt = 0x0B1C3D2F; + achi = 0x00004433; + acli = 0xFFCC0011; + resulth = 0xFFFFFFFFFFF81F29; + resultl = 0xFFFFFFFFB355089D; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "msub $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((acho != resulth) || (aclo != resultl)) { + printf("msub wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/msubu.c b/tests/tcg/mips/mips64-dsp/msubu.c new file mode 100644 index 0000000000..55f8ae046f --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/msubu.c @@ -0,0 +1,32 @@ +#include "io.h" + +int main(void) +{ + long long achi, acli, rs, rt; + long long acho, aclo; + long long resulth, resultl; + + rs = 0x00BBAACC; + rt = 0x0B1C3D2F; + achi = 0x00004433; + acli = 0xFFCC0011; + resulth = 0xFFFFFFFFFFF81F29; + resultl = 0xFFFFFFFFB355089D; + + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "msubu $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((acho != resulth) || (aclo != resultl)) { + printf("msubu wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/mthi.c b/tests/tcg/mips/mips64-dsp/mthi.c new file mode 100644 index 0000000000..857005139b --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/mthi.c @@ -0,0 +1,24 @@ +#include "io.h" + +int main(void) +{ + long long achi, acho; + long long result; + + achi = 0x004433; + result = 0x004433; + + __asm + ("mthi %1, $ac1\n\t" + "mfhi %0, $ac1\n\t" + : "=r"(acho) + : "r"(achi) + ); + if (result != acho) { + printf("mthi wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/mthlip.c b/tests/tcg/mips/mips64-dsp/mthlip.c new file mode 100644 index 0000000000..957cd426f0 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/mthlip.c @@ -0,0 +1,61 @@ +#include "io.h" + +int main(void) +{ + long long rs, ach, acl, dsp; + long long result, resulth, resultl; + + dsp = 0x07; + ach = 0x05; + acl = 0xB4CB; + rs = 0x00FFBBAA; + resulth = 0xB4CB; + resultl = 0x00FFBBAA; + result = 0x27; + + __asm + ("wrdsp %0, 0x01\n\t" + "mthi %1, $ac1\n\t" + "mtlo %2, $ac1\n\t" + "mthlip %3, $ac1\n\t" + "mfhi %1, $ac1\n\t" + "mflo %2, $ac1\n\t" + "rddsp %0\n\t" + : "+r"(dsp), "+r"(ach), "+r"(acl) + : "r"(rs) + ); + dsp = dsp & 0x3F; + if ((dsp != result) || (ach != resulth) || (acl != resultl)) { + printf("mthlip wrong\n"); + + return -1; + } + + dsp = 0x3f; + ach = 0x05; + acl = 0xB4CB; + rs = 0x00FFBBAA; + resulth = 0xB4CB; + resultl = 0x00FFBBAA; + result = 0x3f; + + __asm + ("wrdsp %0, 0x01\n\t" + "mthi %1, $ac1\n\t" + "mtlo %2, $ac1\n\t" + "mthlip %3, $ac1\n\t" + "mfhi %1, $ac1\n\t" + "mflo %2, $ac1\n\t" + "rddsp %0\n\t" + : "+r"(dsp), "+r"(ach), "+r"(acl) + : "r"(rs) + ); + dsp = dsp & 0x3F; + if ((dsp != result) || (ach != resulth) || (acl != resultl)) { + printf("mthlip wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/mtlo.c b/tests/tcg/mips/mips64-dsp/mtlo.c new file mode 100644 index 0000000000..304fffbe7c --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/mtlo.c @@ -0,0 +1,22 @@ +#include "io.h" + +int main(void) +{ + long long acli, aclo; + long long result; + + acli = 0x004433; + result = 0x004433; + + __asm + ("mthi %1, $ac1\n\t" + "mfhi %0, $ac1\n\t" + : "=r"(aclo) + : "r"(acli) + ); + if (result != aclo) { + printf("mtlo wrong\n"); + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhl.c b/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhl.c new file mode 100644 index 0000000000..6c68d45afe --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhl.c @@ -0,0 +1,56 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result; + + rd = 0; + rs = 0x45BCFFFF12345678; + rt = 0x98529AD287654321; + result = 0x52fbec7035a2ca5c; + + __asm + ("muleq_s.pw.qhl %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (result != rd) { + printf("1 muleq_s.pw.qhl error\n"); + + return -1; + } + + rd = 0; + rs = 0x45BC800012345678; + rt = 0x9852800087654321; + result = 0x52fbec707FFFFFFF; + + __asm + ("muleq_s.pw.qhl %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (result != rd) { + printf("2 muleq_s.pw.qhl error\n"); + + return -1; + } + + rd = 0; + __asm + ("rddsp %0\n\t" + : "=r"(rd) + ); + rd = rd >> 21; + rd = rd & 0x1; + + if (rd != 1) { + printf("3 muleq_s.pw.qhl error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhr.c b/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhr.c new file mode 100644 index 0000000000..fa8b41fd39 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhr.c @@ -0,0 +1,57 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rd = 0; + rs = 0x1234567845BCFFFF; + rt = 0x8765432198529AD2; + result = 0x52fbec7035a2ca5c; + + __asm + ("muleq_s.pw.qhr %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (result != rd) { + printf("1 muleq_s.pw.qhr error\n"); + + return -1; + } + + rd = 0; + rs = 0x1234567845BC8000; + rt = 0x8765432198528000; + result = 0x52fbec707FFFFFFF; + + __asm + ("muleq_s.pw.qhr %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (result != rd) { + printf("2 muleq_s.pw.qhr error\n"); + + return -1; + } + + rd = 0; + __asm + ("rddsp %0\n\t" + : "=r"(rd) + ); + rd = rd >> 21; + rd = rd & 0x1; + + if (rd != 1) { + printf("3 muleq_s.pw.qhr error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/muleq_s_w_phl.c b/tests/tcg/mips/mips64-dsp/muleq_s_w_phl.c new file mode 100644 index 0000000000..997a9f64d9 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/muleq_s_w_phl.c @@ -0,0 +1,46 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x80009988; + rt = 0x80009988; + result = 0x7FFFFFFF; + resultdsp = 1; + + __asm + ("muleq_s.w.phl %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + if ((rd != result) || (dsp != resultdsp)) { + printf("muleq_s.w.phl wrong\n"); + + return -1; + } + + rs = 0x12343322; + rt = 0x43213322; + result = 0x98be968; + resultdsp = 1; + + __asm + ("muleq_s.w.phl %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + if ((rd != result) || (dsp != resultdsp)) { + printf("muleq_s.w.phl wrong\n"); + + return -1; + } + + return 0; +} + diff --git a/tests/tcg/mips/mips64-dsp/muleq_s_w_phr.c b/tests/tcg/mips/mips64-dsp/muleq_s_w_phr.c new file mode 100644 index 0000000000..0e594794dd --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/muleq_s_w_phr.c @@ -0,0 +1,45 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x8000; + rt = 0x8000; + result = 0x7FFFFFFF; + resultdsp = 1; + + __asm + ("muleq_s.w.phr %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + if ((rd != result) || (dsp != resultdsp)) { + printf("muleq_s.w.phr wrong\n"); + + return -1; + } + + rs = 0x1234; + rt = 0x4321; + result = 0x98be968; + resultdsp = 1; + + __asm + ("muleq_s.w.phr %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + if ((rd != result) || (dsp != resultdsp)) { + printf("muleq_s.w.phr wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbl.c b/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbl.c new file mode 100644 index 0000000000..2f444c9f85 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbl.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x80001234; + rt = 0x80004321; + result = 0xFFFFFFFFFFFF0000; + resultdsp = 1; + + __asm + ("muleu_s.ph.qbl %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + if ((rd != result) || (dsp != resultdsp)) { + printf("muleu_s.ph.qbl wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbr.c b/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbr.c new file mode 100644 index 0000000000..8bd0e9942c --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbr.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x8000; + rt = 0x80004321; + result = 0xFFFFFFFFFFFF0000; + resultdsp = 1; + + __asm + ("muleu_s.ph.qbr %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + if ((rd != result) || (dsp != resultdsp)) { + printf("muleu_s.ph.qbr wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/muleu_s_qh_obl.c b/tests/tcg/mips/mips64-dsp/muleu_s_qh_obl.c new file mode 100644 index 0000000000..db0d386e88 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/muleu_s_qh_obl.c @@ -0,0 +1,30 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long dsp; + long long resdsp, result; + + rd = 0; + rs = 0x1234567802020202; + rt = 0x0034432112344321; + result = 0x03A8FFFFFFFFFFFF; + resdsp = 0x01; + + __asm + ("muleu_s.qh.obl %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + + dsp = (dsp >> 21) & 0x01; + if ((rd != result) || (resdsp != dsp)) { + printf("muleu_s.qh.obl error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/muleu_s_qh_obr.c b/tests/tcg/mips/mips64-dsp/muleu_s_qh_obr.c new file mode 100644 index 0000000000..52ed9c095a --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/muleu_s_qh_obr.c @@ -0,0 +1,31 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long dsp; + long long resdsp, result; + + rd = 0; + rs = 0x0202020212345678; + + rt = 0x0034432112344321; + result = 0x03A8FFFFFFFFFFFF; + resdsp = 0x01; + + __asm + ("muleu_s.qh.obr %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + + dsp = (dsp >> 21) & 0x01; + if ((rd != result) || (resdsp != dsp)) { + printf("muleu_s.qh.obr error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/mulq_rs_ph.c b/tests/tcg/mips/mips64-dsp/mulq_rs_ph.c new file mode 100644 index 0000000000..fd6233d4df --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/mulq_rs_ph.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x80001234; + rt = 0x80004321; + result = 0x7FFF098C; + resultdsp = 1; + + __asm + ("mulq_rs.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + if ((rd != result) || (dsp != resultdsp)) { + printf("mulq_rs.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/mulq_rs_qh.c b/tests/tcg/mips/mips64-dsp/mulq_rs_qh.c new file mode 100644 index 0000000000..7863c05912 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/mulq_rs_qh.c @@ -0,0 +1,33 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result, dsp, dspresult; + rt = 0x80003698CE8F9201; + rs = 0x800034634BCDE321; + result = 0x7fff16587a530313; + + dspresult = 0x01; + + __asm + ("mulq_rs.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + + if (rd != result) { + printf("mulq_rs.qh error\n"); + + return -1; + } + + dsp = (dsp >> 21) & 0x01; + if (dsp != dspresult) { + printf("mulq_rs.qh DSPControl Reg ouflag error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/mulsaq_s_l_pw.c b/tests/tcg/mips/mips64-dsp/mulsaq_s_l_pw.c new file mode 100644 index 0000000000..02548f85cf --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/mulsaq_s_l_pw.c @@ -0,0 +1,59 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, dsp; + long long achi, acli; + long long acho, aclo; + long long resl, resh; + + achi = 0x4; + acli = 0x4; + + rs = 0x1234567887654321; + rt = 0x8765432112345678; + + resh = 0x4; + resl = 0x4; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "mulsaq_s.l.pw $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((acho != resh) || (aclo != resl)) { + printf("1 mulsaq_s.l.pw wrong\n"); + + return -1; + } + + achi = 0x4; + acli = 0x4; + + rs = 0x8000000087654321; + rt = 0x8000000012345678; + + resh = 0x4; + resl = 0x1e8ee513; + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "mulsaq_s.l.pw $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x1; + if ((dsp != 0x1) || (acho != resh) || (aclo != resl)) { + printf("2 mulsaq_s.l.pw wrong\n"); + + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/mulsaq_s_w_qh.c b/tests/tcg/mips/mips64-dsp/mulsaq_s_w_qh.c new file mode 100644 index 0000000000..92d7a0b4f2 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/mulsaq_s_w_qh.c @@ -0,0 +1,57 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, dsp; + long long achi, acli; + long long acho, aclo; + long long resl, resh; + + achi = 0x4; + acli = 0x4; + + rs = 0x5678123443218765; + rt = 0x4321876556781234; + + resh = 0x4; + resl = 0x342fcbd4; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "mulsaq_s.w.qh $ac1, %4, %5\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((acho != resh) || (aclo != resl)) { + printf("1 mulsaq_s.w.qh wrong\n"); + return -1; + } + + achi = 0x4; + acli = 0x4; + + rs = 0x8000800087654321; + rt = 0x8000800012345678; + + resh = 0x3; + resl = 0xffffffffe5e81a1c; + __asm + ("mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "mulsaq_s.w.qh $ac1, %5, %6\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "=r"(acho), "=r"(aclo), "=r"(dsp) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x1; + if ((dsp != 0x1) || (acho != resh) || (aclo != resl)) { + printf("2 mulsaq_s.w.qh wrong\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/mult.c b/tests/tcg/mips/mips64-dsp/mult.c new file mode 100644 index 0000000000..4a294d1a0c --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/mult.c @@ -0,0 +1,26 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, ach, acl; + long long result, resulth, resultl; + + rs = 0x00FFBBAA; + rt = 0x4B231000; + resulth = 0x4b0f01; + resultl = 0x71f8a000; + __asm + ("mult $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(ach), "=r"(acl) + : "r"(rs), "r"(rt) + ); + if ((ach != resulth) || (acl != resultl)) { + printf("mult wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/multu.c b/tests/tcg/mips/mips64-dsp/multu.c new file mode 100644 index 0000000000..21a8a7c77d --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/multu.c @@ -0,0 +1,26 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt, ach, acl; + long long result, resulth, resultl; + + rs = 0x00FFBBAA; + rt = 0x4B231000; + resulth = 0x4b0f01; + resultl = 0x71f8a000; + __asm + ("multu $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "=r"(ach), "=r"(acl) + : "r"(rs), "r"(rt) + ); + if ((ach != resulth) || (acl != resultl)) { + printf("multu wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/packrl_ph.c b/tests/tcg/mips/mips64-dsp/packrl_ph.c new file mode 100644 index 0000000000..3722b0ae6c --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/packrl_ph.c @@ -0,0 +1,24 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x56788765; + + __asm + ("packrl.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (result != rd) { + printf("packrl.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/packrl_pw.c b/tests/tcg/mips/mips64-dsp/packrl_pw.c new file mode 100644 index 0000000000..7807418834 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/packrl_pw.c @@ -0,0 +1,24 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long res; + + rs = 0x1234567887654321; + rt = 0xabcdef9812345678; + + res = 0x87654321abcdef98; + + __asm + ("packrl.pw %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != res) { + printf("packrl.pw error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/pick_ob.c b/tests/tcg/mips/mips64-dsp/pick_ob.c new file mode 100644 index 0000000000..160049ffd4 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/pick_ob.c @@ -0,0 +1,66 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long res; + + dsp = 0xff000000; + + rs = 0x1234567812345678; + rt = 0x8765432187654321; + + res = 0x1234567812345678; + + __asm + ("wrdsp %1, 0x10\n\t" + "pick.ob %0, %2, %3\n\t" + : "=r"(rd) + : "r"(dsp), "r"(rs), "r"(rt) + ); + + if (rd != res) { + printf("1 pick.ob error\n"); + return -1; + } + + dsp = 0x00000000; + + rs = 0x1234567812345678; + rt = 0x8765432187654321; + + res = 0x8765432187654321; + + __asm + ("wrdsp %1, 0x10\n\t" + "pick.ob %0, %2, %3\n\t" + : "=r"(rd) + : "r"(dsp), "r"(rs), "r"(rt) + ); + + if (rd != res) { + printf("2 pick.ob error\n"); + return -1; + } + + dsp = 0x34000000; + + rs = 0x1234567812345678; + rt = 0x8765432187654321; + + res = 0x8765567887344321; + + __asm + ("wrdsp %1, 0x10\n\t" + "pick.ob %0, %2, %3\n\t" + : "=r"(rd) + : "r"(dsp), "r"(rs), "r"(rt) + ); + + if (rd != res) { + printf("3 pick.ob error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/pick_ph.c b/tests/tcg/mips/mips64-dsp/pick_ph.c new file mode 100644 index 0000000000..8800c14d1e --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/pick_ph.c @@ -0,0 +1,60 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result; + + rs = 0x12345678; + rt = 0x87654321; + dsp = 0x0A000000; + result = 0x12344321; + + __asm + ("wrdsp %3, 0x10\n\t" + "pick.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt), "r"(dsp) + ); + if (rd != result) { + printf("1 pick.ph wrong\n"); + + return -1; + } + + rs = 0x12345678; + rt = 0x87654321; + dsp = 0x03000000; + result = 0x12345678; + + __asm + ("wrdsp %3, 0x10\n\t" + "pick.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt), "r"(dsp) + ); + if (rd != result) { + printf("2 pick.ph wrong\n"); + + return -1; + } + + rs = 0x12345678; + rt = 0x87654321; + dsp = 0x00000000; + result = 0xffffffff87654321; + + __asm + ("wrdsp %3, 0x10\n\t" + "pick.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt), "r"(dsp) + ); + if (rd != result) { + printf("3 pick.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/pick_pw.c b/tests/tcg/mips/mips64-dsp/pick_pw.c new file mode 100644 index 0000000000..24d80f551a --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/pick_pw.c @@ -0,0 +1,48 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long res; + dsp = 0xff000000; + + rs = 0x1234567812345678; + rt = 0x8765432187654321; + + res = 0x1234567812345678; + + __asm + ("wrdsp %1, 0x10\n\t" + "wrdsp %1\n\t" + "pick.pw %0, %2, %3\n\t" + : "=r"(rd), "+r"(dsp) + : "r"(rs), "r"(rt) + ); + + if (rd != res) { + printf("pick.pw error\n"); + return -1; + } + + dsp = 0x00000000; + + rs = 0x1234567812345678; + rt = 0x8765432187654321; + + res = 0x8765432187654321; + + __asm + ("wrdsp %1, 0x10\n\t" + "wrdsp %1\n\t" + "pick.pw %0, %2, %3\n\t" + : "=r"(rd), "+r"(dsp) + : "r"(rs), "r"(rt) + ); + + if (rd != res) { + printf("pick.pw error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/pick_qb.c b/tests/tcg/mips/mips64-dsp/pick_qb.c new file mode 100644 index 0000000000..0d5de9db9e --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/pick_qb.c @@ -0,0 +1,43 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result; + + rs = 0x12345678; + rt = 0x87654321; + dsp = 0x0f000000; + result = 0x12345678; + + __asm + ("wrdsp %3, 0x10\n\t" + "pick.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt), "r"(dsp) + ); + if (rd != result) { + printf("pick.qb wrong\n"); + + return -1; + } + + rs = 0x12345678; + rt = 0x87654321; + dsp = 0x00000000; + result = 0xffffffff87654321; + + __asm + ("wrdsp %3, 0x10\n\t" + "pick.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt), "r"(dsp) + ); + if (rd != result) { + printf("pick.qb wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/pick_qh.c b/tests/tcg/mips/mips64-dsp/pick_qh.c new file mode 100644 index 0000000000..aa2e2938af --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/pick_qh.c @@ -0,0 +1,48 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long res; + dsp = 0xff000000; + + rs = 0x1234567812345678; + rt = 0x8765432187654321; + + res = 0x1234567812345678; + + __asm + ("wrdsp %1, 0x10\n\t" + "wrdsp %1\n\t" + "pick.qh %0, %2, %3\n\t" + : "=r"(rd), "+r"(dsp) + : "r"(rs), "r"(rt) + ); + + if (rd != res) { + printf("pick.qh error\n"); + return -1; + } + + dsp = 0x00000000; + + rs = 0x1234567812345678; + rt = 0x8765432187654321; + + res = 0x8765432187654321; + + __asm + ("wrdsp %1, 0x10\n\t" + "wrdsp %1\n\t" + "pick.qh %0, %2, %3\n\t" + : "=r"(rd), "+r"(dsp) + : "r"(rs), "r"(rt) + ); + + if (rd != res) { + printf("pick.qh error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/preceq_l_pwl.c b/tests/tcg/mips/mips64-dsp/preceq_l_pwl.c new file mode 100644 index 0000000000..64551007cf --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/preceq_l_pwl.c @@ -0,0 +1,24 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + rt = 0xFFFFFFFF11111111; + result = 0xFFFFFFFF00000000; + + __asm + ("preceq.l.pwl %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("preceq.l.pwl wrong\n"); + + return -1; + } + + return 0; +} + diff --git a/tests/tcg/mips/mips64-dsp/preceq_l_pwr.c b/tests/tcg/mips/mips64-dsp/preceq_l_pwr.c new file mode 100644 index 0000000000..1e05339d23 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/preceq_l_pwr.c @@ -0,0 +1,24 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + rt = 0xFFFFFFFF11111111; + result = 0x1111111100000000; + + __asm + ("preceq.l.pwl %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("preceq.l.pwr wrong\n"); + + return -1; + } + + return 0; +} + diff --git a/tests/tcg/mips/mips64-dsp/preceq_pw_qhl.c b/tests/tcg/mips/mips64-dsp/preceq_pw_qhl.c new file mode 100644 index 0000000000..f44b940492 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/preceq_pw_qhl.c @@ -0,0 +1,21 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result; + rt = 0x0123456789ABCDEF; + result = 0x0123000045670000; + + __asm + ("preceq.pw.qhl %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (result != rd) { + printf("preceq.pw.qhl error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/preceq_pw_qhla.c b/tests/tcg/mips/mips64-dsp/preceq_pw_qhla.c new file mode 100644 index 0000000000..f0f78f43c5 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/preceq_pw_qhla.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result; + + rt = 0x123456789ABCDEF0; + result = 0x123400009ABC0000; + + __asm + ("preceq.pw.qhla %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("preceq.pw.qhla error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/preceq_pw_qhr.c b/tests/tcg/mips/mips64-dsp/preceq_pw_qhr.c new file mode 100644 index 0000000000..709d4f9004 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/preceq_pw_qhr.c @@ -0,0 +1,21 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result; + rt = 0x0123456789ABCDEF; + result = 0x89AB0000CDEF0000; + + __asm + ("preceq.pw.qhr %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (result != rd) { + printf("preceq.pw.qhr error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/preceq_pw_qhra.c b/tests/tcg/mips/mips64-dsp/preceq_pw_qhra.c new file mode 100644 index 0000000000..4d071ec863 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/preceq_pw_qhra.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result; + + rt = 0x123456789ABCDEF0; + result = 0x56780000DEF00000; + + __asm + ("preceq.pw.qhra %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("preceq.pw.qhra error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/preceq_w_phl.c b/tests/tcg/mips/mips64-dsp/preceq_w_phl.c new file mode 100644 index 0000000000..4ed3fc030c --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/preceq_w_phl.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x87654321; + result = 0xFFFFFFFF87650000; + + __asm + ("preceq.w.phl %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (result != rd) { + printf("preceq.w.phl wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/preceq_w_phr.c b/tests/tcg/mips/mips64-dsp/preceq_w_phr.c new file mode 100644 index 0000000000..e2ea0933b2 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/preceq_w_phr.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x87654321; + result = 0x43210000; + + __asm + ("preceq.w.phr %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (result != rd) { + printf("preceq.w.phr wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precequ_ph_qbl.c b/tests/tcg/mips/mips64-dsp/precequ_ph_qbl.c new file mode 100644 index 0000000000..17b73311dc --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precequ_ph_qbl.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x87654321; + result = 0x43803280; + + __asm + ("precequ.ph.qbl %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (result != rd) { + printf("precequ.ph.qbl wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precequ_ph_qbla.c b/tests/tcg/mips/mips64-dsp/precequ_ph_qbla.c new file mode 100644 index 0000000000..15e94946b1 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precequ_ph_qbla.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x87654321; + result = 0x43802180; + + __asm + ("precequ.ph.qbla %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (result != rd) { + printf("precequ.ph.qbla wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precequ_ph_qbr.c b/tests/tcg/mips/mips64-dsp/precequ_ph_qbr.c new file mode 100644 index 0000000000..495368ce0b --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precequ_ph_qbr.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x87654321; + result = 0x21801080; + + __asm + ("precequ.ph.qbr %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (result != rd) { + printf("precequ.ph.qbr wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precequ_ph_qbra.c b/tests/tcg/mips/mips64-dsp/precequ_ph_qbra.c new file mode 100644 index 0000000000..7c6636975c --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precequ_ph_qbra.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x87654321; + result = 0x32801080; + + __asm + ("precequ.ph.qbra %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (result != rd) { + printf("precequ.ph.qbra wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precequ_qh_obl.c b/tests/tcg/mips/mips64-dsp/precequ_qh_obl.c new file mode 100644 index 0000000000..176d2365a8 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precequ_qh_obl.c @@ -0,0 +1,22 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result; + rt = 0x123456789ABCDEF0; + result = 0x09001A002B003C00; + + __asm + ("precequ.qh.obla %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("precequ.qh.obla error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precequ_qh_obla.c b/tests/tcg/mips/mips64-dsp/precequ_qh_obla.c new file mode 100644 index 0000000000..93a36a4855 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precequ_qh_obla.c @@ -0,0 +1,22 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result; + rt = 0x123456789ABCDEF0; + result = 0x09002B004D006F00; + + __asm + ("precequ.qh.obla %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("precequ.qh.obla error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precequ_qh_obr.c b/tests/tcg/mips/mips64-dsp/precequ_qh_obr.c new file mode 100644 index 0000000000..121473083b --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precequ_qh_obr.c @@ -0,0 +1,24 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result; + + rt = 0x123456789ABCDEF0; + result = 0x4D005E006F007000; + + __asm + ("precequ.qh.obr %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("precequ.qh.obr error\n"); + + return -1; + } + + return 0; +} + diff --git a/tests/tcg/mips/mips64-dsp/precequ_qh_obra.c b/tests/tcg/mips/mips64-dsp/precequ_qh_obra.c new file mode 100644 index 0000000000..3aa0e096ca --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precequ_qh_obra.c @@ -0,0 +1,24 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result; + + rt = 0x123456789ABCDEF0; + result = 0x1A003C005D007000; + + __asm + ("precequ.qh.obra %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("precequ.qh.obra error\n"); + + return -1; + } + + return 0; +} + diff --git a/tests/tcg/mips/mips64-dsp/preceu_ph_qbl.c b/tests/tcg/mips/mips64-dsp/preceu_ph_qbl.c new file mode 100644 index 0000000000..81f7917c19 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/preceu_ph_qbl.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x87654321; + result = 0x00870065; + + __asm + ("preceu.ph.qbl %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (result != rd) { + printf("preceu.ph.qbl wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/preceu_ph_qbla.c b/tests/tcg/mips/mips64-dsp/preceu_ph_qbla.c new file mode 100644 index 0000000000..38cf6a62b9 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/preceu_ph_qbla.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x87654321; + result = 0x00870043; + + __asm + ("preceu.ph.qbla %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (result != rd) { + printf("preceu.ph.qbla wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/preceu_ph_qbr.c b/tests/tcg/mips/mips64-dsp/preceu_ph_qbr.c new file mode 100644 index 0000000000..70c32b6716 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/preceu_ph_qbr.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x87654321; + result = 0x00430021; + + __asm + ("preceu.ph.qbr %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (result != rd) { + printf("preceu.ph.qbr wrong"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/preceu_ph_qbra.c b/tests/tcg/mips/mips64-dsp/preceu_ph_qbra.c new file mode 100644 index 0000000000..c6638aaafd --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/preceu_ph_qbra.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x87654321; + result = 0x00650021; + + __asm + ("preceu.ph.qbra %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (result != rd) { + printf("preceu.ph.qbra wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/preceu_qh_obl.c b/tests/tcg/mips/mips64-dsp/preceu_qh_obl.c new file mode 100644 index 0000000000..63f9373b08 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/preceu_qh_obl.c @@ -0,0 +1,22 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result; + rt = 0x123456789ABCDEF0; + result = 0x0012003400560078; + + __asm + ("preceu.qh.obl %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("preceu.qh.obl error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/preceu_qh_obla.c b/tests/tcg/mips/mips64-dsp/preceu_qh_obla.c new file mode 100644 index 0000000000..5fb65e4049 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/preceu_qh_obla.c @@ -0,0 +1,22 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result; + rt = 0x123456789ABCDEF0; + result = 0x00120056009A00DE; + + __asm + ("preceu.qh.obla %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("preceu.qh.obla error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/preceu_qh_obr.c b/tests/tcg/mips/mips64-dsp/preceu_qh_obr.c new file mode 100644 index 0000000000..9af3b6372e --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/preceu_qh_obr.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result; + + rt = 0x123456789ABCDEF0; + result = 0x009A00BC00DE00F0; + + __asm + ("preceu.qh.obr %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("preceu.qh.obr error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/preceu_qh_obra.c b/tests/tcg/mips/mips64-dsp/preceu_qh_obra.c new file mode 100644 index 0000000000..fd04083371 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/preceu_qh_obra.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result; + + rt = 0x123456789ABCDEF0; + result = 0x0034007800BC00F0; + + __asm + ("preceu.qh.obra %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("preceu.qh.obra error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precr_ob_qh.c b/tests/tcg/mips/mips64-dsp/precr_ob_qh.c new file mode 100644 index 0000000000..ce2da79af8 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precr_ob_qh.c @@ -0,0 +1,25 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long res; + + rs = 0x1234567812345678; + rt = 0x8765432187654321; + + res = 0x3478347865216521; + + __asm + ("precr.ob.qh %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != res) { + printf("precr.ob.qh error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precr_sra_qh_pw.c b/tests/tcg/mips/mips64-dsp/precr_sra_qh_pw.c new file mode 100644 index 0000000000..8bb16de9af --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precr_sra_qh_pw.c @@ -0,0 +1,40 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long res; + + rt = 0x8765432187654321; + rs = 0x1234567812345678; + + res = 0x4321432156785678; + + __asm + ("precr_sra.qh.pw %0, %1, 0x0\n\t" + : "=r"(rt) + : "r"(rs) + ); + + if (rt != res) { + printf("precr_sra.qh.pw error\n"); + return -1; + } + + rt = 0x8765432187654321; + rs = 0x1234567812345678; + + res = 0x5432543245674567; + + __asm + ("precr_sra.qh.pw %0, %1, 0x4\n\t" + : "=r"(rt) + : "r"(rs) + ); + + if (rt != res) { + printf("precr_sra.qh.pw error\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precr_sra_r_qh_pw.c b/tests/tcg/mips/mips64-dsp/precr_sra_r_qh_pw.c new file mode 100644 index 0000000000..734ac322e7 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precr_sra_r_qh_pw.c @@ -0,0 +1,40 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long res; + + rt = 0x8765432187654321; + rs = 0x1234567812345678; + + res = 0x4321432156785678; + + __asm + ("precr_sra_r.qh.pw %0, %1, 0x0\n\t" + : "=r"(rt) + : "r"(rs) + ); + + if (rt != res) { + printf("precr_sra_r.qh.pw error\n"); + return -1; + } + + rt = 0x8765432187654321; + rs = 0x1234567812345678; + + res = 0x5432543245684568; + + __asm + ("precr_sra_r.qh.pw %0, %1, 0x4\n\t" + : "=r"(rt) + : "r"(rs) + ); + + if (rt != res) { + printf("precr_sra_r.qh.pw error\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precrq_ob_qh.c b/tests/tcg/mips/mips64-dsp/precrq_ob_qh.c new file mode 100644 index 0000000000..4f61b1709e --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precrq_ob_qh.c @@ -0,0 +1,25 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long res; + + rs = 0x1234567812345678; + rt = 0x8765432187654321; + + res = 0x1256125687438743; + + __asm + ("precrq.ob.qh %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != res) { + printf("precrq.ob.qh error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precrq_ph_w.c b/tests/tcg/mips/mips64-dsp/precrq_ph_w.c new file mode 100644 index 0000000000..f0946abdcb --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precrq_ph_w.c @@ -0,0 +1,24 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x12348765; + + __asm + ("precrq.ph.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (result != rd) { + printf("precrq.ph.w wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precrq_pw_l.c b/tests/tcg/mips/mips64-dsp/precrq_pw_l.c new file mode 100644 index 0000000000..da957c0743 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precrq_pw_l.c @@ -0,0 +1,25 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long res; + + rs = 0x1234567812345678; + rt = 0x8765432187654321; + + res = 0x1234567887654321; + + __asm + ("precrq.pw.l %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != res) { + printf("precrq.pw.l error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precrq_qb_ph.c b/tests/tcg/mips/mips64-dsp/precrq_qb_ph.c new file mode 100644 index 0000000000..f417c9f342 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precrq_qb_ph.c @@ -0,0 +1,24 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x12568743; + + __asm + ("precrq.qb.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (result != rd) { + printf("precrq.qb.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precrq_qh_pw.c b/tests/tcg/mips/mips64-dsp/precrq_qh_pw.c new file mode 100644 index 0000000000..4a4ffef8ea --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precrq_qh_pw.c @@ -0,0 +1,25 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long res; + + rs = 0x1234567812345678; + rt = 0x8765432187654321; + + res = 0x1234123487658765; + + __asm + ("precrq.qh.pw %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != res) { + printf("precrq.qh.pw error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precrq_rs_ph_w.c b/tests/tcg/mips/mips64-dsp/precrq_rs_ph_w.c new file mode 100644 index 0000000000..61da3331fb --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precrq_rs_ph_w.c @@ -0,0 +1,41 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long dsp; + long long result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x12348765; + + __asm + ("precrq_rs.ph.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (result != rd) { + printf("1 precrq_rs.ph.w wrong\n"); + + return -1; + } + + rs = 0x7fffC678; + rt = 0x865432A0; + result = 0x7fff8654; + + __asm + ("precrq_rs.ph.w %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + if ((result != rd) || (((dsp >> 22) & 0x01) != 1)) { + printf("2 precrq_rs.ph.w wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precrq_rs_qh_pw.c b/tests/tcg/mips/mips64-dsp/precrq_rs_qh_pw.c new file mode 100644 index 0000000000..ac78728abf --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precrq_rs_qh_pw.c @@ -0,0 +1,43 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long dsp; + long long res; + + rs = 0x1234567812345678; + rt = 0x8765432187654321; + + res = 0x1234123487658765; + + __asm + ("precrq_rs.qh.pw %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != res) { + printf("precrq_rs.qh.pw error\n"); + return -1; + } + + rs = 0x7fffC67812345678; + rt = 0x8765432187654321; + + res = 0x7fff123487658765; + + __asm + ("precrq_rs.qh.pw %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + + if (rd != res) { + printf("precrq_rs.qh.pw error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precrqu_s_ob_qh.c b/tests/tcg/mips/mips64-dsp/precrqu_s_ob_qh.c new file mode 100644 index 0000000000..e27c36b7fd --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precrqu_s_ob_qh.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long res, resdsp; + + rs = 0x7fff567812345678; + rt = 0x8765432187654321; + + res = 0xffac24ac00860086; + resdsp = 0x1; + + __asm + ("precrqu_s.ob.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 22) & 0x1; + if ((rd != res) || (dsp != resdsp)) { + printf("precrq_s.ob.qh error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/precrqu_s_qb_ph.c b/tests/tcg/mips/mips64-dsp/precrqu_s_qb_ph.c new file mode 100644 index 0000000000..cb1fee4508 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/precrqu_s_qb_ph.c @@ -0,0 +1,26 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long dsp; + long long result; + + rs = 0x12345678; + rt = 0x87657fff; + result = 0x24AC00FF; + + __asm + ("precrqu_s.qb.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + if ((result != rd) || (((dsp >> 22) & 0x01) != 0x01)) { + printf("precrqu_s.qb.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/prependd.c b/tests/tcg/mips/mips64-dsp/prependd.c new file mode 100644 index 0000000000..b4208c2dab --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/prependd.c @@ -0,0 +1,37 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs; + long long res; + rt = 0x1234567887654321; + rs = 0xabcd1234abcd8765; + + res = 0x1234567887654321; + __asm + ("prependd %0, %1, 0x0\n\t" + : "=r"(rt) + : "r"(rs) + ); + + if (rt != res) { + printf("prependd error\n"); + return -1; + } + + rt = 0x1234567887654321; + rs = 0xabcd1234abcd8765; + + res = 0xd876512345678876; + __asm + ("prependd %0, %1, 0x4\n\t" + : "=r"(rt) + : "r"(rs) + ); + + if (rt != res) { + printf("prependd error\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/prependw.c b/tests/tcg/mips/mips64-dsp/prependw.c new file mode 100644 index 0000000000..d91bd2023c --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/prependw.c @@ -0,0 +1,37 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs; + long long res; + rt = 0x1234567887654321; + rs = 0xabcd1234abcd8765; + + res = 0x1234567887654321; + __asm + ("prependw %0, %1, 0x0\n\t" + : "=r"(rt) + : "r"(rs) + ); + + if (rt != res) { + printf("prependw error\n"); + return -1; + } + + rt = 0x1234567887654321; + rs = 0xabcd1234abcd8765; + + res = 0x5123456788765432; + __asm + ("prependw %0, %1, 0x4\n\t" + : "=r"(rt) + : "r"(rs) + ); + + if (rt != res) { + printf("prependw error\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/printf.c b/tests/tcg/mips/mips64-dsp/printf.c new file mode 100644 index 0000000000..cf8676d390 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/printf.c @@ -0,0 +1,266 @@ + +typedef unsigned long va_list; + +#define ACC 4 +#define __read(source) \ +({ va_list __res; \ + __asm__ __volatile__( \ + "move\t%0, " #source "\n\t" \ + : "=r" (__res)); \ + __res; \ +}) + +enum format_type { + FORMAT_TYPE_NONE, + FORMAT_TYPE_HEX, + FORMAT_TYPE_ULONG, + FORMAT_TYPE_FLOAT +}; + +struct printf_spec { + char type; +}; + +static int format_decode(char *fmt, struct printf_spec *spec) +{ + char *start = fmt; + + for (; *fmt ; ++fmt) { + if (*fmt == '%') { + break; + } + } + + switch (*++fmt) { + case 'x': + spec->type = FORMAT_TYPE_HEX; + break; + + case 'd': + spec->type = FORMAT_TYPE_ULONG; + break; + + case 'f': + spec->type = FORMAT_TYPE_FLOAT; + break; + + default: + spec->type = FORMAT_TYPE_NONE; + } + + return ++fmt - start; +} + +void *memcpy(void *dest, void *src, int n) +{ + int i; + char *s = src; + char *d = dest; + + for (i = 0; i < n; i++) { + d[i] = s[i]; + } + return dest; +} + +char *number(char *buf, va_list num) +{ + int i; + char *str = buf; + static char digits[16] = "0123456789abcdef"; + str = str + sizeof(num) * 2; + + for (i = 0; i < sizeof(num) * 2; i++) { + *--str = digits[num & 15]; + num >>= 4; + } + + return buf + sizeof(num) * 2; +} + +char *__number(char *buf, va_list num) +{ + int i; + va_list mm = num; + char *str = buf; + + if (!num) { + *str++ = '0'; + return str; + } + + for (i = 0; mm; mm = mm/10, i++) { + /* Do nothing. */ + } + + str = str + i; + + while (num) { + *--str = num % 10 + 48; + num = num / 10; + } + + return str + i; +} + +va_list modf(va_list args, va_list *integer, va_list *num) +{ + int i; + double dot_v = 0; + va_list E, DOT, DOT_V; + + if (!args) { + return 0; + } + + for (i = 0, args = args << 1 >> 1; i < 52; i++) { + if ((args >> i) & 0x1) { + break; + } + } + + *integer = 0; + + if ((args >> 56 != 0x3f) || (args >> 52 == 0x3ff)) { + E = (args >> 52) - 1023; + DOT = 52 - E - i; + DOT_V = args << (12 + E) >> (12 + E) >> i; + *integer = ((args << 12 >> 12) >> (i + DOT)) | (1 << E); + } else { + E = ~((args >> 52) - 1023) + 1; + DOT_V = args << 12 >> 12; + + dot_v += 1.0 / (1 << E); + + for (i = 1; i <= 16; i++) { + if ((DOT_V >> (52 - i)) & 0x1) { + dot_v += 1.0 / (1 << E + i); + } + } + + for (i = 1, E = 0; i <= ACC; i++) { + dot_v *= 10; + if (!(va_list)dot_v) { + E++; + } + } + + *num = E; + + return dot_v; + } + + if (args & 0xf) { + for (i = 1; i <= 16; i++) { + if ((DOT_V >> (DOT - i)) & 0x1) { + dot_v += 1.0 / (1 << i); + } + } + + for (i = 1, E = 0; i <= ACC; i++) { + dot_v *= 10; + if (!(va_list)dot_v) { + E++; + } + } + + *num = E; + + return dot_v; + } else if (DOT) { + for (i = 1; i <= DOT; i++) { + if ((DOT_V >> (DOT - i)) & 0x1) { + dot_v += 1.0 / (1 << i); + } + } + + for (i = 1; i <= ACC; i++) { + dot_v = dot_v * 10; + } + + return dot_v; + } + + return 0; +} + +int vsnprintf(char *buf, int size, char *fmt, va_list args) +{ + char *str, *mm; + struct printf_spec spec = {0}; + + str = mm = buf; + + while (*fmt) { + char *old_fmt = fmt; + int read = format_decode(fmt, &spec); + + fmt += read; + + switch (spec.type) { + case FORMAT_TYPE_NONE: { + memcpy(str, old_fmt, read); + str += read; + break; + } + case FORMAT_TYPE_HEX: { + memcpy(str, old_fmt, read); + str = number(str + read, args); + for (; *mm ; ++mm) { + if (*mm == '%') { + *mm = '0'; + break; + } + } + break; + } + case FORMAT_TYPE_ULONG: { + memcpy(str, old_fmt, read - 2); + str = __number(str + read - 2, args); + break; + } + case FORMAT_TYPE_FLOAT: { + va_list integer, dot_v, num; + dot_v = modf(args, &integer, &num); + memcpy(str, old_fmt, read - 2); + str += read - 2; + if ((args >> 63 & 0x1)) { + *str++ = '-'; + } + str = __number(str, integer); + if (dot_v) { + *str++ = '.'; + while (num--) { + *str++ = '0'; + } + str = __number(str, dot_v); + } + break; + } + } + } + *str = '\0'; + + return str - buf; +} + +static void serial_out(char *str) +{ + while (*str) { + *(char *)0xffffffffb80003f8 = *str++; + } +} + +int vprintf(char *fmt, va_list args) +{ + int printed_len = 0; + static char printf_buf[512]; + printed_len = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args); + serial_out(printf_buf); + return printed_len; +} + +int printf(char *fmt, ...) +{ + return vprintf(fmt, __read($5)); +} diff --git a/tests/tcg/mips/mips64-dsp/raddu_l_ob.c b/tests/tcg/mips/mips64-dsp/raddu_l_ob.c new file mode 100644 index 0000000000..76ddf25fb9 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/raddu_l_ob.c @@ -0,0 +1,22 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, result; + rs = 0x12345678ABCDEF0; + result = 0x000000000001E258; + + __asm + ("raddu.l.ob %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs) + ); + + if (rd != result) { + printf("raddu.l.ob error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/raddu_w_qb.c b/tests/tcg/mips/mips64-dsp/raddu_w_qb.c new file mode 100644 index 0000000000..c9d6535bba --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/raddu_w_qb.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs; + long long result; + + rs = 0x12345678; + result = 0x114; + + __asm + ("raddu.w.qb %0, %1\n\t" + : "=r"(rd) + : "r"(rs) + ); + if (rd != result) { + printf("raddu.w.qb wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/rddsp.c b/tests/tcg/mips/mips64-dsp/rddsp.c new file mode 100644 index 0000000000..7165572435 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/rddsp.c @@ -0,0 +1,53 @@ +#include "io.h" + +int main(void) +{ + long long dsp_i, dsp_o; + long long ccond_i, outflag_i, efi_i, c_i, scount_i, pos_i; + long long ccond_o, outflag_o, efi_o, c_o, scount_o, pos_o; + long long ccond_r, outflag_r, efi_r, c_r, scount_r, pos_r; + + ccond_i = 0x000000BC;/* 4 */ + outflag_i = 0x0000001B;/* 3 */ + efi_i = 0x00000001;/* 5 */ + c_i = 0x00000001;/* 2 */ + scount_i = 0x0000000F;/* 1 */ + pos_i = 0x0000000C;/* 0 */ + + dsp_i = (ccond_i << 24) | \ + (outflag_i << 16) | \ + (efi_i << 14) | \ + (c_i << 13) | \ + (scount_i << 7) | \ + pos_i; + + ccond_r = ccond_i; + outflag_r = outflag_i; + efi_r = efi_i; + c_r = c_i; + scount_r = scount_i; + pos_r = pos_i; + + __asm + ("wrdsp %1, 0x3F\n\t" + "rddsp %0, 0x3F\n\t" + : "=r"(dsp_o) + : "r"(dsp_i) + ); + + ccond_o = (dsp_o >> 24) & 0xFF; + outflag_o = (dsp_o >> 16) & 0xFF; + efi_o = (dsp_o >> 14) & 0x01; + c_o = (dsp_o >> 14) & 0x01; + scount_o = (dsp_o >> 7) & 0x3F; + pos_o = dsp_o & 0x1F; + + if ((ccond_o != ccond_r) || (outflag_o != outflag_r) || (efi_o != efi_r) \ + || (c_o != c_r) || (scount_o != scount_r) || (pos_o != pos_r)) { + printf("rddsp wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/repl_ob.c b/tests/tcg/mips/mips64-dsp/repl_ob.c new file mode 100644 index 0000000000..20cb780136 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/repl_ob.c @@ -0,0 +1,21 @@ +#include "io.h" + +int main(void) +{ + long long rd, result; + rd = 0; + result = 0xFFFFFFFFFFFFFFFF; + + __asm + ("repl.ob %0, 0xFF\n\t" + : "=r"(rd) + ); + + if (result != rd) { + printf("repl.ob error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/repl_ph.c b/tests/tcg/mips/mips64-dsp/repl_ph.c new file mode 100644 index 0000000000..11d29bdbc2 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/repl_ph.c @@ -0,0 +1,30 @@ +#include "io.h" + +int main(void) +{ + long long rd, result; + + result = 0x01BF01BF; + __asm + ("repl.ph %0, 0x1BF\n\t" + : "=r"(rd) + ); + if (rd != result) { + printf("repl.ph wrong\n"); + + return -1; + } + + result = 0x01FF01FF; + __asm + ("repl.ph %0, 0x01FF\n\t" + : "=r"(rd) + ); + if (rd != result) { + printf("repl.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/repl_pw.c b/tests/tcg/mips/mips64-dsp/repl_pw.c new file mode 100644 index 0000000000..d35376a2a3 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/repl_pw.c @@ -0,0 +1,34 @@ +#include "io.h" + +int main(void) +{ + long long rd, result; + rd = 0; + result = 0x000001FF000001FF; + + __asm + ("repl.pw %0, 0x1FF\n\t" + : "=r"(rd) + ); + + if (result != rd) { + printf("repl.pw error1\n"); + + return -1; + } + + rd = 0; + result = 0xFFFFFE00FFFFFE00; + __asm + ("repl.pw %0, 0xFFFFFFFFFFFFFE00\n\t" + : "=r"(rd) + ); + + if (result != rd) { + printf("repl.pw error2\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/repl_qb.c b/tests/tcg/mips/mips64-dsp/repl_qb.c new file mode 100644 index 0000000000..592feaecb0 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/repl_qb.c @@ -0,0 +1,19 @@ +#include "io.h" + +int main(void) +{ + long long rd, result; + + result = 0xFFFFFFFFBFBFBFBF; + __asm + ("repl.qb %0, 0xBF\n\t" + : "=r"(rd) + ); + if (rd != result) { + printf("repl.qb wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/repl_qh.c b/tests/tcg/mips/mips64-dsp/repl_qh.c new file mode 100644 index 0000000000..82afc37167 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/repl_qh.c @@ -0,0 +1,34 @@ +#include "io.h" + +int main(void) +{ + long long rd, result; + rd = 0; + result = 0x01FF01FF01FF01FF; + + __asm + ("repl.qh %0, 0x1FF\n\t" + : "=r"(rd) + ); + + if (result != rd) { + printf("repl.qh error 1\n"); + + return -1; + } + + rd = 0; + result = 0xFE00FE00FE00FE00; + __asm + ("repl.qh %0, 0xFFFFFFFFFFFFFE00\n\t" + : "=r"(rd) + ); + + if (result != rd) { + printf("repl.qh error 2\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/replv_ob.c b/tests/tcg/mips/mips64-dsp/replv_ob.c new file mode 100644 index 0000000000..31ff3186d3 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/replv_ob.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result; + + rt = 0xFF; + result = 0xFFFFFFFFFFFFFFFF; + + __asm + ("replv.ob %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("replv.ob error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/replv_ph.c b/tests/tcg/mips/mips64-dsp/replv_ph.c new file mode 100644 index 0000000000..0af7a36b40 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/replv_ph.c @@ -0,0 +1,22 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x12345678; + result = 0x56785678; + __asm + ("replv.ph %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("replv.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/replv_pw.c b/tests/tcg/mips/mips64-dsp/replv_pw.c new file mode 100644 index 0000000000..e1789af4c8 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/replv_pw.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, result; + rd = 0; + rt = 0xFFFFFFFF; + result = 0xFFFFFFFFFFFFFFFF; + + __asm + ("replv.pw %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (result != rd) { + printf("replv.pw error\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/replv_qb.c b/tests/tcg/mips/mips64-dsp/replv_qb.c new file mode 100644 index 0000000000..d99298c31e --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/replv_qb.c @@ -0,0 +1,22 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x12345678; + result = 0x78787878; + __asm + ("replv.qb %0, %1\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("replv.qb wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shilo.c b/tests/tcg/mips/mips64-dsp/shilo.c new file mode 100644 index 0000000000..5f454f69e0 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shilo.c @@ -0,0 +1,29 @@ +#include "io.h" + +int main(void) +{ + long long ach, acl; + long long resulth, resultl; + + ach = 0xBBAACCFF; + acl = 0x1C3B001D; + + resulth = 0x17755; + resultl = 0xFFFFFFFF99fe3876; + + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "shilo $ac1, 0x0F\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + ); + if ((ach != resulth) || (acl != resultl)) { + printf("shilo wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shilov.c b/tests/tcg/mips/mips64-dsp/shilov.c new file mode 100644 index 0000000000..e82615a8c9 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shilov.c @@ -0,0 +1,31 @@ +#include "io.h" + +int main(void) +{ + long long rs, ach, acl; + long long resulth, resultl; + + rs = 0x0F; + ach = 0xBBAACCFF; + acl = 0x1C3B001D; + + resulth = 0x17755; + resultl = 0xFFFFFFFF99fe3876; + + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "shilov $ac1, %2\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs) + ); + if ((ach != resulth) || (acl != resultl)) { + printf("shilov wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shll_ob.c b/tests/tcg/mips/mips64-dsp/shll_ob.c new file mode 100644 index 0000000000..7dcb58ff46 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shll_ob.c @@ -0,0 +1,43 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, dsp; + long long res, resdsp; + + rt = 0x9ba8765433456789; + res = 0x9ba8765433456789; + resdsp = 0x0; + __asm + ("shll.ob %0, %2, 0x0\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + + dsp = (dsp >> 22) & 0x1; + + if ((dsp != resdsp) || (rd != res)) { + printf("shll.ob error\n"); + return -1; + } + + rt = 0x9ba8765433456789; + res = 0xd840b0a098283848; + resdsp = 0x1; + __asm + ("shll.ob %0, %2, 0x3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + + dsp = (dsp >> 22) & 0x1; + + if ((dsp != resdsp) || (rd != res)) { + printf("shll.ob error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shll_ph.c b/tests/tcg/mips/mips64-dsp/shll_ph.c new file mode 100644 index 0000000000..42b462d20d --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shll_ph.c @@ -0,0 +1,43 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, dsp; + long long result, resultdsp; + + rt = 0x12345678; + result = 0x12345678; + resultdsp = 0; + + __asm + ("shll.ph %0, %2, 0x0\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shll.ph wrong\n"); + + return -1; + } + + rt = 0x12345678; + result = 0xFFFFFFFFA000C000; + resultdsp = 1; + + __asm + ("shll.ph %0, %2, 0x0B\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shll.ph wrong1\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shll_pw.c b/tests/tcg/mips/mips64-dsp/shll_pw.c new file mode 100644 index 0000000000..d7878b2792 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shll_pw.c @@ -0,0 +1,43 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, dsp; + long long result, resultdsp; + + rt = 0x8765432112345678; + result = 0x8765432112345678; + resultdsp = 0; + + __asm + ("shll.pw %0, %2, 0x0\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shll.pw wrong\n"); + return -1; + } + + rt = 0x8765432112345678; + result = 0x6543210034567800; + resultdsp = 1; + + __asm + ("shll.pw %0, %2, 0x8\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shll.pw wrong\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shll_qb.c b/tests/tcg/mips/mips64-dsp/shll_qb.c new file mode 100644 index 0000000000..c21ab6698a --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shll_qb.c @@ -0,0 +1,26 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, dsp; + long long result, resultdsp; + + rt = 0x87654321; + result = 0x38281808; + resultdsp = 0x01; + + __asm + ("shll.qb %0, %2, 0x03\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + dsp = (dsp >> 22) & 0x01; + if (rd != result) { + printf("shll.qb wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shll_qh.c b/tests/tcg/mips/mips64-dsp/shll_qh.c new file mode 100644 index 0000000000..1380825a32 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shll_qh.c @@ -0,0 +1,42 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, dsp; + long long res, resdsp; + + rt = 0x9ba8765433456789; + res = 0x9ba8765433456789; + resdsp = 0x0; + __asm + ("shll.qh %0, %2, 0x0\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + dsp = (dsp >> 22) & 0x1; + + if ((dsp != resdsp) || (rd != res)) { + printf("shll.qh error\n"); + return -1; + } + + rt = 0x9ba8765433456789; + res = 0xdd40b2a09a283c48; + resdsp = 0x1; + __asm + ("shll.qh %0, %2, 0x3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + + dsp = (dsp >> 22) & 0x1; + + if ((dsp != resdsp) || (rd != res)) { + printf("shll.qh error1\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shll_s_ph.c b/tests/tcg/mips/mips64-dsp/shll_s_ph.c new file mode 100644 index 0000000000..1cf5d6da6e --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shll_s_ph.c @@ -0,0 +1,43 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, dsp; + long long result, resultdsp; + + rt = 0x12345678; + result = 0x12345678; + resultdsp = 0x0; + + __asm + ("shll_s.ph %0, %2, 0x0\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shll_s.ph wrong\n"); + + return -1; + } + + rt = 0x12345678; + result = 0x7FFF7FFF; + resultdsp = 0x01; + + __asm + ("shll_s.ph %0, %2, 0x0B\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shll_s.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shll_s_pw.c b/tests/tcg/mips/mips64-dsp/shll_s_pw.c new file mode 100644 index 0000000000..e38f6860c7 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shll_s_pw.c @@ -0,0 +1,43 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, dsp; + long long result, resultdsp; + + rt = 0x8765432112345678; + result = 0x8765432112345678; + resultdsp = 0; + + __asm + ("shll_s.pw %0, %2, 0x0\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shll_s.pw wrong\n"); + return -1; + } + + rt = 0x8765432112345678; + result = 0x800000007fffffff; + resultdsp = 1; + + __asm + ("shll_s.pw %0, %2, 0x8\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shll_s.pw wrong\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shll_s_qh.c b/tests/tcg/mips/mips64-dsp/shll_s_qh.c new file mode 100644 index 0000000000..f2f57fa27a --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shll_s_qh.c @@ -0,0 +1,43 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, dsp; + long long res, resdsp; + + rt = 0x9ba8765433456789; + res = 0x9ba8765433456789; + resdsp = 0x0; + __asm + ("shll_s.qh %0, %2, 0x0\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + + dsp = (dsp >> 22) & 0x1; + + if ((dsp != resdsp) || (rd != res)) { + printf("shll_s.qh error\n"); + return -1; + } + + rt = 0x9ba8765433456789; + res = 0x80007fff7fff7fff; + resdsp = 0x1; + __asm + ("shll_s.qh %0, %2, 0x3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + + dsp = (dsp >> 22) & 0x1; + + if ((dsp != resdsp) || (rd != res)) { + printf("shll_s.qh error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shll_s_w.c b/tests/tcg/mips/mips64-dsp/shll_s_w.c new file mode 100644 index 0000000000..57800615d2 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shll_s_w.c @@ -0,0 +1,26 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, dsp; + long long result, resultdsp; + + rt = 0x12345678; + result = 0x7FFFFFFF; + resultdsp = 0x01; + + __asm + ("shll_s.w %0, %2, 0x0B\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt) + ); + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shll_s.w wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shllv_ob.c b/tests/tcg/mips/mips64-dsp/shllv_ob.c new file mode 100644 index 0000000000..96a2e6f55f --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shllv_ob.c @@ -0,0 +1,45 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, rs, dsp; + long long result, resultdsp; + + rt = 0x8765432112345678; + rs = 0x0; + result = 0x8765432112345678; + resultdsp = 0; + + __asm + ("shllv.ob %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shllv.ob wrong\n"); + return -1; + } + + rt = 0x8765432112345678; + rs = 0x4; + result = 0x7050301020406080; + resultdsp = 1; + + __asm + ("shllv.ob %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shllv.ob wrong\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shllv_ph.c b/tests/tcg/mips/mips64-dsp/shllv_ph.c new file mode 100644 index 0000000000..532291f3fb --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shllv_ph.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x0B; + rt = 0x12345678; + result = 0xFFFFFFFFA000C000; + resultdsp = 1; + + __asm + ("shllv.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shllv.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shllv_pw.c b/tests/tcg/mips/mips64-dsp/shllv_pw.c new file mode 100644 index 0000000000..8d4ec295bd --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shllv_pw.c @@ -0,0 +1,45 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, rs, dsp; + long long result, resultdsp; + rt = 0x8765432112345678; + rs = 0x0; + result = 0x8765432112345678; + resultdsp = 0; + + __asm + ("shllv.pw %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shllv.pw wrong\n"); + return -1; + } + + + rt = 0x8765432112345678; + rs = 0x8; + result = 0x6543210034567800; + resultdsp = 1; + + __asm + ("shllv.pw %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shllv.pw wrong\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shllv_qb.c b/tests/tcg/mips/mips64-dsp/shllv_qb.c new file mode 100644 index 0000000000..e49356b8ec --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shllv_qb.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x03; + rt = 0x87654321; + result = 0x38281808; + resultdsp = 0x01; + + __asm + ("shllv.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + dsp = (dsp >> 22) & 0x01; + if (rd != result) { + printf("shllv.qb wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shllv_qh.c b/tests/tcg/mips/mips64-dsp/shllv_qh.c new file mode 100644 index 0000000000..0de4077e7d --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shllv_qh.c @@ -0,0 +1,45 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, rs, dsp; + long long result, resultdsp; + + rt = 0x8765432112345678; + rs = 0x0; + result = 0x8765432112345678; + resultdsp = 0; + + __asm + ("shllv.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shllv.qh wrong\n"); + return -1; + } + + rt = 0x8765432112345678; + rs = 0x4; + result = 0x7650321023406780; + resultdsp = 1; + + __asm + ("shllv.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shllv.qh wrong\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shllv_s_ph.c b/tests/tcg/mips/mips64-dsp/shllv_s_ph.c new file mode 100644 index 0000000000..7e69f941f4 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shllv_s_ph.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x0B; + rt = 0x12345678; + result = 0x7FFF7FFF; + resultdsp = 0x01; + + __asm + ("shllv_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shllv_s.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shllv_s_pw.c b/tests/tcg/mips/mips64-dsp/shllv_s_pw.c new file mode 100644 index 0000000000..f8dc8d2964 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shllv_s_pw.c @@ -0,0 +1,45 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, rs, dsp; + long long result, resultdsp; + + rt = 0x8765432112345678; + rs = 0x0; + result = 0x8765432112345678; + resultdsp = 0; + + __asm + ("shllv_s.pw %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shllv_s.pw wrong\n"); + return -1; + } + + rt = 0x8765432112345678; + rs = 0x8; + result = 0x800000007fffffff; + resultdsp = 1; + + __asm + ("shllv_s.pw %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shllv_s.pw wrong\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shllv_s_qh.c b/tests/tcg/mips/mips64-dsp/shllv_s_qh.c new file mode 100644 index 0000000000..db3832d091 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shllv_s_qh.c @@ -0,0 +1,45 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, rs, dsp; + long long result, resultdsp; + + rt = 0x8765432112345678; + rs = 0x0; + result = 0x8765432112345678; + resultdsp = 0; + + __asm + ("shllv_s.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shllv_s.qh wrong\n"); + return -1; + } + + rt = 0x8765432112345678; + rs = 0x4; + result = 0x80007fff7fff7fff; + resultdsp = 1; + + __asm + ("shllv_s.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shllv_s.qh wrong\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shllv_s_w.c b/tests/tcg/mips/mips64-dsp/shllv_s_w.c new file mode 100644 index 0000000000..5f6af8b8c0 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shllv_s_w.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x0B; + rt = 0x12345678; + result = 0x7FFFFFFF; + resultdsp = 0x01; + + __asm + ("shllv_s.w %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rt), "r"(rs) + ); + dsp = (dsp >> 22) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("shllv_s.w wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shra_ob.c b/tests/tcg/mips/mips64-dsp/shra_ob.c new file mode 100644 index 0000000000..d7fcfa816b --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shra_ob.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main() +{ + long long rd, rt; + long long res; + + rt = 0xbc98756abc654389; + res = 0xfbf9f7f6fb0604f8; + + __asm + ("shra.ob %0, %1, 0x4\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (rd != res) { + printf("shra.ob error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shra_ph.c b/tests/tcg/mips/mips64-dsp/shra_ph.c new file mode 100644 index 0000000000..a2dc014742 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shra_ph.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x87654321; + result = 0xFFFFFFFFF0EC0864; + + __asm + ("shra.ph %0, %1, 0x03\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("shra.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shra_pw.c b/tests/tcg/mips/mips64-dsp/shra_pw.c new file mode 100644 index 0000000000..33b1b8fe72 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shra_pw.c @@ -0,0 +1,36 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long res; + + rt = 0x1234567887654321; + res = 0x01234567f8765432; + + __asm + ("shra.pw %0, %1, 0x4" + : "=r"(rd) + : "r"(rt) + ); + + if (rd != res) { + printf("shra.pw error\n"); + return -1; + } + + rt = 0x1234567887654321; + res = 0x1234567887654321; + + __asm + ("shra.pw %0, %1, 0x0" + : "=r"(rd) + : "r"(rt) + ); + + if (rd != res) { + printf("shra.pw error\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shra_qh.c b/tests/tcg/mips/mips64-dsp/shra_qh.c new file mode 100644 index 0000000000..85dbfef3ea --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shra_qh.c @@ -0,0 +1,37 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long res; + + rt = 0x8512345654323454; + res = 0xf851034505430345; + + __asm + ("shra.qh %0, %1, 0x4\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (rd != res) { + printf("shra.qh error\n"); + return -1; + } + + rt = 0x8512345654323454; + res = 0x8512345654323454; + + __asm + ("shra.qh %0, %1, 0x0\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (rd != res) { + printf("shra.qh error1\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shra_r_ob.c b/tests/tcg/mips/mips64-dsp/shra_r_ob.c new file mode 100644 index 0000000000..184709443e --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shra_r_ob.c @@ -0,0 +1,22 @@ +#include "io.h" + +int main() +{ + long long rd, rt; + long long res; + + rt = 0xbc98756abc654389; + res = 0xfcfaf8f7fc0705f9; + + __asm + ("shra_r.ob %0, %1, 0x4\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (rd != res) { + printf("shra_r.ob error\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shra_r_ph.c b/tests/tcg/mips/mips64-dsp/shra_r_ph.c new file mode 100644 index 0000000000..e0943ad474 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shra_r_ph.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x87654321; + result = 0xFFFFFFFFF0ED0864; + + __asm + ("shra_r.ph %0, %1, 0x03\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("shra_r.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shra_r_pw.c b/tests/tcg/mips/mips64-dsp/shra_r_pw.c new file mode 100644 index 0000000000..6a86e684b8 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shra_r_pw.c @@ -0,0 +1,36 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long res; + + rt = 0x1234567887654321; + res = 0x01234568f8765432; + + __asm + ("shra_r.pw %0, %1, 0x4" + : "=r"(rd) + : "r"(rt) + ); + + if (rd != res) { + printf("shra_r.pw error\n"); + return -1; + } + + rt = 0x1234567887654321; + res = 0x1234567887654321; + + __asm + ("shra_r.pw %0, %1, 0x0" + : "=r"(rd) + : "r"(rt) + ); + + if (rd != res) { + printf("shra_r.pw error\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shra_r_qh.c b/tests/tcg/mips/mips64-dsp/shra_r_qh.c new file mode 100644 index 0000000000..d5c2110efe --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shra_r_qh.c @@ -0,0 +1,37 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long res; + + rt = 0x8512345654323454; + res = 0xf0a2068b0a86068b; + + __asm + ("shra_r.qh %0, %1, 0x3\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (rd != res) { + printf("shra_r.qh error\n"); + return -1; + } + + rt = 0x8512345654323454; + res = 0x8512345654323454; + + __asm + ("shra_r.qh %0, %1, 0x0\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (rd != res) { + printf("shra_r.qh error1\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shra_r_w.c b/tests/tcg/mips/mips64-dsp/shra_r_w.c new file mode 100644 index 0000000000..36d2c9c887 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shra_r_w.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x87654321; + result = 0xFFFFFFFFF0ECA864; + + __asm + ("shra_r.w %0, %1, 0x03\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("shra_r.w wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shrav_ph.c b/tests/tcg/mips/mips64-dsp/shrav_ph.c new file mode 100644 index 0000000000..1b4e983746 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shrav_ph.c @@ -0,0 +1,24 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x03; + rt = 0x87654321; + result = 0xFFFFFFFFF0EC0864; + + __asm + ("shrav.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + if (rd != result) { + printf("shrav.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shrav_pw.c b/tests/tcg/mips/mips64-dsp/shrav_pw.c new file mode 100644 index 0000000000..e19d515797 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shrav_pw.c @@ -0,0 +1,38 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, rs; + long long res; + + rt = 0x1234567887654321; + rs = 0x4; + res = 0x01234567f8765432; + + __asm + ("shrav.pw %0, %1, %2" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + + if (rd != res) { + printf("shrav.pw error\n"); + return -1; + } + + rt = 0x1234567887654321; + rs = 0x0; + res = 0x1234567887654321; + + __asm + ("shrav.pw %0, %1, %2" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + + if (rd != res) { + printf("shrav.pw error1\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shrav_qh.c b/tests/tcg/mips/mips64-dsp/shrav_qh.c new file mode 100644 index 0000000000..dc92e09d44 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shrav_qh.c @@ -0,0 +1,39 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, rs; + long long res; + + rt = 0x8512345654323454; + rs = 0x4; + res = 0xf851034505430345; + + __asm + ("shrav.qh %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + + if (rd != res) { + printf("shrav.qh error\n"); + return -1; + } + + rt = 0x8512345654323454; + rs = 0x0; + res = 0x8512345654323454; + + __asm + ("shrav.qh %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + + if (rd != res) { + printf("shrav.qh error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shrav_r_ph.c b/tests/tcg/mips/mips64-dsp/shrav_r_ph.c new file mode 100644 index 0000000000..350d5294fc --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shrav_r_ph.c @@ -0,0 +1,24 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x03; + rt = 0x87654321; + result = 0xFFFFFFFFF0ED0864; + + __asm + ("shrav_r.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + if (rd != result) { + printf("shrav_r.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shrav_r_pw.c b/tests/tcg/mips/mips64-dsp/shrav_r_pw.c new file mode 100644 index 0000000000..25b0545931 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shrav_r_pw.c @@ -0,0 +1,37 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, rs; + long long res; + + rt = 0x1234567887654321; + rs = 0x4; + res = 0x01234568f8765432; + + __asm + ("shrav_r.pw %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + + if (rd != res) { + printf("shrav_r.pw error\n"); + return -1; + } + + rt = 0x1234567887654321; + rs = 0x0; + res = 0x1234567887654321; + + __asm + ("shrav_r.pw %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + if (rd != res) { + printf("shrav_r.pw error\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shrav_r_qh.c b/tests/tcg/mips/mips64-dsp/shrav_r_qh.c new file mode 100644 index 0000000000..fd187a1e0b --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shrav_r_qh.c @@ -0,0 +1,39 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, rs; + long long res; + + rt = 0x8512345654323454; + rs = 0x3; + res = 0xf0a2068b0a86068b; + + __asm + ("shrav_r.qh %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + + if (rd != res) { + printf("shrav_r.qh error\n"); + return -1; + } + + rt = 0x400000000000000; + rs = 0x0; + res = 0x400000000000000; + + __asm + ("shrav_r.qh %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + + if (rd != res) { + printf("shrav_r.qh error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shrav_r_w.c b/tests/tcg/mips/mips64-dsp/shrav_r_w.c new file mode 100644 index 0000000000..3766c7255c --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shrav_r_w.c @@ -0,0 +1,24 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x03; + rt = 0x87654321; + result = 0xFFFFFFFFF0ECA864; + + __asm + ("shrav_r.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + if (rd != result) { + printf("shrav_r.w wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shrl_ob.c b/tests/tcg/mips/mips64-dsp/shrl_ob.c new file mode 100644 index 0000000000..a1145713a0 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shrl_ob.c @@ -0,0 +1,38 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long res; + + rt = 0xab76543212345678; + res = 0x150e0a0602060a0f; + + __asm + ("shrl.ob %0, %1, 0x3\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (rd != res) { + printf("shrl.ob error\n"); + return -1; + } + + rt = 0xab76543212345678; + res = 0xab76543212345678; + + __asm + ("shrl.ob %0, %1, 0x0\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (rd != res) { + printf("shrl.ob error\n"); + return -1; + } + + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shrl_qb.c b/tests/tcg/mips/mips64-dsp/shrl_qb.c new file mode 100644 index 0000000000..c0e36dba10 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shrl_qb.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x12345678; + result = 0x00010203; + + __asm + ("shrl.qb %0, %1, 0x05\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("shrl.qb wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shrl_qh.c b/tests/tcg/mips/mips64-dsp/shrl_qh.c new file mode 100644 index 0000000000..c1562463e0 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shrl_qh.c @@ -0,0 +1,22 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt; + long long res; + + rt = 0x8765679abc543786; + res = 0x087606790bc50378; + + __asm + ("shrl.qh %0, %1, 0x4\n\t" + : "=r"(rd) + : "r"(rt) + ); + + if (rd != res) { + printf("shrl.qh error\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shrlv_ob.c b/tests/tcg/mips/mips64-dsp/shrlv_ob.c new file mode 100644 index 0000000000..cb39c46716 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shrlv_ob.c @@ -0,0 +1,39 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, rs; + long long res; + + rt = 0xab76543212345678; + rs = 0x3; + res = 0x150e0a0602060a0f; + + __asm + ("shrlv.ob %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + + if (rd != res) { + printf("shrlv.ob error\n"); + return -1; + } + + rt = 0xab76543212345678; + rs = 0x0; + res = 0xab76543212345678; + + __asm + ("shrlv.ob %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + + if (rd != res) { + printf("shrlv.ob error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shrlv_qb.c b/tests/tcg/mips/mips64-dsp/shrlv_qb.c new file mode 100644 index 0000000000..5616aa9c5b --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shrlv_qb.c @@ -0,0 +1,24 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x05; + rt = 0x12345678; + result = 0x00010203; + + __asm + ("shrlv.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + if (rd != result) { + printf("shrlv.qb wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/shrlv_qh.c b/tests/tcg/mips/mips64-dsp/shrlv_qh.c new file mode 100644 index 0000000000..05de2fd6c8 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/shrlv_qh.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, rs; + long long res; + + rt = 0x8765679abc543786; + rs = 0x4; + res = 0x087606790bc50378; + + __asm + ("shrlv.qh %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + + if (rd != res) { + printf("shrlv.qh error\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/subq_ph.c b/tests/tcg/mips/mips64-dsp/subq_ph.c new file mode 100644 index 0000000000..6a1b18610c --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/subq_ph.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x12345678; + rt = 0x87654321; + result = 0xFFFFFFFF8ACF1357; + resultdsp = 0x01; + + __asm + ("subq.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("subq.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/subq_pw.c b/tests/tcg/mips/mips64-dsp/subq_pw.c new file mode 100644 index 0000000000..32f96ba4bd --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/subq_pw.c @@ -0,0 +1,44 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result, dspreg, dspresult; + rt = 0x123456789ABCDEF0; + rs = 0x123456789ABCDEF0; + result = 0x0; + dspresult = 0x0; + + __asm + ("subq.pw %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + dspreg = (dspreg >> 20) & 0x1; + if ((rd != result) || (dspreg != dspresult)) { + printf("subq.pw error1\n\t"); + + return -1; + } + + rt = 0x123456789ABCDEF1; + rs = 0x123456789ABCDEF2; + result = 0x0000000000000001; + dspresult = 0x0; + + __asm + ("subq.pw %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + dspreg = (dspreg >> 20) & 0x1; + if ((rd != result) || (dspreg != dspresult)) { + printf("subq.pw error2\n"); + + return -1; + } + + return 0; +} + diff --git a/tests/tcg/mips/mips64-dsp/subq_qh.c b/tests/tcg/mips/mips64-dsp/subq_qh.c new file mode 100644 index 0000000000..76d5f0a10a --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/subq_qh.c @@ -0,0 +1,26 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result, dspreg, dspresult; + rt = 0x123456789ABCDEF0; + rs = 0x123456789ABCDEF0; + result = 0x0; + dspresult = 0x0; + + __asm + ("subq.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + dspreg = (dspreg >> 20) & 0x1; + if ((rd != result) || (dspreg != dspresult)) { + printf("subq.qh error\n\t"); + + return -1; + } + + return 0; +} + diff --git a/tests/tcg/mips/mips64-dsp/subq_s_ph.c b/tests/tcg/mips/mips64-dsp/subq_s_ph.c new file mode 100644 index 0000000000..0b162f07ea --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/subq_s_ph.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x7FFF1357; + resultdsp = 0x01; + + __asm + ("subq_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("subq_s.ph wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/subq_s_pw.c b/tests/tcg/mips/mips64-dsp/subq_s_pw.c new file mode 100644 index 0000000000..e8e0b0567e --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/subq_s_pw.c @@ -0,0 +1,63 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result, dspreg, dspresult; + rt = 0x9FFFFFFD9FFFFFFD; + rs = 0x4000000080000000; + result = 0x7fffffffe0000003; + dspresult = 0x1; + + __asm + ("subq_s.pw %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + dspreg = (dspreg >> 20) & 0x1; + if ((rd != result) || (dspreg != dspresult)) { + printf("subq_s.pw error1\n"); + + return -1; + } + + rt = 0x123456789ABCDEF1; + rs = 0x123456789ABCDEF2; + result = 0x0000000000000001; + /* This time we do not set dspctrl, but it setted in pre-action. */ + dspresult = 0x1; + + __asm + ("subq_s.pw %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + dspreg = (dspreg >> 20) & 0x1; + if ((rd != result) || (dspreg != dspresult)) { + printf("subq_s.pw error2\n"); + + return -1; + } + + rt = 0x8000000080000000; + rs = 0x7000000070000000; + dspresult = 0x1; + + __asm + ("subq_s.pw %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = (dspreg >> 20) & 0x1; + if ((dspreg != dspresult)) { + printf("subq_s.pw error3\n"); + + return -1; + } + + return 0; +} + diff --git a/tests/tcg/mips/mips64-dsp/subq_s_qh.c b/tests/tcg/mips/mips64-dsp/subq_s_qh.c new file mode 100644 index 0000000000..4053b6b884 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/subq_s_qh.c @@ -0,0 +1,61 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result, dspreg, dspresult; + rs = 0x123456789ABCDEF0; + rt = 0x123456789ABCDEF0; + result = 0x0; + dspresult = 0x0; + + __asm + ("subq_s.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + dspreg = (dspreg >> 20) & 0x1; + if ((rd != result) || (dspreg != dspresult)) { + printf("subq_s.qh error1\n"); + + return -1; + } + + rs = 0x4000000080000000; + rt = 0x9FFD00009FFC0000; + result = 0x7FFF0000E0040000; + dspresult = 0x1; + + __asm + ("subq_s.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + dspreg = (dspreg >> 20) & 0x1; + if ((rd != result) || (dspreg != dspresult)) { + printf("subq_s.qh error2\n"); + + return -1; + } + + rs = 0x8000000000000000; + rt = 0x7000000000000000; + result = 0x8000000000000000; + dspresult = 0x1; + __asm + ("subq_s.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = (dspreg >> 20) & 0x1; + if ((rd != result) || (dspreg != dspresult)) { + printf("subq_s.qh error3\n"); + return -1; + } + + return 0; +} + diff --git a/tests/tcg/mips/mips64-dsp/subq_s_w.c b/tests/tcg/mips/mips64-dsp/subq_s_w.c new file mode 100644 index 0000000000..91d32da172 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/subq_s_w.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x7FFFFFFF; + resultdsp = 0x01; + + __asm + ("subq_s.w %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("subq_s.w wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/subu_ob.c b/tests/tcg/mips/mips64-dsp/subu_ob.c new file mode 100644 index 0000000000..f670967113 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/subu_ob.c @@ -0,0 +1,26 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result, dspreg, dspresult; + rs = 0x6F6F6F6F6F6F6F6F; + rt = 0x5E5E5E5E5E5E5E5E; + result = 0x1111111111111111; + dspresult = 0x0; + + __asm + ("subu.ob %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + if ((rd != result) || (dspreg != dspresult)) { + printf("subu.ob error\n"); + + return -1; + } + + return 0; +} + diff --git a/tests/tcg/mips/mips64-dsp/subu_qb.c b/tests/tcg/mips/mips64-dsp/subu_qb.c new file mode 100644 index 0000000000..9eb80df379 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/subu_qb.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x12345678; + rt = 0x87654321; + result = 0xFFFFFFFF8BCF1357; + resultdsp = 0x01; + + __asm + ("subu.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("subu.qb wrong\n"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/subu_s_ob.c b/tests/tcg/mips/mips64-dsp/subu_s_ob.c new file mode 100644 index 0000000000..5df64e5ff0 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/subu_s_ob.c @@ -0,0 +1,26 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dspreg, result, dspresult; + rs = 0x12345678ABCDEF0; + rt = 0x12345678ABCDEF1; + result = 0x00000000000; + dspresult = 0x01; + + __asm + ("subu_s.ob %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 20) & 0x01); + if ((rd != result) || (dspreg != dspresult)) { + printf("subu_s.ob error\n\t"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/subu_s_qb.c b/tests/tcg/mips/mips64-dsp/subu_s_qb.c new file mode 100644 index 0000000000..9de76f4a1f --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/subu_s_qb.c @@ -0,0 +1,27 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x00001357; + resultdsp = 0x01; + + __asm + ("subu_s.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + if ((dsp != resultdsp) || (rd != result)) { + printf("subu_s_qb wrong"); + + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dsp/wrdsp.c b/tests/tcg/mips/mips64-dsp/wrdsp.c new file mode 100644 index 0000000000..3033fd88d1 --- /dev/null +++ b/tests/tcg/mips/mips64-dsp/wrdsp.c @@ -0,0 +1,48 @@ +#include "io.h" + +int main(void) +{ + long long dsp_i, dsp_o; + long long ccond_i, outflag_i, efi_i, c_i, scount_i, pos_i; + long long ccond_o, outflag_o, efi_o, c_o, scount_o, pos_o; + long long ccond_r, outflag_r, efi_r, c_r, scount_r, pos_r; + + ccond_i = 0x000000BC;/* 4 */ + outflag_i = 0x0000001B;/* 3 */ + efi_i = 0x00000001;/* 5 */ + c_i = 0x00000001;/* 2 */ + scount_i = 0x0000000F;/* 1 */ + pos_i = 0x0000000C;/* 0 */ + + dsp_i = (ccond_i << 24) | (outflag_i << 16) | (efi_i << 14) | (c_i << 13) + | (scount_i << 7) | pos_i; + + ccond_r = ccond_i; + outflag_r = outflag_i; + efi_r = efi_i; + c_r = c_i; + scount_r = scount_i; + pos_r = pos_i; + + __asm + ("wrdsp %1, 0x3F\n\t" + "rddsp %0, 0x3F\n\t" + : "=r"(dsp_o) + : "r"(dsp_i) + ); + + ccond_o = (dsp_o >> 24) & 0xFF; + outflag_o = (dsp_o >> 16) & 0xFF; + efi_o = (dsp_o >> 14) & 0x01; + c_o = (dsp_o >> 14) & 0x01; + scount_o = (dsp_o >> 7) & 0x3F; + pos_o = dsp_o & 0x1F; + + if ((ccond_o != ccond_r) || (outflag_o != outflag_r) || (efi_o != efi_r) \ + || (c_o != c_r) || (scount_o != scount_r) || (pos_o != pos_r)) { + printf("wrddsp wrong\n"); + + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/.directory b/tests/tcg/mips/mips64-dspr2/.directory new file mode 100644 index 0000000000..c75a91451c --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/.directory @@ -0,0 +1,2 @@ +[Dolphin] +Timestamp=2012,8,3,16,41,52 diff --git a/tests/tcg/mips/mips64-dspr2/Makefile b/tests/tcg/mips/mips64-dspr2/Makefile new file mode 100644 index 0000000000..ba44bb9c0e --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/Makefile @@ -0,0 +1,116 @@ +CROSS_COMPILE ?= mips64el-unknown-linux-gnu- + +SIM = qemu-system-mips64el +SIMFLAGS = -nographic -cpu mips64dspr2 -kernel + +AS = $(CROSS_COMPILE)as +LD = $(CROSS_COMPILE)ld +CC = $(CROSS_COMPILE)gcc +AR = $(CROSS_COMPILE)ar +NM = $(CROSS_COMPILE)nm +STRIP = $(CROSS_COMPILE)strip +RANLIB = $(CROSS_COMPILE)ranlib +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump + +VECTORS_OBJ ?= ./head.o ./printf.o + +HEAD_FLAGS ?= -nostdinc -mabi=64 -G 0 -mno-abicalls -fno-pic -pipe \ + -msoft-float -march=mips64 -Wa,-mips64 -Wa,--trap \ + -msym32 -DKBUILD_64BIT_SYM32 -I./ + +CFLAGS ?= -nostdinc -mabi=64 -G 0 -mno-abicalls -fno-pic -fno-builtin \ + -pipe -march=mips64r2 -mgp64 -mdspr2 -static -Wa,--trap -msym32 \ + -DKBUILD_64BIT_SYM32 -I./ + +LDFLAGS = -T./mips_boot.lds -L./ +FLAGS = -nostdlib -mabi=64 -march=mips64r2 -mgp64 -mdspr2 + +TESTCASES = absq_s_qb.tst +TESTCASES += addqh_ph.tst +TESTCASES += addqh_r_ph.tst +TESTCASES += addqh_r_w.tst +TESTCASES += addqh_w.tst +#TESTCASES += adduh_ob.tst +TESTCASES += adduh_qb.tst +#TESTCASES += adduh_r_ob.tst +TESTCASES += adduh_r_qb.tst +TESTCASES += addu_ph.tst +#TESTCASES += addu_qh.tst +TESTCASES += addu_s_ph.tst +#TESTCASES += addu_s_qh.tst +TESTCASES += append.tst +TESTCASES += balign.tst +#TESTCASES += cmpgdu_eq_ob.tst +TESTCASES += cmpgdu_eq_qb.tst +#TESTCASES += cmpgdu_le_ob.tst +TESTCASES += cmpgdu_le_qb.tst +#TESTCASES += cmpgdu_lt_ob.tst +TESTCASES += cmpgdu_lt_qb.tst +#TESTCASES += dbalign.tst +TESTCASES += dpaqx_sa_w_ph.tst +TESTCASES += dpaqx_s_w_ph.tst +TESTCASES += dpa_w_ph.tst +#TESTCASES += dpa_w_qh.tst +TESTCASES += dpax_w_ph.tst +TESTCASES += dpsqx_sa_w_ph.tst +TESTCASES += dpsqx_s_w_ph.tst +TESTCASES += dps_w_ph.tst +#TESTCASES += dps_w_qh.tst +TESTCASES += dpsx_w_ph.tst +TESTCASES += mul_ph.tst +TESTCASES += mulq_rs_w.tst +TESTCASES += mulq_s_ph.tst +TESTCASES += mulq_s_w.tst +TESTCASES += mulsaq_s_w_ph.tst +TESTCASES += mulsa_w_ph.tst +TESTCASES += mul_s_ph.tst +TESTCASES += precr_qb_ph.tst +TESTCASES += precr_sra_ph_w.tst +TESTCASES += precr_sra_r_ph_w.tst +TESTCASES += prepend.tst +TESTCASES += shra_qb.tst +TESTCASES += shra_r_qb.tst +#TESTCASES += shrav_ob.tst +TESTCASES += shrav_qb.tst +#TESTCASES += shrav_r_ob.tst +TESTCASES += shrav_r_qb.tst +TESTCASES += shrl_ph.tst +TESTCASES += shrlv_ph.tst +TESTCASES += subqh_ph.tst +TESTCASES += subqh_r_ph.tst +TESTCASES += subqh_r_w.tst +TESTCASES += subqh_w.tst +#TESTCASES += subuh_ob.tst +TESTCASES += subuh_qb.tst +#TESTCASES += subuh_r_ob.tst +TESTCASES += subuh_r_qb.tst +TESTCASES += subu_ph.tst +#TESTCASES += subu_qh.tst +TESTCASES += subu_s_ph.tst +#TESTCASES += subu_s_qh.tst + +all: build + +head.o : head.S + $(Q)$(CC) $(HEAD_FLAGS) -D"STACK_TOP=0xffffffff80200000" -c $< -o $@ + +%.o : %.S + $(CC) $(CFLAGS) -c $< -o $@ + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +%.tst: %.o $(VECTORS_OBJ) + $(CC) $(VECTORS_OBJ) $(FLAGS) $(LDFLAGS) $< -o $@ + +build: $(VECTORS_OBJ) $(MIPSSOC_LIB) $(TESTCASES) + +check: $(VECTORS_OBJ) $(MIPSSOC_LIB) $(TESTCASES) + @for case in $(TESTCASES); do \ + echo $(SIM) $(SIMFLAGS) ./$$case; \ + $(SIM) $(SIMFLAGS) ./$$case & (sleep 1; killall $(SIM)); \ + done + +clean: + $(Q)rm -f *.o *.tst *.a diff --git a/tests/tcg/mips/mips64-dspr2/absq_s_qb.c b/tests/tcg/mips/mips64-dspr2/absq_s_qb.c new file mode 100644 index 0000000000..f7aec3e568 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/absq_s_qb.c @@ -0,0 +1,42 @@ +#include "io.h" +int main() +{ + long long input, result, dsp; + long long hope; + + input = 0x701BA35E; + hope = 0x701B5D5E; + + __asm + ("absq_s.qb %0, %1\n\t" + : "=r"(result) + : "r"(input) + ); + if (result != hope) { + printf("absq_s.qb error\n"); + return -1; + } + + input = 0x801BA35E; + hope = 0x7F1B5D5E; + + __asm + ("absq_s.qb %0, %2\n\t" + "rddsp %1\n\t" + : "=r"(result), "=r"(dsp) + : "r"(input) + ); + dsp = dsp >> 20; + dsp &= 0x01; + if (result != hope) { + printf("absq_s.qb error\n"); + return -1; + } + + if (dsp != 1) { + printf("absq_s.qb error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/addqh_ph.c b/tests/tcg/mips/mips64-dspr2/addqh_ph.c new file mode 100644 index 0000000000..6b43cb8d06 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/addqh_ph.c @@ -0,0 +1,35 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x706A13FE; + rt = 0x13065174; + result = 0x41B832B9; + __asm + ("addqh.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (result != rd) { + printf("addqh.ph error!\n"); + return -1; + } + + rs = 0x81000100; + rt = 0xc2000100; + result = 0xffffffffa1800100; + __asm + ("addqh.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (result != rd) { + printf("addqh.ph error!\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/addqh_r_ph.c b/tests/tcg/mips/mips64-dspr2/addqh_r_ph.c new file mode 100644 index 0000000000..890ec98d9b --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/addqh_r_ph.c @@ -0,0 +1,35 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x706A13FE; + rt = 0x13065174; + result = 0x41B832B9; + __asm + ("addqh_r.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("addqh_r.ph error\n"); + return -1; + } + + rs = 0x81010100; + rt = 0xc2000100; + result = 0xffffffffa1810100; + __asm + ("addqh_r.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("addqh_r.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/addqh_r_w.c b/tests/tcg/mips/mips64-dspr2/addqh_r_w.c new file mode 100644 index 0000000000..d324decbd3 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/addqh_r_w.c @@ -0,0 +1,38 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x00000010; + rt = 0x00000001; + result = 0x00000009; + + __asm + ("addqh_r.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("addqh_r.w error!\n"); + return -1; + } + rs = 0xFFFFFFFE; + rt = 0x00000001; + result = 0x00000000; + + __asm + ("addqh_r.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("addqh_r.w error!\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/addqh_w.c b/tests/tcg/mips/mips64-dspr2/addqh_w.c new file mode 100644 index 0000000000..78559e6784 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/addqh_w.c @@ -0,0 +1,39 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x00000010; + rt = 0x00000001; + result = 0x00000008; + + __asm + ("addqh.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("addqh.w wrong\n"); + return -1; + } + + rs = 0xFFFFFFFE; + rt = 0x00000001; + result = 0xFFFFFFFFFFFFFFFF; + + __asm + ("addqh.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("addqh.w wrong\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/addu_ph.c b/tests/tcg/mips/mips64-dspr2/addu_ph.c new file mode 100644 index 0000000000..d64c8cde8a --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/addu_ph.c @@ -0,0 +1,37 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long dsp; + long long result; + + rs = 0x00FF00FF; + rt = 0x00010001; + result = 0x01000100; + __asm + ("addu.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("1 addu.ph error\n"); + return -1; + } + + rs = 0xFFFF1111; + rt = 0x00020001; + result = 0x00011112; + __asm + ("addu.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + if ((rd != result) || (((dsp >> 20) & 0x01) != 1)) { + printf("2 addu.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/addu_qh.c b/tests/tcg/mips/mips64-dspr2/addu_qh.c new file mode 100644 index 0000000000..edcbf342ce --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/addu_qh.c @@ -0,0 +1,43 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dspreg; + long long result, dspresult; + + rs = 0x123456787FFF0000; + rt = 0x1111111180000000; + result = 0x23456789FFFF0000; + dspresult = 0x0; + + __asm("addu.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 20) & 0x01); + if ((rd != result) || (dspreg != dspresult)) { + printf("addu.qh error\n"); + return -1; + } + + rs = 0x123456787FFF0000; + rt = 0x1111111180020000; + result = 0x23456789FFFF0000; + dspresult = 0x01; + + __asm("addu.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 20) & 0x01); + if ((rd != result) || (dspreg != dspresult)) { + printf("addu.qh overflow error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/addu_s_ph.c b/tests/tcg/mips/mips64-dspr2/addu_s_ph.c new file mode 100644 index 0000000000..9250edb45c --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/addu_s_ph.c @@ -0,0 +1,37 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long dsp; + long long result; + + rs = 0x00FE00FE; + rt = 0x00020001; + result = 0x010000FF; + __asm + ("addu_s.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("addu_s.ph error\n"); + return -1; + } + + rs = 0xFFFF1111; + rt = 0x00020001; + result = 0xFFFFFFFFFFFF1112; + __asm + ("addu_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + if ((rd != result) || (((dsp >> 20) & 0x01) != 1)) { + printf("addu_s.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/addu_s_qh.c b/tests/tcg/mips/mips64-dspr2/addu_s_qh.c new file mode 100644 index 0000000000..b0c1626251 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/addu_s_qh.c @@ -0,0 +1,43 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dspreg; + long long result, dspresult; + + rs = 0x123456787FFF0000; + rt = 0x1111111180000000; + result = 0x23456789FFFF0000; + dspresult = 0x0; + + __asm("addu_s.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 20) & 0x01); + if ((rd != result) || (dspreg != dspresult)) { + printf("1 addu_s.qh error\n"); + return -1; + } + + rs = 0x12345678FFFF0000; + rt = 0x11111111000F0000; + result = 0x23456789FFFF0000; + dspresult = 0x01; + + __asm("addu_s.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 20) & 0x01); + if ((rd != result) || (dspreg != dspresult)) { + printf("2 addu_s.qh error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/adduh_ob.c b/tests/tcg/mips/mips64-dspr2/adduh_ob.c new file mode 100644 index 0000000000..9b309f6f16 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/adduh_ob.c @@ -0,0 +1,35 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result; + rs = 0xFF987CDEBCEF2356; + rt = 0xFF987CDEBCEF2354; + result = 0xFF987CDEBCEF2355; + + __asm("adduh.ob %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("adduh.ob error\n\t"); + return -1; + } + + rs = 0xac50691729945316; + rt = 0xb9234ca3f5573162; + result = 0xb2395a5d8f75423c; + + __asm("adduh.ob %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("adduh.ob error\n\t"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/adduh_qb.c b/tests/tcg/mips/mips64-dspr2/adduh_qb.c new file mode 100644 index 0000000000..796b409a86 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/adduh_qb.c @@ -0,0 +1,35 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0xFF0055AA; + rt = 0x0113421B; + result = 0xffffffff80094B62; + __asm + ("adduh.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("adduh.qb error\n"); + return -1; + } + rs = 0xFFFF0FFF; + rt = 0x00010111; + result = 0x7F800888; + + __asm + ("adduh.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("adduh.qb error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/adduh_r_ob.c b/tests/tcg/mips/mips64-dspr2/adduh_r_ob.c new file mode 100644 index 0000000000..832de833ef --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/adduh_r_ob.c @@ -0,0 +1,35 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result; + rs = 0xFF987CDEBCEF2356; + rt = 0xFF987CDEBCEF2355; + result = 0xFF987CDEBCEF2356; + + __asm("adduh_r.ob %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("1 adduh_r.ob error\n\t"); + return -1; + } + + rs = 0xac50691729945316; + rt = 0xb9234ca3f5573162; + result = 0xb33a5b5d8f76423c; + + __asm("adduh_r.ob %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("2 adduh_r.ob error\n\t"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/adduh_r_qb.c b/tests/tcg/mips/mips64-dspr2/adduh_r_qb.c new file mode 100644 index 0000000000..ae65fa5e18 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/adduh_r_qb.c @@ -0,0 +1,35 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0xFF0055AA; + rt = 0x01112211; + result = 0xffffffff80093C5E; + __asm + ("adduh_r.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("adduh_r.qb error\n"); + return -1; + } + + rs = 0xFFFF0FFF; + rt = 0x00010111; + result = 0xffffffff80800888; + __asm + ("adduh_r.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("adduh_r.qb error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/append.c b/tests/tcg/mips/mips64-dspr2/append.c new file mode 100644 index 0000000000..68a7cecc4b --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/append.c @@ -0,0 +1,35 @@ +#include"io.h" + +int main(void) +{ + long long rs, rt; + long long result; + + rs = 0xFF0055AA; + rt = 0x0113421B; + result = 0x02268436; + __asm + ("append %0, %1, 0x01\n\t" + : "+r"(rt) + : "r"(rs) + ); + if (rt != result) { + printf("append error\n"); + return -1; + } + + rs = 0xFFFF0FFF; + rt = 0x00010111; + result = 0x0010111F; + __asm + ("append %0, %1, 0x04\n\t" + : "+r"(rt) + : "r"(rs) + ); + if (rt != result) { + printf("append error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/balign.c b/tests/tcg/mips/mips64-dspr2/balign.c new file mode 100644 index 0000000000..7fbe815782 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/balign.c @@ -0,0 +1,35 @@ +#include"io.h" + +int main(void) +{ + long long rs, rt; + long long result; + + rs = 0xFF0055AA; + rt = 0x0113421B; + result = 0x13421BFF; + __asm + ("balign %0, %1, 0x01\n\t" + : "+r"(rt) + : "r"(rs) + ); + if (rt != result) { + printf("balign error\n"); + return -1; + } + + rs = 0xFFFF0FFF; + rt = 0x00010111; + result = 0x11FFFF0F; + __asm + ("balign %0, %1, 0x03\n\t" + : "+r"(rt) + : "r"(rs) + ); + if (rt != result) { + printf("balign error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_ob.c b/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_ob.c new file mode 100644 index 0000000000..61217f38cf --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_ob.c @@ -0,0 +1,44 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result, dspreg, dspresult; + + rs = 0x123456789ABCDEF0; + rt = 0x123456789ABCDEFF; + result = 0xFE; + dspresult = 0xFE; + + __asm("cmpgdu.eq.ob %0, %2, %3\n\t" + "rddsp %1" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0xFF); + + if ((rd != result) || (dspreg != dspresult)) { + printf("1 cmpgdu.eq.ob error\n"); + return -1; + } + + rs = 0x133256789ABCDEF0; + rt = 0x123456789ABCDEFF; + result = 0x3E; + dspresult = 0x3E; + + __asm("cmpgdu.eq.ob %0, %2, %3\n\t" + "rddsp %1" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0xFF); + + if ((rd != result) || (dspreg != dspresult)) { + printf("2 cmpgdu.eq.ob error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_qb.c b/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_qb.c new file mode 100644 index 0000000000..c63f6480eb --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_qb.c @@ -0,0 +1,41 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long dsp; + long long result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x02; + __asm + ("cmpgdu.eq.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + if ((rd != result) || (dsp != result)) { + printf("cmpgdu.eq.qb error\n"); + return -1; + } + + rs = 0x11777066; + rt = 0x11777066; + result = 0x0F; + __asm + ("cmpgdu.eq.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + + if ((rd != result) || (dsp != result)) { + printf("cmpgdu.eq.qb error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/cmpgdu_le_ob.c b/tests/tcg/mips/mips64-dspr2/cmpgdu_le_ob.c new file mode 100644 index 0000000000..b3da098189 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/cmpgdu_le_ob.c @@ -0,0 +1,44 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result, dspreg, dspresult; + + rs = 0x123456789abcdef0; + rt = 0x123456789abcdeff; + dspresult = 0xff; + result = 0xff; + + __asm("cmpgdu.le.ob %0, %2, %3\n\t" + "rddsp %1" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0xff); + + if ((rd != result) || (dspreg != dspresult)) { + printf("cmpgdu.le.ob error\n"); + return -1; + } + + rs = 0x113556789ABCDEF0; + rt = 0x123456789ABCDEFF; + result = 0xBE; + dspresult = 0xFE; + + __asm("cmpgdu.eq.ob %0, %2, %3\n\t" + "rddsp %1" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0xFF); + + if ((rd != result) || (dspreg != dspresult)) { + printf("cmpgdu.eq.ob error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/cmpgdu_le_qb.c b/tests/tcg/mips/mips64-dspr2/cmpgdu_le_qb.c new file mode 100644 index 0000000000..f0a60ea4e0 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/cmpgdu_le_qb.c @@ -0,0 +1,48 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long dsp; + long long result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x0F; + __asm + ("cmpgdu.le.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + if (rd != result) { + printf("cmpgdu.le.qb error\n"); + return -1; + } + if (dsp != result) { + printf("cmpgdu.le.qb error\n"); + return -1; + } + + rs = 0x11777066; + rt = 0x11707066; + result = 0x0B; + __asm + ("cmpgdu.le.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + if (rd != result) { + printf("cmpgdu.le.qb error\n"); + return -1; + } + if (dsp != result) { + printf("cmpgdu.le.qb error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_ob.c b/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_ob.c new file mode 100644 index 0000000000..d80b4e6ab9 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_ob.c @@ -0,0 +1,44 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result, dspreg, dspresult; + + rs = 0x123456789ABCDEF0; + rt = 0x123456789ABCDEFF; + dspresult = 0x01; + result = 0x01; + + __asm("cmpgdu.lt.ob %0, %2, %3\n\t" + "rddsp %1" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0xFF); + + if ((rd != result) || (dspreg != dspresult)) { + printf("cmpgdu.lt.ob error\n"); + return -1; + } + + rs = 0x143356789ABCDEF0; + rt = 0x123456789ABCDEFF; + dspresult = 0x41; + result = 0x41; + + __asm("cmpgdu.lt.ob %0, %2, %3\n\t" + "rddsp %1" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 24) & 0xFF); + + if ((rd != result) || (dspreg != dspresult)) { + printf("cmpgdu.lt.ob error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_qb.c b/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_qb.c new file mode 100644 index 0000000000..a71e4e307f --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_qb.c @@ -0,0 +1,48 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long dsp; + long long result; + + rs = 0x11777066; + rt = 0x55AA70FF; + result = 0x0D; + __asm + ("cmpgdu.lt.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + if (rd != result) { + printf("cmpgdu.lt.qb error\n"); + return -1; + } + if (dsp != result) { + printf("cmpgdu.lt.qb error\n"); + return -1; + } + + rs = 0x11777066; + rt = 0x11777066; + result = 0x00; + __asm + ("cmpgdu.lt.qb %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 24) & 0x0F; + if (rd != result) { + printf("cmpgdu.lt.qb error\n"); + return -1; + } + if (dsp != result) { + printf("cmpgdu.lt.qb error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/dbalign.c b/tests/tcg/mips/mips64-dspr2/dbalign.c new file mode 100644 index 0000000000..c7431b1857 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/dbalign.c @@ -0,0 +1,39 @@ +#include "io.h" + +int main(void) +{ + long long rt, rs; + long long res; + + rt = 0x1234567887654321; + rs = 0xabcd1234abcd1234; + + res = 0x34567887654321ab; + + asm ("dbalign %0, %1, 0x1\n" + : "=r"(rt) + : "r"(rs) + ); + + if (rt != res) { + printf("dbalign error\n"); + return -1; + } + + rt = 0x1234567887654321; + rs = 0xabcd1234abcd1234; + + res = 0x7887654321abcd12; + + asm ("dbalign %0, %1, 0x3\n" + : "=r"(rt) + : "r"(rs) + ); + + if (rt != res) { + printf("dbalign error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/dpa_w_ph.c b/tests/tcg/mips/mips64-dspr2/dpa_w_ph.c new file mode 100644 index 0000000000..39dc99aa55 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/dpa_w_ph.c @@ -0,0 +1,47 @@ +#include"io.h" + +int main(void) +{ + long long rs, rt; + long long ach = 5, acl = 5; + long long resulth, resultl; + + rs = 0x00FF00FF; + rt = 0x00010002; + resulth = 0x05; + resultl = 0x0302; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpa.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + if ((ach != resulth) || (acl != resultl)) { + printf("1 dpa.w.ph error\n"); + return -1; + } + + ach = 6, acl = 7; + rs = 0xFFFF00FF; + rt = 0xFFFF0002; + resulth = 0x05; + resultl = 0xfffffffffffe0206; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpa.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + if ((ach != resulth) || (acl != resultl)) { + printf("2 dpa.w.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/dpa_w_qh.c b/tests/tcg/mips/mips64-dspr2/dpa_w_qh.c new file mode 100644 index 0000000000..1411e44be3 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/dpa_w_qh.c @@ -0,0 +1,56 @@ +#include"io.h" +int main(void) +{ + long long rt, rs; + long long achi, acli; + long long acho, aclo; + long long resh, resl; + + achi = 0x1; + acli = 0x1; + + rs = 0x0001000100010001; + rt = 0x0002000200020002; + + resh = 0x1; + resl = 0x9; + + asm("mthi %2, $ac1\t\n" + "mtlo %3, $ac1\t\n" + "dpa.w.qh $ac1, %4, %5\t\n" + "mfhi %0, $ac1\t\n" + "mflo %1, $ac1\t\n" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((acho != resh) || (aclo != resl)) { + printf("1 dpa.w.qh error\n"); + return -1; + } + + + achi = 0xffffffff; + acli = 0xaaaaaaaa; + + rs = 0xaaaabbbbccccdddd; + rt = 0x7777888899996666; + + resh = 0xffffffffffffffff; + resl = 0x320cdf02; + + asm("mthi %2, $ac1\t\n" + "mtlo %3, $ac1\t\n" + "dpa.w.qh $ac1, %4, %5\t\n" + "mfhi %0, $ac1\t\n" + "mflo %1, $ac1\t\n" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + if ((acho != resh) || (aclo != resl)) { + printf("2 dpa.w.qh error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/dpaqx_s_w_ph.c b/tests/tcg/mips/mips64-dspr2/dpaqx_s_w_ph.c new file mode 100644 index 0000000000..51252fb980 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/dpaqx_s_w_ph.c @@ -0,0 +1,97 @@ +#include"io.h" + +int main(void) +{ + long long rs, rt, dsp; + long long ach = 5, acl = 5; + long long resulth, resultl, resultdsp; + + rs = 0x800000FF; + rt = 0x00018000; + resulth = 0x05; + resultl = 0xFFFFFFFF80000202; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpaqx_s.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + if (dsp != resultdsp) { + printf("dpaqx_s.w.ph error\n"); + return -1; + } + if (ach != resulth) { + printf("dpaqx_s.w.ph error\n"); + return -1; + } + if (acl != resultl) { + printf("dpaqx_s.w.ph error\n"); + return -1; + } + + ach = 5; + acl = 5; + rs = 0x00FF00FF; + rt = 0x00010002; + resulth = 0x05; + resultl = 0x05FF; + /*********************************************************** + * Because of we set outflag at last time, although this + * time we set nothing, but it is stay the last time value. + **********************************************************/ + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpaqx_s.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + if (dsp != resultdsp) { + printf("dpaqx_s.w.ph error\n"); + return -1; + } + if (ach != resulth) { + printf("dpaqx_s.w.ph error\n"); + return -1; + } + if (acl != resultl) { + printf("dpaqx_s.w.ph error\n"); + return -1; + } + + ach = 5; + acl = 5; + rs = 0x800000FF; + rt = 0x00028000; + resulth = 0x05; + resultl = 0xffffffff80000400; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpaqx_s.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + if ((dsp != resultdsp) || (ach != resulth) || (acl != resultl)) { + printf("dpaqx_s.w.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/dpaqx_sa_w_ph.c b/tests/tcg/mips/mips64-dspr2/dpaqx_sa_w_ph.c new file mode 100644 index 0000000000..18d6b3a98e --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/dpaqx_sa_w_ph.c @@ -0,0 +1,54 @@ +#include "io.h" + +int main() +{ + long long rs, rt, dsp; + long long ach = 5, acl = 5; + long long resulth, resultl, resultdsp; + + rs = 0x00FF00FF; + rt = 0x00010002; + resulth = 0x00; + resultl = 0x7FFFFFFF; + resultdsp = 0x01; + __asm + ("wrdsp %2\n\t" + "mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpaqx_sa.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "+r"(dsp) + : "r"(rs), "r"(rt) + ); + if ((dsp >> (16 + 1) != resultdsp) || (ach != resulth) || + (acl != resultl)) { + printf("dpaqx_sa.w.ph errror\n"); + } + + ach = 9; + acl = 0xb; + rs = 0x800000FF; + rt = 0x00018000; + resulth = 0x00; + resultl = 0x7fffffff; + resultdsp = 0x01; + __asm + ("wrdsp %2\n\t" + "mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpaqx_sa.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "+r"(dsp) + : "r"(rs), "r"(rt) + ); + if ((dsp >> (16 + 1) != resultdsp) || (ach != resulth) || + (acl != resultl)) { + printf("dpaqx_sa.w.ph errror\n"); + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/dpax_w_ph.c b/tests/tcg/mips/mips64-dspr2/dpax_w_ph.c new file mode 100644 index 0000000000..9d595fc14a --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/dpax_w_ph.c @@ -0,0 +1,32 @@ +#include"io.h" + +int main(void) +{ + long rs, rt; + long ach = 5, acl = 5; + long resulth, resultl; + + rs = 0x00FF00FF; + rt = 0x00010002; + resulth = 0x05; + resultl = 0x0302; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpax.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + if (ach != resulth) { + printf("dpax.w.ph error\n"); + return -1; + } + if (acl != resultl) { + printf("dpax.w.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/dps_w_ph.c b/tests/tcg/mips/mips64-dspr2/dps_w_ph.c new file mode 100644 index 0000000000..99f292ecb2 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/dps_w_ph.c @@ -0,0 +1,28 @@ +#include"io.h" + +int main(void) +{ + long long rs, rt; + long long ach = 5, acl = 5; + long long resulth, resultl; + + rs = 0x00FF00FF; + rt = 0x00010002; + resulth = 0x04; + resultl = 0xFFFFFFFFFFFFFFD08; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dps.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + if (ach != resulth || acl != resultl) { + printf("dps.w.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/dps_w_qh.c b/tests/tcg/mips/mips64-dspr2/dps_w_qh.c new file mode 100644 index 0000000000..61277eb30c --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/dps_w_qh.c @@ -0,0 +1,55 @@ +#include "io.h" + +int main(void) +{ + long long rs, rt; + long long achi, acli; + long long acho, aclo; + long long resh, resl; + + rs = 0x0000000100000001; + rt = 0x0000000200000002; + achi = 0x1; + acli = 0x8; + + resh = 0x1; + resl = 0x4; + + asm ("mthi %2, $ac1\t\n" + "mtlo %3, $ac1\t\n" + "dps.w.qh $ac1, %4, %5\t\n" + "mfhi %0, $ac1\t\n" + "mflo %1, $ac1\t\n" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((acho != resh) || (aclo != resl)) { + printf("1 dps.w.qh error\n"); + return -1; + } + + rs = 0xaaaabbbbccccdddd; + rt = 0xaaaabbbbccccdddd; + + achi = 0x88888888; + achi = 0x55555555; + + resh = 0xfffffffff7777777; + resl = 0x0a38b181; + + asm ("mthi %2, $ac1\t\n" + "mtlo %3, $ac1\t\n" + "dps.w.qh $ac1, %4, %5\t\n" + "mfhi %0, $ac1\t\n" + "mflo %1, $ac1\t\n" + : "=r"(acho), "=r"(aclo) + : "r"(achi), "r"(acli), "r"(rs), "r"(rt) + ); + + if ((acho != resh) || (aclo != resl)) { + printf("1 dps.w.qh error\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/dpsqx_s_w_ph.c b/tests/tcg/mips/mips64-dspr2/dpsqx_s_w_ph.c new file mode 100644 index 0000000000..ba46a92698 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/dpsqx_s_w_ph.c @@ -0,0 +1,55 @@ +#include"io.h" + +int main(void) +{ + long long rs, rt, dsp; + long long ach = 5, acl = 5; + long long resulth, resultl, resultdsp; + + rs = 0xBC0123AD; + rt = 0x01643721; + resulth = 0x04; + resultl = 0xFFFFFFFFAEA3E09B; + resultdsp = 0x00; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsqx_s.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + if (dsp != resultdsp || ach != resulth || acl != resultl) { + printf("dpsqx_s.w.ph error\n"); + return -1; + } + + ach = 0x99f13005; + acl = 0x51730062; + rs = 0x80008000; + rt = 0x80008000; + + resulth = 0xffffffff99f13004; + resultl = 0x51730064; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsqx_s.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + if (dsp != resultdsp || ach != resulth || acl != resultl) { + printf("dpsqx_s.w.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/dpsqx_sa_w_ph.c b/tests/tcg/mips/mips64-dspr2/dpsqx_sa_w_ph.c new file mode 100644 index 0000000000..24c888134d --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/dpsqx_sa_w_ph.c @@ -0,0 +1,53 @@ +#include"io.h" +int main() +{ + long long rs, rt, dsp; + long long ach = 5, acl = 5; + long long resulth, resultl, resultdsp; + + rs = 0xBC0123AD; + rt = 0x01643721; + resulth = 0x00; + resultl = 0x7FFFFFFF; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsqx_sa.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + if (dsp != resultdsp || ach != resulth || acl != resultl) { + printf("dpsqx_sa.w.ph error\n"); + return -1; + } + + ach = 0x8c0b354A; + acl = 0xbbc02249; + rs = 0x800023AD; + rt = 0x01648000; + resulth = 0xffffffffffffffff; + resultl = 0xffffffff80000000; + resultdsp = 0x01; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsqx_sa.w.ph $ac1, %3, %4\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + "rddsp %2\n\t" + : "+r"(ach), "+r"(acl), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 17) & 0x01; + if (dsp != resultdsp || ach != resulth || acl != resultl) { + printf("dpsqx_sa.w.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/dpsx_w_ph.c b/tests/tcg/mips/mips64-dspr2/dpsx_w_ph.c new file mode 100644 index 0000000000..b6291b5eb6 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/dpsx_w_ph.c @@ -0,0 +1,28 @@ +#include"io.h" + +int main(void) +{ + long long rs, rt; + long long ach = 5, acl = 5; + long long resulth, resultl; + + rs = 0xBC0123AD; + rt = 0x01643721; + resulth = 0x04; + resultl = 0xFFFFFFFFD751F050; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpsx.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + if (ach != resulth || acl != resultl) { + printf("dpsx.w.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/head.S b/tests/tcg/mips/mips64-dspr2/head.S new file mode 100644 index 0000000000..9a099ae42f --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/head.S @@ -0,0 +1,16 @@ +/* + * Startup Code for MIPS64 CPU-core + * + */ +.text +.globl _start +.align 4 +_start: + ori $2, $2, 0xffff + sll $2, $2, 16 + ori $2, $2, 0xffff + mtc0 $2, $12, 0 + jal main + +end: + b end diff --git a/tests/tcg/mips/mips64-dspr2/io.h b/tests/tcg/mips/mips64-dspr2/io.h new file mode 100644 index 0000000000..b7db61d7c1 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/io.h @@ -0,0 +1,22 @@ +#ifndef _ASM_IO_H +#define _ASM_IO_H +extern int printf(const char *fmt, ...); +extern unsigned long get_ticks(void); + +#define _read(source) \ +({ unsigned long __res; \ + __asm__ __volatile__( \ + "mfc0\t%0, " #source "\n\t" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __read(source) \ +({ unsigned long __res; \ + __asm__ __volatile__( \ + "move\t%0, " #source "\n\t" \ + : "=r" (__res)); \ + __res; \ +}) + +#endif diff --git a/tests/tcg/mips/mips64-dspr2/mips_boot.lds b/tests/tcg/mips/mips64-dspr2/mips_boot.lds new file mode 100644 index 0000000000..bd7c0c0f3f --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/mips_boot.lds @@ -0,0 +1,31 @@ +OUTPUT_ARCH(mips) +SECTIONS +{ + . = 0xffffffff80100000; + . = ALIGN((1 << 13)); + .text : + { + *(.text) + *(.rodata) + *(.rodata.*) + } + + __init_begin = .; + . = ALIGN((1 << 12)); + .init.text : AT(ADDR(.init.text) - 0) + { + *(.init.text) + } + .init.data : AT(ADDR(.init.data) - 0) + { + *(.init.data) + } + . = ALIGN((1 << 12)); + __init_end = .; + + . = ALIGN((1 << 13)); + .data : + { + *(.data) + } +} diff --git a/tests/tcg/mips/mips64-dspr2/mul_ph.c b/tests/tcg/mips/mips64-dspr2/mul_ph.c new file mode 100644 index 0000000000..5a3d05cb29 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/mul_ph.c @@ -0,0 +1,50 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x03FB1234; + rt = 0x0BCC4321; + result = 0xFFFFFFFFF504F4B4; + resultdsp = 1; + + __asm + ("mul.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + if (rd != result || dsp != resultdsp) { + printf("mul.ph wrong\n"); + return -1; + } + + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + rs = 0x00210010; + rt = 0x00110005; + result = 0x2310050; + resultdsp = 0; + + __asm + ("mul.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + if (rd != result || dsp != resultdsp) { + printf("mul.ph wrong\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/mul_s_ph.c b/tests/tcg/mips/mips64-dspr2/mul_s_ph.c new file mode 100644 index 0000000000..7c8b2c718f --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/mul_s_ph.c @@ -0,0 +1,67 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x03FB1234; + rt = 0x0BCC4321; + result = 0x7fff7FFF; + resultdsp = 1; + + __asm + ("mul_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + if (rd != result || dsp != resultdsp) { + printf("1 mul_s.ph error\n"); + return -1; + } + + rs = 0x7fffff00; + rt = 0xff007fff; + result = 0xffffffff80008000; + resultdsp = 1; + + __asm + ("mul_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + if (rd != result || dsp != resultdsp) { + printf("2 mul_s.ph error\n"); + return -1; + } + + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + rs = 0x00320001; + rt = 0x00210002; + result = 0x06720002; + resultdsp = 0; + + __asm + ("mul_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + if (rd != result || dsp != resultdsp) { + printf("3 mul_s.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/mulq_rs_w.c b/tests/tcg/mips/mips64-dspr2/mulq_rs_w.c new file mode 100644 index 0000000000..ffdc66d54a --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/mulq_rs_w.c @@ -0,0 +1,40 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x80001234; + rt = 0x80004321; + result = 0xFFFFFFFF80005555; + + __asm + ("mulq_rs.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("mulq_rs.w error!\n"); + return -1; + } + + rs = 0x80000000; + rt = 0x80000000; + result = 0x7FFFFFFF; + resultdsp = 1; + + __asm + ("mulq_rs.w %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + if (rd != result || dsp != resultdsp) { + printf("mulq_rs.w error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/mulq_s_ph.c b/tests/tcg/mips/mips64-dspr2/mulq_s_ph.c new file mode 100644 index 0000000000..b8c20c68cc --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/mulq_s_ph.c @@ -0,0 +1,26 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x80001234; + rt = 0x80004321; + result = 0x7FFF098B; + resultdsp = 1; + + __asm + ("mulq_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + if (rd != result || dsp != resultdsp) { + printf("mulq_s.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/mulq_s_w.c b/tests/tcg/mips/mips64-dspr2/mulq_s_w.c new file mode 100644 index 0000000000..db74b713f2 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/mulq_s_w.c @@ -0,0 +1,40 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x80001234; + rt = 0x80004321; + result = 0xFFFFFFFF80005555; + + __asm + ("mulq_s.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("mulq_s.w error\n"); + return -1; + } + + rs = 0x80000000; + rt = 0x80000000; + result = 0x7FFFFFFF; + resultdsp = 1; + + __asm + ("mulq_s.w %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 21) & 0x01; + if (rd != result || dsp != resultdsp) { + printf("mulq_s.w error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/mulsa_w_ph.c b/tests/tcg/mips/mips64-dspr2/mulsa_w_ph.c new file mode 100644 index 0000000000..5b22a60a8d --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/mulsa_w_ph.c @@ -0,0 +1,30 @@ +#include"io.h" + +int main(void) +{ + long long rs, rt, ach, acl; + long long resulth, resultl; + + ach = 0x05; + acl = 0x00BBDDCC; + rs = 0x80001234; + rt = 0x80004321; + resulth = 0x05; + resultl = 0x3BF5E918; + + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "mulsa.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + if (ach != resulth || acl != resultl) { + printf("mulsa.w.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/mulsaq_s_w_ph.c b/tests/tcg/mips/mips64-dspr2/mulsaq_s_w_ph.c new file mode 100644 index 0000000000..835a73d479 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/mulsaq_s_w_ph.c @@ -0,0 +1,30 @@ +#include"io.h" + +int main(void) +{ + long long rs, rt, ach, acl; + long long resulth, resultl; + + ach = 0x05; + acl = 0x00BBDDCC; + rs = 0x80001234; + rt = 0x80004321; + resulth = 0x05; + resultl = 0x772ff463; + + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "mulsaq_s.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + if (ach != resulth || acl != resultl) { + printf("mulsaq_s.w.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/precr_qb_ph.c b/tests/tcg/mips/mips64-dspr2/precr_qb_ph.c new file mode 100644 index 0000000000..80d5e8dce9 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/precr_qb_ph.c @@ -0,0 +1,23 @@ +#include"io.h" + +int main() +{ + long long rd, rs, rt; + long long result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x34786521; + + __asm + ("precr.qb.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (result != rd) { + printf("precr.qb.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/precr_sra_ph_w.c b/tests/tcg/mips/mips64-dspr2/precr_sra_ph_w.c new file mode 100644 index 0000000000..b1d7bcdf8e --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/precr_sra_ph_w.c @@ -0,0 +1,37 @@ +#include"io.h" + +int main(void) +{ + long long rs, rt; + long long result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x43215678; + + __asm + ("precr_sra.ph.w %0, %1, 0x00\n\t" + : "+r"(rt) + : "r"(rs) + ); + if (result != rt) { + printf("precr_sra.ph.w error\n"); + return -1; + } + + rs = 0x12345678; + rt = 0x87654321; + result = 0xFFFFFFFFFFFF0000; + + __asm + ("precr_sra.ph.w %0, %1, 0x1F\n\t" + : "+r"(rt) + : "r"(rs) + ); + if (result != rt) { + printf("precr_sra.ph.w error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/precr_sra_r_ph_w.c b/tests/tcg/mips/mips64-dspr2/precr_sra_r_ph_w.c new file mode 100644 index 0000000000..62d220dcae --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/precr_sra_r_ph_w.c @@ -0,0 +1,37 @@ +#include"io.h" + +int main(void) +{ + long long rs, rt; + long long result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x43215678; + + __asm + ("precr_sra_r.ph.w %0, %1, 0x00\n\t" + : "+r"(rt) + : "r"(rs) + ); + if (result != rt) { + printf("precr_sra_r.ph.w error\n"); + return -1; + } + + rs = 0x12345678; + rt = 0x87654321; + result = 0xFFFFFFFFFFFF0000; + + __asm + ("precr_sra_r.ph.w %0, %1, 0x1F\n\t" + : "+r"(rt) + : "r"(rs) + ); + if (result != rt) { + printf("precr_sra_r.ph.w error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/prepend.c b/tests/tcg/mips/mips64-dspr2/prepend.c new file mode 100644 index 0000000000..4ab083e969 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/prepend.c @@ -0,0 +1,35 @@ +#include"io.h" + +int main(void) +{ + long long rs, rt; + long long result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0xFFFFFFFF87654321; + __asm + ("prepend %0, %1, 0x00\n\t" + : "+r"(rt) + : "r"(rs) + ); + if (rt != result) { + printf("prepend error\n"); + return -1; + } + + rs = 0x12345678; + rt = 0x87654321; + result = 0xFFFFFFFFACF10ECA; + __asm + ("prepend %0, %1, 0x0F\n\t" + : "+r"(rt) + : "r"(rs) + ); + if (rt != result) { + printf("prepend error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/printf.c b/tests/tcg/mips/mips64-dspr2/printf.c new file mode 100644 index 0000000000..cf8676d390 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/printf.c @@ -0,0 +1,266 @@ + +typedef unsigned long va_list; + +#define ACC 4 +#define __read(source) \ +({ va_list __res; \ + __asm__ __volatile__( \ + "move\t%0, " #source "\n\t" \ + : "=r" (__res)); \ + __res; \ +}) + +enum format_type { + FORMAT_TYPE_NONE, + FORMAT_TYPE_HEX, + FORMAT_TYPE_ULONG, + FORMAT_TYPE_FLOAT +}; + +struct printf_spec { + char type; +}; + +static int format_decode(char *fmt, struct printf_spec *spec) +{ + char *start = fmt; + + for (; *fmt ; ++fmt) { + if (*fmt == '%') { + break; + } + } + + switch (*++fmt) { + case 'x': + spec->type = FORMAT_TYPE_HEX; + break; + + case 'd': + spec->type = FORMAT_TYPE_ULONG; + break; + + case 'f': + spec->type = FORMAT_TYPE_FLOAT; + break; + + default: + spec->type = FORMAT_TYPE_NONE; + } + + return ++fmt - start; +} + +void *memcpy(void *dest, void *src, int n) +{ + int i; + char *s = src; + char *d = dest; + + for (i = 0; i < n; i++) { + d[i] = s[i]; + } + return dest; +} + +char *number(char *buf, va_list num) +{ + int i; + char *str = buf; + static char digits[16] = "0123456789abcdef"; + str = str + sizeof(num) * 2; + + for (i = 0; i < sizeof(num) * 2; i++) { + *--str = digits[num & 15]; + num >>= 4; + } + + return buf + sizeof(num) * 2; +} + +char *__number(char *buf, va_list num) +{ + int i; + va_list mm = num; + char *str = buf; + + if (!num) { + *str++ = '0'; + return str; + } + + for (i = 0; mm; mm = mm/10, i++) { + /* Do nothing. */ + } + + str = str + i; + + while (num) { + *--str = num % 10 + 48; + num = num / 10; + } + + return str + i; +} + +va_list modf(va_list args, va_list *integer, va_list *num) +{ + int i; + double dot_v = 0; + va_list E, DOT, DOT_V; + + if (!args) { + return 0; + } + + for (i = 0, args = args << 1 >> 1; i < 52; i++) { + if ((args >> i) & 0x1) { + break; + } + } + + *integer = 0; + + if ((args >> 56 != 0x3f) || (args >> 52 == 0x3ff)) { + E = (args >> 52) - 1023; + DOT = 52 - E - i; + DOT_V = args << (12 + E) >> (12 + E) >> i; + *integer = ((args << 12 >> 12) >> (i + DOT)) | (1 << E); + } else { + E = ~((args >> 52) - 1023) + 1; + DOT_V = args << 12 >> 12; + + dot_v += 1.0 / (1 << E); + + for (i = 1; i <= 16; i++) { + if ((DOT_V >> (52 - i)) & 0x1) { + dot_v += 1.0 / (1 << E + i); + } + } + + for (i = 1, E = 0; i <= ACC; i++) { + dot_v *= 10; + if (!(va_list)dot_v) { + E++; + } + } + + *num = E; + + return dot_v; + } + + if (args & 0xf) { + for (i = 1; i <= 16; i++) { + if ((DOT_V >> (DOT - i)) & 0x1) { + dot_v += 1.0 / (1 << i); + } + } + + for (i = 1, E = 0; i <= ACC; i++) { + dot_v *= 10; + if (!(va_list)dot_v) { + E++; + } + } + + *num = E; + + return dot_v; + } else if (DOT) { + for (i = 1; i <= DOT; i++) { + if ((DOT_V >> (DOT - i)) & 0x1) { + dot_v += 1.0 / (1 << i); + } + } + + for (i = 1; i <= ACC; i++) { + dot_v = dot_v * 10; + } + + return dot_v; + } + + return 0; +} + +int vsnprintf(char *buf, int size, char *fmt, va_list args) +{ + char *str, *mm; + struct printf_spec spec = {0}; + + str = mm = buf; + + while (*fmt) { + char *old_fmt = fmt; + int read = format_decode(fmt, &spec); + + fmt += read; + + switch (spec.type) { + case FORMAT_TYPE_NONE: { + memcpy(str, old_fmt, read); + str += read; + break; + } + case FORMAT_TYPE_HEX: { + memcpy(str, old_fmt, read); + str = number(str + read, args); + for (; *mm ; ++mm) { + if (*mm == '%') { + *mm = '0'; + break; + } + } + break; + } + case FORMAT_TYPE_ULONG: { + memcpy(str, old_fmt, read - 2); + str = __number(str + read - 2, args); + break; + } + case FORMAT_TYPE_FLOAT: { + va_list integer, dot_v, num; + dot_v = modf(args, &integer, &num); + memcpy(str, old_fmt, read - 2); + str += read - 2; + if ((args >> 63 & 0x1)) { + *str++ = '-'; + } + str = __number(str, integer); + if (dot_v) { + *str++ = '.'; + while (num--) { + *str++ = '0'; + } + str = __number(str, dot_v); + } + break; + } + } + } + *str = '\0'; + + return str - buf; +} + +static void serial_out(char *str) +{ + while (*str) { + *(char *)0xffffffffb80003f8 = *str++; + } +} + +int vprintf(char *fmt, va_list args) +{ + int printed_len = 0; + static char printf_buf[512]; + printed_len = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args); + serial_out(printf_buf); + return printed_len; +} + +int printf(char *fmt, ...) +{ + return vprintf(fmt, __read($5)); +} diff --git a/tests/tcg/mips/mips64-dspr2/shra_qb.c b/tests/tcg/mips/mips64-dspr2/shra_qb.c new file mode 100644 index 0000000000..cac3102355 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/shra_qb.c @@ -0,0 +1,35 @@ +#include"io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x12345678; + result = 0x02060A0F; + + __asm + ("shra.qb %0, %1, 0x03\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("shra.qb error\n"); + return -1; + } + + rt = 0x87654321; + result = 0xFFFFFFFFF00C0804; + + __asm + ("shra.qb %0, %1, 0x03\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("shra.qb error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/shra_r_qb.c b/tests/tcg/mips/mips64-dspr2/shra_r_qb.c new file mode 100644 index 0000000000..9c64f75bd4 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/shra_r_qb.c @@ -0,0 +1,35 @@ +#include "io.h" + +int main() +{ + int rd, rt; + int result; + + rt = 0x12345678; + result = 0x02070B0F; + + __asm + ("shra_r.qb %0, %1, 0x03\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("shra_r.qb wrong\n"); + return -1; + } + + rt = 0x87654321; + result = 0xF10D0804; + + __asm + ("shra_r.qb %0, %1, 0x03\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("shra_r.qb wrong\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/shrav_ob.c b/tests/tcg/mips/mips64-dspr2/shrav_ob.c new file mode 100644 index 0000000000..fbdfbab35a --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/shrav_ob.c @@ -0,0 +1,22 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, rs; + long long res; + + rt = 0x1234567887654321; + rs = 0x4; + res = 0xf1f3f5f7f8060402; + + asm ("shrav.ob %0, %1, %2" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + + if (rd != res) { + printf("shra.ob error\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/shrav_qb.c b/tests/tcg/mips/mips64-dspr2/shrav_qb.c new file mode 100644 index 0000000000..a716203d80 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/shrav_qb.c @@ -0,0 +1,37 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x03; + rt = 0x12345678; + result = 0x02060A0F; + + __asm + ("shrav.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + if (rd != result) { + printf("shrav.qb error\n"); + return -1; + } + + rs = 0x03; + rt = 0x87654321; + result = 0xFFFFFFFFF00C0804; + + __asm + ("shrav.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + if (rd != result) { + printf("shrav.qb error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/shrav_r_ob.c b/tests/tcg/mips/mips64-dspr2/shrav_r_ob.c new file mode 100644 index 0000000000..b80100a7c2 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/shrav_r_ob.c @@ -0,0 +1,22 @@ +#include "io.h" + +int main(void) +{ + long long rd, rt, rs; + long long res; + + rt = 0x1234567887654321; + rs = 0x4; + res = 0xe3e7ebf0f1ede9e5; + + asm ("shrav_r.ob %0, %1, %2" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + + if (rd != res) { + printf("shra_r.ob error\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/shrav_r_qb.c b/tests/tcg/mips/mips64-dspr2/shrav_r_qb.c new file mode 100644 index 0000000000..009080b2a7 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/shrav_r_qb.c @@ -0,0 +1,37 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x03; + rt = 0x12345678; + result = 0x02070B0F; + + __asm + ("shrav_r.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + if (rd != result) { + printf("shrav_r.qb error\n"); + return -1; + } + + rs = 0x03; + rt = 0x87654321; + result = 0xFFFFFFFFF10D0804; + + __asm + ("shrav_r.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + if (rd != result) { + printf("shrav_r.qb error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/shrl_ph.c b/tests/tcg/mips/mips64-dspr2/shrl_ph.c new file mode 100644 index 0000000000..e32d976625 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/shrl_ph.c @@ -0,0 +1,22 @@ +#include"io.h" + +int main(void) +{ + long long rd, rt; + long long result; + + rt = 0x12345678; + result = 0x009102B3; + + __asm + ("shrl.ph %0, %1, 0x05\n\t" + : "=r"(rd) + : "r"(rt) + ); + if (rd != result) { + printf("shrl.ph error!\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/shrlv_ph.c b/tests/tcg/mips/mips64-dspr2/shrlv_ph.c new file mode 100644 index 0000000000..58c5488b58 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/shrlv_ph.c @@ -0,0 +1,23 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x05; + rt = 0x12345678; + result = 0x009102B3; + + __asm + ("shrlv.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rt), "r"(rs) + ); + if (rd != result) { + printf("shrlv.ph error!\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/subqh_ph.c b/tests/tcg/mips/mips64-dspr2/subqh_ph.c new file mode 100644 index 0000000000..90374019ae --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/subqh_ph.c @@ -0,0 +1,23 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x456709AB; + + __asm + ("subqh.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("subqh.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/subqh_r_ph.c b/tests/tcg/mips/mips64-dspr2/subqh_r_ph.c new file mode 100644 index 0000000000..b8f9d2fee6 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/subqh_r_ph.c @@ -0,0 +1,23 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x456809AC; + + __asm + ("subqh_r.ph %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("subqh_r.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/subqh_r_w.c b/tests/tcg/mips/mips64-dspr2/subqh_r_w.c new file mode 100644 index 0000000000..b025e40a35 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/subqh_r_w.c @@ -0,0 +1,23 @@ +#include"io.h" + +int main() +{ + long long rd, rs, rt; + long long result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x456789AC; + + __asm + ("subqh_r.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("subqh_r.w error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/subqh_w.c b/tests/tcg/mips/mips64-dspr2/subqh_w.c new file mode 100644 index 0000000000..65f17603d8 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/subqh_w.c @@ -0,0 +1,23 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0x456789AB; + + __asm + ("subqh.w %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("subqh.w error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/subu_ph.c b/tests/tcg/mips/mips64-dspr2/subu_ph.c new file mode 100644 index 0000000000..60a6b1b7da --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/subu_ph.c @@ -0,0 +1,26 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x87654321; + rt = 0x12345678; + result = 0x7531ECA9; + resultdsp = 0x01; + + __asm + ("subu.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + if (dsp != resultdsp || rd != result) { + printf("subu.ph error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/subu_qh.c b/tests/tcg/mips/mips64-dspr2/subu_qh.c new file mode 100644 index 0000000000..911cb349d4 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/subu_qh.c @@ -0,0 +1,24 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dspreg, result, dspresult; + rs = 0x123456789ABCDEF0; + rt = 0x123456789ABCDEF1; + result = 0x000000000000000F; + dspresult = 0x01; + + __asm("subu.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 20) & 0x01); + if ((rd != result) || (dspreg != dspresult)) { + printf("subu.qh error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/subu_s_ph.c b/tests/tcg/mips/mips64-dspr2/subu_s_ph.c new file mode 100644 index 0000000000..ae32cc06f5 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/subu_s_ph.c @@ -0,0 +1,25 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt, dsp; + long long result, resultdsp; + + rs = 0x87654321; + rt = 0x12345678; + result = 0x75310000; + resultdsp = 0x01; + + __asm + ("subu_s.ph %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dsp) + : "r"(rs), "r"(rt) + ); + dsp = (dsp >> 20) & 0x01; + if (dsp != resultdsp || rd != result) { + printf("subu_s.ph error\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/subu_s_qh.c b/tests/tcg/mips/mips64-dspr2/subu_s_qh.c new file mode 100644 index 0000000000..de7a29e775 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/subu_s_qh.c @@ -0,0 +1,42 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, dspreg, result, dspresult; + rs = 0x1111111111111111; + rt = 0x2222222222222222; + result = 0x1111111111111111; + dspresult = 0x00; + + __asm("subu_s.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 20) & 0x01); + if ((rd != result) || (dspreg != dspresult)) { + printf("subu_s.qh error\n\t"); + return -1; + } + + + rs = 0x8888888888888888; + rt = 0xa888a888a888a888; + result = 0x0000000000000000; + dspresult = 0x01; + + __asm("subu_s.qh %0, %2, %3\n\t" + "rddsp %1\n\t" + : "=r"(rd), "=r"(dspreg) + : "r"(rs), "r"(rt) + ); + + dspreg = ((dspreg >> 20) & 0x01); + if ((rd != result) || (dspreg != dspresult)) { + printf("subu_s.qh error\n\t"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/subuh_ob.c b/tests/tcg/mips/mips64-dspr2/subuh_ob.c new file mode 100644 index 0000000000..3fc452bf8e --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/subuh_ob.c @@ -0,0 +1,36 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result; + + rd = 0x0; + rs = 0x246856789ABCDEF0; + rt = 0x123456789ABCDEF0; + result = 0x091A000000000000; + + __asm("subuh.ob %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("subuh.ob error\n"); + return -1; + } + + rs = 0x246856789ABCDEF0; + rt = 0x1131517191B1D1F1; + result = 0x1b4f2d2d51637577; + + __asm("subuh.ob %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("subuh.ob error\n"); + return -1; + } + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/subuh_qb.c b/tests/tcg/mips/mips64-dspr2/subuh_qb.c new file mode 100644 index 0000000000..aac7a834ee --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/subuh_qb.c @@ -0,0 +1,23 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0xC5E7092B; + + __asm + ("subuh.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("subuh.qb wrong\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/subuh_r_ob.c b/tests/tcg/mips/mips64-dspr2/subuh_r_ob.c new file mode 100644 index 0000000000..fc20ffd09e --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/subuh_r_ob.c @@ -0,0 +1,23 @@ +#include "io.h" + +int main(void) +{ + long long rd, rs, rt, result; + + rd = 0x0; + rs = 0x246956789ABCDEF0; + rt = 0x123456789ABCDEF0; + result = 0x091B000000000000; + + __asm("subuh.ob %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + + if (rd != result) { + printf("subuh.ob error\n"); + return -1; + } + + return 0; +} diff --git a/tests/tcg/mips/mips64-dspr2/subuh_r_qb.c b/tests/tcg/mips/mips64-dspr2/subuh_r_qb.c new file mode 100644 index 0000000000..66d4680440 --- /dev/null +++ b/tests/tcg/mips/mips64-dspr2/subuh_r_qb.c @@ -0,0 +1,37 @@ +#include"io.h" + +int main(void) +{ + long long rd, rs, rt; + long long result; + + rs = 0x12345678; + rt = 0x87654321; + result = 0xC6E80A2C; + + __asm + ("subuh_r.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("1 subuh_r.qb wrong\n"); + return -1; + } + + rs = 0xBEFC292A; + rt = 0x9205C1B4; + result = 0x167cb4bb; + + __asm + ("subuh_r.qb %0, %1, %2\n\t" + : "=r"(rd) + : "r"(rs), "r"(rt) + ); + if (rd != result) { + printf("2 subuh_r.qb wrong\n"); + return -1; + } + + return 0; +} From b30706dda79894c01768df23cde526061d609258 Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Wed, 24 Oct 2012 22:17:14 +0800 Subject: [PATCH 1408/2270] target-mips: Change TODO file Change DSP r1 & DSP r2 into microMIPS DSP encodings in TODO file. Signed-off-by: Jia Liu Signed-off-by: Aurelien Jarno --- target-mips/TODO | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target-mips/TODO b/target-mips/TODO index 2a3546f624..1d782d8027 100644 --- a/target-mips/TODO +++ b/target-mips/TODO @@ -6,8 +6,7 @@ General - Unimplemented ASEs: - MDMX - SmartMIPS - - DSP r1 - - DSP r2 + - microMIPS DSP r1 & r2 encodings - MT ASE only partially implemented and not functional - Shadow register support only partially implemented, lacks set switching on interrupt/exception. From 40e3acc18f1c663ee8f0c981525316f864f7b8ea Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Wed, 31 Oct 2012 22:14:46 +0100 Subject: [PATCH 1409/2270] target-mips: remove #if defined(TARGET_MIPS64) in opcode enums All switch() decoding instruction have a default entry, so it is possible to have unused enum entries. Remove conditional definitions of MIPS64 opcode enums, as it only makes the code less readable. Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index fea4113092..6dc2b62844 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -318,46 +318,30 @@ enum { OPC_LX_DSP = 0x0A | OPC_SPECIAL3, /* MIPS DSP Arithmetic */ OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3, -#if defined(TARGET_MIPS64) OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3, -#endif OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3, -#if defined(TARGET_MIPS64) OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3, -#endif /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */ /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */ OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3, -#if defined(TARGET_MIPS64) OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3, -#endif /* MIPS DSP GPR-Based Shift Sub-class */ OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3, -#if defined(TARGET_MIPS64) OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3, -#endif /* MIPS DSP Multiply Sub-class insns */ /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */ /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */ OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3, -#if defined(TARGET_MIPS64) OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3, -#endif /* DSP Bit/Manipulation Sub-class */ OPC_INSV_DSP = 0x0C | OPC_SPECIAL3, -#if defined(TARGET_MIPS64) OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3, -#endif /* MIPS DSP Compare-Pick Sub-class */ OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3, -#if defined(TARGET_MIPS64) OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3, -#endif /* MIPS DSP Accumulator and DSPControl Access Sub-class */ OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3, -#if defined(TARGET_MIPS64) OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3, -#endif }; /* BSHFL opcodes */ @@ -380,9 +364,7 @@ enum { /* MIPS DSP REGIMM opcodes */ enum { OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM, -#if defined(TARGET_MIPS64) OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM, -#endif }; #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) @@ -391,9 +373,7 @@ enum { OPC_LBUX = (0x06 << 6) | OPC_LX_DSP, OPC_LHX = (0x04 << 6) | OPC_LX_DSP, OPC_LWX = (0x00 << 6) | OPC_LX_DSP, -#if defined(TARGET_MIPS64) OPC_LDX = (0x08 << 6) | OPC_LX_DSP, -#endif }; #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) @@ -591,9 +571,6 @@ enum { OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP, }; - - -#if defined(TARGET_MIPS64) #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { /* MIPS DSP Arithmetic Sub-class */ @@ -622,9 +599,7 @@ enum { OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP, OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP, }; -#endif -#if defined(TARGET_MIPS64) #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { /* MIPS DSP Multiply Sub-class insns */ @@ -656,9 +631,7 @@ enum { OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP, OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP, }; -#endif -#if defined(TARGET_MIPS64) #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { /* DSP Compare-Pick Sub-class */ @@ -691,9 +664,7 @@ enum { OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP, OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP, }; -#endif -#if defined(TARGET_MIPS64) #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { /* DSP Compare-Pick Sub-class */ @@ -702,9 +673,7 @@ enum { OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP, OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP, }; -#endif -#if defined(TARGET_MIPS64) #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { /* MIPS DSP Accumulator and DSPControl Access Sub-class */ @@ -736,9 +705,7 @@ enum { /* DSP Bit/Manipulation Sub-class */ OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP, }; -#endif -#if defined(TARGET_MIPS64) #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { /* MIPS DSP Multiply Sub-class insns */ @@ -769,9 +736,7 @@ enum { OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP, OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP, }; -#endif -#if defined(TARGET_MIPS64) #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) enum { /* MIPS DSP GPR-Based Shift Sub-class */ @@ -802,7 +767,6 @@ enum { OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP, OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP, }; -#endif /* Coprocessor 0 (rs field) */ #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) From ac4119c023c72b15f54238af43e4a178fcf41494 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 12 Oct 2012 09:52:49 +0200 Subject: [PATCH 1410/2270] chardev: Use timer instead of bottom-half to postpone open event As the block layer may decide to flush bottom-halfs while the machine is still initializing (e.g. to read geometry data from the disk), our postponed open event may be processed before the last frontend registered with a muxed chardev. Until the semantics of BHs have been clarified, use an expired timer to achieve the same effect (suggested by Paolo Bonzini). This requires to perform the alarm timer initialization earlier as otherwise timer subsystem can be used before being ready. Signed-off-by: Jan Kiszka --- qemu-char.c | 13 +++++++------ qemu-char.h | 2 +- vl.c | 10 +++++----- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index afe2bfb4dd..88f40254b7 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -123,19 +123,20 @@ void qemu_chr_be_event(CharDriverState *s, int event) s->chr_event(s->handler_opaque, event); } -static void qemu_chr_generic_open_bh(void *opaque) +static void qemu_chr_fire_open_event(void *opaque) { CharDriverState *s = opaque; qemu_chr_be_event(s, CHR_EVENT_OPENED); - qemu_bh_delete(s->bh); - s->bh = NULL; + qemu_free_timer(s->open_timer); + s->open_timer = NULL; } void qemu_chr_generic_open(CharDriverState *s) { - if (s->bh == NULL) { - s->bh = qemu_bh_new(qemu_chr_generic_open_bh, s); - qemu_bh_schedule(s->bh); + if (s->open_timer == NULL) { + s->open_timer = qemu_new_timer_ms(vm_clock, + qemu_chr_fire_open_event, s); + qemu_mod_timer(s->open_timer, qemu_get_clock_ms(vm_clock) - 1); } } diff --git a/qemu-char.h b/qemu-char.h index 486644b3bd..297dd98342 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -69,7 +69,7 @@ struct CharDriverState { void (*chr_guest_open)(struct CharDriverState *chr); void (*chr_guest_close)(struct CharDriverState *chr); void *opaque; - QEMUBH *bh; + QEMUTimer *open_timer; char *label; char *filename; int opened; diff --git a/vl.c b/vl.c index 5a3d316980..5513d1518e 100644 --- a/vl.c +++ b/vl.c @@ -3551,6 +3551,11 @@ int main(int argc, char **argv, char **envp) add_device_config(DEV_VIRTCON, "vc:80Cx24C"); } + if (init_timer_alarm() < 0) { + fprintf(stderr, "could not initialize alarm timer\n"); + exit(1); + } + socket_init(); if (qemu_opts_foreach(qemu_find_opts("chardev"), chardev_init_func, NULL, 1) != 0) @@ -3618,11 +3623,6 @@ int main(int argc, char **argv, char **envp) os_set_line_buffering(); - if (init_timer_alarm() < 0) { - fprintf(stderr, "could not initialize alarm timer\n"); - exit(1); - } - #ifdef CONFIG_SPICE /* spice needs the timers to be initialized by this point */ qemu_spice_init(); From e1e1b25c97632cf68d6a11e20f8068282e3d7915 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 31 Oct 2012 10:30:55 +1100 Subject: [PATCH 1411/2270] target-alpha: Use TCG_CALL_NO_WG Mark helper functions that raise exceptions, but otherwise do not change TCG register state, with TCG_CALL_NO_WG. Signed-off-by: Richard Henderson --- target-alpha/helper.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/target-alpha/helper.h b/target-alpha/helper.h index 162816fa73..dd55f89aad 100644 --- a/target-alpha/helper.h +++ b/target-alpha/helper.h @@ -3,12 +3,12 @@ DEF_HELPER_3(excp, noreturn, env, int, int) DEF_HELPER_FLAGS_1(load_pcc, TCG_CALL_NO_RWG_SE, i64, env) -DEF_HELPER_3(addqv, i64, env, i64, i64) -DEF_HELPER_3(addlv, i64, env, i64, i64) -DEF_HELPER_3(subqv, i64, env, i64, i64) -DEF_HELPER_3(sublv, i64, env, i64, i64) -DEF_HELPER_3(mullv, i64, env, i64, i64) -DEF_HELPER_3(mulqv, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(addqv, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(addlv, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(subqv, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(sublv, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(mullv, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(mulqv, TCG_CALL_NO_WG, i64, env, i64, i64) DEF_HELPER_FLAGS_2(umulh, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_1(ctpop, TCG_CALL_NO_RWG_SE, i64, i64) @@ -92,11 +92,11 @@ DEF_HELPER_FLAGS_2(setroundmode, TCG_CALL_NO_RWG, void, env, i32) DEF_HELPER_FLAGS_2(setflushzero, TCG_CALL_NO_RWG, void, env, i32) DEF_HELPER_FLAGS_1(fp_exc_clear, TCG_CALL_NO_RWG, void, env) DEF_HELPER_FLAGS_1(fp_exc_get, TCG_CALL_NO_RWG_SE, i32, env) -DEF_HELPER_3(fp_exc_raise, void, env, i32, i32) -DEF_HELPER_3(fp_exc_raise_s, void, env, i32, i32) +DEF_HELPER_FLAGS_3(fp_exc_raise, TCG_CALL_NO_WG, void, env, i32, i32) +DEF_HELPER_FLAGS_3(fp_exc_raise_s, TCG_CALL_NO_WG, void, env, i32, i32) -DEF_HELPER_2(ieee_input, void, env, i64) -DEF_HELPER_2(ieee_input_cmp, void, env, i64) +DEF_HELPER_FLAGS_2(ieee_input, TCG_CALL_NO_WG, void, env, i64) +DEF_HELPER_FLAGS_2(ieee_input_cmp, TCG_CALL_NO_WG, void, env, i64) #if !defined (CONFIG_USER_ONLY) DEF_HELPER_2(hw_ret, void, env, i64) From b3a1be87bac3a6aaa59bb88c1410f170dc9b22d5 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Wed, 31 Oct 2012 00:50:15 +0100 Subject: [PATCH 1412/2270] tcg: don't remove op if output needs to be synced to memory Commit 9c43b68de628a1e2cba556adfb71c17028eb802e do not correctly check for dead outputs when they need to be synced to memory in case of half-dead operations. Fix that by applying the same pattern than for the default case. Tested-by: Stefan Weil Signed-off-by: Aurelien Jarno --- tcg/tcg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index c3a7f19bd7..11334387a0 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1329,8 +1329,8 @@ static void tcg_liveness_analysis(TCGContext *s) the low part. The result can be optimized to a simple add or sub. This happens often for x86_64 guest when the cpu mode is set to 32 bit. */ - if (dead_temps[args[1]]) { - if (dead_temps[args[0]]) { + if (dead_temps[args[1]] && !mem_temps[1]) { + if (dead_temps[args[0]] && !mem_temps[0]) { goto do_remove; } /* Create the single operation plus nop. */ @@ -1355,8 +1355,8 @@ static void tcg_liveness_analysis(TCGContext *s) nb_iargs = 2; nb_oargs = 2; /* Likewise, test for the high part of the operation dead. */ - if (dead_temps[args[1]]) { - if (dead_temps[args[0]]) { + if (dead_temps[args[1]] && !mem_temps[1]) { + if (dead_temps[args[0]] && !mem_temps[0]) { goto do_remove; } gen_opc_buf[op_index] = op = INDEX_op_mul_i32; From 4636401d99c113c67229ceabe93666767a619a25 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 28 Oct 2012 15:42:55 +0100 Subject: [PATCH 1413/2270] target-mips: correctly restore btarget upon exception When the CPU state is restored through retranslation after an exception, btarget should also be restored. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/target-mips/translate.c b/target-mips/translate.c index 6dc2b62844..bf2cb0ba7c 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1015,6 +1015,7 @@ static TCGv_i32 fpu_fcr0, fpu_fcr31; static TCGv_i64 fpu_f64[32]; static uint32_t gen_opc_hflags[OPC_BUF_SIZE]; +static target_ulong gen_opc_btarget[OPC_BUF_SIZE]; #include "gen-icount.h" @@ -15581,6 +15582,7 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb, } gen_opc_pc[lj] = ctx.pc; gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK; + gen_opc_btarget[lj] = ctx.btarget; gen_opc_instr_start[lj] = 1; gen_opc_icount[lj] = num_insns; } @@ -16001,4 +16003,13 @@ void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos) env->active_tc.PC = gen_opc_pc[pc_pos]; env->hflags &= ~MIPS_HFLAG_BMASK; env->hflags |= gen_opc_hflags[pc_pos]; + switch (env->hflags & MIPS_HFLAG_BMASK_BASE) { + case MIPS_HFLAG_BR: + break; + case MIPS_HFLAG_BC: + case MIPS_HFLAG_BL: + case MIPS_HFLAG_B: + env->btarget = gen_opc_btarget[pc_pos]; + break; + } } From 1e0e239a89b5a5ffe475a8efce5e59383a88af44 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 28 Oct 2012 15:55:47 +0100 Subject: [PATCH 1414/2270] target-mips: do not save CPU state when using retranslation When the CPU state after a possible retranslation is going to be handled through code retranslation, we don't need to save the CPU state before. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index bf2cb0ba7c..a84ed6e547 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1626,13 +1626,11 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, switch (opc) { #if defined(TARGET_MIPS64) case OPC_LWU: - save_cpu_state(ctx, 0); op_ld_lwu(t0, t0, ctx); gen_store_gpr(t0, rt); opn = "lwu"; break; case OPC_LD: - save_cpu_state(ctx, 0); op_ld_ld(t0, t0, ctx); gen_store_gpr(t0, rt); opn = "ld"; @@ -1658,7 +1656,6 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, opn = "ldr"; break; case OPC_LDPC: - save_cpu_state(ctx, 0); tcg_gen_movi_tl(t1, pc_relative_pc(ctx)); gen_op_addr_add(ctx, t0, t0, t1); op_ld_ld(t0, t0, ctx); @@ -1667,7 +1664,6 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, break; #endif case OPC_LWPC: - save_cpu_state(ctx, 0); tcg_gen_movi_tl(t1, pc_relative_pc(ctx)); gen_op_addr_add(ctx, t0, t0, t1); op_ld_lw(t0, t0, ctx); @@ -1675,31 +1671,26 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, opn = "lwpc"; break; case OPC_LW: - save_cpu_state(ctx, 0); op_ld_lw(t0, t0, ctx); gen_store_gpr(t0, rt); opn = "lw"; break; case OPC_LH: - save_cpu_state(ctx, 0); op_ld_lh(t0, t0, ctx); gen_store_gpr(t0, rt); opn = "lh"; break; case OPC_LHU: - save_cpu_state(ctx, 0); op_ld_lhu(t0, t0, ctx); gen_store_gpr(t0, rt); opn = "lhu"; break; case OPC_LB: - save_cpu_state(ctx, 0); op_ld_lb(t0, t0, ctx); gen_store_gpr(t0, rt); opn = "lb"; break; case OPC_LBU: - save_cpu_state(ctx, 0); op_ld_lbu(t0, t0, ctx); gen_store_gpr(t0, rt); opn = "lbu"; @@ -1744,7 +1735,6 @@ static void gen_st (DisasContext *ctx, uint32_t opc, int rt, switch (opc) { #if defined(TARGET_MIPS64) case OPC_SD: - save_cpu_state(ctx, 0); op_st_sd(t1, t0, ctx); opn = "sd"; break; @@ -1760,17 +1750,14 @@ static void gen_st (DisasContext *ctx, uint32_t opc, int rt, break; #endif case OPC_SW: - save_cpu_state(ctx, 0); op_st_sw(t1, t0, ctx); opn = "sw"; break; case OPC_SH: - save_cpu_state(ctx, 0); op_st_sh(t1, t0, ctx); opn = "sh"; break; case OPC_SB: - save_cpu_state(ctx, 0); op_st_sb(t1, t0, ctx); opn = "sb"; break; @@ -8691,7 +8678,6 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, } /* Don't do NOP if destination is zero: we must perform the actual memory access. */ - save_cpu_state(ctx, 0); switch (opc) { case OPC_LWXC1: check_cop1x(ctx); @@ -10964,7 +10950,6 @@ static void gen_ldxs (DisasContext *ctx, int base, int index, int rd) gen_op_addr_add(ctx, t0, t1, t0); } - save_cpu_state(ctx, 0); op_ld_lw(t1, t0, ctx); gen_store_gpr(t1, rd); @@ -10994,7 +10979,6 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, generate_exception(ctx, EXCP_RI); return; } - save_cpu_state(ctx, 0); op_ld_lw(t1, t0, ctx); gen_store_gpr(t1, rd); tcg_gen_movi_tl(t1, 4); @@ -11004,7 +10988,6 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, opn = "lwp"; break; case SWP: - save_cpu_state(ctx, 0); gen_load_gpr(t1, rd); op_st_sw(t1, t0, ctx); tcg_gen_movi_tl(t1, 4); @@ -11019,7 +11002,6 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, generate_exception(ctx, EXCP_RI); return; } - save_cpu_state(ctx, 0); op_ld_ld(t1, t0, ctx); gen_store_gpr(t1, rd); tcg_gen_movi_tl(t1, 8); @@ -11029,7 +11011,6 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, opn = "ldp"; break; case SDP: - save_cpu_state(ctx, 0); gen_load_gpr(t1, rd); op_st_sd(t1, t0, ctx); tcg_gen_movi_tl(t1, 8); @@ -12671,7 +12652,6 @@ static void gen_mipsdsp_ld(CPUMIPSState *env, DisasContext *ctx, uint32_t opc, gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]); } - save_cpu_state(ctx, 0); switch (opc) { case OPC_LBUX: op_ld_lbu(t0, t0, ctx); From bbc1dedef6530917e34a94a2641932e636f9b02d Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:20 +0200 Subject: [PATCH 1415/2270] softfloat: implement fused multiply-add NaN propagation for MIPS Add a pickNaNMulAdd function for MIPS, implementing NaN propagation rules for MIPS fused multiply-add instructions. Cc: Peter Maydell Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- fpu/softfloat-specialize.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h index a1d489e425..518f694a68 100644 --- a/fpu/softfloat-specialize.h +++ b/fpu/softfloat-specialize.h @@ -486,6 +486,33 @@ static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, return 1; } } +#elif defined(TARGET_MIPS) +static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, + flag cIsQNaN, flag cIsSNaN, flag infzero STATUS_PARAM) +{ + /* For MIPS, the (inf,zero,qnan) case sets InvalidOp and returns + * the default NaN + */ + if (infzero) { + float_raise(float_flag_invalid STATUS_VAR); + return 3; + } + + /* Prefer sNaN over qNaN, in the a, b, c order. */ + if (aIsSNaN) { + return 0; + } else if (bIsSNaN) { + return 1; + } else if (cIsSNaN) { + return 2; + } else if (aIsQNaN) { + return 0; + } else if (bIsQNaN) { + return 1; + } else { + return 2; + } +} #elif defined(TARGET_PPC) static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, flag cIsQNaN, flag cIsSNaN, flag infzero STATUS_PARAM) From b3d6cd447d594217cbfd09a3ffdf7b7893a1aa92 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:20 +0200 Subject: [PATCH 1416/2270] target-mips: use the softfloat floatXX_muladd functions Use the new softfloat floatXX_muladd() functions to implement the madd, msub, nmadd and nmsub instructions. At the same time replace the name of the helpers by the name of the instruction, as the only reason for the previous names was to keep the macros simple. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/helper.h | 8 +-- target-mips/op_helper.c | 135 ++++++++++++++-------------------------- target-mips/translate.c | 24 +++---- 3 files changed, 63 insertions(+), 104 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index 36a2e8da07..da8d9a1381 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -254,10 +254,10 @@ FOP_PROTO(rsqrt2) DEF_HELPER_4(float_ ## op ## _s, i32, env, i32, i32, i32) \ DEF_HELPER_4(float_ ## op ## _d, i64, env, i64, i64, i64) \ DEF_HELPER_4(float_ ## op ## _ps, i64, env, i64, i64, i64) -FOP_PROTO(muladd) -FOP_PROTO(mulsub) -FOP_PROTO(nmuladd) -FOP_PROTO(nmulsub) +FOP_PROTO(madd) +FOP_PROTO(msub) +FOP_PROTO(nmadd) +FOP_PROTO(nmsub) #undef FOP_PROTO #define FOP_PROTO(op) \ diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index d50334f45f..1abed8e3da 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -3031,95 +3031,54 @@ FLOAT_BINOP(mul) FLOAT_BINOP(div) #undef FLOAT_BINOP -/* ternary operations */ -#define FLOAT_TERNOP(name1, name2) \ -uint64_t helper_float_ ## name1 ## name2 ## _d(CPUMIPSState *env, \ - uint64_t fdt0, \ - uint64_t fdt1, \ - uint64_t fdt2) \ -{ \ - fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status); \ - return float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status); \ -} \ - \ -uint32_t helper_float_ ## name1 ## name2 ## _s(CPUMIPSState *env, \ - uint32_t fst0, \ - uint32_t fst1, \ - uint32_t fst2) \ -{ \ - fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \ - return float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \ -} \ - \ -uint64_t helper_float_ ## name1 ## name2 ## _ps(CPUMIPSState *env, \ - uint64_t fdt0, \ - uint64_t fdt1, \ - uint64_t fdt2) \ -{ \ - uint32_t fst0 = fdt0 & 0XFFFFFFFF; \ - uint32_t fsth0 = fdt0 >> 32; \ - uint32_t fst1 = fdt1 & 0XFFFFFFFF; \ - uint32_t fsth1 = fdt1 >> 32; \ - uint32_t fst2 = fdt2 & 0XFFFFFFFF; \ - uint32_t fsth2 = fdt2 >> 32; \ - \ - fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \ - fsth0 = float32_ ## name1 (fsth0, fsth1, &env->active_fpu.fp_status); \ - fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \ - fsth2 = float32_ ## name2 (fsth0, fsth2, &env->active_fpu.fp_status); \ - return ((uint64_t)fsth2 << 32) | fst2; \ +/* FMA based operations */ +#define FLOAT_FMA(name, type) \ +uint64_t helper_float_ ## name ## _d(CPUMIPSState *env, \ + uint64_t fdt0, uint64_t fdt1, \ + uint64_t fdt2) \ +{ \ + set_float_exception_flags(0, &env->active_fpu.fp_status); \ + fdt0 = float64_muladd(fdt0, fdt1, fdt2, type, \ + &env->active_fpu.fp_status); \ + update_fcr31(env); \ + return fdt0; \ +} \ + \ +uint32_t helper_float_ ## name ## _s(CPUMIPSState *env, \ + uint32_t fst0, uint32_t fst1, \ + uint32_t fst2) \ +{ \ + set_float_exception_flags(0, &env->active_fpu.fp_status); \ + fst0 = float32_muladd(fst0, fst1, fst2, type, \ + &env->active_fpu.fp_status); \ + update_fcr31(env); \ + return fst0; \ +} \ + \ +uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \ + uint64_t fdt0, uint64_t fdt1, \ + uint64_t fdt2) \ +{ \ + uint32_t fst0 = fdt0 & 0XFFFFFFFF; \ + uint32_t fsth0 = fdt0 >> 32; \ + uint32_t fst1 = fdt1 & 0XFFFFFFFF; \ + uint32_t fsth1 = fdt1 >> 32; \ + uint32_t fst2 = fdt2 & 0XFFFFFFFF; \ + uint32_t fsth2 = fdt2 >> 32; \ + \ + set_float_exception_flags(0, &env->active_fpu.fp_status); \ + fst0 = float32_muladd(fst0, fst1, fst2, type, \ + &env->active_fpu.fp_status); \ + fsth0 = float32_muladd(fsth0, fsth1, fsth2, type, \ + &env->active_fpu.fp_status); \ + update_fcr31(env); \ + return ((uint64_t)fsth0 << 32) | fst0; \ } - -FLOAT_TERNOP(mul, add) -FLOAT_TERNOP(mul, sub) -#undef FLOAT_TERNOP - -/* negated ternary operations */ -#define FLOAT_NTERNOP(name1, name2) \ -uint64_t helper_float_n ## name1 ## name2 ## _d(CPUMIPSState *env, \ - uint64_t fdt0, \ - uint64_t fdt1, \ - uint64_t fdt2) \ -{ \ - fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status); \ - fdt2 = float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status); \ - return float64_chs(fdt2); \ -} \ - \ -uint32_t helper_float_n ## name1 ## name2 ## _s(CPUMIPSState *env, \ - uint32_t fst0, \ - uint32_t fst1, \ - uint32_t fst2) \ -{ \ - fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \ - fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \ - return float32_chs(fst2); \ -} \ - \ -uint64_t helper_float_n ## name1 ## name2 ## _ps(CPUMIPSState *env, \ - uint64_t fdt0, \ - uint64_t fdt1, \ - uint64_t fdt2) \ -{ \ - uint32_t fst0 = fdt0 & 0XFFFFFFFF; \ - uint32_t fsth0 = fdt0 >> 32; \ - uint32_t fst1 = fdt1 & 0XFFFFFFFF; \ - uint32_t fsth1 = fdt1 >> 32; \ - uint32_t fst2 = fdt2 & 0XFFFFFFFF; \ - uint32_t fsth2 = fdt2 >> 32; \ - \ - fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \ - fsth0 = float32_ ## name1 (fsth0, fsth1, &env->active_fpu.fp_status); \ - fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \ - fsth2 = float32_ ## name2 (fsth0, fsth2, &env->active_fpu.fp_status); \ - fst2 = float32_chs(fst2); \ - fsth2 = float32_chs(fsth2); \ - return ((uint64_t)fsth2 << 32) | fst2; \ -} - -FLOAT_NTERNOP(mul, add) -FLOAT_NTERNOP(mul, sub) -#undef FLOAT_NTERNOP +FLOAT_FMA(madd, 0) +FLOAT_FMA(msub, float_muladd_negate_c) +FLOAT_FMA(nmadd, float_muladd_negate_result) +FLOAT_FMA(nmsub, float_muladd_negate_result | float_muladd_negate_c) +#undef FLOAT_FMA /* MIPS specific binary operations */ uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) diff --git a/target-mips/translate.c b/target-mips/translate.c index a84ed6e547..e7184715bf 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -8817,7 +8817,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr32(fp0, fs); gen_load_fpr32(fp1, ft); gen_load_fpr32(fp2, fr); - gen_helper_float_muladd_s(fp2, cpu_env, fp0, fp1, fp2); + gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i32(fp0); tcg_temp_free_i32(fp1); gen_store_fpr32(fp2, fd); @@ -8836,7 +8836,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); gen_load_fpr64(ctx, fp2, fr); - gen_helper_float_muladd_d(fp2, cpu_env, fp0, fp1, fp2); + gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i64(fp0); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp2, fd); @@ -8854,7 +8854,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); gen_load_fpr64(ctx, fp2, fr); - gen_helper_float_muladd_ps(fp2, cpu_env, fp0, fp1, fp2); + gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i64(fp0); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp2, fd); @@ -8872,7 +8872,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr32(fp0, fs); gen_load_fpr32(fp1, ft); gen_load_fpr32(fp2, fr); - gen_helper_float_mulsub_s(fp2, cpu_env, fp0, fp1, fp2); + gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i32(fp0); tcg_temp_free_i32(fp1); gen_store_fpr32(fp2, fd); @@ -8891,7 +8891,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); gen_load_fpr64(ctx, fp2, fr); - gen_helper_float_mulsub_d(fp2, cpu_env, fp0, fp1, fp2); + gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i64(fp0); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp2, fd); @@ -8909,7 +8909,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); gen_load_fpr64(ctx, fp2, fr); - gen_helper_float_mulsub_ps(fp2, cpu_env, fp0, fp1, fp2); + gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i64(fp0); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp2, fd); @@ -8927,7 +8927,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr32(fp0, fs); gen_load_fpr32(fp1, ft); gen_load_fpr32(fp2, fr); - gen_helper_float_nmuladd_s(fp2, cpu_env, fp0, fp1, fp2); + gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i32(fp0); tcg_temp_free_i32(fp1); gen_store_fpr32(fp2, fd); @@ -8946,7 +8946,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); gen_load_fpr64(ctx, fp2, fr); - gen_helper_float_nmuladd_d(fp2, cpu_env, fp0, fp1, fp2); + gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i64(fp0); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp2, fd); @@ -8964,7 +8964,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); gen_load_fpr64(ctx, fp2, fr); - gen_helper_float_nmuladd_ps(fp2, cpu_env, fp0, fp1, fp2); + gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i64(fp0); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp2, fd); @@ -8982,7 +8982,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr32(fp0, fs); gen_load_fpr32(fp1, ft); gen_load_fpr32(fp2, fr); - gen_helper_float_nmulsub_s(fp2, cpu_env, fp0, fp1, fp2); + gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i32(fp0); tcg_temp_free_i32(fp1); gen_store_fpr32(fp2, fd); @@ -9001,7 +9001,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); gen_load_fpr64(ctx, fp2, fr); - gen_helper_float_nmulsub_d(fp2, cpu_env, fp0, fp1, fp2); + gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i64(fp0); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp2, fd); @@ -9019,7 +9019,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, gen_load_fpr64(ctx, fp0, fs); gen_load_fpr64(ctx, fp1, ft); gen_load_fpr64(ctx, fp2, fr); - gen_helper_float_nmulsub_ps(fp2, cpu_env, fp0, fp1, fp2); + gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2); tcg_temp_free_i64(fp0); tcg_temp_free_i64(fp1); gen_store_fpr64(ctx, fp2, fd); From 4a587b2ccb336e36817712ab21c513e35baa0eca Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 28 Oct 2012 18:08:27 +0100 Subject: [PATCH 1417/2270] target-mips: keep softfloat exception set to 0 between instructions Instead of clearing the softfloat exception flags before each floating point instruction, reset them to 0 in update_fcr31() when an exception is detected. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 73 ++++++----------------------------------- 1 file changed, 10 insertions(+), 63 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 1abed8e3da..82044990b0 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2445,10 +2445,16 @@ static inline void update_fcr31(CPUMIPSState *env) int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->active_fpu.fp_status)); SET_FP_CAUSE(env->active_fpu.fcr31, tmp); - if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp) - helper_raise_exception(env, EXCP_FPE); - else - UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp); + + if (tmp) { + set_float_exception_flags(0, &env->active_fpu.fp_status); + + if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp) { + helper_raise_exception(env, EXCP_FPE); + } else { + UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp); + } + } } /* Float support. @@ -2471,7 +2477,6 @@ uint64_t helper_float_cvtd_s(CPUMIPSState *env, uint32_t fst0) { uint64_t fdt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status); update_fcr31(env); return fdt2; @@ -2481,7 +2486,6 @@ uint64_t helper_float_cvtd_w(CPUMIPSState *env, uint32_t wt0) { uint64_t fdt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status); update_fcr31(env); return fdt2; @@ -2491,7 +2495,6 @@ uint64_t helper_float_cvtd_l(CPUMIPSState *env, uint64_t dt0) { uint64_t fdt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status); update_fcr31(env); return fdt2; @@ -2501,7 +2504,6 @@ uint64_t helper_float_cvtl_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t dt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) @@ -2513,7 +2515,6 @@ uint64_t helper_float_cvtl_s(CPUMIPSState *env, uint32_t fst0) { uint64_t dt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) @@ -2526,7 +2527,6 @@ uint64_t helper_float_cvtps_pw(CPUMIPSState *env, uint64_t dt0) uint32_t fst2; uint32_t fsth2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status); update_fcr31(env); @@ -2538,7 +2538,6 @@ uint64_t helper_float_cvtpw_ps(CPUMIPSState *env, uint64_t fdt0) uint32_t wt2; uint32_t wth2; - set_float_exception_flags(0, &env->active_fpu.fp_status); wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status); update_fcr31(env); @@ -2553,7 +2552,6 @@ uint32_t helper_float_cvts_d(CPUMIPSState *env, uint64_t fdt0) { uint32_t fst2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status); update_fcr31(env); return fst2; @@ -2563,7 +2561,6 @@ uint32_t helper_float_cvts_w(CPUMIPSState *env, uint32_t wt0) { uint32_t fst2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status); update_fcr31(env); return fst2; @@ -2573,7 +2570,6 @@ uint32_t helper_float_cvts_l(CPUMIPSState *env, uint64_t dt0) { uint32_t fst2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status); update_fcr31(env); return fst2; @@ -2583,7 +2579,6 @@ uint32_t helper_float_cvts_pl(CPUMIPSState *env, uint32_t wt0) { uint32_t wt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); wt2 = wt0; update_fcr31(env); return wt2; @@ -2593,7 +2588,6 @@ uint32_t helper_float_cvts_pu(CPUMIPSState *env, uint32_t wth0) { uint32_t wt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); wt2 = wth0; update_fcr31(env); return wt2; @@ -2603,7 +2597,6 @@ uint32_t helper_float_cvtw_s(CPUMIPSState *env, uint32_t fst0) { uint32_t wt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) @@ -2615,7 +2608,6 @@ uint32_t helper_float_cvtw_d(CPUMIPSState *env, uint64_t fdt0) { uint32_t wt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) @@ -2627,7 +2619,6 @@ uint64_t helper_float_roundl_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t dt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status); dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; @@ -2641,7 +2632,6 @@ uint64_t helper_float_roundl_s(CPUMIPSState *env, uint32_t fst0) { uint64_t dt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status); dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; @@ -2655,7 +2645,6 @@ uint32_t helper_float_roundw_d(CPUMIPSState *env, uint64_t fdt0) { uint32_t wt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status); wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; @@ -2669,7 +2658,6 @@ uint32_t helper_float_roundw_s(CPUMIPSState *env, uint32_t fst0) { uint32_t wt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status); wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; @@ -2683,7 +2671,6 @@ uint64_t helper_float_truncl_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t dt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status); update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) @@ -2695,7 +2682,6 @@ uint64_t helper_float_truncl_s(CPUMIPSState *env, uint32_t fst0) { uint64_t dt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status); update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) @@ -2707,7 +2693,6 @@ uint32_t helper_float_truncw_d(CPUMIPSState *env, uint64_t fdt0) { uint32_t wt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status); update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) @@ -2719,7 +2704,6 @@ uint32_t helper_float_truncw_s(CPUMIPSState *env, uint32_t fst0) { uint32_t wt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status); update_fcr31(env); if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) @@ -2731,7 +2715,6 @@ uint64_t helper_float_ceill_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t dt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; @@ -2745,7 +2728,6 @@ uint64_t helper_float_ceill_s(CPUMIPSState *env, uint32_t fst0) { uint64_t dt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; @@ -2759,7 +2741,6 @@ uint32_t helper_float_ceilw_d(CPUMIPSState *env, uint64_t fdt0) { uint32_t wt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; @@ -2773,7 +2754,6 @@ uint32_t helper_float_ceilw_s(CPUMIPSState *env, uint32_t fst0) { uint32_t wt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; @@ -2787,7 +2767,6 @@ uint64_t helper_float_floorl_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t dt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; @@ -2801,7 +2780,6 @@ uint64_t helper_float_floorl_s(CPUMIPSState *env, uint32_t fst0) { uint64_t dt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; @@ -2815,7 +2793,6 @@ uint32_t helper_float_floorw_d(CPUMIPSState *env, uint64_t fdt0) { uint32_t wt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; @@ -2829,7 +2806,6 @@ uint32_t helper_float_floorw_s(CPUMIPSState *env, uint32_t fst0) { uint32_t wt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; @@ -2867,7 +2843,6 @@ uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t fdt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status); update_fcr31(env); return fdt2; @@ -2877,7 +2852,6 @@ uint32_t helper_float_recip_s(CPUMIPSState *env, uint32_t fst0) { uint32_t fst2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status); update_fcr31(env); return fst2; @@ -2887,7 +2861,6 @@ uint64_t helper_float_rsqrt_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t fdt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status); fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status); update_fcr31(env); @@ -2898,7 +2871,6 @@ uint32_t helper_float_rsqrt_s(CPUMIPSState *env, uint32_t fst0) { uint32_t fst2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status); fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status); update_fcr31(env); @@ -2909,7 +2881,6 @@ uint64_t helper_float_recip1_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t fdt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status); update_fcr31(env); return fdt2; @@ -2919,7 +2890,6 @@ uint32_t helper_float_recip1_s(CPUMIPSState *env, uint32_t fst0) { uint32_t fst2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status); update_fcr31(env); return fst2; @@ -2930,7 +2900,6 @@ uint64_t helper_float_recip1_ps(CPUMIPSState *env, uint64_t fdt0) uint32_t fst2; uint32_t fsth2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_div(FLOAT_ONE32, fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); fsth2 = float32_div(FLOAT_ONE32, fdt0 >> 32, &env->active_fpu.fp_status); update_fcr31(env); @@ -2941,7 +2910,6 @@ uint64_t helper_float_rsqrt1_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t fdt2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status); fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status); update_fcr31(env); @@ -2952,7 +2920,6 @@ uint32_t helper_float_rsqrt1_s(CPUMIPSState *env, uint32_t fst0) { uint32_t fst2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status); fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status); update_fcr31(env); @@ -2964,7 +2931,6 @@ uint64_t helper_float_rsqrt1_ps(CPUMIPSState *env, uint64_t fdt0) uint32_t fst2; uint32_t fsth2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status); fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status); @@ -2982,7 +2948,6 @@ uint64_t helper_float_ ## name ## _d(CPUMIPSState *env, \ { \ uint64_t dt2; \ \ - set_float_exception_flags(0, &env->active_fpu.fp_status); \ dt2 = float64_ ## name (fdt0, fdt1, &env->active_fpu.fp_status); \ update_fcr31(env); \ if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) \ @@ -2995,7 +2960,6 @@ uint32_t helper_float_ ## name ## _s(CPUMIPSState *env, \ { \ uint32_t wt2; \ \ - set_float_exception_flags(0, &env->active_fpu.fp_status); \ wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \ update_fcr31(env); \ if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) \ @@ -3014,7 +2978,6 @@ uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \ uint32_t wt2; \ uint32_t wth2; \ \ - set_float_exception_flags(0, &env->active_fpu.fp_status); \ wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \ wth2 = float32_ ## name (fsth0, fsth1, &env->active_fpu.fp_status); \ update_fcr31(env); \ @@ -3037,7 +3000,6 @@ uint64_t helper_float_ ## name ## _d(CPUMIPSState *env, \ uint64_t fdt0, uint64_t fdt1, \ uint64_t fdt2) \ { \ - set_float_exception_flags(0, &env->active_fpu.fp_status); \ fdt0 = float64_muladd(fdt0, fdt1, fdt2, type, \ &env->active_fpu.fp_status); \ update_fcr31(env); \ @@ -3048,7 +3010,6 @@ uint32_t helper_float_ ## name ## _s(CPUMIPSState *env, \ uint32_t fst0, uint32_t fst1, \ uint32_t fst2) \ { \ - set_float_exception_flags(0, &env->active_fpu.fp_status); \ fst0 = float32_muladd(fst0, fst1, fst2, type, \ &env->active_fpu.fp_status); \ update_fcr31(env); \ @@ -3066,7 +3027,6 @@ uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \ uint32_t fst2 = fdt2 & 0XFFFFFFFF; \ uint32_t fsth2 = fdt2 >> 32; \ \ - set_float_exception_flags(0, &env->active_fpu.fp_status); \ fst0 = float32_muladd(fst0, fst1, fst2, type, \ &env->active_fpu.fp_status); \ fsth0 = float32_muladd(fsth0, fsth1, fsth2, type, \ @@ -3083,7 +3043,6 @@ FLOAT_FMA(nmsub, float_muladd_negate_result | float_muladd_negate_c) /* MIPS specific binary operations */ uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) { - set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status); fdt2 = float64_chs(float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status)); update_fcr31(env); @@ -3092,7 +3051,6 @@ uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) uint32_t helper_float_recip2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2) { - set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status)); update_fcr31(env); @@ -3106,7 +3064,6 @@ uint64_t helper_float_recip2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) uint32_t fst2 = fdt2 & 0XFFFFFFFF; uint32_t fsth2 = fdt2 >> 32; - set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status); fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status)); @@ -3117,7 +3074,6 @@ uint64_t helper_float_recip2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) uint64_t helper_float_rsqrt2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) { - set_float_exception_flags(0, &env->active_fpu.fp_status); fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status); fdt2 = float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status); fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->active_fpu.fp_status)); @@ -3127,7 +3083,6 @@ uint64_t helper_float_rsqrt2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) uint32_t helper_float_rsqrt2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2) { - set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status); fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status)); @@ -3142,7 +3097,6 @@ uint64_t helper_float_rsqrt2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) uint32_t fst2 = fdt2 & 0XFFFFFFFF; uint32_t fsth2 = fdt2 >> 32; - set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status); fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status); @@ -3162,7 +3116,6 @@ uint64_t helper_float_addr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1) uint32_t fst2; uint32_t fsth2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_add (fst0, fsth0, &env->active_fpu.fp_status); fsth2 = float32_add (fst1, fsth1, &env->active_fpu.fp_status); update_fcr31(env); @@ -3178,7 +3131,6 @@ uint64_t helper_float_mulr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1) uint32_t fst2; uint32_t fsth2; - set_float_exception_flags(0, &env->active_fpu.fp_status); fst2 = float32_mul (fst0, fsth0, &env->active_fpu.fp_status); fsth2 = float32_mul (fst1, fsth1, &env->active_fpu.fp_status); update_fcr31(env); @@ -3191,7 +3143,6 @@ void helper_cmp_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \ uint64_t fdt1, int cc) \ { \ int c; \ - set_float_exception_flags(0, &env->active_fpu.fp_status); \ c = cond; \ update_fcr31(env); \ if (c) \ @@ -3203,7 +3154,6 @@ void helper_cmpabs_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \ uint64_t fdt1, int cc) \ { \ int c; \ - set_float_exception_flags(0, &env->active_fpu.fp_status); \ fdt0 = float64_abs(fdt0); \ fdt1 = float64_abs(fdt1); \ c = cond; \ @@ -3240,7 +3190,6 @@ void helper_cmp_s_ ## op(CPUMIPSState *env, uint32_t fst0, \ uint32_t fst1, int cc) \ { \ int c; \ - set_float_exception_flags(0, &env->active_fpu.fp_status); \ c = cond; \ update_fcr31(env); \ if (c) \ @@ -3252,7 +3201,6 @@ void helper_cmpabs_s_ ## op(CPUMIPSState *env, uint32_t fst0, \ uint32_t fst1, int cc) \ { \ int c; \ - set_float_exception_flags(0, &env->active_fpu.fp_status); \ fst0 = float32_abs(fst0); \ fst1 = float32_abs(fst1); \ c = cond; \ @@ -3290,7 +3238,6 @@ void helper_cmp_ps_ ## op(CPUMIPSState *env, uint64_t fdt0, \ { \ uint32_t fst0, fsth0, fst1, fsth1; \ int ch, cl; \ - set_float_exception_flags(0, &env->active_fpu.fp_status); \ fst0 = fdt0 & 0XFFFFFFFF; \ fsth0 = fdt0 >> 32; \ fst1 = fdt1 & 0XFFFFFFFF; \ From 5dbe90bba778c6ffcd0c7991ec67c4e7469e1c09 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:20 +0200 Subject: [PATCH 1418/2270] target-mips: fix FPU exceptions For each FPU instruction that can trigger an FPU exception, to call call update_fcr31() after. Remove the manual NaN assignment in case of float to float operation, as softfloat is already taking care of that. However for float to int operation, the value has to be changed to the MIPS one. In the cvtpw_ps case, the two registers have to be handled separately to guarantee a correct final value in both registers. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 82044990b0..7981ea2f3a 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2465,12 +2465,16 @@ static inline void update_fcr31(CPUMIPSState *env) /* unary operations, modifying fp status */ uint64_t helper_float_sqrt_d(CPUMIPSState *env, uint64_t fdt0) { - return float64_sqrt(fdt0, &env->active_fpu.fp_status); + fdt0 = float64_sqrt(fdt0, &env->active_fpu.fp_status); + update_fcr31(env); + return fdt0; } uint32_t helper_float_sqrt_s(CPUMIPSState *env, uint32_t fst0) { - return float32_sqrt(fst0, &env->active_fpu.fp_status); + fst0 = float32_sqrt(fst0, &env->active_fpu.fp_status); + update_fcr31(env); + return fst0; } uint64_t helper_float_cvtd_s(CPUMIPSState *env, uint32_t fst0) @@ -2537,14 +2541,24 @@ uint64_t helper_float_cvtpw_ps(CPUMIPSState *env, uint64_t fdt0) { uint32_t wt2; uint32_t wth2; + int excp, excph; wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); - wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status); - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) { + excp = get_float_exception_flags(&env->active_fpu.fp_status); + if (excp & (float_flag_overflow | float_flag_invalid)) { wt2 = FLOAT_SNAN32; + } + + set_float_exception_flags(0, &env->active_fpu.fp_status); + wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status); + excph = get_float_exception_flags(&env->active_fpu.fp_status); + if (excph & (float_flag_overflow | float_flag_invalid)) { wth2 = FLOAT_SNAN32; } + + set_float_exception_flags(excp | excph, &env->active_fpu.fp_status); + update_fcr31(env); + return ((uint64_t)wth2 << 32) | wt2; } @@ -2950,8 +2964,6 @@ uint64_t helper_float_ ## name ## _d(CPUMIPSState *env, \ \ dt2 = float64_ ## name (fdt0, fdt1, &env->active_fpu.fp_status); \ update_fcr31(env); \ - if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) \ - dt2 = FLOAT_QNAN64; \ return dt2; \ } \ \ @@ -2962,8 +2974,6 @@ uint32_t helper_float_ ## name ## _s(CPUMIPSState *env, \ \ wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \ update_fcr31(env); \ - if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) \ - wt2 = FLOAT_QNAN32; \ return wt2; \ } \ \ @@ -2981,10 +2991,6 @@ uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \ wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \ wth2 = float32_ ## name (fsth0, fsth1, &env->active_fpu.fp_status); \ update_fcr31(env); \ - if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) { \ - wt2 = FLOAT_QNAN32; \ - wth2 = FLOAT_QNAN32; \ - } \ return ((uint64_t)wth2 << 32) | wt2; \ } From 4cc2e5f989728424e913777c494d68dbf0d2ec09 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 23 Oct 2012 09:53:50 +0200 Subject: [PATCH 1419/2270] target-mips: cleanup float to int conversion helpers Instead of accessing the flags from the floating point control register after updating it, read the softfloat flags. This is just code cleanup and should not change the behaviour. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 118 +++++++++++++++++++++++++++------------- 1 file changed, 79 insertions(+), 39 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 7981ea2f3a..d3a317bea9 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2509,9 +2509,11 @@ uint64_t helper_float_cvtl_d(CPUMIPSState *env, uint64_t fdt0) uint64_t dt2; dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { dt2 = FLOAT_SNAN64; + } + update_fcr31(env); return dt2; } @@ -2520,9 +2522,11 @@ uint64_t helper_float_cvtl_s(CPUMIPSState *env, uint32_t fst0) uint64_t dt2; dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { dt2 = FLOAT_SNAN64; + } + update_fcr31(env); return dt2; } @@ -2613,8 +2617,10 @@ uint32_t helper_float_cvtw_s(CPUMIPSState *env, uint32_t fst0) wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { wt2 = FLOAT_SNAN32; + } return wt2; } @@ -2623,9 +2629,11 @@ uint32_t helper_float_cvtw_d(CPUMIPSState *env, uint64_t fdt0) uint32_t wt2; wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { wt2 = FLOAT_SNAN32; + } + update_fcr31(env); return wt2; } @@ -2636,9 +2644,11 @@ uint64_t helper_float_roundl_d(CPUMIPSState *env, uint64_t fdt0) set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status); dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { dt2 = FLOAT_SNAN64; + } + update_fcr31(env); return dt2; } @@ -2649,9 +2659,11 @@ uint64_t helper_float_roundl_s(CPUMIPSState *env, uint32_t fst0) set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status); dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { dt2 = FLOAT_SNAN64; + } + update_fcr31(env); return dt2; } @@ -2662,9 +2674,11 @@ uint32_t helper_float_roundw_d(CPUMIPSState *env, uint64_t fdt0) set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status); wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { wt2 = FLOAT_SNAN32; + } + update_fcr31(env); return wt2; } @@ -2675,9 +2689,11 @@ uint32_t helper_float_roundw_s(CPUMIPSState *env, uint32_t fst0) set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status); wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { wt2 = FLOAT_SNAN32; + } + update_fcr31(env); return wt2; } @@ -2686,9 +2702,11 @@ uint64_t helper_float_truncl_d(CPUMIPSState *env, uint64_t fdt0) uint64_t dt2; dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status); - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { dt2 = FLOAT_SNAN64; + } + update_fcr31(env); return dt2; } @@ -2697,9 +2715,11 @@ uint64_t helper_float_truncl_s(CPUMIPSState *env, uint32_t fst0) uint64_t dt2; dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status); - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { dt2 = FLOAT_SNAN64; + } + update_fcr31(env); return dt2; } @@ -2708,9 +2728,11 @@ uint32_t helper_float_truncw_d(CPUMIPSState *env, uint64_t fdt0) uint32_t wt2; wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status); - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { wt2 = FLOAT_SNAN32; + } + update_fcr31(env); return wt2; } @@ -2719,9 +2741,11 @@ uint32_t helper_float_truncw_s(CPUMIPSState *env, uint32_t fst0) uint32_t wt2; wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status); - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { wt2 = FLOAT_SNAN32; + } + update_fcr31(env); return wt2; } @@ -2732,9 +2756,11 @@ uint64_t helper_float_ceill_d(CPUMIPSState *env, uint64_t fdt0) set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { dt2 = FLOAT_SNAN64; + } + update_fcr31(env); return dt2; } @@ -2745,9 +2771,11 @@ uint64_t helper_float_ceill_s(CPUMIPSState *env, uint32_t fst0) set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { dt2 = FLOAT_SNAN64; + } + update_fcr31(env); return dt2; } @@ -2758,9 +2786,11 @@ uint32_t helper_float_ceilw_d(CPUMIPSState *env, uint64_t fdt0) set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { wt2 = FLOAT_SNAN32; + } + update_fcr31(env); return wt2; } @@ -2771,9 +2801,11 @@ uint32_t helper_float_ceilw_s(CPUMIPSState *env, uint32_t fst0) set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { wt2 = FLOAT_SNAN32; + } + update_fcr31(env); return wt2; } @@ -2784,9 +2816,11 @@ uint64_t helper_float_floorl_d(CPUMIPSState *env, uint64_t fdt0) set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { dt2 = FLOAT_SNAN64; + } + update_fcr31(env); return dt2; } @@ -2797,9 +2831,11 @@ uint64_t helper_float_floorl_s(CPUMIPSState *env, uint32_t fst0) set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { dt2 = FLOAT_SNAN64; + } + update_fcr31(env); return dt2; } @@ -2810,9 +2846,11 @@ uint32_t helper_float_floorw_d(CPUMIPSState *env, uint64_t fdt0) set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { wt2 = FLOAT_SNAN32; + } + update_fcr31(env); return wt2; } @@ -2823,9 +2861,11 @@ uint32_t helper_float_floorw_s(CPUMIPSState *env, uint32_t fst0) set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); RESTORE_ROUNDING_MODE; - update_fcr31(env); - if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { wt2 = FLOAT_SNAN32; + } + update_fcr31(env); return wt2; } From 05993cd05fcdebc75f8432cf6ad558726dc8ec15 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 23 Oct 2012 10:12:00 +0200 Subject: [PATCH 1420/2270] target-mips: use softfloat constants when possible softfloat already has a few constants defined, use them instead of redefining them in target-mips. Rename FLOAT_SNAN32 and FLOAT_SNAN64 to FP_TO_INT32_OVERFLOW and FP_TO_INT64_OVERFLOW as even if they have the same value, they are technically different (and defined differently in the MIPS ISA). Remove the unused constants. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 92 ++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 48 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index d3a317bea9..2f9ec5d26e 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2332,14 +2332,10 @@ void cpu_unassigned_access(CPUMIPSState *env, hwaddr addr, /* Complex FPU operations which may need stack space. */ -#define FLOAT_ONE32 make_float32(0x3f8 << 20) -#define FLOAT_ONE64 make_float64(0x3ffULL << 52) #define FLOAT_TWO32 make_float32(1 << 30) #define FLOAT_TWO64 make_float64(1ULL << 62) -#define FLOAT_QNAN32 0x7fbfffff -#define FLOAT_QNAN64 0x7ff7ffffffffffffULL -#define FLOAT_SNAN32 0x7fffffff -#define FLOAT_SNAN64 0x7fffffffffffffffULL +#define FP_TO_INT32_OVERFLOW 0x7fffffff +#define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL /* convert MIPS rounding mode in FCR31 to IEEE library */ static unsigned int ieee_rm[] = { @@ -2511,7 +2507,7 @@ uint64_t helper_float_cvtl_d(CPUMIPSState *env, uint64_t fdt0) dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - dt2 = FLOAT_SNAN64; + dt2 = FP_TO_INT64_OVERFLOW; } update_fcr31(env); return dt2; @@ -2524,7 +2520,7 @@ uint64_t helper_float_cvtl_s(CPUMIPSState *env, uint32_t fst0) dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - dt2 = FLOAT_SNAN64; + dt2 = FP_TO_INT64_OVERFLOW; } update_fcr31(env); return dt2; @@ -2550,14 +2546,14 @@ uint64_t helper_float_cvtpw_ps(CPUMIPSState *env, uint64_t fdt0) wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); excp = get_float_exception_flags(&env->active_fpu.fp_status); if (excp & (float_flag_overflow | float_flag_invalid)) { - wt2 = FLOAT_SNAN32; + wt2 = FP_TO_INT32_OVERFLOW; } set_float_exception_flags(0, &env->active_fpu.fp_status); wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status); excph = get_float_exception_flags(&env->active_fpu.fp_status); if (excph & (float_flag_overflow | float_flag_invalid)) { - wth2 = FLOAT_SNAN32; + wth2 = FP_TO_INT32_OVERFLOW; } set_float_exception_flags(excp | excph, &env->active_fpu.fp_status); @@ -2619,7 +2615,7 @@ uint32_t helper_float_cvtw_s(CPUMIPSState *env, uint32_t fst0) update_fcr31(env); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - wt2 = FLOAT_SNAN32; + wt2 = FP_TO_INT32_OVERFLOW; } return wt2; } @@ -2631,7 +2627,7 @@ uint32_t helper_float_cvtw_d(CPUMIPSState *env, uint64_t fdt0) wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - wt2 = FLOAT_SNAN32; + wt2 = FP_TO_INT32_OVERFLOW; } update_fcr31(env); return wt2; @@ -2646,7 +2642,7 @@ uint64_t helper_float_roundl_d(CPUMIPSState *env, uint64_t fdt0) RESTORE_ROUNDING_MODE; if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - dt2 = FLOAT_SNAN64; + dt2 = FP_TO_INT64_OVERFLOW; } update_fcr31(env); return dt2; @@ -2661,7 +2657,7 @@ uint64_t helper_float_roundl_s(CPUMIPSState *env, uint32_t fst0) RESTORE_ROUNDING_MODE; if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - dt2 = FLOAT_SNAN64; + dt2 = FP_TO_INT64_OVERFLOW; } update_fcr31(env); return dt2; @@ -2676,7 +2672,7 @@ uint32_t helper_float_roundw_d(CPUMIPSState *env, uint64_t fdt0) RESTORE_ROUNDING_MODE; if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - wt2 = FLOAT_SNAN32; + wt2 = FP_TO_INT32_OVERFLOW; } update_fcr31(env); return wt2; @@ -2691,7 +2687,7 @@ uint32_t helper_float_roundw_s(CPUMIPSState *env, uint32_t fst0) RESTORE_ROUNDING_MODE; if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - wt2 = FLOAT_SNAN32; + wt2 = FP_TO_INT32_OVERFLOW; } update_fcr31(env); return wt2; @@ -2704,7 +2700,7 @@ uint64_t helper_float_truncl_d(CPUMIPSState *env, uint64_t fdt0) dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - dt2 = FLOAT_SNAN64; + dt2 = FP_TO_INT64_OVERFLOW; } update_fcr31(env); return dt2; @@ -2717,7 +2713,7 @@ uint64_t helper_float_truncl_s(CPUMIPSState *env, uint32_t fst0) dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - dt2 = FLOAT_SNAN64; + dt2 = FP_TO_INT64_OVERFLOW; } update_fcr31(env); return dt2; @@ -2730,7 +2726,7 @@ uint32_t helper_float_truncw_d(CPUMIPSState *env, uint64_t fdt0) wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - wt2 = FLOAT_SNAN32; + wt2 = FP_TO_INT32_OVERFLOW; } update_fcr31(env); return wt2; @@ -2743,7 +2739,7 @@ uint32_t helper_float_truncw_s(CPUMIPSState *env, uint32_t fst0) wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - wt2 = FLOAT_SNAN32; + wt2 = FP_TO_INT32_OVERFLOW; } update_fcr31(env); return wt2; @@ -2758,7 +2754,7 @@ uint64_t helper_float_ceill_d(CPUMIPSState *env, uint64_t fdt0) RESTORE_ROUNDING_MODE; if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - dt2 = FLOAT_SNAN64; + dt2 = FP_TO_INT64_OVERFLOW; } update_fcr31(env); return dt2; @@ -2773,7 +2769,7 @@ uint64_t helper_float_ceill_s(CPUMIPSState *env, uint32_t fst0) RESTORE_ROUNDING_MODE; if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - dt2 = FLOAT_SNAN64; + dt2 = FP_TO_INT64_OVERFLOW; } update_fcr31(env); return dt2; @@ -2788,7 +2784,7 @@ uint32_t helper_float_ceilw_d(CPUMIPSState *env, uint64_t fdt0) RESTORE_ROUNDING_MODE; if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - wt2 = FLOAT_SNAN32; + wt2 = FP_TO_INT32_OVERFLOW; } update_fcr31(env); return wt2; @@ -2803,7 +2799,7 @@ uint32_t helper_float_ceilw_s(CPUMIPSState *env, uint32_t fst0) RESTORE_ROUNDING_MODE; if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - wt2 = FLOAT_SNAN32; + wt2 = FP_TO_INT32_OVERFLOW; } update_fcr31(env); return wt2; @@ -2818,7 +2814,7 @@ uint64_t helper_float_floorl_d(CPUMIPSState *env, uint64_t fdt0) RESTORE_ROUNDING_MODE; if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - dt2 = FLOAT_SNAN64; + dt2 = FP_TO_INT64_OVERFLOW; } update_fcr31(env); return dt2; @@ -2833,7 +2829,7 @@ uint64_t helper_float_floorl_s(CPUMIPSState *env, uint32_t fst0) RESTORE_ROUNDING_MODE; if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - dt2 = FLOAT_SNAN64; + dt2 = FP_TO_INT64_OVERFLOW; } update_fcr31(env); return dt2; @@ -2848,7 +2844,7 @@ uint32_t helper_float_floorw_d(CPUMIPSState *env, uint64_t fdt0) RESTORE_ROUNDING_MODE; if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - wt2 = FLOAT_SNAN32; + wt2 = FP_TO_INT32_OVERFLOW; } update_fcr31(env); return wt2; @@ -2863,7 +2859,7 @@ uint32_t helper_float_floorw_s(CPUMIPSState *env, uint32_t fst0) RESTORE_ROUNDING_MODE; if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { - wt2 = FLOAT_SNAN32; + wt2 = FP_TO_INT32_OVERFLOW; } update_fcr31(env); return wt2; @@ -2897,7 +2893,7 @@ uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t fdt2; - fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status); + fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status); update_fcr31(env); return fdt2; } @@ -2906,7 +2902,7 @@ uint32_t helper_float_recip_s(CPUMIPSState *env, uint32_t fst0) { uint32_t fst2; - fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status); + fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status); update_fcr31(env); return fst2; } @@ -2916,7 +2912,7 @@ uint64_t helper_float_rsqrt_d(CPUMIPSState *env, uint64_t fdt0) uint64_t fdt2; fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status); - fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status); + fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status); update_fcr31(env); return fdt2; } @@ -2926,7 +2922,7 @@ uint32_t helper_float_rsqrt_s(CPUMIPSState *env, uint32_t fst0) uint32_t fst2; fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status); - fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status); + fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status); update_fcr31(env); return fst2; } @@ -2935,7 +2931,7 @@ uint64_t helper_float_recip1_d(CPUMIPSState *env, uint64_t fdt0) { uint64_t fdt2; - fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status); + fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status); update_fcr31(env); return fdt2; } @@ -2944,7 +2940,7 @@ uint32_t helper_float_recip1_s(CPUMIPSState *env, uint32_t fst0) { uint32_t fst2; - fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status); + fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status); update_fcr31(env); return fst2; } @@ -2954,8 +2950,8 @@ uint64_t helper_float_recip1_ps(CPUMIPSState *env, uint64_t fdt0) uint32_t fst2; uint32_t fsth2; - fst2 = float32_div(FLOAT_ONE32, fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); - fsth2 = float32_div(FLOAT_ONE32, fdt0 >> 32, &env->active_fpu.fp_status); + fst2 = float32_div(float32_one, fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); + fsth2 = float32_div(float32_one, fdt0 >> 32, &env->active_fpu.fp_status); update_fcr31(env); return ((uint64_t)fsth2 << 32) | fst2; } @@ -2965,7 +2961,7 @@ uint64_t helper_float_rsqrt1_d(CPUMIPSState *env, uint64_t fdt0) uint64_t fdt2; fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status); - fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status); + fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status); update_fcr31(env); return fdt2; } @@ -2975,7 +2971,7 @@ uint32_t helper_float_rsqrt1_s(CPUMIPSState *env, uint32_t fst0) uint32_t fst2; fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status); - fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status); + fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status); update_fcr31(env); return fst2; } @@ -2987,8 +2983,8 @@ uint64_t helper_float_rsqrt1_ps(CPUMIPSState *env, uint64_t fdt0) fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status); - fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status); - fsth2 = float32_div(FLOAT_ONE32, fsth2, &env->active_fpu.fp_status); + fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status); + fsth2 = float32_div(float32_one, fsth2, &env->active_fpu.fp_status); update_fcr31(env); return ((uint64_t)fsth2 << 32) | fst2; } @@ -3090,7 +3086,7 @@ FLOAT_FMA(nmsub, float_muladd_negate_result | float_muladd_negate_c) uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) { fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status); - fdt2 = float64_chs(float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status)); + fdt2 = float64_chs(float64_sub(fdt2, float64_one, &env->active_fpu.fp_status)); update_fcr31(env); return fdt2; } @@ -3098,7 +3094,7 @@ uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) uint32_t helper_float_recip2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2) { fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); - fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status)); + fst2 = float32_chs(float32_sub(fst2, float32_one, &env->active_fpu.fp_status)); update_fcr31(env); return fst2; } @@ -3112,8 +3108,8 @@ uint64_t helper_float_recip2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status); - fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status)); - fsth2 = float32_chs(float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status)); + fst2 = float32_chs(float32_sub(fst2, float32_one, &env->active_fpu.fp_status)); + fsth2 = float32_chs(float32_sub(fsth2, float32_one, &env->active_fpu.fp_status)); update_fcr31(env); return ((uint64_t)fsth2 << 32) | fst2; } @@ -3121,7 +3117,7 @@ uint64_t helper_float_recip2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) uint64_t helper_float_rsqrt2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) { fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status); - fdt2 = float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status); + fdt2 = float64_sub(fdt2, float64_one, &env->active_fpu.fp_status); fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->active_fpu.fp_status)); update_fcr31(env); return fdt2; @@ -3130,7 +3126,7 @@ uint64_t helper_float_rsqrt2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) uint32_t helper_float_rsqrt2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2) { fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); - fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status); + fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status); fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status)); update_fcr31(env); return fst2; @@ -3145,8 +3141,8 @@ uint64_t helper_float_rsqrt2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status); - fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status); - fsth2 = float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status); + fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status); + fsth2 = float32_sub(fsth2, float32_one, &env->active_fpu.fp_status); fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status)); fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->active_fpu.fp_status)); update_fcr31(env); From 5f7319cd84ecb82f65c67dd1033ec27647fcb7db Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 28 Oct 2012 19:34:03 +0100 Subject: [PATCH 1421/2270] target-mips: restore CPU state after an FPU exception Rework *raise_exception*() functions so that they can be called from other helpers, passing the return address as an argument. Use do_raise_exception() function in update_fcr31() to correctly restore the CPU state after an FPU exception. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 191 +++++++++++++++++++++------------------- 1 file changed, 98 insertions(+), 93 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 2f9ec5d26e..a7509ca885 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -33,35 +33,50 @@ static inline void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global); /*****************************************************************************/ /* Exceptions processing helpers */ -void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception, - int error_code) +static inline void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, + uint32_t exception, + int error_code, + uintptr_t pc) { + TranslationBlock *tb; #if 1 if (exception < 0x100) qemu_log("%s: %d %d\n", __func__, exception, error_code); #endif env->exception_index = exception; env->error_code = error_code; + + if (pc) { + /* now we have a real cpu fault */ + tb = tb_find_pc(pc); + if (tb) { + /* the PC is inside the translated code. It means that we have + a virtual CPU fault */ + cpu_restore_state(tb, env, pc); + } + } + cpu_loop_exit(env); } +static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env, + uint32_t exception, + uintptr_t pc) +{ + do_raise_exception_err(env, exception, 0, pc); +} + +void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception, + int error_code) +{ + do_raise_exception_err(env, exception, error_code, 0); +} + void helper_raise_exception(CPUMIPSState *env, uint32_t exception) { - helper_raise_exception_err(env, exception, 0); + do_raise_exception(env, exception, 0); } -#if !defined(CONFIG_USER_ONLY) -static void do_restore_state(CPUMIPSState *env, uintptr_t pc) -{ - TranslationBlock *tb; - - tb = tb_find_pc (pc); - if (tb) { - cpu_restore_state(tb, env, pc); - } -} -#endif - #if defined(CONFIG_USER_ONLY) #define HELPER_LD(name, insn, type) \ static inline type do_##name(CPUMIPSState *env, target_ulong addr, \ @@ -2295,28 +2310,18 @@ static void do_unaligned_access(CPUMIPSState *env, target_ulong addr, int is_write, int is_user, uintptr_t retaddr) { env->CP0_BadVAddr = addr; - do_restore_state(env, retaddr); - helper_raise_exception(env, (is_write == 1) ? EXCP_AdES : EXCP_AdEL); + do_raise_exception(env, (is_write == 1) ? EXCP_AdES : EXCP_AdEL, retaddr); } void tlb_fill(CPUMIPSState *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { - TranslationBlock *tb; int ret; ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx); if (ret) { - if (retaddr) { - /* now we have a real cpu fault */ - tb = tb_find_pc(retaddr); - if (tb) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, retaddr); - } - } - helper_raise_exception_err(env, env->exception_index, env->error_code); + do_raise_exception_err(env, env->exception_index, + env->error_code, retaddr); } } @@ -2410,7 +2415,7 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t reg) RESTORE_FLUSH_MODE; set_float_exception_flags(0, &env->active_fpu.fp_status); if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31)) - helper_raise_exception(env, EXCP_FPE); + do_raise_exception(env, EXCP_FPE, GETPC()); } static inline int ieee_ex_to_mips(int xcpt) @@ -2436,7 +2441,7 @@ static inline int ieee_ex_to_mips(int xcpt) return ret; } -static inline void update_fcr31(CPUMIPSState *env) +static inline void update_fcr31(CPUMIPSState *env, uintptr_t pc) { int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->active_fpu.fp_status)); @@ -2446,7 +2451,7 @@ static inline void update_fcr31(CPUMIPSState *env) set_float_exception_flags(0, &env->active_fpu.fp_status); if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp) { - helper_raise_exception(env, EXCP_FPE); + do_raise_exception(env, EXCP_FPE, pc); } else { UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp); } @@ -2462,14 +2467,14 @@ static inline void update_fcr31(CPUMIPSState *env) uint64_t helper_float_sqrt_d(CPUMIPSState *env, uint64_t fdt0) { fdt0 = float64_sqrt(fdt0, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return fdt0; } uint32_t helper_float_sqrt_s(CPUMIPSState *env, uint32_t fst0) { fst0 = float32_sqrt(fst0, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return fst0; } @@ -2478,7 +2483,7 @@ uint64_t helper_float_cvtd_s(CPUMIPSState *env, uint32_t fst0) uint64_t fdt2; fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return fdt2; } @@ -2487,7 +2492,7 @@ uint64_t helper_float_cvtd_w(CPUMIPSState *env, uint32_t wt0) uint64_t fdt2; fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return fdt2; } @@ -2496,7 +2501,7 @@ uint64_t helper_float_cvtd_l(CPUMIPSState *env, uint64_t dt0) uint64_t fdt2; fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return fdt2; } @@ -2509,7 +2514,7 @@ uint64_t helper_float_cvtl_d(CPUMIPSState *env, uint64_t fdt0) & (float_flag_invalid | float_flag_overflow)) { dt2 = FP_TO_INT64_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return dt2; } @@ -2522,7 +2527,7 @@ uint64_t helper_float_cvtl_s(CPUMIPSState *env, uint32_t fst0) & (float_flag_invalid | float_flag_overflow)) { dt2 = FP_TO_INT64_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return dt2; } @@ -2533,7 +2538,7 @@ uint64_t helper_float_cvtps_pw(CPUMIPSState *env, uint64_t dt0) fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return ((uint64_t)fsth2 << 32) | fst2; } @@ -2557,7 +2562,7 @@ uint64_t helper_float_cvtpw_ps(CPUMIPSState *env, uint64_t fdt0) } set_float_exception_flags(excp | excph, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return ((uint64_t)wth2 << 32) | wt2; } @@ -2567,7 +2572,7 @@ uint32_t helper_float_cvts_d(CPUMIPSState *env, uint64_t fdt0) uint32_t fst2; fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return fst2; } @@ -2576,7 +2581,7 @@ uint32_t helper_float_cvts_w(CPUMIPSState *env, uint32_t wt0) uint32_t fst2; fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return fst2; } @@ -2585,7 +2590,7 @@ uint32_t helper_float_cvts_l(CPUMIPSState *env, uint64_t dt0) uint32_t fst2; fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return fst2; } @@ -2594,7 +2599,7 @@ uint32_t helper_float_cvts_pl(CPUMIPSState *env, uint32_t wt0) uint32_t wt2; wt2 = wt0; - update_fcr31(env); + update_fcr31(env, GETPC()); return wt2; } @@ -2603,7 +2608,7 @@ uint32_t helper_float_cvts_pu(CPUMIPSState *env, uint32_t wth0) uint32_t wt2; wt2 = wth0; - update_fcr31(env); + update_fcr31(env, GETPC()); return wt2; } @@ -2612,7 +2617,7 @@ uint32_t helper_float_cvtw_s(CPUMIPSState *env, uint32_t fst0) uint32_t wt2; wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { wt2 = FP_TO_INT32_OVERFLOW; @@ -2629,7 +2634,7 @@ uint32_t helper_float_cvtw_d(CPUMIPSState *env, uint64_t fdt0) & (float_flag_invalid | float_flag_overflow)) { wt2 = FP_TO_INT32_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return wt2; } @@ -2644,7 +2649,7 @@ uint64_t helper_float_roundl_d(CPUMIPSState *env, uint64_t fdt0) & (float_flag_invalid | float_flag_overflow)) { dt2 = FP_TO_INT64_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return dt2; } @@ -2659,7 +2664,7 @@ uint64_t helper_float_roundl_s(CPUMIPSState *env, uint32_t fst0) & (float_flag_invalid | float_flag_overflow)) { dt2 = FP_TO_INT64_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return dt2; } @@ -2674,7 +2679,7 @@ uint32_t helper_float_roundw_d(CPUMIPSState *env, uint64_t fdt0) & (float_flag_invalid | float_flag_overflow)) { wt2 = FP_TO_INT32_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return wt2; } @@ -2689,7 +2694,7 @@ uint32_t helper_float_roundw_s(CPUMIPSState *env, uint32_t fst0) & (float_flag_invalid | float_flag_overflow)) { wt2 = FP_TO_INT32_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return wt2; } @@ -2702,7 +2707,7 @@ uint64_t helper_float_truncl_d(CPUMIPSState *env, uint64_t fdt0) & (float_flag_invalid | float_flag_overflow)) { dt2 = FP_TO_INT64_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return dt2; } @@ -2715,7 +2720,7 @@ uint64_t helper_float_truncl_s(CPUMIPSState *env, uint32_t fst0) & (float_flag_invalid | float_flag_overflow)) { dt2 = FP_TO_INT64_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return dt2; } @@ -2728,7 +2733,7 @@ uint32_t helper_float_truncw_d(CPUMIPSState *env, uint64_t fdt0) & (float_flag_invalid | float_flag_overflow)) { wt2 = FP_TO_INT32_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return wt2; } @@ -2741,7 +2746,7 @@ uint32_t helper_float_truncw_s(CPUMIPSState *env, uint32_t fst0) & (float_flag_invalid | float_flag_overflow)) { wt2 = FP_TO_INT32_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return wt2; } @@ -2756,7 +2761,7 @@ uint64_t helper_float_ceill_d(CPUMIPSState *env, uint64_t fdt0) & (float_flag_invalid | float_flag_overflow)) { dt2 = FP_TO_INT64_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return dt2; } @@ -2771,7 +2776,7 @@ uint64_t helper_float_ceill_s(CPUMIPSState *env, uint32_t fst0) & (float_flag_invalid | float_flag_overflow)) { dt2 = FP_TO_INT64_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return dt2; } @@ -2786,7 +2791,7 @@ uint32_t helper_float_ceilw_d(CPUMIPSState *env, uint64_t fdt0) & (float_flag_invalid | float_flag_overflow)) { wt2 = FP_TO_INT32_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return wt2; } @@ -2801,7 +2806,7 @@ uint32_t helper_float_ceilw_s(CPUMIPSState *env, uint32_t fst0) & (float_flag_invalid | float_flag_overflow)) { wt2 = FP_TO_INT32_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return wt2; } @@ -2816,7 +2821,7 @@ uint64_t helper_float_floorl_d(CPUMIPSState *env, uint64_t fdt0) & (float_flag_invalid | float_flag_overflow)) { dt2 = FP_TO_INT64_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return dt2; } @@ -2831,7 +2836,7 @@ uint64_t helper_float_floorl_s(CPUMIPSState *env, uint32_t fst0) & (float_flag_invalid | float_flag_overflow)) { dt2 = FP_TO_INT64_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return dt2; } @@ -2846,7 +2851,7 @@ uint32_t helper_float_floorw_d(CPUMIPSState *env, uint64_t fdt0) & (float_flag_invalid | float_flag_overflow)) { wt2 = FP_TO_INT32_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return wt2; } @@ -2861,7 +2866,7 @@ uint32_t helper_float_floorw_s(CPUMIPSState *env, uint32_t fst0) & (float_flag_invalid | float_flag_overflow)) { wt2 = FP_TO_INT32_OVERFLOW; } - update_fcr31(env); + update_fcr31(env, GETPC()); return wt2; } @@ -2894,7 +2899,7 @@ uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0) uint64_t fdt2; fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return fdt2; } @@ -2903,7 +2908,7 @@ uint32_t helper_float_recip_s(CPUMIPSState *env, uint32_t fst0) uint32_t fst2; fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return fst2; } @@ -2913,7 +2918,7 @@ uint64_t helper_float_rsqrt_d(CPUMIPSState *env, uint64_t fdt0) fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status); fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return fdt2; } @@ -2923,7 +2928,7 @@ uint32_t helper_float_rsqrt_s(CPUMIPSState *env, uint32_t fst0) fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status); fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return fst2; } @@ -2932,7 +2937,7 @@ uint64_t helper_float_recip1_d(CPUMIPSState *env, uint64_t fdt0) uint64_t fdt2; fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return fdt2; } @@ -2941,7 +2946,7 @@ uint32_t helper_float_recip1_s(CPUMIPSState *env, uint32_t fst0) uint32_t fst2; fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return fst2; } @@ -2952,7 +2957,7 @@ uint64_t helper_float_recip1_ps(CPUMIPSState *env, uint64_t fdt0) fst2 = float32_div(float32_one, fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); fsth2 = float32_div(float32_one, fdt0 >> 32, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return ((uint64_t)fsth2 << 32) | fst2; } @@ -2962,7 +2967,7 @@ uint64_t helper_float_rsqrt1_d(CPUMIPSState *env, uint64_t fdt0) fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status); fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return fdt2; } @@ -2972,7 +2977,7 @@ uint32_t helper_float_rsqrt1_s(CPUMIPSState *env, uint32_t fst0) fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status); fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return fst2; } @@ -2985,7 +2990,7 @@ uint64_t helper_float_rsqrt1_ps(CPUMIPSState *env, uint64_t fdt0) fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status); fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status); fsth2 = float32_div(float32_one, fsth2, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return ((uint64_t)fsth2 << 32) | fst2; } @@ -2999,7 +3004,7 @@ uint64_t helper_float_ ## name ## _d(CPUMIPSState *env, \ uint64_t dt2; \ \ dt2 = float64_ ## name (fdt0, fdt1, &env->active_fpu.fp_status); \ - update_fcr31(env); \ + update_fcr31(env, GETPC()); \ return dt2; \ } \ \ @@ -3009,7 +3014,7 @@ uint32_t helper_float_ ## name ## _s(CPUMIPSState *env, \ uint32_t wt2; \ \ wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \ - update_fcr31(env); \ + update_fcr31(env, GETPC()); \ return wt2; \ } \ \ @@ -3026,7 +3031,7 @@ uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \ \ wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \ wth2 = float32_ ## name (fsth0, fsth1, &env->active_fpu.fp_status); \ - update_fcr31(env); \ + update_fcr31(env, GETPC()); \ return ((uint64_t)wth2 << 32) | wt2; \ } @@ -3044,7 +3049,7 @@ uint64_t helper_float_ ## name ## _d(CPUMIPSState *env, \ { \ fdt0 = float64_muladd(fdt0, fdt1, fdt2, type, \ &env->active_fpu.fp_status); \ - update_fcr31(env); \ + update_fcr31(env, GETPC()); \ return fdt0; \ } \ \ @@ -3054,7 +3059,7 @@ uint32_t helper_float_ ## name ## _s(CPUMIPSState *env, \ { \ fst0 = float32_muladd(fst0, fst1, fst2, type, \ &env->active_fpu.fp_status); \ - update_fcr31(env); \ + update_fcr31(env, GETPC()); \ return fst0; \ } \ \ @@ -3073,7 +3078,7 @@ uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \ &env->active_fpu.fp_status); \ fsth0 = float32_muladd(fsth0, fsth1, fsth2, type, \ &env->active_fpu.fp_status); \ - update_fcr31(env); \ + update_fcr31(env, GETPC()); \ return ((uint64_t)fsth0 << 32) | fst0; \ } FLOAT_FMA(madd, 0) @@ -3087,7 +3092,7 @@ uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) { fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status); fdt2 = float64_chs(float64_sub(fdt2, float64_one, &env->active_fpu.fp_status)); - update_fcr31(env); + update_fcr31(env, GETPC()); return fdt2; } @@ -3095,7 +3100,7 @@ uint32_t helper_float_recip2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2) { fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); fst2 = float32_chs(float32_sub(fst2, float32_one, &env->active_fpu.fp_status)); - update_fcr31(env); + update_fcr31(env, GETPC()); return fst2; } @@ -3110,7 +3115,7 @@ uint64_t helper_float_recip2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status); fst2 = float32_chs(float32_sub(fst2, float32_one, &env->active_fpu.fp_status)); fsth2 = float32_chs(float32_sub(fsth2, float32_one, &env->active_fpu.fp_status)); - update_fcr31(env); + update_fcr31(env, GETPC()); return ((uint64_t)fsth2 << 32) | fst2; } @@ -3119,7 +3124,7 @@ uint64_t helper_float_rsqrt2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status); fdt2 = float64_sub(fdt2, float64_one, &env->active_fpu.fp_status); fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->active_fpu.fp_status)); - update_fcr31(env); + update_fcr31(env, GETPC()); return fdt2; } @@ -3128,7 +3133,7 @@ uint32_t helper_float_rsqrt2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2) fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status); fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status)); - update_fcr31(env); + update_fcr31(env, GETPC()); return fst2; } @@ -3145,7 +3150,7 @@ uint64_t helper_float_rsqrt2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) fsth2 = float32_sub(fsth2, float32_one, &env->active_fpu.fp_status); fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status)); fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->active_fpu.fp_status)); - update_fcr31(env); + update_fcr31(env, GETPC()); return ((uint64_t)fsth2 << 32) | fst2; } @@ -3160,7 +3165,7 @@ uint64_t helper_float_addr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1) fst2 = float32_add (fst0, fsth0, &env->active_fpu.fp_status); fsth2 = float32_add (fst1, fsth1, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return ((uint64_t)fsth2 << 32) | fst2; } @@ -3175,7 +3180,7 @@ uint64_t helper_float_mulr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1) fst2 = float32_mul (fst0, fsth0, &env->active_fpu.fp_status); fsth2 = float32_mul (fst1, fsth1, &env->active_fpu.fp_status); - update_fcr31(env); + update_fcr31(env, GETPC()); return ((uint64_t)fsth2 << 32) | fst2; } @@ -3186,7 +3191,7 @@ void helper_cmp_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \ { \ int c; \ c = cond; \ - update_fcr31(env); \ + update_fcr31(env, GETPC()); \ if (c) \ SET_FP_COND(cc, env->active_fpu); \ else \ @@ -3199,7 +3204,7 @@ void helper_cmpabs_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \ fdt0 = float64_abs(fdt0); \ fdt1 = float64_abs(fdt1); \ c = cond; \ - update_fcr31(env); \ + update_fcr31(env, GETPC()); \ if (c) \ SET_FP_COND(cc, env->active_fpu); \ else \ @@ -3233,7 +3238,7 @@ void helper_cmp_s_ ## op(CPUMIPSState *env, uint32_t fst0, \ { \ int c; \ c = cond; \ - update_fcr31(env); \ + update_fcr31(env, GETPC()); \ if (c) \ SET_FP_COND(cc, env->active_fpu); \ else \ @@ -3246,7 +3251,7 @@ void helper_cmpabs_s_ ## op(CPUMIPSState *env, uint32_t fst0, \ fst0 = float32_abs(fst0); \ fst1 = float32_abs(fst1); \ c = cond; \ - update_fcr31(env); \ + update_fcr31(env, GETPC()); \ if (c) \ SET_FP_COND(cc, env->active_fpu); \ else \ @@ -3286,7 +3291,7 @@ void helper_cmp_ps_ ## op(CPUMIPSState *env, uint64_t fdt0, \ fsth1 = fdt1 >> 32; \ cl = condl; \ ch = condh; \ - update_fcr31(env); \ + update_fcr31(env, GETPC()); \ if (cl) \ SET_FP_COND(cc, env->active_fpu); \ else \ @@ -3307,7 +3312,7 @@ void helper_cmpabs_ps_ ## op(CPUMIPSState *env, uint64_t fdt0, \ fsth1 = float32_abs(fdt1 >> 32); \ cl = condl; \ ch = condh; \ - update_fcr31(env); \ + update_fcr31(env, GETPC()); \ if (cl) \ SET_FP_COND(cc, env->active_fpu); \ else \ From 2910c6cbaacf7b9d54be3ce8ca03d68db45767bb Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:20 +0200 Subject: [PATCH 1422/2270] target-mips: cleanup load/store operations Load/store operations use macros for historical reasons. Now that there is no point in keeping them, replace them by direct calls to qemu_ld/st. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 99 +++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 64 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index e7184715bf..79c2e92e9d 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1484,35 +1484,6 @@ FOP_CONDS(abs, 1, ps, FMT_PS, 64) #undef gen_ldcmp_fpr64 /* load/store instructions. */ -#define OP_LD(insn,fname) \ -static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \ -{ \ - tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \ -} -OP_LD(lb,ld8s); -OP_LD(lbu,ld8u); -OP_LD(lh,ld16s); -OP_LD(lhu,ld16u); -OP_LD(lw,ld32s); -#if defined(TARGET_MIPS64) -OP_LD(lwu,ld32u); -OP_LD(ld,ld64); -#endif -#undef OP_LD - -#define OP_ST(insn,fname) \ -static inline void op_st_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \ -{ \ - tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \ -} -OP_ST(sb,st8); -OP_ST(sh,st16); -OP_ST(sw,st32); -#if defined(TARGET_MIPS64) -OP_ST(sd,st64); -#endif -#undef OP_ST - #ifdef CONFIG_USER_ONLY #define OP_LD_ATOMIC(insn,fname) \ static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \ @@ -1626,12 +1597,12 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, switch (opc) { #if defined(TARGET_MIPS64) case OPC_LWU: - op_ld_lwu(t0, t0, ctx); + tcg_gen_qemu_ld32u(t0, t0, ctx->mem_idx); gen_store_gpr(t0, rt); opn = "lwu"; break; case OPC_LD: - op_ld_ld(t0, t0, ctx); + tcg_gen_qemu_ld64(t0, t0, ctx->mem_idx); gen_store_gpr(t0, rt); opn = "ld"; break; @@ -1658,7 +1629,7 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, case OPC_LDPC: tcg_gen_movi_tl(t1, pc_relative_pc(ctx)); gen_op_addr_add(ctx, t0, t0, t1); - op_ld_ld(t0, t0, ctx); + tcg_gen_qemu_ld64(t0, t0, ctx->mem_idx); gen_store_gpr(t0, rt); opn = "ldpc"; break; @@ -1666,32 +1637,32 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, case OPC_LWPC: tcg_gen_movi_tl(t1, pc_relative_pc(ctx)); gen_op_addr_add(ctx, t0, t0, t1); - op_ld_lw(t0, t0, ctx); + tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx); gen_store_gpr(t0, rt); opn = "lwpc"; break; case OPC_LW: - op_ld_lw(t0, t0, ctx); + tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx); gen_store_gpr(t0, rt); opn = "lw"; break; case OPC_LH: - op_ld_lh(t0, t0, ctx); + tcg_gen_qemu_ld16s(t0, t0, ctx->mem_idx); gen_store_gpr(t0, rt); opn = "lh"; break; case OPC_LHU: - op_ld_lhu(t0, t0, ctx); + tcg_gen_qemu_ld16u(t0, t0, ctx->mem_idx); gen_store_gpr(t0, rt); opn = "lhu"; break; case OPC_LB: - op_ld_lb(t0, t0, ctx); + tcg_gen_qemu_ld8s(t0, t0, ctx->mem_idx); gen_store_gpr(t0, rt); opn = "lb"; break; case OPC_LBU: - op_ld_lbu(t0, t0, ctx); + tcg_gen_qemu_ld8u(t0, t0, ctx->mem_idx); gen_store_gpr(t0, rt); opn = "lbu"; break; @@ -1735,7 +1706,7 @@ static void gen_st (DisasContext *ctx, uint32_t opc, int rt, switch (opc) { #if defined(TARGET_MIPS64) case OPC_SD: - op_st_sd(t1, t0, ctx); + tcg_gen_qemu_st64(t1, t0, ctx->mem_idx); opn = "sd"; break; case OPC_SDL: @@ -1750,15 +1721,15 @@ static void gen_st (DisasContext *ctx, uint32_t opc, int rt, break; #endif case OPC_SW: - op_st_sw(t1, t0, ctx); + tcg_gen_qemu_st32(t1, t0, ctx->mem_idx); opn = "sw"; break; case OPC_SH: - op_st_sh(t1, t0, ctx); + tcg_gen_qemu_st16(t1, t0, ctx->mem_idx); opn = "sh"; break; case OPC_SB: - op_st_sb(t1, t0, ctx); + tcg_gen_qemu_st8(t1, t0, ctx->mem_idx); opn = "sb"; break; case OPC_SWL: @@ -9320,22 +9291,22 @@ static void gen_mips16_save (DisasContext *ctx, case 4: gen_base_offset_addr(ctx, t0, 29, 12); gen_load_gpr(t1, 7); - op_st_sw(t1, t0, ctx); + tcg_gen_qemu_st32(t1, t0, ctx->mem_idx); /* Fall through */ case 3: gen_base_offset_addr(ctx, t0, 29, 8); gen_load_gpr(t1, 6); - op_st_sw(t1, t0, ctx); + tcg_gen_qemu_st32(t1, t0, ctx->mem_idx); /* Fall through */ case 2: gen_base_offset_addr(ctx, t0, 29, 4); gen_load_gpr(t1, 5); - op_st_sw(t1, t0, ctx); + tcg_gen_qemu_st32(t1, t0, ctx->mem_idx); /* Fall through */ case 1: gen_base_offset_addr(ctx, t0, 29, 0); gen_load_gpr(t1, 4); - op_st_sw(t1, t0, ctx); + tcg_gen_qemu_st32(t1, t0, ctx->mem_idx); } gen_load_gpr(t0, 29); @@ -9343,7 +9314,7 @@ static void gen_mips16_save (DisasContext *ctx, #define DECR_AND_STORE(reg) do { \ tcg_gen_subi_tl(t0, t0, 4); \ gen_load_gpr(t1, reg); \ - op_st_sw(t1, t0, ctx); \ + tcg_gen_qemu_st32(t1, t0, ctx->mem_idx); \ } while (0) if (do_ra) { @@ -9441,10 +9412,10 @@ static void gen_mips16_restore (DisasContext *ctx, tcg_gen_addi_tl(t0, cpu_gpr[29], framesize); -#define DECR_AND_LOAD(reg) do { \ - tcg_gen_subi_tl(t0, t0, 4); \ - op_ld_lw(t1, t0, ctx); \ - gen_store_gpr(t1, reg); \ +#define DECR_AND_LOAD(reg) do { \ + tcg_gen_subi_tl(t0, t0, 4); \ + tcg_gen_qemu_ld32u(t1, t0, ctx->mem_idx); \ + gen_store_gpr(t1, reg); \ } while (0) if (do_ra) { @@ -10950,7 +10921,7 @@ static void gen_ldxs (DisasContext *ctx, int base, int index, int rd) gen_op_addr_add(ctx, t0, t1, t0); } - op_ld_lw(t1, t0, ctx); + tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx); gen_store_gpr(t1, rd); tcg_temp_free(t0); @@ -10979,21 +10950,21 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, generate_exception(ctx, EXCP_RI); return; } - op_ld_lw(t1, t0, ctx); + tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx); gen_store_gpr(t1, rd); tcg_gen_movi_tl(t1, 4); gen_op_addr_add(ctx, t0, t0, t1); - op_ld_lw(t1, t0, ctx); + tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx); gen_store_gpr(t1, rd+1); opn = "lwp"; break; case SWP: gen_load_gpr(t1, rd); - op_st_sw(t1, t0, ctx); + tcg_gen_qemu_st32(t1, t0, ctx->mem_idx); tcg_gen_movi_tl(t1, 4); gen_op_addr_add(ctx, t0, t0, t1); gen_load_gpr(t1, rd+1); - op_st_sw(t1, t0, ctx); + tcg_gen_qemu_st32(t1, t0, ctx->mem_idx); opn = "swp"; break; #ifdef TARGET_MIPS64 @@ -11002,21 +10973,21 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, generate_exception(ctx, EXCP_RI); return; } - op_ld_ld(t1, t0, ctx); + tcg_gen_qemu_ld64(t1, t0, ctx->mem_idx); gen_store_gpr(t1, rd); tcg_gen_movi_tl(t1, 8); gen_op_addr_add(ctx, t0, t0, t1); - op_ld_ld(t1, t0, ctx); + tcg_gen_qemu_ld64(t1, t0, ctx->mem_idx); gen_store_gpr(t1, rd+1); opn = "ldp"; break; case SDP: gen_load_gpr(t1, rd); - op_st_sd(t1, t0, ctx); + tcg_gen_qemu_st64(t1, t0, ctx->mem_idx); tcg_gen_movi_tl(t1, 8); gen_op_addr_add(ctx, t0, t0, t1); gen_load_gpr(t1, rd+1); - op_st_sd(t1, t0, ctx); + tcg_gen_qemu_st64(t1, t0, ctx->mem_idx); opn = "sdp"; break; #endif @@ -12654,23 +12625,23 @@ static void gen_mipsdsp_ld(CPUMIPSState *env, DisasContext *ctx, uint32_t opc, switch (opc) { case OPC_LBUX: - op_ld_lbu(t0, t0, ctx); + tcg_gen_qemu_ld8u(t0, t0, ctx->mem_idx); gen_store_gpr(t0, rd); opn = "lbux"; break; case OPC_LHX: - op_ld_lh(t0, t0, ctx); + tcg_gen_qemu_ld16s(t0, t0, ctx->mem_idx); gen_store_gpr(t0, rd); opn = "lhx"; break; case OPC_LWX: - op_ld_lw(t0, t0, ctx); + tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx); gen_store_gpr(t0, rd); opn = "lwx"; break; #if defined(TARGET_MIPS64) case OPC_LDX: - op_ld_ld(t0, t0, ctx); + tcg_gen_qemu_ld64(t0, t0, ctx->mem_idx); gen_store_gpr(t0, rd); opn = "ldx"; break; From 3cee3050ce2d79837fa286a730a54e2a8b9dc5dc Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:20 +0200 Subject: [PATCH 1423/2270] target-mips: optimize load operations Only allocate t1 when needed. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 79c2e92e9d..a48a475806 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1591,7 +1591,6 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, } t0 = tcg_temp_new(); - t1 = tcg_temp_new(); gen_base_offset_addr(ctx, t0, base, offset); switch (opc) { @@ -1614,29 +1613,35 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, break; case OPC_LDL: save_cpu_state(ctx, 1); + t1 = tcg_temp_new(); gen_load_gpr(t1, rt); gen_helper_1e2i(ldl, t1, t1, t0, ctx->mem_idx); gen_store_gpr(t1, rt); + tcg_temp_free(t1); opn = "ldl"; break; case OPC_LDR: save_cpu_state(ctx, 1); + t1 = tcg_temp_new(); gen_load_gpr(t1, rt); gen_helper_1e2i(ldr, t1, t1, t0, ctx->mem_idx); gen_store_gpr(t1, rt); + tcg_temp_free(t1); opn = "ldr"; break; case OPC_LDPC: - tcg_gen_movi_tl(t1, pc_relative_pc(ctx)); + t1 = tcg_const_tl(pc_relative_pc(ctx)); gen_op_addr_add(ctx, t0, t0, t1); + tcg_temp_free(t1); tcg_gen_qemu_ld64(t0, t0, ctx->mem_idx); gen_store_gpr(t0, rt); opn = "ldpc"; break; #endif case OPC_LWPC: - tcg_gen_movi_tl(t1, pc_relative_pc(ctx)); + t1 = tcg_const_tl(pc_relative_pc(ctx)); gen_op_addr_add(ctx, t0, t0, t1); + tcg_temp_free(t1); tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx); gen_store_gpr(t0, rt); opn = "lwpc"; @@ -1668,16 +1673,20 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, break; case OPC_LWL: save_cpu_state(ctx, 1); + t1 = tcg_temp_new(); gen_load_gpr(t1, rt); gen_helper_1e2i(lwl, t1, t1, t0, ctx->mem_idx); gen_store_gpr(t1, rt); + tcg_temp_free(t1); opn = "lwl"; break; case OPC_LWR: save_cpu_state(ctx, 1); + t1 = tcg_temp_new(); gen_load_gpr(t1, rt); gen_helper_1e2i(lwr, t1, t1, t0, ctx->mem_idx); gen_store_gpr(t1, rt); + tcg_temp_free(t1); opn = "lwr"; break; case OPC_LL: @@ -1690,7 +1699,6 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); tcg_temp_free(t0); - tcg_temp_free(t1); } /* Store */ From 18bba4dc781a273c2c1ff5baec2909c214e2e0fa Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:20 +0200 Subject: [PATCH 1424/2270] target-mips: simplify load/store microMIPS helpers load/store microMIPS helpers are reinventing the wheel. Call do_lw, do_ll, do_sw and do_sl instead of using a macro calling the cpu_* load/store functions. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 73 +++++------------------------------------ 1 file changed, 9 insertions(+), 64 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index a7509ca885..78497d9a87 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -594,32 +594,19 @@ void helper_lwm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, { target_ulong base_reglist = reglist & 0xf; target_ulong do_r31 = reglist & 0x10; -#ifdef CONFIG_USER_ONLY -#undef ldfun -#define ldfun(env, addr) ldl_raw(addr) -#else - uint32_t (*ldfun)(CPUMIPSState *env, target_ulong); - - switch (mem_idx) - { - case 0: ldfun = cpu_ldl_kernel; break; - case 1: ldfun = cpu_ldl_super; break; - default: - case 2: ldfun = cpu_ldl_user; break; - } -#endif if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) { target_ulong i; for (i = 0; i < base_reglist; i++) { - env->active_tc.gpr[multiple_regs[i]] = (target_long)ldfun(env, addr); + env->active_tc.gpr[multiple_regs[i]] = + (target_long)do_lw(env, addr, mem_idx); addr += 4; } } if (do_r31) { - env->active_tc.gpr[31] = (target_long)ldfun(env, addr); + env->active_tc.gpr[31] = (target_long)do_lw(env, addr, mem_idx); } } @@ -628,32 +615,18 @@ void helper_swm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, { target_ulong base_reglist = reglist & 0xf; target_ulong do_r31 = reglist & 0x10; -#ifdef CONFIG_USER_ONLY -#undef stfun -#define stfun(env, addr, val) stl_raw(addr, val) -#else - void (*stfun)(CPUMIPSState *env, target_ulong, uint32_t); - - switch (mem_idx) - { - case 0: stfun = cpu_stl_kernel; break; - case 1: stfun = cpu_stl_super; break; - default: - case 2: stfun = cpu_stl_user; break; - } -#endif if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) { target_ulong i; for (i = 0; i < base_reglist; i++) { - stfun(env, addr, env->active_tc.gpr[multiple_regs[i]]); + do_sw(env, addr, env->active_tc.gpr[multiple_regs[i]], mem_idx); addr += 4; } } if (do_r31) { - stfun(env, addr, env->active_tc.gpr[31]); + do_sw(env, addr, env->active_tc.gpr[31], mem_idx); } } @@ -663,32 +636,18 @@ void helper_ldm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, { target_ulong base_reglist = reglist & 0xf; target_ulong do_r31 = reglist & 0x10; -#ifdef CONFIG_USER_ONLY -#undef ldfun -#define ldfun(env, addr) ldq_raw(addr) -#else - uint64_t (*ldfun)(CPUMIPSState *env, target_ulong); - - switch (mem_idx) - { - case 0: ldfun = cpu_ldq_kernel; break; - case 1: ldfun = cpu_ldq_super; break; - default: - case 2: ldfun = cpu_ldq_user; break; - } -#endif if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) { target_ulong i; for (i = 0; i < base_reglist; i++) { - env->active_tc.gpr[multiple_regs[i]] = ldfun(env, addr); + env->active_tc.gpr[multiple_regs[i]] = do_ld(env, addr, mem_idx); addr += 8; } } if (do_r31) { - env->active_tc.gpr[31] = ldfun(env, addr); + env->active_tc.gpr[31] = do_ld(env, addr, mem_idx); } } @@ -697,32 +656,18 @@ void helper_sdm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, { target_ulong base_reglist = reglist & 0xf; target_ulong do_r31 = reglist & 0x10; -#ifdef CONFIG_USER_ONLY -#undef stfun -#define stfun(env, addr, val) stq_raw(addr, val) -#else - void (*stfun)(CPUMIPSState *env, target_ulong, uint64_t); - - switch (mem_idx) - { - case 0: stfun = cpu_stq_kernel; break; - case 1: stfun = cpu_stq_super; break; - default: - case 2: stfun = cpu_stq_user; break; - } -#endif if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) { target_ulong i; for (i = 0; i < base_reglist; i++) { - stfun(env, addr, env->active_tc.gpr[multiple_regs[i]]); + do_sd(env, addr, env->active_tc.gpr[multiple_regs[i]], mem_idx); addr += 8; } } if (do_r31) { - stfun(env, addr, env->active_tc.gpr[31]); + do_sd(env, addr, env->active_tc.gpr[31], mem_idx); } } #endif From fc40787abcf8452b8f50d92b7a13243a12972c7a Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:21 +0200 Subject: [PATCH 1425/2270] target-mips: implement unaligned loads using TCG Load/store from helpers should be avoided as they are quite inefficient. Rewrite unaligned loads instructions using TCG and aligned loads. The number of actual loads operations to implement an unaligned load instruction is reduced from up to 8 to 1. Note: As we can't rely on shift by 32 or 64 undefined behaviour, the code loads already shift by one constants. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/helper.h | 4 -- target-mips/op_helper.c | 142 ---------------------------------------- target-mips/translate.c | 75 +++++++++++++++++---- 3 files changed, 62 insertions(+), 159 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index da8d9a1381..acf9ebd759 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -4,13 +4,9 @@ DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int) DEF_HELPER_2(raise_exception, noreturn, env, i32) #ifdef TARGET_MIPS64 -DEF_HELPER_4(ldl, tl, env, tl, tl, int) -DEF_HELPER_4(ldr, tl, env, tl, tl, int) DEF_HELPER_4(sdl, void, env, tl, tl, int) DEF_HELPER_4(sdr, void, env, tl, tl, int) #endif -DEF_HELPER_4(lwl, tl, env, tl, tl, int) -DEF_HELPER_4(lwr, tl, env, tl, tl, int) DEF_HELPER_4(swl, void, env, tl, tl, int) DEF_HELPER_4(swr, void, env, tl, tl, int) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 78497d9a87..773c7104af 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -350,56 +350,6 @@ HELPER_ST_ATOMIC(scd, ld, sd, 0x7) #define GET_OFFSET(addr, offset) (addr - (offset)) #endif -target_ulong helper_lwl(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2, int mem_idx) -{ - target_ulong tmp; - - tmp = do_lbu(env, arg2, mem_idx); - arg1 = (arg1 & 0x00FFFFFF) | (tmp << 24); - - if (GET_LMASK(arg2) <= 2) { - tmp = do_lbu(env, GET_OFFSET(arg2, 1), mem_idx); - arg1 = (arg1 & 0xFF00FFFF) | (tmp << 16); - } - - if (GET_LMASK(arg2) <= 1) { - tmp = do_lbu(env, GET_OFFSET(arg2, 2), mem_idx); - arg1 = (arg1 & 0xFFFF00FF) | (tmp << 8); - } - - if (GET_LMASK(arg2) == 0) { - tmp = do_lbu(env, GET_OFFSET(arg2, 3), mem_idx); - arg1 = (arg1 & 0xFFFFFF00) | tmp; - } - return (int32_t)arg1; -} - -target_ulong helper_lwr(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2, int mem_idx) -{ - target_ulong tmp; - - tmp = do_lbu(env, arg2, mem_idx); - arg1 = (arg1 & 0xFFFFFF00) | tmp; - - if (GET_LMASK(arg2) >= 1) { - tmp = do_lbu(env, GET_OFFSET(arg2, -1), mem_idx); - arg1 = (arg1 & 0xFFFF00FF) | (tmp << 8); - } - - if (GET_LMASK(arg2) >= 2) { - tmp = do_lbu(env, GET_OFFSET(arg2, -2), mem_idx); - arg1 = (arg1 & 0xFF00FFFF) | (tmp << 16); - } - - if (GET_LMASK(arg2) == 3) { - tmp = do_lbu(env, GET_OFFSET(arg2, -3), mem_idx); - arg1 = (arg1 & 0x00FFFFFF) | (tmp << 24); - } - return (int32_t)arg1; -} - void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, int mem_idx) { @@ -440,98 +390,6 @@ void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, #define GET_LMASK64(v) (((v) & 7) ^ 7) #endif -target_ulong helper_ldl(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2, int mem_idx) -{ - uint64_t tmp; - - tmp = do_lbu(env, arg2, mem_idx); - arg1 = (arg1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56); - - if (GET_LMASK64(arg2) <= 6) { - tmp = do_lbu(env, GET_OFFSET(arg2, 1), mem_idx); - arg1 = (arg1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48); - } - - if (GET_LMASK64(arg2) <= 5) { - tmp = do_lbu(env, GET_OFFSET(arg2, 2), mem_idx); - arg1 = (arg1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40); - } - - if (GET_LMASK64(arg2) <= 4) { - tmp = do_lbu(env, GET_OFFSET(arg2, 3), mem_idx); - arg1 = (arg1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32); - } - - if (GET_LMASK64(arg2) <= 3) { - tmp = do_lbu(env, GET_OFFSET(arg2, 4), mem_idx); - arg1 = (arg1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24); - } - - if (GET_LMASK64(arg2) <= 2) { - tmp = do_lbu(env, GET_OFFSET(arg2, 5), mem_idx); - arg1 = (arg1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16); - } - - if (GET_LMASK64(arg2) <= 1) { - tmp = do_lbu(env, GET_OFFSET(arg2, 6), mem_idx); - arg1 = (arg1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8); - } - - if (GET_LMASK64(arg2) == 0) { - tmp = do_lbu(env, GET_OFFSET(arg2, 7), mem_idx); - arg1 = (arg1 & 0xFFFFFFFFFFFFFF00ULL) | tmp; - } - - return arg1; -} - -target_ulong helper_ldr(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2, int mem_idx) -{ - uint64_t tmp; - - tmp = do_lbu(env, arg2, mem_idx); - arg1 = (arg1 & 0xFFFFFFFFFFFFFF00ULL) | tmp; - - if (GET_LMASK64(arg2) >= 1) { - tmp = do_lbu(env, GET_OFFSET(arg2, -1), mem_idx); - arg1 = (arg1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8); - } - - if (GET_LMASK64(arg2) >= 2) { - tmp = do_lbu(env, GET_OFFSET(arg2, -2), mem_idx); - arg1 = (arg1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16); - } - - if (GET_LMASK64(arg2) >= 3) { - tmp = do_lbu(env, GET_OFFSET(arg2, -3), mem_idx); - arg1 = (arg1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24); - } - - if (GET_LMASK64(arg2) >= 4) { - tmp = do_lbu(env, GET_OFFSET(arg2, -4), mem_idx); - arg1 = (arg1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32); - } - - if (GET_LMASK64(arg2) >= 5) { - tmp = do_lbu(env, GET_OFFSET(arg2, -5), mem_idx); - arg1 = (arg1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40); - } - - if (GET_LMASK64(arg2) >= 6) { - tmp = do_lbu(env, GET_OFFSET(arg2, -6), mem_idx); - arg1 = (arg1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48); - } - - if (GET_LMASK64(arg2) == 7) { - tmp = do_lbu(env, GET_OFFSET(arg2, -7), mem_idx); - arg1 = (arg1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56); - } - - return arg1; -} - void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, int mem_idx) { diff --git a/target-mips/translate.c b/target-mips/translate.c index a48a475806..05d88c4bfc 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1580,7 +1580,7 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int base, int16_t offset) { const char *opn = "ld"; - TCGv t0, t1; + TCGv t0, t1, t2; if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) { /* Loongson CPU uses a load to zero register for prefetch. @@ -1612,21 +1612,45 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, opn = "lld"; break; case OPC_LDL: - save_cpu_state(ctx, 1); t1 = tcg_temp_new(); + tcg_gen_andi_tl(t1, t0, 7); +#ifndef TARGET_WORDS_BIGENDIAN + tcg_gen_xori_tl(t1, t1, 7); +#endif + tcg_gen_shli_tl(t1, t1, 3); + tcg_gen_andi_tl(t0, t0, ~7); + tcg_gen_qemu_ld64(t0, t0, ctx->mem_idx); + tcg_gen_shl_tl(t0, t0, t1); + tcg_gen_xori_tl(t1, t1, 63); + t2 = tcg_const_tl(0x7fffffffffffffffull); + tcg_gen_shr_tl(t2, t2, t1); gen_load_gpr(t1, rt); - gen_helper_1e2i(ldl, t1, t1, t0, ctx->mem_idx); - gen_store_gpr(t1, rt); + tcg_gen_and_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_or_tl(t0, t0, t1); tcg_temp_free(t1); + gen_store_gpr(t0, rt); opn = "ldl"; break; case OPC_LDR: - save_cpu_state(ctx, 1); t1 = tcg_temp_new(); + tcg_gen_andi_tl(t1, t0, 7); +#ifdef TARGET_WORDS_BIGENDIAN + tcg_gen_xori_tl(t1, t1, 7); +#endif + tcg_gen_shli_tl(t1, t1, 3); + tcg_gen_andi_tl(t0, t0, ~7); + tcg_gen_qemu_ld64(t0, t0, ctx->mem_idx); + tcg_gen_shr_tl(t0, t0, t1); + tcg_gen_xori_tl(t1, t1, 63); + t2 = tcg_const_tl(0xfffffffffffffffeull); + tcg_gen_shl_tl(t2, t2, t1); gen_load_gpr(t1, rt); - gen_helper_1e2i(ldr, t1, t1, t0, ctx->mem_idx); - gen_store_gpr(t1, rt); + tcg_gen_and_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_or_tl(t0, t0, t1); tcg_temp_free(t1); + gen_store_gpr(t0, rt); opn = "ldr"; break; case OPC_LDPC: @@ -1672,21 +1696,46 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, opn = "lbu"; break; case OPC_LWL: - save_cpu_state(ctx, 1); t1 = tcg_temp_new(); + tcg_gen_andi_tl(t1, t0, 3); +#ifndef TARGET_WORDS_BIGENDIAN + tcg_gen_xori_tl(t1, t1, 3); +#endif + tcg_gen_shli_tl(t1, t1, 3); + tcg_gen_andi_tl(t0, t0, ~3); + tcg_gen_qemu_ld32u(t0, t0, ctx->mem_idx); + tcg_gen_shl_tl(t0, t0, t1); + tcg_gen_xori_tl(t1, t1, 31); + t2 = tcg_const_tl(0x7fffffffull); + tcg_gen_shr_tl(t2, t2, t1); gen_load_gpr(t1, rt); - gen_helper_1e2i(lwl, t1, t1, t0, ctx->mem_idx); - gen_store_gpr(t1, rt); + tcg_gen_and_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_or_tl(t0, t0, t1); tcg_temp_free(t1); + tcg_gen_ext32s_tl(t0, t0); + gen_store_gpr(t0, rt); opn = "lwl"; break; case OPC_LWR: - save_cpu_state(ctx, 1); t1 = tcg_temp_new(); + tcg_gen_andi_tl(t1, t0, 3); +#ifdef TARGET_WORDS_BIGENDIAN + tcg_gen_xori_tl(t1, t1, 3); +#endif + tcg_gen_shli_tl(t1, t1, 3); + tcg_gen_andi_tl(t0, t0, ~3); + tcg_gen_qemu_ld32u(t0, t0, ctx->mem_idx); + tcg_gen_shr_tl(t0, t0, t1); + tcg_gen_xori_tl(t1, t1, 31); + t2 = tcg_const_tl(0xfffffffeull); + tcg_gen_shl_tl(t2, t2, t1); gen_load_gpr(t1, rt); - gen_helper_1e2i(lwr, t1, t1, t0, ctx->mem_idx); - gen_store_gpr(t1, rt); + tcg_gen_and_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_or_tl(t0, t0, t1); tcg_temp_free(t1); + gen_store_gpr(t0, rt); opn = "lwr"; break; case OPC_LL: From 2d2826b99ee810057c76b48377d286beb9ee943b Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:21 +0200 Subject: [PATCH 1426/2270] target-mips: don't use local temps for store conditional Store conditional operations only need local temps in user mode. Fix the code to use temp local only in user mode, this spares two memory stores in system mode. At the same time remove a wrong a wrong copied & pasted comment, store operations don't have a register destination. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 05d88c4bfc..2484b238db 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1814,13 +1814,14 @@ static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt, const char *opn = "st_cond"; TCGv t0, t1; +#ifdef CONFIG_USER_ONLY t0 = tcg_temp_local_new(); - - gen_base_offset_addr(ctx, t0, base, offset); - /* Don't do NOP if destination is zero: we must perform the actual - memory access. */ - t1 = tcg_temp_local_new(); +#else + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); +#endif + gen_base_offset_addr(ctx, t0, base, offset); gen_load_gpr(t1, rt); switch (opc) { #if defined(TARGET_MIPS64) From acf124655873cf7256877a35efd8dacca1b199d8 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:21 +0200 Subject: [PATCH 1427/2270] target-mips: implement movn/movz using movcond Avoid the branches in movn/movz implementation and replace them with movcond. Also update a wrong command. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 2484b238db..c6b5862e16 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -2359,35 +2359,32 @@ static void gen_cond_move(CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rd, int rs, int rt) { const char *opn = "cond move"; - int l1; + TCGv t0, t1, t2; if (rd == 0) { - /* If no destination, treat it as a NOP. - For add & sub, we must generate the overflow exception when needed. */ + /* If no destination, treat it as a NOP. */ MIPS_DEBUG("NOP"); return; } - l1 = gen_new_label(); + t0 = tcg_temp_new(); + gen_load_gpr(t0, rt); + t1 = tcg_const_tl(0); + t2 = tcg_temp_new(); + gen_load_gpr(t2, rs); switch (opc) { case OPC_MOVN: - if (likely(rt != 0)) - tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1); - else - tcg_gen_br(l1); + tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]); opn = "movn"; break; case OPC_MOVZ: - if (likely(rt != 0)) - tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1); + tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]); opn = "movz"; break; } - if (rs != 0) - tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); - else - tcg_gen_movi_tl(cpu_gpr[rd], 0); - gen_set_label(l1); + tcg_temp_free(t2); + tcg_temp_free(t1); + tcg_temp_free(t0); (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); From 51127181cfac0315720e6ca502eb133a353f6b11 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:21 +0200 Subject: [PATCH 1428/2270] target-mips: optimize ddiv/ddivu/div/divu with movcond The result of a division by 0, or a division of INT_MIN by -1 in the signed case, is unpredictable. Just replace 0 by 1 in that case so that it doesn't trigger a floating point exception on the host. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 85 ++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 48 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index c6b5862e16..b92a84473c 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -2653,60 +2653,48 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, TCGv t0, t1; unsigned int acc; - switch (opc) { - case OPC_DIV: - case OPC_DIVU: -#if defined(TARGET_MIPS64) - case OPC_DDIV: - case OPC_DDIVU: -#endif - t0 = tcg_temp_local_new(); - t1 = tcg_temp_local_new(); - break; - default: - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - break; - } + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); gen_load_gpr(t0, rs); gen_load_gpr(t1, rt); + switch (opc) { case OPC_DIV: { - int l1 = gen_new_label(); - int l2 = gen_new_label(); - + TCGv t2 = tcg_temp_new(); + TCGv t3 = tcg_temp_new(); tcg_gen_ext32s_tl(t0, t0); tcg_gen_ext32s_tl(t1, t1); - tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); - tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2); - tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2); - - tcg_gen_mov_tl(cpu_LO[0], t0); - tcg_gen_movi_tl(cpu_HI[0], 0); - tcg_gen_br(l1); - gen_set_label(l2); + tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1); + tcg_gen_and_tl(t2, t2, t3); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); + tcg_gen_or_tl(t2, t2, t3); + tcg_gen_movi_tl(t3, 0); + tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); tcg_gen_div_tl(cpu_LO[0], t0, t1); tcg_gen_rem_tl(cpu_HI[0], t0, t1); tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]); tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]); - gen_set_label(l1); + tcg_temp_free(t3); + tcg_temp_free(t2); } opn = "div"; break; case OPC_DIVU: { - int l1 = gen_new_label(); - + TCGv t2 = tcg_const_tl(0); + TCGv t3 = tcg_const_tl(1); tcg_gen_ext32u_tl(t0, t0); tcg_gen_ext32u_tl(t1, t1); - tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); + tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); tcg_gen_divu_tl(cpu_LO[0], t0, t1); tcg_gen_remu_tl(cpu_HI[0], t0, t1); tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]); tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]); - gen_set_label(l1); + tcg_temp_free(t3); + tcg_temp_free(t2); } opn = "divu"; break; @@ -2759,30 +2747,31 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, #if defined(TARGET_MIPS64) case OPC_DDIV: { - int l1 = gen_new_label(); - int l2 = gen_new_label(); - - tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); - tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2); - tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2); - tcg_gen_mov_tl(cpu_LO[0], t0); - tcg_gen_movi_tl(cpu_HI[0], 0); - tcg_gen_br(l1); - gen_set_label(l2); - tcg_gen_div_i64(cpu_LO[0], t0, t1); - tcg_gen_rem_i64(cpu_HI[0], t0, t1); - gen_set_label(l1); + TCGv t2 = tcg_temp_new(); + TCGv t3 = tcg_temp_new(); + tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL); + tcg_gen_and_tl(t2, t2, t3); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); + tcg_gen_or_tl(t2, t2, t3); + tcg_gen_movi_tl(t3, 0); + tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); + tcg_gen_div_tl(cpu_LO[0], t0, t1); + tcg_gen_rem_tl(cpu_HI[0], t0, t1); + tcg_temp_free(t3); + tcg_temp_free(t2); } opn = "ddiv"; break; case OPC_DDIVU: { - int l1 = gen_new_label(); - - tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); + TCGv t2 = tcg_const_tl(0); + TCGv t3 = tcg_const_tl(1); + tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); tcg_gen_divu_i64(cpu_LO[0], t0, t1); tcg_gen_remu_i64(cpu_HI[0], t0, t1); - gen_set_label(l1); + tcg_temp_free(t3); + tcg_temp_free(t2); } opn = "ddivu"; break; From e0d002f17d1db1ade2b8d24b4a7c7ab361256726 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:21 +0200 Subject: [PATCH 1429/2270] target-mips: use deposit instead of hardcoded version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the deposit op instead of and hardcoded bit field insertion. It allows the host to emit the corresponding instruction if available. At the same time remove the (lsb > msb) test. The MIPS64R2 instruction set manual says "Because of the instruction format, lsb can never be greater than msb, so there is no UNPREDICATABLE case for this instruction." (Bug reported as LP:1071149.) Cc: Никита Канунников Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index b92a84473c..8175da05d0 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -3928,7 +3928,6 @@ static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt, { TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - target_ulong mask; gen_load_gpr(t1, rs); switch (opc) { @@ -3961,45 +3960,22 @@ static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt, case OPC_INS: if (lsb > msb) goto fail; - mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb; gen_load_gpr(t0, rt); - tcg_gen_andi_tl(t0, t0, ~mask); - tcg_gen_shli_tl(t1, t1, lsb); - tcg_gen_andi_tl(t1, t1, mask); - tcg_gen_or_tl(t0, t0, t1); + tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1); tcg_gen_ext32s_tl(t0, t0); break; #if defined(TARGET_MIPS64) case OPC_DINSM: - if (lsb > msb) - goto fail; - mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb; gen_load_gpr(t0, rt); - tcg_gen_andi_tl(t0, t0, ~mask); - tcg_gen_shli_tl(t1, t1, lsb); - tcg_gen_andi_tl(t1, t1, mask); - tcg_gen_or_tl(t0, t0, t1); + tcg_gen_deposit_tl(t0, t0, t1, lsb, msb + 32 - lsb + 1); break; case OPC_DINSU: - if (lsb > msb) - goto fail; - mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32); gen_load_gpr(t0, rt); - tcg_gen_andi_tl(t0, t0, ~mask); - tcg_gen_shli_tl(t1, t1, lsb + 32); - tcg_gen_andi_tl(t1, t1, mask); - tcg_gen_or_tl(t0, t0, t1); + tcg_gen_deposit_tl(t0, t0, t1, lsb + 32, msb - lsb + 1); break; case OPC_DINS: - if (lsb > msb) - goto fail; gen_load_gpr(t0, rt); - mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb; - gen_load_gpr(t0, rt); - tcg_gen_andi_tl(t0, t0, ~mask); - tcg_gen_shli_tl(t1, t1, lsb); - tcg_gen_andi_tl(t1, t1, mask); - tcg_gen_or_tl(t0, t0, t1); + tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1); break; #endif default: From bc3e45e13a93b883f0369acb2e19c0cec8705a7a Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:21 +0200 Subject: [PATCH 1430/2270] target-mips: fix TLBR wrt SEGMask Like r4k_map_address(), r4k_helper_tlbp() should use SEGMask to mask the address. Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 773c7104af..cdd6880efc 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1856,6 +1856,9 @@ void r4k_helper_tlbp(CPUMIPSState *env) mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); tag = env->CP0_EntryHi & ~mask; VPN = tlb->VPN & ~mask; +#if defined(TARGET_MIPS64) + tag &= env->SEGMask; +#endif /* Check ASID, virtual page number & size */ if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) { /* TLB match */ @@ -1871,6 +1874,9 @@ void r4k_helper_tlbp(CPUMIPSState *env) mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); tag = env->CP0_EntryHi & ~mask; VPN = tlb->VPN & ~mask; +#if defined(TARGET_MIPS64) + tag &= env->SEGMask; +#endif /* Check ASID, virtual page number & size */ if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) { r4k_mips_tlb_flush_extra (env, i); From 286d52ebfc0d0d53c2a878e454292fea14bad41b Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 9 Oct 2012 21:53:21 +0200 Subject: [PATCH 1431/2270] target-mips: don't flush extra TLB on permissions upgrade If the guest uses a TLBWI instruction for upgrading permissions, we don't need to flush the extra TLBs. This improve boot time performance by about 10%. Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index cdd6880efc..f45d494b14 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1819,14 +1819,32 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx) void r4k_helper_tlbwi(CPUMIPSState *env) { + r4k_tlb_t *tlb; int idx; + target_ulong VPN; + uint8_t ASID; + bool G, V0, D0, V1, D1; idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb; + tlb = &env->tlb->mmu.r4k.tlb[idx]; + VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); +#if defined(TARGET_MIPS64) + VPN &= env->SEGMask; +#endif + ASID = env->CP0_EntryHi & 0xff; + G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; + V0 = (env->CP0_EntryLo0 & 2) != 0; + D0 = (env->CP0_EntryLo0 & 4) != 0; + V1 = (env->CP0_EntryLo1 & 2) != 0; + D1 = (env->CP0_EntryLo1 & 4) != 0; - /* Discard cached TLB entries. We could avoid doing this if the - tlbwi is just upgrading access permissions on the current entry; - that might be a further win. */ - r4k_mips_tlb_flush_extra (env, env->tlb->nb_tlb); + /* Discard cached TLB entries, unless tlbwi is just upgrading access + permissions on the current entry. */ + if (tlb->VPN != VPN || tlb->ASID != ASID || tlb->G != G || + (tlb->V0 && !V0) || (tlb->D0 && !D0) || + (tlb->V1 && !V1) || (tlb->D1 && !D1)) { + r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb); + } r4k_invalidate_tlb(env, idx, 0); r4k_fill_tlb(env, idx); From e5b8b0d4ba29fe1268ba049519a1b0cf8552a21a Mon Sep 17 00:00:00 2001 From: Dmitry Fleytman Date: Fri, 19 Oct 2012 07:56:55 +0200 Subject: [PATCH 1432/2270] e1000: drop check_rxov, always treat RX ring with RDH == RDT as empty Real HW always treats RX ring with RDH == RDT as empty. Emulation is supposed to behave the same. Reported-by: Chris Webb Reported-by: Richard Davies Signed-off-by: Dmitry Fleytman Signed-off-by: Stefan Hajnoczi --- hw/e1000.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/hw/e1000.c b/hw/e1000.c index e4f1ffef74..ec32f591af 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -92,7 +92,6 @@ typedef struct E1000State_st { uint32_t rxbuf_size; uint32_t rxbuf_min_shift; - int check_rxov; struct e1000_tx { unsigned char header[256]; unsigned char vlan_header[4]; @@ -741,11 +740,11 @@ static bool e1000_has_rxbufs(E1000State *s, size_t total_size) int bufs; /* Fast-path short packets */ if (total_size <= s->rxbuf_size) { - return s->mac_reg[RDH] != s->mac_reg[RDT] || !s->check_rxov; + return s->mac_reg[RDH] != s->mac_reg[RDT]; } if (s->mac_reg[RDH] < s->mac_reg[RDT]) { bufs = s->mac_reg[RDT] - s->mac_reg[RDH]; - } else if (s->mac_reg[RDH] > s->mac_reg[RDT] || !s->check_rxov) { + } else if (s->mac_reg[RDH] > s->mac_reg[RDT]) { bufs = s->mac_reg[RDLEN] / sizeof(struct e1000_rx_desc) + s->mac_reg[RDT] - s->mac_reg[RDH]; } else { @@ -848,7 +847,6 @@ e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size) if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN]) s->mac_reg[RDH] = 0; - s->check_rxov = 1; /* see comment in start_xmit; same here */ if (s->mac_reg[RDH] == rdh_start) { DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n", @@ -925,7 +923,6 @@ mac_writereg(E1000State *s, int index, uint32_t val) static void set_rdt(E1000State *s, int index, uint32_t val) { - s->check_rxov = 0; s->mac_reg[index] = val & 0xffff; if (e1000_has_rxbufs(s, 1)) { qemu_flush_queued_packets(&s->nic->nc); From f0e3ac70341febed02591b61b579723279783053 Mon Sep 17 00:00:00 2001 From: Lei Li Date: Thu, 1 Nov 2012 17:39:55 +0800 Subject: [PATCH 1433/2270] net: use "socket" model name for UDP sockets Fix the problem that can not delete the udp socket. It's caused by passing "udp" model to net_socket_udp_init, but we do not have "udp" model in our model list. Pass the right model "socket" to init function. https://bugs.launchpad.net/qemu/+bug/1073585?comments=all Signed-off-by: Lei Li Signed-off-by: Stefan Hajnoczi --- net/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/socket.c b/net/socket.c index b75d567695..c01323d4b0 100644 --- a/net/socket.c +++ b/net/socket.c @@ -747,7 +747,7 @@ int net_init_socket(const NetClientOptions *opts, const char *name, error_report("localaddr= is mandatory with udp="); return -1; } - if (net_socket_udp_init(peer, "udp", name, sock->udp, sock->localaddr) == + if (net_socket_udp_init(peer, "socket", name, sock->udp, sock->localaddr) == -1) { return -1; } From 645c9496f7083c105ecd32f32532496af6aadf62 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 24 Oct 2012 14:34:12 +0200 Subject: [PATCH 1434/2270] net: Reject non-netdevs in qmp_netdev_del() The netdev_del command crashes when given a -net device, because it calls qemu_opts_del(NULL). Check that this is a -netdev before attempting to delete it and the QemuOpts. Note the subtle change from qemu_find_opts_err("netdev", errp) to qemu_find_opts_err("netdev", NULL). Since "netdev" is a built in options group and we don't check for NULL return anyway, there's no use in passing errp here. Signed-off-by: Stefan Hajnoczi --- net.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net.c b/net.c index ae4bc0d431..e8ae13e283 100644 --- a/net.c +++ b/net.c @@ -827,6 +827,7 @@ exit_err: void qmp_netdev_del(const char *id, Error **errp) { NetClientState *nc; + QemuOpts *opts; nc = qemu_find_netdev(id); if (!nc) { @@ -834,8 +835,14 @@ void qmp_netdev_del(const char *id, Error **errp) return; } + opts = qemu_opts_find(qemu_find_opts_err("netdev", NULL), id); + if (!opts) { + error_setg(errp, "Device '%s' is not a netdev", id); + return; + } + qemu_del_net_client(nc); - qemu_opts_del(qemu_opts_find(qemu_find_opts_err("netdev", errp), id)); + qemu_opts_del(opts); } void print_net_client(Monitor *mon, NetClientState *nc) From 372254c6e5c078fb13b236bb648d2b9b2b0c70f1 Mon Sep 17 00:00:00 2001 From: "Gabriel L. Somlo" Date: Wed, 31 Oct 2012 14:15:39 -0400 Subject: [PATCH 1435/2270] e1000: pre-initialize RAH/RAL registers Some guest operating systems' drivers (Mac OS X in particular) fail to properly initialize the Receive Address registers (probably expecting them to be pre-initialized by an earlier component, such as a specific proprietary BIOS). This patch pre-initializes the RA registers, allowing OS X networking to function properly. Other guest operating systems are not affected, and free to (re)initialize these registers during boot. [According to the datasheet the Address Valid bits in the RA registers are cleared on PCI or software reset. This patch adds the NIC's MAC address and sets Address Valid on reset. So we diverge from real hardware behavior here. -- Stefan] Signed-off-by: Gabriel Somlo Signed-off-by: Stefan Hajnoczi --- hw/e1000.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hw/e1000.c b/hw/e1000.c index ec32f591af..cb7e7e8366 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -265,6 +265,8 @@ rxbufsize(uint32_t v) static void e1000_reset(void *opaque) { E1000State *d = opaque; + uint8_t *macaddr = d->conf.macaddr.a; + int i; qemu_del_timer(d->autoneg_timer); memset(d->phy_reg, 0, sizeof d->phy_reg); @@ -277,6 +279,14 @@ static void e1000_reset(void *opaque) if (d->nic->nc.link_down) { e1000_link_down(d); } + + /* Some guests expect pre-initialized RAH/RAL (AddrValid flag + MACaddr) */ + d->mac_reg[RA] = 0; + d->mac_reg[RA + 1] = E1000_RAH_AV; + for (i = 0; i < 4; i++) { + d->mac_reg[RA] |= macaddr[i] << (8 * i); + d->mac_reg[RA + 1] |= (i < 2) ? macaddr[i + 4] << (8 * i) : 0; + } } static void From a3cfa18eb075c7ef78358ca1956fe7b01caa1724 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 29 Oct 2012 17:24:57 +0000 Subject: [PATCH 1436/2270] Revert "PPC: pseries: Remove hack for PIO window" This reverts commit a178274efabcbbc5d44805b51def874e47051325. Contrary to that commit's message, the users of old_portio are not all gone. In particular VGA still uses it via portio_list_add(). Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_pci.c | 44 +++++++++++++++++++++++++++++++++++++++++++- hw/spapr_pci.h | 2 +- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index c2c3079d21..a08ed11166 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -439,6 +439,43 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level) qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level); } +static uint64_t spapr_io_read(void *opaque, hwaddr addr, + unsigned size) +{ + switch (size) { + case 1: + return cpu_inb(addr); + case 2: + return cpu_inw(addr); + case 4: + return cpu_inl(addr); + } + assert(0); +} + +static void spapr_io_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) +{ + switch (size) { + case 1: + cpu_outb(addr, data); + return; + case 2: + cpu_outw(addr, data); + return; + case 4: + cpu_outl(addr, data); + return; + } + assert(0); +} + +static const MemoryRegionOps spapr_io_ops = { + .endianness = DEVICE_LITTLE_ENDIAN, + .read = spapr_io_read, + .write = spapr_io_write +}; + /* * MSI/MSIX memory region implementation. * The handler handles both MSI and MSIX. @@ -508,9 +545,14 @@ static int spapr_phb_init(SysBusDevice *s) * old_portion are updated */ sprintf(namebuf, "%s.io", sphb->dtbusname); memory_region_init(&sphb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE); + /* FIXME: fix to support multiple PHBs */ + memory_region_add_subregion(get_system_io(), 0, &sphb->iospace); + sprintf(namebuf, "%s.io-alias", sphb->dtbusname); + memory_region_init_io(&sphb->iowindow, &spapr_io_ops, sphb, + namebuf, SPAPR_PCI_IO_WIN_SIZE); memory_region_add_subregion(get_system_memory(), sphb->io_win_addr, - &sphb->iospace); + &sphb->iowindow); /* As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors, * we need to allocate some memory to catch those writes coming diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index a77d7d5448..e307ac8035 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -44,7 +44,7 @@ typedef struct sPAPRPHBState { MemoryRegion memspace, iospace; hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size; hwaddr msi_win_addr; - MemoryRegion memwindow, msiwindow; + MemoryRegion memwindow, iowindow, msiwindow; uint32_t dma_liobn; uint64_t dma_window_start; From ac7d12ba256b7c9d4e122d0d6877e2312d6c19ed Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 29 Oct 2012 17:24:58 +0000 Subject: [PATCH 1437/2270] target-ppc: Rework storage of VPA registration state We change the storage of the VPA information to explicitly use fixed size integer types which will make life easier for syncing this data with KVM, which we will need in future. Signed-off-by: David Gibson [agraf: fix commit message] Signed-off-by: Alexander Graf --- target-ppc/cpu.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 286f42a808..e603d9f936 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1045,9 +1045,9 @@ struct CPUPPCState { #endif #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) - hwaddr vpa_addr; - hwaddr slb_shadow_addr, slb_shadow_size; - hwaddr dtl_addr, dtl_size; + uint64_t vpa_addr; + uint64_t slb_shadow_addr, slb_shadow_size; + uint64_t dtl_addr, dtl_size; #endif /* TARGET_PPC64 */ int error_code; From 3030442054e04b2538016920f0da6e94743f48be Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 29 Oct 2012 17:24:59 +0000 Subject: [PATCH 1438/2270] target-ppc: Extend FPU state for newer POWER CPUs This patch adds some extra FPU state to CPUPPCState. Specifically, fpscr is extended to a target_ulong bits, since some recent (64 bit) CPUs now have more status bits than fit inside 32 bits. Also, we add the 32 VSR registers present on CPUs with VSX (these extend the standard FP regs, which together with the Altivec/VMX registers form a 64 x 128bit register file for VSX). We don't actually support the instructions using these extra registers in TCG yet, but we still need a place to store the state so we can sync it with KVM and savevm/loadvm it. This patch updates the savevm code to not fail on the extended state, but also does not actually save it - that's a project for another patch. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- target-ppc/cpu.h | 4 +++- target-ppc/machine.c | 8 ++++++-- target-ppc/translate.c | 29 ++++++++++++++++++----------- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index e603d9f936..380a8d2926 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -963,7 +963,7 @@ struct CPUPPCState { /* floating point registers */ float64 fpr[32]; /* floating point status and control register */ - uint32_t fpscr; + target_ulong fpscr; /* Next instruction pointer */ target_ulong nip; @@ -1014,6 +1014,8 @@ struct CPUPPCState { /* Altivec registers */ ppc_avr_t avr[32]; uint32_t vscr; + /* VSX registers */ + uint64_t vsr[32]; /* SPE registers */ uint64_t spe_acc; uint32_t spe_fscr; diff --git a/target-ppc/machine.c b/target-ppc/machine.c index 21ce7575e3..5e7bc00e26 100644 --- a/target-ppc/machine.c +++ b/target-ppc/machine.c @@ -6,6 +6,7 @@ void cpu_save(QEMUFile *f, void *opaque) { CPUPPCState *env = (CPUPPCState *)opaque; unsigned int i, j; + uint32_t fpscr; for (i = 0; i < 32; i++) qemu_put_betls(f, &env->gpr[i]); @@ -30,7 +31,8 @@ void cpu_save(QEMUFile *f, void *opaque) u.d = env->fpr[i]; qemu_put_be64(f, u.l); } - qemu_put_be32s(f, &env->fpscr); + fpscr = env->fpscr; + qemu_put_be32s(f, &fpscr); qemu_put_sbe32s(f, &env->access_type); #if defined(TARGET_PPC64) qemu_put_betls(f, &env->asr); @@ -90,6 +92,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) CPUPPCState *env = (CPUPPCState *)opaque; unsigned int i, j; target_ulong sdr1; + uint32_t fpscr; for (i = 0; i < 32; i++) qemu_get_betls(f, &env->gpr[i]); @@ -114,7 +117,8 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) u.l = qemu_get_be64(f); env->fpr[i] = u.d; } - qemu_get_be32s(f, &env->fpscr); + qemu_get_be32s(f, &fpscr); + env->fpscr = fpscr; qemu_get_sbe32s(f, &env->access_type); #if defined(TARGET_PPC64) qemu_get_betls(f, &env->asr); diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 1042268ecf..56725e6a61 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -68,7 +68,7 @@ static TCGv cpu_cfar; #endif static TCGv cpu_xer; static TCGv cpu_reserve; -static TCGv_i32 cpu_fpscr; +static TCGv cpu_fpscr; static TCGv_i32 cpu_access_type; #include "gen-icount.h" @@ -163,8 +163,8 @@ void ppc_translate_init(void) offsetof(CPUPPCState, reserve_addr), "reserve_addr"); - cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0, - offsetof(CPUPPCState, fpscr), "fpscr"); + cpu_fpscr = tcg_global_mem_new(TCG_AREG0, + offsetof(CPUPPCState, fpscr), "fpscr"); cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUPPCState, access_type), "access_type"); @@ -2302,6 +2302,7 @@ GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT); /* mcrfs */ static void gen_mcrfs(DisasContext *ctx) { + TCGv tmp = tcg_temp_new(); int bfa; if (unlikely(!ctx->fpu_enabled)) { @@ -2309,9 +2310,11 @@ static void gen_mcrfs(DisasContext *ctx) return; } bfa = 4 * (7 - crfS(ctx->opcode)); - tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa); + tcg_gen_shri_tl(tmp, cpu_fpscr, bfa); + tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp); + tcg_temp_free(tmp); tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf); - tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(0xF << bfa)); + tcg_gen_andi_tl(cpu_fpscr, cpu_fpscr, ~(0xF << bfa)); } /* mffs */ @@ -2322,7 +2325,7 @@ static void gen_mffs(DisasContext *ctx) return; } gen_reset_fpstatus(); - tcg_gen_extu_i32_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr); + tcg_gen_extu_tl_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr); gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0); } @@ -2346,7 +2349,8 @@ static void gen_mtfsb0(DisasContext *ctx) tcg_temp_free_i32(t0); } if (unlikely(Rc(ctx->opcode) != 0)) { - tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX); + tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); + tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); } } @@ -2371,7 +2375,8 @@ static void gen_mtfsb1(DisasContext *ctx) tcg_temp_free_i32(t0); } if (unlikely(Rc(ctx->opcode) != 0)) { - tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX); + tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); + tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); } /* We can raise a differed exception */ gen_helper_float_check_status(cpu_env); @@ -2397,7 +2402,8 @@ static void gen_mtfsf(DisasContext *ctx) gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0); tcg_temp_free_i32(t0); if (unlikely(Rc(ctx->opcode) != 0)) { - tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX); + tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); + tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); } /* We can raise a differed exception */ gen_helper_float_check_status(cpu_env); @@ -2425,7 +2431,8 @@ static void gen_mtfsfi(DisasContext *ctx) tcg_temp_free_i64(t0); tcg_temp_free_i32(t1); if (unlikely(Rc(ctx->opcode) != 0)) { - tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX); + tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); + tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); } /* We can raise a differed exception */ gen_helper_float_check_status(cpu_env); @@ -9463,7 +9470,7 @@ void cpu_dump_state (CPUPPCState *env, FILE *f, fprintf_function cpu_fprintf, if ((i & (RFPL - 1)) == (RFPL - 1)) cpu_fprintf(f, "\n"); } - cpu_fprintf(f, "FPSCR %08x\n", env->fpscr); + cpu_fprintf(f, "FPSCR " TARGET_FMT_lx "\n", env->fpscr); #if !defined(CONFIG_USER_ONLY) cpu_fprintf(f, " SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx " PVR " TARGET_FMT_lx " VRSAVE " TARGET_FMT_lx "\n", From bf0175de6c76779d4c8b0606de7bd2a5a0b87c7a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 29 Oct 2012 17:25:00 +0000 Subject: [PATCH 1439/2270] pseries: Clean up inconsistent variable name in xics.c Throughout xics.c 'nr' is used to refer to a global interrupt number, and 'server' is used to refer to an interrupt server number (i.e. CPU number). Except in icp_set_mfrr(), where 'nr' is used as a server number. Fix this confusing inconsistency. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/xics.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/xics.c b/hw/xics.c index ce88aa750b..7a899dd44f 100644 --- a/hw/xics.c +++ b/hw/xics.c @@ -108,13 +108,13 @@ static void icp_set_cppr(struct icp_state *icp, int server, uint8_t cppr) } } -static void icp_set_mfrr(struct icp_state *icp, int nr, uint8_t mfrr) +static void icp_set_mfrr(struct icp_state *icp, int server, uint8_t mfrr) { - struct icp_server_state *ss = icp->ss + nr; + struct icp_server_state *ss = icp->ss + server; ss->mfrr = mfrr; if (mfrr < CPPR(ss)) { - icp_check_ipi(icp, nr); + icp_check_ipi(icp, server); } } From 1ecbbab46925d4810fc35aba45cf93cb80ff0734 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 29 Oct 2012 17:25:02 +0000 Subject: [PATCH 1440/2270] pseries: Cleanup duplications of ics_valid_irq() code A couple of places in xics.c open-coded the same logic as is already implemented in ics_valid_irq(). This patch fixes the code duplication. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/xics.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/xics.c b/hw/xics.c index 7a899dd44f..ff4b5e210f 100644 --- a/hw/xics.c +++ b/hw/xics.c @@ -326,8 +326,7 @@ static void ics_eoi(struct ics_state *ics, int nr) qemu_irq xics_get_qirq(struct icp_state *icp, int irq) { - if ((irq < icp->ics->offset) - || (irq >= (icp->ics->offset + icp->ics->nr_irqs))) { + if (!ics_valid_irq(icp->ics, irq)) { return NULL; } @@ -336,8 +335,7 @@ qemu_irq xics_get_qirq(struct icp_state *icp, int irq) void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi) { - assert((irq >= icp->ics->offset) - && (irq < (icp->ics->offset + icp->ics->nr_irqs))); + assert(ics_valid_irq(icp->ics, irq)); icp->ics->irqs[irq - icp->ics->offset].lsi = lsi; } From 87e487a14bd9f3fb4a2b27179377e011bdda7c51 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 4 Jun 2010 11:46:35 +0200 Subject: [PATCH 1441/2270] console: QLIST-ify display change listeners. Signed-off-by: Gerd Hoffmann --- console.h | 72 ++++++++++++++++++++++++++++-------------------------- hw/xenfb.c | 2 +- vl.c | 9 +++---- 3 files changed, 42 insertions(+), 41 deletions(-) diff --git a/console.h b/console.h index 6099d8d710..4239eb346c 100644 --- a/console.h +++ b/console.h @@ -164,7 +164,7 @@ struct DisplayChangeListener { int w, int h, uint32_t c); void (*dpy_text_cursor)(struct DisplayState *s, int x, int y); - struct DisplayChangeListener *next; + QLIST_ENTRY(DisplayChangeListener) next; }; struct DisplayAllocator { @@ -179,7 +179,7 @@ struct DisplayState { struct QEMUTimer *gui_timer; struct DisplayAllocator* allocator; - struct DisplayChangeListener* listeners; + QLIST_HEAD(, DisplayChangeListener) listeners; void (*mouse_set)(int x, int y, int on); void (*cursor_define)(QEMUCursor *cursor); @@ -231,72 +231,76 @@ static inline int is_buffer_shared(DisplaySurface *surface) static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl) { - dcl->next = ds->listeners; - ds->listeners = dcl; + QLIST_INSERT_HEAD(&ds->listeners, dcl, next); } static inline void dpy_update(DisplayState *s, int x, int y, int w, int h) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { dcl->dpy_update(s, x, y, w, h); - dcl = dcl->next; } } static inline void dpy_resize(DisplayState *s) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { dcl->dpy_resize(s); - dcl = dcl->next; } } static inline void dpy_setdata(DisplayState *s) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - if (dcl->dpy_setdata) dcl->dpy_setdata(s); - dcl = dcl->next; + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_setdata) { + dcl->dpy_setdata(s); + } } } static inline void dpy_refresh(DisplayState *s) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - if (dcl->dpy_refresh) dcl->dpy_refresh(s); - dcl = dcl->next; + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_refresh) { + dcl->dpy_refresh(s); + } } } static inline void dpy_copy(struct DisplayState *s, int src_x, int src_y, - int dst_x, int dst_y, int w, int h) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - if (dcl->dpy_copy) + int dst_x, int dst_y, int w, int h) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_copy) { dcl->dpy_copy(s, src_x, src_y, dst_x, dst_y, w, h); - else /* TODO */ + } else { /* TODO */ dcl->dpy_update(s, dst_x, dst_y, w, h); - dcl = dcl->next; + } } } static inline void dpy_fill(struct DisplayState *s, int x, int y, - int w, int h, uint32_t c) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - if (dcl->dpy_fill) dcl->dpy_fill(s, x, y, w, h, c); - dcl = dcl->next; + int w, int h, uint32_t c) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_fill) { + dcl->dpy_fill(s, x, y, w, h, c); + } } } -static inline void dpy_cursor(struct DisplayState *s, int x, int y) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - if (dcl->dpy_text_cursor) dcl->dpy_text_cursor(s, x, y); - dcl = dcl->next; +static inline void dpy_cursor(struct DisplayState *s, int x, int y) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_text_cursor) { + dcl->dpy_text_cursor(s, x, y); + } } } diff --git a/hw/xenfb.c b/hw/xenfb.c index 338800a4d9..ef24c3315c 100644 --- a/hw/xenfb.c +++ b/hw/xenfb.c @@ -717,7 +717,7 @@ static void xenfb_update(void *opaque) if (xenfb_queue_full(xenfb)) return; - for (l = xenfb->c.ds->listeners; l != NULL; l = l->next) { + QLIST_FOREACH(l, &xenfb->c.ds->listeners, next) { if (l->idle) continue; idle = 0; diff --git a/vl.c b/vl.c index 5513d1518e..427e8a2d40 100644 --- a/vl.c +++ b/vl.c @@ -1359,15 +1359,14 @@ static void gui_update(void *opaque) { uint64_t interval = GUI_REFRESH_INTERVAL; DisplayState *ds = opaque; - DisplayChangeListener *dcl = ds->listeners; + DisplayChangeListener *dcl; dpy_refresh(ds); - while (dcl != NULL) { + QLIST_FOREACH(dcl, &ds->listeners, next) { if (dcl->gui_timer_interval && dcl->gui_timer_interval < interval) interval = dcl->gui_timer_interval; - dcl = dcl->next; } qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock_ms(rt_clock)); } @@ -3846,14 +3845,12 @@ int main(int argc, char **argv, char **envp) /* display setup */ dpy_resize(ds); - dcl = ds->listeners; - while (dcl != NULL) { + QLIST_FOREACH(dcl, &ds->listeners, next) { if (dcl->dpy_refresh != NULL) { ds->gui_timer = qemu_new_timer_ms(rt_clock, gui_update, ds); qemu_mod_timer(ds->gui_timer, qemu_get_clock_ms(rt_clock)); break; } - dcl = dcl->next; } text_consoles_set_display(ds); From 35c9e0a5c2804b94d1a452a0a9a12d7a893b5318 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 4 Jun 2010 11:51:31 +0200 Subject: [PATCH 1442/2270] console: add unregister_displaychangelistener Also change the way the gui_timer is initialized: each time a displaychangelistener is registered or unregistered we'll check whether we need a timer (due to dpy_refresh callback being present) and if so setup a timer, otherwise zap it. This way the gui timer works correctly with displaychangelisteners coming and going. Signed-off-by: Gerd Hoffmann --- console.h | 10 ++++++++++ vl.c | 31 +++++++++++++++++++++++-------- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/console.h b/console.h index 4239eb346c..f476ac810d 100644 --- a/console.h +++ b/console.h @@ -229,9 +229,19 @@ static inline int is_buffer_shared(DisplaySurface *surface) !(surface->flags & QEMU_REALPIXELS_FLAG)); } +void gui_setup_refresh(DisplayState *ds); + static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl) { QLIST_INSERT_HEAD(&ds->listeners, dcl, next); + gui_setup_refresh(ds); +} + +static inline void unregister_displaychangelistener(DisplayState *ds, + DisplayChangeListener *dcl) +{ + QLIST_REMOVE(dcl, next); + gui_setup_refresh(ds); } static inline void dpy_update(DisplayState *s, int x, int y, int w, int h) diff --git a/vl.c b/vl.c index 427e8a2d40..4c45b02f05 100644 --- a/vl.c +++ b/vl.c @@ -1371,6 +1371,29 @@ static void gui_update(void *opaque) qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock_ms(rt_clock)); } +void gui_setup_refresh(DisplayState *ds) +{ + DisplayChangeListener *dcl; + bool need_timer = false; + + QLIST_FOREACH(dcl, &ds->listeners, next) { + if (dcl->dpy_refresh != NULL) { + need_timer = true; + break; + } + } + + if (need_timer && ds->gui_timer == NULL) { + ds->gui_timer = qemu_new_timer_ms(rt_clock, gui_update, ds); + qemu_mod_timer(ds->gui_timer, qemu_get_clock_ms(rt_clock)); + } + if (!need_timer && ds->gui_timer != NULL) { + qemu_del_timer(ds->gui_timer); + qemu_free_timer(ds->gui_timer); + ds->gui_timer = NULL; + } +} + struct vm_change_state_entry { VMChangeStateHandler *cb; void *opaque; @@ -2454,7 +2477,6 @@ int main(int argc, char **argv, char **envp) const char *kernel_filename, *kernel_cmdline; char boot_devices[33] = "cad"; /* default to HD->floppy->CD-ROM */ DisplayState *ds; - DisplayChangeListener *dcl; int cyls, heads, secs, translation; QemuOpts *hda_opts = NULL, *opts, *machine_opts; QemuOptsList *olist; @@ -3845,13 +3867,6 @@ int main(int argc, char **argv, char **envp) /* display setup */ dpy_resize(ds); - QLIST_FOREACH(dcl, &ds->listeners, next) { - if (dcl->dpy_refresh != NULL) { - ds->gui_timer = qemu_new_timer_ms(rt_clock, gui_update, ds); - qemu_mod_timer(ds->gui_timer, qemu_get_clock_ms(rt_clock)); - break; - } - } text_consoles_set_display(ds); if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { From bf2fde70fea6b3245dab44253deafba95f2979e5 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 12 Sep 2012 07:56:45 +0200 Subject: [PATCH 1443/2270] console: move set_mouse + cursor_define callbacks When adding DisplayChangeListeners the set_mouse and cursor_define callbacks have been left in DisplayState for some reason. Fix it. Signed-off-by: Gerd Hoffmann --- console.c | 2 +- console.h | 39 +++++++++++++++++++++++++++++++++++---- hw/jazz_led.c | 2 +- hw/qxl-render.c | 2 +- hw/vga.c | 10 +++++----- hw/vmware_vga.c | 11 ++++++----- ui/sdl.c | 8 ++++---- ui/spice-display.c | 4 ++-- ui/vnc.c | 8 ++++---- 9 files changed, 59 insertions(+), 27 deletions(-) diff --git a/console.c b/console.c index 3f3d2547bf..260a029246 100644 --- a/console.c +++ b/console.c @@ -1242,7 +1242,7 @@ static void text_console_update(void *opaque, console_ch_t *chardata) s->text_y[1] = 0; } if (s->cursor_invalidate) { - dpy_cursor(s->ds, s->x, s->y); + dpy_text_cursor(s->ds, s->x, s->y); s->cursor_invalidate = 0; } } diff --git a/console.h b/console.h index f476ac810d..fb38ce9060 100644 --- a/console.h +++ b/console.h @@ -164,6 +164,9 @@ struct DisplayChangeListener { int w, int h, uint32_t c); void (*dpy_text_cursor)(struct DisplayState *s, int x, int y); + void (*dpy_mouse_set)(struct DisplayState *s, int x, int y, int on); + void (*dpy_cursor_define)(struct DisplayState *s, QEMUCursor *cursor); + QLIST_ENTRY(DisplayChangeListener) next; }; @@ -181,9 +184,6 @@ struct DisplayState { struct DisplayAllocator* allocator; QLIST_HEAD(, DisplayChangeListener) listeners; - void (*mouse_set)(int x, int y, int on); - void (*cursor_define)(QEMUCursor *cursor); - struct DisplayState *next; }; @@ -304,7 +304,7 @@ static inline void dpy_fill(struct DisplayState *s, int x, int y, } } -static inline void dpy_cursor(struct DisplayState *s, int x, int y) +static inline void dpy_text_cursor(struct DisplayState *s, int x, int y) { struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { @@ -314,6 +314,37 @@ static inline void dpy_cursor(struct DisplayState *s, int x, int y) } } +static inline void dpy_mouse_set(struct DisplayState *s, int x, int y, int on) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_mouse_set) { + dcl->dpy_mouse_set(s, x, y, on); + } + } +} + +static inline void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_cursor_define) { + dcl->dpy_cursor_define(s, cursor); + } + } +} + +static inline bool dpy_cursor_define_supported(struct DisplayState *s) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_cursor_define) { + return true; + } + } + return false; +} + static inline int ds_get_linesize(DisplayState *ds) { return ds->surface->linesize; diff --git a/hw/jazz_led.c b/hw/jazz_led.c index a6a90ab283..853bf6d4c1 100644 --- a/hw/jazz_led.c +++ b/hw/jazz_led.c @@ -210,7 +210,7 @@ static void jazz_led_text_update(void *opaque, console_ch_t *chardata) LedState *s = opaque; char buf[2]; - dpy_cursor(s->ds, -1, -1); + dpy_text_cursor(s->ds, -1, -1); qemu_console_resize(s->ds, 2, 1); /* TODO: draw the segments */ diff --git a/hw/qxl-render.c b/hw/qxl-render.c index b66c168ef6..e8cf29e62a 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -234,7 +234,7 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext) return 1; } - if (!qxl->ssd.ds->mouse_set || !qxl->ssd.ds->cursor_define) { + if (!dpy_cursor_define_supported(qxl->ssd.ds)) { return 0; } diff --git a/hw/vga.c b/hw/vga.c index e4220df25e..f3256cb6c7 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -2070,11 +2070,11 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) { cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20); if (cursor_visible && cursor_offset < size && cursor_offset >= 0) - dpy_cursor(s->ds, - TEXTMODE_X(cursor_offset), - TEXTMODE_Y(cursor_offset)); + dpy_text_cursor(s->ds, + TEXTMODE_X(cursor_offset), + TEXTMODE_Y(cursor_offset)); else - dpy_cursor(s->ds, -1, -1); + dpy_text_cursor(s->ds, -1, -1); s->cursor_offset = cursor_offset; s->cursor_start = s->cr[VGA_CRTC_CURSOR_START]; s->cursor_end = s->cr[VGA_CRTC_CURSOR_END]; @@ -2135,7 +2135,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) /* Display a message */ s->last_width = 60; s->last_height = height = 3; - dpy_cursor(s->ds, -1, -1); + dpy_text_cursor(s->ds, -1, -1); s->ds->surface->width = s->last_width; s->ds->surface->height = height; dpy_resize(s->ds); diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index badaf7cef4..dc9279064c 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -478,8 +478,7 @@ static inline void vmsvga_cursor_define(struct vmsvga_state_s *s, qc = cursor_builtin_left_ptr(); } - if (s->vga.ds->cursor_define) - s->vga.ds->cursor_define(qc); + dpy_cursor_define(s->vga.ds, qc); cursor_put(qc); } #endif @@ -754,9 +753,10 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) caps |= SVGA_CAP_RECT_FILL; #endif #ifdef HW_MOUSE_ACCEL - if (s->vga.ds->mouse_set) + if (dpy_cursor_define_supported(s->vga.ds)) { caps |= SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 | SVGA_CAP_CURSOR_BYPASS; + } #endif return caps; @@ -903,8 +903,9 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) s->cursor.on |= (value == SVGA_CURSOR_ON_SHOW); s->cursor.on &= (value != SVGA_CURSOR_ON_HIDE); #ifdef HW_MOUSE_ACCEL - if (s->vga.ds->mouse_set && value <= SVGA_CURSOR_ON_SHOW) - s->vga.ds->mouse_set(s->cursor.x, s->cursor.y, s->cursor.on); + if (value <= SVGA_CURSOR_ON_SHOW) { + dpy_mouse_set(s->vga.ds, s->cursor.x, s->cursor.y, s->cursor.on); + } #endif break; diff --git a/ui/sdl.c b/ui/sdl.c index f6f711c1bb..f8ead930ae 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -905,7 +905,7 @@ static void sdl_fill(DisplayState *ds, int x, int y, int w, int h, uint32_t c) SDL_FillRect(real_screen, &dst, c); } -static void sdl_mouse_warp(int x, int y, int on) +static void sdl_mouse_warp(DisplayState *ds, int x, int y, int on) { if (on) { if (!guest_cursor) @@ -921,7 +921,7 @@ static void sdl_mouse_warp(int x, int y, int on) guest_x = x, guest_y = y; } -static void sdl_mouse_define(QEMUCursor *c) +static void sdl_mouse_define(DisplayState *ds, QEMUCursor *c) { uint8_t *image, *mask; int bpl; @@ -1025,8 +1025,8 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) dcl->dpy_refresh = sdl_refresh; dcl->dpy_setdata = sdl_setdata; dcl->dpy_fill = sdl_fill; - ds->mouse_set = sdl_mouse_warp; - ds->cursor_define = sdl_mouse_define; + dcl->dpy_mouse_set = sdl_mouse_warp; + dcl->dpy_cursor_define = sdl_mouse_define; register_displaychangelistener(ds, dcl); da = g_malloc0(sizeof(DisplayAllocator)); diff --git a/ui/spice-display.c b/ui/spice-display.c index b61764f381..5779fa8ba6 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -404,12 +404,12 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd) void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd) { if (ssd->cursor) { - ssd->ds->cursor_define(ssd->cursor); + dpy_cursor_define(ssd->ds, ssd->cursor); cursor_put(ssd->cursor); ssd->cursor = NULL; } if (ssd->mouse_x != -1 && ssd->mouse_y != -1) { - ssd->ds->mouse_set(ssd->mouse_x, ssd->mouse_y, 1); + dpy_mouse_set(ssd->ds, ssd->mouse_x, ssd->mouse_y, 1); ssd->mouse_x = -1; ssd->mouse_y = -1; } diff --git a/ui/vnc.c b/ui/vnc.c index d0ffcc54af..1b70db7e05 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -802,7 +802,7 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int } } -static void vnc_mouse_set(int x, int y, int visible) +static void vnc_mouse_set(DisplayState *ds, int x, int y, int visible) { /* can we ask the client(s) to move the pointer ??? */ } @@ -829,7 +829,7 @@ static int vnc_cursor_define(VncState *vs) return -1; } -static void vnc_dpy_cursor_define(QEMUCursor *c) +static void vnc_dpy_cursor_define(DisplayState *ds, QEMUCursor *c) { VncDisplay *vd = vnc_display; VncState *vs; @@ -2757,9 +2757,9 @@ void vnc_display_init(DisplayState *ds) dcl->dpy_update = vnc_dpy_update; dcl->dpy_resize = vnc_dpy_resize; dcl->dpy_setdata = vnc_dpy_setdata; + dcl->dpy_mouse_set = vnc_mouse_set; + dcl->dpy_cursor_define = vnc_dpy_cursor_define; register_displaychangelistener(ds, dcl); - ds->mouse_set = vnc_mouse_set; - ds->cursor_define = vnc_dpy_cursor_define; } From 76ffb0b4d048aac18b54f8555c60b6d3b0e2bc37 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 28 Sep 2012 13:24:17 +0200 Subject: [PATCH 1444/2270] console: s/TextConsole/QemuConsole/ Signed-off-by: Gerd Hoffmann --- console.c | 72 +++++++++++++++++++++++++-------------------------- qemu-common.h | 3 +-- 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/console.c b/console.c index 260a029246..b53dc1b6f3 100644 --- a/console.c +++ b/console.c @@ -114,20 +114,20 @@ typedef enum { TEXT_CONSOLE_FIXED_SIZE } console_type_t; -/* ??? This is mis-named. - It is used for both text and graphical consoles. */ -struct TextConsole { +struct QemuConsole { int index; console_type_t console_type; DisplayState *ds; + /* Graphic console state. */ vga_hw_update_ptr hw_update; vga_hw_invalidate_ptr hw_invalidate; vga_hw_screen_dump_ptr hw_screen_dump; vga_hw_text_update_ptr hw_text_update; void *hw; - int g_width, g_height; + + /* Text console state */ int width; int height; int total_height; @@ -161,8 +161,8 @@ struct TextConsole { }; static DisplayState *display_state; -static TextConsole *active_console; -static TextConsole *consoles[MAX_CONSOLES]; +static QemuConsole *active_console; +static QemuConsole *consoles[MAX_CONSOLES]; static int nb_consoles = 0; void vga_hw_update(void) @@ -179,7 +179,7 @@ void vga_hw_invalidate(void) void qmp_screendump(const char *filename, Error **errp) { - TextConsole *previous_active_console; + QemuConsole *previous_active_console; bool cswitch; previous_active_console = active_console; @@ -521,7 +521,7 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch, } } -static void text_console_resize(TextConsole *s) +static void text_console_resize(QemuConsole *s) { TextCell *cells, *c, *c1; int w1, x, y, last_width; @@ -553,7 +553,7 @@ static void text_console_resize(TextConsole *s) s->cells = cells; } -static inline void text_update_xy(TextConsole *s, int x, int y) +static inline void text_update_xy(QemuConsole *s, int x, int y) { s->text_x[0] = MIN(s->text_x[0], x); s->text_x[1] = MAX(s->text_x[1], x); @@ -561,7 +561,7 @@ static inline void text_update_xy(TextConsole *s, int x, int y) s->text_y[1] = MAX(s->text_y[1], y); } -static void invalidate_xy(TextConsole *s, int x, int y) +static void invalidate_xy(QemuConsole *s, int x, int y) { if (s->update_x0 > x * FONT_WIDTH) s->update_x0 = x * FONT_WIDTH; @@ -573,7 +573,7 @@ static void invalidate_xy(TextConsole *s, int x, int y) s->update_y1 = (y + 1) * FONT_HEIGHT; } -static void update_xy(TextConsole *s, int x, int y) +static void update_xy(QemuConsole *s, int x, int y) { TextCell *c; int y1, y2; @@ -597,7 +597,7 @@ static void update_xy(TextConsole *s, int x, int y) } } -static void console_show_cursor(TextConsole *s, int show) +static void console_show_cursor(QemuConsole *s, int show) { TextCell *c; int y, y1; @@ -631,7 +631,7 @@ static void console_show_cursor(TextConsole *s, int show) } } -static void console_refresh(TextConsole *s) +static void console_refresh(QemuConsole *s) { TextCell *c; int x, y, y1; @@ -666,7 +666,7 @@ static void console_refresh(TextConsole *s) static void console_scroll(int ydelta) { - TextConsole *s; + QemuConsole *s; int i, y1; s = active_console; @@ -698,7 +698,7 @@ static void console_scroll(int ydelta) console_refresh(s); } -static void console_put_lf(TextConsole *s) +static void console_put_lf(QemuConsole *s) { TextCell *c; int x, y1; @@ -749,7 +749,7 @@ static void console_put_lf(TextConsole *s) * NOTE: I know this code is not very efficient (checking every color for it * self) but it is more readable and better maintainable. */ -static void console_handle_escape(TextConsole *s) +static void console_handle_escape(QemuConsole *s) { int i; @@ -842,7 +842,7 @@ static void console_handle_escape(TextConsole *s) } } -static void console_clear_xy(TextConsole *s, int x, int y) +static void console_clear_xy(QemuConsole *s, int x, int y) { int y1 = (s->y_base + y) % s->total_height; TextCell *c = &s->cells[y1 * s->width + x]; @@ -852,7 +852,7 @@ static void console_clear_xy(TextConsole *s, int x, int y) } /* set cursor, checking bounds */ -static void set_cursor(TextConsole *s, int x, int y) +static void set_cursor(QemuConsole *s, int x, int y) { if (x < 0) { x = 0; @@ -871,7 +871,7 @@ static void set_cursor(TextConsole *s, int x, int y) s->y = y; } -static void console_putchar(TextConsole *s, int ch) +static void console_putchar(QemuConsole *s, int ch) { TextCell *c; int y1, i; @@ -1078,7 +1078,7 @@ static void console_putchar(TextConsole *s, int ch) void console_select(unsigned int index) { - TextConsole *s; + QemuConsole *s; if (index >= MAX_CONSOLES) return; @@ -1111,7 +1111,7 @@ void console_select(unsigned int index) static int console_puts(CharDriverState *chr, const uint8_t *buf, int len) { - TextConsole *s = chr->opaque; + QemuConsole *s = chr->opaque; int i; s->update_x0 = s->width * FONT_WIDTH; @@ -1133,7 +1133,7 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len) static void kbd_send_chars(void *opaque) { - TextConsole *s = opaque; + QemuConsole *s = opaque; int len; uint8_t buf[16]; @@ -1156,7 +1156,7 @@ static void kbd_send_chars(void *opaque) /* called when an ascii key is pressed */ void kbd_put_keysym(int keysym) { - TextConsole *s; + QemuConsole *s; uint8_t buf[16], *q; int c; @@ -1211,7 +1211,7 @@ void kbd_put_keysym(int keysym) static void text_console_invalidate(void *opaque) { - TextConsole *s = (TextConsole *) opaque; + QemuConsole *s = (QemuConsole *) opaque; if (!ds_get_bits_per_pixel(s->ds) && s->console_type == TEXT_CONSOLE) { s->g_width = ds_get_width(s->ds); s->g_height = ds_get_height(s->ds); @@ -1222,7 +1222,7 @@ static void text_console_invalidate(void *opaque) static void text_console_update(void *opaque, console_ch_t *chardata) { - TextConsole *s = (TextConsole *) opaque; + QemuConsole *s = (QemuConsole *) opaque; int i, j, src; if (s->text_x[0] <= s->text_x[1]) { @@ -1247,10 +1247,10 @@ static void text_console_update(void *opaque, console_ch_t *chardata) } } -static TextConsole *get_graphic_console(DisplayState *ds) +static QemuConsole *get_graphic_console(DisplayState *ds) { int i; - TextConsole *s; + QemuConsole *s; for (i = 0; i < nb_consoles; i++) { s = consoles[i]; if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds) @@ -1259,14 +1259,14 @@ static TextConsole *get_graphic_console(DisplayState *ds) return NULL; } -static TextConsole *new_console(DisplayState *ds, console_type_t console_type) +static QemuConsole *new_console(DisplayState *ds, console_type_t console_type) { - TextConsole *s; + QemuConsole *s; int i; if (nb_consoles >= MAX_CONSOLES) return NULL; - s = g_malloc0(sizeof(TextConsole)); + s = g_malloc0(sizeof(QemuConsole)); if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) && (console_type == GRAPHIC_CONSOLE))) { active_console = s; @@ -1417,7 +1417,7 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update, vga_hw_text_update_ptr text_update, void *opaque) { - TextConsole *s; + QemuConsole *s; DisplayState *ds; ds = (DisplayState *) g_malloc0(sizeof(DisplayState)); @@ -1463,14 +1463,14 @@ void console_color_init(DisplayState *ds) static void text_console_set_echo(CharDriverState *chr, bool echo) { - TextConsole *s = chr->opaque; + QemuConsole *s = chr->opaque; s->echo = echo; } static void text_console_update_cursor(void *opaque) { - TextConsole *s = opaque; + QemuConsole *s = opaque; s->cursor_visible_phase = !s->cursor_visible_phase; vga_hw_invalidate(); @@ -1480,7 +1480,7 @@ static void text_console_update_cursor(void *opaque) static void text_console_do_init(CharDriverState *chr, DisplayState *ds) { - TextConsole *s; + QemuConsole *s; static int color_inited; s = chr->opaque; @@ -1543,7 +1543,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds) CharDriverState *text_console_init(QemuOpts *opts) { CharDriverState *chr; - TextConsole *s; + QemuConsole *s; unsigned width; unsigned height; @@ -1589,7 +1589,7 @@ void text_consoles_set_display(DisplayState *ds) void qemu_console_resize(DisplayState *ds, int width, int height) { - TextConsole *s = get_graphic_console(ds); + QemuConsole *s = get_graphic_console(ds); if (!s) return; s->g_width = width; diff --git a/qemu-common.h b/qemu-common.h index b54612b1a5..fdd0dbcf64 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -264,8 +264,7 @@ typedef struct DisplayChangeListener DisplayChangeListener; typedef struct DisplaySurface DisplaySurface; typedef struct DisplayAllocator DisplayAllocator; typedef struct PixelFormat PixelFormat; -typedef struct TextConsole TextConsole; -typedef TextConsole QEMUConsole; +typedef struct QemuConsole QemuConsole; typedef struct CharDriverState CharDriverState; typedef struct MACAddr MACAddr; typedef struct NetClientState NetClientState; From a93a4a226a2afba147ba5df688b85d844f537c68 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 28 Sep 2012 15:02:08 +0200 Subject: [PATCH 1445/2270] console: untangle gfx & txt updates Stop abusing displaysurface fields for text mode displays. (bpp = 0, width = cols, height = lines). Add flags to displaystate indicating whenever text mode display (curses) or gfx mode displays (sdl, vnc, ...) are present. Add separate displaychangelistener callbacks for text / gfx mode resize & updates. This allows to enable gfx and txt diplays at the same time and also paves the way for more cleanups in the future. Signed-off-by: Gerd Hoffmann --- console.c | 59 ++++++++++++++++++----------------- console.h | 74 +++++++++++++++++++++++++++++++------------- hw/blizzard.c | 4 +-- hw/exynos4210_fimd.c | 2 +- hw/g364fb.c | 7 +++-- hw/jazz_led.c | 4 +-- hw/milkymist-vgafb.c | 2 +- hw/musicpal.c | 2 +- hw/nseries.c | 2 +- hw/omap_lcdc.c | 2 +- hw/palm.c | 2 +- hw/pl110.c | 2 +- hw/pxa2xx_lcd.c | 8 ++--- hw/qxl-render.c | 10 +++--- hw/qxl.c | 4 +-- hw/sm501.c | 4 +-- hw/ssd0303.c | 2 +- hw/ssd0323.c | 2 +- hw/tc6393xb.c | 4 +-- hw/tcx.c | 16 +++++----- hw/vga.c | 34 +++++++++----------- hw/vmware_vga.c | 4 +-- ui/curses.c | 21 +++++-------- ui/sdl.c | 12 +++---- ui/spice-display.c | 4 +-- ui/vnc.c | 8 ++--- vl.c | 14 +++++++-- 27 files changed, 171 insertions(+), 138 deletions(-) diff --git a/console.c b/console.c index b53dc1b6f3..61812c7c7f 100644 --- a/console.c +++ b/console.c @@ -638,30 +638,33 @@ static void console_refresh(QemuConsole *s) if (s != active_console) return; - if (!ds_get_bits_per_pixel(s->ds)) { + + if (s->ds->have_text) { s->text_x[0] = 0; s->text_y[0] = 0; s->text_x[1] = s->width - 1; s->text_y[1] = s->height - 1; s->cursor_invalidate = 1; - return; } - vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds), - color_table[0][COLOR_BLACK]); - y1 = s->y_displayed; - for(y = 0; y < s->height; y++) { - c = s->cells + y1 * s->width; - for(x = 0; x < s->width; x++) { - vga_putcharxy(s->ds, x, y, c->ch, - &(c->t_attrib)); - c++; + if (s->ds->have_gfx) { + vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds), + color_table[0][COLOR_BLACK]); + y1 = s->y_displayed; + for (y = 0; y < s->height; y++) { + c = s->cells + y1 * s->width; + for (x = 0; x < s->width; x++) { + vga_putcharxy(s->ds, x, y, c->ch, + &(c->t_attrib)); + c++; + } + if (++y1 == s->total_height) { + y1 = 0; + } } - if (++y1 == s->total_height) - y1 = 0; + console_show_cursor(s, 1); + dpy_gfx_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds)); } - console_show_cursor(s, 1); - dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds)); } static void console_scroll(int ydelta) @@ -1094,17 +1097,17 @@ void console_select(unsigned int index) qemu_del_timer(active_console->cursor_timer); } active_console = s; - if (ds_get_bits_per_pixel(s->ds)) { + if (ds->have_gfx) { ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height); - } else { - s->ds->surface->width = s->width; - s->ds->surface->height = s->height; + dpy_gfx_resize(ds); + } + if (ds->have_text) { + dpy_text_resize(ds, s->width, s->height); } if (s->cursor_timer) { qemu_mod_timer(s->cursor_timer, qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2); } - dpy_resize(s->ds); vga_hw_invalidate(); } } @@ -1123,10 +1126,10 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len) console_putchar(s, buf[i]); } console_show_cursor(s, 1); - if (ds_get_bits_per_pixel(s->ds) && s->update_x0 < s->update_x1) { - dpy_update(s->ds, s->update_x0, s->update_y0, - s->update_x1 - s->update_x0, - s->update_y1 - s->update_y0); + if (s->ds->have_gfx && s->update_x0 < s->update_x1) { + dpy_gfx_update(s->ds, s->update_x0, s->update_y0, + s->update_x1 - s->update_x0, + s->update_y1 - s->update_y0); } return len; } @@ -1234,8 +1237,8 @@ static void text_console_update(void *opaque, console_ch_t *chardata) (s->cells[src].t_attrib.fgcol << 12) | (s->cells[src].t_attrib.bgcol << 8) | (s->cells[src].t_attrib.bold << 21)); - dpy_update(s->ds, s->text_x[0], s->text_y[0], - s->text_x[1] - s->text_x[0], i - s->text_y[0]); + dpy_text_update(s->ds, s->text_x[0], s->text_y[0], + s->text_x[1] - s->text_x[0], i - s->text_y[0]); s->text_x[0] = s->width; s->text_y[0] = s->height; s->text_x[1] = 0; @@ -1596,7 +1599,7 @@ void qemu_console_resize(DisplayState *ds, int width, int height) s->g_height = height; if (is_graphic_console()) { ds->surface = qemu_resize_displaysurface(ds, width, height); - dpy_resize(ds); + dpy_gfx_resize(ds); } } @@ -1604,7 +1607,7 @@ void qemu_console_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h) { if (is_graphic_console()) { - dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h); + dpy_gfx_copy(ds, src_x, src_y, dst_x, dst_y, w, h); } } diff --git a/console.h b/console.h index fb38ce9060..00e2f03424 100644 --- a/console.h +++ b/console.h @@ -154,15 +154,19 @@ struct DisplayChangeListener { int idle; uint64_t gui_timer_interval; - void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h); - void (*dpy_resize)(struct DisplayState *s); - void (*dpy_setdata)(struct DisplayState *s); void (*dpy_refresh)(struct DisplayState *s); - void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y, - int dst_x, int dst_y, int w, int h); - void (*dpy_fill)(struct DisplayState *s, int x, int y, - int w, int h, uint32_t c); + + void (*dpy_gfx_update)(struct DisplayState *s, int x, int y, int w, int h); + void (*dpy_gfx_resize)(struct DisplayState *s); + void (*dpy_gfx_setdata)(struct DisplayState *s); + void (*dpy_gfx_copy)(struct DisplayState *s, int src_x, int src_y, + int dst_x, int dst_y, int w, int h); + void (*dpy_gfx_fill)(struct DisplayState *s, int x, int y, + int w, int h, uint32_t c); + void (*dpy_text_cursor)(struct DisplayState *s, int x, int y); + void (*dpy_text_resize)(struct DisplayState *s, int w, int h); + void (*dpy_text_update)(struct DisplayState *s, int x, int y, int w, int h); void (*dpy_mouse_set)(struct DisplayState *s, int x, int y, int on); void (*dpy_cursor_define)(struct DisplayState *s, QEMUCursor *cursor); @@ -180,6 +184,8 @@ struct DisplayState { struct DisplaySurface *surface; void *opaque; struct QEMUTimer *gui_timer; + bool have_gfx; + bool have_text; struct DisplayAllocator* allocator; QLIST_HEAD(, DisplayChangeListener) listeners; @@ -244,28 +250,32 @@ static inline void unregister_displaychangelistener(DisplayState *ds, gui_setup_refresh(ds); } -static inline void dpy_update(DisplayState *s, int x, int y, int w, int h) +static inline void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h) { struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { - dcl->dpy_update(s, x, y, w, h); + if (dcl->dpy_gfx_update) { + dcl->dpy_gfx_update(s, x, y, w, h); + } } } -static inline void dpy_resize(DisplayState *s) +static inline void dpy_gfx_resize(DisplayState *s) { struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { - dcl->dpy_resize(s); + if (dcl->dpy_gfx_resize) { + dcl->dpy_gfx_resize(s); + } } } -static inline void dpy_setdata(DisplayState *s) +static inline void dpy_gfx_setdata(DisplayState *s) { struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_setdata) { - dcl->dpy_setdata(s); + if (dcl->dpy_gfx_setdata) { + dcl->dpy_gfx_setdata(s); } } } @@ -280,26 +290,26 @@ static inline void dpy_refresh(DisplayState *s) } } -static inline void dpy_copy(struct DisplayState *s, int src_x, int src_y, +static inline void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y, int dst_x, int dst_y, int w, int h) { struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_copy) { - dcl->dpy_copy(s, src_x, src_y, dst_x, dst_y, w, h); + if (dcl->dpy_gfx_copy) { + dcl->dpy_gfx_copy(s, src_x, src_y, dst_x, dst_y, w, h); } else { /* TODO */ - dcl->dpy_update(s, dst_x, dst_y, w, h); + dcl->dpy_gfx_update(s, dst_x, dst_y, w, h); } } } -static inline void dpy_fill(struct DisplayState *s, int x, int y, - int w, int h, uint32_t c) +static inline void dpy_gfx_fill(struct DisplayState *s, int x, int y, + int w, int h, uint32_t c) { struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_fill) { - dcl->dpy_fill(s, x, y, w, h, c); + if (dcl->dpy_gfx_fill) { + dcl->dpy_gfx_fill(s, x, y, w, h, c); } } } @@ -314,6 +324,26 @@ static inline void dpy_text_cursor(struct DisplayState *s, int x, int y) } } +static inline void dpy_text_update(DisplayState *s, int x, int y, int w, int h) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_text_update) { + dcl->dpy_text_update(s, x, y, w, h); + } + } +} + +static inline void dpy_text_resize(DisplayState *s, int w, int h) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_text_resize) { + dcl->dpy_text_resize(s, w, h); + } + } +} + static inline void dpy_mouse_set(struct DisplayState *s, int x, int y, int on) { struct DisplayChangeListener *dcl; diff --git a/hw/blizzard.c b/hw/blizzard.c index 06e19b364b..1b57eb5396 100644 --- a/hw/blizzard.c +++ b/hw/blizzard.c @@ -921,8 +921,8 @@ static void blizzard_update_display(void *opaque) for (; y < s->my[1]; y ++, src += bypl, dst += bypl) memcpy(dst, src, bwidth); - dpy_update(s->state, s->mx[0], s->my[0], - s->mx[1] - s->mx[0], y - s->my[0]); + dpy_gfx_update(s->state, s->mx[0], s->my[0], + s->mx[1] - s->mx[0], y - s->my[0]); s->mx[0] = s->x; s->mx[1] = 0; diff --git a/hw/exynos4210_fimd.c b/hw/exynos4210_fimd.c index 7cb2c31bee..f2443ca4af 100644 --- a/hw/exynos4210_fimd.c +++ b/hw/exynos4210_fimd.c @@ -1307,7 +1307,7 @@ static void exynos4210_fimd_update(void *opaque) fimd_copy_line_toqemu(global_width, s->ifb + global_width * line * RGBA_SIZE, d + global_width * line * bpp); } - dpy_update(s->console, 0, 0, global_width, global_height); + dpy_gfx_update(s->console, 0, 0, global_width, global_height); } s->invalidate = false; s->vidintcon[1] |= FIMD_VIDINT_INTFRMPEND; diff --git a/hw/g364fb.c b/hw/g364fb.c index f7b4bf5ae2..8192baf1c8 100644 --- a/hw/g364fb.c +++ b/hw/g364fb.c @@ -197,7 +197,8 @@ static void g364fb_draw_graphic8(G364State *s) reset_dirty(s, page_min, page_max); page_min = (ram_addr_t)-1; page_max = 0; - dpy_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); + dpy_gfx_update(s->ds, xmin, ymin, + xmax - xmin + 1, ymax - ymin + 1); xmin = s->width; xmax = 0; ymin = s->height; @@ -216,7 +217,7 @@ static void g364fb_draw_graphic8(G364State *s) done: if (page_min != (ram_addr_t)-1) { - dpy_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); + dpy_gfx_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); reset_dirty(s, page_min, page_max); } } @@ -238,7 +239,7 @@ static void g364fb_draw_blank(G364State *s) d += ds_get_linesize(s->ds); } - dpy_update(s->ds, 0, 0, s->width, s->height); + dpy_gfx_update(s->ds, 0, 0, s->width, s->height); s->blanked = 1; } diff --git a/hw/jazz_led.c b/hw/jazz_led.c index 853bf6d4c1..640e75ef2f 100644 --- a/hw/jazz_led.c +++ b/hw/jazz_led.c @@ -196,7 +196,7 @@ static void jazz_led_update_display(void *opaque) } s->state = REDRAW_NONE; - dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds)); + dpy_gfx_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds)); } static void jazz_led_invalidate_display(void *opaque) @@ -218,7 +218,7 @@ static void jazz_led_text_update(void *opaque, console_ch_t *chardata) console_write_ch(chardata++, 0x00200100 | buf[0]); console_write_ch(chardata++, 0x00200100 | buf[1]); - dpy_update(s->ds, 0, 0, 2, 1); + dpy_text_update(s->ds, 0, 0, 2, 1); } static int jazz_led_post_load(void *opaque, int version_id) diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c index 8d36bc10f6..833881cc6a 100644 --- a/hw/milkymist-vgafb.c +++ b/hw/milkymist-vgafb.c @@ -134,7 +134,7 @@ static void vgafb_update_display(void *opaque) &first, &last); if (first >= 0) { - dpy_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1); + dpy_gfx_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1); } s->invalidate = 0; } diff --git a/hw/musicpal.c b/hw/musicpal.c index beec76bf38..e0c57c84eb 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -526,7 +526,7 @@ static void lcd_refresh(void *opaque) ds_get_bits_per_pixel(s->ds)); } - dpy_update(s->ds, 0, 0, 128*3, 64*3); + dpy_gfx_update(s->ds, 0, 0, 128*3, 64*3); } static void lcd_invalidate(void *opaque) diff --git a/hw/nseries.c b/hw/nseries.c index 9306aa15a7..26d5e3507f 100644 --- a/hw/nseries.c +++ b/hw/nseries.c @@ -1376,7 +1376,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device, size until the guest activates the display. */ ds = get_displaystate(); ds->surface = qemu_resize_displaysurface(ds, 800, 480); - dpy_resize(ds); + dpy_gfx_resize(ds); } static struct arm_boot_info n800_binfo = { diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c index bf177c22dd..d7ae3032be 100644 --- a/hw/omap_lcdc.c +++ b/hw/omap_lcdc.c @@ -219,7 +219,7 @@ static void omap_update_display(void *opaque) draw_line, omap_lcd->palette, &first, &last); if (first >= 0) { - dpy_update(omap_lcd->state, 0, first, width, last - first + 1); + dpy_gfx_update(omap_lcd->state, 0, first, width, last - first + 1); } omap_lcd->invalidate = 0; } diff --git a/hw/palm.c b/hw/palm.c index d26305159d..6f6f414e6e 100644 --- a/hw/palm.c +++ b/hw/palm.c @@ -273,7 +273,7 @@ static void palmte_init(QEMUMachineInitArgs *args) will set the size once configured, so this just sets an initial size until the guest activates the display. */ ds->surface = qemu_resize_displaysurface(ds, 320, 320); - dpy_resize(ds); + dpy_gfx_resize(ds); } static QEMUMachine palmte_machine = { diff --git a/hw/pl110.c b/hw/pl110.c index 82486b0c14..79a3f82ddf 100644 --- a/hw/pl110.c +++ b/hw/pl110.c @@ -239,7 +239,7 @@ static void pl110_update_display(void *opaque) fn, s->palette, &first, &last); if (first >= 0) { - dpy_update(s->ds, 0, first, s->cols, last - first + 1); + dpy_gfx_update(s->ds, 0, first, s->cols, last - first + 1); } s->invalidate = 0; } diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c index 38c38890c9..b53dfaf3cf 100644 --- a/hw/pxa2xx_lcd.c +++ b/hw/pxa2xx_lcd.c @@ -871,20 +871,20 @@ static void pxa2xx_update_display(void *opaque) if (miny >= 0) { switch (s->orientation) { case 0: - dpy_update(s->ds, 0, miny, s->xres, maxy - miny + 1); + dpy_gfx_update(s->ds, 0, miny, s->xres, maxy - miny + 1); break; case 90: - dpy_update(s->ds, miny, 0, maxy - miny + 1, s->xres); + dpy_gfx_update(s->ds, miny, 0, maxy - miny + 1, s->xres); break; case 180: maxy = s->yres - maxy - 1; miny = s->yres - miny - 1; - dpy_update(s->ds, 0, maxy, s->xres, miny - maxy + 1); + dpy_gfx_update(s->ds, 0, maxy, s->xres, miny - maxy + 1); break; case 270: maxy = s->yres - maxy - 1; miny = s->yres - miny - 1; - dpy_update(s->ds, maxy, 0, miny - maxy + 1, s->xres); + dpy_gfx_update(s->ds, maxy, 0, miny - maxy + 1, s->xres); break; } } diff --git a/hw/qxl-render.c b/hw/qxl-render.c index e8cf29e62a..47eb8b4154 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -123,17 +123,17 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) qxl->guest_primary.surface.width, qxl->guest_primary.surface.height); } - dpy_resize(vga->ds); + dpy_gfx_resize(vga->ds); } for (i = 0; i < qxl->num_dirty_rects; i++) { if (qemu_spice_rect_is_empty(qxl->dirty+i)) { break; } qxl_blit(qxl, qxl->dirty+i); - dpy_update(vga->ds, - qxl->dirty[i].left, qxl->dirty[i].top, - qxl->dirty[i].right - qxl->dirty[i].left, - qxl->dirty[i].bottom - qxl->dirty[i].top); + dpy_gfx_update(vga->ds, + qxl->dirty[i].left, qxl->dirty[i].top, + qxl->dirty[i].right - qxl->dirty[i].left, + qxl->dirty[i].bottom - qxl->dirty[i].top); } qxl->num_dirty_rects = 0; } diff --git a/hw/qxl.c b/hw/qxl.c index d54daf6d3b..1f56fcd169 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1864,8 +1864,8 @@ static void display_refresh(struct DisplayState *ds) } static DisplayChangeListener display_listener = { - .dpy_update = display_update, - .dpy_resize = display_resize, + .dpy_gfx_update = display_update, + .dpy_gfx_resize = display_resize, .dpy_refresh = display_refresh, }; diff --git a/hw/sm501.c b/hw/sm501.c index 4aafe49cce..50324cda53 100644 --- a/hw/sm501.c +++ b/hw/sm501.c @@ -1351,7 +1351,7 @@ static void sm501_draw_crt(SM501State * s) } else { if (y_start >= 0) { /* flush to display */ - dpy_update(s->ds, 0, y_start, width, y - y_start); + dpy_gfx_update(s->ds, 0, y_start, width, y - y_start); y_start = -1; } } @@ -1362,7 +1362,7 @@ static void sm501_draw_crt(SM501State * s) /* complete flush to display */ if (y_start >= 0) - dpy_update(s->ds, 0, y_start, width, y - y_start); + dpy_gfx_update(s->ds, 0, y_start, width, y - y_start); /* clear dirty flags */ if (page_min != ~0l) { diff --git a/hw/ssd0303.c b/hw/ssd0303.c index 4e1ee6e12b..d7fd828c65 100644 --- a/hw/ssd0303.c +++ b/hw/ssd0303.c @@ -252,7 +252,7 @@ static void ssd0303_update_display(void *opaque) } } s->redraw = 0; - dpy_update(s->ds, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY); + dpy_gfx_update(s->ds, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY); } static void ssd0303_invalidate_display(void * opaque) diff --git a/hw/ssd0323.c b/hw/ssd0323.c index 9c42d648e2..4098830c2b 100644 --- a/hw/ssd0323.c +++ b/hw/ssd0323.c @@ -260,7 +260,7 @@ static void ssd0323_update_display(void *opaque) } } s->redraw = 0; - dpy_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY); + dpy_gfx_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY); } static void ssd0323_invalidate_display(void * opaque) diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c index 31d4f26629..f0320271d4 100644 --- a/hw/tc6393xb.c +++ b/hw/tc6393xb.c @@ -454,7 +454,7 @@ static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update) return; } - dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height); + dpy_gfx_update(s->ds, 0, 0, s->scr_width, s->scr_height); } static void tc6393xb_draw_blank(TC6393xbState *s, int full_update) @@ -472,7 +472,7 @@ static void tc6393xb_draw_blank(TC6393xbState *s, int full_update) d += ds_get_linesize(s->ds); } - dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height); + dpy_gfx_update(s->ds, 0, 0, s->scr_width, s->scr_height); } static void tc6393xb_update_display(void *opaque) diff --git a/hw/tcx.c b/hw/tcx.c index 7abe865e3f..7aee2a9bd3 100644 --- a/hw/tcx.c +++ b/hw/tcx.c @@ -268,8 +268,8 @@ static void tcx_update_display(void *opaque) } else { if (y_start >= 0) { /* flush to display */ - dpy_update(ts->ds, 0, y_start, - ts->width, y - y_start); + dpy_gfx_update(ts->ds, 0, y_start, + ts->width, y - y_start); y_start = -1; } d += dd * 4; @@ -278,8 +278,8 @@ static void tcx_update_display(void *opaque) } if (y_start >= 0) { /* flush to display */ - dpy_update(ts->ds, 0, y_start, - ts->width, y - y_start); + dpy_gfx_update(ts->ds, 0, y_start, + ts->width, y - y_start); } /* reset modified pages */ if (page_max >= page_min) { @@ -344,8 +344,8 @@ static void tcx24_update_display(void *opaque) } else { if (y_start >= 0) { /* flush to display */ - dpy_update(ts->ds, 0, y_start, - ts->width, y - y_start); + dpy_gfx_update(ts->ds, 0, y_start, + ts->width, y - y_start); y_start = -1; } d += dd * 4; @@ -356,8 +356,8 @@ static void tcx24_update_display(void *opaque) } if (y_start >= 0) { /* flush to display */ - dpy_update(ts->ds, 0, y_start, - ts->width, y - y_start); + dpy_gfx_update(ts->ds, 0, y_start, + ts->width, y - y_start); } /* reset modified pages */ if (page_max >= page_min) { diff --git a/hw/vga.c b/hw/vga.c index f3256cb6c7..dc8dddec80 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -1456,8 +1456,8 @@ static void vga_draw_text(VGACommonState *s, int full_update) ch_attr_ptr++; } if (cx_max != -1) { - dpy_update(s->ds, cx_min * cw, cy * cheight, - (cx_max - cx_min + 1) * cw, cheight); + dpy_gfx_update(s->ds, cx_min * cw, cy * cheight, + (cx_max - cx_min + 1) * cw, cheight); } dest += linesize * cheight; line1 = line + cheight; @@ -1688,7 +1688,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) s->ds->surface->pf = qemu_different_endianness_pixelformat(depth); #endif - dpy_resize(s->ds); + dpy_gfx_resize(s->ds); } else { qemu_console_resize(s->ds, disp_width, height); } @@ -1702,7 +1702,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) } else if (is_buffer_shared(s->ds->surface) && (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) { s->ds->surface->data = s->vram_ptr + (s->start_addr * 4); - dpy_setdata(s->ds); + dpy_gfx_setdata(s->ds); } s->rgb_to_pixel = @@ -1807,8 +1807,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) } else { if (y_start >= 0) { /* flush to display */ - dpy_update(s->ds, 0, y_start, - disp_width, y - y_start); + dpy_gfx_update(s->ds, 0, y_start, + disp_width, y - y_start); y_start = -1; } } @@ -1828,8 +1828,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) } if (y_start >= 0) { /* flush to display */ - dpy_update(s->ds, 0, y_start, - disp_width, y - y_start); + dpy_gfx_update(s->ds, 0, y_start, + disp_width, y - y_start); } /* reset modified pages */ if (page_max >= page_min) { @@ -1863,8 +1863,8 @@ static void vga_draw_blank(VGACommonState *s, int full_update) memset(d, val, w); d += ds_get_linesize(s->ds); } - dpy_update(s->ds, 0, 0, - s->last_scr_width, s->last_scr_height); + dpy_gfx_update(s->ds, 0, 0, + s->last_scr_width, s->last_scr_height); } #define GMODE_TEXT 0 @@ -2052,9 +2052,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) cw != s->last_cw || cheight != s->last_ch) { s->last_scr_width = width * cw; s->last_scr_height = height * cheight; - s->ds->surface->width = width; - s->ds->surface->height = height; - dpy_resize(s->ds); + dpy_text_resize(s->ds, width, height); s->last_width = width; s->last_height = height; s->last_ch = cheight; @@ -2087,7 +2085,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) for (i = 0; i < size; src ++, dst ++, i ++) console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src))); - dpy_update(s->ds, 0, 0, width, height); + dpy_text_update(s->ds, 0, 0, width, height); } else { c_max = 0; @@ -2110,7 +2108,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) if (c_min <= c_max) { i = TEXTMODE_Y(c_min); - dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1); + dpy_text_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1); } } @@ -2136,9 +2134,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) s->last_width = 60; s->last_height = height = 3; dpy_text_cursor(s->ds, -1, -1); - s->ds->surface->width = s->last_width; - s->ds->surface->height = height; - dpy_resize(s->ds); + dpy_text_resize(s->ds, s->last_width, height); for (dst = chardata, i = 0; i < s->last_width * height; i ++) console_write_ch(dst ++, ' '); @@ -2149,7 +2145,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) for (i = 0; i < size; i ++) console_write_ch(dst ++, 0x00200100 | msg_buffer[i]); - dpy_update(s->ds, 0, 0, s->last_width, height); + dpy_text_update(s->ds, 0, 0, s->last_width, height); } static uint64_t vga_mem_read(void *opaque, hwaddr addr, diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index dc9279064c..34532e5c3a 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -321,14 +321,14 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s, for (; line > 0; line --, src += bypl, dst += bypl) memcpy(dst, src, width); - dpy_update(s->vga.ds, x, y, w, h); + dpy_gfx_update(s->vga.ds, x, y, w, h); } static inline void vmsvga_update_screen(struct vmsvga_state_s *s) { memcpy(ds_get_data(s->vga.ds), s->vga.vram_ptr, s->bypp * s->width * s->height); - dpy_update(s->vga.ds, 0, 0, s->width, s->height); + dpy_gfx_update(s->vga.ds, 0, 0, s->width, s->height); } static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s, diff --git a/ui/curses.c b/ui/curses.c index c2be2c641a..b40b22307d 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -95,17 +95,16 @@ static void curses_calc_pad(void) } } -static void curses_resize(DisplayState *ds) +static void curses_resize(DisplayState *ds, int width, int height) { - if (ds_get_width(ds) == gwidth && ds_get_height(ds) == gheight) + if (width == gwidth && height == gheight) { return; + } - gwidth = ds_get_width(ds); - gheight = ds_get_height(ds); + gwidth = width; + gheight = height; curses_calc_pad(); - ds->surface->width = width * FONT_WIDTH; - ds->surface->height = height * FONT_HEIGHT; } #ifndef _WIN32 @@ -167,8 +166,6 @@ static void curses_refresh(DisplayState *ds) clear(); refresh(); curses_calc_pad(); - ds->surface->width = FONT_WIDTH * width; - ds->surface->height = FONT_HEIGHT * height; vga_hw_invalidate(); invalidate = 0; } @@ -195,8 +192,6 @@ static void curses_refresh(DisplayState *ds) refresh(); curses_calc_pad(); curses_update(ds, 0, 0, width, height); - ds->surface->width = FONT_WIDTH * width; - ds->surface->height = FONT_HEIGHT * height; continue; } #endif @@ -355,13 +350,11 @@ void curses_display_init(DisplayState *ds, int full_screen) #endif dcl = (DisplayChangeListener *) g_malloc0(sizeof(DisplayChangeListener)); - dcl->dpy_update = curses_update; - dcl->dpy_resize = curses_resize; + dcl->dpy_text_update = curses_update; + dcl->dpy_text_resize = curses_resize; dcl->dpy_refresh = curses_refresh; dcl->dpy_text_cursor = curses_cursor_position; register_displaychangelistener(ds, dcl); - qemu_free_displaysurface(ds); - ds->surface = qemu_create_displaysurface_from(640, 400, 0, 0, (uint8_t*) screen); invalidate = 1; } diff --git a/ui/sdl.c b/ui/sdl.c index f8ead930ae..fac1a4740d 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -553,7 +553,7 @@ static void sdl_scale(DisplayState *ds, int width, int height) if (!is_buffer_shared(ds->surface)) { ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds), ds_get_height(ds)); - dpy_resize(ds); + dpy_gfx_resize(ds); } } @@ -1020,11 +1020,11 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) } dcl = g_malloc0(sizeof(DisplayChangeListener)); - dcl->dpy_update = sdl_update; - dcl->dpy_resize = sdl_resize; + dcl->dpy_gfx_update = sdl_update; + dcl->dpy_gfx_resize = sdl_resize; dcl->dpy_refresh = sdl_refresh; - dcl->dpy_setdata = sdl_setdata; - dcl->dpy_fill = sdl_fill; + dcl->dpy_gfx_setdata = sdl_setdata; + dcl->dpy_gfx_fill = sdl_fill; dcl->dpy_mouse_set = sdl_mouse_warp; dcl->dpy_cursor_define = sdl_mouse_define; register_displaychangelistener(ds, dcl); @@ -1034,7 +1034,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) da->resize_displaysurface = sdl_resize_displaysurface; da->free_displaysurface = sdl_free_displaysurface; if (register_displayallocator(ds, da) == da) { - dpy_resize(ds); + dpy_gfx_resize(ds); } mouse_mode_notifier.notify = sdl_mouse_mode_change; diff --git a/ui/spice-display.c b/ui/spice-display.c index 5779fa8ba6..fb99148349 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -571,8 +571,8 @@ static void display_refresh(struct DisplayState *ds) } static DisplayChangeListener display_listener = { - .dpy_update = display_update, - .dpy_resize = display_resize, + .dpy_gfx_update = display_update, + .dpy_gfx_resize = display_resize, .dpy_refresh = display_refresh, }; diff --git a/ui/vnc.c b/ui/vnc.c index 1b70db7e05..0ae1c74984 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -2753,10 +2753,10 @@ void vnc_display_init(DisplayState *ds) qemu_mutex_init(&vs->mutex); vnc_start_worker_thread(); - dcl->dpy_copy = vnc_dpy_copy; - dcl->dpy_update = vnc_dpy_update; - dcl->dpy_resize = vnc_dpy_resize; - dcl->dpy_setdata = vnc_dpy_setdata; + dcl->dpy_gfx_copy = vnc_dpy_copy; + dcl->dpy_gfx_update = vnc_dpy_update; + dcl->dpy_gfx_resize = vnc_dpy_resize; + dcl->dpy_gfx_setdata = vnc_dpy_setdata; dcl->dpy_mouse_set = vnc_mouse_set; dcl->dpy_cursor_define = vnc_dpy_cursor_define; register_displaychangelistener(ds, dcl); diff --git a/vl.c b/vl.c index 4c45b02f05..8716fc0a6c 100644 --- a/vl.c +++ b/vl.c @@ -1375,11 +1375,18 @@ void gui_setup_refresh(DisplayState *ds) { DisplayChangeListener *dcl; bool need_timer = false; + bool have_gfx = false; + bool have_text = false; QLIST_FOREACH(dcl, &ds->listeners, next) { if (dcl->dpy_refresh != NULL) { need_timer = true; - break; + } + if (dcl->dpy_gfx_update != NULL) { + have_gfx = true; + } + if (dcl->dpy_text_update != NULL) { + have_text = true; } } @@ -1392,6 +1399,9 @@ void gui_setup_refresh(DisplayState *ds) qemu_free_timer(ds->gui_timer); ds->gui_timer = NULL; } + + ds->have_gfx = have_gfx; + ds->have_text = have_text; } struct vm_change_state_entry { @@ -3866,7 +3876,7 @@ int main(int argc, char **argv, char **envp) #endif /* display setup */ - dpy_resize(ds); + dpy_gfx_resize(ds); text_consoles_set_display(ds); if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { From e250d949feb1334828f27f0d145c35f29c4b7639 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 28 Sep 2012 15:30:07 +0200 Subject: [PATCH 1446/2270] console: init displaychangelisteners on register Signed-off-by: Gerd Hoffmann --- console.h | 3 +++ vl.c | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/console.h b/console.h index 00e2f03424..7e0ac760e3 100644 --- a/console.h +++ b/console.h @@ -241,6 +241,9 @@ static inline void register_displaychangelistener(DisplayState *ds, DisplayChang { QLIST_INSERT_HEAD(&ds->listeners, dcl, next); gui_setup_refresh(ds); + if (dcl->dpy_gfx_resize) { + dcl->dpy_gfx_resize(ds); + } } static inline void unregister_displaychangelistener(DisplayState *ds, diff --git a/vl.c b/vl.c index 8716fc0a6c..df776e91ad 100644 --- a/vl.c +++ b/vl.c @@ -3876,7 +3876,6 @@ int main(int argc, char **argv, char **envp) #endif /* display setup */ - dpy_gfx_resize(ds); text_consoles_set_display(ds); if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { From 9678aedd8e76978465698b9edeb069ccee15e975 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 9 Oct 2012 17:10:13 +0200 Subject: [PATCH 1447/2270] vga: fix text mode updating With both text (curses) and graphics (vnc/sdl/spice/...) display active vga text mode emulation fails to update both correctly. Depending on whenever vga_update_text() or vga_draw_text() happens to be called first only the text display or only the graphics display will see display resolution changes and full redraws. Fix it by calling both text/gfx resize functions in both code paths and keep track of full screen redraws needed in VGACommonState fields. Signed-off-by: Gerd Hoffmann --- hw/vga.c | 19 +++++++++++++++++++ hw/vga_int.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/hw/vga.c b/hw/vga.c index dc8dddec80..f31dbdd652 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -1346,6 +1346,7 @@ static void vga_draw_text(VGACommonState *s, int full_update) s->last_scr_width = width * cw; s->last_scr_height = height * cheight; qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height); + dpy_text_resize(s->ds, width, height); s->last_depth = 0; s->last_width = width; s->last_height = height; @@ -1359,6 +1360,14 @@ static void vga_draw_text(VGACommonState *s, int full_update) palette = s->last_palette; x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3); + if (full_update) { + s->full_update_text = 1; + } + if (s->full_update_gfx) { + s->full_update_gfx = 0; + full_update |= 1; + } + cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) | s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr; if (cursor_offset != s->cursor_offset || @@ -2052,7 +2061,9 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) cw != s->last_cw || cheight != s->last_ch) { s->last_scr_width = width * cw; s->last_scr_height = height * cheight; + qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height); dpy_text_resize(s->ds, width, height); + s->last_depth = 0; s->last_width = width; s->last_height = height; s->last_ch = cheight; @@ -2060,6 +2071,14 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) full_update = 1; } + if (full_update) { + s->full_update_gfx = 1; + } + if (s->full_update_text) { + s->full_update_text = 0; + full_update |= 1; + } + /* Update "hardware" cursor */ cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) | s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr; diff --git a/hw/vga_int.h b/hw/vga_int.h index 22f1706adf..d4da777e62 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -154,6 +154,8 @@ typedef struct VGACommonState { vga_hw_invalidate_ptr invalidate; vga_hw_screen_dump_ptr screen_dump; vga_hw_text_update_ptr text_update; + bool full_update_text; + bool full_update_gfx; /* hardware mouse cursor support */ uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; void (*cursor_invalidate)(struct VGACommonState *s); From 4dc6a39bbd1a03f86797e0df2db285318f086aee Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 28 Sep 2012 15:31:33 +0200 Subject: [PATCH 1448/2270] console: remove dpy_gfx_fill Unused code. 'nuff said. Signed-off-by: Gerd Hoffmann --- console.h | 13 ------------- ui/sdl.c | 7 ------- 2 files changed, 20 deletions(-) diff --git a/console.h b/console.h index 7e0ac760e3..6492e67bd2 100644 --- a/console.h +++ b/console.h @@ -161,8 +161,6 @@ struct DisplayChangeListener { void (*dpy_gfx_setdata)(struct DisplayState *s); void (*dpy_gfx_copy)(struct DisplayState *s, int src_x, int src_y, int dst_x, int dst_y, int w, int h); - void (*dpy_gfx_fill)(struct DisplayState *s, int x, int y, - int w, int h, uint32_t c); void (*dpy_text_cursor)(struct DisplayState *s, int x, int y); void (*dpy_text_resize)(struct DisplayState *s, int w, int h); @@ -306,17 +304,6 @@ static inline void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y, } } -static inline void dpy_gfx_fill(struct DisplayState *s, int x, int y, - int w, int h, uint32_t c) -{ - struct DisplayChangeListener *dcl; - QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_gfx_fill) { - dcl->dpy_gfx_fill(s, x, y, w, h, c); - } - } -} - static inline void dpy_text_cursor(struct DisplayState *s, int x, int y) { struct DisplayChangeListener *dcl; diff --git a/ui/sdl.c b/ui/sdl.c index fac1a4740d..c3ba79fe43 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -899,12 +899,6 @@ static void sdl_refresh(DisplayState *ds) } } -static void sdl_fill(DisplayState *ds, int x, int y, int w, int h, uint32_t c) -{ - SDL_Rect dst = { x, y, w, h }; - SDL_FillRect(real_screen, &dst, c); -} - static void sdl_mouse_warp(DisplayState *ds, int x, int y, int on) { if (on) { @@ -1024,7 +1018,6 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) dcl->dpy_gfx_resize = sdl_resize; dcl->dpy_refresh = sdl_refresh; dcl->dpy_gfx_setdata = sdl_setdata; - dcl->dpy_gfx_fill = sdl_fill; dcl->dpy_mouse_set = sdl_mouse_warp; dcl->dpy_cursor_define = sdl_mouse_define; register_displaychangelistener(ds, dcl); From 187cd1d9f30d13f0d0ef682e4d91cfa3e4cbd472 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 26 Sep 2012 07:46:20 +0200 Subject: [PATCH 1449/2270] console: remove DisplayAllocator Causes [temporary] preformance regression with 24bpp vga modes @ sdl. Signed-off-by: Gerd Hoffmann --- console.c | 52 ++++++++-------------- console.h | 34 +++------------ qemu-common.h | 1 - ui/sdl.c | 117 +++----------------------------------------------- 4 files changed, 31 insertions(+), 173 deletions(-) diff --git a/console.c b/console.c index 61812c7c7f..71cc543b7b 100644 --- a/console.c +++ b/console.c @@ -1294,9 +1294,10 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type) return s; } -static DisplaySurface* defaultallocator_create_displaysurface(int width, int height) +DisplaySurface *qemu_create_displaysurface(DisplayState *ds, + int width, int height) { - DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface)); + DisplaySurface *surface = g_new0(DisplaySurface, 1); int linesize = width * 4; qemu_alloc_display(surface, width, height, linesize, @@ -1304,13 +1305,15 @@ static DisplaySurface* defaultallocator_create_displaysurface(int width, int hei return surface; } -static DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface, - int width, int height) +DisplaySurface *qemu_resize_displaysurface(DisplayState *ds, + int width, int height) { int linesize = width * 4; - qemu_alloc_display(surface, width, height, linesize, + + trace_displaysurface_resize(ds, ds->surface, width, height); + qemu_alloc_display(ds->surface, width, height, linesize, qemu_default_pixelformat(32), 0); - return surface; + return ds->surface; } void qemu_alloc_display(DisplaySurface *surface, int width, int height, @@ -1323,7 +1326,7 @@ void qemu_alloc_display(DisplaySurface *surface, int width, int height, surface->pf = pf; if (surface->flags & QEMU_ALLOCATED_FLAG) { data = g_realloc(surface->data, - surface->linesize * surface->height); + surface->linesize * surface->height); } else { data = g_malloc(surface->linesize * surface->height); } @@ -1334,7 +1337,7 @@ void qemu_alloc_display(DisplaySurface *surface, int width, int height, #endif } -DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, +DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp, int linesize, uint8_t *data) { DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface)); @@ -1351,28 +1354,24 @@ DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, return surface; } -static void defaultallocator_free_displaysurface(DisplaySurface *surface) +void qemu_free_displaysurface(DisplayState *ds) { - if (surface == NULL) + trace_displaysurface_free(ds, ds->surface); + if (ds->surface == NULL) { return; - if (surface->flags & QEMU_ALLOCATED_FLAG) - g_free(surface->data); - g_free(surface); + } + if (ds->surface->flags & QEMU_ALLOCATED_FLAG) { + g_free(ds->surface->data); + } + g_free(ds->surface); } -static struct DisplayAllocator default_allocator = { - defaultallocator_create_displaysurface, - defaultallocator_resize_displaysurface, - defaultallocator_free_displaysurface -}; - static void dumb_display_init(void) { DisplayState *ds = g_malloc0(sizeof(DisplayState)); int width = 640; int height = 480; - ds->allocator = &default_allocator; if (is_fixedsize_console()) { width = active_console->g_width; height = active_console->g_height; @@ -1402,18 +1401,6 @@ DisplayState *get_displaystate(void) return display_state; } -DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da) -{ - if(ds->allocator == &default_allocator) { - DisplaySurface *surf; - surf = da->create_displaysurface(ds_get_width(ds), ds_get_height(ds)); - defaultallocator_free_displaysurface(ds->surface); - ds->surface = surf; - ds->allocator = da; - } - return ds->allocator; -} - DisplayState *graphic_console_init(vga_hw_update_ptr update, vga_hw_invalidate_ptr invalidate, vga_hw_screen_dump_ptr screen_dump, @@ -1424,7 +1411,6 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update, DisplayState *ds; ds = (DisplayState *) g_malloc0(sizeof(DisplayState)); - ds->allocator = &default_allocator; ds->surface = qemu_create_displaysurface(ds, 640, 480); s = new_console(ds, GRAPHIC_CONSOLE); diff --git a/console.h b/console.h index 6492e67bd2..6be880a554 100644 --- a/console.h +++ b/console.h @@ -107,7 +107,6 @@ void kbd_put_keysym(int keysym); #define QEMU_BIG_ENDIAN_FLAG 0x01 #define QEMU_ALLOCATED_FLAG 0x02 -#define QEMU_REALPIXELS_FLAG 0x04 struct PixelFormat { uint8_t bits_per_pixel; @@ -172,12 +171,6 @@ struct DisplayChangeListener { QLIST_ENTRY(DisplayChangeListener) next; }; -struct DisplayAllocator { - DisplaySurface* (*create_displaysurface)(int width, int height); - DisplaySurface* (*resize_displaysurface)(DisplaySurface *surface, int width, int height); - void (*free_displaysurface)(DisplaySurface *surface); -}; - struct DisplayState { struct DisplaySurface *surface; void *opaque; @@ -185,7 +178,6 @@ struct DisplayState { bool have_gfx; bool have_text; - struct DisplayAllocator* allocator; QLIST_HEAD(, DisplayChangeListener) listeners; struct DisplayState *next; @@ -200,24 +192,11 @@ void qemu_alloc_display(DisplaySurface *surface, int width, int height, PixelFormat qemu_different_endianness_pixelformat(int bpp); PixelFormat qemu_default_pixelformat(int bpp); -DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da); - -static inline DisplaySurface* qemu_create_displaysurface(DisplayState *ds, int width, int height) -{ - return ds->allocator->create_displaysurface(width, height); -} - -static inline DisplaySurface* qemu_resize_displaysurface(DisplayState *ds, int width, int height) -{ - trace_displaysurface_resize(ds, ds->surface, width, height); - return ds->allocator->resize_displaysurface(ds->surface, width, height); -} - -static inline void qemu_free_displaysurface(DisplayState *ds) -{ - trace_displaysurface_free(ds, ds->surface); - ds->allocator->free_displaysurface(ds->surface); -} +DisplaySurface *qemu_create_displaysurface(DisplayState *ds, + int width, int height); +DisplaySurface *qemu_resize_displaysurface(DisplayState *ds, + int width, int height); +void qemu_free_displaysurface(DisplayState *ds); static inline int is_surface_bgr(DisplaySurface *surface) { @@ -229,8 +208,7 @@ static inline int is_surface_bgr(DisplaySurface *surface) static inline int is_buffer_shared(DisplaySurface *surface) { - return (!(surface->flags & QEMU_ALLOCATED_FLAG) && - !(surface->flags & QEMU_REALPIXELS_FLAG)); + return !(surface->flags & QEMU_ALLOCATED_FLAG); } void gui_setup_refresh(DisplayState *ds); diff --git a/qemu-common.h b/qemu-common.h index fdd0dbcf64..89cec1d817 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -262,7 +262,6 @@ typedef struct DriveInfo DriveInfo; typedef struct DisplayState DisplayState; typedef struct DisplayChangeListener DisplayChangeListener; typedef struct DisplaySurface DisplaySurface; -typedef struct DisplayAllocator DisplayAllocator; typedef struct PixelFormat PixelFormat; typedef struct QemuConsole QemuConsole; typedef struct CharDriverState CharDriverState; diff --git a/ui/sdl.c b/ui/sdl.c index c3ba79fe43..37f01b217d 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -55,7 +55,6 @@ static int absolute_enabled = 0; static int guest_cursor = 0; static int guest_x, guest_y; static SDL_Cursor *guest_sprite = NULL; -static uint8_t allocator; static SDL_PixelFormat host_format; static int scaling_active = 0; static Notifier mouse_mode_notifier; @@ -117,108 +116,13 @@ static void do_sdl_resize(int width, int height, int bpp) static void sdl_resize(DisplayState *ds) { - if (!allocator) { - if (!scaling_active) - do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0); - else if (real_screen->format->BitsPerPixel != ds_get_bits_per_pixel(ds)) - do_sdl_resize(real_screen->w, real_screen->h, ds_get_bits_per_pixel(ds)); - sdl_setdata(ds); - } else { - if (guest_screen != NULL) { - SDL_FreeSurface(guest_screen); - guest_screen = NULL; - } + if (!scaling_active) { + do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0); + } else if (real_screen->format->BitsPerPixel != ds_get_bits_per_pixel(ds)) { + do_sdl_resize(real_screen->w, real_screen->h, + ds_get_bits_per_pixel(ds)); } -} - -static PixelFormat sdl_to_qemu_pixelformat(SDL_PixelFormat *sdl_pf) -{ - PixelFormat qemu_pf; - - memset(&qemu_pf, 0x00, sizeof(PixelFormat)); - - qemu_pf.bits_per_pixel = sdl_pf->BitsPerPixel; - qemu_pf.bytes_per_pixel = sdl_pf->BytesPerPixel; - qemu_pf.depth = (qemu_pf.bits_per_pixel) == 32 ? 24 : (qemu_pf.bits_per_pixel); - - qemu_pf.rmask = sdl_pf->Rmask; - qemu_pf.gmask = sdl_pf->Gmask; - qemu_pf.bmask = sdl_pf->Bmask; - qemu_pf.amask = sdl_pf->Amask; - - qemu_pf.rshift = sdl_pf->Rshift; - qemu_pf.gshift = sdl_pf->Gshift; - qemu_pf.bshift = sdl_pf->Bshift; - qemu_pf.ashift = sdl_pf->Ashift; - - qemu_pf.rbits = 8 - sdl_pf->Rloss; - qemu_pf.gbits = 8 - sdl_pf->Gloss; - qemu_pf.bbits = 8 - sdl_pf->Bloss; - qemu_pf.abits = 8 - sdl_pf->Aloss; - - qemu_pf.rmax = ((1 << qemu_pf.rbits) - 1); - qemu_pf.gmax = ((1 << qemu_pf.gbits) - 1); - qemu_pf.bmax = ((1 << qemu_pf.bbits) - 1); - qemu_pf.amax = ((1 << qemu_pf.abits) - 1); - - return qemu_pf; -} - -static DisplaySurface* sdl_create_displaysurface(int width, int height) -{ - DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface)); - - surface->width = width; - surface->height = height; - - if (scaling_active) { - int linesize; - PixelFormat pf; - if (host_format.BytesPerPixel != 2 && host_format.BytesPerPixel != 4) { - linesize = width * 4; - pf = qemu_default_pixelformat(32); - } else { - linesize = width * host_format.BytesPerPixel; - pf = sdl_to_qemu_pixelformat(&host_format); - } - qemu_alloc_display(surface, width, height, linesize, pf, 0); - return surface; - } - - if (host_format.BitsPerPixel == 16) - do_sdl_resize(width, height, 16); - else - do_sdl_resize(width, height, 32); - - surface->pf = sdl_to_qemu_pixelformat(real_screen->format); - surface->linesize = real_screen->pitch; - surface->data = real_screen->pixels; - -#ifdef HOST_WORDS_BIGENDIAN - surface->flags = QEMU_REALPIXELS_FLAG | QEMU_BIG_ENDIAN_FLAG; -#else - surface->flags = QEMU_REALPIXELS_FLAG; -#endif - allocator = 1; - - return surface; -} - -static void sdl_free_displaysurface(DisplaySurface *surface) -{ - allocator = 0; - if (surface == NULL) - return; - - if (surface->flags & QEMU_ALLOCATED_FLAG) - g_free(surface->data); - g_free(surface); -} - -static DisplaySurface* sdl_resize_displaysurface(DisplaySurface *surface, int width, int height) -{ - sdl_free_displaysurface(surface); - return sdl_create_displaysurface(width, height); + sdl_setdata(ds); } /* generic keyboard conversion */ @@ -949,7 +853,6 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) { int flags; uint8_t data = 0; - DisplayAllocator *da; const SDL_VideoInfo *vi; char *filename; @@ -1022,14 +925,6 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) dcl->dpy_cursor_define = sdl_mouse_define; register_displaychangelistener(ds, dcl); - da = g_malloc0(sizeof(DisplayAllocator)); - da->create_displaysurface = sdl_create_displaysurface; - da->resize_displaysurface = sdl_resize_displaysurface; - da->free_displaysurface = sdl_free_displaysurface; - if (register_displayallocator(ds, da) == da) { - dpy_gfx_resize(ds); - } - mouse_mode_notifier.notify = sdl_mouse_mode_change; qemu_add_mouse_mode_change_notifier(&mouse_mode_notifier); From 9f2c7d7d67c228ae6a02f50082f0c6d10703f483 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 27 Sep 2012 09:52:35 +0200 Subject: [PATCH 1450/2270] pixman: add submodule Add pixman submodule as fallback for old distros. Picking version 0.18.4. This is shipped by rhel6 and also the minimum version needed by spice so this should serve well as baseline. Signed-off-by: Gerd Hoffmann --- .gitmodules | 3 +++ pixman | 1 + 2 files changed, 4 insertions(+) create mode 160000 pixman diff --git a/.gitmodules b/.gitmodules index eca876f85d..cfa2af9f7a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "roms/sgabios"] path = roms/sgabios url = git://git.qemu.org/sgabios.git +[submodule "pixman"] + path = pixman + url = git://anongit.freedesktop.org/pixman diff --git a/pixman b/pixman new file mode 160000 index 0000000000..97336fad32 --- /dev/null +++ b/pixman @@ -0,0 +1 @@ +Subproject commit 97336fad32acf802003855cd8bd6477fa49a12e3 From 85e05d825f7a9ecc1b5100bdd553fcc682c8366e Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 26 Oct 2012 10:10:54 +0200 Subject: [PATCH 1451/2270] xhci: add {get,set}_field macros & enum for pls Add {get,set}_field macros (simliar to ehci) to read and update some bits of a word. Put them into use for updating pls (port link state) values. Also add a enum for pls values. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 7b65741dd5..c062330f8a 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -146,6 +146,21 @@ typedef struct XHCITRB { bool ccs; } XHCITRB; +enum { + PLS_U0 = 0, + PLS_U1 = 1, + PLS_U2 = 2, + PLS_U3 = 3, + PLS_DISABLED = 4, + PLS_RX_DETECT = 5, + PLS_INACTIVE = 6, + PLS_POLLING = 7, + PLS_RECOVERY = 8, + PLS_HOT_RESET = 9, + PLS_COMPILANCE_MODE = 10, + PLS_TEST_MODE = 11, + PLS_RESUME = 15, +}; typedef enum TRBType { TRB_RESERVED = 0, @@ -287,6 +302,16 @@ typedef enum TRBCCode { typedef struct XHCIState XHCIState; +#define get_field(data, field) \ + (((data) >> field##_SHIFT) & field##_MASK) + +#define set_field(data, newval, field) do { \ + uint32_t val = *data; \ + val &= ~(field##_MASK << field##_SHIFT); \ + val |= ((newval) & field##_MASK) << field##_SHIFT; \ + *data = val; \ + } while (0) + typedef enum EPType { ET_INVALID = 0, ET_ISO_OUT, @@ -2334,7 +2359,7 @@ static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach) } } - if (xhci_running(xhci)) { + if (xhci_running(port->xhci)) { port->portsc |= PORTSC_CSC; XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, port->portnr << 24}; @@ -2368,7 +2393,7 @@ static void xhci_reset(DeviceState *dev) } for (i = 0; i < xhci->numports; i++) { - xhci_update_port(xhci, xhci->ports + i, 0); + xhci_update_port(xhci->ports + i, 0); } for (i = 0; i < xhci->numintrs; i++) { @@ -2499,8 +2524,8 @@ static void xhci_port_write(void *ptr, hwaddr reg, PORTSC_PRC|PORTSC_PLC|PORTSC_CEC)); if (val & PORTSC_LWS) { /* overwrite PLS only when LWS=1 */ - portsc &= ~(PORTSC_PLS_MASK << PORTSC_PLS_SHIFT); - portsc |= val & (PORTSC_PLS_MASK << PORTSC_PLS_SHIFT); + uint32_t pls = get_field(val, PORTSC_PLS); + set_field(&portsc, pls, PORTSC_PLS); } /* read/write bits */ portsc &= ~(PORTSC_PP|PORTSC_WCE|PORTSC_WDE|PORTSC_WOE); @@ -2832,13 +2857,11 @@ static void xhci_wakeup(USBPort *usbport) XHCIPort *port = xhci_lookup_port(xhci, usbport); XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, port->portnr << 24}; - uint32_t pls; - pls = (port->portsc >> PORTSC_PLS_SHIFT) & PORTSC_PLS_MASK; - if (pls != 3) { + if (get_field(port->portsc, PORTSC_PLS) != PLS_U3) { return; } - port->portsc |= 0xf << PORTSC_PLS_SHIFT; + set_field(&port->portsc, PLS_RESUME, PORTSC_PLS); if (port->portsc & PORTSC_PLC) { return; } From f321402785f443d7b95e746aae686e28d74e344c Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 26 Oct 2012 10:13:13 +0200 Subject: [PATCH 1452/2270] xhci: s/xhci_update_port/xhci_port_update/ Rename the function for xhci_port_* naming scheme, also drop the xhci parameter as port carries a pointer to xhci anyway. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index c062330f8a..f5ab6928ae 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2337,7 +2337,7 @@ static void xhci_process_commands(XHCIState *xhci) } } -static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach) +static void xhci_port_update(XHCIPort *port, int is_detach) { port->portsc = PORTSC_PP; if (port->uport->dev && port->uport->dev->attached && !is_detach && @@ -2363,7 +2363,7 @@ static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach) port->portsc |= PORTSC_CSC; XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, port->portnr << 24}; - xhci_event(xhci, &ev, 0); + xhci_event(port->xhci, &ev, 0); DPRINTF("xhci: port change event for port %d\n", port->portnr); } } @@ -2393,7 +2393,7 @@ static void xhci_reset(DeviceState *dev) } for (i = 0; i < xhci->numports; i++) { - xhci_update_port(xhci->ports + i, 0); + xhci_port_update(xhci->ports + i, 0); } for (i = 0; i < xhci->numintrs; i++) { @@ -2840,7 +2840,7 @@ static void xhci_attach(USBPort *usbport) XHCIState *xhci = usbport->opaque; XHCIPort *port = xhci_lookup_port(xhci, usbport); - xhci_update_port(xhci, port, 0); + xhci_port_update(port, 0); } static void xhci_detach(USBPort *usbport) @@ -2848,7 +2848,7 @@ static void xhci_detach(USBPort *usbport) XHCIState *xhci = usbport->opaque; XHCIPort *port = xhci_lookup_port(xhci, usbport); - xhci_update_port(xhci, port, 1); + xhci_port_update(port, 1); } static void xhci_wakeup(USBPort *usbport) From 6a32f80f056b577d275268e4f6f3477ba721c94f Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 26 Oct 2012 10:15:47 +0200 Subject: [PATCH 1453/2270] xhci: add xhci_port_have_device Factor out the code which checks whenever a usb device is attached to the port in question. No functional change. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index f5ab6928ae..62cca90a3c 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2337,11 +2337,21 @@ static void xhci_process_commands(XHCIState *xhci) } } +static bool xhci_port_have_device(XHCIPort *port) +{ + if (!port->uport->dev || !port->uport->dev->attached) { + return false; /* no device present */ + } + if (!((1 << port->uport->dev->speed) & port->speedmask)) { + return false; /* speed mismatch */ + } + return true; +} + static void xhci_port_update(XHCIPort *port, int is_detach) { port->portsc = PORTSC_PP; - if (port->uport->dev && port->uport->dev->attached && !is_detach && - (1 << port->uport->dev->speed) & port->speedmask) { + if (!is_detach && xhci_port_have_device(port)) { port->portsc |= PORTSC_CCS; switch (port->uport->dev->speed) { case USB_SPEED_LOW: From f705a362800733c363f0458f75942f8dc61b7abb Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 26 Oct 2012 10:19:02 +0200 Subject: [PATCH 1454/2270] xhci: add xhci_port_notify Create a function to notify the guest about port status changes and put it into use. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 62cca90a3c..3af463986d 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2348,6 +2348,21 @@ static bool xhci_port_have_device(XHCIPort *port) return true; } +static void xhci_port_notify(XHCIPort *port, uint32_t bits) +{ + XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, + port->portnr << 24 }; + + if ((port->portsc & bits) == bits) { + return; + } + port->portsc |= bits; + if (!xhci_running(port->xhci)) { + return; + } + xhci_event(port->xhci, &ev, 0); +} + static void xhci_port_update(XHCIPort *port, int is_detach) { port->portsc = PORTSC_PP; @@ -2369,13 +2384,7 @@ static void xhci_port_update(XHCIPort *port, int is_detach) } } - if (xhci_running(port->xhci)) { - port->portsc |= PORTSC_CSC; - XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, - port->portnr << 24}; - xhci_event(port->xhci, &ev, 0); - DPRINTF("xhci: port change event for port %d\n", port->portnr); - } + xhci_port_notify(port, PORTSC_CSC); } static void xhci_reset(DeviceState *dev) @@ -2865,18 +2874,12 @@ static void xhci_wakeup(USBPort *usbport) { XHCIState *xhci = usbport->opaque; XHCIPort *port = xhci_lookup_port(xhci, usbport); - XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, - port->portnr << 24}; if (get_field(port->portsc, PORTSC_PLS) != PLS_U3) { return; } set_field(&port->portsc, PLS_RESUME, PORTSC_PLS); - if (port->portsc & PORTSC_PLC) { - return; - } - port->portsc |= PORTSC_PLC; - xhci_event(xhci, &ev, 0); + xhci_port_notify(port, PORTSC_PLC); } static void xhci_complete(USBPort *port, USBPacket *packet) From 40030130d167f2bf762155a1a7e0073de5545e8b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 26 Oct 2012 10:22:37 +0200 Subject: [PATCH 1455/2270] xhci: add xhci_port_reset Move port reset logic to its own function. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 3af463986d..1db803cda9 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2387,6 +2387,13 @@ static void xhci_port_update(XHCIPort *port, int is_detach) xhci_port_notify(port, PORTSC_CSC); } +static void xhci_port_reset(XHCIPort *port) +{ + DPRINTF("xhci: port %d reset\n", port); + usb_device_reset(port->uport->dev); + port->portsc |= PORTSC_PRC | PORTSC_PED; +} + static void xhci_reset(DeviceState *dev) { XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev.qdev, dev); @@ -2549,13 +2556,11 @@ static void xhci_port_write(void *ptr, hwaddr reg, /* read/write bits */ portsc &= ~(PORTSC_PP|PORTSC_WCE|PORTSC_WDE|PORTSC_WOE); portsc |= (val & (PORTSC_PP|PORTSC_WCE|PORTSC_WDE|PORTSC_WOE)); + port->portsc = portsc; /* write-1-to-start bits */ if (val & PORTSC_PR) { - DPRINTF("xhci: port %d reset\n", port); - usb_device_reset(port->uport->dev); - portsc |= PORTSC_PRC | PORTSC_PED; + xhci_port_reset(port); } - port->portsc = portsc; break; case 0x04: /* PORTPMSC */ case 0x08: /* PORTLI */ From b62b08282d9539a109b02e217d0cc7f7dcdb87ac Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 26 Oct 2012 10:30:53 +0200 Subject: [PATCH 1456/2270] xhci: set pls in xhci_port_update & xhci_port_reset Set the port link state to the correct values in xhci_port_update and xhci_port_reset functions. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 1db803cda9..84d1b26bbb 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2365,33 +2365,55 @@ static void xhci_port_notify(XHCIPort *port, uint32_t bits) static void xhci_port_update(XHCIPort *port, int is_detach) { + uint32_t pls = PLS_RX_DETECT; + port->portsc = PORTSC_PP; if (!is_detach && xhci_port_have_device(port)) { port->portsc |= PORTSC_CCS; switch (port->uport->dev->speed) { case USB_SPEED_LOW: port->portsc |= PORTSC_SPEED_LOW; + pls = PLS_POLLING; break; case USB_SPEED_FULL: port->portsc |= PORTSC_SPEED_FULL; + pls = PLS_POLLING; break; case USB_SPEED_HIGH: port->portsc |= PORTSC_SPEED_HIGH; + pls = PLS_POLLING; break; case USB_SPEED_SUPER: port->portsc |= PORTSC_SPEED_SUPER; + port->portsc |= PORTSC_PED; + pls = PLS_U0; break; } } - + set_field(&port->portsc, pls, PORTSC_PLS); xhci_port_notify(port, PORTSC_CSC); } static void xhci_port_reset(XHCIPort *port) { DPRINTF("xhci: port %d reset\n", port); + if (!xhci_port_have_device(port)) { + return; + } + usb_device_reset(port->uport->dev); - port->portsc |= PORTSC_PRC | PORTSC_PED; + + switch (port->uport->dev->speed) { + case USB_SPEED_LOW: + case USB_SPEED_FULL: + case USB_SPEED_HIGH: + set_field(&port->portsc, PLS_U0, PORTSC_PLS); + port->portsc |= PORTSC_PED; + break; + } + + port->portsc &= ~PORTSC_PR; + xhci_port_notify(port, PORTSC_PRC); } static void xhci_reset(DeviceState *dev) From 4f47f0f82eccbda44bac929df94fa244bf3452bd Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 26 Oct 2012 11:49:06 +0200 Subject: [PATCH 1457/2270] xhci: add port trace points Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 6 +++++- trace-events | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 84d1b26bbb..325963882d 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2391,12 +2391,14 @@ static void xhci_port_update(XHCIPort *port, int is_detach) } } set_field(&port->portsc, pls, PORTSC_PLS); + trace_usb_xhci_port_link(port->portnr, pls); xhci_port_notify(port, PORTSC_CSC); } static void xhci_port_reset(XHCIPort *port) { - DPRINTF("xhci: port %d reset\n", port); + trace_usb_xhci_port_reset(port->portnr); + if (!xhci_port_have_device(port)) { return; } @@ -2408,6 +2410,7 @@ static void xhci_port_reset(XHCIPort *port) case USB_SPEED_FULL: case USB_SPEED_HIGH: set_field(&port->portsc, PLS_U0, PORTSC_PLS); + trace_usb_xhci_port_link(port->portnr, PLS_U0); port->portsc |= PORTSC_PED; break; } @@ -2574,6 +2577,7 @@ static void xhci_port_write(void *ptr, hwaddr reg, /* overwrite PLS only when LWS=1 */ uint32_t pls = get_field(val, PORTSC_PLS); set_field(&portsc, pls, PORTSC_PLS); + trace_usb_xhci_port_link(port->portnr, pls); } /* read/write bits */ portsc &= ~(PORTSC_PP|PORTSC_WCE|PORTSC_WDE|PORTSC_WOE); diff --git a/trace-events b/trace-events index 7ee21e58ea..0cb991e789 100644 --- a/trace-events +++ b/trace-events @@ -333,6 +333,8 @@ usb_xhci_irq_msix_use(uint32_t nr) "nr %d" usb_xhci_irq_msix_unuse(uint32_t nr) "nr %d" usb_xhci_queue_event(uint32_t vector, uint32_t idx, const char *trb, const char *evt, uint64_t param, uint32_t status, uint32_t control) "v %d, idx %d, %s, %s, p %016" PRIx64 ", s %08x, c 0x%08x" usb_xhci_fetch_trb(uint64_t addr, const char *name, uint64_t param, uint32_t status, uint32_t control) "addr %016" PRIx64 ", %s, p %016" PRIx64 ", s %08x, c 0x%08x" +usb_xhci_port_reset(uint32_t port) "port %d" +usb_xhci_port_link(uint32_t port, uint32_t pls) "port %d, pls %d" usb_xhci_slot_enable(uint32_t slotid) "slotid %d" usb_xhci_slot_disable(uint32_t slotid) "slotid %d" usb_xhci_slot_address(uint32_t slotid) "slotid %d" From 0bc85da69e01f25c27f575ef0d57d29be4154d71 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 26 Oct 2012 13:09:56 +0200 Subject: [PATCH 1458/2270] xhci: allow address slot being called multiple times win8 guests do that for some reason ... Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 325963882d..900abf5566 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -483,6 +483,8 @@ enum xhci_flags { static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid); +static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid, + unsigned int epid); static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v); static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v); @@ -1075,8 +1077,7 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, slot = &xhci->slots[slotid-1]; if (slot->eps[epid-1]) { - fprintf(stderr, "xhci: slot %d ep %d already enabled!\n", slotid, epid); - return CC_TRB_ERROR; + xhci_disable_ep(xhci, slotid, epid); } epctx = g_malloc(sizeof(XHCIEPContext)); @@ -1919,6 +1920,9 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, } for (i = 0; i < xhci->numslots; i++) { + if (i == slotid-1) { + continue; + } if (xhci->slots[i].uport == uport) { fprintf(stderr, "xhci: port %s already assigned to slot %d\n", uport->path, i+1); @@ -1936,6 +1940,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, slot->devaddr = xhci->devaddr++; slot_ctx[3] = (SLOT_ADDRESSED << SLOT_STATE_SHIFT) | slot->devaddr; DPRINTF("xhci: device address is %d\n", slot->devaddr); + usb_device_reset(dev); usb_device_handle_control(dev, NULL, DeviceOutRequest | USB_REQ_SET_ADDRESS, slot->devaddr, 0, 0, NULL); From 27a11324e07f23587abfac3f0fd2fd6fb536aa74 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Mon, 29 Oct 2012 11:34:34 +1000 Subject: [PATCH 1459/2270] usb/ehci: parameterise the register region offsets The capabilities register and operational register offsets can vary from one EHCI implementation to the next. Parameterise accordingly. Signed-off-by: Peter Crosthwaite Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 68 +++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index f14f9d7018..7f04322485 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -48,20 +48,18 @@ #define USB_RET_PROCERR (-99) #define MMIO_SIZE 0x1000 +#define CAPA_SIZE 0x10 /* Capability Registers Base Address - section 2.2 */ -#define CAPREGBASE 0x0000 -#define CAPLENGTH CAPREGBASE + 0x0000 // 1-byte, 0x0001 reserved -#define HCIVERSION CAPREGBASE + 0x0002 // 2-bytes, i/f version # -#define HCSPARAMS CAPREGBASE + 0x0004 // 4-bytes, structural params -#define HCCPARAMS CAPREGBASE + 0x0008 // 4-bytes, capability params +#define CAPLENGTH 0x0000 /* 1-byte, 0x0001 reserved */ +#define HCIVERSION 0x0002 /* 2-bytes, i/f version # */ +#define HCSPARAMS 0x0004 /* 4-bytes, structural params */ +#define HCCPARAMS 0x0008 /* 4-bytes, capability params */ #define EECP HCCPARAMS + 1 -#define HCSPPORTROUTE1 CAPREGBASE + 0x000c -#define HCSPPORTROUTE2 CAPREGBASE + 0x0010 +#define HCSPPORTROUTE1 0x000c +#define HCSPPORTROUTE2 0x0010 -#define OPREGBASE 0x0020 // Operational Registers Base Address - -#define USBCMD OPREGBASE + 0x0000 +#define USBCMD 0x0000 #define USBCMD_RUNSTOP (1 << 0) // run / Stop #define USBCMD_HCRESET (1 << 1) // HC Reset #define USBCMD_FLS (3 << 2) // Frame List Size @@ -75,7 +73,7 @@ #define USBCMD_ITC (0x7f << 16) // Int Threshold Control #define USBCMD_ITC_SH 16 // Int Threshold Control Shift -#define USBSTS OPREGBASE + 0x0004 +#define USBSTS 0x0004 #define USBSTS_RO_MASK 0x0000003f #define USBSTS_INT (1 << 0) // USB Interrupt #define USBSTS_ERRINT (1 << 1) // Error Interrupt @@ -92,18 +90,18 @@ * Interrupt enable bits correspond to the interrupt active bits in USBSTS * so no need to redefine here. */ -#define USBINTR OPREGBASE + 0x0008 +#define USBINTR 0x0008 #define USBINTR_MASK 0x0000003f -#define FRINDEX OPREGBASE + 0x000c -#define CTRLDSSEGMENT OPREGBASE + 0x0010 -#define PERIODICLISTBASE OPREGBASE + 0x0014 -#define ASYNCLISTADDR OPREGBASE + 0x0018 +#define FRINDEX 0x000c +#define CTRLDSSEGMENT 0x0010 +#define PERIODICLISTBASE 0x0014 +#define ASYNCLISTADDR 0x0018 #define ASYNCLISTADDR_MASK 0xffffffe0 -#define CONFIGFLAG OPREGBASE + 0x0040 +#define CONFIGFLAG 0x0040 -#define PORTSC (OPREGBASE + 0x0044) +#define PORTSC 0x0044 #define PORTSC_BEGIN PORTSC #define PORTSC_END (PORTSC + 4 * NB_PORTS) /* @@ -395,6 +393,8 @@ struct EHCIState { MemoryRegion mem_opreg; MemoryRegion mem_ports; int companion_count; + uint16_t capsbase; + uint16_t opregbase; /* properties */ uint32_t maxframes; @@ -403,9 +403,9 @@ struct EHCIState { * EHCI spec version 1.0 Section 2.3 * Host Controller Operational Registers */ - uint8_t caps[OPREGBASE]; + uint8_t caps[CAPA_SIZE]; union { - uint32_t opreg[(PORTSC_BEGIN-OPREGBASE)/sizeof(uint32_t)]; + uint32_t opreg[PORTSC_BEGIN/sizeof(uint32_t)]; struct { uint32_t usbcmd; uint32_t usbsts; @@ -506,8 +506,7 @@ static const char *state2str(uint32_t state) static const char *addr2str(hwaddr addr) { - return nr2str(ehci_mmio_names, ARRAY_SIZE(ehci_mmio_names), - addr + OPREGBASE); + return nr2str(ehci_mmio_names, ARRAY_SIZE(ehci_mmio_names), addr); } static void ehci_trace_usbsts(uint32_t mask, int state) @@ -1115,7 +1114,7 @@ static uint64_t ehci_opreg_read(void *ptr, hwaddr addr, uint32_t val; val = s->opreg[addr >> 2]; - trace_usb_ehci_opreg_read(addr + OPREGBASE, addr2str(addr), val); + trace_usb_ehci_opreg_read(addr + s->opregbase, addr2str(addr), val); return val; } @@ -1211,9 +1210,9 @@ static void ehci_opreg_write(void *ptr, hwaddr addr, uint32_t old = *mmio; int i; - trace_usb_ehci_opreg_write(addr + OPREGBASE, addr2str(addr), val); + trace_usb_ehci_opreg_write(addr + s->opregbase, addr2str(addr), val); - switch (addr + OPREGBASE) { + switch (addr) { case USBCMD: if (val & USBCMD_HCRESET) { ehci_reset(s); @@ -1291,7 +1290,8 @@ static void ehci_opreg_write(void *ptr, hwaddr addr, } *mmio = val; - trace_usb_ehci_opreg_change(addr + OPREGBASE, addr2str(addr), *mmio, old); + trace_usb_ehci_opreg_change(addr + s->opregbase, addr2str(addr), + *mmio, old); } @@ -2731,8 +2731,11 @@ static int usb_ehci_initfn(PCIDevice *dev) pci_conf[0x6e] = 0x00; pci_conf[0x6f] = 0xc0; // USBLEFCTLSTS + s->capsbase = 0x00; + s->opregbase = 0x20; + /* 2.2 host controller interface version */ - s->caps[0x00] = (uint8_t) OPREGBASE; + s->caps[0x00] = (uint8_t)(s->opregbase - s->capsbase); s->caps[0x01] = 0x00; s->caps[0x02] = 0x00; s->caps[0x03] = 0x01; /* HC version */ @@ -2765,15 +2768,16 @@ static int usb_ehci_initfn(PCIDevice *dev) memory_region_init(&s->mem, "ehci", MMIO_SIZE); memory_region_init_io(&s->mem_caps, &ehci_mmio_caps_ops, s, - "capabilities", OPREGBASE); + "capabilities", CAPA_SIZE); memory_region_init_io(&s->mem_opreg, &ehci_mmio_opreg_ops, s, - "operational", PORTSC_BEGIN - OPREGBASE); + "operational", PORTSC_BEGIN); memory_region_init_io(&s->mem_ports, &ehci_mmio_port_ops, s, "ports", PORTSC_END - PORTSC_BEGIN); - memory_region_add_subregion(&s->mem, 0, &s->mem_caps); - memory_region_add_subregion(&s->mem, OPREGBASE, &s->mem_opreg); - memory_region_add_subregion(&s->mem, PORTSC_BEGIN, &s->mem_ports); + memory_region_add_subregion(&s->mem, s->capsbase, &s->mem_caps); + memory_region_add_subregion(&s->mem, s->opregbase, &s->mem_opreg); + memory_region_add_subregion(&s->mem, s->opregbase + PORTSC_BEGIN, + &s->mem_ports); pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); From 7ae6ce0258096d3ad974d274aafcf130d5a31bb7 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Mon, 29 Oct 2012 11:34:35 +1000 Subject: [PATCH 1460/2270] usb/ehci: Abstract away PCI DMA API Pull the DMAContext for the PCI DMA out at device init time and put it into the device state. Use dma_memory_read/write() instead of pci specific versions. Signed-off-by: Peter Crosthwaite Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 7f04322485..28890b5f84 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -389,6 +389,7 @@ struct EHCIState { USBBus bus; qemu_irq irq; MemoryRegion mem; + DMAContext *dma; MemoryRegion mem_caps; MemoryRegion mem_opreg; MemoryRegion mem_ports; @@ -1304,7 +1305,7 @@ static inline int get_dwords(EHCIState *ehci, uint32_t addr, int i; for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { - pci_dma_read(&ehci->dev, addr, buf, sizeof(*buf)); + dma_memory_read(ehci->dma, addr, buf, sizeof(*buf)); *buf = le32_to_cpu(*buf); } @@ -1319,7 +1320,7 @@ static inline int put_dwords(EHCIState *ehci, uint32_t addr, for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { uint32_t tmp = cpu_to_le32(*buf); - pci_dma_write(&ehci->dev, addr, &tmp, sizeof(tmp)); + dma_memory_write(ehci->dma, addr, &tmp, sizeof(tmp)); } return 1; @@ -1402,7 +1403,7 @@ static int ehci_init_transfer(EHCIPacket *p) cpage = get_field(p->qtd.token, QTD_TOKEN_CPAGE); bytes = get_field(p->qtd.token, QTD_TOKEN_TBYTES); offset = p->qtd.bufptr[0] & ~QTD_BUFPTR_MASK; - pci_dma_sglist_init(&p->sgl, &p->queue->ehci->dev, 5); + qemu_sglist_init(&p->sgl, 5, p->queue->ehci->dma); while (bytes > 0) { if (cpage > 4) { @@ -1647,7 +1648,7 @@ static int ehci_process_itd(EHCIState *ehci, return USB_RET_PROCERR; } - pci_dma_sglist_init(&ehci->isgl, &ehci->dev, 2); + qemu_sglist_init(&ehci->isgl, 2, ehci->dma); if (off + len > 4096) { /* transfer crosses page border */ uint32_t len2 = off + len - 4096; @@ -2402,7 +2403,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci) } list |= ((ehci->frindex & 0x1ff8) >> 1); - pci_dma_read(&ehci->dev, list, &entry, sizeof entry); + dma_memory_read(ehci->dma, list, &entry, sizeof entry); entry = le32_to_cpu(entry); DPRINTF("PERIODIC state adv fr=%d. [%08X] -> %08X\n", @@ -2750,6 +2751,8 @@ static int usb_ehci_initfn(PCIDevice *dev) s->irq = s->dev.irq[3]; + s->dma = pci_dma_context(dev); + usb_bus_new(&s->bus, &ehci_bus_ops, &s->dev.qdev); for(i = 0; i < NB_PORTS; i++) { usb_register_port(&s->bus, &s->ports[i], s, i, &ehci_port_ops, From 5010d4dc618b6b8e7c21129c487c06f6493f71fc Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Mon, 29 Oct 2012 11:34:36 +1000 Subject: [PATCH 1461/2270] usb/ehci: seperate out PCIisms Seperate the PCI stuff from the EHCI components. Extracted the PCIDevice out into a new wrapper struct to make EHCIState non-PCI-specific. Seperated tho non PCI init component out into a seperate "common" init function. Signed-off-by: Peter Crosthwaite Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 124 +++++++++++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 52 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 28890b5f84..59580fc80b 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -385,7 +385,6 @@ struct EHCIQueue { typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead; struct EHCIState { - PCIDevice dev; USBBus bus; qemu_irq irq; MemoryRegion mem; @@ -447,6 +446,11 @@ struct EHCIState { bool int_req_by_async; }; +typedef struct EHCIPCIState { + PCIDevice pcidev; + EHCIState ehci; +} EHCIPCIState; + #define SET_LAST_RUN_CLOCK(s) \ (s)->last_run_ns = qemu_get_clock_ns(vm_clock); @@ -2553,7 +2557,7 @@ static const MemoryRegionOps ehci_mmio_port_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static int usb_ehci_initfn(PCIDevice *dev); +static int usb_ehci_pci_initfn(PCIDevice *dev); static USBPortOps ehci_port_ops = { .attach = ehci_attach, @@ -2614,12 +2618,11 @@ static void usb_ehci_vm_state_change(void *opaque, int running, RunState state) } static const VMStateDescription vmstate_ehci = { - .name = "ehci", + .name = "ehci-core", .version_id = 2, .minimum_version_id = 1, .post_load = usb_ehci_post_load, .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(dev, EHCIState), /* mmio registers */ VMSTATE_UINT32(usbcmd, EHCIState), VMSTATE_UINT32(usbsts, EHCIState), @@ -2650,8 +2653,19 @@ static const VMStateDescription vmstate_ehci = { } }; -static Property ehci_properties[] = { - DEFINE_PROP_UINT32("maxframes", EHCIState, maxframes, 128), +static const VMStateDescription vmstate_ehci_pci = { + .name = "ehci", + .version_id = 2, + .minimum_version_id = 1, + .post_load = usb_ehci_post_load, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE(pcidev, EHCIPCIState), + VMSTATE_STRUCT(ehci, EHCIPCIState, 2, vmstate_ehci, EHCIState), + } +}; + +static Property ehci_pci_properties[] = { + DEFINE_PROP_UINT32("maxframes", EHCIPCIState, ehci.maxframes, 128), DEFINE_PROP_END_OF_LIST(), }; @@ -2660,13 +2674,13 @@ static void ehci_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = usb_ehci_initfn; + k->init = usb_ehci_pci_initfn; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82801D; /* ich4 */ k->revision = 0x10; k->class_id = PCI_CLASS_SERIAL_USB; dc->vmsd = &vmstate_ehci; - dc->props = ehci_properties; + dc->props = ehci_pci_properties; } static TypeInfo ehci_info = { @@ -2681,13 +2695,13 @@ static void ich9_ehci_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = usb_ehci_initfn; + k->init = usb_ehci_pci_initfn; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1; k->revision = 0x03; k->class_id = PCI_CLASS_SERIAL_USB; dc->vmsd = &vmstate_ehci; - dc->props = ehci_properties; + dc->props = ehci_pci_properties; } static TypeInfo ich9_ehci_info = { @@ -2697,44 +2711,10 @@ static TypeInfo ich9_ehci_info = { .class_init = ich9_ehci_class_init, }; -static int usb_ehci_initfn(PCIDevice *dev) +static void usb_ehci_initfn(EHCIState *s, DeviceState *dev) { - EHCIState *s = DO_UPCAST(EHCIState, dev, dev); - uint8_t *pci_conf = s->dev.config; int i; - pci_set_byte(&pci_conf[PCI_CLASS_PROG], 0x20); - - /* capabilities pointer */ - pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x00); - //pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x50); - - pci_set_byte(&pci_conf[PCI_INTERRUPT_PIN], 4); /* interrupt pin D */ - pci_set_byte(&pci_conf[PCI_MIN_GNT], 0); - pci_set_byte(&pci_conf[PCI_MAX_LAT], 0); - - // pci_conf[0x50] = 0x01; // power management caps - - pci_set_byte(&pci_conf[USB_SBRN], USB_RELEASE_2); // release number (2.1.4) - pci_set_byte(&pci_conf[0x61], 0x20); // frame length adjustment (2.1.5) - pci_set_word(&pci_conf[0x62], 0x00); // port wake up capability (2.1.6) - - pci_conf[0x64] = 0x00; - pci_conf[0x65] = 0x00; - pci_conf[0x66] = 0x00; - pci_conf[0x67] = 0x00; - pci_conf[0x68] = 0x01; - pci_conf[0x69] = 0x00; - pci_conf[0x6a] = 0x00; - pci_conf[0x6b] = 0x00; // USBLEGSUP - pci_conf[0x6c] = 0x00; - pci_conf[0x6d] = 0x00; - pci_conf[0x6e] = 0x00; - pci_conf[0x6f] = 0xc0; // USBLEFCTLSTS - - s->capsbase = 0x00; - s->opregbase = 0x20; - /* 2.2 host controller interface version */ s->caps[0x00] = (uint8_t)(s->opregbase - s->capsbase); s->caps[0x01] = 0x00; @@ -2745,15 +2725,10 @@ static int usb_ehci_initfn(PCIDevice *dev) s->caps[0x06] = 0x00; s->caps[0x07] = 0x00; s->caps[0x08] = 0x80; /* We can cache whole frame, no 64-bit */ - s->caps[0x09] = 0x68; /* EECP */ s->caps[0x0a] = 0x00; s->caps[0x0b] = 0x00; - s->irq = s->dev.irq[3]; - - s->dma = pci_dma_context(dev); - - usb_bus_new(&s->bus, &ehci_bus_ops, &s->dev.qdev); + usb_bus_new(&s->bus, &ehci_bus_ops, dev); for(i = 0; i < NB_PORTS; i++) { usb_register_port(&s->bus, &s->ports[i], s, i, &ehci_port_ops, USB_SPEED_MASK_HIGH); @@ -2781,8 +2756,53 @@ static int usb_ehci_initfn(PCIDevice *dev) memory_region_add_subregion(&s->mem, s->opregbase, &s->mem_opreg); memory_region_add_subregion(&s->mem, s->opregbase + PORTSC_BEGIN, &s->mem_ports); +} - pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); +static int usb_ehci_pci_initfn(PCIDevice *dev) +{ + EHCIPCIState *i = DO_UPCAST(EHCIPCIState, pcidev, dev); + EHCIState *s = &i->ehci; + uint8_t *pci_conf = dev->config; + + pci_set_byte(&pci_conf[PCI_CLASS_PROG], 0x20); + + /* capabilities pointer */ + pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x00); + /* pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x50); */ + + pci_set_byte(&pci_conf[PCI_INTERRUPT_PIN], 4); /* interrupt pin D */ + pci_set_byte(&pci_conf[PCI_MIN_GNT], 0); + pci_set_byte(&pci_conf[PCI_MAX_LAT], 0); + + /* pci_conf[0x50] = 0x01; *//* power management caps */ + + pci_set_byte(&pci_conf[USB_SBRN], USB_RELEASE_2); /* release # (2.1.4) */ + pci_set_byte(&pci_conf[0x61], 0x20); /* frame length adjustment (2.1.5) */ + pci_set_word(&pci_conf[0x62], 0x00); /* port wake up capability (2.1.6) */ + + pci_conf[0x64] = 0x00; + pci_conf[0x65] = 0x00; + pci_conf[0x66] = 0x00; + pci_conf[0x67] = 0x00; + pci_conf[0x68] = 0x01; + pci_conf[0x69] = 0x00; + pci_conf[0x6a] = 0x00; + pci_conf[0x6b] = 0x00; /* USBLEGSUP */ + pci_conf[0x6c] = 0x00; + pci_conf[0x6d] = 0x00; + pci_conf[0x6e] = 0x00; + pci_conf[0x6f] = 0xc0; /* USBLEFCTLSTS */ + + s->caps[0x09] = 0x68; /* EECP */ + + s->irq = dev->irq[3]; + s->dma = pci_dma_context(dev); + + s->capsbase = 0x00; + s->opregbase = 0x20; + + usb_ehci_initfn(s, DEVICE(dev)); + pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); return 0; } From 569c7fc8400ea3a7b13589af889003208aaae2ed Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Mon, 29 Oct 2012 11:34:39 +1000 Subject: [PATCH 1462/2270] usb/ehci: Guard definition of EHCI_DEBUG Guard against re-definition of EHCI_DEBUG. Allows for turning on of debug info from configure (using --qemu-extra-cflags="-DEHCI_DEBUG=1") rather than source code hacking. Signed-off-by: Peter Crosthwaite Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 59580fc80b..d3168c954d 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -36,7 +36,9 @@ #include "dma.h" #include "sysemu.h" +#ifndef EHCI_DEBUG #define EHCI_DEBUG 0 +#endif #if EHCI_DEBUG #define DPRINTF printf From 0bf96f9457cdaf620bb8195a971bbdcc732ba32b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 30 Oct 2012 12:20:06 +0100 Subject: [PATCH 1463/2270] usb/ehci: split into multiple source files Signed-off-by: Gerd Hoffmann --- hw/usb/Makefile.objs | 2 +- hw/usb/hcd-ehci-pci.c | 138 ++++++++++++++ hw/usb/hcd-ehci.c | 426 +----------------------------------------- hw/usb/hcd-ehci.h | 320 +++++++++++++++++++++++++++++++ 4 files changed, 462 insertions(+), 424 deletions(-) create mode 100644 hw/usb/hcd-ehci-pci.c create mode 100644 hw/usb/hcd-ehci.h diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs index 6425c1ff73..5c7b024103 100644 --- a/hw/usb/Makefile.objs +++ b/hw/usb/Makefile.objs @@ -1,6 +1,6 @@ common-obj-$(CONFIG_USB_UHCI) += hcd-uhci.o common-obj-$(CONFIG_USB_OHCI) += hcd-ohci.o -common-obj-$(CONFIG_USB_EHCI) += hcd-ehci.o +common-obj-$(CONFIG_USB_EHCI) += hcd-ehci.o hcd-ehci-pci.o common-obj-$(CONFIG_USB_XHCI) += hcd-xhci.o common-obj-y += libhw.o diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c new file mode 100644 index 0000000000..daac41d7f8 --- /dev/null +++ b/hw/usb/hcd-ehci-pci.c @@ -0,0 +1,138 @@ +/* + * QEMU USB EHCI Emulation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or(at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "hw/usb/hcd-ehci.h" +#include "hw/pci.h" + +typedef struct EHCIPCIState { + PCIDevice pcidev; + EHCIState ehci; +} EHCIPCIState; + +static int usb_ehci_pci_initfn(PCIDevice *dev) +{ + EHCIPCIState *i = DO_UPCAST(EHCIPCIState, pcidev, dev); + EHCIState *s = &i->ehci; + uint8_t *pci_conf = dev->config; + + pci_set_byte(&pci_conf[PCI_CLASS_PROG], 0x20); + + /* capabilities pointer */ + pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x00); + /* pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x50); */ + + pci_set_byte(&pci_conf[PCI_INTERRUPT_PIN], 4); /* interrupt pin D */ + pci_set_byte(&pci_conf[PCI_MIN_GNT], 0); + pci_set_byte(&pci_conf[PCI_MAX_LAT], 0); + + /* pci_conf[0x50] = 0x01; *//* power management caps */ + + pci_set_byte(&pci_conf[USB_SBRN], USB_RELEASE_2); /* release # (2.1.4) */ + pci_set_byte(&pci_conf[0x61], 0x20); /* frame length adjustment (2.1.5) */ + pci_set_word(&pci_conf[0x62], 0x00); /* port wake up capability (2.1.6) */ + + pci_conf[0x64] = 0x00; + pci_conf[0x65] = 0x00; + pci_conf[0x66] = 0x00; + pci_conf[0x67] = 0x00; + pci_conf[0x68] = 0x01; + pci_conf[0x69] = 0x00; + pci_conf[0x6a] = 0x00; + pci_conf[0x6b] = 0x00; /* USBLEGSUP */ + pci_conf[0x6c] = 0x00; + pci_conf[0x6d] = 0x00; + pci_conf[0x6e] = 0x00; + pci_conf[0x6f] = 0xc0; /* USBLEFCTLSTS */ + + s->caps[0x09] = 0x68; /* EECP */ + + s->irq = dev->irq[3]; + s->dma = pci_dma_context(dev); + + s->capsbase = 0x00; + s->opregbase = 0x20; + + usb_ehci_initfn(s, DEVICE(dev)); + pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); + + return 0; +} + +static Property ehci_pci_properties[] = { + DEFINE_PROP_UINT32("maxframes", EHCIPCIState, ehci.maxframes, 128), + DEFINE_PROP_END_OF_LIST(), +}; + +static const VMStateDescription vmstate_ehci_pci = { + .name = "ehci", + .version_id = 2, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE(pcidev, EHCIPCIState), + VMSTATE_STRUCT(ehci, EHCIPCIState, 2, vmstate_ehci, EHCIState), + } +}; + +static void ehci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->init = usb_ehci_pci_initfn; + k->vendor_id = PCI_VENDOR_ID_INTEL; + k->device_id = PCI_DEVICE_ID_INTEL_82801D; /* ich4 */ + k->revision = 0x10; + k->class_id = PCI_CLASS_SERIAL_USB; + dc->vmsd = &vmstate_ehci; + dc->props = ehci_pci_properties; +} + +static TypeInfo ehci_info = { + .name = "usb-ehci", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(EHCIState), + .class_init = ehci_class_init, +}; + +static void ich9_ehci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->init = usb_ehci_pci_initfn; + k->vendor_id = PCI_VENDOR_ID_INTEL; + k->device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1; + k->revision = 0x03; + k->class_id = PCI_CLASS_SERIAL_USB; + dc->vmsd = &vmstate_ehci; + dc->props = ehci_pci_properties; +} + +static TypeInfo ich9_ehci_info = { + .name = "ich9-usb-ehci1", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(EHCIState), + .class_init = ich9_ehci_class_init, +}; + +static void ehci_pci_register_types(void) +{ + type_register_static(&ehci_info); + type_register_static(&ich9_ehci_info); +} + +type_init(ehci_pci_register_types) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index d3168c954d..d9dc576e7c 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -27,31 +27,11 @@ * along with this program; if not, see . */ -#include "hw/hw.h" -#include "qemu-timer.h" -#include "hw/usb.h" -#include "hw/pci.h" -#include "monitor.h" -#include "trace.h" -#include "dma.h" -#include "sysemu.h" - -#ifndef EHCI_DEBUG -#define EHCI_DEBUG 0 -#endif - -#if EHCI_DEBUG -#define DPRINTF printf -#else -#define DPRINTF(...) -#endif +#include "hw/usb/hcd-ehci.h" /* internal processing - reset HC to try and recover */ #define USB_RET_PROCERR (-99) -#define MMIO_SIZE 0x1000 -#define CAPA_SIZE 0x10 - /* Capability Registers Base Address - section 2.2 */ #define CAPLENGTH 0x0000 /* 1-byte, 0x0001 reserved */ #define HCIVERSION 0x0002 /* 2-bytes, i/f version # */ @@ -103,9 +83,6 @@ #define CONFIGFLAG 0x0040 -#define PORTSC 0x0044 -#define PORTSC_BEGIN PORTSC -#define PORTSC_END (PORTSC + 4 * NB_PORTS) /* * Bits that are reserved or are read-only are masked out of values * written to us by software @@ -137,7 +114,6 @@ #define FRAME_TIMER_NS (1000000000 / FRAME_TIMER_FREQ) #define NB_MAXINTRATE 8 // Max rate at which controller issues ints -#define NB_PORTS 6 // Number of downstream ports #define BUFF_SIZE 5*4096 // Max bytes to transfer per transaction #define MAX_QH 100 // Max allowable queue heads in a chain #define MIN_FR_PER_TICK 3 // Min frames to process when catching up @@ -174,285 +150,6 @@ typedef enum { #define NLPTR_TYPE_STITD 2 // split xaction, isoc xfer descriptor #define NLPTR_TYPE_FSTN 3 // frame span traversal node - -/* EHCI spec version 1.0 Section 3.3 - */ -typedef struct EHCIitd { - uint32_t next; - - uint32_t transact[8]; -#define ITD_XACT_ACTIVE (1 << 31) -#define ITD_XACT_DBERROR (1 << 30) -#define ITD_XACT_BABBLE (1 << 29) -#define ITD_XACT_XACTERR (1 << 28) -#define ITD_XACT_LENGTH_MASK 0x0fff0000 -#define ITD_XACT_LENGTH_SH 16 -#define ITD_XACT_IOC (1 << 15) -#define ITD_XACT_PGSEL_MASK 0x00007000 -#define ITD_XACT_PGSEL_SH 12 -#define ITD_XACT_OFFSET_MASK 0x00000fff - - uint32_t bufptr[7]; -#define ITD_BUFPTR_MASK 0xfffff000 -#define ITD_BUFPTR_SH 12 -#define ITD_BUFPTR_EP_MASK 0x00000f00 -#define ITD_BUFPTR_EP_SH 8 -#define ITD_BUFPTR_DEVADDR_MASK 0x0000007f -#define ITD_BUFPTR_DEVADDR_SH 0 -#define ITD_BUFPTR_DIRECTION (1 << 11) -#define ITD_BUFPTR_MAXPKT_MASK 0x000007ff -#define ITD_BUFPTR_MAXPKT_SH 0 -#define ITD_BUFPTR_MULT_MASK 0x00000003 -#define ITD_BUFPTR_MULT_SH 0 -} EHCIitd; - -/* EHCI spec version 1.0 Section 3.4 - */ -typedef struct EHCIsitd { - uint32_t next; // Standard next link pointer - uint32_t epchar; -#define SITD_EPCHAR_IO (1 << 31) -#define SITD_EPCHAR_PORTNUM_MASK 0x7f000000 -#define SITD_EPCHAR_PORTNUM_SH 24 -#define SITD_EPCHAR_HUBADD_MASK 0x007f0000 -#define SITD_EPCHAR_HUBADDR_SH 16 -#define SITD_EPCHAR_EPNUM_MASK 0x00000f00 -#define SITD_EPCHAR_EPNUM_SH 8 -#define SITD_EPCHAR_DEVADDR_MASK 0x0000007f - - uint32_t uframe; -#define SITD_UFRAME_CMASK_MASK 0x0000ff00 -#define SITD_UFRAME_CMASK_SH 8 -#define SITD_UFRAME_SMASK_MASK 0x000000ff - - uint32_t results; -#define SITD_RESULTS_IOC (1 << 31) -#define SITD_RESULTS_PGSEL (1 << 30) -#define SITD_RESULTS_TBYTES_MASK 0x03ff0000 -#define SITD_RESULTS_TYBYTES_SH 16 -#define SITD_RESULTS_CPROGMASK_MASK 0x0000ff00 -#define SITD_RESULTS_CPROGMASK_SH 8 -#define SITD_RESULTS_ACTIVE (1 << 7) -#define SITD_RESULTS_ERR (1 << 6) -#define SITD_RESULTS_DBERR (1 << 5) -#define SITD_RESULTS_BABBLE (1 << 4) -#define SITD_RESULTS_XACTERR (1 << 3) -#define SITD_RESULTS_MISSEDUF (1 << 2) -#define SITD_RESULTS_SPLITXSTATE (1 << 1) - - uint32_t bufptr[2]; -#define SITD_BUFPTR_MASK 0xfffff000 -#define SITD_BUFPTR_CURROFF_MASK 0x00000fff -#define SITD_BUFPTR_TPOS_MASK 0x00000018 -#define SITD_BUFPTR_TPOS_SH 3 -#define SITD_BUFPTR_TCNT_MASK 0x00000007 - - uint32_t backptr; // Standard next link pointer -} EHCIsitd; - -/* EHCI spec version 1.0 Section 3.5 - */ -typedef struct EHCIqtd { - uint32_t next; // Standard next link pointer - uint32_t altnext; // Standard next link pointer - uint32_t token; -#define QTD_TOKEN_DTOGGLE (1 << 31) -#define QTD_TOKEN_TBYTES_MASK 0x7fff0000 -#define QTD_TOKEN_TBYTES_SH 16 -#define QTD_TOKEN_IOC (1 << 15) -#define QTD_TOKEN_CPAGE_MASK 0x00007000 -#define QTD_TOKEN_CPAGE_SH 12 -#define QTD_TOKEN_CERR_MASK 0x00000c00 -#define QTD_TOKEN_CERR_SH 10 -#define QTD_TOKEN_PID_MASK 0x00000300 -#define QTD_TOKEN_PID_SH 8 -#define QTD_TOKEN_ACTIVE (1 << 7) -#define QTD_TOKEN_HALT (1 << 6) -#define QTD_TOKEN_DBERR (1 << 5) -#define QTD_TOKEN_BABBLE (1 << 4) -#define QTD_TOKEN_XACTERR (1 << 3) -#define QTD_TOKEN_MISSEDUF (1 << 2) -#define QTD_TOKEN_SPLITXSTATE (1 << 1) -#define QTD_TOKEN_PING (1 << 0) - - uint32_t bufptr[5]; // Standard buffer pointer -#define QTD_BUFPTR_MASK 0xfffff000 -#define QTD_BUFPTR_SH 12 -} EHCIqtd; - -/* EHCI spec version 1.0 Section 3.6 - */ -typedef struct EHCIqh { - uint32_t next; // Standard next link pointer - - /* endpoint characteristics */ - uint32_t epchar; -#define QH_EPCHAR_RL_MASK 0xf0000000 -#define QH_EPCHAR_RL_SH 28 -#define QH_EPCHAR_C (1 << 27) -#define QH_EPCHAR_MPLEN_MASK 0x07FF0000 -#define QH_EPCHAR_MPLEN_SH 16 -#define QH_EPCHAR_H (1 << 15) -#define QH_EPCHAR_DTC (1 << 14) -#define QH_EPCHAR_EPS_MASK 0x00003000 -#define QH_EPCHAR_EPS_SH 12 -#define EHCI_QH_EPS_FULL 0 -#define EHCI_QH_EPS_LOW 1 -#define EHCI_QH_EPS_HIGH 2 -#define EHCI_QH_EPS_RESERVED 3 - -#define QH_EPCHAR_EP_MASK 0x00000f00 -#define QH_EPCHAR_EP_SH 8 -#define QH_EPCHAR_I (1 << 7) -#define QH_EPCHAR_DEVADDR_MASK 0x0000007f -#define QH_EPCHAR_DEVADDR_SH 0 - - /* endpoint capabilities */ - uint32_t epcap; -#define QH_EPCAP_MULT_MASK 0xc0000000 -#define QH_EPCAP_MULT_SH 30 -#define QH_EPCAP_PORTNUM_MASK 0x3f800000 -#define QH_EPCAP_PORTNUM_SH 23 -#define QH_EPCAP_HUBADDR_MASK 0x007f0000 -#define QH_EPCAP_HUBADDR_SH 16 -#define QH_EPCAP_CMASK_MASK 0x0000ff00 -#define QH_EPCAP_CMASK_SH 8 -#define QH_EPCAP_SMASK_MASK 0x000000ff -#define QH_EPCAP_SMASK_SH 0 - - uint32_t current_qtd; // Standard next link pointer - uint32_t next_qtd; // Standard next link pointer - uint32_t altnext_qtd; -#define QH_ALTNEXT_NAKCNT_MASK 0x0000001e -#define QH_ALTNEXT_NAKCNT_SH 1 - - uint32_t token; // Same as QTD token - uint32_t bufptr[5]; // Standard buffer pointer -#define BUFPTR_CPROGMASK_MASK 0x000000ff -#define BUFPTR_FRAMETAG_MASK 0x0000001f -#define BUFPTR_SBYTES_MASK 0x00000fe0 -#define BUFPTR_SBYTES_SH 5 -} EHCIqh; - -/* EHCI spec version 1.0 Section 3.7 - */ -typedef struct EHCIfstn { - uint32_t next; // Standard next link pointer - uint32_t backptr; // Standard next link pointer -} EHCIfstn; - -typedef struct EHCIPacket EHCIPacket; -typedef struct EHCIQueue EHCIQueue; -typedef struct EHCIState EHCIState; - -enum async_state { - EHCI_ASYNC_NONE = 0, - EHCI_ASYNC_INITIALIZED, - EHCI_ASYNC_INFLIGHT, - EHCI_ASYNC_FINISHED, -}; - -struct EHCIPacket { - EHCIQueue *queue; - QTAILQ_ENTRY(EHCIPacket) next; - - EHCIqtd qtd; /* copy of current QTD (being worked on) */ - uint32_t qtdaddr; /* address QTD read from */ - - USBPacket packet; - QEMUSGList sgl; - int pid; - enum async_state async; - int usb_status; -}; - -struct EHCIQueue { - EHCIState *ehci; - QTAILQ_ENTRY(EHCIQueue) next; - uint32_t seen; - uint64_t ts; - int async; - int transact_ctr; - - /* cached data from guest - needs to be flushed - * when guest removes an entry (doorbell, handshake sequence) - */ - EHCIqh qh; /* copy of current QH (being worked on) */ - uint32_t qhaddr; /* address QH read from */ - uint32_t qtdaddr; /* address QTD read from */ - USBDevice *dev; - QTAILQ_HEAD(pkts_head, EHCIPacket) packets; -}; - -typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead; - -struct EHCIState { - USBBus bus; - qemu_irq irq; - MemoryRegion mem; - DMAContext *dma; - MemoryRegion mem_caps; - MemoryRegion mem_opreg; - MemoryRegion mem_ports; - int companion_count; - uint16_t capsbase; - uint16_t opregbase; - - /* properties */ - uint32_t maxframes; - - /* - * EHCI spec version 1.0 Section 2.3 - * Host Controller Operational Registers - */ - uint8_t caps[CAPA_SIZE]; - union { - uint32_t opreg[PORTSC_BEGIN/sizeof(uint32_t)]; - struct { - uint32_t usbcmd; - uint32_t usbsts; - uint32_t usbintr; - uint32_t frindex; - uint32_t ctrldssegment; - uint32_t periodiclistbase; - uint32_t asynclistaddr; - uint32_t notused[9]; - uint32_t configflag; - }; - }; - uint32_t portsc[NB_PORTS]; - - /* - * Internal states, shadow registers, etc - */ - QEMUTimer *frame_timer; - QEMUBH *async_bh; - uint32_t astate; /* Current state in asynchronous schedule */ - uint32_t pstate; /* Current state in periodic schedule */ - USBPort ports[NB_PORTS]; - USBPort *companion_ports[NB_PORTS]; - uint32_t usbsts_pending; - uint32_t usbsts_frindex; - EHCIQueueHead aqueues; - EHCIQueueHead pqueues; - - /* which address to look at next */ - uint32_t a_fetch_addr; - uint32_t p_fetch_addr; - - USBPacket ipacket; - QEMUSGList isgl; - - uint64_t last_run_ns; - uint32_t async_stepdown; - bool int_req_by_async; -}; - -typedef struct EHCIPCIState { - PCIDevice pcidev; - EHCIState ehci; -} EHCIPCIState; - #define SET_LAST_RUN_CLOCK(s) \ (s)->last_run_ns = qemu_get_clock_ns(vm_clock); @@ -2559,8 +2256,6 @@ static const MemoryRegionOps ehci_mmio_port_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static int usb_ehci_pci_initfn(PCIDevice *dev); - static USBPortOps ehci_port_ops = { .attach = ehci_attach, .detach = ehci_detach, @@ -2619,7 +2314,7 @@ static void usb_ehci_vm_state_change(void *opaque, int running, RunState state) } } -static const VMStateDescription vmstate_ehci = { +const VMStateDescription vmstate_ehci = { .name = "ehci-core", .version_id = 2, .minimum_version_id = 1, @@ -2655,65 +2350,7 @@ static const VMStateDescription vmstate_ehci = { } }; -static const VMStateDescription vmstate_ehci_pci = { - .name = "ehci", - .version_id = 2, - .minimum_version_id = 1, - .post_load = usb_ehci_post_load, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(pcidev, EHCIPCIState), - VMSTATE_STRUCT(ehci, EHCIPCIState, 2, vmstate_ehci, EHCIState), - } -}; - -static Property ehci_pci_properties[] = { - DEFINE_PROP_UINT32("maxframes", EHCIPCIState, ehci.maxframes, 128), - DEFINE_PROP_END_OF_LIST(), -}; - -static void ehci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->init = usb_ehci_pci_initfn; - k->vendor_id = PCI_VENDOR_ID_INTEL; - k->device_id = PCI_DEVICE_ID_INTEL_82801D; /* ich4 */ - k->revision = 0x10; - k->class_id = PCI_CLASS_SERIAL_USB; - dc->vmsd = &vmstate_ehci; - dc->props = ehci_pci_properties; -} - -static TypeInfo ehci_info = { - .name = "usb-ehci", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(EHCIState), - .class_init = ehci_class_init, -}; - -static void ich9_ehci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->init = usb_ehci_pci_initfn; - k->vendor_id = PCI_VENDOR_ID_INTEL; - k->device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1; - k->revision = 0x03; - k->class_id = PCI_CLASS_SERIAL_USB; - dc->vmsd = &vmstate_ehci; - dc->props = ehci_pci_properties; -} - -static TypeInfo ich9_ehci_info = { - .name = "ich9-usb-ehci1", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(EHCIState), - .class_init = ich9_ehci_class_init, -}; - -static void usb_ehci_initfn(EHCIState *s, DeviceState *dev) +void usb_ehci_initfn(EHCIState *s, DeviceState *dev) { int i; @@ -2760,63 +2397,6 @@ static void usb_ehci_initfn(EHCIState *s, DeviceState *dev) &s->mem_ports); } -static int usb_ehci_pci_initfn(PCIDevice *dev) -{ - EHCIPCIState *i = DO_UPCAST(EHCIPCIState, pcidev, dev); - EHCIState *s = &i->ehci; - uint8_t *pci_conf = dev->config; - - pci_set_byte(&pci_conf[PCI_CLASS_PROG], 0x20); - - /* capabilities pointer */ - pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x00); - /* pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x50); */ - - pci_set_byte(&pci_conf[PCI_INTERRUPT_PIN], 4); /* interrupt pin D */ - pci_set_byte(&pci_conf[PCI_MIN_GNT], 0); - pci_set_byte(&pci_conf[PCI_MAX_LAT], 0); - - /* pci_conf[0x50] = 0x01; *//* power management caps */ - - pci_set_byte(&pci_conf[USB_SBRN], USB_RELEASE_2); /* release # (2.1.4) */ - pci_set_byte(&pci_conf[0x61], 0x20); /* frame length adjustment (2.1.5) */ - pci_set_word(&pci_conf[0x62], 0x00); /* port wake up capability (2.1.6) */ - - pci_conf[0x64] = 0x00; - pci_conf[0x65] = 0x00; - pci_conf[0x66] = 0x00; - pci_conf[0x67] = 0x00; - pci_conf[0x68] = 0x01; - pci_conf[0x69] = 0x00; - pci_conf[0x6a] = 0x00; - pci_conf[0x6b] = 0x00; /* USBLEGSUP */ - pci_conf[0x6c] = 0x00; - pci_conf[0x6d] = 0x00; - pci_conf[0x6e] = 0x00; - pci_conf[0x6f] = 0xc0; /* USBLEFCTLSTS */ - - s->caps[0x09] = 0x68; /* EECP */ - - s->irq = dev->irq[3]; - s->dma = pci_dma_context(dev); - - s->capsbase = 0x00; - s->opregbase = 0x20; - - usb_ehci_initfn(s, DEVICE(dev)); - pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); - - return 0; -} - -static void ehci_register_types(void) -{ - type_register_static(&ehci_info); - type_register_static(&ich9_ehci_info); -} - -type_init(ehci_register_types) - /* * vim: expandtab ts=4 */ diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h new file mode 100644 index 0000000000..0ec675c352 --- /dev/null +++ b/hw/usb/hcd-ehci.h @@ -0,0 +1,320 @@ +/* + * QEMU USB EHCI Emulation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or(at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "hw/hw.h" +#include "qemu-timer.h" +#include "hw/usb.h" +#include "monitor.h" +#include "trace.h" +#include "dma.h" +#include "sysemu.h" + +#ifndef EHCI_DEBUG +#define EHCI_DEBUG 0 +#endif + +#if EHCI_DEBUG +#define DPRINTF printf +#else +#define DPRINTF(...) +#endif + +#define MMIO_SIZE 0x1000 +#define CAPA_SIZE 0x10 + +#define PORTSC 0x0044 +#define PORTSC_BEGIN PORTSC +#define PORTSC_END (PORTSC + 4 * NB_PORTS) + +#define NB_PORTS 6 /* Number of downstream ports */ + +typedef struct EHCIPacket EHCIPacket; +typedef struct EHCIQueue EHCIQueue; +typedef struct EHCIState EHCIState; + +/* EHCI spec version 1.0 Section 3.3 + */ +typedef struct EHCIitd { + uint32_t next; + + uint32_t transact[8]; +#define ITD_XACT_ACTIVE (1 << 31) +#define ITD_XACT_DBERROR (1 << 30) +#define ITD_XACT_BABBLE (1 << 29) +#define ITD_XACT_XACTERR (1 << 28) +#define ITD_XACT_LENGTH_MASK 0x0fff0000 +#define ITD_XACT_LENGTH_SH 16 +#define ITD_XACT_IOC (1 << 15) +#define ITD_XACT_PGSEL_MASK 0x00007000 +#define ITD_XACT_PGSEL_SH 12 +#define ITD_XACT_OFFSET_MASK 0x00000fff + + uint32_t bufptr[7]; +#define ITD_BUFPTR_MASK 0xfffff000 +#define ITD_BUFPTR_SH 12 +#define ITD_BUFPTR_EP_MASK 0x00000f00 +#define ITD_BUFPTR_EP_SH 8 +#define ITD_BUFPTR_DEVADDR_MASK 0x0000007f +#define ITD_BUFPTR_DEVADDR_SH 0 +#define ITD_BUFPTR_DIRECTION (1 << 11) +#define ITD_BUFPTR_MAXPKT_MASK 0x000007ff +#define ITD_BUFPTR_MAXPKT_SH 0 +#define ITD_BUFPTR_MULT_MASK 0x00000003 +#define ITD_BUFPTR_MULT_SH 0 +} EHCIitd; + +/* EHCI spec version 1.0 Section 3.4 + */ +typedef struct EHCIsitd { + uint32_t next; /* Standard next link pointer */ + uint32_t epchar; +#define SITD_EPCHAR_IO (1 << 31) +#define SITD_EPCHAR_PORTNUM_MASK 0x7f000000 +#define SITD_EPCHAR_PORTNUM_SH 24 +#define SITD_EPCHAR_HUBADD_MASK 0x007f0000 +#define SITD_EPCHAR_HUBADDR_SH 16 +#define SITD_EPCHAR_EPNUM_MASK 0x00000f00 +#define SITD_EPCHAR_EPNUM_SH 8 +#define SITD_EPCHAR_DEVADDR_MASK 0x0000007f + + uint32_t uframe; +#define SITD_UFRAME_CMASK_MASK 0x0000ff00 +#define SITD_UFRAME_CMASK_SH 8 +#define SITD_UFRAME_SMASK_MASK 0x000000ff + + uint32_t results; +#define SITD_RESULTS_IOC (1 << 31) +#define SITD_RESULTS_PGSEL (1 << 30) +#define SITD_RESULTS_TBYTES_MASK 0x03ff0000 +#define SITD_RESULTS_TYBYTES_SH 16 +#define SITD_RESULTS_CPROGMASK_MASK 0x0000ff00 +#define SITD_RESULTS_CPROGMASK_SH 8 +#define SITD_RESULTS_ACTIVE (1 << 7) +#define SITD_RESULTS_ERR (1 << 6) +#define SITD_RESULTS_DBERR (1 << 5) +#define SITD_RESULTS_BABBLE (1 << 4) +#define SITD_RESULTS_XACTERR (1 << 3) +#define SITD_RESULTS_MISSEDUF (1 << 2) +#define SITD_RESULTS_SPLITXSTATE (1 << 1) + + uint32_t bufptr[2]; +#define SITD_BUFPTR_MASK 0xfffff000 +#define SITD_BUFPTR_CURROFF_MASK 0x00000fff +#define SITD_BUFPTR_TPOS_MASK 0x00000018 +#define SITD_BUFPTR_TPOS_SH 3 +#define SITD_BUFPTR_TCNT_MASK 0x00000007 + + uint32_t backptr; /* Standard next link pointer */ +} EHCIsitd; + +/* EHCI spec version 1.0 Section 3.5 + */ +typedef struct EHCIqtd { + uint32_t next; /* Standard next link pointer */ + uint32_t altnext; /* Standard next link pointer */ + uint32_t token; +#define QTD_TOKEN_DTOGGLE (1 << 31) +#define QTD_TOKEN_TBYTES_MASK 0x7fff0000 +#define QTD_TOKEN_TBYTES_SH 16 +#define QTD_TOKEN_IOC (1 << 15) +#define QTD_TOKEN_CPAGE_MASK 0x00007000 +#define QTD_TOKEN_CPAGE_SH 12 +#define QTD_TOKEN_CERR_MASK 0x00000c00 +#define QTD_TOKEN_CERR_SH 10 +#define QTD_TOKEN_PID_MASK 0x00000300 +#define QTD_TOKEN_PID_SH 8 +#define QTD_TOKEN_ACTIVE (1 << 7) +#define QTD_TOKEN_HALT (1 << 6) +#define QTD_TOKEN_DBERR (1 << 5) +#define QTD_TOKEN_BABBLE (1 << 4) +#define QTD_TOKEN_XACTERR (1 << 3) +#define QTD_TOKEN_MISSEDUF (1 << 2) +#define QTD_TOKEN_SPLITXSTATE (1 << 1) +#define QTD_TOKEN_PING (1 << 0) + + uint32_t bufptr[5]; /* Standard buffer pointer */ +#define QTD_BUFPTR_MASK 0xfffff000 +#define QTD_BUFPTR_SH 12 +} EHCIqtd; + +/* EHCI spec version 1.0 Section 3.6 + */ +typedef struct EHCIqh { + uint32_t next; /* Standard next link pointer */ + + /* endpoint characteristics */ + uint32_t epchar; +#define QH_EPCHAR_RL_MASK 0xf0000000 +#define QH_EPCHAR_RL_SH 28 +#define QH_EPCHAR_C (1 << 27) +#define QH_EPCHAR_MPLEN_MASK 0x07FF0000 +#define QH_EPCHAR_MPLEN_SH 16 +#define QH_EPCHAR_H (1 << 15) +#define QH_EPCHAR_DTC (1 << 14) +#define QH_EPCHAR_EPS_MASK 0x00003000 +#define QH_EPCHAR_EPS_SH 12 +#define EHCI_QH_EPS_FULL 0 +#define EHCI_QH_EPS_LOW 1 +#define EHCI_QH_EPS_HIGH 2 +#define EHCI_QH_EPS_RESERVED 3 + +#define QH_EPCHAR_EP_MASK 0x00000f00 +#define QH_EPCHAR_EP_SH 8 +#define QH_EPCHAR_I (1 << 7) +#define QH_EPCHAR_DEVADDR_MASK 0x0000007f +#define QH_EPCHAR_DEVADDR_SH 0 + + /* endpoint capabilities */ + uint32_t epcap; +#define QH_EPCAP_MULT_MASK 0xc0000000 +#define QH_EPCAP_MULT_SH 30 +#define QH_EPCAP_PORTNUM_MASK 0x3f800000 +#define QH_EPCAP_PORTNUM_SH 23 +#define QH_EPCAP_HUBADDR_MASK 0x007f0000 +#define QH_EPCAP_HUBADDR_SH 16 +#define QH_EPCAP_CMASK_MASK 0x0000ff00 +#define QH_EPCAP_CMASK_SH 8 +#define QH_EPCAP_SMASK_MASK 0x000000ff +#define QH_EPCAP_SMASK_SH 0 + + uint32_t current_qtd; /* Standard next link pointer */ + uint32_t next_qtd; /* Standard next link pointer */ + uint32_t altnext_qtd; +#define QH_ALTNEXT_NAKCNT_MASK 0x0000001e +#define QH_ALTNEXT_NAKCNT_SH 1 + + uint32_t token; /* Same as QTD token */ + uint32_t bufptr[5]; /* Standard buffer pointer */ +#define BUFPTR_CPROGMASK_MASK 0x000000ff +#define BUFPTR_FRAMETAG_MASK 0x0000001f +#define BUFPTR_SBYTES_MASK 0x00000fe0 +#define BUFPTR_SBYTES_SH 5 +} EHCIqh; + +/* EHCI spec version 1.0 Section 3.7 + */ +typedef struct EHCIfstn { + uint32_t next; /* Standard next link pointer */ + uint32_t backptr; /* Standard next link pointer */ +} EHCIfstn; + +enum async_state { + EHCI_ASYNC_NONE = 0, + EHCI_ASYNC_INITIALIZED, + EHCI_ASYNC_INFLIGHT, + EHCI_ASYNC_FINISHED, +}; + +struct EHCIPacket { + EHCIQueue *queue; + QTAILQ_ENTRY(EHCIPacket) next; + + EHCIqtd qtd; /* copy of current QTD (being worked on) */ + uint32_t qtdaddr; /* address QTD read from */ + + USBPacket packet; + QEMUSGList sgl; + int pid; + enum async_state async; + int usb_status; +}; + +struct EHCIQueue { + EHCIState *ehci; + QTAILQ_ENTRY(EHCIQueue) next; + uint32_t seen; + uint64_t ts; + int async; + int transact_ctr; + + /* cached data from guest - needs to be flushed + * when guest removes an entry (doorbell, handshake sequence) + */ + EHCIqh qh; /* copy of current QH (being worked on) */ + uint32_t qhaddr; /* address QH read from */ + uint32_t qtdaddr; /* address QTD read from */ + USBDevice *dev; + QTAILQ_HEAD(pkts_head, EHCIPacket) packets; +}; + +typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead; + +struct EHCIState { + USBBus bus; + qemu_irq irq; + MemoryRegion mem; + DMAContext *dma; + MemoryRegion mem_caps; + MemoryRegion mem_opreg; + MemoryRegion mem_ports; + int companion_count; + uint16_t capsbase; + uint16_t opregbase; + + /* properties */ + uint32_t maxframes; + + /* + * EHCI spec version 1.0 Section 2.3 + * Host Controller Operational Registers + */ + uint8_t caps[CAPA_SIZE]; + union { + uint32_t opreg[PORTSC_BEGIN/sizeof(uint32_t)]; + struct { + uint32_t usbcmd; + uint32_t usbsts; + uint32_t usbintr; + uint32_t frindex; + uint32_t ctrldssegment; + uint32_t periodiclistbase; + uint32_t asynclistaddr; + uint32_t notused[9]; + uint32_t configflag; + }; + }; + uint32_t portsc[NB_PORTS]; + + /* + * Internal states, shadow registers, etc + */ + QEMUTimer *frame_timer; + QEMUBH *async_bh; + uint32_t astate; /* Current state in asynchronous schedule */ + uint32_t pstate; /* Current state in periodic schedule */ + USBPort ports[NB_PORTS]; + USBPort *companion_ports[NB_PORTS]; + uint32_t usbsts_pending; + uint32_t usbsts_frindex; + EHCIQueueHead aqueues; + EHCIQueueHead pqueues; + + /* which address to look at next */ + uint32_t a_fetch_addr; + uint32_t p_fetch_addr; + + USBPacket ipacket; + QEMUSGList isgl; + + uint64_t last_run_ns; + uint32_t async_stepdown; + bool int_req_by_async; +}; + +extern const VMStateDescription vmstate_ehci; + +void usb_ehci_initfn(EHCIState *s, DeviceState *dev); From e433785a768391795e88fbbdd75bbd34859666d3 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 30 Oct 2012 15:08:37 +0100 Subject: [PATCH 1464/2270] usb/ehci: add sysbus variant Signed-off-by: Gerd Hoffmann --- hw/usb/Makefile.objs | 2 +- hw/usb/hcd-ehci-sysbus.c | 77 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 hw/usb/hcd-ehci-sysbus.c diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs index 5c7b024103..7669938abd 100644 --- a/hw/usb/Makefile.objs +++ b/hw/usb/Makefile.objs @@ -1,6 +1,6 @@ common-obj-$(CONFIG_USB_UHCI) += hcd-uhci.o common-obj-$(CONFIG_USB_OHCI) += hcd-ohci.o -common-obj-$(CONFIG_USB_EHCI) += hcd-ehci.o hcd-ehci-pci.o +common-obj-$(CONFIG_USB_EHCI) += hcd-ehci.o hcd-ehci-pci.o hcd-ehci-sysbus.o common-obj-$(CONFIG_USB_XHCI) += hcd-xhci.o common-obj-y += libhw.o diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c new file mode 100644 index 0000000000..1584079796 --- /dev/null +++ b/hw/usb/hcd-ehci-sysbus.c @@ -0,0 +1,77 @@ +/* + * QEMU USB EHCI Emulation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or(at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "hw/usb/hcd-ehci.h" +#include "hw/sysbus.h" + +typedef struct EHCISysBusState { + SysBusDevice busdev; + EHCIState ehci; +} EHCISysBusState; + +static const VMStateDescription vmstate_ehci_sysbus = { + .name = "ehci-sysbus", + .version_id = 2, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_STRUCT(ehci, EHCISysBusState, 2, vmstate_ehci, EHCIState), + VMSTATE_END_OF_LIST() + } +}; + +static Property ehci_sysbus_properties[] = { + DEFINE_PROP_UINT32("maxframes", EHCISysBusState, ehci.maxframes, 128), + DEFINE_PROP_END_OF_LIST(), +}; + +static int usb_ehci_sysbus_initfn(SysBusDevice *dev) +{ + EHCISysBusState *i = FROM_SYSBUS(EHCISysBusState, dev); + EHCIState *s = &i->ehci; + + s->capsbase = 0x100; + s->opregbase = 0x140; + + usb_ehci_initfn(s, DEVICE(dev)); + sysbus_init_irq(dev, &s->irq); + sysbus_init_mmio(dev, &s->mem); + return 0; +} + +static void ehci_sysbus_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = usb_ehci_sysbus_initfn; + dc->vmsd = &vmstate_ehci_sysbus; + dc->props = ehci_sysbus_properties; +} + +TypeInfo ehci_xlnx_type_info = { + .name = "xlnx,ps7-usb", + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(EHCISysBusState), + .class_init = ehci_sysbus_class_init, +}; + +static void ehci_sysbus_register_types(void) +{ + type_register_static(&ehci_xlnx_type_info); +} + +type_init(ehci_sysbus_register_types) From e2134eb9223edac82cc7aa2281779c92c920d579 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 25 Sep 2012 16:04:58 +0200 Subject: [PATCH 1465/2270] pixman: windup in configure & makefiles Signed-off-by: Gerd Hoffmann --- Makefile | 9 +++++++++ configure | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/Makefile b/Makefile index b522b10195..e4866d9bd3 100644 --- a/Makefile +++ b/Makefile @@ -118,6 +118,15 @@ endif subdir-libcacard: $(oslib-obj-y) $(trace-obj-y) qemu-timer-common.o +subdir-pixman: pixman/Makefile + $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C pixman V="$(V)" all,) + +pixman/Makefile: $(SRC_PATH)/pixman/configure + (cd pixman; $(SRC_PATH)/pixman/configure --disable-shared --enable-static) + +$(SRC_PATH)/pixman/configure: + (cd $(SRC_PATH)/pixman; autoreconf -v --install) + $(filter %-softmmu,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) $(common-obj-y) $(extra-obj-y) subdir-libdis $(filter %-user,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) subdir-libdis-user subdir-libuser diff --git a/configure b/configure index 9c6ac875a5..79701ea27b 100755 --- a/configure +++ b/configure @@ -147,6 +147,7 @@ curses="" docs="" fdt="" nptl="" +pixman="" sdl="" virtfs="" vnc="yes" @@ -642,6 +643,10 @@ for opt do # configure to be used by RPM and similar macros that set # lots of directory switches by default. ;; + --with-system-pixman) pixman="system" + ;; + --without-system-pixman) pixman="internal" + ;; --disable-sdl) sdl="no" ;; --enable-sdl) sdl="yes" @@ -2094,6 +2099,34 @@ else exit 1 fi +########################################## +# pixman support probe + +if test "$pixman" = ""; then + if $pkg_config pixman-1 > /dev/null 2>&1; then + pixman="system" + else + pixman="internal" + fi +fi +if test "$pixman" = "system"; then + pixman_cflags=`$pkg_config --cflags pixman-1 2>/dev/null` + pixman_libs=`$pkg_config --libs pixman-1 2>/dev/null` +else + if test ! -d ${source_path}/pixman/pixman; then + echo "ERROR: pixman not present. Your options:" + echo " (1) Prefered: Install the pixman devel package (any recent" + echo " distro should have packages as Xorg needs pixman too)." + echo " (2) Fetch the pixman submodule, using:" + echo " git submodule update --init pixman" + exit 1 + fi + pixman_cflags="-I${source_path}/pixman/pixman" + pixman_libs="-Lpixman/pixman/.libs -lpixman-1" +fi +QEMU_CFLAGS="$QEMU_CFLAGS $pixman_cflags" +libs_softmmu="$libs_softmmu $pixman_libs" + ########################################## # libcap probe @@ -3142,6 +3175,7 @@ echo "-Werror enabled $werror" if test "$darwin" = "yes" ; then echo "Cocoa support $cocoa" fi +echo "pixman $pixman" echo "SDL support $sdl" echo "curses support $curses" echo "curl support $curl" @@ -3908,6 +3942,9 @@ if test "$target_softmmu" = "yes" ; then if test "$smartcard_nss" = "yes" ; then echo "subdir-$target: subdir-libcacard" >> $config_host_mak fi + if test "$pixman" = "internal" ; then + echo "subdir-$target: subdir-pixman" >> $config_host_mak + fi case "$target_arch2" in i386|x86_64) echo "CONFIG_HAVE_CORE_DUMP=y" >> $config_target_mak @@ -4111,6 +4148,7 @@ DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas" DIRS="$DIRS roms/seabios roms/vgabios" DIRS="$DIRS qapi-generated" DIRS="$DIRS libcacard libcacard/libcacard libcacard/trace" +DIRS="$DIRS pixman" FILES="Makefile tests/tcg/Makefile qdict-test-data.txt" FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit" FILES="$FILES tests/tcg/lm32/Makefile libcacard/Makefile" From d2ec7e24a270ba72a151b506ac57c6cd21e3c587 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 25 Sep 2012 16:23:24 +0200 Subject: [PATCH 1466/2270] pixman: helper functions Add some helper functions which will be put into use by following patches. Signed-off-by: Gerd Hoffmann --- Makefile.objs | 1 + qemu-pixman.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-pixman.h | 32 +++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 qemu-pixman.c create mode 100644 qemu-pixman.h diff --git a/Makefile.objs b/Makefile.objs index 9eca179903..acca2854d1 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -65,6 +65,7 @@ common-obj-y = $(block-obj-y) blockdev.o blockdev-nbd.o block/ common-obj-y += net.o net/ common-obj-y += qom/ common-obj-y += readline.o console.o cursor.o +common-obj-y += qemu-pixman.o common-obj-y += $(oslib-obj-y) common-obj-$(CONFIG_WIN32) += os-win32.o common-obj-$(CONFIG_POSIX) += os-posix.o diff --git a/qemu-pixman.c b/qemu-pixman.c new file mode 100644 index 0000000000..7547ed74c1 --- /dev/null +++ b/qemu-pixman.c @@ -0,0 +1,60 @@ +#include "qemu-pixman.h" + +int qemu_pixman_get_type(int rshift, int gshift, int bshift) +{ + int type = PIXMAN_TYPE_OTHER; + + if (rshift > gshift && gshift > bshift) { + if (bshift == 0) { + type = PIXMAN_TYPE_ARGB; + } else { +#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0, 21, 8) + type = PIXMAN_TYPE_RGBA; +#endif + } + } else if (rshift < gshift && gshift < bshift) { + if (rshift == 0) { + type = PIXMAN_TYPE_ABGR; + } else { + type = PIXMAN_TYPE_BGRA; + } + } + return type; +} + +pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf) +{ + pixman_format_code_t format; + int type; + + type = qemu_pixman_get_type(pf->rshift, pf->gshift, pf->bshift); + format = PIXMAN_FORMAT(pf->bits_per_pixel, type, + pf->abits, pf->rbits, pf->gbits, pf->bbits); + if (!pixman_format_supported_source(format)) { + return 0; + } + return format; +} + +pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format, + int width) +{ + pixman_image_t *image = pixman_image_create_bits(format, width, 1, NULL, 0); + assert(image != NULL); + return image; +} + +void qemu_pixman_linebuf_fill(pixman_image_t *linebuf, pixman_image_t *fb, + int width, int y) +{ + pixman_image_composite(PIXMAN_OP_SRC, fb, NULL, linebuf, + 0, y, 0, 0, 0, 0, width, 1); +} + +void qemu_pixman_image_unref(pixman_image_t *image) +{ + if (image == NULL) { + return; + } + pixman_image_unref(image); +} diff --git a/qemu-pixman.h b/qemu-pixman.h new file mode 100644 index 0000000000..7652c41277 --- /dev/null +++ b/qemu-pixman.h @@ -0,0 +1,32 @@ +#ifndef QEMU_PIXMAN_H +#define QEMU_PIXMAN_H + +#include + +#include "console.h" + +/* + * pixman image formats are defined to be native endian, + * that means host byte order on qemu. So we go define + * fixed formats here for cases where it is needed, like + * feeding libjpeg / libpng and writing screenshots. + */ + +#ifdef HOST_WORDS_BIGENDIAN +# define PIXMAN_BE_r8g8b8 PIXMAN_r8g8b8 +#else +# define PIXMAN_BE_r8g8b8 PIXMAN_b8g8r8 +#endif + +/* -------------------------------------------------------------------- */ + +int qemu_pixman_get_type(int rshift, int gshift, int bshift); +pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf); + +pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format, + int width); +void qemu_pixman_linebuf_fill(pixman_image_t *linebuf, pixman_image_t *fb, + int width, int y); +void qemu_pixman_image_unref(pixman_image_t *image); + +#endif /* QEMU_PIXMAN_H */ From 69c7777720c18d8afca7d9685c6dced1aae3a056 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 26 Sep 2012 15:20:05 +0200 Subject: [PATCH 1467/2270] pixman: add pixman image to DisplaySurface Surfaces are now allocated using pixman. DisplaySurface gets new struct fields with pixman image and data. DisplayChangeListeners can easily start using pixman now. Signed-off-by: Gerd Hoffmann --- console.c | 37 ++++++++++++++++++++++++------------- console.h | 3 +++ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/console.c b/console.c index 71cc543b7b..5e1c5f560d 100644 --- a/console.c +++ b/console.c @@ -1319,18 +1319,23 @@ DisplaySurface *qemu_resize_displaysurface(DisplayState *ds, void qemu_alloc_display(DisplaySurface *surface, int width, int height, int linesize, PixelFormat pf, int newflags) { - void *data; surface->width = width; surface->height = height; surface->linesize = linesize; surface->pf = pf; - if (surface->flags & QEMU_ALLOCATED_FLAG) { - data = g_realloc(surface->data, - surface->linesize * surface->height); - } else { - data = g_malloc(surface->linesize * surface->height); - } - surface->data = (uint8_t *)data; + + qemu_pixman_image_unref(surface->image); + surface->image = NULL; + surface->data = NULL; + + surface->format = qemu_pixman_get_format(&pf); + assert(surface->format != 0); + surface->image = pixman_image_create_bits(surface->format, + width, height, + NULL, linesize); + assert(surface->image != NULL); + + surface->data = (uint8_t *)pixman_image_get_data(surface->image); surface->flags = newflags | QEMU_ALLOCATED_FLAG; #ifdef HOST_WORDS_BIGENDIAN surface->flags |= QEMU_BIG_ENDIAN_FLAG; @@ -1338,14 +1343,22 @@ void qemu_alloc_display(DisplaySurface *surface, int width, int height, } DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp, - int linesize, uint8_t *data) + int linesize, uint8_t *data) { - DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface)); + DisplaySurface *surface = g_new0(DisplaySurface, 1); surface->width = width; surface->height = height; surface->linesize = linesize; surface->pf = qemu_default_pixelformat(bpp); + + surface->format = qemu_pixman_get_format(&surface->pf); + assert(surface->format != 0); + surface->image = pixman_image_create_bits(surface->format, + width, height, + (void *)data, linesize); + assert(surface->image != NULL); + #ifdef HOST_WORDS_BIGENDIAN surface->flags = QEMU_BIG_ENDIAN_FLAG; #endif @@ -1360,9 +1373,7 @@ void qemu_free_displaysurface(DisplayState *ds) if (ds->surface == NULL) { return; } - if (ds->surface->flags & QEMU_ALLOCATED_FLAG) { - g_free(ds->surface->data); - } + qemu_pixman_image_unref(ds->surface->image); g_free(ds->surface); } diff --git a/console.h b/console.h index 6be880a554..f19e6a443b 100644 --- a/console.h +++ b/console.h @@ -2,6 +2,7 @@ #define CONSOLE_H #include "qemu-char.h" +#include "qemu-pixman.h" #include "qdict.h" #include "notify.h" #include "monitor.h" @@ -119,6 +120,8 @@ struct PixelFormat { }; struct DisplaySurface { + pixman_format_code_t format; + pixman_image_t *image; uint8_t flags; int width; int height; From 537a43913c19973adc4153d30498591f92a90359 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 27 Sep 2012 11:06:36 +0200 Subject: [PATCH 1468/2270] console: make qemu_alloc_display static Signed-off-by: Gerd Hoffmann --- console.c | 48 ++++++++++++++++++++++++------------------------ console.h | 2 -- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/console.c b/console.c index 5e1c5f560d..48d88e43ce 100644 --- a/console.c +++ b/console.c @@ -1294,30 +1294,8 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type) return s; } -DisplaySurface *qemu_create_displaysurface(DisplayState *ds, - int width, int height) -{ - DisplaySurface *surface = g_new0(DisplaySurface, 1); - - int linesize = width * 4; - qemu_alloc_display(surface, width, height, linesize, - qemu_default_pixelformat(32), 0); - return surface; -} - -DisplaySurface *qemu_resize_displaysurface(DisplayState *ds, - int width, int height) -{ - int linesize = width * 4; - - trace_displaysurface_resize(ds, ds->surface, width, height); - qemu_alloc_display(ds->surface, width, height, linesize, - qemu_default_pixelformat(32), 0); - return ds->surface; -} - -void qemu_alloc_display(DisplaySurface *surface, int width, int height, - int linesize, PixelFormat pf, int newflags) +static void qemu_alloc_display(DisplaySurface *surface, int width, int height, + int linesize, PixelFormat pf, int newflags) { surface->width = width; surface->height = height; @@ -1342,6 +1320,28 @@ void qemu_alloc_display(DisplaySurface *surface, int width, int height, #endif } +DisplaySurface *qemu_create_displaysurface(DisplayState *ds, + int width, int height) +{ + DisplaySurface *surface = g_new0(DisplaySurface, 1); + + int linesize = width * 4; + qemu_alloc_display(surface, width, height, linesize, + qemu_default_pixelformat(32), 0); + return surface; +} + +DisplaySurface *qemu_resize_displaysurface(DisplayState *ds, + int width, int height) +{ + int linesize = width * 4; + + trace_displaysurface_resize(ds, ds->surface, width, height); + qemu_alloc_display(ds->surface, width, height, linesize, + qemu_default_pixelformat(32), 0); + return ds->surface; +} + DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp, int linesize, uint8_t *data) { diff --git a/console.h b/console.h index f19e6a443b..21bd957d95 100644 --- a/console.h +++ b/console.h @@ -190,8 +190,6 @@ void register_displaystate(DisplayState *ds); DisplayState *get_displaystate(void); DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, int linesize, uint8_t *data); -void qemu_alloc_display(DisplaySurface *surface, int width, int height, - int linesize, PixelFormat pf, int newflags); PixelFormat qemu_different_endianness_pixelformat(int bpp); PixelFormat qemu_default_pixelformat(int bpp); From 09bbb0ae8226c71aba440bdfa6fca300acd9e5d4 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 10 Oct 2012 11:16:26 +0200 Subject: [PATCH 1469/2270] console: don't set PixelFormat alpha fields for 32bpp Currently it is inconstent, PixelFormat->amask is left unset whereas abits and amax and ashift are filled. As an alpha channel doesn't make sense for the vga framebuffer leave all alpha fields clear. Signed-off-by: Gerd Hoffmann --- console.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/console.c b/console.c index 48d88e43ce..d28b75ec7d 100644 --- a/console.c +++ b/console.c @@ -1715,18 +1715,15 @@ PixelFormat qemu_default_pixelformat(int bpp) pf.rmask = 0x00FF0000; pf.gmask = 0x0000FF00; pf.bmask = 0x000000FF; - pf.amax = 255; pf.rmax = 255; pf.gmax = 255; pf.bmax = 255; - pf.ashift = 24; pf.rshift = 16; pf.gshift = 8; pf.bshift = 0; pf.rbits = 8; pf.gbits = 8; pf.bbits = 8; - pf.abits = 8; break; default: break; From b6e9f63711ea19b110574e384477bad4ea74f4a2 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 10 Oct 2012 13:02:14 +0200 Subject: [PATCH 1470/2270] qxl: stop direct access to DisplaySurface fields. Signed-off-by: Gerd Hoffmann --- hw/qxl-render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/qxl-render.c b/hw/qxl-render.c index 47eb8b4154..98ecb21405 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -24,7 +24,7 @@ static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect) { uint8_t *src; - uint8_t *dst = qxl->vga.ds->surface->data; + uint8_t *dst = ds_get_data(qxl->vga.ds); int len, i; if (is_buffer_shared(qxl->vga.ds->surface)) { From 1fd2510a3786fb557919cdd71e8e65c504439ddc Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 10 Oct 2012 13:05:05 +0200 Subject: [PATCH 1471/2270] vga: stop direct access to DisplaySurface fields. Signed-off-by: Gerd Hoffmann --- hw/vga.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/hw/vga.c b/hw/vga.c index f31dbdd652..1188463208 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -1709,8 +1709,13 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) s->last_depth = depth; full_update = 1; } else if (is_buffer_shared(s->ds->surface) && - (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) { - s->ds->surface->data = s->vram_ptr + (s->start_addr * 4); + (full_update || ds_get_data(s->ds) != s->vram_ptr + + (s->start_addr * 4))) { + qemu_free_displaysurface(s->ds); + s->ds->surface = qemu_create_displaysurface_from(disp_width, + height, depth, + s->line_offset, + s->vram_ptr + (s->start_addr * 4)); dpy_gfx_setdata(s->ds); } From b12f32c408ef8cb9b3a4dfcb3710b382fd24a3ee Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 10 Oct 2012 13:12:58 +0200 Subject: [PATCH 1472/2270] pixman: switch screendump function. Signed-off-by: Gerd Hoffmann --- hw/vga.c | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/hw/vga.c b/hw/vga.c index 1188463208..023134ef68 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -2393,13 +2393,12 @@ void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory) void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp) { + int width = pixman_image_get_width(ds->image); + int height = pixman_image_get_height(ds->image); FILE *f; - uint8_t *d, *d1; - uint32_t v; - int y, x; - uint8_t r, g, b; + int y; int ret; - char *linebuf, *pbuf; + pixman_image_t *linebuf; trace_ppm_save(filename, ds); f = fopen(filename, "wb"); @@ -2408,33 +2407,17 @@ void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp) strerror(errno)); return; } - ret = fprintf(f, "P6\n%d %d\n%d\n", ds->width, ds->height, 255); + ret = fprintf(f, "P6\n%d %d\n%d\n", width, height, 255); if (ret < 0) { linebuf = NULL; goto write_err; } - linebuf = g_malloc(ds->width * 3); - d1 = ds->data; - for(y = 0; y < ds->height; y++) { - d = d1; - pbuf = linebuf; - for(x = 0; x < ds->width; x++) { - if (ds->pf.bits_per_pixel == 32) - v = *(uint32_t *)d; - else - v = (uint32_t) (*(uint16_t *)d); - /* Limited to 8 or fewer bits per channel: */ - r = ((v >> ds->pf.rshift) & ds->pf.rmax) << (8 - ds->pf.rbits); - g = ((v >> ds->pf.gshift) & ds->pf.gmax) << (8 - ds->pf.gbits); - b = ((v >> ds->pf.bshift) & ds->pf.bmax) << (8 - ds->pf.bbits); - *pbuf++ = r; - *pbuf++ = g; - *pbuf++ = b; - d += ds->pf.bytes_per_pixel; - } - d1 += ds->linesize; + linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width); + for (y = 0; y < height; y++) { + qemu_pixman_linebuf_fill(linebuf, ds->image, width, y); clearerr(f); - ret = fwrite(linebuf, 1, pbuf - linebuf, f); + ret = fwrite(pixman_image_get_data(linebuf), 1, + pixman_image_get_stride(linebuf), f); (void)ret; if (ferror(f)) { goto write_err; @@ -2442,7 +2425,7 @@ void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp) } out: - g_free(linebuf); + qemu_pixman_image_unref(linebuf); fclose(f); return; From 9f64916da20eea67121d544698676295bbb105a7 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 10 Oct 2012 13:29:43 +0200 Subject: [PATCH 1473/2270] pixman/vnc: use pixman images in vnc. The vnc code uses *three* DisplaySurfaces: First is the surface of the actual QemuConsole, usually the guest screen, but could also be a text console (monitor/serial reachable via Ctrl-Alt- keys). This is left as-is. Second is the current server's view of the screen content. The vnc code uses this to figure which parts of the guest screen did _really_ change to reduce the amount of updates sent to the vnc clients. It is also used as data source when sending out the updates to the clients. This surface gets replaced by a pixman image. The format changes too, instead of using the guest screen format we'll use fixed 32bit rgb framebuffer and convert the pixels on the fly when comparing and updating the server framebuffer. Third surface carries the format expected by the vnc client. That isn't used to store image data. This surface is switched to PixelFormat and a boolean for bigendian byte order. Signed-off-by: Gerd Hoffmann --- ui/vnc-enc-hextile-template.h | 23 ++-- ui/vnc-enc-hextile.c | 45 ++++--- ui/vnc-enc-tight.c | 144 ++++++++++----------- ui/vnc-enc-zrle.c | 18 +-- ui/vnc-jobs.c | 3 +- ui/vnc.c | 235 +++++++++++++++++++--------------- ui/vnc.h | 19 ++- 7 files changed, 259 insertions(+), 228 deletions(-) diff --git a/ui/vnc-enc-hextile-template.h b/ui/vnc-enc-hextile-template.h index a7310e1947..d868d75720 100644 --- a/ui/vnc-enc-hextile-template.h +++ b/ui/vnc-enc-hextile-template.h @@ -14,7 +14,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs, int *has_bg, int *has_fg) { VncDisplay *vd = vs->vd; - uint8_t *row = vd->server->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds); + uint8_t *row = vnc_server_fb_ptr(vd, x, y); pixel_t *irow = (pixel_t *)row; int j, i; pixel_t *last_bg = (pixel_t *)last_bg_; @@ -25,7 +25,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs, int bg_count = 0; int fg_count = 0; int flags = 0; - uint8_t data[(vs->clientds.pf.bytes_per_pixel + 2) * 16 * 16]; + uint8_t data[(vs->client_pf.bytes_per_pixel + 2) * 16 * 16]; int n_data = 0; int n_subtiles = 0; @@ -58,7 +58,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs, } if (n_colors > 2) break; - irow += ds_get_linesize(vs->ds) / sizeof(pixel_t); + irow += vnc_server_fb_stride(vd) / sizeof(pixel_t); } if (n_colors > 1 && fg_count > bg_count) { @@ -106,7 +106,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs, n_data += 2; n_subtiles++; } - irow += ds_get_linesize(vs->ds) / sizeof(pixel_t); + irow += vnc_server_fb_stride(vd) / sizeof(pixel_t); } break; case 3: @@ -133,7 +133,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs, has_color = 0; #ifdef GENERIC vnc_convert_pixel(vs, data + n_data, color); - n_data += vs->clientds.pf.bytes_per_pixel; + n_data += vs->client_pf.bytes_per_pixel; #else memcpy(data + n_data, &color, sizeof(color)); n_data += sizeof(pixel_t); @@ -153,7 +153,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs, if (has_color) { #ifdef GENERIC vnc_convert_pixel(vs, data + n_data, color); - n_data += vs->clientds.pf.bytes_per_pixel; + n_data += vs->client_pf.bytes_per_pixel; #else memcpy(data + n_data, &color, sizeof(color)); n_data += sizeof(pixel_t); @@ -162,7 +162,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs, n_data += 2; n_subtiles++; } - irow += ds_get_linesize(vs->ds) / sizeof(pixel_t); + irow += vnc_server_fb_stride(vd) / sizeof(pixel_t); } /* A SubrectsColoured subtile invalidates the foreground color */ @@ -190,18 +190,17 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs, vnc_write_u8(vs, flags); if (n_colors < 4) { if (flags & 0x02) - vs->write_pixels(vs, &vd->server->pf, last_bg, sizeof(pixel_t)); + vs->write_pixels(vs, last_bg, sizeof(pixel_t)); if (flags & 0x04) - vs->write_pixels(vs, &vd->server->pf, last_fg, sizeof(pixel_t)); + vs->write_pixels(vs, last_fg, sizeof(pixel_t)); if (n_subtiles) { vnc_write_u8(vs, n_subtiles); vnc_write(vs, data, n_data); } } else { for (j = 0; j < h; j++) { - vs->write_pixels(vs, &vd->server->pf, row, - w * ds_get_bytes_per_pixel(vs->ds)); - row += ds_get_linesize(vs->ds); + vs->write_pixels(vs, row, w * 4); + row += vnc_server_fb_stride(vd); } } } diff --git a/ui/vnc-enc-hextile.c b/ui/vnc-enc-hextile.c index c860dbb2e5..263a0ce9d2 100644 --- a/ui/vnc-enc-hextile.c +++ b/ui/vnc-enc-hextile.c @@ -68,10 +68,9 @@ int vnc_hextile_send_framebuffer_update(VncState *vs, int x, int i, j; int has_fg, has_bg; uint8_t *last_fg, *last_bg; - VncDisplay *vd = vs->vd; - last_fg = (uint8_t *) g_malloc(vd->server->pf.bytes_per_pixel); - last_bg = (uint8_t *) g_malloc(vd->server->pf.bytes_per_pixel); + last_fg = (uint8_t *) g_malloc(VNC_SERVER_FB_BYTES); + last_bg = (uint8_t *) g_malloc(VNC_SERVER_FB_BYTES); has_fg = has_bg = 0; for (j = y; j < (y + h); j += 16) { for (i = x; i < (x + w); i += 16) { @@ -89,28 +88,28 @@ int vnc_hextile_send_framebuffer_update(VncState *vs, int x, void vnc_hextile_set_pixel_conversion(VncState *vs, int generic) { if (!generic) { - switch (vs->ds->surface->pf.bits_per_pixel) { - case 8: - vs->hextile.send_tile = send_hextile_tile_8; - break; - case 16: - vs->hextile.send_tile = send_hextile_tile_16; - break; - case 32: - vs->hextile.send_tile = send_hextile_tile_32; - break; + switch (VNC_SERVER_FB_BITS) { + case 8: + vs->hextile.send_tile = send_hextile_tile_8; + break; + case 16: + vs->hextile.send_tile = send_hextile_tile_16; + break; + case 32: + vs->hextile.send_tile = send_hextile_tile_32; + break; } } else { - switch (vs->ds->surface->pf.bits_per_pixel) { - case 8: - vs->hextile.send_tile = send_hextile_tile_generic_8; - break; - case 16: - vs->hextile.send_tile = send_hextile_tile_generic_16; - break; - case 32: - vs->hextile.send_tile = send_hextile_tile_generic_32; - break; + switch (VNC_SERVER_FB_BITS) { + case 8: + vs->hextile.send_tile = send_hextile_tile_generic_8; + break; + case 16: + vs->hextile.send_tile = send_hextile_tile_generic_16; + break; + case 32: + vs->hextile.send_tile = send_hextile_tile_generic_32; + break; } } } diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c index 5d492abe92..8013c5c6dd 100644 --- a/ui/vnc-enc-tight.c +++ b/ui/vnc-enc-tight.c @@ -124,7 +124,7 @@ static bool tight_can_send_png_rect(VncState *vs, int w, int h) } if (ds_get_bytes_per_pixel(vs->ds) == 1 || - vs->clientds.pf.bytes_per_pixel == 1) { + vs->client_pf.bytes_per_pixel == 1) { return false; } @@ -153,7 +153,7 @@ tight_detect_smooth_image24(VncState *vs, int w, int h) * If client is big-endian, color samples begin from the second * byte (offset 1) of a 32-bit pixel value. */ - off = !!(vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG); + off = vs->client_be; memset(stats, 0, sizeof (stats)); @@ -216,16 +216,16 @@ tight_detect_smooth_image24(VncState *vs, int w, int h) unsigned int errors; \ unsigned char *buf = vs->tight.tight.buffer; \ \ - endian = ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \ - (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)); \ + endian = 0; /* FIXME: ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \ + (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)); */ \ \ \ - max[0] = vs->clientds.pf.rmax; \ - max[1] = vs->clientds.pf.gmax; \ - max[2] = vs->clientds.pf.bmax; \ - shift[0] = vs->clientds.pf.rshift; \ - shift[1] = vs->clientds.pf.gshift; \ - shift[2] = vs->clientds.pf.bshift; \ + max[0] = vs->client_pf.rmax; \ + max[1] = vs->client_pf.gmax; \ + max[2] = vs->client_pf.bmax; \ + shift[0] = vs->client_pf.rshift; \ + shift[1] = vs->client_pf.gshift; \ + shift[2] = vs->client_pf.bshift; \ \ memset(stats, 0, sizeof(stats)); \ \ @@ -302,7 +302,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h) } if (ds_get_bytes_per_pixel(vs->ds) == 1 || - vs->clientds.pf.bytes_per_pixel == 1 || + vs->client_pf.bytes_per_pixel == 1 || w < VNC_TIGHT_DETECT_MIN_WIDTH || h < VNC_TIGHT_DETECT_MIN_HEIGHT) { return 0; } @@ -317,7 +317,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h) } } - if (vs->clientds.pf.bytes_per_pixel == 4) { + if (vs->client_pf.bytes_per_pixel == 4) { if (vs->tight.pixel24) { errors = tight_detect_smooth_image24(vs, w, h); if (vs->tight.quality != (uint8_t)-1) { @@ -430,7 +430,7 @@ static int tight_fill_palette(VncState *vs, int x, int y, max = 256; } - switch(vs->clientds.pf.bytes_per_pixel) { + switch (vs->client_pf.bytes_per_pixel) { case 4: return tight_fill_palette32(vs, x, y, max, count, bg, fg, palette); case 2: @@ -557,15 +557,15 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h) buf32 = (uint32_t *)buf; memset(vs->tight.gradient.buffer, 0, w * 3 * sizeof(int)); - if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) == - (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)) { - shift[0] = vs->clientds.pf.rshift; - shift[1] = vs->clientds.pf.gshift; - shift[2] = vs->clientds.pf.bshift; + if (1 /* FIXME: (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) == + (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) */) { + shift[0] = vs->client_pf.rshift; + shift[1] = vs->client_pf.gshift; + shift[2] = vs->client_pf.bshift; } else { - shift[0] = 24 - vs->clientds.pf.rshift; - shift[1] = 24 - vs->clientds.pf.gshift; - shift[2] = 24 - vs->clientds.pf.bshift; + shift[0] = 24 - vs->client_pf.rshift; + shift[1] = 24 - vs->client_pf.gshift; + shift[2] = 24 - vs->client_pf.bshift; } for (y = 0; y < h; y++) { @@ -615,15 +615,15 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h) \ memset (vs->tight.gradient.buffer, 0, w * 3 * sizeof(int)); \ \ - endian = ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \ - (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)); \ + endian = 0; /* FIXME: ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \ + (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)); */ \ \ - max[0] = vs->clientds.pf.rmax; \ - max[1] = vs->clientds.pf.gmax; \ - max[2] = vs->clientds.pf.bmax; \ - shift[0] = vs->clientds.pf.rshift; \ - shift[1] = vs->clientds.pf.gshift; \ - shift[2] = vs->clientds.pf.bshift; \ + max[0] = vs->client_pf.rmax; \ + max[1] = vs->client_pf.gmax; \ + max[2] = vs->client_pf.bmax; \ + shift[0] = vs->client_pf.rshift; \ + shift[1] = vs->client_pf.gshift; \ + shift[2] = vs->client_pf.bshift; \ \ for (y = 0; y < h; y++) { \ for (c = 0; c < 3; c++) { \ @@ -682,9 +682,7 @@ DEFINE_GRADIENT_FILTER_FUNCTION(32) uint##bpp##_t c; \ int dx, dy; \ \ - fbptr = (uint##bpp##_t *) \ - (vd->server->data + y * ds_get_linesize(vs->ds) + \ - x * ds_get_bytes_per_pixel(vs->ds)); \ + fbptr = vnc_server_fb_ptr(vd, x, y); \ \ c = *fbptr; \ if (samecolor && (uint32_t)c != *color) { \ @@ -698,7 +696,7 @@ DEFINE_GRADIENT_FILTER_FUNCTION(32) } \ } \ fbptr = (uint##bpp##_t *) \ - ((uint8_t *)fbptr + ds_get_linesize(vs->ds)); \ + ((uint8_t *)fbptr + vnc_server_fb_stride(vd)); \ } \ \ *color = (uint32_t)c; \ @@ -712,9 +710,7 @@ DEFINE_CHECK_SOLID_FUNCTION(8) static bool check_solid_tile(VncState *vs, int x, int y, int w, int h, uint32_t* color, bool samecolor) { - VncDisplay *vd = vs->vd; - - switch(vd->server->pf.bytes_per_pixel) { + switch (VNC_SERVER_FB_BYTES) { case 4: return check_solid_tile32(vs, x, y, w, h, color, samecolor); case 2: @@ -906,15 +902,15 @@ static void tight_pack24(VncState *vs, uint8_t *buf, size_t count, size_t *ret) buf32 = (uint32_t *)buf; - if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) == - (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)) { - rshift = vs->clientds.pf.rshift; - gshift = vs->clientds.pf.gshift; - bshift = vs->clientds.pf.bshift; + if (1 /* FIXME: (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) == + (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) */) { + rshift = vs->client_pf.rshift; + gshift = vs->client_pf.gshift; + bshift = vs->client_pf.bshift; } else { - rshift = 24 - vs->clientds.pf.rshift; - gshift = 24 - vs->clientds.pf.gshift; - bshift = 24 - vs->clientds.pf.bshift; + rshift = 24 - vs->client_pf.rshift; + gshift = 24 - vs->client_pf.gshift; + bshift = 24 - vs->client_pf.bshift; } if (ret) { @@ -946,7 +942,7 @@ static int send_full_color_rect(VncState *vs, int x, int y, int w, int h) tight_pack24(vs, vs->tight.tight.buffer, w * h, &vs->tight.tight.offset); bytes = 3; } else { - bytes = vs->clientds.pf.bytes_per_pixel; + bytes = vs->client_pf.bytes_per_pixel; } bytes = tight_compress_data(vs, stream, w * h * bytes, @@ -966,7 +962,7 @@ static int send_solid_rect(VncState *vs) tight_pack24(vs, vs->tight.tight.buffer, 1, &vs->tight.tight.offset); bytes = 3; } else { - bytes = vs->clientds.pf.bytes_per_pixel; + bytes = vs->client_pf.bytes_per_pixel; } vnc_write(vs, vs->tight.tight.buffer, bytes); @@ -983,7 +979,7 @@ static int send_mono_rect(VncState *vs, int x, int y, #ifdef CONFIG_VNC_PNG if (tight_can_send_png_rect(vs, w, h)) { int ret; - int bpp = vs->clientds.pf.bytes_per_pixel * 8; + int bpp = vs->client_pf.bytes_per_pixel * 8; VncPalette *palette = palette_new(2, bpp); palette_put(palette, bg); @@ -1000,7 +996,7 @@ static int send_mono_rect(VncState *vs, int x, int y, vnc_write_u8(vs, VNC_TIGHT_FILTER_PALETTE); vnc_write_u8(vs, 1); - switch(vs->clientds.pf.bytes_per_pixel) { + switch (vs->client_pf.bytes_per_pixel) { case 4: { uint32_t buf[2] = {bg, fg}; @@ -1043,7 +1039,7 @@ static void write_palette(int idx, uint32_t color, void *opaque) { struct palette_cb_priv *priv = opaque; VncState *vs = priv->vs; - uint32_t bytes = vs->clientds.pf.bytes_per_pixel; + uint32_t bytes = vs->client_pf.bytes_per_pixel; if (bytes == 4) { ((uint32_t*)priv->header)[idx] = color; @@ -1058,8 +1054,9 @@ static bool send_gradient_rect(VncState *vs, int x, int y, int w, int h) int level = tight_conf[vs->tight.compression].gradient_zlib_level; ssize_t bytes; - if (vs->clientds.pf.bytes_per_pixel == 1) + if (vs->client_pf.bytes_per_pixel == 1) { return send_full_color_rect(vs, x, y, w, h); + } vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4); vnc_write_u8(vs, VNC_TIGHT_FILTER_GRADIENT); @@ -1069,7 +1066,7 @@ static bool send_gradient_rect(VncState *vs, int x, int y, int w, int h) if (vs->tight.pixel24) { tight_filter_gradient24(vs, vs->tight.tight.buffer, w, h); bytes = 3; - } else if (vs->clientds.pf.bytes_per_pixel == 4) { + } else if (vs->client_pf.bytes_per_pixel == 4) { tight_filter_gradient32(vs, (uint32_t *)vs->tight.tight.buffer, w, h); bytes = 4; } else { @@ -1107,7 +1104,7 @@ static int send_palette_rect(VncState *vs, int x, int y, vnc_write_u8(vs, VNC_TIGHT_FILTER_PALETTE); vnc_write_u8(vs, colors - 1); - switch(vs->clientds.pf.bytes_per_pixel) { + switch (vs->client_pf.bytes_per_pixel) { case 4: { size_t old_offset, offset; @@ -1156,8 +1153,7 @@ static void rgb_prepare_row24(VncState *vs, uint8_t *dst, int x, int y, uint32_t *fbptr; uint32_t pix; - fbptr = (uint32_t *)(vd->server->data + y * ds_get_linesize(vs->ds) + - x * ds_get_bytes_per_pixel(vs->ds)); + fbptr = vnc_server_fb_ptr(vd, x, y); while (count--) { pix = *fbptr++; @@ -1178,9 +1174,7 @@ static void rgb_prepare_row24(VncState *vs, uint8_t *dst, int x, int y, uint##bpp##_t pix; \ int r, g, b; \ \ - fbptr = (uint##bpp##_t *) \ - (vd->server->data + y * ds_get_linesize(vs->ds) + \ - x * ds_get_bytes_per_pixel(vs->ds)); \ + fbptr = vnc_server_fb_ptr(vd, x, y); \ \ while (count--) { \ pix = *fbptr++; \ @@ -1207,10 +1201,8 @@ DEFINE_RGB_GET_ROW_FUNCTION(32) static void rgb_prepare_row(VncState *vs, uint8_t *dst, int x, int y, int count) { - if (ds_get_bytes_per_pixel(vs->ds) == 4) { - if (vs->ds->surface->pf.rmax == 0xFF && - vs->ds->surface->pf.gmax == 0xFF && - vs->ds->surface->pf.bmax == 0xFF) { + if (VNC_SERVER_FB_BYTES == 4) { + if (1) { rgb_prepare_row24(vs, dst, x, y, count); } else { rgb_prepare_row32(vs, dst, x, y, count); @@ -1326,23 +1318,23 @@ static void write_png_palette(int idx, uint32_t pix, void *opaque) if (vs->tight.pixel24) { - color->red = (pix >> vs->clientds.pf.rshift) & vs->clientds.pf.rmax; - color->green = (pix >> vs->clientds.pf.gshift) & vs->clientds.pf.gmax; - color->blue = (pix >> vs->clientds.pf.bshift) & vs->clientds.pf.bmax; + color->red = (pix >> vs->client_pf.rshift) & vs->client_pf.rmax; + color->green = (pix >> vs->client_pf.gshift) & vs->client_pf.gmax; + color->blue = (pix >> vs->client_pf.bshift) & vs->client_pf.bmax; } else { int red, green, blue; - red = (pix >> vs->clientds.pf.rshift) & vs->clientds.pf.rmax; - green = (pix >> vs->clientds.pf.gshift) & vs->clientds.pf.gmax; - blue = (pix >> vs->clientds.pf.bshift) & vs->clientds.pf.bmax; - color->red = ((red * 255 + vs->clientds.pf.rmax / 2) / - vs->clientds.pf.rmax); - color->green = ((green * 255 + vs->clientds.pf.gmax / 2) / - vs->clientds.pf.gmax); - color->blue = ((blue * 255 + vs->clientds.pf.bmax / 2) / - vs->clientds.pf.bmax); + red = (pix >> vs->client_pf.rshift) & vs->client_pf.rmax; + green = (pix >> vs->client_pf.gshift) & vs->client_pf.gmax; + blue = (pix >> vs->client_pf.bshift) & vs->client_pf.bmax; + color->red = ((red * 255 + vs->client_pf.rmax / 2) / + vs->client_pf.rmax); + color->green = ((green * 255 + vs->client_pf.gmax / 2) / + vs->client_pf.gmax); + color->blue = ((blue * 255 + vs->client_pf.bmax / 2) / + vs->client_pf.bmax); } } @@ -1422,7 +1414,7 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h, png_set_PLTE(png_ptr, info_ptr, png_palette, palette_size(palette)); - if (vs->clientds.pf.bytes_per_pixel == 4) { + if (vs->client_pf.bytes_per_pixel == 4) { tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette); } else { tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette); @@ -1713,8 +1705,8 @@ static int tight_send_framebuffer_update(VncState *vs, int x, int y, { int max_rows; - if (vs->clientds.pf.bytes_per_pixel == 4 && vs->clientds.pf.rmax == 0xFF && - vs->clientds.pf.bmax == 0xFF && vs->clientds.pf.gmax == 0xFF) { + if (vs->client_pf.bytes_per_pixel == 4 && vs->client_pf.rmax == 0xFF && + vs->client_pf.bmax == 0xFF && vs->client_pf.gmax == 0xFF) { vs->tight.pixel24 = true; } else { vs->tight.pixel24 = false; diff --git a/ui/vnc-enc-zrle.c b/ui/vnc-enc-zrle.c index 917d384f57..ed3b48465d 100644 --- a/ui/vnc-enc-zrle.c +++ b/ui/vnc-enc-zrle.c @@ -255,7 +255,7 @@ static void zrle_write_u8(VncState *vs, uint8_t value) static int zrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) { - bool be = !!(vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG); + bool be = vs->client_be; size_t bytes; int zywrle_level; @@ -277,13 +277,13 @@ static int zrle_send_framebuffer_update(VncState *vs, int x, int y, vnc_zrle_start(vs); - switch(vs->clientds.pf.bytes_per_pixel) { + switch (vs->client_pf.bytes_per_pixel) { case 1: zrle_encode_8ne(vs, x, y, w, h, zywrle_level); break; case 2: - if (vs->clientds.pf.gmax > 0x1F) { + if (vs->client_pf.gmax > 0x1F) { if (be) { zrle_encode_16be(vs, x, y, w, h, zywrle_level); } else { @@ -304,13 +304,13 @@ static int zrle_send_framebuffer_update(VncState *vs, int x, int y, bool fits_in_ms3bytes; fits_in_ls3bytes = - ((vs->clientds.pf.rmax << vs->clientds.pf.rshift) < (1 << 24) && - (vs->clientds.pf.gmax << vs->clientds.pf.gshift) < (1 << 24) && - (vs->clientds.pf.bmax << vs->clientds.pf.bshift) < (1 << 24)); + ((vs->client_pf.rmax << vs->client_pf.rshift) < (1 << 24) && + (vs->client_pf.gmax << vs->client_pf.gshift) < (1 << 24) && + (vs->client_pf.bmax << vs->client_pf.bshift) < (1 << 24)); - fits_in_ms3bytes = (vs->clientds.pf.rshift > 7 && - vs->clientds.pf.gshift > 7 && - vs->clientds.pf.bshift > 7); + fits_in_ms3bytes = (vs->client_pf.rshift > 7 && + vs->client_pf.gshift > 7 && + vs->client_pf.bshift > 7); if ((fits_in_ls3bytes && !be) || (fits_in_ms3bytes && be)) { if (be) { diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c index 3c592b3f3d..04f139b56f 100644 --- a/ui/vnc-jobs.c +++ b/ui/vnc-jobs.c @@ -187,7 +187,8 @@ static void vnc_async_encoding_start(VncState *orig, VncState *local) local->vd = orig->vd; local->lossy_rect = orig->lossy_rect; local->write_pixels = orig->write_pixels; - local->clientds = orig->clientds; + local->client_pf = orig->client_pf; + local->client_be = orig->client_be; local->tight = orig->tight; local->zlib = orig->zlib; local->hextile = orig->hextile; diff --git a/ui/vnc.c b/ui/vnc.c index 0ae1c74984..15aef86047 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -436,6 +436,8 @@ static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h) int i; VncDisplay *vd = ds->opaque; struct VncSurface *s = &vd->guest; + int width = ds_get_width(ds); + int height = ds_get_height(ds); h += y; @@ -446,10 +448,10 @@ static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h) w += (x % 16); x -= (x % 16); - x = MIN(x, s->ds->width); - y = MIN(y, s->ds->height); - w = MIN(x + w, s->ds->width) - x; - h = MIN(h, s->ds->height); + x = MIN(x, width); + y = MIN(y, height); + w = MIN(x + w, width) - x; + h = MIN(h, height); for (; y < h; y++) for (i = 0; i < w; i += 16) @@ -550,6 +552,21 @@ static void vnc_abort_display_jobs(VncDisplay *vd) } } +int vnc_server_fb_stride(VncDisplay *vd) +{ + return pixman_image_get_stride(vd->server); +} + +void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y) +{ + uint8_t *ptr; + + ptr = (uint8_t *)pixman_image_get_data(vd->server); + ptr += y * vnc_server_fb_stride(vd); + ptr += x * VNC_SERVER_FB_BYTES; + return ptr; +} + static void vnc_dpy_resize(DisplayState *ds) { VncDisplay *vd = ds->opaque; @@ -558,20 +575,20 @@ static void vnc_dpy_resize(DisplayState *ds) vnc_abort_display_jobs(vd); /* server surface */ - if (!vd->server) - vd->server = g_malloc0(sizeof(*vd->server)); - if (vd->server->data) - g_free(vd->server->data); - *(vd->server) = *(ds->surface); - vd->server->data = g_malloc0(vd->server->linesize * - vd->server->height); + qemu_pixman_image_unref(vd->server); + vd->server = pixman_image_create_bits(VNC_SERVER_FB_FORMAT, + ds_get_width(ds), + ds_get_height(ds), + NULL, 0); /* guest surface */ - if (!vd->guest.ds) - vd->guest.ds = g_malloc0(sizeof(*vd->guest.ds)); +#if 0 /* FIXME */ if (ds_get_bytes_per_pixel(ds) != vd->guest.ds->pf.bytes_per_pixel) console_color_init(ds); - *(vd->guest.ds) = *(ds->surface); +#endif + qemu_pixman_image_unref(vd->guest.fb); + vd->guest.fb = pixman_image_ref(ds->surface->image); + vd->guest.format = ds->surface->format; memset(vd->guest.dirty, 0xFF, sizeof(vd->guest.dirty)); QTAILQ_FOREACH(vs, &vd->clients, next) { @@ -585,7 +602,7 @@ static void vnc_dpy_resize(DisplayState *ds) } /* fastest code */ -static void vnc_write_pixels_copy(VncState *vs, struct PixelFormat *pf, +static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size) { vnc_write(vs, pixels, size); @@ -595,23 +612,23 @@ static void vnc_write_pixels_copy(VncState *vs, struct PixelFormat *pf, void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v) { uint8_t r, g, b; - VncDisplay *vd = vs->vd; - r = ((((v & vd->server->pf.rmask) >> vd->server->pf.rshift) << vs->clientds.pf.rbits) >> - vd->server->pf.rbits); - g = ((((v & vd->server->pf.gmask) >> vd->server->pf.gshift) << vs->clientds.pf.gbits) >> - vd->server->pf.gbits); - b = ((((v & vd->server->pf.bmask) >> vd->server->pf.bshift) << vs->clientds.pf.bbits) >> - vd->server->pf.bbits); - v = (r << vs->clientds.pf.rshift) | - (g << vs->clientds.pf.gshift) | - (b << vs->clientds.pf.bshift); - switch(vs->clientds.pf.bytes_per_pixel) { +#if VNC_SERVER_FB_FORMAT == PIXMAN_FORMAT(32, PIXMAN_TYPE_ARGB, 0, 8, 8, 8) + r = (((v & 0x00ff0000) >> 16) << vs->client_pf.rbits) >> 8; + g = (((v & 0x0000ff00) >> 8) << vs->client_pf.gbits) >> 8; + b = (((v & 0x000000ff) >> 0) << vs->client_pf.bbits) >> 8; +#else +# error need some bits here if you change VNC_SERVER_FB_FORMAT +#endif + v = (r << vs->client_pf.rshift) | + (g << vs->client_pf.gshift) | + (b << vs->client_pf.bshift); + switch (vs->client_pf.bytes_per_pixel) { case 1: buf[0] = v; break; case 2: - if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) { + if (vs->client_be) { buf[0] = v >> 8; buf[1] = v; } else { @@ -621,7 +638,7 @@ void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v) break; default: case 4: - if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) { + if (vs->client_be) { buf[0] = v >> 24; buf[1] = v >> 16; buf[2] = v >> 8; @@ -636,37 +653,37 @@ void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v) } } -static void vnc_write_pixels_generic(VncState *vs, struct PixelFormat *pf, +static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size) { uint8_t buf[4]; - if (pf->bytes_per_pixel == 4) { + if (VNC_SERVER_FB_BYTES == 4) { uint32_t *pixels = pixels1; int n, i; n = size >> 2; - for(i = 0; i < n; i++) { + for (i = 0; i < n; i++) { vnc_convert_pixel(vs, buf, pixels[i]); - vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel); + vnc_write(vs, buf, vs->client_pf.bytes_per_pixel); } - } else if (pf->bytes_per_pixel == 2) { + } else if (VNC_SERVER_FB_BYTES == 2) { uint16_t *pixels = pixels1; int n, i; n = size >> 1; - for(i = 0; i < n; i++) { + for (i = 0; i < n; i++) { vnc_convert_pixel(vs, buf, pixels[i]); - vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel); + vnc_write(vs, buf, vs->client_pf.bytes_per_pixel); } - } else if (pf->bytes_per_pixel == 1) { + } else if (VNC_SERVER_FB_BYTES == 1) { uint8_t *pixels = pixels1; int n, i; n = size; - for(i = 0; i < n; i++) { + for (i = 0; i < n; i++) { vnc_convert_pixel(vs, buf, pixels[i]); - vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel); + vnc_write(vs, buf, vs->client_pf.bytes_per_pixel); } } else { - fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n"); + fprintf(stderr, "%s: VncState color depth not supported\n", __func__); } } @@ -676,10 +693,10 @@ int vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) uint8_t *row; VncDisplay *vd = vs->vd; - row = vd->server->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds); + row = vnc_server_fb_ptr(vd, x, y); for (i = 0; i < h; i++) { - vs->write_pixels(vs, &vd->server->pf, row, w * ds_get_bytes_per_pixel(vs->ds)); - row += ds_get_linesize(vs->ds); + vs->write_pixels(vs, row, w * VNC_SERVER_FB_BYTES); + row += vnc_server_fb_stride(vd); } return 1; } @@ -736,7 +753,7 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int VncState *vs, *vn; uint8_t *src_row; uint8_t *dst_row; - int i,x,y,pitch,depth,inc,w_lim,s; + int i, x, y, pitch, inc, w_lim, s; int cmp_bytes; vnc_refresh_server_surface(vd); @@ -749,10 +766,9 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int } /* do bitblit op on the local surface too */ - pitch = ds_get_linesize(vd->ds); - depth = ds_get_bytes_per_pixel(vd->ds); - src_row = vd->server->data + pitch * src_y + depth * src_x; - dst_row = vd->server->data + pitch * dst_y + depth * dst_x; + pitch = vnc_server_fb_stride(vd); + src_row = vnc_server_fb_ptr(vd, src_x, src_y); + dst_row = vnc_server_fb_ptr(vd, dst_x, dst_y); y = dst_y; inc = 1; if (dst_y > src_y) { @@ -780,7 +796,7 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int } else { s = 16; } - cmp_bytes = s * depth; + cmp_bytes = s * VNC_SERVER_FB_BYTES; if (memcmp(src_row, dst_row, cmp_bytes) == 0) continue; memmove(dst_row, src_row, cmp_bytes); @@ -790,8 +806,8 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int } } } - src_row += pitch - w * depth; - dst_row += pitch - w * depth; + src_row += pitch - w * VNC_SERVER_FB_BYTES; + dst_row += pitch - w * VNC_SERVER_FB_BYTES; y += inc; } @@ -810,7 +826,6 @@ static void vnc_mouse_set(DisplayState *ds, int x, int y, int visible) static int vnc_cursor_define(VncState *vs) { QEMUCursor *c = vs->vd->cursor; - PixelFormat pf = qemu_default_pixelformat(32); int isize; if (vnc_has_feature(vs, VNC_FEATURE_RICH_CURSOR)) { @@ -820,8 +835,8 @@ static int vnc_cursor_define(VncState *vs) vnc_write_u16(vs, 1); /* # of rects */ vnc_framebuffer_update(vs, c->hot_x, c->hot_y, c->width, c->height, VNC_ENCODING_RICH_CURSOR); - isize = c->width * c->height * vs->clientds.pf.bytes_per_pixel; - vnc_write_pixels_generic(vs, &pf, c->data, isize); + isize = c->width * c->height * vs->client_pf.bytes_per_pixel; + vnc_write_pixels_generic(vs, c->data, isize); vnc_write(vs, vs->vd->cursor_mask, vs->vd->cursor_msize); vnc_unlock_output(vs); return 0; @@ -898,8 +913,8 @@ static int vnc_update_client(VncState *vs, int has_dirty) */ job = vnc_job_new(vs); - width = MIN(vd->server->width, vs->client_width); - height = MIN(vd->server->height, vs->client_height); + width = MIN(pixman_image_get_width(vd->server), vs->client_width); + height = MIN(pixman_image_get_height(vd->server), vs->client_height); for (y = 0; y < height; y++) { int x; @@ -1861,9 +1876,9 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) static void set_pixel_conversion(VncState *vs) { - if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) == - (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) && - !memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) { + pixman_format_code_t fmt = qemu_pixman_get_format(&vs->client_pf); + + if (fmt == VNC_SERVER_FB_FORMAT) { vs->write_pixels = vnc_write_pixels_copy; vnc_hextile_set_pixel_conversion(vs, 0); } else { @@ -1883,23 +1898,22 @@ static void set_pixel_format(VncState *vs, return; } - vs->clientds = *(vs->vd->guest.ds); - vs->clientds.pf.rmax = red_max; - vs->clientds.pf.rbits = hweight_long(red_max); - vs->clientds.pf.rshift = red_shift; - vs->clientds.pf.rmask = red_max << red_shift; - vs->clientds.pf.gmax = green_max; - vs->clientds.pf.gbits = hweight_long(green_max); - vs->clientds.pf.gshift = green_shift; - vs->clientds.pf.gmask = green_max << green_shift; - vs->clientds.pf.bmax = blue_max; - vs->clientds.pf.bbits = hweight_long(blue_max); - vs->clientds.pf.bshift = blue_shift; - vs->clientds.pf.bmask = blue_max << blue_shift; - vs->clientds.pf.bits_per_pixel = bits_per_pixel; - vs->clientds.pf.bytes_per_pixel = bits_per_pixel / 8; - vs->clientds.pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel; - vs->clientds.flags = big_endian_flag ? QEMU_BIG_ENDIAN_FLAG : 0x00; + vs->client_pf.rmax = red_max; + vs->client_pf.rbits = hweight_long(red_max); + vs->client_pf.rshift = red_shift; + vs->client_pf.rmask = red_max << red_shift; + vs->client_pf.gmax = green_max; + vs->client_pf.gbits = hweight_long(green_max); + vs->client_pf.gshift = green_shift; + vs->client_pf.gmask = green_max << green_shift; + vs->client_pf.bmax = blue_max; + vs->client_pf.bbits = hweight_long(blue_max); + vs->client_pf.bshift = blue_shift; + vs->client_pf.bmask = blue_max << blue_shift; + vs->client_pf.bits_per_pixel = bits_per_pixel; + vs->client_pf.bytes_per_pixel = bits_per_pixel / 8; + vs->client_pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel; + vs->client_be = big_endian_flag; set_pixel_conversion(vs); @@ -1910,8 +1924,10 @@ static void set_pixel_format(VncState *vs, static void pixel_format_message (VncState *vs) { char pad[3] = { 0, 0, 0 }; - vnc_write_u8(vs, vs->ds->surface->pf.bits_per_pixel); /* bits-per-pixel */ - vnc_write_u8(vs, vs->ds->surface->pf.depth); /* depth */ + vs->client_pf = qemu_default_pixelformat(32); + + vnc_write_u8(vs, vs->client_pf.bits_per_pixel); /* bits-per-pixel */ + vnc_write_u8(vs, vs->client_pf.depth); /* depth */ #ifdef HOST_WORDS_BIGENDIAN vnc_write_u8(vs, 1); /* big-endian-flag */ @@ -1919,27 +1935,25 @@ static void pixel_format_message (VncState *vs) { vnc_write_u8(vs, 0); /* big-endian-flag */ #endif vnc_write_u8(vs, 1); /* true-color-flag */ - vnc_write_u16(vs, vs->ds->surface->pf.rmax); /* red-max */ - vnc_write_u16(vs, vs->ds->surface->pf.gmax); /* green-max */ - vnc_write_u16(vs, vs->ds->surface->pf.bmax); /* blue-max */ - vnc_write_u8(vs, vs->ds->surface->pf.rshift); /* red-shift */ - vnc_write_u8(vs, vs->ds->surface->pf.gshift); /* green-shift */ - vnc_write_u8(vs, vs->ds->surface->pf.bshift); /* blue-shift */ + vnc_write_u16(vs, vs->client_pf.rmax); /* red-max */ + vnc_write_u16(vs, vs->client_pf.gmax); /* green-max */ + vnc_write_u16(vs, vs->client_pf.bmax); /* blue-max */ + vnc_write_u8(vs, vs->client_pf.rshift); /* red-shift */ + vnc_write_u8(vs, vs->client_pf.gshift); /* green-shift */ + vnc_write_u8(vs, vs->client_pf.bshift); /* blue-shift */ + vnc_write(vs, pad, 3); /* padding */ vnc_hextile_set_pixel_conversion(vs, 0); - - vs->clientds = *(vs->ds->surface); - vs->clientds.flags &= ~QEMU_ALLOCATED_FLAG; vs->write_pixels = vnc_write_pixels_copy; - - vnc_write(vs, pad, 3); /* padding */ } static void vnc_dpy_setdata(DisplayState *ds) { VncDisplay *vd = ds->opaque; - *(vd->guest.ds) = *(ds->surface); + qemu_pixman_image_unref(vd->guest.fb); + vd->guest.fb = pixman_image_ref(ds->surface->image); + vd->guest.format = ds->surface->format; vnc_dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds)); } @@ -2443,12 +2457,14 @@ static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y) static int vnc_update_stats(VncDisplay *vd, struct timeval * tv) { + int width = pixman_image_get_width(vd->guest.fb); + int height = pixman_image_get_height(vd->guest.fb); int x, y; struct timeval res; int has_dirty = 0; - for (y = 0; y < vd->guest.ds->height; y += VNC_STAT_RECT) { - for (x = 0; x < vd->guest.ds->width; x += VNC_STAT_RECT) { + for (y = 0; y < height; y += VNC_STAT_RECT) { + for (x = 0; x < width; x += VNC_STAT_RECT) { VncRectStat *rect = vnc_stat_rect(vd, x, y); rect->updated = false; @@ -2462,8 +2478,8 @@ static int vnc_update_stats(VncDisplay *vd, struct timeval * tv) } vd->guest.last_freq_check = *tv; - for (y = 0; y < vd->guest.ds->height; y += VNC_STAT_RECT) { - for (x = 0; x < vd->guest.ds->width; x += VNC_STAT_RECT) { + for (y = 0; y < height; y += VNC_STAT_RECT) { + for (x = 0; x < width; x += VNC_STAT_RECT) { VncRectStat *rect= vnc_stat_rect(vd, x, y); int count = ARRAY_SIZE(rect->times); struct timeval min, max; @@ -2532,12 +2548,15 @@ static void vnc_rect_updated(VncDisplay *vd, int x, int y, struct timeval * tv) static int vnc_refresh_server_surface(VncDisplay *vd) { + int width = pixman_image_get_width(vd->guest.fb); + int height = pixman_image_get_height(vd->guest.fb); int y; uint8_t *guest_row; uint8_t *server_row; int cmp_bytes; VncState *vs; int has_dirty = 0; + pixman_image_t *tmpbuf = NULL; struct timeval tv = { 0, 0 }; @@ -2551,22 +2570,31 @@ static int vnc_refresh_server_surface(VncDisplay *vd) * Check and copy modified bits from guest to server surface. * Update server dirty map. */ - cmp_bytes = 16 * ds_get_bytes_per_pixel(vd->ds); - if (cmp_bytes > vd->ds->surface->linesize) { - cmp_bytes = vd->ds->surface->linesize; + cmp_bytes = 64; + if (cmp_bytes > vnc_server_fb_stride(vd)) { + cmp_bytes = vnc_server_fb_stride(vd); } - guest_row = vd->guest.ds->data; - server_row = vd->server->data; - for (y = 0; y < vd->guest.ds->height; y++) { + if (vd->guest.format != VNC_SERVER_FB_FORMAT) { + int width = pixman_image_get_width(vd->server); + tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, width); + } + guest_row = (uint8_t *)pixman_image_get_data(vd->guest.fb); + server_row = (uint8_t *)pixman_image_get_data(vd->server); + for (y = 0; y < height; y++) { if (!bitmap_empty(vd->guest.dirty[y], VNC_DIRTY_BITS)) { int x; uint8_t *guest_ptr; uint8_t *server_ptr; - guest_ptr = guest_row; + if (vd->guest.format != VNC_SERVER_FB_FORMAT) { + qemu_pixman_linebuf_fill(tmpbuf, vd->guest.fb, width, y); + guest_ptr = (uint8_t *)pixman_image_get_data(tmpbuf); + } else { + guest_ptr = guest_row; + } server_ptr = server_row; - for (x = 0; x + 15 < vd->guest.ds->width; + for (x = 0; x + 15 < width; x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) { if (!test_and_clear_bit((x / 16), vd->guest.dirty[y])) continue; @@ -2581,9 +2609,10 @@ static int vnc_refresh_server_surface(VncDisplay *vd) has_dirty++; } } - guest_row += ds_get_linesize(vd->ds); - server_row += ds_get_linesize(vd->ds); + guest_row += pixman_image_get_stride(vd->guest.fb); + server_row += pixman_image_get_stride(vd->server); } + qemu_pixman_image_unref(tmpbuf); return has_dirty; } diff --git a/ui/vnc.h b/ui/vnc.h index 068c2fcda5..d003afbbfd 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -69,7 +69,7 @@ typedef struct VncRectEntry VncRectEntry; typedef int VncReadEvent(VncState *vs, uint8_t *data, size_t len); -typedef void VncWritePixels(VncState *vs, struct PixelFormat *pf, void *data, int size); +typedef void VncWritePixels(VncState *vs, void *data, int size); typedef void VncSendHextileTile(VncState *vs, int x, int y, int w, int h, @@ -117,7 +117,8 @@ struct VncSurface struct timeval last_freq_check; DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT], VNC_MAX_WIDTH / 16); VncRectStat stats[VNC_STAT_ROWS][VNC_STAT_COLS]; - DisplaySurface *ds; + pixman_image_t *fb; + pixman_format_code_t format; }; typedef enum VncShareMode { @@ -151,7 +152,7 @@ struct VncDisplay uint8_t *cursor_mask; struct VncSurface guest; /* guest visible surface (aka ds->surface) */ - DisplaySurface *server; /* vnc server surface */ + pixman_image_t *server; /* vnc server surface */ char *display; char *password; @@ -275,7 +276,9 @@ struct VncState Buffer input; /* current output mode information */ VncWritePixels *write_pixels; - DisplaySurface clientds; + PixelFormat client_pf; + pixman_format_code_t client_format; + bool client_be; CaptureVoiceOut *audio_cap; struct audsettings as; @@ -527,6 +530,14 @@ static inline uint32_t vnc_has_feature(VncState *vs, int feature) { void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h, int32_t encoding); +/* server fb is in PIXMAN_x8r8g8b8 */ +#define VNC_SERVER_FB_FORMAT PIXMAN_FORMAT(32, PIXMAN_TYPE_ARGB, 0, 8, 8, 8) +#define VNC_SERVER_FB_BITS (PIXMAN_FORMAT_BPP(VNC_SERVER_FB_FORMAT)) +#define VNC_SERVER_FB_BYTES ((VNC_SERVER_FB_BITS+7)/8) + +void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y); +int vnc_server_fb_stride(VncDisplay *vd); + void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v); double vnc_update_freq(VncState *vs, int x, int y, int w, int h); void vnc_sent_lossy_rect(VncState *vs, int x, int y, int w, int h); From 47683d669f993308c2b84bed4ce64aafb5d7ced4 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 11 Oct 2012 12:04:33 +0200 Subject: [PATCH 1474/2270] pixman/vnc: remove rgb_prepare_row* functions Let pixman do it instead. Signed-off-by: Gerd Hoffmann --- ui/vnc-enc-tight.c | 84 ++++++---------------------------------------- 1 file changed, 10 insertions(+), 74 deletions(-) diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c index 8013c5c6dd..9fd255650e 100644 --- a/ui/vnc-enc-tight.c +++ b/ui/vnc-enc-tight.c @@ -1145,74 +1145,6 @@ static int send_palette_rect(VncState *vs, int x, int y, return (bytes >= 0); } -#if defined(CONFIG_VNC_JPEG) || defined(CONFIG_VNC_PNG) -static void rgb_prepare_row24(VncState *vs, uint8_t *dst, int x, int y, - int count) -{ - VncDisplay *vd = vs->vd; - uint32_t *fbptr; - uint32_t pix; - - fbptr = vnc_server_fb_ptr(vd, x, y); - - while (count--) { - pix = *fbptr++; - *dst++ = (uint8_t)(pix >> vs->ds->surface->pf.rshift); - *dst++ = (uint8_t)(pix >> vs->ds->surface->pf.gshift); - *dst++ = (uint8_t)(pix >> vs->ds->surface->pf.bshift); - } -} - -#define DEFINE_RGB_GET_ROW_FUNCTION(bpp) \ - \ - static void \ - rgb_prepare_row##bpp(VncState *vs, uint8_t *dst, \ - int x, int y, int count) \ - { \ - VncDisplay *vd = vs->vd; \ - uint##bpp##_t *fbptr; \ - uint##bpp##_t pix; \ - int r, g, b; \ - \ - fbptr = vnc_server_fb_ptr(vd, x, y); \ - \ - while (count--) { \ - pix = *fbptr++; \ - \ - r = (int)((pix >> vs->ds->surface->pf.rshift) \ - & vs->ds->surface->pf.rmax); \ - g = (int)((pix >> vs->ds->surface->pf.gshift) \ - & vs->ds->surface->pf.gmax); \ - b = (int)((pix >> vs->ds->surface->pf.bshift) \ - & vs->ds->surface->pf.bmax); \ - \ - *dst++ = (uint8_t)((r * 255 + vs->ds->surface->pf.rmax / 2) \ - / vs->ds->surface->pf.rmax); \ - *dst++ = (uint8_t)((g * 255 + vs->ds->surface->pf.gmax / 2) \ - / vs->ds->surface->pf.gmax); \ - *dst++ = (uint8_t)((b * 255 + vs->ds->surface->pf.bmax / 2) \ - / vs->ds->surface->pf.bmax); \ - } \ - } - -DEFINE_RGB_GET_ROW_FUNCTION(16) -DEFINE_RGB_GET_ROW_FUNCTION(32) - -static void rgb_prepare_row(VncState *vs, uint8_t *dst, int x, int y, - int count) -{ - if (VNC_SERVER_FB_BYTES == 4) { - if (1) { - rgb_prepare_row24(vs, dst, x, y, count); - } else { - rgb_prepare_row32(vs, dst, x, y, count); - } - } else { - rgb_prepare_row16(vs, dst, x, y, count); - } -} -#endif /* CONFIG_VNC_JPEG or CONFIG_VNC_PNG */ - /* * JPEG compression stuff. */ @@ -1257,6 +1189,7 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality) struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; struct jpeg_destination_mgr manager; + pixman_image_t *linebuf; JSAMPROW row[1]; uint8_t *buf; int dy; @@ -1285,13 +1218,14 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality) jpeg_start_compress(&cinfo, true); - buf = g_malloc(w * 3); + linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, w); + buf = (uint8_t *)pixman_image_get_data(linebuf); row[0] = buf; for (dy = 0; dy < h; dy++) { - rgb_prepare_row(vs, buf, x, y + dy, w); + qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, dy); jpeg_write_scanlines(&cinfo, row, 1); } - g_free(buf); + qemu_pixman_image_unref(linebuf); jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); @@ -1370,6 +1304,7 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h, png_structp png_ptr; png_infop info_ptr; png_colorp png_palette = NULL; + pixman_image_t *linebuf; int level = tight_png_conf[vs->tight.compression].png_zlib_level; int filters = tight_png_conf[vs->tight.compression].png_filters; uint8_t *buf; @@ -1424,17 +1359,18 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h, png_write_info(png_ptr, info_ptr); buffer_reserve(&vs->tight.png, 2048); - buf = g_malloc(w * 3); + linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, w); + buf = (uint8_t *)pixman_image_get_data(linebuf); for (dy = 0; dy < h; dy++) { if (color_type == PNG_COLOR_TYPE_PALETTE) { memcpy(buf, vs->tight.tight.buffer + (dy * w), w); } else { - rgb_prepare_row(vs, buf, x, y + dy, w); + qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, dy); } png_write_row(png_ptr, buf); } - g_free(buf); + qemu_pixman_image_unref(linebuf); png_write_end(png_ptr, NULL); From 94362682d31eb7c9bfd6bf74cd615d0616a09361 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 11 Oct 2012 12:11:27 +0200 Subject: [PATCH 1475/2270] pixman/vnc: remove dead code. Switching the vnc server framebuffer to use 32bpp unconditionally turns the code bits which handle 8 and 16 bpp into dead code. Remove them. Signed-off-by: Gerd Hoffmann --- ui/vnc-enc-hextile.c | 32 ---------------------- ui/vnc-enc-tight.c | 64 +++++++++++++++++++------------------------- ui/vnc.c | 18 ------------- 3 files changed, 27 insertions(+), 87 deletions(-) diff --git a/ui/vnc-enc-hextile.c b/ui/vnc-enc-hextile.c index 263a0ce9d2..2e768fd899 100644 --- a/ui/vnc-enc-hextile.c +++ b/ui/vnc-enc-hextile.c @@ -32,30 +32,10 @@ static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h) ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F); } -#define BPP 8 -#include "vnc-enc-hextile-template.h" -#undef BPP - -#define BPP 16 -#include "vnc-enc-hextile-template.h" -#undef BPP - #define BPP 32 #include "vnc-enc-hextile-template.h" #undef BPP -#define GENERIC -#define BPP 8 -#include "vnc-enc-hextile-template.h" -#undef BPP -#undef GENERIC - -#define GENERIC -#define BPP 16 -#include "vnc-enc-hextile-template.h" -#undef BPP -#undef GENERIC - #define GENERIC #define BPP 32 #include "vnc-enc-hextile-template.h" @@ -89,24 +69,12 @@ void vnc_hextile_set_pixel_conversion(VncState *vs, int generic) { if (!generic) { switch (VNC_SERVER_FB_BITS) { - case 8: - vs->hextile.send_tile = send_hextile_tile_8; - break; - case 16: - vs->hextile.send_tile = send_hextile_tile_16; - break; case 32: vs->hextile.send_tile = send_hextile_tile_32; break; } } else { switch (VNC_SERVER_FB_BITS) { - case 8: - vs->hextile.send_tile = send_hextile_tile_generic_8; - break; - case 16: - vs->hextile.send_tile = send_hextile_tile_generic_16; - break; case 32: vs->hextile.send_tile = send_hextile_tile_generic_32; break; diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c index 9fd255650e..9ae4cabffc 100644 --- a/ui/vnc-enc-tight.c +++ b/ui/vnc-enc-tight.c @@ -671,41 +671,35 @@ DEFINE_GRADIENT_FILTER_FUNCTION(32) * that case new color will be stored in *colorPtr. */ -#define DEFINE_CHECK_SOLID_FUNCTION(bpp) \ - \ - static bool \ - check_solid_tile##bpp(VncState *vs, int x, int y, int w, int h, \ - uint32_t* color, bool samecolor) \ - { \ - VncDisplay *vd = vs->vd; \ - uint##bpp##_t *fbptr; \ - uint##bpp##_t c; \ - int dx, dy; \ - \ - fbptr = vnc_server_fb_ptr(vd, x, y); \ - \ - c = *fbptr; \ - if (samecolor && (uint32_t)c != *color) { \ - return false; \ - } \ - \ - for (dy = 0; dy < h; dy++) { \ - for (dx = 0; dx < w; dx++) { \ - if (c != fbptr[dx]) { \ - return false; \ - } \ - } \ - fbptr = (uint##bpp##_t *) \ - ((uint8_t *)fbptr + vnc_server_fb_stride(vd)); \ - } \ - \ - *color = (uint32_t)c; \ - return true; \ +static bool +check_solid_tile32(VncState *vs, int x, int y, int w, int h, + uint32_t *color, bool samecolor) +{ + VncDisplay *vd = vs->vd; + uint32_t *fbptr; + uint32_t c; + int dx, dy; + + fbptr = vnc_server_fb_ptr(vd, x, y); + + c = *fbptr; + if (samecolor && (uint32_t)c != *color) { + return false; } -DEFINE_CHECK_SOLID_FUNCTION(32) -DEFINE_CHECK_SOLID_FUNCTION(16) -DEFINE_CHECK_SOLID_FUNCTION(8) + for (dy = 0; dy < h; dy++) { + for (dx = 0; dx < w; dx++) { + if (c != fbptr[dx]) { + return false; + } + } + fbptr = (uint32_t *) + ((uint8_t *)fbptr + vnc_server_fb_stride(vd)); + } + + *color = (uint32_t)c; + return true; +} static bool check_solid_tile(VncState *vs, int x, int y, int w, int h, uint32_t* color, bool samecolor) @@ -713,10 +707,6 @@ static bool check_solid_tile(VncState *vs, int x, int y, int w, int h, switch (VNC_SERVER_FB_BYTES) { case 4: return check_solid_tile32(vs, x, y, w, h, color, samecolor); - case 2: - return check_solid_tile16(vs, x, y, w, h, color, samecolor); - default: - return check_solid_tile8(vs, x, y, w, h, color, samecolor); } } diff --git a/ui/vnc.c b/ui/vnc.c index 15aef86047..7c120e6f06 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -666,24 +666,6 @@ static void vnc_write_pixels_generic(VncState *vs, vnc_convert_pixel(vs, buf, pixels[i]); vnc_write(vs, buf, vs->client_pf.bytes_per_pixel); } - } else if (VNC_SERVER_FB_BYTES == 2) { - uint16_t *pixels = pixels1; - int n, i; - n = size >> 1; - for (i = 0; i < n; i++) { - vnc_convert_pixel(vs, buf, pixels[i]); - vnc_write(vs, buf, vs->client_pf.bytes_per_pixel); - } - } else if (VNC_SERVER_FB_BYTES == 1) { - uint8_t *pixels = pixels1; - int n, i; - n = size; - for (i = 0; i < n; i++) { - vnc_convert_pixel(vs, buf, pixels[i]); - vnc_write(vs, buf, vs->client_pf.bytes_per_pixel); - } - } else { - fprintf(stderr, "%s: VncState color depth not supported\n", __func__); } } From 64f735920ad319aee860e56bb9bad6cfccf4ad40 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 10 Oct 2012 11:15:52 +0200 Subject: [PATCH 1476/2270] pixman: drop obsolete fields from DisplaySurface Signed-off-by: Gerd Hoffmann --- console.c | 9 --------- console.h | 23 +++++++++++++---------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/console.c b/console.c index d28b75ec7d..048b48e721 100644 --- a/console.c +++ b/console.c @@ -1297,14 +1297,10 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type) static void qemu_alloc_display(DisplaySurface *surface, int width, int height, int linesize, PixelFormat pf, int newflags) { - surface->width = width; - surface->height = height; - surface->linesize = linesize; surface->pf = pf; qemu_pixman_image_unref(surface->image); surface->image = NULL; - surface->data = NULL; surface->format = qemu_pixman_get_format(&pf); assert(surface->format != 0); @@ -1313,7 +1309,6 @@ static void qemu_alloc_display(DisplaySurface *surface, int width, int height, NULL, linesize); assert(surface->image != NULL); - surface->data = (uint8_t *)pixman_image_get_data(surface->image); surface->flags = newflags | QEMU_ALLOCATED_FLAG; #ifdef HOST_WORDS_BIGENDIAN surface->flags |= QEMU_BIG_ENDIAN_FLAG; @@ -1347,9 +1342,6 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp, { DisplaySurface *surface = g_new0(DisplaySurface, 1); - surface->width = width; - surface->height = height; - surface->linesize = linesize; surface->pf = qemu_default_pixelformat(bpp); surface->format = qemu_pixman_get_format(&surface->pf); @@ -1362,7 +1354,6 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp, #ifdef HOST_WORDS_BIGENDIAN surface->flags = QEMU_BIG_ENDIAN_FLAG; #endif - surface->data = data; return surface; } diff --git a/console.h b/console.h index 21bd957d95..33ad69b48c 100644 --- a/console.h +++ b/console.h @@ -123,10 +123,6 @@ struct DisplaySurface { pixman_format_code_t format; pixman_image_t *image; uint8_t flags; - int width; - int height; - int linesize; /* bytes per line */ - uint8_t *data; struct PixelFormat pf; }; @@ -346,32 +342,39 @@ static inline bool dpy_cursor_define_supported(struct DisplayState *s) static inline int ds_get_linesize(DisplayState *ds) { - return ds->surface->linesize; + return pixman_image_get_stride(ds->surface->image); } static inline uint8_t* ds_get_data(DisplayState *ds) { - return ds->surface->data; + return (void *)pixman_image_get_data(ds->surface->image); } static inline int ds_get_width(DisplayState *ds) { - return ds->surface->width; + return pixman_image_get_width(ds->surface->image); } static inline int ds_get_height(DisplayState *ds) { - return ds->surface->height; + return pixman_image_get_height(ds->surface->image); } static inline int ds_get_bits_per_pixel(DisplayState *ds) { - return ds->surface->pf.bits_per_pixel; + int bits = PIXMAN_FORMAT_BPP(ds->surface->format); + return bits; } static inline int ds_get_bytes_per_pixel(DisplayState *ds) { - return ds->surface->pf.bytes_per_pixel; + int bits = PIXMAN_FORMAT_BPP(ds->surface->format); + return (bits + 7) / 8; +} + +static inline pixman_format_code_t ds_get_format(DisplayState *ds) +{ + return ds->surface->format; } #ifdef CONFIG_CURSES From 892776ce02e3915b8db9d85935ea144ee5a1a41a Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Mon, 29 Oct 2012 11:34:38 +1000 Subject: [PATCH 1477/2270] xilinx_zynq: add USB controllers Add the two usb controllers in Zynq. Signed-off-by: Peter Crosthwaite Signed-off-by: Gerd Hoffmann --- hw/xilinx_zynq.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c index 00262350b6..1f12a3d1ad 100644 --- a/hw/xilinx_zynq.c +++ b/hw/xilinx_zynq.c @@ -166,6 +166,9 @@ static void zynq_init(QEMUMachineInitArgs *args) zynq_init_spi_flashes(0xE0007000, pic[81-IRQ_OFFSET], false); zynq_init_spi_flashes(0xE000D000, pic[51-IRQ_OFFSET], true); + sysbus_create_simple("xlnx,ps7-usb", 0xE0002000, pic[53-IRQ_OFFSET]); + sysbus_create_simple("xlnx,ps7-usb", 0xE0003000, pic[75-IRQ_OFFSET]); + sysbus_create_simple("cadence_uart", 0xE0000000, pic[59-IRQ_OFFSET]); sysbus_create_simple("cadence_uart", 0xE0001000, pic[82-IRQ_OFFSET]); From 2c2e852509de3fecf606e8f2dcbca0ebd1eddc10 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 25 Oct 2012 16:22:57 +0200 Subject: [PATCH 1478/2270] uhci: dynamic type generation Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 194 +++++++++++++++++----------------------------- 1 file changed, 69 insertions(+), 125 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index b6b972fa92..925c738e7d 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -88,6 +88,16 @@ enum { typedef struct UHCIState UHCIState; typedef struct UHCIAsync UHCIAsync; typedef struct UHCIQueue UHCIQueue; +typedef struct UHCIInfo UHCIInfo; + +struct UHCIInfo { + const char *name; + uint16_t vendor_id; + uint16_t device_id; + uint8_t revision; + int (*initfn)(PCIDevice *dev); + bool unplug; +}; /* * Pending async transaction. @@ -1293,143 +1303,77 @@ static Property uhci_properties[] = { DEFINE_PROP_END_OF_LIST(), }; -static void piix3_uhci_class_init(ObjectClass *klass, void *data) +static void uhci_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + UHCIInfo *info = data; - k->init = usb_uhci_common_initfn; - k->exit = usb_uhci_exit; - k->vendor_id = PCI_VENDOR_ID_INTEL; - k->device_id = PCI_DEVICE_ID_INTEL_82371SB_2; - k->revision = 0x01; - k->class_id = PCI_CLASS_SERIAL_USB; + k->init = info->initfn ? info->initfn : usb_uhci_common_initfn; + k->exit = info->unplug ? usb_uhci_exit : NULL; + k->vendor_id = info->vendor_id; + k->device_id = info->device_id; + k->revision = info->revision; + k->class_id = PCI_CLASS_SERIAL_USB; dc->vmsd = &vmstate_uhci; dc->props = uhci_properties; } -static TypeInfo piix3_uhci_info = { - .name = "piix3-usb-uhci", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(UHCIState), - .class_init = piix3_uhci_class_init, -}; - -static void piix4_uhci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->init = usb_uhci_common_initfn; - k->exit = usb_uhci_exit; - k->vendor_id = PCI_VENDOR_ID_INTEL; - k->device_id = PCI_DEVICE_ID_INTEL_82371AB_2; - k->revision = 0x01; - k->class_id = PCI_CLASS_SERIAL_USB; - dc->vmsd = &vmstate_uhci; - dc->props = uhci_properties; -} - -static TypeInfo piix4_uhci_info = { - .name = "piix4-usb-uhci", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(UHCIState), - .class_init = piix4_uhci_class_init, -}; - -static void vt82c686b_uhci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->init = usb_uhci_vt82c686b_initfn; - k->exit = usb_uhci_exit; - k->vendor_id = PCI_VENDOR_ID_VIA; - k->device_id = PCI_DEVICE_ID_VIA_UHCI; - k->revision = 0x01; - k->class_id = PCI_CLASS_SERIAL_USB; - dc->vmsd = &vmstate_uhci; - dc->props = uhci_properties; -} - -static TypeInfo vt82c686b_uhci_info = { - .name = "vt82c686b-usb-uhci", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(UHCIState), - .class_init = vt82c686b_uhci_class_init, -}; - -static void ich9_uhci1_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->init = usb_uhci_common_initfn; - k->vendor_id = PCI_VENDOR_ID_INTEL; - k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI1; - k->revision = 0x03; - k->class_id = PCI_CLASS_SERIAL_USB; - dc->vmsd = &vmstate_uhci; - dc->props = uhci_properties; -} - -static TypeInfo ich9_uhci1_info = { - .name = "ich9-usb-uhci1", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(UHCIState), - .class_init = ich9_uhci1_class_init, -}; - -static void ich9_uhci2_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->init = usb_uhci_common_initfn; - k->vendor_id = PCI_VENDOR_ID_INTEL; - k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI2; - k->revision = 0x03; - k->class_id = PCI_CLASS_SERIAL_USB; - dc->vmsd = &vmstate_uhci; - dc->props = uhci_properties; -} - -static TypeInfo ich9_uhci2_info = { - .name = "ich9-usb-uhci2", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(UHCIState), - .class_init = ich9_uhci2_class_init, -}; - -static void ich9_uhci3_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->init = usb_uhci_common_initfn; - k->vendor_id = PCI_VENDOR_ID_INTEL; - k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI3; - k->revision = 0x03; - k->class_id = PCI_CLASS_SERIAL_USB; - dc->vmsd = &vmstate_uhci; - dc->props = uhci_properties; -} - -static TypeInfo ich9_uhci3_info = { - .name = "ich9-usb-uhci3", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(UHCIState), - .class_init = ich9_uhci3_class_init, +static UHCIInfo uhci_info[] = { + { + .name = "piix3-usb-uhci", + .vendor_id = PCI_VENDOR_ID_INTEL, + .device_id = PCI_DEVICE_ID_INTEL_82371SB_2, + .revision = 0x01, + .unplug = true, + },{ + .name = "piix4-usb-uhci", + .vendor_id = PCI_VENDOR_ID_INTEL, + .device_id = PCI_DEVICE_ID_INTEL_82371AB_2, + .revision = 0x01, + .unplug = true, + },{ + .name = "vt82c686b-usb-uhci", + .vendor_id = PCI_VENDOR_ID_VIA, + .device_id = PCI_DEVICE_ID_VIA_UHCI, + .revision = 0x01, + .initfn = usb_uhci_vt82c686b_initfn, + .unplug = true, + },{ + .name = "ich9-usb-uhci1", + .vendor_id = PCI_VENDOR_ID_INTEL, + .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI1, + .revision = 0x03, + .unplug = false, + },{ + .name = "ich9-usb-uhci2", + .vendor_id = PCI_VENDOR_ID_INTEL, + .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI2, + .revision = 0x03, + .unplug = false, + },{ + .name = "ich9-usb-uhci3", + .vendor_id = PCI_VENDOR_ID_INTEL, + .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI3, + .revision = 0x03, + .unplug = false, + } }; static void uhci_register_types(void) { - type_register_static(&piix3_uhci_info); - type_register_static(&piix4_uhci_info); - type_register_static(&vt82c686b_uhci_info); - type_register_static(&ich9_uhci1_info); - type_register_static(&ich9_uhci2_info); - type_register_static(&ich9_uhci3_info); + TypeInfo uhci_type_info = { + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(UHCIState), + .class_init = uhci_class_init, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(uhci_info); i++) { + uhci_type_info.name = uhci_info[i].name; + uhci_type_info.class_data = uhci_info + i; + type_register(&uhci_type_info); + } } type_init(uhci_register_types) From 8f3f90b0c7d095ba11b1ad558a0b7c2eeb36c8dc Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 26 Oct 2012 14:56:19 +0200 Subject: [PATCH 1479/2270] uhci: stick irq routing info into UHCIInfo too. Kills the ugly "switch (device_id) { ... }" struct and makes it easier to figure what the differences between the uhci variants are. Need our own DeviceClass struct for that so we can allocate some space to store UHCIInfo. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 925c738e7d..27046b65c8 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -89,16 +89,23 @@ typedef struct UHCIState UHCIState; typedef struct UHCIAsync UHCIAsync; typedef struct UHCIQueue UHCIQueue; typedef struct UHCIInfo UHCIInfo; +typedef struct UHCIPCIDeviceClass UHCIPCIDeviceClass; struct UHCIInfo { const char *name; uint16_t vendor_id; uint16_t device_id; uint8_t revision; + uint8_t irq_pin; int (*initfn)(PCIDevice *dev); bool unplug; }; +struct UHCIPCIDeviceClass { + PCIDeviceClass parent_class; + UHCIInfo info; +}; + /* * Pending async transaction. * 'packet' must be the first field because completion @@ -1218,6 +1225,7 @@ static USBBusOps uhci_bus_ops = { static int usb_uhci_common_initfn(PCIDevice *dev) { PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); + UHCIPCIDeviceClass *u = container_of(pc, UHCIPCIDeviceClass, parent_class); UHCIState *s = DO_UPCAST(UHCIState, dev, dev); uint8_t *pci_conf = s->dev.config; int i; @@ -1226,20 +1234,7 @@ static int usb_uhci_common_initfn(PCIDevice *dev) /* TODO: reset value should be 0. */ pci_conf[USB_SBRN] = USB_RELEASE_1; // release number - switch (pc->device_id) { - case PCI_DEVICE_ID_INTEL_82801I_UHCI1: - s->irq_pin = 0; /* A */ - break; - case PCI_DEVICE_ID_INTEL_82801I_UHCI2: - s->irq_pin = 1; /* B */ - break; - case PCI_DEVICE_ID_INTEL_82801I_UHCI3: - s->irq_pin = 2; /* C */ - break; - default: - s->irq_pin = 3; /* D */ - break; - } + s->irq_pin = u->info.irq_pin; pci_config_set_interrupt_pin(pci_conf, s->irq_pin + 1); if (s->masterbus) { @@ -1307,6 +1302,7 @@ static void uhci_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + UHCIPCIDeviceClass *u = container_of(k, UHCIPCIDeviceClass, parent_class); UHCIInfo *info = data; k->init = info->initfn ? info->initfn : usb_uhci_common_initfn; @@ -1317,6 +1313,7 @@ static void uhci_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_SERIAL_USB; dc->vmsd = &vmstate_uhci; dc->props = uhci_properties; + u->info = *info; } static UHCIInfo uhci_info[] = { @@ -1325,18 +1322,21 @@ static UHCIInfo uhci_info[] = { .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82371SB_2, .revision = 0x01, + .irq_pin = 3, .unplug = true, },{ .name = "piix4-usb-uhci", .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82371AB_2, .revision = 0x01, + .irq_pin = 3, .unplug = true, },{ .name = "vt82c686b-usb-uhci", .vendor_id = PCI_VENDOR_ID_VIA, .device_id = PCI_DEVICE_ID_VIA_UHCI, .revision = 0x01, + .irq_pin = 3, .initfn = usb_uhci_vt82c686b_initfn, .unplug = true, },{ @@ -1344,18 +1344,21 @@ static UHCIInfo uhci_info[] = { .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI1, .revision = 0x03, + .irq_pin = 0, .unplug = false, },{ .name = "ich9-usb-uhci2", .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI2, .revision = 0x03, + .irq_pin = 1, .unplug = false, },{ .name = "ich9-usb-uhci3", .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI3, .revision = 0x03, + .irq_pin = 2, .unplug = false, } }; @@ -1365,6 +1368,7 @@ static void uhci_register_types(void) TypeInfo uhci_type_info = { .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(UHCIState), + .class_size = sizeof(UHCIPCIDeviceClass), .class_init = uhci_class_init, }; int i; From 74625ea27c39df7047ebefb11c4a04c3a3513f16 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 30 Oct 2012 09:57:28 +0100 Subject: [PATCH 1480/2270] uhci: add ich9 00:1a.* variants Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 27046b65c8..71263fe143 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -1340,26 +1340,47 @@ static UHCIInfo uhci_info[] = { .initfn = usb_uhci_vt82c686b_initfn, .unplug = true, },{ - .name = "ich9-usb-uhci1", + .name = "ich9-usb-uhci1", /* 00:1d.0 */ .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI1, .revision = 0x03, .irq_pin = 0, .unplug = false, },{ - .name = "ich9-usb-uhci2", + .name = "ich9-usb-uhci2", /* 00:1d.1 */ .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI2, .revision = 0x03, .irq_pin = 1, .unplug = false, },{ - .name = "ich9-usb-uhci3", + .name = "ich9-usb-uhci3", /* 00:1d.2 */ .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI3, .revision = 0x03, .irq_pin = 2, .unplug = false, + },{ + .name = "ich9-usb-uhci4", /* 00:1a.0 */ + .vendor_id = PCI_VENDOR_ID_INTEL, + .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI4, + .revision = 0x03, + .irq_pin = 0, + .unplug = false, + },{ + .name = "ich9-usb-uhci5", /* 00:1a.1 */ + .vendor_id = PCI_VENDOR_ID_INTEL, + .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI5, + .revision = 0x03, + .irq_pin = 1, + .unplug = false, + },{ + .name = "ich9-usb-uhci6", /* 00:1a.2 */ + .vendor_id = PCI_VENDOR_ID_INTEL, + .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI6, + .revision = 0x03, + .irq_pin = 2, + .unplug = false, } }; From df013187777efc62faeea979cfec2ca4470cc34b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 30 Oct 2012 12:53:17 +0100 Subject: [PATCH 1481/2270] usb/ehci-pci: dynamic type generation Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci-pci.c | 66 +++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c index daac41d7f8..df137cccc9 100644 --- a/hw/usb/hcd-ehci-pci.c +++ b/hw/usb/hcd-ehci-pci.c @@ -23,6 +23,13 @@ typedef struct EHCIPCIState { EHCIState ehci; } EHCIPCIState; +typedef struct EHCIPCIInfo { + const char *name; + uint16_t vendor_id; + uint16_t device_id; + uint8_t revision; +} EHCIPCIInfo; + static int usb_ehci_pci_initfn(PCIDevice *dev) { EHCIPCIState *i = DO_UPCAST(EHCIPCIState, pcidev, dev); @@ -91,48 +98,45 @@ static void ehci_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + EHCIPCIInfo *i = data; k->init = usb_ehci_pci_initfn; - k->vendor_id = PCI_VENDOR_ID_INTEL; - k->device_id = PCI_DEVICE_ID_INTEL_82801D; /* ich4 */ - k->revision = 0x10; + k->vendor_id = i->vendor_id; + k->device_id = i->device_id; + k->revision = i->revision; k->class_id = PCI_CLASS_SERIAL_USB; dc->vmsd = &vmstate_ehci; dc->props = ehci_pci_properties; } -static TypeInfo ehci_info = { - .name = "usb-ehci", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(EHCIState), - .class_init = ehci_class_init, -}; - -static void ich9_ehci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->init = usb_ehci_pci_initfn; - k->vendor_id = PCI_VENDOR_ID_INTEL; - k->device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1; - k->revision = 0x03; - k->class_id = PCI_CLASS_SERIAL_USB; - dc->vmsd = &vmstate_ehci; - dc->props = ehci_pci_properties; -} - -static TypeInfo ich9_ehci_info = { - .name = "ich9-usb-ehci1", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(EHCIState), - .class_init = ich9_ehci_class_init, +static struct EHCIPCIInfo ehci_pci_info[] = { + { + .name = "usb-ehci", + .vendor_id = PCI_VENDOR_ID_INTEL, + .device_id = PCI_DEVICE_ID_INTEL_82801D, /* ich4 */ + .revision = 0x10, + },{ + .name = "ich9-usb-ehci1", + .vendor_id = PCI_VENDOR_ID_INTEL, + .device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1, + .revision = 0x03, + } }; static void ehci_pci_register_types(void) { - type_register_static(&ehci_info); - type_register_static(&ich9_ehci_info); + TypeInfo ehci_type_info = { + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(EHCIPCIState), + .class_init = ehci_class_init, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(ehci_pci_info); i++) { + ehci_type_info.name = ehci_pci_info[i].name; + ehci_type_info.class_data = ehci_pci_info + i; + type_register(&ehci_type_info); + } } type_init(ehci_pci_register_types) From ba07630c79807147786d3fd033e2762ae84eb132 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 30 Oct 2012 13:17:46 +0100 Subject: [PATCH 1482/2270] usb/ehci-pci: add ich9 00:1a.* variant Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci-pci.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c index df137cccc9..79bc276a44 100644 --- a/hw/usb/hcd-ehci-pci.c +++ b/hw/usb/hcd-ehci-pci.c @@ -116,10 +116,15 @@ static struct EHCIPCIInfo ehci_pci_info[] = { .device_id = PCI_DEVICE_ID_INTEL_82801D, /* ich4 */ .revision = 0x10, },{ - .name = "ich9-usb-ehci1", + .name = "ich9-usb-ehci1", /* 00:1d.7 */ .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1, .revision = 0x03, + },{ + .name = "ich9-usb-ehci2", /* 00:1a.7 */ + .vendor_id = PCI_VENDOR_ID_INTEL, + .device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI2, + .revision = 0x03, } }; From bb4d2b2f0aad4a940db86eb469de0bf91c1c6837 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 30 Oct 2012 13:18:36 +0100 Subject: [PATCH 1483/2270] usb/ehci-pci: add helper to create ich9 usb controllers Signed-off-by: Gerd Hoffmann --- hw/usb.h | 2 ++ hw/usb/hcd-ehci-pci.c | 53 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/hw/usb.h b/hw/usb.h index 3a6cc8444a..1837bf780f 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -524,5 +524,7 @@ const char *usb_device_get_product_desc(USBDevice *dev); const USBDesc *usb_device_get_usb_desc(USBDevice *dev); +int ehci_create_ich9_with_companions(PCIBus *bus, int slot); + #endif diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c index 79bc276a44..d5c7d462d0 100644 --- a/hw/usb/hcd-ehci-pci.c +++ b/hw/usb/hcd-ehci-pci.c @@ -145,3 +145,56 @@ static void ehci_pci_register_types(void) } type_init(ehci_pci_register_types) + +struct ehci_companions { + const char *name; + int func; + int port; +}; + +static const struct ehci_companions ich9_1d[] = { + { .name = "ich9-usb-uhci1", .func = 0, .port = 0 }, + { .name = "ich9-usb-uhci2", .func = 1, .port = 2 }, + { .name = "ich9-usb-uhci3", .func = 2, .port = 4 }, +}; + +static const struct ehci_companions ich9_1a[] = { + { .name = "ich9-usb-uhci4", .func = 0, .port = 0 }, + { .name = "ich9-usb-uhci5", .func = 1, .port = 2 }, + { .name = "ich9-usb-uhci6", .func = 2, .port = 4 }, +}; + +int ehci_create_ich9_with_companions(PCIBus *bus, int slot) +{ + const struct ehci_companions *comp; + PCIDevice *ehci, *uhci; + BusState *usbbus; + const char *name; + int i; + + switch (slot) { + case 0x1d: + name = "ich9-usb-ehci1"; + comp = ich9_1d; + break; + case 0x1a: + name = "ich9-usb-ehci2"; + comp = ich9_1a; + break; + default: + return -1; + } + + ehci = pci_create_multifunction(bus, PCI_DEVFN(slot, 7), true, name); + qdev_init_nofail(&ehci->qdev); + usbbus = QLIST_FIRST(&ehci->qdev.child_bus); + + for (i = 0; i < 3; i++) { + uhci = pci_create_multifunction(bus, PCI_DEVFN(slot, comp[i].func), + true, comp[i].name); + qdev_prop_set_string(&uhci->qdev, "masterbus", usbbus->name); + qdev_prop_set_uint32(&uhci->qdev, "firstport", comp[i].port); + qdev_init_nofail(&uhci->qdev); + } + return 0; +} From faccca000f27bb63fce0c71dc4ca68be1c23a8b0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 31 Oct 2012 12:54:36 +0100 Subject: [PATCH 1484/2270] uhci: Add a uhci_handle_td_error() helper function Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 90 +++++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 71263fe143..a06372b461 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -735,9 +735,52 @@ static void uhci_read_td(UHCIState *s, UHCI_TD *td, uint32_t link) le32_to_cpus(&td->buffer); } +static int uhci_handle_td_error(UHCIState *s, UHCI_TD *td, uint32_t td_addr, + int status, uint32_t *int_mask) +{ + uint32_t queue_token = uhci_queue_token(td); + int ret; + + switch (status) { + case USB_RET_NAK: + td->ctrl |= TD_CTRL_NAK; + return TD_RESULT_NEXT_QH; + + case USB_RET_STALL: + td->ctrl |= TD_CTRL_STALL; + trace_usb_uhci_packet_complete_stall(queue_token, td_addr); + ret = TD_RESULT_NEXT_QH; + break; + + case USB_RET_BABBLE: + td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL; + /* frame interrupted */ + trace_usb_uhci_packet_complete_babble(queue_token, td_addr); + ret = TD_RESULT_STOP_FRAME; + break; + + case USB_RET_IOERROR: + case USB_RET_NODEV: + default: + td->ctrl |= TD_CTRL_TIMEOUT; + td->ctrl &= ~(3 << TD_CTRL_ERROR_SHIFT); + trace_usb_uhci_packet_complete_error(queue_token, td_addr); + ret = TD_RESULT_NEXT_QH; + break; + } + + td->ctrl &= ~TD_CTRL_ACTIVE; + s->status |= UHCI_STS_USBERR; + if (td->ctrl & TD_CTRL_IOC) { + *int_mask |= 0x01; + } + uhci_update_irq(s); + return ret; +} + static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_t *int_mask) { - int len = 0, max_len, err, ret; + int len = 0, max_len, ret; uint8_t pid; max_len = ((td->token >> 21) + 1) & 0x7ff; @@ -748,8 +791,9 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_ if (td->ctrl & TD_CTRL_IOS) td->ctrl &= ~TD_CTRL_ACTIVE; - if (ret < 0) - goto out; + if (ret < 0) { + return uhci_handle_td_error(s, td, async->td_addr, ret, int_mask); + } len = async->packet.result; td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff); @@ -775,46 +819,6 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_ trace_usb_uhci_packet_complete_success(async->queue->token, async->td_addr); return TD_RESULT_COMPLETE; - -out: - switch(ret) { - case USB_RET_NAK: - td->ctrl |= TD_CTRL_NAK; - return TD_RESULT_NEXT_QH; - - case USB_RET_STALL: - td->ctrl |= TD_CTRL_STALL; - trace_usb_uhci_packet_complete_stall(async->queue->token, - async->td_addr); - err = TD_RESULT_NEXT_QH; - break; - - case USB_RET_BABBLE: - td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL; - /* frame interrupted */ - trace_usb_uhci_packet_complete_babble(async->queue->token, - async->td_addr); - err = TD_RESULT_STOP_FRAME; - break; - - case USB_RET_IOERROR: - case USB_RET_NODEV: - default: - td->ctrl |= TD_CTRL_TIMEOUT; - td->ctrl &= ~(3 << TD_CTRL_ERROR_SHIFT); - trace_usb_uhci_packet_complete_error(async->queue->token, - async->td_addr); - err = TD_RESULT_NEXT_QH; - break; - } - - td->ctrl &= ~TD_CTRL_ACTIVE; - s->status |= UHCI_STS_USBERR; - if (td->ctrl & TD_CTRL_IOC) { - *int_mask |= 0x01; - } - uhci_update_irq(s); - return err; } static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr, From 7f102ebeb5bad7b723a25557234b0feb493f6134 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 31 Oct 2012 12:54:37 +0100 Subject: [PATCH 1485/2270] uhci: Don't crash on device disconnect My recent uhci cleanup series has introduced a regression, where qemu sometimes crashes on a device disconnect. The problem is that the uhci code never checked for a device not / no longer existing, instead it was relying on usb_handle_packet accepting a NULL device. But since we now pass usb_handle_packet q->ep->dev, rather then just a local dev variable, we crash as q->ep == NULL due to the device no longer existing. This patch fixes this. Note that this patch also improves over the old behavior were we would: 1) create a queue for the device 2) create an async for the packet 3) have usb_handle_packet fail 4) destroy the async 5) wait for the queue to be idle for 32 frames 6) destroy the queue Which was rather sub-optimal. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index a06372b461..f4b555addc 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -896,6 +896,11 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr, if (q == NULL) { USBDevice *dev = uhci_find_device(s, (td->token >> 8) & 0x7f); USBEndpoint *ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf); + + if (ep == NULL) { + return uhci_handle_td_error(s, td, td_addr, USB_RET_NODEV, + int_mask); + } q = uhci_queue_new(s, qh_addr, td, ep); } async = uhci_async_alloc(q, td_addr); From a552a966f16b7b39c5df16fc17e12d02c4fa5954 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 31 Oct 2012 13:47:09 +0100 Subject: [PATCH 1486/2270] usb: Add packet combining functions Currently we only do pipelining for output endpoints, since to properly support short-not-ok semantics we can only have one outstanding input packet. Since the ehci and uhci controllers have a limited per td packet size guests will split large input transfers to into multiple packets, and since we don't pipeline these, this comes with a serious performance penalty. This patch adds helper functions to (re-)combine packets which belong to 1 transfer at the guest device-driver level into 1 large transger. This can be used by (redirection) usb-devices to enable pipelining for input endpoints. This patch will combine packets together until a transfer terminating packet is encountered. A terminating packet is a packet which meets one or more of the following conditions: 1) The packet size is *not* a multiple of the endpoint max packet size 2) The packet does *not* have its short-not-ok flag set 3) The packet has its interrupt-on-complete flag set The short-not-ok flag of the combined packet is that of the terminating packet. Multiple combined packets may be submitted to the device, if the combined packets do not have their short-not-ok flag set, enabling true pipelining. If a combined packet does have its short-not-ok flag set the queue will wait with submitting further packets to the device until that packet has completed. Once enabled in the usb-redir and ehci code, this improves the speed (MB/s) of a Linux guest reading from a USB mass storage device by a factor of 1.2 - 1.5. And the main reason why I started working on this, when reading from a pl2303 USB<->serial converter, it combines the previous 4 packets submitted per device-driver level read into 1 big read, reducing the number of packets / sec by a factor 4, and it allows to have multiple reads outstanding. This allows for much better latency tolerance without the pl2303's internal buffer overflowing (which was happening at 115200 bps, without serial flow control). Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb.h | 13 +++ hw/usb/Makefile.objs | 2 +- hw/usb/combined-packet.c | 179 +++++++++++++++++++++++++++++++++++++++ hw/usb/core.c | 1 + 4 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 hw/usb/combined-packet.c diff --git a/hw/usb.h b/hw/usb.h index 1837bf780f..aef07f4a07 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -160,6 +160,7 @@ typedef struct USBBusOps USBBusOps; typedef struct USBPort USBPort; typedef struct USBDevice USBDevice; typedef struct USBPacket USBPacket; +typedef struct USBCombinedPacket USBCombinedPacket; typedef struct USBEndpoint USBEndpoint; typedef struct USBDesc USBDesc; @@ -356,7 +357,15 @@ struct USBPacket { int result; /* transfer length or USB_RET_* status code */ /* Internal use by the USB layer. */ USBPacketState state; + USBCombinedPacket *combined; QTAILQ_ENTRY(USBPacket) queue; + QTAILQ_ENTRY(USBPacket) combined_entry; +}; + +struct USBCombinedPacket { + USBPacket *first; + QTAILQ_HEAD(packets_head, USBPacket) packets; + QEMUIOVector iov; }; void usb_packet_init(USBPacket *p); @@ -399,6 +408,10 @@ void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled); USBPacket *usb_ep_find_packet_by_id(USBDevice *dev, int pid, int ep, uint64_t id); +void usb_ep_combine_input_packets(USBEndpoint *ep); +void usb_combined_input_packet_complete(USBDevice *dev, USBPacket *p); +void usb_combined_packet_cancel(USBDevice *dev, USBPacket *p); + void usb_attach(USBPort *port); void usb_detach(USBPort *port); void usb_port_reset(USBPort *port); diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs index 7669938abd..5a4eeb6d13 100644 --- a/hw/usb/Makefile.objs +++ b/hw/usb/Makefile.objs @@ -7,7 +7,7 @@ common-obj-y += libhw.o common-obj-$(CONFIG_SMARTCARD) += dev-smartcard-reader.o common-obj-$(CONFIG_USB_REDIR) += redirect.o -common-obj-y += core.o bus.o desc.o dev-hub.o +common-obj-y += core.o combined-packet.o bus.o desc.o dev-hub.o common-obj-y += host-$(HOST_USB).o dev-bluetooth.o common-obj-y += dev-hid.o dev-storage.o dev-wacom.o common-obj-y += dev-serial.o dev-network.o dev-audio.o diff --git a/hw/usb/combined-packet.c b/hw/usb/combined-packet.c new file mode 100644 index 0000000000..652bf02628 --- /dev/null +++ b/hw/usb/combined-packet.c @@ -0,0 +1,179 @@ +/* + * QEMU USB packet combining code (for input pipelining) + * + * Copyright(c) 2012 Red Hat, Inc. + * + * Red Hat Authors: + * Hans de Goede + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or(at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +#include "qemu-common.h" +#include "hw/usb.h" +#include "iov.h" +#include "trace.h" + +static void usb_combined_packet_add(USBCombinedPacket *combined, USBPacket *p) +{ + qemu_iovec_concat(&combined->iov, &p->iov, 0, p->iov.size); + QTAILQ_INSERT_TAIL(&combined->packets, p, combined_entry); + p->combined = combined; +} + +static void usb_combined_packet_remove(USBCombinedPacket *combined, + USBPacket *p) +{ + assert(p->combined == combined); + p->combined = NULL; + QTAILQ_REMOVE(&combined->packets, p, combined_entry); +} + +/* Also handles completion of non combined packets for pipelined input eps */ +void usb_combined_input_packet_complete(USBDevice *dev, USBPacket *p) +{ + USBCombinedPacket *combined = p->combined; + USBEndpoint *ep = p->ep; + USBPacket *next; + enum { completing, complete, leftover }; + int result, state = completing; + bool short_not_ok; + + if (combined == NULL) { + usb_packet_complete_one(dev, p); + goto leave; + } + + assert(combined->first == p && p == QTAILQ_FIRST(&combined->packets)); + + result = combined->first->result; + short_not_ok = QTAILQ_LAST(&combined->packets, packets_head)->short_not_ok; + + QTAILQ_FOREACH_SAFE(p, &combined->packets, combined_entry, next) { + if (state == completing) { + /* Distribute data over uncombined packets */ + if (result >= p->iov.size) { + p->result = p->iov.size; + } else { + /* Send short or error packet to complete the transfer */ + p->result = result; + state = complete; + } + p->short_not_ok = short_not_ok; + usb_combined_packet_remove(combined, p); + usb_packet_complete_one(dev, p); + result -= p->result; + } else { + /* Remove any leftover packets from the queue */ + state = leftover; + p->result = USB_RET_REMOVE_FROM_QUEUE; + dev->port->ops->complete(dev->port, p); + } + } + /* + * If we had leftover packets the hcd driver will have cancelled them + * and usb_combined_packet_cancel has already freed combined! + */ + if (state != leftover) { + g_free(combined); + } +leave: + /* Check if there are packets in the queue waiting for our completion */ + usb_ep_combine_input_packets(ep); +} + +/* May only be called for combined packets! */ +void usb_combined_packet_cancel(USBDevice *dev, USBPacket *p) +{ + USBCombinedPacket *combined = p->combined; + assert(combined != NULL); + + usb_combined_packet_remove(combined, p); + if (p == combined->first) { + usb_device_cancel_packet(dev, p); + } + if (QTAILQ_EMPTY(&combined->packets)) { + g_free(combined); + } +} + +/* + * Large input transfers can get split into multiple input packets, this + * function recombines them, removing the short_not_ok checks which all but + * the last packet of such splits transfers have, thereby allowing input + * transfer pipelining (which we cannot do on short_not_ok transfers) + */ +void usb_ep_combine_input_packets(USBEndpoint *ep) +{ + USBPacket *p, *u, *next, *prev = NULL, *first = NULL; + USBPort *port = ep->dev->port; + int ret; + + assert(ep->pipeline); + assert(ep->pid == USB_TOKEN_IN); + + QTAILQ_FOREACH_SAFE(p, &ep->queue, queue, next) { + /* Empty the queue on a halt */ + if (ep->halted) { + p->result = USB_RET_REMOVE_FROM_QUEUE; + port->ops->complete(port, p); + continue; + } + + /* Skip packets already submitted to the device */ + if (p->state == USB_PACKET_ASYNC) { + prev = p; + continue; + } + usb_packet_check_state(p, USB_PACKET_QUEUED); + + /* + * If the previous (combined) packet has the short_not_ok flag set + * stop, as we must not submit packets to the device after a transfer + * ending with short_not_ok packet. + */ + if (prev && prev->short_not_ok) { + break; + } + + if (first) { + if (first->combined == NULL) { + USBCombinedPacket *combined = g_new0(USBCombinedPacket, 1); + + combined->first = first; + QTAILQ_INIT(&combined->packets); + qemu_iovec_init(&combined->iov, 2); + usb_combined_packet_add(combined, first); + } + usb_combined_packet_add(first->combined, p); + } else { + first = p; + } + + /* Is this packet the last one of a (combined) transfer? */ + if ((p->iov.size % ep->max_packet_size) != 0 || !p->short_not_ok || + next == NULL) { + ret = usb_device_handle_data(ep->dev, first); + assert(ret == USB_RET_ASYNC); + if (first->combined) { + QTAILQ_FOREACH(u, &first->combined->packets, combined_entry) { + usb_packet_set_state(u, USB_PACKET_ASYNC); + } + } else { + usb_packet_set_state(first, USB_PACKET_ASYNC); + } + first = NULL; + prev = p; + } + } +} diff --git a/hw/usb/core.c b/hw/usb/core.c index 632a8efe47..ab37f6f7b8 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -545,6 +545,7 @@ void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id, p->parameter = 0; p->short_not_ok = short_not_ok; p->int_req = int_req; + p->combined = NULL; qemu_iovec_reset(&p->iov); usb_packet_set_state(p, USB_PACKET_SETUP); } From 579967bea69bf1b32faee13ff76b19ba641a2618 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 31 Oct 2012 13:47:10 +0100 Subject: [PATCH 1487/2270] combined-packet: Add a workaround for Linux usbfs + live migration Older versions (anything but the latest) of Linux usbfs + libusb(x), will submit larger (bulk) transfers split into multiple 16k submissions, which means that rather then all tds getting linked into the queue in one atomic operarion they get linked in a bunch at a time, which could cause problems if: 1) We scan the queue while libusb is in the middle of submitting a split bulk transfer 2) While this bulk transfer is pending we migrate to another host. The problem is that after 2, the new host will rescan the queue and combine the packets in one large transfer, where as 1) has caused the original host to see them as 2 transfers. This patch fixes this by stopping combinging if we detect a 16k transfer with its int_req flag set. This should not adversely effect performance for other cases as: 1) Linux never sets the interrupt flag on packets other then the last 2) Windows does set the in_req flag on each td, but will submit large transfers in 20k tds thus never triggering the check Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/combined-packet.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hw/usb/combined-packet.c b/hw/usb/combined-packet.c index 652bf02628..3904e71634 100644 --- a/hw/usb/combined-packet.c +++ b/hw/usb/combined-packet.c @@ -117,7 +117,7 @@ void usb_ep_combine_input_packets(USBEndpoint *ep) { USBPacket *p, *u, *next, *prev = NULL, *first = NULL; USBPort *port = ep->dev->port; - int ret; + int ret, totalsize; assert(ep->pipeline); assert(ep->pid == USB_TOKEN_IN); @@ -161,8 +161,11 @@ void usb_ep_combine_input_packets(USBEndpoint *ep) } /* Is this packet the last one of a (combined) transfer? */ + totalsize = (p->combined) ? p->combined->iov.size : p->iov.size; if ((p->iov.size % ep->max_packet_size) != 0 || !p->short_not_ok || - next == NULL) { + next == NULL || + /* Work around for Linux usbfs bulk splitting + migration */ + (totalsize == 16348 && p->int_req)) { ret = usb_device_handle_data(ep->dev, first); assert(ret == USB_RET_ASYNC); if (first->combined) { From c19a798133e936a15ee0175ebc973d777c4c62ed Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 31 Oct 2012 13:47:11 +0100 Subject: [PATCH 1488/2270] usb-redir: Add support for 32 bits bulk packet length Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- configure | 2 +- hw/usb/redirect.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 9c6ac875a5..fbebf0f448 100755 --- a/configure +++ b/configure @@ -2755,7 +2755,7 @@ fi # check for usbredirparser for usb network redirection support if test "$usb_redir" != "no" ; then - if $pkg_config --atleast-version=0.5 libusbredirparser-0.5 >/dev/null 2>&1 ; then + if $pkg_config --atleast-version=0.5.3 libusbredirparser-0.5 >/dev/null 2>&1 ; then usb_redir="yes" usb_redir_cflags=$($pkg_config --cflags libusbredirparser-0.5 2>/dev/null) usb_redir_libs=$($pkg_config --libs libusbredirparser-0.5 2>/dev/null) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 22f671b3b1..6008620241 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -575,6 +575,10 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p, bulk_packet.endpoint = ep; bulk_packet.length = p->iov.size; bulk_packet.stream_id = 0; + bulk_packet.length_high = p->iov.size >> 16; + assert(bulk_packet.length_high == 0 || + usbredirparser_peer_has_cap(dev->parser, + usb_redir_cap_32bits_bulk_length)); if (ep & USB_DIR_IN) { usbredirparser_send_bulk_packet(dev->parser, p->id, @@ -896,6 +900,7 @@ static void usbredir_create_parser(USBRedirDevice *dev) usbredirparser_caps_set_cap(caps, usb_redir_cap_filter); usbredirparser_caps_set_cap(caps, usb_redir_cap_ep_info_max_packet_size); usbredirparser_caps_set_cap(caps, usb_redir_cap_64bits_ids); + usbredirparser_caps_set_cap(caps, usb_redir_cap_32bits_bulk_length); if (runstate_check(RUN_STATE_INMIGRATE)) { flags |= usbredirparser_fl_no_hello; @@ -1452,7 +1457,7 @@ static void usbredir_bulk_packet(void *priv, uint64_t id, { USBRedirDevice *dev = priv; uint8_t ep = bulk_packet->endpoint; - int len = bulk_packet->length; + int len = (bulk_packet->length_high << 16) | bulk_packet->length; USBPacket *p; DPRINTF("bulk-in status %d ep %02X len %d id %"PRIu64"\n", From 1b36c4d826b586de40efd0c2d3c269b14ca8e150 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 31 Oct 2012 13:47:12 +0100 Subject: [PATCH 1489/2270] usb-redir: Add support for input pipelining Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 63 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 10 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 6008620241..448cfabb17 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -29,6 +29,7 @@ #include "qemu-timer.h" #include "monitor.h" #include "sysemu.h" +#include "iov.h" #include #include @@ -312,6 +313,11 @@ static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p) { USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + if (p->combined) { + usb_combined_packet_cancel(udev, p); + return; + } + packet_id_queue_add(&dev->cancelled, p->id); usbredirparser_send_cancel_data_packet(dev->parser, p->id); usbredirparser_do_write(dev->parser); @@ -331,6 +337,10 @@ static void usbredir_fill_already_in_flight_from_ep(USBRedirDevice *dev, static USBPacket *p; QTAILQ_FOREACH(p, &ep->queue, queue) { + /* Skip combined packets, except for the first */ + if (p->combined && p != p->combined->first) { + continue; + } packet_id_queue_add(&dev->already_in_flight, p->id); } } @@ -565,17 +575,18 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p, uint8_t ep) { struct usb_redir_bulk_packet_header bulk_packet; + size_t size = (p->combined) ? p->combined->iov.size : p->iov.size; - DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, p->iov.size, p->id); + DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, size, p->id); if (usbredir_already_in_flight(dev, p->id)) { return USB_RET_ASYNC; } bulk_packet.endpoint = ep; - bulk_packet.length = p->iov.size; + bulk_packet.length = size; bulk_packet.stream_id = 0; - bulk_packet.length_high = p->iov.size >> 16; + bulk_packet.length_high = size >> 16; assert(bulk_packet.length_high == 0 || usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_32bits_bulk_length)); @@ -584,11 +595,16 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p, usbredirparser_send_bulk_packet(dev->parser, p->id, &bulk_packet, NULL, 0); } else { - uint8_t buf[p->iov.size]; - usb_packet_copy(p, buf, p->iov.size); - usbredir_log_data(dev, "bulk data out:", buf, p->iov.size); + uint8_t buf[size]; + if (p->combined) { + iov_to_buf(p->combined->iov.iov, p->combined->iov.niov, + 0, buf, size); + } else { + usb_packet_copy(p, buf, size); + } + usbredir_log_data(dev, "bulk data out:", buf, size); usbredirparser_send_bulk_packet(dev->parser, p->id, - &bulk_packet, buf, p->iov.size); + &bulk_packet, buf, size); } usbredirparser_do_write(dev->parser); return USB_RET_ASYNC; @@ -705,6 +721,10 @@ static int usbredir_handle_data(USBDevice *udev, USBPacket *p) case USB_ENDPOINT_XFER_ISOC: return usbredir_handle_iso_data(dev, p, ep); case USB_ENDPOINT_XFER_BULK: + if (p->state == USB_PACKET_SETUP && p->pid == USB_TOKEN_IN && + p->ep->pipeline) { + return USB_RET_ADD_TO_QUEUE; + } return usbredir_handle_bulk_data(dev, p, ep); case USB_ENDPOINT_XFER_INT: return usbredir_handle_interrupt_data(dev, p, ep); @@ -715,6 +735,13 @@ static int usbredir_handle_data(USBDevice *udev, USBPacket *p) } } +static void usbredir_flush_ep_queue(USBDevice *dev, USBEndpoint *ep) +{ + if (ep->pid == USB_TOKEN_IN && ep->pipeline) { + usb_ep_combine_input_packets(ep); + } +} + static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p, int config) { @@ -1283,6 +1310,11 @@ static void usbredir_set_pipeline(USBRedirDevice *dev, struct USBEndpoint *uep) if (uep->pid == USB_TOKEN_OUT) { uep->pipeline = true; } + if (uep->pid == USB_TOKEN_IN && uep->max_packet_size != 0 && + usbredirparser_peer_has_cap(dev->parser, + usb_redir_cap_32bits_bulk_length)) { + uep->pipeline = true; + } } static void usbredir_ep_info(void *priv, @@ -1465,11 +1497,17 @@ static void usbredir_bulk_packet(void *priv, uint64_t id, p = usbredir_find_packet_by_id(dev, ep, id); if (p) { + size_t size = (p->combined) ? p->combined->iov.size : p->iov.size; len = usbredir_handle_status(dev, bulk_packet->status, len); if (len > 0) { usbredir_log_data(dev, "bulk data in:", data, data_len); - if (data_len <= p->iov.size) { - usb_packet_copy(p, data, data_len); + if (data_len <= size) { + if (p->combined) { + iov_from_buf(p->combined->iov.iov, p->combined->iov.niov, + 0, data, data_len); + } else { + usb_packet_copy(p, data, data_len); + } } else { ERROR("bulk got more data then requested (%d > %zd)\n", data_len, p->iov.size); @@ -1477,7 +1515,11 @@ static void usbredir_bulk_packet(void *priv, uint64_t id, } } p->result = len; - usb_packet_complete(&dev->dev, p); + if (p->pid == USB_TOKEN_IN && p->ep->pipeline) { + usb_combined_input_packet_complete(&dev->dev, p); + } else { + usb_packet_complete(&dev->dev, p); + } } free(data); } @@ -1884,6 +1926,7 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data) uc->handle_reset = usbredir_handle_reset; uc->handle_data = usbredir_handle_data; uc->handle_control = usbredir_handle_control; + uc->flush_ep_queue = usbredir_flush_ep_queue; dc->vmsd = &usbredir_vmstate; dc->props = usbredir_properties; } From 7e03d1781690c9e9ad67a671237dbcc0d159f528 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 31 Oct 2012 13:47:13 +0100 Subject: [PATCH 1490/2270] usb-redir: Add an usbredir_setup_usb_eps() helper function Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 448cfabb17..a3df757c43 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1317,17 +1317,35 @@ static void usbredir_set_pipeline(USBRedirDevice *dev, struct USBEndpoint *uep) } } +static void usbredir_setup_usb_eps(USBRedirDevice *dev) +{ + struct USBEndpoint *usb_ep; + int i, pid; + + for (i = 0; i < MAX_ENDPOINTS; i++) { + pid = (i & 0x10) ? USB_TOKEN_IN : USB_TOKEN_OUT; + usb_ep = usb_ep_get(&dev->dev, pid, i & 0x0f); + usb_ep->type = dev->endpoint[i].type; + usb_ep->ifnum = dev->endpoint[i].interface; + usb_ep->max_packet_size = dev->endpoint[i].max_packet_size; + usbredir_set_pipeline(dev, usb_ep); + } +} + static void usbredir_ep_info(void *priv, struct usb_redir_ep_info_header *ep_info) { USBRedirDevice *dev = priv; - struct USBEndpoint *usb_ep; int i; for (i = 0; i < MAX_ENDPOINTS; i++) { dev->endpoint[i].type = ep_info->type[i]; dev->endpoint[i].interval = ep_info->interval[i]; dev->endpoint[i].interface = ep_info->interface[i]; + if (usbredirparser_peer_has_cap(dev->parser, + usb_redir_cap_ep_info_max_packet_size)) { + dev->endpoint[i].max_packet_size = ep_info->max_packet_size[i]; + } switch (dev->endpoint[i].type) { case usb_redir_type_invalid: break; @@ -1348,18 +1366,8 @@ static void usbredir_ep_info(void *priv, usbredir_device_disconnect(dev); return; } - usb_ep = usb_ep_get(&dev->dev, - (i & 0x10) ? USB_TOKEN_IN : USB_TOKEN_OUT, - i & 0x0f); - usb_ep->type = dev->endpoint[i].type; - usb_ep->ifnum = dev->endpoint[i].interface; - if (usbredirparser_peer_has_cap(dev->parser, - usb_redir_cap_ep_info_max_packet_size)) { - dev->endpoint[i].max_packet_size = - usb_ep->max_packet_size = ep_info->max_packet_size[i]; - } - usbredir_set_pipeline(dev, usb_ep); } + usbredir_setup_usb_eps(dev); } static void usbredir_configuration_status(void *priv, uint64_t id, @@ -1601,8 +1609,6 @@ static void usbredir_pre_save(void *priv) static int usbredir_post_load(void *priv, int version_id) { USBRedirDevice *dev = priv; - struct USBEndpoint *usb_ep; - int i; switch (dev->device_info.speed) { case usb_redir_speed_low: @@ -1622,15 +1628,8 @@ static int usbredir_post_load(void *priv, int version_id) } dev->dev.speedmask = (1 << dev->dev.speed); - for (i = 0; i < MAX_ENDPOINTS; i++) { - usb_ep = usb_ep_get(&dev->dev, - (i & 0x10) ? USB_TOKEN_IN : USB_TOKEN_OUT, - i & 0x0f); - usb_ep->type = dev->endpoint[i].type; - usb_ep->ifnum = dev->endpoint[i].interface; - usb_ep->max_packet_size = dev->endpoint[i].max_packet_size; - usbredir_set_pipeline(dev, usb_ep); - } + usbredir_setup_usb_eps(dev); + return 0; } From 24ac283aa293f9bd8ca4137775506edf33e45eae Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 31 Oct 2012 13:47:14 +0100 Subject: [PATCH 1491/2270] usb-redir: Use reject rather the disconnect on bad ep info So that the client gets a notification about us disconnecting the device. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index a3df757c43..5c2d185550 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1353,7 +1353,8 @@ static void usbredir_ep_info(void *priv, case usb_redir_type_interrupt: if (dev->endpoint[i].interval == 0) { ERROR("Received 0 interval for isoc or irq endpoint\n"); - usbredir_device_disconnect(dev); + usbredir_reject_device(dev); + return; } /* Fall through */ case usb_redir_type_control: @@ -1363,7 +1364,7 @@ static void usbredir_ep_info(void *priv, break; default: ERROR("Received invalid endpoint type\n"); - usbredir_device_disconnect(dev); + usbredir_reject_device(dev); return; } } From cdfd3530fafbef441ab6b86da64151f74073e5bd Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Wed, 31 Oct 2012 13:47:15 +0100 Subject: [PATCH 1492/2270] usb-redir: Allow to attach USB 2.0 devices to 1.1 host controller This follows the logic of host-linux: If a 2.0 device has no ISO endpoint and no interrupt endpoint with a packet size > 64, we can attach it also to an 1.1 host controller. In case the redir server does not report endpoint sizes, play safe and remove the 1.1 compatibility as well. Moreover, if we detect a conflicting change in the configuration after the device was already attached, it will be disconnected immediately. HdG: Several small cleanups and fixes Signed-off-by: Jan Kiszka Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 5c2d185550..8d4d3f41be 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -106,6 +106,7 @@ struct USBRedirDevice { struct usb_redir_interface_info_header interface_info; struct usbredirfilter_rule *filter_rules; int filter_rules_count; + int compatible_speedmask; }; static void usbredir_hello(void *priv, struct usb_redir_hello_header *h); @@ -962,6 +963,7 @@ static void usbredir_do_attach(void *opaque) } if (usb_device_attach(&dev->dev) != 0) { + WARNING("rejecting device due to speed mismatch\n"); usbredir_reject_device(dev); } } @@ -1068,6 +1070,9 @@ static int usbredir_initfn(USBDevice *udev) /* We'll do the attach once we receive the speed from the usb-host */ udev->auto_attach = 0; + /* Will be cleared during setup when we find conflicts */ + dev->compatible_speedmask = USB_SPEED_MASK_FULL; + /* Let the backend know we are ready */ qemu_chr_fe_open(dev->cs); qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read, @@ -1208,6 +1213,7 @@ static void usbredir_device_connect(void *priv, case usb_redir_speed_low: speed = "low speed"; dev->dev.speed = USB_SPEED_LOW; + dev->compatible_speedmask &= ~USB_SPEED_MASK_FULL; break; case usb_redir_speed_full: speed = "full speed"; @@ -1241,7 +1247,7 @@ static void usbredir_device_connect(void *priv, device_connect->device_class); } - dev->dev.speedmask = (1 << dev->dev.speed); + dev->dev.speedmask = (1 << dev->dev.speed) | dev->compatible_speedmask; dev->device_info = *device_connect; if (usbredir_check_filter(dev)) { @@ -1281,6 +1287,7 @@ static void usbredir_device_disconnect(void *priv) dev->interface_info.interface_count = NO_INTERFACE_INFO; dev->dev.addr = 0; dev->dev.speed = 0; + dev->compatible_speedmask = USB_SPEED_MASK_FULL; } static void usbredir_interface_info(void *priv, @@ -1302,6 +1309,12 @@ static void usbredir_interface_info(void *priv, } } +static void usbredir_mark_speed_incompatible(USBRedirDevice *dev, int speed) +{ + dev->compatible_speedmask &= ~(1 << speed); + dev->dev.speedmask = (1 << dev->dev.speed) | dev->compatible_speedmask; +} + static void usbredir_set_pipeline(USBRedirDevice *dev, struct USBEndpoint *uep) { if (uep->type != USB_ENDPOINT_XFER_BULK) { @@ -1350,7 +1363,14 @@ static void usbredir_ep_info(void *priv, case usb_redir_type_invalid: break; case usb_redir_type_iso: + usbredir_mark_speed_incompatible(dev, USB_SPEED_FULL); + /* Fall through */ case usb_redir_type_interrupt: + if (!usbredirparser_peer_has_cap(dev->parser, + usb_redir_cap_ep_info_max_packet_size) || + ep_info->max_packet_size[i] > 64) { + usbredir_mark_speed_incompatible(dev, USB_SPEED_FULL); + } if (dev->endpoint[i].interval == 0) { ERROR("Received 0 interval for isoc or irq endpoint\n"); usbredir_reject_device(dev); @@ -1368,6 +1388,14 @@ static void usbredir_ep_info(void *priv, return; } } + /* The new ep info may have caused a speed incompatibility, recheck */ + if (dev->dev.attached && + !(dev->dev.port->speedmask & dev->dev.speedmask)) { + ERROR("Device no longer matches speed after endpoint info change, " + "disconnecting!\n"); + usbredir_reject_device(dev); + return; + } usbredir_setup_usb_eps(dev); } From 95a59dc03988d190bbc72d980a149be3a79592fb Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 31 Oct 2012 13:47:16 +0100 Subject: [PATCH 1493/2270] usb-redir: Allow redirecting super speed devices to high speed controllers Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 8d4d3f41be..c5cfe0b313 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1071,7 +1071,7 @@ static int usbredir_initfn(USBDevice *udev) udev->auto_attach = 0; /* Will be cleared during setup when we find conflicts */ - dev->compatible_speedmask = USB_SPEED_MASK_FULL; + dev->compatible_speedmask = USB_SPEED_MASK_FULL | USB_SPEED_MASK_HIGH; /* Let the backend know we are ready */ qemu_chr_fe_open(dev->cs); @@ -1214,10 +1214,12 @@ static void usbredir_device_connect(void *priv, speed = "low speed"; dev->dev.speed = USB_SPEED_LOW; dev->compatible_speedmask &= ~USB_SPEED_MASK_FULL; + dev->compatible_speedmask &= ~USB_SPEED_MASK_HIGH; break; case usb_redir_speed_full: speed = "full speed"; dev->dev.speed = USB_SPEED_FULL; + dev->compatible_speedmask &= ~USB_SPEED_MASK_HIGH; break; case usb_redir_speed_high: speed = "high speed"; @@ -1287,7 +1289,7 @@ static void usbredir_device_disconnect(void *priv) dev->interface_info.interface_count = NO_INTERFACE_INFO; dev->dev.addr = 0; dev->dev.speed = 0; - dev->compatible_speedmask = USB_SPEED_MASK_FULL; + dev->compatible_speedmask = USB_SPEED_MASK_FULL | USB_SPEED_MASK_HIGH; } static void usbredir_interface_info(void *priv, @@ -1364,6 +1366,7 @@ static void usbredir_ep_info(void *priv, break; case usb_redir_type_iso: usbredir_mark_speed_incompatible(dev, USB_SPEED_FULL); + usbredir_mark_speed_incompatible(dev, USB_SPEED_HIGH); /* Fall through */ case usb_redir_type_interrupt: if (!usbredirparser_peer_has_cap(dev->parser, @@ -1371,6 +1374,11 @@ static void usbredir_ep_info(void *priv, ep_info->max_packet_size[i] > 64) { usbredir_mark_speed_incompatible(dev, USB_SPEED_FULL); } + if (!usbredirparser_peer_has_cap(dev->parser, + usb_redir_cap_ep_info_max_packet_size) || + ep_info->max_packet_size[i] > 1024) { + usbredir_mark_speed_incompatible(dev, USB_SPEED_HIGH); + } if (dev->endpoint[i].interval == 0) { ERROR("Received 0 interval for isoc or irq endpoint\n"); usbredir_reject_device(dev); @@ -1501,6 +1509,17 @@ static void usbredir_control_packet(void *priv, uint64_t id, DPRINTF("ctrl-in status %d len %d id %"PRIu64"\n", control_packet->status, len, id); + /* Fix up USB-3 ep0 maxpacket size to allow superspeed connected devices + * to work redirected to a not superspeed capable hcd */ + if (dev->dev.speed == USB_SPEED_SUPER && + !((dev->dev.port->speedmask & USB_SPEED_MASK_SUPER)) && + control_packet->requesttype == 0x80 && + control_packet->request == 6 && + control_packet->value == 0x100 && control_packet->index == 0 && + data_len >= 18 && data[7] == 9) { + data[7] = 64; + } + p = usbredir_find_packet_by_id(dev, 0, id); if (p) { len = usbredir_handle_status(dev, control_packet->status, len); From fc53b7d4b7fe409acae7d8d55a868eb5c696d71c Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 26 Oct 2012 16:29:38 +0100 Subject: [PATCH 1494/2270] arm_boot: Change initrd load address to "halfway through RAM" To avoid continually having to bump the initrd load address to account for larger kernel images, put the initrd halfway through RAM. This allows large kernels on new boards with lots of RAM to work OK, without breaking existing usecases for boards with only 32MB of RAM. Note that this change fixes in passing a bug where we were passing an overly large max_size to load_image_targphys() for the initrd, which meant that we wouldn't correctly refuse to load an enormous initrd that didn't actually fit into RAM. Signed-off-by: Peter Maydell Reviewed-by: Aurelien Jarno Reviewed-by: Igor Mitsyanko Tested-by: Cole Robinson Signed-off-by: Aurelien Jarno --- hw/arm-misc.h | 1 + hw/arm_boot.c | 40 +++++++++++++++++++++++++--------------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/hw/arm-misc.h b/hw/arm-misc.h index d02f7f08c8..adb166586b 100644 --- a/hw/arm-misc.h +++ b/hw/arm-misc.h @@ -56,6 +56,7 @@ struct arm_boot_info { const struct arm_boot_info *info); /* Used internally by arm_boot.c */ int is_linux; + hwaddr initrd_start; hwaddr initrd_size; hwaddr entry; }; diff --git a/hw/arm_boot.c b/hw/arm_boot.c index 09bf6c5cdc..92e2cab476 100644 --- a/hw/arm_boot.c +++ b/hw/arm_boot.c @@ -18,7 +18,6 @@ #define KERNEL_ARGS_ADDR 0x100 #define KERNEL_LOAD_ADDR 0x00010000 -#define INITRD_LOAD_ADDR 0x00d00000 /* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */ static uint32_t bootloader[] = { @@ -109,7 +108,7 @@ static void set_kernel_args(const struct arm_boot_info *info) /* ATAG_INITRD2 */ WRITE_WORD(p, 4); WRITE_WORD(p, 0x54420005); - WRITE_WORD(p, info->loader_start + INITRD_LOAD_ADDR); + WRITE_WORD(p, info->initrd_start); WRITE_WORD(p, initrd_size); } if (info->kernel_cmdline && *info->kernel_cmdline) { @@ -185,10 +184,11 @@ static void set_kernel_args_old(const struct arm_boot_info *info) /* pages_in_vram */ WRITE_WORD(p, 0); /* initrd_start */ - if (initrd_size) - WRITE_WORD(p, info->loader_start + INITRD_LOAD_ADDR); - else + if (initrd_size) { + WRITE_WORD(p, info->initrd_start); + } else { WRITE_WORD(p, 0); + } /* initrd_size */ WRITE_WORD(p, initrd_size); /* rd_start */ @@ -281,14 +281,13 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo) if (binfo->initrd_size) { rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start", - binfo->loader_start + INITRD_LOAD_ADDR); + binfo->initrd_start); if (rc < 0) { fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n"); } rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end", - binfo->loader_start + INITRD_LOAD_ADDR + - binfo->initrd_size); + binfo->initrd_start + binfo->initrd_size); if (rc < 0) { fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n"); } @@ -375,6 +374,19 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) big_endian = 0; #endif + /* We want to put the initrd far enough into RAM that when the + * kernel is uncompressed it will not clobber the initrd. However + * on boards without much RAM we must ensure that we still leave + * enough room for a decent sized initrd, and on boards with large + * amounts of RAM we must avoid the initrd being so far up in RAM + * that it is outside lowmem and inaccessible to the kernel. + * So for boards with less than 256MB of RAM we put the initrd + * halfway into RAM, and for boards with 256MB of RAM or more we put + * the initrd at 128MB. + */ + info->initrd_start = info->loader_start + + MIN(info->ram_size / 2, 128 * 1024 * 1024); + /* Assume that raw images are linux kernels, and ELF images are not. */ kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry, NULL, NULL, big_endian, ELF_MACHINE, 1); @@ -398,10 +410,9 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) if (is_linux) { if (info->initrd_filename) { initrd_size = load_image_targphys(info->initrd_filename, - info->loader_start - + INITRD_LOAD_ADDR, - info->ram_size - - INITRD_LOAD_ADDR); + info->initrd_start, + info->ram_size - + info->initrd_start); if (initrd_size < 0) { fprintf(stderr, "qemu: could not load initrd '%s'\n", info->initrd_filename); @@ -419,9 +430,8 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) */ if (info->dtb_filename) { /* Place the DTB after the initrd in memory */ - hwaddr dtb_start = TARGET_PAGE_ALIGN(info->loader_start - + INITRD_LOAD_ADDR - + initrd_size); + hwaddr dtb_start = TARGET_PAGE_ALIGN(info->initrd_start + + initrd_size); if (load_dtb(dtb_start, info)) { exit(1); } From 2ddef11bede823b068b59a66b4c5c62377e69b2f Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Fri, 19 Oct 2012 19:08:04 +1000 Subject: [PATCH 1495/2270] cadence_uart: More debug information Add more helpful debug information to the cadence UART. Signed-off-by: Peter Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Stefan Hajnoczi --- hw/cadence_uart.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c index a7d0504c58..686e6172d0 100644 --- a/hw/cadence_uart.c +++ b/hw/cadence_uart.c @@ -359,7 +359,7 @@ static void uart_write(void *opaque, hwaddr offset, { UartState *s = (UartState *)opaque; - DB_PRINT(" offset:%x data:%08x\n", offset, (unsigned)value); + DB_PRINT(" offset:%x data:%08x\n", (unsigned)offset, (unsigned)value); offset >>= 2; switch (offset) { case R_IER: /* ier (wts imr) */ @@ -405,12 +405,15 @@ static uint64_t uart_read(void *opaque, hwaddr offset, offset >>= 2; if (offset >= R_MAX) { - return 0; + c = 0; } else if (offset == R_TX_RX) { uart_read_rx_fifo(s, &c); - return c; + } else { + c = s->r[offset]; } - return s->r[offset]; + + DB_PRINT(" offset:%x data:%08x\n", (unsigned)(offset << 2), (unsigned)c); + return c; } static const MemoryRegionOps uart_ops = { From e88a676e916bd29c1224ea46e037f354776fa3c8 Mon Sep 17 00:00:00 2001 From: Meador Inge Date: Fri, 24 Feb 2012 16:18:41 -0600 Subject: [PATCH 1496/2270] m68k: Return semihosting errno values correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixing a simple typo, s/errno/err/, that caused the error status from GDB semihosted system calls to be returned incorrectly. Signed-off-by: Meador Inge Reviewed-by: Andreas Färber Signed-off-by: Stefan Hajnoczi --- target-m68k/m68k-semi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-m68k/m68k-semi.c b/target-m68k/m68k-semi.c index 3bb30cd1f7..fed44ea490 100644 --- a/target-m68k/m68k-semi.c +++ b/target-m68k/m68k-semi.c @@ -150,7 +150,7 @@ static void m68k_semi_cb(CPUM68KState *env, target_ulong ret, target_ulong err) } /* FIXME - handle put_user() failure */ put_user_u32(ret, args); - put_user_u32(errno, args + 4); + put_user_u32(err, args + 4); } #define ARG(n) \ From 8f7219675353f909a1ff1fa4542626a5dc4553cf Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 28 Oct 2012 11:04:46 +0000 Subject: [PATCH 1497/2270] target-sparc: make do_unaligned_access static Signed-off-by: Blue Swirl Signed-off-by: Stefan Hajnoczi --- target-sparc/cpu.h | 3 --- target-sparc/ldst_helper.c | 8 ++++++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index a55fe08d36..7c689ee3bb 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -711,9 +711,6 @@ uint64_t cpu_tick_get_count(CPUTimer *timer); void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit); trap_state* cpu_tsptr(CPUSPARCState* env); #endif -void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env, target_ulong addr, - int is_write, int is_user, - uintptr_t retaddr); void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr); #define TB_FLAG_FPU_ENABLED (1 << 4) diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c index 356144a5c0..f3e08fd6e6 100644 --- a/target-sparc/ldst_helper.c +++ b/target-sparc/ldst_helper.c @@ -65,6 +65,9 @@ #define QT1 (env->qt1) #if !defined(CONFIG_USER_ONLY) +static void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env, + target_ulong addr, int is_write, + int is_user, uintptr_t retaddr); #include "softmmu_exec.h" #define MMUSUFFIX _mmu #define ALIGNED_ONLY @@ -2407,8 +2410,9 @@ void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr) } #if !defined(CONFIG_USER_ONLY) -void do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write, - int is_user, uintptr_t retaddr) +static void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env, + target_ulong addr, int is_write, + int is_user, uintptr_t retaddr) { #ifdef DEBUG_UNALIGNED printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx From 4fdcac0e2b102c8017cf81eb6dfb3e5e1c490949 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 28 Oct 2012 11:04:47 +0000 Subject: [PATCH 1498/2270] vl.c: add missing static Add missing 'static' qualifiers. Signed-off-by: Blue Swirl Signed-off-by: Stefan Hajnoczi --- sysemu.h | 5 ----- vl.c | 21 ++++++++++++--------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/sysemu.h b/sysemu.h index f72b4ce125..f5ac664067 100644 --- a/sysemu.h +++ b/sysemu.h @@ -19,7 +19,6 @@ extern uint8_t qemu_uuid[]; int qemu_uuid_parse(const char *str, uint8_t *uuid); #define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" -void runstate_init(void); bool runstate_check(RunState state); void runstate_set(RunState new_state); int runstate_is_running(void); @@ -57,11 +56,7 @@ void qemu_system_debug_request(void); void qemu_system_vmstop_request(RunState reason); int qemu_shutdown_requested_get(void); int qemu_reset_requested_get(void); -int qemu_shutdown_requested(void); -int qemu_reset_requested(void); -int qemu_powerdown_requested(void); void qemu_system_killed(int signal, pid_t pid); -void qemu_kill_report(void); void qemu_devices_reset(void); void qemu_system_reset(bool report); diff --git a/vl.c b/vl.c index 5513d1518e..d840c32161 100644 --- a/vl.c +++ b/vl.c @@ -180,7 +180,7 @@ static const char *data_dir; const char *bios_name = NULL; enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; DisplayType display_type = DT_DEFAULT; -int display_remote = 0; +static int display_remote; const char* keyboard_layout = NULL; ram_addr_t ram_size; const char *mem_path = NULL; @@ -214,7 +214,7 @@ const char *vnc_display; int acpi_enabled = 1; int no_hpet = 0; int fd_bootchk = 1; -int no_reboot = 0; +static int no_reboot; int no_shutdown = 0; int cursor_hide = 1; int graphic_rotate = 0; @@ -242,7 +242,8 @@ struct FWBootEntry { char *suffix; }; -QTAILQ_HEAD(, FWBootEntry) fw_boot_order = QTAILQ_HEAD_INITIALIZER(fw_boot_order); +static QTAILQ_HEAD(, FWBootEntry) fw_boot_order = + QTAILQ_HEAD_INITIALIZER(fw_boot_order); int nb_numa_nodes; uint64_t node_mem[MAX_NODES]; @@ -396,7 +397,7 @@ bool runstate_check(RunState state) return current_run_state == state; } -void runstate_init(void) +static void runstate_init(void) { const RunStateTransition *p; @@ -1457,14 +1458,14 @@ int qemu_reset_requested_get(void) return reset_requested; } -int qemu_shutdown_requested(void) +static int qemu_shutdown_requested(void) { int r = shutdown_requested; shutdown_requested = 0; return r; } -void qemu_kill_report(void) +static void qemu_kill_report(void) { if (!qtest_enabled() && shutdown_signal != -1) { fprintf(stderr, "qemu: terminating on signal %d", shutdown_signal); @@ -1480,7 +1481,7 @@ void qemu_kill_report(void) } } -int qemu_reset_requested(void) +static int qemu_reset_requested(void) { int r = reset_requested; reset_requested = 0; @@ -1501,7 +1502,7 @@ static int qemu_wakeup_requested(void) return r; } -int qemu_powerdown_requested(void) +static int qemu_powerdown_requested(void) { int r = powerdown_requested; powerdown_requested = 0; @@ -2127,7 +2128,9 @@ struct device_config { Location loc; QTAILQ_ENTRY(device_config) next; }; -QTAILQ_HEAD(, device_config) device_configs = QTAILQ_HEAD_INITIALIZER(device_configs); + +static QTAILQ_HEAD(, device_config) device_configs = + QTAILQ_HEAD_INITIALIZER(device_configs); static void add_device_config(int type, const char *cmdline) { From 71a8cdeca095acb2a67924de870f4ee8da5b8803 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 28 Oct 2012 11:04:48 +0000 Subject: [PATCH 1499/2270] vnc: add missing static Add missing 'static' qualifiers. Signed-off-by: Blue Swirl Signed-off-by: Stefan Hajnoczi --- console.h | 2 -- ui/vnc-jobs.c | 10 +++++----- ui/vnc-jobs.h | 1 - ui/vnc.c | 14 +++++++------- ui/vnc.h | 5 ----- 5 files changed, 12 insertions(+), 20 deletions(-) diff --git a/console.h b/console.h index 6099d8d710..5ad361510a 100644 --- a/console.h +++ b/console.h @@ -377,10 +377,8 @@ void cocoa_display_init(DisplayState *ds, int full_screen); /* vnc.c */ void vnc_display_init(DisplayState *ds); -void vnc_display_close(DisplayState *ds); void vnc_display_open(DisplayState *ds, const char *display, Error **errp); void vnc_display_add_client(DisplayState *ds, int csock, int skipauth); -int vnc_display_disable_login(DisplayState *ds); char *vnc_display_local_addr(DisplayState *ds); #ifdef CONFIG_VNC int vnc_display_password(DisplayState *ds, const char *password); diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c index 3c592b3f3d..dfe482dc0f 100644 --- a/ui/vnc-jobs.c +++ b/ui/vnc-jobs.c @@ -320,6 +320,11 @@ static void *vnc_worker_thread(void *arg) return NULL; } +static bool vnc_worker_thread_running(void) +{ + return queue; /* Check global queue */ +} + void vnc_start_worker_thread(void) { VncJobQueue *q; @@ -332,11 +337,6 @@ void vnc_start_worker_thread(void) queue = q; /* Set global queue */ } -bool vnc_worker_thread_running(void) -{ - return queue; /* Check global queue */ -} - void vnc_stop_worker_thread(void) { if (!vnc_worker_thread_running()) diff --git a/ui/vnc-jobs.h b/ui/vnc-jobs.h index 86e6d888c6..31da103fac 100644 --- a/ui/vnc-jobs.h +++ b/ui/vnc-jobs.h @@ -40,7 +40,6 @@ void vnc_jobs_join(VncState *vs); void vnc_jobs_consume_buffer(VncState *vs); void vnc_start_worker_thread(void); -bool vnc_worker_thread_running(void); void vnc_stop_worker_thread(void); /* Locks */ diff --git a/ui/vnc.c b/ui/vnc.c index d0ffcc54af..d95e6ef5f3 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -479,12 +479,12 @@ void buffer_reserve(Buffer *buffer, size_t len) } } -int buffer_empty(Buffer *buffer) +static int buffer_empty(Buffer *buffer) { return buffer->offset == 0; } -uint8_t *buffer_end(Buffer *buffer) +static uint8_t *buffer_end(Buffer *buffer) { return buffer->buffer + buffer->offset; } @@ -1376,17 +1376,17 @@ void vnc_flush(VncState *vs) vnc_unlock_output(vs); } -uint8_t read_u8(uint8_t *data, size_t offset) +static uint8_t read_u8(uint8_t *data, size_t offset) { return data[offset]; } -uint16_t read_u16(uint8_t *data, size_t offset) +static uint16_t read_u16(uint8_t *data, size_t offset) { return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF); } -int32_t read_s32(uint8_t *data, size_t offset) +static int32_t read_s32(uint8_t *data, size_t offset) { return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]); @@ -2763,7 +2763,7 @@ void vnc_display_init(DisplayState *ds) } -void vnc_display_close(DisplayState *ds) +static void vnc_display_close(DisplayState *ds) { VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; @@ -2785,7 +2785,7 @@ void vnc_display_close(DisplayState *ds) #endif } -int vnc_display_disable_login(DisplayState *ds) +static int vnc_display_disable_login(DisplayState *ds) { VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; diff --git a/ui/vnc.h b/ui/vnc.h index 068c2fcda5..c89f6934b4 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -493,9 +493,6 @@ void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting); /* Buffer I/O functions */ -uint8_t read_u8(uint8_t *data, size_t offset); -uint16_t read_u16(uint8_t *data, size_t offset); -int32_t read_s32(uint8_t *data, size_t offset); uint32_t read_u32(uint8_t *data, size_t offset); /* Protocol stage functions */ @@ -507,8 +504,6 @@ void start_auth_vnc(VncState *vs); /* Buffer management */ void buffer_reserve(Buffer *buffer, size_t len); -int buffer_empty(Buffer *buffer); -uint8_t *buffer_end(Buffer *buffer); void buffer_reset(Buffer *buffer); void buffer_free(Buffer *buffer); void buffer_append(Buffer *buffer, const void *data, size_t len); From 434482925ee11091fc111bd2a86de0b677b3e943 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 28 Oct 2012 11:04:49 +0000 Subject: [PATCH 1500/2270] ppc: add missing static Add missing 'static' qualifiers. Signed-off-by: Blue Swirl Acked-by: Alexander Graf Signed-off-by: Stefan Hajnoczi --- hw/adb.c | 8 ++++---- hw/adb.h | 4 ---- hw/nvram.h | 10 +--------- hw/ppc.c | 16 ++++++++-------- target-ppc/cpu.h | 1 - 5 files changed, 13 insertions(+), 26 deletions(-) diff --git a/hw/adb.c b/hw/adb.c index aa15f55dc9..3b547f0af7 100644 --- a/hw/adb.c +++ b/hw/adb.c @@ -108,10 +108,10 @@ int adb_poll(ADBBusState *s, uint8_t *obuf) return olen; } -ADBDevice *adb_register_device(ADBBusState *s, int devaddr, - ADBDeviceRequest *devreq, - ADBDeviceReset *devreset, - void *opaque) +static ADBDevice *adb_register_device(ADBBusState *s, int devaddr, + ADBDeviceRequest *devreq, + ADBDeviceReset *devreset, + void *opaque) { ADBDevice *d; if (s->nb_devices >= MAX_ADB_DEVICES) diff --git a/hw/adb.h b/hw/adb.h index b2a591c546..5b27da2dd3 100644 --- a/hw/adb.h +++ b/hw/adb.h @@ -56,10 +56,6 @@ int adb_request(ADBBusState *s, uint8_t *buf_out, const uint8_t *buf, int len); int adb_poll(ADBBusState *s, uint8_t *buf_out); -ADBDevice *adb_register_device(ADBBusState *s, int devaddr, - ADBDeviceRequest *devreq, - ADBDeviceReset *devreset, - void *opaque); void adb_kbd_init(ADBBusState *bus); void adb_mouse_init(ADBBusState *bus); diff --git a/hw/nvram.h b/hw/nvram.h index a4a1db4976..72363ced42 100644 --- a/hw/nvram.h +++ b/hw/nvram.h @@ -10,17 +10,9 @@ typedef struct nvram_t { nvram_write_t write_fn; } nvram_t; -void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value); -uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr); -void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value); -uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr); -void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value); uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr); -void NVRAM_set_string (nvram_t *nvram, uint32_t addr, - const char *str, uint32_t max); int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max); -void NVRAM_set_crc (nvram_t *nvram, uint32_t addr, - uint32_t start, uint32_t count); + int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size, const char *arch, uint32_t RAM_size, int boot_device, diff --git a/hw/ppc.c b/hw/ppc.c index 98546de991..e4a0a3e822 100644 --- a/hw/ppc.c +++ b/hw/ppc.c @@ -721,7 +721,7 @@ static void cpu_ppc_hdecr_cb (void *opaque) _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1); } -void cpu_ppc_store_purr (CPUPPCState *env, uint64_t value) +static void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value) { ppc_tb_t *tb_env = env->tb_env; @@ -1152,23 +1152,23 @@ static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val) (*nvram->write_fn)(nvram->opaque, addr, val); } -void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value) +static void NVRAM_set_byte(nvram_t *nvram, uint32_t addr, uint8_t value) { nvram_write(nvram, addr, value); } -uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr) +static uint8_t NVRAM_get_byte(nvram_t *nvram, uint32_t addr) { return nvram_read(nvram, addr); } -void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value) +static void NVRAM_set_word(nvram_t *nvram, uint32_t addr, uint16_t value) { nvram_write(nvram, addr, value >> 8); nvram_write(nvram, addr + 1, value & 0xFF); } -uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr) +static uint16_t NVRAM_get_word(nvram_t *nvram, uint32_t addr) { uint16_t tmp; @@ -1178,7 +1178,7 @@ uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr) return tmp; } -void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value) +static void NVRAM_set_lword(nvram_t *nvram, uint32_t addr, uint32_t value) { nvram_write(nvram, addr, value >> 24); nvram_write(nvram, addr + 1, (value >> 16) & 0xFF); @@ -1198,8 +1198,8 @@ uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr) return tmp; } -void NVRAM_set_string (nvram_t *nvram, uint32_t addr, - const char *str, uint32_t max) +static void NVRAM_set_string(nvram_t *nvram, uint32_t addr, const char *str, + uint32_t max) { int i; diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 286f42a808..ddee9a00a4 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1177,7 +1177,6 @@ void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value); uint32_t cpu_ppc_load_hdecr (CPUPPCState *env); void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value); uint64_t cpu_ppc_load_purr (CPUPPCState *env); -void cpu_ppc_store_purr (CPUPPCState *env, uint64_t value); uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env); uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env); #if !defined(CONFIG_USER_ONLY) From 6575c289f8c9820a7a0d2de2b0c3c58b13d9abc8 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 28 Oct 2012 11:04:50 +0000 Subject: [PATCH 1501/2270] target-ppc: make some functions static Signed-off-by: Blue Swirl Acked-by: Alexander Graf Signed-off-by: Stefan Hajnoczi --- target-ppc/cpu.h | 6 ------ target-ppc/mmu_helper.c | 11 ++++++----- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index ddee9a00a4..bb5b0a4a99 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1140,10 +1140,6 @@ int cpu_ppc_signal_handler (int host_signum, void *pinfo, int cpu_ppc_handle_mmu_fault (CPUPPCState *env, target_ulong address, int rw, int mmu_idx); #define cpu_handle_mmu_fault cpu_ppc_handle_mmu_fault -#if !defined(CONFIG_USER_ONLY) -int get_physical_address (CPUPPCState *env, mmu_ctx_t *ctx, target_ulong vaddr, - int rw, int access_type); -#endif void do_interrupt (CPUPPCState *env); void ppc_hw_interrupt (CPUPPCState *env); @@ -1188,8 +1184,6 @@ void store_40x_dbcr0 (CPUPPCState *env, uint32_t val); void store_40x_sler (CPUPPCState *env, uint32_t val); void store_booke_tcr (CPUPPCState *env, target_ulong val); void store_booke_tsr (CPUPPCState *env, target_ulong val); -void booke206_flush_tlb(CPUPPCState *env, int flags, const int check_iprot); -hwaddr booke206_tlb_to_page_size(CPUPPCState *env, ppcmas_tlb_t *tlb); int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, hwaddr *raddrp, target_ulong address, uint32_t pid); diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c index 811f47f309..318ce92adb 100644 --- a/target-ppc/mmu_helper.c +++ b/target-ppc/mmu_helper.c @@ -1276,7 +1276,8 @@ static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, return ret; } -void booke206_flush_tlb(CPUPPCState *env, int flags, const int check_iprot) +static void booke206_flush_tlb(CPUPPCState *env, int flags, + const int check_iprot) { int tlb_size; int i, j; @@ -1297,8 +1298,8 @@ void booke206_flush_tlb(CPUPPCState *env, int flags, const int check_iprot) tlb_flush(env, 1); } -hwaddr booke206_tlb_to_page_size(CPUPPCState *env, - ppcmas_tlb_t *tlb) +static hwaddr booke206_tlb_to_page_size(CPUPPCState *env, + ppcmas_tlb_t *tlb) { int tlbm_size; @@ -1706,8 +1707,8 @@ static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx, return ret; } -int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr, - int rw, int access_type) +static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, + target_ulong eaddr, int rw, int access_type) { int ret; From 8b9c99d9dcbf532649f8e614becfa15d2ac4ea75 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 28 Oct 2012 11:04:51 +0000 Subject: [PATCH 1502/2270] exec: make some functions static Signed-off-by: Blue Swirl Signed-off-by: Stefan Hajnoczi --- cpu-common.h | 5 ----- exec-all.h | 2 -- exec.c | 15 +++++++++------ memory-internal.h | 2 -- 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/cpu-common.h b/cpu-common.h index 5f9308933c..d2fbafac9c 100644 --- a/cpu-common.h +++ b/cpu-common.h @@ -39,10 +39,6 @@ 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_ram_ptr_length(ram_addr_t addr, ram_addr_t *size); -/* Same but slower, to use for migration, where the order of - * RAMBlocks must not change. */ -void *qemu_safe_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); @@ -67,7 +63,6 @@ void *cpu_physical_memory_map(hwaddr addr, void cpu_physical_memory_unmap(void *buffer, hwaddr len, int is_write, hwaddr access_len); void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque)); -void cpu_unregister_map_client(void *cookie); bool cpu_physical_memory_is_io(hwaddr phys_addr); diff --git a/exec-all.h b/exec-all.h index 2ea0e4fc24..8db47f5c9b 100644 --- a/exec-all.h +++ b/exec-all.h @@ -194,8 +194,6 @@ static inline unsigned int tb_phys_hash_func(tb_page_addr_t pc) void tb_free(TranslationBlock *tb); void tb_flush(CPUArchState *env); -void tb_link_page(TranslationBlock *tb, - tb_page_addr_t phys_pc, tb_page_addr_t phys_page2); void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr); extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; diff --git a/exec.c b/exec.c index b0ed5939e9..42cc0975e6 100644 --- a/exec.c +++ b/exec.c @@ -188,9 +188,12 @@ static unsigned phys_map_nodes_nb, phys_map_nodes_nb_alloc; static void io_mem_init(void); static void memory_map_init(void); +static void *qemu_safe_ram_ptr(ram_addr_t addr); static MemoryRegion io_mem_watch; #endif +static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, + tb_page_addr_t phys_page2); /* statistics */ static int tb_flush_count; @@ -1349,8 +1352,8 @@ static inline void tb_alloc_page(TranslationBlock *tb, /* add a new TB and link it to the physical page tables. phys_page2 is (-1) to indicate that only one page contains the TB. */ -void tb_link_page(TranslationBlock *tb, - tb_page_addr_t phys_pc, tb_page_addr_t phys_page2) +static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, + tb_page_addr_t phys_page2) { unsigned int h; TranslationBlock **ptb; @@ -1859,7 +1862,7 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, } } -int cpu_physical_memory_set_dirty_tracking(int enable) +static int cpu_physical_memory_set_dirty_tracking(int enable) { int ret = 0; in_migration = enable; @@ -2741,7 +2744,7 @@ void *qemu_get_ram_ptr(ram_addr_t addr) /* Return a host pointer to ram allocated with qemu_ram_alloc. * Same as qemu_get_ram_ptr but avoid reordering ramblocks. */ -void *qemu_safe_ram_ptr(ram_addr_t addr) +static void *qemu_safe_ram_ptr(ram_addr_t addr) { RAMBlock *block; @@ -2771,7 +2774,7 @@ void *qemu_safe_ram_ptr(ram_addr_t addr) /* Return a host pointer to guest's ram. Similar to qemu_get_ram_ptr * but takes a size argument */ -void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size) +static void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size) { if (*size == 0) { return NULL; @@ -3519,7 +3522,7 @@ void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque)) return client; } -void cpu_unregister_map_client(void *_client) +static void cpu_unregister_map_client(void *_client) { MapClient *client = (MapClient *)_client; diff --git a/memory-internal.h b/memory-internal.h index 1c34b9751c..1da240039d 100644 --- a/memory-internal.h +++ b/memory-internal.h @@ -55,8 +55,6 @@ struct MemoryRegionSection; void qemu_register_coalesced_mmio(hwaddr addr, ram_addr_t size); void qemu_unregister_coalesced_mmio(hwaddr addr, ram_addr_t size); -int cpu_physical_memory_set_dirty_tracking(int enable); - #define VGA_DIRTY_FLAG 0x01 #define CODE_DIRTY_FLAG 0x02 #define MIGRATION_DIRTY_FLAG 0x08 From 0d3cf3b6ff469bba95ae235021a3be232af4068d Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 1 Nov 2012 17:29:24 +0100 Subject: [PATCH 1503/2270] pc: Drop redundant test for ROM memory region Just a few lines above, we already initialize rom_memory accordingly. Signed-off-by: Jan Kiszka Signed-off-by: Stefan Hajnoczi --- hw/pc_piix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 85529b2cea..cfa839c8b4 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -178,7 +178,7 @@ static void pc_init1(MemoryRegion *system_memory, fw_cfg = pc_memory_init(system_memory, kernel_filename, kernel_cmdline, initrd_filename, below_4g_mem_size, above_4g_mem_size, - pci_enabled ? rom_memory : system_memory, &ram_memory); + rom_memory, &ram_memory); } gsi_state = g_malloc0(sizeof(*gsi_state)); From dc63936df7cc4c6f07b8c8c4ba0bf177b8df085e Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 2 Nov 2012 08:44:13 +0100 Subject: [PATCH 1504/2270] xenfb: fix build breakage caused by console cleanup series Console cleanup series renamed dpy_resize and dpy_update all over the tree, but hw/xenfb.c was forgotten. Update it too so it builds again. Reported-by: Jan Kiszka Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- hw/xenfb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/xenfb.c b/hw/xenfb.c index ef24c3315c..442a63a320 100644 --- a/hw/xenfb.c +++ b/hw/xenfb.c @@ -648,7 +648,7 @@ static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h) xen_be_printf(&xenfb->c.xendev, 0, "%s: oops: convert %d -> %d bpp?\n", __FUNCTION__, xenfb->depth, bpp); - dpy_update(xenfb->c.ds, x, y, w, h); + dpy_gfx_update(xenfb->c.ds, x, y, w, h); } #ifdef XENFB_TYPE_REFRESH_PERIOD @@ -766,7 +766,7 @@ static void xenfb_update(void *opaque) xen_be_printf(&xenfb->c.xendev, 1, "update: resizing: %dx%d @ %d bpp%s\n", xenfb->width, xenfb->height, xenfb->depth, is_buffer_shared(xenfb->c.ds->surface) ? " (shared)" : ""); - dpy_resize(xenfb->c.ds); + dpy_gfx_resize(xenfb->c.ds); xenfb->up_fullscreen = 1; } From 1d8ddda045b4b72dc95a325debb6df0fc19ec821 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 2 Nov 2012 14:54:43 +0000 Subject: [PATCH 1505/2270] ui/cocoa.m: Update to new DisplayChangeListener member names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit a93a4a2 changed the names of some fields in DisplayChangeListener and broke compilation of the cocoa UI. Update to the new names. Acked-by: Gerd Hoffmann Reviewed-by: Andreas Färber Signed-off-by: Peter Maydell Signed-off-by: Anthony Liguori --- ui/cocoa.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index 2383646dc0..87d2e44c69 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -1017,8 +1017,8 @@ void cocoa_display_init(DisplayState *ds, int full_screen) dcl = g_malloc0(sizeof(DisplayChangeListener)); // register vga output callbacks - dcl->dpy_update = cocoa_update; - dcl->dpy_resize = cocoa_resize; + dcl->dpy_gfx_update = cocoa_update; + dcl->dpy_gfx_resize = cocoa_resize; dcl->dpy_refresh = cocoa_refresh; register_displaychangelistener(ds, dcl); From e4ab0d6b0d1118a90238d8194eedb91aab15ebe1 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Fri, 2 Nov 2012 14:25:15 -0200 Subject: [PATCH 1506/2270] target-i386: cpu: fix --disable-kvm compilation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the following: target-i386/cpu.o: In function `kvm_cpu_fill_host': target-i386/cpu.c:783: undefined reference to `kvm_state' I didn't notice the problem before because GCC was optimizing the entire kvm_cpu_fill_host() function out (because all calls are conditional on kvm_enabled()). * cpu_x86_fill_model_id() is used only if CONFIG_KVM is set, so #ifdef it entirely to avoid compiler warnings. * kvm_cpu_fill_host() should be called only if KVM is enabled, so use #ifdef CONFIG_KVM around the entire function body. Reported-by: Andreas Färber Signed-off-by: Eduardo Habkost Signed-off-by: Andreas Färber --- target-i386/cpu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index c46286ab3e..e1db639295 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -758,6 +758,7 @@ static x86_def_t builtin_x86_defs[] = { }, }; +#ifdef CONFIG_KVM static int cpu_x86_fill_model_id(char *str) { uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; @@ -772,6 +773,7 @@ static int cpu_x86_fill_model_id(char *str) } return 0; } +#endif /* Fill a x86_def_t struct with information about the host CPU, and * the CPU features supported by the host hardware + host kernel @@ -780,6 +782,7 @@ static int cpu_x86_fill_model_id(char *str) */ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) { +#ifdef CONFIG_KVM KVMState *s = kvm_state; uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; @@ -838,6 +841,7 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) * unsupported ones later. */ x86_cpu_def->svm_features = -1; +#endif /* CONFIG_KVM */ } static int unavailable_host_feature(struct model_features_t *f, uint32_t mask) From 5f0ebf1b4d58be0c0bb05beb195b6f42942eeee8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 21 Sep 2012 12:04:03 +0200 Subject: [PATCH 1507/2270] migration: unify stdio-based QEMUFile operations Now that qemu_fseek does not exist anymore, there is no reason to do an fseek before fread/fwrite when operating on an stdio file. Thus, unify the get/put_buffer callbacks used by qemu_fopen with those used for pipes. Reviewed-by: Orit Wasserman Signed-off-by: Paolo Bonzini --- savevm.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/savevm.c b/savevm.c index 43d3d1bbeb..cfcf91847d 100644 --- a/savevm.c +++ b/savevm.c @@ -343,21 +343,6 @@ QEMUFile *qemu_fopen_socket(int fd) return s->file; } -static int file_put_buffer(void *opaque, const uint8_t *buf, - int64_t pos, int size) -{ - QEMUFileStdio *s = opaque; - fseek(s->stdio_file, pos, SEEK_SET); - return fwrite(buf, 1, size, s->stdio_file); -} - -static int file_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) -{ - QEMUFileStdio *s = opaque; - fseek(s->stdio_file, pos, SEEK_SET); - return fread(buf, 1, size, s->stdio_file); -} - QEMUFile *qemu_fopen(const char *filename, const char *mode) { QEMUFileStdio *s; @@ -376,10 +361,10 @@ QEMUFile *qemu_fopen(const char *filename, const char *mode) goto fail; if(mode[0] == 'w') { - s->file = qemu_fopen_ops(s, file_put_buffer, NULL, stdio_fclose, + s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_fclose, NULL, NULL, NULL); } else { - s->file = qemu_fopen_ops(s, NULL, file_get_buffer, stdio_fclose, + s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_fclose, NULL, NULL, NULL); } return s->file; From 9229bf3c2d7afcd1adce7258843d9bc82b066b08 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 8 Aug 2012 10:15:15 +0200 Subject: [PATCH 1508/2270] migration: consolidate QEMUFile methods in a single QEMUFileOps struct Reviewed-by: Orit Wasserman Signed-off-by: Paolo Bonzini --- buffered_file.c | 13 ++++-- qemu-file.h | 16 ++++--- savevm.c | 108 +++++++++++++++++++++++++++--------------------- 3 files changed, 79 insertions(+), 58 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index ed92df1053..a5c0b128e0 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -234,6 +234,14 @@ static void buffered_rate_tick(void *opaque) buffered_put_buffer(s, NULL, 0, 0); } +static const QEMUFileOps buffered_file_ops = { + .put_buffer = buffered_put_buffer, + .close = buffered_close, + .rate_limit = buffered_rate_limit, + .get_rate_limit = buffered_get_rate_limit, + .set_rate_limit = buffered_set_rate_limit, +}; + QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state) { QEMUFileBuffered *s; @@ -243,10 +251,7 @@ QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state) s->migration_state = migration_state; s->xfer_limit = migration_state->bandwidth_limit / 10; - s->file = qemu_fopen_ops(s, buffered_put_buffer, NULL, - buffered_close, buffered_rate_limit, - buffered_set_rate_limit, - buffered_get_rate_limit); + s->file = qemu_fopen_ops(s, &buffered_file_ops); s->timer = qemu_new_timer_ms(rt_clock, buffered_rate_tick, s); diff --git a/qemu-file.h b/qemu-file.h index 9c8985b610..c89e8e09dc 100644 --- a/qemu-file.h +++ b/qemu-file.h @@ -59,12 +59,16 @@ typedef int (QEMUFileRateLimit)(void *opaque); typedef int64_t (QEMUFileSetRateLimit)(void *opaque, int64_t new_rate); typedef int64_t (QEMUFileGetRateLimit)(void *opaque); -QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer, - QEMUFileGetBufferFunc *get_buffer, - QEMUFileCloseFunc *close, - QEMUFileRateLimit *rate_limit, - QEMUFileSetRateLimit *set_rate_limit, - QEMUFileGetRateLimit *get_rate_limit); +typedef struct QEMUFileOps { + QEMUFilePutBufferFunc *put_buffer; + QEMUFileGetBufferFunc *get_buffer; + QEMUFileCloseFunc *close; + QEMUFileRateLimit *rate_limit; + QEMUFileSetRateLimit *set_rate_limit; + QEMUFileGetRateLimit *get_rate_limit; +} QEMUFileOps; + +QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops); QEMUFile *qemu_fopen(const char *filename, const char *mode); QEMUFile *qemu_fdopen(int fd, const char *mode); QEMUFile *qemu_fopen_socket(int fd); diff --git a/savevm.c b/savevm.c index cfcf91847d..a4158ecbf7 100644 --- a/savevm.c +++ b/savevm.c @@ -163,12 +163,7 @@ void qemu_announce_self(void) #define IO_BUF_SIZE 32768 struct QEMUFile { - QEMUFilePutBufferFunc *put_buffer; - QEMUFileGetBufferFunc *get_buffer; - QEMUFileCloseFunc *close; - QEMUFileRateLimit *rate_limit; - QEMUFileSetRateLimit *set_rate_limit; - QEMUFileGetRateLimit *get_rate_limit; + const QEMUFileOps *ops; void *opaque; int is_write; @@ -257,6 +252,16 @@ static int stdio_fclose(void *opaque) return ret; } +static const QEMUFileOps stdio_pipe_read_ops = { + .get_buffer = stdio_get_buffer, + .close = stdio_pclose +}; + +static const QEMUFileOps stdio_pipe_write_ops = { + .put_buffer = stdio_put_buffer, + .close = stdio_pclose +}; + QEMUFile *qemu_popen(FILE *stdio_file, const char *mode) { QEMUFileStdio *s; @@ -271,11 +276,9 @@ QEMUFile *qemu_popen(FILE *stdio_file, const char *mode) s->stdio_file = stdio_file; if(mode[0] == 'r') { - s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_pclose, - NULL, NULL, NULL); + s->file = qemu_fopen_ops(s, &stdio_pipe_read_ops); } else { - s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_pclose, - NULL, NULL, NULL); + s->file = qemu_fopen_ops(s, &stdio_pipe_write_ops); } return s->file; } @@ -303,6 +306,16 @@ int qemu_stdio_fd(QEMUFile *f) return fd; } +static const QEMUFileOps stdio_file_read_ops = { + .get_buffer = stdio_get_buffer, + .close = stdio_fclose +}; + +static const QEMUFileOps stdio_file_write_ops = { + .put_buffer = stdio_put_buffer, + .close = stdio_fclose +}; + QEMUFile *qemu_fdopen(int fd, const char *mode) { QEMUFileStdio *s; @@ -320,11 +333,9 @@ QEMUFile *qemu_fdopen(int fd, const char *mode) goto fail; if(mode[0] == 'r') { - s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_fclose, - NULL, NULL, NULL); + s->file = qemu_fopen_ops(s, &stdio_file_read_ops); } else { - s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_fclose, - NULL, NULL, NULL); + s->file = qemu_fopen_ops(s, &stdio_file_write_ops); } return s->file; @@ -333,13 +344,17 @@ fail: return NULL; } +static const QEMUFileOps socket_read_ops = { + .get_buffer = socket_get_buffer, + .close = socket_close +}; + QEMUFile *qemu_fopen_socket(int fd) { QEMUFileSocket *s = g_malloc0(sizeof(QEMUFileSocket)); s->fd = fd; - s->file = qemu_fopen_ops(s, NULL, socket_get_buffer, socket_close, - NULL, NULL, NULL); + s->file = qemu_fopen_ops(s, &socket_read_ops); return s->file; } @@ -361,11 +376,9 @@ QEMUFile *qemu_fopen(const char *filename, const char *mode) goto fail; if(mode[0] == 'w') { - s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_fclose, - NULL, NULL, NULL); + s->file = qemu_fopen_ops(s, &stdio_file_write_ops); } else { - s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_fclose, - NULL, NULL, NULL); + s->file = qemu_fopen_ops(s, &stdio_file_read_ops); } return s->file; fail: @@ -390,32 +403,31 @@ static int bdrv_fclose(void *opaque) return bdrv_flush(opaque); } +static const QEMUFileOps bdrv_read_ops = { + .get_buffer = block_get_buffer, + .close = bdrv_fclose +}; + +static const QEMUFileOps bdrv_write_ops = { + .put_buffer = block_put_buffer, + .close = bdrv_fclose +}; + static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable) { if (is_writable) - return qemu_fopen_ops(bs, block_put_buffer, NULL, bdrv_fclose, - NULL, NULL, NULL); - return qemu_fopen_ops(bs, NULL, block_get_buffer, bdrv_fclose, NULL, NULL, NULL); + return qemu_fopen_ops(bs, &bdrv_write_ops); + return qemu_fopen_ops(bs, &bdrv_read_ops); } -QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer, - QEMUFileGetBufferFunc *get_buffer, - QEMUFileCloseFunc *close, - QEMUFileRateLimit *rate_limit, - QEMUFileSetRateLimit *set_rate_limit, - QEMUFileGetRateLimit *get_rate_limit) +QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops) { QEMUFile *f; f = g_malloc0(sizeof(QEMUFile)); f->opaque = opaque; - f->put_buffer = put_buffer; - f->get_buffer = get_buffer; - f->close = close; - f->rate_limit = rate_limit; - f->set_rate_limit = set_rate_limit; - f->get_rate_limit = get_rate_limit; + f->ops = ops; f->is_write = 0; return f; @@ -438,11 +450,11 @@ static int qemu_fflush(QEMUFile *f) { int ret = 0; - if (!f->put_buffer) + if (!f->ops->put_buffer) return 0; if (f->is_write && f->buf_index > 0) { - ret = f->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index); + ret = f->ops->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index); if (ret >= 0) { f->buf_offset += f->buf_index; } @@ -456,7 +468,7 @@ static void qemu_fill_buffer(QEMUFile *f) int len; int pending; - if (!f->get_buffer) + if (!f->ops->get_buffer) return; if (f->is_write) @@ -469,7 +481,7 @@ static void qemu_fill_buffer(QEMUFile *f) f->buf_index = 0; f->buf_size = pending; - len = f->get_buffer(f->opaque, f->buf + pending, f->buf_offset, + len = f->ops->get_buffer(f->opaque, f->buf + pending, f->buf_offset, IO_BUF_SIZE - pending); if (len > 0) { f->buf_size += len; @@ -493,8 +505,8 @@ int qemu_fclose(QEMUFile *f) int ret; ret = qemu_fflush(f); - if (f->close) { - int ret2 = f->close(f->opaque); + if (f->ops->close) { + int ret2 = f->ops->close(f->opaque); if (ret >= 0) { ret = ret2; } @@ -511,7 +523,7 @@ int qemu_fclose(QEMUFile *f) int qemu_file_put_notify(QEMUFile *f) { - return f->put_buffer(f->opaque, NULL, 0, 0); + return f->ops->put_buffer(f->opaque, NULL, 0, 0); } void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) @@ -658,16 +670,16 @@ static int64_t qemu_ftell(QEMUFile *f) int qemu_file_rate_limit(QEMUFile *f) { - if (f->rate_limit) - return f->rate_limit(f->opaque); + if (f->ops->rate_limit) + return f->ops->rate_limit(f->opaque); return 0; } int64_t qemu_file_get_rate_limit(QEMUFile *f) { - if (f->get_rate_limit) - return f->get_rate_limit(f->opaque); + if (f->ops->get_rate_limit) + return f->ops->get_rate_limit(f->opaque); return 0; } @@ -676,8 +688,8 @@ int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate) { /* any failed or completed migration keeps its state to allow probing of * migration data, but has no associated file anymore */ - if (f && f->set_rate_limit) - return f->set_rate_limit(f->opaque, new_rate); + if (f && f->ops->set_rate_limit) + return f->ops->set_rate_limit(f->opaque, new_rate); return 0; } From 70eb6330343ebc61e5fb22be3d137df40f4bb058 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 8 Aug 2012 10:20:18 +0200 Subject: [PATCH 1509/2270] migration: add qemu_get_fd Reviewed-by: Orit Wasserman Signed-off-by: Paolo Bonzini --- buffered_file.c | 8 ++++++++ qemu-file.h | 6 ++++++ savevm.c | 27 +++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/buffered_file.c b/buffered_file.c index a5c0b128e0..bd0f61d8c9 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -174,6 +174,13 @@ static int buffered_close(void *opaque) * 1: Time to stop * negative: There has been an error */ +static int buffered_get_fd(void *opaque) +{ + QEMUFileBuffered *s = opaque; + + return qemu_get_fd(s->file); +} + static int buffered_rate_limit(void *opaque) { QEMUFileBuffered *s = opaque; @@ -235,6 +242,7 @@ static void buffered_rate_tick(void *opaque) } static const QEMUFileOps buffered_file_ops = { + .get_fd = buffered_get_fd, .put_buffer = buffered_put_buffer, .close = buffered_close, .rate_limit = buffered_rate_limit, diff --git a/qemu-file.h b/qemu-file.h index c89e8e09dc..d552f5d906 100644 --- a/qemu-file.h +++ b/qemu-file.h @@ -47,6 +47,10 @@ typedef int (QEMUFileGetBufferFunc)(void *opaque, uint8_t *buf, */ typedef int (QEMUFileCloseFunc)(void *opaque); +/* Called to return the OS file descriptor associated to the QEMUFile. + */ +typedef int (QEMUFileGetFD)(void *opaque); + /* Called to determine if the file has exceeded its bandwidth allocation. The * bandwidth capping is a soft limit, not a hard limit. */ @@ -63,6 +67,7 @@ typedef struct QEMUFileOps { QEMUFilePutBufferFunc *put_buffer; QEMUFileGetBufferFunc *get_buffer; QEMUFileCloseFunc *close; + QEMUFileGetFD *get_fd; QEMUFileRateLimit *rate_limit; QEMUFileSetRateLimit *set_rate_limit; QEMUFileGetRateLimit *get_rate_limit; @@ -74,6 +79,7 @@ QEMUFile *qemu_fdopen(int fd, const char *mode); QEMUFile *qemu_fopen_socket(int fd); QEMUFile *qemu_popen(FILE *popen_file, const char *mode); QEMUFile *qemu_popen_cmd(const char *command, const char *mode); +int qemu_get_fd(QEMUFile *f); int qemu_stdio_fd(QEMUFile *f); int qemu_fclose(QEMUFile *f); void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size); diff --git a/savevm.c b/savevm.c index a4158ecbf7..a58fe9ac49 100644 --- a/savevm.c +++ b/savevm.c @@ -188,6 +188,13 @@ typedef struct QEMUFileSocket QEMUFile *file; } QEMUFileSocket; +static int socket_get_fd(void *opaque) +{ + QEMUFileSocket *s = opaque; + + return s->fd; +} + static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) { QEMUFileSocket *s = opaque; @@ -210,6 +217,13 @@ static int socket_close(void *opaque) return 0; } +static int stdio_get_fd(void *opaque) +{ + QEMUFileStdio *s = opaque; + + return fileno(s->stdio_file); +} + static int stdio_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size) { QEMUFileStdio *s = opaque; @@ -253,11 +267,13 @@ static int stdio_fclose(void *opaque) } static const QEMUFileOps stdio_pipe_read_ops = { + .get_fd = stdio_get_fd, .get_buffer = stdio_get_buffer, .close = stdio_pclose }; static const QEMUFileOps stdio_pipe_write_ops = { + .get_fd = stdio_get_fd, .put_buffer = stdio_put_buffer, .close = stdio_pclose }; @@ -307,11 +323,13 @@ int qemu_stdio_fd(QEMUFile *f) } static const QEMUFileOps stdio_file_read_ops = { + .get_fd = stdio_get_fd, .get_buffer = stdio_get_buffer, .close = stdio_fclose }; static const QEMUFileOps stdio_file_write_ops = { + .get_fd = stdio_get_fd, .put_buffer = stdio_put_buffer, .close = stdio_fclose }; @@ -345,6 +363,7 @@ fail: } static const QEMUFileOps socket_read_ops = { + .get_fd = socket_get_fd, .get_buffer = socket_get_buffer, .close = socket_close }; @@ -492,6 +511,14 @@ static void qemu_fill_buffer(QEMUFile *f) qemu_file_set_error(f, len); } +int qemu_get_fd(QEMUFile *f) +{ + if (f->ops->get_fd) { + return f->ops->get_fd(f->opaque); + } + return -1; +} + /** Closes the file * * Returns negative error value if any error happened on previous operations or From d263a20bcfc94a59c87176df6c2d29d65a7e4e6a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 8 Aug 2012 10:21:26 +0200 Subject: [PATCH 1510/2270] migration: replace qemu_stdio_fd with qemu_get_fd Reviewed-by: Orit Wasserman Signed-off-by: Paolo Bonzini --- migration-exec.c | 4 ++-- migration-fd.c | 2 +- qemu-file.h | 1 - savevm.c | 11 ----------- 4 files changed, 3 insertions(+), 15 deletions(-) diff --git a/migration-exec.c b/migration-exec.c index 519af57ac7..452bf071f1 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -88,7 +88,7 @@ static void exec_accept_incoming_migration(void *opaque) QEMUFile *f = opaque; process_incoming_migration(f); - qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL); + qemu_set_fd_handler2(qemu_get_fd(f), NULL, NULL, NULL, NULL); qemu_fclose(f); } @@ -103,6 +103,6 @@ void exec_start_incoming_migration(const char *command, Error **errp) return; } - qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, + qemu_set_fd_handler2(qemu_get_fd(f), NULL, exec_accept_incoming_migration, NULL, f); } diff --git a/migration-fd.c b/migration-fd.c index ce6932d7c3..b47b222e88 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -93,7 +93,7 @@ static void fd_accept_incoming_migration(void *opaque) QEMUFile *f = opaque; process_incoming_migration(f); - qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL); + qemu_set_fd_handler2(qemu_get_fd(f), NULL, NULL, NULL, NULL); qemu_fclose(f); } diff --git a/qemu-file.h b/qemu-file.h index d552f5d906..d64bdbb19b 100644 --- a/qemu-file.h +++ b/qemu-file.h @@ -80,7 +80,6 @@ QEMUFile *qemu_fopen_socket(int fd); QEMUFile *qemu_popen(FILE *popen_file, const char *mode); QEMUFile *qemu_popen_cmd(const char *command, const char *mode); int qemu_get_fd(QEMUFile *f); -int qemu_stdio_fd(QEMUFile *f); int qemu_fclose(QEMUFile *f); void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size); void qemu_put_byte(QEMUFile *f, int v); diff --git a/savevm.c b/savevm.c index a58fe9ac49..0ab1ad4afd 100644 --- a/savevm.c +++ b/savevm.c @@ -311,17 +311,6 @@ QEMUFile *qemu_popen_cmd(const char *command, const char *mode) return qemu_popen(popen_file, mode); } -int qemu_stdio_fd(QEMUFile *f) -{ - QEMUFileStdio *p; - int fd; - - p = (QEMUFileStdio *)f->opaque; - fd = fileno(p->stdio_file); - - return fd; -} - static const QEMUFileOps stdio_file_read_ops = { .get_fd = stdio_get_fd, .get_buffer = stdio_get_buffer, From a6ef29096b89640acaa5edc3a74c2e3efbfa306f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 7 Aug 2012 10:49:13 +0200 Subject: [PATCH 1511/2270] migration: clean up server sockets and handlers before invoking process_incoming_migration A first step towards making a common "suffix" for all migration protocols, and moving it to process_incoming_migration. Reviewed-by: Orit Wasserman Signed-off-by: Paolo Bonzini --- migration-exec.c | 2 +- migration-fd.c | 2 +- migration-tcp.c | 7 +++---- migration-unix.c | 7 +++---- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/migration-exec.c b/migration-exec.c index 452bf071f1..014c60f01d 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -87,8 +87,8 @@ static void exec_accept_incoming_migration(void *opaque) { QEMUFile *f = opaque; - process_incoming_migration(f); qemu_set_fd_handler2(qemu_get_fd(f), NULL, NULL, NULL, NULL); + process_incoming_migration(f); qemu_fclose(f); } diff --git a/migration-fd.c b/migration-fd.c index b47b222e88..a4cd83ff7c 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -92,8 +92,8 @@ static void fd_accept_incoming_migration(void *opaque) { QEMUFile *f = opaque; - process_incoming_migration(f); qemu_set_fd_handler2(qemu_get_fd(f), NULL, NULL, NULL, NULL); + process_incoming_migration(f); qemu_fclose(f); } diff --git a/migration-tcp.c b/migration-tcp.c index 46f6ac545c..96a832caa8 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -88,12 +88,14 @@ static void tcp_accept_incoming_migration(void *opaque) do { c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen); } while (c == -1 && socket_error() == EINTR); + qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL); + close(s); DPRINTF("accepted migration\n"); if (c == -1) { fprintf(stderr, "could not accept migration connection\n"); - goto out2; + goto out; } f = qemu_fopen_socket(c); @@ -106,9 +108,6 @@ static void tcp_accept_incoming_migration(void *opaque) qemu_fclose(f); out: close(c); -out2: - qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL); - close(s); } void tcp_start_incoming_migration(const char *host_port, Error **errp) diff --git a/migration-unix.c b/migration-unix.c index ed3db3a39a..5dc49cdf0f 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -88,12 +88,14 @@ static void unix_accept_incoming_migration(void *opaque) do { c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen); } while (c == -1 && errno == EINTR); + qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL); + close(s); DPRINTF("accepted migration\n"); if (c == -1) { fprintf(stderr, "could not accept migration connection\n"); - goto out2; + goto out; } f = qemu_fopen_socket(c); @@ -106,9 +108,6 @@ static void unix_accept_incoming_migration(void *opaque) qemu_fclose(f); out: close(c); -out2: - qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL); - close(s); } void unix_start_incoming_migration(const char *path, Error **errp) From 8dc592e620b45c4745380b0694ec1aedc073bda2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 27 Sep 2012 13:25:45 +0200 Subject: [PATCH 1512/2270] migration: use migrate_fd_close in migrate_fd_cleanup migrate_fd_cleanup will usually close the file descriptor via buffered_file_close's call to migrate_fd_close. However, in the case of s->file == NULL it is "inlining" migrate_fd_close (almost: there is a direct close() instead of using s->close(s)). To fix the inconsistency and clean up the code, allow multiple calls to migrate_fd_close and use the function in migrate_fd_cleanup. Signed-off-by: Paolo Bonzini --- migration.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/migration.c b/migration.c index 300ab75aaf..a63596f9a0 100644 --- a/migration.c +++ b/migration.c @@ -243,21 +243,13 @@ static int migrate_fd_cleanup(MigrationState *s) { int ret = 0; - if (s->fd != -1) { - qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); - } - if (s->file) { DPRINTF("closing file\n"); ret = qemu_fclose(s->file); s->file = NULL; } - if (s->fd != -1) { - close(s->fd); - s->fd = -1; - } - + migrate_fd_close(s); return ret; } @@ -393,8 +385,13 @@ int migrate_fd_wait_for_unfreeze(MigrationState *s) int migrate_fd_close(MigrationState *s) { - qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); - return s->close(s); + int rc = 0; + if (s->fd != -1) { + qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); + rc = s->close(s); + s->fd = -1; + } + return rc; } void add_migration_state_change_notifier(Notifier *notify) From 09bac73c13b57acd304efb54a361c244d60d375c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 27 Sep 2012 13:33:08 +0200 Subject: [PATCH 1513/2270] migration: use closesocket, not close Windows requires this. Migration does not quite work under Windows but let's be uniform across QEMU. Reviewed-by: Orit Wasserman Signed-off-by: Paolo Bonzini --- migration-tcp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/migration-tcp.c b/migration-tcp.c index 96a832caa8..1a12f17886 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -45,7 +45,7 @@ static int tcp_close(MigrationState *s) int r = 0; DPRINTF("tcp_close\n"); if (s->fd != -1) { - if (close(s->fd) < 0) { + if (closesocket(s->fd) < 0) { r = -errno; } s->fd = -1; @@ -89,7 +89,7 @@ static void tcp_accept_incoming_migration(void *opaque) c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen); } while (c == -1 && socket_error() == EINTR); qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL); - close(s); + closesocket(s); DPRINTF("accepted migration\n"); @@ -107,7 +107,7 @@ static void tcp_accept_incoming_migration(void *opaque) process_incoming_migration(f); qemu_fclose(f); out: - close(c); + closesocket(c); } void tcp_start_incoming_migration(const char *host_port, Error **errp) From 6c3601361ff22cb8bda3f483ea11c4f7bd095094 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 27 Sep 2012 13:30:15 +0200 Subject: [PATCH 1514/2270] migration: xxx_close will only be called once No need to test s->fd again, it is tested in the caller. Reviewed-by: Orit Wasserman Signed-off-by: Paolo Bonzini --- migration-exec.c | 14 ++++++-------- migration-fd.c | 33 +++++++++++++++------------------ migration-tcp.c | 7 ++----- migration-unix.c | 7 ++----- 4 files changed, 25 insertions(+), 36 deletions(-) diff --git a/migration-exec.c b/migration-exec.c index 014c60f01d..2ce7770cfa 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -48,14 +48,12 @@ static int exec_close(MigrationState *s) { int ret = 0; DPRINTF("exec_close\n"); - if (s->opaque) { - ret = qemu_fclose(s->opaque); - s->opaque = NULL; - s->fd = -1; - if (ret >= 0 && !(WIFEXITED(ret) && WEXITSTATUS(ret) == 0)) { - /* close succeeded, but non-zero exit code: */ - ret = -EIO; /* fake errno value */ - } + ret = qemu_fclose(s->opaque); + s->opaque = NULL; + s->fd = -1; + if (ret >= 0 && !(WIFEXITED(ret) && WEXITSTATUS(ret) == 0)) { + /* close succeeded, but non-zero exit code: */ + ret = -EIO; /* fake errno value */ } return ret; } diff --git a/migration-fd.c b/migration-fd.c index a4cd83ff7c..c678b23b7e 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -48,29 +48,26 @@ static int fd_close(MigrationState *s) int ret; DPRINTF("fd_close\n"); - if (s->fd != -1) { - ret = fstat(s->fd, &st); - if (ret == 0 && S_ISREG(st.st_mode)) { - /* - * If the file handle is a regular file make sure the - * data is flushed to disk before signaling success. - */ - ret = fsync(s->fd); - if (ret != 0) { - ret = -errno; - perror("migration-fd: fsync"); - return ret; - } - } - ret = close(s->fd); - s->fd = -1; + ret = fstat(s->fd, &st); + if (ret == 0 && S_ISREG(st.st_mode)) { + /* + * If the file handle is a regular file make sure the + * data is flushed to disk before signaling success. + */ + ret = fsync(s->fd); if (ret != 0) { ret = -errno; - perror("migration-fd: close"); + perror("migration-fd: fsync"); return ret; } } - return 0; + ret = close(s->fd); + s->fd = -1; + if (ret != 0) { + ret = -errno; + perror("migration-fd: close"); + } + return ret; } void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp) diff --git a/migration-tcp.c b/migration-tcp.c index 1a12f17886..bb27ce832a 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -44,11 +44,8 @@ static int tcp_close(MigrationState *s) { int r = 0; DPRINTF("tcp_close\n"); - if (s->fd != -1) { - if (closesocket(s->fd) < 0) { - r = -errno; - } - s->fd = -1; + if (closesocket(s->fd) < 0) { + r = -socket_error(); } return r; } diff --git a/migration-unix.c b/migration-unix.c index 5dc49cdf0f..9b5521edec 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -44,11 +44,8 @@ static int unix_close(MigrationState *s) { int r = 0; DPRINTF("unix_close\n"); - if (s->fd != -1) { - if (close(s->fd) < 0) { - r = -errno; - } - s->fd = -1; + if (close(s->fd) < 0) { + r = -errno; } return r; } From ab52a824a496f4459539a9a11152d6da68703ea0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 7 Aug 2012 10:50:26 +0200 Subject: [PATCH 1515/2270] migration: close socket QEMUFile from socket_close The common suffix now is process_incoming_migration+qemu_fclose. Reviewed-by: Orit Wasserman Signed-off-by: Paolo Bonzini --- migration-tcp.c | 2 ++ migration-unix.c | 2 ++ savevm.c | 1 + 3 files changed, 5 insertions(+) diff --git a/migration-tcp.c b/migration-tcp.c index bb27ce832a..1279cc9677 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -103,6 +103,8 @@ static void tcp_accept_incoming_migration(void *opaque) process_incoming_migration(f); qemu_fclose(f); + return; + out: closesocket(c); } diff --git a/migration-unix.c b/migration-unix.c index 9b5521edec..96ea71b787 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -103,6 +103,8 @@ static void unix_accept_incoming_migration(void *opaque) process_incoming_migration(f); qemu_fclose(f); + return; + out: close(c); } diff --git a/savevm.c b/savevm.c index 0ab1ad4afd..cdad3ad8e4 100644 --- a/savevm.c +++ b/savevm.c @@ -213,6 +213,7 @@ static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) static int socket_close(void *opaque) { QEMUFileSocket *s = opaque; + closesocket(s->fd); g_free(s); return 0; } From 1c12e1f5b2ce215ee25b4a4e365e76269edf911c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 7 Aug 2012 10:51:51 +0200 Subject: [PATCH 1516/2270] migration: move qemu_fclose to process_incoming_migration The common suffix is now just process_incoming_migration. Reviewed-by: Orit Wasserman Signed-off-by: Paolo Bonzini --- migration-exec.c | 1 - migration-fd.c | 1 - migration-tcp.c | 1 - migration-unix.c | 1 - migration.c | 6 +++++- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/migration-exec.c b/migration-exec.c index 2ce7770cfa..2b6fcb4262 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -87,7 +87,6 @@ static void exec_accept_incoming_migration(void *opaque) qemu_set_fd_handler2(qemu_get_fd(f), NULL, NULL, NULL, NULL); process_incoming_migration(f); - qemu_fclose(f); } void exec_start_incoming_migration(const char *command, Error **errp) diff --git a/migration-fd.c b/migration-fd.c index c678b23b7e..5fe28e09fd 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -91,7 +91,6 @@ static void fd_accept_incoming_migration(void *opaque) qemu_set_fd_handler2(qemu_get_fd(f), NULL, NULL, NULL, NULL); process_incoming_migration(f); - qemu_fclose(f); } void fd_start_incoming_migration(const char *infd, Error **errp) diff --git a/migration-tcp.c b/migration-tcp.c index 1279cc9677..5e855fe72f 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -102,7 +102,6 @@ static void tcp_accept_incoming_migration(void *opaque) } process_incoming_migration(f); - qemu_fclose(f); return; out: diff --git a/migration-unix.c b/migration-unix.c index 96ea71b787..dba72b4a54 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -102,7 +102,6 @@ static void unix_accept_incoming_migration(void *opaque) } process_incoming_migration(f); - qemu_fclose(f); return; out: diff --git a/migration.c b/migration.c index a63596f9a0..2741d979fc 100644 --- a/migration.c +++ b/migration.c @@ -85,7 +85,11 @@ void qemu_start_incoming_migration(const char *uri, Error **errp) void process_incoming_migration(QEMUFile *f) { - if (qemu_loadvm_state(f) < 0) { + int ret; + + ret = qemu_loadvm_state(f); + qemu_fclose(f); + if (ret < 0) { fprintf(stderr, "load of migration failed\n"); exit(0); } From 595ab64169be9063d64c3b1aa1c249fbe2662221 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 7 Aug 2012 11:07:59 +0200 Subject: [PATCH 1517/2270] migration: handle EAGAIN while reading QEMUFile This will never happen right now (the assertion would fail). The next patch will set the socket or pipe in non-blocking mode, thus enabling this part of the code. Coroutines can just stop whenever they want with qemu_coroutine_yield. As soon as select tells the main loop that the migration stream is readable, the coroutine is re-entered directly in qemu_get_buffer, where it will read more data and pass it to the loading routines. Signed-off-by: Paolo Bonzini --- savevm.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/savevm.c b/savevm.c index cdad3ad8e4..5d04d59688 100644 --- a/savevm.c +++ b/savevm.c @@ -200,13 +200,22 @@ static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) QEMUFileSocket *s = opaque; ssize_t len; - do { + for (;;) { len = qemu_recv(s->fd, buf, size, 0); - } while (len == -1 && socket_error() == EINTR); + if (len != -1) { + break; + } + if (socket_error() == EAGAIN) { + assert(qemu_in_coroutine()); + qemu_coroutine_yield(); + } else if (socket_error() != EINTR) { + break; + } + } - if (len == -1) + if (len == -1) { len = -socket_error(); - + } return len; } @@ -237,10 +246,19 @@ static int stdio_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) FILE *fp = s->stdio_file; int bytes; - do { + for (;;) { clearerr(fp); bytes = fread(buf, 1, size, fp); - } while ((bytes == 0) && ferror(fp) && (errno == EINTR)); + if (bytes != 0 || !ferror(fp)) { + break; + } + if (errno == EAGAIN) { + assert(qemu_in_coroutine()); + qemu_coroutine_yield(); + } else if (errno != EINTR) { + break; + } + } return bytes; } From 82a4da79fd6c108400637143f8439c2364bdb21e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 7 Aug 2012 10:57:43 +0200 Subject: [PATCH 1518/2270] migration: move process_incoming_migration to a coroutine The final part of incoming migration, which now consists of process_incoming_migration for all protocols, is thus made non-blocking. Reviewed-by: Orit Wasserman Signed-off-by: Paolo Bonzini --- migration.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/migration.c b/migration.c index 2741d979fc..73ce170ddf 100644 --- a/migration.c +++ b/migration.c @@ -83,11 +83,13 @@ void qemu_start_incoming_migration(const char *uri, Error **errp) } } -void process_incoming_migration(QEMUFile *f) +static void process_incoming_migration_co(void *opaque) { + QEMUFile *f = opaque; int ret; ret = qemu_loadvm_state(f); + qemu_set_fd_handler(qemu_get_fd(f), NULL, NULL, NULL); qemu_fclose(f); if (ret < 0) { fprintf(stderr, "load of migration failed\n"); @@ -107,6 +109,23 @@ void process_incoming_migration(QEMUFile *f) } } +static void enter_migration_coroutine(void *opaque) +{ + Coroutine *co = opaque; + qemu_coroutine_enter(co, NULL); +} + +void process_incoming_migration(QEMUFile *f) +{ + Coroutine *co = qemu_coroutine_create(process_incoming_migration_co); + int fd = qemu_get_fd(f); + + assert(fd != -1); + socket_set_nonblock(fd); + qemu_set_fd_handler(fd, enter_migration_coroutine, NULL, co); + qemu_coroutine_enter(co, f); +} + /* amount of nanoseconds we are willing to wait for migration to be down. * the choice of nanoseconds is because it is the maximum resolution that * get_clock() can achieve. It is an internal measure. All user-visible From 1f001dc7bc9e435bf231a5b0edcad1c7c2bd6214 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 2 Nov 2012 15:43:20 +0100 Subject: [PATCH 1519/2270] compiler: support Darwin weak references Weakrefs only tell you if the symbol was defined elsewhere, so you need a further check at runtime to pick the default definition when needed. This could be automated by the compiler, but it does not do it. Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- compiler.h | 9 +++++++- osdep.c | 56 ++++++++++++++++++++++++++++---------------------- oslib-win32.c | 12 ++++++----- qemu-sockets.c | 40 ++++++++++++++++++++---------------- qmp.c | 2 ++ 5 files changed, 71 insertions(+), 48 deletions(-) diff --git a/compiler.h b/compiler.h index 58865d65e8..55d7d74775 100644 --- a/compiler.h +++ b/compiler.h @@ -50,8 +50,15 @@ # define __printf__ __gnu_printf__ # endif # endif -# define QEMU_WEAK_ALIAS(newname, oldname) \ +# if defined(__APPLE__) +# define QEMU_WEAK_ALIAS(newname, oldname) \ + static typeof(oldname) weak_##newname __attribute__((unused, weakref(#oldname))) +# define QEMU_WEAK_REF(newname, oldname) (weak_##newname ? weak_##newname : oldname) +# else +# define QEMU_WEAK_ALIAS(newname, oldname) \ typeof(oldname) newname __attribute__((weak, alias (#oldname))) +# define QEMU_WEAK_REF(newname, oldname) newname +# endif #else #define GCC_ATTR /**/ #define GCC_FMT_ATTR(n, m) diff --git a/osdep.c b/osdep.c index a87d4a453d..2f7a49159a 100644 --- a/osdep.c +++ b/osdep.c @@ -54,6 +54,38 @@ static bool fips_enabled = false; static const char *qemu_version = QEMU_VERSION; +static int default_fdset_get_fd(int64_t fdset_id, int flags) +{ + return -1; +} +QEMU_WEAK_ALIAS(monitor_fdset_get_fd, default_fdset_get_fd); +#define monitor_fdset_get_fd \ + QEMU_WEAK_REF(monitor_fdset_get_fd, default_fdset_get_fd) + +static int default_fdset_dup_fd_add(int64_t fdset_id, int dup_fd) +{ + return -1; +} +QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_add, default_fdset_dup_fd_add); +#define monitor_fdset_dup_fd_add \ + QEMU_WEAK_REF(monitor_fdset_dup_fd_add, default_fdset_dup_fd_add) + +static int default_fdset_dup_fd_remove(int dup_fd) +{ + return -1; +} +QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_remove, default_fdset_dup_fd_remove); +#define monitor_fdset_dup_fd_remove \ + QEMU_WEAK_REF(monitor_fdset_dup_fd_remove, default_fdset_dup_fd_remove) + +static int default_fdset_dup_fd_find(int dup_fd) +{ + return -1; +} +QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_find, default_fdset_dup_fd_find); +#define monitor_fdset_dup_fd_find \ + QEMU_WEAK_REF(monitor_fdset_dup_fd_remove, default_fdset_dup_fd_find) + int socket_set_cork(int fd, int v) { #if defined(SOL_TCP) && defined(TCP_CORK) @@ -400,27 +432,3 @@ bool fips_get_state(void) return fips_enabled; } - -static int default_fdset_get_fd(int64_t fdset_id, int flags) -{ - return -1; -} -QEMU_WEAK_ALIAS(monitor_fdset_get_fd, default_fdset_get_fd); - -static int default_fdset_dup_fd_add(int64_t fdset_id, int dup_fd) -{ - return -1; -} -QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_add, default_fdset_dup_fd_add); - -static int default_fdset_dup_fd_remove(int dup_fd) -{ - return -1; -} -QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_remove, default_fdset_dup_fd_remove); - -static int default_fdset_dup_fd_find(int dup_fd) -{ - return -1; -} -QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_find, default_fdset_dup_fd_find); diff --git a/oslib-win32.c b/oslib-win32.c index 9ca83df011..326a2bddb3 100644 --- a/oslib-win32.c +++ b/oslib-win32.c @@ -32,6 +32,13 @@ #include "trace.h" #include "qemu_socket.h" +static void default_qemu_fd_register(int fd) +{ +} +QEMU_WEAK_ALIAS(qemu_fd_register, default_qemu_fd_register); +#define qemu_fd_register \ + QEMU_WEAK_REF(qemu_fd_register, default_qemu_fd_register) + void *qemu_oom_check(void *ptr) { if (ptr == NULL) { @@ -150,8 +157,3 @@ int qemu_get_thread_id(void) { return GetCurrentThreadId(); } - -static void default_qemu_fd_register(int fd) -{ -} -QEMU_WEAK_ALIAS(qemu_fd_register, default_qemu_fd_register); diff --git a/qemu-sockets.c b/qemu-sockets.c index f2a637165b..abcd791cb6 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -61,6 +61,28 @@ static QemuOptsList dummy_opts = { }, }; +static int default_monitor_get_fd(Monitor *mon, const char *name, Error **errp) +{ + error_setg(errp, "only QEMU supports file descriptor passing"); + return -1; +} +QEMU_WEAK_ALIAS(monitor_get_fd, default_monitor_get_fd); +#define monitor_get_fd \ + QEMU_WEAK_REF(monitor_get_fd, default_monitor_get_fd) + +static int default_qemu_set_fd_handler2(int fd, + IOCanReadHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque) + +{ + abort(); +} +QEMU_WEAK_ALIAS(qemu_set_fd_handler2, default_qemu_set_fd_handler2); +#define qemu_set_fd_handler2 \ + QEMU_WEAK_REF(qemu_set_fd_handler2, default_qemu_set_fd_handler2) + static int inet_getport(struct addrinfo *e) { struct sockaddr_in *i4; @@ -967,21 +989,3 @@ int socket_init(void) #endif return 0; } - -static int default_monitor_get_fd(Monitor *mon, const char *name, Error **errp) -{ - error_setg(errp, "only QEMU supports file descriptor passing"); - return -1; -} -QEMU_WEAK_ALIAS(monitor_get_fd, default_monitor_get_fd); - -static int default_qemu_set_fd_handler2(int fd, - IOCanReadHandler *fd_read_poll, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque) - -{ - abort(); -} -QEMU_WEAK_ALIAS(qemu_set_fd_handler2, default_qemu_set_fd_handler2); diff --git a/qmp.c b/qmp.c index 638888a64e..13e83a59e0 100644 --- a/qmp.c +++ b/qmp.c @@ -477,6 +477,8 @@ static CpuDefinitionInfoList *default_arch_query_cpu_definitions(Error **errp) return NULL; } QEMU_WEAK_ALIAS(arch_query_cpu_definitions, default_arch_query_cpu_definitions); +#define arch_query_cpu_definitions \ + QEMU_WEAK_REF(arch_query_cpu_definitions, default_arch_query_cpu_definitions) CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) { From c166cb72f1676855816340666c3b618beef4b976 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 2 Nov 2012 15:43:21 +0100 Subject: [PATCH 1520/2270] semaphore: implement fallback counting semaphores with mutex+condvar OpenBSD and Darwin do not have sem_timedwait. Implement a fallback for them. Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- qemu-thread-posix.c | 90 ++++++++++++++++++++++++++++++++++++++++----- qemu-thread-posix.h | 6 +++ 2 files changed, 87 insertions(+), 9 deletions(-) diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c index 6a3d3a12a8..4ef9c7b3f8 100644 --- a/qemu-thread-posix.c +++ b/qemu-thread-posix.c @@ -122,36 +122,106 @@ void qemu_sem_init(QemuSemaphore *sem, int init) { int rc; +#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) + rc = pthread_mutex_init(&sem->lock, NULL); + if (rc != 0) { + error_exit(rc, __func__); + } + rc = pthread_cond_init(&sem->cond, NULL); + if (rc != 0) { + error_exit(rc, __func__); + } + if (init < 0) { + error_exit(EINVAL, __func__); + } + sem->count = init; +#else rc = sem_init(&sem->sem, 0, init); if (rc < 0) { error_exit(errno, __func__); } +#endif } void qemu_sem_destroy(QemuSemaphore *sem) { int rc; +#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) + rc = pthread_cond_destroy(&sem->cond); + if (rc < 0) { + error_exit(rc, __func__); + } + rc = pthread_mutex_destroy(&sem->lock); + if (rc < 0) { + error_exit(rc, __func__); + } +#else rc = sem_destroy(&sem->sem); if (rc < 0) { error_exit(errno, __func__); } +#endif } void qemu_sem_post(QemuSemaphore *sem) { int rc; +#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) + pthread_mutex_lock(&sem->lock); + if (sem->count == INT_MAX) { + rc = EINVAL; + } else if (sem->count++ < 0) { + rc = pthread_cond_signal(&sem->cond); + } else { + rc = 0; + } + pthread_mutex_unlock(&sem->lock); + if (rc != 0) { + error_exit(rc, __func__); + } +#else rc = sem_post(&sem->sem); if (rc < 0) { error_exit(errno, __func__); } +#endif +} + +static void compute_abs_deadline(struct timespec *ts, int ms) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + ts->tv_nsec = tv.tv_usec * 1000 + (ms % 1000) * 1000000; + ts->tv_sec = tv.tv_sec + ms / 1000; + if (ts->tv_nsec >= 1000000000) { + ts->tv_sec++; + ts->tv_nsec -= 1000000000; + } } int qemu_sem_timedwait(QemuSemaphore *sem, int ms) { int rc; + struct timespec ts; +#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) + compute_abs_deadline(&ts, ms); + pthread_mutex_lock(&sem->lock); + --sem->count; + while (sem->count < 0) { + rc = pthread_cond_timedwait(&sem->cond, &sem->lock, &ts); + if (rc == ETIMEDOUT) { + break; + } + if (rc != 0) { + error_exit(rc, __func__); + } + } + pthread_mutex_unlock(&sem->lock); + return (rc == ETIMEDOUT ? -1 : 0); +#else if (ms <= 0) { /* This is cheaper than sem_timedwait. */ do { @@ -161,15 +231,7 @@ int qemu_sem_timedwait(QemuSemaphore *sem, int ms) return -1; } } else { - struct timeval tv; - struct timespec ts; - gettimeofday(&tv, NULL); - ts.tv_nsec = tv.tv_usec * 1000 + (ms % 1000) * 1000000; - ts.tv_sec = tv.tv_sec + ms / 1000; - if (ts.tv_nsec >= 1000000000) { - ts.tv_sec++; - ts.tv_nsec -= 1000000000; - } + compute_abs_deadline(&ts, ms); do { rc = sem_timedwait(&sem->sem, &ts); } while (rc == -1 && errno == EINTR); @@ -181,10 +243,19 @@ int qemu_sem_timedwait(QemuSemaphore *sem, int ms) error_exit(errno, __func__); } return 0; +#endif } void qemu_sem_wait(QemuSemaphore *sem) { +#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) + pthread_mutex_lock(&sem->lock); + --sem->count; + while (sem->count < 0) { + pthread_cond_wait(&sem->cond, &sem->lock); + } + pthread_mutex_unlock(&sem->lock); +#else int rc; do { @@ -193,6 +264,7 @@ void qemu_sem_wait(QemuSemaphore *sem) if (rc < 0) { error_exit(errno, __func__); } +#endif } void qemu_thread_create(QemuThread *thread, diff --git a/qemu-thread-posix.h b/qemu-thread-posix.h index 2542c15200..380bae209b 100644 --- a/qemu-thread-posix.h +++ b/qemu-thread-posix.h @@ -12,7 +12,13 @@ struct QemuCond { }; struct QemuSemaphore { +#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) + pthread_mutex_t lock; + pthread_cond_t cond; + int count; +#else sem_t sem; +#endif }; struct QemuThread { From c8122c35e611385b31e2d8ccb059d0687540244a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 2 Nov 2012 15:43:22 +0100 Subject: [PATCH 1521/2270] qemu-timer: reinitialize timers after fork Timers are not inherited by the child of a fork(2), so just use pthread_atfork to reinstate them after daemonize. Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- qemu-timer.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/qemu-timer.c b/qemu-timer.c index f3426c9937..7b2217aab0 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -742,6 +742,17 @@ static void quit_timers(void) t->stop(t); } +static void reinit_timers(void) +{ + struct qemu_alarm_timer *t = alarm_timer; + t->stop(t); + if (t->start(t)) { + fprintf(stderr, "Internal timer error: aborting\n"); + exit(1); + } + qemu_rearm_alarm_timer(t); +} + int init_timer_alarm(void) { struct qemu_alarm_timer *t = NULL; @@ -765,6 +776,9 @@ int init_timer_alarm(void) } atexit(quit_timers); +#ifdef CONFIG_POSIX + pthread_atfork(NULL, NULL, reinit_timers); +#endif alarm_timer = t; return 0; From f9ab4654e370ceedb745523b607a628e297cb6ab Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 2 Nov 2012 15:43:23 +0100 Subject: [PATCH 1522/2270] vl: unify calls to init_timer_alarm init_timer_alarm was being called twice. This is not needed. Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- main-loop.c | 5 ++++- vl.c | 5 ----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/main-loop.c b/main-loop.c index e43c7c8e8d..234a3130c2 100644 --- a/main-loop.c +++ b/main-loop.c @@ -123,7 +123,10 @@ int qemu_init_main_loop(void) GSource *src; init_clocks(); - init_timer_alarm(); + if (init_timer_alarm() < 0) { + fprintf(stderr, "could not initialize alarm timer\n"); + exit(1); + } qemu_mutex_lock_iothread(); ret = qemu_signal_init(); diff --git a/vl.c b/vl.c index 99681dabf5..e2d5276988 100644 --- a/vl.c +++ b/vl.c @@ -3616,11 +3616,6 @@ int main(int argc, char **argv, char **envp) add_device_config(DEV_VIRTCON, "vc:80Cx24C"); } - if (init_timer_alarm() < 0) { - fprintf(stderr, "could not initialize alarm timer\n"); - exit(1); - } - socket_init(); if (qemu_opts_foreach(qemu_find_opts("chardev"), chardev_init_func, NULL, 1) != 0) From 49cf57281b74ccb64587ccc0626fc55a01227a15 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 2 Nov 2012 15:43:24 +0100 Subject: [PATCH 1523/2270] vl: delay thread initialization after daemonization Commit ac4119c (chardev: Use timer instead of bottom-half to postpone open event, 2012-10-12) moved the alarm timer initialization to an earlier point but failed to consider that it depends on qemu_init_main_loop. Later, commit 1c53786 (vl: init main loop earlier, 2012-10-30) fixed this, but left -daemonize in two different ways. First, timers need to be reinitialized after forking. Second, the global mutex was being held by the parent, and thus dropped after forking. The first is now fixed using pthread_atfork. For the second part, make sure that the global mutex is not taken before daemonization, and similarly delay qemu_thread_self. Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- main-loop.c | 1 - vl.c | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/main-loop.c b/main-loop.c index 234a3130c2..c87624e621 100644 --- a/main-loop.c +++ b/main-loop.c @@ -128,7 +128,6 @@ int qemu_init_main_loop(void) exit(1); } - qemu_mutex_lock_iothread(); ret = qemu_signal_init(); if (ret) { return ret; diff --git a/vl.c b/vl.c index e2d5276988..0f5b07bbde 100644 --- a/vl.c +++ b/vl.c @@ -3477,7 +3477,6 @@ int main(int argc, char **argv, char **envp) } loc_set_none(); - qemu_init_cpu_loop(); if (qemu_init_main_loop()) { fprintf(stderr, "qemu_init_main_loop failed\n"); exit(1); @@ -3677,6 +3676,9 @@ int main(int argc, char **argv, char **envp) os_set_line_buffering(); + qemu_init_cpu_loop(); + qemu_mutex_lock_iothread(); + #ifdef CONFIG_SPICE /* spice needs the timers to be initialized by this point */ qemu_spice_init(); From aed91c1bff5e568c7b0fbd0e1e7e2f9e62409e73 Mon Sep 17 00:00:00 2001 From: Meador Inge Date: Mon, 29 Oct 2012 12:05:09 +0000 Subject: [PATCH 1524/2270] m68k: Return semihosting errno values correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixing a simple typo, s/errno/err/, that caused the error status from GDB semihosted system calls to be returned incorrectly. Signed-off-by: Meador Inge Reviewed-by: Andreas Färber Signed-off-by: Peter Maydell Signed-off-by: Blue Swirl --- target-m68k/m68k-semi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-m68k/m68k-semi.c b/target-m68k/m68k-semi.c index 3bb30cd1f7..fed44ea490 100644 --- a/target-m68k/m68k-semi.c +++ b/target-m68k/m68k-semi.c @@ -150,7 +150,7 @@ static void m68k_semi_cb(CPUM68KState *env, target_ulong ret, target_ulong err) } /* FIXME - handle put_user() failure */ put_user_u32(ret, args); - put_user_u32(errno, args + 4); + put_user_u32(err, args + 4); } #define ARG(n) \ From 7ba6c10490cf57608045eb2b6351f185d600f4ea Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 29 Oct 2012 12:05:10 +0000 Subject: [PATCH 1525/2270] target-m68k/m68k-semi: Handle get_user failure Handle failure of get_user accessing the semihosting argument block, rather than simply ignoring the failures. Signed-off-by: Peter Maydell Signed-off-by: Blue Swirl --- target-m68k/m68k-semi.c | 144 ++++++++++++++++++++++++++-------------- 1 file changed, 93 insertions(+), 51 deletions(-) diff --git a/target-m68k/m68k-semi.c b/target-m68k/m68k-semi.c index fed44ea490..d569bf17c0 100644 --- a/target-m68k/m68k-semi.c +++ b/target-m68k/m68k-semi.c @@ -153,17 +153,21 @@ static void m68k_semi_cb(CPUM68KState *env, target_ulong ret, target_ulong err) put_user_u32(err, args + 4); } -#define ARG(n) \ -({ \ - target_ulong __arg; \ - /* FIXME - handle get_user() failure */ \ - get_user_ual(__arg, args + (n) * 4); \ - __arg; \ -}) -#define PARG(x) ((unsigned long)ARG(x)) +/* Read the input value from the argument block; fail the semihosting + * call if the memory read fails. + */ +#define GET_ARG(n) do { \ + if (get_user_ual(arg ## n, args + (n) * 4)) { \ + result = -1; \ + errno = EFAULT; \ + goto failed; \ + } \ +} while (0) + void do_m68k_semihosting(CPUM68KState *env, int nr) { uint32_t args; + target_ulong arg0, arg1, arg2, arg3; void *p; void *q; uint32_t len; @@ -175,27 +179,33 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) gdb_exit(env, env->dregs[0]); exit(env->dregs[0]); case HOSTED_OPEN: + GET_ARG(0); + GET_ARG(1); + GET_ARG(2); + GET_ARG(3); if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_cb, "open,%s,%x,%x", ARG(0), (int)ARG(1), - ARG(2), ARG(3)); + gdb_do_syscall(m68k_semi_cb, "open,%s,%x,%x", arg0, (int)arg1, + arg2, arg3); return; } else { - if (!(p = lock_user_string(ARG(0)))) { + p = lock_user_string(arg0); + if (!p) { /* FIXME - check error code? */ result = -1; } else { - result = open(p, translate_openflags(ARG(2)), ARG(3)); - unlock_user(p, ARG(0), 0); + result = open(p, translate_openflags(arg2), arg3); + unlock_user(p, arg0, 0); } } break; case HOSTED_CLOSE: { /* Ignore attempts to close stdin/out/err. */ - int fd = ARG(0); + GET_ARG(0); + int fd = arg0; if (fd > 2) { if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_cb, "close,%x", ARG(0)); + gdb_do_syscall(m68k_semi_cb, "close,%x", arg0); return; } else { result = close(fd); @@ -206,47 +216,59 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) break; } case HOSTED_READ: - len = ARG(2); + GET_ARG(0); + GET_ARG(1); + GET_ARG(2); + len = arg2; if (use_gdb_syscalls()) { gdb_do_syscall(m68k_semi_cb, "read,%x,%x,%x", - ARG(0), ARG(1), len); + arg0, arg1, len); return; } else { - if (!(p = lock_user(VERIFY_WRITE, ARG(1), len, 0))) { + p = lock_user(VERIFY_WRITE, arg1, len, 0); + if (!p) { /* FIXME - check error code? */ result = -1; } else { - result = read(ARG(0), p, len); - unlock_user(p, ARG(1), len); + result = read(arg0, p, len); + unlock_user(p, arg1, len); } } break; case HOSTED_WRITE: - len = ARG(2); + GET_ARG(0); + GET_ARG(1); + GET_ARG(2); + len = arg2; if (use_gdb_syscalls()) { gdb_do_syscall(m68k_semi_cb, "write,%x,%x,%x", - ARG(0), ARG(1), len); + arg0, arg1, len); return; } else { - if (!(p = lock_user(VERIFY_READ, ARG(1), len, 1))) { + p = lock_user(VERIFY_READ, arg1, len, 1); + if (!p) { /* FIXME - check error code? */ result = -1; } else { - result = write(ARG(0), p, len); - unlock_user(p, ARG(0), 0); + result = write(arg0, p, len); + unlock_user(p, arg0, 0); } } break; case HOSTED_LSEEK: { uint64_t off; - off = (uint32_t)ARG(2) | ((uint64_t)ARG(1) << 32); + GET_ARG(0); + GET_ARG(1); + GET_ARG(2); + GET_ARG(3); + off = (uint32_t)arg2 | ((uint64_t)arg1 << 32); if (use_gdb_syscalls()) { m68k_semi_is_fseek = 1; gdb_do_syscall(m68k_semi_cb, "fseek,%x,%lx,%x", - ARG(0), off, ARG(3)); + arg0, off, arg3); } else { - off = lseek(ARG(0), off, ARG(3)); + off = lseek(arg0, off, arg3); /* FIXME - handle put_user() failure */ put_user_u32(off >> 32, args); put_user_u32(off, args + 4); @@ -255,74 +277,89 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) return; } case HOSTED_RENAME: + GET_ARG(0); + GET_ARG(1); + GET_ARG(2); + GET_ARG(3); if (use_gdb_syscalls()) { gdb_do_syscall(m68k_semi_cb, "rename,%s,%s", - ARG(0), (int)ARG(1), ARG(2), (int)ARG(3)); + arg0, (int)arg1, arg2, (int)arg3); return; } else { - p = lock_user_string(ARG(0)); - q = lock_user_string(ARG(2)); + p = lock_user_string(arg0); + q = lock_user_string(arg2); if (!p || !q) { /* FIXME - check error code? */ result = -1; } else { result = rename(p, q); } - unlock_user(p, ARG(0), 0); - unlock_user(q, ARG(2), 0); + unlock_user(p, arg0, 0); + unlock_user(q, arg2, 0); } break; case HOSTED_UNLINK: + GET_ARG(0); + GET_ARG(1); if (use_gdb_syscalls()) { gdb_do_syscall(m68k_semi_cb, "unlink,%s", - ARG(0), (int)ARG(1)); + arg0, (int)arg1); return; } else { - if (!(p = lock_user_string(ARG(0)))) { + p = lock_user_string(arg0); + if (!p) { /* FIXME - check error code? */ result = -1; } else { result = unlink(p); - unlock_user(p, ARG(0), 0); + unlock_user(p, arg0, 0); } } break; case HOSTED_STAT: + GET_ARG(0); + GET_ARG(1); + GET_ARG(2); if (use_gdb_syscalls()) { gdb_do_syscall(m68k_semi_cb, "stat,%s,%x", - ARG(0), (int)ARG(1), ARG(2)); + arg0, (int)arg1, arg2); return; } else { struct stat s; - if (!(p = lock_user_string(ARG(0)))) { + p = lock_user_string(arg0); + if (!p) { /* FIXME - check error code? */ result = -1; } else { result = stat(p, &s); - unlock_user(p, ARG(0), 0); + unlock_user(p, arg0, 0); } if (result == 0) { - translate_stat(env, ARG(2), &s); + translate_stat(env, arg2, &s); } } break; case HOSTED_FSTAT: + GET_ARG(0); + GET_ARG(1); if (use_gdb_syscalls()) { gdb_do_syscall(m68k_semi_cb, "fstat,%x,%x", - ARG(0), ARG(1)); + arg0, arg1); return; } else { struct stat s; - result = fstat(ARG(0), &s); + result = fstat(arg0, &s); if (result == 0) { - translate_stat(env, ARG(1), &s); + translate_stat(env, arg1, &s); } } break; case HOSTED_GETTIMEOFDAY: + GET_ARG(0); + GET_ARG(1); if (use_gdb_syscalls()) { gdb_do_syscall(m68k_semi_cb, "gettimeofday,%x,%x", - ARG(0), ARG(1)); + arg0, arg1); return; } else { qemu_timeval tv; @@ -330,37 +367,41 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) result = qemu_gettimeofday(&tv); if (result != 0) { if (!(p = lock_user(VERIFY_WRITE, - ARG(0), sizeof(struct gdb_timeval), 0))) { + arg0, sizeof(struct gdb_timeval), 0))) { /* FIXME - check error code? */ result = -1; } else { p->tv_sec = cpu_to_be32(tv.tv_sec); p->tv_usec = cpu_to_be64(tv.tv_usec); - unlock_user(p, ARG(0), sizeof(struct gdb_timeval)); + unlock_user(p, arg0, sizeof(struct gdb_timeval)); } } } break; case HOSTED_ISATTY: + GET_ARG(0); if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_cb, "isatty,%x", ARG(0)); + gdb_do_syscall(m68k_semi_cb, "isatty,%x", arg0); return; } else { - result = isatty(ARG(0)); + result = isatty(arg0); } break; case HOSTED_SYSTEM: + GET_ARG(0); + GET_ARG(1); if (use_gdb_syscalls()) { gdb_do_syscall(m68k_semi_cb, "system,%s", - ARG(0), (int)ARG(1)); + arg0, (int)arg1); return; } else { - if (!(p = lock_user_string(ARG(0)))) { + p = lock_user_string(arg0); + if (!p) { /* FIXME - check error code? */ result = -1; } else { result = system(p); - unlock_user(p, ARG(0), 0); + unlock_user(p, arg0, 0); } } break; @@ -402,6 +443,7 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) cpu_abort(env, "Unsupported semihosting syscall %d\n", nr); result = 0; } +failed: /* FIXME - handle put_user() failure */ put_user_u32(result, args); put_user_u32(errno, args + 4); From 1073bfd8c0829be06e6ad1cbb4a2f48f8bb594bc Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 29 Oct 2012 12:05:11 +0000 Subject: [PATCH 1526/2270] target-m68k/m68k-semi.c: Log when put_user for returning values fails Abstract out the use of put_user for returning semihosting call results, so that we can log when a guest erroneously attempts a semihosting call with an unwritable argument block. Signed-off-by: Peter Maydell Signed-off-by: Blue Swirl --- target-m68k/m68k-semi.c | 47 +++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/target-m68k/m68k-semi.c b/target-m68k/m68k-semi.c index d569bf17c0..9f7a24cdb4 100644 --- a/target-m68k/m68k-semi.c +++ b/target-m68k/m68k-semi.c @@ -133,24 +133,44 @@ static void translate_stat(CPUM68KState *env, target_ulong addr, struct stat *s) unlock_user(p, addr, sizeof(struct m68k_gdb_stat)); } +static void m68k_semi_return_u32(CPUM68KState *env, uint32_t ret, uint32_t err) +{ + target_ulong args = env->dregs[1]; + if (put_user_u32(ret, args) || + put_user_u32(err, args + 4)) { + /* The m68k semihosting ABI does not provide any way to report this + * error to the guest, so the best we can do is log it in qemu. + * It is always a guest error not to pass us a valid argument block. + */ + qemu_log_mask(LOG_GUEST_ERROR, "m68k-semihosting: return value " + "discarded because argument block not writable\n"); + } +} + +static void m68k_semi_return_u64(CPUM68KState *env, uint64_t ret, uint32_t err) +{ + target_ulong args = env->dregs[1]; + if (put_user_u32(ret >> 32, args) || + put_user_u32(ret, args + 4) || + put_user_u32(err, args + 8)) { + /* No way to report this via m68k semihosting ABI; just log it */ + qemu_log_mask(LOG_GUEST_ERROR, "m68k-semihosting: return value " + "discarded because argument block not writable\n"); + } +} + static int m68k_semi_is_fseek; static void m68k_semi_cb(CPUM68KState *env, target_ulong ret, target_ulong err) { - target_ulong args; - - args = env->dregs[1]; if (m68k_semi_is_fseek) { /* FIXME: We've already lost the high bits of the fseek return value. */ - /* FIXME - handle put_user() failure */ - put_user_u32(0, args); - args += 4; + m68k_semi_return_u64(env, ret, err); m68k_semi_is_fseek = 0; + } else { + m68k_semi_return_u32(env, ret, err); } - /* FIXME - handle put_user() failure */ - put_user_u32(ret, args); - put_user_u32(err, args + 4); } /* Read the input value from the argument block; fail the semihosting @@ -269,10 +289,7 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) arg0, off, arg3); } else { off = lseek(arg0, off, arg3); - /* FIXME - handle put_user() failure */ - put_user_u32(off >> 32, args); - put_user_u32(off, args + 4); - put_user_u32(errno, args + 8); + m68k_semi_return_u64(env, off, errno); } return; } @@ -444,7 +461,5 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) result = 0; } failed: - /* FIXME - handle put_user() failure */ - put_user_u32(result, args); - put_user_u32(errno, args + 4); + m68k_semi_return_u32(env, result, errno); } From 32761257c0b9fa7ee04d2871a6e48a41f119c469 Mon Sep 17 00:00:00 2001 From: Yeongkyoon Lee Date: Wed, 31 Oct 2012 16:04:23 +0900 Subject: [PATCH 1527/2270] configure: Add CONFIG_QEMU_LDST_OPTIMIZATION for TCG qemu_ld/st optimization Enable CONFIG_QEMU_LDST_OPTIMIZATION for TCG qemu_ld/st optimization only when a host is i386 or x86_64. Signed-off-by: Yeongkyoon Lee Signed-off-by: Blue Swirl --- configure | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/configure b/configure index ba99f67dd5..8e70cbb224 100755 --- a/configure +++ b/configure @@ -3881,6 +3881,12 @@ upper() { echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]' } +case "$cpu" in + i386|x86_64) + echo "CONFIG_QEMU_LDST_OPTIMIZATION=y" >> $config_target_mak + ;; +esac + echo "TARGET_SHORT_ALIGNMENT=$target_short_alignment" >> $config_target_mak echo "TARGET_INT_ALIGNMENT=$target_int_alignment" >> $config_target_mak echo "TARGET_LONG_ALIGNMENT=$target_long_alignment" >> $config_target_mak From fdbb84d1332ae0827d60f1a2ca03c7d5678c6edd Mon Sep 17 00:00:00 2001 From: Yeongkyoon Lee Date: Wed, 31 Oct 2012 16:04:24 +0900 Subject: [PATCH 1528/2270] tcg: Add extended GETPC mechanism for MMU helpers with ldst optimization Add GETPC_EXT which is used by MMU helpers to selectively calculate the code address of accessing guest memory when called from a qemu_ld/st optimized code or a C function. Currently, it supports only i386 and x86-64 hosts. Signed-off-by: Yeongkyoon Lee Signed-off-by: Blue Swirl --- exec-all.h | 36 ++++++++++++++++++++++++++++++++++++ exec.c | 11 +++++++++++ softmmu_template.h | 16 ++++++++-------- 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/exec-all.h b/exec-all.h index 2ea0e4fc24..ad6d22b6c5 100644 --- a/exec-all.h +++ b/exec-all.h @@ -310,6 +310,42 @@ extern uintptr_t tci_tb_ptr; # define GETPC() ((uintptr_t)__builtin_return_address(0) - 1) #endif +#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU) +/* qemu_ld/st optimization split code generation to fast and slow path, thus, + it needs special handling for an MMU helper which is called from the slow + path, to get the fast path's pc without any additional argument. + It uses a tricky solution which embeds the fast path pc into the slow path. + + Code flow in slow path: + (1) pre-process + (2) call MMU helper + (3) jump to (5) + (4) fast path information (implementation specific) + (5) post-process (e.g. stack adjust) + (6) jump to corresponding code of the next of fast path + */ +# if defined(__i386__) || defined(__x86_64__) +/* To avoid broken disassembling, long jmp is used for embedding fast path pc, + so that the destination is the next code of fast path, though this jmp is + never executed. + + call MMU helper + jmp POST_PROC (2byte) <- GETRA() + jmp NEXT_CODE (5byte) + POST_PROCESS ... <- GETRA() + 7 + */ +# define GETRA() ((uintptr_t)__builtin_return_address(0)) +# define GETPC_LDST() ((uintptr_t)(GETRA() + 7 + \ + *(int32_t *)((void *)GETRA() + 3) - 1)) +# else +# error "CONFIG_QEMU_LDST_OPTIMIZATION needs GETPC_LDST() implementation!" +# endif +bool is_tcg_gen_code(uintptr_t pc_ptr); +# define GETPC_EXT() (is_tcg_gen_code(GETRA()) ? GETPC_LDST() : GETPC()) +#else +# define GETPC_EXT() GETPC() +#endif + #if !defined(CONFIG_USER_ONLY) struct MemoryRegion *iotlb_to_region(hwaddr index); diff --git a/exec.c b/exec.c index df6793812f..8bff743a62 100644 --- a/exec.c +++ b/exec.c @@ -1390,6 +1390,17 @@ void tb_link_page(TranslationBlock *tb, mmap_unlock(); } +#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU) +/* check whether the given addr is in TCG generated code buffer or not */ +bool is_tcg_gen_code(uintptr_t tc_ptr) +{ + /* This can be called during code generation, code_gen_buffer_max_size + is used instead of code_gen_ptr for upper boundary checking */ + return (tc_ptr >= (uintptr_t)code_gen_buffer && + tc_ptr < (uintptr_t)(code_gen_buffer + code_gen_buffer_max_size)); +} +#endif + /* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr < tb[1].tc_ptr. Return NULL if not found */ TranslationBlock *tb_find_pc(uintptr_t tc_ptr) diff --git a/softmmu_template.h b/softmmu_template.h index 20d6baba68..ce30d8bddc 100644 --- a/softmmu_template.h +++ b/softmmu_template.h @@ -111,13 +111,13 @@ glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr, /* IO access */ if ((addr & (DATA_SIZE - 1)) != 0) goto do_unaligned_access; - retaddr = GETPC(); + retaddr = GETPC_EXT(); ioaddr = env->iotlb[mmu_idx][index]; res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr); } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { /* slow unaligned access (it spans two pages or IO) */ do_unaligned_access: - retaddr = GETPC(); + retaddr = GETPC_EXT(); #ifdef ALIGNED_ONLY do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); #endif @@ -128,7 +128,7 @@ glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr, uintptr_t addend; #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) { - retaddr = GETPC(); + retaddr = GETPC_EXT(); do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); } #endif @@ -138,7 +138,7 @@ glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr, } } else { /* the page is not in the TLB : fill it */ - retaddr = GETPC(); + retaddr = GETPC_EXT(); #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); @@ -257,12 +257,12 @@ void glue(glue(helper_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, /* IO access */ if ((addr & (DATA_SIZE - 1)) != 0) goto do_unaligned_access; - retaddr = GETPC(); + retaddr = GETPC_EXT(); ioaddr = env->iotlb[mmu_idx][index]; glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr); } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { do_unaligned_access: - retaddr = GETPC(); + retaddr = GETPC_EXT(); #ifdef ALIGNED_ONLY do_unaligned_access(env, addr, 1, mmu_idx, retaddr); #endif @@ -273,7 +273,7 @@ void glue(glue(helper_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, uintptr_t addend; #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) { - retaddr = GETPC(); + retaddr = GETPC_EXT(); do_unaligned_access(env, addr, 1, mmu_idx, retaddr); } #endif @@ -283,7 +283,7 @@ void glue(glue(helper_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, } } else { /* the page is not in the TLB : fill it */ - retaddr = GETPC(); + retaddr = GETPC_EXT(); #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) do_unaligned_access(env, addr, 1, mmu_idx, retaddr); From b76f0d8c2e3eac94bc7fd90a510cb7426b2a2699 Mon Sep 17 00:00:00 2001 From: Yeongkyoon Lee Date: Wed, 31 Oct 2012 16:04:25 +0900 Subject: [PATCH 1529/2270] tcg: Optimize qemu_ld/st by generating slow paths at the end of a block Add optimized TCG qemu_ld/st generation which locates the code of TLB miss cases at the end of a block after generating the other IRs. Currently, this optimization supports only i386 and x86_64 hosts. Signed-off-by: Yeongkyoon Lee Signed-off-by: Blue Swirl --- tcg/i386/tcg-target.c | 440 ++++++++++++++++++++++++++++-------------- tcg/tcg.c | 12 ++ tcg/tcg.h | 30 +++ 3 files changed, 338 insertions(+), 144 deletions(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index e45a5a0426..6f3ad3ceab 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -1002,6 +1002,17 @@ static const void *qemu_st_helpers[4] = { helper_stq_mmu, }; +static void add_qemu_ldst_label(TCGContext *s, + int is_ld, + int opc, + int data_reg, + int data_reg2, + int addrlo_reg, + int addrhi_reg, + int mem_index, + uint8_t *raddr, + uint8_t **label_ptr); + /* Perform the TLB load and compare. Inputs: @@ -1060,19 +1071,19 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx, tcg_out_mov(s, type, r1, addrlo); - /* jne label1 */ - tcg_out8(s, OPC_JCC_short + JCC_JNE); + /* jne slow_path */ + tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0); label_ptr[0] = s->code_ptr; - s->code_ptr++; + s->code_ptr += 4; if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) { /* cmp 4(r0), addrhi */ tcg_out_modrm_offset(s, OPC_CMP_GvEv, args[addrlo_idx+1], r0, 4); - /* jne label1 */ - tcg_out8(s, OPC_JCC_short + JCC_JNE); + /* jne slow_path */ + tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0); label_ptr[1] = s->code_ptr; - s->code_ptr++; + s->code_ptr += 4; } /* TLB Hit. */ @@ -1193,10 +1204,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int addrlo_idx; #if defined(CONFIG_SOFTMMU) int mem_index, s_bits; -#if TCG_TARGET_REG_BITS == 32 - int stack_adjust; -#endif - uint8_t *label_ptr[3]; + uint8_t *label_ptr[2]; #endif data_reg = args[0]; @@ -1216,87 +1224,17 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, /* TLB Hit. */ tcg_out_qemu_ld_direct(s, data_reg, data_reg2, TCG_REG_L1, 0, 0, opc); - /* jmp label2 */ - tcg_out8(s, OPC_JMP_short); - label_ptr[2] = s->code_ptr; - s->code_ptr++; - - /* TLB Miss. */ - - /* label1: */ - *label_ptr[0] = s->code_ptr - label_ptr[0] - 1; - if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) { - *label_ptr[1] = s->code_ptr - label_ptr[1] - 1; - } - - /* XXX: move that code at the end of the TB */ -#if TCG_TARGET_REG_BITS == 32 - tcg_out_pushi(s, mem_index); - stack_adjust = 4; - if (TARGET_LONG_BITS == 64) { - tcg_out_push(s, args[addrlo_idx + 1]); - stack_adjust += 4; - } - tcg_out_push(s, args[addrlo_idx]); - stack_adjust += 4; - tcg_out_push(s, TCG_AREG0); - stack_adjust += 4; -#else - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0); - /* The second argument is already loaded with addrlo. */ - tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], mem_index); -#endif - - tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]); - -#if TCG_TARGET_REG_BITS == 32 - if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) { - /* Pop and discard. This is 2 bytes smaller than the add. */ - tcg_out_pop(s, TCG_REG_ECX); - } else if (stack_adjust != 0) { - tcg_out_addi(s, TCG_REG_CALL_STACK, stack_adjust); - } -#endif - - switch(opc) { - case 0 | 4: - tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW); - break; - case 1 | 4: - tcg_out_ext16s(s, data_reg, TCG_REG_EAX, P_REXW); - break; - case 0: - tcg_out_ext8u(s, data_reg, TCG_REG_EAX); - break; - case 1: - tcg_out_ext16u(s, data_reg, TCG_REG_EAX); - break; - case 2: - tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX); - break; -#if TCG_TARGET_REG_BITS == 64 - case 2 | 4: - tcg_out_ext32s(s, data_reg, TCG_REG_EAX); - break; -#endif - case 3: - if (TCG_TARGET_REG_BITS == 64) { - tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX); - } else if (data_reg == TCG_REG_EDX) { - /* xchg %edx, %eax */ - tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX, 0, 0, 0); - tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EAX); - } else { - tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX); - tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EDX); - } - break; - default: - tcg_abort(); - } - - /* label2: */ - *label_ptr[2] = s->code_ptr - label_ptr[2] - 1; + /* Record the current context of a load into ldst label */ + add_qemu_ldst_label(s, + 1, + opc, + data_reg, + data_reg2, + args[addrlo_idx], + args[addrlo_idx + 1], + mem_index, + s->code_ptr, + label_ptr); #else { int32_t offset = GUEST_BASE; @@ -1393,8 +1331,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int addrlo_idx; #if defined(CONFIG_SOFTMMU) int mem_index, s_bits; - int stack_adjust; - uint8_t *label_ptr[3]; + uint8_t *label_ptr[2]; #endif data_reg = args[0]; @@ -1414,57 +1351,17 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, /* TLB Hit. */ tcg_out_qemu_st_direct(s, data_reg, data_reg2, TCG_REG_L1, 0, 0, opc); - /* jmp label2 */ - tcg_out8(s, OPC_JMP_short); - label_ptr[2] = s->code_ptr; - s->code_ptr++; - - /* TLB Miss. */ - - /* label1: */ - *label_ptr[0] = s->code_ptr - label_ptr[0] - 1; - if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) { - *label_ptr[1] = s->code_ptr - label_ptr[1] - 1; - } - - /* XXX: move that code at the end of the TB */ -#if TCG_TARGET_REG_BITS == 32 - tcg_out_pushi(s, mem_index); - stack_adjust = 4; - if (opc == 3) { - tcg_out_push(s, data_reg2); - stack_adjust += 4; - } - tcg_out_push(s, data_reg); - stack_adjust += 4; - if (TARGET_LONG_BITS == 64) { - tcg_out_push(s, args[addrlo_idx + 1]); - stack_adjust += 4; - } - tcg_out_push(s, args[addrlo_idx]); - stack_adjust += 4; - tcg_out_push(s, TCG_AREG0); - stack_adjust += 4; -#else - tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0); - /* The second argument is already loaded with addrlo. */ - tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32), - tcg_target_call_iarg_regs[2], data_reg); - tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3], mem_index); - stack_adjust = 0; -#endif - - tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]); - - if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) { - /* Pop and discard. This is 2 bytes smaller than the add. */ - tcg_out_pop(s, TCG_REG_ECX); - } else if (stack_adjust != 0) { - tcg_out_addi(s, TCG_REG_CALL_STACK, stack_adjust); - } - - /* label2: */ - *label_ptr[2] = s->code_ptr - label_ptr[2] - 1; + /* Record the current context of a store into ldst label */ + add_qemu_ldst_label(s, + 0, + opc, + data_reg, + data_reg2, + args[addrlo_idx], + args[addrlo_idx + 1], + mem_index, + s->code_ptr, + label_ptr); #else { int32_t offset = GUEST_BASE; @@ -1491,6 +1388,261 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, #endif } +#if defined(CONFIG_SOFTMMU) +/* + * Record the context of a call to the out of line helper code for the slow path + * for a load or store, so that we can later generate the correct helper code + */ +static void add_qemu_ldst_label(TCGContext *s, + int is_ld, + int opc, + int data_reg, + int data_reg2, + int addrlo_reg, + int addrhi_reg, + int mem_index, + uint8_t *raddr, + uint8_t **label_ptr) +{ + int idx; + TCGLabelQemuLdst *label; + + if (s->nb_qemu_ldst_labels >= TCG_MAX_QEMU_LDST) { + tcg_abort(); + } + + idx = s->nb_qemu_ldst_labels++; + label = (TCGLabelQemuLdst *)&s->qemu_ldst_labels[idx]; + label->is_ld = is_ld; + label->opc = opc; + label->datalo_reg = data_reg; + label->datahi_reg = data_reg2; + label->addrlo_reg = addrlo_reg; + label->addrhi_reg = addrhi_reg; + label->mem_index = mem_index; + label->raddr = raddr; + label->label_ptr[0] = label_ptr[0]; + if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) { + label->label_ptr[1] = label_ptr[1]; + } +} + +/* + * Generate code for the slow path for a load at the end of block + */ +static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *label) +{ + int s_bits; + int opc = label->opc; + int mem_index = label->mem_index; +#if TCG_TARGET_REG_BITS == 32 + int stack_adjust; + int addrlo_reg = label->addrlo_reg; + int addrhi_reg = label->addrhi_reg; +#endif + int data_reg = label->datalo_reg; + int data_reg2 = label->datahi_reg; + uint8_t *raddr = label->raddr; + uint8_t **label_ptr = &label->label_ptr[0]; + + s_bits = opc & 3; + + /* resolve label address */ + *(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4); + if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) { + *(uint32_t *)label_ptr[1] = (uint32_t)(s->code_ptr - label_ptr[1] - 4); + } + +#if TCG_TARGET_REG_BITS == 32 + tcg_out_pushi(s, mem_index); + stack_adjust = 4; + if (TARGET_LONG_BITS == 64) { + tcg_out_push(s, addrhi_reg); + stack_adjust += 4; + } + tcg_out_push(s, addrlo_reg); + stack_adjust += 4; + tcg_out_push(s, TCG_AREG0); + stack_adjust += 4; +#else + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0); + /* The second argument is already loaded with addrlo. */ + tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], mem_index); +#endif + + /* Code generation of qemu_ld/st's slow path calling MMU helper + + PRE_PROC ... + call MMU helper + jmp POST_PROC (2b) : short forward jump <- GETRA() + jmp next_code (5b) : dummy long backward jump which is never executed + POST_PROC ... : do post-processing <- GETRA() + 7 + jmp next_code : jump to the code corresponding to next IR of qemu_ld/st + */ + + tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]); + + /* Jump to post-processing code */ + tcg_out8(s, OPC_JMP_short); + tcg_out8(s, 5); + /* Dummy backward jump having information of fast path'pc for MMU helpers */ + tcg_out8(s, OPC_JMP_long); + *(int32_t *)s->code_ptr = (int32_t)(raddr - s->code_ptr - 4); + s->code_ptr += 4; + +#if TCG_TARGET_REG_BITS == 32 + if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) { + /* Pop and discard. This is 2 bytes smaller than the add. */ + tcg_out_pop(s, TCG_REG_ECX); + } else if (stack_adjust != 0) { + tcg_out_addi(s, TCG_REG_CALL_STACK, stack_adjust); + } +#endif + + switch(opc) { + case 0 | 4: + tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW); + break; + case 1 | 4: + tcg_out_ext16s(s, data_reg, TCG_REG_EAX, P_REXW); + break; + case 0: + tcg_out_ext8u(s, data_reg, TCG_REG_EAX); + break; + case 1: + tcg_out_ext16u(s, data_reg, TCG_REG_EAX); + break; + case 2: + tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX); + break; +#if TCG_TARGET_REG_BITS == 64 + case 2 | 4: + tcg_out_ext32s(s, data_reg, TCG_REG_EAX); + break; +#endif + case 3: + if (TCG_TARGET_REG_BITS == 64) { + tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX); + } else if (data_reg == TCG_REG_EDX) { + /* xchg %edx, %eax */ + tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX, 0, 0, 0); + tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EAX); + } else { + tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX); + tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EDX); + } + break; + default: + tcg_abort(); + } + + /* Jump to the code corresponding to next IR of qemu_st */ + tcg_out_jmp(s, (tcg_target_long)raddr); +} + +/* + * Generate code for the slow path for a store at the end of block + */ +static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *label) +{ + int s_bits; + int stack_adjust; + int opc = label->opc; + int mem_index = label->mem_index; + int data_reg = label->datalo_reg; +#if TCG_TARGET_REG_BITS == 32 + int data_reg2 = label->datahi_reg; + int addrlo_reg = label->addrlo_reg; + int addrhi_reg = label->addrhi_reg; +#endif + uint8_t *raddr = label->raddr; + uint8_t **label_ptr = &label->label_ptr[0]; + + s_bits = opc & 3; + + /* resolve label address */ + *(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4); + if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) { + *(uint32_t *)label_ptr[1] = (uint32_t)(s->code_ptr - label_ptr[1] - 4); + } + +#if TCG_TARGET_REG_BITS == 32 + tcg_out_pushi(s, mem_index); + stack_adjust = 4; + if (opc == 3) { + tcg_out_push(s, data_reg2); + stack_adjust += 4; + } + tcg_out_push(s, data_reg); + stack_adjust += 4; + if (TARGET_LONG_BITS == 64) { + tcg_out_push(s, addrhi_reg); + stack_adjust += 4; + } + tcg_out_push(s, addrlo_reg); + stack_adjust += 4; + tcg_out_push(s, TCG_AREG0); + stack_adjust += 4; +#else + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0); + /* The second argument is already loaded with addrlo. */ + tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32), + tcg_target_call_iarg_regs[2], data_reg); + tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3], mem_index); + stack_adjust = 0; +#endif + + /* Code generation of qemu_ld/st's slow path calling MMU helper + + PRE_PROC ... + call MMU helper + jmp POST_PROC (2b) : short forward jump <- GETRA() + jmp next_code (5b) : dummy long backward jump which is never executed + POST_PROC ... : do post-processing <- GETRA() + 7 + jmp next_code : jump to the code corresponding to next IR of qemu_ld/st + */ + + tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]); + + /* Jump to post-processing code */ + tcg_out8(s, OPC_JMP_short); + tcg_out8(s, 5); + /* Dummy backward jump having information of fast path'pc for MMU helpers */ + tcg_out8(s, OPC_JMP_long); + *(int32_t *)s->code_ptr = (int32_t)(raddr - s->code_ptr - 4); + s->code_ptr += 4; + + if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) { + /* Pop and discard. This is 2 bytes smaller than the add. */ + tcg_out_pop(s, TCG_REG_ECX); + } else if (stack_adjust != 0) { + tcg_out_addi(s, TCG_REG_CALL_STACK, stack_adjust); + } + + /* Jump to the code corresponding to next IR of qemu_st */ + tcg_out_jmp(s, (tcg_target_long)raddr); +} + +/* + * Generate TB finalization at the end of block + */ +void tcg_out_tb_finalize(TCGContext *s) +{ + int i; + TCGLabelQemuLdst *label; + + /* qemu_ld/st slow paths */ + for (i = 0; i < s->nb_qemu_ldst_labels; i++) { + label = (TCGLabelQemuLdst *)&s->qemu_ldst_labels[i]; + if (label->is_ld) { + tcg_out_qemu_ld_slow_path(s, label); + } else { + tcg_out_qemu_st_slow_path(s, label); + } + } +} +#endif /* CONFIG_SOFTMMU */ + static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, const int *const_args) { diff --git a/tcg/tcg.c b/tcg/tcg.c index 11334387a0..42052dba7b 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -299,6 +299,14 @@ void tcg_func_start(TCGContext *s) gen_opc_ptr = gen_opc_buf; gen_opparam_ptr = gen_opparam_buf; + +#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU) + /* Initialize qemu_ld/st labels to assist code generation at the end of TB + for TLB miss cases at the end of TB */ + s->qemu_ldst_labels = tcg_malloc(sizeof(TCGLabelQemuLdst) * + TCG_MAX_QEMU_LDST); + s->nb_qemu_ldst_labels = 0; +#endif } static inline void tcg_temp_alloc(TCGContext *s, int n) @@ -2314,6 +2322,10 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, #endif } the_end: +#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU) + /* Generate TB finalization at the end of block */ + tcg_out_tb_finalize(s); +#endif return -1; } diff --git a/tcg/tcg.h b/tcg/tcg.h index a6c9256f8b..c2ae873715 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -188,6 +188,24 @@ typedef tcg_target_ulong TCGArg; are aliases for target_ulong and host pointer sized values respectively. */ +#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU) +/* Macros/structures for qemu_ld/st IR code optimization: + TCG_MAX_HELPER_LABELS is defined as same as OPC_BUF_SIZE in exec-all.h. */ +#define TCG_MAX_QEMU_LDST 640 + +typedef struct TCGLabelQemuLdst { + int is_ld:1; /* qemu_ld: 1, qemu_st: 0 */ + int opc:4; + int addrlo_reg; /* reg index for low word of guest virtual addr */ + int addrhi_reg; /* reg index for high word of guest virtual addr */ + int datalo_reg; /* reg index for low word to be loaded or stored */ + int datahi_reg; /* reg index for high word to be loaded or stored */ + int mem_index; /* soft MMU memory index */ + uint8_t *raddr; /* gen code addr of the next IR of qemu_ld/st IR */ + uint8_t *label_ptr[2]; /* label pointers to be updated */ +} TCGLabelQemuLdst; +#endif + #ifdef CONFIG_DEBUG_TCG #define DEBUG_TCGV 1 #endif @@ -431,6 +449,13 @@ struct TCGContext { int temps_in_use; int goto_tb_issue_mask; #endif + +#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU) + /* labels info for qemu_ld/st IRs + The labels help to generate TLB miss case codes at the end of TB */ + TCGLabelQemuLdst *qemu_ldst_labels; + int nb_qemu_ldst_labels; +#endif }; extern TCGContext tcg_ctx; @@ -634,3 +659,8 @@ extern uint8_t *code_gen_prologue; #endif void tcg_register_jit(void *buf, size_t buf_size); + +#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU) +/* Generate TB finalization at the end of block */ +void tcg_out_tb_finalize(TCGContext *s); +#endif From 0d7937974cd0504f30ad483c3368b21da426ddf9 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 3 Nov 2012 12:47:08 +0100 Subject: [PATCH 1530/2270] vmware_vga: Coding style cleanup Fix coding style as suggested by checkpatch.pl Signed-off-by: BALATON Zoltan Signed-off-by: Blue Swirl --- hw/vmware_vga.c | 272 ++++++++++++++++++++++++++---------------------- 1 file changed, 149 insertions(+), 123 deletions(-) diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 34532e5c3a..bf14e788d2 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -79,7 +79,7 @@ struct vmsvga_state_s { } *cmd; }; -#define REDRAW_FIFO_LEN 512 +#define REDRAW_FIFO_LEN 512 struct vmsvga_rect_s { int x, y, w, h; } redraw_fifo[REDRAW_FIFO_LEN]; @@ -92,31 +92,31 @@ struct pci_vmsvga_state_s { MemoryRegion io_bar; }; -#define SVGA_MAGIC 0x900000UL -#define SVGA_MAKE_ID(ver) (SVGA_MAGIC << 8 | (ver)) -#define SVGA_ID_0 SVGA_MAKE_ID(0) -#define SVGA_ID_1 SVGA_MAKE_ID(1) -#define SVGA_ID_2 SVGA_MAKE_ID(2) +#define SVGA_MAGIC 0x900000UL +#define SVGA_MAKE_ID(ver) (SVGA_MAGIC << 8 | (ver)) +#define SVGA_ID_0 SVGA_MAKE_ID(0) +#define SVGA_ID_1 SVGA_MAKE_ID(1) +#define SVGA_ID_2 SVGA_MAKE_ID(2) -#define SVGA_LEGACY_BASE_PORT 0x4560 -#define SVGA_INDEX_PORT 0x0 -#define SVGA_VALUE_PORT 0x1 -#define SVGA_BIOS_PORT 0x2 +#define SVGA_LEGACY_BASE_PORT 0x4560 +#define SVGA_INDEX_PORT 0x0 +#define SVGA_VALUE_PORT 0x1 +#define SVGA_BIOS_PORT 0x2 #define SVGA_VERSION_2 #ifdef SVGA_VERSION_2 -# define SVGA_ID SVGA_ID_2 -# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT -# define SVGA_IO_MUL 1 -# define SVGA_FIFO_SIZE 0x10000 -# define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA2 +# define SVGA_ID SVGA_ID_2 +# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT +# define SVGA_IO_MUL 1 +# define SVGA_FIFO_SIZE 0x10000 +# define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA2 #else -# define SVGA_ID SVGA_ID_1 -# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT -# define SVGA_IO_MUL 4 -# define SVGA_FIFO_SIZE 0x10000 -# define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA +# define SVGA_ID SVGA_ID_1 +# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT +# define SVGA_IO_MUL 4 +# define SVGA_FIFO_SIZE 0x10000 +# define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA #endif enum { @@ -128,7 +128,7 @@ enum { SVGA_REG_MAX_WIDTH = 4, SVGA_REG_MAX_HEIGHT = 5, SVGA_REG_DEPTH = 6, - SVGA_REG_BITS_PER_PIXEL = 7, /* Current bpp in the guest */ + SVGA_REG_BITS_PER_PIXEL = 7, /* Current bpp in the guest */ SVGA_REG_PSEUDOCOLOR = 8, SVGA_REG_RED_MASK = 9, SVGA_REG_GREEN_MASK = 10, @@ -141,46 +141,46 @@ enum { /* ID 1 and 2 registers */ SVGA_REG_CAPABILITIES = 17, - SVGA_REG_MEM_START = 18, /* Memory for command FIFO */ + SVGA_REG_MEM_START = 18, /* Memory for command FIFO */ SVGA_REG_MEM_SIZE = 19, - SVGA_REG_CONFIG_DONE = 20, /* Set when memory area configured */ - SVGA_REG_SYNC = 21, /* Write to force synchronization */ - SVGA_REG_BUSY = 22, /* Read to check if sync is done */ - SVGA_REG_GUEST_ID = 23, /* Set guest OS identifier */ - SVGA_REG_CURSOR_ID = 24, /* ID of cursor */ - SVGA_REG_CURSOR_X = 25, /* Set cursor X position */ - SVGA_REG_CURSOR_Y = 26, /* Set cursor Y position */ - SVGA_REG_CURSOR_ON = 27, /* Turn cursor on/off */ - SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* Current bpp in the host */ - SVGA_REG_SCRATCH_SIZE = 29, /* Number of scratch registers */ - SVGA_REG_MEM_REGS = 30, /* Number of FIFO registers */ - SVGA_REG_NUM_DISPLAYS = 31, /* Number of guest displays */ - SVGA_REG_PITCHLOCK = 32, /* Fixed pitch for all modes */ + SVGA_REG_CONFIG_DONE = 20, /* Set when memory area configured */ + SVGA_REG_SYNC = 21, /* Write to force synchronization */ + SVGA_REG_BUSY = 22, /* Read to check if sync is done */ + SVGA_REG_GUEST_ID = 23, /* Set guest OS identifier */ + SVGA_REG_CURSOR_ID = 24, /* ID of cursor */ + SVGA_REG_CURSOR_X = 25, /* Set cursor X position */ + SVGA_REG_CURSOR_Y = 26, /* Set cursor Y position */ + SVGA_REG_CURSOR_ON = 27, /* Turn cursor on/off */ + SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* Current bpp in the host */ + SVGA_REG_SCRATCH_SIZE = 29, /* Number of scratch registers */ + SVGA_REG_MEM_REGS = 30, /* Number of FIFO registers */ + SVGA_REG_NUM_DISPLAYS = 31, /* Number of guest displays */ + SVGA_REG_PITCHLOCK = 32, /* Fixed pitch for all modes */ - SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */ + SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */ SVGA_PALETTE_END = SVGA_PALETTE_BASE + 767, SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + 768, }; -#define SVGA_CAP_NONE 0 -#define SVGA_CAP_RECT_FILL (1 << 0) -#define SVGA_CAP_RECT_COPY (1 << 1) -#define SVGA_CAP_RECT_PAT_FILL (1 << 2) -#define SVGA_CAP_LEGACY_OFFSCREEN (1 << 3) -#define SVGA_CAP_RASTER_OP (1 << 4) -#define SVGA_CAP_CURSOR (1 << 5) -#define SVGA_CAP_CURSOR_BYPASS (1 << 6) -#define SVGA_CAP_CURSOR_BYPASS_2 (1 << 7) -#define SVGA_CAP_8BIT_EMULATION (1 << 8) -#define SVGA_CAP_ALPHA_CURSOR (1 << 9) -#define SVGA_CAP_GLYPH (1 << 10) -#define SVGA_CAP_GLYPH_CLIPPING (1 << 11) -#define SVGA_CAP_OFFSCREEN_1 (1 << 12) -#define SVGA_CAP_ALPHA_BLEND (1 << 13) -#define SVGA_CAP_3D (1 << 14) -#define SVGA_CAP_EXTENDED_FIFO (1 << 15) -#define SVGA_CAP_MULTIMON (1 << 16) -#define SVGA_CAP_PITCHLOCK (1 << 17) +#define SVGA_CAP_NONE 0 +#define SVGA_CAP_RECT_FILL (1 << 0) +#define SVGA_CAP_RECT_COPY (1 << 1) +#define SVGA_CAP_RECT_PAT_FILL (1 << 2) +#define SVGA_CAP_LEGACY_OFFSCREEN (1 << 3) +#define SVGA_CAP_RASTER_OP (1 << 4) +#define SVGA_CAP_CURSOR (1 << 5) +#define SVGA_CAP_CURSOR_BYPASS (1 << 6) +#define SVGA_CAP_CURSOR_BYPASS_2 (1 << 7) +#define SVGA_CAP_8BIT_EMULATION (1 << 8) +#define SVGA_CAP_ALPHA_CURSOR (1 << 9) +#define SVGA_CAP_GLYPH (1 << 10) +#define SVGA_CAP_GLYPH_CLIPPING (1 << 11) +#define SVGA_CAP_OFFSCREEN_1 (1 << 12) +#define SVGA_CAP_ALPHA_BLEND (1 << 13) +#define SVGA_CAP_3D (1 << 14) +#define SVGA_CAP_EXTENDED_FIFO (1 << 15) +#define SVGA_CAP_MULTIMON (1 << 16) +#define SVGA_CAP_PITCHLOCK (1 << 17) /* * FIFO offsets (seen as an array of 32-bit words) @@ -190,7 +190,7 @@ enum { * The original defined FIFO offsets */ SVGA_FIFO_MIN = 0, - SVGA_FIFO_MAX, /* The distance from MIN to MAX must be at least 10K */ + SVGA_FIFO_MAX, /* The distance from MIN to MAX must be at least 10K */ SVGA_FIFO_NEXT_CMD, SVGA_FIFO_STOP, @@ -204,21 +204,21 @@ enum { SVGA_FIFO_PITCHLOCK, }; -#define SVGA_FIFO_CAP_NONE 0 -#define SVGA_FIFO_CAP_FENCE (1 << 0) -#define SVGA_FIFO_CAP_ACCELFRONT (1 << 1) -#define SVGA_FIFO_CAP_PITCHLOCK (1 << 2) +#define SVGA_FIFO_CAP_NONE 0 +#define SVGA_FIFO_CAP_FENCE (1 << 0) +#define SVGA_FIFO_CAP_ACCELFRONT (1 << 1) +#define SVGA_FIFO_CAP_PITCHLOCK (1 << 2) -#define SVGA_FIFO_FLAG_NONE 0 -#define SVGA_FIFO_FLAG_ACCELFRONT (1 << 0) +#define SVGA_FIFO_FLAG_NONE 0 +#define SVGA_FIFO_FLAG_ACCELFRONT (1 << 0) /* These values can probably be changed arbitrarily. */ -#define SVGA_SCRATCH_SIZE 0x8000 -#define SVGA_MAX_WIDTH 2360 -#define SVGA_MAX_HEIGHT 1770 +#define SVGA_SCRATCH_SIZE 0x8000 +#define SVGA_MAX_WIDTH 2360 +#define SVGA_MAX_HEIGHT 1770 #ifdef VERBOSE -# define GUEST_OS_BASE 0x5001 +# define GUEST_OS_BASE 0x5001 static const char *vmsvga_guest_id[] = { [0x00] = "Dos", [0x01] = "Windows 3.1", @@ -299,28 +299,27 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s, if (x + w > s->width) { fprintf(stderr, "%s: update width too large x: %d, w: %d\n", - __FUNCTION__, x, w); + __func__, x, w); x = MIN(x, s->width); w = s->width - x; } if (y + h > s->height) { fprintf(stderr, "%s: update height too large y: %d, h: %d\n", - __FUNCTION__, y, h); + __func__, y, h); y = MIN(y, s->height); h = s->height - y; } - line = h; bypl = s->bypp * s->width; width = s->bypp * w; start = s->bypp * x + bypl * y; src = s->vga.vram_ptr + start; dst = ds_get_data(s->vga.ds) + start; - for (; line > 0; line --, src += bypl, dst += bypl) + for (line = h; line > 0; line--, src += bypl, dst += bypl) { memcpy(dst, src, width); - + } dpy_gfx_update(s->vga.ds, x, y, w, h); } @@ -334,7 +333,8 @@ static inline void vmsvga_update_screen(struct vmsvga_state_s *s) static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s, int x, int y, int w, int h) { - struct vmsvga_rect_s *rect = &s->redraw_fifo[s->redraw_fifo_last ++]; + struct vmsvga_rect_s *rect = &s->redraw_fifo[s->redraw_fifo_last++]; + s->redraw_fifo_last &= REDRAW_FIFO_LEN - 1; rect->x = x; rect->y = y; @@ -345,6 +345,7 @@ static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s, static inline void vmsvga_update_rect_flush(struct vmsvga_state_s *s) { struct vmsvga_rect_s *rect; + if (s->invalidated) { s->redraw_fifo_first = s->redraw_fifo_last; return; @@ -352,7 +353,7 @@ static inline void vmsvga_update_rect_flush(struct vmsvga_state_s *s) /* Overlapping region updates can be optimised out here - if someone * knows a smart algorithm to do that, please share. */ while (s->redraw_fifo_first != s->redraw_fifo_last) { - rect = &s->redraw_fifo[s->redraw_fifo_first ++]; + rect = &s->redraw_fifo[s->redraw_fifo_first++]; s->redraw_fifo_first &= REDRAW_FIFO_LEN - 1; vmsvga_update_rect(s, rect->x, rect->y, rect->w, rect->h); } @@ -437,8 +438,8 @@ struct vmsvga_cursor_definition_s { uint32_t image[4096]; }; -#define SVGA_BITMAP_SIZE(w, h) ((((w) + 31) >> 5) * (h)) -#define SVGA_PIXMAP_SIZE(w, h, bpp) (((((w) * (bpp)) + 31) >> 5) * (h)) +#define SVGA_BITMAP_SIZE(w, h) ((((w) + 31) >> 5) * (h)) +#define SVGA_PIXMAP_SIZE(w, h, bpp) (((((w) * (bpp)) + 31) >> 5) * (h)) #ifdef HW_MOUSE_ACCEL static inline void vmsvga_cursor_define(struct vmsvga_state_s *s, @@ -452,16 +453,16 @@ static inline void vmsvga_cursor_define(struct vmsvga_state_s *s, qc->hot_y = c->hot_y; switch (c->bpp) { case 1: - cursor_set_mono(qc, 0xffffff, 0x000000, (void*)c->image, - 1, (void*)c->mask); + cursor_set_mono(qc, 0xffffff, 0x000000, (void *)c->image, + 1, (void *)c->mask); #ifdef DEBUG cursor_print_ascii_art(qc, "vmware/mono"); #endif break; case 32: /* fill alpha channel from mask, set color to zero */ - cursor_set_mono(qc, 0x000000, 0x000000, (void*)c->mask, - 1, (void*)c->mask); + cursor_set_mono(qc, 0x000000, 0x000000, (void *)c->mask, + 1, (void *)c->mask); /* add in rgb values */ pixels = c->width * c->height; for (i = 0; i < pixels; i++) { @@ -473,7 +474,7 @@ static inline void vmsvga_cursor_define(struct vmsvga_state_s *s, break; default: fprintf(stderr, "%s: unhandled bpp %d, using fallback cursor\n", - __FUNCTION__, c->bpp); + __func__, c->bpp); cursor_put(qc); qc = cursor_builtin_left_ptr(); } @@ -483,25 +484,30 @@ static inline void vmsvga_cursor_define(struct vmsvga_state_s *s, } #endif -#define CMD(f) le32_to_cpu(s->cmd->f) +#define CMD(f) le32_to_cpu(s->cmd->f) static inline int vmsvga_fifo_length(struct vmsvga_state_s *s) { int num; - if (!s->config || !s->enable) + + if (!s->config || !s->enable) { return 0; + } num = CMD(next_cmd) - CMD(stop); - if (num < 0) + if (num < 0) { num += CMD(max) - CMD(min); + } return num >> 2; } static inline uint32_t vmsvga_fifo_read_raw(struct vmsvga_state_s *s) { uint32_t cmd = s->fifo[CMD(stop) >> 2]; + s->cmd->stop = cpu_to_le32(CMD(stop) + 4); - if (CMD(stop) >= CMD(max)) + if (CMD(stop) >= CMD(max)) { s->cmd->stop = s->cmd->min; + } return cmd; } @@ -527,8 +533,9 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s) case SVGA_CMD_UPDATE: case SVGA_CMD_UPDATE_VERBOSE: len -= 5; - if (len < 0) + if (len < 0) { goto rewind; + } x = vmsvga_fifo_read(s); y = vmsvga_fifo_read(s); @@ -539,8 +546,9 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s) case SVGA_CMD_RECT_FILL: len -= 6; - if (len < 0) + if (len < 0) { goto rewind; + } colour = vmsvga_fifo_read(s); x = vmsvga_fifo_read(s); @@ -557,8 +565,9 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s) case SVGA_CMD_RECT_COPY: len -= 7; - if (len < 0) + if (len < 0) { goto rewind; + } x = vmsvga_fifo_read(s); y = vmsvga_fifo_read(s); @@ -576,8 +585,9 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s) case SVGA_CMD_DEFINE_CURSOR: len -= 8; - if (len < 0) + if (len < 0) { goto rewind; + } cursor.id = vmsvga_fifo_read(s); cursor.hot_x = vmsvga_fifo_read(s); @@ -589,17 +599,21 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s) args = SVGA_BITMAP_SIZE(x, y) + SVGA_PIXMAP_SIZE(x, y, cursor.bpp); if (SVGA_BITMAP_SIZE(x, y) > sizeof cursor.mask || - SVGA_PIXMAP_SIZE(x, y, cursor.bpp) > sizeof cursor.image) + SVGA_PIXMAP_SIZE(x, y, cursor.bpp) > sizeof cursor.image) { goto badcmd; + } len -= args; - if (len < 0) + if (len < 0) { goto rewind; + } - for (args = 0; args < SVGA_BITMAP_SIZE(x, y); args ++) + for (args = 0; args < SVGA_BITMAP_SIZE(x, y); args++) { cursor.mask[args] = vmsvga_fifo_read_raw(s); - for (args = 0; args < SVGA_PIXMAP_SIZE(x, y, cursor.bpp); args ++) + } + for (args = 0; args < SVGA_PIXMAP_SIZE(x, y, cursor.bpp); args++) { cursor.image[args] = vmsvga_fifo_read_raw(s); + } #ifdef HW_MOUSE_ACCEL vmsvga_cursor_define(s, &cursor); break; @@ -614,9 +628,9 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s) */ case SVGA_CMD_DEFINE_ALPHA_CURSOR: len -= 6; - if (len < 0) + if (len < 0) { goto rewind; - + } vmsvga_fifo_read(s); vmsvga_fifo_read(s); vmsvga_fifo_read(s); @@ -632,9 +646,9 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s) goto badcmd; case SVGA_CMD_DRAW_GLYPH_CLIPPED: len -= 4; - if (len < 0) + if (len < 0) { goto rewind; - + } vmsvga_fifo_read(s); vmsvga_fifo_read(s); args = 7 + (vmsvga_fifo_read(s) >> 2); @@ -658,12 +672,14 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s) args = 0; badcmd: len -= args; - if (len < 0) + if (len < 0) { goto rewind; - while (args --) + } + while (args--) { vmsvga_fifo_read(s); + } printf("%s: Unknown command 0x%02x in SVGA command FIFO\n", - __FUNCTION__, cmd); + __func__, cmd); break; rewind: @@ -678,12 +694,14 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s) static uint32_t vmsvga_index_read(void *opaque, uint32_t address) { struct vmsvga_state_s *s = opaque; + return s->index; } static void vmsvga_index_write(void *opaque, uint32_t address, uint32_t index) { struct vmsvga_state_s *s = opaque; + s->index = index; } @@ -691,6 +709,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) { uint32_t caps; struct vmsvga_state_s *s = opaque; + switch (s->index) { case SVGA_REG_ID: return s->svgaid; @@ -805,9 +824,10 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) default: if (s->index >= SVGA_SCRATCH_BASE && - s->index < SVGA_SCRATCH_BASE + s->scratch_size) + s->index < SVGA_SCRATCH_BASE + s->scratch_size) { return s->scratch[s->index - SVGA_SCRATCH_BASE]; - printf("%s: Bad register %02x\n", __FUNCTION__, s->index); + } + printf("%s: Bad register %02x\n", __func__, s->index); } return 0; @@ -816,10 +836,12 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) { struct vmsvga_state_s *s = opaque; + switch (s->index) { case SVGA_REG_ID: - if (value == SVGA_ID_2 || value == SVGA_ID_1 || value == SVGA_ID_0) + if (value == SVGA_ID_2 || value == SVGA_ID_1 || value == SVGA_ID_0) { s->svgaid = value; + } break; case SVGA_REG_ENABLE: @@ -850,7 +872,7 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) case SVGA_REG_DEPTH: case SVGA_REG_BITS_PER_PIXEL: if (value != s->depth) { - printf("%s: Bad colour depth: %i bits\n", __FUNCTION__, value); + printf("%s: Bad colour depth: %i bits\n", __func__, value); s->config = 0; } break; @@ -859,15 +881,18 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) if (value) { s->fifo = (uint32_t *) s->fifo_ptr; /* Check range and alignment. */ - if ((CMD(min) | CMD(max) | - CMD(next_cmd) | CMD(stop)) & 3) + if ((CMD(min) | CMD(max) | CMD(next_cmd) | CMD(stop)) & 3) { break; - if (CMD(min) < (uint8_t *) s->cmd->fifo - (uint8_t *) s->fifo) + } + if (CMD(min) < (uint8_t *) s->cmd->fifo - (uint8_t *) s->fifo) { break; - if (CMD(max) > SVGA_FIFO_SIZE) + } + if (CMD(max) > SVGA_FIFO_SIZE) { break; - if (CMD(max) < CMD(min) + 10 * 1024) + } + if (CMD(max) < CMD(min) + 10 * 1024) { break; + } } s->config = !!value; break; @@ -881,9 +906,10 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) s->guest = value; #ifdef VERBOSE if (value >= GUEST_OS_BASE && value < GUEST_OS_BASE + - ARRAY_SIZE(vmsvga_guest_id)) - printf("%s: guest runs %s.\n", __FUNCTION__, - vmsvga_guest_id[value - GUEST_OS_BASE]); + ARRAY_SIZE(vmsvga_guest_id)) { + printf("%s: guest runs %s.\n", __func__, + vmsvga_guest_id[value - GUEST_OS_BASE]); + } #endif break; @@ -921,20 +947,19 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) s->scratch[s->index - SVGA_SCRATCH_BASE] = value; break; } - printf("%s: Bad register %02x\n", __FUNCTION__, s->index); + printf("%s: Bad register %02x\n", __func__, s->index); } } static uint32_t vmsvga_bios_read(void *opaque, uint32_t address) { - printf("%s: what are we supposed to return?\n", __FUNCTION__); + printf("%s: what are we supposed to return?\n", __func__); return 0xcafe; } static void vmsvga_bios_write(void *opaque, uint32_t address, uint32_t data) { - printf("%s: what are we supposed to do with (%08x)?\n", - __FUNCTION__, data); + printf("%s: what are we supposed to do with (%08x)?\n", __func__, data); } static inline void vmsvga_size(struct vmsvga_state_s *s) @@ -1024,8 +1049,9 @@ static void vmsvga_text_update(void *opaque, console_ch_t *chardata) { struct vmsvga_state_s *s = opaque; - if (s->vga.text_update) + if (s->vga.text_update) { s->vga.text_update(&s->vga, chardata); + } } static int vmsvga_post_load(void *opaque, int version_id) @@ -1033,9 +1059,9 @@ static int vmsvga_post_load(void *opaque, int version_id) struct vmsvga_state_s *s = opaque; s->invalidated = 1; - if (s->config) + if (s->config) { s->fifo = (uint32_t *) s->fifo_ptr; - + } return 0; } @@ -1045,7 +1071,7 @@ static const VMStateDescription vmstate_vmware_vga_internal = { .minimum_version_id = 0, .minimum_version_id_old = 0, .post_load = vmsvga_post_load, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_INT32_EQUAL(depth, struct vmsvga_state_s), VMSTATE_INT32(enable, struct vmsvga_state_s), VMSTATE_INT32(config, struct vmsvga_state_s), @@ -1071,7 +1097,7 @@ static const VMStateDescription vmstate_vmware_vga = { .version_id = 0, .minimum_version_id = 0, .minimum_version_id_old = 0, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(card, struct pci_vmsvga_state_s), VMSTATE_STRUCT(chip, struct pci_vmsvga_state_s, 0, vmstate_vmware_vga_internal, struct vmsvga_state_s), @@ -1180,9 +1206,9 @@ static int pci_vmsvga_initfn(PCIDevice *dev) iomem = &s->chip.vga.vram; - s->card.config[PCI_CACHE_LINE_SIZE] = 0x08; /* Cache line size */ - s->card.config[PCI_LATENCY_TIMER] = 0x40; /* Latency timer */ - s->card.config[PCI_INTERRUPT_LINE] = 0xff; /* End */ + s->card.config[PCI_CACHE_LINE_SIZE] = 0x08; /* Cache line size */ + s->card.config[PCI_LATENCY_TIMER] = 0x40; /* Latency timer */ + s->card.config[PCI_INTERRUPT_LINE] = 0xff; /* End */ memory_region_init_io(&s->io_bar, &vmsvga_io_ops, &s->chip, "vmsvga-io", 0x10); From aa32b38c5b2eb1afe30b3292454411bb760a432d Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 3 Nov 2012 12:47:08 +0100 Subject: [PATCH 1531/2270] vmware_vga: Remove duplicated info from local state Removed info from vmsvga_state that is available from elsewhere and thus was duplicated here unnecessarily. Signed-off-by: BALATON Zoltan Signed-off-by: Blue Swirl --- console.h | 20 ++++++ hw/vmware_vga.c | 159 ++++++++++++++++++++---------------------------- 2 files changed, 85 insertions(+), 94 deletions(-) diff --git a/console.h b/console.h index 0df033d674..70c9a55942 100644 --- a/console.h +++ b/console.h @@ -377,6 +377,26 @@ static inline pixman_format_code_t ds_get_format(DisplayState *ds) return ds->surface->format; } +static inline int ds_get_depth(DisplayState *ds) +{ + return ds->surface->pf.depth; +} + +static inline int ds_get_rmask(DisplayState *ds) +{ + return ds->surface->pf.rmask; +} + +static inline int ds_get_gmask(DisplayState *ds) +{ + return ds->surface->pf.gmask; +} + +static inline int ds_get_bmask(DisplayState *ds) +{ + return ds->surface->pf.bmask; +} + #ifdef CONFIG_CURSES #include typedef chtype console_ch_t; diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index bf14e788d2..240443bfda 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -36,11 +36,8 @@ struct vmsvga_state_s { VGACommonState vga; - int width; - int height; int invalidated; int depth; - int bypp; int enable; int config; struct { @@ -57,9 +54,6 @@ struct vmsvga_state_s { int new_height; uint32_t guest; uint32_t svgaid; - uint32_t wred; - uint32_t wgreen; - uint32_t wblue; int syncing; int fb_size; @@ -297,23 +291,23 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s, uint8_t *src; uint8_t *dst; - if (x + w > s->width) { + if (x + w > ds_get_width(s->vga.ds)) { fprintf(stderr, "%s: update width too large x: %d, w: %d\n", __func__, x, w); - x = MIN(x, s->width); - w = s->width - x; + x = MIN(x, ds_get_width(s->vga.ds)); + w = ds_get_width(s->vga.ds) - x; } - if (y + h > s->height) { + if (y + h > ds_get_height(s->vga.ds)) { fprintf(stderr, "%s: update height too large y: %d, h: %d\n", __func__, y, h); - y = MIN(y, s->height); - h = s->height - y; + y = MIN(y, ds_get_height(s->vga.ds)); + h = ds_get_height(s->vga.ds) - y; } - bypl = s->bypp * s->width; - width = s->bypp * w; - start = s->bypp * x + bypl * y; + bypl = ds_get_linesize(s->vga.ds); + width = ds_get_bytes_per_pixel(s->vga.ds) * w; + start = ds_get_bytes_per_pixel(s->vga.ds) * x + bypl * y; src = s->vga.vram_ptr + start; dst = ds_get_data(s->vga.ds) + start; @@ -326,8 +320,9 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s, static inline void vmsvga_update_screen(struct vmsvga_state_s *s) { memcpy(ds_get_data(s->vga.ds), s->vga.vram_ptr, - s->bypp * s->width * s->height); - dpy_gfx_update(s->vga.ds, 0, 0, s->width, s->height); + ds_get_linesize(s->vga.ds) * ds_get_height(s->vga.ds)); + dpy_gfx_update(s->vga.ds, 0, 0, + ds_get_width(s->vga.ds), ds_get_height(s->vga.ds)); } static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s, @@ -364,20 +359,21 @@ static inline void vmsvga_copy_rect(struct vmsvga_state_s *s, int x0, int y0, int x1, int y1, int w, int h) { uint8_t *vram = s->vga.vram_ptr; - int bypl = s->bypp * s->width; - int width = s->bypp * w; + int bypl = ds_get_linesize(s->vga.ds); + int bypp = ds_get_bytes_per_pixel(s->vga.ds); + int width = bypp * w; int line = h; uint8_t *ptr[2]; if (y1 > y0) { - ptr[0] = vram + s->bypp * x0 + bypl * (y0 + h - 1); - ptr[1] = vram + s->bypp * x1 + bypl * (y1 + h - 1); + ptr[0] = vram + bypp * x0 + bypl * (y0 + h - 1); + ptr[1] = vram + bypp * x1 + bypl * (y1 + h - 1); for (; line > 0; line --, ptr[0] -= bypl, ptr[1] -= bypl) { memmove(ptr[1], ptr[0], width); } } else { - ptr[0] = vram + s->bypp * x0 + bypl * y0; - ptr[1] = vram + s->bypp * x1 + bypl * y1; + ptr[0] = vram + bypp * x0 + bypl * y0; + ptr[1] = vram + bypp * x1 + bypl * y1; for (; line > 0; line --, ptr[0] += bypl, ptr[1] += bypl) { memmove(ptr[1], ptr[0], width); } @@ -391,13 +387,11 @@ static inline void vmsvga_copy_rect(struct vmsvga_state_s *s, static inline void vmsvga_fill_rect(struct vmsvga_state_s *s, uint32_t c, int x, int y, int w, int h) { - uint8_t *vram = s->vga.vram_ptr; - int bypp = s->bypp; - int bypl = bypp * s->width; - int width = bypp * w; + int bypl = ds_get_linesize(s->vga.ds); + int width = ds_get_bytes_per_pixel(s->vga.ds) * w; int line = h; int column; - uint8_t *fst = vram + bypp * x + bypl * y; + uint8_t *fst; uint8_t *dst; uint8_t *src; uint8_t col[4]; @@ -407,12 +401,14 @@ static inline void vmsvga_fill_rect(struct vmsvga_state_s *s, col[2] = c >> 16; col[3] = c >> 24; + fst = s->vga.vram_ptr + ds_get_bytes_per_pixel(s->vga.ds) * x + bypl * y; + if (line--) { dst = fst; src = col; for (column = width; column > 0; column--) { *(dst++) = *(src++); - if (src - col == bypp) { + if (src - col == ds_get_bytes_per_pixel(s->vga.ds)) { src = col; } } @@ -718,10 +714,10 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) return s->enable; case SVGA_REG_WIDTH: - return s->width; + return ds_get_width(s->vga.ds); case SVGA_REG_HEIGHT: - return s->height; + return ds_get_height(s->vga.ds); case SVGA_REG_MAX_WIDTH: return SVGA_MAX_WIDTH; @@ -730,23 +726,25 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) return SVGA_MAX_HEIGHT; case SVGA_REG_DEPTH: - return s->depth; + return ds_get_depth(s->vga.ds); case SVGA_REG_BITS_PER_PIXEL: - return (s->depth + 7) & ~7; + return ds_get_bits_per_pixel(s->vga.ds); case SVGA_REG_PSEUDOCOLOR: return 0x0; case SVGA_REG_RED_MASK: - return s->wred; + return ds_get_rmask(s->vga.ds); + case SVGA_REG_GREEN_MASK: - return s->wgreen; + return ds_get_gmask(s->vga.ds); + case SVGA_REG_BLUE_MASK: - return s->wblue; + return ds_get_bmask(s->vga.ds); case SVGA_REG_BYTES_PER_LINE: - return ((s->depth + 7) >> 3) * s->new_width; + return ds_get_bytes_per_pixel(s->vga.ds) * s->new_width; case SVGA_REG_FB_START: { struct pci_vmsvga_state_s *pci_vmsvga @@ -811,7 +809,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) return s->cursor.on; case SVGA_REG_HOST_BITS_PER_PIXEL: - return (s->depth + 7) & ~7; + return ds_get_bits_per_pixel(s->vga.ds); case SVGA_REG_SCRATCH_SIZE: return s->scratch_size; @@ -847,8 +845,6 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) case SVGA_REG_ENABLE: s->enable = value; s->config &= !!value; - s->width = -1; - s->height = -1; s->invalidated = 1; s->vga.invalidate(&s->vga); if (s->enable) { @@ -860,18 +856,26 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) break; case SVGA_REG_WIDTH: - s->new_width = value; - s->invalidated = 1; + if (value <= SVGA_MAX_WIDTH) { + s->new_width = value; + s->invalidated = 1; + } else { + printf("%s: Bad width: %i\n", __func__, value); + } break; case SVGA_REG_HEIGHT: - s->new_height = value; - s->invalidated = 1; + if (value <= SVGA_MAX_HEIGHT) { + s->new_height = value; + s->invalidated = 1; + } else { + printf("%s: Bad height: %i\n", __func__, value); + } break; case SVGA_REG_DEPTH: case SVGA_REG_BITS_PER_PIXEL: - if (value != s->depth) { + if (value != ds_get_bits_per_pixel(s->vga.ds)) { printf("%s: Bad colour depth: %i bits\n", __func__, value); s->config = 0; } @@ -962,12 +966,11 @@ static void vmsvga_bios_write(void *opaque, uint32_t address, uint32_t data) printf("%s: what are we supposed to do with (%08x)?\n", __func__, data); } -static inline void vmsvga_size(struct vmsvga_state_s *s) +static inline void vmsvga_check_size(struct vmsvga_state_s *s) { - if (s->new_width != s->width || s->new_height != s->height) { - s->width = s->new_width; - s->height = s->new_height; - qemu_console_resize(s->vga.ds, s->width, s->height); + if (s->new_width != ds_get_width(s->vga.ds) || + s->new_height != ds_get_height(s->vga.ds)) { + qemu_console_resize(s->vga.ds, s->new_width, s->new_height); s->invalidated = 1; } } @@ -980,7 +983,7 @@ static void vmsvga_update_display(void *opaque) return; } - vmsvga_size(s); + vmsvga_check_size(s); vmsvga_fifo_run(s); vmsvga_update_rect_flush(s); @@ -1004,8 +1007,6 @@ static void vmsvga_reset(DeviceState *dev) s->index = 0; s->enable = 0; s->config = 0; - s->width = -1; - s->height = -1; s->svgaid = SVGA_ID; s->cursor.on = 0; s->redraw_fifo_first = 0; @@ -1037,9 +1038,13 @@ static void vmsvga_screen_dump(void *opaque, const char *filename, bool cswitch, return; } - if (s->depth == 32) { - DisplaySurface *ds = qemu_create_displaysurface_from(s->width, - s->height, 32, ds_get_linesize(s->vga.ds), s->vga.vram_ptr); + if (ds_get_bits_per_pixel(s->vga.ds) == 32) { + DisplaySurface *ds = qemu_create_displaysurface_from( + ds_get_width(s->vga.ds), + ds_get_height(s->vga.ds), + 32, + ds_get_linesize(s->vga.ds), + s->vga.vram_ptr); ppm_save(filename, ds, errp); g_free(ds); } @@ -1125,40 +1130,9 @@ static void vmsvga_init(struct vmsvga_state_s *s, vga_common_init(&s->vga); vga_init(&s->vga, address_space, io, true); vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga); - - s->depth = ds_get_bits_per_pixel(s->vga.ds); - s->bypp = ds_get_bytes_per_pixel(s->vga.ds); - switch (s->depth) { - case 8: - s->wred = 0x00000007; - s->wgreen = 0x00000038; - s->wblue = 0x000000c0; - break; - case 15: - s->wred = 0x0000001f; - s->wgreen = 0x000003e0; - s->wblue = 0x00007c00; - break; - case 16: - s->wred = 0x0000001f; - s->wgreen = 0x000007e0; - s->wblue = 0x0000f800; - break; - case 24: - s->wred = 0x00ff0000; - s->wgreen = 0x0000ff00; - s->wblue = 0x000000ff; - break; - case 32: - s->wred = 0x00ff0000; - s->wgreen = 0x0000ff00; - s->wblue = 0x000000ff; - break; - } } -static uint64_t vmsvga_io_read(void *opaque, hwaddr addr, - unsigned size) +static uint64_t vmsvga_io_read(void *opaque, hwaddr addr, unsigned size) { struct vmsvga_state_s *s = opaque; @@ -1202,9 +1176,6 @@ static int pci_vmsvga_initfn(PCIDevice *dev) { struct pci_vmsvga_state_s *s = DO_UPCAST(struct pci_vmsvga_state_s, card, dev); - MemoryRegion *iomem; - - iomem = &s->chip.vga.vram; s->card.config[PCI_CACHE_LINE_SIZE] = 0x08; /* Cache line size */ s->card.config[PCI_LATENCY_TIMER] = 0x40; /* Latency timer */ @@ -1215,10 +1186,10 @@ static int pci_vmsvga_initfn(PCIDevice *dev) memory_region_set_flush_coalesced(&s->io_bar); pci_register_bar(&s->card, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar); - vmsvga_init(&s->chip, pci_address_space(dev), - pci_address_space_io(dev)); + vmsvga_init(&s->chip, pci_address_space(dev), pci_address_space_io(dev)); - pci_register_bar(&s->card, 1, PCI_BASE_ADDRESS_MEM_PREFETCH, iomem); + pci_register_bar(&s->card, 1, PCI_BASE_ADDRESS_MEM_PREFETCH, + &s->chip.vga.vram); pci_register_bar(&s->card, 2, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->chip.fifo_ram); From 5b9575c8b7873dee4ab233e065888bbce6dfbaa8 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 3 Nov 2012 12:47:08 +0100 Subject: [PATCH 1532/2270] vmware_vga: Return a value for FB_SIZE before the device is enabled According to the documentation drivers using this device should read FB_SIZE before enabling the device to know what memory to map. This would not work if we return 0 before enabled. The docs also mention reading SVGA_REG_DEPTH but not writing it. (Only SVGA_REG_BITS_PER_PIXEL can be written but we don't really support that either.) Signed-off-by: BALATON Zoltan Signed-off-by: Blue Swirl --- hw/vmware_vga.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 240443bfda..038994e705 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -31,13 +31,14 @@ #define HW_FILL_ACCEL #define HW_MOUSE_ACCEL -# include "vga_int.h" +#include "vga_int.h" + +/* See http://vmware-svga.sf.net/ for some documentation on VMWare SVGA */ struct vmsvga_state_s { VGACommonState vga; int invalidated; - int depth; int enable; int config; struct { @@ -55,7 +56,6 @@ struct vmsvga_state_s { uint32_t guest; uint32_t svgaid; int syncing; - int fb_size; MemoryRegion fifo_ram; uint8_t *fifo_ptr; @@ -756,10 +756,10 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) return 0x0; case SVGA_REG_VRAM_SIZE: - return s->vga.vram_size; + return s->vga.vram_size; /* No physical VRAM besides the framebuffer */ case SVGA_REG_FB_SIZE: - return s->fb_size; + return s->vga.vram_size; case SVGA_REG_CAPABILITIES: caps = SVGA_CAP_NONE; @@ -848,7 +848,6 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) s->invalidated = 1; s->vga.invalidate(&s->vga); if (s->enable) { - s->fb_size = ((s->depth + 7) >> 3) * s->new_width * s->new_height; vga_dirty_log_stop(&s->vga); } else { vga_dirty_log_start(&s->vga); @@ -873,10 +872,9 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) } break; - case SVGA_REG_DEPTH: case SVGA_REG_BITS_PER_PIXEL: if (value != ds_get_bits_per_pixel(s->vga.ds)) { - printf("%s: Bad colour depth: %i bits\n", __func__, value); + printf("%s: Bad bits per pixel: %i bits\n", __func__, value); s->config = 0; } break; @@ -939,6 +937,7 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) #endif break; + case SVGA_REG_DEPTH: case SVGA_REG_MEM_REGS: case SVGA_REG_NUM_DISPLAYS: case SVGA_REG_PITCHLOCK: @@ -1077,7 +1076,7 @@ static const VMStateDescription vmstate_vmware_vga_internal = { .minimum_version_id_old = 0, .post_load = vmsvga_post_load, .fields = (VMStateField[]) { - VMSTATE_INT32_EQUAL(depth, struct vmsvga_state_s), + VMSTATE_UNUSED(4), /* was depth */ VMSTATE_INT32(enable, struct vmsvga_state_s), VMSTATE_INT32(config, struct vmsvga_state_s), VMSTATE_INT32(cursor.id, struct vmsvga_state_s), @@ -1092,7 +1091,7 @@ static const VMStateDescription vmstate_vmware_vga_internal = { VMSTATE_UINT32(guest, struct vmsvga_state_s), VMSTATE_UINT32(svgaid, struct vmsvga_state_s), VMSTATE_INT32(syncing, struct vmsvga_state_s), - VMSTATE_INT32(fb_size, struct vmsvga_state_s), + VMSTATE_UNUSED(4), /* was fb_size */ VMSTATE_END_OF_LIST() } }; From b51d7b2e10564aedc83513d3961a69f22509eaa9 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 3 Nov 2012 12:47:08 +0100 Subject: [PATCH 1533/2270] vmware_vga: Allow simple drivers to work without using the fifo Postpone stopping the dirty log to the point where the command fifo is configured to allow drivers which don't use the fifo to work too. (Without this the picture rendered into the vram never got to the screen and the DIRECT_VRAM option meant to support this case was removed a year ago.) Signed-off-by: BALATON Zoltan Signed-off-by: Blue Swirl --- hw/vga.c | 2 +- hw/vga_int.h | 1 + hw/vmware_vga.c | 34 +++++++++++++++++++++------------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/hw/vga.c b/hw/vga.c index 023134ef68..81aa76bef9 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -1616,7 +1616,7 @@ void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2) } } -static void vga_sync_dirty_bitmap(VGACommonState *s) +void vga_sync_dirty_bitmap(VGACommonState *s) { memory_region_sync_dirty_bitmap(&s->vram); } diff --git a/hw/vga_int.h b/hw/vga_int.h index d4da777e62..bcb738d8c9 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -186,6 +186,7 @@ MemoryRegion *vga_init_io(VGACommonState *s, const MemoryRegionPortio **vbe_ports); void vga_common_reset(VGACommonState *s); +void vga_sync_dirty_bitmap(VGACommonState *s); void vga_dirty_log_start(VGACommonState *s); void vga_dirty_log_stop(VGACommonState *s); diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 038994e705..7c766fb3da 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -317,14 +317,6 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s, dpy_gfx_update(s->vga.ds, x, y, w, h); } -static inline void vmsvga_update_screen(struct vmsvga_state_s *s) -{ - memcpy(ds_get_data(s->vga.ds), s->vga.vram_ptr, - ds_get_linesize(s->vga.ds) * ds_get_height(s->vga.ds)); - dpy_gfx_update(s->vga.ds, 0, 0, - ds_get_width(s->vga.ds), ds_get_height(s->vga.ds)); -} - static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s, int x, int y, int w, int h) { @@ -843,11 +835,10 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) break; case SVGA_REG_ENABLE: - s->enable = value; - s->config &= !!value; + s->enable = !!value; s->invalidated = 1; s->vga.invalidate(&s->vga); - if (s->enable) { + if (s->enable && s->config) { vga_dirty_log_stop(&s->vga); } else { vga_dirty_log_start(&s->vga); @@ -895,6 +886,7 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) if (CMD(max) < CMD(min) + 10 * 1024) { break; } + vga_dirty_log_stop(&s->vga); } s->config = !!value; break; @@ -977,6 +969,8 @@ static inline void vmsvga_check_size(struct vmsvga_state_s *s) static void vmsvga_update_display(void *opaque) { struct vmsvga_state_s *s = opaque; + bool dirty = false; + if (!s->enable) { s->vga.update(&s->vga); return; @@ -991,9 +985,23 @@ static void vmsvga_update_display(void *opaque) * Is it more efficient to look at vram VGA-dirty bits or wait * for the driver to issue SVGA_CMD_UPDATE? */ - if (s->invalidated) { + if (memory_region_is_logging(&s->vga.vram)) { + vga_sync_dirty_bitmap(&s->vga); + dirty = memory_region_get_dirty(&s->vga.vram, 0, + ds_get_linesize(s->vga.ds) * ds_get_height(s->vga.ds), + DIRTY_MEMORY_VGA); + } + if (s->invalidated || dirty) { s->invalidated = 0; - vmsvga_update_screen(s); + memcpy(ds_get_data(s->vga.ds), s->vga.vram_ptr, + ds_get_linesize(s->vga.ds) * ds_get_height(s->vga.ds)); + dpy_gfx_update(s->vga.ds, 0, 0, + ds_get_width(s->vga.ds), ds_get_height(s->vga.ds)); + } + if (dirty) { + memory_region_reset_dirty(&s->vga.vram, 0, + ds_get_linesize(s->vga.ds) * ds_get_height(s->vga.ds), + DIRTY_MEMORY_VGA); } } From ed224a56b3b3234d99832a063ee3aaee3613d115 Mon Sep 17 00:00:00 2001 From: malc Date: Sat, 3 Nov 2012 19:38:32 +0400 Subject: [PATCH 1534/2270] tcg/ppc: ld/st optimization Signed-off-by: malc --- configure | 2 +- exec-all.h | 3 + tcg/ppc/tcg-target.c | 465 ++++++++++++++++++++++++------------------- 3 files changed, 268 insertions(+), 202 deletions(-) diff --git a/configure b/configure index 8e70cbb224..7290f50e11 100755 --- a/configure +++ b/configure @@ -3882,7 +3882,7 @@ upper() { } case "$cpu" in - i386|x86_64) + i386|x86_64|ppc) echo "CONFIG_QEMU_LDST_OPTIMIZATION=y" >> $config_target_mak ;; esac diff --git a/exec-all.h b/exec-all.h index 898fe2d862..94ed613e37 100644 --- a/exec-all.h +++ b/exec-all.h @@ -335,6 +335,9 @@ extern uintptr_t tci_tb_ptr; # define GETRA() ((uintptr_t)__builtin_return_address(0)) # define GETPC_LDST() ((uintptr_t)(GETRA() + 7 + \ *(int32_t *)((void *)GETRA() + 3) - 1)) +# elif defined (_ARCH_PPC) && !defined (_ARCH_PPC64) +# define GETRA() ((uintptr_t)__builtin_return_address(0)) +# define GETPC_LDST() ((uintptr_t) ((*(int32_t *)(GETRA() + 4)) - 1)) # else # error "CONFIG_QEMU_LDST_OPTIMIZATION needs GETPC_LDST() implementation!" # endif diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 60b7b92621..a1c74cea63 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -39,8 +39,6 @@ static uint8_t *tb_ret_addr; #define LR_OFFSET 4 #endif -#define FAST_PATH - #ifndef GUEST_BASE #define GUEST_BASE 0 #endif @@ -520,6 +518,37 @@ static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg) #if defined(CONFIG_SOFTMMU) +static void add_qemu_ldst_label (TCGContext *s, + int is_ld, + int opc, + int data_reg, + int data_reg2, + int addrlo_reg, + int addrhi_reg, + int mem_index, + uint8_t *raddr, + uint8_t *label_ptr) +{ + int idx; + TCGLabelQemuLdst *label; + + if (s->nb_qemu_ldst_labels >= TCG_MAX_QEMU_LDST) { + tcg_abort(); + } + + idx = s->nb_qemu_ldst_labels++; + label = (TCGLabelQemuLdst *)&s->qemu_ldst_labels[idx]; + label->is_ld = is_ld; + label->opc = opc; + label->datalo_reg = data_reg; + label->datahi_reg = data_reg2; + label->addrlo_reg = addrlo_reg; + label->addrhi_reg = addrhi_reg; + label->mem_index = mem_index; + label->raddr = raddr; + label->label_ptr[0] = label_ptr; +} + #include "../../softmmu_defs.h" /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, @@ -539,36 +568,12 @@ static const void * const qemu_st_helpers[4] = { helper_stl_mmu, helper_stq_mmu, }; -#endif -static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) +static void tcg_out_tlb_check (TCGContext *s, int r0, int r1, int r2, + int addr_reg, int addr_reg2, int s_bits, + int offset1, int offset2, uint8_t **label_ptr) { - int addr_reg, data_reg, data_reg2, r0, r1, rbase, bswap; -#ifdef CONFIG_SOFTMMU - int mem_index, s_bits, r2, ir; - void *label1_ptr, *label2_ptr; -#if TARGET_LONG_BITS == 64 - int addr_reg2; -#endif -#endif - - data_reg = *args++; - if (opc == 3) - data_reg2 = *args++; - else - data_reg2 = 0; - addr_reg = *args++; - -#ifdef CONFIG_SOFTMMU -#if TARGET_LONG_BITS == 64 - addr_reg2 = *args++; -#endif - mem_index = *args; - s_bits = opc & 3; - r0 = 3; - r1 = 4; - r2 = 0; - rbase = 0; + uint16_t retranst; tcg_out32 (s, (RLWINM | RA (r0) @@ -582,7 +587,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) tcg_out32 (s, (LWZU | RT (r1) | RA (r0) - | offsetof (CPUArchState, tlb_table[mem_index][0].addr_read) + | offset1 ) ); tcg_out32 (s, (RLWINM @@ -600,77 +605,58 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) tcg_out32 (s, CMP | BF (6) | RA (addr_reg2) | RB (r1)); tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ)); #endif + *label_ptr = s->code_ptr; + retranst = ((uint16_t *) s->code_ptr)[1] & ~3; + tcg_out32 (s, BC | BI (7, CR_EQ) | retranst | BO_COND_FALSE); - label1_ptr = s->code_ptr; -#ifdef FAST_PATH - tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE); -#endif - - /* slow path */ - ir = 3; - tcg_out_mov (s, TCG_TYPE_I32, ir++, TCG_AREG0); -#if TARGET_LONG_BITS == 32 - tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg); -#else -#ifdef TCG_TARGET_CALL_ALIGN_ARGS - ir |= 1; -#endif - tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg2); - tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg); -#endif - tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index); - - tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1); - switch (opc) { - case 0|4: - tcg_out32 (s, EXTSB | RA (data_reg) | RS (3)); - break; - case 1|4: - tcg_out32 (s, EXTSH | RA (data_reg) | RS (3)); - break; - case 0: - case 1: - case 2: - if (data_reg != 3) - tcg_out_mov (s, TCG_TYPE_I32, data_reg, 3); - break; - case 3: - if (data_reg == 3) { - if (data_reg2 == 4) { - tcg_out_mov (s, TCG_TYPE_I32, 0, 4); - tcg_out_mov (s, TCG_TYPE_I32, 4, 3); - tcg_out_mov (s, TCG_TYPE_I32, 3, 0); - } - else { - tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 3); - tcg_out_mov (s, TCG_TYPE_I32, 3, 4); - } - } - else { - if (data_reg != 4) tcg_out_mov (s, TCG_TYPE_I32, data_reg, 4); - if (data_reg2 != 3) tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 3); - } - break; - } - label2_ptr = s->code_ptr; - tcg_out32 (s, B); - - /* label1: fast path */ -#ifdef FAST_PATH - reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr); -#endif - - /* r0 now contains &env->tlb_table[mem_index][index].addr_read */ + /* r0 now contains &env->tlb_table[mem_index][index].addr_x */ tcg_out32 (s, (LWZ | RT (r0) | RA (r0) - | (offsetof (CPUTLBEntry, addend) - - offsetof (CPUTLBEntry, addr_read)) - )); + | offset2 + ) + ); /* r0 = env->tlb_table[mem_index][index].addend */ tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg)); /* r0 = env->tlb_table[mem_index][index].addend + addr */ +} +#endif + +static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) +{ + int addr_reg, addr_reg2, data_reg, data_reg2, r0, r1, rbase, bswap; +#ifdef CONFIG_SOFTMMU + int mem_index, s_bits, r2; + uint8_t *label_ptr; +#endif + + data_reg = *args++; + if (opc == 3) + data_reg2 = *args++; + else + data_reg2 = 0; + addr_reg = *args++; + +#ifdef CONFIG_SOFTMMU +#if TARGET_LONG_BITS == 64 + addr_reg2 = *args++; +#else + addr_reg2 = 0; +#endif + mem_index = *args; + s_bits = opc & 3; + r0 = 3; + r1 = 4; + r2 = 0; + rbase = 0; + + tcg_out_tlb_check ( + s, r0, r1, r2, addr_reg, addr_reg2, s_bits, + offsetof (CPUArchState, tlb_table[mem_index][0].addr_read), + offsetof (CPUTLBEntry, addend) - offsetof (CPUTLBEntry, addr_read), + &label_ptr + ); #else /* !CONFIG_SOFTMMU */ r0 = addr_reg; r1 = 3; @@ -736,21 +722,26 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) } break; } - #ifdef CONFIG_SOFTMMU - reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr); + add_qemu_ldst_label (s, + 1, + opc, + data_reg, + data_reg2, + addr_reg, + addr_reg2, + mem_index, + s->code_ptr, + label_ptr); #endif } static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) { - int addr_reg, r0, r1, data_reg, data_reg2, bswap, rbase; + int addr_reg, addr_reg2, r0, r1, data_reg, data_reg2, bswap, rbase; #ifdef CONFIG_SOFTMMU - int mem_index, r2, ir; - void *label1_ptr, *label2_ptr; -#if TARGET_LONG_BITS == 64 - int addr_reg2; -#endif + int mem_index, r2; + uint8_t *label_ptr; #endif data_reg = *args++; @@ -763,6 +754,8 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) #ifdef CONFIG_SOFTMMU #if TARGET_LONG_BITS == 64 addr_reg2 = *args++; +#else + addr_reg2 = 0; #endif mem_index = *args; r0 = 3; @@ -770,105 +763,12 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) r2 = 0; rbase = 0; - tcg_out32 (s, (RLWINM - | RA (r0) - | RS (addr_reg) - | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS)) - | MB (32 - (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)) - | ME (31 - CPU_TLB_ENTRY_BITS) - ) + tcg_out_tlb_check ( + s, r0, r1, r2, addr_reg, addr_reg2, opc & 3, + offsetof (CPUArchState, tlb_table[mem_index][0].addr_write), + offsetof (CPUTLBEntry, addend) - offsetof (CPUTLBEntry, addr_write), + &label_ptr ); - tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0)); - tcg_out32 (s, (LWZU - | RT (r1) - | RA (r0) - | offsetof (CPUArchState, tlb_table[mem_index][0].addr_write) - ) - ); - tcg_out32 (s, (RLWINM - | RA (r2) - | RS (addr_reg) - | SH (0) - | MB ((32 - opc) & 31) - | ME (31 - TARGET_PAGE_BITS) - ) - ); - - tcg_out32 (s, CMP | (7 << 23) | RA (r2) | RB (r1)); -#if TARGET_LONG_BITS == 64 - tcg_out32 (s, LWZ | RT (r1) | RA (r0) | 4); - tcg_out32 (s, CMP | BF (6) | RA (addr_reg2) | RB (r1)); - tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ)); -#endif - - label1_ptr = s->code_ptr; -#ifdef FAST_PATH - tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE); -#endif - - /* slow path */ - ir = 3; - tcg_out_mov (s, TCG_TYPE_I32, ir++, TCG_AREG0); -#if TARGET_LONG_BITS == 32 - tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg); -#else -#ifdef TCG_TARGET_CALL_ALIGN_ARGS - ir |= 1; -#endif - tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg2); - tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg); -#endif - - switch (opc) { - case 0: - tcg_out32 (s, (RLWINM - | RA (ir) - | RS (data_reg) - | SH (0) - | MB (24) - | ME (31))); - break; - case 1: - tcg_out32 (s, (RLWINM - | RA (ir) - | RS (data_reg) - | SH (0) - | MB (16) - | ME (31))); - break; - case 2: - tcg_out_mov (s, TCG_TYPE_I32, ir, data_reg); - break; - case 3: -#ifdef TCG_TARGET_CALL_ALIGN_ARGS - ir |= 1; -#endif - tcg_out_mov (s, TCG_TYPE_I32, ir++, data_reg2); - tcg_out_mov (s, TCG_TYPE_I32, ir, data_reg); - break; - } - ir++; - - tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index); - tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1); - label2_ptr = s->code_ptr; - tcg_out32 (s, B); - - /* label1: fast path */ -#ifdef FAST_PATH - reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr); -#endif - - tcg_out32 (s, (LWZ - | RT (r0) - | RA (r0) - | (offsetof (CPUTLBEntry, addend) - - offsetof (CPUTLBEntry, addr_write)) - )); - /* r0 = env->tlb_table[mem_index][index].addend */ - tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg)); - /* r0 = env->tlb_table[mem_index][index].addend + addr */ - #else /* !CONFIG_SOFTMMU */ r0 = addr_reg; r1 = 3; @@ -916,10 +816,173 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) } #ifdef CONFIG_SOFTMMU - reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr); + add_qemu_ldst_label (s, + 0, + opc, + data_reg, + data_reg2, + addr_reg, + addr_reg2, + mem_index, + s->code_ptr, + label_ptr); #endif } +#if defined(CONFIG_SOFTMMU) +static void tcg_out_qemu_ld_slow_path (TCGContext *s, TCGLabelQemuLdst *label) +{ + int s_bits; + int ir; + int opc = label->opc; + int mem_index = label->mem_index; + int data_reg = label->datalo_reg; + int data_reg2 = label->datahi_reg; + int addr_reg = label->addrlo_reg; + uint8_t *raddr = label->raddr; + uint8_t **label_ptr = &label->label_ptr[0]; + + s_bits = opc & 3; + + /* resolve label address */ + reloc_pc14 (label_ptr[0], (tcg_target_long) s->code_ptr); + + /* slow path */ + ir = 3; + tcg_out_mov (s, TCG_TYPE_I32, ir++, TCG_AREG0); +#if TARGET_LONG_BITS == 32 + tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg); +#else +#ifdef TCG_TARGET_CALL_ALIGN_ARGS + ir |= 1; +#endif + tcg_out_mov (s, TCG_TYPE_I32, ir++, label->addrhi_reg); + tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg); +#endif + tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index); + tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1); + tcg_out32 (s, B | 8); + tcg_out32 (s, (tcg_target_long) raddr); + switch (opc) { + case 0|4: + tcg_out32 (s, EXTSB | RA (data_reg) | RS (3)); + break; + case 1|4: + tcg_out32 (s, EXTSH | RA (data_reg) | RS (3)); + break; + case 0: + case 1: + case 2: + if (data_reg != 3) + tcg_out_mov (s, TCG_TYPE_I32, data_reg, 3); + break; + case 3: + if (data_reg == 3) { + if (data_reg2 == 4) { + tcg_out_mov (s, TCG_TYPE_I32, 0, 4); + tcg_out_mov (s, TCG_TYPE_I32, 4, 3); + tcg_out_mov (s, TCG_TYPE_I32, 3, 0); + } + else { + tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 3); + tcg_out_mov (s, TCG_TYPE_I32, 3, 4); + } + } + else { + if (data_reg != 4) tcg_out_mov (s, TCG_TYPE_I32, data_reg, 4); + if (data_reg2 != 3) tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 3); + } + break; + } + /* Jump to the code corresponding to next IR of qemu_st */ + tcg_out_b (s, 0, (tcg_target_long) raddr); +} + +static void tcg_out_qemu_st_slow_path (TCGContext *s, TCGLabelQemuLdst *label) +{ + int s_bits; + int ir; + int opc = label->opc; + int mem_index = label->mem_index; + int data_reg = label->datalo_reg; + int data_reg2 = label->datahi_reg; + int addr_reg = label->addrlo_reg; + uint8_t *raddr = label->raddr; + uint8_t **label_ptr = &label->label_ptr[0]; + + s_bits = opc & 3; + + /* resolve label address */ + reloc_pc14 (label_ptr[0], (tcg_target_long) s->code_ptr); + + /* slow path */ + ir = 3; + tcg_out_mov (s, TCG_TYPE_I32, ir++, TCG_AREG0); +#if TARGET_LONG_BITS == 32 + tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg); +#else +#ifdef TCG_TARGET_CALL_ALIGN_ARGS + ir |= 1; +#endif + tcg_out_mov (s, TCG_TYPE_I32, ir++, label->addrhi_reg); + tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg); +#endif + + switch (opc) { + case 0: + tcg_out32 (s, (RLWINM + | RA (ir) + | RS (data_reg) + | SH (0) + | MB (24) + | ME (31))); + break; + case 1: + tcg_out32 (s, (RLWINM + | RA (ir) + | RS (data_reg) + | SH (0) + | MB (16) + | ME (31))); + break; + case 2: + tcg_out_mov (s, TCG_TYPE_I32, ir, data_reg); + break; + case 3: +#ifdef TCG_TARGET_CALL_ALIGN_ARGS + ir |= 1; +#endif + tcg_out_mov (s, TCG_TYPE_I32, ir++, data_reg2); + tcg_out_mov (s, TCG_TYPE_I32, ir, data_reg); + break; + } + ir++; + + tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index); + tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1); + tcg_out32 (s, B | 8); + tcg_out32 (s, (tcg_target_long) raddr); + tcg_out_b (s, 0, (tcg_target_long) raddr); +} + +void tcg_out_tb_finalize(TCGContext *s) +{ + int i; + TCGLabelQemuLdst *label; + + /* qemu_ld/st slow paths */ + for (i = 0; i < s->nb_qemu_ldst_labels; i++) { + label = (TCGLabelQemuLdst *) &s->qemu_ldst_labels[i]; + if (label->is_ld) { + tcg_out_qemu_ld_slow_path (s, label); + } + else { + tcg_out_qemu_st_slow_path (s, label); + } + } +} +#endif + static void tcg_target_qemu_prologue (TCGContext *s) { int i, frame_size; From 30ea833941a7de51454cf99913f5edb3e7e21c0d Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Fri, 2 Nov 2012 16:12:53 -0500 Subject: [PATCH 1535/2270] build: pthread_atfork() needs include of pthread.h Cc: Paolo Bonzini Signed-off-by: Anthony Liguori --- qemu-timer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/qemu-timer.c b/qemu-timer.c index 7b2217aab0..8d9cf38bb2 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -30,6 +30,9 @@ #include "hw/hw.h" #include "qemu-timer.h" +#ifdef CONFIG_POSIX +#include +#endif #ifdef _WIN32 #include From 1cfd981ff1e8ff0858cd71cfae0c7c7ba741f380 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sat, 3 Nov 2012 18:48:35 +0000 Subject: [PATCH 1536/2270] target-mips: use ULL for 64 bit constants Fix build on a 32 bit host: CC mips-softmmu/target-mips/dsp_helper.o /src/qemu/target-mips/dsp_helper.c: In function 'helper_dextr_rs_w': /src/qemu/target-mips/dsp_helper.c:3556: error: integer constant is too large for 'long' type /src/qemu/target-mips/dsp_helper.c: In function 'helper_extr_s_h': /src/qemu/target-mips/dsp_helper.c:3656: error: integer constant is too large for 'long' type Signed-off-by: Blue Swirl Signed-off-by: Aurelien Jarno --- target-mips/dsp_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index b59133ea8f..e7949c22c0 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -3553,7 +3553,7 @@ target_ulong helper_dextr_rs_w(target_ulong ac, target_ulong shift, if (temp128 == 0) { temp[0] = 0x0FFFFFFFF; } else { - temp[0] = 0x0100000000; + temp[0] = 0x0100000000ULL; } set_DSPControl_overflow_flag(1, 23, env); } @@ -3653,7 +3653,7 @@ target_ulong helper_extr_s_h(target_ulong ac, target_ulong shift, if (temp > (int64_t)0x7FFF) { temp = 0x00007FFF; set_DSPControl_overflow_flag(1, 23, env); - } else if (temp < (int64_t)0xFFFFFFFFFFFF8000) { + } else if (temp < (int64_t)0xFFFFFFFFFFFF8000ULL) { temp = 0xFFFF8000; set_DSPControl_overflow_flag(1, 23, env); } From 48f4ba671bbb3dd212002d57b72a23375f51619b Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Mon, 15 Oct 2012 14:54:03 +0200 Subject: [PATCH 1537/2270] hw/qxl: guest bug on primary create with stride %4 != 0 Due to usage of pixman for rendering on all spice surfaces we have pixman's requirement that the stride be word aligned. A guest not honoring that can crash spice and qemu with it due to failure to create a surface (in spice-server). Avoid this early on in primary surface creation and offscreen surface creation. Recently windows guests got odd width support which triggers a non word aligned primary surface in 16bit color depth. Off screen surfaces have always been word aligned, but doesn't hurt to check them here too. Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hw/qxl.c b/hw/qxl.c index 1f56fcd169..cc16eaf2aa 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -447,6 +447,12 @@ static int qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext) qxl->ssd.num_surfaces); return 1; } + if (cmd->type == QXL_SURFACE_CMD_CREATE && + (cmd->u.surface_create.stride & 0x03) != 0) { + qxl_set_guest_bug(qxl, "QXL_CMD_SURFACE stride = %d %% 4 != 0\n", + cmd->u.surface_create.stride); + return 1; + } qemu_mutex_lock(&qxl->track_lock); if (cmd->type == QXL_SURFACE_CMD_CREATE) { qxl->guest_surfaces.cmds[id] = ext->cmd.data; @@ -1357,6 +1363,12 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm, trace_qxl_create_guest_primary_rest(qxl->id, sc->stride, sc->type, sc->flags); + if ((surface.stride & 0x3) != 0) { + qxl_set_guest_bug(qxl, "primary surface stride = %d %% 4 != 0", + surface.stride); + return; + } + surface.mouse_mode = true; surface.group_id = MEMSLOT_GROUP_GUEST; if (loadvm) { From 511aefb0c60e3063ead76d4ba6aabf619eed18ef Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Thu, 1 Nov 2012 14:56:00 +0200 Subject: [PATCH 1538/2270] hw/qxl: qxl_send_events: nop if stopped Added a trace point for easy logging. RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=870972 Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 8 +++++++- trace-events | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/hw/qxl.c b/hw/qxl.c index cc16eaf2aa..f19451bd6f 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1701,7 +1701,13 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events) uint32_t le_events = cpu_to_le32(events); trace_qxl_send_events(d->id, events); - assert(qemu_spice_display_is_running(&d->ssd)); + if (!qemu_spice_display_is_running(&d->ssd)) { + /* spice-server tracks guest running state and should not do this */ + fprintf(stderr, "%s: spice-server bug: guest stopped, ignoring\n", + __func__); + trace_qxl_send_events_vm_stopped(d->id, events); + return; + } old_pending = __sync_fetch_and_or(&d->ram->int_pending, le_events); if ((old_pending & le_events) == le_events) { return; diff --git a/trace-events b/trace-events index b84d631dc7..e1a37cc26f 100644 --- a/trace-events +++ b/trace-events @@ -1001,6 +1001,7 @@ qxl_spice_update_area(int qid, uint32_t surface_id, uint32_t left, uint32_t righ qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dirty_region) "%d #d=%d clear=%d" qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d offset=%d size=%d" qxl_send_events(int qid, uint32_t events) "%d %d" +qxl_send_events_vm_stopped(int qid, uint32_t events) "%d %d" qxl_set_guest_bug(int qid) "%d" qxl_interrupt_client_monitors_config(int qid, int num_heads, void *heads) "%d %d %p" qxl_client_monitors_config_unsupported_by_guest(int qid, uint32_t int_mask, void *client_monitors_config) "%d %X %p" From 958c2bceba06696e9c223498aaf81d06ce95f608 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 14 Sep 2012 22:17:44 +0200 Subject: [PATCH 1539/2270] qxl: fix cursor reset When resetting the qxl cursor notify the qemu displaystate too. Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/qxl.c b/hw/qxl.c index f19451bd6f..063970dc28 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -293,6 +293,10 @@ void qxl_spice_reset_cursor(PCIQXLDevice *qxl) qemu_mutex_lock(&qxl->track_lock); qxl->guest_cursor = 0; qemu_mutex_unlock(&qxl->track_lock); + if (qxl->ssd.cursor) { + cursor_put(qxl->ssd.cursor); + } + qxl->ssd.cursor = cursor_builtin_hidden(); } From e32c25b5f2452c7fed4dbe8962f4a9f4831fbe24 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 30 Oct 2012 14:55:12 +0100 Subject: [PATCH 1540/2270] qxl: call dpy_gfx_resize when entering vga mode When entering vga mode the display size likely changes, notify all displaychangelisteners about this. Probably went unnoticed for a while as one if the first things the guest does after leaving qxl native mode and entering qxl vga mode is to set the vga video mode. But there is still a small window where qemu can operate on stale data, leading to crashes now and then. https://bugzilla.redhat.com/show_bug.cgi?id=865767 Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/qxl.c b/hw/qxl.c index 063970dc28..e7bf3a11a7 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1069,7 +1069,7 @@ static void qxl_enter_vga_mode(PCIQXLDevice *d) trace_qxl_enter_vga_mode(d->id); qemu_spice_create_host_primary(&d->ssd); d->mode = QXL_MODE_VGA; - memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty)); + dpy_gfx_resize(d->ssd.ds); vga_dirty_log_start(&d->vga); } From d9a86569ca3617a495ffb352e9a390747eaa6b24 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 2 Nov 2012 09:12:49 +0100 Subject: [PATCH 1541/2270] spice: switch to pixman Switch over spice-display.c to use the pixman library instead of the home-grown pflib bits. Signed-off-by: Gerd Hoffmann --- console.h | 5 +++++ qemu-pixman.c | 13 ++++++++++++ qemu-pixman.h | 2 ++ ui/spice-display.c | 51 ++++++++++++++++++++-------------------------- ui/spice-display.h | 7 +++---- 5 files changed, 45 insertions(+), 33 deletions(-) diff --git a/console.h b/console.h index 70c9a55942..50a0512f32 100644 --- a/console.h +++ b/console.h @@ -377,6 +377,11 @@ static inline pixman_format_code_t ds_get_format(DisplayState *ds) return ds->surface->format; } +static inline pixman_image_t *ds_get_image(DisplayState *ds) +{ + return ds->surface->image; +} + static inline int ds_get_depth(DisplayState *ds) { return ds->surface->pf.depth; diff --git a/qemu-pixman.c b/qemu-pixman.c index 7547ed74c1..71a9ea43a6 100644 --- a/qemu-pixman.c +++ b/qemu-pixman.c @@ -51,6 +51,19 @@ void qemu_pixman_linebuf_fill(pixman_image_t *linebuf, pixman_image_t *fb, 0, y, 0, 0, 0, 0, width, 1); } +pixman_image_t *qemu_pixman_mirror_create(pixman_format_code_t format, + pixman_image_t *image) +{ + pixman_image_t *mirror; + + mirror = pixman_image_create_bits(format, + pixman_image_get_width(image), + pixman_image_get_height(image), + NULL, + pixman_image_get_stride(image)); + return mirror; +} + void qemu_pixman_image_unref(pixman_image_t *image) { if (image == NULL) { diff --git a/qemu-pixman.h b/qemu-pixman.h index 7652c41277..e267d73683 100644 --- a/qemu-pixman.h +++ b/qemu-pixman.h @@ -27,6 +27,8 @@ pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format, int width); void qemu_pixman_linebuf_fill(pixman_image_t *linebuf, pixman_image_t *fb, int width, int y); +pixman_image_t *qemu_pixman_mirror_create(pixman_format_code_t format, + pixman_image_t *image); void qemu_pixman_image_unref(pixman_image_t *image); #endif /* QEMU_PIXMAN_H */ diff --git a/ui/spice-display.c b/ui/spice-display.c index fb99148349..fe2fdfba68 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -150,9 +150,9 @@ static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd, QXLDrawable *drawable; QXLImage *image; QXLCommand *cmd; - uint8_t *src, *mirror, *dst; - int by, bw, bh, offset, bytes; + int bw, bh; struct timespec time_space; + pixman_image_t *dest; trace_qemu_spice_create_update( rect->left, rect->right, @@ -195,20 +195,15 @@ static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd, image->bitmap.palette = 0; image->bitmap.format = SPICE_BITMAP_FMT_32BIT; - offset = - rect->top * ds_get_linesize(ssd->ds) + - rect->left * ds_get_bytes_per_pixel(ssd->ds); - bytes = ds_get_bytes_per_pixel(ssd->ds) * bw; - src = ds_get_data(ssd->ds) + offset; - mirror = ssd->ds_mirror + offset; - dst = update->bitmap; - for (by = 0; by < bh; by++) { - memcpy(mirror, src, bytes); - qemu_pf_conv_run(ssd->conv, dst, mirror, bw); - src += ds_get_linesize(ssd->ds); - mirror += ds_get_linesize(ssd->ds); - dst += image->bitmap.stride; - } + dest = pixman_image_create_bits(PIXMAN_x8r8g8b8, bw, bh, + (void *)update->bitmap, bw * 4); + pixman_image_composite(PIXMAN_OP_SRC, ssd->surface, NULL, ssd->mirror, + rect->left, rect->top, 0, 0, + rect->left, rect->top, bw, bh); + pixman_image_composite(PIXMAN_OP_SRC, ssd->mirror, NULL, dest, + rect->left, rect->top, 0, 0, + 0, 0, bw, bh); + pixman_image_unref(dest); cmd->type = QXL_CMD_DRAW; cmd->data = (uintptr_t)drawable; @@ -229,14 +224,10 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) return; }; - if (ssd->conv == NULL) { - PixelFormat dst = qemu_default_pixelformat(32); - ssd->conv = qemu_pf_conv_get(&dst, &ssd->ds->surface->pf); - assert(ssd->conv); - } - if (ssd->ds_mirror == NULL) { - int size = ds_get_height(ssd->ds) * ds_get_linesize(ssd->ds); - ssd->ds_mirror = g_malloc0(size); + if (ssd->surface == NULL) { + ssd->surface = pixman_image_ref(ds_get_image(ssd->ds)); + ssd->mirror = qemu_pixman_mirror_create(ds_get_format(ssd->ds), + ds_get_image(ssd->ds)); } for (blk = 0; blk < blocks; blk++) { @@ -244,7 +235,7 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) } guest = ds_get_data(ssd->ds); - mirror = ssd->ds_mirror; + mirror = (void *)pixman_image_get_data(ssd->mirror); for (y = ssd->dirty.top; y < ssd->dirty.bottom; y++) { yoff = y * ds_get_linesize(ssd->ds); for (x = ssd->dirty.left; x < ssd->dirty.right; x += blksize) { @@ -383,10 +374,12 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd) dprint(1, "%s:\n", __FUNCTION__); memset(&ssd->dirty, 0, sizeof(ssd->dirty)); - qemu_pf_conv_put(ssd->conv); - ssd->conv = NULL; - g_free(ssd->ds_mirror); - ssd->ds_mirror = NULL; + if (ssd->surface) { + pixman_image_unref(ssd->surface); + ssd->surface = NULL; + pixman_image_unref(ssd->mirror); + ssd->mirror = NULL; + } qemu_mutex_lock(&ssd->lock); while ((update = QTAILQ_FIRST(&ssd->updates)) != NULL) { diff --git a/ui/spice-display.h b/ui/spice-display.h index d7669277fd..38b6ea98b3 100644 --- a/ui/spice-display.h +++ b/ui/spice-display.h @@ -20,8 +20,7 @@ #include #include "qemu-thread.h" -#include "console.h" -#include "pflib.h" +#include "qemu-pixman.h" #include "sysemu.h" #define NUM_MEMSLOTS 8 @@ -72,13 +71,13 @@ typedef struct SimpleSpiceUpdate SimpleSpiceUpdate; struct SimpleSpiceDisplay { DisplayState *ds; - uint8_t *ds_mirror; void *buf; int bufsize; QXLWorker *worker; QXLInstance qxl; uint32_t unique; - QemuPfConv *conv; + pixman_image_t *surface; + pixman_image_t *mirror; int32_t num_surfaces; QXLRect dirty; From 365b1e9e3486aaa55f30df6f16ecafffaef6ec98 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 18 Sep 2012 08:52:26 +0200 Subject: [PATCH 1542/2270] pflib: unused, remove it. Replaced by pixman library. Signed-off-by: Gerd Hoffmann --- Makefile.objs | 1 - pflib.c | 215 -------------------------------------------------- pflib.h | 20 ----- 3 files changed, 236 deletions(-) delete mode 100644 pflib.c delete mode 100644 pflib.h diff --git a/Makefile.objs b/Makefile.objs index 593a59267c..37be7e26f7 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -78,7 +78,6 @@ common-obj-y += input.o common-obj-y += buffered_file.o migration.o migration-tcp.o common-obj-y += qemu-char.o #aio.o common-obj-y += block-migration.o iohandler.o -common-obj-y += pflib.o common-obj-y += bitmap.o bitops.o common-obj-y += page_cache.o diff --git a/pflib.c b/pflib.c deleted file mode 100644 index 987e11001a..0000000000 --- a/pflib.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * PixelFormat conversion library. - * - * Author: Gerd Hoffmann - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ -#include "qemu-common.h" -#include "console.h" -#include "pflib.h" - -typedef struct QemuPixel QemuPixel; - -typedef void (*pf_convert)(QemuPfConv *conv, - void *dst, void *src, uint32_t cnt); -typedef void (*pf_convert_from)(PixelFormat *pf, - QemuPixel *dst, void *src, uint32_t cnt); -typedef void (*pf_convert_to)(PixelFormat *pf, - void *dst, QemuPixel *src, uint32_t cnt); - -struct QemuPfConv { - pf_convert convert; - PixelFormat src; - PixelFormat dst; - - /* for copy_generic() */ - pf_convert_from conv_from; - pf_convert_to conv_to; - QemuPixel *conv_buf; - uint32_t conv_cnt; -}; - -struct QemuPixel { - uint8_t red; - uint8_t green; - uint8_t blue; - uint8_t alpha; -}; - -/* ----------------------------------------------------------------------- */ -/* PixelFormat -> QemuPixel conversions */ - -static void conv_16_to_pixel(PixelFormat *pf, - QemuPixel *dst, void *src, uint32_t cnt) -{ - uint16_t *src16 = src; - - while (cnt > 0) { - dst->red = ((*src16 & pf->rmask) >> pf->rshift) << (8 - pf->rbits); - dst->green = ((*src16 & pf->gmask) >> pf->gshift) << (8 - pf->gbits); - dst->blue = ((*src16 & pf->bmask) >> pf->bshift) << (8 - pf->bbits); - dst->alpha = ((*src16 & pf->amask) >> pf->ashift) << (8 - pf->abits); - dst++, src16++, cnt--; - } -} - -/* assumes pf->{r,g,b,a}bits == 8 */ -static void conv_32_to_pixel_fast(PixelFormat *pf, - QemuPixel *dst, void *src, uint32_t cnt) -{ - uint32_t *src32 = src; - - while (cnt > 0) { - dst->red = (*src32 & pf->rmask) >> pf->rshift; - dst->green = (*src32 & pf->gmask) >> pf->gshift; - dst->blue = (*src32 & pf->bmask) >> pf->bshift; - dst->alpha = (*src32 & pf->amask) >> pf->ashift; - dst++, src32++, cnt--; - } -} - -static void conv_32_to_pixel_generic(PixelFormat *pf, - QemuPixel *dst, void *src, uint32_t cnt) -{ - uint32_t *src32 = src; - - while (cnt > 0) { - if (pf->rbits < 8) { - dst->red = ((*src32 & pf->rmask) >> pf->rshift) << (8 - pf->rbits); - } else { - dst->red = ((*src32 & pf->rmask) >> pf->rshift) >> (pf->rbits - 8); - } - if (pf->gbits < 8) { - dst->green = ((*src32 & pf->gmask) >> pf->gshift) << (8 - pf->gbits); - } else { - dst->green = ((*src32 & pf->gmask) >> pf->gshift) >> (pf->gbits - 8); - } - if (pf->bbits < 8) { - dst->blue = ((*src32 & pf->bmask) >> pf->bshift) << (8 - pf->bbits); - } else { - dst->blue = ((*src32 & pf->bmask) >> pf->bshift) >> (pf->bbits - 8); - } - if (pf->abits < 8) { - dst->alpha = ((*src32 & pf->amask) >> pf->ashift) << (8 - pf->abits); - } else { - dst->alpha = ((*src32 & pf->amask) >> pf->ashift) >> (pf->abits - 8); - } - dst++, src32++, cnt--; - } -} - -/* ----------------------------------------------------------------------- */ -/* QemuPixel -> PixelFormat conversions */ - -static void conv_pixel_to_16(PixelFormat *pf, - void *dst, QemuPixel *src, uint32_t cnt) -{ - uint16_t *dst16 = dst; - - while (cnt > 0) { - *dst16 = ((uint16_t)src->red >> (8 - pf->rbits)) << pf->rshift; - *dst16 |= ((uint16_t)src->green >> (8 - pf->gbits)) << pf->gshift; - *dst16 |= ((uint16_t)src->blue >> (8 - pf->bbits)) << pf->bshift; - *dst16 |= ((uint16_t)src->alpha >> (8 - pf->abits)) << pf->ashift; - dst16++, src++, cnt--; - } -} - -static void conv_pixel_to_32(PixelFormat *pf, - void *dst, QemuPixel *src, uint32_t cnt) -{ - uint32_t *dst32 = dst; - - while (cnt > 0) { - *dst32 = ((uint32_t)src->red >> (8 - pf->rbits)) << pf->rshift; - *dst32 |= ((uint32_t)src->green >> (8 - pf->gbits)) << pf->gshift; - *dst32 |= ((uint32_t)src->blue >> (8 - pf->bbits)) << pf->bshift; - *dst32 |= ((uint32_t)src->alpha >> (8 - pf->abits)) << pf->ashift; - dst32++, src++, cnt--; - } -} - -/* ----------------------------------------------------------------------- */ -/* PixelFormat -> PixelFormat conversions */ - -static void convert_copy(QemuPfConv *conv, void *dst, void *src, uint32_t cnt) -{ - uint32_t bytes = cnt * conv->src.bytes_per_pixel; - memcpy(dst, src, bytes); -} - -static void convert_generic(QemuPfConv *conv, void *dst, void *src, uint32_t cnt) -{ - if (conv->conv_cnt < cnt) { - conv->conv_cnt = cnt; - conv->conv_buf = g_realloc(conv->conv_buf, sizeof(QemuPixel) * conv->conv_cnt); - } - conv->conv_from(&conv->src, conv->conv_buf, src, cnt); - conv->conv_to(&conv->dst, dst, conv->conv_buf, cnt); -} - -/* ----------------------------------------------------------------------- */ -/* public interface */ - -QemuPfConv *qemu_pf_conv_get(PixelFormat *dst, PixelFormat *src) -{ - QemuPfConv *conv = g_malloc0(sizeof(QemuPfConv)); - - conv->src = *src; - conv->dst = *dst; - - if (memcmp(&conv->src, &conv->dst, sizeof(PixelFormat)) == 0) { - /* formats identical, can simply copy */ - conv->convert = convert_copy; - } else { - /* generic two-step conversion: src -> QemuPixel -> dst */ - switch (conv->src.bytes_per_pixel) { - case 2: - conv->conv_from = conv_16_to_pixel; - break; - case 4: - if (conv->src.rbits == 8 && conv->src.gbits == 8 && conv->src.bbits == 8) { - conv->conv_from = conv_32_to_pixel_fast; - } else { - conv->conv_from = conv_32_to_pixel_generic; - } - break; - default: - goto err; - } - switch (conv->dst.bytes_per_pixel) { - case 2: - conv->conv_to = conv_pixel_to_16; - break; - case 4: - conv->conv_to = conv_pixel_to_32; - break; - default: - goto err; - } - conv->convert = convert_generic; - } - return conv; - -err: - g_free(conv); - return NULL; -} - -void qemu_pf_conv_run(QemuPfConv *conv, void *dst, void *src, uint32_t cnt) -{ - conv->convert(conv, dst, src, cnt); -} - -void qemu_pf_conv_put(QemuPfConv *conv) -{ - if (conv) { - g_free(conv->conv_buf); - g_free(conv); - } -} diff --git a/pflib.h b/pflib.h deleted file mode 100644 index b70c313acf..0000000000 --- a/pflib.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __QEMU_PFLIB_H -#define __QEMU_PFLIB_H - -/* - * PixelFormat conversion library. - * - * Author: Gerd Hoffmann - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - */ - -typedef struct QemuPfConv QemuPfConv; - -QemuPfConv *qemu_pf_conv_get(PixelFormat *dst, PixelFormat *src); -void qemu_pf_conv_run(QemuPfConv *conv, void *dst, void *src, uint32_t cnt); -void qemu_pf_conv_put(QemuPfConv *conv); - -#endif From bdd4df332a1bdb20b7fa39ea741f7830e41e1187 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 2 Nov 2012 09:37:27 +0100 Subject: [PATCH 1543/2270] spice: fix initialization order Register displaychangelistener last, after spice is fully initialized, otherwise we may hit NULL pointer dereferences when qemu starts calling our callbacks. Commit e250d949feb1334828f27f0d145c35f29c4b7639 triggers this bug. Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 10 ++++++++-- ui/spice-display.c | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index e7bf3a11a7..1bc2d32aa8 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -2049,6 +2049,7 @@ static int qxl_init_primary(PCIDevice *dev) PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev); VGACommonState *vga = &qxl->vga; PortioList *qxl_vga_port_list = g_new(PortioList, 1); + int rc; qxl->id = 0; qxl_init_ramsize(qxl); @@ -2063,9 +2064,14 @@ static int qxl_init_primary(PCIDevice *dev) qemu_spice_display_init_common(&qxl->ssd, vga->ds); qxl0 = qxl; - register_displaychangelistener(vga->ds, &display_listener); - return qxl_init_common(qxl); + rc = qxl_init_common(qxl); + if (rc != 0) { + return rc; + } + + register_displaychangelistener(vga->ds, &display_listener); + return rc; } static int qxl_init_secondary(PCIDevice *dev) diff --git a/ui/spice-display.c b/ui/spice-display.c index fe2fdfba68..0cc0116a5d 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -573,7 +573,6 @@ void qemu_spice_display_init(DisplayState *ds) { assert(sdpy.ds == NULL); qemu_spice_display_init_common(&sdpy, ds); - register_displaychangelistener(ds, &display_listener); sdpy.qxl.base.sif = &dpy_interface.base; qemu_spice_add_interface(&sdpy.qxl.base); @@ -581,4 +580,5 @@ void qemu_spice_display_init(DisplayState *ds) qemu_spice_create_host_memslot(&sdpy); qemu_spice_create_host_primary(&sdpy); + register_displaychangelistener(ds, &display_listener); } From c878da3b27ceeed953c9f9a1eb002d59e9dcb4c6 Mon Sep 17 00:00:00 2001 From: malc Date: Mon, 5 Nov 2012 21:47:04 +0400 Subject: [PATCH 1544/2270] tcg/ppc32: Use trampolines to trim the code size for mmu slow path accessors mmu access looks something like: if miss goto slow_path done: ... ; end of the TB slow_path:
 mr r3, r27         ; move areg0 to r3
                    ; (r3 holds the first argument for all the PPC32 ABIs)
 
 b $+8
 .long done
 
 b done

On ppc32  is:

(SysV and Darwin)

mmu_helper is most likely not within direct branching distance from
the call site, necessitating

a. moving 32 bit offset of mmu_helper into a GPR ; 8 bytes
b. moving GPR to CTR/LR                          ; 4 bytes
c. (finally) branching to CTR/LR                 ; 4 bytes

r3 setting              - 4 bytes
call                    - 16 bytes
dummy jump over retaddr - 4 bytes
embedded retaddr        - 4 bytes
         Total overhead - 28 bytes

(PowerOpen (AIX))
a. moving 32 bit offset of mmu_helper's TOC into a GPR1 ; 8 bytes
b. loading 32 bit function pointer into GPR2            ; 4 bytes
c. moving GPR2 to CTR/LR                                ; 4 bytes
d. loading 32 bit small area pointer into R2            ; 4 bytes
e. (finally) branching to CTR/LR                        ; 4 bytes

r3 setting              - 4 bytes
call                    - 24 bytes
dummy jump over retaddr - 4 bytes
embedded retaddr        - 4 bytes
         Total overhead - 36 bytes

Following is done to trim the code size of slow path sections:

In tcg_target_qemu_prologue trampolines are emitted that look like this:

trampoline:
mfspr r3, LR
addi  r3, 4
mtspr LR, r3      ; fixup LR to point over embedded retaddr
mr    r3, r27
 ; tail call of sorts

And slow path becomes:

slow_path:
 
 
 .long done
 
 b done

call                    - 4 bytes (trampoline is within code gen buffer
                                   and most likely accessible via
                                   direct branch)
embedded retaddr        - 4 bytes
         Total overhead - 8 bytes

In the end the icache pressure is decreased by 20/28 bytes at the cost
of an extra jump to trampoline and adjusting LR (to skip over embedded
retaddr) once inside.

Signed-off-by: malc 
---
 exec-all.h           |  2 +-
 tcg/ppc/tcg-target.c | 32 ++++++++++++++++++++++++--------
 2 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/exec-all.h b/exec-all.h
index 94ed613e37..6b3272ab9e 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -337,7 +337,7 @@ extern uintptr_t tci_tb_ptr;
                                     *(int32_t *)((void *)GETRA() + 3) - 1))
 # elif defined (_ARCH_PPC) && !defined (_ARCH_PPC64)
 #  define GETRA() ((uintptr_t)__builtin_return_address(0))
-#  define GETPC_LDST() ((uintptr_t) ((*(int32_t *)(GETRA() + 4)) - 1))
+#  define GETPC_LDST() ((uintptr_t) ((*(int32_t *)(GETRA() - 4)) - 1))
 # else
 #  error "CONFIG_QEMU_LDST_OPTIMIZATION needs GETPC_LDST() implementation!"
 # endif
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index a1c74cea63..34a0693c58 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -569,6 +569,9 @@ static const void * const qemu_st_helpers[4] = {
     helper_stq_mmu,
 };
 
+static void *ld_trampolines[4];
+static void *st_trampolines[4];
+
 static void tcg_out_tlb_check (TCGContext *s, int r0, int r1, int r2,
                                int addr_reg, int addr_reg2, int s_bits,
                                int offset1, int offset2, uint8_t **label_ptr)
@@ -848,8 +851,7 @@ static void tcg_out_qemu_ld_slow_path (TCGContext *s, TCGLabelQemuLdst *label)
     reloc_pc14 (label_ptr[0], (tcg_target_long) s->code_ptr);
 
     /* slow path */
-    ir = 3;
-    tcg_out_mov (s, TCG_TYPE_I32, ir++, TCG_AREG0);
+    ir = 4;
 #if TARGET_LONG_BITS == 32
     tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg);
 #else
@@ -860,8 +862,7 @@ static void tcg_out_qemu_ld_slow_path (TCGContext *s, TCGLabelQemuLdst *label)
     tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg);
 #endif
     tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
-    tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
-    tcg_out32 (s, B | 8);
+    tcg_out_call (s, (tcg_target_long) ld_trampolines[s_bits], 1);
     tcg_out32 (s, (tcg_target_long) raddr);
     switch (opc) {
     case 0|4:
@@ -916,8 +917,7 @@ static void tcg_out_qemu_st_slow_path (TCGContext *s, TCGLabelQemuLdst *label)
     reloc_pc14 (label_ptr[0], (tcg_target_long) s->code_ptr);
 
     /* slow path */
-    ir = 3;
-    tcg_out_mov (s, TCG_TYPE_I32, ir++, TCG_AREG0);
+    ir = 4;
 #if TARGET_LONG_BITS == 32
     tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg);
 #else
@@ -959,8 +959,7 @@ static void tcg_out_qemu_st_slow_path (TCGContext *s, TCGLabelQemuLdst *label)
     ir++;
 
     tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
-    tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1);
-    tcg_out32 (s, B | 8);
+    tcg_out_call (s, (tcg_target_long) st_trampolines[opc], 1);
     tcg_out32 (s, (tcg_target_long) raddr);
     tcg_out_b (s, 0, (tcg_target_long) raddr);
 }
@@ -983,6 +982,15 @@ void tcg_out_tb_finalize(TCGContext *s)
 }
 #endif
 
+static void emit_ldst_trampoline (TCGContext *s, const void *ptr)
+{
+    tcg_out32 (s, MFSPR | RT (3) | LR);
+    tcg_out32 (s, ADDI | RT (3) | RA (3) | 4);
+    tcg_out32 (s, MTSPR | RS (3) | LR);
+    tcg_out_mov (s, TCG_TYPE_I32, 3, TCG_AREG0);
+    tcg_out_b (s, 0, (tcg_target_long) ptr);
+}
+
 static void tcg_target_qemu_prologue (TCGContext *s)
 {
     int i, frame_size;
@@ -1043,6 +1051,14 @@ static void tcg_target_qemu_prologue (TCGContext *s)
     tcg_out32 (s, MTSPR | RS (0) | LR);
     tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
     tcg_out32 (s, BCLR | BO_ALWAYS);
+
+    for (i = 0; i < 4; ++i) {
+        ld_trampolines[i] = s->code_ptr;
+        emit_ldst_trampoline (s, qemu_ld_helpers[i]);
+
+        st_trampolines[i] = s->code_ptr;
+        emit_ldst_trampoline (s, qemu_st_helpers[i]);
+    }
 }
 
 static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,

From 2592c59a66d456fe98fe96cb5787b356c40ee66f Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Sat, 3 Nov 2012 18:10:17 +0100
Subject: [PATCH 1545/2270] tools: initialize main loop before block layer

Tools were broken because they initialized the block layer while
qemu_aio_context was still NULL.

Reported-by: malc 
Signed-off-by: Paolo Bonzini 
Signed-off-by: malc 
---
 qemu-img.c | 3 +--
 qemu-io.c  | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/qemu-img.c b/qemu-img.c
index b17bddd25c..e29e01b729 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -2001,14 +2001,13 @@ int main(int argc, char **argv)
 
     error_set_progname(argv[0]);
 
+    qemu_init_main_loop();
     bdrv_init();
     if (argc < 2)
         help();
     cmdname = argv[1];
     argc--; argv++;
 
-    qemu_init_main_loop();
-
     /* find the command */
     for(cmd = img_cmds; cmd->name != NULL; cmd++) {
         if (!strcmp(cmdname, cmd->name)) {
diff --git a/qemu-io.c b/qemu-io.c
index d0f4fb70c7..1ad7d3adb9 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1892,9 +1892,8 @@ int main(int argc, char **argv)
         exit(1);
     }
 
-    bdrv_init();
-
     qemu_init_main_loop();
+    bdrv_init();
 
     /* initialize commands */
     quit_init();

From b8c6a5d9d0ab426c1626cd6c228b09b9529dba31 Mon Sep 17 00:00:00 2001
From: Peter Crosthwaite 
Date: Thu, 8 Nov 2012 14:01:19 +1000
Subject: [PATCH 1546/2270] microblaze: translate.c: Fix swaph decoding

The swaph instruction was not decoding correctly. s/1e1/1e2 on the
9 LSBs on the instruction decode.

Reported-by: David Holsgrove 
Signed-off-by: Peter Crosthwaite 
Signed-off-by: Edgar E. Iglesias 
---
 target-microblaze/translate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 7d864b1dac..6f27c24b76 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -840,7 +840,7 @@ static void dec_bit(DisasContext *dc)
             LOG_DIS("swapb r%d r%d\n", dc->rd, dc->ra);
             tcg_gen_bswap32_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
             break;
-        case 0x1e1:
+        case 0x1e2:
             /*swaph */
             LOG_DIS("swaph r%d r%d\n", dc->rd, dc->ra);
             tcg_gen_rotri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 16);

From 9a77a0f58923443913e1071ffb47b74c54566e70 Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Thu, 1 Nov 2012 17:15:01 +0100
Subject: [PATCH 1547/2270] usb: split packet result into actual_length +
 status

Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.

An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.

While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.

This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.

This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.

Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb.h                      |  24 ++--
 hw/usb/bus.c                  |  13 +--
 hw/usb/combined-packet.c      |  29 +++--
 hw/usb/core.c                 | 209 ++++++++++++++++++----------------
 hw/usb/desc.c                 |  16 ++-
 hw/usb/desc.h                 |   3 +-
 hw/usb/dev-audio.c            |  49 +++-----
 hw/usb/dev-bluetooth.c        |  33 +++---
 hw/usb/dev-hid.c              |  42 ++++---
 hw/usb/dev-hub.c              |  34 +++---
 hw/usb/dev-network.c          | 101 ++++++++--------
 hw/usb/dev-serial.c           |  29 ++---
 hw/usb/dev-smartcard-reader.c |  69 +++++------
 hw/usb/dev-storage.c          |  51 ++++-----
 hw/usb/dev-uas.c              |  36 +++---
 hw/usb/dev-wacom.c            |  38 +++----
 hw/usb/hcd-ehci.c             |  26 +++--
 hw/usb/hcd-musb.c             |  16 +--
 hw/usb/hcd-ohci.c             |  26 +++--
 hw/usb/hcd-uhci.c             |  34 +++---
 hw/usb/hcd-xhci.c             |  46 ++++----
 hw/usb/host-bsd.c             |  27 ++---
 hw/usb/host-linux.c           | 128 +++++++++++----------
 hw/usb/redirect.c             | 157 ++++++++++++++-----------
 24 files changed, 610 insertions(+), 626 deletions(-)

diff --git a/hw/usb.h b/hw/usb.h
index aef07f4a07..7d6de69ec4 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -38,6 +38,7 @@
 #define USB_TOKEN_IN    0x69 /* device -> host */
 #define USB_TOKEN_OUT   0xe1 /* host -> device */
 
+#define USB_RET_SUCCESS           (0)
 #define USB_RET_NODEV             (-1)
 #define USB_RET_NAK               (-2)
 #define USB_RET_STALL             (-3)
@@ -280,18 +281,20 @@ typedef struct USBDeviceClass {
      * Process control request.
      * Called from handle_packet().
      *
-     * Returns length or one of the USB_RET_ codes.
+     * Status gets stored in p->status, and if p->status == USB_RET_SUCCESS
+     * then the number of bytes transfered is stored in p->actual_length
      */
-    int (*handle_control)(USBDevice *dev, USBPacket *p, int request, int value,
-                          int index, int length, uint8_t *data);
+    void (*handle_control)(USBDevice *dev, USBPacket *p, int request, int value,
+                           int index, int length, uint8_t *data);
 
     /*
      * Process data transfers (both BULK and ISOC).
      * Called from handle_packet().
      *
-     * Returns length or one of the USB_RET_ codes.
+     * Status gets stored in p->status, and if p->status == USB_RET_SUCCESS
+     * then the number of bytes transfered is stored in p->actual_length
      */
-    int (*handle_data)(USBDevice *dev, USBPacket *p);
+    void (*handle_data)(USBDevice *dev, USBPacket *p);
 
     void (*set_interface)(USBDevice *dev, int interface,
                           int alt_old, int alt_new);
@@ -354,7 +357,8 @@ struct USBPacket {
     uint64_t parameter; /* control transfers */
     bool short_not_ok;
     bool int_req;
-    int result; /* transfer length or USB_RET_* status code */
+    int status; /* USB_RET_* status code */
+    int actual_length; /* Number of bytes actually transfered */
     /* Internal use by the USB layer.  */
     USBPacketState state;
     USBCombinedPacket *combined;
@@ -388,7 +392,7 @@ static inline bool usb_packet_is_inflight(USBPacket *p)
 
 USBDevice *usb_find_device(USBPort *port, uint8_t addr);
 
-int usb_handle_packet(USBDevice *dev, USBPacket *p);
+void usb_handle_packet(USBDevice *dev, USBPacket *p);
 void usb_packet_complete(USBDevice *dev, USBPacket *p);
 void usb_packet_complete_one(USBDevice *dev, USBPacket *p);
 void usb_cancel_packet(USBPacket * p);
@@ -523,10 +527,10 @@ void usb_device_handle_attach(USBDevice *dev);
 
 void usb_device_handle_reset(USBDevice *dev);
 
-int usb_device_handle_control(USBDevice *dev, USBPacket *p, int request, int value,
-                              int index, int length, uint8_t *data);
+void usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
+                               int val, int index, int length, uint8_t *data);
 
-int usb_device_handle_data(USBDevice *dev, USBPacket *p);
+void usb_device_handle_data(USBDevice *dev, USBPacket *p);
 
 void usb_device_set_interface(USBDevice *dev, int interface,
                               int alt_old, int alt_new);
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index 8066291b34..99aac7a2c0 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -140,24 +140,21 @@ void usb_device_handle_reset(USBDevice *dev)
     }
 }
 
-int usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
-                              int value, int index, int length, uint8_t *data)
+void usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
+                               int value, int index, int length, uint8_t *data)
 {
     USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
     if (klass->handle_control) {
-        return klass->handle_control(dev, p, request, value, index, length,
-                                         data);
+        klass->handle_control(dev, p, request, value, index, length, data);
     }
-    return -ENOSYS;
 }
 
-int usb_device_handle_data(USBDevice *dev, USBPacket *p)
+void usb_device_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
     if (klass->handle_data) {
-        return klass->handle_data(dev, p);
+        klass->handle_data(dev, p);
     }
-    return -ENOSYS;
 }
 
 const char *usb_device_get_product_desc(USBDevice *dev)
diff --git a/hw/usb/combined-packet.c b/hw/usb/combined-packet.c
index 3904e71634..e72219894b 100644
--- a/hw/usb/combined-packet.c
+++ b/hw/usb/combined-packet.c
@@ -46,7 +46,7 @@ void usb_combined_input_packet_complete(USBDevice *dev, USBPacket *p)
     USBEndpoint *ep = p->ep;
     USBPacket *next;
     enum { completing, complete, leftover };
-    int result, state = completing;
+    int status, actual_length, state = completing;
     bool short_not_ok;
 
     if (combined == NULL) {
@@ -56,27 +56,34 @@ void usb_combined_input_packet_complete(USBDevice *dev, USBPacket *p)
 
     assert(combined->first == p && p == QTAILQ_FIRST(&combined->packets));
 
-    result = combined->first->result;
+    status = combined->first->status;
+    actual_length = combined->first->actual_length;
     short_not_ok = QTAILQ_LAST(&combined->packets, packets_head)->short_not_ok;
 
     QTAILQ_FOREACH_SAFE(p, &combined->packets, combined_entry, next) {
         if (state == completing) {
             /* Distribute data over uncombined packets */
-            if (result >= p->iov.size) {
-                p->result = p->iov.size;
+            if (actual_length >= p->iov.size) {
+                p->actual_length = p->iov.size;
             } else {
                 /* Send short or error packet to complete the transfer */
-                p->result = result;
+                p->actual_length = actual_length;
                 state = complete;
             }
+            /* Report status on the last packet */
+            if (state == complete || next == NULL) {
+                p->status = status;
+            } else {
+                p->status = USB_RET_SUCCESS;
+            }
             p->short_not_ok = short_not_ok;
             usb_combined_packet_remove(combined, p);
             usb_packet_complete_one(dev, p);
-            result -= p->result;
+            actual_length -= p->actual_length;
         } else {
             /* Remove any leftover packets from the queue */
             state = leftover;
-            p->result = USB_RET_REMOVE_FROM_QUEUE;
+            p->status = USB_RET_REMOVE_FROM_QUEUE;
             dev->port->ops->complete(dev->port, p);
         }
     }
@@ -117,7 +124,7 @@ void usb_ep_combine_input_packets(USBEndpoint *ep)
 {
     USBPacket *p, *u, *next, *prev = NULL, *first = NULL;
     USBPort *port = ep->dev->port;
-    int ret, totalsize;
+    int totalsize;
 
     assert(ep->pipeline);
     assert(ep->pid == USB_TOKEN_IN);
@@ -125,7 +132,7 @@ void usb_ep_combine_input_packets(USBEndpoint *ep)
     QTAILQ_FOREACH_SAFE(p, &ep->queue, queue, next) {
         /* Empty the queue on a halt */
         if (ep->halted) {
-            p->result = USB_RET_REMOVE_FROM_QUEUE;
+            p->status = USB_RET_REMOVE_FROM_QUEUE;
             port->ops->complete(port, p);
             continue;
         }
@@ -166,8 +173,8 @@ void usb_ep_combine_input_packets(USBEndpoint *ep)
                 next == NULL ||
                 /* Work around for Linux usbfs bulk splitting + migration */
                 (totalsize == 16348 && p->int_req)) {
-            ret = usb_device_handle_data(ep->dev, first);
-            assert(ret == USB_RET_ASYNC);
+            usb_device_handle_data(ep->dev, first);
+            assert(first->status == USB_RET_ASYNC);
             if (first->combined) {
                 QTAILQ_FOREACH(u, &first->combined->packets, combined_entry) {
                     usb_packet_set_state(u, USB_PACKET_ASYNC);
diff --git a/hw/usb/core.c b/hw/usb/core.c
index ab37f6f7b8..52b53108cd 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -97,17 +97,17 @@ void usb_wakeup(USBEndpoint *ep)
 #define SETUP_STATE_ACK   3
 #define SETUP_STATE_PARAM 4
 
-static int do_token_setup(USBDevice *s, USBPacket *p)
+static void do_token_setup(USBDevice *s, USBPacket *p)
 {
     int request, value, index;
-    int ret = 0;
 
     if (p->iov.size != 8) {
-        return USB_RET_STALL;
+        p->status = USB_RET_STALL;
+        return;
     }
 
     usb_packet_copy(p, s->setup_buf, p->iov.size);
-    p->result = 0;
+    p->actual_length = 0;
     s->setup_len   = (s->setup_buf[7] << 8) | s->setup_buf[6];
     s->setup_index = 0;
 
@@ -116,24 +116,26 @@ static int do_token_setup(USBDevice *s, USBPacket *p)
     index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
 
     if (s->setup_buf[0] & USB_DIR_IN) {
-        ret = usb_device_handle_control(s, p, request, value, index,
-                                        s->setup_len, s->data_buf);
-        if (ret == USB_RET_ASYNC) {
-             s->setup_state = SETUP_STATE_SETUP;
-             return USB_RET_ASYNC;
+        usb_device_handle_control(s, p, request, value, index,
+                                  s->setup_len, s->data_buf);
+        if (p->status == USB_RET_ASYNC) {
+            s->setup_state = SETUP_STATE_SETUP;
+        }
+        if (p->status != USB_RET_SUCCESS) {
+            return;
         }
-        if (ret < 0)
-            return ret;
 
-        if (ret < s->setup_len)
-            s->setup_len = ret;
+        if (p->actual_length < s->setup_len) {
+            s->setup_len = p->actual_length;
+        }
         s->setup_state = SETUP_STATE_DATA;
     } else {
         if (s->setup_len > sizeof(s->data_buf)) {
             fprintf(stderr,
                 "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
                 s->setup_len, sizeof(s->data_buf));
-            return USB_RET_STALL;
+            p->status = USB_RET_STALL;
+            return;
         }
         if (s->setup_len == 0)
             s->setup_state = SETUP_STATE_ACK;
@@ -141,13 +143,12 @@ static int do_token_setup(USBDevice *s, USBPacket *p)
             s->setup_state = SETUP_STATE_DATA;
     }
 
-    return ret;
+    p->actual_length = 8;
 }
 
-static int do_token_in(USBDevice *s, USBPacket *p)
+static void do_token_in(USBDevice *s, USBPacket *p)
 {
     int request, value, index;
-    int ret = 0;
 
     assert(p->ep->nr == 0);
 
@@ -158,19 +159,15 @@ static int do_token_in(USBDevice *s, USBPacket *p)
     switch(s->setup_state) {
     case SETUP_STATE_ACK:
         if (!(s->setup_buf[0] & USB_DIR_IN)) {
-            ret = usb_device_handle_control(s, p, request, value, index,
-                                            s->setup_len, s->data_buf);
-            if (ret == USB_RET_ASYNC) {
-                return USB_RET_ASYNC;
+            usb_device_handle_control(s, p, request, value, index,
+                                      s->setup_len, s->data_buf);
+            if (p->status == USB_RET_ASYNC) {
+                return;
             }
             s->setup_state = SETUP_STATE_IDLE;
-            if (ret > 0)
-                return 0;
-            return ret;
+            p->actual_length = 0;
         }
-
-        /* return 0 byte */
-        return 0;
+        break;
 
     case SETUP_STATE_DATA:
         if (s->setup_buf[0] & USB_DIR_IN) {
@@ -180,20 +177,21 @@ static int do_token_in(USBDevice *s, USBPacket *p)
             }
             usb_packet_copy(p, s->data_buf + s->setup_index, len);
             s->setup_index += len;
-            if (s->setup_index >= s->setup_len)
+            if (s->setup_index >= s->setup_len) {
                 s->setup_state = SETUP_STATE_ACK;
-            return len;
+            }
+            return;
         }
-
         s->setup_state = SETUP_STATE_IDLE;
-        return USB_RET_STALL;
+        p->status = USB_RET_STALL;
+        break;
 
     default:
-        return USB_RET_STALL;
+        p->status = USB_RET_STALL;
     }
 }
 
-static int do_token_out(USBDevice *s, USBPacket *p)
+static void do_token_out(USBDevice *s, USBPacket *p)
 {
     assert(p->ep->nr == 0);
 
@@ -205,7 +203,7 @@ static int do_token_out(USBDevice *s, USBPacket *p)
         } else {
             /* ignore additional output */
         }
-        return 0;
+        break;
 
     case SETUP_STATE_DATA:
         if (!(s->setup_buf[0] & USB_DIR_IN)) {
@@ -215,23 +213,23 @@ static int do_token_out(USBDevice *s, USBPacket *p)
             }
             usb_packet_copy(p, s->data_buf + s->setup_index, len);
             s->setup_index += len;
-            if (s->setup_index >= s->setup_len)
+            if (s->setup_index >= s->setup_len) {
                 s->setup_state = SETUP_STATE_ACK;
-            return len;
+            }
+            return;
         }
-
         s->setup_state = SETUP_STATE_IDLE;
-        return USB_RET_STALL;
+        p->status = USB_RET_STALL;
+        break;
 
     default:
-        return USB_RET_STALL;
+        p->status = USB_RET_STALL;
     }
 }
 
-static int do_parameter(USBDevice *s, USBPacket *p)
+static void do_parameter(USBDevice *s, USBPacket *p)
 {
-    int request, value, index;
-    int i, ret = 0;
+    int i, request, value, index;
 
     for (i = 0; i < 8; i++) {
         s->setup_buf[i] = p->parameter >> (i*8);
@@ -249,27 +247,27 @@ static int do_parameter(USBDevice *s, USBPacket *p)
         fprintf(stderr,
                 "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
                 s->setup_len, sizeof(s->data_buf));
-        return USB_RET_STALL;
+        p->status = USB_RET_STALL;
+        return;
     }
 
     if (p->pid == USB_TOKEN_OUT) {
         usb_packet_copy(p, s->data_buf, s->setup_len);
     }
 
-    ret = usb_device_handle_control(s, p, request, value, index,
-                                    s->setup_len, s->data_buf);
-    if (ret < 0) {
-        return ret;
+    usb_device_handle_control(s, p, request, value, index,
+                              s->setup_len, s->data_buf);
+    if (p->status == USB_RET_ASYNC) {
+        return;
     }
 
-    if (ret < s->setup_len) {
-        s->setup_len = ret;
+    if (p->actual_length < s->setup_len) {
+        s->setup_len = p->actual_length;
     }
     if (p->pid == USB_TOKEN_IN) {
+        p->actual_length = 0;
         usb_packet_copy(p, s->data_buf, s->setup_len);
     }
-
-    return ret;
 }
 
 /* ctrl complete function for devices which use usb_generic_handle_packet and
@@ -278,30 +276,30 @@ static int do_parameter(USBDevice *s, USBPacket *p)
    usb_packet_complete to complete their async control packets. */
 void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p)
 {
-    if (p->result < 0) {
+    if (p->status < 0) {
         s->setup_state = SETUP_STATE_IDLE;
     }
 
     switch (s->setup_state) {
     case SETUP_STATE_SETUP:
-        if (p->result < s->setup_len) {
-            s->setup_len = p->result;
+        if (p->actual_length < s->setup_len) {
+            s->setup_len = p->actual_length;
         }
         s->setup_state = SETUP_STATE_DATA;
-        p->result = 8;
+        p->actual_length = 8;
         break;
 
     case SETUP_STATE_ACK:
         s->setup_state = SETUP_STATE_IDLE;
-        p->result = 0;
+        p->actual_length = 0;
         break;
 
     case SETUP_STATE_PARAM:
-        if (p->result < s->setup_len) {
-            s->setup_len = p->result;
+        if (p->actual_length < s->setup_len) {
+            s->setup_len = p->actual_length;
         }
         if (p->pid == USB_TOKEN_IN) {
-            p->result = 0;
+            p->actual_length = 0;
             usb_packet_copy(p, s->data_buf, s->setup_len);
         }
         break;
@@ -342,40 +340,57 @@ USBDevice *usb_find_device(USBPort *port, uint8_t addr)
     return usb_device_find_device(dev, addr);
 }
 
-static int usb_process_one(USBPacket *p)
+static void usb_process_one(USBPacket *p)
 {
     USBDevice *dev = p->ep->dev;
 
+    /*
+     * Handlers expect status to be initialized to USB_RET_SUCCESS, but it
+     * can be USB_RET_NAK here from a previous usb_process_one() call,
+     * or USB_RET_ASYNC from going through usb_queue_one().
+     */
+    p->status = USB_RET_SUCCESS;
+
     if (p->ep->nr == 0) {
         /* control pipe */
         if (p->parameter) {
-            return do_parameter(dev, p);
+            do_parameter(dev, p);
+            return;
         }
         switch (p->pid) {
         case USB_TOKEN_SETUP:
-            return do_token_setup(dev, p);
+            do_token_setup(dev, p);
+            break;
         case USB_TOKEN_IN:
-            return do_token_in(dev, p);
+            do_token_in(dev, p);
+            break;
         case USB_TOKEN_OUT:
-            return do_token_out(dev, p);
+            do_token_out(dev, p);
+            break;
         default:
-            return USB_RET_STALL;
+            p->status = USB_RET_STALL;
         }
     } else {
         /* data pipe */
-        return usb_device_handle_data(dev, p);
+        usb_device_handle_data(dev, p);
     }
 }
 
-/* Hand over a packet to a device for processing.  Return value
+static void usb_queue_one(USBPacket *p)
+{
+    usb_packet_set_state(p, USB_PACKET_QUEUED);
+    QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
+    p->status = USB_RET_ASYNC;
+}
+
+/* Hand over a packet to a device for processing.  p->status ==
    USB_RET_ASYNC indicates the processing isn't finished yet, the
    driver will call usb_packet_complete() when done processing it. */
-int usb_handle_packet(USBDevice *dev, USBPacket *p)
+void usb_handle_packet(USBDevice *dev, USBPacket *p)
 {
-    int ret;
-
     if (dev == NULL) {
-        return USB_RET_NODEV;
+        p->status = USB_RET_NODEV;
+        return;
     }
     assert(dev == p->ep->dev);
     assert(dev->state == USB_STATE_DEFAULT);
@@ -389,32 +404,26 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
     }
 
     if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) {
-        ret = usb_process_one(p);
-        if (ret == USB_RET_ASYNC) {
+        usb_process_one(p);
+        if (p->status == USB_RET_ASYNC) {
             assert(p->ep->type != USB_ENDPOINT_XFER_ISOC);
             usb_packet_set_state(p, USB_PACKET_ASYNC);
             QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
-        } else if (ret == USB_RET_ADD_TO_QUEUE) {
-            usb_packet_set_state(p, USB_PACKET_QUEUED);
-            QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
-            ret = USB_RET_ASYNC;
+        } else if (p->status == USB_RET_ADD_TO_QUEUE) {
+            usb_queue_one(p);
         } else {
             /*
              * When pipelining is enabled usb-devices must always return async,
              * otherwise packets can complete out of order!
              */
             assert(!p->ep->pipeline || QTAILQ_EMPTY(&p->ep->queue));
-            if (ret != USB_RET_NAK) {
-                p->result = ret;
+            if (p->status != USB_RET_NAK) {
                 usb_packet_set_state(p, USB_PACKET_COMPLETE);
             }
         }
     } else {
-        ret = USB_RET_ASYNC;
-        usb_packet_set_state(p, USB_PACKET_QUEUED);
-        QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
+        usb_queue_one(p);
     }
-    return ret;
 }
 
 void usb_packet_complete_one(USBDevice *dev, USBPacket *p)
@@ -422,9 +431,10 @@ void usb_packet_complete_one(USBDevice *dev, USBPacket *p)
     USBEndpoint *ep = p->ep;
 
     assert(QTAILQ_FIRST(&ep->queue) == p);
-    assert(p->result != USB_RET_ASYNC && p->result != USB_RET_NAK);
+    assert(p->status != USB_RET_ASYNC && p->status != USB_RET_NAK);
 
-    if (p->result < 0 || (p->short_not_ok && (p->result < p->iov.size))) {
+    if (p->status != USB_RET_SUCCESS ||
+            (p->short_not_ok && (p->actual_length < p->iov.size))) {
         ep->halted = true;
     }
     usb_packet_set_state(p, USB_PACKET_COMPLETE);
@@ -438,7 +448,6 @@ void usb_packet_complete_one(USBDevice *dev, USBPacket *p)
 void usb_packet_complete(USBDevice *dev, USBPacket *p)
 {
     USBEndpoint *ep = p->ep;
-    int ret;
 
     usb_packet_check_state(p, USB_PACKET_ASYNC);
     usb_packet_complete_one(dev, p);
@@ -447,7 +456,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
         p = QTAILQ_FIRST(&ep->queue);
         if (ep->halted) {
             /* Empty the queue on a halt */
-            p->result = USB_RET_REMOVE_FROM_QUEUE;
+            p->status = USB_RET_REMOVE_FROM_QUEUE;
             dev->port->ops->complete(dev->port, p);
             continue;
         }
@@ -455,12 +464,11 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
             break;
         }
         usb_packet_check_state(p, USB_PACKET_QUEUED);
-        ret = usb_process_one(p);
-        if (ret == USB_RET_ASYNC) {
+        usb_process_one(p);
+        if (p->status == USB_RET_ASYNC) {
             usb_packet_set_state(p, USB_PACKET_ASYNC);
             break;
         }
-        p->result = ret;
         usb_packet_complete_one(ep->dev, p);
     }
 }
@@ -541,7 +549,8 @@ void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id,
     p->id = id;
     p->pid = pid;
     p->ep = ep;
-    p->result = 0;
+    p->status = USB_RET_SUCCESS;
+    p->actual_length = 0;
     p->parameter = 0;
     p->short_not_ok = short_not_ok;
     p->int_req = int_req;
@@ -557,31 +566,31 @@ void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len)
 
 void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes)
 {
-    assert(p->result >= 0);
-    assert(p->result + bytes <= p->iov.size);
+    assert(p->actual_length >= 0);
+    assert(p->actual_length + bytes <= p->iov.size);
     switch (p->pid) {
     case USB_TOKEN_SETUP:
     case USB_TOKEN_OUT:
-        iov_to_buf(p->iov.iov, p->iov.niov, p->result, ptr, bytes);
+        iov_to_buf(p->iov.iov, p->iov.niov, p->actual_length, ptr, bytes);
         break;
     case USB_TOKEN_IN:
-        iov_from_buf(p->iov.iov, p->iov.niov, p->result, ptr, bytes);
+        iov_from_buf(p->iov.iov, p->iov.niov, p->actual_length, ptr, bytes);
         break;
     default:
         fprintf(stderr, "%s: invalid pid: %x\n", __func__, p->pid);
         abort();
     }
-    p->result += bytes;
+    p->actual_length += bytes;
 }
 
 void usb_packet_skip(USBPacket *p, size_t bytes)
 {
-    assert(p->result >= 0);
-    assert(p->result + bytes <= p->iov.size);
+    assert(p->actual_length >= 0);
+    assert(p->actual_length + bytes <= p->iov.size);
     if (p->pid == USB_TOKEN_IN) {
-        iov_memset(p->iov.iov, p->iov.niov, p->result, 0, bytes);
+        iov_memset(p->iov.iov, p->iov.niov, p->actual_length, 0, bytes);
     }
-    p->result += bytes;
+    p->actual_length += bytes;
 }
 
 void usb_packet_cleanup(USBPacket *p)
diff --git a/hw/usb/desc.c b/hw/usb/desc.c
index 1f12eaecbf..b7c32333d7 100644
--- a/hw/usb/desc.c
+++ b/hw/usb/desc.c
@@ -626,7 +626,8 @@ int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len)
     return pos;
 }
 
-int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len)
+int usb_desc_get_descriptor(USBDevice *dev, USBPacket *p,
+                            int value, uint8_t *dest, size_t len)
 {
     const USBDesc *desc = usb_device_get_usb_desc(dev);
     const USBDescDevice *other_dev;
@@ -696,6 +697,8 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
             ret = len;
         }
         memcpy(dest, buf, ret);
+        p->actual_length = ret;
+        ret = 0;
     }
     return ret;
 }
@@ -715,7 +718,7 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
         break;
 
     case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
-        ret = usb_desc_get_descriptor(dev, value, data, length);
+        ret = usb_desc_get_descriptor(dev, p, value, data, length);
         break;
 
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
@@ -724,7 +727,8 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
          * the non zero value of bConfigurationValue.
          */
         data[0] = dev->config ? dev->config->bConfigurationValue : 0;
-        ret = 1;
+        p->actual_length = 1;
+        ret = 0;
         break;
     case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
         ret = usb_desc_set_config(dev, value);
@@ -749,7 +753,8 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
             data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP;
         }
         data[1] = 0x00;
-        ret = 2;
+        p->actual_length = 2;
+        ret = 0;
         break;
     }
     case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
@@ -772,7 +777,8 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
             break;
         }
         data[0] = dev->altsetting[index];
-        ret = 1;
+        p->actual_length = 1;
+        ret = 0;
         break;
     case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
         ret = usb_desc_set_interface(dev, index, value);
diff --git a/hw/usb/desc.h b/hw/usb/desc.h
index 68bb570679..ddd3e7485c 100644
--- a/hw/usb/desc.h
+++ b/hw/usb/desc.h
@@ -216,7 +216,8 @@ void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str);
 void usb_desc_create_serial(USBDevice *dev);
 const char *usb_desc_get_string(USBDevice *dev, uint8_t index);
 int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len);
-int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len);
+int usb_desc_get_descriptor(USBDevice *dev, USBPacket *p,
+        int value, uint8_t *dest, size_t len);
 int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
         int request, int value, int index, int length, uint8_t *data);
 
diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c
index 2594c78104..b669601c92 100644
--- a/hw/usb/dev-audio.c
+++ b/hw/usb/dev-audio.c
@@ -503,7 +503,7 @@ static int usb_audio_set_control(USBAudioState *s, uint8_t attrib,
     return ret;
 }
 
-static int usb_audio_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_audio_handle_control(USBDevice *dev, USBPacket *p,
                                     int request, int value, int index,
                                     int length, uint8_t *data)
 {
@@ -518,7 +518,7 @@ static int usb_audio_handle_control(USBDevice *dev, USBPacket *p,
 
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
     if (ret >= 0) {
-        return ret;
+        return;
     }
 
     switch (request) {
@@ -534,6 +534,7 @@ static int usb_audio_handle_control(USBDevice *dev, USBPacket *p,
             }
             goto fail;
         }
+        p->actual_length = ret;
         break;
 
     case ClassInterfaceOutRequest | CR_SET_CUR:
@@ -557,10 +558,9 @@ fail:
                     "request 0x%04x value 0x%04x index 0x%04x length 0x%04x\n",
                     request, value, index, length);
         }
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-    return ret;
 }
 
 static void usb_audio_set_interface(USBDevice *dev, int iface,
@@ -583,50 +583,35 @@ static void usb_audio_handle_reset(USBDevice *dev)
     usb_audio_set_output_altset(s, ALTSET_OFF);
 }
 
-static int usb_audio_handle_dataout(USBAudioState *s, USBPacket *p)
+static void usb_audio_handle_dataout(USBAudioState *s, USBPacket *p)
 {
-    int rc;
-
     if (s->out.altset == ALTSET_OFF) {
-        return USB_RET_STALL;
+        p->status = USB_RET_STALL;
+        return;
     }
 
-    rc = streambuf_put(&s->out.buf, p);
-    if (rc < p->iov.size && s->debug > 1) {
+    streambuf_put(&s->out.buf, p);
+    if (p->actual_length < p->iov.size && s->debug > 1) {
         fprintf(stderr, "usb-audio: output overrun (%zd bytes)\n",
-                p->iov.size - rc);
+                p->iov.size - p->actual_length);
     }
-
-    return 0;
 }
 
-static int usb_audio_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_audio_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBAudioState *s = (USBAudioState *) dev;
-    int ret = 0;
 
-    switch (p->pid) {
-    case USB_TOKEN_OUT:
-        switch (p->ep->nr) {
-        case 1:
-            ret = usb_audio_handle_dataout(s, p);
-            break;
-        default:
-            goto fail;
-        }
-        break;
-
-    default:
-fail:
-        ret = USB_RET_STALL;
-        break;
+    if (p->pid == USB_TOKEN_OUT && p->ep->nr == 1) {
+        usb_audio_handle_dataout(s, p);
+        return;
     }
-    if (ret == USB_RET_STALL && s->debug) {
+
+    p->status = USB_RET_STALL;
+    if (s->debug) {
         fprintf(stderr, "usb-audio: failed data transaction: "
                         "pid 0x%x ep 0x%x len 0x%zx\n",
                         p->pid, p->ep->nr, p->iov.size);
     }
-    return ret;
 }
 
 static void usb_audio_handle_destroy(USBDevice *dev)
diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c
index 55bc19184b..bfb96bf9f0 100644
--- a/hw/usb/dev-bluetooth.c
+++ b/hw/usb/dev-bluetooth.c
@@ -285,13 +285,15 @@ static void usb_bt_fifo_enqueue(struct usb_hci_in_fifo_s *fifo,
     fifo->fifo[off].len = len;
 }
 
-static inline int usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo,
+static inline void usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo,
                 USBPacket *p)
 {
     int len;
 
-    if (likely(!fifo->len))
-        return USB_RET_STALL;
+    if (likely(!fifo->len)) {
+        p->status = USB_RET_STALL;
+        return;
+    }
 
     len = MIN(p->iov.size, fifo->fifo[fifo->start].len);
     usb_packet_copy(p, fifo->fifo[fifo->start].data, len);
@@ -310,8 +312,6 @@ static inline int usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo,
         fifo->dstart = 0;
         fifo->dsize = DFIFO_LEN_MASK + 1;
     }
-
-    return len;
 }
 
 static inline void usb_bt_fifo_out_enqueue(struct USBBtState *s,
@@ -363,7 +363,7 @@ static void usb_bt_handle_reset(USBDevice *dev)
     s->outsco.len = 0;
 }
 
-static int usb_bt_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_bt_handle_control(USBDevice *dev, USBPacket *p,
                int request, int value, int index, int length, uint8_t *data)
 {
     struct USBBtState *s = (struct USBBtState *) dev->opaque;
@@ -382,16 +382,15 @@ static int usb_bt_handle_control(USBDevice *dev, USBPacket *p,
             usb_bt_fifo_reset(&s->sco);
             break;
         }
-        return ret;
+        return;
     }
 
-    ret = 0;
     switch (request) {
     case InterfaceRequest | USB_REQ_GET_STATUS:
     case EndpointRequest | USB_REQ_GET_STATUS:
         data[0] = 0x00;
         data[1] = 0x00;
-        ret = 2;
+        p->actual_length = 2;
         break;
     case InterfaceOutRequest | USB_REQ_CLEAR_FEATURE:
     case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
@@ -407,16 +406,14 @@ static int usb_bt_handle_control(USBDevice *dev, USBPacket *p,
         break;
     default:
     fail:
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-    return ret;
 }
 
-static int usb_bt_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_bt_handle_data(USBDevice *dev, USBPacket *p)
 {
     struct USBBtState *s = (struct USBBtState *) dev->opaque;
-    int ret = 0;
 
     if (!s->config)
         goto fail;
@@ -425,15 +422,15 @@ static int usb_bt_handle_data(USBDevice *dev, USBPacket *p)
     case USB_TOKEN_IN:
         switch (p->ep->nr) {
         case USB_EVT_EP:
-            ret = usb_bt_fifo_dequeue(&s->evt, p);
+            usb_bt_fifo_dequeue(&s->evt, p);
             break;
 
         case USB_ACL_EP:
-            ret = usb_bt_fifo_dequeue(&s->acl, p);
+            usb_bt_fifo_dequeue(&s->acl, p);
             break;
 
         case USB_SCO_EP:
-            ret = usb_bt_fifo_dequeue(&s->sco, p);
+            usb_bt_fifo_dequeue(&s->sco, p);
             break;
 
         default:
@@ -460,11 +457,9 @@ static int usb_bt_handle_data(USBDevice *dev, USBPacket *p)
 
     default:
     fail:
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-
-    return ret;
 }
 
 static void usb_bt_out_hci_packet_event(void *opaque,
diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
index b3dcd23109..55266b18ef 100644
--- a/hw/usb/dev-hid.c
+++ b/hw/usb/dev-hid.c
@@ -371,7 +371,7 @@ static void usb_hid_handle_reset(USBDevice *dev)
     hid_reset(&us->hid);
 }
 
-static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_hid_handle_control(USBDevice *dev, USBPacket *p,
                int request, int value, int index, int length, uint8_t *data)
 {
     USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
@@ -380,10 +380,9 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
 
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
     if (ret >= 0) {
-        return ret;
+        return;
     }
 
-    ret = 0;
     switch (request) {
         /* hid specific requests */
     case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
@@ -392,15 +391,15 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
             if (hs->kind == HID_MOUSE) {
 		memcpy(data, qemu_mouse_hid_report_descriptor,
 		       sizeof(qemu_mouse_hid_report_descriptor));
-		ret = sizeof(qemu_mouse_hid_report_descriptor);
+                p->actual_length = sizeof(qemu_mouse_hid_report_descriptor);
             } else if (hs->kind == HID_TABLET) {
                 memcpy(data, qemu_tablet_hid_report_descriptor,
 		       sizeof(qemu_tablet_hid_report_descriptor));
-		ret = sizeof(qemu_tablet_hid_report_descriptor);
+                p->actual_length = sizeof(qemu_tablet_hid_report_descriptor);
             } else if (hs->kind == HID_KEYBOARD) {
                 memcpy(data, qemu_keyboard_hid_report_descriptor,
                        sizeof(qemu_keyboard_hid_report_descriptor));
-                ret = sizeof(qemu_keyboard_hid_report_descriptor);
+                p->actual_length = sizeof(qemu_keyboard_hid_report_descriptor);
             }
             break;
         default:
@@ -409,14 +408,14 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
         break;
     case GET_REPORT:
         if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
-            ret = hid_pointer_poll(hs, data, length);
+            p->actual_length = hid_pointer_poll(hs, data, length);
         } else if (hs->kind == HID_KEYBOARD) {
-            ret = hid_keyboard_poll(hs, data, length);
+            p->actual_length = hid_keyboard_poll(hs, data, length);
         }
         break;
     case SET_REPORT:
         if (hs->kind == HID_KEYBOARD) {
-            ret = hid_keyboard_write(hs, data, length);
+            p->actual_length = hid_keyboard_write(hs, data, length);
         } else {
             goto fail;
         }
@@ -425,19 +424,18 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
         if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
             goto fail;
         }
-        ret = 1;
         data[0] = hs->protocol;
+        p->actual_length = 1;
         break;
     case SET_PROTOCOL:
         if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
             goto fail;
         }
-        ret = 0;
         hs->protocol = value;
         break;
     case GET_IDLE:
-        ret = 1;
         data[0] = hs->idle;
+        p->actual_length = 1;
         break;
     case SET_IDLE:
         hs->idle = (uint8_t) (value >> 8);
@@ -445,22 +443,20 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
         if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
             hid_pointer_activate(hs);
         }
-        ret = 0;
         break;
     default:
     fail:
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-    return ret;
 }
 
-static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_hid_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
     HIDState *hs = &us->hid;
     uint8_t buf[p->iov.size];
-    int ret = 0;
+    int len = 0;
 
     switch (p->pid) {
     case USB_TOKEN_IN:
@@ -471,15 +467,16 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
             }
             if (!hid_has_events(hs) &&
                 (!hs->idle || hs->next_idle_clock - curtime > 0)) {
-                return USB_RET_NAK;
+                p->status = USB_RET_NAK;
+                return;
             }
             hid_set_next_idle(hs, curtime);
             if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
-                ret = hid_pointer_poll(hs, buf, p->iov.size);
+                len = hid_pointer_poll(hs, buf, p->iov.size);
             } else if (hs->kind == HID_KEYBOARD) {
-                ret = hid_keyboard_poll(hs, buf, p->iov.size);
+                len = hid_keyboard_poll(hs, buf, p->iov.size);
             }
-            usb_packet_copy(p, buf, ret);
+            usb_packet_copy(p, buf, len);
         } else {
             goto fail;
         }
@@ -487,10 +484,9 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
     case USB_TOKEN_OUT:
     default:
     fail:
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-    return ret;
 }
 
 static void usb_hid_handle_destroy(USBDevice *dev)
diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
index 8fd30df0e6..9ee60dd412 100644
--- a/hw/usb/dev-hub.c
+++ b/hw/usb/dev-hub.c
@@ -288,7 +288,7 @@ static const char *feature_name(int feature)
     return name[feature] ?: "?";
 }
 
-static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_hub_handle_control(USBDevice *dev, USBPacket *p,
                int request, int value, int index, int length, uint8_t *data)
 {
     USBHubState *s = (USBHubState *)dev;
@@ -298,7 +298,7 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
 
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
     if (ret >= 0) {
-        return ret;
+        return;
     }
 
     switch(request) {
@@ -306,7 +306,6 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
         if (value == 0 && index != 0x81) { /* clear ep halt */
             goto fail;
         }
-        ret = 0;
         break;
         /* usb specific requests */
     case GetHubStatus:
@@ -314,7 +313,7 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
         data[1] = 0;
         data[2] = 0;
         data[3] = 0;
-        ret = 4;
+        p->actual_length = 4;
         break;
     case GetPortStatus:
         {
@@ -331,16 +330,14 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
             data[1] = port->wPortStatus >> 8;
             data[2] = port->wPortChange;
             data[3] = port->wPortChange >> 8;
-            ret = 4;
+            p->actual_length = 4;
         }
         break;
     case SetHubFeature:
     case ClearHubFeature:
-        if (value == 0 || value == 1) {
-        } else {
+        if (value != 0 && value != 1) {
             goto fail;
         }
-        ret = 0;
         break;
     case SetPortFeature:
         {
@@ -373,7 +370,6 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
             default:
                 goto fail;
             }
-            ret = 0;
         }
         break;
     case ClearPortFeature:
@@ -413,7 +409,6 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
             default:
                 goto fail;
             }
-            ret = 0;
         }
         break;
     case GetHubDescriptor:
@@ -437,22 +432,20 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
                 var_hub_size++;
             }
 
-            ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size;
-            data[0] = ret;
+            p->actual_length = sizeof(qemu_hub_hub_descriptor) + var_hub_size;
+            data[0] = p->actual_length;
             break;
         }
     default:
     fail:
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-    return ret;
 }
 
-static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_hub_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBHubState *s = (USBHubState *)dev;
-    int ret;
 
     switch(p->pid) {
     case USB_TOKEN_IN:
@@ -465,7 +458,8 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
             if (p->iov.size == 1) { /* FreeBSD workaround */
                 n = 1;
             } else if (n > p->iov.size) {
-                return USB_RET_BABBLE;
+                p->status = USB_RET_BABBLE;
+                return;
             }
             status = 0;
             for(i = 0; i < NUM_PORTS; i++) {
@@ -478,9 +472,8 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
                     buf[i] = status >> (8 * i);
                 }
                 usb_packet_copy(p, buf, n);
-                ret = n;
             } else {
-                ret = USB_RET_NAK; /* usb11 11.13.1 */
+                p->status = USB_RET_NAK; /* usb11 11.13.1 */
             }
         } else {
             goto fail;
@@ -489,10 +482,9 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
     case USB_TOKEN_OUT:
     default:
     fail:
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-    return ret;
 }
 
 static void usb_hub_handle_destroy(USBDevice *dev)
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index e4a43599b5..14d9e5aa5b 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -1048,7 +1048,7 @@ static void usb_net_handle_reset(USBDevice *dev)
 {
 }
 
-static int usb_net_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_net_handle_control(USBDevice *dev, USBPacket *p,
                int request, int value, int index, int length, uint8_t *data)
 {
     USBNetState *s = (USBNetState *) dev;
@@ -1056,10 +1056,9 @@ static int usb_net_handle_control(USBDevice *dev, USBPacket *p,
 
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
     if (ret >= 0) {
-        return ret;
+        return;
     }
 
-    ret = 0;
     switch(request) {
     case ClassInterfaceOutRequest | USB_CDC_SEND_ENCAPSULATED_COMMAND:
         if (!is_rndis(s) || value || index != 0) {
@@ -1078,22 +1077,25 @@ static int usb_net_handle_control(USBDevice *dev, USBPacket *p,
         }
 #endif
         ret = rndis_parse(s, data, length);
+        if (ret < 0) {
+            p->status = ret;
+        }
         break;
 
     case ClassInterfaceRequest | USB_CDC_GET_ENCAPSULATED_RESPONSE:
         if (!is_rndis(s) || value || index != 0) {
             goto fail;
         }
-        ret = rndis_get_response(s, data);
-        if (!ret) {
+        p->actual_length = rndis_get_response(s, data);
+        if (p->actual_length == 0) {
             data[0] = 0;
-            ret = 1;
+            p->actual_length = 1;
         }
 #ifdef TRAFFIC_DEBUG
         {
             unsigned int i;
             fprintf(stderr, "GET_ENCAPSULATED_RESPONSE:");
-            for (i = 0; i < ret; i++) {
+            for (i = 0; i < p->actual_length; i++) {
                 if (!(i & 15))
                     fprintf(stderr, "\n%04x:", i);
                 fprintf(stderr, " %02x", data[i]);
@@ -1108,72 +1110,67 @@ static int usb_net_handle_control(USBDevice *dev, USBPacket *p,
         fprintf(stderr, "usbnet: failed control transaction: "
                         "request 0x%x value 0x%x index 0x%x length 0x%x\n",
                         request, value, index, length);
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-    return ret;
 }
 
-static int usb_net_handle_statusin(USBNetState *s, USBPacket *p)
+static void usb_net_handle_statusin(USBNetState *s, USBPacket *p)
 {
     le32 buf[2];
-    int ret = 8;
 
     if (p->iov.size < 8) {
-        return USB_RET_STALL;
+        p->status = USB_RET_STALL;
+        return;
     }
 
     buf[0] = cpu_to_le32(1);
     buf[1] = cpu_to_le32(0);
     usb_packet_copy(p, buf, 8);
-    if (!s->rndis_resp.tqh_first)
-        ret = USB_RET_NAK;
+    if (!s->rndis_resp.tqh_first) {
+        p->status = USB_RET_NAK;
+    }
 
 #ifdef TRAFFIC_DEBUG
     fprintf(stderr, "usbnet: interrupt poll len %zu return %d",
-            p->iov.size, ret);
-    iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", ret);
+            p->iov.size, p->status);
+    iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", p->status);
 #endif
-
-    return ret;
 }
 
-static int usb_net_handle_datain(USBNetState *s, USBPacket *p)
+static void usb_net_handle_datain(USBNetState *s, USBPacket *p)
 {
-    int ret = USB_RET_NAK;
+    int len;
 
     if (s->in_ptr > s->in_len) {
         usb_net_reset_in_buf(s);
-        ret = USB_RET_NAK;
-        return ret;
+        p->status = USB_RET_NAK;
+        return;
     }
     if (!s->in_len) {
-        ret = USB_RET_NAK;
-        return ret;
+        p->status = USB_RET_NAK;
+        return;
     }
-    ret = s->in_len - s->in_ptr;
-    if (ret > p->iov.size) {
-        ret = p->iov.size;
+    len = s->in_len - s->in_ptr;
+    if (len > p->iov.size) {
+        len = p->iov.size;
     }
-    usb_packet_copy(p, &s->in_buf[s->in_ptr], ret);
-    s->in_ptr += ret;
+    usb_packet_copy(p, &s->in_buf[s->in_ptr], len);
+    s->in_ptr += len;
     if (s->in_ptr >= s->in_len &&
-                    (is_rndis(s) || (s->in_len & (64 - 1)) || !ret)) {
+                    (is_rndis(s) || (s->in_len & (64 - 1)) || !len)) {
         /* no short packet necessary */
         usb_net_reset_in_buf(s);
     }
 
 #ifdef TRAFFIC_DEBUG
-    fprintf(stderr, "usbnet: data in len %zu return %d", p->iov.size, ret);
-    iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", ret);
+    fprintf(stderr, "usbnet: data in len %zu return %d", p->iov.size, len);
+    iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", len);
 #endif
-
-    return ret;
 }
 
-static int usb_net_handle_dataout(USBNetState *s, USBPacket *p)
+static void usb_net_handle_dataout(USBNetState *s, USBPacket *p)
 {
-    int ret = p->iov.size;
     int sz = sizeof(s->out_buf) - s->out_ptr;
     struct rndis_packet_msg_type *msg =
             (struct rndis_packet_msg_type *) s->out_buf;
@@ -1184,21 +1181,23 @@ static int usb_net_handle_dataout(USBNetState *s, USBPacket *p)
     iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", p->iov.size);
 #endif
 
-    if (sz > ret)
-        sz = ret;
+    if (sz > p->iov.size) {
+        sz = p->iov.size;
+    }
     usb_packet_copy(p, &s->out_buf[s->out_ptr], sz);
     s->out_ptr += sz;
 
     if (!is_rndis(s)) {
-        if (ret < 64) {
+        if (p->iov.size < 64) {
             qemu_send_packet(&s->nic->nc, s->out_buf, s->out_ptr);
             s->out_ptr = 0;
         }
-        return ret;
+        return;
     }
     len = le32_to_cpu(msg->MessageLength);
-    if (s->out_ptr < 8 || s->out_ptr < len)
-        return ret;
+    if (s->out_ptr < 8 || s->out_ptr < len) {
+        return;
+    }
     if (le32_to_cpu(msg->MessageType) == RNDIS_PACKET_MSG) {
         uint32_t offs = 8 + le32_to_cpu(msg->DataOffset);
         uint32_t size = le32_to_cpu(msg->DataLength);
@@ -1207,24 +1206,21 @@ static int usb_net_handle_dataout(USBNetState *s, USBPacket *p)
     }
     s->out_ptr -= len;
     memmove(s->out_buf, &s->out_buf[len], s->out_ptr);
-
-    return ret;
 }
 
-static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_net_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBNetState *s = (USBNetState *) dev;
-    int ret = 0;
 
     switch(p->pid) {
     case USB_TOKEN_IN:
         switch (p->ep->nr) {
         case 1:
-            ret = usb_net_handle_statusin(s, p);
+            usb_net_handle_statusin(s, p);
             break;
 
         case 2:
-            ret = usb_net_handle_datain(s, p);
+            usb_net_handle_datain(s, p);
             break;
 
         default:
@@ -1235,7 +1231,7 @@ static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
     case USB_TOKEN_OUT:
         switch (p->ep->nr) {
         case 2:
-            ret = usb_net_handle_dataout(s, p);
+            usb_net_handle_dataout(s, p);
             break;
 
         default:
@@ -1245,14 +1241,15 @@ static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
 
     default:
     fail:
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-    if (ret == USB_RET_STALL)
+
+    if (p->status == USB_RET_STALL) {
         fprintf(stderr, "usbnet: failed data transaction: "
                         "pid 0x%x ep 0x%x len 0x%zx\n",
                         p->pid, p->ep->nr, p->iov.size);
-    return ret;
+    }
 }
 
 static ssize_t usbnet_receive(NetClientState *nc, const uint8_t *buf, size_t size)
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index a466f9929c..99b19df1d1 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -219,7 +219,7 @@ static uint8_t usb_get_modem_lines(USBSerialState *s)
     return ret;
 }
 
-static int usb_serial_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_serial_handle_control(USBDevice *dev, USBPacket *p,
                int request, int value, int index, int length, uint8_t *data)
 {
     USBSerialState *s = (USBSerialState *)dev;
@@ -228,13 +228,11 @@ static int usb_serial_handle_control(USBDevice *dev, USBPacket *p,
     DPRINTF("got control %x, value %x\n",request, value);
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
     if (ret >= 0) {
-        return ret;
+        return;
     }
 
-    ret = 0;
     switch (request) {
     case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
-        ret = 0;
         break;
 
         /* Class specific requests.  */
@@ -323,7 +321,7 @@ static int usb_serial_handle_control(USBDevice *dev, USBPacket *p,
     case DeviceInVendor | FTDI_GET_MDM_ST:
         data[0] = usb_get_modem_lines(s) | 1;
         data[1] = 0;
-        ret = 2;
+        p->actual_length = 2;
         break;
     case DeviceOutVendor | FTDI_SET_EVENT_CHR:
         /* TODO: handle it */
@@ -338,25 +336,23 @@ static int usb_serial_handle_control(USBDevice *dev, USBPacket *p,
         break;
     case DeviceInVendor | FTDI_GET_LATENCY:
         data[0] = s->latency;
-        ret = 1;
+        p->actual_length = 1;
         break;
     default:
     fail:
         DPRINTF("got unsupported/bogus control %x, value %x\n", request, value);
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-    return ret;
 }
 
-static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_serial_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBSerialState *s = (USBSerialState *)dev;
-    int i, ret = 0;
     uint8_t devep = p->ep->nr;
     struct iovec *iov;
     uint8_t header[2];
-    int first_len, len;
+    int i, first_len, len;
 
     switch (p->pid) {
     case USB_TOKEN_OUT:
@@ -366,6 +362,7 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
             iov = p->iov.iov + i;
             qemu_chr_fe_write(s->cs, iov->iov_base, iov->iov_len);
         }
+        p->actual_length = p->iov.size;
         break;
 
     case USB_TOKEN_IN:
@@ -374,7 +371,7 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
         first_len = RECV_BUF - s->recv_ptr;
         len = p->iov.size;
         if (len <= 2) {
-            ret = USB_RET_NAK;
+            p->status = USB_RET_NAK;
             break;
         }
         header[0] = usb_get_modem_lines(s) | 1;
@@ -384,7 +381,6 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
             s->event_trigger &= ~FTDI_BI;
             header[1] = FTDI_BI;
             usb_packet_copy(p, header, 2);
-            ret = 2;
             break;
         } else {
             header[1] = 0;
@@ -393,7 +389,7 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
         if (len > s->recv_used)
             len = s->recv_used;
         if (!len) {
-            ret = USB_RET_NAK;
+            p->status = USB_RET_NAK;
             break;
         }
         if (first_len > len)
@@ -404,17 +400,14 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
             usb_packet_copy(p, s->recv_buf, len - first_len);
         s->recv_used -= len;
         s->recv_ptr = (s->recv_ptr + len) % RECV_BUF;
-        ret = len + 2;
         break;
 
     default:
         DPRINTF("Bad token\n");
     fail:
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-
-    return ret;
 }
 
 static void usb_serial_handle_destroy(USBDevice *dev)
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 1ea079176a..190fcd62d4 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -635,39 +635,38 @@ static void ccid_handle_reset(USBDevice *dev)
     ccid_reset(s);
 }
 
-static int ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
+static void ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
                                int value, int index, int length, uint8_t *data)
 {
     USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
-    int ret = 0;
+    int ret;
 
     DPRINTF(s, 1, "got control %x, value %x\n", request, value);
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
     if (ret >= 0) {
-        return ret;
+        return;
     }
 
     switch (request) {
         /* Class specific requests.  */
     case InterfaceOutClass | CCID_CONTROL_ABORT:
         DPRINTF(s, 1, "ccid_control abort UNIMPLEMENTED\n");
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     case InterfaceInClass | CCID_CONTROL_GET_CLOCK_FREQUENCIES:
         DPRINTF(s, 1, "ccid_control get clock frequencies UNIMPLEMENTED\n");
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     case InterfaceInClass | CCID_CONTROL_GET_DATA_RATES:
         DPRINTF(s, 1, "ccid_control get data rates UNIMPLEMENTED\n");
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     default:
         DPRINTF(s, 1, "got unsupported/bogus control %x, value %x\n",
                 request, value);
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-    return ret;
 }
 
 static bool ccid_card_inserted(USBCCIDState *s)
@@ -870,18 +869,13 @@ static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock *recv)
     }
 }
 
-/*
- * Handle a single USB_TOKEN_OUT, return value returned to guest.
- * Return value:
- *  0             - all ok
- *  USB_RET_STALL - failed to handle packet
- */
-static int ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
+static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
 {
     CCID_Header *ccid_header;
 
     if (p->iov.size + s->bulk_out_pos > BULK_OUT_DATA_SIZE) {
-        return USB_RET_STALL;
+        p->status = USB_RET_STALL;
+        return;
     }
     ccid_header = (CCID_Header *)s->bulk_out_data;
     usb_packet_copy(p, s->bulk_out_data + s->bulk_out_pos, p->iov.size);
@@ -890,7 +884,7 @@ static int ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
         DPRINTF(s, D_VERBOSE,
             "usb-ccid: bulk_in: expecting more packets (%zd/%d)\n",
             p->iov.size, ccid_header->dwLength);
-        return 0;
+        return;
     }
     if (s->bulk_out_pos < 10) {
         DPRINTF(s, 1,
@@ -949,60 +943,52 @@ static int ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
         }
     }
     s->bulk_out_pos = 0;
-    return 0;
 }
 
-static int ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p)
+static void ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p)
 {
-    int ret = 0;
+    int len = 0;
 
-    assert(p->iov.size > 0);
     ccid_bulk_in_get(s);
     if (s->current_bulk_in != NULL) {
-        ret = MIN(s->current_bulk_in->len - s->current_bulk_in->pos,
+        len = MIN(s->current_bulk_in->len - s->current_bulk_in->pos,
                   p->iov.size);
         usb_packet_copy(p, s->current_bulk_in->data +
-                        s->current_bulk_in->pos, ret);
-        s->current_bulk_in->pos += ret;
+                        s->current_bulk_in->pos, len);
+        s->current_bulk_in->pos += len;
         if (s->current_bulk_in->pos == s->current_bulk_in->len) {
             ccid_bulk_in_release(s);
         }
     } else {
         /* return when device has no data - usb 2.0 spec Table 8-4 */
-        ret = USB_RET_NAK;
+        p->status = USB_RET_NAK;
     }
-    if (ret > 0) {
+    if (len) {
         DPRINTF(s, D_MORE_INFO,
                 "%s: %zd/%d req/act to guest (BULK_IN)\n",
-                __func__, p->iov.size, ret);
+                __func__, p->iov.size, len);
     }
-    if (ret != USB_RET_NAK && ret < p->iov.size) {
+    if (len < p->iov.size) {
         DPRINTF(s, 1,
                 "%s: returning short (EREMOTEIO) %d < %zd\n",
-                __func__, ret, p->iov.size);
+                __func__, len, p->iov.size);
     }
-    return ret;
 }
 
-static int ccid_handle_data(USBDevice *dev, USBPacket *p)
+static void ccid_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
-    int ret = 0;
     uint8_t buf[2];
 
     switch (p->pid) {
     case USB_TOKEN_OUT:
-        ret = ccid_handle_bulk_out(s, p);
+        ccid_handle_bulk_out(s, p);
         break;
 
     case USB_TOKEN_IN:
         switch (p->ep->nr) {
         case CCID_BULK_IN_EP:
-            if (!p->iov.size) {
-                ret = USB_RET_NAK;
-            } else {
-                ret = ccid_bulk_in_copy_to_guest(s, p);
-            }
+            ccid_bulk_in_copy_to_guest(s, p);
             break;
         case CCID_INT_IN_EP:
             if (s->notify_slot_change) {
@@ -1010,7 +996,6 @@ static int ccid_handle_data(USBDevice *dev, USBPacket *p)
                 buf[0] = CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange;
                 buf[1] = s->bmSlotICCState;
                 usb_packet_copy(p, buf, 2);
-                ret = 2;
                 s->notify_slot_change = false;
                 s->bmSlotICCState &= ~SLOT_0_CHANGED_MASK;
                 DPRINTF(s, D_INFO,
@@ -1021,17 +1006,15 @@ static int ccid_handle_data(USBDevice *dev, USBPacket *p)
             break;
         default:
             DPRINTF(s, 1, "Bad endpoint\n");
-            ret = USB_RET_STALL;
+            p->status = USB_RET_STALL;
             break;
         }
         break;
     default:
         DPRINTF(s, 1, "Bad token\n");
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-
-    return ret;
 }
 
 static void ccid_handle_destroy(USBDevice *dev)
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index e732191a26..50af97109b 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -215,7 +215,7 @@ static const USBDesc desc = {
 static void usb_msd_copy_data(MSDState *s, USBPacket *p)
 {
     uint32_t len;
-    len = p->iov.size - p->result;
+    len = p->iov.size - p->actual_length;
     if (len > s->scsi_len)
         len = s->scsi_len;
     usb_packet_copy(p, scsi_req_get_buf(s->req) + s->scsi_off, len);
@@ -263,7 +263,8 @@ static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
     if (p) {
         usb_msd_copy_data(s, p);
         p = s->packet;
-        if (p && p->result == p->iov.size) {
+        if (p && p->actual_length == p->iov.size) {
+            p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
             usb_msd_packet_complete(s);
         }
     }
@@ -292,7 +293,7 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r
             s->mode = USB_MSDM_CBW;
         } else {
             if (s->data_len) {
-                int len = (p->iov.size - p->result);
+                int len = (p->iov.size - p->actual_length);
                 usb_packet_skip(p, len);
                 s->data_len -= len;
             }
@@ -300,6 +301,7 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r
                 s->mode = USB_MSDM_CSW;
             }
         }
+        p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
         usb_msd_packet_complete(s);
     } else if (s->data_len == 0) {
         s->mode = USB_MSDM_CSW;
@@ -330,14 +332,14 @@ static void usb_msd_handle_reset(USBDevice *dev)
     assert(s->req == NULL);
 
     if (s->packet) {
-        s->packet->result = USB_RET_STALL;
+        s->packet->status = USB_RET_STALL;
         usb_msd_packet_complete(s);
     }
 
     s->mode = USB_MSDM_CBW;
 }
 
-static int usb_msd_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_msd_handle_control(USBDevice *dev, USBPacket *p,
                int request, int value, int index, int length, uint8_t *data)
 {
     MSDState *s = (MSDState *)dev;
@@ -345,29 +347,25 @@ static int usb_msd_handle_control(USBDevice *dev, USBPacket *p,
 
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
     if (ret >= 0) {
-        return ret;
+        return;
     }
 
-    ret = 0;
     switch (request) {
     case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
-        ret = 0;
         break;
         /* Class specific requests.  */
     case ClassInterfaceOutRequest | MassStorageReset:
         /* Reset state ready for the next CBW.  */
         s->mode = USB_MSDM_CBW;
-        ret = 0;
         break;
     case ClassInterfaceRequest | GetMaxLun:
         data[0] = 0;
-        ret = 1;
+        p->actual_length = 1;
         break;
     default:
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-    return ret;
 }
 
 static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
@@ -382,11 +380,10 @@ static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
     }
 }
 
-static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
 {
     MSDState *s = (MSDState *)dev;
     uint32_t tag;
-    int ret = 0;
     struct usb_msd_cbw cbw;
     uint8_t devep = p->ep->nr;
 
@@ -433,7 +430,6 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             if (s->req && s->req->cmd.xfer != SCSI_XFER_NONE) {
                 scsi_req_continue(s->req);
             }
-            ret = p->result;
             break;
 
         case USB_MSDM_DATAOUT:
@@ -446,7 +442,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
                 usb_msd_copy_data(s, p);
             }
             if (le32_to_cpu(s->csw.residue)) {
-                int len = p->iov.size - p->result;
+                int len = p->iov.size - p->actual_length;
                 if (len) {
                     usb_packet_skip(p, len);
                     s->data_len -= len;
@@ -455,12 +451,10 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
                     }
                 }
             }
-            if (p->result < p->iov.size) {
+            if (p->actual_length < p->iov.size) {
                 DPRINTF("Deferring packet %p [wait data-out]\n", p);
                 s->packet = p;
-                ret = USB_RET_ASYNC;
-            } else {
-                ret = p->result;
+                p->status = USB_RET_ASYNC;
             }
             break;
 
@@ -481,7 +475,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             }
             /* Waiting for SCSI write to complete.  */
             s->packet = p;
-            ret = USB_RET_ASYNC;
+            p->status = USB_RET_ASYNC;
             break;
 
         case USB_MSDM_CSW:
@@ -493,11 +487,10 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
                 /* still in flight */
                 DPRINTF("Deferring packet %p [wait status]\n", p);
                 s->packet = p;
-                ret = USB_RET_ASYNC;
+                p->status = USB_RET_ASYNC;
             } else {
                 usb_msd_send_status(s, p);
                 s->mode = USB_MSDM_CBW;
-                ret = 13;
             }
             break;
 
@@ -508,7 +501,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
                 usb_msd_copy_data(s, p);
             }
             if (le32_to_cpu(s->csw.residue)) {
-                int len = p->iov.size - p->result;
+                int len = p->iov.size - p->actual_length;
                 if (len) {
                     usb_packet_skip(p, len);
                     s->data_len -= len;
@@ -517,12 +510,10 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
                     }
                 }
             }
-            if (p->result < p->iov.size) {
+            if (p->actual_length < p->iov.size) {
                 DPRINTF("Deferring packet %p [wait data-in]\n", p);
                 s->packet = p;
-                ret = USB_RET_ASYNC;
-            } else {
-                ret = p->result;
+                p->status = USB_RET_ASYNC;
             }
             break;
 
@@ -535,11 +526,9 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
     default:
         DPRINTF("Bad token\n");
     fail:
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-
-    return ret;
 }
 
 static void usb_msd_password_cb(void *opaque, int err)
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index 4389380e95..a21b2ba627 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -256,10 +256,10 @@ static void usb_uas_send_status_bh(void *opaque)
 
     uas->status = NULL;
     usb_packet_copy(p, &st->status, st->length);
-    p->result = st->length;
     QTAILQ_REMOVE(&uas->results, st, next);
     g_free(st);
 
+    p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
     usb_packet_complete(&uas->dev, p);
 }
 
@@ -349,6 +349,7 @@ static void usb_uas_complete_data_packet(UASRequest *req)
     p = req->data;
     req->data = NULL;
     req->data_async = false;
+    p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
     usb_packet_complete(&req->uas->dev, p);
 }
 
@@ -357,16 +358,16 @@ static void usb_uas_copy_data(UASRequest *req)
     uint32_t length;
 
     length = MIN(req->buf_size - req->buf_off,
-                 req->data->iov.size - req->data->result);
+                 req->data->iov.size - req->data->actual_length);
     trace_usb_uas_xfer_data(req->uas->dev.addr, req->tag, length,
-                            req->data->result, req->data->iov.size,
+                            req->data->actual_length, req->data->iov.size,
                             req->buf_off, req->buf_size);
     usb_packet_copy(req->data, scsi_req_get_buf(req->req) + req->buf_off,
                     length);
     req->buf_off += length;
     req->data_off += length;
 
-    if (req->data->result == req->data->iov.size) {
+    if (req->data->actual_length == req->data->iov.size) {
         usb_uas_complete_data_packet(req);
     }
     if (req->buf_size && req->buf_off == req->buf_size) {
@@ -504,17 +505,17 @@ static void usb_uas_handle_reset(USBDevice *dev)
     }
 }
 
-static int usb_uas_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_uas_handle_control(USBDevice *dev, USBPacket *p,
                int request, int value, int index, int length, uint8_t *data)
 {
     int ret;
 
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
     if (ret >= 0) {
-        return ret;
+        return;
     }
     fprintf(stderr, "%s: unhandled control request\n", __func__);
-    return USB_RET_STALL;
+    p->status = USB_RET_STALL;
 }
 
 static void usb_uas_cancel_io(USBDevice *dev, USBPacket *p)
@@ -641,13 +642,13 @@ incorrect_lun:
     usb_uas_queue_response(uas, tag, UAS_RC_INCORRECT_LUN, 0);
 }
 
-static int usb_uas_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
 {
     UASDevice *uas = DO_UPCAST(UASDevice, dev, dev);
     uas_ui ui;
     UASStatus *st;
     UASRequest *req;
-    int length, ret = 0;
+    int length;
 
     switch (p->ep->nr) {
     case UAS_PIPE_ID_COMMAND:
@@ -656,16 +657,14 @@ static int usb_uas_handle_data(USBDevice *dev, USBPacket *p)
         switch (ui.hdr.id) {
         case UAS_UI_COMMAND:
             usb_uas_command(uas, &ui);
-            ret = length;
             break;
         case UAS_UI_TASK_MGMT:
             usb_uas_task(uas, &ui);
-            ret = length;
             break;
         default:
             fprintf(stderr, "%s: unknown command ui: id 0x%x\n",
                     __func__, ui.hdr.id);
-            ret = USB_RET_STALL;
+            p->status = USB_RET_STALL;
             break;
         }
         break;
@@ -674,11 +673,10 @@ static int usb_uas_handle_data(USBDevice *dev, USBPacket *p)
         if (st == NULL) {
             assert(uas->status == NULL);
             uas->status = p;
-            ret = USB_RET_ASYNC;
+            p->status = USB_RET_ASYNC;
             break;
         }
         usb_packet_copy(p, &st->status, st->length);
-        ret = st->length;
         QTAILQ_REMOVE(&uas->results, st, next);
         g_free(st);
         break;
@@ -687,28 +685,26 @@ static int usb_uas_handle_data(USBDevice *dev, USBPacket *p)
         req = (p->ep->nr == UAS_PIPE_ID_DATA_IN) ? uas->datain : uas->dataout;
         if (req == NULL) {
             fprintf(stderr, "%s: no inflight request\n", __func__);
-            ret = USB_RET_STALL;
+            p->status = USB_RET_STALL;
             break;
         }
         scsi_req_ref(req->req);
         req->data = p;
         usb_uas_copy_data(req);
-        if (p->result == p->iov.size || req->complete) {
+        if (p->actual_length == p->iov.size || req->complete) {
             req->data = NULL;
-            ret = p->result;
         } else {
             req->data_async = true;
-            ret = USB_RET_ASYNC;
+            p->status = USB_RET_ASYNC;
         }
         scsi_req_unref(req->req);
         usb_uas_start_next_transfer(uas);
         break;
     default:
         fprintf(stderr, "%s: invalid endpoint %d\n", __func__, p->ep->nr);
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-    return ret;
 }
 
 static void usb_uas_handle_destroy(USBDevice *dev)
diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c
index ed9a5ee358..08b416daa6 100644
--- a/hw/usb/dev-wacom.c
+++ b/hw/usb/dev-wacom.c
@@ -250,7 +250,7 @@ static void usb_wacom_handle_reset(USBDevice *dev)
     s->mode = WACOM_MODE_HID;
 }
 
-static int usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
                int request, int value, int index, int length, uint8_t *data)
 {
     USBWacomState *s = (USBWacomState *) dev;
@@ -258,10 +258,9 @@ static int usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
 
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
     if (ret >= 0) {
-        return ret;
+        return;
     }
 
-    ret = 0;
     switch (request) {
     case WACOM_SET_REPORT:
         if (s->mouse_grabbed) {
@@ -269,61 +268,58 @@ static int usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
             s->mouse_grabbed = 0;
         }
         s->mode = data[0];
-        ret = 0;
         break;
     case WACOM_GET_REPORT:
         data[0] = 0;
         data[1] = s->mode;
-        ret = 2;
+        p->actual_length = 2;
         break;
     /* USB HID requests */
     case HID_GET_REPORT:
         if (s->mode == WACOM_MODE_HID)
-            ret = usb_mouse_poll(s, data, length);
+            p->actual_length = usb_mouse_poll(s, data, length);
         else if (s->mode == WACOM_MODE_WACOM)
-            ret = usb_wacom_poll(s, data, length);
+            p->actual_length = usb_wacom_poll(s, data, length);
         break;
     case HID_GET_IDLE:
-        ret = 1;
         data[0] = s->idle;
+        p->actual_length = 1;
         break;
     case HID_SET_IDLE:
         s->idle = (uint8_t) (value >> 8);
-        ret = 0;
         break;
     default:
-        ret = USB_RET_STALL;
+        p->status = USB_RET_STALL;
         break;
     }
-    return ret;
 }
 
-static int usb_wacom_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_wacom_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBWacomState *s = (USBWacomState *) dev;
     uint8_t buf[p->iov.size];
-    int ret = 0;
+    int len = 0;
 
     switch (p->pid) {
     case USB_TOKEN_IN:
         if (p->ep->nr == 1) {
-            if (!(s->changed || s->idle))
-                return USB_RET_NAK;
+            if (!(s->changed || s->idle)) {
+                p->status = USB_RET_NAK;
+                return;
+            }
             s->changed = 0;
             if (s->mode == WACOM_MODE_HID)
-                ret = usb_mouse_poll(s, buf, p->iov.size);
+                len = usb_mouse_poll(s, buf, p->iov.size);
             else if (s->mode == WACOM_MODE_WACOM)
-                ret = usb_wacom_poll(s, buf, p->iov.size);
-            usb_packet_copy(p, buf, ret);
+                len = usb_wacom_poll(s, buf, p->iov.size);
+            usb_packet_copy(p, buf, len);
             break;
         }
         /* Fall through.  */
     case USB_TOKEN_OUT:
     default:
-        ret = USB_RET_STALL;
-        break;
+        p->status = USB_RET_STALL;
     }
-    return ret;
 }
 
 static void usb_wacom_handle_destroy(USBDevice *dev)
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index d9dc576e7c..3a1f5134ea 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1163,7 +1163,7 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
     p = container_of(packet, EHCIPacket, packet);
     assert(p->async == EHCI_ASYNC_INFLIGHT);
 
-    if (packet->result == USB_RET_REMOVE_FROM_QUEUE) {
+    if (packet->status == USB_RET_REMOVE_FROM_QUEUE) {
         trace_usb_ehci_packet_action(p->queue, p, "remove");
         ehci_free_packet(p);
         return;
@@ -1171,7 +1171,7 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
 
     trace_usb_ehci_packet_action(p->queue, p, "wakeup");
     p->async = EHCI_ASYNC_FINISHED;
-    p->usb_status = packet->result;
+    p->usb_status = packet->status ? packet->status : packet->actual_length;
 
     if (p->queue->async) {
         qemu_bh_schedule(p->queue->ehci->async_bh);
@@ -1253,7 +1253,6 @@ static void ehci_execute_complete(EHCIQueue *q)
 static int ehci_execute(EHCIPacket *p, const char *action)
 {
     USBEndpoint *ep;
-    int ret;
     int endp;
     bool spd;
 
@@ -1303,17 +1302,22 @@ static int ehci_execute(EHCIPacket *p, const char *action)
     }
 
     trace_usb_ehci_packet_action(p->queue, p, action);
-    ret = usb_handle_packet(p->queue->dev, &p->packet);
-    DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd endp %x ret %d\n",
-            q->qhaddr, q->qh.next, q->qtdaddr, q->pid,
-            q->packet.iov.size, endp, ret);
+    usb_handle_packet(p->queue->dev, &p->packet);
+    DPRINTF("submit: qh 0x%x next 0x%x qtd 0x%x pid 0x%x len %zd endp 0x%x "
+            "status %d actual_length %d\n", p->queue->qhaddr, p->qtd.next,
+            p->qtdaddr, p->pid, p->packet.iov.size, endp, p->packet.status,
+            p->packet.actual_length);
 
-    if (ret > BUFF_SIZE) {
+    if (p->packet.actual_length > BUFF_SIZE) {
         fprintf(stderr, "ret from usb_handle_packet > BUFF_SIZE\n");
         return USB_RET_PROCERR;
     }
 
-    return ret;
+    if (p->packet.status == USB_RET_SUCCESS) {
+        return p->packet.actual_length;
+    } else {
+        return p->packet.status;
+    }
 }
 
 /*  4.7.2
@@ -1370,8 +1374,10 @@ static int ehci_process_itd(EHCIState *ehci,
                 usb_packet_setup(&ehci->ipacket, pid, ep, addr, false,
                                  (itd->transact[i] & ITD_XACT_IOC) != 0);
                 usb_packet_map(&ehci->ipacket, &ehci->isgl);
-                ret = usb_handle_packet(dev, &ehci->ipacket);
+                usb_handle_packet(dev, &ehci->ipacket);
                 usb_packet_unmap(&ehci->ipacket, &ehci->isgl);
+                ret = (ehci->ipacket.status == USB_RET_SUCCESS) ?
+                      ehci->ipacket.actual_length : ehci->ipacket.status;
             } else {
                 DPRINTF("ISOCH: attempt to addess non-iso endpoint\n");
                 ret = USB_RET_NAK;
diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c
index 4f5539020b..c707f7a2bb 100644
--- a/hw/usb/hcd-musb.c
+++ b/hw/usb/hcd-musb.c
@@ -607,7 +607,6 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
 {
     USBDevice *dev;
     USBEndpoint *uep;
-    int ret;
     int idx = epnum && dir;
     int ttype;
 
@@ -632,15 +631,19 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
     ep->packey[dir].ep = ep;
     ep->packey[dir].dir = dir;
 
-    ret = usb_handle_packet(dev, &ep->packey[dir].p);
+    usb_handle_packet(dev, &ep->packey[dir].p);
 
-    if (ret == USB_RET_ASYNC) {
+    if (ep->packey[dir].p.status == USB_RET_ASYNC) {
         usb_device_flush_ep_queue(dev, uep);
         ep->status[dir] = len;
         return;
     }
 
-    ep->status[dir] = ret;
+    if (ep->packey[dir].p.status == USB_RET_SUCCESS) {
+        ep->status[dir] = ep->packey[dir].p.actual_length;
+    } else {
+        ep->status[dir] = ep->packey[dir].p.status;
+    }
     musb_schedule_cb(&s->port, &ep->packey[dir].p);
 }
 
@@ -754,7 +757,6 @@ static void musb_rx_packet_complete(USBPacket *packey, void *opaque)
 
     if (ep->status[1] == USB_RET_STALL) {
         ep->status[1] = 0;
-        packey->result = 0;
 
         ep->csr[1] |= MGC_M_RXCSR_H_RXSTALL;
         if (!epnum)
@@ -793,14 +795,12 @@ static void musb_rx_packet_complete(USBPacket *packey, void *opaque)
     /* TODO: check len for over/underruns of an OUT packet?  */
     /* TODO: perhaps make use of e->ext_size[1] here.  */
 
-    packey->result = ep->status[1];
-
     if (!(ep->csr[1] & (MGC_M_RXCSR_H_RXSTALL | MGC_M_RXCSR_DATAERROR))) {
         ep->csr[1] |= MGC_M_RXCSR_FIFOFULL | MGC_M_RXCSR_RXPKTRDY;
         if (!epnum)
             ep->csr[0] |= MGC_M_CSR0_RXPKTRDY;
 
-        ep->rxcount = packey->result; /* XXX: MIN(packey->len, ep->maxp[1]); */
+        ep->rxcount = ep->status[1]; /* XXX: MIN(packey->len, ep->maxp[1]); */
         /* In DMA mode: assert DMA request for this EP */
     }
 
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 7571e9e44a..6a39e9697b 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -807,21 +807,24 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
                          DMA_DIRECTION_TO_DEVICE);
     }
 
-    if (completion) {
-        ret = ohci->usb_packet.result;
-    } else {
+    if (!completion) {
         bool int_req = relative_frame_number == frame_count &&
                        OHCI_BM(iso_td.flags, TD_DI) == 0;
         dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
         ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
         usb_packet_setup(&ohci->usb_packet, pid, ep, addr, false, int_req);
         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
-        ret = usb_handle_packet(dev, &ohci->usb_packet);
-        if (ret == USB_RET_ASYNC) {
+        usb_handle_packet(dev, &ohci->usb_packet);
+        if (ohci->usb_packet.status == USB_RET_ASYNC) {
             usb_device_flush_ep_queue(dev, ep);
             return 1;
         }
     }
+    if (ohci->usb_packet.status == USB_RET_SUCCESS) {
+        ret = ohci->usb_packet.actual_length;
+    } else {
+        ret = ohci->usb_packet.status;
+    }
 
 #ifdef DEBUG_ISOCH
     printf("so 0x%.8x eo 0x%.8x\nsa 0x%.8x ea 0x%.8x\ndir %s len %zu ret %d\n",
@@ -997,7 +1000,6 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
     }
 #endif
     if (completion) {
-        ret = ohci->usb_packet.result;
         ohci->async_td = 0;
         ohci->async_complete = 0;
     } else {
@@ -1017,16 +1019,22 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
         usb_packet_setup(&ohci->usb_packet, pid, ep, addr, !flag_r,
                          OHCI_BM(td.flags, TD_DI) == 0);
         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
-        ret = usb_handle_packet(dev, &ohci->usb_packet);
+        usb_handle_packet(dev, &ohci->usb_packet);
 #ifdef DEBUG_PACKET
-        DPRINTF("ret=%d\n", ret);
+        DPRINTF("status=%d\n", ohci->usb_packet.status);
 #endif
-        if (ret == USB_RET_ASYNC) {
+        if (ohci->usb_packet.status == USB_RET_ASYNC) {
             usb_device_flush_ep_queue(dev, ep);
             ohci->async_td = addr;
             return 1;
         }
     }
+    if (ohci->usb_packet.status == USB_RET_SUCCESS) {
+        ret = ohci->usb_packet.actual_length;
+    } else {
+        ret = ohci->usb_packet.status;
+    }
+
     if (ret >= 0) {
         if (dir == OHCI_TD_DIR_IN) {
             ohci_copy_td(ohci, &td, ohci->usb_buf, ret,
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index f4b555addc..2838d21644 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -780,22 +780,21 @@ static int uhci_handle_td_error(UHCIState *s, UHCI_TD *td, uint32_t td_addr,
 
 static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_t *int_mask)
 {
-    int len = 0, max_len, ret;
+    int len = 0, max_len;
     uint8_t pid;
 
     max_len = ((td->token >> 21) + 1) & 0x7ff;
     pid = td->token & 0xff;
 
-    ret = async->packet.result;
-
     if (td->ctrl & TD_CTRL_IOS)
         td->ctrl &= ~TD_CTRL_ACTIVE;
 
-    if (ret < 0) {
-        return uhci_handle_td_error(s, td, async->td_addr, ret, int_mask);
+    if (async->packet.status != USB_RET_SUCCESS) {
+        return uhci_handle_td_error(s, td, async->td_addr,
+                                    async->packet.status, int_mask);
     }
 
-    len = async->packet.result;
+    len = async->packet.actual_length;
     td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
 
     /* The NAK bit may have been set by a previous frame, so clear it
@@ -824,7 +823,7 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_
 static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
                           UHCI_TD *td, uint32_t td_addr, uint32_t *int_mask)
 {
-    int len = 0, max_len;
+    int ret, max_len;
     bool spd;
     bool queuing = (q != NULL);
     uint8_t pid = td->token & 0xff;
@@ -915,13 +914,14 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
     switch(pid) {
     case USB_TOKEN_OUT:
     case USB_TOKEN_SETUP:
-        len = usb_handle_packet(q->ep->dev, &async->packet);
-        if (len >= 0)
-            len = max_len;
+        usb_handle_packet(q->ep->dev, &async->packet);
+        if (async->packet.status == USB_RET_SUCCESS) {
+            async->packet.actual_length = max_len;
+        }
         break;
 
     case USB_TOKEN_IN:
-        len = usb_handle_packet(q->ep->dev, &async->packet);
+        usb_handle_packet(q->ep->dev, &async->packet);
         break;
 
     default:
@@ -932,8 +932,8 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
         uhci_update_irq(s);
         return TD_RESULT_STOP_FRAME;
     }
- 
-    if (len == USB_RET_ASYNC) {
+
+    if (async->packet.status == USB_RET_ASYNC) {
         uhci_async_link(async);
         if (!queuing) {
             uhci_queue_fill(q, td);
@@ -941,13 +941,11 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
         return TD_RESULT_ASYNC_START;
     }
 
-    async->packet.result = len;
-
 done:
-    len = uhci_complete_td(s, td, async, int_mask);
+    ret = uhci_complete_td(s, td, async, int_mask);
     usb_packet_unmap(&async->packet, &async->sgl);
     uhci_async_free(async);
-    return len;
+    return ret;
 }
 
 static void uhci_async_complete(USBPort *port, USBPacket *packet)
@@ -955,7 +953,7 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet)
     UHCIAsync *async = container_of(packet, UHCIAsync, packet);
     UHCIState *s = async->queue->uhci;
 
-    if (packet->result == USB_RET_REMOVE_FROM_QUEUE) {
+    if (packet->status == USB_RET_REMOVE_FROM_QUEUE) {
         uhci_async_unlink(async);
         uhci_async_cancel(async);
         return;
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 900abf5566..d4a2e0c3ec 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1388,7 +1388,7 @@ static void xhci_xfer_report(XHCITransfer *xfer)
     XHCIState *xhci = xfer->xhci;
     int i;
 
-    left = xfer->packet.result < 0 ? 0 : xfer->packet.result;
+    left = xfer->packet.status ? 0 : xfer->packet.actual_length;
 
     for (i = 0; i < xfer->trb_count; i++) {
         XHCITRB *trb = &xfer->trbs[i];
@@ -1490,16 +1490,16 @@ static int xhci_setup_packet(XHCITransfer *xfer)
     return 0;
 }
 
-static int xhci_complete_packet(XHCITransfer *xfer, int ret)
+static int xhci_complete_packet(XHCITransfer *xfer)
 {
-    if (ret == USB_RET_ASYNC) {
+    if (xfer->packet.status == USB_RET_ASYNC) {
         trace_usb_xhci_xfer_async(xfer);
         xfer->running_async = 1;
         xfer->running_retry = 0;
         xfer->complete = 0;
         xfer->cancelled = 0;
         return 0;
-    } else if (ret == USB_RET_NAK) {
+    } else if (xfer->packet.status == USB_RET_NAK) {
         trace_usb_xhci_xfer_nak(xfer);
         xfer->running_async = 0;
         xfer->running_retry = 1;
@@ -1513,16 +1513,16 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret)
         xhci_xfer_unmap(xfer);
     }
 
-    if (ret >= 0) {
-        trace_usb_xhci_xfer_success(xfer, ret);
+    if (xfer->packet.status == USB_RET_SUCCESS) {
+        trace_usb_xhci_xfer_success(xfer, xfer->packet.actual_length);
         xfer->status = CC_SUCCESS;
         xhci_xfer_report(xfer);
         return 0;
     }
 
     /* error */
-    trace_usb_xhci_xfer_error(xfer, ret);
-    switch (ret) {
+    trace_usb_xhci_xfer_error(xfer, xfer->packet.status);
+    switch (xfer->packet.status) {
     case USB_RET_NODEV:
         xfer->status = CC_USB_TRANSACTION_ERROR;
         xhci_xfer_report(xfer);
@@ -1534,7 +1534,8 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret)
         xhci_stall_ep(xfer);
         break;
     default:
-        fprintf(stderr, "%s: FIXME: ret = %d\n", __FUNCTION__, ret);
+        fprintf(stderr, "%s: FIXME: status = %d\n", __func__,
+                xfer->packet.status);
         FIXME();
     }
     return 0;
@@ -1544,7 +1545,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
 {
     XHCITRB *trb_setup, *trb_status;
     uint8_t bmRequestType;
-    int ret;
 
     trb_setup = &xfer->trbs[0];
     trb_status = &xfer->trbs[xfer->trb_count-1];
@@ -1587,9 +1587,9 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
     }
     xfer->packet.parameter = trb_setup->parameter;
 
-    ret = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
+    usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
 
-    xhci_complete_packet(xfer, ret);
+    xhci_complete_packet(xfer);
     if (!xfer->running_async && !xfer->running_retry) {
         xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
     }
@@ -1636,7 +1636,6 @@ static void xhci_check_iso_kick(XHCIState *xhci, XHCITransfer *xfer,
 static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx)
 {
     uint64_t mfindex;
-    int ret;
 
     DPRINTF("xhci_submit(slotid=%d,epid=%d)\n", xfer->slotid, xfer->epid);
 
@@ -1671,9 +1670,9 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
     if (xhci_setup_packet(xfer) < 0) {
         return -1;
     }
-    ret = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
+    usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
 
-    xhci_complete_packet(xfer, ret);
+    xhci_complete_packet(xfer);
     if (!xfer->running_async && !xfer->running_retry) {
         xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
     }
@@ -1711,7 +1710,6 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
 
     if (epctx->retry) {
         XHCITransfer *xfer = epctx->retry;
-        int result;
 
         trace_usb_xhci_xfer_retry(xfer);
         assert(xfer->running_retry);
@@ -1725,19 +1723,19 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
             if (xhci_setup_packet(xfer) < 0) {
                 return;
             }
-            result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
-            assert(result != USB_RET_NAK);
-            xhci_complete_packet(xfer, result);
+            usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
+            assert(xfer->packet.status != USB_RET_NAK);
+            xhci_complete_packet(xfer);
         } else {
             /* retry nak'ed transfer */
             if (xhci_setup_packet(xfer) < 0) {
                 return;
             }
-            result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
-            if (result == USB_RET_NAK) {
+            usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
+            if (xfer->packet.status == USB_RET_NAK) {
                 return;
             }
-            xhci_complete_packet(xfer, result);
+            xhci_complete_packet(xfer);
         }
         assert(!xfer->running_retry);
         epctx->retry = NULL;
@@ -2922,11 +2920,11 @@ static void xhci_complete(USBPort *port, USBPacket *packet)
 {
     XHCITransfer *xfer = container_of(packet, XHCITransfer, packet);
 
-    if (packet->result == USB_RET_REMOVE_FROM_QUEUE) {
+    if (packet->status == USB_RET_REMOVE_FROM_QUEUE) {
         xhci_ep_nuke_one_xfer(xfer);
         return;
     }
-    xhci_complete_packet(xfer, packet->result);
+    xhci_complete_packet(xfer);
     xhci_kick_ep(xfer->xhci, xfer->slotid, xfer->epid);
 }
 
diff --git a/hw/usb/host-bsd.c b/hw/usb/host-bsd.c
index ec26266620..6473e8b747 100644
--- a/hw/usb/host-bsd.c
+++ b/hw/usb/host-bsd.c
@@ -121,7 +121,7 @@ static void usb_host_handle_reset(USBDevice *dev)
  * -check device states against transfer requests
  *  and return appropriate response
  */
-static int usb_host_handle_control(USBDevice *dev,
+static void usb_host_handle_control(USBDevice *dev,
                                    USBPacket *p,
                                    int request,
                                    int value,
@@ -139,7 +139,6 @@ static int usb_host_handle_control(USBDevice *dev,
 
         /* specific SET_ADDRESS support */
         dev->addr = value;
-        return 0;
     } else if ((request >> 8) == UT_WRITE_DEVICE &&
                (request & 0xff) == UR_SET_CONFIG) {
 
@@ -151,10 +150,8 @@ static int usb_host_handle_control(USBDevice *dev,
             printf("handle_control: failed to set configuration - %s\n",
                    strerror(errno));
 #endif
-            return USB_RET_STALL;
+            p->status = USB_RET_STALL;
         }
-
-        return 0;
     } else if ((request >> 8) == UT_WRITE_INTERFACE &&
                (request & 0xff) == UR_SET_INTERFACE) {
 
@@ -168,10 +165,8 @@ static int usb_host_handle_control(USBDevice *dev,
             printf("handle_control: failed to set alternate interface - %s\n",
                    strerror(errno));
 #endif
-            return USB_RET_STALL;
+            p->status = USB_RET_STALL;
         }
-
-        return 0;
     } else {
         req.ucr_request.bmRequestType = request >> 8;
         req.ucr_request.bRequest = request & 0xff;
@@ -201,14 +196,14 @@ static int usb_host_handle_control(USBDevice *dev,
             printf("handle_control: error after request - %s\n",
                    strerror(errno));
 #endif
-            return USB_RET_NAK; // STALL
+            p->status = USB_RET_NAK; /* STALL */
         } else {
-            return req.ucr_actlen;
+            p->actual_length = req.ucr_actlen;
         }
     }
 }
 
-static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_host_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBHostDevice *s = (USBHostDevice *)dev;
     int ret, fd, mode;
@@ -232,7 +227,8 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
     fd = ensure_ep_open(s, devep, mode);
     if (fd < 0) {
         sigprocmask(SIG_SETMASK, &old_mask, NULL);
-        return USB_RET_NODEV;
+        p->status = USB_RET_NODEV;
+        return;
     }
 
     if (ioctl(fd, USB_SET_TIMEOUT, &timeout) < 0) {
@@ -267,12 +263,13 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
         switch(errno) {
         case ETIMEDOUT:
         case EINTR:
-            return USB_RET_NAK;
+            p->status = USB_RET_NAK;
+            break;
         default:
-            return USB_RET_STALL;
+            p->status = USB_RET_STALL;
         }
     } else {
-        return ret;
+        p->actual_length = ret;
     }
 }
 
diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c
index 3a258b4bd4..ca3e24a850 100644
--- a/hw/usb/host-linux.c
+++ b/hw/usb/host-linux.c
@@ -366,28 +366,29 @@ static void async_complete(void *opaque)
         if (p) {
             switch (aurb->urb.status) {
             case 0:
-                p->result += aurb->urb.actual_length;
+                p->actual_length = aurb->urb.actual_length;
+                p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
                 break;
 
             case -EPIPE:
                 set_halt(s, p->pid, p->ep->nr);
-                p->result = USB_RET_STALL;
+                p->status = USB_RET_STALL;
                 break;
 
             case -EOVERFLOW:
-                p->result = USB_RET_BABBLE;
+                p->status = USB_RET_BABBLE;
                 break;
 
             default:
-                p->result = USB_RET_IOERROR;
+                p->status = USB_RET_IOERROR;
                 break;
             }
 
             if (aurb->urb.type == USBDEVFS_URB_TYPE_CONTROL) {
-                trace_usb_host_req_complete(s->bus_num, s->addr, p, p->result);
+                trace_usb_host_req_complete(s->bus_num, s->addr, p, p->status);
                 usb_generic_async_ctrl_complete(&s->dev, p);
             } else if (!aurb->more) {
-                trace_usb_host_req_complete(s->bus_num, s->addr, p, p->result);
+                trace_usb_host_req_complete(s->bus_num, s->addr, p, p->status);
                 usb_packet_complete(&s->dev, p);
             }
         }
@@ -733,27 +734,31 @@ static void usb_host_stop_n_free_iso(USBHostDevice *s, int pid, uint8_t ep)
     clear_iso_started(s, pid, ep);
 }
 
-static int urb_status_to_usb_ret(int status)
+static void urb_status_to_usb_ret(int status, USBPacket *p)
 {
     switch (status) {
     case -EPIPE:
-        return USB_RET_STALL;
+        p->status = USB_RET_STALL;
+        break;
     case -EOVERFLOW:
-        return USB_RET_BABBLE;
+        p->status = USB_RET_BABBLE;
+        break;
     default:
-        return USB_RET_IOERROR;
+        p->status = USB_RET_IOERROR;
     }
 }
 
-static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
+static void usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
 {
     AsyncURB *aurb;
-    int i, j, ret, max_packet_size, offset, len = 0;
+    int i, j, max_packet_size, offset, len;
     uint8_t *buf;
 
     max_packet_size = p->ep->max_packet_size;
-    if (max_packet_size == 0)
-        return USB_RET_NAK;
+    if (max_packet_size == 0) {
+        p->status = USB_RET_NAK;
+        return;
+    }
 
     aurb = get_iso_urb(s, p->pid, p->ep->nr);
     if (!aurb) {
@@ -766,18 +771,17 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
         if (in) {
             /* Check urb status  */
             if (aurb[i].urb.status) {
-                len = urb_status_to_usb_ret(aurb[i].urb.status);
+                urb_status_to_usb_ret(aurb[i].urb.status, p);
                 /* Move to the next urb */
                 aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB - 1;
             /* Check frame status */
             } else if (aurb[i].urb.iso_frame_desc[j].status) {
-                len = urb_status_to_usb_ret(
-                                        aurb[i].urb.iso_frame_desc[j].status);
+                urb_status_to_usb_ret(aurb[i].urb.iso_frame_desc[j].status, p);
             /* Check the frame fits */
             } else if (aurb[i].urb.iso_frame_desc[j].actual_length
                        > p->iov.size) {
                 printf("husb: received iso data is larger then packet\n");
-                len = USB_RET_BABBLE;
+                p->status = USB_RET_BABBLE;
             /* All good copy data over */
             } else {
                 len = aurb[i].urb.iso_frame_desc[j].actual_length;
@@ -792,7 +796,8 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
             /* Check the frame fits */
             if (len > max_packet_size) {
                 printf("husb: send iso data is larger then max packet size\n");
-                return USB_RET_NAK;
+                p->status = USB_RET_NAK;
+                return;
             }
 
             /* All good copy data over */
@@ -823,17 +828,16 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
         /* (Re)-submit all fully consumed / filled urbs */
         for (i = 0; i < s->iso_urb_count; i++) {
             if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
-                ret = ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]);
-                if (ret < 0) {
+                if (ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]) < 0) {
                     perror("USBDEVFS_SUBMITURB");
-                    if (!in || len == 0) {
+                    if (!in || p->status == USB_RET_SUCCESS) {
                         switch(errno) {
                         case ETIMEDOUT:
-                            len = USB_RET_NAK;
+                            p->status = USB_RET_NAK;
                             break;
                         case EPIPE:
                         default:
-                            len = USB_RET_STALL;
+                            p->status = USB_RET_STALL;
                         }
                     }
                     break;
@@ -843,11 +847,9 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
             }
         }
     }
-
-    return len;
 }
 
-static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_host_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
     struct usbdevfs_urb *urb;
@@ -862,7 +864,8 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
 
     if (!is_valid(s, p->pid, p->ep->nr)) {
         trace_usb_host_req_complete(s->bus_num, s->addr, p, USB_RET_NAK);
-        return USB_RET_NAK;
+        p->status = USB_RET_NAK;
+        return;
     }
 
     if (p->pid == USB_TOKEN_IN) {
@@ -877,13 +880,15 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
         if (ret < 0) {
             perror("USBDEVFS_CLEAR_HALT");
             trace_usb_host_req_complete(s->bus_num, s->addr, p, USB_RET_NAK);
-            return USB_RET_NAK;
+            p->status = USB_RET_NAK;
+            return;
         }
         clear_halt(s, p->pid, p->ep->nr);
     }
 
     if (is_isoc(s, p->pid, p->ep->nr)) {
-        return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
+        usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
+        return;
     }
 
     v = 0;
@@ -933,17 +938,19 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
             case ETIMEDOUT:
                 trace_usb_host_req_complete(s->bus_num, s->addr, p,
                                             USB_RET_NAK);
-                return USB_RET_NAK;
+                p->status = USB_RET_NAK;
+                break;
             case EPIPE:
             default:
                 trace_usb_host_req_complete(s->bus_num, s->addr, p,
                                             USB_RET_STALL);
-                return USB_RET_STALL;
+                p->status = USB_RET_STALL;
             }
+            return;
         }
     } while (rem > 0);
 
-    return USB_RET_ASYNC;
+    p->status = USB_RET_ASYNC;
 }
 
 static int ctrl_error(void)
@@ -955,14 +962,13 @@ static int ctrl_error(void)
     }
 }
 
-static int usb_host_set_address(USBHostDevice *s, int addr)
+static void usb_host_set_address(USBHostDevice *s, int addr)
 {
     trace_usb_host_set_address(s->bus_num, s->addr, addr);
     s->dev.addr = addr;
-    return 0;
 }
 
-static int usb_host_set_config(USBHostDevice *s, int config)
+static void usb_host_set_config(USBHostDevice *s, int config, USBPacket *p)
 {
     int ret, first = 1;
 
@@ -987,14 +993,15 @@ again:
     }
 
     if (ret < 0) {
-        return ctrl_error();
+        p->status = ctrl_error();
+        return;
     }
     usb_host_claim_interfaces(s, config);
     usb_linux_update_endp_table(s);
-    return 0;
 }
 
-static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
+static void usb_host_set_interface(USBHostDevice *s, int iface, int alt,
+                                   USBPacket *p)
 {
     struct usbdevfs_setinterface si;
     int i, ret;
@@ -1011,7 +1018,8 @@ static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
     }
 
     if (iface >= USB_MAX_INTERFACES) {
-        return USB_RET_STALL;
+        p->status = USB_RET_STALL;
+        return;
     }
 
     si.interface  = iface;
@@ -1022,15 +1030,15 @@ static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
             iface, alt, ret, errno);
 
     if (ret < 0) {
-        return ctrl_error();
+        p->status = ctrl_error();
+        return;
     }
 
     s->dev.altsetting[iface] = alt;
     usb_linux_update_endp_table(s);
-    return 0;
 }
 
-static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_host_handle_control(USBDevice *dev, USBPacket *p,
                int request, int value, int index, int length, uint8_t *data)
 {
     USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
@@ -1048,19 +1056,19 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
 
     switch (request) {
     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-        ret = usb_host_set_address(s, value);
-        trace_usb_host_req_emulated(s->bus_num, s->addr, p, ret);
-        return ret;
+        usb_host_set_address(s, value);
+        trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status);
+        return;
 
     case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-        ret = usb_host_set_config(s, value & 0xff);
-        trace_usb_host_req_emulated(s->bus_num, s->addr, p, ret);
-        return ret;
+        usb_host_set_config(s, value & 0xff, p);
+        trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status);
+        return;
 
     case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
-        ret = usb_host_set_interface(s, index, value);
-        trace_usb_host_req_emulated(s->bus_num, s->addr, p, ret);
-        return ret;
+        usb_host_set_interface(s, index, value, p);
+        trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status);
+        return;
 
     case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
         if (value == 0) { /* clear halt */
@@ -1068,17 +1076,16 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
             ioctl(s->fd, USBDEVFS_CLEAR_HALT, &index);
             clear_halt(s, pid, index & 0x0f);
             trace_usb_host_req_emulated(s->bus_num, s->addr, p, 0);
-            return 0;
+            return;
         }
     }
 
     /* The rest are asynchronous */
-    assert(p && p->result == 0);
-
     if (length > sizeof(dev->data_buf)) {
         fprintf(stderr, "husb: ctrl buffer too small (%d > %zu)\n",
                 length, sizeof(dev->data_buf));
-        return USB_RET_STALL;
+        p->status = USB_RET_STALL;
+        return;
     }
 
     aurb = async_alloc(s);
@@ -1112,14 +1119,17 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
 
         switch(errno) {
         case ETIMEDOUT:
-            return USB_RET_NAK;
+            p->status = USB_RET_NAK;
+            break;
         case EPIPE:
         default:
-            return USB_RET_STALL;
+            p->status = USB_RET_STALL;
+            break;
         }
+        return;
     }
 
-    return USB_RET_ASYNC;
+    p->status = USB_RET_ASYNC;
 }
 
 /* returns 1 on problem encountered or 0 for success */
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index c5cfe0b313..cd4388e332 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -141,8 +141,8 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id,
     struct usb_redir_interrupt_packet_header *interrupt_header,
     uint8_t *data, int data_len);
 
-static int usbredir_handle_status(USBRedirDevice *dev,
-                                       int status, int actual_len);
+static void usbredir_handle_status(USBRedirDevice *dev, USBPacket *p,
+    int status);
 
 #define VERSION "qemu usb-redir guest " QEMU_VERSION
 
@@ -443,7 +443,7 @@ static void usbredir_handle_reset(USBDevice *udev)
     usbredirparser_do_write(dev->parser);
 }
 
-static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
+static void usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
                                      uint8_t ep)
 {
     int status, len;
@@ -500,7 +500,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
                 !dev->endpoint[EP2I(ep)].bufpq_prefilled) {
             if (dev->endpoint[EP2I(ep)].bufpq_size <
                     dev->endpoint[EP2I(ep)].bufpq_target_size) {
-                return usbredir_handle_status(dev, 0, 0);
+                return;
             }
             dev->endpoint[EP2I(ep)].bufpq_prefilled = 1;
         }
@@ -514,7 +514,8 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
             /* Check iso_error for stream errors, otherwise its an underrun */
             status = dev->endpoint[EP2I(ep)].iso_error;
             dev->endpoint[EP2I(ep)].iso_error = 0;
-            return status ? USB_RET_IOERROR : 0;
+            p->status = status ? USB_RET_IOERROR : USB_RET_SUCCESS;
+            return;
         }
         DPRINTF2("iso-token-in ep %02X status %d len %d queue-size: %d\n", ep,
                  isop->status, isop->len, dev->endpoint[EP2I(ep)].bufpq_size);
@@ -522,7 +523,8 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
         status = isop->status;
         if (status != usb_redir_success) {
             bufp_free(dev, isop, ep);
-            return USB_RET_IOERROR;
+            p->status = USB_RET_IOERROR;
+            return;
         }
 
         len = isop->len;
@@ -530,11 +532,11 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
             ERROR("received iso data is larger then packet ep %02X (%d > %d)\n",
                   ep, len, (int)p->iov.size);
             bufp_free(dev, isop, ep);
-            return USB_RET_BABBLE;
+            p->status = USB_RET_BABBLE;
+            return;
         }
         usb_packet_copy(p, isop->data, len);
         bufp_free(dev, isop, ep);
-        return len;
     } else {
         /* If the stream was not started because of a pending error don't
            send the packet to the usb-host */
@@ -554,7 +556,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
         dev->endpoint[EP2I(ep)].iso_error = 0;
         DPRINTF2("iso-token-out ep %02X status %d len %zd\n", ep, status,
                  p->iov.size);
-        return usbredir_handle_status(dev, status, p->iov.size);
+        usbredir_handle_status(dev, p, status);
     }
 }
 
@@ -572,7 +574,7 @@ static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep)
     usbredir_free_bufpq(dev, ep);
 }
 
-static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
+static void usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
                                       uint8_t ep)
 {
     struct usb_redir_bulk_packet_header bulk_packet;
@@ -581,7 +583,8 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
     DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, size, p->id);
 
     if (usbredir_already_in_flight(dev, p->id)) {
-        return USB_RET_ASYNC;
+        p->status = USB_RET_ASYNC;
+        return;
     }
 
     bulk_packet.endpoint  = ep;
@@ -608,10 +611,10 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
                                         &bulk_packet, buf, size);
     }
     usbredirparser_do_write(dev->parser);
-    return USB_RET_ASYNC;
+    p->status = USB_RET_ASYNC;
 }
 
-static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
+static void usbredir_handle_interrupt_data(USBRedirDevice *dev,
                                            USBPacket *p, uint8_t ep)
 {
     if (ep & USB_DIR_IN) {
@@ -643,9 +646,11 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
             status = dev->endpoint[EP2I(ep)].interrupt_error;
             dev->endpoint[EP2I(ep)].interrupt_error = 0;
             if (status) {
-                return usbredir_handle_status(dev, status, 0);
+                usbredir_handle_status(dev, p, status);
+            } else {
+                p->status = USB_RET_NAK;
             }
-            return USB_RET_NAK;
+            return;
         }
         DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
                 intp->status, intp->len);
@@ -653,18 +658,19 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
         status = intp->status;
         if (status != usb_redir_success) {
             bufp_free(dev, intp, ep);
-            return usbredir_handle_status(dev, status, 0);
+            usbredir_handle_status(dev, p, status);
+            return;
         }
 
         len = intp->len;
         if (len > p->iov.size) {
             ERROR("received int data is larger then packet ep %02X\n", ep);
             bufp_free(dev, intp, ep);
-            return USB_RET_BABBLE;
+            p->status = USB_RET_BABBLE;
+            return;
         }
         usb_packet_copy(p, intp->data, len);
         bufp_free(dev, intp, ep);
-        return len;
     } else {
         /* Output interrupt endpoint, normal async operation */
         struct usb_redir_interrupt_packet_header interrupt_packet;
@@ -674,7 +680,8 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
                 p->iov.size, p->id);
 
         if (usbredir_already_in_flight(dev, p->id)) {
-            return USB_RET_ASYNC;
+            p->status = USB_RET_ASYNC;
+            return;
         }
 
         interrupt_packet.endpoint  = ep;
@@ -685,7 +692,7 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
         usbredirparser_send_interrupt_packet(dev->parser, p->id,
                                         &interrupt_packet, buf, p->iov.size);
         usbredirparser_do_write(dev->parser);
-        return USB_RET_ASYNC;
+        p->status = USB_RET_ASYNC;
     }
 }
 
@@ -705,7 +712,7 @@ static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev,
     usbredir_free_bufpq(dev, ep);
 }
 
-static int usbredir_handle_data(USBDevice *udev, USBPacket *p)
+static void usbredir_handle_data(USBDevice *udev, USBPacket *p)
 {
     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
     uint8_t ep;
@@ -718,21 +725,26 @@ static int usbredir_handle_data(USBDevice *udev, USBPacket *p)
     switch (dev->endpoint[EP2I(ep)].type) {
     case USB_ENDPOINT_XFER_CONTROL:
         ERROR("handle_data called for control transfer on ep %02X\n", ep);
-        return USB_RET_NAK;
+        p->status = USB_RET_NAK;
+        break;
     case USB_ENDPOINT_XFER_ISOC:
-        return usbredir_handle_iso_data(dev, p, ep);
+        usbredir_handle_iso_data(dev, p, ep);
+        break;
     case USB_ENDPOINT_XFER_BULK:
         if (p->state == USB_PACKET_SETUP && p->pid == USB_TOKEN_IN &&
                 p->ep->pipeline) {
-            return USB_RET_ADD_TO_QUEUE;
+            p->status = USB_RET_ADD_TO_QUEUE;
+            break;
         }
-        return usbredir_handle_bulk_data(dev, p, ep);
+        usbredir_handle_bulk_data(dev, p, ep);
+        break;
     case USB_ENDPOINT_XFER_INT:
-        return usbredir_handle_interrupt_data(dev, p, ep);
+        usbredir_handle_interrupt_data(dev, p, ep);
+        break;
     default:
         ERROR("handle_data ep %02X has unknown type %d\n", ep,
               dev->endpoint[EP2I(ep)].type);
-        return USB_RET_NAK;
+        p->status = USB_RET_NAK;
     }
 }
 
@@ -743,7 +755,7 @@ static void usbredir_flush_ep_queue(USBDevice *dev, USBEndpoint *ep)
     }
 }
 
-static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
+static void usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
                                 int config)
 {
     struct usb_redir_set_configuration_header set_config;
@@ -768,19 +780,19 @@ static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
     set_config.configuration = config;
     usbredirparser_send_set_configuration(dev->parser, p->id, &set_config);
     usbredirparser_do_write(dev->parser);
-    return USB_RET_ASYNC;
+    p->status = USB_RET_ASYNC;
 }
 
-static int usbredir_get_config(USBRedirDevice *dev, USBPacket *p)
+static void usbredir_get_config(USBRedirDevice *dev, USBPacket *p)
 {
     DPRINTF("get config id %"PRIu64"\n", p->id);
 
     usbredirparser_send_get_configuration(dev->parser, p->id);
     usbredirparser_do_write(dev->parser);
-    return USB_RET_ASYNC;
+    p->status = USB_RET_ASYNC;
 }
 
-static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p,
+static void usbredir_set_interface(USBRedirDevice *dev, USBPacket *p,
                                    int interface, int alt)
 {
     struct usb_redir_set_alt_setting_header set_alt;
@@ -808,10 +820,10 @@ static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p,
     set_alt.alt = alt;
     usbredirparser_send_set_alt_setting(dev->parser, p->id, &set_alt);
     usbredirparser_do_write(dev->parser);
-    return USB_RET_ASYNC;
+    p->status = USB_RET_ASYNC;
 }
 
-static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p,
+static void usbredir_get_interface(USBRedirDevice *dev, USBPacket *p,
                                    int interface)
 {
     struct usb_redir_get_alt_setting_header get_alt;
@@ -821,17 +833,18 @@ static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p,
     get_alt.interface = interface;
     usbredirparser_send_get_alt_setting(dev->parser, p->id, &get_alt);
     usbredirparser_do_write(dev->parser);
-    return USB_RET_ASYNC;
+    p->status = USB_RET_ASYNC;
 }
 
-static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
+static void usbredir_handle_control(USBDevice *udev, USBPacket *p,
         int request, int value, int index, int length, uint8_t *data)
 {
     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
     struct usb_redir_control_packet_header control_packet;
 
     if (usbredir_already_in_flight(dev, p->id)) {
-        return USB_RET_ASYNC;
+        p->status = USB_RET_ASYNC;
+        return;
     }
 
     /* Special cases for certain standard device requests */
@@ -839,15 +852,19 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
         DPRINTF("set address %d\n", value);
         dev->dev.addr = value;
-        return 0;
+        return;
     case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-        return usbredir_set_config(dev, p, value & 0xff);
+        usbredir_set_config(dev, p, value & 0xff);
+        return;
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-        return usbredir_get_config(dev, p);
+        usbredir_get_config(dev, p);
+        return;
     case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
-        return usbredir_set_interface(dev, p, index, value);
+        usbredir_set_interface(dev, p, index, value);
+        return;
     case InterfaceRequest | USB_REQ_GET_INTERFACE:
-        return usbredir_get_interface(dev, p, index);
+        usbredir_get_interface(dev, p, index);
+        return;
     }
 
     /* Normal ctrl requests, note request is (bRequestType << 8) | bRequest */
@@ -871,7 +888,7 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
                                            &control_packet, data, length);
     }
     usbredirparser_do_write(dev->parser);
-    return USB_RET_ASYNC;
+    p->status = USB_RET_ASYNC;
 }
 
 /*
@@ -1159,29 +1176,34 @@ error:
  * usbredirparser packet complete callbacks
  */
 
-static int usbredir_handle_status(USBRedirDevice *dev,
-                                       int status, int actual_len)
+static void usbredir_handle_status(USBRedirDevice *dev, USBPacket *p,
+    int status)
 {
     switch (status) {
     case usb_redir_success:
-        return actual_len;
+        p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
+        break;
     case usb_redir_stall:
-        return USB_RET_STALL;
+        p->status = USB_RET_STALL;
+        break;
     case usb_redir_cancelled:
         /*
          * When the usbredir-host unredirects a device, it will report a status
          * of cancelled for all pending packets, followed by a disconnect msg.
          */
-        return USB_RET_IOERROR;
+        p->status = USB_RET_IOERROR;
+        break;
     case usb_redir_inval:
         WARNING("got invalid param error from usb-host?\n");
-        return USB_RET_IOERROR;
+        p->status = USB_RET_IOERROR;
+        break;
     case usb_redir_babble:
-        return USB_RET_BABBLE;
+        p->status = USB_RET_BABBLE;
+        break;
     case usb_redir_ioerror:
     case usb_redir_timeout:
     default:
-        return USB_RET_IOERROR;
+        p->status = USB_RET_IOERROR;
     }
 }
 
@@ -1412,7 +1434,6 @@ static void usbredir_configuration_status(void *priv, uint64_t id,
 {
     USBRedirDevice *dev = priv;
     USBPacket *p;
-    int len = 0;
 
     DPRINTF("set config status %d config %d id %"PRIu64"\n",
             config_status->status, config_status->configuration, id);
@@ -1421,9 +1442,9 @@ static void usbredir_configuration_status(void *priv, uint64_t id,
     if (p) {
         if (dev->dev.setup_buf[0] & USB_DIR_IN) {
             dev->dev.data_buf[0] = config_status->configuration;
-            len = 1;
+            p->actual_length = 1;
         }
-        p->result = usbredir_handle_status(dev, config_status->status, len);
+        usbredir_handle_status(dev, p, config_status->status);
         usb_generic_async_ctrl_complete(&dev->dev, p);
     }
 }
@@ -1433,7 +1454,6 @@ static void usbredir_alt_setting_status(void *priv, uint64_t id,
 {
     USBRedirDevice *dev = priv;
     USBPacket *p;
-    int len = 0;
 
     DPRINTF("alt status %d intf %d alt %d id: %"PRIu64"\n",
             alt_setting_status->status, alt_setting_status->interface,
@@ -1443,10 +1463,9 @@ static void usbredir_alt_setting_status(void *priv, uint64_t id,
     if (p) {
         if (dev->dev.setup_buf[0] & USB_DIR_IN) {
             dev->dev.data_buf[0] = alt_setting_status->alt;
-            len = 1;
+            p->actual_length = 1;
         }
-        p->result =
-            usbredir_handle_status(dev, alt_setting_status->status, len);
+        usbredir_handle_status(dev, p, alt_setting_status->status);
         usb_generic_async_ctrl_complete(&dev->dev, p);
     }
 }
@@ -1522,18 +1541,19 @@ static void usbredir_control_packet(void *priv, uint64_t id,
 
     p = usbredir_find_packet_by_id(dev, 0, id);
     if (p) {
-        len = usbredir_handle_status(dev, control_packet->status, len);
-        if (len > 0) {
+        usbredir_handle_status(dev, p, control_packet->status);
+        if (p->status == USB_RET_SUCCESS) {
             usbredir_log_data(dev, "ctrl data in:", data, data_len);
             if (data_len <= sizeof(dev->dev.data_buf)) {
                 memcpy(dev->dev.data_buf, data, data_len);
             } else {
                 ERROR("ctrl buffer too small (%d > %zu)\n",
                       data_len, sizeof(dev->dev.data_buf));
-                len = USB_RET_STALL;
+                p->status = USB_RET_STALL;
+                len = 0;
             }
         }
-        p->result = len;
+        p->actual_length = len;
         usb_generic_async_ctrl_complete(&dev->dev, p);
     }
     free(data);
@@ -1554,8 +1574,8 @@ static void usbredir_bulk_packet(void *priv, uint64_t id,
     p = usbredir_find_packet_by_id(dev, ep, id);
     if (p) {
         size_t size = (p->combined) ? p->combined->iov.size : p->iov.size;
-        len = usbredir_handle_status(dev, bulk_packet->status, len);
-        if (len > 0) {
+        usbredir_handle_status(dev, p, bulk_packet->status);
+        if (p->status == USB_RET_SUCCESS) {
             usbredir_log_data(dev, "bulk data in:", data, data_len);
             if (data_len <= size) {
                 if (p->combined) {
@@ -1567,10 +1587,11 @@ static void usbredir_bulk_packet(void *priv, uint64_t id,
             } else {
                 ERROR("bulk got more data then requested (%d > %zd)\n",
                       data_len, p->iov.size);
-                len = USB_RET_BABBLE;
+                p->status = USB_RET_BABBLE;
+                len = 0;
             }
         }
-        p->result = len;
+        p->actual_length = len;
         if (p->pid == USB_TOKEN_IN && p->ep->pipeline) {
             usb_combined_input_packet_complete(&dev->dev, p);
         } else {
@@ -1636,8 +1657,8 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id,
 
         USBPacket *p = usbredir_find_packet_by_id(dev, ep, id);
         if (p) {
-            p->result = usbredir_handle_status(dev,
-                                               interrupt_packet->status, len);
+            usbredir_handle_status(dev, p, interrupt_packet->status);
+            p->actual_length = len;
             usb_packet_complete(&dev->dev, p);
         }
     }

From e94ca437ba92f6e0aeeb0dbda75e158479d413b7 Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Thu, 1 Nov 2012 17:15:02 +0100
Subject: [PATCH 1548/2270] usb-redir: Allow packets to have both data and an
 error-status

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/redirect.c | 56 +++++++++++++++++------------------------------
 1 file changed, 20 insertions(+), 36 deletions(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index cd4388e332..be9a232059 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -521,22 +521,16 @@ static void usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
                  isop->status, isop->len, dev->endpoint[EP2I(ep)].bufpq_size);
 
         status = isop->status;
-        if (status != usb_redir_success) {
-            bufp_free(dev, isop, ep);
-            p->status = USB_RET_IOERROR;
-            return;
-        }
-
         len = isop->len;
         if (len > p->iov.size) {
             ERROR("received iso data is larger then packet ep %02X (%d > %d)\n",
                   ep, len, (int)p->iov.size);
-            bufp_free(dev, isop, ep);
-            p->status = USB_RET_BABBLE;
-            return;
+            len = p->iov.size;
+            status = usb_redir_babble;
         }
         usb_packet_copy(p, isop->data, len);
         bufp_free(dev, isop, ep);
+        usbredir_handle_status(dev, p, status);
     } else {
         /* If the stream was not started because of a pending error don't
            send the packet to the usb-host */
@@ -656,21 +650,15 @@ static void usbredir_handle_interrupt_data(USBRedirDevice *dev,
                 intp->status, intp->len);
 
         status = intp->status;
-        if (status != usb_redir_success) {
-            bufp_free(dev, intp, ep);
-            usbredir_handle_status(dev, p, status);
-            return;
-        }
-
         len = intp->len;
         if (len > p->iov.size) {
             ERROR("received int data is larger then packet ep %02X\n", ep);
-            bufp_free(dev, intp, ep);
-            p->status = USB_RET_BABBLE;
-            return;
+            len = p->iov.size;
+            status = usb_redir_babble;
         }
         usb_packet_copy(p, intp->data, len);
         bufp_free(dev, intp, ep);
+        usbredir_handle_status(dev, p, status);
     } else {
         /* Output interrupt endpoint, normal async operation */
         struct usb_redir_interrupt_packet_header interrupt_packet;
@@ -1542,16 +1530,15 @@ static void usbredir_control_packet(void *priv, uint64_t id,
     p = usbredir_find_packet_by_id(dev, 0, id);
     if (p) {
         usbredir_handle_status(dev, p, control_packet->status);
-        if (p->status == USB_RET_SUCCESS) {
+        if (data_len > 0) {
             usbredir_log_data(dev, "ctrl data in:", data, data_len);
-            if (data_len <= sizeof(dev->dev.data_buf)) {
-                memcpy(dev->dev.data_buf, data, data_len);
-            } else {
+            if (data_len > sizeof(dev->dev.data_buf)) {
                 ERROR("ctrl buffer too small (%d > %zu)\n",
                       data_len, sizeof(dev->dev.data_buf));
                 p->status = USB_RET_STALL;
-                len = 0;
+                data_len = len = sizeof(dev->dev.data_buf);
             }
+            memcpy(dev->dev.data_buf, data, data_len);
         }
         p->actual_length = len;
         usb_generic_async_ctrl_complete(&dev->dev, p);
@@ -1575,20 +1562,19 @@ static void usbredir_bulk_packet(void *priv, uint64_t id,
     if (p) {
         size_t size = (p->combined) ? p->combined->iov.size : p->iov.size;
         usbredir_handle_status(dev, p, bulk_packet->status);
-        if (p->status == USB_RET_SUCCESS) {
+        if (data_len > 0) {
             usbredir_log_data(dev, "bulk data in:", data, data_len);
-            if (data_len <= size) {
-                if (p->combined) {
-                    iov_from_buf(p->combined->iov.iov, p->combined->iov.niov,
-                                 0, data, data_len);
-                } else {
-                    usb_packet_copy(p, data, data_len);
-                }
-            } else {
+            if (data_len > size) {
                 ERROR("bulk got more data then requested (%d > %zd)\n",
                       data_len, p->iov.size);
                 p->status = USB_RET_BABBLE;
-                len = 0;
+                data_len = len = size;
+            }
+            if (p->combined) {
+                iov_from_buf(p->combined->iov.iov, p->combined->iov.niov,
+                             0, data, data_len);
+            } else {
+                usb_packet_copy(p, data, data_len);
             }
         }
         p->actual_length = len;
@@ -1653,12 +1639,10 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id,
         /* bufp_alloc also adds the packet to the ep queue */
         bufp_alloc(dev, data, data_len, interrupt_packet->status, ep);
     } else {
-        int len = interrupt_packet->length;
-
         USBPacket *p = usbredir_find_packet_by_id(dev, ep, id);
         if (p) {
             usbredir_handle_status(dev, p, interrupt_packet->status);
-            p->actual_length = len;
+            p->actual_length = interrupt_packet->length;
             usb_packet_complete(&dev->dev, p);
         }
     }

From 01e26b0ea3c289efc58d31e28408e42c3fcded22 Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Thu, 1 Nov 2012 17:15:03 +0100
Subject: [PATCH 1549/2270] ehci: Get rid of the magical PROC_ERR status

Instead make ehci_execute and ehci_fill_queue return the again value.

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-ehci.c | 55 +++++++++++++++++++++--------------------------
 1 file changed, 24 insertions(+), 31 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 3a1f5134ea..73be5757f8 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -29,9 +29,6 @@
 
 #include "hw/usb/hcd-ehci.h"
 
-/* internal processing - reset HC to try and recover */
-#define USB_RET_PROCERR   (-99)
-
 /* Capability Registers Base Address - section 2.2 */
 #define CAPLENGTH        0x0000  /* 1-byte, 0x0001 reserved */
 #define HCIVERSION       0x0002  /* 2-bytes, i/f version # */
@@ -1111,7 +1108,7 @@ static int ehci_init_transfer(EHCIPacket *p)
     while (bytes > 0) {
         if (cpage > 4) {
             fprintf(stderr, "cpage out of range (%d)\n", cpage);
-            return USB_RET_PROCERR;
+            return -1;
         }
 
         page  = p->qtd.bufptr[cpage] & QTD_BUFPTR_MASK;
@@ -1248,8 +1245,7 @@ static void ehci_execute_complete(EHCIQueue *q)
     }
 }
 
-// 4.10.3
-
+/* 4.10.3 returns "again" */
 static int ehci_execute(EHCIPacket *p, const char *action)
 {
     USBEndpoint *ep;
@@ -1261,13 +1257,13 @@ static int ehci_execute(EHCIPacket *p, const char *action)
 
     if (!(p->qtd.token & QTD_TOKEN_ACTIVE)) {
         fprintf(stderr, "Attempting to execute inactive qtd\n");
-        return USB_RET_PROCERR;
+        return -1;
     }
 
     if (get_field(p->qtd.token, QTD_TOKEN_TBYTES) > BUFF_SIZE) {
         ehci_trace_guest_bug(p->queue->ehci,
                              "guest requested more bytes than allowed");
-        return USB_RET_PROCERR;
+        return -1;
     }
 
     p->pid = (p->qtd.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH;
@@ -1291,7 +1287,7 @@ static int ehci_execute(EHCIPacket *p, const char *action)
 
     if (p->async == EHCI_ASYNC_NONE) {
         if (ehci_init_transfer(p) != 0) {
-            return USB_RET_PROCERR;
+            return -1;
         }
 
         spd = (p->pid == USB_TOKEN_IN && NLPTR_TBIT(p->qtd.altnext) == 0);
@@ -1310,14 +1306,10 @@ static int ehci_execute(EHCIPacket *p, const char *action)
 
     if (p->packet.actual_length > BUFF_SIZE) {
         fprintf(stderr, "ret from usb_handle_packet > BUFF_SIZE\n");
-        return USB_RET_PROCERR;
+        return -1;
     }
 
-    if (p->packet.status == USB_RET_SUCCESS) {
-        return p->packet.actual_length;
-    } else {
-        return p->packet.status;
-    }
+    return 1;
 }
 
 /*  4.7.2
@@ -1352,7 +1344,7 @@ static int ehci_process_itd(EHCIState *ehci,
             }
 
             if (len > BUFF_SIZE) {
-                return USB_RET_PROCERR;
+                return -1;
             }
 
             qemu_sglist_init(&ehci->isgl, 2, ehci->dma);
@@ -1752,8 +1744,7 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
             break;
         case EHCI_ASYNC_INFLIGHT:
             /* Check if the guest has added new tds to the queue */
-            again = (ehci_fill_queue(QTAILQ_LAST(&q->packets, pkts_head)) ==
-                     USB_RET_PROCERR) ? -1 : 1;
+            again = ehci_fill_queue(QTAILQ_LAST(&q->packets, pkts_head));
             /* Unfinished async handled packet, go horizontal */
             ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
             break;
@@ -1790,6 +1781,7 @@ static int ehci_state_horizqh(EHCIQueue *q)
     return again;
 }
 
+/* Returns "again" */
 static int ehci_fill_queue(EHCIPacket *p)
 {
     USBEndpoint *ep = p->packet.ep;
@@ -1818,17 +1810,14 @@ static int ehci_fill_queue(EHCIPacket *p)
         p = ehci_alloc_packet(q);
         p->qtdaddr = qtdaddr;
         p->qtd = qtd;
-        p->usb_status = ehci_execute(p, "queue");
-        if (p->usb_status == USB_RET_PROCERR) {
-            break;
+        if (ehci_execute(p, "queue") == -1) {
+            return -1;
         }
-        assert(p->usb_status == USB_RET_ASYNC);
+        assert(p->packet.status == USB_RET_ASYNC);
         p->async = EHCI_ASYNC_INFLIGHT;
     }
-    if (p->usb_status != USB_RET_PROCERR) {
-        usb_device_flush_ep_queue(ep->dev, ep);
-    }
-    return p->usb_status;
+    usb_device_flush_ep_queue(ep->dev, ep);
+    return 1;
 }
 
 static int ehci_state_execute(EHCIQueue *q)
@@ -1857,23 +1846,27 @@ static int ehci_state_execute(EHCIQueue *q)
         ehci_set_usbsts(q->ehci, USBSTS_REC);
     }
 
-    p->usb_status = ehci_execute(p, "process");
-    if (p->usb_status == USB_RET_PROCERR) {
-        again = -1;
+    again = ehci_execute(p, "process");
+    if (again == -1) {
         goto out;
     }
-    if (p->usb_status == USB_RET_ASYNC) {
+    if (p->packet.status == USB_RET_ASYNC) {
         ehci_flush_qh(q);
         trace_usb_ehci_packet_action(p->queue, p, "async");
         p->async = EHCI_ASYNC_INFLIGHT;
         ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
         if (q->async) {
-            again = (ehci_fill_queue(p) == USB_RET_PROCERR) ? -1 : 1;
+            again = ehci_fill_queue(p);
         } else {
             again = 1;
         }
         goto out;
     }
+    if (p->packet.status == USB_RET_SUCCESS) {
+        p->usb_status = p->packet.actual_length;
+    } else {
+        p->usb_status = p->packet.status;
+    }
 
     ehci_set_state(q->ehci, q->async, EST_EXECUTING);
     again = 1;

From e696b1da42cd80787d45f6e9a6329d9ef3c8acb2 Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Thu, 1 Nov 2012 17:15:04 +0100
Subject: [PATCH 1550/2270] ehci: Add support for packets with both data and an
 error status

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-ehci.c | 161 ++++++++++++++++++++++------------------------
 hw/usb/hcd-ehci.h |   1 -
 2 files changed, 77 insertions(+), 85 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 73be5757f8..ee6c9ae302 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1126,16 +1126,16 @@ static int ehci_init_transfer(EHCIPacket *p)
     return 0;
 }
 
-static void ehci_finish_transfer(EHCIQueue *q, int status)
+static void ehci_finish_transfer(EHCIQueue *q, int len)
 {
     uint32_t cpage, offset;
 
-    if (status > 0) {
+    if (len > 0) {
         /* update cpage & offset */
         cpage  = get_field(q->qh.token, QTD_TOKEN_CPAGE);
         offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK;
 
-        offset += status;
+        offset += len;
         cpage  += offset >> QTD_BUFPTR_SH;
         offset &= ~QTD_BUFPTR_MASK;
 
@@ -1168,7 +1168,6 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
 
     trace_usb_ehci_packet_action(p->queue, p, "wakeup");
     p->async = EHCI_ASYNC_FINISHED;
-    p->usb_status = packet->status ? packet->status : packet->actual_length;
 
     if (p->queue->async) {
         qemu_bh_schedule(p->queue->ehci->async_bh);
@@ -1178,58 +1177,60 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
 static void ehci_execute_complete(EHCIQueue *q)
 {
     EHCIPacket *p = QTAILQ_FIRST(&q->packets);
+    uint32_t tbytes;
 
     assert(p != NULL);
     assert(p->qtdaddr == q->qtdaddr);
     assert(p->async == EHCI_ASYNC_INITIALIZED ||
            p->async == EHCI_ASYNC_FINISHED);
 
-    DPRINTF("execute_complete: qhaddr 0x%x, next %x, qtdaddr 0x%x, status %d\n",
-            q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status);
+    DPRINTF("execute_complete: qhaddr 0x%x, next 0x%x, qtdaddr 0x%x, "
+            "status %d, actual_length %d\n",
+            q->qhaddr, q->qh.next, q->qtdaddr,
+            p->packet.status, p->packet.actual_length);
 
-    if (p->usb_status < 0) {
-        switch (p->usb_status) {
-        case USB_RET_IOERROR:
-        case USB_RET_NODEV:
-            q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
-            set_field(&q->qh.token, 0, QTD_TOKEN_CERR);
-            ehci_raise_irq(q->ehci, USBSTS_ERRINT);
-            break;
-        case USB_RET_STALL:
-            q->qh.token |= QTD_TOKEN_HALT;
-            ehci_raise_irq(q->ehci, USBSTS_ERRINT);
-            break;
-        case USB_RET_NAK:
-            set_field(&q->qh.altnext_qtd, 0, QH_ALTNEXT_NAKCNT);
-            return; /* We're not done yet with this transaction */
-        case USB_RET_BABBLE:
-            q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
-            ehci_raise_irq(q->ehci, USBSTS_ERRINT);
-            break;
-        default:
-            /* should not be triggerable */
-            fprintf(stderr, "USB invalid response %d\n", p->usb_status);
-            assert(0);
-            break;
+    switch (p->packet.status) {
+    case USB_RET_SUCCESS:
+        break;
+    case USB_RET_IOERROR:
+    case USB_RET_NODEV:
+        q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
+        set_field(&q->qh.token, 0, QTD_TOKEN_CERR);
+        ehci_raise_irq(q->ehci, USBSTS_ERRINT);
+        break;
+    case USB_RET_STALL:
+        q->qh.token |= QTD_TOKEN_HALT;
+        ehci_raise_irq(q->ehci, USBSTS_ERRINT);
+        break;
+    case USB_RET_NAK:
+        set_field(&q->qh.altnext_qtd, 0, QH_ALTNEXT_NAKCNT);
+        return; /* We're not done yet with this transaction */
+    case USB_RET_BABBLE:
+        q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
+        ehci_raise_irq(q->ehci, USBSTS_ERRINT);
+        break;
+    default:
+        /* should not be triggerable */
+        fprintf(stderr, "USB invalid response %d\n", p->packet.status);
+        assert(0);
+        break;
+    }
+
+    /* TODO check 4.12 for splits */
+    tbytes = get_field(q->qh.token, QTD_TOKEN_TBYTES);
+    if (tbytes && p->pid == USB_TOKEN_IN) {
+        tbytes -= p->packet.actual_length;
+        if (tbytes) {
+            /* 4.15.1.2 must raise int on a short input packet */
+            ehci_raise_irq(q->ehci, USBSTS_INT);
         }
     } else {
-        // TODO check 4.12 for splits
-        uint32_t tbytes = get_field(q->qh.token, QTD_TOKEN_TBYTES);
-
-        if (tbytes && p->pid == USB_TOKEN_IN) {
-            tbytes -= p->usb_status;
-            if (tbytes) {
-                /* 4.15.1.2 must raise int on a short input packet */
-                ehci_raise_irq(q->ehci, USBSTS_INT);
-            }
-        } else {
-            tbytes = 0;
-        }
-
-        DPRINTF("updating tbytes to %d\n", tbytes);
-        set_field(&q->qh.token, tbytes, QTD_TOKEN_TBYTES);
+        tbytes = 0;
     }
-    ehci_finish_transfer(q, p->usb_status);
+    DPRINTF("updating tbytes to %d\n", tbytes);
+    set_field(&q->qh.token, tbytes, QTD_TOKEN_TBYTES);
+
+    ehci_finish_transfer(q, p->packet.actual_length);
     usb_packet_unmap(&p->packet, &p->sgl);
     qemu_sglist_destroy(&p->sgl);
     p->async = EHCI_ASYNC_NONE;
@@ -1321,7 +1322,6 @@ static int ehci_process_itd(EHCIState *ehci,
 {
     USBDevice *dev;
     USBEndpoint *ep;
-    int ret;
     uint32_t i, len, pid, dir, devaddr, endp;
     uint32_t pg, off, ptr1, ptr2, max, mult;
 
@@ -1368,45 +1368,43 @@ static int ehci_process_itd(EHCIState *ehci,
                 usb_packet_map(&ehci->ipacket, &ehci->isgl);
                 usb_handle_packet(dev, &ehci->ipacket);
                 usb_packet_unmap(&ehci->ipacket, &ehci->isgl);
-                ret = (ehci->ipacket.status == USB_RET_SUCCESS) ?
-                      ehci->ipacket.actual_length : ehci->ipacket.status;
             } else {
                 DPRINTF("ISOCH: attempt to addess non-iso endpoint\n");
-                ret = USB_RET_NAK;
+                ehci->ipacket.status = USB_RET_NAK;
+                ehci->ipacket.actual_length = 0;
             }
             qemu_sglist_destroy(&ehci->isgl);
 
-            if (ret < 0) {
-                switch (ret) {
-                default:
-                    fprintf(stderr, "Unexpected iso usb result: %d\n", ret);
-                    /* Fall through */
-                case USB_RET_IOERROR:
-                case USB_RET_NODEV:
-                    /* 3.3.2: XACTERR is only allowed on IN transactions */
-                    if (dir) {
-                        itd->transact[i] |= ITD_XACT_XACTERR;
-                        ehci_raise_irq(ehci, USBSTS_ERRINT);
-                    }
-                    break;
-                case USB_RET_BABBLE:
-                    itd->transact[i] |= ITD_XACT_BABBLE;
+            switch (ehci->ipacket.status) {
+            case USB_RET_SUCCESS:
+                break;
+            default:
+                fprintf(stderr, "Unexpected iso usb result: %d\n",
+                        ehci->ipacket.status);
+                /* Fall through */
+            case USB_RET_IOERROR:
+            case USB_RET_NODEV:
+                /* 3.3.2: XACTERR is only allowed on IN transactions */
+                if (dir) {
+                    itd->transact[i] |= ITD_XACT_XACTERR;
                     ehci_raise_irq(ehci, USBSTS_ERRINT);
-                    break;
-                case USB_RET_NAK:
-                    /* no data for us, so do a zero-length transfer */
-                    ret = 0;
-                    break;
                 }
+                break;
+            case USB_RET_BABBLE:
+                itd->transact[i] |= ITD_XACT_BABBLE;
+                ehci_raise_irq(ehci, USBSTS_ERRINT);
+                break;
+            case USB_RET_NAK:
+                /* no data for us, so do a zero-length transfer */
+                ehci->ipacket.actual_length = 0;
+                break;
             }
-            if (ret >= 0) {
-                if (!dir) {
-                    /* OUT */
-                    set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH);
-                } else {
-                    /* IN */
-                    set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
-                }
+            if (!dir) {
+                set_field(&itd->transact[i], len - ehci->ipacket.actual_length,
+                          ITD_XACT_LENGTH); /* OUT */
+            } else {
+                set_field(&itd->transact[i], ehci->ipacket.actual_length,
+                          ITD_XACT_LENGTH); /* IN */
             }
             if (itd->transact[i] & ITD_XACT_IOC) {
                 ehci_raise_irq(ehci, USBSTS_INT);
@@ -1862,11 +1860,6 @@ static int ehci_state_execute(EHCIQueue *q)
         }
         goto out;
     }
-    if (p->packet.status == USB_RET_SUCCESS) {
-        p->usb_status = p->packet.actual_length;
-    } else {
-        p->usb_status = p->packet.status;
-    }
 
     ehci_set_state(q->ehci, q->async, EST_EXECUTING);
     again = 1;
@@ -1890,7 +1883,7 @@ static int ehci_state_executing(EHCIQueue *q)
     }
 
     /* 4.10.5 */
-    if (p->usb_status == USB_RET_NAK) {
+    if (p->packet.status == USB_RET_NAK) {
         ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
     } else {
         ehci_set_state(q->ehci, q->async, EST_WRITEBACK);
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index 0ec675c352..d8078f4555 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -230,7 +230,6 @@ struct EHCIPacket {
     QEMUSGList sgl;
     int pid;
     enum async_state async;
-    int usb_status;
 };
 
 struct EHCIQueue {

From 9b8251c5c44a70a63c642e4e345fa8c12ed022ed Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Thu, 1 Nov 2012 17:15:05 +0100
Subject: [PATCH 1551/2270] xhci: Add support for packets with both data and an
 error status

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-xhci.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index d4a2e0c3ec..a181d45910 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1388,7 +1388,7 @@ static void xhci_xfer_report(XHCITransfer *xfer)
     XHCIState *xhci = xfer->xhci;
     int i;
 
-    left = xfer->packet.status ? 0 : xfer->packet.actual_length;
+    left = xfer->packet.actual_length;
 
     for (i = 0; i < xfer->trb_count; i++) {
         XHCITRB *trb = &xfer->trbs[i];
@@ -1416,7 +1416,7 @@ static void xhci_xfer_report(XHCITransfer *xfer)
 
         if (!reported && ((trb->control & TRB_TR_IOC) ||
                           (shortpkt && (trb->control & TRB_TR_ISP)) ||
-                          (xfer->status != CC_SUCCESS))) {
+                          (xfer->status != CC_SUCCESS && left == 0))) {
             event.slotid = xfer->slotid;
             event.epid = xfer->epid;
             event.length = (trb->status & 0x1ffff) - chunk;

From ffd8a97fb33d3b036d61c508bd73ee7fa4051c6b Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Thu, 1 Nov 2012 17:15:06 +0100
Subject: [PATCH 1552/2270] usb/combined-packet: Move freeing of combined to
 usb_combined_packet_remove()

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/combined-packet.c | 33 +++++++++++++++------------------
 1 file changed, 15 insertions(+), 18 deletions(-)

diff --git a/hw/usb/combined-packet.c b/hw/usb/combined-packet.c
index e72219894b..4a0c299457 100644
--- a/hw/usb/combined-packet.c
+++ b/hw/usb/combined-packet.c
@@ -31,12 +31,16 @@ static void usb_combined_packet_add(USBCombinedPacket *combined, USBPacket *p)
     p->combined = combined;
 }
 
+/* Note will free combined when the last packet gets removed */
 static void usb_combined_packet_remove(USBCombinedPacket *combined,
                                        USBPacket *p)
 {
     assert(p->combined == combined);
     p->combined = NULL;
     QTAILQ_REMOVE(&combined->packets, p, combined_entry);
+    if (QTAILQ_EMPTY(&combined->packets)) {
+        g_free(combined);
+    }
 }
 
 /* Also handles completion of non combined packets for pipelined input eps */
@@ -45,9 +49,8 @@ void usb_combined_input_packet_complete(USBDevice *dev, USBPacket *p)
     USBCombinedPacket *combined = p->combined;
     USBEndpoint *ep = p->ep;
     USBPacket *next;
-    enum { completing, complete, leftover };
-    int status, actual_length, state = completing;
-    bool short_not_ok;
+    int status, actual_length;
+    bool short_not_ok, done = false;
 
     if (combined == NULL) {
         usb_packet_complete_one(dev, p);
@@ -61,39 +64,34 @@ void usb_combined_input_packet_complete(USBDevice *dev, USBPacket *p)
     short_not_ok = QTAILQ_LAST(&combined->packets, packets_head)->short_not_ok;
 
     QTAILQ_FOREACH_SAFE(p, &combined->packets, combined_entry, next) {
-        if (state == completing) {
+        if (!done) {
             /* Distribute data over uncombined packets */
             if (actual_length >= p->iov.size) {
                 p->actual_length = p->iov.size;
             } else {
                 /* Send short or error packet to complete the transfer */
                 p->actual_length = actual_length;
-                state = complete;
+                done = true;
             }
             /* Report status on the last packet */
-            if (state == complete || next == NULL) {
+            if (done || next == NULL) {
                 p->status = status;
             } else {
                 p->status = USB_RET_SUCCESS;
             }
             p->short_not_ok = short_not_ok;
+            /* Note will free combined when the last packet gets removed! */
             usb_combined_packet_remove(combined, p);
             usb_packet_complete_one(dev, p);
             actual_length -= p->actual_length;
         } else {
             /* Remove any leftover packets from the queue */
-            state = leftover;
             p->status = USB_RET_REMOVE_FROM_QUEUE;
+            /* Note will free combined on the last packet! */
             dev->port->ops->complete(dev->port, p);
         }
     }
-    /*
-     * If we had leftover packets the hcd driver will have cancelled them
-     * and usb_combined_packet_cancel has already freed combined!
-     */
-    if (state != leftover) {
-        g_free(combined);
-    }
+    /* Do not use combined here, it has been freed! */
 leave:
     /* Check if there are packets in the queue waiting for our completion */
     usb_ep_combine_input_packets(ep);
@@ -104,14 +102,13 @@ void usb_combined_packet_cancel(USBDevice *dev, USBPacket *p)
 {
     USBCombinedPacket *combined = p->combined;
     assert(combined != NULL);
+    USBPacket *first = p->combined->first;
 
+    /* Note will free combined on the last packet! */
     usb_combined_packet_remove(combined, p);
-    if (p == combined->first) {
+    if (p == first) {
         usb_device_cancel_packet(dev, p);
     }
-    if (QTAILQ_EMPTY(&combined->packets)) {
-        g_free(combined);
-    }
 }
 
 /*

From 616b5d53ae81a94a4aabe8a87a5d950e9d349bc5 Mon Sep 17 00:00:00 2001
From: David Gibson 
Date: Mon, 5 Nov 2012 14:29:01 +1100
Subject: [PATCH 1553/2270] xhci: Fix some DMA host endian bugs

The xhci device does correct endian switches on the results of some DMAs
but not all.  In particular, there are many DMAs of what are essentially
arrays of 32-bit integers which never get byteswapped.  This causes them
to be interpreted incorrectly on big-endian hosts, since (as per the xhci
spec) these arrays are always little-endian in guest memory.

This patch adds some helper functions to fix these bugs.  This may not be
all the endian bugs in the xhci code, but it's certainly some of them and
the Linux guest xhci driver certainly gets further with these fixes.

Signed-off-by: David Gibson 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-xhci.c | 81 +++++++++++++++++++++++++++++++----------------
 1 file changed, 54 insertions(+), 27 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index a181d45910..8ef4b0730e 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -634,6 +634,34 @@ static inline dma_addr_t xhci_mask64(uint64_t addr)
     }
 }
 
+static inline void xhci_dma_read_u32s(XHCIState *xhci, dma_addr_t addr,
+                                      uint32_t *buf, size_t len)
+{
+    int i;
+
+    assert((len % sizeof(uint32_t)) == 0);
+
+    pci_dma_read(&xhci->pci_dev, addr, buf, len);
+
+    for (i = 0; i < (len / sizeof(uint32_t)); i++) {
+        buf[i] = le32_to_cpu(buf[i]);
+    }
+}
+
+static inline void xhci_dma_write_u32s(XHCIState *xhci, dma_addr_t addr,
+                                       uint32_t *buf, size_t len)
+{
+    int i;
+    uint32_t tmp[len / sizeof(uint32_t)];
+
+    assert((len % sizeof(uint32_t)) == 0);
+
+    for (i = 0; i < (len / sizeof(uint32_t)); i++) {
+        tmp[i] = cpu_to_le32(buf[i]);
+    }
+    pci_dma_write(&xhci->pci_dev, addr, tmp, len);
+}
+
 static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport)
 {
     int index;
@@ -1045,14 +1073,14 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
 {
     uint32_t ctx[5];
 
-    pci_dma_read(&xhci->pci_dev, epctx->pctx, ctx, sizeof(ctx));
+    xhci_dma_read_u32s(xhci, epctx->pctx, ctx, sizeof(ctx));
     ctx[0] &= ~EP_STATE_MASK;
     ctx[0] |= state;
     ctx[2] = epctx->ring.dequeue | epctx->ring.ccs;
     ctx[3] = (epctx->ring.dequeue >> 16) >> 16;
     DPRINTF("xhci: set epctx: " DMA_ADDR_FMT " state=%d dequeue=%08x%08x\n",
             epctx->pctx, state, ctx[3], ctx[2]);
-    pci_dma_write(&xhci->pci_dev, epctx->pctx, ctx, sizeof(ctx));
+    xhci_dma_write_u32s(xhci, epctx->pctx, ctx, sizeof(ctx));
     epctx->state = state;
 }
 
@@ -1881,14 +1909,14 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
     assert(slotid >= 1 && slotid <= xhci->numslots);
 
     dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high);
-    pci_dma_read(&xhci->pci_dev, dcbaap + 8*slotid, &poctx, sizeof(poctx));
+    poctx = ldq_le_pci_dma(&xhci->pci_dev, dcbaap + 8*slotid);
     ictx = xhci_mask64(pictx);
-    octx = xhci_mask64(le64_to_cpu(poctx));
+    octx = xhci_mask64(poctx);
 
     DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx);
     DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx);
 
-    pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx));
+    xhci_dma_read_u32s(xhci, ictx, ictl_ctx, sizeof(ictl_ctx));
 
     if (ictl_ctx[0] != 0x0 || ictl_ctx[1] != 0x3) {
         fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
@@ -1896,8 +1924,8 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
         return CC_TRB_ERROR;
     }
 
-    pci_dma_read(&xhci->pci_dev, ictx+32, slot_ctx, sizeof(slot_ctx));
-    pci_dma_read(&xhci->pci_dev, ictx+64, ep0_ctx, sizeof(ep0_ctx));
+    xhci_dma_read_u32s(xhci, ictx+32, slot_ctx, sizeof(slot_ctx));
+    xhci_dma_read_u32s(xhci, ictx+64, ep0_ctx, sizeof(ep0_ctx));
 
     DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n",
             slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
@@ -1951,8 +1979,8 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
     DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n",
             ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
 
-    pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
-    pci_dma_write(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx));
+    xhci_dma_write_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
+    xhci_dma_write_u32s(xhci, octx+32, ep0_ctx, sizeof(ep0_ctx));
 
     return res;
 }
@@ -1985,17 +2013,17 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
             }
         }
 
-        pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
+        xhci_dma_read_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
         slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
         slot_ctx[3] |= SLOT_ADDRESSED << SLOT_STATE_SHIFT;
         DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
                 slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
-        pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
+        xhci_dma_write_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
 
         return CC_SUCCESS;
     }
 
-    pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx));
+    xhci_dma_read_u32s(xhci, ictx, ictl_ctx, sizeof(ictl_ctx));
 
     if ((ictl_ctx[0] & 0x3) != 0x0 || (ictl_ctx[1] & 0x3) != 0x1) {
         fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
@@ -2003,8 +2031,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
         return CC_TRB_ERROR;
     }
 
-    pci_dma_read(&xhci->pci_dev, ictx+32, islot_ctx, sizeof(islot_ctx));
-    pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
+    xhci_dma_read_u32s(xhci, ictx+32, islot_ctx, sizeof(islot_ctx));
+    xhci_dma_read_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
 
     if (SLOT_STATE(slot_ctx[3]) < SLOT_ADDRESSED) {
         fprintf(stderr, "xhci: invalid slot state %08x\n", slot_ctx[3]);
@@ -2016,8 +2044,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
             xhci_disable_ep(xhci, slotid, i);
         }
         if (ictl_ctx[1] & (1<pci_dev, ictx+32+(32*i), ep_ctx,
-                         sizeof(ep_ctx));
+            xhci_dma_read_u32s(xhci, ictx+32+(32*i), ep_ctx, sizeof(ep_ctx));
             DPRINTF("xhci: input ep%d.%d context: %08x %08x %08x %08x %08x\n",
                     i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2],
                     ep_ctx[3], ep_ctx[4]);
@@ -2029,7 +2056,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
             DPRINTF("xhci: output ep%d.%d context: %08x %08x %08x %08x %08x\n",
                     i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2],
                     ep_ctx[3], ep_ctx[4]);
-            pci_dma_write(&xhci->pci_dev, octx+(32*i), ep_ctx, sizeof(ep_ctx));
+            xhci_dma_write_u32s(xhci, octx+(32*i), ep_ctx, sizeof(ep_ctx));
         }
     }
 
@@ -2041,7 +2068,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
     DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
             slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
 
-    pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
+    xhci_dma_write_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
 
     return CC_SUCCESS;
 }
@@ -2066,7 +2093,7 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
     DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx);
     DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx);
 
-    pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx));
+    xhci_dma_read_u32s(xhci, ictx, ictl_ctx, sizeof(ictl_ctx));
 
     if (ictl_ctx[0] != 0x0 || ictl_ctx[1] & ~0x3) {
         fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
@@ -2075,12 +2102,12 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
     }
 
     if (ictl_ctx[1] & 0x1) {
-        pci_dma_read(&xhci->pci_dev, ictx+32, islot_ctx, sizeof(islot_ctx));
+        xhci_dma_read_u32s(xhci, ictx+32, islot_ctx, sizeof(islot_ctx));
 
         DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n",
                 islot_ctx[0], islot_ctx[1], islot_ctx[2], islot_ctx[3]);
 
-        pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
+        xhci_dma_read_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
 
         slot_ctx[1] &= ~0xFFFF; /* max exit latency */
         slot_ctx[1] |= islot_ctx[1] & 0xFFFF;
@@ -2090,17 +2117,17 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
         DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
                 slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
 
-        pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
+        xhci_dma_write_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
     }
 
     if (ictl_ctx[1] & 0x2) {
-        pci_dma_read(&xhci->pci_dev, ictx+64, iep0_ctx, sizeof(iep0_ctx));
+        xhci_dma_read_u32s(xhci, ictx+64, iep0_ctx, sizeof(iep0_ctx));
 
         DPRINTF("xhci: input ep0 context: %08x %08x %08x %08x %08x\n",
                 iep0_ctx[0], iep0_ctx[1], iep0_ctx[2],
                 iep0_ctx[3], iep0_ctx[4]);
 
-        pci_dma_read(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx));
+        xhci_dma_read_u32s(xhci, octx+32, ep0_ctx, sizeof(ep0_ctx));
 
         ep0_ctx[1] &= ~0xFFFF0000; /* max packet size*/
         ep0_ctx[1] |= iep0_ctx[1] & 0xFFFF0000;
@@ -2108,7 +2135,7 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
         DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n",
                 ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
 
-        pci_dma_write(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx));
+        xhci_dma_write_u32s(xhci, octx+32, ep0_ctx, sizeof(ep0_ctx));
     }
 
     return CC_SUCCESS;
@@ -2133,12 +2160,12 @@ static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid)
         }
     }
 
-    pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
+    xhci_dma_read_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
     slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
     slot_ctx[3] |= SLOT_DEFAULT << SLOT_STATE_SHIFT;
     DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
             slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
-    pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
+    xhci_dma_write_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
 
     return CC_SUCCESS;
 }

From 9d1530470bba5d8bec4796c0b43b874d5f9ef017 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Thu, 8 Nov 2012 10:14:46 +0100
Subject: [PATCH 1554/2270] ehci: fix migration

Commit 5010d4dc618b6b8e7c21129c487c06f6493f71fc reorganized vmstate to
split core + pci, but got two little details wrong.  Fix them.

Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-ehci-pci.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c
index d5c7d462d0..fe45a1fbba 100644
--- a/hw/usb/hcd-ehci-pci.c
+++ b/hw/usb/hcd-ehci-pci.c
@@ -91,6 +91,7 @@ static const VMStateDescription vmstate_ehci_pci = {
     .fields      = (VMStateField[]) {
         VMSTATE_PCI_DEVICE(pcidev, EHCIPCIState),
         VMSTATE_STRUCT(ehci, EHCIPCIState, 2, vmstate_ehci, EHCIState),
+        VMSTATE_END_OF_LIST()
     }
 };
 
@@ -105,7 +106,7 @@ static void ehci_class_init(ObjectClass *klass, void *data)
     k->device_id = i->device_id;
     k->revision = i->revision;
     k->class_id = PCI_CLASS_SERIAL_USB;
-    dc->vmsd = &vmstate_ehci;
+    dc->vmsd = &vmstate_ehci_pci;
     dc->props = ehci_pci_properties;
 }
 

From 5c61afec86e5b2597b19b4657edc404fd76e6eb9 Mon Sep 17 00:00:00 2001
From: Jan Kiszka 
Date: Sun, 4 Nov 2012 09:16:55 +0100
Subject: [PATCH 1555/2270] kvmvapic: Fix TB invalidation after instruction
 patching
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Since 0b57e287, cpu_memory_rw_debug already triggers a TB invalidation.
As it doesn't (and cannot) set is_cpu_write_access=1 but "consumes" the
currently executed TB, the tb_invalidate_phys_page_range call from
patch_instruction didn't work anymore.

Fix this by open-coding the required bits to restore the CPU state from
the current TB position before patching and resume execution on the
patched instruction afterward.

Signed-off-by: Jan Kiszka 
Tested-by: Hervé Poussineau 
Signed-off-by: Blue Swirl 
---
 hw/kvmvapic.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/hw/kvmvapic.c b/hw/kvmvapic.c
index dc111ee8e6..e04c4011d7 100644
--- a/hw/kvmvapic.c
+++ b/hw/kvmvapic.c
@@ -384,10 +384,13 @@ static void patch_call(VAPICROMState *s, CPUX86State *env, target_ulong ip,
 
 static void patch_instruction(VAPICROMState *s, CPUX86State *env, target_ulong ip)
 {
-    hwaddr paddr;
     VAPICHandlers *handlers;
     uint8_t opcode[2];
     uint32_t imm32;
+    TranslationBlock *current_tb;
+    target_ulong current_pc = 0;
+    target_ulong current_cs_base = 0;
+    int current_flags = 0;
 
     if (smp_cpus == 1) {
         handlers = &s->rom_state.up;
@@ -395,6 +398,13 @@ static void patch_instruction(VAPICROMState *s, CPUX86State *env, target_ulong i
         handlers = &s->rom_state.mp;
     }
 
+    if (!kvm_enabled()) {
+        current_tb = tb_find_pc(env->mem_io_pc);
+        cpu_restore_state(current_tb, env, env->mem_io_pc);
+        cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base,
+                             ¤t_flags);
+    }
+
     pause_all_vcpus();
 
     cpu_memory_rw_debug(env, ip, opcode, sizeof(opcode), 0);
@@ -430,9 +440,11 @@ static void patch_instruction(VAPICROMState *s, CPUX86State *env, target_ulong i
 
     resume_all_vcpus();
 
-    paddr = cpu_get_phys_page_debug(env, ip);
-    paddr += ip & ~TARGET_PAGE_MASK;
-    tb_invalidate_phys_page_range(paddr, paddr + 1, 1);
+    if (!kvm_enabled()) {
+        env->current_tb = NULL;
+        tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
+        cpu_resume_from_signal(env, NULL);
+    }
 }
 
 void vapic_report_tpr_access(DeviceState *dev, void *cpu, target_ulong ip,

From 1f202568e0553b416483e5993f1bde219c22cf72 Mon Sep 17 00:00:00 2001
From: BALATON Zoltan 
Date: Sun, 4 Nov 2012 18:41:59 +0100
Subject: [PATCH 1556/2270] vmware_vga: Add back some info in local state
 partially reverting aa32b38c

Keep saving display surface parameters at init and using these cached
values instead of getting them when needed. Not sure why this is
needed (maybe due to the interaction with the vga device) but not
doing this broke the Xorg vmware driver at least.

Signed-off-by: BALATON Zoltan 
Tested-by: Jan Kiszka 
Signed-off-by: Blue Swirl 
---
 hw/vmware_vga.c | 30 +++++++++++++++++++++---------
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 7c766fb3da..834588daf6 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -39,6 +39,8 @@ struct vmsvga_state_s {
     VGACommonState vga;
 
     int invalidated;
+    int depth;
+    int bypp;
     int enable;
     int config;
     struct {
@@ -55,6 +57,9 @@ struct vmsvga_state_s {
     int new_height;
     uint32_t guest;
     uint32_t svgaid;
+    uint32_t wred;
+    uint32_t wgreen;
+    uint32_t wblue;
     int syncing;
 
     MemoryRegion fifo_ram;
@@ -718,25 +723,25 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
         return SVGA_MAX_HEIGHT;
 
     case SVGA_REG_DEPTH:
-        return ds_get_depth(s->vga.ds);
+        return s->depth;
 
     case SVGA_REG_BITS_PER_PIXEL:
-        return ds_get_bits_per_pixel(s->vga.ds);
+        return (s->depth + 7) & ~7;
 
     case SVGA_REG_PSEUDOCOLOR:
         return 0x0;
 
     case SVGA_REG_RED_MASK:
-        return ds_get_rmask(s->vga.ds);
+        return s->wred;
 
     case SVGA_REG_GREEN_MASK:
-        return ds_get_gmask(s->vga.ds);
+        return s->wgreen;
 
     case SVGA_REG_BLUE_MASK:
-        return ds_get_bmask(s->vga.ds);
+        return s->wblue;
 
     case SVGA_REG_BYTES_PER_LINE:
-        return ds_get_bytes_per_pixel(s->vga.ds) * s->new_width;
+        return s->bypp * s->new_width;
 
     case SVGA_REG_FB_START: {
         struct pci_vmsvga_state_s *pci_vmsvga
@@ -801,7 +806,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
         return s->cursor.on;
 
     case SVGA_REG_HOST_BITS_PER_PIXEL:
-        return ds_get_bits_per_pixel(s->vga.ds);
+        return (s->depth + 7) & ~7;
 
     case SVGA_REG_SCRATCH_SIZE:
         return s->scratch_size;
@@ -864,7 +869,7 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value)
         break;
 
     case SVGA_REG_BITS_PER_PIXEL:
-        if (value != ds_get_bits_per_pixel(s->vga.ds)) {
+        if (value != s->depth) {
             printf("%s: Bad bits per pixel: %i bits\n", __func__, value);
             s->config = 0;
         }
@@ -1084,7 +1089,7 @@ static const VMStateDescription vmstate_vmware_vga_internal = {
     .minimum_version_id_old = 0,
     .post_load = vmsvga_post_load,
     .fields      = (VMStateField[]) {
-        VMSTATE_UNUSED(4), /* was depth */
+        VMSTATE_INT32_EQUAL(depth, struct vmsvga_state_s),
         VMSTATE_INT32(enable, struct vmsvga_state_s),
         VMSTATE_INT32(config, struct vmsvga_state_s),
         VMSTATE_INT32(cursor.id, struct vmsvga_state_s),
@@ -1137,6 +1142,13 @@ static void vmsvga_init(struct vmsvga_state_s *s,
     vga_common_init(&s->vga);
     vga_init(&s->vga, address_space, io, true);
     vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
+    /* Save some values here in case they are changed later.
+     * This is suspicious and needs more though why it is needed. */
+    s->depth = ds_get_bits_per_pixel(s->vga.ds);
+    s->bypp = ds_get_bytes_per_pixel(s->vga.ds);
+    s->wred = ds_get_rmask(s->vga.ds);
+    s->wgreen = ds_get_gmask(s->vga.ds);
+    s->wblue = ds_get_bmask(s->vga.ds);
 }
 
 static uint64_t vmsvga_io_read(void *opaque, hwaddr addr, unsigned size)

From 253ecf83bcc658316bab3250401943d9b44c7898 Mon Sep 17 00:00:00 2001
From: Stefan Weil 
Date: Sun, 4 Nov 2012 21:42:08 +0100
Subject: [PATCH 1557/2270] qemu-timer: Fix compilation for non-POSIX hosts

A compiler warning is caused by the unused local function reinit_timers
on non-POSIX hosts. Include that function only for POSIX hosts.

Signed-off-by: Stefan Weil 
Signed-off-by: Blue Swirl 
---
 qemu-timer.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/qemu-timer.c b/qemu-timer.c
index 8d9cf38bb2..0d2bb94289 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -745,6 +745,7 @@ static void quit_timers(void)
     t->stop(t);
 }
 
+#ifdef CONFIG_POSIX
 static void reinit_timers(void)
 {
     struct qemu_alarm_timer *t = alarm_timer;
@@ -755,6 +756,7 @@ static void reinit_timers(void)
     }
     qemu_rearm_alarm_timer(t);
 }
+#endif /* CONFIG_POSIX */
 
 int init_timer_alarm(void)
 {

From 22bde7145495ad78c4bed8bb76d9401ec8d107b2 Mon Sep 17 00:00:00 2001
From: Jan Kiszka 
Date: Mon, 5 Nov 2012 16:45:56 +0100
Subject: [PATCH 1558/2270] memory: Reintroduce dirty flag to optimize changes
 on disabled regions

Cirrus is triggering this, e.g. during Win2k boot: Changes only on
disabled regions require no topology update when transaction depth drops
to 0 again.

Signed-off-by: Jan Kiszka 
Signed-off-by: Blue Swirl 
---
 memory.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/memory.c b/memory.c
index 243cb23969..09e44b84ab 100644
--- a/memory.c
+++ b/memory.c
@@ -22,7 +22,8 @@
 
 #include "memory-internal.h"
 
-unsigned memory_region_transaction_depth = 0;
+static unsigned memory_region_transaction_depth;
+static bool memory_region_update_pending;
 static bool global_dirty_log = false;
 
 static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners
@@ -741,7 +742,8 @@ void memory_region_transaction_commit(void)
 
     assert(memory_region_transaction_depth);
     --memory_region_transaction_depth;
-    if (!memory_region_transaction_depth) {
+    if (!memory_region_transaction_depth && memory_region_update_pending) {
+        memory_region_update_pending = false;
         MEMORY_LISTENER_CALL_GLOBAL(begin, Forward);
 
         QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
@@ -1060,6 +1062,7 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
 
     memory_region_transaction_begin();
     mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask);
+    memory_region_update_pending |= mr->enabled;
     memory_region_transaction_commit();
 }
 
@@ -1097,6 +1100,7 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
     if (mr->readonly != readonly) {
         memory_region_transaction_begin();
         mr->readonly = readonly;
+        memory_region_update_pending |= mr->enabled;
         memory_region_transaction_commit();
     }
 }
@@ -1106,6 +1110,7 @@ void memory_region_rom_device_set_readable(MemoryRegion *mr, bool readable)
     if (mr->readable != readable) {
         memory_region_transaction_begin();
         mr->readable = readable;
+        memory_region_update_pending |= mr->enabled;
         memory_region_transaction_commit();
     }
 }
@@ -1248,6 +1253,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
     memmove(&mr->ioeventfds[i+1], &mr->ioeventfds[i],
             sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb-1 - i));
     mr->ioeventfds[i] = mrfd;
+    memory_region_update_pending |= mr->enabled;
     memory_region_transaction_commit();
 }
 
@@ -1280,6 +1286,7 @@ void memory_region_del_eventfd(MemoryRegion *mr,
     --mr->ioeventfd_nb;
     mr->ioeventfds = g_realloc(mr->ioeventfds,
                                   sizeof(*mr->ioeventfds)*mr->ioeventfd_nb + 1);
+    memory_region_update_pending |= mr->enabled;
     memory_region_transaction_commit();
 }
 
@@ -1323,6 +1330,7 @@ static void memory_region_add_subregion_common(MemoryRegion *mr,
     }
     QTAILQ_INSERT_TAIL(&mr->subregions, subregion, subregions_link);
 done:
+    memory_region_update_pending |= mr->enabled && subregion->enabled;
     memory_region_transaction_commit();
 }
 
@@ -1353,6 +1361,7 @@ void memory_region_del_subregion(MemoryRegion *mr,
     assert(subregion->parent == mr);
     subregion->parent = NULL;
     QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
+    memory_region_update_pending |= mr->enabled && subregion->enabled;
     memory_region_transaction_commit();
 }
 
@@ -1363,6 +1372,7 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled)
     }
     memory_region_transaction_begin();
     mr->enabled = enabled;
+    memory_region_update_pending = true;
     memory_region_transaction_commit();
 }
 
@@ -1397,6 +1407,7 @@ void memory_region_set_alias_offset(MemoryRegion *mr, hwaddr offset)
 
     memory_region_transaction_begin();
     mr->alias_offset = offset;
+    memory_region_update_pending |= mr->enabled;
     memory_region_transaction_commit();
 }
 

From 7ea692b24055022248b895f2203a6ab1ad54859b Mon Sep 17 00:00:00 2001
From: Jan Kiszka 
Date: Wed, 31 Oct 2012 10:49:02 +0100
Subject: [PATCH 1559/2270] memory: Don't dump disabled regions

This makes "info mtree" output readable again.

Signed-off-by: Jan Kiszka 
Signed-off-by: Blue Swirl 
---
 memory.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/memory.c b/memory.c
index 09e44b84ab..741985385c 100644
--- a/memory.c
+++ b/memory.c
@@ -1601,7 +1601,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
     const MemoryRegion *submr;
     unsigned int i;
 
-    if (!mr) {
+    if (!mr || !mr->enabled) {
         return;
     }
 

From a9523d14c47fbdecb319211afac00caa62d998a8 Mon Sep 17 00:00:00 2001
From: Catalin Patulea 
Date: Mon, 29 Oct 2012 03:45:51 -0400
Subject: [PATCH 1560/2270] tests/tcg: new test for i386 FPREM and FPREM1

This is setting the stage for a cleanup of FPREM and FPREM1 helpers while being
sure that they behave same as bare metal.

The test constructs operands using combinations of corner cases for the
floating-point bitfields and prints operands, result and FPU status word for
FPREM and FPREM1. The outputs can then be compared between bare metal and QEMU.
The 'run-test-i386-fprem' make target does just that.

Signed-off-by: Catalin Patulea 
Signed-off-by: Blue Swirl 
---
 tests/tcg/Makefile          |   9 +
 tests/tcg/test-i386-fprem.c | 353 ++++++++++++++++++++++++++++++++++++
 2 files changed, 362 insertions(+)
 create mode 100644 tests/tcg/test-i386-fprem.c

diff --git a/tests/tcg/Makefile b/tests/tcg/Makefile
index 80b1a4b529..24e3154cae 100644
--- a/tests/tcg/Makefile
+++ b/tests/tcg/Makefile
@@ -22,6 +22,7 @@ I386_TESTS=hello-i386 \
 	   testthread \
 	   sha1-i386 \
 	   test-i386 \
+	   test-i386-fprem \
 	   test-mmap \
 	   # runcom
 
@@ -55,6 +56,11 @@ run-test-i386: test-i386
 	-$(QEMU) test-i386 > test-i386.out
 	@if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK"; fi
 
+run-test-i386-fprem: test-i386-fprem
+	./test-i386-fprem > test-i386-fprem.ref
+	-$(QEMU) test-i386-fprem > test-i386-fprem.out
+	@if diff -u test-i386-fprem.ref test-i386-fprem.out ; then echo "Auto Test OK"; fi
+
 run-test-x86_64: test-x86_64
 	./test-x86_64 > test-x86_64.ref
 	-$(QEMU_X86_64) test-x86_64 > test-x86_64.out
@@ -93,6 +99,9 @@ test-i386: test-i386.c test-i386-code16.S test-i386-vm86.S \
 	$(CC_I386) $(QEMU_INCLUDES) $(CFLAGS) $(LDFLAGS) -o $@ \
               $(.
+ */
+#include "compiler.h"
+#include "osdep.h"
+#include 
+#include 
+
+/*
+ * Inspired by 's union ieee854_long_double, but with single
+ * long long mantissa fields and assuming little-endianness for simplicity.
+ */
+union float80u {
+    long double d;
+
+    /* This is the IEEE 854 double-extended-precision format.  */
+    struct {
+        unsigned long long mantissa:63;
+        unsigned int one:1;
+        unsigned int exponent:15;
+        unsigned int negative:1;
+        unsigned int empty:16;
+    } QEMU_PACKED ieee;
+
+    /* This is for NaNs in the IEEE 854 double-extended-precision format.  */
+    struct {
+        unsigned long long mantissa:62;
+        unsigned int quiet_nan:1;
+        unsigned int one:1;
+        unsigned int exponent:15;
+        unsigned int negative:1;
+        unsigned int empty:16;
+    } QEMU_PACKED ieee_nan;
+};
+
+#define IEEE854_LONG_DOUBLE_BIAS 0x3fff
+
+static const union float80u q_nan = {
+    .ieee_nan.negative = 0,  /* X */
+    .ieee_nan.exponent = 0x7fff,
+    .ieee_nan.one = 1,
+    .ieee_nan.quiet_nan = 1,
+    .ieee_nan.mantissa = 0,
+};
+
+static const union float80u s_nan = {
+    .ieee_nan.negative = 0,  /* X */
+    .ieee_nan.exponent = 0x7fff,
+    .ieee_nan.one = 1,
+    .ieee_nan.quiet_nan = 0,
+    .ieee_nan.mantissa = 1,  /* nonzero */
+};
+
+static const union float80u pos_inf = {
+    .ieee.negative = 0,
+    .ieee.exponent = 0x7fff,
+    .ieee.one = 1,
+    .ieee.mantissa = 0,
+};
+
+static const union float80u pseudo_pos_inf = {  /* "unsupported" */
+    .ieee.negative = 0,
+    .ieee.exponent = 0x7fff,
+    .ieee.one = 0,
+    .ieee.mantissa = 0,
+};
+
+static const union float80u pos_denorm = {
+    .ieee.negative = 0,
+    .ieee.exponent = 0,
+    .ieee.one = 0,
+    .ieee.mantissa = 1,
+};
+
+static const union float80u smallest_positive_norm = {
+    .ieee.negative = 0,
+    .ieee.exponent = 1,
+    .ieee.one = 1,
+    .ieee.mantissa = 0,
+};
+
+static void fninit()
+{
+    asm volatile ("fninit\n");
+}
+
+static long double fprem(long double a, long double b, uint16_t *sw)
+{
+    long double result;
+    asm volatile ("fprem\n"
+                  "fnstsw %1\n"
+                  : "=t" (result), "=m" (*sw)
+                  : "0" (a), "u" (b)
+                  : "st(1)");
+    return result;
+}
+
+static long double fprem1(long double a, long double b, uint16_t *sw)
+{
+    long double result;
+    asm volatile ("fprem1\n"
+                  "fnstsw %1\n"
+                  : "=t" (result), "=m" (*sw)
+                  : "0" (a), "u" (b)
+                  : "st(1)");
+    return result;
+}
+
+#define FPUS_IE (1 << 0)
+#define FPUS_DE (1 << 1)
+#define FPUS_ZE (1 << 2)
+#define FPUS_OE (1 << 3)
+#define FPUS_UE (1 << 4)
+#define FPUS_PE (1 << 5)
+#define FPUS_SF (1 << 6)
+#define FPUS_SE (1 << 7)
+#define FPUS_C0 (1 << 8)
+#define FPUS_C1 (1 << 9)
+#define FPUS_C2 (1 << 10)
+#define FPUS_TOP 0x3800
+#define FPUS_C3 (1 << 14)
+#define FPUS_B  (1 << 15)
+
+#define FPUS_EMASK 0x007f
+
+#define FPUC_EM 0x3f
+
+static void psw(uint16_t sw)
+{
+    printf("SW:  C3 TopC2C1C0\n");
+    printf("SW: %c %d %3d %d %d %d %c %c %c %c %c %c %c %c\n",
+           sw & FPUS_B ? 'B' : 'b',
+           !!(sw & FPUS_C3),
+           (sw & FPUS_TOP) >> 11,
+           !!(sw & FPUS_C2),
+           !!(sw & FPUS_C1),
+           !!(sw & FPUS_C0),
+           (sw & FPUS_SE) ? 'S' : 's',
+           (sw & FPUS_SF) ? 'F' : 'f',
+           (sw & FPUS_PE) ? 'P' : 'p',
+           (sw & FPUS_UE) ? 'U' : 'u',
+           (sw & FPUS_OE) ? 'O' : 'o',
+           (sw & FPUS_ZE) ? 'Z' : 'z',
+           (sw & FPUS_DE) ? 'D' : 'd',
+           (sw & FPUS_IE) ? 'I' : 'i');
+}
+
+static void do_fprem(long double a, long double b)
+{
+    const union float80u au = {.d = a};
+    const union float80u bu = {.d = b};
+    union float80u ru;
+    uint16_t sw;
+
+    printf("A: S=%d Exp=%04x Int=%d (QNaN=%d) Sig=%016llx (%.06Le)\n",
+           au.ieee.negative, au.ieee.exponent, au.ieee.one,
+           au.ieee_nan.quiet_nan, (unsigned long long)au.ieee.mantissa,
+           a);
+    printf("B: S=%d Exp=%04x Int=%d (QNaN=%d) Sig=%016llx (%.06Le)\n",
+           bu.ieee.negative, bu.ieee.exponent, bu.ieee.one,
+           bu.ieee_nan.quiet_nan, (unsigned long long)bu.ieee.mantissa,
+           b);
+    fflush(stdout);
+
+    fninit();
+    ru.d = fprem(a, b, &sw);
+    psw(sw);
+
+    printf("R : S=%d Exp=%04x Int=%d (QNaN=%d) Sig=%016llx (%.06Le)\n",
+           ru.ieee.negative, ru.ieee.exponent, ru.ieee.one,
+           ru.ieee_nan.quiet_nan, (unsigned long long)ru.ieee.mantissa,
+           ru.d);
+
+    fninit();
+    ru.d = fprem1(a, b, &sw);
+    psw(sw);
+
+    printf("R1: S=%d Exp=%04x Int=%d (QNaN=%d) Sig=%016llx (%.06Le)\n",
+           ru.ieee.negative, ru.ieee.exponent, ru.ieee.one,
+           ru.ieee_nan.quiet_nan, (unsigned long long)ru.ieee.mantissa,
+           ru.d);
+
+    printf("\n");
+}
+
+static void do_fprem_stack_underflow(void)
+{
+    const long double a = 1.0;
+    union float80u ru;
+    uint16_t sw;
+
+    fninit();
+    asm volatile ("fprem\n"
+                  "fnstsw %1\n"
+                  : "=t" (ru.d), "=m" (sw)
+                  : "0" (a)
+                  : "st(1)");
+    psw(sw);
+
+    printf("R: S=%d Exp=%04x Int=%d (QNaN=%d) Sig=%016llx (%.06Le)\n",
+           ru.ieee.negative, ru.ieee.exponent, ru.ieee.one,
+           ru.ieee_nan.quiet_nan, (unsigned long long)ru.ieee.mantissa,
+           ru.d);
+    printf("\n");
+}
+
+static void test_fprem_cases(void)
+{
+    printf("= stack underflow =\n");
+    do_fprem_stack_underflow();
+
+    printf("= invalid operation =\n");
+    do_fprem(s_nan.d, 1.0);
+    do_fprem(1.0, 0.0);
+    do_fprem(pos_inf.d, 1.0);
+    do_fprem(pseudo_pos_inf.d, 1.0);
+
+    printf("= denormal =\n");
+    do_fprem(pos_denorm.d, 1.0);
+    do_fprem(1.0, pos_denorm.d);
+
+    /* printf("= underflow =\n"); */
+    /* TODO: Is there a case where FPREM raises underflow? */
+}
+
+static void test_fprem_pairs(void)
+{
+    unsigned long long count;
+
+    unsigned int negative_index_a = 0;
+    unsigned int negative_index_b = 0;
+    static const unsigned int negative_values[] = {
+        0,
+        1,
+    };
+
+    unsigned int exponent_index_a = 0;
+    unsigned int exponent_index_b = 0;
+    static const unsigned int exponent_values[] = {
+        0,
+        1,
+        2,
+        IEEE854_LONG_DOUBLE_BIAS - 1,
+        IEEE854_LONG_DOUBLE_BIAS,
+        IEEE854_LONG_DOUBLE_BIAS + 1,
+        0x7ffd,
+        0x7ffe,
+        0x7fff,
+    };
+
+    unsigned int one_index_a = 0;
+    unsigned int one_index_b = 0;
+    static const unsigned int one_values[] = {
+        0,
+        1,
+    };
+
+    unsigned int quiet_nan_index_a = 0;
+    unsigned int quiet_nan_index_b = 0;
+    static const unsigned int quiet_nan_values[] = {
+        0,
+        1,
+    };
+
+    unsigned int mantissa_index_a = 0;
+    unsigned int mantissa_index_b = 0;
+    static const unsigned long long mantissa_values[] = {
+        0,
+        1,
+        2,
+        0x3ffffffffffffffdULL,
+        0x3ffffffffffffffeULL,
+        0x3fffffffffffffffULL,
+    };
+
+    for (count = 0; ; ++count) {
+#define INIT_FIELD(var, field) \
+            .ieee_nan.field = field##_values[field##_index_##var]
+        const union float80u a = {
+            INIT_FIELD(a, negative),
+            INIT_FIELD(a, exponent),
+            INIT_FIELD(a, one),
+            INIT_FIELD(a, quiet_nan),
+            INIT_FIELD(a, mantissa),
+        };
+        const union float80u b = {
+            INIT_FIELD(b, negative),
+            INIT_FIELD(b, exponent),
+            INIT_FIELD(b, one),
+            INIT_FIELD(b, quiet_nan),
+            INIT_FIELD(b, mantissa),
+        };
+#undef INIT_FIELD
+
+        do_fprem(a.d, b.d);
+
+        int carry = 1;
+#define CARRY_INTO(var, field) do { \
+            if (carry) { \
+                if (++field##_index_##var == ARRAY_SIZE(field##_values)) { \
+                    field##_index_##var = 0; \
+                } else { \
+                    carry = 0; \
+                } \
+            } \
+        } while (0)
+        CARRY_INTO(b, mantissa);
+        CARRY_INTO(b, quiet_nan);
+        CARRY_INTO(b, one);
+        CARRY_INTO(b, exponent);
+        CARRY_INTO(b, negative);
+        CARRY_INTO(a, mantissa);
+        CARRY_INTO(a, quiet_nan);
+        CARRY_INTO(a, one);
+        CARRY_INTO(a, exponent);
+        CARRY_INTO(a, negative);
+#undef CARRY_INTO
+
+        if (carry) {
+            break;
+        }
+    }
+
+    fprintf(stderr, "test-i386-fprem: tested %llu cases\n", count);
+}
+
+int main(int argc, char **argv)
+{
+    test_fprem_cases();
+    test_fprem_pairs();
+    return 0;
+}

From 4d4d9b3adb0e36e75cf9b2126ee1d01b1d59f8a1 Mon Sep 17 00:00:00 2001
From: Blue Swirl 
Date: Sat, 13 Oct 2012 18:46:05 +0000
Subject: [PATCH 1561/2270] m48t59: remove unused m48t59_set_addr

Signed-off-by: Blue Swirl 
---
 hw/m48t59.c | 7 -------
 hw/nvram.h  | 1 -
 2 files changed, 8 deletions(-)

diff --git a/hw/m48t59.c b/hw/m48t59.c
index 9e8e692669..7da7e7c822 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -468,13 +468,6 @@ uint32_t m48t59_read (void *opaque, uint32_t addr)
     return retval;
 }
 
-void m48t59_set_addr (void *opaque, uint32_t addr)
-{
-    M48t59State *NVRAM = opaque;
-
-    NVRAM->addr = addr;
-}
-
 void m48t59_toggle_lock (void *opaque, int lock)
 {
     M48t59State *NVRAM = opaque;
diff --git a/hw/nvram.h b/hw/nvram.h
index 72363ced42..59337faaad 100644
--- a/hw/nvram.h
+++ b/hw/nvram.h
@@ -30,6 +30,5 @@ M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
                              int type);
 M48t59State *m48t59_init(qemu_irq IRQ, hwaddr mem_base,
                          uint32_t io_base, uint16_t size, int type);
-void m48t59_set_addr (void *opaque, uint32_t addr);
 
 #endif /* !NVRAM_H */

From e62774c41006bc8072579515b9f6782b56c33bd1 Mon Sep 17 00:00:00 2001
From: Blue Swirl 
Date: Sat, 13 Oct 2012 18:49:20 +0000
Subject: [PATCH 1562/2270] sun4c: remove unused functions

Signed-off-by: Blue Swirl 
---
 hw/sun4c_intctl.c | 23 -----------------------
 hw/sun4m.h        |  4 ----
 2 files changed, 27 deletions(-)

diff --git a/hw/sun4c_intctl.c b/hw/sun4c_intctl.c
index 8cd70ab64c..702e9f5444 100644
--- a/hw/sun4c_intctl.c
+++ b/hw/sun4c_intctl.c
@@ -94,29 +94,6 @@ static const MemoryRegionOps sun4c_intctl_mem_ops = {
     },
 };
 
-void sun4c_pic_info(Monitor *mon, void *opaque)
-{
-    Sun4c_INTCTLState *s = opaque;
-
-    monitor_printf(mon, "master: pending 0x%2.2x, enabled 0x%2.2x\n",
-                   s->pending, s->reg);
-}
-
-void sun4c_irq_info(Monitor *mon, void *opaque)
-{
-#ifndef DEBUG_IRQ_COUNT
-    monitor_printf(mon, "irq statistic code not compiled.\n");
-#else
-    Sun4c_INTCTLState *s = opaque;
-    int64_t count;
-
-    monitor_printf(mon, "IRQ statistics:\n");
-    count = s->irq_count;
-    if (count > 0)
-        monitor_printf(mon, " %" PRId64 "\n", count);
-#endif
-}
-
 static const uint32_t intbit_to_level[] = { 0, 1, 4, 6, 8, 10, 0, 14, };
 
 static void sun4c_check_interrupts(void *opaque)
diff --git a/hw/sun4m.h b/hw/sun4m.h
index a8c3133703..47eb945f07 100644
--- a/hw/sun4m.h
+++ b/hw/sun4m.h
@@ -26,10 +26,6 @@ static inline void sparc_iommu_memory_write(void *opaque,
 void slavio_pic_info(Monitor *mon, DeviceState *dev);
 void slavio_irq_info(Monitor *mon, DeviceState *dev);
 
-/* sun4c_intctl.c */
-void sun4c_pic_info(Monitor *mon, void *opaque);
-void sun4c_irq_info(Monitor *mon, void *opaque);
-
 /* sun4m.c */
 void sun4m_pic_info(Monitor *mon);
 void sun4m_irq_info(Monitor *mon);

From 036208c9ab50b0910c24b28a440c15e66e8a2652 Mon Sep 17 00:00:00 2001
From: Blue Swirl 
Date: Sat, 13 Oct 2012 18:52:23 +0000
Subject: [PATCH 1563/2270] slirp: remove unused function u_sleep

Signed-off-by: Blue Swirl 
---
 slirp/misc.c | 14 --------------
 slirp/misc.h |  1 -
 2 files changed, 15 deletions(-)

diff --git a/slirp/misc.c b/slirp/misc.c
index 0bee864337..664532a663 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -253,20 +253,6 @@ void lprint(const char *format, ...)
     va_end(args);
 }
 
-void
-u_sleep(int usec)
-{
-	struct timeval t;
-	fd_set fdset;
-
-	FD_ZERO(&fdset);
-
-	t.tv_sec = 0;
-	t.tv_usec = usec * 1000;
-
-	select(0, &fdset, &fdset, &fdset, &t);
-}
-
 void slirp_connection_info(Slirp *slirp, Monitor *mon)
 {
     const char * const tcpstates[] = {
diff --git a/slirp/misc.h b/slirp/misc.h
index ed40a103c5..cc36aeb959 100644
--- a/slirp/misc.h
+++ b/slirp/misc.h
@@ -64,7 +64,6 @@ void snooze_hup(int);
 void snooze(void);
 void relay(int);
 void add_emu(char *);
-void u_sleep(int);
 void fd_nonblock(int);
 void fd_block(int);
 int rsh_exec(struct socket *, struct socket *, char *, char *, char *);

From f4359b9ffe895fda6d1ec3dd441cb8a208fb4dce Mon Sep 17 00:00:00 2001
From: Blue Swirl 
Date: Sat, 8 Sep 2012 12:40:00 +0000
Subject: [PATCH 1564/2270] disas: avoid using cpu_single_env

Pass around CPUArchState instead of using global cpu_single_env.

Signed-off-by: Blue Swirl 
Acked-by: Richard Henderson 
Acked-by: Aurelien Jarno 
Acked-by: Guan Xuetao 
---
 disas.c                       | 149 ++++++++++++++++++----------------
 disas.h                       |   3 +-
 qemu-log.h                    |   6 +-
 target-alpha/translate.c      |   2 +-
 target-arm/translate.c        |   2 +-
 target-cris/translate.c       |   2 +-
 target-i386/translate.c       |   2 +-
 target-lm32/translate.c       |   2 +-
 target-m68k/translate.c       |   2 +-
 target-microblaze/translate.c |   2 +-
 target-mips/translate.c       |   2 +-
 target-openrisc/translate.c   |   2 +-
 target-ppc/translate.c        |   2 +-
 target-s390x/translate.c      |   2 +-
 target-sh4/translate.c        |   2 +-
 target-sparc/translate.c      |   2 +-
 target-unicore32/translate.c  |   2 +-
 17 files changed, 100 insertions(+), 86 deletions(-)

diff --git a/disas.c b/disas.c
index b801c8f51d..6da1dd09f4 100644
--- a/disas.c
+++ b/disas.c
@@ -7,6 +7,11 @@
 #include "cpu.h"
 #include "disas.h"
 
+typedef struct CPUDebug {
+    struct disassemble_info info;
+    CPUArchState *env;
+} CPUDebug;
+
 /* Filled in by elfload.c.  Simplistic, but will do for now. */
 struct syminfo *syminfos = NULL;
 
@@ -32,7 +37,9 @@ target_read_memory (bfd_vma memaddr,
                     int length,
                     struct disassemble_info *info)
 {
-    cpu_memory_rw_debug(cpu_single_env, memaddr, myaddr, length, 0);
+    CPUDebug *s = container_of(info, CPUDebug, info);
+
+    cpu_memory_rw_debug(s->env, memaddr, myaddr, length, 0);
     return 0;
 }
 
@@ -158,32 +165,35 @@ print_insn_thumb1(bfd_vma pc, disassemble_info *info)
     ppc  - nonzero means little endian
     other targets - unused
  */
-void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
+void target_disas(FILE *out, CPUArchState *env, target_ulong code,
+                  target_ulong size, int flags)
 {
     target_ulong pc;
     int count;
-    struct disassemble_info disasm_info;
+    CPUDebug s;
     int (*print_insn)(bfd_vma pc, disassemble_info *info);
 
-    INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
+    INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
 
-    disasm_info.read_memory_func = target_read_memory;
-    disasm_info.buffer_vma = code;
-    disasm_info.buffer_length = size;
-    disasm_info.print_address_func = generic_print_target_address;
+    s.env = env;
+    s.info.read_memory_func = target_read_memory;
+    s.info.buffer_vma = code;
+    s.info.buffer_length = size;
+    s.info.print_address_func = generic_print_target_address;
 
 #ifdef TARGET_WORDS_BIGENDIAN
-    disasm_info.endian = BFD_ENDIAN_BIG;
+    s.info.endian = BFD_ENDIAN_BIG;
 #else
-    disasm_info.endian = BFD_ENDIAN_LITTLE;
+    s.info.endian = BFD_ENDIAN_LITTLE;
 #endif
 #if defined(TARGET_I386)
-    if (flags == 2)
-        disasm_info.mach = bfd_mach_x86_64;
-    else if (flags == 1)
-        disasm_info.mach = bfd_mach_i386_i8086;
-    else
-        disasm_info.mach = bfd_mach_i386_i386;
+    if (flags == 2) {
+        s.info.mach = bfd_mach_x86_64;
+    } else if (flags == 1) {
+        s.info.mach = bfd_mach_i386_i8086;
+    } else {
+        s.info.mach = bfd_mach_i386_i386;
+    }
     print_insn = print_insn_i386;
 #elif defined(TARGET_ARM)
     if (flags & 1) {
@@ -193,27 +203,28 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
     }
     if (flags & 2) {
 #ifdef TARGET_WORDS_BIGENDIAN
-        disasm_info.endian = BFD_ENDIAN_LITTLE;
+        s.info.endian = BFD_ENDIAN_LITTLE;
 #else
-        disasm_info.endian = BFD_ENDIAN_BIG;
+        s.info.endian = BFD_ENDIAN_BIG;
 #endif
     }
 #elif defined(TARGET_SPARC)
     print_insn = print_insn_sparc;
 #ifdef TARGET_SPARC64
-    disasm_info.mach = bfd_mach_sparc_v9b;
+    s.info.mach = bfd_mach_sparc_v9b;
 #endif
 #elif defined(TARGET_PPC)
-    if (flags >> 16)
-        disasm_info.endian = BFD_ENDIAN_LITTLE;
+    if (flags >> 16) {
+        s.info.endian = BFD_ENDIAN_LITTLE;
+    }
     if (flags & 0xFFFF) {
         /* If we have a precise definitions of the instructions set, use it */
-        disasm_info.mach = flags & 0xFFFF;
+        s.info.mach = flags & 0xFFFF;
     } else {
 #ifdef TARGET_PPC64
-        disasm_info.mach = bfd_mach_ppc64;
+        s.info.mach = bfd_mach_ppc64;
 #else
-        disasm_info.mach = bfd_mach_ppc;
+        s.info.mach = bfd_mach_ppc;
 #endif
     }
     print_insn = print_insn_ppc;
@@ -226,27 +237,27 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
     print_insn = print_insn_little_mips;
 #endif
 #elif defined(TARGET_SH4)
-    disasm_info.mach = bfd_mach_sh4;
+    s.info.mach = bfd_mach_sh4;
     print_insn = print_insn_sh;
 #elif defined(TARGET_ALPHA)
-    disasm_info.mach = bfd_mach_alpha_ev6;
+    s.info.mach = bfd_mach_alpha_ev6;
     print_insn = print_insn_alpha;
 #elif defined(TARGET_CRIS)
     if (flags != 32) {
-        disasm_info.mach = bfd_mach_cris_v0_v10;
+        s.info.mach = bfd_mach_cris_v0_v10;
         print_insn = print_insn_crisv10;
     } else {
-        disasm_info.mach = bfd_mach_cris_v32;
+        s.info.mach = bfd_mach_cris_v32;
         print_insn = print_insn_crisv32;
     }
 #elif defined(TARGET_S390X)
-    disasm_info.mach = bfd_mach_s390_64;
+    s.info.mach = bfd_mach_s390_64;
     print_insn = print_insn_s390;
 #elif defined(TARGET_MICROBLAZE)
-    disasm_info.mach = bfd_arch_microblaze;
+    s.info.mach = bfd_arch_microblaze;
     print_insn = print_insn_microblaze;
 #elif defined(TARGET_LM32)
-    disasm_info.mach = bfd_mach_lm32;
+    s.info.mach = bfd_mach_lm32;
     print_insn = print_insn_lm32;
 #else
     fprintf(out, "0x" TARGET_FMT_lx
@@ -256,14 +267,14 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
 
     for (pc = code; size > 0; pc += count, size -= count) {
 	fprintf(out, "0x" TARGET_FMT_lx ":  ", pc);
-	count = print_insn(pc, &disasm_info);
+	count = print_insn(pc, &s.info);
 #if 0
         {
             int i;
             uint8_t b;
             fprintf(out, " {");
             for(i = 0; i < count; i++) {
-                target_read_memory(pc + i, &b, 1, &disasm_info);
+                target_read_memory(pc + i, &b, 1, &s.info);
                 fprintf(out, " %02x", b);
             }
             fprintf(out, " }");
@@ -287,28 +298,28 @@ void disas(FILE *out, void *code, unsigned long size)
 {
     uintptr_t pc;
     int count;
-    struct disassemble_info disasm_info;
+    CPUDebug s;
     int (*print_insn)(bfd_vma pc, disassemble_info *info);
 
-    INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
-    disasm_info.print_address_func = generic_print_host_address;
+    INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
+    s.info.print_address_func = generic_print_host_address;
 
-    disasm_info.buffer = code;
-    disasm_info.buffer_vma = (uintptr_t)code;
-    disasm_info.buffer_length = size;
+    s.info.buffer = code;
+    s.info.buffer_vma = (uintptr_t)code;
+    s.info.buffer_length = size;
 
 #ifdef HOST_WORDS_BIGENDIAN
-    disasm_info.endian = BFD_ENDIAN_BIG;
+    s.info.endian = BFD_ENDIAN_BIG;
 #else
-    disasm_info.endian = BFD_ENDIAN_LITTLE;
+    s.info.endian = BFD_ENDIAN_LITTLE;
 #endif
 #if defined(CONFIG_TCG_INTERPRETER)
     print_insn = print_insn_tci;
 #elif defined(__i386__)
-    disasm_info.mach = bfd_mach_i386_i386;
+    s.info.mach = bfd_mach_i386_i386;
     print_insn = print_insn_i386;
 #elif defined(__x86_64__)
-    disasm_info.mach = bfd_mach_x86_64;
+    s.info.mach = bfd_mach_x86_64;
     print_insn = print_insn_i386;
 #elif defined(_ARCH_PPC)
     print_insn = print_insn_ppc;
@@ -316,7 +327,7 @@ void disas(FILE *out, void *code, unsigned long size)
     print_insn = print_insn_alpha;
 #elif defined(__sparc__)
     print_insn = print_insn_sparc;
-    disasm_info.mach = bfd_mach_sparc_v9b;
+    s.info.mach = bfd_mach_sparc_v9b;
 #elif defined(__arm__)
     print_insn = print_insn_arm;
 #elif defined(__MIPSEB__)
@@ -338,7 +349,7 @@ void disas(FILE *out, void *code, unsigned long size)
 #endif
     for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
         fprintf(out, "0x%08" PRIxPTR ":  ", pc);
-	count = print_insn(pc, &disasm_info);
+        count = print_insn(pc, &s.info);
 	fprintf(out, "\n");
 	if (count < 0)
 	    break;
@@ -366,16 +377,17 @@ const char *lookup_symbol(target_ulong orig_addr)
 #include "monitor.h"
 
 static int monitor_disas_is_physical;
-static CPUArchState *monitor_disas_env;
 
 static int
 monitor_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length,
                      struct disassemble_info *info)
 {
+    CPUDebug *s = container_of(info, CPUDebug, info);
+
     if (monitor_disas_is_physical) {
         cpu_physical_memory_read(memaddr, myaddr, length);
     } else {
-        cpu_memory_rw_debug(monitor_disas_env, memaddr,myaddr, length, 0);
+        cpu_memory_rw_debug(s->env, memaddr,myaddr, length, 0);
     }
     return 0;
 }
@@ -394,30 +406,31 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
                    target_ulong pc, int nb_insn, int is_physical, int flags)
 {
     int count, i;
-    struct disassemble_info disasm_info;
+    CPUDebug s;
     int (*print_insn)(bfd_vma pc, disassemble_info *info);
 
-    INIT_DISASSEMBLE_INFO(disasm_info, (FILE *)mon, monitor_fprintf);
+    INIT_DISASSEMBLE_INFO(s.info, (FILE *)mon, monitor_fprintf);
 
-    monitor_disas_env = env;
+    s.env = env;
     monitor_disas_is_physical = is_physical;
-    disasm_info.read_memory_func = monitor_read_memory;
-    disasm_info.print_address_func = generic_print_target_address;
+    s.info.read_memory_func = monitor_read_memory;
+    s.info.print_address_func = generic_print_target_address;
 
-    disasm_info.buffer_vma = pc;
+    s.info.buffer_vma = pc;
 
 #ifdef TARGET_WORDS_BIGENDIAN
-    disasm_info.endian = BFD_ENDIAN_BIG;
+    s.info.endian = BFD_ENDIAN_BIG;
 #else
-    disasm_info.endian = BFD_ENDIAN_LITTLE;
+    s.info.endian = BFD_ENDIAN_LITTLE;
 #endif
 #if defined(TARGET_I386)
-    if (flags == 2)
-        disasm_info.mach = bfd_mach_x86_64;
-    else if (flags == 1)
-        disasm_info.mach = bfd_mach_i386_i8086;
-    else
-        disasm_info.mach = bfd_mach_i386_i386;
+    if (flags == 2) {
+        s.info.mach = bfd_mach_x86_64;
+    } else if (flags == 1) {
+        s.info.mach = bfd_mach_i386_i8086;
+    } else {
+        s.info.mach = bfd_mach_i386_i386;
+    }
     print_insn = print_insn_i386;
 #elif defined(TARGET_ARM)
     print_insn = print_insn_arm;
@@ -426,13 +439,13 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
 #elif defined(TARGET_SPARC)
     print_insn = print_insn_sparc;
 #ifdef TARGET_SPARC64
-    disasm_info.mach = bfd_mach_sparc_v9b;
+    s.info.mach = bfd_mach_sparc_v9b;
 #endif
 #elif defined(TARGET_PPC)
 #ifdef TARGET_PPC64
-    disasm_info.mach = bfd_mach_ppc64;
+    s.info.mach = bfd_mach_ppc64;
 #else
-    disasm_info.mach = bfd_mach_ppc;
+    s.info.mach = bfd_mach_ppc;
 #endif
     print_insn = print_insn_ppc;
 #elif defined(TARGET_M68K)
@@ -444,13 +457,13 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
     print_insn = print_insn_little_mips;
 #endif
 #elif defined(TARGET_SH4)
-    disasm_info.mach = bfd_mach_sh4;
+    s.info.mach = bfd_mach_sh4;
     print_insn = print_insn_sh;
 #elif defined(TARGET_S390X)
-    disasm_info.mach = bfd_mach_s390_64;
+    s.info.mach = bfd_mach_s390_64;
     print_insn = print_insn_s390;
 #elif defined(TARGET_LM32)
-    disasm_info.mach = bfd_mach_lm32;
+    s.info.mach = bfd_mach_lm32;
     print_insn = print_insn_lm32;
 #else
     monitor_printf(mon, "0x" TARGET_FMT_lx
@@ -460,7 +473,7 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
 
     for(i = 0; i < nb_insn; i++) {
 	monitor_printf(mon, "0x" TARGET_FMT_lx ":  ", pc);
-	count = print_insn(pc, &disasm_info);
+        count = print_insn(pc, &s.info);
 	monitor_printf(mon, "\n");
 	if (count < 0)
 	    break;
diff --git a/disas.h b/disas.h
index a8a09740db..c13ca9a3a4 100644
--- a/disas.h
+++ b/disas.h
@@ -6,7 +6,8 @@
 #ifdef NEED_CPU_H
 /* Disassemble this for me please... (debugging). */
 void disas(FILE *out, void *code, unsigned long size);
-void target_disas(FILE *out, target_ulong code, target_ulong size, int flags);
+void target_disas(FILE *out, CPUArchState *env, target_ulong code,
+                  target_ulong size, int flags);
 
 void monitor_disas(Monitor *mon, CPUArchState *env,
                    target_ulong pc, int nb_insn, int is_physical, int flags);
diff --git a/qemu-log.h b/qemu-log.h
index ce6bb095b3..344eca3f1b 100644
--- a/qemu-log.h
+++ b/qemu-log.h
@@ -84,10 +84,10 @@ static inline void log_cpu_state_mask(int mask, CPUArchState *env1, int flags)
 }
 
 /* disas() and target_disas() to qemu_logfile: */
-static inline void log_target_disas(target_ulong start, target_ulong len,
-                                    int flags)
+static inline void log_target_disas(CPUArchState *env, target_ulong start,
+                                    target_ulong len, int flags)
 {
-    target_disas(qemu_logfile, start, len, flags);
+    target_disas(qemu_logfile, env, start, len, flags);
 }
 
 static inline void log_disas(void *code, unsigned long size)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index f707d8deb9..8c4dd021f3 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3477,7 +3477,7 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(pc_start, ctx.pc - pc_start, 1);
+        log_target_disas(env, pc_start, ctx.pc - pc_start, 1);
         qemu_log("\n");
     }
 #endif
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 25433da037..7d8f8e5edc 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9968,7 +9968,7 @@ done_generating:
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("----------------\n");
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(pc_start, dc->pc - pc_start,
+        log_target_disas(env, pc_start, dc->pc - pc_start,
                          dc->thumb | (dc->bswap_code << 1));
         qemu_log("\n");
     }
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 755de659df..f8ebc43a86 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3413,7 +3413,7 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
 #ifdef DEBUG_DISAS
 #if !DISAS_CRIS
 	if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
-		log_target_disas(pc_start, dc->pc - pc_start,
+                log_target_disas(env, pc_start, dc->pc - pc_start,
                                  dc->env->pregs[PR_VR]);
 		qemu_log("\nisize=%d osize=%td\n",
 			dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
diff --git a/target-i386/translate.c b/target-i386/translate.c
index ee7585044b..bf52eefa55 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -8047,7 +8047,7 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
         else
 #endif
             disas_flags = !dc->code32;
-        log_target_disas(pc_start, pc_ptr - pc_start, disas_flags);
+        log_target_disas(env, pc_start, pc_ptr - pc_start, disas_flags);
         qemu_log("\n");
     }
 #endif
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index 77c2866611..3307daaf11 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -1120,7 +1120,7 @@ static void gen_intermediate_code_internal(CPULM32State *env,
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("\n");
-        log_target_disas(pc_start, dc->pc - pc_start, 0);
+        log_target_disas(env, pc_start, dc->pc - pc_start, 0);
         qemu_log("\nisize=%d osize=%td\n",
             dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
     }
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 451ef7410f..1430d4c991 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3070,7 +3070,7 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("----------------\n");
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(pc_start, dc->pc - pc_start, 0);
+        log_target_disas(env, pc_start, dc->pc - pc_start, 0);
         qemu_log("\n");
     }
 #endif
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 6f27c24b76..13fd73574b 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1913,7 +1913,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("\n");
 #if DISAS_GNU
-        log_target_disas(pc_start, dc->pc - pc_start, 0);
+        log_target_disas(env, pc_start, dc->pc - pc_start, 0);
 #endif
         qemu_log("\nisize=%d osize=%td\n",
             dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 8175da05d0..df92781b2c 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15640,7 +15640,7 @@ done_generating:
     LOG_DISAS("\n");
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(pc_start, ctx.pc - pc_start, 0);
+        log_target_disas(env, pc_start, ctx.pc - pc_start, 0);
         qemu_log("\n");
     }
 #endif
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index e2cad3ad42..ff2feb48db 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1797,7 +1797,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("\n");
-        log_target_disas(pc_start, dc->pc - pc_start, 0);
+        log_target_disas(&cpu->env, pc_start, dc->pc - pc_start, 0);
         qemu_log("\nisize=%d osize=%td\n",
             dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
     }
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 56725e6a61..f0d49eea3f 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9790,7 +9790,7 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
         flags = env->bfd_mach;
         flags |= ctx.le_mode << 16;
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(pc_start, ctx.nip - pc_start, flags);
+        log_target_disas(env, pc_start, ctx.nip - pc_start, flags);
         qemu_log("\n");
     }
 #endif
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index db464cc073..c6267a8769 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -5220,7 +5220,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
 #if defined(S390X_DEBUG_DISAS)
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(pc_start, dc.pc - pc_start, 1);
+        log_target_disas(env, pc_start, dc.pc - pc_start, 1);
         qemu_log("\n");
     }
 #endif
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 9d955eb204..2ae7f03d35 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -2070,7 +2070,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
 	qemu_log("IN:\n");	/* , lookup_symbol(pc_start)); */
-	log_target_disas(pc_start, ctx.pc - pc_start, 0);
+        log_target_disas(env, pc_start, ctx.pc - pc_start, 0);
 	qemu_log("\n");
     }
 #endif
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 9e46f1424b..1d8b8ad9b9 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5353,7 +5353,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("--------------\n");
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(pc_start, last_pc + 4 - pc_start, 0);
+        log_target_disas(env, pc_start, last_pc + 4 - pc_start, 0);
         qemu_log("\n");
     }
 #endif
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index c3cdafa18e..57b18ac0c6 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -2109,7 +2109,7 @@ done_generating:
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("----------------\n");
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(pc_start, dc->pc - pc_start, 0);
+        log_target_disas(env, pc_start, dc->pc - pc_start, 0);
         qemu_log("\n");
     }
 #endif

From 4840552601caf1779b3de34bc8ea3fc128a52d04 Mon Sep 17 00:00:00 2001
From: Blue Swirl 
Date: Sat, 8 Sep 2012 12:43:16 +0000
Subject: [PATCH 1565/2270] kvm: avoid using cpu_single_env
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Pass around CPUArchState instead of using global cpu_single_env.

Signed-off-by: Blue Swirl 
Reviewed-by: Andreas Färber 
---
 target-i386/kvm.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 73e2035637..f669281e13 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1945,14 +1945,15 @@ void kvm_arch_remove_all_hw_breakpoints(void)
 
 static CPUWatchpoint hw_watchpoint;
 
-static int kvm_handle_debug(struct kvm_debug_exit_arch *arch_info)
+static int kvm_handle_debug(CPUX86State *env,
+                            struct kvm_debug_exit_arch *arch_info)
 {
     int ret = 0;
     int n;
 
     if (arch_info->exception == 1) {
         if (arch_info->dr6 & (1 << 14)) {
-            if (cpu_single_env->singlestep_enabled) {
+            if (env->singlestep_enabled) {
                 ret = EXCP_DEBUG;
             }
         } else {
@@ -1964,13 +1965,13 @@ static int kvm_handle_debug(struct kvm_debug_exit_arch *arch_info)
                         break;
                     case 0x1:
                         ret = EXCP_DEBUG;
-                        cpu_single_env->watchpoint_hit = &hw_watchpoint;
+                        env->watchpoint_hit = &hw_watchpoint;
                         hw_watchpoint.vaddr = hw_breakpoint[n].addr;
                         hw_watchpoint.flags = BP_MEM_WRITE;
                         break;
                     case 0x3:
                         ret = EXCP_DEBUG;
-                        cpu_single_env->watchpoint_hit = &hw_watchpoint;
+                        env->watchpoint_hit = &hw_watchpoint;
                         hw_watchpoint.vaddr = hw_breakpoint[n].addr;
                         hw_watchpoint.flags = BP_MEM_ACCESS;
                         break;
@@ -1978,16 +1979,16 @@ static int kvm_handle_debug(struct kvm_debug_exit_arch *arch_info)
                 }
             }
         }
-    } else if (kvm_find_sw_breakpoint(cpu_single_env, arch_info->pc)) {
+    } else if (kvm_find_sw_breakpoint(env, arch_info->pc)) {
         ret = EXCP_DEBUG;
     }
     if (ret == 0) {
-        cpu_synchronize_state(cpu_single_env);
-        assert(cpu_single_env->exception_injected == -1);
+        cpu_synchronize_state(env);
+        assert(env->exception_injected == -1);
 
         /* pass to guest */
-        cpu_single_env->exception_injected = arch_info->exception;
-        cpu_single_env->has_error_code = 0;
+        env->exception_injected = arch_info->exception;
+        env->has_error_code = 0;
     }
 
     return ret;
@@ -2071,7 +2072,7 @@ int kvm_arch_handle_exit(CPUX86State *env, struct kvm_run *run)
         break;
     case KVM_EXIT_DEBUG:
         DPRINTF("kvm_exit_debug\n");
-        ret = kvm_handle_debug(&run->debug.arch);
+        ret = kvm_handle_debug(env, &run->debug.arch);
         break;
     default:
         fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);

From 447b3b60d15e1db6967a19e40284d33136a7c9e7 Mon Sep 17 00:00:00 2001
From: Blue Swirl 
Date: Sat, 8 Sep 2012 12:58:13 +0000
Subject: [PATCH 1566/2270] target-unicore32: avoid using cpu_single_env
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Pass around CPUArchState instead of using global cpu_single_env.

Signed-off-by: Blue Swirl 
Acked-by: Guan Xuetao 
Reviewed-by: Andreas Färber 
---
 target-unicore32/softmmu.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/target-unicore32/softmmu.c b/target-unicore32/softmmu.c
index 9c2c54cbc8..fc27100f27 100644
--- a/target-unicore32/softmmu.c
+++ b/target-unicore32/softmmu.c
@@ -31,7 +31,7 @@
 
 
 /* Map CPU modes onto saved register banks.  */
-static inline int bank_number(int mode)
+static inline int bank_number(CPUUniCore32State *env, int mode)
 {
     switch (mode) {
     case ASR_MODE_USER:
@@ -46,7 +46,7 @@ static inline int bank_number(int mode)
     case ASR_MODE_INTR:
         return 4;
     }
-    cpu_abort(cpu_single_env, "Bad mode %x\n", mode);
+    cpu_abort(env, "Bad mode %x\n", mode);
     return -1;
 }
 
@@ -60,12 +60,12 @@ void switch_mode(CPUUniCore32State *env, int mode)
         return;
     }
 
-    i = bank_number(old_mode);
+    i = bank_number(env, old_mode);
     env->banked_r29[i] = env->regs[29];
     env->banked_r30[i] = env->regs[30];
     env->banked_bsr[i] = env->bsr;
 
-    i = bank_number(mode);
+    i = bank_number(env, mode);
     env->regs[29] = env->banked_r29[i];
     env->regs[30] = env->banked_r30[i];
     env->bsr = env->banked_bsr[i];

From 0c4fabea809008702645e6b2c64926892b47f76d Mon Sep 17 00:00:00 2001
From: Blue Swirl 
Date: Sat, 8 Sep 2012 13:09:07 +0000
Subject: [PATCH 1567/2270] target-xtensa: avoid using cpu_single_env
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Pass around CPUArchState instead of using global cpu_single_env.

Signed-off-by: Blue Swirl 
Acked-by: Max Filippov 
Reviewed-by: Andreas Färber 
---
 target-xtensa/translate.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 82e8cccadc..3c03775a76 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -810,7 +810,7 @@ static TCGv_i32 gen_mac16_m(TCGv_i32 v, bool hi, bool is_unsigned)
     return m;
 }
 
-static void disas_xtensa_insn(DisasContext *dc)
+static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 {
 #define HAS_OPTION_BITS(opt) do { \
         if (!option_bits_enabled(dc, opt)) { \
@@ -900,8 +900,8 @@ static void disas_xtensa_insn(DisasContext *dc)
 
 #define RSR_SR (b1)
 
-    uint8_t b0 = cpu_ldub_code(cpu_single_env, dc->pc);
-    uint8_t b1 = cpu_ldub_code(cpu_single_env, dc->pc + 1);
+    uint8_t b0 = cpu_ldub_code(env, dc->pc);
+    uint8_t b1 = cpu_ldub_code(env, dc->pc + 1);
     uint8_t b2 = 0;
 
     static const uint32_t B4CONST[] = {
@@ -917,7 +917,7 @@ static void disas_xtensa_insn(DisasContext *dc)
         HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);
     } else {
         dc->next_pc = dc->pc + 3;
-        b2 = cpu_ldub_code(cpu_single_env, dc->pc + 2);
+        b2 = cpu_ldub_code(env, dc->pc + 2);
     }
 
     switch (OP0) {
@@ -2931,7 +2931,7 @@ static void gen_intermediate_code_internal(
             gen_ibreak_check(env, &dc);
         }
 
-        disas_xtensa_insn(&dc);
+        disas_xtensa_insn(env, &dc);
         ++insn_count;
         if (dc.icount) {
             tcg_gen_mov_i32(cpu_SR[ICOUNT], dc.next_icount);

From 0af10c86ed6656da0c9b680ec9d1c65768dd99b2 Mon Sep 17 00:00:00 2001
From: Blue Swirl 
Date: Sat, 8 Sep 2012 13:26:02 +0000
Subject: [PATCH 1568/2270] target-i386: avoid using cpu_single_env
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Pass around CPUArchState instead of using global cpu_single_env.

Signed-off-by: Blue Swirl 
Reviewed-by: Andreas Färber 
---
 target-i386/translate.c | 440 ++++++++++++++++++++--------------------
 1 file changed, 222 insertions(+), 218 deletions(-)

diff --git a/target-i386/translate.c b/target-i386/translate.c
index bf52eefa55..7fdb8bcbbe 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -2018,7 +2018,8 @@ static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
     }
 }
 
-static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
+static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm,
+                          int *reg_ptr, int *offset_ptr)
 {
     target_long disp;
     int havesib;
@@ -2044,7 +2045,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
 
         if (base == 4) {
             havesib = 1;
-            code = cpu_ldub_code(cpu_single_env, s->pc++);
+            code = cpu_ldub_code(env, s->pc++);
             scale = (code >> 6) & 3;
             index = ((code >> 3) & 7) | REX_X(s);
             base = (code & 7);
@@ -2055,7 +2056,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
         case 0:
             if ((base & 7) == 5) {
                 base = -1;
-                disp = (int32_t)cpu_ldl_code(cpu_single_env, s->pc);
+                disp = (int32_t)cpu_ldl_code(env, s->pc);
                 s->pc += 4;
                 if (CODE64(s) && !havesib) {
                     disp += s->pc + s->rip_offset;
@@ -2065,11 +2066,11 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
             }
             break;
         case 1:
-            disp = (int8_t)cpu_ldub_code(cpu_single_env, s->pc++);
+            disp = (int8_t)cpu_ldub_code(env, s->pc++);
             break;
         default:
         case 2:
-            disp = (int32_t)cpu_ldl_code(cpu_single_env, s->pc);
+            disp = (int32_t)cpu_ldl_code(env, s->pc);
             s->pc += 4;
             break;
         }
@@ -2132,7 +2133,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
         switch (mod) {
         case 0:
             if (rm == 6) {
-                disp = cpu_lduw_code(cpu_single_env, s->pc);
+                disp = cpu_lduw_code(env, s->pc);
                 s->pc += 2;
                 gen_op_movl_A0_im(disp);
                 rm = 0; /* avoid SS override */
@@ -2142,11 +2143,11 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
             }
             break;
         case 1:
-            disp = (int8_t)cpu_ldub_code(cpu_single_env, s->pc++);
+            disp = (int8_t)cpu_ldub_code(env, s->pc++);
             break;
         default:
         case 2:
-            disp = cpu_lduw_code(cpu_single_env, s->pc);
+            disp = cpu_lduw_code(env, s->pc);
             s->pc += 2;
             break;
         }
@@ -2202,7 +2203,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
     *offset_ptr = disp;
 }
 
-static void gen_nop_modrm(DisasContext *s, int modrm)
+static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
 {
     int mod, rm, base, code;
 
@@ -2216,7 +2217,7 @@ static void gen_nop_modrm(DisasContext *s, int modrm)
         base = rm;
 
         if (base == 4) {
-            code = cpu_ldub_code(cpu_single_env, s->pc++);
+            code = cpu_ldub_code(env, s->pc++);
             base = (code & 7);
         }
 
@@ -2276,7 +2277,8 @@ static void gen_add_A0_ds_seg(DisasContext *s)
 
 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
    OR_TMP0 */
-static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
+static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
+                           int ot, int reg, int is_store)
 {
     int mod, rm, opreg, disp;
 
@@ -2293,7 +2295,7 @@ static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_s
                 gen_op_mov_reg_T0(ot, reg);
         }
     } else {
-        gen_lea_modrm(s, modrm, &opreg, &disp);
+        gen_lea_modrm(env, s, modrm, &opreg, &disp);
         if (is_store) {
             if (reg != OR_TMP0)
                 gen_op_mov_TN_reg(ot, 0, reg);
@@ -2306,22 +2308,22 @@ static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_s
     }
 }
 
-static inline uint32_t insn_get(DisasContext *s, int ot)
+static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, int ot)
 {
     uint32_t ret;
 
     switch(ot) {
     case OT_BYTE:
-        ret = cpu_ldub_code(cpu_single_env, s->pc);
+        ret = cpu_ldub_code(env, s->pc);
         s->pc++;
         break;
     case OT_WORD:
-        ret = cpu_lduw_code(cpu_single_env, s->pc);
+        ret = cpu_lduw_code(env, s->pc);
         s->pc += 2;
         break;
     default:
     case OT_LONG:
-        ret = cpu_ldl_code(cpu_single_env, s->pc);
+        ret = cpu_ldl_code(env, s->pc);
         s->pc += 4;
         break;
     }
@@ -3167,7 +3169,8 @@ static const struct SSEOpHelper_eppi sse_op_table7[256] = {
     [0x63] = SSE42_OP(pcmpistri),
 };
 
-static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
+static void gen_sse(CPUX86State *env, DisasContext *s, int b,
+                    target_ulong pc_start, int rex_r)
 {
     int b1, op1_offset, op2_offset, is_xmm, val, ot;
     int modrm, mod, rm, reg, reg_addr, offset_addr;
@@ -3230,7 +3233,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         gen_helper_enter_mmx(cpu_env);
     }
 
-    modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+    modrm = cpu_ldub_code(env, s->pc++);
     reg = ((modrm >> 3) & 7);
     if (is_xmm)
         reg |= rex_r;
@@ -3241,7 +3244,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x0e7: /* movntq */
             if (mod == 3)
                 goto illegal_op;
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
             break;
         case 0x1e7: /* movntdq */
@@ -3249,20 +3252,20 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x12b: /* movntps */
             if (mod == 3)
                 goto illegal_op;
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
             break;
         case 0x3f0: /* lddqu */
             if (mod == 3)
                 goto illegal_op;
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
             break;
         case 0x22b: /* movntss */
         case 0x32b: /* movntsd */
             if (mod == 3)
                 goto illegal_op;
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             if (b1 & 1) {
                 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,
                     xmm_regs[reg]));
@@ -3275,12 +3278,12 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x6e: /* movd mm, ea */
 #ifdef TARGET_X86_64
             if (s->dflag == 2) {
-                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
+                gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 0);
                 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
             } else
 #endif
             {
-                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
+                gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 0);
                 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
                                  offsetof(CPUX86State,fpregs[reg].mmx));
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
@@ -3290,14 +3293,14 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x16e: /* movd xmm, ea */
 #ifdef TARGET_X86_64
             if (s->dflag == 2) {
-                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
+                gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 0);
                 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
                                  offsetof(CPUX86State,xmm_regs[reg]));
                 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T[0]);
             } else
 #endif
             {
-                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
+                gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 0);
                 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
                                  offsetof(CPUX86State,xmm_regs[reg]));
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
@@ -3306,7 +3309,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             break;
         case 0x6f: /* movq mm, ea */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
             } else {
                 rm = (modrm & 7);
@@ -3323,7 +3326,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x16f: /* movdqa xmm, ea */
         case 0x26f: /* movdqu xmm, ea */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
             } else {
                 rm = (modrm & 7) | REX_B(s);
@@ -3333,7 +3336,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             break;
         case 0x210: /* movss xmm, ea */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
                 gen_op_movl_T0_0();
@@ -3348,7 +3351,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             break;
         case 0x310: /* movsd xmm, ea */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
                 gen_op_movl_T0_0();
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
@@ -3362,7 +3365,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x012: /* movlps */
         case 0x112: /* movlpd */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
             } else {
                 /* movhlps */
@@ -3373,7 +3376,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             break;
         case 0x212: /* movsldup */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
             } else {
                 rm = (modrm & 7) | REX_B(s);
@@ -3389,7 +3392,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             break;
         case 0x312: /* movddup */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
             } else {
                 rm = (modrm & 7) | REX_B(s);
@@ -3402,7 +3405,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x016: /* movhps */
         case 0x116: /* movhpd */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
             } else {
                 /* movlhps */
@@ -3413,7 +3416,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             break;
         case 0x216: /* movshdup */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
             } else {
                 rm = (modrm & 7) | REX_B(s);
@@ -3434,8 +3437,8 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
 
                 if (b1 == 1 && reg != 0)
                     goto illegal_op;
-                field_length = cpu_ldub_code(cpu_single_env, s->pc++) & 0x3F;
-                bit_index = cpu_ldub_code(cpu_single_env, s->pc++) & 0x3F;
+                field_length = cpu_ldub_code(env, s->pc++) & 0x3F;
+                bit_index = cpu_ldub_code(env, s->pc++) & 0x3F;
                 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
                     offsetof(CPUX86State,xmm_regs[reg]));
                 if (b1 == 1)
@@ -3453,13 +3456,13 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             if (s->dflag == 2) {
                 tcg_gen_ld_i64(cpu_T[0], cpu_env, 
                                offsetof(CPUX86State,fpregs[reg].mmx));
-                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
+                gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 1);
             } else
 #endif
             {
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, 
                                  offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
-                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
+                gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 1);
             }
             break;
         case 0x17e: /* movd ea, xmm */
@@ -3467,18 +3470,18 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             if (s->dflag == 2) {
                 tcg_gen_ld_i64(cpu_T[0], cpu_env, 
                                offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
-                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
+                gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 1);
             } else
 #endif
             {
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, 
                                  offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
-                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
+                gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 1);
             }
             break;
         case 0x27e: /* movq xmm, ea */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
             } else {
                 rm = (modrm & 7) | REX_B(s);
@@ -3489,7 +3492,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             break;
         case 0x7f: /* movq ea, mm */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));
             } else {
                 rm = (modrm & 7);
@@ -3504,7 +3507,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x17f: /* movdqa ea, xmm */
         case 0x27f: /* movdqu ea, xmm */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
             } else {
                 rm = (modrm & 7) | REX_B(s);
@@ -3514,7 +3517,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             break;
         case 0x211: /* movss ea, xmm */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
                 gen_op_st_T0_A0(OT_LONG + s->mem_index);
             } else {
@@ -3525,7 +3528,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             break;
         case 0x311: /* movsd ea, xmm */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
             } else {
                 rm = (modrm & 7) | REX_B(s);
@@ -3536,7 +3539,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x013: /* movlps */
         case 0x113: /* movlpd */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
             } else {
                 goto illegal_op;
@@ -3545,7 +3548,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x017: /* movhps */
         case 0x117: /* movhpd */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
             } else {
                 goto illegal_op;
@@ -3560,7 +3563,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             if (b1 >= 2) {
 	        goto illegal_op;
             }
-            val = cpu_ldub_code(cpu_single_env, s->pc++);
+            val = cpu_ldub_code(env, s->pc++);
             if (is_xmm) {
                 gen_op_movl_T0_im(val);
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
@@ -3610,7 +3613,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x12a: /* cvtpi2pd */
             gen_helper_enter_mmx(cpu_env);
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 op2_offset = offsetof(CPUX86State,mmx_t0);
                 gen_ldq_env_A0(s->mem_index, op2_offset);
             } else {
@@ -3633,7 +3636,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x22a: /* cvtsi2ss */
         case 0x32a: /* cvtsi2sd */
             ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
-            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
+            gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
             op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
             if (ot == OT_LONG) {
@@ -3655,7 +3658,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x12d: /* cvtpd2pi */
             gen_helper_enter_mmx(cpu_env);
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 op2_offset = offsetof(CPUX86State,xmm_t0);
                 gen_ldo_env_A0(s->mem_index, op2_offset);
             } else {
@@ -3686,7 +3689,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x32d: /* cvtsd2si */
             ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 if ((b >> 8) & 1) {
                     gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_Q(0)));
                 } else {
@@ -3718,8 +3721,8 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0xc4: /* pinsrw */
         case 0x1c4:
             s->rip_offset = 1;
-            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
-            val = cpu_ldub_code(cpu_single_env, s->pc++);
+            gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
+            val = cpu_ldub_code(env, s->pc++);
             if (b1) {
                 val &= 7;
                 tcg_gen_st16_tl(cpu_T[0], cpu_env,
@@ -3735,7 +3738,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             if (mod != 3)
                 goto illegal_op;
             ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
-            val = cpu_ldub_code(cpu_single_env, s->pc++);
+            val = cpu_ldub_code(env, s->pc++);
             if (b1) {
                 val &= 7;
                 rm = (modrm & 7) | REX_B(s);
@@ -3752,7 +3755,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             break;
         case 0x1d6: /* movq ea, xmm */
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
             } else {
                 rm = (modrm & 7) | REX_B(s);
@@ -3796,7 +3799,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
                 goto crc32;
         case 0x038:
             b = modrm;
-            modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+            modrm = cpu_ldub_code(env, s->pc++);
             rm = modrm & 7;
             reg = ((modrm >> 3) & 7) | rex_r;
             mod = (modrm >> 6) & 3;
@@ -3817,7 +3820,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
                     op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
                 } else {
                     op2_offset = offsetof(CPUX86State,xmm_t0);
-                    gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                    gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                     switch (b) {
                     case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
                     case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
@@ -3852,7 +3855,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
                     op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
                 } else {
                     op2_offset = offsetof(CPUX86State,mmx_t0);
-                    gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                    gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                     gen_ldq_env_A0(s->mem_index, op2_offset);
                 }
             }
@@ -3870,7 +3873,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x338: /* crc32 */
         crc32:
             b = modrm;
-            modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+            modrm = cpu_ldub_code(env, s->pc++);
             reg = ((modrm >> 3) & 7) | rex_r;
 
             if (b != 0xf0 && b != 0xf1)
@@ -3890,7 +3893,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
 
             gen_op_mov_TN_reg(OT_LONG, 0, reg);
             tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
-            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
+            gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
             gen_helper_crc32(cpu_T[0], cpu_tmp2_i32,
                              cpu_T[0], tcg_const_i32(8 << ot));
 
@@ -3900,7 +3903,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x03a:
         case 0x13a:
             b = modrm;
-            modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+            modrm = cpu_ldub_code(env, s->pc++);
             rm = modrm & 7;
             reg = ((modrm >> 3) & 7) | rex_r;
             mod = (modrm >> 6) & 3;
@@ -3919,9 +3922,9 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
                 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
                 rm = (modrm & 7) | REX_B(s);
                 if (mod != 3)
-                    gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                    gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 reg = ((modrm >> 3) & 7) | rex_r;
-                val = cpu_ldub_code(cpu_single_env, s->pc++);
+                val = cpu_ldub_code(env, s->pc++);
                 switch (b) {
                 case 0x14: /* pextrb */
                     tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
@@ -4051,7 +4054,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
                     op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
                 } else {
                     op2_offset = offsetof(CPUX86State,xmm_t0);
-                    gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                    gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                     gen_ldo_env_A0(s->mem_index, op2_offset);
                 }
             } else {
@@ -4060,11 +4063,11 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
                     op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
                 } else {
                     op2_offset = offsetof(CPUX86State,mmx_t0);
-                    gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                    gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                     gen_ldq_env_A0(s->mem_index, op2_offset);
                 }
             }
-            val = cpu_ldub_code(cpu_single_env, s->pc++);
+            val = cpu_ldub_code(env, s->pc++);
 
             if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
                 s->cc_op = CC_OP_EFLAGS;
@@ -4095,7 +4098,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         if (is_xmm) {
             op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 op2_offset = offsetof(CPUX86State,xmm_t0);
                 if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
                                 b == 0xc2)) {
@@ -4118,7 +4121,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         } else {
             op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 op2_offset = offsetof(CPUX86State,mmx_t0);
                 gen_ldq_env_A0(s->mem_index, op2_offset);
             } else {
@@ -4130,7 +4133,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
         case 0x0f: /* 3DNow! data insns */
             if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
                 goto illegal_op;
-            val = cpu_ldub_code(cpu_single_env, s->pc++);
+            val = cpu_ldub_code(env, s->pc++);
             sse_fn_epp = sse_op_table5[val];
             if (!sse_fn_epp) {
                 goto illegal_op;
@@ -4141,7 +4144,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             break;
         case 0x70: /* pshufx insn */
         case 0xc6: /* pshufx insn */
-            val = cpu_ldub_code(cpu_single_env, s->pc++);
+            val = cpu_ldub_code(env, s->pc++);
             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
             tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
             /* XXX: introduce a new table? */
@@ -4150,7 +4153,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             break;
         case 0xc2:
             /* compare insns */
-            val = cpu_ldub_code(cpu_single_env, s->pc++);
+            val = cpu_ldub_code(env, s->pc++);
             if (val >= 8)
                 goto illegal_op;
             sse_fn_epp = sse_op_table4[val][b1];
@@ -4195,7 +4198,8 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
 
 /* convert one instruction. s->is_jmp is set if the translation must
    be stopped. Return the next pc value */
-static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
+static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
+                               target_ulong pc_start)
 {
     int b, prefixes, aflag, dflag;
     int shift, ot;
@@ -4220,7 +4224,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
 #endif
     s->rip_offset = 0; /* for relative ip address */
  next_byte:
-    b = cpu_ldub_code(cpu_single_env, s->pc);
+    b = cpu_ldub_code(env, s->pc);
     s->pc++;
     /* check prefixes */
 #ifdef TARGET_X86_64
@@ -4335,7 +4339,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
     case 0x0f:
         /**************************/
         /* extended op code */
-        b = cpu_ldub_code(cpu_single_env, s->pc++) | 0x100;
+        b = cpu_ldub_code(env, s->pc++) | 0x100;
         goto reswitch;
 
         /**************************/
@@ -4360,12 +4364,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
 
             switch(f) {
             case 0: /* OP Ev, Gv */
-                modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+                modrm = cpu_ldub_code(env, s->pc++);
                 reg = ((modrm >> 3) & 7) | rex_r;
                 mod = (modrm >> 6) & 3;
                 rm = (modrm & 7) | REX_B(s);
                 if (mod != 3) {
-                    gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                    gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                     opreg = OR_TMP0;
                 } else if (op == OP_XORL && rm == reg) {
                 xor_zero:
@@ -4382,12 +4386,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                 gen_op(s, op, ot, opreg);
                 break;
             case 1: /* OP Gv, Ev */
-                modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+                modrm = cpu_ldub_code(env, s->pc++);
                 mod = (modrm >> 6) & 3;
                 reg = ((modrm >> 3) & 7) | rex_r;
                 rm = (modrm & 7) | REX_B(s);
                 if (mod != 3) {
-                    gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                    gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                     gen_op_ld_T1_A0(ot + s->mem_index);
                 } else if (op == OP_XORL && rm == reg) {
                     goto xor_zero;
@@ -4397,7 +4401,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                 gen_op(s, op, ot, reg);
                 break;
             case 2: /* OP A, Iv */
-                val = insn_get(s, ot);
+                val = insn_get(env, s, ot);
                 gen_op_movl_T1_im(val);
                 gen_op(s, op, ot, OR_EAX);
                 break;
@@ -4419,7 +4423,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             else
                 ot = dflag + OT_WORD;
 
-            modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+            modrm = cpu_ldub_code(env, s->pc++);
             mod = (modrm >> 6) & 3;
             rm = (modrm & 7) | REX_B(s);
             op = (modrm >> 3) & 7;
@@ -4429,7 +4433,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                     s->rip_offset = 1;
                 else
                     s->rip_offset = insn_const_size(ot);
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 opreg = OR_TMP0;
             } else {
                 opreg = rm;
@@ -4440,10 +4444,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             case 0x80:
             case 0x81:
             case 0x82:
-                val = insn_get(s, ot);
+                val = insn_get(env, s, ot);
                 break;
             case 0x83:
-                val = (int8_t)insn_get(s, OT_BYTE);
+                val = (int8_t)insn_get(env, s, OT_BYTE);
                 break;
             }
             gen_op_movl_T1_im(val);
@@ -4468,14 +4472,14 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         else
             ot = dflag + OT_WORD;
 
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         rm = (modrm & 7) | REX_B(s);
         op = (modrm >> 3) & 7;
         if (mod != 3) {
             if (op == 0)
                 s->rip_offset = insn_const_size(ot);
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             gen_op_ld_T0_A0(ot + s->mem_index);
         } else {
             gen_op_mov_TN_reg(ot, 0, rm);
@@ -4483,7 +4487,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
 
         switch(op) {
         case 0: /* test */
-            val = insn_get(s, ot);
+            val = insn_get(env, s, ot);
             gen_op_movl_T1_im(val);
             gen_op_testl_T0_T1_cc();
             s->cc_op = CC_OP_LOGICB + ot;
@@ -4700,7 +4704,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         else
             ot = dflag + OT_WORD;
 
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         rm = (modrm & 7) | REX_B(s);
         op = (modrm >> 3) & 7;
@@ -4719,7 +4723,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             }
         }
         if (mod != 3) {
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             if (op >= 2 && op != 3 && op != 5)
                 gen_op_ld_T0_A0(ot + s->mem_index);
         } else {
@@ -4812,10 +4816,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         else
             ot = dflag + OT_WORD;
 
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
 
-        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
+        gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
         gen_op_mov_TN_reg(ot, 1, reg);
         gen_op_testl_T0_T1_cc();
         s->cc_op = CC_OP_LOGICB + ot;
@@ -4827,7 +4831,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             ot = OT_BYTE;
         else
             ot = dflag + OT_WORD;
-        val = insn_get(s, ot);
+        val = insn_get(env, s, ot);
 
         gen_op_mov_TN_reg(ot, 0, OR_EAX);
         gen_op_movl_T1_im(val);
@@ -4877,18 +4881,18 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
     case 0x69: /* imul Gv, Ev, I */
     case 0x6b:
         ot = dflag + OT_WORD;
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         if (b == 0x69)
             s->rip_offset = insn_const_size(ot);
         else if (b == 0x6b)
             s->rip_offset = 1;
-        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
+        gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
         if (b == 0x69) {
-            val = insn_get(s, ot);
+            val = insn_get(env, s, ot);
             gen_op_movl_T1_im(val);
         } else if (b == 0x6b) {
-            val = (int8_t)insn_get(s, OT_BYTE);
+            val = (int8_t)insn_get(env, s, OT_BYTE);
             gen_op_movl_T1_im(val);
         } else {
             gen_op_mov_TN_reg(ot, 1, reg);
@@ -4941,7 +4945,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             ot = OT_BYTE;
         else
             ot = dflag + OT_WORD;
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         mod = (modrm >> 6) & 3;
         if (mod == 3) {
@@ -4952,7 +4956,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             gen_op_mov_reg_T1(ot, reg);
             gen_op_mov_reg_T0(ot, rm);
         } else {
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             gen_op_mov_TN_reg(ot, 0, reg);
             gen_op_ld_T1_A0(ot + s->mem_index);
             gen_op_addl_T0_T1();
@@ -4972,7 +4976,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                 ot = OT_BYTE;
             else
                 ot = dflag + OT_WORD;
-            modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+            modrm = cpu_ldub_code(env, s->pc++);
             reg = ((modrm >> 3) & 7) | rex_r;
             mod = (modrm >> 6) & 3;
             t0 = tcg_temp_local_new();
@@ -4984,7 +4988,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                 rm = (modrm & 7) | REX_B(s);
                 gen_op_mov_v_reg(ot, t0, rm);
             } else {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 tcg_gen_mov_tl(a0, cpu_A0);
                 gen_op_ld_v(ot + s->mem_index, t0, a0);
                 rm = 0; /* avoid warning */
@@ -5020,7 +5024,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         }
         break;
     case 0x1c7: /* cmpxchg8b */
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         if ((mod == 3) || ((modrm & 0x38) != 0x8))
             goto illegal_op;
@@ -5031,7 +5035,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             gen_jmp_im(pc_start - s->cs_base);
             if (s->cc_op != CC_OP_DYNAMIC)
                 gen_op_set_cc_op(s->cc_op);
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             gen_helper_cmpxchg16b(cpu_env, cpu_A0);
         } else
 #endif        
@@ -5041,7 +5045,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             gen_jmp_im(pc_start - s->cs_base);
             if (s->cc_op != CC_OP_DYNAMIC)
                 gen_op_set_cc_op(s->cc_op);
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             gen_helper_cmpxchg8b(cpu_env, cpu_A0);
         }
         s->cc_op = CC_OP_EFLAGS;
@@ -5082,9 +5086,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             ot = dflag + OT_WORD;
         }
         if (b == 0x68)
-            val = insn_get(s, ot);
+            val = insn_get(env, s, ot);
         else
-            val = (int8_t)insn_get(s, OT_BYTE);
+            val = (int8_t)insn_get(env, s, OT_BYTE);
         gen_op_movl_T0_im(val);
         gen_push_T0(s);
         break;
@@ -5094,7 +5098,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         } else {
             ot = dflag + OT_WORD;
         }
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         gen_pop_T0(s);
         if (mod == 3) {
@@ -5105,7 +5109,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         } else {
             /* NOTE: order is important too for MMU exceptions */
             s->popl_esp_hack = 1 << ot;
-            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
+            gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
             s->popl_esp_hack = 0;
             gen_pop_update(s);
         }
@@ -5113,9 +5117,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
     case 0xc8: /* enter */
         {
             int level;
-            val = cpu_lduw_code(cpu_single_env, s->pc);
+            val = cpu_lduw_code(env, s->pc);
             s->pc += 2;
-            level = cpu_ldub_code(cpu_single_env, s->pc++);
+            level = cpu_ldub_code(env, s->pc++);
             gen_enter(s, val, level);
         }
         break;
@@ -5195,11 +5199,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             ot = OT_BYTE;
         else
             ot = dflag + OT_WORD;
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
 
         /* generate a generic store */
-        gen_ldst_modrm(s, modrm, ot, reg, 1);
+        gen_ldst_modrm(env, s, modrm, ot, reg, 1);
         break;
     case 0xc6:
     case 0xc7: /* mov Ev, Iv */
@@ -5207,13 +5211,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             ot = OT_BYTE;
         else
             ot = dflag + OT_WORD;
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         if (mod != 3) {
             s->rip_offset = insn_const_size(ot);
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
         }
-        val = insn_get(s, ot);
+        val = insn_get(env, s, ot);
         gen_op_movl_T0_im(val);
         if (mod != 3)
             gen_op_st_T0_A0(ot + s->mem_index);
@@ -5226,18 +5230,18 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             ot = OT_BYTE;
         else
             ot = OT_WORD + dflag;
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
 
-        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
+        gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
         gen_op_mov_reg_T0(ot, reg);
         break;
     case 0x8e: /* mov seg, Gv */
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         reg = (modrm >> 3) & 7;
         if (reg >= 6 || reg == R_CS)
             goto illegal_op;
-        gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
+        gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
         gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
         if (reg == R_SS) {
             /* if reg == SS, inhibit interrupts/trace */
@@ -5253,7 +5257,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         }
         break;
     case 0x8c: /* mov Gv, seg */
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         reg = (modrm >> 3) & 7;
         mod = (modrm >> 6) & 3;
         if (reg >= 6)
@@ -5263,7 +5267,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             ot = OT_WORD + dflag;
         else
             ot = OT_WORD;
-        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
+        gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
         break;
 
     case 0x1b6: /* movzbS Gv, Eb */
@@ -5276,7 +5280,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             d_ot = dflag + OT_WORD;
             /* ot is the size of source */
             ot = (b & 1) + OT_BYTE;
-            modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+            modrm = cpu_ldub_code(env, s->pc++);
             reg = ((modrm >> 3) & 7) | rex_r;
             mod = (modrm >> 6) & 3;
             rm = (modrm & 7) | REX_B(s);
@@ -5300,7 +5304,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                 }
                 gen_op_mov_reg_T0(d_ot, reg);
             } else {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 if (b & 8) {
                     gen_op_lds_T0_A0(ot + s->mem_index);
                 } else {
@@ -5313,7 +5317,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
 
     case 0x8d: /* lea */
         ot = dflag + OT_WORD;
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         if (mod == 3)
             goto illegal_op;
@@ -5322,7 +5326,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         s->override = -1;
         val = s->addseg;
         s->addseg = 0;
-        gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+        gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
         s->addseg = val;
         gen_op_mov_reg_A0(ot - OT_WORD, reg);
         break;
@@ -5340,16 +5344,16 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                 ot = dflag + OT_WORD;
 #ifdef TARGET_X86_64
             if (s->aflag == 2) {
-                offset_addr = cpu_ldq_code(cpu_single_env, s->pc);
+                offset_addr = cpu_ldq_code(env, s->pc);
                 s->pc += 8;
                 gen_op_movq_A0_im(offset_addr);
             } else
 #endif
             {
                 if (s->aflag) {
-                    offset_addr = insn_get(s, OT_LONG);
+                    offset_addr = insn_get(env, s, OT_LONG);
                 } else {
-                    offset_addr = insn_get(s, OT_WORD);
+                    offset_addr = insn_get(env, s, OT_WORD);
                 }
                 gen_op_movl_A0_im(offset_addr);
             }
@@ -5387,7 +5391,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         gen_op_mov_reg_T0(OT_BYTE, R_EAX);
         break;
     case 0xb0 ... 0xb7: /* mov R, Ib */
-        val = insn_get(s, OT_BYTE);
+        val = insn_get(env, s, OT_BYTE);
         gen_op_movl_T0_im(val);
         gen_op_mov_reg_T0(OT_BYTE, (b & 7) | REX_B(s));
         break;
@@ -5396,7 +5400,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         if (dflag == 2) {
             uint64_t tmp;
             /* 64 bit case */
-            tmp = cpu_ldq_code(cpu_single_env, s->pc);
+            tmp = cpu_ldq_code(env, s->pc);
             s->pc += 8;
             reg = (b & 7) | REX_B(s);
             gen_movtl_T0_im(tmp);
@@ -5405,7 +5409,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
 #endif
         {
             ot = dflag ? OT_LONG : OT_WORD;
-            val = insn_get(s, ot);
+            val = insn_get(env, s, ot);
             reg = (b & 7) | REX_B(s);
             gen_op_movl_T0_im(val);
             gen_op_mov_reg_T0(ot, reg);
@@ -5424,7 +5428,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             ot = OT_BYTE;
         else
             ot = dflag + OT_WORD;
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         mod = (modrm >> 6) & 3;
         if (mod == 3) {
@@ -5435,7 +5439,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             gen_op_mov_reg_T0(ot, rm);
             gen_op_mov_reg_T1(ot, reg);
         } else {
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             gen_op_mov_TN_reg(ot, 0, reg);
             /* for xchg, lock is implicit */
             if (!(prefixes & PREFIX_LOCK))
@@ -5467,12 +5471,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         op = R_GS;
     do_lxx:
         ot = dflag ? OT_LONG : OT_WORD;
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         mod = (modrm >> 6) & 3;
         if (mod == 3)
             goto illegal_op;
-        gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+        gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
         gen_op_ld_T1_A0(ot + s->mem_index);
         gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
         /* load the segment first to handle exceptions properly */
@@ -5499,7 +5503,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             else
                 ot = dflag + OT_WORD;
 
-            modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+            modrm = cpu_ldub_code(env, s->pc++);
             mod = (modrm >> 6) & 3;
             op = (modrm >> 3) & 7;
 
@@ -5507,7 +5511,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                 if (shift == 2) {
                     s->rip_offset = 1;
                 }
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 opreg = OR_TMP0;
             } else {
                 opreg = (modrm & 7) | REX_B(s);
@@ -5518,7 +5522,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                 gen_shift(s, op, ot, opreg, OR_ECX);
             } else {
                 if (shift == 2) {
-                    shift = cpu_ldub_code(cpu_single_env, s->pc++);
+                    shift = cpu_ldub_code(env, s->pc++);
                 }
                 gen_shifti(s, op, ot, opreg, shift);
             }
@@ -5552,12 +5556,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         shift = 0;
     do_shiftd:
         ot = dflag + OT_WORD;
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         rm = (modrm & 7) | REX_B(s);
         reg = ((modrm >> 3) & 7) | rex_r;
         if (mod != 3) {
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             opreg = OR_TMP0;
         } else {
             opreg = rm;
@@ -5565,7 +5569,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         gen_op_mov_TN_reg(ot, 1, reg);
 
         if (shift) {
-            val = cpu_ldub_code(cpu_single_env, s->pc++);
+            val = cpu_ldub_code(env, s->pc++);
             tcg_gen_movi_tl(cpu_T3, val);
         } else {
             tcg_gen_mov_tl(cpu_T3, cpu_regs[R_ECX]);
@@ -5582,13 +5586,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
             break;
         }
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         rm = modrm & 7;
         op = ((b & 7) << 3) | ((modrm >> 3) & 7);
         if (mod != 3) {
             /* memory op */
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             switch(op) {
             case 0x00 ... 0x07: /* fxxxs */
             case 0x10 ... 0x17: /* fixxxl */
@@ -6213,7 +6217,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             ot = OT_BYTE;
         else
             ot = dflag ? OT_LONG : OT_WORD;
-        val = cpu_ldub_code(cpu_single_env, s->pc++);
+        val = cpu_ldub_code(env, s->pc++);
         gen_op_movl_T0_im(val);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
@@ -6233,7 +6237,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             ot = OT_BYTE;
         else
             ot = dflag ? OT_LONG : OT_WORD;
-        val = cpu_ldub_code(cpu_single_env, s->pc++);
+        val = cpu_ldub_code(env, s->pc++);
         gen_op_movl_T0_im(val);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      svm_is_rep(prefixes));
@@ -6295,7 +6299,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         /************************/
         /* control */
     case 0xc2: /* ret im */
-        val = cpu_ldsw_code(cpu_single_env, s->pc);
+        val = cpu_ldsw_code(env, s->pc);
         s->pc += 2;
         gen_pop_T0(s);
         if (CODE64(s) && s->dflag)
@@ -6315,7 +6319,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         gen_eob(s);
         break;
     case 0xca: /* lret im */
-        val = cpu_ldsw_code(cpu_single_env, s->pc);
+        val = cpu_ldsw_code(env, s->pc);
         s->pc += 2;
     do_lret:
         if (s->pe && !s->vm86) {
@@ -6371,9 +6375,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
     case 0xe8: /* call im */
         {
             if (dflag)
-                tval = (int32_t)insn_get(s, OT_LONG);
+                tval = (int32_t)insn_get(env, s, OT_LONG);
             else
-                tval = (int16_t)insn_get(s, OT_WORD);
+                tval = (int16_t)insn_get(env, s, OT_WORD);
             next_eip = s->pc - s->cs_base;
             tval += next_eip;
             if (s->dflag == 0)
@@ -6392,8 +6396,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             if (CODE64(s))
                 goto illegal_op;
             ot = dflag ? OT_LONG : OT_WORD;
-            offset = insn_get(s, ot);
-            selector = insn_get(s, OT_WORD);
+            offset = insn_get(env, s, ot);
+            selector = insn_get(env, s, OT_WORD);
 
             gen_op_movl_T0_im(selector);
             gen_op_movl_T1_imu(offset);
@@ -6401,9 +6405,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         goto do_lcall;
     case 0xe9: /* jmp im */
         if (dflag)
-            tval = (int32_t)insn_get(s, OT_LONG);
+            tval = (int32_t)insn_get(env, s, OT_LONG);
         else
-            tval = (int16_t)insn_get(s, OT_WORD);
+            tval = (int16_t)insn_get(env, s, OT_WORD);
         tval += s->pc - s->cs_base;
         if (s->dflag == 0)
             tval &= 0xffff;
@@ -6418,28 +6422,28 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             if (CODE64(s))
                 goto illegal_op;
             ot = dflag ? OT_LONG : OT_WORD;
-            offset = insn_get(s, ot);
-            selector = insn_get(s, OT_WORD);
+            offset = insn_get(env, s, ot);
+            selector = insn_get(env, s, OT_WORD);
 
             gen_op_movl_T0_im(selector);
             gen_op_movl_T1_imu(offset);
         }
         goto do_ljmp;
     case 0xeb: /* jmp Jb */
-        tval = (int8_t)insn_get(s, OT_BYTE);
+        tval = (int8_t)insn_get(env, s, OT_BYTE);
         tval += s->pc - s->cs_base;
         if (s->dflag == 0)
             tval &= 0xffff;
         gen_jmp(s, tval);
         break;
     case 0x70 ... 0x7f: /* jcc Jb */
-        tval = (int8_t)insn_get(s, OT_BYTE);
+        tval = (int8_t)insn_get(env, s, OT_BYTE);
         goto do_jcc;
     case 0x180 ... 0x18f: /* jcc Jv */
         if (dflag) {
-            tval = (int32_t)insn_get(s, OT_LONG);
+            tval = (int32_t)insn_get(env, s, OT_LONG);
         } else {
-            tval = (int16_t)insn_get(s, OT_WORD);
+            tval = (int16_t)insn_get(env, s, OT_WORD);
         }
     do_jcc:
         next_eip = s->pc - s->cs_base;
@@ -6450,9 +6454,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         break;
 
     case 0x190 ... 0x19f: /* setcc Gv */
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         gen_setcc(s, b);
-        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
+        gen_ldst_modrm(env, s, modrm, OT_BYTE, OR_TMP0, 1);
         break;
     case 0x140 ... 0x14f: /* cmov Gv, Ev */
         {
@@ -6460,12 +6464,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             TCGv t0;
 
             ot = dflag + OT_WORD;
-            modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+            modrm = cpu_ldub_code(env, s->pc++);
             reg = ((modrm >> 3) & 7) | rex_r;
             mod = (modrm >> 6) & 3;
             t0 = tcg_temp_local_new();
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_op_ld_v(ot + s->mem_index, t0, cpu_A0);
             } else {
                 rm = (modrm & 7) | REX_B(s);
@@ -6618,19 +6622,19 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         /* bit operations */
     case 0x1ba: /* bt/bts/btr/btc Gv, im */
         ot = dflag + OT_WORD;
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         op = (modrm >> 3) & 7;
         mod = (modrm >> 6) & 3;
         rm = (modrm & 7) | REX_B(s);
         if (mod != 3) {
             s->rip_offset = 1;
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             gen_op_ld_T0_A0(ot + s->mem_index);
         } else {
             gen_op_mov_TN_reg(ot, 0, rm);
         }
         /* load shift */
-        val = cpu_ldub_code(cpu_single_env, s->pc++);
+        val = cpu_ldub_code(env, s->pc++);
         gen_op_movl_T1_im(val);
         if (op < 4)
             goto illegal_op;
@@ -6649,13 +6653,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         op = 3;
     do_btx:
         ot = dflag + OT_WORD;
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         mod = (modrm >> 6) & 3;
         rm = (modrm & 7) | REX_B(s);
         gen_op_mov_TN_reg(OT_LONG, 1, reg);
         if (mod != 3) {
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             /* specific case: we need to add a displacement */
             gen_exts(ot, cpu_T[1]);
             tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot);
@@ -6710,9 +6714,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             TCGv t0;
 
             ot = dflag + OT_WORD;
-            modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+            modrm = cpu_ldub_code(env, s->pc++);
             reg = ((modrm >> 3) & 7) | rex_r;
-            gen_ldst_modrm(s,modrm, ot, OR_TMP0, 0);
+            gen_ldst_modrm(env, s,modrm, ot, OR_TMP0, 0);
             gen_extu(ot, cpu_T[0]);
             t0 = tcg_temp_local_new();
             tcg_gen_mov_tl(t0, cpu_T[0]);
@@ -6782,7 +6786,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
     case 0xd4: /* aam */
         if (CODE64(s))
             goto illegal_op;
-        val = cpu_ldub_code(cpu_single_env, s->pc++);
+        val = cpu_ldub_code(env, s->pc++);
         if (val == 0) {
             gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
         } else {
@@ -6793,7 +6797,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
     case 0xd5: /* aad */
         if (CODE64(s))
             goto illegal_op;
-        val = cpu_ldub_code(cpu_single_env, s->pc++);
+        val = cpu_ldub_code(env, s->pc++);
         gen_helper_aad(cpu_env, tcg_const_i32(val));
         s->cc_op = CC_OP_LOGICB;
         break;
@@ -6827,7 +6831,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
         break;
     case 0xcd: /* int N */
-        val = cpu_ldub_code(cpu_single_env, s->pc++);
+        val = cpu_ldub_code(env, s->pc++);
         if (s->vm86 && s->iopl != 3) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
         } else {
@@ -6849,7 +6853,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         gen_debug(s, pc_start - s->cs_base);
 #else
         /* start debug */
-        tb_flush(cpu_single_env);
+        tb_flush(env);
         cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
 #endif
         break;
@@ -6897,13 +6901,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         if (CODE64(s))
             goto illegal_op;
         ot = dflag ? OT_LONG : OT_WORD;
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         reg = (modrm >> 3) & 7;
         mod = (modrm >> 6) & 3;
         if (mod == 3)
             goto illegal_op;
         gen_op_mov_TN_reg(ot, 0, reg);
-        gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+        gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
         gen_jmp_im(pc_start - s->cs_base);
         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
         if (ot == OT_WORD) {
@@ -6944,7 +6948,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         {
             int l1, l2, l3;
 
-            tval = (int8_t)insn_get(s, OT_BYTE);
+            tval = (int8_t)insn_get(env, s, OT_BYTE);
             next_eip = s->pc - s->cs_base;
             tval += next_eip;
             if (s->dflag == 0)
@@ -7024,7 +7028,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         break;
     case 0x134: /* sysenter */
         /* For Intel SYSENTER is valid on 64-bit */
-        if (CODE64(s) && cpu_single_env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
+        if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
             goto illegal_op;
         if (!s->pe) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
@@ -7037,7 +7041,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         break;
     case 0x135: /* sysexit */
         /* For Intel SYSEXIT is valid on 64-bit */
-        if (CODE64(s) && cpu_single_env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
+        if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
             goto illegal_op;
         if (!s->pe) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
@@ -7088,7 +7092,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         }
         break;
     case 0x100:
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         op = (modrm >> 3) & 7;
         switch(op) {
@@ -7100,7 +7104,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             ot = OT_WORD;
             if (mod == 3)
                 ot += s->dflag;
-            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
+            gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
             break;
         case 2: /* lldt */
             if (!s->pe || s->vm86)
@@ -7109,7 +7113,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
             } else {
                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
-                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
+                gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
                 gen_jmp_im(pc_start - s->cs_base);
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
@@ -7123,7 +7127,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             ot = OT_WORD;
             if (mod == 3)
                 ot += s->dflag;
-            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
+            gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
             break;
         case 3: /* ltr */
             if (!s->pe || s->vm86)
@@ -7132,7 +7136,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
             } else {
                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
-                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
+                gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
                 gen_jmp_im(pc_start - s->cs_base);
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                 gen_helper_ltr(cpu_env, cpu_tmp2_i32);
@@ -7142,7 +7146,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         case 5: /* verw */
             if (!s->pe || s->vm86)
                 goto illegal_op;
-            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
+            gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
             if (s->cc_op != CC_OP_DYNAMIC)
                 gen_op_set_cc_op(s->cc_op);
             if (op == 4) {
@@ -7157,7 +7161,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         }
         break;
     case 0x101:
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         op = (modrm >> 3) & 7;
         rm = modrm & 7;
@@ -7166,7 +7170,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             if (mod == 3)
                 goto illegal_op;
             gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit));
             gen_op_st_T0_A0(OT_WORD + s->mem_index);
             gen_add_A0_im(s, 2);
@@ -7230,7 +7234,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                 }
             } else { /* sidt */
                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit));
                 gen_op_st_T0_A0(OT_WORD + s->mem_index);
                 gen_add_A0_im(s, 2);
@@ -7332,7 +7336,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             } else {
                 gen_svm_check_intercept(s, pc_start,
                                         op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_op_ld_T1_A0(OT_WORD + s->mem_index);
                 gen_add_A0_im(s, 2);
                 gen_op_ld_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
@@ -7354,14 +7358,14 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
 #else
             tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]));
 #endif
-            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
+            gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 1);
             break;
         case 6: /* lmsw */
             if (s->cpl != 0) {
                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
             } else {
                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
-                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
+                gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
                 gen_helper_lmsw(cpu_env, cpu_T[0]);
                 gen_jmp_im(s->pc - s->cs_base);
                 gen_eob(s);
@@ -7375,7 +7379,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                     if (s->cc_op != CC_OP_DYNAMIC)
                         gen_op_set_cc_op(s->cc_op);
                     gen_jmp_im(pc_start - s->cs_base);
-                    gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                    gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                     gen_helper_invlpg(cpu_env, cpu_A0);
                     gen_jmp_im(s->pc - s->cs_base);
                     gen_eob(s);
@@ -7442,7 +7446,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             /* d_ot is the size of destination */
             d_ot = dflag + OT_WORD;
 
-            modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+            modrm = cpu_ldub_code(env, s->pc++);
             reg = ((modrm >> 3) & 7) | rex_r;
             mod = (modrm >> 6) & 3;
             rm = (modrm & 7) | REX_B(s);
@@ -7454,7 +7458,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                     tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
                 gen_op_mov_reg_T0(d_ot, reg);
             } else {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 if (d_ot == OT_QUAD) {
                     gen_op_lds_T0_A0(OT_LONG + s->mem_index);
                 } else {
@@ -7474,12 +7478,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             t1 = tcg_temp_local_new();
             t2 = tcg_temp_local_new();
             ot = OT_WORD;
-            modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+            modrm = cpu_ldub_code(env, s->pc++);
             reg = (modrm >> 3) & 7;
             mod = (modrm >> 6) & 3;
             rm = modrm & 7;
             if (mod != 3) {
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
                 gen_op_ld_v(ot + s->mem_index, t0, cpu_A0);
                 a0 = tcg_temp_local_new();
                 tcg_gen_mov_tl(a0, cpu_A0);
@@ -7522,9 +7526,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             if (!s->pe || s->vm86)
                 goto illegal_op;
             ot = dflag ? OT_LONG : OT_WORD;
-            modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+            modrm = cpu_ldub_code(env, s->pc++);
             reg = ((modrm >> 3) & 7) | rex_r;
-            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
+            gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
             t0 = tcg_temp_local_new();
             if (s->cc_op != CC_OP_DYNAMIC)
                 gen_op_set_cc_op(s->cc_op);
@@ -7543,7 +7547,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         }
         break;
     case 0x118:
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         op = (modrm >> 3) & 7;
         switch(op) {
@@ -7553,24 +7557,24 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         case 3: /* prefetchnt0 */
             if (mod == 3)
                 goto illegal_op;
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             /* nothing more to do */
             break;
         default: /* nop (multi byte) */
-            gen_nop_modrm(s, modrm);
+            gen_nop_modrm(env, s, modrm);
             break;
         }
         break;
     case 0x119 ... 0x11f: /* nop (multi byte) */
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
-        gen_nop_modrm(s, modrm);
+        modrm = cpu_ldub_code(env, s->pc++);
+        gen_nop_modrm(env, s, modrm);
         break;
     case 0x120: /* mov reg, crN */
     case 0x122: /* mov crN, reg */
         if (s->cpl != 0) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
         } else {
-            modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+            modrm = cpu_ldub_code(env, s->pc++);
             /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
              * AMD documentation (24594.pdf) and testing of
              * intel 386 and 486 processors all show that the mod bits
@@ -7616,7 +7620,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         if (s->cpl != 0) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
         } else {
-            modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+            modrm = cpu_ldub_code(env, s->pc++);
             /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
              * AMD documentation (24594.pdf) and testing of
              * intel 386 and 486 processors all show that the mod bits
@@ -7660,16 +7664,16 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         if (!(s->cpuid_features & CPUID_SSE2))
             goto illegal_op;
         ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         if (mod == 3)
             goto illegal_op;
         reg = ((modrm >> 3) & 7) | rex_r;
         /* generate a generic store */
-        gen_ldst_modrm(s, modrm, ot, reg, 1);
+        gen_ldst_modrm(env, s, modrm, ot, reg, 1);
         break;
     case 0x1ae:
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         op = (modrm >> 3) & 7;
         switch(op) {
@@ -7681,7 +7685,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
                 break;
             }
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             if (s->cc_op != CC_OP_DYNAMIC)
                 gen_op_set_cc_op(s->cc_op);
             gen_jmp_im(pc_start - s->cs_base);
@@ -7695,7 +7699,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
                 break;
             }
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             if (s->cc_op != CC_OP_DYNAMIC)
                 gen_op_set_cc_op(s->cc_op);
             gen_jmp_im(pc_start - s->cs_base);
@@ -7711,7 +7715,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
                 mod == 3)
                 goto illegal_op;
-            gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             if (op == 2) {
                 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
@@ -7736,7 +7740,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                 /* clflush */
                 if (!(s->cpuid_features & CPUID_CLFLUSH))
                     goto illegal_op;
-                gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
             }
             break;
         default:
@@ -7744,11 +7748,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         }
         break;
     case 0x10d: /* 3DNow! prefetch(w) */
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         if (mod == 3)
             goto illegal_op;
-        gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
+        gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr);
         /* ignore for now */
         break;
     case 0x1aa: /* rsm */
@@ -7767,7 +7771,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
             goto illegal_op;
 
-        modrm = cpu_ldub_code(cpu_single_env, s->pc++);
+        modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
 
         if (s->prefix & PREFIX_DATA)
@@ -7777,7 +7781,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         else
             ot = OT_QUAD;
 
-        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
+        gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
         gen_helper_popcnt(cpu_T[0], cpu_env, cpu_T[0], tcg_const_i32(ot));
         gen_op_mov_reg_T0(ot, reg);
 
@@ -7794,7 +7798,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
     case 0x1c2:
     case 0x1c4 ... 0x1c6:
     case 0x1d0 ... 0x1fe:
-        gen_sse(s, b, pc_start, rex_r);
+        gen_sse(env, s, b, pc_start, rex_r);
         break;
     default:
         goto illegal_op;
@@ -7994,7 +7998,7 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
             gen_io_start();
 
-        pc_ptr = disas_insn(dc, pc_ptr);
+        pc_ptr = disas_insn(env, dc, pc_ptr);
         num_insns++;
         /* stop translation if indicated */
         if (dc->is_jmp)

From 7c2c3ea3fd9e108a1c174a5db021ac1d33b1a22d Mon Sep 17 00:00:00 2001
From: Eric Johnson 
Date: Fri, 9 Nov 2012 19:40:51 -0800
Subject: [PATCH 1569/2270] target-mips: Fix seg fault for LUI when
 MIPS_DEBUG_DISAS==1.

The call to gen_logic_imm for OPC_LUI passes -1 for rs.  This
causes the MIPS_DEBUG statement to seg fault due to the deference
of regnames[rs].  This patch fixes that.

Signed-off-by: Eric Johnson 
Signed-off-by: Aurelien Jarno 
(aurel32: replaced static string formating by a static string)
---
 target-mips/translate.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index df92781b2c..f6fc0c27ae 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -2013,7 +2013,6 @@ static void gen_logic_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
                           int rt, int rs, int16_t imm)
 {
     target_ulong uimm;
-    const char *opn = "imm logic";
 
     if (rt == 0) {
         /* If no destination, treat it as a NOP. */
@@ -2027,29 +2026,34 @@ static void gen_logic_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
             tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
         else
             tcg_gen_movi_tl(cpu_gpr[rt], 0);
-        opn = "andi";
+        MIPS_DEBUG("andi %s, %s, " TARGET_FMT_lx, regnames[rt],
+                   regnames[rs], uimm);
         break;
     case OPC_ORI:
         if (rs != 0)
             tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
         else
             tcg_gen_movi_tl(cpu_gpr[rt], uimm);
-        opn = "ori";
+        MIPS_DEBUG("ori %s, %s, " TARGET_FMT_lx, regnames[rt],
+                   regnames[rs], uimm);
         break;
     case OPC_XORI:
         if (likely(rs != 0))
             tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
         else
             tcg_gen_movi_tl(cpu_gpr[rt], uimm);
-        opn = "xori";
+        MIPS_DEBUG("xori %s, %s, " TARGET_FMT_lx, regnames[rt],
+                   regnames[rs], uimm);
         break;
     case OPC_LUI:
         tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
-        opn = "lui";
+        MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
+        break;
+
+    default:
+        MIPS_DEBUG("Unknown logical immediate opcode %08x", opc);
         break;
     }
-    (void)opn; /* avoid a compiler warning */
-    MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
 }
 
 /* Set on less than with immediate operand */

From 3c5645fab3c4b65d0cffbe1aaafc787e4be63d0f Mon Sep 17 00:00:00 2001
From: Kirill Batuzov 
Date: Wed, 7 Nov 2012 15:26:38 +0400
Subject: [PATCH 1570/2270] tcg: properly check that op's output needs to be
 synced to memory

Fix typo introduced in b3a1be87bac3a6aaa59bb88c1410f170dc9b22d5.

Reported-by: Ruslan Savchenko 
Signed-off-by: Kirill Batuzov 
Signed-off-by: Aurelien Jarno 
---
 tcg/tcg.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 42052dba7b..35fba50c7f 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1337,8 +1337,8 @@ static void tcg_liveness_analysis(TCGContext *s)
                the low part.  The result can be optimized to a simple
                add or sub.  This happens often for x86_64 guest when the
                cpu mode is set to 32 bit.  */
-            if (dead_temps[args[1]] && !mem_temps[1]) {
-                if (dead_temps[args[0]] && !mem_temps[0]) {
+            if (dead_temps[args[1]] && !mem_temps[args[1]]) {
+                if (dead_temps[args[0]] && !mem_temps[args[0]]) {
                     goto do_remove;
                 }
                 /* Create the single operation plus nop.  */
@@ -1363,8 +1363,8 @@ static void tcg_liveness_analysis(TCGContext *s)
             nb_iargs = 2;
             nb_oargs = 2;
             /* Likewise, test for the high part of the operation dead.  */
-            if (dead_temps[args[1]] && !mem_temps[1]) {
-                if (dead_temps[args[0]] && !mem_temps[0]) {
+            if (dead_temps[args[1]] && !mem_temps[args[1]]) {
+                if (dead_temps[args[0]] && !mem_temps[args[0]]) {
                     goto do_remove;
                 }
                 gen_opc_buf[op_index] = op = INDEX_op_mul_i32;

From 7e7f4a0efc81258213dc34aeeaade36b0f59d076 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Sat, 3 Nov 2012 18:06:26 +0100
Subject: [PATCH 1571/2270] qemu-nbd: initialize main loop before block layer

qemu-nbd was broken because they initialized the block layer while
qemu_aio_context was still NULL.

Signed-off-by: Paolo Bonzini 
---
 qemu-nbd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/qemu-nbd.c b/qemu-nbd.c
index 15bcd08123..80f08d8464 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -539,6 +539,7 @@ int main(int argc, char **argv)
         snprintf(sockpath, 128, SOCKET_PATH, basename(device));
     }
 
+    qemu_init_main_loop();
     bdrv_init();
     atexit(bdrv_close_all);
 
@@ -584,7 +585,6 @@ int main(int argc, char **argv)
         memset(&client_thread, 0, sizeof(client_thread));
     }
 
-    qemu_init_main_loop();
     qemu_set_fd_handler2(fd, nbd_can_accept, nbd_accept, NULL,
                          (void *)(uintptr_t)fd);
 

From d04b0bbbc9cf61446e5c2e159eef50891009fd9c Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Sun, 4 Nov 2012 12:56:39 +0100
Subject: [PATCH 1572/2270] nbd: accept relative path to Unix socket

Adding the "is_unix" member now will simplify the parsing of NBD URIs.

Signed-off-by: Paolo Bonzini 
---
 block/nbd.c | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/block/nbd.c b/block/nbd.c
index 2bce47bf7a..48bbecacaf 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -55,7 +55,6 @@ typedef struct BDRVNBDState {
     uint32_t nbdflags;
     off_t size;
     size_t blocksize;
-    char *export_name; /* An NBD server may export several devices */
 
     CoMutex send_mutex;
     CoMutex free_sema;
@@ -65,13 +64,12 @@ typedef struct BDRVNBDState {
     Coroutine *recv_coroutine[MAX_NBD_REQUESTS];
     struct nbd_reply reply;
 
-    /* If it begins with  '/', this is a UNIX domain socket. Otherwise,
-     * it's a string of the form :port
-     */
+    int is_unix;
     char *host_spec;
+    char *export_name; /* An NBD server may export several devices */
 } BDRVNBDState;
 
-static int nbd_config(BDRVNBDState *s, const char *filename, int flags)
+static int nbd_config(BDRVNBDState *s, const char *filename)
 {
     char *file;
     char *export_name;
@@ -98,11 +96,10 @@ static int nbd_config(BDRVNBDState *s, const char *filename, int flags)
 
     /* are we a UNIX or TCP socket? */
     if (strstart(host_spec, "unix:", &unixpath)) {
-        if (unixpath[0] != '/') { /* We demand  an absolute path*/
-            goto out;
-        }
+        s->is_unix = true;
         s->host_spec = g_strdup(unixpath);
     } else {
+        s->is_unix = false;
         s->host_spec = g_strdup(host_spec);
     }
 
@@ -262,7 +259,7 @@ static int nbd_establish_connection(BlockDriverState *bs)
     off_t size;
     size_t blocksize;
 
-    if (s->host_spec[0] == '/') {
+    if (s->is_unix) {
         sock = unix_socket_outgoing(s->host_spec);
     } else {
         sock = tcp_socket_outgoing_spec(s->host_spec);
@@ -320,7 +317,7 @@ static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
     qemu_co_mutex_init(&s->free_sema);
 
     /* Pop the config into our state object. Exit if invalid. */
-    result = nbd_config(s, filename, flags);
+    result = nbd_config(s, filename);
     if (result != 0) {
         return result;
     }

From 1d7d2a9d2191c34bd1ad69b420db9b47faa3fb8c Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Sun, 4 Nov 2012 13:04:24 +0100
Subject: [PATCH 1573/2270] nbd: accept URIs

The URI syntax is consistent with the Gluster syntax.  Export names
are specified in the path, preceded by one or more (otherwise unused)
slashes.

Signed-off-by: Paolo Bonzini 
---
 block/nbd.c   | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 qemu-doc.texi | 25 ++++++++-----
 2 files changed, 114 insertions(+), 9 deletions(-)

diff --git a/block/nbd.c b/block/nbd.c
index 48bbecacaf..e87c248175 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -28,6 +28,7 @@
 
 #include "qemu-common.h"
 #include "nbd.h"
+#include "uri.h"
 #include "block_int.h"
 #include "module.h"
 #include "qemu_socket.h"
@@ -69,6 +70,69 @@ typedef struct BDRVNBDState {
     char *export_name; /* An NBD server may export several devices */
 } BDRVNBDState;
 
+static int nbd_parse_uri(BDRVNBDState *s, const char *filename)
+{
+    URI *uri;
+    const char *p;
+    QueryParams *qp = NULL;
+    int ret = 0;
+
+    uri = uri_parse(filename);
+    if (!uri) {
+        return -EINVAL;
+    }
+
+    /* transport */
+    if (!strcmp(uri->scheme, "nbd")) {
+        s->is_unix = false;
+    } else if (!strcmp(uri->scheme, "nbd+tcp")) {
+        s->is_unix = false;
+    } else if (!strcmp(uri->scheme, "nbd+unix")) {
+        s->is_unix = true;
+    } else {
+        ret = -EINVAL;
+        goto out;
+    }
+
+    p = uri->path ? uri->path : "/";
+    p += strspn(p, "/");
+    if (p[0]) {
+        s->export_name = g_strdup(p);
+    }
+
+    qp = query_params_parse(uri->query);
+    if (qp->n > 1 || (s->is_unix && !qp->n) || (!s->is_unix && qp->n)) {
+        ret = -EINVAL;
+        goto out;
+    }
+
+    if (s->is_unix) {
+        /* nbd+unix:///export?socket=path */
+        if (uri->server || uri->port || strcmp(qp->p[0].name, "socket")) {
+            ret = -EINVAL;
+            goto out;
+        }
+        s->host_spec = g_strdup(qp->p[0].value);
+    } else {
+        /* nbd[+tcp]://host:port/export */
+        if (!uri->server) {
+            ret = -EINVAL;
+            goto out;
+        }
+        if (!uri->port) {
+            uri->port = NBD_DEFAULT_PORT;
+        }
+        s->host_spec = g_strdup_printf("%s:%d", uri->server, uri->port);
+    }
+
+out:
+    if (qp) {
+        query_params_free(qp);
+    }
+    uri_free(uri);
+    return ret;
+}
+
 static int nbd_config(BDRVNBDState *s, const char *filename)
 {
     char *file;
@@ -77,6 +141,10 @@ static int nbd_config(BDRVNBDState *s, const char *filename)
     const char *unixpath;
     int err = -EINVAL;
 
+    if (strstr(filename, "://")) {
+        return nbd_parse_uri(s, filename);
+    }
+
     file = g_strdup(filename);
 
     export_name = strstr(file, EN_OPTSTR);
@@ -495,6 +563,33 @@ static int64_t nbd_getlength(BlockDriverState *bs)
 
 static BlockDriver bdrv_nbd = {
     .format_name         = "nbd",
+    .protocol_name       = "nbd",
+    .instance_size       = sizeof(BDRVNBDState),
+    .bdrv_file_open      = nbd_open,
+    .bdrv_co_readv       = nbd_co_readv,
+    .bdrv_co_writev      = nbd_co_writev,
+    .bdrv_close          = nbd_close,
+    .bdrv_co_flush_to_os = nbd_co_flush,
+    .bdrv_co_discard     = nbd_co_discard,
+    .bdrv_getlength      = nbd_getlength,
+};
+
+static BlockDriver bdrv_nbd_tcp = {
+    .format_name         = "nbd",
+    .protocol_name       = "nbd+tcp",
+    .instance_size       = sizeof(BDRVNBDState),
+    .bdrv_file_open      = nbd_open,
+    .bdrv_co_readv       = nbd_co_readv,
+    .bdrv_co_writev      = nbd_co_writev,
+    .bdrv_close          = nbd_close,
+    .bdrv_co_flush_to_os = nbd_co_flush,
+    .bdrv_co_discard     = nbd_co_discard,
+    .bdrv_getlength      = nbd_getlength,
+};
+
+static BlockDriver bdrv_nbd_unix = {
+    .format_name         = "nbd",
+    .protocol_name       = "nbd+unix",
     .instance_size       = sizeof(BDRVNBDState),
     .bdrv_file_open      = nbd_open,
     .bdrv_co_readv       = nbd_co_readv,
@@ -503,12 +598,13 @@ static BlockDriver bdrv_nbd = {
     .bdrv_co_flush_to_os = nbd_co_flush,
     .bdrv_co_discard     = nbd_co_discard,
     .bdrv_getlength      = nbd_getlength,
-    .protocol_name       = "nbd",
 };
 
 static void bdrv_nbd_init(void)
 {
     bdrv_register(&bdrv_nbd);
+    bdrv_register(&bdrv_nbd_tcp);
+    bdrv_register(&bdrv_nbd_unix);
 }
 
 block_init(bdrv_nbd_init);
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 35cabbcb9e..d8fb2de10e 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -610,14 +610,14 @@ QEMU can access directly to block device exported using the Network Block Device
 protocol.
 
 @example
-qemu-system-i386 linux.img -hdb nbd:my_nbd_server.mydomain.org:1024
+qemu-system-i386 linux.img -hdb nbd://my_nbd_server.mydomain.org:1024/
 @end example
 
 If the NBD server is located on the same host, you can use an unix socket instead
 of an inet socket:
 
 @example
-qemu-system-i386 linux.img -hdb nbd:unix:/tmp/my_socket
+qemu-system-i386 linux.img -hdb nbd+unix://?socket=/tmp/my_socket
 @end example
 
 In this case, the block device must be exported using qemu-nbd:
@@ -631,17 +631,26 @@ The use of qemu-nbd allows to share a disk between several guests:
 qemu-nbd --socket=/tmp/my_socket --share=2 my_disk.qcow2
 @end example
 
+@noindent
 and then you can use it with two guests:
 @example
-qemu-system-i386 linux1.img -hdb nbd:unix:/tmp/my_socket
-qemu-system-i386 linux2.img -hdb nbd:unix:/tmp/my_socket
+qemu-system-i386 linux1.img -hdb nbd+unix://?socket=/tmp/my_socket
+qemu-system-i386 linux2.img -hdb nbd+unix://?socket=/tmp/my_socket
 @end example
 
-If the nbd-server uses named exports (since NBD 2.9.18), you must use the
-"exportname" option:
+If the nbd-server uses named exports (supported since NBD 2.9.18, or with QEMU's
+own embedded NBD server), you must specify an export name in the URI:
 @example
-qemu-system-i386 -cdrom nbd:localhost:exportname=debian-500-ppc-netinst
-qemu-system-i386 -cdrom nbd:localhost:exportname=openSUSE-11.1-ppc-netinst
+qemu-system-i386 -cdrom nbd://localhost/debian-500-ppc-netinst
+qemu-system-i386 -cdrom nbd://localhost/openSUSE-11.1-ppc-netinst
+@end example
+
+The URI syntax for NBD is supported since QEMU 1.3.  An alternative syntax is
+also available.  Here are some example of the older syntax:
+@example
+qemu-system-i386 linux.img -hdb nbd:my_nbd_server.mydomain.org:1024
+qemu-system-i386 linux2.img -hdb nbd:unix:/tmp/my_socket
+qemu-system-i386 -cdrom nbd:localhost:10809:exportname=debian-500-ppc-netinst
 @end example
 
 @node disk_images_sheepdog

From fc6467eaf22f974620b5dd046afca04e619f9be9 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Mon, 12 Nov 2012 14:12:54 +0100
Subject: [PATCH 1574/2270] nbd: fix nbd_server_stop crash when no server was
 running

This failed on the new assertion of qemu_set_fd_handler2:

qemu-system-x86_64: /home/pbonzini/work/upstream/qemu/iohandler.c:60: qemu_set_fd_handler2: Assertion `fd >= 0' failed.

Signed-off-by: Paolo Bonzini 
---
 blockdev-nbd.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index 8031813071..274fba6e46 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -113,7 +113,9 @@ void qmp_nbd_server_stop(Error **errp)
         nbd_close_notifier(&cn->n, nbd_export_get_blockdev(cn->exp));
     }
 
-    qemu_set_fd_handler2(server_fd, NULL, NULL, NULL, NULL);
-    close(server_fd);
-    server_fd = -1;
+    if (server_fd != -1) {
+        qemu_set_fd_handler2(server_fd, NULL, NULL, NULL, NULL);
+        close(server_fd);
+        server_fd = -1;
+    }
 }

From e644473445177671ec408dfdec705cf931657998 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Sun, 4 Nov 2012 12:43:37 +0100
Subject: [PATCH 1575/2270] nbd: force read-only export for read-only devices

This is the desired behavior for HMP, but it is a better choice for QMP as well.

Signed-off-by: Paolo Bonzini 
---
 blockdev-nbd.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index 274fba6e46..e362572279 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -93,6 +93,13 @@ void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
         return;
     }
 
+    if (!has_writable) {
+        writable = true;
+    }
+    if (bdrv_is_read_only(bs)) {
+        writable = false;
+    }
+
     exp = nbd_export_new(bs, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY,
                          nbd_server_put_ref);
 

From 17b6be4a7fc9db4f4c56908bab137d4c491471f1 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Mon, 12 Nov 2012 14:25:17 +0100
Subject: [PATCH 1576/2270] nbd: disallow nbd-server-add before
 nbd-server-start

It works nicely with the QMP commands, but it adds useless complication
with HMP.  In particular, see the following:

    (qemu) nbd_server_add -w scsi0-hd0
    (qemu) nbd_server_start -a localhost:10809
    NBD server already exporting device scsi0-hd0

Signed-off-by: Paolo Bonzini 
---
 blockdev-nbd.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index e362572279..d1721a3e26 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -82,6 +82,11 @@ void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
     NBDExport *exp;
     NBDCloseNotifier *n;
 
+    if (server_fd == -1) {
+        error_setg(errp, "NBD server not running");
+        return;
+    }
+
     if (nbd_export_find(device)) {
         error_setg(errp, "NBD server already exporting device '%s'", device);
         return;

From 4057725f35abe00ea371f85c6e27dd25eafd9ddf Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Thu, 23 Aug 2012 11:53:04 +0200
Subject: [PATCH 1577/2270] hmp: add NBD server commands

Signed-off-by: Paolo Bonzini 
---
 hmp-commands.hx | 45 +++++++++++++++++++++++++++++
 hmp.c           | 76 +++++++++++++++++++++++++++++++++++++++++++++++++
 hmp.h           |  3 ++
 3 files changed, 124 insertions(+)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index f916385c0a..b74ef75c39 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1310,6 +1310,51 @@ Remove all matches from the access control list, and set the default
 policy back to @code{deny}.
 ETEXI
 
+    {
+        .name       = "nbd_server_start",
+        .args_type  = "all:-a,writable:-w,uri:s",
+        .params     = "nbd_server_start [-a] [-w] host:port",
+        .help       = "serve block devices on the given host and port",
+        .mhandler.cmd = hmp_nbd_server_start,
+    },
+STEXI
+@item nbd_server_start @var{host}:@var{port}
+@findex nbd_server_start
+Start an NBD server on the given host and/or port.  If the @option{-a}
+option is included, all of the virtual machine's block devices that
+have an inserted media on them are automatically exported; in this case,
+the @option{-w} option makes the devices writable too.
+ETEXI
+
+    {
+        .name       = "nbd_server_add",
+        .args_type  = "writable:-w,device:B",
+        .params     = "nbd_server_add [-w] device",
+        .help       = "export a block device via NBD",
+        .mhandler.cmd = hmp_nbd_server_add,
+    },
+STEXI
+@item nbd_server_add @var{device}
+@findex nbd_server_add
+Export a block device through QEMU's NBD server, which must be started
+beforehand with @command{nbd_server_start}.  The @option{-w} option makes the
+exported device writable too.
+ETEXI
+
+    {
+        .name       = "nbd_server_stop",
+        .args_type  = "",
+        .params     = "nbd_server_stop",
+        .help       = "stop serving block devices using the NBD protocol",
+        .mhandler.cmd = hmp_nbd_server_stop,
+    },
+STEXI
+@item nbd_server_stop
+@findex nbd_server_stop
+Stop the QEMU embedded NBD server.
+ETEXI
+
+
 #if defined(TARGET_I386)
 
     {
diff --git a/hmp.c b/hmp.c
index 895a343dc3..180ba2bfd9 100644
--- a/hmp.c
+++ b/hmp.c
@@ -18,6 +18,7 @@
 #include "qemu-option.h"
 #include "qemu-timer.h"
 #include "qmp-commands.h"
+#include "qemu_socket.h"
 #include "monitor.h"
 #include "console.h"
 
@@ -1259,3 +1260,78 @@ void hmp_screen_dump(Monitor *mon, const QDict *qdict)
     qmp_screendump(filename, &err);
     hmp_handle_error(mon, &err);
 }
+
+void hmp_nbd_server_start(Monitor *mon, const QDict *qdict)
+{
+    const char *uri = qdict_get_str(qdict, "uri");
+    int writable = qdict_get_try_bool(qdict, "writable", 0);
+    int all = qdict_get_try_bool(qdict, "all", 0);
+    Error *local_err = NULL;
+    BlockInfoList *block_list, *info;
+    SocketAddress *addr;
+
+    if (writable && !all) {
+        error_setg(&local_err, "-w only valid together with -a");
+        goto exit;
+    }
+
+    /* First check if the address is valid and start the server.  */
+    addr = socket_parse(uri, &local_err);
+    if (local_err != NULL) {
+        goto exit;
+    }
+
+    qmp_nbd_server_start(addr, &local_err);
+    qapi_free_SocketAddress(addr);
+    if (local_err != NULL) {
+        goto exit;
+    }
+
+    if (!all) {
+        return;
+    }
+
+    /* Then try adding all block devices.  If one fails, close all and
+     * exit.
+     */
+    block_list = qmp_query_block(NULL);
+
+    for (info = block_list; info; info = info->next) {
+        if (!info->value->has_inserted) {
+            continue;
+        }
+
+        qmp_nbd_server_add(info->value->device, true, writable, &local_err);
+
+        if (local_err != NULL) {
+            qmp_nbd_server_stop(NULL);
+            break;
+        }
+    }
+
+    qapi_free_BlockInfoList(block_list);
+
+exit:
+    hmp_handle_error(mon, &local_err);
+}
+
+void hmp_nbd_server_add(Monitor *mon, const QDict *qdict)
+{
+    const char *device = qdict_get_str(qdict, "device");
+    int writable = qdict_get_try_bool(qdict, "writable", 0);
+    Error *local_err = NULL;
+
+    qmp_nbd_server_add(device, true, writable, &local_err);
+
+    if (local_err != NULL) {
+        hmp_handle_error(mon, &local_err);
+    }
+}
+
+void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict)
+{
+    Error *errp = NULL;
+
+    qmp_nbd_server_stop(&errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index 34eb2b36f3..0ab03be982 100644
--- a/hmp.h
+++ b/hmp.h
@@ -77,5 +77,8 @@ void hmp_getfd(Monitor *mon, const QDict *qdict);
 void hmp_closefd(Monitor *mon, const QDict *qdict);
 void hmp_send_key(Monitor *mon, const QDict *qdict);
 void hmp_screen_dump(Monitor *mon, const QDict *qdict);
+void hmp_nbd_server_start(Monitor *mon, const QDict *qdict);
+void hmp_nbd_server_add(Monitor *mon, const QDict *qdict);
+void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict);
 
 #endif

From c8dcb531bcd37a4a81d2cc08a89fcd19c34348f9 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Wed, 10 Oct 2012 12:18:03 +0200
Subject: [PATCH 1578/2270] scsi: do not return short responses for emulated
 commands

The inquiry command, for the case of VPD=1, was returning short
responses; the number of returned bytes was just the number of bytes
in the request, without padding to the specified allocation length
with zero bytes.  This is usually harmless, but it is a violation
of the SCSI specification.

To fix this, always pad with zero bytes to r->cmd.xfer in
scsi_disk_emulate_command, and return at most r->buflen bytes
(the size of the buffer for command data) rather than at most
buflen bytes (the number of bytes that was filled in).

Before this patch, "strace sg_inq -p0x83 /dev/sda" would report a
non-zero resid value.  After this patch, it reports resid=0.

Signed-off-by: Paolo Bonzini 
---
 hw/scsi-disk.c | 34 ++++++++++++++++++----------------
 1 file changed, 18 insertions(+), 16 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 1b0afa6352..098558d372 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -652,7 +652,6 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
     if (buflen > SCSI_MAX_INQUIRY_LEN) {
         buflen = SCSI_MAX_INQUIRY_LEN;
     }
-    memset(outbuf, 0, buflen);
 
     outbuf[0] = s->qdev.type & 0x1f;
     outbuf[1] = (s->features & (1 << SCSI_DISK_F_REMOVABLE)) ? 0x80 : 0;
@@ -1596,24 +1595,26 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
         break;
     }
 
+    /*
+     * FIXME: we shouldn't return anything bigger than 4k, but the code
+     * requires the buffer to be as big as req->cmd.xfer in several
+     * places.  So, do not allow CDBs with a very large ALLOCATION
+     * LENGTH.  The real fix would be to modify scsi_read_data and
+     * dma_buf_read, so that they return data beyond the buflen
+     * as all zeros.
+     */
+    if (req->cmd.xfer > 65536) {
+        goto illegal_request;
+    }
+    r->buflen = MAX(4096, req->cmd.xfer);
+
     if (!r->iov.iov_base) {
-        /*
-         * FIXME: we shouldn't return anything bigger than 4k, but the code
-         * requires the buffer to be as big as req->cmd.xfer in several
-         * places.  So, do not allow CDBs with a very large ALLOCATION
-         * LENGTH.  The real fix would be to modify scsi_read_data and
-         * dma_buf_read, so that they return data beyond the buflen
-         * as all zeros.
-         */
-        if (req->cmd.xfer > 65536) {
-            goto illegal_request;
-        }
-        r->buflen = MAX(4096, req->cmd.xfer);
         r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
     }
 
     buflen = req->cmd.xfer;
     outbuf = r->iov.iov_base;
+    memset(outbuf, 0, r->buflen);
     switch (req->cmd.buf[0]) {
     case TEST_UNIT_READY:
         assert(!s->tray_open && bdrv_is_inserted(s->qdev.conf.bs));
@@ -1694,12 +1695,14 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
         outbuf[5] = 0;
         outbuf[6] = s->qdev.blocksize >> 8;
         outbuf[7] = 0;
-        buflen = 8;
         break;
     case REQUEST_SENSE:
         /* Just return "NO SENSE".  */
         buflen = scsi_build_sense(NULL, 0, outbuf, r->buflen,
                                   (req->cmd.buf[1] & 1) == 0);
+        if (buflen < 0) {
+            goto illegal_request;
+        }
         break;
     case MECHANISM_STATUS:
         buflen = scsi_emulate_mechanism_status(s, outbuf);
@@ -1770,7 +1773,6 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
             }
 
             /* Protection, exponent and lowest lba field left blank. */
-            buflen = req->cmd.xfer;
             break;
         }
         DPRINTF("Unsupported Service Action In\n");
@@ -1827,7 +1829,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
         return 0;
     }
     assert(!r->req.aiocb);
-    r->iov.iov_len = MIN(buflen, req->cmd.xfer);
+    r->iov.iov_len = MIN(r->buflen, req->cmd.xfer);
     if (r->iov.iov_len == 0) {
         scsi_req_complete(&r->req, GOOD);
     }

From cd41a671b370a3dd603963432d2b02f1e5990fb7 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Mon, 8 Oct 2012 16:50:51 +0200
Subject: [PATCH 1579/2270] virtio-scsi: factor checks for
 VIRTIO_SCSI_S_DRIVER_OK when reporting events

Suggested by Laszlo Ersek.

Signed-off-by: Paolo Bonzini 
---
 hw/virtio-scsi.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index b54c7895fc..30d3f8aca7 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -596,6 +596,10 @@ static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
     VirtIOSCSIEvent *evt;
     int in_size;
 
+    if (!(s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+        return;
+    }
+
     if (!req) {
         s->events_dropped = true;
         return;
@@ -648,7 +652,6 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
     VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
 
     if (((s->vdev.guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) &&
-        (s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK) &&
         dev->type != TYPE_ROM) {
         virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE,
                                sense.asc | (sense.ascq << 8));
@@ -659,8 +662,7 @@ static void virtio_scsi_hotplug(SCSIBus *bus, SCSIDevice *dev)
 {
     VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
 
-    if (((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) &&
-        (s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+    if ((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
         virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET,
                                VIRTIO_SCSI_EVT_RESET_RESCAN);
     }

From b5232e904fadac8af239306719be4a554f9e9263 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Mon, 8 Oct 2012 16:46:54 +0200
Subject: [PATCH 1580/2270] scsi: remove superfluous call to scsi_device_set_ua

Suggested by Laszlo Ersek.

Signed-off-by: Paolo Bonzini 
---
 hw/scsi-disk.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 098558d372..d15f891974 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1964,7 +1964,6 @@ static void scsi_disk_resize_cb(void *opaque)
      * direct-access devices.
      */
     if (s->qdev.type == TYPE_DISK) {
-        scsi_device_set_ua(&s->qdev, SENSE_CODE(CAPACITY_CHANGED));
         scsi_device_report_change(&s->qdev, SENSE_CODE(CAPACITY_CHANGED));
     }
 }

From 346a3017ec8d5ac4a6961d823f1e576867dc35ef Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Fri, 28 Sep 2012 16:43:41 +0200
Subject: [PATCH 1581/2270] megasas: do not include block_int.h

Signed-off-by: Paolo Bonzini 
---
 hw/megasas.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/megasas.c b/hw/megasas.c
index 7a2036eb76..b845ea7b48 100644
--- a/hw/megasas.c
+++ b/hw/megasas.c
@@ -25,7 +25,6 @@
 #include "iov.h"
 #include "scsi.h"
 #include "scsi-defs.h"
-#include "block_int.h"
 #include "trace.h"
 
 #include "mfi.h"

From accfeb2dd32ece73350b06cee1b2403f47e86fe3 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Wed, 31 Oct 2012 17:14:41 +0100
Subject: [PATCH 1582/2270] scsi-disk: flush cache after disabling it

SBC says that "if an application client changes the WCE bit from one to
zero via a MODE SELECT command, then the device server shall write
any data in volatile cache to non-volatile medium before completing
the command".

Signed-off-by: Paolo Bonzini 
---
 hw/scsi-disk.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index d15f891974..49b5686a92 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1387,6 +1387,7 @@ invalid_param_len:
 
 static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf)
 {
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
     uint8_t *p = inbuf;
     int cmd = r->req.cmd.buf[0];
     int len = r->req.cmd.xfer;
@@ -1423,6 +1424,14 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf)
             return;
         }
     }
+    if (!bdrv_enable_write_cache(s->qdev.conf.bs)) {
+        /* The request is used as the AIO opaque value, so add a ref.  */
+        scsi_req_ref(&r->req);
+        bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
+        r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r);
+        return;
+    }
+
     scsi_req_complete(&r->req, GOOD);
     return;
 

From 4003e24fce1df84a2e8c992376ed2c294816c33c Mon Sep 17 00:00:00 2001
From: Hannes Reinecke 
Date: Mon, 12 Nov 2012 15:42:42 +0100
Subject: [PATCH 1583/2270] megasas: Correct target/lun mapping

The structure to reference a logical drive has an unused field,
which can be used to carry the lun ID. This enabled seabios to
establish the proper target/LUN mapping.

Cc: Paolo Bonzini 
Cc: Gerd Hoffmann 
Signed-off-by: Hannes Reinecke 
Signed-off-by: Paolo Bonzini 
---
 hw/megasas.c | 1 +
 hw/mfi.h     | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/megasas.c b/hw/megasas.c
index b845ea7b48..291ff40403 100644
--- a/hw/megasas.c
+++ b/hw/megasas.c
@@ -1079,6 +1079,7 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd)
         /* Logical device size is in blocks */
         bdrv_get_geometry(conf->bs, &ld_size);
         info.ld_list[num_ld_disks].ld.v.target_id = sdev->id;
+        info.ld_list[num_ld_disks].ld.v.lun_id = sdev->lun;
         info.ld_list[num_ld_disks].state = MFI_LD_STATE_OPTIMAL;
         info.ld_list[num_ld_disks].size = cpu_to_le64(ld_size);
         num_ld_disks++;
diff --git a/hw/mfi.h b/hw/mfi.h
index 436b6906b1..cd8355badf 100644
--- a/hw/mfi.h
+++ b/hw/mfi.h
@@ -1085,7 +1085,7 @@ struct mfi_pd_list {
 union mfi_ld_ref {
     struct {
         uint8_t target_id;
-        uint8_t reserved;
+        uint8_t lun_id;
         uint16_t seq;
     } v;
     uint32_t ref;

From 9e11908f12f92e31ea94dc2a4c962c836cba9f2a Mon Sep 17 00:00:00 2001
From: Peter Maydell 
Date: Mon, 29 Oct 2012 11:34:32 +1000
Subject: [PATCH 1584/2270] dma: Define dma_context_memory and use in
 sysbus-ohci

Define a new global dma_context_memory which is a DMAContext corresponding
to the global address_space_memory AddressSpace. This can be used by
sysbus peripherals like sysbus-ohci which need to do DMA.

In particular, use it in the sysbus-ohci device, which fixes a
segfault when attempting to use that device.

Signed-off-by: Peter Maydell 
Reviewed-by: Peter Crosthwaite 
---
 dma.h             | 5 +++++
 exec.c            | 5 +++++
 hw/usb/hcd-ohci.c | 2 +-
 3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/dma.h b/dma.h
index 91ccdb5eac..eedf878383 100644
--- a/dma.h
+++ b/dma.h
@@ -68,6 +68,11 @@ struct DMAContext {
     DMAUnmapFunc *unmap;
 };
 
+/* A global DMA context corresponding to the address_space_memory
+ * AddressSpace, for sysbus devices which do DMA.
+ */
+extern DMAContext dma_context_memory;
+
 static inline void dma_barrier(DMAContext *dma, DMADirection dir)
 {
     /*
diff --git a/exec.c b/exec.c
index af94f9cd86..8435de0bd2 100644
--- a/exec.c
+++ b/exec.c
@@ -34,6 +34,7 @@
 #include "hw/xen.h"
 #include "qemu-timer.h"
 #include "memory.h"
+#include "dma.h"
 #include "exec-memory.h"
 #if defined(CONFIG_USER_ONLY)
 #include 
@@ -103,6 +104,7 @@ static MemoryRegion *system_io;
 
 AddressSpace address_space_io;
 AddressSpace address_space_memory;
+DMAContext dma_context_memory;
 
 MemoryRegion io_mem_ram, io_mem_rom, io_mem_unassigned, io_mem_notdirty;
 static MemoryRegion io_mem_subpage_ram;
@@ -3294,6 +3296,9 @@ static void memory_map_init(void)
     memory_listener_register(&core_memory_listener, &address_space_memory);
     memory_listener_register(&io_memory_listener, &address_space_io);
     memory_listener_register(&tcg_memory_listener, &address_space_memory);
+
+    dma_context_init(&dma_context_memory, &address_space_memory,
+                     NULL, NULL, NULL);
 }
 
 MemoryRegion *get_system_memory(void)
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 7571e9e44a..efae0322ee 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -1851,7 +1851,7 @@ static int ohci_init_pxa(SysBusDevice *dev)
 
     /* Cannot fail as we pass NULL for masterbus */
     usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0,
-                  NULL);
+                  &dma_context_memory);
     sysbus_init_irq(dev, &s->ohci.irq);
     sysbus_init_mmio(dev, &s->ohci.mem);
 

From dd72fdd06268860a24f9f3828efade547ee2e2a9 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Tue, 30 Oct 2012 17:31:43 +0100
Subject: [PATCH 1585/2270] virtio-scsi: use dma_context_memory

Until address_space_rw was introduced, NULL was accepted as a
placeholder for DMA with no IOMMU (to address_space_memory).

This does not work anymore, and dma_context_memory needs to
be specified explicitly.

Signed-off-by: Paolo Bonzini 
---
 hw/virtio-scsi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 30d3f8aca7..7d546f6ca7 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -204,7 +204,7 @@ static void virtio_scsi_bad_req(void)
 static void qemu_sgl_init_external(QEMUSGList *qsgl, struct iovec *sg,
                                    hwaddr *addr, int num)
 {
-    memset(qsgl, 0, sizeof(*qsgl));
+    qemu_sglist_init(qsgl, num, &dma_context_memory);
     while (num--) {
         qemu_sglist_add(qsgl, *(addr++), (sg++)->iov_len);
     }

From f5022a135e4309a54d433c69b2a056756b2d0d6b Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Mon, 12 Nov 2012 13:30:10 +0100
Subject: [PATCH 1586/2270] aio: fix aio_ctx_prepare with idle bottom halves

Commit ed2aec4867f0d5f5de496bb765347b5d0cfe113d changed the return
value of aio_ctx_prepare from false to true when only idle bottom
halves are available.  This broke PC old-style DMA, which uses them.
Fix this by making aio_ctx_prepare return true only when non-idle
bottom halves are scheduled to run.

Reported-by: malc 
Signed-off-by: Paolo Bonzini 
Signed-off-by: malc 
---
 async.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/async.c b/async.c
index 04f9dcbb4d..3f0e8f367c 100644
--- a/async.c
+++ b/async.c
@@ -122,11 +122,9 @@ aio_ctx_prepare(GSource *source, gint    *timeout)
 {
     AioContext *ctx = (AioContext *) source;
     QEMUBH *bh;
-    bool scheduled = false;
 
     for (bh = ctx->first_bh; bh; bh = bh->next) {
         if (!bh->deleted && bh->scheduled) {
-            scheduled = true;
             if (bh->idle) {
                 /* idle bottom halves will be polled at least
                  * every 10ms */
@@ -135,12 +133,12 @@ aio_ctx_prepare(GSource *source, gint    *timeout)
                 /* non-idle bottom halves will be executed
                  * immediately */
                 *timeout = 0;
-                break;
+                return true;
             }
         }
     }
 
-    return scheduled;
+    return false;
 }
 
 static gboolean

From c8969eded252058e90e91f12f75f32aceae46ec9 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Tue, 13 Nov 2012 10:34:17 +0100
Subject: [PATCH 1587/2270] nbd: fixes to read-only handling

We do not need BLKROSET if the kernel supports setting flags.
Also, always do BLKROSET even for a read-write export, otherwise
the read-only state remains "sticky" after the invocation of
"qemu-nbd -r".

Signed-off-by: Paolo Bonzini 
---
 nbd.c | 23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/nbd.c b/nbd.c
index cec5a9449b..97a5914e0f 100644
--- a/nbd.c
+++ b/nbd.c
@@ -596,24 +596,23 @@ int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize)
         return -serrno;
     }
 
-    if (flags & NBD_FLAG_READ_ONLY) {
-        int read_only = 1;
-        TRACE("Setting readonly attribute");
+    if (ioctl(fd, NBD_SET_FLAGS, flags) < 0) {
+        if (errno == ENOTTY) {
+            int read_only = (flags & NBD_FLAG_READ_ONLY) != 0;
+            TRACE("Setting readonly attribute");
 
-        if (ioctl(fd, BLKROSET, (unsigned long) &read_only) < 0) {
+            if (ioctl(fd, BLKROSET, (unsigned long) &read_only) < 0) {
+                int serrno = errno;
+                LOG("Failed setting read-only attribute");
+                return -serrno;
+            }
+        } else {
             int serrno = errno;
-            LOG("Failed setting read-only attribute");
+            LOG("Failed setting flags");
             return -serrno;
         }
     }
 
-    if (ioctl(fd, NBD_SET_FLAGS, flags) < 0
-        && errno != ENOTTY) {
-        int serrno = errno;
-        LOG("Failed setting flags");
-        return -serrno;
-    }
-
     TRACE("Negotiation ended");
 
     return 0;

From 716b8e4dd2f7a1674bf77d49fd50139cb577e70f Mon Sep 17 00:00:00 2001
From: Alex Williamson 
Date: Tue, 13 Nov 2012 12:27:40 -0700
Subject: [PATCH 1588/2270] linux-headers: Update to 3.7-rc5

update-linux-headers.sh script run against Linux tag v3.7-rc5

Signed-off-by: Alex Williamson 
---
 linux-headers/asm-powerpc/kvm_para.h |  6 +++---
 linux-headers/asm-s390/kvm_para.h    |  8 +-------
 linux-headers/asm-x86/kvm.h          | 17 +++++++++++++++++
 linux-headers/linux/kvm.h            | 25 +++++++++++++++++++++----
 linux-headers/linux/kvm_para.h       |  6 +++---
 linux-headers/linux/vfio.h           |  6 +++---
 linux-headers/linux/virtio_config.h  |  6 +++---
 linux-headers/linux/virtio_ring.h    |  6 +++---
 8 files changed, 54 insertions(+), 26 deletions(-)

diff --git a/linux-headers/asm-powerpc/kvm_para.h b/linux-headers/asm-powerpc/kvm_para.h
index c047a84000..5e04383a1d 100644
--- a/linux-headers/asm-powerpc/kvm_para.h
+++ b/linux-headers/asm-powerpc/kvm_para.h
@@ -17,8 +17,8 @@
  * Authors: Hollis Blanchard 
  */
 
-#ifndef __POWERPC_KVM_PARA_H__
-#define __POWERPC_KVM_PARA_H__
+#ifndef _UAPI__POWERPC_KVM_PARA_H__
+#define _UAPI__POWERPC_KVM_PARA_H__
 
 #include 
 
@@ -87,4 +87,4 @@ struct kvm_vcpu_arch_shared {
 #define KVM_MAGIC_FEAT_MAS0_TO_SPRG7	(1 << 1)
 
 
-#endif /* __POWERPC_KVM_PARA_H__ */
+#endif /* _UAPI__POWERPC_KVM_PARA_H__ */
diff --git a/linux-headers/asm-s390/kvm_para.h b/linux-headers/asm-s390/kvm_para.h
index 870051f645..ff1f4e7b30 100644
--- a/linux-headers/asm-s390/kvm_para.h
+++ b/linux-headers/asm-s390/kvm_para.h
@@ -1,5 +1,5 @@
 /*
- * definition for paravirtual devices on s390
+ * User API definitions for paravirtual devices on s390
  *
  * Copyright IBM Corp. 2008
  *
@@ -9,9 +9,3 @@
  *
  *    Author(s): Christian Borntraeger 
  */
-
-#ifndef __S390_KVM_PARA_H
-#define __S390_KVM_PARA_H
-
-
-#endif /* __S390_KVM_PARA_H */
diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h
index 246617efd6..a65ec29e6f 100644
--- a/linux-headers/asm-x86/kvm.h
+++ b/linux-headers/asm-x86/kvm.h
@@ -9,6 +9,22 @@
 #include 
 #include 
 
+#define DE_VECTOR 0
+#define DB_VECTOR 1
+#define BP_VECTOR 3
+#define OF_VECTOR 4
+#define BR_VECTOR 5
+#define UD_VECTOR 6
+#define NM_VECTOR 7
+#define DF_VECTOR 8
+#define TS_VECTOR 10
+#define NP_VECTOR 11
+#define SS_VECTOR 12
+#define GP_VECTOR 13
+#define PF_VECTOR 14
+#define MF_VECTOR 16
+#define MC_VECTOR 18
+
 /* Select x86 specific features in  */
 #define __KVM_HAVE_PIT
 #define __KVM_HAVE_IOAPIC
@@ -25,6 +41,7 @@
 #define __KVM_HAVE_DEBUGREGS
 #define __KVM_HAVE_XSAVE
 #define __KVM_HAVE_XCRS
+#define __KVM_HAVE_READONLY_MEM
 
 /* Architectural interrupt line count. */
 #define KVM_NR_INTERRUPTS 256
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 4b9e575dd0..81d2feb7ab 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -101,9 +101,13 @@ struct kvm_userspace_memory_region {
 	__u64 userspace_addr; /* start of the userspace allocated memory */
 };
 
-/* for kvm_memory_region::flags */
-#define KVM_MEM_LOG_DIRTY_PAGES  1UL
-#define KVM_MEMSLOT_INVALID      (1UL << 1)
+/*
+ * The bit 0 ~ bit 15 of kvm_memory_region::flags are visible for userspace,
+ * other bits are reserved for kvm internal use which are defined in
+ * include/linux/kvm_host.h.
+ */
+#define KVM_MEM_LOG_DIRTY_PAGES	(1UL << 0)
+#define KVM_MEM_READONLY	(1UL << 1)
 
 /* for KVM_IRQ_LINE */
 struct kvm_irq_level {
@@ -618,6 +622,10 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_PPC_GET_SMMU_INFO 78
 #define KVM_CAP_S390_COW 79
 #define KVM_CAP_PPC_ALLOC_HTAB 80
+#ifdef __KVM_HAVE_READONLY_MEM
+#define KVM_CAP_READONLY_MEM 81
+#endif
+#define KVM_CAP_IRQFD_RESAMPLE 82
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -683,12 +691,21 @@ struct kvm_xen_hvm_config {
 #endif
 
 #define KVM_IRQFD_FLAG_DEASSIGN (1 << 0)
+/*
+ * Available with KVM_CAP_IRQFD_RESAMPLE
+ *
+ * KVM_IRQFD_FLAG_RESAMPLE indicates resamplefd is valid and specifies
+ * the irqfd to operate in resampling mode for level triggered interrupt
+ * emlation.  See Documentation/virtual/kvm/api.txt.
+ */
+#define KVM_IRQFD_FLAG_RESAMPLE (1 << 1)
 
 struct kvm_irqfd {
 	__u32 fd;
 	__u32 gsi;
 	__u32 flags;
-	__u8  pad[20];
+	__u32 resamplefd;
+	__u8  pad[16];
 };
 
 struct kvm_clock_data {
diff --git a/linux-headers/linux/kvm_para.h b/linux-headers/linux/kvm_para.h
index 7bdcf93c1d..cea2c5c72d 100644
--- a/linux-headers/linux/kvm_para.h
+++ b/linux-headers/linux/kvm_para.h
@@ -1,5 +1,5 @@
-#ifndef __LINUX_KVM_PARA_H
-#define __LINUX_KVM_PARA_H
+#ifndef _UAPI__LINUX_KVM_PARA_H
+#define _UAPI__LINUX_KVM_PARA_H
 
 /*
  * This header file provides a method for making a hypercall to the host
@@ -25,4 +25,4 @@
  */
 #include 
 
-#endif /* __LINUX_KVM_PARA_H */
+#endif /* _UAPI__LINUX_KVM_PARA_H */
diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index f787b727a9..4758d1bfcf 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -8,8 +8,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#ifndef VFIO_H
-#define VFIO_H
+#ifndef _UAPIVFIO_H
+#define _UAPIVFIO_H
 
 #include 
 #include 
@@ -365,4 +365,4 @@ struct vfio_iommu_type1_dma_unmap {
 
 #define VFIO_IOMMU_UNMAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 14)
 
-#endif /* VFIO_H */
+#endif /* _UAPIVFIO_H */
diff --git a/linux-headers/linux/virtio_config.h b/linux-headers/linux/virtio_config.h
index 4f51d8f3af..b7cda390fd 100644
--- a/linux-headers/linux/virtio_config.h
+++ b/linux-headers/linux/virtio_config.h
@@ -1,5 +1,5 @@
-#ifndef _LINUX_VIRTIO_CONFIG_H
-#define _LINUX_VIRTIO_CONFIG_H
+#ifndef _UAPI_LINUX_VIRTIO_CONFIG_H
+#define _UAPI_LINUX_VIRTIO_CONFIG_H
 /* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so
  * anyone can use the definitions to implement compatible drivers/servers.
  *
@@ -51,4 +51,4 @@
  * suppressed them? */
 #define VIRTIO_F_NOTIFY_ON_EMPTY	24
 
-#endif /* _LINUX_VIRTIO_CONFIG_H */
+#endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */
diff --git a/linux-headers/linux/virtio_ring.h b/linux-headers/linux/virtio_ring.h
index 1b333e2536..921694a084 100644
--- a/linux-headers/linux/virtio_ring.h
+++ b/linux-headers/linux/virtio_ring.h
@@ -1,5 +1,5 @@
-#ifndef _LINUX_VIRTIO_RING_H
-#define _LINUX_VIRTIO_RING_H
+#ifndef _UAPI_LINUX_VIRTIO_RING_H
+#define _UAPI_LINUX_VIRTIO_RING_H
 /* An interface for efficient virtio implementation, currently for use by KVM
  * and lguest, but hopefully others soon.  Do NOT change this since it will
  * break existing servers and clients.
@@ -160,4 +160,4 @@ static __inline__ int vring_need_event(__u16 event_idx, __u16 new_idx, __u16 old
 	return (__u16)(new_idx - event_idx - 1) < (__u16)(new_idx - old);
 }
 
-#endif /* _LINUX_VIRTIO_RING_H */
+#endif /* _UAPI_LINUX_VIRTIO_RING_H */

From e1d1e5867d0bd54c4fc51ec2cddc701258314db0 Mon Sep 17 00:00:00 2001
From: Alex Williamson 
Date: Tue, 13 Nov 2012 12:27:40 -0700
Subject: [PATCH 1589/2270] vfio-pci: Add KVM INTx acceleration

This makes use of the new level irqfd support enabling bypass of qemu
userspace both on INTx injection and unmask.  This significantly
boosts the performance of devices making use of legacy interrupts (ex.
~60% better netperf TCP_RR scores for an e1000e assigned to a Linux
guest and booted with pci=nomsi).  This also avoids flipping mmaps on
and off to simulate EOIs, so greatly improves performance of device
access in addition to interrupt latency.

Signed-off-by: Alex Williamson 
---
 hw/vfio_pci.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 186 insertions(+)

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index 0473ae866c..4e9c2ddbf9 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -185,6 +185,21 @@ static void vfio_unmask_intx(VFIODevice *vdev)
     ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
 }
 
+#ifdef CONFIG_KVM /* Unused outside of CONFIG_KVM code */
+static void vfio_mask_intx(VFIODevice *vdev)
+{
+    struct vfio_irq_set irq_set = {
+        .argsz = sizeof(irq_set),
+        .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_MASK,
+        .index = VFIO_PCI_INTX_IRQ_INDEX,
+        .start = 0,
+        .count = 1,
+    };
+
+    ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
+}
+#endif
+
 /*
  * Disabling BAR mmaping can be slow, but toggling it around INTx can
  * also be a huge overhead.  We try to get the best of both worlds by
@@ -248,6 +263,161 @@ static void vfio_eoi(VFIODevice *vdev)
     vfio_unmask_intx(vdev);
 }
 
+static void vfio_enable_intx_kvm(VFIODevice *vdev)
+{
+#ifdef CONFIG_KVM
+    struct kvm_irqfd irqfd = {
+        .fd = event_notifier_get_fd(&vdev->intx.interrupt),
+        .gsi = vdev->intx.route.irq,
+        .flags = KVM_IRQFD_FLAG_RESAMPLE,
+    };
+    struct vfio_irq_set *irq_set;
+    int ret, argsz;
+    int32_t *pfd;
+
+    if (!kvm_irqchip_in_kernel() ||
+        vdev->intx.route.mode != PCI_INTX_ENABLED ||
+        !kvm_check_extension(kvm_state, KVM_CAP_IRQFD_RESAMPLE)) {
+        return;
+    }
+
+    /* Get to a known interrupt state */
+    qemu_set_fd_handler(irqfd.fd, NULL, NULL, vdev);
+    vfio_mask_intx(vdev);
+    vdev->intx.pending = false;
+    qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
+
+    /* Get an eventfd for resample/unmask */
+    if (event_notifier_init(&vdev->intx.unmask, 0)) {
+        error_report("vfio: Error: event_notifier_init failed eoi\n");
+        goto fail;
+    }
+
+    /* KVM triggers it, VFIO listens for it */
+    irqfd.resamplefd = event_notifier_get_fd(&vdev->intx.unmask);
+
+    if (kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd)) {
+        error_report("vfio: Error: Failed to setup resample irqfd: %m\n");
+        goto fail_irqfd;
+    }
+
+    argsz = sizeof(*irq_set) + sizeof(*pfd);
+
+    irq_set = g_malloc0(argsz);
+    irq_set->argsz = argsz;
+    irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_UNMASK;
+    irq_set->index = VFIO_PCI_INTX_IRQ_INDEX;
+    irq_set->start = 0;
+    irq_set->count = 1;
+    pfd = (int32_t *)&irq_set->data;
+
+    *pfd = irqfd.resamplefd;
+
+    ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
+    g_free(irq_set);
+    if (ret) {
+        error_report("vfio: Error: Failed to setup INTx unmask fd: %m\n");
+        goto fail_vfio;
+    }
+
+    /* Let'em rip */
+    vfio_unmask_intx(vdev);
+
+    vdev->intx.kvm_accel = true;
+
+    DPRINTF("%s(%04x:%02x:%02x.%x) KVM INTx accel enabled\n",
+            __func__, vdev->host.domain, vdev->host.bus,
+            vdev->host.slot, vdev->host.function);
+
+    return;
+
+fail_vfio:
+    irqfd.flags = KVM_IRQFD_FLAG_DEASSIGN;
+    kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd);
+fail_irqfd:
+    event_notifier_cleanup(&vdev->intx.unmask);
+fail:
+    qemu_set_fd_handler(irqfd.fd, vfio_intx_interrupt, NULL, vdev);
+    vfio_unmask_intx(vdev);
+#endif
+}
+
+static void vfio_disable_intx_kvm(VFIODevice *vdev)
+{
+#ifdef CONFIG_KVM
+    struct kvm_irqfd irqfd = {
+        .fd = event_notifier_get_fd(&vdev->intx.interrupt),
+        .gsi = vdev->intx.route.irq,
+        .flags = KVM_IRQFD_FLAG_DEASSIGN,
+    };
+
+    if (!vdev->intx.kvm_accel) {
+        return;
+    }
+
+    /*
+     * Get to a known state, hardware masked, QEMU ready to accept new
+     * interrupts, QEMU IRQ de-asserted.
+     */
+    vfio_mask_intx(vdev);
+    vdev->intx.pending = false;
+    qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
+
+    /* Tell KVM to stop listening for an INTx irqfd */
+    if (kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd)) {
+        error_report("vfio: Error: Failed to disable INTx irqfd: %m\n");
+    }
+
+    /* We only need to close the eventfd for VFIO to cleanup the kernel side */
+    event_notifier_cleanup(&vdev->intx.unmask);
+
+    /* QEMU starts listening for interrupt events. */
+    qemu_set_fd_handler(irqfd.fd, vfio_intx_interrupt, NULL, vdev);
+
+    vdev->intx.kvm_accel = false;
+
+    /* If we've missed an event, let it re-fire through QEMU */
+    vfio_unmask_intx(vdev);
+
+    DPRINTF("%s(%04x:%02x:%02x.%x) KVM INTx accel disabled\n",
+            __func__, vdev->host.domain, vdev->host.bus,
+            vdev->host.slot, vdev->host.function);
+#endif
+}
+
+static void vfio_update_irq(PCIDevice *pdev)
+{
+    VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev);
+    PCIINTxRoute route;
+
+    if (vdev->interrupt != VFIO_INT_INTx) {
+        return;
+    }
+
+    route = pci_device_route_intx_to_irq(&vdev->pdev, vdev->intx.pin);
+
+    if (!pci_intx_route_changed(&vdev->intx.route, &route)) {
+        return; /* Nothing changed */
+    }
+
+    DPRINTF("%s(%04x:%02x:%02x.%x) IRQ moved %d -> %d\n", __func__,
+            vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function, vdev->intx.route.irq, route.irq);
+
+    vfio_disable_intx_kvm(vdev);
+
+    vdev->intx.route = route;
+
+    if (route.mode != PCI_INTX_ENABLED) {
+        return;
+    }
+
+    vfio_enable_intx_kvm(vdev);
+
+    /* Re-enable the interrupt in cased we missed an EOI */
+    vfio_eoi(vdev);
+}
+
 static int vfio_enable_intx(VFIODevice *vdev)
 {
     uint8_t pin = vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1);
@@ -262,6 +432,18 @@ static int vfio_enable_intx(VFIODevice *vdev)
     vfio_disable_interrupts(vdev);
 
     vdev->intx.pin = pin - 1; /* Pin A (1) -> irq[0] */
+
+#ifdef CONFIG_KVM
+    /*
+     * Only conditional to avoid generating error messages on platforms
+     * where we won't actually use the result anyway.
+     */
+    if (kvm_check_extension(kvm_state, KVM_CAP_IRQFD_RESAMPLE)) {
+        vdev->intx.route = pci_device_route_intx_to_irq(&vdev->pdev,
+                                                        vdev->intx.pin);
+    }
+#endif
+
     ret = event_notifier_init(&vdev->intx.interrupt, 0);
     if (ret) {
         error_report("vfio: Error: event_notifier_init failed\n");
@@ -290,6 +472,8 @@ static int vfio_enable_intx(VFIODevice *vdev)
         return -errno;
     }
 
+    vfio_enable_intx_kvm(vdev);
+
     vdev->interrupt = VFIO_INT_INTx;
 
     DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain,
@@ -303,6 +487,7 @@ static void vfio_disable_intx(VFIODevice *vdev)
     int fd;
 
     qemu_del_timer(vdev->intx.mmap_timer);
+    vfio_disable_intx_kvm(vdev);
     vfio_disable_irqindex(vdev, VFIO_PCI_INTX_IRQ_INDEX);
     vdev->intx.pending = false;
     qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
@@ -1839,6 +2024,7 @@ static int vfio_initfn(PCIDevice *pdev)
     if (vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1)) {
         vdev->intx.mmap_timer = qemu_new_timer_ms(vm_clock,
                                                   vfio_intx_mmap_enable, vdev);
+        pci_device_set_intx_routing_notifier(&vdev->pdev, vfio_update_irq);
         ret = vfio_enable_intx(vdev);
         if (ret) {
             goto out_teardown;

From a771c51703cf9f91023c6570426258bdf5ec775b Mon Sep 17 00:00:00 2001
From: Alex Williamson 
Date: Tue, 13 Nov 2012 12:27:40 -0700
Subject: [PATCH 1590/2270] vfio-pci: Use common msi_get_message

We can get rid of our local version now that a helper exists.

Signed-off-by: Alex Williamson 
---
 hw/vfio_pci.c | 24 +-----------------------
 1 file changed, 1 insertion(+), 23 deletions(-)

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index 4e9c2ddbf9..7c27834e06 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -688,28 +688,6 @@ static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr)
     vector->use = false;
 }
 
-/* TODO This should move to msi.c */
-static MSIMessage msi_get_msg(PCIDevice *pdev, unsigned int vector)
-{
-    uint16_t flags = pci_get_word(pdev->config + pdev->msi_cap + PCI_MSI_FLAGS);
-    bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
-    MSIMessage msg;
-
-    if (msi64bit) {
-        msg.address = pci_get_quad(pdev->config +
-                                   pdev->msi_cap + PCI_MSI_ADDRESS_LO);
-    } else {
-        msg.address = pci_get_long(pdev->config +
-                                   pdev->msi_cap + PCI_MSI_ADDRESS_LO);
-    }
-
-    msg.data = pci_get_word(pdev->config + pdev->msi_cap +
-                            (msi64bit ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32));
-    msg.data += vector;
-
-    return msg;
-}
-
 static void vfio_enable_msix(VFIODevice *vdev)
 {
     vfio_disable_interrupts(vdev);
@@ -748,7 +726,7 @@ retry:
             error_report("vfio: Error: event_notifier_init failed\n");
         }
 
-        msg = msi_get_msg(&vdev->pdev, i);
+        msg = msi_get_message(&vdev->pdev, i);
 
         /*
          * Attempt to enable route through KVM irqchip,

From 5ca9388a4d22a68439a04b0735c34bdcac553e48 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Wed, 7 Nov 2012 11:06:23 +0100
Subject: [PATCH 1591/2270] pixman: add output dir to include path

Needed to make sure the (generated) pixman-version.h file is found.
Based on a patch from Blue Swirl.

Signed-off-by: Gerd Hoffmann 
---
 configure | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/configure b/configure
index 7290f50e11..e6fe4f8fe3 100755
--- a/configure
+++ b/configure
@@ -2121,11 +2121,10 @@ else
     echo "      git submodule update --init pixman"
     exit 1
   fi
-  pixman_cflags="-I${source_path}/pixman/pixman"
-  pixman_libs="-Lpixman/pixman/.libs -lpixman-1"
+  mkdir -p pixman/pixman
+  pixman_cflags="-I\$(SRC_PATH)/pixman/pixman -I\$(BUILD_DIR)/pixman/pixman"
+  pixman_libs="-L\$(BUILD_DIR)/pixman/pixman/.libs -lpixman-1"
 fi
-QEMU_CFLAGS="$QEMU_CFLAGS $pixman_cflags"
-libs_softmmu="$libs_softmmu $pixman_libs"
 
 ##########################################
 # libcap probe
@@ -3137,6 +3136,10 @@ if test "$cpu" = "ppc64" -a "$targetos" != "Darwin" ; then
   roms="$roms spapr-rtas"
 fi
 
+# add pixman flags after all config tests are done
+QEMU_CFLAGS="$QEMU_CFLAGS $pixman_cflags"
+libs_softmmu="$libs_softmmu $pixman_libs"
+
 echo "Install prefix    $prefix"
 echo "BIOS directory    `eval echo $qemu_datadir`"
 echo "binary directory  `eval echo $bindir`"
@@ -4154,7 +4157,6 @@ DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas"
 DIRS="$DIRS roms/seabios roms/vgabios"
 DIRS="$DIRS qapi-generated"
 DIRS="$DIRS libcacard libcacard/libcacard libcacard/trace"
-DIRS="$DIRS pixman"
 FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
 FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit"
 FILES="$FILES tests/tcg/lm32/Makefile libcacard/Makefile"

From 42da6041d5e30fcf49ba639477a05e781594a7a5 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Wed, 7 Nov 2012 11:09:52 +0100
Subject: [PATCH 1592/2270] pixman: set --host for cross builds

Set --host when calling pixman configure while doing cross builds so
pixman's autoconf picks up the cross build tools correctly.

Signed-off-by: Gerd Hoffmann 
---
 Makefile  | 2 +-
 configure | 5 +++++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index ca14a215ce..ff2c16d026 100644
--- a/Makefile
+++ b/Makefile
@@ -122,7 +122,7 @@ subdir-pixman: pixman/Makefile
 	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C pixman V="$(V)" all,)
 
 pixman/Makefile: $(SRC_PATH)/pixman/configure
-	(cd pixman; $(SRC_PATH)/pixman/configure --disable-shared --enable-static)
+	(cd pixman; $(SRC_PATH)/pixman/configure $(AUTOCONF_HOST) --disable-shared --enable-static)
 
 $(SRC_PATH)/pixman/configure:
 	(cd $(SRC_PATH)/pixman; autoreconf -v --install)
diff --git a/configure b/configure
index e6fe4f8fe3..0a241ebac6 100755
--- a/configure
+++ b/configure
@@ -3649,6 +3649,11 @@ if test "$sparse" = "yes" ; then
   echo "HOST_CC      := REAL_CC=\"\$(HOST_CC)\" cgcc"  >> $config_host_mak
   echo "QEMU_CFLAGS  += -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-non-pointer-null" >> $config_host_mak
 fi
+if test "$cross_prefix" != ""; then
+  echo "AUTOCONF_HOST := --host=${cross_prefix%-}"     >> $config_host_mak
+else
+  echo "AUTOCONF_HOST := "                             >> $config_host_mak
+fi
 echo "LDFLAGS=$LDFLAGS" >> $config_host_mak
 echo "ARLIBS_BEGIN=$arlibs_begin" >> $config_host_mak
 echo "ARLIBS_END=$arlibs_end" >> $config_host_mak

From 4d5bdd0b460ee2ff8989b0f83fa38a3af052b343 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Wed, 7 Nov 2012 11:41:01 +0100
Subject: [PATCH 1593/2270] pixman: disable gtk

gtk is only needed to build test cases.
Disable it to simplify the build.

Signed-off-by: Gerd Hoffmann 
---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index ff2c16d026..e68bb8fae4 100644
--- a/Makefile
+++ b/Makefile
@@ -122,7 +122,7 @@ subdir-pixman: pixman/Makefile
 	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C pixman V="$(V)" all,)
 
 pixman/Makefile: $(SRC_PATH)/pixman/configure
-	(cd pixman; $(SRC_PATH)/pixman/configure $(AUTOCONF_HOST) --disable-shared --enable-static)
+	(cd pixman; $(SRC_PATH)/pixman/configure $(AUTOCONF_HOST) --disable-gtk --disable-shared --enable-static)
 
 $(SRC_PATH)/pixman/configure:
 	(cd $(SRC_PATH)/pixman; autoreconf -v --install)

From c28fa5a0b3566b133b5e3336d04f1333970ac179 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Wed, 14 Nov 2012 13:26:54 +0100
Subject: [PATCH 1594/2270] pixman: pass cflags, add -fPIC

Pass on CFLAGS to the pixman configure script.
Add -fPIC to the cflags, needed to make the final link succeed.

Signed-off-by: Gerd Hoffmann 
---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index e68bb8fae4..4538b87e36 100644
--- a/Makefile
+++ b/Makefile
@@ -122,7 +122,7 @@ subdir-pixman: pixman/Makefile
 	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C pixman V="$(V)" all,)
 
 pixman/Makefile: $(SRC_PATH)/pixman/configure
-	(cd pixman; $(SRC_PATH)/pixman/configure $(AUTOCONF_HOST) --disable-gtk --disable-shared --enable-static)
+	(cd pixman; CFLAGS="$(CFLAGS) -fPIC" $(SRC_PATH)/pixman/configure $(AUTOCONF_HOST) --disable-gtk --disable-shared --enable-static)
 
 $(SRC_PATH)/pixman/configure:
 	(cd $(SRC_PATH)/pixman; autoreconf -v --install)

From b776eca138b641a0234a957a9ff5c2ca4c6772d5 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Mon, 12 Nov 2012 12:18:38 +0100
Subject: [PATCH 1595/2270] pixman: build internal version early

Signed-off-by: Eric Johnson 
Signed-off-by: Gerd Hoffmann 
---
 configure | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/configure b/configure
index 0a241ebac6..f847ee264e 100755
--- a/configure
+++ b/configure
@@ -3956,9 +3956,6 @@ if test "$target_softmmu" = "yes" ; then
   if test "$smartcard_nss" = "yes" ; then
     echo "subdir-$target: subdir-libcacard" >> $config_host_mak
   fi
-  if test "$pixman" = "internal" ; then
-    echo "subdir-$target: subdir-pixman" >> $config_host_mak
-  fi
   case "$target_arch2" in
     i386|x86_64)
       echo "CONFIG_HAVE_CORE_DUMP=y" >> $config_target_mak
@@ -4156,6 +4153,10 @@ echo "QEMU_INCLUDES+=$includes" >> $config_target_mak
 
 done # for target in $targets
 
+if [ "$pixman" = "internal" ]; then
+  echo "config-host.h: subdir-pixman" >> $config_host_mak
+fi
+
 # build tree in object directory in case the source is not in the current directory
 DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32"
 DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas"

From daa8e5a077e9d8ca2615f5590fa98b3fcc4c9f47 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Tue, 13 Nov 2012 09:38:06 +0100
Subject: [PATCH 1596/2270] pixman: add licensing info

Signed-off-by: Gerd Hoffmann 
---
 qemu-pixman.c | 5 +++++
 qemu-pixman.h | 5 +++++
 2 files changed, 10 insertions(+)

diff --git a/qemu-pixman.c b/qemu-pixman.c
index 7547ed74c1..063b52dbb1 100644
--- a/qemu-pixman.c
+++ b/qemu-pixman.c
@@ -1,3 +1,8 @@
+/*
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
 #include "qemu-pixman.h"
 
 int qemu_pixman_get_type(int rshift, int gshift, int bshift)
diff --git a/qemu-pixman.h b/qemu-pixman.h
index 7652c41277..783a39252e 100644
--- a/qemu-pixman.h
+++ b/qemu-pixman.h
@@ -1,3 +1,8 @@
+/*
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
 #ifndef QEMU_PIXMAN_H
 #define QEMU_PIXMAN_H
 

From feb33ea728a72730389bc5d4bf52d33f09c7868b Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Wed, 14 Nov 2012 13:45:55 +0100
Subject: [PATCH 1597/2270] pixman: cleanup properly on make distclean

Signed-off-by: Gerd Hoffmann 
---
 Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Makefile b/Makefile
index 4538b87e36..81c660f9f4 100644
--- a/Makefile
+++ b/Makefile
@@ -278,6 +278,7 @@ distclean: clean
 	for d in $(TARGET_DIRS) $(QEMULIBS); do \
 	rm -rf $$d || exit 1 ; \
         done
+	test -f pixman/config.log && make -C pixman distclean
 
 KEYMAPS=da     en-gb  et  fr     fr-ch  is  lt  modifiers  no  pt-br  sv \
 ar      de     en-us  fi  fr-be  hr     it  lv  nl         pl  ru     th \

From 8809e28937b8a48ff0dfeeb93498641392f26019 Mon Sep 17 00:00:00 2001
From: Bharata B Rao 
Date: Wed, 24 Oct 2012 17:17:53 +0530
Subject: [PATCH 1598/2270] qemu: Document GlusterFS block driver usage

Signed-off-by: Bharata B Rao 
Signed-off-by: Kevin Wolf 
---
 qemu-doc.texi   | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-options.hx | 17 +++++++++++++++++
 2 files changed, 66 insertions(+)

diff --git a/qemu-doc.texi b/qemu-doc.texi
index d8fb2de10e..6ff309ddf4 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -421,6 +421,7 @@ snapshots.
 * disk_images_nbd::           NBD access
 * disk_images_sheepdog::      Sheepdog disk images
 * disk_images_iscsi::         iSCSI LUNs
+* disk_images_gluster::       GlusterFS disk images
 @end menu
 
 @node disk_images_quickstart
@@ -814,7 +815,55 @@ qemu-system-i386 -iscsi initiator-name=iqn.qemu.test:my-initiator \
     -cdrom iscsi://127.0.0.1/iqn.qemu.test/2
 @end example
 
+@node disk_images_gluster
+@subsection GlusterFS disk images
 
+GlusterFS is an user space distributed file system.
+
+You can boot from the GlusterFS disk image with the command:
+@example
+qemu-system-x86_64 -drive file=gluster[+@var{transport}]://[@var{server}[:@var{port}]]/@var{volname}/@var{image}[?socket=...]
+@end example
+
+@var{gluster} is the protocol.
+
+@var{transport} specifies the transport type used to connect to gluster
+management daemon (glusterd). Valid transport types are
+tcp, unix and rdma. If a transport type isn't specified, then tcp
+type is assumed.
+
+@var{server} specifies the server where the volume file specification for
+the given volume resides. This can be either hostname, ipv4 address
+or ipv6 address. ipv6 address needs to be within square brackets [ ].
+If transport type is unix, then @var{server} field should not be specifed.
+Instead @var{socket} field needs to be populated with the path to unix domain
+socket.
+
+@var{port} is the port number on which glusterd is listening. This is optional
+and if not specified, QEMU will send 0 which will make gluster to use the
+default port. If the transport type is unix, then @var{port} should not be
+specified.
+
+@var{volname} is the name of the gluster volume which contains the disk image.
+
+@var{image} is the path to the actual disk image that resides on gluster volume.
+
+You can create a GlusterFS disk image with the command:
+@example
+qemu-img create gluster://@var{server}/@var{volname}/@var{image} @var{size}
+@end example
+
+Examples
+@example
+qemu-system-x86_64 -drive file=gluster://1.2.3.4/testvol/a.img
+qemu-system-x86_64 -drive file=gluster+tcp://1.2.3.4/testvol/a.img
+qemu-system-x86_64 -drive file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img
+qemu-system-x86_64 -drive file=gluster+tcp://[1:2:3:4:5:6:7:8]/testvol/dir/a.img
+qemu-system-x86_64 -drive file=gluster+tcp://[1:2:3:4:5:6:7:8]:24007/testvol/dir/a.img
+qemu-system-x86_64 -drive file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img
+qemu-system-x86_64 -drive file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket
+qemu-system-x86_64 -drive file=gluster+rdma://1.2.3.4:24007/testvol/a.img
+@end example
 
 @node pcsys_network
 @section Network emulation
diff --git a/qemu-options.hx b/qemu-options.hx
index fe8f15c541..06aa1ae6e3 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2054,6 +2054,23 @@ qemu-system-i386 --drive file=sheepdog:192.0.2.1:30000:MyVirtualMachine
 
 See also @url{http://http://www.osrg.net/sheepdog/}.
 
+@item GlusterFS
+GlusterFS is an user space distributed file system.
+QEMU supports the use of GlusterFS volumes for hosting VM disk images using
+TCP, Unix Domain Sockets and RDMA transport protocols.
+
+Syntax for specifying a VM disk image on GlusterFS volume is
+@example
+gluster[+transport]://[server[:port]]/volname/image[?socket=...]
+@end example
+
+
+Example
+@example
+qemu-system-x86_84 --drive file=gluster://192.0.2.1/testvol/a.img
+@end example
+
+See also @url{http://www.gluster.org}.
 @end table
 ETEXI
 

From a3548077062dd9dc2701ebffd931ba6eaef40bec Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Fri, 26 Oct 2012 16:33:32 +0200
Subject: [PATCH 1599/2270] qcow2: Fix refcount table size calculation

A missing factor for the refcount table entry size in the calculation
could mean that too little memory was allocated for the in-memory
representation of the table, resulting in a buffer overflow.

Signed-off-by: Kevin Wolf 
Reviewed-by: Michael Tokarev 
Tested-by: Michael Tokarev 
---
 block/qcow2-refcount.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 5e3f9153fb..96224d1af2 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -301,7 +301,8 @@ static int alloc_refcount_block(BlockDriverState *bs,
     uint64_t last_table_size;
     uint64_t blocks_clusters;
     do {
-        uint64_t table_clusters = size_to_clusters(s, table_size);
+        uint64_t table_clusters =
+            size_to_clusters(s, table_size * sizeof(uint64_t));
         blocks_clusters = 1 +
             ((table_clusters + refcount_block_clusters - 1)
             / refcount_block_clusters);

From d2ef210cb8d3e7d1dc4e1c6050d2092bda18a5a8 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Fri, 26 Oct 2012 20:31:15 +0200
Subject: [PATCH 1600/2270] qemu-iotests: qcow2: Test growing large refcount
 table

Actually writing all the content with 512 byte sector size would take
forever, therefore build the image file with a Python script and use
qemu-io for the last write that actually triggers the refcount table
growth.

Signed-off-by: Kevin Wolf 
---
 tests/qemu-iotests/044        | 117 ++++++++++++++++++++++++++++++++++
 tests/qemu-iotests/044.out    |   6 ++
 tests/qemu-iotests/group      |   1 +
 tests/qemu-iotests/iotests.py |   6 +-
 tests/qemu-iotests/qcow2.py   |   9 +--
 5 files changed, 134 insertions(+), 5 deletions(-)
 create mode 100755 tests/qemu-iotests/044
 create mode 100644 tests/qemu-iotests/044.out

diff --git a/tests/qemu-iotests/044 b/tests/qemu-iotests/044
new file mode 100755
index 0000000000..11ea0f4d35
--- /dev/null
+++ b/tests/qemu-iotests/044
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+#
+# Tests growing a large refcount table.
+#
+# Copyright (C) 2012 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 .
+#
+
+import time
+import os
+import qcow2
+from qcow2 import QcowHeader
+import iotests
+from iotests import qemu_img, qemu_img_verbose, qemu_io
+import struct
+import subprocess
+
+test_img = os.path.join(iotests.test_dir, 'test.img')
+
+class TestRefcountTableGrowth(iotests.QMPTestCase):
+    '''Abstract base class for image mirroring test cases'''
+
+    def preallocate(self, name):
+        fd = open(name, "r+b")
+        try:
+            off_reftable = 512
+            off_refblock = off_reftable + (512 * 512)
+            off_l1       = off_refblock + (512 * 512 * 64)
+            off_l2       = off_l1 + (512 * 512 * 4 * 8)
+            off_data     = off_l2 + (512 * 512 * 4 * 512)
+
+            # Write a new header
+            h = QcowHeader(fd)
+            h.refcount_table_offset = off_reftable
+            h.refcount_table_clusters = 512
+            h.l1_table_offset = off_l1
+            h.l1_size = 512 * 512 * 4
+            h.update(fd)
+
+            # Write a refcount table
+            fd.seek(off_reftable)
+
+            for i in xrange(0, h.refcount_table_clusters):
+                sector = ''.join(struct.pack('>Q',
+                    off_refblock + i * 64 * 512 + j * 512)
+                    for j in xrange(0, 64))
+                fd.write(sector)
+
+            # Write the refcount blocks
+            assert(fd.tell() == off_refblock)
+            sector = ''.join(struct.pack('>H', 1) for j in xrange(0, 64 * 256))
+            for block in xrange(0, h.refcount_table_clusters):
+                fd.write(sector)
+
+            # Write the L1 table
+            assert(fd.tell() == off_l1)
+            assert(off_l2 + 512 * h.l1_size == off_data)
+            table = ''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j)
+                for j in xrange(0, h.l1_size))
+            fd.write(table)
+
+            # Write the L2 tables
+            assert(fd.tell() == off_l2)
+            img_file_size = h.refcount_table_clusters * 64 * 256 * 512
+            remaining = img_file_size - off_data
+
+            off = off_data
+            while remaining > 1024 * 512:
+                pytable = list((1 << 63) | off + 512 * j
+                    for j in xrange(0, 1024))
+                table = struct.pack('>1024Q', *pytable)
+                fd.write(table)
+                remaining = remaining - 1024 * 512
+                off = off + 1024 * 512
+
+            table = ''.join(struct.pack('>Q', (1 << 63) | off + 512 * j)
+                for j in xrange(0, remaining / 512))
+            fd.write(table)
+
+
+            # Data
+            fd.truncate(img_file_size)
+
+
+        finally:
+            fd.close()
+
+
+    def setUp(self):
+        qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=512', test_img, '16G')
+        self.preallocate(test_img)
+        pass
+
+
+    def tearDown(self):
+        os.remove(test_img)
+        pass
+
+    def test_grow_refcount_table(self):
+        qemu_io('-c', 'write 3800M 1M', test_img)
+        qemu_img_verbose('check' , test_img)
+        pass
+
+if __name__ == '__main__':
+    iotests.main(supported_fmts=['qcow2'])
diff --git a/tests/qemu-iotests/044.out b/tests/qemu-iotests/044.out
new file mode 100644
index 0000000000..7a4007137d
--- /dev/null
+++ b/tests/qemu-iotests/044.out
@@ -0,0 +1,6 @@
+No errors were found on the image.
+.
+----------------------------------------------------------------------
+Ran 1 tests
+
+OK
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index ac86f54ae3..a4a9044f24 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -50,3 +50,4 @@
 041 rw auto backing
 042 rw auto quick
 043 rw auto backing
+044 rw auto
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 735c6745d7..b2eaf20f0b 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -42,6 +42,10 @@ def qemu_img(*args):
     devnull = open('/dev/null', 'r+')
     return subprocess.call(qemu_img_args + list(args), stdin=devnull, stdout=devnull)
 
+def qemu_img_verbose(*args):
+    '''Run qemu-img without supressing its output and return the exit code'''
+    return subprocess.call(qemu_img_args + list(args))
+
 def qemu_io(*args):
     '''Run qemu-io and return the stdout data'''
     args = qemu_io_args + list(args)
@@ -182,4 +186,4 @@ def main(supported_fmts=[]):
     try:
         unittest.main(testRunner=MyTestRunner)
     finally:
-        sys.stderr.write(re.sub(r'Ran (\d+) test[s] in [\d.]+s', r'Ran \1 tests', output.getvalue()))
+        sys.stderr.write(re.sub(r'Ran (\d+) tests? in [\d.]+s', r'Ran \1 tests', output.getvalue()))
diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py
index 97f37707bc..fecf5b9a59 100755
--- a/tests/qemu-iotests/qcow2.py
+++ b/tests/qemu-iotests/qcow2.py
@@ -233,8 +233,9 @@ def usage():
     for name, handler, num_args, desc in cmds:
         print "    %-20s - %s" % (name, desc)
 
-if len(sys.argv) < 3:
-    usage()
-    sys.exit(1)
+if __name__ == '__main__':
+    if len(sys.argv) < 3:
+        usage()
+        sys.exit(1)
 
-main(sys.argv[1], sys.argv[2], sys.argv[3:])
+    main(sys.argv[1], sys.argv[2], sys.argv[3:])

From 54d01a0073db56230815d16cf3e6054c1dba919a Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi 
Date: Fri, 9 Nov 2012 14:29:03 +0100
Subject: [PATCH 1601/2270] MAINTAINERS: add Stefan Hajnoczi as block and
 virtio-blk co-maintainer

Kevin has requested co-maintainership to give him more time to write
code.  We will alternate patch review duties on a weekly basis.

Signed-off-by: Stefan Hajnoczi 
Signed-off-by: Kevin Wolf 
---
 MAINTAINERS | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8f5681fd64..2ede20d60b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -553,6 +553,7 @@ T: git git://github.com/kvaneesh/QEMU.git
 
 virtio-blk
 M: Kevin Wolf 
+M: Stefan Hajnoczi 
 S: Supported
 F: hw/virtio-blk*
 
@@ -583,6 +584,7 @@ F: audio/
 
 Block
 M: Kevin Wolf 
+M: Stefan Hajnoczi 
 S: Supported
 F: block*
 F: block/

From cee40d2d2dda87fd9705ed4b85e2c0cf0e5c2ac4 Mon Sep 17 00:00:00 2001
From: Stefan Weil 
Date: Sun, 4 Nov 2012 12:09:34 +0100
Subject: [PATCH 1602/2270] block: Workaround for older versions of MinGW gcc

Versions before gcc-4.6 don't support unnamed fields in initializers
(see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=10676).

Offset and OffsetHigh belong to an unnamed struct which is part of an
unnamed union. Therefore the original code does not work with older
versions of gcc.

Signed-off-by: Stefan Weil 
Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Kevin Wolf 
---
 block/win32-aio.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/block/win32-aio.c b/block/win32-aio.c
index c34dc73b6c..92f25a97e5 100644
--- a/block/win32-aio.c
+++ b/block/win32-aio.c
@@ -167,11 +167,11 @@ BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
         waiocb->is_linear = true;
     }
 
-    waiocb->ov = (OVERLAPPED) {
-        .Offset = (DWORD) offset,
-        .OffsetHigh = (DWORD) (offset >> 32),
-        .hEvent = event_notifier_get_handle(&aio->e)
-    };
+    memset(&waiocb->ov, 0, sizeof(waiocb->ov));
+    waiocb->ov.Offset = (DWORD)offset;
+    waiocb->ov.OffsetHigh = (DWORD)(offset >> 32);
+    waiocb->ov.hEvent = event_notifier_get_handle(&aio->e);
+
     aio->count++;
 
     if (type & QEMU_AIO_READ) {

From a9660664fde89ef2c7bc629eda547a48b288fbb9 Mon Sep 17 00:00:00 2001
From: Nick Thomas 
Date: Fri, 2 Nov 2012 13:01:23 +0000
Subject: [PATCH 1603/2270] tests: allow qemu-iotests to be run against nbd
 backend

To do this, we start a qemu-nbd process at _make_test_img and kill
it in _cleanup_test_img. $TEST_IMG is changed to point at the TCP
server. We also remove the checks for existence of binaries from
common.config - they're duplicated in common, and we can make the
qemu-nbd check conditional on $IMGPROTO being "nbd" if we do it there.

Signed-off-by: Nick Thomas 
Acked-by: Paolo Bonzini 
Signed-off-by: Kevin Wolf 
---
 tests/qemu-iotests/common        | 13 ++++++++++---
 tests/qemu-iotests/common.config | 10 ++++++----
 tests/qemu-iotests/common.rc     | 23 ++++++++++++++++++++++-
 3 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
index 1f6fdf5c56..b3aad89e2c 100644
--- a/tests/qemu-iotests/common
+++ b/tests/qemu-iotests/common
@@ -136,6 +136,7 @@ check options
     -vmdk               test vmdk
     -rbd                test rbd
     -sheepdog           test sheepdog
+    -nbd                test nbd
     -xdiff		graphical mode diff
     -nocache		use O_DIRECT on backing file
     -misalign		misalign memory allocations
@@ -197,12 +198,14 @@ testlist options
 	    IMGPROTO=rbd
 	    xpand=false
 	    ;;
-
 	-sheepdog)
 	    IMGPROTO=sheepdog
 	    xpand=false
 	    ;;
-
+	-nbd)
+	    IMGPROTO=nbd
+	    xpand=false
+	    ;;
 	-nocache)
 	    QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --nocache"
 	    xpand=false
@@ -350,7 +353,11 @@ fi
 
 [ "$QEMU" = "" ] && _fatal "qemu not found"
 [ "$QEMU_IMG" = "" ] && _fatal "qemu-img not found"
-[ "$QEMU_IO" = "" ] && _fatal "qemu-img not found"
+[ "$QEMU_IO" = "" ] && _fatal "qemu-io not found"
+
+if [ "$IMGPROTO" = "nbd" ] ; then
+    [ "$QEMU_NBD" = "" ] && _fatal "qemu-nbd not found"
+fi
 
 if $valgrind; then
     export REAL_QEMU_IO="$QEMU_IO_PROG"
diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config
index df082e750c..08a3f100b8 100644
--- a/tests/qemu-iotests/common.config
+++ b/tests/qemu-iotests/common.config
@@ -90,21 +90,23 @@ export PS_ALL_FLAGS="-ef"
 if [ -z "$QEMU_PROG" ]; then
     export QEMU_PROG="`set_prog_path qemu`"
 fi
-[ "$QEMU_PROG" = "" ] && _fatal "qemu not found"
 
 if [ -z "$QEMU_IMG_PROG" ]; then
     export QEMU_IMG_PROG="`set_prog_path qemu-img`"
 fi
-[ "$QEMU_IMG_PROG" = "" ] && _fatal "qemu-img not found"
 
 if [ -z "$QEMU_IO_PROG" ]; then
     export QEMU_IO_PROG="`set_prog_path qemu-io`"
 fi
-[ "$QEMU_IO_PROG" = "" ] && _fatal "qemu-io not found"
+
+if [ -z "$QEMU_NBD_PROG" ]; then
+    export QEMU_NBD_PROG="`set_prog_path qemu-nbd`"
+fi
 
 export QEMU=$QEMU_PROG
-export QEMU_IMG=$QEMU_IMG_PROG 
+export QEMU_IMG=$QEMU_IMG_PROG
 export QEMU_IO="$QEMU_IO_PROG $QEMU_IO_OPTIONS"
+export QEMU_NBD=$QEMU_NBD_PROG
 
 [ -f /etc/qemu-iotest.config ]       && . /etc/qemu-iotest.config
 
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 334534f22c..aef5f52b4f 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -49,6 +49,9 @@ umask 022
 
 if [ "$IMGPROTO" = "file" ]; then
     TEST_IMG=$TEST_DIR/t.$IMGFMT
+elif [ "$IMGPROTO" = "nbd" ]; then
+    TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
+    TEST_IMG="nbd:127.0.0.1:10810"
 else
     TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
 fi
@@ -86,6 +89,13 @@ _make_test_img()
     local extra_img_options=""
     local image_size=$*
     local optstr=""
+    local img_name=""
+
+    if [ -n "$TEST_IMG_FILE" ]; then
+        img_name=$TEST_IMG_FILE
+    else
+        img_name=$TEST_IMG
+    fi
 
     if [ -n "$IMGOPTS" ]; then
         optstr=$(_optstr_add "$optstr" "$IMGOPTS")
@@ -104,7 +114,7 @@ _make_test_img()
     fi
 
     # XXX(hch): have global image options?
-    $QEMU_IMG create -f $IMGFMT $extra_img_options $TEST_IMG $image_size | \
+    $QEMU_IMG create -f $IMGFMT $extra_img_options $img_name $image_size | \
         sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
             -e "s#$TEST_DIR#TEST_DIR#g" \
             -e "s#$IMGFMT#IMGFMT#g" \
@@ -115,12 +125,23 @@ _make_test_img()
             -e "s# compat6=\\(on\\|off\\)##g" \
             -e "s# static=\\(on\\|off\\)##g" \
             -e "s# lazy_refcounts=\\(on\\|off\\)##g"
+
+    # Start an NBD server on the image file, which is what we'll be talking to
+    if [ $IMGPROTO = "nbd" ]; then
+        eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810  $TEST_IMG_FILE &"
+        QEMU_NBD_PID=$!
+        sleep 1 # FIXME: qemu-nbd needs to be listening before we continue
+    fi
 }
 
 _cleanup_test_img()
 {
     case "$IMGPROTO" in
 
+        nbd)
+            kill $QEMU_NBD_PID
+            rm -f $TEST_IMG_FILE
+            ;;
         file)
             rm -f $TEST_DIR/t.$IMGFMT
             rm -f $TEST_DIR/t.$IMGFMT.orig

From 8c82e9a4331bad42dfc01158fbd1e8f4c2f1c957 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi 
Date: Wed, 31 Oct 2012 16:34:35 +0100
Subject: [PATCH 1604/2270] aio: switch aiocb_size type int -> size_t

Using appropriate types for variables is a good thing :).  All users
simply do sizeof(MyType) and the value is passed to a memory allocator,
it should be size_t.

Signed-off-by: Stefan Hajnoczi 
Reviewed-by: Paolo Bonzini 
Signed-off-by: Kevin Wolf 
---
 qemu-aio.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/qemu-aio.h b/qemu-aio.h
index 1b7eb6ef5b..111b0b3f0a 100644
--- a/qemu-aio.h
+++ b/qemu-aio.h
@@ -23,7 +23,7 @@ typedef void BlockDriverCompletionFunc(void *opaque, int ret);
 
 typedef struct AIOPool {
     void (*cancel)(BlockDriverAIOCB *acb);
-    int aiocb_size;
+    size_t aiocb_size;
     BlockDriverAIOCB *free_aiocb;
 } AIOPool;
 

From d37c975fb134e1b16f09b4e6545e2c0591fb6455 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi 
Date: Wed, 31 Oct 2012 16:34:36 +0100
Subject: [PATCH 1605/2270] aio: use g_slice_alloc() for AIOCB pooling

AIO control blocks are frequently acquired and released because each aio
request involves at least one AIOCB.  Therefore, we pool them to avoid
heap allocation overhead.

The problem with the freelist approach in AIOPool is thread-safety.  If
we want BlockDriverStates to associate with AioContexts that execute in
multiple threads, then a global freelist becomes a problem.

This patch drops the freelist and instead uses g_slice_alloc() which is
tuned for per-thread fixed-size object pools.  qemu_aio_get() and
qemu_aio_release() are now thread-safe.

Note that the change from g_malloc0() to g_slice_alloc() should be safe
since the freelist reuse case doesn't zero the AIOCB either.

Signed-off-by: Stefan Hajnoczi 
Reviewed-by: Paolo Bonzini 
Signed-off-by: Kevin Wolf 
---
 block.c    | 15 ++++-----------
 qemu-aio.h |  2 --
 2 files changed, 4 insertions(+), 13 deletions(-)

diff --git a/block.c b/block.c
index da1fdca0e0..ea0f7d8367 100644
--- a/block.c
+++ b/block.c
@@ -3909,13 +3909,8 @@ void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
 {
     BlockDriverAIOCB *acb;
 
-    if (pool->free_aiocb) {
-        acb = pool->free_aiocb;
-        pool->free_aiocb = acb->next;
-    } else {
-        acb = g_malloc0(pool->aiocb_size);
-        acb->pool = pool;
-    }
+    acb = g_slice_alloc(pool->aiocb_size);
+    acb->pool = pool;
     acb->bs = bs;
     acb->cb = cb;
     acb->opaque = opaque;
@@ -3924,10 +3919,8 @@ void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
 
 void qemu_aio_release(void *p)
 {
-    BlockDriverAIOCB *acb = (BlockDriverAIOCB *)p;
-    AIOPool *pool = acb->pool;
-    acb->next = pool->free_aiocb;
-    pool->free_aiocb = acb;
+    BlockDriverAIOCB *acb = p;
+    g_slice_free1(acb->pool->aiocb_size, acb);
 }
 
 /**************************************************************/
diff --git a/qemu-aio.h b/qemu-aio.h
index 111b0b3f0a..b29c509f27 100644
--- a/qemu-aio.h
+++ b/qemu-aio.h
@@ -24,7 +24,6 @@ typedef void BlockDriverCompletionFunc(void *opaque, int ret);
 typedef struct AIOPool {
     void (*cancel)(BlockDriverAIOCB *acb);
     size_t aiocb_size;
-    BlockDriverAIOCB *free_aiocb;
 } AIOPool;
 
 struct BlockDriverAIOCB {
@@ -32,7 +31,6 @@ struct BlockDriverAIOCB {
     BlockDriverState *bs;
     BlockDriverCompletionFunc *cb;
     void *opaque;
-    BlockDriverAIOCB *next;
 };
 
 void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,

From d7331bed11f5e65b3b640aab59ab22bc61a4e77d Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi 
Date: Wed, 31 Oct 2012 16:34:37 +0100
Subject: [PATCH 1606/2270] aio: rename AIOPool to AIOCBInfo

Now that AIOPool no longer keeps a freelist, it isn't really a "pool"
anymore.  Rename it to AIOCBInfo and make it const since it no longer
needs to be modified.

Signed-off-by: Stefan Hajnoczi 
Signed-off-by: Kevin Wolf 
---
 block.c           | 22 +++++++++++-----------
 block/blkdebug.c  |  4 ++--
 block/blkverify.c |  4 ++--
 block/curl.c      |  4 ++--
 block/gluster.c   |  6 +++---
 block/iscsi.c     | 12 ++++++------
 block/linux-aio.c |  4 ++--
 block/qed.c       |  4 ++--
 block/rbd.c       |  4 ++--
 block/sheepdog.c  |  4 ++--
 block/win32-aio.c |  4 ++--
 dma-helpers.c     |  4 ++--
 hw/ide/core.c     |  4 ++--
 qemu-aio.h        |  8 ++++----
 thread-pool.c     |  4 ++--
 15 files changed, 46 insertions(+), 46 deletions(-)

diff --git a/block.c b/block.c
index ea0f7d8367..854ebd60d4 100644
--- a/block.c
+++ b/block.c
@@ -3521,7 +3521,7 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
 
 void bdrv_aio_cancel(BlockDriverAIOCB *acb)
 {
-    acb->pool->cancel(acb);
+    acb->aiocb_info->cancel(acb);
 }
 
 /* block I/O throttling */
@@ -3711,7 +3711,7 @@ static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
     qemu_aio_release(acb);
 }
 
-static AIOPool bdrv_em_aio_pool = {
+static const AIOCBInfo bdrv_em_aiocb_info = {
     .aiocb_size         = sizeof(BlockDriverAIOCBSync),
     .cancel             = bdrv_aio_cancel_em,
 };
@@ -3740,7 +3740,7 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
 {
     BlockDriverAIOCBSync *acb;
 
-    acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque);
+    acb = qemu_aio_get(&bdrv_em_aiocb_info, bs, cb, opaque);
     acb->is_write = is_write;
     acb->qiov = qiov;
     acb->bounce = qemu_blockalign(bs, qiov->size);
@@ -3785,7 +3785,7 @@ static void bdrv_aio_co_cancel_em(BlockDriverAIOCB *blockacb)
     qemu_aio_flush();
 }
 
-static AIOPool bdrv_em_co_aio_pool = {
+static const AIOCBInfo bdrv_em_co_aiocb_info = {
     .aiocb_size         = sizeof(BlockDriverAIOCBCoroutine),
     .cancel             = bdrv_aio_co_cancel_em,
 };
@@ -3828,7 +3828,7 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
     Coroutine *co;
     BlockDriverAIOCBCoroutine *acb;
 
-    acb = qemu_aio_get(&bdrv_em_co_aio_pool, bs, cb, opaque);
+    acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque);
     acb->req.sector = sector_num;
     acb->req.nb_sectors = nb_sectors;
     acb->req.qiov = qiov;
@@ -3858,7 +3858,7 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
     Coroutine *co;
     BlockDriverAIOCBCoroutine *acb;
 
-    acb = qemu_aio_get(&bdrv_em_co_aio_pool, bs, cb, opaque);
+    acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque);
     co = qemu_coroutine_create(bdrv_aio_flush_co_entry);
     qemu_coroutine_enter(co, acb);
 
@@ -3884,7 +3884,7 @@ BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs,
 
     trace_bdrv_aio_discard(bs, sector_num, nb_sectors, opaque);
 
-    acb = qemu_aio_get(&bdrv_em_co_aio_pool, bs, cb, opaque);
+    acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque);
     acb->req.sector = sector_num;
     acb->req.nb_sectors = nb_sectors;
     co = qemu_coroutine_create(bdrv_aio_discard_co_entry);
@@ -3904,13 +3904,13 @@ void bdrv_init_with_whitelist(void)
     bdrv_init();
 }
 
-void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
+void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs,
                    BlockDriverCompletionFunc *cb, void *opaque)
 {
     BlockDriverAIOCB *acb;
 
-    acb = g_slice_alloc(pool->aiocb_size);
-    acb->pool = pool;
+    acb = g_slice_alloc(aiocb_info->aiocb_size);
+    acb->aiocb_info = aiocb_info;
     acb->bs = bs;
     acb->cb = cb;
     acb->opaque = opaque;
@@ -3920,7 +3920,7 @@ void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
 void qemu_aio_release(void *p)
 {
     BlockDriverAIOCB *acb = p;
-    g_slice_free1(acb->pool->aiocb_size, acb);
+    g_slice_free1(acb->aiocb_info->aiocb_size, acb);
 }
 
 /**************************************************************/
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 1206d5256b..d61ece86a9 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -41,7 +41,7 @@ typedef struct BlkdebugAIOCB {
 
 static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb);
 
-static AIOPool blkdebug_aio_pool = {
+static const AIOCBInfo blkdebug_aiocb_info = {
     .aiocb_size = sizeof(BlkdebugAIOCB),
     .cancel     = blkdebug_aio_cancel,
 };
@@ -335,7 +335,7 @@ static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
         return NULL;
     }
 
-    acb = qemu_aio_get(&blkdebug_aio_pool, bs, cb, opaque);
+    acb = qemu_aio_get(&blkdebug_aiocb_info, bs, cb, opaque);
     acb->ret = -error;
 
     bh = qemu_bh_new(error_callback_bh, acb);
diff --git a/block/blkverify.c b/block/blkverify.c
index 9d5f1ec5b9..4beede77ab 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -48,7 +48,7 @@ static void blkverify_aio_cancel(BlockDriverAIOCB *blockacb)
     }
 }
 
-static AIOPool blkverify_aio_pool = {
+static const AIOCBInfo blkverify_aiocb_info = {
     .aiocb_size         = sizeof(BlkverifyAIOCB),
     .cancel             = blkverify_aio_cancel,
 };
@@ -233,7 +233,7 @@ static BlkverifyAIOCB *blkverify_aio_get(BlockDriverState *bs, bool is_write,
                                          BlockDriverCompletionFunc *cb,
                                          void *opaque)
 {
-    BlkverifyAIOCB *acb = qemu_aio_get(&blkverify_aio_pool, bs, cb, opaque);
+    BlkverifyAIOCB *acb = qemu_aio_get(&blkverify_aiocb_info, bs, cb, opaque);
 
     acb->bh = NULL;
     acb->is_write = is_write;
diff --git a/block/curl.c b/block/curl.c
index c1074cd2e3..1179484de0 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -438,7 +438,7 @@ static void curl_aio_cancel(BlockDriverAIOCB *blockacb)
     // Do we have to implement canceling? Seems to work without...
 }
 
-static AIOPool curl_aio_pool = {
+static const AIOCBInfo curl_aiocb_info = {
     .aiocb_size         = sizeof(CURLAIOCB),
     .cancel             = curl_aio_cancel,
 };
@@ -505,7 +505,7 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
 {
     CURLAIOCB *acb;
 
-    acb = qemu_aio_get(&curl_aio_pool, bs, cb, opaque);
+    acb = qemu_aio_get(&curl_aiocb_info, bs, cb, opaque);
 
     acb->qiov = qiov;
     acb->sector_num = sector_num;
diff --git a/block/gluster.c b/block/gluster.c
index 3588d7377f..1c90174b13 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -388,7 +388,7 @@ static void qemu_gluster_aio_cancel(BlockDriverAIOCB *blockacb)
     }
 }
 
-static AIOPool gluster_aio_pool = {
+static const AIOCBInfo gluster_aiocb_info = {
     .aiocb_size = sizeof(GlusterAIOCB),
     .cancel = qemu_gluster_aio_cancel,
 };
@@ -439,7 +439,7 @@ static BlockDriverAIOCB *qemu_gluster_aio_rw(BlockDriverState *bs,
     size = nb_sectors * BDRV_SECTOR_SIZE;
     s->qemu_aio_count++;
 
-    acb = qemu_aio_get(&gluster_aio_pool, bs, cb, opaque);
+    acb = qemu_aio_get(&gluster_aiocb_info, bs, cb, opaque);
     acb->size = size;
     acb->ret = 0;
     acb->finished = NULL;
@@ -484,7 +484,7 @@ static BlockDriverAIOCB *qemu_gluster_aio_flush(BlockDriverState *bs,
     GlusterAIOCB *acb;
     BDRVGlusterState *s = bs->opaque;
 
-    acb = qemu_aio_get(&gluster_aio_pool, bs, cb, opaque);
+    acb = qemu_aio_get(&gluster_aiocb_info, bs, cb, opaque);
     acb->size = 0;
     acb->ret = 0;
     acb->finished = NULL;
diff --git a/block/iscsi.c b/block/iscsi.c
index d0b1a10ee4..a6a819d68f 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -133,7 +133,7 @@ iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
     }
 }
 
-static AIOPool iscsi_aio_pool = {
+static const AIOCBInfo iscsi_aiocb_info = {
     .aiocb_size         = sizeof(IscsiAIOCB),
     .cancel             = iscsi_aio_cancel,
 };
@@ -234,7 +234,7 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
     uint64_t lba;
     struct iscsi_data data;
 
-    acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
+    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
     trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb);
 
     acb->iscsilun = iscsilun;
@@ -325,7 +325,7 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
 
     qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors;
 
-    acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
+    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
     trace_iscsi_aio_readv(iscsi, sector_num, nb_sectors, opaque, acb);
 
     acb->iscsilun = iscsilun;
@@ -430,7 +430,7 @@ iscsi_aio_flush(BlockDriverState *bs,
     struct iscsi_context *iscsi = iscsilun->iscsi;
     IscsiAIOCB *acb;
 
-    acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
+    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
 
     acb->iscsilun = iscsilun;
     acb->canceled   = 0;
@@ -483,7 +483,7 @@ iscsi_aio_discard(BlockDriverState *bs,
     IscsiAIOCB *acb;
     struct unmap_list list[1];
 
-    acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
+    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
 
     acb->iscsilun = iscsilun;
     acb->canceled   = 0;
@@ -558,7 +558,7 @@ static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
 
     assert(req == SG_IO);
 
-    acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
+    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
 
     acb->iscsilun = iscsilun;
     acb->canceled    = 0;
diff --git a/block/linux-aio.c b/block/linux-aio.c
index 6ca984dbe8..91ef863241 100644
--- a/block/linux-aio.c
+++ b/block/linux-aio.c
@@ -140,7 +140,7 @@ static void laio_cancel(BlockDriverAIOCB *blockacb)
     }
 }
 
-static AIOPool laio_pool = {
+static const AIOCBInfo laio_aiocb_info = {
     .aiocb_size         = sizeof(struct qemu_laiocb),
     .cancel             = laio_cancel,
 };
@@ -154,7 +154,7 @@ BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
     struct iocb *iocbs;
     off_t offset = sector_num * 512;
 
-    laiocb = qemu_aio_get(&laio_pool, bs, cb, opaque);
+    laiocb = qemu_aio_get(&laio_aiocb_info, bs, cb, opaque);
     laiocb->nbytes = nb_sectors * 512;
     laiocb->ctx = s;
     laiocb->ret = -EINPROGRESS;
diff --git a/block/qed.c b/block/qed.c
index 6c182ca917..0b5374a202 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -30,7 +30,7 @@ static void qed_aio_cancel(BlockDriverAIOCB *blockacb)
     }
 }
 
-static AIOPool qed_aio_pool = {
+static const AIOCBInfo qed_aiocb_info = {
     .aiocb_size         = sizeof(QEDAIOCB),
     .cancel             = qed_aio_cancel,
 };
@@ -1311,7 +1311,7 @@ static BlockDriverAIOCB *qed_aio_setup(BlockDriverState *bs,
                                        BlockDriverCompletionFunc *cb,
                                        void *opaque, int flags)
 {
-    QEDAIOCB *acb = qemu_aio_get(&qed_aio_pool, bs, cb, opaque);
+    QEDAIOCB *acb = qemu_aio_get(&qed_aiocb_info, bs, cb, opaque);
 
     trace_qed_aio_setup(bs->opaque, acb, sector_num, nb_sectors,
                         opaque, flags);
diff --git a/block/rbd.c b/block/rbd.c
index 015a9db0ad..0aaacaf859 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -570,7 +570,7 @@ static void qemu_rbd_aio_cancel(BlockDriverAIOCB *blockacb)
     acb->cancelled = 1;
 }
 
-static AIOPool rbd_aio_pool = {
+static const AIOCBInfo rbd_aiocb_info = {
     .aiocb_size = sizeof(RBDAIOCB),
     .cancel = qemu_rbd_aio_cancel,
 };
@@ -672,7 +672,7 @@ static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs,
 
     BDRVRBDState *s = bs->opaque;
 
-    acb = qemu_aio_get(&rbd_aio_pool, bs, cb, opaque);
+    acb = qemu_aio_get(&rbd_aiocb_info, bs, cb, opaque);
     acb->cmd = cmd;
     acb->qiov = qiov;
     if (cmd == RBD_AIO_DISCARD) {
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 93061744d6..a48f58cfe8 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -420,7 +420,7 @@ static void sd_aio_cancel(BlockDriverAIOCB *blockacb)
     acb->canceled = true;
 }
 
-static AIOPool sd_aio_pool = {
+static const AIOCBInfo sd_aiocb_info = {
     .aiocb_size = sizeof(SheepdogAIOCB),
     .cancel = sd_aio_cancel,
 };
@@ -431,7 +431,7 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
 {
     SheepdogAIOCB *acb;
 
-    acb = qemu_aio_get(&sd_aio_pool, bs, cb, opaque);
+    acb = qemu_aio_get(&sd_aiocb_info, bs, cb, opaque);
 
     acb->qiov = qiov;
 
diff --git a/block/win32-aio.c b/block/win32-aio.c
index 92f25a97e5..4704ee06c2 100644
--- a/block/win32-aio.c
+++ b/block/win32-aio.c
@@ -131,7 +131,7 @@ static void win32_aio_cancel(BlockDriverAIOCB *blockacb)
     }
 }
 
-static AIOPool win32_aio_pool = {
+static const AIOCBInfo win32_aiocb_info = {
     .aiocb_size         = sizeof(QEMUWin32AIOCB),
     .cancel             = win32_aio_cancel,
 };
@@ -145,7 +145,7 @@ BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
     uint64_t offset = sector_num * 512;
     DWORD rc;
 
-    waiocb = qemu_aio_get(&win32_aio_pool, bs, cb, opaque);
+    waiocb = qemu_aio_get(&win32_aiocb_info, bs, cb, opaque);
     waiocb->nbytes = nb_sectors * 512;
     waiocb->qiov = qiov;
     waiocb->is_read = (type == QEMU_AIO_READ);
diff --git a/dma-helpers.c b/dma-helpers.c
index 0c18e9e4d8..4f5fb649e7 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -195,7 +195,7 @@ static void dma_aio_cancel(BlockDriverAIOCB *acb)
     dma_complete(dbs, 0);
 }
 
-static AIOPool dma_aio_pool = {
+static const AIOCBInfo dma_aiocb_info = {
     .aiocb_size         = sizeof(DMAAIOCB),
     .cancel             = dma_aio_cancel,
 };
@@ -205,7 +205,7 @@ BlockDriverAIOCB *dma_bdrv_io(
     DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
     void *opaque, DMADirection dir)
 {
-    DMAAIOCB *dbs = qemu_aio_get(&dma_aio_pool, bs, cb, opaque);
+    DMAAIOCB *dbs = qemu_aio_get(&dma_aiocb_info, bs, cb, opaque);
 
     trace_dma_bdrv_io(dbs, bs, sector_num, (dir == DMA_DIRECTION_TO_DEVICE));
 
diff --git a/hw/ide/core.c b/hw/ide/core.c
index d683a8cc84..7d6b0fa7b4 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -336,7 +336,7 @@ static void trim_aio_cancel(BlockDriverAIOCB *acb)
     qemu_aio_release(iocb);
 }
 
-static AIOPool trim_aio_pool = {
+static const AIOCBInfo trim_aiocb_info = {
     .aiocb_size         = sizeof(TrimAIOCB),
     .cancel             = trim_aio_cancel,
 };
@@ -360,7 +360,7 @@ BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs,
     TrimAIOCB *iocb;
     int i, j, ret;
 
-    iocb = qemu_aio_get(&trim_aio_pool, bs, cb, opaque);
+    iocb = qemu_aio_get(&trim_aiocb_info, bs, cb, opaque);
     iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb);
     iocb->ret = 0;
 
diff --git a/qemu-aio.h b/qemu-aio.h
index b29c509f27..3889fe97a4 100644
--- a/qemu-aio.h
+++ b/qemu-aio.h
@@ -21,19 +21,19 @@
 typedef struct BlockDriverAIOCB BlockDriverAIOCB;
 typedef void BlockDriverCompletionFunc(void *opaque, int ret);
 
-typedef struct AIOPool {
+typedef struct AIOCBInfo {
     void (*cancel)(BlockDriverAIOCB *acb);
     size_t aiocb_size;
-} AIOPool;
+} AIOCBInfo;
 
 struct BlockDriverAIOCB {
-    AIOPool *pool;
+    const AIOCBInfo *aiocb_info;
     BlockDriverState *bs;
     BlockDriverCompletionFunc *cb;
     void *opaque;
 };
 
-void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
+void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs,
                    BlockDriverCompletionFunc *cb, void *opaque);
 void qemu_aio_release(void *p);
 
diff --git a/thread-pool.c b/thread-pool.c
index 651b32419b..204f70b7b5 100644
--- a/thread-pool.c
+++ b/thread-pool.c
@@ -216,7 +216,7 @@ static void thread_pool_cancel(BlockDriverAIOCB *acb)
     qemu_mutex_unlock(&lock);
 }
 
-static AIOPool thread_pool_cb_pool = {
+static const AIOCBInfo thread_pool_aiocb_info = {
     .aiocb_size         = sizeof(ThreadPoolElement),
     .cancel             = thread_pool_cancel,
 };
@@ -226,7 +226,7 @@ BlockDriverAIOCB *thread_pool_submit_aio(ThreadPoolFunc *func, void *arg,
 {
     ThreadPoolElement *req;
 
-    req = qemu_aio_get(&thread_pool_cb_pool, NULL, cb, opaque);
+    req = qemu_aio_get(&thread_pool_aiocb_info, NULL, cb, opaque);
     req->func = func;
     req->arg = arg;
     req->state = THREAD_QUEUED;

From 34abf9a7d82cd959622996733884469a33f7e2e0 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Mon, 3 Sep 2012 23:46:54 +0000
Subject: [PATCH 1607/2270] fdc: Remove status0 parameter from
 fdctrl_set_fifo()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

It decided whether an interrupt is triggered. Only one caller made use
of this functionality, so move the code there.

In this one caller, the interrupt must actually be triggered
unconditionally, like it was before commit 2fee0088. For example, a
successful read without an implied seek can result in st0 = 0, but still
triggers the interrupt.

Signed-off-by: Kevin Wolf 
Tested-by: Hervé Poussineau 
---
 hw/fdc.c | 33 ++++++++++++++++-----------------
 1 file changed, 16 insertions(+), 17 deletions(-)

diff --git a/hw/fdc.c b/hw/fdc.c
index bf8c1d9f13..3585220c82 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1079,15 +1079,12 @@ static void fdctrl_reset_fifo(FDCtrl *fdctrl)
 }
 
 /* Set FIFO status for the host to read */
-static void fdctrl_set_fifo(FDCtrl *fdctrl, int fifo_len, uint8_t status0)
+static void fdctrl_set_fifo(FDCtrl *fdctrl, int fifo_len)
 {
     fdctrl->data_dir = FD_DIR_READ;
     fdctrl->data_len = fifo_len;
     fdctrl->data_pos = 0;
     fdctrl->msr |= FD_MSR_CMDBUSY | FD_MSR_RQM | FD_MSR_DIO;
-    if (status0) {
-        fdctrl_raise_irq(fdctrl, status0);
-    }
 }
 
 /* Set an error: unimplemented/unknown command */
@@ -1096,7 +1093,7 @@ static void fdctrl_unimplemented(FDCtrl *fdctrl, int direction)
     qemu_log_mask(LOG_UNIMP, "fdc: unimplemented command 0x%02x\n",
                   fdctrl->fifo[0]);
     fdctrl->fifo[0] = FD_SR0_INVCMD;
-    fdctrl_set_fifo(fdctrl, 1, 0);
+    fdctrl_set_fifo(fdctrl, 1);
 }
 
 /* Seek to next sector
@@ -1170,7 +1167,9 @@ static void fdctrl_stop_transfer(FDCtrl *fdctrl, uint8_t status0,
     }
     fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
     fdctrl->msr &= ~FD_MSR_NONDMA;
-    fdctrl_set_fifo(fdctrl, 7, fdctrl->status0);
+
+    fdctrl_set_fifo(fdctrl, 7);
+    fdctrl_raise_irq(fdctrl, fdctrl->status0);
 }
 
 /* Prepare a data transfer (either DMA or FIFO) */
@@ -1536,7 +1535,7 @@ static void fdctrl_handle_lock(FDCtrl *fdctrl, int direction)
 {
     fdctrl->lock = (fdctrl->fifo[0] & 0x80) ? 1 : 0;
     fdctrl->fifo[0] = fdctrl->lock << 4;
-    fdctrl_set_fifo(fdctrl, 1, 0);
+    fdctrl_set_fifo(fdctrl, 1);
 }
 
 static void fdctrl_handle_dumpreg(FDCtrl *fdctrl, int direction)
@@ -1561,20 +1560,20 @@ static void fdctrl_handle_dumpreg(FDCtrl *fdctrl, int direction)
         (cur_drv->perpendicular << 2);
     fdctrl->fifo[8] = fdctrl->config;
     fdctrl->fifo[9] = fdctrl->precomp_trk;
-    fdctrl_set_fifo(fdctrl, 10, 0);
+    fdctrl_set_fifo(fdctrl, 10);
 }
 
 static void fdctrl_handle_version(FDCtrl *fdctrl, int direction)
 {
     /* Controller's version */
     fdctrl->fifo[0] = fdctrl->version;
-    fdctrl_set_fifo(fdctrl, 1, 0);
+    fdctrl_set_fifo(fdctrl, 1);
 }
 
 static void fdctrl_handle_partid(FDCtrl *fdctrl, int direction)
 {
     fdctrl->fifo[0] = 0x41; /* Stepping 1 */
-    fdctrl_set_fifo(fdctrl, 1, 0);
+    fdctrl_set_fifo(fdctrl, 1);
 }
 
 static void fdctrl_handle_restore(FDCtrl *fdctrl, int direction)
@@ -1627,7 +1626,7 @@ static void fdctrl_handle_save(FDCtrl *fdctrl, int direction)
     fdctrl->fifo[12] = fdctrl->pwrd;
     fdctrl->fifo[13] = 0;
     fdctrl->fifo[14] = 0;
-    fdctrl_set_fifo(fdctrl, 15, 0);
+    fdctrl_set_fifo(fdctrl, 15);
 }
 
 static void fdctrl_handle_readid(FDCtrl *fdctrl, int direction)
@@ -1693,7 +1692,7 @@ static void fdctrl_handle_sense_drive_status(FDCtrl *fdctrl, int direction)
         (cur_drv->head << 2) |
         GET_CUR_DRV(fdctrl) |
         0x28;
-    fdctrl_set_fifo(fdctrl, 1, 0);
+    fdctrl_set_fifo(fdctrl, 1);
 }
 
 static void fdctrl_handle_recalibrate(FDCtrl *fdctrl, int direction)
@@ -1718,7 +1717,7 @@ static void fdctrl_handle_sense_interrupt_status(FDCtrl *fdctrl, int direction)
         fdctrl->reset_sensei--;
     } else if (!(fdctrl->sra & FD_SRA_INTPEND)) {
         fdctrl->fifo[0] = FD_SR0_INVCMD;
-        fdctrl_set_fifo(fdctrl, 1, 0);
+        fdctrl_set_fifo(fdctrl, 1);
         return;
     } else {
         fdctrl->fifo[0] =
@@ -1727,7 +1726,7 @@ static void fdctrl_handle_sense_interrupt_status(FDCtrl *fdctrl, int direction)
     }
 
     fdctrl->fifo[1] = cur_drv->track;
-    fdctrl_set_fifo(fdctrl, 2, 0);
+    fdctrl_set_fifo(fdctrl, 2);
     fdctrl_reset_irq(fdctrl);
     fdctrl->status0 = FD_SR0_RDYCHG;
 }
@@ -1769,7 +1768,7 @@ static void fdctrl_handle_powerdown_mode(FDCtrl *fdctrl, int direction)
 {
     fdctrl->pwrd = fdctrl->fifo[1];
     fdctrl->fifo[0] = fdctrl->fifo[1];
-    fdctrl_set_fifo(fdctrl, 1, 0);
+    fdctrl_set_fifo(fdctrl, 1);
 }
 
 static void fdctrl_handle_option(FDCtrl *fdctrl, int direction)
@@ -1788,7 +1787,7 @@ static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direct
             fdctrl->fifo[0] = fdctrl->fifo[1];
             fdctrl->fifo[2] = 0;
             fdctrl->fifo[3] = 0;
-            fdctrl_set_fifo(fdctrl, 4, 0);
+            fdctrl_set_fifo(fdctrl, 4);
         } else {
             fdctrl_reset_fifo(fdctrl);
         }
@@ -1796,7 +1795,7 @@ static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direct
         /* ERROR */
         fdctrl->fifo[0] = 0x80 |
             (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
-        fdctrl_set_fifo(fdctrl, 1, 0);
+        fdctrl_set_fifo(fdctrl, 1);
     }
 }
 

From 1f507913762c03332a06232930ebb1f753992660 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= 
Date: Tue, 18 Sep 2012 22:48:48 +0200
Subject: [PATCH 1608/2270] fdc-test: split test_media_change() test, so insert
 part can be reused
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Hervé Poussineau 
Signed-off-by: Kevin Wolf 
---
 tests/fdc-test.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index fa7441110d..a4303d19d8 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -217,7 +217,7 @@ static void test_read_without_media(void)
     g_assert(ret == 0);
 }
 
-static void test_media_change(void)
+static void test_media_insert(void)
 {
     uint8_t dir;
 
@@ -245,6 +245,13 @@ static void test_media_change(void)
     assert_bit_clear(dir, DSKCHG);
     dir = inb(FLOPPY_BASE + reg_dir);
     assert_bit_clear(dir, DSKCHG);
+}
+
+static void test_media_change(void)
+{
+    uint8_t dir;
+
+    test_media_insert();
 
     /* Eject the floppy and check that DSKCHG is set. Reading it out doesn't
      * reset the bit. */

From 44212dcc467cfe20f0ffe89c35c1fbd7849ea924 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= 
Date: Tue, 18 Sep 2012 22:49:30 +0200
Subject: [PATCH 1609/2270] fdc-test: insert media before fuzzing registers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

A media will be required for future fdc tests.

Signed-off-by: Hervé Poussineau 
Signed-off-by: Kevin Wolf 
---
 tests/fdc-test.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index a4303d19d8..67bfb22174 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -376,6 +376,7 @@ int main(int argc, char **argv)
     qtest_add_func("/fdc/media_change", test_media_change);
     qtest_add_func("/fdc/sense_interrupt", test_sense_interrupt);
     qtest_add_func("/fdc/relative_seek", test_relative_seek);
+    qtest_add_func("/fdc/media_insert", test_media_insert);
     qtest_add_func("/fdc/fuzz-registers", fuzz_registers);
 
     ret = g_test_run();

From 5f8ae8e2b5eda3c03ea49bd6d9029562f156ad07 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= 
Date: Tue, 18 Sep 2012 23:02:59 +0200
Subject: [PATCH 1610/2270] fdc-test: add tests for non-DMA READ command
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Hervé Poussineau 
Signed-off-by: Kevin Wolf 
---
 tests/fdc-test.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 98 insertions(+)

diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index 67bfb22174..4649e3fedb 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -55,6 +55,8 @@ enum {
 };
 
 enum {
+    BUSY    = 0x10,
+    NONDMA  = 0x20,
     RQM     = 0x80,
     DIO     = 0x40,
 
@@ -166,6 +168,69 @@ static uint8_t send_read_command(void)
     return ret;
 }
 
+static uint8_t send_read_no_dma_command(int nb_sect, uint8_t expected_st0)
+{
+    uint8_t drive = 0;
+    uint8_t head = 0;
+    uint8_t cyl = 0;
+    uint8_t sect_addr = 1;
+    uint8_t sect_size = 2;
+    uint8_t eot = nb_sect;
+    uint8_t gap = 0x1b;
+    uint8_t gpl = 0xff;
+
+    uint8_t msr = 0;
+    uint8_t st0;
+
+    uint8_t ret = 0;
+
+    floppy_send(CMD_READ);
+    floppy_send(head << 2 | drive);
+    g_assert(!get_irq(FLOPPY_IRQ));
+    floppy_send(cyl);
+    floppy_send(head);
+    floppy_send(sect_addr);
+    floppy_send(sect_size);
+    floppy_send(eot);
+    floppy_send(gap);
+    floppy_send(gpl);
+
+    uint16_t i = 0;
+    uint8_t n = 2;
+    for (; i < n; i++) {
+        msr = inb(FLOPPY_BASE + reg_msr);
+        if (msr == (BUSY | NONDMA | DIO | RQM)) {
+            break;
+        }
+        sleep(1);
+    }
+
+    if (i >= n) {
+        return 1;
+    }
+
+    /* Non-DMA mode */
+    for (i = 0; i < 512 * 2 * nb_sect; i++) {
+        msr = inb(FLOPPY_BASE + reg_msr);
+        assert_bit_set(msr, BUSY | RQM | DIO);
+        inb(FLOPPY_BASE + reg_fifo);
+    }
+
+    st0 = floppy_recv();
+    if (st0 != expected_st0) {
+        ret = 1;
+    }
+
+    floppy_recv();
+    floppy_recv();
+    floppy_recv();
+    floppy_recv();
+    floppy_recv();
+    floppy_recv();
+
+    return ret;
+}
+
 static void send_seek(int cyl)
 {
     int drive = 0;
@@ -327,6 +392,36 @@ static void test_relative_seek(void)
     g_assert(pcn == 0);
 }
 
+static void test_read_no_dma_1(void)
+{
+    uint8_t ret;
+
+    outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
+    send_seek(0);
+    ret = send_read_no_dma_command(1, 0x24); /* FIXME: should be 0x04 */
+    g_assert(ret == 0);
+}
+
+static void test_read_no_dma_18(void)
+{
+    uint8_t ret;
+
+    outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
+    send_seek(0);
+    ret = send_read_no_dma_command(18, 0x24); /* FIXME: should be 0x04 */
+    g_assert(ret == 0);
+}
+
+static void test_read_no_dma_19(void)
+{
+    uint8_t ret;
+
+    outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
+    send_seek(0);
+    ret = send_read_no_dma_command(19, 0x20);
+    g_assert(ret == 0);
+}
+
 /* success if no crash or abort */
 static void fuzz_registers(void)
 {
@@ -377,6 +472,9 @@ int main(int argc, char **argv)
     qtest_add_func("/fdc/sense_interrupt", test_sense_interrupt);
     qtest_add_func("/fdc/relative_seek", test_relative_seek);
     qtest_add_func("/fdc/media_insert", test_media_insert);
+    qtest_add_func("/fdc/read_no_dma_1", test_read_no_dma_1);
+    qtest_add_func("/fdc/read_no_dma_18", test_read_no_dma_18);
+    qtest_add_func("/fdc/read_no_dma_19", test_read_no_dma_19);
     qtest_add_func("/fdc/fuzz-registers", fuzz_registers);
 
     ret = g_test_run();

From d497d53497070322e04796a9958e551d88c9f3a9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= 
Date: Sun, 19 Aug 2012 10:21:14 +0200
Subject: [PATCH 1611/2270] fdc: use status0 field instead of a local variable
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Hervé Poussineau 
Signed-off-by: Kevin Wolf 
---
 hw/fdc.c | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/hw/fdc.c b/hw/fdc.c
index 3585220c82..7e4b0ce0dc 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -327,7 +327,7 @@ static void fdctrl_reset(FDCtrl *fdctrl, int do_irq);
 static void fdctrl_reset_fifo(FDCtrl *fdctrl);
 static int fdctrl_transfer_handler (void *opaque, int nchan,
                                     int dma_pos, int dma_len);
-static void fdctrl_raise_irq(FDCtrl *fdctrl, uint8_t status0);
+static void fdctrl_raise_irq(FDCtrl *fdctrl);
 static FDrive *get_cur_drv(FDCtrl *fdctrl);
 
 static uint32_t fdctrl_read_statusA(FDCtrl *fdctrl);
@@ -799,6 +799,7 @@ static void fdctrl_handle_tc(void *opaque, int irq, int level)
 /* Change IRQ state */
 static void fdctrl_reset_irq(FDCtrl *fdctrl)
 {
+    fdctrl->status0 = 0;
     if (!(fdctrl->sra & FD_SRA_INTPEND))
         return;
     FLOPPY_DPRINTF("Reset interrupt\n");
@@ -806,14 +807,13 @@ static void fdctrl_reset_irq(FDCtrl *fdctrl)
     fdctrl->sra &= ~FD_SRA_INTPEND;
 }
 
-static void fdctrl_raise_irq(FDCtrl *fdctrl, uint8_t status0)
+static void fdctrl_raise_irq(FDCtrl *fdctrl)
 {
     /* Sparc mutation */
     if (fdctrl->sun4m && (fdctrl->msr & FD_MSR_CMDBUSY)) {
         /* XXX: not sure */
         fdctrl->msr &= ~FD_MSR_CMDBUSY;
         fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
-        fdctrl->status0 = status0;
         return;
     }
     if (!(fdctrl->sra & FD_SRA_INTPEND)) {
@@ -822,7 +822,6 @@ static void fdctrl_raise_irq(FDCtrl *fdctrl, uint8_t status0)
     }
 
     fdctrl->reset_sensei = 0;
-    fdctrl->status0 = status0;
     FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", fdctrl->status0);
 }
 
@@ -851,7 +850,8 @@ static void fdctrl_reset(FDCtrl *fdctrl, int do_irq)
         fd_recalibrate(&fdctrl->drives[i]);
     fdctrl_reset_fifo(fdctrl);
     if (do_irq) {
-        fdctrl_raise_irq(fdctrl, FD_SR0_RDYCHG);
+        fdctrl->status0 |= FD_SR0_RDYCHG;
+        fdctrl_raise_irq(fdctrl);
         fdctrl->reset_sensei = FD_RESET_SENSEI_COUNT;
     }
 }
@@ -1169,7 +1169,7 @@ static void fdctrl_stop_transfer(FDCtrl *fdctrl, uint8_t status0,
     fdctrl->msr &= ~FD_MSR_NONDMA;
 
     fdctrl_set_fifo(fdctrl, 7);
-    fdctrl_raise_irq(fdctrl, fdctrl->status0);
+    fdctrl_raise_irq(fdctrl);
 }
 
 /* Prepare a data transfer (either DMA or FIFO) */
@@ -1284,7 +1284,8 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
     if (direction != FD_DIR_WRITE)
         fdctrl->msr |= FD_MSR_DIO;
     /* IO based transfer: calculate len */
-    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
+    fdctrl->status0 |= FD_SR0_SEEK;
+    fdctrl_raise_irq(fdctrl);
 }
 
 /* Prepare a transfer of deleted data */
@@ -1704,7 +1705,8 @@ static void fdctrl_handle_recalibrate(FDCtrl *fdctrl, int direction)
     fd_recalibrate(cur_drv);
     fdctrl_reset_fifo(fdctrl);
     /* Raise Interrupt */
-    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
+    fdctrl->status0 |= FD_SR0_SEEK;
+    fdctrl_raise_irq(fdctrl);
 }
 
 static void fdctrl_handle_sense_interrupt_status(FDCtrl *fdctrl, int direction)
@@ -1743,7 +1745,8 @@ static void fdctrl_handle_seek(FDCtrl *fdctrl, int direction)
      */
     fd_seek(cur_drv, cur_drv->head, fdctrl->fifo[2], cur_drv->sect, 1);
     /* Raise Interrupt */
-    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
+    fdctrl->status0 |= FD_SR0_SEEK;
+    fdctrl_raise_irq(fdctrl);
 }
 
 static void fdctrl_handle_perpendicular_mode(FDCtrl *fdctrl, int direction)
@@ -1814,7 +1817,8 @@ static void fdctrl_handle_relative_seek_in(FDCtrl *fdctrl, int direction)
     }
     fdctrl_reset_fifo(fdctrl);
     /* Raise Interrupt */
-    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
+    fdctrl->status0 |= FD_SR0_SEEK;
+    fdctrl_raise_irq(fdctrl);
 }
 
 static void fdctrl_handle_relative_seek_out(FDCtrl *fdctrl, int direction)
@@ -1831,7 +1835,8 @@ static void fdctrl_handle_relative_seek_out(FDCtrl *fdctrl, int direction)
     }
     fdctrl_reset_fifo(fdctrl);
     /* Raise Interrupt */
-    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
+    fdctrl->status0 |= FD_SR0_SEEK;
+    fdctrl_raise_irq(fdctrl);
 }
 
 static const struct {

From c5139bd9a9d78053a4da5047deb34e478a52d669 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= 
Date: Thu, 20 Sep 2012 22:50:17 +0200
Subject: [PATCH 1612/2270] fdc: fix FD_SR0_SEEK for non-DMA transfers and
 multi sectors transfers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

On non-DMA transfers, fdctrl_stop_transfer() used to set FD_SR0_SEEK
no matter if there actually was a seek or not. This is obviously wrong.

fdctrl_seek_to_next_sect() has this information because it performs
the seek itself.

Signed-off-by: Hervé Poussineau 
Signed-off-by: Kevin Wolf 
---
 hw/fdc.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/fdc.c b/hw/fdc.c
index 7e4b0ce0dc..e47050f5a5 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1123,11 +1123,13 @@ static int fdctrl_seek_to_next_sect(FDCtrl *fdctrl, FDrive *cur_drv)
             } else {
                 new_head = 0;
                 new_track++;
+                fdctrl->status0 |= FD_SR0_SEEK;
                 if ((cur_drv->flags & FDISK_DBL_SIDES) == 0) {
                     ret = 0;
                 }
             }
         } else {
+            fdctrl->status0 |= FD_SR0_SEEK;
             new_track++;
             ret = 0;
         }
@@ -1458,7 +1460,7 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
          * then from status mode to command mode
          */
         if (fdctrl->msr & FD_MSR_NONDMA) {
-            fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
+            fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
         } else {
             fdctrl_reset_fifo(fdctrl);
             fdctrl_reset_irq(fdctrl);
@@ -1922,7 +1924,7 @@ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
          * then from status mode to command mode
          */
         if (fdctrl->data_pos == fdctrl->data_len)
-            fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
+            fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
         return;
     }
     if (fdctrl->data_pos == 0) {

From d6ed4e21060d13a2faf7c1c9d121e68a16a411f8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= 
Date: Thu, 20 Sep 2012 23:01:58 +0200
Subject: [PATCH 1613/2270] fdc: fix FD_SR0_SEEK for initial seek on DMA
 transfers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

fdctrl_start_transfer() used to set FD_SR0_SEEK no matter if
there actually was a seek or not. This is obviously wrong.

fdctrl_start_transfer() has this information because it performs
the initial seek itself.

Signed-off-by: Hervé Poussineau 
Signed-off-by: Kevin Wolf 
---
 hw/fdc.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/hw/fdc.c b/hw/fdc.c
index e47050f5a5..a9a2a2a10a 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1179,7 +1179,6 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
 {
     FDrive *cur_drv;
     uint8_t kh, kt, ks;
-    int did_seek = 0;
 
     SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
     cur_drv = get_cur_drv(fdctrl);
@@ -1213,7 +1212,7 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
         fdctrl->fifo[5] = ks;
         return;
     case 1:
-        did_seek = 1;
+        fdctrl->status0 |= FD_SR0_SEEK;
         break;
     default:
         break;
@@ -1240,10 +1239,6 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
         fdctrl->data_state |= FD_STATE_MULTI;
     else
         fdctrl->data_state &= ~FD_STATE_MULTI;
-    if (did_seek)
-        fdctrl->data_state |= FD_STATE_SEEK;
-    else
-        fdctrl->data_state &= ~FD_STATE_SEEK;
     if (fdctrl->fifo[5] == 00) {
         fdctrl->data_len = fdctrl->fifo[8];
     } else {
@@ -1286,7 +1281,6 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
     if (direction != FD_DIR_WRITE)
         fdctrl->msr |= FD_MSR_DIO;
     /* IO based transfer: calculate len */
-    fdctrl->status0 |= FD_SR0_SEEK;
     fdctrl_raise_irq(fdctrl);
 }
 

From 075f5532f182a12d8c89352f876363f110722e82 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= 
Date: Thu, 20 Sep 2012 23:07:53 +0200
Subject: [PATCH 1614/2270] fdc: fix false FD_SR0_SEEK
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Do not always set FD_SR0_SEEK, as callers already set it if needed.

Signed-off-by: Hervé Poussineau 
Signed-off-by: Kevin Wolf 
---
 hw/fdc.c         | 10 +++++++---
 tests/fdc-test.c |  6 +++---
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/hw/fdc.c b/hw/fdc.c
index a9a2a2a10a..525ba20194 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1149,10 +1149,14 @@ static void fdctrl_stop_transfer(FDCtrl *fdctrl, uint8_t status0,
                                  uint8_t status1, uint8_t status2)
 {
     FDrive *cur_drv;
-
     cur_drv = get_cur_drv(fdctrl);
-    fdctrl->status0 = status0 | FD_SR0_SEEK | (cur_drv->head << 2) |
-                      GET_CUR_DRV(fdctrl);
+
+    fdctrl->status0 &= ~(FD_SR0_DS0 | FD_SR0_DS1 | FD_SR0_HEAD);
+    fdctrl->status0 |= GET_CUR_DRV(fdctrl);
+    if (cur_drv->head) {
+        fdctrl->status0 |= FD_SR0_HEAD;
+    }
+    fdctrl->status0 |= status0;
 
     FLOPPY_DPRINTF("transfer status: %02x %02x %02x (%02x)\n",
                    status0, status1, status2, fdctrl->status0);
diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index 4649e3fedb..1156112028 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -154,7 +154,7 @@ static uint8_t send_read_command(void)
     }
 
     st0 = floppy_recv();
-    if (st0 != 0x60) {
+    if (st0 != 0x40) {
         ret = 1;
     }
 
@@ -398,7 +398,7 @@ static void test_read_no_dma_1(void)
 
     outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
     send_seek(0);
-    ret = send_read_no_dma_command(1, 0x24); /* FIXME: should be 0x04 */
+    ret = send_read_no_dma_command(1, 0x04);
     g_assert(ret == 0);
 }
 
@@ -408,7 +408,7 @@ static void test_read_no_dma_18(void)
 
     outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
     send_seek(0);
-    ret = send_read_no_dma_command(18, 0x24); /* FIXME: should be 0x04 */
+    ret = send_read_no_dma_command(18, 0x04);
     g_assert(ret == 0);
 }
 

From 67f194bd815374fa7d5cb97d415f28f98b840378 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Thu, 20 Sep 2012 23:20:07 +0200
Subject: [PATCH 1615/2270] fdc-test: Check READ ID
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

ST0 shouldn't include 0x20 (FD_SR0_SEEK) after READ ID.

Signed-off-by: Kevin Wolf 
Tested-by: Hervé Poussineau 
---
 tests/fdc-test.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index 1156112028..e8ce6867a6 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -48,6 +48,7 @@ enum {
 
 enum {
     CMD_SENSE_INT           = 0x08,
+    CMD_READ_ID             = 0x0a,
     CMD_SEEK                = 0x0f,
     CMD_READ                = 0xe6,
     CMD_RELATIVE_SEEK_OUT   = 0x8f,
@@ -392,6 +393,70 @@ static void test_relative_seek(void)
     g_assert(pcn == 0);
 }
 
+static void test_read_id(void)
+{
+    uint8_t drive = 0;
+    uint8_t head = 0;
+    uint8_t cyl;
+    uint8_t st0;
+
+    /* Seek to track 0 and check with READ ID */
+    send_seek(0);
+
+    floppy_send(CMD_READ_ID);
+    g_assert(!get_irq(FLOPPY_IRQ));
+    floppy_send(head << 2 | drive);
+
+    while (!get_irq(FLOPPY_IRQ)) {
+        /* qemu involves a timer with READ ID... */
+        clock_step(1000000000LL / 50);
+    }
+
+    st0 = floppy_recv();
+    floppy_recv();
+    floppy_recv();
+    cyl = floppy_recv();
+    head = floppy_recv();
+    floppy_recv();
+    floppy_recv();
+
+    g_assert_cmpint(cyl, ==, 0);
+    g_assert_cmpint(head, ==, 0);
+    g_assert_cmpint(st0, ==, head << 2);
+
+    /* Seek to track 8 on head 1 and check with READ ID */
+    head = 1;
+    cyl = 8;
+
+    floppy_send(CMD_SEEK);
+    floppy_send(head << 2 | drive);
+    g_assert(!get_irq(FLOPPY_IRQ));
+    floppy_send(cyl);
+    g_assert(get_irq(FLOPPY_IRQ));
+    ack_irq(NULL);
+
+    floppy_send(CMD_READ_ID);
+    g_assert(!get_irq(FLOPPY_IRQ));
+    floppy_send(head << 2 | drive);
+
+    while (!get_irq(FLOPPY_IRQ)) {
+        /* qemu involves a timer with READ ID... */
+        clock_step(1000000000LL / 50);
+    }
+
+    st0 = floppy_recv();
+    floppy_recv();
+    floppy_recv();
+    cyl = floppy_recv();
+    head = floppy_recv();
+    floppy_recv();
+    floppy_recv();
+
+    g_assert_cmpint(cyl, ==, 8);
+    g_assert_cmpint(head, ==, 1);
+    g_assert_cmpint(st0, ==, head << 2);
+}
+
 static void test_read_no_dma_1(void)
 {
     uint8_t ret;
@@ -471,6 +536,7 @@ int main(int argc, char **argv)
     qtest_add_func("/fdc/media_change", test_media_change);
     qtest_add_func("/fdc/sense_interrupt", test_sense_interrupt);
     qtest_add_func("/fdc/relative_seek", test_relative_seek);
+    qtest_add_func("/fdc/read_id", test_read_id);
     qtest_add_func("/fdc/media_insert", test_media_insert);
     qtest_add_func("/fdc/read_no_dma_1", test_read_no_dma_1);
     qtest_add_func("/fdc/read_no_dma_18", test_read_no_dma_18);

From 7ea004ed67e08462926a8559e1c6953e387e4035 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= 
Date: Tue, 18 Sep 2012 23:04:10 +0200
Subject: [PATCH 1616/2270] fdc: implement VERIFY command
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

VERIFY command is like a READ command, except that read data is not
transfered by DMA.
As DMA engine is not used, so we have to start data transfer ourselves.

Signed-off-by: Hervé Poussineau 
Signed-off-by: Kevin Wolf 
---
 hw/fdc.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/hw/fdc.c b/hw/fdc.c
index 525ba20194..3a82ed11fc 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -349,6 +349,7 @@ enum {
     FD_DIR_SCANE   = 2,
     FD_DIR_SCANL   = 3,
     FD_DIR_SCANH   = 4,
+    FD_DIR_VERIFY  = 5,
 };
 
 enum {
@@ -1266,14 +1267,21 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
         if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL ||
               direction == FD_DIR_SCANH) && dma_mode == 0) ||
             (direction == FD_DIR_WRITE && dma_mode == 2) ||
-            (direction == FD_DIR_READ && dma_mode == 1)) {
+            (direction == FD_DIR_READ && dma_mode == 1) ||
+            (direction == FD_DIR_VERIFY)) {
             /* No access is allowed until DMA transfer has completed */
             fdctrl->msr &= ~FD_MSR_RQM;
-            /* Now, we just have to wait for the DMA controller to
-             * recall us...
-             */
-            DMA_hold_DREQ(fdctrl->dma_chann);
-            DMA_schedule(fdctrl->dma_chann);
+            if (direction != FD_DIR_VERIFY) {
+                /* Now, we just have to wait for the DMA controller to
+                 * recall us...
+                 */
+                DMA_hold_DREQ(fdctrl->dma_chann);
+                DMA_schedule(fdctrl->dma_chann);
+            } else {
+                /* Start transfer */
+                fdctrl_transfer_handler(fdctrl, fdctrl->dma_chann, 0,
+                                        fdctrl->data_len);
+            }
             return;
         } else {
             FLOPPY_DPRINTF("bad dma_mode=%d direction=%d\n", dma_mode,
@@ -1376,6 +1384,9 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
                 goto transfer_error;
             }
             break;
+        case FD_DIR_VERIFY:
+            /* VERIFY commands */
+            break;
         default:
             /* SCAN commands */
             {
@@ -1858,7 +1869,7 @@ static const struct {
     { FD_CMD_SAVE, 0xff, "SAVE", 0, fdctrl_handle_save }, /* part of READ DELETED DATA */
     { FD_CMD_READ_DELETED, 0x1f, "READ DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_READ },
     { FD_CMD_SCAN_EQUAL, 0x1f, "SCAN EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANE },
-    { FD_CMD_VERIFY, 0x1f, "VERIFY", 8, fdctrl_unimplemented },
+    { FD_CMD_VERIFY, 0x1f, "VERIFY", 8, fdctrl_start_transfer, FD_DIR_VERIFY },
     { FD_CMD_SCAN_LOW_OR_EQUAL, 0x1f, "SCAN LOW OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANL },
     { FD_CMD_SCAN_HIGH_OR_EQUAL, 0x1f, "SCAN HIGH OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANH },
     { FD_CMD_WRITE_DELETED, 0x3f, "WRITE DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_WRITE },

From 6f442fe83821a06c5408056c7879e83a74f2ff32 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= 
Date: Tue, 18 Sep 2012 23:04:56 +0200
Subject: [PATCH 1617/2270] fdc-tests: add tests for VERIFY command
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Hervé Poussineau 
Signed-off-by: Kevin Wolf 
---
 tests/fdc-test.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index e8ce6867a6..4b0301da46 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -50,6 +50,7 @@ enum {
     CMD_SENSE_INT           = 0x08,
     CMD_READ_ID             = 0x0a,
     CMD_SEEK                = 0x0f,
+    CMD_VERIFY              = 0x16,
     CMD_READ                = 0xe6,
     CMD_RELATIVE_SEEK_OUT   = 0x8f,
     CMD_RELATIVE_SEEK_IN    = 0xcf,
@@ -113,7 +114,7 @@ static void ack_irq(uint8_t *pcn)
     g_assert(!get_irq(FLOPPY_IRQ));
 }
 
-static uint8_t send_read_command(void)
+static uint8_t send_read_command(uint8_t cmd)
 {
     uint8_t drive = 0;
     uint8_t head = 0;
@@ -129,7 +130,7 @@ static uint8_t send_read_command(void)
 
     uint8_t ret = 0;
 
-    floppy_send(CMD_READ);
+    floppy_send(cmd);
     floppy_send(head << 2 | drive);
     g_assert(!get_irq(FLOPPY_IRQ));
     floppy_send(cyl);
@@ -279,7 +280,7 @@ static void test_read_without_media(void)
 {
     uint8_t ret;
 
-    ret = send_read_command();
+    ret = send_read_command(CMD_READ);
     g_assert(ret == 0);
 }
 
@@ -487,6 +488,14 @@ static void test_read_no_dma_19(void)
     g_assert(ret == 0);
 }
 
+static void test_verify(void)
+{
+    uint8_t ret;
+
+    ret = send_read_command(CMD_VERIFY);
+    g_assert(ret == 0);
+}
+
 /* success if no crash or abort */
 static void fuzz_registers(void)
 {
@@ -537,6 +546,7 @@ int main(int argc, char **argv)
     qtest_add_func("/fdc/sense_interrupt", test_sense_interrupt);
     qtest_add_func("/fdc/relative_seek", test_relative_seek);
     qtest_add_func("/fdc/read_id", test_read_id);
+    qtest_add_func("/fdc/verify", test_verify);
     qtest_add_func("/fdc/media_insert", test_media_insert);
     qtest_add_func("/fdc/read_no_dma_1", test_read_no_dma_1);
     qtest_add_func("/fdc/read_no_dma_18", test_read_no_dma_18);

From 27c86e24e9d6b2bbe15c16bc09eba5bd6fa094f2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= 
Date: Sun, 19 Aug 2012 22:04:43 +0200
Subject: [PATCH 1618/2270] fdc: remove double affectation of FD_MSR_CMDBUSY
 flag
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

FD_MSR_CMDBUSY flag is already set in fdctrl_write_data(), just
before calling the command handler (fdctrl_start_transfer() here).

Signed-off-by: Hervé Poussineau 
Signed-off-by: Kevin Wolf 
---
 hw/fdc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/fdc.c b/hw/fdc.c
index 3a82ed11fc..a197c48b97 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1239,7 +1239,7 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
     /* Set the FIFO state */
     fdctrl->data_dir = direction;
     fdctrl->data_pos = 0;
-    fdctrl->msr |= FD_MSR_CMDBUSY;
+    assert(fdctrl->msr & FD_MSR_CMDBUSY);
     if (fdctrl->fifo[0] & 0x80)
         fdctrl->data_state |= FD_STATE_MULTI;
     else

From c83f97b563b5eb8ae5d10e6653f5f3f0f8c71b02 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= 
Date: Mon, 20 Aug 2012 13:50:34 +0200
Subject: [PATCH 1619/2270] fdc: fix typo in zero constant
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Hervé Poussineau 
Signed-off-by: Kevin Wolf 
---
 hw/fdc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/fdc.c b/hw/fdc.c
index a197c48b97..de8778b7fa 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1244,7 +1244,7 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
         fdctrl->data_state |= FD_STATE_MULTI;
     else
         fdctrl->data_state &= ~FD_STATE_MULTI;
-    if (fdctrl->fifo[5] == 00) {
+    if (fdctrl->fifo[5] == 0) {
         fdctrl->data_len = fdctrl->fifo[8];
     } else {
         int tmp;

From cd30b53d22c96bddefab3f4b396e4d49da17f434 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= 
Date: Thu, 20 Sep 2012 23:11:58 +0200
Subject: [PATCH 1620/2270] fdc: remove last usage of FD_STATE_SEEK
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Replace it by directly setting FD_SR0_SEEK if required

Signed-off-by: Hervé Poussineau 
Signed-off-by: Kevin Wolf 
---
 hw/fdc.c | 12 ++----------
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/hw/fdc.c b/hw/fdc.c
index de8778b7fa..29b5449ff8 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -355,7 +355,6 @@ enum {
 enum {
     FD_STATE_MULTI  = 0x01,	/* multi track flag */
     FD_STATE_FORMAT = 0x02,	/* format flag */
-    FD_STATE_SEEK   = 0x04,	/* seek flag */
 };
 
 enum {
@@ -497,7 +496,6 @@ enum {
 };
 
 #define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI)
-#define FD_DID_SEEK(state) ((state) & FD_STATE_SEEK)
 #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT)
 
 struct FDCtrl {
@@ -1422,8 +1420,6 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
         fdctrl->data_dir == FD_DIR_SCANL ||
         fdctrl->data_dir == FD_DIR_SCANH)
         status2 = FD_SR2_SEH;
-    if (FD_DID_SEEK(fdctrl->data_state))
-        status0 |= FD_SR0_SEEK;
     fdctrl->data_len -= len;
     fdctrl_stop_transfer(fdctrl, status0, status1, status2);
  transfer_error:
@@ -1517,7 +1513,7 @@ static void fdctrl_format_sector(FDCtrl *fdctrl)
         fdctrl->fifo[5] = ks;
         return;
     case 1:
-        fdctrl->data_state |= FD_STATE_SEEK;
+        fdctrl->status0 |= FD_SR0_SEEK;
         break;
     default:
         break;
@@ -1531,10 +1527,7 @@ static void fdctrl_format_sector(FDCtrl *fdctrl)
         if (cur_drv->sect == cur_drv->last_sect) {
             fdctrl->data_state &= ~FD_STATE_FORMAT;
             /* Last sector done */
-            if (FD_DID_SEEK(fdctrl->data_state))
-                fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
-            else
-                fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
+            fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
         } else {
             /* More to do */
             fdctrl->data_pos = 0;
@@ -1661,7 +1654,6 @@ static void fdctrl_handle_format_track(FDCtrl *fdctrl, int direction)
         fdctrl->data_state |= FD_STATE_MULTI;
     else
         fdctrl->data_state &= ~FD_STATE_MULTI;
-    fdctrl->data_state &= ~FD_STATE_SEEK;
     cur_drv->bps =
         fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2];
 #if 0

From b1649fae49a899a222c3ac53c5009dd6f23349e1 Mon Sep 17 00:00:00 2001
From: Gerhard Wiesinger 
Date: Sat, 10 Nov 2012 09:22:18 +0100
Subject: [PATCH 1621/2270] vmdk: Fix data corruption bug in WRITE and READ
 handling

Fixed a MAJOR BUG in VMDK files on file boundaries on reads
and ALSO ON WRITES WHICH MIGHT CORRUPT THE IMAGE AND DATA!!!!!!

Triggered for example with the following VMDK file (partly listed):
RW 4193792 FLAT "XP-W1-f001.vmdk" 0
RW 2097664 FLAT "XP-W1-f002.vmdk" 0
RW 4193792 FLAT "XP-W1-f003.vmdk" 0
RW 512 FLAT "XP-W1-f004.vmdk" 0
RW 4193792 FLAT "XP-W1-f005.vmdk" 0
RW 2097664 FLAT "XP-W1-f006.vmdk" 0
RW 4193792 FLAT "XP-W1-f007.vmdk" 0
RW 512 FLAT "XP-W1-f008.vmdk" 0

Patch includes:
1.) Patch fixes wrong calculation on extent boundaries. Especially it
fixes the relativeness of the sector number to the current extent.

Verfied correctness with:
1.) Converted either with Virtualbox to VDI and then with qemu-img and
    then with qemu-img only:

    VBoxManage clonehd --format vdi /VM/XP-W/new/XP-W1.vmdk ~/.VirtualBox/Harddisks/XP-W1-new-test.vdi
    ./qemu-img convert -O raw ~/.VirtualBox/Harddisks/XP-W1-new-test.vdi /root/QEMU/VM-XP-W1/XP-W1-via-VBOX.img
    md5sum /root/QEMU/VM-XP-W/XP-W1-direct.img
    md5sum /root/QEMU/VM-XP-W/XP-W1-via-VBOX.img
    => same MD5 hash

2.) Verified debug log files
3.) Run Windows XP successfully
4.) chkdsk run successfully without any errors

Signed-off-by: Gerhard Wiesinger 
Acked-by: Fam Zheng 
Signed-off-by: Kevin Wolf 
---
 block/vmdk.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/block/vmdk.c b/block/vmdk.c
index 1a80e5a247..51398c0c08 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1092,6 +1092,7 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
     BDRVVmdkState *s = bs->opaque;
     int ret;
     uint64_t n, index_in_cluster;
+    uint64_t extent_begin_sector, extent_relative_sector_num;
     VmdkExtent *extent = NULL;
     uint64_t cluster_offset;
 
@@ -1103,7 +1104,9 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
         ret = get_cluster_offset(
                             bs, extent, NULL,
                             sector_num << 9, 0, &cluster_offset);
-        index_in_cluster = sector_num % extent->cluster_sectors;
+        extent_begin_sector = extent->end_sector - extent->sectors;
+        extent_relative_sector_num = sector_num - extent_begin_sector;
+        index_in_cluster = extent_relative_sector_num % extent->cluster_sectors;
         n = extent->cluster_sectors - index_in_cluster;
         if (n > nb_sectors) {
             n = nb_sectors;
@@ -1154,6 +1157,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
     VmdkExtent *extent = NULL;
     int n, ret;
     int64_t index_in_cluster;
+    uint64_t extent_begin_sector, extent_relative_sector_num;
     uint64_t cluster_offset;
     VmdkMetaData m_data;
 
@@ -1196,7 +1200,9 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
         if (ret) {
             return -EINVAL;
         }
-        index_in_cluster = sector_num % extent->cluster_sectors;
+        extent_begin_sector = extent->end_sector - extent->sectors;
+        extent_relative_sector_num = sector_num - extent_begin_sector;
+        index_in_cluster = extent_relative_sector_num % extent->cluster_sectors;
         n = extent->cluster_sectors - index_in_cluster;
         if (n > nb_sectors) {
             n = nb_sectors;

From b618f4a1c15d793c16c159059dd6f173e3e20f3e Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Tue, 13 Nov 2012 16:39:48 +0100
Subject: [PATCH 1622/2270] megasas: Use bdrv_drain_all instead of
 qemu_aio_flush

Calling qemu_aio_flush() directly can hang when combined with I/O
throttling.

Signed-off-by: Kevin Wolf 
Acked-by: Paolo Bonzini 
---
 hw/megasas.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/megasas.c b/hw/megasas.c
index 291ff40403..61b6527928 100644
--- a/hw/megasas.c
+++ b/hw/megasas.c
@@ -1296,7 +1296,7 @@ static int megasas_dcmd_get_properties(MegasasState *s, MegasasCmd *cmd)
 
 static int megasas_cache_flush(MegasasState *s, MegasasCmd *cmd)
 {
-    qemu_aio_flush();
+    bdrv_drain_all();
     return MFI_STAT_OK;
 }
 

From e7c8b094c2cf4f7e1609e24efffe3632cba84346 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Tue, 13 Nov 2012 16:41:22 +0100
Subject: [PATCH 1623/2270] qemu-io: Use bdrv_drain_all instead of
 qemu_aio_flush

This is harmless as of today because I/O throttling is not used in
qemu-io, however as soon as .bdrv_drain handlers will be introduced,
qemu-io must be sure to call bdrv_drain_all().

Signed-off-by: Kevin Wolf 
---
 qemu-io.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/qemu-io.c b/qemu-io.c
index 1ad7d3adb9..92cdb2ab9c 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1362,7 +1362,7 @@ static int aio_write_f(int argc, char **argv)
 
 static int aio_flush_f(int argc, char **argv)
 {
-    qemu_aio_flush();
+    bdrv_drain_all();
     return 0;
 }
 

From b0b873a07872f7ab7f66f259c73fb9dd42aa66a9 Mon Sep 17 00:00:00 2001
From: Marcelo Tosatti 
Date: Tue, 30 Oct 2012 21:14:19 -0200
Subject: [PATCH 1624/2270] acpi_piix4: fix migration of gpe fields

Migrate 16 bytes for en/sts fields (which is the correct size),
increase version to 3, and document how to support incoming
migration from qemu-kvm 1.2.

Acked-by: Paolo Bonzini 
Signed-off-by: Marcelo Tosatti 
---
 hw/acpi_piix4.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 46 insertions(+), 4 deletions(-)

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 15275cf3e5..519269a013 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -235,10 +235,9 @@ static int vmstate_acpi_post_load(void *opaque, int version_id)
  {                                                                   \
      .name       = (stringify(_field)),                              \
      .version_id = 0,                                                \
-     .num        = GPE_LEN,                                          \
      .info       = &vmstate_info_uint16,                             \
      .size       = sizeof(uint16_t),                                 \
-     .flags      = VMS_ARRAY | VMS_POINTER,                          \
+     .flags      = VMS_SINGLE | VMS_POINTER,                         \
      .offset     = vmstate_offset_pointer(_state, _field, uint8_t),  \
  }
 
@@ -267,11 +266,54 @@ static const VMStateDescription vmstate_pci_status = {
     }
 };
 
+static int acpi_load_old(QEMUFile *f, void *opaque, int version_id)
+{
+    PIIX4PMState *s = opaque;
+    int ret, i;
+    uint16_t temp;
+
+    ret = pci_device_load(&s->dev, f);
+    if (ret < 0) {
+        return ret;
+    }
+    qemu_get_be16s(f, &s->ar.pm1.evt.sts);
+    qemu_get_be16s(f, &s->ar.pm1.evt.en);
+    qemu_get_be16s(f, &s->ar.pm1.cnt.cnt);
+
+    ret = vmstate_load_state(f, &vmstate_apm, opaque, 1);
+    if (ret) {
+        return ret;
+    }
+
+    qemu_get_timer(f, s->ar.tmr.timer);
+    qemu_get_sbe64s(f, &s->ar.tmr.overflow_time);
+
+    qemu_get_be16s(f, (uint16_t *)s->ar.gpe.sts);
+    for (i = 0; i < 3; i++) {
+        qemu_get_be16s(f, &temp);
+    }
+
+    qemu_get_be16s(f, (uint16_t *)s->ar.gpe.en);
+    for (i = 0; i < 3; i++) {
+        qemu_get_be16s(f, &temp);
+    }
+
+    ret = vmstate_load_state(f, &vmstate_pci_status, opaque, 1);
+    return ret;
+}
+
+/* qemu-kvm 1.2 uses version 3 but advertised as 2
+ * To support incoming qemu-kvm 1.2 migration, change version_id
+ * and minimum_version_id to 2 below (which breaks migration from
+ * qemu 1.2).
+ *
+ */
 static const VMStateDescription vmstate_acpi = {
     .name = "piix4_pm",
-    .version_id = 2,
-    .minimum_version_id = 1,
+    .version_id = 3,
+    .minimum_version_id = 3,
     .minimum_version_id_old = 1,
+    .load_state_old = acpi_load_old,
     .post_load = vmstate_acpi_post_load,
     .fields      = (VMStateField []) {
         VMSTATE_PCI_DEVICE(dev, PIIX4PMState),

From 78021d6d8dc50ed4d67442c3ca11eab78220e9ef Mon Sep 17 00:00:00 2001
From: Jan Kiszka 
Date: Mon, 12 Nov 2012 15:04:35 +0100
Subject: [PATCH 1625/2270] kvm: Actually remove software breakpoints from list
 on cleanup

So far we only removed them from the guest, leaving its states in the
list. This made it impossible for gdb to re-enable breakpoints on the
same address after re-attaching.

Signed-off-by: Jan Kiszka 
Signed-off-by: Marcelo Tosatti 
---
 kvm-all.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/kvm-all.c b/kvm-all.c
index b6d0483576..3bc3347d07 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1905,6 +1905,8 @@ void kvm_remove_all_breakpoints(CPUArchState *current_env)
                 }
             }
         }
+        QTAILQ_REMOVE(&s->kvm_sw_breakpoints, bp, entry);
+        g_free(bp);
     }
     kvm_arch_remove_all_hw_breakpoints();
 

From 04509ad939a7878b487b29e3500b79b5e2c1de35 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Tue, 23 Oct 2012 19:44:02 -0200
Subject: [PATCH 1626/2270] qemu-common.h: Comment about usage rules
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Every time we make a tiny change on a header file, we often find
circular header dependency problems. To avoid this nightmare, we need to
stop including qemu-common.h from other headers, and we should gradually
move the declarations from the catch-all qemu-common.h header to their
specific headers.

This simply adds a comment documenting the rules about qemu-common.h,
hoping that people will see it before including qemu-common.h from other
header files, and before adding more declarations to qemu-common.h.

Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 qemu-common.h | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/qemu-common.h b/qemu-common.h
index ac9985cc6d..093d1198ec 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -1,5 +1,14 @@
 
-/* Common header file that is included by all of qemu.  */
+/* Common header file that is included by all of QEMU.
+ *
+ * This file is supposed to be included only by .c files. No header file should
+ * depend on qemu-common.h, as this would easily lead to circular header
+ * dependencies.
+ *
+ * If a header file uses a definition from qemu-common.h, that definition
+ * must be moved to a separate header file, and the header that uses it
+ * must include that header.
+ */
 #ifndef QEMU_COMMON_H
 #define QEMU_COMMON_H
 

From 5202ef942fb986011a31d9366fbf93a56f0056e4 Mon Sep 17 00:00:00 2001
From: Igor Mammedov 
Date: Tue, 16 Oct 2012 03:57:21 +0200
Subject: [PATCH 1627/2270] Move qemu_irq typedef out of qemu-common.h
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

It's necessary for making CPU child of DEVICE without
causing circular header deps.

Signed-off-by: Igor Mammedov 
[ehabkost: re-added the typedef to hw/irq.h after rebasing]
Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 hw/arm-misc.h | 1 +
 hw/bt.h       | 2 ++
 hw/devices.h  | 2 ++
 hw/irq.h      | 2 ++
 hw/omap.h     | 1 +
 hw/soc_dma.h  | 1 +
 hw/xen.h      | 1 +
 qemu-common.h | 1 -
 8 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index adb166586b..d129678b26 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -12,6 +12,7 @@
 #define ARM_MISC_H 1
 
 #include "memory.h"
+#include "hw/irq.h"
 
 /* The CPU is also modeled as an interrupt controller.  */
 #define ARM_PIC_CPU_IRQ 0
diff --git a/hw/bt.h b/hw/bt.h
index a48b8d4b13..ebf6a370a1 100644
--- a/hw/bt.h
+++ b/hw/bt.h
@@ -23,6 +23,8 @@
  * along with this program; if not, see .
  */
 
+#include "hw/irq.h"
+
 /* BD Address */
 typedef struct {
     uint8_t b[6];
diff --git a/hw/devices.h b/hw/devices.h
index 1a55c1e905..c60bcabae3 100644
--- a/hw/devices.h
+++ b/hw/devices.h
@@ -1,6 +1,8 @@
 #ifndef QEMU_DEVICES_H
 #define QEMU_DEVICES_H
 
+#include "hw/irq.h"
+
 /* ??? Not all users of this file can include cpu-common.h.  */
 struct MemoryRegion;
 
diff --git a/hw/irq.h b/hw/irq.h
index e640c105e7..610e6b7623 100644
--- a/hw/irq.h
+++ b/hw/irq.h
@@ -3,6 +3,8 @@
 
 /* Generic IRQ/GPIO pin infrastructure.  */
 
+typedef struct IRQState *qemu_irq;
+
 typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
 
 void qemu_set_irq(qemu_irq irq, int level);
diff --git a/hw/omap.h b/hw/omap.h
index 8bd7c73cf6..2b383ffc44 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -19,6 +19,7 @@
 #ifndef hw_omap_h
 #include "memory.h"
 # define hw_omap_h		"omap.h"
+#include "hw/irq.h"
 
 # define OMAP_EMIFS_BASE	0x00000000
 # define OMAP2_Q0_BASE		0x00000000
diff --git a/hw/soc_dma.h b/hw/soc_dma.h
index 9340b8f38e..5948489eae 100644
--- a/hw/soc_dma.h
+++ b/hw/soc_dma.h
@@ -19,6 +19,7 @@
  */
 
 #include "memory.h"
+#include "hw/irq.h"
 
 struct soc_dma_s;
 struct soc_dma_ch_s;
diff --git a/hw/xen.h b/hw/xen.h
index d14e92d5aa..e3cca7fb92 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -8,6 +8,7 @@
  */
 #include 
 
+#include "hw/irq.h"
 #include "qemu-common.h"
 
 /* xen-machine.c */
diff --git a/qemu-common.h b/qemu-common.h
index 093d1198ec..9112e2de7a 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -292,7 +292,6 @@ typedef struct PCIEPort PCIEPort;
 typedef struct PCIESlot PCIESlot;
 typedef struct MSIMessage MSIMessage;
 typedef struct SerialState SerialState;
-typedef struct IRQState *qemu_irq;
 typedef struct PCMCIACardState PCMCIACardState;
 typedef struct MouseTransformInfo MouseTransformInfo;
 typedef struct uWireSlave uWireSlave;

From 074a86fccd185616469dfcdc0e157f438aebba18 Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Fri, 10 Aug 2012 12:00:43 -0500
Subject: [PATCH 1628/2270] qdev: Split up header so it can be used in cpu.h
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Header file dependency is a frickin' nightmare right now.  cpu.h tends
to get included in our 'include everything' header files but qdev also
needs to include those headers mainly for qdev-properties since it knows
about CharDriverState and friends.

We can solve this for now by splitting out qdev.h along the same lines
that we previously split the C file.  Then cpu.h just needs to include
qdev-core.h.

hw/qdev.h is split into following new headers:
    hw/qdev-core.h
    hw/qdev-properties.h
    hw/qdev-monitor.h

Signed-off-by: Anthony Liguori 

[ehabkost: re-add DEFINE_PROP_PCI_HOST_DEVADDR, that was removed on the
 original patch (by mistake, I guess)]
[ehabkost: kill qdev_prop_set_vlan() declaration]
[ehabkost: moved get_fw_dev_path() comment to the original location
 (I don't know why it was moved)]
[ehabkost: removed qdev_exists() declaration]
[ehabkost: keep using 'QemuOpts' instead of 'struct QemuOpts', as
 qdev-core.h includes qemu-option.h]

Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 hw/mc146818rtc.c     |   1 +
 hw/qdev-addr.c       |   1 +
 hw/qdev-core.h       | 238 ++++++++++++++++++++++++++++
 hw/qdev-monitor.h    |  16 ++
 hw/qdev-properties.c |   1 +
 hw/qdev-properties.h | 130 +++++++++++++++
 hw/qdev.c            |   1 +
 hw/qdev.h            | 370 +------------------------------------------
 8 files changed, 392 insertions(+), 366 deletions(-)
 create mode 100644 hw/qdev-core.h
 create mode 100644 hw/qdev-monitor.h
 create mode 100644 hw/qdev-properties.h

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 98839f278d..7d84ce3d74 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -25,6 +25,7 @@
 #include "qemu-timer.h"
 #include "sysemu.h"
 #include "mc146818rtc.h"
+#include "qapi/qapi-visit-core.h"
 
 #ifdef TARGET_I386
 #include "apic.h"
diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c
index de0ba8726e..ea32c31ab6 100644
--- a/hw/qdev-addr.c
+++ b/hw/qdev-addr.c
@@ -1,6 +1,7 @@
 #include "qdev.h"
 #include "qdev-addr.h"
 #include "hwaddr.h"
+#include "qapi/qapi-visit-core.h"
 
 /* --- target physical address --- */
 
diff --git a/hw/qdev-core.h b/hw/qdev-core.h
new file mode 100644
index 0000000000..fce9e2249c
--- /dev/null
+++ b/hw/qdev-core.h
@@ -0,0 +1,238 @@
+#ifndef QDEV_CORE_H
+#define QDEV_CORE_H
+
+#include "qemu-queue.h"
+#include "qemu-option.h"
+#include "qemu/object.h"
+#include "hw/irq.h"
+#include "error.h"
+
+typedef struct Property Property;
+
+typedef struct PropertyInfo PropertyInfo;
+
+typedef struct CompatProperty CompatProperty;
+
+typedef struct BusState BusState;
+
+typedef struct BusClass BusClass;
+
+enum DevState {
+    DEV_STATE_CREATED = 1,
+    DEV_STATE_INITIALIZED,
+};
+
+enum {
+    DEV_NVECTORS_UNSPECIFIED = -1,
+};
+
+#define TYPE_DEVICE "device"
+#define DEVICE(obj) OBJECT_CHECK(DeviceState, (obj), TYPE_DEVICE)
+#define DEVICE_CLASS(klass) OBJECT_CLASS_CHECK(DeviceClass, (klass), TYPE_DEVICE)
+#define DEVICE_GET_CLASS(obj) OBJECT_GET_CLASS(DeviceClass, (obj), TYPE_DEVICE)
+
+typedef int (*qdev_initfn)(DeviceState *dev);
+typedef int (*qdev_event)(DeviceState *dev);
+typedef void (*qdev_resetfn)(DeviceState *dev);
+
+struct VMStateDescription;
+
+typedef struct DeviceClass {
+    ObjectClass parent_class;
+
+    const char *fw_name;
+    const char *desc;
+    Property *props;
+    int no_user;
+
+    /* callbacks */
+    void (*reset)(DeviceState *dev);
+
+    /* device state */
+    const struct VMStateDescription *vmsd;
+
+    /* Private to qdev / bus.  */
+    qdev_initfn init;
+    qdev_event unplug;
+    qdev_event exit;
+    const char *bus_type;
+} DeviceClass;
+
+/* This structure should not be accessed directly.  We declare it here
+   so that it can be embedded in individual device state structures.  */
+struct DeviceState {
+    Object parent_obj;
+
+    const char *id;
+    enum DevState state;
+    QemuOpts *opts;
+    int hotplugged;
+    BusState *parent_bus;
+    int num_gpio_out;
+    qemu_irq *gpio_out;
+    int num_gpio_in;
+    qemu_irq *gpio_in;
+    QLIST_HEAD(, BusState) child_bus;
+    int num_child_bus;
+    int instance_id_alias;
+    int alias_required_for_version;
+};
+
+#define TYPE_BUS "bus"
+#define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS)
+#define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS)
+#define BUS_GET_CLASS(obj) OBJECT_GET_CLASS(BusClass, (obj), TYPE_BUS)
+
+struct BusClass {
+    ObjectClass parent_class;
+
+    /* FIXME first arg should be BusState */
+    void (*print_dev)(Monitor *mon, DeviceState *dev, int indent);
+    char *(*get_dev_path)(DeviceState *dev);
+    /*
+     * This callback is used to create Open Firmware device path in accordance
+     * with OF spec http://forthworks.com/standards/of1275.pdf. Individual bus
+     * bindings can be found at http://playground.sun.com/1275/bindings/.
+     */
+    char *(*get_fw_dev_path)(DeviceState *dev);
+    int (*reset)(BusState *bus);
+};
+
+typedef struct BusChild {
+    DeviceState *child;
+    int index;
+    QTAILQ_ENTRY(BusChild) sibling;
+} BusChild;
+
+/**
+ * BusState:
+ * @qom_allocated: Indicates whether the object was allocated by QOM.
+ * @glib_allocated: Indicates whether the object was initialized in-place
+ * yet is expected to be freed with g_free().
+ */
+struct BusState {
+    Object obj;
+    DeviceState *parent;
+    const char *name;
+    int allow_hotplug;
+    bool qom_allocated;
+    bool glib_allocated;
+    int max_index;
+    QTAILQ_HEAD(ChildrenHead, BusChild) children;
+    QLIST_ENTRY(BusState) sibling;
+};
+
+struct Property {
+    const char   *name;
+    PropertyInfo *info;
+    int          offset;
+    uint8_t      bitnr;
+    uint8_t      qtype;
+    int64_t      defval;
+};
+
+struct PropertyInfo {
+    const char *name;
+    const char *legacy_name;
+    const char **enum_table;
+    int (*parse)(DeviceState *dev, Property *prop, const char *str);
+    int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
+    ObjectPropertyAccessor *get;
+    ObjectPropertyAccessor *set;
+    ObjectPropertyRelease *release;
+};
+
+typedef struct GlobalProperty {
+    const char *driver;
+    const char *property;
+    const char *value;
+    QTAILQ_ENTRY(GlobalProperty) next;
+} GlobalProperty;
+
+/*** Board API.  This should go away once we have a machine config file.  ***/
+
+DeviceState *qdev_create(BusState *bus, const char *name);
+DeviceState *qdev_try_create(BusState *bus, const char *name);
+int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT;
+void qdev_init_nofail(DeviceState *dev);
+void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
+                                 int required_for_version);
+void qdev_unplug(DeviceState *dev, Error **errp);
+void qdev_free(DeviceState *dev);
+int qdev_simple_unplug_cb(DeviceState *dev);
+void qdev_machine_creation_done(void);
+bool qdev_machine_modified(void);
+
+qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
+void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
+
+BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
+
+/*** Device API.  ***/
+
+/* Register device properties.  */
+/* GPIO inputs also double as IRQ sinks.  */
+void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
+void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
+
+BusState *qdev_get_parent_bus(DeviceState *dev);
+
+/*** BUS API. ***/
+
+DeviceState *qdev_find_recursive(BusState *bus, const char *id);
+
+/* Returns 0 to walk children, > 0 to skip walk, < 0 to terminate walk. */
+typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
+typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
+
+void qbus_create_inplace(BusState *bus, const char *typename,
+                         DeviceState *parent, const char *name);
+BusState *qbus_create(const char *typename, DeviceState *parent, const char *name);
+/* Returns > 0 if either devfn or busfn skip walk somewhere in cursion,
+ *         < 0 if either devfn or busfn terminate walk somewhere in cursion,
+ *           0 otherwise. */
+int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
+                       qbus_walkerfn *busfn, void *opaque);
+int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
+                       qbus_walkerfn *busfn, void *opaque);
+void qdev_reset_all(DeviceState *dev);
+void qbus_reset_all_fn(void *opaque);
+
+void qbus_free(BusState *bus);
+
+#define FROM_QBUS(type, dev) DO_UPCAST(type, qbus, dev)
+
+/* This should go away once we get rid of the NULL bus hack */
+BusState *sysbus_get_default(void);
+
+char *qdev_get_fw_dev_path(DeviceState *dev);
+
+/**
+ * @qdev_machine_init
+ *
+ * Initialize platform devices before machine init.  This is a hack until full
+ * support for composition is added.
+ */
+void qdev_machine_init(void);
+
+/**
+ * @device_reset
+ *
+ * Reset a single device (by calling the reset method).
+ */
+void device_reset(DeviceState *dev);
+
+const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev);
+
+const char *qdev_fw_name(DeviceState *dev);
+
+Object *qdev_get_machine(void);
+
+/* FIXME: make this a link<> */
+void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
+
+extern int qdev_hotplug;
+
+char *qdev_get_dev_path(DeviceState *dev);
+
+#endif
diff --git a/hw/qdev-monitor.h b/hw/qdev-monitor.h
new file mode 100644
index 0000000000..220ceba4c5
--- /dev/null
+++ b/hw/qdev-monitor.h
@@ -0,0 +1,16 @@
+#ifndef QEMU_QDEV_MONITOR_H
+#define QEMU_QDEV_MONITOR_H
+
+#include "qdev-core.h"
+#include "monitor.h"
+
+/*** monitor commands ***/
+
+void do_info_qtree(Monitor *mon);
+void do_info_qdm(Monitor *mon);
+int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int qdev_device_help(QemuOpts *opts);
+DeviceState *qdev_device_add(QemuOpts *opts);
+
+#endif
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 8aca0d43fe..81d901c6c4 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -4,6 +4,7 @@
 #include "blockdev.h"
 #include "hw/block-common.h"
 #include "net/hub.h"
+#include "qapi/qapi-visit-core.h"
 
 void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
 {
diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h
new file mode 100644
index 0000000000..5b046abb28
--- /dev/null
+++ b/hw/qdev-properties.h
@@ -0,0 +1,130 @@
+#ifndef QEMU_QDEV_PROPERTIES_H
+#define QEMU_QDEV_PROPERTIES_H
+
+#include "qdev-core.h"
+
+/*** qdev-properties.c ***/
+
+extern PropertyInfo qdev_prop_bit;
+extern PropertyInfo qdev_prop_uint8;
+extern PropertyInfo qdev_prop_uint16;
+extern PropertyInfo qdev_prop_uint32;
+extern PropertyInfo qdev_prop_int32;
+extern PropertyInfo qdev_prop_uint64;
+extern PropertyInfo qdev_prop_hex8;
+extern PropertyInfo qdev_prop_hex32;
+extern PropertyInfo qdev_prop_hex64;
+extern PropertyInfo qdev_prop_string;
+extern PropertyInfo qdev_prop_chr;
+extern PropertyInfo qdev_prop_ptr;
+extern PropertyInfo qdev_prop_macaddr;
+extern PropertyInfo qdev_prop_losttickpolicy;
+extern PropertyInfo qdev_prop_bios_chs_trans;
+extern PropertyInfo qdev_prop_drive;
+extern PropertyInfo qdev_prop_netdev;
+extern PropertyInfo qdev_prop_vlan;
+extern PropertyInfo qdev_prop_pci_devfn;
+extern PropertyInfo qdev_prop_blocksize;
+extern PropertyInfo qdev_prop_pci_host_devaddr;
+
+#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
+        .name      = (_name),                                    \
+        .info      = &(_prop),                                   \
+        .offset    = offsetof(_state, _field)                    \
+            + type_check(_type,typeof_field(_state, _field)),    \
+        }
+#define DEFINE_PROP_DEFAULT(_name, _state, _field, _defval, _prop, _type) { \
+        .name      = (_name),                                           \
+        .info      = &(_prop),                                          \
+        .offset    = offsetof(_state, _field)                           \
+            + type_check(_type,typeof_field(_state, _field)),           \
+        .qtype     = QTYPE_QINT,                                        \
+        .defval    = (_type)_defval,                                    \
+        }
+#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) {  \
+        .name      = (_name),                                    \
+        .info      = &(qdev_prop_bit),                           \
+        .bitnr    = (_bit),                                      \
+        .offset    = offsetof(_state, _field)                    \
+            + type_check(uint32_t,typeof_field(_state, _field)), \
+        .qtype     = QTYPE_QBOOL,                                \
+        .defval    = (bool)_defval,                              \
+        }
+
+#define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
+#define DEFINE_PROP_UINT16(_n, _s, _f, _d)                      \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint16, uint16_t)
+#define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint32, uint32_t)
+#define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_int32, int32_t)
+#define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t)
+#define DEFINE_PROP_HEX8(_n, _s, _f, _d)                       \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex8, uint8_t)
+#define DEFINE_PROP_HEX32(_n, _s, _f, _d)                       \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex32, uint32_t)
+#define DEFINE_PROP_HEX64(_n, _s, _f, _d)                       \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex64, uint64_t)
+#define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d)                   \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t)
+
+#define DEFINE_PROP_PTR(_n, _s, _f)             \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*)
+#define DEFINE_PROP_CHR(_n, _s, _f)             \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharDriverState*)
+#define DEFINE_PROP_STRING(_n, _s, _f)             \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*)
+#define DEFINE_PROP_NETDEV(_n, _s, _f)             \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NetClientState*)
+#define DEFINE_PROP_VLAN(_n, _s, _f)             \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NetClientState*)
+#define DEFINE_PROP_DRIVE(_n, _s, _f) \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *)
+#define DEFINE_PROP_MACADDR(_n, _s, _f)         \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
+#define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
+                        LostTickPolicy)
+#define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int)
+#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f, _d) \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t)
+#define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress)
+
+#define DEFINE_PROP_END_OF_LIST()               \
+    {}
+
+/* Set properties between creation and init.  */
+void *qdev_get_prop_ptr(DeviceState *dev, Property *prop);
+int qdev_prop_parse(DeviceState *dev, const char *name, const char *value);
+void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value);
+void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value);
+void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value);
+void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
+void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value);
+void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value);
+void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value);
+void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value);
+void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value);
+int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) QEMU_WARN_UNUSED_RESULT;
+void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value);
+void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
+void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
+/* FIXME: Remove opaque pointer properties.  */
+void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
+
+void qdev_prop_register_global_list(GlobalProperty *props);
+void qdev_prop_set_globals(DeviceState *dev);
+void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
+                                    Property *prop, const char *value);
+
+/**
+ * @qdev_property_add_static - add a @Property to a device referencing a
+ * field in a struct.
+ */
+void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp);
+
+#endif
diff --git a/hw/qdev.c b/hw/qdev.c
index 9b9aba376b..7ddcd24299 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -29,6 +29,7 @@
 #include "qdev.h"
 #include "sysemu.h"
 #include "error.h"
+#include "qapi/qapi-visit-core.h"
 
 int qdev_hotplug = 0;
 static bool qdev_hot_added = false;
diff --git a/hw/qdev.h b/hw/qdev.h
index c6ac636200..365b8d6ca2 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -1,371 +1,9 @@
 #ifndef QDEV_H
 #define QDEV_H
 
-#include "hw.h"
-#include "qemu-queue.h"
-#include "qemu-char.h"
-#include "qemu-option.h"
-#include "qapi/qapi-visit-core.h"
-#include "qemu/object.h"
-#include "error.h"
-
-typedef struct Property Property;
-
-typedef struct PropertyInfo PropertyInfo;
-
-typedef struct CompatProperty CompatProperty;
-
-typedef struct BusState BusState;
-
-typedef struct BusClass BusClass;
-
-enum DevState {
-    DEV_STATE_CREATED = 1,
-    DEV_STATE_INITIALIZED,
-};
-
-enum {
-    DEV_NVECTORS_UNSPECIFIED = -1,
-};
-
-#define TYPE_DEVICE "device"
-#define DEVICE(obj) OBJECT_CHECK(DeviceState, (obj), TYPE_DEVICE)
-#define DEVICE_CLASS(klass) OBJECT_CLASS_CHECK(DeviceClass, (klass), TYPE_DEVICE)
-#define DEVICE_GET_CLASS(obj) OBJECT_GET_CLASS(DeviceClass, (obj), TYPE_DEVICE)
-
-typedef int (*qdev_initfn)(DeviceState *dev);
-typedef int (*qdev_event)(DeviceState *dev);
-typedef void (*qdev_resetfn)(DeviceState *dev);
-
-typedef struct DeviceClass {
-    ObjectClass parent_class;
-
-    const char *fw_name;
-    const char *desc;
-    Property *props;
-    int no_user;
-
-    /* callbacks */
-    void (*reset)(DeviceState *dev);
-
-    /* device state */
-    const VMStateDescription *vmsd;
-
-    /* Private to qdev / bus.  */
-    qdev_initfn init;
-    qdev_event unplug;
-    qdev_event exit;
-    const char *bus_type;
-} DeviceClass;
-
-/* This structure should not be accessed directly.  We declare it here
-   so that it can be embedded in individual device state structures.  */
-struct DeviceState {
-    Object parent_obj;
-
-    const char *id;
-    enum DevState state;
-    QemuOpts *opts;
-    int hotplugged;
-    BusState *parent_bus;
-    int num_gpio_out;
-    qemu_irq *gpio_out;
-    int num_gpio_in;
-    qemu_irq *gpio_in;
-    QLIST_HEAD(, BusState) child_bus;
-    int num_child_bus;
-    int instance_id_alias;
-    int alias_required_for_version;
-};
-
-#define TYPE_BUS "bus"
-#define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS)
-#define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS)
-#define BUS_GET_CLASS(obj) OBJECT_GET_CLASS(BusClass, (obj), TYPE_BUS)
-
-struct BusClass {
-    ObjectClass parent_class;
-
-    /* FIXME first arg should be BusState */
-    void (*print_dev)(Monitor *mon, DeviceState *dev, int indent);
-    char *(*get_dev_path)(DeviceState *dev);
-    /*
-     * This callback is used to create Open Firmware device path in accordance
-     * with OF spec http://forthworks.com/standards/of1275.pdf. Individual bus
-     * bindings can be found at http://playground.sun.com/1275/bindings/.
-     */
-    char *(*get_fw_dev_path)(DeviceState *dev);
-    int (*reset)(BusState *bus);
-};
-
-typedef struct BusChild {
-    DeviceState *child;
-    int index;
-    QTAILQ_ENTRY(BusChild) sibling;
-} BusChild;
-
-/**
- * BusState:
- * @qom_allocated: Indicates whether the object was allocated by QOM.
- * @glib_allocated: Indicates whether the object was initialized in-place
- * yet is expected to be freed with g_free().
- */
-struct BusState {
-    Object obj;
-    DeviceState *parent;
-    const char *name;
-    int allow_hotplug;
-    bool qom_allocated;
-    bool glib_allocated;
-    int max_index;
-    QTAILQ_HEAD(ChildrenHead, BusChild) children;
-    QLIST_ENTRY(BusState) sibling;
-};
-
-struct Property {
-    const char   *name;
-    PropertyInfo *info;
-    int          offset;
-    uint8_t      bitnr;
-    uint8_t      qtype;
-    int64_t      defval;
-};
-
-struct PropertyInfo {
-    const char *name;
-    const char *legacy_name;
-    const char **enum_table;
-    int (*parse)(DeviceState *dev, Property *prop, const char *str);
-    int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
-    ObjectPropertyAccessor *get;
-    ObjectPropertyAccessor *set;
-    ObjectPropertyRelease *release;
-};
-
-typedef struct GlobalProperty {
-    const char *driver;
-    const char *property;
-    const char *value;
-    QTAILQ_ENTRY(GlobalProperty) next;
-} GlobalProperty;
-
-/*** Board API.  This should go away once we have a machine config file.  ***/
-
-DeviceState *qdev_create(BusState *bus, const char *name);
-DeviceState *qdev_try_create(BusState *bus, const char *name);
-int qdev_device_help(QemuOpts *opts);
-DeviceState *qdev_device_add(QemuOpts *opts);
-int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT;
-void qdev_init_nofail(DeviceState *dev);
-void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
-                                 int required_for_version);
-void qdev_unplug(DeviceState *dev, Error **errp);
-void qdev_free(DeviceState *dev);
-int qdev_simple_unplug_cb(DeviceState *dev);
-void qdev_machine_creation_done(void);
-bool qdev_machine_modified(void);
-
-qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
-void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
-
-BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
-
-/*** Device API.  ***/
-
-/* Register device properties.  */
-/* GPIO inputs also double as IRQ sinks.  */
-void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
-void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
-
-BusState *qdev_get_parent_bus(DeviceState *dev);
-
-/*** BUS API. ***/
-
-DeviceState *qdev_find_recursive(BusState *bus, const char *id);
-
-/* Returns 0 to walk children, > 0 to skip walk, < 0 to terminate walk. */
-typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
-typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
-
-void qbus_create_inplace(BusState *bus, const char *typename,
-                         DeviceState *parent, const char *name);
-BusState *qbus_create(const char *typename, DeviceState *parent, const char *name);
-/* Returns > 0 if either devfn or busfn skip walk somewhere in cursion,
- *         < 0 if either devfn or busfn terminate walk somewhere in cursion,
- *           0 otherwise. */
-int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
-                       qbus_walkerfn *busfn, void *opaque);
-int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
-                       qbus_walkerfn *busfn, void *opaque);
-void qdev_reset_all(DeviceState *dev);
-void qbus_reset_all_fn(void *opaque);
-
-void qbus_free(BusState *bus);
-
-#define FROM_QBUS(type, dev) DO_UPCAST(type, qbus, dev)
-
-/* This should go away once we get rid of the NULL bus hack */
-BusState *sysbus_get_default(void);
-
-/*** monitor commands ***/
-
-void do_info_qtree(Monitor *mon);
-void do_info_qdm(Monitor *mon);
-int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
-int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
-
-/*** qdev-properties.c ***/
-
-extern PropertyInfo qdev_prop_bit;
-extern PropertyInfo qdev_prop_uint8;
-extern PropertyInfo qdev_prop_uint16;
-extern PropertyInfo qdev_prop_uint32;
-extern PropertyInfo qdev_prop_int32;
-extern PropertyInfo qdev_prop_uint64;
-extern PropertyInfo qdev_prop_hex8;
-extern PropertyInfo qdev_prop_hex32;
-extern PropertyInfo qdev_prop_hex64;
-extern PropertyInfo qdev_prop_string;
-extern PropertyInfo qdev_prop_chr;
-extern PropertyInfo qdev_prop_ptr;
-extern PropertyInfo qdev_prop_macaddr;
-extern PropertyInfo qdev_prop_losttickpolicy;
-extern PropertyInfo qdev_prop_bios_chs_trans;
-extern PropertyInfo qdev_prop_drive;
-extern PropertyInfo qdev_prop_netdev;
-extern PropertyInfo qdev_prop_vlan;
-extern PropertyInfo qdev_prop_pci_devfn;
-extern PropertyInfo qdev_prop_blocksize;
-extern PropertyInfo qdev_prop_pci_host_devaddr;
-
-#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
-        .name      = (_name),                                    \
-        .info      = &(_prop),                                   \
-        .offset    = offsetof(_state, _field)                    \
-            + type_check(_type,typeof_field(_state, _field)),    \
-        }
-#define DEFINE_PROP_DEFAULT(_name, _state, _field, _defval, _prop, _type) { \
-        .name      = (_name),                                           \
-        .info      = &(_prop),                                          \
-        .offset    = offsetof(_state, _field)                           \
-            + type_check(_type,typeof_field(_state, _field)),           \
-        .qtype     = QTYPE_QINT,                                        \
-        .defval    = (_type)_defval,                                    \
-        }
-#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) {  \
-        .name      = (_name),                                    \
-        .info      = &(qdev_prop_bit),                           \
-        .bitnr    = (_bit),                                      \
-        .offset    = offsetof(_state, _field)                    \
-            + type_check(uint32_t,typeof_field(_state, _field)), \
-        .qtype     = QTYPE_QBOOL,                                \
-        .defval    = (bool)_defval,                              \
-        }
-
-#define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
-#define DEFINE_PROP_UINT16(_n, _s, _f, _d)                      \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint16, uint16_t)
-#define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint32, uint32_t)
-#define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_int32, int32_t)
-#define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t)
-#define DEFINE_PROP_HEX8(_n, _s, _f, _d)                       \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex8, uint8_t)
-#define DEFINE_PROP_HEX32(_n, _s, _f, _d)                       \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex32, uint32_t)
-#define DEFINE_PROP_HEX64(_n, _s, _f, _d)                       \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex64, uint64_t)
-#define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d)                   \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t)
-
-#define DEFINE_PROP_PTR(_n, _s, _f)             \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*)
-#define DEFINE_PROP_CHR(_n, _s, _f)             \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharDriverState*)
-#define DEFINE_PROP_STRING(_n, _s, _f)             \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*)
-#define DEFINE_PROP_NETDEV(_n, _s, _f)             \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NetClientState*)
-#define DEFINE_PROP_VLAN(_n, _s, _f)             \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NetClientState*)
-#define DEFINE_PROP_DRIVE(_n, _s, _f) \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *)
-#define DEFINE_PROP_MACADDR(_n, _s, _f)         \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
-#define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
-                        LostTickPolicy)
-#define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int)
-#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f, _d) \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t)
-#define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress)
-
-#define DEFINE_PROP_END_OF_LIST()               \
-    {}
-
-/* Set properties between creation and init.  */
-void *qdev_get_prop_ptr(DeviceState *dev, Property *prop);
-int qdev_prop_parse(DeviceState *dev, const char *name, const char *value);
-void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value);
-void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value);
-void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value);
-void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
-void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value);
-void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value);
-void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value);
-void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value);
-void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value);
-int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) QEMU_WARN_UNUSED_RESULT;
-void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value);
-void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
-void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
-/* FIXME: Remove opaque pointer properties.  */
-void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
-
-void qdev_prop_register_global_list(GlobalProperty *props);
-void qdev_prop_set_globals(DeviceState *dev);
-void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
-                                    Property *prop, const char *value);
-
-char *qdev_get_fw_dev_path(DeviceState *dev);
-
-/**
- * @qdev_property_add_static - add a @Property to a device referencing a
- * field in a struct.
- */
-void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp);
-
-/**
- * @qdev_machine_init
- *
- * Initialize platform devices before machine init.  This is a hack until full
- * support for composition is added.
- */
-void qdev_machine_init(void);
-
-/**
- * @device_reset
- *
- * Reset a single device (by calling the reset method).
- */
-void device_reset(DeviceState *dev);
-
-const VMStateDescription *qdev_get_vmsd(DeviceState *dev);
-
-const char *qdev_fw_name(DeviceState *dev);
-
-Object *qdev_get_machine(void);
-
-/* FIXME: make this a link<> */
-void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
-
-extern int qdev_hotplug;
-
-char *qdev_get_dev_path(DeviceState *dev);
+#include "hw/hw.h"
+#include "qdev-core.h"
+#include "qdev-properties.h"
+#include "qdev-monitor.h"
 
 #endif

From 017cf5b1d22f80f36dc4c5aba465b178cc209d35 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Tue, 23 Oct 2012 19:43:01 -0200
Subject: [PATCH 1629/2270] qemu-fsdev-dummy.c: Include module.h
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

module.h is where machine_init() is defined, but qemu-fsdev-dummy.c
doesn't include it.

The header is probably being included by accident because some other
headers are including qemu-common.h, but those headers should eventually
stop including qemu-common.h.

Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 fsdev/qemu-fsdev-dummy.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/fsdev/qemu-fsdev-dummy.c b/fsdev/qemu-fsdev-dummy.c
index 4e700dd4e4..300f2758be 100644
--- a/fsdev/qemu-fsdev-dummy.c
+++ b/fsdev/qemu-fsdev-dummy.c
@@ -14,6 +14,7 @@
 #include 
 #include "qemu-fsdev.h"
 #include "qemu-config.h"
+#include "module.h"
 
 int qemu_fsdev_add(QemuOpts *opts)
 {

From bcbb78c6b6db9e784448a8b521c14af083585ce4 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Tue, 23 Oct 2012 21:01:36 -0200
Subject: [PATCH 1630/2270] vnc-palette.h: Include 
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

 is needed for the 'bool' type, used in the header.

The header is probably being included by accident because some other
headers are including qemu-common.h, but those headers should eventually
stop including qemu-common.h.

Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 ui/vnc-palette.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/ui/vnc-palette.h b/ui/vnc-palette.h
index 3260885ff0..b82dc5db91 100644
--- a/ui/vnc-palette.h
+++ b/ui/vnc-palette.h
@@ -32,6 +32,7 @@
 #include "qlist.h"
 #include "qemu-queue.h"
 #include 
+#include 
 
 #define VNC_PALETTE_HASH_SIZE 256
 #define VNC_PALETTE_MAX_SIZE  256

From c8aba9ced945a59fe2638d34660a940a3e727038 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Tue, 23 Oct 2012 21:29:38 -0200
Subject: [PATCH 1631/2270] qemu-config.h: Include headers it needs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Include:
-  for FILE
- qemu-option.h for QemuOptsList

Some of those headers were probably being included by accident because
some other headers were including qemu-common.h, but those headers
should eventually stop including qemu-common.h.

Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 qemu-config.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/qemu-config.h b/qemu-config.h
index 5557562c33..812c4c5b10 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -1,6 +1,8 @@
 #ifndef QEMU_CONFIG_H
 #define QEMU_CONFIG_H
 
+#include 
+#include "qemu-option.h"
 #include "error.h"
 
 extern QemuOptsList qemu_fsdev_opts;

From 17e0b6ab08bd272aee24bd1a173bf0adc708d0aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andreas=20F=C3=A4rber?= 
Date: Wed, 14 Nov 2012 16:42:39 +0100
Subject: [PATCH 1632/2270] osdep: Move qemu_{open,close}() prototypes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

They are implemented in osdep.c, so keep the prototypes in osdep.h.

Suggested-by: Igor Mammedov 
Signed-off-by: Andreas Färber 
Acked-by: Eduardo Habkost 
---
 osdep.h       | 3 +++
 qemu-common.h | 2 --
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/osdep.h b/osdep.h
index 585e2c1787..87d3b9cfa8 100644
--- a/osdep.h
+++ b/osdep.h
@@ -136,6 +136,9 @@ void qemu_vfree(void *ptr);
 
 int qemu_madvise(void *addr, size_t len, int advice);
 
+int qemu_open(const char *name, int flags, ...);
+int qemu_close(int fd);
+
 #if defined(__HAIKU__) && defined(__i386__)
 #define FMT_pid "%ld"
 #elif defined(WIN64)
diff --git a/qemu-common.h b/qemu-common.h
index 9112e2de7a..cef264cc85 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -217,8 +217,6 @@ const char *path(const char *pathname);
 
 void *qemu_oom_check(void *ptr);
 
-int qemu_open(const char *name, int flags, ...);
-int qemu_close(int fd);
 ssize_t qemu_write_full(int fd, const void *buf, size_t count)
     QEMU_WARN_UNUSED_RESULT;
 ssize_t qemu_send_full(int fd, const void *buf, size_t count, int flags)

From da4fea066d9e08654940801d46e350a8bbd56547 Mon Sep 17 00:00:00 2001
From: Igor Mammedov 
Date: Mon, 20 Aug 2012 01:39:37 +0200
Subject: [PATCH 1633/2270] qapi-types.h: Don't include qemu-common.h
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Needed to prevent build breakage when CPUState becomes a child of
DeviceState.

Signed-off-by: Igor Mammedov 
[ehabkost: include  too]
Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 scripts/qapi-types.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 1b84834959..6bc2391874 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -273,7 +273,8 @@ fdecl.write(mcgen('''
 #ifndef %(guard)s
 #define %(guard)s
 
-#include "qemu-common.h"
+#include 
+#include 
 
 ''',
                   guard=guardname(h_file)))

From c8acc380be7c7bb489037c927a2a5c217535f864 Mon Sep 17 00:00:00 2001
From: Andre Przywara 
Date: Wed, 14 Nov 2012 16:28:52 -0200
Subject: [PATCH 1634/2270] target-i386/cpu: Name new CPUID bits
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Update QEMU's knowledge of CPUID bit names. This allows to
enable/disable those new features on QEMU's command line when
using KVM and prepares future feature enablement in QEMU.

This adds F16C, RDRAND, LWP, TBM, TopoExt, PerfCtr_Core, PerfCtr_NB,
FSGSBASE, BMI1, AVX2, BMI2, ERMS, PCID, InvPCID, RTM, RDSeed and ADX.

Sources where the AMD BKDG for Family 15h/Model 10h, Intel Software
Developer Manual, and the Linux kernel for the leaf 7 bits.

Signed-off-by: Andre Przywara 
Signed-off-by: Boris Ostrovsky 
[ehabkost: added CPUID_EXT_PCID]
[ehabkost: edited commit message]
[ehabkost: rebased against latest qemu.git master]
Signed-off-by: Eduardo Habkost 
Reviewed-by: Igor Mammedov 
Signed-off-by: Andreas Färber 
---
 target-i386/cpu.c | 12 ++++++------
 target-i386/cpu.h | 22 ++++++++++++++++++++++
 2 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index e1db639295..f896e0cdca 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -66,7 +66,7 @@ static const char *ext_feature_name[] = {
     NULL, "pcid", "dca", "sse4.1|sse4_1",
     "sse4.2|sse4_2", "x2apic", "movbe", "popcnt",
     "tsc-deadline", "aes", "xsave", "osxsave",
-    "avx", NULL, NULL, "hypervisor",
+    "avx", "f16c", "rdrand", "hypervisor",
 };
 /* Feature names that are already defined on feature_name[] but are set on
  * CPUID[8000_0001].EDX on AMD CPUs don't have their names on
@@ -87,10 +87,10 @@ static const char *ext3_feature_name[] = {
     "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */,
     "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
     "3dnowprefetch", "osvw", "ibs", "xop",
-    "skinit", "wdt", NULL, NULL,
-    "fma4", NULL, "cvt16", "nodeid_msr",
-    NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL,
+    "skinit", "wdt", NULL, "lwp",
+    "fma4", "tce", NULL, "nodeid_msr",
+    NULL, "tbm", "topoext", "perfctr_core",
+    "perfctr_nb", NULL, NULL, NULL,
     NULL, NULL, NULL, NULL,
 };
 
@@ -119,7 +119,7 @@ static const char *svm_feature_name[] = {
 static const char *cpuid_7_0_ebx_feature_name[] = {
     "fsgsbase", NULL, NULL, "bmi1", "hle", "avx2", NULL, "smep",
     "bmi2", "erms", "invpcid", "rtm", NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL, "smap", NULL, NULL, NULL,
+    NULL, NULL, "rdseed", "adx", "smap", NULL, NULL, NULL,
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 };
 
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index cdc59dc0ca..90ef1ff1e2 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -403,9 +403,11 @@
 #define CPUID_EXT_TM2      (1 << 8)
 #define CPUID_EXT_SSSE3    (1 << 9)
 #define CPUID_EXT_CID      (1 << 10)
+#define CPUID_EXT_FMA      (1 << 12)
 #define CPUID_EXT_CX16     (1 << 13)
 #define CPUID_EXT_XTPR     (1 << 14)
 #define CPUID_EXT_PDCM     (1 << 15)
+#define CPUID_EXT_PCID     (1 << 17)
 #define CPUID_EXT_DCA      (1 << 18)
 #define CPUID_EXT_SSE41    (1 << 19)
 #define CPUID_EXT_SSE42    (1 << 20)
@@ -417,6 +419,8 @@
 #define CPUID_EXT_XSAVE    (1 << 26)
 #define CPUID_EXT_OSXSAVE  (1 << 27)
 #define CPUID_EXT_AVX      (1 << 28)
+#define CPUID_EXT_F16C     (1 << 29)
+#define CPUID_EXT_RDRAND   (1 << 30)
 #define CPUID_EXT_HYPERVISOR  (1 << 31)
 
 #define CPUID_EXT2_FPU     (1 << 0)
@@ -472,7 +476,15 @@
 #define CPUID_EXT3_IBS     (1 << 10)
 #define CPUID_EXT3_XOP     (1 << 11)
 #define CPUID_EXT3_SKINIT  (1 << 12)
+#define CPUID_EXT3_WDT     (1 << 13)
+#define CPUID_EXT3_LWP     (1 << 15)
 #define CPUID_EXT3_FMA4    (1 << 16)
+#define CPUID_EXT3_TCE     (1 << 17)
+#define CPUID_EXT3_NODEID  (1 << 19)
+#define CPUID_EXT3_TBM     (1 << 21)
+#define CPUID_EXT3_TOPOEXT (1 << 22)
+#define CPUID_EXT3_PERFCORE (1 << 23)
+#define CPUID_EXT3_PERFNB  (1 << 24)
 
 #define CPUID_SVM_NPT          (1 << 0)
 #define CPUID_SVM_LBRV         (1 << 1)
@@ -485,7 +497,17 @@
 #define CPUID_SVM_PAUSEFILTER  (1 << 10)
 #define CPUID_SVM_PFTHRESHOLD  (1 << 12)
 
+#define CPUID_7_0_EBX_FSGSBASE (1 << 0)
+#define CPUID_7_0_EBX_BMI1     (1 << 3)
+#define CPUID_7_0_EBX_HLE      (1 << 4)
+#define CPUID_7_0_EBX_AVX2     (1 << 5)
 #define CPUID_7_0_EBX_SMEP     (1 << 7)
+#define CPUID_7_0_EBX_BMI2     (1 << 8)
+#define CPUID_7_0_EBX_ERMS     (1 << 9)
+#define CPUID_7_0_EBX_INVPCID  (1 << 10)
+#define CPUID_7_0_EBX_RTM      (1 << 11)
+#define CPUID_7_0_EBX_RDSEED   (1 << 18)
+#define CPUID_7_0_EBX_ADX      (1 << 19)
 #define CPUID_7_0_EBX_SMAP     (1 << 20)
 
 #define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */

From 021941b9d97127bbd62a2ca39208d6a5d486b3cb Mon Sep 17 00:00:00 2001
From: Andre Przywara 
Date: Wed, 14 Nov 2012 16:28:53 -0200
Subject: [PATCH 1635/2270] target-i386/cpu: Add new Opteron CPU model
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Add a new base CPU model called Opteron_G5 to model the latest
Opteron CPUs. This increases the model value and model numbers and
adds TBM, F16C and FMA over the latest G4 model.

Signed-off-by: Andre Przywara 
Signed-off-by: Boris Ostrovsky 
[ehabkost: edited commit message]
Signed-off-by: Eduardo Habkost 
Reviewed-by: Igor Mammedov 
Signed-off-by: Andreas Färber 
---
 target-i386/cpu.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index f896e0cdca..c3aff4fe29 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -756,6 +756,38 @@ static x86_def_t builtin_x86_defs[] = {
         .xlevel = 0x8000001A,
         .model_id = "AMD Opteron 62xx class CPU",
     },
+    {
+        .name = "Opteron_G5",
+        .level = 0xd,
+        .vendor1 = CPUID_VENDOR_AMD_1,
+        .vendor2 = CPUID_VENDOR_AMD_2,
+        .vendor3 = CPUID_VENDOR_AMD_3,
+        .family = 21,
+        .model = 2,
+        .stepping = 0,
+        .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+             CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
+             CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
+             CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
+             CPUID_DE | CPUID_FP87,
+        .ext_features = CPUID_EXT_F16C | CPUID_EXT_AVX | CPUID_EXT_XSAVE |
+             CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
+             CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_FMA |
+             CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3,
+        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP |
+             CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
+             CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
+             CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
+             CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
+             CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
+             CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
+        .ext3_features = CPUID_EXT3_TBM | CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
+             CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
+             CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
+             CPUID_EXT3_LAHF_LM,
+        .xlevel = 0x8000001A,
+        .model_id = "AMD Opteron 63xx class CPU",
+    },
 };
 
 #ifdef CONFIG_KVM

From 37507094f350b75c62dc059f998e7185de3ab60a Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Wed, 14 Nov 2012 16:28:54 -0200
Subject: [PATCH 1636/2270] target-i386: Add Haswell CPU model
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Features added to the model, in relation to SandyBridge:

fma       CPUID[1].ECX[12]
pcid      CPUID[1].ECX[17]
movbe     CPUID[1].ECX[22]
fsgsbase  CPUID[EAX=7,ECX=0].EBX[0]
bmi1      CPUID[EAX=7,ECX=0].EBX[3]
hle       CPUID[EAX=7,ECX=0].EBX[4]
avx2      CPUID[EAX=7,ECX=0].EBX[5]
smep      CPUID[EAX=7,ECX=0].EBX[7]
bmi2      CPUID[EAX=7,ECX=0].EBX[8]
erms      CPUID[EAX=7,ECX=0].EBX[9]
invpcid   CPUID[EAX=7,ECX=0].EBX[10]
rtm       CPUID[EAX=7,ECX=0].EBX[11]

Signed-off-by: Eduardo Habkost 
Reviewed-by: Igor Mammedov 
Signed-off-by: Andreas Färber 
---
 target-i386/cpu.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index c3aff4fe29..64c34910a0 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -646,6 +646,35 @@ static x86_def_t builtin_x86_defs[] = {
         .xlevel = 0x8000000A,
         .model_id = "Intel Xeon E312xx (Sandy Bridge)",
     },
+    {
+        .name = "Haswell",
+        .level = 0xd,
+        .vendor1 = CPUID_VENDOR_INTEL_1,
+        .vendor2 = CPUID_VENDOR_INTEL_2,
+        .vendor3 = CPUID_VENDOR_INTEL_3,
+        .family = 6,
+        .model = 60,
+        .stepping = 1,
+        .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+             CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
+             CPUID_PGE | CPUID_MTRR | CPUID_APIC | CPUID_CX8 |
+             CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
+             CPUID_DE | CPUID_FP87,
+        .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
+             CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
+             CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
+             CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
+             CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
+             CPUID_EXT_PCID,
+        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
+        .ext3_features = CPUID_EXT3_LAHF_LM,
+        .cpuid_7_0_ebx_features = CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
+            CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
+            CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
+            CPUID_7_0_EBX_RTM,
+        .xlevel = 0x8000000A,
+        .model_id = "Intel Core Processor (Haswell)",
+    },
     {
         .name = "Opteron_G1",
         .level = 5,

From 1a89b60885ccc2abf7cc50275fcee70d0347425e Mon Sep 17 00:00:00 2001
From: Nickolai Zeldovich 
Date: Mon, 12 Nov 2012 17:59:49 +0100
Subject: [PATCH 1637/2270] slirp: Don't crash on packets from 0.0.0.0/8.

LWIP can generate packets with a source of 0.0.0.0, which triggers an
assertion failure in arp_table_add().  Instead of crashing, simply return
to avoid adding an invalid ARP table entry.

Signed-off-by: Nickolai Zeldovich 
Signed-off-by: Jan Kiszka 
---
 slirp/arp_table.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/slirp/arp_table.c b/slirp/arp_table.c
index 5d7b8acd1d..bf698c1ac5 100644
--- a/slirp/arp_table.c
+++ b/slirp/arp_table.c
@@ -38,7 +38,9 @@ void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN])
                 ethaddr[3], ethaddr[4], ethaddr[5]));
 
     /* Check 0.0.0.0/8 invalid source-only addresses */
-    assert((ip_addr & htonl(~(0xf << 28))) != 0);
+    if ((ip_addr & htonl(~(0xf << 28))) == 0) {
+        return;
+    }
 
     if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
         /* Do not register broadcast addresses */

From 63d2960bc46f63137d7fbd5ff56b81e54710d195 Mon Sep 17 00:00:00 2001
From: Klaus Stengel 
Date: Sat, 27 Oct 2012 19:53:39 +0200
Subject: [PATCH 1638/2270] slirp: Add domain-search option to slirp's DHCP
 server

This patch will allow the user to include the domain-search option in
replies from the built-in DHCP server. The domain suffixes can be
specified by adding dnssearch= entries to the "-net user" parameter.

[Jan: tiny style adjustments]

Signed-off-by: Klaus Stengel 
Signed-off-by: Jan Kiszka 
---
 net/slirp.c         |  35 ++++-
 qapi-schema.json    |   4 +
 qemu-options.hx     |  18 ++-
 slirp/Makefile.objs |   2 +-
 slirp/bootp.c       |  12 ++
 slirp/dnssearch.c   | 314 ++++++++++++++++++++++++++++++++++++++++++++
 slirp/libslirp.h    |   3 +-
 slirp/slirp.c       |   8 +-
 slirp/slirp.h       |   5 +
 9 files changed, 392 insertions(+), 9 deletions(-)
 create mode 100644 slirp/dnssearch.c

diff --git a/net/slirp.c b/net/slirp.c
index bf86a446c3..afb52c3af1 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -136,7 +136,7 @@ static int net_slirp_init(NetClientState *peer, const char *model,
                           const char *vhostname, const char *tftp_export,
                           const char *bootfile, const char *vdhcp_start,
                           const char *vnameserver, const char *smb_export,
-                          const char *vsmbserver)
+                          const char *vsmbserver, const char **dnssearch)
 {
     /* default settings according to historic slirp */
     struct in_addr net  = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */
@@ -242,7 +242,7 @@ static int net_slirp_init(NetClientState *peer, const char *model,
     s = DO_UPCAST(SlirpState, nc, nc);
 
     s->slirp = slirp_init(restricted, net, mask, host, vhostname,
-                          tftp_export, bootfile, dhcp, dns, s);
+                          tftp_export, bootfile, dhcp, dns, dnssearch, s);
     QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry);
 
     for (config = slirp_configs; config; config = config->next) {
@@ -699,6 +699,31 @@ net_init_slirp_configs(const StringList *fwd, int flags)
     }
 }
 
+static const char **slirp_dnssearch(const StringList *dnsname)
+{
+    const StringList *c = dnsname;
+    size_t i = 0, num_opts = 0;
+    const char **ret;
+
+    while (c) {
+        num_opts++;
+        c = c->next;
+    }
+
+    if (num_opts == 0) {
+        return NULL;
+    }
+
+    ret = g_malloc((num_opts + 1) * sizeof(*ret));
+    c = dnsname;
+    while (c) {
+        ret[i++] = c->value->str;
+        c = c->next;
+    }
+    ret[i] = NULL;
+    return ret;
+}
+
 int net_init_slirp(const NetClientOptions *opts, const char *name,
                    NetClientState *peer)
 {
@@ -706,6 +731,7 @@ int net_init_slirp(const NetClientOptions *opts, const char *name,
     char *vnet;
     int ret;
     const NetdevUserOptions *user;
+    const char **dnssearch;
 
     assert(opts->kind == NET_CLIENT_OPTIONS_KIND_USER);
     user = opts->user;
@@ -714,6 +740,8 @@ int net_init_slirp(const NetClientOptions *opts, const char *name,
            user->has_ip  ? g_strdup_printf("%s/24", user->ip) :
            NULL;
 
+    dnssearch = slirp_dnssearch(user->dnssearch);
+
     /* all optional fields are initialized to "all bits zero" */
 
     net_init_slirp_configs(user->hostfwd, SLIRP_CFG_HOSTFWD);
@@ -722,7 +750,7 @@ int net_init_slirp(const NetClientOptions *opts, const char *name,
     ret = net_slirp_init(peer, "user", name, user->q_restrict, vnet,
                          user->host, user->hostname, user->tftp,
                          user->bootfile, user->dhcpstart, user->dns, user->smb,
-                         user->smbserver);
+                         user->smbserver, dnssearch);
 
     while (slirp_configs) {
         config = slirp_configs;
@@ -731,6 +759,7 @@ int net_init_slirp(const NetClientOptions *opts, const char *name,
     }
 
     g_free(vnet);
+    g_free(dnssearch);
 
     return ret;
 }
diff --git a/qapi-schema.json b/qapi-schema.json
index 542e3ac069..5dfa052391 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2404,6 +2404,9 @@
 #
 # @dns: #optional guest-visible address of the virtual nameserver
 #
+# @dnssearch: #optional list of DNS suffixes to search, passed as DHCP option
+#             to the guest
+#
 # @smb: #optional root directory of the built-in SMB server
 #
 # @smbserver: #optional IP address of the built-in SMB server
@@ -2426,6 +2429,7 @@
     '*bootfile':  'str',
     '*dhcpstart': 'str',
     '*dns':       'str',
+    '*dnssearch': ['String'],
     '*smb':       'str',
     '*smbserver': 'str',
     '*hostfwd':   ['String'],
diff --git a/qemu-options.hx b/qemu-options.hx
index fe8f15c541..a165cff071 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1318,8 +1318,8 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
     "                create a new Network Interface Card and connect it to VLAN 'n'\n"
 #ifdef CONFIG_SLIRP
     "-net user[,vlan=n][,name=str][,net=addr[/mask]][,host=addr][,restrict=on|off]\n"
-    "         [,hostname=host][,dhcpstart=addr][,dns=addr][,tftp=dir][,bootfile=f]\n"
-    "         [,hostfwd=rule][,guestfwd=rule]"
+    "         [,hostname=host][,dhcpstart=addr][,dns=addr][,dnssearch=domain][,tftp=dir]\n"
+    "         [,bootfile=f][,hostfwd=rule][,guestfwd=rule]"
 #ifndef _WIN32
                                              "[,smb=dir[,smbserver=addr]]\n"
 #endif
@@ -1428,7 +1428,7 @@ able to contact the host and no guest IP packets will be routed over the host
 to the outside. This option does not affect any explicitly set forwarding rules.
 
 @item hostname=@var{name}
-Specifies the client hostname reported by the builtin DHCP server.
+Specifies the client hostname reported by the built-in DHCP server.
 
 @item dhcpstart=@var{addr}
 Specify the first of the 16 IPs the built-in DHCP server can assign. Default
@@ -1439,6 +1439,18 @@ Specify the guest-visible address of the virtual nameserver. The address must
 be different from the host address. Default is the 3rd IP in the guest network,
 i.e. x.x.x.3.
 
+@item dnssearch=@var{domain}
+Provides an entry for the domain-search list sent by the built-in
+DHCP server. More than one domain suffix can be transmitted by specifying
+this option multiple times. If supported, this will cause the guest to
+automatically try to append the given domain suffix(es) in case a domain name
+can not be resolved.
+
+Example:
+@example
+qemu -net user,dnssearch=mgmt.example.org,dnssearch=example.org [...]
+@end example
+
 @item tftp=@var{dir}
 When using the user mode network stack, activate a built-in TFTP
 server. The files in @var{dir} will be exposed as the root of a TFTP server.
diff --git a/slirp/Makefile.objs b/slirp/Makefile.objs
index bb43d3c08c..2daa9dc58d 100644
--- a/slirp/Makefile.objs
+++ b/slirp/Makefile.objs
@@ -1,3 +1,3 @@
-common-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o
+common-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o dnssearch.o
 common-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
 common-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o
diff --git a/slirp/bootp.c b/slirp/bootp.c
index 64eac7d101..b7db9fa335 100644
--- a/slirp/bootp.c
+++ b/slirp/bootp.c
@@ -287,6 +287,18 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
             memcpy(q, slirp->client_hostname, val);
             q += val;
         }
+
+        if (slirp->vdnssearch) {
+            size_t spaceleft = sizeof(rbp->bp_vend) - (q - rbp->bp_vend);
+            val = slirp->vdnssearch_len;
+            if (val + 1 > spaceleft) {
+                g_warning("DHCP packet size exceeded, "
+                    "omitting domain-search option.");
+            } else {
+                memcpy(q, slirp->vdnssearch, val);
+                q += val;
+            }
+        }
     } else {
         static const char nak_msg[] = "requested address not available";
 
diff --git a/slirp/dnssearch.c b/slirp/dnssearch.c
new file mode 100644
index 0000000000..4c9064ecb6
--- /dev/null
+++ b/slirp/dnssearch.c
@@ -0,0 +1,314 @@
+/*
+ * Domain search option for DHCP (RFC 3397)
+ *
+ * Copyright (c) 2012 Klaus Stengel
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include "slirp.h"
+
+static const uint8_t RFC3397_OPT_DOMAIN_SEARCH = 119;
+static const uint8_t MAX_OPT_LEN = 255;
+static const uint8_t OPT_HEADER_LEN = 2;
+static const uint8_t REFERENCE_LEN = 2;
+
+struct compact_domain;
+
+typedef struct compact_domain {
+    struct compact_domain *self;
+    struct compact_domain *refdom;
+    uint8_t *labels;
+    size_t len;
+    size_t common_octets;
+} CompactDomain;
+
+static size_t
+domain_suffix_diffoff(const CompactDomain *a, const CompactDomain *b)
+{
+    size_t la = a->len, lb = b->len;
+    uint8_t *da = a->labels + la, *db = b->labels + lb;
+    size_t i, lm = (la < lb) ? la : lb;
+
+    for (i = 0; i < lm; i++) {
+        da--; db--;
+        if (*da != *db) {
+            break;
+        }
+    }
+    return i;
+}
+
+static int domain_suffix_ord(const void *cva, const void *cvb)
+{
+    const CompactDomain *a = cva, *b = cvb;
+    size_t la = a->len, lb = b->len;
+    size_t doff = domain_suffix_diffoff(a, b);
+    uint8_t ca = a->labels[la - doff];
+    uint8_t cb = b->labels[lb - doff];
+
+    if (ca < cb) {
+        return -1;
+    }
+    if (ca > cb) {
+        return 1;
+    }
+    if (la < lb) {
+        return -1;
+    }
+    if (la > lb) {
+        return 1;
+    }
+    return 0;
+}
+
+static size_t domain_common_label(CompactDomain *a, CompactDomain *b)
+{
+    size_t res, doff = domain_suffix_diffoff(a, b);
+    uint8_t *first_eq_pos = a->labels + (a->len - doff);
+    uint8_t *label = a->labels;
+
+    while (*label && label < first_eq_pos) {
+        label += *label + 1;
+    }
+    res = a->len - (label - a->labels);
+    /* only report if it can help to reduce the packet size */
+    return (res > REFERENCE_LEN) ? res : 0;
+}
+
+static void domain_fixup_order(CompactDomain *cd, size_t n)
+{
+    size_t i;
+
+    for (i = 0; i < n; i++) {
+        CompactDomain *cur = cd + i, *next = cd[i].self;
+
+        while (!cur->common_octets) {
+            CompactDomain *tmp = next->self; /* backup target value */
+
+            next->self = cur;
+            cur->common_octets++;
+
+            cur = next;
+            next = tmp;
+        }
+    }
+}
+
+static void domain_mklabels(CompactDomain *cd, const char *input)
+{
+    uint8_t *len_marker = cd->labels;
+    uint8_t *output = len_marker; /* pre-incremented */
+    const char *in = input;
+    char cur_chr;
+    size_t len = 0;
+
+    if (cd->len == 0) {
+        goto fail;
+    }
+    cd->len++;
+
+    do {
+        cur_chr = *in++;
+        if (cur_chr == '.' || cur_chr == '\0') {
+            len = output - len_marker;
+            if ((len == 0 && cur_chr == '.') || len >= 64) {
+                goto fail;
+            }
+            *len_marker = len;
+
+            output++;
+            len_marker = output;
+        } else {
+            output++;
+            *output = cur_chr;
+        }
+    } while (cur_chr != '\0');
+
+    /* ensure proper zero-termination */
+    if (len != 0) {
+        *len_marker = 0;
+        cd->len++;
+    }
+    return;
+
+fail:
+    g_warning("failed to parse domain name '%s'\n", input);
+    cd->len = 0;
+}
+
+static void
+domain_mkxrefs(CompactDomain *doms, CompactDomain *last, size_t depth)
+{
+    CompactDomain *i = doms, *target = doms;
+
+    do {
+        if (i->labels < target->labels) {
+            target = i;
+        }
+    } while (i++ != last);
+
+    for (i = doms; i != last; i++) {
+        CompactDomain *group_last;
+        size_t next_depth;
+
+        if (i->common_octets == depth) {
+            continue;
+        }
+
+        next_depth = -1;
+        for (group_last = i; group_last != last; group_last++) {
+            size_t co = group_last->common_octets;
+            if (co <= depth) {
+                break;
+            }
+            if (co < next_depth) {
+                next_depth = co;
+            }
+        }
+        domain_mkxrefs(i, group_last, next_depth);
+
+        i = group_last;
+        if (i == last) {
+            break;
+        }
+    }
+
+    if (depth == 0) {
+        return;
+    }
+
+    i = doms;
+    do {
+        if (i != target && i->refdom == NULL) {
+            i->refdom = target;
+            i->common_octets = depth;
+        }
+    } while (i++ != last);
+}
+
+static size_t domain_compactify(CompactDomain *domains, size_t n)
+{
+    uint8_t *start = domains->self->labels, *outptr = start;
+    size_t i;
+
+    for (i = 0; i < n; i++) {
+        CompactDomain *cd = domains[i].self;
+        CompactDomain *rd = cd->refdom;
+
+        if (rd != NULL) {
+            size_t moff = (rd->labels - start)
+                    + (rd->len - cd->common_octets);
+            if (moff < 0x3FFFu) {
+                cd->len -= cd->common_octets - 2;
+                cd->labels[cd->len - 1] = moff & 0xFFu;
+                cd->labels[cd->len - 2] = 0xC0u | (moff >> 8);
+            }
+        }
+
+        if (cd->labels != outptr) {
+            memmove(outptr, cd->labels, cd->len);
+            cd->labels = outptr;
+        }
+        outptr += cd->len;
+    }
+    return outptr - start;
+}
+
+int translate_dnssearch(Slirp *s, const char **names)
+{
+    size_t blocks, bsrc_start, bsrc_end, bdst_start;
+    size_t i, num_domains, memreq = 0;
+    uint8_t *result = NULL, *outptr;
+    CompactDomain *domains = NULL;
+    const char **nameptr = names;
+
+    while (*nameptr != NULL) {
+        nameptr++;
+    }
+
+    num_domains = nameptr - names;
+    if (num_domains == 0) {
+        return -2;
+    }
+
+    domains = g_malloc(num_domains * sizeof(*domains));
+
+    for (i = 0; i < num_domains; i++) {
+        size_t nlen = strlen(names[i]);
+        memreq += nlen + 2; /* 1 zero octet + 1 label length octet */
+        domains[i].self = domains + i;
+        domains[i].len = nlen;
+        domains[i].common_octets = 0;
+        domains[i].refdom = NULL;
+    }
+
+    /* reserve extra 2 header bytes for each 255 bytes of output */
+    memreq += ((memreq + MAX_OPT_LEN - 1) / MAX_OPT_LEN) * OPT_HEADER_LEN;
+    result = g_malloc(memreq * sizeof(*result));
+
+    outptr = result;
+    for (i = 0; i < num_domains; i++) {
+        domains[i].labels = outptr;
+        domain_mklabels(domains + i, names[i]);
+        outptr += domains[i].len;
+    }
+
+    if (outptr == result) {
+        g_free(domains);
+        g_free(result);
+        return -1;
+    }
+
+    qsort(domains, num_domains, sizeof(*domains), domain_suffix_ord);
+    domain_fixup_order(domains, num_domains);
+
+    for (i = 1; i < num_domains; i++) {
+        size_t cl = domain_common_label(domains + i - 1, domains + i);
+        domains[i - 1].common_octets = cl;
+    }
+
+    domain_mkxrefs(domains, domains + num_domains - 1, 0);
+    memreq = domain_compactify(domains, num_domains);
+
+    blocks = (memreq + MAX_OPT_LEN - 1) / MAX_OPT_LEN;
+    bsrc_end = memreq;
+    bsrc_start = (blocks - 1) * MAX_OPT_LEN;
+    bdst_start = bsrc_start + blocks * OPT_HEADER_LEN;
+    memreq += blocks * OPT_HEADER_LEN;
+
+    while (blocks--) {
+        size_t len = bsrc_end - bsrc_start;
+        memmove(result + bdst_start, result + bsrc_start, len);
+        result[bdst_start - 2] = RFC3397_OPT_DOMAIN_SEARCH;
+        result[bdst_start - 1] = len;
+        bsrc_end = bsrc_start;
+        bsrc_start -= MAX_OPT_LEN;
+        bdst_start -= MAX_OPT_LEN + OPT_HEADER_LEN;
+    }
+
+    g_free(domains);
+    s->vdnssearch = result;
+    s->vdnssearch_len = memreq;
+    return 0;
+}
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index 9b471b5053..49609c2ad7 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -12,7 +12,8 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
                   struct in_addr vnetmask, struct in_addr vhost,
                   const char *vhostname, const char *tftp_path,
                   const char *bootfile, struct in_addr vdhcp_start,
-                  struct in_addr vnameserver, void *opaque);
+                  struct in_addr vnameserver, const char **vdnssearch,
+                  void *opaque);
 void slirp_cleanup(Slirp *slirp);
 
 void slirp_update_timeout(uint32_t *timeout);
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 38e0a2193a..3395d509a2 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -203,7 +203,8 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
                   struct in_addr vnetmask, struct in_addr vhost,
                   const char *vhostname, const char *tftp_path,
                   const char *bootfile, struct in_addr vdhcp_start,
-                  struct in_addr vnameserver, void *opaque)
+                  struct in_addr vnameserver, const char **vdnssearch,
+                  void *opaque)
 {
     Slirp *slirp = g_malloc0(sizeof(Slirp));
 
@@ -233,6 +234,10 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
     slirp->vdhcp_startaddr = vdhcp_start;
     slirp->vnameserver_addr = vnameserver;
 
+    if (vdnssearch) {
+        translate_dnssearch(slirp, vdnssearch);
+    }
+
     slirp->opaque = opaque;
 
     register_savevm(NULL, "slirp", 0, 3,
@@ -252,6 +257,7 @@ void slirp_cleanup(Slirp *slirp)
     ip_cleanup(slirp);
     m_cleanup(slirp);
 
+    g_free(slirp->vdnssearch);
     g_free(slirp->tftp_prefix);
     g_free(slirp->bootp_filename);
     g_free(slirp);
diff --git a/slirp/slirp.h b/slirp/slirp.h
index f2c5eca892..0107b07e66 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -235,6 +235,8 @@ struct Slirp {
     /* bootp/dhcp states */
     BOOTPClient bootp_clients[NB_BOOTP_CLIENTS];
     char *bootp_filename;
+    size_t vdnssearch_len;
+    uint8_t *vdnssearch;
 
     /* tcp states */
     struct socket tcb;
@@ -294,6 +296,9 @@ void lprint(const char *, ...) GCC_FMT_ATTR(1, 2);
 #define SO_OPTIONS DO_KEEPALIVE
 #define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL)
 
+/* dnssearch.c */
+int translate_dnssearch(Slirp *s, const char ** names);
+
 /* cksum.c */
 int cksum(struct mbuf *m, int len);
 

From 68d001928b151a0c50f367c0bdca645b3d5e9ed3 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno 
Date: Wed, 14 Nov 2012 15:04:42 +0100
Subject: [PATCH 1639/2270] mips/malta: fix CBUS UART interrupt pin

According to the MIPS Malta Developement Platform User's Manual, the
i8259 interrupt controller is supposed to be connected to the hardware
IRQ0, and the CBUS UART to the hardware interrupt 2.

In QEMU they are both connected to hardware interrupt 0, the CBUS UART
interrupt being wrong. This patch fixes that. It should be noted that
the irq array in QEMU includes the software interrupts, hence
env->irq[2] is the first hardware interrupt.

Cc: Ralf Baechle 
Reviewed-by: Eric Johnson 
Signed-off-by: Aurelien Jarno 
---
 hw/mips_malta.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 0571d58908..4d2464a02c 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -861,7 +861,8 @@ void mips_malta_init(QEMUMachineInitArgs *args)
     be = 0;
 #endif
     /* FPGA */
-    malta_fpga_init(system_memory, FPGA_ADDRESS, env->irq[2], serial_hds[2]);
+    /* The CBUS UART is attached to the MIPS CPU INT2 pin, ie interrupt 4 */
+    malta_fpga_init(system_memory, FPGA_ADDRESS, env->irq[4], serial_hds[2]);
 
     /* Load firmware in flash / BIOS. */
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);

From 6801038bc52d61f81ac8a25fbe392f1bad982887 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=99=B3=E9=9F=8B=E4=BB=BB=20=28Wei-Ren=20Chen=29?=
 
Date: Wed, 14 Nov 2012 10:49:55 +0800
Subject: [PATCH 1640/2270] target-mips: fix wrong microMIPS opcode encoding

While reading microMIPS decoding, I found a possible wrong opcode
encoding. According to [1] page 166, the bits 13..12 for MULTU is
0x01 rather than 0x00. Please review, thanks.

[1] MIPS Architecture for Programmers VolumeIV-e: The MIPS DSP
    Application-Specific Extension to the microMIPS32 Architecture

Signed-off-by: Chen Wei-Ren 
Signed-off-by: Aurelien Jarno 
---
 target-mips/translate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index f6fc0c27ae..01b48fa2a2 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -10385,7 +10385,7 @@ enum {
 
     /* bits 13..12 for 0x32 */
     MULT_ACC = 0x0,
-    MULTU_ACC = 0x0,
+    MULTU_ACC = 0x1,
 
     /* bits 15..12 for 0x2c */
     SEB = 0x2,

From 80dcfb8532ae76343109a48f12ba8ca1c505c179 Mon Sep 17 00:00:00 2001
From: Alon Levy 
Date: Wed, 14 Nov 2012 15:09:07 +0200
Subject: [PATCH 1641/2270] virtio-serial-bus: post_load send_event when vm is
 running

Alexander Larsson found irq injection to Windows guests stopped after a
migration.  The symptom was the mouse stopped working.

Reproduction steps are:
1. On src, start qemu with a virtio-serial port without any backend
2. On dest, start qemu with a virtio-serial port with a backend
3. Migrate.

Upon migration, the older code detected the change in backend connection
status, and sent a notification to the guest.  However, it's not
guaranteed that the apic is ready to inject irqs into the guest, and the
irq line remained high, resulting in any future interrupts going
unnoticed by the guest as well.

Add a new timer based on vm_clock for 1 ns in the future from post_load
to do the event send in case host_connected differs between migration
source and target.

RHBZ: 867366

Signed-off-by: Alon Levy 
Acked-by: Paolo Bonzini 
Signed-off-by: Amit Shah  # verbose commit log
---
 hw/virtio-serial-bus.c | 54 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 44 insertions(+), 10 deletions(-)

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index d20bd8bf75..efa8a81db6 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -53,6 +53,15 @@ struct VirtIOSerial {
     uint32_t *ports_map;
 
     struct virtio_console_config config;
+
+    struct {
+        QEMUTimer *timer;
+        int nr_active_ports;
+        struct {
+            VirtIOSerialPort *port;
+            uint8_t host_connected;
+        } *connected;
+    } post_load;
 };
 
 static VirtIOSerialPort *find_port_by_id(VirtIOSerial *vser, uint32_t id)
@@ -626,6 +635,29 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
     }
 }
 
+static void virtio_serial_post_load_timer_cb(void *opaque)
+{
+    int i;
+    VirtIOSerial *s = opaque;
+    VirtIOSerialPort *port;
+    uint8_t host_connected;
+
+    for (i = 0 ; i < s->post_load.nr_active_ports; ++i) {
+        port = s->post_load.connected[i].port;
+        host_connected = s->post_load.connected[i].host_connected;
+        if (host_connected != port->host_connected) {
+            /*
+             * We have to let the guest know of the host connection
+             * status change
+             */
+            send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN,
+                               port->host_connected);
+        }
+    }
+    g_free(s->post_load.connected);
+    s->post_load.connected = NULL;
+}
+
 static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
 {
     VirtIOSerial *s = opaque;
@@ -673,10 +705,13 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
 
     qemu_get_be32s(f, &nr_active_ports);
 
+    s->post_load.nr_active_ports = nr_active_ports;
+    s->post_load.connected =
+        g_malloc0(sizeof(*s->post_load.connected) * nr_active_ports);
+
     /* Items in struct VirtIOSerialPort */
     for (i = 0; i < nr_active_ports; i++) {
         uint32_t id;
-        bool host_connected;
 
         id = qemu_get_be32(f);
         port = find_port_by_id(s, id);
@@ -685,15 +720,8 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
         }
 
         port->guest_connected = qemu_get_byte(f);
-        host_connected = qemu_get_byte(f);
-        if (host_connected != port->host_connected) {
-            /*
-             * We have to let the guest know of the host connection
-             * status change
-             */
-            send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN,
-                               port->host_connected);
-        }
+        s->post_load.connected[i].port = port;
+        s->post_load.connected[i].host_connected = qemu_get_byte(f);
 
         if (version_id > 2) {
             uint32_t elem_popped;
@@ -718,6 +746,7 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
             }
         }
     }
+    qemu_mod_timer(s->post_load.timer, 1);
     return 0;
 }
 
@@ -967,6 +996,9 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf)
     register_savevm(dev, "virtio-console", -1, 3, virtio_serial_save,
                     virtio_serial_load, vser);
 
+    vser->post_load.timer = qemu_new_timer_ns(vm_clock,
+            virtio_serial_post_load_timer_cb, vser);
+
     return vdev;
 }
 
@@ -979,6 +1011,8 @@ void virtio_serial_exit(VirtIODevice *vdev)
     g_free(vser->ivqs);
     g_free(vser->ovqs);
     g_free(vser->ports_map);
+    g_free(vser->post_load.connected);
+    qemu_free_timer(vser->post_load.timer);
 
     virtio_cleanup(vdev);
 }

From 4ea375bf37d655bbf1696239ebea8575956bb226 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Thu, 8 Nov 2012 15:54:05 +0100
Subject: [PATCH 1642/2270] fix live migration

Commit 1c380f9460522f32c8dd2577b2a53d518ec91c6d breaks live migration.
DMA stops working for ehci (and probably for any pci device) after
restoring the guest because the bus master region never gets enabled.
Add code doing that after loading the pci config space from vmstate.

Cc: Avi Kivity 
Cc: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/pci.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/hw/pci.c b/hw/pci.c
index dceda0bdc5..9841e398a6 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -367,6 +367,10 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
 
     pci_update_mappings(s);
 
+    memory_region_set_enabled(&s->bus_master_enable_region,
+                              pci_get_word(s->config + PCI_COMMAND)
+                              & PCI_COMMAND_MASTER);
+
     g_free(config);
     return 0;
 }

From 155de06f2480219ea99916ddb9ad61b622b8f51f Mon Sep 17 00:00:00 2001
From: David Gibson 
Date: Wed, 14 Nov 2012 16:23:50 +1100
Subject: [PATCH 1643/2270] usb: Fix (another) bug in usb_packet_map() for
 IOMMU handling

Elements in qemu SGLists can cross IOMMU page boundaries.  So, in commit
39c138c8420f51a7da7b35233a8d7400a0b589ac "usb: Fix usb_packet_map() in the
presence of IOMMUs", I changed usb_packet_map() to split up each SGList
element on IOMMU page boundaries and each resulting piece of qemu's memory
space separately to the iovec the usb code uses internally.

That was correct in concept, but the patch has a bug.  The 'base' variable
correctly steps through the dma address of each piece, but then we call
the dma_memory_map() function on the base address of the whole SGList
element every time.

This patch fixes at least one problem using XHCI on the pseries guest
machine.  It didn't affect OHCI because that doesn't use usb_packet_map().
In theory it also affects EHCI, but we haven't observed that in practice.
I think the transfers were small enough on EHCI that they never crossed an
IOMMU page boundary in practice.

Signed-off-by: David Gibson 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/libhw.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/usb/libhw.c b/hw/usb/libhw.c
index 703e2d213b..24d3cad3a2 100644
--- a/hw/usb/libhw.c
+++ b/hw/usb/libhw.c
@@ -37,7 +37,7 @@ int usb_packet_map(USBPacket *p, QEMUSGList *sgl)
 
         while (len) {
             dma_addr_t xlen = len;
-            mem = dma_memory_map(sgl->dma, sgl->sg[i].base, &xlen, dir);
+            mem = dma_memory_map(sgl->dma, base, &xlen, dir);
             if (!mem) {
                 goto err;
             }

From c06c68c928edd36eb56baa0d2db065bbec28af27 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Wed, 14 Nov 2012 15:51:18 +0100
Subject: [PATCH 1644/2270] usb-host: scan for usb devices when the vm starts

Commit a844ed842d9a9d929645c09ae0f52f753d7a02e0 leads to usb-host
detecting devices not right after qemu startup because the guest
isn't running yet.  Instead they are found on the first of the
regular usb device poll runs.  Which is too late for seabios to see
them, so booting from usb sticks fails.

Fix this by adding a vm state change handler which triggers a device
scan when the vm is started.

Signed-off-by: Gerd Hoffmann 
---
 hw/usb/host-linux.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c
index ca3e24a850..5bc77b2fec 100644
--- a/hw/usb/host-linux.c
+++ b/hw/usb/host-linux.c
@@ -1738,6 +1738,7 @@ static int usb_host_scan(void *opaque, USBScanFunc *func)
 }
 
 static QEMUTimer *usb_auto_timer;
+static VMChangeStateEntry *usb_vmstate;
 
 static int usb_host_auto_scan(void *opaque, int bus_num,
                               int addr, const char *port,
@@ -1792,6 +1793,13 @@ static int usb_host_auto_scan(void *opaque, int bus_num,
     return 0;
 }
 
+static void usb_host_vm_state(void *unused, int running, RunState state)
+{
+    if (running) {
+        usb_host_auto_check(unused);
+    }
+}
+
 static void usb_host_auto_check(void *unused)
 {
     struct USBHostDevice *s;
@@ -1820,6 +1828,9 @@ static void usb_host_auto_check(void *unused)
         }
     }
 
+    if (!usb_vmstate) {
+        usb_vmstate = qemu_add_vm_change_state_handler(usb_host_vm_state, NULL);
+    }
     if (!usb_auto_timer) {
         usb_auto_timer = qemu_new_timer_ms(rt_clock, usb_host_auto_check, NULL);
         if (!usb_auto_timer) {

From df9ffb726ff13f850b8829be1bc85ed621b903ac Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Mon, 12 Nov 2012 12:40:46 +0100
Subject: [PATCH 1645/2270] vga: fix bochs alignment issue

The bochs dispi interface traditionally uses port 0x1ce as 16bit index
register and port 0x1cf as 16bit data register.  The later is unaligned,
and probably for that reason the the data register was moved to 0x1d0
for non-x86 archs.

This patch makes the data register available at 0x1d0 on x86 too.  The
old x86 location is kept for compatibility reasons, so both 0x1cf and
0x1d0 can be used as data register on x86.

Signed-off-by: Gerd Hoffmann 
---
 docs/specs/standard-vga.txt | 3 ++-
 hw/vga.c                    | 3 +--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/docs/specs/standard-vga.txt b/docs/specs/standard-vga.txt
index 1cecccd469..8a4c1e93cd 100644
--- a/docs/specs/standard-vga.txt
+++ b/docs/specs/standard-vga.txt
@@ -36,7 +36,8 @@ IO ports used
 
 03c0 - 03df : standard vga ports
 01ce        : bochs vbe interface index port
-01cf        : bochs vbe interface data port
+01cf        : bochs vbe interface data port (x86 only)
+01d0        : bochs vbe interface data port
 
 
 Memory regions used
diff --git a/hw/vga.c b/hw/vga.c
index 81aa76bef9..2b0200a164 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2321,9 +2321,8 @@ static const MemoryRegionPortio vbe_portio_list[] = {
     { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
 # ifdef TARGET_I386
     { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
-# else
-    { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
 # endif
+    { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
     PORTIO_END_OF_LIST(),
 };
 

From c96c53b5f10c4b34e9fe1dcb1a5aadf204c16279 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Mon, 12 Nov 2012 22:33:21 +0100
Subject: [PATCH 1646/2270] vga: fix mmio vga register mapping

---
 hw/vga-pci.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index ec29cac7f4..947e35c76f 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -84,9 +84,10 @@ static void pci_vga_ioport_write(void *ptr, hwaddr addr,
                                  uint64_t val, unsigned size)
 {
     PCIVGAState *d = ptr;
+
     switch (size) {
     case 1:
-        vga_ioport_write(&d->vga, addr, val);
+        vga_ioport_write(&d->vga, addr + 0x3c0, val);
         break;
     case 2:
         /*
@@ -94,8 +95,8 @@ static void pci_vga_ioport_write(void *ptr, hwaddr addr,
          * indexed registers with a single word write because the
          * index byte is updated first.
          */
-        vga_ioport_write(&d->vga, addr, val & 0xff);
-        vga_ioport_write(&d->vga, addr+1, (val >> 8) & 0xff);
+        vga_ioport_write(&d->vga, addr + 0x3c0, val & 0xff);
+        vga_ioport_write(&d->vga, addr + 0x3c1, (val >> 8) & 0xff);
         break;
     }
 }

From 537e8f1aa838677c8efd5e0966e89c4b5423dd18 Mon Sep 17 00:00:00 2001
From: Jan Kiszka 
Date: Thu, 15 Nov 2012 09:23:30 +0100
Subject: [PATCH 1647/2270] usb: host-linux: Ignore parsing errors of the
 device descriptors

The Linux is more tolerant here as well: Just stop parsing the device
descriptors when an error is detected but do not reset what was found
so far. This allows to run buggy devices with partially invalid
descriptors.

Signed-off-by: Jan Kiszka 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/host-linux.c | 31 +++++++++++--------------------
 1 file changed, 11 insertions(+), 20 deletions(-)

diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c
index 5bc77b2fec..b17e1dcb7f 100644
--- a/hw/usb/host-linux.c
+++ b/hw/usb/host-linux.c
@@ -135,7 +135,7 @@ static int parse_filter(const char *spec, struct USBAutoFilter *f);
 static void usb_host_auto_check(void *unused);
 static int usb_host_read_file(char *line, size_t line_size,
                             const char *device_file, const char *device_name);
-static int usb_linux_update_endp_table(USBHostDevice *s);
+static void usb_linux_update_endp_table(USBHostDevice *s);
 
 static int usb_host_usbfs_type(USBHostDevice *s, USBPacket *p)
 {
@@ -1132,8 +1132,7 @@ static void usb_host_handle_control(USBDevice *dev, USBPacket *p,
     p->status = USB_RET_ASYNC;
 }
 
-/* returns 1 on problem encountered or 0 for success */
-static int usb_linux_update_endp_table(USBHostDevice *s)
+static void usb_linux_update_endp_table(USBHostDevice *s)
 {
     static const char *tname[] = {
         [USB_ENDPOINT_XFER_CONTROL] = "control",
@@ -1159,23 +1158,23 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
         if (d->bLength < 2) {
             trace_usb_host_parse_error(s->bus_num, s->addr,
                                        "descriptor too short");
-            goto error;
+            return;
         }
         if (i + d->bLength > s->descr_len) {
             trace_usb_host_parse_error(s->bus_num, s->addr,
                                        "descriptor too long");
-            goto error;
+            return;
         }
         switch (d->bDescriptorType) {
         case 0:
             trace_usb_host_parse_error(s->bus_num, s->addr,
                                        "invalid descriptor type");
-            goto error;
+            return;
         case USB_DT_DEVICE:
             if (d->bLength < 0x12) {
                 trace_usb_host_parse_error(s->bus_num, s->addr,
                                            "device descriptor too short");
-                goto error;
+                return;
             }
             v = (d->u.device.idVendor_hi << 8) | d->u.device.idVendor_lo;
             p = (d->u.device.idProduct_hi << 8) | d->u.device.idProduct_lo;
@@ -1185,7 +1184,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
             if (d->bLength < 0x09) {
                 trace_usb_host_parse_error(s->bus_num, s->addr,
                                            "config descriptor too short");
-                goto error;
+                return;
             }
             configuration = d->u.config.bConfigurationValue;
             active = (configuration == s->dev.configuration);
@@ -1196,7 +1195,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
             if (d->bLength < 0x09) {
                 trace_usb_host_parse_error(s->bus_num, s->addr,
                                            "interface descriptor too short");
-                goto error;
+                return;
             }
             interface = d->u.interface.bInterfaceNumber;
             altsetting = d->u.interface.bAlternateSetting;
@@ -1209,7 +1208,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
             if (d->bLength < 0x07) {
                 trace_usb_host_parse_error(s->bus_num, s->addr,
                                            "endpoint descriptor too short");
-                goto error;
+                return;
             }
             devep = d->u.endpoint.bEndpointAddress;
             pid = (devep & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT;
@@ -1217,7 +1216,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
             if (ep == 0) {
                 trace_usb_host_parse_error(s->bus_num, s->addr,
                                            "invalid endpoint address");
-                goto error;
+                return;
             }
 
             type = d->u.endpoint.bmAttributes & 0x3;
@@ -1250,11 +1249,6 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
             break;
         }
     }
-    return 0;
-
-error:
-    usb_ep_reset(&s->dev);
-    return 1;
 }
 
 /*
@@ -1341,10 +1335,7 @@ static int usb_host_open(USBHostDevice *dev, int bus_num,
     }
 
     usb_ep_init(&dev->dev);
-    ret = usb_linux_update_endp_table(dev);
-    if (ret) {
-        goto fail;
-    }
+    usb_linux_update_endp_table(dev);
 
     if (speed == -1) {
         struct usbdevfs_connectinfo ci;

From 30d68cf6e156b97fc462e18f38ce83f44702cd7f Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Wed, 14 Nov 2012 17:21:36 +0100
Subject: [PATCH 1648/2270] ehci: Don't access packet after freeing it

ehci_state_writeback() will free the packet, so we should not access
the packet after calling ehci_state_writeback().

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-ehci.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index ee6c9ae302..a8b1a40dea 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -453,12 +453,13 @@ static EHCIPacket *ehci_alloc_packet(EHCIQueue *q)
 static void ehci_free_packet(EHCIPacket *p)
 {
     if (p->async == EHCI_ASYNC_FINISHED) {
-        int state = ehci_get_state(p->queue->ehci, p->queue->async);
+        EHCIQueue *q = p->queue;
+        int state = ehci_get_state(q->ehci, q->async);
         /* This is a normal, but rare condition (cancel racing completion) */
         fprintf(stderr, "EHCI: Warning packet completed but not processed\n");
-        ehci_state_executing(p->queue);
-        ehci_state_writeback(p->queue);
-        ehci_set_state(p->queue->ehci, p->queue->async, state);
+        ehci_state_executing(q);
+        ehci_state_writeback(q);
+        ehci_set_state(q->ehci, q->async, state);
         /* state_writeback recurses into us with async == EHCI_ASYNC_NONE!! */
         return;
     }

From ff80ce599e0465cc6109a38bd3a8ca1890e88891 Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Wed, 14 Nov 2012 17:21:37 +0100
Subject: [PATCH 1649/2270] ehci: Fixup q->qtdaddr after cancelling an already
 completed packet

This avoids the q->qtdaddr == p->qtdaddr asserts we have triggering, when
a queue contains multiple completed packages when we cancel the queue.

I triggered this with windows7 + async interrupt endpoint handling (*)
+ not detecting circles in ehci_fill_queue() properly, which makes the qtd
validation in ehci_fill_queue fail, causing cancellation of the queue on every
mouse event ...

*) Which is not going upstream as it will cause loss of interrupt events on
migration.

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-ehci.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index a8b1a40dea..5e3b4a8c4c 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -189,6 +189,7 @@ static const char *ehci_mmio_names[] = {
 
 static int ehci_state_executing(EHCIQueue *q);
 static int ehci_state_writeback(EHCIQueue *q);
+static int ehci_state_advqueue(EHCIQueue *q);
 static int ehci_fill_queue(EHCIPacket *p);
 
 static const char *nr2str(const char **n, size_t len, uint32_t nr)
@@ -459,6 +460,9 @@ static void ehci_free_packet(EHCIPacket *p)
         fprintf(stderr, "EHCI: Warning packet completed but not processed\n");
         ehci_state_executing(q);
         ehci_state_writeback(q);
+        if (!(q->qh.token & QTD_TOKEN_HALT)) {
+            ehci_state_advqueue(q);
+        }
         ehci_set_state(q->ehci, q->async, state);
         /* state_writeback recurses into us with async == EHCI_ASYNC_NONE!! */
         return;

From 601a234731602df7c2bf6d01301c6eec4b1d1a5a Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Wed, 14 Nov 2012 17:21:38 +0100
Subject: [PATCH 1650/2270] ehci: Better detection for qtd-s linked in circles

Windows links interrupt qtd-s in circles, which means that when interrupt
endpoints return USB_RET_ASYNC, combined with the recent
"ehci: Retry to fill the queue while waiting for td completion" patch,
we keep adding the tds to the queue over and over again, as we detect the
circle from fill_queue, but we call it over and over again ...

This patch fixes this by changing the circle detection to also detect
circling into tds already queued up previously.

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-ehci.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 5e3b4a8c4c..89b7520c07 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1790,7 +1790,7 @@ static int ehci_fill_queue(EHCIPacket *p)
     USBEndpoint *ep = p->packet.ep;
     EHCIQueue *q = p->queue;
     EHCIqtd qtd = p->qtd;
-    uint32_t qtdaddr, start_addr = p->qtdaddr;
+    uint32_t qtdaddr;
 
     for (;;) {
         if (NLPTR_TBIT(qtd.next) != 0) {
@@ -1801,8 +1801,10 @@ static int ehci_fill_queue(EHCIPacket *p)
          * Detect circular td lists, Windows creates these, counting on the
          * active bit going low after execution to make the queue stop.
          */
-        if (qtdaddr == start_addr) {
-            break;
+        QTAILQ_FOREACH(p, &q->packets, next) {
+            if (p->qtdaddr == qtdaddr) {
+                goto leave;
+            }
         }
         get_dwords(q->ehci, NLPTR_GET(qtdaddr),
                    (uint32_t *) &qtd, sizeof(EHCIqtd) >> 2);
@@ -1819,6 +1821,7 @@ static int ehci_fill_queue(EHCIPacket *p)
         assert(p->packet.status == USB_RET_ASYNC);
         p->async = EHCI_ASYNC_INFLIGHT;
     }
+leave:
     usb_device_flush_ep_queue(ep->dev, ep);
     return 1;
 }

From 2c7b15c1dec4b2ec17549c760df0b7a7cea3ed7d Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Thu, 15 Nov 2012 14:14:58 +0100
Subject: [PATCH 1651/2270] ehci: Don't verify the next pointer for periodic
 qh-s and qtd-s

While testing the move to async packet handling for interrupt endpoints I
noticed that Windows-XP likes to play tricks with the next pointer for
periodic qh-s, so we should not fail qh / qtd verification when it changes.

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-ehci.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 89b7520c07..287a066d0a 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1550,8 +1550,10 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
     endp    = get_field(qh.epchar, QH_EPCHAR_EP);
     if ((devaddr != get_field(q->qh.epchar, QH_EPCHAR_DEVADDR)) ||
         (endp    != get_field(q->qh.epchar, QH_EPCHAR_EP)) ||
-        (memcmp(&qh.current_qtd, &q->qh.current_qtd,
-                                 9 * sizeof(uint32_t)) != 0) ||
+        (qh.current_qtd != q->qh.current_qtd) ||
+        (q->async && qh.next_qtd != q->qh.next_qtd) ||
+        (memcmp(&qh.altnext_qtd, &q->qh.altnext_qtd,
+                                 7 * sizeof(uint32_t)) != 0) ||
         (q->dev != NULL && q->dev->addr != devaddr)) {
         if (ehci_reset_queue(q) > 0) {
             ehci_trace_guest_bug(ehci, "guest updated active QH");
@@ -1719,7 +1721,8 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
     p = QTAILQ_FIRST(&q->packets);
     if (p != NULL) {
         if (p->qtdaddr != q->qtdaddr ||
-            (!NLPTR_TBIT(p->qtd.next) && (p->qtd.next != qtd.next)) ||
+            (q->async && !NLPTR_TBIT(p->qtd.next) &&
+                (p->qtd.next != qtd.next)) ||
             (!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd.altnext)) ||
             p->qtd.bufptr[0] != qtd.bufptr[0]) {
             ehci_cancel_queue(q);

From 40862309a9d733cb0e878c79f477de003897b5d2 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Tue, 13 Nov 2012 17:20:05 +0100
Subject: [PATCH 1652/2270] ehci: keep the frame timer running in case the
 guest asked for frame list rollover interrupts

Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-ehci.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 287a066d0a..14269dafed 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -964,6 +964,9 @@ static void ehci_opreg_write(void *ptr, hwaddr addr,
 
     case USBINTR:
         val &= USBINTR_MASK;
+        if (ehci_enabled(s) && (USBSTS_FLR & val)) {
+            qemu_bh_schedule(s->async_bh);
+        }
         break;
 
     case FRINDEX:
@@ -2220,6 +2223,10 @@ static void ehci_frame_timer(void *opaque)
         ehci->async_stepdown = 0;
     }
 
+    if (ehci_enabled(ehci) && (ehci->usbintr & USBSTS_FLR)) {
+        need_timer++;
+    }
+
     if (need_timer) {
         /* If we've raised int, we speed up the timer, so that we quickly
          * notice any new packets queued up in response */

From 55903f1d2d8abfa8d7610ab32a4046a1ed4fdbb8 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Thu, 15 Nov 2012 13:07:49 +0100
Subject: [PATCH 1653/2270] ehci: handle dma errors

Starting with commit 1c380f9460522f32c8dd2577b2a53d518ec91c6d dma
transfers can actually fail.  This patch makes ehci keep track
of the busmaster bit in pci config space, by setting/clearing the
dma_context pointer.  Attempts to dma without context will result
in raising HSE (Host System Error) interrupt and stopping the host
controller.

This patch fixes WinXP not booting with a usb stick attached to ehci.
Root cause is seabios activating ehci so you can boot from the stick,
and WinXP clearing the busmaster bit before resetting the host
controller, leading to ehci actually trying dma while it is disabled.

Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-ehci-pci.c | 17 ++++++++++++
 hw/usb/hcd-ehci.c     | 63 ++++++++++++++++++++++++++++++-------------
 trace-events          |  1 +
 3 files changed, 62 insertions(+), 19 deletions(-)

diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c
index fe45a1fbba..5887eab197 100644
--- a/hw/usb/hcd-ehci-pci.c
+++ b/hw/usb/hcd-ehci-pci.c
@@ -17,6 +17,7 @@
 
 #include "hw/usb/hcd-ehci.h"
 #include "hw/pci.h"
+#include "range.h"
 
 typedef struct EHCIPCIState {
     PCIDevice pcidev;
@@ -79,6 +80,21 @@ static int usb_ehci_pci_initfn(PCIDevice *dev)
     return 0;
 }
 
+static void usb_ehci_pci_write_config(PCIDevice *dev, uint32_t addr,
+                                      uint32_t val, int l)
+{
+    EHCIPCIState *i = DO_UPCAST(EHCIPCIState, pcidev, dev);
+    bool busmaster;
+
+    pci_default_write_config(dev, addr, val, l);
+
+    if (!range_covers_byte(addr, l, PCI_COMMAND)) {
+        return;
+    }
+    busmaster = pci_get_word(dev->config + PCI_COMMAND) & PCI_COMMAND_MASTER;
+    i->ehci.dma = busmaster ? pci_dma_context(dev) : NULL;
+}
+
 static Property ehci_pci_properties[] = {
     DEFINE_PROP_UINT32("maxframes", EHCIPCIState, ehci.maxframes, 128),
     DEFINE_PROP_END_OF_LIST(),
@@ -106,6 +122,7 @@ static void ehci_class_init(ObjectClass *klass, void *data)
     k->device_id = i->device_id;
     k->revision = i->revision;
     k->class_id = PCI_CLASS_SERIAL_USB;
+    k->config_write = usb_ehci_pci_write_config;
     dc->vmsd = &vmstate_ehci_pci;
     dc->props = ehci_pci_properties;
 }
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 14269dafed..7df8e21ecb 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1003,21 +1003,25 @@ static void ehci_opreg_write(void *ptr, hwaddr addr,
                                 *mmio, old);
 }
 
-
-// TODO : Put in common header file, duplication from usb-ohci.c
-
 /* Get an array of dwords from main memory */
 static inline int get_dwords(EHCIState *ehci, uint32_t addr,
                              uint32_t *buf, int num)
 {
     int i;
 
+    if (!ehci->dma) {
+        ehci_raise_irq(ehci, USBSTS_HSE);
+        ehci->usbcmd &= ~USBCMD_RUNSTOP;
+        trace_usb_ehci_dma_error();
+        return -1;
+    }
+
     for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
         dma_memory_read(ehci->dma, addr, buf, sizeof(*buf));
         *buf = le32_to_cpu(*buf);
     }
 
-    return 1;
+    return num;
 }
 
 /* Put an array of dwords in to main memory */
@@ -1026,12 +1030,19 @@ static inline int put_dwords(EHCIState *ehci, uint32_t addr,
 {
     int i;
 
+    if (!ehci->dma) {
+        ehci_raise_irq(ehci, USBSTS_HSE);
+        ehci->usbcmd &= ~USBCMD_RUNSTOP;
+        trace_usb_ehci_dma_error();
+        return -1;
+    }
+
     for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
         uint32_t tmp = cpu_to_le32(*buf);
         dma_memory_write(ehci->dma, addr, &tmp, sizeof(tmp));
     }
 
-    return 1;
+    return num;
 }
 
 /*
@@ -1443,8 +1454,10 @@ static int ehci_state_waitlisthead(EHCIState *ehci,  int async)
 
     /*  Find the head of the list (4.9.1.1) */
     for(i = 0; i < MAX_QH; i++) {
-        get_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &qh,
-                   sizeof(EHCIqh) >> 2);
+        if (get_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &qh,
+                       sizeof(EHCIqh) >> 2) < 0) {
+            return 0;
+        }
         ehci_trace_qh(NULL, NLPTR_GET(entry), &qh);
 
         if (qh.epchar & QH_EPCHAR_H) {
@@ -1541,8 +1554,11 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
         goto out;
     }
 
-    get_dwords(ehci, NLPTR_GET(q->qhaddr),
-               (uint32_t *) &qh, sizeof(EHCIqh) >> 2);
+    if (get_dwords(ehci, NLPTR_GET(q->qhaddr),
+                   (uint32_t *) &qh, sizeof(EHCIqh) >> 2) < 0) {
+        q = NULL;
+        goto out;
+    }
     ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &qh);
 
     /*
@@ -1631,8 +1647,10 @@ static int ehci_state_fetchitd(EHCIState *ehci, int async)
     assert(!async);
     entry = ehci_get_fetch_addr(ehci, async);
 
-    get_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &itd,
-               sizeof(EHCIitd) >> 2);
+    if (get_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &itd,
+                   sizeof(EHCIitd) >> 2) < 0) {
+        return -1;
+    }
     ehci_trace_itd(ehci, entry, &itd);
 
     if (ehci_process_itd(ehci, &itd, entry) != 0) {
@@ -1655,8 +1673,10 @@ static int ehci_state_fetchsitd(EHCIState *ehci, int async)
     assert(!async);
     entry = ehci_get_fetch_addr(ehci, async);
 
-    get_dwords(ehci, NLPTR_GET(entry), (uint32_t *)&sitd,
-               sizeof(EHCIsitd) >> 2);
+    if (get_dwords(ehci, NLPTR_GET(entry), (uint32_t *)&sitd,
+                   sizeof(EHCIsitd) >> 2) < 0) {
+        return 0;
+    }
     ehci_trace_sitd(ehci, entry, &sitd);
 
     if (!(sitd.results & SITD_RESULTS_ACTIVE)) {
@@ -1717,8 +1737,10 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
     EHCIPacket *p;
     int again = 1;
 
-    get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &qtd,
-               sizeof(EHCIqtd) >> 2);
+    if (get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &qtd,
+                   sizeof(EHCIqtd) >> 2) < 0) {
+        return 0;
+    }
     ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &qtd);
 
     p = QTAILQ_FIRST(&q->packets);
@@ -1812,8 +1834,10 @@ static int ehci_fill_queue(EHCIPacket *p)
                 goto leave;
             }
         }
-        get_dwords(q->ehci, NLPTR_GET(qtdaddr),
-                   (uint32_t *) &qtd, sizeof(EHCIqtd) >> 2);
+        if (get_dwords(q->ehci, NLPTR_GET(qtdaddr),
+                       (uint32_t *) &qtd, sizeof(EHCIqtd) >> 2) < 0) {
+            return -1;
+        }
         ehci_trace_qtd(q, NLPTR_GET(qtdaddr), &qtd);
         if (!(qtd.token & QTD_TOKEN_ACTIVE)) {
             break;
@@ -2112,8 +2136,9 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
         }
         list |= ((ehci->frindex & 0x1ff8) >> 1);
 
-        dma_memory_read(ehci->dma, list, &entry, sizeof entry);
-        entry = le32_to_cpu(entry);
+        if (get_dwords(ehci, list, &entry, 1) < 0) {
+            break;
+        }
 
         DPRINTF("PERIODIC state adv fr=%d.  [%08X] -> %08X\n",
                 ehci->frindex / 8, list, entry);
diff --git a/trace-events b/trace-events
index e1a37cc26f..35308be525 100644
--- a/trace-events
+++ b/trace-events
@@ -286,6 +286,7 @@ usb_ehci_irq(uint32_t level, uint32_t frindex, uint32_t sts, uint32_t mask) "lev
 usb_ehci_guest_bug(const char *reason) "%s"
 usb_ehci_doorbell_ring(void) ""
 usb_ehci_doorbell_ack(void) ""
+usb_ehci_dma_error(void) ""
 
 # hw/usb/hcd-uhci.c
 usb_uhci_reset(void) "=== RESET ==="

From 2cb343b442c98b45d1187f5691c45b3c114f3b04 Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Thu, 15 Nov 2012 14:14:59 +0100
Subject: [PATCH 1654/2270] usb-redir: Only add actually in flight packets to
 the in flight queue

Packets which are queued up, but not yet handed over to the device, are
*not* in flight.

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/redirect.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index be9a232059..32ae1034cc 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -342,7 +342,9 @@ static void usbredir_fill_already_in_flight_from_ep(USBRedirDevice *dev,
         if (p->combined && p != p->combined->first) {
             continue;
         }
-        packet_id_queue_add(&dev->already_in_flight, p->id);
+        if (p->state == USB_PACKET_ASYNC) {
+            packet_id_queue_add(&dev->already_in_flight, p->id);
+        }
     }
 }
 

From 618fbc951d190734bac73d86abd1a77180a83050 Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Thu, 15 Nov 2012 14:15:00 +0100
Subject: [PATCH 1655/2270] usb-redir: Set default debug level to warning

The previous default of 0 means that even errors and warnings would not
get printed, which is really not a good default.

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/redirect.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 32ae1034cc..0c95e6b05e 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1962,7 +1962,7 @@ static const VMStateDescription usbredir_vmstate = {
 
 static Property usbredir_properties[] = {
     DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
-    DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
+    DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, usbredirparser_warning),
     DEFINE_PROP_STRING("filter", USBRedirDevice, filter_str),
     DEFINE_PROP_INT32("bootindex", USBRedirDevice, bootindex, -1),
     DEFINE_PROP_END_OF_LIST(),

From 8c908fca584dbf47094b63f132bb49b82eaa3e19 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Thu, 15 Nov 2012 16:11:20 +0100
Subject: [PATCH 1656/2270] usb-host: update tracing

Now that we have separate status and length fields in USBPacket
update the completion tracepoint to log both.

Signed-off-by: Gerd Hoffmann 
---
 hw/usb/host-linux.c | 20 ++++++++++++--------
 trace-events        |  2 +-
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c
index b17e1dcb7f..e3d394fcef 100644
--- a/hw/usb/host-linux.c
+++ b/hw/usb/host-linux.c
@@ -385,10 +385,12 @@ static void async_complete(void *opaque)
             }
 
             if (aurb->urb.type == USBDEVFS_URB_TYPE_CONTROL) {
-                trace_usb_host_req_complete(s->bus_num, s->addr, p, p->status);
+                trace_usb_host_req_complete(s->bus_num, s->addr, p,
+                                            p->status, aurb->urb.actual_length);
                 usb_generic_async_ctrl_complete(&s->dev, p);
             } else if (!aurb->more) {
-                trace_usb_host_req_complete(s->bus_num, s->addr, p, p->status);
+                trace_usb_host_req_complete(s->bus_num, s->addr, p,
+                                            p->status, aurb->urb.actual_length);
                 usb_packet_complete(&s->dev, p);
             }
         }
@@ -863,8 +865,9 @@ static void usb_host_handle_data(USBDevice *dev, USBPacket *p)
                             p->ep->nr, p->iov.size);
 
     if (!is_valid(s, p->pid, p->ep->nr)) {
-        trace_usb_host_req_complete(s->bus_num, s->addr, p, USB_RET_NAK);
         p->status = USB_RET_NAK;
+        trace_usb_host_req_complete(s->bus_num, s->addr, p,
+                                    p->status, p->actual_length);
         return;
     }
 
@@ -879,8 +882,9 @@ static void usb_host_handle_data(USBDevice *dev, USBPacket *p)
         ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &arg);
         if (ret < 0) {
             perror("USBDEVFS_CLEAR_HALT");
-            trace_usb_host_req_complete(s->bus_num, s->addr, p, USB_RET_NAK);
             p->status = USB_RET_NAK;
+            trace_usb_host_req_complete(s->bus_num, s->addr, p,
+                                        p->status, p->actual_length);
             return;
         }
         clear_halt(s, p->pid, p->ep->nr);
@@ -936,15 +940,15 @@ static void usb_host_handle_data(USBDevice *dev, USBPacket *p)
 
             switch(errno) {
             case ETIMEDOUT:
-                trace_usb_host_req_complete(s->bus_num, s->addr, p,
-                                            USB_RET_NAK);
                 p->status = USB_RET_NAK;
+                trace_usb_host_req_complete(s->bus_num, s->addr, p,
+                                            p->status, p->actual_length);
                 break;
             case EPIPE:
             default:
-                trace_usb_host_req_complete(s->bus_num, s->addr, p,
-                                            USB_RET_STALL);
                 p->status = USB_RET_STALL;
+                trace_usb_host_req_complete(s->bus_num, s->addr, p,
+                                            p->status, p->actual_length);
             }
             return;
         }
diff --git a/trace-events b/trace-events
index 35308be525..6c6cbf10fd 100644
--- a/trace-events
+++ b/trace-events
@@ -409,7 +409,7 @@ usb_host_claim_interfaces(int bus, int addr, int config, int nif) "dev %d:%d, co
 usb_host_release_interfaces(int bus, int addr) "dev %d:%d"
 usb_host_req_control(int bus, int addr, void *p, int req, int value, int index) "dev %d:%d, packet %p, req 0x%x, value %d, index %d"
 usb_host_req_data(int bus, int addr, void *p, int in, int ep, int size) "dev %d:%d, packet %p, in %d, ep %d, size %d"
-usb_host_req_complete(int bus, int addr, void *p, int status) "dev %d:%d, packet %p, status %d"
+usb_host_req_complete(int bus, int addr, void *p, int status, int length) "dev %d:%d, packet %p, status %d, length %d"
 usb_host_req_emulated(int bus, int addr, void *p, int status) "dev %d:%d, packet %p, status %d"
 usb_host_req_canceled(int bus, int addr, void *p) "dev %d:%d, packet %p"
 usb_host_urb_submit(int bus, int addr, void *aurb, int length, int more) "dev %d:%d, aurb %p, length %d, more %d"

From 71e0aa3930e7ac2e039b175ffad222e3dc5b1813 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Thu, 15 Nov 2012 16:11:49 +0100
Subject: [PATCH 1657/2270] usb-host: fix splitted transfers

USBPacket->actual_length wasn't updated correctly for USBPackets
splitted into multiple urbs.  Fix it.

Signed-off-by: Gerd Hoffmann 
---
 hw/usb/host-linux.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c
index e3d394fcef..aa77b7704d 100644
--- a/hw/usb/host-linux.c
+++ b/hw/usb/host-linux.c
@@ -366,8 +366,11 @@ static void async_complete(void *opaque)
         if (p) {
             switch (aurb->urb.status) {
             case 0:
-                p->actual_length = aurb->urb.actual_length;
-                p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
+                p->actual_length += aurb->urb.actual_length;
+                if (!aurb->more) {
+                    /* Clear previous ASYNC status */
+                    p->status = USB_RET_SUCCESS;
+                }
                 break;
 
             case -EPIPE:

From 81dee729c1a8fccaab8cd978721acca0282f43c9 Mon Sep 17 00:00:00 2001
From: "Daniel P. Berrange" 
Date: Fri, 2 Nov 2012 12:00:53 +0000
Subject: [PATCH 1658/2270] Avoid all systemtap reserved words

Over time various systemtap reserved words have been blacklisted
in the trace backend generator. The list is not complete though,
so there is continued risk of problems in the future. Preempt
such problems by specifying the full list of systemtap keywords
listed in its parser as identified here:

  http://sourceware.org/ml/systemtap/2012-q4/msg00157.html

Signed-off-by: Daniel P. Berrange 
Signed-off-by: Stefan Hajnoczi 
---
 scripts/tracetool/backend/dtrace.py | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/scripts/tracetool/backend/dtrace.py b/scripts/tracetool/backend/dtrace.py
index 6be7047018..23c43e2772 100644
--- a/scripts/tracetool/backend/dtrace.py
+++ b/scripts/tracetool/backend/dtrace.py
@@ -73,6 +73,15 @@ def d(events):
         '};')
 
 
+# Technically 'self' is not used by systemtap yet, but
+# they recommended we keep it in the reserved list anyway
+RESERVED_WORDS = (
+    'break', 'catch', 'continue', 'delete', 'else', 'for',
+    'foreach', 'function', 'global', 'if', 'in', 'limit',
+    'long', 'next', 'probe', 'return', 'self', 'string',
+    'try', 'while'
+    )
+
 def stap(events):
     for e in events:
         # Define prototype for probe arguments
@@ -87,7 +96,7 @@ def stap(events):
         if len(e.args) > 0:
             for name in e.args.names():
                 # Append underscore to reserved keywords
-                if name in ('limit', 'in', 'next', 'self', 'function'):
+                if name in RESERVED_WORDS:
                     name += '_'
                 out('  %s = $arg%d;' % (name, i))
                 i += 1

From ddde8acc989d9e59b37605d438d5cb6b5ce8fbae Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Fri, 26 Oct 2012 13:46:34 +0200
Subject: [PATCH 1659/2270] trace: allow disabling events in events file

Disable trace events prefixed with a '-'.  Useful
to enable a group of tracepoints with exceptions,
like this:

  usb_xhci_port_*
  -usb_xhci_port_read

which will enable all xhci port tracepoints except reads.

Signed-off-by: Gerd Hoffmann 
Signed-off-by: Stefan Hajnoczi 
---
 trace/control.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/trace/control.c b/trace/control.c
index 22d5863eeb..be05efb99b 100644
--- a/trace/control.c
+++ b/trace/control.c
@@ -12,6 +12,8 @@
 
 void trace_backend_init_events(const char *fname)
 {
+    int ret;
+
     if (fname == NULL) {
         return;
     }
@@ -30,7 +32,12 @@ void trace_backend_init_events(const char *fname)
             if ('#' == line_buf[0]) { /* skip commented lines */
                 continue;
             }
-            if (!trace_event_set_state(line_buf, true)) {
+            if ('-' == line_buf[0]) {
+                ret = trace_event_set_state(line_buf+1, false);
+            } else {
+                ret = trace_event_set_state(line_buf, true);
+            }
+            if (!ret) {
                 fprintf(stderr,
                         "error: trace event '%s' does not exist\n", line_buf);
                 exit(1);

From 8f5a0fb1f4e3167b893e3a4272446e2cf1568058 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi 
Date: Mon, 5 Nov 2012 08:48:29 +0100
Subject: [PATCH 1660/2270] trace: document '-' syntax for disabling events

Signed-off-by: Stefan Hajnoczi 
---
 docs/tracing.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/docs/tracing.txt b/docs/tracing.txt
index c541133368..79014093db 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -139,6 +139,10 @@ having a common prefix in a batch. For example, virtio-blk trace events could
 be enabled using:
   trace-event virtio_blk_* on
 
+If a line in the "-trace events=" file begins with a '-', the trace event
+will be disabled instead of enabled.  This is useful when a wildcard was used
+to enable an entire family of events but one noisy event needs to be disabled.
+
 == Trace backends ==
 
 The "tracetool" script automates tedious trace event code generation and also

From e94c4c9287392e9c4de5e9cc3a0fa40da959ccb5 Mon Sep 17 00:00:00 2001
From: Liming Wang 
Date: Fri, 16 Nov 2012 15:10:49 +0800
Subject: [PATCH 1661/2270] trace: Remove "info trace" from documents

commit 88affa1c monitor: remove unused do_info_trace

has removed "info trace" function from monitor, so remove it from documents.

Signed-off-by: Liming Wang 
Signed-off-by: Stefan Hajnoczi 
---
 docs/tracing.txt | 9 ---------
 hmp-commands.hx  | 7 -------
 2 files changed, 16 deletions(-)

diff --git a/docs/tracing.txt b/docs/tracing.txt
index 79014093db..453cc4a63d 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -189,15 +189,6 @@ records the char* pointer value instead of the string that is pointed to.
 
 ==== Monitor commands ====
 
-* info trace
-  Display the contents of trace buffer.  This command dumps the trace buffer
-  with simple formatting.  For full pretty-printing, use the simpletrace.py
-  script on a binary trace file.
-
-  The trace buffer is written into until full.  The full trace buffer is
-  flushed and emptied.  This means the 'info trace' will display few or no
-  entries if the buffer has just been flushed.
-
 * trace-file on|off|flush|set 
   Enable/disable/flush the trace file or set the trace file name.
 
diff --git a/hmp-commands.hx b/hmp-commands.hx
index b74ef75c39..010b8c9ba5 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1573,13 +1573,6 @@ show roms
 @end table
 ETEXI
 
-#ifdef CONFIG_TRACE_SIMPLE
-STEXI
-@item info trace
-show contents of trace buffer
-ETEXI
-#endif
-
 STEXI
 @item info trace-events
 show available trace events and their state

From 68d98d3e42b2b291274537d1ae4092e11d321437 Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Mon, 25 Jun 2012 14:36:33 -0500
Subject: [PATCH 1662/2270] vl: add -object option to create QOM objects from
 the command line

This will create a new QOM object in the '/objects' path.  Note that properties
are set in order which allows for simple objects to be initialized entirely
with this option and then realized.

This option is roughly equivalent to -device but for things that are not
devices.

Signed-off-by: Anthony Liguori 
---
 qemu-config.c   | 10 +++++++++
 qemu-options.hx |  8 +++++++
 vl.c            | 56 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 74 insertions(+)

diff --git a/qemu-config.c b/qemu-config.c
index 3154cac10f..10d1ba4176 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -682,6 +682,15 @@ static QemuOptsList qemu_add_fd_opts = {
     },
 };
 
+static QemuOptsList qemu_object_opts = {
+    .name = "object",
+    .implied_opt_name = "qom-type",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
+    .desc = {
+        { }
+    },
+};
+
 static QemuOptsList *vm_config_groups[32] = {
     &qemu_drive_opts,
     &qemu_chardev_opts,
@@ -699,6 +708,7 @@ static QemuOptsList *vm_config_groups[32] = {
     &qemu_iscsi_opts,
     &qemu_sandbox_opts,
     &qemu_add_fd_opts,
+    &qemu_object_opts,
     NULL,
 };
 
diff --git a/qemu-options.hx b/qemu-options.hx
index fe8f15c541..dd86bfee6a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2904,6 +2904,14 @@ DEF("no-kvm-irqchip", HAS_ARG, QEMU_OPTION_no_kvm_irqchip, "", QEMU_ARCH_I386)
 HXCOMM Deprecated (ignored)
 DEF("tdf", 0, QEMU_OPTION_tdf,"", QEMU_ARCH_ALL)
 
+DEF("object", HAS_ARG, QEMU_OPTION_object,
+    "-object TYPENAME[,PROP1=VALUE1,...]\n"
+    "                create an new object of type TYPENAME setting properties\n"
+    "                in the order they are specified.  Note that the 'id'\n"
+    "                property must be set.  These objects are placed in the\n"
+    "                '/objects' path.\n",
+    QEMU_ARCH_ALL)
+
 HXCOMM This is the last statement. Insert new options before this line!
 STEXI
 @end table
diff --git a/vl.c b/vl.c
index 4f03a72e58..c8e9c782d6 100644
--- a/vl.c
+++ b/vl.c
@@ -168,6 +168,7 @@ int main(int argc, char **argv)
 #include "osdep.h"
 
 #include "ui/qemu-spice.h"
+#include "qapi/string-input-visitor.h"
 
 //#define DEBUG_NET
 //#define DEBUG_SLIRP
@@ -2476,6 +2477,53 @@ static void free_and_trace(gpointer mem)
     free(mem);
 }
 
+static int object_set_property(const char *name, const char *value, void *opaque)
+{
+    Object *obj = OBJECT(opaque);
+    StringInputVisitor *siv;
+    Error *local_err = NULL;
+
+    if (strcmp(name, "qom-type") == 0 || strcmp(name, "id") == 0) {
+        return 0;
+    }
+
+    siv = string_input_visitor_new(value);
+    object_property_set(obj, string_input_get_visitor(siv), name, &local_err);
+    string_input_visitor_cleanup(siv);
+
+    if (local_err) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
+
+    return 0;
+}
+
+static int object_create(QemuOpts *opts, void *opaque)
+{
+    const char *type = qemu_opt_get(opts, "qom-type");
+    const char *id = qemu_opts_id(opts);
+    Object *obj;
+
+    g_assert(type != NULL);
+
+    if (id == NULL) {
+        qerror_report(QERR_MISSING_PARAMETER, "id");
+        return -1;
+    }
+
+    obj = object_new(type);
+    if (qemu_opt_foreach(opts, object_set_property, obj, 1) < 0) {
+        return -1;
+    }
+
+    object_property_add_child(container_get(object_get_root(), "/objects"),
+                              id, obj, NULL);
+
+    return 0;
+}
+
 int main(int argc, char **argv, char **envp)
 {
     int i;
@@ -3473,6 +3521,9 @@ int main(int argc, char **argv, char **envp)
                 exit(1);
 #endif
                 break;
+            case QEMU_OPTION_object:
+                opts = qemu_opts_parse(qemu_find_opts("object"), optarg, 1);
+                break;
             default:
                 os_parse_cmd_args(popt->index, optarg);
             }
@@ -3508,6 +3559,11 @@ int main(int argc, char **argv, char **envp)
         qemu_set_version(machine->hw_version);
     }
 
+    if (qemu_opts_foreach(qemu_find_opts("object"),
+                          object_create, NULL, 0) != 0) {
+        exit(1);
+    }
+
     /* Init CPU def lists, based on config
      * - Must be called after all the qemu_read_config_file() calls
      * - Must be called before list_cpus()

From 0e5588438d921b8686bbf455f400f727b2ff7b62 Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Mon, 25 Jun 2012 10:32:46 -0500
Subject: [PATCH 1663/2270] object: add object_property_add_bool (v2)

Signed-off-by: Anthony Liguori 
---
v1 -> v2
 - Fix whitespace (Andreas Faerber)
---
 include/qemu/object.h | 16 +++++++++++++
 qom/object.c          | 56 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/include/qemu/object.h b/include/qemu/object.h
index cc75feed66..be707f1a36 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -946,6 +946,22 @@ void object_property_add_str(Object *obj, const char *name,
                              void (*set)(Object *, const char *, struct Error **),
                              struct Error **errp);
 
+/**
+ * object_property_add_bool:
+ * @obj: the object to add a property to
+ * @name: the name of the property
+ * @get: the getter or NULL if the property is write-only.
+ * @set: the setter or NULL if the property is read-only
+ * @errp: if an error occurs, a pointer to an area to store the error
+ *
+ * Add a bool property using getters/setters.  This function will add a
+ * property of type 'bool'.
+ */
+void object_property_add_bool(Object *obj, const char *name,
+                              bool (*get)(Object *, struct Error **),
+                              void (*set)(Object *, bool, struct Error **),
+                              struct Error **errp);
+
 /**
  * object_child_foreach:
  * @obj: the object whose children will be navigated
diff --git a/qom/object.c b/qom/object.c
index e3e9242638..d7092b09d8 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1183,6 +1183,62 @@ void object_property_add_str(Object *obj, const char *name,
                         prop, errp);
 }
 
+typedef struct BoolProperty
+{
+    bool (*get)(Object *, Error **);
+    void (*set)(Object *, bool, Error **);
+} BoolProperty;
+
+static void property_get_bool(Object *obj, Visitor *v, void *opaque,
+                              const char *name, Error **errp)
+{
+    BoolProperty *prop = opaque;
+    bool value;
+
+    value = prop->get(obj, errp);
+    visit_type_bool(v, &value, name, errp);
+}
+
+static void property_set_bool(Object *obj, Visitor *v, void *opaque,
+                              const char *name, Error **errp)
+{
+    BoolProperty *prop = opaque;
+    bool value;
+    Error *local_err = NULL;
+
+    visit_type_bool(v, &value, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    prop->set(obj, value, errp);
+}
+
+static void property_release_bool(Object *obj, const char *name,
+                                  void *opaque)
+{
+    BoolProperty *prop = opaque;
+    g_free(prop);
+}
+
+void object_property_add_bool(Object *obj, const char *name,
+                              bool (*get)(Object *, Error **),
+                              void (*set)(Object *, bool, Error **),
+                              Error **errp)
+{
+    BoolProperty *prop = g_malloc0(sizeof(*prop));
+
+    prop->get = get;
+    prop->set = set;
+
+    object_property_add(obj, name, "bool",
+                        get ? property_get_bool : NULL,
+                        set ? property_set_bool : NULL,
+                        property_release_bool,
+                        prop, errp);
+}
+
 static char *qdev_get_type(Object *obj, Error **errp)
 {
     return g_strdup(object_get_typename(obj));

From a9b7b2ad7b075dba5495271706670e5c6b1304bc Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Mon, 25 Jun 2012 10:03:47 -0500
Subject: [PATCH 1664/2270] rng: add RndBackend abstract object class

This is the backend used by devices that need to request entropy.

Signed-off-by: Anthony Liguori 
---
 Makefile.objs          |  2 +
 backends/Makefile.objs |  1 +
 backends/rng.c         | 93 ++++++++++++++++++++++++++++++++++++++++++
 include/qemu/rng.h     | 93 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 189 insertions(+)
 create mode 100644 backends/Makefile.objs
 create mode 100644 backends/rng.c
 create mode 100644 include/qemu/rng.h

diff --git a/Makefile.objs b/Makefile.objs
index 37be7e26f7..dc1e699914 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -100,6 +100,8 @@ common-obj-y += vl.o
 
 common-obj-$(CONFIG_SLIRP) += slirp/
 
+common-obj-y += backends/
+
 ######################################################################
 # libseccomp
 ifeq ($(CONFIG_SECCOMP),y)
diff --git a/backends/Makefile.objs b/backends/Makefile.objs
new file mode 100644
index 0000000000..06e08c782d
--- /dev/null
+++ b/backends/Makefile.objs
@@ -0,0 +1 @@
+common-obj-y += rng.o
diff --git a/backends/rng.c b/backends/rng.c
new file mode 100644
index 0000000000..06f261180c
--- /dev/null
+++ b/backends/rng.c
@@ -0,0 +1,93 @@
+/*
+ * QEMU Random Number Generator Backend
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Anthony Liguori   
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/rng.h"
+#include "qerror.h"
+
+void rng_backend_request_entropy(RngBackend *s, size_t size,
+                                 EntropyReceiveFunc *receive_entropy,
+                                 void *opaque)
+{
+    RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
+
+    if (k->request_entropy) {
+        k->request_entropy(s, size, receive_entropy, opaque);
+    }
+}
+
+void rng_backend_cancel_requests(RngBackend *s)
+{
+    RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
+
+    if (k->cancel_requests) {
+        k->cancel_requests(s);
+    }
+}
+
+static bool rng_backend_prop_get_opened(Object *obj, Error **errp)
+{
+    RngBackend *s = RNG_BACKEND(obj);
+
+    return s->opened;
+}
+
+void rng_backend_open(RngBackend *s, Error **errp)
+{
+    object_property_set_bool(OBJECT(s), true, "opened", errp);
+}
+
+static void rng_backend_prop_set_opened(Object *obj, bool value, Error **errp)
+{
+    RngBackend *s = RNG_BACKEND(obj);
+    RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
+
+    if (value == s->opened) {
+        return;
+    }
+
+    if (!value && s->opened) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    if (k->opened) {
+        k->opened(s, errp);
+    }
+
+    if (!error_is_set(errp)) {
+        s->opened = value;
+    }
+}
+
+static void rng_backend_init(Object *obj)
+{
+    object_property_add_bool(obj, "opened",
+                             rng_backend_prop_get_opened,
+                             rng_backend_prop_set_opened,
+                             NULL);
+}
+
+static TypeInfo rng_backend_info = {
+    .name = TYPE_RNG_BACKEND,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(RngBackend),
+    .instance_init = rng_backend_init,
+    .class_size = sizeof(RngBackendClass),
+    .abstract = true,
+};
+
+static void register_types(void)
+{
+    type_register_static(&rng_backend_info);
+}
+
+type_init(register_types);
diff --git a/include/qemu/rng.h b/include/qemu/rng.h
new file mode 100644
index 0000000000..7e9d6723ff
--- /dev/null
+++ b/include/qemu/rng.h
@@ -0,0 +1,93 @@
+/*
+ * QEMU Random Number Generator Backend
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Anthony Liguori   
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_RNG_H
+#define QEMU_RNG_H
+
+#include "qemu/object.h"
+#include "qemu-common.h"
+#include "error.h"
+
+#define TYPE_RNG_BACKEND "rng-backend"
+#define RNG_BACKEND(obj) \
+    OBJECT_CHECK(RngBackend, (obj), TYPE_RNG_BACKEND)
+#define RNG_BACKEND_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(RngBackendClass, (obj), TYPE_RNG_BACKEND)
+#define RNG_BACKEND_CLASS(klass) \
+    OBJECT_CLASS_CHECK(RngBackendClass, (klass), TYPE_RNG_BACKEND)
+
+typedef struct RngBackendClass RngBackendClass;
+typedef struct RngBackend RngBackend;
+
+typedef void (EntropyReceiveFunc)(void *opaque,
+                                  const void *data,
+                                  size_t size);
+
+struct RngBackendClass
+{
+    ObjectClass parent_class;
+
+    void (*request_entropy)(RngBackend *s, size_t size,
+                            EntropyReceiveFunc *recieve_entropy, void *opaque);
+    void (*cancel_requests)(RngBackend *s);
+
+    void (*opened)(RngBackend *s, Error **errp);
+};
+
+struct RngBackend
+{
+    Object parent;
+
+    /*< protected >*/
+    bool opened;
+};
+
+/**
+ * rng_backend_request_entropy:
+ * @s: the backend to request entropy from
+ * @size: the number of bytes of data to request
+ * @receive_entropy: a function to be invoked when entropy is available
+ * @opaque: data that should be passed to @receive_entropy
+ *
+ * This function is used by the front-end to request entropy from an entropy
+ * source.  This function can be called multiple times before @receive_entropy
+ * is invoked with different values of @receive_entropy and @opaque.  The
+ * backend will queue each request and handle appropriate.
+ *
+ * The backend does not need to pass the full amount of data to @receive_entropy
+ * but will pass at a value greater than 0.
+ */
+void rng_backend_request_entropy(RngBackend *s, size_t size,
+                                 EntropyReceiveFunc *receive_entropy,
+                                 void *opaque);
+
+/**
+ * rng_backend_cancel_requests:
+ * @s: the backend to cancel all pending requests in
+ *
+ * Cancels all pending requests submitted by @rng_backend_request_entropy.  This
+ * should be used by a device during reset or in preparation for live migration
+ * to stop tracking any request.
+ */
+void rng_backend_cancel_requests(RngBackend *s);
+
+/**
+ * rng_backend_open:
+ * @s: the backend to open
+ * @errp: a pointer to return the #Error object if an error occurs.
+ *
+ * This function will open the backend if it is not already open.  Calling this
+ * function on an already opened backend will not result in an error.
+ */ 
+void rng_backend_open(RngBackend *s, Error **errp);
+
+#endif

From 5c74521d249486fa3e749dbbf6d56a70d4d7235f Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Mon, 25 Jun 2012 10:34:09 -0500
Subject: [PATCH 1665/2270] rng-random: add an RNG backend that uses
 /dev/random (v3)

The filename can be overridden but it expects a non-blocking source of entropy.
A typical invocation would be:

qemu -object rng-random,id=rng0 -device virtio-rng-pci,rng=rng0

This can also be used with /dev/urandom by using the command line:

qemu -object rng-random,filename=/dev/urandom,id=rng0 \
     -device virtio-rng-pci,rng=rng0

Signed-off-by: Anthony Liguori 
---
v1 -> v2
 - merged header split patch into this one
v2 -> v3
 - bug fix in rng-random (Paolo)
---
 backends/Makefile.objs    |   2 +-
 backends/rng-random.c     | 161 ++++++++++++++++++++++++++++++++++++++
 include/qemu/rng-random.h |  22 ++++++
 3 files changed, 184 insertions(+), 1 deletion(-)
 create mode 100644 backends/rng-random.c
 create mode 100644 include/qemu/rng-random.h

diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 06e08c782d..23ca19b320 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -1 +1 @@
-common-obj-y += rng.o
+common-obj-y += rng.o rng-random.o
diff --git a/backends/rng-random.c b/backends/rng-random.c
new file mode 100644
index 0000000000..9c9923b2ac
--- /dev/null
+++ b/backends/rng-random.c
@@ -0,0 +1,161 @@
+/*
+ * QEMU Random Number Generator Backend
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Anthony Liguori   
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/rng-random.h"
+#include "qemu/rng.h"
+#include "qerror.h"
+#include "main-loop.h"
+
+struct RndRandom
+{
+    RngBackend parent;
+
+    int fd;
+    char *filename;
+
+    EntropyReceiveFunc *receive_func;
+    void *opaque;
+    size_t size;
+};
+
+/**
+ * A simple and incomplete backend to request entropy from /dev/random.
+ *
+ * This backend exposes an additional "filename" property that can be used to
+ * set the filename to use to open the backend.
+ */
+
+static void entropy_available(void *opaque)
+{
+    RndRandom *s = RNG_RANDOM(opaque);
+    uint8_t buffer[s->size];
+    ssize_t len;
+
+    len = read(s->fd, buffer, s->size);
+    g_assert(len != -1);
+
+    s->receive_func(s->opaque, buffer, len);
+    s->receive_func = NULL;
+
+    qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+}
+
+static void rng_random_request_entropy(RngBackend *b, size_t size,
+                                        EntropyReceiveFunc *receive_entropy,
+                                        void *opaque)
+{
+    RndRandom *s = RNG_RANDOM(b);
+
+    if (s->receive_func) {
+        s->receive_func(s->opaque, NULL, 0);
+    }
+
+    s->receive_func = receive_entropy;
+    s->opaque = opaque;
+    s->size = size;
+
+    qemu_set_fd_handler(s->fd, entropy_available, NULL, s);
+}
+
+static void rng_random_opened(RngBackend *b, Error **errp)
+{
+    RndRandom *s = RNG_RANDOM(b);
+
+    if (s->filename == NULL) {
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE,
+                  "filename", "a valid filename");
+    } else {
+        s->fd = open(s->filename, O_RDONLY | O_NONBLOCK);
+
+        if (s->fd == -1) {
+            error_set(errp, QERR_OPEN_FILE_FAILED, s->filename);
+        }
+    }
+}
+
+static char *rng_random_get_filename(Object *obj, Error **errp)
+{
+    RndRandom *s = RNG_RANDOM(obj);
+
+    if (s->filename) {
+        return g_strdup(s->filename);
+    }
+
+    return NULL;
+}
+
+static void rng_random_set_filename(Object *obj, const char *filename,
+                                 Error **errp)
+{
+    RngBackend *b = RNG_BACKEND(obj);
+    RndRandom *s = RNG_RANDOM(obj);
+
+    if (b->opened) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    if (s->filename) {
+        g_free(s->filename);
+    }
+
+    s->filename = g_strdup(filename);
+}
+
+static void rng_random_init(Object *obj)
+{
+    RndRandom *s = RNG_RANDOM(obj);
+
+    object_property_add_str(obj, "filename",
+                            rng_random_get_filename,
+                            rng_random_set_filename,
+                            NULL);
+
+    s->filename = g_strdup("/dev/random");
+}
+
+static void rng_random_finalize(Object *obj)
+{
+    RndRandom *s = RNG_RANDOM(obj);
+
+    qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+
+    if (s->fd != -1) {
+        close(s->fd);
+    }
+
+    g_free(s->filename);
+}
+
+static void rng_random_class_init(ObjectClass *klass, void *data)
+{
+    RngBackendClass *rbc = RNG_BACKEND_CLASS(klass);
+
+    rbc->request_entropy = rng_random_request_entropy;
+    rbc->opened = rng_random_opened;
+}
+
+static TypeInfo rng_random_info = {
+    .name = TYPE_RNG_RANDOM,
+    .parent = TYPE_RNG_BACKEND,
+    .instance_size = sizeof(RndRandom),
+    .class_init = rng_random_class_init,
+    .instance_init = rng_random_init,
+    .instance_finalize = rng_random_finalize,
+};
+
+static void register_types(void)
+{
+    type_register_static(&rng_random_info);
+}
+
+type_init(register_types);
diff --git a/include/qemu/rng-random.h b/include/qemu/rng-random.h
new file mode 100644
index 0000000000..6249290cc4
--- /dev/null
+++ b/include/qemu/rng-random.h
@@ -0,0 +1,22 @@
+/*
+ * QEMU Random Number Generator Backend
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Anthony Liguori   
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#ifndef QEMU_RNG_RANDOM_H
+#define QEMU_RNG_RANDOM_H
+
+#include "qemu/object.h"
+
+#define TYPE_RNG_RANDOM "rng-random"
+#define RNG_RANDOM(obj) OBJECT_CHECK(RndRandom, (obj), TYPE_RNG_RANDOM)
+
+typedef struct RndRandom RndRandom;
+
+#endif

From 1da2738f5566263177d09c1b9eaf7cbeeb17e815 Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Mon, 25 Jun 2012 13:13:31 -0500
Subject: [PATCH 1666/2270] rng-egd: introduce EGD compliant RNG backend

This backend talks EGD to a CharDriverState.  A typical way to invoke this would
be:

qemu -chardev socket,host=localhost,port=1024,id=chr0 \
     -object rng-egd,chardev=chr0,id=egd0 \
     -device virtio-rng-pci,rng=egd0

Signed-off-by: Anthony Liguori 
---
 backends/Makefile.objs |   2 +-
 backends/rng-egd.c     | 215 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 216 insertions(+), 1 deletion(-)
 create mode 100644 backends/rng-egd.c

diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 23ca19b320..875eebce6a 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -1 +1 @@
-common-obj-y += rng.o rng-random.o
+common-obj-y += rng.o rng-random.o rng-egd.o
diff --git a/backends/rng-egd.c b/backends/rng-egd.c
new file mode 100644
index 0000000000..ec5835839a
--- /dev/null
+++ b/backends/rng-egd.c
@@ -0,0 +1,215 @@
+/*
+ * QEMU Random Number Generator Backend
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Anthony Liguori   
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/rng.h"
+#include "qemu-char.h"
+#include "qerror.h"
+#include "hw/qdev.h" /* just for DEFINE_PROP_CHR */
+
+#define TYPE_RNG_EGD "rng-egd"
+#define RNG_EGD(obj) OBJECT_CHECK(RngEgd, (obj), TYPE_RNG_EGD)
+
+typedef struct RngEgd
+{
+    RngBackend parent;
+
+    CharDriverState *chr;
+    char *chr_name;
+
+    GSList *requests;
+} RngEgd;
+
+typedef struct RngRequest
+{
+    EntropyReceiveFunc *receive_entropy;
+    uint8_t *data;
+    void *opaque;
+    size_t offset;
+    size_t size;
+} RngRequest;
+
+static void rng_egd_request_entropy(RngBackend *b, size_t size,
+                                    EntropyReceiveFunc *receive_entropy,
+                                    void *opaque)
+{
+    RngEgd *s = RNG_EGD(b);
+    RngRequest *req;
+
+    req = g_malloc(sizeof(*req));
+
+    req->offset = 0;
+    req->size = size;
+    req->receive_entropy = receive_entropy;
+    req->opaque = opaque;
+    req->data = g_malloc(req->size);
+
+    while (size > 0) {
+        uint8_t header[2];
+        uint8_t len = MIN(size, 255);
+
+        /* synchronous entropy request */
+        header[0] = 0x02;
+        header[1] = len;
+
+        qemu_chr_fe_write(s->chr, header, sizeof(header));
+
+        size -= len;
+    }
+
+    s->requests = g_slist_append(s->requests, req);
+}
+
+static void rng_egd_free_request(RngRequest *req)
+{
+    g_free(req->data);
+    g_free(req);
+}
+
+static int rng_egd_chr_can_read(void *opaque)
+{
+    RngEgd *s = RNG_EGD(opaque);
+    GSList *i;
+    int size = 0;
+
+    for (i = s->requests; i; i = i->next) {
+        RngRequest *req = i->data;
+        size += req->size - req->offset;
+    }
+
+    return size;
+}
+
+static void rng_egd_chr_read(void *opaque, const uint8_t *buf, int size)
+{
+    RngEgd *s = RNG_EGD(opaque);
+
+    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);
+        req->offset += len;
+        size -= len;
+
+        if (req->offset == req->size) {
+            s->requests = g_slist_remove_link(s->requests, s->requests);
+
+            req->receive_entropy(req->opaque, req->data, req->size);
+
+            rng_egd_free_request(req);
+        }
+    }
+}
+
+static void rng_egd_cancel_requests(RngBackend *b)
+{
+    RngEgd *s = RNG_EGD(b);
+
+    /* We simply delete the list of pending requests.  If there is data in the 
+     * queue waiting to be read, this is okay, because there will always be
+     * more data than we requested originally
+     */
+    g_slist_free_full(s->requests,
+                      (GDestroyNotify)rng_egd_free_request);
+    s->requests = NULL;
+}
+
+static void rng_egd_opened(RngBackend *b, Error **errp)
+{
+    RngEgd *s = RNG_EGD(b);
+
+    if (s->chr_name == NULL) {
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE,
+                  "chardev", "a valid character device");
+        return;
+    }
+
+    s->chr = qemu_chr_find(s->chr_name);
+    if (s->chr == NULL) {
+        error_set(errp, QERR_DEVICE_NOT_FOUND, s->chr_name);
+        return;
+    }
+
+    /* FIXME we should resubmit pending requests when the CDS reconnects. */
+    qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read, rng_egd_chr_read,
+                          NULL, s);
+}
+
+static void rng_egd_set_chardev(Object *obj, const char *value, Error **errp)
+{
+    RngBackend *b = RNG_BACKEND(obj);
+    RngEgd *s = RNG_EGD(b);
+
+    if (b->opened) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+    } else {
+        g_free(s->chr_name);
+        s->chr_name = g_strdup(value);
+    }
+}
+
+static char *rng_egd_get_chardev(Object *obj, Error **errp)
+{
+    RngEgd *s = RNG_EGD(obj);
+
+    if (s->chr && s->chr->label) {
+        return g_strdup(s->chr->label);
+    }
+
+    return NULL;
+}
+
+static void rng_egd_init(Object *obj)
+{
+    object_property_add_str(obj, "chardev",
+                            rng_egd_get_chardev, rng_egd_set_chardev,
+                            NULL);
+}
+
+static void rng_egd_finalize(Object *obj)
+{
+    RngEgd *s = RNG_EGD(obj);
+
+    if (s->chr) {
+        qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
+    }
+
+    g_free(s->chr_name);
+
+    g_slist_free_full(s->requests, (GDestroyNotify)rng_egd_free_request);
+    s->requests = NULL;
+}
+
+static void rng_egd_class_init(ObjectClass *klass, void *data)
+{
+    RngBackendClass *rbc = RNG_BACKEND_CLASS(klass);
+
+    rbc->request_entropy = rng_egd_request_entropy;
+    rbc->cancel_requests = rng_egd_cancel_requests;
+    rbc->opened = rng_egd_opened;
+}
+
+static TypeInfo rng_egd_info = {
+    .name = TYPE_RNG_EGD,
+    .parent = TYPE_RNG_BACKEND,
+    .instance_size = sizeof(RngEgd),
+    .class_init = rng_egd_class_init,
+    .instance_init = rng_egd_init,
+    .instance_finalize = rng_egd_finalize,
+};
+
+static void register_types(void)
+{
+    type_register_static(&rng_egd_info);
+}
+
+type_init(register_types);

From 16c915ba42b45df7a64a6908287f03bfa3764bed Mon Sep 17 00:00:00 2001
From: Amit Shah 
Date: Wed, 20 Jun 2012 12:29:32 +0530
Subject: [PATCH 1667/2270] virtio-rng: hardware random number generator device

The Linux kernel already has a virtio-rng driver, this is the device
implementation.

When the guest asks for entropy from the virtio hwrng, it puts a buffer
in the vq.  We then put entropy into that buffer, and push it back to
the guest.

Signed-off-by: Amit Shah 
Signed-off-by: Anthony Liguori 
---
aliguori: converted to new RngBackend interface
aliguori: remove entropy needed event
aliguori: fix migration
---
 hw/Makefile.objs     |   1 +
 hw/pci.h             |   1 +
 hw/s390-virtio-bus.c |  37 ++++++++
 hw/s390-virtio-bus.h |   2 +
 hw/virtio-pci.c      |  60 ++++++++++++
 hw/virtio-pci.h      |   2 +
 hw/virtio-rng.c      | 211 +++++++++++++++++++++++++++++++++++++++++++
 hw/virtio-rng.h      |  24 +++++
 hw/virtio.h          |   3 +
 9 files changed, 341 insertions(+)
 create mode 100644 hw/virtio-rng.c
 create mode 100644 hw/virtio-rng.h

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index af4ab0c735..ea46f8128e 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -1,6 +1,7 @@
 common-obj-y = usb/ ide/
 common-obj-y += loader.o
 common-obj-$(CONFIG_VIRTIO) += virtio-console.o
+common-obj-$(CONFIG_VIRTIO) += virtio-rng.o
 common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
 common-obj-y += fw_cfg.o
 common-obj-$(CONFIG_PCI) += pci.o pci_bridge.o pci_bridge_dev.o
diff --git a/hw/pci.h b/hw/pci.h
index 241c1d8905..4da0c2a4c9 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -76,6 +76,7 @@
 #define PCI_DEVICE_ID_VIRTIO_BALLOON     0x1002
 #define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
 #define PCI_DEVICE_ID_VIRTIO_SCSI        0x1004
+#define PCI_DEVICE_ID_VIRTIO_RNG         0x1005
 
 #define FMT_PCIBUS                      PRIx64
 
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 5849a964a4..e0ac2d1ec2 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -26,6 +26,7 @@
 #include "loader.h"
 #include "elf.h"
 #include "hw/virtio.h"
+#include "hw/virtio-rng.h"
 #include "hw/virtio-serial.h"
 #include "hw/virtio-net.h"
 #include "hw/sysbus.h"
@@ -206,6 +207,18 @@ static int s390_virtio_scsi_init(VirtIOS390Device *dev)
     return s390_virtio_device_init(dev, vdev);
 }
 
+static int s390_virtio_rng_init(VirtIOS390Device *dev)
+{
+    VirtIODevice *vdev;
+
+    vdev = virtio_rng_init((DeviceState *)dev, &dev->rng);
+    if (!vdev) {
+        return -1;
+    }
+
+    return s390_virtio_device_init(dev, vdev);
+}
+
 static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)
 {
     ram_addr_t token_off;
@@ -448,6 +461,29 @@ static TypeInfo s390_virtio_serial = {
     .class_init    = s390_virtio_serial_class_init,
 };
 
+static void s390_virtio_rng_initfn(Object *obj)
+{
+    VirtIOS390Device *dev = VIRTIO_S390_DEVICE(obj);
+
+    object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
+                             (Object **)&dev->rng.rng, NULL);
+}
+
+static void s390_virtio_rng_class_init(ObjectClass *klass, void *data)
+{
+    VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
+
+    k->init = s390_virtio_rng_init;
+}
+
+static TypeInfo s390_virtio_rng = {
+    .name          = "virtio-rng-s390",
+    .parent        = TYPE_VIRTIO_S390_DEVICE,
+    .instance_size = sizeof(VirtIOS390Device),
+    .instance_init = s390_virtio_rng_initfn,
+    .class_init    = s390_virtio_rng_class_init,
+};
+
 static int s390_virtio_busdev_init(DeviceState *dev)
 {
     VirtIOS390Device *_dev = (VirtIOS390Device *)dev;
@@ -528,6 +564,7 @@ static void s390_virtio_register_types(void)
     type_register_static(&s390_virtio_blk);
     type_register_static(&s390_virtio_net);
     type_register_static(&s390_virtio_scsi);
+    type_register_static(&s390_virtio_rng);
     type_register_static(&s390_virtio_bridge_info);
 }
 
diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h
index 4873134ae9..a83afe785f 100644
--- a/hw/s390-virtio-bus.h
+++ b/hw/s390-virtio-bus.h
@@ -19,6 +19,7 @@
 
 #include "virtio-blk.h"
 #include "virtio-net.h"
+#include "virtio-rng.h"
 #include "virtio-serial.h"
 #include "virtio-scsi.h"
 
@@ -75,6 +76,7 @@ struct VirtIOS390Device {
     virtio_serial_conf serial;
     virtio_net_conf net;
     VirtIOSCSIConf scsi;
+    VirtIORNGConf rng;
 };
 
 typedef struct VirtIOS390Bus {
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 96031500ee..a3d4777e8d 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -852,6 +852,28 @@ static void virtio_balloon_exit_pci(PCIDevice *pci_dev)
     virtio_exit_pci(pci_dev);
 }
 
+static int virtio_rng_init_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+    VirtIODevice *vdev;
+
+    vdev = virtio_rng_init(&pci_dev->qdev, &proxy->rng);
+    if (!vdev) {
+        return -1;
+    }
+    virtio_init_pci(proxy, vdev);
+    return 0;
+}
+
+static void virtio_rng_exit_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+
+    virtio_pci_stop_ioeventfd(proxy);
+    virtio_rng_exit(proxy->vdev);
+    virtio_exit_pci(pci_dev);
+}
+
 static Property virtio_blk_properties[] = {
     DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
     DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, blk.conf),
@@ -982,6 +1004,43 @@ static TypeInfo virtio_balloon_info = {
     .class_init    = virtio_balloon_class_init,
 };
 
+static void virtio_rng_initfn(Object *obj)
+{
+    PCIDevice *pci_dev = PCI_DEVICE(obj);
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+
+    object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
+                             (Object **)&proxy->rng.rng, NULL);
+}
+
+static Property virtio_rng_properties[] = {
+    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_rng_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = virtio_rng_init_pci;
+    k->exit = virtio_rng_exit_pci;
+    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    k->device_id = PCI_DEVICE_ID_VIRTIO_RNG;
+    k->revision = VIRTIO_PCI_ABI_VERSION;
+    k->class_id = PCI_CLASS_OTHERS;
+    dc->reset = virtio_pci_reset;
+    dc->props = virtio_rng_properties;
+}
+
+static TypeInfo virtio_rng_info = {
+    .name          = "virtio-rng-pci",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(VirtIOPCIProxy),
+    .instance_init = virtio_rng_initfn,
+    .class_init    = virtio_rng_class_init,
+};
+
 static int virtio_scsi_init_pci(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
@@ -1046,6 +1105,7 @@ static void virtio_pci_register_types(void)
     type_register_static(&virtio_serial_info);
     type_register_static(&virtio_balloon_info);
     type_register_static(&virtio_scsi_info);
+    type_register_static(&virtio_rng_info);
 }
 
 type_init(virtio_pci_register_types)
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index ac9d522f37..b58d9a2d19 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -17,6 +17,7 @@
 
 #include "virtio-blk.h"
 #include "virtio-net.h"
+#include "virtio-rng.h"
 #include "virtio-serial.h"
 #include "virtio-scsi.h"
 
@@ -46,6 +47,7 @@ typedef struct {
     virtio_serial_conf serial;
     virtio_net_conf net;
     VirtIOSCSIConf scsi;
+    VirtIORNGConf rng;
     bool ioeventfd_disabled;
     bool ioeventfd_started;
     VirtIOIRQFD *vector_irqfd;
diff --git a/hw/virtio-rng.c b/hw/virtio-rng.c
new file mode 100644
index 0000000000..b7fb5e9d61
--- /dev/null
+++ b/hw/virtio-rng.c
@@ -0,0 +1,211 @@
+/*
+ * A virtio device implementing a hardware random number generator.
+ *
+ * Copyright 2012 Red Hat, Inc.
+ * Copyright 2012 Amit Shah 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#include "iov.h"
+#include "qdev.h"
+#include "virtio.h"
+#include "virtio-rng.h"
+#include "qemu/rng.h"
+
+typedef struct VirtIORNG {
+    VirtIODevice vdev;
+
+    DeviceState *qdev;
+
+    /* Only one vq - guest puts buffer(s) on it when it needs entropy */
+    VirtQueue *vq;
+    VirtQueueElement elem;
+
+    /* Config data for the device -- currently only chardev */
+    VirtIORNGConf *conf;
+
+    /* Whether we've popped a vq element into 'elem' above */
+    bool popped;
+
+    RngBackend *rng;
+} VirtIORNG;
+
+static bool is_guest_ready(VirtIORNG *vrng)
+{
+    if (virtio_queue_ready(vrng->vq)
+        && (vrng->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+        return true;
+    }
+    return false;
+}
+
+static size_t pop_an_elem(VirtIORNG *vrng)
+{
+    size_t size;
+
+    if (!vrng->popped && !virtqueue_pop(vrng->vq, &vrng->elem)) {
+        return 0;
+    }
+    vrng->popped = true;
+
+    size = iov_size(vrng->elem.in_sg, vrng->elem.in_num);
+    return size;
+}
+
+/* Send data from a char device over to the guest */
+static void chr_read(void *opaque, const void *buf, size_t size)
+{
+    VirtIORNG *vrng = opaque;
+    size_t len;
+    int offset;
+
+    if (!is_guest_ready(vrng)) {
+        return;
+    }
+
+    offset = 0;
+    while (offset < size) {
+        if (!pop_an_elem(vrng)) {
+            break;
+        }
+        len = iov_from_buf(vrng->elem.in_sg, vrng->elem.in_num,
+                           0, buf + offset, size - offset);
+        offset += len;
+
+        virtqueue_push(vrng->vq, &vrng->elem, len);
+        vrng->popped = false;
+    }
+    virtio_notify(&vrng->vdev, vrng->vq);
+
+    /*
+     * Lastly, if we had multiple elems queued by the guest, and we
+     * didn't have enough data to fill them all, indicate we want more
+     * data.
+     */
+    len = pop_an_elem(vrng);
+    if (len) {
+        rng_backend_request_entropy(vrng->rng, size, chr_read, vrng);
+    }
+}
+
+static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
+{
+    VirtIORNG *vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
+    size_t size;
+
+    size = pop_an_elem(vrng);
+    if (size) {
+        rng_backend_request_entropy(vrng->rng, size, chr_read, vrng);
+    }
+}
+
+static uint32_t get_features(VirtIODevice *vdev, uint32_t f)
+{
+    return f;
+}
+
+static void virtio_rng_save(QEMUFile *f, void *opaque)
+{
+    VirtIORNG *vrng = opaque;
+
+    virtio_save(&vrng->vdev, f);
+
+    qemu_put_byte(f, vrng->popped);
+    if (vrng->popped) {
+        int i;
+
+        qemu_put_be32(f, vrng->elem.index);
+
+        qemu_put_be32(f, vrng->elem.in_num);
+        for (i = 0; i < vrng->elem.in_num; i++) {
+            qemu_put_be64(f, vrng->elem.in_addr[i]);
+        }
+
+        qemu_put_be32(f, vrng->elem.out_num);
+        for (i = 0; i < vrng->elem.out_num; i++) {
+            qemu_put_be64(f, vrng->elem.out_addr[i]);
+        }
+    }
+}
+
+static int virtio_rng_load(QEMUFile *f, void *opaque, int version_id)
+{
+    VirtIORNG *vrng = opaque;
+
+    if (version_id != 1) {
+        return -EINVAL;
+    }
+    virtio_load(&vrng->vdev, f);
+
+    vrng->popped = qemu_get_byte(f);
+    if (vrng->popped) {
+        int i;
+
+        vrng->elem.index = qemu_get_be32(f);
+
+        vrng->elem.in_num = qemu_get_be32(f);
+        g_assert(vrng->elem.in_num < VIRTQUEUE_MAX_SIZE);
+        for (i = 0; i < vrng->elem.in_num; i++) {
+            vrng->elem.in_addr[i] = qemu_get_be64(f);
+        }
+
+        vrng->elem.out_num = qemu_get_be32(f);
+        g_assert(vrng->elem.out_num < VIRTQUEUE_MAX_SIZE);
+        for (i = 0; i < vrng->elem.out_num; i++) {
+            vrng->elem.out_addr[i] = qemu_get_be64(f);
+        }
+
+        virtqueue_map_sg(vrng->elem.in_sg, vrng->elem.in_addr,
+                         vrng->elem.in_num, 1);
+        virtqueue_map_sg(vrng->elem.out_sg, vrng->elem.out_addr,
+                         vrng->elem.out_num, 0);
+    }
+    return 0;
+}
+
+VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf)
+{
+    VirtIORNG *vrng;
+    VirtIODevice *vdev;
+    Error *local_err = NULL;
+
+    vdev = virtio_common_init("virtio-rng", VIRTIO_ID_RNG, 0,
+                              sizeof(VirtIORNG));
+
+    vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
+
+    vrng->rng = conf->rng;
+    if (vrng->rng == NULL) {
+        qerror_report(QERR_INVALID_PARAMETER_VALUE, "rng", "a valid object");
+        return NULL;
+    }
+
+    rng_backend_open(vrng->rng, &local_err);
+    if (local_err) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return NULL;
+    }
+
+    vrng->vq = virtio_add_queue(vdev, 8, handle_input);
+    vrng->vdev.get_features = get_features;
+
+    vrng->qdev = dev;
+    vrng->conf = conf;
+    vrng->popped = false;
+    register_savevm(dev, "virtio-rng", -1, 1, virtio_rng_save,
+                    virtio_rng_load, vrng);
+
+    return vdev;
+}
+
+void virtio_rng_exit(VirtIODevice *vdev)
+{
+    VirtIORNG *vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
+
+    unregister_savevm(vrng->qdev, "virtio-rng", vrng);
+    virtio_cleanup(vdev);
+}
diff --git a/hw/virtio-rng.h b/hw/virtio-rng.h
new file mode 100644
index 0000000000..fbb01048ba
--- /dev/null
+++ b/hw/virtio-rng.h
@@ -0,0 +1,24 @@
+/*
+ * Virtio RNG Support
+ *
+ * Copyright Red Hat, Inc. 2012
+ * Copyright Amit Shah 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#ifndef _QEMU_VIRTIO_RNG_H
+#define _QEMU_VIRTIO_RNG_H
+
+#include "qemu/rng.h"
+
+/* The Virtio ID for the virtio rng device */
+#define VIRTIO_ID_RNG    4
+
+struct VirtIORNGConf {
+    RngBackend *rng;
+};
+
+#endif
diff --git a/hw/virtio.h b/hw/virtio.h
index ac482be24c..df8d0f7b69 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -203,6 +203,8 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *serial);
 VirtIODevice *virtio_balloon_init(DeviceState *dev);
 typedef struct VirtIOSCSIConf VirtIOSCSIConf;
 VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *conf);
+typedef struct VirtIORNGConf VirtIORNGConf;
+VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf);
 #ifdef CONFIG_LINUX
 VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
 #endif
@@ -213,6 +215,7 @@ void virtio_blk_exit(VirtIODevice *vdev);
 void virtio_serial_exit(VirtIODevice *vdev);
 void virtio_balloon_exit(VirtIODevice *vdev);
 void virtio_scsi_exit(VirtIODevice *vdev);
+void virtio_rng_exit(VirtIODevice *vdev);
 
 #define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
 	DEFINE_PROP_BIT("indirect_desc", _state, _field, \

From 904d6f588063fb5ad2b61998acdf1e73fb465067 Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Tue, 30 Oct 2012 17:45:05 -0500
Subject: [PATCH 1668/2270] virtio-rng: add rate limiting support

This adds parameters to virtio-rng-pci to allow rate limiting the entropy a
guest receives.  An example command line:

$ qemu -device virtio-rng-pci,max-bytes=1024,period=1000

Would limit entropy collection to 1Kb/s.

Signed-off-by: Anthony Liguori 
---
 hw/virtio-pci.c |  7 ++++++
 hw/virtio-rng.c | 63 ++++++++++++++++++++++++++++++++++++++++++-------
 hw/virtio-rng.h |  2 ++
 3 files changed, 64 insertions(+), 8 deletions(-)

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index a3d4777e8d..f90296d672 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -1015,6 +1015,13 @@ static void virtio_rng_initfn(Object *obj)
 
 static Property virtio_rng_properties[] = {
     DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+    /* Set a default rate limit of 2^47 bytes per minute or roughly 2TB/s.  If
+       you have an entropy source capable of generating more entropy than this
+       and you can pass it through via virtio-rng, then hats off to you.  Until
+       then, this is unlimited for all practical purposes.
+    */
+    DEFINE_PROP_UINT64("max-bytes", VirtIOPCIProxy, rng.max_bytes, INT64_MAX),
+    DEFINE_PROP_UINT32("period", VirtIOPCIProxy, rng.period_ms, 1 << 16),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/virtio-rng.c b/hw/virtio-rng.c
index b7fb5e9d61..3ca96c855f 100644
--- a/hw/virtio-rng.c
+++ b/hw/virtio-rng.c
@@ -31,6 +31,12 @@ typedef struct VirtIORNG {
     bool popped;
 
     RngBackend *rng;
+
+    /* We purposefully don't migrate this state.  The quota will reset on the
+     * destination as a result.  Rate limiting is host state, not guest state.
+     */
+    QEMUTimer *rate_limit_timer;
+    int64_t quota_remaining;
 } VirtIORNG;
 
 static bool is_guest_ready(VirtIORNG *vrng)
@@ -55,6 +61,8 @@ static size_t pop_an_elem(VirtIORNG *vrng)
     return size;
 }
 
+static void virtio_rng_process(VirtIORNG *vrng);
+
 /* Send data from a char device over to the guest */
 static void chr_read(void *opaque, const void *buf, size_t size)
 {
@@ -66,6 +74,8 @@ static void chr_read(void *opaque, const void *buf, size_t size)
         return;
     }
 
+    vrng->quota_remaining -= size;
+
     offset = 0;
     while (offset < size) {
         if (!pop_an_elem(vrng)) {
@@ -85,21 +95,30 @@ static void chr_read(void *opaque, const void *buf, size_t size)
      * didn't have enough data to fill them all, indicate we want more
      * data.
      */
-    len = pop_an_elem(vrng);
-    if (len) {
+    virtio_rng_process(vrng);
+}
+
+static void virtio_rng_process(VirtIORNG *vrng)
+{
+    ssize_t size;
+
+    if (!is_guest_ready(vrng)) {
+        return;
+    }
+
+    size = pop_an_elem(vrng);
+    size = MIN(vrng->quota_remaining, size);
+
+    if (size > 0) {
         rng_backend_request_entropy(vrng->rng, size, chr_read, vrng);
     }
 }
 
+
 static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
 {
     VirtIORNG *vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
-    size_t size;
-
-    size = pop_an_elem(vrng);
-    if (size) {
-        rng_backend_request_entropy(vrng->rng, size, chr_read, vrng);
-    }
+    virtio_rng_process(vrng);
 }
 
 static uint32_t get_features(VirtIODevice *vdev, uint32_t f)
@@ -163,9 +182,27 @@ static int virtio_rng_load(QEMUFile *f, void *opaque, int version_id)
         virtqueue_map_sg(vrng->elem.out_sg, vrng->elem.out_addr,
                          vrng->elem.out_num, 0);
     }
+
+    /* We may have an element ready but couldn't process it due to a quota
+       limit.  Make sure to try again after live migration when the quota may
+       have been reset.
+    */
+    virtio_rng_process(vrng);
+
     return 0;
 }
 
+static void check_rate_limit(void *opaque)
+{
+    VirtIORNG *s = opaque;
+
+    s->quota_remaining = s->conf->max_bytes;
+    virtio_rng_process(s);
+    qemu_mod_timer(s->rate_limit_timer,
+                   qemu_get_clock_ms(vm_clock) + s->conf->period_ms);
+}
+
+
 VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf)
 {
     VirtIORNG *vrng;
@@ -196,6 +233,16 @@ VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf)
     vrng->qdev = dev;
     vrng->conf = conf;
     vrng->popped = false;
+    vrng->quota_remaining = vrng->conf->max_bytes;
+
+    g_assert_cmpint(vrng->conf->max_bytes, <=, INT64_MAX);
+
+    vrng->rate_limit_timer = qemu_new_timer_ms(vm_clock,
+                                               check_rate_limit, vrng);
+
+    qemu_mod_timer(vrng->rate_limit_timer,
+                   qemu_get_clock_ms(vm_clock) + vrng->conf->period_ms);
+
     register_savevm(dev, "virtio-rng", -1, 1, virtio_rng_save,
                     virtio_rng_load, vrng);
 
diff --git a/hw/virtio-rng.h b/hw/virtio-rng.h
index fbb01048ba..7324d0ab57 100644
--- a/hw/virtio-rng.h
+++ b/hw/virtio-rng.h
@@ -19,6 +19,8 @@
 
 struct VirtIORNGConf {
     RngBackend *rng;
+    uint64_t max_bytes;
+    uint32_t period_ms;
 };
 
 #endif

From 500054f161c29ff9db125c0b872809191ad6920b Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Fri, 26 Oct 2012 12:05:49 -0500
Subject: [PATCH 1669/2270] virtio-rng-pci: create a default backend if none
 exists

This allows you to specify:

  $ qemu -device virtio-rng-pci

And things will Just Work with a reasonable default.

Signed-off-by: Anthony Liguori 
---
 hw/virtio-pci.c | 13 +++++++++++++
 hw/virtio-rng.h |  2 ++
 2 files changed, 15 insertions(+)

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index f90296d672..71f4fb5dc6 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -857,6 +857,19 @@ static int virtio_rng_init_pci(PCIDevice *pci_dev)
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
     VirtIODevice *vdev;
 
+    if (proxy->rng.rng == NULL) {
+        proxy->rng.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM));
+
+        object_property_add_child(OBJECT(pci_dev),
+                                  "default-backend",
+                                  OBJECT(proxy->rng.default_backend),
+                                  NULL);
+
+        object_property_set_link(OBJECT(pci_dev),
+                                 OBJECT(proxy->rng.default_backend),
+                                 "rng", NULL);
+    }
+
     vdev = virtio_rng_init(&pci_dev->qdev, &proxy->rng);
     if (!vdev) {
         return -1;
diff --git a/hw/virtio-rng.h b/hw/virtio-rng.h
index 7324d0ab57..f42d748eba 100644
--- a/hw/virtio-rng.h
+++ b/hw/virtio-rng.h
@@ -13,6 +13,7 @@
 #define _QEMU_VIRTIO_RNG_H
 
 #include "qemu/rng.h"
+#include "qemu/rng-random.h"
 
 /* The Virtio ID for the virtio rng device */
 #define VIRTIO_ID_RNG    4
@@ -21,6 +22,7 @@ struct VirtIORNGConf {
     RngBackend *rng;
     uint64_t max_bytes;
     uint32_t period_ms;
+    RndRandom *default_backend;
 };
 
 #endif

From 9cb535fe4ef08b01e583ec955767a0899ff79afe Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Fri, 16 Nov 2012 13:09:34 -0600
Subject: [PATCH 1670/2270] rng-egd: don't use gslist_free_full

This function was only introduced in glib 2.28.0.

Signed-off-by: Anthony Liguori 
---
 backends/rng-egd.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/backends/rng-egd.c b/backends/rng-egd.c
index ec5835839a..ad8473777c 100644
--- a/backends/rng-egd.c
+++ b/backends/rng-egd.c
@@ -110,6 +110,18 @@ static void rng_egd_chr_read(void *opaque, const uint8_t *buf, int size)
     }
 }
 
+static void rng_egd_free_requests(RngEgd *s)
+{
+    GSList *i;
+
+    for (i = s->requests; i; i = i->next) {
+        rng_egd_free_request(i->data);
+    }
+
+    g_slist_free(s->requests);
+    s->requests = NULL;
+}
+
 static void rng_egd_cancel_requests(RngBackend *b)
 {
     RngEgd *s = RNG_EGD(b);
@@ -118,9 +130,7 @@ static void rng_egd_cancel_requests(RngBackend *b)
      * queue waiting to be read, this is okay, because there will always be
      * more data than we requested originally
      */
-    g_slist_free_full(s->requests,
-                      (GDestroyNotify)rng_egd_free_request);
-    s->requests = NULL;
+    rng_egd_free_requests(s);
 }
 
 static void rng_egd_opened(RngBackend *b, Error **errp)
@@ -185,8 +195,7 @@ static void rng_egd_finalize(Object *obj)
 
     g_free(s->chr_name);
 
-    g_slist_free_full(s->requests, (GDestroyNotify)rng_egd_free_request);
-    s->requests = NULL;
+    rng_egd_free_requests(s);
 }
 
 static void rng_egd_class_init(ObjectClass *klass, void *data)

From 7b5eff4daa65ab8672de8c126d7757cbbeb31a08 Mon Sep 17 00:00:00 2001
From: Evgeny Voevodin 
Date: Mon, 12 Nov 2012 13:27:43 +0400
Subject: [PATCH 1671/2270] target-cris/translate.c: Code style clean-up

Signed-off-by: Evgeny Voevodin 
Reviewed-by: Richard Henderson 
Signed-off-by: Blue Swirl 
---
 target-cris/translate.c | 4798 ++++++++++++++++++++-------------------
 1 file changed, 2419 insertions(+), 2379 deletions(-)

diff --git a/target-cris/translate.c b/target-cris/translate.c
index f8ebc43a86..023980ec56 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -74,89 +74,89 @@ static TCGv env_pc;
 
 /* This is the state at translation time.  */
 typedef struct DisasContext {
-	CPUCRISState *env;
-	target_ulong pc, ppc;
+    CPUCRISState *env;
+    target_ulong pc, ppc;
 
-	/* Decoder.  */
+    /* Decoder.  */
         unsigned int (*decoder)(CPUCRISState *env, struct DisasContext *dc);
-	uint32_t ir;
-	uint32_t opcode;
-	unsigned int op1;
-	unsigned int op2;
-	unsigned int zsize, zzsize;
-	unsigned int mode;
-	unsigned int postinc;
+    uint32_t ir;
+    uint32_t opcode;
+    unsigned int op1;
+    unsigned int op2;
+    unsigned int zsize, zzsize;
+    unsigned int mode;
+    unsigned int postinc;
 
-	unsigned int size;
-	unsigned int src;
-	unsigned int dst;
-	unsigned int cond;
+    unsigned int size;
+    unsigned int src;
+    unsigned int dst;
+    unsigned int cond;
 
-	int update_cc;
-	int cc_op;
-	int cc_size;
-	uint32_t cc_mask;
+    int update_cc;
+    int cc_op;
+    int cc_size;
+    uint32_t cc_mask;
 
-	int cc_size_uptodate; /* -1 invalid or last written value.  */
+    int cc_size_uptodate; /* -1 invalid or last written value.  */
 
-	int cc_x_uptodate;  /* 1 - ccs, 2 - known | X_FLAG. 0 not uptodate.  */
-	int flags_uptodate; /* Wether or not $ccs is uptodate.  */
-	int flagx_known; /* Wether or not flags_x has the x flag known at
-			    translation time.  */
-	int flags_x;
+    int cc_x_uptodate;  /* 1 - ccs, 2 - known | X_FLAG. 0 not uptodate.  */
+    int flags_uptodate; /* Wether or not $ccs is uptodate.  */
+    int flagx_known; /* Wether or not flags_x has the x flag known at
+                translation time.  */
+    int flags_x;
 
-	int clear_x; /* Clear x after this insn?  */
-	int clear_prefix; /* Clear prefix after this insn?  */
-	int clear_locked_irq; /* Clear the irq lockout.  */
-	int cpustate_changed;
-	unsigned int tb_flags; /* tb dependent flags.  */
-	int is_jmp;
+    int clear_x; /* Clear x after this insn?  */
+    int clear_prefix; /* Clear prefix after this insn?  */
+    int clear_locked_irq; /* Clear the irq lockout.  */
+    int cpustate_changed;
+    unsigned int tb_flags; /* tb dependent flags.  */
+    int is_jmp;
 
 #define JMP_NOJMP     0
 #define JMP_DIRECT    1
 #define JMP_DIRECT_CC 2
 #define JMP_INDIRECT  3
-	int jmp; /* 0=nojmp, 1=direct, 2=indirect.  */ 
-	uint32_t jmp_pc;
+    int jmp; /* 0=nojmp, 1=direct, 2=indirect.  */
+    uint32_t jmp_pc;
 
-	int delayed_branch;
+    int delayed_branch;
 
-	struct TranslationBlock *tb;
-	int singlestep_enabled;
+    struct TranslationBlock *tb;
+    int singlestep_enabled;
 } DisasContext;
 
 static void gen_BUG(DisasContext *dc, const char *file, int line)
 {
-	printf ("BUG: pc=%x %s %d\n", dc->pc, file, line);
-	qemu_log("BUG: pc=%x %s %d\n", dc->pc, file, line);
-	cpu_abort(dc->env, "%s:%d\n", file, line);
+    printf("BUG: pc=%x %s %d\n", dc->pc, file, line);
+    qemu_log("BUG: pc=%x %s %d\n", dc->pc, file, line);
+    cpu_abort(dc->env, "%s:%d\n", file, line);
 }
 
 static const char *regnames[] =
 {
-	"$r0", "$r1", "$r2", "$r3",
-	"$r4", "$r5", "$r6", "$r7",
-	"$r8", "$r9", "$r10", "$r11",
-	"$r12", "$r13", "$sp", "$acr",
+    "$r0", "$r1", "$r2", "$r3",
+    "$r4", "$r5", "$r6", "$r7",
+    "$r8", "$r9", "$r10", "$r11",
+    "$r12", "$r13", "$sp", "$acr",
 };
 static const char *pregnames[] =
 {
-	"$bz", "$vr", "$pid", "$srs",
-	"$wz", "$exs", "$eda", "$mof",
-	"$dz", "$ebp", "$erp", "$srp",
-	"$nrp", "$ccs", "$usp", "$spc",
+    "$bz", "$vr", "$pid", "$srs",
+    "$wz", "$exs", "$eda", "$mof",
+    "$dz", "$ebp", "$erp", "$srp",
+    "$nrp", "$ccs", "$usp", "$spc",
 };
 
 /* We need this table to handle preg-moves with implicit width.  */
 static int preg_sizes[] = {
-	1, /* bz.  */
-	1, /* vr.  */
-	4, /* pid.  */
-	1, /* srs.  */
-	2, /* wz.  */
-	4, 4, 4,
-	4, 4, 4, 4,
-	4, 4, 4, 4,
+    1, /* bz.  */
+    1, /* vr.  */
+    4, /* pid.  */
+    1, /* srs.  */
+    2, /* wz.  */
+    4, 4, 4,
+    4, 4, 4, 4,
+    4, 4, 4, 4,
 };
 
 #define t_gen_mov_TN_env(tn, member) \
@@ -166,113 +166,122 @@ static int preg_sizes[] = {
 
 static inline void t_gen_mov_TN_reg(TCGv tn, int r)
 {
-	if (r < 0 || r > 15)
-		fprintf(stderr, "wrong register read $r%d\n", r);
-	tcg_gen_mov_tl(tn, cpu_R[r]);
+    if (r < 0 || r > 15) {
+        fprintf(stderr, "wrong register read $r%d\n", r);
+    }
+    tcg_gen_mov_tl(tn, cpu_R[r]);
 }
 static inline void t_gen_mov_reg_TN(int r, TCGv tn)
 {
-	if (r < 0 || r > 15)
-		fprintf(stderr, "wrong register write $r%d\n", r);
-	tcg_gen_mov_tl(cpu_R[r], tn);
+    if (r < 0 || r > 15) {
+        fprintf(stderr, "wrong register write $r%d\n", r);
+    }
+    tcg_gen_mov_tl(cpu_R[r], tn);
 }
 
 static inline void _t_gen_mov_TN_env(TCGv tn, int offset)
 {
-	if (offset > sizeof (CPUCRISState))
-		fprintf(stderr, "wrong load from env from off=%d\n", offset);
-	tcg_gen_ld_tl(tn, cpu_env, offset);
+    if (offset > sizeof(CPUCRISState)) {
+        fprintf(stderr, "wrong load from env from off=%d\n", offset);
+    }
+    tcg_gen_ld_tl(tn, cpu_env, offset);
 }
 static inline void _t_gen_mov_env_TN(int offset, TCGv tn)
 {
-	if (offset > sizeof (CPUCRISState))
-		fprintf(stderr, "wrong store to env at off=%d\n", offset);
-	tcg_gen_st_tl(tn, cpu_env, offset);
+    if (offset > sizeof(CPUCRISState)) {
+        fprintf(stderr, "wrong store to env at off=%d\n", offset);
+    }
+    tcg_gen_st_tl(tn, cpu_env, offset);
 }
 
 static inline void t_gen_mov_TN_preg(TCGv tn, int r)
 {
-	if (r < 0 || r > 15)
-		fprintf(stderr, "wrong register read $p%d\n", r);
-	if (r == PR_BZ || r == PR_WZ || r == PR_DZ)
-		tcg_gen_mov_tl(tn, tcg_const_tl(0));
-	else if (r == PR_VR)
-		tcg_gen_mov_tl(tn, tcg_const_tl(32));
-	else
-		tcg_gen_mov_tl(tn, cpu_PR[r]);
+    if (r < 0 || r > 15) {
+        fprintf(stderr, "wrong register read $p%d\n", r);
+    }
+    if (r == PR_BZ || r == PR_WZ || r == PR_DZ) {
+        tcg_gen_mov_tl(tn, tcg_const_tl(0));
+    } else if (r == PR_VR) {
+        tcg_gen_mov_tl(tn, tcg_const_tl(32));
+    } else {
+        tcg_gen_mov_tl(tn, cpu_PR[r]);
+    }
 }
 static inline void t_gen_mov_preg_TN(DisasContext *dc, int r, TCGv tn)
 {
-	if (r < 0 || r > 15)
-		fprintf(stderr, "wrong register write $p%d\n", r);
-	if (r == PR_BZ || r == PR_WZ || r == PR_DZ)
-		return;
-	else if (r == PR_SRS)
-		tcg_gen_andi_tl(cpu_PR[r], tn, 3);
-	else {
-		if (r == PR_PID) 
-                        gen_helper_tlb_flush_pid(cpu_env, tn);
-		if (dc->tb_flags & S_FLAG && r == PR_SPC) 
-                        gen_helper_spc_write(cpu_env, tn);
-		else if (r == PR_CCS)
-			dc->cpustate_changed = 1;
-		tcg_gen_mov_tl(cpu_PR[r], tn);
-	}
+    if (r < 0 || r > 15) {
+        fprintf(stderr, "wrong register write $p%d\n", r);
+    }
+    if (r == PR_BZ || r == PR_WZ || r == PR_DZ) {
+        return;
+    } else if (r == PR_SRS) {
+        tcg_gen_andi_tl(cpu_PR[r], tn, 3);
+    } else {
+        if (r == PR_PID) {
+            gen_helper_tlb_flush_pid(cpu_env, tn);
+        }
+        if (dc->tb_flags & S_FLAG && r == PR_SPC) {
+            gen_helper_spc_write(cpu_env, tn);
+        } else if (r == PR_CCS) {
+            dc->cpustate_changed = 1;
+        }
+        tcg_gen_mov_tl(cpu_PR[r], tn);
+    }
 }
 
 /* Sign extend at translation time.  */
 static int sign_extend(unsigned int val, unsigned int width)
 {
-	int sval;
+    int sval;
 
-	/* LSL.  */
-	val <<= 31 - width;
-	sval = val;
-	/* ASR.  */
-	sval >>= 31 - width;
-	return sval;
+    /* LSL.  */
+    val <<= 31 - width;
+    sval = val;
+    /* ASR.  */
+    sval >>= 31 - width;
+    return sval;
 }
 
 static int cris_fetch(CPUCRISState *env, DisasContext *dc, uint32_t addr,
-		      unsigned int size, unsigned int sign)
+              unsigned int size, unsigned int sign)
 {
-	int r;
+    int r;
 
-	switch (size) {
-		case 4:
-		{
-                        r = cpu_ldl_code(env, addr);
-			break;
-		}
-		case 2:
-		{
-			if (sign) {
-                                r = cpu_ldsw_code(env, addr);
-			} else {
-                                r = cpu_lduw_code(env, addr);
-			}
-			break;
-		}
-		case 1:
-		{
-			if (sign) {
-                                r = cpu_ldsb_code(env, addr);
-			} else {
-                                r = cpu_ldub_code(env, addr);
-			}
-			break;
-		}
-		default:
-			cpu_abort(dc->env, "Invalid fetch size %d\n", size);
-			break;
-	}
-	return r;
+    switch (size) {
+    case 4:
+    {
+        r = cpu_ldl_code(env, addr);
+        break;
+    }
+    case 2:
+    {
+        if (sign) {
+            r = cpu_ldsw_code(env, addr);
+        } else {
+            r = cpu_lduw_code(env, addr);
+        }
+        break;
+    }
+    case 1:
+    {
+        if (sign) {
+            r = cpu_ldsb_code(env, addr);
+        } else {
+            r = cpu_ldub_code(env, addr);
+        }
+        break;
+    }
+    default:
+        cpu_abort(dc->env, "Invalid fetch size %d\n", size);
+        break;
+    }
+    return r;
 }
 
 static void cris_lock_irq(DisasContext *dc)
 {
-	dc->clear_locked_irq = 0;
-	t_gen_mov_env_TN(locked_irq, tcg_const_tl(1));
+    dc->clear_locked_irq = 0;
+    t_gen_mov_env_TN(locked_irq, tcg_const_tl(1));
 }
 
 static inline void t_gen_raise_exception(uint32_t index)
@@ -284,240 +293,241 @@ static inline void t_gen_raise_exception(uint32_t index)
 
 static void t_gen_lsl(TCGv d, TCGv a, TCGv b)
 {
-	TCGv t0, t_31;
+    TCGv t0, t_31;
 
-	t0 = tcg_temp_new();
-	t_31 = tcg_const_tl(31);
-	tcg_gen_shl_tl(d, a, b);
+    t0 = tcg_temp_new();
+    t_31 = tcg_const_tl(31);
+    tcg_gen_shl_tl(d, a, b);
 
-	tcg_gen_sub_tl(t0, t_31, b);
-	tcg_gen_sar_tl(t0, t0, t_31);
-	tcg_gen_and_tl(t0, t0, d);
-	tcg_gen_xor_tl(d, d, t0);
-	tcg_temp_free(t0);
-	tcg_temp_free(t_31);
+    tcg_gen_sub_tl(t0, t_31, b);
+    tcg_gen_sar_tl(t0, t0, t_31);
+    tcg_gen_and_tl(t0, t0, d);
+    tcg_gen_xor_tl(d, d, t0);
+    tcg_temp_free(t0);
+    tcg_temp_free(t_31);
 }
 
 static void t_gen_lsr(TCGv d, TCGv a, TCGv b)
 {
-	TCGv t0, t_31;
+    TCGv t0, t_31;
 
-	t0 = tcg_temp_new();
-	t_31 = tcg_temp_new();
-	tcg_gen_shr_tl(d, a, b);
+    t0 = tcg_temp_new();
+    t_31 = tcg_temp_new();
+    tcg_gen_shr_tl(d, a, b);
 
-	tcg_gen_movi_tl(t_31, 31);
-	tcg_gen_sub_tl(t0, t_31, b);
-	tcg_gen_sar_tl(t0, t0, t_31);
-	tcg_gen_and_tl(t0, t0, d);
-	tcg_gen_xor_tl(d, d, t0);
-	tcg_temp_free(t0);
-	tcg_temp_free(t_31);
+    tcg_gen_movi_tl(t_31, 31);
+    tcg_gen_sub_tl(t0, t_31, b);
+    tcg_gen_sar_tl(t0, t0, t_31);
+    tcg_gen_and_tl(t0, t0, d);
+    tcg_gen_xor_tl(d, d, t0);
+    tcg_temp_free(t0);
+    tcg_temp_free(t_31);
 }
 
 static void t_gen_asr(TCGv d, TCGv a, TCGv b)
 {
-	TCGv t0, t_31;
+    TCGv t0, t_31;
 
-	t0 = tcg_temp_new();
-	t_31 = tcg_temp_new();
-	tcg_gen_sar_tl(d, a, b);
+    t0 = tcg_temp_new();
+    t_31 = tcg_temp_new();
+    tcg_gen_sar_tl(d, a, b);
 
-	tcg_gen_movi_tl(t_31, 31);
-	tcg_gen_sub_tl(t0, t_31, b);
-	tcg_gen_sar_tl(t0, t0, t_31);
-	tcg_gen_or_tl(d, d, t0);
-	tcg_temp_free(t0);
-	tcg_temp_free(t_31);
+    tcg_gen_movi_tl(t_31, 31);
+    tcg_gen_sub_tl(t0, t_31, b);
+    tcg_gen_sar_tl(t0, t0, t_31);
+    tcg_gen_or_tl(d, d, t0);
+    tcg_temp_free(t0);
+    tcg_temp_free(t_31);
 }
 
 /* 64-bit signed mul, lower result in d and upper in d2.  */
 static void t_gen_muls(TCGv d, TCGv d2, TCGv a, TCGv b)
 {
-	TCGv_i64 t0, t1;
+    TCGv_i64 t0, t1;
 
-	t0 = tcg_temp_new_i64();
-	t1 = tcg_temp_new_i64();
+    t0 = tcg_temp_new_i64();
+    t1 = tcg_temp_new_i64();
 
-	tcg_gen_ext_i32_i64(t0, a);
-	tcg_gen_ext_i32_i64(t1, b);
-	tcg_gen_mul_i64(t0, t0, t1);
+    tcg_gen_ext_i32_i64(t0, a);
+    tcg_gen_ext_i32_i64(t1, b);
+    tcg_gen_mul_i64(t0, t0, t1);
 
-	tcg_gen_trunc_i64_i32(d, t0);
-	tcg_gen_shri_i64(t0, t0, 32);
-	tcg_gen_trunc_i64_i32(d2, t0);
+    tcg_gen_trunc_i64_i32(d, t0);
+    tcg_gen_shri_i64(t0, t0, 32);
+    tcg_gen_trunc_i64_i32(d2, t0);
 
-	tcg_temp_free_i64(t0);
-	tcg_temp_free_i64(t1);
+    tcg_temp_free_i64(t0);
+    tcg_temp_free_i64(t1);
 }
 
 /* 64-bit unsigned muls, lower result in d and upper in d2.  */
 static void t_gen_mulu(TCGv d, TCGv d2, TCGv a, TCGv b)
 {
-	TCGv_i64 t0, t1;
+    TCGv_i64 t0, t1;
 
-	t0 = tcg_temp_new_i64();
-	t1 = tcg_temp_new_i64();
+    t0 = tcg_temp_new_i64();
+    t1 = tcg_temp_new_i64();
 
-	tcg_gen_extu_i32_i64(t0, a);
-	tcg_gen_extu_i32_i64(t1, b);
-	tcg_gen_mul_i64(t0, t0, t1);
+    tcg_gen_extu_i32_i64(t0, a);
+    tcg_gen_extu_i32_i64(t1, b);
+    tcg_gen_mul_i64(t0, t0, t1);
 
-	tcg_gen_trunc_i64_i32(d, t0);
-	tcg_gen_shri_i64(t0, t0, 32);
-	tcg_gen_trunc_i64_i32(d2, t0);
+    tcg_gen_trunc_i64_i32(d, t0);
+    tcg_gen_shri_i64(t0, t0, 32);
+    tcg_gen_trunc_i64_i32(d2, t0);
 
-	tcg_temp_free_i64(t0);
-	tcg_temp_free_i64(t1);
+    tcg_temp_free_i64(t0);
+    tcg_temp_free_i64(t1);
 }
 
 static void t_gen_cris_dstep(TCGv d, TCGv a, TCGv b)
 {
-	int l1;
+    int l1;
 
-	l1 = gen_new_label();
+    l1 = gen_new_label();
 
-	/* 
-	 * d <<= 1
-	 * if (d >= s)
-	 *    d -= s;
-	 */
-	tcg_gen_shli_tl(d, a, 1);
-	tcg_gen_brcond_tl(TCG_COND_LTU, d, b, l1);
-	tcg_gen_sub_tl(d, d, b);
-	gen_set_label(l1);
+    /*
+     * d <<= 1
+     * if (d >= s)
+     *    d -= s;
+     */
+    tcg_gen_shli_tl(d, a, 1);
+    tcg_gen_brcond_tl(TCG_COND_LTU, d, b, l1);
+    tcg_gen_sub_tl(d, d, b);
+    gen_set_label(l1);
 }
 
 static void t_gen_cris_mstep(TCGv d, TCGv a, TCGv b, TCGv ccs)
 {
-	TCGv t;
+    TCGv t;
 
-	/* 
-	 * d <<= 1
-	 * if (n)
-	 *    d += s;
-	 */
-	t = tcg_temp_new();
-	tcg_gen_shli_tl(d, a, 1);
-	tcg_gen_shli_tl(t, ccs, 31 - 3);
-	tcg_gen_sari_tl(t, t, 31);
-	tcg_gen_and_tl(t, t, b);
-	tcg_gen_add_tl(d, d, t);
-	tcg_temp_free(t);
+    /*
+     * d <<= 1
+     * if (n)
+     *    d += s;
+     */
+    t = tcg_temp_new();
+    tcg_gen_shli_tl(d, a, 1);
+    tcg_gen_shli_tl(t, ccs, 31 - 3);
+    tcg_gen_sari_tl(t, t, 31);
+    tcg_gen_and_tl(t, t, b);
+    tcg_gen_add_tl(d, d, t);
+    tcg_temp_free(t);
 }
 
 /* Extended arithmetics on CRIS.  */
 static inline void t_gen_add_flag(TCGv d, int flag)
 {
-	TCGv c;
+    TCGv c;
 
-	c = tcg_temp_new();
-	t_gen_mov_TN_preg(c, PR_CCS);
-	/* Propagate carry into d.  */
-	tcg_gen_andi_tl(c, c, 1 << flag);
-	if (flag)
-		tcg_gen_shri_tl(c, c, flag);
-	tcg_gen_add_tl(d, d, c);
-	tcg_temp_free(c);
+    c = tcg_temp_new();
+    t_gen_mov_TN_preg(c, PR_CCS);
+    /* Propagate carry into d.  */
+    tcg_gen_andi_tl(c, c, 1 << flag);
+    if (flag) {
+        tcg_gen_shri_tl(c, c, flag);
+    }
+    tcg_gen_add_tl(d, d, c);
+    tcg_temp_free(c);
 }
 
 static inline void t_gen_addx_carry(DisasContext *dc, TCGv d)
 {
-	if (dc->flagx_known) {
-		if (dc->flags_x) {
-			TCGv c;
+    if (dc->flagx_known) {
+        if (dc->flags_x) {
+            TCGv c;
             
-			c = tcg_temp_new();
-			t_gen_mov_TN_preg(c, PR_CCS);
-			/* C flag is already at bit 0.  */
-			tcg_gen_andi_tl(c, c, C_FLAG);
-			tcg_gen_add_tl(d, d, c);
-			tcg_temp_free(c);
-		}
-	} else {
-		TCGv x, c;
+            c = tcg_temp_new();
+            t_gen_mov_TN_preg(c, PR_CCS);
+            /* C flag is already at bit 0.  */
+            tcg_gen_andi_tl(c, c, C_FLAG);
+            tcg_gen_add_tl(d, d, c);
+            tcg_temp_free(c);
+        }
+    } else {
+        TCGv x, c;
 
-		x = tcg_temp_new();
-		c = tcg_temp_new();
-		t_gen_mov_TN_preg(x, PR_CCS);
-		tcg_gen_mov_tl(c, x);
+        x = tcg_temp_new();
+        c = tcg_temp_new();
+        t_gen_mov_TN_preg(x, PR_CCS);
+        tcg_gen_mov_tl(c, x);
 
-		/* Propagate carry into d if X is set. Branch free.  */
-		tcg_gen_andi_tl(c, c, C_FLAG);
-		tcg_gen_andi_tl(x, x, X_FLAG);
-		tcg_gen_shri_tl(x, x, 4);
+        /* Propagate carry into d if X is set. Branch free.  */
+        tcg_gen_andi_tl(c, c, C_FLAG);
+        tcg_gen_andi_tl(x, x, X_FLAG);
+        tcg_gen_shri_tl(x, x, 4);
 
-		tcg_gen_and_tl(x, x, c);
-		tcg_gen_add_tl(d, d, x);        
-		tcg_temp_free(x);
-		tcg_temp_free(c);
-	}
+        tcg_gen_and_tl(x, x, c);
+        tcg_gen_add_tl(d, d, x);
+        tcg_temp_free(x);
+        tcg_temp_free(c);
+    }
 }
 
 static inline void t_gen_subx_carry(DisasContext *dc, TCGv d)
 {
-	if (dc->flagx_known) {
-		if (dc->flags_x) {
-			TCGv c;
+    if (dc->flagx_known) {
+        if (dc->flags_x) {
+            TCGv c;
             
-			c = tcg_temp_new();
-			t_gen_mov_TN_preg(c, PR_CCS);
-			/* C flag is already at bit 0.  */
-			tcg_gen_andi_tl(c, c, C_FLAG);
-			tcg_gen_sub_tl(d, d, c);
-			tcg_temp_free(c);
-		}
-	} else {
-		TCGv x, c;
+            c = tcg_temp_new();
+            t_gen_mov_TN_preg(c, PR_CCS);
+            /* C flag is already at bit 0.  */
+            tcg_gen_andi_tl(c, c, C_FLAG);
+            tcg_gen_sub_tl(d, d, c);
+            tcg_temp_free(c);
+        }
+    } else {
+        TCGv x, c;
 
-		x = tcg_temp_new();
-		c = tcg_temp_new();
-		t_gen_mov_TN_preg(x, PR_CCS);
-		tcg_gen_mov_tl(c, x);
+        x = tcg_temp_new();
+        c = tcg_temp_new();
+        t_gen_mov_TN_preg(x, PR_CCS);
+        tcg_gen_mov_tl(c, x);
 
-		/* Propagate carry into d if X is set. Branch free.  */
-		tcg_gen_andi_tl(c, c, C_FLAG);
-		tcg_gen_andi_tl(x, x, X_FLAG);
-		tcg_gen_shri_tl(x, x, 4);
+        /* Propagate carry into d if X is set. Branch free.  */
+        tcg_gen_andi_tl(c, c, C_FLAG);
+        tcg_gen_andi_tl(x, x, X_FLAG);
+        tcg_gen_shri_tl(x, x, 4);
 
-		tcg_gen_and_tl(x, x, c);
-		tcg_gen_sub_tl(d, d, x);
-		tcg_temp_free(x);
-		tcg_temp_free(c);
-	}
+        tcg_gen_and_tl(x, x, c);
+        tcg_gen_sub_tl(d, d, x);
+        tcg_temp_free(x);
+        tcg_temp_free(c);
+    }
 }
 
 /* Swap the two bytes within each half word of the s operand.
    T0 = ((T0 << 8) & 0xff00ff00) | ((T0 >> 8) & 0x00ff00ff)  */
 static inline void t_gen_swapb(TCGv d, TCGv s)
 {
-	TCGv t, org_s;
+    TCGv t, org_s;
 
-	t = tcg_temp_new();
-	org_s = tcg_temp_new();
+    t = tcg_temp_new();
+    org_s = tcg_temp_new();
 
-	/* d and s may refer to the same object.  */
-	tcg_gen_mov_tl(org_s, s);
-	tcg_gen_shli_tl(t, org_s, 8);
-	tcg_gen_andi_tl(d, t, 0xff00ff00);
-	tcg_gen_shri_tl(t, org_s, 8);
-	tcg_gen_andi_tl(t, t, 0x00ff00ff);
-	tcg_gen_or_tl(d, d, t);
-	tcg_temp_free(t);
-	tcg_temp_free(org_s);
+    /* d and s may refer to the same object.  */
+    tcg_gen_mov_tl(org_s, s);
+    tcg_gen_shli_tl(t, org_s, 8);
+    tcg_gen_andi_tl(d, t, 0xff00ff00);
+    tcg_gen_shri_tl(t, org_s, 8);
+    tcg_gen_andi_tl(t, t, 0x00ff00ff);
+    tcg_gen_or_tl(d, d, t);
+    tcg_temp_free(t);
+    tcg_temp_free(org_s);
 }
 
 /* Swap the halfwords of the s operand.  */
 static inline void t_gen_swapw(TCGv d, TCGv s)
 {
-	TCGv t;
-	/* d and s refer the same object.  */
-	t = tcg_temp_new();
-	tcg_gen_mov_tl(t, s);
-	tcg_gen_shli_tl(d, t, 16);
-	tcg_gen_shri_tl(t, t, 16);
-	tcg_gen_or_tl(d, d, t);
-	tcg_temp_free(t);
+    TCGv t;
+    /* d and s refer the same object.  */
+    t = tcg_temp_new();
+    tcg_gen_mov_tl(t, s);
+    tcg_gen_shli_tl(d, t, 16);
+    tcg_gen_shri_tl(t, t, 16);
+    tcg_gen_or_tl(d, d, t);
+    tcg_temp_free(t);
 }
 
 /* Reverse the within each byte.
@@ -532,607 +542,611 @@ static inline void t_gen_swapw(TCGv d, TCGv s)
  */
 static inline void t_gen_swapr(TCGv d, TCGv s)
 {
-	struct {
-		int shift; /* LSL when positive, LSR when negative.  */
-		uint32_t mask;
-	} bitrev [] = {
-		{7, 0x80808080},
-		{5, 0x40404040},
-		{3, 0x20202020},
-		{1, 0x10101010},
-		{-1, 0x08080808},
-		{-3, 0x04040404},
-		{-5, 0x02020202},
-		{-7, 0x01010101}
-	};
-	int i;
-	TCGv t, org_s;
+    struct {
+        int shift; /* LSL when positive, LSR when negative.  */
+        uint32_t mask;
+    } bitrev[] = {
+        {7, 0x80808080},
+        {5, 0x40404040},
+        {3, 0x20202020},
+        {1, 0x10101010},
+        {-1, 0x08080808},
+        {-3, 0x04040404},
+        {-5, 0x02020202},
+        {-7, 0x01010101}
+    };
+    int i;
+    TCGv t, org_s;
 
-	/* d and s refer the same object.  */
-	t = tcg_temp_new();
-	org_s = tcg_temp_new();
-	tcg_gen_mov_tl(org_s, s);
+    /* d and s refer the same object.  */
+    t = tcg_temp_new();
+    org_s = tcg_temp_new();
+    tcg_gen_mov_tl(org_s, s);
 
-	tcg_gen_shli_tl(t, org_s,  bitrev[0].shift);
-	tcg_gen_andi_tl(d, t,  bitrev[0].mask);
-	for (i = 1; i < ARRAY_SIZE(bitrev); i++) {
-		if (bitrev[i].shift >= 0) {
-			tcg_gen_shli_tl(t, org_s,  bitrev[i].shift);
-		} else {
-			tcg_gen_shri_tl(t, org_s,  -bitrev[i].shift);
-		}
-		tcg_gen_andi_tl(t, t,  bitrev[i].mask);
-		tcg_gen_or_tl(d, d, t);
-	}
-	tcg_temp_free(t);
-	tcg_temp_free(org_s);
+    tcg_gen_shli_tl(t, org_s,  bitrev[0].shift);
+    tcg_gen_andi_tl(d, t,  bitrev[0].mask);
+    for (i = 1; i < ARRAY_SIZE(bitrev); i++) {
+        if (bitrev[i].shift >= 0) {
+            tcg_gen_shli_tl(t, org_s,  bitrev[i].shift);
+        } else {
+            tcg_gen_shri_tl(t, org_s,  -bitrev[i].shift);
+        }
+        tcg_gen_andi_tl(t, t,  bitrev[i].mask);
+        tcg_gen_or_tl(d, d, t);
+    }
+    tcg_temp_free(t);
+    tcg_temp_free(org_s);
 }
 
 static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false)
 {
-	int l1;
+    int l1;
 
-	l1 = gen_new_label();
+    l1 = gen_new_label();
 
-	/* Conditional jmp.  */
-	tcg_gen_mov_tl(env_pc, pc_false);
-	tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
-	tcg_gen_mov_tl(env_pc, pc_true);
-	gen_set_label(l1);
+    /* Conditional jmp.  */
+    tcg_gen_mov_tl(env_pc, pc_false);
+    tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
+    tcg_gen_mov_tl(env_pc, pc_true);
+    gen_set_label(l1);
 }
 
 static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
 {
-	TranslationBlock *tb;
-	tb = dc->tb;
-	if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
-		tcg_gen_goto_tb(n);
-		tcg_gen_movi_tl(env_pc, dest);
+    TranslationBlock *tb;
+    tb = dc->tb;
+    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
+        tcg_gen_goto_tb(n);
+        tcg_gen_movi_tl(env_pc, dest);
                 tcg_gen_exit_tb((tcg_target_long)tb + n);
-	} else {
-		tcg_gen_movi_tl(env_pc, dest);
-		tcg_gen_exit_tb(0);
-	}
+    } else {
+        tcg_gen_movi_tl(env_pc, dest);
+        tcg_gen_exit_tb(0);
+    }
 }
 
 static inline void cris_clear_x_flag(DisasContext *dc)
 {
-	if (dc->flagx_known && dc->flags_x)
-		dc->flags_uptodate = 0;
+    if (dc->flagx_known && dc->flags_x) {
+        dc->flags_uptodate = 0;
+    }
 
-	dc->flagx_known = 1;
-	dc->flags_x = 0;
+    dc->flagx_known = 1;
+    dc->flags_x = 0;
 }
 
 static void cris_flush_cc_state(DisasContext *dc)
 {
-	if (dc->cc_size_uptodate != dc->cc_size) {
-		tcg_gen_movi_tl(cc_size, dc->cc_size);
-		dc->cc_size_uptodate = dc->cc_size;
-	}
-	tcg_gen_movi_tl(cc_op, dc->cc_op);
-	tcg_gen_movi_tl(cc_mask, dc->cc_mask);
+    if (dc->cc_size_uptodate != dc->cc_size) {
+        tcg_gen_movi_tl(cc_size, dc->cc_size);
+        dc->cc_size_uptodate = dc->cc_size;
+    }
+    tcg_gen_movi_tl(cc_op, dc->cc_op);
+    tcg_gen_movi_tl(cc_mask, dc->cc_mask);
 }
 
 static void cris_evaluate_flags(DisasContext *dc)
 {
-	if (dc->flags_uptodate)
-		return;
+    if (dc->flags_uptodate) {
+        return;
+    }
 
-	cris_flush_cc_state(dc);
+    cris_flush_cc_state(dc);
 
-	switch (dc->cc_op)
-	{
-	case CC_OP_MCP:
-                gen_helper_evaluate_flags_mcp(cpu_PR[PR_CCS], cpu_env,
-					cpu_PR[PR_CCS], cc_src,
-					cc_dest, cc_result);
-		break;
-	case CC_OP_MULS:
-                gen_helper_evaluate_flags_muls(cpu_PR[PR_CCS], cpu_env,
-					cpu_PR[PR_CCS], cc_result,
-					cpu_PR[PR_MOF]);
-		break;
-	case CC_OP_MULU:
-                gen_helper_evaluate_flags_mulu(cpu_PR[PR_CCS], cpu_env,
-					cpu_PR[PR_CCS], cc_result,
-					cpu_PR[PR_MOF]);
-		break;
-	case CC_OP_MOVE:
-	case CC_OP_AND:
-	case CC_OP_OR:
-	case CC_OP_XOR:
-	case CC_OP_ASR:
-	case CC_OP_LSR:
-	case CC_OP_LSL:
-		switch (dc->cc_size)
-		{
-		case 4:
-                        gen_helper_evaluate_flags_move_4(cpu_PR[PR_CCS],
-                                           cpu_env, cpu_PR[PR_CCS], cc_result);
-			break;
-		case 2:
-                        gen_helper_evaluate_flags_move_2(cpu_PR[PR_CCS],
-                                           cpu_env, cpu_PR[PR_CCS], cc_result);
-			break;
-		default:
-                        gen_helper_evaluate_flags(cpu_env);
-			break;
-		}
-		break;
-	case CC_OP_FLAGS:
-		/* live.  */
-		break;
-	case CC_OP_SUB:
-	case CC_OP_CMP:
-		if (dc->cc_size == 4)
-                        gen_helper_evaluate_flags_sub_4(cpu_PR[PR_CCS], cpu_env,
-				cpu_PR[PR_CCS], cc_src, cc_dest, cc_result);
-		else
-                        gen_helper_evaluate_flags(cpu_env);
-
-		break;
-	default:
-		switch (dc->cc_size)
-		{
-			case 4:
-                        gen_helper_evaluate_flags_alu_4(cpu_PR[PR_CCS], cpu_env,
-				cpu_PR[PR_CCS], cc_src, cc_dest, cc_result);
-				break;
-			default:
-                                gen_helper_evaluate_flags(cpu_env);
-				break;
-		}
-		break;
-	}
-
-	if (dc->flagx_known) {
-		if (dc->flags_x)
-			tcg_gen_ori_tl(cpu_PR[PR_CCS], 
-				       cpu_PR[PR_CCS], X_FLAG);
-		else if (dc->cc_op == CC_OP_FLAGS)
-			tcg_gen_andi_tl(cpu_PR[PR_CCS], 
-					cpu_PR[PR_CCS], ~X_FLAG);
+    switch (dc->cc_op) {
+    case CC_OP_MCP:
+        gen_helper_evaluate_flags_mcp(cpu_PR[PR_CCS], cpu_env,
+                cpu_PR[PR_CCS], cc_src,
+                cc_dest, cc_result);
+        break;
+    case CC_OP_MULS:
+        gen_helper_evaluate_flags_muls(cpu_PR[PR_CCS], cpu_env,
+                cpu_PR[PR_CCS], cc_result,
+                cpu_PR[PR_MOF]);
+        break;
+    case CC_OP_MULU:
+        gen_helper_evaluate_flags_mulu(cpu_PR[PR_CCS], cpu_env,
+                cpu_PR[PR_CCS], cc_result,
+                cpu_PR[PR_MOF]);
+        break;
+    case CC_OP_MOVE:
+    case CC_OP_AND:
+    case CC_OP_OR:
+    case CC_OP_XOR:
+    case CC_OP_ASR:
+    case CC_OP_LSR:
+    case CC_OP_LSL:
+        switch (dc->cc_size) {
+        case 4:
+            gen_helper_evaluate_flags_move_4(cpu_PR[PR_CCS],
+                    cpu_env, cpu_PR[PR_CCS], cc_result);
+            break;
+        case 2:
+            gen_helper_evaluate_flags_move_2(cpu_PR[PR_CCS],
+                    cpu_env, cpu_PR[PR_CCS], cc_result);
+            break;
+        default:
+            gen_helper_evaluate_flags(cpu_env);
+            break;
         }
-	dc->flags_uptodate = 1;
+        break;
+    case CC_OP_FLAGS:
+        /* live.  */
+        break;
+    case CC_OP_SUB:
+    case CC_OP_CMP:
+        if (dc->cc_size == 4) {
+            gen_helper_evaluate_flags_sub_4(cpu_PR[PR_CCS], cpu_env,
+                    cpu_PR[PR_CCS], cc_src, cc_dest, cc_result);
+        } else {
+            gen_helper_evaluate_flags(cpu_env);
+        }
+
+        break;
+    default:
+        switch (dc->cc_size) {
+        case 4:
+            gen_helper_evaluate_flags_alu_4(cpu_PR[PR_CCS], cpu_env,
+                    cpu_PR[PR_CCS], cc_src, cc_dest, cc_result);
+            break;
+        default:
+            gen_helper_evaluate_flags(cpu_env);
+            break;
+        }
+        break;
+    }
+
+    if (dc->flagx_known) {
+        if (dc->flags_x) {
+            tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], X_FLAG);
+        } else if (dc->cc_op == CC_OP_FLAGS) {
+            tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~X_FLAG);
+        }
+    }
+    dc->flags_uptodate = 1;
 }
 
 static void cris_cc_mask(DisasContext *dc, unsigned int mask)
 {
-	uint32_t ovl;
+    uint32_t ovl;
 
-	if (!mask) {
-		dc->update_cc = 0;
-		return;
-	}	
+    if (!mask) {
+        dc->update_cc = 0;
+        return;
+    }
 
-	/* Check if we need to evaluate the condition codes due to 
-	   CC overlaying.  */
-	ovl = (dc->cc_mask ^ mask) & ~mask;
-	if (ovl) {
-		/* TODO: optimize this case. It trigs all the time.  */
-		cris_evaluate_flags (dc);
-	}
-	dc->cc_mask = mask;
-	dc->update_cc = 1;
+    /* Check if we need to evaluate the condition codes due to
+       CC overlaying.  */
+    ovl = (dc->cc_mask ^ mask) & ~mask;
+    if (ovl) {
+        /* TODO: optimize this case. It trigs all the time.  */
+        cris_evaluate_flags(dc);
+    }
+    dc->cc_mask = mask;
+    dc->update_cc = 1;
 }
 
 static void cris_update_cc_op(DisasContext *dc, int op, int size)
 {
-	dc->cc_op = op;
-	dc->cc_size = size;
-	dc->flags_uptodate = 0;
+    dc->cc_op = op;
+    dc->cc_size = size;
+    dc->flags_uptodate = 0;
 }
 
 static inline void cris_update_cc_x(DisasContext *dc)
 {
-	/* Save the x flag state at the time of the cc snapshot.  */
-	if (dc->flagx_known) {
-		if (dc->cc_x_uptodate == (2 | dc->flags_x))
-			return;
-		tcg_gen_movi_tl(cc_x, dc->flags_x);
-		dc->cc_x_uptodate = 2 | dc->flags_x;
-	}
-	else {
-		tcg_gen_andi_tl(cc_x, cpu_PR[PR_CCS], X_FLAG);
-		dc->cc_x_uptodate = 1;
-	}
+    /* Save the x flag state at the time of the cc snapshot.  */
+    if (dc->flagx_known) {
+        if (dc->cc_x_uptodate == (2 | dc->flags_x)) {
+            return;
+        }
+        tcg_gen_movi_tl(cc_x, dc->flags_x);
+        dc->cc_x_uptodate = 2 | dc->flags_x;
+    } else {
+        tcg_gen_andi_tl(cc_x, cpu_PR[PR_CCS], X_FLAG);
+        dc->cc_x_uptodate = 1;
+    }
 }
 
 /* Update cc prior to executing ALU op. Needs source operands untouched.  */
 static void cris_pre_alu_update_cc(DisasContext *dc, int op, 
-				   TCGv dst, TCGv src, int size)
+                   TCGv dst, TCGv src, int size)
 {
-	if (dc->update_cc) {
-		cris_update_cc_op(dc, op, size);
-		tcg_gen_mov_tl(cc_src, src);
+    if (dc->update_cc) {
+        cris_update_cc_op(dc, op, size);
+        tcg_gen_mov_tl(cc_src, src);
 
-		if (op != CC_OP_MOVE
-		    && op != CC_OP_AND
-		    && op != CC_OP_OR
-		    && op != CC_OP_XOR
-		    && op != CC_OP_ASR
-		    && op != CC_OP_LSR
-		    && op != CC_OP_LSL)
-			tcg_gen_mov_tl(cc_dest, dst);
+        if (op != CC_OP_MOVE
+            && op != CC_OP_AND
+            && op != CC_OP_OR
+            && op != CC_OP_XOR
+            && op != CC_OP_ASR
+            && op != CC_OP_LSR
+            && op != CC_OP_LSL) {
+            tcg_gen_mov_tl(cc_dest, dst);
+        }
 
-		cris_update_cc_x(dc);
-	}
+        cris_update_cc_x(dc);
+    }
 }
 
 /* Update cc after executing ALU op. needs the result.  */
 static inline void cris_update_result(DisasContext *dc, TCGv res)
 {
-	if (dc->update_cc)
-		tcg_gen_mov_tl(cc_result, res);
+    if (dc->update_cc) {
+        tcg_gen_mov_tl(cc_result, res);
+    }
 }
 
 /* Returns one if the write back stage should execute.  */
 static void cris_alu_op_exec(DisasContext *dc, int op, 
-			       TCGv dst, TCGv a, TCGv b, int size)
+                   TCGv dst, TCGv a, TCGv b, int size)
 {
-	/* Emit the ALU insns.  */
-	switch (op)
-	{
-		case CC_OP_ADD:
-			tcg_gen_add_tl(dst, a, b);
-			/* Extended arithmetics.  */
-			t_gen_addx_carry(dc, dst);
-			break;
-		case CC_OP_ADDC:
-			tcg_gen_add_tl(dst, a, b);
-			t_gen_add_flag(dst, 0); /* C_FLAG.  */
-			break;
-		case CC_OP_MCP:
-			tcg_gen_add_tl(dst, a, b);
-			t_gen_add_flag(dst, 8); /* R_FLAG.  */
-			break;
-		case CC_OP_SUB:
-			tcg_gen_sub_tl(dst, a, b);
-			/* Extended arithmetics.  */
-			t_gen_subx_carry(dc, dst);
-			break;
-		case CC_OP_MOVE:
-			tcg_gen_mov_tl(dst, b);
-			break;
-		case CC_OP_OR:
-			tcg_gen_or_tl(dst, a, b);
-			break;
-		case CC_OP_AND:
-			tcg_gen_and_tl(dst, a, b);
-			break;
-		case CC_OP_XOR:
-			tcg_gen_xor_tl(dst, a, b);
-			break;
-		case CC_OP_LSL:
-			t_gen_lsl(dst, a, b);
-			break;
-		case CC_OP_LSR:
-			t_gen_lsr(dst, a, b);
-			break;
-		case CC_OP_ASR:
-			t_gen_asr(dst, a, b);
-			break;
-		case CC_OP_NEG:
-			tcg_gen_neg_tl(dst, b);
-			/* Extended arithmetics.  */
-			t_gen_subx_carry(dc, dst);
-			break;
-		case CC_OP_LZ:
-			gen_helper_lz(dst, b);
-			break;
-		case CC_OP_MULS:
-			t_gen_muls(dst, cpu_PR[PR_MOF], a, b);
-			break;
-		case CC_OP_MULU:
-			t_gen_mulu(dst, cpu_PR[PR_MOF], a, b);
-			break;
-		case CC_OP_DSTEP:
-			t_gen_cris_dstep(dst, a, b);
-			break;
-		case CC_OP_MSTEP:
-			t_gen_cris_mstep(dst, a, b, cpu_PR[PR_CCS]);
-			break;
-		case CC_OP_BOUND:
-		{
-			int l1;
-			l1 = gen_new_label();
-			tcg_gen_mov_tl(dst, a);
-			tcg_gen_brcond_tl(TCG_COND_LEU, a, b, l1);
-			tcg_gen_mov_tl(dst, b);
-			gen_set_label(l1);
-		}
-		break;
-		case CC_OP_CMP:
-			tcg_gen_sub_tl(dst, a, b);
-			/* Extended arithmetics.  */
-			t_gen_subx_carry(dc, dst);
-			break;
-		default:
-			qemu_log("illegal ALU op.\n");
-			BUG();
-			break;
-	}
+    /* Emit the ALU insns.  */
+    switch (op) {
+    case CC_OP_ADD:
+        tcg_gen_add_tl(dst, a, b);
+        /* Extended arithmetics.  */
+        t_gen_addx_carry(dc, dst);
+        break;
+    case CC_OP_ADDC:
+        tcg_gen_add_tl(dst, a, b);
+        t_gen_add_flag(dst, 0); /* C_FLAG.  */
+        break;
+    case CC_OP_MCP:
+        tcg_gen_add_tl(dst, a, b);
+        t_gen_add_flag(dst, 8); /* R_FLAG.  */
+        break;
+    case CC_OP_SUB:
+        tcg_gen_sub_tl(dst, a, b);
+        /* Extended arithmetics.  */
+        t_gen_subx_carry(dc, dst);
+        break;
+    case CC_OP_MOVE:
+        tcg_gen_mov_tl(dst, b);
+        break;
+    case CC_OP_OR:
+        tcg_gen_or_tl(dst, a, b);
+        break;
+    case CC_OP_AND:
+        tcg_gen_and_tl(dst, a, b);
+        break;
+    case CC_OP_XOR:
+        tcg_gen_xor_tl(dst, a, b);
+        break;
+    case CC_OP_LSL:
+        t_gen_lsl(dst, a, b);
+        break;
+    case CC_OP_LSR:
+        t_gen_lsr(dst, a, b);
+        break;
+    case CC_OP_ASR:
+        t_gen_asr(dst, a, b);
+        break;
+    case CC_OP_NEG:
+        tcg_gen_neg_tl(dst, b);
+        /* Extended arithmetics.  */
+        t_gen_subx_carry(dc, dst);
+        break;
+    case CC_OP_LZ:
+        gen_helper_lz(dst, b);
+        break;
+    case CC_OP_MULS:
+        t_gen_muls(dst, cpu_PR[PR_MOF], a, b);
+        break;
+    case CC_OP_MULU:
+        t_gen_mulu(dst, cpu_PR[PR_MOF], a, b);
+        break;
+    case CC_OP_DSTEP:
+        t_gen_cris_dstep(dst, a, b);
+        break;
+    case CC_OP_MSTEP:
+        t_gen_cris_mstep(dst, a, b, cpu_PR[PR_CCS]);
+        break;
+    case CC_OP_BOUND:
+    {
+        int l1;
+        l1 = gen_new_label();
+        tcg_gen_mov_tl(dst, a);
+        tcg_gen_brcond_tl(TCG_COND_LEU, a, b, l1);
+        tcg_gen_mov_tl(dst, b);
+        gen_set_label(l1);
+    }
+        break;
+    case CC_OP_CMP:
+        tcg_gen_sub_tl(dst, a, b);
+        /* Extended arithmetics.  */
+        t_gen_subx_carry(dc, dst);
+        break;
+    default:
+        qemu_log("illegal ALU op.\n");
+        BUG();
+        break;
+    }
 
-	if (size == 1)
-		tcg_gen_andi_tl(dst, dst, 0xff);
-	else if (size == 2)
-		tcg_gen_andi_tl(dst, dst, 0xffff);
+    if (size == 1) {
+        tcg_gen_andi_tl(dst, dst, 0xff);
+    } else if (size == 2) {
+        tcg_gen_andi_tl(dst, dst, 0xffff);
+    }
 }
 
 static void cris_alu(DisasContext *dc, int op,
-			       TCGv d, TCGv op_a, TCGv op_b, int size)
+                   TCGv d, TCGv op_a, TCGv op_b, int size)
 {
-	TCGv tmp;
-	int writeback;
+    TCGv tmp;
+    int writeback;
 
-	writeback = 1;
+    writeback = 1;
 
-	if (op == CC_OP_CMP) {
-		tmp = tcg_temp_new();
-		writeback = 0;
-	} else if (size == 4) {
-		tmp = d;
-		writeback = 0;
-	} else
-		tmp = tcg_temp_new();
+    if (op == CC_OP_CMP) {
+        tmp = tcg_temp_new();
+        writeback = 0;
+    } else if (size == 4) {
+        tmp = d;
+        writeback = 0;
+    } else {
+        tmp = tcg_temp_new();
+    }
 
 
-	cris_pre_alu_update_cc(dc, op, op_a, op_b, size);
-	cris_alu_op_exec(dc, op, tmp, op_a, op_b, size);
-	cris_update_result(dc, tmp);
+    cris_pre_alu_update_cc(dc, op, op_a, op_b, size);
+    cris_alu_op_exec(dc, op, tmp, op_a, op_b, size);
+    cris_update_result(dc, tmp);
 
-	/* Writeback.  */
-	if (writeback) {
-		if (size == 1)
-			tcg_gen_andi_tl(d, d, ~0xff);
-		else
-			tcg_gen_andi_tl(d, d, ~0xffff);
-		tcg_gen_or_tl(d, d, tmp);
-	}
-	if (!TCGV_EQUAL(tmp, d))
-		tcg_temp_free(tmp);
+    /* Writeback.  */
+    if (writeback) {
+        if (size == 1) {
+            tcg_gen_andi_tl(d, d, ~0xff);
+        } else {
+            tcg_gen_andi_tl(d, d, ~0xffff);
+        }
+        tcg_gen_or_tl(d, d, tmp);
+    }
+    if (!TCGV_EQUAL(tmp, d)) {
+        tcg_temp_free(tmp);
+    }
 }
 
 static int arith_cc(DisasContext *dc)
 {
-	if (dc->update_cc) {
-		switch (dc->cc_op) {
-			case CC_OP_ADDC: return 1;
-			case CC_OP_ADD: return 1;
-			case CC_OP_SUB: return 1;
-			case CC_OP_DSTEP: return 1;
-			case CC_OP_LSL: return 1;
-			case CC_OP_LSR: return 1;
-			case CC_OP_ASR: return 1;
-			case CC_OP_CMP: return 1;
-			case CC_OP_NEG: return 1;
-			case CC_OP_OR: return 1;
-			case CC_OP_AND: return 1;
-			case CC_OP_XOR: return 1;
-			case CC_OP_MULU: return 1;
-			case CC_OP_MULS: return 1;
-			default:
-				return 0;
-		}
-	}
-	return 0;
+    if (dc->update_cc) {
+        switch (dc->cc_op) {
+        case CC_OP_ADDC: return 1;
+        case CC_OP_ADD: return 1;
+        case CC_OP_SUB: return 1;
+        case CC_OP_DSTEP: return 1;
+        case CC_OP_LSL: return 1;
+        case CC_OP_LSR: return 1;
+        case CC_OP_ASR: return 1;
+        case CC_OP_CMP: return 1;
+        case CC_OP_NEG: return 1;
+        case CC_OP_OR: return 1;
+        case CC_OP_AND: return 1;
+        case CC_OP_XOR: return 1;
+        case CC_OP_MULU: return 1;
+        case CC_OP_MULS: return 1;
+        default:
+            return 0;
+        }
+    }
+    return 0;
 }
 
 static void gen_tst_cc (DisasContext *dc, TCGv cc, int cond)
 {
-	int arith_opt, move_opt;
+    int arith_opt, move_opt;
 
-	/* TODO: optimize more condition codes.  */
+    /* TODO: optimize more condition codes.  */
 
-	/*
-	 * If the flags are live, we've gotta look into the bits of CCS.
-	 * Otherwise, if we just did an arithmetic operation we try to
-	 * evaluate the condition code faster.
-	 *
-	 * When this function is done, T0 should be non-zero if the condition
-	 * code is true.
-	 */
-	arith_opt = arith_cc(dc) && !dc->flags_uptodate;
-	move_opt = (dc->cc_op == CC_OP_MOVE);
-	switch (cond) {
-		case CC_EQ:
-			if ((arith_opt || move_opt)
-			    && dc->cc_x_uptodate != (2 | X_FLAG)) {
-				tcg_gen_setcond_tl(TCG_COND_EQ, cc,
-						   cc_result, tcg_const_tl(0));
-			}
-			else {
-				cris_evaluate_flags(dc);
-				tcg_gen_andi_tl(cc, 
-						cpu_PR[PR_CCS], Z_FLAG);
-			}
-			break;
-		case CC_NE:
-			if ((arith_opt || move_opt)
-			    && dc->cc_x_uptodate != (2 | X_FLAG)) {
-				tcg_gen_mov_tl(cc, cc_result);
-	 		} else {
-				cris_evaluate_flags(dc);
-				tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
-						Z_FLAG);
-				tcg_gen_andi_tl(cc, cc, Z_FLAG);
-			}
-			break;
-		case CC_CS:
-			cris_evaluate_flags(dc);
-			tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], C_FLAG);
-			break;
-		case CC_CC:
-			cris_evaluate_flags(dc);
-			tcg_gen_xori_tl(cc, cpu_PR[PR_CCS], C_FLAG);
-			tcg_gen_andi_tl(cc, cc, C_FLAG);
-			break;
-		case CC_VS:
-			cris_evaluate_flags(dc);
-			tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], V_FLAG);
-			break;
-		case CC_VC:
-			cris_evaluate_flags(dc);
-			tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
-					V_FLAG);
-			tcg_gen_andi_tl(cc, cc, V_FLAG);
-			break;
-		case CC_PL:
-			if (arith_opt || move_opt) {
-				int bits = 31;
+    /*
+     * If the flags are live, we've gotta look into the bits of CCS.
+     * Otherwise, if we just did an arithmetic operation we try to
+     * evaluate the condition code faster.
+     *
+     * When this function is done, T0 should be non-zero if the condition
+     * code is true.
+     */
+    arith_opt = arith_cc(dc) && !dc->flags_uptodate;
+    move_opt = (dc->cc_op == CC_OP_MOVE);
+    switch (cond) {
+    case CC_EQ:
+        if ((arith_opt || move_opt)
+                && dc->cc_x_uptodate != (2 | X_FLAG)) {
+            tcg_gen_setcond_tl(TCG_COND_EQ, cc,
+                    cc_result, tcg_const_tl(0));
+        } else {
+            cris_evaluate_flags(dc);
+            tcg_gen_andi_tl(cc,
+                    cpu_PR[PR_CCS], Z_FLAG);
+        }
+        break;
+    case CC_NE:
+        if ((arith_opt || move_opt)
+                && dc->cc_x_uptodate != (2 | X_FLAG)) {
+            tcg_gen_mov_tl(cc, cc_result);
+        } else {
+            cris_evaluate_flags(dc);
+            tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
+                    Z_FLAG);
+            tcg_gen_andi_tl(cc, cc, Z_FLAG);
+        }
+        break;
+    case CC_CS:
+        cris_evaluate_flags(dc);
+        tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], C_FLAG);
+        break;
+    case CC_CC:
+        cris_evaluate_flags(dc);
+        tcg_gen_xori_tl(cc, cpu_PR[PR_CCS], C_FLAG);
+        tcg_gen_andi_tl(cc, cc, C_FLAG);
+        break;
+    case CC_VS:
+        cris_evaluate_flags(dc);
+        tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], V_FLAG);
+        break;
+    case CC_VC:
+        cris_evaluate_flags(dc);
+        tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
+                V_FLAG);
+        tcg_gen_andi_tl(cc, cc, V_FLAG);
+        break;
+    case CC_PL:
+        if (arith_opt || move_opt) {
+            int bits = 31;
 
-				if (dc->cc_size == 1)
-					bits = 7;
-				else if (dc->cc_size == 2)
-					bits = 15;	
+            if (dc->cc_size == 1) {
+                bits = 7;
+            } else if (dc->cc_size == 2) {
+                bits = 15;
+            }
 
-				tcg_gen_shri_tl(cc, cc_result, bits);
-				tcg_gen_xori_tl(cc, cc, 1);
-			} else {
-				cris_evaluate_flags(dc);
-				tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
-						N_FLAG);
-				tcg_gen_andi_tl(cc, cc, N_FLAG);
-			}
-			break;
-		case CC_MI:
-			if (arith_opt || move_opt) {
-				int bits = 31;
+            tcg_gen_shri_tl(cc, cc_result, bits);
+            tcg_gen_xori_tl(cc, cc, 1);
+        } else {
+            cris_evaluate_flags(dc);
+            tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
+                    N_FLAG);
+            tcg_gen_andi_tl(cc, cc, N_FLAG);
+        }
+        break;
+    case CC_MI:
+        if (arith_opt || move_opt) {
+            int bits = 31;
 
-				if (dc->cc_size == 1)
-					bits = 7;
-				else if (dc->cc_size == 2)
-					bits = 15;	
+            if (dc->cc_size == 1) {
+                bits = 7;
+            } else if (dc->cc_size == 2) {
+                bits = 15;
+            }
 
-				tcg_gen_shri_tl(cc, cc_result, bits);
-				tcg_gen_andi_tl(cc, cc, 1);
-			}
-			else {
-				cris_evaluate_flags(dc);
-				tcg_gen_andi_tl(cc, cpu_PR[PR_CCS],
-						N_FLAG);
-			}
-			break;
-		case CC_LS:
-			cris_evaluate_flags(dc);
-			tcg_gen_andi_tl(cc, cpu_PR[PR_CCS],
-					C_FLAG | Z_FLAG);
-			break;
-		case CC_HI:
-			cris_evaluate_flags(dc);
-			{
-				TCGv tmp;
+            tcg_gen_shri_tl(cc, cc_result, bits);
+            tcg_gen_andi_tl(cc, cc, 1);
+        } else {
+            cris_evaluate_flags(dc);
+            tcg_gen_andi_tl(cc, cpu_PR[PR_CCS],
+                    N_FLAG);
+        }
+        break;
+    case CC_LS:
+        cris_evaluate_flags(dc);
+        tcg_gen_andi_tl(cc, cpu_PR[PR_CCS],
+                C_FLAG | Z_FLAG);
+        break;
+    case CC_HI:
+        cris_evaluate_flags(dc);
+        {
+            TCGv tmp;
 
-				tmp = tcg_temp_new();
-				tcg_gen_xori_tl(tmp, cpu_PR[PR_CCS],
-						C_FLAG | Z_FLAG);
-				/* Overlay the C flag on top of the Z.  */
-				tcg_gen_shli_tl(cc, tmp, 2);
-				tcg_gen_and_tl(cc, tmp, cc);
-				tcg_gen_andi_tl(cc, cc, Z_FLAG);
+            tmp = tcg_temp_new();
+            tcg_gen_xori_tl(tmp, cpu_PR[PR_CCS],
+                    C_FLAG | Z_FLAG);
+            /* Overlay the C flag on top of the Z.  */
+            tcg_gen_shli_tl(cc, tmp, 2);
+            tcg_gen_and_tl(cc, tmp, cc);
+            tcg_gen_andi_tl(cc, cc, Z_FLAG);
 
-				tcg_temp_free(tmp);
-			}
-			break;
-		case CC_GE:
-			cris_evaluate_flags(dc);
-			/* Overlay the V flag on top of the N.  */
-			tcg_gen_shli_tl(cc, cpu_PR[PR_CCS], 2);
-			tcg_gen_xor_tl(cc,
-				       cpu_PR[PR_CCS], cc);
-			tcg_gen_andi_tl(cc, cc, N_FLAG);
-			tcg_gen_xori_tl(cc, cc, N_FLAG);
-			break;
-		case CC_LT:
-			cris_evaluate_flags(dc);
-			/* Overlay the V flag on top of the N.  */
-			tcg_gen_shli_tl(cc, cpu_PR[PR_CCS], 2);
-			tcg_gen_xor_tl(cc,
-				       cpu_PR[PR_CCS], cc);
-			tcg_gen_andi_tl(cc, cc, N_FLAG);
-			break;
-		case CC_GT:
-			cris_evaluate_flags(dc);
-			{
-				TCGv n, z;
+            tcg_temp_free(tmp);
+        }
+        break;
+    case CC_GE:
+        cris_evaluate_flags(dc);
+        /* Overlay the V flag on top of the N.  */
+        tcg_gen_shli_tl(cc, cpu_PR[PR_CCS], 2);
+        tcg_gen_xor_tl(cc,
+                cpu_PR[PR_CCS], cc);
+        tcg_gen_andi_tl(cc, cc, N_FLAG);
+        tcg_gen_xori_tl(cc, cc, N_FLAG);
+        break;
+    case CC_LT:
+        cris_evaluate_flags(dc);
+        /* Overlay the V flag on top of the N.  */
+        tcg_gen_shli_tl(cc, cpu_PR[PR_CCS], 2);
+        tcg_gen_xor_tl(cc,
+                cpu_PR[PR_CCS], cc);
+        tcg_gen_andi_tl(cc, cc, N_FLAG);
+        break;
+    case CC_GT:
+        cris_evaluate_flags(dc);
+        {
+            TCGv n, z;
 
-				n = tcg_temp_new();
-				z = tcg_temp_new();
+            n = tcg_temp_new();
+            z = tcg_temp_new();
 
-				/* To avoid a shift we overlay everything on
-				   the V flag.  */
-				tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2);
-				tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1);
-				/* invert Z.  */
-				tcg_gen_xori_tl(z, z, 2);
+            /* To avoid a shift we overlay everything on
+                   the V flag.  */
+            tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2);
+            tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1);
+            /* invert Z.  */
+            tcg_gen_xori_tl(z, z, 2);
 
-				tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]);
-				tcg_gen_xori_tl(n, n, 2);
-				tcg_gen_and_tl(cc, z, n);
-				tcg_gen_andi_tl(cc, cc, 2);
+            tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]);
+            tcg_gen_xori_tl(n, n, 2);
+            tcg_gen_and_tl(cc, z, n);
+            tcg_gen_andi_tl(cc, cc, 2);
 
-				tcg_temp_free(n);
-				tcg_temp_free(z);
-			}
-			break;
-		case CC_LE:
-			cris_evaluate_flags(dc);
-			{
-				TCGv n, z;
+            tcg_temp_free(n);
+            tcg_temp_free(z);
+        }
+        break;
+    case CC_LE:
+        cris_evaluate_flags(dc);
+        {
+            TCGv n, z;
 
-				n = tcg_temp_new();
-				z = tcg_temp_new();
+            n = tcg_temp_new();
+            z = tcg_temp_new();
 
-				/* To avoid a shift we overlay everything on
-				   the V flag.  */
-				tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2);
-				tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1);
+            /* To avoid a shift we overlay everything on
+                   the V flag.  */
+            tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2);
+            tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1);
 
-				tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]);
-				tcg_gen_or_tl(cc, z, n);
-				tcg_gen_andi_tl(cc, cc, 2);
+            tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]);
+            tcg_gen_or_tl(cc, z, n);
+            tcg_gen_andi_tl(cc, cc, 2);
 
-				tcg_temp_free(n);
-				tcg_temp_free(z);
-			}
-			break;
-		case CC_P:
-			cris_evaluate_flags(dc);
-			tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], P_FLAG);
-			break;
-		case CC_A:
-			tcg_gen_movi_tl(cc, 1);
-			break;
-		default:
-			BUG();
-			break;
-	};
+            tcg_temp_free(n);
+            tcg_temp_free(z);
+        }
+        break;
+    case CC_P:
+        cris_evaluate_flags(dc);
+        tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], P_FLAG);
+        break;
+    case CC_A:
+        tcg_gen_movi_tl(cc, 1);
+        break;
+    default:
+        BUG();
+        break;
+    };
 }
 
 static void cris_store_direct_jmp(DisasContext *dc)
 {
-	/* Store the direct jmp state into the cpu-state.  */
-	if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
-		if (dc->jmp == JMP_DIRECT) {
-			tcg_gen_movi_tl(env_btaken, 1);
-		}
-		tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
-		dc->jmp = JMP_INDIRECT;
-	}
+    /* Store the direct jmp state into the cpu-state.  */
+    if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
+        if (dc->jmp == JMP_DIRECT) {
+            tcg_gen_movi_tl(env_btaken, 1);
+        }
+        tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
+        dc->jmp = JMP_INDIRECT;
+    }
 }
 
 static void cris_prepare_cc_branch (DisasContext *dc, 
-				    int offset, int cond)
+                    int offset, int cond)
 {
-	/* This helps us re-schedule the micro-code to insns in delay-slots
-	   before the actual jump.  */
-	dc->delayed_branch = 2;
-	dc->jmp = JMP_DIRECT_CC;
-	dc->jmp_pc = dc->pc + offset;
+    /* This helps us re-schedule the micro-code to insns in delay-slots
+       before the actual jump.  */
+    dc->delayed_branch = 2;
+    dc->jmp = JMP_DIRECT_CC;
+    dc->jmp_pc = dc->pc + offset;
 
-	gen_tst_cc (dc, env_btaken, cond);
-	tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
+    gen_tst_cc(dc, env_btaken, cond);
+    tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
 }
 
 
@@ -1140,199 +1154,207 @@ static void cris_prepare_cc_branch (DisasContext *dc,
    when the dest addr is constant to allow tb chaining.  */
 static inline void cris_prepare_jmp (DisasContext *dc, unsigned int type)
 {
-	/* This helps us re-schedule the micro-code to insns in delay-slots
-	   before the actual jump.  */
-	dc->delayed_branch = 2;
-	dc->jmp = type;
-	if (type == JMP_INDIRECT) {
-		tcg_gen_movi_tl(env_btaken, 1);
-	}
+    /* This helps us re-schedule the micro-code to insns in delay-slots
+       before the actual jump.  */
+    dc->delayed_branch = 2;
+    dc->jmp = type;
+    if (type == JMP_INDIRECT) {
+        tcg_gen_movi_tl(env_btaken, 1);
+    }
 }
 
 static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr)
 {
-	int mem_index = cpu_mmu_index(dc->env);
+    int mem_index = cpu_mmu_index(dc->env);
 
-	/* If we get a fault on a delayslot we must keep the jmp state in
-	   the cpu-state to be able to re-execute the jmp.  */
-	if (dc->delayed_branch == 1)
-		cris_store_direct_jmp(dc);
+    /* If we get a fault on a delayslot we must keep the jmp state in
+       the cpu-state to be able to re-execute the jmp.  */
+    if (dc->delayed_branch == 1) {
+        cris_store_direct_jmp(dc);
+    }
 
-        tcg_gen_qemu_ld64(dst, addr, mem_index);
+    tcg_gen_qemu_ld64(dst, addr, mem_index);
 }
 
 static void gen_load(DisasContext *dc, TCGv dst, TCGv addr, 
-		     unsigned int size, int sign)
+             unsigned int size, int sign)
 {
-	int mem_index = cpu_mmu_index(dc->env);
+    int mem_index = cpu_mmu_index(dc->env);
 
-	/* If we get a fault on a delayslot we must keep the jmp state in
-	   the cpu-state to be able to re-execute the jmp.  */
-	if (dc->delayed_branch == 1)
-		cris_store_direct_jmp(dc);
+    /* If we get a fault on a delayslot we must keep the jmp state in
+       the cpu-state to be able to re-execute the jmp.  */
+    if (dc->delayed_branch == 1) {
+        cris_store_direct_jmp(dc);
+    }
 
-	if (size == 1) {
-		if (sign)
-			tcg_gen_qemu_ld8s(dst, addr, mem_index);
-		else
-			tcg_gen_qemu_ld8u(dst, addr, mem_index);
-	}
-	else if (size == 2) {
-		if (sign)
-			tcg_gen_qemu_ld16s(dst, addr, mem_index);
-		else
-			tcg_gen_qemu_ld16u(dst, addr, mem_index);
-	}
-	else if (size == 4) {
-		tcg_gen_qemu_ld32u(dst, addr, mem_index);
-	}
-	else {
-		abort();
-	}
+    if (size == 1) {
+        if (sign) {
+            tcg_gen_qemu_ld8s(dst, addr, mem_index);
+        } else {
+            tcg_gen_qemu_ld8u(dst, addr, mem_index);
+        }
+    } else if (size == 2) {
+        if (sign) {
+            tcg_gen_qemu_ld16s(dst, addr, mem_index);
+        } else {
+            tcg_gen_qemu_ld16u(dst, addr, mem_index);
+        }
+    } else if (size == 4) {
+        tcg_gen_qemu_ld32u(dst, addr, mem_index);
+    } else {
+        abort();
+    }
 }
 
 static void gen_store (DisasContext *dc, TCGv addr, TCGv val,
-		       unsigned int size)
+               unsigned int size)
 {
-	int mem_index = cpu_mmu_index(dc->env);
+    int mem_index = cpu_mmu_index(dc->env);
 
-	/* If we get a fault on a delayslot we must keep the jmp state in
-	   the cpu-state to be able to re-execute the jmp.  */
-	if (dc->delayed_branch == 1)
- 		cris_store_direct_jmp(dc);
+    /* If we get a fault on a delayslot we must keep the jmp state in
+       the cpu-state to be able to re-execute the jmp.  */
+    if (dc->delayed_branch == 1) {
+        cris_store_direct_jmp(dc);
+    }
 
 
-	/* Conditional writes. We only support the kind were X and P are known
-	   at translation time.  */
-	if (dc->flagx_known && dc->flags_x && (dc->tb_flags & P_FLAG)) {
-		dc->postinc = 0;
-		cris_evaluate_flags(dc);
-		tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], C_FLAG);
-		return;
-	}
+    /* Conditional writes. We only support the kind were X and P are known
+       at translation time.  */
+    if (dc->flagx_known && dc->flags_x && (dc->tb_flags & P_FLAG)) {
+        dc->postinc = 0;
+        cris_evaluate_flags(dc);
+        tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], C_FLAG);
+        return;
+    }
 
-	if (size == 1)
-		tcg_gen_qemu_st8(val, addr, mem_index);
-	else if (size == 2)
-		tcg_gen_qemu_st16(val, addr, mem_index);
-	else
-		tcg_gen_qemu_st32(val, addr, mem_index);
+    if (size == 1) {
+        tcg_gen_qemu_st8(val, addr, mem_index);
+    } else if (size == 2) {
+        tcg_gen_qemu_st16(val, addr, mem_index);
+    } else {
+        tcg_gen_qemu_st32(val, addr, mem_index);
+    }
 
-	if (dc->flagx_known && dc->flags_x) {
-		cris_evaluate_flags(dc);
-		tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~C_FLAG);
-	}
+    if (dc->flagx_known && dc->flags_x) {
+        cris_evaluate_flags(dc);
+        tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~C_FLAG);
+    }
 }
 
 static inline void t_gen_sext(TCGv d, TCGv s, int size)
 {
-	if (size == 1)
-		tcg_gen_ext8s_i32(d, s);
-	else if (size == 2)
-		tcg_gen_ext16s_i32(d, s);
-	else if(!TCGV_EQUAL(d, s))
-		tcg_gen_mov_tl(d, s);
+    if (size == 1) {
+        tcg_gen_ext8s_i32(d, s);
+    } else if (size == 2) {
+        tcg_gen_ext16s_i32(d, s);
+    } else if (!TCGV_EQUAL(d, s)) {
+        tcg_gen_mov_tl(d, s);
+    }
 }
 
 static inline void t_gen_zext(TCGv d, TCGv s, int size)
 {
-	if (size == 1)
-		tcg_gen_ext8u_i32(d, s);
-	else if (size == 2)
-		tcg_gen_ext16u_i32(d, s);
-	else if (!TCGV_EQUAL(d, s))
-		tcg_gen_mov_tl(d, s);
+    if (size == 1) {
+        tcg_gen_ext8u_i32(d, s);
+    } else if (size == 2) {
+        tcg_gen_ext16u_i32(d, s);
+    } else if (!TCGV_EQUAL(d, s)) {
+        tcg_gen_mov_tl(d, s);
+    }
 }
 
 #if DISAS_CRIS
 static char memsize_char(int size)
 {
-	switch (size)
-	{
-		case 1: return 'b';  break;
-		case 2: return 'w';  break;
-		case 4: return 'd';  break;
-		default:
-			return 'x';
-			break;
-	}
+    switch (size) {
+    case 1: return 'b';  break;
+    case 2: return 'w';  break;
+    case 4: return 'd';  break;
+    default:
+        return 'x';
+        break;
+    }
 }
 #endif
 
 static inline unsigned int memsize_z(DisasContext *dc)
 {
-	return dc->zsize + 1;
+    return dc->zsize + 1;
 }
 
 static inline unsigned int memsize_zz(DisasContext *dc)
 {
-	switch (dc->zzsize)
-	{
-		case 0: return 1;
-		case 1: return 2;
-		default:
-			return 4;
-	}
+    switch (dc->zzsize) {
+    case 0: return 1;
+    case 1: return 2;
+    default:
+        return 4;
+    }
 }
 
 static inline void do_postinc (DisasContext *dc, int size)
 {
-	if (dc->postinc)
-		tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], size);
+    if (dc->postinc) {
+        tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], size);
+    }
 }
 
 static inline void dec_prep_move_r(DisasContext *dc, int rs, int rd,
-				   int size, int s_ext, TCGv dst)
+                   int size, int s_ext, TCGv dst)
 {
-	if (s_ext)
-		t_gen_sext(dst, cpu_R[rs], size);
-	else
-		t_gen_zext(dst, cpu_R[rs], size);
+    if (s_ext) {
+        t_gen_sext(dst, cpu_R[rs], size);
+    } else {
+        t_gen_zext(dst, cpu_R[rs], size);
+    }
 }
 
 /* Prepare T0 and T1 for a register alu operation.
    s_ext decides if the operand1 should be sign-extended or zero-extended when
    needed.  */
 static void dec_prep_alu_r(DisasContext *dc, int rs, int rd,
-			  int size, int s_ext, TCGv dst, TCGv src)
+              int size, int s_ext, TCGv dst, TCGv src)
 {
-	dec_prep_move_r(dc, rs, rd, size, s_ext, src);
+    dec_prep_move_r(dc, rs, rd, size, s_ext, src);
 
-	if (s_ext)
-		t_gen_sext(dst, cpu_R[rd], size);
-	else
-		t_gen_zext(dst, cpu_R[rd], size);
+    if (s_ext) {
+        t_gen_sext(dst, cpu_R[rd], size);
+    } else {
+        t_gen_zext(dst, cpu_R[rd], size);
+    }
 }
 
 static int dec_prep_move_m(CPUCRISState *env, DisasContext *dc,
                            int s_ext, int memsize, TCGv dst)
 {
-	unsigned int rs;
-	uint32_t imm;
-	int is_imm;
-	int insn_len = 2;
+    unsigned int rs;
+    uint32_t imm;
+    int is_imm;
+    int insn_len = 2;
 
-	rs = dc->op1;
-	is_imm = rs == 15 && dc->postinc;
+    rs = dc->op1;
+    is_imm = rs == 15 && dc->postinc;
 
-	/* Load [$rs] onto T1.  */
-	if (is_imm) {
-		insn_len = 2 + memsize;
-		if (memsize == 1)
-			insn_len++;
+    /* Load [$rs] onto T1.  */
+    if (is_imm) {
+        insn_len = 2 + memsize;
+        if (memsize == 1) {
+            insn_len++;
+        }
 
-                imm = cris_fetch(env, dc, dc->pc + 2, memsize, s_ext);
-		tcg_gen_movi_tl(dst, imm);
-		dc->postinc = 0;
-	} else {
-		cris_flush_cc_state(dc);
-		gen_load(dc, dst, cpu_R[rs], memsize, 0);
-		if (s_ext)
-			t_gen_sext(dst, dst, memsize);
-		else
-			t_gen_zext(dst, dst, memsize);
-	}
-	return insn_len;
+        imm = cris_fetch(env, dc, dc->pc + 2, memsize, s_ext);
+        tcg_gen_movi_tl(dst, imm);
+        dc->postinc = 0;
+    } else {
+        cris_flush_cc_state(dc);
+        gen_load(dc, dst, cpu_R[rs], memsize, 0);
+        if (s_ext) {
+            t_gen_sext(dst, dst, memsize);
+        } else {
+            t_gen_zext(dst, dst, memsize);
+        }
+    }
+    return insn_len;
 }
 
 /* Prepare T0 and T1 for a memory + alu operation.
@@ -1341,22 +1363,22 @@ static int dec_prep_move_m(CPUCRISState *env, DisasContext *dc,
 static int dec_prep_alu_m(CPUCRISState *env, DisasContext *dc,
                           int s_ext, int memsize, TCGv dst, TCGv src)
 {
-	int insn_len;
+    int insn_len;
 
-        insn_len = dec_prep_move_m(env, dc, s_ext, memsize, src);
-	tcg_gen_mov_tl(dst, cpu_R[dc->op2]);
-	return insn_len;
+    insn_len = dec_prep_move_m(env, dc, s_ext, memsize, src);
+    tcg_gen_mov_tl(dst, cpu_R[dc->op2]);
+    return insn_len;
 }
 
 #if DISAS_CRIS
 static const char *cc_name(int cc)
 {
-	static const char *cc_names[16] = {
-		"cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi",
-		"ls", "hi", "ge", "lt", "gt", "le", "a", "p"
-	};
-	assert(cc < 16);
-	return cc_names[cc];
+    static const char *cc_names[16] = {
+        "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi",
+        "ls", "hi", "ge", "lt", "gt", "le", "a", "p"
+    };
+    assert(cc < 16);
+    return cc_names[cc];
 }
 #endif
 
@@ -1364,1773 +1386,1781 @@ static const char *cc_name(int cc)
 
 static int dec_bccq(CPUCRISState *env, DisasContext *dc)
 {
-	int32_t offset;
-	int sign;
-	uint32_t cond = dc->op2;
+    int32_t offset;
+    int sign;
+    uint32_t cond = dc->op2;
 
-	offset = EXTRACT_FIELD (dc->ir, 1, 7);
-	sign = EXTRACT_FIELD(dc->ir, 0, 0);
+    offset = EXTRACT_FIELD(dc->ir, 1, 7);
+    sign = EXTRACT_FIELD(dc->ir, 0, 0);
 
-	offset *= 2;
-	offset |= sign << 8;
-	offset = sign_extend(offset, 8);
+    offset *= 2;
+    offset |= sign << 8;
+    offset = sign_extend(offset, 8);
 
-	LOG_DIS("b%s %x\n", cc_name(cond), dc->pc + offset);
+    LOG_DIS("b%s %x\n", cc_name(cond), dc->pc + offset);
 
-	/* op2 holds the condition-code.  */
-	cris_cc_mask(dc, 0);
-	cris_prepare_cc_branch (dc, offset, cond);
-	return 2;
+    /* op2 holds the condition-code.  */
+    cris_cc_mask(dc, 0);
+    cris_prepare_cc_branch(dc, offset, cond);
+    return 2;
 }
 static int dec_addoq(CPUCRISState *env, DisasContext *dc)
 {
-	int32_t imm;
+    int32_t imm;
 
-	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 7);
-	imm = sign_extend(dc->op1, 7);
+    dc->op1 = EXTRACT_FIELD(dc->ir, 0, 7);
+    imm = sign_extend(dc->op1, 7);
 
-	LOG_DIS("addoq %d, $r%u\n", imm, dc->op2);
-	cris_cc_mask(dc, 0);
-	/* Fetch register operand,  */
-	tcg_gen_addi_tl(cpu_R[R_ACR], cpu_R[dc->op2], imm);
+    LOG_DIS("addoq %d, $r%u\n", imm, dc->op2);
+    cris_cc_mask(dc, 0);
+    /* Fetch register operand,  */
+    tcg_gen_addi_tl(cpu_R[R_ACR], cpu_R[dc->op2], imm);
 
-	return 2;
+    return 2;
 }
 static int dec_addq(CPUCRISState *env, DisasContext *dc)
 {
-	LOG_DIS("addq %u, $r%u\n", dc->op1, dc->op2);
+    LOG_DIS("addq %u, $r%u\n", dc->op1, dc->op2);
 
-	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
+    dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
 
-	cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_cc_mask(dc, CC_MASK_NZVC);
 
-	cris_alu(dc, CC_OP_ADD,
-		    cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
-	return 2;
+    cris_alu(dc, CC_OP_ADD,
+            cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
+    return 2;
 }
 static int dec_moveq(CPUCRISState *env, DisasContext *dc)
 {
-	uint32_t imm;
+    uint32_t imm;
 
-	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
-	imm = sign_extend(dc->op1, 5);
-	LOG_DIS("moveq %d, $r%u\n", imm, dc->op2);
+    dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
+    imm = sign_extend(dc->op1, 5);
+    LOG_DIS("moveq %d, $r%u\n", imm, dc->op2);
 
-	tcg_gen_movi_tl(cpu_R[dc->op2], imm);
-	return 2;
+    tcg_gen_movi_tl(cpu_R[dc->op2], imm);
+    return 2;
 }
 static int dec_subq(CPUCRISState *env, DisasContext *dc)
 {
-	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
+    dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
 
-	LOG_DIS("subq %u, $r%u\n", dc->op1, dc->op2);
+    LOG_DIS("subq %u, $r%u\n", dc->op1, dc->op2);
 
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	cris_alu(dc, CC_OP_SUB,
-		    cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
-	return 2;
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_alu(dc, CC_OP_SUB,
+            cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
+    return 2;
 }
 static int dec_cmpq(CPUCRISState *env, DisasContext *dc)
 {
-	uint32_t imm;
-	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
-	imm = sign_extend(dc->op1, 5);
+    uint32_t imm;
+    dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
+    imm = sign_extend(dc->op1, 5);
 
-	LOG_DIS("cmpq %d, $r%d\n", imm, dc->op2);
-	cris_cc_mask(dc, CC_MASK_NZVC);
+    LOG_DIS("cmpq %d, $r%d\n", imm, dc->op2);
+    cris_cc_mask(dc, CC_MASK_NZVC);
 
-	cris_alu(dc, CC_OP_CMP,
-		    cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
-	return 2;
+    cris_alu(dc, CC_OP_CMP,
+            cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
+    return 2;
 }
 static int dec_andq(CPUCRISState *env, DisasContext *dc)
 {
-	uint32_t imm;
-	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
-	imm = sign_extend(dc->op1, 5);
+    uint32_t imm;
+    dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
+    imm = sign_extend(dc->op1, 5);
 
-	LOG_DIS("andq %d, $r%d\n", imm, dc->op2);
-	cris_cc_mask(dc, CC_MASK_NZ);
+    LOG_DIS("andq %d, $r%d\n", imm, dc->op2);
+    cris_cc_mask(dc, CC_MASK_NZ);
 
-	cris_alu(dc, CC_OP_AND,
-		    cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
-	return 2;
+    cris_alu(dc, CC_OP_AND,
+            cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
+    return 2;
 }
 static int dec_orq(CPUCRISState *env, DisasContext *dc)
 {
-	uint32_t imm;
-	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
-	imm = sign_extend(dc->op1, 5);
-	LOG_DIS("orq %d, $r%d\n", imm, dc->op2);
-	cris_cc_mask(dc, CC_MASK_NZ);
+    uint32_t imm;
+    dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
+    imm = sign_extend(dc->op1, 5);
+    LOG_DIS("orq %d, $r%d\n", imm, dc->op2);
+    cris_cc_mask(dc, CC_MASK_NZ);
 
-	cris_alu(dc, CC_OP_OR,
-		    cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
-	return 2;
+    cris_alu(dc, CC_OP_OR,
+            cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
+    return 2;
 }
 static int dec_btstq(CPUCRISState *env, DisasContext *dc)
 {
-	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
-	LOG_DIS("btstq %u, $r%d\n", dc->op1, dc->op2);
+    dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
+    LOG_DIS("btstq %u, $r%d\n", dc->op1, dc->op2);
 
-	cris_cc_mask(dc, CC_MASK_NZ);
-	cris_evaluate_flags(dc);
+    cris_cc_mask(dc, CC_MASK_NZ);
+    cris_evaluate_flags(dc);
         gen_helper_btst(cpu_PR[PR_CCS], cpu_env, cpu_R[dc->op2],
-			tcg_const_tl(dc->op1), cpu_PR[PR_CCS]);
-	cris_alu(dc, CC_OP_MOVE,
-		 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4);
-	cris_update_cc_op(dc, CC_OP_FLAGS, 4);
-	dc->flags_uptodate = 1;
-	return 2;
+            tcg_const_tl(dc->op1), cpu_PR[PR_CCS]);
+    cris_alu(dc, CC_OP_MOVE,
+         cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4);
+    cris_update_cc_op(dc, CC_OP_FLAGS, 4);
+    dc->flags_uptodate = 1;
+    return 2;
 }
 static int dec_asrq(CPUCRISState *env, DisasContext *dc)
 {
-	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
-	LOG_DIS("asrq %u, $r%d\n", dc->op1, dc->op2);
-	cris_cc_mask(dc, CC_MASK_NZ);
+    dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
+    LOG_DIS("asrq %u, $r%d\n", dc->op1, dc->op2);
+    cris_cc_mask(dc, CC_MASK_NZ);
 
-	tcg_gen_sari_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
-	cris_alu(dc, CC_OP_MOVE,
-		    cpu_R[dc->op2],
-		    cpu_R[dc->op2], cpu_R[dc->op2], 4);
-	return 2;
+    tcg_gen_sari_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
+    cris_alu(dc, CC_OP_MOVE,
+            cpu_R[dc->op2],
+            cpu_R[dc->op2], cpu_R[dc->op2], 4);
+    return 2;
 }
 static int dec_lslq(CPUCRISState *env, DisasContext *dc)
 {
-	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
-	LOG_DIS("lslq %u, $r%d\n", dc->op1, dc->op2);
+    dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
+    LOG_DIS("lslq %u, $r%d\n", dc->op1, dc->op2);
 
-	cris_cc_mask(dc, CC_MASK_NZ);
+    cris_cc_mask(dc, CC_MASK_NZ);
 
-	tcg_gen_shli_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
+    tcg_gen_shli_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
 
-	cris_alu(dc, CC_OP_MOVE,
-		    cpu_R[dc->op2],
-		    cpu_R[dc->op2], cpu_R[dc->op2], 4);
-	return 2;
+    cris_alu(dc, CC_OP_MOVE,
+            cpu_R[dc->op2],
+            cpu_R[dc->op2], cpu_R[dc->op2], 4);
+    return 2;
 }
 static int dec_lsrq(CPUCRISState *env, DisasContext *dc)
 {
-	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
-	LOG_DIS("lsrq %u, $r%d\n", dc->op1, dc->op2);
+    dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
+    LOG_DIS("lsrq %u, $r%d\n", dc->op1, dc->op2);
 
-	cris_cc_mask(dc, CC_MASK_NZ);
+    cris_cc_mask(dc, CC_MASK_NZ);
 
-	tcg_gen_shri_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
-	cris_alu(dc, CC_OP_MOVE,
-		    cpu_R[dc->op2],
-		    cpu_R[dc->op2], cpu_R[dc->op2], 4);
-	return 2;
+    tcg_gen_shri_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
+    cris_alu(dc, CC_OP_MOVE,
+            cpu_R[dc->op2],
+            cpu_R[dc->op2], cpu_R[dc->op2], 4);
+    return 2;
 }
 
 static int dec_move_r(CPUCRISState *env, DisasContext *dc)
 {
-	int size = memsize_zz(dc);
+    int size = memsize_zz(dc);
 
-	LOG_DIS("move.%c $r%u, $r%u\n",
-		    memsize_char(size), dc->op1, dc->op2);
+    LOG_DIS("move.%c $r%u, $r%u\n",
+            memsize_char(size), dc->op1, dc->op2);
 
-	cris_cc_mask(dc, CC_MASK_NZ);
-	if (size == 4) {
-		dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, cpu_R[dc->op2]);
-		cris_cc_mask(dc, CC_MASK_NZ);
-		cris_update_cc_op(dc, CC_OP_MOVE, 4);
-		cris_update_cc_x(dc);
-		cris_update_result(dc, cpu_R[dc->op2]);
-	}
-	else {
-		TCGv t0;
+    cris_cc_mask(dc, CC_MASK_NZ);
+    if (size == 4) {
+        dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, cpu_R[dc->op2]);
+        cris_cc_mask(dc, CC_MASK_NZ);
+        cris_update_cc_op(dc, CC_OP_MOVE, 4);
+        cris_update_cc_x(dc);
+        cris_update_result(dc, cpu_R[dc->op2]);
+    } else {
+        TCGv t0;
 
-		t0 = tcg_temp_new();
-		dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0);
-		cris_alu(dc, CC_OP_MOVE,
-			 cpu_R[dc->op2],
-			 cpu_R[dc->op2], t0, size);
-		tcg_temp_free(t0);
-	}
-	return 2;
+        t0 = tcg_temp_new();
+        dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0);
+        cris_alu(dc, CC_OP_MOVE,
+             cpu_R[dc->op2],
+             cpu_R[dc->op2], t0, size);
+        tcg_temp_free(t0);
+    }
+    return 2;
 }
 
 static int dec_scc_r(CPUCRISState *env, DisasContext *dc)
 {
-	int cond = dc->op2;
+    int cond = dc->op2;
 
-	LOG_DIS("s%s $r%u\n",
-		    cc_name(cond), dc->op1);
+    LOG_DIS("s%s $r%u\n",
+            cc_name(cond), dc->op1);
 
-	if (cond != CC_A)
-	{
-		int l1;
+    if (cond != CC_A) {
+        int l1;
 
-		gen_tst_cc (dc, cpu_R[dc->op1], cond);
-		l1 = gen_new_label();
-		tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[dc->op1], 0, l1);
-		tcg_gen_movi_tl(cpu_R[dc->op1], 1);
-		gen_set_label(l1);
-	}
-	else
-		tcg_gen_movi_tl(cpu_R[dc->op1], 1);
+        gen_tst_cc(dc, cpu_R[dc->op1], cond);
+        l1 = gen_new_label();
+        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[dc->op1], 0, l1);
+        tcg_gen_movi_tl(cpu_R[dc->op1], 1);
+        gen_set_label(l1);
+    } else {
+        tcg_gen_movi_tl(cpu_R[dc->op1], 1);
+    }
 
-	cris_cc_mask(dc, 0);
-	return 2;
+    cris_cc_mask(dc, 0);
+    return 2;
 }
 
 static inline void cris_alu_alloc_temps(DisasContext *dc, int size, TCGv *t)
 {
-	if (size == 4) {
-		t[0] = cpu_R[dc->op2];
-		t[1] = cpu_R[dc->op1];
-	} else {
-		t[0] = tcg_temp_new();
-		t[1] = tcg_temp_new();
-	}
+    if (size == 4) {
+        t[0] = cpu_R[dc->op2];
+        t[1] = cpu_R[dc->op1];
+    } else {
+        t[0] = tcg_temp_new();
+        t[1] = tcg_temp_new();
+    }
 }
 
 static inline void cris_alu_free_temps(DisasContext *dc, int size, TCGv *t)
 {
-	if (size != 4) {
-		tcg_temp_free(t[0]);
-		tcg_temp_free(t[1]);
-	}
+    if (size != 4) {
+        tcg_temp_free(t[0]);
+        tcg_temp_free(t[1]);
+    }
 }
 
 static int dec_and_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int size = memsize_zz(dc);
+    TCGv t[2];
+    int size = memsize_zz(dc);
 
-	LOG_DIS("and.%c $r%u, $r%u\n",
-		    memsize_char(size), dc->op1, dc->op2);
+    LOG_DIS("and.%c $r%u, $r%u\n",
+            memsize_char(size), dc->op1, dc->op2);
 
-	cris_cc_mask(dc, CC_MASK_NZ);
+    cris_cc_mask(dc, CC_MASK_NZ);
 
-	cris_alu_alloc_temps(dc, size, t);
-	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
-	cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], size);
-	cris_alu_free_temps(dc, size, t);
-	return 2;
+    cris_alu_alloc_temps(dc, size, t);
+    dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
+    cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], size);
+    cris_alu_free_temps(dc, size, t);
+    return 2;
 }
 
 static int dec_lz_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t0;
-	LOG_DIS("lz $r%u, $r%u\n",
-		    dc->op1, dc->op2);
-	cris_cc_mask(dc, CC_MASK_NZ);
-	t0 = tcg_temp_new();
-	dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0, cpu_R[dc->op2], t0);
-	cris_alu(dc, CC_OP_LZ, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
-	tcg_temp_free(t0);
-	return 2;
+    TCGv t0;
+    LOG_DIS("lz $r%u, $r%u\n",
+            dc->op1, dc->op2);
+    cris_cc_mask(dc, CC_MASK_NZ);
+    t0 = tcg_temp_new();
+    dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0, cpu_R[dc->op2], t0);
+    cris_alu(dc, CC_OP_LZ, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
+    tcg_temp_free(t0);
+    return 2;
 }
 
 static int dec_lsl_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int size = memsize_zz(dc);
+    TCGv t[2];
+    int size = memsize_zz(dc);
 
-	LOG_DIS("lsl.%c $r%u, $r%u\n",
-		    memsize_char(size), dc->op1, dc->op2);
+    LOG_DIS("lsl.%c $r%u, $r%u\n",
+            memsize_char(size), dc->op1, dc->op2);
 
-	cris_cc_mask(dc, CC_MASK_NZ);
-	cris_alu_alloc_temps(dc, size, t);
-	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
-	tcg_gen_andi_tl(t[1], t[1], 63);
-	cris_alu(dc, CC_OP_LSL, cpu_R[dc->op2], t[0], t[1], size);
-	cris_alu_alloc_temps(dc, size, t);
-	return 2;
+    cris_cc_mask(dc, CC_MASK_NZ);
+    cris_alu_alloc_temps(dc, size, t);
+    dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
+    tcg_gen_andi_tl(t[1], t[1], 63);
+    cris_alu(dc, CC_OP_LSL, cpu_R[dc->op2], t[0], t[1], size);
+    cris_alu_alloc_temps(dc, size, t);
+    return 2;
 }
 
 static int dec_lsr_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int size = memsize_zz(dc);
+    TCGv t[2];
+    int size = memsize_zz(dc);
 
-	LOG_DIS("lsr.%c $r%u, $r%u\n",
-		    memsize_char(size), dc->op1, dc->op2);
+    LOG_DIS("lsr.%c $r%u, $r%u\n",
+            memsize_char(size), dc->op1, dc->op2);
 
-	cris_cc_mask(dc, CC_MASK_NZ);
-	cris_alu_alloc_temps(dc, size, t);
-	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
-	tcg_gen_andi_tl(t[1], t[1], 63);
-	cris_alu(dc, CC_OP_LSR, cpu_R[dc->op2], t[0], t[1], size);
-	cris_alu_free_temps(dc, size, t);
-	return 2;
+    cris_cc_mask(dc, CC_MASK_NZ);
+    cris_alu_alloc_temps(dc, size, t);
+    dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
+    tcg_gen_andi_tl(t[1], t[1], 63);
+    cris_alu(dc, CC_OP_LSR, cpu_R[dc->op2], t[0], t[1], size);
+    cris_alu_free_temps(dc, size, t);
+    return 2;
 }
 
 static int dec_asr_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int size = memsize_zz(dc);
+    TCGv t[2];
+    int size = memsize_zz(dc);
 
-	LOG_DIS("asr.%c $r%u, $r%u\n",
-		    memsize_char(size), dc->op1, dc->op2);
+    LOG_DIS("asr.%c $r%u, $r%u\n",
+            memsize_char(size), dc->op1, dc->op2);
 
-	cris_cc_mask(dc, CC_MASK_NZ);
-	cris_alu_alloc_temps(dc, size, t);
-	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1, t[0], t[1]);
-	tcg_gen_andi_tl(t[1], t[1], 63);
-	cris_alu(dc, CC_OP_ASR, cpu_R[dc->op2], t[0], t[1], size);
-	cris_alu_free_temps(dc, size, t);
-	return 2;
+    cris_cc_mask(dc, CC_MASK_NZ);
+    cris_alu_alloc_temps(dc, size, t);
+    dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1, t[0], t[1]);
+    tcg_gen_andi_tl(t[1], t[1], 63);
+    cris_alu(dc, CC_OP_ASR, cpu_R[dc->op2], t[0], t[1], size);
+    cris_alu_free_temps(dc, size, t);
+    return 2;
 }
 
 static int dec_muls_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int size = memsize_zz(dc);
+    TCGv t[2];
+    int size = memsize_zz(dc);
 
-	LOG_DIS("muls.%c $r%u, $r%u\n",
-		    memsize_char(size), dc->op1, dc->op2);
-	cris_cc_mask(dc, CC_MASK_NZV);
-	cris_alu_alloc_temps(dc, size, t);
-	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1, t[0], t[1]);
+    LOG_DIS("muls.%c $r%u, $r%u\n",
+            memsize_char(size), dc->op1, dc->op2);
+    cris_cc_mask(dc, CC_MASK_NZV);
+    cris_alu_alloc_temps(dc, size, t);
+    dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1, t[0], t[1]);
 
-	cris_alu(dc, CC_OP_MULS, cpu_R[dc->op2], t[0], t[1], 4);
-	cris_alu_free_temps(dc, size, t);
-	return 2;
+    cris_alu(dc, CC_OP_MULS, cpu_R[dc->op2], t[0], t[1], 4);
+    cris_alu_free_temps(dc, size, t);
+    return 2;
 }
 
 static int dec_mulu_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int size = memsize_zz(dc);
+    TCGv t[2];
+    int size = memsize_zz(dc);
 
-	LOG_DIS("mulu.%c $r%u, $r%u\n",
-		    memsize_char(size), dc->op1, dc->op2);
-	cris_cc_mask(dc, CC_MASK_NZV);
-	cris_alu_alloc_temps(dc, size, t);
-	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
+    LOG_DIS("mulu.%c $r%u, $r%u\n",
+            memsize_char(size), dc->op1, dc->op2);
+    cris_cc_mask(dc, CC_MASK_NZV);
+    cris_alu_alloc_temps(dc, size, t);
+    dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
 
-	cris_alu(dc, CC_OP_MULU, cpu_R[dc->op2], t[0], t[1], 4);
-	cris_alu_alloc_temps(dc, size, t);
-	return 2;
+    cris_alu(dc, CC_OP_MULU, cpu_R[dc->op2], t[0], t[1], 4);
+    cris_alu_alloc_temps(dc, size, t);
+    return 2;
 }
 
 
 static int dec_dstep_r(CPUCRISState *env, DisasContext *dc)
 {
-	LOG_DIS("dstep $r%u, $r%u\n", dc->op1, dc->op2);
-	cris_cc_mask(dc, CC_MASK_NZ);
-	cris_alu(dc, CC_OP_DSTEP,
-		    cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4);
-	return 2;
+    LOG_DIS("dstep $r%u, $r%u\n", dc->op1, dc->op2);
+    cris_cc_mask(dc, CC_MASK_NZ);
+    cris_alu(dc, CC_OP_DSTEP,
+            cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4);
+    return 2;
 }
 
 static int dec_xor_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int size = memsize_zz(dc);
-	LOG_DIS("xor.%c $r%u, $r%u\n",
-		    memsize_char(size), dc->op1, dc->op2);
-	BUG_ON(size != 4); /* xor is dword.  */
-	cris_cc_mask(dc, CC_MASK_NZ);
-	cris_alu_alloc_temps(dc, size, t);
-	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
+    TCGv t[2];
+    int size = memsize_zz(dc);
+    LOG_DIS("xor.%c $r%u, $r%u\n",
+            memsize_char(size), dc->op1, dc->op2);
+    BUG_ON(size != 4); /* xor is dword.  */
+    cris_cc_mask(dc, CC_MASK_NZ);
+    cris_alu_alloc_temps(dc, size, t);
+    dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
 
-	cris_alu(dc, CC_OP_XOR, cpu_R[dc->op2], t[0], t[1], 4);
-	cris_alu_free_temps(dc, size, t);
-	return 2;
+    cris_alu(dc, CC_OP_XOR, cpu_R[dc->op2], t[0], t[1], 4);
+    cris_alu_free_temps(dc, size, t);
+    return 2;
 }
 
 static int dec_bound_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv l0;
-	int size = memsize_zz(dc);
-	LOG_DIS("bound.%c $r%u, $r%u\n",
-		    memsize_char(size), dc->op1, dc->op2);
-	cris_cc_mask(dc, CC_MASK_NZ);
-	l0 = tcg_temp_local_new();
-	dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, l0);
-	cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], cpu_R[dc->op2], l0, 4);
-	tcg_temp_free(l0);
-	return 2;
+    TCGv l0;
+    int size = memsize_zz(dc);
+    LOG_DIS("bound.%c $r%u, $r%u\n",
+            memsize_char(size), dc->op1, dc->op2);
+    cris_cc_mask(dc, CC_MASK_NZ);
+    l0 = tcg_temp_local_new();
+    dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, l0);
+    cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], cpu_R[dc->op2], l0, 4);
+    tcg_temp_free(l0);
+    return 2;
 }
 
 static int dec_cmp_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int size = memsize_zz(dc);
-	LOG_DIS("cmp.%c $r%u, $r%u\n",
-		    memsize_char(size), dc->op1, dc->op2);
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	cris_alu_alloc_temps(dc, size, t);
-	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
+    TCGv t[2];
+    int size = memsize_zz(dc);
+    LOG_DIS("cmp.%c $r%u, $r%u\n",
+            memsize_char(size), dc->op1, dc->op2);
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_alu_alloc_temps(dc, size, t);
+    dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
 
-	cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], t[0], t[1], size);
-	cris_alu_free_temps(dc, size, t);
-	return 2;
+    cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], t[0], t[1], size);
+    cris_alu_free_temps(dc, size, t);
+    return 2;
 }
 
 static int dec_abs_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t0;
+    TCGv t0;
 
-	LOG_DIS("abs $r%u, $r%u\n",
-		    dc->op1, dc->op2);
-	cris_cc_mask(dc, CC_MASK_NZ);
+    LOG_DIS("abs $r%u, $r%u\n",
+            dc->op1, dc->op2);
+    cris_cc_mask(dc, CC_MASK_NZ);
 
-	t0 = tcg_temp_new();
-	tcg_gen_sari_tl(t0, cpu_R[dc->op1], 31);
-	tcg_gen_xor_tl(cpu_R[dc->op2], cpu_R[dc->op1], t0);
-	tcg_gen_sub_tl(cpu_R[dc->op2], cpu_R[dc->op2], t0);
-	tcg_temp_free(t0);
+    t0 = tcg_temp_new();
+    tcg_gen_sari_tl(t0, cpu_R[dc->op1], 31);
+    tcg_gen_xor_tl(cpu_R[dc->op2], cpu_R[dc->op1], t0);
+    tcg_gen_sub_tl(cpu_R[dc->op2], cpu_R[dc->op2], t0);
+    tcg_temp_free(t0);
 
-	cris_alu(dc, CC_OP_MOVE,
-		    cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4);
-	return 2;
+    cris_alu(dc, CC_OP_MOVE,
+            cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4);
+    return 2;
 }
 
 static int dec_add_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int size = memsize_zz(dc);
-	LOG_DIS("add.%c $r%u, $r%u\n",
-		    memsize_char(size), dc->op1, dc->op2);
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	cris_alu_alloc_temps(dc, size, t);
-	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
+    TCGv t[2];
+    int size = memsize_zz(dc);
+    LOG_DIS("add.%c $r%u, $r%u\n",
+            memsize_char(size), dc->op1, dc->op2);
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_alu_alloc_temps(dc, size, t);
+    dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
 
-	cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], t[0], t[1], size);
-	cris_alu_free_temps(dc, size, t);
-	return 2;
+    cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], t[0], t[1], size);
+    cris_alu_free_temps(dc, size, t);
+    return 2;
 }
 
 static int dec_addc_r(CPUCRISState *env, DisasContext *dc)
 {
-	LOG_DIS("addc $r%u, $r%u\n",
-		    dc->op1, dc->op2);
-	cris_evaluate_flags(dc);
-	/* Set for this insn.  */
-	dc->flagx_known = 1;
-	dc->flags_x = X_FLAG;
+    LOG_DIS("addc $r%u, $r%u\n",
+            dc->op1, dc->op2);
+    cris_evaluate_flags(dc);
+    /* Set for this insn.  */
+    dc->flagx_known = 1;
+    dc->flags_x = X_FLAG;
 
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	cris_alu(dc, CC_OP_ADDC,
-		 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4);
-	return 2;
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_alu(dc, CC_OP_ADDC,
+         cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4);
+    return 2;
 }
 
 static int dec_mcp_r(CPUCRISState *env, DisasContext *dc)
 {
-	LOG_DIS("mcp $p%u, $r%u\n",
-		     dc->op2, dc->op1);
-	cris_evaluate_flags(dc);
-	cris_cc_mask(dc, CC_MASK_RNZV);
-	cris_alu(dc, CC_OP_MCP,
-		    cpu_R[dc->op1], cpu_R[dc->op1], cpu_PR[dc->op2], 4);
-	return 2;
+    LOG_DIS("mcp $p%u, $r%u\n",
+             dc->op2, dc->op1);
+    cris_evaluate_flags(dc);
+    cris_cc_mask(dc, CC_MASK_RNZV);
+    cris_alu(dc, CC_OP_MCP,
+            cpu_R[dc->op1], cpu_R[dc->op1], cpu_PR[dc->op2], 4);
+    return 2;
 }
 
 #if DISAS_CRIS
 static char * swapmode_name(int mode, char *modename) {
-	int i = 0;
-	if (mode & 8)
-		modename[i++] = 'n';
-	if (mode & 4)
-		modename[i++] = 'w';
-	if (mode & 2)
-		modename[i++] = 'b';
-	if (mode & 1)
-		modename[i++] = 'r';
-	modename[i++] = 0;
-	return modename;
+    int i = 0;
+    if (mode & 8) {
+        modename[i++] = 'n';
+    }
+    if (mode & 4) {
+        modename[i++] = 'w';
+    }
+    if (mode & 2) {
+        modename[i++] = 'b';
+    }
+    if (mode & 1) {
+        modename[i++] = 'r';
+    }
+    modename[i++] = 0;
+    return modename;
 }
 #endif
 
 static int dec_swap_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t0;
+    TCGv t0;
 #if DISAS_CRIS
-	char modename[4];
+    char modename[4];
 #endif
-	LOG_DIS("swap%s $r%u\n",
-		     swapmode_name(dc->op2, modename), dc->op1);
+    LOG_DIS("swap%s $r%u\n",
+             swapmode_name(dc->op2, modename), dc->op1);
 
-	cris_cc_mask(dc, CC_MASK_NZ);
-	t0 = tcg_temp_new();
-	t_gen_mov_TN_reg(t0, dc->op1);
-	if (dc->op2 & 8)
-		tcg_gen_not_tl(t0, t0);
-	if (dc->op2 & 4)
-		t_gen_swapw(t0, t0);
-	if (dc->op2 & 2)
-		t_gen_swapb(t0, t0);
-	if (dc->op2 & 1)
-		t_gen_swapr(t0, t0);
-	cris_alu(dc, CC_OP_MOVE,
-		    cpu_R[dc->op1], cpu_R[dc->op1], t0, 4);
-	tcg_temp_free(t0);
-	return 2;
+    cris_cc_mask(dc, CC_MASK_NZ);
+    t0 = tcg_temp_new();
+    t_gen_mov_TN_reg(t0, dc->op1);
+    if (dc->op2 & 8) {
+        tcg_gen_not_tl(t0, t0);
+    }
+    if (dc->op2 & 4) {
+        t_gen_swapw(t0, t0);
+    }
+    if (dc->op2 & 2) {
+        t_gen_swapb(t0, t0);
+    }
+    if (dc->op2 & 1) {
+        t_gen_swapr(t0, t0);
+    }
+    cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op1], cpu_R[dc->op1], t0, 4);
+    tcg_temp_free(t0);
+    return 2;
 }
 
 static int dec_or_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int size = memsize_zz(dc);
-	LOG_DIS("or.%c $r%u, $r%u\n",
-		    memsize_char(size), dc->op1, dc->op2);
-	cris_cc_mask(dc, CC_MASK_NZ);
-	cris_alu_alloc_temps(dc, size, t);
-	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
-	cris_alu(dc, CC_OP_OR, cpu_R[dc->op2], t[0], t[1], size);
-	cris_alu_free_temps(dc, size, t);
-	return 2;
+    TCGv t[2];
+    int size = memsize_zz(dc);
+    LOG_DIS("or.%c $r%u, $r%u\n",
+            memsize_char(size), dc->op1, dc->op2);
+    cris_cc_mask(dc, CC_MASK_NZ);
+    cris_alu_alloc_temps(dc, size, t);
+    dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
+    cris_alu(dc, CC_OP_OR, cpu_R[dc->op2], t[0], t[1], size);
+    cris_alu_free_temps(dc, size, t);
+    return 2;
 }
 
 static int dec_addi_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t0;
-	LOG_DIS("addi.%c $r%u, $r%u\n",
-		    memsize_char(memsize_zz(dc)), dc->op2, dc->op1);
-	cris_cc_mask(dc, 0);
-	t0 = tcg_temp_new();
-	tcg_gen_shl_tl(t0, cpu_R[dc->op2], tcg_const_tl(dc->zzsize));
-	tcg_gen_add_tl(cpu_R[dc->op1], cpu_R[dc->op1], t0);
-	tcg_temp_free(t0);
-	return 2;
+    TCGv t0;
+    LOG_DIS("addi.%c $r%u, $r%u\n",
+            memsize_char(memsize_zz(dc)), dc->op2, dc->op1);
+    cris_cc_mask(dc, 0);
+    t0 = tcg_temp_new();
+    tcg_gen_shl_tl(t0, cpu_R[dc->op2], tcg_const_tl(dc->zzsize));
+    tcg_gen_add_tl(cpu_R[dc->op1], cpu_R[dc->op1], t0);
+    tcg_temp_free(t0);
+    return 2;
 }
 
 static int dec_addi_acr(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t0;
-	LOG_DIS("addi.%c $r%u, $r%u, $acr\n",
-		  memsize_char(memsize_zz(dc)), dc->op2, dc->op1);
-	cris_cc_mask(dc, 0);
-	t0 = tcg_temp_new();
-	tcg_gen_shl_tl(t0, cpu_R[dc->op2], tcg_const_tl(dc->zzsize));
-	tcg_gen_add_tl(cpu_R[R_ACR], cpu_R[dc->op1], t0);
-	tcg_temp_free(t0);
-	return 2;
+    TCGv t0;
+    LOG_DIS("addi.%c $r%u, $r%u, $acr\n",
+          memsize_char(memsize_zz(dc)), dc->op2, dc->op1);
+    cris_cc_mask(dc, 0);
+    t0 = tcg_temp_new();
+    tcg_gen_shl_tl(t0, cpu_R[dc->op2], tcg_const_tl(dc->zzsize));
+    tcg_gen_add_tl(cpu_R[R_ACR], cpu_R[dc->op1], t0);
+    tcg_temp_free(t0);
+    return 2;
 }
 
 static int dec_neg_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int size = memsize_zz(dc);
-	LOG_DIS("neg.%c $r%u, $r%u\n",
-		    memsize_char(size), dc->op1, dc->op2);
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	cris_alu_alloc_temps(dc, size, t);
-	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
+    TCGv t[2];
+    int size = memsize_zz(dc);
+    LOG_DIS("neg.%c $r%u, $r%u\n",
+            memsize_char(size), dc->op1, dc->op2);
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_alu_alloc_temps(dc, size, t);
+    dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
 
-	cris_alu(dc, CC_OP_NEG, cpu_R[dc->op2], t[0], t[1], size);
-	cris_alu_free_temps(dc, size, t);
-	return 2;
+    cris_alu(dc, CC_OP_NEG, cpu_R[dc->op2], t[0], t[1], size);
+    cris_alu_free_temps(dc, size, t);
+    return 2;
 }
 
 static int dec_btst_r(CPUCRISState *env, DisasContext *dc)
 {
-	LOG_DIS("btst $r%u, $r%u\n",
-		    dc->op1, dc->op2);
-	cris_cc_mask(dc, CC_MASK_NZ);
-	cris_evaluate_flags(dc);
+    LOG_DIS("btst $r%u, $r%u\n",
+            dc->op1, dc->op2);
+    cris_cc_mask(dc, CC_MASK_NZ);
+    cris_evaluate_flags(dc);
         gen_helper_btst(cpu_PR[PR_CCS], cpu_env, cpu_R[dc->op2],
-			cpu_R[dc->op1], cpu_PR[PR_CCS]);
-	cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2],
-		 cpu_R[dc->op2], cpu_R[dc->op2], 4);
-	cris_update_cc_op(dc, CC_OP_FLAGS, 4);
-	dc->flags_uptodate = 1;
-	return 2;
+            cpu_R[dc->op1], cpu_PR[PR_CCS]);
+    cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2],
+         cpu_R[dc->op2], cpu_R[dc->op2], 4);
+    cris_update_cc_op(dc, CC_OP_FLAGS, 4);
+    dc->flags_uptodate = 1;
+    return 2;
 }
 
 static int dec_sub_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int size = memsize_zz(dc);
-	LOG_DIS("sub.%c $r%u, $r%u\n",
-		    memsize_char(size), dc->op1, dc->op2);
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	cris_alu_alloc_temps(dc, size, t);
-	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
-	cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], size);
-	cris_alu_free_temps(dc, size, t);
-	return 2;
+    TCGv t[2];
+    int size = memsize_zz(dc);
+    LOG_DIS("sub.%c $r%u, $r%u\n",
+            memsize_char(size), dc->op1, dc->op2);
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_alu_alloc_temps(dc, size, t);
+    dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
+    cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], size);
+    cris_alu_free_temps(dc, size, t);
+    return 2;
 }
 
 /* Zero extension. From size to dword.  */
 static int dec_movu_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t0;
-	int size = memsize_z(dc);
-	LOG_DIS("movu.%c $r%u, $r%u\n",
-		    memsize_char(size),
-		    dc->op1, dc->op2);
+    TCGv t0;
+    int size = memsize_z(dc);
+    LOG_DIS("movu.%c $r%u, $r%u\n",
+            memsize_char(size),
+            dc->op1, dc->op2);
 
-	cris_cc_mask(dc, CC_MASK_NZ);
-	t0 = tcg_temp_new();
-	dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0);
-	cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
-	tcg_temp_free(t0);
-	return 2;
+    cris_cc_mask(dc, CC_MASK_NZ);
+    t0 = tcg_temp_new();
+    dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0);
+    cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
+    tcg_temp_free(t0);
+    return 2;
 }
 
 /* Sign extension. From size to dword.  */
 static int dec_movs_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t0;
-	int size = memsize_z(dc);
-	LOG_DIS("movs.%c $r%u, $r%u\n",
-		    memsize_char(size),
-		    dc->op1, dc->op2);
+    TCGv t0;
+    int size = memsize_z(dc);
+    LOG_DIS("movs.%c $r%u, $r%u\n",
+            memsize_char(size),
+            dc->op1, dc->op2);
 
-	cris_cc_mask(dc, CC_MASK_NZ);
-	t0 = tcg_temp_new();
-	/* Size can only be qi or hi.  */
-	t_gen_sext(t0, cpu_R[dc->op1], size);
-	cris_alu(dc, CC_OP_MOVE,
-		    cpu_R[dc->op2], cpu_R[dc->op1], t0, 4);
-	tcg_temp_free(t0);
-	return 2;
+    cris_cc_mask(dc, CC_MASK_NZ);
+    t0 = tcg_temp_new();
+    /* Size can only be qi or hi.  */
+    t_gen_sext(t0, cpu_R[dc->op1], size);
+    cris_alu(dc, CC_OP_MOVE,
+            cpu_R[dc->op2], cpu_R[dc->op1], t0, 4);
+    tcg_temp_free(t0);
+    return 2;
 }
 
 /* zero extension. From size to dword.  */
 static int dec_addu_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t0;
-	int size = memsize_z(dc);
-	LOG_DIS("addu.%c $r%u, $r%u\n",
-		    memsize_char(size),
-		    dc->op1, dc->op2);
+    TCGv t0;
+    int size = memsize_z(dc);
+    LOG_DIS("addu.%c $r%u, $r%u\n",
+            memsize_char(size),
+            dc->op1, dc->op2);
 
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	t0 = tcg_temp_new();
-	/* Size can only be qi or hi.  */
-	t_gen_zext(t0, cpu_R[dc->op1], size);
-	cris_alu(dc, CC_OP_ADD,
-		    cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
-	tcg_temp_free(t0);
-	return 2;
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    t0 = tcg_temp_new();
+    /* Size can only be qi or hi.  */
+    t_gen_zext(t0, cpu_R[dc->op1], size);
+    cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
+    tcg_temp_free(t0);
+    return 2;
 }
 
 /* Sign extension. From size to dword.  */
 static int dec_adds_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t0;
-	int size = memsize_z(dc);
-	LOG_DIS("adds.%c $r%u, $r%u\n",
-		    memsize_char(size),
-		    dc->op1, dc->op2);
+    TCGv t0;
+    int size = memsize_z(dc);
+    LOG_DIS("adds.%c $r%u, $r%u\n",
+            memsize_char(size),
+            dc->op1, dc->op2);
 
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	t0 = tcg_temp_new();
-	/* Size can only be qi or hi.  */
-	t_gen_sext(t0, cpu_R[dc->op1], size);
-	cris_alu(dc, CC_OP_ADD,
-		    cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
-	tcg_temp_free(t0);
-	return 2;
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    t0 = tcg_temp_new();
+    /* Size can only be qi or hi.  */
+    t_gen_sext(t0, cpu_R[dc->op1], size);
+    cris_alu(dc, CC_OP_ADD,
+            cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
+    tcg_temp_free(t0);
+    return 2;
 }
 
 /* Zero extension. From size to dword.  */
 static int dec_subu_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t0;
-	int size = memsize_z(dc);
-	LOG_DIS("subu.%c $r%u, $r%u\n",
-		    memsize_char(size),
-		    dc->op1, dc->op2);
+    TCGv t0;
+    int size = memsize_z(dc);
+    LOG_DIS("subu.%c $r%u, $r%u\n",
+            memsize_char(size),
+            dc->op1, dc->op2);
 
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	t0 = tcg_temp_new();
-	/* Size can only be qi or hi.  */
-	t_gen_zext(t0, cpu_R[dc->op1], size);
-	cris_alu(dc, CC_OP_SUB,
-		    cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
-	tcg_temp_free(t0);
-	return 2;
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    t0 = tcg_temp_new();
+    /* Size can only be qi or hi.  */
+    t_gen_zext(t0, cpu_R[dc->op1], size);
+    cris_alu(dc, CC_OP_SUB,
+            cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
+    tcg_temp_free(t0);
+    return 2;
 }
 
 /* Sign extension. From size to dword.  */
 static int dec_subs_r(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t0;
-	int size = memsize_z(dc);
-	LOG_DIS("subs.%c $r%u, $r%u\n",
-		    memsize_char(size),
-		    dc->op1, dc->op2);
+    TCGv t0;
+    int size = memsize_z(dc);
+    LOG_DIS("subs.%c $r%u, $r%u\n",
+            memsize_char(size),
+            dc->op1, dc->op2);
 
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	t0 = tcg_temp_new();
-	/* Size can only be qi or hi.  */
-	t_gen_sext(t0, cpu_R[dc->op1], size);
-	cris_alu(dc, CC_OP_SUB,
-		    cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
-	tcg_temp_free(t0);
-	return 2;
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    t0 = tcg_temp_new();
+    /* Size can only be qi or hi.  */
+    t_gen_sext(t0, cpu_R[dc->op1], size);
+    cris_alu(dc, CC_OP_SUB,
+            cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
+    tcg_temp_free(t0);
+    return 2;
 }
 
 static int dec_setclrf(CPUCRISState *env, DisasContext *dc)
 {
-	uint32_t flags;
-	int set = (~dc->opcode >> 2) & 1;
+    uint32_t flags;
+    int set = (~dc->opcode >> 2) & 1;
 
 
-	flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4)
-		| EXTRACT_FIELD(dc->ir, 0, 3);
-	if (set && flags == 0) {
-		LOG_DIS("nop\n");
-		return 2;
-	} else if (!set && (flags & 0x20)) {
-		LOG_DIS("di\n");
-	}
-	else {
-		LOG_DIS("%sf %x\n",
-			     set ? "set" : "clr",
-			    flags);
-	}
+    flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4)
+        | EXTRACT_FIELD(dc->ir, 0, 3);
+    if (set && flags == 0) {
+        LOG_DIS("nop\n");
+        return 2;
+    } else if (!set && (flags & 0x20)) {
+        LOG_DIS("di\n");
+    } else {
+        LOG_DIS("%sf %x\n", set ? "set" : "clr", flags);
+    }
 
-	/* User space is not allowed to touch these. Silently ignore.  */
-	if (dc->tb_flags & U_FLAG) {
-		flags &= ~(S_FLAG | I_FLAG | U_FLAG);
-	}
+    /* User space is not allowed to touch these. Silently ignore.  */
+    if (dc->tb_flags & U_FLAG) {
+        flags &= ~(S_FLAG | I_FLAG | U_FLAG);
+    }
 
-	if (flags & X_FLAG) {
-		dc->flagx_known = 1;
-		if (set)
-			dc->flags_x = X_FLAG;
-		else
-			dc->flags_x = 0;
-	}
+    if (flags & X_FLAG) {
+        dc->flagx_known = 1;
+        if (set) {
+            dc->flags_x = X_FLAG;
+        } else {
+            dc->flags_x = 0;
+        }
+    }
 
-	/* Break the TB if any of the SPI flag changes.  */
-	if (flags & (P_FLAG | S_FLAG)) {
-		tcg_gen_movi_tl(env_pc, dc->pc + 2);
-		dc->is_jmp = DISAS_UPDATE;
-		dc->cpustate_changed = 1;
-	}
+    /* Break the TB if any of the SPI flag changes.  */
+    if (flags & (P_FLAG | S_FLAG)) {
+        tcg_gen_movi_tl(env_pc, dc->pc + 2);
+        dc->is_jmp = DISAS_UPDATE;
+        dc->cpustate_changed = 1;
+    }
 
-	/* For the I flag, only act on posedge.  */
-	if ((flags & I_FLAG)) {
-		tcg_gen_movi_tl(env_pc, dc->pc + 2);
-		dc->is_jmp = DISAS_UPDATE;
-		dc->cpustate_changed = 1;
-	}
+    /* For the I flag, only act on posedge.  */
+    if ((flags & I_FLAG)) {
+        tcg_gen_movi_tl(env_pc, dc->pc + 2);
+        dc->is_jmp = DISAS_UPDATE;
+        dc->cpustate_changed = 1;
+    }
 
 
-	/* Simply decode the flags.  */
-	cris_evaluate_flags (dc);
-	cris_update_cc_op(dc, CC_OP_FLAGS, 4);
-	cris_update_cc_x(dc);
-	tcg_gen_movi_tl(cc_op, dc->cc_op);
+    /* Simply decode the flags.  */
+    cris_evaluate_flags(dc);
+    cris_update_cc_op(dc, CC_OP_FLAGS, 4);
+    cris_update_cc_x(dc);
+    tcg_gen_movi_tl(cc_op, dc->cc_op);
 
-	if (set) {
-		if (!(dc->tb_flags & U_FLAG) && (flags & U_FLAG)) {
-			/* Enter user mode.  */
-			t_gen_mov_env_TN(ksp, cpu_R[R_SP]);
-			tcg_gen_mov_tl(cpu_R[R_SP], cpu_PR[PR_USP]);
-			dc->cpustate_changed = 1;
-		}
-		tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags);
-	}
-	else
-		tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags);
+    if (set) {
+        if (!(dc->tb_flags & U_FLAG) && (flags & U_FLAG)) {
+            /* Enter user mode.  */
+            t_gen_mov_env_TN(ksp, cpu_R[R_SP]);
+            tcg_gen_mov_tl(cpu_R[R_SP], cpu_PR[PR_USP]);
+            dc->cpustate_changed = 1;
+        }
+        tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags);
+    } else {
+        tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags);
+    }
 
-	dc->flags_uptodate = 1;
-	dc->clear_x = 0;
-	return 2;
+    dc->flags_uptodate = 1;
+    dc->clear_x = 0;
+    return 2;
 }
 
 static int dec_move_rs(CPUCRISState *env, DisasContext *dc)
 {
-	LOG_DIS("move $r%u, $s%u\n", dc->op1, dc->op2);
-	cris_cc_mask(dc, 0);
+    LOG_DIS("move $r%u, $s%u\n", dc->op1, dc->op2);
+    cris_cc_mask(dc, 0);
         gen_helper_movl_sreg_reg(cpu_env, tcg_const_tl(dc->op2),
                                  tcg_const_tl(dc->op1));
-	return 2;
+    return 2;
 }
 static int dec_move_sr(CPUCRISState *env, DisasContext *dc)
 {
-	LOG_DIS("move $s%u, $r%u\n", dc->op2, dc->op1);
-	cris_cc_mask(dc, 0);
+    LOG_DIS("move $s%u, $r%u\n", dc->op2, dc->op1);
+    cris_cc_mask(dc, 0);
         gen_helper_movl_reg_sreg(cpu_env, tcg_const_tl(dc->op1),
                                  tcg_const_tl(dc->op2));
-	return 2;
+    return 2;
 }
 
 static int dec_move_rp(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	LOG_DIS("move $r%u, $p%u\n", dc->op1, dc->op2);
-	cris_cc_mask(dc, 0);
+    TCGv t[2];
+    LOG_DIS("move $r%u, $p%u\n", dc->op1, dc->op2);
+    cris_cc_mask(dc, 0);
 
-	t[0] = tcg_temp_new();
-	if (dc->op2 == PR_CCS) {
-		cris_evaluate_flags(dc);
-		t_gen_mov_TN_reg(t[0], dc->op1);
-		if (dc->tb_flags & U_FLAG) {
-			t[1] = tcg_temp_new();
-			/* User space is not allowed to touch all flags.  */
-			tcg_gen_andi_tl(t[0], t[0], 0x39f);
-			tcg_gen_andi_tl(t[1], cpu_PR[PR_CCS], ~0x39f);
-			tcg_gen_or_tl(t[0], t[1], t[0]);
-			tcg_temp_free(t[1]);
-		}
-	}
-	else
-		t_gen_mov_TN_reg(t[0], dc->op1);
+    t[0] = tcg_temp_new();
+    if (dc->op2 == PR_CCS) {
+        cris_evaluate_flags(dc);
+        t_gen_mov_TN_reg(t[0], dc->op1);
+        if (dc->tb_flags & U_FLAG) {
+            t[1] = tcg_temp_new();
+            /* User space is not allowed to touch all flags.  */
+            tcg_gen_andi_tl(t[0], t[0], 0x39f);
+            tcg_gen_andi_tl(t[1], cpu_PR[PR_CCS], ~0x39f);
+            tcg_gen_or_tl(t[0], t[1], t[0]);
+            tcg_temp_free(t[1]);
+        }
+    } else {
+        t_gen_mov_TN_reg(t[0], dc->op1);
+    }
 
-	t_gen_mov_preg_TN(dc, dc->op2, t[0]);
-	if (dc->op2 == PR_CCS) {
-		cris_update_cc_op(dc, CC_OP_FLAGS, 4);
-		dc->flags_uptodate = 1;
-	}
-	tcg_temp_free(t[0]);
-	return 2;
+    t_gen_mov_preg_TN(dc, dc->op2, t[0]);
+    if (dc->op2 == PR_CCS) {
+        cris_update_cc_op(dc, CC_OP_FLAGS, 4);
+        dc->flags_uptodate = 1;
+    }
+    tcg_temp_free(t[0]);
+    return 2;
 }
 static int dec_move_pr(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t0;
-	LOG_DIS("move $p%u, $r%u\n", dc->op2, dc->op1);
-	cris_cc_mask(dc, 0);
+    TCGv t0;
+    LOG_DIS("move $p%u, $r%u\n", dc->op2, dc->op1);
+    cris_cc_mask(dc, 0);
 
-	if (dc->op2 == PR_CCS)
-		cris_evaluate_flags(dc);
+    if (dc->op2 == PR_CCS) {
+        cris_evaluate_flags(dc);
+    }
 
-        if (dc->op2 == PR_DZ) {
-		tcg_gen_movi_tl(cpu_R[dc->op1], 0);
-        } else {
-		t0 = tcg_temp_new();
-		t_gen_mov_TN_preg(t0, dc->op2);
-		cris_alu(dc, CC_OP_MOVE,
-			 cpu_R[dc->op1], cpu_R[dc->op1], t0,
-			 preg_sizes[dc->op2]);
-		tcg_temp_free(t0);
-	}
-	return 2;
+    if (dc->op2 == PR_DZ) {
+        tcg_gen_movi_tl(cpu_R[dc->op1], 0);
+    } else {
+        t0 = tcg_temp_new();
+        t_gen_mov_TN_preg(t0, dc->op2);
+        cris_alu(dc, CC_OP_MOVE,
+                cpu_R[dc->op1], cpu_R[dc->op1], t0,
+                preg_sizes[dc->op2]);
+        tcg_temp_free(t0);
+    }
+    return 2;
 }
 
 static int dec_move_mr(CPUCRISState *env, DisasContext *dc)
 {
-	int memsize = memsize_zz(dc);
-	int insn_len;
-	LOG_DIS("move.%c [$r%u%s, $r%u\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2);
+    int memsize = memsize_zz(dc);
+    int insn_len;
+    LOG_DIS("move.%c [$r%u%s, $r%u\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+                    dc->op2);
 
-	if (memsize == 4) {
-                insn_len = dec_prep_move_m(env, dc, 0, 4, cpu_R[dc->op2]);
-		cris_cc_mask(dc, CC_MASK_NZ);
-		cris_update_cc_op(dc, CC_OP_MOVE, 4);
-		cris_update_cc_x(dc);
-		cris_update_result(dc, cpu_R[dc->op2]);
-	}
-	else {
-		TCGv t0;
+    if (memsize == 4) {
+        insn_len = dec_prep_move_m(env, dc, 0, 4, cpu_R[dc->op2]);
+        cris_cc_mask(dc, CC_MASK_NZ);
+        cris_update_cc_op(dc, CC_OP_MOVE, 4);
+        cris_update_cc_x(dc);
+        cris_update_result(dc, cpu_R[dc->op2]);
+    } else {
+        TCGv t0;
 
-		t0 = tcg_temp_new();
-                insn_len = dec_prep_move_m(env, dc, 0, memsize, t0);
-		cris_cc_mask(dc, CC_MASK_NZ);
-		cris_alu(dc, CC_OP_MOVE,
-			    cpu_R[dc->op2], cpu_R[dc->op2], t0, memsize);
-		tcg_temp_free(t0);
-	}
-	do_postinc(dc, memsize);
-	return insn_len;
+        t0 = tcg_temp_new();
+        insn_len = dec_prep_move_m(env, dc, 0, memsize, t0);
+        cris_cc_mask(dc, CC_MASK_NZ);
+        cris_alu(dc, CC_OP_MOVE,
+                cpu_R[dc->op2], cpu_R[dc->op2], t0, memsize);
+        tcg_temp_free(t0);
+    }
+    do_postinc(dc, memsize);
+    return insn_len;
 }
 
 static inline void cris_alu_m_alloc_temps(TCGv *t)
 {
-	t[0] = tcg_temp_new();
-	t[1] = tcg_temp_new();
+    t[0] = tcg_temp_new();
+    t[1] = tcg_temp_new();
 }
 
 static inline void cris_alu_m_free_temps(TCGv *t)
 {
-	tcg_temp_free(t[0]);
-	tcg_temp_free(t[1]);
+    tcg_temp_free(t[0]);
+    tcg_temp_free(t[1]);
 }
 
 static int dec_movs_m(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int memsize = memsize_z(dc);
-	int insn_len;
-	LOG_DIS("movs.%c [$r%u%s, $r%u\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2);
+    TCGv t[2];
+    int memsize = memsize_z(dc);
+    int insn_len;
+    LOG_DIS("movs.%c [$r%u%s, $r%u\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2);
 
-	cris_alu_m_alloc_temps(t);
-	/* sign extend.  */
+    cris_alu_m_alloc_temps(t);
+    /* sign extend.  */
         insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]);
-	cris_cc_mask(dc, CC_MASK_NZ);
-	cris_alu(dc, CC_OP_MOVE,
-		    cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
-	do_postinc(dc, memsize);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    cris_cc_mask(dc, CC_MASK_NZ);
+    cris_alu(dc, CC_OP_MOVE,
+            cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
+    do_postinc(dc, memsize);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_addu_m(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int memsize = memsize_z(dc);
-	int insn_len;
-	LOG_DIS("addu.%c [$r%u%s, $r%u\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2);
+    TCGv t[2];
+    int memsize = memsize_z(dc);
+    int insn_len;
+    LOG_DIS("addu.%c [$r%u%s, $r%u\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2);
 
-	cris_alu_m_alloc_temps(t);
-	/* sign extend.  */
+    cris_alu_m_alloc_temps(t);
+    /* sign extend.  */
         insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	cris_alu(dc, CC_OP_ADD,
-		    cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
-	do_postinc(dc, memsize);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_alu(dc, CC_OP_ADD,
+            cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
+    do_postinc(dc, memsize);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_adds_m(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int memsize = memsize_z(dc);
-	int insn_len;
-	LOG_DIS("adds.%c [$r%u%s, $r%u\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2);
+    TCGv t[2];
+    int memsize = memsize_z(dc);
+    int insn_len;
+    LOG_DIS("adds.%c [$r%u%s, $r%u\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2);
 
-	cris_alu_m_alloc_temps(t);
-	/* sign extend.  */
+    cris_alu_m_alloc_temps(t);
+    /* sign extend.  */
         insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]);
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
-	do_postinc(dc, memsize);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
+    do_postinc(dc, memsize);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_subu_m(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int memsize = memsize_z(dc);
-	int insn_len;
-	LOG_DIS("subu.%c [$r%u%s, $r%u\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2);
+    TCGv t[2];
+    int memsize = memsize_z(dc);
+    int insn_len;
+    LOG_DIS("subu.%c [$r%u%s, $r%u\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2);
 
-	cris_alu_m_alloc_temps(t);
-	/* sign extend.  */
+    cris_alu_m_alloc_temps(t);
+    /* sign extend.  */
         insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
-	do_postinc(dc, memsize);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
+    do_postinc(dc, memsize);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_subs_m(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int memsize = memsize_z(dc);
-	int insn_len;
-	LOG_DIS("subs.%c [$r%u%s, $r%u\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2);
+    TCGv t[2];
+    int memsize = memsize_z(dc);
+    int insn_len;
+    LOG_DIS("subs.%c [$r%u%s, $r%u\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2);
 
-	cris_alu_m_alloc_temps(t);
-	/* sign extend.  */
+    cris_alu_m_alloc_temps(t);
+    /* sign extend.  */
         insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]);
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
-	do_postinc(dc, memsize);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
+    do_postinc(dc, memsize);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_movu_m(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int memsize = memsize_z(dc);
-	int insn_len;
+    TCGv t[2];
+    int memsize = memsize_z(dc);
+    int insn_len;
 
-	LOG_DIS("movu.%c [$r%u%s, $r%u\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2);
+    LOG_DIS("movu.%c [$r%u%s, $r%u\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2);
 
-	cris_alu_m_alloc_temps(t);
+    cris_alu_m_alloc_temps(t);
         insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
-	cris_cc_mask(dc, CC_MASK_NZ);
-	cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
-	do_postinc(dc, memsize);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    cris_cc_mask(dc, CC_MASK_NZ);
+    cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
+    do_postinc(dc, memsize);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_cmpu_m(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int memsize = memsize_z(dc);
-	int insn_len;
-	LOG_DIS("cmpu.%c [$r%u%s, $r%u\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2);
+    TCGv t[2];
+    int memsize = memsize_z(dc);
+    int insn_len;
+    LOG_DIS("cmpu.%c [$r%u%s, $r%u\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2);
 
-	cris_alu_m_alloc_temps(t);
+    cris_alu_m_alloc_temps(t);
         insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
-	do_postinc(dc, memsize);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
+    do_postinc(dc, memsize);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_cmps_m(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int memsize = memsize_z(dc);
-	int insn_len;
-	LOG_DIS("cmps.%c [$r%u%s, $r%u\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2);
+    TCGv t[2];
+    int memsize = memsize_z(dc);
+    int insn_len;
+    LOG_DIS("cmps.%c [$r%u%s, $r%u\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2);
 
-	cris_alu_m_alloc_temps(t);
+    cris_alu_m_alloc_temps(t);
         insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]);
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	cris_alu(dc, CC_OP_CMP,
-		    cpu_R[dc->op2], cpu_R[dc->op2], t[1],
-		    memsize_zz(dc));
-	do_postinc(dc, memsize);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_alu(dc, CC_OP_CMP,
+            cpu_R[dc->op2], cpu_R[dc->op2], t[1],
+            memsize_zz(dc));
+    do_postinc(dc, memsize);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_cmp_m(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int memsize = memsize_zz(dc);
-	int insn_len;
-	LOG_DIS("cmp.%c [$r%u%s, $r%u\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2);
+    TCGv t[2];
+    int memsize = memsize_zz(dc);
+    int insn_len;
+    LOG_DIS("cmp.%c [$r%u%s, $r%u\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2);
 
-	cris_alu_m_alloc_temps(t);
+    cris_alu_m_alloc_temps(t);
         insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	cris_alu(dc, CC_OP_CMP,
-		    cpu_R[dc->op2], cpu_R[dc->op2], t[1],
-		    memsize_zz(dc));
-	do_postinc(dc, memsize);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_alu(dc, CC_OP_CMP,
+            cpu_R[dc->op2], cpu_R[dc->op2], t[1],
+            memsize_zz(dc));
+    do_postinc(dc, memsize);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_test_m(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int memsize = memsize_zz(dc);
-	int insn_len;
-	LOG_DIS("test.%c [$r%u%s] op2=%x\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2);
+    TCGv t[2];
+    int memsize = memsize_zz(dc);
+    int insn_len;
+    LOG_DIS("test.%c [$r%u%s] op2=%x\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2);
 
-	cris_evaluate_flags(dc);
+    cris_evaluate_flags(dc);
 
-	cris_alu_m_alloc_temps(t);
+    cris_alu_m_alloc_temps(t);
         insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
-	cris_cc_mask(dc, CC_MASK_NZ);
-	tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3);
+    cris_cc_mask(dc, CC_MASK_NZ);
+    tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3);
 
-	cris_alu(dc, CC_OP_CMP,
-		 cpu_R[dc->op2], t[1], tcg_const_tl(0), memsize_zz(dc));
-	do_postinc(dc, memsize);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    cris_alu(dc, CC_OP_CMP,
+         cpu_R[dc->op2], t[1], tcg_const_tl(0), memsize_zz(dc));
+    do_postinc(dc, memsize);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_and_m(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int memsize = memsize_zz(dc);
-	int insn_len;
-	LOG_DIS("and.%c [$r%u%s, $r%u\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2);
+    TCGv t[2];
+    int memsize = memsize_zz(dc);
+    int insn_len;
+    LOG_DIS("and.%c [$r%u%s, $r%u\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2);
 
-	cris_alu_m_alloc_temps(t);
+    cris_alu_m_alloc_temps(t);
         insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
-	cris_cc_mask(dc, CC_MASK_NZ);
-	cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
-	do_postinc(dc, memsize);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    cris_cc_mask(dc, CC_MASK_NZ);
+    cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
+    do_postinc(dc, memsize);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_add_m(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int memsize = memsize_zz(dc);
-	int insn_len;
-	LOG_DIS("add.%c [$r%u%s, $r%u\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2);
+    TCGv t[2];
+    int memsize = memsize_zz(dc);
+    int insn_len;
+    LOG_DIS("add.%c [$r%u%s, $r%u\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2);
 
-	cris_alu_m_alloc_temps(t);
+    cris_alu_m_alloc_temps(t);
         insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	cris_alu(dc, CC_OP_ADD,
-		 cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
-	do_postinc(dc, memsize);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_alu(dc, CC_OP_ADD,
+         cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
+    do_postinc(dc, memsize);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_addo_m(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int memsize = memsize_zz(dc);
-	int insn_len;
-	LOG_DIS("add.%c [$r%u%s, $r%u\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2);
+    TCGv t[2];
+    int memsize = memsize_zz(dc);
+    int insn_len;
+    LOG_DIS("add.%c [$r%u%s, $r%u\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2);
 
-	cris_alu_m_alloc_temps(t);
+    cris_alu_m_alloc_temps(t);
         insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]);
-	cris_cc_mask(dc, 0);
-	cris_alu(dc, CC_OP_ADD, cpu_R[R_ACR], t[0], t[1], 4);
-	do_postinc(dc, memsize);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    cris_cc_mask(dc, 0);
+    cris_alu(dc, CC_OP_ADD, cpu_R[R_ACR], t[0], t[1], 4);
+    do_postinc(dc, memsize);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_bound_m(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv l[2];
-	int memsize = memsize_zz(dc);
-	int insn_len;
-	LOG_DIS("bound.%c [$r%u%s, $r%u\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2);
+    TCGv l[2];
+    int memsize = memsize_zz(dc);
+    int insn_len;
+    LOG_DIS("bound.%c [$r%u%s, $r%u\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2);
 
-	l[0] = tcg_temp_local_new();
-	l[1] = tcg_temp_local_new();
+    l[0] = tcg_temp_local_new();
+    l[1] = tcg_temp_local_new();
         insn_len = dec_prep_alu_m(env, dc, 0, memsize, l[0], l[1]);
-	cris_cc_mask(dc, CC_MASK_NZ);
-	cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], l[0], l[1], 4);
-	do_postinc(dc, memsize);
-	tcg_temp_free(l[0]);
-	tcg_temp_free(l[1]);
-	return insn_len;
+    cris_cc_mask(dc, CC_MASK_NZ);
+    cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], l[0], l[1], 4);
+    do_postinc(dc, memsize);
+    tcg_temp_free(l[0]);
+    tcg_temp_free(l[1]);
+    return insn_len;
 }
 
 static int dec_addc_mr(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int insn_len = 2;
-	LOG_DIS("addc [$r%u%s, $r%u\n",
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2);
+    TCGv t[2];
+    int insn_len = 2;
+    LOG_DIS("addc [$r%u%s, $r%u\n",
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2);
 
-	cris_evaluate_flags(dc);
+    cris_evaluate_flags(dc);
 
-	/* Set for this insn.  */
-	dc->flagx_known = 1;
-	dc->flags_x = X_FLAG;
+    /* Set for this insn.  */
+    dc->flagx_known = 1;
+    dc->flags_x = X_FLAG;
 
-	cris_alu_m_alloc_temps(t);
+    cris_alu_m_alloc_temps(t);
         insn_len = dec_prep_alu_m(env, dc, 0, 4, t[0], t[1]);
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	cris_alu(dc, CC_OP_ADDC, cpu_R[dc->op2], t[0], t[1], 4);
-	do_postinc(dc, 4);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_alu(dc, CC_OP_ADDC, cpu_R[dc->op2], t[0], t[1], 4);
+    do_postinc(dc, 4);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_sub_m(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int memsize = memsize_zz(dc);
-	int insn_len;
-	LOG_DIS("sub.%c [$r%u%s, $r%u ir=%x zz=%x\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2, dc->ir, dc->zzsize);
+    TCGv t[2];
+    int memsize = memsize_zz(dc);
+    int insn_len;
+    LOG_DIS("sub.%c [$r%u%s, $r%u ir=%x zz=%x\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2, dc->ir, dc->zzsize);
 
-	cris_alu_m_alloc_temps(t);
+    cris_alu_m_alloc_temps(t);
         insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
-	cris_cc_mask(dc, CC_MASK_NZVC);
-	cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], memsize);
-	do_postinc(dc, memsize);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], memsize);
+    do_postinc(dc, memsize);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_or_m(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int memsize = memsize_zz(dc);
-	int insn_len;
-	LOG_DIS("or.%c [$r%u%s, $r%u pc=%x\n",
-		    memsize_char(memsize),
-		    dc->op1, dc->postinc ? "+]" : "]",
-		    dc->op2, dc->pc);
+    TCGv t[2];
+    int memsize = memsize_zz(dc);
+    int insn_len;
+    LOG_DIS("or.%c [$r%u%s, $r%u pc=%x\n",
+            memsize_char(memsize),
+            dc->op1, dc->postinc ? "+]" : "]",
+            dc->op2, dc->pc);
 
-	cris_alu_m_alloc_temps(t);
+    cris_alu_m_alloc_temps(t);
         insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
-	cris_cc_mask(dc, CC_MASK_NZ);
-	cris_alu(dc, CC_OP_OR,
-		    cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
-	do_postinc(dc, memsize);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    cris_cc_mask(dc, CC_MASK_NZ);
+    cris_alu(dc, CC_OP_OR,
+            cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
+    do_postinc(dc, memsize);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_move_mp(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t[2];
-	int memsize = memsize_zz(dc);
-	int insn_len = 2;
+    TCGv t[2];
+    int memsize = memsize_zz(dc);
+    int insn_len = 2;
 
-	LOG_DIS("move.%c [$r%u%s, $p%u\n",
-		    memsize_char(memsize),
-		    dc->op1,
-		    dc->postinc ? "+]" : "]",
-		    dc->op2);
+    LOG_DIS("move.%c [$r%u%s, $p%u\n",
+            memsize_char(memsize),
+            dc->op1,
+            dc->postinc ? "+]" : "]",
+            dc->op2);
 
-	cris_alu_m_alloc_temps(t);
+    cris_alu_m_alloc_temps(t);
         insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
-	cris_cc_mask(dc, 0);
-	if (dc->op2 == PR_CCS) {
-		cris_evaluate_flags(dc);
-		if (dc->tb_flags & U_FLAG) {
-			/* User space is not allowed to touch all flags.  */
-			tcg_gen_andi_tl(t[1], t[1], 0x39f);
-			tcg_gen_andi_tl(t[0], cpu_PR[PR_CCS], ~0x39f);
-			tcg_gen_or_tl(t[1], t[0], t[1]);
-		}
-	}
+    cris_cc_mask(dc, 0);
+    if (dc->op2 == PR_CCS) {
+        cris_evaluate_flags(dc);
+        if (dc->tb_flags & U_FLAG) {
+            /* User space is not allowed to touch all flags.  */
+            tcg_gen_andi_tl(t[1], t[1], 0x39f);
+            tcg_gen_andi_tl(t[0], cpu_PR[PR_CCS], ~0x39f);
+            tcg_gen_or_tl(t[1], t[0], t[1]);
+        }
+    }
 
-	t_gen_mov_preg_TN(dc, dc->op2, t[1]);
+    t_gen_mov_preg_TN(dc, dc->op2, t[1]);
 
-	do_postinc(dc, memsize);
-	cris_alu_m_free_temps(t);
-	return insn_len;
+    do_postinc(dc, memsize);
+    cris_alu_m_free_temps(t);
+    return insn_len;
 }
 
 static int dec_move_pm(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv t0;
-	int memsize;
+    TCGv t0;
+    int memsize;
 
-	memsize = preg_sizes[dc->op2];
+    memsize = preg_sizes[dc->op2];
 
-	LOG_DIS("move.%c $p%u, [$r%u%s\n",
-		     memsize_char(memsize), 
-		     dc->op2, dc->op1, dc->postinc ? "+]" : "]");
+    LOG_DIS("move.%c $p%u, [$r%u%s\n",
+            memsize_char(memsize),
+            dc->op2, dc->op1, dc->postinc ? "+]" : "]");
 
-	/* prepare store. Address in T0, value in T1.  */
-	if (dc->op2 == PR_CCS)
-		cris_evaluate_flags(dc);
-	t0 = tcg_temp_new();
-	t_gen_mov_TN_preg(t0, dc->op2);
-	cris_flush_cc_state(dc);
-	gen_store(dc, cpu_R[dc->op1], t0, memsize);
-	tcg_temp_free(t0);
+    /* prepare store. Address in T0, value in T1.  */
+    if (dc->op2 == PR_CCS) {
+        cris_evaluate_flags(dc);
+    }
+    t0 = tcg_temp_new();
+    t_gen_mov_TN_preg(t0, dc->op2);
+    cris_flush_cc_state(dc);
+    gen_store(dc, cpu_R[dc->op1], t0, memsize);
+    tcg_temp_free(t0);
 
-	cris_cc_mask(dc, 0);
-	if (dc->postinc)
-		tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize);
-	return 2;
+    cris_cc_mask(dc, 0);
+    if (dc->postinc) {
+        tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize);
+    }
+    return 2;
 }
 
 static int dec_movem_mr(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv_i64 tmp[16];
-        TCGv tmp32;
-	TCGv addr;
-	int i;
-	int nr = dc->op2 + 1;
+    TCGv_i64 tmp[16];
+    TCGv tmp32;
+    TCGv addr;
+    int i;
+    int nr = dc->op2 + 1;
 
-	LOG_DIS("movem [$r%u%s, $r%u\n", dc->op1,
-		    dc->postinc ? "+]" : "]", dc->op2);
+    LOG_DIS("movem [$r%u%s, $r%u\n", dc->op1,
+            dc->postinc ? "+]" : "]", dc->op2);
 
-	addr = tcg_temp_new();
-	/* There are probably better ways of doing this.  */
-	cris_flush_cc_state(dc);
-	for (i = 0; i < (nr >> 1); i++) {
-		tmp[i] = tcg_temp_new_i64();
-		tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
-		gen_load64(dc, tmp[i], addr);
-	}
-	if (nr & 1) {
-		tmp32 = tcg_temp_new_i32();
-		tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
-		gen_load(dc, tmp32, addr, 4, 0);
-	} else
-		TCGV_UNUSED(tmp32);
-	tcg_temp_free(addr);
+    addr = tcg_temp_new();
+    /* There are probably better ways of doing this.  */
+    cris_flush_cc_state(dc);
+    for (i = 0; i < (nr >> 1); i++) {
+        tmp[i] = tcg_temp_new_i64();
+        tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
+        gen_load64(dc, tmp[i], addr);
+    }
+    if (nr & 1) {
+        tmp32 = tcg_temp_new_i32();
+        tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
+        gen_load(dc, tmp32, addr, 4, 0);
+    } else {
+        TCGV_UNUSED(tmp32);
+    }
+    tcg_temp_free(addr);
 
-	for (i = 0; i < (nr >> 1); i++) {
-		tcg_gen_trunc_i64_i32(cpu_R[i * 2], tmp[i]);
-		tcg_gen_shri_i64(tmp[i], tmp[i], 32);
-		tcg_gen_trunc_i64_i32(cpu_R[i * 2 + 1], tmp[i]);
-		tcg_temp_free_i64(tmp[i]);
-	}
-	if (nr & 1) {
-		tcg_gen_mov_tl(cpu_R[dc->op2], tmp32);
-		tcg_temp_free(tmp32);
-	}
+    for (i = 0; i < (nr >> 1); i++) {
+        tcg_gen_trunc_i64_i32(cpu_R[i * 2], tmp[i]);
+        tcg_gen_shri_i64(tmp[i], tmp[i], 32);
+        tcg_gen_trunc_i64_i32(cpu_R[i * 2 + 1], tmp[i]);
+        tcg_temp_free_i64(tmp[i]);
+    }
+    if (nr & 1) {
+        tcg_gen_mov_tl(cpu_R[dc->op2], tmp32);
+        tcg_temp_free(tmp32);
+    }
 
-	/* writeback the updated pointer value.  */
-	if (dc->postinc)
-		tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], nr * 4);
+    /* writeback the updated pointer value.  */
+    if (dc->postinc) {
+        tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], nr * 4);
+    }
 
-	/* gen_load might want to evaluate the previous insns flags.  */
-	cris_cc_mask(dc, 0);
-	return 2;
+    /* gen_load might want to evaluate the previous insns flags.  */
+    cris_cc_mask(dc, 0);
+    return 2;
 }
 
 static int dec_movem_rm(CPUCRISState *env, DisasContext *dc)
 {
-	TCGv tmp;
-	TCGv addr;
-	int i;
+    TCGv tmp;
+    TCGv addr;
+    int i;
 
-	LOG_DIS("movem $r%u, [$r%u%s\n", dc->op2, dc->op1,
-		     dc->postinc ? "+]" : "]");
+    LOG_DIS("movem $r%u, [$r%u%s\n", dc->op2, dc->op1,
+            dc->postinc ? "+]" : "]");
 
-	cris_flush_cc_state(dc);
+    cris_flush_cc_state(dc);
 
-	tmp = tcg_temp_new();
-	addr = tcg_temp_new();
-	tcg_gen_movi_tl(tmp, 4);
-	tcg_gen_mov_tl(addr, cpu_R[dc->op1]);
-	for (i = 0; i <= dc->op2; i++) {
-		/* Displace addr.  */
-		/* Perform the store.  */
-		gen_store(dc, addr, cpu_R[i], 4);
-		tcg_gen_add_tl(addr, addr, tmp);
-	}
-	if (dc->postinc)
-		tcg_gen_mov_tl(cpu_R[dc->op1], addr);
-	cris_cc_mask(dc, 0);
-	tcg_temp_free(tmp);
-	tcg_temp_free(addr);
-	return 2;
+    tmp = tcg_temp_new();
+    addr = tcg_temp_new();
+    tcg_gen_movi_tl(tmp, 4);
+    tcg_gen_mov_tl(addr, cpu_R[dc->op1]);
+    for (i = 0; i <= dc->op2; i++) {
+        /* Displace addr.  */
+        /* Perform the store.  */
+        gen_store(dc, addr, cpu_R[i], 4);
+        tcg_gen_add_tl(addr, addr, tmp);
+    }
+    if (dc->postinc) {
+        tcg_gen_mov_tl(cpu_R[dc->op1], addr);
+    }
+    cris_cc_mask(dc, 0);
+    tcg_temp_free(tmp);
+    tcg_temp_free(addr);
+    return 2;
 }
 
 static int dec_move_rm(CPUCRISState *env, DisasContext *dc)
 {
-	int memsize;
+    int memsize;
 
-	memsize = memsize_zz(dc);
+    memsize = memsize_zz(dc);
 
-	LOG_DIS("move.%c $r%u, [$r%u]\n",
-		     memsize_char(memsize), dc->op2, dc->op1);
+    LOG_DIS("move.%c $r%u, [$r%u]\n",
+            memsize_char(memsize), dc->op2, dc->op1);
 
-	/* prepare store.  */
-	cris_flush_cc_state(dc);
-	gen_store(dc, cpu_R[dc->op1], cpu_R[dc->op2], memsize);
+    /* prepare store.  */
+    cris_flush_cc_state(dc);
+    gen_store(dc, cpu_R[dc->op1], cpu_R[dc->op2], memsize);
 
-	if (dc->postinc)
-		tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize);
-	cris_cc_mask(dc, 0);
-	return 2;
+    if (dc->postinc) {
+        tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize);
+    }
+    cris_cc_mask(dc, 0);
+    return 2;
 }
 
 static int dec_lapcq(CPUCRISState *env, DisasContext *dc)
 {
-	LOG_DIS("lapcq %x, $r%u\n",
-		    dc->pc + dc->op1*2, dc->op2);
-	cris_cc_mask(dc, 0);
-	tcg_gen_movi_tl(cpu_R[dc->op2], dc->pc + dc->op1 * 2);
-	return 2;
+    LOG_DIS("lapcq %x, $r%u\n",
+            dc->pc + dc->op1*2, dc->op2);
+    cris_cc_mask(dc, 0);
+    tcg_gen_movi_tl(cpu_R[dc->op2], dc->pc + dc->op1 * 2);
+    return 2;
 }
 
 static int dec_lapc_im(CPUCRISState *env, DisasContext *dc)
 {
-	unsigned int rd;
-	int32_t imm;
-	int32_t pc;
+    unsigned int rd;
+    int32_t imm;
+    int32_t pc;
 
-	rd = dc->op2;
+    rd = dc->op2;
 
-	cris_cc_mask(dc, 0);
-        imm = cris_fetch(env, dc, dc->pc + 2, 4, 0);
-	LOG_DIS("lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2);
+    cris_cc_mask(dc, 0);
+    imm = cris_fetch(env, dc, dc->pc + 2, 4, 0);
+    LOG_DIS("lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2);
 
-	pc = dc->pc;
-	pc += imm;
-	tcg_gen_movi_tl(cpu_R[rd], pc);
-	return 6;
+    pc = dc->pc;
+    pc += imm;
+    tcg_gen_movi_tl(cpu_R[rd], pc);
+    return 6;
 }
 
 /* Jump to special reg.  */
 static int dec_jump_p(CPUCRISState *env, DisasContext *dc)
 {
-	LOG_DIS("jump $p%u\n", dc->op2);
+    LOG_DIS("jump $p%u\n", dc->op2);
 
-	if (dc->op2 == PR_CCS)
-		cris_evaluate_flags(dc);
-	t_gen_mov_TN_preg(env_btarget, dc->op2);
-	/* rete will often have low bit set to indicate delayslot.  */
-	tcg_gen_andi_tl(env_btarget, env_btarget, ~1);
-	cris_cc_mask(dc, 0);
-	cris_prepare_jmp(dc, JMP_INDIRECT);
-	return 2;
+    if (dc->op2 == PR_CCS) {
+        cris_evaluate_flags(dc);
+    }
+    t_gen_mov_TN_preg(env_btarget, dc->op2);
+    /* rete will often have low bit set to indicate delayslot.  */
+    tcg_gen_andi_tl(env_btarget, env_btarget, ~1);
+    cris_cc_mask(dc, 0);
+    cris_prepare_jmp(dc, JMP_INDIRECT);
+    return 2;
 }
 
 /* Jump and save.  */
 static int dec_jas_r(CPUCRISState *env, DisasContext *dc)
 {
-	LOG_DIS("jas $r%u, $p%u\n", dc->op1, dc->op2);
-	cris_cc_mask(dc, 0);
-	/* Store the return address in Pd.  */
-	tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
-	if (dc->op2 > 15)
-		abort();
-	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4));
+    LOG_DIS("jas $r%u, $p%u\n", dc->op1, dc->op2);
+    cris_cc_mask(dc, 0);
+    /* Store the return address in Pd.  */
+    tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
+    if (dc->op2 > 15) {
+        abort();
+    }
+    t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4));
 
-	cris_prepare_jmp(dc, JMP_INDIRECT);
-	return 2;
+    cris_prepare_jmp(dc, JMP_INDIRECT);
+    return 2;
 }
 
 static int dec_jas_im(CPUCRISState *env, DisasContext *dc)
 {
-	uint32_t imm;
+    uint32_t imm;
 
-        imm = cris_fetch(env, dc, dc->pc + 2, 4, 0);
+    imm = cris_fetch(env, dc, dc->pc + 2, 4, 0);
 
-	LOG_DIS("jas 0x%x\n", imm);
-	cris_cc_mask(dc, 0);
-	/* Store the return address in Pd.  */
-	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
+    LOG_DIS("jas 0x%x\n", imm);
+    cris_cc_mask(dc, 0);
+    /* Store the return address in Pd.  */
+    t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
 
-	dc->jmp_pc = imm;
-	cris_prepare_jmp(dc, JMP_DIRECT);
-	return 6;
+    dc->jmp_pc = imm;
+    cris_prepare_jmp(dc, JMP_DIRECT);
+    return 6;
 }
 
 static int dec_jasc_im(CPUCRISState *env, DisasContext *dc)
 {
-	uint32_t imm;
+    uint32_t imm;
 
-        imm = cris_fetch(env, dc, dc->pc + 2, 4, 0);
+    imm = cris_fetch(env, dc, dc->pc + 2, 4, 0);
 
-	LOG_DIS("jasc 0x%x\n", imm);
-	cris_cc_mask(dc, 0);
-	/* Store the return address in Pd.  */
-	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8 + 4));
+    LOG_DIS("jasc 0x%x\n", imm);
+    cris_cc_mask(dc, 0);
+    /* Store the return address in Pd.  */
+    t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8 + 4));
 
-	dc->jmp_pc = imm;
-	cris_prepare_jmp(dc, JMP_DIRECT);
-	return 6;
+    dc->jmp_pc = imm;
+    cris_prepare_jmp(dc, JMP_DIRECT);
+    return 6;
 }
 
 static int dec_jasc_r(CPUCRISState *env, DisasContext *dc)
 {
-	LOG_DIS("jasc_r $r%u, $p%u\n", dc->op1, dc->op2);
-	cris_cc_mask(dc, 0);
-	/* Store the return address in Pd.  */
-	tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
-	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4 + 4));
-	cris_prepare_jmp(dc, JMP_INDIRECT);
-	return 2;
+    LOG_DIS("jasc_r $r%u, $p%u\n", dc->op1, dc->op2);
+    cris_cc_mask(dc, 0);
+    /* Store the return address in Pd.  */
+    tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
+    t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4 + 4));
+    cris_prepare_jmp(dc, JMP_INDIRECT);
+    return 2;
 }
 
 static int dec_bcc_im(CPUCRISState *env, DisasContext *dc)
 {
-	int32_t offset;
-	uint32_t cond = dc->op2;
+    int32_t offset;
+    uint32_t cond = dc->op2;
 
-        offset = cris_fetch(env, dc, dc->pc + 2, 2, 1);
+    offset = cris_fetch(env, dc, dc->pc + 2, 2, 1);
 
-	LOG_DIS("b%s %d pc=%x dst=%x\n",
-		    cc_name(cond), offset,
-		    dc->pc, dc->pc + offset);
+    LOG_DIS("b%s %d pc=%x dst=%x\n",
+            cc_name(cond), offset,
+            dc->pc, dc->pc + offset);
 
-	cris_cc_mask(dc, 0);
-	/* op2 holds the condition-code.  */
-	cris_prepare_cc_branch (dc, offset, cond);
-	return 4;
+    cris_cc_mask(dc, 0);
+    /* op2 holds the condition-code.  */
+    cris_prepare_cc_branch(dc, offset, cond);
+    return 4;
 }
 
 static int dec_bas_im(CPUCRISState *env, DisasContext *dc)
 {
-	int32_t simm;
+    int32_t simm;
 
+    simm = cris_fetch(env, dc, dc->pc + 2, 4, 0);
 
-        simm = cris_fetch(env, dc, dc->pc + 2, 4, 0);
+    LOG_DIS("bas 0x%x, $p%u\n", dc->pc + simm, dc->op2);
+    cris_cc_mask(dc, 0);
+    /* Store the return address in Pd.  */
+    t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
 
-	LOG_DIS("bas 0x%x, $p%u\n", dc->pc + simm, dc->op2);
-	cris_cc_mask(dc, 0);
-	/* Store the return address in Pd.  */
-	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
-
-	dc->jmp_pc = dc->pc + simm;
-	cris_prepare_jmp(dc, JMP_DIRECT);
-	return 6;
+    dc->jmp_pc = dc->pc + simm;
+    cris_prepare_jmp(dc, JMP_DIRECT);
+    return 6;
 }
 
 static int dec_basc_im(CPUCRISState *env, DisasContext *dc)
 {
-	int32_t simm;
-        simm = cris_fetch(env, dc, dc->pc + 2, 4, 0);
+    int32_t simm;
+    simm = cris_fetch(env, dc, dc->pc + 2, 4, 0);
 
-	LOG_DIS("basc 0x%x, $p%u\n", dc->pc + simm, dc->op2);
-	cris_cc_mask(dc, 0);
-	/* Store the return address in Pd.  */
-	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 12));
+    LOG_DIS("basc 0x%x, $p%u\n", dc->pc + simm, dc->op2);
+    cris_cc_mask(dc, 0);
+    /* Store the return address in Pd.  */
+    t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 12));
 
-	dc->jmp_pc = dc->pc + simm;
-	cris_prepare_jmp(dc, JMP_DIRECT);
-	return 6;
+    dc->jmp_pc = dc->pc + simm;
+    cris_prepare_jmp(dc, JMP_DIRECT);
+    return 6;
 }
 
 static int dec_rfe_etc(CPUCRISState *env, DisasContext *dc)
 {
-	cris_cc_mask(dc, 0);
+    cris_cc_mask(dc, 0);
 
-	if (dc->op2 == 15) {
-		t_gen_mov_env_TN(halted, tcg_const_tl(1));
-		tcg_gen_movi_tl(env_pc, dc->pc + 2);
-		t_gen_raise_exception(EXCP_HLT);
-		return 2;
-	}
+    if (dc->op2 == 15) {
+        t_gen_mov_env_TN(halted, tcg_const_tl(1));
+        tcg_gen_movi_tl(env_pc, dc->pc + 2);
+        t_gen_raise_exception(EXCP_HLT);
+        return 2;
+    }
 
-	switch (dc->op2 & 7) {
-		case 2:
-			/* rfe.  */
-			LOG_DIS("rfe\n");
-			cris_evaluate_flags(dc);
-                        gen_helper_rfe(cpu_env);
-			dc->is_jmp = DISAS_UPDATE;
-			break;
-		case 5:
-			/* rfn.  */
-			LOG_DIS("rfn\n");
-			cris_evaluate_flags(dc);
-                        gen_helper_rfn(cpu_env);
-			dc->is_jmp = DISAS_UPDATE;
-			break;
-		case 6:
-			LOG_DIS("break %d\n", dc->op1);
-			cris_evaluate_flags (dc);
-			/* break.  */
-			tcg_gen_movi_tl(env_pc, dc->pc + 2);
+    switch (dc->op2 & 7) {
+    case 2:
+        /* rfe.  */
+        LOG_DIS("rfe\n");
+        cris_evaluate_flags(dc);
+        gen_helper_rfe(cpu_env);
+        dc->is_jmp = DISAS_UPDATE;
+        break;
+    case 5:
+        /* rfn.  */
+        LOG_DIS("rfn\n");
+        cris_evaluate_flags(dc);
+        gen_helper_rfn(cpu_env);
+        dc->is_jmp = DISAS_UPDATE;
+        break;
+    case 6:
+        LOG_DIS("break %d\n", dc->op1);
+        cris_evaluate_flags(dc);
+        /* break.  */
+        tcg_gen_movi_tl(env_pc, dc->pc + 2);
 
-			/* Breaks start at 16 in the exception vector.  */
-			t_gen_mov_env_TN(trap_vector, 
-					 tcg_const_tl(dc->op1 + 16));
-			t_gen_raise_exception(EXCP_BREAK);
-			dc->is_jmp = DISAS_UPDATE;
-			break;
-		default:
-			printf ("op2=%x\n", dc->op2);
-			BUG();
-			break;
+        /* Breaks start at 16 in the exception vector.  */
+        t_gen_mov_env_TN(trap_vector,
+                tcg_const_tl(dc->op1 + 16));
+        t_gen_raise_exception(EXCP_BREAK);
+        dc->is_jmp = DISAS_UPDATE;
+        break;
+    default:
+        printf("op2=%x\n", dc->op2);
+        BUG();
+        break;
 
-	}
-	return 2;
+    }
+    return 2;
 }
 
 static int dec_ftag_fidx_d_m(CPUCRISState *env, DisasContext *dc)
 {
-	return 2;
+    return 2;
 }
 
 static int dec_ftag_fidx_i_m(CPUCRISState *env, DisasContext *dc)
 {
-	return 2;
+    return 2;
 }
 
 static int dec_null(CPUCRISState *env, DisasContext *dc)
 {
-	printf ("unknown insn pc=%x opc=%x op1=%x op2=%x\n",
-		dc->pc, dc->opcode, dc->op1, dc->op2);
-	fflush(NULL);
-	BUG();
-	return 2;
+    printf("unknown insn pc=%x opc=%x op1=%x op2=%x\n",
+        dc->pc, dc->opcode, dc->op1, dc->op2);
+    fflush(NULL);
+    BUG();
+    return 2;
 }
 
 static struct decoder_info {
-	struct {
-		uint32_t bits;
-		uint32_t mask;
-	};
-        int (*dec)(CPUCRISState *env, DisasContext *dc);
+    struct {
+        uint32_t bits;
+        uint32_t mask;
+    };
+    int (*dec)(CPUCRISState *env, DisasContext *dc);
 } decinfo[] = {
-	/* Order matters here.  */
-	{DEC_MOVEQ, dec_moveq},
-	{DEC_BTSTQ, dec_btstq},
-	{DEC_CMPQ, dec_cmpq},
-	{DEC_ADDOQ, dec_addoq},
-	{DEC_ADDQ, dec_addq},
-	{DEC_SUBQ, dec_subq},
-	{DEC_ANDQ, dec_andq},
-	{DEC_ORQ, dec_orq},
-	{DEC_ASRQ, dec_asrq},
-	{DEC_LSLQ, dec_lslq},
-	{DEC_LSRQ, dec_lsrq},
-	{DEC_BCCQ, dec_bccq},
+    /* Order matters here.  */
+    {DEC_MOVEQ, dec_moveq},
+    {DEC_BTSTQ, dec_btstq},
+    {DEC_CMPQ, dec_cmpq},
+    {DEC_ADDOQ, dec_addoq},
+    {DEC_ADDQ, dec_addq},
+    {DEC_SUBQ, dec_subq},
+    {DEC_ANDQ, dec_andq},
+    {DEC_ORQ, dec_orq},
+    {DEC_ASRQ, dec_asrq},
+    {DEC_LSLQ, dec_lslq},
+    {DEC_LSRQ, dec_lsrq},
+    {DEC_BCCQ, dec_bccq},
 
-	{DEC_BCC_IM, dec_bcc_im},
-	{DEC_JAS_IM, dec_jas_im},
-	{DEC_JAS_R, dec_jas_r},
-	{DEC_JASC_IM, dec_jasc_im},
-	{DEC_JASC_R, dec_jasc_r},
-	{DEC_BAS_IM, dec_bas_im},
-	{DEC_BASC_IM, dec_basc_im},
-	{DEC_JUMP_P, dec_jump_p},
-	{DEC_LAPC_IM, dec_lapc_im},
-	{DEC_LAPCQ, dec_lapcq},
+    {DEC_BCC_IM, dec_bcc_im},
+    {DEC_JAS_IM, dec_jas_im},
+    {DEC_JAS_R, dec_jas_r},
+    {DEC_JASC_IM, dec_jasc_im},
+    {DEC_JASC_R, dec_jasc_r},
+    {DEC_BAS_IM, dec_bas_im},
+    {DEC_BASC_IM, dec_basc_im},
+    {DEC_JUMP_P, dec_jump_p},
+    {DEC_LAPC_IM, dec_lapc_im},
+    {DEC_LAPCQ, dec_lapcq},
 
-	{DEC_RFE_ETC, dec_rfe_etc},
-	{DEC_ADDC_MR, dec_addc_mr},
+    {DEC_RFE_ETC, dec_rfe_etc},
+    {DEC_ADDC_MR, dec_addc_mr},
 
-	{DEC_MOVE_MP, dec_move_mp},
-	{DEC_MOVE_PM, dec_move_pm},
-	{DEC_MOVEM_MR, dec_movem_mr},
-	{DEC_MOVEM_RM, dec_movem_rm},
-	{DEC_MOVE_PR, dec_move_pr},
-	{DEC_SCC_R, dec_scc_r},
-	{DEC_SETF, dec_setclrf},
-	{DEC_CLEARF, dec_setclrf},
+    {DEC_MOVE_MP, dec_move_mp},
+    {DEC_MOVE_PM, dec_move_pm},
+    {DEC_MOVEM_MR, dec_movem_mr},
+    {DEC_MOVEM_RM, dec_movem_rm},
+    {DEC_MOVE_PR, dec_move_pr},
+    {DEC_SCC_R, dec_scc_r},
+    {DEC_SETF, dec_setclrf},
+    {DEC_CLEARF, dec_setclrf},
 
-	{DEC_MOVE_SR, dec_move_sr},
-	{DEC_MOVE_RP, dec_move_rp},
-	{DEC_SWAP_R, dec_swap_r},
-	{DEC_ABS_R, dec_abs_r},
-	{DEC_LZ_R, dec_lz_r},
-	{DEC_MOVE_RS, dec_move_rs},
-	{DEC_BTST_R, dec_btst_r},
-	{DEC_ADDC_R, dec_addc_r},
+    {DEC_MOVE_SR, dec_move_sr},
+    {DEC_MOVE_RP, dec_move_rp},
+    {DEC_SWAP_R, dec_swap_r},
+    {DEC_ABS_R, dec_abs_r},
+    {DEC_LZ_R, dec_lz_r},
+    {DEC_MOVE_RS, dec_move_rs},
+    {DEC_BTST_R, dec_btst_r},
+    {DEC_ADDC_R, dec_addc_r},
 
-	{DEC_DSTEP_R, dec_dstep_r},
-	{DEC_XOR_R, dec_xor_r},
-	{DEC_MCP_R, dec_mcp_r},
-	{DEC_CMP_R, dec_cmp_r},
+    {DEC_DSTEP_R, dec_dstep_r},
+    {DEC_XOR_R, dec_xor_r},
+    {DEC_MCP_R, dec_mcp_r},
+    {DEC_CMP_R, dec_cmp_r},
 
-	{DEC_ADDI_R, dec_addi_r},
-	{DEC_ADDI_ACR, dec_addi_acr},
+    {DEC_ADDI_R, dec_addi_r},
+    {DEC_ADDI_ACR, dec_addi_acr},
 
-	{DEC_ADD_R, dec_add_r},
-	{DEC_SUB_R, dec_sub_r},
+    {DEC_ADD_R, dec_add_r},
+    {DEC_SUB_R, dec_sub_r},
 
-	{DEC_ADDU_R, dec_addu_r},
-	{DEC_ADDS_R, dec_adds_r},
-	{DEC_SUBU_R, dec_subu_r},
-	{DEC_SUBS_R, dec_subs_r},
-	{DEC_LSL_R, dec_lsl_r},
+    {DEC_ADDU_R, dec_addu_r},
+    {DEC_ADDS_R, dec_adds_r},
+    {DEC_SUBU_R, dec_subu_r},
+    {DEC_SUBS_R, dec_subs_r},
+    {DEC_LSL_R, dec_lsl_r},
 
-	{DEC_AND_R, dec_and_r},
-	{DEC_OR_R, dec_or_r},
-	{DEC_BOUND_R, dec_bound_r},
-	{DEC_ASR_R, dec_asr_r},
-	{DEC_LSR_R, dec_lsr_r},
+    {DEC_AND_R, dec_and_r},
+    {DEC_OR_R, dec_or_r},
+    {DEC_BOUND_R, dec_bound_r},
+    {DEC_ASR_R, dec_asr_r},
+    {DEC_LSR_R, dec_lsr_r},
 
-	{DEC_MOVU_R, dec_movu_r},
-	{DEC_MOVS_R, dec_movs_r},
-	{DEC_NEG_R, dec_neg_r},
-	{DEC_MOVE_R, dec_move_r},
+    {DEC_MOVU_R, dec_movu_r},
+    {DEC_MOVS_R, dec_movs_r},
+    {DEC_NEG_R, dec_neg_r},
+    {DEC_MOVE_R, dec_move_r},
 
-	{DEC_FTAG_FIDX_I_M, dec_ftag_fidx_i_m},
-	{DEC_FTAG_FIDX_D_M, dec_ftag_fidx_d_m},
+    {DEC_FTAG_FIDX_I_M, dec_ftag_fidx_i_m},
+    {DEC_FTAG_FIDX_D_M, dec_ftag_fidx_d_m},
 
-	{DEC_MULS_R, dec_muls_r},
-	{DEC_MULU_R, dec_mulu_r},
+    {DEC_MULS_R, dec_muls_r},
+    {DEC_MULU_R, dec_mulu_r},
 
-	{DEC_ADDU_M, dec_addu_m},
-	{DEC_ADDS_M, dec_adds_m},
-	{DEC_SUBU_M, dec_subu_m},
-	{DEC_SUBS_M, dec_subs_m},
+    {DEC_ADDU_M, dec_addu_m},
+    {DEC_ADDS_M, dec_adds_m},
+    {DEC_SUBU_M, dec_subu_m},
+    {DEC_SUBS_M, dec_subs_m},
 
-	{DEC_CMPU_M, dec_cmpu_m},
-	{DEC_CMPS_M, dec_cmps_m},
-	{DEC_MOVU_M, dec_movu_m},
-	{DEC_MOVS_M, dec_movs_m},
+    {DEC_CMPU_M, dec_cmpu_m},
+    {DEC_CMPS_M, dec_cmps_m},
+    {DEC_MOVU_M, dec_movu_m},
+    {DEC_MOVS_M, dec_movs_m},
 
-	{DEC_CMP_M, dec_cmp_m},
-	{DEC_ADDO_M, dec_addo_m},
-	{DEC_BOUND_M, dec_bound_m},
-	{DEC_ADD_M, dec_add_m},
-	{DEC_SUB_M, dec_sub_m},
-	{DEC_AND_M, dec_and_m},
-	{DEC_OR_M, dec_or_m},
-	{DEC_MOVE_RM, dec_move_rm},
-	{DEC_TEST_M, dec_test_m},
-	{DEC_MOVE_MR, dec_move_mr},
+    {DEC_CMP_M, dec_cmp_m},
+    {DEC_ADDO_M, dec_addo_m},
+    {DEC_BOUND_M, dec_bound_m},
+    {DEC_ADD_M, dec_add_m},
+    {DEC_SUB_M, dec_sub_m},
+    {DEC_AND_M, dec_and_m},
+    {DEC_OR_M, dec_or_m},
+    {DEC_MOVE_RM, dec_move_rm},
+    {DEC_TEST_M, dec_test_m},
+    {DEC_MOVE_MR, dec_move_mr},
 
-	{{0, 0}, dec_null}
+    {{0, 0}, dec_null}
 };
 
 static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc)
 {
-	int insn_len = 2;
-	int i;
+    int insn_len = 2;
+    int i;
 
-	if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
-		tcg_gen_debug_insn_start(dc->pc);
+    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
+        tcg_gen_debug_insn_start(dc->pc);
         }
 
-	/* Load a halfword onto the instruction register.  */
+    /* Load a halfword onto the instruction register.  */
         dc->ir = cris_fetch(env, dc, dc->pc, 2, 0);
 
-	/* Now decode it.  */
-	dc->opcode   = EXTRACT_FIELD(dc->ir, 4, 11);
-	dc->op1      = EXTRACT_FIELD(dc->ir, 0, 3);
-	dc->op2      = EXTRACT_FIELD(dc->ir, 12, 15);
-	dc->zsize    = EXTRACT_FIELD(dc->ir, 4, 4);
-	dc->zzsize   = EXTRACT_FIELD(dc->ir, 4, 5);
-	dc->postinc  = EXTRACT_FIELD(dc->ir, 10, 10);
+    /* Now decode it.  */
+    dc->opcode   = EXTRACT_FIELD(dc->ir, 4, 11);
+    dc->op1      = EXTRACT_FIELD(dc->ir, 0, 3);
+    dc->op2      = EXTRACT_FIELD(dc->ir, 12, 15);
+    dc->zsize    = EXTRACT_FIELD(dc->ir, 4, 4);
+    dc->zzsize   = EXTRACT_FIELD(dc->ir, 4, 5);
+    dc->postinc  = EXTRACT_FIELD(dc->ir, 10, 10);
 
-	/* Large switch for all insns.  */
-	for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
-		if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits)
-		{
-                        insn_len = decinfo[i].dec(env, dc);
-			break;
-		}
-	}
+    /* Large switch for all insns.  */
+    for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
+        if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) {
+            insn_len = decinfo[i].dec(env, dc);
+            break;
+        }
+    }
 
 #if !defined(CONFIG_USER_ONLY)
-	/* Single-stepping ?  */
-	if (dc->tb_flags & S_FLAG) {
-		int l1;
+    /* Single-stepping ?  */
+    if (dc->tb_flags & S_FLAG) {
+        int l1;
 
-		l1 = gen_new_label();
-		tcg_gen_brcondi_tl(TCG_COND_NE, cpu_PR[PR_SPC], dc->pc, l1);
-		/* We treat SPC as a break with an odd trap vector.  */
-		cris_evaluate_flags (dc);
-		t_gen_mov_env_TN(trap_vector, tcg_const_tl(3));
-		tcg_gen_movi_tl(env_pc, dc->pc + insn_len);
-		tcg_gen_movi_tl(cpu_PR[PR_SPC], dc->pc + insn_len);
-		t_gen_raise_exception(EXCP_BREAK);
-		gen_set_label(l1);
-	}
+        l1 = gen_new_label();
+        tcg_gen_brcondi_tl(TCG_COND_NE, cpu_PR[PR_SPC], dc->pc, l1);
+        /* We treat SPC as a break with an odd trap vector.  */
+        cris_evaluate_flags(dc);
+        t_gen_mov_env_TN(trap_vector, tcg_const_tl(3));
+        tcg_gen_movi_tl(env_pc, dc->pc + insn_len);
+        tcg_gen_movi_tl(cpu_PR[PR_SPC], dc->pc + insn_len);
+        t_gen_raise_exception(EXCP_BREAK);
+        gen_set_label(l1);
+    }
 #endif
-	return insn_len;
+    return insn_len;
 }
 
 static void check_breakpoint(CPUCRISState *env, DisasContext *dc)
 {
-	CPUBreakpoint *bp;
+    CPUBreakpoint *bp;
 
-	if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-		QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
-			if (bp->pc == dc->pc) {
-				cris_evaluate_flags (dc);
-				tcg_gen_movi_tl(env_pc, dc->pc);
-				t_gen_raise_exception(EXCP_DEBUG);
-				dc->is_jmp = DISAS_UPDATE;
-			}
-		}
-	}
+    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
+        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+            if (bp->pc == dc->pc) {
+                cris_evaluate_flags(dc);
+                tcg_gen_movi_tl(env_pc, dc->pc);
+                t_gen_raise_exception(EXCP_DEBUG);
+                dc->is_jmp = DISAS_UPDATE;
+            }
+        }
+    }
 }
 
 #include "translate_v10.c"
@@ -3174,250 +3204,256 @@ static void
 gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
                                int search_pc)
 {
-	uint16_t *gen_opc_end;
-   	uint32_t pc_start;
-	unsigned int insn_len;
-	int j, lj;
-	struct DisasContext ctx;
-	struct DisasContext *dc = &ctx;
-	uint32_t next_page_start;
-	target_ulong npc;
-        int num_insns;
-        int max_insns;
+    uint16_t *gen_opc_end;
+    uint32_t pc_start;
+    unsigned int insn_len;
+    int j, lj;
+    struct DisasContext ctx;
+    struct DisasContext *dc = &ctx;
+    uint32_t next_page_start;
+    target_ulong npc;
+    int num_insns;
+    int max_insns;
 
-	qemu_log_try_set_file(stderr);
+    qemu_log_try_set_file(stderr);
 
-	if (env->pregs[PR_VR] == 32) {
-		dc->decoder = crisv32_decoder;
-		dc->clear_locked_irq = 0;
-	} else {
-		dc->decoder = crisv10_decoder;
-		dc->clear_locked_irq = 1;
-	}
+    if (env->pregs[PR_VR] == 32) {
+        dc->decoder = crisv32_decoder;
+        dc->clear_locked_irq = 0;
+    } else {
+        dc->decoder = crisv10_decoder;
+        dc->clear_locked_irq = 1;
+    }
 
-	/* Odd PC indicates that branch is rexecuting due to exception in the
-	 * delayslot, like in real hw.
-	 */
-	pc_start = tb->pc & ~1;
-	dc->env = env;
-	dc->tb = tb;
+    /* Odd PC indicates that branch is rexecuting due to exception in the
+     * delayslot, like in real hw.
+     */
+    pc_start = tb->pc & ~1;
+    dc->env = env;
+    dc->tb = tb;
 
-	gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
 
-	dc->is_jmp = DISAS_NEXT;
-	dc->ppc = pc_start;
-	dc->pc = pc_start;
-	dc->singlestep_enabled = env->singlestep_enabled;
-	dc->flags_uptodate = 1;
-	dc->flagx_known = 1;
-	dc->flags_x = tb->flags & X_FLAG;
-	dc->cc_x_uptodate = 0;
-	dc->cc_mask = 0;
-	dc->update_cc = 0;
-	dc->clear_prefix = 0;
+    dc->is_jmp = DISAS_NEXT;
+    dc->ppc = pc_start;
+    dc->pc = pc_start;
+    dc->singlestep_enabled = env->singlestep_enabled;
+    dc->flags_uptodate = 1;
+    dc->flagx_known = 1;
+    dc->flags_x = tb->flags & X_FLAG;
+    dc->cc_x_uptodate = 0;
+    dc->cc_mask = 0;
+    dc->update_cc = 0;
+    dc->clear_prefix = 0;
 
-	cris_update_cc_op(dc, CC_OP_FLAGS, 4);
-	dc->cc_size_uptodate = -1;
+    cris_update_cc_op(dc, CC_OP_FLAGS, 4);
+    dc->cc_size_uptodate = -1;
 
-	/* Decode TB flags.  */
-	dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG \
-					| X_FLAG | PFIX_FLAG);
-	dc->delayed_branch = !!(tb->flags & 7);
-	if (dc->delayed_branch)
-		dc->jmp = JMP_INDIRECT;
-	else
-		dc->jmp = JMP_NOJMP;
+    /* Decode TB flags.  */
+    dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG \
+            | X_FLAG | PFIX_FLAG);
+    dc->delayed_branch = !!(tb->flags & 7);
+    if (dc->delayed_branch) {
+        dc->jmp = JMP_INDIRECT;
+    } else {
+        dc->jmp = JMP_NOJMP;
+    }
 
-	dc->cpustate_changed = 0;
+    dc->cpustate_changed = 0;
 
-	if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
-		qemu_log(
-                        "srch=%d pc=%x %x flg=%" PRIx64 " bt=%x ds=%u ccs=%x\n"
-			"pid=%x usp=%x\n"
-			"%x.%x.%x.%x\n"
-			"%x.%x.%x.%x\n"
-			"%x.%x.%x.%x\n"
-			"%x.%x.%x.%x\n",
-			search_pc, dc->pc, dc->ppc,
-                        (uint64_t)tb->flags,
-			env->btarget, (unsigned)tb->flags & 7,
-			env->pregs[PR_CCS], 
-			env->pregs[PR_PID], env->pregs[PR_USP],
-			env->regs[0], env->regs[1], env->regs[2], env->regs[3],
-			env->regs[4], env->regs[5], env->regs[6], env->regs[7],
-			env->regs[8], env->regs[9],
-			env->regs[10], env->regs[11],
-			env->regs[12], env->regs[13],
-			env->regs[14], env->regs[15]);
-		qemu_log("--------------\n");
-		qemu_log("IN: %s\n", lookup_symbol(pc_start));
-	}
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+        qemu_log(
+                "srch=%d pc=%x %x flg=%" PRIx64 " bt=%x ds=%u ccs=%x\n"
+                "pid=%x usp=%x\n"
+                "%x.%x.%x.%x\n"
+                "%x.%x.%x.%x\n"
+                "%x.%x.%x.%x\n"
+                "%x.%x.%x.%x\n",
+                search_pc, dc->pc, dc->ppc,
+                (uint64_t)tb->flags,
+                env->btarget, (unsigned)tb->flags & 7,
+                env->pregs[PR_CCS],
+                env->pregs[PR_PID], env->pregs[PR_USP],
+                env->regs[0], env->regs[1], env->regs[2], env->regs[3],
+                env->regs[4], env->regs[5], env->regs[6], env->regs[7],
+                env->regs[8], env->regs[9],
+                env->regs[10], env->regs[11],
+                env->regs[12], env->regs[13],
+                env->regs[14], env->regs[15]);
+        qemu_log("--------------\n");
+        qemu_log("IN: %s\n", lookup_symbol(pc_start));
+    }
 
-	next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
-	lj = -1;
-        num_insns = 0;
-        max_insns = tb->cflags & CF_COUNT_MASK;
-        if (max_insns == 0)
-            max_insns = CF_COUNT_MASK;
+    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+    lj = -1;
+    num_insns = 0;
+    max_insns = tb->cflags & CF_COUNT_MASK;
+    if (max_insns == 0) {
+        max_insns = CF_COUNT_MASK;
+    }
 
-        gen_icount_start();
-	do
-	{
-		check_breakpoint(env, dc);
+    gen_icount_start();
+    do {
+        check_breakpoint(env, dc);
 
-		if (search_pc) {
-			j = gen_opc_ptr - gen_opc_buf;
-			if (lj < j) {
-				lj++;
-				while (lj < j)
-					gen_opc_instr_start[lj++] = 0;
-			}
-			if (dc->delayed_branch == 1)
-				gen_opc_pc[lj] = dc->ppc | 1;
-			else
-				gen_opc_pc[lj] = dc->pc;
-			gen_opc_instr_start[lj] = 1;
-                        gen_opc_icount[lj] = num_insns;
-		}
+        if (search_pc) {
+            j = gen_opc_ptr - gen_opc_buf;
+            if (lj < j) {
+                lj++;
+                while (lj < j) {
+                    gen_opc_instr_start[lj++] = 0;
+                }
+            }
+            if (dc->delayed_branch == 1) {
+                gen_opc_pc[lj] = dc->ppc | 1;
+            } else {
+                gen_opc_pc[lj] = dc->pc;
+            }
+            gen_opc_instr_start[lj] = 1;
+            gen_opc_icount[lj] = num_insns;
+        }
 
-		/* Pretty disas.  */
-		LOG_DIS("%8.8x:\t", dc->pc);
+        /* Pretty disas.  */
+        LOG_DIS("%8.8x:\t", dc->pc);
 
-                if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
-                    gen_io_start();
-		dc->clear_x = 1;
+        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+            gen_io_start();
+        }
+        dc->clear_x = 1;
 
-                insn_len = dc->decoder(env, dc);
-		dc->ppc = dc->pc;
-		dc->pc += insn_len;
-		if (dc->clear_x)
-			cris_clear_x_flag(dc);
+        insn_len = dc->decoder(env, dc);
+        dc->ppc = dc->pc;
+        dc->pc += insn_len;
+        if (dc->clear_x) {
+            cris_clear_x_flag(dc);
+        }
 
-                num_insns++;
-		/* Check for delayed branches here. If we do it before
-		   actually generating any host code, the simulator will just
-		   loop doing nothing for on this program location.  */
-		if (dc->delayed_branch) {
-			dc->delayed_branch--;
-			if (dc->delayed_branch == 0)
-			{
-				if (tb->flags & 7)
-					t_gen_mov_env_TN(dslot, 
-						tcg_const_tl(0));
-				if (dc->cpustate_changed || !dc->flagx_known
-				    || (dc->flags_x != (tb->flags & X_FLAG))) {
-					cris_store_direct_jmp(dc);
-				}
+        num_insns++;
+        /* Check for delayed branches here. If we do it before
+           actually generating any host code, the simulator will just
+           loop doing nothing for on this program location.  */
+        if (dc->delayed_branch) {
+            dc->delayed_branch--;
+            if (dc->delayed_branch == 0) {
+                if (tb->flags & 7) {
+                    t_gen_mov_env_TN(dslot, tcg_const_tl(0));
+                }
+                if (dc->cpustate_changed || !dc->flagx_known
+                    || (dc->flags_x != (tb->flags & X_FLAG))) {
+                    cris_store_direct_jmp(dc);
+                }
 
-				if (dc->clear_locked_irq) {
-					dc->clear_locked_irq = 0;
-					t_gen_mov_env_TN(locked_irq,
-							 tcg_const_tl(0));
-				}
+                if (dc->clear_locked_irq) {
+                    dc->clear_locked_irq = 0;
+                    t_gen_mov_env_TN(locked_irq, tcg_const_tl(0));
+                }
 
-				if (dc->jmp == JMP_DIRECT_CC) {
-					int l1;
+                if (dc->jmp == JMP_DIRECT_CC) {
+                    int l1;
 
-					l1 = gen_new_label();
-					cris_evaluate_flags(dc);
+                    l1 = gen_new_label();
+                    cris_evaluate_flags(dc);
 
-					/* Conditional jmp.  */
-					tcg_gen_brcondi_tl(TCG_COND_EQ,
-							   env_btaken, 0, l1);
-					gen_goto_tb(dc, 1, dc->jmp_pc);
-					gen_set_label(l1);
-					gen_goto_tb(dc, 0, dc->pc);
-					dc->is_jmp = DISAS_TB_JUMP;
-					dc->jmp = JMP_NOJMP;
-				} else if (dc->jmp == JMP_DIRECT) {
-					cris_evaluate_flags(dc);
-					gen_goto_tb(dc, 0, dc->jmp_pc);
-					dc->is_jmp = DISAS_TB_JUMP;
-					dc->jmp = JMP_NOJMP;
-				} else {
-					t_gen_cc_jmp(env_btarget, 
-						     tcg_const_tl(dc->pc));
-					dc->is_jmp = DISAS_JUMP;
-				}
-				break;
-			}
-		}
+                    /* Conditional jmp.  */
+                    tcg_gen_brcondi_tl(TCG_COND_EQ,
+                               env_btaken, 0, l1);
+                    gen_goto_tb(dc, 1, dc->jmp_pc);
+                    gen_set_label(l1);
+                    gen_goto_tb(dc, 0, dc->pc);
+                    dc->is_jmp = DISAS_TB_JUMP;
+                    dc->jmp = JMP_NOJMP;
+                } else if (dc->jmp == JMP_DIRECT) {
+                    cris_evaluate_flags(dc);
+                    gen_goto_tb(dc, 0, dc->jmp_pc);
+                    dc->is_jmp = DISAS_TB_JUMP;
+                    dc->jmp = JMP_NOJMP;
+                } else {
+                    t_gen_cc_jmp(env_btarget, tcg_const_tl(dc->pc));
+                    dc->is_jmp = DISAS_JUMP;
+                }
+                break;
+            }
+        }
 
-		/* If we are rexecuting a branch due to exceptions on
-		   delay slots dont break.  */
-		if (!(tb->pc & 1) && env->singlestep_enabled)
-			break;
-	} while (!dc->is_jmp && !dc->cpustate_changed
-		 && gen_opc_ptr < gen_opc_end
-                 && !singlestep
-		 && (dc->pc < next_page_start)
-                 && num_insns < max_insns);
+        /* If we are rexecuting a branch due to exceptions on
+           delay slots dont break.  */
+        if (!(tb->pc & 1) && env->singlestep_enabled) {
+            break;
+        }
+    } while (!dc->is_jmp && !dc->cpustate_changed
+            && gen_opc_ptr < gen_opc_end
+            && !singlestep
+            && (dc->pc < next_page_start)
+            && num_insns < max_insns);
 
-	if (dc->clear_locked_irq)
-		t_gen_mov_env_TN(locked_irq, tcg_const_tl(0));
+    if (dc->clear_locked_irq) {
+        t_gen_mov_env_TN(locked_irq, tcg_const_tl(0));
+    }
 
-	npc = dc->pc;
+    npc = dc->pc;
 
         if (tb->cflags & CF_LAST_IO)
             gen_io_end();
-	/* Force an update if the per-tb cpu state has changed.  */
-	if (dc->is_jmp == DISAS_NEXT
-	    && (dc->cpustate_changed || !dc->flagx_known 
-	    || (dc->flags_x != (tb->flags & X_FLAG)))) {
-		dc->is_jmp = DISAS_UPDATE;
-		tcg_gen_movi_tl(env_pc, npc);
-	}
-	/* Broken branch+delayslot sequence.  */
-	if (dc->delayed_branch == 1) {
-		/* Set env->dslot to the size of the branch insn.  */
-		t_gen_mov_env_TN(dslot, tcg_const_tl(dc->pc - dc->ppc));
-		cris_store_direct_jmp(dc);
-	}
+    /* Force an update if the per-tb cpu state has changed.  */
+    if (dc->is_jmp == DISAS_NEXT
+        && (dc->cpustate_changed || !dc->flagx_known
+        || (dc->flags_x != (tb->flags & X_FLAG)))) {
+        dc->is_jmp = DISAS_UPDATE;
+        tcg_gen_movi_tl(env_pc, npc);
+    }
+    /* Broken branch+delayslot sequence.  */
+    if (dc->delayed_branch == 1) {
+        /* Set env->dslot to the size of the branch insn.  */
+        t_gen_mov_env_TN(dslot, tcg_const_tl(dc->pc - dc->ppc));
+        cris_store_direct_jmp(dc);
+    }
 
-	cris_evaluate_flags (dc);
+    cris_evaluate_flags(dc);
 
-	if (unlikely(env->singlestep_enabled)) {
-		if (dc->is_jmp == DISAS_NEXT)
-			tcg_gen_movi_tl(env_pc, npc);
-		t_gen_raise_exception(EXCP_DEBUG);
-	} else {
-		switch(dc->is_jmp) {
-			case DISAS_NEXT:
-				gen_goto_tb(dc, 1, npc);
-				break;
-			default:
-			case DISAS_JUMP:
-			case DISAS_UPDATE:
-				/* indicate that the hash table must be used
-				   to find the next TB */
-				tcg_gen_exit_tb(0);
-				break;
-			case DISAS_SWI:
-			case DISAS_TB_JUMP:
-				/* nothing more to generate */
-				break;
-		}
-	}
-        gen_icount_end(tb, num_insns);
-	*gen_opc_ptr = INDEX_op_end;
-	if (search_pc) {
-		j = gen_opc_ptr - gen_opc_buf;
-		lj++;
-		while (lj <= j)
-			gen_opc_instr_start[lj++] = 0;
-	} else {
-		tb->size = dc->pc - pc_start;
-                tb->icount = num_insns;
-	}
+    if (unlikely(env->singlestep_enabled)) {
+        if (dc->is_jmp == DISAS_NEXT) {
+            tcg_gen_movi_tl(env_pc, npc);
+        }
+        t_gen_raise_exception(EXCP_DEBUG);
+    } else {
+        switch (dc->is_jmp) {
+        case DISAS_NEXT:
+            gen_goto_tb(dc, 1, npc);
+            break;
+        default:
+        case DISAS_JUMP:
+        case DISAS_UPDATE:
+            /* indicate that the hash table must be used
+                   to find the next TB */
+            tcg_gen_exit_tb(0);
+            break;
+        case DISAS_SWI:
+        case DISAS_TB_JUMP:
+            /* nothing more to generate */
+            break;
+        }
+    }
+    gen_icount_end(tb, num_insns);
+    *gen_opc_ptr = INDEX_op_end;
+    if (search_pc) {
+        j = gen_opc_ptr - gen_opc_buf;
+        lj++;
+        while (lj <= j) {
+            gen_opc_instr_start[lj++] = 0;
+        }
+    } else {
+        tb->size = dc->pc - pc_start;
+        tb->icount = num_insns;
+    }
 
 #ifdef DEBUG_DISAS
 #if !DISAS_CRIS
-	if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
-                log_target_disas(env, pc_start, dc->pc - pc_start,
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+        log_target_disas(env, pc_start, dc->pc - pc_start,
                                  dc->env->pregs[PR_VR]);
-		qemu_log("\nisize=%d osize=%td\n",
-			dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
-	}
+        qemu_log("\nisize=%d osize=%td\n",
+            dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
+    }
 #endif
 #endif
 }
@@ -3435,41 +3471,45 @@ void gen_intermediate_code_pc (CPUCRISState *env, struct TranslationBlock *tb)
 void cpu_dump_state (CPUCRISState *env, FILE *f, fprintf_function cpu_fprintf,
                      int flags)
 {
-	int i;
-	uint32_t srs;
+    int i;
+    uint32_t srs;
 
-	if (!env || !f)
-		return;
+    if (!env || !f) {
+        return;
+    }
 
-	cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n"
-		    "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n",
-		    env->pc, env->pregs[PR_CCS], env->btaken, env->btarget,
-		    env->cc_op,
-		    env->cc_src, env->cc_dest, env->cc_result, env->cc_mask);
+    cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n"
+            "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n",
+            env->pc, env->pregs[PR_CCS], env->btaken, env->btarget,
+            env->cc_op,
+            env->cc_src, env->cc_dest, env->cc_result, env->cc_mask);
 
 
-	for (i = 0; i < 16; i++) {
-		cpu_fprintf(f, "%s=%8.8x ",regnames[i], env->regs[i]);
-		if ((i + 1) % 4 == 0)
-			cpu_fprintf(f, "\n");
-	}
-	cpu_fprintf(f, "\nspecial regs:\n");
-	for (i = 0; i < 16; i++) {
-		cpu_fprintf(f, "%s=%8.8x ", pregnames[i], env->pregs[i]);
-		if ((i + 1) % 4 == 0)
-			cpu_fprintf(f, "\n");
-	}
-	srs = env->pregs[PR_SRS];
-	cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs);
-	if (srs < ARRAY_SIZE(env->sregs)) {
-		for (i = 0; i < 16; i++) {
-			cpu_fprintf(f, "s%2.2d=%8.8x ",
-				    i, env->sregs[srs][i]);
-			if ((i + 1) % 4 == 0)
-				cpu_fprintf(f, "\n");
-		}
-	}
-	cpu_fprintf(f, "\n\n");
+    for (i = 0; i < 16; i++) {
+        cpu_fprintf(f, "%s=%8.8x ", regnames[i], env->regs[i]);
+        if ((i + 1) % 4 == 0) {
+            cpu_fprintf(f, "\n");
+        }
+    }
+    cpu_fprintf(f, "\nspecial regs:\n");
+    for (i = 0; i < 16; i++) {
+        cpu_fprintf(f, "%s=%8.8x ", pregnames[i], env->pregs[i]);
+        if ((i + 1) % 4 == 0) {
+            cpu_fprintf(f, "\n");
+        }
+    }
+    srs = env->pregs[PR_SRS];
+    cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs);
+    if (srs < ARRAY_SIZE(env->sregs)) {
+        for (i = 0; i < 16; i++) {
+            cpu_fprintf(f, "s%2.2d=%8.8x ",
+                    i, env->sregs[srs][i]);
+            if ((i + 1) % 4 == 0) {
+                cpu_fprintf(f, "\n");
+            }
+        }
+    }
+    cpu_fprintf(f, "\n\n");
 
 }
 
@@ -3478,11 +3518,11 @@ struct
     uint32_t vr;
     const char *name;
 } cris_cores[] = {
-	{8, "crisv8"},
-	{9, "crisv9"},
-	{10, "crisv10"},
-	{11, "crisv11"},
-	{32, "crisv32"},
+    {8, "crisv8"},
+    {9, "crisv9"},
+    {10, "crisv10"},
+    {11, "crisv11"},
+    {32, "crisv32"},
 };
 
 void cris_cpu_list(FILE *f, fprintf_function cpu_fprintf)
@@ -3581,5 +3621,5 @@ CRISCPU *cpu_cris_init(const char *cpu_model)
 
 void restore_state_to_opc(CPUCRISState *env, TranslationBlock *tb, int pc_pos)
 {
-	env->pc = gen_opc_pc[pc_pos];
+    env->pc = gen_opc_pc[pc_pos];
 }

From 8232a46a165c20fdc8f6bb2d06c71be55afce051 Mon Sep 17 00:00:00 2001
From: Evgeny Voevodin 
Date: Mon, 12 Nov 2012 13:27:44 +0400
Subject: [PATCH 1672/2270] tcg/tcg.h: Duplicate global TCG variables in
 TCGContext

Signed-off-by: Evgeny Voevodin 
Reviewed-by: Richard Henderson 
Signed-off-by: Blue Swirl 
---
 tcg/tcg.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tcg/tcg.h b/tcg/tcg.h
index c2ae873715..6ffec1d47a 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -450,6 +450,12 @@ struct TCGContext {
     int goto_tb_issue_mask;
 #endif
 
+    uint16_t gen_opc_buf[OPC_BUF_SIZE];
+    TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE];
+
+    uint16_t *gen_opc_ptr;
+    TCGArg *gen_opparam_ptr;
+
 #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
     /* labels info for qemu_ld/st IRs
        The labels help to generate TLB miss case codes at the end of TB */

From efd7f48600e0e7803765d7b31cea131aae2b7329 Mon Sep 17 00:00:00 2001
From: Evgeny Voevodin 
Date: Mon, 12 Nov 2012 13:27:45 +0400
Subject: [PATCH 1673/2270] TCG: Use gen_opc_ptr from context instead of global
 variable.

Signed-off-by: Evgeny Voevodin 
Reviewed-by: Richard Henderson 
Signed-off-by: Blue Swirl 
---
 target-alpha/translate.c      |  8 ++--
 target-arm/translate.c        |  8 ++--
 target-cris/translate.c       | 10 ++---
 target-i386/translate.c       |  8 ++--
 target-lm32/translate.c       | 10 ++---
 target-m68k/translate.c       |  8 ++--
 target-microblaze/translate.c | 10 ++---
 target-mips/translate.c       |  9 +++--
 target-openrisc/translate.c   | 10 ++---
 target-ppc/translate.c        |  9 +++--
 target-s390x/translate.c      |  9 +++--
 target-sh4/translate.c        |  8 ++--
 target-sparc/translate.c      |  8 ++--
 target-unicore32/translate.c  |  8 ++--
 target-xtensa/translate.c     |  6 +--
 tcg/tcg-op.h                  | 70 +++++++++++++++++------------------
 tcg/tcg.c                     | 16 ++++----
 17 files changed, 109 insertions(+), 106 deletions(-)

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 8c4dd021f3..f160f83ffe 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3406,7 +3406,7 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
             }
         }
         if (search_pc) {
-            j = gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j)
@@ -3432,7 +3432,7 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
            or exhaust instruction count, stop generation.  */
         if (ret == NO_EXIT
             && ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0
-                || gen_opc_ptr >= gen_opc_end
+                || tcg_ctx.gen_opc_ptr >= gen_opc_end
                 || num_insns >= max_insns
                 || singlestep
                 || env->singlestep_enabled)) {
@@ -3463,9 +3463,9 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
     }
 
     gen_icount_end(tb, num_insns);
-    *gen_opc_ptr = INDEX_op_end;
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
-        j = gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 7d8f8e5edc..014f3582b9 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9834,7 +9834,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
             }
         }
         if (search_pc) {
-            j = gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j)
@@ -9881,7 +9881,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
          * Also stop translation when a page boundary is reached.  This
          * ensures prefetch aborts occur at the right place.  */
         num_insns ++;
-    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
+    } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
              !env->singlestep_enabled &&
              !singlestep &&
              dc->pc < next_page_start &&
@@ -9962,7 +9962,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
 
 done_generating:
     gen_icount_end(tb, num_insns);
-    *gen_opc_ptr = INDEX_op_end;
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
 
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -9974,7 +9974,7 @@ done_generating:
     }
 #endif
     if (search_pc) {
-        j = gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 023980ec56..02969d4d53 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3297,7 +3297,7 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
         check_breakpoint(env, dc);
 
         if (search_pc) {
-            j = gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j) {
@@ -3381,7 +3381,7 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
             break;
         }
     } while (!dc->is_jmp && !dc->cpustate_changed
-            && gen_opc_ptr < gen_opc_end
+            && tcg_ctx.gen_opc_ptr < gen_opc_end
             && !singlestep
             && (dc->pc < next_page_start)
             && num_insns < max_insns);
@@ -3434,9 +3434,9 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
         }
     }
     gen_icount_end(tb, num_insns);
-    *gen_opc_ptr = INDEX_op_end;
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
-        j = gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
         lj++;
         while (lj <= j) {
             gen_opc_instr_start[lj++] = 0;
@@ -3452,7 +3452,7 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
         log_target_disas(env, pc_start, dc->pc - pc_start,
                                  dc->env->pregs[PR_VR]);
         qemu_log("\nisize=%d osize=%td\n",
-            dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
+            dc->pc - pc_start, tcg_ctx.gen_opc_ptr - gen_opc_buf);
     }
 #endif
 #endif
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 7fdb8bcbbe..2658bf29c9 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7984,7 +7984,7 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
             }
         }
         if (search_pc) {
-            j = gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j)
@@ -8015,7 +8015,7 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
             break;
         }
         /* if too long translation, stop generation too */
-        if (gen_opc_ptr >= gen_opc_end ||
+        if (tcg_ctx.gen_opc_ptr >= gen_opc_end ||
             (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
             num_insns >= max_insns) {
             gen_jmp_im(pc_ptr - dc->cs_base);
@@ -8031,10 +8031,10 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
     gen_icount_end(tb, num_insns);
-    *gen_opc_ptr = INDEX_op_end;
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     /* we don't forget to fill the last values */
     if (search_pc) {
-        j = gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index 3307daaf11..8c2a6181d8 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -1047,7 +1047,7 @@ static void gen_intermediate_code_internal(CPULM32State *env,
         check_breakpoint(env, dc);
 
         if (search_pc) {
-            j = gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j) {
@@ -1071,7 +1071,7 @@ static void gen_intermediate_code_internal(CPULM32State *env,
         num_insns++;
 
     } while (!dc->is_jmp
-         && gen_opc_ptr < gen_opc_end
+         && tcg_ctx.gen_opc_ptr < gen_opc_end
          && !env->singlestep_enabled
          && !singlestep
          && (dc->pc < next_page_start)
@@ -1105,9 +1105,9 @@ static void gen_intermediate_code_internal(CPULM32State *env,
     }
 
     gen_icount_end(tb, num_insns);
-    *gen_opc_ptr = INDEX_op_end;
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
-        j = gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
         lj++;
         while (lj <= j) {
             gen_opc_instr_start[lj++] = 0;
@@ -1122,7 +1122,7 @@ static void gen_intermediate_code_internal(CPULM32State *env,
         qemu_log("\n");
         log_target_disas(env, pc_start, dc->pc - pc_start, 0);
         qemu_log("\nisize=%d osize=%td\n",
-            dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
+            dc->pc - pc_start, tcg_ctx.gen_opc_ptr - gen_opc_buf);
     }
 #endif
 }
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 1430d4c991..ede3536dc4 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3015,7 +3015,7 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
                 break;
         }
         if (search_pc) {
-            j = gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j)
@@ -3030,7 +3030,7 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
         dc->insn_pc = dc->pc;
 	disas_m68k_insn(env, dc);
         num_insns++;
-    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
+    } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
              !env->singlestep_enabled &&
              !singlestep &&
              (pc_offset) < (TARGET_PAGE_SIZE - 32) &&
@@ -3064,7 +3064,7 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
         }
     }
     gen_icount_end(tb, num_insns);
-    *gen_opc_ptr = INDEX_op_end;
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
 
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -3075,7 +3075,7 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
     }
 #endif
     if (search_pc) {
-        j = gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 13fd73574b..a84c22ee0f 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1784,7 +1784,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
         check_breakpoint(env, dc);
 
         if (search_pc) {
-            j = gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j)
@@ -1846,7 +1846,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
         if (env->singlestep_enabled)
             break;
     } while (!dc->is_jmp && !dc->cpustate_changed
-         && gen_opc_ptr < gen_opc_end
+         && tcg_ctx.gen_opc_ptr < gen_opc_end
                  && !singlestep
          && (dc->pc < next_page_start)
                  && num_insns < max_insns);
@@ -1897,9 +1897,9 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
         }
     }
     gen_icount_end(tb, num_insns);
-    *gen_opc_ptr = INDEX_op_end;
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
-        j = gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
@@ -1916,7 +1916,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
         log_target_disas(env, pc_start, dc->pc - pc_start, 0);
 #endif
         qemu_log("\nisize=%d osize=%td\n",
-            dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
+            dc->pc - pc_start, tcg_ctx.gen_opc_ptr - gen_opc_buf);
     }
 #endif
 #endif
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 01b48fa2a2..cc126f5382 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15549,7 +15549,7 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
         }
 
         if (search_pc) {
-            j = gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j)
@@ -15597,8 +15597,9 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
         if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
             break;
 
-        if (gen_opc_ptr >= gen_opc_end)
+        if (tcg_ctx.gen_opc_ptr >= gen_opc_end) {
             break;
+        }
 
         if (num_insns >= max_insns)
             break;
@@ -15630,9 +15631,9 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
     }
 done_generating:
     gen_icount_end(tb, num_insns);
-    *gen_opc_ptr = INDEX_op_end;
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
-        j = gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index ff2feb48db..eba134e0b7 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1703,7 +1703,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
     do {
         check_breakpoint(cpu, dc);
         if (search_pc) {
-            j = gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
             if (k < j) {
                 k++;
                 while (k < j) {
@@ -1744,7 +1744,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
             }
         }
     } while (!dc->is_jmp
-             && gen_opc_ptr < gen_opc_end
+             && tcg_ctx.gen_opc_ptr < gen_opc_end
              && !cpu->env.singlestep_enabled
              && !singlestep
              && (dc->pc < next_page_start)
@@ -1782,9 +1782,9 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
     }
 
     gen_icount_end(tb, num_insns);
-    *gen_opc_ptr = INDEX_op_end;
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
-        j = gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
         k++;
         while (k <= j) {
             gen_opc_instr_start[k++] = 0;
@@ -1799,7 +1799,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
         qemu_log("\n");
         log_target_disas(&cpu->env, pc_start, dc->pc - pc_start, 0);
         qemu_log("\nisize=%d osize=%td\n",
-            dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
+            dc->pc - pc_start, tcg_ctx.gen_opc_ptr - gen_opc_buf);
     }
 #endif
 }
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index f0d49eea3f..b2a8374e61 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9664,7 +9664,8 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
 
     gen_icount_start();
     /* Set env in case of segfault during code fetch */
-    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
+    while (ctx.exception == POWERPC_EXCP_NONE
+            && tcg_ctx.gen_opc_ptr < gen_opc_end) {
         if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
             QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
                 if (bp->pc == ctx.nip) {
@@ -9674,7 +9675,7 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
             }
         }
         if (unlikely(search_pc)) {
-            j = gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j)
@@ -9774,9 +9775,9 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
         tcg_gen_exit_tb(0);
     }
     gen_icount_end(tb, num_insns);
-    *gen_opc_ptr = INDEX_op_end;
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (unlikely(search_pc)) {
-        j = gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index c6267a8769..945cc51aaf 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -5156,7 +5156,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
             }
         }
         if (search_pc) {
-            j = gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j) {
@@ -5182,7 +5182,8 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
         if (env->singlestep_enabled) {
             gen_debug(&dc);
         }
-    } while (!dc.is_jmp && gen_opc_ptr < gen_opc_end && dc.pc < next_page_start
+    } while (!dc.is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end
+             && dc.pc < next_page_start
              && num_insns < max_insns && !env->singlestep_enabled
              && !singlestep);
 
@@ -5206,9 +5207,9 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
         tcg_gen_exit_tb(0);
     }
     gen_icount_end(tb, num_insns);
-    *gen_opc_ptr = INDEX_op_end;
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
-        j = gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
         lj++;
         while (lj <= j) {
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 2ae7f03d35..b43e6c28dc 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -1986,7 +1986,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
     if (max_insns == 0)
         max_insns = CF_COUNT_MASK;
     gen_icount_start();
-    while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
+    while (ctx.bstate == BS_NONE && tcg_ctx.gen_opc_ptr < gen_opc_end) {
         if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
             QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
                 if (ctx.pc == bp->pc) {
@@ -1999,7 +1999,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
 	    }
 	}
         if (search_pc) {
-            i = gen_opc_ptr - gen_opc_buf;
+            i = tcg_ctx.gen_opc_ptr - gen_opc_buf;
             if (ii < i) {
                 ii++;
                 while (ii < i)
@@ -2056,9 +2056,9 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
     }
 
     gen_icount_end(tb, num_insns);
-    *gen_opc_ptr = INDEX_op_end;
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
-        i = gen_opc_ptr - gen_opc_buf;
+        i = tcg_ctx.gen_opc_ptr - gen_opc_buf;
         ii++;
         while (ii <= i)
             gen_opc_instr_start[ii++] = 0;
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 1d8b8ad9b9..47bbc91426 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5279,7 +5279,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
         }
         if (spc) {
             qemu_log("Search PC...\n");
-            j = gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j)
@@ -5312,7 +5312,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
         if (dc->singlestep) {
             break;
         }
-    } while ((gen_opc_ptr < gen_opc_end) &&
+    } while ((tcg_ctx.gen_opc_ptr < gen_opc_end) &&
              (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) &&
              num_insns < max_insns);
 
@@ -5334,9 +5334,9 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
         }
     }
     gen_icount_end(tb, num_insns);
-    *gen_opc_ptr = INDEX_op_end;
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (spc) {
-        j = gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index 57b18ac0c6..d6bb6696ab 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -1999,7 +1999,7 @@ static inline void gen_intermediate_code_internal(CPUUniCore32State *env,
             }
         }
         if (search_pc) {
-            j = gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j) {
@@ -2031,7 +2031,7 @@ static inline void gen_intermediate_code_internal(CPUUniCore32State *env,
          * Also stop translation when a page boundary is reached.  This
          * ensures prefetch aborts occur at the right place.  */
         num_insns++;
-    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
+    } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
              !env->singlestep_enabled &&
              !singlestep &&
              dc->pc < next_page_start &&
@@ -2103,7 +2103,7 @@ static inline void gen_intermediate_code_internal(CPUUniCore32State *env,
 
 done_generating:
     gen_icount_end(tb, num_insns);
-    *gen_opc_ptr = INDEX_op_end;
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
 
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -2114,7 +2114,7 @@ done_generating:
     }
 #endif
     if (search_pc) {
-        j = gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
         lj++;
         while (lj <= j) {
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 3c03775a76..f272eac56d 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -2893,7 +2893,7 @@ static void gen_intermediate_code_internal(
         check_breakpoint(env, &dc);
 
         if (search_pc) {
-            j = gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j) {
@@ -2944,7 +2944,7 @@ static void gen_intermediate_code_internal(
     } while (dc.is_jmp == DISAS_NEXT &&
             insn_count < max_insns &&
             dc.pc < next_page_start &&
-            gen_opc_ptr < gen_opc_end);
+            tcg_ctx.gen_opc_ptr < gen_opc_end);
 
     reset_litbase(&dc);
     reset_sar_tracker(&dc);
@@ -2960,7 +2960,7 @@ static void gen_intermediate_code_internal(
         gen_jumpi(&dc, dc.pc, 0);
     }
     gen_icount_end(tb, insn_count);
-    *gen_opc_ptr = INDEX_op_end;
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
 
     if (!search_pc) {
         tb->size = dc.pc - pc_start;
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 8d1da2b670..9bc890fd6f 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -27,58 +27,58 @@ int gen_new_label(void);
 
 static inline void tcg_gen_op0(TCGOpcode opc)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
 }
 
 static inline void tcg_gen_op1_i32(TCGOpcode opc, TCGv_i32 arg1)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
 }
 
 static inline void tcg_gen_op1_i64(TCGOpcode opc, TCGv_i64 arg1)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
 }
 
 static inline void tcg_gen_op1i(TCGOpcode opc, TCGArg arg1)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = arg1;
 }
 
 static inline void tcg_gen_op2_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
 }
 
 static inline void tcg_gen_op2_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
 }
 
 static inline void tcg_gen_op2i_i32(TCGOpcode opc, TCGv_i32 arg1, TCGArg arg2)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
     *gen_opparam_ptr++ = arg2;
 }
 
 static inline void tcg_gen_op2i_i64(TCGOpcode opc, TCGv_i64 arg1, TCGArg arg2)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
     *gen_opparam_ptr++ = arg2;
 }
 
 static inline void tcg_gen_op2ii(TCGOpcode opc, TCGArg arg1, TCGArg arg2)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = arg1;
     *gen_opparam_ptr++ = arg2;
 }
@@ -86,7 +86,7 @@ static inline void tcg_gen_op2ii(TCGOpcode opc, TCGArg arg1, TCGArg arg2)
 static inline void tcg_gen_op3_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                    TCGv_i32 arg3)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
@@ -95,7 +95,7 @@ static inline void tcg_gen_op3_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
 static inline void tcg_gen_op3_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
                                    TCGv_i64 arg3)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
@@ -104,7 +104,7 @@ static inline void tcg_gen_op3_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
 static inline void tcg_gen_op3i_i32(TCGOpcode opc, TCGv_i32 arg1,
                                     TCGv_i32 arg2, TCGArg arg3)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
     *gen_opparam_ptr++ = arg3;
@@ -113,7 +113,7 @@ static inline void tcg_gen_op3i_i32(TCGOpcode opc, TCGv_i32 arg1,
 static inline void tcg_gen_op3i_i64(TCGOpcode opc, TCGv_i64 arg1,
                                     TCGv_i64 arg2, TCGArg arg3)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
     *gen_opparam_ptr++ = arg3;
@@ -122,7 +122,7 @@ static inline void tcg_gen_op3i_i64(TCGOpcode opc, TCGv_i64 arg1,
 static inline void tcg_gen_ldst_op_i32(TCGOpcode opc, TCGv_i32 val,
                                        TCGv_ptr base, TCGArg offset)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I32(val);
     *gen_opparam_ptr++ = GET_TCGV_PTR(base);
     *gen_opparam_ptr++ = offset;
@@ -131,7 +131,7 @@ static inline void tcg_gen_ldst_op_i32(TCGOpcode opc, TCGv_i32 val,
 static inline void tcg_gen_ldst_op_i64(TCGOpcode opc, TCGv_i64 val,
                                        TCGv_ptr base, TCGArg offset)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(val);
     *gen_opparam_ptr++ = GET_TCGV_PTR(base);
     *gen_opparam_ptr++ = offset;
@@ -140,7 +140,7 @@ static inline void tcg_gen_ldst_op_i64(TCGOpcode opc, TCGv_i64 val,
 static inline void tcg_gen_qemu_ldst_op_i64_i32(TCGOpcode opc, TCGv_i64 val,
                                                 TCGv_i32 addr, TCGArg mem_index)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(val);
     *gen_opparam_ptr++ = GET_TCGV_I32(addr);
     *gen_opparam_ptr++ = mem_index;
@@ -149,7 +149,7 @@ static inline void tcg_gen_qemu_ldst_op_i64_i32(TCGOpcode opc, TCGv_i64 val,
 static inline void tcg_gen_qemu_ldst_op_i64_i64(TCGOpcode opc, TCGv_i64 val,
                                                 TCGv_i64 addr, TCGArg mem_index)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(val);
     *gen_opparam_ptr++ = GET_TCGV_I64(addr);
     *gen_opparam_ptr++ = mem_index;
@@ -158,7 +158,7 @@ static inline void tcg_gen_qemu_ldst_op_i64_i64(TCGOpcode opc, TCGv_i64 val,
 static inline void tcg_gen_op4_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                    TCGv_i32 arg3, TCGv_i32 arg4)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
@@ -168,7 +168,7 @@ static inline void tcg_gen_op4_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
 static inline void tcg_gen_op4_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
                                    TCGv_i64 arg3, TCGv_i64 arg4)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
@@ -178,7 +178,7 @@ static inline void tcg_gen_op4_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
 static inline void tcg_gen_op4i_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                     TCGv_i32 arg3, TCGArg arg4)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
@@ -188,7 +188,7 @@ static inline void tcg_gen_op4i_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
 static inline void tcg_gen_op4i_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
                                     TCGv_i64 arg3, TCGArg arg4)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
@@ -198,7 +198,7 @@ static inline void tcg_gen_op4i_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
 static inline void tcg_gen_op4ii_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                      TCGArg arg3, TCGArg arg4)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
     *gen_opparam_ptr++ = arg3;
@@ -208,7 +208,7 @@ static inline void tcg_gen_op4ii_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2
 static inline void tcg_gen_op4ii_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
                                      TCGArg arg3, TCGArg arg4)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
     *gen_opparam_ptr++ = arg3;
@@ -218,7 +218,7 @@ static inline void tcg_gen_op4ii_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2
 static inline void tcg_gen_op5_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                    TCGv_i32 arg3, TCGv_i32 arg4, TCGv_i32 arg5)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
@@ -229,7 +229,7 @@ static inline void tcg_gen_op5_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
 static inline void tcg_gen_op5_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
                                    TCGv_i64 arg3, TCGv_i64 arg4, TCGv_i64 arg5)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
@@ -240,7 +240,7 @@ static inline void tcg_gen_op5_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
 static inline void tcg_gen_op5i_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                     TCGv_i32 arg3, TCGv_i32 arg4, TCGArg arg5)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
@@ -251,7 +251,7 @@ static inline void tcg_gen_op5i_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
 static inline void tcg_gen_op5i_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
                                     TCGv_i64 arg3, TCGv_i64 arg4, TCGArg arg5)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
@@ -263,7 +263,7 @@ static inline void tcg_gen_op5ii_i32(TCGOpcode opc, TCGv_i32 arg1,
                                      TCGv_i32 arg2, TCGv_i32 arg3,
                                      TCGArg arg4, TCGArg arg5)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
@@ -275,7 +275,7 @@ static inline void tcg_gen_op5ii_i64(TCGOpcode opc, TCGv_i64 arg1,
                                      TCGv_i64 arg2, TCGv_i64 arg3,
                                      TCGArg arg4, TCGArg arg5)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
@@ -287,7 +287,7 @@ static inline void tcg_gen_op6_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                    TCGv_i32 arg3, TCGv_i32 arg4, TCGv_i32 arg5,
                                    TCGv_i32 arg6)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
@@ -300,7 +300,7 @@ static inline void tcg_gen_op6_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
                                    TCGv_i64 arg3, TCGv_i64 arg4, TCGv_i64 arg5,
                                    TCGv_i64 arg6)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
@@ -313,7 +313,7 @@ static inline void tcg_gen_op6i_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                     TCGv_i32 arg3, TCGv_i32 arg4,
                                     TCGv_i32 arg5, TCGArg arg6)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
@@ -326,7 +326,7 @@ static inline void tcg_gen_op6i_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
                                     TCGv_i64 arg3, TCGv_i64 arg4,
                                     TCGv_i64 arg5, TCGArg arg6)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
@@ -339,7 +339,7 @@ static inline void tcg_gen_op6ii_i32(TCGOpcode opc, TCGv_i32 arg1,
                                      TCGv_i32 arg2, TCGv_i32 arg3,
                                      TCGv_i32 arg4, TCGArg arg5, TCGArg arg6)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
@@ -352,7 +352,7 @@ static inline void tcg_gen_op6ii_i64(TCGOpcode opc, TCGv_i64 arg1,
                                      TCGv_i64 arg2, TCGv_i64 arg3,
                                      TCGv_i64 arg4, TCGArg arg5, TCGArg arg6)
 {
-    *gen_opc_ptr++ = opc;
+    *tcg_ctx.gen_opc_ptr++ = opc;
     *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
     *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 35fba50c7f..d04392dacd 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -297,7 +297,7 @@ void tcg_func_start(TCGContext *s)
     s->goto_tb_issue_mask = 0;
 #endif
 
-    gen_opc_ptr = gen_opc_buf;
+    s->gen_opc_ptr = gen_opc_buf;
     gen_opparam_ptr = gen_opparam_buf;
 
 #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
@@ -641,7 +641,7 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
     }
 #endif /* TCG_TARGET_EXTEND_ARGS */
 
-    *gen_opc_ptr++ = INDEX_op_call;
+    *s->gen_opc_ptr++ = INDEX_op_call;
     nparam = gen_opparam_ptr++;
     if (ret != TCG_CALL_DUMMY_ARG) {
 #if TCG_TARGET_REG_BITS < 64
@@ -898,7 +898,7 @@ void tcg_dump_ops(TCGContext *s)
     first_insn = 1;
     opc_ptr = gen_opc_buf;
     args = gen_opparam_buf;
-    while (opc_ptr < gen_opc_ptr) {
+    while (opc_ptr < s->gen_opc_ptr) {
         c = *opc_ptr++;
         def = &tcg_op_defs[c];
         if (c == INDEX_op_debug_insn_start) {
@@ -1229,9 +1229,9 @@ static void tcg_liveness_analysis(TCGContext *s)
     uint16_t dead_args;
     uint8_t sync_args;
     
-    gen_opc_ptr++; /* skip end */
+    s->gen_opc_ptr++; /* skip end */
 
-    nb_ops = gen_opc_ptr - gen_opc_buf;
+    nb_ops = s->gen_opc_ptr - gen_opc_buf;
 
     s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
     s->op_sync_args = tcg_malloc(nb_ops * sizeof(uint8_t));
@@ -1448,7 +1448,7 @@ static void tcg_liveness_analysis(TCGContext *s)
 static void tcg_liveness_analysis(TCGContext *s)
 {
     int nb_ops;
-    nb_ops = gen_opc_ptr - gen_opc_buf;
+    nb_ops = s->gen_opc_ptr - gen_opc_buf;
 
     s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
     memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
@@ -2222,7 +2222,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
 
 #ifdef USE_TCG_OPTIMIZATIONS
     gen_opparam_ptr =
-        tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
+        tcg_optimize(s, s->gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
 #endif
 
 #ifdef CONFIG_PROFILER
@@ -2334,7 +2334,7 @@ int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
 #ifdef CONFIG_PROFILER
     {
         int n;
-        n = (gen_opc_ptr - gen_opc_buf);
+        n = (s->gen_opc_ptr - gen_opc_buf);
         s->op_count += n;
         if (n > s->op_count_max)
             s->op_count_max = n;

From c4afe5c4d30e1dd6fc1f2b0b32ffb50f4d5ada82 Mon Sep 17 00:00:00 2001
From: Evgeny Voevodin 
Date: Mon, 12 Nov 2012 13:27:46 +0400
Subject: [PATCH 1674/2270] TCG: Use gen_opparam_ptr from context instead of
 global variable.

Signed-off-by: Evgeny Voevodin 
Reviewed-by: Richard Henderson 
Signed-off-by: Blue Swirl 
---
 gen-icount.h |   2 +-
 tcg/tcg-op.h | 254 +++++++++++++++++++++++++--------------------------
 tcg/tcg.c    |  36 ++++----
 3 files changed, 146 insertions(+), 146 deletions(-)

diff --git a/gen-icount.h b/gen-icount.h
index 430cb446d0..248cf5b16d 100644
--- a/gen-icount.h
+++ b/gen-icount.h
@@ -16,7 +16,7 @@ static inline void gen_icount_start(void)
     count = tcg_temp_local_new_i32();
     tcg_gen_ld_i32(count, cpu_env, offsetof(CPUArchState, icount_decr.u32));
     /* This is a horrid hack to allow fixing up the value later.  */
-    icount_arg = gen_opparam_ptr + 1;
+    icount_arg = tcg_ctx.gen_opparam_ptr + 1;
     tcg_gen_subi_i32(count, count, 0xdeadbeef);
 
     tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, icount_label);
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 9bc890fd6f..0b3cb0be3a 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -33,230 +33,230 @@ static inline void tcg_gen_op0(TCGOpcode opc)
 static inline void tcg_gen_op1_i32(TCGOpcode opc, TCGv_i32 arg1)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg1);
 }
 
 static inline void tcg_gen_op1_i64(TCGOpcode opc, TCGv_i64 arg1)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg1);
 }
 
 static inline void tcg_gen_op1i(TCGOpcode opc, TCGArg arg1)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = arg1;
+    *tcg_ctx.gen_opparam_ptr++ = arg1;
 }
 
 static inline void tcg_gen_op2_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg2);
 }
 
 static inline void tcg_gen_op2_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg2);
 }
 
 static inline void tcg_gen_op2i_i32(TCGOpcode opc, TCGv_i32 arg1, TCGArg arg2)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
-    *gen_opparam_ptr++ = arg2;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = arg2;
 }
 
 static inline void tcg_gen_op2i_i64(TCGOpcode opc, TCGv_i64 arg1, TCGArg arg2)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
-    *gen_opparam_ptr++ = arg2;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = arg2;
 }
 
 static inline void tcg_gen_op2ii(TCGOpcode opc, TCGArg arg1, TCGArg arg2)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = arg1;
-    *gen_opparam_ptr++ = arg2;
+    *tcg_ctx.gen_opparam_ptr++ = arg1;
+    *tcg_ctx.gen_opparam_ptr++ = arg2;
 }
 
 static inline void tcg_gen_op3_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                    TCGv_i32 arg3)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg3);
 }
 
 static inline void tcg_gen_op3_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
                                    TCGv_i64 arg3)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg3);
 }
 
 static inline void tcg_gen_op3i_i32(TCGOpcode opc, TCGv_i32 arg1,
                                     TCGv_i32 arg2, TCGArg arg3)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
-    *gen_opparam_ptr++ = arg3;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = arg3;
 }
 
 static inline void tcg_gen_op3i_i64(TCGOpcode opc, TCGv_i64 arg1,
                                     TCGv_i64 arg2, TCGArg arg3)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
-    *gen_opparam_ptr++ = arg3;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = arg3;
 }
 
 static inline void tcg_gen_ldst_op_i32(TCGOpcode opc, TCGv_i32 val,
                                        TCGv_ptr base, TCGArg offset)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I32(val);
-    *gen_opparam_ptr++ = GET_TCGV_PTR(base);
-    *gen_opparam_ptr++ = offset;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(val);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_PTR(base);
+    *tcg_ctx.gen_opparam_ptr++ = offset;
 }
 
 static inline void tcg_gen_ldst_op_i64(TCGOpcode opc, TCGv_i64 val,
                                        TCGv_ptr base, TCGArg offset)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(val);
-    *gen_opparam_ptr++ = GET_TCGV_PTR(base);
-    *gen_opparam_ptr++ = offset;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(val);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_PTR(base);
+    *tcg_ctx.gen_opparam_ptr++ = offset;
 }
 
 static inline void tcg_gen_qemu_ldst_op_i64_i32(TCGOpcode opc, TCGv_i64 val,
                                                 TCGv_i32 addr, TCGArg mem_index)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(val);
-    *gen_opparam_ptr++ = GET_TCGV_I32(addr);
-    *gen_opparam_ptr++ = mem_index;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(val);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(addr);
+    *tcg_ctx.gen_opparam_ptr++ = mem_index;
 }
 
 static inline void tcg_gen_qemu_ldst_op_i64_i64(TCGOpcode opc, TCGv_i64 val,
                                                 TCGv_i64 addr, TCGArg mem_index)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(val);
-    *gen_opparam_ptr++ = GET_TCGV_I64(addr);
-    *gen_opparam_ptr++ = mem_index;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(val);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(addr);
+    *tcg_ctx.gen_opparam_ptr++ = mem_index;
 }
 
 static inline void tcg_gen_op4_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                    TCGv_i32 arg3, TCGv_i32 arg4)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg4);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg4);
 }
 
 static inline void tcg_gen_op4_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
                                    TCGv_i64 arg3, TCGv_i64 arg4)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg4);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg4);
 }
 
 static inline void tcg_gen_op4i_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                     TCGv_i32 arg3, TCGArg arg4)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
-    *gen_opparam_ptr++ = arg4;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = arg4;
 }
 
 static inline void tcg_gen_op4i_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
                                     TCGv_i64 arg3, TCGArg arg4)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
-    *gen_opparam_ptr++ = arg4;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = arg4;
 }
 
 static inline void tcg_gen_op4ii_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                      TCGArg arg3, TCGArg arg4)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
-    *gen_opparam_ptr++ = arg3;
-    *gen_opparam_ptr++ = arg4;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = arg3;
+    *tcg_ctx.gen_opparam_ptr++ = arg4;
 }
 
 static inline void tcg_gen_op4ii_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
                                      TCGArg arg3, TCGArg arg4)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
-    *gen_opparam_ptr++ = arg3;
-    *gen_opparam_ptr++ = arg4;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = arg3;
+    *tcg_ctx.gen_opparam_ptr++ = arg4;
 }
 
 static inline void tcg_gen_op5_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                    TCGv_i32 arg3, TCGv_i32 arg4, TCGv_i32 arg5)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg4);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg5);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg4);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg5);
 }
 
 static inline void tcg_gen_op5_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
                                    TCGv_i64 arg3, TCGv_i64 arg4, TCGv_i64 arg5)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg4);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg5);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg4);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg5);
 }
 
 static inline void tcg_gen_op5i_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                     TCGv_i32 arg3, TCGv_i32 arg4, TCGArg arg5)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg4);
-    *gen_opparam_ptr++ = arg5;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg4);
+    *tcg_ctx.gen_opparam_ptr++ = arg5;
 }
 
 static inline void tcg_gen_op5i_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
                                     TCGv_i64 arg3, TCGv_i64 arg4, TCGArg arg5)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg4);
-    *gen_opparam_ptr++ = arg5;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg4);
+    *tcg_ctx.gen_opparam_ptr++ = arg5;
 }
 
 static inline void tcg_gen_op5ii_i32(TCGOpcode opc, TCGv_i32 arg1,
@@ -264,11 +264,11 @@ static inline void tcg_gen_op5ii_i32(TCGOpcode opc, TCGv_i32 arg1,
                                      TCGArg arg4, TCGArg arg5)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
-    *gen_opparam_ptr++ = arg4;
-    *gen_opparam_ptr++ = arg5;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = arg4;
+    *tcg_ctx.gen_opparam_ptr++ = arg5;
 }
 
 static inline void tcg_gen_op5ii_i64(TCGOpcode opc, TCGv_i64 arg1,
@@ -276,11 +276,11 @@ static inline void tcg_gen_op5ii_i64(TCGOpcode opc, TCGv_i64 arg1,
                                      TCGArg arg4, TCGArg arg5)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
-    *gen_opparam_ptr++ = arg4;
-    *gen_opparam_ptr++ = arg5;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = arg4;
+    *tcg_ctx.gen_opparam_ptr++ = arg5;
 }
 
 static inline void tcg_gen_op6_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
@@ -288,12 +288,12 @@ static inline void tcg_gen_op6_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                    TCGv_i32 arg6)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg4);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg5);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg6);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg4);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg5);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg6);
 }
 
 static inline void tcg_gen_op6_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
@@ -301,12 +301,12 @@ static inline void tcg_gen_op6_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
                                    TCGv_i64 arg6)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg4);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg5);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg6);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg4);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg5);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg6);
 }
 
 static inline void tcg_gen_op6i_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
@@ -314,12 +314,12 @@ static inline void tcg_gen_op6i_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
                                     TCGv_i32 arg5, TCGArg arg6)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg4);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg5);
-    *gen_opparam_ptr++ = arg6;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg4);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg5);
+    *tcg_ctx.gen_opparam_ptr++ = arg6;
 }
 
 static inline void tcg_gen_op6i_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
@@ -327,12 +327,12 @@ static inline void tcg_gen_op6i_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
                                     TCGv_i64 arg5, TCGArg arg6)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg4);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg5);
-    *gen_opparam_ptr++ = arg6;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg4);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg5);
+    *tcg_ctx.gen_opparam_ptr++ = arg6;
 }
 
 static inline void tcg_gen_op6ii_i32(TCGOpcode opc, TCGv_i32 arg1,
@@ -340,12 +340,12 @@ static inline void tcg_gen_op6ii_i32(TCGOpcode opc, TCGv_i32 arg1,
                                      TCGv_i32 arg4, TCGArg arg5, TCGArg arg6)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
-    *gen_opparam_ptr++ = GET_TCGV_I32(arg4);
-    *gen_opparam_ptr++ = arg5;
-    *gen_opparam_ptr++ = arg6;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I32(arg4);
+    *tcg_ctx.gen_opparam_ptr++ = arg5;
+    *tcg_ctx.gen_opparam_ptr++ = arg6;
 }
 
 static inline void tcg_gen_op6ii_i64(TCGOpcode opc, TCGv_i64 arg1,
@@ -353,12 +353,12 @@ static inline void tcg_gen_op6ii_i64(TCGOpcode opc, TCGv_i64 arg1,
                                      TCGv_i64 arg4, TCGArg arg5, TCGArg arg6)
 {
     *tcg_ctx.gen_opc_ptr++ = opc;
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
-    *gen_opparam_ptr++ = GET_TCGV_I64(arg4);
-    *gen_opparam_ptr++ = arg5;
-    *gen_opparam_ptr++ = arg6;
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+    *tcg_ctx.gen_opparam_ptr++ = GET_TCGV_I64(arg4);
+    *tcg_ctx.gen_opparam_ptr++ = arg5;
+    *tcg_ctx.gen_opparam_ptr++ = arg6;
 }
 
 static inline void gen_set_label(int n)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index d04392dacd..96535b6187 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -298,7 +298,7 @@ void tcg_func_start(TCGContext *s)
 #endif
 
     s->gen_opc_ptr = gen_opc_buf;
-    gen_opparam_ptr = gen_opparam_buf;
+    s->gen_opparam_ptr = gen_opparam_buf;
 
 #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
     /* Initialize qemu_ld/st labels to assist code generation at the end of TB
@@ -642,22 +642,22 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
 #endif /* TCG_TARGET_EXTEND_ARGS */
 
     *s->gen_opc_ptr++ = INDEX_op_call;
-    nparam = gen_opparam_ptr++;
+    nparam = s->gen_opparam_ptr++;
     if (ret != TCG_CALL_DUMMY_ARG) {
 #if TCG_TARGET_REG_BITS < 64
         if (sizemask & 1) {
 #ifdef TCG_TARGET_WORDS_BIGENDIAN
-            *gen_opparam_ptr++ = ret + 1;
-            *gen_opparam_ptr++ = ret;
+            *s->gen_opparam_ptr++ = ret + 1;
+            *s->gen_opparam_ptr++ = ret;
 #else
-            *gen_opparam_ptr++ = ret;
-            *gen_opparam_ptr++ = ret + 1;
+            *s->gen_opparam_ptr++ = ret;
+            *s->gen_opparam_ptr++ = ret + 1;
 #endif
             nb_rets = 2;
         } else
 #endif
         {
-            *gen_opparam_ptr++ = ret;
+            *s->gen_opparam_ptr++ = ret;
             nb_rets = 1;
         }
     } else {
@@ -671,7 +671,7 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
             /* some targets want aligned 64 bit args */
             if (real_args & 1) {
-                *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
+                *s->gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
                 real_args++;
             }
 #endif
@@ -686,28 +686,28 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
 	       have to get more complicated to differentiate between
 	       stack arguments and register arguments.  */
 #if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
-            *gen_opparam_ptr++ = args[i] + 1;
-            *gen_opparam_ptr++ = args[i];
+            *s->gen_opparam_ptr++ = args[i] + 1;
+            *s->gen_opparam_ptr++ = args[i];
 #else
-            *gen_opparam_ptr++ = args[i];
-            *gen_opparam_ptr++ = args[i] + 1;
+            *s->gen_opparam_ptr++ = args[i];
+            *s->gen_opparam_ptr++ = args[i] + 1;
 #endif
             real_args += 2;
             continue;
         }
 #endif /* TCG_TARGET_REG_BITS < 64 */
 
-        *gen_opparam_ptr++ = args[i];
+        *s->gen_opparam_ptr++ = args[i];
         real_args++;
     }
-    *gen_opparam_ptr++ = GET_TCGV_PTR(func);
+    *s->gen_opparam_ptr++ = GET_TCGV_PTR(func);
 
-    *gen_opparam_ptr++ = flags;
+    *s->gen_opparam_ptr++ = flags;
 
     *nparam = (nb_rets << 16) | (real_args + 1);
 
     /* total parameters, needed to go backward in the instruction stream */
-    *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
+    *s->gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
 
 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
     for (i = 0; i < nargs; ++i) {
@@ -1240,7 +1240,7 @@ static void tcg_liveness_analysis(TCGContext *s)
     mem_temps = tcg_malloc(s->nb_temps);
     tcg_la_func_end(s, dead_temps, mem_temps);
 
-    args = gen_opparam_ptr;
+    args = s->gen_opparam_ptr;
     op_index = nb_ops - 1;
     while (op_index >= 0) {
         op = gen_opc_buf[op_index];
@@ -2221,7 +2221,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
 #endif
 
 #ifdef USE_TCG_OPTIMIZATIONS
-    gen_opparam_ptr =
+    s->gen_opparam_ptr =
         tcg_optimize(s, s->gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
 #endif
 

From 92414b31e726ead5fd93a5bee5a6d1aecc66e454 Mon Sep 17 00:00:00 2001
From: Evgeny Voevodin 
Date: Mon, 12 Nov 2012 13:27:47 +0400
Subject: [PATCH 1675/2270] TCG: Use gen_opc_buf from context instead of global
 variable.

Signed-off-by: Evgeny Voevodin 
Reviewed-by: Richard Henderson 
Signed-off-by: Blue Swirl 
---
 target-alpha/translate.c      |  6 ++--
 target-arm/translate.c        |  6 ++--
 target-cris/translate.c       |  8 ++---
 target-i386/translate.c       |  6 ++--
 target-lm32/translate.c       |  9 ++---
 target-m68k/translate.c       |  6 ++--
 target-microblaze/translate.c |  9 ++---
 target-mips/translate.c       |  6 ++--
 target-openrisc/translate.c   |  9 ++---
 target-ppc/translate.c        |  6 ++--
 target-s390x/translate.c      |  6 ++--
 target-sh4/translate.c        |  6 ++--
 target-sparc/translate.c      |  6 ++--
 target-unicore32/translate.c  |  6 ++--
 target-xtensa/translate.c     |  4 +--
 tcg/optimize.c                | 62 +++++++++++++++++------------------
 tcg/tcg.c                     | 30 ++++++++---------
 17 files changed, 97 insertions(+), 94 deletions(-)

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index f160f83ffe..4045f788ea 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3373,7 +3373,7 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
     int max_insns;
 
     pc_start = tb->pc;
-    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
     ctx.tb = tb;
     ctx.env = env;
@@ -3406,7 +3406,7 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
             }
         }
         if (search_pc) {
-            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j)
@@ -3465,7 +3465,7 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
     gen_icount_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
-        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 014f3582b9..c42110ab0d 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9727,7 +9727,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
 
     dc->tb = tb;
 
-    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
     dc->is_jmp = DISAS_NEXT;
     dc->pc = pc_start;
@@ -9834,7 +9834,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
             }
         }
         if (search_pc) {
-            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j)
@@ -9974,7 +9974,7 @@ done_generating:
     }
 #endif
     if (search_pc) {
-        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 02969d4d53..0b0e86dbd1 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3232,7 +3232,7 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
     dc->env = env;
     dc->tb = tb;
 
-    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
     dc->is_jmp = DISAS_NEXT;
     dc->ppc = pc_start;
@@ -3297,7 +3297,7 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
         check_breakpoint(env, dc);
 
         if (search_pc) {
-            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j) {
@@ -3436,7 +3436,7 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
     gen_icount_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
-        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j) {
             gen_opc_instr_start[lj++] = 0;
@@ -3452,7 +3452,7 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
         log_target_disas(env, pc_start, dc->pc - pc_start,
                                  dc->env->pregs[PR_VR]);
         qemu_log("\nisize=%d osize=%td\n",
-            dc->pc - pc_start, tcg_ctx.gen_opc_ptr - gen_opc_buf);
+            dc->pc - pc_start, tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf);
     }
 #endif
 #endif
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 2658bf29c9..8e676ba1a8 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7962,7 +7962,7 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
     cpu_ptr0 = tcg_temp_new_ptr();
     cpu_ptr1 = tcg_temp_new_ptr();
 
-    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
     dc->is_jmp = DISAS_NEXT;
     pc_ptr = pc_start;
@@ -7984,7 +7984,7 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
             }
         }
         if (search_pc) {
-            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j)
@@ -8034,7 +8034,7 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     /* we don't forget to fill the last values */
     if (search_pc) {
-        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index 8c2a6181d8..af986499f2 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -1018,7 +1018,7 @@ static void gen_intermediate_code_internal(CPULM32State *env,
     dc->env = env;
     dc->tb = tb;
 
-    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
     dc->is_jmp = DISAS_NEXT;
     dc->pc = pc_start;
@@ -1047,7 +1047,7 @@ static void gen_intermediate_code_internal(CPULM32State *env,
         check_breakpoint(env, dc);
 
         if (search_pc) {
-            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j) {
@@ -1107,7 +1107,7 @@ static void gen_intermediate_code_internal(CPULM32State *env,
     gen_icount_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
-        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j) {
             gen_opc_instr_start[lj++] = 0;
@@ -1122,7 +1122,8 @@ static void gen_intermediate_code_internal(CPULM32State *env,
         qemu_log("\n");
         log_target_disas(env, pc_start, dc->pc - pc_start, 0);
         qemu_log("\nisize=%d osize=%td\n",
-            dc->pc - pc_start, tcg_ctx.gen_opc_ptr - gen_opc_buf);
+            dc->pc - pc_start, tcg_ctx.gen_opc_ptr -
+            tcg_ctx.gen_opc_buf);
     }
 #endif
 }
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index ede3536dc4..b13be4899e 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2982,7 +2982,7 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
 
     dc->tb = tb;
 
-    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
     dc->env = env;
     dc->is_jmp = DISAS_NEXT;
@@ -3015,7 +3015,7 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
                 break;
         }
         if (search_pc) {
-            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j)
@@ -3075,7 +3075,7 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
     }
 #endif
     if (search_pc) {
-        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index a84c22ee0f..cce4494954 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1741,7 +1741,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
     dc->tb = tb;
     org_flags = dc->synced_flags = dc->tb_flags = tb->flags;
 
-    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
     dc->is_jmp = DISAS_NEXT;
     dc->jmp = 0;
@@ -1784,7 +1784,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
         check_breakpoint(env, dc);
 
         if (search_pc) {
-            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j)
@@ -1899,7 +1899,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
     gen_icount_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
-        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
@@ -1916,7 +1916,8 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
         log_target_disas(env, pc_start, dc->pc - pc_start, 0);
 #endif
         qemu_log("\nisize=%d osize=%td\n",
-            dc->pc - pc_start, tcg_ctx.gen_opc_ptr - gen_opc_buf);
+            dc->pc - pc_start, tcg_ctx.gen_opc_ptr -
+            tcg_ctx.gen_opc_buf);
     }
 #endif
 #endif
diff --git a/target-mips/translate.c b/target-mips/translate.c
index cc126f5382..8b438f8bb0 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15513,7 +15513,7 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
         qemu_log("search pc %d\n", search_pc);
 
     pc_start = tb->pc;
-    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
     ctx.pc = pc_start;
     ctx.saved_pc = -1;
     ctx.singlestep_enabled = env->singlestep_enabled;
@@ -15549,7 +15549,7 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
         }
 
         if (search_pc) {
-            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j)
@@ -15633,7 +15633,7 @@ done_generating:
     gen_icount_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
-        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index eba134e0b7..f14da7bd1a 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1675,7 +1675,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
     pc_start = tb->pc;
     dc->tb = tb;
 
-    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
     dc->is_jmp = DISAS_NEXT;
     dc->ppc = pc_start;
     dc->pc = pc_start;
@@ -1703,7 +1703,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
     do {
         check_breakpoint(cpu, dc);
         if (search_pc) {
-            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
             if (k < j) {
                 k++;
                 while (k < j) {
@@ -1784,7 +1784,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
     gen_icount_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
-        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         k++;
         while (k <= j) {
             gen_opc_instr_start[k++] = 0;
@@ -1799,7 +1799,8 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
         qemu_log("\n");
         log_target_disas(&cpu->env, pc_start, dc->pc - pc_start, 0);
         qemu_log("\nisize=%d osize=%td\n",
-            dc->pc - pc_start, tcg_ctx.gen_opc_ptr - gen_opc_buf);
+            dc->pc - pc_start, tcg_ctx.gen_opc_ptr -
+            tcg_ctx.gen_opc_buf);
     }
 #endif
 }
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index b2a8374e61..16b9c5dd57 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9624,7 +9624,7 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
     int max_insns;
 
     pc_start = tb->pc;
-    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
     ctx.nip = pc_start;
     ctx.tb = tb;
     ctx.exception = POWERPC_EXCP_NONE;
@@ -9675,7 +9675,7 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
             }
         }
         if (unlikely(search_pc)) {
-            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j)
@@ -9777,7 +9777,7 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
     gen_icount_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (unlikely(search_pc)) {
-        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 945cc51aaf..993f20752c 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -5134,7 +5134,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
     dc.tb = tb;
     dc.cc_op = CC_OP_DYNAMIC;
 
-    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
     next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
 
@@ -5156,7 +5156,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
             }
         }
         if (search_pc) {
-            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j) {
@@ -5209,7 +5209,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
     gen_icount_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
-        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j) {
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index b43e6c28dc..5497dede05 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -1967,7 +1967,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
     int max_insns;
 
     pc_start = tb->pc;
-    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
     ctx.pc = pc_start;
     ctx.flags = (uint32_t)tb->flags;
     ctx.bstate = BS_NONE;
@@ -1999,7 +1999,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
 	    }
 	}
         if (search_pc) {
-            i = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+            i = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
             if (ii < i) {
                 ii++;
                 while (ii < i)
@@ -2058,7 +2058,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
     gen_icount_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
-        i = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+        i = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         ii++;
         while (ii <= i)
             gen_opc_instr_start[ii++] = 0;
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 47bbc91426..2ae803695b 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5257,7 +5257,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
     dc->fpu_enabled = tb_fpu_enabled(tb->flags);
     dc->address_mask_32bit = tb_am_enabled(tb->flags);
     dc->singlestep = (env->singlestep_enabled || singlestep);
-    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
     num_insns = 0;
     max_insns = tb->cflags & CF_COUNT_MASK;
@@ -5279,7 +5279,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
         }
         if (spc) {
             qemu_log("Search PC...\n");
-            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j)
@@ -5336,7 +5336,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
     gen_icount_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (spc) {
-        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index d6bb6696ab..052bb45d70 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -1956,7 +1956,7 @@ static inline void gen_intermediate_code_internal(CPUUniCore32State *env,
 
     dc->tb = tb;
 
-    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
     dc->is_jmp = DISAS_NEXT;
     dc->pc = pc_start;
@@ -1999,7 +1999,7 @@ static inline void gen_intermediate_code_internal(CPUUniCore32State *env,
             }
         }
         if (search_pc) {
-            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j) {
@@ -2114,7 +2114,7 @@ done_generating:
     }
 #endif
     if (search_pc) {
-        j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j) {
             gen_opc_instr_start[lj++] = 0;
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index f272eac56d..e5a3f49a75 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -2849,7 +2849,7 @@ static void gen_intermediate_code_internal(
     DisasContext dc;
     int insn_count = 0;
     int j, lj = -1;
-    uint16_t *gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    uint16_t *gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
     int max_insns = tb->cflags & CF_COUNT_MASK;
     uint32_t pc_start = tb->pc;
     uint32_t next_page_start =
@@ -2893,7 +2893,7 @@ static void gen_intermediate_code_internal(
         check_breakpoint(env, &dc);
 
         if (search_pc) {
-            j = tcg_ctx.gen_opc_ptr - gen_opc_buf;
+            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
             if (lj < j) {
                 lj++;
                 while (lj < j) {
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 8e5d918030..9109b813e0 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -484,10 +484,10 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
     nb_globals = s->nb_globals;
     memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
 
-    nb_ops = tcg_opc_ptr - gen_opc_buf;
+    nb_ops = tcg_opc_ptr - s->gen_opc_buf;
     gen_args = args;
     for (op_index = 0; op_index < nb_ops; op_index++) {
-        op = gen_opc_buf[op_index];
+        op = s->gen_opc_buf[op_index];
         def = &tcg_op_defs[op];
         /* Do copy propagation */
         if (op == INDEX_op_call) {
@@ -569,7 +569,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         CASE_OP_32_64(rotr):
             if (temps[args[1]].state == TCG_TEMP_CONST
                 && temps[args[1]].val == 0) {
-                gen_opc_buf[op_index] = op_to_movi(op);
+                s->gen_opc_buf[op_index] = op_to_movi(op);
                 tcg_opt_gen_movi(gen_args, args[0], 0);
                 args += 3;
                 gen_args += 2;
@@ -598,9 +598,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
             if (temps[args[2]].state == TCG_TEMP_CONST
                 && temps[args[2]].val == 0) {
                 if (temps_are_copies(args[0], args[1])) {
-                    gen_opc_buf[op_index] = INDEX_op_nop;
+                    s->gen_opc_buf[op_index] = INDEX_op_nop;
                 } else {
-                    gen_opc_buf[op_index] = op_to_mov(op);
+                    s->gen_opc_buf[op_index] = op_to_mov(op);
                     tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
                     gen_args += 2;
                 }
@@ -618,7 +618,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         CASE_OP_32_64(mul):
             if ((temps[args[2]].state == TCG_TEMP_CONST
                 && temps[args[2]].val == 0)) {
-                gen_opc_buf[op_index] = op_to_movi(op);
+                s->gen_opc_buf[op_index] = op_to_movi(op);
                 tcg_opt_gen_movi(gen_args, args[0], 0);
                 args += 3;
                 gen_args += 2;
@@ -635,9 +635,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         CASE_OP_32_64(and):
             if (temps_are_copies(args[1], args[2])) {
                 if (temps_are_copies(args[0], args[1])) {
-                    gen_opc_buf[op_index] = INDEX_op_nop;
+                    s->gen_opc_buf[op_index] = INDEX_op_nop;
                 } else {
-                    gen_opc_buf[op_index] = op_to_mov(op);
+                    s->gen_opc_buf[op_index] = op_to_mov(op);
                     tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
                     gen_args += 2;
                 }
@@ -654,7 +654,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         CASE_OP_32_64(sub):
         CASE_OP_32_64(xor):
             if (temps_are_copies(args[1], args[2])) {
-                gen_opc_buf[op_index] = op_to_movi(op);
+                s->gen_opc_buf[op_index] = op_to_movi(op);
                 tcg_opt_gen_movi(gen_args, args[0], 0);
                 gen_args += 2;
                 args += 3;
@@ -672,7 +672,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         CASE_OP_32_64(mov):
             if (temps_are_copies(args[0], args[1])) {
                 args += 2;
-                gen_opc_buf[op_index] = INDEX_op_nop;
+                s->gen_opc_buf[op_index] = INDEX_op_nop;
                 break;
             }
             if (temps[args[1]].state != TCG_TEMP_CONST) {
@@ -684,7 +684,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
             /* Source argument is constant.  Rewrite the operation and
                let movi case handle it. */
             op = op_to_movi(op);
-            gen_opc_buf[op_index] = op;
+            s->gen_opc_buf[op_index] = op;
             args[1] = temps[args[1]].val;
             /* fallthrough */
         CASE_OP_32_64(movi):
@@ -702,7 +702,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         case INDEX_op_ext32s_i64:
         case INDEX_op_ext32u_i64:
             if (temps[args[1]].state == TCG_TEMP_CONST) {
-                gen_opc_buf[op_index] = op_to_movi(op);
+                s->gen_opc_buf[op_index] = op_to_movi(op);
                 tmp = do_constant_folding(op, temps[args[1]].val, 0);
                 tcg_opt_gen_movi(gen_args, args[0], tmp);
                 gen_args += 2;
@@ -729,7 +729,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         CASE_OP_32_64(nor):
             if (temps[args[1]].state == TCG_TEMP_CONST
                 && temps[args[2]].state == TCG_TEMP_CONST) {
-                gen_opc_buf[op_index] = op_to_movi(op);
+                s->gen_opc_buf[op_index] = op_to_movi(op);
                 tmp = do_constant_folding(op, temps[args[1]].val,
                                           temps[args[2]].val);
                 tcg_opt_gen_movi(gen_args, args[0], tmp);
@@ -742,7 +742,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         CASE_OP_32_64(deposit):
             if (temps[args[1]].state == TCG_TEMP_CONST
                 && temps[args[2]].state == TCG_TEMP_CONST) {
-                gen_opc_buf[op_index] = op_to_movi(op);
+                s->gen_opc_buf[op_index] = op_to_movi(op);
                 tmp = ((1ull << args[4]) - 1);
                 tmp = (temps[args[1]].val & ~(tmp << args[3]))
                       | ((temps[args[2]].val & tmp) << args[3]);
@@ -756,7 +756,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         CASE_OP_32_64(setcond):
             tmp = do_constant_folding_cond(op, args[1], args[2], args[3]);
             if (tmp != 2) {
-                gen_opc_buf[op_index] = op_to_movi(op);
+                s->gen_opc_buf[op_index] = op_to_movi(op);
                 tcg_opt_gen_movi(gen_args, args[0], tmp);
                 gen_args += 2;
                 args += 4;
@@ -769,11 +769,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
             if (tmp != 2) {
                 if (tmp) {
                     memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
-                    gen_opc_buf[op_index] = INDEX_op_br;
+                    s->gen_opc_buf[op_index] = INDEX_op_br;
                     gen_args[0] = args[3];
                     gen_args += 1;
                 } else {
-                    gen_opc_buf[op_index] = INDEX_op_nop;
+                    s->gen_opc_buf[op_index] = INDEX_op_nop;
                 }
                 args += 4;
                 break;
@@ -784,13 +784,13 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
             tmp = do_constant_folding_cond(op, args[1], args[2], args[5]);
             if (tmp != 2) {
                 if (temps_are_copies(args[0], args[4-tmp])) {
-                    gen_opc_buf[op_index] = INDEX_op_nop;
+                    s->gen_opc_buf[op_index] = INDEX_op_nop;
                 } else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) {
-                    gen_opc_buf[op_index] = op_to_movi(op);
+                    s->gen_opc_buf[op_index] = op_to_movi(op);
                     tcg_opt_gen_movi(gen_args, args[0], temps[args[4-tmp]].val);
                     gen_args += 2;
                 } else {
-                    gen_opc_buf[op_index] = op_to_mov(op);
+                    s->gen_opc_buf[op_index] = op_to_mov(op);
                     tcg_opt_gen_mov(s, gen_args, args[0], args[4-tmp]);
                     gen_args += 2;
                 }
@@ -820,12 +820,12 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                 }
 
                 /* We emit the extra nop when we emit the add2/sub2.  */
-                assert(gen_opc_buf[op_index + 1] == INDEX_op_nop);
+                assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
 
                 rl = args[0];
                 rh = args[1];
-                gen_opc_buf[op_index] = INDEX_op_movi_i32;
-                gen_opc_buf[++op_index] = INDEX_op_movi_i32;
+                s->gen_opc_buf[op_index] = INDEX_op_movi_i32;
+                s->gen_opc_buf[++op_index] = INDEX_op_movi_i32;
                 tcg_opt_gen_movi(&gen_args[0], rl, (uint32_t)a);
                 tcg_opt_gen_movi(&gen_args[2], rh, (uint32_t)(a >> 32));
                 gen_args += 4;
@@ -843,12 +843,12 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                 TCGArg rl, rh;
 
                 /* We emit the extra nop when we emit the mulu2.  */
-                assert(gen_opc_buf[op_index + 1] == INDEX_op_nop);
+                assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
 
                 rl = args[0];
                 rh = args[1];
-                gen_opc_buf[op_index] = INDEX_op_movi_i32;
-                gen_opc_buf[++op_index] = INDEX_op_movi_i32;
+                s->gen_opc_buf[op_index] = INDEX_op_movi_i32;
+                s->gen_opc_buf[++op_index] = INDEX_op_movi_i32;
                 tcg_opt_gen_movi(&gen_args[0], rl, (uint32_t)r);
                 tcg_opt_gen_movi(&gen_args[2], rh, (uint32_t)(r >> 32));
                 gen_args += 4;
@@ -862,11 +862,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
             if (tmp != 2) {
                 if (tmp) {
                     memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
-                    gen_opc_buf[op_index] = INDEX_op_br;
+                    s->gen_opc_buf[op_index] = INDEX_op_br;
                     gen_args[0] = args[5];
                     gen_args += 1;
                 } else {
-                    gen_opc_buf[op_index] = INDEX_op_nop;
+                    s->gen_opc_buf[op_index] = INDEX_op_nop;
                 }
             } else if ((args[4] == TCG_COND_LT || args[4] == TCG_COND_GE)
                        && temps[args[2]].state == TCG_TEMP_CONST
@@ -876,7 +876,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                 /* Simplify LT/GE comparisons vs zero to a single compare
                    vs the high word of the input.  */
                 memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
-                gen_opc_buf[op_index] = INDEX_op_brcond_i32;
+                s->gen_opc_buf[op_index] = INDEX_op_brcond_i32;
                 gen_args[0] = args[1];
                 gen_args[1] = args[3];
                 gen_args[2] = args[4];
@@ -891,7 +891,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
         case INDEX_op_setcond2_i32:
             tmp = do_constant_folding_cond2(&args[1], &args[3], args[5]);
             if (tmp != 2) {
-                gen_opc_buf[op_index] = INDEX_op_movi_i32;
+                s->gen_opc_buf[op_index] = INDEX_op_movi_i32;
                 tcg_opt_gen_movi(gen_args, args[0], tmp);
                 gen_args += 2;
             } else if ((args[5] == TCG_COND_LT || args[5] == TCG_COND_GE)
@@ -901,7 +901,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                        && temps[args[4]].val == 0) {
                 /* Simplify LT/GE comparisons vs zero to a single compare
                    vs the high word of the input.  */
-                gen_opc_buf[op_index] = INDEX_op_setcond_i32;
+                s->gen_opc_buf[op_index] = INDEX_op_setcond_i32;
                 gen_args[0] = args[0];
                 gen_args[1] = args[2];
                 gen_args[2] = args[4];
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 96535b6187..a039001369 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -297,7 +297,7 @@ void tcg_func_start(TCGContext *s)
     s->goto_tb_issue_mask = 0;
 #endif
 
-    s->gen_opc_ptr = gen_opc_buf;
+    s->gen_opc_ptr = s->gen_opc_buf;
     s->gen_opparam_ptr = gen_opparam_buf;
 
 #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
@@ -896,7 +896,7 @@ void tcg_dump_ops(TCGContext *s)
     char buf[128];
 
     first_insn = 1;
-    opc_ptr = gen_opc_buf;
+    opc_ptr = s->gen_opc_buf;
     args = gen_opparam_buf;
     while (opc_ptr < s->gen_opc_ptr) {
         c = *opc_ptr++;
@@ -1231,7 +1231,7 @@ static void tcg_liveness_analysis(TCGContext *s)
     
     s->gen_opc_ptr++; /* skip end */
 
-    nb_ops = s->gen_opc_ptr - gen_opc_buf;
+    nb_ops = s->gen_opc_ptr - s->gen_opc_buf;
 
     s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
     s->op_sync_args = tcg_malloc(nb_ops * sizeof(uint8_t));
@@ -1243,7 +1243,7 @@ static void tcg_liveness_analysis(TCGContext *s)
     args = s->gen_opparam_ptr;
     op_index = nb_ops - 1;
     while (op_index >= 0) {
-        op = gen_opc_buf[op_index];
+        op = s->gen_opc_buf[op_index];
         def = &tcg_op_defs[op];
         switch(op) {
         case INDEX_op_call:
@@ -1266,7 +1266,7 @@ static void tcg_liveness_analysis(TCGContext *s)
                             goto do_not_remove_call;
                         }
                     }
-                    tcg_set_nop(s, gen_opc_buf + op_index, 
+                    tcg_set_nop(s, s->gen_opc_buf + op_index,
                                 args - 1, nb_args);
                 } else {
                 do_not_remove_call:
@@ -1347,11 +1347,11 @@ static void tcg_liveness_analysis(TCGContext *s)
                 } else {
                     op = INDEX_op_sub_i32;
                 }
-                gen_opc_buf[op_index] = op;
+                s->gen_opc_buf[op_index] = op;
                 args[1] = args[2];
                 args[2] = args[4];
-                assert(gen_opc_buf[op_index + 1] == INDEX_op_nop);
-                tcg_set_nop(s, gen_opc_buf + op_index + 1, args + 3, 3);
+                assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
+                tcg_set_nop(s, s->gen_opc_buf + op_index + 1, args + 3, 3);
                 /* Fall through and mark the single-word operation live.  */
                 nb_iargs = 2;
                 nb_oargs = 1;
@@ -1367,11 +1367,11 @@ static void tcg_liveness_analysis(TCGContext *s)
                 if (dead_temps[args[0]] && !mem_temps[args[0]]) {
                     goto do_remove;
                 }
-                gen_opc_buf[op_index] = op = INDEX_op_mul_i32;
+                s->gen_opc_buf[op_index] = op = INDEX_op_mul_i32;
                 args[1] = args[2];
                 args[2] = args[3];
-                assert(gen_opc_buf[op_index + 1] == INDEX_op_nop);
-                tcg_set_nop(s, gen_opc_buf + op_index + 1, args + 3, 1);
+                assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
+                tcg_set_nop(s, s->gen_opc_buf + op_index + 1, args + 3, 1);
                 /* Fall through and mark the single-word operation live.  */
                 nb_oargs = 1;
             }
@@ -1394,7 +1394,7 @@ static void tcg_liveness_analysis(TCGContext *s)
                     }
                 }
             do_remove:
-                tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
+                tcg_set_nop(s, s->gen_opc_buf + op_index, args, def->nb_args);
 #ifdef CONFIG_PROFILER
                 s->del_op_count++;
 #endif
@@ -1448,7 +1448,7 @@ static void tcg_liveness_analysis(TCGContext *s)
 static void tcg_liveness_analysis(TCGContext *s)
 {
     int nb_ops;
-    nb_ops = s->gen_opc_ptr - gen_opc_buf;
+    nb_ops = s->gen_opc_ptr - s->gen_opc_buf;
 
     s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
     memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
@@ -2253,7 +2253,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
     op_index = 0;
 
     for(;;) {
-        opc = gen_opc_buf[op_index];
+        opc = s->gen_opc_buf[op_index];
 #ifdef CONFIG_PROFILER
         tcg_table_op_count[opc]++;
 #endif
@@ -2334,7 +2334,7 @@ int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
 #ifdef CONFIG_PROFILER
     {
         int n;
-        n = (s->gen_opc_ptr - gen_opc_buf);
+        n = (s->gen_opc_ptr - s->gen_opc_buf);
         s->op_count += n;
         if (n > s->op_count_max)
             s->op_count_max = n;

From 1ff0a2c594356b134af6742b9cb5e5757c620881 Mon Sep 17 00:00:00 2001
From: Evgeny Voevodin 
Date: Mon, 12 Nov 2012 13:27:48 +0400
Subject: [PATCH 1676/2270] TCG: Use gen_opparam_buf from context instead of
 global variable.

Signed-off-by: Evgeny Voevodin 
Reviewed-by: Richard Henderson 
Signed-off-by: Blue Swirl 
---
 tcg/tcg.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index a039001369..ea0bd3a7a7 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -298,7 +298,7 @@ void tcg_func_start(TCGContext *s)
 #endif
 
     s->gen_opc_ptr = s->gen_opc_buf;
-    s->gen_opparam_ptr = gen_opparam_buf;
+    s->gen_opparam_ptr = s->gen_opparam_buf;
 
 #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
     /* Initialize qemu_ld/st labels to assist code generation at the end of TB
@@ -897,7 +897,7 @@ void tcg_dump_ops(TCGContext *s)
 
     first_insn = 1;
     opc_ptr = s->gen_opc_buf;
-    args = gen_opparam_buf;
+    args = s->gen_opparam_buf;
     while (opc_ptr < s->gen_opc_ptr) {
         c = *opc_ptr++;
         def = &tcg_op_defs[c];
@@ -1440,8 +1440,9 @@ static void tcg_liveness_analysis(TCGContext *s)
         op_index--;
     }
 
-    if (args != gen_opparam_buf)
+    if (args != s->gen_opparam_buf) {
         tcg_abort();
+    }
 }
 #else
 /* dummy liveness analysis */
@@ -2222,7 +2223,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
 
 #ifdef USE_TCG_OPTIMIZATIONS
     s->gen_opparam_ptr =
-        tcg_optimize(s, s->gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
+        tcg_optimize(s, s->gen_opc_ptr, s->gen_opparam_buf, tcg_op_defs);
 #endif
 
 #ifdef CONFIG_PROFILER
@@ -2249,7 +2250,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
     s->code_buf = gen_code_buf;
     s->code_ptr = gen_code_buf;
 
-    args = gen_opparam_buf;
+    args = s->gen_opparam_buf;
     op_index = 0;
 
     for(;;) {

From 83eeb39669a19716a44bcad5a34158543b3779b8 Mon Sep 17 00:00:00 2001
From: Evgeny Voevodin 
Date: Mon, 12 Nov 2012 13:27:49 +0400
Subject: [PATCH 1677/2270] TCG: Remove unused global variables

Signed-off-by: Evgeny Voevodin 
Reviewed-by: Richard Henderson 
Signed-off-by: Blue Swirl 
---
 tcg/tcg.c       | 4 ----
 tcg/tcg.h       | 4 ----
 translate-all.c | 3 ---
 3 files changed, 11 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index ea0bd3a7a7..4f756962c5 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -96,10 +96,6 @@ const size_t tcg_op_defs_max = ARRAY_SIZE(tcg_op_defs);
 static TCGRegSet tcg_target_available_regs[2];
 static TCGRegSet tcg_target_call_clobber_regs;
 
-/* XXX: move that inside the context */
-uint16_t *gen_opc_ptr;
-TCGArg *gen_opparam_ptr;
-
 static inline void tcg_out8(TCGContext *s, uint8_t v)
 {
     *s->code_ptr++ = v;
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 6ffec1d47a..9481e35ab4 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -465,10 +465,6 @@ struct TCGContext {
 };
 
 extern TCGContext tcg_ctx;
-extern uint16_t *gen_opc_ptr;
-extern TCGArg *gen_opparam_ptr;
-extern uint16_t gen_opc_buf[];
-extern TCGArg gen_opparam_buf[];
 
 /* pool based memory allocation */
 
diff --git a/translate-all.c b/translate-all.c
index 5bd2d3711a..d9c2e57861 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -33,9 +33,6 @@
 /* code generation context */
 TCGContext tcg_ctx;
 
-uint16_t gen_opc_buf[OPC_BUF_SIZE];
-TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE];
-
 target_ulong gen_opc_pc[OPC_BUF_SIZE];
 uint16_t gen_opc_icount[OPC_BUF_SIZE];
 uint8_t gen_opc_instr_start[OPC_BUF_SIZE];

From 2c5c4451e69a69c0fad3303c25cc7eaad6950f79 Mon Sep 17 00:00:00 2001
From: Blue Swirl 
Date: Sat, 3 Nov 2012 15:42:21 +0000
Subject: [PATCH 1678/2270] libseccomp: require version 1.0.0

Debian Wheezy has version 0.1.0 which is not compatible, avoid it.

Signed-off-by: Blue Swirl 
---
 configure | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure b/configure
index f847ee264e..e6c5712723 100755
--- a/configure
+++ b/configure
@@ -1383,7 +1383,7 @@ fi
 # libseccomp check
 
 if test "$seccomp" != "no" ; then
-    if $pkg_config libseccomp --modversion >/dev/null 2>&1; then
+    if $pkg_config --atleast-version=1.0.0 libseccomp --modversion >/dev/null 2>&1; then
         LIBS=`$pkg_config --libs libseccomp`
 	seccomp="yes"
     else

From 3bc2f570ec9fc930619a8ef26a22dd6d03c25dac Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Fri, 16 Nov 2012 18:35:27 +0100
Subject: [PATCH 1679/2270] build: replace weak symbols with a static library

Weak symbols were a nice idea, but they turned out not to be a good one.
Toolchain support is just too sparse, in particular llvm-gcc is totally
broken.

This patch uses a surprisingly low-tech approach: a static library.
Symbols in a static library are always overridden by symbols in an
object file.  Furthermore, if you place each function in a separate
source file, object files for unused functions will not be taken in.
This means that each function can use all the dependencies that it needs
(especially QAPI stuff such as error_setg).

Thus, all stubs are placed in separate object files and put together in
a static library.  The library then is linked to all programs.

Signed-off-by: Paolo Bonzini 
Tested-by: Peter Maydell 
Reviewed-by: Peter Maydell 
Tested-by: Stefan Weil 
Signed-off-by: Blue Swirl 
---
 Makefile                   | 16 +++++++++++-----
 Makefile.objs              |  5 +++++
 Makefile.target            |  4 ++--
 compiler.h                 | 11 -----------
 osdep.c                    | 32 --------------------------------
 oslib-win32.c              |  7 -------
 qemu-sockets.c             | 22 ----------------------
 qmp.c                      |  9 ---------
 rules.mak                  |  2 +-
 stubs/Makefile.objs        |  8 ++++++++
 stubs/arch-query-cpu-def.c |  9 +++++++++
 stubs/fd-register.c        |  6 ++++++
 stubs/fdset-add-fd.c       |  7 +++++++
 stubs/fdset-find-fd.c      |  7 +++++++
 stubs/fdset-get-fd.c       |  7 +++++++
 stubs/fdset-remove-fd.c    |  7 +++++++
 stubs/get-fd.c             |  8 ++++++++
 stubs/set-fd-handler.c     | 11 +++++++++++
 18 files changed, 89 insertions(+), 89 deletions(-)
 create mode 100644 stubs/Makefile.objs
 create mode 100644 stubs/arch-query-cpu-def.c
 create mode 100644 stubs/fd-register.c
 create mode 100644 stubs/fdset-add-fd.c
 create mode 100644 stubs/fdset-find-fd.c
 create mode 100644 stubs/fdset-get-fd.c
 create mode 100644 stubs/fdset-remove-fd.c
 create mode 100644 stubs/get-fd.c
 create mode 100644 stubs/set-fd-handler.c

diff --git a/Makefile b/Makefile
index 81c660f9f4..b8301a2521 100644
--- a/Makefile
+++ b/Makefile
@@ -157,6 +157,12 @@ version.o: $(SRC_PATH)/version.rc config-host.h
 	$(call quiet-command,$(WINDRES) -I. -o $@ $<,"  RC    $(TARGET_DIR)$@")
 
 version-obj-$(CONFIG_WIN32) += version.o
+
+######################################################################
+# Build library with stubs
+
+libqemustub.a: $(stub-obj-y)
+
 ######################################################################
 # Support building shared library libcacard
 
@@ -183,13 +189,13 @@ tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \
 	main-loop.o iohandler.o error.o
 tools-obj-$(CONFIG_POSIX) += compatfd.o
 
-qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
-qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
-qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
+qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y) libqemustub.a
+qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y) libqemustub.a
+qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y) libqemustub.a
 
 qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
 
-vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) libcacard/vscclient.o
+vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) libcacard/vscclient.o libqemustub.a
 	$(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^ $(libcacard_libs) $(LIBS),"  LINK  $@")
 
 fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o oslib-posix.o $(trace-obj-y)
@@ -232,7 +238,7 @@ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
 QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
 $(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
 
-qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(oslib-obj-y) $(trace-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y)
+qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(oslib-obj-y) $(trace-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y) libqemustub.a
 
 QEMULIBS=libuser libdis libdis-user
 
diff --git a/Makefile.objs b/Makefile.objs
index dc1e699914..3c7abca433 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -1,3 +1,7 @@
+#######################################################################
+# Stub library, linked in tools
+stub-obj-y = stubs/
+
 #######################################################################
 # Target-independent parts used in system and user emulation
 universal-obj-y =
@@ -239,6 +243,7 @@ vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
 QEMU_CFLAGS+=$(GLIB_CFLAGS)
 
 nested-vars += \
+	stub-obj-y \
 	qga-obj-y \
 	qom-obj-y \
 	qapi-obj-y \
diff --git a/Makefile.target b/Makefile.target
index 3822bc5ac3..8b658c0d13 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -162,12 +162,12 @@ endif #CONFIG_LINUX_USER
 
 ifdef QEMU_PROGW
 # The linker builds a windows executable. Make also a console executable.
-$(QEMU_PROGW): $(all-obj-y)
+$(QEMU_PROGW): $(all-obj-y) ../libqemustub.a
 	$(call LINK,$^)
 $(QEMU_PROG): $(QEMU_PROGW)
 	$(call quiet-command,$(OBJCOPY) --subsystem console $(QEMU_PROGW) $(QEMU_PROG),"  GEN   $(TARGET_DIR)$(QEMU_PROG)")
 else
-$(QEMU_PROG): $(all-obj-y)
+$(QEMU_PROG): $(all-obj-y) ../libqemustub.a
 	$(call LINK,$^)
 endif
 
diff --git a/compiler.h b/compiler.h
index 55d7d74775..2f7998b6c1 100644
--- a/compiler.h
+++ b/compiler.h
@@ -50,20 +50,9 @@
 #   define __printf__ __gnu_printf__
 #  endif
 # endif
-# if defined(__APPLE__)
-#  define QEMU_WEAK_ALIAS(newname, oldname) \
-        static typeof(oldname) weak_##newname __attribute__((unused, weakref(#oldname)))
-#  define QEMU_WEAK_REF(newname, oldname) (weak_##newname ? weak_##newname : oldname)
-# else
-#  define QEMU_WEAK_ALIAS(newname, oldname) \
-        typeof(oldname) newname __attribute__((weak, alias (#oldname)))
-#  define QEMU_WEAK_REF(newname, oldname) newname
-# endif
 #else
 #define GCC_ATTR /**/
 #define GCC_FMT_ATTR(n, m)
-#define QEMU_WEAK_ALIAS(newname, oldname) \
-        _Pragma("weak " #newname "=" #oldname)
 #endif
 
 #endif /* COMPILER_H */
diff --git a/osdep.c b/osdep.c
index 2f7a49159a..3a63d26e75 100644
--- a/osdep.c
+++ b/osdep.c
@@ -54,38 +54,6 @@ static bool fips_enabled = false;
 
 static const char *qemu_version = QEMU_VERSION;
 
-static int default_fdset_get_fd(int64_t fdset_id, int flags)
-{
-    return -1;
-}
-QEMU_WEAK_ALIAS(monitor_fdset_get_fd, default_fdset_get_fd);
-#define monitor_fdset_get_fd \
-    QEMU_WEAK_REF(monitor_fdset_get_fd, default_fdset_get_fd)
-
-static int default_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
-{
-    return -1;
-}
-QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_add, default_fdset_dup_fd_add);
-#define monitor_fdset_dup_fd_add \
-    QEMU_WEAK_REF(monitor_fdset_dup_fd_add, default_fdset_dup_fd_add)
-
-static int default_fdset_dup_fd_remove(int dup_fd)
-{
-    return -1;
-}
-QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_remove, default_fdset_dup_fd_remove);
-#define monitor_fdset_dup_fd_remove \
-    QEMU_WEAK_REF(monitor_fdset_dup_fd_remove, default_fdset_dup_fd_remove)
-
-static int default_fdset_dup_fd_find(int dup_fd)
-{
-    return -1;
-}
-QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_find, default_fdset_dup_fd_find);
-#define monitor_fdset_dup_fd_find \
-    QEMU_WEAK_REF(monitor_fdset_dup_fd_remove, default_fdset_dup_fd_find)
-
 int socket_set_cork(int fd, int v)
 {
 #if defined(SOL_TCP) && defined(TCP_CORK)
diff --git a/oslib-win32.c b/oslib-win32.c
index 326a2bddb3..51b33e8b20 100644
--- a/oslib-win32.c
+++ b/oslib-win32.c
@@ -32,13 +32,6 @@
 #include "trace.h"
 #include "qemu_socket.h"
 
-static void default_qemu_fd_register(int fd)
-{
-}
-QEMU_WEAK_ALIAS(qemu_fd_register, default_qemu_fd_register);
-#define qemu_fd_register \
-    QEMU_WEAK_REF(qemu_fd_register, default_qemu_fd_register)
-
 void *qemu_oom_check(void *ptr)
 {
     if (ptr == NULL) {
diff --git a/qemu-sockets.c b/qemu-sockets.c
index abcd791cb6..cfed9c5a5b 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -61,28 +61,6 @@ static QemuOptsList dummy_opts = {
     },
 };
 
-static int default_monitor_get_fd(Monitor *mon, const char *name, Error **errp)
-{
-    error_setg(errp, "only QEMU supports file descriptor passing");
-    return -1;
-}
-QEMU_WEAK_ALIAS(monitor_get_fd, default_monitor_get_fd);
-#define monitor_get_fd \
-    QEMU_WEAK_REF(monitor_get_fd, default_monitor_get_fd)
-
-static int default_qemu_set_fd_handler2(int fd,
-                                        IOCanReadHandler *fd_read_poll,
-                                        IOHandler *fd_read,
-                                        IOHandler *fd_write,
-                                        void *opaque)
-
-{
-    abort();
-}
-QEMU_WEAK_ALIAS(qemu_set_fd_handler2, default_qemu_set_fd_handler2);
-#define qemu_set_fd_handler2 \
-    QEMU_WEAK_REF(qemu_set_fd_handler2, default_qemu_set_fd_handler2)
-
 static int inet_getport(struct addrinfo *e)
 {
     struct sockaddr_in *i4;
diff --git a/qmp.c b/qmp.c
index 13e83a59e0..e3a7f0b217 100644
--- a/qmp.c
+++ b/qmp.c
@@ -471,15 +471,6 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
     return prop_list;
 }
 
-static CpuDefinitionInfoList *default_arch_query_cpu_definitions(Error **errp)
-{
-    error_set(errp, QERR_NOT_SUPPORTED);
-    return NULL;
-}
-QEMU_WEAK_ALIAS(arch_query_cpu_definitions, default_arch_query_cpu_definitions);
-#define arch_query_cpu_definitions \
-    QEMU_WEAK_REF(arch_query_cpu_definitions, default_arch_query_cpu_definitions)
-
 CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
 {
     return arch_query_cpu_definitions(errp);
diff --git a/rules.mak b/rules.mak
index 1b173aa981..d0b04e44f5 100644
--- a/rules.mak
+++ b/rules.mak
@@ -31,7 +31,7 @@ endif
 %.o: %.m
 	$(call quiet-command,$(OBJCC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"  OBJC  $(TARGET_DIR)$@")
 
-LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(sort $(1)) $(LIBS),"  LINK  $(TARGET_DIR)$@")
+LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(LIBS),"  LINK  $(TARGET_DIR)$@")
 
 %$(EXESUF): %.o
 	$(call LINK,$^)
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
new file mode 100644
index 0000000000..035b29a1f3
--- /dev/null
+++ b/stubs/Makefile.objs
@@ -0,0 +1,8 @@
+stub-obj-y += arch-query-cpu-def.o
+stub-obj-y += fdset-add-fd.o
+stub-obj-y += fdset-find-fd.o
+stub-obj-y += fdset-get-fd.o
+stub-obj-y += fdset-remove-fd.o
+stub-obj-y += get-fd.o
+stub-obj-y += set-fd-handler.o
+stub-obj-$(CONFIG_WIN32) += fd-register.o
diff --git a/stubs/arch-query-cpu-def.c b/stubs/arch-query-cpu-def.c
new file mode 100644
index 0000000000..47b524628d
--- /dev/null
+++ b/stubs/arch-query-cpu-def.c
@@ -0,0 +1,9 @@
+#include "qemu-common.h"
+#include "arch_init.h"
+#include "qerror.h"
+
+CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
+{
+    error_set(errp, QERR_NOT_SUPPORTED);
+    return NULL;
+}
diff --git a/stubs/fd-register.c b/stubs/fd-register.c
new file mode 100644
index 0000000000..813b6dd7c0
--- /dev/null
+++ b/stubs/fd-register.c
@@ -0,0 +1,6 @@
+#include "qemu-common.h"
+#include "main-loop.h"
+
+void qemu_fd_register(int fd)
+{
+}
diff --git a/stubs/fdset-add-fd.c b/stubs/fdset-add-fd.c
new file mode 100644
index 0000000000..09fe2a839a
--- /dev/null
+++ b/stubs/fdset-add-fd.c
@@ -0,0 +1,7 @@
+#include "qemu-common.h"
+#include "monitor.h"
+
+int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
+{
+    return -1;
+}
diff --git a/stubs/fdset-find-fd.c b/stubs/fdset-find-fd.c
new file mode 100644
index 0000000000..f82baa066c
--- /dev/null
+++ b/stubs/fdset-find-fd.c
@@ -0,0 +1,7 @@
+#include "qemu-common.h"
+#include "monitor.h"
+
+int monitor_fdset_dup_fd_find(int dup_fd)
+{
+    return -1;
+}
diff --git a/stubs/fdset-get-fd.c b/stubs/fdset-get-fd.c
new file mode 100644
index 0000000000..4106cf90f0
--- /dev/null
+++ b/stubs/fdset-get-fd.c
@@ -0,0 +1,7 @@
+#include "qemu-common.h"
+#include "monitor.h"
+
+int monitor_fdset_get_fd(int64_t fdset_id, int flags)
+{
+    return -1;
+}
diff --git a/stubs/fdset-remove-fd.c b/stubs/fdset-remove-fd.c
new file mode 100644
index 0000000000..861b31247e
--- /dev/null
+++ b/stubs/fdset-remove-fd.c
@@ -0,0 +1,7 @@
+#include "qemu-common.h"
+#include "monitor.h"
+
+int monitor_fdset_dup_fd_remove(int dupfd)
+{
+    return -1;
+}
diff --git a/stubs/get-fd.c b/stubs/get-fd.c
new file mode 100644
index 0000000000..3561ab60e2
--- /dev/null
+++ b/stubs/get-fd.c
@@ -0,0 +1,8 @@
+#include "qemu-common.h"
+#include "monitor.h"
+
+int monitor_get_fd(Monitor *mon, const char *name, Error **errp)
+{
+    error_setg(errp, "only QEMU supports file descriptor passing");
+    return -1;
+}
diff --git a/stubs/set-fd-handler.c b/stubs/set-fd-handler.c
new file mode 100644
index 0000000000..4807b5dc22
--- /dev/null
+++ b/stubs/set-fd-handler.c
@@ -0,0 +1,11 @@
+#include "qemu-common.h"
+#include "main-loop.h"
+
+int qemu_set_fd_handler2(int fd,
+                         IOCanReadHandler *fd_read_poll,
+                         IOHandler *fd_read,
+                         IOHandler *fd_write,
+                         void *opaque)
+{
+    abort();
+}

From de91f537997c96204e35fb308aacb102071f0827 Mon Sep 17 00:00:00 2001
From: Stefan Weil 
Date: Sun, 18 Nov 2012 20:06:19 +0100
Subject: [PATCH 1680/2270] tci: fix build breakage for target MIPS

commit 5f7319cd introduced GETPC() usage for MIPS, which is currently
not defined when building with --enable-tcg-interpreter. Add MIPS to
the list of targets we selectively define GETPC() for.

Signed-off-by: Stefan Weil 
Signed-off-by: Blue Swirl 
---
 exec-all.h | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/exec-all.h b/exec-all.h
index 6b3272ab9e..21aacdab50 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -290,10 +290,11 @@ extern int tb_invalidated_flag;
 /* The return address may point to the start of the next instruction.
    Subtracting one gets us the call instruction itself.  */
 #if defined(CONFIG_TCG_INTERPRETER)
-/* Alpha and SH4 user mode emulations and Softmmu call GETPC().
+/* Softmmu, Alpha, MIPS, SH4 and SPARC user mode emulations call GETPC().
    For all others, GETPC remains undefined (which makes TCI a little faster. */
-# if defined(CONFIG_SOFTMMU) || defined(TARGET_ALPHA) || defined(TARGET_SH4) \
-     || defined(TARGET_SPARC)
+# if defined(CONFIG_SOFTMMU) || \
+    defined(TARGET_ALPHA) || defined(TARGET_MIPS) || \
+    defined(TARGET_SH4) || defined(TARGET_SPARC)
 extern uintptr_t tci_tb_ptr;
 #  define GETPC() tci_tb_ptr
 # endif

From 13586813446054aeff71b359aa627e201094375c Mon Sep 17 00:00:00 2001
From: Stefan Weil 
Date: Sun, 18 Nov 2012 20:16:26 +0100
Subject: [PATCH 1681/2270] tci: Fix build breakage (unresolved symbol
 tcg_out_tb_finalize)

Commit 32761257c0b9fa7ee04d2871a6e48a41f119c469 enabled
qemu_ld/st optimization unconditionally for some hosts.

The TCG interpreter still does not support this kind of
optimization. Therefore builds with TCI fail with an
unresolved symbol tcg_out_tb_finalize. This is fixed here.

Signed-off-by: Stefan Weil 
Signed-off-by: Blue Swirl 
---
 configure | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index e6c5712723..780b19afd6 100755
--- a/configure
+++ b/configure
@@ -3891,7 +3891,10 @@ upper() {
 
 case "$cpu" in
   i386|x86_64|ppc)
-    echo "CONFIG_QEMU_LDST_OPTIMIZATION=y" >> $config_target_mak
+    # The TCG interpreter currently does not support ld/st optimization.
+    if test "$tcg_interpreter" = "no" ; then
+        echo "CONFIG_QEMU_LDST_OPTIMIZATION=y" >> $config_target_mak
+    fi
   ;;
 esac
 

From e24dc9feb0d68142d54dc3c097f57588836d1338 Mon Sep 17 00:00:00 2001
From: Stefan Weil 
Date: Tue, 18 Sep 2012 22:52:14 +0200
Subject: [PATCH 1682/2270] tci: Support deposit operations

The operations for INDEX_op_deposit_i32 and INDEX_op_deposit_i64
are now supported and enabled by default.

Signed-off-by: Stefan Weil 
Signed-off-by: Blue Swirl 
---
 tcg/tci/tcg-target.c | 24 ++++++++++++++++++++++++
 tcg/tci/tcg-target.h |  4 ++--
 tci.c                | 22 ++++++++++++++++++++++
 3 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c
index e930740835..1707169ea8 100644
--- a/tcg/tci/tcg-target.c
+++ b/tcg/tci/tcg-target.c
@@ -122,6 +122,9 @@ static const TCGTargetOpDef tcg_target_op_defs[] = {
     { INDEX_op_rotl_i32, { R, RI, RI } },
     { INDEX_op_rotr_i32, { R, RI, RI } },
 #endif
+#if TCG_TARGET_HAS_deposit_i32
+    { INDEX_op_deposit_i32, { R, "0", R } },
+#endif
 
     { INDEX_op_brcond_i32, { R, RI } },
 
@@ -199,6 +202,9 @@ static const TCGTargetOpDef tcg_target_op_defs[] = {
 #if TCG_TARGET_HAS_rot_i64
     { INDEX_op_rotl_i64, { R, RI, RI } },
     { INDEX_op_rotr_i64, { R, RI, RI } },
+#endif
+#if TCG_TARGET_HAS_deposit_i64
+    { INDEX_op_deposit_i64, { R, "0", R } },
 #endif
     { INDEX_op_brcond_i64, { R, RI } },
 
@@ -653,6 +659,15 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
         tcg_out_ri32(s, const_args[1], args[1]);
         tcg_out_ri32(s, const_args[2], args[2]);
         break;
+    case INDEX_op_deposit_i32:  /* Optional (TCG_TARGET_HAS_deposit_i32). */
+        tcg_out_r(s, args[0]);
+        tcg_out_r(s, args[1]);
+        tcg_out_r(s, args[2]);
+        assert(args[3] <= UINT8_MAX);
+        tcg_out8(s, args[3]);
+        assert(args[4] <= UINT8_MAX);
+        tcg_out8(s, args[4]);
+        break;
 
 #if TCG_TARGET_REG_BITS == 64
     case INDEX_op_mov_i64:
@@ -680,6 +695,15 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
         tcg_out_ri64(s, const_args[1], args[1]);
         tcg_out_ri64(s, const_args[2], args[2]);
         break;
+    case INDEX_op_deposit_i64:  /* Optional (TCG_TARGET_HAS_deposit_i64). */
+        tcg_out_r(s, args[0]);
+        tcg_out_r(s, args[1]);
+        tcg_out_r(s, args[2]);
+        assert(args[3] <= UINT8_MAX);
+        tcg_out8(s, args[3]);
+        assert(args[4] <= UINT8_MAX);
+        tcg_out8(s, args[4]);
+        break;
     case INDEX_op_div_i64:      /* Optional (TCG_TARGET_HAS_div_i64). */
     case INDEX_op_divu_i64:     /* Optional (TCG_TARGET_HAS_div_i64). */
     case INDEX_op_rem_i64:      /* Optional (TCG_TARGET_HAS_div_i64). */
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index 37f28c0522..a832f5cf52 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -67,7 +67,7 @@
 #define TCG_TARGET_HAS_ext8u_i32        1
 #define TCG_TARGET_HAS_ext16u_i32       1
 #define TCG_TARGET_HAS_andc_i32         0
-#define TCG_TARGET_HAS_deposit_i32      0
+#define TCG_TARGET_HAS_deposit_i32      1
 #define TCG_TARGET_HAS_eqv_i32          0
 #define TCG_TARGET_HAS_nand_i32         0
 #define TCG_TARGET_HAS_nor_i32          0
@@ -81,7 +81,7 @@
 #define TCG_TARGET_HAS_bswap16_i64      1
 #define TCG_TARGET_HAS_bswap32_i64      1
 #define TCG_TARGET_HAS_bswap64_i64      1
-#define TCG_TARGET_HAS_deposit_i64      0
+#define TCG_TARGET_HAS_deposit_i64      1
 /* Not more than one of the next two defines must be 1. */
 #define TCG_TARGET_HAS_div_i64          0
 #define TCG_TARGET_HAS_div2_i64         0
diff --git a/tci.c b/tci.c
index 98f5f713e0..9c87c8e8b3 100644
--- a/tci.c
+++ b/tci.c
@@ -688,6 +688,17 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
             t2 = tci_read_ri32(&tb_ptr);
             tci_write_reg32(t0, (t1 >> t2) | (t1 << (32 - t2)));
             break;
+#endif
+#if TCG_TARGET_HAS_deposit_i32
+        case INDEX_op_deposit_i32:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r32(&tb_ptr);
+            t2 = tci_read_r32(&tb_ptr);
+            tmp16 = *tb_ptr++;
+            tmp8 = *tb_ptr++;
+            tmp32 = (((1 << tmp8) - 1) << tmp16);
+            tci_write_reg32(t0, (t1 & ~tmp32) | ((t2 << tmp16) & tmp32));
+            break;
 #endif
         case INDEX_op_brcond_i32:
             t0 = tci_read_r32(&tb_ptr);
@@ -935,6 +946,17 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
         case INDEX_op_rotr_i64:
             TODO();
             break;
+#endif
+#if TCG_TARGET_HAS_deposit_i64
+        case INDEX_op_deposit_i64:
+            t0 = *tb_ptr++;
+            t1 = tci_read_r64(&tb_ptr);
+            t2 = tci_read_r64(&tb_ptr);
+            tmp16 = *tb_ptr++;
+            tmp8 = *tb_ptr++;
+            tmp64 = (((1ULL << tmp8) - 1) << tmp16);
+            tci_write_reg64(t0, (t1 & ~tmp64) | ((t2 << tmp16) & tmp64));
+            break;
 #endif
         case INDEX_op_brcond_i64:
             t0 = tci_read_r64(&tb_ptr);

From 31a322895851cddf648f95954af4725d71d778a4 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Mon, 19 Nov 2012 09:45:06 +0100
Subject: [PATCH 1683/2270] libcacard: make unnesting rules available to
 Makefile.objs

Signed-off-by: Paolo Bonzini 
---
 libcacard/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcacard/Makefile b/libcacard/Makefile
index 487f434894..f501cecf7b 100644
--- a/libcacard/Makefile
+++ b/libcacard/Makefile
@@ -1,6 +1,6 @@
 -include ../config-host.mak
--include $(SRC_PATH)/Makefile.objs
 -include $(SRC_PATH)/rules.mak
+-include $(SRC_PATH)/Makefile.objs
 
 libcacard_includedir=$(includedir)/cacard
 

From a636be69a8da6807a75fd441d245dcf610172a40 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Mon, 19 Nov 2012 09:45:20 +0100
Subject: [PATCH 1684/2270] libcacard: link in stubs

Signed-off-by: Paolo Bonzini 
---
 libcacard/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcacard/Makefile b/libcacard/Makefile
index f501cecf7b..c26aac65c3 100644
--- a/libcacard/Makefile
+++ b/libcacard/Makefile
@@ -7,7 +7,7 @@ libcacard_includedir=$(includedir)/cacard
 $(call set-vpath, $(SRC_PATH))
 
 # objects linked into a shared library, built with libtool with -fPIC if required
-QEMU_OBJS=$(oslib-obj-y) qemu-timer-common.o $(trace-obj-y)
+QEMU_OBJS=$(oslib-obj-y) qemu-timer-common.o $(trace-obj-y) $(stub-obj-y)
 QEMU_OBJS_LIB=$(patsubst %.o,%.lo,$(QEMU_OBJS))
 
 QEMU_CFLAGS+=-I../

From 2b84c2be00a5d5b2fb23700fd9051657be3cc9e0 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Mon, 19 Nov 2012 09:45:34 +0100
Subject: [PATCH 1685/2270] tests: link in stubs

Signed-off-by: Paolo Bonzini 
---
 tests/Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/Makefile b/tests/Makefile
index 9bf0765de3..ca680e5644 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -48,7 +48,7 @@ tests/check-qdict$(EXESUF): tests/check-qdict.o qdict.o qfloat.o qint.o qstring.
 tests/check-qlist$(EXESUF): tests/check-qlist.o qlist.o qint.o
 tests/check-qfloat$(EXESUF): tests/check-qfloat.o qfloat.o
 tests/check-qjson$(EXESUF): tests/check-qjson.o $(qobject-obj-y) qemu-tool.o
-tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y) $(block-obj-y) iov.o
+tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y) $(block-obj-y) iov.o libqemustub.a
 tests/test-iov$(EXESUF): tests/test-iov.o iov.o
 
 tests/test-qapi-types.c tests/test-qapi-types.h :\
@@ -81,7 +81,7 @@ TARGETS=$(patsubst %-softmmu,%, $(filter %-softmmu,$(TARGET_DIRS)))
 QTEST_TARGETS=$(foreach TARGET,$(TARGETS), $(if $(check-qtest-$(TARGET)-y), $(TARGET),))
 check-qtest-$(CONFIG_POSIX)=$(foreach TARGET,$(TARGETS), $(check-qtest-$(TARGET)-y))
 
-qtest-obj-y = tests/libqtest.o $(oslib-obj-y)
+qtest-obj-y = tests/libqtest.o $(oslib-obj-y) libqemustub.a
 $(check-qtest-y): $(qtest-obj-y)
 
 .PHONY: check-help

From 16529cedcef18bf116f10279e9c9abb6645467d6 Mon Sep 17 00:00:00 2001
From: Stefan Weil 
Date: Sun, 18 Nov 2012 23:09:51 +0100
Subject: [PATCH 1686/2270] Makefile: Add missing dependency (fix parallel
 builds)

The executables in i386-softmmu, i386-linux-user, ...
depend on the recently added libqemustub.a.

Signed-off-by: Stefan Weil 
Signed-off-by: Paolo Bonzini 
---
 Makefile | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Makefile b/Makefile
index b8301a2521..3e8d441637 100644
--- a/Makefile
+++ b/Makefile
@@ -127,6 +127,8 @@ pixman/Makefile: $(SRC_PATH)/pixman/configure
 $(SRC_PATH)/pixman/configure:
 	(cd $(SRC_PATH)/pixman; autoreconf -v --install)
 
+$(SUBDIR_RULES): libqemustub.a
+
 $(filter %-softmmu,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) $(common-obj-y) $(extra-obj-y) subdir-libdis
 
 $(filter %-user,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) subdir-libdis-user subdir-libuser

From e75fce6cda8cd515645e0bd16ed4ef6260d777c7 Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Sat, 17 Nov 2012 07:40:47 -0600
Subject: [PATCH 1687/2270] rng-random: only build on POSIX platforms

There is no /dev/random on win32.

Cc: Stefan Weil 
Signed-off-by: Anthony Liguori 
---
 backends/Makefile.objs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 875eebce6a..883676106b 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -1 +1,2 @@
-common-obj-y += rng.o rng-random.o rng-egd.o
+common-obj-y += rng.o rng-egd.o
+common-obj-$(CONFIG_POSIX) += rng-random.o

From ecdffbccd783cd79eb3ce206375270de54046ea0 Mon Sep 17 00:00:00 2001
From: malc 
Date: Mon, 19 Nov 2012 22:22:24 +0400
Subject: [PATCH 1688/2270] tcg/ppc: Remove unused s_bits variable

Thanks to Alexander Graf for heads up.

Signed-off-by: malc 
---
 tcg/ppc/tcg-target.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 34a0693c58..a42a04a62a 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -901,7 +901,6 @@ static void tcg_out_qemu_ld_slow_path (TCGContext *s, TCGLabelQemuLdst *label)
 
 static void tcg_out_qemu_st_slow_path (TCGContext *s, TCGLabelQemuLdst *label)
 {
-    int s_bits;
     int ir;
     int opc = label->opc;
     int mem_index = label->mem_index;
@@ -911,8 +910,6 @@ static void tcg_out_qemu_st_slow_path (TCGContext *s, TCGLabelQemuLdst *label)
     uint8_t *raddr = label->raddr;
     uint8_t **label_ptr = &label->label_ptr[0];
 
-    s_bits = opc & 3;
-
     /* resolve label address */
     reloc_pc14 (label_ptr[0], (tcg_target_long) s->code_ptr);
 

From 456a84d156a7c42f18b1da176dd6219e2dffd043 Mon Sep 17 00:00:00 2001
From: malc 
Date: Mon, 19 Nov 2012 22:23:17 +0400
Subject: [PATCH 1689/2270] audio/wavcapture: Clarify licensing

Signed-off-by: malc 
---
 audio/wavcapture.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/audio/wavcapture.c b/audio/wavcapture.c
index 4f785f5f49..f73691cc9b 100644
--- a/audio/wavcapture.c
+++ b/audio/wavcapture.c
@@ -1,3 +1,4 @@
+/* public domain */
 #include "hw/hw.h"
 #include "monitor.h"
 #include "audio.h"

From 72bc6f1bf710e205f175af9b1fc8bbd83e8da71f Mon Sep 17 00:00:00 2001
From: malc 
Date: Mon, 19 Nov 2012 22:26:13 +0400
Subject: [PATCH 1690/2270] audio/audio_pt_int: Clarify licensing

Signed-off-by: malc 
---
 audio/audio_pt_int.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/audio/audio_pt_int.c b/audio/audio_pt_int.c
index 9a9c306a9c..e3ccb11944 100644
--- a/audio/audio_pt_int.c
+++ b/audio/audio_pt_int.c
@@ -1,3 +1,4 @@
+/* public domain */
 #include "qemu-common.h"
 #include "audio.h"
 

From 1d2a67f89abee0cef4e3d8a8dec739ef0be77120 Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Mon, 19 Nov 2012 10:31:17 -0600
Subject: [PATCH 1691/2270] Update version for 1.3.0-rc0 release

Signed-off-by: Anthony Liguori 
---
 VERSION | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/VERSION b/VERSION
index 99188f0c6f..2d04904622 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.50
+1.2.90

From 58ddcd50f30cb5c020bd4f9f36b01ee160a27cac Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" 
Date: Tue, 13 Nov 2012 12:23:23 +0200
Subject: [PATCH 1692/2270] tap: reset vnet header size on open

For tap, we currently assume the vnet header size is 10
(the default value) but that might not be the case
if tap is persistent and has been used by qemu previously.
To fix, set host header size in tap device on open.

Signed-off-by: Michael S. Tsirkin 
Tested-by: Alexander Graf 
Signed-off-by: Stefan Hajnoczi 
---
 net/tap.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/net/tap.c b/net/tap.c
index df89caaac6..1abfd44bd9 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -341,6 +341,13 @@ static TAPState *net_tap_fd_init(NetClientState *peer,
     s->using_vnet_hdr = 0;
     s->has_ufo = tap_probe_has_ufo(s->fd);
     tap_set_offload(&s->nc, 0, 0, 0, 0, 0);
+    /*
+     * Make sure host header length is set correctly in tap:
+     * it might have been modified by another instance of qemu.
+     */
+    if (tap_probe_vnet_hdr_len(s->fd, s->host_vnet_hdr_len)) {
+        tap_fd_set_vnet_hdr_len(s->fd, s->host_vnet_hdr_len);
+    }
     tap_read_poll(s, 1);
     s->vhost_net = NULL;
     return s;

From ecf51c9abe63eae282e5f912d9367ce75f36636a Mon Sep 17 00:00:00 2001
From: malc 
Date: Wed, 21 Nov 2012 10:55:28 +0400
Subject: [PATCH 1693/2270] tcg/ppc: Fix !softmmu case

Signed-off-by: malc 
---
 tcg/ppc/tcg-target.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index a42a04a62a..d72d396270 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -628,9 +628,9 @@ static void tcg_out_tlb_check (TCGContext *s, int r0, int r1, int r2,
 
 static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
 {
-    int addr_reg, addr_reg2, data_reg, data_reg2, r0, r1, rbase, bswap;
+    int addr_reg, data_reg, data_reg2, r0, r1, rbase, bswap;
 #ifdef CONFIG_SOFTMMU
-    int mem_index, s_bits, r2;
+    int mem_index, s_bits, r2, addr_reg2;
     uint8_t *label_ptr;
 #endif
 
@@ -741,9 +741,9 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
 
 static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
 {
-    int addr_reg, addr_reg2, r0, r1, data_reg, data_reg2, bswap, rbase;
+    int addr_reg, r0, r1, data_reg, data_reg2, bswap, rbase;
 #ifdef CONFIG_SOFTMMU
-    int mem_index, r2;
+    int mem_index, r2, addr_reg2;
     uint8_t *label_ptr;
 #endif
 
@@ -979,6 +979,7 @@ void tcg_out_tb_finalize(TCGContext *s)
 }
 #endif
 
+#ifdef CONFIG_SOFTMMU
 static void emit_ldst_trampoline (TCGContext *s, const void *ptr)
 {
     tcg_out32 (s, MFSPR | RT (3) | LR);
@@ -987,6 +988,7 @@ static void emit_ldst_trampoline (TCGContext *s, const void *ptr)
     tcg_out_mov (s, TCG_TYPE_I32, 3, TCG_AREG0);
     tcg_out_b (s, 0, (tcg_target_long) ptr);
 }
+#endif
 
 static void tcg_target_qemu_prologue (TCGContext *s)
 {
@@ -1049,6 +1051,7 @@ static void tcg_target_qemu_prologue (TCGContext *s)
     tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
     tcg_out32 (s, BCLR | BO_ALWAYS);
 
+#ifdef CONFIG_SOFTMMU
     for (i = 0; i < 4; ++i) {
         ld_trampolines[i] = s->code_ptr;
         emit_ldst_trampoline (s, qemu_ld_helpers[i]);
@@ -1056,6 +1059,7 @@ static void tcg_target_qemu_prologue (TCGContext *s)
         st_trampolines[i] = s->code_ptr;
         emit_ldst_trampoline (s, qemu_st_helpers[i]);
     }
+#endif
 }
 
 static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,

From 1ccbc2851282564308f790753d7158487b6af8e2 Mon Sep 17 00:00:00 2001
From: Anthony PERARD 
Date: Fri, 16 Nov 2012 04:08:14 +0000
Subject: [PATCH 1694/2270] qemu-sockets: Fix parsing of the inet option 'to'.

Having a qemu command line argument like "-vnc 127.0.0.1:0,to=99" is broken.
This have been break with commit 879e45c72da1569e07fbbc6a1aa2a708ea796044.

Signed-off-by: Anthony PERARD 
Signed-off-by: Stefan Hajnoczi 
Signed-off-by: malc 
---
 qemu-sockets.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/qemu-sockets.c b/qemu-sockets.c
index cfed9c5a5b..d314cf1d1b 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -529,8 +529,9 @@ static InetSocketAddress *inet_parse(const char *str, Error **errp)
     optstr = str + pos;
     h = strstr(optstr, ",to=");
     if (h) {
-        if (1 != sscanf(str, "%d%n", &to, &pos) ||
-            (str[pos] != '\0' && str[pos] != ',')) {
+        h += 4;
+        if (sscanf(h, "%d%n", &to, &pos) != 1 ||
+            (h[pos] != '\0' && h[pos] != ',')) {
             error_setg(errp, "error parsing to= argument");
             goto fail;
         }

From 1bc6b705eed02dab9feb0e663219b5623f3d684d Mon Sep 17 00:00:00 2001
From: Jeff Cody 
Date: Tue, 20 Nov 2012 10:21:10 -0500
Subject: [PATCH 1695/2270] block: add bdrv_reopen() support for raw hdev,
 floppy, and cdrom

For hdev, floppy, and cdrom, the reopen() handlers are the same as
for the file reopen handler.  For floppy and cdrom types, however,
we keep O_NONBLOCK, as in the _open function.

Signed-off-by: Jeff Cody 
Signed-off-by: Stefan Hajnoczi 
---
 block/raw-posix.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/block/raw-posix.c b/block/raw-posix.c
index f2f0404f6f..550c81f22b 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -333,6 +333,10 @@ static int raw_reopen_prepare(BDRVReopenState *state,
     }
 #endif
 
+    if (s->type == FTYPE_FD || s->type == FTYPE_CD) {
+        raw_s->open_flags |= O_NONBLOCK;
+    }
+
     raw_parse_flags(state->flags, &raw_s->open_flags);
 
     raw_s->fd = -1;
@@ -1409,6 +1413,9 @@ static BlockDriver bdrv_host_device = {
     .bdrv_probe_device  = hdev_probe_device,
     .bdrv_file_open     = hdev_open,
     .bdrv_close         = raw_close,
+    .bdrv_reopen_prepare = raw_reopen_prepare,
+    .bdrv_reopen_commit  = raw_reopen_commit,
+    .bdrv_reopen_abort   = raw_reopen_abort,
     .bdrv_create        = hdev_create,
     .create_options     = raw_create_options,
     .bdrv_has_zero_init = hdev_has_zero_init,
@@ -1530,6 +1537,9 @@ static BlockDriver bdrv_host_floppy = {
     .bdrv_probe_device	= floppy_probe_device,
     .bdrv_file_open     = floppy_open,
     .bdrv_close         = raw_close,
+    .bdrv_reopen_prepare = raw_reopen_prepare,
+    .bdrv_reopen_commit  = raw_reopen_commit,
+    .bdrv_reopen_abort   = raw_reopen_abort,
     .bdrv_create        = hdev_create,
     .create_options     = raw_create_options,
     .bdrv_has_zero_init = hdev_has_zero_init,
@@ -1629,6 +1639,9 @@ static BlockDriver bdrv_host_cdrom = {
     .bdrv_probe_device	= cdrom_probe_device,
     .bdrv_file_open     = cdrom_open,
     .bdrv_close         = raw_close,
+    .bdrv_reopen_prepare = raw_reopen_prepare,
+    .bdrv_reopen_commit  = raw_reopen_commit,
+    .bdrv_reopen_abort   = raw_reopen_abort,
     .bdrv_create        = hdev_create,
     .create_options     = raw_create_options,
     .bdrv_has_zero_init = hdev_has_zero_init,
@@ -1748,6 +1761,9 @@ static BlockDriver bdrv_host_cdrom = {
     .bdrv_probe_device	= cdrom_probe_device,
     .bdrv_file_open     = cdrom_open,
     .bdrv_close         = raw_close,
+    .bdrv_reopen_prepare = raw_reopen_prepare,
+    .bdrv_reopen_commit  = raw_reopen_commit,
+    .bdrv_reopen_abort   = raw_reopen_abort,
     .bdrv_create        = hdev_create,
     .create_options     = raw_create_options,
     .bdrv_has_zero_init = hdev_has_zero_init,

From 8ba2aae32c40f544def6be7ae82be9bcb781e01d Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi 
Date: Tue, 20 Nov 2012 16:34:17 +0100
Subject: [PATCH 1696/2270] vdi: don't override libuuid symbols

It's poor symbol hygiene to provide a global symbols that collide with a
common library like libuuid.  If QEMU links against a shared library
that depends on uuid_generate() it can end up calling our stub version
of the function.

This exact scenario happened with GlusterFS libgfapi.so, which depends
on libglusterfs.so's uuid_generate().

Scope the uuid stubs for vdi.c only and avoid affecting other shared
objects.

Signed-off-by: Stefan Hajnoczi 
Reviewed-by: Kevin Wolf 
---
 block/vdi.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/block/vdi.c b/block/vdi.c
index f35b12ec98..c8330b7eae 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -60,9 +60,6 @@
 /* TODO: move uuid emulation to some central place in QEMU. */
 #include "sysemu.h"     /* UUID_FMT */
 typedef unsigned char uuid_t[16];
-void uuid_generate(uuid_t out);
-int uuid_is_null(const uuid_t uu);
-void uuid_unparse(const uuid_t uu, char *out);
 #endif
 
 /* Code configuration options. */
@@ -124,18 +121,18 @@ void uuid_unparse(const uuid_t uu, char *out);
 #define VDI_IS_ALLOCATED(X) ((X) < VDI_DISCARDED)
 
 #if !defined(CONFIG_UUID)
-void uuid_generate(uuid_t out)
+static inline void uuid_generate(uuid_t out)
 {
     memset(out, 0, sizeof(uuid_t));
 }
 
-int uuid_is_null(const uuid_t uu)
+static inline int uuid_is_null(const uuid_t uu)
 {
     uuid_t null_uuid = { 0 };
     return memcmp(uu, null_uuid, sizeof(uuid_t)) == 0;
 }
 
-void uuid_unparse(const uuid_t uu, char *out)
+static inline void uuid_unparse(const uuid_t uu, char *out)
 {
     snprintf(out, 37, UUID_FMT,
             uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7],

From 08448d5195aeff49bf25fb62b4a6218f079f5284 Mon Sep 17 00:00:00 2001
From: Stefan Priebe 
Date: Tue, 20 Nov 2012 13:44:55 +0100
Subject: [PATCH 1697/2270] use int64_t for return values from rbd instead of
 int

rbd / rados tends to return pretty often length of writes
or discarded blocks. These values might be bigger than int.

The steps to reproduce are:

  mkfs.xfs -f a whole device bigger than int in bytes. mkfs.xfs sends
  a discard. Important is that you use scsi-hd and set
  discard_granularity=512. Otherwise rbd disabled discard support.

Signed-off-by: Stefan Priebe 
Signed-off-by: Stefan Hajnoczi 
---
 block/rbd.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/block/rbd.c b/block/rbd.c
index 0aaacaf859..f3becc7a8b 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -69,7 +69,7 @@ typedef enum {
 typedef struct RBDAIOCB {
     BlockDriverAIOCB common;
     QEMUBH *bh;
-    int ret;
+    int64_t ret;
     QEMUIOVector *qiov;
     char *bounce;
     RBDAIOCmd cmd;
@@ -86,7 +86,7 @@ typedef struct RADOSCB {
     int done;
     int64_t size;
     char *buf;
-    int ret;
+    int64_t ret;
 } RADOSCB;
 
 #define RBD_FD_READ 0

From 038268e2e8087ee2fd8987a77ba580e15f14c147 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Tue, 20 Nov 2012 17:27:43 +0100
Subject: [PATCH 1698/2270] ide: Fix crash with too long PRD

Without this, s->nsector can become negative and badness happens (trying
to malloc huge amount of memory and glib calls abort())

Signed-off-by: Kevin Wolf 
Signed-off-by: Stefan Hajnoczi 
---
 hw/ide/core.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 7d6b0fa7b4..c2ab78753a 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -579,6 +579,7 @@ void ide_dma_cb(void *opaque, int ret)
     IDEState *s = opaque;
     int n;
     int64_t sector_num;
+    bool stay_active = false;
 
     if (ret < 0) {
         int op = BM_STATUS_DMA_RETRY;
@@ -594,6 +595,14 @@ void ide_dma_cb(void *opaque, int ret)
     }
 
     n = s->io_buffer_size >> 9;
+    if (n > s->nsector) {
+        /* The PRDs were longer than needed for this request. Shorten them so
+         * we don't get a negative remainder. The Active bit must remain set
+         * after the request completes. */
+        n = s->nsector;
+        stay_active = true;
+    }
+
     sector_num = ide_get_sector(s);
     if (n > 0) {
         dma_buf_commit(s);
@@ -646,6 +655,9 @@ eot:
         bdrv_acct_done(s->bs, &s->acct);
     }
     ide_set_inactive(s);
+    if (stay_active) {
+        s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_DMAING);
+    }
 }
 
 static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd)

From 72bcca73c7a67c8506fa737618861ad413dabf38 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Tue, 20 Nov 2012 17:27:44 +0100
Subject: [PATCH 1699/2270] ide: Fix status register after short PRDs

When failing a request because the length of the regions described by
the PRDT was too short for the requested number of sectors, the IDE
emulation forgot to update the status register, so that the device would
keep the BSY flag set indefinitely.

Signed-off-by: Kevin Wolf 
Signed-off-by: Stefan Hajnoczi 
---
 hw/ide/core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index c2ab78753a..8da894f240 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -625,6 +625,7 @@ void ide_dma_cb(void *opaque, int ret)
     if (s->bus->dma->ops->prepare_buf(s->bus->dma, ide_cmd_is_read(s)) == 0) {
         /* The PRDs were too short. Reset the Active bit, but don't raise an
          * interrupt. */
+        s->status = READY_STAT | SEEK_STAT;
         goto eot;
     }
 

From 9995c0b706a2270a49c5bebbcda0b62263a31aa3 Mon Sep 17 00:00:00 2001
From: Lei Li 
Date: Mon, 19 Nov 2012 17:15:08 +0800
Subject: [PATCH 1700/2270] Fix the inconsistency in x509-dh-key-file parameter

Commit c448e8552b0f6135dabddf944a7110f929c08320 (spice: tls
support) added options to the -spice command line. But there
is an inconsistency between the declaration of the option
'x509-dh-key-file' to -spice command line and its parameter
parsing 'x509-dh-file' in function qemu_spice_init.

https://bugs.launchpad.net/qemu/+bug/1035042

Reported-by: Alon Bar-Lev 
Signed-off-by: Lei Li 
Signed-off-by: Gerd Hoffmann 
---
 ui/spice-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ui/spice-core.c b/ui/spice-core.c
index 51473650c0..261c6f2c11 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -610,7 +610,7 @@ void qemu_spice_init(void)
         }
 
         x509_key_password = qemu_opt_get(opts, "x509-key-password");
-        x509_dh_file = qemu_opt_get(opts, "x509-dh-file");
+        x509_dh_file = qemu_opt_get(opts, "x509-dh-key-file");
         tls_ciphers = qemu_opt_get(opts, "tls-ciphers");
     }
 

From 21a50d0b1a0745e485eff3e5aa393cdc4a1980b6 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Wed, 21 Nov 2012 14:41:48 +0100
Subject: [PATCH 1701/2270] spice: add new spice-server callbacks to
 ui/spice-display.c

Otherwise qemu crashes with non-qxl graphics cards.

Signed-off-by: Gerd Hoffmann 
---
 ui/spice-display.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/ui/spice-display.c b/ui/spice-display.c
index 0cc0116a5d..6aff3368ca 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -525,6 +525,37 @@ static int interface_flush_resources(QXLInstance *sin)
     return 0;
 }
 
+static void interface_update_area_complete(QXLInstance *sin,
+        uint32_t surface_id,
+        QXLRect *dirty, uint32_t num_updated_rects)
+{
+    /* should never be called, used in qxl native mode only */
+    fprintf(stderr, "%s: abort()\n", __func__);
+    abort();
+}
+
+/* called from spice server thread context only */
+static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
+{
+    /* should never be called, used in qxl native mode only */
+    fprintf(stderr, "%s: abort()\n", __func__);
+    abort();
+}
+
+static void interface_set_client_capabilities(QXLInstance *sin,
+                                              uint8_t client_present,
+                                              uint8_t caps[58])
+{
+    dprint(3, "%s:\n", __func__);
+}
+
+static int interface_client_monitors_config(QXLInstance *sin,
+                                        VDAgentMonitorsConfig *monitors_config)
+{
+    dprint(3, "%s:\n", __func__);
+    return 0; /* == not supported by guest */
+}
+
 static const QXLInterface dpy_interface = {
     .base.type               = SPICE_INTERFACE_QXL,
     .base.description        = "qemu simple display",
@@ -544,6 +575,10 @@ static const QXLInterface dpy_interface = {
     .req_cursor_notification = interface_req_cursor_notification,
     .notify_update           = interface_notify_update,
     .flush_resources         = interface_flush_resources,
+    .async_complete          = interface_async_complete,
+    .update_area_complete    = interface_update_area_complete,
+    .set_client_capabilities = interface_set_client_capabilities,
+    .client_monitors_config  = interface_client_monitors_config,
 };
 
 static SimpleSpiceDisplay sdpy;

From 887938160e5d631c56ee115b1817613a60184138 Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Sat, 17 Nov 2012 12:11:49 +0100
Subject: [PATCH 1702/2270] uhci: Add a completions_only flag for async
 completions

Add a completions_only flag, and set this when running process_frame for async
completion handling, this fixes 2 issues in a single patch:

1) It makes sure async completed packets get written to guest mem immediately,
even if all the bandwidth for the frame was consumed from the timer run
process_frame. This is necessary as delaying their writeback to the next frame
can cause the completion to get lost on migration.

2) The calling of process_frame from a bh on async completion causes iso
tds to get server more often they should, messing up usb sound class device
timing. By only processing completed packets, the iso tds get skipped fixing
this.

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-uhci.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 2838d21644..ef326330d3 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -152,6 +152,7 @@ struct UHCIState {
     QEMUBH *bh;
     uint32_t frame_bytes;
     uint32_t frame_bandwidth;
+    bool completions_only;
     UHCIPort ports[NB_PORTS];
 
     /* Interrupts that should be raised at the end of the current frame.  */
@@ -891,6 +892,10 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
         goto done;
     }
 
+    if (s->completions_only) {
+        return TD_RESULT_ASYNC_CONT;
+    }
+
     /* Allocate new packet */
     if (q == NULL) {
         USBDevice *dev = uhci_find_device(s, (td->token >> 8) & 0x7f);
@@ -960,9 +965,9 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet)
     }
 
     async->done = 1;
-    if (s->frame_bytes < s->frame_bandwidth) {
-        qemu_bh_schedule(s->bh);
-    }
+    /* Force processing of this packet *now*, needed for migration */
+    s->completions_only = true;
+    qemu_bh_schedule(s->bh);
 }
 
 static int is_valid(uint32_t link)
@@ -1054,7 +1059,7 @@ static void uhci_process_frame(UHCIState *s)
     qhdb_reset(&qhdb);
 
     for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) {
-        if (s->frame_bytes >= s->frame_bandwidth) {
+        if (!s->completions_only && s->frame_bytes >= s->frame_bandwidth) {
             /* We've reached the usb 1.1 bandwidth, which is
                1280 bytes/frame, stop processing */
             trace_usb_uhci_frame_stop_bandwidth();
@@ -1170,6 +1175,7 @@ static void uhci_frame_timer(void *opaque)
     /* prepare the timer for the next frame */
     s->expire_time += (get_ticks_per_sec() / FRAME_TIMER_FREQ);
     s->frame_bytes = 0;
+    s->completions_only = false;
     qemu_bh_cancel(s->bh);
 
     if (!(s->cmd & UHCI_CMD_RS)) {

From 1cbdde909f70fd15ff85f068a6318b73865c7fa3 Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Sat, 17 Nov 2012 12:11:50 +0100
Subject: [PATCH 1703/2270] uhci: Don't allow the guest to set port-enabled
 when there is no dev connected

It is possible for device disconnect and the guest trying to reset the port
(because of USB xact errors prior to the disconnect getting signaled) to race,
when we hit this race, the guest will write the port-control register with its
pre-disconnect value + the reset bit set, after which we have a disconnected
device with its port-enabled bit set in its port-control register, which
is no good :)

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-uhci.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index ef326330d3..078be2ad6a 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -556,6 +556,10 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
                 }
             }
             port->ctrl &= UHCI_PORT_READ_ONLY;
+            /* enabled may only be set if a device is connected */
+            if (!(port->ctrl & UHCI_PORT_CCS)) {
+                val &= ~UHCI_PORT_EN;
+            }
             port->ctrl |= (val & ~UHCI_PORT_READ_ONLY);
             /* some bits are reset when a '1' is written to them */
             port->ctrl &= ~(val & UHCI_PORT_WRITE_CLEAR);

From 71d2c9cf656cb8b55a71057c1943ade197c1bb5b Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Sat, 17 Nov 2012 12:11:51 +0100
Subject: [PATCH 1704/2270] uhci: Fix double unlink

uhci_async_cancel() already does a uhci_async_unlink().

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-uhci.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 078be2ad6a..8e478030ad 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -963,7 +963,6 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet)
     UHCIState *s = async->queue->uhci;
 
     if (packet->status == USB_RET_REMOVE_FROM_QUEUE) {
-        uhci_async_unlink(async);
         uhci_async_cancel(async);
         return;
     }

From 33c1a6856f06fccd7cbfe53e06f9ebbe95bd565f Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Sat, 17 Nov 2012 12:15:01 +0100
Subject: [PATCH 1705/2270] usb-bt: Return NAK instead of STALL when interrupt
 ep has no data

I noticed this while making all devices with interrupt endpoints properly
do wakeup. While at it also add wakeup support.

Note that I've not tested this, but returning STALL for an interrupt ep
which has no data is cleary the wrong thing to do.

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/dev-bluetooth.c | 25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c
index bfb96bf9f0..39984f53eb 100644
--- a/hw/usb/dev-bluetooth.c
+++ b/hw/usb/dev-bluetooth.c
@@ -27,6 +27,7 @@
 struct USBBtState {
     USBDevice dev;
     struct HCIInfo *hci;
+    USBEndpoint *intr;
 
     int config;
 
@@ -290,10 +291,7 @@ static inline void usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo,
 {
     int len;
 
-    if (likely(!fifo->len)) {
-        p->status = USB_RET_STALL;
-        return;
-    }
+    assert(fifo->len != 0);
 
     len = MIN(p->iov.size, fifo->fifo[fifo->start].len);
     usb_packet_copy(p, fifo->fifo[fifo->start].data, len);
@@ -422,14 +420,26 @@ static void usb_bt_handle_data(USBDevice *dev, USBPacket *p)
     case USB_TOKEN_IN:
         switch (p->ep->nr) {
         case USB_EVT_EP:
+            if (s->evt.len == 0) {
+                p->status = USB_RET_NAK;
+                break;
+            }
             usb_bt_fifo_dequeue(&s->evt, p);
             break;
 
         case USB_ACL_EP:
+            if (s->evt.len == 0) {
+                p->status = USB_RET_STALL;
+                break;
+            }
             usb_bt_fifo_dequeue(&s->acl, p);
             break;
 
         case USB_SCO_EP:
+            if (s->evt.len == 0) {
+                p->status = USB_RET_STALL;
+                break;
+            }
             usb_bt_fifo_dequeue(&s->sco, p);
             break;
 
@@ -467,6 +477,9 @@ static void usb_bt_out_hci_packet_event(void *opaque,
 {
     struct USBBtState *s = (struct USBBtState *) opaque;
 
+    if (s->evt.len == 0) {
+        usb_wakeup(s->intr);
+    }
     usb_bt_fifo_enqueue(&s->evt, data, len);
 }
 
@@ -489,8 +502,12 @@ static void usb_bt_handle_destroy(USBDevice *dev)
 
 static int usb_bt_initfn(USBDevice *dev)
 {
+    struct USBBtState *s = DO_UPCAST(struct USBBtState, dev, dev);
+
     usb_desc_create_serial(dev);
     usb_desc_init(dev);
+    s->intr = usb_ep_get(dev, USB_TOKEN_IN, USB_EVT_EP);
+
     return 0;
 }
 

From c4020746ff49b2156b4f98672c077d1a3b86fa8b Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Sat, 17 Nov 2012 12:15:02 +0100
Subject: [PATCH 1706/2270] usb-smartcard-reader: Properly NAK interrupt eps
 when we've no events

When we've no data to return from the interrupt endpoint, return NAK rather
then a 0 length packet.

CC: Alon Levy 
Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/dev-smartcard-reader.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 190fcd62d4..de955b709f 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -1002,6 +1002,8 @@ static void ccid_handle_data(USBDevice *dev, USBPacket *p)
                         "handle_data: int_in: notify_slot_change %X, "
                         "requested len %zd\n",
                         s->bmSlotICCState, p->iov.size);
+            } else {
+                p->status = USB_RET_NAK;
             }
             break;
         default:

From 234e810cce018daf2030e04e399a17b744fa3e0d Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Sat, 17 Nov 2012 12:26:56 +0100
Subject: [PATCH 1707/2270] usb-redir: Split usb_handle_interrupt_data into
 separate in/out functions

No functional changes.

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/redirect.c | 148 ++++++++++++++++++++++++----------------------
 1 file changed, 77 insertions(+), 71 deletions(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 0c95e6b05e..66637a85da 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -610,80 +610,82 @@ static void usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
     p->status = USB_RET_ASYNC;
 }
 
-static void usbredir_handle_interrupt_data(USBRedirDevice *dev,
-                                           USBPacket *p, uint8_t ep)
+static void usbredir_handle_interrupt_in_data(USBRedirDevice *dev,
+                                              USBPacket *p, uint8_t ep)
 {
-    if (ep & USB_DIR_IN) {
-        /* Input interrupt endpoint, buffered packet input */
-        struct buf_packet *intp;
-        int status, len;
+    /* Input interrupt endpoint, buffered packet input */
+    struct buf_packet *intp;
+    int status, len;
 
-        if (!dev->endpoint[EP2I(ep)].interrupt_started &&
-                !dev->endpoint[EP2I(ep)].interrupt_error) {
-            struct usb_redir_start_interrupt_receiving_header start_int = {
-                .endpoint = ep,
-            };
-            /* No id, we look at the ep when receiving a status back */
-            usbredirparser_send_start_interrupt_receiving(dev->parser, 0,
-                                                          &start_int);
-            usbredirparser_do_write(dev->parser);
-            DPRINTF("interrupt recv started ep %02X\n", ep);
-            dev->endpoint[EP2I(ep)].interrupt_started = 1;
-            /* We don't really want to drop interrupt packets ever, but
-               having some upper limit to how much we buffer is good. */
-            dev->endpoint[EP2I(ep)].bufpq_target_size = 1000;
-            dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
-        }
-
-        intp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
-        if (intp == NULL) {
-            DPRINTF2("interrupt-token-in ep %02X, no intp\n", ep);
-            /* Check interrupt_error for stream errors */
-            status = dev->endpoint[EP2I(ep)].interrupt_error;
-            dev->endpoint[EP2I(ep)].interrupt_error = 0;
-            if (status) {
-                usbredir_handle_status(dev, p, status);
-            } else {
-                p->status = USB_RET_NAK;
-            }
-            return;
-        }
-        DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
-                intp->status, intp->len);
-
-        status = intp->status;
-        len = intp->len;
-        if (len > p->iov.size) {
-            ERROR("received int data is larger then packet ep %02X\n", ep);
-            len = p->iov.size;
-            status = usb_redir_babble;
-        }
-        usb_packet_copy(p, intp->data, len);
-        bufp_free(dev, intp, ep);
-        usbredir_handle_status(dev, p, status);
-    } else {
-        /* Output interrupt endpoint, normal async operation */
-        struct usb_redir_interrupt_packet_header interrupt_packet;
-        uint8_t buf[p->iov.size];
-
-        DPRINTF("interrupt-out ep %02X len %zd id %"PRIu64"\n", ep,
-                p->iov.size, p->id);
-
-        if (usbredir_already_in_flight(dev, p->id)) {
-            p->status = USB_RET_ASYNC;
-            return;
-        }
-
-        interrupt_packet.endpoint  = ep;
-        interrupt_packet.length    = p->iov.size;
-
-        usb_packet_copy(p, buf, p->iov.size);
-        usbredir_log_data(dev, "interrupt data out:", buf, p->iov.size);
-        usbredirparser_send_interrupt_packet(dev->parser, p->id,
-                                        &interrupt_packet, buf, p->iov.size);
+    if (!dev->endpoint[EP2I(ep)].interrupt_started &&
+            !dev->endpoint[EP2I(ep)].interrupt_error) {
+        struct usb_redir_start_interrupt_receiving_header start_int = {
+            .endpoint = ep,
+        };
+        /* No id, we look at the ep when receiving a status back */
+        usbredirparser_send_start_interrupt_receiving(dev->parser, 0,
+                                                      &start_int);
         usbredirparser_do_write(dev->parser);
-        p->status = USB_RET_ASYNC;
+        DPRINTF("interrupt recv started ep %02X\n", ep);
+        dev->endpoint[EP2I(ep)].interrupt_started = 1;
+        /* We don't really want to drop interrupt packets ever, but
+           having some upper limit to how much we buffer is good. */
+        dev->endpoint[EP2I(ep)].bufpq_target_size = 1000;
+        dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
     }
+
+    intp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
+    if (intp == NULL) {
+        DPRINTF2("interrupt-token-in ep %02X, no intp\n", ep);
+        /* Check interrupt_error for stream errors */
+        status = dev->endpoint[EP2I(ep)].interrupt_error;
+        dev->endpoint[EP2I(ep)].interrupt_error = 0;
+        if (status) {
+            usbredir_handle_status(dev, p, status);
+        } else {
+            p->status = USB_RET_NAK;
+        }
+        return;
+    }
+    DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
+            intp->status, intp->len);
+
+    status = intp->status;
+    len = intp->len;
+    if (len > p->iov.size) {
+        ERROR("received int data is larger then packet ep %02X\n", ep);
+        len = p->iov.size;
+        status = usb_redir_babble;
+    }
+    usb_packet_copy(p, intp->data, len);
+    bufp_free(dev, intp, ep);
+    usbredir_handle_status(dev, p, status);
+}
+
+static void usbredir_handle_interrupt_out_data(USBRedirDevice *dev,
+                                               USBPacket *p, uint8_t ep)
+{
+    /* Output interrupt endpoint, normal async operation */
+    struct usb_redir_interrupt_packet_header interrupt_packet;
+    uint8_t buf[p->iov.size];
+
+    DPRINTF("interrupt-out ep %02X len %zd id %"PRIu64"\n", ep,
+            p->iov.size, p->id);
+
+    if (usbredir_already_in_flight(dev, p->id)) {
+        p->status = USB_RET_ASYNC;
+        return;
+    }
+
+    interrupt_packet.endpoint  = ep;
+    interrupt_packet.length    = p->iov.size;
+
+    usb_packet_copy(p, buf, p->iov.size);
+    usbredir_log_data(dev, "interrupt data out:", buf, p->iov.size);
+    usbredirparser_send_interrupt_packet(dev->parser, p->id,
+                                    &interrupt_packet, buf, p->iov.size);
+    usbredirparser_do_write(dev->parser);
+    p->status = USB_RET_ASYNC;
 }
 
 static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev,
@@ -729,7 +731,11 @@ static void usbredir_handle_data(USBDevice *udev, USBPacket *p)
         usbredir_handle_bulk_data(dev, p, ep);
         break;
     case USB_ENDPOINT_XFER_INT:
-        usbredir_handle_interrupt_data(dev, p, ep);
+        if (ep & USB_DIR_IN) {
+            usbredir_handle_interrupt_in_data(dev, p, ep);
+        } else {
+            usbredir_handle_interrupt_out_data(dev, p, ep);
+        }
         break;
     default:
         ERROR("handle_data ep %02X has unknown type %d\n", ep,

From 723aedd53281cfa0997457cb156a59909a75f5a8 Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Sat, 17 Nov 2012 12:26:57 +0100
Subject: [PATCH 1708/2270] usb-redir: Don't handle interrupt output packets
 async

Instead report them as successfully completed directly on submission, this
has 2 advantages:

1) This matches the timing of interrupt output packets on real hardware,
with the previous async handling, if an ep has an interval of say 500 ms,
then there would be 500+ ms between the submission and the guest seeing the
completion, as we wont do the write back until the qh gets polled again. And
in the mean time the guest may very well have timed out, as the guest can
reasonable expect a much quicker completion.

2) This fixes interrupt output packets potentially getting send twice
surrounding a migration. As we delay the writeback to guest memory until
the qh gets polled again, there is a window between completion and writeback
where migration can happen, in this case the destination will not know
about the completion, and it will execute the packet *again*

But it does also come with a disadvantage:

1) If the actual interrupt out to the real usb device fails, there is no
way to report this back to the guest.

This patch assumes however that interrupt outs in practice never fail, as
they are only used by specialized drivers, which are unlikely to issue illegal
requests (unlike general class drivers which often issue requests which some
devices don't implement). And that thus the advantages outway the disadvantage.

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/redirect.c | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 66637a85da..490c90fae1 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -662,21 +662,22 @@ static void usbredir_handle_interrupt_in_data(USBRedirDevice *dev,
     usbredir_handle_status(dev, p, status);
 }
 
+/*
+ * Handle interrupt out data, the usbredir protocol expects us to do this
+ * async, so that it can report back a completion status. But guests will
+ * expect immediate completion for an interrupt endpoint, and handling this
+ * async causes migration issues. So we report success directly, counting
+ * on the fact that output interrupt packets normally always succeed.
+ */
 static void usbredir_handle_interrupt_out_data(USBRedirDevice *dev,
                                                USBPacket *p, uint8_t ep)
 {
-    /* Output interrupt endpoint, normal async operation */
     struct usb_redir_interrupt_packet_header interrupt_packet;
     uint8_t buf[p->iov.size];
 
     DPRINTF("interrupt-out ep %02X len %zd id %"PRIu64"\n", ep,
             p->iov.size, p->id);
 
-    if (usbredir_already_in_flight(dev, p->id)) {
-        p->status = USB_RET_ASYNC;
-        return;
-    }
-
     interrupt_packet.endpoint  = ep;
     interrupt_packet.length    = p->iov.size;
 
@@ -685,7 +686,6 @@ static void usbredir_handle_interrupt_out_data(USBRedirDevice *dev,
     usbredirparser_send_interrupt_packet(dev->parser, p->id,
                                     &interrupt_packet, buf, p->iov.size);
     usbredirparser_do_write(dev->parser);
-    p->status = USB_RET_ASYNC;
 }
 
 static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev,
@@ -1647,11 +1647,13 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id,
         /* bufp_alloc also adds the packet to the ep queue */
         bufp_alloc(dev, data, data_len, interrupt_packet->status, ep);
     } else {
-        USBPacket *p = usbredir_find_packet_by_id(dev, ep, id);
-        if (p) {
-            usbredir_handle_status(dev, p, interrupt_packet->status);
-            p->actual_length = interrupt_packet->length;
-            usb_packet_complete(&dev->dev, p);
+        /*
+         * We report output interrupt packets as completed directly upon
+         * submission, so all we can do here if one failed is warn.
+         */
+        if (interrupt_packet->status) {
+            WARNING("interrupt output failed status %d ep %02X id %"PRIu64"\n",
+                    interrupt_packet->status, ep, id);
         }
     }
 }

From c6e88b3b27b411e3f1c924deb8b71b20f8a11107 Mon Sep 17 00:00:00 2001
From: Bruce Rogers 
Date: Tue, 20 Nov 2012 07:11:21 -0700
Subject: [PATCH 1709/2270] Legacy qemu-kvm options have no argument

The options no-kvm, no-kvm-pit, no-kvm-pit-reinjection, and no-kvm-irqchip
should be marked as having no argument.

Signed-off-by: Bruce Rogers 
Reviewed-by: Jan Kiszka 
Signed-off-by: Marcelo Tosatti 
---
 qemu-options.hx | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index 9bb29d3907..fbcf079f47 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2918,17 +2918,17 @@ Enable FIPS 140-2 compliance mode.
 ETEXI
 
 HXCOMM Deprecated by -machine accel=tcg property
-DEF("no-kvm", HAS_ARG, QEMU_OPTION_no_kvm, "", QEMU_ARCH_I386)
+DEF("no-kvm", 0, QEMU_OPTION_no_kvm, "", QEMU_ARCH_I386)
 
 HXCOMM Deprecated by kvm-pit driver properties
-DEF("no-kvm-pit-reinjection", HAS_ARG, QEMU_OPTION_no_kvm_pit_reinjection,
+DEF("no-kvm-pit-reinjection", 0, QEMU_OPTION_no_kvm_pit_reinjection,
     "", QEMU_ARCH_I386)
 
 HXCOMM Deprecated (ignored)
-DEF("no-kvm-pit", HAS_ARG, QEMU_OPTION_no_kvm_pit, "", QEMU_ARCH_I386)
+DEF("no-kvm-pit", 0, QEMU_OPTION_no_kvm_pit, "", QEMU_ARCH_I386)
 
 HXCOMM Deprecated by -machine kernel_irqchip=on|off property
-DEF("no-kvm-irqchip", HAS_ARG, QEMU_OPTION_no_kvm_irqchip, "", QEMU_ARCH_I386)
+DEF("no-kvm-irqchip", 0, QEMU_OPTION_no_kvm_irqchip, "", QEMU_ARCH_I386)
 
 HXCOMM Deprecated (ignored)
 DEF("tdf", 0, QEMU_OPTION_tdf,"", QEMU_ARCH_ALL)

From d17bd1d8cc27f8c1a24c65f555a77a661c332b7f Mon Sep 17 00:00:00 2001
From: Aurelien Jarno 
Date: Tue, 9 Oct 2012 21:53:11 +0200
Subject: [PATCH 1710/2270] tcg/arm: fix TLB access in qemu-ld/st ops

The TCG arm backend considers likely that the offset to the TLB
entries does not exceed 12 bits for mem_index = 0. In practice this is
not true for at least the MIPS target.

The current patch fixes that by loading the bits 23-12 with a separate
instruction, and using loads with address writeback, independently of
the value of mem_idx. In total this allow a 24-bit offset, which is a
lot more than needed.

Cc: Andrzej Zaborowski 
Cc: Peter Maydell 
Cc: qemu-stable@nongnu.org
Signed-off-by: Aurelien Jarno 
---
 tcg/arm/tcg-target.c | 78 ++++++++++++++++++++++++--------------------
 1 file changed, 42 insertions(+), 36 deletions(-)

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index e790bf04b4..9550102714 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -639,6 +639,22 @@ static inline void tcg_out_ld32_12(TCGContext *s, int cond,
                         (rn << 16) | (rd << 12) | ((-im) & 0xfff));
 }
 
+/* Offset pre-increment with base writeback.  */
+static inline void tcg_out_ld32_12wb(TCGContext *s, int cond,
+                                     int rd, int rn, tcg_target_long im)
+{
+    /* ldr with writeback and both register equals is UNPREDICTABLE */
+    assert(rd != rn);
+
+    if (im >= 0) {
+        tcg_out32(s, (cond << 28) | 0x05b00000 |
+                        (rn << 16) | (rd << 12) | (im & 0xfff));
+    } else {
+        tcg_out32(s, (cond << 28) | 0x05300000 |
+                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
+    }
+}
+
 static inline void tcg_out_st32_12(TCGContext *s, int cond,
                 int rd, int rn, tcg_target_long im)
 {
@@ -1071,7 +1087,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 {
     int addr_reg, data_reg, data_reg2, bswap;
 #ifdef CONFIG_SOFTMMU
-    int mem_index, s_bits;
+    int mem_index, s_bits, tlb_offset;
     TCGReg argreg;
 # if TARGET_LONG_BITS == 64
     int addr_reg2;
@@ -1111,19 +1127,15 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
                     TCG_REG_R0, TCG_REG_R8, CPU_TLB_SIZE - 1);
     tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_AREG0,
                     TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
-    /* In the
-     *  ldr r1 [r0, #(offsetof(CPUArchState, tlb_table[mem_index][0].addr_read))]
-     * below, the offset is likely to exceed 12 bits if mem_index != 0 and
-     * not exceed otherwise, so use an
-     *  add r0, r0, #(mem_index * sizeof *CPUArchState.tlb_table)
-     * before.
-     */
-    if (mem_index)
+    /* We assume that the offset is contained within 20 bits.  */
+    tlb_offset = offsetof(CPUArchState, tlb_table[mem_index][0].addr_read);
+    assert(tlb_offset & ~0xfffff == 0);
+    if (tlb_offset > 0xfff) {
         tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
-                        (mem_index << (TLB_SHIFT & 1)) |
-                        ((16 - (TLB_SHIFT >> 1)) << 8));
-    tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R0,
-                    offsetof(CPUArchState, tlb_table[0][0].addr_read));
+                        0xa00 | (tlb_offset >> 12));
+        tlb_offset &= 0xfff;
+    }
+    tcg_out_ld32_12wb(s, COND_AL, TCG_REG_R1, TCG_REG_R0, tlb_offset);
     tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
                     TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
     /* Check alignment.  */
@@ -1131,15 +1143,14 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
         tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
                         0, addr_reg, (1 << s_bits) - 1);
 #  if TARGET_LONG_BITS == 64
-    /* XXX: possibly we could use a block data load or writeback in
-     * the first access.  */
-    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
-                    offsetof(CPUArchState, tlb_table[0][0].addr_read) + 4);
+    /* XXX: possibly we could use a block data load in the first access.  */
+    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0, 4);
     tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
                     TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
 #  endif
     tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
-                    offsetof(CPUArchState, tlb_table[0][0].addend));
+                    offsetof(CPUTLBEntry, addend)
+                    - offsetof(CPUTLBEntry, addr_read));
 
     switch (opc) {
     case 0:
@@ -1288,7 +1299,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
 {
     int addr_reg, data_reg, data_reg2, bswap;
 #ifdef CONFIG_SOFTMMU
-    int mem_index, s_bits;
+    int mem_index, s_bits, tlb_offset;
     TCGReg argreg;
 # if TARGET_LONG_BITS == 64
     int addr_reg2;
@@ -1325,19 +1336,15 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
                     TCG_REG_R0, TCG_REG_R8, CPU_TLB_SIZE - 1);
     tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0,
                     TCG_AREG0, TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
-    /* In the
-     *  ldr r1 [r0, #(offsetof(CPUArchState, tlb_table[mem_index][0].addr_write))]
-     * below, the offset is likely to exceed 12 bits if mem_index != 0 and
-     * not exceed otherwise, so use an
-     *  add r0, r0, #(mem_index * sizeof *CPUArchState.tlb_table)
-     * before.
-     */
-    if (mem_index)
+    /* We assume that the offset is contained within 20 bits.  */
+    tlb_offset = offsetof(CPUArchState, tlb_table[mem_index][0].addr_write);
+    assert(tlb_offset & ~0xfffff == 0);
+    if (tlb_offset > 0xfff) {
         tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
-                        (mem_index << (TLB_SHIFT & 1)) |
-                        ((16 - (TLB_SHIFT >> 1)) << 8));
-    tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R0,
-                    offsetof(CPUArchState, tlb_table[0][0].addr_write));
+                        0xa00 | (tlb_offset >> 12));
+        tlb_offset &= 0xfff;
+    }
+    tcg_out_ld32_12wb(s, COND_AL, TCG_REG_R1, TCG_REG_R0, tlb_offset);
     tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
                     TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
     /* Check alignment.  */
@@ -1345,15 +1352,14 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
         tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
                         0, addr_reg, (1 << s_bits) - 1);
 #  if TARGET_LONG_BITS == 64
-    /* XXX: possibly we could use a block data load or writeback in
-     * the first access.  */
-    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
-                    offsetof(CPUArchState, tlb_table[0][0].addr_write) + 4);
+    /* XXX: possibly we could use a block data load in the first access.  */
+    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0, 4);
     tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
                     TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
 #  endif
     tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
-                    offsetof(CPUArchState, tlb_table[0][0].addend));
+                    offsetof(CPUTLBEntry, addend)
+                    - offsetof(CPUTLBEntry, addr_write));
 
     switch (opc) {
     case 0:

From 7aab08aa786e3a8838beac758ee61c5000144937 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno 
Date: Tue, 9 Oct 2012 21:53:11 +0200
Subject: [PATCH 1711/2270] tcg/arm: fix cross-endian qemu_st16

The bswap16 TCG opcode assumes that the high bytes of the temp equal
to 0 before calling it. The ARM backend implementation takes this
assumption to slightly optimize the generated code.

The same implementation is called for implementing the cross-endian
qemu_st16 opcode, where this assumption is not true anymore. One way to
fix that would be to zero the high bytes before calling it. Given the
store instruction just ignore them, it is possible to provide a slightly
more optimized version. With ARMv6+ the rev16 instruction does the work
correctly. For lower ARM versions the patch provides a version which
behaves correctly with non-zero high bytes, but fill them with junk.

Cc: Andrzej Zaborowski 
Cc: Peter Maydell 
Cc: qemu-stable@nongnu.org
Reviewed-by: Peter Maydell 
Signed-off-by: Aurelien Jarno 
---
 tcg/arm/tcg-target.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 9550102714..47612fe260 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -611,6 +611,22 @@ static inline void tcg_out_bswap16(TCGContext *s, int cond, int rd, int rn)
     }
 }
 
+/* swap the two low bytes assuming that the two high input bytes and the
+   two high output bit can hold any value. */
+static inline void tcg_out_bswap16st(TCGContext *s, int cond, int rd, int rn)
+{
+    if (use_armv6_instructions) {
+        /* rev16 */
+        tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
+    } else {
+        tcg_out_dat_reg(s, cond, ARITH_MOV,
+                        TCG_REG_R8, 0, rn, SHIFT_IMM_LSR(8));
+        tcg_out_dat_imm(s, cond, ARITH_AND, TCG_REG_R8, TCG_REG_R8, 0xff);
+        tcg_out_dat_reg(s, cond, ARITH_ORR,
+                        rd, TCG_REG_R8, rn, SHIFT_IMM_LSL(8));
+    }
+}
+
 static inline void tcg_out_bswap32(TCGContext *s, int cond, int rd, int rn)
 {
     if (use_armv6_instructions) {
@@ -1367,7 +1383,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
         break;
     case 1:
         if (bswap) {
-            tcg_out_bswap16(s, COND_EQ, TCG_REG_R0, data_reg);
+            tcg_out_bswap16st(s, COND_EQ, TCG_REG_R0, data_reg);
             tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
         } else {
             tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
@@ -1453,7 +1469,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
         break;
     case 1:
         if (bswap) {
-            tcg_out_bswap16(s, COND_AL, TCG_REG_R0, data_reg);
+            tcg_out_bswap16st(s, COND_AL, TCG_REG_R0, data_reg);
             tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addr_reg, 0);
         } else {
             tcg_out_st16_8(s, COND_AL, data_reg, addr_reg, 0);

From 44e04d3b945ba6f5cc87e65192081da4783f73fa Mon Sep 17 00:00:00 2001
From: Aurelien Jarno 
Date: Tue, 9 Oct 2012 21:53:12 +0200
Subject: [PATCH 1712/2270] target-openrisc: remove conflicting definitions
 from cpu.h

On an ARM host, the registers definitions from cpu.h clash
with /usr/include/sys/ucontext.h. As there are unused, just remove
them.

Cc: Jia Liu 
Cc: qemu-stable@nongnu.org
Reviewed-by: Peter Maydell 
Signed-off-by: Aurelien Jarno 
---
 target-openrisc/cpu.h | 18 ------------------
 1 file changed, 18 deletions(-)

diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index d42ffb09b6..ebb5ad3124 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -89,24 +89,6 @@ enum {
 /* Interrupt */
 #define NR_IRQS  32
 
-/* Registers */
-enum {
-    R0 = 0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10,
-    R11, R12, R13, R14, R15, R16, R17, R18, R19, R20,
-    R21, R22, R23, R24, R25, R26, R27, R28, R29, R30,
-    R31
-};
-
-/* Register aliases */
-enum {
-    R_ZERO = R0,
-    R_SP = R1,
-    R_FP = R2,
-    R_LR = R9,
-    R_RV = R11,
-    R_RVH = R12
-};
-
 /* Unit presece register */
 enum {
     UPR_UP = (1 << 0),

From d132c79f6b68622e8a115327d1f60176e1816c7c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=99=B3=E9=9F=8B=E4=BB=BB=20=28Wei-Ren=20Chen=29?=
 
Date: Wed, 21 Nov 2012 13:50:45 +0800
Subject: [PATCH 1713/2270] target-mips: Add comments on POOL32Axf encoding

  Current QEMU MIPS POOL32AXF encoding comes from microMIPS32
and microMIPS32 DSP. Add comment here to help reading.

Signed-off-by: Chen Wei-Ren 
Reviewed-by: Eric Johnson 
Signed-off-by: Aurelien Jarno 
---
 target-mips/translate.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 8b438f8bb0..7a85d21429 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -10359,6 +10359,19 @@ enum {
 
 /* POOL32AXF encoding of minor opcode field extension */
 
+/*
+ * 1. MIPS Architecture for Programmers Volume II-B:
+ *      The microMIPS32 Instruction Set (Revision 3.05)
+ *
+ *    Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
+ *
+ * 2. MIPS Architecture for Programmers VolumeIV-e:
+ *      The MIPS DSP Application-Specific Extension
+ *        to the microMIPS32 Architecture (Revision 2.34)
+ *
+ *    Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
+ */
+
 enum {
     /* bits 11..6 */
     TEQ = 0x00,
@@ -10371,6 +10384,8 @@ enum {
     MFC0 = 0x03,
     MTC0 = 0x0b,
 
+    /* begin of microMIPS32 DSP */
+
     /* bits 13..12 for 0x01 */
     MFHI_ACC = 0x0,
     MFLO_ACC = 0x1,
@@ -10387,6 +10402,8 @@ enum {
     MULT_ACC = 0x0,
     MULTU_ACC = 0x1,
 
+    /* end of microMIPS32 DSP */
+
     /* bits 15..12 for 0x2c */
     SEB = 0x2,
     SEH = 0x3,

From 211da99290c8d570eee78f3f534f7e7d9d8f9da8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=99=B3=E9=9F=8B=E4=BB=BB=20=28Wei-Ren=20Chen=29?=
 
Date: Wed, 21 Nov 2012 14:04:41 +0800
Subject: [PATCH 1714/2270] target-mips: Clean up microMIPS32 major opcode

  I check MIPS microMIPS manual [1], and found the major opcode might
be wrong. I add a comment to explicitly indicate what manual I am refering
to, and according that manual I remove microMIPS32 major opcodes 0x1f.
As for others, like 0x16, 0x17, 0x36 and 0x37, they are for higher-order
MIPS ISA level or new revision of this microMIPS architecture. Quote
from Johnson, they are belong MIPS64 [2].

[1] http://www.mips.com/products/architectures/micromips/#specifications

    MIPS Architecture for Programmers Volume II-B:
      The microMIPS32 Instruction Set (Revision 3.05)

    MD00582-2B-microMIPS-AFP-03.05.pdf

[2] http://www.mips.com/products/architectures/mips64/

    MIPS Architecture For Programmers
      Volume II-A: The MIPS64 Instruction Set

    MD00087-2B-MIPS64BIS-AFP-03.51.pdf

Signed-off-by: Chen Wei-Ren 
Reviewed-by: Eric Johnson 
Signed-off-by: Aurelien Jarno 
---
 target-mips/translate.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 7a85d21429..5342591a88 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -10239,9 +10239,19 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
     return n_bytes;
 }
 
-/* microMIPS extension to MIPS32 */
+/* microMIPS extension to MIPS32/MIPS64 */
 
-/* microMIPS32 major opcodes */
+/*
+ * microMIPS32/microMIPS64 major opcodes
+ *
+ * 1. MIPS Architecture for Programmers Volume II-B:
+ *      The microMIPS32 Instruction Set (Revision 3.05)
+ *
+ *    Table 6.2 microMIPS32 Encoding of Major Opcode Field
+ *
+ * 2. MIPS Architecture For Programmers Volume II-A:
+ *      The MIPS64 Instruction Set (Revision 3.51)
+ */
 
 enum {
     POOL32A = 0x00,
@@ -10268,9 +10278,10 @@ enum {
     POOL16D = 0x13,
     ORI32 = 0x14,
     POOL32F = 0x15,
-    POOL32S = 0x16,
-    DADDIU32 = 0x17,
+    POOL32S = 0x16,  /* MIPS64 */
+    DADDIU32 = 0x17, /* MIPS64 */
 
+    /* 0x1f is reserved */
     POOL32C = 0x18,
     LWGP16 = 0x19,
     LW16 = 0x1a,
@@ -10278,7 +10289,6 @@ enum {
     XORI32 = 0x1c,
     JALS32 = 0x1d,
     ADDIUPC = 0x1e,
-    POOL48A = 0x1f,
 
     /* 0x20 is reserved */
     RES_20 = 0x20,
@@ -10307,8 +10317,8 @@ enum {
     B16 = 0x33,
     ANDI32 = 0x34,
     J32 = 0x35,
-    SD32 = 0x36,
-    LD32 = 0x37,
+    SD32 = 0x36, /* MIPS64 */
+    LD32 = 0x37, /* MIPS64 */
 
     /* 0x38 and 0x39 are reserved */
     RES_38 = 0x38,

From e5138db510efb61523be92c225d8c65eb985fff0 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno 
Date: Sat, 24 Nov 2012 11:53:55 +0100
Subject: [PATCH 1715/2270] tcg: mark local temps as MEM in dead_temp()

In dead_temp, local temps should always be marked as back to memory,
even if they have not been allocated (i.e. they are discared before
cross a basic block).

It fixes the following assertion in target-xtensa:

    qemu-system-xtensa: tcg/tcg.c:1665: temp_save: Assertion `s->temps[temp].val_type == 2 || s->temps[temp].fixed_reg' failed.
    Aborted

Reported-by: Max Filippov 
Tested-by: Max Filippov 
Signed-off-by: Aurelien Jarno 
---
 tcg/tcg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 4f756962c5..cb193f2683 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1615,7 +1615,7 @@ static inline void temp_dead(TCGContext *s, int temp)
         if (ts->val_type == TEMP_VAL_REG) {
             s->reg_to_temp[ts->reg] = -1;
         }
-        if (temp < s->nb_globals || (ts->temp_local && ts->mem_allocated)) {
+        if (temp < s->nb_globals || ts->temp_local) {
             ts->val_type = TEMP_VAL_MEM;
         } else {
             ts->val_type = TEMP_VAL_DEAD;

From 31abf92447353ee09ecad0b3b18e458eef3a1215 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno 
Date: Sat, 24 Nov 2012 13:35:06 +0100
Subject: [PATCH 1716/2270] target-mips: remove POOL48A from the microMIPS
 decoding

Signed-off-by: Aurelien Jarno 
---
 target-mips/translate.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 5342591a88..71c55bcadb 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -12383,7 +12383,6 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b
         case LB32:
         case LH32:
         case DADDIU32:
-        case POOL48A:           /* ??? */
         case LWC132:
         case LDC132:
         case LD32:

From c6c5063c7a5bb1d3fe6b9931a1ec15294e39b8b1 Mon Sep 17 00:00:00 2001
From: Richard Henderson 
Date: Mon, 19 Nov 2012 12:43:14 -0800
Subject: [PATCH 1717/2270] tci: Fix type of tci_read_label

Fixes the pointer truncation that was occurring for branches.

Cc: Stefan Weil 
Cc: Blue Swirl 
Signed-off-by: Richard Henderson 
Reviewed-by: Stefan Weil 
Tested-by: Stefan Weil 
Signed-off-by: Blue Swirl 
---
 tci.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tci.c b/tci.c
index 9c87c8e8b3..54cf1d9524 100644
--- a/tci.c
+++ b/tci.c
@@ -338,9 +338,9 @@ static uint64_t tci_read_ri64(uint8_t **tb_ptr)
 }
 #endif
 
-static target_ulong tci_read_label(uint8_t **tb_ptr)
+static tcg_target_ulong tci_read_label(uint8_t **tb_ptr)
 {
-    target_ulong label = tci_read_i(tb_ptr);
+    tcg_target_ulong label = tci_read_i(tb_ptr);
     assert(label != 0);
     return label;
 }

From 89c9bc3d147fdaa932db99b0463b4af1d3e7cda1 Mon Sep 17 00:00:00 2001
From: Stefan Weil 
Date: Thu, 22 Nov 2012 07:25:48 +0100
Subject: [PATCH 1718/2270] block: Fix regression for MinGW (assertion caused
 by short string)

The local string tmp_filename is passed to function get_tmp_filename
which expects a string with minimum size MAX_PATH for w32 hosts.

MAX_PATH is 260 and PATH_MAX is 259, so tmp_filename was too short.

Commit eba25057b9a5e19d10ace2bc7716667a31297169 introduced this
regression.

Signed-off-by: Stefan Weil 
Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Blue Swirl 
---
 block.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/block.c b/block.c
index 854ebd60d4..c05875fe39 100644
--- a/block.c
+++ b/block.c
@@ -787,7 +787,8 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
               BlockDriver *drv)
 {
     int ret;
-    char tmp_filename[PATH_MAX];
+    /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
+    char tmp_filename[PATH_MAX + 1];
 
     if (flags & BDRV_O_SNAPSHOT) {
         BlockDriverState *bs1;

From a85903ff80f9bfa6390069856a8ec706b0b5ad5a Mon Sep 17 00:00:00 2001
From: Wenchao Xia 
Date: Sat, 24 Nov 2012 17:27:18 +0800
Subject: [PATCH 1719/2270] Build system fix distclean error for pixman

  Currently Makefile test if pixman have configure log, but the script directly
return error if that file do not exist. This patch fix it.

Signed-off-by: Wenchao Xia 
Reviewed-by: Peter Maydell 
Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Blue Swirl 
---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 3e8d441637..9ecbcbb0a7 100644
--- a/Makefile
+++ b/Makefile
@@ -286,7 +286,7 @@ distclean: clean
 	for d in $(TARGET_DIRS) $(QEMULIBS); do \
 	rm -rf $$d || exit 1 ; \
         done
-	test -f pixman/config.log && make -C pixman distclean
+	if test -f pixman/config.log; then make -C pixman distclean; fi
 
 KEYMAPS=da     en-gb  et  fr     fr-ch  is  lt  modifiers  no  pt-br  sv \
 ar      de     en-us  fi  fr-be  hr     it  lv  nl         pl  ru     th \

From 06dec08374a4a4bd882994a3dfd103e314584c4c Mon Sep 17 00:00:00 2001
From: Jan Kiszka 
Date: Thu, 22 Nov 2012 18:30:02 +0100
Subject: [PATCH 1720/2270] chardev: Use real-time clock for open timer

The vm clock may be stopped, and then we won't get open events anymore.
Seen with QMP sessions.

Reported-by: Dietmar Maurer 
Tested-by: Luiz Capitulino 
Signed-off-by: Jan Kiszka 
Signed-off-by: Blue Swirl 
---
 qemu-char.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index 88f40254b7..242b799909 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -134,9 +134,9 @@ static void qemu_chr_fire_open_event(void *opaque)
 void qemu_chr_generic_open(CharDriverState *s)
 {
     if (s->open_timer == NULL) {
-        s->open_timer = qemu_new_timer_ms(vm_clock,
+        s->open_timer = qemu_new_timer_ms(rt_clock,
                                           qemu_chr_fire_open_event, s);
-        qemu_mod_timer(s->open_timer, qemu_get_clock_ms(vm_clock) - 1);
+        qemu_mod_timer(s->open_timer, qemu_get_clock_ms(rt_clock) - 1);
     }
 }
 

From 7eff57421ff31657434545104b9f91a28e7869ff Mon Sep 17 00:00:00 2001
From: Catalin Patulea 
Date: Fri, 9 Nov 2012 19:01:26 -0500
Subject: [PATCH 1721/2270] vnc: fix option misspelling ("non-adapative" ->
 "non-adaptive")

Signed-off-by: Catalin Patulea 
Signed-off-by: Anthony Liguori 
---
 ui/vnc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index 61f120e315..ba303626ad 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2945,7 +2945,7 @@ void vnc_display_open(DisplayState *ds, const char *display, Error **errp)
 #endif
         } else if (strncmp(options, "lossy", 5) == 0) {
             vs->lossy = true;
-        } else if (strncmp(options, "non-adapative", 13) == 0) {
+        } else if (strncmp(options, "non-adaptive", 12) == 0) {
             vs->non_adaptive = true;
         } else if (strncmp(options, "share=", 6) == 0) {
             if (strncmp(options+6, "ignore", 6) == 0) {

From 9011a1a7bbf00deeada3447143bbde7e0a685297 Mon Sep 17 00:00:00 2001
From: Isaku Yamahata 
Date: Wed, 14 Nov 2012 15:54:01 -0500
Subject: [PATCH 1722/2270] pc, pc_piix: split out pc nic initialization

Factor out pc nic initialization.
This simplifies the pc initialization and will reduce the code
duplication of q35 pc initialization.

Reviewed-by: Paolo Bonzini 
Reviewed-by: Anthony Liguori 
Signed-off-by: Isaku Yamahata 
Signed-off-by: Jason Baron 
Signed-off-by: Anthony Liguori 
---
 hw/pc.c      | 15 +++++++++++++++
 hw/pc.h      |  1 +
 hw/pc_piix.c |  9 +--------
 3 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 4aca4986dd..04553f8d36 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1058,6 +1058,21 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
     *floppy = fdctrl_init_isa(isa_bus, fd);
 }
 
+void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus)
+{
+    int i;
+
+    for (i = 0; i < nb_nics; i++) {
+        NICInfo *nd = &nd_table[i];
+
+        if (!pci_bus || (nd->model && strcmp(nd->model, "ne2k_isa") == 0)) {
+            pc_init_ne2k_isa(isa_bus, nd);
+        } else {
+            pci_nic_init_nofail(nd, "e1000", NULL);
+        }
+    }
+}
+
 void pc_pci_device_init(PCIBus *pci_bus)
 {
     int max_bus;
diff --git a/hw/pc.h b/hw/pc.h
index e7993ca5d9..d6639a69c4 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -98,6 +98,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
                   const char *boot_device,
                   ISADevice *floppy, BusState *ide0, BusState *ide1,
                   ISADevice *s);
+void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus);
 void pc_pci_device_init(PCIBus *pci_bus);
 
 typedef void (*cpu_set_smm_t)(int smm, void *arg);
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index cfa839c8b4..910d417002 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -234,14 +234,7 @@ static void pc_init1(MemoryRegion *system_memory,
     /* init basic PC hardware */
     pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled());
 
-    for(i = 0; i < nb_nics; i++) {
-        NICInfo *nd = &nd_table[i];
-
-        if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
-            pc_init_ne2k_isa(isa_bus, nd);
-        else
-            pci_nic_init_nofail(nd, "e1000", NULL);
-    }
+    pc_nic_init(isa_bus, pci_bus);
 
     ide_drive_get(hd, MAX_IDE_BUS);
     if (pci_enabled) {

From a39e356458335418973ca7d388c02712145cd177 Mon Sep 17 00:00:00 2001
From: Jason Baron 
Date: Wed, 14 Nov 2012 15:54:01 -0500
Subject: [PATCH 1723/2270] pc: Move ioapic_init() from pc_piix.c to pc.c

Move ioapic_init() from pc_piix.c to pc.c, to make it a common function.
Rename ioapic_init() -> ioapic_init_gsi().
Move to pc.h so q35 can use them as well.

Reviewed-by: Paolo Bonzini 
Signed-off-by: Jason Baron 
Signed-off-by: Anthony Liguori 
---
 hw/pc.c      | 24 ++++++++++++++++++++++++
 hw/pc.h      |  2 ++
 hw/pc_piix.c | 25 +------------------------
 3 files changed, 27 insertions(+), 24 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 04553f8d36..2b5bbbfb30 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1083,3 +1083,27 @@ void pc_pci_device_init(PCIBus *pci_bus)
         pci_create_simple(pci_bus, -1, "lsi53c895a");
     }
 }
+
+void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
+{
+    DeviceState *dev;
+    SysBusDevice *d;
+    unsigned int i;
+
+    if (kvm_irqchip_in_kernel()) {
+        dev = qdev_create(NULL, "kvm-ioapic");
+    } else {
+        dev = qdev_create(NULL, "ioapic");
+    }
+    if (parent_name) {
+        object_property_add_child(object_resolve_path(parent_name, NULL),
+                                  "ioapic", OBJECT(dev), NULL);
+    }
+    qdev_init_nofail(dev);
+    d = sysbus_from_qdev(dev);
+    sysbus_mmio_map(d, 0, 0xfec00000);
+
+    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+        gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
+    }
+}
diff --git a/hw/pc.h b/hw/pc.h
index d6639a69c4..2237e86446 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -104,6 +104,8 @@ void pc_pci_device_init(PCIBus *pci_bus);
 typedef void (*cpu_set_smm_t)(int smm, void *arg);
 void cpu_smm_register(cpu_set_smm_t callback, void *arg);
 
+void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name);
+
 /* acpi.c */
 extern int acpi_enabled;
 extern char *acpi_tables;
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 910d417002..e460799b1b 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -95,29 +95,6 @@ static void kvm_piix3_gsi_handler(void *opaque, int n, int level)
     }
 }
 
-static void ioapic_init(GSIState *gsi_state)
-{
-    DeviceState *dev;
-    SysBusDevice *d;
-    unsigned int i;
-
-    if (kvm_irqchip_in_kernel()) {
-        dev = qdev_create(NULL, "kvm-ioapic");
-    } else {
-        dev = qdev_create(NULL, "ioapic");
-    }
-    /* FIXME: this should be under the piix3.  */
-    object_property_add_child(object_resolve_path("i440fx", NULL),
-                              "ioapic", OBJECT(dev), NULL);
-    qdev_init_nofail(dev);
-    d = sysbus_from_qdev(dev);
-    sysbus_mmio_map(d, 0, 0xfec00000);
-
-    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
-        gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
-    }
-}
-
 /* PC hardware initialisation */
 static void pc_init1(MemoryRegion *system_memory,
                      MemoryRegion *system_io,
@@ -221,7 +198,7 @@ static void pc_init1(MemoryRegion *system_memory,
         gsi_state->i8259_irq[i] = i8259[i];
     }
     if (pci_enabled) {
-        ioapic_init(gsi_state);
+        ioapic_init_gsi(gsi_state, "i440fx");
     }
 
     pc_register_ferr_irq(gsi[13]);

From d8ee03843fcacfb70c0260af74f20ba9808d4f2e Mon Sep 17 00:00:00 2001
From: Jason Baron 
Date: Wed, 14 Nov 2012 15:54:02 -0500
Subject: [PATCH 1724/2270] pc_piix: Move kvm irq routing functions out of
 pc_piix.c

Rename: kvm_piix3_gsi_handlei() -> kvm_pc_gsi_handler()
        kvm_piix3_setup_irq_routing() -> kvm_pc_setup_irq_routing()

This is in preparation for other users, namely q35 at this time.

Signed-off-by: Jason Baron 
Signed-off-by: Anthony Liguori 
---
 hw/kvm/ioapic.c | 40 ++++++++++++++++++++++++++++++++++++++++
 hw/pc_piix.c    | 45 ++-------------------------------------------
 kvm.h           |  2 ++
 3 files changed, 44 insertions(+), 43 deletions(-)

diff --git a/hw/kvm/ioapic.c b/hw/kvm/ioapic.c
index 6c3b8fe39a..f95c157591 100644
--- a/hw/kvm/ioapic.c
+++ b/hw/kvm/ioapic.c
@@ -15,6 +15,46 @@
 #include "hw/apic_internal.h"
 #include "kvm.h"
 
+/* PC Utility function */
+void kvm_pc_setup_irq_routing(bool pci_enabled)
+{
+    KVMState *s = kvm_state;
+    int i;
+
+    if (kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) {
+        for (i = 0; i < 8; ++i) {
+            if (i == 2) {
+                continue;
+            }
+            kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_MASTER, i);
+        }
+        for (i = 8; i < 16; ++i) {
+            kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_SLAVE, i - 8);
+        }
+        if (pci_enabled) {
+            for (i = 0; i < 24; ++i) {
+                if (i == 0) {
+                    kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, 2);
+                } else if (i != 2) {
+                    kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, i);
+                }
+            }
+        }
+    }
+}
+
+void kvm_pc_gsi_handler(void *opaque, int n, int level)
+{
+    GSIState *s = opaque;
+
+    if (n < ISA_NUM_IRQS) {
+        /* Kernel will forward to both PIC and IOAPIC */
+        qemu_set_irq(s->i8259_irq[n], level);
+    } else {
+        qemu_set_irq(s->ioapic_irq[n], level);
+    }
+}
+
 typedef struct KVMIOAPICState KVMIOAPICState;
 
 struct KVMIOAPICState {
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index e460799b1b..aa3e7f40dc 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -54,47 +54,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 void kvm_piix3_setup_irq_routing(bool pci_enabled)
-{
-#ifdef CONFIG_KVM
-    KVMState *s = kvm_state;
-    int i;
-
-    if (kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) {
-        for (i = 0; i < 8; ++i) {
-            if (i == 2) {
-                continue;
-            }
-            kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_MASTER, i);
-        }
-        for (i = 8; i < 16; ++i) {
-            kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_SLAVE, i - 8);
-        }
-        if (pci_enabled) {
-            for (i = 0; i < 24; ++i) {
-                if (i == 0) {
-                    kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, 2);
-                } else if (i != 2) {
-                    kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, i);
-                }
-            }
-        }
-    }
-#endif /* CONFIG_KVM */
-}
-
-static void kvm_piix3_gsi_handler(void *opaque, int n, int level)
-{
-    GSIState *s = opaque;
-
-    if (n < ISA_NUM_IRQS) {
-        /* Kernel will forward to both PIC and IOAPIC */
-        qemu_set_irq(s->i8259_irq[n], level);
-    } else {
-        qemu_set_irq(s->ioapic_irq[n], level);
-    }
-}
-
 /* PC hardware initialisation */
 static void pc_init1(MemoryRegion *system_memory,
                      MemoryRegion *system_io,
@@ -160,8 +119,8 @@ static void pc_init1(MemoryRegion *system_memory,
 
     gsi_state = g_malloc0(sizeof(*gsi_state));
     if (kvm_irqchip_in_kernel()) {
-        kvm_piix3_setup_irq_routing(pci_enabled);
-        gsi = qemu_allocate_irqs(kvm_piix3_gsi_handler, gsi_state,
+        kvm_pc_setup_irq_routing(pci_enabled);
+        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
                                  GSI_NUM_PINS);
     } else {
         gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
diff --git a/kvm.h b/kvm.h
index 1e7f244561..72d866a966 100644
--- a/kvm.h
+++ b/kvm.h
@@ -275,4 +275,6 @@ void kvm_irqchip_release_virq(KVMState *s, int virq);
 
 int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
 int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
+void kvm_pc_gsi_handler(void *opaque, int n, int level);
+void kvm_pc_setup_irq_routing(bool pci_enabled);
 #endif

From 410edd922d2a90c79cd92b086c0e53650ea52c02 Mon Sep 17 00:00:00 2001
From: Isaku Yamahata 
Date: Wed, 14 Nov 2012 15:54:02 -0500
Subject: [PATCH 1725/2270] pc/piix_pci: factor out smram/pam logic

Factor out smram/pam logic for use by other chipsets, namely q35
at this point.

Note: Should be factored out into a generic North Bridge Class.

[jbaron@redhat.com: changes for updated memory API]
Signed-off-by: Isaku Yamahata 
Signed-off-by: Jason Baron 
Signed-off-by: Anthony Liguori 
---
 hw/Makefile.objs |  1 +
 hw/pam.c         | 87 +++++++++++++++++++++++++++++++++++++++++++
 hw/pam.h         | 97 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/piix_pci.c    | 68 ++++++++-------------------------
 4 files changed, 200 insertions(+), 53 deletions(-)
 create mode 100644 hw/pam.c
 create mode 100644 hw/pam.h

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index ea46f8128e..5ebe6afd91 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -38,6 +38,7 @@ common-obj-$(CONFIG_SMARTCARD) += ccid-card-passthru.o
 common-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
 common-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
 common-obj-y += fifo.o
+common-obj-y += pam.o
 
 # PPC devices
 common-obj-$(CONFIG_PREP_PCI) += prep_pci.o
diff --git a/hw/pam.c b/hw/pam.c
new file mode 100644
index 0000000000..a95e2cfb07
--- /dev/null
+++ b/hw/pam.c
@@ -0,0 +1,87 @@
+/*
+ * QEMU i440FX/PIIX3 PCI Bridge Emulation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2011 Isaku Yamahata 
+ *                    VA Linux Systems Japan K.K.
+ * Copyright (c) 2012 Jason Baron 
+ *
+ * Split out from piix_pci.c
+ *
+ * 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 "sysemu.h"
+#include "pam.h"
+
+void smram_update(MemoryRegion *smram_region, uint8_t smram,
+                  uint8_t smm_enabled)
+{
+    bool smram_enabled;
+
+    smram_enabled = ((smm_enabled && (smram & SMRAM_G_SMRAME)) ||
+                        (smram & SMRAM_D_OPEN));
+    memory_region_set_enabled(smram_region, !smram_enabled);
+}
+
+void smram_set_smm(uint8_t *host_smm_enabled, int smm, uint8_t smram,
+                   MemoryRegion *smram_region)
+{
+    uint8_t smm_enabled = (smm != 0);
+    if (*host_smm_enabled != smm_enabled) {
+        *host_smm_enabled = smm_enabled;
+        smram_update(smram_region, smram, *host_smm_enabled);
+    }
+}
+
+void init_pam(MemoryRegion *ram_memory, MemoryRegion *system_memory,
+              MemoryRegion *pci_address_space, PAMMemoryRegion *mem,
+              uint32_t start, uint32_t size)
+{
+    int i;
+
+    /* RAM */
+    memory_region_init_alias(&mem->alias[3], "pam-ram", ram_memory,
+                             start, size);
+    /* ROM (XXX: not quite correct) */
+    memory_region_init_alias(&mem->alias[1], "pam-rom", ram_memory,
+                             start, size);
+    memory_region_set_readonly(&mem->alias[1], true);
+
+    /* XXX: should distinguish read/write cases */
+    memory_region_init_alias(&mem->alias[0], "pam-pci", pci_address_space,
+                             start, size);
+    memory_region_init_alias(&mem->alias[2], "pam-pci", pci_address_space,
+                             start, size);
+
+    for (i = 0; i < 4; ++i) {
+        memory_region_set_enabled(&mem->alias[i], false);
+        memory_region_add_subregion_overlap(system_memory, start,
+                                            &mem->alias[i], 1);
+    }
+    mem->current = 0;
+}
+
+void pam_update(PAMMemoryRegion *pam, int idx, uint8_t val)
+{
+    assert(0 <= idx && idx <= 12);
+
+    memory_region_set_enabled(&pam->alias[pam->current], false);
+    pam->current = (val >> ((!(idx & 1)) * 4)) & PAM_ATTR_MASK;
+    memory_region_set_enabled(&pam->alias[pam->current], true);
+}
diff --git a/hw/pam.h b/hw/pam.h
new file mode 100644
index 0000000000..2d77ebe0d9
--- /dev/null
+++ b/hw/pam.h
@@ -0,0 +1,97 @@
+#ifndef QEMU_PAM_H
+#define QEMU_PAM_H
+
+/*
+ * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2011 Isaku Yamahata 
+ *               VA Linux Systems Japan K.K.
+ * Copyright (c) 2012 Jason Baron 
+ *
+ * Split out from piix_pci.c
+ *
+ * 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.
+ */
+
+/*
+ * SMRAM memory area and PAM memory area in Legacy address range for PC.
+ * PAM: Programmable Attribute Map registers
+ *
+ * 0xa0000 - 0xbffff compatible SMRAM
+ *
+ * 0xc0000 - 0xc3fff Expansion area memory segments
+ * 0xc4000 - 0xc7fff
+ * 0xc8000 - 0xcbfff
+ * 0xcc000 - 0xcffff
+ * 0xd0000 - 0xd3fff
+ * 0xd4000 - 0xd7fff
+ * 0xd8000 - 0xdbfff
+ * 0xdc000 - 0xdffff
+ * 0xe0000 - 0xe3fff Extended System BIOS Area Memory Segments
+ * 0xe4000 - 0xe7fff
+ * 0xe8000 - 0xebfff
+ * 0xec000 - 0xeffff
+ *
+ * 0xf0000 - 0xfffff System BIOS Area Memory Segments
+ */
+
+#include "qemu-common.h"
+#include "memory.h"
+
+#define SMRAM_C_BASE    0xa0000
+#define SMRAM_C_END     0xc0000
+#define SMRAM_C_SIZE    0x20000
+
+#define PAM_EXPAN_BASE  0xc0000
+#define PAM_EXPAN_SIZE  0x04000
+
+#define PAM_EXBIOS_BASE 0xe0000
+#define PAM_EXBIOS_SIZE 0x04000
+
+#define PAM_BIOS_BASE   0xf0000
+#define PAM_BIOS_END    0xfffff
+/* 64KB: Intel 3 series express chipset family p. 58*/
+#define PAM_BIOS_SIZE   0x10000
+
+/* PAM registers: log nibble and high nibble*/
+#define PAM_ATTR_WE     ((uint8_t)2)
+#define PAM_ATTR_RE     ((uint8_t)1)
+#define PAM_ATTR_MASK   ((uint8_t)3)
+
+/* SMRAM register */
+#define SMRAM_D_OPEN           ((uint8_t)(1 << 6))
+#define SMRAM_D_CLS            ((uint8_t)(1 << 5))
+#define SMRAM_D_LCK            ((uint8_t)(1 << 4))
+#define SMRAM_G_SMRAME         ((uint8_t)(1 << 3))
+#define SMRAM_C_BASE_SEG_MASK  ((uint8_t)0x7)
+#define SMRAM_C_BASE_SEG       ((uint8_t)0x2)  /* hardwired to b010 */
+
+typedef struct PAMMemoryRegion {
+    MemoryRegion alias[4];  /* index = PAM value */
+    unsigned current;
+} PAMMemoryRegion;
+
+void smram_update(MemoryRegion *smram_region, uint8_t smram,
+                  uint8_t smm_enabled);
+void smram_set_smm(uint8_t *host_smm_enabled, int smm, uint8_t smram,
+                   MemoryRegion *smram_region);
+void init_pam(MemoryRegion *ram, MemoryRegion *system, MemoryRegion *pci,
+              PAMMemoryRegion *mem, uint32_t start, uint32_t size);
+void pam_update(PAMMemoryRegion *mem, int idx, uint8_t val);
+
+#endif /* QEMU_PAM_H */
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 9af5847690..ba1b3de749 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -30,6 +30,7 @@
 #include "sysbus.h"
 #include "range.h"
 #include "xen.h"
+#include "pam.h"
 
 /*
  * I440FX chipset data sheet.
@@ -68,11 +69,6 @@ typedef struct PIIX3State {
     int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
 } PIIX3State;
 
-typedef struct PAMMemoryRegion {
-    MemoryRegion alias[4];  /* index = PAM value */
-    unsigned current;
-} PAMMemoryRegion;
-
 struct PCII440FXState {
     PCIDevice dev;
     MemoryRegion *system_memory;
@@ -105,52 +101,16 @@ static int pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx)
     return (pci_intx + slot_addend) & 3;
 }
 
-static void init_pam(PCII440FXState *d, PAMMemoryRegion *mem,
-                     uint32_t start, uint32_t size)
+static void i440fx_update_memory_mappings(PCII440FXState *d)
 {
     int i;
 
-    /* RAM */
-    memory_region_init_alias(&mem->alias[3], "pam-ram", d->ram_memory, start, size);
-    /* ROM (XXX: not quite correct) */
-    memory_region_init_alias(&mem->alias[1], "pam-rom", d->ram_memory, start, size);
-    memory_region_set_readonly(&mem->alias[1], true);
-
-    /* XXX: should distinguish read/write cases */
-    memory_region_init_alias(&mem->alias[0], "pam-pci", d->pci_address_space,
-                             start, size);
-    memory_region_init_alias(&mem->alias[2], "pam-pci", d->pci_address_space,
-                             start, size);
-
-    for (i = 0; i < 4; ++i) {
-        memory_region_set_enabled(&mem->alias[i], false);
-        memory_region_add_subregion_overlap(d->system_memory, start, &mem->alias[i], 1);
-    }
-    mem->current = 0;
-}
-
-static void update_pam(PAMMemoryRegion *pam, unsigned r)
-{
-    memory_region_set_enabled(&pam->alias[pam->current], false);
-    pam->current = r;
-    memory_region_set_enabled(&pam->alias[pam->current], true);
-}
-
-static void i440fx_update_memory_mappings(PCII440FXState *d)
-{
-    int i, r;
-    uint32_t smram;
-    bool smram_enabled;
-
     memory_region_transaction_begin();
-    update_pam(&d->pam_regions[0], (d->dev.config[I440FX_PAM] >> 4) & 3);
-    for(i = 0; i < 12; i++) {
-        r = (d->dev.config[(i >> 1) + (I440FX_PAM + 1)] >> ((i & 1) * 4)) & 3;
-        update_pam(&d->pam_regions[i+1], r);
+    for (i = 0; i < 13; i++) {
+        pam_update(&d->pam_regions[i], i,
+                   d->dev.config[I440FX_PAM + ((i + 1) / 2)]);
     }
-    smram = d->dev.config[I440FX_SMRAM];
-    smram_enabled = (d->smm_enabled && (smram & 0x08)) || (smram & 0x40);
-    memory_region_set_enabled(&d->smram_region, !smram_enabled);
+    smram_update(&d->smram_region, d->dev.config[I440FX_SMRAM], d->smm_enabled);
     memory_region_transaction_commit();
 }
 
@@ -158,11 +118,10 @@ static void i440fx_set_smm(int val, void *arg)
 {
     PCII440FXState *d = arg;
 
-    val = (val != 0);
-    if (d->smm_enabled != val) {
-        d->smm_enabled = val;
-        i440fx_update_memory_mappings(d);
-    }
+    memory_region_transaction_begin();
+    smram_set_smm(&d->smm_enabled, val, d->dev.config[I440FX_SMRAM],
+                  &d->smram_region);
+    memory_region_transaction_commit();
 }
 
 
@@ -300,9 +259,12 @@ static PCIBus *i440fx_common_init(const char *device_name,
     memory_region_add_subregion_overlap(f->system_memory, 0xa0000,
                                         &f->smram_region, 1);
     memory_region_set_enabled(&f->smram_region, false);
-    init_pam(f, &f->pam_regions[0], 0xf0000, 0x10000);
+    init_pam(f->ram_memory, f->system_memory, f->pci_address_space,
+             &f->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE);
     for (i = 0; i < 12; ++i) {
-        init_pam(f, &f->pam_regions[i+1], 0xc0000 + i * 0x4000, 0x4000);
+        init_pam(f->ram_memory, f->system_memory, f->pci_address_space,
+                 &f->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE,
+                 PAM_EXPAN_SIZE);
     }
 
     /* Xen supports additional interrupt routes from the PCI devices to

From e516572fdefdf1168e890d1fd79d56cd44aa2102 Mon Sep 17 00:00:00 2001
From: Jason Baron 
Date: Thu, 22 Nov 2012 22:05:06 -0500
Subject: [PATCH 1726/2270] ich9: Add acpi support and definitions

Lay the groundwork for subsequent ich9 support.

Signed-off-by: Isaku Yamahata 
Signed-off-by: Jason Baron 
Signed-off-by: Anthony Liguori 
---
 hw/Makefile.objs |   2 +-
 hw/acpi_ich9.c   | 315 +++++++++++++++++++++++++++++++++++++++++++++++
 hw/acpi_ich9.h   |  47 +++++++
 hw/ich9.h        | 207 +++++++++++++++++++++++++++++++
 hw/pci_ids.h     |  12 ++
 5 files changed, 582 insertions(+), 1 deletion(-)
 create mode 100644 hw/acpi_ich9.c
 create mode 100644 hw/acpi_ich9.h
 create mode 100644 hw/ich9.h

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 5ebe6afd91..b863b3145a 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -28,7 +28,7 @@ common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
 common-obj-$(CONFIG_PCSPK) += pcspk.o
 common-obj-$(CONFIG_PCKBD) += pckbd.o
 common-obj-$(CONFIG_FDC) += fdc.o
-common-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
+common-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o acpi_ich9.o
 common-obj-$(CONFIG_APM) += pm_smbus.o apm.o
 common-obj-$(CONFIG_DMA) += dma.o
 common-obj-$(CONFIG_I82374) += i82374.o
diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
new file mode 100644
index 0000000000..c45921c243
--- /dev/null
+++ b/hw/acpi_ich9.c
@@ -0,0 +1,315 @@
+/*
+ * ACPI implementation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see 
+ */
+/*
+ *  Copyright (c) 2009 Isaku Yamahata 
+ *                     VA Linux Systems Japan K.K.
+ *  Copyright (C) 2012 Jason Baron 
+ *
+ *  This is based on acpi.c.
+ */
+#include "hw.h"
+#include "pc.h"
+#include "pci.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
+#include "acpi.h"
+
+#include "ich9.h"
+
+//#define DEBUG
+
+#ifdef DEBUG
+#define ICH9_DEBUG(fmt, ...) \
+do { printf("%s "fmt, __func__, ## __VA_ARGS__); } while (0)
+#else
+#define ICH9_DEBUG(fmt, ...)    do { } while (0)
+#endif
+
+static void pm_ioport_write_fallback(void *opaque, uint32_t addr, int len,
+                                     uint32_t val);
+static uint32_t pm_ioport_read_fallback(void *opaque, uint32_t addr, int len);
+
+static void pm_update_sci(ICH9LPCPMRegs *pm)
+{
+    int sci_level, pm1a_sts;
+
+    pm1a_sts = acpi_pm1_evt_get_sts(&pm->acpi_regs);
+
+    sci_level = (((pm1a_sts & pm->acpi_regs.pm1.evt.en) &
+                  (ACPI_BITMASK_RT_CLOCK_ENABLE |
+                   ACPI_BITMASK_POWER_BUTTON_ENABLE |
+                   ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
+                   ACPI_BITMASK_TIMER_ENABLE)) != 0);
+    qemu_set_irq(pm->irq, sci_level);
+
+    /* schedule a timer interruption if needed */
+    acpi_pm_tmr_update(&pm->acpi_regs,
+                       (pm->acpi_regs.pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) &&
+                       !(pm1a_sts & ACPI_BITMASK_TIMER_STATUS));
+}
+
+static void ich9_pm_update_sci_fn(ACPIREGS *regs)
+{
+    ICH9LPCPMRegs *pm = container_of(regs, ICH9LPCPMRegs, acpi_regs);
+    pm_update_sci(pm);
+}
+
+static void pm_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    ICH9LPCPMRegs *pm = opaque;
+
+    switch (addr & ICH9_PMIO_MASK) {
+    case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + ICH9_PMIO_GPE0_LEN - 1):
+        acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val);
+        break;
+    default:
+        break;
+    }
+
+    ICH9_DEBUG("port=0x%04x val=0x%04x\n", addr, val);
+}
+
+static uint32_t pm_ioport_readb(void *opaque, uint32_t addr)
+{
+    ICH9LPCPMRegs *pm = opaque;
+    uint32_t val = 0;
+
+    switch (addr & ICH9_PMIO_MASK) {
+    case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + ICH9_PMIO_GPE0_LEN - 1):
+        val = acpi_gpe_ioport_readb(&pm->acpi_regs, addr);
+        break;
+    default:
+        val = 0;
+        break;
+    }
+    ICH9_DEBUG("port=0x%04x val=0x%04x\n", addr, val);
+    return val;
+}
+
+static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
+{
+    ICH9LPCPMRegs *pm = opaque;
+
+    switch (addr & ICH9_PMIO_MASK) {
+    case ICH9_PMIO_PM1_STS:
+        acpi_pm1_evt_write_sts(&pm->acpi_regs, val);
+        pm_update_sci(pm);
+        break;
+    case ICH9_PMIO_PM1_EN:
+        pm->acpi_regs.pm1.evt.en = val;
+        pm_update_sci(pm);
+        break;
+    case ICH9_PMIO_PM1_CNT:
+        acpi_pm1_cnt_write(&pm->acpi_regs, val, 0);
+        break;
+    default:
+        pm_ioport_write_fallback(opaque, addr, 2, val);
+        break;
+    }
+    ICH9_DEBUG("port=0x%04x val=0x%04x\n", addr, val);
+}
+
+static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
+{
+    ICH9LPCPMRegs *pm = opaque;
+    uint32_t val;
+
+    switch (addr & ICH9_PMIO_MASK) {
+    case ICH9_PMIO_PM1_STS:
+        val = acpi_pm1_evt_get_sts(&pm->acpi_regs);
+        break;
+    case ICH9_PMIO_PM1_EN:
+        val = pm->acpi_regs.pm1.evt.en;
+        break;
+    case ICH9_PMIO_PM1_CNT:
+        val = pm->acpi_regs.pm1.cnt.cnt;
+        break;
+    default:
+        val = pm_ioport_read_fallback(opaque, addr, 2);
+        break;
+    }
+    ICH9_DEBUG("port=0x%04x val=0x%04x\n", addr, val);
+    return val;
+}
+
+static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+    ICH9LPCPMRegs *pm = opaque;
+
+    switch (addr & ICH9_PMIO_MASK) {
+    case ICH9_PMIO_SMI_EN:
+        pm->smi_en = val;
+        break;
+    default:
+        pm_ioport_write_fallback(opaque, addr, 4, val);
+        break;
+    }
+    ICH9_DEBUG("port=0x%04x val=0x%08x\n", addr, val);
+}
+
+static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
+{
+    ICH9LPCPMRegs *pm = opaque;
+    uint32_t val;
+
+    switch (addr & ICH9_PMIO_MASK) {
+    case ICH9_PMIO_PM1_TMR:
+        val = acpi_pm_tmr_get(&pm->acpi_regs);
+        break;
+    case ICH9_PMIO_SMI_EN:
+        val = pm->smi_en;
+        break;
+
+    default:
+        val = pm_ioport_read_fallback(opaque, addr, 4);
+        break;
+    }
+    ICH9_DEBUG("port=0x%04x val=0x%08x\n", addr, val);
+    return val;
+}
+
+static void pm_ioport_write_fallback(void *opaque, uint32_t addr, int len,
+                                     uint32_t val)
+ {
+    int subsize = (len == 4) ? 2 : 1;
+    IOPortWriteFunc *ioport_write =
+        (subsize == 2) ? pm_ioport_writew : pm_ioport_writeb;
+
+    int i;
+
+    for (i = 0; i < len; i += subsize) {
+        ioport_write(opaque, addr, val);
+        val >>= 8 * subsize;
+    }
+}
+
+static uint32_t pm_ioport_read_fallback(void *opaque, uint32_t addr, int len)
+{
+    int subsize = (len == 4) ? 2 : 1;
+    IOPortReadFunc *ioport_read =
+        (subsize == 2) ? pm_ioport_readw : pm_ioport_readb;
+
+    uint32_t val;
+    int i;
+
+    val = 0;
+    for (i = 0; i < len; i += subsize) {
+        val <<= 8 * subsize;
+        val |= ioport_read(opaque, addr);
+    }
+
+    return val;
+}
+
+void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base)
+{
+    ICH9_DEBUG("to 0x%x\n", pm_io_base);
+
+    assert((pm_io_base & ICH9_PMIO_MASK) == 0);
+
+    if (pm->pm_io_base != 0) {
+        isa_unassign_ioport(pm->pm_io_base, ICH9_PMIO_SIZE);
+    }
+
+    /* don't map at 0 */
+    if (pm_io_base == 0) {
+        return;
+    }
+
+    register_ioport_write(pm_io_base, ICH9_PMIO_SIZE, 1, pm_ioport_writeb, pm);
+    register_ioport_read(pm_io_base, ICH9_PMIO_SIZE, 1, pm_ioport_readb, pm);
+    register_ioport_write(pm_io_base, ICH9_PMIO_SIZE, 2, pm_ioport_writew, pm);
+    register_ioport_read(pm_io_base, ICH9_PMIO_SIZE, 2, pm_ioport_readw, pm);
+    register_ioport_write(pm_io_base, ICH9_PMIO_SIZE, 4, pm_ioport_writel, pm);
+    register_ioport_read(pm_io_base, ICH9_PMIO_SIZE, 4, pm_ioport_readl, pm);
+
+    pm->pm_io_base = pm_io_base;
+    acpi_gpe_blk(&pm->acpi_regs, pm_io_base + ICH9_PMIO_GPE0_STS);
+}
+
+static int ich9_pm_post_load(void *opaque, int version_id)
+{
+    ICH9LPCPMRegs *pm = opaque;
+    uint32_t pm_io_base = pm->pm_io_base;
+    pm->pm_io_base = 0;
+    ich9_pm_iospace_update(pm, pm_io_base);
+    return 0;
+}
+
+#define VMSTATE_GPE_ARRAY(_field, _state)                            \
+ {                                                                   \
+     .name       = (stringify(_field)),                              \
+     .version_id = 0,                                                \
+     .num        = ICH9_PMIO_GPE0_LEN,                               \
+     .info       = &vmstate_info_uint8,                              \
+     .size       = sizeof(uint8_t),                                  \
+     .flags      = VMS_ARRAY | VMS_POINTER,                          \
+     .offset     = vmstate_offset_pointer(_state, _field, uint8_t),  \
+ }
+
+const VMStateDescription vmstate_ich9_pm = {
+    .name = "ich9_pm",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = ich9_pm_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT16(acpi_regs.pm1.evt.sts, ICH9LPCPMRegs),
+        VMSTATE_UINT16(acpi_regs.pm1.evt.en, ICH9LPCPMRegs),
+        VMSTATE_UINT16(acpi_regs.pm1.cnt.cnt, ICH9LPCPMRegs),
+        VMSTATE_TIMER(acpi_regs.tmr.timer, ICH9LPCPMRegs),
+        VMSTATE_INT64(acpi_regs.tmr.overflow_time, ICH9LPCPMRegs),
+        VMSTATE_GPE_ARRAY(acpi_regs.gpe.sts, ICH9LPCPMRegs),
+        VMSTATE_GPE_ARRAY(acpi_regs.gpe.en, ICH9LPCPMRegs),
+        VMSTATE_UINT32(smi_en, ICH9LPCPMRegs),
+        VMSTATE_UINT32(smi_sts, ICH9LPCPMRegs),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void pm_reset(void *opaque)
+{
+    ICH9LPCPMRegs *pm = opaque;
+    ich9_pm_iospace_update(pm, 0);
+
+    acpi_pm1_evt_reset(&pm->acpi_regs);
+    acpi_pm1_cnt_reset(&pm->acpi_regs);
+    acpi_pm_tmr_reset(&pm->acpi_regs);
+    acpi_gpe_reset(&pm->acpi_regs);
+
+    pm_update_sci(pm);
+}
+
+static void pm_powerdown_req(Notifier *n, void *opaque)
+{
+    ICH9LPCPMRegs *pm = container_of(n, ICH9LPCPMRegs, powerdown_notifier);
+
+    acpi_pm1_evt_power_down(&pm->acpi_regs);
+}
+
+void ich9_pm_init(ICH9LPCPMRegs *pm, qemu_irq sci_irq, qemu_irq cmos_s3)
+{
+    acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn);
+    acpi_pm1_cnt_init(&pm->acpi_regs);
+    acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
+
+    pm->irq = sci_irq;
+    qemu_register_reset(pm_reset, pm);
+    pm->powerdown_notifier.notify = pm_powerdown_req;
+    qemu_register_powerdown_notifier(&pm->powerdown_notifier);
+}
diff --git a/hw/acpi_ich9.h b/hw/acpi_ich9.h
new file mode 100644
index 0000000000..180c40673b
--- /dev/null
+++ b/hw/acpi_ich9.h
@@ -0,0 +1,47 @@
+/*
+ * QEMU GMCH/ICH9 LPC PM Emulation
+ *
+ *  Copyright (c) 2009 Isaku Yamahata 
+ *                     VA Linux Systems Japan K.K.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see 
+ */
+
+#ifndef HW_ACPI_ICH9_H
+#define HW_ACPI_ICH9_H
+
+#include "acpi.h"
+
+typedef struct ICH9LPCPMRegs {
+    /*
+     * In ich9 spec says that pm1_cnt register is 32bit width and
+     * that the upper 16bits are reserved and unused.
+     * PM1a_CNT_BLK = 2 in FADT so it is defined as uint16_t.
+     */
+    ACPIREGS acpi_regs;
+    uint32_t smi_en;
+    uint32_t smi_sts;
+
+    qemu_irq irq;      /* SCI */
+
+    uint32_t pm_io_base;
+    Notifier powerdown_notifier;
+} ICH9LPCPMRegs;
+
+void ich9_pm_init(ICH9LPCPMRegs *pm,
+                  qemu_irq sci_irq, qemu_irq cmos_s3_resume);
+void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base);
+extern const VMStateDescription vmstate_ich9_pm;
+
+#endif /* HW_ACPI_ICH9_H */
diff --git a/hw/ich9.h b/hw/ich9.h
new file mode 100644
index 0000000000..de491350c3
--- /dev/null
+++ b/hw/ich9.h
@@ -0,0 +1,207 @@
+#ifndef HW_ICH9_H
+#define HW_ICH9_H
+
+#include "hw.h"
+#include "range.h"
+#include "isa.h"
+#include "sysbus.h"
+#include "pc.h"
+#include "apm.h"
+#include "ioapic.h"
+#include "pci.h"
+#include "pcie_host.h"
+#include "pci_bridge.h"
+#include "acpi.h"
+#include "acpi_ich9.h"
+#include "pam.h"
+#include "pci_internals.h"
+
+void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
+int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx);
+void ich9_lpc_pm_init(PCIDevice *pci_lpc, qemu_irq cmos_s3);
+PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int sec_bus);
+i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base);
+
+#define ICH9_CC_SIZE                            (16 * 1024)     /* 16KB */
+
+#define TYPE_ICH9_LPC_DEVICE "ICH9 LPC"
+#define ICH9_LPC_DEVICE(obj) \
+     OBJECT_CHECK(ICH9LPCState, (obj), TYPE_ICH9_LPC_DEVICE)
+
+typedef struct ICH9LPCState {
+    /* ICH9 LPC PCI to ISA bridge */
+    PCIDevice d;
+
+    /* (pci device, intx) -> pirq
+     * In real chipset case, the unused slots are never used
+     * as ICH9 supports only D25-D32 irq routing.
+     * On the other hand in qemu case, any slot/function can be populated
+     * via command line option.
+     * So fallback interrupt routing for any devices in any slots is necessary.
+    */
+    uint8_t irr[PCI_SLOT_MAX][PCI_NUM_PINS];
+
+    APMState apm;
+    ICH9LPCPMRegs pm;
+    uint32_t sci_level; /* track sci level */
+
+    /* 10.1 Chipset Configuration registers(Memory Space)
+     which is pointed by RCBA */
+    uint8_t chip_config[ICH9_CC_SIZE];
+    /* isa bus */
+    ISABus *isa_bus;
+    MemoryRegion rbca_mem;
+
+    qemu_irq *pic;
+    qemu_irq *ioapic;
+} ICH9LPCState;
+
+#define Q35_MASK(bit, ms_bit, ls_bit) \
+((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1)))
+
+/* ICH9: Chipset Configuration Registers */
+#define ICH9_CC_ADDR_MASK                       (ICH9_CC_SIZE - 1)
+
+#define ICH9_CC
+#define ICH9_CC_D28IP                           0x310C
+#define ICH9_CC_D28IP_SHIFT                     4
+#define ICH9_CC_D28IP_MASK                      0xf
+#define ICH9_CC_D28IP_DEFAULT                   0x00214321
+#define ICH9_CC_D31IR                           0x3140
+#define ICH9_CC_D30IR                           0x3142
+#define ICH9_CC_D29IR                           0x3144
+#define ICH9_CC_D28IR                           0x3146
+#define ICH9_CC_D27IR                           0x3148
+#define ICH9_CC_D26IR                           0x314C
+#define ICH9_CC_D25IR                           0x3150
+#define ICH9_CC_DIR_DEFAULT                     0x3210
+#define ICH9_CC_D30IR_DEFAULT                   0x0
+#define ICH9_CC_DIR_SHIFT                       4
+#define ICH9_CC_DIR_MASK                        0x7
+#define ICH9_CC_OIC                             0x31FF
+#define ICH9_CC_OIC_AEN                         0x1
+
+/* D28:F[0-5] */
+#define ICH9_PCIE_DEV                           28
+#define ICH9_PCIE_FUNC_MAX                      6
+
+
+/* D29:F0 USB UHCI Controller #1 */
+#define ICH9_USB_UHCI1_DEV                      29
+#define ICH9_USB_UHCI1_FUNC                     0
+
+/* D30:F0 DMI-to-PCI brdige */
+#define ICH9_D2P_BRIDGE                         "ICH9 D2P BRIDGE"
+#define ICH9_D2P_BRIDGE_SAVEVM_VERSION          0
+
+#define ICH9_D2P_BRIDGE_DEV                     30
+#define ICH9_D2P_BRIDGE_FUNC                    0
+
+#define ICH9_D2P_SECONDARY_DEFAULT              (256 - 8)
+
+#define ICH9_D2P_A2_REVISION                    0x92
+
+
+/* D31:F1 LPC controller */
+#define ICH9_A2_LPC                             "ICH9 A2 LPC"
+#define ICH9_A2_LPC_SAVEVM_VERSION              0
+
+#define ICH9_LPC_DEV                            31
+#define ICH9_LPC_FUNC                           0
+
+#define ICH9_A2_LPC_REVISION                    0x2
+#define ICH9_LPC_NB_PIRQS                       8       /* PCI A-H */
+
+#define ICH9_LPC_PMBASE                         0x40
+#define ICH9_LPC_PMBASE_BASE_ADDRESS_MASK       Q35_MASK(32, 15, 7)
+#define ICH9_LPC_PMBASE_RTE                     0x1
+#define ICH9_LPC_PMBASE_DEFAULT                 0x1
+#define ICH9_LPC_ACPI_CTRL                      0x44
+#define ICH9_LPC_ACPI_CTRL_ACPI_EN              0x80
+#define ICH9_LPC_ACPI_CTRL_SCI_IRQ_SEL_MASK     Q35_MASK(8, 2, 0)
+#define ICH9_LPC_ACPI_CTRL_9                    0x0
+#define ICH9_LPC_ACPI_CTRL_10                   0x1
+#define ICH9_LPC_ACPI_CTRL_11                   0x2
+#define ICH9_LPC_ACPI_CTRL_20                   0x4
+#define ICH9_LPC_ACPI_CTRL_21                   0x5
+#define ICH9_LPC_ACPI_CTRL_DEFAULT              0x0
+
+#define ICH9_LPC_PIRQA_ROUT                     0x60
+#define ICH9_LPC_PIRQB_ROUT                     0x61
+#define ICH9_LPC_PIRQC_ROUT                     0x62
+#define ICH9_LPC_PIRQD_ROUT                     0x63
+
+#define ICH9_LPC_PIRQE_ROUT                     0x68
+#define ICH9_LPC_PIRQF_ROUT                     0x69
+#define ICH9_LPC_PIRQG_ROUT                     0x6a
+#define ICH9_LPC_PIRQH_ROUT                     0x6b
+
+#define ICH9_LPC_PIRQ_ROUT_IRQEN                0x80
+#define ICH9_LPC_PIRQ_ROUT_MASK                 Q35_MASK(8, 3, 0)
+#define ICH9_LPC_PIRQ_ROUT_DEFAULT              0x80
+
+#define ICH9_LPC_RCBA                           0xf0
+#define ICH9_LPC_RCBA_BA_MASK                   Q35_MASK(32, 31, 14)
+#define ICH9_LPC_RCBA_EN                        0x1
+#define ICH9_LPC_RCBA_DEFAULT                   0x0
+
+#define ICH9_LPC_PIC_NUM_PINS                   16
+#define ICH9_LPC_IOAPIC_NUM_PINS                24
+
+/* D31:F2 SATA Controller #1 */
+#define ICH9_SATA1_DEV                          31
+#define ICH9_SATA1_FUNC                         2
+
+/* D30:F1 power management I/O registers
+   offset from the address ICH9_LPC_PMBASE */
+
+/* ICH9 LPC PM I/O registers are 128 ports and 128-aligned */
+#define ICH9_PMIO_SIZE                          128
+#define ICH9_PMIO_MASK                          (ICH9_PMIO_SIZE - 1)
+
+#define ICH9_PMIO_PM1_STS                       0x00
+#define ICH9_PMIO_PM1_EN                        0x02
+#define ICH9_PMIO_PM1_CNT                       0x04
+#define ICH9_PMIO_PM1_TMR                       0x08
+#define ICH9_PMIO_GPE0_STS                      0x20
+#define ICH9_PMIO_GPE0_EN                       0x28
+#define ICH9_PMIO_GPE0_LEN                      16
+#define ICH9_PMIO_SMI_EN                        0x30
+#define ICH9_PMIO_SMI_EN_APMC_EN                (1 << 5)
+#define ICH9_PMIO_SMI_STS                       0x34
+
+/* FADT ACPI_ENABLE/ACPI_DISABLE */
+#define ICH9_APM_ACPI_ENABLE                    0x2
+#define ICH9_APM_ACPI_DISABLE                   0x3
+
+
+/* D31:F3 SMBus controller */
+#define ICH9_A2_SMB_REVISION                    0x02
+#define ICH9_SMB_PI                             0x00
+
+#define ICH9_SMB_SMBMBAR0                       0x10
+#define ICH9_SMB_SMBMBAR1                       0x14
+#define ICH9_SMB_SMBM_BAR                       0
+#define ICH9_SMB_SMBM_SIZE                      (1 << 8)
+#define ICH9_SMB_SMB_BASE                       0x20
+#define ICH9_SMB_SMB_BASE_BAR                   4
+#define ICH9_SMB_SMB_BASE_SIZE                  (1 << 5)
+#define ICH9_SMB_HOSTC                          0x40
+#define ICH9_SMB_HOSTC_SSRESET                  ((uint8_t)(1 << 3))
+#define ICH9_SMB_HOSTC_I2C_EN                   ((uint8_t)(1 << 2))
+#define ICH9_SMB_HOSTC_SMB_SMI_EN               ((uint8_t)(1 << 1))
+#define ICH9_SMB_HOSTC_HST_EN                   ((uint8_t)(1 << 0))
+
+/* D31:F3 SMBus I/O and memory mapped I/O registers */
+#define ICH9_SMB_DEV                            31
+#define ICH9_SMB_FUNC                           3
+
+#define ICH9_SMB_HST_STS                        0x00
+#define ICH9_SMB_HST_CNT                        0x02
+#define ICH9_SMB_HST_CMD                        0x03
+#define ICH9_SMB_XMIT_SLVA                      0x04
+#define ICH9_SMB_HST_D0                         0x05
+#define ICH9_SMB_HST_D1                         0x06
+#define ICH9_SMB_HOST_BLOCK_DB                  0x07
+
+#endif /* HW_ICH9_H */
diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index 41f3570fb9..d1e83ddd06 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -36,6 +36,7 @@
 #define PCI_CLASS_BRIDGE_HOST            0x0600
 #define PCI_CLASS_BRIDGE_ISA             0x0601
 #define PCI_CLASS_BRIDGE_PCI             0x0604
+#define PCI_CLASS_BRDIGE_PCI_INF_SUB     0x01
 #define PCI_CLASS_BRIDGE_OTHER           0x0680
 
 #define PCI_CLASS_COMMUNICATION_SERIAL   0x0700
@@ -116,6 +117,17 @@
 #define PCI_DEVICE_ID_INTEL_82371AB      0x7111
 #define PCI_DEVICE_ID_INTEL_82371AB_2    0x7112
 #define PCI_DEVICE_ID_INTEL_82371AB_3    0x7113
+
+#define PCI_DEVICE_ID_INTEL_ICH9_0       0x2910
+#define PCI_DEVICE_ID_INTEL_ICH9_1       0x2917
+#define PCI_DEVICE_ID_INTEL_ICH9_2       0x2912
+#define PCI_DEVICE_ID_INTEL_ICH9_3       0x2913
+#define PCI_DEVICE_ID_INTEL_ICH9_4       0x2914
+#define PCI_DEVICE_ID_INTEL_ICH9_5       0x2919
+#define PCI_DEVICE_ID_INTEL_ICH9_6       0x2930
+#define PCI_DEVICE_ID_INTEL_ICH9_7       0x2916
+#define PCI_DEVICE_ID_INTEL_ICH9_8       0x2918
+
 #define PCI_DEVICE_ID_INTEL_82801I_UHCI1 0x2934
 #define PCI_DEVICE_ID_INTEL_82801I_UHCI2 0x2935
 #define PCI_DEVICE_ID_INTEL_82801I_UHCI3 0x2936

From 4d00636e97b7f55810ff7faccff594159175e24e Mon Sep 17 00:00:00 2001
From: Jason Baron 
Date: Wed, 14 Nov 2012 15:54:05 -0500
Subject: [PATCH 1727/2270] ich9: Add the lpc chip

Add support for the ICH9 LPC chip.

Signed-off-by: Isaku Yamahata 
Signed-off-by: Jason Baron 
Signed-off-by: Anthony Liguori 
---
 hw/i386/Makefile.objs |   1 +
 hw/lpc_ich9.c         | 523 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 524 insertions(+)
 create mode 100644 hw/lpc_ich9.c

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 8c764bbfef..9543a69022 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -6,6 +6,7 @@ obj-y += pci-hotplug.o smbios.o wdt_ib700.o
 obj-y += debugcon.o multiboot.o
 obj-y += pc_piix.o
 obj-y += pc_sysfw.o
+obj-y += lpc_ich9.o
 obj-$(CONFIG_XEN) += xen_platform.o xen_apic.o
 obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o
 obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o
diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
new file mode 100644
index 0000000000..f8f06b394c
--- /dev/null
+++ b/hw/lpc_ich9.c
@@ -0,0 +1,523 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+/*
+ * QEMU ICH9 Emulation
+ *
+ *  Copyright (c) 2009, 2010, 2011
+ *                Isaku Yamahata 
+ *                VA Linux Systems Japan K.K.
+ *  Copyright (C) 2012 Jason Baron 
+ *
+ *  This is based on piix_pci.c, but heavily modified.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see 
+ */
+
+#include "qemu-common.h"
+#include "hw.h"
+#include "range.h"
+#include "isa.h"
+#include "sysbus.h"
+#include "pc.h"
+#include "apm.h"
+#include "ioapic.h"
+#include "pci.h"
+#include "pcie_host.h"
+#include "pci_bridge.h"
+#include "ich9.h"
+#include "acpi.h"
+#include "acpi_ich9.h"
+#include "pam.h"
+#include "pci_internals.h"
+#include "exec-memory.h"
+
+static int ich9_lpc_sci_irq(ICH9LPCState *lpc);
+
+/*****************************************************************************/
+/* ICH9 LPC PCI to ISA bridge */
+
+static void ich9_lpc_reset(DeviceState *qdev);
+
+/* chipset configuration register
+ * to access chipset configuration registers, pci_[sg]et_{byte, word, long}
+ * are used.
+ * Although it's not pci configuration space, it's little endian as Intel.
+ */
+
+static void ich9_cc_update_ir(uint8_t irr[PCI_NUM_PINS], uint16_t ir)
+{
+    int intx;
+    for (intx = 0; intx < PCI_NUM_PINS; intx++) {
+        irr[intx] = (ir >> (intx * ICH9_CC_DIR_SHIFT)) & ICH9_CC_DIR_MASK;
+    }
+}
+
+static void ich9_cc_update(ICH9LPCState *lpc)
+{
+    int slot;
+    int pci_intx;
+
+    const int reg_offsets[] = {
+        ICH9_CC_D25IR,
+        ICH9_CC_D26IR,
+        ICH9_CC_D27IR,
+        ICH9_CC_D28IR,
+        ICH9_CC_D29IR,
+        ICH9_CC_D30IR,
+        ICH9_CC_D31IR,
+    };
+    const int *offset;
+
+    /* D{25 - 31}IR, but D30IR is read only to 0. */
+    for (slot = 25, offset = reg_offsets; slot < 32; slot++, offset++) {
+        if (slot == 30) {
+            continue;
+        }
+        ich9_cc_update_ir(lpc->irr[slot],
+                          pci_get_word(lpc->chip_config + *offset));
+    }
+
+    /*
+     * D30: DMI2PCI bridge
+     * It is arbitrarily decided how INTx lines of PCI devicesbehind the bridge
+     * are connected to pirq lines. Our choice is PIRQ[E-H].
+     * INT[A-D] are connected to PIRQ[E-H]
+     */
+    for (pci_intx = 0; pci_intx < PCI_NUM_PINS; pci_intx++) {
+        lpc->irr[30][pci_intx] = pci_intx + 4;
+    }
+}
+
+static void ich9_cc_init(ICH9LPCState *lpc)
+{
+    int slot;
+    int intx;
+
+    /* the default irq routing is arbitrary as long as it matches with
+     * acpi irq routing table.
+     * The one that is incompatible with piix_pci(= bochs) one is
+     * intentionally chosen to let the users know that the different
+     * board is used.
+     *
+     * int[A-D] -> pirq[E-F]
+     * avoid pirq A-D because they are used for pci express port
+     */
+    for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+        for (intx = 0; intx < PCI_NUM_PINS; intx++) {
+            lpc->irr[slot][intx] = (slot + intx) % 4 + 4;
+        }
+    }
+    ich9_cc_update(lpc);
+}
+
+static void ich9_cc_reset(ICH9LPCState *lpc)
+{
+    uint8_t *c = lpc->chip_config;
+
+    memset(lpc->chip_config, 0, sizeof(lpc->chip_config));
+
+    pci_set_long(c + ICH9_CC_D31IR, ICH9_CC_DIR_DEFAULT);
+    pci_set_long(c + ICH9_CC_D30IR, ICH9_CC_D30IR_DEFAULT);
+    pci_set_long(c + ICH9_CC_D29IR, ICH9_CC_DIR_DEFAULT);
+    pci_set_long(c + ICH9_CC_D28IR, ICH9_CC_DIR_DEFAULT);
+    pci_set_long(c + ICH9_CC_D27IR, ICH9_CC_DIR_DEFAULT);
+    pci_set_long(c + ICH9_CC_D26IR, ICH9_CC_DIR_DEFAULT);
+    pci_set_long(c + ICH9_CC_D25IR, ICH9_CC_DIR_DEFAULT);
+
+    ich9_cc_update(lpc);
+}
+
+static void ich9_cc_addr_len(uint64_t *addr, unsigned *len)
+{
+    *addr &= ICH9_CC_ADDR_MASK;
+    if (*addr + *len >= ICH9_CC_SIZE) {
+        *len = ICH9_CC_SIZE - *addr;
+    }
+}
+
+/* val: little endian */
+static void ich9_cc_write(void *opaque, hwaddr addr,
+                          uint64_t val, unsigned len)
+{
+    ICH9LPCState *lpc = (ICH9LPCState *)opaque;
+
+    ich9_cc_addr_len(&addr, &len);
+    memcpy(lpc->chip_config + addr, &val, len);
+    ich9_cc_update(lpc);
+}
+
+/* return value: little endian */
+static uint64_t ich9_cc_read(void *opaque, hwaddr addr,
+                              unsigned len)
+{
+    ICH9LPCState *lpc = (ICH9LPCState *)opaque;
+
+    uint32_t val = 0;
+    ich9_cc_addr_len(&addr, &len);
+    memcpy(&val, lpc->chip_config + addr, len);
+    return val;
+}
+
+/* IRQ routing */
+/* */
+static void ich9_lpc_rout(uint8_t pirq_rout, int *pic_irq, int *pic_dis)
+{
+    *pic_irq = pirq_rout & ICH9_LPC_PIRQ_ROUT_MASK;
+    *pic_dis = pirq_rout & ICH9_LPC_PIRQ_ROUT_IRQEN;
+}
+
+static void ich9_lpc_pic_irq(ICH9LPCState *lpc, int pirq_num,
+                             int *pic_irq, int *pic_dis)
+{
+    switch (pirq_num) {
+    case 0 ... 3: /* A-D */
+        ich9_lpc_rout(lpc->d.config[ICH9_LPC_PIRQA_ROUT + pirq_num],
+                      pic_irq, pic_dis);
+        return;
+    case 4 ... 7: /* E-H */
+        ich9_lpc_rout(lpc->d.config[ICH9_LPC_PIRQE_ROUT + (pirq_num - 4)],
+                      pic_irq, pic_dis);
+        return;
+    default:
+        break;
+    }
+    abort();
+}
+
+/* pic_irq: i8254 irq 0-15 */
+static void ich9_lpc_update_pic(ICH9LPCState *lpc, int pic_irq)
+{
+    int i, pic_level;
+
+    /* The pic level is the logical OR of all the PCI irqs mapped to it */
+    pic_level = 0;
+    for (i = 0; i < ICH9_LPC_NB_PIRQS; i++) {
+        int tmp_irq;
+        int tmp_dis;
+        ich9_lpc_pic_irq(lpc, i, &tmp_irq, &tmp_dis);
+        if (!tmp_dis && pic_irq == tmp_irq) {
+            pic_level |= pci_bus_get_irq_level(lpc->d.bus, i);
+        }
+    }
+    if (pic_irq == ich9_lpc_sci_irq(lpc)) {
+        pic_level |= lpc->sci_level;
+    }
+
+    qemu_set_irq(lpc->pic[pic_irq], pic_level);
+}
+
+/* pirq: pirq[A-H] 0-7*/
+static void ich9_lpc_update_by_pirq(ICH9LPCState *lpc, int pirq)
+{
+    int pic_irq;
+    int pic_dis;
+
+    ich9_lpc_pic_irq(lpc, pirq, &pic_irq, &pic_dis);
+    assert(pic_irq < ICH9_LPC_PIC_NUM_PINS);
+    if (pic_dis) {
+        return;
+    }
+
+    ich9_lpc_update_pic(lpc, pic_irq);
+}
+
+/* APIC mode: GSIx: PIRQ[A-H] -> GSI 16, ... no pirq shares same APIC pins. */
+static int ich9_pirq_to_gsi(int pirq)
+{
+    return pirq + ICH9_LPC_PIC_NUM_PINS;
+}
+
+static int ich9_gsi_to_pirq(int gsi)
+{
+    return gsi - ICH9_LPC_PIC_NUM_PINS;
+}
+
+static void ich9_lpc_update_apic(ICH9LPCState *lpc, int gsi)
+{
+    int level;
+
+    level = pci_bus_get_irq_level(lpc->d.bus, ich9_gsi_to_pirq(gsi));
+    if (gsi == ich9_lpc_sci_irq(lpc)) {
+        level |= lpc->sci_level;
+    }
+
+    qemu_set_irq(lpc->ioapic[gsi], level);
+}
+
+void ich9_lpc_set_irq(void *opaque, int pirq, int level)
+{
+    ICH9LPCState *lpc = opaque;
+
+    assert(0 <= pirq);
+    assert(pirq < ICH9_LPC_NB_PIRQS);
+
+    ich9_lpc_update_apic(lpc, ich9_pirq_to_gsi(pirq));
+    ich9_lpc_update_by_pirq(lpc, pirq);
+}
+
+/* return the pirq number (PIRQ[A-H]:0-7) corresponding to
+ * a given device irq pin.
+ */
+int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx)
+{
+    BusState *bus = qdev_get_parent_bus(&pci_dev->qdev);
+    PCIBus *pci_bus = PCI_BUS(bus);
+    PCIDevice *lpc_pdev =
+            pci_bus->devices[PCI_DEVFN(ICH9_LPC_DEV, ICH9_LPC_FUNC)];
+    ICH9LPCState *lpc = ICH9_LPC_DEVICE(lpc_pdev);
+
+    return lpc->irr[PCI_SLOT(pci_dev->devfn)][intx];
+}
+
+static int ich9_lpc_sci_irq(ICH9LPCState *lpc)
+{
+    switch (lpc->d.config[ICH9_LPC_ACPI_CTRL] &
+            ICH9_LPC_ACPI_CTRL_SCI_IRQ_SEL_MASK) {
+    case ICH9_LPC_ACPI_CTRL_9:
+        return 9;
+    case ICH9_LPC_ACPI_CTRL_10:
+        return 10;
+    case ICH9_LPC_ACPI_CTRL_11:
+        return 11;
+    case ICH9_LPC_ACPI_CTRL_20:
+        return 20;
+    case ICH9_LPC_ACPI_CTRL_21:
+        return 21;
+    default:
+        /* reserved */
+        break;
+    }
+    return -1;
+}
+
+static void ich9_set_sci(void *opaque, int irq_num, int level)
+{
+    ICH9LPCState *lpc = opaque;
+    int irq;
+
+    assert(irq_num == 0);
+    level = !!level;
+    if (level == lpc->sci_level) {
+        return;
+    }
+    lpc->sci_level = level;
+
+    irq = ich9_lpc_sci_irq(lpc);
+    if (irq < 0) {
+        return;
+    }
+
+    ich9_lpc_update_apic(lpc, irq);
+    if (irq < ICH9_LPC_PIC_NUM_PINS) {
+        ich9_lpc_update_pic(lpc, irq);
+    }
+}
+
+void ich9_lpc_pm_init(PCIDevice *lpc_pci, qemu_irq cmos_s3)
+{
+    ICH9LPCState *lpc = ICH9_LPC_DEVICE(lpc_pci);
+    qemu_irq *sci_irq;
+
+    sci_irq = qemu_allocate_irqs(ich9_set_sci, lpc, 1);
+    ich9_pm_init(&lpc->pm, sci_irq[0], cmos_s3);
+
+    ich9_lpc_reset(&lpc->d.qdev);
+}
+
+/* APM */
+
+static void ich9_apm_ctrl_changed(uint32_t val, void *arg)
+{
+    ICH9LPCState *lpc = arg;
+
+    /* ACPI specs 3.0, 4.7.2.5 */
+    acpi_pm1_cnt_update(&lpc->pm.acpi_regs,
+                        val == ICH9_APM_ACPI_ENABLE,
+                        val == ICH9_APM_ACPI_DISABLE);
+
+    /* SMI_EN = PMBASE + 30. SMI control and enable register */
+    if (lpc->pm.smi_en & ICH9_PMIO_SMI_EN_APMC_EN) {
+        cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
+    }
+}
+
+/* config:PMBASE */
+static void
+ich9_lpc_pmbase_update(ICH9LPCState *lpc)
+{
+    uint32_t pm_io_base = pci_get_long(lpc->d.config + ICH9_LPC_PMBASE);
+    pm_io_base &= ICH9_LPC_PMBASE_BASE_ADDRESS_MASK;
+
+    ich9_pm_iospace_update(&lpc->pm, pm_io_base);
+}
+
+/* config:RBCA */
+static void ich9_lpc_rcba_update(ICH9LPCState *lpc, uint32_t rbca_old)
+{
+    uint32_t rbca = pci_get_long(lpc->d.config + ICH9_LPC_RCBA);
+
+    if (rbca_old & ICH9_LPC_RCBA_EN) {
+            memory_region_del_subregion(get_system_memory(), &lpc->rbca_mem);
+    }
+    if (rbca & ICH9_LPC_RCBA_EN) {
+            memory_region_add_subregion_overlap(get_system_memory(),
+                                                rbca & ICH9_LPC_RCBA_BA_MASK,
+                                                &lpc->rbca_mem, 1);
+    }
+}
+
+static int ich9_lpc_post_load(void *opaque, int version_id)
+{
+    ICH9LPCState *lpc = opaque;
+
+    ich9_lpc_pmbase_update(lpc);
+    ich9_lpc_rcba_update(lpc, 0 /* disabled ICH9_LPC_RBCA_EN */);
+    return 0;
+}
+
+static void ich9_lpc_config_write(PCIDevice *d,
+                                  uint32_t addr, uint32_t val, int len)
+{
+    ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);
+    uint32_t rbca_old = pci_get_long(d->config + ICH9_LPC_RCBA);
+
+    pci_default_write_config(d, addr, val, len);
+    if (ranges_overlap(addr, len, ICH9_LPC_PMBASE, 4)) {
+        ich9_lpc_pmbase_update(lpc);
+    }
+    if (ranges_overlap(addr, len, ICH9_LPC_RCBA, 4)) {
+        ich9_lpc_rcba_update(lpc, rbca_old);
+    }
+}
+
+static void ich9_lpc_reset(DeviceState *qdev)
+{
+    PCIDevice *d = PCI_DEVICE(qdev);
+    ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);
+    uint32_t rbca_old = pci_get_long(d->config + ICH9_LPC_RCBA);
+    int i;
+
+    for (i = 0; i < 4; i++) {
+        pci_set_byte(d->config + ICH9_LPC_PIRQA_ROUT + i,
+                     ICH9_LPC_PIRQ_ROUT_DEFAULT);
+    }
+    for (i = 0; i < 4; i++) {
+        pci_set_byte(d->config + ICH9_LPC_PIRQE_ROUT + i,
+                     ICH9_LPC_PIRQ_ROUT_DEFAULT);
+    }
+    pci_set_byte(d->config + ICH9_LPC_ACPI_CTRL, ICH9_LPC_ACPI_CTRL_DEFAULT);
+
+    pci_set_long(d->config + ICH9_LPC_PMBASE, ICH9_LPC_PMBASE_DEFAULT);
+    pci_set_long(d->config + ICH9_LPC_RCBA, ICH9_LPC_RCBA_DEFAULT);
+
+    ich9_cc_reset(lpc);
+
+    ich9_lpc_pmbase_update(lpc);
+    ich9_lpc_rcba_update(lpc, rbca_old);
+
+    lpc->sci_level = 0;
+}
+
+static const MemoryRegionOps rbca_mmio_ops = {
+    .read = ich9_cc_read,
+    .write = ich9_cc_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int ich9_lpc_initfn(PCIDevice *d)
+{
+    ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);
+    ISABus *isa_bus;
+
+    isa_bus = isa_bus_new(&d->qdev, get_system_io());
+
+    pci_set_long(d->wmask + ICH9_LPC_PMBASE,
+                 ICH9_LPC_PMBASE_BASE_ADDRESS_MASK);
+
+    memory_region_init_io(&lpc->rbca_mem, &rbca_mmio_ops, lpc,
+                            "lpc-rbca-mmio", ICH9_CC_SIZE);
+
+    lpc->isa_bus = isa_bus;
+
+    ich9_cc_init(lpc);
+    apm_init(&lpc->apm, ich9_apm_ctrl_changed, lpc);
+    return 0;
+}
+
+static const VMStateDescription vmstate_ich9_lpc = {
+    .name = "ICH9LPC",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = ich9_lpc_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE(d, ICH9LPCState),
+        VMSTATE_STRUCT(apm, ICH9LPCState, 0, vmstate_apm, APMState),
+        VMSTATE_STRUCT(pm, ICH9LPCState, 0, vmstate_ich9_pm, ICH9LPCPMRegs),
+        VMSTATE_UINT8_ARRAY(chip_config, ICH9LPCState, ICH9_CC_SIZE),
+        VMSTATE_UINT32(sci_level, ICH9LPCState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void ich9_lpc_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    dc->reset = ich9_lpc_reset;
+    k->init = ich9_lpc_initfn;
+    dc->vmsd = &vmstate_ich9_lpc;
+    dc->no_user = 1;
+    k->config_write = ich9_lpc_config_write;
+    dc->desc = "ICH9 LPC bridge";
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_ICH9_8;
+    k->revision = ICH9_A2_LPC_REVISION;
+    k->class_id = PCI_CLASS_BRIDGE_ISA;
+
+}
+
+static const TypeInfo ich9_lpc_info = {
+    .name       = TYPE_ICH9_LPC_DEVICE,
+    .parent     = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(struct ICH9LPCState),
+    .class_init  = ich9_lpc_class_init,
+};
+
+static void ich9_lpc_register(void)
+{
+    type_register_static(&ich9_lpc_info);
+}
+
+type_init(ich9_lpc_register);

From 678e7b94b182f846de61e38e8a6499f9c55dbcf0 Mon Sep 17 00:00:00 2001
From: Jason Baron 
Date: Thu, 22 Nov 2012 22:06:42 -0500
Subject: [PATCH 1728/2270] ich9: Add smbus

Add support for the ich9 smbus chip.

Signed-off-by: Isaku Yamahata 
Signed-off-by: Jason Baron 
Signed-off-by: Anthony Liguori 
---
 hw/Makefile.objs |   2 +-
 hw/smbus_ich9.c  | 159 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 160 insertions(+), 1 deletion(-)
 create mode 100644 hw/smbus_ich9.c

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index b863b3145a..35773de1e6 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -28,7 +28,7 @@ common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
 common-obj-$(CONFIG_PCSPK) += pcspk.o
 common-obj-$(CONFIG_PCKBD) += pckbd.o
 common-obj-$(CONFIG_FDC) += fdc.o
-common-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o acpi_ich9.o
+common-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o acpi_ich9.o smbus_ich9.o
 common-obj-$(CONFIG_APM) += pm_smbus.o apm.o
 common-obj-$(CONFIG_DMA) += dma.o
 common-obj-$(CONFIG_I82374) += i82374.o
diff --git a/hw/smbus_ich9.c b/hw/smbus_ich9.c
new file mode 100644
index 0000000000..6940583bb6
--- /dev/null
+++ b/hw/smbus_ich9.c
@@ -0,0 +1,159 @@
+/*
+ * ACPI implementation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see 
+ */
+/*
+ *  Copyright (c) 2009 Isaku Yamahata 
+ *                     VA Linux Systems Japan K.K.
+ *  Copyright (C) 2012 Jason Baron 
+ *
+ *  This is based on acpi.c, but heavily rewritten.
+ */
+#include "hw.h"
+#include "pc.h"
+#include "pm_smbus.h"
+#include "pci.h"
+#include "sysemu.h"
+#include "i2c.h"
+#include "smbus.h"
+
+#include "ich9.h"
+
+#define TYPE_ICH9_SMB_DEVICE "ICH9 SMB"
+#define ICH9_SMB_DEVICE(obj) \
+     OBJECT_CHECK(ICH9SMBState, (obj), TYPE_ICH9_SMB_DEVICE)
+
+typedef struct ICH9SMBState {
+    PCIDevice dev;
+
+    PMSMBus smb;
+    MemoryRegion mem_bar;
+} ICH9SMBState;
+
+static const VMStateDescription vmstate_ich9_smbus = {
+    .name = "ich9_smb",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE(dev, struct ICH9SMBState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void ich9_smb_ioport_writeb(void *opaque, hwaddr addr,
+                                   uint64_t val, unsigned size)
+{
+    ICH9SMBState *s = opaque;
+    uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
+
+    if ((hostc & ICH9_SMB_HOSTC_HST_EN) && !(hostc & ICH9_SMB_HOSTC_I2C_EN)) {
+        uint64_t offset = addr - s->dev.io_regions[ICH9_SMB_SMB_BASE_BAR].addr;
+        smb_ioport_writeb(&s->smb, offset, val);
+    }
+}
+
+static uint64_t ich9_smb_ioport_readb(void *opaque, hwaddr addr,
+                                      unsigned size)
+{
+    ICH9SMBState *s = opaque;
+    uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
+
+    if ((hostc & ICH9_SMB_HOSTC_HST_EN) && !(hostc & ICH9_SMB_HOSTC_I2C_EN)) {
+        uint64_t offset = addr - s->dev.io_regions[ICH9_SMB_SMB_BASE_BAR].addr;
+        return smb_ioport_readb(&s->smb, offset);
+    }
+
+    return 0xff;
+}
+
+static const MemoryRegionOps lpc_smb_mmio_ops = {
+    .read = ich9_smb_ioport_readb,
+    .write = ich9_smb_ioport_writeb,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
+static int ich9_smbus_initfn(PCIDevice *d)
+{
+    ICH9SMBState *s = ICH9_SMB_DEVICE(d);
+
+    /* TODO? D31IP.SMIP in chipset configuration space */
+    pci_config_set_interrupt_pin(d->config, 0x01); /* interrupt pin 1 */
+
+    pci_set_byte(d->config + ICH9_SMB_HOSTC, 0);
+
+    /*
+     * update parameters based on
+     * paralell_hds[0]
+     * serial_hds[0]
+     * serial_hds[0]
+     * fdc
+     *
+     * Is there any OS that depends on them?
+     */
+
+    /* TODO smb_io_base */
+    pci_set_byte(d->config + ICH9_SMB_HOSTC, 0);
+    /* TODO bar0, bar1: 64bit BAR support*/
+
+    memory_region_init_io(&s->mem_bar, &lpc_smb_mmio_ops, s, "ich9-smbus-bar",
+                            ICH9_SMB_SMB_BASE_SIZE);
+    pci_register_bar(d, ICH9_SMB_SMB_BASE_BAR, PCI_BASE_ADDRESS_SPACE_IO,
+                        &s->mem_bar);
+    pm_smbus_init(&d->qdev, &s->smb);
+    return 0;
+}
+
+static void ich9_smb_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_ICH9_6;
+    k->revision = ICH9_A2_SMB_REVISION;
+    k->class_id = PCI_CLASS_SERIAL_SMBUS;
+    dc->no_user = 1;
+    dc->vmsd = &vmstate_ich9_smbus;
+    dc->desc = "ICH9 SMBUS Bridge";
+    k->init = ich9_smbus_initfn;
+}
+
+i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base)
+{
+    PCIDevice *d =
+        pci_create_simple_multifunction(bus, devfn, true, TYPE_ICH9_SMB_DEVICE);
+    ICH9SMBState *s = ICH9_SMB_DEVICE(d);
+    return s->smb.smbus;
+}
+
+static const TypeInfo ich9_smb_info = {
+    .name   = TYPE_ICH9_SMB_DEVICE,
+    .parent = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(ICH9SMBState),
+    .class_init = ich9_smb_class_init,
+};
+
+static void ich9_smb_register(void)
+{
+    type_register_static(&ich9_smb_info);
+}
+
+type_init(ich9_smb_register);

From df2d8b3ed4d2b6406335d274f9537d78ac4e3c0c Mon Sep 17 00:00:00 2001
From: Isaku Yamahata 
Date: Wed, 14 Nov 2012 15:54:06 -0500
Subject: [PATCH 1729/2270] q35: Introduce q35 pc based chipset emulator

pc q35 based chipset emulator to support pci express natively. Based on
Anthony Liguori's suggestion, the machine name is 'q35-next', with an alias
of 'q35'. At this point, there are no compatibility guarantees. When the
chipset stabilizes more, we will begin to version the machine names.

Major features which still need to be added:

-Migration support (mostly around ahci)
-ACPI hotplug support (pcie hotplug support is working)
-Passthrough support

Signed-off-by: Isaku Yamahata 
Signed-off-by: Jason Baron 
Signed-off-by: Anthony Liguori 
---
 hw/i386/Makefile.objs |   2 +-
 hw/pc_q35.c           | 220 ++++++++++++++++++++++++++++++
 hw/pci_ids.h          |   2 +
 hw/q35.c              | 309 ++++++++++++++++++++++++++++++++++++++++++
 hw/q35.h              | 150 ++++++++++++++++++++
 5 files changed, 682 insertions(+), 1 deletion(-)
 create mode 100644 hw/pc_q35.c
 create mode 100644 hw/q35.c
 create mode 100644 hw/q35.h

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 9543a69022..0d3f6a8e84 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -6,7 +6,7 @@ obj-y += pci-hotplug.o smbios.o wdt_ib700.o
 obj-y += debugcon.o multiboot.o
 obj-y += pc_piix.o
 obj-y += pc_sysfw.o
-obj-y += lpc_ich9.o
+obj-y += lpc_ich9.o q35.o pc_q35.o
 obj-$(CONFIG_XEN) += xen_platform.o xen_apic.o
 obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o
 obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o
diff --git a/hw/pc_q35.c b/hw/pc_q35.c
new file mode 100644
index 0000000000..142bf8aa1b
--- /dev/null
+++ b/hw/pc_q35.c
@@ -0,0 +1,220 @@
+/*
+ * Q35 chipset based pc system emulator
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2009, 2010
+ *               Isaku Yamahata 
+ *               VA Linux Systems Japan K.K.
+ * Copyright (C) 2012 Jason Baron 
+ *
+ * This is based on pc.c, but heavily modified.
+ *
+ * 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.h"
+#include "arch_init.h"
+#include "smbus.h"
+#include "boards.h"
+#include "mc146818rtc.h"
+#include "xen.h"
+#include "kvm.h"
+#include "q35.h"
+#include "exec-memory.h"
+#include "ich9.h"
+#include "hw/ide/pci.h"
+#include "hw/ide/ahci.h"
+#include "hw/usb.h"
+
+/* ICH9 AHCI has 6 ports */
+#define MAX_SATA_PORTS     6
+
+/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
+ *    BIOS will read it and start S3 resume at POST Entry */
+static void pc_cmos_set_s3_resume(void *opaque, int irq, int level)
+{
+    ISADevice *s = opaque;
+
+    if (level) {
+        rtc_set_memory(s, 0xF, 0xFE);
+    }
+}
+
+/* PC hardware initialisation */
+static void pc_q35_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;
+    ram_addr_t below_4g_mem_size, above_4g_mem_size;
+    Q35PCIHost *q35_host;
+    PCIBus *host_bus;
+    PCIDevice *lpc;
+    BusState *idebus[MAX_SATA_PORTS];
+    ISADevice *rtc_state;
+    ISADevice *floppy;
+    MemoryRegion *pci_memory;
+    MemoryRegion *rom_memory;
+    MemoryRegion *ram_memory;
+    GSIState *gsi_state;
+    ISABus *isa_bus;
+    int pci_enabled = 1;
+    qemu_irq *cpu_irq;
+    qemu_irq *gsi;
+    qemu_irq *i8259;
+    int i;
+    ICH9LPCState *ich9_lpc;
+    PCIDevice *ahci;
+    qemu_irq *cmos_s3;
+
+    pc_cpus_init(cpu_model);
+
+    if (ram_size >= 0xb0000000) {
+        above_4g_mem_size = ram_size - 0xb0000000;
+        below_4g_mem_size = 0xb0000000;
+    } else {
+        above_4g_mem_size = 0;
+        below_4g_mem_size = ram_size;
+    }
+
+    /* pci enabled */
+    if (pci_enabled) {
+        pci_memory = g_new(MemoryRegion, 1);
+        memory_region_init(pci_memory, "pci", INT64_MAX);
+        rom_memory = pci_memory;
+    } else {
+        pci_memory = NULL;
+        rom_memory = get_system_memory();
+    }
+
+    /* allocate ram and load rom/bios */
+    if (!xen_enabled()) {
+        pc_memory_init(get_system_memory(), kernel_filename, kernel_cmdline,
+                       initrd_filename, below_4g_mem_size, above_4g_mem_size,
+                       rom_memory, &ram_memory);
+    }
+
+    /* irq lines */
+    gsi_state = g_malloc0(sizeof(*gsi_state));
+    if (kvm_irqchip_in_kernel()) {
+        kvm_pc_setup_irq_routing(pci_enabled);
+        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
+                                 GSI_NUM_PINS);
+    } else {
+        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
+    }
+
+    /* create pci host bus */
+    q35_host = Q35_HOST_DEVICE(qdev_create(NULL, TYPE_Q35_HOST_DEVICE));
+
+    q35_host->mch.ram_memory = ram_memory;
+    q35_host->mch.pci_address_space = pci_memory;
+    q35_host->mch.system_memory = get_system_memory();
+    q35_host->mch.address_space_io = get_system_io();;
+    q35_host->mch.below_4g_mem_size = below_4g_mem_size;
+    q35_host->mch.above_4g_mem_size = above_4g_mem_size;
+    /* pci */
+    qdev_init_nofail(DEVICE(q35_host));
+    host_bus = q35_host->host.pci.bus;
+    /* create ISA bus */
+    lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_LPC_DEV,
+                                          ICH9_LPC_FUNC), true,
+                                          TYPE_ICH9_LPC_DEVICE);
+    ich9_lpc = ICH9_LPC_DEVICE(lpc);
+    ich9_lpc->pic = gsi;
+    ich9_lpc->ioapic = gsi_state->ioapic_irq;
+    pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc,
+                 ICH9_LPC_NB_PIRQS);
+    isa_bus = ich9_lpc->isa_bus;
+
+    /*end early*/
+    isa_bus_irqs(isa_bus, gsi);
+
+    if (kvm_irqchip_in_kernel()) {
+        i8259 = kvm_i8259_init(isa_bus);
+    } else if (xen_enabled()) {
+        i8259 = xen_interrupt_controller_init();
+    } else {
+        cpu_irq = pc_allocate_cpu_irq();
+        i8259 = i8259_init(isa_bus, cpu_irq[0]);
+    }
+
+    for (i = 0; i < ISA_NUM_IRQS; i++) {
+        gsi_state->i8259_irq[i] = i8259[i];
+    }
+    if (pci_enabled) {
+        ioapic_init_gsi(gsi_state, NULL);
+    }
+
+    pc_register_ferr_irq(gsi[13]);
+
+    /* init basic PC hardware */
+    pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, false);
+
+    /* connect pm stuff to lpc */
+    cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
+    ich9_lpc_pm_init(lpc, *cmos_s3);
+
+    /* ahci and SATA device, for q35 1 ahci controller is built-in */
+    ahci = pci_create_simple_multifunction(host_bus,
+                                           PCI_DEVFN(ICH9_SATA1_DEV,
+                                                     ICH9_SATA1_FUNC),
+                                           true, "ich9-ahci");
+    idebus[0] = qdev_get_child_bus(&ahci->qdev, "ide.0");
+    idebus[1] = qdev_get_child_bus(&ahci->qdev, "ide.1");
+
+    if (usb_enabled(false)) {
+        /* Should we create 6 UHCI according to ich9 spec? */
+        ehci_create_ich9_with_companions(host_bus, 0x1d);
+    }
+
+    /* TODO: Populate SPD eeprom data.  */
+    smbus_eeprom_init(ich9_smb_init(host_bus,
+                                    PCI_DEVFN(ICH9_SMB_DEV, ICH9_SMB_FUNC),
+                                    0xb100),
+                      8, NULL, 0);
+
+    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
+                 floppy, idebus[0], idebus[1], rtc_state);
+
+    /* the rest devices to which pci devfn is automatically assigned */
+    pc_vga_init(isa_bus, host_bus);
+    audio_init(isa_bus, host_bus);
+    pc_nic_init(isa_bus, host_bus);
+    if (pci_enabled) {
+        pc_pci_device_init(host_bus);
+    }
+}
+
+static QEMUMachine pc_q35_machine = {
+    .name = "q35-next",
+    .alias = "q35",
+    .desc = "Q35 chipset PC",
+    .init = pc_q35_init,
+    .max_cpus = 255,
+};
+
+static void pc_q35_machine_init(void)
+{
+    qemu_register_machine(&pc_q35_machine);
+}
+
+machine_init(pc_q35_machine_init);
diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index d1e83ddd06..5df7245349 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -138,6 +138,8 @@
 #define PCI_DEVICE_ID_INTEL_82801I_EHCI2 0x293c
 #define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed
 
+#define PCI_DEVICE_ID_INTEL_Q35_MCH      0x29c0
+
 #define PCI_VENDOR_ID_XEN               0x5853
 #define PCI_DEVICE_ID_XEN_PLATFORM      0x0001
 
diff --git a/hw/q35.c b/hw/q35.c
new file mode 100644
index 0000000000..efebc2786a
--- /dev/null
+++ b/hw/q35.c
@@ -0,0 +1,309 @@
+/*
+ * QEMU MCH/ICH9 PCI Bridge Emulation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2009, 2010, 2011
+ *               Isaku Yamahata 
+ *               VA Linux Systems Japan K.K.
+ * Copyright (C) 2012 Jason Baron 
+ *
+ * This is based on piix_pci.c, but heavily modified.
+ *
+ * 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.h"
+#include "q35.h"
+
+/****************************************************************************
+ * Q35 host
+ */
+
+static int q35_host_init(SysBusDevice *dev)
+{
+    PCIBus *b;
+    PCIHostState *pci = FROM_SYSBUS(PCIHostState, dev);
+    Q35PCIHost *s = Q35_HOST_DEVICE(&dev->qdev);
+
+    memory_region_init_io(&pci->conf_mem, &pci_host_conf_le_ops, pci,
+                          "pci-conf-idx", 4);
+    sysbus_add_io(dev, MCH_HOST_BRIDGE_CONFIG_ADDR, &pci->conf_mem);
+    sysbus_init_ioports(&pci->busdev, MCH_HOST_BRIDGE_CONFIG_ADDR, 4);
+
+    memory_region_init_io(&pci->data_mem, &pci_host_data_le_ops, pci,
+                          "pci-conf-data", 4);
+    sysbus_add_io(dev, MCH_HOST_BRIDGE_CONFIG_DATA, &pci->data_mem);
+    sysbus_init_ioports(&pci->busdev, MCH_HOST_BRIDGE_CONFIG_DATA, 4);
+
+    if (pcie_host_init(&s->host) < 0) {
+        return -1;
+    }
+    b = pci_bus_new(&s->host.pci.busdev.qdev, "pcie.0",
+                    s->mch.pci_address_space, s->mch.address_space_io, 0);
+    s->host.pci.bus = b;
+    qdev_set_parent_bus(DEVICE(&s->mch), BUS(b));
+    qdev_init_nofail(DEVICE(&s->mch));
+
+    return 0;
+}
+
+static Property mch_props[] = {
+    DEFINE_PROP_UINT64("MCFG", Q35PCIHost, host.base_addr,
+                        MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void q35_host_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = q35_host_init;
+    dc->props = mch_props;
+}
+
+static void q35_host_initfn(Object *obj)
+{
+    Q35PCIHost *s = Q35_HOST_DEVICE(obj);
+
+    object_initialize(&s->mch, TYPE_MCH_PCI_DEVICE);
+    object_property_add_child(OBJECT(s), "mch", OBJECT(&s->mch), NULL);
+    qdev_prop_set_uint32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0));
+    qdev_prop_set_bit(DEVICE(&s->mch), "multifunction", false);
+}
+
+static const TypeInfo q35_host_info = {
+    .name       = TYPE_Q35_HOST_DEVICE,
+    .parent     = TYPE_PCIE_HOST_BRIDGE,
+    .instance_size = sizeof(Q35PCIHost),
+    .instance_init = q35_host_initfn,
+    .class_init = q35_host_class_init,
+};
+
+/****************************************************************************
+ * MCH D0:F0
+ */
+
+/* PCIe MMCFG */
+static void mch_update_pciexbar(MCHPCIState *mch)
+{
+    PCIDevice *pci_dev = &mch->d;
+    BusState *bus = qdev_get_parent_bus(&pci_dev->qdev);
+    DeviceState *qdev = bus->parent;
+    Q35PCIHost *s = Q35_HOST_DEVICE(qdev);
+
+    uint64_t pciexbar;
+    int enable;
+    uint64_t addr;
+    uint64_t addr_mask;
+    uint32_t length;
+
+    pciexbar = pci_get_quad(pci_dev->config + MCH_HOST_BRIDGE_PCIEXBAR);
+    enable = pciexbar & MCH_HOST_BRIDGE_PCIEXBAREN;
+    addr_mask = MCH_HOST_BRIDGE_PCIEXBAR_ADMSK;
+    switch (pciexbar & MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_MASK) {
+    case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_256M:
+        length = 256 * 1024 * 1024;
+        break;
+    case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_128M:
+        length = 128 * 1024 * 1024;
+        addr_mask |= MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK |
+            MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK;
+        break;
+    case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_64M:
+        length = 64 * 1024 * 1024;
+        addr_mask |= MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK;
+        break;
+    case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD:
+    default:
+        enable = 0;
+        length = 0;
+        abort();
+        break;
+    }
+    addr = pciexbar & addr_mask;
+    pcie_host_mmcfg_update(&s->host, enable, addr, length);
+}
+
+/* PAM */
+static void mch_update_pam(MCHPCIState *mch)
+{
+    int i;
+
+    memory_region_transaction_begin();
+    for (i = 0; i < 13; i++) {
+        pam_update(&mch->pam_regions[i], i,
+                   mch->d.config[MCH_HOST_BRIDGE_PAM0 + ((i + 1) / 2)]);
+    }
+    memory_region_transaction_commit();
+}
+
+/* SMRAM */
+static void mch_update_smram(MCHPCIState *mch)
+{
+    memory_region_transaction_begin();
+    smram_update(&mch->smram_region, mch->d.config[MCH_HOST_BRDIGE_SMRAM],
+                    mch->smm_enabled);
+    memory_region_transaction_commit();
+}
+
+static void mch_set_smm(int smm, void *arg)
+{
+    MCHPCIState *mch = arg;
+
+    memory_region_transaction_begin();
+    smram_set_smm(&mch->smm_enabled, smm, mch->d.config[MCH_HOST_BRDIGE_SMRAM],
+                    &mch->smram_region);
+    memory_region_transaction_commit();
+}
+
+static void mch_write_config(PCIDevice *d,
+                              uint32_t address, uint32_t val, int len)
+{
+    MCHPCIState *mch = MCH_PCI_DEVICE(d);
+
+    /* XXX: implement SMRAM.D_LOCK */
+    pci_default_write_config(d, address, val, len);
+
+    if (ranges_overlap(address, len, MCH_HOST_BRIDGE_PAM0,
+                       MCH_HOST_BRIDGE_PAM_SIZE)) {
+        mch_update_pam(mch);
+    }
+
+    if (ranges_overlap(address, len, MCH_HOST_BRIDGE_PCIEXBAR,
+                       MCH_HOST_BRIDGE_PCIEXBAR_SIZE)) {
+        mch_update_pciexbar(mch);
+    }
+
+    if (ranges_overlap(address, len, MCH_HOST_BRDIGE_SMRAM,
+                       MCH_HOST_BRDIGE_SMRAM_SIZE)) {
+        mch_update_smram(mch);
+    }
+}
+
+static void mch_update(MCHPCIState *mch)
+{
+    mch_update_pciexbar(mch);
+    mch_update_pam(mch);
+    mch_update_smram(mch);
+}
+
+static int mch_post_load(void *opaque, int version_id)
+{
+    MCHPCIState *mch = opaque;
+    mch_update(mch);
+    return 0;
+}
+
+static const VMStateDescription vmstate_mch = {
+    .name = "mch",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = mch_post_load,
+    .fields = (VMStateField []) {
+        VMSTATE_PCI_DEVICE(d, MCHPCIState),
+        VMSTATE_UINT8(smm_enabled, MCHPCIState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void mch_reset(DeviceState *qdev)
+{
+    PCIDevice *d = PCI_DEVICE(qdev);
+    MCHPCIState *mch = MCH_PCI_DEVICE(d);
+
+    pci_set_quad(d->config + MCH_HOST_BRIDGE_PCIEXBAR,
+                 MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT);
+
+    d->config[MCH_HOST_BRDIGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_DEFAULT;
+
+    mch_update(mch);
+}
+
+static int mch_init(PCIDevice *d)
+{
+    int i;
+    hwaddr pci_hole64_size;
+    MCHPCIState *mch = MCH_PCI_DEVICE(d);
+
+    /* setup pci memory regions */
+    memory_region_init_alias(&mch->pci_hole, "pci-hole",
+                             mch->pci_address_space,
+                             mch->below_4g_mem_size,
+                             0x100000000ULL - mch->below_4g_mem_size);
+    memory_region_add_subregion(mch->system_memory, mch->below_4g_mem_size,
+                                &mch->pci_hole);
+    pci_hole64_size = (sizeof(hwaddr) == 4 ? 0 :
+                       ((uint64_t)1 << 62));
+    memory_region_init_alias(&mch->pci_hole_64bit, "pci-hole64",
+                             mch->pci_address_space,
+                             0x100000000ULL + mch->above_4g_mem_size,
+                             pci_hole64_size);
+    if (pci_hole64_size) {
+        memory_region_add_subregion(mch->system_memory,
+                                    0x100000000ULL + mch->above_4g_mem_size,
+                                    &mch->pci_hole_64bit);
+    }
+    /* smram */
+    cpu_smm_register(&mch_set_smm, mch);
+    memory_region_init_alias(&mch->smram_region, "smram-region",
+                             mch->pci_address_space, 0xa0000, 0x20000);
+    memory_region_add_subregion_overlap(mch->system_memory, 0xa0000,
+                                        &mch->smram_region, 1);
+    memory_region_set_enabled(&mch->smram_region, false);
+    init_pam(mch->ram_memory, mch->system_memory, mch->pci_address_space,
+             &mch->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE);
+    for (i = 0; i < 12; ++i) {
+        init_pam(mch->ram_memory, mch->system_memory, mch->pci_address_space,
+                 &mch->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE,
+                 PAM_EXPAN_SIZE);
+    }
+    return 0;
+}
+
+static void mch_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    k->init = mch_init;
+    k->config_write = mch_write_config;
+    dc->reset = mch_reset;
+    dc->desc = "Host bridge";
+    dc->vmsd = &vmstate_mch;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_Q35_MCH;
+    k->revision = MCH_HOST_BRIDGE_REVISION_DEFUALT;
+    k->class_id = PCI_CLASS_BRIDGE_HOST;
+}
+
+static const TypeInfo mch_info = {
+    .name = TYPE_MCH_PCI_DEVICE,
+    .parent = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(MCHPCIState),
+    .class_init = mch_class_init,
+};
+
+static void q35_register(void)
+{
+    type_register_static(&mch_info);
+    type_register_static(&q35_host_info);
+}
+
+type_init(q35_register);
diff --git a/hw/q35.h b/hw/q35.h
new file mode 100644
index 0000000000..e34f7c165f
--- /dev/null
+++ b/hw/q35.h
@@ -0,0 +1,150 @@
+/*
+ * q35.h
+ *
+ * Copyright (c) 2009 Isaku Yamahata 
+ *                    VA Linux Systems Japan K.K.
+ * Copyright (C) 2012 Jason Baron 
+ *
+ * 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 Lesser General Public
+ * License along with this library; if not, see 
+ */
+
+#ifndef HW_Q35_H
+#define HW_Q35_H
+
+#include "hw.h"
+#include "range.h"
+#include "isa.h"
+#include "sysbus.h"
+#include "pc.h"
+#include "apm.h"
+#include "apic.h"
+#include "pci.h"
+#include "pcie_host.h"
+#include "acpi.h"
+#include "acpi_ich9.h"
+#include "pam.h"
+
+#define TYPE_Q35_HOST_DEVICE "q35-pcihost"
+#define Q35_HOST_DEVICE(obj) \
+     OBJECT_CHECK(Q35PCIHost, (obj), TYPE_Q35_HOST_DEVICE)
+
+#define TYPE_MCH_PCI_DEVICE "mch"
+#define MCH_PCI_DEVICE(obj) \
+     OBJECT_CHECK(MCHPCIState, (obj), TYPE_MCH_PCI_DEVICE)
+
+typedef struct MCHPCIState {
+    PCIDevice d;
+    MemoryRegion *ram_memory;
+    MemoryRegion *pci_address_space;
+    MemoryRegion *system_memory;
+    MemoryRegion *address_space_io;
+    PAMMemoryRegion pam_regions[13];
+    MemoryRegion smram_region;
+    MemoryRegion pci_hole;
+    MemoryRegion pci_hole_64bit;
+    uint8_t smm_enabled;
+    ram_addr_t below_4g_mem_size;
+    ram_addr_t above_4g_mem_size;
+} MCHPCIState;
+
+typedef struct Q35PCIHost {
+    PCIExpressHost host;
+    MCHPCIState mch;
+} Q35PCIHost;
+
+#define Q35_MASK(bit, ms_bit, ls_bit) \
+((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1)))
+
+/*
+ * gmch part
+ */
+
+/* PCI configuration */
+#define MCH_HOST_BRIDGE                        "MCH"
+
+#define MCH_HOST_BRIDGE_CONFIG_ADDR            0xcf8
+#define MCH_HOST_BRIDGE_CONFIG_DATA            0xcfc
+
+/* D0:F0 configuration space */
+#define MCH_HOST_BRIDGE_REVISION_DEFUALT       0x0
+
+#define MCH_HOST_BRIDGE_PCIEXBAR               0x60    /* 64bit register */
+#define MCH_HOST_BRIDGE_PCIEXBAR_SIZE          8       /* 64bit register */
+#define MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT       0xb0000000
+#define MCH_HOST_BRIDGE_PCIEXBAR_ADMSK         Q35_MASK(64, 35, 28)
+#define MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK      ((uint64_t)(1 << 26))
+#define MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK       ((uint64_t)(1 << 25))
+#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_MASK   ((uint64_t)(0x3 << 1))
+#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_256M   ((uint64_t)(0x0 << 1))
+#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_128M   ((uint64_t)(0x1 << 1))
+#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_64M    ((uint64_t)(0x2 << 1))
+#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD    ((uint64_t)(0x3 << 1))
+#define MCH_HOST_BRIDGE_PCIEXBAREN             ((uint64_t)1)
+
+#define MCH_HOST_BRIDGE_PAM_NB                 7
+#define MCH_HOST_BRIDGE_PAM_SIZE               7
+#define MCH_HOST_BRIDGE_PAM0                   0x90
+#define MCH_HOST_BRIDGE_PAM_BIOS_AREA          0xf0000
+#define MCH_HOST_BRIDGE_PAM_AREA_SIZE          0x10000 /* 16KB */
+#define MCH_HOST_BRIDGE_PAM1                   0x91
+#define MCH_HOST_BRIDGE_PAM_EXPAN_AREA         0xc0000
+#define MCH_HOST_BRIDGE_PAM_EXPAN_SIZE         0x04000
+#define MCH_HOST_BRIDGE_PAM2                   0x92
+#define MCH_HOST_BRIDGE_PAM3                   0x93
+#define MCH_HOST_BRIDGE_PAM4                   0x94
+#define MCH_HOST_BRIDGE_PAM_EXBIOS_AREA        0xe0000
+#define MCH_HOST_BRIDGE_PAM_EXBIOS_SIZE        0x04000
+#define MCH_HOST_BRIDGE_PAM5                   0x95
+#define MCH_HOST_BRIDGE_PAM6                   0x96
+#define MCH_HOST_BRIDGE_PAM_WE_HI              ((uint8_t)(0x2 << 4))
+#define MCH_HOST_BRIDGE_PAM_RE_HI              ((uint8_t)(0x1 << 4))
+#define MCH_HOST_BRIDGE_PAM_HI_MASK            ((uint8_t)(0x3 << 4))
+#define MCH_HOST_BRIDGE_PAM_WE_LO              ((uint8_t)0x2)
+#define MCH_HOST_BRIDGE_PAM_RE_LO              ((uint8_t)0x1)
+#define MCH_HOST_BRIDGE_PAM_LO_MASK            ((uint8_t)0x3)
+#define MCH_HOST_BRIDGE_PAM_WE                 ((uint8_t)0x2)
+#define MCH_HOST_BRIDGE_PAM_RE                 ((uint8_t)0x1)
+#define MCH_HOST_BRIDGE_PAM_MASK               ((uint8_t)0x3)
+
+#define MCH_HOST_BRDIGE_SMRAM                  0x9d
+#define MCH_HOST_BRDIGE_SMRAM_SIZE             1
+#define MCH_HOST_BRIDGE_SMRAM_DEFAULT          ((uint8_t)0x2)
+#define MCH_HOST_BRIDGE_SMRAM_D_OPEN           ((uint8_t)(1 << 6))
+#define MCH_HOST_BRIDGE_SMRAM_D_CLS            ((uint8_t)(1 << 5))
+#define MCH_HOST_BRIDGE_SMRAM_D_LCK            ((uint8_t)(1 << 4))
+#define MCH_HOST_BRIDGE_SMRAM_G_SMRAME         ((uint8_t)(1 << 3))
+#define MCH_HOST_BRIDGE_SMRAM_C_BASE_SEG_MASK  ((uint8_t)0x7)
+#define MCH_HOST_BRIDGE_SMRAM_C_BASE_SEG       ((uint8_t)0x2)  /* hardwired to b010 */
+#define MCH_HOST_BRIDGE_SMRAM_C_BASE           0xa0000
+#define MCH_HOST_BRIDGE_SMRAM_C_END            0xc0000
+#define MCH_HOST_BRIDGE_SMRAM_C_SIZE           0x20000
+#define MCH_HOST_BRIDGE_UPPER_SYSTEM_BIOS_END  0x100000
+
+#define MCH_HOST_BRIDGE_ESMRAMC                0x9e
+#define MCH_HOST_BRDIGE_ESMRAMC_H_SMRAME       ((uint8_t)(1 << 6))
+#define MCH_HOST_BRDIGE_ESMRAMC_E_SMERR        ((uint8_t)(1 << 5))
+#define MCH_HOST_BRDIGE_ESMRAMC_SM_CACHE       ((uint8_t)(1 << 4))
+#define MCH_HOST_BRDIGE_ESMRAMC_SM_L1          ((uint8_t)(1 << 3))
+#define MCH_HOST_BRDIGE_ESMRAMC_SM_L2          ((uint8_t)(1 << 2))
+#define MCH_HOST_BRDIGE_ESMRAMC_TSEG_SZ_MASK   ((uint8_t)(0x3 << 1))
+#define MCH_HOST_BRDIGE_ESMRAMC_TSEG_SZ_1MB    ((uint8_t)(0x0 << 1))
+#define MCH_HOST_BRDIGE_ESMRAMC_TSEG_SZ_2MB    ((uint8_t)(0x1 << 1))
+#define MCH_HOST_BRDIGE_ESMRAMC_TSEG_SZ_8MB    ((uint8_t)(0x2 << 1))
+#define MCH_HOST_BRDIGE_ESMRAMC_T_EN           ((uint8_t)1)
+
+/* D1:F0 PCIE* port*/
+#define MCH_PCIE_DEV                           1
+#define MCH_PCIE_FUNC                          0
+
+#endif /* HW_Q35_H */

From a1c9304683161a68c1fc1d9c3bc174ec8e26a61a Mon Sep 17 00:00:00 2001
From: Jason Baron 
Date: Wed, 14 Nov 2012 15:54:07 -0500
Subject: [PATCH 1730/2270] ich9: Add i82801b11 dmi-to-pci bridge

Add the dmi-to-pci i82801b11 bridge chip. This is the pci bridge chip
that q35 uses on its host bus for PCI bus arbitration.

Signed-off-by: Isaku Yamahata 
Signed-off-by: Jason Baron 
Signed-off-by: Anthony Liguori 
---
 hw/Makefile.objs |   1 +
 hw/i82801b11.c   | 125 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 126 insertions(+)
 create mode 100644 hw/i82801b11.c

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 35773de1e6..d581d8d6d6 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -10,6 +10,7 @@ common-obj-$(CONFIG_PCI) += shpc.o
 common-obj-$(CONFIG_PCI) += slotid_cap.o
 common-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
 common-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
+common-obj-$(CONFIG_PCI) += i82801b11.o
 common-obj-y += watchdog.o
 common-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
 common-obj-$(CONFIG_ECC) += ecc.o
diff --git a/hw/i82801b11.c b/hw/i82801b11.c
new file mode 100644
index 0000000000..3d1f996b2f
--- /dev/null
+++ b/hw/i82801b11.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+/*
+ * QEMU i82801b11 dmi-to-pci Bridge Emulation
+ *
+ *  Copyright (c) 2009, 2010, 2011
+ *                Isaku Yamahata 
+ *                VA Linux Systems Japan K.K.
+ *  Copyright (C) 2012 Jason Baron 
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see 
+ */
+
+#include "pci.h"
+#include "ich9.h"
+
+
+/*****************************************************************************/
+/* ICH9 DMI-to-PCI bridge */
+#define I82801ba_SSVID_OFFSET   0x50
+#define I82801ba_SSVID_SVID     0
+#define I82801ba_SSVID_SSID     0
+
+typedef struct I82801b11Bridge {
+    PCIBridge br;
+} I82801b11Bridge;
+
+static int i82801b11_bridge_initfn(PCIDevice *d)
+{
+    int rc;
+
+    rc = pci_bridge_initfn(d);
+    if (rc < 0) {
+        return rc;
+    }
+
+    rc = pci_bridge_ssvid_init(d, I82801ba_SSVID_OFFSET,
+                               I82801ba_SSVID_SVID, I82801ba_SSVID_SSID);
+    if (rc < 0) {
+        goto err_bridge;
+    }
+    pci_config_set_prog_interface(d->config, PCI_CLASS_BRDIGE_PCI_INF_SUB);
+    return 0;
+
+err_bridge:
+    pci_bridge_exitfn(d);
+
+    return rc;
+}
+
+static void i82801b11_bridge_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->is_bridge = 1;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82801BA_11;
+    k->revision = ICH9_D2P_A2_REVISION;
+    k->init = i82801b11_bridge_initfn;
+}
+
+static const TypeInfo i82801b11_bridge_info = {
+    .name          = "i82801b11-bridge",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(I82801b11Bridge),
+    .class_init    = i82801b11_bridge_class_init,
+};
+
+PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int sec_bus)
+{
+    PCIDevice *d;
+    PCIBridge *br;
+    char buf[16];
+    DeviceState *qdev;
+
+    d = pci_create_multifunction(bus, devfn, true, "i82801b11-bridge");
+    if (!d) {
+        return NULL;
+    }
+    br = DO_UPCAST(PCIBridge, dev, d);
+    qdev = &br->dev.qdev;
+
+    snprintf(buf, sizeof(buf), "pci.%d", sec_bus);
+    pci_bridge_map_irq(br, buf, pci_swizzle_map_irq_fn);
+    qdev_init_nofail(qdev);
+
+    return pci_bridge_get_sec_bus(br);
+}
+
+static void d2pbr_register(void)
+{
+    type_register_static(&i82801b11_bridge_info);
+}
+
+type_init(d2pbr_register);

From 21bcfdd9a43041720f9370831c694bcb2e11eea4 Mon Sep 17 00:00:00 2001
From: Jan Kiszka 
Date: Wed, 14 Nov 2012 15:54:07 -0500
Subject: [PATCH 1731/2270] q35: Suppress SMM BIOS initialization under KVM

Same as for i44fx: KVM does not support SMM yet. Signal it initialized
to Seabios to avoid failures.

Reviewed-by: Paolo Bonzini 
Signed-off-by: Jan Kiszka 
Signed-off-by: Jason Baron 
Signed-off-by: Anthony Liguori 
---
 hw/acpi_ich9.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index c45921c243..61034d3bd7 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -28,6 +28,7 @@
 #include "qemu-timer.h"
 #include "sysemu.h"
 #include "acpi.h"
+#include "kvm.h"
 
 #include "ich9.h"
 
@@ -292,6 +293,12 @@ static void pm_reset(void *opaque)
     acpi_pm_tmr_reset(&pm->acpi_regs);
     acpi_gpe_reset(&pm->acpi_regs);
 
+    if (kvm_enabled()) {
+        /* Mark SMM as already inited to prevent SMM from running. KVM does not
+         * support SMM mode. */
+        pm->smi_en |= ICH9_PMIO_SMI_EN_APMC_EN;
+    }
+
     pm_update_sci(pm);
 }
 

From 243b95111c8b8d171e627247a7de16e94c7e9de0 Mon Sep 17 00:00:00 2001
From: Jan Kiszka 
Date: Wed, 14 Nov 2012 15:54:08 -0500
Subject: [PATCH 1732/2270] q35: Fix non-PCI IRQ processing in
 ich9_lpc_update_apic

Avoid passing a non-PCI IRQ to ich9_gsi_to_pirq. It's wrong and triggers
an assertion.

Reviewed-by: Paolo Bonzini 
Signed-off-by: Jan Kiszka 
Signed-off-by: Jason Baron 
Signed-off-by: Anthony Liguori 
---
 hw/lpc_ich9.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
index f8f06b394c..2fc83a496f 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -264,9 +264,11 @@ static int ich9_gsi_to_pirq(int gsi)
 
 static void ich9_lpc_update_apic(ICH9LPCState *lpc, int gsi)
 {
-    int level;
+    int level = 0;
 
-    level = pci_bus_get_irq_level(lpc->d.bus, ich9_gsi_to_pirq(gsi));
+    if (gsi >= ICH9_LPC_PIC_NUM_PINS) {
+        level |= pci_bus_get_irq_level(lpc->d.bus, ich9_gsi_to_pirq(gsi));
+    }
     if (gsi == ich9_lpc_sci_irq(lpc)) {
         level |= lpc->sci_level;
     }

From 21022c92dc5095324ceb3effc068b5ff81642125 Mon Sep 17 00:00:00 2001
From: Jan Kiszka 
Date: Wed, 14 Nov 2012 15:54:08 -0500
Subject: [PATCH 1733/2270] q35: Add kvmclock support

Reviewed-by: Paolo Bonzini 
Signed-off-by: Jan Kiszka 
Signed-off-by: Jason Baron 
Signed-off-by: Anthony Liguori 
---
 hw/pc_q35.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hw/pc_q35.c b/hw/pc_q35.c
index 142bf8aa1b..3429a9ae8f 100644
--- a/hw/pc_q35.c
+++ b/hw/pc_q35.c
@@ -34,6 +34,7 @@
 #include "mc146818rtc.h"
 #include "xen.h"
 #include "kvm.h"
+#include "kvm/clock.h"
 #include "q35.h"
 #include "exec-memory.h"
 #include "ich9.h"
@@ -87,6 +88,8 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
 
     pc_cpus_init(cpu_model);
 
+    kvmclock_create();
+
     if (ram_size >= 0xb0000000) {
         above_4g_mem_size = ram_size - 0xb0000000;
         below_4g_mem_size = 0xb0000000;

From b022b4a44abda9b6f89777b07e538be6f8f7aacb Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Fri, 23 Nov 2012 15:59:43 +0100
Subject: [PATCH 1734/2270] aio: avoid livelock behavior for Win32

The repeated calls to WaitForMultipleObjects may cause a livelock in aio_poll,
where no progress is made on bottom halves.  This patch matches the behavior
of the POSIX code.

Signed-off-by: Paolo Bonzini 
Signed-off-by: Anthony Liguori 
---
 aio-win32.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/aio-win32.c b/aio-win32.c
index a84eb71246..cec4646635 100644
--- a/aio-win32.c
+++ b/aio-win32.c
@@ -173,7 +173,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
     }
 
     /* wait until next event */
-    for (;;) {
+    while (count > 0) {
         int timeout = blocking ? INFINITE : 0;
         int ret = WaitForMultipleObjects(count, events, FALSE, timeout);
 
@@ -209,6 +209,9 @@ bool aio_poll(AioContext *ctx, bool blocking)
                 g_free(tmp);
             }
         }
+
+        /* Try again, but only call each handler once.  */
+        events[ret - WAIT_OBJECT_0] = events[--count];
     }
 
     return progress;

From b2ea25d7aea3106f3cad597be20cf5ab4d87f7ab Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Fri, 23 Nov 2012 16:13:23 +0100
Subject: [PATCH 1735/2270] tests: add AioContext unit tests

Signed-off-by: Paolo Bonzini 
Signed-off-by: Anthony Liguori 
---
 tests/Makefile   |   2 +
 tests/test-aio.c | 667 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 669 insertions(+)
 create mode 100644 tests/test-aio.c

diff --git a/tests/Makefile b/tests/Makefile
index ca680e5644..61cbe3b5fa 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -15,6 +15,7 @@ check-unit-y += tests/test-string-output-visitor$(EXESUF)
 check-unit-y += tests/test-coroutine$(EXESUF)
 check-unit-y += tests/test-visitor-serialization$(EXESUF)
 check-unit-y += tests/test-iov$(EXESUF)
+check-unit-y += tests/test-aio$(EXESUF)
 
 check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 
@@ -49,6 +50,7 @@ tests/check-qlist$(EXESUF): tests/check-qlist.o qlist.o qint.o
 tests/check-qfloat$(EXESUF): tests/check-qfloat.o qfloat.o
 tests/check-qjson$(EXESUF): tests/check-qjson.o $(qobject-obj-y) qemu-tool.o
 tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y) $(block-obj-y) iov.o libqemustub.a
+tests/test-aio$(EXESUF): tests/test-aio.o $(coroutine-obj-y) $(tools-obj-y) $(block-obj-y) libqemustub.a
 tests/test-iov$(EXESUF): tests/test-iov.o iov.o
 
 tests/test-qapi-types.c tests/test-qapi-types.h :\
diff --git a/tests/test-aio.c b/tests/test-aio.c
new file mode 100644
index 0000000000..f53c908707
--- /dev/null
+++ b/tests/test-aio.c
@@ -0,0 +1,667 @@
+/*
+ * AioContext tests
+ *
+ * Copyright Red Hat, Inc. 2012
+ *
+ * Authors:
+ *  Paolo Bonzini    
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include 
+#include "qemu-aio.h"
+
+AioContext *ctx;
+
+/* Simple callbacks for testing.  */
+
+typedef struct {
+    QEMUBH *bh;
+    int n;
+    int max;
+} BHTestData;
+
+static void bh_test_cb(void *opaque)
+{
+    BHTestData *data = opaque;
+    if (++data->n < data->max) {
+        qemu_bh_schedule(data->bh);
+    }
+}
+
+static void bh_delete_cb(void *opaque)
+{
+    BHTestData *data = opaque;
+    if (++data->n < data->max) {
+        qemu_bh_schedule(data->bh);
+    } else {
+        qemu_bh_delete(data->bh);
+        data->bh = NULL;
+    }
+}
+
+typedef struct {
+    EventNotifier e;
+    int n;
+    int active;
+    bool auto_set;
+} EventNotifierTestData;
+
+static int event_active_cb(EventNotifier *e)
+{
+    EventNotifierTestData *data = container_of(e, EventNotifierTestData, e);
+    return data->active > 0;
+}
+
+static void event_ready_cb(EventNotifier *e)
+{
+    EventNotifierTestData *data = container_of(e, EventNotifierTestData, e);
+    g_assert(event_notifier_test_and_clear(e));
+    data->n++;
+    if (data->active > 0) {
+        data->active--;
+    }
+    if (data->auto_set && data->active) {
+        event_notifier_set(e);
+    }
+}
+
+/* Tests using aio_*.  */
+
+static void test_notify(void)
+{
+    g_assert(!aio_poll(ctx, false));
+    aio_notify(ctx);
+    g_assert(!aio_poll(ctx, true));
+    g_assert(!aio_poll(ctx, false));
+}
+
+static void test_flush(void)
+{
+    g_assert(!aio_poll(ctx, false));
+    aio_notify(ctx);
+    aio_flush(ctx);
+    g_assert(!aio_poll(ctx, false));
+}
+
+static void test_bh_schedule(void)
+{
+    BHTestData data = { .n = 0 };
+    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
+
+    qemu_bh_schedule(data.bh);
+    g_assert_cmpint(data.n, ==, 0);
+
+    g_assert(aio_poll(ctx, true));
+    g_assert_cmpint(data.n, ==, 1);
+
+    g_assert(!aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 1);
+    qemu_bh_delete(data.bh);
+}
+
+static void test_bh_schedule10(void)
+{
+    BHTestData data = { .n = 0, .max = 10 };
+    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
+
+    qemu_bh_schedule(data.bh);
+    g_assert_cmpint(data.n, ==, 0);
+
+    g_assert(aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 1);
+
+    g_assert(aio_poll(ctx, true));
+    g_assert_cmpint(data.n, ==, 2);
+
+    aio_flush(ctx);
+    g_assert_cmpint(data.n, ==, 10);
+
+    g_assert(!aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 10);
+    qemu_bh_delete(data.bh);
+}
+
+static void test_bh_cancel(void)
+{
+    BHTestData data = { .n = 0 };
+    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
+
+    qemu_bh_schedule(data.bh);
+    g_assert_cmpint(data.n, ==, 0);
+
+    qemu_bh_cancel(data.bh);
+    g_assert_cmpint(data.n, ==, 0);
+
+    g_assert(!aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 0);
+    qemu_bh_delete(data.bh);
+}
+
+static void test_bh_delete(void)
+{
+    BHTestData data = { .n = 0 };
+    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
+
+    qemu_bh_schedule(data.bh);
+    g_assert_cmpint(data.n, ==, 0);
+
+    qemu_bh_delete(data.bh);
+    g_assert_cmpint(data.n, ==, 0);
+
+    g_assert(!aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 0);
+}
+
+static void test_bh_delete_from_cb(void)
+{
+    BHTestData data1 = { .n = 0, .max = 1 };
+
+    data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1);
+
+    qemu_bh_schedule(data1.bh);
+    g_assert_cmpint(data1.n, ==, 0);
+
+    aio_flush(ctx);
+    g_assert_cmpint(data1.n, ==, data1.max);
+    g_assert(data1.bh == NULL);
+
+    g_assert(!aio_poll(ctx, false));
+    g_assert(!aio_poll(ctx, true));
+}
+
+static void test_bh_delete_from_cb_many(void)
+{
+    BHTestData data1 = { .n = 0, .max = 1 };
+    BHTestData data2 = { .n = 0, .max = 3 };
+    BHTestData data3 = { .n = 0, .max = 2 };
+    BHTestData data4 = { .n = 0, .max = 4 };
+
+    data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1);
+    data2.bh = aio_bh_new(ctx, bh_delete_cb, &data2);
+    data3.bh = aio_bh_new(ctx, bh_delete_cb, &data3);
+    data4.bh = aio_bh_new(ctx, bh_delete_cb, &data4);
+
+    qemu_bh_schedule(data1.bh);
+    qemu_bh_schedule(data2.bh);
+    qemu_bh_schedule(data3.bh);
+    qemu_bh_schedule(data4.bh);
+    g_assert_cmpint(data1.n, ==, 0);
+    g_assert_cmpint(data2.n, ==, 0);
+    g_assert_cmpint(data3.n, ==, 0);
+    g_assert_cmpint(data4.n, ==, 0);
+
+    g_assert(aio_poll(ctx, false));
+    g_assert_cmpint(data1.n, ==, 1);
+    g_assert_cmpint(data2.n, ==, 1);
+    g_assert_cmpint(data3.n, ==, 1);
+    g_assert_cmpint(data4.n, ==, 1);
+    g_assert(data1.bh == NULL);
+
+    aio_flush(ctx);
+    g_assert_cmpint(data1.n, ==, data1.max);
+    g_assert_cmpint(data2.n, ==, data2.max);
+    g_assert_cmpint(data3.n, ==, data3.max);
+    g_assert_cmpint(data4.n, ==, data4.max);
+    g_assert(data1.bh == NULL);
+    g_assert(data2.bh == NULL);
+    g_assert(data3.bh == NULL);
+    g_assert(data4.bh == NULL);
+}
+
+static void test_bh_flush(void)
+{
+    BHTestData data = { .n = 0 };
+    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
+
+    qemu_bh_schedule(data.bh);
+    g_assert_cmpint(data.n, ==, 0);
+
+    aio_flush(ctx);
+    g_assert_cmpint(data.n, ==, 1);
+
+    g_assert(!aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 1);
+    qemu_bh_delete(data.bh);
+}
+
+static void test_set_event_notifier(void)
+{
+    EventNotifierTestData data = { .n = 0, .active = 0 };
+    event_notifier_init(&data.e, false);
+    aio_set_event_notifier(ctx, &data.e, event_ready_cb, event_active_cb);
+    g_assert(!aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 0);
+
+    aio_set_event_notifier(ctx, &data.e, NULL, NULL);
+    g_assert(!aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 0);
+    event_notifier_cleanup(&data.e);
+}
+
+static void test_wait_event_notifier(void)
+{
+    EventNotifierTestData data = { .n = 0, .active = 1 };
+    event_notifier_init(&data.e, false);
+    aio_set_event_notifier(ctx, &data.e, event_ready_cb, event_active_cb);
+    g_assert(aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 0);
+    g_assert_cmpint(data.active, ==, 1);
+
+    event_notifier_set(&data.e);
+    g_assert(aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 1);
+    g_assert_cmpint(data.active, ==, 0);
+
+    g_assert(!aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 1);
+    g_assert_cmpint(data.active, ==, 0);
+
+    aio_set_event_notifier(ctx, &data.e, NULL, NULL);
+    g_assert(!aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 1);
+
+    event_notifier_cleanup(&data.e);
+}
+
+static void test_flush_event_notifier(void)
+{
+    EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true };
+    event_notifier_init(&data.e, false);
+    aio_set_event_notifier(ctx, &data.e, event_ready_cb, event_active_cb);
+    g_assert(aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 0);
+    g_assert_cmpint(data.active, ==, 10);
+
+    event_notifier_set(&data.e);
+    g_assert(aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 1);
+    g_assert_cmpint(data.active, ==, 9);
+    g_assert(aio_poll(ctx, false));
+
+    aio_flush(ctx);
+    g_assert_cmpint(data.n, ==, 10);
+    g_assert_cmpint(data.active, ==, 0);
+    g_assert(!aio_poll(ctx, false));
+
+    aio_set_event_notifier(ctx, &data.e, NULL, NULL);
+    g_assert(!aio_poll(ctx, false));
+    event_notifier_cleanup(&data.e);
+}
+
+static void test_wait_event_notifier_noflush(void)
+{
+    EventNotifierTestData data = { .n = 0 };
+    EventNotifierTestData dummy = { .n = 0, .active = 1 };
+
+    event_notifier_init(&data.e, false);
+    aio_set_event_notifier(ctx, &data.e, event_ready_cb, NULL);
+
+    g_assert(!aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 0);
+
+    /* Until there is an active descriptor, aio_poll may or may not call
+     * event_ready_cb.  Still, it must not block.  */
+    event_notifier_set(&data.e);
+    g_assert(!aio_poll(ctx, true));
+    data.n = 0;
+
+    /* An active event notifier forces aio_poll to look at EventNotifiers.  */
+    event_notifier_init(&dummy.e, false);
+    aio_set_event_notifier(ctx, &dummy.e, event_ready_cb, event_active_cb);
+
+    event_notifier_set(&data.e);
+    g_assert(aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 1);
+    g_assert(!aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 1);
+
+    event_notifier_set(&data.e);
+    g_assert(aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 2);
+    g_assert(!aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 2);
+
+    event_notifier_set(&dummy.e);
+    aio_flush(ctx);
+    g_assert_cmpint(data.n, ==, 2);
+    g_assert_cmpint(dummy.n, ==, 1);
+    g_assert_cmpint(dummy.active, ==, 0);
+
+    aio_set_event_notifier(ctx, &dummy.e, NULL, NULL);
+    event_notifier_cleanup(&dummy.e);
+
+    aio_set_event_notifier(ctx, &data.e, NULL, NULL);
+    g_assert(!aio_poll(ctx, false));
+    g_assert_cmpint(data.n, ==, 2);
+
+    event_notifier_cleanup(&data.e);
+}
+
+/* Now the same tests, using the context as a GSource.  They are
+ * very similar to the ones above, with g_main_context_iteration
+ * replacing aio_poll.  However:
+ * - sometimes both the AioContext and the glib main loop wake
+ *   themselves up.  Hence, some "g_assert(!aio_poll(ctx, false));"
+ *   are replaced by "while (g_main_context_iteration(NULL, false));".
+ * - there is no exact replacement for aio_flush's blocking wait.
+ *   "while (g_main_context_iteration(NULL, true)" seems to work,
+ *   but it is not documented _why_ it works.  For these tests a
+ *   non-blocking loop like "while (g_main_context_iteration(NULL, false)"
+ *   works well, and that's what I am using.
+ */
+
+static void test_source_notify(void)
+{
+    while (g_main_context_iteration(NULL, false));
+    aio_notify(ctx);
+    g_assert(g_main_context_iteration(NULL, true));
+    g_assert(!g_main_context_iteration(NULL, false));
+}
+
+static void test_source_flush(void)
+{
+    g_assert(!g_main_context_iteration(NULL, false));
+    aio_notify(ctx);
+    while (g_main_context_iteration(NULL, false));
+    g_assert(!g_main_context_iteration(NULL, false));
+}
+
+static void test_source_bh_schedule(void)
+{
+    BHTestData data = { .n = 0 };
+    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
+
+    qemu_bh_schedule(data.bh);
+    g_assert_cmpint(data.n, ==, 0);
+
+    g_assert(g_main_context_iteration(NULL, true));
+    g_assert_cmpint(data.n, ==, 1);
+
+    g_assert(!g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 1);
+    qemu_bh_delete(data.bh);
+}
+
+static void test_source_bh_schedule10(void)
+{
+    BHTestData data = { .n = 0, .max = 10 };
+    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
+
+    qemu_bh_schedule(data.bh);
+    g_assert_cmpint(data.n, ==, 0);
+
+    g_assert(g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 1);
+
+    g_assert(g_main_context_iteration(NULL, true));
+    g_assert_cmpint(data.n, ==, 2);
+
+    while (g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 10);
+
+    g_assert(!g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 10);
+    qemu_bh_delete(data.bh);
+}
+
+static void test_source_bh_cancel(void)
+{
+    BHTestData data = { .n = 0 };
+    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
+
+    qemu_bh_schedule(data.bh);
+    g_assert_cmpint(data.n, ==, 0);
+
+    qemu_bh_cancel(data.bh);
+    g_assert_cmpint(data.n, ==, 0);
+
+    while (g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 0);
+    qemu_bh_delete(data.bh);
+}
+
+static void test_source_bh_delete(void)
+{
+    BHTestData data = { .n = 0 };
+    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
+
+    qemu_bh_schedule(data.bh);
+    g_assert_cmpint(data.n, ==, 0);
+
+    qemu_bh_delete(data.bh);
+    g_assert_cmpint(data.n, ==, 0);
+
+    while (g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 0);
+}
+
+static void test_source_bh_delete_from_cb(void)
+{
+    BHTestData data1 = { .n = 0, .max = 1 };
+
+    data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1);
+
+    qemu_bh_schedule(data1.bh);
+    g_assert_cmpint(data1.n, ==, 0);
+
+    g_main_context_iteration(NULL, true);
+    g_assert_cmpint(data1.n, ==, data1.max);
+    g_assert(data1.bh == NULL);
+
+    g_assert(!g_main_context_iteration(NULL, false));
+}
+
+static void test_source_bh_delete_from_cb_many(void)
+{
+    BHTestData data1 = { .n = 0, .max = 1 };
+    BHTestData data2 = { .n = 0, .max = 3 };
+    BHTestData data3 = { .n = 0, .max = 2 };
+    BHTestData data4 = { .n = 0, .max = 4 };
+
+    data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1);
+    data2.bh = aio_bh_new(ctx, bh_delete_cb, &data2);
+    data3.bh = aio_bh_new(ctx, bh_delete_cb, &data3);
+    data4.bh = aio_bh_new(ctx, bh_delete_cb, &data4);
+
+    qemu_bh_schedule(data1.bh);
+    qemu_bh_schedule(data2.bh);
+    qemu_bh_schedule(data3.bh);
+    qemu_bh_schedule(data4.bh);
+    g_assert_cmpint(data1.n, ==, 0);
+    g_assert_cmpint(data2.n, ==, 0);
+    g_assert_cmpint(data3.n, ==, 0);
+    g_assert_cmpint(data4.n, ==, 0);
+
+    g_assert(g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data1.n, ==, 1);
+    g_assert_cmpint(data2.n, ==, 1);
+    g_assert_cmpint(data3.n, ==, 1);
+    g_assert_cmpint(data4.n, ==, 1);
+    g_assert(data1.bh == NULL);
+
+    while (g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data1.n, ==, data1.max);
+    g_assert_cmpint(data2.n, ==, data2.max);
+    g_assert_cmpint(data3.n, ==, data3.max);
+    g_assert_cmpint(data4.n, ==, data4.max);
+    g_assert(data1.bh == NULL);
+    g_assert(data2.bh == NULL);
+    g_assert(data3.bh == NULL);
+    g_assert(data4.bh == NULL);
+}
+
+static void test_source_bh_flush(void)
+{
+    BHTestData data = { .n = 0 };
+    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
+
+    qemu_bh_schedule(data.bh);
+    g_assert_cmpint(data.n, ==, 0);
+
+    g_assert(g_main_context_iteration(NULL, true));
+    g_assert_cmpint(data.n, ==, 1);
+
+    g_assert(!g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 1);
+    qemu_bh_delete(data.bh);
+}
+
+static void test_source_set_event_notifier(void)
+{
+    EventNotifierTestData data = { .n = 0, .active = 0 };
+    event_notifier_init(&data.e, false);
+    aio_set_event_notifier(ctx, &data.e, event_ready_cb, event_active_cb);
+    while (g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 0);
+
+    aio_set_event_notifier(ctx, &data.e, NULL, NULL);
+    while (g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 0);
+    event_notifier_cleanup(&data.e);
+}
+
+static void test_source_wait_event_notifier(void)
+{
+    EventNotifierTestData data = { .n = 0, .active = 1 };
+    event_notifier_init(&data.e, false);
+    aio_set_event_notifier(ctx, &data.e, event_ready_cb, event_active_cb);
+    g_assert(g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 0);
+    g_assert_cmpint(data.active, ==, 1);
+
+    event_notifier_set(&data.e);
+    g_assert(g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 1);
+    g_assert_cmpint(data.active, ==, 0);
+
+    while (g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 1);
+    g_assert_cmpint(data.active, ==, 0);
+
+    aio_set_event_notifier(ctx, &data.e, NULL, NULL);
+    while (g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 1);
+
+    event_notifier_cleanup(&data.e);
+}
+
+static void test_source_flush_event_notifier(void)
+{
+    EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true };
+    event_notifier_init(&data.e, false);
+    aio_set_event_notifier(ctx, &data.e, event_ready_cb, event_active_cb);
+    g_assert(g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 0);
+    g_assert_cmpint(data.active, ==, 10);
+
+    event_notifier_set(&data.e);
+    g_assert(g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 1);
+    g_assert_cmpint(data.active, ==, 9);
+    g_assert(g_main_context_iteration(NULL, false));
+
+    while (g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 10);
+    g_assert_cmpint(data.active, ==, 0);
+    g_assert(!g_main_context_iteration(NULL, false));
+
+    aio_set_event_notifier(ctx, &data.e, NULL, NULL);
+    while (g_main_context_iteration(NULL, false));
+    event_notifier_cleanup(&data.e);
+}
+
+static void test_source_wait_event_notifier_noflush(void)
+{
+    EventNotifierTestData data = { .n = 0 };
+    EventNotifierTestData dummy = { .n = 0, .active = 1 };
+
+    event_notifier_init(&data.e, false);
+    aio_set_event_notifier(ctx, &data.e, event_ready_cb, NULL);
+
+    while (g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 0);
+
+    /* Until there is an active descriptor, glib may or may not call
+     * event_ready_cb.  Still, it must not block.  */
+    event_notifier_set(&data.e);
+    g_main_context_iteration(NULL, true);
+    data.n = 0;
+
+    /* An active event notifier forces aio_poll to look at EventNotifiers.  */
+    event_notifier_init(&dummy.e, false);
+    aio_set_event_notifier(ctx, &dummy.e, event_ready_cb, event_active_cb);
+
+    event_notifier_set(&data.e);
+    g_assert(g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 1);
+    g_assert(!g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 1);
+
+    event_notifier_set(&data.e);
+    g_assert(g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 2);
+    g_assert(!g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 2);
+
+    event_notifier_set(&dummy.e);
+    while (g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 2);
+    g_assert_cmpint(dummy.n, ==, 1);
+    g_assert_cmpint(dummy.active, ==, 0);
+
+    aio_set_event_notifier(ctx, &dummy.e, NULL, NULL);
+    event_notifier_cleanup(&dummy.e);
+
+    aio_set_event_notifier(ctx, &data.e, NULL, NULL);
+    while (g_main_context_iteration(NULL, false));
+    g_assert_cmpint(data.n, ==, 2);
+
+    event_notifier_cleanup(&data.e);
+}
+
+/* End of tests.  */
+
+int main(int argc, char **argv)
+{
+    GSource *src;
+
+    ctx = aio_context_new();
+    src = aio_get_g_source(ctx);
+    g_source_attach(src, NULL);
+    g_source_unref(src);
+
+    while (g_main_context_iteration(NULL, false));
+
+    g_test_init(&argc, &argv, NULL);
+    g_test_add_func("/aio/notify",                  test_notify);
+    g_test_add_func("/aio/flush",                   test_flush);
+    g_test_add_func("/aio/bh/schedule",             test_bh_schedule);
+    g_test_add_func("/aio/bh/schedule10",           test_bh_schedule10);
+    g_test_add_func("/aio/bh/cancel",               test_bh_cancel);
+    g_test_add_func("/aio/bh/delete",               test_bh_delete);
+    g_test_add_func("/aio/bh/callback-delete/one",  test_bh_delete_from_cb);
+    g_test_add_func("/aio/bh/callback-delete/many", test_bh_delete_from_cb_many);
+    g_test_add_func("/aio/bh/flush",                test_bh_flush);
+    g_test_add_func("/aio/event/add-remove",        test_set_event_notifier);
+    g_test_add_func("/aio/event/wait",              test_wait_event_notifier);
+    g_test_add_func("/aio/event/wait/no-flush-cb",  test_wait_event_notifier_noflush);
+    g_test_add_func("/aio/event/flush",             test_flush_event_notifier);
+
+    g_test_add_func("/aio-gsource/notify",                  test_source_notify);
+    g_test_add_func("/aio-gsource/flush",                   test_source_flush);
+    g_test_add_func("/aio-gsource/bh/schedule",             test_source_bh_schedule);
+    g_test_add_func("/aio-gsource/bh/schedule10",           test_source_bh_schedule10);
+    g_test_add_func("/aio-gsource/bh/cancel",               test_source_bh_cancel);
+    g_test_add_func("/aio-gsource/bh/delete",               test_source_bh_delete);
+    g_test_add_func("/aio-gsource/bh/callback-delete/one",  test_source_bh_delete_from_cb);
+    g_test_add_func("/aio-gsource/bh/callback-delete/many", test_source_bh_delete_from_cb_many);
+    g_test_add_func("/aio-gsource/bh/flush",                test_source_bh_flush);
+    g_test_add_func("/aio-gsource/event/add-remove",        test_source_set_event_notifier);
+    g_test_add_func("/aio-gsource/event/wait",              test_source_wait_event_notifier);
+    g_test_add_func("/aio-gsource/event/wait/no-flush-cb",  test_source_wait_event_notifier_noflush);
+    g_test_add_func("/aio-gsource/event/flush",             test_source_flush_event_notifier);
+    return g_test_run();
+}

From 74c856e9228445bac1624f6aad83422bdbc59f98 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Fri, 23 Nov 2012 16:13:24 +0100
Subject: [PATCH 1736/2270] tests: add thread pool unit tests

Signed-off-by: Paolo Bonzini 
Signed-off-by: Anthony Liguori 
---
 tests/Makefile           |   2 +
 tests/test-thread-pool.c | 213 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 215 insertions(+)
 create mode 100644 tests/test-thread-pool.c

diff --git a/tests/Makefile b/tests/Makefile
index 61cbe3b5fa..b60f0fb8f0 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -16,6 +16,7 @@ check-unit-y += tests/test-coroutine$(EXESUF)
 check-unit-y += tests/test-visitor-serialization$(EXESUF)
 check-unit-y += tests/test-iov$(EXESUF)
 check-unit-y += tests/test-aio$(EXESUF)
+check-unit-y += tests/test-thread-pool$(EXESUF)
 
 check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 
@@ -51,6 +52,7 @@ tests/check-qfloat$(EXESUF): tests/check-qfloat.o qfloat.o
 tests/check-qjson$(EXESUF): tests/check-qjson.o $(qobject-obj-y) qemu-tool.o
 tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y) $(block-obj-y) iov.o libqemustub.a
 tests/test-aio$(EXESUF): tests/test-aio.o $(coroutine-obj-y) $(tools-obj-y) $(block-obj-y) libqemustub.a
+tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(coroutine-obj-y) $(tools-obj-y) $(block-obj-y) libqemustub.a
 tests/test-iov$(EXESUF): tests/test-iov.o iov.o
 
 tests/test-qapi-types.c tests/test-qapi-types.h :\
diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c
new file mode 100644
index 0000000000..484c5b3b9b
--- /dev/null
+++ b/tests/test-thread-pool.c
@@ -0,0 +1,213 @@
+#include 
+#include "qemu-common.h"
+#include "qemu-aio.h"
+#include "thread-pool.h"
+#include "block.h"
+
+static int active;
+
+typedef struct {
+    BlockDriverAIOCB *aiocb;
+    int n;
+    int ret;
+} WorkerTestData;
+
+static int worker_cb(void *opaque)
+{
+    WorkerTestData *data = opaque;
+    return __sync_fetch_and_add(&data->n, 1);
+}
+
+static int long_cb(void *opaque)
+{
+    WorkerTestData *data = opaque;
+    __sync_fetch_and_add(&data->n, 1);
+    g_usleep(2000000);
+    __sync_fetch_and_add(&data->n, 1);
+    return 0;
+}
+
+static void done_cb(void *opaque, int ret)
+{
+    WorkerTestData *data = opaque;
+    g_assert_cmpint(data->ret, ==, -EINPROGRESS);
+    data->ret = ret;
+    data->aiocb = NULL;
+
+    /* Callbacks are serialized, so no need to use atomic ops.  */
+    active--;
+}
+
+/* A non-blocking poll of the main AIO context (we cannot use aio_poll
+ * because we do not know the AioContext).
+ */
+static void qemu_aio_wait_nonblocking(void)
+{
+    qemu_notify_event();
+    qemu_aio_wait();
+}
+
+static void test_submit(void)
+{
+    WorkerTestData data = { .n = 0 };
+    thread_pool_submit(worker_cb, &data);
+    qemu_aio_flush();
+    g_assert_cmpint(data.n, ==, 1);
+}
+
+static void test_submit_aio(void)
+{
+    WorkerTestData data = { .n = 0, .ret = -EINPROGRESS };
+    data.aiocb = thread_pool_submit_aio(worker_cb, &data, done_cb, &data);
+
+    /* The callbacks are not called until after the first wait.  */
+    active = 1;
+    g_assert_cmpint(data.ret, ==, -EINPROGRESS);
+    qemu_aio_flush();
+    g_assert_cmpint(active, ==, 0);
+    g_assert_cmpint(data.n, ==, 1);
+    g_assert_cmpint(data.ret, ==, 0);
+}
+
+static void co_test_cb(void *opaque)
+{
+    WorkerTestData *data = opaque;
+
+    active = 1;
+    data->n = 0;
+    data->ret = -EINPROGRESS;
+    thread_pool_submit_co(worker_cb, data);
+
+    /* The test continues in test_submit_co, after qemu_coroutine_enter... */
+
+    g_assert_cmpint(data->n, ==, 1);
+    data->ret = 0;
+    active--;
+
+    /* The test continues in test_submit_co, after qemu_aio_flush... */
+}
+
+static void test_submit_co(void)
+{
+    WorkerTestData data;
+    Coroutine *co = qemu_coroutine_create(co_test_cb);
+
+    qemu_coroutine_enter(co, &data);
+
+    /* Back here once the worker has started.  */
+
+    g_assert_cmpint(active, ==, 1);
+    g_assert_cmpint(data.ret, ==, -EINPROGRESS);
+
+    /* qemu_aio_flush will execute the rest of the coroutine.  */
+
+    qemu_aio_flush();
+
+    /* Back here after the coroutine has finished.  */
+
+    g_assert_cmpint(active, ==, 0);
+    g_assert_cmpint(data.ret, ==, 0);
+}
+
+static void test_submit_many(void)
+{
+    WorkerTestData data[100];
+    int i;
+
+    /* Start more work items than there will be threads.  */
+    for (i = 0; i < 100; i++) {
+        data[i].n = 0;
+        data[i].ret = -EINPROGRESS;
+        thread_pool_submit_aio(worker_cb, &data[i], done_cb, &data[i]);
+    }
+
+    active = 100;
+    while (active > 0) {
+        qemu_aio_wait();
+    }
+    for (i = 0; i < 100; i++) {
+        g_assert_cmpint(data[i].n, ==, 1);
+        g_assert_cmpint(data[i].ret, ==, 0);
+    }
+}
+
+static void test_cancel(void)
+{
+    WorkerTestData data[100];
+    int i;
+
+    /* Start more work items than there will be threads, to ensure
+     * the pool is full.
+     */
+    test_submit_many();
+
+    /* Start long running jobs, to ensure we can cancel some.  */
+    for (i = 0; i < 100; i++) {
+        data[i].n = 0;
+        data[i].ret = -EINPROGRESS;
+        data[i].aiocb = thread_pool_submit_aio(long_cb, &data[i],
+                                               done_cb, &data[i]);
+    }
+
+    /* Starting the threads may be left to a bottom half.  Let it
+     * run, but do not waste too much time...
+     */
+    active = 100;
+    qemu_aio_wait_nonblocking();
+
+    /* Wait some time for the threads to start, with some sanity
+     * testing on the behavior of the scheduler...
+     */
+    g_assert_cmpint(active, ==, 100);
+    g_usleep(1000000);
+    g_assert_cmpint(active, >, 50);
+
+    /* Cancel the jobs that haven't been started yet.  */
+    for (i = 0; i < 100; i++) {
+        if (__sync_val_compare_and_swap(&data[i].n, 0, 3) == 0) {
+            data[i].ret = -ECANCELED;
+            bdrv_aio_cancel(data[i].aiocb);
+            active--;
+        }
+    }
+    g_assert_cmpint(active, >, 5);
+    g_assert_cmpint(active, <, 95);
+
+    /* Canceling the others will be a blocking operation.  */
+    for (i = 0; i < 100; i++) {
+        if (data[i].n != 3) {
+            bdrv_aio_cancel(data[i].aiocb);
+        }
+    }
+
+    /* Finish execution and execute any remaining callbacks.  */
+    qemu_aio_flush();
+    g_assert_cmpint(active, ==, 0);
+    for (i = 0; i < 100; i++) {
+        if (data[i].n == 3) {
+            g_assert_cmpint(data[i].ret, ==, -ECANCELED);
+            g_assert(data[i].aiocb != NULL);
+        } else {
+            g_assert_cmpint(data[i].n, ==, 2);
+            g_assert_cmpint(data[i].ret, ==, 0);
+            g_assert(data[i].aiocb == NULL);
+        }
+    }
+}
+
+int main(int argc, char **argv)
+{
+    /* These should be removed once each AioContext has its thread pool.
+     * The test should create its own AioContext.
+     */
+    qemu_init_main_loop();
+    bdrv_init();
+
+    g_test_init(&argc, &argv, NULL);
+    g_test_add_func("/thread-pool/submit", test_submit);
+    g_test_add_func("/thread-pool/submit-aio", test_submit_aio);
+    g_test_add_func("/thread-pool/submit-co", test_submit_co);
+    g_test_add_func("/thread-pool/submit-many", test_submit_many);
+    g_test_add_func("/thread-pool/cancel", test_cancel);
+    return g_test_run();
+}

From b7f43fe46029d8fd0594cd599fa2599dcce0f553 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Fri, 23 Nov 2012 16:56:17 +0100
Subject: [PATCH 1737/2270] qom: dynamic_cast of NULL is always NULL

Trying to cast a NULL value will cause a crash.  Returning
NULL is also sensible, and it is also what the type-unsafe
DO_UPCAST macro does.

Reported-by: Markus Armbruster 
Signed-off-by: Paolo Bonzini 
Signed-off-by: Anthony Liguori 
---
 qom/object.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/qom/object.c b/qom/object.c
index d7092b09d8..2e18c9a4ed 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -417,7 +417,7 @@ void object_delete(Object *obj)
 
 Object *object_dynamic_cast(Object *obj, const char *typename)
 {
-    if (object_class_dynamic_cast(object_get_class(obj), typename)) {
+    if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
         return obj;
     }
 
@@ -430,7 +430,7 @@ Object *object_dynamic_cast_assert(Object *obj, const char *typename)
 
     inst = object_dynamic_cast(obj, typename);
 
-    if (!inst) {
+    if (!inst && obj) {
         fprintf(stderr, "Object %p is not an instance of type %s\n",
                 obj, typename);
         abort();

From b5007bcc9729acd995518c52eb1038c4d8416b5d Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Fri, 23 Nov 2012 16:56:18 +0100
Subject: [PATCH 1738/2270] hmp: do not crash on invalid SCSI hotplug

Commit 0d93692 (qdev: Convert busses to QEMU Object Model, 2012-05-02)
removed a check on the type of the bus where a SCSI disk is hotplugged.
However, hot-plugging to the wrong kind of device now causes a crash
due to either a NULL pointer dereference (avoided by the previous patch)
or a failed QOM cast.

Instead, in this case we need to use object_dynamic_cast and check for
the result, similar to what was done before that commit.

Reported-by: Markus Armbruster 
Signed-off-by: Paolo Bonzini 
Signed-off-by: Anthony Liguori 
---
 hw/pci-hotplug.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index e7fb780a08..0ca5546fc6 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -80,7 +80,13 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
     SCSIBus *scsibus;
     SCSIDevice *scsidev;
 
-    scsibus = SCSI_BUS(QLIST_FIRST(&adapter->child_bus));
+    scsibus = (SCSIBus *)
+        object_dynamic_cast(OBJECT(QLIST_FIRST(&adapter->child_bus)),
+                            TYPE_SCSI_BUS);
+    if (!scsibus) {
+	error_report("Device is not a SCSI adapter");
+	return -1;
+    }
 
     /*
      * drive_init() tries to find a default for dinfo->unit.  Doesn't

From 80ae416058d8941824f450343781183618555415 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Thu, 22 Nov 2012 13:31:03 -0200
Subject: [PATCH 1739/2270] target-i386/cpu: Add missing flags to Haswell CPU
 model
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When adding the Haswell CPU model, I intended to make it a superset of the
features present on the SandyBridge model, but I have removed the SEP and
RDTSCP features from the feature list by mistake. This patch adds the
missing SEP and RDTSCP features (that are present on SandyBridge) to
Haswell.

Reported-by: Martin Kletzander 
Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 target-i386/cpu.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 64c34910a0..4fdd4f72d2 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -657,7 +657,7 @@ static x86_def_t builtin_x86_defs[] = {
         .stepping = 1,
         .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
-             CPUID_PGE | CPUID_MTRR | CPUID_APIC | CPUID_CX8 |
+             CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
         .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
@@ -666,7 +666,8 @@ static x86_def_t builtin_x86_defs[] = {
              CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
              CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
              CPUID_EXT_PCID,
-        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
+        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
+             CPUID_EXT2_SYSCALL,
         .ext3_features = CPUID_EXT3_LAHF_LM,
         .cpuid_7_0_ebx_features = CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
             CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |

From a0a7068104cc9908d0875404b0fa2ebf46e40f97 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno 
Date: Sat, 24 Nov 2012 15:07:01 +0100
Subject: [PATCH 1740/2270] target-i386: Enable SSSE3 TCG support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

SSSE3 support has been added to TCG more than 4 years ago in commit
4242b1bd8acc19aaaacffdaad4ac23213d72a72b. It has been disabled by
mistake in commit 551a2dec8fa55006a68393b9d6fb63577d2b3f1c.

Signed-off-by: Aurelien Jarno 
Signed-off-by: Andreas Färber 
---
 target-i386/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 4fdd4f72d2..c6c2ca03a1 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -315,7 +315,7 @@ typedef struct x86_def_t {
           /* missing:
           CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */
 #define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | \
-          CPUID_EXT_CX16 | CPUID_EXT_POPCNT | \
+          CPUID_EXT_SSSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT | \
           CPUID_EXT_HYPERVISOR)
           /* missing:
           CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST,

From d688e5239aad2a1f991147974832ce026f78c1a3 Mon Sep 17 00:00:00 2001
From: Peter Maydell 
Date: Tue, 20 Nov 2012 08:16:51 +0000
Subject: [PATCH 1741/2270] hw/ide/macio: Fix segfault caused by NULL
 DMAContext*
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Pass qemu_sglist_init the global dma_context_memory rather than a NULL
pointer; this fixes a segfault in dma_memory_map() when the guest
starts using DMA.

Reported-by: Amadeusz Sławiński 
Signed-off-by: Peter Maydell 
Signed-off-by: Alexander Graf 
---
 hw/ide/macio.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 720af6ed9b..d2edcc0850 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -76,7 +76,8 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
 
     s->io_buffer_size = io->len;
 
-    qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1, NULL);
+    qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1,
+                     &dma_context_memory);
     qemu_sglist_add(&s->sg, io->addr, io->len);
     io->addr += io->len;
     io->len = 0;
@@ -132,7 +133,8 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
     s->io_buffer_index = 0;
     s->io_buffer_size = io->len;
 
-    qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1, NULL);
+    qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1,
+                     &dma_context_memory);
     qemu_sglist_add(&s->sg, io->addr, io->len);
     io->addr += io->len;
     io->len = 0;

From f0cc4aa8450376ca2aee3ebb09db71f9f2ff333b Mon Sep 17 00:00:00 2001
From: Julio Guerra 
Date: Fri, 19 Oct 2012 00:17:13 +0000
Subject: [PATCH 1742/2270] PPC: Fix missing TRACE exception

This patch fixes bug 1031698 :
https://bugs.launchpad.net/qemu/+bug/1031698

If we look at the (truncated) translation of the conditional branch
instruction in the test submitted in the bug post, the call to the
exception helper is missing in the "bne-false" chunk of translated
code :

IN:
bne-    0x1800278

OUT:
0xb544236d:  jne    0xb5442396

0xb5442373:  mov    %ebp,(%esp)
0xb5442376:  mov    $0x44,%ebx
0xb544237b:  mov    %ebx,0x4(%esp)
0xb544237f:  mov    $0x1800278,%ebx
0xb5442384:  mov    %ebx,0x25c(%ebp)
0xb544238a:  call   0x827475a
                     ^^^^^^^^^^^^^^^^^^

0xb5442396:  mov    %ebp,(%esp)
0xb5442399:  mov    $0x44,%ebx
0xb544239e:  mov    %ebx,0x4(%esp)
0xb54423a2:  mov    $0x1800270,%ebx
0xb54423a7:  mov    %ebx,0x25c(%ebp)

Indeed, gen_exception(ctx, excp) called by gen_goto_tb (called by
gen_bcond) changes ctx->exception's value to excp's :

gen_bcond()
{
  gen_goto_tb(ctx, 0, ctx->nip + li - 4);
  /* ctx->exception value is POWERPC_EXCP_BRANCH */

  gen_goto_tb(ctx, 1, ctx->nip);
  /* ctx->exception now value is POWERPC_EXCP_TRACE */
}

Making the following gen_goto_tb()'s test false during the second call :

if ((ctx->singlestep_enabled &
    (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
    ctx->exception == POWERPC_EXCP_BRANCH /* false...*/) {
         target_ulong tmp = ctx->nip;
         ctx->nip = dest;
         /* ... and this is the missing call */
         gen_exception(ctx, POWERPC_EXCP_TRACE);
         ctx->nip = tmp;
}

So the patch simply adds the missing matching case, fixing our problem.

Signed-off-by: Julio Guerra 
Signed-off-by: Alexander Graf 
---
 target-ppc/translate.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 16b9c5dd57..987b04eda5 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3473,7 +3473,8 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
         if (unlikely(ctx->singlestep_enabled)) {
             if ((ctx->singlestep_enabled &
                 (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
-                ctx->exception == POWERPC_EXCP_BRANCH) {
+                (ctx->exception == POWERPC_EXCP_BRANCH ||
+                 ctx->exception == POWERPC_EXCP_TRACE)) {
                 target_ulong tmp = ctx->nip;
                 ctx->nip = dest;
                 gen_exception(ctx, POWERPC_EXCP_TRACE);

From 752ced0488806830f18f96b60ae6f3d1fadfd089 Mon Sep 17 00:00:00 2001
From: Alexey Kardashevskiy 
Date: Mon, 19 Nov 2012 15:40:47 +0000
Subject: [PATCH 1743/2270] kvm: fix incorrect length in a loop over kvm dirty
 pages map

QEMU allocates a map enough for 4k pages. However the system page size
can be 64K (for example on POWER) and the host kernel uses only a small
part of it as one big stores a dirty flag for 16 pages 4K each,
the hpratio variable stores this ratio and
the kvm_get_dirty_pages_log_range function handles it correctly.

However kvm_get_dirty_pages_log_range still goes beyond the data
provided by the host kernel which is not correct. It does not cause
errors at the moment as the whole bitmap is zeroed before doing KVM ioctl.

The patch reduces number of iterations over the map.

Signed-off-by: Alexey Kardashevskiy 
Signed-off-by: Alexander Graf 
---
 kvm-all.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kvm-all.c b/kvm-all.c
index 3bc3347d07..8e9a8d8fd2 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -364,7 +364,7 @@ static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section,
     unsigned int i, j;
     unsigned long page_number, c;
     hwaddr addr, addr1;
-    unsigned int len = ((section->size / TARGET_PAGE_SIZE) + HOST_LONG_BITS - 1) / HOST_LONG_BITS;
+    unsigned int len = ((section->size / getpagesize()) + HOST_LONG_BITS - 1) / HOST_LONG_BITS;
     unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE;
 
     /*

From 70c68cf638b4cf44a42a937622deac3ad3c7833c Mon Sep 17 00:00:00 2001
From: Alexey Kardashevskiy 
Date: Mon, 12 Nov 2012 16:46:59 +0000
Subject: [PATCH 1744/2270] pseries: Fix bug in PCI MSI allocation

In one of the recent reworks to the XICS code, a bug was introduced where
we use the wrong sense and allocate level interrupts instead of message
interrupts for PCI MSIs.  This patch fixes it.

Signed-off-by: Alexey Kardashevskiy 
Signed-off-by: David Gibson 
Signed-off-by: Alexander Graf 
---
 hw/spapr_pci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index a08ed11166..3c5b855bc0 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -351,7 +351,7 @@ static void rtas_ibm_change_msi(sPAPREnvironment *spapr,
 
     /* There is no cached config, allocate MSIs */
     if (!phb->msi_table[ndev].nvec) {
-        irq = spapr_allocate_irq_block(req_num, true);
+        irq = spapr_allocate_irq_block(req_num, false);
         if (irq < 0) {
             fprintf(stderr, "Cannot allocate MSIs for device#%d", ndev);
             rtas_st(rets, 0, -1); /* Hardware error */

From c4d88267ae76810420295a1682cf779c49f3ddec Mon Sep 17 00:00:00 2001
From: Peter Maydell 
Date: Thu, 22 Nov 2012 06:48:45 +0000
Subject: [PATCH 1745/2270] vl.c: Fix broken -usb option

Commit 094b287f0b accidentally broke the "-usb" command line
option, so it would have no effect if the user had not specified
any machine options at that point. (the return value from
'qemu_opts_find(qemu_find_opts("machine"), 0);' is NULL if there
are no user specified options, so it is only to be used for
looking up an option, not when trying to set one.) Similarly,
would '-usbdevice' no longer cause USB to default to enabled.

Fix this regression by using the same style of code for forcing
the usb=on machine option that we use for other aliases such as
'-enable-kvm'.

Signed-off-by: Peter Maydell 
Signed-off-by: Alexander Graf 
---
 vl.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/vl.c b/vl.c
index c8e9c782d6..a3ab3841a7 100644
--- a/vl.c
+++ b/vl.c
@@ -3273,16 +3273,12 @@ int main(int argc, char **argv, char **envp)
                 break;
             }
             case QEMU_OPTION_usb:
-                machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-                if (machine_opts) {
-                    qemu_opt_set_bool(machine_opts, "usb", true);
-                }
+                olist = qemu_find_opts("machine");
+                qemu_opts_parse(olist, "usb=on", 0);
                 break;
             case QEMU_OPTION_usbdevice:
-                machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-                if (machine_opts) {
-                    qemu_opt_set_bool(machine_opts, "usb", true);
-                }
+                olist = qemu_find_opts("machine");
+                qemu_opts_parse(olist, "usb=on", 0);
                 add_device_config(DEV_USB, optarg);
                 break;
             case QEMU_OPTION_device:

From 6e72719e721a40fe1224701ca10edc1caf0cd708 Mon Sep 17 00:00:00 2001
From: Alexander Graf 
Date: Mon, 26 Nov 2012 19:49:58 +0100
Subject: [PATCH 1746/2270] fbdev: fix pixman compile on old pixman
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

My QEMU compile failed with the following error:

qemu-pixman.c: In function ‘qemu_pixman_get_type’:
qemu-pixman.c:24: error: ‘PIXMAN_TYPE_BGRA’ undeclared (first use in this function)
qemu-pixman.c:24: error: (Each undeclared identifier is reported only once
qemu-pixman.c:24: error: for each function it appears in.)

Guard the PIXMAN_TYPE_BGRA branch like in the case right above the failing
case, so that compilation is fixed. Functionality on such old pixman is a
different question ;-).

Signed-off-by: Alexander Graf 
---
 qemu-pixman.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/qemu-pixman.c b/qemu-pixman.c
index ac7bc018ec..e46e1804f6 100644
--- a/qemu-pixman.c
+++ b/qemu-pixman.c
@@ -21,7 +21,9 @@ int qemu_pixman_get_type(int rshift, int gshift, int bshift)
         if (rshift == 0) {
             type = PIXMAN_TYPE_ABGR;
         } else {
+#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0, 21, 8)
             type = PIXMAN_TYPE_BGRA;
+#endif
         }
     }
     return type;

From 8c7c3c58e3e33c80d1eef1514db3c705a4de692e Mon Sep 17 00:00:00 2001
From: Heinz Graalfs 
Date: Mon, 19 Nov 2012 23:28:34 +0000
Subject: [PATCH 1747/2270] s390: Fix ram_size updating in machine init

The global variable 'ram_size' is hidden by the local variable
declaration in s390_init(). Since we want to update the global
ram size in certain cases we must not use a local ram_size
variable.
- This fixes booting with unusual ram sizes like -m 67001
- This changes behaviour back to the situation before commit
  5f072e1f3075bd869e0ace9f2545a85992ac0084
  (create struct for machine initialization arguments)

Signed-off-by: Heinz Graalfs 
Reviewed-by: Eduardo Habkost 
Signed-off-by: Christian Borntraeger 
Signed-off-by: Alexander Graf 
---
 hw/s390-virtio.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 685cb5413e..ca1bb09816 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -155,7 +155,6 @@ unsigned s390_del_running_cpu(CPUS390XState *env)
 static void s390_init(QEMUMachineInitArgs *args)
 {
     ram_addr_t my_ram_size = args->ram_size;
-    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;

From 773de5c786a6050bbf3b33c0e29d1bd519a40b4b Mon Sep 17 00:00:00 2001
From: Cornelia Huck 
Date: Fri, 23 Nov 2012 00:18:12 +0000
Subject: [PATCH 1748/2270] sclp: Fix uninitialized var in
 handle_write_event_buf().

Some gcc versions rightly complain about a possibly unitialized rc,
so let's move setting it before the QTAILQ_FOREACH().

Signed-off-by: Cornelia Huck 
Signed-off-by: Christian Borntraeger 
Signed-off-by: Jens Freimann 
Signed-off-by: Alexander Graf 
---
 hw/s390x/event-facility.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c
index 93676602a7..bc9cea9e1b 100644
--- a/hw/s390x/event-facility.c
+++ b/hw/s390x/event-facility.c
@@ -112,12 +112,13 @@ static uint16_t handle_write_event_buf(SCLPEventFacility *ef,
     SCLPEvent *event;
     SCLPEventClass *ec;
 
+    rc = SCLP_RC_INVALID_FUNCTION;
+
     QTAILQ_FOREACH(kid, &ef->sbus.qbus.children, sibling) {
         DeviceState *qdev = kid->child;
         event = (SCLPEvent *) qdev;
         ec = SCLP_EVENT_GET_CLASS(event);
 
-        rc = SCLP_RC_INVALID_FUNCTION;
         if (ec->write_event_data &&
             ec->event_type() == event_buf->type) {
             rc = ec->write_event_data(event, event_buf);

From 764b63125a77dab54ed405d493452a4e05679c2e Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Fri, 23 Nov 2012 09:47:12 +0100
Subject: [PATCH 1749/2270] qom: fix refcount of non-heap-allocated objects
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The reference count for embedded objects is always one too low, because
object_initialize_with_type returns with zero references to the object.
This causes premature finalization of the object (or an assertion failure)
after calling object_ref to add an extra reference and object_unref to
remove it.

The fix is to move the initial object_ref call from object_new_with_type
to object_initialize_with_type.

Acked-by: Andreas Färber 
Signed-off-by: Paolo Bonzini 
Signed-off-by: Anthony Liguori 
---
 qom/object.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/qom/object.c b/qom/object.c
index 2e18c9a4ed..662ff7e093 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -307,6 +307,7 @@ void object_initialize_with_type(void *data, TypeImpl *type)
 
     memset(obj, 0, type->instance_size);
     obj->class = type->class;
+    object_ref(obj);
     QTAILQ_INIT(&obj->properties);
     object_init_with_type(obj, type);
 }
@@ -395,7 +396,6 @@ Object *object_new_with_type(Type type)
 
     obj = g_malloc(type->instance_size);
     object_initialize_with_type(obj, type);
-    object_ref(obj);
 
     return obj;
 }

From 667d22d1ae59da46b4c1fbd094ca61145f19b8c3 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Fri, 23 Nov 2012 09:47:13 +0100
Subject: [PATCH 1750/2270] qdev: move bus removal to object_unparent
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Add an ObjectClass method that is done at object_unparent time.  It
should remove any backlinks to the object in the composition tree,
so that object_delete will be able to drop the last reference and
free the object.

Use it for qdev buses.

Reviewed-by: Andreas Färber 
Signed-off-by: Paolo Bonzini 
Signed-off-by: Anthony Liguori 
---
 hw/qdev.c             | 16 +++++++++++++---
 include/qemu/object.h | 11 +++++++++++
 qom/object.c          |  3 +++
 3 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/hw/qdev.c b/hw/qdev.c
index 7ddcd24299..f43717baa5 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -705,9 +705,6 @@ static void device_finalize(Object *obj)
             qemu_opts_del(dev->opts);
         }
     }
-    if (dev->parent_bus) {
-        bus_remove_child(dev->parent_bus, dev);
-    }
 }
 
 static void device_class_base_init(ObjectClass *class, void *data)
@@ -720,6 +717,18 @@ static void device_class_base_init(ObjectClass *class, void *data)
     klass->props = NULL;
 }
 
+static void qdev_remove_from_bus(Object *obj)
+{
+    DeviceState *dev = DEVICE(obj);
+
+    bus_remove_child(dev->parent_bus, dev);
+}
+
+static void device_class_init(ObjectClass *class, void *data)
+{
+    class->unparent = qdev_remove_from_bus;
+}
+
 void device_reset(DeviceState *dev)
 {
     DeviceClass *klass = DEVICE_GET_CLASS(dev);
@@ -747,6 +756,7 @@ static TypeInfo device_type_info = {
     .instance_init = device_initfn,
     .instance_finalize = device_finalize,
     .class_base_init = device_class_base_init,
+    .class_init = device_class_init,
     .abstract = true,
     .class_size = sizeof(DeviceClass),
 };
diff --git a/include/qemu/object.h b/include/qemu/object.h
index be707f1a36..232463b3c7 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -229,6 +229,15 @@ typedef struct ObjectProperty
     QTAILQ_ENTRY(ObjectProperty) node;
 } ObjectProperty;
 
+/**
+ * ObjectUnparent:
+ * @obj: the object that is being removed from the composition tree
+ *
+ * Called when an object is being removed from the QOM composition tree.
+ * The function should remove any backlinks from children objects to @obj.
+ */
+typedef void (ObjectUnparent)(Object *obj);
+
 /**
  * ObjectClass:
  *
@@ -240,6 +249,8 @@ struct ObjectClass
     /*< private >*/
     Type type;
     GSList *interfaces;
+
+    ObjectUnparent *unparent;
 };
 
 /**
diff --git a/qom/object.c b/qom/object.c
index 662ff7e093..07495066d5 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -363,6 +363,9 @@ void object_unparent(Object *obj)
     if (obj->parent) {
         object_property_del_child(obj->parent, obj, NULL);
     }
+    if (obj->class->unparent) {
+        (obj->class->unparent)(obj);
+    }
 }
 
 static void object_deinit(Object *obj, TypeImpl *type)

From fde9bf4470d4a3b6ee1da0dee2370ab028b6314a Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Fri, 23 Nov 2012 09:47:14 +0100
Subject: [PATCH 1751/2270] qom: make object_delete usable for
 statically-allocated objects
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Store in the object the freeing function that will be used at deletion
time.  This makes it possible to use object_delete on statically-allocated
(embedded) objects.  Dually, it makes it possible to use object_unparent
and object_unref without leaking memory, when the lifetime of object
might extend until after the call to object_delete.

Reviewed-by: Andreas Färber 
Signed-off-by: Paolo Bonzini 
Signed-off-by: Anthony Liguori 
---
 include/qemu/object.h | 9 +++++++++
 qom/object.c          | 5 ++++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/include/qemu/object.h b/include/qemu/object.h
index 232463b3c7..5ddcb4aa5f 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -238,6 +238,14 @@ typedef struct ObjectProperty
  */
 typedef void (ObjectUnparent)(Object *obj);
 
+/**
+ * ObjectFree:
+ * @obj: the object being freed
+ *
+ * Called when an object's last reference is removed.
+ */
+typedef void (ObjectFree)(void *obj);
+
 /**
  * ObjectClass:
  *
@@ -272,6 +280,7 @@ struct Object
 {
     /*< private >*/
     ObjectClass *class;
+    ObjectFree *free;
     QTAILQ_HEAD(, ObjectProperty) properties;
     uint32_t ref;
     Object *parent;
diff --git a/qom/object.c b/qom/object.c
index 07495066d5..3b50255450 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -388,6 +388,9 @@ void object_finalize(void *data)
     object_property_del_all(obj);
 
     g_assert(obj->ref == 0);
+    if (obj->free) {
+        obj->free(obj);
+    }
 }
 
 Object *object_new_with_type(Type type)
@@ -399,6 +402,7 @@ Object *object_new_with_type(Type type)
 
     obj = g_malloc(type->instance_size);
     object_initialize_with_type(obj, type);
+    obj->free = g_free;
 
     return obj;
 }
@@ -415,7 +419,6 @@ void object_delete(Object *obj)
     object_unparent(obj);
     g_assert(obj->ref == 1);
     object_unref(obj);
-    g_free(obj);
 }
 
 Object *object_dynamic_cast(Object *obj, const char *typename)

From 64b625f4b2fdb2c873e25c149648b2ce923faab7 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Fri, 23 Nov 2012 09:47:15 +0100
Subject: [PATCH 1752/2270] qdev: simplify (de)allocation of buses

All conditional deallocation can now be done with object_delete.
Remove the @qom_allocated and @glib_allocated fields; replace the latter
with a direct assignment of the @free function pointer.

Signed-off-by: Paolo Bonzini 
Signed-off-by: Anthony Liguori 
---
 hw/pci.c       |  2 +-
 hw/qdev-core.h |  5 -----
 hw/qdev.c      | 10 +---------
 hw/sysbus.c    |  2 +-
 4 files changed, 3 insertions(+), 16 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 9841e398a6..97a0cd77c1 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -301,9 +301,9 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name,
     PCIBus *bus;
 
     bus = g_malloc0(sizeof(*bus));
-    bus->qbus.glib_allocated = true;
     pci_bus_new_inplace(bus, parent, name, address_space_mem,
                         address_space_io, devfn_min);
+    OBJECT(bus)->free = g_free;
     return bus;
 }
 
diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index fce9e2249c..fff7f0f5ab 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -106,17 +106,12 @@ typedef struct BusChild {
 
 /**
  * BusState:
- * @qom_allocated: Indicates whether the object was allocated by QOM.
- * @glib_allocated: Indicates whether the object was initialized in-place
- * yet is expected to be freed with g_free().
  */
 struct BusState {
     Object obj;
     DeviceState *parent;
     const char *name;
     int allow_hotplug;
-    bool qom_allocated;
-    bool glib_allocated;
     int max_index;
     QTAILQ_HEAD(ChildrenHead, BusChild) children;
     QLIST_ENTRY(BusState) sibling;
diff --git a/hw/qdev.c b/hw/qdev.c
index f43717baa5..788b4da55c 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -454,7 +454,6 @@ BusState *qbus_create(const char *typename, DeviceState *parent, const char *nam
     BusState *bus;
 
     bus = BUS(object_new(typename));
-    bus->qom_allocated = true;
 
     bus->parent = parent;
     bus->name = name ? g_strdup(name) : NULL;
@@ -465,14 +464,7 @@ BusState *qbus_create(const char *typename, DeviceState *parent, const char *nam
 
 void qbus_free(BusState *bus)
 {
-    if (bus->qom_allocated) {
-        object_delete(OBJECT(bus));
-    } else {
-        object_finalize(OBJECT(bus));
-        if (bus->glib_allocated) {
-            g_free(bus);
-        }
-    }
+    object_delete(OBJECT(bus));
 }
 
 static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev)
diff --git a/hw/sysbus.c b/hw/sysbus.c
index 4969f06a66..ef8ffb6603 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -274,7 +274,7 @@ static void main_system_bus_create(void)
     main_system_bus = g_malloc0(system_bus_info.instance_size);
     qbus_create_inplace(main_system_bus, TYPE_SYSTEM_BUS, NULL,
                         "main-system-bus");
-    main_system_bus->glib_allocated = true;
+    OBJECT(main_system_bus)->free = g_free;
     object_property_add_child(container_get(qdev_get_machine(),
                                             "/unattached"),
                               "sysbus", OBJECT(main_system_bus), NULL);

From 339c2708e7a0d91e926c473314d563354a949c7f Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Fri, 23 Nov 2012 09:47:16 +0100
Subject: [PATCH 1753/2270] qom: make object_finalize static

It is not used anymore, and there is no need to make it public.

Signed-off-by: Paolo Bonzini 
Signed-off-by: Anthony Liguori 
---
 include/qemu/object.h | 9 ---------
 qom/object.c          | 2 +-
 2 files changed, 1 insertion(+), 10 deletions(-)

diff --git a/include/qemu/object.h b/include/qemu/object.h
index 5ddcb4aa5f..ed1f47f050 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -504,15 +504,6 @@ void object_initialize_with_type(void *data, Type type);
  */
 void object_initialize(void *obj, const char *typename);
 
-/**
- * object_finalize:
- * @obj: The object to finalize.
- *
- * This function destroys and object without freeing the memory associated with
- * it.
- */
-void object_finalize(void *obj);
-
 /**
  * object_dynamic_cast:
  * @obj: The object to cast.
diff --git a/qom/object.c b/qom/object.c
index 3b50255450..0739aa2943 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -379,7 +379,7 @@ static void object_deinit(Object *obj, TypeImpl *type)
     }
 }
 
-void object_finalize(void *data)
+static void object_finalize(void *data)
 {
     Object *obj = data;
     TypeImpl *ti = obj->class->type;

From fa5358c69d090d13f762f545d39c5e03124dfdd8 Mon Sep 17 00:00:00 2001
From: Peter Maydell 
Date: Thu, 22 Nov 2012 16:48:45 +0000
Subject: [PATCH 1754/2270] vl.c: Fix broken -usb option

Commit 094b287f0b accidentally broke the "-usb" command line
option, so it would have no effect if the user had not specified
any machine options at that point. (the return value from
'qemu_opts_find(qemu_find_opts("machine"), 0);' is NULL if there
are no user specified options, so it is only to be used for
looking up an option, not when trying to set one.) Similarly,
would '-usbdevice' no longer cause USB to default to enabled.

Fix this regression by using the same style of code for forcing
the usb=on machine option that we use for other aliases such as
'-enable-kvm'.

Signed-off-by: Peter Maydell 
Signed-off-by: Anthony Liguori 
---
 vl.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/vl.c b/vl.c
index c8e9c782d6..a3ab3841a7 100644
--- a/vl.c
+++ b/vl.c
@@ -3273,16 +3273,12 @@ int main(int argc, char **argv, char **envp)
                 break;
             }
             case QEMU_OPTION_usb:
-                machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-                if (machine_opts) {
-                    qemu_opt_set_bool(machine_opts, "usb", true);
-                }
+                olist = qemu_find_opts("machine");
+                qemu_opts_parse(olist, "usb=on", 0);
                 break;
             case QEMU_OPTION_usbdevice:
-                machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-                if (machine_opts) {
-                    qemu_opt_set_bool(machine_opts, "usb", true);
-                }
+                olist = qemu_find_opts("machine");
+                qemu_opts_parse(olist, "usb=on", 0);
                 add_device_config(DEV_USB, optarg);
                 break;
             case QEMU_OPTION_device:

From e1e54f3fbee6c0652e19182f4c747de172cbe8b1 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Thu, 22 Nov 2012 13:31:03 -0200
Subject: [PATCH 1755/2270] target-i386: cpu: add missing flags to Haswell CPU
 model
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When adding the Haswell CPU model, I intended to make it a superset of the
features present on the SandyBridge model, but I have removed the SEP and
RDTSCP features from the feature list by mistake. This patch adds the missing
SEP and RDTSCP features (that are present on SandyBridge) to Haswell.

Reported-by: Martin Kletzander 
Acked-by: Andreas Färber 
Signed-off-by: Eduardo Habkost 
Signed-off-by: Anthony Liguori 
---
 target-i386/cpu.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 64c34910a0..4fdd4f72d2 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -657,7 +657,7 @@ static x86_def_t builtin_x86_defs[] = {
         .stepping = 1,
         .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
-             CPUID_PGE | CPUID_MTRR | CPUID_APIC | CPUID_CX8 |
+             CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
         .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
@@ -666,7 +666,8 @@ static x86_def_t builtin_x86_defs[] = {
              CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
              CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
              CPUID_EXT_PCID,
-        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
+        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
+             CPUID_EXT2_SYSCALL,
         .ext3_features = CPUID_EXT3_LAHF_LM,
         .cpuid_7_0_ebx_features = CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
             CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |

From 0c26f2eca40d6c65ea9edc62a10e510dc7f65cc8 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi 
Date: Mon, 26 Nov 2012 13:10:12 +0100
Subject: [PATCH 1756/2270] qapi: handle visitor->type_size() in
 QapiDeallocVisitor
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

visit_type_size() requires either visitor->type_size() or
visitor_uint64() to be implemented, otherwise a NULL function pointer is
invoked.

It is possible to trigger this crash as follows:

  $ qemu-system-x86_64 -netdev tap,sndbuf=0,id=netdev0 \
                       -device virtio-blk-pci,netdev=netdev0

The 'sndbuf' option has type "size".

Reviewed-by: Andreas Färber 
Reviewed-by: Michael Roth 
Signed-off-by: Stefan Hajnoczi 
Signed-off-by: Anthony Liguori 
---
 qapi/qapi-dealloc-visitor.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c
index a154523731..a07b171b86 100644
--- a/qapi/qapi-dealloc-visitor.c
+++ b/qapi/qapi-dealloc-visitor.c
@@ -132,6 +132,11 @@ static void qapi_dealloc_type_number(Visitor *v, double *obj, const char *name,
 {
 }
 
+static void qapi_dealloc_type_size(Visitor *v, size_t *obj, const char *name,
+                                   Error **errp)
+{
+}
+
 static void qapi_dealloc_type_enum(Visitor *v, int *obj, const char *strings[],
                                    const char *kind, const char *name,
                                    Error **errp)
@@ -164,6 +169,7 @@ QapiDeallocVisitor *qapi_dealloc_visitor_new(void)
     v->visitor.type_bool = qapi_dealloc_type_bool;
     v->visitor.type_str = qapi_dealloc_type_str;
     v->visitor.type_number = qapi_dealloc_type_number;
+    v->visitor.type_size = qapi_dealloc_type_size;
 
     QTAILQ_INIT(&v->stack);
 

From 25d87288b150032fedcf7b5380fb54fdbdd6788d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andreas=20F=C3=A4rber?= 
Date: Sun, 25 Nov 2012 20:44:33 +0100
Subject: [PATCH 1757/2270] i8259: Fix PIC_COMMON() macro
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

It used a wrong struct type name since its introduction in
8f04ee0882aec9fe91fb70f767edf5dacff59835 (isa: pic: convert to QEMU
Object Model), apparently it is unused so far.

Signed-off-by: Andreas Färber 
Signed-off-by: Anthony Liguori 
---
 hw/i8259_internal.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/i8259_internal.h b/hw/i8259_internal.h
index 4137b61703..8785b1da3f 100644
--- a/hw/i8259_internal.h
+++ b/hw/i8259_internal.h
@@ -33,7 +33,7 @@ typedef struct PICCommonState PICCommonState;
 
 #define TYPE_PIC_COMMON "pic-common"
 #define PIC_COMMON(obj) \
-     OBJECT_CHECK(PICCommon, (obj), TYPE_PIC_COMMON)
+     OBJECT_CHECK(PICCommonState, (obj), TYPE_PIC_COMMON)
 #define PIC_COMMON_CLASS(klass) \
      OBJECT_CLASS_CHECK(PICCommonClass, (klass), TYPE_PIC_COMMON)
 #define PIC_COMMON_GET_CLASS(obj) \

From 14417039653d3293a795646730a7bf5055d78709 Mon Sep 17 00:00:00 2001
From: Amit Shah 
Date: Wed, 21 Nov 2012 11:21:18 +0530
Subject: [PATCH 1758/2270] virtio-rng: use virtqueue_get_avail_bytes, fix
 migration

Popping an elem from the vq just to find out its length causes problems
with save/load later on.  Use the new virtqueue_get_avail_bytes()
function instead, saves us the complexity in the migration code, as well
as makes the migration endian-safe.

Signed-off-by: Amit Shah 
Reviewed-by: Anthony Liguori 
Signed-off-by: Anthony Liguori 
---
 hw/virtio-rng.c | 76 ++++++++-----------------------------------------
 1 file changed, 12 insertions(+), 64 deletions(-)

diff --git a/hw/virtio-rng.c b/hw/virtio-rng.c
index 3ca96c855f..6c49bb2e9c 100644
--- a/hw/virtio-rng.c
+++ b/hw/virtio-rng.c
@@ -22,14 +22,10 @@ typedef struct VirtIORNG {
 
     /* Only one vq - guest puts buffer(s) on it when it needs entropy */
     VirtQueue *vq;
-    VirtQueueElement elem;
 
     /* Config data for the device -- currently only chardev */
     VirtIORNGConf *conf;
 
-    /* Whether we've popped a vq element into 'elem' above */
-    bool popped;
-
     RngBackend *rng;
 
     /* We purposefully don't migrate this state.  The quota will reset on the
@@ -48,17 +44,12 @@ static bool is_guest_ready(VirtIORNG *vrng)
     return false;
 }
 
-static size_t pop_an_elem(VirtIORNG *vrng)
+static size_t get_request_size(VirtQueue *vq)
 {
-    size_t size;
+    unsigned int in, out;
 
-    if (!vrng->popped && !virtqueue_pop(vrng->vq, &vrng->elem)) {
-        return 0;
-    }
-    vrng->popped = true;
-
-    size = iov_size(vrng->elem.in_sg, vrng->elem.in_num);
-    return size;
+    virtqueue_get_avail_bytes(vq, &in, &out);
+    return in;
 }
 
 static void virtio_rng_process(VirtIORNG *vrng);
@@ -67,6 +58,7 @@ static void virtio_rng_process(VirtIORNG *vrng);
 static void chr_read(void *opaque, const void *buf, size_t size)
 {
     VirtIORNG *vrng = opaque;
+    VirtQueueElement elem;
     size_t len;
     int offset;
 
@@ -78,15 +70,14 @@ static void chr_read(void *opaque, const void *buf, size_t size)
 
     offset = 0;
     while (offset < size) {
-        if (!pop_an_elem(vrng)) {
+        if (!virtqueue_pop(vrng->vq, &elem)) {
             break;
         }
-        len = iov_from_buf(vrng->elem.in_sg, vrng->elem.in_num,
+        len = iov_from_buf(elem.in_sg, elem.in_num,
                            0, buf + offset, size - offset);
         offset += len;
 
-        virtqueue_push(vrng->vq, &vrng->elem, len);
-        vrng->popped = false;
+        virtqueue_push(vrng->vq, &elem, len);
     }
     virtio_notify(&vrng->vdev, vrng->vq);
 
@@ -100,21 +91,19 @@ static void chr_read(void *opaque, const void *buf, size_t size)
 
 static void virtio_rng_process(VirtIORNG *vrng)
 {
-    ssize_t size;
+    size_t size;
 
     if (!is_guest_ready(vrng)) {
         return;
     }
 
-    size = pop_an_elem(vrng);
+    size = get_request_size(vrng->vq);
     size = MIN(vrng->quota_remaining, size);
-
-    if (size > 0) {
+    if (size) {
         rng_backend_request_entropy(vrng->rng, size, chr_read, vrng);
     }
 }
 
-
 static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
 {
     VirtIORNG *vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
@@ -131,23 +120,6 @@ static void virtio_rng_save(QEMUFile *f, void *opaque)
     VirtIORNG *vrng = opaque;
 
     virtio_save(&vrng->vdev, f);
-
-    qemu_put_byte(f, vrng->popped);
-    if (vrng->popped) {
-        int i;
-
-        qemu_put_be32(f, vrng->elem.index);
-
-        qemu_put_be32(f, vrng->elem.in_num);
-        for (i = 0; i < vrng->elem.in_num; i++) {
-            qemu_put_be64(f, vrng->elem.in_addr[i]);
-        }
-
-        qemu_put_be32(f, vrng->elem.out_num);
-        for (i = 0; i < vrng->elem.out_num; i++) {
-            qemu_put_be64(f, vrng->elem.out_addr[i]);
-        }
-    }
 }
 
 static int virtio_rng_load(QEMUFile *f, void *opaque, int version_id)
@@ -159,30 +131,6 @@ static int virtio_rng_load(QEMUFile *f, void *opaque, int version_id)
     }
     virtio_load(&vrng->vdev, f);
 
-    vrng->popped = qemu_get_byte(f);
-    if (vrng->popped) {
-        int i;
-
-        vrng->elem.index = qemu_get_be32(f);
-
-        vrng->elem.in_num = qemu_get_be32(f);
-        g_assert(vrng->elem.in_num < VIRTQUEUE_MAX_SIZE);
-        for (i = 0; i < vrng->elem.in_num; i++) {
-            vrng->elem.in_addr[i] = qemu_get_be64(f);
-        }
-
-        vrng->elem.out_num = qemu_get_be32(f);
-        g_assert(vrng->elem.out_num < VIRTQUEUE_MAX_SIZE);
-        for (i = 0; i < vrng->elem.out_num; i++) {
-            vrng->elem.out_addr[i] = qemu_get_be64(f);
-        }
-
-        virtqueue_map_sg(vrng->elem.in_sg, vrng->elem.in_addr,
-                         vrng->elem.in_num, 1);
-        virtqueue_map_sg(vrng->elem.out_sg, vrng->elem.out_addr,
-                         vrng->elem.out_num, 0);
-    }
-
     /* We may have an element ready but couldn't process it due to a quota
        limit.  Make sure to try again after live migration when the quota may
        have been reset.
@@ -232,7 +180,7 @@ VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf)
 
     vrng->qdev = dev;
     vrng->conf = conf;
-    vrng->popped = false;
+
     vrng->quota_remaining = vrng->conf->max_bytes;
 
     g_assert_cmpint(vrng->conf->max_bytes, <=, INT64_MAX);

From 4621c1768ef5d12171cca2aa1473595ecb9f1c9e Mon Sep 17 00:00:00 2001
From: Amit Shah 
Date: Wed, 21 Nov 2012 11:21:19 +0530
Subject: [PATCH 1759/2270] virtio-rng: remove extra request for entropy

If we got fewer bytes from the backend than requested, don't poke the
backend for more bytes; the guest will ask for more (or if the guest has
already asked for more, the backend knows about it via handle_input()).

Signed-off-by: Amit Shah 
Reviewed-by: Anthony Liguori 
Signed-off-by: Anthony Liguori 
---
 hw/virtio-rng.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/hw/virtio-rng.c b/hw/virtio-rng.c
index 6c49bb2e9c..cf5a8ff77e 100644
--- a/hw/virtio-rng.c
+++ b/hw/virtio-rng.c
@@ -80,13 +80,6 @@ static void chr_read(void *opaque, const void *buf, size_t size)
         virtqueue_push(vrng->vq, &elem, len);
     }
     virtio_notify(&vrng->vdev, vrng->vq);
-
-    /*
-     * Lastly, if we had multiple elems queued by the guest, and we
-     * didn't have enough data to fill them all, indicate we want more
-     * data.
-     */
-    virtio_rng_process(vrng);
 }
 
 static void virtio_rng_process(VirtIORNG *vrng)

From 8cc677435498561d8fe213bb44a02cf4f75cc685 Mon Sep 17 00:00:00 2001
From: Amit Shah 
Date: Wed, 21 Nov 2012 11:21:20 +0530
Subject: [PATCH 1760/2270] virtio-rng: disable timer on device removal

Disable the rate-limit timer on device remove (e.g. hot-unplug).

Signed-off-by: Amit Shah 
Reviewed-by: Anthony Liguori 
Signed-off-by: Anthony Liguori 
---
 hw/virtio-rng.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/virtio-rng.c b/hw/virtio-rng.c
index cf5a8ff77e..c8a6da7fbb 100644
--- a/hw/virtio-rng.c
+++ b/hw/virtio-rng.c
@@ -194,6 +194,8 @@ void virtio_rng_exit(VirtIODevice *vdev)
 {
     VirtIORNG *vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
 
+    qemu_del_timer(vrng->rate_limit_timer);
+    qemu_free_timer(vrng->rate_limit_timer);
     unregister_savevm(vrng->qdev, "virtio-rng", vrng);
     virtio_cleanup(vdev);
 }

From 42015c9acb9fb418c97c42f6e0d44c84999c769d Mon Sep 17 00:00:00 2001
From: Amit Shah 
Date: Wed, 21 Nov 2012 11:21:21 +0530
Subject: [PATCH 1761/2270] virtio-rng: fix typos, comments

Fix typos, whitespace and update comments to match current
implementation.

Signed-off-by: Amit Shah 
Signed-off-by: Anthony Liguori 
---
 hw/virtio-rng.c    | 7 +++----
 include/qemu/rng.h | 6 +++---
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/hw/virtio-rng.c b/hw/virtio-rng.c
index c8a6da7fbb..f4ed9cf92a 100644
--- a/hw/virtio-rng.c
+++ b/hw/virtio-rng.c
@@ -23,7 +23,6 @@ typedef struct VirtIORNG {
     /* Only one vq - guest puts buffer(s) on it when it needs entropy */
     VirtQueue *vq;
 
-    /* Config data for the device -- currently only chardev */
     VirtIORNGConf *conf;
 
     RngBackend *rng;
@@ -125,9 +124,9 @@ static int virtio_rng_load(QEMUFile *f, void *opaque, int version_id)
     virtio_load(&vrng->vdev, f);
 
     /* We may have an element ready but couldn't process it due to a quota
-       limit.  Make sure to try again after live migration when the quota may
-       have been reset.
-    */
+     * limit.  Make sure to try again after live migration when the quota may
+     * have been reset.
+     */
     virtio_rng_process(vrng);
 
     return 0;
diff --git a/include/qemu/rng.h b/include/qemu/rng.h
index 7e9d6723ff..d094bf8d4c 100644
--- a/include/qemu/rng.h
+++ b/include/qemu/rng.h
@@ -61,10 +61,10 @@ struct RngBackend
  * This function is used by the front-end to request entropy from an entropy
  * source.  This function can be called multiple times before @receive_entropy
  * is invoked with different values of @receive_entropy and @opaque.  The
- * backend will queue each request and handle appropriate.
+ * backend will queue each request and handle appropriately.
  *
  * The backend does not need to pass the full amount of data to @receive_entropy
- * but will pass at a value greater than 0.
+ * but will pass a value greater than 0.
  */
 void rng_backend_request_entropy(RngBackend *s, size_t size,
                                  EntropyReceiveFunc *receive_entropy,
@@ -87,7 +87,7 @@ void rng_backend_cancel_requests(RngBackend *s);
  *
  * This function will open the backend if it is not already open.  Calling this
  * function on an already opened backend will not result in an error.
- */ 
+ */
 void rng_backend_open(RngBackend *s, Error **errp);
 
 #endif

From 1e1d71a582c60b7c435b05934423c87f83eab542 Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Mon, 26 Nov 2012 15:13:31 -0600
Subject: [PATCH 1762/2270] Update version for 1.3.0-rc1

Signed-off-by: Anthony Liguori 
---
 VERSION | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/VERSION b/VERSION
index 2d04904622..1ec5aef844 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.90
+1.2.91

From d60478c59a348886d82492861c5cd4fba572ebd5 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Tue, 27 Nov 2012 09:51:48 +0100
Subject: [PATCH 1763/2270] tests: make threadpool cancellation test looser

The cancellation test is failing on the buildbots.  While the failure
merits a little more investigation to understand what is going on,
the logs show that the failure is not impacting the coverage
provided by the test.  Hence, loosen a bit the assertions in a
way that should let the test proceed and hopefully pass.

Signed-off-by: Paolo Bonzini 
Signed-off-by: Anthony Liguori 
---
 tests/test-thread-pool.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c
index 484c5b3b9b..fea0445fb4 100644
--- a/tests/test-thread-pool.c
+++ b/tests/test-thread-pool.c
@@ -134,6 +134,7 @@ static void test_submit_many(void)
 static void test_cancel(void)
 {
     WorkerTestData data[100];
+    int num_canceled;
     int i;
 
     /* Start more work items than there will be threads, to ensure
@@ -163,15 +164,17 @@ static void test_cancel(void)
     g_assert_cmpint(active, >, 50);
 
     /* Cancel the jobs that haven't been started yet.  */
+    num_canceled = 0;
     for (i = 0; i < 100; i++) {
         if (__sync_val_compare_and_swap(&data[i].n, 0, 3) == 0) {
             data[i].ret = -ECANCELED;
             bdrv_aio_cancel(data[i].aiocb);
             active--;
+            num_canceled++;
         }
     }
-    g_assert_cmpint(active, >, 5);
-    g_assert_cmpint(active, <, 95);
+    g_assert_cmpint(active, >, 0);
+    g_assert_cmpint(num_canceled, <, 100);
 
     /* Canceling the others will be a blocking operation.  */
     for (i = 0; i < 100; i++) {

From 03a36f17d7788e4a1e07b3341b18028aa0206845 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Tue, 27 Nov 2012 09:16:24 +0100
Subject: [PATCH 1764/2270] virtio-rng: do not use g_assert_cmpint

g_assert_cmpint is not available on glib 2.12, which is the minimum
version required to build QEMU (we only require 2.16 to run tests,
since that is the first version including GTester).  Do not use it
in hardware models, use a normal assertion instead.

This fixes the buildbot failure for default_x86_64_rhel5.

Signed-off-by: Paolo Bonzini 
Signed-off-by: Anthony Liguori 
---
 hw/virtio-rng.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/hw/virtio-rng.c b/hw/virtio-rng.c
index f4ed9cf92a..df329f25e1 100644
--- a/hw/virtio-rng.c
+++ b/hw/virtio-rng.c
@@ -173,10 +173,9 @@ VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf)
     vrng->qdev = dev;
     vrng->conf = conf;
 
+    assert(vrng->conf->max_bytes <= INT64_MAX);
     vrng->quota_remaining = vrng->conf->max_bytes;
 
-    g_assert_cmpint(vrng->conf->max_bytes, <=, INT64_MAX);
-
     vrng->rate_limit_timer = qemu_new_timer_ms(vm_clock,
                                                check_rate_limit, vrng);
 

From 02c6ccc6dde90dcbf5975b1cfe2ab199e525ec11 Mon Sep 17 00:00:00 2001
From: Alex Horn 
Date: Mon, 26 Nov 2012 17:32:54 +0100
Subject: [PATCH 1765/2270] rtc: Only call rtc_set_cmos when Register B SET
 flag is disabled.

This bug occurs when the SET flag of Register B is enabled. When an RTC
data register (i.e. any of the ten time/calender CMOS bytes) is set, the
data is (as expected) correctly stored in the cmos_data array. However,
since the SET flag is enabled, the function rtc_set_time is not invoked.
As a result, the field base_rtc in RTCState remains uninitialized. This
causes a problem on subsequent writes which can end up overwriting data.
To see this, consider writing data to Register A after having written
data to any of the RTC data registers; the following figure illustrates
the call stack for the Register A write operation:

 +- cmos_io_port_write
 +-- check_update_timer
 +---- get_next_alarm
 +------ rtc_update_time

In rtc_update_time, get_guest_rtc calculates the wrong time and
overwrites the previously written RTC data register values.

Signed-off-by: Alex Horn 
Signed-off-by: Paolo Bonzini 
Signed-off-by: Anthony Liguori 
---
 hw/mc146818rtc.c |  6 +++++-
 tests/rtc-test.c | 40 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 7d84ce3d74..c79fca7d68 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -570,7 +570,11 @@ static void rtc_update_time(RTCState *s)
     guest_nsec = get_guest_rtc_ns(s);
     guest_sec = guest_nsec / NSEC_PER_SEC;
     gmtime_r(&guest_sec, &ret);
-    rtc_set_cmos(s, &ret);
+
+    /* Is SET flag of Register B disabled? */
+    if ((s->cmos_data[RTC_REG_B] & REG_B_SET) == 0) {
+        rtc_set_cmos(s, &ret);
+    }
 }
 
 static int update_in_progress(RTCState *s)
diff --git a/tests/rtc-test.c b/tests/rtc-test.c
index 7fdc94a3de..02edbf5727 100644
--- a/tests/rtc-test.c
+++ b/tests/rtc-test.c
@@ -327,6 +327,45 @@ static void fuzz_registers(void)
     }
 }
 
+static void register_b_set_flag(void)
+{
+    /* Enable binary-coded decimal (BCD) mode and SET flag in Register B*/
+    cmos_write(RTC_REG_B, (cmos_read(RTC_REG_B) & ~REG_B_DM) | REG_B_SET);
+
+    cmos_write(RTC_REG_A, 0x76);
+    cmos_write(RTC_YEAR, 0x11);
+    cmos_write(RTC_CENTURY, 0x20);
+    cmos_write(RTC_MONTH, 0x02);
+    cmos_write(RTC_DAY_OF_MONTH, 0x02);
+    cmos_write(RTC_HOURS, 0x02);
+    cmos_write(RTC_MINUTES, 0x04);
+    cmos_write(RTC_SECONDS, 0x58);
+    cmos_write(RTC_REG_A, 0x26);
+
+    /* Since SET flag is still enabled, these are equality checks. */
+    g_assert_cmpint(cmos_read(RTC_HOURS), ==, 0x02);
+    g_assert_cmpint(cmos_read(RTC_MINUTES), ==, 0x04);
+    g_assert_cmpint(cmos_read(RTC_SECONDS), ==, 0x58);
+    g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02);
+    g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02);
+    g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x11);
+    g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x20);
+
+    /* Disable SET flag in Register B */
+    cmos_write(RTC_REG_B, cmos_read(RTC_REG_B) & ~REG_B_SET);
+
+    g_assert_cmpint(cmos_read(RTC_HOURS), ==, 0x02);
+    g_assert_cmpint(cmos_read(RTC_MINUTES), ==, 0x04);
+
+    /* Since SET flag is disabled, this is an inequality check.
+     * We (reasonably) assume that no (sexagesimal) overflow occurs. */
+    g_assert_cmpint(cmos_read(RTC_SECONDS), >=, 0x58);
+    g_assert_cmpint(cmos_read(RTC_DAY_OF_MONTH), ==, 0x02);
+    g_assert_cmpint(cmos_read(RTC_MONTH), ==, 0x02);
+    g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x11);
+    g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x20);
+}
+
 int main(int argc, char **argv)
 {
     QTestState *s = NULL;
@@ -342,6 +381,7 @@ int main(int argc, char **argv)
     qtest_add_func("/rtc/alarm-time", alarm_time);
     qtest_add_func("/rtc/set-year/20xx", set_year_20xx);
     qtest_add_func("/rtc/set-year/1980", set_year_1980);
+    qtest_add_func("/rtc/register_b_set_flag", register_b_set_flag);
     qtest_add_func("/rtc/fuzz-registers", fuzz_registers);
     ret = g_test_run();
 

From 8ffaaba0e939f2a284bb23d1f6f7f9e2104a97e2 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Mon, 26 Nov 2012 15:19:31 +0100
Subject: [PATCH 1766/2270] nbd: fix use of two uninitialized bytes when
 connecting to a named export

Reported-by: Michal Privoznik 
Signed-off-by: Paolo Bonzini 
---
 nbd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/nbd.c b/nbd.c
index 97a5914e0f..01976e8e33 100644
--- a/nbd.c
+++ b/nbd.c
@@ -397,6 +397,7 @@ static int nbd_send_negotiate(NBDClient *client)
     rc = -EINVAL;
 
     TRACE("Beginning negotiation.");
+    memset(buf, 0, sizeof(buf));
     memcpy(buf, "NBDMAGIC", 8);
     if (client->exp) {
         assert ((client->exp->nbdflags & ~65535) == 0);
@@ -406,7 +407,6 @@ static int nbd_send_negotiate(NBDClient *client)
     } else {
         cpu_to_be64w((uint64_t*)(buf + 8), NBD_OPTS_MAGIC);
     }
-    memset(buf + 28, 0, 124);
 
     if (client->exp) {
         if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {

From f3313d23a061648c99609a4c127ed13c820f831d Mon Sep 17 00:00:00 2001
From: Michal Privoznik 
Date: Wed, 28 Nov 2012 11:46:39 +0100
Subject: [PATCH 1767/2270] nbd-server-add: Fix the default for 'writable'

The documentation to this monitor command tells, that 'writable'
argument is optional and defaults to false. However, the code sets
true as the default. But since some applications may already been
using this, it's safer to fix the code and not documentation which
would break those applications.

Signed-off-by: Michal Privoznik 
Signed-off-by: Paolo Bonzini 
---
 blockdev-nbd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index d1721a3e26..6b26bbf8c5 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -99,7 +99,7 @@ void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
     }
 
     if (!has_writable) {
-        writable = true;
+        writable = false;
     }
     if (bdrv_is_read_only(bs)) {
         writable = false;

From 8da1e18b0cf46b6c95c88bbad1cc50d6dd1bef4b Mon Sep 17 00:00:00 2001
From: Peter Lieven 
Date: Thu, 15 Nov 2012 15:42:06 +0100
Subject: [PATCH 1768/2270] iscsi: fix segfault in url parsing

If an invalid URL is specified iscsi_get_error(iscsi) is called
with iscsi == NULL.

Signed-off-by: Peter Lieven 
Signed-off-by: Paolo Bonzini 
---
 block/iscsi.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/block/iscsi.c b/block/iscsi.c
index a6a819d68f..5cd8b49a3f 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -947,8 +947,7 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
 
     iscsi_url = iscsi_parse_full_url(iscsi, filename);
     if (iscsi_url == NULL) {
-        error_report("Failed to parse URL : %s %s", filename,
-                     iscsi_get_error(iscsi));
+        error_report("Failed to parse URL : %s", filename);
         ret = -EINVAL;
         goto out;
     }

From e829b0bb054ed3389e5b22dad61875e51674e629 Mon Sep 17 00:00:00 2001
From: Peter Lieven 
Date: Sat, 17 Nov 2012 14:37:39 +0100
Subject: [PATCH 1769/2270] iscsi: fix deadlock during login

If the connection is interrupted before the first login is successfully
completed qemu-kvm is waiting forever in qemu_aio_wait().

This is fixed by performing an sync login to the target. If the
connection breaks after the first successful login errors are
handled internally by libiscsi.

Signed-off-by: Peter Lieven 
Signed-off-by: Paolo Bonzini 
---
 block/iscsi.c | 251 ++++++++++++++------------------------------------
 1 file changed, 70 insertions(+), 181 deletions(-)

diff --git a/block/iscsi.c b/block/iscsi.c
index 5cd8b49a3f..01340e1167 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -65,13 +65,6 @@ typedef struct IscsiAIOCB {
 #endif
 } IscsiAIOCB;
 
-struct IscsiTask {
-    IscsiLun *iscsilun;
-    BlockDriverState *bs;
-    int status;
-    int complete;
-};
-
 static void
 iscsi_bh_cb(void *p)
 {
@@ -380,7 +373,7 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
         *(uint16_t *)&acb->task->cdb[7] = htons(num_sectors);
         break;
     }
-    
+
     if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
                                  iscsi_aio_read16_cb,
                                  NULL,
@@ -665,163 +658,6 @@ iscsi_getlength(BlockDriverState *bs)
     return len;
 }
 
-static void
-iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status,
-                        void *command_data, void *opaque)
-{
-    struct IscsiTask *itask = opaque;
-    struct scsi_readcapacity16 *rc16;
-    struct scsi_task *task = command_data;
-
-    if (status != 0) {
-        error_report("iSCSI: Failed to read capacity of iSCSI lun. %s",
-                     iscsi_get_error(iscsi));
-        itask->status   = 1;
-        itask->complete = 1;
-        scsi_free_scsi_task(task);
-        return;
-    }
-
-    rc16 = scsi_datain_unmarshall(task);
-    if (rc16 == NULL) {
-        error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
-        itask->status   = 1;
-        itask->complete = 1;
-        scsi_free_scsi_task(task);
-        return;
-    }
-
-    itask->iscsilun->block_size = rc16->block_length;
-    itask->iscsilun->num_blocks = rc16->returned_lba + 1;
-    itask->bs->total_sectors    = itask->iscsilun->num_blocks *
-                               itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
-
-    itask->status   = 0;
-    itask->complete = 1;
-    scsi_free_scsi_task(task);
-}
-
-static void
-iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status,
-                        void *command_data, void *opaque)
-{
-    struct IscsiTask *itask = opaque;
-    struct scsi_readcapacity10 *rc10;
-    struct scsi_task *task = command_data;
-
-    if (status != 0) {
-        error_report("iSCSI: Failed to read capacity of iSCSI lun. %s",
-                     iscsi_get_error(iscsi));
-        itask->status   = 1;
-        itask->complete = 1;
-        scsi_free_scsi_task(task);
-        return;
-    }
-
-    rc10 = scsi_datain_unmarshall(task);
-    if (rc10 == NULL) {
-        error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
-        itask->status   = 1;
-        itask->complete = 1;
-        scsi_free_scsi_task(task);
-        return;
-    }
-
-    itask->iscsilun->block_size = rc10->block_size;
-    if (rc10->lba == 0) {
-        /* blank disk loaded */
-        itask->iscsilun->num_blocks = 0;
-    } else {
-        itask->iscsilun->num_blocks = rc10->lba + 1;
-    }
-    itask->bs->total_sectors    = itask->iscsilun->num_blocks *
-                               itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
-
-    itask->status   = 0;
-    itask->complete = 1;
-    scsi_free_scsi_task(task);
-}
-
-static void
-iscsi_inquiry_cb(struct iscsi_context *iscsi, int status, void *command_data,
-                 void *opaque)
-{
-    struct IscsiTask *itask = opaque;
-    struct scsi_task *task = command_data;
-    struct scsi_inquiry_standard *inq;
-
-    if (status != 0) {
-        itask->status   = 1;
-        itask->complete = 1;
-        scsi_free_scsi_task(task);
-        return;
-    }
-
-    inq = scsi_datain_unmarshall(task);
-    if (inq == NULL) {
-        error_report("iSCSI: Failed to unmarshall inquiry data.");
-        itask->status   = 1;
-        itask->complete = 1;
-        scsi_free_scsi_task(task);
-        return;
-    }
-
-    itask->iscsilun->type = inq->periperal_device_type;
-
-    scsi_free_scsi_task(task);
-
-    switch (itask->iscsilun->type) {
-    case TYPE_DISK:
-        task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun,
-                                   iscsi_readcapacity16_cb, opaque);
-        if (task == NULL) {
-            error_report("iSCSI: failed to send readcapacity16 command.");
-            itask->status   = 1;
-            itask->complete = 1;
-            return;
-        }
-        break;
-    case TYPE_ROM:
-        task = iscsi_readcapacity10_task(iscsi, itask->iscsilun->lun,
-                                   0, 0,
-                                   iscsi_readcapacity10_cb, opaque);
-        if (task == NULL) {
-            error_report("iSCSI: failed to send readcapacity16 command.");
-            itask->status   = 1;
-            itask->complete = 1;
-            return;
-        }
-        break;
-    default:
-        itask->status   = 0;
-        itask->complete = 1;
-    }
-}
-
-static void
-iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data,
-                 void *opaque)
-{
-    struct IscsiTask *itask = opaque;
-    struct scsi_task *task;
-
-    if (status != 0) {
-        itask->status   = 1;
-        itask->complete = 1;
-        return;
-    }
-
-    task = iscsi_inquiry_task(iscsi, itask->iscsilun->lun,
-                              0, 0, 36,
-                              iscsi_inquiry_cb, opaque);
-    if (task == NULL) {
-        error_report("iSCSI: failed to send inquiry command.");
-        itask->status   = 1;
-        itask->complete = 1;
-        return;
-    }
-}
-
 static int parse_chap(struct iscsi_context *iscsi, const char *target)
 {
     QemuOptsList *list;
@@ -934,7 +770,10 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
     IscsiLun *iscsilun = bs->opaque;
     struct iscsi_context *iscsi = NULL;
     struct iscsi_url *iscsi_url = NULL;
-    struct IscsiTask task;
+    struct scsi_task *task = NULL;
+    struct scsi_inquiry_standard *inq = NULL;
+    struct scsi_readcapacity10 *rc10 = NULL;
+    struct scsi_readcapacity16 *rc16 = NULL;
     char *initiator_name = NULL;
     int ret;
 
@@ -997,33 +836,80 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
     /* check if we got HEADER_DIGEST via the options */
     parse_header_digest(iscsi, iscsi_url->target);
 
-    task.iscsilun = iscsilun;
-    task.status = 0;
-    task.complete = 0;
-    task.bs = bs;
+    if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
+        error_report("iSCSI: Failed to connect to LUN : %s",
+            iscsi_get_error(iscsi));
+        ret = -EINVAL;
+        goto out;
+    }
 
     iscsilun->iscsi = iscsi;
     iscsilun->lun   = iscsi_url->lun;
 
-    if (iscsi_full_connect_async(iscsi, iscsi_url->portal, iscsi_url->lun,
-                                 iscsi_connect_cb, &task)
-        != 0) {
-        error_report("iSCSI: Failed to start async connect.");
+    task = iscsi_inquiry_sync(iscsi, iscsilun->lun, 0, 0, 36);
+
+    if (task == NULL || task->status != SCSI_STATUS_GOOD) {
+        error_report("iSCSI: failed to send inquiry command.");
         ret = -EINVAL;
         goto out;
     }
 
-    while (!task.complete) {
-        iscsi_set_events(iscsilun);
-        qemu_aio_wait();
-    }
-    if (task.status != 0) {
-        error_report("iSCSI: Failed to connect to LUN : %s",
-                     iscsi_get_error(iscsi));
+    inq = scsi_datain_unmarshall(task);
+    if (inq == NULL) {
+        error_report("iSCSI: Failed to unmarshall inquiry data.");
         ret = -EINVAL;
         goto out;
     }
 
+    iscsilun->type = inq->periperal_device_type;
+
+    scsi_free_scsi_task(task);
+
+    switch (iscsilun->type) {
+    case TYPE_DISK:
+        task = iscsi_readcapacity16_sync(iscsi, iscsilun->lun);
+        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
+            error_report("iSCSI: failed to send readcapacity16 command.");
+            ret = -EINVAL;
+            goto out;
+        }
+        rc16 = scsi_datain_unmarshall(task);
+        if (rc16 == NULL) {
+            error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
+            ret = -EINVAL;
+            goto out;
+        }
+        iscsilun->block_size = rc16->block_length;
+        iscsilun->num_blocks = rc16->returned_lba + 1;
+        break;
+    case TYPE_ROM:
+        task = iscsi_readcapacity10_sync(iscsi, iscsilun->lun, 0, 0);
+        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
+            error_report("iSCSI: failed to send readcapacity10 command.");
+            ret = -EINVAL;
+            goto out;
+        }
+        rc10 = scsi_datain_unmarshall(task);
+        if (rc10 == NULL) {
+            error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
+            ret = -EINVAL;
+            goto out;
+        }
+        iscsilun->block_size = rc10->block_size;
+        if (rc10->lba == 0) {
+            /* blank disk loaded */
+            iscsilun->num_blocks = 0;
+        } else {
+            iscsilun->num_blocks = rc10->lba + 1;
+        }
+        break;
+    default:
+        break;
+    }
+
+    bs->total_sectors    = iscsilun->num_blocks *
+                           iscsilun->block_size / BDRV_SECTOR_SIZE ;
+
     /* Medium changer or tape. We dont have any emulation for this so this must
      * be sg ioctl compatible. We force it to be sg, otherwise qemu will try
      * to read from the device to guess the image format.
@@ -1042,6 +928,9 @@ out:
     if (iscsi_url != NULL) {
         iscsi_destroy_url(iscsi_url);
     }
+    if (task != NULL) {
+        scsi_free_scsi_task(task);
+    }
 
     if (ret) {
         if (iscsi != NULL) {

From f807ecd5741325fe0d281199ff22cdda0acb6a7a Mon Sep 17 00:00:00 2001
From: Peter Lieven 
Date: Sat, 17 Nov 2012 16:20:28 +0100
Subject: [PATCH 1770/2270] iscsi: do not assume device is zero initialized

Without any complex checks we can't assume that an
iscsi target is initialized to zero.

Signed-off-by: Peter Lieven 
Signed-off-by: Paolo Bonzini 
---
 block/iscsi.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/block/iscsi.c b/block/iscsi.c
index 01340e1167..c0b70b3d32 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -951,6 +951,11 @@ static void iscsi_close(BlockDriverState *bs)
     memset(iscsilun, 0, sizeof(IscsiLun));
 }
 
+static int iscsi_has_zero_init(BlockDriverState *bs)
+{
+    return 0;
+}
+
 static BlockDriver bdrv_iscsi = {
     .format_name     = "iscsi",
     .protocol_name   = "iscsi",
@@ -966,6 +971,7 @@ static BlockDriver bdrv_iscsi = {
     .bdrv_aio_flush  = iscsi_aio_flush,
 
     .bdrv_aio_discard = iscsi_aio_discard,
+    .bdrv_has_zero_init = iscsi_has_zero_init,
 
 #ifdef __linux__
     .bdrv_ioctl       = iscsi_ioctl,

From 474ee55a18765e7de8f0b2cc00db5d26286bb24d Mon Sep 17 00:00:00 2001
From: David Gibson 
Date: Fri, 23 Nov 2012 16:08:44 +1100
Subject: [PATCH 1771/2270] virtio-scsi: Fix some endian bugs with virtio-scsi

The virtio-scsi specification does not specify the correct endianness for
fields in the request structure.  It's therefore best to assume that it is
"guest native" endian since that's the (stupid and poorly defined) norm in
virtio.

However, the qemu device for virtio-scsi has no byteswaps at all, and so
will break if the guest has different endianness from the host.  This patch
fixes it by adding tswap() calls for the sense_len and resid fields in
the request structure.  In theory status_qualifier needs swaps as well,
but that field is never actually touched.  The tag field is a uint64_t, but
since its value is completely arbitrary, it might as well be uint8_t[8]
and so it does not need swapping.

Cc: Paolo Bonzini 
Cc: Paul 'Rusty' Russell 
Signed-off-by: David Gibson 
Signed-off-by: Paolo Bonzini 
---
 hw/virtio-scsi.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 7d546f6ca7..924fc69b73 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -424,15 +424,17 @@ static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
                                          size_t resid)
 {
     VirtIOSCSIReq *req = r->hba_private;
+    uint32_t sense_len;
 
     req->resp.cmd->response = VIRTIO_SCSI_S_OK;
     req->resp.cmd->status = status;
     if (req->resp.cmd->status == GOOD) {
-        req->resp.cmd->resid = resid;
+        req->resp.cmd->resid = tswap32(resid);
     } else {
         req->resp.cmd->resid = 0;
-        req->resp.cmd->sense_len =
-            scsi_req_get_sense(r, req->resp.cmd->sense, VIRTIO_SCSI_SENSE_SIZE);
+        sense_len = scsi_req_get_sense(r, req->resp.cmd->sense,
+                                       VIRTIO_SCSI_SENSE_SIZE);
+        req->resp.cmd->sense_len = tswap32(sense_len);
     }
     virtio_scsi_complete_req(req);
 }

From 863d1050c96cff91dd478767c0da9cc288575919 Mon Sep 17 00:00:00 2001
From: David Gibson 
Date: Mon, 26 Nov 2012 12:33:52 +1100
Subject: [PATCH 1772/2270] virtio-scsi: Fix subtle (guest) endian bug

The virtio-scsi config space is, by specification, in guest endian (which
is ill-defined, but there you go).  In virtio_scsi_get_config() we set up
all the fields in there, using stl_raw().  Which is a problem for the
max_channel and max_target fields, which are 16-bit, not 32-bit.  For
little-endian targets we get away with it by accident, since the first
two bytes will still be correct, and the extra two bytes written (with
zeroes) will be overwritten correctly by the next store.

But for big-endian guests, this means the max_target field ends up as zero,
which means the guest will only recognize a single disk on the virtio-scsi
bus.  This patch fixes the problem.

Cc: Paolo Bonzini 
Cc: Paul 'Rusty' Russell 
Signed-off-by: David Gibson 
Signed-off-by: Paolo Bonzini 
---
 hw/virtio-scsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 924fc69b73..bfe1860505 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -534,8 +534,8 @@ static void virtio_scsi_get_config(VirtIODevice *vdev,
     stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
     stl_raw(&scsiconf->sense_size, s->sense_size);
     stl_raw(&scsiconf->cdb_size, s->cdb_size);
-    stl_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
-    stl_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
+    stw_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
+    stw_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
     stl_raw(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
 }
 

From cbdd1999daf2341b33d3ba8036fd84898e1e7c31 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Wed, 28 Nov 2012 09:40:23 +0100
Subject: [PATCH 1773/2270] build: compile translate.o with -fno-gcse option on
 GCC 4.6.x and 4.7.[012]

These versions of GCC require insane (>2GB) amounts of memory to compile
translate.o.  As a countermeasure, disable the culprit optimization pass.
This should fix the buildbot failure for default_x86_64_fedora16.  Anyway
this is a good thing to do because people will try to compile 1.3 with
less than 2GB of memory and complain.

Signed-off-by: Paolo Bonzini 
Signed-off-by: Anthony Liguori 
---
 Makefile.target |  3 +++
 configure       | 16 ++++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/Makefile.target b/Makefile.target
index 8b658c0d13..927347bac2 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -143,6 +143,9 @@ GENERATED_HEADERS += hmp-commands.h qmp-commands-old.h
 
 endif # CONFIG_SOFTMMU
 
+# Workaround for http://gcc.gnu.org/PR55489, see configure.
+%/translate.o: QEMU_CFLAGS += $(TRANSLATE_OPT_CFLAGS)
+
 nested-vars += obj-y
 
 # This resolves all nested paths, so it must come last
diff --git a/configure b/configure
index 780b19afd6..994f7310b8 100755
--- a/configure
+++ b/configure
@@ -1183,6 +1183,21 @@ for flag in $gcc_flags; do
     fi
 done
 
+# Workaround for http://gcc.gnu.org/PR55489.  Happens with -fPIE/-fPIC and
+# large functions that use global variables.  The bug is in all releases of
+# GCC, but it became particularly acute in 4.6.x and 4.7.x.  It is fixed in
+# 4.7.3 and 4.8.0.  We should be able to delete this at the end of 2013.
+cat > $TMPC << EOF
+#if __GNUC__ == 4 && (__GNUC_MINOR__ == 6 || (__GNUC_MINOR__ == 7 && __GNUC_PATCHLEVEL__ <= 2))
+int main(void) { return 0; }
+#else
+#error No bug in this compiler.
+#endif
+EOF
+if compile_prog "-Werror -fno-gcse" "" ; then
+  TRANSLATE_OPT_CFLAGS=-fno-gcse
+fi
+
 if test "$static" = "yes" ; then
   if test "$pie" = "yes" ; then
     echo "static and pie are mutually incompatible"
@@ -3662,6 +3677,7 @@ echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
 echo "EXESUF=$EXESUF" >> $config_host_mak
 echo "LIBS_QGA+=$libs_qga" >> $config_host_mak
 echo "POD2MAN=$POD2MAN" >> $config_host_mak
+echo "TRANSLATE_OPT_CFLAGS=$TRANSLATE_OPT_CFLAGS" >> $config_host_mak
 
 # generate list of library paths for linker script
 

From e9bff10f8db94912b1b0e6e2e3394cae02faf614 Mon Sep 17 00:00:00 2001
From: Jan Kiszka 
Date: Thu, 22 Nov 2012 20:56:11 +0100
Subject: [PATCH 1774/2270] event notifier: Fix setup for win32

The event notifier state is only reset by test_and_clear. But we created
the windows event object with auto-reset, which subtly swallowed events.

Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Jan Kiszka 
Signed-off-by: Anthony Liguori 
---
 event_notifier-win32.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/event_notifier-win32.c b/event_notifier-win32.c
index c723dadf31..4ed21c2a7c 100644
--- a/event_notifier-win32.c
+++ b/event_notifier-win32.c
@@ -16,7 +16,7 @@
 
 int event_notifier_init(EventNotifier *e, int active)
 {
-    e->event = CreateEvent(NULL, FALSE, FALSE, NULL);
+    e->event = CreateEvent(NULL, TRUE, FALSE, NULL);
     assert(e->event);
     return 0;
 }

From fa98efe932d93a15ffa867f3b05149c8d1fc7c28 Mon Sep 17 00:00:00 2001
From: Yonit Halperin 
Date: Wed, 28 Nov 2012 10:08:22 -0500
Subject: [PATCH 1775/2270] qxl: reload memslots after migration, when qxl is
 in UNDEFINED mode

The devram memslot stays active when qxl enters UNDEFINED mode (i.e, no
primary surface). If migration has occurred while the device is in
UNDEFINED stae, the memslots have to be reloaded at the destination.

Fixes rhbz#874574

Signed-off-by: Yonit Halperin 
Signed-off-by: Gerd Hoffmann 
---
 hw/qxl.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/qxl.c b/hw/qxl.c
index 1bc2d32aa8..96887c4aad 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -2146,6 +2146,7 @@ static int qxl_post_load(void *opaque, int version)
 
     switch (newmode) {
     case QXL_MODE_UNDEFINED:
+        qxl_create_memslots(d);
         break;
     case QXL_MODE_VGA:
         qxl_create_memslots(d);

From 6c2d1c32d084320081b0cd047f8cacd6e722d03a Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Thu, 22 Nov 2012 14:44:50 +0100
Subject: [PATCH 1776/2270] usb: tag usb host adapters as not hotpluggable.

Hotplugging them simply doesn't work, so tag them accordingly to
avoid users trying and then crashing qemu.

For xhci there is nothing fundamental which prevents hotplug from
working, we'll "only" need a exit() function which cleans up
everything properly.  That isn't for 1.3 though.

For ehci+uhci+ohci hotplug can't be supported until qemu gains the
capability to hotplug multifunction pci devices.

https://bugzilla.redhat.com/show_bug.cgi?id=879096

Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-ehci-pci.c | 1 +
 hw/usb/hcd-ohci.c     | 1 +
 hw/usb/hcd-uhci.c     | 1 +
 hw/usb/hcd-xhci.c     | 1 +
 4 files changed, 4 insertions(+)

diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c
index 5887eab197..41dbb539f2 100644
--- a/hw/usb/hcd-ehci-pci.c
+++ b/hw/usb/hcd-ehci-pci.c
@@ -123,6 +123,7 @@ static void ehci_class_init(ObjectClass *klass, void *data)
     k->revision = i->revision;
     k->class_id = PCI_CLASS_SERIAL_USB;
     k->config_write = usb_ehci_pci_write_config;
+    k->no_hotplug = 1;
     dc->vmsd = &vmstate_ehci_pci;
     dc->props = ehci_pci_properties;
 }
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 64de906e41..e16a2ecab4 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -1882,6 +1882,7 @@ static void ohci_pci_class_init(ObjectClass *klass, void *data)
     k->vendor_id = PCI_VENDOR_ID_APPLE;
     k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB;
     k->class_id = PCI_CLASS_SERIAL_USB;
+    k->no_hotplug = 1;
     dc->desc = "Apple USB Controller";
     dc->props = ohci_pci_properties;
 }
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 8e478030ad..d053791de0 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -1327,6 +1327,7 @@ static void uhci_class_init(ObjectClass *klass, void *data)
     k->device_id = info->device_id;
     k->revision  = info->revision;
     k->class_id  = PCI_CLASS_SERIAL_USB;
+    k->no_hotplug = 1;
     dc->vmsd = &vmstate_uhci;
     dc->props = uhci_properties;
     u->info = *info;
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 8ef4b0730e..efb509e423 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -3167,6 +3167,7 @@ static void xhci_class_init(ObjectClass *klass, void *data)
     k->class_id     = PCI_CLASS_SERIAL_USB;
     k->revision     = 0x03;
     k->is_express   = 1;
+    k->no_hotplug   = 1;
 }
 
 static TypeInfo xhci_info = {

From c128d6a6d785eb9235a4f6dbd52f405ab8c60bee Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi 
Date: Sun, 25 Nov 2012 16:49:15 +0100
Subject: [PATCH 1777/2270] usb: fail usbdevice_create() when there is no USB
 bus

Report an error instead of segfaulting when attaching a USB device to a
machine with no USB busses:

  $ qemu-system-arm -machine vexpress-a9 \
      -sd Fedora-17-armhfp-vexpress-mmcblk0.img \
      -kernel vmlinuz-3.4.2-3.fc17.armv7hl \
      -initrd initramfs-3.4.2-3.fc17.armv7hl.img \
      -usbdevice disk:format=raw:test.img

Note that the vexpress-a9 machine does not have a USB host controller.

Reported-by: David Abdurachmanov 
Signed-off-by: Stefan Hajnoczi 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/bus.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index 99aac7a2c0..55d0edd5c3 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -590,6 +590,13 @@ USBDevice *usbdevice_create(const char *cmdline)
         return NULL;
     }
 
+    if (!bus) {
+        error_report("Error: no usb bus to attach usbdevice %s, "
+                     "please try -machine usb=on and check that "
+                     "the machine model supports USB", driver);
+        return NULL;
+    }
+
     if (!f->usbdevice_init) {
         if (*params) {
             error_report("usbdevice %s accepts no params", driver);

From 2b29f492c844ed03d6d16ebe6bb760d71b6557fe Mon Sep 17 00:00:00 2001
From: Peter Crosthwaite 
Date: Thu, 29 Nov 2012 11:43:18 +1000
Subject: [PATCH 1778/2270] ehci-sysbus: Attach DMA context.

This was left as NULL on the initial merge due to debate on the mailing list on
how to handle DMA contexts for sysbus devices. Patch
9e11908f12f92e31ea94dc2a4c962c836cba9f2a was later merged to fix OHCI. This is the,
equivalent fix for sysbus EHCI.

Signed-off-by: Peter Crosthwaite 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-ehci-sysbus.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
index 1584079796..803df92f31 100644
--- a/hw/usb/hcd-ehci-sysbus.c
+++ b/hw/usb/hcd-ehci-sysbus.c
@@ -45,6 +45,7 @@ static int usb_ehci_sysbus_initfn(SysBusDevice *dev)
 
     s->capsbase = 0x100;
     s->opregbase = 0x140;
+    s->dma = &dma_context_memory;
 
     usb_ehci_initfn(s, DEVICE(dev));
     sysbus_init_irq(dev, &s->irq);

From 1d16252652688a775b244fffa1b9ac9b719ceffc Mon Sep 17 00:00:00 2001
From: Bruce Rogers 
Date: Tue, 27 Nov 2012 13:11:25 -0700
Subject: [PATCH 1779/2270] qapi: fix qapi_dealloc_type_size parameter type

The second parameter to qapi_dealloc_type_size should be a uint64_t *,
not a size_t *. This was causing our 32 bit x86 build to fail, since
warnings are treated as errors.

Signed-off-by: Bruce Rogers 
Reviewed-by: Michael Roth 
Reviewed-by: Stefan Weil 
Signed-off-by: Luiz Capitulino 
---
 qapi/qapi-dealloc-visitor.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c
index a07b171b86..75214e7daa 100644
--- a/qapi/qapi-dealloc-visitor.c
+++ b/qapi/qapi-dealloc-visitor.c
@@ -132,7 +132,7 @@ static void qapi_dealloc_type_number(Visitor *v, double *obj, const char *name,
 {
 }
 
-static void qapi_dealloc_type_size(Visitor *v, size_t *obj, const char *name,
+static void qapi_dealloc_type_size(Visitor *v, uint64_t *obj, const char *name,
                                    Error **errp)
 {
 }

From e912c96f7d2e5ccd8a6352ee74f5beee2a7d9976 Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Thu, 29 Nov 2012 07:46:23 -0600
Subject: [PATCH 1780/2270] qdev: relax bus type check in qdev_device_add()
 (v2)

We are currently checking for an exact type match.  Use QOM dynamic_cast to
check for a compatible type instead.

Cc: Konrad Frederic 
Cc: Peter Maydell 
Signed-off-by: Anthony Liguori 
---
v1 -> v2:
 - also add cast to qbus_find_recursive (Peter)
 - simplify by doing object_dynamic_cast instead of messing with classes
---
 hw/qdev-monitor.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c
index 479eecda31..a1b4d6ae5f 100644
--- a/hw/qdev-monitor.c
+++ b/hw/qdev-monitor.c
@@ -289,8 +289,7 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name,
     if (name && (strcmp(bus->name, name) != 0)) {
         match = 0;
     }
-    if (bus_typename &&
-        (strcmp(object_get_typename(OBJECT(bus)), bus_typename) != 0)) {
+    if (bus_typename && !object_dynamic_cast(OBJECT(bus), bus_typename)) {
         match = 0;
     }
     if (match) {
@@ -435,7 +434,7 @@ DeviceState *qdev_device_add(QemuOpts *opts)
         if (!bus) {
             return NULL;
         }
-        if (strcmp(object_get_typename(OBJECT(bus)), k->bus_type) != 0) {
+        if (!object_dynamic_cast(OBJECT(bus), k->bus_type)) {
             qerror_report(QERR_BAD_BUS_FOR_DEVICE,
                           driver, object_get_typename(OBJECT(bus)));
             return NULL;

From 044d003db9b6a588be2c9d0ec9de694ba3848551 Mon Sep 17 00:00:00 2001
From: Max Filippov 
Date: Thu, 29 Nov 2012 19:53:20 +0400
Subject: [PATCH 1781/2270] qemu-tech.texi: update implemented xtensa features
 list

Debug option is available since QEMU-1.2; FP coprocessor and
coprocessor context is available since QEMU-1.3.

Signed-off-by: Max Filippov 
Signed-off-by: Anthony Liguori 
---
 qemu-tech.texi | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/qemu-tech.texi b/qemu-tech.texi
index d73dda8e35..8aefa743a8 100644
--- a/qemu-tech.texi
+++ b/qemu-tech.texi
@@ -262,16 +262,16 @@ Current QEMU limitations:
 
 @item Core Xtensa ISA emulation, including most options: code density,
 loop, extended L32R, 16- and 32-bit multiplication, 32-bit division,
-MAC16, miscellaneous operations, boolean, multiprocessor synchronization,
+MAC16, miscellaneous operations, boolean, FP coprocessor, coprocessor
+context, debug, multiprocessor synchronization,
 conditional store, exceptions, relocatable vectors, unaligned exception,
 interrupts (including high priority and timer), hardware alignment,
 region protection, region translation, MMU, windowed registers, thread
 pointer, processor ID.
 
-@item Not implemented options: FP coprocessor, coprocessor context,
-data/instruction cache (including cache prefetch and locking), XLMI,
-processor interface, debug. Also options not covered by the core ISA
-(e.g. FLIX, wide branches) are not implemented.
+@item Not implemented options: data/instruction cache (including cache
+prefetch and locking), XLMI, processor interface. Also options not
+covered by the core ISA (e.g. FLIX, wide branches) are not implemented.
 
 @item Can run most Xtensa Linux binaries.
 

From e1f7b4812eab992de46c98b3726745afb042a7f0 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" 
Date: Fri, 30 Nov 2012 00:02:56 +0200
Subject: [PATCH 1782/2270] virtio: limit avail bytes lookahead

Commit 0d8d7690850eb0cf2b2b60933cf47669a6b6f18f introduced
a regression in virtio-net performance because it looks
into the ring aggressively while we really only care
about a single packet worth of buffers.
Reported as bugzilla 1066055 in launchpad.

To fix, add parameters limiting lookahead, and
use in virtqueue_avail_bytes.

Signed-off-by: Michael S. Tsirkin 
Reported-by: Edivaldo de Araujo Pereira 
Tested-by: Edivaldo de Araujo Pereira 
Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Anthony Liguori 
---
 hw/virtio-rng.c        | 12 +++++++++---
 hw/virtio-serial-bus.c |  2 +-
 hw/virtio.c            | 15 ++++++++-------
 hw/virtio.h            |  3 ++-
 4 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/hw/virtio-rng.c b/hw/virtio-rng.c
index df329f25e1..a73ef8e334 100644
--- a/hw/virtio-rng.c
+++ b/hw/virtio-rng.c
@@ -43,11 +43,11 @@ static bool is_guest_ready(VirtIORNG *vrng)
     return false;
 }
 
-static size_t get_request_size(VirtQueue *vq)
+static size_t get_request_size(VirtQueue *vq, unsigned quota)
 {
     unsigned int in, out;
 
-    virtqueue_get_avail_bytes(vq, &in, &out);
+    virtqueue_get_avail_bytes(vq, &in, &out, quota, 0);
     return in;
 }
 
@@ -84,12 +84,18 @@ static void chr_read(void *opaque, const void *buf, size_t size)
 static void virtio_rng_process(VirtIORNG *vrng)
 {
     size_t size;
+    unsigned quota;
 
     if (!is_guest_ready(vrng)) {
         return;
     }
 
-    size = get_request_size(vrng->vq);
+    if (vrng->quota_remaining < 0) {
+        quota = 0;
+    } else {
+        quota = MIN((uint64_t)vrng->quota_remaining, (uint64_t)UINT32_MAX);
+    }
+    size = get_request_size(vrng->vq, quota);
     size = MIN(vrng->quota_remaining, size);
     if (size) {
         rng_backend_request_entropy(vrng->rng, size, chr_read, vrng);
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index efa8a81db6..155da58dcd 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -306,7 +306,7 @@ size_t virtio_serial_guest_ready(VirtIOSerialPort *port)
     if (use_multiport(port->vser) && !port->guest_connected) {
         return 0;
     }
-    virtqueue_get_avail_bytes(vq, &bytes, NULL);
+    virtqueue_get_avail_bytes(vq, &bytes, NULL, 4096, 0);
     return bytes;
 }
 
diff --git a/hw/virtio.c b/hw/virtio.c
index ec8b7d8463..f40a8c5571 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -336,7 +336,8 @@ static unsigned virtqueue_next_desc(hwaddr desc_pa,
 }
 
 void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
-                               unsigned int *out_bytes)
+                               unsigned int *out_bytes,
+                               unsigned max_in_bytes, unsigned max_out_bytes)
 {
     unsigned int idx;
     unsigned int total_bufs, in_total, out_total;
@@ -385,6 +386,9 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
             } else {
                 out_total += vring_desc_len(desc_pa, i);
             }
+            if (in_total >= max_in_bytes && out_total >= max_out_bytes) {
+                goto done;
+            }
         } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max);
 
         if (!indirect)
@@ -392,6 +396,7 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
         else
             total_bufs++;
     }
+done:
     if (in_bytes) {
         *in_bytes = in_total;
     }
@@ -405,12 +410,8 @@ int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes,
 {
     unsigned int in_total, out_total;
 
-    virtqueue_get_avail_bytes(vq, &in_total, &out_total);
-    if ((in_bytes && in_bytes < in_total)
-        || (out_bytes && out_bytes < out_total)) {
-        return 1;
-    }
-    return 0;
+    virtqueue_get_avail_bytes(vq, &in_total, &out_total, in_bytes, out_bytes);
+    return in_bytes <= in_total && out_bytes <= out_total;
 }
 
 void virtqueue_map_sg(struct iovec *sg, hwaddr *addr,
diff --git a/hw/virtio.h b/hw/virtio.h
index df8d0f7b69..7c17f7ba0b 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -150,7 +150,8 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem);
 int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes,
                           unsigned int out_bytes);
 void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
-                               unsigned int *out_bytes);
+                               unsigned int *out_bytes,
+                               unsigned max_in_bytes, unsigned max_out_bytes);
 
 void virtio_notify(VirtIODevice *vdev, VirtQueue *vq);
 

From a13e5e05570e6c0d0a6c8d9b5c516278770adae5 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Wed, 21 Nov 2012 12:26:56 +0100
Subject: [PATCH 1783/2270] Documentation: Update block cache mode information

Somehow we forgot to update this when cache=writeback became the
default. While changing the information on the default, also make the
description of all caches modes a bit more accurate.

Signed-off-by: Kevin Wolf 
Acked-by: Stefan Hajnoczi 
---
 qemu-options.hx | 38 +++++++++++++++++++-------------------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index fbcf079f47..de43b1b48b 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -206,33 +206,33 @@ Open drive @option{file} as read-only. Guest write attempts will fail.
 file sectors into the image file.
 @end table
 
-By default, writethrough caching is used for all block device.  This means that
-the host page cache will be used to read and write data but write notification
-will be sent to the guest only when the data has been reported as written by
-the storage subsystem.
+By default, the @option{cache=writeback} mode is used. It will report data
+writes as completed as soon as the data is present in the host page cache.
+This is safe as long as your guest OS makes sure to correctly flush disk caches
+where needed. If your guest OS does not handle volatile disk write caches
+correctly and your host crashes or loses power, then the guest may experience
+data corruption.
 
-Writeback caching will report data writes as completed as soon as the data is
-present in the host page cache.  This is safe as long as you trust your host.
-If your host crashes or loses power, then the guest may experience data
-corruption.
+For such guests, you should consider using @option{cache=writethrough}. This
+means that the host page cache will be used to read and write data, but write
+notification will be sent to the guest only after QEMU has made sure to flush
+each write to the disk. Be aware that this has a major impact on performance.
 
 The host page cache can be avoided entirely with @option{cache=none}.  This will
-attempt to do disk IO directly to the guests memory.  QEMU may still perform
-an internal copy of the data.
+attempt to do disk IO directly to the guest's memory.  QEMU may still perform
+an internal copy of the data. Note that this is considered a writeback mode and
+the guest OS must handle the disk write cache correctly in order to avoid data
+corruption on host crashes.
 
 The host page cache can be avoided while only sending write notifications to
-the guest when the data has been reported as written by the storage subsystem
-using @option{cache=directsync}.
-
-Some block drivers perform badly with @option{cache=writethrough}, most notably,
-qcow2.  If performance is more important than correctness,
-@option{cache=writeback} should be used with qcow2.
+the guest when the data has been flushed to the disk using
+@option{cache=directsync}.
 
 In case you don't care about data integrity over host failures, use
-cache=unsafe. This option tells QEMU that it never needs to write any data
-to the disk but can instead keeps things in cache. If anything goes wrong,
+@option{cache=unsafe}. This option tells QEMU that it never needs to write any
+data to the disk but can instead keep things in cache. If anything goes wrong,
 like your host losing power, the disk storage getting disconnected accidentally,
-etc. you're image will most probably be rendered unusable.   When using
+etc. your image will most probably be rendered unusable.   When using
 the @option{-snapshot} option, unsafe caching is always used.
 
 Copy-on-read avoids accessing the same backing file sectors repeatedly and is

From d3067b020bdeb572f381c5be4420eedfd6af5884 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Wed, 21 Nov 2012 14:21:47 +0100
Subject: [PATCH 1784/2270] Documentation: Update image format information

Document new and yet undocumented options and image formats. The
qemu-img man page contains information only for raw and qcow2 now and
references the HTML documentation for a more detailed description of
other formats.

Signed-off-by: Kevin Wolf 
Acked-by: Stefan Hajnoczi 
---
 qemu-doc.texi | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-img.texi |  88 +++++++++-----------------
 2 files changed, 196 insertions(+), 59 deletions(-)

diff --git a/qemu-doc.texi b/qemu-doc.texi
index 6ff309ddf4..6d7f50d832 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -416,6 +416,7 @@ snapshots.
 * vm_snapshots::              VM snapshots
 * qemu_img_invocation::       qemu-img Invocation
 * qemu_nbd_invocation::       qemu-nbd Invocation
+* disk_images_formats::       Disk image file formats
 * host_drives::               Using host drives
 * disk_images_fat_images::    Virtual FAT disk images
 * disk_images_nbd::           NBD access
@@ -507,6 +508,172 @@ state is not saved or restored properly (in particular USB).
 
 @include qemu-nbd.texi
 
+@node disk_images_formats
+@subsection Disk image file formats
+
+QEMU supports many image file formats that can be used with VMs as well as with
+any of the tools (like @code{qemu-img}). This includes the preferred formats
+raw and qcow2 as well as formats that are supported for compatibility with
+older QEMU versions or other hypervisors.
+
+Depending on the image format, different options can be passed to
+@code{qemu-img create} and @code{qemu-img convert} using the @code{-o} option.
+This section describes each format and the options that are supported for it.
+
+@table @option
+@item raw
+
+Raw disk image format. This format has the advantage of
+being simple and easily exportable to all other emulators. If your
+file system supports @emph{holes} (for example in ext2 or ext3 on
+Linux or NTFS on Windows), then only the written sectors will reserve
+space. Use @code{qemu-img info} to know the real size used by the
+image or @code{ls -ls} on Unix/Linux.
+
+@item qcow2
+QEMU image format, the most versatile format. Use it to have smaller
+images (useful if your filesystem does not supports holes, for example
+on Windows), optional AES encryption, zlib based compression and
+support of multiple VM snapshots.
+
+Supported options:
+@table @code
+@item compat
+Determines the qcow2 version to use. @code{compat=0.10} uses the traditional
+image format that can be read by any QEMU since 0.10 (this is the default).
+@code{compat=1.1} enables image format extensions that only QEMU 1.1 and
+newer understand. Amongst others, this includes zero clusters, which allow
+efficient copy-on-read for sparse images.
+
+@item backing_file
+File name of a base image (see @option{create} subcommand)
+@item backing_fmt
+Image format of the base image
+@item encryption
+If this option is set to @code{on}, the image is encrypted.
+
+Encryption uses the AES format which is very secure (128 bit keys). Use
+a long password (16 characters) to get maximum protection.
+
+@item cluster_size
+Changes the qcow2 cluster size (must be between 512 and 2M). Smaller cluster
+sizes can improve the image file size whereas larger cluster sizes generally
+provide better performance.
+
+@item preallocation
+Preallocation mode (allowed values: off, metadata). An image with preallocated
+metadata is initially larger but can improve performance when the image needs
+to grow.
+
+@item lazy_refcounts
+If this option is set to @code{on}, reference count updates are postponed with
+the goal of avoiding metadata I/O and improving performance. This is
+particularly interesting with @option{cache=writethrough} which doesn't batch
+metadata updates. The tradeoff is that after a host crash, the reference count
+tables must be rebuilt, i.e. on the next open an (automatic) @code{qemu-img
+check -r all} is required, which may take some time.
+
+This option can only be enabled if @code{compat=1.1} is specified.
+
+@end table
+
+@item qed
+Old QEMU image format with support for backing files and compact image files
+(when your filesystem or transport medium does not support holes).
+
+When converting QED images to qcow2, you might want to consider using the
+@code{lazy_refcounts=on} option to get a more QED-like behaviour.
+
+Supported options:
+@table @code
+@item backing_file
+File name of a base image (see @option{create} subcommand).
+@item backing_fmt
+Image file format of backing file (optional).  Useful if the format cannot be
+autodetected because it has no header, like some vhd/vpc files.
+@item cluster_size
+Changes the cluster size (must be power-of-2 between 4K and 64K). Smaller
+cluster sizes can improve the image file size whereas larger cluster sizes
+generally provide better performance.
+@item table_size
+Changes the number of clusters per L1/L2 table (must be power-of-2 between 1
+and 16).  There is normally no need to change this value but this option can be
+used for performance benchmarking.
+@end table
+
+@item qcow
+Old QEMU image format with support for backing files, compact image files,
+encryption and compression.
+
+Supported options:
+@table @code
+@item backing_file
+File name of a base image (see @option{create} subcommand)
+@item encryption
+If this option is set to @code{on}, the image is encrypted.
+@end table
+
+@item cow
+User Mode Linux Copy On Write image format. It is supported only for
+compatibility with previous versions.
+Supported options:
+@table @code
+@item backing_file
+File name of a base image (see @option{create} subcommand)
+@end table
+
+@item vdi
+VirtualBox 1.1 compatible image format.
+Supported options:
+@table @code
+@item static
+If this option is set to @code{on}, the image is created with metadata
+preallocation.
+@end table
+
+@item vmdk
+VMware 3 and 4 compatible image format.
+
+Supported options:
+@table @code
+@item backing_file
+File name of a base image (see @option{create} subcommand).
+@item compat6
+Create a VMDK version 6 image (instead of version 4)
+@item subformat
+Specifies which VMDK subformat to use. Valid options are
+@code{monolithicSparse} (default),
+@code{monolithicFlat},
+@code{twoGbMaxExtentSparse},
+@code{twoGbMaxExtentFlat} and
+@code{streamOptimized}.
+@end table
+
+@item vpc
+VirtualPC compatible image format (VHD).
+Supported options:
+@table @code
+@item subformat
+Specifies which VHD subformat to use. Valid options are
+@code{dynamic} (default) and @code{fixed}.
+@end table
+@end table
+
+@subsubsection Read-only formats
+More disk image file formats are supported in a read-only mode.
+@table @option
+@item bochs
+Bochs images of @code{growing} type.
+@item cloop
+Linux Compressed Loop image, useful only to reuse directly compressed
+CD-ROM images present for example in the Knoppix CD-ROMs.
+@item dmg
+Apple disk image.
+@item parallels
+Parallels disk image format.
+@end table
+
+
 @node host_drives
 @subsection Using host drives
 
diff --git a/qemu-img.texi b/qemu-img.texi
index 60b83fc11a..00fca8da86 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -226,7 +226,10 @@ After using this command to grow a disk image, you must use file system and
 partitioning tools inside the VM to actually begin using the new space on the
 device.
 @end table
+@c man end
 
+@ignore
+@c man begin NOTES
 Supported image file formats:
 
 @table @option
@@ -247,6 +250,13 @@ support of multiple VM snapshots.
 
 Supported options:
 @table @code
+@item compat
+Determines the qcow2 version to use. @code{compat=0.10} uses the traditional
+image format that can be read by any QEMU since 0.10 (this is the default).
+@code{compat=1.1} enables image format extensions that only QEMU 1.1 and
+newer understand. Amongst others, this includes zero clusters, which allow
+efficient copy-on-read for sparse images.
+
 @item backing_file
 File name of a base image (see @option{create} subcommand)
 @item backing_fmt
@@ -267,73 +277,33 @@ Preallocation mode (allowed values: off, metadata). An image with preallocated
 metadata is initially larger but can improve performance when the image needs
 to grow.
 
+@item lazy_refcounts
+If this option is set to @code{on}, reference count updates are postponed with
+the goal of avoiding metadata I/O and improving performance. This is
+particularly interesting with @option{cache=writethrough} which doesn't batch
+metadata updates. The tradeoff is that after a host crash, the reference count
+tables must be rebuilt, i.e. on the next open an (automatic) @code{qemu-img
+check -r all} is required, which may take some time.
+
+This option can only be enabled if @code{compat=1.1} is specified.
+
 @end table
 
-@item qed
-Image format with support for backing files and compact image files (when your
-filesystem or transport medium does not support holes).  Good performance due
-to less metadata than the more featureful qcow2 format, especially with
-cache=writethrough or cache=directsync.  Consider using qcow2 which will soon
-have a similar optimization and is most actively developed.
+@item Other
+QEMU also supports various other image file formats for compatibility with
+older QEMU versions or other hypervisors, including VMDK, VDI, VHD (vpc), qcow1
+and QED. For a full list of supported formats see @code{qemu-img --help}.
+For a more detailed description of these formats, see the QEMU Emulation User
+Documentation.
 
-Supported options:
-@table @code
-@item backing_file
-File name of a base image (see @option{create} subcommand).
-@item backing_fmt
-Image file format of backing file (optional).  Useful if the format cannot be
-autodetected because it has no header, like some vhd/vpc files.
-@item cluster_size
-Changes the cluster size (must be power-of-2 between 4K and 64K). Smaller
-cluster sizes can improve the image file size whereas larger cluster sizes
-generally provide better performance.
-@item table_size
-Changes the number of clusters per L1/L2 table (must be power-of-2 between 1
-and 16).  There is normally no need to change this value but this option can be
-used for performance benchmarking.
-@end table
-
-@item qcow
-Old QEMU image format. Left for compatibility.
-
-Supported options:
-@table @code
-@item backing_file
-File name of a base image (see @option{create} subcommand)
-@item encryption
-If this option is set to @code{on}, the image is encrypted.
-@end table
-
-@item cow
-User Mode Linux Copy On Write image format. Used to be the only growable
-image format in QEMU. It is supported only for compatibility with
-previous versions. It does not work on win32.
-@item vdi
-VirtualBox 1.1 compatible image format.
-@item vmdk
-VMware 3 and 4 compatible image format.
-
-Supported options:
-@table @code
-@item backing_fmt
-Image format of the base image
-@item compat6
-Create a VMDK version 6 image (instead of version 4)
-@end table
-
-@item vpc
-VirtualPC compatible image format (VHD).
-
-@item cloop
-Linux Compressed Loop image, useful only to reuse directly compressed
-CD-ROM images present for example in the Knoppix CD-ROMs.
+The main purpose of the block drivers for these formats is image conversion.
+For running VMs, it is recommended to convert the disk images to either raw or
+qcow2 in order to achieve good performance.
 @end table
 
 
 @c man end
 
-@ignore
-
 @setfilename qemu-img
 @settitle QEMU disk image utility
 

From 0c6f08b0b0d0c758789cdb7257a48e873598bdbb Mon Sep 17 00:00:00 2001
From: Pavel Hrdina 
Date: Mon, 26 Nov 2012 16:37:39 +0100
Subject: [PATCH 1785/2270] atapi: make change media detection for guests
 easier

If you have a guest with a media in the optical drive and you change
it, the windows guest cannot properly recognize this media change.

Windows needs to detect sense "NOT_READY with ASC_MEDIUM_NOT_PRESENT"
before we send sense "UNIT_ATTENTION with ASC_MEDIUM_MAY_HAVE_CHANGED".

Signed-off-by: Pavel Hrdina 
Signed-off-by: Kevin Wolf 
---
 hw/ide/atapi.c | 15 ++++++++++-----
 hw/ide/core.c  |  6 ------
 2 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index 685cbaa889..861fd2bec3 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -1124,12 +1124,17 @@ void ide_atapi_cmd(IDEState *s)
      * GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close
      * states rely on this behavior.
      */
-    if (!s->tray_open && bdrv_is_inserted(s->bs) && s->cdrom_changed) {
-        ide_atapi_cmd_error(s, NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+    if (!(atapi_cmd_table[s->io_buffer[0]].flags & ALLOW_UA) &&
+        !s->tray_open && bdrv_is_inserted(s->bs) && s->cdrom_changed) {
+
+        if (s->cdrom_changed == 1) {
+            ide_atapi_cmd_error(s, NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+            s->cdrom_changed = 2;
+        } else {
+            ide_atapi_cmd_error(s, UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED);
+            s->cdrom_changed = 0;
+        }
 
-        s->cdrom_changed = 0;
-        s->sense_key = UNIT_ATTENTION;
-        s->asc = ASC_MEDIUM_MAY_HAVE_CHANGED;
         return;
     }
 
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 8da894f240..c4f93d0e47 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2160,12 +2160,6 @@ static int ide_drive_post_load(void *opaque, int version_id)
 {
     IDEState *s = opaque;
 
-    if (version_id < 3) {
-        if (s->sense_key == UNIT_ATTENTION &&
-            s->asc == ASC_MEDIUM_MAY_HAVE_CHANGED) {
-            s->cdrom_changed = 1;
-        }
-    }
     if (s->identify_set) {
         bdrv_set_enable_write_cache(s->bs, !!(s->identify_data[85] & (1 << 5)));
     }

From e3980e28bb888bf643054770452998d1b4319609 Mon Sep 17 00:00:00 2001
From: Dietmar Maurer 
Date: Wed, 24 Oct 2012 12:10:47 +0200
Subject: [PATCH 1786/2270] stream: fix ratelimit_set_speed

The formula to compute slice_quota was wrong since commit 6ef228fc.

Signed-off-by: Dietmar Maurer 
Reviewed-by: Eric Blake 
Signed-off-by: Kevin Wolf 
---
 include/qemu/ratelimit.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/qemu/ratelimit.h b/include/qemu/ratelimit.h
index c6ac281141..d1610f135b 100644
--- a/include/qemu/ratelimit.h
+++ b/include/qemu/ratelimit.h
@@ -42,7 +42,7 @@ static inline void ratelimit_set_speed(RateLimit *limit, uint64_t speed,
                                        uint64_t slice_ns)
 {
     limit->slice_ns = slice_ns;
-    limit->slice_quota = ((double)speed * 1000000000ULL) / slice_ns;
+    limit->slice_quota = ((double)speed * slice_ns)/1000000000ULL;
 }
 
 #endif

From 2ad2210a7d2483c4c98423ebd59fad87c6124096 Mon Sep 17 00:00:00 2001
From: Peter Maydell 
Date: Sat, 10 Nov 2012 21:47:52 +0000
Subject: [PATCH 1787/2270] coroutine-sigaltstack.c: Use stack_t, not struct
 sigaltstack

Use the POSIX-specified stack_t type as the argument to sigaltstack()
rather than the legacy struct sigaltstack. This allows us to compile
on MacOSX with --with-coroutine=sigaltstack.

Signed-off-by: Peter Maydell 
Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Kevin Wolf 
---
 coroutine-sigaltstack.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/coroutine-sigaltstack.c b/coroutine-sigaltstack.c
index 861e87805a..39dbaa5da1 100644
--- a/coroutine-sigaltstack.c
+++ b/coroutine-sigaltstack.c
@@ -171,8 +171,8 @@ static Coroutine *coroutine_new(void)
     CoroutineThreadState *coTS;
     struct sigaction sa;
     struct sigaction osa;
-    struct sigaltstack ss;
-    struct sigaltstack oss;
+    stack_t ss;
+    stack_t oss;
     sigset_t sigs;
     sigset_t osigs;
     jmp_buf old_env;

From fe512d65e0b752dfa7af6cfb374a0820d35040d0 Mon Sep 17 00:00:00 2001
From: Eduardo Otubo 
Date: Thu, 29 Nov 2012 13:56:41 -0200
Subject: [PATCH 1788/2270] seccomp: adding new syscalls (bugzilla 855162)

According to the bug 855162[0] - there's the need of adding new syscalls
to the whitelist when using Qemu with Libvirt.

[0] - https://bugzilla.redhat.com/show_bug.cgi?id=855162

Reported-by: Paul Moore 
Tested-by: Paul Moore 
Signed-off-by: Eduardo Otubo 
Signed-off-by: Corey Bryant 
Signed-off-by: Anthony Liguori 
---
 qemu-seccomp.c | 156 +++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 139 insertions(+), 17 deletions(-)

diff --git a/qemu-seccomp.c b/qemu-seccomp.c
index 64329a3c09..2a71d6fee9 100644
--- a/qemu-seccomp.c
+++ b/qemu-seccomp.c
@@ -26,8 +26,12 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
     { SCMP_SYS(timer_gettime), 254 },
     { SCMP_SYS(futex), 253 },
     { SCMP_SYS(select), 252 },
+#if defined(__x86_64__)
     { SCMP_SYS(recvfrom), 251 },
     { SCMP_SYS(sendto), 250 },
+#elif defined(__i386__)
+    { SCMP_SYS(socketcall), 250 },
+#endif
     { SCMP_SYS(read), 249 },
     { SCMP_SYS(brk), 248 },
     { SCMP_SYS(clone), 247 },
@@ -36,15 +40,30 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
     { SCMP_SYS(execve), 245 },
     { SCMP_SYS(open), 245 },
     { SCMP_SYS(ioctl), 245 },
+#if defined(__x86_64__)
+    { SCMP_SYS(socket), 245 },
+    { SCMP_SYS(setsockopt), 245 },
     { SCMP_SYS(recvmsg), 245 },
     { SCMP_SYS(sendmsg), 245 },
     { SCMP_SYS(accept), 245 },
     { SCMP_SYS(connect), 245 },
+    { SCMP_SYS(socketpair), 245 },
+    { SCMP_SYS(bind), 245 },
+    { SCMP_SYS(listen), 245 },
+    { SCMP_SYS(semget), 245 },
+#elif defined(__i386__)
+    { SCMP_SYS(ipc), 245 },
+#endif
     { SCMP_SYS(gettimeofday), 245 },
     { SCMP_SYS(readlink), 245 },
     { SCMP_SYS(access), 245 },
     { SCMP_SYS(prctl), 245 },
     { SCMP_SYS(signalfd), 245 },
+    { SCMP_SYS(getrlimit), 245 },
+    { SCMP_SYS(set_tid_address), 245 },
+    { SCMP_SYS(statfs), 245 },
+    { SCMP_SYS(unlink), 245 },
+    { SCMP_SYS(wait4), 245 },
 #if defined(__i386__)
     { SCMP_SYS(fcntl64), 245 },
     { SCMP_SYS(fstat64), 245 },
@@ -56,30 +75,33 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
     { SCMP_SYS(sigreturn), 245 },
     { SCMP_SYS(_newselect), 245 },
     { SCMP_SYS(_llseek), 245 },
-    { SCMP_SYS(mmap2), 245},
+    { SCMP_SYS(mmap2), 245 },
     { SCMP_SYS(sigprocmask), 245 },
-#elif defined(__x86_64__)
-    { SCMP_SYS(sched_getparam), 245},
-    { SCMP_SYS(sched_getscheduler), 245},
-    { SCMP_SYS(fstat), 245},
-    { SCMP_SYS(clock_getres), 245},
-    { SCMP_SYS(sched_get_priority_min), 245},
-    { SCMP_SYS(sched_get_priority_max), 245},
-    { SCMP_SYS(stat), 245},
-    { SCMP_SYS(socket), 245},
-    { SCMP_SYS(setsockopt), 245},
-    { SCMP_SYS(uname), 245},
-    { SCMP_SYS(semget), 245},
 #endif
+    { SCMP_SYS(sched_getparam), 245 },
+    { SCMP_SYS(sched_getscheduler), 245 },
+    { SCMP_SYS(fstat), 245 },
+    { SCMP_SYS(clock_getres), 245 },
+    { SCMP_SYS(sched_get_priority_min), 245 },
+    { SCMP_SYS(sched_get_priority_max), 245 },
+    { SCMP_SYS(stat), 245 },
+    { SCMP_SYS(uname), 245 },
     { SCMP_SYS(eventfd2), 245 },
     { SCMP_SYS(dup), 245 },
+    { SCMP_SYS(dup2), 245 },
+    { SCMP_SYS(dup3), 245 },
     { SCMP_SYS(gettid), 245 },
+    { SCMP_SYS(getgid), 245 },
+    { SCMP_SYS(getegid), 245 },
+    { SCMP_SYS(getuid), 245 },
+    { SCMP_SYS(geteuid), 245 },
     { SCMP_SYS(timer_create), 245 },
     { SCMP_SYS(exit), 245 },
     { SCMP_SYS(clock_gettime), 245 },
     { SCMP_SYS(time), 245 },
     { SCMP_SYS(restart_syscall), 245 },
     { SCMP_SYS(pwrite64), 245 },
+    { SCMP_SYS(nanosleep), 245 },
     { SCMP_SYS(chown), 245 },
     { SCMP_SYS(openat), 245 },
     { SCMP_SYS(getdents), 245 },
@@ -93,8 +115,6 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
     { SCMP_SYS(lseek), 245 },
     { SCMP_SYS(pselect6), 245 },
     { SCMP_SYS(fork), 245 },
-    { SCMP_SYS(bind), 245 },
-    { SCMP_SYS(listen), 245 },
     { SCMP_SYS(eventfd), 245 },
     { SCMP_SYS(rt_sigprocmask), 245 },
     { SCMP_SYS(write), 244 },
@@ -104,10 +124,112 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
     { SCMP_SYS(pipe2), 242 },
     { SCMP_SYS(munmap), 242 },
     { SCMP_SYS(mremap), 242 },
+    { SCMP_SYS(fdatasync), 242 },
+    { SCMP_SYS(close), 242 },
+    { SCMP_SYS(rt_sigpending), 242 },
+    { SCMP_SYS(rt_sigtimedwait), 242 },
+    { SCMP_SYS(readv), 242 },
+    { SCMP_SYS(writev), 242 },
+    { SCMP_SYS(preadv), 242 },
+    { SCMP_SYS(pwritev), 242 },
+    { SCMP_SYS(setrlimit), 242 },
+    { SCMP_SYS(ftruncate), 242 },
+    { SCMP_SYS(lstat), 242 },
+    { SCMP_SYS(pipe), 242 },
+    { SCMP_SYS(umask), 242 },
+    { SCMP_SYS(chdir), 242 },
+    { SCMP_SYS(setitimer), 242 },
+    { SCMP_SYS(setsid), 242 },
+    { SCMP_SYS(poll), 242 },
+    { SCMP_SYS(epoll_create), 242 },
+    { SCMP_SYS(epoll_ctl), 242 },
+    { SCMP_SYS(epoll_wait), 242 },
+#if defined(__i386__)
+    { SCMP_SYS(waitpid), 242 },
+#elif defined(__x86_64__)
     { SCMP_SYS(getsockname), 242 },
     { SCMP_SYS(getpeername), 242 },
-    { SCMP_SYS(fdatasync), 242 },
-    { SCMP_SYS(close), 242 }
+    { SCMP_SYS(accept4), 242 },
+    { SCMP_SYS(newfstatat), 241 },
+    { SCMP_SYS(shutdown), 241 },
+    { SCMP_SYS(getsockopt), 241 },
+    { SCMP_SYS(semctl), 241 },
+    { SCMP_SYS(semop), 241 },
+    { SCMP_SYS(semtimedop), 241 },
+    { SCMP_SYS(epoll_ctl_old), 241 },
+    { SCMP_SYS(epoll_wait_old), 241 },
+#endif
+    { SCMP_SYS(epoll_pwait), 241 },
+    { SCMP_SYS(epoll_create1), 241 },
+    { SCMP_SYS(ppoll), 241 },
+    { SCMP_SYS(creat), 241 },
+    { SCMP_SYS(link), 241 },
+    { SCMP_SYS(getpid), 241 },
+    { SCMP_SYS(getppid), 241 },
+    { SCMP_SYS(getpgrp), 241 },
+    { SCMP_SYS(getpgid), 241 },
+    { SCMP_SYS(getsid), 241 },
+    { SCMP_SYS(getdents64), 241 },
+    { SCMP_SYS(getresuid), 241 },
+    { SCMP_SYS(getresgid), 241 },
+    { SCMP_SYS(getgroups), 241 },
+#if defined(__i386__)
+    { SCMP_SYS(getresuid32), 241 },
+    { SCMP_SYS(getresgid32), 241 },
+    { SCMP_SYS(getgroups32), 241 },
+    { SCMP_SYS(signal), 241 },
+    { SCMP_SYS(sigaction), 241 },
+    { SCMP_SYS(sigsuspend), 241 },
+    { SCMP_SYS(sigpending), 241 },
+    { SCMP_SYS(truncate64), 241 },
+    { SCMP_SYS(ftruncate64), 241 },
+    { SCMP_SYS(fchown32), 241 },
+    { SCMP_SYS(chown32), 241 },
+    { SCMP_SYS(lchown32), 241 },
+    { SCMP_SYS(statfs64), 241 },
+    { SCMP_SYS(fstatfs64), 241 },
+    { SCMP_SYS(fstatat64), 241 },
+    { SCMP_SYS(lstat64), 241 },
+    { SCMP_SYS(sendfile64), 241 },
+    { SCMP_SYS(ugetrlimit), 241 },
+#endif
+    { SCMP_SYS(alarm), 241 },
+    { SCMP_SYS(rt_sigsuspend), 241 },
+    { SCMP_SYS(rt_sigqueueinfo), 241 },
+    { SCMP_SYS(rt_tgsigqueueinfo), 241 },
+    { SCMP_SYS(sigaltstack), 241 },
+    { SCMP_SYS(signalfd4), 241 },
+    { SCMP_SYS(truncate), 241 },
+    { SCMP_SYS(fchown), 241 },
+    { SCMP_SYS(lchown), 241 },
+    { SCMP_SYS(fchownat), 241 },
+    { SCMP_SYS(fstatfs), 241 },
+    { SCMP_SYS(sendfile), 241 },
+    { SCMP_SYS(getitimer), 241 },
+    { SCMP_SYS(syncfs), 241 },
+    { SCMP_SYS(fsync), 241 },
+    { SCMP_SYS(fchdir), 241 },
+    { SCMP_SYS(flock), 241 },
+    { SCMP_SYS(msync), 241 },
+    { SCMP_SYS(sched_setparam), 241 },
+    { SCMP_SYS(sched_setscheduler), 241 },
+    { SCMP_SYS(sched_yield), 241 },
+    { SCMP_SYS(sched_rr_get_interval), 241 },
+    { SCMP_SYS(sched_setaffinity), 241 },
+    { SCMP_SYS(sched_getaffinity), 241 },
+    { SCMP_SYS(readahead), 241 },
+    { SCMP_SYS(timer_getoverrun), 241 },
+    { SCMP_SYS(unlinkat), 241 },
+    { SCMP_SYS(readlinkat), 241 },
+    { SCMP_SYS(faccessat), 241 },
+    { SCMP_SYS(get_robust_list), 241 },
+    { SCMP_SYS(splice), 241 },
+    { SCMP_SYS(vmsplice), 241 },
+    { SCMP_SYS(getcpu), 241 },
+    { SCMP_SYS(sendmmsg), 241 },
+    { SCMP_SYS(recvmmsg), 241 },
+    { SCMP_SYS(prlimit64), 241 },
+    { SCMP_SYS(waitid), 241 }
 };
 
 int seccomp_start(void)

From c6e052f0809b56a657b2afcd728e07ffddb28f06 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Thu, 29 Nov 2012 18:11:50 +0100
Subject: [PATCH 1789/2270] multiboot: fix e801 memory map

The e801 memory sizes in the multiboot structures hard-code the available
low memory to 640.  However, the value should not include the size of the
EBDA.  Fill the value in the option ROM, getting the size of low memory
from the BIOS.

Cc: Alexander Graf 
Signed-off-by: Paolo Bonzini 
Signed-off-by: Paolo Bonzini 
Signed-off-by: Anthony Liguori 
---
 pc-bios/multiboot.bin         | Bin 1024 -> 1024 bytes
 pc-bios/optionrom/multiboot.S |   7 +++++++
 2 files changed, 7 insertions(+)

diff --git a/pc-bios/multiboot.bin b/pc-bios/multiboot.bin
index f74a6e142fddc054d7f40ab346a108532afac40f..7b3c1745a430ea5e0e15b9aa817d1cbbaa40db14 100644
GIT binary patch
delta 81
zcmZqRXyBNj#q7o8KT+38L4+xd@o;KdryK*rZVrajPB|8aZaEhwAcKt|ty|7*VtW(k
kS)sHUDQSyY7$$Qv{%2ueV91@!$z;eVv)P(y2P2~%0BkrF9smFU

delta 72
zcmZqRXyBNj#capqJWgJByEE-zoLs=f!*~_|qXQE}

diff --git a/pc-bios/optionrom/multiboot.S b/pc-bios/optionrom/multiboot.S
index f08222a3c6..003bcfb49f 100644
--- a/pc-bios/optionrom/multiboot.S
+++ b/pc-bios/optionrom/multiboot.S
@@ -75,6 +75,13 @@ run_multiboot:
 	shr		$4, %eax
 	mov		%ax, %fs
 
+	/* Account for the EBDA in the multiboot structure's e801
+	 * map.
+	 */
+	int		$0x12
+	cwtl
+	movl		%eax, %fs:4
+
 	/* ES = mmap_addr */
 	mov 		%fs:48, %eax
 	shr		$4, %eax

From 1f32989d7349c31419d01a0b874f5eb3a238d913 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Fri, 30 Nov 2012 16:02:58 +0100
Subject: [PATCH 1790/2270] seabios: update to
 b1c35f2b28cc0c94ebed8176ff61ac0e0b377798

This patch updates the seabios submodule to commit
b1c35f2b28cc0c94ebed8176ff61ac0e0b377798.

Most important change is that seabios sets the busmaster bit
in the pci config space for the lsi and esp scsi host adapters.
Since commit 1c380f9460522f32c8dd2577b2a53d518ec91c6d qemu
is strict here and disallows any dma access when the bit is
clear.

Signed-off-by: Gerd Hoffmann 
---
 roms/seabios | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/roms/seabios b/roms/seabios
index 5a02306538..b1c35f2b28 160000
--- a/roms/seabios
+++ b/roms/seabios
@@ -1 +1 @@
-Subproject commit 5a023065388287e261ae9212452ff541f9fa9cd3
+Subproject commit b1c35f2b28cc0c94ebed8176ff61ac0e0b377798

From d76aa45bf1f226d2c4e28f6dacbdbbefd51a37ca Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Fri, 30 Nov 2012 09:04:08 -0600
Subject: [PATCH 1791/2270] Revert "audio/audio_pt_int: Clarify licensing"

This reverts commit 72bc6f1bf710e205f175af9b1fc8bbd83e8da71f.

This patch wasn't submitted to the list and did not get Acked by other
copyright holders in the file.

Signed-off-by: Anthony Liguori 
---
 audio/audio_pt_int.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/audio/audio_pt_int.c b/audio/audio_pt_int.c
index e3ccb11944..9a9c306a9c 100644
--- a/audio/audio_pt_int.c
+++ b/audio/audio_pt_int.c
@@ -1,4 +1,3 @@
-/* public domain */
 #include "qemu-common.h"
 #include "audio.h"
 

From 46ee77b357dde619db30d835f73a9001b9c75a03 Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Fri, 30 Nov 2012 09:04:47 -0600
Subject: [PATCH 1792/2270] Revert "audio/wavcapture: Clarify licensing"

This reverts commit 456a84d156a7c42f18b1da176dd6219e2dffd043.

This patch wasn't submitted to the list and did not get Acked by other
copyright holders in the file.

Signed-off-by: Anthony Liguori 
---
 audio/wavcapture.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/audio/wavcapture.c b/audio/wavcapture.c
index f73691cc9b..4f785f5f49 100644
--- a/audio/wavcapture.c
+++ b/audio/wavcapture.c
@@ -1,4 +1,3 @@
-/* public domain */
 #include "hw/hw.h"
 #include "monitor.h"
 #include "audio.h"

From 7527bd85be991d91584329fcbb44af322758719e Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Fri, 30 Nov 2012 16:24:40 +0100
Subject: [PATCH 1793/2270] roms: also copy the dsdt when updating seabios.

Signed-off-by: Gerd Hoffmann 
---
 roms/Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/roms/Makefile b/roms/Makefile
index feb9c2b145..5e645bc7d1 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -12,6 +12,7 @@ bios: config.seabios
 	sh configure-seabios.sh $<
 	make -C seabios out/bios.bin
 	cp seabios/out/bios.bin ../pc-bios/bios.bin
+	cp seabios/out/*dsdt.aml ../pc-bios/
 
 seavgabios: $(patsubst %,seavgabios-%,$(vgabios_variants))
 

From d7a51dbbaa70677846453f8c961590913052dd86 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Fri, 30 Nov 2012 16:24:59 +0100
Subject: [PATCH 1794/2270] seabios: update binaries in pc-bios/

Signed-off-by: Gerd Hoffmann 
---
 pc-bios/acpi-dsdt.aml | Bin 0 -> 4540 bytes
 pc-bios/bios.bin      | Bin 131072 -> 131072 bytes
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 pc-bios/acpi-dsdt.aml

diff --git a/pc-bios/acpi-dsdt.aml b/pc-bios/acpi-dsdt.aml
new file mode 100644
index 0000000000000000000000000000000000000000..bb3dd83a56f84131f9c9f968cbee9385931cecd3
GIT binary patch
literal 4540
zcmb7|&u`<#6~`Y%N~T7#Oxd*8_Wn|ZAZ^lZR+JpKy;&kl)eP`aAHy>&^
zGm_&uoxkP*l>4>Et_@Io>|hIO0BG)ZS_|pVQP|{_olI!%
zB0WDF+7yFsxlqX{bc`g$;poyg0h9}Ur-~vY*96E&bd`}PDH7)*eN`EWzEee!k*gX;
zqN|KVNs&<&O-4pD&|pd^U9~VWnmo!WrOc9)kahLO?aQN}q_j58%8Bi9t?
zL>cFtVVpBEGUA-!oG9a*I^)zCr_MQ1#yQiBGtD^DoD*f7Q!q}!I0ffK8RyI}&J5$s
za88tQ&Mf21GR`dLL>cFtWt_8&bCz?WjC1A~XO3~^I489I45p4u{S5rIP;tnWt?-Kan3W&dCrM4&bh!i7Z~RP=R_IjG#RJKI8DxpGS0ck
zI2Re`BIiUI=Uif(ON?`gbE1rM-e8#~e
zbFMPZRmQo>IZ?(rZ!*rCjPoYvL>cG2#W-&<&Rd)lWt{Ui$fxp#RucS*hq)>t1W%Y
zt#_jPm4f#xyjkHLZp-cL0DgO4eUkxv8V2cwcj~)N!EHN!!Cd#fP89~!5)7!R_emg(
zV3hsrG=S3puU%spFib7y}t)X{`8O#lg&{#^}yo8Hy%3Jt$jvJ)Z@n$alUSEGrLSNG&+?T(Fe32&eoyn7PEvRG^=0~mmj
zDALOR5I%%N>JYjoj`pDDT>7i3iBB3I71En;$aSc9c3eLkAb!-exI(Q!F=>uhp+r&>G4s
z^_2=raRc7eC_6cHPaY&&Zs#(+2Ifz~ulvc9CvUlrt%}q3s=-k}FaIzYrSK~s!?{L?
zKZ@ls#B4+PSp8Vl_2Teq@M_9_xMM{RG>O-Ey3Bt|3VWJD|DF^V>V*n=(YQ)cqZH+9
zDMaFbkD&cy?r%4OSs^Eg!7q4}XD`czm$O>50sIaN1
zQ?W@!gNiLGnpA8T4CiWeGw<5h+yI)O5prxxd`MW{yY$MT&&e(k=BeI;7mwC)wR{ivj4VNp@0qN1A%%}01RjM7J9
z*vG}29*c~*-h5=Y6?ABq@;QmAbLzAHCnR(x7dhlzq#Zb1)$(1&yDM@|9
z_u8KFvLDU@_oQ}{+Pfz^l)ZK>yGYQl#~+y9ilw(?dJ88=XG)abGQT~&HBE0{Pmdez
z4^Cf>r7z3$7SPK2>%*o9_n7xh`v=J`0T9wBK;+@+r?&
zZMRt}mDa&b`K?k3%tgOmvS9z}T%p(3G_bV{`{6Ev^OW9|Fla5T-VUqjNIwtNFT(1V
TVO0&QT3Fd(<%Cr|tTy4lRx~#~

literal 0
HcmV?d00001

diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index eac67cb05a8a10f4244c3e4aeb0c35e725347e40..dc9b57ddc9a39f3d8ea75a8f23e3869c26144795 100644
GIT binary patch
delta 35856
zcmZ^M3tUu1`~RF}ffW{ZkwsBKKvxAt1+S=Ji(JG@iXe!0?Lx;(WxAVM=0Xd~aiy%$
zs5dK3yIYc&AeM4bP_t6A!b^%}b#PJfinrYV_c;q>@B91v`FuHZW}caOX6Bh^o_S`@
znv=mo8Fe~eaz}j|Otc;~~V(b~<4Ir%xV~+zXfK@?^y$h5B$GV~g!2J-$455rg0W*PD!x-BFR0G4i
zF*X^P+8yNqhk=ns#ya)F6L>eAv8_Pg2*w5iuK;7Ly&0Pbd<*;q+yiudkO_zbEWm5P
z(~+nM_ykzgmoW)=2dDwQ1%mo9)&m#-i~y>Dp8#Wj#x_PFFK_}F8;xNC`VK%30M?oK
zQ#1tQ4H#k>>kRx9$JlAWeI&XN_yceNCryks18(u41AYS9jbbbWs0OY8Vj^RUfjr<9
zU@I^_338Q;;Z0#|2aqs^u_wnd);JF1KY2W3#S<7Cn!(tkz#L!+unKq!*aqwYUdloX
zr=nMY*+BbgjP(Y#&BX8kXMk?AAU{AF@FwsLa1eNBHW&cr%|&B@O^Z=EaC0%nf7lYn
zJ_J4k_5lY08Avok@`0O6(c)z&95}n2v1@?W3+OE%6FB=KV;6wCK=ca8Mh;`2=Au!6
z_GK^%gaAE&M}a9oHyeZ)*kHw}w&AYKCJzz*Q@TFA(&
z5Xg0mt>lb(tVadF31jnjGIr!Ew0svDxeMd}8v?6K8M_KhFJo*kuxvM42D}Sw1&V=P
zKoxKhI0e)Le*%p_b~$5T0}J8|bqa!&$*tN+o6j@H>!N1z7<8sKWSn
zuSOzJ3>*S}1rql&Htt)-G5`zkGmv)#tp?TsZvZ=hYTzjFEASU^6VQH#*#V3Ivc5is_fNj8j;NDLt>}SS&enATWUdPyrCmHiRg#rQ9
zX~z743ZMbd|H{}9AQ@N(tOwo%HUgUfb{4|}q@2g|H_S4?3|I^BXCqJy><8+AMu7be
zLSW7X#-0E~U?H#wFayhg6+jMfq#3;coB)DU(2T%xpji#3-5J{q)B;YRrw5b}@HOD>
ziSbYO#QX-jv}0@;rxRngK5_Xe(e6U<1AeP5@^BjW^Z=U^4JCVDZ5$0PX_*
zz8D4|3783N0qTJXIxq-)tHb!erpJpPV}b3liUFy>bHJy-9^f3%0Hpe3EdZ_p0S2h(
z4w&n}WMD3#BZRdRV-Z~$dn%N%@4_JY-5C24kh-IXffK-4AkBzj>IDI{;?L~f(Bplu
zyhdW00Uz~6rTx&&{ZV){hzLWV%i|&OK$ir@9!X^E3!n-xBta1YF9H7nssI^?OolcD
z<^t8gqA{Qy2PT1Az^w5Y|MCgwqKS-|fJcEBfr>1sRAAmz#?AwSreQdsK6}r>+y`C(
z+~#6jftMCT`7B|q7qAF;3-}p`Fr%A+!+>Tf1bG>zDX<+#SdO6tRxQW)-$!8F3mAqM
zkqG<%H~~FW=?LISU`!6;fI}~1>9j#8fpWkv4|)PP1?clJm7yt%MZz_~Se
zw}V;WN8lfV460&D}kiXg~uGWPd>(4%jol~A{*0H1d-gMg*)qK5$Md+06eCXB=TjC~J`
z+lrQb0Kox5Kg7HR_5njbVr(!}?gQYdPf!W)&ZiJ0;Mix-^V`r1pJN&WyMdp88$jR}
z7zSV%@GS5daC$pqFMkOIw*%7_uwKU>O$oXK=nG5$o(B?kLj3|I(AEFh1)Tt_ErntN
z4wr*w4_f^V1Pd6v7ZP2GRTS7?1qD@&3Tk1}0UrTh19uKXk9-S804L!Hl-hR~{}JC~
zY5;HifEfVw*dBNd_yBnF7;FK+a2!h}@I5g27c3^ge&8p-0SI-N%cszY)0nbA$Qfu<
zpcs&WOTeOEkv~{qFH{MvCC3`5Zk7iUw)zbO$
z@C?4MOK(+PC+_GnE{J#XWzr0zy3pV+O*U!@#~VYXdi!K!ki4y#rv>%z7oMSG1dF%0
zdIZW`dk0gcI%7&^x~)+yRcG6ybfq<^;=7c#=nmf=G{~Ro-q(mf4zE2IC|s}Ow}OUy
zQM`Fjt`jT{5AN!E)#l#A>tn$KU9TD?^}XQUt*?~&WAHj^SlZ9mOIK}&okaawh#_!M
z8}&1{uw?AlItJFNjl2{8CL~bR>jwWN#Hh+?=6{C_QN4YO4-W02GT-7eLc6JgZtD{%e*v7oKo3pe%GG%f@x9$U!W>nsGI;G02{6iMQeEpX}u7-g06D58o
z;{E0?6OFDS`Mhp_s%mfWN!?>S`%!_fUgPV!_nx%yCQJqQqhP2@zzO`d-DNAfTitE9
z+4DhStQ&Z0BJQVAmZ8_sD+is_FyUL2q4c2!KDRju3ZzV@t+MIUeQzs0?cp#jgK
z|D;;9>#2geKc9#`?a<4!ZgG<_JR}$?c7t(L?p=K^EW79DcNganhe`!+UgfKeQL5;h
ze7AAHoTXG}->VqS2N=>>vmMjYP+h9Hj^YCl4@Tq;H=wSXI^89{`?&Zv5|8(uSlLH}
z7GmO}w&Kq>wehc$|8C;rdc>&=H~E?#8LE#v^7B0+RIyDZ+Me$SerM3Q3v&`|_w*Kd
zexf+}7BBA=sVa-*a~KoXvWIh
zn;>WhMA90&=?_VolJEv4BpNmI^}B=6)ot-BDZb{vW5p)EED~bf#%Pvn)i-)qk44%PpsKGtDoQ
zWsqYW{8<0NJq5=W1`g?mFd0V52ceD2BOLGmw)ir1|IW_B(6?0^Lc}M
zPMmk~--DkjZ;)y5^KV%OV-?caetUo_Bz>70?UZA#K>`wuYIzZeNEAdo(VDsRsFSD3
zC1(e%5k@H5c+FpktF@0eYAesH=j%yOmH5RJk6uNJUblU`G3cSR%)j`SAz_{Ow~8wo
zrj?U^Qk)(qBdQv=O1{?(uM^No;+dUa7ppMZmMdwA*dj|fr)f5Iw)TGHOQ=*lr
z-buVeoGxptA?OtUd*p&J*KnRihHA-kT3Jv4dib=(cYc_7v_&GNN5Y0q8HqvZmmQbG
zp6{Yms4G1arC4
z(pwD$&}AZWDpox*d%(p{Wj9Ek`<&ssO+8ejPV;(GV2AMAt;!_;Rwk{Op7NkN?i)XA
zP!5u66OExX#gRa>uAvC#=mObL_|2fxIu=p2;IP58pu*rzZ_-`4@qEdq_}>MUXFbnP
zNL77xj{lOd$a))shl*Lb-W@I^XvN)U(TW{@jaX51dpixQGiz(ziHQC=+QsMI`3>oo
zdRtr`EI6jin~2=@xIn0;a?fi#TLe?DPua2JYsYvenldq=)Sjlvhmz{JvcSoT&%A-J9
zrr1wUP+SfMylcSD_tdKa)aQe@f3zP=C(z1?!e
z;ceFl*4GZYA)-PZN2!Z1OO_*<=^_;;?x5^{`~cls*Owyp(jVy@7`?u=T*5(&txBDHSL=lmu1Gb_XUi$rk`}F`Z9=t+uawgR^?C`pN&!`B@7%k@(c(+)YfkZZ
z#zgq9F`?G+sMX&0Yjm_du1v>Ij#=yT5#oh=5svf>`J)qj@z}_jN>@$((Pak*KtmeP
zjns!qKaD^F8R4D8el*e7(}Yo0y;0cK(S(^HMM=vvQkFXZlEwX-?I>Onwf2AtRJyxD
z$M21uIC?+Ag;ND7m;w%i?Y3a?xBDDyjimsr;BI!GK^TAA9si{r6>55u)ZeYgG>{D6
zy_vyZ8yBQ1$l%+@#fKmBYf-lWGiWhAEh7cW-KoYje!y0*D%cLpS89s&)v}0Ox}nM
zncZK~*O=5QTZOxH&%VMKXk;d-|SbVxaa0*RzFh`D#T0`9lGfyq~pO(2&mYcCUjvnij4k*?pj!__VsVl#(UW8-?kLesSzmCV6&l
ztT9WaE7cm8YF#TJr8>M^VZ~IcB+3J1&Z)5$^_m|nE^FiG0K6WsMt6*ozF?19*`|2*AdNP=v~xY#HkCfu
z%eT#XM-_F4kDJ|_9!qEU@SH>CeqUCyWp;bPD&F%!FKLSL=Vgljv=n}|TKCt_>X@du
zR@uA}1*To~W>Us+804I#0k!Vo;FQ9(?vbt#tERMyrG~b&iigr%o&XJ2#h+8fP1FgW
zQFR?gpgyUtvRC!4yyNVmwfW%JRvRMD+tB){L{MpOMlat2PtE&m=!hB57JMvScz_{!ge)|Yw=2wZb9&;0h+)5PtI*p6VlsKE*qN_<%A?EuyS}X9W#kxk
z-K^K`nxLvY-%h#)K|EW|-+Ria8CHS91`o>M-#*n@g?xWKWlVaa%}sHAJ7mGN(f8a!
zHAZ8X4{;=W$6k;}j36&`Z=Ub}!9jOzJ!*GpO#60j6-SYBtrlPF`ALF~&G#!@XzZRL
zf4q~LY;XukIWJ+Gb*FHK(LdtXq|F5xB`?hDB6M_>@BOdx`-0PL^SgI$YAe70=dgWF
z(~x?iaaE}lG0;6GnJGA{!Su;gQ@cv49Mm4e&ZZsC)0VBr?r{D52vPTk)fwOB8jX|^<
z2}VjMN}1(KG2~b1@@hNbGywzxmT6^2+PX}?_mPs_f6;#@tp12^da;wQS=6?z5IOJj
z+85^p&b*0rZM<<|?y$_H^muca7*4fm-sg|3=+PErhoI$dm|5i`3cV$Vtn7*yx`?j!($W{-^NL7MyAN=
zW%}E^@#P`bZ1j6qbU1dX`fO>v(Tl?4jmB(gtx-eck!SS4Lmm#_M7Hf~V>i4^#Gd02
zmGS3)pnDuIAul|qquLK^vOI^UVVG>0w`Oc7Xt7urA-bG9foA`lJ9@Kk&Ye()Cn>Mk
zVYe;GFc_lx*sbBx*T(xaDP5&tCwl-qRUqbHi^uf$_z_z-zp8&XHRV6tX$$liZ;Z;e
zFXzE|3#}!ZDG;BXMobM>xTgRM0LtG_FQ1v9Zl!HT(g1}vlLub%j5+keP0&PW{6TuL
zlLVplN9d)*q`}KhBg|Zs#$frNH0&X$Gzc(C!v+bZG58u$+8H?asW_}gD6XE8>?SX~
ztTh(UO9|NxDDDEi>@oS`@V(;(_uux*qFsLPM|X@LHQ^{1^}VhmJN@{^cfp&9~&6RF|*tKk`dd!>;iE
ztXiUax;Bx#EmVUS_q(i#iGNvQWY?5kI>=
z(AvbE&RX}K&>l!e;
zi=(obS?4O0S}l(P3%U1JA*joz!HlkuKLs)Ap>ARa;-?gYk_AVi1JB&Jw&Q^-_Q5dG
zi#9}ABZ(>-srKh-<%KKfSVEbMv6hEWwKe$_E1QPZSsTR;q>kf2IMen(Fb|#Jvh>Ty
z+;_Maj?znqC)mg8EjK02W{Q&#qwEE0M`?&x@Ibd7{)dO;Hy-J=vk2?JF4SqyRBtN#
zRmWm=&vz2*kxN|Bw&uOPns0k!k@la6kkuvOMUjGPP!i94a}GVq-b_=)BysIqomC@~
zc=%iWbqQ!4lxvhU-WVyL&*Rx|IjlFp-Tzg=85=D%S_hWn3dxY42;1v{I}w8`yN7%M
z#sK;#|CTO)7wnDb<78wo`8z}-jA_HI^HXLbiHW-kdp5gSIHJgXMy;48-4G4ZEv|o3e*~mTL;M?CGsH%U1UwAt+
zMlpc@T;awr2
zI9qIuPqa8M%wDo?t<%}i1g#@>PDVqsa)o@;7#P56Jx8LT2wjX01KggdO8dhhOv|tes`B`{cFM
zwCQB-JH%(GfRj*LoAWTHaNLB;XAUTfOAxsTg2YcSdgA(4b5Z^Rq_+K5ZNnh&)0W54
zE(MAzutu$-Mf$q_EF;+#-ga~+!ys~4~tH>D9d+#G(YZklOXp>d8+itp5)+Wf2J(*D$gaRRD$H9Y=oxk#XXKReY1d)OV_}D|4`Dyf4kgZbfV%!^U
z--lS&C}9}BAb%*@MS@~9h{q$md!jK06~>}0J!ZZMaj_UXQ*)i|IBPzIBn>%>t&R>z
zi2-$Za~(y3L5u}@9f{uXXPal{UowX&&i|#Ib75OLp@5g_L8c*xTr0WLYz)o7A43a*
z@C;H${S?ZdA^%cKmUJMQaYr$csG))_$mp~>G1?eX-7AgQUMSM4%m0FcJ|w8%T)&{Q
zRa`U;t4JPZ7&Z0;BNg=wy<)5JkVu8&Y&fVzto9Ix(YH`OGkfmAMGCx-|H3{|lYhu;
zurJr!dG9~sLt-IVrm$LA&QW1MAv_4a5RLt5BZ9;nxBt;q2<4yt5vB{3Zc7)hL|5#%
zPn{gfPyNx&s?JPDV-pFsLr(NtERsxeR!v)rCqXsYQ-hp?Hq>K+fiQ+ZjGF>d#Sdu`
zZF&(G2cQFOP}Ex6egmp?)8&8u0HT5}uz{a&^qC&F
zQ~yXFoxd2|e8{irA58uZTcy+XBdKA1*g<4AgpqtsmL^+`S&$(OMqJx`5){p+iAjvG
z!B*q6{o)jA{C;sW8#Vq|Q%KOmu7cDMb`Ml3pc=m=3WZAngYef)YxKvh0m&zZqJm@b
z7aDdl>I{@OqF?ZmqP)C{7nBkheaq3|iCT9mf&SIHQz`V%@!N>OB%9U|5zEsY_*q1{pnH^_R&Sp%*mZ>)Z0;e#)a|KSd!o)74!I!iQ
zgwU??)oQ16IwoGe2WDu)QAna~{}aj*>pEum85^)bl-lMC>i-gSYwgrBio_QOR
zh*9t)ySCo_Q8Mg}=_;)ELZ41n#sA`iS?gM9vCdwy)i+6_4XM&WTfHa#W>?B?w)&7%
z-LCH@iH{I>bxY9}nEB+w>edYQM;mHQ2DHOjYtqsK(@DBp_Hl1tGD#Zzz*39*;wO6`
z7!Li1VIz|lpxtn*mQgG?4iax7Af9PGV3QXt<;@YHe$vg#KQxl;12Pw@JiNCtOeB7E
z#1C{F!;$Y)9E*agqK(ShyK|3t%ys)j91<5!QsbQXaP}1!hhOzlIGouK3Lg0C=;0lX
zp@$vqaSg!@N3UM?Os#NAzW+D>CAy!=kjFg-3|9SW<0A(QP<>+KiwE@M@4d6Mx8iv-j
za=Wd~TbA&*-s{;-DLHc)l}wvrPw^ng9J^}KRCY~TrYa3$xOGjv(=hLV3D%?4q@=O@RawXRE|Y_+m_CJ{rkgJ
z8y4}S?~k4N03uNK1WJ<6FF{5)0;TiPMflR5hP0rR$XjZoU>PC{NR6oLbdBz9XkF*m
z?pS#pL1oyuVPAn_90xMQS83FbJc|Y#bWWSfmu?xT+Wjo*?Bo3frOZOg^jZA3E!|YY
z67I1zWN=qBwzb^0!}@#_Ddv!$Lg|pJ&nPp)5$dX|Vg;YJwR6W~RA42Nq`UCc-k}M2
z(1{aq`_=_2zxTToaKJ4N7F^Z9+7jo~9
zBK>PA{9pkxZZp;(WBJ*UeC$Whs3yM5%Re&f&bw+%HdBqURAaFF=#B6W^VuJF8-1NJ
z(Q4u?A{S4|!uNu+&Wy37|rxkkFdlo!3nA+`xg*f}FDLQc()&5QWK
zkGuBkfF!AoVrXfRlPHtf9je7(HyE*A8PddHkVITh&y>R#al{-$!dQf)}YFg;?T=Y$;netn%WR%(eKm7Ag
zx`z)yR{6SrX)&Ig?Q!Hiq?Li+{v>2zN;x`7G1lt~3yBaLsuU{V
zz1=YQiPZgHZbovXzVu8dt@NPbRd5VlGiNz}_R~2*u{a6B=2s;h6(=D-_BFW}8F|lJ
z*eG$wrxR6=kK?hQb?K7WN_RUAG&w{w6g0K&iTC;9&w8jPDP)0d#VKS;QK#N?I_j#fw~e=2kqP2h
zfnJji*nMdCLbKmHJ9oKW@GxubW7IeoyGrwIp!8??Yt)u{c_p@;Q^Y3P>uo>`#!K5W
zUh?3DD5**Q{tZRr+XGCk4Lq75okSBs$K<6&Siy4lGl38MJbd^kC_+BA9rlhIG>
zmePO^=TieP*ku&0G+}{wrfu2!=t;ie^Q`t(?8VU4hKwoVekv*MN$&i7iswZNpL>GO
z{G#uyPUDqUUW8_mY75QAK$t0paz*x<c{5+8gv|
z{7`Ya>oomNc1iay1BHMbm|AjIs14Z3CUG*jksIgm)E#3yms5D-9KLDCYTptplaks9
z&0Qydw1N*Vd8wB&c#l7U`0A{(sFtA<*C8N&-8OoU&*mpf2C9n3bKjkTzGYORZZ@V+
zo!skjK4@nT&odNtW)`2bGs{zW6ycX<@qIfj13r8K1s`xkVJ!5ZE}~bp(GlA6zM9@)
zIb)Dq1kb;~v%iXSF}3(HB-TzViy@|*I8okCOr^A)C@-GL4}TTcZ4j!XLmhbNXoGVO
zJ&xDdx$ptR5-0vMdBm>wJ!epO{tSM6*Jk}wSdq7+)GPN1o)e#Yl-o)t2e?t>cvqy4
zXeaX2>AbPDbNlq!PUk+F3phf@UQbS#%>&E&s5;E%NoAH^En4xTD^6!-hWI}6L4w+*
z*kg0hh&uV+8h*a4gEiD;)=KASyMO{&!+DfT+juvvF8?^fcJJ&FI^D}JP%F-Yiq;rr
zJAd1rsn?ZO(NWv3mF?Tzjthl-qsyl=cI>>=Np_EH^rKc+dX%)ebQFaDYZE3~u`x)c
zO)MF4DO7Ol)d%}5>g%jBibP+BikT=`+|(uj_Nm~fSvm`S)9?pqpp!kxq0x-Vsg@>c
zrKOsh(Rw#@j|QeEHvWMEZfcAUtTibO!02k$sC2QrDukob=)hFa>B%_7)6i<3q9h!-
z97q+nQ`dJvg^EcCl5qL)I+%B3%7+e%>kCtSFqm~)2!U#L^uZ08+`H(!^%Vljv_G%L
zO6+U*u+`tr9(GWdw*l)t@onedly{6ROcF@iApTAAcen@T2#F&*(X5fKW8p
z-Z2^d1J4_6y8`9A=ppjg^F4c0t%?=i3mi!`S@2YMM57a18m-(}(JDz(k>n{Z0Kbmu
zC_^nJ50YjXm0J#F3_U78@ghn{4lgH5O1a-DrztU!55<_2m?-;%aJWl!ww000+>Wo=
zr_%Pl){=vSno^A&*Y~N<_Tl+$LZTlPCD&9zkf9{Lg8=VEcg$_P@Txzv&8tj8%
z^~6>5^c#T2(o~lnX^IyioSQ2~&kZlfFfh3mIt<-TE9{hXaRT+r%OFEk1Fj;l=u6Rb
zgcn4Ei%uBS(h15EFnkJ){IoKPY%xF@+ope98V{;`BzOk)ic)2{g;=PQ6MiR?i@YOv
zVVQhcWlw96{Bs6)rfI0lr^!crLjwDv&vI94nZ7-=7CyXS_O80pZ>59(qo
z_JRlH%A?qL(uEgnW9wS=gl^ZlbTOBjHhvQ1=tfX!e@X~$ZU}O
zm
z`VJ*N_5*4}yR^lsmUiiPM?E}N-=a$FC|j57An|=_+`_iTeLE423lMyGW>tUdU#=$Z
z%|f1kn)v+znVA)5on_3f10?N2G`+cH^G3h+_AM>Zy{SJw~?la
zR4eh%%5<%3WH4^QVvT$Njvihk>!>+(@^eykeV1(
zmnD2rjlt@^1j3ROF26F7o{{n@GoY|4mRWOF7~PpUqm1F+iM(yR(my}hsy&K}rBjztu122bqRfy^
zHO3a3qvZqRc>E!M-)BV)`E3*lc{_zacBrQ+Z#rLds7vQKocECL?gHw832rFNGa5)t
z=B4v}hX#0mhaSi~WO3hDGm+mv)I0ilkWXnHcpT$|r(#IpvGzM~7p~it>S;G=WgqBm#hp<9ZGh@&xZ}Qk&$DVSNiH*kRDJ?W3$Cr1cAM}<_JVRp&N)UoOf~Ac!uwx^UtgJ)Z@WdA^Jm9-L&qk`!nZ!4J7Yx&wG%OBQq7R`PHdN9YWe*O;
zv0d&xno7^R@1e(n>N&U|bpp;y(CX!(OTpCvD4$N^MXEQnt=`KCu&xI|%%ExBM8>jS
zsp#{x=V?UEUbwJ9ksjuuHF=5y$C`rxM-;my$m6qD?TZ_$
z6A+TFT;H0r%#AHm*Ca(`tud+dDwcWFBn{4Tw8M#8LDC}yNpUqv6ZC~i6S1V|g^O56
z^bu9Nl_^jMhHBXCnocGm9T!1I)tKC7<63a^aYvF=yLTDt;8VYU#CmE)>3o$q5=}^t
zK2$!8nzBX7slg4>1Y}G_#)-H>I-$no-riQ>QJC)Lx{f*$WCekRi-hRoFasRH1;+}G
zR>^3GEwLt99bc2|KDj2@gViK^YNcdNO|n*7
zo9si&V@LEv8iPKHLg$j?lxx3mI_Y53fRhWoVv9@X_THy4
zrENI$YSlwGaII}uaMRVex%c1qa?{-l5_}30IutJHEL|<{hS8B~*9gN^xFmIgq%xAE
zGJ&F3z||HKugnBeNezNWd?(#52Q@3G{PDMZXd8=1tw++>sM$CVv6^hR
zVLi+s0|U&v*FlNno`3~e=ZCs(6)!?q=4PieLWYT!o}M@vE5pURiam(S%35jR&KTR@
zg6*sm=Tq9vG_eYU4xB}OSbD$4Vx)M3!^Dxqa7^1YT4Ew*-LwtS{69x~3~@x&B-TXY
zxV@&Yrl7JQv8Er;zo4q(A|&cKNt9uOB2gD@zhNs?6J^4MrX$?vSU0*l9DU5-_bzHw
zINsrRePPbm#&>zBiaw3*(MmJ&Vr=&WTOAoZTIEBEG9Of%eWmbg<+{;s4c@4J
z`+DUa6Ve!6LANmzF)8gn)H%Yj%JXin+rY~Hp+^F-fdV7xjG%+Kme@#bWg|fDIT9O(
zrLb0vZc2XWFFp7AF*senq6yR9Xsc2!I3BL_du6@4Fi{_cvIfZ>&!Jcx6oKzSI13D7
zmVV+}|0-JEi8~J%qa*P!w<|D*8w&UfKX#jfK@E2#!G{d#)?-$uy4kxHWT^_X+SMee
zSWSX}gm!?275rG?!0?==;R$+286Jo2cL8_sZ8aKPF&#A`fLgq`1dPZgi
zIG;5P!C&wnZuhcJQ$v6(?Q$y_Yr^TH(>}1(awAu4T!}+COf`{UwLuZ$nE?0xn;nT`kJn@8X)fzBAg8!X2
zVK|SkGfYR`5$MEF+sbfei7xvZ2Be(gs?JO7fh-NHz}nsv7-_qog?5o@Nd=-mLKQOf
zy|ys&8zX3-R&>aSxgcXAXvJt=TxUqa7kDZ-Yh#datJF}QM*0W$
zoikhRU0eLb5f8D;+ntQEYNHQDA6IGhqilB#mgY6Ex5Ez?q-wS#Vyls!D!xE^uE#La
zO4{80n^1C_e>JypD_)~#-dP7%8wjxpS%v1%w!cgw{xI;q1aQ7|a(;!uw*^>T!!
z)Z|bQCXeL?zJaBW8mxGCd9-6O;daxIxoiofDstkXFgEQg9|5O;B1+f7{+T&3ui=!)IxxO3uoww$uHeJ)&>s-}w$
zQmsQ>pc+M@uQ7Y95%MZ5O*JZ-fncy*vaflcRulJ{>HS@|e>nRX^5p|1;I?SIok>VG8=NFMbV(Z5iLu
zx9Di3(1ZK@I$L;!KmBXyP%T+Q7v_E(YQC$Bmf)L){|#T4&jkz01%(KMu@h$QJmAcr
z_G}ORvE%do+F$#7Zy{Ou03M5})46aqC9)gZPus?lH7H@xh3E1rmIuk>hPG`Ct-dSh
z6ZoZ`a^@gzIh*ON)hp#m2b+KAC(eco8~NX7y9rc^N$J+>^$ANjTwYF$t+F
z@)W}nA*>Umn+i7?*YlclVT#dccilfNON9oI=lyR^?p+^|K-Og|VHObvfl&G2d@8;9
z;%zU}YuO$VuTUvO|6d&NrS%c|hswcJD@o+V^^1KUNyM2(0*t-rL-N2x9(BH>s&gVA
zb3Q6fhR~LKz;MImawk>v3nFA*OrorOI%o-N@jBpU^9R_o8+rmFyl$9R@kxgK5E}W6q;#Qd18nwhgJ3m-U(AJ!0fyf0`ru;xZDD
zkKv`RbvI>j$HhffI{lL3X!9x!rp>ApOb32Z$IIGJLcU5IC`i?G!hjz{!QGaxQ6W|1
z(B|CrvUoU^2-6yU-f_!iyAP#8BR*t5{525$Q-miOP6AV-n{BkxOQocj%9BtJO)*{gx|U}W4t0jy1XM80DFKQiWVarEb
zgy*~9ClqK>MIVoPVI$PU$HH@#_C(_)N>Wt?u;p@+KtyMDwkU7zuvpDo^K
z;WrM)yb&!7|49tj;tf6z_f{z&KEW`Qh;p@Tgu4M!se5@kT*L>!(S36${>Q(tduH_y3NV2RAB}`%
zmneM?cfe!HLCu&NHN0qtEX_3@3>1L{nZg=eSSgsGvf>$7(EvODkUgl7jC|W&q0=GT
zc~t=fixOe}|LB0-ufc^syc-H8xJk)s$c9#$pt02$gu5;KfH!ax0K+Xc;c_NfmX4A3
z;n|f}G}0a2u9G8X7`5h}$_@(5Xk5%NLE=v}b+&5pvm|?|#2uP8v!jLy@n9jaAVsJ(
zsm7$ohi2EBJVHYYm6J$AIqk*9)+Fjt)N#u#ngun2swN)Wmw1(5O}v{>8xK>e;(@JF
z17=d}aSCtWW>a^<-oj&)qF`d2PAeqEY)ox9fg+E%dSmO2@H01IL?E%t~y<3u;FAb>9!nO
zyx^gF@M$EZA9WO@yVoRmFtVi!(mj=r&tk828bnjLWfx9CX6{IP2xjr9N$^xTyy!(`
zakDuzwrUOLk+Q?!(zReAkbiV-s5PL<7l9
zpBcuK%6o2wL4n!Q%x>AzqtJq$q!%3SiV{>*)J@WYp8utzeu%(Gf_F?w%-VnU4y6=d
zJqtS6?D+)vGcZe(NS5&{v?S~$?}25AYeydGlJ;>;j0T?|fxn!&|rs1?0@1ct3#aTZ?nF%;bc(Tej1
z#?@mKk>3*sx@%#zw8p+bvCmTMx`$$4qu8kw8;cpYnSRi~ZqnOiz4G}dmTxVaYISIo
zeF~%#)ofl1(*$m$55b;fts!5QrE4B+pE)QV
zuByvQjFw_%wZy>j^#!Q^A)Wp|q)(z`$}BaN?<7*qa4(dKb=d?`6P1dE#G<8`k%+-6
za@n4s&9=sQ`04V!k-64A26~OGF1vF3Njm88&(2+@_3*Q3@bn!r5T0x0EUKZw1}a@C
zqsDGRW83ZpL#JU|KqvAzPtxrwSPS33U58mpf!*}30#$xyo!!q>BF>2#a$JS-
zjZa6bR=e>Zp6;nydy6+eJ!$Yxc&W%H)8+q+6$U<9;<9Wv4R1Rn{eQ2cb+OV#H5zC7
zL@Nd3PhmM1jy$;zx1sR?)aWp*{SSSFC9f_;;@X#-&YZX#v>Kb|$>;l!=U~|!Oc*0d
zXxnU8!ThDgEqMNNF{bTy>XA^|Cd(I~Uu;~wF^WDF-gcv3FJeWiia6|WhxYbTeq$=t
zseBSFR#8j(A>U?M$Az1{R2Ou-_st0FniQuqUHp?$4~NjyFgOSA#J5@5w(YY
z?j-uw?3s=i>?8029qvon)5-c*c7AqP1-(IPyX$5iveZ!4Qwa;^-eti`Nag5MHc$z<
zn>&>CM`*FGELMqdn%&Dn;t@~=O|
z!Oq>k6`iB_3)YOoN_o|GSx@??p$?~^cAs?+`tte6*s%T{+2JH?m|(2NJ(0w&Apj%W
zLbZgb-U5|9fO3^BqxYTvM=njnxe>UUDCQ79%e#^cldQq>gOCX!2s)eEPz4(Nt|CTL
zIef#DtP}L{s#~)?R=N#LwXAE;>KZJsd}A^shDUG|D3@ESVaBC6vw&~~d|3(56Ss-7k@qP8R~m861;14Z&lP#cg#P^U-yPii+qLJO55~8fxM6nssM*tB
z9?fSw2ouKel@A7cd#iC-p60n%yON3rH#J_Sb}ph6P0>D2VX?2l%deYSpdYctPfR{2
z9jg%n+=RrUIo?9BFr;Xuw=mdEKdM)0nYXY=rP7Zsl6-{~!q_4YoiNX;pU`gh=+q?5
z?36KyKJf{uW1^y>hA@N2?D0`i%n&d;DJq)H=)WTypqq^|6Jcv=Lef}DD>8HxW_ZuRkNu9@
z>dSuH0y(!7HFXs7R5>Gxo(~l8qiN}-y8?w3DvB7?MMw{ig%*_SG1sf%F4I7*sLNs~
z>bw7nD%##f2(~J}n`xBl;}~Yd^Iqcl5g^?M;f$`>lRFcN=jxYO2#CtA8FtX@D|R;M
zScWu5ZJ(>2Sq)uOo&JwzJ*m;2(X@q1lLDwT$LMT(0R0+CHaxKd?LHe3cL^(!lZ|lSgzyr4UfM;8
z-9oR?r*&Ju#Sf#HA*v^iabMv2qC;EIz;H*;qM3Nms;s3;hf)1tct$Sm~z8|
zqUS<{(Dt>IhK~}2dw!Q4s_X0IT}4|$gtU~z$ykY$gZ)(KX62@b7M<7X@QVDG!>a#}`|!%KXYet6BlC@xg!+xIdAp!JGLu9AWcOAFkN5Ou-TT~P(
z^c3DM+8Zi#@}AR1@=Vchp+XOjH>lWzBA+m!voNVBJWLp%dT_sJ241_UP>ADO+hLQW
z#|26_ZDG-T9Eu+-JaoV4wJ;$tU~OAr8*yqzHm#4mr)Y1OFj#o9=th{(t>=nX3R-35
zKA=)QG^ABB6?bz)nQAu_<#ZDQizasy{DS;J(tx9M2yOEL6Q-QGSB4lm5>!WTm*#d8
zqE!<<1W9Y-d$=0kRdR@1F+s(w*81e7w-k<)@3v%)7suD1U|L|O|1(OJ9I0XtDmC?u
z9>S|0CJOE;+R#IIOLhEaQB+T1;~@Hds@?S6VMOKLgKiHn;_!*MeooExgS0I_bCzF-
z@^GYm&?%33qn9vwLS9#}f6URl95*R(T&7&0ISjFgJ}w=Uf4K?ysLVgK{0;FVs`PuD
zOW?QO@Y^S@d)fE_nepK^s!W+hlY0vbefsKg64F42
z9`H67eb-wU?enM-MG1TR>Wjkq2yxy&;|FeNFDJ`aistnZrgv2I+gn%Ak|q~7-)@G+
zdAI0vA7SLEX8JjtXe6TPbVf!SAf{ViO((M$lWGW`tua!n7NhCcO*9~!mV563227Vf
z8iKSrF|%lTr0|r-C`v9UIv6SRe^hZT{$IZ7^T={ek#+%Ts#r(&dj4*Nz4tqXt~VCV>L-luUjk15`|G9o;bKhN
zw2_d-rJbNVJ}5oWPuL`MT%i1bllyM^S%v81%~$a|ytS8|&LVS^@V4s4r6Rv*A$o`t
zIa{Y?PuH{z5y{UfZfq<4ctdOHir+wXG!!k176z%lYAE_5T8I^FMUH5}XkCX9fb_%b
zfxEinjUM(a?HV_m>=x^-TU~%l5m*tN#(WKm#q}b4c(y%NRfaW}6|ObDjI7u{3$#IP
zhSR~LAkUbOxNJ-X55>`uXQU62afhY=k4-oX&qh7I#a@@C!`Ph9gVwc@cil2aSNbWnv&rf3Cx4BH9iMC-Qc85Fq?5%Ox>M$R*>*>0mmT4yhG;UPl(Q^NcTnj^xcAY0QpD(l=~HqIiWqqw~h^s$xXdFg{?3
zJDw>c!y7%-1vxPMuAV}Z=v~N0p9CZD`B{6yAT-yAFnX~M9?IEhYcHY+^FyU$(bnT~
z2Ik4Ea;4C>uR}+Nk@P<200q0Lg46y3XP
zUaF${VZ`A5PrPIN|H1>~-;BqX>ej(mxIjRmkLk
z>yW;(W%OeaPFt;8M6mz7a|rt9z@>o;}|&o|&NeNKb!IVu^9U|ONYX28*-@;CY!{p{LN_`=7o
zk-Tb0(FUH`Q`FK}+@*mbk>)!QU(oyl2ct$JAL7rIf2s=y4a}}h*19o!j5M+~*_CCP
zT3Sh2q+c)$zD_GV-P*M4MC7(%^J*>+7hrN(qb*1@~
zhWY0z);{@|+FpnbVfc+zwXW3UOZS!3!Yz|lur%2VUA>cnPec^X^bf)Hc!1iYaHpaf@e@$w
z;zt7AjDQYP5jTk4MDma5t%$~dim@8Oj}Zt25Zs0bM9>pIHdXA3*@*}Kr6RG+6(qW^
z5p1EWKoA!`_S0jn^7~mxKY}-K;|7URzCg`Wem)BcCy-!8iYHR2mB?9#D5RXh1HJGj
zg7r!eGQL)6sPt=LMkIbA5g$>=n!=2}NC9~-DV@7}JmV4M(rNQqN>BQ@T3M{BuJ
zI6+I+g>UgF>F{OTg_&TW*Y>(nD;94QX(&uq)8y-1m>EMhLQvs^6r$)#`WRP5&<66d
z=71}bx%Q18hk{qU-Kx~<@;*esK3d-*aF1tW=Fh^f5h*{p4HmDtdW$l4cJ&uRL6_~L
zVG>v;8@pa9%uK}36CqL)T><^0+fb2WtIu(_q1eJq)8*oIikx3A5gKrB5C0v3VCke>
zHpn@zH}@;{Ye`i#q${Z^OXr;PYI6WOy`Zu&=Z?^+qWP$;Ufb{lI#q6j)3Kp92+KZ2
z@eS5gMCwY>3+P`girIFPZ+Q$-pyoR$zStTMx0+;?b4_|wL8f|5dUQdiJG2V!>e=yi
zLg^&v&tIfW11`tv3nzp|A6HbEeIbSCBS}!I}F~*p|tb0!}zQ!81h#_(f7>Y$8X25>v
z*0HpP7OgD0T3y5ObrR>Iw6imZ@Tpsb+t1d*tU+q+ehTEt?N<{iUz@Lc?E%zMI_|cQ#aw
z2W+cf?}m1qqrPFuSbh3u3^n#T~)PhF5Ijn
zw=2ULH>X2YFesR*|3X2mamvF>DBkeEUToW95eQo`O>K=nJTa1{N(DZAUnF&Xr9gIGl)W6XKfkqfu;|kgs-H;=|_*q14ghc4tkg=xi&6I$@nHQQWqWhMeQr
z`2$-{TSKNG)Ln!HWA%PIYZ`AT666Yylj30Ebh*U+hEfl2pYNepmkqlGa}k)8Iz*k!
zV~0{uXJw8%6GZ!ja8n6dKdwL)7@i|ueB)5k@Pf
zF+C$KD_EPJIX5%Qs13{Oo)@fTS!wgM-Cx(v8o5wzJA(R3^4p^UtjhDJ5E1VaM}fR~
z81>}e4x=8t{W$XB=CRb=`5zM}zB+M`_T{Y9jI@@RvW=<6oNUF@TK;hyIkxJ-GIQp<
zuEi3EHr1%@9@Zyska&cO@1|#JqqN=gTC2d7znMgl)FI9I+6&nWvW;mOAtJ7{Y}G51
zUyfJBj1S|kQ|JX3z~qxvlfuH1`PeDc*(-VYxKYWfff&ag1Ddk)WyrAxfc
zXe#CtrqUoDJ&N-9s;Tr5uNXxmTBm2K=4Pd_jI@lk6h69_2YzA)|E~D|6TrzW{9nO;
z9sW1<(y09V|Ml-3s!=V&zo5%njMD~TSP1Q-QT^PPUx=gJ9vNx+)a=ykWR{+l
zmi$`A>!ONQ6g6On|a)`A4?l!BY>BlwY(6u|#XA%9du
zhg9lHr93i~3?9Krm^gJY*uJYA2&mhVW#HwhG*oim!0)HhrPdcxFf6rV6^qx&muFD3
ze*
zKLEKN!w#q#@Jn~cbgabfvW@-96bu_a?*4^EAV})0nSm6zKU9tB+ZM#q5
zwa%trH94>!Tr4YSC{&a8d$!#kpl`C3onVLFI^y1H-Jn%8nr#o7{UIwAiy4GtS)p_y{W*P--jv
zj+u0&Jj_VGtx8eS14{WTMtT#fe8osQp~}uVG`{~YH7GnqS3~t;i?ngkEf#IP%PMaD
zoiRgUG_#7|Yj|l6)k^_<};p
zmDc6Uw+qQjl9pz0^$IddO^f-G74!kk=G|68F*_~h6IRj;H?go}8II}Q%^+40CYt9c
zC_zm
z>h_z=yZn>R`0qZ4(u`qC|4@Ft><2cp4>QchY>gQn*YeiuXiXPqNFdR$n}^}T2}SH8
zo7s&S3Z95nuA_01t&Y2_r)cWP$E>H$9{o;=8gaqQior@{<~+V=J@xDxlGJle+giCSy)G4an^uqDbQWfV;$A4@;39p4W#v7qDZ_TB&JzI{w9&K0kyelOo?%H8W@H(MKQP=wiIM=X>-Ex$!^V
zqmCVYPeCT0%_OE^PRw)zRUq(3^J5;qkveG_#Mh=_LnRhEnE7L#v=RB3!FOz=07~c8
z8)@+1+cnQ6s7FhJIx__&XNGIfq-iYRIguty1~GG=G#;^udZoXAQV<&+BeTj)eb1!g
zGr>xDmMoNd9;mp10r@(G;oI7P=7OrU2NV1WA`~L~i>hQPg@3(?yj~7$;krK!qj38Q
z@-$YVeM%Nl-LJLTJ}NdM3Bk|Nukc=*sZ-E(uvuIv!_SO~{?AOpKj~RvCGIMoxtYBD
ziv$-lxBnxfYve7P>4Jl^`ixNAQT&Z<)R8{r?`)&>Ed#~egJPhF;R`>YyQJoGw$s4S
zn@5>~^jdEV^|5UKQ+ai-R$dEg^aXjID$6=jyuHWq^V?|?dXDT5X?Ulq$Jmuo9pz7!
ziz;;V=bnzh`cvxi;PnAtyrozY}k5udQ#qkmv2rCKrg7@A@5&3(cWinH|Be*32`=6zn;#(`k%IAr$
z3i06cL^p+a{8?ggyt_iIexB%|5a}qtzLNr+4q^Dr<0jOl39RebEn7`i+08y}-n_^y(7`hcmp?-8$F8PGo
zN>cR@dBbNEB}qjQ^5xGd+<_i)w>{)5o!-rZ_TY72bJ#3
zSL~rHw3V~Hu%Oa-*<+OEz&KuI9mouOc=SG6M`8TC
zeHg_aea;{3qeS)bCjk@7VNZU=-z}$j-@LI1`14}~WG#!)Q$$ZMaaWm=Ijf*(&4^}L
zQN}=5rHaoDm&+??HmSRw61~9KZ+Wi+bcP1=2M1`G+Mp2ceZ!X>q%oSs@L4~Bs#J--
zYc0QgkRr4bL9`^pFahKn;b8Q8!rr9>9rBGl@JnI#J_zFn4`B`X;2o|#OkJg}p?vsZ
z3gxadsdc^Z%+%_4e$RTBECI9Hes4mh+icD`qXv!-a7DnhL(%Ag3`Qu~gR)hEJL
zQ?!k;#znN%6n#q(ZkpwVP8Q}Mw9_5|;$kM4Psg<)o9KO$EMMLFFYFLIf6v4J!nd<^
ze}p1olfw9~o2g?Pd&3dQRdfG`nbkl-OWV1
z4k-CSs5?qxvRZ~LON|IP#vV|7JRt}M&?I*~s^1kgw0elee62*QPLjHjq6_ow9sh}2Vj75WA+
zQwR(c0{(EtjMRf0fGCk3AdhVMuegi{{T}@83SRoH9W6a3XfM0#0oh9`WBx+m5xFQX
zOjud~Q--TEm~w-xT93dTT0BSveE!I4$;%2OfHjJ=3>UI+f$0c^(AyDIHWHaGU9#CT6GJM%KXqd)FED1
zOQgiihcR$l++j2+NNR6It&~QD57VR`=uzhGyM;lBDgnwMi+$u7`Uyyd>w>6
zVRim1+=M8^qTs>I-0uUlLuIO~Y)c{j;gjJ#SS88N*~M9
z57R`)!w<2=;_zV_?>GxCxqTJ2Big`qM}UCD-Qa7FVA!kR6-Q{bkDF%Y3CXfY5}nD@
zF4}buPdZ8?q^#@w!=v<~bZQH~a+G`qJ}5^bH1dg-Ix`&+UEKZx6eBYq{0TfvT8ek7
z(AN~5GcJ5$(q7%nLyu9AkM}i2B2O=xp_{nACX$)gY~mTm$k!v28B(4W2Q&YAoUcEI
znVaiR{P;0ih>6_LhGDyn@bzYRKDgMx#Y()RLxa
z6}wTucb%Z#iAPTO;w*r2El62?SyfqGSwoqb-8gb0NToWZHTin_bZ|rJaE#NR
zRY1^Vj%-2I}blg^eu*
zxUCV@GdVCA{YX2s(!f5LzwYHBtNt75#VvGtMU!|01fx-kXS~VHvU&vd{l9!;G6K9cLbW
zof=zxwG{4l99KO5M=Ji3dszS#c&z6o7K-yZFJhlLml>izh8czF-29cJp`wh6`S-rgWclwZeA75>=HQ%%TDGKHawnA8JXD!z;7ao-e
z_uaE+Mx#_7DW!6j&y;D4RJ>ny-4B~xnke&O6%?p3eIu+N;Pi+8b;kFUO3r8|2gjH8
zFGBcpweM*@3efCqel&i<#7R?Pr?OTofR)yj)teg3VR0yv&dfP^dQ!r)_&CkZjrf%7
gYQFO^ZSoddlSQ1%=CWg7GlNZ}>}Cy5veCBx1#bk8#sB~S

delta 35208
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%0D`Yv5MOrluW>Bt5G#@%@J}(6VpRjLkHXkD5t1A0h
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
Ds-xpF


From 01bbd8bf2caced5cb07939669f58d3a7bcc78092 Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Fri, 30 Nov 2012 15:04:16 -0600
Subject: [PATCH 1795/2270] Update version for 1.3.0-rc2

Signed-off-by: Anthony Liguori 
---
 VERSION | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/VERSION b/VERSION
index 1ec5aef844..19838b230d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.91
+1.2.92

From b0d9ffcd0251161c7c92f94804dcf599dfa3edeb Mon Sep 17 00:00:00 2001
From: Michael Contreras 
Date: Sun, 2 Dec 2012 20:11:22 -0800
Subject: [PATCH 1796/2270] e1000: Discard packets that are too long if !SBP
 and !LPE

The e1000_receive function for the e1000 needs to discard packets longer than
1522 bytes if the SBP and LPE flags are disabled. The linux driver assumes
this behavior and allocates memory based on this assumption.

Signed-off-by: Michael Contreras 
Signed-off-by: Anthony Liguori 
---
 hw/e1000.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/hw/e1000.c b/hw/e1000.c
index cb7e7e8366..5537ad2fc4 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -59,6 +59,9 @@ static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
 #define PNPMMIO_SIZE      0x20000
 #define MIN_BUF_SIZE      60 /* Min. octets in an ethernet frame sans FCS */
 
+/* this is the size past which hardware will drop packets when setting LPE=0 */
+#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
+
 /*
  * HW models:
  *  E1000_DEV_ID_82540EM works with Windows and Linux
@@ -805,6 +808,13 @@ e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size)
         size = sizeof(min_buf);
     }
 
+    /* Discard oversized packets if !LPE and !SBP. */
+    if (size > MAXIMUM_ETHERNET_VLAN_SIZE
+        && !(s->mac_reg[RCTL] & E1000_RCTL_LPE)
+        && !(s->mac_reg[RCTL] & E1000_RCTL_SBP)) {
+        return size;
+    }
+
     if (!receive_filter(s, buf, size))
         return size;
 

From 6d6c9f59ca1b1a76ade7ad868bef191818f58819 Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Mon, 3 Dec 2012 08:02:50 -0600
Subject: [PATCH 1797/2270] Update version for 1.3.0 release

Signed-off-by: Anthony Liguori 
---
 VERSION | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/VERSION b/VERSION
index 19838b230d..f0bb29e763 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.92
+1.3.0

From 16c6c80ac3a772b42a87b77dfdf0fdac7c607b0e Mon Sep 17 00:00:00 2001
From: Anthony Liguori 
Date: Mon, 3 Dec 2012 14:08:40 -0600
Subject: [PATCH 1798/2270] Open up 1.4 development branch

Signed-off-by: Anthony Liguori 
---
 VERSION | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/VERSION b/VERSION
index f0bb29e763..52356d37e0 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.3.0
+1.3.50

From af11110bb83166473064389faa27e8c6703b2008 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Thu, 22 Nov 2012 11:34:44 +0100
Subject: [PATCH 1799/2270] apci: switch piix4 to memory api

Signed-off-by: Gerd Hoffmann 
---
 hw/acpi_piix4.c | 41 ++++++++++++++++++++++++-----------------
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 519269a013..320e045938 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -28,6 +28,7 @@
 #include "range.h"
 #include "ioport.h"
 #include "fw_cfg.h"
+#include "exec-memory.h"
 
 //#define DEBUG
 
@@ -55,7 +56,7 @@ struct pci_status {
 
 typedef struct PIIX4PMState {
     PCIDevice dev;
-    IORange ioport;
+    MemoryRegion io;
     ACPIREGS ar;
 
     APMState apm;
@@ -109,10 +110,10 @@ static void pm_tmr_timer(ACPIREGS *ar)
     pm_update_sci(s);
 }
 
-static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width,
-                            uint64_t val)
+static void pm_ioport_write(void *opaque, hwaddr addr, uint64_t val,
+                            unsigned width)
 {
-    PIIX4PMState *s = container_of(ioport, PIIX4PMState, ioport);
+    PIIX4PMState *s = opaque;
 
     if (width != 2) {
         PIIX4_DPRINTF("PM write port=0x%04x width=%d val=0x%08x\n",
@@ -138,10 +139,9 @@ static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width,
                   (unsigned int)val);
 }
 
-static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width,
-                            uint64_t *data)
+static uint64_t pm_ioport_read(void *opaque, hwaddr addr, unsigned width)
 {
-    PIIX4PMState *s = container_of(ioport, PIIX4PMState, ioport);
+    PIIX4PMState *s = opaque;
     uint32_t val;
 
     switch(addr) {
@@ -162,12 +162,17 @@ static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width,
         break;
     }
     PIIX4_DPRINTF("PM readw port=0x%04x val=0x%04x\n", (unsigned int)addr, val);
-    *data = val;
+    return val;
 }
 
-static const IORangeOps pm_iorange_ops = {
+static const MemoryRegionOps pm_io_ops = {
     .read = pm_ioport_read,
     .write = pm_ioport_write,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 4,
+    .impl.min_access_size = 1,
+    .impl.max_access_size = 4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static void apm_ctrl_changed(uint32_t val, void *arg)
@@ -193,15 +198,13 @@ static void pm_io_space_update(PIIX4PMState *s)
 {
     uint32_t pm_io_base;
 
-    if (s->dev.config[0x80] & 1) {
-        pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40));
-        pm_io_base &= 0xffc0;
+    pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40));
+    pm_io_base &= 0xffc0;
 
-        /* XXX: need to improve memory and ioport allocation */
-        PIIX4_DPRINTF("PM: mapping to 0x%x\n", pm_io_base);
-        iorange_init(&s->ioport, &pm_iorange_ops, pm_io_base, 64);
-        ioport_register(&s->ioport);
-    }
+    memory_region_transaction_begin();
+    memory_region_set_enabled(&s->io, s->dev.config[0x80] & 1);
+    memory_region_set_address(&s->io, pm_io_base);
+    memory_region_transaction_commit();
 }
 
 static void pm_write_config(PCIDevice *d,
@@ -456,6 +459,10 @@ static int piix4_pm_initfn(PCIDevice *dev)
     register_ioport_write(s->smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
     register_ioport_read(s->smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
 
+    memory_region_init_io(&s->io, &pm_io_ops, s, "piix4-pm", 64);
+    memory_region_set_enabled(&s->io, false);
+    memory_region_add_subregion(get_system_io(), 0, &s->io);
+
     acpi_pm_tmr_init(&s->ar, pm_tmr_timer);
     acpi_gpe_init(&s->ar, GPE_LEN);
 

From cacaab8bdd74608361a488aac600d609dafd53e5 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Thu, 22 Nov 2012 12:08:22 +0100
Subject: [PATCH 1800/2270] apci: switch ich9 to memory api

Signed-off-by: Gerd Hoffmann 
---
 hw/acpi_ich9.c | 44 +++++++++++++++++++++++++++-----------------
 hw/acpi_ich9.h |  1 +
 2 files changed, 28 insertions(+), 17 deletions(-)

diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index 61034d3bd7..bf361ece5d 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -29,6 +29,7 @@
 #include "sysemu.h"
 #include "acpi.h"
 #include "kvm.h"
+#include "exec-memory.h"
 
 #include "ich9.h"
 
@@ -217,30 +218,34 @@ static uint32_t pm_ioport_read_fallback(void *opaque, uint32_t addr, int len)
     return val;
 }
 
+static const MemoryRegionOps pm_io_ops = {
+    .old_portio = (MemoryRegionPortio[]) {
+        { .offset = 0, .len = ICH9_PMIO_SIZE, .size = 1,
+          .read = pm_ioport_readb, .write = pm_ioport_writeb },
+        { .offset = 0, .len = ICH9_PMIO_SIZE, .size = 2,
+          .read = pm_ioport_readw, .write = pm_ioport_writew },
+        { .offset = 0, .len = ICH9_PMIO_SIZE, .size = 4,
+          .read = pm_ioport_readl, .write = pm_ioport_writel },
+        PORTIO_END_OF_LIST(),
+    },
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 4,
+    .impl.min_access_size = 1,
+    .impl.max_access_size = 4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base)
 {
     ICH9_DEBUG("to 0x%x\n", pm_io_base);
 
     assert((pm_io_base & ICH9_PMIO_MASK) == 0);
 
-    if (pm->pm_io_base != 0) {
-        isa_unassign_ioport(pm->pm_io_base, ICH9_PMIO_SIZE);
-    }
-
-    /* don't map at 0 */
-    if (pm_io_base == 0) {
-        return;
-    }
-
-    register_ioport_write(pm_io_base, ICH9_PMIO_SIZE, 1, pm_ioport_writeb, pm);
-    register_ioport_read(pm_io_base, ICH9_PMIO_SIZE, 1, pm_ioport_readb, pm);
-    register_ioport_write(pm_io_base, ICH9_PMIO_SIZE, 2, pm_ioport_writew, pm);
-    register_ioport_read(pm_io_base, ICH9_PMIO_SIZE, 2, pm_ioport_readw, pm);
-    register_ioport_write(pm_io_base, ICH9_PMIO_SIZE, 4, pm_ioport_writel, pm);
-    register_ioport_read(pm_io_base, ICH9_PMIO_SIZE, 4, pm_ioport_readl, pm);
-
     pm->pm_io_base = pm_io_base;
-    acpi_gpe_blk(&pm->acpi_regs, pm_io_base + ICH9_PMIO_GPE0_STS);
+    memory_region_transaction_begin();
+    memory_region_set_enabled(&pm->io, pm->pm_io_base != 0);
+    memory_region_set_address(&pm->io, pm->pm_io_base);
+    memory_region_transaction_commit();
 }
 
 static int ich9_pm_post_load(void *opaque, int version_id)
@@ -311,9 +316,14 @@ static void pm_powerdown_req(Notifier *n, void *opaque)
 
 void ich9_pm_init(ICH9LPCPMRegs *pm, qemu_irq sci_irq, qemu_irq cmos_s3)
 {
+    memory_region_init_io(&pm->io, &pm_io_ops, pm, "ich9-pm", ICH9_PMIO_SIZE);
+    memory_region_set_enabled(&pm->io, false);
+    memory_region_add_subregion(get_system_io(), 0, &pm->io);
+
     acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn);
     acpi_pm1_cnt_init(&pm->acpi_regs);
     acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
+    acpi_gpe_blk(&pm->acpi_regs, ICH9_PMIO_GPE0_STS);
 
     pm->irq = sci_irq;
     qemu_register_reset(pm_reset, pm);
diff --git a/hw/acpi_ich9.h b/hw/acpi_ich9.h
index 180c40673b..0a2ee6c83d 100644
--- a/hw/acpi_ich9.h
+++ b/hw/acpi_ich9.h
@@ -30,6 +30,7 @@ typedef struct ICH9LPCPMRegs {
      * PM1a_CNT_BLK = 2 in FADT so it is defined as uint16_t.
      */
     ACPIREGS acpi_regs;
+    MemoryRegion io;
     uint32_t smi_en;
     uint32_t smi_sts;
 

From a29028214c1d5d3571b27e6745f14534e6d8a662 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Fri, 23 Nov 2012 08:29:27 +0100
Subject: [PATCH 1801/2270] apci: switch vt82c686 to memory api

Signed-off-by: Gerd Hoffmann 
---
 hw/vt82c686.c | 37 +++++++++++++++++++++++++++----------
 1 file changed, 27 insertions(+), 10 deletions(-)

diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 5d7c00cf4b..3fc6063d7d 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -24,6 +24,7 @@
 #include "pm_smbus.h"
 #include "sysemu.h"
 #include "qemu-timer.h"
+#include "exec-memory.h"
 
 typedef uint32_t pci_addr_t;
 #include "pci_host.h"
@@ -159,6 +160,7 @@ static void vt82c686b_write_config(PCIDevice * d, uint32_t address,
 
 typedef struct VT686PMState {
     PCIDevice dev;
+    MemoryRegion io;
     ACPIREGS ar;
     APMState apm;
     PMSMBus smb;
@@ -266,21 +268,32 @@ static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
     return val;
 }
 
+static const MemoryRegionOps pm_io_ops = {
+    .old_portio = (MemoryRegionPortio[]) {
+        { .offset = 0, .len = 64, .size = 2,
+          .read = pm_ioport_readw, .write = pm_ioport_writew },
+        { .offset = 0, .len = 64, .size = 4,
+          .read = pm_ioport_readl, .write = pm_ioport_writel },
+        PORTIO_END_OF_LIST(),
+    },
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 4,
+    .impl.min_access_size = 1,
+    .impl.max_access_size = 4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 static void pm_io_space_update(VT686PMState *s)
 {
     uint32_t pm_io_base;
 
-    if (s->dev.config[0x80] & 1) {
-        pm_io_base = pci_get_long(s->dev.config + 0x40);
-        pm_io_base &= 0xffc0;
+    pm_io_base = pci_get_long(s->dev.config + 0x40);
+    pm_io_base &= 0xffc0;
 
-        /* XXX: need to improve memory and ioport allocation */
-        DPRINTF("PM: mapping to 0x%x\n", pm_io_base);
-        register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s);
-        register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s);
-        register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s);
-        register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s);
-    }
+    memory_region_transaction_begin();
+    memory_region_set_enabled(&s->io, s->dev.config[0x80] & 1);
+    memory_region_set_address(&s->io, pm_io_base);
+    memory_region_transaction_commit();
 }
 
 static void pm_write_config(PCIDevice *d,
@@ -429,6 +442,10 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
 
     apm_init(&s->apm, NULL, s);
 
+    memory_region_init_io(&s->io, &pm_io_ops, s, "vt82c686-pm", 64);
+    memory_region_set_enabled(&s->io, false);
+    memory_region_add_subregion(get_system_io(), 0, &s->io);
+
     acpi_pm_tmr_init(&s->ar, pm_tmr_timer);
     acpi_pm1_cnt_init(&s->ar);
 

From 77d58b1e47c8d1c661f98f12b47ab519d3561488 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Thu, 22 Nov 2012 12:12:30 +0100
Subject: [PATCH 1802/2270] apci: switch timer to memory api

Signed-off-by: Gerd Hoffmann 
---
 hw/acpi.c       | 19 +++++++++++++++++--
 hw/acpi.h       |  5 +++--
 hw/acpi_ich9.c  |  5 +----
 hw/acpi_piix4.c |  5 +----
 hw/vt82c686.c   |  6 +-----
 5 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/hw/acpi.c b/hw/acpi.c
index f4aca493fc..ba25c23bed 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -331,7 +331,7 @@ void acpi_pm_tmr_calc_overflow_time(ACPIREGS *ar)
     ar->tmr.overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
 }
 
-uint32_t acpi_pm_tmr_get(ACPIREGS *ar)
+static uint32_t acpi_pm_tmr_get(ACPIREGS *ar)
 {
     uint32_t d = acpi_pm_tmr_get_clock();
     return d & 0xffffff;
@@ -344,10 +344,25 @@ static void acpi_pm_tmr_timer(void *opaque)
     ar->tmr.update_sci(ar);
 }
 
-void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci)
+static uint64_t acpi_pm_tmr_read(void *opaque, hwaddr addr, unsigned width)
+{
+    return acpi_pm_tmr_get(opaque);
+}
+
+static const MemoryRegionOps acpi_pm_tmr_ops = {
+    .read = acpi_pm_tmr_read,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci,
+                      MemoryRegion *parent)
 {
     ar->tmr.update_sci = update_sci;
     ar->tmr.timer = qemu_new_timer_ns(vm_clock, acpi_pm_tmr_timer, ar);
+    memory_region_init_io(&ar->tmr.io, &acpi_pm_tmr_ops, ar, "acpi-tmr", 4);
+    memory_region_add_subregion(parent, 8, &ar->tmr.io);
 }
 
 void acpi_pm_tmr_reset(ACPIREGS *ar)
diff --git a/hw/acpi.h b/hw/acpi.h
index 7337f41857..91f42c3db1 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -84,6 +84,7 @@ typedef void (*acpi_update_sci_fn)(ACPIREGS *ar);
 
 struct ACPIPMTimer {
     QEMUTimer *timer;
+    MemoryRegion io;
     int64_t overflow_time;
 
     acpi_update_sci_fn update_sci;
@@ -119,8 +120,8 @@ struct ACPIREGS {
 /* PM_TMR */
 void acpi_pm_tmr_update(ACPIREGS *ar, bool enable);
 void acpi_pm_tmr_calc_overflow_time(ACPIREGS *ar);
-uint32_t acpi_pm_tmr_get(ACPIREGS *ar);
-void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci);
+void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci,
+                      MemoryRegion *parent);
 void acpi_pm_tmr_reset(ACPIREGS *ar);
 
 #include "qemu-timer.h"
diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index bf361ece5d..ec6d5f2b5a 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -170,9 +170,6 @@ static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
     uint32_t val;
 
     switch (addr & ICH9_PMIO_MASK) {
-    case ICH9_PMIO_PM1_TMR:
-        val = acpi_pm_tmr_get(&pm->acpi_regs);
-        break;
     case ICH9_PMIO_SMI_EN:
         val = pm->smi_en;
         break;
@@ -320,7 +317,7 @@ void ich9_pm_init(ICH9LPCPMRegs *pm, qemu_irq sci_irq, qemu_irq cmos_s3)
     memory_region_set_enabled(&pm->io, false);
     memory_region_add_subregion(get_system_io(), 0, &pm->io);
 
-    acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn);
+    acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
     acpi_pm1_cnt_init(&pm->acpi_regs);
     acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
     acpi_gpe_blk(&pm->acpi_regs, ICH9_PMIO_GPE0_STS);
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 320e045938..75761a08a7 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -154,9 +154,6 @@ static uint64_t pm_ioport_read(void *opaque, hwaddr addr, unsigned width)
     case 0x04:
         val = s->ar.pm1.cnt.cnt;
         break;
-    case 0x08:
-        val = acpi_pm_tmr_get(&s->ar);
-        break;
     default:
         val = 0;
         break;
@@ -463,7 +460,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
     memory_region_set_enabled(&s->io, false);
     memory_region_add_subregion(get_system_io(), 0, &s->io);
 
-    acpi_pm_tmr_init(&s->ar, pm_tmr_timer);
+    acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
     acpi_gpe_init(&s->ar, GPE_LEN);
 
     s->powerdown_notifier.notify = piix4_pm_powerdown_req;
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 3fc6063d7d..219cfaec72 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -252,14 +252,10 @@ static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
 
 static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
 {
-    VT686PMState *s = opaque;
     uint32_t val;
 
     addr &= 0x0f;
     switch (addr) {
-    case 0x08:
-        val = acpi_pm_tmr_get(&s->ar);
-        break;
     default:
         val = 0;
         break;
@@ -446,7 +442,7 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
     memory_region_set_enabled(&s->io, false);
     memory_region_add_subregion(get_system_io(), 0, &s->io);
 
-    acpi_pm_tmr_init(&s->ar, pm_tmr_timer);
+    acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
     acpi_pm1_cnt_init(&s->ar);
 
     pm_smbus_init(&s->dev.qdev, &s->smb);

From afafe4bbe0cf7d3318e1ac7b40925561f86a6bd4 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Thu, 22 Nov 2012 13:17:57 +0100
Subject: [PATCH 1803/2270] apci: switch cnt to memory api

Signed-off-by: Gerd Hoffmann 
---
 hw/acpi.c       | 38 ++++++++++++++++++++++++++++++--------
 hw/acpi.h       |  5 +++--
 hw/acpi_ich9.c  |  8 +-------
 hw/acpi_piix4.c |  8 +-------
 hw/vt82c686.c   |  8 +-------
 5 files changed, 36 insertions(+), 31 deletions(-)

diff --git a/hw/acpi.c b/hw/acpi.c
index ba25c23bed..956db95be4 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -372,13 +372,7 @@ void acpi_pm_tmr_reset(ACPIREGS *ar)
 }
 
 /* ACPI PM1aCNT */
-void acpi_pm1_cnt_init(ACPIREGS *ar)
-{
-    ar->wakeup.notify = acpi_notify_wakeup;
-    qemu_register_wakeup_notifier(&ar->wakeup);
-}
-
-void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val, char s4)
+static void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val)
 {
     ar->pm1.cnt.cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
 
@@ -393,7 +387,7 @@ void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val, char s4)
             qemu_system_suspend_request();
             break;
         default:
-            if (sus_typ == s4) { /* S4 request */
+            if (sus_typ == ar->pm1.cnt.s4_val) { /* S4 request */
                 monitor_protocol_event(QEVENT_SUSPEND_DISK, NULL);
                 qemu_system_shutdown_request();
             }
@@ -413,6 +407,34 @@ void acpi_pm1_cnt_update(ACPIREGS *ar,
     }
 }
 
+static uint64_t acpi_pm_cnt_read(void *opaque, hwaddr addr, unsigned width)
+{
+    ACPIREGS *ar = opaque;
+    return ar->pm1.cnt.cnt;
+}
+
+static void acpi_pm_cnt_write(void *opaque, hwaddr addr, uint64_t val,
+                              unsigned width)
+{
+    acpi_pm1_cnt_write(opaque, val);
+}
+
+static const MemoryRegionOps acpi_pm_cnt_ops = {
+    .read = acpi_pm_cnt_read,
+    .write = acpi_pm_cnt_write,
+    .valid.min_access_size = 2,
+    .valid.max_access_size = 2,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent)
+{
+    ar->wakeup.notify = acpi_notify_wakeup;
+    qemu_register_wakeup_notifier(&ar->wakeup);
+    memory_region_init_io(&ar->pm1.cnt.io, &acpi_pm_cnt_ops, ar, "acpi-cnt", 2);
+    memory_region_add_subregion(parent, 4, &ar->pm1.cnt.io);
+}
+
 void acpi_pm1_cnt_reset(ACPIREGS *ar)
 {
     ar->pm1.cnt.cnt = 0;
diff --git a/hw/acpi.h b/hw/acpi.h
index 91f42c3db1..97aaab847c 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -96,7 +96,9 @@ struct ACPIPM1EVT {
 };
 
 struct ACPIPM1CNT {
+    MemoryRegion io;
     uint16_t cnt;
+    uint8_t s4_val;
 };
 
 struct ACPIGPE {
@@ -139,8 +141,7 @@ void acpi_pm1_evt_power_down(ACPIREGS *ar);
 void acpi_pm1_evt_reset(ACPIREGS *ar);
 
 /* PM1a_CNT: piix and ich9 don't implement PM1b CNT. */
-void acpi_pm1_cnt_init(ACPIREGS *ar);
-void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val, char s4);
+void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent);
 void acpi_pm1_cnt_update(ACPIREGS *ar,
                          bool sci_enable, bool sci_disable);
 void acpi_pm1_cnt_reset(ACPIREGS *ar);
diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index ec6d5f2b5a..7b6c2ef4dc 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -116,9 +116,6 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
         pm->acpi_regs.pm1.evt.en = val;
         pm_update_sci(pm);
         break;
-    case ICH9_PMIO_PM1_CNT:
-        acpi_pm1_cnt_write(&pm->acpi_regs, val, 0);
-        break;
     default:
         pm_ioport_write_fallback(opaque, addr, 2, val);
         break;
@@ -138,9 +135,6 @@ static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
     case ICH9_PMIO_PM1_EN:
         val = pm->acpi_regs.pm1.evt.en;
         break;
-    case ICH9_PMIO_PM1_CNT:
-        val = pm->acpi_regs.pm1.cnt.cnt;
-        break;
     default:
         val = pm_ioport_read_fallback(opaque, addr, 2);
         break;
@@ -318,7 +312,7 @@ void ich9_pm_init(ICH9LPCPMRegs *pm, qemu_irq sci_irq, qemu_irq cmos_s3)
     memory_region_add_subregion(get_system_io(), 0, &pm->io);
 
     acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
-    acpi_pm1_cnt_init(&pm->acpi_regs);
+    acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io);
     acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
     acpi_gpe_blk(&pm->acpi_regs, ICH9_PMIO_GPE0_STS);
 
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 75761a08a7..9d5e346ef3 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -129,9 +129,6 @@ static void pm_ioport_write(void *opaque, hwaddr addr, uint64_t val,
         acpi_pm1_evt_write_en(&s->ar, val);
         pm_update_sci(s);
         break;
-    case 0x04:
-        acpi_pm1_cnt_write(&s->ar, val, s->s4_val);
-        break;
     default:
         break;
     }
@@ -151,9 +148,6 @@ static uint64_t pm_ioport_read(void *opaque, hwaddr addr, unsigned width)
     case 0x02:
         val = s->ar.pm1.evt.en;
         break;
-    case 0x04:
-        val = s->ar.pm1.cnt.cnt;
-        break;
     default:
         val = 0;
         break;
@@ -461,6 +455,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
     memory_region_add_subregion(get_system_io(), 0, &s->io);
 
     acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
+    acpi_pm1_cnt_init(&s->ar, &s->io);
     acpi_gpe_init(&s->ar, GPE_LEN);
 
     s->powerdown_notifier.notify = piix4_pm_powerdown_req;
@@ -487,7 +482,6 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
 
     s = DO_UPCAST(PIIX4PMState, dev, dev);
     s->irq = sci_irq;
-    acpi_pm1_cnt_init(&s->ar);
     s->smi_irq = smi_irq;
     s->kvm_enabled = kvm_enabled;
 
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 219cfaec72..15f0b6a91c 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -211,9 +211,6 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
         acpi_pm1_evt_write_en(&s->ar, val);
         pm_update_sci(s);
         break;
-    case 0x04:
-        acpi_pm1_cnt_write(&s->ar, val, 0);
-        break;
     default:
         break;
     }
@@ -233,9 +230,6 @@ static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
     case 0x02:
         val = s->ar.pm1.evt.en;
         break;
-    case 0x04:
-        val = s->ar.pm1.cnt.cnt;
-        break;
     default:
         val = 0;
         break;
@@ -443,7 +437,7 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
     memory_region_add_subregion(get_system_io(), 0, &s->io);
 
     acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
-    acpi_pm1_cnt_init(&s->ar);
+    acpi_pm1_cnt_init(&s->ar, &s->io);
 
     pm_smbus_init(&s->dev.qdev, &s->smb);
 

From b5a7c024d2606e84e0bbe4a0e87d252dfda41479 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Thu, 22 Nov 2012 13:25:10 +0100
Subject: [PATCH 1804/2270] apci: switch evt to memory api

Signed-off-by: Gerd Hoffmann 
---
 hw/acpi.c       | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
 hw/acpi.h       |  6 ++++--
 hw/acpi_ich9.c  | 18 +-----------------
 hw/acpi_piix4.c | 18 +-----------------
 hw/vt82c686.c   | 18 +-----------------
 5 files changed, 54 insertions(+), 55 deletions(-)

diff --git a/hw/acpi.c b/hw/acpi.c
index 956db95be4..e58e45f301 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -275,7 +275,7 @@ uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar)
     return ar->pm1.evt.sts;
 }
 
-void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val)
+static void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val)
 {
     uint16_t pm1_sts = acpi_pm1_evt_get_sts(ar);
     if (pm1_sts & val & ACPI_BITMASK_TIMER_STATUS) {
@@ -285,7 +285,7 @@ void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val)
     ar->pm1.evt.sts &= ~val;
 }
 
-void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val)
+static void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val)
 {
     ar->pm1.evt.en = val;
     qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_RTC,
@@ -310,6 +310,51 @@ void acpi_pm1_evt_reset(ACPIREGS *ar)
     qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_PMTIMER, 0);
 }
 
+static uint64_t acpi_pm_evt_read(void *opaque, hwaddr addr, unsigned width)
+{
+    ACPIREGS *ar = opaque;
+    switch (addr) {
+    case 0:
+        return acpi_pm1_evt_get_sts(ar);
+    case 2:
+        return ar->pm1.evt.en;
+    default:
+        return 0;
+    }
+}
+
+static void acpi_pm_evt_write(void *opaque, hwaddr addr, uint64_t val,
+                              unsigned width)
+{
+    ACPIREGS *ar = opaque;
+    switch (addr) {
+    case 0:
+        acpi_pm1_evt_write_sts(ar, val);
+        ar->pm1.evt.update_sci(ar);
+        break;
+    case 2:
+        acpi_pm1_evt_write_en(ar, val);
+        ar->pm1.evt.update_sci(ar);
+        break;
+    }
+}
+
+static const MemoryRegionOps acpi_pm_evt_ops = {
+    .read = acpi_pm_evt_read,
+    .write = acpi_pm_evt_write,
+    .valid.min_access_size = 2,
+    .valid.max_access_size = 2,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+void acpi_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci,
+                       MemoryRegion *parent)
+{
+    ar->pm1.evt.update_sci = update_sci;
+    memory_region_init_io(&ar->pm1.evt.io, &acpi_pm_evt_ops, ar, "acpi-evt", 4);
+    memory_region_add_subregion(parent, 0, &ar->pm1.evt.io);
+}
+
 /* ACPI PM_TMR */
 void acpi_pm_tmr_update(ACPIREGS *ar, bool enable)
 {
diff --git a/hw/acpi.h b/hw/acpi.h
index 97aaab847c..918d7f5bca 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -91,8 +91,10 @@ struct ACPIPMTimer {
 };
 
 struct ACPIPM1EVT {
+    MemoryRegion io;
     uint16_t sts;
     uint16_t en;
+    acpi_update_sci_fn update_sci;
 };
 
 struct ACPIPM1CNT {
@@ -135,10 +137,10 @@ static inline int64_t acpi_pm_tmr_get_clock(void)
 
 /* PM1a_EVT: piix and ich9 don't implement PM1b. */
 uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar);
-void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val);
-void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val);
 void acpi_pm1_evt_power_down(ACPIREGS *ar);
 void acpi_pm1_evt_reset(ACPIREGS *ar);
+void acpi_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci,
+                       MemoryRegion *parent);
 
 /* PM1a_CNT: piix and ich9 don't implement PM1b CNT. */
 void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent);
diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index 7b6c2ef4dc..3b5bac6d49 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -105,17 +105,7 @@ static uint32_t pm_ioport_readb(void *opaque, uint32_t addr)
 
 static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
 {
-    ICH9LPCPMRegs *pm = opaque;
-
     switch (addr & ICH9_PMIO_MASK) {
-    case ICH9_PMIO_PM1_STS:
-        acpi_pm1_evt_write_sts(&pm->acpi_regs, val);
-        pm_update_sci(pm);
-        break;
-    case ICH9_PMIO_PM1_EN:
-        pm->acpi_regs.pm1.evt.en = val;
-        pm_update_sci(pm);
-        break;
     default:
         pm_ioport_write_fallback(opaque, addr, 2, val);
         break;
@@ -125,16 +115,9 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
 
 static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
 {
-    ICH9LPCPMRegs *pm = opaque;
     uint32_t val;
 
     switch (addr & ICH9_PMIO_MASK) {
-    case ICH9_PMIO_PM1_STS:
-        val = acpi_pm1_evt_get_sts(&pm->acpi_regs);
-        break;
-    case ICH9_PMIO_PM1_EN:
-        val = pm->acpi_regs.pm1.evt.en;
-        break;
     default:
         val = pm_ioport_read_fallback(opaque, addr, 2);
         break;
@@ -312,6 +295,7 @@ void ich9_pm_init(ICH9LPCPMRegs *pm, qemu_irq sci_irq, qemu_irq cmos_s3)
     memory_region_add_subregion(get_system_io(), 0, &pm->io);
 
     acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
+    acpi_pm1_evt_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
     acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io);
     acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
     acpi_gpe_blk(&pm->acpi_regs, ICH9_PMIO_GPE0_STS);
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 9d5e346ef3..d4e28c4fff 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -113,22 +113,12 @@ static void pm_tmr_timer(ACPIREGS *ar)
 static void pm_ioport_write(void *opaque, hwaddr addr, uint64_t val,
                             unsigned width)
 {
-    PIIX4PMState *s = opaque;
-
     if (width != 2) {
         PIIX4_DPRINTF("PM write port=0x%04x width=%d val=0x%08x\n",
                       (unsigned)addr, width, (unsigned)val);
     }
 
     switch(addr) {
-    case 0x00:
-        acpi_pm1_evt_write_sts(&s->ar, val);
-        pm_update_sci(s);
-        break;
-    case 0x02:
-        acpi_pm1_evt_write_en(&s->ar, val);
-        pm_update_sci(s);
-        break;
     default:
         break;
     }
@@ -138,16 +128,9 @@ static void pm_ioport_write(void *opaque, hwaddr addr, uint64_t val,
 
 static uint64_t pm_ioport_read(void *opaque, hwaddr addr, unsigned width)
 {
-    PIIX4PMState *s = opaque;
     uint32_t val;
 
     switch(addr) {
-    case 0x00:
-        val = acpi_pm1_evt_get_sts(&s->ar);
-        break;
-    case 0x02:
-        val = s->ar.pm1.evt.en;
-        break;
     default:
         val = 0;
         break;
@@ -455,6 +438,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
     memory_region_add_subregion(get_system_io(), 0, &s->io);
 
     acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
+    acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
     acpi_pm1_cnt_init(&s->ar, &s->io);
     acpi_gpe_init(&s->ar, GPE_LEN);
 
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 15f0b6a91c..52f46f10ce 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -199,18 +199,8 @@ static void pm_tmr_timer(ACPIREGS *ar)
 
 static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
 {
-    VT686PMState *s = opaque;
-
     addr &= 0x0f;
     switch (addr) {
-    case 0x00:
-        acpi_pm1_evt_write_sts(&s->ar, val);
-        pm_update_sci(s);
-        break;
-    case 0x02:
-        acpi_pm1_evt_write_en(&s->ar, val);
-        pm_update_sci(s);
-        break;
     default:
         break;
     }
@@ -219,17 +209,10 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
 
 static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
 {
-    VT686PMState *s = opaque;
     uint32_t val;
 
     addr &= 0x0f;
     switch (addr) {
-    case 0x00:
-        val = acpi_pm1_evt_get_sts(&s->ar);
-        break;
-    case 0x02:
-        val = s->ar.pm1.evt.en;
-        break;
     default:
         val = 0;
         break;
@@ -437,6 +420,7 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
     memory_region_add_subregion(get_system_io(), 0, &s->io);
 
     acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
+    acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
     acpi_pm1_cnt_init(&s->ar, &s->io);
 
     pm_smbus_init(&s->dev.qdev, &s->smb);

From ca5d64b4b4fbb01e403f89ec9b399aaa69104b1e Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Thu, 22 Nov 2012 13:27:04 +0100
Subject: [PATCH 1805/2270] acpi: cleanup piix4 memory region

Nothing left to do, everything handled by subregions,
we can zap the reaw/write handlers now.

Signed-off-by: Gerd Hoffmann 
---
 hw/acpi_piix4.c | 41 +----------------------------------------
 1 file changed, 1 insertion(+), 40 deletions(-)

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index d4e28c4fff..cf8aa3d7d7 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -110,45 +110,6 @@ static void pm_tmr_timer(ACPIREGS *ar)
     pm_update_sci(s);
 }
 
-static void pm_ioport_write(void *opaque, hwaddr addr, uint64_t val,
-                            unsigned width)
-{
-    if (width != 2) {
-        PIIX4_DPRINTF("PM write port=0x%04x width=%d val=0x%08x\n",
-                      (unsigned)addr, width, (unsigned)val);
-    }
-
-    switch(addr) {
-    default:
-        break;
-    }
-    PIIX4_DPRINTF("PM writew port=0x%04x val=0x%04x\n", (unsigned int)addr,
-                  (unsigned int)val);
-}
-
-static uint64_t pm_ioport_read(void *opaque, hwaddr addr, unsigned width)
-{
-    uint32_t val;
-
-    switch(addr) {
-    default:
-        val = 0;
-        break;
-    }
-    PIIX4_DPRINTF("PM readw port=0x%04x val=0x%04x\n", (unsigned int)addr, val);
-    return val;
-}
-
-static const MemoryRegionOps pm_io_ops = {
-    .read = pm_ioport_read,
-    .write = pm_ioport_write,
-    .valid.min_access_size = 1,
-    .valid.max_access_size = 4,
-    .impl.min_access_size = 1,
-    .impl.max_access_size = 4,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
 static void apm_ctrl_changed(uint32_t val, void *arg)
 {
     PIIX4PMState *s = arg;
@@ -433,7 +394,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
     register_ioport_write(s->smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
     register_ioport_read(s->smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
 
-    memory_region_init_io(&s->io, &pm_io_ops, s, "piix4-pm", 64);
+    memory_region_init(&s->io, "piix4-pm", 64);
     memory_region_set_enabled(&s->io, false);
     memory_region_add_subregion(get_system_io(), 0, &s->io);
 

From a0f95659da77c8818ebd146bb1546ad152d0833e Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Fri, 23 Nov 2012 09:00:25 +0100
Subject: [PATCH 1806/2270] acpi: cleanup vt82c686 memory region

Nothing left to do, everything handled by subregions,
we can zap the reaw/write handlers now.

Signed-off-by: Gerd Hoffmann 
---
 hw/vt82c686.c | 61 +--------------------------------------------------
 1 file changed, 1 insertion(+), 60 deletions(-)

diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 52f46f10ce..99e6b2f9a9 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -197,65 +197,6 @@ static void pm_tmr_timer(ACPIREGS *ar)
     pm_update_sci(s);
 }
 
-static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
-{
-    addr &= 0x0f;
-    switch (addr) {
-    default:
-        break;
-    }
-    DPRINTF("PM writew port=0x%04x val=0x%02x\n", addr, val);
-}
-
-static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
-{
-    uint32_t val;
-
-    addr &= 0x0f;
-    switch (addr) {
-    default:
-        val = 0;
-        break;
-    }
-    DPRINTF("PM readw port=0x%04x val=0x%02x\n", addr, val);
-    return val;
-}
-
-static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
-{
-    addr &= 0x0f;
-    DPRINTF("PM writel port=0x%04x val=0x%08x\n", addr, val);
-}
-
-static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
-{
-    uint32_t val;
-
-    addr &= 0x0f;
-    switch (addr) {
-    default:
-        val = 0;
-        break;
-    }
-    DPRINTF("PM readl port=0x%04x val=0x%08x\n", addr, val);
-    return val;
-}
-
-static const MemoryRegionOps pm_io_ops = {
-    .old_portio = (MemoryRegionPortio[]) {
-        { .offset = 0, .len = 64, .size = 2,
-          .read = pm_ioport_readw, .write = pm_ioport_writew },
-        { .offset = 0, .len = 64, .size = 4,
-          .read = pm_ioport_readl, .write = pm_ioport_writel },
-        PORTIO_END_OF_LIST(),
-    },
-    .valid.min_access_size = 1,
-    .valid.max_access_size = 4,
-    .impl.min_access_size = 1,
-    .impl.max_access_size = 4,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
 static void pm_io_space_update(VT686PMState *s)
 {
     uint32_t pm_io_base;
@@ -415,7 +356,7 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
 
     apm_init(&s->apm, NULL, s);
 
-    memory_region_init_io(&s->io, &pm_io_ops, s, "vt82c686-pm", 64);
+    memory_region_init(&s->io, "vt82c686-pm", 64);
     memory_region_set_enabled(&s->io, false);
     memory_region_add_subregion(get_system_io(), 0, &s->io);
 

From 76a7daf97458c55b8d8e6d4eadc5c46b16c705ce Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Thu, 22 Nov 2012 13:43:17 +0100
Subject: [PATCH 1807/2270] apci: switch ich9 gpe to memory api

Signed-off-by: Gerd Hoffmann 
---
 hw/acpi_ich9.c | 38 ++++++++++++++++++++++++++++----------
 hw/acpi_ich9.h |  1 +
 2 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index 3b5bac6d49..5fc160a971 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -73,12 +73,7 @@ static void ich9_pm_update_sci_fn(ACPIREGS *regs)
 
 static void pm_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
 {
-    ICH9LPCPMRegs *pm = opaque;
-
     switch (addr & ICH9_PMIO_MASK) {
-    case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + ICH9_PMIO_GPE0_LEN - 1):
-        acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val);
-        break;
     default:
         break;
     }
@@ -88,13 +83,9 @@ static void pm_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
 
 static uint32_t pm_ioport_readb(void *opaque, uint32_t addr)
 {
-    ICH9LPCPMRegs *pm = opaque;
     uint32_t val = 0;
 
     switch (addr & ICH9_PMIO_MASK) {
-    case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + ICH9_PMIO_GPE0_LEN - 1):
-        val = acpi_gpe_ioport_readb(&pm->acpi_regs, addr);
-        break;
     default:
         val = 0;
         break;
@@ -209,6 +200,29 @@ static const MemoryRegionOps pm_io_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
+static uint64_t ich9_gpe_readb(void *opaque, hwaddr addr, unsigned width)
+{
+    ICH9LPCPMRegs *pm = opaque;
+    return acpi_gpe_ioport_readb(&pm->acpi_regs, addr);
+}
+
+static void ich9_gpe_writeb(void *opaque, hwaddr addr, uint64_t val,
+                            unsigned width)
+{
+    ICH9LPCPMRegs *pm = opaque;
+    acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val);
+}
+
+static const MemoryRegionOps ich9_gpe_ops = {
+    .read = ich9_gpe_readb,
+    .write = ich9_gpe_writeb,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 4,
+    .impl.min_access_size = 1,
+    .impl.max_access_size = 1,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base)
 {
     ICH9_DEBUG("to 0x%x\n", pm_io_base);
@@ -297,8 +311,12 @@ void ich9_pm_init(ICH9LPCPMRegs *pm, qemu_irq sci_irq, qemu_irq cmos_s3)
     acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
     acpi_pm1_evt_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
     acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io);
+
     acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
-    acpi_gpe_blk(&pm->acpi_regs, ICH9_PMIO_GPE0_STS);
+    acpi_gpe_blk(&pm->acpi_regs, 0);
+    memory_region_init_io(&pm->io_gpe, &ich9_gpe_ops, pm, "apci-gpe0",
+                          ICH9_PMIO_GPE0_LEN);
+    memory_region_add_subregion(&pm->io, ICH9_PMIO_GPE0_STS, &pm->io_gpe);
 
     pm->irq = sci_irq;
     qemu_register_reset(pm_reset, pm);
diff --git a/hw/acpi_ich9.h b/hw/acpi_ich9.h
index 0a2ee6c83d..f3b05d7229 100644
--- a/hw/acpi_ich9.h
+++ b/hw/acpi_ich9.h
@@ -31,6 +31,7 @@ typedef struct ICH9LPCPMRegs {
      */
     ACPIREGS acpi_regs;
     MemoryRegion io;
+    MemoryRegion io_gpe;
     uint32_t smi_en;
     uint32_t smi_sts;
 

From 10cc69b0de8e1756e6fbda4592c9d0ba3bce58fc Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Thu, 22 Nov 2012 13:51:35 +0100
Subject: [PATCH 1808/2270] apci: switch ich9 smi to memory api

Signed-off-by: Gerd Hoffmann 
---
 hw/acpi_ich9.c | 46 ++++++++++++++++++++++++++++++++++++----------
 hw/acpi_ich9.h |  1 +
 2 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index 5fc160a971..0ed17da1eb 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -119,12 +119,7 @@ static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
 
 static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
 {
-    ICH9LPCPMRegs *pm = opaque;
-
     switch (addr & ICH9_PMIO_MASK) {
-    case ICH9_PMIO_SMI_EN:
-        pm->smi_en = val;
-        break;
     default:
         pm_ioport_write_fallback(opaque, addr, 4, val);
         break;
@@ -134,14 +129,9 @@ static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
 
 static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
 {
-    ICH9LPCPMRegs *pm = opaque;
     uint32_t val;
 
     switch (addr & ICH9_PMIO_MASK) {
-    case ICH9_PMIO_SMI_EN:
-        val = pm->smi_en;
-        break;
-
     default:
         val = pm_ioport_read_fallback(opaque, addr, 4);
         break;
@@ -223,6 +213,38 @@ static const MemoryRegionOps ich9_gpe_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
+static uint64_t ich9_smi_readl(void *opaque, hwaddr addr, unsigned width)
+{
+    ICH9LPCPMRegs *pm = opaque;
+    switch (addr) {
+    case 0:
+        return pm->smi_en;
+    case 4:
+        return pm->smi_sts;
+    default:
+        return 0;
+    }
+}
+
+static void ich9_smi_writel(void *opaque, hwaddr addr, uint64_t val,
+                            unsigned width)
+{
+    ICH9LPCPMRegs *pm = opaque;
+    switch (addr) {
+    case 0:
+        pm->smi_en = val;
+        break;
+    }
+}
+
+static const MemoryRegionOps ich9_smi_ops = {
+    .read = ich9_smi_readl,
+    .write = ich9_smi_writel,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base)
 {
     ICH9_DEBUG("to 0x%x\n", pm_io_base);
@@ -318,6 +340,10 @@ void ich9_pm_init(ICH9LPCPMRegs *pm, qemu_irq sci_irq, qemu_irq cmos_s3)
                           ICH9_PMIO_GPE0_LEN);
     memory_region_add_subregion(&pm->io, ICH9_PMIO_GPE0_STS, &pm->io_gpe);
 
+    memory_region_init_io(&pm->io_smi, &ich9_smi_ops, pm, "apci-smi",
+                          8);
+    memory_region_add_subregion(&pm->io, ICH9_PMIO_SMI_EN, &pm->io_smi);
+
     pm->irq = sci_irq;
     qemu_register_reset(pm_reset, pm);
     pm->powerdown_notifier.notify = pm_powerdown_req;
diff --git a/hw/acpi_ich9.h b/hw/acpi_ich9.h
index f3b05d7229..bc221d3cbc 100644
--- a/hw/acpi_ich9.h
+++ b/hw/acpi_ich9.h
@@ -32,6 +32,7 @@ typedef struct ICH9LPCPMRegs {
     ACPIREGS acpi_regs;
     MemoryRegion io;
     MemoryRegion io_gpe;
+    MemoryRegion io_smi;
     uint32_t smi_en;
     uint32_t smi_sts;
 

From 4a522de0905c88160b6f93eb5d35883382a0c333 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Thu, 22 Nov 2012 14:01:20 +0100
Subject: [PATCH 1809/2270] acpi: cleanup ich9 memory region

Nothing left to do, everything handled by subregions,
we can zap the reaw/write handlers now.

Signed-off-by: Gerd Hoffmann 
---
 hw/acpi_ich9.c | 125 +------------------------------------------------
 1 file changed, 1 insertion(+), 124 deletions(-)

diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index 0ed17da1eb..db0d7a5063 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -42,10 +42,6 @@ do { printf("%s "fmt, __func__, ## __VA_ARGS__); } while (0)
 #define ICH9_DEBUG(fmt, ...)    do { } while (0)
 #endif
 
-static void pm_ioport_write_fallback(void *opaque, uint32_t addr, int len,
-                                     uint32_t val);
-static uint32_t pm_ioport_read_fallback(void *opaque, uint32_t addr, int len);
-
 static void pm_update_sci(ICH9LPCPMRegs *pm)
 {
     int sci_level, pm1a_sts;
@@ -71,125 +67,6 @@ static void ich9_pm_update_sci_fn(ACPIREGS *regs)
     pm_update_sci(pm);
 }
 
-static void pm_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
-    switch (addr & ICH9_PMIO_MASK) {
-    default:
-        break;
-    }
-
-    ICH9_DEBUG("port=0x%04x val=0x%04x\n", addr, val);
-}
-
-static uint32_t pm_ioport_readb(void *opaque, uint32_t addr)
-{
-    uint32_t val = 0;
-
-    switch (addr & ICH9_PMIO_MASK) {
-    default:
-        val = 0;
-        break;
-    }
-    ICH9_DEBUG("port=0x%04x val=0x%04x\n", addr, val);
-    return val;
-}
-
-static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
-{
-    switch (addr & ICH9_PMIO_MASK) {
-    default:
-        pm_ioport_write_fallback(opaque, addr, 2, val);
-        break;
-    }
-    ICH9_DEBUG("port=0x%04x val=0x%04x\n", addr, val);
-}
-
-static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
-{
-    uint32_t val;
-
-    switch (addr & ICH9_PMIO_MASK) {
-    default:
-        val = pm_ioport_read_fallback(opaque, addr, 2);
-        break;
-    }
-    ICH9_DEBUG("port=0x%04x val=0x%04x\n", addr, val);
-    return val;
-}
-
-static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
-{
-    switch (addr & ICH9_PMIO_MASK) {
-    default:
-        pm_ioport_write_fallback(opaque, addr, 4, val);
-        break;
-    }
-    ICH9_DEBUG("port=0x%04x val=0x%08x\n", addr, val);
-}
-
-static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
-{
-    uint32_t val;
-
-    switch (addr & ICH9_PMIO_MASK) {
-    default:
-        val = pm_ioport_read_fallback(opaque, addr, 4);
-        break;
-    }
-    ICH9_DEBUG("port=0x%04x val=0x%08x\n", addr, val);
-    return val;
-}
-
-static void pm_ioport_write_fallback(void *opaque, uint32_t addr, int len,
-                                     uint32_t val)
- {
-    int subsize = (len == 4) ? 2 : 1;
-    IOPortWriteFunc *ioport_write =
-        (subsize == 2) ? pm_ioport_writew : pm_ioport_writeb;
-
-    int i;
-
-    for (i = 0; i < len; i += subsize) {
-        ioport_write(opaque, addr, val);
-        val >>= 8 * subsize;
-    }
-}
-
-static uint32_t pm_ioport_read_fallback(void *opaque, uint32_t addr, int len)
-{
-    int subsize = (len == 4) ? 2 : 1;
-    IOPortReadFunc *ioport_read =
-        (subsize == 2) ? pm_ioport_readw : pm_ioport_readb;
-
-    uint32_t val;
-    int i;
-
-    val = 0;
-    for (i = 0; i < len; i += subsize) {
-        val <<= 8 * subsize;
-        val |= ioport_read(opaque, addr);
-    }
-
-    return val;
-}
-
-static const MemoryRegionOps pm_io_ops = {
-    .old_portio = (MemoryRegionPortio[]) {
-        { .offset = 0, .len = ICH9_PMIO_SIZE, .size = 1,
-          .read = pm_ioport_readb, .write = pm_ioport_writeb },
-        { .offset = 0, .len = ICH9_PMIO_SIZE, .size = 2,
-          .read = pm_ioport_readw, .write = pm_ioport_writew },
-        { .offset = 0, .len = ICH9_PMIO_SIZE, .size = 4,
-          .read = pm_ioport_readl, .write = pm_ioport_writel },
-        PORTIO_END_OF_LIST(),
-    },
-    .valid.min_access_size = 1,
-    .valid.max_access_size = 4,
-    .impl.min_access_size = 1,
-    .impl.max_access_size = 4,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
 static uint64_t ich9_gpe_readb(void *opaque, hwaddr addr, unsigned width)
 {
     ICH9LPCPMRegs *pm = opaque;
@@ -326,7 +203,7 @@ static void pm_powerdown_req(Notifier *n, void *opaque)
 
 void ich9_pm_init(ICH9LPCPMRegs *pm, qemu_irq sci_irq, qemu_irq cmos_s3)
 {
-    memory_region_init_io(&pm->io, &pm_io_ops, pm, "ich9-pm", ICH9_PMIO_SIZE);
+    memory_region_init(&pm->io, "ich9-pm", ICH9_PMIO_SIZE);
     memory_region_set_enabled(&pm->io, false);
     memory_region_add_subregion(get_system_io(), 0, &pm->io);
 

From 798512e5522685163c8d5fc5093aea19ae9cce06 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Fri, 23 Nov 2012 14:57:01 +0100
Subject: [PATCH 1810/2270] acpi: switch smbus to memory api

Signed-off-by: Gerd Hoffmann 
---
 hw/acpi_piix4.c |  5 ++---
 hw/pm_smbus.c   | 17 ++++++++++++----
 hw/pm_smbus.h   |  3 +--
 hw/smbus_ich9.c | 52 ++++++++++++++-----------------------------------
 hw/vt82c686.c   |  6 ++----
 5 files changed, 33 insertions(+), 50 deletions(-)

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index cf8aa3d7d7..9e6c97ebd3 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -391,8 +391,8 @@ static int piix4_pm_initfn(PCIDevice *dev)
     pci_conf[0x90] = s->smb_io_base | 1;
     pci_conf[0x91] = s->smb_io_base >> 8;
     pci_conf[0xd2] = 0x09;
-    register_ioport_write(s->smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
-    register_ioport_read(s->smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
+    pm_smbus_init(&s->dev.qdev, &s->smb);
+    memory_region_add_subregion(get_system_io(), s->smb_io_base, &s->smb.io);
 
     memory_region_init(&s->io, "piix4-pm", 64);
     memory_region_set_enabled(&s->io, false);
@@ -406,7 +406,6 @@ static int piix4_pm_initfn(PCIDevice *dev)
     s->powerdown_notifier.notify = piix4_pm_powerdown_req;
     qemu_register_powerdown_notifier(&s->powerdown_notifier);
 
-    pm_smbus_init(&s->dev.qdev, &s->smb);
     s->machine_ready.notify = piix4_pm_machine_ready;
     qemu_add_machine_init_done_notifier(&s->machine_ready);
     qemu_register_reset(piix4_reset, s);
diff --git a/hw/pm_smbus.c b/hw/pm_smbus.c
index 5d6046de5a..ea1380ca68 100644
--- a/hw/pm_smbus.c
+++ b/hw/pm_smbus.c
@@ -94,10 +94,11 @@ static void smb_transaction(PMSMBus *s)
     s->smb_stat |= 0x04;
 }
 
-void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
+                              unsigned width)
 {
     PMSMBus *s = opaque;
-    addr &= 0x3f;
+
     SMBUS_DPRINTF("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
     switch(addr) {
     case SMBHSTSTS:
@@ -131,12 +132,11 @@ void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
     }
 }
 
-uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
+static uint64_t smb_ioport_readb(void *opaque, hwaddr addr, unsigned width)
 {
     PMSMBus *s = opaque;
     uint32_t val;
 
-    addr &= 0x3f;
     switch(addr) {
     case SMBHSTSTS:
         val = s->smb_stat;
@@ -170,7 +170,16 @@ uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
     return val;
 }
 
+static const MemoryRegionOps pm_smbus_ops = {
+    .read = smb_ioport_readb,
+    .write = smb_ioport_writeb,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 1,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 void pm_smbus_init(DeviceState *parent, PMSMBus *smb)
 {
     smb->smbus = i2c_init_bus(parent, "i2c");
+    memory_region_init_io(&smb->io, &pm_smbus_ops, smb, "pm-smbus", 64);
 }
diff --git a/hw/pm_smbus.h b/hw/pm_smbus.h
index 4750a409f9..e3069bf7d4 100644
--- a/hw/pm_smbus.h
+++ b/hw/pm_smbus.h
@@ -3,6 +3,7 @@
 
 typedef struct PMSMBus {
     i2c_bus *smbus;
+    MemoryRegion io;
 
     uint8_t smb_stat;
     uint8_t smb_ctl;
@@ -15,7 +16,5 @@ typedef struct PMSMBus {
 } PMSMBus;
 
 void pm_smbus_init(DeviceState *parent, PMSMBus *smb);
-void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val);
-uint32_t smb_ioport_readb(void *opaque, uint32_t addr);
 
 #endif /* !PM_SMBUS_H */
diff --git a/hw/smbus_ich9.c b/hw/smbus_ich9.c
index 6940583bb6..54e7e1252d 100644
--- a/hw/smbus_ich9.c
+++ b/hw/smbus_ich9.c
@@ -40,7 +40,6 @@ typedef struct ICH9SMBState {
     PCIDevice dev;
 
     PMSMBus smb;
-    MemoryRegion mem_bar;
 } ICH9SMBState;
 
 static const VMStateDescription vmstate_ich9_smbus = {
@@ -54,42 +53,23 @@ static const VMStateDescription vmstate_ich9_smbus = {
     }
 };
 
-static void ich9_smb_ioport_writeb(void *opaque, hwaddr addr,
-                                   uint64_t val, unsigned size)
+static void ich9_smbus_write_config(PCIDevice *d, uint32_t address,
+                                    uint32_t val, int len)
 {
-    ICH9SMBState *s = opaque;
-    uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
+    ICH9SMBState *s = ICH9_SMB_DEVICE(d);
 
-    if ((hostc & ICH9_SMB_HOSTC_HST_EN) && !(hostc & ICH9_SMB_HOSTC_I2C_EN)) {
-        uint64_t offset = addr - s->dev.io_regions[ICH9_SMB_SMB_BASE_BAR].addr;
-        smb_ioport_writeb(&s->smb, offset, val);
+    pci_default_write_config(d, address, val, len);
+    if (range_covers_byte(address, len, ICH9_SMB_HOSTC)) {
+        uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
+        if ((hostc & ICH9_SMB_HOSTC_HST_EN) &&
+            !(hostc & ICH9_SMB_HOSTC_I2C_EN)) {
+            memory_region_set_enabled(&s->smb.io, true);
+        } else {
+            memory_region_set_enabled(&s->smb.io, false);
+        }
     }
 }
 
-static uint64_t ich9_smb_ioport_readb(void *opaque, hwaddr addr,
-                                      unsigned size)
-{
-    ICH9SMBState *s = opaque;
-    uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
-
-    if ((hostc & ICH9_SMB_HOSTC_HST_EN) && !(hostc & ICH9_SMB_HOSTC_I2C_EN)) {
-        uint64_t offset = addr - s->dev.io_regions[ICH9_SMB_SMB_BASE_BAR].addr;
-        return smb_ioport_readb(&s->smb, offset);
-    }
-
-    return 0xff;
-}
-
-static const MemoryRegionOps lpc_smb_mmio_ops = {
-    .read = ich9_smb_ioport_readb,
-    .write = ich9_smb_ioport_writeb,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-    .impl = {
-        .min_access_size = 1,
-        .max_access_size = 1,
-    },
-};
-
 static int ich9_smbus_initfn(PCIDevice *d)
 {
     ICH9SMBState *s = ICH9_SMB_DEVICE(d);
@@ -109,15 +89,12 @@ static int ich9_smbus_initfn(PCIDevice *d)
      * Is there any OS that depends on them?
      */
 
-    /* TODO smb_io_base */
     pci_set_byte(d->config + ICH9_SMB_HOSTC, 0);
     /* TODO bar0, bar1: 64bit BAR support*/
 
-    memory_region_init_io(&s->mem_bar, &lpc_smb_mmio_ops, s, "ich9-smbus-bar",
-                            ICH9_SMB_SMB_BASE_SIZE);
-    pci_register_bar(d, ICH9_SMB_SMB_BASE_BAR, PCI_BASE_ADDRESS_SPACE_IO,
-                        &s->mem_bar);
     pm_smbus_init(&d->qdev, &s->smb);
+    pci_register_bar(d, ICH9_SMB_SMB_BASE_BAR, PCI_BASE_ADDRESS_SPACE_IO,
+                     &s->smb.io);
     return 0;
 }
 
@@ -134,6 +111,7 @@ static void ich9_smb_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_ich9_smbus;
     dc->desc = "ICH9 SMBUS Bridge";
     k->init = ich9_smbus_initfn;
+    k->config_write = ich9_smbus_write_config;
 }
 
 i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base)
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 99e6b2f9a9..5016e954d3 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -351,8 +351,8 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
     pci_conf[0x90] = s->smb_io_base | 1;
     pci_conf[0x91] = s->smb_io_base >> 8;
     pci_conf[0xd2] = 0x90;
-    register_ioport_write(s->smb_io_base, 0xf, 1, smb_ioport_writeb, &s->smb);
-    register_ioport_read(s->smb_io_base, 0xf, 1, smb_ioport_readb, &s->smb);
+    pm_smbus_init(&s->dev.qdev, &s->smb);
+    memory_region_add_subregion(get_system_io(), s->smb_io_base, &s->smb.io);
 
     apm_init(&s->apm, NULL, s);
 
@@ -364,8 +364,6 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
     acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
     acpi_pm1_cnt_init(&s->ar, &s->io);
 
-    pm_smbus_init(&s->dev.qdev, &s->smb);
-
     return 0;
 }
 

From 24fe083de67e0f736c54da4abda05f23ec37c51d Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Fri, 23 Nov 2012 14:58:04 +0100
Subject: [PATCH 1811/2270] acpi: fix piix4 smbus mapping

Make write to the smbus base register and enable bit actually work.

Signed-off-by: Gerd Hoffmann 
---
 hw/acpi_piix4.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 9e6c97ebd3..b1d5bf3d61 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -142,12 +142,29 @@ static void pm_io_space_update(PIIX4PMState *s)
     memory_region_transaction_commit();
 }
 
+static void smbus_io_space_update(PIIX4PMState *s)
+{
+    s->smb_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x90));
+    s->smb_io_base &= 0xffc0;
+
+    memory_region_transaction_begin();
+    memory_region_set_enabled(&s->smb.io, s->dev.config[0xd2] & 1);
+    memory_region_set_address(&s->smb.io, s->smb_io_base);
+    memory_region_transaction_commit();
+}
+
 static void pm_write_config(PCIDevice *d,
                             uint32_t address, uint32_t val, int len)
 {
     pci_default_write_config(d, address, val, len);
-    if (range_covers_byte(address, len, 0x80))
+    if (range_covers_byte(address, len, 0x80) ||
+        ranges_overlap(address, len, 0x40, 4)) {
         pm_io_space_update((PIIX4PMState *)d);
+    }
+    if (range_covers_byte(address, len, 0xd2) ||
+        ranges_overlap(address, len, 0x90, 4)) {
+        smbus_io_space_update((PIIX4PMState *)d);
+    }
 }
 
 static void vmstate_pci_status_pre_save(void *opaque)
@@ -392,6 +409,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
     pci_conf[0x91] = s->smb_io_base >> 8;
     pci_conf[0xd2] = 0x09;
     pm_smbus_init(&s->dev.qdev, &s->smb);
+    memory_region_set_enabled(&s->smb.io, pci_conf[0xd2] & 1);
     memory_region_add_subregion(get_system_io(), s->smb_io_base, &s->smb.io);
 
     memory_region_init(&s->io, "piix4-pm", 64);

From b65b93f24cb84923d2d7d43cf87d40bc88b6bdcd Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Fri, 23 Nov 2012 15:35:13 +0100
Subject: [PATCH 1812/2270] apci: switch piix4 gpe to memory api

Signed-off-by: Gerd Hoffmann 
---
 hw/acpi_piix4.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index b1d5bf3d61..c1a58d32c7 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -57,6 +57,7 @@ struct pci_status {
 typedef struct PIIX4PMState {
     PCIDevice dev;
     MemoryRegion io;
+    MemoryRegion io_gpe;
     ACPIREGS ar;
 
     APMState apm;
@@ -500,7 +501,7 @@ static void piix4_pm_register_types(void)
 
 type_init(piix4_pm_register_types)
 
-static uint32_t gpe_readb(void *opaque, uint32_t addr)
+static uint64_t gpe_readb(void *opaque, hwaddr addr, unsigned width)
 {
     PIIX4PMState *s = opaque;
     uint32_t val = acpi_gpe_ioport_readb(&s->ar, addr);
@@ -509,7 +510,8 @@ static uint32_t gpe_readb(void *opaque, uint32_t addr)
     return val;
 }
 
-static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void gpe_writeb(void *opaque, hwaddr addr, uint64_t val,
+                       unsigned width)
 {
     PIIX4PMState *s = opaque;
 
@@ -519,6 +521,16 @@ static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
     PIIX4_DPRINTF("gpe write %x <== %d\n", addr, val);
 }
 
+static const MemoryRegionOps piix4_gpe_ops = {
+    .read = gpe_readb,
+    .write = gpe_writeb,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 4,
+    .impl.min_access_size = 1,
+    .impl.max_access_size = 1,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 static uint32_t pci_up_read(void *opaque, uint32_t addr)
 {
     PIIX4PMState *s = opaque;
@@ -567,10 +579,10 @@ static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
 
 static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
 {
-
-    register_ioport_write(GPE_BASE, GPE_LEN, 1, gpe_writeb, s);
-    register_ioport_read(GPE_BASE, GPE_LEN, 1,  gpe_readb, s);
-    acpi_gpe_blk(&s->ar, GPE_BASE);
+    memory_region_init_io(&s->io_gpe, &piix4_gpe_ops, s, "apci-gpe0",
+                          GPE_LEN);
+    memory_region_add_subregion(get_system_io(), GPE_BASE, &s->io_gpe);
+    acpi_gpe_blk(&s->ar, 0);
 
     register_ioport_read(PCI_UP_BASE, 4, 4, pci_up_read, s);
     register_ioport_read(PCI_DOWN_BASE, 4, 4, pci_down_read, s);

From c84649ca66a32aadba20a8202062b02247270ee5 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Fri, 23 Nov 2012 15:37:05 +0100
Subject: [PATCH 1813/2270] acpi: remove acpi_gpe_blk

With gpe being switched to memory api this is no longer needed.

Signed-off-by: Gerd Hoffmann 
---
 hw/acpi.c       | 7 -------
 hw/acpi.h       | 2 --
 hw/acpi_ich9.c  | 1 -
 hw/acpi_piix4.c | 1 -
 4 files changed, 11 deletions(-)

diff --git a/hw/acpi.c b/hw/acpi.c
index e58e45f301..ae29a59077 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -493,11 +493,6 @@ void acpi_gpe_init(ACPIREGS *ar, uint8_t len)
     ar->gpe.en = g_malloc0(len / 2);
 }
 
-void acpi_gpe_blk(ACPIREGS *ar, uint32_t blk)
-{
-    ar->gpe.blk = blk;
-}
-
 void acpi_gpe_reset(ACPIREGS *ar)
 {
     memset(ar->gpe.sts, 0, ar->gpe.len / 2);
@@ -523,7 +518,6 @@ void acpi_gpe_ioport_writeb(ACPIREGS *ar, uint32_t addr, uint32_t val)
 {
     uint8_t *cur;
 
-    addr -= ar->gpe.blk;
     cur = acpi_gpe_ioport_get_ptr(ar, addr);
     if (addr < ar->gpe.len / 2) {
         /* GPE_STS */
@@ -541,7 +535,6 @@ uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t addr)
     uint8_t *cur;
     uint32_t val;
 
-    addr -= ar->gpe.blk;
     cur = acpi_gpe_ioport_get_ptr(ar, addr);
     val = 0;
     if (cur != NULL) {
diff --git a/hw/acpi.h b/hw/acpi.h
index 918d7f5bca..afda153d09 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -104,7 +104,6 @@ struct ACPIPM1CNT {
 };
 
 struct ACPIGPE {
-    uint32_t blk;
     uint8_t len;
 
     uint8_t *sts;
@@ -150,7 +149,6 @@ void acpi_pm1_cnt_reset(ACPIREGS *ar);
 
 /* GPE0 */
 void acpi_gpe_init(ACPIREGS *ar, uint8_t len);
-void acpi_gpe_blk(ACPIREGS *ar, uint32_t blk);
 void acpi_gpe_reset(ACPIREGS *ar);
 
 void acpi_gpe_ioport_writeb(ACPIREGS *ar, uint32_t addr, uint32_t val);
diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index db0d7a5063..c5978d33cc 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -212,7 +212,6 @@ void ich9_pm_init(ICH9LPCPMRegs *pm, qemu_irq sci_irq, qemu_irq cmos_s3)
     acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io);
 
     acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
-    acpi_gpe_blk(&pm->acpi_regs, 0);
     memory_region_init_io(&pm->io_gpe, &ich9_gpe_ops, pm, "apci-gpe0",
                           ICH9_PMIO_GPE0_LEN);
     memory_region_add_subregion(&pm->io, ICH9_PMIO_GPE0_STS, &pm->io_gpe);
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index c1a58d32c7..d2ba56e5bf 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -582,7 +582,6 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
     memory_region_init_io(&s->io_gpe, &piix4_gpe_ops, s, "apci-gpe0",
                           GPE_LEN);
     memory_region_add_subregion(get_system_io(), GPE_BASE, &s->io_gpe);
-    acpi_gpe_blk(&s->ar, 0);
 
     register_ioport_read(PCI_UP_BASE, 4, 4, pci_up_read, s);
     register_ioport_read(PCI_DOWN_BASE, 4, 4, pci_down_read, s);

From c177684c753a0b1337acebb7dbc6f3f3a9700321 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Fri, 23 Nov 2012 16:03:19 +0100
Subject: [PATCH 1814/2270] apci: switch piix4 pci hotplug to memory api

Signed-off-by: Gerd Hoffmann 
---
 hw/acpi_piix4.c | 37 +++++++++++++++++++++++++++++--------
 1 file changed, 29 insertions(+), 8 deletions(-)

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index d2ba56e5bf..263338aa20 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -42,6 +42,9 @@
 
 #define GPE_BASE 0xafe0
 #define GPE_LEN 4
+
+#define PCI_HOTPLUG_ADDR 0xae00
+#define PCI_HOTPLUG_SIZE 0x000f
 #define PCI_UP_BASE 0xae00
 #define PCI_DOWN_BASE 0xae04
 #define PCI_EJ_BASE 0xae08
@@ -58,6 +61,7 @@ typedef struct PIIX4PMState {
     PCIDevice dev;
     MemoryRegion io;
     MemoryRegion io_gpe;
+    MemoryRegion io_pci;
     ACPIREGS ar;
 
     APMState apm;
@@ -574,6 +578,27 @@ static uint32_t pcirmv_read(void *opaque, uint32_t addr)
     return s->pci0_hotplug_enable;
 }
 
+static const MemoryRegionOps piix4_pci_ops = {
+    .old_portio = (MemoryRegionPortio[]) {
+        {
+            .offset = PCI_UP_BASE - PCI_HOTPLUG_ADDR,   .len = 4, .size = 4,
+            .read = pci_up_read,
+        },{
+            .offset = PCI_DOWN_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
+            .read = pci_down_read,
+        },{
+            .offset = PCI_EJ_BASE - PCI_HOTPLUG_ADDR,   .len = 4, .size = 4,
+            .read = pci_features_read,
+            .write = pciej_write,
+        },{
+            .offset = PCI_RMV_BASE - PCI_HOTPLUG_ADDR,  .len = 4, .size = 4,
+            .read = pcirmv_read,
+        },
+        PORTIO_END_OF_LIST()
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
                                 PCIHotplugState state);
 
@@ -583,14 +608,10 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
                           GPE_LEN);
     memory_region_add_subregion(get_system_io(), GPE_BASE, &s->io_gpe);
 
-    register_ioport_read(PCI_UP_BASE, 4, 4, pci_up_read, s);
-    register_ioport_read(PCI_DOWN_BASE, 4, 4, pci_down_read, s);
-
-    register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, s);
-    register_ioport_read(PCI_EJ_BASE, 4, 4,  pci_features_read, s);
-
-    register_ioport_read(PCI_RMV_BASE, 4, 4,  pcirmv_read, s);
-
+    memory_region_init_io(&s->io_pci, &piix4_pci_ops, s, "apci-pci-hotplug",
+                          PCI_HOTPLUG_SIZE);
+    memory_region_add_subregion(get_system_io(), PCI_HOTPLUG_ADDR,
+                                &s->io_pci);
     pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
 }
 

From 3f5bc9e8af8c9ee617b143e42ad4bd2feb379a19 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Fri, 23 Nov 2012 15:02:18 +0100
Subject: [PATCH 1815/2270] q35: update lpc pci config space according to
 configured devices

Signed-off-by: Gerd Hoffmann 
---
 hw/ich9.h       |  1 +
 hw/lpc_ich9.c   | 29 +++++++++++++++++++++++++++++
 hw/smbus_ich9.c | 12 ------------
 3 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/hw/ich9.h b/hw/ich9.h
index de491350c3..34e216f142 100644
--- a/hw/ich9.h
+++ b/hw/ich9.h
@@ -51,6 +51,7 @@ typedef struct ICH9LPCState {
     /* isa bus */
     ISABus *isa_bus;
     MemoryRegion rbca_mem;
+    Notifier machine_ready;
 
     qemu_irq *pic;
     qemu_irq *ioapic;
diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
index 2fc83a496f..6585236148 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -60,6 +60,7 @@
 #include "pam.h"
 #include "pci_internals.h"
 #include "exec-memory.h"
+#include "sysemu.h"
 
 static int ich9_lpc_sci_irq(ICH9LPCState *lpc);
 
@@ -456,6 +457,30 @@ static const MemoryRegionOps rbca_mmio_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
+static void ich9_lpc_machine_ready(Notifier *n, void *opaque)
+{
+    ICH9LPCState *s = container_of(n, ICH9LPCState, machine_ready);
+    uint8_t *pci_conf;
+
+    pci_conf = s->d.config;
+    if (isa_is_ioport_assigned(0x3f8)) {
+        /* com1 */
+        pci_conf[0x82] |= 0x01;
+    }
+    if (isa_is_ioport_assigned(0x2f8)) {
+        /* com2 */
+        pci_conf[0x82] |= 0x02;
+    }
+    if (isa_is_ioport_assigned(0x378)) {
+        /* lpt */
+        pci_conf[0x82] |= 0x04;
+    }
+    if (isa_is_ioport_assigned(0x3f0)) {
+        /* floppy */
+        pci_conf[0x82] |= 0x08;
+    }
+}
+
 static int ich9_lpc_initfn(PCIDevice *d)
 {
     ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);
@@ -473,6 +498,10 @@ static int ich9_lpc_initfn(PCIDevice *d)
 
     ich9_cc_init(lpc);
     apm_init(&lpc->apm, ich9_apm_ctrl_changed, lpc);
+
+    lpc->machine_ready.notify = ich9_lpc_machine_ready;
+    qemu_add_machine_init_done_notifier(&lpc->machine_ready);
+
     return 0;
 }
 
diff --git a/hw/smbus_ich9.c b/hw/smbus_ich9.c
index 54e7e1252d..4194785d71 100644
--- a/hw/smbus_ich9.c
+++ b/hw/smbus_ich9.c
@@ -77,18 +77,6 @@ static int ich9_smbus_initfn(PCIDevice *d)
     /* TODO? D31IP.SMIP in chipset configuration space */
     pci_config_set_interrupt_pin(d->config, 0x01); /* interrupt pin 1 */
 
-    pci_set_byte(d->config + ICH9_SMB_HOSTC, 0);
-
-    /*
-     * update parameters based on
-     * paralell_hds[0]
-     * serial_hds[0]
-     * serial_hds[0]
-     * fdc
-     *
-     * Is there any OS that depends on them?
-     */
-
     pci_set_byte(d->config + ICH9_SMB_HOSTC, 0);
     /* TODO bar0, bar1: 64bit BAR support*/
 

From 3e43749882c558875f70ac5deda39cdc9797e245 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Tue, 27 Nov 2012 08:24:42 +0100
Subject: [PATCH 1816/2270] acpi: drop debug port

I'm pretty sure this isn't needed any more.  I think this predates the
switch to seabios, and the seabios DSDT table has a DBUG() aml macro
which writes stuff to the seabios debug port (0x402).

Signed-off-by: Gerd Hoffmann 
---
 hw/acpi_piix4.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 263338aa20..b03454e6c0 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -38,8 +38,6 @@
 # define PIIX4_DPRINTF(format, ...)     do { } while (0)
 #endif
 
-#define ACPI_DBG_IO_ADDR  0xb044
-
 #define GPE_BASE 0xafe0
 #define GPE_LEN 4
 
@@ -129,11 +127,6 @@ static void apm_ctrl_changed(uint32_t val, void *arg)
     }
 }
 
-static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
-{
-    PIIX4_DPRINTF("ACPI: DBG: 0x%08x\n", val);
-}
-
 static void pm_io_space_update(PIIX4PMState *s)
 {
     uint32_t pm_io_base;
@@ -400,8 +393,6 @@ static int piix4_pm_initfn(PCIDevice *dev)
     /* APM */
     apm_init(&s->apm, apm_ctrl_changed, s);
 
-    register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
-
     if (s->kvm_enabled) {
         /* Mark SMM as already inited to prevent SMM from running.  KVM does not
          * support SMM mode. */

From f1ae2e3883c4ee3a9f91f484690abe42f5063d64 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Tue, 4 Dec 2012 14:39:16 +0100
Subject: [PATCH 1817/2270] add pc-1.4

Signed-off-by: Gerd Hoffmann 
---
 hw/pc_piix.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index aa3e7f40dc..040cd079ed 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -281,8 +281,8 @@ static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
 }
 #endif
 
-static QEMUMachine pc_machine_v1_3 = {
-    .name = "pc-1.3",
+static QEMUMachine pc_machine_v1_4 = {
+    .name = "pc-1.4",
     .alias = "pc",
     .desc = "Standard PC",
     .init = pc_init_pci_1_3,
@@ -290,6 +290,16 @@ static QEMUMachine pc_machine_v1_3 = {
     .is_default = 1,
 };
 
+static QEMUMachine pc_machine_v1_3 = {
+    .name = "pc-1.3",
+    .desc = "Standard PC",
+    .init = pc_init_pci_1_3,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        { /* end of list */ }
+    },
+};
+
 #define PC_COMPAT_1_2 \
         {\
             .driver   = "nec-usb-xhci",\
@@ -626,6 +636,7 @@ static QEMUMachine xenfv_machine = {
 
 static void pc_machine_init(void)
 {
+    qemu_register_machine(&pc_machine_v1_4);
     qemu_register_machine(&pc_machine_v1_3);
     qemu_register_machine(&pc_machine_v1_2);
     qemu_register_machine(&pc_machine_v1_1);

From 8beba9304391189666df1b62b23a5101b3831317 Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Sat, 17 Nov 2012 12:47:14 +0100
Subject: [PATCH 1818/2270] usb: Call wakeup when data becomes available for
 all devices with int eps

This is necessary for proper interaction with the xhci controller, and it
will allow other hcds to lower there frame timer while waiting for interrupt
data.

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/dev-hub.c     | 2 ++
 hw/usb/dev-network.c | 7 +++++++
 hw/usb/dev-wacom.c   | 4 ++++
 hw/usb/redirect.c    | 4 ++++
 4 files changed, 17 insertions(+)

diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
index 9ee60dd412..470fbbb86c 100644
--- a/hw/usb/dev-hub.c
+++ b/hw/usb/dev-hub.c
@@ -184,6 +184,7 @@ static void usb_hub_detach(USBPort *port1)
         port->wPortStatus &= ~PORT_STAT_ENABLE;
         port->wPortChange |= PORT_STAT_C_ENABLE;
     }
+    usb_wakeup(s->intr);
 }
 
 static void usb_hub_child_detach(USBPort *port1, USBDevice *child)
@@ -363,6 +364,7 @@ static void usb_hub_handle_control(USBDevice *dev, USBPacket *p,
                     port->wPortChange |= PORT_STAT_C_RESET;
                     /* set enable bit */
                     port->wPortStatus |= PORT_STAT_ENABLE;
+                    usb_wakeup(s->intr);
                 }
                 break;
             case PORT_POWER:
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index 14d9e5aa5b..30cb03373e 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -639,6 +639,8 @@ typedef struct USBNetState {
     unsigned int in_ptr, in_len;
     uint8_t in_buf[2048];
 
+    USBEndpoint *intr;
+
     char usbstring_mac[13];
     NICState *nic;
     NICConf conf;
@@ -851,6 +853,10 @@ static void *rndis_queue_response(USBNetState *s, unsigned int length)
     struct rndis_response *r =
             g_malloc0(sizeof(struct rndis_response) + length);
 
+    if (QTAILQ_EMPTY(&s->rndis_resp)) {
+        usb_wakeup(s->intr);
+    }
+
     QTAILQ_INSERT_TAIL(&s->rndis_resp, r, entries);
     r->length = length;
 
@@ -1349,6 +1355,7 @@ static int usb_net_initfn(USBDevice *dev)
     s->media_state = 0;	/* NDIS_MEDIA_STATE_CONNECTED */;
     s->filter = 0;
     s->vendorid = 0x1234;
+    s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(&net_usbnet_info, &s->conf,
diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c
index 08b416daa6..f7342b08c3 100644
--- a/hw/usb/dev-wacom.c
+++ b/hw/usb/dev-wacom.c
@@ -43,6 +43,7 @@
 
 typedef struct USBWacomState {
     USBDevice dev;
+    USBEndpoint *intr;
     QEMUPutMouseEntry *eh_entry;
     int dx, dy, dz, buttons_state;
     int x, y;
@@ -137,6 +138,7 @@ static void usb_mouse_event(void *opaque,
     s->dz += dz1;
     s->buttons_state = buttons_state;
     s->changed = 1;
+    usb_wakeup(s->intr);
 }
 
 static void usb_wacom_event(void *opaque,
@@ -150,6 +152,7 @@ static void usb_wacom_event(void *opaque,
     s->dz += dz;
     s->buttons_state = buttons_state;
     s->changed = 1;
+    usb_wakeup(s->intr);
 }
 
 static inline int int_clamp(int val, int vmin, int vmax)
@@ -337,6 +340,7 @@ static int usb_wacom_initfn(USBDevice *dev)
     USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev);
     usb_desc_create_serial(dev);
     usb_desc_init(dev);
+    s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
     s->changed = 1;
     return 0;
 }
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 490c90fae1..9e7f6453f7 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1644,6 +1644,10 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id,
             return;
         }
 
+        if (QTAILQ_EMPTY(&dev->endpoint[EP2I(ep)].bufpq)) {
+            usb_wakeup(usb_ep_get(&dev->dev, USB_TOKEN_IN, ep & 0x0f));
+        }
+
         /* bufp_alloc also adds the packet to the ep queue */
         bufp_alloc(dev, data, data_len, interrupt_packet->status, ep);
     } else {

From be41efde3ca0372dbf7543e09ff473b4eec25057 Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Sat, 17 Nov 2012 12:47:15 +0100
Subject: [PATCH 1819/2270] usb: Don't allow USB_RET_ASYNC for interrupt
 packets

It is tempting to use USB_RET_ASYNC for interrupt packets, rather then the
current NAK + polling approach, but this causes issues for migration, as
an async completed packet will not getting written back to guest memory until
the next poll time, and if a migration happens in between it will get lost!

Make an exception for host devices, because:
1) host-linux actually uses async completion for interrupt endpoints
2) host devices don't migrate anyways

Ideally we would convert host-linux.c to handle (input) interrupt endpoints in
a buffered manner like it does for isoc endpoints, keeping multiple urbs
submitted to ensure the devices timing requirements are met, as well as making
its interrupt ep handling the same as other usb-devices.

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb.h            | 1 +
 hw/usb/core.c       | 4 ++++
 hw/usb/host-bsd.c   | 1 +
 hw/usb/host-linux.c | 1 +
 4 files changed, 7 insertions(+)

diff --git a/hw/usb.h b/hw/usb.h
index 7d6de69ec4..58f812f7d0 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -197,6 +197,7 @@ struct USBEndpoint {
 
 enum USBDeviceFlags {
     USB_DEV_FLAG_FULL_PATH,
+    USB_DEV_FLAG_IS_HOST,
 };
 
 /* definition of a USB device */
diff --git a/hw/usb/core.c b/hw/usb/core.c
index 52b53108cd..8e360d3ec0 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -406,7 +406,11 @@ void usb_handle_packet(USBDevice *dev, USBPacket *p)
     if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) {
         usb_process_one(p);
         if (p->status == USB_RET_ASYNC) {
+            /* hcd drivers cannot handle async for isoc */
             assert(p->ep->type != USB_ENDPOINT_XFER_ISOC);
+            /* using async for interrupt packets breaks migration */
+            assert(p->ep->type != USB_ENDPOINT_XFER_INT ||
+                   (dev->flags & USB_DEV_FLAG_IS_HOST));
             usb_packet_set_state(p, USB_PACKET_ASYNC);
             QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
         } else if (p->status == USB_RET_ADD_TO_QUEUE) {
diff --git a/hw/usb/host-bsd.c b/hw/usb/host-bsd.c
index 6473e8b747..dae0009378 100644
--- a/hw/usb/host-bsd.c
+++ b/hw/usb/host-bsd.c
@@ -292,6 +292,7 @@ static void usb_host_handle_destroy(USBDevice *opaque)
 
 static int usb_host_initfn(USBDevice *dev)
 {
+    dev->flags |= (1 << USB_DEV_FLAG_IS_HOST);
     return 0;
 }
 
diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c
index aa77b7704d..bdafb6bc87 100644
--- a/hw/usb/host-linux.c
+++ b/hw/usb/host-linux.c
@@ -1476,6 +1476,7 @@ static int usb_host_initfn(USBDevice *dev)
 {
     USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
 
+    dev->flags |= (1 << USB_DEV_FLAG_IS_HOST);
     dev->auto_attach = 0;
     s->fd = -1;
     s->hub_fd = -1;

From 386ab487ebc25d780ddfc4a9aea0b21c4a9aaa94 Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Sat, 17 Nov 2012 12:47:16 +0100
Subject: [PATCH 1820/2270] usb: Allow overriding of usb_desc at the device
 level

This allows devices to present a different set of descriptors based on
device properties.

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb.h     | 1 +
 hw/usb/bus.c | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/hw/usb.h b/hw/usb.h
index 58f812f7d0..268e6539aa 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -230,6 +230,7 @@ struct USBDevice {
     USBEndpoint ep_out[USB_MAX_ENDPOINTS];
 
     QLIST_HEAD(, USBDescString) strings;
+    const USBDesc *usb_desc; /* Overrides class usb_desc if not NULL */
     const USBDescDevice *device;
 
     int configuration;
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index 55d0edd5c3..8264c240ee 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -166,6 +166,9 @@ const char *usb_device_get_product_desc(USBDevice *dev)
 const USBDesc *usb_device_get_usb_desc(USBDevice *dev)
 {
     USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+    if (dev->usb_desc) {
+        return dev->usb_desc;
+    }
     return klass->usb_desc;
 }
 

From 8082624099bce56a3139e6b9f72016c00fd10227 Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Sat, 17 Nov 2012 12:47:17 +0100
Subject: [PATCH 1821/2270] ehci: Lower timer freq when the periodic schedule
 is idle

Lower the timer freq if no iso schedule packets complete for 64 frames in
a row.

We can safely do this, without adding latency, because:
1) If there is isoc traffic this will never trigger
2) For async handled interrupt packets (only usb-host), the completion handler
   will immediately schedule the frame_timer from a bh
3) All devices using NAK to signal no data for interrupt endpoints now use
   wakeup, which will immediately schedule the frame_timer from a bh

The advantage of this is that when we only have interrupt packets in the
periodic schedule, async_stepdown can do its work and significantly lower
the frequency at which the frame_timer runs.

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-ehci.c | 39 +++++++++++++++++++++++++++++++++------
 hw/usb/hcd-ehci.h |  1 +
 2 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 7df8e21ecb..7536837fb2 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -114,6 +114,7 @@
 #define BUFF_SIZE        5*4096   // Max bytes to transfer per transaction
 #define MAX_QH           100      // Max allowable queue heads in a chain
 #define MIN_FR_PER_TICK  3        // Min frames to process when catching up
+#define PERIODIC_ACTIVE  64
 
 /*  Internal periodic / asynchronous schedule state machine states
  */
@@ -738,6 +739,19 @@ static int ehci_register_companion(USBBus *bus, USBPort *ports[],
     return 0;
 }
 
+static void ehci_wakeup_endpoint(USBBus *bus, USBEndpoint *ep)
+{
+    EHCIState *s = container_of(bus, EHCIState, bus);
+    uint32_t portsc = s->portsc[ep->dev->port->index];
+
+    if (portsc & PORTSC_POWNER) {
+        return;
+    }
+
+    s->periodic_sched_active = PERIODIC_ACTIVE;
+    qemu_bh_schedule(s->async_bh);
+}
+
 static USBDevice *ehci_find_device(EHCIState *ehci, uint8_t addr)
 {
     USBDevice *dev;
@@ -1188,9 +1202,10 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
     trace_usb_ehci_packet_action(p->queue, p, "wakeup");
     p->async = EHCI_ASYNC_FINISHED;
 
-    if (p->queue->async) {
-        qemu_bh_schedule(p->queue->ehci->async_bh);
+    if (!p->queue->async) {
+        s->periodic_sched_active = PERIODIC_ACTIVE;
     }
+    qemu_bh_schedule(s->async_bh);
 }
 
 static void ehci_execute_complete(EHCIQueue *q)
@@ -1344,6 +1359,8 @@ static int ehci_process_itd(EHCIState *ehci,
     uint32_t i, len, pid, dir, devaddr, endp;
     uint32_t pg, off, ptr1, ptr2, max, mult;
 
+    ehci->periodic_sched_active = PERIODIC_ACTIVE;
+
     dir =(itd->bufptr[1] & ITD_BUFPTR_DIRECTION);
     devaddr = get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR);
     endp = get_field(itd->bufptr[0], ITD_BUFPTR_EP);
@@ -2033,6 +2050,9 @@ static void ehci_advance_state(EHCIState *ehci, int async)
         case EST_WRITEBACK:
             assert(q != NULL);
             again = ehci_state_writeback(q);
+            if (!async) {
+                ehci->periodic_sched_active = PERIODIC_ACTIVE;
+            }
             break;
 
         default:
@@ -2198,7 +2218,6 @@ static void ehci_frame_timer(void *opaque)
 
     if (ehci_periodic_enabled(ehci) || ehci->pstate != EST_INACTIVE) {
         need_timer++;
-        ehci->async_stepdown = 0;
 
         if (frames > ehci->maxframes) {
             skipped_frames = frames - ehci->maxframes;
@@ -2222,18 +2241,25 @@ static void ehci_frame_timer(void *opaque)
                     break;
                 }
             }
+            if (ehci->periodic_sched_active) {
+                ehci->periodic_sched_active--;
+            }
             ehci_update_frindex(ehci, 1);
             ehci_advance_periodic_state(ehci);
             ehci->last_run_ns += FRAME_TIMER_NS;
         }
     } else {
-        if (ehci->async_stepdown < ehci->maxframes / 2) {
-            ehci->async_stepdown++;
-        }
+        ehci->periodic_sched_active = 0;
         ehci_update_frindex(ehci, frames);
         ehci->last_run_ns += FRAME_TIMER_NS * frames;
     }
 
+    if (ehci->periodic_sched_active) {
+        ehci->async_stepdown = 0;
+    } else if (ehci->async_stepdown < ehci->maxframes / 2) {
+        ehci->async_stepdown++;
+    }
+
     /*  Async is not inside loop since it executes everything it can once
      *  called
      */
@@ -2301,6 +2327,7 @@ static USBPortOps ehci_port_ops = {
 
 static USBBusOps ehci_bus_ops = {
     .register_companion = ehci_register_companion,
+    .wakeup_endpoint = ehci_wakeup_endpoint,
 };
 
 static int usb_ehci_post_load(void *opaque, int version_id)
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index d8078f4555..772870b727 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -311,6 +311,7 @@ struct EHCIState {
 
     uint64_t last_run_ns;
     uint32_t async_stepdown;
+    uint32_t periodic_sched_active;
     bool int_req_by_async;
 };
 

From 427e3aa151c749225364d0c30640e2e3c1756d9d Mon Sep 17 00:00:00 2001
From: Hans de Goede 
Date: Sat, 17 Nov 2012 12:47:18 +0100
Subject: [PATCH 1822/2270] usb-tablet: Allow connecting to ehci

Our ehci code has is capable of significantly lowering the wakeup rate
for the hcd emulation while the device is idle. It is possible to add
similar code ot the uhci emulation, but that simply is not there atm,
and there is no reason why a (virtual) usb-tablet can not be a USB-2 device.

Making usb-hid devices connect to the emulated ehci controller instead
of the emulated uhci controller on vms which have both lowers the cpuload
for a fully idle vm from 20% to 2-3% (on my laptop).

An alternative implementation to using a property to select the tablet
type, would be simply making it a new device type, ie usb-tablet2, but the
downside of that is that this will require libvirt changes to be available
through libvirt at all, and then management tools changes to become the
default for new vms, where as using a property will automatically get
any pc-1.3 type vms the lower cpuload.

[ kraxel: adapt compat property for post-1.3 merge ]

Signed-off-by: Hans de Goede 
Signed-off-by: Gerd Hoffmann 

tablet compat fixup

Signed-off-by: Gerd Hoffmann 
---
 hw/pc_piix.c     |  9 +++++
 hw/usb/dev-hid.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 040cd079ed..19e342aeb4 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -290,17 +290,26 @@ static QEMUMachine pc_machine_v1_4 = {
     .is_default = 1,
 };
 
+#define PC_COMPAT_1_3 \
+        {\
+            .driver   = "usb-tablet",\
+            .property = "usb_version",\
+            .value    = stringify(1),\
+        }
+
 static QEMUMachine pc_machine_v1_3 = {
     .name = "pc-1.3",
     .desc = "Standard PC",
     .init = pc_init_pci_1_3,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_1_3,
         { /* end of list */ }
     },
 };
 
 #define PC_COMPAT_1_2 \
+        PC_COMPAT_1_3,\
         {\
             .driver   = "nec-usb-xhci",\
             .property = "msi",\
diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
index 55266b18ef..87491284a8 100644
--- a/hw/usb/dev-hid.c
+++ b/hw/usb/dev-hid.c
@@ -46,6 +46,7 @@ typedef struct USBHIDState {
     USBDevice dev;
     USBEndpoint *intr;
     HIDState hid;
+    uint32_t usb_version;
 } USBHIDState;
 
 enum {
@@ -131,6 +132,36 @@ static const USBDescIface desc_iface_tablet = {
     },
 };
 
+static const USBDescIface desc_iface_tablet2 = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 1,
+    .bInterfaceClass               = USB_CLASS_HID,
+    .bInterfaceProtocol            = 0x02,
+    .ndesc                         = 1,
+    .descs = (USBDescOther[]) {
+        {
+            /* HID descriptor */
+            .data = (uint8_t[]) {
+                0x09,          /*  u8  bLength */
+                USB_DT_HID,    /*  u8  bDescriptorType */
+                0x01, 0x00,    /*  u16 HID_class */
+                0x00,          /*  u8  country_code */
+                0x01,          /*  u8  num_descriptors */
+                USB_DT_REPORT, /*  u8  type: Report */
+                74, 0,         /*  u16 len */
+            },
+        },
+    },
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_INT,
+            .wMaxPacketSize        = 8,
+            .bInterval             = 4, /* 2 ^ (4-1) * 125 usecs = 1 ms */
+        },
+    },
+};
+
 static const USBDescIface desc_iface_keyboard = {
     .bInterfaceNumber              = 0,
     .bNumEndpoints                 = 1,
@@ -196,6 +227,23 @@ static const USBDescDevice desc_device_tablet = {
     },
 };
 
+static const USBDescDevice desc_device_tablet2 = {
+    .bcdUSB                        = 0x0200,
+    .bMaxPacketSize0               = 64,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .iConfiguration        = STR_CONFIG_TABLET,
+            .bmAttributes          = 0xa0,
+            .bMaxPower             = 50,
+            .nif = 1,
+            .ifs = &desc_iface_tablet2,
+        },
+    },
+};
+
 static const USBDescDevice desc_device_keyboard = {
     .bcdUSB                        = 0x0100,
     .bMaxPacketSize0               = 8,
@@ -239,6 +287,20 @@ static const USBDesc desc_tablet = {
     .str  = desc_strings,
 };
 
+static const USBDesc desc_tablet2 = {
+    .id = {
+        .idVendor          = 0x0627,
+        .idProduct         = 0x0001,
+        .bcdDevice         = 0,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT_TABLET,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device_tablet,
+    .high = &desc_device_tablet2,
+    .str  = desc_strings,
+};
+
 static const USBDesc desc_keyboard = {
     .id = {
         .idVendor          = 0x0627,
@@ -508,6 +570,21 @@ static int usb_hid_initfn(USBDevice *dev, int kind)
 
 static int usb_tablet_initfn(USBDevice *dev)
 {
+    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
+
+    switch (us->usb_version) {
+    case 1:
+        dev->usb_desc = &desc_tablet;
+        break;
+    case 2:
+        dev->usb_desc = &desc_tablet2;
+        break;
+    default:
+        error_report("Invalid usb version %d for usb-tabler (must be 1 or 2)",
+                     us->usb_version);
+        return -1;
+    }
+
     return usb_hid_initfn(dev, HID_TABLET);
 }
 
@@ -562,8 +639,14 @@ static void usb_hid_class_initfn(ObjectClass *klass, void *data)
     uc->handle_control = usb_hid_handle_control;
     uc->handle_data    = usb_hid_handle_data;
     uc->handle_destroy = usb_hid_handle_destroy;
+    uc->handle_attach  = usb_desc_attach;
 }
 
+static Property usb_tablet_properties[] = {
+        DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2),
+        DEFINE_PROP_END_OF_LIST(),
+};
+
 static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -572,8 +655,8 @@ static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
     usb_hid_class_initfn(klass, data);
     uc->init           = usb_tablet_initfn;
     uc->product_desc   = "QEMU USB Tablet";
-    uc->usb_desc       = &desc_tablet;
     dc->vmsd = &vmstate_usb_ptr;
+    dc->props = usb_tablet_properties;
 }
 
 static TypeInfo usb_tablet_info = {

From ac10027327e27c9b360452e01af3ef2147f5a26f Mon Sep 17 00:00:00 2001
From: Julien Grall 
Date: Wed, 19 Sep 2012 12:50:02 +0100
Subject: [PATCH 1823/2270] isa: Add isa_address_space_io()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This function permits to retrieve ISA IO address space.
It will be usefull when we need to pass IO address space as argument.

Signed-off-by: Julien Grall 
Acked-by: Avi Kivity 
Signed-off-by: Andreas Färber 
---
 hw/isa-bus.c | 9 +++++++++
 hw/isa.h     | 1 +
 2 files changed, 10 insertions(+)

diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index 685fdc0f82..144a88e272 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -264,4 +264,13 @@ MemoryRegion *isa_address_space(ISADevice *dev)
     return get_system_memory();
 }
 
+MemoryRegion *isa_address_space_io(ISADevice *dev)
+{
+    if (dev) {
+        return isa_bus_from_device(dev)->address_space_io;
+    }
+
+    return isabus->address_space_io;
+}
+
 type_init(isabus_register_types)
diff --git a/hw/isa.h b/hw/isa.h
index f9382e8367..9d719fa3c8 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -43,6 +43,7 @@ void isa_bus_irqs(ISABus *bus, qemu_irq *irqs);
 qemu_irq isa_get_irq(ISADevice *dev, int isairq);
 void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq);
 MemoryRegion *isa_address_space(ISADevice *dev);
+MemoryRegion *isa_address_space_io(ISADevice *dev);
 ISADevice *isa_create(ISABus *bus, const char *name);
 ISADevice *isa_try_create(ISABus *bus, const char *name);
 ISADevice *isa_create_simple(ISABus *bus, const char *name);

From 42d8a3cf960659069bd2b2d9c443dafd7585607f Mon Sep 17 00:00:00 2001
From: Julien Grall 
Date: Wed, 19 Sep 2012 12:50:03 +0100
Subject: [PATCH 1824/2270] hw/apm.c: Replace register_ioport_*
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Replace all register_ioport_*() with a MemoryRegion.
This permits to use the new Memory stuff like listeners.

Moreover, the PCI device is added as an argument for apm_init(),
so we can register IO inside the PCI IO address space.

Signed-off-by: Julien Grall 
Acked-by: Avi Kivity 
[AF: Rebased onto hwaddr and q35]
Signed-off-by: Andreas Färber 
---
 hw/acpi_piix4.c |  2 +-
 hw/apm.c        | 23 ++++++++++++++++++-----
 hw/apm.h        |  5 ++++-
 hw/lpc_ich9.c   |  2 +-
 hw/vt82c686.c   |  2 +-
 5 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 519269a013..dbddde13ab 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -438,7 +438,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
     pci_conf[0x3d] = 0x01; // interrupt pin 1
 
     /* APM */
-    apm_init(&s->apm, apm_ctrl_changed, s);
+    apm_init(dev, &s->apm, apm_ctrl_changed, s);
 
     register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
 
diff --git a/hw/apm.c b/hw/apm.c
index 2aead52a74..e988ad9939 100644
--- a/hw/apm.c
+++ b/hw/apm.c
@@ -22,6 +22,7 @@
 
 #include "apm.h"
 #include "hw.h"
+#include "pci.h"
 
 //#define DEBUG
 
@@ -35,7 +36,8 @@
 #define APM_CNT_IOPORT  0xb2
 #define APM_STS_IOPORT  0xb3
 
-static void apm_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void apm_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
+                              unsigned size)
 {
     APMState *apm = opaque;
     addr &= 1;
@@ -51,7 +53,7 @@ static void apm_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
     }
 }
 
-static uint32_t apm_ioport_readb(void *opaque, uint32_t addr)
+static uint64_t apm_ioport_readb(void *opaque, hwaddr addr, unsigned size)
 {
     APMState *apm = opaque;
     uint32_t val;
@@ -78,12 +80,23 @@ const VMStateDescription vmstate_apm = {
     }
 };
 
-void apm_init(APMState *apm, apm_ctrl_changed_t callback, void *arg)
+static const MemoryRegionOps apm_ops = {
+    .read = apm_ioport_readb,
+    .write = apm_ioport_writeb,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
+void apm_init(PCIDevice *dev, APMState *apm, apm_ctrl_changed_t callback,
+              void *arg)
 {
     apm->callback = callback;
     apm->arg = arg;
 
     /* ioport 0xb2, 0xb3 */
-    register_ioport_write(APM_CNT_IOPORT, 2, 1, apm_ioport_writeb, apm);
-    register_ioport_read(APM_CNT_IOPORT, 2, 1, apm_ioport_readb, apm);
+    memory_region_init_io(&apm->io, &apm_ops, apm, "apm-io", 2);
+    memory_region_add_subregion(pci_address_space_io(dev), APM_CNT_IOPORT,
+                                &apm->io);
 }
diff --git a/hw/apm.h b/hw/apm.h
index f7c741e327..5431b6d7c8 100644
--- a/hw/apm.h
+++ b/hw/apm.h
@@ -4,6 +4,7 @@
 #include 
 #include "qemu-common.h"
 #include "hw.h"
+#include "memory.h"
 
 typedef void (*apm_ctrl_changed_t)(uint32_t val, void *arg);
 
@@ -13,9 +14,11 @@ typedef struct APMState {
 
     apm_ctrl_changed_t callback;
     void *arg;
+    MemoryRegion io;
 } APMState;
 
-void apm_init(APMState *s, apm_ctrl_changed_t callback, void *arg);
+void apm_init(PCIDevice *dev, APMState *s, apm_ctrl_changed_t callback,
+              void *arg);
 
 extern const VMStateDescription vmstate_apm;
 
diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
index 2fc83a496f..7de5427a69 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -472,7 +472,7 @@ static int ich9_lpc_initfn(PCIDevice *d)
     lpc->isa_bus = isa_bus;
 
     ich9_cc_init(lpc);
-    apm_init(&lpc->apm, ich9_apm_ctrl_changed, lpc);
+    apm_init(d, &lpc->apm, ich9_apm_ctrl_changed, lpc);
     return 0;
 }
 
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 5d7c00cf4b..7f11dbe782 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -427,7 +427,7 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
     register_ioport_write(s->smb_io_base, 0xf, 1, smb_ioport_writeb, &s->smb);
     register_ioport_read(s->smb_io_base, 0xf, 1, smb_ioport_readb, &s->smb);
 
-    apm_init(&s->apm, NULL, s);
+    apm_init(dev, &s->apm, NULL, s);
 
     acpi_pm_tmr_init(&s->ar, pm_tmr_timer);
     acpi_pm1_cnt_init(&s->ar);

From c75e6d8e354c44e76045cb0de20cda1a4ce4d575 Mon Sep 17 00:00:00 2001
From: Julien Grall 
Date: Wed, 19 Sep 2012 12:50:06 +0100
Subject: [PATCH 1825/2270] hw/cirrus_vga.c: Replace register_ioport_*
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Replace all register_ioport_*() with the new Memory API.
This permits to use the new Memory stuff like listeners.

Signed-off-by: Julien Grall 
Acked-by: Avi Kivity 
[AF: Rebased onto hwaddr]
Signed-off-by: Andreas Färber 
---
 hw/cirrus_vga.c | 48 ++++++++++++++++++++++++++++--------------------
 1 file changed, 28 insertions(+), 20 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 9bef96e6d7..40efa8a523 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -197,6 +197,7 @@ typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
 typedef struct CirrusVGAState {
     VGACommonState vga;
 
+    MemoryRegion cirrus_vga_io;
     MemoryRegion cirrus_linear_io;
     MemoryRegion cirrus_linear_bitblt_io;
     MemoryRegion cirrus_mmio_io;
@@ -2432,13 +2433,15 @@ static void cirrus_update_memory_access(CirrusVGAState *s)
 
 /* I/O ports */
 
-static uint32_t cirrus_vga_ioport_read(void *opaque, uint32_t addr)
+static uint64_t cirrus_vga_ioport_read(void *opaque, hwaddr addr,
+                                       unsigned size)
 {
     CirrusVGAState *c = opaque;
     VGACommonState *s = &c->vga;
     int val, index;
 
     qemu_flush_coalesced_mmio_buffer();
+    addr += 0x3b0;
 
     if (vga_ioport_invalid(s, addr)) {
 	val = 0xff;
@@ -2527,13 +2530,15 @@ static uint32_t cirrus_vga_ioport_read(void *opaque, uint32_t addr)
     return val;
 }
 
-static void cirrus_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+static void cirrus_vga_ioport_write(void *opaque, hwaddr addr, uint64_t val,
+                                    unsigned size)
 {
     CirrusVGAState *c = opaque;
     VGACommonState *s = &c->vga;
     int index;
 
     qemu_flush_coalesced_mmio_buffer();
+    addr += 0x3b0;
 
     /* check port range access depending on color/monochrome mode */
     if (vga_ioport_invalid(s, addr)) {
@@ -2646,7 +2651,7 @@ static uint64_t cirrus_mmio_read(void *opaque, hwaddr addr,
     if (addr >= 0x100) {
         return cirrus_mmio_blt_read(s, addr - 0x100);
     } else {
-        return cirrus_vga_ioport_read(s, addr + 0x3c0);
+        return cirrus_vga_ioport_read(s, addr + 0x10, size);
     }
 }
 
@@ -2658,7 +2663,7 @@ static void cirrus_mmio_write(void *opaque, hwaddr addr,
     if (addr >= 0x100) {
 	cirrus_mmio_blt_write(s, addr - 0x100, val);
     } else {
-        cirrus_vga_ioport_write(s, addr + 0x3c0, val);
+        cirrus_vga_ioport_write(s, addr + 0x10, val, size);
     }
 }
 
@@ -2784,8 +2789,19 @@ static const MemoryRegionOps cirrus_linear_io_ops = {
     },
 };
 
+static const MemoryRegionOps cirrus_vga_io_ops = {
+    .read = cirrus_vga_ioport_read,
+    .write = cirrus_vga_ioport_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
 static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci,
-                               MemoryRegion *system_memory)
+                               MemoryRegion *system_memory,
+                               MemoryRegion *system_io)
 {
     int i;
     static int inited;
@@ -2817,19 +2833,10 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci,
             s->bustype = CIRRUS_BUSTYPE_ISA;
     }
 
-    register_ioport_write(0x3c0, 16, 1, cirrus_vga_ioport_write, s);
-
-    register_ioport_write(0x3b4, 2, 1, cirrus_vga_ioport_write, s);
-    register_ioport_write(0x3d4, 2, 1, cirrus_vga_ioport_write, s);
-    register_ioport_write(0x3ba, 1, 1, cirrus_vga_ioport_write, s);
-    register_ioport_write(0x3da, 1, 1, cirrus_vga_ioport_write, s);
-
-    register_ioport_read(0x3c0, 16, 1, cirrus_vga_ioport_read, s);
-
-    register_ioport_read(0x3b4, 2, 1, cirrus_vga_ioport_read, s);
-    register_ioport_read(0x3d4, 2, 1, cirrus_vga_ioport_read, s);
-    register_ioport_read(0x3ba, 1, 1, cirrus_vga_ioport_read, s);
-    register_ioport_read(0x3da, 1, 1, cirrus_vga_ioport_read, s);
+    /* Register ioport 0x3b0 - 0x3df */
+    memory_region_init_io(&s->cirrus_vga_io, &cirrus_vga_io_ops, s,
+                          "cirrus-io", 0x30);
+    memory_region_add_subregion(system_io, 0x3b0, &s->cirrus_vga_io);
 
     memory_region_init(&s->low_mem_container,
                        "cirrus-lowmem-container",
@@ -2900,7 +2907,7 @@ static int vga_initfn(ISADevice *dev)
 
     vga_common_init(s);
     cirrus_init_common(&d->cirrus_vga, CIRRUS_ID_CLGD5430, 0,
-                       isa_address_space(dev));
+                       isa_address_space(dev), isa_address_space_io(dev));
     s->ds = graphic_console_init(s->update, s->invalidate,
                                  s->screen_dump, s->text_update,
                                  s);
@@ -2948,7 +2955,8 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
 
      /* setup VGA */
      vga_common_init(&s->vga);
-     cirrus_init_common(s, device_id, 1, pci_address_space(dev));
+     cirrus_init_common(s, device_id, 1, pci_address_space(dev),
+                        pci_address_space_io(dev));
      s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
                                       s->vga.screen_dump, s->vga.text_update,
                                       &s->vga);

From 568fd159e4ca82d213706acd2cf4c94f27537096 Mon Sep 17 00:00:00 2001
From: Julien Grall 
Date: Wed, 19 Sep 2012 12:50:07 +0100
Subject: [PATCH 1826/2270] serial: Replace register_ioport_*
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Replace all register_ioport_*() with a MemoryRegion.
This permits to use the new Memory stuff like listeners.

For more flexibility, the IO address space is passed as an argument.

Signed-off-by: Julien Grall 
Acked-by: Avi Kivity 
[AF: Rebased onto serial split]
Signed-off-by: Andreas Färber 
---
 hw/mips_mipssim.c | 3 ++-
 hw/serial.c       | 4 ++--
 hw/serial.h       | 2 +-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index a95a3c1f11..20b5f1a58c 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -217,7 +217,8 @@ mips_mipssim_init(QEMUMachineInitArgs *args)
     /* A single 16450 sits at offset 0x3f8. It is attached to
        MIPS CPU INT2, which is interrupt 4. */
     if (serial_hds[0])
-        serial_init(0x3f8, env->irq[4], 115200, serial_hds[0]);
+        serial_init(0x3f8, env->irq[4], 115200, serial_hds[0],
+                    get_system_io());
 
     if (nd_table[0].used)
         /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */
diff --git a/hw/serial.c b/hw/serial.c
index 60283eab91..07a2a11931 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -718,7 +718,7 @@ const MemoryRegionOps serial_io_ops = {
 };
 
 SerialState *serial_init(int base, qemu_irq irq, int baudbase,
-                         CharDriverState *chr)
+                         CharDriverState *chr, MemoryRegion *system_io)
 {
     SerialState *s;
 
@@ -732,7 +732,7 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase,
     vmstate_register(NULL, base, &vmstate_serial, s);
 
     memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
-    memory_region_add_subregion(get_system_io(), base, &s->io);
+    memory_region_add_subregion(system_io, base, &s->io);
 
     return s;
 }
diff --git a/hw/serial.h b/hw/serial.h
index f1e3c4aaa7..ed1a5cd43e 100644
--- a/hw/serial.h
+++ b/hw/serial.h
@@ -89,7 +89,7 @@ void serial_set_frequency(SerialState *s, uint32_t frequency);
 
 /* legacy pre qom */
 SerialState *serial_init(int base, qemu_irq irq, int baudbase,
-                         CharDriverState *chr);
+                         CharDriverState *chr, MemoryRegion *system_io);
 SerialState *serial_mm_init(MemoryRegion *address_space,
                             hwaddr base, int it_shift,
                             qemu_irq irq, int baudbase,

From 258711c6448c44b60b0fecef1d3b09c71e23e304 Mon Sep 17 00:00:00 2001
From: Julien Grall 
Date: Wed, 19 Sep 2012 12:50:08 +0100
Subject: [PATCH 1827/2270] hw/pc.c: Replace register_ioport_*
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Replace all register_ioport_*() with portio_*() or a MemoryRegion.
This permits to use the new Memory stuff like listeners.

Signed-off-by: Julien Grall 
Acked-by: Avi Kivity 
[AF: Rebased onto hwaddr]
Signed-off-by: Andreas Färber 
---
 hw/pc.c | 49 ++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 40 insertions(+), 9 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 2b5bbbfb30..b11e7c4adc 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -98,7 +98,8 @@ void gsi_handler(void *opaque, int n, int level)
     qemu_set_irq(s->ioapic_irq[n], level);
 }
 
-static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
+static void ioport80_write(void *opaque, hwaddr addr, uint64_t data,
+                           unsigned size)
 {
 }
 
@@ -116,7 +117,8 @@ void cpu_set_ferr(CPUX86State *s)
     qemu_irq_raise(ferr_irq);
 }
 
-static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data)
+static void ioportF0_write(void *opaque, hwaddr addr, uint64_t data,
+                           unsigned size)
 {
     qemu_irq_lower(ferr_irq);
 }
@@ -567,6 +569,14 @@ int e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
     return index;
 }
 
+static const MemoryRegionPortio bochs_bios_portio_list[] = {
+    { 0x500, 1, 1, .write = bochs_bios_write, }, /* 0x500 */
+    { 0x501, 1, 1, .write = bochs_bios_write, }, /* 0x501 */
+    { 0x501, 2, 2, .write = bochs_bios_write, }, /* 0x501 */
+    { 0x8900, 1, 1, .write = bochs_bios_write, }, /* 0x8900 */
+    PORTIO_END_OF_LIST(),
+};
+
 static void *bochs_bios_init(void)
 {
     void *fw_cfg;
@@ -574,12 +584,11 @@ static void *bochs_bios_init(void)
     size_t smbios_len;
     uint64_t *numa_fw_cfg;
     int i, j;
+    PortioList *bochs_bios_port_list = g_new(PortioList, 1);
 
-    register_ioport_write(0x8900, 1, 1, bochs_bios_write, NULL);
-
-    register_ioport_write(0x501, 1, 1, bochs_bios_write, NULL);
-    register_ioport_write(0x501, 1, 2, bochs_bios_write, NULL);
-    register_ioport_write(0x502, 1, 2, bochs_bios_write, NULL);
+    portio_list_init(bochs_bios_port_list, bochs_bios_portio_list,
+                     NULL, "bochs-bios");
+    portio_list_add(bochs_bios_port_list, get_system_io(), 0x0);
 
     fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
 
@@ -967,6 +976,24 @@ static void cpu_request_exit(void *opaque, int irq, int level)
     }
 }
 
+static const MemoryRegionOps ioport80_io_ops = {
+    .write = ioport80_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
+static const MemoryRegionOps ioportF0_io_ops = {
+    .write = ioportF0_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
 void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
                           ISADevice **rtc_state,
                           ISADevice **floppy,
@@ -981,10 +1008,14 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
     qemu_irq *a20_line;
     ISADevice *i8042, *port92, *vmmouse, *pit = NULL;
     qemu_irq *cpu_exit_irq;
+    MemoryRegion *ioport80_io = g_new(MemoryRegion, 1);
+    MemoryRegion *ioportF0_io = g_new(MemoryRegion, 1);
 
-    register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
+    memory_region_init_io(ioport80_io, &ioport80_io_ops, NULL, "ioport80", 1);
+    memory_region_add_subregion(isa_bus->address_space_io, 0x80, ioport80_io);
 
-    register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
+    memory_region_init_io(ioportF0_io, &ioportF0_io_ops, NULL, "ioportF0", 1);
+    memory_region_add_subregion(isa_bus->address_space_io, 0xf0, ioportF0_io);
 
     /*
      * Check if an HPET shall be created.

From 582299336879504353e60c7937fbc70fea93f3da Mon Sep 17 00:00:00 2001
From: Julien Grall 
Date: Wed, 19 Sep 2012 12:50:09 +0100
Subject: [PATCH 1828/2270] hw/dma.c: Replace register_ioport_*
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Replace all register_ioport_*() with the new Memory API functions.
This permits to use the new Memory stuff like listeners.

Signed-off-by: Julien Grall 
Acked-by: Avi Kivity 
[AF: Rebased onto hwaddr]
Signed-off-by: Andreas Färber 
---
 hw/dma.c | 106 ++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 70 insertions(+), 36 deletions(-)

diff --git a/hw/dma.c b/hw/dma.c
index d6aeac2834..c2d7b21562 100644
--- a/hw/dma.c
+++ b/hw/dma.c
@@ -58,6 +58,8 @@ static struct dma_cont {
     int dshift;
     struct dma_regs regs[4];
     qemu_irq *cpu_request_exit;
+    MemoryRegion channel_io;
+    MemoryRegion cont_io;
 } dma_controllers[2];
 
 enum {
@@ -149,7 +151,7 @@ static inline int getff (struct dma_cont *d)
     return ff;
 }
 
-static uint32_t read_chan (void *opaque, uint32_t nport)
+static uint64_t read_chan(void *opaque, hwaddr nport, unsigned size)
 {
     struct dma_cont *d = opaque;
     int ichan, nreg, iport, ff, val, dir;
@@ -171,7 +173,8 @@ static uint32_t read_chan (void *opaque, uint32_t nport)
     return (val >> (d->dshift + (ff << 3))) & 0xff;
 }
 
-static void write_chan (void *opaque, uint32_t nport, uint32_t data)
+static void write_chan(void *opaque, hwaddr nport, uint64_t data,
+                       unsigned size)
 {
     struct dma_cont *d = opaque;
     int iport, ichan, nreg;
@@ -189,22 +192,23 @@ static void write_chan (void *opaque, uint32_t nport, uint32_t data)
     }
 }
 
-static void write_cont (void *opaque, uint32_t nport, uint32_t data)
+static void write_cont(void *opaque, hwaddr nport, uint64_t data,
+                       unsigned size)
 {
     struct dma_cont *d = opaque;
     int iport, ichan = 0;
 
     iport = (nport >> d->dshift) & 0x0f;
     switch (iport) {
-    case 0x08:                  /* command */
+    case 0x01:                  /* command */
         if ((data != 0) && (data & CMD_NOT_SUPPORTED)) {
-            dolog ("command %#x not supported\n", data);
+            dolog("command %"PRIx64" not supported\n", data);
             return;
         }
         d->command = data;
         break;
 
-    case 0x09:
+    case 0x02:
         ichan = data & 3;
         if (data & 4) {
             d->status |= 1 << (ichan + 4);
@@ -216,7 +220,7 @@ static void write_cont (void *opaque, uint32_t nport, uint32_t data)
         DMA_run();
         break;
 
-    case 0x0a:                  /* single mask */
+    case 0x03:                  /* single mask */
         if (data & 4)
             d->mask |= 1 << (data & 3);
         else
@@ -224,7 +228,7 @@ static void write_cont (void *opaque, uint32_t nport, uint32_t data)
         DMA_run();
         break;
 
-    case 0x0b:                  /* mode */
+    case 0x04:                  /* mode */
         {
             ichan = data & 3;
 #ifdef DEBUG_DMA
@@ -243,23 +247,23 @@ static void write_cont (void *opaque, uint32_t nport, uint32_t data)
             break;
         }
 
-    case 0x0c:                  /* clear flip flop */
+    case 0x05:                  /* clear flip flop */
         d->flip_flop = 0;
         break;
 
-    case 0x0d:                  /* reset */
+    case 0x06:                  /* reset */
         d->flip_flop = 0;
         d->mask = ~0;
         d->status = 0;
         d->command = 0;
         break;
 
-    case 0x0e:                  /* clear mask for all channels */
+    case 0x07:                  /* clear mask for all channels */
         d->mask = 0;
         DMA_run();
         break;
 
-    case 0x0f:                  /* write mask for all channels */
+    case 0x08:                  /* write mask for all channels */
         d->mask = data;
         DMA_run();
         break;
@@ -277,7 +281,7 @@ static void write_cont (void *opaque, uint32_t nport, uint32_t data)
 #endif
 }
 
-static uint32_t read_cont (void *opaque, uint32_t nport)
+static uint64_t read_cont(void *opaque, hwaddr nport, unsigned size)
 {
     struct dma_cont *d = opaque;
     int iport, val;
@@ -463,7 +467,7 @@ void DMA_schedule(int nchan)
 static void dma_reset(void *opaque)
 {
     struct dma_cont *d = opaque;
-    write_cont (d, (0x0d << d->dshift), 0);
+    write_cont(d, (0x06 << d->dshift), 0, 1);
 }
 
 static int dma_phony_handler (void *opaque, int nchan, int dma_pos, int dma_len)
@@ -473,38 +477,68 @@ static int dma_phony_handler (void *opaque, int nchan, int dma_pos, int dma_len)
     return dma_pos;
 }
 
+
+static const MemoryRegionOps channel_io_ops = {
+    .read = read_chan,
+    .write = write_chan,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
+/* IOport from page_base */
+static const MemoryRegionPortio page_portio_list[] = {
+    { 0x01, 3, 1, .write = write_page, .read = read_page, },
+    { 0x07, 1, 1, .write = write_page, .read = read_page, },
+    PORTIO_END_OF_LIST(),
+};
+
+/* IOport from pageh_base */
+static const MemoryRegionPortio pageh_portio_list[] = {
+    { 0x01, 3, 1, .write = write_pageh, .read = read_pageh, },
+    { 0x07, 3, 1, .write = write_pageh, .read = read_pageh, },
+    PORTIO_END_OF_LIST(),
+};
+
+static const MemoryRegionOps cont_io_ops = {
+    .read = read_cont,
+    .write = write_cont,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
 /* dshift = 0: 8 bit DMA, 1 = 16 bit DMA */
 static void dma_init2(struct dma_cont *d, int base, int dshift,
                       int page_base, int pageh_base,
                       qemu_irq *cpu_request_exit)
 {
-    static const int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 };
     int i;
 
     d->dshift = dshift;
     d->cpu_request_exit = cpu_request_exit;
-    for (i = 0; i < 8; i++) {
-        register_ioport_write (base + (i << dshift), 1, 1, write_chan, d);
-        register_ioport_read (base + (i << dshift), 1, 1, read_chan, d);
-    }
-    for (i = 0; i < ARRAY_SIZE (page_port_list); i++) {
-        register_ioport_write (page_base + page_port_list[i], 1, 1,
-                               write_page, d);
-        register_ioport_read (page_base + page_port_list[i], 1, 1,
-                              read_page, d);
-        if (pageh_base >= 0) {
-            register_ioport_write (pageh_base + page_port_list[i], 1, 1,
-                                   write_pageh, d);
-            register_ioport_read (pageh_base + page_port_list[i], 1, 1,
-                                  read_pageh, d);
-        }
-    }
-    for (i = 0; i < 8; i++) {
-        register_ioport_write (base + ((i + 8) << dshift), 1, 1,
-                               write_cont, d);
-        register_ioport_read (base + ((i + 8) << dshift), 1, 1,
-                              read_cont, d);
+
+    memory_region_init_io(&d->channel_io, &channel_io_ops, d,
+                          "dma-chan", 8 << d->dshift);
+    memory_region_add_subregion(isa_address_space_io(NULL),
+                                base, &d->channel_io);
+
+    isa_register_portio_list(NULL, page_base, page_portio_list, d,
+                             "dma-page");
+    if (pageh_base >= 0) {
+        isa_register_portio_list(NULL, pageh_base, pageh_portio_list, d,
+                                 "dma-pageh");
     }
+
+    memory_region_init_io(&d->cont_io, &cont_io_ops, d, "dma-cont",
+                          8 << d->dshift);
+    memory_region_add_subregion(isa_address_space_io(NULL),
+                                base + (8 << d->dshift), &d->cont_io);
+
     qemu_register_reset(dma_reset, d);
     dma_reset(d);
     for (i = 0; i < ARRAY_SIZE (d->regs); ++i) {

From d4d230da08918183929c7d6cb54824b391536904 Mon Sep 17 00:00:00 2001
From: Peter Crosthwaite 
Date: Wed, 5 Dec 2012 16:53:42 +1000
Subject: [PATCH 1829/2270] xilinx_axienet: Implement R_IS behaviour

The interrupt status register R_IS is the standard clear-on-write behaviour.
This was unimplemented and defaulting to updating the register to the written
value. Implemented clear-on-write.

Reported-by: Jason Wu 
Signed-off-by: Peter Crosthwaite 
Signed-off-by: Edgar E. Iglesias 
---
 hw/xilinx_axienet.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index baae02bd66..f2e3bf1274 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -591,6 +591,10 @@ static void enet_write(void *opaque, hwaddr addr,
             s->maddr[s->fmi & 3][addr & 1] = value;
             break;
 
+        case R_IS:
+            s->regs[addr] &= ~value;
+            break;
+
         case 0x8000 ... 0x83ff:
             s->ext_mtable[addr - 0x8000] = value;
             break;

From 859cc10d23e619153670fc58683373fa24d25b68 Mon Sep 17 00:00:00 2001
From: Peter Crosthwaite 
Date: Wed, 5 Dec 2012 16:53:43 +1000
Subject: [PATCH 1830/2270] xilinx_uartlite: suppress "cannot receive message"

This message is not an error condition, its just informing the user that
the device is corking the uart traffic to not drop characters.

Reported-by: Jason Wu 
Signed-off-by: Peter Crosthwaite 
Signed-off-by: Edgar E. Iglesias 
---
 hw/xilinx_uartlite.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
index d20fc4124b..f890f2363d 100644
--- a/hw/xilinx_uartlite.c
+++ b/hw/xilinx_uartlite.c
@@ -182,12 +182,8 @@ static void uart_rx(void *opaque, const uint8_t *buf, int size)
 static int uart_can_rx(void *opaque)
 {
     struct xlx_uartlite *s = opaque;
-    int r;
 
-    r = s->rx_fifo_len < sizeof(s->rx_fifo);
-    if (!r)
-        printf("cannot receive!\n");
-    return r;
+    return s->rx_fifo_len < sizeof(s->rx_fifo);
 }
 
 static void uart_event(void *opaque, int event)

From 80625b97b52836b944a6438e8e3e9d992e6a00b6 Mon Sep 17 00:00:00 2001
From: Peter Crosthwaite 
Date: Wed, 5 Dec 2012 16:53:44 +1000
Subject: [PATCH 1831/2270] xilinx_uartlite: Accept input after rx FIFO pop

The device return false from the can receive function when the FIFO is
full. This mean the device should check for buffered input whenever a byte is
popped from the FIFO.

Reported-by: Jason Wu 
Signed-off-by: Peter Crosthwaite 
Signed-off-by: Edgar E. Iglesias 
---
 hw/xilinx_uartlite.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
index f890f2363d..02c5850331 100644
--- a/hw/xilinx_uartlite.c
+++ b/hw/xilinx_uartlite.c
@@ -97,6 +97,7 @@ uart_read(void *opaque, hwaddr addr, unsigned int size)
                 s->rx_fifo_len--;
             uart_update_status(s);
             uart_update_irq(s);
+            qemu_chr_accept_input(s->chr);
             break;
 
         default:

From 9fd2ecdc8cb2dc1a8a7c57b6c9c60bc9947b6a73 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Thu, 11 Oct 2012 14:20:23 +0200
Subject: [PATCH 1832/2270] virtfs-proxy-helper: use setresuid and setresgid

The setfsuid and setfsgid system calls are obscure and they complicate
the error checking (that glibc's warn_unused_result "feature" forces
us to do).  Switch to the standard setresuid and setresgid functions.

Signed-off-by: Paolo Bonzini 
---
 fsdev/virtfs-proxy-helper.c | 93 +++++++++++++++++++++++++------------
 1 file changed, 64 insertions(+), 29 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index f9a8270ee9..df2a9392b1 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -272,31 +272,76 @@ static int send_status(int sockfd, struct iovec *iovec, int status)
 /*
  * from man 7 capabilities, section
  * Effect of User ID Changes on Capabilities:
- * 4. If the file system user ID is changed from 0 to nonzero (see setfsuid(2))
- * then the following capabilities are cleared from the effective set:
- * CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH,  CAP_FOWNER, CAP_FSETID,
- * CAP_LINUX_IMMUTABLE  (since  Linux 2.2.30), CAP_MAC_OVERRIDE, and CAP_MKNOD
- * (since Linux 2.2.30). If the file system UID is changed from nonzero to 0,
- * then any of these capabilities that are enabled in the permitted set
- * are enabled in the effective set.
+ * If the effective user ID is changed from nonzero to 0, then the permitted
+ * set is copied to the effective set.  If the effective user ID is changed
+ * from 0 to nonzero, then all capabilities are are cleared from the effective
+ * set.
+ *
+ * The setfsuid/setfsgid man pages warn that changing the effective user ID may
+ * expose the program to unwanted signals, but this is not true anymore: for an
+ * unprivileged (without CAP_KILL) program to send a signal, the real or
+ * effective user ID of the sending process must equal the real or saved user
+ * ID of the target process.  Even when dropping privileges, it is enough to
+ * keep the saved UID to a "privileged" value and virtfs-proxy-helper won't
+ * be exposed to signals.  So just use setresuid/setresgid.
  */
-static int setfsugid(int uid, int gid)
+static int setugid(int uid, int gid, int *suid, int *sgid)
 {
+    int retval;
+
     /*
-     * We still need DAC_OVERRIDE because  we don't change
+     * We still need DAC_OVERRIDE because we don't change
      * supplementary group ids, and hence may be subjected DAC rules
      */
     cap_value_t cap_list[] = {
         CAP_DAC_OVERRIDE,
     };
 
-    setfsgid(gid);
-    setfsuid(uid);
+    *suid = geteuid();
+    *sgid = getegid();
+
+    if (setresgid(-1, gid, *sgid) == -1) {
+        retval = -errno;
+        goto err_out;
+    }
+
+    if (setresuid(-1, uid, *suid) == -1) {
+        retval = -errno;
+        goto err_sgid;
+    }
 
     if (uid != 0 || gid != 0) {
-        return do_cap_set(cap_list, ARRAY_SIZE(cap_list), 0);
+        if (do_cap_set(cap_list, ARRAY_SIZE(cap_list), 0) < 0) {
+            retval = -errno;
+            goto err_suid;
+        }
     }
     return 0;
+
+err_suid:
+    if (setresuid(-1, *suid, *suid) == -1) {
+        abort();
+    }
+err_sgid:
+    if (setresgid(-1, *sgid, *sgid) == -1) {
+        abort();
+    }
+err_out:
+    return retval;
+}
+
+/*
+ * This is used to reset the ugid back with the saved values
+ * There is nothing much we can do checking error values here.
+ */
+static void resetugid(int suid, int sgid)
+{
+    if (setresgid(-1, sgid, sgid) == -1) {
+        abort();
+    }
+    if (setresuid(-1, suid, suid) == -1) {
+        abort();
+    }
 }
 
 /*
@@ -578,18 +623,15 @@ static int do_create_others(int type, struct iovec *iovec)
 
     v9fs_string_init(&path);
     v9fs_string_init(&oldpath);
-    cur_uid = geteuid();
-    cur_gid = getegid();
 
     retval = proxy_unmarshal(iovec, offset, "dd", &uid, &gid);
     if (retval < 0) {
         return retval;
     }
     offset += retval;
-    retval = setfsugid(uid, gid);
+    retval = setugid(uid, gid, &cur_uid, &cur_gid);
     if (retval < 0) {
-        retval = -errno;
-        goto err_out;
+        goto unmarshal_err_out;
     }
     switch (type) {
     case T_MKNOD:
@@ -619,9 +661,10 @@ static int do_create_others(int type, struct iovec *iovec)
     }
 
 err_out:
+    resetugid(cur_uid, cur_gid);
+unmarshal_err_out:
     v9fs_string_free(&path);
     v9fs_string_free(&oldpath);
-    setfsugid(cur_uid, cur_gid);
     return retval;
 }
 
@@ -641,24 +684,16 @@ static int do_create(struct iovec *iovec)
     if (ret < 0) {
         goto unmarshal_err_out;
     }
-    cur_uid = geteuid();
-    cur_gid = getegid();
-    ret = setfsugid(uid, gid);
+    ret = setugid(uid, gid, &cur_uid, &cur_gid);
     if (ret < 0) {
-        /*
-         * On failure reset back to the
-         * old uid/gid
-         */
-        ret = -errno;
-        goto err_out;
+        goto unmarshal_err_out;
     }
     ret = open(path.data, flags, mode);
     if (ret < 0) {
         ret = -errno;
     }
 
-err_out:
-    setfsugid(cur_uid, cur_gid);
+    resetugid(cur_uid, cur_gid);
 unmarshal_err_out:
     v9fs_string_free(&path);
     return ret;

From 34f5606ee101f82a247d09d05644ad2a63c8e342 Mon Sep 17 00:00:00 2001
From: Petar Jovanovic 
Date: Mon, 26 Nov 2012 16:13:21 +0100
Subject: [PATCH 1833/2270] target-mips: Fix incorrect code and test for INSV

Content of register rs should be shifted for pos before applying a mask.
This change contains both fix for the instruction and to the existing test.

Signed-off-by: Petar Jovanovic 
Reviewed-by: Eric Johnson 
Signed-off-by: Aurelien Jarno 
---
 target-mips/dsp_helper.c         | 2 +-
 tests/tcg/mips/mips32-dsp/insv.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index e7949c22c0..fda5f0460b 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -3152,7 +3152,7 @@ target_ulong helper_##name(CPUMIPSState *env, target_ulong rs,  \
                                                                 \
     filter = ((int32_t)0x01 << size) - 1;                       \
     filter = filter << pos;                                     \
-    temprs = rs & filter;                                       \
+    temprs = (rs << pos) & filter;                              \
     temprt = rt & ~filter;                                      \
     temp = temprs | temprt;                                     \
                                                                 \
diff --git a/tests/tcg/mips/mips32-dsp/insv.c b/tests/tcg/mips/mips32-dsp/insv.c
index 7e3b047606..243b00733d 100644
--- a/tests/tcg/mips/mips32-dsp/insv.c
+++ b/tests/tcg/mips/mips32-dsp/insv.c
@@ -10,7 +10,7 @@ int main()
     dsp    = 0x305;
     rt     = 0x12345678;
     rs     = 0x87654321;
-    result = 0x12345338;
+    result = 0x12345438;
     __asm
         ("wrdsp %2, 0x03\n\t"
          "insv  %0, %1\n\t"

From 19e6c50d2d843220efbdd3b2db21d83c122c364a Mon Sep 17 00:00:00 2001
From: Petar Jovanovic 
Date: Wed, 5 Dec 2012 00:29:10 +0100
Subject: [PATCH 1834/2270] target-mips: Fix incorrect shift for SHILO and
 SHILOV

helper_shilo has not been shifting an accumulator value correctly for negative
values in 'shift' field. Minor optimization for shift=0 case.
This change also adds tests that will trigger issue and check for regressions.

Signed-off-by: Petar Jovanovic 
Reviewed-by: Richard Henderson 
Reviewed-by: Eric Johnson 
Signed-off-by: Aurelien Jarno 
---
 target-mips/dsp_helper.c           | 17 +++++++++--------
 tests/tcg/mips/mips32-dsp/shilo.c  | 18 ++++++++++++++++++
 tests/tcg/mips/mips32-dsp/shilov.c | 20 ++++++++++++++++++++
 3 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index fda5f0460b..14daf91950 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -3814,17 +3814,18 @@ void helper_shilo(target_ulong ac, target_ulong rs, CPUMIPSState *env)
 
     rs5_0 = rs & 0x3F;
     rs5_0 = (int8_t)(rs5_0 << 2) >> 2;
-    rs5_0 = MIPSDSP_ABS(rs5_0);
+
+    if (unlikely(rs5_0 == 0)) {
+        return;
+    }
+
     acc   = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) |
             ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
-    if (rs5_0 == 0) {
-        temp = acc;
+
+    if (rs5_0 > 0) {
+        temp = acc >> rs5_0;
     } else {
-        if (rs5_0 > 0) {
-            temp = acc >> rs5_0;
-        } else {
-            temp = acc << rs5_0;
-        }
+        temp = acc << -rs5_0;
     }
 
     env->active_tc.HI[ac] = (target_ulong)(int32_t)((temp & MIPSDSP_LHI) >> 32);
diff --git a/tests/tcg/mips/mips32-dsp/shilo.c b/tests/tcg/mips/mips32-dsp/shilo.c
index b686616d80..ce8ebc69c2 100644
--- a/tests/tcg/mips/mips32-dsp/shilo.c
+++ b/tests/tcg/mips/mips32-dsp/shilo.c
@@ -23,5 +23,23 @@ int main()
     assert(ach == resulth);
     assert(acl == resultl);
 
+
+    ach = 0x1;
+    acl = 0x80000000;
+
+    resulth = 0x3;
+    resultl = 0x0;
+
+    __asm
+        ("mthi %0, $ac1\n\t"
+         "mtlo %1, $ac1\n\t"
+         "shilo $ac1, -1\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
     return 0;
 }
diff --git a/tests/tcg/mips/mips32-dsp/shilov.c b/tests/tcg/mips/mips32-dsp/shilov.c
index f186032a14..e1d6cea4b6 100644
--- a/tests/tcg/mips/mips32-dsp/shilov.c
+++ b/tests/tcg/mips/mips32-dsp/shilov.c
@@ -25,5 +25,25 @@ int main()
     assert(ach == resulth);
     assert(acl == resultl);
 
+
+    rs  = 0xffffffff;
+    ach = 0x1;
+    acl = 0x80000000;
+
+    resulth = 0x3;
+    resultl = 0x0;
+
+    __asm
+        ("mthi %0, $ac1\n\t"
+         "mtlo %1, $ac1\n\t"
+         "shilov $ac1, %2\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
     return 0;
 }

From 89e0e9c71e608f3679f30e88d988903536c6f7f3 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Tue, 23 Oct 2012 20:42:56 -0200
Subject: [PATCH 1835/2270] user: Move *-user/qemu-types.h to main directory
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The bsd-user/qemu-types.h and linux-user/qemu-types.h files are almost
the same, but linux-user has the additional definitions of tswapal().

This moves the linux-user file to the main directory, so the same file
can be used by linux-user and bsd-user.

Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 bsd-user/qemu-types.h                   | 24 ------------------------
 linux-user/qemu-types.h => qemu-types.h |  0
 2 files changed, 24 deletions(-)
 delete mode 100644 bsd-user/qemu-types.h
 rename linux-user/qemu-types.h => qemu-types.h (100%)

diff --git a/bsd-user/qemu-types.h b/bsd-user/qemu-types.h
deleted file mode 100644
index 1adda9fbdb..0000000000
--- a/bsd-user/qemu-types.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef QEMU_TYPES_H
-#define QEMU_TYPES_H
-#include "cpu.h"
-
-#ifdef TARGET_ABI32
-typedef uint32_t abi_ulong;
-typedef int32_t abi_long;
-#define TARGET_ABI_FMT_lx "%08x"
-#define TARGET_ABI_FMT_ld "%d"
-#define TARGET_ABI_FMT_lu "%u"
-#define TARGET_ABI_BITS 32
-#else
-typedef target_ulong abi_ulong;
-typedef target_long abi_long;
-#define TARGET_ABI_FMT_lx TARGET_FMT_lx
-#define TARGET_ABI_FMT_ld TARGET_FMT_ld
-#define TARGET_ABI_FMT_lu TARGET_FMT_lu
-#define TARGET_ABI_BITS TARGET_LONG_BITS
-/* for consistency, define ABI32 too */
-#if TARGET_ABI_BITS == 32
-#define TARGET_ABI32 1
-#endif
-#endif
-#endif
diff --git a/linux-user/qemu-types.h b/qemu-types.h
similarity index 100%
rename from linux-user/qemu-types.h
rename to qemu-types.h

From ee9baa00f2623f1f627913f62d60f2888286319a Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Tue, 23 Oct 2012 22:54:34 -0200
Subject: [PATCH 1836/2270] user: Rename qemu-types.h to qemu-user-types.h
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The header file is specific for *-user, but I plan to introduce a more
generic qemu-types.h file, so I'm renaming it.

Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 bsd-user/qemu.h                   | 2 +-
 cpu-all.h                         | 2 +-
 linux-user/qemu.h                 | 2 +-
 qemu-types.h => qemu-user-types.h | 0
 4 files changed, 3 insertions(+), 3 deletions(-)
 rename qemu-types.h => qemu-user-types.h (100%)

diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index 8a5ee3d81f..d2688995bd 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -11,7 +11,7 @@
 #include 
 #endif /* DEBUG_REMAP */
 
-#include "qemu-types.h"
+#include "qemu-user-types.h"
 
 enum BSDType {
     target_freebsd,
diff --git a/cpu-all.h b/cpu-all.h
index c9c51b83ac..d6b2b19743 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -180,7 +180,7 @@ static inline void tswap64s(uint64_t *s)
 
 #if defined(CONFIG_USER_ONLY)
 #include 
-#include "qemu-types.h"
+#include "qemu-user-types.h"
 
 /* On some host systems the guest address space is reserved on the host.
  * This allows the guest address space to be offset to a convenient location.
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 5e53dca09e..ceddb3ce72 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -11,7 +11,7 @@
 #include 
 #endif /* DEBUG_REMAP */
 
-#include "qemu-types.h"
+#include "qemu-user-types.h"
 
 #include "thunk.h"
 #include "syscall_defs.h"
diff --git a/qemu-types.h b/qemu-user-types.h
similarity index 100%
rename from qemu-types.h
rename to qemu-user-types.h

From 90f0cfa410544727ac4e9c130f9e5032e1fb9b71 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Tue, 23 Oct 2012 21:19:18 -0200
Subject: [PATCH 1837/2270] ui/vnc-palette.c: Include headers it needs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Include:
 -  for g_malloc0()
 -  for memset()

Some of those headers were probably being included by accident because
some other headers were including qemu-common.h, but those headers
should eventually stop including qemu-common.h.

Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 ui/vnc-palette.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/ui/vnc-palette.c b/ui/vnc-palette.c
index 63d5f64917..c130deee9d 100644
--- a/ui/vnc-palette.c
+++ b/ui/vnc-palette.c
@@ -27,6 +27,8 @@
  */
 
 #include "vnc-palette.h"
+#include 
+#include 
 
 static VncPaletteEntry *palette_find(const VncPalette *palette,
                                      uint32_t color, unsigned int hash)

From ccff63cac4f0d391187c9ee9aa2cab754df80c41 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Tue, 23 Oct 2012 21:35:44 -0200
Subject: [PATCH 1838/2270] qapi/qmp-registry.c: Include headers it needs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Include:
-  for g_malloc0()
-  for strcmp()

Some of those headers were probably being included by accident because
some other headers were including qemu-common.h, but those headers
should eventually stop including qemu-common.h.

Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 qapi/qmp-registry.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c
index 5414613377..c2c31b420d 100644
--- a/qapi/qmp-registry.c
+++ b/qapi/qmp-registry.c
@@ -12,6 +12,8 @@
  *
  */
 
+#include 
+#include 
 #include "qapi/qmp-core.h"
 
 static QTAILQ_HEAD(QmpCommandList, QmpCommand) qmp_commands =

From 4d4922c339abf67e47c79068d343ed41a020b8e2 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Tue, 23 Oct 2012 21:37:20 -0200
Subject: [PATCH 1839/2270] qga/channel-posix.c: Include headers it needs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Include:
 -  for errno
 -  &  for fcntl()
 -  for exit()
 - "osdep.h" for qemu_open()

Some of those headers were probably being included by accident because
some other headers were including qemu-common.h, but those headers
should eventually stop including qemu-common.h.

Signed-off-by: Eduardo Habkost 
Signed-off-by: Igor Mammedov 
Signed-off-by: Andreas Färber 
---
 qga/channel-posix.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/qga/channel-posix.c b/qga/channel-posix.c
index d152827bcf..769a559456 100644
--- a/qga/channel-posix.c
+++ b/qga/channel-posix.c
@@ -1,5 +1,10 @@
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include "osdep.h"
 #include "qemu_socket.h"
 #include "qga/channel.h"
 

From cad32159663c5910098e10d64f4b5b10648b0095 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Tue, 23 Oct 2012 21:55:19 -0200
Subject: [PATCH 1840/2270] qlist.h: Do not include qemu-common.h
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

I don't know why it was including it, as I don't see any code that
depends on anything from qemu-common.h.

Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 qlist.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/qlist.h b/qlist.h
index ae776f99c3..74089471df 100644
--- a/qlist.h
+++ b/qlist.h
@@ -15,7 +15,6 @@
 
 #include "qobject.h"
 #include "qemu-queue.h"
-#include "qemu-common.h"
 #include "qemu-queue.h"
 
 typedef struct QListEntry {

From 394e1bb79591c2fbfc873e5ccc38e92a3ba992cf Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Tue, 23 Oct 2012 21:41:52 -0200
Subject: [PATCH 1841/2270] Create qemu-types.h for struct typedefs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Instead of keeping all those struct typedefs in qemu-common.h, move it
to a header that can be safely included by other headers, containing
only the struct typedefs and not pulling in other dependencies.

Also, move some of the qdev-core.h typedefs to the new file, too, so
other headers don't need to include qdev-core.h only because of
DeviceState and other typedefs.

This will help us remove qemu-common.h dependencies from some headers
later.

Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 hw/qdev-core.h | 11 +--------
 qemu-common.h  | 52 +-----------------------------------------
 qemu-types.h   | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 63 insertions(+), 61 deletions(-)
 create mode 100644 qemu-types.h

diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index fff7f0f5ab..d672ccafe6 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -3,20 +3,11 @@
 
 #include "qemu-queue.h"
 #include "qemu-option.h"
+#include "qemu-types.h"
 #include "qemu/object.h"
 #include "hw/irq.h"
 #include "error.h"
 
-typedef struct Property Property;
-
-typedef struct PropertyInfo PropertyInfo;
-
-typedef struct CompatProperty CompatProperty;
-
-typedef struct BusState BusState;
-
-typedef struct BusClass BusClass;
-
 enum DevState {
     DEV_STATE_CREATED = 1,
     DEV_STATE_INITIALIZED,
diff --git a/qemu-common.h b/qemu-common.h
index cef264cc85..e67478607b 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -14,6 +14,7 @@
 
 #include "compiler.h"
 #include "config-host.h"
+#include "qemu-types.h"
 
 #if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__) || defined(__ia64__)
 #define WORDS_ALIGNED
@@ -21,15 +22,6 @@
 
 #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
 
-typedef struct QEMUTimer QEMUTimer;
-typedef struct QEMUFile QEMUFile;
-typedef struct QEMUBH QEMUBH;
-typedef struct DeviceState DeviceState;
-
-struct Monitor;
-typedef struct Monitor Monitor;
-typedef struct MigrationParams MigrationParams;
-
 /* we put basic includes here to avoid repeating them in device drivers */
 #include 
 #include 
@@ -258,48 +250,6 @@ struct ParallelIOArg {
 
 typedef int (*DMA_transfer_handler) (void *opaque, int nchan, int pos, int size);
 
-/* A load of opaque types so that device init declarations don't have to
-   pull in all the real definitions.  */
-typedef struct NICInfo NICInfo;
-typedef struct HCIInfo HCIInfo;
-typedef struct AudioState AudioState;
-typedef struct BlockDriverState BlockDriverState;
-typedef struct DriveInfo DriveInfo;
-typedef struct DisplayState DisplayState;
-typedef struct DisplayChangeListener DisplayChangeListener;
-typedef struct DisplaySurface DisplaySurface;
-typedef struct PixelFormat PixelFormat;
-typedef struct QemuConsole QemuConsole;
-typedef struct CharDriverState CharDriverState;
-typedef struct MACAddr MACAddr;
-typedef struct NetClientState NetClientState;
-typedef struct i2c_bus i2c_bus;
-typedef struct ISABus ISABus;
-typedef struct ISADevice ISADevice;
-typedef struct SMBusDevice SMBusDevice;
-typedef struct PCIHostState PCIHostState;
-typedef struct PCIExpressHost PCIExpressHost;
-typedef struct PCIBus PCIBus;
-typedef struct PCIDevice PCIDevice;
-typedef struct PCIExpressDevice PCIExpressDevice;
-typedef struct PCIBridge PCIBridge;
-typedef struct PCIEAERMsg PCIEAERMsg;
-typedef struct PCIEAERLog PCIEAERLog;
-typedef struct PCIEAERErr PCIEAERErr;
-typedef struct PCIEPort PCIEPort;
-typedef struct PCIESlot PCIESlot;
-typedef struct MSIMessage MSIMessage;
-typedef struct SerialState SerialState;
-typedef struct PCMCIACardState PCMCIACardState;
-typedef struct MouseTransformInfo MouseTransformInfo;
-typedef struct uWireSlave uWireSlave;
-typedef struct I2SCodec I2SCodec;
-typedef struct SSIBus SSIBus;
-typedef struct EventNotifier EventNotifier;
-typedef struct VirtIODevice VirtIODevice;
-typedef struct QEMUSGList QEMUSGList;
-typedef struct SHPCDevice SHPCDevice;
-
 typedef uint64_t pcibus_t;
 
 typedef enum LostTickPolicy {
diff --git a/qemu-types.h b/qemu-types.h
new file mode 100644
index 0000000000..fd532a268d
--- /dev/null
+++ b/qemu-types.h
@@ -0,0 +1,61 @@
+#ifndef QEMU_TYPEDEFS_H
+#define QEMU_TYPEDEFS_H
+
+/* A load of opaque types so that device init declarations don't have to
+   pull in all the real definitions.  */
+typedef struct QEMUTimer QEMUTimer;
+typedef struct QEMUFile QEMUFile;
+typedef struct QEMUBH QEMUBH;
+
+struct Monitor;
+typedef struct Monitor Monitor;
+typedef struct MigrationParams MigrationParams;
+
+typedef struct Property Property;
+typedef struct PropertyInfo PropertyInfo;
+typedef struct CompatProperty CompatProperty;
+typedef struct DeviceState DeviceState;
+typedef struct BusState BusState;
+typedef struct BusClass BusClass;
+
+typedef struct NICInfo NICInfo;
+typedef struct HCIInfo HCIInfo;
+typedef struct AudioState AudioState;
+typedef struct BlockDriverState BlockDriverState;
+typedef struct DriveInfo DriveInfo;
+typedef struct DisplayState DisplayState;
+typedef struct DisplayChangeListener DisplayChangeListener;
+typedef struct DisplaySurface DisplaySurface;
+typedef struct PixelFormat PixelFormat;
+typedef struct QemuConsole QemuConsole;
+typedef struct CharDriverState CharDriverState;
+typedef struct MACAddr MACAddr;
+typedef struct NetClientState NetClientState;
+typedef struct i2c_bus i2c_bus;
+typedef struct ISABus ISABus;
+typedef struct ISADevice ISADevice;
+typedef struct SMBusDevice SMBusDevice;
+typedef struct PCIHostState PCIHostState;
+typedef struct PCIExpressHost PCIExpressHost;
+typedef struct PCIBus PCIBus;
+typedef struct PCIDevice PCIDevice;
+typedef struct PCIExpressDevice PCIExpressDevice;
+typedef struct PCIBridge PCIBridge;
+typedef struct PCIEAERMsg PCIEAERMsg;
+typedef struct PCIEAERLog PCIEAERLog;
+typedef struct PCIEAERErr PCIEAERErr;
+typedef struct PCIEPort PCIEPort;
+typedef struct PCIESlot PCIESlot;
+typedef struct MSIMessage MSIMessage;
+typedef struct SerialState SerialState;
+typedef struct PCMCIACardState PCMCIACardState;
+typedef struct MouseTransformInfo MouseTransformInfo;
+typedef struct uWireSlave uWireSlave;
+typedef struct I2SCodec I2SCodec;
+typedef struct SSIBus SSIBus;
+typedef struct EventNotifier EventNotifier;
+typedef struct VirtIODevice VirtIODevice;
+typedef struct QEMUSGList QEMUSGList;
+typedef struct SHPCDevice SHPCDevice;
+
+#endif /* QEMU_TYPEDEFS_H */

From bcf7930105c26d09ae83cbd8b982d01bb421f215 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Tue, 23 Oct 2012 21:44:08 -0200
Subject: [PATCH 1842/2270] sysemu.h: Include qemu-types.h instead of
 qemu-common.h
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

It just needs the Monitor and DeviceState typedefs, so it doesn't need
all of qemu-common.h.

Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 sysemu.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sysemu.h b/sysemu.h
index f5ac664067..ab1ef8be5f 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -2,7 +2,7 @@
 #define SYSEMU_H
 /* Misc. things related to the system emulator.  */
 
-#include "qemu-common.h"
+#include "qemu-types.h"
 #include "qemu-option.h"
 #include "qemu-queue.h"
 #include "qemu-timer.h"

From 23e3fbec3355e67dbf26e98bbe33ef354097df8e Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Tue, 4 Dec 2012 11:19:34 -0200
Subject: [PATCH 1843/2270] qdev: qdev_create(): use error_report() instead of
 hw_error()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

hw_error() is specific for fatal hardware emulation errors, not for
internal errors related to the qdev object/class abstraction or object
initialization.

Replace it with an error_report() call, followed by abort().

This will also help reduce dependencies of the qdev code (as hw_error()
is from cpus.o, and depends on the CPU list from exec.o).

Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 hw/qdev.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/qdev.c b/hw/qdev.c
index 788b4da55c..599382cab2 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -109,10 +109,12 @@ DeviceState *qdev_create(BusState *bus, const char *name)
     dev = qdev_try_create(bus, name);
     if (!dev) {
         if (bus) {
-            hw_error("Unknown device '%s' for bus '%s'\n", name,
-                     object_get_typename(OBJECT(bus)));
+            error_report("Unknown device '%s' for bus '%s'\n", name,
+                         object_get_typename(OBJECT(bus)));
+            abort();
         } else {
-            hw_error("Unknown device '%s' for default sysbus\n", name);
+            error_report("Unknown device '%s' for default sysbus\n", name);
+            abort();
         }
     }
 

From 9f3fb5657b2133a408ccf40b4ab57dec9b4ce771 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Tue, 4 Dec 2012 17:34:38 -0200
Subject: [PATCH 1844/2270] target-i386/cpu.c: Coding style fixes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

- Use spaces instead of tabs on cpu_x86_cpuid().
- Use braces on 'if' statement cpu_x86_find_by_name().

Signed-off-by: Eduardo Habkost 
Reviewed-by: Igor Mammedov 
Signed-off-by: Andreas Färber 
---
 target-i386/cpu.c | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index c6c2ca03a1..754af6840b 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1215,7 +1215,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
 
     char *s = g_strdup(cpu_model);
     char *featurestr, *name = strtok(s, ",");
-    /* Features to be added*/
+    /* Features to be added */
     uint32_t plus_features = 0, plus_ext_features = 0;
     uint32_t plus_ext2_features = 0, plus_ext3_features = 0;
     uint32_t plus_kvm_features = kvm_default_features, plus_svm_features = 0;
@@ -1227,9 +1227,11 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
     uint32_t minus_7_0_ebx_features = 0;
     uint32_t numvalue;
 
-    for (def = x86_defs; def; def = def->next)
-        if (name && !strcmp(name, def->name))
+    for (def = x86_defs; def; def = def->next) {
+        if (name && !strcmp(name, def->name)) {
             break;
+        }
+    }
     if (kvm_enabled() && name && strcmp(name, "host") == 0) {
         kvm_cpu_fill_host(x86_cpu_def);
     } else if (!def) {
@@ -1835,17 +1837,17 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         }
         break;
     case 0x8000000A:
-	if (env->cpuid_ext3_features & CPUID_EXT3_SVM) {
-		*eax = 0x00000001; /* SVM Revision */
-		*ebx = 0x00000010; /* nr of ASIDs */
-		*ecx = 0;
-		*edx = env->cpuid_svm_features; /* optional features */
-	} else {
-		*eax = 0;
-		*ebx = 0;
-		*ecx = 0;
-		*edx = 0;
-	}
+        if (env->cpuid_ext3_features & CPUID_EXT3_SVM) {
+            *eax = 0x00000001; /* SVM Revision */
+            *ebx = 0x00000010; /* nr of ASIDs */
+            *ecx = 0;
+            *edx = env->cpuid_svm_features; /* optional features */
+        } else {
+            *eax = 0;
+            *ebx = 0;
+            *ecx = 0;
+            *edx = 0;
+        }
         break;
     case 0xC0000000:
         *eax = env->cpuid_xlevel2;

From 8f961357d06a0beeb7d3efbde1d754d82ff6a300 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Tue, 4 Dec 2012 17:34:39 -0200
Subject: [PATCH 1845/2270] target-i386: Separate feature string parsing from
 CPU model lookup
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Instead of parsing the whole cpu_model string inside
cpu_x86_find_by_name(), first split it into the CPU model name and the
full feature string, then parse the feature string into pieces.

When using CPU model classes, those two pieces of information will be
used at different moments (CPU model name will be used to find CPU
class, feature string will be used after CPU object was created), so
making the split in two steps will make it easier to refactor the code
later.

This should also help on the CPU properties work, that will just need to
replace the cpu_x86_parse_featurestr() logic (and can keep the CPU model
lookup code as-is).

Signed-off-by: Eduardo Habkost 
Reviewed-by: Igor Mammedov 
Signed-off-by: Andreas Färber 
---
 target-i386/cpu.c | 69 +++++++++++++++++++++++++++++++----------------
 1 file changed, 46 insertions(+), 23 deletions(-)

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 754af6840b..7877df174e 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1208,13 +1208,32 @@ static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque,
     cpu->env.tsc_khz = value / 1000;
 }
 
-static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
+static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *name)
 {
-    unsigned int i;
     x86_def_t *def;
 
-    char *s = g_strdup(cpu_model);
-    char *featurestr, *name = strtok(s, ",");
+    for (def = x86_defs; def; def = def->next) {
+        if (name && !strcmp(name, def->name)) {
+            break;
+        }
+    }
+    if (kvm_enabled() && name && strcmp(name, "host") == 0) {
+        kvm_cpu_fill_host(x86_cpu_def);
+    } else if (!def) {
+        return -1;
+    } else {
+        memcpy(x86_cpu_def, def, sizeof(*def));
+    }
+
+    return 0;
+}
+
+/* Parse "+feature,-feature,feature=foo" CPU feature string
+ */
+static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features)
+{
+    unsigned int i;
+    char *featurestr; /* Single 'key=value" string being parsed */
     /* Features to be added */
     uint32_t plus_features = 0, plus_ext_features = 0;
     uint32_t plus_ext2_features = 0, plus_ext3_features = 0;
@@ -1227,24 +1246,11 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
     uint32_t minus_7_0_ebx_features = 0;
     uint32_t numvalue;
 
-    for (def = x86_defs; def; def = def->next) {
-        if (name && !strcmp(name, def->name)) {
-            break;
-        }
-    }
-    if (kvm_enabled() && name && strcmp(name, "host") == 0) {
-        kvm_cpu_fill_host(x86_cpu_def);
-    } else if (!def) {
-        goto error;
-    } else {
-        memcpy(x86_cpu_def, def, sizeof(*def));
-    }
-
     add_flagname_to_bitmaps("hypervisor", &plus_features,
             &plus_ext_features, &plus_ext2_features, &plus_ext3_features,
             &plus_kvm_features, &plus_svm_features,  &plus_7_0_ebx_features);
 
-    featurestr = strtok(NULL, ",");
+    featurestr = features ? strtok(features, ",") : NULL;
 
     while (featurestr) {
         char *val;
@@ -1378,11 +1384,9 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
     if (x86_cpu_def->cpuid_7_0_ebx_features && x86_cpu_def->level < 7) {
         x86_cpu_def->level = 7;
     }
-    g_free(s);
     return 0;
 
 error:
-    g_free(s);
     return -1;
 }
 
@@ -1492,11 +1496,25 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model)
     CPUX86State *env = &cpu->env;
     x86_def_t def1, *def = &def1;
     Error *error = NULL;
+    char *name, *features;
+    gchar **model_pieces;
 
     memset(def, 0, sizeof(*def));
 
-    if (cpu_x86_find_by_name(def, cpu_model) < 0)
-        return -1;
+    model_pieces = g_strsplit(cpu_model, ",", 2);
+    if (!model_pieces[0]) {
+        goto error;
+    }
+    name = model_pieces[0];
+    features = model_pieces[1];
+
+    if (cpu_x86_find_by_name(def, name) < 0) {
+        goto error;
+    }
+
+    if (cpu_x86_parse_featurestr(def, features) < 0) {
+        goto error;
+    }
     if (def->vendor1) {
         env->cpuid_vendor1 = def->vendor1;
         env->cpuid_vendor2 = def->vendor2;
@@ -1553,9 +1571,14 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model)
     if (error) {
         fprintf(stderr, "%s\n", error_get_pretty(error));
         error_free(error);
-        return -1;
+        goto error;
     }
+
+    g_strfreev(model_pieces);
     return 0;
+error:
+    g_strfreev(model_pieces);
+    return -1;
 }
 
 #if !defined(CONFIG_USER_ONLY)

From 9df694eeb8447ae5a302b4d40df9a8b91dfc61da Mon Sep 17 00:00:00 2001
From: Igor Mammedov 
Date: Mon, 22 Oct 2012 17:03:10 +0200
Subject: [PATCH 1846/2270] target-i386: Use define for cpuid vendor string
 size
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Igor Mammedov 
Reviewed-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 target-i386/cpu.c | 6 +++---
 target-i386/cpu.h | 2 ++
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 7877df174e..a631ae9c87 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1106,13 +1106,13 @@ static char *x86_cpuid_get_vendor(Object *obj, Error **errp)
     char *value;
     int i;
 
-    value = (char *)g_malloc(12 + 1);
+    value = (char *)g_malloc(CPUID_VENDOR_SZ + 1);
     for (i = 0; i < 4; i++) {
         value[i    ] = env->cpuid_vendor1 >> (8 * i);
         value[i + 4] = env->cpuid_vendor2 >> (8 * i);
         value[i + 8] = env->cpuid_vendor3 >> (8 * i);
     }
-    value[12] = '\0';
+    value[CPUID_VENDOR_SZ] = '\0';
     return value;
 }
 
@@ -1123,7 +1123,7 @@ static void x86_cpuid_set_vendor(Object *obj, const char *value,
     CPUX86State *env = &cpu->env;
     int i;
 
-    if (strlen(value) != 12) {
+    if (strlen(value) != CPUID_VENDOR_SZ) {
         error_set(errp, QERR_PROPERTY_VALUE_BAD, "",
                   "vendor", value);
         return;
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 90ef1ff1e2..386c4f6d98 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -510,6 +510,8 @@
 #define CPUID_7_0_EBX_ADX      (1 << 19)
 #define CPUID_7_0_EBX_SMAP     (1 << 20)
 
+#define CPUID_VENDOR_SZ      12
+
 #define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */
 #define CPUID_VENDOR_INTEL_2 0x49656e69 /* "ineI" */
 #define CPUID_VENDOR_INTEL_3 0x6c65746e /* "ntel" */

From 038d3d44598232f5aad40d1c84c215f38a21576c Mon Sep 17 00:00:00 2001
From: Peter Crosthwaite 
Date: Thu, 15 Nov 2012 16:32:53 +1000
Subject: [PATCH 1847/2270] sd: Send debug printfery to stderr not stdout

Some debug printfs for SD are coming up in stdout. Redirected them to stderr
instead.

Signed-off-by: Peter Crosthwaite 
Reviewed-by: Peter Maydell 
Signed-off-by: Stefan Hajnoczi 
---
 hw/sd.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/sd.c b/hw/sd.c
index 3c34d43ad4..607edba9c8 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -1439,8 +1439,8 @@ send_response:
         int i;
         DPRINTF("Response:");
         for (i = 0; i < rsplen; i++)
-            printf(" %02x", response[i]);
-        printf(" state %d\n", sd->state);
+            fprintf(stderr, " %02x", response[i]);
+        fprintf(stderr, " state %d\n", sd->state);
     } else {
         DPRINTF("No response %d\n", sd->state);
     }

From bb5b5c20b7f68c79e036cd3ec5e9e6362c112670 Mon Sep 17 00:00:00 2001
From: Peter Maydell 
Date: Sat, 20 Oct 2012 20:37:04 +0100
Subject: [PATCH 1848/2270] configure: Remove stray debug output

Rather than printing a message saying we're silently falling
back to gthread coroutines when running on MacOS, actually
do it silently.

Signed-off-by: Peter Maydell 
Signed-off-by: Stefan Hajnoczi 
---
 configure | 2 --
 1 file changed, 2 deletions(-)

diff --git a/configure b/configure
index 994f7310b8..447e6ed976 100755
--- a/configure
+++ b/configure
@@ -2969,8 +2969,6 @@ EOF
     else
 	coroutine_backend=gthread
     fi
-  else
-    echo "Silently falling back into gthread backend under darwin"
   fi
 elif test "$coroutine" = "gthread" ; then
   coroutine_backend=gthread

From eac29d87c883fcbb54913ae20ed2bdccb4bcf7a3 Mon Sep 17 00:00:00 2001
From: Stefan Weil 
Date: Fri, 2 Nov 2012 08:14:12 +0100
Subject: [PATCH 1849/2270] Fix spelling (prefered -> preferred)

Signed-off-by: Stefan Weil 
Signed-off-by: Stefan Hajnoczi 
---
 configure       | 2 +-
 net/tap-win32.c | 7 ++++---
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/configure b/configure
index 447e6ed976..79605d2b75 100755
--- a/configure
+++ b/configure
@@ -2130,7 +2130,7 @@ if test "$pixman" = "system"; then
 else
   if test ! -d ${source_path}/pixman/pixman; then
     echo "ERROR: pixman not present. Your options:"
-    echo "  (1) Prefered: Install the pixman devel package (any recent"
+    echo "  (1) Preferred: Install the pixman devel package (any recent"
     echo "      distro should have packages as Xorg needs pixman too)."
     echo "  (2) Fetch the pixman submodule, using:"
     echo "      git submodule update --init pixman"
diff --git a/net/tap-win32.c b/net/tap-win32.c
index 8d2d32b1c3..f9bd74109c 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -565,7 +565,7 @@ static void tap_win32_free_buffer(tap_win32_overlapped_t *overlapped,
 }
 
 static int tap_win32_open(tap_win32_overlapped_t **phandle,
-                          const char *prefered_name)
+                          const char *preferred_name)
 {
     char device_path[256];
     char device_guid[0x100];
@@ -581,8 +581,9 @@ static int tap_win32_open(tap_win32_overlapped_t **phandle,
     DWORD version_len;
     DWORD idThread;
 
-    if (prefered_name != NULL)
-        snprintf(name_buffer, sizeof(name_buffer), "%s", prefered_name);
+    if (preferred_name != NULL) {
+        snprintf(name_buffer, sizeof(name_buffer), "%s", preferred_name);
+    }
 
     rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer));
     if (rc)

From a93cf9dfba171aa94e3c4002d58abef2a3732bfb Mon Sep 17 00:00:00 2001
From: Stefan Weil 
Date: Fri, 2 Nov 2012 08:29:53 +0100
Subject: [PATCH 1850/2270] Fix comments (adress -> address, layed -> laid,
 wierd -> weird)

Remove also a duplicated 'the'.

Signed-off-by: Stefan Weil 
Signed-off-by: Stefan Hajnoczi 
---
 slirp/ip_icmp.c | 2 +-
 tcg/tcg.h       | 4 ++--
 uri.c           | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index d571fd0b76..9f1cb08a18 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -352,7 +352,7 @@ icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
 
   ip->ip_ttl = MAXTTL;
   ip->ip_p = IPPROTO_ICMP;
-  ip->ip_dst = ip->ip_src;    /* ip adresses */
+  ip->ip_dst = ip->ip_src;    /* ip addresses */
   ip->ip_src = m->slirp->vhost_addr;
 
   (void ) ip_output((struct socket *)NULL, m);
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 9481e35ab4..e7de8c00a3 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -290,8 +290,8 @@ typedef int TCGv_i64;
 #define TCG_CALL_DUMMY_TCGV     MAKE_TCGV_I32(-1)
 #define TCG_CALL_DUMMY_ARG      ((TCGArg)(-1))
 
-/* Conditions.  Note that these are layed out for easy manipulation by
-   the the functions below:
+/* Conditions.  Note that these are laid out for easy manipulation by
+   the functions below:
      bit 0 is used for inverting;
      bit 1 is signed,
      bit 2 is unsigned,
diff --git a/uri.c b/uri.c
index dd922de339..138547b821 100644
--- a/uri.c
+++ b/uri.c
@@ -432,7 +432,7 @@ rfc3986_parse_host(URI *uri, const char **str)
 
     host = cur;
     /*
-     * IPv6 and future adressing scheme are enclosed between brackets
+     * IPv6 and future addressing scheme are enclosed between brackets
      */
     if (*cur == '[') {
         cur++;
@@ -1917,7 +1917,7 @@ done:
  *     http://site1.com/docs/pic1.gif   http://site1.com/docs/pic1.gif
  *
  *
- * Note: if the URI reference is really wierd or complicated, it may be
+ * Note: if the URI reference is really weird or complicated, it may be
  *       worthwhile to first convert it into a "nice" one by calling
  *       uri_resolve (using 'base') before calling this routine,
  *       since this routine (for reasonable efficiency) assumes URI has

From 8367a14fd3c1ecd5551c91cd3f951ffc61ad7c12 Mon Sep 17 00:00:00 2001
From: Stefan Weil 
Date: Fri, 2 Nov 2012 08:35:54 +0100
Subject: [PATCH 1851/2270] s390x: Spelling fixes (endianess -> endianness,
 occured -> occurred)

Replace also "write into" by "write to".

Signed-off-by: Stefan Weil 
Signed-off-by: Stefan Hajnoczi 
---
 hw/s390x/sclp.h        | 4 ++--
 hw/s390x/sclpconsole.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/s390x/sclp.h b/hw/s390x/sclp.h
index fe89dadd68..231a38aa09 100644
--- a/hw/s390x/sclp.h
+++ b/hw/s390x/sclp.h
@@ -51,7 +51,7 @@
 
 /*
  * Normally packed structures are not the right thing to do, since all code
- * must take care of endianess. We cant use ldl_phys and friends for two
+ * must take care of endianness. We cannot use ldl_phys and friends for two
  * reasons, though:
  * - some of the embedded structures below the SCCB can appear multiple times
  *   at different locations, so there is no fixed offset
@@ -60,7 +60,7 @@
  *   alter the structure while we parse it. We cannot use ldl_p and friends
  *   either without doing pointer arithmetics
  * So we have to double check that all users of sclp data structures use the
- * right endianess wrappers.
+ * right endianness wrappers.
  */
 typedef struct SCCBHeader {
     uint16_t length;
diff --git a/hw/s390x/sclpconsole.c b/hw/s390x/sclpconsole.c
index 0ec5623f57..fece878e88 100644
--- a/hw/s390x/sclpconsole.c
+++ b/hw/s390x/sclpconsole.c
@@ -179,8 +179,8 @@ static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
 }
 
 /* triggered by SCLP's write_event_data
- *  - write console data into character layer
- *  returns < 0 if an error occured
+ *  - write console data to character layer
+ *  returns < 0 if an error occurred
  */
 static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf,
                                   size_t len)

From c47d08ceff8ac76ff857016c80a8864fcf45a7d6 Mon Sep 17 00:00:00 2001
From: Richard Henderson 
Date: Fri, 2 Nov 2012 08:36:35 +1100
Subject: [PATCH 1852/2270] target-alpha: Remove t0, t1 from CPUAlphaState

These fields are no longer (or were never?) used.

Signed-off-by: Richard Henderson 
Signed-off-by: Stefan Hajnoczi 
---
 target-alpha/cpu.h | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 34221fb184..9939d61ca8 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -280,13 +280,6 @@ struct CPUAlphaState {
     struct QEMUTimer *alarm_timer;
     uint64_t alarm_expire;
 
-#if TARGET_LONG_BITS > HOST_LONG_BITS
-    /* temporary fixed-point registers
-     * used to emulate 64 bits target on 32 bits hosts
-     */
-    target_ulong t0, t1;
-#endif
-
     /* Those resources are used only in QEMU core */
     CPU_COMMON
 

From d694516440ca31bbcc7ad73f5e99b45fbeb2a6e6 Mon Sep 17 00:00:00 2001
From: Richard Henderson 
Date: Fri, 2 Nov 2012 08:36:36 +1100
Subject: [PATCH 1853/2270] target-m68k: Remove t1 from CPUM68KState

This field is no longer used.

Cc: Paul Brook 
Signed-off-by: Richard Henderson 
Signed-off-by: Stefan Hajnoczi 
---
 target-m68k/cpu.h | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 780e2c94e7..f4fcdeee7a 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -103,9 +103,6 @@ typedef struct CPUM68KState {
     uint32_t rambar0;
     uint32_t cacr;
 
-    /* ??? remove this.  */
-    uint32_t t1;
-
     int pending_vector;
     int pending_level;
 

From dee17bf9e5d29bd08592c6fc47541aad70444bbc Mon Sep 17 00:00:00 2001
From: Richard Henderson 
Date: Fri, 2 Nov 2012 08:36:37 +1100
Subject: [PATCH 1854/2270] target-sparc: Remove t0, t1 from CPUSPARCState

These fields are no longer used.

Cc: Blue Swirl 
Signed-off-by: Richard Henderson 
Signed-off-by: Stefan Hajnoczi 
---
 target-sparc/cpu.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 042d52a310..375f20a71e 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -392,7 +392,6 @@ struct CPUSPARCState {
     target_ulong cc_dst;
     uint32_t cc_op;
 
-    target_ulong t0, t1; /* temporaries live across basic blocks */
     target_ulong cond; /* conditional branch result (XXX: save it in a
                           temporary register when possible) */
 

From 036f0f8356936dba36b952c16f477b3f04f54e37 Mon Sep 17 00:00:00 2001
From: Peter Crosthwaite 
Date: Mon, 19 Nov 2012 15:13:49 +1000
Subject: [PATCH 1855/2270] arm: a9mpcore: remove un-used ptimer_iomem field

I'm guessing this is a hangover from a previous coreification of the mptimer
sub-module. This field is completely unused - removed.

Signed-off-by: Peter Crosthwaite 
Reviewed-by: Peter Maydell 
Signed-off-by: Stefan Hajnoczi 
---
 hw/a9mpcore.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 824ff0a4de..f802de0824 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -19,7 +19,6 @@ typedef struct a9mp_priv_state {
     uint32_t old_timer_status[8];
     uint32_t num_cpu;
     MemoryRegion scu_iomem;
-    MemoryRegion ptimer_iomem;
     MemoryRegion container;
     DeviceState *mptimer;
     DeviceState *gic;

From 4dbd84e26f53d3283baa463f390f9623e8913e8f Mon Sep 17 00:00:00 2001
From: Markus Armbruster 
Date: Thu, 22 Nov 2012 15:16:36 +0100
Subject: [PATCH 1856/2270] Clean up pci_drive_hot_add()'s use of
 BlockInterfaceType

pci_drive_hot_add() parameter type has the wrong type: int instead of
BlockInterfaceType.  It's actually redundant, so we can just drop it.

Signed-off-by: Markus Armbruster 
Signed-off-by: Stefan Hajnoczi 
---
 hw/device-hotplug.c | 11 ++++-------
 hw/pci-hotplug.c    |  7 +++----
 sysemu.h            |  3 +--
 3 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index eec0fe3148..6d9c080381 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -49,18 +49,16 @@ DriveInfo *add_init_drive(const char *optstr)
 }
 
 #if !defined(TARGET_I386)
-int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
-                      DriveInfo *dinfo, int type)
+int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo)
 {
     /* On non-x86 we don't do PCI hotplug */
-    monitor_printf(mon, "Can't hot-add drive to type %d\n", type);
+    monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type);
     return -1;
 }
 #endif
 
 void drive_hot_add(Monitor *mon, const QDict *qdict)
 {
-    int type;
     DriveInfo *dinfo = NULL;
     const char *opts = qdict_get_str(qdict, "opts");
 
@@ -72,14 +70,13 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
         monitor_printf(mon, "Parameter addr not supported\n");
         goto err;
     }
-    type = dinfo->type;
 
-    switch (type) {
+    switch (dinfo->type) {
     case IF_NONE:
         monitor_printf(mon, "OK\n");
         break;
     default:
-        if (pci_drive_hot_add(mon, qdict, dinfo, type)) {
+        if (pci_drive_hot_add(mon, qdict, dinfo)) {
             goto err;
         }
     }
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 0ca5546fc6..3bcfdcc1a6 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -111,15 +111,14 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
     return 0;
 }
 
-int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
-                      DriveInfo *dinfo, int type)
+int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo)
 {
     int dom, pci_bus;
     unsigned slot;
     PCIDevice *dev;
     const char *pci_addr = qdict_get_str(qdict, "pci_addr");
 
-    switch (type) {
+    switch (dinfo->type) {
     case IF_SCSI:
         if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
             goto err;
@@ -135,7 +134,7 @@ int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
         }
         break;
     default:
-        monitor_printf(mon, "Can't hot-add drive to type %d\n", type);
+        monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type);
         goto err;
     }
 
diff --git a/sysemu.h b/sysemu.h
index f5ac664067..c1b370b781 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -145,8 +145,7 @@ extern unsigned int nb_prom_envs;
 
 /* pci-hotplug */
 void pci_device_hot_add(Monitor *mon, const QDict *qdict);
-int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
-                      DriveInfo *dinfo, int type);
+int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo);
 void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict);
 
 /* generic hotplug */

From 993d46ce7e54f3d035d344ed1b145b13f9ac54b9 Mon Sep 17 00:00:00 2001
From: Stefan Weil 
Date: Fri, 23 Nov 2012 07:26:04 +0100
Subject: [PATCH 1857/2270] Fix spelling in comments and documentation

These spelling bugs were found by codespell:

supressing -> suppressing
transfered -> transferred

Signed-off-by: Stefan Weil 
Signed-off-by: Stefan Hajnoczi 
---
 hw/usb.h                      | 6 +++---
 tests/qemu-iotests/iotests.py | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/usb.h b/hw/usb.h
index 7d6de69ec4..f05eb1797f 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -282,7 +282,7 @@ typedef struct USBDeviceClass {
      * Called from handle_packet().
      *
      * Status gets stored in p->status, and if p->status == USB_RET_SUCCESS
-     * then the number of bytes transfered is stored in p->actual_length
+     * then the number of bytes transferred is stored in p->actual_length
      */
     void (*handle_control)(USBDevice *dev, USBPacket *p, int request, int value,
                            int index, int length, uint8_t *data);
@@ -292,7 +292,7 @@ typedef struct USBDeviceClass {
      * Called from handle_packet().
      *
      * Status gets stored in p->status, and if p->status == USB_RET_SUCCESS
-     * then the number of bytes transfered is stored in p->actual_length
+     * then the number of bytes transferred is stored in p->actual_length
      */
     void (*handle_data)(USBDevice *dev, USBPacket *p);
 
@@ -358,7 +358,7 @@ struct USBPacket {
     bool short_not_ok;
     bool int_req;
     int status; /* USB_RET_* status code */
-    int actual_length; /* Number of bytes actually transfered */
+    int actual_length; /* Number of bytes actually transferred */
     /* Internal use by the USB layer.  */
     USBPacketState state;
     USBCombinedPacket *combined;
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index b2eaf20f0b..0be5c7e13f 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -43,7 +43,7 @@ def qemu_img(*args):
     return subprocess.call(qemu_img_args + list(args), stdin=devnull, stdout=devnull)
 
 def qemu_img_verbose(*args):
-    '''Run qemu-img without supressing its output and return the exit code'''
+    '''Run qemu-img without suppressing its output and return the exit code'''
     return subprocess.call(qemu_img_args + list(args))
 
 def qemu_io(*args):

From 3528a3cba1f59de520fad7b1c843759e8655ea2c Mon Sep 17 00:00:00 2001
From: Michal Privoznik 
Date: Fri, 23 Nov 2012 09:52:39 +0100
Subject: [PATCH 1858/2270] qemu-options: Fix space at EOL

There's no need to add a space at the end of line.
Moreover, it can make problems in some projects that
store the help output into a file (and run couple of
tests based on that) and have space at EOL forbidden.

Signed-off-by: Michal Privoznik 
Reviewed-by: Peter Maydell 
Signed-off-by: Stefan Hajnoczi 
---
 qemu-options.hx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index de43b1b48b..231cc4f55f 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1331,7 +1331,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
     "                connect the host TAP network interface to VLAN 'n'\n"
 #else
     "-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile][,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostforce=on|off]\n"
-    "                connect the host TAP network interface to VLAN 'n' \n"
+    "                connect the host TAP network interface to VLAN 'n'\n"
     "                use network scripts 'file' (default=" DEFAULT_NETWORK_SCRIPT ")\n"
     "                to configure it and 'dfile' (default=" DEFAULT_NETWORK_DOWN_SCRIPT ")\n"
     "                to deconfigure it\n"

From 654598c944aa31cdbea435bd468055af9c918d16 Mon Sep 17 00:00:00 2001
From: Markus Armbruster 
Date: Fri, 23 Nov 2012 19:12:18 +0100
Subject: [PATCH 1859/2270] pc_sysfw: Plug memory leak on
 pc_fw_add_pflash_drv() error path

Harmless, because we the error inevitably leads to another, fatal one
in pc_system_flash_init(): PC system firmware (pflash) not available.
Fix it anyway.

Signed-off-by: Markus Armbruster 
Signed-off-by: Stefan Hajnoczi 
---
 hw/pc_sysfw.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/hw/pc_sysfw.c b/hw/pc_sysfw.c
index 9d7c5f4003..40bced2322 100644
--- a/hw/pc_sysfw.c
+++ b/hw/pc_sysfw.c
@@ -98,7 +98,9 @@ static void pc_fw_add_pflash_drv(void)
       return;
     }
 
-    drive_init(opts, machine->use_scsi);
+    if (!drive_init(opts, machine->use_scsi)) {
+        qemu_opts_del(opts);
+    }
 }
 
 static void pc_system_flash_init(MemoryRegion *rom_memory,

From b34d12d153e6e5c5e5e00eac510b054a94409deb Mon Sep 17 00:00:00 2001
From: Igor Mammedov 
Date: Mon, 22 Oct 2012 17:03:00 +0200
Subject: [PATCH 1860/2270] target-i386: Postpone cpuid_level update to realize
 time
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Delay capping cpuid_level to 7 to realize time so property setters
for cpuid_7_0_ebx_features and "level" could be used in any order/time
between x86_cpu_initfn() and x86_cpu_realize().

Signed-off-by: Igor Mammedov 
Signed-off-by: Eduardo Habkost 
Signed-off-by: Andreas Färber 
---
 target-i386/cpu.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index a631ae9c87..7be3ad82cb 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1381,9 +1381,6 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features)
         if (kvm_check_features_against_host(x86_cpu_def) && enforce_cpuid)
             goto error;
     }
-    if (x86_cpu_def->cpuid_7_0_ebx_features && x86_cpu_def->level < 7) {
-        x86_cpu_def->level = 7;
-    }
     return 0;
 
 error:
@@ -2074,6 +2071,11 @@ static void x86_cpu_apic_init(X86CPU *cpu, Error **errp)
 void x86_cpu_realize(Object *obj, Error **errp)
 {
     X86CPU *cpu = X86_CPU(obj);
+    CPUX86State *env = &cpu->env;
+
+    if (env->cpuid_7_0_ebx_features && env->cpuid_level < 7) {
+        env->cpuid_level = 7;
+    }
 
 #ifndef CONFIG_USER_ONLY
     qemu_register_reset(x86_cpu_machine_reset_cb, cpu);

From 0be4835b4932f38167b611c2b311ebaaec98a8eb Mon Sep 17 00:00:00 2001
From: Richard Henderson 
Date: Fri, 2 Nov 2012 09:20:46 +1100
Subject: [PATCH 1861/2270] exec: Advise huge pages for the TCG code gen buffer

After allocating 32MB or more contiguous memory, huge pages
would seem to be ideal.

Signed-off-by: Richard Henderson 
Signed-off-by: Blue Swirl 
---
 exec.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/exec.c b/exec.c
index 8435de0bd2..0594b07057 100644
--- a/exec.c
+++ b/exec.c
@@ -607,6 +607,8 @@ static inline void code_gen_alloc(size_t tb_size)
         exit(1);
     }
 
+    qemu_madvise(code_gen_buffer, code_gen_buffer_size, QEMU_MADV_HUGEPAGE);
+
     /* Steal room for the prologue at the end of the buffer.  This ensures
        (via the MAX_CODE_GEN_BUFFER_SIZE limits above) that direct branches
        from TB's to the prologue are going to be in range.  It also means

From 2aa1cb514cdce31ca68902d464cd03d31a76e998 Mon Sep 17 00:00:00 2001
From: Brad Smith 
Date: Mon, 19 Nov 2012 04:22:12 -0500
Subject: [PATCH 1862/2270] curses: Remove OpenBSD workaround

I removed the same sort of workaround for OpenBSD within the
configure script with commit 4dcc3f5876fa638d5c35bd47be3b717ea74cc2e7
but didn't bother to grep further to come across this same chunk
of code in the curses code itself. So the following diff removes
the same workaround chunk within the curses code.

Signed-off-by: Brad Smith 
Signed-off-by: Blue Swirl 
---
 ui/curses.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/ui/curses.c b/ui/curses.c
index b40b22307d..5dc0b2c95f 100644
--- a/ui/curses.c
+++ b/ui/curses.c
@@ -28,10 +28,6 @@
 #include 
 #endif
 
-#ifdef __OpenBSD__
-#define resize_term resizeterm
-#endif
-
 #include "qemu-common.h"
 #include "console.h"
 #include "sysemu.h"

From c3a43607d927e6a0ecce0b61e8297c1cfe604c14 Mon Sep 17 00:00:00 2001
From: Evgeny Voevodin 
Date: Wed, 21 Nov 2012 11:43:03 +0400
Subject: [PATCH 1863/2270] tcg/tcg.h: Duplicate global TCG gen_opc_ arrays
 into TCGContext.

Signed-off-by: Evgeny Voevodin 
Signed-off-by: Blue Swirl 
---
 tcg/tcg.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tcg/tcg.h b/tcg/tcg.h
index 9481e35ab4..f6e255f775 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -455,6 +455,9 @@ struct TCGContext {
 
     uint16_t *gen_opc_ptr;
     TCGArg *gen_opparam_ptr;
+    target_ulong gen_opc_pc[OPC_BUF_SIZE];
+    uint16_t gen_opc_icount[OPC_BUF_SIZE];
+    uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
 
 #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
     /* labels info for qemu_ld/st IRs

From 25983cad31969e3003eef77bc03a6700f46899d2 Mon Sep 17 00:00:00 2001
From: Evgeny Voevodin 
Date: Wed, 21 Nov 2012 11:43:04 +0400
Subject: [PATCH 1864/2270] TCG: Use gen_opc_pc from context instead of global
 variable.

Signed-off-by: Evgeny Voevodin 
Signed-off-by: Blue Swirl 
---
 target-alpha/translate.c      | 4 ++--
 target-arm/translate.c        | 4 ++--
 target-cris/translate.c       | 6 +++---
 target-i386/translate.c       | 9 +++++----
 target-lm32/translate.c       | 4 ++--
 target-m68k/translate.c       | 4 ++--
 target-microblaze/translate.c | 4 ++--
 target-mips/translate.c       | 4 ++--
 target-openrisc/translate.c   | 4 ++--
 target-ppc/translate.c        | 4 ++--
 target-s390x/translate.c      | 4 ++--
 target-sh4/translate.c        | 4 ++--
 target-sparc/translate.c      | 4 ++--
 target-unicore32/translate.c  | 4 ++--
 target-xtensa/translate.c     | 4 ++--
 15 files changed, 34 insertions(+), 33 deletions(-)

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 4045f788ea..bcde367da6 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3412,7 +3412,7 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
                 while (lj < j)
                     gen_opc_instr_start[lj++] = 0;
             }
-            gen_opc_pc[lj] = ctx.pc;
+            tcg_ctx.gen_opc_pc[lj] = ctx.pc;
             gen_opc_instr_start[lj] = 1;
             gen_opc_icount[lj] = num_insns;
         }
@@ -3551,5 +3551,5 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
 
 void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, int pc_pos)
 {
-    env->pc = gen_opc_pc[pc_pos];
+    env->pc = tcg_ctx.gen_opc_pc[pc_pos];
 }
diff --git a/target-arm/translate.c b/target-arm/translate.c
index c42110ab0d..8ea8bbae3d 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9840,7 +9840,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
                 while (lj < j)
                     gen_opc_instr_start[lj++] = 0;
             }
-            gen_opc_pc[lj] = dc->pc;
+            tcg_ctx.gen_opc_pc[lj] = dc->pc;
             gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
             gen_opc_instr_start[lj] = 1;
             gen_opc_icount[lj] = num_insns;
@@ -10043,6 +10043,6 @@ void cpu_dump_state(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf,
 
 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
 {
-    env->regs[15] = gen_opc_pc[pc_pos];
+    env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
     env->condexec_bits = gen_opc_condexec_bits[pc_pos];
 }
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 0b0e86dbd1..745cd7acb4 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3305,9 +3305,9 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
                 }
             }
             if (dc->delayed_branch == 1) {
-                gen_opc_pc[lj] = dc->ppc | 1;
+                tcg_ctx.gen_opc_pc[lj] = dc->ppc | 1;
             } else {
-                gen_opc_pc[lj] = dc->pc;
+                tcg_ctx.gen_opc_pc[lj] = dc->pc;
             }
             gen_opc_instr_start[lj] = 1;
             gen_opc_icount[lj] = num_insns;
@@ -3621,5 +3621,5 @@ CRISCPU *cpu_cris_init(const char *cpu_model)
 
 void restore_state_to_opc(CPUCRISState *env, TranslationBlock *tb, int pc_pos)
 {
-    env->pc = gen_opc_pc[pc_pos];
+    env->pc = tcg_ctx.gen_opc_pc[pc_pos];
 }
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 8e676ba1a8..aea843cafe 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7990,7 +7990,7 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
                 while (lj < j)
                     gen_opc_instr_start[lj++] = 0;
             }
-            gen_opc_pc[lj] = pc_ptr;
+            tcg_ctx.gen_opc_pc[lj] = pc_ptr;
             gen_opc_cc_op[lj] = dc->cc_op;
             gen_opc_instr_start[lj] = 1;
             gen_opc_icount[lj] = num_insns;
@@ -8081,15 +8081,16 @@ void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
         qemu_log("RESTORE:\n");
         for(i = 0;i <= pc_pos; i++) {
             if (gen_opc_instr_start[i]) {
-                qemu_log("0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]);
+                qemu_log("0x%04x: " TARGET_FMT_lx "\n", i,
+                        tcg_ctx.gen_opc_pc[i]);
             }
         }
         qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
-                pc_pos, gen_opc_pc[pc_pos] - tb->cs_base,
+                pc_pos, tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base,
                 (uint32_t)tb->cs_base);
     }
 #endif
-    env->eip = gen_opc_pc[pc_pos] - tb->cs_base;
+    env->eip = tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base;
     cc_op = gen_opc_cc_op[pc_pos];
     if (cc_op != CC_OP_DYNAMIC)
         env->cc_op = cc_op;
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index af986499f2..fcafb06fb5 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -1054,7 +1054,7 @@ static void gen_intermediate_code_internal(CPULM32State *env,
                     gen_opc_instr_start[lj++] = 0;
                 }
             }
-            gen_opc_pc[lj] = dc->pc;
+            tcg_ctx.gen_opc_pc[lj] = dc->pc;
             gen_opc_instr_start[lj] = 1;
             gen_opc_icount[lj] = num_insns;
         }
@@ -1172,7 +1172,7 @@ void cpu_dump_state(CPULM32State *env, FILE *f, fprintf_function cpu_fprintf,
 
 void restore_state_to_opc(CPULM32State *env, TranslationBlock *tb, int pc_pos)
 {
-    env->pc = gen_opc_pc[pc_pos];
+    env->pc = tcg_ctx.gen_opc_pc[pc_pos];
 }
 
 void lm32_translate_init(void)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index b13be4899e..74772dd6a5 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3021,7 +3021,7 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
                 while (lj < j)
                     gen_opc_instr_start[lj++] = 0;
             }
-            gen_opc_pc[lj] = dc->pc;
+            tcg_ctx.gen_opc_pc[lj] = dc->pc;
             gen_opc_instr_start[lj] = 1;
             gen_opc_icount[lj] = num_insns;
         }
@@ -3121,5 +3121,5 @@ void cpu_dump_state(CPUM68KState *env, FILE *f, fprintf_function cpu_fprintf,
 
 void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb, int pc_pos)
 {
-    env->pc = gen_opc_pc[pc_pos];
+    env->pc = tcg_ctx.gen_opc_pc[pc_pos];
 }
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index cce4494954..6803f735b1 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1790,7 +1790,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
                 while (lj < j)
                     gen_opc_instr_start[lj++] = 0;
             }
-            gen_opc_pc[lj] = dc->pc;
+            tcg_ctx.gen_opc_pc[lj] = dc->pc;
             gen_opc_instr_start[lj] = 1;
                         gen_opc_icount[lj] = num_insns;
         }
@@ -2014,5 +2014,5 @@ MicroBlazeCPU *cpu_mb_init(const char *cpu_model)
 
 void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, int pc_pos)
 {
-    env->sregs[SR_PC] = gen_opc_pc[pc_pos];
+    env->sregs[SR_PC] = tcg_ctx.gen_opc_pc[pc_pos];
 }
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 71c55bcadb..e1ea9687cc 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15581,7 +15581,7 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
                 while (lj < j)
                     gen_opc_instr_start[lj++] = 0;
             }
-            gen_opc_pc[lj] = ctx.pc;
+            tcg_ctx.gen_opc_pc[lj] = ctx.pc;
             gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
             gen_opc_btarget[lj] = ctx.btarget;
             gen_opc_instr_start[lj] = 1;
@@ -16002,7 +16002,7 @@ void cpu_state_reset(CPUMIPSState *env)
 
 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
 {
-    env->active_tc.PC = gen_opc_pc[pc_pos];
+    env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
     env->hflags &= ~MIPS_HFLAG_BMASK;
     env->hflags |= gen_opc_hflags[pc_pos];
     switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index f14da7bd1a..b7ad6a4ef6 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1710,7 +1710,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
                     gen_opc_instr_start[k++] = 0;
                 }
             }
-            gen_opc_pc[k] = dc->pc;
+            tcg_ctx.gen_opc_pc[k] = dc->pc;
             gen_opc_instr_start[k] = 1;
             gen_opc_icount[k] = num_insns;
         }
@@ -1832,5 +1832,5 @@ void cpu_dump_state(CPUOpenRISCState *env, FILE *f,
 void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
                           int pc_pos)
 {
-    env->pc = gen_opc_pc[pc_pos];
+    env->pc = tcg_ctx.gen_opc_pc[pc_pos];
 }
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 987b04eda5..276edc82ed 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9682,7 +9682,7 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
                 while (lj < j)
                     gen_opc_instr_start[lj++] = 0;
             }
-            gen_opc_pc[lj] = ctx.nip;
+            tcg_ctx.gen_opc_pc[lj] = ctx.nip;
             gen_opc_instr_start[lj] = 1;
             gen_opc_icount[lj] = num_insns;
         }
@@ -9810,5 +9810,5 @@ void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb)
 
 void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, int pc_pos)
 {
-    env->nip = gen_opc_pc[pc_pos];
+    env->nip = tcg_ctx.gen_opc_pc[pc_pos];
 }
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 993f20752c..ff2868f910 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -5163,7 +5163,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
                     gen_opc_instr_start[lj++] = 0;
                 }
             }
-            gen_opc_pc[lj] = dc.pc;
+            tcg_ctx.gen_opc_pc[lj] = dc.pc;
             gen_opc_cc_op[lj] = dc.cc_op;
             gen_opc_instr_start[lj] = 1;
             gen_opc_icount[lj] = num_insns;
@@ -5240,7 +5240,7 @@ void gen_intermediate_code_pc (CPUS390XState *env, struct TranslationBlock *tb)
 void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, int pc_pos)
 {
     int cc_op;
-    env->psw.addr = gen_opc_pc[pc_pos];
+    env->psw.addr = tcg_ctx.gen_opc_pc[pc_pos];
     cc_op = gen_opc_cc_op[pc_pos];
     if ((cc_op != CC_OP_DYNAMIC) && (cc_op != CC_OP_STATIC)) {
         env->cc_op = cc_op;
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 5497dede05..4def163dc4 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -2005,7 +2005,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
                 while (ii < i)
                     gen_opc_instr_start[ii++] = 0;
             }
-            gen_opc_pc[ii] = ctx.pc;
+            tcg_ctx.gen_opc_pc[ii] = ctx.pc;
             gen_opc_hflags[ii] = ctx.flags;
             gen_opc_instr_start[ii] = 1;
             gen_opc_icount[ii] = num_insns;
@@ -2088,6 +2088,6 @@ void gen_intermediate_code_pc(CPUSH4State * env, struct TranslationBlock *tb)
 
 void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb, int pc_pos)
 {
-    env->pc = gen_opc_pc[pc_pos];
+    env->pc = tcg_ctx.gen_opc_pc[pc_pos];
     env->flags = gen_opc_hflags[pc_pos];
 }
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 2ae803695b..4f3a84473c 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5284,7 +5284,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
                 lj++;
                 while (lj < j)
                     gen_opc_instr_start[lj++] = 0;
-                gen_opc_pc[lj] = dc->pc;
+                tcg_ctx.gen_opc_pc[lj] = dc->pc;
                 gen_opc_npc[lj] = dc->npc;
                 gen_opc_instr_start[lj] = 1;
                 gen_opc_icount[lj] = num_insns;
@@ -5478,7 +5478,7 @@ void gen_intermediate_code_init(CPUSPARCState *env)
 void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb, int pc_pos)
 {
     target_ulong npc;
-    env->pc = gen_opc_pc[pc_pos];
+    env->pc = tcg_ctx.gen_opc_pc[pc_pos];
     npc = gen_opc_npc[pc_pos];
     if (npc == 1) {
         /* dynamic NPC: already stored */
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index 052bb45d70..32a426522c 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -2006,7 +2006,7 @@ static inline void gen_intermediate_code_internal(CPUUniCore32State *env,
                     gen_opc_instr_start[lj++] = 0;
                 }
             }
-            gen_opc_pc[lj] = dc->pc;
+            tcg_ctx.gen_opc_pc[lj] = dc->pc;
             gen_opc_instr_start[lj] = 1;
             gen_opc_icount[lj] = num_insns;
         }
@@ -2203,5 +2203,5 @@ void cpu_dump_state(CPUUniCore32State *env, FILE *f,
 
 void restore_state_to_opc(CPUUniCore32State *env, TranslationBlock *tb, int pc_pos)
 {
-    env->regs[31] = gen_opc_pc[pc_pos];
+    env->regs[31] = tcg_ctx.gen_opc_pc[pc_pos];
 }
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index e5a3f49a75..21126fc396 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -2900,7 +2900,7 @@ static void gen_intermediate_code_internal(
                     gen_opc_instr_start[lj++] = 0;
                 }
             }
-            gen_opc_pc[lj] = dc.pc;
+            tcg_ctx.gen_opc_pc[lj] = dc.pc;
             gen_opc_instr_start[lj] = 1;
             gen_opc_icount[lj] = insn_count;
         }
@@ -3028,5 +3028,5 @@ void cpu_dump_state(CPUXtensaState *env, FILE *f, fprintf_function cpu_fprintf,
 
 void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, int pc_pos)
 {
-    env->pc = gen_opc_pc[pc_pos];
+    env->pc = tcg_ctx.gen_opc_pc[pc_pos];
 }

From c9c99c22d5f8e9cfa83260fbe236a57e7383d673 Mon Sep 17 00:00:00 2001
From: Evgeny Voevodin 
Date: Wed, 21 Nov 2012 11:43:05 +0400
Subject: [PATCH 1865/2270] TCG: Use gen_opc_icount from context instead of
 global variable.

Signed-off-by: Evgeny Voevodin 
Signed-off-by: Blue Swirl 
---
 target-alpha/translate.c      | 2 +-
 target-arm/translate.c        | 2 +-
 target-cris/translate.c       | 2 +-
 target-i386/translate.c       | 2 +-
 target-lm32/translate.c       | 2 +-
 target-m68k/translate.c       | 2 +-
 target-microblaze/translate.c | 2 +-
 target-mips/translate.c       | 2 +-
 target-openrisc/translate.c   | 2 +-
 target-ppc/translate.c        | 2 +-
 target-s390x/translate.c      | 2 +-
 target-sh4/translate.c        | 2 +-
 target-sparc/translate.c      | 2 +-
 target-unicore32/translate.c  | 2 +-
 target-xtensa/translate.c     | 2 +-
 translate-all.c               | 2 +-
 16 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index bcde367da6..8b73fbb0eb 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3414,7 +3414,7 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
             }
             tcg_ctx.gen_opc_pc[lj] = ctx.pc;
             gen_opc_instr_start[lj] = 1;
-            gen_opc_icount[lj] = num_insns;
+            tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
             gen_io_start();
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 8ea8bbae3d..4695d8b49b 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9843,7 +9843,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
             tcg_ctx.gen_opc_pc[lj] = dc->pc;
             gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
             gen_opc_instr_start[lj] = 1;
-            gen_opc_icount[lj] = num_insns;
+            tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
 
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 745cd7acb4..6ec8c3c284 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3310,7 +3310,7 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
                 tcg_ctx.gen_opc_pc[lj] = dc->pc;
             }
             gen_opc_instr_start[lj] = 1;
-            gen_opc_icount[lj] = num_insns;
+            tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
 
         /* Pretty disas.  */
diff --git a/target-i386/translate.c b/target-i386/translate.c
index aea843cafe..80fb695fc8 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7993,7 +7993,7 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
             tcg_ctx.gen_opc_pc[lj] = pc_ptr;
             gen_opc_cc_op[lj] = dc->cc_op;
             gen_opc_instr_start[lj] = 1;
-            gen_opc_icount[lj] = num_insns;
+            tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
             gen_io_start();
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index fcafb06fb5..4e029e06de 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -1056,7 +1056,7 @@ static void gen_intermediate_code_internal(CPULM32State *env,
             }
             tcg_ctx.gen_opc_pc[lj] = dc->pc;
             gen_opc_instr_start[lj] = 1;
-            gen_opc_icount[lj] = num_insns;
+            tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
 
         /* Pretty disas.  */
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 74772dd6a5..0762085568 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3023,7 +3023,7 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
             }
             tcg_ctx.gen_opc_pc[lj] = dc->pc;
             gen_opc_instr_start[lj] = 1;
-            gen_opc_icount[lj] = num_insns;
+            tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
             gen_io_start();
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 6803f735b1..d975756538 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1792,7 +1792,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
             }
             tcg_ctx.gen_opc_pc[lj] = dc->pc;
             gen_opc_instr_start[lj] = 1;
-                        gen_opc_icount[lj] = num_insns;
+                        tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
 
         /* Pretty disas.  */
diff --git a/target-mips/translate.c b/target-mips/translate.c
index e1ea9687cc..abecfb3f3b 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15585,7 +15585,7 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
             gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
             gen_opc_btarget[lj] = ctx.btarget;
             gen_opc_instr_start[lj] = 1;
-            gen_opc_icount[lj] = num_insns;
+            tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
             gen_io_start();
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index b7ad6a4ef6..5b08314723 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1712,7 +1712,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
             }
             tcg_ctx.gen_opc_pc[k] = dc->pc;
             gen_opc_instr_start[k] = 1;
-            gen_opc_icount[k] = num_insns;
+            tcg_ctx.gen_opc_icount[k] = num_insns;
         }
 
         if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 276edc82ed..7fdde5fae7 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9684,7 +9684,7 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
             }
             tcg_ctx.gen_opc_pc[lj] = ctx.nip;
             gen_opc_instr_start[lj] = 1;
-            gen_opc_icount[lj] = num_insns;
+            tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
         LOG_DISAS("----------------\n");
         LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index ff2868f910..b2774ee76b 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -5166,7 +5166,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
             tcg_ctx.gen_opc_pc[lj] = dc.pc;
             gen_opc_cc_op[lj] = dc.cc_op;
             gen_opc_instr_start[lj] = 1;
-            gen_opc_icount[lj] = num_insns;
+            tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start();
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 4def163dc4..ca76be53d4 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -2008,7 +2008,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
             tcg_ctx.gen_opc_pc[ii] = ctx.pc;
             gen_opc_hflags[ii] = ctx.flags;
             gen_opc_instr_start[ii] = 1;
-            gen_opc_icount[ii] = num_insns;
+            tcg_ctx.gen_opc_icount[ii] = num_insns;
         }
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
             gen_io_start();
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 4f3a84473c..cbb8997de9 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5287,7 +5287,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
                 tcg_ctx.gen_opc_pc[lj] = dc->pc;
                 gen_opc_npc[lj] = dc->npc;
                 gen_opc_instr_start[lj] = 1;
-                gen_opc_icount[lj] = num_insns;
+                tcg_ctx.gen_opc_icount[lj] = num_insns;
             }
         }
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index 32a426522c..05626158fd 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -2008,7 +2008,7 @@ static inline void gen_intermediate_code_internal(CPUUniCore32State *env,
             }
             tcg_ctx.gen_opc_pc[lj] = dc->pc;
             gen_opc_instr_start[lj] = 1;
-            gen_opc_icount[lj] = num_insns;
+            tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
 
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 21126fc396..e93c2e6fa8 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -2902,7 +2902,7 @@ static void gen_intermediate_code_internal(
             }
             tcg_ctx.gen_opc_pc[lj] = dc.pc;
             gen_opc_instr_start[lj] = 1;
-            gen_opc_icount[lj] = insn_count;
+            tcg_ctx.gen_opc_icount[lj] = insn_count;
         }
 
         if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
diff --git a/translate-all.c b/translate-all.c
index d9c2e57861..177e95ab0c 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -148,7 +148,7 @@ int cpu_restore_state(TranslationBlock *tb,
     /* now find start of instruction before */
     while (gen_opc_instr_start[j] == 0)
         j--;
-    env->icount_decr.u16.low -= gen_opc_icount[j];
+    env->icount_decr.u16.low -= s->gen_opc_icount[j];
 
     restore_state_to_opc(env, tb, j);
 

From ab1103def476d985c08362df97ff9cb9c112adfc Mon Sep 17 00:00:00 2001
From: Evgeny Voevodin 
Date: Wed, 21 Nov 2012 11:43:06 +0400
Subject: [PATCH 1866/2270] TCG: Use gen_opc_instr_start from context instead
 of global variable.

Signed-off-by: Evgeny Voevodin 
Signed-off-by: Blue Swirl 
---
 target-alpha/translate.c      | 6 +++---
 target-arm/translate.c        | 6 +++---
 target-cris/translate.c       | 6 +++---
 target-i386/translate.c       | 8 ++++----
 target-lm32/translate.c       | 6 +++---
 target-m68k/translate.c       | 6 +++---
 target-microblaze/translate.c | 6 +++---
 target-mips/translate.c       | 6 +++---
 target-openrisc/translate.c   | 6 +++---
 target-ppc/translate.c        | 6 +++---
 target-s390x/translate.c      | 6 +++---
 target-sh4/translate.c        | 6 +++---
 target-sparc/translate.c      | 6 +++---
 target-unicore32/translate.c  | 6 +++---
 target-xtensa/translate.c     | 4 ++--
 translate-all.c               | 3 ++-
 16 files changed, 47 insertions(+), 46 deletions(-)

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 8b73fbb0eb..71fe1a1ab0 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3410,10 +3410,10 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
             if (lj < j) {
                 lj++;
                 while (lj < j)
-                    gen_opc_instr_start[lj++] = 0;
+                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
             }
             tcg_ctx.gen_opc_pc[lj] = ctx.pc;
-            gen_opc_instr_start[lj] = 1;
+            tcg_ctx.gen_opc_instr_start[lj] = 1;
             tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
@@ -3468,7 +3468,7 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j)
-            gen_opc_instr_start[lj++] = 0;
+            tcg_ctx.gen_opc_instr_start[lj++] = 0;
     } else {
         tb->size = ctx.pc - pc_start;
         tb->icount = num_insns;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 4695d8b49b..3cf3604517 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9838,11 +9838,11 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
             if (lj < j) {
                 lj++;
                 while (lj < j)
-                    gen_opc_instr_start[lj++] = 0;
+                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
             }
             tcg_ctx.gen_opc_pc[lj] = dc->pc;
             gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
-            gen_opc_instr_start[lj] = 1;
+            tcg_ctx.gen_opc_instr_start[lj] = 1;
             tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
 
@@ -9977,7 +9977,7 @@ done_generating:
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j)
-            gen_opc_instr_start[lj++] = 0;
+            tcg_ctx.gen_opc_instr_start[lj++] = 0;
     } else {
         tb->size = dc->pc - pc_start;
         tb->icount = num_insns;
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 6ec8c3c284..60bdc241ef 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3301,7 +3301,7 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
             if (lj < j) {
                 lj++;
                 while (lj < j) {
-                    gen_opc_instr_start[lj++] = 0;
+                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
                 }
             }
             if (dc->delayed_branch == 1) {
@@ -3309,7 +3309,7 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
             } else {
                 tcg_ctx.gen_opc_pc[lj] = dc->pc;
             }
-            gen_opc_instr_start[lj] = 1;
+            tcg_ctx.gen_opc_instr_start[lj] = 1;
             tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
 
@@ -3439,7 +3439,7 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j) {
-            gen_opc_instr_start[lj++] = 0;
+            tcg_ctx.gen_opc_instr_start[lj++] = 0;
         }
     } else {
         tb->size = dc->pc - pc_start;
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 80fb695fc8..f394ea69a5 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7988,11 +7988,11 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
             if (lj < j) {
                 lj++;
                 while (lj < j)
-                    gen_opc_instr_start[lj++] = 0;
+                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
             }
             tcg_ctx.gen_opc_pc[lj] = pc_ptr;
             gen_opc_cc_op[lj] = dc->cc_op;
-            gen_opc_instr_start[lj] = 1;
+            tcg_ctx.gen_opc_instr_start[lj] = 1;
             tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
@@ -8037,7 +8037,7 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j)
-            gen_opc_instr_start[lj++] = 0;
+            tcg_ctx.gen_opc_instr_start[lj++] = 0;
     }
 
 #ifdef DEBUG_DISAS
@@ -8080,7 +8080,7 @@ void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
         int i;
         qemu_log("RESTORE:\n");
         for(i = 0;i <= pc_pos; i++) {
-            if (gen_opc_instr_start[i]) {
+            if (tcg_ctx.gen_opc_instr_start[i]) {
                 qemu_log("0x%04x: " TARGET_FMT_lx "\n", i,
                         tcg_ctx.gen_opc_pc[i]);
             }
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index 4e029e06de..e131ad1b5f 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -1051,11 +1051,11 @@ static void gen_intermediate_code_internal(CPULM32State *env,
             if (lj < j) {
                 lj++;
                 while (lj < j) {
-                    gen_opc_instr_start[lj++] = 0;
+                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
                 }
             }
             tcg_ctx.gen_opc_pc[lj] = dc->pc;
-            gen_opc_instr_start[lj] = 1;
+            tcg_ctx.gen_opc_instr_start[lj] = 1;
             tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
 
@@ -1110,7 +1110,7 @@ static void gen_intermediate_code_internal(CPULM32State *env,
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j) {
-            gen_opc_instr_start[lj++] = 0;
+            tcg_ctx.gen_opc_instr_start[lj++] = 0;
         }
     } else {
         tb->size = dc->pc - pc_start;
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 0762085568..11defc6e04 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3019,10 +3019,10 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
             if (lj < j) {
                 lj++;
                 while (lj < j)
-                    gen_opc_instr_start[lj++] = 0;
+                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
             }
             tcg_ctx.gen_opc_pc[lj] = dc->pc;
-            gen_opc_instr_start[lj] = 1;
+            tcg_ctx.gen_opc_instr_start[lj] = 1;
             tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
@@ -3078,7 +3078,7 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j)
-            gen_opc_instr_start[lj++] = 0;
+            tcg_ctx.gen_opc_instr_start[lj++] = 0;
     } else {
         tb->size = dc->pc - pc_start;
         tb->icount = num_insns;
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index d975756538..6ceff02a12 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1788,10 +1788,10 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
             if (lj < j) {
                 lj++;
                 while (lj < j)
-                    gen_opc_instr_start[lj++] = 0;
+                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
             }
             tcg_ctx.gen_opc_pc[lj] = dc->pc;
-            gen_opc_instr_start[lj] = 1;
+            tcg_ctx.gen_opc_instr_start[lj] = 1;
                         tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
 
@@ -1902,7 +1902,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j)
-            gen_opc_instr_start[lj++] = 0;
+            tcg_ctx.gen_opc_instr_start[lj++] = 0;
     } else {
         tb->size = dc->pc - pc_start;
                 tb->icount = num_insns;
diff --git a/target-mips/translate.c b/target-mips/translate.c
index abecfb3f3b..65e6725cc9 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15579,12 +15579,12 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
             if (lj < j) {
                 lj++;
                 while (lj < j)
-                    gen_opc_instr_start[lj++] = 0;
+                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
             }
             tcg_ctx.gen_opc_pc[lj] = ctx.pc;
             gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
             gen_opc_btarget[lj] = ctx.btarget;
-            gen_opc_instr_start[lj] = 1;
+            tcg_ctx.gen_opc_instr_start[lj] = 1;
             tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
@@ -15662,7 +15662,7 @@ done_generating:
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j)
-            gen_opc_instr_start[lj++] = 0;
+            tcg_ctx.gen_opc_instr_start[lj++] = 0;
     } else {
         tb->size = ctx.pc - pc_start;
         tb->icount = num_insns;
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 5b08314723..9ac999a9c8 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1707,11 +1707,11 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
             if (k < j) {
                 k++;
                 while (k < j) {
-                    gen_opc_instr_start[k++] = 0;
+                    tcg_ctx.gen_opc_instr_start[k++] = 0;
                 }
             }
             tcg_ctx.gen_opc_pc[k] = dc->pc;
-            gen_opc_instr_start[k] = 1;
+            tcg_ctx.gen_opc_instr_start[k] = 1;
             tcg_ctx.gen_opc_icount[k] = num_insns;
         }
 
@@ -1787,7 +1787,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         k++;
         while (k <= j) {
-            gen_opc_instr_start[k++] = 0;
+            tcg_ctx.gen_opc_instr_start[k++] = 0;
         }
     } else {
         tb->size = dc->pc - pc_start;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 7fdde5fae7..653c2fdb1f 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9680,10 +9680,10 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
             if (lj < j) {
                 lj++;
                 while (lj < j)
-                    gen_opc_instr_start[lj++] = 0;
+                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
             }
             tcg_ctx.gen_opc_pc[lj] = ctx.nip;
-            gen_opc_instr_start[lj] = 1;
+            tcg_ctx.gen_opc_instr_start[lj] = 1;
             tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
         LOG_DISAS("----------------\n");
@@ -9781,7 +9781,7 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j)
-            gen_opc_instr_start[lj++] = 0;
+            tcg_ctx.gen_opc_instr_start[lj++] = 0;
     } else {
         tb->size = ctx.nip - pc_start;
         tb->icount = num_insns;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b2774ee76b..787e3c6963 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -5160,12 +5160,12 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
             if (lj < j) {
                 lj++;
                 while (lj < j) {
-                    gen_opc_instr_start[lj++] = 0;
+                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
                 }
             }
             tcg_ctx.gen_opc_pc[lj] = dc.pc;
             gen_opc_cc_op[lj] = dc.cc_op;
-            gen_opc_instr_start[lj] = 1;
+            tcg_ctx.gen_opc_instr_start[lj] = 1;
             tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
@@ -5212,7 +5212,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j) {
-            gen_opc_instr_start[lj++] = 0;
+            tcg_ctx.gen_opc_instr_start[lj++] = 0;
         }
     } else {
         tb->size = dc.pc - pc_start;
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index ca76be53d4..86493e1b03 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -2003,11 +2003,11 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
             if (ii < i) {
                 ii++;
                 while (ii < i)
-                    gen_opc_instr_start[ii++] = 0;
+                    tcg_ctx.gen_opc_instr_start[ii++] = 0;
             }
             tcg_ctx.gen_opc_pc[ii] = ctx.pc;
             gen_opc_hflags[ii] = ctx.flags;
-            gen_opc_instr_start[ii] = 1;
+            tcg_ctx.gen_opc_instr_start[ii] = 1;
             tcg_ctx.gen_opc_icount[ii] = num_insns;
         }
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
@@ -2061,7 +2061,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
         i = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         ii++;
         while (ii <= i)
-            gen_opc_instr_start[ii++] = 0;
+            tcg_ctx.gen_opc_instr_start[ii++] = 0;
     } else {
         tb->size = ctx.pc - pc_start;
         tb->icount = num_insns;
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index cbb8997de9..5859f2e801 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5283,10 +5283,10 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
             if (lj < j) {
                 lj++;
                 while (lj < j)
-                    gen_opc_instr_start[lj++] = 0;
+                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
                 tcg_ctx.gen_opc_pc[lj] = dc->pc;
                 gen_opc_npc[lj] = dc->npc;
-                gen_opc_instr_start[lj] = 1;
+                tcg_ctx.gen_opc_instr_start[lj] = 1;
                 tcg_ctx.gen_opc_icount[lj] = num_insns;
             }
         }
@@ -5339,7 +5339,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j)
-            gen_opc_instr_start[lj++] = 0;
+            tcg_ctx.gen_opc_instr_start[lj++] = 0;
 #if 0
         log_page_dump();
 #endif
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index 05626158fd..3951758fc8 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -2003,11 +2003,11 @@ static inline void gen_intermediate_code_internal(CPUUniCore32State *env,
             if (lj < j) {
                 lj++;
                 while (lj < j) {
-                    gen_opc_instr_start[lj++] = 0;
+                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
                 }
             }
             tcg_ctx.gen_opc_pc[lj] = dc->pc;
-            gen_opc_instr_start[lj] = 1;
+            tcg_ctx.gen_opc_instr_start[lj] = 1;
             tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
 
@@ -2117,7 +2117,7 @@ done_generating:
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
         lj++;
         while (lj <= j) {
-            gen_opc_instr_start[lj++] = 0;
+            tcg_ctx.gen_opc_instr_start[lj++] = 0;
         }
     } else {
         tb->size = dc->pc - pc_start;
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index e93c2e6fa8..828b9cabb5 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -2897,11 +2897,11 @@ static void gen_intermediate_code_internal(
             if (lj < j) {
                 lj++;
                 while (lj < j) {
-                    gen_opc_instr_start[lj++] = 0;
+                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
                 }
             }
             tcg_ctx.gen_opc_pc[lj] = dc.pc;
-            gen_opc_instr_start[lj] = 1;
+            tcg_ctx.gen_opc_instr_start[lj] = 1;
             tcg_ctx.gen_opc_icount[lj] = insn_count;
         }
 
diff --git a/translate-all.c b/translate-all.c
index 177e95ab0c..2f616bf321 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -146,8 +146,9 @@ int cpu_restore_state(TranslationBlock *tb,
     if (j < 0)
         return -1;
     /* now find start of instruction before */
-    while (gen_opc_instr_start[j] == 0)
+    while (s->gen_opc_instr_start[j] == 0) {
         j--;
+    }
     env->icount_decr.u16.low -= s->gen_opc_icount[j];
 
     restore_state_to_opc(env, tb, j);

From 94788f54e9deeaa2c82891a7d216fdd6e0e58749 Mon Sep 17 00:00:00 2001
From: Evgeny Voevodin 
Date: Wed, 21 Nov 2012 11:43:07 +0400
Subject: [PATCH 1867/2270] TCG: Remove unused global gen_opc_ arrays.

Signed-off-by: Evgeny Voevodin 
Signed-off-by: Blue Swirl 
---
 exec-all.h      | 4 ----
 translate-all.c | 4 ----
 2 files changed, 8 deletions(-)

diff --git a/exec-all.h b/exec-all.h
index 21aacdab50..b18d4ca534 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -70,10 +70,6 @@ typedef struct TranslationBlock TranslationBlock;
 
 #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * MAX_OPC_PARAM)
 
-extern target_ulong gen_opc_pc[OPC_BUF_SIZE];
-extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
-extern uint16_t gen_opc_icount[OPC_BUF_SIZE];
-
 #include "qemu-log.h"
 
 void gen_intermediate_code(CPUArchState *env, struct TranslationBlock *tb);
diff --git a/translate-all.c b/translate-all.c
index 2f616bf321..f22e3eedd2 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -33,10 +33,6 @@
 /* code generation context */
 TCGContext tcg_ctx;
 
-target_ulong gen_opc_pc[OPC_BUF_SIZE];
-uint16_t gen_opc_icount[OPC_BUF_SIZE];
-uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
-
 void cpu_gen_init(void)
 {
     tcg_context_init(&tcg_ctx); 

From 288fa40736e6eb63132d01aa6dc21ee831b796ae Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Tue, 27 Nov 2012 13:19:40 +0100
Subject: [PATCH 1868/2270] pixman: require 0.18.4 or newer

When older versions are found the internal pixman version is prefered.

Signed-off-by: Gerd Hoffmann 
Signed-off-by: Blue Swirl 
---
 configure | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 994f7310b8..44034d66b9 100755
--- a/configure
+++ b/configure
@@ -2118,7 +2118,7 @@ fi
 # pixman support probe
 
 if test "$pixman" = ""; then
-  if $pkg_config pixman-1 > /dev/null 2>&1; then
+  if $pkg_config --atleast-version=0.18.4 pixman-1 > /dev/null 2>&1; then
     pixman="system"
   else
     pixman="internal"
@@ -2129,7 +2129,7 @@ if test "$pixman" = "system"; then
   pixman_libs=`$pkg_config --libs pixman-1 2>/dev/null`
 else
   if test ! -d ${source_path}/pixman/pixman; then
-    echo "ERROR: pixman not present. Your options:"
+    echo "ERROR: pixman not present (or older than 0.18.4). Your options:"
     echo "  (1) Prefered: Install the pixman devel package (any recent"
     echo "      distro should have packages as Xorg needs pixman too)."
     echo "  (2) Fetch the pixman submodule, using:"

From 475363176c80feedb8feb5e335ba64de68c7b055 Mon Sep 17 00:00:00 2001
From: Peter Maydell 
Date: Wed, 31 Oct 2012 09:30:47 +0000
Subject: [PATCH 1869/2270] HACKING: List areas where we may rely on impdef C
 behaviour

Add a section to HACKING saying which version of the C spec
we use and describing the bits of implementation defined C
compiler behaviour which C code in QEMU is allowed to rely on.

Signed-off-by: Peter Maydell 
Signed-off-by: Blue Swirl 
---
 HACKING | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/HACKING b/HACKING
index 89a6b3ad44..6654d33249 100644
--- a/HACKING
+++ b/HACKING
@@ -123,3 +123,23 @@ gcc's printf attribute directive in the prototype.
 This makes it so gcc's -Wformat and -Wformat-security options can do
 their jobs and cross-check format strings with the number and types
 of arguments.
+
+6. C standard, implementation defined and undefined behaviors
+
+C code in QEMU should be written to the C99 language specification. A copy
+of the final version of the C99 standard with corrigenda TC1, TC2, and TC3
+included, formatted as a draft, can be downloaded from:
+ http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf
+
+The C language specification defines regions of undefined behavior and
+implementation defined behavior (to give compiler authors enough leeway to
+produce better code).  In general, code in QEMU should follow the language
+specification and avoid both undefined and implementation defined
+constructs. ("It works fine on the gcc I tested it with" is not a valid
+argument...) However there are a few areas where we allow ourselves to
+assume certain behaviors because in practice all the platforms we care about
+behave in the same way and writing strictly conformant code would be
+painful. These are:
+ * you may assume that integers are 2s complement representation
+ * you may assume that right shift of a signed integer duplicates
+   the sign bit (ie it is an arithmetic shift, not a logical shift)

From 511c68d3af626cb0a39034cb77e7ac64d3a26c0c Mon Sep 17 00:00:00 2001
From: Eduardo Habkost 
Date: Tue, 4 Dec 2012 16:32:58 -0200
Subject: [PATCH 1870/2270] finally kill cpudef config section support

The external CPU models were removed on QEMU 1.2, and the support for
the "cpudef" config sections was documented as deprecated, but the
actual removal of the config section was pending.

Now that QEMU 1.3 was released, we can finally kill the support for
cpudef config sections, and support only the built-in CPU models from
target-i386/cpu.c.

Signed-off-by: Eduardo Habkost 
Signed-off-by: Blue Swirl 
---
 qemu-config.c | 49 -------------------------------------------------
 1 file changed, 49 deletions(-)

diff --git a/qemu-config.c b/qemu-config.c
index 10d1ba4176..aa78fb9ea7 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -417,54 +417,6 @@ static QemuOptsList qemu_trace_opts = {
     },
 };
 
-static QemuOptsList qemu_cpudef_opts = {
-    .name = "cpudef",
-    .head = QTAILQ_HEAD_INITIALIZER(qemu_cpudef_opts.head),
-    .desc = {
-        {
-            .name = "name",
-            .type = QEMU_OPT_STRING,
-        },{
-            .name = "level",
-            .type = QEMU_OPT_NUMBER,
-        },{
-            .name = "vendor",
-            .type = QEMU_OPT_STRING,
-        },{
-            .name = "family",
-            .type = QEMU_OPT_NUMBER,
-        },{
-            .name = "model",
-            .type = QEMU_OPT_NUMBER,
-        },{
-            .name = "stepping",
-            .type = QEMU_OPT_NUMBER,
-        },{
-            .name = "feature_edx",      /* cpuid 0000_0001.edx */
-            .type = QEMU_OPT_STRING,
-        },{
-            .name = "feature_ecx",      /* cpuid 0000_0001.ecx */
-            .type = QEMU_OPT_STRING,
-        },{
-            .name = "extfeature_edx",   /* cpuid 8000_0001.edx */
-            .type = QEMU_OPT_STRING,
-        },{
-            .name = "extfeature_ecx",   /* cpuid 8000_0001.ecx */
-            .type = QEMU_OPT_STRING,
-        },{
-            .name = "xlevel",
-            .type = QEMU_OPT_NUMBER,
-        },{
-            .name = "model_id",
-            .type = QEMU_OPT_STRING,
-        },{
-            .name = "vendor_override",
-            .type = QEMU_OPT_NUMBER,
-        },
-        { /* end of list */ }
-    },
-};
-
 QemuOptsList qemu_spice_opts = {
     .name = "spice",
     .head = QTAILQ_HEAD_INITIALIZER(qemu_spice_opts.head),
@@ -700,7 +652,6 @@ static QemuOptsList *vm_config_groups[32] = {
     &qemu_rtc_opts,
     &qemu_global_opts,
     &qemu_mon_opts,
-    &qemu_cpudef_opts,
     &qemu_trace_opts,
     &qemu_option_rom_opts,
     &qemu_machine_opts,

From fcc803d119a4c01a9b0ee5bda35fda1eeabffa33 Mon Sep 17 00:00:00 2001
From: Max Filippov 
Date: Wed, 5 Dec 2012 07:15:20 +0400
Subject: [PATCH 1871/2270] target-xtensa: implement ATOMCTL SR

ATOMCTL SR controls s32c1i opcode behavior depending on targeted memory
type. See ISA, 4.3.12.4 for details.

Signed-off-by: Max Filippov 
Signed-off-by: Blue Swirl 
---
 target-xtensa/cpu.c          |  2 ++
 target-xtensa/cpu.h          | 10 +++++++
 target-xtensa/helper.c       | 56 ++++++++++++++++++++++++++---------
 target-xtensa/helper.h       |  1 +
 target-xtensa/op_helper.c    | 57 ++++++++++++++++++++++++++++++++++++
 target-xtensa/overlay_tool.h |  6 ++++
 target-xtensa/translate.c    | 13 ++++++++
 7 files changed, 131 insertions(+), 14 deletions(-)

diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
index 9d01983d44..c6aa45ee6f 100644
--- a/target-xtensa/cpu.c
+++ b/target-xtensa/cpu.c
@@ -48,6 +48,8 @@ static void xtensa_cpu_reset(CPUState *s)
             XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10;
     env->sregs[VECBASE] = env->config->vecbase;
     env->sregs[IBREAKENABLE] = 0;
+    env->sregs[ATOMCTL] = xtensa_option_enabled(env->config,
+            XTENSA_OPTION_ATOMCTL) ? 0x28 : 0x15;
 
     env->pending_irq_level = 0;
     reset_mmu(env);
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 74e98883bf..d240ab70d9 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -65,6 +65,7 @@ enum {
     XTENSA_OPTION_FP_COPROCESSOR,
     XTENSA_OPTION_MP_SYNCHRO,
     XTENSA_OPTION_CONDITIONAL_STORE,
+    XTENSA_OPTION_ATOMCTL,
 
     /* Interrupts and exceptions */
     XTENSA_OPTION_EXCEPTION,
@@ -128,6 +129,7 @@ enum {
     ITLBCFG = 91,
     DTLBCFG = 92,
     IBREAKENABLE = 96,
+    ATOMCTL = 99,
     IBREAKA = 128,
     DBREAKA = 144,
     DBREAKC = 160,
@@ -193,6 +195,14 @@ enum {
 
 #define REGION_PAGE_MASK 0xe0000000
 
+#define PAGE_CACHE_MASK    0x700
+#define PAGE_CACHE_SHIFT   8
+#define PAGE_CACHE_INVALID 0x000
+#define PAGE_CACHE_BYPASS  0x100
+#define PAGE_CACHE_WT      0x200
+#define PAGE_CACHE_WB      0x400
+#define PAGE_CACHE_ISOLATE 0x600
+
 enum {
     /* Static vectors */
     EXC_RESET,
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index d94bae210d..ecd0182281 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -390,6 +390,7 @@ int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb,
 static unsigned mmu_attr_to_access(uint32_t attr)
 {
     unsigned access = 0;
+
     if (attr < 12) {
         access |= PAGE_READ;
         if (attr & 0x1) {
@@ -398,8 +399,22 @@ static unsigned mmu_attr_to_access(uint32_t attr)
         if (attr & 0x2) {
             access |= PAGE_WRITE;
         }
+
+        switch (attr & 0xc) {
+        case 0:
+            access |= PAGE_CACHE_BYPASS;
+            break;
+
+        case 4:
+            access |= PAGE_CACHE_WB;
+            break;
+
+        case 8:
+            access |= PAGE_CACHE_WT;
+            break;
+        }
     } else if (attr == 13) {
-        access |= PAGE_READ | PAGE_WRITE;
+        access |= PAGE_READ | PAGE_WRITE | PAGE_CACHE_ISOLATE;
     }
     return access;
 }
@@ -410,14 +425,17 @@ static unsigned mmu_attr_to_access(uint32_t attr)
  */
 static unsigned region_attr_to_access(uint32_t attr)
 {
-    unsigned access = 0;
-    if ((attr < 6 && attr != 3) || attr == 14) {
-        access |= PAGE_READ | PAGE_WRITE;
-    }
-    if (attr > 0 && attr < 6) {
-        access |= PAGE_EXEC;
-    }
-    return access;
+    static const unsigned access[16] = {
+         [0] = PAGE_READ | PAGE_WRITE             | PAGE_CACHE_WT,
+         [1] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WT,
+         [2] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_BYPASS,
+         [3] =                          PAGE_EXEC | PAGE_CACHE_WB,
+         [4] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WB,
+         [5] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WB,
+        [14] = PAGE_READ | PAGE_WRITE             | PAGE_CACHE_ISOLATE,
+    };
+
+    return access[attr & 0xf];
 }
 
 static bool is_access_granted(unsigned access, int is_write)
@@ -566,7 +584,7 @@ int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb,
     } else {
         *paddr = vaddr;
         *page_size = TARGET_PAGE_SIZE;
-        *access = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+        *access = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_BYPASS;
         return 0;
     }
 }
@@ -599,24 +617,34 @@ static void dump_tlb(FILE *f, fprintf_function cpu_fprintf,
                 xtensa_tlb_get_entry(env, dtlb, wi, ei);
 
             if (entry->asid) {
+                static const char * const cache_text[8] = {
+                    [PAGE_CACHE_BYPASS >> PAGE_CACHE_SHIFT] = "Bypass",
+                    [PAGE_CACHE_WT >> PAGE_CACHE_SHIFT] = "WT",
+                    [PAGE_CACHE_WB >> PAGE_CACHE_SHIFT] = "WB",
+                    [PAGE_CACHE_ISOLATE >> PAGE_CACHE_SHIFT] = "Isolate",
+                };
                 unsigned access = attr_to_access(entry->attr);
+                unsigned cache_idx = (access & PAGE_CACHE_MASK) >>
+                    PAGE_CACHE_SHIFT;
 
                 if (print_header) {
                     print_header = false;
                     cpu_fprintf(f, "Way %u (%d %s)\n", wi, sz, sz_text);
                     cpu_fprintf(f,
-                            "\tVaddr       Paddr       ASID  Attr RWX\n"
-                            "\t----------  ----------  ----  ---- ---\n");
+                            "\tVaddr       Paddr       ASID  Attr RWX Cache\n"
+                            "\t----------  ----------  ----  ---- --- -------\n");
                 }
                 cpu_fprintf(f,
-                        "\t0x%08x  0x%08x  0x%02x  0x%02x %c%c%c\n",
+                        "\t0x%08x  0x%08x  0x%02x  0x%02x %c%c%c %-7s\n",
                         entry->vaddr,
                         entry->paddr,
                         entry->asid,
                         entry->attr,
                         (access & PAGE_READ) ? 'R' : '-',
                         (access & PAGE_WRITE) ? 'W' : '-',
-                        (access & PAGE_EXEC) ? 'X' : '-');
+                        (access & PAGE_EXEC) ? 'X' : '-',
+                        cache_text[cache_idx] ? cache_text[cache_idx] :
+                            "Invalid");
             }
         }
     }
diff --git a/target-xtensa/helper.h b/target-xtensa/helper.h
index 1163c09836..5b4cd2700f 100644
--- a/target-xtensa/helper.h
+++ b/target-xtensa/helper.h
@@ -23,6 +23,7 @@ DEF_HELPER_3(waiti, void, env, i32, i32)
 DEF_HELPER_3(timer_irq, void, env, i32, i32)
 DEF_HELPER_2(advance_ccount, void, env, i32)
 DEF_HELPER_1(check_interrupts, void, env)
+DEF_HELPER_3(check_atomctl, void, env, i32, i32)
 
 DEF_HELPER_2(wsr_rasid, void, env, i32)
 DEF_HELPER_FLAGS_3(rtlb0, TCG_CALL_NO_RWG_SE, i32, env, i32, i32)
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index ae0c09977b..0e0f21d1a2 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -415,6 +415,63 @@ void HELPER(check_interrupts)(CPUXtensaState *env)
     check_interrupts(env);
 }
 
+/*!
+ * Check vaddr accessibility/cache attributes and raise an exception if
+ * specified by the ATOMCTL SR.
+ *
+ * Note: local memory exclusion is not implemented
+ */
+void HELPER(check_atomctl)(CPUXtensaState *env, uint32_t pc, uint32_t vaddr)
+{
+    uint32_t paddr, page_size, access;
+    uint32_t atomctl = env->sregs[ATOMCTL];
+    int rc = xtensa_get_physical_addr(env, true, vaddr, 1,
+            xtensa_get_cring(env), &paddr, &page_size, &access);
+
+    /*
+     * s32c1i never causes LOAD_PROHIBITED_CAUSE exceptions,
+     * see opcode description in the ISA
+     */
+    if (rc == 0 &&
+            (access & (PAGE_READ | PAGE_WRITE)) != (PAGE_READ | PAGE_WRITE)) {
+        rc = STORE_PROHIBITED_CAUSE;
+    }
+
+    if (rc) {
+        HELPER(exception_cause_vaddr)(env, pc, rc, vaddr);
+    }
+
+    /*
+     * When data cache is not configured use ATOMCTL bypass field.
+     * See ISA, 4.3.12.4 The Atomic Operation Control Register (ATOMCTL)
+     * under the Conditional Store Option.
+     */
+    if (!xtensa_option_enabled(env->config, XTENSA_OPTION_DCACHE)) {
+        access = PAGE_CACHE_BYPASS;
+    }
+
+    switch (access & PAGE_CACHE_MASK) {
+    case PAGE_CACHE_WB:
+        atomctl >>= 2;
+    case PAGE_CACHE_WT:
+        atomctl >>= 2;
+    case PAGE_CACHE_BYPASS:
+        if ((atomctl & 0x3) == 0) {
+            HELPER(exception_cause_vaddr)(env, pc,
+                    LOAD_STORE_ERROR_CAUSE, vaddr);
+        }
+        break;
+
+    case PAGE_CACHE_ISOLATE:
+        HELPER(exception_cause_vaddr)(env, pc,
+                LOAD_STORE_ERROR_CAUSE, vaddr);
+        break;
+
+    default:
+        break;
+    }
+}
+
 void HELPER(wsr_rasid)(CPUXtensaState *env, uint32_t v)
 {
     v = (v & 0xffffff00) | 0x1;
diff --git a/target-xtensa/overlay_tool.h b/target-xtensa/overlay_tool.h
index e39505316b..50bf5735e9 100644
--- a/target-xtensa/overlay_tool.h
+++ b/target-xtensa/overlay_tool.h
@@ -42,6 +42,10 @@
 #define XCHAL_VECBASE_RESET_VADDR 0
 #endif
 
+#ifndef XCHAL_HW_MIN_VERSION
+#define XCHAL_HW_MIN_VERSION 0
+#endif
+
 #define XCHAL_OPTION(xchal, qemu) ((xchal) ? XTENSA_OPTION_BIT(qemu) : 0)
 
 #define XTENSA_OPTIONS ( \
@@ -62,6 +66,8 @@
     XCHAL_OPTION(XCHAL_HAVE_FP, XTENSA_OPTION_FP_COPROCESSOR) | \
     XCHAL_OPTION(XCHAL_HAVE_RELEASE_SYNC, XTENSA_OPTION_MP_SYNCHRO) | \
     XCHAL_OPTION(XCHAL_HAVE_S32C1I, XTENSA_OPTION_CONDITIONAL_STORE) | \
+    XCHAL_OPTION(XCHAL_HAVE_S32C1I && XCHAL_HW_MIN_VERSION >= 230000, \
+        XTENSA_OPTION_ATOMCTL) | \
     /* Interrupts and exceptions */ \
     XCHAL_OPTION(XCHAL_HAVE_EXCEPTIONS, XTENSA_OPTION_EXCEPTION) | \
     XCHAL_OPTION(XCHAL_HAVE_VECBASE, XTENSA_OPTION_RELOCATABLE_VECTOR) | \
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 828b9cabb5..dc08de51ba 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -99,6 +99,7 @@ static const char * const sregnames[256] = {
     [ITLBCFG] = "ITLBCFG",
     [DTLBCFG] = "DTLBCFG",
     [IBREAKENABLE] = "IBREAKENABLE",
+    [ATOMCTL] = "ATOMCTL",
     [IBREAKA] = "IBREAKA0",
     [IBREAKA + 1] = "IBREAKA1",
     [DBREAKA] = "DBREAKA0",
@@ -556,6 +557,11 @@ static void gen_wsr_ibreakenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
     gen_jumpi_check_loop_end(dc, 0);
 }
 
+static void gen_wsr_atomctl(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    tcg_gen_andi_i32(cpu_SR[sr], v, 0x3f);
+}
+
 static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     unsigned id = sr - IBREAKA;
@@ -693,6 +699,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [ITLBCFG] = gen_wsr_tlbcfg,
         [DTLBCFG] = gen_wsr_tlbcfg,
         [IBREAKENABLE] = gen_wsr_ibreakenable,
+        [ATOMCTL] = gen_wsr_atomctl,
         [IBREAKA] = gen_wsr_ibreaka,
         [IBREAKA + 1] = gen_wsr_ibreaka,
         [DBREAKA] = gen_wsr_dbreaka,
@@ -2317,10 +2324,15 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 int label = gen_new_label();
                 TCGv_i32 tmp = tcg_temp_local_new_i32();
                 TCGv_i32 addr = tcg_temp_local_new_i32();
+                TCGv_i32 tpc;
 
                 tcg_gen_mov_i32(tmp, cpu_R[RRI8_T]);
                 tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2);
                 gen_load_store_alignment(dc, 2, addr, true);
+
+                gen_advance_ccount(dc);
+                tpc = tcg_const_i32(dc->pc);
+                gen_helper_check_atomctl(cpu_env, tpc, addr);
                 tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, dc->cring);
                 tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[RRI8_T],
                         cpu_SR[SCOMPARE1], label);
@@ -2328,6 +2340,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 tcg_gen_qemu_st32(tmp, addr, dc->cring);
 
                 gen_set_label(label);
+                tcg_temp_free(tpc);
                 tcg_temp_free(addr);
                 tcg_temp_free(tmp);
             }

From 4e41d2f5830a76d3fe92b3d3b18cc9f2ee927770 Mon Sep 17 00:00:00 2001
From: Max Filippov 
Date: Wed, 5 Dec 2012 07:15:21 +0400
Subject: [PATCH 1872/2270] target-xtensa: implement CACHEATTR SR

In XEA1, the Options for Memory Protection and Translation and the
corresponding TLB management instructions are not available. Instead,
functionality similar to the Region Protection Option is available
through the cache attribute register. See ISA, A.2.14 for details.

Signed-off-by: Max Filippov 
Signed-off-by: Blue Swirl 
---
 target-xtensa/cpu.c          |  1 +
 target-xtensa/cpu.h          |  2 ++
 target-xtensa/helper.c       | 21 ++++++++++++++++++++-
 target-xtensa/overlay_tool.h |  1 +
 target-xtensa/translate.c    |  1 +
 5 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
index c6aa45ee6f..035b07c1c5 100644
--- a/target-xtensa/cpu.c
+++ b/target-xtensa/cpu.c
@@ -48,6 +48,7 @@ static void xtensa_cpu_reset(CPUState *s)
             XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10;
     env->sregs[VECBASE] = env->config->vecbase;
     env->sregs[IBREAKENABLE] = 0;
+    env->sregs[CACHEATTR] = 0x22222222;
     env->sregs[ATOMCTL] = xtensa_option_enabled(env->config,
             XTENSA_OPTION_ATOMCTL) ? 0x28 : 0x15;
 
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index d240ab70d9..068ad69ee9 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -94,6 +94,7 @@ enum {
     XTENSA_OPTION_REGION_PROTECTION,
     XTENSA_OPTION_REGION_TRANSLATION,
     XTENSA_OPTION_MMU,
+    XTENSA_OPTION_CACHEATTR,
 
     /* Other */
     XTENSA_OPTION_WINDOWED_REGISTER,
@@ -129,6 +130,7 @@ enum {
     ITLBCFG = 91,
     DTLBCFG = 92,
     IBREAKENABLE = 96,
+    CACHEATTR = 98,
     ATOMCTL = 99,
     IBREAKA = 128,
     DBREAKA = 144,
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index ecd0182281..200fb43c28 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -438,6 +438,24 @@ static unsigned region_attr_to_access(uint32_t attr)
     return access[attr & 0xf];
 }
 
+/*!
+ * Convert cacheattr to PAGE_{READ,WRITE,EXEC} mask.
+ * See ISA, A.2.14 The Cache Attribute Register
+ */
+static unsigned cacheattr_attr_to_access(uint32_t attr)
+{
+    static const unsigned access[16] = {
+         [0] = PAGE_READ | PAGE_WRITE             | PAGE_CACHE_WT,
+         [1] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WT,
+         [2] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_BYPASS,
+         [3] =                          PAGE_EXEC | PAGE_CACHE_WB,
+         [4] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WB,
+        [14] = PAGE_READ | PAGE_WRITE             | PAGE_CACHE_ISOLATE,
+    };
+
+    return access[attr & 0xf];
+}
+
 static bool is_access_granted(unsigned access, int is_write)
 {
     switch (is_write) {
@@ -584,7 +602,8 @@ int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb,
     } else {
         *paddr = vaddr;
         *page_size = TARGET_PAGE_SIZE;
-        *access = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_BYPASS;
+        *access = cacheattr_attr_to_access(
+                env->sregs[CACHEATTR] >> ((vaddr & 0xe0000000) >> 27));
         return 0;
     }
 }
diff --git a/target-xtensa/overlay_tool.h b/target-xtensa/overlay_tool.h
index 50bf5735e9..45205b8e67 100644
--- a/target-xtensa/overlay_tool.h
+++ b/target-xtensa/overlay_tool.h
@@ -91,6 +91,7 @@
     XCHAL_OPTION(XCHAL_HAVE_XLT_CACHEATTR, \
             XTENSA_OPTION_REGION_TRANSLATION) | \
     XCHAL_OPTION(XCHAL_HAVE_PTP_MMU, XTENSA_OPTION_MMU) | \
+    XCHAL_OPTION(XCHAL_HAVE_CACHEATTR, XTENSA_OPTION_CACHEATTR) | \
     /* Other, TODO */ \
     XCHAL_OPTION(XCHAL_HAVE_WINDOWED, XTENSA_OPTION_WINDOWED_REGISTER) | \
     XCHAL_OPTION(XCHAL_HAVE_DEBUG, XTENSA_OPTION_DEBUG))
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index dc08de51ba..eb4812099e 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -99,6 +99,7 @@ static const char * const sregnames[256] = {
     [ITLBCFG] = "ITLBCFG",
     [DTLBCFG] = "DTLBCFG",
     [IBREAKENABLE] = "IBREAKENABLE",
+    [CACHEATTR] = "CACHEATTR",
     [ATOMCTL] = "ATOMCTL",
     [IBREAKA] = "IBREAKA0",
     [IBREAKA + 1] = "IBREAKA1",

From fe0bd475aa31e60674f7f53b85dc293108026202 Mon Sep 17 00:00:00 2001
From: Max Filippov 
Date: Wed, 5 Dec 2012 07:15:22 +0400
Subject: [PATCH 1873/2270] target-xtensa: restrict available SRs by enabled
 options

Beginning with the RA-2004.1 release, SR access instructions (rsr, wsr,
xsr) are associated with their corresponding SR and raise illegal opcode
exception in case the register is not configured for the core.

Signed-off-by: Max Filippov 
Signed-off-by: Blue Swirl 
---
 target-xtensa/cpu.h          |   1 +
 target-xtensa/overlay_tool.h |   4 +-
 target-xtensa/translate.c    | 230 +++++++++++++++++++----------------
 3 files changed, 130 insertions(+), 105 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 068ad69ee9..a73d32d898 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -416,6 +416,7 @@ void debug_exception_env(CPUXtensaState *new_env, uint32_t cause);
 
 
 #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
+#define XTENSA_OPTION_ALL (~(uint64_t)0)
 
 static inline bool xtensa_option_bits_enabled(const XtensaConfig *config,
         uint64_t opt)
diff --git a/target-xtensa/overlay_tool.h b/target-xtensa/overlay_tool.h
index 45205b8e67..0b47029f8c 100644
--- a/target-xtensa/overlay_tool.h
+++ b/target-xtensa/overlay_tool.h
@@ -94,7 +94,9 @@
     XCHAL_OPTION(XCHAL_HAVE_CACHEATTR, XTENSA_OPTION_CACHEATTR) | \
     /* Other, TODO */ \
     XCHAL_OPTION(XCHAL_HAVE_WINDOWED, XTENSA_OPTION_WINDOWED_REGISTER) | \
-    XCHAL_OPTION(XCHAL_HAVE_DEBUG, XTENSA_OPTION_DEBUG))
+    XCHAL_OPTION(XCHAL_HAVE_DEBUG, XTENSA_OPTION_DEBUG) |\
+    XCHAL_OPTION(XCHAL_HAVE_THREADPTR, XTENSA_OPTION_THREAD_POINTER) | \
+    XCHAL_OPTION(XCHAL_HAVE_PRID, XTENSA_OPTION_PROCESSOR_ID))
 
 #ifndef XCHAL_WINDOW_OF4_VECOFS
 #define XCHAL_WINDOW_OF4_VECOFS         0x00000000
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index eb4812099e..74b7b0f1aa 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -78,78 +78,102 @@ static TCGv_i32 cpu_UR[256];
 
 #include "gen-icount.h"
 
-static const char * const sregnames[256] = {
-    [LBEG] = "LBEG",
-    [LEND] = "LEND",
-    [LCOUNT] = "LCOUNT",
-    [SAR] = "SAR",
-    [BR] = "BR",
-    [LITBASE] = "LITBASE",
-    [SCOMPARE1] = "SCOMPARE1",
-    [ACCLO] = "ACCLO",
-    [ACCHI] = "ACCHI",
-    [MR] = "MR0",
-    [MR + 1] = "MR1",
-    [MR + 2] = "MR2",
-    [MR + 3] = "MR3",
-    [WINDOW_BASE] = "WINDOW_BASE",
-    [WINDOW_START] = "WINDOW_START",
-    [PTEVADDR] = "PTEVADDR",
-    [RASID] = "RASID",
-    [ITLBCFG] = "ITLBCFG",
-    [DTLBCFG] = "DTLBCFG",
-    [IBREAKENABLE] = "IBREAKENABLE",
-    [CACHEATTR] = "CACHEATTR",
-    [ATOMCTL] = "ATOMCTL",
-    [IBREAKA] = "IBREAKA0",
-    [IBREAKA + 1] = "IBREAKA1",
-    [DBREAKA] = "DBREAKA0",
-    [DBREAKA + 1] = "DBREAKA1",
-    [DBREAKC] = "DBREAKC0",
-    [DBREAKC + 1] = "DBREAKC1",
-    [EPC1] = "EPC1",
-    [EPC1 + 1] = "EPC2",
-    [EPC1 + 2] = "EPC3",
-    [EPC1 + 3] = "EPC4",
-    [EPC1 + 4] = "EPC5",
-    [EPC1 + 5] = "EPC6",
-    [EPC1 + 6] = "EPC7",
-    [DEPC] = "DEPC",
-    [EPS2] = "EPS2",
-    [EPS2 + 1] = "EPS3",
-    [EPS2 + 2] = "EPS4",
-    [EPS2 + 3] = "EPS5",
-    [EPS2 + 4] = "EPS6",
-    [EPS2 + 5] = "EPS7",
-    [EXCSAVE1] = "EXCSAVE1",
-    [EXCSAVE1 + 1] = "EXCSAVE2",
-    [EXCSAVE1 + 2] = "EXCSAVE3",
-    [EXCSAVE1 + 3] = "EXCSAVE4",
-    [EXCSAVE1 + 4] = "EXCSAVE5",
-    [EXCSAVE1 + 5] = "EXCSAVE6",
-    [EXCSAVE1 + 6] = "EXCSAVE7",
-    [CPENABLE] = "CPENABLE",
-    [INTSET] = "INTSET",
-    [INTCLEAR] = "INTCLEAR",
-    [INTENABLE] = "INTENABLE",
-    [PS] = "PS",
-    [VECBASE] = "VECBASE",
-    [EXCCAUSE] = "EXCCAUSE",
-    [DEBUGCAUSE] = "DEBUGCAUSE",
-    [CCOUNT] = "CCOUNT",
-    [PRID] = "PRID",
-    [ICOUNT] = "ICOUNT",
-    [ICOUNTLEVEL] = "ICOUNTLEVEL",
-    [EXCVADDR] = "EXCVADDR",
-    [CCOMPARE] = "CCOMPARE0",
-    [CCOMPARE + 1] = "CCOMPARE1",
-    [CCOMPARE + 2] = "CCOMPARE2",
+typedef struct XtensaReg {
+    const char *name;
+    uint64_t opt_bits;
+} XtensaReg;
+
+#define XTENSA_REG(regname, opt) { \
+        .name = (regname), \
+        .opt_bits = XTENSA_OPTION_BIT(opt), \
+    }
+
+#define XTENSA_REG_BITS(regname, opt) { \
+        .name = (regname), \
+        .opt_bits = (opt), \
+    }
+
+static const XtensaReg sregnames[256] = {
+    [LBEG] = XTENSA_REG("LBEG", XTENSA_OPTION_LOOP),
+    [LEND] = XTENSA_REG("LEND", XTENSA_OPTION_LOOP),
+    [LCOUNT] = XTENSA_REG("LCOUNT", XTENSA_OPTION_LOOP),
+    [SAR] = XTENSA_REG_BITS("SAR", XTENSA_OPTION_ALL),
+    [BR] = XTENSA_REG("BR", XTENSA_OPTION_BOOLEAN),
+    [LITBASE] = XTENSA_REG("LITBASE", XTENSA_OPTION_EXTENDED_L32R),
+    [SCOMPARE1] = XTENSA_REG("SCOMPARE1", XTENSA_OPTION_CONDITIONAL_STORE),
+    [ACCLO] = XTENSA_REG("ACCLO", XTENSA_OPTION_MAC16),
+    [ACCHI] = XTENSA_REG("ACCHI", XTENSA_OPTION_MAC16),
+    [MR] = XTENSA_REG("MR0", XTENSA_OPTION_MAC16),
+    [MR + 1] = XTENSA_REG("MR1", XTENSA_OPTION_MAC16),
+    [MR + 2] = XTENSA_REG("MR2", XTENSA_OPTION_MAC16),
+    [MR + 3] = XTENSA_REG("MR3", XTENSA_OPTION_MAC16),
+    [WINDOW_BASE] = XTENSA_REG("WINDOW_BASE", XTENSA_OPTION_WINDOWED_REGISTER),
+    [WINDOW_START] = XTENSA_REG("WINDOW_START",
+            XTENSA_OPTION_WINDOWED_REGISTER),
+    [PTEVADDR] = XTENSA_REG("PTEVADDR", XTENSA_OPTION_MMU),
+    [RASID] = XTENSA_REG("RASID", XTENSA_OPTION_MMU),
+    [ITLBCFG] = XTENSA_REG("ITLBCFG", XTENSA_OPTION_MMU),
+    [DTLBCFG] = XTENSA_REG("DTLBCFG", XTENSA_OPTION_MMU),
+    [IBREAKENABLE] = XTENSA_REG("IBREAKENABLE", XTENSA_OPTION_DEBUG),
+    [CACHEATTR] = XTENSA_REG("CACHEATTR", XTENSA_OPTION_CACHEATTR),
+    [ATOMCTL] = XTENSA_REG("ATOMCTL", XTENSA_OPTION_ATOMCTL),
+    [IBREAKA] = XTENSA_REG("IBREAKA0", XTENSA_OPTION_DEBUG),
+    [IBREAKA + 1] = XTENSA_REG("IBREAKA1", XTENSA_OPTION_DEBUG),
+    [DBREAKA] = XTENSA_REG("DBREAKA0", XTENSA_OPTION_DEBUG),
+    [DBREAKA + 1] = XTENSA_REG("DBREAKA1", XTENSA_OPTION_DEBUG),
+    [DBREAKC] = XTENSA_REG("DBREAKC0", XTENSA_OPTION_DEBUG),
+    [DBREAKC + 1] = XTENSA_REG("DBREAKC1", XTENSA_OPTION_DEBUG),
+    [EPC1] = XTENSA_REG("EPC1", XTENSA_OPTION_EXCEPTION),
+    [EPC1 + 1] = XTENSA_REG("EPC2", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [EPC1 + 2] = XTENSA_REG("EPC3", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [EPC1 + 3] = XTENSA_REG("EPC4", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [EPC1 + 4] = XTENSA_REG("EPC5", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [EPC1 + 5] = XTENSA_REG("EPC6", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [EPC1 + 6] = XTENSA_REG("EPC7", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [DEPC] = XTENSA_REG("DEPC", XTENSA_OPTION_EXCEPTION),
+    [EPS2] = XTENSA_REG("EPS2", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [EPS2 + 1] = XTENSA_REG("EPS3", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [EPS2 + 2] = XTENSA_REG("EPS4", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [EPS2 + 3] = XTENSA_REG("EPS5", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [EPS2 + 4] = XTENSA_REG("EPS6", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [EPS2 + 5] = XTENSA_REG("EPS7", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [EXCSAVE1] = XTENSA_REG("EXCSAVE1", XTENSA_OPTION_EXCEPTION),
+    [EXCSAVE1 + 1] = XTENSA_REG("EXCSAVE2",
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [EXCSAVE1 + 2] = XTENSA_REG("EXCSAVE3",
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [EXCSAVE1 + 3] = XTENSA_REG("EXCSAVE4",
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [EXCSAVE1 + 4] = XTENSA_REG("EXCSAVE5",
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [EXCSAVE1 + 5] = XTENSA_REG("EXCSAVE6",
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [EXCSAVE1 + 6] = XTENSA_REG("EXCSAVE7",
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
+    [CPENABLE] = XTENSA_REG("CPENABLE", XTENSA_OPTION_COPROCESSOR),
+    [INTSET] = XTENSA_REG("INTSET", XTENSA_OPTION_INTERRUPT),
+    [INTCLEAR] = XTENSA_REG("INTCLEAR", XTENSA_OPTION_INTERRUPT),
+    [INTENABLE] = XTENSA_REG("INTENABLE", XTENSA_OPTION_INTERRUPT),
+    [PS] = XTENSA_REG_BITS("PS", XTENSA_OPTION_ALL),
+    [VECBASE] = XTENSA_REG("VECBASE", XTENSA_OPTION_RELOCATABLE_VECTOR),
+    [EXCCAUSE] = XTENSA_REG("EXCCAUSE", XTENSA_OPTION_EXCEPTION),
+    [DEBUGCAUSE] = XTENSA_REG("DEBUGCAUSE", XTENSA_OPTION_DEBUG),
+    [CCOUNT] = XTENSA_REG("CCOUNT", XTENSA_OPTION_TIMER_INTERRUPT),
+    [PRID] = XTENSA_REG("PRID", XTENSA_OPTION_PROCESSOR_ID),
+    [ICOUNT] = XTENSA_REG("ICOUNT", XTENSA_OPTION_DEBUG),
+    [ICOUNTLEVEL] = XTENSA_REG("ICOUNTLEVEL", XTENSA_OPTION_DEBUG),
+    [EXCVADDR] = XTENSA_REG("EXCVADDR", XTENSA_OPTION_EXCEPTION),
+    [CCOMPARE] = XTENSA_REG("CCOMPARE0", XTENSA_OPTION_TIMER_INTERRUPT),
+    [CCOMPARE + 1] = XTENSA_REG("CCOMPARE1",
+            XTENSA_OPTION_TIMER_INTERRUPT),
+    [CCOMPARE + 2] = XTENSA_REG("CCOMPARE2",
+            XTENSA_OPTION_TIMER_INTERRUPT),
 };
 
-static const char * const uregnames[256] = {
-    [THREADPTR] = "THREADPTR",
-    [FCR] = "FCR",
-    [FSR] = "FSR",
+static const XtensaReg uregnames[256] = {
+    [THREADPTR] = XTENSA_REG("THREADPTR", XTENSA_OPTION_THREAD_POINTER),
+    [FCR] = XTENSA_REG("FCR", XTENSA_OPTION_FP_COPROCESSOR),
+    [FSR] = XTENSA_REG("FSR", XTENSA_OPTION_FP_COPROCESSOR),
 };
 
 void xtensa_translate_init(void)
@@ -185,18 +209,18 @@ void xtensa_translate_init(void)
     }
 
     for (i = 0; i < 256; ++i) {
-        if (sregnames[i]) {
+        if (sregnames[i].name) {
             cpu_SR[i] = tcg_global_mem_new_i32(TCG_AREG0,
                     offsetof(CPUXtensaState, sregs[i]),
-                    sregnames[i]);
+                    sregnames[i].name);
         }
     }
 
     for (i = 0; i < 256; ++i) {
-        if (uregnames[i]) {
+        if (uregnames[i].name) {
             cpu_UR[i] = tcg_global_mem_new_i32(TCG_AREG0,
                     offsetof(CPUXtensaState, uregs[i]),
-                    uregnames[i]);
+                    uregnames[i].name);
         }
     }
 #define GEN_HELPER 2
@@ -452,6 +476,18 @@ static void gen_brcondi(DisasContext *dc, TCGCond cond,
     tcg_temp_free(tmp);
 }
 
+static void gen_check_sr(DisasContext *dc, uint32_t sr)
+{
+    if (!xtensa_option_bits_enabled(dc->config, sregnames[sr].opt_bits)) {
+        if (sregnames[sr].name) {
+            qemu_log("SR %s is not configured\n", sregnames[sr].name);
+        } else {
+            qemu_log("SR %d is not implemented\n", sr);
+        }
+        gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
+    }
+}
+
 static void gen_rsr_ccount(DisasContext *dc, TCGv_i32 d, uint32_t sr)
 {
     gen_advance_ccount(dc);
@@ -473,14 +509,10 @@ static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
         [PTEVADDR] = gen_rsr_ptevaddr,
     };
 
-    if (sregnames[sr]) {
-        if (rsr_handler[sr]) {
-            rsr_handler[sr](dc, d, sr);
-        } else {
-            tcg_gen_mov_i32(d, cpu_SR[sr]);
-        }
+    if (rsr_handler[sr]) {
+        rsr_handler[sr](dc, d, sr);
     } else {
-        qemu_log("RSR %d not implemented, ", sr);
+        tcg_gen_mov_i32(d, cpu_SR[sr]);
     }
 }
 
@@ -721,14 +753,10 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [CCOMPARE + 2] = gen_wsr_ccompare,
     };
 
-    if (sregnames[sr]) {
-        if (wsr_handler[sr]) {
-            wsr_handler[sr](dc, sr, s);
-        } else {
-            tcg_gen_mov_i32(cpu_SR[sr], s);
-        }
+    if (wsr_handler[sr]) {
+        wsr_handler[sr](dc, sr, s);
     } else {
-        qemu_log("WSR %d not implemented, ", sr);
+        tcg_gen_mov_i32(cpu_SR[sr], s);
     }
 }
 
@@ -1439,6 +1467,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             case 6: /*XSR*/
                 {
                     TCGv_i32 tmp = tcg_temp_new_i32();
+                    gen_check_sr(dc, RSR_SR);
                     if (RSR_SR >= 64) {
                         gen_check_privilege(dc);
                     }
@@ -1447,9 +1476,6 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                     gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
                     gen_wsr(dc, RSR_SR, tmp);
                     tcg_temp_free(tmp);
-                    if (!sregnames[RSR_SR]) {
-                        TBD();
-                    }
                 }
                 break;
 
@@ -1672,25 +1698,21 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
         case 3: /*RST3*/
             switch (OP2) {
             case 0: /*RSR*/
+                gen_check_sr(dc, RSR_SR);
                 if (RSR_SR >= 64) {
                     gen_check_privilege(dc);
                 }
                 gen_window_check1(dc, RRR_T);
                 gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
-                if (!sregnames[RSR_SR]) {
-                    TBD();
-                }
                 break;
 
             case 1: /*WSR*/
+                gen_check_sr(dc, RSR_SR);
                 if (RSR_SR >= 64) {
                     gen_check_privilege(dc);
                 }
                 gen_window_check1(dc, RRR_T);
                 gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);
-                if (!sregnames[RSR_SR]) {
-                    TBD();
-                }
                 break;
 
             case 2: /*SEXTu*/
@@ -1807,7 +1829,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 gen_window_check1(dc, RRR_R);
                 {
                     int st = (RRR_S << 4) + RRR_T;
-                    if (uregnames[st]) {
+                    if (uregnames[st].name) {
                         tcg_gen_mov_i32(cpu_R[RRR_R], cpu_UR[st]);
                     } else {
                         qemu_log("RUR %d not implemented, ", st);
@@ -1818,7 +1840,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
             case 15: /*WUR*/
                 gen_window_check1(dc, RRR_T);
-                if (uregnames[RSR_SR]) {
+                if (uregnames[RSR_SR].name) {
                     gen_wur(RSR_SR, cpu_R[RRR_T]);
                 } else {
                     qemu_log("WUR %d not implemented, ", RSR_SR);
@@ -3000,8 +3022,8 @@ void cpu_dump_state(CPUXtensaState *env, FILE *f, fprintf_function cpu_fprintf,
     cpu_fprintf(f, "PC=%08x\n\n", env->pc);
 
     for (i = j = 0; i < 256; ++i) {
-        if (sregnames[i]) {
-            cpu_fprintf(f, "%s=%08x%c", sregnames[i], env->sregs[i],
+        if (xtensa_option_bits_enabled(env->config, sregnames[i].opt_bits)) {
+            cpu_fprintf(f, "%12s=%08x%c", sregnames[i].name, env->sregs[i],
                     (j++ % 4) == 3 ? '\n' : ' ');
         }
     }
@@ -3009,8 +3031,8 @@ void cpu_dump_state(CPUXtensaState *env, FILE *f, fprintf_function cpu_fprintf,
     cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
 
     for (i = j = 0; i < 256; ++i) {
-        if (uregnames[i]) {
-            cpu_fprintf(f, "%s=%08x%c", uregnames[i], env->uregs[i],
+        if (xtensa_option_bits_enabled(env->config, uregnames[i].opt_bits)) {
+            cpu_fprintf(f, "%s=%08x%c", uregnames[i].name, env->uregs[i],
                     (j++ % 4) == 3 ? '\n' : ' ');
         }
     }
@@ -3018,7 +3040,7 @@ void cpu_dump_state(CPUXtensaState *env, FILE *f, fprintf_function cpu_fprintf,
     cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
 
     for (i = 0; i < 16; ++i) {
-        cpu_fprintf(f, "A%02d=%08x%c", i, env->regs[i],
+        cpu_fprintf(f, " A%02d=%08x%c", i, env->regs[i],
                 (i % 4) == 3 ? '\n' : ' ');
     }
 

From 53593e90d13264dc88b3281ddf75ceaa641df05a Mon Sep 17 00:00:00 2001
From: Max Filippov 
Date: Wed, 5 Dec 2012 07:15:23 +0400
Subject: [PATCH 1874/2270] target-xtensa: better control rsr/wsr/xsr access to
 SRs

There are read-only (DEBUGCAUSE, PRID) and write-only (INTCLEAR) SRs,
and INTERRUPT/INTSET SR allows rsr/wsr, but not xsr. Raise illeagal
opcode exception on illegal access to these SRs.

Signed-off-by: Max Filippov 
Signed-off-by: Blue Swirl 
---
 target-xtensa/translate.c | 49 ++++++++++++++++++++++++---------------
 1 file changed, 30 insertions(+), 19 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 74b7b0f1aa..3303e5f693 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -81,16 +81,27 @@ static TCGv_i32 cpu_UR[256];
 typedef struct XtensaReg {
     const char *name;
     uint64_t opt_bits;
+    enum {
+        SR_R = 1,
+        SR_W = 2,
+        SR_X = 4,
+        SR_RW = 3,
+        SR_RWX = 7,
+    } access;
 } XtensaReg;
 
-#define XTENSA_REG(regname, opt) { \
+#define XTENSA_REG_ACCESS(regname, opt, acc) { \
         .name = (regname), \
         .opt_bits = XTENSA_OPTION_BIT(opt), \
+        .access = (acc), \
     }
 
+#define XTENSA_REG(regname, opt) XTENSA_REG_ACCESS(regname, opt, SR_RWX)
+
 #define XTENSA_REG_BITS(regname, opt) { \
         .name = (regname), \
         .opt_bits = (opt), \
+        .access = SR_RWX, \
     }
 
 static const XtensaReg sregnames[256] = {
@@ -151,15 +162,15 @@ static const XtensaReg sregnames[256] = {
     [EXCSAVE1 + 6] = XTENSA_REG("EXCSAVE7",
             XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
     [CPENABLE] = XTENSA_REG("CPENABLE", XTENSA_OPTION_COPROCESSOR),
-    [INTSET] = XTENSA_REG("INTSET", XTENSA_OPTION_INTERRUPT),
-    [INTCLEAR] = XTENSA_REG("INTCLEAR", XTENSA_OPTION_INTERRUPT),
+    [INTSET] = XTENSA_REG_ACCESS("INTSET", XTENSA_OPTION_INTERRUPT, SR_RW),
+    [INTCLEAR] = XTENSA_REG_ACCESS("INTCLEAR", XTENSA_OPTION_INTERRUPT, SR_W),
     [INTENABLE] = XTENSA_REG("INTENABLE", XTENSA_OPTION_INTERRUPT),
     [PS] = XTENSA_REG_BITS("PS", XTENSA_OPTION_ALL),
     [VECBASE] = XTENSA_REG("VECBASE", XTENSA_OPTION_RELOCATABLE_VECTOR),
     [EXCCAUSE] = XTENSA_REG("EXCCAUSE", XTENSA_OPTION_EXCEPTION),
-    [DEBUGCAUSE] = XTENSA_REG("DEBUGCAUSE", XTENSA_OPTION_DEBUG),
+    [DEBUGCAUSE] = XTENSA_REG_ACCESS("DEBUGCAUSE", XTENSA_OPTION_DEBUG, SR_R),
     [CCOUNT] = XTENSA_REG("CCOUNT", XTENSA_OPTION_TIMER_INTERRUPT),
-    [PRID] = XTENSA_REG("PRID", XTENSA_OPTION_PROCESSOR_ID),
+    [PRID] = XTENSA_REG_ACCESS("PRID", XTENSA_OPTION_PROCESSOR_ID, SR_R),
     [ICOUNT] = XTENSA_REG("ICOUNT", XTENSA_OPTION_DEBUG),
     [ICOUNTLEVEL] = XTENSA_REG("ICOUNTLEVEL", XTENSA_OPTION_DEBUG),
     [EXCVADDR] = XTENSA_REG("EXCVADDR", XTENSA_OPTION_EXCEPTION),
@@ -476,7 +487,7 @@ static void gen_brcondi(DisasContext *dc, TCGCond cond,
     tcg_temp_free(tmp);
 }
 
-static void gen_check_sr(DisasContext *dc, uint32_t sr)
+static void gen_check_sr(DisasContext *dc, uint32_t sr, unsigned access)
 {
     if (!xtensa_option_bits_enabled(dc->config, sregnames[sr].opt_bits)) {
         if (sregnames[sr].name) {
@@ -485,6 +496,16 @@ static void gen_check_sr(DisasContext *dc, uint32_t sr)
             qemu_log("SR %d is not implemented\n", sr);
         }
         gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
+    } else if (!(sregnames[sr].access & access)) {
+        static const char * const access_text[] = {
+            [SR_R] = "rsr",
+            [SR_W] = "wsr",
+            [SR_X] = "xsr",
+        };
+        assert(access < ARRAY_SIZE(access_text) && access_text[access]);
+        qemu_log("SR %s is not available for %s\n", sregnames[sr].name,
+                access_text[access]);
+        gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
     }
 }
 
@@ -679,14 +700,6 @@ static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
     gen_jumpi_check_loop_end(dc, -1);
 }
 
-static void gen_wsr_debugcause(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-}
-
-static void gen_wsr_prid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-}
-
 static void gen_wsr_icount(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     if (dc->icount) {
@@ -744,8 +757,6 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [INTCLEAR] = gen_wsr_intclear,
         [INTENABLE] = gen_wsr_intenable,
         [PS] = gen_wsr_ps,
-        [DEBUGCAUSE] = gen_wsr_debugcause,
-        [PRID] = gen_wsr_prid,
         [ICOUNT] = gen_wsr_icount,
         [ICOUNTLEVEL] = gen_wsr_icountlevel,
         [CCOMPARE] = gen_wsr_ccompare,
@@ -1467,7 +1478,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             case 6: /*XSR*/
                 {
                     TCGv_i32 tmp = tcg_temp_new_i32();
-                    gen_check_sr(dc, RSR_SR);
+                    gen_check_sr(dc, RSR_SR, SR_X);
                     if (RSR_SR >= 64) {
                         gen_check_privilege(dc);
                     }
@@ -1698,7 +1709,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
         case 3: /*RST3*/
             switch (OP2) {
             case 0: /*RSR*/
-                gen_check_sr(dc, RSR_SR);
+                gen_check_sr(dc, RSR_SR, SR_R);
                 if (RSR_SR >= 64) {
                     gen_check_privilege(dc);
                 }
@@ -1707,7 +1718,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 break;
 
             case 1: /*WSR*/
-                gen_check_sr(dc, RSR_SR);
+                gen_check_sr(dc, RSR_SR, SR_W);
                 if (RSR_SR >= 64) {
                     gen_check_privilege(dc);
                 }

From b7909d81f7658f64bba0faed83e7c2fd6a52fcba Mon Sep 17 00:00:00 2001
From: Max Filippov 
Date: Wed, 5 Dec 2012 07:15:24 +0400
Subject: [PATCH 1875/2270] target-xtensa: implement MISC SR

The Miscellaneous Special Registers Option provides zero to four scratch
registers within the processor readable and writable by RSR, WSR, and
XSR. These registers are privileged. They may be useful for some
application-specific exception and interrupt processing tasks in the
kernel. The MISC registers are undefined after reset.
See ISA, 4.7.3 for details.

Signed-off-by: Max Filippov 
Signed-off-by: Blue Swirl 
---
 target-xtensa/cpu.h          | 1 +
 target-xtensa/overlay_tool.h | 1 +
 target-xtensa/translate.c    | 4 ++++
 3 files changed, 6 insertions(+)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index a73d32d898..08fd5bc395 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -153,6 +153,7 @@ enum {
     ICOUNTLEVEL = 237,
     EXCVADDR = 238,
     CCOMPARE = 240,
+    MISC = 244,
 };
 
 #define PS_INTLEVEL 0xf
diff --git a/target-xtensa/overlay_tool.h b/target-xtensa/overlay_tool.h
index 0b47029f8c..dd4f51a7b7 100644
--- a/target-xtensa/overlay_tool.h
+++ b/target-xtensa/overlay_tool.h
@@ -95,6 +95,7 @@
     /* Other, TODO */ \
     XCHAL_OPTION(XCHAL_HAVE_WINDOWED, XTENSA_OPTION_WINDOWED_REGISTER) | \
     XCHAL_OPTION(XCHAL_HAVE_DEBUG, XTENSA_OPTION_DEBUG) |\
+    XCHAL_OPTION(XCHAL_NUM_MISC_REGS > 0, XTENSA_OPTION_MISC_SR) | \
     XCHAL_OPTION(XCHAL_HAVE_THREADPTR, XTENSA_OPTION_THREAD_POINTER) | \
     XCHAL_OPTION(XCHAL_HAVE_PRID, XTENSA_OPTION_PROCESSOR_ID))
 
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 3303e5f693..52edcefb05 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -179,6 +179,10 @@ static const XtensaReg sregnames[256] = {
             XTENSA_OPTION_TIMER_INTERRUPT),
     [CCOMPARE + 2] = XTENSA_REG("CCOMPARE2",
             XTENSA_OPTION_TIMER_INTERRUPT),
+    [MISC] = XTENSA_REG("MISC0", XTENSA_OPTION_MISC_SR),
+    [MISC + 1] = XTENSA_REG("MISC1", XTENSA_OPTION_MISC_SR),
+    [MISC + 2] = XTENSA_REG("MISC2", XTENSA_OPTION_MISC_SR),
+    [MISC + 3] = XTENSA_REG("MISC3", XTENSA_OPTION_MISC_SR),
 };
 
 static const XtensaReg uregnames[256] = {

From efdfac94f48f8589a0d60b650c7bed989a341eaa Mon Sep 17 00:00:00 2001
From: Max Filippov 
Date: Wed, 5 Dec 2012 07:15:25 +0400
Subject: [PATCH 1876/2270] target-xtensa: add SR accessibility unit tests

Signed-off-by: Max Filippov 
Signed-off-by: Blue Swirl 
---
 tests/tcg/xtensa/Makefile   |  1 +
 tests/tcg/xtensa/macros.inc |  2 +-
 tests/tcg/xtensa/test_sr.S  | 90 +++++++++++++++++++++++++++++++++++++
 3 files changed, 92 insertions(+), 1 deletion(-)
 create mode 100644 tests/tcg/xtensa/test_sr.S

diff --git a/tests/tcg/xtensa/Makefile b/tests/tcg/xtensa/Makefile
index 0ff0ccfb8c..56cfe0f7b8 100644
--- a/tests/tcg/xtensa/Makefile
+++ b/tests/tcg/xtensa/Makefile
@@ -45,6 +45,7 @@ TESTCASES += test_rst0.tst
 TESTCASES += test_sar.tst
 TESTCASES += test_sext.tst
 TESTCASES += test_shift.tst
+TESTCASES += test_sr.tst
 TESTCASES += test_timer.tst
 TESTCASES += test_windowed.tst
 
diff --git a/tests/tcg/xtensa/macros.inc b/tests/tcg/xtensa/macros.inc
index 23bf3e96c8..c9be1ce516 100644
--- a/tests/tcg/xtensa/macros.inc
+++ b/tests/tcg/xtensa/macros.inc
@@ -1,7 +1,7 @@
 .macro test_suite name
 .data
 status: .word result
-result: .space 20
+result: .space 256
 .text
 .global main
 .align 4
diff --git a/tests/tcg/xtensa/test_sr.S b/tests/tcg/xtensa/test_sr.S
new file mode 100644
index 0000000000..470c03dae2
--- /dev/null
+++ b/tests/tcg/xtensa/test_sr.S
@@ -0,0 +1,90 @@
+.include "macros.inc"
+
+test_suite sr
+
+.macro  sr_op sym, op_sym, op_byte, sr
+    .if \sym
+    \op_sym a4, \sr
+    .else
+    .byte 0x40, \sr, \op_byte
+    .endif
+.endm
+
+.macro 	test_sr_op sym, mask, op, op_byte, sr
+    movi    a4, 0
+    .if (\mask)
+    set_vector kernel, 0
+    sr_op   \sym, \op, \op_byte, \sr
+    .else
+    set_vector kernel, 2f
+1:
+    sr_op   \sym, \op, \op_byte, \sr
+    test_fail
+2:
+    reset_ps
+    rsr     a2, exccause
+    assert  eqi, a2, 0
+    rsr     a2, epc1
+    movi    a3, 1b
+    assert  eq, a2, a3
+    .endif
+.endm
+
+.macro  test_sr_mask sr, sym, mask
+test \sr
+    test_sr_op \sym, \mask & 1, rsr, 0x03, \sr
+    test_sr_op \sym, \mask & 2, wsr, 0x13, \sr
+    test_sr_op \sym, \mask & 4, xsr, 0x61, \sr
+test_end
+.endm
+
+.macro  test_sr sr, conf
+    test_sr_mask    \sr, \conf, 7
+.endm
+
+test_sr acchi, 1
+test_sr acclo, 1
+test_sr_mask /*atomctl*/99, 0, 0
+test_sr_mask /*br*/4, 0, 0
+test_sr_mask /*cacheattr*/98, 0, 0
+test_sr ccompare0, 1
+test_sr ccount, 1
+test_sr cpenable, 1
+test_sr dbreaka0, 1
+test_sr dbreakc0, 1
+test_sr_mask debugcause, 1, 1
+test_sr depc, 1
+test_sr dtlbcfg, 1
+test_sr epc1, 1
+test_sr epc2, 1
+test_sr eps2, 1
+test_sr exccause, 1
+test_sr excsave1, 1
+test_sr excsave2, 1
+test_sr excvaddr, 1
+test_sr ibreaka0, 1
+test_sr ibreakenable, 1
+test_sr icount, 1
+test_sr icountlevel, 1
+test_sr_mask /*intclear*/227, 0, 2
+test_sr_mask /*interrupt*/226, 0, 3
+test_sr intenable, 1
+test_sr itlbcfg, 1
+test_sr lbeg, 1
+test_sr lcount, 1
+test_sr lend, 1
+test_sr litbase, 1
+test_sr m0, 1
+test_sr misc0, 1
+test_sr_mask /*prefctl*/40, 0, 0
+test_sr_mask /*prid*/235, 0, 1
+test_sr ps, 1
+test_sr ptevaddr, 1
+test_sr rasid, 1
+test_sr sar, 1
+test_sr scompare1, 1
+test_sr vecbase, 1
+test_sr windowbase, 1
+test_sr windowstart, 1
+
+test_suite_end

From 5dacd229ebb46c236cb1dd0c65a4e4f2cfb55dfb Mon Sep 17 00:00:00 2001
From: Max Filippov 
Date: Wed, 5 Dec 2012 07:15:26 +0400
Subject: [PATCH 1877/2270] target-xtensa: add s32c1i unit tests

Signed-off-by: Max Filippov 
Signed-off-by: Blue Swirl 
---
 tests/tcg/xtensa/Makefile      |  1 +
 tests/tcg/xtensa/test_s32c1i.S | 39 ++++++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+)
 create mode 100644 tests/tcg/xtensa/test_s32c1i.S

diff --git a/tests/tcg/xtensa/Makefile b/tests/tcg/xtensa/Makefile
index 56cfe0f7b8..002fd871d9 100644
--- a/tests/tcg/xtensa/Makefile
+++ b/tests/tcg/xtensa/Makefile
@@ -42,6 +42,7 @@ endif
 TESTCASES += test_quo.tst
 TESTCASES += test_rem.tst
 TESTCASES += test_rst0.tst
+TESTCASES += test_s32c1i.tst
 TESTCASES += test_sar.tst
 TESTCASES += test_sext.tst
 TESTCASES += test_shift.tst
diff --git a/tests/tcg/xtensa/test_s32c1i.S b/tests/tcg/xtensa/test_s32c1i.S
new file mode 100644
index 0000000000..4536015a84
--- /dev/null
+++ b/tests/tcg/xtensa/test_s32c1i.S
@@ -0,0 +1,39 @@
+.include "macros.inc"
+
+test_suite s32c1i
+
+test s32c1i_nowrite
+    movi    a2, 1f
+    movi    a3, 1
+    wsr     a3, scompare1
+    movi    a1, 2
+    s32c1i  a1, a2, 0
+    assert  ne, a1, a3
+    l32i    a1, a2, 0
+    assert  eqi, a1, 3
+
+.data
+.align 4
+1:
+    .word   3
+.text
+test_end
+
+test s32c1i_write
+    movi    a2, 1f
+    movi    a3, 3
+    wsr     a3, scompare1
+    movi    a1, 2
+    s32c1i  a1, a2, 0
+    assert  eq, a1, a3
+    l32i    a1, a2, 0
+    assert  eqi, a1, 2
+
+.data
+.align 4
+1:
+    .word   3
+.text
+test_end
+
+test_suite_end

From f877d09e63bd94424dab049da75bc1cd601a7609 Mon Sep 17 00:00:00 2001
From: Max Filippov 
Date: Wed, 5 Dec 2012 07:15:27 +0400
Subject: [PATCH 1878/2270] target-xtensa: use movcond where possible

Use movcond for all sorts of conditional moves, ABS, CLAMPS, MIN/MAX
opcodes.

Signed-off-by: Max Filippov 
Signed-off-by: Blue Swirl 
---
 target-xtensa/translate.c | 92 ++++++++++++++++++---------------------
 1 file changed, 42 insertions(+), 50 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 52edcefb05..5d8762c0ca 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -1403,12 +1403,14 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
                 case 1: /*ABS*/
                     {
-                        int label = gen_new_label();
-                        tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
-                        tcg_gen_brcondi_i32(
-                                TCG_COND_GE, cpu_R[RRR_R], 0, label);
-                        tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
-                        gen_set_label(label);
+                        TCGv_i32 zero = tcg_const_i32(0);
+                        TCGv_i32 neg = tcg_temp_new_i32();
+
+                        tcg_gen_neg_i32(neg, cpu_R[RRR_T]);
+                        tcg_gen_movcond_i32(TCG_COND_GE, cpu_R[RRR_R],
+                                cpu_R[RRR_T], zero, cpu_R[RRR_T], neg);
+                        tcg_temp_free(neg);
+                        tcg_temp_free(zero);
                     }
                     break;
 
@@ -1755,22 +1757,20 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 {
                     TCGv_i32 tmp1 = tcg_temp_new_i32();
                     TCGv_i32 tmp2 = tcg_temp_new_i32();
-                    int label = gen_new_label();
+                    TCGv_i32 zero = tcg_const_i32(0);
 
                     tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 24 - RRR_T);
                     tcg_gen_xor_i32(tmp2, tmp1, cpu_R[RRR_S]);
                     tcg_gen_andi_i32(tmp2, tmp2, 0xffffffff << (RRR_T + 7));
-                    tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
-                    tcg_gen_brcondi_i32(TCG_COND_EQ, tmp2, 0, label);
 
                     tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 31);
-                    tcg_gen_xori_i32(cpu_R[RRR_R], tmp1,
-                            0xffffffff >> (25 - RRR_T));
-
-                    gen_set_label(label);
+                    tcg_gen_xori_i32(tmp1, tmp1, 0xffffffff >> (25 - RRR_T));
 
+                    tcg_gen_movcond_i32(TCG_COND_EQ, cpu_R[RRR_R], tmp2, zero,
+                            cpu_R[RRR_S], tmp1);
                     tcg_temp_free(tmp1);
                     tcg_temp_free(tmp2);
+                    tcg_temp_free(zero);
                 }
                 break;
 
@@ -1787,19 +1787,9 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                         TCG_COND_LEU,
                         TCG_COND_GEU
                     };
-                    int label = gen_new_label();
-
-                    if (RRR_R != RRR_T) {
-                        tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
-                        tcg_gen_brcond_i32(cond[OP2 - 4],
-                                cpu_R[RRR_S], cpu_R[RRR_T], label);
-                        tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
-                    } else {
-                        tcg_gen_brcond_i32(cond[OP2 - 4],
-                                cpu_R[RRR_T], cpu_R[RRR_S], label);
-                        tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
-                    }
-                    gen_set_label(label);
+                    tcg_gen_movcond_i32(cond[OP2 - 4], cpu_R[RRR_R],
+                            cpu_R[RRR_S], cpu_R[RRR_T],
+                            cpu_R[RRR_S], cpu_R[RRR_T]);
                 }
                 break;
 
@@ -1810,15 +1800,16 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 {
                     static const TCGCond cond[] = {
-                        TCG_COND_NE,
                         TCG_COND_EQ,
+                        TCG_COND_NE,
+                        TCG_COND_LT,
                         TCG_COND_GE,
-                        TCG_COND_LT
                     };
-                    int label = gen_new_label();
-                    tcg_gen_brcondi_i32(cond[OP2 - 8], cpu_R[RRR_T], 0, label);
-                    tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
-                    gen_set_label(label);
+                    TCGv_i32 zero = tcg_const_i32(0);
+
+                    tcg_gen_movcond_i32(cond[OP2 - 8], cpu_R[RRR_R],
+                            cpu_R[RRR_T], zero, cpu_R[RRR_S], cpu_R[RRR_R]);
+                    tcg_temp_free(zero);
                 }
                 break;
 
@@ -1827,16 +1818,16 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
                 gen_window_check2(dc, RRR_R, RRR_S);
                 {
-                    int label = gen_new_label();
+                    TCGv_i32 zero = tcg_const_i32(0);
                     TCGv_i32 tmp = tcg_temp_new_i32();
 
                     tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << RRR_T);
-                    tcg_gen_brcondi_i32(
-                            OP2 & 1 ? TCG_COND_EQ : TCG_COND_NE,
-                            tmp, 0, label);
-                    tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
-                    gen_set_label(label);
+                    tcg_gen_movcond_i32(OP2 & 1 ? TCG_COND_NE : TCG_COND_EQ,
+                            cpu_R[RRR_R], tmp, zero,
+                            cpu_R[RRR_S], cpu_R[RRR_R]);
+
                     tcg_temp_free(tmp);
+                    tcg_temp_free(zero);
                 }
                 break;
 
@@ -2127,15 +2118,16 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 gen_check_cpenable(dc, 0);
                 {
                     static const TCGCond cond[] = {
-                        TCG_COND_NE,
                         TCG_COND_EQ,
+                        TCG_COND_NE,
+                        TCG_COND_LT,
                         TCG_COND_GE,
-                        TCG_COND_LT
                     };
-                    int label = gen_new_label();
-                    tcg_gen_brcondi_i32(cond[OP2 - 8], cpu_R[RRR_T], 0, label);
-                    tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_FR[RRR_S]);
-                    gen_set_label(label);
+                    TCGv_i32 zero = tcg_const_i32(0);
+
+                    tcg_gen_movcond_i32(cond[OP2 - 8], cpu_FR[RRR_R],
+                            cpu_R[RRR_T], zero, cpu_FR[RRR_S], cpu_FR[RRR_R]);
+                    tcg_temp_free(zero);
                 }
                 break;
 
@@ -2144,16 +2136,16 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
                 gen_check_cpenable(dc, 0);
                 {
-                    int label = gen_new_label();
+                    TCGv_i32 zero = tcg_const_i32(0);
                     TCGv_i32 tmp = tcg_temp_new_i32();
 
                     tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << RRR_T);
-                    tcg_gen_brcondi_i32(
-                            OP2 & 1 ? TCG_COND_EQ : TCG_COND_NE,
-                            tmp, 0, label);
-                    tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_FR[RRR_S]);
-                    gen_set_label(label);
+                    tcg_gen_movcond_i32(OP2 & 1 ? TCG_COND_NE : TCG_COND_EQ,
+                            cpu_FR[RRR_R], tmp, zero,
+                            cpu_FR[RRR_S], cpu_FR[RRR_R]);
+
                     tcg_temp_free(tmp);
+                    tcg_temp_free(zero);
                 }
                 break;
 

From 24c35a504e8b09e697d0268bbefb2a329b901611 Mon Sep 17 00:00:00 2001
From: Peter Maydell 
Date: Fri, 12 Oct 2012 03:55:51 +0000
Subject: [PATCH 1879/2270] linux-user: Merge pread/pwrite into
 pread64/pwrite64

The Linux syscalls underlying pread() and pwrite() take a 64 bit
offset on all architectures, even if some of them name the syscall
"pread/pwrite" rather than "pread64/pwrite64" for historical reasons.
So move the four QEMU target architectures (arm, i386, sparc,
unicore32) which were defining TARGET_NR_pread/pwrite to define
TARGET_NR_pread64/pwrite64 instead, and drop the TARGET_NR_pread/pwrite
implementation code completely.

(Based on examination of the kernel sources for the four architectures
this patch affects.)

Signed-off-by: Peter Maydell 
Signed-off-by: Blue Swirl 
---
 linux-user/arm/syscall_nr.h       |  4 ++--
 linux-user/i386/syscall_nr.h      |  4 ++--
 linux-user/sparc/syscall_nr.h     |  4 ++--
 linux-user/strace.list            |  6 ------
 linux-user/syscall.c              | 18 ------------------
 linux-user/unicore32/syscall_nr.h |  4 ++--
 6 files changed, 8 insertions(+), 32 deletions(-)

diff --git a/linux-user/arm/syscall_nr.h b/linux-user/arm/syscall_nr.h
index 5356395659..42d68550dc 100644
--- a/linux-user/arm/syscall_nr.h
+++ b/linux-user/arm/syscall_nr.h
@@ -182,8 +182,8 @@
 #define TARGET_NR_rt_sigtimedwait		(177)
 #define TARGET_NR_rt_sigqueueinfo		(178)
 #define TARGET_NR_rt_sigsuspend		(179)
-#define TARGET_NR_pread			(180)
-#define TARGET_NR_pwrite			(181)
+#define TARGET_NR_pread64                       (180)
+#define TARGET_NR_pwrite64                      (181)
 #define TARGET_NR_chown			(182)
 #define TARGET_NR_getcwd			(183)
 #define TARGET_NR_capget			(184)
diff --git a/linux-user/i386/syscall_nr.h b/linux-user/i386/syscall_nr.h
index 74abfcacb4..f0803050d8 100644
--- a/linux-user/i386/syscall_nr.h
+++ b/linux-user/i386/syscall_nr.h
@@ -182,8 +182,8 @@
 #define TARGET_NR_rt_sigtimedwait	177
 #define TARGET_NR_rt_sigqueueinfo	178
 #define TARGET_NR_rt_sigsuspend	179
-#define TARGET_NR_pread		180
-#define TARGET_NR_pwrite		181
+#define TARGET_NR_pread64               180
+#define TARGET_NR_pwrite64              181
 #define TARGET_NR_chown		182
 #define TARGET_NR_getcwd		183
 #define TARGET_NR_capget		184
diff --git a/linux-user/sparc/syscall_nr.h b/linux-user/sparc/syscall_nr.h
index f201f9f788..061711cc03 100644
--- a/linux-user/sparc/syscall_nr.h
+++ b/linux-user/sparc/syscall_nr.h
@@ -62,8 +62,8 @@
 #define TARGET_NR_getpagesize         64 /* Common                                      */
 #define TARGET_NR_msync               65 /* Common in newer 1.3.x revs...               */
 #define TARGET_NR_vfork               66 /* Common                                      */
-#define TARGET_NR_pread               67 /* Linux Specific                              */
-#define TARGET_NR_pwrite              68 /* Linux Specific                              */
+#define TARGET_NR_pread64             67 /* Linux Specific */
+#define TARGET_NR_pwrite64            68 /* Linux Specific */
 #define TARGET_NR_geteuid32           69 /* Linux sparc32, sbrk under SunOS             */
 #define TARGET_NR_getegid32           70 /* Linux sparc32, sstk under SunOS             */
 #define TARGET_NR_mmap                71 /* Common                                      */
diff --git a/linux-user/strace.list b/linux-user/strace.list
index af3c6a0cce..08f115d843 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -972,9 +972,6 @@
 #ifdef TARGET_NR_prctl
 { TARGET_NR_prctl, "prctl" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_pread
-{ TARGET_NR_pread, "pread" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_pread64
 { TARGET_NR_pread64, "pread64" , NULL, NULL, NULL },
 #endif
@@ -993,9 +990,6 @@
 #ifdef TARGET_NR_putpmsg
 { TARGET_NR_putpmsg, "putpmsg" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_pwrite
-{ TARGET_NR_pwrite, "pwrite" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_pwrite64
 { TARGET_NR_pwrite64, "pwrite64" , NULL, NULL, NULL },
 #endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index e4291ed776..31d5276465 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7449,24 +7449,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         goto unimplemented;
 #endif
 #endif
-#ifdef TARGET_NR_pread
-    case TARGET_NR_pread:
-        if (regpairs_aligned(cpu_env))
-            arg4 = arg5;
-        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
-            goto efault;
-        ret = get_errno(pread(arg1, p, arg3, arg4));
-        unlock_user(p, arg2, ret);
-        break;
-    case TARGET_NR_pwrite:
-        if (regpairs_aligned(cpu_env))
-            arg4 = arg5;
-        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
-            goto efault;
-        ret = get_errno(pwrite(arg1, p, arg3, arg4));
-        unlock_user(p, arg2, 0);
-        break;
-#endif
 #ifdef TARGET_NR_pread64
     case TARGET_NR_pread64:
         if (regpairs_aligned(cpu_env)) {
diff --git a/linux-user/unicore32/syscall_nr.h b/linux-user/unicore32/syscall_nr.h
index 9c72d84d80..486b8c45a0 100644
--- a/linux-user/unicore32/syscall_nr.h
+++ b/linux-user/unicore32/syscall_nr.h
@@ -187,8 +187,8 @@
 #define TARGET_NR_rt_sigtimedwait               177
 #define TARGET_NR_rt_sigqueueinfo               178
 #define TARGET_NR_rt_sigsuspend                 179
-#define TARGET_NR_pread                         180
-#define TARGET_NR_pwrite                        181
+#define TARGET_NR_pread64                       180
+#define TARGET_NR_pwrite64                      181
 #define TARGET_NR_chown                         182
 #define TARGET_NR_getcwd                        183
 #define TARGET_NR_capget                        184

From e49d021e574c3ee8e443bcc84d1fb7dfb4c87c42 Mon Sep 17 00:00:00 2001
From: Peter Maydell 
Date: Fri, 7 Dec 2012 15:39:13 +0000
Subject: [PATCH 1880/2270] configure: Default to 'cc', not 'gcc'

Default to 'cc' as our compiler, rather than 'gcc'. We used to have
to insist on gcc when we still kept the CPU env in a fixed global
register, but this is no longer necessary and we will now compile OK
on clang as well as gcc.  Using 'cc' should generally result in us
using the most standard and maintained system compiler for the
platform.  (For instance on newer MacOS X 'gcc' exists but is an
elderly compiler provided mostly for legacy reasons, and 'cc'
(which is clang) is definitely the better choice.) On Linux there
will generally be no user-visible change since cc will be gcc.

This changeover necessitates a slight reworking of how we set the
'cc' variable, because GNU cross toolchains generally provide a
'${cross_prefix}gcc' but not a '${cross_prefix}cc'.

Signed-off-by: Peter Maydell 
Signed-off-by: Blue Swirl 
---
 configure | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 44034d66b9..e5aedef788 100755
--- a/configure
+++ b/configure
@@ -116,7 +116,7 @@ audio_drv_list=""
 audio_card_list="ac97 es1370 sb16 hda"
 audio_possible_cards="ac97 es1370 sb16 cs4231a adlib gus hda"
 block_drv_whitelist=""
-host_cc="gcc"
+host_cc="cc"
 libs_softmmu=""
 libs_tools=""
 audio_pt_int=""
@@ -250,7 +250,16 @@ done
 # Using uname is really, really broken.  Once we have the right set of checks
 # we can eliminate its usage altogether.
 
-cc="${CC-${cross_prefix}gcc}"
+# Preferred compiler:
+#  ${CC} (if set)
+#  ${cross_prefix}gcc (if cross-prefix specified)
+#  system compiler
+if test -z "${CC}${cross_prefix}"; then
+  cc="$host_cc"
+else
+  cc="${CC-${cross_prefix}gcc}"
+fi
+
 ar="${AR-${cross_prefix}ar}"
 objcopy="${OBJCOPY-${cross_prefix}objcopy}"
 ld="${LD-${cross_prefix}ld}"

From d281084d3e51f03999d12a506491a0c6f31b40e8 Mon Sep 17 00:00:00 2001
From: Alex Williamson 
Date: Mon, 10 Dec 2012 11:30:03 -0700
Subject: [PATCH 1881/2270] vfio-pci: Don't use kvm_irqchip_in_kernel

kvm_irqchip_in_kernel() has an architecture specific meaning, so
we shouldn't be using it to determine whether to enabled KVM INTx
bypass.  kvm_irqfds_enabled() seems most appropriate.  Also use this
to protect our other call to kvm_check_extension() as that explodes
when KVM isn't enabled.

Signed-off-by: Alex Williamson 
Cc: qemu-stable@nongnu.org
---
 hw/vfio_pci.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index 7c27834e06..fbfe670078 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -275,7 +275,7 @@ static void vfio_enable_intx_kvm(VFIODevice *vdev)
     int ret, argsz;
     int32_t *pfd;
 
-    if (!kvm_irqchip_in_kernel() ||
+    if (!kvm_irqfds_enabled() ||
         vdev->intx.route.mode != PCI_INTX_ENABLED ||
         !kvm_check_extension(kvm_state, KVM_CAP_IRQFD_RESAMPLE)) {
         return;
@@ -438,7 +438,8 @@ static int vfio_enable_intx(VFIODevice *vdev)
      * Only conditional to avoid generating error messages on platforms
      * where we won't actually use the result anyway.
      */
-    if (kvm_check_extension(kvm_state, KVM_CAP_IRQFD_RESAMPLE)) {
+    if (kvm_irqfds_enabled() &&
+        kvm_check_extension(kvm_state, KVM_CAP_IRQFD_RESAMPLE)) {
         vdev->intx.route = pci_device_route_intx_to_irq(&vdev->pdev,
                                                         vdev->intx.pin);
     }

From ff1562908d1da12362aa9e3f3bfc7ba0da8114a4 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann 
Date: Tue, 11 Dec 2012 08:24:30 +0100
Subject: [PATCH 1882/2270] seabios: update to
 e8a76b0f225bba5ba9d63ab227e0a37b3beb1059

This patch updates seabios to latest git master.  Changes:

  (1) q35 patches merged.
  (2) some acpi cleanups.
  (3) fixes irq 8 conflict.

(3) makes this a candidate for the stable branch

Cc: qemu-stable@nongnu.org
Signed-off-by: Gerd Hoffmann 
---
 pc-bios/acpi-dsdt.aml     | Bin 4540 -> 4438 bytes
 pc-bios/bios.bin          | Bin 131072 -> 262144 bytes
 pc-bios/q35-acpi-dsdt.aml | Bin 0 -> 7458 bytes
 roms/seabios              |   2 +-
 4 files changed, 1 insertion(+), 1 deletion(-)
 create mode 100644 pc-bios/q35-acpi-dsdt.aml

diff --git a/pc-bios/acpi-dsdt.aml b/pc-bios/acpi-dsdt.aml
index bb3dd83a56f84131f9c9f968cbee9385931cecd3..18b4dc1aa53859593604abe598b05784b116a360 100644
GIT binary patch
delta 574
zcmdm^d`*eVCD`0uHizAVnY*n>jg-F>?BHKs32dzQI|{EXc(-IgqP>R~4=*x=C`fJg=xQ1J{26
zH&!HJPnOB&xFiju8`a|U0wN5J0}PFw85lhD8Q6UST>TgsEEt%b9YG9cXD1-V;pPG)
z1$?9@zv8l&Gxv6KiHA9nnOTH0J~+gYVF?#MN4#@T@MM2(N#^J#^~nX?5_Vt_K@Kif
zB?f^?hUg|Q7B?4XxcAr@L?pm^3qa;4EMS|Qz_5g2Aq(87Q`|E3(M@(f0U>bvSm1g<
zF2&R%D8R+*&RD@*!OX#-)W86;)Ro2A-`5c4U{*#*Xu_-p`4g8hKbU{;Ff(u{34qOU
zW0}03N6ZT9WKh81)W`IL38;+&s7=6|10L>^FR`0XuH^ONb)OB2Hv!iYP*iT5?7%+x
y6mL5t!{m#6+LLSfY}tI+ef+$gCOh$2PyWLfJoy5j&g5!-V94_8Z2rZ6h!Fs+D3!_p

delta 695
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
WNQ(5Ag=7s~Vr%*
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

literal 0
HcmV?d00001

diff --git a/roms/seabios b/roms/seabios
index b1c35f2b28..e8a76b0f22 160000
--- a/roms/seabios
+++ b/roms/seabios
@@ -1 +1 @@
-Subproject commit b1c35f2b28cc0c94ebed8176ff61ac0e0b377798
+Subproject commit e8a76b0f225bba5ba9d63ab227e0a37b3beb1059

From 9fe3781f09f94f3ce76e52899bcdeb0d5164dbb1 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi 
Date: Tue, 4 Dec 2012 16:12:18 +0100
Subject: [PATCH 1883/2270] tests: use aio_poll() instead of aio_flush() in
 test-aio.c

There has been confusion between various aio wait and flush functions.
It's time to get rid of qemu_aio_flush() but in the aio test cases we
really do want this low-level functionality.

Therefore declare a local wait_for_aio() helper for the test cases.
Drop the aio_flush() test case.

Signed-off-by: Stefan Hajnoczi 
Acked-by: Paolo Bonzini 
Signed-off-by: Kevin Wolf 
---
 tests/test-aio.c | 31 +++++++++++++++----------------
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/tests/test-aio.c b/tests/test-aio.c
index f53c908707..a8a4f0c6a5 100644
--- a/tests/test-aio.c
+++ b/tests/test-aio.c
@@ -15,6 +15,14 @@
 
 AioContext *ctx;
 
+/* Wait until there are no more BHs or AIO requests */
+static void wait_for_aio(void)
+{
+    while (aio_poll(ctx, true)) {
+        /* Do nothing */
+    }
+}
+
 /* Simple callbacks for testing.  */
 
 typedef struct {
@@ -78,14 +86,6 @@ static void test_notify(void)
     g_assert(!aio_poll(ctx, false));
 }
 
-static void test_flush(void)
-{
-    g_assert(!aio_poll(ctx, false));
-    aio_notify(ctx);
-    aio_flush(ctx);
-    g_assert(!aio_poll(ctx, false));
-}
-
 static void test_bh_schedule(void)
 {
     BHTestData data = { .n = 0 };
@@ -116,7 +116,7 @@ static void test_bh_schedule10(void)
     g_assert(aio_poll(ctx, true));
     g_assert_cmpint(data.n, ==, 2);
 
-    aio_flush(ctx);
+    wait_for_aio();
     g_assert_cmpint(data.n, ==, 10);
 
     g_assert(!aio_poll(ctx, false));
@@ -164,7 +164,7 @@ static void test_bh_delete_from_cb(void)
     qemu_bh_schedule(data1.bh);
     g_assert_cmpint(data1.n, ==, 0);
 
-    aio_flush(ctx);
+    wait_for_aio();
     g_assert_cmpint(data1.n, ==, data1.max);
     g_assert(data1.bh == NULL);
 
@@ -200,7 +200,7 @@ static void test_bh_delete_from_cb_many(void)
     g_assert_cmpint(data4.n, ==, 1);
     g_assert(data1.bh == NULL);
 
-    aio_flush(ctx);
+    wait_for_aio();
     g_assert_cmpint(data1.n, ==, data1.max);
     g_assert_cmpint(data2.n, ==, data2.max);
     g_assert_cmpint(data3.n, ==, data3.max);
@@ -219,7 +219,7 @@ static void test_bh_flush(void)
     qemu_bh_schedule(data.bh);
     g_assert_cmpint(data.n, ==, 0);
 
-    aio_flush(ctx);
+    wait_for_aio();
     g_assert_cmpint(data.n, ==, 1);
 
     g_assert(!aio_poll(ctx, false));
@@ -281,7 +281,7 @@ static void test_flush_event_notifier(void)
     g_assert_cmpint(data.active, ==, 9);
     g_assert(aio_poll(ctx, false));
 
-    aio_flush(ctx);
+    wait_for_aio();
     g_assert_cmpint(data.n, ==, 10);
     g_assert_cmpint(data.active, ==, 0);
     g_assert(!aio_poll(ctx, false));
@@ -325,7 +325,7 @@ static void test_wait_event_notifier_noflush(void)
     g_assert_cmpint(data.n, ==, 2);
 
     event_notifier_set(&dummy.e);
-    aio_flush(ctx);
+    wait_for_aio();
     g_assert_cmpint(data.n, ==, 2);
     g_assert_cmpint(dummy.n, ==, 1);
     g_assert_cmpint(dummy.active, ==, 0);
@@ -346,7 +346,7 @@ static void test_wait_event_notifier_noflush(void)
  * - sometimes both the AioContext and the glib main loop wake
  *   themselves up.  Hence, some "g_assert(!aio_poll(ctx, false));"
  *   are replaced by "while (g_main_context_iteration(NULL, false));".
- * - there is no exact replacement for aio_flush's blocking wait.
+ * - there is no exact replacement for a blocking wait.
  *   "while (g_main_context_iteration(NULL, true)" seems to work,
  *   but it is not documented _why_ it works.  For these tests a
  *   non-blocking loop like "while (g_main_context_iteration(NULL, false)"
@@ -637,7 +637,6 @@ int main(int argc, char **argv)
 
     g_test_init(&argc, &argv, NULL);
     g_test_add_func("/aio/notify",                  test_notify);
-    g_test_add_func("/aio/flush",                   test_flush);
     g_test_add_func("/aio/bh/schedule",             test_bh_schedule);
     g_test_add_func("/aio/bh/schedule10",           test_bh_schedule10);
     g_test_add_func("/aio/bh/cancel",               test_bh_cancel);

From 8a805c222caa0e20bf11d2267f726d0bb5917d94 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi 
Date: Tue, 4 Dec 2012 16:12:19 +0100
Subject: [PATCH 1884/2270] tests: avoid qemu_aio_flush() in test-thread-pool.c

We need to eliminate calls to qemu_aio_flush() since the function is
being removed.  Most callers will use bdrv_drain_all() instead but
test-thread-pool.c is lower level.

Since the test uses the global AioContext we can loop on qemu_aio_wait()
to wait for aio and bh activity to complete.

Signed-off-by: Stefan Hajnoczi 
Acked-by: Paolo Bonzini 
Signed-off-by: Kevin Wolf 
---
 tests/test-thread-pool.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c
index fea0445fb4..ea8e676b0c 100644
--- a/tests/test-thread-pool.c
+++ b/tests/test-thread-pool.c
@@ -47,11 +47,19 @@ static void qemu_aio_wait_nonblocking(void)
     qemu_aio_wait();
 }
 
+/* Wait until all aio and bh activity has finished */
+static void qemu_aio_wait_all(void)
+{
+    while (qemu_aio_wait()) {
+        /* Do nothing */
+    }
+}
+
 static void test_submit(void)
 {
     WorkerTestData data = { .n = 0 };
     thread_pool_submit(worker_cb, &data);
-    qemu_aio_flush();
+    qemu_aio_wait_all();
     g_assert_cmpint(data.n, ==, 1);
 }
 
@@ -63,7 +71,7 @@ static void test_submit_aio(void)
     /* The callbacks are not called until after the first wait.  */
     active = 1;
     g_assert_cmpint(data.ret, ==, -EINPROGRESS);
-    qemu_aio_flush();
+    qemu_aio_wait_all();
     g_assert_cmpint(active, ==, 0);
     g_assert_cmpint(data.n, ==, 1);
     g_assert_cmpint(data.ret, ==, 0);
@@ -84,7 +92,7 @@ static void co_test_cb(void *opaque)
     data->ret = 0;
     active--;
 
-    /* The test continues in test_submit_co, after qemu_aio_flush... */
+    /* The test continues in test_submit_co, after qemu_aio_wait_all... */
 }
 
 static void test_submit_co(void)
@@ -99,9 +107,9 @@ static void test_submit_co(void)
     g_assert_cmpint(active, ==, 1);
     g_assert_cmpint(data.ret, ==, -EINPROGRESS);
 
-    /* qemu_aio_flush will execute the rest of the coroutine.  */
+    /* qemu_aio_wait_all will execute the rest of the coroutine.  */
 
-    qemu_aio_flush();
+    qemu_aio_wait_all();
 
     /* Back here after the coroutine has finished.  */
 
@@ -184,7 +192,7 @@ static void test_cancel(void)
     }
 
     /* Finish execution and execute any remaining callbacks.  */
-    qemu_aio_flush();
+    qemu_aio_wait_all();
     g_assert_cmpint(active, ==, 0);
     for (i = 0; i < 100; i++) {
         if (data[i].n == 3) {

From d318aea9325c99b15c87a7c14865386c2fde0d2c Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Tue, 13 Nov 2012 16:35:08 +0100
Subject: [PATCH 1885/2270] block: Improve bdrv_aio_co_cancel_em

Instead of waiting for all requests to complete, wait just for the
specific request that should be cancelled.

Signed-off-by: Kevin Wolf 
---
 block.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/block.c b/block.c
index c05875fe39..c7a1a3c85c 100644
--- a/block.c
+++ b/block.c
@@ -3778,12 +3778,20 @@ typedef struct BlockDriverAIOCBCoroutine {
     BlockDriverAIOCB common;
     BlockRequest req;
     bool is_write;
+    bool *done;
     QEMUBH* bh;
 } BlockDriverAIOCBCoroutine;
 
 static void bdrv_aio_co_cancel_em(BlockDriverAIOCB *blockacb)
 {
-    qemu_aio_flush();
+    BlockDriverAIOCBCoroutine *acb =
+        container_of(blockacb, BlockDriverAIOCBCoroutine, common);
+    bool done = false;
+
+    acb->done = &done;
+    while (!done) {
+        qemu_aio_wait();
+    }
 }
 
 static const AIOCBInfo bdrv_em_co_aiocb_info = {
@@ -3796,6 +3804,11 @@ static void bdrv_co_em_bh(void *opaque)
     BlockDriverAIOCBCoroutine *acb = opaque;
 
     acb->common.cb(acb->common.opaque, acb->req.error);
+
+    if (acb->done) {
+        *acb->done = true;
+    }
+
     qemu_bh_delete(acb->bh);
     qemu_aio_release(acb);
 }
@@ -3834,6 +3847,7 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
     acb->req.nb_sectors = nb_sectors;
     acb->req.qiov = qiov;
     acb->is_write = is_write;
+    acb->done = NULL;
 
     co = qemu_coroutine_create(bdrv_co_do_rw);
     qemu_coroutine_enter(co, acb);
@@ -3860,6 +3874,8 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
     BlockDriverAIOCBCoroutine *acb;
 
     acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque);
+    acb->done = NULL;
+
     co = qemu_coroutine_create(bdrv_aio_flush_co_entry);
     qemu_coroutine_enter(co, acb);
 
@@ -3888,6 +3904,7 @@ BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs,
     acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque);
     acb->req.sector = sector_num;
     acb->req.nb_sectors = nb_sectors;
+    acb->done = NULL;
     co = qemu_coroutine_create(bdrv_aio_discard_co_entry);
     qemu_coroutine_enter(co, acb);
 

From c57b6656c3168bccca7f78b3f740e9149893b3da Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Tue, 13 Nov 2012 16:35:13 +0100
Subject: [PATCH 1886/2270] aio: Get rid of qemu_aio_flush()

There are no remaining users, and new users should probably be
using bdrv_drain_all() in the first place.

Signed-off-by: Kevin Wolf 
---
 async.c        | 5 -----
 block/commit.c | 2 +-
 block/mirror.c | 2 +-
 block/stream.c | 2 +-
 main-loop.c    | 5 -----
 qemu-aio.h     | 9 ++-------
 6 files changed, 5 insertions(+), 20 deletions(-)

diff --git a/async.c b/async.c
index 3f0e8f367c..41ae0c1195 100644
--- a/async.c
+++ b/async.c
@@ -215,8 +215,3 @@ void aio_context_unref(AioContext *ctx)
 {
     g_source_unref(&ctx->source);
 }
-
-void aio_flush(AioContext *ctx)
-{
-    while (aio_poll(ctx, true));
-}
diff --git a/block/commit.c b/block/commit.c
index fae79582d4..e2bb1e241b 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -103,7 +103,7 @@ static void coroutine_fn commit_run(void *opaque)
 
 wait:
         /* Note that even when no rate limit is applied we need to yield
-         * with no pending I/O here so that qemu_aio_flush() returns.
+         * with no pending I/O here so that bdrv_drain_all() returns.
          */
         block_job_sleep_ns(&s->common, rt_clock, delay_ns);
         if (block_job_is_cancelled(&s->common)) {
diff --git a/block/mirror.c b/block/mirror.c
index d6618a4b34..b1f5d4fa22 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -205,7 +205,7 @@ static void coroutine_fn mirror_run(void *opaque)
             }
 
             /* Note that even when no rate limit is applied we need to yield
-             * with no pending I/O here so that qemu_aio_flush() returns.
+             * with no pending I/O here so that bdrv_drain_all() returns.
              */
             block_job_sleep_ns(&s->common, rt_clock, delay_ns);
             if (block_job_is_cancelled(&s->common)) {
diff --git a/block/stream.c b/block/stream.c
index 0c0fc7a13b..0dcd286035 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -108,7 +108,7 @@ static void coroutine_fn stream_run(void *opaque)
 
 wait:
         /* Note that even when no rate limit is applied we need to yield
-         * with no pending I/O here so that qemu_aio_flush() returns.
+         * with no pending I/O here so that bdrv_drain_all() returns.
          */
         block_job_sleep_ns(&s->common, rt_clock, delay_ns);
         if (block_job_is_cancelled(&s->common)) {
diff --git a/main-loop.c b/main-loop.c
index c87624e621..7dba6f6e35 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -432,11 +432,6 @@ QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
     return aio_bh_new(qemu_aio_context, cb, opaque);
 }
 
-void qemu_aio_flush(void)
-{
-    aio_flush(qemu_aio_context);
-}
-
 bool qemu_aio_wait(void)
 {
     return aio_poll(qemu_aio_context, true);
diff --git a/qemu-aio.h b/qemu-aio.h
index 3889fe97a4..31884a8f16 100644
--- a/qemu-aio.h
+++ b/qemu-aio.h
@@ -162,10 +162,6 @@ void qemu_bh_cancel(QEMUBH *bh);
  */
 void qemu_bh_delete(QEMUBH *bh);
 
-/* Flush any pending AIO operation. This function will block until all
- * outstanding AIO operations have been completed or cancelled. */
-void aio_flush(AioContext *ctx);
-
 /* Return whether there are any pending callbacks from the GSource
  * attached to the AioContext.
  *
@@ -196,7 +192,7 @@ typedef int (AioFlushHandler)(void *opaque);
 
 /* Register a file descriptor and associated callbacks.  Behaves very similarly
  * to qemu_set_fd_handler2.  Unlike qemu_set_fd_handler2, these callbacks will
- * be invoked when using either qemu_aio_wait() or qemu_aio_flush().
+ * be invoked when using qemu_aio_wait().
  *
  * Code that invokes AIO completion functions should rely on this function
  * instead of qemu_set_fd_handler[2].
@@ -211,7 +207,7 @@ void aio_set_fd_handler(AioContext *ctx,
 
 /* Register an event notifier and associated callbacks.  Behaves very similarly
  * to event_notifier_set_handler.  Unlike event_notifier_set_handler, these callbacks
- * will be invoked when using either qemu_aio_wait() or qemu_aio_flush().
+ * will be invoked when using qemu_aio_wait().
  *
  * Code that invokes AIO completion functions should rely on this function
  * instead of event_notifier_set_handler.
@@ -228,7 +224,6 @@ GSource *aio_get_g_source(AioContext *ctx);
 
 /* Functions to operate on the main QEMU AioContext.  */
 
-void qemu_aio_flush(void);
 bool qemu_aio_wait(void);
 void qemu_aio_set_event_notifier(EventNotifier *notifier,
                                  EventNotifierHandler *io_read,

From 7b272452398135e4f8e48341239705d03c82dae3 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Mon, 12 Nov 2012 17:05:39 +0100
Subject: [PATCH 1887/2270] block: Factor out bdrv_open_flags

Signed-off-by: Kevin Wolf 
---
 block.c | 35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/block.c b/block.c
index c7a1a3c85c..c4f5566b5d 100644
--- a/block.c
+++ b/block.c
@@ -634,6 +634,26 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs)
     bs->copy_on_read--;
 }
 
+static int bdrv_open_flags(BlockDriverState *bs, int flags)
+{
+    int open_flags = flags | BDRV_O_CACHE_WB;
+
+    /*
+     * Clear flags that are internal to the block layer before opening the
+     * image.
+     */
+    open_flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
+
+    /*
+     * Snapshots should be writable.
+     */
+    if (bs->is_temporary) {
+        open_flags |= BDRV_O_RDWR;
+    }
+
+    return open_flags;
+}
+
 /*
  * Common part for opening disk images and files
  */
@@ -665,20 +685,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
     bs->opaque = g_malloc0(drv->instance_size);
 
     bs->enable_write_cache = !!(flags & BDRV_O_CACHE_WB);
-    open_flags = flags | BDRV_O_CACHE_WB;
-
-    /*
-     * Clear flags that are internal to the block layer before opening the
-     * image.
-     */
-    open_flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
-
-    /*
-     * Snapshots should be writable.
-     */
-    if (bs->is_temporary) {
-        open_flags |= BDRV_O_RDWR;
-    }
+    open_flags = bdrv_open_flags(bs, flags);
 
     bs->read_only = !(open_flags & BDRV_O_RDWR);
 

From f500a6d3c2b9ef0bb06d0080d91d8ed3c1d68f58 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Mon, 12 Nov 2012 17:35:27 +0100
Subject: [PATCH 1888/2270] block: Avoid second open for format probing

This fixes problems that are caused by the additional open/close cycle
of the existing format probing, for example related to qemu-nbd without
-t option or file descriptor passing.

Signed-off-by: Kevin Wolf 
---
 block.c | 74 ++++++++++++++++++++++++++++++++-------------------------
 1 file changed, 42 insertions(+), 32 deletions(-)

diff --git a/block.c b/block.c
index c4f5566b5d..2ec3afebfe 100644
--- a/block.c
+++ b/block.c
@@ -518,22 +518,16 @@ BlockDriver *bdrv_find_protocol(const char *filename)
     return NULL;
 }
 
-static int find_image_format(const char *filename, BlockDriver **pdrv)
+static int find_image_format(BlockDriverState *bs, const char *filename,
+                             BlockDriver **pdrv)
 {
-    int ret, score, score_max;
+    int score, score_max;
     BlockDriver *drv1, *drv;
     uint8_t buf[2048];
-    BlockDriverState *bs;
-
-    ret = bdrv_file_open(&bs, filename, 0);
-    if (ret < 0) {
-        *pdrv = NULL;
-        return ret;
-    }
+    int ret = 0;
 
     /* Return the raw BlockDriver * to scsi-generic devices or empty drives */
     if (bs->sg || !bdrv_is_inserted(bs)) {
-        bdrv_delete(bs);
         drv = bdrv_find_format("raw");
         if (!drv) {
             ret = -ENOENT;
@@ -543,7 +537,6 @@ static int find_image_format(const char *filename, BlockDriver **pdrv)
     }
 
     ret = bdrv_pread(bs, 0, buf, sizeof(buf));
-    bdrv_delete(bs);
     if (ret < 0) {
         *pdrv = NULL;
         return ret;
@@ -657,7 +650,8 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags)
 /*
  * Common part for opening disk images and files
  */
-static int bdrv_open_common(BlockDriverState *bs, const char *filename,
+static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
+    const char *filename,
     int flags, BlockDriver *drv)
 {
     int ret, open_flags;
@@ -691,12 +685,16 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
 
     /* Open the image, either directly or using a protocol */
     if (drv->bdrv_file_open) {
-        ret = drv->bdrv_file_open(bs, filename, open_flags);
-    } else {
-        ret = bdrv_file_open(&bs->file, filename, open_flags);
-        if (ret >= 0) {
-            ret = drv->bdrv_open(bs, open_flags);
+        if (file != NULL) {
+            bdrv_swap(file, bs);
+            ret = 0;
+        } else {
+            ret = drv->bdrv_file_open(bs, filename, open_flags);
         }
+    } else {
+        assert(file != NULL);
+        bs->file = file;
+        ret = drv->bdrv_open(bs, open_flags);
     }
 
     if (ret < 0) {
@@ -716,10 +714,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
     return 0;
 
 free_and_fail:
-    if (bs->file) {
-        bdrv_delete(bs->file);
-        bs->file = NULL;
-    }
+    bs->file = NULL;
     g_free(bs->opaque);
     bs->opaque = NULL;
     bs->drv = NULL;
@@ -741,7 +736,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
     }
 
     bs = bdrv_new("");
-    ret = bdrv_open_common(bs, filename, flags, drv);
+    ret = bdrv_open_common(bs, NULL, filename, flags, drv);
     if (ret < 0) {
         bdrv_delete(bs);
         return ret;
@@ -796,6 +791,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
     int ret;
     /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
     char tmp_filename[PATH_MAX + 1];
+    BlockDriverState *file = NULL;
 
     if (flags & BDRV_O_SNAPSHOT) {
         BlockDriverState *bs1;
@@ -855,25 +851,36 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
         bs->is_temporary = 1;
     }
 
-    /* Find the right image format driver */
-    if (!drv) {
-        ret = find_image_format(filename, &drv);
-    }
-
-    if (!drv) {
-        goto unlink_and_fail;
-    }
-
+    /* Open image file without format layer */
     if (flags & BDRV_O_RDWR) {
         flags |= BDRV_O_ALLOW_RDWR;
     }
 
+    ret = bdrv_file_open(&file, filename, bdrv_open_flags(bs, flags));
+    if (ret < 0) {
+        return ret;
+    }
+
+    /* Find the right image format driver */
+    if (!drv) {
+        ret = find_image_format(file, filename, &drv);
+    }
+
+    if (!drv) {
+        goto unlink_and_fail;
+    }
+
     /* Open the image */
-    ret = bdrv_open_common(bs, filename, flags, drv);
+    ret = bdrv_open_common(bs, file, filename, flags, drv);
     if (ret < 0) {
         goto unlink_and_fail;
     }
 
+    if (bs->file != file) {
+        bdrv_delete(file);
+        file = NULL;
+    }
+
     /* If there is a backing file, use it */
     if ((flags & BDRV_O_NO_BACKING) == 0) {
         ret = bdrv_open_backing_file(bs);
@@ -895,6 +902,9 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
     return 0;
 
 unlink_and_fail:
+    if (file != NULL) {
+        bdrv_delete(file);
+    }
     if (bs->is_temporary) {
         unlink(filename);
     }

From d567e62f98d5789ff4d273b924a0474931c71e8b Mon Sep 17 00:00:00 2001
From: David Gibson 
Date: Thu, 15 Nov 2012 13:12:14 +1100
Subject: [PATCH 1889/2270] virtio-blk: Remove duplicate property definition

For the virtio-blk device (via virtio-pci) the property "config-wce" is
defined in two places.  First, it's defined from the
DEFINE_VIRTIO_BLK_FEATURES macro, second it's defined directly in
virtio-pci, just two lines above the call to that macro.

The direct definition in virtio-pci.c is broken, since it operates on the
'config_wce' field of VirtIOBlkConf, which is never used anywhere else.
Therefore, this patch removes both the extra property definition and the
redundant field it works on.

Cc: Kevin Wolf 
Cc: Anthony Liguori 
Cc: Paul 'Rusty' Russell 

Signed-off-by: David Gibson 
Signed-off-by: Stefan Hajnoczi 
---
 hw/virtio-blk.h | 1 -
 hw/virtio-pci.c | 1 -
 2 files changed, 2 deletions(-)

diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h
index f0740d01af..651a000b9f 100644
--- a/hw/virtio-blk.h
+++ b/hw/virtio-blk.h
@@ -104,7 +104,6 @@ struct VirtIOBlkConf
     BlockConf conf;
     char *serial;
     uint32_t scsi;
-    uint32_t config_wce;
 };
 
 #define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 71f4fb5dc6..7684ac9a70 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -895,7 +895,6 @@ static Property virtio_blk_properties[] = {
 #ifdef __linux__
     DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true),
 #endif
-    DEFINE_PROP_BIT("config-wce", VirtIOPCIProxy, blk.config_wce, 0, true),
     DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
     DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
     DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),

From 1fe1fa510aa3d4eb1fb4246d4951ef48e4c949c2 Mon Sep 17 00:00:00 2001
From: Charles Arnold 
Date: Fri, 2 Nov 2012 09:54:24 -0600
Subject: [PATCH 1890/2270] block: vpc initialize the uuid footer field

Initialize the uuid field in the footer with a generated uuid.

Signed-off-by: Charles Arnold 
Reviewed-by: Paolo Bonzini 
Signed-off-by: Stefan Hajnoczi 
---
 block/vpc.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/block/vpc.c b/block/vpc.c
index b6bf52f140..f14c6ae196 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -26,6 +26,9 @@
 #include "block_int.h"
 #include "module.h"
 #include "migration.h"
+#if defined(CONFIG_UUID)
+#include 
+#endif
 
 /**************************************************************/
 
@@ -739,7 +742,9 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
 
     footer->type = be32_to_cpu(disk_type);
 
-    /* TODO uuid is missing */
+#if defined(CONFIG_UUID)
+    uuid_generate(footer->uuid);
+#endif
 
     footer->checksum = be32_to_cpu(vpc_checksum(buf, HEADER_SIZE));
 

From 258d2edbcd4bb5d267c96163333820332e1c14fa Mon Sep 17 00:00:00 2001
From: Charles Arnold 
Date: Tue, 30 Oct 2012 20:59:32 -0600
Subject: [PATCH 1891/2270] block: vpc support for ~2 TB disks

The VHD specification allows for up to a 2 TB disk size. The current
implementation in qemu emulates EIDE and ATA-2 hardware which only allows
for up to 127 GB.  This disk size limitation can be overridden by allowing
up to 255 heads instead of the normal 4 bit limitation of 16.  Doing so
allows disk images to be created of up to nearly 2 TB.  This change does
not violate the VHD format specification nor does it change how smaller
disks (ie, <=127GB) are defined.

[Charles Arnold also writes: "In analyzing a 160 GB VHD fixed disk image
created on Windows 2008 R2, it appears that MS is also ignoring the CHS
values in the footer geometry field in whatever driver they use for
accessing the image.  The CHS values are set at 65535,16,255 which
obviously doesn't represent an image size of 160 GB." -- Stefan]

Signed-off-by: Charles Arnold 
Reviewed-by: Paolo Bonzini 
Signed-off-by: Stefan Hajnoczi 
---
 block/vpc.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/block/vpc.c b/block/vpc.c
index f14c6ae196..566e9a3b37 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -201,7 +201,8 @@ static int vpc_open(BlockDriverState *bs, int flags)
     bs->total_sectors = (int64_t)
         be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl;
 
-    if (bs->total_sectors >= 65535 * 16 * 255) {
+    /* Allow a maximum disk size of approximately 2 TB */
+    if (bs->total_sectors >= 65535LL * 255 * 255) {
         err = -EFBIG;
         goto fail;
     }
@@ -527,19 +528,27 @@ static coroutine_fn int vpc_co_write(BlockDriverState *bs, int64_t sector_num,
  * Note that the geometry doesn't always exactly match total_sectors but
  * may round it down.
  *
- * Returns 0 on success, -EFBIG if the size is larger than 127 GB
+ * Returns 0 on success, -EFBIG if the size is larger than ~2 TB. Override
+ * the hardware EIDE and ATA-2 limit of 16 heads (max disk size of 127 GB)
+ * and instead allow up to 255 heads.
  */
 static int calculate_geometry(int64_t total_sectors, uint16_t* cyls,
     uint8_t* heads, uint8_t* secs_per_cyl)
 {
     uint32_t cyls_times_heads;
 
-    if (total_sectors > 65535 * 16 * 255)
+    /* Allow a maximum disk size of approximately 2 TB */
+    if (total_sectors > 65535LL * 255 * 255) {
         return -EFBIG;
+    }
 
     if (total_sectors > 65535 * 16 * 63) {
         *secs_per_cyl = 255;
-        *heads = 16;
+        if (total_sectors > 65535 * 16 * 255) {
+            *heads = 255;
+        } else {
+            *heads = 16;
+        }
         cyls_times_heads = total_sectors / *secs_per_cyl;
     } else {
         *secs_per_cyl = 17;

From c208e8c2d88eea2bbafc2850d8856525637e495d Mon Sep 17 00:00:00 2001
From: Paolo Bonzini 
Date: Fri, 2 Nov 2012 16:14:20 +0100
Subject: [PATCH 1892/2270] raw-posix: inline paio_ioctl into hdev_aio_ioctl

clang now warns about an unused function:
  CC    block/raw-posix.o
block/raw-posix.c:707:26: warning: unused function paio_ioctl
[-Wunused-function]
static BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
                         ^
1 warning generated.

because the only use of paio_ioctl() is inside a #if defined(__linux__)
guard and it is static now.

Reported-by: Peter Maydell 
Signed-off-by: Paolo Bonzini 
Signed-off-by: Stefan Hajnoczi 
---
 block/raw-posix.c | 27 ++++++++++-----------------
 1 file changed, 10 insertions(+), 17 deletions(-)

diff --git a/block/raw-posix.c b/block/raw-posix.c
index 550c81f22b..abfedbea73 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -708,22 +708,6 @@ static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
     return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
 }
 
-static BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
-        unsigned long int req, void *buf,
-        BlockDriverCompletionFunc *cb, void *opaque)
-{
-    RawPosixAIOData *acb = g_slice_new(RawPosixAIOData);
-
-    acb->bs = bs;
-    acb->aio_type = QEMU_AIO_IOCTL;
-    acb->aio_fildes = fd;
-    acb->aio_offset = 0;
-    acb->aio_ioctl_buf = buf;
-    acb->aio_ioctl_cmd = req;
-
-    return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
-}
-
 static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
         BlockDriverCompletionFunc *cb, void *opaque, int type)
@@ -1346,10 +1330,19 @@ static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
         BlockDriverCompletionFunc *cb, void *opaque)
 {
     BDRVRawState *s = bs->opaque;
+    RawPosixAIOData *acb;
 
     if (fd_open(bs) < 0)
         return NULL;
-    return paio_ioctl(bs, s->fd, req, buf, cb, opaque);
+
+    acb = g_slice_new(RawPosixAIOData);
+    acb->bs = bs;
+    acb->aio_type = QEMU_AIO_IOCTL;
+    acb->aio_fildes = s->fd;
+    acb->aio_offset = 0;
+    acb->aio_ioctl_buf = buf;
+    acb->aio_ioctl_cmd = req;
+    return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
 }
 
 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)

From 2d0d2837dcf786da415cf4165d37f4ddd684ff57 Mon Sep 17 00:00:00 2001
From: Christian Borntraeger 
Date: Tue, 20 Nov 2012 15:30:34 +0100
Subject: [PATCH 1893/2270] Support default block interfaces per QEMUMachine

There are QEMUMachines that have neither IF_IDE nor IF_SCSI as a
default/standard interface to their block devices / drives. Therefore,
this patch introduces a new field default_block_type per QEMUMachine
struct. The prior use_scsi field becomes thereby obsolete and is
replaced through .default_block_type = IF_SCSI.

This patch also changes the default for s390x to IF_VIRTIO and
removes an early hack that converts IF_IDE drives.
Other parties have already claimed interest (e.g. IF_SD for exynos)

To create a sane default, for machines that dont specify a
default_block_type, this patch makes IF_IDE = 0 and IF_NONE = 1.
I checked all users of IF_NONE (blockdev.c and ww/device-hotplug.c)
as well as IF_IDE and it seems that it is ok to change the defines -
in other words, I found no obvious (to me) assumption in the code
regarding IF_NONE==0. IF_NONE is only set if there is an
explicit if=none. Without if=* the interface becomes IF_DEFAULT.

I would suggest to have some additional care, e.g. by letting
this patch sit some days in the block tree.

Based on an initial patch from Einar Lueck 

Signed-off-by: Christian Borntraeger 
CC: Igor Mitsyanko 
CC: Markus Armbruster 
CC: Kevin Wolf 
Reviewed-by: Alexander Graf 
Acked-by: Igor Mitsyanko 
Reviewed-by: Markus Armbruster 
Signed-off-by: Stefan Hajnoczi 
---
 blockdev.c          |  4 ++--
 blockdev.h          |  9 +++++++--
 hw/boards.h         |  3 ++-
 hw/device-hotplug.c |  2 +-
 hw/highbank.c       |  2 +-
 hw/leon3.c          |  1 -
 hw/mips_jazz.c      |  4 ++--
 hw/pc_sysfw.c       |  2 +-
 hw/puv3.c           |  1 -
 hw/realview.c       |  6 +++---
 hw/s390-virtio.c    | 17 ++---------------
 hw/spapr.c          |  2 +-
 hw/sun4m.c          | 24 ++++++++++++------------
 hw/versatilepb.c    |  4 ++--
 hw/vexpress.c       |  4 ++--
 hw/xilinx_zynq.c    |  2 +-
 vl.c                | 21 ++++++++++++---------
 17 files changed, 51 insertions(+), 57 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index e73fd6e388..4a4d99f223 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -275,7 +275,7 @@ static bool do_check_io_limits(BlockIOLimit *io_limits)
     return true;
 }
 
-DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
+DriveInfo *drive_init(QemuOpts *opts, BlockInterfaceType block_default_type)
 {
     const char *buf;
     const char *file = NULL;
@@ -325,7 +325,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
             return NULL;
 	}
     } else {
-        type = default_to_scsi ? IF_SCSI : IF_IDE;
+        type = block_default_type;
     }
 
     max_devs = if_max_devs[type];
diff --git a/blockdev.h b/blockdev.h
index 5f27b643be..d73d552a98 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -19,8 +19,13 @@ void blockdev_auto_del(BlockDriverState *bs);
 
 typedef enum {
     IF_DEFAULT = -1,            /* for use with drive_add() only */
+    /*
+     * IF_IDE must be zero, because we want QEMUMachine member
+     * block_default_type to default-initialize to IF_IDE
+     */
+    IF_IDE = 0,
     IF_NONE,
-    IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
+    IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
     IF_COUNT
 } BlockInterfaceType;
 
@@ -51,7 +56,7 @@ DriveInfo *drive_get_by_blockdev(BlockDriverState *bs);
 QemuOpts *drive_def(const char *optstr);
 QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
                     const char *optstr);
-DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi);
+DriveInfo *drive_init(QemuOpts *arg, BlockInterfaceType block_default_type);
 
 /* device-hotplug */
 
diff --git a/hw/boards.h b/hw/boards.h
index 813d0e5109..c66fa16a9d 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -3,6 +3,7 @@
 #ifndef HW_BOARDS_H
 #define HW_BOARDS_H
 
+#include "blockdev.h"
 #include "qdev.h"
 
 typedef struct QEMUMachineInitArgs {
@@ -24,7 +25,7 @@ typedef struct QEMUMachine {
     const char *desc;
     QEMUMachineInitFunc *init;
     QEMUMachineResetFunc *reset;
-    int use_scsi;
+    BlockInterfaceType block_default_type;
     int max_cpus;
     unsigned int no_serial:1,
         no_parallel:1,
diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index 6d9c080381..839b9ea1d4 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -39,7 +39,7 @@ DriveInfo *add_init_drive(const char *optstr)
     if (!opts)
         return NULL;
 
-    dinfo = drive_init(opts, current_machine->use_scsi);
+    dinfo = drive_init(opts, current_machine->block_default_type);
     if (!dinfo) {
         qemu_opts_del(opts);
         return NULL;
diff --git a/hw/highbank.c b/hw/highbank.c
index afbb005422..e8e5bf0826 100644
--- a/hw/highbank.c
+++ b/hw/highbank.c
@@ -326,7 +326,7 @@ static QEMUMachine highbank_machine = {
     .name = "highbank",
     .desc = "Calxeda Highbank (ECX-1000)",
     .init = highbank_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
     .max_cpus = 4,
 };
 
diff --git a/hw/leon3.c b/hw/leon3.c
index 774273828f..ef83dffd85 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -212,7 +212,6 @@ static QEMUMachine leon3_generic_machine = {
     .name     = "leon3_generic",
     .desc     = "Leon-3 generic",
     .init     = leon3_generic_hw_init,
-    .use_scsi = 0,
 };
 
 static void leon3_machine_init(void)
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 0847427241..ea1416ae2f 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -324,14 +324,14 @@ static QEMUMachine mips_magnum_machine = {
     .name = "magnum",
     .desc = "MIPS Magnum",
     .init = mips_magnum_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
 };
 
 static QEMUMachine mips_pica61_machine = {
     .name = "pica61",
     .desc = "Acer Pica 61",
     .init = mips_pica61_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
 };
 
 static void mips_jazz_machine_init(void)
diff --git a/hw/pc_sysfw.c b/hw/pc_sysfw.c
index 40bced2322..d7ea3a5595 100644
--- a/hw/pc_sysfw.c
+++ b/hw/pc_sysfw.c
@@ -98,7 +98,7 @@ static void pc_fw_add_pflash_drv(void)
       return;
     }
 
-    if (!drive_init(opts, machine->use_scsi)) {
+    if (!drive_init(opts, machine->block_default_type)) {
         qemu_opts_del(opts);
     }
 }
diff --git a/hw/puv3.c b/hw/puv3.c
index 764799cff4..3d7734936b 100644
--- a/hw/puv3.c
+++ b/hw/puv3.c
@@ -122,7 +122,6 @@ static QEMUMachine puv3_machine = {
     .desc = "PKUnity Version-3 based on UniCore32",
     .init = puv3_init,
     .is_default = 1,
-    .use_scsi = 0,
 };
 
 static void puv3_machine_init(void)
diff --git a/hw/realview.c b/hw/realview.c
index e789c159a9..8ea4ad7423 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -364,14 +364,14 @@ static QEMUMachine realview_eb_machine = {
     .name = "realview-eb",
     .desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)",
     .init = realview_eb_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
 };
 
 static QEMUMachine realview_eb_mpcore_machine = {
     .name = "realview-eb-mpcore",
     .desc = "ARM RealView Emulation Baseboard (ARM11MPCore)",
     .init = realview_eb_mpcore_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
     .max_cpus = 4,
 };
 
@@ -385,7 +385,7 @@ static QEMUMachine realview_pbx_a9_machine = {
     .name = "realview-pbx-a9",
     .desc = "ARM RealView Platform Baseboard Explore for Cortex-A9",
     .init = realview_pbx_a9_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
     .max_cpus = 4,
 };
 
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index ca1bb09816..7aca0c4aad 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -314,21 +314,6 @@ static void s390_init(QEMUMachineInitArgs *args)
         qdev_set_nic_properties(dev, nd);
         qdev_init_nofail(dev);
     }
-
-    /* Create VirtIO disk drives */
-    for(i = 0; i < MAX_BLK_DEVS; i++) {
-        DriveInfo *dinfo;
-        DeviceState *dev;
-
-        dinfo = drive_get(IF_IDE, 0, i);
-        if (!dinfo) {
-            continue;
-        }
-
-        dev = qdev_create((BusState *)s390_bus, "virtio-blk-s390");
-        qdev_prop_set_drive_nofail(dev, "drive", dinfo->bdrv);
-        qdev_init_nofail(dev);
-    }
 }
 
 static QEMUMachine s390_machine = {
@@ -336,6 +321,7 @@ static QEMUMachine s390_machine = {
     .alias = "s390",
     .desc = "VirtIO based S390 machine",
     .init = s390_init,
+    .block_default_type = IF_VIRTIO,
     .no_cdrom = 1,
     .no_floppy = 1,
     .no_serial = 1,
@@ -352,3 +338,4 @@ static void s390_machine_init(void)
 }
 
 machine_init(s390_machine_init);
+
diff --git a/hw/spapr.c b/hw/spapr.c
index ad3f0ea7fc..d955f02a3b 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -924,9 +924,9 @@ static QEMUMachine spapr_machine = {
     .desc = "pSeries Logical Partition (PAPR compliant)",
     .init = ppc_spapr_init,
     .reset = ppc_spapr_reset,
+    .block_default_type = IF_SCSI,
     .max_cpus = MAX_CPUS,
     .no_parallel = 1,
-    .use_scsi = 1,
 };
 
 static void spapr_machine_init(void)
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 1a786762aa..52cf82b681 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -1426,7 +1426,7 @@ static QEMUMachine ss5_machine = {
     .name = "SS-5",
     .desc = "Sun4m platform, SPARCstation 5",
     .init = ss5_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
     .is_default = 1,
 };
 
@@ -1434,7 +1434,7 @@ static QEMUMachine ss10_machine = {
     .name = "SS-10",
     .desc = "Sun4m platform, SPARCstation 10",
     .init = ss10_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
     .max_cpus = 4,
 };
 
@@ -1442,7 +1442,7 @@ static QEMUMachine ss600mp_machine = {
     .name = "SS-600MP",
     .desc = "Sun4m platform, SPARCserver 600MP",
     .init = ss600mp_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
     .max_cpus = 4,
 };
 
@@ -1450,7 +1450,7 @@ static QEMUMachine ss20_machine = {
     .name = "SS-20",
     .desc = "Sun4m platform, SPARCstation 20",
     .init = ss20_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
     .max_cpus = 4,
 };
 
@@ -1458,35 +1458,35 @@ static QEMUMachine voyager_machine = {
     .name = "Voyager",
     .desc = "Sun4m platform, SPARCstation Voyager",
     .init = vger_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
 };
 
 static QEMUMachine ss_lx_machine = {
     .name = "LX",
     .desc = "Sun4m platform, SPARCstation LX",
     .init = ss_lx_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
 };
 
 static QEMUMachine ss4_machine = {
     .name = "SS-4",
     .desc = "Sun4m platform, SPARCstation 4",
     .init = ss4_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
 };
 
 static QEMUMachine scls_machine = {
     .name = "SPARCClassic",
     .desc = "Sun4m platform, SPARCClassic",
     .init = scls_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
 };
 
 static QEMUMachine sbook_machine = {
     .name = "SPARCbook",
     .desc = "Sun4m platform, SPARCbook",
     .init = sbook_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
 };
 
 static const struct sun4d_hwdef sun4d_hwdefs[] = {
@@ -1709,7 +1709,7 @@ static QEMUMachine ss1000_machine = {
     .name = "SS-1000",
     .desc = "Sun4d platform, SPARCserver 1000",
     .init = ss1000_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
     .max_cpus = 8,
 };
 
@@ -1717,7 +1717,7 @@ static QEMUMachine ss2000_machine = {
     .name = "SS-2000",
     .desc = "Sun4d platform, SPARCcenter 2000",
     .init = ss2000_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
     .max_cpus = 20,
 };
 
@@ -1896,7 +1896,7 @@ static QEMUMachine ss2_machine = {
     .name = "SS-2",
     .desc = "Sun4c platform, SPARCstation 2",
     .init = ss2_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
 };
 
 static void sun4m_register_types(void)
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 25e652b1aa..4892c1d27a 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -358,14 +358,14 @@ static QEMUMachine versatilepb_machine = {
     .name = "versatilepb",
     .desc = "ARM Versatile/PB (ARM926EJ-S)",
     .init = vpb_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
 };
 
 static QEMUMachine versatileab_machine = {
     .name = "versatileab",
     .desc = "ARM Versatile/AB (ARM926EJ-S)",
     .init = vab_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
 };
 
 static void versatile_machine_init(void)
diff --git a/hw/vexpress.c b/hw/vexpress.c
index d93f057bff..e89694c86e 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -477,7 +477,7 @@ static QEMUMachine vexpress_a9_machine = {
     .name = "vexpress-a9",
     .desc = "ARM Versatile Express for Cortex-A9",
     .init = vexpress_a9_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
     .max_cpus = 4,
 };
 
@@ -485,7 +485,7 @@ static QEMUMachine vexpress_a15_machine = {
     .name = "vexpress-a15",
     .desc = "ARM Versatile Express for Cortex-A15",
     .init = vexpress_a15_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
     .max_cpus = 4,
 };
 
diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
index 1f12a3d1ad..a4a71c2497 100644
--- a/hw/xilinx_zynq.c
+++ b/hw/xilinx_zynq.c
@@ -200,7 +200,7 @@ static QEMUMachine zynq_machine = {
     .name = "xilinx-zynq-a9",
     .desc = "Xilinx Zynq Platform Baseboard for Cortex-A9",
     .init = zynq_init,
-    .use_scsi = 1,
+    .block_default_type = IF_SCSI,
     .max_cpus = 1,
     .no_sdcard = 1
 };
diff --git a/vl.c b/vl.c
index a3ab3841a7..ee10d21c78 100644
--- a/vl.c
+++ b/vl.c
@@ -886,9 +886,9 @@ static int cleanup_add_fd(QemuOpts *opts, void *opaque)
 
 static int drive_init_func(QemuOpts *opts, void *opaque)
 {
-    int *use_scsi = opaque;
+    BlockInterfaceType *block_default_type = opaque;
 
-    return drive_init(opts, *use_scsi) == NULL;
+    return drive_init(opts, *block_default_type) == NULL;
 }
 
 static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
@@ -899,14 +899,15 @@ static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
     return 0;
 }
 
-static void default_drive(int enable, int snapshot, int use_scsi,
+static void default_drive(int enable, int snapshot,
+                          BlockInterfaceType block_default_type,
                           BlockInterfaceType type, int index,
                           const char *optstr)
 {
     QemuOpts *opts;
 
     if (type == IF_DEFAULT) {
-        type = use_scsi ? IF_SCSI : IF_IDE;
+        type = block_default_type;
     }
 
     if (!enable || drive_get_by_index(type, index)) {
@@ -917,7 +918,7 @@ static void default_drive(int enable, int snapshot, int use_scsi,
     if (snapshot) {
         drive_enable_snapshot(opts, NULL);
     }
-    if (!drive_init(opts, use_scsi)) {
+    if (!drive_init(opts, type)) {
         exit(1);
     }
 }
@@ -3770,14 +3771,16 @@ int main(int argc, char **argv, char **envp)
     /* open the virtual block devices */
     if (snapshot)
         qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot, NULL, 0);
-    if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func, &machine->use_scsi, 1) != 0)
+    if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func,
+                          &machine->block_default_type, 1) != 0) {
         exit(1);
+    }
 
-    default_drive(default_cdrom, snapshot, machine->use_scsi,
+    default_drive(default_cdrom, snapshot, machine->block_default_type,
                   IF_DEFAULT, 2, CDROM_OPTS);
-    default_drive(default_floppy, snapshot, machine->use_scsi,
+    default_drive(default_floppy, snapshot, machine->block_default_type,
                   IF_FLOPPY, 0, FD_OPTS);
-    default_drive(default_sdcard, snapshot, machine->use_scsi,
+    default_drive(default_sdcard, snapshot, machine->block_default_type,
                   IF_SD, 0, SD_OPTS);
 
     register_savevm_live(NULL, "ram", 0, 4, &savevm_ram_handlers, NULL);

From 3c42ea66888f149d72d600bab63624b2d849e4bf Mon Sep 17 00:00:00 2001
From: Christian Borntraeger 
Date: Thu, 22 Nov 2012 21:02:55 +0100
Subject: [PATCH 1894/2270] block: simplify default_drive

Markus Armbruster pointed out that there is only one caller
to default_drive with IF_DEFAULT as a type. Lets get rid
of the block_default_type parameter and adopt the caller
to do the right thing (asking the machine struct).

Signed-off-by: Christian Borntraeger 
Reviewed-by: Markus Armbruster 
Signed-off-by: Stefan Hajnoczi 
---
 vl.c | 20 ++++++--------------
 1 file changed, 6 insertions(+), 14 deletions(-)

diff --git a/vl.c b/vl.c
index ee10d21c78..6b3827cf06 100644
--- a/vl.c
+++ b/vl.c
@@ -899,17 +899,11 @@ static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
     return 0;
 }
 
-static void default_drive(int enable, int snapshot,
-                          BlockInterfaceType block_default_type,
-                          BlockInterfaceType type, int index,
-                          const char *optstr)
+static void default_drive(int enable, int snapshot, BlockInterfaceType type,
+                          int index, const char *optstr)
 {
     QemuOpts *opts;
 
-    if (type == IF_DEFAULT) {
-        type = block_default_type;
-    }
-
     if (!enable || drive_get_by_index(type, index)) {
         return;
     }
@@ -3776,12 +3770,10 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
-    default_drive(default_cdrom, snapshot, machine->block_default_type,
-                  IF_DEFAULT, 2, CDROM_OPTS);
-    default_drive(default_floppy, snapshot, machine->block_default_type,
-                  IF_FLOPPY, 0, FD_OPTS);
-    default_drive(default_sdcard, snapshot, machine->block_default_type,
-                  IF_SD, 0, SD_OPTS);
+    default_drive(default_cdrom, snapshot, machine->block_default_type, 2,
+                  CDROM_OPTS);
+    default_drive(default_floppy, snapshot, IF_FLOPPY, 0, FD_OPTS);
+    default_drive(default_sdcard, snapshot, IF_SD, 0, SD_OPTS);
 
     register_savevm_live(NULL, "ram", 0, 4, &savevm_ram_handlers, NULL);
 

From 71c79813d83b5b45ba934cf995436063da458f66 Mon Sep 17 00:00:00 2001
From: Luiz Capitulino 
Date: Fri, 30 Nov 2012 10:52:04 -0200
Subject: [PATCH 1895/2270] block: bdrv_img_create(): add Error ** argument

This commit adds an Error ** argument to bdrv_img_create() and set it
appropriately on error.

Callers of bdrv_img_create() pass NULL for the new argument and still
rely on bdrv_img_create()'s return value. Next commits will change
callers to use the Error object instead.

Signed-off-by: Luiz Capitulino 
Signed-off-by: Kevin Wolf 
---
 block.c    | 22 +++++++++++++++++++++-
 block.h    |  2 +-
 blockdev.c |  6 +++---
 qemu-img.c |  2 +-
 4 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/block.c b/block.c
index 2ec3afebfe..066bd66db0 100644
--- a/block.c
+++ b/block.c
@@ -4444,7 +4444,7 @@ bdrv_acct_done(BlockDriverState *bs, BlockAcctCookie *cookie)
 
 int bdrv_img_create(const char *filename, const char *fmt,
                     const char *base_filename, const char *base_fmt,
-                    char *options, uint64_t img_size, int flags)
+                    char *options, uint64_t img_size, int flags, Error **errp)
 {
     QEMUOptionParameter *param = NULL, *create_options = NULL;
     QEMUOptionParameter *backing_fmt, *backing_file, *size;
@@ -4457,6 +4457,7 @@ int bdrv_img_create(const char *filename, const char *fmt,
     drv = bdrv_find_format(fmt);
     if (!drv) {
         error_report("Unknown file format '%s'", fmt);
+        error_setg(errp, "Unknown file format '%s'", fmt);
         ret = -EINVAL;
         goto out;
     }
@@ -4464,6 +4465,7 @@ int bdrv_img_create(const char *filename, const char *fmt,
     proto_drv = bdrv_find_protocol(filename);
     if (!proto_drv) {
         error_report("Unknown protocol '%s'", filename);
+        error_setg(errp, "Unknown protocol '%s'", filename);
         ret = -EINVAL;
         goto out;
     }
@@ -4483,6 +4485,7 @@ int bdrv_img_create(const char *filename, const char *fmt,
         param = parse_option_parameters(options, create_options, param);
         if (param == NULL) {
             error_report("Invalid options for file format '%s'.", fmt);
+            error_setg(errp, "Invalid options for file format '%s'.", fmt);
             ret = -EINVAL;
             goto out;
         }
@@ -4493,6 +4496,8 @@ int bdrv_img_create(const char *filename, const char *fmt,
                                  base_filename)) {
             error_report("Backing file not supported for file format '%s'",
                          fmt);
+            error_setg(errp, "Backing file not supported for file format '%s'",
+                       fmt);
             ret = -EINVAL;
             goto out;
         }
@@ -4502,6 +4507,8 @@ int bdrv_img_create(const char *filename, const char *fmt,
         if (set_option_parameter(param, BLOCK_OPT_BACKING_FMT, base_fmt)) {
             error_report("Backing file format not supported for file "
                          "format '%s'", fmt);
+            error_setg(errp, "Backing file format not supported for file "
+                             "format '%s'", fmt);
             ret = -EINVAL;
             goto out;
         }
@@ -4512,6 +4519,8 @@ int bdrv_img_create(const char *filename, const char *fmt,
         if (!strcmp(filename, backing_file->value.s)) {
             error_report("Error: Trying to create an image with the "
                          "same filename as the backing file");
+            error_setg(errp, "Error: Trying to create an image with the "
+                             "same filename as the backing file");
             ret = -EINVAL;
             goto out;
         }
@@ -4523,6 +4532,8 @@ int bdrv_img_create(const char *filename, const char *fmt,
         if (!backing_drv) {
             error_report("Unknown backing file format '%s'",
                          backing_fmt->value.s);
+            error_setg(errp, "Unknown backing file format '%s'",
+                       backing_fmt->value.s);
             ret = -EINVAL;
             goto out;
         }
@@ -4546,6 +4557,8 @@ int bdrv_img_create(const char *filename, const char *fmt,
             ret = bdrv_open(bs, backing_file->value.s, back_flags, backing_drv);
             if (ret < 0) {
                 error_report("Could not open '%s'", backing_file->value.s);
+                error_setg_errno(errp, -ret, "Could not open '%s'",
+                                 backing_file->value.s);
                 goto out;
             }
             bdrv_get_geometry(bs, &size);
@@ -4555,6 +4568,7 @@ int bdrv_img_create(const char *filename, const char *fmt,
             set_option_parameter(param, BLOCK_OPT_SIZE, buf);
         } else {
             error_report("Image creation needs a size parameter");
+            error_setg(errp, "Image creation needs a size parameter");
             ret = -EINVAL;
             goto out;
         }
@@ -4570,12 +4584,18 @@ int bdrv_img_create(const char *filename, const char *fmt,
         if (ret == -ENOTSUP) {
             error_report("Formatting or formatting option not supported for "
                          "file format '%s'", fmt);
+            error_setg(errp,"Formatting or formatting option not supported for "
+                            "file format '%s'", fmt);
         } else if (ret == -EFBIG) {
             error_report("The image size is too large for file format '%s'",
                          fmt);
+            error_setg(errp, "The image size is too large for file format '%s'",
+                       fmt);
         } else {
             error_report("%s: error while creating %s: %s", filename, fmt,
                          strerror(-ret));
+            error_setg(errp, "%s: error while creating %s: %s", filename, fmt,
+                       strerror(-ret));
         }
     }
 
diff --git a/block.h b/block.h
index 722c620590..ff54d15c86 100644
--- a/block.h
+++ b/block.h
@@ -345,7 +345,7 @@ int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
 
 int bdrv_img_create(const char *filename, const char *fmt,
                     const char *base_filename, const char *base_fmt,
-                    char *options, uint64_t img_size, int flags);
+                    char *options, uint64_t img_size, int flags, Error **errp);
 
 void bdrv_set_buffer_alignment(BlockDriverState *bs, int align);
 void *qemu_blockalign(BlockDriverState *bs, size_t size);
diff --git a/blockdev.c b/blockdev.c
index 4a4d99f223..500f09116a 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -789,7 +789,7 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp)
             ret = bdrv_img_create(new_image_file, format,
                                   states->old_bs->filename,
                                   states->old_bs->drv->format_name,
-                                  NULL, -1, flags);
+                                  NULL, -1, flags, NULL);
             if (ret) {
                 error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file);
                 goto delete_and_fail;
@@ -1264,7 +1264,7 @@ void qmp_drive_mirror(const char *device, const char *target,
         bdrv_get_geometry(bs, &size);
         size *= 512;
         ret = bdrv_img_create(target, format,
-                              NULL, NULL, NULL, size, flags);
+                              NULL, NULL, NULL, size, flags, NULL);
     } else {
         switch (mode) {
         case NEW_IMAGE_MODE_EXISTING:
@@ -1275,7 +1275,7 @@ void qmp_drive_mirror(const char *device, const char *target,
             ret = bdrv_img_create(target, format,
                                   source->filename,
                                   source->drv->format_name,
-                                  NULL, -1, flags);
+                                  NULL, -1, flags, NULL);
             break;
         default:
             abort();
diff --git a/qemu-img.c b/qemu-img.c
index e29e01b729..3896689060 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -362,7 +362,7 @@ static int img_create(int argc, char **argv)
     }
 
     ret = bdrv_img_create(filename, fmt, base_filename, base_fmt,
-                          options, img_size, BDRV_O_FLAGS);
+                          options, img_size, BDRV_O_FLAGS, NULL);
 out:
     if (ret) {
         return 1;

From 9b37525a7dbc4f5eef0023fc92716259a3d94612 Mon Sep 17 00:00:00 2001
From: Luiz Capitulino 
Date: Fri, 30 Nov 2012 10:52:05 -0200
Subject: [PATCH 1896/2270] qemu-img: img_create(): pass Error object to
 bdrv_img_create()

Signed-off-by: Luiz Capitulino 
Signed-off-by: Kevin Wolf 
---
 qemu-img.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/qemu-img.c b/qemu-img.c
index 3896689060..595b6f5136 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -301,6 +301,7 @@ static int img_create(int argc, char **argv)
     const char *filename;
     const char *base_filename = NULL;
     char *options = NULL;
+    Error *local_err = NULL;
 
     for(;;) {
         c = getopt(argc, argv, "F:b:f:he6o:");
@@ -361,8 +362,14 @@ static int img_create(int argc, char **argv)
         goto out;
     }
 
-    ret = bdrv_img_create(filename, fmt, base_filename, base_fmt,
-                          options, img_size, BDRV_O_FLAGS, NULL);
+    bdrv_img_create(filename, fmt, base_filename, base_fmt,
+                    options, img_size, BDRV_O_FLAGS, &local_err);
+    if (error_is_set(&local_err)) {
+        error_report("%s", error_get_pretty(local_err));
+        error_free(local_err);
+        ret = -1;
+    }
+
 out:
     if (ret) {
         return 1;

From a930091189cedcc0023dd38f705e2a46e530f4a4 Mon Sep 17 00:00:00 2001
From: Luiz Capitulino 
Date: Fri, 30 Nov 2012 10:52:06 -0200
Subject: [PATCH 1897/2270] qemu-img: img_create(): drop unneeded goto and ret
 variable

Signed-off-by: Luiz Capitulino 
Signed-off-by: Kevin Wolf 
---
 qemu-img.c | 14 ++++----------
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/qemu-img.c b/qemu-img.c
index 595b6f5136..c4dae88e84 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -294,7 +294,7 @@ static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
 
 static int img_create(int argc, char **argv)
 {
-    int c, ret = 0;
+    int c;
     uint64_t img_size = -1;
     const char *fmt = "raw";
     const char *base_fmt = NULL;
@@ -351,15 +351,13 @@ static int img_create(int argc, char **argv)
             error_report("Invalid image size specified! You may use k, M, G or "
                   "T suffixes for ");
             error_report("kilobytes, megabytes, gigabytes and terabytes.");
-            ret = -1;
-            goto out;
+            return 1;
         }
         img_size = (uint64_t)sval;
     }
 
     if (options && is_help_option(options)) {
-        ret = print_block_option_help(filename, fmt);
-        goto out;
+        return print_block_option_help(filename, fmt);
     }
 
     bdrv_img_create(filename, fmt, base_filename, base_fmt,
@@ -367,13 +365,9 @@ static int img_create(int argc, char **argv)
     if (error_is_set(&local_err)) {
         error_report("%s", error_get_pretty(local_err));
         error_free(local_err);
-        ret = -1;
-    }
-
-out:
-    if (ret) {
         return 1;
     }
+
     return 0;
 }
 

From 43e17041156ddecac8a7500648e71287ba270c0a Mon Sep 17 00:00:00 2001
From: Luiz Capitulino 
Date: Fri, 30 Nov 2012 10:52:07 -0200
Subject: [PATCH 1898/2270] qmp: qmp_transaction(): pass Error object to
 bdrv_img_create()

Signed-off-by: Luiz Capitulino 
Signed-off-by: Kevin Wolf 
---
 blockdev.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 500f09116a..6fb336294c 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -707,6 +707,7 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp)
     int ret = 0;
     BlockdevActionList *dev_entry = dev_list;
     BlkTransactionStates *states, *next;
+    Error *local_err = NULL;
 
     QSIMPLEQ_HEAD(snap_bdrv_states, BlkTransactionStates) snap_bdrv_states;
     QSIMPLEQ_INIT(&snap_bdrv_states);
@@ -786,12 +787,12 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp)
 
         /* create new image w/backing file */
         if (mode != NEW_IMAGE_MODE_EXISTING) {
-            ret = bdrv_img_create(new_image_file, format,
-                                  states->old_bs->filename,
-                                  states->old_bs->drv->format_name,
-                                  NULL, -1, flags, NULL);
-            if (ret) {
-                error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file);
+            bdrv_img_create(new_image_file, format,
+                            states->old_bs->filename,
+                            states->old_bs->drv->format_name,
+                            NULL, -1, flags, &local_err);
+            if (error_is_set(&local_err)) {
+                error_propagate(errp, local_err);
                 goto delete_and_fail;
             }
         }

From cf8f2426c55245f437a91f2fdabbed4ea24e7786 Mon Sep 17 00:00:00 2001
From: Luiz Capitulino 
Date: Fri, 30 Nov 2012 10:52:08 -0200
Subject: [PATCH 1899/2270] qmp: qmp_drive_mirror(): pass Error object to
 bdrv_img_create()

Signed-off-by: Luiz Capitulino 
Signed-off-by: Kevin Wolf 
---
 blockdev.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 6fb336294c..463f4c2094 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1264,8 +1264,8 @@ void qmp_drive_mirror(const char *device, const char *target,
         assert(format && drv);
         bdrv_get_geometry(bs, &size);
         size *= 512;
-        ret = bdrv_img_create(target, format,
-                              NULL, NULL, NULL, size, flags, NULL);
+        bdrv_img_create(target, format,
+                        NULL, NULL, NULL, size, flags, &local_err);
     } else {
         switch (mode) {
         case NEW_IMAGE_MODE_EXISTING:
@@ -1273,18 +1273,18 @@ void qmp_drive_mirror(const char *device, const char *target,
             break;
         case NEW_IMAGE_MODE_ABSOLUTE_PATHS:
             /* create new image with backing file */
-            ret = bdrv_img_create(target, format,
-                                  source->filename,
-                                  source->drv->format_name,
-                                  NULL, -1, flags, NULL);
+            bdrv_img_create(target, format,
+                            source->filename,
+                            source->drv->format_name,
+                            NULL, -1, flags, &local_err);
             break;
         default:
             abort();
         }
     }
 
-    if (ret) {
-        error_set(errp, QERR_OPEN_FILE_FAILED, target);
+    if (error_is_set(&local_err)) {
+        error_propagate(errp, local_err);
         return;
     }
 

From d92ada2202a0730e396304908ff7b870168387d2 Mon Sep 17 00:00:00 2001
From: Luiz Capitulino 
Date: Fri, 30 Nov 2012 10:52:09 -0200
Subject: [PATCH 1900/2270] block: bdrv_img_create(): drop unused error
 handling code

Signed-off-by: Luiz Capitulino 
Signed-off-by: Kevin Wolf 
---
 block.c | 40 +++++-----------------------------------
 block.h |  6 +++---
 2 files changed, 8 insertions(+), 38 deletions(-)

diff --git a/block.c b/block.c
index 066bd66db0..b3faf3a463 100644
--- a/block.c
+++ b/block.c
@@ -4442,9 +4442,9 @@ bdrv_acct_done(BlockDriverState *bs, BlockAcctCookie *cookie)
     bs->total_time_ns[cookie->type] += get_clock() - cookie->start_time_ns;
 }
 
-int bdrv_img_create(const char *filename, const char *fmt,
-                    const char *base_filename, const char *base_fmt,
-                    char *options, uint64_t img_size, int flags, Error **errp)
+void bdrv_img_create(const char *filename, const char *fmt,
+                     const char *base_filename, const char *base_fmt,
+                     char *options, uint64_t img_size, int flags, Error **errp)
 {
     QEMUOptionParameter *param = NULL, *create_options = NULL;
     QEMUOptionParameter *backing_fmt, *backing_file, *size;
@@ -4456,18 +4456,14 @@ int bdrv_img_create(const char *filename, const char *fmt,
     /* Find driver and parse its options */
     drv = bdrv_find_format(fmt);
     if (!drv) {
-        error_report("Unknown file format '%s'", fmt);
         error_setg(errp, "Unknown file format '%s'", fmt);
-        ret = -EINVAL;
-        goto out;
+        return;
     }
 
     proto_drv = bdrv_find_protocol(filename);
     if (!proto_drv) {
-        error_report("Unknown protocol '%s'", filename);
         error_setg(errp, "Unknown protocol '%s'", filename);
-        ret = -EINVAL;
-        goto out;
+        return;
     }
 
     create_options = append_option_parameters(create_options,
@@ -4484,9 +4480,7 @@ int bdrv_img_create(const char *filename, const char *fmt,
     if (options) {
         param = parse_option_parameters(options, create_options, param);
         if (param == NULL) {
-            error_report("Invalid options for file format '%s'.", fmt);
             error_setg(errp, "Invalid options for file format '%s'.", fmt);
-            ret = -EINVAL;
             goto out;
         }
     }
@@ -4494,22 +4488,16 @@ int bdrv_img_create(const char *filename, const char *fmt,
     if (base_filename) {
         if (set_option_parameter(param, BLOCK_OPT_BACKING_FILE,
                                  base_filename)) {
-            error_report("Backing file not supported for file format '%s'",
-                         fmt);
             error_setg(errp, "Backing file not supported for file format '%s'",
                        fmt);
-            ret = -EINVAL;
             goto out;
         }
     }
 
     if (base_fmt) {
         if (set_option_parameter(param, BLOCK_OPT_BACKING_FMT, base_fmt)) {
-            error_report("Backing file format not supported for file "
-                         "format '%s'", fmt);
             error_setg(errp, "Backing file format not supported for file "
                              "format '%s'", fmt);
-            ret = -EINVAL;
             goto out;
         }
     }
@@ -4517,11 +4505,8 @@ int bdrv_img_create(const char *filename, const char *fmt,
     backing_file = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
     if (backing_file && backing_file->value.s) {
         if (!strcmp(filename, backing_file->value.s)) {
-            error_report("Error: Trying to create an image with the "
-                         "same filename as the backing file");
             error_setg(errp, "Error: Trying to create an image with the "
                              "same filename as the backing file");
-            ret = -EINVAL;
             goto out;
         }
     }
@@ -4530,11 +4515,8 @@ int bdrv_img_create(const char *filename, const char *fmt,
     if (backing_fmt && backing_fmt->value.s) {
         backing_drv = bdrv_find_format(backing_fmt->value.s);
         if (!backing_drv) {
-            error_report("Unknown backing file format '%s'",
-                         backing_fmt->value.s);
             error_setg(errp, "Unknown backing file format '%s'",
                        backing_fmt->value.s);
-            ret = -EINVAL;
             goto out;
         }
     }
@@ -4556,7 +4538,6 @@ int bdrv_img_create(const char *filename, const char *fmt,
 
             ret = bdrv_open(bs, backing_file->value.s, back_flags, backing_drv);
             if (ret < 0) {
-                error_report("Could not open '%s'", backing_file->value.s);
                 error_setg_errno(errp, -ret, "Could not open '%s'",
                                  backing_file->value.s);
                 goto out;
@@ -4567,9 +4548,7 @@ int bdrv_img_create(const char *filename, const char *fmt,
             snprintf(buf, sizeof(buf), "%" PRId64, size);
             set_option_parameter(param, BLOCK_OPT_SIZE, buf);
         } else {
-            error_report("Image creation needs a size parameter");
             error_setg(errp, "Image creation needs a size parameter");
-            ret = -EINVAL;
             goto out;
         }
     }
@@ -4579,21 +4558,14 @@ int bdrv_img_create(const char *filename, const char *fmt,
     puts("");
 
     ret = bdrv_create(drv, filename, param);
-
     if (ret < 0) {
         if (ret == -ENOTSUP) {
-            error_report("Formatting or formatting option not supported for "
-                         "file format '%s'", fmt);
             error_setg(errp,"Formatting or formatting option not supported for "
                             "file format '%s'", fmt);
         } else if (ret == -EFBIG) {
-            error_report("The image size is too large for file format '%s'",
-                         fmt);
             error_setg(errp, "The image size is too large for file format '%s'",
                        fmt);
         } else {
-            error_report("%s: error while creating %s: %s", filename, fmt,
-                         strerror(-ret));
             error_setg(errp, "%s: error while creating %s: %s", filename, fmt,
                        strerror(-ret));
         }
@@ -4606,6 +4578,4 @@ out:
     if (bs) {
         bdrv_delete(bs);
     }
-
-    return ret;
 }
diff --git a/block.h b/block.h
index ff54d15c86..24bea09530 100644
--- a/block.h
+++ b/block.h
@@ -343,9 +343,9 @@ int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
 int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
                       int64_t pos, int size);
 
-int bdrv_img_create(const char *filename, const char *fmt,
-                    const char *base_filename, const char *base_fmt,
-                    char *options, uint64_t img_size, int flags, Error **errp);
+void bdrv_img_create(const char *filename, const char *fmt,
+                     const char *base_filename, const char *base_fmt,
+                     char *options, uint64_t img_size, int flags, Error **errp);
 
 void bdrv_set_buffer_alignment(BlockDriverState *bs, int align);
 void *qemu_blockalign(BlockDriverState *bs, size_t size);

From 23e956bfe6af6f71046772478ed08d4e5c9c62d4 Mon Sep 17 00:00:00 2001
From: Corey Bryant 
Date: Wed, 14 Nov 2012 17:53:16 -0500
Subject: [PATCH 1901/2270] tests: Add tests for fdsets

Signed-off-by: Corey Bryant 
Reviewed-by: Kevin Wolf 
Signed-off-by: Stefan Hajnoczi 
---
 tests/qemu-iotests/045        | 129 ++++++++++++++++++++++++++++++++++
 tests/qemu-iotests/045.out    |   5 ++
 tests/qemu-iotests/group      |   1 +
 tests/qemu-iotests/iotests.py |  12 ++++
 4 files changed, 147 insertions(+)
 create mode 100755 tests/qemu-iotests/045
 create mode 100644 tests/qemu-iotests/045.out

diff --git a/tests/qemu-iotests/045 b/tests/qemu-iotests/045
new file mode 100755
index 0000000000..2b6f1af27a
--- /dev/null
+++ b/tests/qemu-iotests/045
@@ -0,0 +1,129 @@
+#!/usr/bin/env python
+#
+# Tests for fdsets.
+#
+# Copyright (C) 2012 IBM Corp.
+#
+# 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 .
+#
+
+import os
+import iotests
+from iotests import qemu_img
+
+image0 = os.path.join(iotests.test_dir, 'image0')
+image1 = os.path.join(iotests.test_dir, 'image1')
+image2 = os.path.join(iotests.test_dir, 'image2')
+image3 = os.path.join(iotests.test_dir, 'image3')
+image4 = os.path.join(iotests.test_dir, 'image4')
+
+class TestFdSets(iotests.QMPTestCase):
+
+    def setUp(self):
+        self.vm = iotests.VM()
+        qemu_img('create', '-f', iotests.imgfmt, image0, '128K')
+        qemu_img('create', '-f', iotests.imgfmt, image1, '128K')
+        qemu_img('create', '-f', iotests.imgfmt, image2, '128K')
+        qemu_img('create', '-f', iotests.imgfmt, image3, '128K')
+        qemu_img('create', '-f', iotests.imgfmt, image4, '128K')
+        self.file0 = open(image0, 'r')
+        self.file1 = open(image1, 'w+')
+        self.file2 = open(image2, 'r')
+        self.file3 = open(image3, 'r')
+        self.file4 = open(image4, 'r')
+        self.vm.add_fd(self.file0.fileno(), 1, 'image0:r')
+        self.vm.add_fd(self.file1.fileno(), 1, 'image1:w+')
+        self.vm.add_fd(self.file2.fileno(), 0, 'image2:r')
+        self.vm.add_fd(self.file3.fileno(), 2, 'image3:r')
+        self.vm.add_fd(self.file4.fileno(), 2, 'image4:r')
+        self.vm.add_drive("/dev/fdset/1")
+        self.vm.launch()
+
+    def tearDown(self):
+        self.vm.shutdown()
+        self.file0.close()
+        self.file1.close()
+        self.file2.close()
+        self.file3.close()
+        self.file4.close()
+        os.remove(image0)
+        os.remove(image1)
+        os.remove(image2)
+        os.remove(image3)
+        os.remove(image4)
+
+    def test_query_fdset(self):
+        result = self.vm.qmp('query-fdsets')
+        self.assert_qmp(result, 'return[0]/fdset-id', 2)
+        self.assert_qmp(result, 'return[1]/fdset-id', 1)
+        self.assert_qmp(result, 'return[2]/fdset-id', 0)
+        self.assert_qmp(result, 'return[0]/fds[0]/opaque', 'image3:r')
+        self.assert_qmp(result, 'return[0]/fds[1]/opaque', 'image4:r')
+        self.assert_qmp(result, 'return[1]/fds[0]/opaque', 'image0:r')
+        self.assert_qmp(result, 'return[1]/fds[1]/opaque', 'image1:w+')
+        self.assert_qmp(result, 'return[2]/fds[0]/opaque', 'image2:r')
+        self.vm.shutdown()
+
+    def test_remove_fdset(self):
+        result = self.vm.qmp('remove-fd', fdset_id=2)
+        self.assert_qmp(result, 'return', {})
+        result = self.vm.qmp('query-fdsets')
+        self.assert_qmp(result, 'return[0]/fdset-id', 1)
+        self.assert_qmp(result, 'return[1]/fdset-id', 0)
+        self.assert_qmp(result, 'return[0]/fds[0]/opaque', 'image0:r')
+        self.assert_qmp(result, 'return[0]/fds[1]/opaque', 'image1:w+')
+        self.assert_qmp(result, 'return[1]/fds[0]/opaque', 'image2:r')
+        self.vm.shutdown()
+
+    def test_remove_fd(self):
+        result = self.vm.qmp('query-fdsets')
+        fd_image3 = result['return'][0]['fds'][0]['fd']
+        result = self.vm.qmp('remove-fd', fdset_id=2, fd=fd_image3)
+        self.assert_qmp(result, 'return', {})
+        result = self.vm.qmp('query-fdsets')
+        self.assert_qmp(result, 'return[0]/fdset-id', 2)
+        self.assert_qmp(result, 'return[1]/fdset-id', 1)
+        self.assert_qmp(result, 'return[2]/fdset-id', 0)
+        self.assert_qmp(result, 'return[0]/fds[0]/opaque', 'image4:r')
+        self.assert_qmp(result, 'return[1]/fds[0]/opaque', 'image0:r')
+        self.assert_qmp(result, 'return[1]/fds[1]/opaque', 'image1:w+')
+        self.assert_qmp(result, 'return[2]/fds[0]/opaque', 'image2:r')
+        self.vm.shutdown()
+
+    def test_remove_fd_invalid_fdset(self):
+        result = self.vm.qmp('query-fdsets')
+        fd_image3 = result['return'][0]['fds'][0]['fd']
+        result = self.vm.qmp('remove-fd', fdset_id=3, fd=fd_image3)
+        self.assert_qmp(result, 'error/class', 'GenericError')
+        self.assert_qmp(result, 'error/desc',
+            'File descriptor named \'fdset-id:3, fd:%d\' not found' % fd_image3)
+        self.vm.shutdown()
+
+    def test_remove_fd_invalid_fd(self):
+        result = self.vm.qmp('query-fdsets')
+        result = self.vm.qmp('remove-fd', fdset_id=2, fd=999)
+        self.assert_qmp(result, 'error/class', 'GenericError')
+        self.assert_qmp(result, 'error/desc',
+            'File descriptor named \'fdset-id:2, fd:999\' not found')
+        self.vm.shutdown()
+
+    def test_add_fd_invalid_fd(self):
+        result = self.vm.qmp('add-fd', fdset_id=2)
+        self.assert_qmp(result, 'error/class', 'GenericError')
+        self.assert_qmp(result, 'error/desc',
+                'No file descriptor supplied via SCM_RIGHTS')
+        self.vm.shutdown()
+
+if __name__ == '__main__':
+    iotests.main(supported_fmts=['raw'])
diff --git a/tests/qemu-iotests/045.out b/tests/qemu-iotests/045.out
new file mode 100644
index 0000000000..3f8a935a08
--- /dev/null
+++ b/tests/qemu-iotests/045.out
@@ -0,0 +1,5 @@
+......
+----------------------------------------------------------------------
+Ran 6 tests
+
+OK
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index a4a9044f24..5b39785461 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -51,3 +51,4 @@
 042 rw auto quick
 043 rw auto backing
 044 rw auto
+045 rw auto
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 0be5c7e13f..569ca3d804 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -79,6 +79,18 @@ class VM(object):
         self._num_drives += 1
         return self
 
+    def add_fd(self, fd, fdset, opaque, opts=''):
+        '''Pass a file descriptor to the VM'''
+        options = ['fd=%d' % fd,
+                   'set=%d' % fdset,
+                   'opaque=%s' % opaque]
+        if opts:
+            options.append(opts)
+
+        self._args.append('-add-fd')
+        self._args.append(','.join(options))
+        return self
+
     def launch(self):
         '''Launch the VM and establish a QMP connection'''
         devnull = open('/dev/null', 'rb')

From 791bfa35ee00ca10b13bedfb048ffda385b151c7 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Tue, 4 Dec 2012 16:35:12 +0100
Subject: [PATCH 1902/2270] qemu-io: Implement write -c for compressed clusters

This makes it easier to create images with both compressed and
uncompressed clusters for testing.

Signed-off-by: Kevin Wolf 
Signed-off-by: Stefan Hajnoczi 
---
 qemu-io.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/qemu-io.c b/qemu-io.c
index 92cdb2ab9c..b4b0898741 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -265,6 +265,18 @@ static int do_co_write_zeroes(int64_t offset, int count, int *total)
     }
 }
 
+static int do_write_compressed(char *buf, int64_t offset, int count, int *total)
+{
+    int ret;
+
+    ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
+    if (ret < 0) {
+        return ret;
+    }
+    *total = count;
+    return 1;
+}
+
 static int do_load_vmstate(char *buf, int64_t offset, int count, int *total)
 {
     *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
@@ -687,6 +699,7 @@ static void write_help(void)
 " Writes into a segment of the currently open file, using a buffer\n"
 " filled with a set pattern (0xcdcdcdcd).\n"
 " -b, -- write to the VM state rather than the virtual disk\n"
+" -c, -- write compressed data with bdrv_write_compressed\n"
 " -p, -- use bdrv_pwrite to write the file\n"
 " -P, -- use different pattern to fill file\n"
 " -C, -- report statistics in a machine parsable format\n"
@@ -703,7 +716,7 @@ static const cmdinfo_t write_cmd = {
     .cfunc      = write_f,
     .argmin     = 2,
     .argmax     = -1,
-    .args       = "[-bCpqz] [-P pattern ] off len",
+    .args       = "[-bcCpqz] [-P pattern ] off len",
     .oneline    = "writes a number of bytes at a specified offset",
     .help       = write_help,
 };
@@ -712,6 +725,7 @@ static int write_f(int argc, char **argv)
 {
     struct timeval t1, t2;
     int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
+    int cflag = 0;
     int c, cnt;
     char *buf = NULL;
     int64_t offset;
@@ -720,11 +734,14 @@ static int write_f(int argc, char **argv)
     int total = 0;
     int pattern = 0xcd;
 
-    while ((c = getopt(argc, argv, "bCpP:qz")) != EOF) {
+    while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
         switch (c) {
         case 'b':
             bflag = 1;
             break;
+        case 'c':
+            cflag = 1;
+            break;
         case 'C':
             Cflag = 1;
             break;
@@ -801,6 +818,8 @@ static int write_f(int argc, char **argv)
         cnt = do_save_vmstate(buf, offset, count, &total);
     } else if (zflag) {
         cnt = do_co_write_zeroes(offset, count, &total);
+    } else if (cflag) {
+        cnt = do_write_compressed(buf, offset, count, &total);
     } else {
         cnt = do_write(buf, offset, count, &total);
     }

From 473c7f0255920bcaf37411990a3725898772817f Mon Sep 17 00:00:00 2001
From: Stefan Priebe 
Date: Fri, 30 Nov 2012 09:55:46 +0100
Subject: [PATCH 1903/2270] rbd: Fix race between aio completition and aio
 cancel

This one fixes a race which qemu had also in iscsi block driver
between cancellation and io completition.

qemu_rbd_aio_cancel was not synchronously waiting for the end of
the command.

To archieve this it introduces a new status flag which uses
-EINPROGRESS.

Signed-off-by: Stefan Priebe 
Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Kevin Wolf 
---
 block/rbd.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/block/rbd.c b/block/rbd.c
index f3becc7a8b..737bab16cc 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -77,6 +77,7 @@ typedef struct RBDAIOCB {
     int error;
     struct BDRVRBDState *s;
     int cancelled;
+    int status;
 } RBDAIOCB;
 
 typedef struct RADOSCB {
@@ -376,12 +377,6 @@ static void qemu_rbd_complete_aio(RADOSCB *rcb)
     RBDAIOCB *acb = rcb->acb;
     int64_t r;
 
-    if (acb->cancelled) {
-        qemu_vfree(acb->bounce);
-        qemu_aio_release(acb);
-        goto done;
-    }
-
     r = rcb->ret;
 
     if (acb->cmd == RBD_AIO_WRITE ||
@@ -409,7 +404,6 @@ static void qemu_rbd_complete_aio(RADOSCB *rcb)
     /* Note that acb->bh can be NULL in case where the aio was cancelled */
     acb->bh = qemu_bh_new(rbd_aio_bh_cb, acb);
     qemu_bh_schedule(acb->bh);
-done:
     g_free(rcb);
 }
 
@@ -568,6 +562,12 @@ static void qemu_rbd_aio_cancel(BlockDriverAIOCB *blockacb)
 {
     RBDAIOCB *acb = (RBDAIOCB *) blockacb;
     acb->cancelled = 1;
+
+    while (acb->status == -EINPROGRESS) {
+        qemu_aio_wait();
+    }
+
+    qemu_aio_release(acb);
 }
 
 static const AIOCBInfo rbd_aiocb_info = {
@@ -639,8 +639,11 @@ static void rbd_aio_bh_cb(void *opaque)
     acb->common.cb(acb->common.opaque, (acb->ret > 0 ? 0 : acb->ret));
     qemu_bh_delete(acb->bh);
     acb->bh = NULL;
+    acb->status = 0;
 
-    qemu_aio_release(acb);
+    if (!acb->cancelled) {
+        qemu_aio_release(acb);
+    }
 }
 
 static int rbd_aio_discard_wrapper(rbd_image_t image,
@@ -685,6 +688,7 @@ static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs,
     acb->s = s;
     acb->cancelled = 0;
     acb->bh = NULL;
+    acb->status = -EINPROGRESS;
 
     if (cmd == RBD_AIO_WRITE) {
         qemu_iovec_to_buf(acb->qiov, 0, acb->bounce, qiov->size);

From fbcad04d6bfdff937536eb23088a01a280a1a3af Mon Sep 17 00:00:00 2001
From: Fabien Chouteau 
Date: Mon, 10 Dec 2012 12:56:22 +0100
Subject: [PATCH 1904/2270] Fix error code checking for SetFilePointer() call

An error has occurred if the return value is invalid_set_file_pointer
and getlasterror doesn't return no_error.

Signed-off-by: Fabien Chouteau 
Acked-by: Stefan Hajnoczi 
---
 block/raw-win32.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/block/raw-win32.c b/block/raw-win32.c
index 0c05c58c5a..ce207a3109 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -303,13 +303,24 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset)
 {
     BDRVRawState *s = bs->opaque;
     LONG low, high;
+    DWORD dwPtrLow;
 
     low = offset;
     high = offset >> 32;
-    if (!SetFilePointer(s->hfile, low, &high, FILE_BEGIN))
-	return -EIO;
-    if (!SetEndOfFile(s->hfile))
+
+    /*
+     * An error has occurred if the return value is INVALID_SET_FILE_POINTER
+     * and GetLastError doesn't return NO_ERROR.
+     */
+    dwPtrLow = SetFilePointer(s->hfile, low, &high, FILE_BEGIN);
+    if (dwPtrLow == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
+        fprintf(stderr, "SetFilePointer error: %d\n", GetLastError());
         return -EIO;
+    }
+    if (SetEndOfFile(s->hfile) == 0) {
+        fprintf(stderr, "SetEndOfFile error: %d\n", GetLastError());
+        return -EIO;
+    }
     return 0;
 }
 

From bf471f7950e9dc9416747b2774eb712f63afe5a7 Mon Sep 17 00:00:00 2001
From: Peter Maydell 
Date: Tue, 11 Dec 2012 11:30:37 +0000
Subject: [PATCH 1905/2270] hw/arm_boot, exynos4210, highbank: Fix secondary
 boot GIC init

Fix the code in the secondary CPU boot stubs so that it correctly
initialises the GIC rather than relying on bugs or implementation
dependent aspects of the QEMU GIC implementation:
 * set the GIC_PMR.Priority field to all-ones, so that all
   interrupts are passed through. The default of all-zeroes
   means all interrupts are masked, and QEMU only booted because
   of a bug in the priority masking in our GIC implementation.
 * add a barrier after GIC setup and before WFI to ensure that
   GIC config is complete before we go into a possible low power
   state. This isn't needed with the software GIC model but could
   be required when using KVM and executing this code on the
   real hardware CPU.

Note that of the three secondary stub implementations, only
the common generic one needs to support both v6 and v7 DSB
encodings; highbank and exynos4210 will always be v7 CPUs.

Signed-off-by: Peter Maydell 
Reviewed-by: Igor Mitsyanko 
---
 hw/arm_boot.c   | 17 ++++++++++++++---
 hw/exynos4210.c | 10 +++++++---
 hw/highbank.c   |  7 +++++--
 3 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index 92e2cab476..ec3b8d5d12 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -44,11 +44,17 @@ static uint32_t bootloader[] = {
  * for an interprocessor interrupt and polling a configurable
  * location for the kernel secondary CPU entry point.
  */
+#define DSB_INSN 0xf57ff04f
+#define CP15_DSB_INSN 0xee070f9a /* mcr cp15, 0, r0, c7, c10, 4 */
+
 static uint32_t smpboot[] = {
-  0xe59f201c, /* ldr r2, gic_cpu_if */
-  0xe59f001c, /* ldr r0, startaddr */
+  0xe59f2028, /* ldr r2, gic_cpu_if */
+  0xe59f0028, /* ldr r0, startaddr */
   0xe3a01001, /* mov r1, #1 */
-  0xe5821000, /* str r1, [r2] */
+  0xe5821000, /* str r1, [r2] - set GICC_CTLR.Enable */
+  0xe3a010ff, /* mov r1, #0xff */
+  0xe5821004, /* str r1, [r2, 4] - set GIC_PMR.Priority to 0xff */
+  DSB_INSN,   /* dsb */
   0xe320f003, /* wfi */
   0xe5901000, /* ldr     r1, [r0] */
   0xe1110001, /* tst     r1, r1 */
@@ -65,6 +71,11 @@ static void default_write_secondary(ARMCPU *cpu,
     smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
     smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
     for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
+        /* Replace DSB with the pre-v7 DSB if necessary. */
+        if (!arm_feature(&cpu->env, ARM_FEATURE_V7) &&
+            smpboot[n] == DSB_INSN) {
+            smpboot[n] = CP15_DSB_INSN;
+        }
         smpboot[n] = tswap32(smpboot[n]);
     }
     rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
diff --git a/hw/exynos4210.c b/hw/exynos4210.c
index 00d4db8871..22148cd946 100644
--- a/hw/exynos4210.c
+++ b/hw/exynos4210.c
@@ -80,12 +80,16 @@ void exynos4210_write_secondary(ARMCPU *cpu,
 {
     int n;
     uint32_t smpboot[] = {
-        0xe59f3024, /* ldr r3, External gic_cpu_if */
-        0xe59f2024, /* ldr r2, Internal gic_cpu_if */
-        0xe59f0024, /* ldr r0, startaddr */
+        0xe59f3034, /* ldr r3, External gic_cpu_if */
+        0xe59f2034, /* ldr r2, Internal gic_cpu_if */
+        0xe59f0034, /* ldr r0, startaddr */
         0xe3a01001, /* mov r1, #1 */
         0xe5821000, /* str r1, [r2] */
         0xe5831000, /* str r1, [r3] */
+        0xe3a010ff, /* mov r1, #0xff */
+        0xe5821004, /* str r1, [r2, #4] */
+        0xe5831004, /* str r1, [r3, #4] */
+        0xf57ff04f, /* dsb */
         0xe320f003, /* wfi */
         0xe5901000, /* ldr     r1, [r0] */
         0xe1110001, /* tst     r1, r1 */
diff --git a/hw/highbank.c b/hw/highbank.c
index afbb005422..447e57d758 100644
--- a/hw/highbank.c
+++ b/hw/highbank.c
@@ -44,9 +44,12 @@ static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
         0xe210000f, /* ands r0, r0, #0x0f */
         0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */
         0xe0830200, /* add r0, r3, r0, lsl #4 */
-        0xe59f2018, /* ldr r2, privbase */
+        0xe59f2024, /* ldr r2, privbase */
         0xe3a01001, /* mov r1, #1 */
-        0xe5821100, /* str r1, [r2, #256] */
+        0xe5821100, /* str r1, [r2, #256] - set GICC_CTLR.Enable */
+        0xe3a010ff, /* mov r1, #0xff */
+        0xe5821104, /* str r1, [r2, #260] - set GICC_PMR.Priority to 0xff */
+        0xf57ff04f, /* dsb */
         0xe320f003, /* wfi */
         0xe5901000, /* ldr     r1, [r0] */
         0xe1110001, /* tst     r1, r1 */

From cad065f18e1ca7694385f42f560da637d4e651b6 Mon Sep 17 00:00:00 2001
From: Peter Maydell 
Date: Tue, 11 Dec 2012 11:30:37 +0000
Subject: [PATCH 1906/2270] hw/arm_gic: Fix comparison with priority mask
 register

The GIC spec states that only interrupts with higher priority
than the value in the GICC_PMR priority mask register are
passed through to the processor. We were incorrectly allowing
through interrupts with a priority equal to the specified
value: correct the comparison operation to match the spec.

Signed-off-by: Peter Maydell 
Reviewed-by: Igor Mitsyanko 
---
 hw/arm_gic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index f9e423f152..672d539996 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -73,7 +73,7 @@ void gic_update(GICState *s)
             }
         }
         level = 0;
-        if (best_prio <= s->priority_mask[cpu]) {
+        if (best_prio < s->priority_mask[cpu]) {
             s->current_pending[cpu] = best_irq;
             if (best_prio < s->running_priority[cpu]) {
                 DPRINTF("Raised pending IRQ %d\n", best_irq);

From ee3f095680e4f578f4f1371a90acc20375b48966 Mon Sep 17 00:00:00 2001
From: Peter Maydell 
Date: Tue, 11 Dec 2012 11:30:37 +0000
Subject: [PATCH 1907/2270] hw/arm_gic_common: Correct GICC_PMR reset value for
 newer GICs

The GIC architecture specification for v1 and v2 GICs (as found
on the Cortex-A9 and newer) states that the GICC_PMR reset value
is zero; this differs from the 0xf0 reset value used on 11MPCore.
The NVIC is different again in not having a CPU interface; since
we share the GIC code we must force the priority mask field to
allow through all interrupts.

Signed-off-by: Peter Maydell 
Reviewed-by: Igor Mitsyanko 
---
 hw/arm_gic_common.c | 6 +++++-
 hw/armv7m_nvic.c    | 4 +++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/hw/arm_gic_common.c b/hw/arm_gic_common.c
index 8369309d21..73ae331807 100644
--- a/hw/arm_gic_common.c
+++ b/hw/arm_gic_common.c
@@ -127,7 +127,11 @@ static void arm_gic_common_reset(DeviceState *dev)
     int i;
     memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
     for (i = 0 ; i < s->num_cpu; i++) {
-        s->priority_mask[i] = 0xf0;
+        if (s->revision == REV_11MPCORE) {
+            s->priority_mask[i] = 0xf0;
+        } else {
+            s->priority_mask[i] = 0;
+        }
         s->current_pending[i] = 1023;
         s->running_irq[i] = 1023;
         s->running_priority[i] = 0x100;
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index f0a2e7b5d2..4963678bf1 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -455,9 +455,11 @@ static void armv7m_nvic_reset(DeviceState *dev)
     nc->parent_reset(dev);
     /* Common GIC reset resets to disabled; the NVIC doesn't have
      * per-CPU interfaces so mark our non-existent CPU interface
-     * as enabled by default.
+     * as enabled by default, and with a priority mask which allows
+     * all interrupts through.
      */
     s->gic.cpu_enabled[0] = 1;
+    s->gic.priority_mask[0] = 0x100;
     /* The NVIC as a whole is always enabled. */
     s->gic.enabled = 1;
     systick_reset(s);

From 79f5d67e9db35d53b478699393590392f7be03ac Mon Sep 17 00:00:00 2001
From: walimis 
Date: Tue, 11 Dec 2012 11:30:37 +0000
Subject: [PATCH 1908/2270] xilinx_zynq: Add one variable to avoid overwriting
 QSPI bus

commit 7b482bcf xilinx_zynq: added QSPI controller

Adds one QSPI controller, which has two spi buses, one is for
spi0, and another is for spi1. But when initializing the spi1
bus, "dev" has been overwrited by the ssi_create_slave_no_init() function,
so that qdev_get_child_bus() returns NULL and the last two m25p80 flashes
won't be attached to the spi1 bus, but to main-system-bus.

Here we add one variable to avoid overwriting.

Signed-off-by: Liming Wang 
Reviewed-by: Peter Crosthwaite 
Signed-off-by: Peter Maydell 
---
 hw/xilinx_zynq.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
index 1f12a3d1ad..49233d8e2e 100644
--- a/hw/xilinx_zynq.c
+++ b/hw/xilinx_zynq.c
@@ -57,6 +57,7 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
     DeviceState *dev;
     SysBusDevice *busdev;
     SSIBus *spi;
+    DeviceState *flash_dev;
     int i, j;
     int num_busses =  is_qspi ? NUM_QSPI_BUSSES : 1;
     int num_ss = is_qspi ? NUM_QSPI_FLASHES : NUM_SPI_FLASHES;
@@ -81,11 +82,11 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
         spi = (SSIBus *)qdev_get_child_bus(dev, bus_name);
 
         for (j = 0; j < num_ss; ++j) {
-            dev = ssi_create_slave_no_init(spi, "m25p80");
-            qdev_prop_set_string(dev, "partname", "n25q128");
-            qdev_init_nofail(dev);
+            flash_dev = ssi_create_slave_no_init(spi, "m25p80");
+            qdev_prop_set_string(flash_dev, "partname", "n25q128");
+            qdev_init_nofail(flash_dev);
 
-            cs_line = qdev_get_gpio_in(dev, 0);
+            cs_line = qdev_get_gpio_in(flash_dev, 0);
             sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line);
         }
     }

From f47b48fb678581d6ee369cfe26b3513100b7d53e Mon Sep 17 00:00:00 2001
From: Daniel Sangorrin 
Date: Tue, 11 Dec 2012 11:30:38 +0000
Subject: [PATCH 1909/2270] hw/arm_gic: fix target CPUs affected by set
 enable/pending ops

Fix a bug on the ARM GIC model where interrupts are not
set pending on the correct target CPUs when they are
triggered by writes to the Interrupt Set Enable or
Set Pending registers.

Signed-off-by: Daniel Sangorrin 
Signed-off-by: Peter Maydell 
---
 hw/arm_gic.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 672d539996..8d769de4f5 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -374,7 +374,8 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
           value = 0xff;
         for (i = 0; i < 8; i++) {
             if (value & (1 << i)) {
-                int mask = (irq < GIC_INTERNAL) ? (1 << cpu) : GIC_TARGET(irq);
+                int mask =
+                    (irq < GIC_INTERNAL) ? (1 << cpu) : GIC_TARGET(irq + i);
                 int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
 
                 if (!GIC_TEST_ENABLED(irq + i, cm)) {
@@ -417,7 +418,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
 
         for (i = 0; i < 8; i++) {
             if (value & (1 << i)) {
-                GIC_SET_PENDING(irq + i, GIC_TARGET(irq));
+                GIC_SET_PENDING(irq + i, GIC_TARGET(irq + i));
             }
         }
     } else if (offset < 0x300) {

From 97331270e50f5858c82a0c6d146da81f5b776535 Mon Sep 17 00:00:00 2001
From: Jean-Christophe DUBOIS 
Date: Mon, 3 Dec 2012 12:55:57 +0000
Subject: [PATCH 1910/2270] exynos4210/mct: Avoid infinite loop on non
 incremental timers

Check for a 0 "distance" value to avoid infinite loop when the
expired FCR timer was not programed with auto-increment.

With this change the behavior is coherent with the same type
of code in the exynos4210_gfrc_restart() function in the same
file.

Linux seems to mostly use this timer with auto-increment
which explain why it is not a problem most of the time.

However other OS might have a problem with this if they
don't use the auto-increment feature.

Signed-off-by: Jean-Christophe DUBOIS 
Reviewed-by: Evgeny Voevodin 
Signed-off-by: Peter Maydell 
---
 hw/exynos4210_mct.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/exynos4210_mct.c b/hw/exynos4210_mct.c
index e79cd6ac01..37dbda92df 100644
--- a/hw/exynos4210_mct.c
+++ b/hw/exynos4210_mct.c
@@ -568,7 +568,7 @@ static void exynos4210_gfrc_event(void *opaque)
     /* Reload FRC to reach nearest comparator */
     s->g_timer.curr_comp = exynos4210_gcomp_find(s);
     distance = exynos4210_gcomp_get_distance(s, s->g_timer.curr_comp);
-    if (distance > MCT_GT_COUNTER_STEP) {
+    if (distance > MCT_GT_COUNTER_STEP || !distance) {
         distance = MCT_GT_COUNTER_STEP;
     }
     exynos4210_gfrc_set_count(&s->g_timer, distance);

From c474ced8fe6684265fbb6a3183eb0cbea561409f Mon Sep 17 00:00:00 2001
From: Dong Xu Wang 
Date: Thu, 6 Dec 2012 14:47:18 +0800
Subject: [PATCH 1911/2270] qemu-option: opt_set(): split it up into more
 functions

The new functions are opts_accepts_any() and find_desc_by_name(), which
are also going to be used by qemu_opts_validate() (see next commit).

This also makes opt_set() slightly more readable.

Signed-off-by: Luiz Capitulino 
Signed-off-by: Dong Xu Wang 
Signed-off-by: Kevin Wolf 
---
 qemu-option.c | 40 ++++++++++++++++++++++++----------------
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/qemu-option.c b/qemu-option.c
index 27891e74e7..375daaa4ad 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -602,26 +602,36 @@ static void qemu_opt_del(QemuOpt *opt)
     g_free(opt);
 }
 
-static void opt_set(QemuOpts *opts, const char *name, const char *value,
-                    bool prepend, Error **errp)
+static bool opts_accepts_any(const QemuOpts *opts)
+{
+    return opts->list->desc[0].name == NULL;
+}
+
+static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
+                                            const char *name)
 {
-    QemuOpt *opt;
-    const QemuOptDesc *desc = opts->list->desc;
-    Error *local_err = NULL;
     int i;
 
     for (i = 0; desc[i].name != NULL; i++) {
         if (strcmp(desc[i].name, name) == 0) {
-            break;
+            return &desc[i];
         }
     }
-    if (desc[i].name == NULL) {
-        if (i == 0) {
-            /* empty list -> allow any */;
-        } else {
-            error_set(errp, QERR_INVALID_PARAMETER, name);
-            return;
-        }
+
+    return NULL;
+}
+
+static void opt_set(QemuOpts *opts, const char *name, const char *value,
+                    bool prepend, Error **errp)
+{
+    QemuOpt *opt;
+    const QemuOptDesc *desc;
+    Error *local_err = NULL;
+
+    desc = find_desc_by_name(opts->list->desc, name);
+    if (!desc && !opts_accepts_any(opts)) {
+        error_set(errp, QERR_INVALID_PARAMETER, name);
+        return;
     }
 
     opt = g_malloc0(sizeof(*opt));
@@ -632,9 +642,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
     } else {
         QTAILQ_INSERT_TAIL(&opts->head, opt, next);
     }
-    if (desc[i].name != NULL) {
-        opt->desc = desc+i;
-    }
+    opt->desc = desc;
     if (value) {
         opt->str = g_strdup(value);
     }

From db97ceba1e17db59188e91b66e61bf84a6a71081 Mon Sep 17 00:00:00 2001
From: Dong Xu Wang 
Date: Thu, 6 Dec 2012 14:47:19 +0800
Subject: [PATCH 1912/2270] qemu-option: qemu_opts_validate(): fix duplicated
 code

Use opts_accepts_any() and find_desc_by_name().

Signed-off-by: Luiz Capitulino 
Signed-off-by: Dong Xu Wang 
Signed-off-by: Kevin Wolf 
---
 qemu-option.c | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/qemu-option.c b/qemu-option.c
index 375daaa4ad..74321bbc13 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -1076,23 +1076,15 @@ void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
     QemuOpt *opt;
     Error *local_err = NULL;
 
-    assert(opts->list->desc[0].name == NULL);
+    assert(opts_accepts_any(opts));
 
     QTAILQ_FOREACH(opt, &opts->head, next) {
-        int i;
-
-        for (i = 0; desc[i].name != NULL; i++) {
-            if (strcmp(desc[i].name, opt->name) == 0) {
-                break;
-            }
-        }
-        if (desc[i].name == NULL) {
+        opt->desc = find_desc_by_name(desc, opt->name);
+        if (!opt->desc) {
             error_set(errp, QERR_INVALID_PARAMETER, opt->name);
             return;
         }
 
-        opt->desc = &desc[i];
-
         qemu_opt_parse(opt, &local_err);
         if (error_is_set(&local_err)) {
             error_propagate(errp, local_err);

From ad718d01ba0af531d10b0a8685cf5047edfd1891 Mon Sep 17 00:00:00 2001
From: Dong Xu Wang 
Date: Thu, 6 Dec 2012 14:47:20 +0800
Subject: [PATCH 1913/2270] qemu-option: qemu_opt_set_bool(): fix code
 duplication

It will set opt->str in qemu_opt_set_bool, without opt->str, there
will be some potential bugs.

These are uses of opt->str, and what happens when it isn't set:

* qemu_opt_get(): returns NULL, which means "not set".  Bug can bite
  when value isn't the default value.

* qemu_opt_parse(): passes NULL to parse_option_bool(), which treats it
  like "on".  Wrong if the value is actually false.  Bug can bite when
  qemu_opts_validate() runs after qemu_opt_set_bool().

* qemu_opt_del(): passes NULL to g_free(), which is just fine.

* qemu_opt_foreach(): passes NULL to the callback, which is unlikely to
  be prepared for it.

* qemu_opts_print(): prints NULL, which crashes on some systems.

* qemu_opts_to_qdict(): passes NULL to qstring_from_str(), which
  crashes.

It also makes qemu_opt_set_bool more readable by using find_desc_by_name
and opts_accepts_any.

It is based on Luiz's patch and uses Markus's comments. Discussions can
be found at:
http://lists.nongnu.org/archive/html/qemu-devel/2012-07/msg02716.html

Signed-off-by: Dong Xu Wang 
Signed-off-by: Kevin Wolf 
---
 qemu-option.c | 29 ++++++++++-------------------
 1 file changed, 10 insertions(+), 19 deletions(-)

diff --git a/qemu-option.c b/qemu-option.c
index 74321bbc13..e0131ce7b1 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -677,30 +677,21 @@ int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
 {
     QemuOpt *opt;
     const QemuOptDesc *desc = opts->list->desc;
-    int i;
-
-    for (i = 0; desc[i].name != NULL; i++) {
-        if (strcmp(desc[i].name, name) == 0) {
-            break;
-        }
-    }
-    if (desc[i].name == NULL) {
-        if (i == 0) {
-            /* empty list -> allow any */;
-        } else {
-            qerror_report(QERR_INVALID_PARAMETER, name);
-            return -1;
-        }
-    }
 
     opt = g_malloc0(sizeof(*opt));
+    opt->desc = find_desc_by_name(desc, name);
+    if (!opt->desc && !opts_accepts_any(opts)) {
+        qerror_report(QERR_INVALID_PARAMETER, name);
+        g_free(opt);
+        return -1;
+    }
+
     opt->name = g_strdup(name);
     opt->opts = opts;
-    QTAILQ_INSERT_TAIL(&opts->head, opt, next);
-    if (desc[i].name != NULL) {
-        opt->desc = desc+i;
-    }
     opt->value.boolean = !!val;
+    opt->str = g_strdup(val ? "on" : "off");
+    QTAILQ_INSERT_TAIL(&opts->head, opt, next);
+
     return 0;
 }
 

From dd39244978627e41a66b98d20eceddb1d7d25def Mon Sep 17 00:00:00 2001
From: Dong Xu Wang 
Date: Thu, 6 Dec 2012 14:47:21 +0800
Subject: [PATCH 1914/2270] introduce qemu_opts_create_nofail function

While id is NULL, qemu_opts_create can not fail, so ignore
errors is fine.

Signed-off-by: Dong Xu Wang 
Signed-off-by: Kevin Wolf 
---
 qemu-option.c | 9 +++++++++
 qemu-option.h | 1 +
 2 files changed, 10 insertions(+)

diff --git a/qemu-option.c b/qemu-option.c
index e0131ce7b1..1303188dbd 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -780,6 +780,15 @@ QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
     return opts;
 }
 
+QemuOpts *qemu_opts_create_nofail(QemuOptsList *list)
+{
+    QemuOpts *opts;
+    Error *errp = NULL;
+    opts = qemu_opts_create(list, NULL, 0, &errp);
+    assert_no_error(errp);
+    return opts;
+}
+
 void qemu_opts_reset(QemuOptsList *list)
 {
     QemuOpts *opts, *next_opts;
diff --git a/qemu-option.h b/qemu-option.h
index ca729862d5..b0f8d1ecd6 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -133,6 +133,7 @@ int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
 QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id);
 QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
                            int fail_if_exists, Error **errp);
+QemuOpts *qemu_opts_create_nofail(QemuOptsList *list);
 void qemu_opts_reset(QemuOptsList *list);
 void qemu_opts_loc_restore(QemuOpts *opts);
 int qemu_opts_set(QemuOptsList *list, const char *id,

From e478b448d7c36046462733ffaeaea0961575790a Mon Sep 17 00:00:00 2001
From: Dong Xu Wang 
Date: Thu, 6 Dec 2012 14:47:22 +0800
Subject: [PATCH 1915/2270] use qemu_opts_create_nofail

We will use qemu_opts_create_nofail function, it can make code
more readable.

Signed-off-by: Dong Xu Wang 
Signed-off-by: Kevin Wolf 
---
 blockdev.c     |  2 +-
 hw/watchdog.c  |  2 +-
 qemu-config.c  |  4 ++--
 qemu-img.c     |  2 +-
 qemu-sockets.c | 16 ++++++++--------
 vl.c           | 12 +++++-------
 6 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 463f4c2094..9a05e57009 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -568,7 +568,7 @@ DriveInfo *drive_init(QemuOpts *opts, BlockInterfaceType block_default_type)
         break;
     case IF_VIRTIO:
         /* add virtio block device */
-        opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0, NULL);
+        opts = qemu_opts_create_nofail(qemu_find_opts("device"));
         if (arch_type == QEMU_ARCH_S390X) {
             qemu_opt_set(opts, "driver", "virtio-blk-s390");
         } else {
diff --git a/hw/watchdog.c b/hw/watchdog.c
index b52acedd98..5c82c17d09 100644
--- a/hw/watchdog.c
+++ b/hw/watchdog.c
@@ -66,7 +66,7 @@ int select_watchdog(const char *p)
     QLIST_FOREACH(model, &watchdog_list, entry) {
         if (strcasecmp(model->wdt_name, p) == 0) {
             /* add the device */
-            opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0, NULL);
+            opts = qemu_opts_create_nofail(qemu_find_opts("device"));
             qemu_opt_set(opts, "driver", p);
             return 0;
         }
diff --git a/qemu-config.c b/qemu-config.c
index aa78fb9ea7..54db9813e8 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -756,7 +756,7 @@ int qemu_global_option(const char *str)
         return -1;
     }
 
-    opts = qemu_opts_create(&qemu_global_opts, NULL, 0, NULL);
+    opts = qemu_opts_create_nofail(&qemu_global_opts);
     qemu_opt_set(opts, "driver", driver);
     qemu_opt_set(opts, "property", property);
     qemu_opt_set(opts, "value", str+offset+1);
@@ -843,7 +843,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
                 error_free(local_err);
                 goto out;
             }
-            opts = qemu_opts_create(list, NULL, 0, NULL);
+            opts = qemu_opts_create_nofail(list);
             continue;
         }
         if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
diff --git a/qemu-img.c b/qemu-img.c
index c4dae88e84..c989a52564 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1934,7 +1934,7 @@ static int img_resize(int argc, char **argv)
     }
 
     /* Parse size */
-    param = qemu_opts_create(&resize_options, NULL, 0, NULL);
+    param = qemu_opts_create_nofail(&resize_options);
     if (qemu_opt_set(param, BLOCK_OPT_SIZE, size)) {
         /* Error message already printed when size parsing fails */
         ret = -1;
diff --git a/qemu-sockets.c b/qemu-sockets.c
index d314cf1d1b..c52a40a411 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -579,7 +579,7 @@ int inet_listen(const char *str, char *ostr, int olen,
 
     addr = inet_parse(str, errp);
     if (addr != NULL) {
-        opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
+        opts = qemu_opts_create_nofail(&dummy_opts);
         inet_addr_to_opts(opts, addr);
         qapi_free_InetSocketAddress(addr);
         sock = inet_listen_opts(opts, port_offset, errp);
@@ -618,7 +618,7 @@ int inet_connect(const char *str, Error **errp)
 
     addr = inet_parse(str, errp);
     if (addr != NULL) {
-        opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
+        opts = qemu_opts_create_nofail(&dummy_opts);
         inet_addr_to_opts(opts, addr);
         qapi_free_InetSocketAddress(addr);
         sock = inet_connect_opts(opts, errp, NULL, NULL);
@@ -652,7 +652,7 @@ int inet_nonblocking_connect(const char *str,
 
     addr = inet_parse(str, errp);
     if (addr != NULL) {
-        opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
+        opts = qemu_opts_create_nofail(&dummy_opts);
         inet_addr_to_opts(opts, addr);
         qapi_free_InetSocketAddress(addr);
         sock = inet_connect_opts(opts, errp, callback, opaque);
@@ -795,7 +795,7 @@ int unix_listen(const char *str, char *ostr, int olen, Error **errp)
     char *path, *optstr;
     int sock, len;
 
-    opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
+    opts = qemu_opts_create_nofail(&dummy_opts);
 
     optstr = strchr(str, ',');
     if (optstr) {
@@ -823,7 +823,7 @@ int unix_connect(const char *path, Error **errp)
     QemuOpts *opts;
     int sock;
 
-    opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
+    opts = qemu_opts_create_nofail(&dummy_opts);
     qemu_opt_set(opts, "path", path);
     sock = unix_connect_opts(opts, errp, NULL, NULL);
     qemu_opts_del(opts);
@@ -840,7 +840,7 @@ int unix_nonblocking_connect(const char *path,
 
     g_assert(callback != NULL);
 
-    opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
+    opts = qemu_opts_create_nofail(&dummy_opts);
     qemu_opt_set(opts, "path", path);
     sock = unix_connect_opts(opts, errp, callback, opaque);
     qemu_opts_del(opts);
@@ -891,7 +891,7 @@ int socket_connect(SocketAddress *addr, Error **errp,
     QemuOpts *opts;
     int fd;
 
-    opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
+    opts = qemu_opts_create_nofail(&dummy_opts);
     switch (addr->kind) {
     case SOCKET_ADDRESS_KIND_INET:
         inet_addr_to_opts(opts, addr->inet);
@@ -922,7 +922,7 @@ int socket_listen(SocketAddress *addr, Error **errp)
     QemuOpts *opts;
     int fd;
 
-    opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
+    opts = qemu_opts_create_nofail(&dummy_opts);
     switch (addr->kind) {
     case SOCKET_ADDRESS_KIND_INET:
         inet_addr_to_opts(opts, addr->inet);
diff --git a/vl.c b/vl.c
index 6b3827cf06..3ebf01f8f1 100644
--- a/vl.c
+++ b/vl.c
@@ -1996,7 +1996,7 @@ static int balloon_parse(const char *arg)
                 return  -1;
         } else {
             /* create empty opts */
-            opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0, NULL);
+            opts = qemu_opts_create_nofail(qemu_find_opts("device"));
         }
         qemu_opt_set(opts, "driver", "virtio-balloon");
         return 0;
@@ -2246,14 +2246,14 @@ static int virtcon_parse(const char *devname)
         exit(1);
     }
 
-    bus_opts = qemu_opts_create(device, NULL, 0, NULL);
+    bus_opts = qemu_opts_create_nofail(device);
     if (arch_type == QEMU_ARCH_S390X) {
         qemu_opt_set(bus_opts, "driver", "virtio-serial-s390");
     } else {
         qemu_opt_set(bus_opts, "driver", "virtio-serial-pci");
     } 
 
-    dev_opts = qemu_opts_create(device, NULL, 0, NULL);
+    dev_opts = qemu_opts_create_nofail(device);
     qemu_opt_set(dev_opts, "driver", "virtconsole");
 
     snprintf(label, sizeof(label), "virtcon%d", index);
@@ -3105,8 +3105,7 @@ int main(int argc, char **argv, char **envp)
 
                 qemu_opt_set_bool(fsdev, "readonly",
                                 qemu_opt_get_bool(opts, "readonly", 0));
-                device = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
-                                          NULL);
+                device = qemu_opts_create_nofail(qemu_find_opts("device"));
                 qemu_opt_set(device, "driver", "virtio-9p-pci");
                 qemu_opt_set(device, "fsdev",
                              qemu_opt_get(opts, "mount_tag"));
@@ -3126,8 +3125,7 @@ int main(int argc, char **argv, char **envp)
                 }
                 qemu_opt_set(fsdev, "fsdriver", "synth");
 
-                device = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
-                                          NULL);
+                device = qemu_opts_create_nofail(qemu_find_opts("device"));
                 qemu_opt_set(device, "driver", "virtio-9p-pci");
                 qemu_opt_set(device, "fsdev", "v_synth");
                 qemu_opt_set(device, "mount_tag", "v_synth");

From b83c18e225cf82a21535561270b6dfd86b1c9031 Mon Sep 17 00:00:00 2001
From: Dong Xu Wang 
Date: Thu, 6 Dec 2012 14:47:23 +0800
Subject: [PATCH 1916/2270] create new function: qemu_opt_set_number

Signed-off-by: Dong Xu Wang 
Signed-off-by: Kevin Wolf 
---
 qemu-option.c | 22 ++++++++++++++++++++++
 qemu-option.h |  1 +
 2 files changed, 23 insertions(+)

diff --git a/qemu-option.c b/qemu-option.c
index 1303188dbd..94557cfde7 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -695,6 +695,28 @@ int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
     return 0;
 }
 
+int qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val)
+{
+    QemuOpt *opt;
+    const QemuOptDesc *desc = opts->list->desc;
+
+    opt = g_malloc0(sizeof(*opt));
+    opt->desc = find_desc_by_name(desc, name);
+    if (!opt->desc && !opts_accepts_any(opts)) {
+        qerror_report(QERR_INVALID_PARAMETER, name);
+        g_free(opt);
+        return -1;
+    }
+
+    opt->name = g_strdup(name);
+    opt->opts = opts;
+    opt->value.uint = val;
+    opt->str = g_strdup_printf("%" PRId64, val);
+    QTAILQ_INSERT_TAIL(&opts->head, opt, next);
+
+    return 0;
+}
+
 int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
                      int abort_on_failure)
 {
diff --git a/qemu-option.h b/qemu-option.h
index b0f8d1ecd6..002dd07ee5 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -126,6 +126,7 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
 void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
                       Error **errp);
 int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val);
+int qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val);
 typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void *opaque);
 int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
                      int abort_on_failure);

From 312a2ba0eb8ab19646517aeaa785475d3fbcfd51 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Thu, 6 Dec 2012 14:32:55 +0100
Subject: [PATCH 1917/2270] blkdebug: Allow usage without config file

As soon as new rules can be set during runtime, as introduced by the
next patch, blkdebug makes sense even without a config file.

Signed-off-by: Kevin Wolf 
---
 block/blkdebug.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/block/blkdebug.c b/block/blkdebug.c
index d61ece86a9..c9041ec3d2 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -240,6 +240,11 @@ static int read_config(BDRVBlkdebugState *s, const char *filename)
     int ret;
     struct add_rule_data d;
 
+    /* Allow usage without config file */
+    if (!*filename) {
+        return 0;
+    }
+
     f = fopen(filename, "r");
     if (f == NULL) {
         return -errno;

From 9e35542b0fc3871caac15ccd57548b99df2c94b7 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Thu, 6 Dec 2012 14:32:56 +0100
Subject: [PATCH 1918/2270] blkdebug: Factor out remove_rule()

The cleanup work to remove a rule depends on the type of the rule. It's
easy for the existing rules as there is no data that must be cleaned up
and is specific to a type yet, but the next patch will change this.

Signed-off-by: Kevin Wolf 
---
 block/blkdebug.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/block/blkdebug.c b/block/blkdebug.c
index c9041ec3d2..859792b647 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -234,6 +234,18 @@ static int add_rule(QemuOpts *opts, void *opaque)
     return 0;
 }
 
+static void remove_rule(BlkdebugRule *rule)
+{
+    switch (rule->action) {
+    case ACTION_INJECT_ERROR:
+    case ACTION_SET_STATE:
+        break;
+    }
+
+    QLIST_REMOVE(rule, next);
+    g_free(rule);
+}
+
 static int read_config(BDRVBlkdebugState *s, const char *filename)
 {
     FILE *f;
@@ -402,8 +414,7 @@ static void blkdebug_close(BlockDriverState *bs)
 
     for (i = 0; i < BLKDBG_EVENT_MAX; i++) {
         QLIST_FOREACH_SAFE(rule, &s->rules[i], next, next) {
-            QLIST_REMOVE(rule, next);
-            g_free(rule);
+            remove_rule(rule);
         }
     }
 }

From 3c90c65d7adab49a41952ee14e1d65f81355e408 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Thu, 6 Dec 2012 14:32:57 +0100
Subject: [PATCH 1919/2270] blkdebug: Implement suspend/resume of AIO requests

This allows more systematic AIO testing. The patch adds three new
operations to blkdebug:

 * Setting a "breakpoint" on a blkdebug event. The next request that
   triggers this breakpoint is suspended and is tagged with a name.
   The breakpoint is removed after a request has triggered it.

 * A suspended request (identified by it's tag) can be resumed

 * It's possible to check whether a suspended request with a given
   tag exists. This can be used for waiting for an event.

Ideally, we would instead tag requests right when they are created and
set breakpoints for individual requests. However, at this point the
block layer doesn't allow this easily, and breakpoints that trigger for
any request already allow a lot of useful testing.

Signed-off-by: Kevin Wolf 
---
 block/blkdebug.c | 108 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 105 insertions(+), 3 deletions(-)

diff --git a/block/blkdebug.c b/block/blkdebug.c
index 859792b647..294e983306 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -29,8 +29,10 @@
 typedef struct BDRVBlkdebugState {
     int state;
     int new_state;
+
     QLIST_HEAD(, BlkdebugRule) rules[BLKDBG_EVENT_MAX];
     QSIMPLEQ_HEAD(, BlkdebugRule) active_rules;
+    QLIST_HEAD(, BlkdebugSuspendedReq) suspended_reqs;
 } BDRVBlkdebugState;
 
 typedef struct BlkdebugAIOCB {
@@ -39,6 +41,12 @@ typedef struct BlkdebugAIOCB {
     int ret;
 } BlkdebugAIOCB;
 
+typedef struct BlkdebugSuspendedReq {
+    Coroutine *co;
+    char *tag;
+    QLIST_ENTRY(BlkdebugSuspendedReq) next;
+} BlkdebugSuspendedReq;
+
 static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb);
 
 static const AIOCBInfo blkdebug_aiocb_info = {
@@ -49,6 +57,7 @@ static const AIOCBInfo blkdebug_aiocb_info = {
 enum {
     ACTION_INJECT_ERROR,
     ACTION_SET_STATE,
+    ACTION_SUSPEND,
 };
 
 typedef struct BlkdebugRule {
@@ -65,6 +74,9 @@ typedef struct BlkdebugRule {
         struct {
             int new_state;
         } set_state;
+        struct {
+            char *tag;
+        } suspend;
     } options;
     QLIST_ENTRY(BlkdebugRule) next;
     QSIMPLEQ_ENTRY(BlkdebugRule) active_next;
@@ -226,6 +238,11 @@ static int add_rule(QemuOpts *opts, void *opaque)
         rule->options.set_state.new_state =
             qemu_opt_get_number(opts, "new_state", 0);
         break;
+
+    case ACTION_SUSPEND:
+        rule->options.suspend.tag =
+            g_strdup(qemu_opt_get(opts, "tag"));
+        break;
     };
 
     /* Add the rule */
@@ -240,6 +257,9 @@ static void remove_rule(BlkdebugRule *rule)
     case ACTION_INJECT_ERROR:
     case ACTION_SET_STATE:
         break;
+    case ACTION_SUSPEND:
+        g_free(rule->options.suspend.tag);
+        break;
     }
 
     QLIST_REMOVE(rule, next);
@@ -406,6 +426,7 @@ static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
     return bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
 }
 
+
 static void blkdebug_close(BlockDriverState *bs)
 {
     BDRVBlkdebugState *s = bs->opaque;
@@ -419,6 +440,27 @@ static void blkdebug_close(BlockDriverState *bs)
     }
 }
 
+static void suspend_request(BlockDriverState *bs, BlkdebugRule *rule)
+{
+    BDRVBlkdebugState *s = bs->opaque;
+    BlkdebugSuspendedReq r;
+
+    r = (BlkdebugSuspendedReq) {
+        .co         = qemu_coroutine_self(),
+        .tag        = g_strdup(rule->options.suspend.tag),
+    };
+
+    remove_rule(rule);
+    QLIST_INSERT_HEAD(&s->suspended_reqs, &r, next);
+
+    printf("blkdebug: Suspended request '%s'\n", r.tag);
+    qemu_coroutine_yield();
+    printf("blkdebug: Resuming request '%s'\n", r.tag);
+
+    QLIST_REMOVE(&r, next);
+    g_free(r.tag);
+}
+
 static bool process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
     bool injected)
 {
@@ -442,6 +484,10 @@ static bool process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
     case ACTION_SET_STATE:
         s->new_state = rule->options.set_state.new_state;
         break;
+
+    case ACTION_SUSPEND:
+        suspend_request(bs, rule);
+        break;
     }
     return injected;
 }
@@ -449,19 +495,72 @@ static bool process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
 static void blkdebug_debug_event(BlockDriverState *bs, BlkDebugEvent event)
 {
     BDRVBlkdebugState *s = bs->opaque;
-    struct BlkdebugRule *rule;
+    struct BlkdebugRule *rule, *next;
     bool injected;
 
     assert((int)event >= 0 && event < BLKDBG_EVENT_MAX);
 
     injected = false;
     s->new_state = s->state;
-    QLIST_FOREACH(rule, &s->rules[event], next) {
+    QLIST_FOREACH_SAFE(rule, &s->rules[event], next, next) {
         injected = process_rule(bs, rule, injected);
     }
     s->state = s->new_state;
 }
 
+static int blkdebug_debug_breakpoint(BlockDriverState *bs, const char *event,
+                                     const char *tag)
+{
+    BDRVBlkdebugState *s = bs->opaque;
+    struct BlkdebugRule *rule;
+    BlkDebugEvent blkdebug_event;
+
+    if (get_event_by_name(event, &blkdebug_event) < 0) {
+        return -ENOENT;
+    }
+
+
+    rule = g_malloc(sizeof(*rule));
+    *rule = (struct BlkdebugRule) {
+        .event  = blkdebug_event,
+        .action = ACTION_SUSPEND,
+        .state  = 0,
+        .options.suspend.tag = g_strdup(tag),
+    };
+
+    QLIST_INSERT_HEAD(&s->rules[blkdebug_event], rule, next);
+
+    return 0;
+}
+
+static int blkdebug_debug_resume(BlockDriverState *bs, const char *tag)
+{
+    BDRVBlkdebugState *s = bs->opaque;
+    BlkdebugSuspendedReq *r;
+
+    QLIST_FOREACH(r, &s->suspended_reqs, next) {
+        if (!strcmp(r->tag, tag)) {
+            qemu_coroutine_enter(r->co, NULL);
+            return 0;
+        }
+    }
+    return -ENOENT;
+}
+
+
+static bool blkdebug_debug_is_suspended(BlockDriverState *bs, const char *tag)
+{
+    BDRVBlkdebugState *s = bs->opaque;
+    BlkdebugSuspendedReq *r;
+
+    QLIST_FOREACH(r, &s->suspended_reqs, next) {
+        if (!strcmp(r->tag, tag)) {
+            return true;
+        }
+    }
+    return false;
+}
+
 static int64_t blkdebug_getlength(BlockDriverState *bs)
 {
     return bdrv_getlength(bs->file);
@@ -480,7 +579,10 @@ static BlockDriver bdrv_blkdebug = {
     .bdrv_aio_readv     = blkdebug_aio_readv,
     .bdrv_aio_writev    = blkdebug_aio_writev,
 
-    .bdrv_debug_event   = blkdebug_debug_event,
+    .bdrv_debug_event           = blkdebug_debug_event,
+    .bdrv_debug_breakpoint      = blkdebug_debug_breakpoint,
+    .bdrv_debug_resume          = blkdebug_debug_resume,
+    .bdrv_debug_is_suspended    = blkdebug_debug_is_suspended,
 };
 
 static void bdrv_blkdebug_init(void)

From 41c695c749b84d40e53e64faadedc0392aaea07e Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Thu, 6 Dec 2012 14:32:58 +0100
Subject: [PATCH 1920/2270] qemu-io: Add AIO debugging commands

This makes the blkdebug suspend/resume functionality available in
qemu-io. Use it like this:

  $ ./qemu-io blkdebug::/tmp/test.qcow2
  qemu-io> break write_aio req_a
  qemu-io> aio_write 0 4k
  qemu-io> blkdebug: Suspended request 'req_a'
  qemu-io> resume req_a
  blkdebug: Resuming request 'req_a'
  qemu-io> wrote 4096/4096 bytes at offset 0
  4 KiB, 1 ops; 0:00:30.71 (133.359788 bytes/sec and 0.0326 ops/sec)

Signed-off-by: Kevin Wolf 
---
 block.c     | 39 ++++++++++++++++++++++++++++++++
 block.h     |  5 +++++
 block_int.h |  6 +++++
 qemu-io.c   | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 114 insertions(+)

diff --git a/block.c b/block.c
index b3faf3a463..0668c4be17 100644
--- a/block.c
+++ b/block.c
@@ -3045,7 +3045,46 @@ void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event)
     }
 
     drv->bdrv_debug_event(bs, event);
+}
 
+int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
+                          const char *tag)
+{
+    while (bs && bs->drv && !bs->drv->bdrv_debug_breakpoint) {
+        bs = bs->file;
+    }
+
+    if (bs && bs->drv && bs->drv->bdrv_debug_breakpoint) {
+        return bs->drv->bdrv_debug_breakpoint(bs, event, tag);
+    }
+
+    return -ENOTSUP;
+}
+
+int bdrv_debug_resume(BlockDriverState *bs, const char *tag)
+{
+    while (bs && bs->drv && !bs->drv->bdrv_debug_resume) {
+        bs = bs->file;
+    }
+
+    if (bs && bs->drv && bs->drv->bdrv_debug_resume) {
+        return bs->drv->bdrv_debug_resume(bs, tag);
+    }
+
+    return -ENOTSUP;
+}
+
+bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag)
+{
+    while (bs && bs->drv && !bs->drv->bdrv_debug_is_suspended) {
+        bs = bs->file;
+    }
+
+    if (bs && bs->drv && bs->drv->bdrv_debug_is_suspended) {
+        return bs->drv->bdrv_debug_is_suspended(bs, tag);
+    }
+
+    return false;
 }
 
 /**************************************************************/
diff --git a/block.h b/block.h
index 24bea09530..893448a5fc 100644
--- a/block.h
+++ b/block.h
@@ -431,4 +431,9 @@ typedef enum {
 #define BLKDBG_EVENT(bs, evt) bdrv_debug_event(bs, evt)
 void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event);
 
+int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
+                           const char *tag);
+int bdrv_debug_resume(BlockDriverState *bs, const char *tag);
+bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag);
+
 #endif
diff --git a/block_int.h b/block_int.h
index 9deedb811a..bf3f79b3db 100644
--- a/block_int.h
+++ b/block_int.h
@@ -190,6 +190,12 @@ struct BlockDriver {
 
     void (*bdrv_debug_event)(BlockDriverState *bs, BlkDebugEvent event);
 
+    /* TODO Better pass a option string/QDict/QemuOpts to add any rule? */
+    int (*bdrv_debug_breakpoint)(BlockDriverState *bs, const char *event,
+        const char *tag);
+    int (*bdrv_debug_resume)(BlockDriverState *bs, const char *tag);
+    bool (*bdrv_debug_is_suspended)(BlockDriverState *bs, const char *tag);
+
     /*
      * Returns 1 if newly created images are guaranteed to contain only
      * zeros, 0 otherwise.
diff --git a/qemu-io.c b/qemu-io.c
index b4b0898741..1637773302 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1671,6 +1671,67 @@ static const cmdinfo_t map_cmd = {
        .oneline        = "prints the allocated areas of a file",
 };
 
+static int break_f(int argc, char **argv)
+{
+    int ret;
+
+    ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
+    if (ret < 0) {
+        printf("Could not set breakpoint: %s\n", strerror(-ret));
+    }
+
+    return 0;
+}
+
+static const cmdinfo_t break_cmd = {
+       .name           = "break",
+       .argmin         = 2,
+       .argmax         = 2,
+       .cfunc          = break_f,
+       .args           = "event tag",
+       .oneline        = "sets a breakpoint on event and tags the stopped "
+                         "request as tag",
+};
+
+static int resume_f(int argc, char **argv)
+{
+    int ret;
+
+    ret = bdrv_debug_resume(bs, argv[1]);
+    if (ret < 0) {
+        printf("Could not resume request: %s\n", strerror(-ret));
+    }
+
+    return 0;
+}
+
+static const cmdinfo_t resume_cmd = {
+       .name           = "resume",
+       .argmin         = 1,
+       .argmax         = 1,
+       .cfunc          = resume_f,
+       .args           = "tag",
+       .oneline        = "resumes the request tagged as tag",
+};
+
+static int wait_break_f(int argc, char **argv)
+{
+    while (!bdrv_debug_is_suspended(bs, argv[1])) {
+        qemu_aio_wait();
+    }
+
+    return 0;
+}
+
+static const cmdinfo_t wait_break_cmd = {
+       .name           = "wait_break",
+       .argmin         = 1,
+       .argmax         = 1,
+       .cfunc          = wait_break_f,
+       .args           = "tag",
+       .oneline        = "waits for the suspension of a request",
+};
+
 static int abort_f(int argc, char **argv)
 {
     abort();
@@ -1934,6 +1995,9 @@ int main(int argc, char **argv)
     add_command(&discard_cmd);
     add_command(&alloc_cmd);
     add_command(&map_cmd);
+    add_command(&break_cmd);
+    add_command(&resume_cmd);
+    add_command(&wait_break_cmd);
     add_command(&abort_cmd);
 
     add_args_command(init_args_command);

From 67a7a0ebe5ef0f337d5f7e7e618b08c562a55da0 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Thu, 6 Dec 2012 14:32:59 +0100
Subject: [PATCH 1921/2270] qcow2: Move BLKDBG_EVENT out of the lock

We want to use these events to suspend requests for testing concurrent
AIO requests. Suspending requests while they are holding the CoMutex is
rather boring for this purpose.

Signed-off-by: Kevin Wolf 
---
 block/qcow2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index c1ff31f482..0a08ec74c7 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -835,8 +835,8 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
                 cur_nr_sectors * 512);
         }
 
-        BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
         qemu_co_mutex_unlock(&s->lock);
+        BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
         trace_qcow2_writev_data(qemu_coroutine_self(),
                                 (cluster_offset >> 9) + index_in_cluster);
         ret = bdrv_co_writev(bs->file,

From 91d4093dce58e343e2336324794daa93517b86c2 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Thu, 6 Dec 2012 14:33:00 +0100
Subject: [PATCH 1922/2270] qemu-iotests: Test concurrent cluster allocations

This adds some first tests for qcow2's dependency handling when two
parallel write requests access the same cluster.

Signed-off-by: Kevin Wolf 
---
 tests/qemu-iotests/046     | 215 +++++++++++++++++++++++++++++++++++++
 tests/qemu-iotests/046.out | 163 ++++++++++++++++++++++++++++
 tests/qemu-iotests/group   |   1 +
 3 files changed, 379 insertions(+)
 create mode 100755 tests/qemu-iotests/046
 create mode 100644 tests/qemu-iotests/046.out

diff --git a/tests/qemu-iotests/046 b/tests/qemu-iotests/046
new file mode 100755
index 0000000000..e0176f42df
--- /dev/null
+++ b/tests/qemu-iotests/046
@@ -0,0 +1,215 @@
+#!/bin/bash
+#
+# Test concurrent cluster allocations
+#
+# Copyright (C) 2012 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 .
+#
+
+# 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
+
+CLUSTER_SIZE=64k
+size=128M
+
+echo
+echo "== creating backing file for COW tests =="
+
+_make_test_img $size
+
+function backing_io()
+{
+    local offset=$1
+    local sectors=$2
+    local op=$3
+    local pattern=0
+    local cur_sec=0
+
+    for i in $(seq 0 $((sectors - 1))); do
+        cur_sec=$((offset / 65536 + i))
+        pattern=$(( ( (cur_sec % 128) + (cur_sec / 128)) % 128 ))
+
+        echo "$op -P $pattern $((cur_sec * 64))k 64k"
+    done
+}
+
+backing_io 0 16 write | $QEMU_IO $TEST_IMG | _filter_qemu_io
+
+mv $TEST_IMG $TEST_IMG.base
+
+_make_test_img -b $TEST_IMG.base 6G
+
+echo
+echo "== Some concurrent requests touching the same cluster =="
+
+function overlay_io()
+{
+# Allocate middle of cluster 1, then write to somewhere before and after it
+cat  < wrote 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 65536
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 131072
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 196608
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 262144
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 327680
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 393216
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 458752
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 524288
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 589824
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 655360
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 720896
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 786432
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 851968
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 917504
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 983040
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' 
+
+== Some concurrent requests touching the same cluster ==
+qemu-io> qemu-io> qemu-io> blkdebug: Suspended request 'A'
+qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> blkdebug: Resuming request 'A'
+qemu-io> wrote 8192/8192 bytes at offset XXX
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 8192/8192 bytes at offset XXX
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 8192/8192 bytes at offset XXX
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-io> blkdebug: Suspended request 'A'
+qemu-io> qemu-io> qemu-io> blkdebug: Resuming request 'A'
+qemu-io> wrote 8192/8192 bytes at offset XXX
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset XXX
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-io> blkdebug: Suspended request 'A'
+qemu-io> qemu-io> qemu-io> blkdebug: Resuming request 'A'
+qemu-io> wrote 8192/8192 bytes at offset XXX
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset XXX
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 32768/32768 bytes at offset XXX
+32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-io> qemu-io> blkdebug: Suspended request 'A'
+qemu-io> qemu-io> qemu-io> blkdebug: Resuming request 'A'
+qemu-io> wrote 8192/8192 bytes at offset XXX
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 57344/57344 bytes at offset XXX
+56 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 4096/4096 bytes at offset XXX
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 32768/32768 bytes at offset XXX
+32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-io> discard 65536/65536 bytes at offset XXX
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-io> qemu-io> blkdebug: Suspended request 'A'
+qemu-io> qemu-io> qemu-io> blkdebug: Resuming request 'A'
+qemu-io> wrote 8192/8192 bytes at offset XXX
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 57344/57344 bytes at offset XXX
+56 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 4096/4096 bytes at offset XXX
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset XXX
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-io> discard 65536/65536 bytes at offset XXX
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-io> qemu-io> blkdebug: Suspended request 'A'
+qemu-io> qemu-io> qemu-io> blkdebug: Resuming request 'A'
+qemu-io> wrote 8192/8192 bytes at offset XXX
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 57344/57344 bytes at offset XXX
+56 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> 
+== Verify image content ==
+qemu-io> read 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 65536
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 73728
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 16384/16384 bytes at offset 81920
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 98304
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 106496
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 114688
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 122880
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 32768/32768 bytes at offset 131072
+32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 163840
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 65536/65536 bytes at offset 172032
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 24576/24576 bytes at offset 237568
+24 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 32768/32768 bytes at offset 262144
+32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 294912
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 303104
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 65536/65536 bytes at offset 311296
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 16384/16384 bytes at offset 376832
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 24576/24576 bytes at offset 393216
+24 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 417792
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 425984
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 57344/57344 bytes at offset 434176
+56 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 24576/24576 bytes at offset 491520
+24 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 516096
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 24576/24576 bytes at offset 524288
+24 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 548864
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 557056
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 57344/57344 bytes at offset 565248
+56 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 24576/24576 bytes at offset 622592
+24 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 647168
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 24576/24576 bytes at offset 655360
+24 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 679936
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 688128
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 57344/57344 bytes at offset 696320
+56 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 32768/32768 bytes at offset 753664
+32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> No errors were found on the image.
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 5b39785461..a0307de06b 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -52,3 +52,4 @@
 043 rw auto backing
 044 rw auto
 045 rw auto
+046 rw auto aio

From 7ec81e56edc2b2007ce0ae3982aa5c18af9546ab Mon Sep 17 00:00:00 2001
From: David Gibson 
Date: Tue, 4 Dec 2012 11:38:38 +1100
Subject: [PATCH 1923/2270] Fix off-by-1 error in RAM migration code

The code for migrating (or savevm-ing) memory pages starts off by creating
a dirty bitmap and filling it with 1s.  Except, actually, because bit
addresses are 0-based it fills every bit except bit 0 with 1s and puts an
extra 1 beyond the end of the bitmap, potentially corrupting unrelated
memory.  Oops.  This patch fixes it.

Signed-off-by: David Gibson 
Signed-off-by: Anthony Liguori 
---
 arch_init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch_init.c b/arch_init.c
index e6effe809a..b75a4c5580 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -568,7 +568,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
     int64_t ram_pages = last_ram_offset() >> TARGET_PAGE_BITS;
 
     migration_bitmap = bitmap_new(ram_pages);
-    bitmap_set(migration_bitmap, 1, ram_pages);
+    bitmap_set(migration_bitmap, 0, ram_pages);
     migration_dirty_pages = ram_pages;
 
     bytes_transferred = 0;

From 45e6cee42b98d10e2e14885ab656541a9ffd5187 Mon Sep 17 00:00:00 2001
From: David Gibson 
Date: Tue, 4 Dec 2012 11:38:39 +1100
Subject: [PATCH 1924/2270] migration: Fix madvise breakage if host and guest
 have different page sizes

madvise(DONTNEED) will throw away the contents of the whole page at the
given address, even if the given length is less than the page size.  One
can argue about whether that's the correct behaviour, but that's what it's
done for a long time in Linux at least.

That means that the madvise() in ram_load(), on a setup where
TARGET_PAGE_SIZE is smaller than the host page size, can throw away data
in guest pages adjacent to the one it's actually processing right now,
leading to guest memory corruption on an incoming migration.

This patch therefore, disables the madvise() if the host page size is
larger than TARGET_PAGE_SIZE.  This means we don't get the benefits of that
madvise() in this case, but a more complete fix is more difficult to
accomplish.  This at least fixes the guest memory corruption.

Signed-off-by: David Gibson 
Reported-by: Alexey Kardashevskiy 
Signed-off-by: Anthony Liguori 
---
 arch_init.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch_init.c b/arch_init.c
index b75a4c5580..83dcc53ff5 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -840,7 +840,8 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
             memset(host, ch, TARGET_PAGE_SIZE);
 #ifndef _WIN32
             if (ch == 0 &&
-                (!kvm_enabled() || kvm_has_sync_mmu())) {
+                (!kvm_enabled() || kvm_has_sync_mmu()) &&
+                getpagesize() <= TARGET_PAGE_SIZE) {
                 qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
             }
 #endif

From 6f918e40e6b7f4e3dcf89c3e3f1001e965a683a1 Mon Sep 17 00:00:00 2001
From: Jason Baron 
Date: Mon, 29 Oct 2012 22:11:31 -0400
Subject: [PATCH 1925/2270] Fixup q35/ich9 Licenses

Cleanup the q35/ich9 license headers.

Signed-off-by: Jason Baron 
Signed-off-by: Michael S. Tsirkin 
Acked-by: Isaku Yamahata 
---
 hw/acpi_ich9.c  | 13 +++++++------
 hw/lpc_ich9.c   | 32 ++++++++------------------------
 hw/smbus_ich9.c | 14 ++++++++------
 3 files changed, 23 insertions(+), 36 deletions(-)

diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index c5978d33cc..85d441c33c 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -2,6 +2,11 @@
  * ACPI implementation
  *
  * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2009 Isaku Yamahata 
+ *                    VA Linux Systems Japan K.K.
+ * Copyright (C) 2012 Jason Baron 
+ *
+ * This is based on acpi.c.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -14,13 +19,9 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see 
- */
-/*
- *  Copyright (c) 2009 Isaku Yamahata 
- *                     VA Linux Systems Japan K.K.
- *  Copyright (C) 2012 Jason Baron 
  *
- *  This is based on acpi.c.
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
  */
 #include "hw.h"
 #include "pc.h"
diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
index 878a43e92c..7a113633ed 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -1,5 +1,13 @@
 /*
+ * QEMU ICH9 Emulation
+ *
  * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2009, 2010, 2011
+ *               Isaku Yamahata 
+ *               VA Linux Systems Japan K.K.
+ * Copyright (C) 2012 Jason Baron 
+ *
+ * This is based on piix_pci.c, but heavily modified.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -19,30 +27,6 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-/*
- * QEMU ICH9 Emulation
- *
- *  Copyright (c) 2009, 2010, 2011
- *                Isaku Yamahata 
- *                VA Linux Systems Japan K.K.
- *  Copyright (C) 2012 Jason Baron 
- *
- *  This is based on piix_pci.c, but heavily modified.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see 
- */
-
 #include "qemu-common.h"
 #include "hw.h"
 #include "range.h"
diff --git a/hw/smbus_ich9.c b/hw/smbus_ich9.c
index 4194785d71..d202664a36 100644
--- a/hw/smbus_ich9.c
+++ b/hw/smbus_ich9.c
@@ -2,6 +2,11 @@
  * ACPI implementation
  *
  * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2009 Isaku Yamahata 
+ *               VA Linux Systems Japan K.K.
+ * Copyright (C) 2012 Jason Baron 
+ *
+ * This is based on acpi.c, but heavily rewritten.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -14,13 +19,10 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see 
- */
-/*
- *  Copyright (c) 2009 Isaku Yamahata 
- *                     VA Linux Systems Japan K.K.
- *  Copyright (C) 2012 Jason Baron 
  *
- *  This is based on acpi.c, but heavily rewritten.
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ *
  */
 #include "hw.h"
 #include "pc.h"

From 89e6d68ef3c45b2c4e3199c3397b5525b752698d Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" 
Date: Mon, 12 Nov 2012 09:13:04 +0200
Subject: [PATCH 1926/2270] tap: reset vnet header size on open

For tap, we currently assume the vnet header size is 10
(the default value) but that might not be the case
if tap is persistent and has been used by qemu previously.
To fix, set vnet header size correctly on open.

Signed-off-by: Michael S. Tsirkin 
---
 net/tap-linux.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/net/tap-linux.c b/net/tap-linux.c
index c6521bec34..3eaedc40ad 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -39,6 +39,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
 {
     struct ifreq ifr;
     int fd, ret;
+    int len = sizeof(struct virtio_net_hdr);
 
     TFR(fd = open(PATH_NET_TUN, O_RDWR));
     if (fd < 0) {
@@ -65,6 +66,13 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
             close(fd);
             return -1;
         }
+        /*
+         * Make sure vnet header size has the default value: for a persistent
+         * tap it might have been modified e.g. by another instance of qemu.
+         * Ignore errors since old kernels do not support this ioctl: in this
+         * case the header size implicitly has the correct value.
+         */
+        ioctl(fd, TUNSETVNETHDRSZ, &len);
     }
 
     if (ifname[0] != '\0')

From c84a2b1aa5ccdddad03d25f58be5c94eba0d9db4 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" 
Date: Mon, 10 Dec 2012 22:52:11 +0200
Subject: [PATCH 1927/2270] get_maintainer.pl: update from linix 3.8

Signed-off-by: Michael S. Tsirkin 
---
 scripts/get_maintainer.pl | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index d9c48e0982..bf5342a08d 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -83,6 +83,8 @@ push(@signature_tags, "Signed-off-by:");
 push(@signature_tags, "Reviewed-by:");
 push(@signature_tags, "Acked-by:");
 
+my $signature_pattern = "\(" . join("|", @signature_tags) . "\)";
+
 # rfc822 email address - preloaded methods go here.
 my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])";
 my $rfc822_char = '[\\000-\\377]';
@@ -95,7 +97,7 @@ my %VCS_cmds_git = (
     "execute_cmd" => \&git_execute_cmd,
     "available" => '(which("git") ne "") && (-d ".git")',
     "find_signers_cmd" =>
-	"git log --no-color --since=\$email_git_since " .
+	"git log --no-color --follow --since=\$email_git_since " .
 	    '--format="GitCommit: %H%n' .
 		      'GitAuthor: %an <%ae>%n' .
 		      'GitDate: %aD%n' .
@@ -328,7 +330,8 @@ sub read_mailmap {
 	# name1  
 	# name1  name2 
 	# (see man git-shortlog)
-	if (/^(.+)<(.+)>$/) {
+
+	if (/^([^<]+)<([^>]+)>$/) {
 	    my $real_name = $1;
 	    my $address = $2;
 
@@ -336,13 +339,13 @@ sub read_mailmap {
 	    ($real_name, $address) = parse_email("$real_name <$address>");
 	    $mailmap->{names}->{$address} = $real_name;
 
-	} elsif (/^<([^\s]+)>\s*<([^\s]+)>$/) {
+	} elsif (/^<([^>]+)>\s*<([^>]+)>$/) {
 	    my $real_address = $1;
 	    my $wrong_address = $2;
 
 	    $mailmap->{addresses}->{$wrong_address} = $real_address;
 
-	} elsif (/^(.+)<([^\s]+)>\s*<([^\s]+)>$/) {
+	} elsif (/^(.+)<([^>]+)>\s*<([^>]+)>$/) {
 	    my $real_name = $1;
 	    my $real_address = $2;
 	    my $wrong_address = $3;
@@ -353,7 +356,7 @@ sub read_mailmap {
 	    $mailmap->{names}->{$wrong_address} = $real_name;
 	    $mailmap->{addresses}->{$wrong_address} = $real_address;
 
-	} elsif (/^(.+)<([^\s]+)>\s*([^\s].*)<([^\s]+)>$/) {
+	} elsif (/^(.+)<([^>]+)>\s*(.+)\s*<([^>]+)>$/) {
 	    my $real_name = $1;
 	    my $real_address = $2;
 	    my $wrong_name = $3;
@@ -472,7 +475,6 @@ my @subsystem = ();
 my @status = ();
 my %deduplicate_name_hash = ();
 my %deduplicate_address_hash = ();
-my $signature_pattern;
 
 my @maintainers = get_maintainers();
 
@@ -920,7 +922,7 @@ sub get_maintainer_role {
     my $start = find_starting_index($index);
     my $end = find_ending_index($index);
 
-    my $role;
+    my $role = "unknown";
     my $subsystem = $typevalue[$start];
     if (length($subsystem) > 20) {
 	$subsystem = substr($subsystem, 0, 17);
@@ -1016,8 +1018,13 @@ sub add_categories {
 		    if ($email_list) {
 			if (!$hash_list_to{lc($list_address)}) {
 			    $hash_list_to{lc($list_address)} = 1;
-			    push(@list_to, [$list_address,
-					    "open list${list_role}"]);
+			    if ($list_additional =~ m/moderated/) {
+				push(@list_to, [$list_address,
+						"moderated list${list_role}"]);
+			    } else {
+				push(@list_to, [$list_address,
+						"open list${list_role}"]);
+			    }
 			}
 		    }
 		}

From 29002d9e104913998265cfff95bb49f4b4a966e2 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" 
Date: Wed, 12 Dec 2012 13:07:29 +0200
Subject: [PATCH 1928/2270] pci: prepare makefiles for pci code reorganization

To make it easier to move code around without breaking
build at intermedite steps, tweak makefiles
to look in pci/ and hw/ for include files, automatically.
This will be reverted at the end of the reorganization.

Signed-off-by: Michael S. Tsirkin 
---
 Makefile        | 1 +
 Makefile.target | 1 +
 Makefile.user   | 1 +
 hw/pci/hw       | 1 +
 4 files changed, 4 insertions(+)
 create mode 120000 hw/pci/hw

diff --git a/Makefile b/Makefile
index 9ecbcbb0a7..b9a81d18a2 100644
--- a/Makefile
+++ b/Makefile
@@ -146,6 +146,7 @@ audio/audio.o audio/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS)
 QEMU_CFLAGS+=$(CURL_CFLAGS)
 
 QEMU_CFLAGS += -I$(SRC_PATH)/include
+QEMU_CFLAGS+=-I$(SRC_PATH)/hw/pci -I$(SRC_PATH)/hw
 
 ui/cocoa.o: ui/cocoa.m
 
diff --git a/Makefile.target b/Makefile.target
index 927347bac2..fe2cc0d8b0 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -12,6 +12,7 @@ endif
 QEMU_CFLAGS += -I.. -I$(SRC_PATH)/target-$(TARGET_BASE_ARCH) -DNEED_CPU_H
 
 QEMU_CFLAGS+=-I$(SRC_PATH)/include
+QEMU_CFLAGS+=-I$(SRC_PATH)/hw/pci -I$(SRC_PATH)/hw
 
 ifdef CONFIG_USER_ONLY
 # user emulator name
diff --git a/Makefile.user b/Makefile.user
index 9302d33245..045ecd3bea 100644
--- a/Makefile.user
+++ b/Makefile.user
@@ -11,6 +11,7 @@ $(call set-vpath, $(SRC_PATH))
 QEMU_CFLAGS+=-I..
 QEMU_CFLAGS += -I$(SRC_PATH)/include
 QEMU_CFLAGS += -DCONFIG_USER_ONLY
+QEMU_CFLAGS+=-I$(SRC_PATH)/hw/pci -I$(SRC_PATH)/hw
 
 include $(SRC_PATH)/Makefile.objs
 
diff --git a/hw/pci/hw b/hw/pci/hw
new file mode 120000
index 0000000000..945c9b46d6
--- /dev/null
+++ b/hw/pci/hw
@@ -0,0 +1 @@
+.
\ No newline at end of file

From ca818cfbfd77e02ffac338866568ac07f6f5fd7d Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" 
Date: Wed, 12 Dec 2012 15:11:55 +0200
Subject: [PATCH 1929/2270] MAINTAINERS: add hw/pci/ to list of PCI files

Signed-off-by: Michael S. Tsirkin 
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 2ede20d60b..c1b16c5fe4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -490,6 +490,7 @@ F: hw/omap*
 PCI
 M: Michael S. Tsirkin 
 S: Supported
+F: hw/pci/*
 F: hw/pci*
 F: hw/piix*
 

From a7f3d65b65b8c86a5ff0c0abcfefb45e2ec6fe4c Mon Sep 17 00:00:00 2001
From: Pavel Hrdina 
Date: Tue, 11 Dec 2012 08:55:48 +0100
Subject: [PATCH 1930/2270] atapi: reset cdrom tray statuses on ide_reset

Tray statuses should be also reseted. Some guests may lock the tray
and after reset before any kernel is loaded the tray should be unlocked.

Also if you reset the real computer the tray is closed. We should
do the same in qemu.

Signed-off-by: Pavel Hrdina 
Signed-off-by: Kevin Wolf 
---
 hw/ide/core.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index c4f93d0e47..1235612d95 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1869,6 +1869,8 @@ static void ide_reset(IDEState *s)
     s->io_buffer_index = 0;
     s->cd_sector_size = 0;
     s->atapi_dma = 0;
+    s->tray_locked = 0;
+    s->tray_open = 0;
     /* ATA DMA state */
     s->io_buffer_size = 0;
     s->req_nb_sectors = 0;

From c3587ca1a25862628e06cc019f91e7b2dcef40bf Mon Sep 17 00:00:00 2001
From: Amit Shah 
Date: Thu, 29 Nov 2012 15:44:44 +0530
Subject: [PATCH 1931/2270] virtio-serial: use uint32_t to count ports

Signed-off-by: Amit Shah 
---
 hw/virtio-serial-bus.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 155da58dcd..30f450cd61 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -56,7 +56,7 @@ struct VirtIOSerial {
 
     struct {
         QEMUTimer *timer;
-        int nr_active_ports;
+        uint32_t nr_active_ports;
         struct {
             VirtIOSerialPort *port;
             uint8_t host_connected;
@@ -637,7 +637,7 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
 
 static void virtio_serial_post_load_timer_cb(void *opaque)
 {
-    int i;
+    uint32_t i;
     VirtIOSerial *s = opaque;
     VirtIOSerialPort *port;
     uint8_t host_connected;

From 2e575a86abc36764ef34030f423ef118914a01cc Mon Sep 17 00:00:00 2001
From: Amit Shah 
Date: Thu, 29 Nov 2012 17:02:14 +0530
Subject: [PATCH 1932/2270] virtio-serial: move active ports loading to
 separate function

The virtio_serial_load() function became too big, split the code that
gets the port info from the source into a separate function.

Signed-off-by: Amit Shah 
---
 hw/virtio-serial-bus.c | 96 ++++++++++++++++++++++++------------------
 1 file changed, 55 insertions(+), 41 deletions(-)

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 30f450cd61..2e0fe3d66f 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -658,10 +658,60 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
     s->post_load.connected = NULL;
 }
 
+static int fetch_active_ports_list(QEMUFile *f, int version_id,
+                                   VirtIOSerial *s, uint32_t nr_active_ports)
+{
+    uint32_t i;
+
+    s->post_load.nr_active_ports = nr_active_ports;
+    s->post_load.connected =
+        g_malloc0(sizeof(*s->post_load.connected) * nr_active_ports);
+
+    /* Items in struct VirtIOSerialPort */
+    for (i = 0; i < nr_active_ports; i++) {
+        VirtIOSerialPort *port;
+        uint32_t id;
+
+        id = qemu_get_be32(f);
+        port = find_port_by_id(s, id);
+        if (!port) {
+            return -EINVAL;
+        }
+
+        port->guest_connected = qemu_get_byte(f);
+        s->post_load.connected[i].port = port;
+        s->post_load.connected[i].host_connected = qemu_get_byte(f);
+
+        if (version_id > 2) {
+            uint32_t elem_popped;
+
+            qemu_get_be32s(f, &elem_popped);
+            if (elem_popped) {
+                qemu_get_be32s(f, &port->iov_idx);
+                qemu_get_be64s(f, &port->iov_offset);
+
+                qemu_get_buffer(f, (unsigned char *)&port->elem,
+                                sizeof(port->elem));
+                virtqueue_map_sg(port->elem.in_sg, port->elem.in_addr,
+                                 port->elem.in_num, 1);
+                virtqueue_map_sg(port->elem.out_sg, port->elem.out_addr,
+                                 port->elem.out_num, 1);
+
+                /*
+                 *  Port was throttled on source machine.  Let's
+                 *  unthrottle it here so data starts flowing again.
+                 */
+                virtio_serial_throttle_port(port, false);
+            }
+        }
+    }
+    qemu_mod_timer(s->post_load.timer, 1);
+    return 0;
+}
+
 static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
 {
     VirtIOSerial *s = opaque;
-    VirtIOSerialPort *port;
     uint32_t max_nr_ports, nr_active_ports, ports_map;
     unsigned int i;
     int ret;
@@ -705,48 +755,12 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
 
     qemu_get_be32s(f, &nr_active_ports);
 
-    s->post_load.nr_active_ports = nr_active_ports;
-    s->post_load.connected =
-        g_malloc0(sizeof(*s->post_load.connected) * nr_active_ports);
-
-    /* Items in struct VirtIOSerialPort */
-    for (i = 0; i < nr_active_ports; i++) {
-        uint32_t id;
-
-        id = qemu_get_be32(f);
-        port = find_port_by_id(s, id);
-        if (!port) {
-            return -EINVAL;
-        }
-
-        port->guest_connected = qemu_get_byte(f);
-        s->post_load.connected[i].port = port;
-        s->post_load.connected[i].host_connected = qemu_get_byte(f);
-
-        if (version_id > 2) {
-            uint32_t elem_popped;
-
-            qemu_get_be32s(f, &elem_popped);
-            if (elem_popped) {
-                qemu_get_be32s(f, &port->iov_idx);
-                qemu_get_be64s(f, &port->iov_offset);
-
-                qemu_get_buffer(f, (unsigned char *)&port->elem,
-                                sizeof(port->elem));
-                virtqueue_map_sg(port->elem.in_sg, port->elem.in_addr,
-                                 port->elem.in_num, 1);
-                virtqueue_map_sg(port->elem.out_sg, port->elem.out_addr,
-                                 port->elem.out_num, 1);
-
-                /*
-                 *  Port was throttled on source machine.  Let's
-                 *  unthrottle it here so data starts flowing again.
-                 */
-                virtio_serial_throttle_port(port, false);
-            }
+    if (nr_active_ports) {
+        ret = fetch_active_ports_list(f, version_id, s, nr_active_ports);
+        if (ret) {
+            return ret;
         }
     }
-    qemu_mod_timer(s->post_load.timer, 1);
     return 0;
 }
 

From bdb917bf8ab187b662c612ee6fb87479c0b82490 Mon Sep 17 00:00:00 2001
From: Amit Shah 
Date: Fri, 30 Nov 2012 00:54:44 +0530
Subject: [PATCH 1933/2270] virtio-serial: allocate post_load only at load-time

This saves us a few bytes in the VirtIOSerial struct.  Not a big
savings, but since the entire structure is used only during a short
while after migration, it's helpful to keep the struct cleaner and
smaller.

Signed-off-by: Amit Shah 
---
 hw/virtio-serial-bus.c | 63 +++++++++++++++++++++++++-----------------
 1 file changed, 38 insertions(+), 25 deletions(-)

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 2e0fe3d66f..09d46593e2 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -36,6 +36,15 @@ struct VirtIOSerialBus {
     uint32_t max_nr_ports;
 };
 
+typedef struct VirtIOSerialPostLoad {
+    QEMUTimer *timer;
+    uint32_t nr_active_ports;
+    struct {
+        VirtIOSerialPort *port;
+        uint8_t host_connected;
+    } *connected;
+} VirtIOSerialPostLoad;
+
 struct VirtIOSerial {
     VirtIODevice vdev;
 
@@ -54,14 +63,7 @@ struct VirtIOSerial {
 
     struct virtio_console_config config;
 
-    struct {
-        QEMUTimer *timer;
-        uint32_t nr_active_ports;
-        struct {
-            VirtIOSerialPort *port;
-            uint8_t host_connected;
-        } *connected;
-    } post_load;
+    struct VirtIOSerialPostLoad *post_load;
 };
 
 static VirtIOSerialPort *find_port_by_id(VirtIOSerial *vser, uint32_t id)
@@ -642,9 +644,12 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
     VirtIOSerialPort *port;
     uint8_t host_connected;
 
-    for (i = 0 ; i < s->post_load.nr_active_ports; ++i) {
-        port = s->post_load.connected[i].port;
-        host_connected = s->post_load.connected[i].host_connected;
+    if (!s->post_load) {
+        return;
+    }
+    for (i = 0 ; i < s->post_load->nr_active_ports; ++i) {
+        port = s->post_load->connected[i].port;
+        host_connected = s->post_load->connected[i].host_connected;
         if (host_connected != port->host_connected) {
             /*
              * We have to let the guest know of the host connection
@@ -654,8 +659,10 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
                                port->host_connected);
         }
     }
-    g_free(s->post_load.connected);
-    s->post_load.connected = NULL;
+    g_free(s->post_load->connected);
+    qemu_free_timer(s->post_load->timer);
+    g_free(s->post_load);
+    s->post_load = NULL;
 }
 
 static int fetch_active_ports_list(QEMUFile *f, int version_id,
@@ -663,9 +670,14 @@ static int fetch_active_ports_list(QEMUFile *f, int version_id,
 {
     uint32_t i;
 
-    s->post_load.nr_active_ports = nr_active_ports;
-    s->post_load.connected =
-        g_malloc0(sizeof(*s->post_load.connected) * nr_active_ports);
+    s->post_load = g_malloc0(sizeof(*s->post_load));
+    s->post_load->nr_active_ports = nr_active_ports;
+    s->post_load->connected =
+        g_malloc0(sizeof(*s->post_load->connected) * nr_active_ports);
+
+    s->post_load->timer = qemu_new_timer_ns(vm_clock,
+                                            virtio_serial_post_load_timer_cb,
+                                            s);
 
     /* Items in struct VirtIOSerialPort */
     for (i = 0; i < nr_active_ports; i++) {
@@ -679,8 +691,8 @@ static int fetch_active_ports_list(QEMUFile *f, int version_id,
         }
 
         port->guest_connected = qemu_get_byte(f);
-        s->post_load.connected[i].port = port;
-        s->post_load.connected[i].host_connected = qemu_get_byte(f);
+        s->post_load->connected[i].port = port;
+        s->post_load->connected[i].host_connected = qemu_get_byte(f);
 
         if (version_id > 2) {
             uint32_t elem_popped;
@@ -705,7 +717,7 @@ static int fetch_active_ports_list(QEMUFile *f, int version_id,
             }
         }
     }
-    qemu_mod_timer(s->post_load.timer, 1);
+    qemu_mod_timer(s->post_load->timer, 1);
     return 0;
 }
 
@@ -1003,6 +1015,8 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf)
 
     vser->qdev = dev;
 
+    vser->post_load = NULL;
+
     /*
      * Register for the savevm section with the virtio-console name
      * to preserve backward compat
@@ -1010,9 +1024,6 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf)
     register_savevm(dev, "virtio-console", -1, 3, virtio_serial_save,
                     virtio_serial_load, vser);
 
-    vser->post_load.timer = qemu_new_timer_ns(vm_clock,
-            virtio_serial_post_load_timer_cb, vser);
-
     return vdev;
 }
 
@@ -1025,9 +1036,11 @@ void virtio_serial_exit(VirtIODevice *vdev)
     g_free(vser->ivqs);
     g_free(vser->ovqs);
     g_free(vser->ports_map);
-    g_free(vser->post_load.connected);
-    qemu_free_timer(vser->post_load.timer);
-
+    if (vser->post_load) {
+        g_free(vser->post_load->connected);
+        qemu_free_timer(vser->post_load->timer);
+        g_free(vser->post_load);
+    }
     virtio_cleanup(vdev);
 }
 

From a75bf146503a94fb900e0dfa0529bd5d1be9fec5 Mon Sep 17 00:00:00 2001
From: Amit Shah 
Date: Thu, 13 Dec 2012 15:54:43 +0530
Subject: [PATCH 1934/2270] virtio-serial: delete timer if active during exit

The post_load timer was being freed, but not deleted.  This could cause
problems when the timer is armed, but the device is hot-unplugged before
the callback is executed.

Signed-off-by: Amit Shah 
---
 hw/virtio-serial-bus.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 09d46593e2..fc0166ca7f 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -1038,6 +1038,7 @@ void virtio_serial_exit(VirtIODevice *vdev)
     g_free(vser->ports_map);
     if (vser->post_load) {
         g_free(vser->post_load->connected);
+        qemu_del_timer(vser->post_load->timer);
         qemu_free_timer(vser->post_load->timer);
         g_free(vser->post_load);
     }

From 580f5c000809108f51a77ae74709100d32be6ea5 Mon Sep 17 00:00:00 2001
From: Antoine Mathys 
Date: Thu, 13 Dec 2012 14:05:27 +0000
Subject: [PATCH 1935/2270] hw/ds1338.c: Correct bug in conversion to BCD.

Signed-off-by: Antoine Mathys 
Signed-off-by: Peter Maydell 
---
 hw/ds1338.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/ds1338.c b/hw/ds1338.c
index b576d56438..faaa4a0a93 100644
--- a/hw/ds1338.c
+++ b/hw/ds1338.c
@@ -57,9 +57,9 @@ static void capture_current_time(DS1338State *s)
     } else {
         s->nvram[2] = to_bcd(now.tm_hour);
     }
-    s->nvram[3] = to_bcd(now.tm_wday) + 1;
+    s->nvram[3] = to_bcd(now.tm_wday + 1);
     s->nvram[4] = to_bcd(now.tm_mday);
-    s->nvram[5] = to_bcd(now.tm_mon) + 1;
+    s->nvram[5] = to_bcd(now.tm_mon + 1);
     s->nvram[6] = to_bcd(now.tm_year - 100);
 }
 

From 95c9361598e66de42facdac64e614e3de85186f5 Mon Sep 17 00:00:00 2001
From: Antoine Mathys 
Date: Thu, 13 Dec 2012 14:05:27 +0000
Subject: [PATCH 1936/2270] hw/ds1338.c: Add definitions for various flags in
 the RTC registers.

Signed-off-by: Antoine Mathys 
Signed-off-by: Peter Maydell 
---
 hw/ds1338.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/hw/ds1338.c b/hw/ds1338.c
index faaa4a0a93..69018bc966 100644
--- a/hw/ds1338.c
+++ b/hw/ds1338.c
@@ -17,6 +17,12 @@
  */
 #define NVRAM_SIZE 64
 
+/* Flags definitions */
+#define SECONDS_CH 0x80
+#define HOURS_12   0x40
+#define HOURS_PM   0x20
+#define CTRL_OSF   0x20
+
 typedef struct {
     I2CSlave i2c;
     int64_t offset;

From 59dda8e05b015471d456177141a7c2eeda3dab14 Mon Sep 17 00:00:00 2001
From: Antoine Mathys 
Date: Thu, 13 Dec 2012 14:05:27 +0000
Subject: [PATCH 1937/2270] hw/ds1338.c: Fix handling of HOURS register.

Per the datasheet, the mapping between 12 and 24 hours modes is:
      0      <->  12   PM
      1-12   <->  1-12 AM
      13-23  <->  1-11 PM

Signed-off-by: Antoine Mathys 
Signed-off-by: Peter Maydell 
---
 hw/ds1338.c | 29 ++++++++++++++++++-----------
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/hw/ds1338.c b/hw/ds1338.c
index 69018bc966..0f887200f3 100644
--- a/hw/ds1338.c
+++ b/hw/ds1338.c
@@ -55,10 +55,15 @@ static void capture_current_time(DS1338State *s)
     qemu_get_timedate(&now, s->offset);
     s->nvram[0] = to_bcd(now.tm_sec);
     s->nvram[1] = to_bcd(now.tm_min);
-    if (s->nvram[2] & 0x40) {
-        s->nvram[2] = (to_bcd((now.tm_hour % 12)) + 1) | 0x40;
-        if (now.tm_hour >= 12) {
-            s->nvram[2] |= 0x20;
+    if (s->nvram[2] & HOURS_12) {
+        int tmp = now.tm_hour;
+        if (tmp == 0) {
+            tmp = 24;
+        }
+        if (tmp <= 12) {
+            s->nvram[2] = HOURS_12 | to_bcd(tmp);
+        } else {
+            s->nvram[2] = HOURS_12 | HOURS_PM | to_bcd(tmp - 12);
         }
     } else {
         s->nvram[2] = to_bcd(now.tm_hour);
@@ -132,16 +137,18 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data)
             now.tm_min = from_bcd(data & 0x7f);
             break;
         case 2:
-            if (data & 0x40) {
-                if (data & 0x20) {
-                    data = from_bcd(data & 0x4f) + 11;
-                } else {
-                    data = from_bcd(data & 0x1f) - 1;
+            if (data & HOURS_12) {
+                int tmp = from_bcd(data & (HOURS_PM - 1));
+                if (data & HOURS_PM) {
+                    tmp += 12;
                 }
+                if (tmp == 24) {
+                    tmp = 0;
+                }
+                now.tm_hour = tmp;
             } else {
-                data = from_bcd(data);
+                now.tm_hour = from_bcd(data & (HOURS_12 - 1));
             }
-            now.tm_hour = data;
             break;
         case 3:
             now.tm_wday = from_bcd(data & 7) - 1;

From ed3d37d287300b7bcdb4605b921e5ec593afd214 Mon Sep 17 00:00:00 2001
From: Antoine Mathys 
Date: Thu, 13 Dec 2012 14:05:28 +0000
Subject: [PATCH 1938/2270] hw/ds1338.c: Ensure state is properly initialized.

Signed-off-by: Antoine Mathys 
Signed-off-by: Peter Maydell 
---
 hw/ds1338.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/hw/ds1338.c b/hw/ds1338.c
index 0f887200f3..d2f52fcbed 100644
--- a/hw/ds1338.c
+++ b/hw/ds1338.c
@@ -179,6 +179,17 @@ static int ds1338_init(I2CSlave *i2c)
     return 0;
 }
 
+static void ds1338_reset(DeviceState *dev)
+{
+    DS1338State *s = FROM_I2C_SLAVE(DS1338State, I2C_SLAVE_FROM_QDEV(dev));
+
+    /* The clock is running and synchronized with the host */
+    s->offset = 0;
+    memset(s->nvram, 0, NVRAM_SIZE);
+    s->ptr = 0;
+    s->addr_byte = false;
+}
+
 static void ds1338_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -188,6 +199,7 @@ static void ds1338_class_init(ObjectClass *klass, void *data)
     k->event = ds1338_event;
     k->recv = ds1338_recv;
     k->send = ds1338_send;
+    dc->reset = ds1338_reset;
     dc->vmsd = &vmstate_ds1338;
 }
 

From 996e91f04b9cc55cf246052856abe9189a5a0f28 Mon Sep 17 00:00:00 2001
From: Antoine Mathys 
Date: Thu, 13 Dec 2012 14:05:28 +0000
Subject: [PATCH 1939/2270] hw/ds1338.c: Implement support for the control
 register.

Signed-off-by: Antoine Mathys 
Signed-off-by: Peter Maydell 
---
 hw/ds1338.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/hw/ds1338.c b/hw/ds1338.c
index d2f52fcbed..94a2f549e4 100644
--- a/hw/ds1338.c
+++ b/hw/ds1338.c
@@ -125,7 +125,8 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data)
         s->addr_byte = false;
         return 0;
     }
-    if (s->ptr < 8) {
+    if (s->ptr < 7) {
+        /* Time register. */
         struct tm now;
         qemu_get_timedate(&now, s->offset);
         switch(s->ptr) {
@@ -162,11 +163,19 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data)
         case 6:
             now.tm_year = from_bcd(data) + 100;
             break;
-        case 7:
-            /* Control register. Currently ignored.  */
-            break;
         }
         s->offset = qemu_timedate_diff(&now);
+    } else if (s->ptr == 7) {
+        /* Control register. */
+
+        /* Ensure bits 2, 3 and 6 will read back as zero. */
+        data &= 0xB3;
+
+        /* Attempting to write the OSF flag to logic 1 leaves the
+           value unchanged. */
+        data = (data & ~CTRL_OSF) | (data & s->nvram[s->ptr] & CTRL_OSF);
+
+        s->nvram[s->ptr] = data;
     } else {
         s->nvram[s->ptr] = data;
     }

From 871edc5fdba884929102b89d28ff363c94f0822d Mon Sep 17 00:00:00 2001
From: Antoine Mathys 
Date: Thu, 13 Dec 2012 14:05:28 +0000
Subject: [PATCH 1940/2270] hw/ds1338.c: Fix handling of DAY (wday) register.

Per the datasheet, the DAY (wday) register is user defined. Implement this.

Signed-off-by: Antoine Mathys 
Signed-off-by: Peter Maydell 
---
 hw/ds1338.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/hw/ds1338.c b/hw/ds1338.c
index 94a2f549e4..1aefa3ba04 100644
--- a/hw/ds1338.c
+++ b/hw/ds1338.c
@@ -26,6 +26,7 @@
 typedef struct {
     I2CSlave i2c;
     int64_t offset;
+    uint8_t wday_offset;
     uint8_t nvram[NVRAM_SIZE];
     int32_t ptr;
     bool addr_byte;
@@ -33,12 +34,13 @@ typedef struct {
 
 static const VMStateDescription vmstate_ds1338 = {
     .name = "ds1338",
-    .version_id = 1,
+    .version_id = 2,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields = (VMStateField[]) {
         VMSTATE_I2C_SLAVE(i2c, DS1338State),
         VMSTATE_INT64(offset, DS1338State),
+        VMSTATE_UINT8_V(wday_offset, DS1338State, 2),
         VMSTATE_UINT8_ARRAY(nvram, DS1338State, NVRAM_SIZE),
         VMSTATE_INT32(ptr, DS1338State),
         VMSTATE_BOOL(addr_byte, DS1338State),
@@ -68,7 +70,7 @@ static void capture_current_time(DS1338State *s)
     } else {
         s->nvram[2] = to_bcd(now.tm_hour);
     }
-    s->nvram[3] = to_bcd(now.tm_wday + 1);
+    s->nvram[3] = (now.tm_wday + s->wday_offset) % 7 + 1;
     s->nvram[4] = to_bcd(now.tm_mday);
     s->nvram[5] = to_bcd(now.tm_mon + 1);
     s->nvram[6] = to_bcd(now.tm_year - 100);
@@ -152,7 +154,13 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data)
             }
             break;
         case 3:
-            now.tm_wday = from_bcd(data & 7) - 1;
+            {
+                /* The day field is supposed to contain a value in
+                   the range 1-7. Otherwise behavior is undefined.
+                 */
+                int user_wday = (data & 7) - 1;
+                s->wday_offset = (user_wday - now.tm_wday + 7) % 7;
+            }
             break;
         case 4:
             now.tm_mday = from_bcd(data & 0x3f);
@@ -194,6 +202,7 @@ static void ds1338_reset(DeviceState *dev)
 
     /* The clock is running and synchronized with the host */
     s->offset = 0;
+    s->wday_offset = 0;
     memset(s->nvram, 0, NVRAM_SIZE);
     s->ptr = 0;
     s->addr_byte = false;

From 1d3afd649bc77aa14bc2741e2da6475822d41c5f Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Fri, 7 Dec 2012 18:08:42 +0100
Subject: [PATCH 1941/2270] qcow2: Round QCowL2Meta.offset down to cluster
 boundary

The offset within the cluster is already present as n_start and this is
what the code uses. QCowL2Meta.offset is only needed at a cluster
granularity.

Signed-off-by: Kevin Wolf 
---
 block/qcow2-cluster.c |  4 ++--
 block/qcow2.h         | 22 ++++++++++++++++++++++
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index e179211c57..d17a37c2fa 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -631,7 +631,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
     old_cluster = g_malloc(m->nb_clusters * sizeof(uint64_t));
 
     /* copy content of unmodified sectors */
-    start_sect = (m->offset & ~(s->cluster_size - 1)) >> 9;
+    start_sect = m->offset >> 9;
     if (m->n_start) {
         cow = true;
         qemu_co_mutex_unlock(&s->lock);
@@ -966,7 +966,7 @@ again:
                 .cluster_offset = keep_clusters == 0 ?
                                   alloc_cluster_offset : cluster_offset,
                 .alloc_offset   = alloc_cluster_offset,
-                .offset         = alloc_offset,
+                .offset         = alloc_offset & ~(s->cluster_size - 1),
                 .n_start        = keep_clusters == 0 ? n_start : 0,
                 .nb_clusters    = nb_clusters,
                 .nb_available   = MIN(requested_sectors, avail_sectors),
diff --git a/block/qcow2.h b/block/qcow2.h
index b4eb65470e..2a406a7e83 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -199,12 +199,34 @@ struct QCowAIOCB;
 /* XXX This could be private for qcow2-cluster.c */
 typedef struct QCowL2Meta
 {
+    /** Guest offset of the first newly allocated cluster */
     uint64_t offset;
+
+    /** Host offset of the first cluster of the request */
     uint64_t cluster_offset;
+
+    /** Host offset of the first newly allocated cluster */
     uint64_t alloc_offset;
+
+    /**
+     * Number of sectors between the start of the first allocated cluster and
+     * the area that the guest actually writes to.
+     */
     int n_start;
+
+    /**
+     * Number of sectors from the start of the first allocated cluster to
+     * the end of the (possibly shortened) request
+     */
     int nb_available;
+
+    /** Number of newly allocated clusters */
     int nb_clusters;
+
+    /**
+     * Requests that overlap with this allocation and wait to be restarted
+     * when the allocating request has completed.
+     */
     CoQueue dependent_requests;
 
     QLIST_ENTRY(QCowL2Meta) next_in_flight;

From 593fb83cacf3818a5623f31a6c04c24d87519ad0 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Fri, 7 Dec 2012 18:08:43 +0100
Subject: [PATCH 1942/2270] qcow2: Introduce Qcow2COWRegion

This makes it easier to address the areas for which a COW must be
performed. As a nice side effect, the COW code in
qcow2_alloc_cluster_link_l2 becomes really trivial.

Signed-off-by: Kevin Wolf 
---
 block/qcow2-cluster.c | 83 +++++++++++++++++++++++++++----------------
 block/qcow2.h         | 29 +++++++++++----
 2 files changed, 76 insertions(+), 36 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index d17a37c2fa..94b7f136fa 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -615,13 +615,41 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
     return cluster_offset;
 }
 
+static int perform_cow(BlockDriverState *bs, QCowL2Meta *m, Qcow2COWRegion *r)
+{
+    BDRVQcowState *s = bs->opaque;
+    int ret;
+
+    if (r->nb_sectors == 0) {
+        return 0;
+    }
+
+    qemu_co_mutex_unlock(&s->lock);
+    ret = copy_sectors(bs, m->offset / BDRV_SECTOR_SIZE, m->alloc_offset,
+                       r->offset / BDRV_SECTOR_SIZE,
+                       r->offset / BDRV_SECTOR_SIZE + r->nb_sectors);
+    qemu_co_mutex_lock(&s->lock);
+
+    if (ret < 0) {
+        return ret;
+    }
+
+    /*
+     * Before we update the L2 table to actually point to the new cluster, we
+     * need to be sure that the refcounts have been increased and COW was
+     * handled.
+     */
+    qcow2_cache_depends_on_flush(s->l2_table_cache);
+
+    return 0;
+}
+
 int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
 {
     BDRVQcowState *s = bs->opaque;
     int i, j = 0, l2_index, ret;
-    uint64_t *old_cluster, start_sect, *l2_table;
+    uint64_t *old_cluster, *l2_table;
     uint64_t cluster_offset = m->alloc_offset;
-    bool cow = false;
 
     trace_qcow2_cluster_link_l2(qemu_coroutine_self(), m->nb_clusters);
 
@@ -631,36 +659,17 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
     old_cluster = g_malloc(m->nb_clusters * sizeof(uint64_t));
 
     /* copy content of unmodified sectors */
-    start_sect = m->offset >> 9;
-    if (m->n_start) {
-        cow = true;
-        qemu_co_mutex_unlock(&s->lock);
-        ret = copy_sectors(bs, start_sect, cluster_offset, 0, m->n_start);
-        qemu_co_mutex_lock(&s->lock);
-        if (ret < 0)
-            goto err;
+    ret = perform_cow(bs, m, &m->cow_start);
+    if (ret < 0) {
+        goto err;
     }
 
-    if (m->nb_available & (s->cluster_sectors - 1)) {
-        cow = true;
-        qemu_co_mutex_unlock(&s->lock);
-        ret = copy_sectors(bs, start_sect, cluster_offset, m->nb_available,
-                           align_offset(m->nb_available, s->cluster_sectors));
-        qemu_co_mutex_lock(&s->lock);
-        if (ret < 0)
-            goto err;
+    ret = perform_cow(bs, m, &m->cow_end);
+    if (ret < 0) {
+        goto err;
     }
 
-    /*
-     * Update L2 table.
-     *
-     * Before we update the L2 table to actually point to the new cluster, we
-     * need to be sure that the refcounts have been increased and COW was
-     * handled.
-     */
-    if (cow) {
-        qcow2_cache_depends_on_flush(s->l2_table_cache);
-    }
+    /* Update L2 table. */
 
     if (qcow2_need_accurate_refcounts(s)) {
         qcow2_cache_set_dependency(bs, s->l2_table_cache,
@@ -957,19 +966,33 @@ again:
              *
              * avail_sectors: Number of sectors from the start of the first
              * newly allocated to the end of the last newly allocated cluster.
+             *
+             * nb_sectors: The number of sectors from the start of the first
+             * newly allocated cluster to the end of the aread that the write
+             * request actually writes to (excluding COW at the end)
              */
             int requested_sectors = n_end - keep_clusters * s->cluster_sectors;
             int avail_sectors = nb_clusters
                                 << (s->cluster_bits - BDRV_SECTOR_BITS);
+            int alloc_n_start = keep_clusters == 0 ? n_start : 0;
+            int nb_sectors = MIN(requested_sectors, avail_sectors);
 
             *m = (QCowL2Meta) {
                 .cluster_offset = keep_clusters == 0 ?
                                   alloc_cluster_offset : cluster_offset,
                 .alloc_offset   = alloc_cluster_offset,
                 .offset         = alloc_offset & ~(s->cluster_size - 1),
-                .n_start        = keep_clusters == 0 ? n_start : 0,
                 .nb_clusters    = nb_clusters,
-                .nb_available   = MIN(requested_sectors, avail_sectors),
+                .nb_available   = nb_sectors,
+
+                .cow_start = {
+                    .offset     = 0,
+                    .nb_sectors = alloc_n_start,
+                },
+                .cow_end = {
+                    .offset     = nb_sectors * BDRV_SECTOR_SIZE,
+                    .nb_sectors = avail_sectors - nb_sectors,
+                },
             };
             qemu_co_queue_init(&m->dependent_requests);
             QLIST_INSERT_HEAD(&s->cluster_allocs, m, next_in_flight);
diff --git a/block/qcow2.h b/block/qcow2.h
index 2a406a7e83..1106b33206 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -196,6 +196,17 @@ typedef struct QCowCreateState {
 
 struct QCowAIOCB;
 
+typedef struct Qcow2COWRegion {
+    /**
+     * Offset of the COW region in bytes from the start of the first cluster
+     * touched by the request.
+     */
+    uint64_t    offset;
+
+    /** Number of sectors to copy */
+    int         nb_sectors;
+} Qcow2COWRegion;
+
 /* XXX This could be private for qcow2-cluster.c */
 typedef struct QCowL2Meta
 {
@@ -208,12 +219,6 @@ typedef struct QCowL2Meta
     /** Host offset of the first newly allocated cluster */
     uint64_t alloc_offset;
 
-    /**
-     * Number of sectors between the start of the first allocated cluster and
-     * the area that the guest actually writes to.
-     */
-    int n_start;
-
     /**
      * Number of sectors from the start of the first allocated cluster to
      * the end of the (possibly shortened) request
@@ -229,6 +234,18 @@ typedef struct QCowL2Meta
      */
     CoQueue dependent_requests;
 
+    /**
+     * The COW Region between the start of the first allocated cluster and the
+     * area the guest actually writes to.
+     */
+    Qcow2COWRegion cow_start;
+
+    /**
+     * The COW Region between the area the guest actually writes to and the
+     * end of the last allocated cluster.
+     */
+    Qcow2COWRegion cow_end;
+
     QLIST_ENTRY(QCowL2Meta) next_in_flight;
 } QCowL2Meta;
 

From cf5c1a231ee99ac21fe8258faf50bb1f65884343 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Fri, 7 Dec 2012 18:08:44 +0100
Subject: [PATCH 1943/2270] qcow2: Allocate l2meta dynamically

As soon as delayed COW is introduced, the l2meta struct is needed even
after completion of the request, so it can't live on the stack.

Signed-off-by: Kevin Wolf 
---
 block/qcow2.c | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 0a08ec74c7..71f870d829 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -774,15 +774,11 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
     QEMUIOVector hd_qiov;
     uint64_t bytes_done = 0;
     uint8_t *cluster_data = NULL;
-    QCowL2Meta l2meta = {
-        .nb_clusters = 0,
-    };
+    QCowL2Meta *l2meta;
 
     trace_qcow2_writev_start_req(qemu_coroutine_self(), sector_num,
                                  remaining_sectors);
 
-    qemu_co_queue_init(&l2meta.dependent_requests);
-
     qemu_iovec_init(&hd_qiov, qiov->niov);
 
     s->cluster_cache_offset = -1; /* disable compressed cache */
@@ -791,6 +787,9 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
 
     while (remaining_sectors != 0) {
 
+        l2meta = g_malloc0(sizeof(*l2meta));
+        qemu_co_queue_init(&l2meta->dependent_requests);
+
         trace_qcow2_writev_start_part(qemu_coroutine_self());
         index_in_cluster = sector_num & (s->cluster_sectors - 1);
         n_end = index_in_cluster + remaining_sectors;
@@ -800,17 +799,17 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
         }
 
         ret = qcow2_alloc_cluster_offset(bs, sector_num << 9,
-            index_in_cluster, n_end, &cur_nr_sectors, &l2meta);
+            index_in_cluster, n_end, &cur_nr_sectors, l2meta);
         if (ret < 0) {
             goto fail;
         }
 
-        if (l2meta.nb_clusters > 0 &&
+        if (l2meta->nb_clusters > 0 &&
             (s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS)) {
             qcow2_mark_dirty(bs);
         }
 
-        cluster_offset = l2meta.cluster_offset;
+        cluster_offset = l2meta->cluster_offset;
         assert((cluster_offset & 511) == 0);
 
         qemu_iovec_reset(&hd_qiov);
@@ -847,12 +846,14 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
             goto fail;
         }
 
-        ret = qcow2_alloc_cluster_link_l2(bs, &l2meta);
+        ret = qcow2_alloc_cluster_link_l2(bs, l2meta);
         if (ret < 0) {
             goto fail;
         }
 
-        run_dependent_requests(s, &l2meta);
+        run_dependent_requests(s, l2meta);
+        g_free(l2meta);
+        l2meta = NULL;
 
         remaining_sectors -= cur_nr_sectors;
         sector_num += cur_nr_sectors;
@@ -862,7 +863,10 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
     ret = 0;
 
 fail:
-    run_dependent_requests(s, &l2meta);
+    if (l2meta != NULL) {
+        run_dependent_requests(s, l2meta);
+        g_free(l2meta);
+    }
 
     qemu_co_mutex_unlock(&s->lock);
 

From 060bee8943c27d4d53f65570fafaa2559fcd87c3 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Fri, 7 Dec 2012 18:08:45 +0100
Subject: [PATCH 1944/2270] qcow2: Drop l2meta.cluster_offset

There's no real reason to have an l2meta for normal requests that don't
allocate anything. Before we can get rid of it, we must return the host
cluster offset in a different way.

Signed-off-by: Kevin Wolf 
---
 block/qcow2-cluster.c | 10 ++++++----
 block/qcow2.c         | 14 +++++++-------
 block/qcow2.h         |  5 +----
 3 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 94b7f136fa..c4752ee812 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -856,7 +856,7 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
  * Return 0 on success and -errno in error cases
  */
 int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
-    int n_start, int n_end, int *num, QCowL2Meta *m)
+    int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta *m)
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index, ret, sectors;
@@ -929,7 +929,6 @@ again:
 
     /* If there is something left to allocate, do that now */
     *m = (QCowL2Meta) {
-        .cluster_offset     = cluster_offset,
         .nb_clusters        = 0,
     };
     qemu_co_queue_init(&m->dependent_requests);
@@ -977,9 +976,11 @@ again:
             int alloc_n_start = keep_clusters == 0 ? n_start : 0;
             int nb_sectors = MIN(requested_sectors, avail_sectors);
 
+            if (keep_clusters == 0) {
+                cluster_offset = alloc_cluster_offset;
+            }
+
             *m = (QCowL2Meta) {
-                .cluster_offset = keep_clusters == 0 ?
-                                  alloc_cluster_offset : cluster_offset,
                 .alloc_offset   = alloc_cluster_offset,
                 .offset         = alloc_offset & ~(s->cluster_size - 1),
                 .nb_clusters    = nb_clusters,
@@ -1007,6 +1008,7 @@ again:
 
     assert(sectors > n_start);
     *num = sectors - n_start;
+    *host_offset = cluster_offset;
 
     return 0;
 
diff --git a/block/qcow2.c b/block/qcow2.c
index 71f870d829..66ca12f94e 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -799,7 +799,7 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
         }
 
         ret = qcow2_alloc_cluster_offset(bs, sector_num << 9,
-            index_in_cluster, n_end, &cur_nr_sectors, l2meta);
+            index_in_cluster, n_end, &cur_nr_sectors, &cluster_offset, l2meta);
         if (ret < 0) {
             goto fail;
         }
@@ -809,7 +809,6 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
             qcow2_mark_dirty(bs);
         }
 
-        cluster_offset = l2meta->cluster_offset;
         assert((cluster_offset & 511) == 0);
 
         qemu_iovec_reset(&hd_qiov);
@@ -1132,6 +1131,7 @@ static int preallocate(BlockDriverState *bs)
 {
     uint64_t nb_sectors;
     uint64_t offset;
+    uint64_t host_offset = 0;
     int num;
     int ret;
     QCowL2Meta meta;
@@ -1139,18 +1139,18 @@ static int preallocate(BlockDriverState *bs)
     nb_sectors = bdrv_getlength(bs) >> 9;
     offset = 0;
     qemu_co_queue_init(&meta.dependent_requests);
-    meta.cluster_offset = 0;
 
     while (nb_sectors) {
         num = MIN(nb_sectors, INT_MAX >> 9);
-        ret = qcow2_alloc_cluster_offset(bs, offset, 0, num, &num, &meta);
+        ret = qcow2_alloc_cluster_offset(bs, offset, 0, num, &num,
+                                         &host_offset, &meta);
         if (ret < 0) {
             return ret;
         }
 
         ret = qcow2_alloc_cluster_link_l2(bs, &meta);
         if (ret < 0) {
-            qcow2_free_any_clusters(bs, meta.cluster_offset, meta.nb_clusters);
+            qcow2_free_any_clusters(bs, meta.alloc_offset, meta.nb_clusters);
             return ret;
         }
 
@@ -1169,10 +1169,10 @@ static int preallocate(BlockDriverState *bs)
      * all of the allocated clusters (otherwise we get failing reads after
      * EOF). Extend the image to the last allocated sector.
      */
-    if (meta.cluster_offset != 0) {
+    if (host_offset != 0) {
         uint8_t buf[512];
         memset(buf, 0, 512);
-        ret = bdrv_write(bs->file, (meta.cluster_offset >> 9) + num - 1, buf, 1);
+        ret = bdrv_write(bs->file, (host_offset >> 9) + num - 1, buf, 1);
         if (ret < 0) {
             return ret;
         }
diff --git a/block/qcow2.h b/block/qcow2.h
index 1106b33206..24f100125c 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -213,9 +213,6 @@ typedef struct QCowL2Meta
     /** Guest offset of the first newly allocated cluster */
     uint64_t offset;
 
-    /** Host offset of the first cluster of the request */
-    uint64_t cluster_offset;
-
     /** Host offset of the first newly allocated cluster */
     uint64_t alloc_offset;
 
@@ -336,7 +333,7 @@ void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
 int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
     int *num, uint64_t *cluster_offset);
 int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
-    int n_start, int n_end, int *num, QCowL2Meta *m);
+    int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta *m);
 uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
                                          uint64_t offset,
                                          int compressed_size);

From f50f88b9fea09fef12cc293126cf45dcf0ef600b Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Fri, 7 Dec 2012 18:08:46 +0100
Subject: [PATCH 1945/2270] qcow2: Allocate l2meta only for cluster allocations

Even for writes to already allocated clusters, an l2meta is allocated,
though it stays effectively unused. After this patch, only allocating
requests still have one. Each l2meta now describes an in-flight request
that writes to clusters that are not yet hooked up in the L2 table.

Signed-off-by: Kevin Wolf 
---
 block/qcow2-cluster.c | 23 +++++++++--------------
 block/qcow2.c         | 32 +++++++++++++++++---------------
 block/qcow2.h         |  7 +++++--
 3 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index c4752ee812..c2b59e7d6a 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -652,9 +652,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
     uint64_t cluster_offset = m->alloc_offset;
 
     trace_qcow2_cluster_link_l2(qemu_coroutine_self(), m->nb_clusters);
-
-    if (m->nb_clusters == 0)
-        return 0;
+    assert(m->nb_clusters > 0);
 
     old_cluster = g_malloc(m->nb_clusters * sizeof(uint64_t));
 
@@ -856,7 +854,7 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
  * Return 0 on success and -errno in error cases
  */
 int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
-    int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta *m)
+    int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta **m)
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index, ret, sectors;
@@ -928,11 +926,6 @@ again:
     }
 
     /* If there is something left to allocate, do that now */
-    *m = (QCowL2Meta) {
-        .nb_clusters        = 0,
-    };
-    qemu_co_queue_init(&m->dependent_requests);
-
     if (nb_clusters > 0) {
         uint64_t alloc_offset;
         uint64_t alloc_cluster_offset;
@@ -980,7 +973,9 @@ again:
                 cluster_offset = alloc_cluster_offset;
             }
 
-            *m = (QCowL2Meta) {
+            *m = g_malloc0(sizeof(**m));
+
+            **m = (QCowL2Meta) {
                 .alloc_offset   = alloc_cluster_offset,
                 .offset         = alloc_offset & ~(s->cluster_size - 1),
                 .nb_clusters    = nb_clusters,
@@ -995,8 +990,8 @@ again:
                     .nb_sectors = avail_sectors - nb_sectors,
                 },
             };
-            qemu_co_queue_init(&m->dependent_requests);
-            QLIST_INSERT_HEAD(&s->cluster_allocs, m, next_in_flight);
+            qemu_co_queue_init(&(*m)->dependent_requests);
+            QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
         }
     }
 
@@ -1013,8 +1008,8 @@ again:
     return 0;
 
 fail:
-    if (m->nb_clusters > 0) {
-        QLIST_REMOVE(m, next_in_flight);
+    if (*m && (*m)->nb_clusters > 0) {
+        QLIST_REMOVE(*m, next_in_flight);
     }
     return ret;
 }
diff --git a/block/qcow2.c b/block/qcow2.c
index 66ca12f94e..08d92cc6e3 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -787,8 +787,7 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
 
     while (remaining_sectors != 0) {
 
-        l2meta = g_malloc0(sizeof(*l2meta));
-        qemu_co_queue_init(&l2meta->dependent_requests);
+        l2meta = NULL;
 
         trace_qcow2_writev_start_part(qemu_coroutine_self());
         index_in_cluster = sector_num & (s->cluster_sectors - 1);
@@ -799,7 +798,7 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
         }
 
         ret = qcow2_alloc_cluster_offset(bs, sector_num << 9,
-            index_in_cluster, n_end, &cur_nr_sectors, &cluster_offset, l2meta);
+            index_in_cluster, n_end, &cur_nr_sectors, &cluster_offset, &l2meta);
         if (ret < 0) {
             goto fail;
         }
@@ -845,14 +844,16 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
             goto fail;
         }
 
-        ret = qcow2_alloc_cluster_link_l2(bs, l2meta);
-        if (ret < 0) {
-            goto fail;
-        }
+        if (l2meta != NULL) {
+            ret = qcow2_alloc_cluster_link_l2(bs, l2meta);
+            if (ret < 0) {
+                goto fail;
+            }
 
-        run_dependent_requests(s, l2meta);
-        g_free(l2meta);
-        l2meta = NULL;
+            run_dependent_requests(s, l2meta);
+            g_free(l2meta);
+            l2meta = NULL;
+        }
 
         remaining_sectors -= cur_nr_sectors;
         sector_num += cur_nr_sectors;
@@ -1134,11 +1135,10 @@ static int preallocate(BlockDriverState *bs)
     uint64_t host_offset = 0;
     int num;
     int ret;
-    QCowL2Meta meta;
+    QCowL2Meta *meta;
 
     nb_sectors = bdrv_getlength(bs) >> 9;
     offset = 0;
-    qemu_co_queue_init(&meta.dependent_requests);
 
     while (nb_sectors) {
         num = MIN(nb_sectors, INT_MAX >> 9);
@@ -1148,15 +1148,17 @@ static int preallocate(BlockDriverState *bs)
             return ret;
         }
 
-        ret = qcow2_alloc_cluster_link_l2(bs, &meta);
+        ret = qcow2_alloc_cluster_link_l2(bs, meta);
         if (ret < 0) {
-            qcow2_free_any_clusters(bs, meta.alloc_offset, meta.nb_clusters);
+            qcow2_free_any_clusters(bs, meta->alloc_offset, meta->nb_clusters);
             return ret;
         }
 
         /* There are no dependent requests, but we need to remove our request
          * from the list of in-flight requests */
-        run_dependent_requests(bs->opaque, &meta);
+        if (meta != NULL) {
+            run_dependent_requests(bs->opaque, meta);
+        }
 
         /* TODO Preallocate data if requested */
 
diff --git a/block/qcow2.h b/block/qcow2.h
index 24f100125c..6dc79b5af4 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -207,7 +207,10 @@ typedef struct Qcow2COWRegion {
     int         nb_sectors;
 } Qcow2COWRegion;
 
-/* XXX This could be private for qcow2-cluster.c */
+/**
+ * Describes an in-flight (part of a) write request that writes to clusters
+ * that are not referenced in their L2 table yet.
+ */
 typedef struct QCowL2Meta
 {
     /** Guest offset of the first newly allocated cluster */
@@ -333,7 +336,7 @@ void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
 int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
     int *num, uint64_t *cluster_offset);
 int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
-    int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta *m);
+    int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta **m);
 uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
                                          uint64_t offset,
                                          int compressed_size);

From 280d373579558f73a8b70e329d9a6206933d3809 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Fri, 7 Dec 2012 18:08:47 +0100
Subject: [PATCH 1946/2270] qcow2: Enable dirty flag in
 qcow2_alloc_cluster_link_l2

This is closer to where the dirty flag is really needed, and it avoids
having checks for special cases related to cluster allocation directly
in the writev loop.

Signed-off-by: Kevin Wolf 
---
 block/qcow2-cluster.c | 5 ++++-
 block/qcow2.c         | 7 +------
 block/qcow2.h         | 2 ++
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index c2b59e7d6a..7a038aca40 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -668,11 +668,14 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
     }
 
     /* Update L2 table. */
-
+    if (s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS) {
+        qcow2_mark_dirty(bs);
+    }
     if (qcow2_need_accurate_refcounts(s)) {
         qcow2_cache_set_dependency(bs, s->l2_table_cache,
                                    s->refcount_block_cache);
     }
+
     ret = get_cluster_table(bs, m->offset, &l2_table, &l2_index);
     if (ret < 0) {
         goto err;
diff --git a/block/qcow2.c b/block/qcow2.c
index 08d92cc6e3..dbcc0fff97 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -222,7 +222,7 @@ static void report_unsupported_feature(BlockDriverState *bs,
  * updated successfully.  Therefore it is not required to check the return
  * value of this function.
  */
-static int qcow2_mark_dirty(BlockDriverState *bs)
+int qcow2_mark_dirty(BlockDriverState *bs)
 {
     BDRVQcowState *s = bs->opaque;
     uint64_t val;
@@ -803,11 +803,6 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
             goto fail;
         }
 
-        if (l2meta->nb_clusters > 0 &&
-            (s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS)) {
-            qcow2_mark_dirty(bs);
-        }
-
         assert((cluster_offset & 511) == 0);
 
         qemu_iovec_reset(&hd_qiov);
diff --git a/block/qcow2.h b/block/qcow2.h
index 6dc79b5af4..a60fcb429a 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -303,6 +303,8 @@ static inline bool qcow2_need_accurate_refcounts(BDRVQcowState *s)
 /* qcow2.c functions */
 int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov,
                   int64_t sector_num, int nb_sectors);
+
+int qcow2_mark_dirty(BlockDriverState *bs);
 int qcow2_update_header(BlockDriverState *bs);
 
 /* qcow2-refcount.c functions */

From 4e95314e2bb7baa64f2a9026df5e2649081b7060 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Fri, 7 Dec 2012 18:08:48 +0100
Subject: [PATCH 1947/2270] qcow2: Execute run_dependent_requests() without
 lock

There's no reason for run_dependent_requests() to hold s->lock, and a
later patch will require that in fact the lock is not held.

Also, before this patch, run_dependent_requests() not only does what its
name suggests, but also removes the l2meta from the list of in-flight
requests. When changing this, it becomes an one-liner, so just inline it
completely.

Signed-off-by: Kevin Wolf 
---
 block/qcow2.c | 36 ++++++++++++++++--------------------
 1 file changed, 16 insertions(+), 20 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index dbcc0fff97..8520bda21a 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -745,21 +745,6 @@ fail:
     return ret;
 }
 
-static void run_dependent_requests(BDRVQcowState *s, QCowL2Meta *m)
-{
-    /* Take the request off the list of running requests */
-    if (m->nb_clusters != 0) {
-        QLIST_REMOVE(m, next_in_flight);
-    }
-
-    /* Restart all dependent requests */
-    if (!qemu_co_queue_empty(&m->dependent_requests)) {
-        qemu_co_mutex_unlock(&s->lock);
-        qemu_co_queue_restart_all(&m->dependent_requests);
-        qemu_co_mutex_lock(&s->lock);
-    }
-}
-
 static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
                            int64_t sector_num,
                            int remaining_sectors,
@@ -845,7 +830,15 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
                 goto fail;
             }
 
-            run_dependent_requests(s, l2meta);
+            /* Take the request off the list of running requests */
+            if (l2meta->nb_clusters != 0) {
+                QLIST_REMOVE(l2meta, next_in_flight);
+            }
+
+            qemu_co_mutex_unlock(&s->lock);
+            qemu_co_queue_restart_all(&l2meta->dependent_requests);
+            qemu_co_mutex_lock(&s->lock);
+
             g_free(l2meta);
             l2meta = NULL;
         }
@@ -858,13 +851,16 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
     ret = 0;
 
 fail:
+    qemu_co_mutex_unlock(&s->lock);
+
     if (l2meta != NULL) {
-        run_dependent_requests(s, l2meta);
+        if (l2meta->nb_clusters != 0) {
+            QLIST_REMOVE(l2meta, next_in_flight);
+        }
+        qemu_co_queue_restart_all(&l2meta->dependent_requests);
         g_free(l2meta);
     }
 
-    qemu_co_mutex_unlock(&s->lock);
-
     qemu_iovec_destroy(&hd_qiov);
     qemu_vfree(cluster_data);
     trace_qcow2_writev_done_req(qemu_coroutine_self(), ret);
@@ -1152,7 +1148,7 @@ static int preallocate(BlockDriverState *bs)
         /* There are no dependent requests, but we need to remove our request
          * from the list of in-flight requests */
         if (meta != NULL) {
-            run_dependent_requests(bs->opaque, meta);
+            QLIST_REMOVE(meta, next_in_flight);
         }
 
         /* TODO Preallocate data if requested */

From 226c3c26b9800b7c6a8d3100e1faad6d2b97b0f5 Mon Sep 17 00:00:00 2001
From: Kevin Wolf 
Date: Fri, 7 Dec 2012 18:08:49 +0100
Subject: [PATCH 1948/2270] qcow2: Factor out handle_dependencies()

Signed-off-by: Kevin Wolf 
---
 block/qcow2-cluster.c | 70 ++++++++++++++++++++++++++-----------------
 1 file changed, 42 insertions(+), 28 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 7a038aca40..468ef1be56 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -753,38 +753,16 @@ out:
 }
 
 /*
- * Allocates new clusters for the given guest_offset.
- *
- * At most *nb_clusters are allocated, and on return *nb_clusters is updated to
- * contain the number of clusters that have been allocated and are contiguous
- * in the image file.
- *
- * If *host_offset is non-zero, it specifies the offset in the image file at
- * which the new clusters must start. *nb_clusters can be 0 on return in this
- * case if the cluster at host_offset is already in use. If *host_offset is
- * zero, the clusters can be allocated anywhere in the image file.
- *
- * *host_offset is updated to contain the offset into the image file at which
- * the first allocated cluster starts.
- *
- * Return 0 on success and -errno in error cases. -EAGAIN means that the
- * function has been waiting for another request and the allocation must be
- * restarted, but the whole request should not be failed.
+ * Check if there already is an AIO write request in flight which allocates
+ * the same cluster. In this case we need to wait until the previous
+ * request has completed and updated the L2 table accordingly.
  */
-static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
-    uint64_t *host_offset, unsigned int *nb_clusters)
+static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
+    unsigned int *nb_clusters)
 {
     BDRVQcowState *s = bs->opaque;
     QCowL2Meta *old_alloc;
 
-    trace_qcow2_do_alloc_clusters_offset(qemu_coroutine_self(), guest_offset,
-                                         *host_offset, *nb_clusters);
-
-    /*
-     * Check if there already is an AIO write request in flight which allocates
-     * the same cluster. In this case we need to wait until the previous
-     * request has completed and updated the L2 table accordingly.
-     */
     QLIST_FOREACH(old_alloc, &s->cluster_allocs, next_in_flight) {
 
         uint64_t start = guest_offset >> s->cluster_bits;
@@ -817,6 +795,42 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
         abort();
     }
 
+    return 0;
+}
+
+/*
+ * Allocates new clusters for the given guest_offset.
+ *
+ * At most *nb_clusters are allocated, and on return *nb_clusters is updated to
+ * contain the number of clusters that have been allocated and are contiguous
+ * in the image file.
+ *
+ * If *host_offset is non-zero, it specifies the offset in the image file at
+ * which the new clusters must start. *nb_clusters can be 0 on return in this
+ * case if the cluster at host_offset is already in use. If *host_offset is
+ * zero, the clusters can be allocated anywhere in the image file.
+ *
+ * *host_offset is updated to contain the offset into the image file at which
+ * the first allocated cluster starts.
+ *
+ * Return 0 on success and -errno in error cases. -EAGAIN means that the
+ * function has been waiting for another request and the allocation must be
+ * restarted, but the whole request should not be failed.
+ */
+static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
+    uint64_t *host_offset, unsigned int *nb_clusters)
+{
+    BDRVQcowState *s = bs->opaque;
+    int ret;
+
+    trace_qcow2_do_alloc_clusters_offset(qemu_coroutine_self(), guest_offset,
+                                         *host_offset, *nb_clusters);
+
+    ret = handle_dependencies(bs, guest_offset, nb_clusters);
+    if (ret < 0) {
+        return ret;
+    }
+
     /* Allocate new clusters */
     trace_qcow2_cluster_alloc_phys(qemu_coroutine_self());
     if (*host_offset == 0) {
@@ -828,7 +842,7 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
         *host_offset = cluster_offset;
         return 0;
     } else {
-        int ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters);
+        ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters);
         if (ret < 0) {
             return ret;
         }

From 044f4c8b0ee90290b6cbbc616c4be3c8aeffcaab Mon Sep 17 00:00:00 2001
From: David Gibson 
Date: Mon, 12 Nov 2012 16:46:49 +0000
Subject: [PATCH 1949/2270] pseries: Fix incorrect initialization of interrupt
 controller

Currently in the reset code for the XICS interrupt controller, we
initialize the pending_priority field to 0 (most favored, by XICS
convention).  This is incorrect, since there is no pending interrupt, it
should be set to least favored - 0xff.  At the moment our XICS
implementation doesn't get hurt by this edge case, but it does confuse the
upcoming kernel XICS implementation.

Signed-off-by: David Gibson 
Signed-off-by: Alexander Graf 
---
 hw/xics.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/xics.c b/hw/xics.c
index 1da310653b..edf58339c0 100644
--- a/hw/xics.c
+++ b/hw/xics.c
@@ -495,7 +495,7 @@ static void xics_reset(void *opaque)
 
     for (i = 0; i < icp->nr_servers; i++) {
         icp->ss[i].xirr = 0;
-        icp->ss[i].pending_priority = 0;
+        icp->ss[i].pending_priority = 0xff;
         icp->ss[i].mfrr = 0xff;
         /* Make all outputs are deasserted */
         qemu_set_irq(icp->ss[i].output, 0);

From bf3bc4c4e992fb9914e2f1f7e8a569394d298b57 Mon Sep 17 00:00:00 2001
From: Ben Herrenschmidt 
Date: Mon, 12 Nov 2012 16:46:50 +0000
Subject: [PATCH 1950/2270] pseries: Use #define for XICS base irq number

Currently the lowest "real" irq number for the XICS irq controller (as
opposed to numbers reserved for IPIs and other special purposes) is
hard coded as 16 in two places - in xics_system_init() and in spapr.c.

As well as being generally bad practice, we're going to need to change this
number soon to fit in with the in-kernel XICS implementation.  This patch
adds a #define for this number to avoid future breakage.

Signed-off-by: Michael Ellerman 
Signed-off-by: Ben Herrenschmidt 
Signed-off-by: David Gibson 
Signed-off-by: Alexander Graf 
---
 hw/spapr.c | 2 +-
 hw/xics.c  | 2 +-
 hw/xics.h  | 1 +
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/hw/spapr.c b/hw/spapr.c
index ad3f0ea7fc..eafee0313d 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -801,7 +801,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
 
     /* Set up Interrupt Controller */
     spapr->icp = xics_system_init(XICS_IRQS);
-    spapr->next_irq = 16;
+    spapr->next_irq = XICS_IRQ_BASE;
 
     /* Set up EPOW events infrastructure */
     spapr_events_init(spapr);
diff --git a/hw/xics.c b/hw/xics.c
index edf58339c0..b8887cd9c7 100644
--- a/hw/xics.c
+++ b/hw/xics.c
@@ -549,7 +549,7 @@ struct icp_state *xics_system_init(int nr_irqs)
 
     ics = g_malloc0(sizeof(*ics));
     ics->nr_irqs = nr_irqs;
-    ics->offset = 16;
+    ics->offset = XICS_IRQ_BASE;
     ics->irqs = g_malloc0(nr_irqs * sizeof(struct ics_irq_state));
 
     icp->ics = ics;
diff --git a/hw/xics.h b/hw/xics.h
index 6817268697..c3bf0083e2 100644
--- a/hw/xics.h
+++ b/hw/xics.h
@@ -28,6 +28,7 @@
 #define __XICS_H__
 
 #define XICS_IPI        0x2
+#define XICS_IRQ_BASE   0x10
 
 struct icp_state;
 

From 4aac82c34675fcbd3722dfc3a2d04c839215ec6b Mon Sep 17 00:00:00 2001
From: Michael Ellerman 
Date: Mon, 12 Nov 2012 16:46:52 +0000
Subject: [PATCH 1951/2270] pseries: Return the token when we register an RTAS
 call

The kernel will soon be able to service some RTAS calls. However the
choice of tokens will still be up to userspace. To support this have
spapr_rtas_register() return the token that is allocated for an
RTAS call, that allows the calling code to tell the kernel what the
token value is.

Signed-off-by: Michael Ellerman 
Signed-off-by: Benjamin Herrenschmidt 
Signed-off-by: David Gibson 
Signed-off-by: Alexander Graf 
---
 hw/spapr.h      | 2 +-
 hw/spapr_rtas.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/spapr.h b/hw/spapr.h
index efe7f5758f..971a50ab02 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -320,7 +320,7 @@ static inline void rtas_st(target_ulong phys, int n, uint32_t val)
 typedef void (*spapr_rtas_fn)(sPAPREnvironment *spapr, uint32_t token,
                               uint32_t nargs, target_ulong args,
                               uint32_t nret, target_ulong rets);
-void spapr_rtas_register(const char *name, spapr_rtas_fn fn);
+int spapr_rtas_register(const char *name, spapr_rtas_fn fn);
 target_ulong spapr_rtas_call(sPAPREnvironment *spapr,
                              uint32_t token, uint32_t nargs, target_ulong args,
                              uint32_t nret, target_ulong rets);
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index 6d5c48a740..45294e8305 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -242,7 +242,7 @@ target_ulong spapr_rtas_call(sPAPREnvironment *spapr,
     return H_PARAMETER;
 }
 
-void spapr_rtas_register(const char *name, spapr_rtas_fn fn)
+int spapr_rtas_register(const char *name, spapr_rtas_fn fn)
 {
     int i;
 
@@ -258,7 +258,7 @@ void spapr_rtas_register(const char *name, spapr_rtas_fn fn)
     rtas_next->name = name;
     rtas_next->fn = fn;
 
-    rtas_next++;
+    return (rtas_next++ - rtas_table) + TOKEN_BASE;
 }
 
 int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,

From d36b66f7a420737dcc24de15b35a465ff6b1798d Mon Sep 17 00:00:00 2001
From: Ben Herrenschmidt 
Date: Mon, 12 Nov 2012 16:46:53 +0000
Subject: [PATCH 1952/2270] pseries: Allow RTAS tokens without a qemu handler

Kernel-based RTAS calls will not have a qemu handler, but will
still be registered in qemu in order to be assigned a token
number and appear in the device-tree.

Let's test for the name being NULL rather than the handler
when deciding to skip an entry while building the device-tree

Signed-off-by: Benjamin Herrenschmidt 
Signed-off-by: David Gibson 
Signed-off-by: Alexander Graf 
---
 hw/spapr_rtas.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index 45294e8305..e618c2db53 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -301,7 +301,7 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
     for (i = 0; i < TOKEN_MAX; i++) {
         struct rtas_call *call = &rtas_table[i];
 
-        if (!call->fn) {
+        if (!call->name) {
             continue;
         }
 

From 500efa2319d1f1074b1d61e5ceb7a0fd61d0831d Mon Sep 17 00:00:00 2001
From: David Gibson 
Date: Mon, 12 Nov 2012 16:46:54 +0000
Subject: [PATCH 1953/2270] pseries: Add tracepoints to the XICS interrupt
 controller

This patch adds tracing / debugging calls to the XICS interrupt controller
implementation used on the pseries machine.

Signed-off-by: Ben Herrenschmidt 
Signed-off-by: David Gibson 
Signed-off-by: Alexander Graf 
---
 hw/xics.c    | 23 ++++++++++++++++++++---
 trace-events | 13 +++++++++++++
 2 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/hw/xics.c b/hw/xics.c
index b8887cd9c7..33f99c7757 100644
--- a/hw/xics.c
+++ b/hw/xics.c
@@ -26,6 +26,7 @@
  */
 
 #include "hw.h"
+#include "trace.h"
 #include "hw/spapr.h"
 #include "hw/xics.h"
 
@@ -66,6 +67,8 @@ static void icp_check_ipi(struct icp_state *icp, int server)
         return;
     }
 
+    trace_xics_icp_check_ipi(server, ss->mfrr);
+
     if (XISR(ss)) {
         ics_reject(icp->ics, XISR(ss));
     }
@@ -120,11 +123,13 @@ static void icp_set_mfrr(struct icp_state *icp, int server, uint8_t mfrr)
 
 static uint32_t icp_accept(struct icp_server_state *ss)
 {
-    uint32_t xirr;
+    uint32_t xirr = ss->xirr;
 
     qemu_irq_lower(ss->output);
-    xirr = ss->xirr;
     ss->xirr = ss->pending_priority << 24;
+
+    trace_xics_icp_accept(xirr, ss->xirr);
+
     return xirr;
 }
 
@@ -134,6 +139,7 @@ static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr)
 
     /* Send EOI -> ICS */
     ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
+    trace_xics_icp_eoi(server, xirr, ss->xirr);
     ics_eoi(icp->ics, xirr & XISR_MASK);
     if (!XISR(ss)) {
         icp_resend(icp, server);
@@ -144,6 +150,8 @@ static void icp_irq(struct icp_state *icp, int server, int nr, uint8_t priority)
 {
     struct icp_server_state *ss = icp->ss + server;
 
+    trace_xics_icp_irq(server, nr, priority);
+
     if ((priority >= CPPR(ss))
         || (XISR(ss) && (ss->pending_priority <= priority))) {
         ics_reject(icp->ics, nr);
@@ -153,6 +161,7 @@ static void icp_irq(struct icp_state *icp, int server, int nr, uint8_t priority)
         }
         ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
         ss->pending_priority = priority;
+        trace_xics_icp_raise(ss->xirr, ss->pending_priority);
         qemu_irq_raise(ss->output);
     }
 }
@@ -217,10 +226,12 @@ static void set_irq_msi(struct ics_state *ics, int srcno, int val)
 {
     struct ics_irq_state *irq = ics->irqs + srcno;
 
+    trace_xics_set_irq_msi(srcno, srcno + ics->offset);
+
     if (val) {
         if (irq->priority == 0xff) {
             irq->status |= XICS_STATUS_MASKED_PENDING;
-            /* masked pending */ ;
+            trace_xics_masked_pending();
         } else  {
             icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
         }
@@ -231,6 +242,7 @@ static void set_irq_lsi(struct ics_state *ics, int srcno, int val)
 {
     struct ics_irq_state *irq = ics->irqs + srcno;
 
+    trace_xics_set_irq_lsi(srcno, srcno + ics->offset);
     if (val) {
         irq->status |= XICS_STATUS_ASSERTED;
     } else {
@@ -279,6 +291,8 @@ static void ics_write_xive(struct ics_state *ics, int nr, int server,
     irq->priority = priority;
     irq->saved_priority = saved_priority;
 
+    trace_xics_ics_write_xive(nr, srcno, server, priority);
+
     if (irq->lsi) {
         write_xive_lsi(ics, srcno);
     } else {
@@ -290,6 +304,7 @@ static void ics_reject(struct ics_state *ics, int nr)
 {
     struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
 
+    trace_xics_ics_reject(nr, nr - ics->offset);
     irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */
     irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */
 }
@@ -315,6 +330,8 @@ static void ics_eoi(struct ics_state *ics, int nr)
     int srcno = nr - ics->offset;
     struct ics_irq_state *irq = ics->irqs + srcno;
 
+    trace_xics_ics_eoi(nr);
+
     if (irq->lsi) {
         irq->status &= ~XICS_STATUS_SENT;
     }
diff --git a/trace-events b/trace-events
index 6c6cbf10fd..6cb450a993 100644
--- a/trace-events
+++ b/trace-events
@@ -1022,3 +1022,16 @@ spapr_pci_rtas_ibm_change_msi(unsigned func, unsigned req) "func %u, requested %
 spapr_pci_rtas_ibm_query_interrupt_source_number(unsigned ioa, unsigned intr) "queries for #%u, IRQ%u"
 spapr_pci_msi_write(uint64_t addr, uint64_t data, uint32_t dt_irq) "@%"PRIx64"<=%"PRIx64" IRQ %u"
 spapr_pci_lsi_set(const char *busname, int pin, uint32_t irq) "%s PIN%d IRQ %u"
+
+# hw/xics.c
+xics_icp_check_ipi(int server, uint8_t mfrr) "CPU %d can take IPI mfrr=%#x"
+xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) "icp_accept: XIRR %#"PRIx32"->%#"PRIx32
+xics_icp_eoi(int server, uint32_t xirr, uint32_t new_xirr) "icp_eoi: server %d given XIRR %#"PRIx32" new XIRR %#"PRIx32
+xics_icp_irq(int server, int nr, uint8_t priority) "cpu %d trying to deliver irq %#"PRIx32" priority %#x"
+xics_icp_raise(uint32_t xirr, uint8_t pending_priority) "raising IRQ new XIRR=%#x new pending priority=%#x"
+xics_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
+xics_masked_pending(void) "set_irq_msi: masked pending"
+xics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
+xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
+xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]"
+xics_ics_eoi(int nr) "ics_eoi: irq %#x"

From 22a2611c9cef4a8c8ad96fe17b3511a6cc5fb3a1 Mon Sep 17 00:00:00 2001
From: David Gibson 
Date: Mon, 12 Nov 2012 16:46:55 +0000
Subject: [PATCH 1954/2270] pseries: Split xics irq configuration from state
 information

Currently the XICS irq controller code has a per-irq state structure which
amongst other things includes whether the interrupt is level or message
triggered - this is configured by the platform code, and is not directly
visible to the guest.  This leads to a slightly awkward construct at reset
time where we need to reset everything in the state structure _except_ the
lsi/msi flag, which needs to retain the information given at platform init
time.

More importantly this flag will make matching the qemu state to the KVM
state for the upcoming in-kernel XICS implementation more awkward.  This
patch, therefore, removes this flag from the per-irq state structure,
instead adding a parallel array giving the lsi/msi configuration per irq.

Signed-off-by: David Gibson 
Signed-off-by: Alexander Graf 
---
 hw/xics.c | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/hw/xics.c b/hw/xics.c
index 33f99c7757..55899ce77d 100644
--- a/hw/xics.c
+++ b/hw/xics.c
@@ -179,13 +179,13 @@ struct ics_irq_state {
 #define XICS_STATUS_REJECTED           0x4
 #define XICS_STATUS_MASKED_PENDING     0x8
     uint8_t status;
-    bool lsi;
 };
 
 struct ics_state {
     int nr_irqs;
     int offset;
     qemu_irq *qirqs;
+    bool *islsi;
     struct ics_irq_state *irqs;
     struct icp_state *icp;
 };
@@ -254,9 +254,8 @@ static void set_irq_lsi(struct ics_state *ics, int srcno, int val)
 static void ics_set_irq(void *opaque, int srcno, int val)
 {
     struct ics_state *ics = (struct ics_state *)opaque;
-    struct ics_irq_state *irq = ics->irqs + srcno;
 
-    if (irq->lsi) {
+    if (ics->islsi[srcno]) {
         set_irq_lsi(ics, srcno, val);
     } else {
         set_irq_msi(ics, srcno, val);
@@ -293,7 +292,7 @@ static void ics_write_xive(struct ics_state *ics, int nr, int server,
 
     trace_xics_ics_write_xive(nr, srcno, server, priority);
 
-    if (irq->lsi) {
+    if (ics->islsi[srcno]) {
         write_xive_lsi(ics, srcno);
     } else {
         write_xive_msi(ics, srcno);
@@ -314,10 +313,8 @@ static void ics_resend(struct ics_state *ics)
     int i;
 
     for (i = 0; i < ics->nr_irqs; i++) {
-        struct ics_irq_state *irq = ics->irqs + i;
-
         /* FIXME: filter by server#? */
-        if (irq->lsi) {
+        if (ics->islsi[i]) {
             resend_lsi(ics, i);
         } else {
             resend_msi(ics, i);
@@ -332,7 +329,7 @@ static void ics_eoi(struct ics_state *ics, int nr)
 
     trace_xics_ics_eoi(nr);
 
-    if (irq->lsi) {
+    if (ics->islsi[srcno]) {
         irq->status &= ~XICS_STATUS_SENT;
     }
 }
@@ -354,7 +351,7 @@ void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi)
 {
     assert(ics_valid_irq(icp->ics, irq));
 
-    icp->ics->irqs[irq - icp->ics->offset].lsi = lsi;
+    icp->ics->islsi[irq - icp->ics->offset] = lsi;
 }
 
 static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
@@ -518,10 +515,8 @@ static void xics_reset(void *opaque)
         qemu_set_irq(icp->ss[i].output, 0);
     }
 
+    memset(ics->irqs, 0, sizeof(struct ics_irq_state) * ics->nr_irqs);
     for (i = 0; i < ics->nr_irqs; i++) {
-        /* Reset everything *except* the type */
-        ics->irqs[i].server = 0;
-        ics->irqs[i].status = 0;
         ics->irqs[i].priority = 0xff;
         ics->irqs[i].saved_priority = 0xff;
     }
@@ -568,6 +563,7 @@ struct icp_state *xics_system_init(int nr_irqs)
     ics->nr_irqs = nr_irqs;
     ics->offset = XICS_IRQ_BASE;
     ics->irqs = g_malloc0(nr_irqs * sizeof(struct ics_irq_state));
+    ics->islsi = g_malloc0(nr_irqs * sizeof(bool));
 
     icp->ics = ics;
     ics->icp = icp;

From 639e8102ae71ce2e46ebeffc6080767e573c0c56 Mon Sep 17 00:00:00 2001
From: David Gibson 
Date: Mon, 12 Nov 2012 16:46:57 +0000
Subject: [PATCH 1955/2270] pseries: Implement PAPR NVRAM

The PAPR specification requires a certain amount of NVRAM, accessed via
RTAS, which we don't currently implement in qemu.  This patch addresses
this deficiency, implementing the NVRAM as a VIO device, with some glue to
instantiate it automatically based on a machine option.

The machine option specifies a drive id, which is used to back the NVRAM,
making it persistent.  If nothing is specified, the driver instead simply
allocates space for the NVRAM, which will not be persistent

Signed-off-by: David Gibson 
Signed-off-by: Alexander Graf 
---
 hw/ppc/Makefile.objs |   2 +-
 hw/spapr.c           |  33 ++++++++
 hw/spapr.h           |   2 +
 hw/spapr_nvram.c     | 196 +++++++++++++++++++++++++++++++++++++++++++
 qemu-config.c        |   4 +
 5 files changed, 236 insertions(+), 1 deletion(-)
 create mode 100644 hw/spapr_nvram.c

diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 8fe21235f0..44921273c3 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -11,7 +11,7 @@ obj-y += ppc_newworld.o
 obj-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
 obj-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
 obj-$(CONFIG_PSERIES) += spapr_pci.o pci-hotplug.o spapr_iommu.o
-obj-$(CONFIG_PSERIES) += spapr_events.o
+obj-$(CONFIG_PSERIES) += spapr_events.o spapr_nvram.o
 # PowerPC 4xx boards
 obj-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
 obj-y += ppc440_bamboo.o
diff --git a/hw/spapr.c b/hw/spapr.c
index eafee0313d..d23aa9d7c1 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -657,6 +657,36 @@ static void spapr_cpu_reset(void *opaque)
         (spapr->htab_shift - 18);
 }
 
+static void spapr_create_nvram(sPAPREnvironment *spapr)
+{
+    QemuOpts *machine_opts;
+    DeviceState *dev;
+
+    dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
+
+    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
+    if (machine_opts) {
+        const char *drivename;
+
+        drivename = qemu_opt_get(machine_opts, "nvram");
+        if (drivename) {
+            BlockDriverState *bs;
+
+            bs = bdrv_find(drivename);
+            if (!bs) {
+                fprintf(stderr, "No such block device \"%s\" for nvram\n",
+                        drivename);
+                exit(1);
+            }
+            qdev_prop_set_drive_nofail(dev, "drive", bs);
+        }
+    }
+
+    qdev_init_nofail(dev);
+
+    spapr->nvram = (struct sPAPRNVRAM *)dev;
+}
+
 /* Returns whether we want to use VGA or not */
 static int spapr_vga_init(PCIBus *pci_bus)
 {
@@ -818,6 +848,9 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
         }
     }
 
+    /* We always have at least the nvram device on VIO */
+    spapr_create_nvram(spapr);
+
     /* Set up PCI */
     spapr_pci_rtas_init();
 
diff --git a/hw/spapr.h b/hw/spapr.h
index 971a50ab02..600722f132 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -6,11 +6,13 @@
 
 struct VIOsPAPRBus;
 struct sPAPRPHBState;
+struct sPAPRNVRAM;
 struct icp_state;
 
 typedef struct sPAPREnvironment {
     struct VIOsPAPRBus *vio_bus;
     QLIST_HEAD(, sPAPRPHBState) phbs;
+    struct sPAPRNVRAM *nvram;
     struct icp_state *icp;
 
     hwaddr ram_limit;
diff --git a/hw/spapr_nvram.c b/hw/spapr_nvram.c
new file mode 100644
index 0000000000..641de485f9
--- /dev/null
+++ b/hw/spapr_nvram.c
@@ -0,0 +1,196 @@
+/*
+ * QEMU sPAPR NVRAM emulation
+ *
+ * Copyright (C) 2012 David Gibson, IBM Corporation.
+ *
+ * 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 
+#include 
+
+#include "device_tree.h"
+#include "hw/sysbus.h"
+#include "hw/spapr.h"
+#include "hw/spapr_vio.h"
+
+typedef struct sPAPRNVRAM {
+    VIOsPAPRDevice sdev;
+    uint32_t size;
+    uint8_t *buf;
+    BlockDriverState *drive;
+} sPAPRNVRAM;
+
+#define MIN_NVRAM_SIZE 8192
+#define DEFAULT_NVRAM_SIZE 16384
+#define MAX_NVRAM_SIZE (UINT16_MAX * 16)
+
+static void rtas_nvram_fetch(sPAPREnvironment *spapr,
+                             uint32_t token, uint32_t nargs,
+                             target_ulong args,
+                             uint32_t nret, target_ulong rets)
+{
+    sPAPRNVRAM *nvram = spapr->nvram;
+    hwaddr offset, buffer, len;
+    int alen;
+    void *membuf;
+
+    if ((nargs != 3) || (nret != 2)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    if (!nvram) {
+        rtas_st(rets, 0, -1);
+        rtas_st(rets, 1, 0);
+        return;
+    }
+
+    offset = rtas_ld(args, 0);
+    buffer = rtas_ld(args, 1);
+    len = rtas_ld(args, 2);
+
+    if (((offset + len) < offset)
+        || ((offset + len) > nvram->size)) {
+        rtas_st(rets, 0, -3);
+        rtas_st(rets, 1, 0);
+        return;
+    }
+
+    membuf = cpu_physical_memory_map(buffer, &len, 1);
+    if (nvram->drive) {
+        alen = bdrv_pread(nvram->drive, offset, membuf, len);
+    } else {
+        assert(nvram->buf);
+
+        memcpy(membuf, nvram->buf + offset, len);
+        alen = len;
+    }
+    cpu_physical_memory_unmap(membuf, len, 1, len);
+
+    rtas_st(rets, 0, (alen < len) ? -1 : 0);
+    rtas_st(rets, 1, (alen < 0) ? 0 : alen);
+}
+
+static void rtas_nvram_store(sPAPREnvironment *spapr,
+                             uint32_t token, uint32_t nargs,
+                             target_ulong args,
+                             uint32_t nret, target_ulong rets)
+{
+    sPAPRNVRAM *nvram = spapr->nvram;
+    hwaddr offset, buffer, len;
+    int alen;
+    void *membuf;
+
+    if ((nargs != 3) || (nret != 2)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    if (!nvram) {
+        rtas_st(rets, 0, -1);
+        return;
+    }
+
+    offset = rtas_ld(args, 0);
+    buffer = rtas_ld(args, 1);
+    len = rtas_ld(args, 2);
+
+    if (((offset + len) < offset)
+        || ((offset + len) > nvram->size)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    membuf = cpu_physical_memory_map(buffer, &len, 0);
+    if (nvram->drive) {
+        alen = bdrv_pwrite(nvram->drive, offset, membuf, len);
+    } else {
+        assert(nvram->buf);
+
+        memcpy(nvram->buf + offset, membuf, len);
+        alen = len;
+    }
+    cpu_physical_memory_unmap(membuf, len, 0, len);
+
+    rtas_st(rets, 0, (alen < len) ? -1 : 0);
+    rtas_st(rets, 1, (alen < 0) ? 0 : alen);
+}
+
+static int spapr_nvram_init(VIOsPAPRDevice *dev)
+{
+    sPAPRNVRAM *nvram = (sPAPRNVRAM *)dev;
+
+    if (nvram->drive) {
+        nvram->size = bdrv_getlength(nvram->drive);
+    } else {
+        nvram->size = DEFAULT_NVRAM_SIZE;
+        nvram->buf = g_malloc0(nvram->size);
+    }
+
+    if ((nvram->size < MIN_NVRAM_SIZE) || (nvram->size > MAX_NVRAM_SIZE)) {
+        fprintf(stderr, "spapr-nvram must be between %d and %d bytes in size\n",
+                MIN_NVRAM_SIZE, MAX_NVRAM_SIZE);
+        return -1;
+    }
+
+    spapr_rtas_register("nvram-fetch", rtas_nvram_fetch);
+    spapr_rtas_register("nvram-store", rtas_nvram_store);
+
+    return 0;
+}
+
+static int spapr_nvram_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
+{
+    sPAPRNVRAM *nvram = (sPAPRNVRAM *)dev;
+
+    return fdt_setprop_cell(fdt, node_off, "#bytes", nvram->size);
+}
+
+static Property spapr_nvram_properties[] = {
+    DEFINE_SPAPR_PROPERTIES(sPAPRNVRAM, sdev),
+    DEFINE_PROP_DRIVE("drive", sPAPRNVRAM, drive),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void spapr_nvram_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
+
+    k->init = spapr_nvram_init;
+    k->devnode = spapr_nvram_devnode;
+    k->dt_name = "nvram";
+    k->dt_type = "nvram";
+    k->dt_compatible = "qemu,spapr-nvram";
+    dc->props = spapr_nvram_properties;
+}
+
+static const TypeInfo spapr_nvram_type_info = {
+    .name          = "spapr-nvram",
+    .parent        = TYPE_VIO_SPAPR_DEVICE,
+    .instance_size = sizeof(sPAPRNVRAM),
+    .class_init    = spapr_nvram_class_init,
+};
+
+static void spapr_nvram_register_types(void)
+{
+    type_register_static(&spapr_nvram_type_info);
+}
+
+type_init(spapr_nvram_register_types)
diff --git a/qemu-config.c b/qemu-config.c
index aa78fb9ea7..de10051654 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -579,6 +579,10 @@ static QemuOptsList qemu_machine_opts = {
             .name = "usb",
             .type = QEMU_OPT_BOOL,
             .help = "Set on/off to enable/disable usb",
+        }, {
+            .name = "nvram",
+            .type = QEMU_OPT_STRING,
+            .help = "Drive backing persistent NVRAM",
         },
         { /* End of list */ }
     },

From 4fd50339c0b55fa6387fa3c28f755c306997064c Mon Sep 17 00:00:00 2001
From: David Gibson 
Date: Mon, 12 Nov 2012 16:46:58 +0000
Subject: [PATCH 1956/2270] pseries: Update SLOF for NVRAM support

Now that we have implemented PAPR compatible NVRAM interfaces in qemu, this
updates the SLOF firmware to actually initialize and use the NVRAM as a
PAPR guest firmware is expected to do.

This SLOF update also includes an ugly but useful workaround for a bug in
the SLES11 installer which caused it to fail under KVM.

Signed-off-by: David Gibson 
Signed-off-by: Alexander Graf 
---
 pc-bios/README   |   2 +-
 pc-bios/slof.bin | Bin 878640 -> 880832 bytes
 roms/SLOF        |   2 +-
 3 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/pc-bios/README b/pc-bios/README
index 303713099e..eff3de7615 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -17,7 +17,7 @@
 - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
   implementation for certain IBM POWER hardware.  The sources are at
   https://github.com/dgibson/SLOF, and the image currently in qemu is
-  built from git tag qemu-slof-20120731.
+  built from git tag qemu-slof-20121018.
 
 - sgabios (the Serial Graphics Adapter option ROM) provides a means for
   legacy x86 software to communicate with an attached serial console as
diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin
index 84ba6b83f3c7fe523cb0b0e73ae8522872d1feef..3410f4fff40ff4a93d8963bf63fd6c1439f8b19c 100644
GIT binary patch
literal 880832
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	F3DG!R5esGl`O3%!iK!EiX+M
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
6w&T%~ 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Π#tQJgH5AYNQuXvcb941 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 literal 878640 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

!upM( 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℘8 z-d3rG>JS=N9m54Du!HoC8P;&;1^4e@eQRJa+l!6g{*7!Pu=fz>jdAIAE>><)s;Uw> zp9>Z`1-=@gH~-|g`KK|iras^6W8YTP0#~4{eWDt&&})30=0kd@)_Y+lB#3RO@KJri zMpVzeD<{8It&Adw-Zi)z?*PCgM&GrnLRejj;lJs=!6^E*5C(Y!}Zy30GsykTAe#@HdVEO>=C z-QP3Z+qX<@4b!i^Wc#p9G?&>J1vcSD*-WNyW4tAy*~=&}7r({GU#3LnLb0&{B8O*D z)n}-eYjSAZx|;Njt_)wX=^E_Vk42J>K~⪻KJShn$5B?8Y>qVS?Ki-wee{%uA)fG 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

KPh<*}LOmI3vP|ab^g^f1JVJ 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 qKmsU;d%kc(#9Vw7nHKbR3GfTx@nPUTo~K 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 Date: Wed, 10 Oct 2012 04:28:27 +0000 Subject: [PATCH 1957/2270] e500: Adding CCSR memory region All devices are also placed under CCSR memory region. The CCSR memory region is exported to pci device. The MSI interrupt generation is the main reason to export the CCSR region to PCI device. This put the requirement to move mpic under CCSR region, but logically all devices should be under CCSR. So this patch places all emulated devices under ccsr region. Signed-off-by: Bharat Bhushan Signed-off-by: Alexander Graf --- hw/ppc/e500.c | 63 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 6749ffffb3..85389335e5 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -46,13 +46,15 @@ /* TODO: parameterize */ #define MPC8544_CCSRBAR_BASE 0xE0000000ULL #define MPC8544_CCSRBAR_SIZE 0x00100000ULL -#define MPC8544_MPIC_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x40000ULL) -#define MPC8544_SERIAL0_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4500ULL) -#define MPC8544_SERIAL1_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4600ULL) -#define MPC8544_PCI_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x8000ULL) +#define MPC8544_MPIC_REGS_OFFSET 0x40000ULL +#define MPC8544_SERIAL0_REGS_OFFSET 0x4500ULL +#define MPC8544_SERIAL1_REGS_OFFSET 0x4600ULL +#define MPC8544_PCI_REGS_OFFSET 0x8000ULL +#define MPC8544_PCI_REGS_BASE (MPC8544_CCSRBAR_BASE + \ + MPC8544_PCI_REGS_OFFSET) #define MPC8544_PCI_REGS_SIZE 0x1000ULL #define MPC8544_PCI_IO 0xE1000000ULL -#define MPC8544_UTIL_BASE (MPC8544_CCSRBAR_BASE + 0xe0000ULL) +#define MPC8544_UTIL_OFFSET 0xe0000ULL #define MPC8544_SPIN_BASE 0xEF000000ULL struct boot_info @@ -267,13 +269,12 @@ static int ppce500_load_device_tree(CPUPPCState *env, /* XXX should contain a reasonable value */ qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0); - snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, - MPC8544_MPIC_REGS_BASE - MPC8544_CCSRBAR_BASE); + snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET); qemu_devtree_add_subnode(fdt, mpic); qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic"); qemu_devtree_setprop_string(fdt, mpic, "compatible", "chrp,open-pic"); - qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_BASE - - MPC8544_CCSRBAR_BASE, 0x40000); + qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET, + 0x40000); qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0); qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2); mpic_ph = qemu_devtree_alloc_phandle(fdt); @@ -286,17 +287,16 @@ static int ppce500_load_device_tree(CPUPPCState *env, * device it finds in the dt as serial output device. And we generate * devices in reverse order to the dt. */ - dt_serial_create(fdt, MPC8544_SERIAL1_REGS_BASE - MPC8544_CCSRBAR_BASE, + dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET, soc, mpic, "serial1", 1, false); - dt_serial_create(fdt, MPC8544_SERIAL0_REGS_BASE - MPC8544_CCSRBAR_BASE, + dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET, soc, mpic, "serial0", 0, true); snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc, - MPC8544_UTIL_BASE - MPC8544_CCSRBAR_BASE); + MPC8544_UTIL_OFFSET); qemu_devtree_add_subnode(fdt, gutil); qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts"); - qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_BASE - - MPC8544_CCSRBAR_BASE, 0x1000); + qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000); qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0); snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE); @@ -422,6 +422,8 @@ void ppce500_init(PPCE500Params *params) qemu_irq **irqs, *mpic; DeviceState *dev; CPUPPCState *firstenv = NULL; + MemoryRegion *ccsr; + SysBusDevice *s; /* Setup CPUs */ if (params->cpu_model == NULL) { @@ -450,7 +452,8 @@ void ppce500_init(PPCE500Params *params) irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT]; irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT]; env->spr[SPR_BOOKE_PIR] = env->cpu_index = i; - env->mpic_cpu_base = MPC8544_MPIC_REGS_BASE + 0x20000; + env->mpic_cpu_base = MPC8544_CCSRBAR_BASE + + MPC8544_MPIC_REGS_OFFSET + 0x20000; ppc_booke_timers_init(env, 400000000, PPC_TIMER_E500); @@ -477,8 +480,12 @@ void ppce500_init(PPCE500Params *params) vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0, ram); + ccsr = g_malloc0(sizeof(MemoryRegion)); + memory_region_init(ccsr, "e500-ccsr", MPC8544_CCSRBAR_SIZE); + memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE, ccsr); + /* MPIC */ - mpic = mpic_init(address_space_mem, MPC8544_MPIC_REGS_BASE, + mpic = mpic_init(ccsr, MPC8544_MPIC_REGS_OFFSET, smp_cpus, irqs, NULL); if (!mpic) { @@ -487,25 +494,35 @@ void ppce500_init(PPCE500Params *params) /* Serial */ if (serial_hds[0]) { - serial_mm_init(address_space_mem, MPC8544_SERIAL0_REGS_BASE, + serial_mm_init(ccsr, MPC8544_SERIAL0_REGS_OFFSET, 0, mpic[12+26], 399193, serial_hds[0], DEVICE_BIG_ENDIAN); } if (serial_hds[1]) { - serial_mm_init(address_space_mem, MPC8544_SERIAL1_REGS_BASE, + serial_mm_init(ccsr, MPC8544_SERIAL1_REGS_OFFSET, 0, mpic[12+26], 399193, serial_hds[1], DEVICE_BIG_ENDIAN); } /* General Utility device */ - sysbus_create_simple("mpc8544-guts", MPC8544_UTIL_BASE, NULL); + dev = qdev_create(NULL, "mpc8544-guts"); + qdev_init_nofail(dev); + s = SYS_BUS_DEVICE(dev); + memory_region_add_subregion(ccsr, MPC8544_UTIL_OFFSET, + sysbus_mmio_get_region(s, 0)); /* PCI */ - dev = sysbus_create_varargs("e500-pcihost", MPC8544_PCI_REGS_BASE, - mpic[pci_irq_nrs[0]], mpic[pci_irq_nrs[1]], - mpic[pci_irq_nrs[2]], mpic[pci_irq_nrs[3]], - NULL); + dev = qdev_create(NULL, "e500-pcihost"); + qdev_init_nofail(dev); + s = SYS_BUS_DEVICE(dev); + sysbus_connect_irq(s, 0, mpic[pci_irq_nrs[0]]); + sysbus_connect_irq(s, 1, mpic[pci_irq_nrs[1]]); + sysbus_connect_irq(s, 2, mpic[pci_irq_nrs[2]]); + sysbus_connect_irq(s, 3, mpic[pci_irq_nrs[3]]); + memory_region_add_subregion(ccsr, MPC8544_PCI_REGS_OFFSET, + sysbus_mmio_get_region(s, 0)); + pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0"); if (!pci_bus) printf("couldn't create PCI controller!\n"); From 3eddc1be1ccb26387f8f960f8a3d8c417064a91f Mon Sep 17 00:00:00 2001 From: Bharat Bhushan Date: Wed, 10 Oct 2012 04:28:28 +0000 Subject: [PATCH 1958/2270] Adding BAR0 for e500 PCI controller PCI Root complex have TYPE-1 configuration header while PCI endpoint have type-0 configuration header. The type-1 configuration header have a BAR (BAR0). In Freescale PCI controller BAR0 is used for mapping pci address space to CCSR address space. This can used for 2 purposes: 1) for MSI interrupt generation 2) Allow CCSR registers access when configured as PCI endpoint, which I am not sure is a use case with QEMU-KVM guest. What I observed is that when guest read the size of BAR0 of host controller configuration header (TYPE1 header) then it always reads it as 0. When looking into the QEMU hw/ppce500_pci.c, I do not find the PCI controller device registering BAR0. I do not find any other controller also doing so may they do not use BAR0. There are two issues when BAR0 is not there (which I can think of): 1) There should be BAR0 emulated for PCI Root complex (TYPE1 header) and when reading the size of BAR0, it should give size as per real h/w. 2) Do we need this BAR0 inbound address translation? When BAR0 is of non-zero size then it will be configured for PCI address space to local address(CCSR) space translation on inbound access. The primary use case is for MSI interrupt generation. The device is configured with an address offsets in PCI address space, which will be translated to MSI interrupt generation MPIC registers. Currently I do not understand the MSI interrupt generation mechanism in QEMU and also IIRC we do not use QEMU MSI interrupt mechanism on e500 guest machines. But this BAR0 will be used when using MSI on e500. I can see one more issue, There are ATMUs emulated in hw/ppce500_pci.c, but i do not see these being used for address translation. So far that works because pci address space and local address space are 1:1 mapped. BAR0 inbound translation + ATMU translation will complete the address translation of inbound traffic. Signed-off-by: Bharat Bhushan [agraf: fix double variable assignment w/o read] Signed-off-by: Alexander Graf --- hw/ppc/e500-ccsr.h | 17 ++++++++++++++ hw/ppc/e500.c | 55 ++++++++++++++++++++++++++++++++++++++-------- hw/ppce500_pci.c | 29 +++++++++++++++++++++++- 3 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 hw/ppc/e500-ccsr.h diff --git a/hw/ppc/e500-ccsr.h b/hw/ppc/e500-ccsr.h new file mode 100644 index 0000000000..f20f51bcd2 --- /dev/null +++ b/hw/ppc/e500-ccsr.h @@ -0,0 +1,17 @@ +#ifndef E500_CCSR_H +#define E500_CCSR_H + +#include "../sysbus.h" + +typedef struct PPCE500CCSRState { + /*< private >*/ + SysBusDevice parent; + /*< public >*/ + + MemoryRegion ccsr_space; +} PPCE500CCSRState; + +#define TYPE_CCSR "e500-ccsr" +#define CCSR(obj) OBJECT_CHECK(PPCE500CCSRState, (obj), TYPE_CCSR) + +#endif /* E500_CCSR_H */ diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 85389335e5..47e2d4169a 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -17,6 +17,7 @@ #include "config.h" #include "qemu-common.h" #include "e500.h" +#include "e500-ccsr.h" #include "net.h" #include "hw/hw.h" #include "hw/serial.h" @@ -422,8 +423,9 @@ void ppce500_init(PPCE500Params *params) qemu_irq **irqs, *mpic; DeviceState *dev; CPUPPCState *firstenv = NULL; - MemoryRegion *ccsr; + MemoryRegion *ccsr_addr_space; SysBusDevice *s; + PPCE500CCSRState *ccsr; /* Setup CPUs */ if (params->cpu_model == NULL) { @@ -480,12 +482,17 @@ void ppce500_init(PPCE500Params *params) vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0, ram); - ccsr = g_malloc0(sizeof(MemoryRegion)); - memory_region_init(ccsr, "e500-ccsr", MPC8544_CCSRBAR_SIZE); - memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE, ccsr); + dev = qdev_create(NULL, "e500-ccsr"); + object_property_add_child(qdev_get_machine(), "e500-ccsr", + OBJECT(dev), NULL); + qdev_init_nofail(dev); + ccsr = CCSR(dev); + ccsr_addr_space = &ccsr->ccsr_space; + memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE, + ccsr_addr_space); /* MPIC */ - mpic = mpic_init(ccsr, MPC8544_MPIC_REGS_OFFSET, + mpic = mpic_init(ccsr_addr_space, MPC8544_MPIC_REGS_OFFSET, smp_cpus, irqs, NULL); if (!mpic) { @@ -494,13 +501,13 @@ void ppce500_init(PPCE500Params *params) /* Serial */ if (serial_hds[0]) { - serial_mm_init(ccsr, MPC8544_SERIAL0_REGS_OFFSET, + serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET, 0, mpic[12+26], 399193, serial_hds[0], DEVICE_BIG_ENDIAN); } if (serial_hds[1]) { - serial_mm_init(ccsr, MPC8544_SERIAL1_REGS_OFFSET, + serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET, 0, mpic[12+26], 399193, serial_hds[1], DEVICE_BIG_ENDIAN); } @@ -509,7 +516,7 @@ void ppce500_init(PPCE500Params *params) dev = qdev_create(NULL, "mpc8544-guts"); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); - memory_region_add_subregion(ccsr, MPC8544_UTIL_OFFSET, + memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET, sysbus_mmio_get_region(s, 0)); /* PCI */ @@ -520,7 +527,7 @@ void ppce500_init(PPCE500Params *params) sysbus_connect_irq(s, 1, mpic[pci_irq_nrs[1]]); sysbus_connect_irq(s, 2, mpic[pci_irq_nrs[2]]); sysbus_connect_irq(s, 3, mpic[pci_irq_nrs[3]]); - memory_region_add_subregion(ccsr, MPC8544_PCI_REGS_OFFSET, + memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET, sysbus_mmio_get_region(s, 0)); pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0"); @@ -595,3 +602,33 @@ void ppce500_init(PPCE500Params *params) kvmppc_init(); } } + +static int e500_ccsr_initfn(SysBusDevice *dev) +{ + PPCE500CCSRState *ccsr; + + ccsr = CCSR(dev); + memory_region_init(&ccsr->ccsr_space, "e500-ccsr", + MPC8544_CCSRBAR_SIZE); + return 0; +} + +static void e500_ccsr_class_init(ObjectClass *klass, void *data) +{ + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + k->init = e500_ccsr_initfn; +} + +static const TypeInfo e500_ccsr_info = { + .name = TYPE_CCSR, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(PPCE500CCSRState), + .class_init = e500_ccsr_class_init, +}; + +static void e500_register_types(void) +{ + type_register_static(&e500_ccsr_info); +} + +type_init(e500_register_types) diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 2ff7438d09..54c72b4fd2 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -15,6 +15,7 @@ */ #include "hw.h" +#include "hw/ppc/e500-ccsr.h" #include "pci.h" #include "pci_host.h" #include "bswap.h" @@ -92,6 +93,19 @@ struct PPCE500PCIState { MemoryRegion pio; }; +#define TYPE_PPC_E500_PCI_BRIDGE "e500-host-bridge" +#define PPC_E500_PCI_BRIDGE(obj) \ + OBJECT_CHECK(PPCE500PCIBridgeState, (obj), TYPE_PPC_E500_PCI_BRIDGE) + +struct PPCE500PCIBridgeState { + /*< private >*/ + PCIDevice parent; + /*< public >*/ + + MemoryRegion bar0; +}; + +typedef struct PPCE500PCIBridgeState PPCE500PCIBridgeState; typedef struct PPCE500PCIState PPCE500PCIState; static uint64_t pci_reg_read4(void *opaque, hwaddr addr, @@ -310,6 +324,18 @@ static const VMStateDescription vmstate_ppce500_pci = { #include "exec-memory.h" +static int e500_pcihost_bridge_initfn(PCIDevice *d) +{ + PPCE500PCIBridgeState *b = PPC_E500_PCI_BRIDGE(d); + PPCE500CCSRState *ccsr = CCSR(container_get(qdev_get_machine(), + "/e500-ccsr")); + + memory_region_init_alias(&b->bar0, "e500-pci-bar0", &ccsr->ccsr_space, + 0, int128_get64(ccsr->ccsr_space.size)); + pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &b->bar0); + return 0; +} + static int e500_pcihost_initfn(SysBusDevice *dev) { PCIHostState *h; @@ -355,6 +381,7 @@ static void e500_host_bridge_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + k->init = e500_pcihost_bridge_initfn; k->vendor_id = PCI_VENDOR_ID_FREESCALE; k->device_id = PCI_DEVICE_ID_MPC8533E; k->class_id = PCI_CLASS_PROCESSOR_POWERPC; @@ -364,7 +391,7 @@ static void e500_host_bridge_class_init(ObjectClass *klass, void *data) static const TypeInfo e500_host_bridge_info = { .name = "e500-host-bridge", .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIDevice), + .instance_size = sizeof(PPCE500PCIBridgeState), .class_init = e500_host_bridge_class_init, }; From 8b1853e7d8c2bf8c6a9f023ab98ba0e8a38bd086 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 3 Dec 2012 16:42:13 +0000 Subject: [PATCH 1959/2270] pseries: Don't allow TCE (iommu) tables to be registered with duplicate LIOBNs The PAPR specification requires that every bus or device mediated by the IOMMU have a unique Logical IO Bus Number (LIOBN). This patch adds a check to enforce this, which will help catch errors in configuration earlier. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_iommu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c index 02d78ccf28..3011b251d3 100644 --- a/hw/spapr_iommu.c +++ b/hw/spapr_iommu.c @@ -120,6 +120,12 @@ DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size) { sPAPRTCETable *tcet; + if (spapr_tce_find_by_liobn(liobn)) { + fprintf(stderr, "Attempted to create TCE table with duplicate" + " LIOBN 0x%x\n", liobn); + return NULL; + } + if (!window_size) { return NULL; } From 38898d7ed803cee5105246150725487add78cbd7 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 6 Dec 2012 15:59:27 +0100 Subject: [PATCH 1960/2270] openpic: Remove unused code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The openpic code had a few WIP bits left that nobody reanimated within the last few years. Remove that code. Signed-off-by: Alexander Graf Acked-by: Hervé Poussineau --- hw/openpic.c | 163 --------------------------------------------------- 1 file changed, 163 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index 8b3784a6bd..b30c853501 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -46,27 +46,8 @@ #define DPRINTF(fmt, ...) do { } while (0) #endif -#define USE_MPCxxx /* Intel model is broken, for now */ - -#if defined (USE_INTEL_GW80314) -/* Intel GW80314 I/O Companion chip */ - -#define MAX_CPU 4 -#define MAX_IRQ 32 -#define MAX_DBL 4 -#define MAX_MBX 4 -#define MAX_TMR 4 -#define VECTOR_BITS 8 -#define MAX_IPI 4 - -#define VID (0x00000000) - -#elif defined(USE_MPCxxx) - #define MAX_CPU 15 #define MAX_IRQ 128 -#define MAX_DBL 0 -#define MAX_MBX 0 #define MAX_TMR 4 #define VECTOR_BITS 8 #define MAX_IPI 4 @@ -149,12 +130,6 @@ enum mpic_ide_bits { IDR_P0 = 0, }; -#else -#error "Please select which OpenPic implementation is to be emulated" -#endif - -#define OPENPIC_PAGE_SIZE 4096 - #define BF_WIDTH(_bits_) \ (((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8)) @@ -250,19 +225,6 @@ typedef struct openpic_t { uint32_t ticc; /* Global timer current count register */ uint32_t tibc; /* Global timer base count register */ } timers[MAX_TMR]; -#if MAX_DBL > 0 - /* Doorbell registers */ - uint32_t dar; /* Doorbell activate register */ - struct { - uint32_t dmr; /* Doorbell messaging register */ - } doorbells[MAX_DBL]; -#endif -#if MAX_MBX > 0 - /* Mailbox registers */ - struct { - uint32_t mbr; /* Mailbox register */ - } mailboxes[MAX_MAILBOXES]; -#endif /* IRQ out is used when in bypass mode (not implemented) */ qemu_irq irq_out; int max_irq; @@ -470,19 +432,6 @@ static void openpic_reset (void *opaque) opp->timers[i].ticc = 0x00000000; opp->timers[i].tibc = 0x80000000; } - /* Initialise doorbells */ -#if MAX_DBL > 0 - opp->dar = 0x00000000; - for (i = 0; i < MAX_DBL; i++) { - opp->doorbells[i].dmr = 0x00000000; - } -#endif - /* Initialise mailboxes */ -#if MAX_MBX > 0 - for (i = 0; i < MAX_MBX; i++) { /* ? */ - opp->mailboxes[i].mbr = 0x00000000; - } -#endif /* Go out of RESET state */ opp->glbc = 0x00000000; } @@ -518,84 +467,6 @@ static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val) opp->src[n_IRQ].ipvp); } -#if 0 // Code provision for Intel model -#if MAX_DBL > 0 -static uint32_t read_doorbell_register (openpic_t *opp, - int n_dbl, uint32_t offset) -{ - uint32_t retval; - - switch (offset) { - case DBL_IPVP_OFFSET: - retval = read_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl); - break; - case DBL_IDE_OFFSET: - retval = read_IRQreg_ide(opp, IRQ_DBL0 + n_dbl); - break; - case DBL_DMR_OFFSET: - retval = opp->doorbells[n_dbl].dmr; - break; - } - - return retval; -} - -static void write_doorbell_register (penpic_t *opp, int n_dbl, - uint32_t offset, uint32_t value) -{ - switch (offset) { - case DBL_IVPR_OFFSET: - write_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl, value); - break; - case DBL_IDE_OFFSET: - write_IRQreg_ide(opp, IRQ_DBL0 + n_dbl, value); - break; - case DBL_DMR_OFFSET: - opp->doorbells[n_dbl].dmr = value; - break; - } -} -#endif - -#if MAX_MBX > 0 -static uint32_t read_mailbox_register (openpic_t *opp, - int n_mbx, uint32_t offset) -{ - uint32_t retval; - - switch (offset) { - case MBX_MBR_OFFSET: - retval = opp->mailboxes[n_mbx].mbr; - break; - case MBX_IVPR_OFFSET: - retval = read_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx); - break; - case MBX_DMR_OFFSET: - retval = read_IRQreg_ide(opp, IRQ_MBX0 + n_mbx); - break; - } - - return retval; -} - -static void write_mailbox_register (openpic_t *opp, int n_mbx, - uint32_t address, uint32_t value) -{ - switch (offset) { - case MBX_MBR_OFFSET: - opp->mailboxes[n_mbx].mbr = value; - break; - case MBX_IVPR_OFFSET: - write_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx, value); - break; - case MBX_DMR_OFFSET: - write_IRQreg_ide(opp, IRQ_MBX0 + n_mbx, value); - break; - } -} -#endif -#endif /* 0 : Code provision for Intel model */ - static void openpic_gbl_write (void *opaque, hwaddr addr, uint32_t val) { openpic_t *opp = opaque; @@ -841,7 +712,6 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr, dst = &opp->dst[idx]; addr &= 0xFF0; switch (addr) { -#if MAX_IPI > 0 case 0x40: /* IPIDR */ case 0x50: case 0x60: @@ -853,7 +723,6 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr, openpic_set_irq(opp, opp->irq_ipi0 + idx, 1); openpic_set_irq(opp, opp->irq_ipi0 + idx, 0); break; -#endif case 0x80: /* PCTP */ dst->pctp = val & 0x0000000F; break; @@ -1109,20 +978,6 @@ static void openpic_save(QEMUFile* f, void *opaque) qemu_put_be32s(f, &opp->timers[i].tibc); } -#if MAX_DBL > 0 - qemu_put_be32s(f, &opp->dar); - - for (i = 0; i < MAX_DBL; i++) { - qemu_put_be32s(f, &opp->doorbells[i].dmr); - } -#endif - -#if MAX_MBX > 0 - for (i = 0; i < MAX_MAILBOXES; i++) { - qemu_put_be32s(f, &opp->mailboxes[i].mbr); - } -#endif - pci_device_save(&opp->pci_dev, f); } @@ -1176,20 +1031,6 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) qemu_get_be32s(f, &opp->timers[i].tibc); } -#if MAX_DBL > 0 - qemu_get_be32s(f, &opp->dar); - - for (i = 0; i < MAX_DBL; i++) { - qemu_get_be32s(f, &opp->doorbells[i].dmr); - } -#endif - -#if MAX_MBX > 0 - for (i = 0; i < MAX_MAILBOXES; i++) { - qemu_get_be32s(f, &opp->mailboxes[i].mbr); - } -#endif - return pci_device_load(&opp->pci_dev, f); } @@ -1222,11 +1063,7 @@ qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, for (; i < OPENPIC_IRQ_TIM0; i++) { opp->src[i].type = IRQ_SPECIAL; } -#if MAX_IPI > 0 m = OPENPIC_IRQ_IPI0; -#else - m = OPENPIC_IRQ_DBL0; -#endif for (; i < m; i++) { opp->src[i].type = IRQ_TIMER; } From cdbb912a6f8b5f325df3a6fd42cb2843032050c9 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 7 Dec 2012 16:10:34 +0100 Subject: [PATCH 1961/2270] mpic: Unify numbering scheme MPIC interrupt numbers in Linux (device tree) and in QEMU are different, because QEMU takes the sparseness of the IRQ number space into account. Remove that cleverness and instead assume a flat number space. This makes the code easier to understand, because we are actually aligned with Linux on the view of our worlds. Signed-off-by: Alexander Graf --- hw/openpic.c | 290 ++++++++------------------------------------------ hw/ppc/e500.c | 4 +- 2 files changed, 45 insertions(+), 249 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index b30c853501..122ce7614f 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -46,11 +46,12 @@ #define DPRINTF(fmt, ...) do { } while (0) #endif -#define MAX_CPU 15 -#define MAX_IRQ 128 +#define MAX_CPU 15 +#define MAX_SRC 256 #define MAX_TMR 4 #define VECTOR_BITS 8 #define MAX_IPI 4 +#define MAX_IRQ (MAX_SRC + MAX_IPI + MAX_TMR) #define VID 0x03 /* MPIC version ID */ #define VENI 0x00000000 /* Vendor ID */ @@ -82,32 +83,25 @@ enum { #define MPIC_MAX_CPU 1 #define MPIC_MAX_EXT 12 #define MPIC_MAX_INT 64 -#define MPIC_MAX_MSG 4 -#define MPIC_MAX_MSI 8 -#define MPIC_MAX_TMR MAX_TMR -#define MPIC_MAX_IPI MAX_IPI -#define MPIC_MAX_IRQ (MPIC_MAX_EXT + MPIC_MAX_INT + MPIC_MAX_TMR + MPIC_MAX_MSG + MPIC_MAX_MSI + (MPIC_MAX_IPI * MPIC_MAX_CPU)) +#define MPIC_MAX_IRQ MAX_IRQ /* Interrupt definitions */ -#define MPIC_EXT_IRQ 0 -#define MPIC_INT_IRQ (MPIC_EXT_IRQ + MPIC_MAX_EXT) -#define MPIC_TMR_IRQ (MPIC_INT_IRQ + MPIC_MAX_INT) -#define MPIC_MSG_IRQ (MPIC_TMR_IRQ + MPIC_MAX_TMR) -#define MPIC_MSI_IRQ (MPIC_MSG_IRQ + MPIC_MAX_MSG) -#define MPIC_IPI_IRQ (MPIC_MSI_IRQ + MPIC_MAX_MSI) +/* IRQs, accessible through the IRQ region */ +#define MPIC_EXT_IRQ 0x00 +#define MPIC_INT_IRQ 0x10 +#define MPIC_MSG_IRQ 0xb0 +#define MPIC_MSI_IRQ 0xe0 +/* These are available through separate regions, but + for simplicity's sake mapped into the same number space */ +#define MPIC_TMR_IRQ 0x100 +#define MPIC_IPI_IRQ 0x104 #define MPIC_GLB_REG_START 0x0 #define MPIC_GLB_REG_SIZE 0x10F0 #define MPIC_TMR_REG_START 0x10F0 #define MPIC_TMR_REG_SIZE 0x220 -#define MPIC_EXT_REG_START 0x10000 -#define MPIC_EXT_REG_SIZE 0x180 -#define MPIC_INT_REG_START 0x10200 -#define MPIC_INT_REG_SIZE 0x800 -#define MPIC_MSG_REG_START 0x11600 -#define MPIC_MSG_REG_SIZE 0x100 -#define MPIC_MSI_REG_START 0x11C00 -#define MPIC_MSI_REG_SIZE 0x100 +#define MPIC_IRQ_REG_START 0x10000 +#define MPIC_IRQ_REG_SIZE (MAX_SRC * 0x20) #define MPIC_CPU_REG_START 0x20000 #define MPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000) @@ -1205,193 +1199,44 @@ static uint32_t mpic_timer_read (void *opaque, hwaddr addr) return retval; } -static void mpic_src_ext_write (void *opaque, hwaddr addr, - uint32_t val) +static void mpic_src_irq_write(void *opaque, hwaddr addr, + uint64_t val, unsigned len) { openpic_t *mpp = opaque; - int idx = MPIC_EXT_IRQ; + int idx = addr / 0x20; - DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val); + DPRINTF("%s: addr " TARGET_FMT_plx " <= %08" PRIx64 "\n", + __func__, addr, val); if (addr & 0xF) return; - if (addr < MPIC_EXT_REG_SIZE) { - idx += (addr & 0xFFF0) >> 5; - if (addr & 0x10) { - /* EXDE / IFEDE / IEEDE */ - write_IRQreg_ide(mpp, idx, val); - } else { - /* EXVP / IFEVP / IEEVP */ - write_IRQreg_ipvp(mpp, idx, val); - } + if (addr & 0x10) { + /* EXDE / IFEDE / IEEDE */ + write_IRQreg_ide(mpp, idx, val); + } else { + /* EXVP / IFEVP / IEEVP */ + write_IRQreg_ipvp(mpp, idx, val); } } -static uint32_t mpic_src_ext_read (void *opaque, hwaddr addr) +static uint64_t mpic_src_irq_read(void *opaque, hwaddr addr, unsigned len) { openpic_t *mpp = opaque; uint32_t retval; - int idx = MPIC_EXT_IRQ; + int idx = addr / 0x20; DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr); - retval = 0xFFFFFFFF; if (addr & 0xF) - return retval; + return -1; - if (addr < MPIC_EXT_REG_SIZE) { - idx += (addr & 0xFFF0) >> 5; - if (addr & 0x10) { - /* EXDE / IFEDE / IEEDE */ - retval = read_IRQreg_ide(mpp, idx); - } else { - /* EXVP / IFEVP / IEEVP */ - retval = read_IRQreg_ipvp(mpp, idx); - } - DPRINTF("%s: => %08x\n", __func__, retval); - } - - return retval; -} - -static void mpic_src_int_write (void *opaque, hwaddr addr, - uint32_t val) -{ - openpic_t *mpp = opaque; - int idx = MPIC_INT_IRQ; - - DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val); - if (addr & 0xF) - return; - - if (addr < MPIC_INT_REG_SIZE) { - idx += (addr & 0xFFF0) >> 5; - if (addr & 0x10) { - /* EXDE / IFEDE / IEEDE */ - write_IRQreg_ide(mpp, idx, val); - } else { - /* EXVP / IFEVP / IEEVP */ - write_IRQreg_ipvp(mpp, idx, val); - } - } -} - -static uint32_t mpic_src_int_read (void *opaque, hwaddr addr) -{ - openpic_t *mpp = opaque; - uint32_t retval; - int idx = MPIC_INT_IRQ; - - DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr); - retval = 0xFFFFFFFF; - if (addr & 0xF) - return retval; - - if (addr < MPIC_INT_REG_SIZE) { - idx += (addr & 0xFFF0) >> 5; - if (addr & 0x10) { - /* EXDE / IFEDE / IEEDE */ - retval = read_IRQreg_ide(mpp, idx); - } else { - /* EXVP / IFEVP / IEEVP */ - retval = read_IRQreg_ipvp(mpp, idx); - } - DPRINTF("%s: => %08x\n", __func__, retval); - } - - return retval; -} - -static void mpic_src_msg_write (void *opaque, hwaddr addr, - uint32_t val) -{ - openpic_t *mpp = opaque; - int idx = MPIC_MSG_IRQ; - - DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val); - if (addr & 0xF) - return; - - if (addr < MPIC_MSG_REG_SIZE) { - idx += (addr & 0xFFF0) >> 5; - if (addr & 0x10) { - /* EXDE / IFEDE / IEEDE */ - write_IRQreg_ide(mpp, idx, val); - } else { - /* EXVP / IFEVP / IEEVP */ - write_IRQreg_ipvp(mpp, idx, val); - } - } -} - -static uint32_t mpic_src_msg_read (void *opaque, hwaddr addr) -{ - openpic_t *mpp = opaque; - uint32_t retval; - int idx = MPIC_MSG_IRQ; - - DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr); - retval = 0xFFFFFFFF; - if (addr & 0xF) - return retval; - - if (addr < MPIC_MSG_REG_SIZE) { - idx += (addr & 0xFFF0) >> 5; - if (addr & 0x10) { - /* EXDE / IFEDE / IEEDE */ - retval = read_IRQreg_ide(mpp, idx); - } else { - /* EXVP / IFEVP / IEEVP */ - retval = read_IRQreg_ipvp(mpp, idx); - } - DPRINTF("%s: => %08x\n", __func__, retval); - } - - return retval; -} - -static void mpic_src_msi_write (void *opaque, hwaddr addr, - uint32_t val) -{ - openpic_t *mpp = opaque; - int idx = MPIC_MSI_IRQ; - - DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val); - if (addr & 0xF) - return; - - if (addr < MPIC_MSI_REG_SIZE) { - idx += (addr & 0xFFF0) >> 5; - if (addr & 0x10) { - /* EXDE / IFEDE / IEEDE */ - write_IRQreg_ide(mpp, idx, val); - } else { - /* EXVP / IFEVP / IEEVP */ - write_IRQreg_ipvp(mpp, idx, val); - } - } -} -static uint32_t mpic_src_msi_read (void *opaque, hwaddr addr) -{ - openpic_t *mpp = opaque; - uint32_t retval; - int idx = MPIC_MSI_IRQ; - - DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr); - retval = 0xFFFFFFFF; - if (addr & 0xF) - return retval; - - if (addr < MPIC_MSI_REG_SIZE) { - idx += (addr & 0xFFF0) >> 5; - if (addr & 0x10) { - /* EXDE / IFEDE / IEEDE */ - retval = read_IRQreg_ide(mpp, idx); - } else { - /* EXVP / IFEVP / IEEVP */ - retval = read_IRQreg_ipvp(mpp, idx); - } - DPRINTF("%s: => %08x\n", __func__, retval); + if (addr & 0x10) { + /* EXDE / IFEDE / IEEDE */ + retval = read_IRQreg_ide(mpp, idx); + } else { + /* EXVP / IFEVP / IEEVP */ + retval = read_IRQreg_ipvp(mpp, idx); } + DPRINTF("%s: => %08x\n", __func__, retval); return retval; } @@ -1438,60 +1283,14 @@ static const MemoryRegionOps mpic_cpu_ops = { .endianness = DEVICE_BIG_ENDIAN, }; -static const MemoryRegionOps mpic_ext_ops = { - .old_mmio = { - .write = { openpic_buggy_write, - openpic_buggy_write, - mpic_src_ext_write, - }, - .read = { openpic_buggy_read, - openpic_buggy_read, - mpic_src_ext_read, - }, - }, +static const MemoryRegionOps mpic_irq_ops = { + .write = mpic_src_irq_write, + .read = mpic_src_irq_read, .endianness = DEVICE_BIG_ENDIAN, -}; - -static const MemoryRegionOps mpic_int_ops = { - .old_mmio = { - .write = { openpic_buggy_write, - openpic_buggy_write, - mpic_src_int_write, - }, - .read = { openpic_buggy_read, - openpic_buggy_read, - mpic_src_int_read, - }, + .impl = { + .min_access_size = 4, + .max_access_size = 4, }, - .endianness = DEVICE_BIG_ENDIAN, -}; - -static const MemoryRegionOps mpic_msg_ops = { - .old_mmio = { - .write = { openpic_buggy_write, - openpic_buggy_write, - mpic_src_msg_write, - }, - .read = { openpic_buggy_read, - openpic_buggy_read, - mpic_src_msg_read, - }, - }, - .endianness = DEVICE_BIG_ENDIAN, -}; - -static const MemoryRegionOps mpic_msi_ops = { - .old_mmio = { - .write = { openpic_buggy_write, - openpic_buggy_write, - mpic_src_msi_write, - }, - .read = { openpic_buggy_read, - openpic_buggy_read, - mpic_src_msi_read, - }, - }, - .endianness = DEVICE_BIG_ENDIAN, }; qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, @@ -1507,10 +1306,7 @@ qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, } const list[] = { {"glb", &mpic_glb_ops, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE}, {"tmr", &mpic_tmr_ops, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE}, - {"ext", &mpic_ext_ops, MPIC_EXT_REG_START, MPIC_EXT_REG_SIZE}, - {"int", &mpic_int_ops, MPIC_INT_REG_START, MPIC_INT_REG_SIZE}, - {"msg", &mpic_msg_ops, MPIC_MSG_REG_START, MPIC_MSG_REG_SIZE}, - {"msi", &mpic_msi_ops, MPIC_MSI_REG_START, MPIC_MSI_REG_SIZE}, + {"irq", &mpic_irq_ops, MPIC_IRQ_REG_START, MPIC_IRQ_REG_SIZE}, {"cpu", &mpic_cpu_ops, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE}, }; diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 47e2d4169a..f3e97d8bb5 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -502,13 +502,13 @@ void ppce500_init(PPCE500Params *params) /* Serial */ if (serial_hds[0]) { serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET, - 0, mpic[12+26], 399193, + 0, mpic[42], 399193, serial_hds[0], DEVICE_BIG_ENDIAN); } if (serial_hds[1]) { serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET, - 0, mpic[12+26], 399193, + 0, mpic[42], 399193, serial_hds[1], DEVICE_BIG_ENDIAN); } From b9b2aaa3c6926cf8af21fe75457ca6c6e0dc1f5d Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 7 Dec 2012 16:31:55 +0100 Subject: [PATCH 1962/2270] openpic: update to proper memory api The openpic code was still using the old mmio memory api. Convert it to be a generic memory api user and clean up some code that becomes redundant that way. Signed-off-by: Alexander Graf --- hw/openpic.c | 138 ++++++++++++++++++--------------------------------- 1 file changed, 48 insertions(+), 90 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index 122ce7614f..1d714f4d7c 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -461,7 +461,8 @@ static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val) opp->src[n_IRQ].ipvp); } -static void openpic_gbl_write (void *opaque, hwaddr addr, uint32_t val) +static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val, + unsigned len) { openpic_t *opp = opaque; IRQ_dst_t *dst; @@ -527,7 +528,7 @@ static void openpic_gbl_write (void *opaque, hwaddr addr, uint32_t val) } } -static uint32_t openpic_gbl_read (void *opaque, hwaddr addr) +static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len) { openpic_t *opp = opaque; uint32_t retval; @@ -584,7 +585,8 @@ static uint32_t openpic_gbl_read (void *opaque, hwaddr addr) return retval; } -static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val) +static void openpic_timer_write(void *opaque, hwaddr addr, uint64_t val, + unsigned len) { openpic_t *opp = opaque; int idx; @@ -615,7 +617,7 @@ static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val) } } -static uint32_t openpic_timer_read (void *opaque, uint32_t addr) +static uint64_t openpic_timer_read(void *opaque, hwaddr addr, unsigned len) { openpic_t *opp = opaque; uint32_t retval; @@ -648,7 +650,8 @@ static uint32_t openpic_timer_read (void *opaque, uint32_t addr) return retval; } -static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val) +static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val, + unsigned len) { openpic_t *opp = opaque; int idx; @@ -667,7 +670,7 @@ static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val) } } -static uint32_t openpic_src_read (void *opaque, uint32_t addr) +static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len) { openpic_t *opp = opaque; uint32_t retval; @@ -749,7 +752,8 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr, } } -static void openpic_cpu_write(void *opaque, hwaddr addr, uint32_t val) +static void openpic_cpu_write(void *opaque, hwaddr addr, uint64_t val, + unsigned len) { openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12); } @@ -833,96 +837,63 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr, return retval; } -static uint32_t openpic_cpu_read(void *opaque, hwaddr addr) +static uint64_t openpic_cpu_read(void *opaque, hwaddr addr, unsigned len) { return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12); } -static void openpic_buggy_write (void *opaque, - hwaddr addr, uint32_t val) -{ - printf("Invalid OPENPIC write access !\n"); -} - -static uint32_t openpic_buggy_read (void *opaque, hwaddr addr) -{ - printf("Invalid OPENPIC read access !\n"); - - return -1; -} - -static void openpic_writel (void *opaque, - hwaddr addr, uint32_t val) +static void openpic_write(void *opaque, hwaddr addr, uint64_t val, + unsigned len) { openpic_t *opp = opaque; - addr &= 0x3FFFF; DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val); if (addr < 0x1100) { /* Global registers */ - openpic_gbl_write(opp, addr, val); + openpic_gbl_write(opp, addr, val, len); } else if (addr < 0x10000) { /* Timers registers */ - openpic_timer_write(opp, addr, val); + openpic_timer_write(opp, addr, val, len); } else if (addr < 0x20000) { /* Source registers */ - openpic_src_write(opp, addr, val); + openpic_src_write(opp, addr, val, len); } else { /* CPU registers */ - openpic_cpu_write(opp, addr, val); + openpic_cpu_write(opp, addr, val, len); } } -static uint32_t openpic_readl (void *opaque,hwaddr addr) +static uint64_t openpic_read(void *opaque, hwaddr addr, unsigned len) { openpic_t *opp = opaque; uint32_t retval; - addr &= 0x3FFFF; DPRINTF("%s: offset %08x\n", __func__, (int)addr); if (addr < 0x1100) { /* Global registers */ - retval = openpic_gbl_read(opp, addr); + retval = openpic_gbl_read(opp, addr, len); } else if (addr < 0x10000) { /* Timers registers */ - retval = openpic_timer_read(opp, addr); + retval = openpic_timer_read(opp, addr, len); } else if (addr < 0x20000) { /* Source registers */ - retval = openpic_src_read(opp, addr); + retval = openpic_src_read(opp, addr, len); } else { /* CPU registers */ - retval = openpic_cpu_read(opp, addr); + retval = openpic_cpu_read(opp, addr, len); } return retval; } -static uint64_t openpic_read(void *opaque, hwaddr addr, - unsigned size) -{ - openpic_t *opp = opaque; - - switch (size) { - case 4: return openpic_readl(opp, addr); - default: return openpic_buggy_read(opp, addr); - } -} - -static void openpic_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size) -{ - openpic_t *opp = opaque; - - switch (size) { - case 4: return openpic_writel(opp, addr, data); - default: return openpic_buggy_write(opp, addr, data); - } -} - static const MemoryRegionOps openpic_ops = { .read = openpic_read, .write = openpic_write, .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, }; static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q) @@ -1131,7 +1102,8 @@ static void mpic_reset (void *opaque) mpp->glbc = 0x00000000; } -static void mpic_timer_write (void *opaque, hwaddr addr, uint32_t val) +static void mpic_timer_write(void *opaque, hwaddr addr, uint64_t val, + unsigned len) { openpic_t *mpp = opaque; int idx, cpu; @@ -1139,7 +1111,6 @@ static void mpic_timer_write (void *opaque, hwaddr addr, uint32_t val) DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val); if (addr & 0xF) return; - addr &= 0xFFFF; cpu = addr >> 12; idx = (addr >> 6) & 0x3; switch (addr & 0x30) { @@ -1164,7 +1135,7 @@ static void mpic_timer_write (void *opaque, hwaddr addr, uint32_t val) } } -static uint32_t mpic_timer_read (void *opaque, hwaddr addr) +static uint64_t mpic_timer_read(void *opaque, hwaddr addr, unsigned len) { openpic_t *mpp = opaque; uint32_t retval; @@ -1174,7 +1145,6 @@ static uint32_t mpic_timer_read (void *opaque, hwaddr addr) retval = 0xFFFFFFFF; if (addr & 0xF) return retval; - addr &= 0xFFFF; cpu = addr >> 12; idx = (addr >> 6) & 0x3; switch (addr & 0x30) { @@ -1242,45 +1212,33 @@ static uint64_t mpic_src_irq_read(void *opaque, hwaddr addr, unsigned len) } static const MemoryRegionOps mpic_glb_ops = { - .old_mmio = { - .write = { openpic_buggy_write, - openpic_buggy_write, - openpic_gbl_write, - }, - .read = { openpic_buggy_read, - openpic_buggy_read, - openpic_gbl_read, - }, - }, + .write = openpic_gbl_write, + .read = openpic_gbl_read, .endianness = DEVICE_BIG_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, }; static const MemoryRegionOps mpic_tmr_ops = { - .old_mmio = { - .write = { openpic_buggy_write, - openpic_buggy_write, - mpic_timer_write, - }, - .read = { openpic_buggy_read, - openpic_buggy_read, - mpic_timer_read, - }, - }, + .write = mpic_timer_write, + .read = mpic_timer_read, .endianness = DEVICE_BIG_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, }; static const MemoryRegionOps mpic_cpu_ops = { - .old_mmio = { - .write = { openpic_buggy_write, - openpic_buggy_write, - openpic_cpu_write, - }, - .read = { openpic_buggy_read, - openpic_buggy_read, - openpic_cpu_read, - }, - }, + .write = openpic_cpu_write, + .read = openpic_cpu_read, .endianness = DEVICE_BIG_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, }; static const MemoryRegionOps mpic_irq_ops = { From a285f1ca703a434fa8edf584f94a1dc29067ab29 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 7 Dec 2012 16:45:40 +0100 Subject: [PATCH 1963/2270] openpic: combine mpic and openpic src handlers The MPIC source irq handler suddenly became identical to the standard OpenPIC source irq handler. Combine them into the same function. Signed-off-by: Alexander Graf --- hw/openpic.c | 52 +++++----------------------------------------------- 1 file changed, 5 insertions(+), 47 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index 1d714f4d7c..b671d9de33 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -100,8 +100,8 @@ enum { #define MPIC_GLB_REG_SIZE 0x10F0 #define MPIC_TMR_REG_START 0x10F0 #define MPIC_TMR_REG_SIZE 0x220 -#define MPIC_IRQ_REG_START 0x10000 -#define MPIC_IRQ_REG_SIZE (MAX_SRC * 0x20) +#define MPIC_SRC_REG_START 0x10000 +#define MPIC_SRC_REG_SIZE (MAX_SRC * 0x20) #define MPIC_CPU_REG_START 0x20000 #define MPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000) @@ -1169,48 +1169,6 @@ static uint64_t mpic_timer_read(void *opaque, hwaddr addr, unsigned len) return retval; } -static void mpic_src_irq_write(void *opaque, hwaddr addr, - uint64_t val, unsigned len) -{ - openpic_t *mpp = opaque; - int idx = addr / 0x20; - - DPRINTF("%s: addr " TARGET_FMT_plx " <= %08" PRIx64 "\n", - __func__, addr, val); - if (addr & 0xF) - return; - - if (addr & 0x10) { - /* EXDE / IFEDE / IEEDE */ - write_IRQreg_ide(mpp, idx, val); - } else { - /* EXVP / IFEVP / IEEVP */ - write_IRQreg_ipvp(mpp, idx, val); - } -} - -static uint64_t mpic_src_irq_read(void *opaque, hwaddr addr, unsigned len) -{ - openpic_t *mpp = opaque; - uint32_t retval; - int idx = addr / 0x20; - - DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr); - if (addr & 0xF) - return -1; - - if (addr & 0x10) { - /* EXDE / IFEDE / IEEDE */ - retval = read_IRQreg_ide(mpp, idx); - } else { - /* EXVP / IFEVP / IEEVP */ - retval = read_IRQreg_ipvp(mpp, idx); - } - DPRINTF("%s: => %08x\n", __func__, retval); - - return retval; -} - static const MemoryRegionOps mpic_glb_ops = { .write = openpic_gbl_write, .read = openpic_gbl_read, @@ -1242,8 +1200,8 @@ static const MemoryRegionOps mpic_cpu_ops = { }; static const MemoryRegionOps mpic_irq_ops = { - .write = mpic_src_irq_write, - .read = mpic_src_irq_read, + .write = openpic_src_write, + .read = openpic_src_read, .endianness = DEVICE_BIG_ENDIAN, .impl = { .min_access_size = 4, @@ -1264,7 +1222,7 @@ qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, } const list[] = { {"glb", &mpic_glb_ops, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE}, {"tmr", &mpic_tmr_ops, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE}, - {"irq", &mpic_irq_ops, MPIC_IRQ_REG_START, MPIC_IRQ_REG_SIZE}, + {"src", &mpic_irq_ops, MPIC_SRC_REG_START, MPIC_SRC_REG_SIZE}, {"cpu", &mpic_cpu_ops, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE}, }; From 780d16b77f992db81e90b7dd7474a9397ce393b9 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 7 Dec 2012 17:15:15 +0100 Subject: [PATCH 1964/2270] openpic: Convert subregions to memory api The "openpic" controller is currently using one big region and does subregion dispatching manually. Move this to the memory api. Signed-off-by: Alexander Graf --- hw/openpic.c | 106 +++++++++++++++++++++++++++++---------------------- 1 file changed, 61 insertions(+), 45 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index b671d9de33..2a3b56af49 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -79,6 +79,15 @@ enum { #define OPENPIC_IRQ_MBX0 (OPENPIC_IRQ_DBL0 + OPENPIC_MAX_DBL) /* First mailbox IRQ */ #endif +#define OPENPIC_GLB_REG_START 0x0 +#define OPENPIC_GLB_REG_SIZE 0x10F0 +#define OPENPIC_TMR_REG_START 0x10F0 +#define OPENPIC_TMR_REG_SIZE 0x220 +#define OPENPIC_SRC_REG_START 0x10000 +#define OPENPIC_SRC_REG_SIZE (MAX_SRC * 0x20) +#define OPENPIC_CPU_REG_START 0x20000 +#define OPENPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000) + /* MPIC */ #define MPIC_MAX_CPU 1 #define MPIC_MAX_EXT 12 @@ -842,53 +851,39 @@ static uint64_t openpic_cpu_read(void *opaque, hwaddr addr, unsigned len) return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12); } -static void openpic_write(void *opaque, hwaddr addr, uint64_t val, - unsigned len) -{ - openpic_t *opp = opaque; +static const MemoryRegionOps openpic_glb_ops = { + .write = openpic_gbl_write, + .read = openpic_gbl_read, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; - DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val); - if (addr < 0x1100) { - /* Global registers */ - openpic_gbl_write(opp, addr, val, len); - } else if (addr < 0x10000) { - /* Timers registers */ - openpic_timer_write(opp, addr, val, len); - } else if (addr < 0x20000) { - /* Source registers */ - openpic_src_write(opp, addr, val, len); - } else { - /* CPU registers */ - openpic_cpu_write(opp, addr, val, len); - } -} +static const MemoryRegionOps openpic_tmr_ops = { + .write = openpic_timer_write, + .read = openpic_timer_read, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; -static uint64_t openpic_read(void *opaque, hwaddr addr, unsigned len) -{ - openpic_t *opp = opaque; - uint32_t retval; +static const MemoryRegionOps openpic_cpu_ops = { + .write = openpic_cpu_write, + .read = openpic_cpu_read, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; - DPRINTF("%s: offset %08x\n", __func__, (int)addr); - if (addr < 0x1100) { - /* Global registers */ - retval = openpic_gbl_read(opp, addr, len); - } else if (addr < 0x10000) { - /* Timers registers */ - retval = openpic_timer_read(opp, addr, len); - } else if (addr < 0x20000) { - /* Source registers */ - retval = openpic_src_read(opp, addr, len); - } else { - /* CPU registers */ - retval = openpic_cpu_read(opp, addr, len); - } - - return retval; -} - -static const MemoryRegionOps openpic_ops = { - .read = openpic_read, - .write = openpic_write, +static const MemoryRegionOps openpic_src_ops = { + .write = openpic_src_write, + .read = openpic_src_read, .endianness = DEVICE_LITTLE_ENDIAN, .impl = { .min_access_size = 4, @@ -1009,12 +1004,33 @@ qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, { openpic_t *opp; int i, m; + struct { + const char *name; + MemoryRegionOps const *ops; + hwaddr start_addr; + ram_addr_t size; + } const list[] = { + {"glb", &openpic_glb_ops, OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE}, + {"tmr", &openpic_tmr_ops, OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE}, + {"src", &openpic_src_ops, OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE}, + {"cpu", &openpic_cpu_ops, OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE}, + }; /* XXX: for now, only one CPU is supported */ if (nb_cpus != 1) return NULL; opp = g_malloc0(sizeof(openpic_t)); - memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000); + + memory_region_init(&opp->mem, "openpic", 0x40000); + + for (i = 0; i < ARRAY_SIZE(list); i++) { + + memory_region_init_io(&opp->sub_io_mem[i], list[i].ops, opp, + list[i].name, list[i].size); + + memory_region_add_subregion(&opp->mem, list[i].start_addr, + &opp->sub_io_mem[i]); + } // isu_base &= 0xFFFC0000; opp->nb_cpus = nb_cpus; From 5861a33898bbddfd1a80c2e202cb9352e3b1ba62 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 7 Dec 2012 23:51:09 +0100 Subject: [PATCH 1965/2270] openpic: combine mpic and openpic irq raise functions The IRQ raise mechanisms of the OpenPIC and MPIC controllers is identical, just that the MPIC one can also raise critical interrupts. Combine those two and check for critical raise capability during runtime. Signed-off-by: Alexander Graf --- hw/openpic.c | 34 ++++++++++++++++------------------ hw/openpic.h | 3 +++ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index 2a3b56af49..d709e36b52 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -207,6 +207,9 @@ typedef struct openpic_t { PCIDevice pci_dev; MemoryRegion mem; + /* Behavior control */ + uint32_t flags; + /* Sub-regions */ MemoryRegion sub_io_mem[7]; @@ -234,9 +237,10 @@ typedef struct openpic_t { int irq_ipi0; int irq_tim0; void (*reset) (void *); - void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *); } openpic_t; +static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src); + static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ) { set_bit(q->queue, n_IRQ); @@ -321,7 +325,7 @@ static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ) return; } DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ); - opp->irq_raise(opp, n_CPU, src); + openpic_irq_raise(opp, n_CPU, src); } /* update pic state because registers for n_IRQ have changed value */ @@ -753,7 +757,7 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr, IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) { DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", idx, n_IRQ); - opp->irq_raise(opp, idx, src); + openpic_irq_raise(opp, idx, src); } break; default: @@ -996,7 +1000,13 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src) { - qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]); + int n_ci = IDR_CI0 - n_CPU; + + if ((opp->flags & OPENPIC_FLAG_IDE_CRIT) && test_bit(&src->ide, n_ci)) { + qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]); + } else { + qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]); + } } qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, @@ -1059,7 +1069,6 @@ qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, openpic_save, openpic_load, opp); qemu_register_reset(openpic_reset, opp); - opp->irq_raise = openpic_irq_raise; opp->reset = openpic_reset; if (pmem) @@ -1068,18 +1077,6 @@ qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq); } -static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src) -{ - int n_ci = IDR_CI0 - n_CPU; - - if(test_bit(&src->ide, n_ci)) { - qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]); - } - else { - qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]); - } -} - static void mpic_reset (void *opaque) { openpic_t *mpp = (openpic_t *)opaque; @@ -1265,7 +1262,8 @@ qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, mpp->dst[i].irqs = irqs[i]; mpp->irq_out = irq_out; - mpp->irq_raise = mpic_irq_raise; + /* Enable critical interrupt support */ + mpp->flags |= OPENPIC_FLAG_IDE_CRIT; mpp->reset = mpic_reset; register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp); diff --git a/hw/openpic.h b/hw/openpic.h index f50a1e42bd..1232d1039c 100644 --- a/hw/openpic.h +++ b/hw/openpic.h @@ -11,6 +11,9 @@ enum { OPENPIC_OUTPUT_NB, }; +/* OpenPIC capability flags */ +#define OPENPIC_FLAG_IDE_CRIT (1 << 0) + qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, qemu_irq **irqs, qemu_irq irq_out); qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, From c38c0b8ad0551e470984f2ae7e8e54aae304ed4b Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 8 Dec 2012 00:43:42 +0100 Subject: [PATCH 1966/2270] openpic: merge mpic and openpic timer handling The openpic and mpic timer handling code is basically the same. Merge them. Signed-off-by: Alexander Graf --- hw/openpic.c | 131 ++++++++++++--------------------------------------- 1 file changed, 31 insertions(+), 100 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index d709e36b52..80016a2039 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -195,7 +195,6 @@ enum IPVP_bits { #define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK) typedef struct IRQ_dst_t { - uint32_t tfrr; uint32_t pctp; /* CPU current task priority */ uint32_t pcsr; /* CPU sensitivity register */ IRQ_queue_t raised; @@ -533,9 +532,6 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val, case 0x10E0: /* SPVE */ opp->spve = val & 0x000000FF; break; - case 0x10F0: /* TIFR */ - opp->tifr = val; - break; default: break; } @@ -587,9 +583,6 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len) case 0x10E0: /* SPVE */ retval = opp->spve; break; - case 0x10F0: /* TIFR */ - retval = opp->tifr; - break; default: break; } @@ -607,24 +600,28 @@ static void openpic_timer_write(void *opaque, hwaddr addr, uint64_t val, DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); if (addr & 0xF) return; - addr -= 0x10; - addr &= 0xFFFF; - idx = (addr & 0xFFF0) >> 6; + idx = (addr >> 6) & 0x3; addr = addr & 0x30; - switch (addr) { - case 0x00: /* TICC */ + + if (addr == 0x0) { + /* TIFR (TFRR) */ + opp->tifr = val; + return; + } + switch (addr & 0x30) { + case 0x00: /* TICC (GTCCR) */ break; - case 0x10: /* TIBC */ + case 0x10: /* TIBC (GTBCR) */ if ((opp->timers[idx].ticc & 0x80000000) != 0 && (val & 0x80000000) == 0 && (opp->timers[idx].tibc & 0x80000000) != 0) opp->timers[idx].ticc &= ~0x80000000; opp->timers[idx].tibc = val; break; - case 0x20: /* TIVP */ + case 0x20: /* TIVP (GTIVPR) */ write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val); break; - case 0x30: /* TIDE */ + case 0x30: /* TIDE (GTIDR) */ write_IRQreg_ide(opp, opp->irq_tim0 + idx, val); break; } @@ -633,31 +630,35 @@ static void openpic_timer_write(void *opaque, hwaddr addr, uint64_t val, static uint64_t openpic_timer_read(void *opaque, hwaddr addr, unsigned len) { openpic_t *opp = opaque; - uint32_t retval; + uint32_t retval = -1; int idx; DPRINTF("%s: addr %08x\n", __func__, addr); - retval = 0xFFFFFFFF; - if (addr & 0xF) - return retval; - addr -= 0x10; - addr &= 0xFFFF; - idx = (addr & 0xFFF0) >> 6; - addr = addr & 0x30; - switch (addr) { - case 0x00: /* TICC */ + if (addr & 0xF) { + goto out; + } + idx = (addr >> 6) & 0x3; + if (addr == 0x0) { + /* TIFR (TFRR) */ + retval = opp->tifr; + goto out; + } + switch (addr & 0x30) { + case 0x00: /* TICC (GTCCR) */ retval = opp->timers[idx].ticc; break; - case 0x10: /* TIBC */ + case 0x10: /* TIBC (GTBCR) */ retval = opp->timers[idx].tibc; break; - case 0x20: /* TIPV */ + case 0x20: /* TIPV (TIPV) */ retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx); break; - case 0x30: /* TIDE */ + case 0x30: /* TIDE (TIDR) */ retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx); break; } + +out: DPRINTF("%s: => %08x\n", __func__, retval); return retval; @@ -930,7 +931,6 @@ static void openpic_save(QEMUFile* f, void *opaque) qemu_put_sbe32s(f, &opp->nb_cpus); for (i = 0; i < opp->nb_cpus; i++) { - qemu_put_be32s(f, &opp->dst[i].tfrr); qemu_put_be32s(f, &opp->dst[i].pctp); qemu_put_be32s(f, &opp->dst[i].pcsr); openpic_save_IRQ_queue(f, &opp->dst[i].raised); @@ -983,7 +983,6 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) qemu_get_sbe32s(f, &opp->nb_cpus); for (i = 0; i < opp->nb_cpus; i++) { - qemu_get_be32s(f, &opp->dst[i].tfrr); qemu_get_be32s(f, &opp->dst[i].pctp); qemu_get_be32s(f, &opp->dst[i].pcsr); openpic_load_IRQ_queue(f, &opp->dst[i].raised); @@ -1100,7 +1099,6 @@ static void mpic_reset (void *opaque) /* Initialise IRQ destinations */ for (i = 0; i < MAX_CPU; i++) { mpp->dst[i].pctp = 0x0000000F; - mpp->dst[i].tfrr = 0x00000000; memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t)); mpp->dst[i].raised.next = -1; memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t)); @@ -1115,73 +1113,6 @@ static void mpic_reset (void *opaque) mpp->glbc = 0x00000000; } -static void mpic_timer_write(void *opaque, hwaddr addr, uint64_t val, - unsigned len) -{ - openpic_t *mpp = opaque; - int idx, cpu; - - DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val); - if (addr & 0xF) - return; - cpu = addr >> 12; - idx = (addr >> 6) & 0x3; - switch (addr & 0x30) { - case 0x00: /* gtccr */ - break; - case 0x10: /* gtbcr */ - if ((mpp->timers[idx].ticc & 0x80000000) != 0 && - (val & 0x80000000) == 0 && - (mpp->timers[idx].tibc & 0x80000000) != 0) - mpp->timers[idx].ticc &= ~0x80000000; - mpp->timers[idx].tibc = val; - break; - case 0x20: /* GTIVPR */ - write_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx, val); - break; - case 0x30: /* GTIDR & TFRR */ - if ((addr & 0xF0) == 0xF0) - mpp->dst[cpu].tfrr = val; - else - write_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx, val); - break; - } -} - -static uint64_t mpic_timer_read(void *opaque, hwaddr addr, unsigned len) -{ - openpic_t *mpp = opaque; - uint32_t retval; - int idx, cpu; - - DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr); - retval = 0xFFFFFFFF; - if (addr & 0xF) - return retval; - cpu = addr >> 12; - idx = (addr >> 6) & 0x3; - switch (addr & 0x30) { - case 0x00: /* gtccr */ - retval = mpp->timers[idx].ticc; - break; - case 0x10: /* gtbcr */ - retval = mpp->timers[idx].tibc; - break; - case 0x20: /* TIPV */ - retval = read_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx); - break; - case 0x30: /* TIDR */ - if ((addr &0xF0) == 0XF0) - retval = mpp->dst[cpu].tfrr; - else - retval = read_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx); - break; - } - DPRINTF("%s: => %08x\n", __func__, retval); - - return retval; -} - static const MemoryRegionOps mpic_glb_ops = { .write = openpic_gbl_write, .read = openpic_gbl_read, @@ -1193,8 +1124,8 @@ static const MemoryRegionOps mpic_glb_ops = { }; static const MemoryRegionOps mpic_tmr_ops = { - .write = mpic_timer_write, - .read = mpic_timer_read, + .write = openpic_timer_write, + .read = openpic_timer_read, .endianness = DEVICE_BIG_ENDIAN, .impl = { .min_access_size = 4, From 825463b38414c9afb657caee1ce20eff2d521317 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 8 Dec 2012 00:58:54 +0100 Subject: [PATCH 1967/2270] openpic: combine openpic and mpic reset functions The openpic and mpic reset handlers are almost identical. Combine them and extract the differences into state variables. Signed-off-by: Alexander Graf --- hw/openpic.c | 103 +++++++++++++++++++++------------------------------ 1 file changed, 42 insertions(+), 61 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index 80016a2039..e94529b7cc 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -53,7 +53,6 @@ #define MAX_IPI 4 #define MAX_IRQ (MAX_SRC + MAX_IPI + MAX_TMR) #define VID 0x03 /* MPIC version ID */ -#define VENI 0x00000000 /* Vendor ID */ enum { IRQ_IPVP = 0, @@ -125,6 +124,14 @@ enum { #define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */ #define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */ +#define FREP_NIRQ_SHIFT 16 +#define FREP_NCPU_SHIFT 8 +#define FREP_VID_SHIFT 0 + +#define VID_REVISION_1_2 2 + +#define VENI_GENERIC 0x00000000 /* Generic Vendor ID */ + enum mpic_ide_bits { IDR_EP = 31, IDR_CI0 = 30, @@ -208,6 +215,13 @@ typedef struct openpic_t { /* Behavior control */ uint32_t flags; + uint32_t nb_irqs; + uint32_t vid; + uint32_t veni; /* Vendor identification register */ + uint32_t spve_mask; + uint32_t tifr_reset; + uint32_t ipvp_reset; + uint32_t ide_reset; /* Sub-regions */ MemoryRegion sub_io_mem[7]; @@ -215,8 +229,6 @@ typedef struct openpic_t { /* Global registers */ uint32_t frep; /* Feature reporting register */ uint32_t glbc; /* Global configuration register */ - uint32_t micr; /* MPIC interrupt configuration register */ - uint32_t veni; /* Vendor identification register */ uint32_t pint; /* Processor initialization register */ uint32_t spve; /* Spurious vector register */ uint32_t tifr; /* Timer frequency reporting register */ @@ -235,7 +247,6 @@ typedef struct openpic_t { int max_irq; int irq_ipi0; int irq_tim0; - void (*reset) (void *); } openpic_t; static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src); @@ -412,17 +423,17 @@ static void openpic_reset (void *opaque) opp->glbc = 0x80000000; /* Initialise controller registers */ - opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID; - opp->veni = VENI; + opp->frep = ((opp->nb_irqs -1) << FREP_NIRQ_SHIFT) | + ((opp->nb_cpus -1) << FREP_NCPU_SHIFT) | + (opp->vid << FREP_VID_SHIFT); + opp->pint = 0x00000000; - opp->spve = 0x000000FF; - opp->tifr = 0x003F7A00; - /* ? */ - opp->micr = 0x00000000; + opp->spve = -1 & opp->spve_mask; + opp->tifr = opp->tifr_reset; /* Initialise IRQ sources */ for (i = 0; i < opp->max_irq; i++) { - opp->src[i].ipvp = 0xA0000000; - opp->src[i].ide = 0x00000000; + opp->src[i].ipvp = opp->ipvp_reset; + opp->src[i].ide = opp->ide_reset; } /* Initialise IRQ destinations */ for (i = 0; i < MAX_CPU; i++) { @@ -499,9 +510,9 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val, case 0x1000: /* FREP */ break; case 0x1020: /* GLBC */ - if (val & 0x80000000 && opp->reset) - opp->reset(opp); - opp->glbc = val & ~0x80000000; + if (val & 0x80000000) { + openpic_reset(opp); + } break; case 0x1080: /* VENI */ break; @@ -530,7 +541,7 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val, } break; case 0x10E0: /* SPVE */ - opp->spve = val & 0x000000FF; + opp->spve = val & opp->spve_mask; break; default: break; @@ -912,9 +923,7 @@ static void openpic_save(QEMUFile* f, void *opaque) openpic_t *opp = (openpic_t *)opaque; unsigned int i; - qemu_put_be32s(f, &opp->frep); qemu_put_be32s(f, &opp->glbc); - qemu_put_be32s(f, &opp->micr); qemu_put_be32s(f, &opp->veni); qemu_put_be32s(f, &opp->pint); qemu_put_be32s(f, &opp->spve); @@ -964,9 +973,7 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) if (version_id != 1) return -EINVAL; - qemu_get_be32s(f, &opp->frep); qemu_get_be32s(f, &opp->glbc); - qemu_get_be32s(f, &opp->micr); qemu_get_be32s(f, &opp->veni); qemu_get_be32s(f, &opp->pint); qemu_get_be32s(f, &opp->spve); @@ -1043,6 +1050,11 @@ qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, // isu_base &= 0xFFFC0000; opp->nb_cpus = nb_cpus; + opp->nb_irqs = OPENPIC_EXT_IRQ; + opp->vid = VID; + opp->veni = VENI_GENERIC; + opp->spve_mask = 0xFF; + opp->tifr_reset = 0x003F7A00; opp->max_irq = OPENPIC_MAX_IRQ; opp->irq_ipi0 = OPENPIC_IRQ_IPI0; opp->irq_tim0 = OPENPIC_IRQ_TIM0; @@ -1068,51 +1080,12 @@ qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, openpic_save, openpic_load, opp); qemu_register_reset(openpic_reset, opp); - opp->reset = openpic_reset; - if (pmem) *pmem = &opp->mem; return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq); } -static void mpic_reset (void *opaque) -{ - openpic_t *mpp = (openpic_t *)opaque; - int i; - - mpp->glbc = 0x80000000; - /* Initialise controller registers */ - mpp->frep = 0x004f0002 | ((mpp->nb_cpus - 1) << 8); - mpp->veni = VENI; - mpp->pint = 0x00000000; - mpp->spve = 0x0000FFFF; - /* Initialise IRQ sources */ - for (i = 0; i < mpp->max_irq; i++) { - mpp->src[i].ipvp = 0x80800000; - mpp->src[i].ide = 0x00000001; - } - /* Set IDE for IPIs to 0 so we don't get spurious interrupts */ - for (i = mpp->irq_ipi0; i < (mpp->irq_ipi0 + MAX_IPI); i++) { - mpp->src[i].ide = 0; - } - /* Initialise IRQ destinations */ - for (i = 0; i < MAX_CPU; i++) { - mpp->dst[i].pctp = 0x0000000F; - memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t)); - mpp->dst[i].raised.next = -1; - memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t)); - mpp->dst[i].servicing.next = -1; - } - /* Initialise timers */ - for (i = 0; i < MAX_TMR; i++) { - mpp->timers[i].ticc = 0x00000000; - mpp->timers[i].tibc = 0x80000000; - } - /* Go out of RESET state */ - mpp->glbc = 0x00000000; -} - static const MemoryRegionOps mpic_glb_ops = { .write = openpic_gbl_write, .read = openpic_gbl_read, @@ -1185,6 +1158,15 @@ qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, } mpp->nb_cpus = nb_cpus; + /* 12 external sources, 48 internal sources , 4 timer sources, + 4 IPI sources, 4 messaging sources, and 8 Shared MSI sources */ + mpp->nb_irqs = 80; + mpp->vid = VID_REVISION_1_2; + mpp->veni = VENI_GENERIC; + mpp->spve_mask = 0xFFFF; + mpp->tifr_reset = 0x00000000; + mpp->ipvp_reset = 0x80000000; + mpp->ide_reset = 0x00000001; mpp->max_irq = MPIC_MAX_IRQ; mpp->irq_ipi0 = MPIC_IPI_IRQ; mpp->irq_tim0 = MPIC_TMR_IRQ; @@ -1195,10 +1177,9 @@ qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, /* Enable critical interrupt support */ mpp->flags |= OPENPIC_FLAG_IDE_CRIT; - mpp->reset = mpic_reset; register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp); - qemu_register_reset(mpic_reset, mpp); + qemu_register_reset(openpic_reset, mpp); return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq); } From 35732cb41e8f8608bb0fd6ae023daee56d439bf1 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 8 Dec 2012 01:04:48 +0100 Subject: [PATCH 1968/2270] openpic: unify memory api subregions The only difference between the "openpic" and "mpic" memory api subregion descriptors is the endianness. Unify them as openpic accessors with explicit endianness markers in their names. Signed-off-by: Alexander Graf --- hw/openpic.c | 108 ++++++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 52 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index e94529b7cc..623c8077de 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -867,7 +867,7 @@ static uint64_t openpic_cpu_read(void *opaque, hwaddr addr, unsigned len) return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12); } -static const MemoryRegionOps openpic_glb_ops = { +static const MemoryRegionOps openpic_glb_ops_le = { .write = openpic_gbl_write, .read = openpic_gbl_read, .endianness = DEVICE_LITTLE_ENDIAN, @@ -877,7 +877,17 @@ static const MemoryRegionOps openpic_glb_ops = { }, }; -static const MemoryRegionOps openpic_tmr_ops = { +static const MemoryRegionOps openpic_glb_ops_be = { + .write = openpic_gbl_write, + .read = openpic_gbl_read, + .endianness = DEVICE_BIG_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + +static const MemoryRegionOps openpic_tmr_ops_le = { .write = openpic_timer_write, .read = openpic_timer_read, .endianness = DEVICE_LITTLE_ENDIAN, @@ -887,7 +897,17 @@ static const MemoryRegionOps openpic_tmr_ops = { }, }; -static const MemoryRegionOps openpic_cpu_ops = { +static const MemoryRegionOps openpic_tmr_ops_be = { + .write = openpic_timer_write, + .read = openpic_timer_read, + .endianness = DEVICE_BIG_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + +static const MemoryRegionOps openpic_cpu_ops_le = { .write = openpic_cpu_write, .read = openpic_cpu_read, .endianness = DEVICE_LITTLE_ENDIAN, @@ -897,7 +917,17 @@ static const MemoryRegionOps openpic_cpu_ops = { }, }; -static const MemoryRegionOps openpic_src_ops = { +static const MemoryRegionOps openpic_cpu_ops_be = { + .write = openpic_cpu_write, + .read = openpic_cpu_read, + .endianness = DEVICE_BIG_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + +static const MemoryRegionOps openpic_src_ops_le = { .write = openpic_src_write, .read = openpic_src_read, .endianness = DEVICE_LITTLE_ENDIAN, @@ -907,6 +937,16 @@ static const MemoryRegionOps openpic_src_ops = { }, }; +static const MemoryRegionOps openpic_src_ops_be = { + .write = openpic_src_write, + .read = openpic_src_read, + .endianness = DEVICE_BIG_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q) { unsigned int i; @@ -1026,10 +1066,14 @@ qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, hwaddr start_addr; ram_addr_t size; } const list[] = { - {"glb", &openpic_glb_ops, OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE}, - {"tmr", &openpic_tmr_ops, OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE}, - {"src", &openpic_src_ops, OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE}, - {"cpu", &openpic_cpu_ops, OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE}, + {"glb", &openpic_glb_ops_le, OPENPIC_GLB_REG_START, + OPENPIC_GLB_REG_SIZE}, + {"tmr", &openpic_tmr_ops_le, OPENPIC_TMR_REG_START, + OPENPIC_TMR_REG_SIZE}, + {"src", &openpic_src_ops_le, OPENPIC_SRC_REG_START, + OPENPIC_SRC_REG_SIZE}, + {"cpu", &openpic_cpu_ops_le, OPENPIC_CPU_REG_START, + OPENPIC_CPU_REG_SIZE}, }; /* XXX: for now, only one CPU is supported */ @@ -1086,46 +1130,6 @@ qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq); } -static const MemoryRegionOps mpic_glb_ops = { - .write = openpic_gbl_write, - .read = openpic_gbl_read, - .endianness = DEVICE_BIG_ENDIAN, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static const MemoryRegionOps mpic_tmr_ops = { - .write = openpic_timer_write, - .read = openpic_timer_read, - .endianness = DEVICE_BIG_ENDIAN, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static const MemoryRegionOps mpic_cpu_ops = { - .write = openpic_cpu_write, - .read = openpic_cpu_read, - .endianness = DEVICE_BIG_ENDIAN, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static const MemoryRegionOps mpic_irq_ops = { - .write = openpic_src_write, - .read = openpic_src_read, - .endianness = DEVICE_BIG_ENDIAN, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, int nb_cpus, qemu_irq **irqs, qemu_irq irq_out) { @@ -1137,10 +1141,10 @@ qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, hwaddr start_addr; ram_addr_t size; } const list[] = { - {"glb", &mpic_glb_ops, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE}, - {"tmr", &mpic_tmr_ops, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE}, - {"src", &mpic_irq_ops, MPIC_SRC_REG_START, MPIC_SRC_REG_SIZE}, - {"cpu", &mpic_cpu_ops, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE}, + {"glb", &openpic_glb_ops_be, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE}, + {"tmr", &openpic_tmr_ops_be, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE}, + {"src", &openpic_src_ops_be, MPIC_SRC_REG_START, MPIC_SRC_REG_SIZE}, + {"cpu", &openpic_cpu_ops_be, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE}, }; mpp = g_malloc0(sizeof(openpic_t)); From e1d10851522d7262a266f95d54c48eb2b1d8eb9b Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 8 Dec 2012 01:25:21 +0100 Subject: [PATCH 1969/2270] openpic: remove unused type variable The openpic source irqs are carrying around a type indicator that is never accessed by anything. Remove it. Signed-off-by: Alexander Graf --- hw/openpic.c | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index 623c8077de..91e87b7d48 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -168,13 +168,6 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr, static void openpic_cpu_write_internal(void *opaque, hwaddr addr, uint32_t val, int idx); -enum { - IRQ_EXTERNAL = 0x01, - IRQ_INTERNAL = 0x02, - IRQ_TIMER = 0x04, - IRQ_SPECIAL = 0x08, -}; - typedef struct IRQ_queue_t { uint32_t queue[BF_WIDTH(MAX_IRQ)]; int next; @@ -184,7 +177,6 @@ typedef struct IRQ_queue_t { typedef struct IRQ_src_t { uint32_t ipvp; /* IRQ vector/priority register */ uint32_t ide; /* IRQ destination register */ - int type; int last_cpu; int pending; /* TRUE if IRQ is pending */ } IRQ_src_t; @@ -972,7 +964,6 @@ static void openpic_save(QEMUFile* f, void *opaque) for (i = 0; i < opp->max_irq; i++) { qemu_put_be32s(f, &opp->src[i].ipvp); qemu_put_be32s(f, &opp->src[i].ide); - qemu_put_sbe32s(f, &opp->src[i].type); qemu_put_sbe32s(f, &opp->src[i].last_cpu); qemu_put_sbe32s(f, &opp->src[i].pending); } @@ -1022,7 +1013,6 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) for (i = 0; i < opp->max_irq; i++) { qemu_get_be32s(f, &opp->src[i].ipvp); qemu_get_be32s(f, &opp->src[i].ide); - qemu_get_sbe32s(f, &opp->src[i].type); qemu_get_sbe32s(f, &opp->src[i].last_cpu); qemu_get_sbe32s(f, &opp->src[i].pending); } @@ -1059,7 +1049,7 @@ qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, qemu_irq **irqs, qemu_irq irq_out) { openpic_t *opp; - int i, m; + int i; struct { const char *name; MemoryRegionOps const *ops; @@ -1102,20 +1092,7 @@ qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, opp->max_irq = OPENPIC_MAX_IRQ; opp->irq_ipi0 = OPENPIC_IRQ_IPI0; opp->irq_tim0 = OPENPIC_IRQ_TIM0; - /* Set IRQ types */ - for (i = 0; i < OPENPIC_EXT_IRQ; i++) { - opp->src[i].type = IRQ_EXTERNAL; - } - for (; i < OPENPIC_IRQ_TIM0; i++) { - opp->src[i].type = IRQ_SPECIAL; - } - m = OPENPIC_IRQ_IPI0; - for (; i < m; i++) { - opp->src[i].type = IRQ_TIMER; - } - for (; i < OPENPIC_MAX_IRQ; i++) { - opp->src[i].type = IRQ_INTERNAL; - } + for (i = 0; i < nb_cpus; i++) opp->dst[i].irqs = irqs[i]; opp->irq_out = irq_out; From 1945dbc15f0f1ffdc9a10526448e9eba7c599d98 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 8 Dec 2012 01:49:52 +0100 Subject: [PATCH 1970/2270] openpic: convert simple reg operations to builtin bitops The openpic code has its own bitmap code to access bits inside of a bitmap. However, that is overkill when we simply want to check for a bit inside of a uint32_t. So instead, let's use normal bit masks and C builtin shifts and ands. Signed-off-by: Alexander Graf --- hw/openpic.c | 67 ++++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index 91e87b7d48..d2038d87cb 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -132,13 +132,12 @@ enum { #define VENI_GENERIC 0x00000000 /* Generic Vendor ID */ -enum mpic_ide_bits { - IDR_EP = 31, - IDR_CI0 = 30, - IDR_CI1 = 29, - IDR_P1 = 1, - IDR_P0 = 0, -}; +#define IDR_EP_SHIFT 31 +#define IDR_EP_MASK (1 << IDR_EP_SHIFT) +#define IDR_CI0_SHIFT 30 +#define IDR_CI1_SHIFT 29 +#define IDR_P1_SHIFT 1 +#define IDR_P0_SHIFT 0 #define BF_WIDTH(_bits_) \ (((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8)) @@ -181,13 +180,17 @@ typedef struct IRQ_src_t { int pending; /* TRUE if IRQ is pending */ } IRQ_src_t; -enum IPVP_bits { - IPVP_MASK = 31, - IPVP_ACTIVITY = 30, - IPVP_MODE = 29, - IPVP_POLARITY = 23, - IPVP_SENSE = 22, -}; +#define IPVP_MASK_SHIFT 31 +#define IPVP_MASK_MASK (1 << IPVP_MASK_SHIFT) +#define IPVP_ACTIVITY_SHIFT 30 +#define IPVP_ACTIVITY_MASK (1 << IPVP_ACTIVITY_SHIFT) +#define IPVP_MODE_SHIFT 29 +#define IPVP_MODE_MASK (1 << IPVP_MODE_SHIFT) +#define IPVP_POLARITY_SHIFT 23 +#define IPVP_POLARITY_MASK (1 << IPVP_POLARITY_SHIFT) +#define IPVP_SENSE_SHIFT 22 +#define IPVP_SENSE_MASK (1 << IPVP_SENSE_SHIFT) + #define IPVP_PRIORITY_MASK (0x1F << 16) #define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16)) #define IPVP_VECTOR_MASK ((1 << VECTOR_BITS) - 1) @@ -310,7 +313,7 @@ static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ) __func__, n_IRQ, n_CPU); return; } - set_bit(&src->ipvp, IPVP_ACTIVITY); + src->ipvp |= IPVP_ACTIVITY_MASK; IRQ_setbit(&dst->raised, n_IRQ); if (priority < dst->raised.priority) { /* An higher priority IRQ is already raised */ @@ -343,7 +346,7 @@ static void openpic_update_irq(openpic_t *opp, int n_IRQ) DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ); return; } - if (test_bit(&src->ipvp, IPVP_MASK)) { + if (src->ipvp & IPVP_MASK_MASK) { /* Interrupt source is disabled */ DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ); return; @@ -353,7 +356,7 @@ static void openpic_update_irq(openpic_t *opp, int n_IRQ) DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ); return; } - if (test_bit(&src->ipvp, IPVP_ACTIVITY)) { + if (src->ipvp & IPVP_ACTIVITY_MASK) { /* IRQ already active */ DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ); return; @@ -367,18 +370,19 @@ static void openpic_update_irq(openpic_t *opp, int n_IRQ) if (src->ide == (1 << src->last_cpu)) { /* Only one CPU is allowed to receive this IRQ */ IRQ_local_pipe(opp, src->last_cpu, n_IRQ); - } else if (!test_bit(&src->ipvp, IPVP_MODE)) { + } else if (!(src->ipvp & IPVP_MODE_MASK)) { /* Directed delivery mode */ for (i = 0; i < opp->nb_cpus; i++) { - if (test_bit(&src->ide, i)) + if (src->ide & (1 << i)) { IRQ_local_pipe(opp, i, n_IRQ); + } } } else { /* Distributed delivery mode */ for (i = src->last_cpu + 1; i != src->last_cpu; i++) { if (i == opp->nb_cpus) i = 0; - if (test_bit(&src->ide, i)) { + if (src->ide & (1 << i)) { IRQ_local_pipe(opp, i, n_IRQ); src->last_cpu = i; break; @@ -395,11 +399,12 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level) src = &opp->src[n_IRQ]; DPRINTF("openpic: set irq %d = %d ipvp=%08x\n", n_IRQ, level, src->ipvp); - if (test_bit(&src->ipvp, IPVP_SENSE)) { + if (src->ipvp & IPVP_SENSE_MASK) { /* level-sensitive irq */ src->pending = level; - if (!level) - reset_bit(&src->ipvp, IPVP_ACTIVITY); + if (!level) { + src->ipvp &= ~IPVP_ACTIVITY_MASK; + } } else { /* edge-sensitive irq */ if (level) @@ -810,13 +815,13 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr, retval = IPVP_VECTOR(opp->spve); } else { src = &opp->src[n_IRQ]; - if (!test_bit(&src->ipvp, IPVP_ACTIVITY) || + if (!(src->ipvp & IPVP_ACTIVITY_MASK) || !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) { /* - Spurious level-sensitive IRQ * - Priorities has been changed * and the pending IRQ isn't allowed anymore */ - reset_bit(&src->ipvp, IPVP_ACTIVITY); + src->ipvp &= ~IPVP_ACTIVITY_MASK; retval = IPVP_VECTOR(opp->spve); } else { /* IRQ enter servicing state */ @@ -825,20 +830,20 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr, } IRQ_resetbit(&dst->raised, n_IRQ); dst->raised.next = -1; - if (!test_bit(&src->ipvp, IPVP_SENSE)) { + if (!(src->ipvp & IPVP_SENSE_MASK)) { /* edge-sensitive IRQ */ - reset_bit(&src->ipvp, IPVP_ACTIVITY); + src->ipvp &= ~IPVP_ACTIVITY_MASK; src->pending = 0; } if ((n_IRQ >= opp->irq_ipi0) && (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) { src->ide &= ~(1 << idx); - if (src->ide && !test_bit(&src->ipvp, IPVP_SENSE)) { + if (src->ide && !(src->ipvp & IPVP_SENSE_MASK)) { /* trigger on CPUs that didn't know about it yet */ openpic_set_irq(opp, n_IRQ, 1); openpic_set_irq(opp, n_IRQ, 0); /* if all CPUs knew about it, set active bit again */ - set_bit(&src->ipvp, IPVP_ACTIVITY); + src->ipvp |= IPVP_ACTIVITY_MASK; } } } @@ -1036,9 +1041,9 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src) { - int n_ci = IDR_CI0 - n_CPU; + int n_ci = IDR_CI0_SHIFT - n_CPU; - if ((opp->flags & OPENPIC_FLAG_IDE_CRIT) && test_bit(&src->ide, n_ci)) { + if ((opp->flags & OPENPIC_FLAG_IDE_CRIT) && (src->ide & (1 << n_ci))) { qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]); } else { qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]); From 6d544ee8ac2097c87fc97b53d6a1310d9daa0562 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 8 Dec 2012 01:59:20 +0100 Subject: [PATCH 1971/2270] openpic: rename openpic_t to OpenPICState Rename the openpic_t struct to OpenPICState, so it adheres better to the current coding style rules. Signed-off-by: Alexander Graf --- hw/openpic.c | 68 ++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index d2038d87cb..d5c27052e9 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -204,7 +204,7 @@ typedef struct IRQ_dst_t { qemu_irq *irqs; } IRQ_dst_t; -typedef struct openpic_t { +typedef struct OpenPICState { PCIDevice pci_dev; MemoryRegion mem; @@ -242,9 +242,9 @@ typedef struct openpic_t { int max_irq; int irq_ipi0; int irq_tim0; -} openpic_t; +} OpenPICState; -static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src); +static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src); static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ) { @@ -261,7 +261,7 @@ static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ) return test_bit(q->queue, n_IRQ); } -static void IRQ_check (openpic_t *opp, IRQ_queue_t *q) +static void IRQ_check(OpenPICState *opp, IRQ_queue_t *q) { int next, i; int priority; @@ -282,7 +282,7 @@ static void IRQ_check (openpic_t *opp, IRQ_queue_t *q) q->priority = priority; } -static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q) +static int IRQ_get_next(OpenPICState *opp, IRQ_queue_t *q) { if (q->next == -1) { /* XXX: optimize */ @@ -292,7 +292,7 @@ static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q) return q->next; } -static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ) +static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ) { IRQ_dst_t *dst; IRQ_src_t *src; @@ -334,7 +334,7 @@ static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ) } /* update pic state because registers for n_IRQ have changed value */ -static void openpic_update_irq(openpic_t *opp, int n_IRQ) +static void openpic_update_irq(OpenPICState *opp, int n_IRQ) { IRQ_src_t *src; int i; @@ -393,7 +393,7 @@ static void openpic_update_irq(openpic_t *opp, int n_IRQ) static void openpic_set_irq(void *opaque, int n_IRQ, int level) { - openpic_t *opp = opaque; + OpenPICState *opp = opaque; IRQ_src_t *src; src = &opp->src[n_IRQ]; @@ -415,7 +415,7 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level) static void openpic_reset (void *opaque) { - openpic_t *opp = (openpic_t *)opaque; + OpenPICState *opp = (OpenPICState *)opaque; int i; opp->glbc = 0x80000000; @@ -450,17 +450,17 @@ static void openpic_reset (void *opaque) opp->glbc = 0x00000000; } -static inline uint32_t read_IRQreg_ide(openpic_t *opp, int n_IRQ) +static inline uint32_t read_IRQreg_ide(OpenPICState *opp, int n_IRQ) { return opp->src[n_IRQ].ide; } -static inline uint32_t read_IRQreg_ipvp(openpic_t *opp, int n_IRQ) +static inline uint32_t read_IRQreg_ipvp(OpenPICState *opp, int n_IRQ) { return opp->src[n_IRQ].ipvp; } -static inline void write_IRQreg_ide(openpic_t *opp, int n_IRQ, uint32_t val) +static inline void write_IRQreg_ide(OpenPICState *opp, int n_IRQ, uint32_t val) { uint32_t tmp; @@ -470,7 +470,7 @@ static inline void write_IRQreg_ide(openpic_t *opp, int n_IRQ, uint32_t val) DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide); } -static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val) +static inline void write_IRQreg_ipvp(OpenPICState *opp, int n_IRQ, uint32_t val) { /* NOTE: not fully accurate for special IRQs, but simple and sufficient */ /* ACTIVITY bit is read-only */ @@ -484,7 +484,7 @@ static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val) static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val, unsigned len) { - openpic_t *opp = opaque; + OpenPICState *opp = opaque; IRQ_dst_t *dst; int idx; @@ -547,7 +547,7 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val, static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len) { - openpic_t *opp = opaque; + OpenPICState *opp = opaque; uint32_t retval; DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr); @@ -599,10 +599,10 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len) return retval; } -static void openpic_timer_write(void *opaque, hwaddr addr, uint64_t val, +static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val, unsigned len) { - openpic_t *opp = opaque; + OpenPICState *opp = opaque; int idx; DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); @@ -635,9 +635,9 @@ static void openpic_timer_write(void *opaque, hwaddr addr, uint64_t val, } } -static uint64_t openpic_timer_read(void *opaque, hwaddr addr, unsigned len) +static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len) { - openpic_t *opp = opaque; + OpenPICState *opp = opaque; uint32_t retval = -1; int idx; @@ -675,7 +675,7 @@ out: static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val, unsigned len) { - openpic_t *opp = opaque; + OpenPICState *opp = opaque; int idx; DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); @@ -694,7 +694,7 @@ static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val, static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len) { - openpic_t *opp = opaque; + OpenPICState *opp = opaque; uint32_t retval; int idx; @@ -719,7 +719,7 @@ static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len) static void openpic_cpu_write_internal(void *opaque, hwaddr addr, uint32_t val, int idx) { - openpic_t *opp = opaque; + OpenPICState *opp = opaque; IRQ_src_t *src; IRQ_dst_t *dst; int s_IRQ, n_IRQ; @@ -783,7 +783,7 @@ static void openpic_cpu_write(void *opaque, hwaddr addr, uint64_t val, static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr, int idx) { - openpic_t *opp = opaque; + OpenPICState *opp = opaque; IRQ_src_t *src; IRQ_dst_t *dst; uint32_t retval; @@ -885,8 +885,8 @@ static const MemoryRegionOps openpic_glb_ops_be = { }; static const MemoryRegionOps openpic_tmr_ops_le = { - .write = openpic_timer_write, - .read = openpic_timer_read, + .write = openpic_tmr_write, + .read = openpic_tmr_read, .endianness = DEVICE_LITTLE_ENDIAN, .impl = { .min_access_size = 4, @@ -895,8 +895,8 @@ static const MemoryRegionOps openpic_tmr_ops_le = { }; static const MemoryRegionOps openpic_tmr_ops_be = { - .write = openpic_timer_write, - .read = openpic_timer_read, + .write = openpic_tmr_write, + .read = openpic_tmr_read, .endianness = DEVICE_BIG_ENDIAN, .impl = { .min_access_size = 4, @@ -957,7 +957,7 @@ static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q) static void openpic_save(QEMUFile* f, void *opaque) { - openpic_t *opp = (openpic_t *)opaque; + OpenPICState *opp = (OpenPICState *)opaque; unsigned int i; qemu_put_be32s(f, &opp->glbc); @@ -1003,7 +1003,7 @@ static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q) static int openpic_load(QEMUFile* f, void *opaque, int version_id) { - openpic_t *opp = (openpic_t *)opaque; + OpenPICState *opp = (OpenPICState *)opaque; unsigned int i; if (version_id != 1) @@ -1039,7 +1039,7 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) return pci_device_load(&opp->pci_dev, f); } -static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src) +static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src) { int n_ci = IDR_CI0_SHIFT - n_CPU; @@ -1053,7 +1053,7 @@ static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src) qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, qemu_irq **irqs, qemu_irq irq_out) { - openpic_t *opp; + OpenPICState *opp; int i; struct { const char *name; @@ -1074,7 +1074,7 @@ qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, /* XXX: for now, only one CPU is supported */ if (nb_cpus != 1) return NULL; - opp = g_malloc0(sizeof(openpic_t)); + opp = g_malloc0(sizeof(OpenPICState)); memory_region_init(&opp->mem, "openpic", 0x40000); @@ -1115,7 +1115,7 @@ qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, int nb_cpus, qemu_irq **irqs, qemu_irq irq_out) { - openpic_t *mpp; + OpenPICState *mpp; int i; struct { const char *name; @@ -1129,7 +1129,7 @@ qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, {"cpu", &openpic_cpu_ops_be, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE}, }; - mpp = g_malloc0(sizeof(openpic_t)); + mpp = g_malloc0(sizeof(OpenPICState)); memory_region_init(&mpp->mem, "mpic", 0x40000); memory_region_add_subregion(address_space, base, &mpp->mem); From 5bac0701113f4de4fee053a3939b0f569a04b88c Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 8 Dec 2012 02:18:58 +0100 Subject: [PATCH 1972/2270] openpic: remove irq_out The current openpic emulation contains half-ready code for bypass mode. Remove it, so that when someone wants to finish it they can start from a clean state. Signed-off-by: Alexander Graf --- hw/openpic.c | 8 ++------ hw/openpic.h | 4 ++-- hw/ppc/e500.c | 2 +- hw/ppc_newworld.c | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index d5c27052e9..5116b3ee4d 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -237,8 +237,6 @@ typedef struct OpenPICState { uint32_t ticc; /* Global timer current count register */ uint32_t tibc; /* Global timer base count register */ } timers[MAX_TMR]; - /* IRQ out is used when in bypass mode (not implemented) */ - qemu_irq irq_out; int max_irq; int irq_ipi0; int irq_tim0; @@ -1051,7 +1049,7 @@ static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src) } qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, - qemu_irq **irqs, qemu_irq irq_out) + qemu_irq **irqs) { OpenPICState *opp; int i; @@ -1100,7 +1098,6 @@ qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, for (i = 0; i < nb_cpus; i++) opp->dst[i].irqs = irqs[i]; - opp->irq_out = irq_out; register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2, openpic_save, openpic_load, opp); @@ -1113,7 +1110,7 @@ qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, } qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, - int nb_cpus, qemu_irq **irqs, qemu_irq irq_out) + int nb_cpus, qemu_irq **irqs) { OpenPICState *mpp; int i; @@ -1159,7 +1156,6 @@ qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, for (i = 0; i < nb_cpus; i++) mpp->dst[i].irqs = irqs[i]; - mpp->irq_out = irq_out; /* Enable critical interrupt support */ mpp->flags |= OPENPIC_FLAG_IDE_CRIT; diff --git a/hw/openpic.h b/hw/openpic.h index 1232d1039c..8a68f20d38 100644 --- a/hw/openpic.h +++ b/hw/openpic.h @@ -15,7 +15,7 @@ enum { #define OPENPIC_FLAG_IDE_CRIT (1 << 0) qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, - qemu_irq **irqs, qemu_irq irq_out); + qemu_irq **irqs); qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, - int nb_cpus, qemu_irq **irqs, qemu_irq irq_out); + int nb_cpus, qemu_irq **irqs); #endif /* __OPENPIC_H__ */ diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index f3e97d8bb5..3f6d58c307 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -493,7 +493,7 @@ void ppce500_init(PPCE500Params *params) /* MPIC */ mpic = mpic_init(ccsr_addr_space, MPC8544_MPIC_REGS_OFFSET, - smp_cpus, irqs, NULL); + smp_cpus, irqs); if (!mpic) { cpu_abort(env, "MPIC failed to initialize\n"); diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index 664747ead3..b9c2cd8d1d 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -320,7 +320,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) exit(1); } } - pic = openpic_init(&pic_mem, smp_cpus, openpic_irqs, NULL); + pic = openpic_init(&pic_mem, smp_cpus, openpic_irqs); if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) { /* 970 gets a U3 bus */ pci_bus = pci_pmac_u3_init(pic, get_system_memory(), get_system_io()); From d0b7263134dfd4d487698b639f2069951f3fdb26 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 8 Dec 2012 05:17:14 +0100 Subject: [PATCH 1973/2270] openpic: convert to qdev This patch converts the OpenPIC device to qdev. Along the way it renames the "openpic" target to "raven" and the "mpic" target to "fsl_mpic_20", to better reflect the actual models they implement. This way we have a generic OpenPIC device now that can handle different flavors of the OpenPIC specification. Signed-off-by: Alexander Graf --- hw/openpic.c | 288 +++++++++++++++++++++++----------------------- hw/openpic.h | 8 +- hw/ppc/e500.c | 24 +++- hw/ppc_newworld.c | 25 +++- 4 files changed, 185 insertions(+), 160 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index 5116b3ee4d..591b2917ed 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -37,6 +37,7 @@ #include "ppc_mac.h" #include "pci.h" #include "openpic.h" +#include "sysbus.h" //#define DEBUG_OPENPIC @@ -54,30 +55,10 @@ #define MAX_IRQ (MAX_SRC + MAX_IPI + MAX_TMR) #define VID 0x03 /* MPIC version ID */ -enum { - IRQ_IPVP = 0, - IRQ_IDE, -}; - -/* OpenPIC */ -#define OPENPIC_MAX_CPU 2 -#define OPENPIC_MAX_IRQ 64 -#define OPENPIC_EXT_IRQ 48 -#define OPENPIC_MAX_TMR MAX_TMR -#define OPENPIC_MAX_IPI MAX_IPI - -/* Interrupt definitions */ -#define OPENPIC_IRQ_FE (OPENPIC_EXT_IRQ) /* Internal functional IRQ */ -#define OPENPIC_IRQ_ERR (OPENPIC_EXT_IRQ + 1) /* Error IRQ */ -#define OPENPIC_IRQ_TIM0 (OPENPIC_EXT_IRQ + 2) /* First timer IRQ */ -#if OPENPIC_MAX_IPI > 0 -#define OPENPIC_IRQ_IPI0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First IPI IRQ */ -#define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_IPI0 + (OPENPIC_MAX_CPU * OPENPIC_MAX_IPI)) /* First doorbell IRQ */ -#else -#define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First doorbell IRQ */ -#define OPENPIC_IRQ_MBX0 (OPENPIC_IRQ_DBL0 + OPENPIC_MAX_DBL) /* First mailbox IRQ */ -#endif +/* OpenPIC capability flags */ +#define OPENPIC_FLAG_IDE_CRIT (1 << 0) +/* OpenPIC address map */ #define OPENPIC_GLB_REG_START 0x0 #define OPENPIC_GLB_REG_SIZE 0x10F0 #define OPENPIC_TMR_REG_START 0x10F0 @@ -87,31 +68,37 @@ enum { #define OPENPIC_CPU_REG_START 0x20000 #define OPENPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000) -/* MPIC */ -#define MPIC_MAX_CPU 1 -#define MPIC_MAX_EXT 12 -#define MPIC_MAX_INT 64 -#define MPIC_MAX_IRQ MAX_IRQ +/* Raven */ +#define RAVEN_MAX_CPU 2 +#define RAVEN_MAX_EXT 48 +#define RAVEN_MAX_IRQ 64 +#define RAVEN_MAX_TMR MAX_TMR +#define RAVEN_MAX_IPI MAX_IPI + +/* Interrupt definitions */ +#define RAVEN_FE_IRQ (RAVEN_MAX_EXT) /* Internal functional IRQ */ +#define RAVEN_ERR_IRQ (RAVEN_MAX_EXT + 1) /* Error IRQ */ +#define RAVEN_TMR_IRQ (RAVEN_MAX_EXT + 2) /* First timer IRQ */ +#define RAVEN_IPI_IRQ (RAVEN_TMR_IRQ + RAVEN_MAX_TMR) /* First IPI IRQ */ +/* First doorbell IRQ */ +#define RAVEN_DBL_IRQ (RAVEN_IPI_IRQ + (RAVEN_MAX_CPU * RAVEN_MAX_IPI)) + +/* FSL_MPIC_20 */ +#define FSL_MPIC_20_MAX_CPU 1 +#define FSL_MPIC_20_MAX_EXT 12 +#define FSL_MPIC_20_MAX_INT 64 +#define FSL_MPIC_20_MAX_IRQ MAX_IRQ /* Interrupt definitions */ /* IRQs, accessible through the IRQ region */ -#define MPIC_EXT_IRQ 0x00 -#define MPIC_INT_IRQ 0x10 -#define MPIC_MSG_IRQ 0xb0 -#define MPIC_MSI_IRQ 0xe0 +#define FSL_MPIC_20_EXT_IRQ 0x00 +#define FSL_MPIC_20_INT_IRQ 0x10 +#define FSL_MPIC_20_MSG_IRQ 0xb0 +#define FSL_MPIC_20_MSI_IRQ 0xe0 /* These are available through separate regions, but for simplicity's sake mapped into the same number space */ -#define MPIC_TMR_IRQ 0x100 -#define MPIC_IPI_IRQ 0x104 - -#define MPIC_GLB_REG_START 0x0 -#define MPIC_GLB_REG_SIZE 0x10F0 -#define MPIC_TMR_REG_START 0x10F0 -#define MPIC_TMR_REG_SIZE 0x220 -#define MPIC_SRC_REG_START 0x10000 -#define MPIC_SRC_REG_SIZE (MAX_SRC * 0x20) -#define MPIC_CPU_REG_START 0x20000 -#define MPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000) +#define FSL_MPIC_20_TMR_IRQ 0x100 +#define FSL_MPIC_20_IPI_IRQ 0x104 /* * Block Revision Register1 (BRR1): QEMU does not fully emulate @@ -129,6 +116,7 @@ enum { #define FREP_VID_SHIFT 0 #define VID_REVISION_1_2 2 +#define VID_REVISION_1_3 3 #define VENI_GENERIC 0x00000000 /* Generic Vendor ID */ @@ -205,10 +193,11 @@ typedef struct IRQ_dst_t { } IRQ_dst_t; typedef struct OpenPICState { - PCIDevice pci_dev; + SysBusDevice busdev; MemoryRegion mem; /* Behavior control */ + uint32_t model; uint32_t flags; uint32_t nb_irqs; uint32_t vid; @@ -231,15 +220,15 @@ typedef struct OpenPICState { IRQ_src_t src[MAX_IRQ]; /* Local registers per output pin */ IRQ_dst_t dst[MAX_CPU]; - int nb_cpus; + uint32_t nb_cpus; /* Timer registers */ struct { uint32_t ticc; /* Global timer current count register */ uint32_t tibc; /* Global timer base count register */ } timers[MAX_TMR]; - int max_irq; - int irq_ipi0; - int irq_tim0; + uint32_t max_irq; + uint32_t irq_ipi0; + uint32_t irq_tim0; } OpenPICState; static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src); @@ -411,9 +400,9 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level) openpic_update_irq(opp, n_IRQ); } -static void openpic_reset (void *opaque) +static void openpic_reset(DeviceState *d) { - OpenPICState *opp = (OpenPICState *)opaque; + OpenPICState *opp = FROM_SYSBUS(typeof (*opp), sysbus_from_qdev(d)); int i; opp->glbc = 0x80000000; @@ -506,7 +495,7 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val, break; case 0x1020: /* GLBC */ if (val & 0x80000000) { - openpic_reset(opp); + openpic_reset(&opp->busdev.qdev); } break; case 0x1080: /* VENI */ @@ -971,7 +960,7 @@ static void openpic_save(QEMUFile* f, void *opaque) qemu_put_sbe32s(f, &opp->src[i].pending); } - qemu_put_sbe32s(f, &opp->nb_cpus); + qemu_put_be32s(f, &opp->nb_cpus); for (i = 0; i < opp->nb_cpus; i++) { qemu_put_be32s(f, &opp->dst[i].pctp); @@ -984,8 +973,6 @@ static void openpic_save(QEMUFile* f, void *opaque) qemu_put_be32s(f, &opp->timers[i].ticc); qemu_put_be32s(f, &opp->timers[i].tibc); } - - pci_device_save(&opp->pci_dev, f); } static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q) @@ -1020,7 +1007,7 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) qemu_get_sbe32s(f, &opp->src[i].pending); } - qemu_get_sbe32s(f, &opp->nb_cpus); + qemu_get_be32s(f, &opp->nb_cpus); for (i = 0; i < opp->nb_cpus; i++) { qemu_get_be32s(f, &opp->dst[i].pctp); @@ -1034,7 +1021,7 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) qemu_get_be32s(f, &opp->timers[i].tibc); } - return pci_device_load(&opp->pci_dev, f); + return 0; } static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src) @@ -1048,17 +1035,18 @@ static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src) } } -qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, - qemu_irq **irqs) +struct memreg { + const char *name; + MemoryRegionOps const *ops; + hwaddr start_addr; + ram_addr_t size; +}; + +static int openpic_init(SysBusDevice *dev) { - OpenPICState *opp; - int i; - struct { - const char *name; - MemoryRegionOps const *ops; - hwaddr start_addr; - ram_addr_t size; - } const list[] = { + OpenPICState *opp = FROM_SYSBUS(typeof (*opp), dev); + int i, j; + const struct memreg list_le[] = { {"glb", &openpic_glb_ops_le, OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE}, {"tmr", &openpic_tmr_ops_le, OPENPIC_TMR_REG_START, @@ -1068,16 +1056,57 @@ qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, {"cpu", &openpic_cpu_ops_le, OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE}, }; + const struct memreg list_be[] = { + {"glb", &openpic_glb_ops_be, OPENPIC_GLB_REG_START, + OPENPIC_GLB_REG_SIZE}, + {"tmr", &openpic_tmr_ops_be, OPENPIC_TMR_REG_START, + OPENPIC_TMR_REG_SIZE}, + {"src", &openpic_src_ops_be, OPENPIC_SRC_REG_START, + OPENPIC_SRC_REG_SIZE}, + {"cpu", &openpic_cpu_ops_be, OPENPIC_CPU_REG_START, + OPENPIC_CPU_REG_SIZE}, + }; + struct memreg const *list; - /* XXX: for now, only one CPU is supported */ - if (nb_cpus != 1) - return NULL; - opp = g_malloc0(sizeof(OpenPICState)); + switch (opp->model) { + case OPENPIC_MODEL_FSL_MPIC_20: + default: + opp->flags |= OPENPIC_FLAG_IDE_CRIT; + opp->nb_irqs = 80; + opp->vid = VID_REVISION_1_2; + opp->veni = VENI_GENERIC; + opp->spve_mask = 0xFFFF; + opp->tifr_reset = 0x00000000; + opp->ipvp_reset = 0x80000000; + opp->ide_reset = 0x00000001; + opp->max_irq = FSL_MPIC_20_MAX_IRQ; + opp->irq_ipi0 = FSL_MPIC_20_IPI_IRQ; + opp->irq_tim0 = FSL_MPIC_20_TMR_IRQ; + list = list_be; + break; + case OPENPIC_MODEL_RAVEN: + opp->nb_irqs = RAVEN_MAX_EXT; + opp->vid = VID_REVISION_1_3; + opp->veni = VENI_GENERIC; + opp->spve_mask = 0xFF; + opp->tifr_reset = 0x003F7A00; + opp->ipvp_reset = 0xA0000000; + opp->ide_reset = 0x00000000; + opp->max_irq = RAVEN_MAX_IRQ; + opp->irq_ipi0 = RAVEN_IPI_IRQ; + opp->irq_tim0 = RAVEN_TMR_IRQ; + list = list_le; + + /* Only UP supported today */ + if (opp->nb_cpus != 1) { + return -EINVAL; + } + break; + } memory_region_init(&opp->mem, "openpic", 0x40000); - for (i = 0; i < ARRAY_SIZE(list); i++) { - + for (i = 0; i < ARRAY_SIZE(list_le); i++) { memory_region_init_io(&opp->sub_io_mem[i], list[i].ops, opp, list[i].name, list[i].size); @@ -1085,83 +1114,48 @@ qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, &opp->sub_io_mem[i]); } - // isu_base &= 0xFFFC0000; - opp->nb_cpus = nb_cpus; - opp->nb_irqs = OPENPIC_EXT_IRQ; - opp->vid = VID; - opp->veni = VENI_GENERIC; - opp->spve_mask = 0xFF; - opp->tifr_reset = 0x003F7A00; - opp->max_irq = OPENPIC_MAX_IRQ; - opp->irq_ipi0 = OPENPIC_IRQ_IPI0; - opp->irq_tim0 = OPENPIC_IRQ_TIM0; - - for (i = 0; i < nb_cpus; i++) - opp->dst[i].irqs = irqs[i]; - - register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2, - openpic_save, openpic_load, opp); - qemu_register_reset(openpic_reset, opp); - - if (pmem) - *pmem = &opp->mem; - - return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq); -} - -qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, - int nb_cpus, qemu_irq **irqs) -{ - OpenPICState *mpp; - int i; - struct { - const char *name; - MemoryRegionOps const *ops; - hwaddr start_addr; - ram_addr_t size; - } const list[] = { - {"glb", &openpic_glb_ops_be, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE}, - {"tmr", &openpic_tmr_ops_be, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE}, - {"src", &openpic_src_ops_be, MPIC_SRC_REG_START, MPIC_SRC_REG_SIZE}, - {"cpu", &openpic_cpu_ops_be, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE}, - }; - - mpp = g_malloc0(sizeof(OpenPICState)); - - memory_region_init(&mpp->mem, "mpic", 0x40000); - memory_region_add_subregion(address_space, base, &mpp->mem); - - for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) { - - memory_region_init_io(&mpp->sub_io_mem[i], list[i].ops, mpp, - list[i].name, list[i].size); - - memory_region_add_subregion(&mpp->mem, list[i].start_addr, - &mpp->sub_io_mem[i]); + for (i = 0; i < opp->nb_cpus; i++) { + opp->dst[i].irqs = g_new(qemu_irq, OPENPIC_OUTPUT_NB); + for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { + sysbus_init_irq(dev, &opp->dst[i].irqs[j]); + } } - mpp->nb_cpus = nb_cpus; - /* 12 external sources, 48 internal sources , 4 timer sources, - 4 IPI sources, 4 messaging sources, and 8 Shared MSI sources */ - mpp->nb_irqs = 80; - mpp->vid = VID_REVISION_1_2; - mpp->veni = VENI_GENERIC; - mpp->spve_mask = 0xFFFF; - mpp->tifr_reset = 0x00000000; - mpp->ipvp_reset = 0x80000000; - mpp->ide_reset = 0x00000001; - mpp->max_irq = MPIC_MAX_IRQ; - mpp->irq_ipi0 = MPIC_IPI_IRQ; - mpp->irq_tim0 = MPIC_TMR_IRQ; + register_savevm(&opp->busdev.qdev, "openpic", 0, 2, + openpic_save, openpic_load, opp); - for (i = 0; i < nb_cpus; i++) - mpp->dst[i].irqs = irqs[i]; + sysbus_init_mmio(dev, &opp->mem); + qdev_init_gpio_in(&dev->qdev, openpic_set_irq, opp->max_irq); - /* Enable critical interrupt support */ - mpp->flags |= OPENPIC_FLAG_IDE_CRIT; - - register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp); - qemu_register_reset(openpic_reset, mpp); - - return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq); + return 0; } + +static Property openpic_properties[] = { + DEFINE_PROP_UINT32("model", OpenPICState, model, OPENPIC_MODEL_FSL_MPIC_20), + DEFINE_PROP_UINT32("nb_cpus", OpenPICState, nb_cpus, 1), + DEFINE_PROP_END_OF_LIST(), +}; + +static void openpic_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = openpic_init; + dc->props = openpic_properties; + dc->reset = openpic_reset; +} + +static TypeInfo openpic_info = { + .name = "openpic", + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(OpenPICState), + .class_init = openpic_class_init, +}; + +static void openpic_register_types(void) +{ + type_register_static(&openpic_info); +} + +type_init(openpic_register_types) diff --git a/hw/openpic.h b/hw/openpic.h index 8a68f20d38..e226d7b563 100644 --- a/hw/openpic.h +++ b/hw/openpic.h @@ -11,11 +11,7 @@ enum { OPENPIC_OUTPUT_NB, }; -/* OpenPIC capability flags */ -#define OPENPIC_FLAG_IDE_CRIT (1 << 0) +#define OPENPIC_MODEL_RAVEN 0 +#define OPENPIC_MODEL_FSL_MPIC_20 1 -qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus, - qemu_irq **irqs); -qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base, - int nb_cpus, qemu_irq **irqs); #endif /* __OPENPIC_H__ */ diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 3f6d58c307..fa9b8ede4b 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -418,7 +418,7 @@ void ppce500_init(PPCE500Params *params) target_ulong dt_base = 0; target_ulong initrd_base = 0; target_long initrd_size=0; - int i=0; + int i = 0, j, k; unsigned int pci_irq_nrs[4] = {1, 2, 3, 4}; qemu_irq **irqs, *mpic; DeviceState *dev; @@ -492,13 +492,27 @@ void ppce500_init(PPCE500Params *params) ccsr_addr_space); /* MPIC */ - mpic = mpic_init(ccsr_addr_space, MPC8544_MPIC_REGS_OFFSET, - smp_cpus, irqs); + mpic = g_new(qemu_irq, 256); + dev = qdev_create(NULL, "openpic"); + qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus); + qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_FSL_MPIC_20); + qdev_init_nofail(dev); + s = sysbus_from_qdev(dev); - if (!mpic) { - cpu_abort(env, "MPIC failed to initialize\n"); + k = 0; + for (i = 0; i < smp_cpus; i++) { + for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { + sysbus_connect_irq(s, k++, irqs[i][j]); + } } + for (i = 0; i < 256; i++) { + mpic[i] = qdev_get_gpio_in(dev, i); + } + + memory_region_add_subregion(ccsr_addr_space, MPC8544_MPIC_REGS_OFFSET, + s->mmio[0].memory); + /* Serial */ if (serial_hds[0]) { serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET, diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index b9c2cd8d1d..8c2114e26f 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -67,6 +67,7 @@ #include "hw/usb.h" #include "blockdev.h" #include "exec-memory.h" +#include "sysbus.h" #define MAX_IDE_BUS 2 #define CFG_ADDR 0xf0000510 @@ -141,7 +142,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) char *filename; qemu_irq *pic, **openpic_irqs; MemoryRegion *unin_memory = g_new(MemoryRegion, 1); - int linux_boot, i; + int linux_boot, i, j, k; MemoryRegion *ram = g_new(MemoryRegion, 1), *bios = g_new(MemoryRegion, 1); hwaddr kernel_base, initrd_base, cmdline_base = 0; long kernel_size, initrd_size; @@ -156,6 +157,8 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) void *fw_cfg; void *dbdma; int machine_arch; + SysBusDevice *s; + DeviceState *dev; linux_boot = (kernel_filename != NULL); @@ -320,7 +323,25 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) exit(1); } } - pic = openpic_init(&pic_mem, smp_cpus, openpic_irqs); + + pic = g_new(qemu_irq, 64); + + dev = qdev_create(NULL, "openpic"); + qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_RAVEN); + qdev_init_nofail(dev); + s = sysbus_from_qdev(dev); + pic_mem = s->mmio[0].memory; + k = 0; + for (i = 0; i < smp_cpus; i++) { + for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { + sysbus_connect_irq(s, k++, openpic_irqs[i][j]); + } + } + + for (i = 0; i < 64; i++) { + pic[i] = qdev_get_gpio_in(dev, i); + } + if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) { /* 970 gets a U3 bus */ pci_bus = pci_pmac_u3_init(pic, get_system_memory(), get_system_io()); From dbbbfd6058dda61f57d1f72133aa54eb27330411 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 8 Dec 2012 13:51:50 +0100 Subject: [PATCH 1974/2270] openpic: make brr1 model specific Now that we can properly distinguish between openpic model differences, let's move brr1 out of the raven code path. Signed-off-by: Alexander Graf --- hw/openpic.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/openpic.c b/hw/openpic.c index 591b2917ed..5bf16ea0a0 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -206,6 +206,7 @@ typedef struct OpenPICState { uint32_t tifr_reset; uint32_t ipvp_reset; uint32_t ide_reset; + uint32_t brr1; /* Sub-regions */ MemoryRegion sub_io_mem[7]; @@ -784,7 +785,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr, addr &= 0xFF0; switch (addr) { case 0x00: /* Block Revision Register1 (BRR1) */ - retval = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN; + retval = opp->brr1; break; case 0x80: /* PCTP */ retval = dst->pctp; @@ -1082,6 +1083,7 @@ static int openpic_init(SysBusDevice *dev) opp->max_irq = FSL_MPIC_20_MAX_IRQ; opp->irq_ipi0 = FSL_MPIC_20_IPI_IRQ; opp->irq_tim0 = FSL_MPIC_20_TMR_IRQ; + opp->brr1 = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN; list = list_be; break; case OPENPIC_MODEL_RAVEN: @@ -1095,6 +1097,7 @@ static int openpic_init(SysBusDevice *dev) opp->max_irq = RAVEN_MAX_IRQ; opp->irq_ipi0 = RAVEN_IPI_IRQ; opp->irq_tim0 = RAVEN_TMR_IRQ; + opp->brr1 = -1; list = list_le; /* Only UP supported today */ From 732aa6ec2639ace8bcb0b27b9c0d71103bd1d153 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 8 Dec 2012 14:18:00 +0100 Subject: [PATCH 1975/2270] openpic: add Shared MSI support The OpenPIC allows MSI access through shared MSI registers. Implement them for the MPC8544 MPIC, so we can support MSIs. Signed-off-by: Alexander Graf --- hw/openpic.c | 150 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 130 insertions(+), 20 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index 5bf16ea0a0..4bea1e7b10 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -38,6 +38,7 @@ #include "pci.h" #include "openpic.h" #include "sysbus.h" +#include "msi.h" //#define DEBUG_OPENPIC @@ -52,6 +53,7 @@ #define MAX_TMR 4 #define VECTOR_BITS 8 #define MAX_IPI 4 +#define MAX_MSI 8 #define MAX_IRQ (MAX_SRC + MAX_IPI + MAX_TMR) #define VID 0x03 /* MPIC version ID */ @@ -63,6 +65,8 @@ #define OPENPIC_GLB_REG_SIZE 0x10F0 #define OPENPIC_TMR_REG_START 0x10F0 #define OPENPIC_TMR_REG_SIZE 0x220 +#define OPENPIC_MSI_REG_START 0x1600 +#define OPENPIC_MSI_REG_SIZE 0x200 #define OPENPIC_SRC_REG_START 0x10000 #define OPENPIC_SRC_REG_SIZE (MAX_SRC * 0x20) #define OPENPIC_CPU_REG_START 0x20000 @@ -127,6 +131,12 @@ #define IDR_P1_SHIFT 1 #define IDR_P0_SHIFT 0 +#define MSIIR_OFFSET 0x140 +#define MSIIR_SRS_SHIFT 29 +#define MSIIR_SRS_MASK (0x7 << MSIIR_SRS_SHIFT) +#define MSIIR_IBS_SHIFT 24 +#define MSIIR_IBS_MASK (0x1f << MSIIR_IBS_SHIFT) + #define BF_WIDTH(_bits_) \ (((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8)) @@ -209,7 +219,7 @@ typedef struct OpenPICState { uint32_t brr1; /* Sub-regions */ - MemoryRegion sub_io_mem[7]; + MemoryRegion sub_io_mem[5]; /* Global registers */ uint32_t frep; /* Feature reporting register */ @@ -227,9 +237,14 @@ typedef struct OpenPICState { uint32_t ticc; /* Global timer current count register */ uint32_t tibc; /* Global timer base count register */ } timers[MAX_TMR]; + /* Shared MSI registers */ + struct { + uint32_t msir; /* Shared Message Signaled Interrupt Register */ + } msi[MAX_MSI]; uint32_t max_irq; uint32_t irq_ipi0; uint32_t irq_tim0; + uint32_t irq_msi; } OpenPICState; static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src); @@ -704,6 +719,68 @@ static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len) return retval; } +static void openpic_msi_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + OpenPICState *opp = opaque; + int idx = opp->irq_msi; + int srs, ibs; + + DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val); + if (addr & 0xF) { + return; + } + + switch (addr) { + case MSIIR_OFFSET: + srs = val >> MSIIR_SRS_SHIFT; + idx += srs; + ibs = (val & MSIIR_IBS_MASK) >> MSIIR_IBS_SHIFT; + opp->msi[srs].msir |= 1 << ibs; + openpic_set_irq(opp, idx, 1); + break; + default: + /* most registers are read-only, thus ignored */ + break; + } +} + +static uint64_t openpic_msi_read(void *opaque, hwaddr addr, unsigned size) +{ + OpenPICState *opp = opaque; + uint64_t r = 0; + int i, srs; + + DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr); + if (addr & 0xF) { + return -1; + } + + srs = addr >> 4; + + switch (addr) { + case 0x00: + case 0x10: + case 0x20: + case 0x30: + case 0x40: + case 0x50: + case 0x60: + case 0x70: /* MSIRs */ + r = opp->msi[srs].msir; + /* Clear on read */ + opp->msi[srs].msir = 0; + break; + case 0x120: /* MSISR */ + for (i = 0; i < MAX_MSI; i++) { + r |= (opp->msi[i].msir ? 1 : 0) << i; + } + break; + } + + return r; +} + static void openpic_cpu_write_internal(void *opaque, hwaddr addr, uint32_t val, int idx) { @@ -932,6 +1009,26 @@ static const MemoryRegionOps openpic_src_ops_be = { }, }; +static const MemoryRegionOps openpic_msi_ops_le = { + .read = openpic_msi_read, + .write = openpic_msi_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + +static const MemoryRegionOps openpic_msi_ops_be = { + .read = openpic_msi_read, + .write = openpic_msi_write, + .endianness = DEVICE_BIG_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q) { unsigned int i; @@ -1039,6 +1136,7 @@ static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src) struct memreg { const char *name; MemoryRegionOps const *ops; + bool map; hwaddr start_addr; ram_addr_t size; }; @@ -1047,27 +1145,31 @@ static int openpic_init(SysBusDevice *dev) { OpenPICState *opp = FROM_SYSBUS(typeof (*opp), dev); int i, j; - const struct memreg list_le[] = { - {"glb", &openpic_glb_ops_le, OPENPIC_GLB_REG_START, - OPENPIC_GLB_REG_SIZE}, - {"tmr", &openpic_tmr_ops_le, OPENPIC_TMR_REG_START, - OPENPIC_TMR_REG_SIZE}, - {"src", &openpic_src_ops_le, OPENPIC_SRC_REG_START, - OPENPIC_SRC_REG_SIZE}, - {"cpu", &openpic_cpu_ops_le, OPENPIC_CPU_REG_START, - OPENPIC_CPU_REG_SIZE}, + struct memreg list_le[] = { + {"glb", &openpic_glb_ops_le, true, + OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE}, + {"tmr", &openpic_tmr_ops_le, true, + OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE}, + {"msi", &openpic_msi_ops_le, true, + OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE}, + {"src", &openpic_src_ops_le, true, + OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE}, + {"cpu", &openpic_cpu_ops_le, true, + OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE}, }; - const struct memreg list_be[] = { - {"glb", &openpic_glb_ops_be, OPENPIC_GLB_REG_START, - OPENPIC_GLB_REG_SIZE}, - {"tmr", &openpic_tmr_ops_be, OPENPIC_TMR_REG_START, - OPENPIC_TMR_REG_SIZE}, - {"src", &openpic_src_ops_be, OPENPIC_SRC_REG_START, - OPENPIC_SRC_REG_SIZE}, - {"cpu", &openpic_cpu_ops_be, OPENPIC_CPU_REG_START, - OPENPIC_CPU_REG_SIZE}, + struct memreg list_be[] = { + {"glb", &openpic_glb_ops_be, true, + OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE}, + {"tmr", &openpic_tmr_ops_be, true, + OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE}, + {"msi", &openpic_msi_ops_be, true, + OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE}, + {"src", &openpic_src_ops_be, true, + OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE}, + {"cpu", &openpic_cpu_ops_be, true, + OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE}, }; - struct memreg const *list; + struct memreg *list; switch (opp->model) { case OPENPIC_MODEL_FSL_MPIC_20: @@ -1083,7 +1185,9 @@ static int openpic_init(SysBusDevice *dev) opp->max_irq = FSL_MPIC_20_MAX_IRQ; opp->irq_ipi0 = FSL_MPIC_20_IPI_IRQ; opp->irq_tim0 = FSL_MPIC_20_TMR_IRQ; + opp->irq_msi = FSL_MPIC_20_MSI_IRQ; opp->brr1 = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN; + msi_supported = true; list = list_be; break; case OPENPIC_MODEL_RAVEN: @@ -1099,6 +1203,8 @@ static int openpic_init(SysBusDevice *dev) opp->irq_tim0 = RAVEN_TMR_IRQ; opp->brr1 = -1; list = list_le; + /* Don't map MSI region */ + list[2].map = false; /* Only UP supported today */ if (opp->nb_cpus != 1) { @@ -1110,6 +1216,10 @@ static int openpic_init(SysBusDevice *dev) memory_region_init(&opp->mem, "openpic", 0x40000); for (i = 0; i < ARRAY_SIZE(list_le); i++) { + if (!list[i].map) { + continue; + } + memory_region_init_io(&opp->sub_io_mem[i], list[i].ops, opp, list[i].name, list[i].size); From a911b7a92064d17b862ae85fe8e5ec91b7ba1aa9 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 8 Dec 2012 14:26:37 +0100 Subject: [PATCH 1976/2270] PPC: e500: Add MSI support Now that our interrupt controller supports MSIs, let's expose that feature to the guest through the device tree! Signed-off-by: Alexander Graf --- hw/ppc/e500.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index fa9b8ede4b..1034f93963 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -48,6 +48,7 @@ #define MPC8544_CCSRBAR_BASE 0xE0000000ULL #define MPC8544_CCSRBAR_SIZE 0x00100000ULL #define MPC8544_MPIC_REGS_OFFSET 0x40000ULL +#define MPC8544_MSI_REGS_OFFSET 0x41600ULL #define MPC8544_SERIAL0_REGS_OFFSET 0x4500ULL #define MPC8544_SERIAL1_REGS_OFFSET 0x4600ULL #define MPC8544_PCI_REGS_OFFSET 0x8000ULL @@ -127,8 +128,10 @@ static int ppce500_load_device_tree(CPUPPCState *env, char soc[128]; char mpic[128]; uint32_t mpic_ph; + uint32_t msi_ph; char gutil[128]; char pci[128]; + char msi[128]; uint32_t pci_map[7 * 8]; uint32_t pci_ranges[14] = { @@ -300,6 +303,25 @@ static int ppce500_load_device_tree(CPUPPCState *env, qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000); qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0); + snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET); + qemu_devtree_add_subnode(fdt, msi); + qemu_devtree_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi"); + qemu_devtree_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200); + msi_ph = qemu_devtree_alloc_phandle(fdt); + qemu_devtree_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100); + qemu_devtree_setprop_phandle(fdt, msi, "interrupt-parent", mpic); + qemu_devtree_setprop_cells(fdt, msi, "interrupts", + 0xe0, 0x0, + 0xe1, 0x0, + 0xe2, 0x0, + 0xe3, 0x0, + 0xe4, 0x0, + 0xe5, 0x0, + 0xe6, 0x0, + 0xe7, 0x0); + qemu_devtree_setprop_cell(fdt, msi, "phandle", msi_ph); + qemu_devtree_setprop_cell(fdt, msi, "linux,phandle", msi_ph); + snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE); qemu_devtree_add_subnode(fdt, pci); qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0); @@ -315,6 +337,7 @@ static int ppce500_load_device_tree(CPUPPCState *env, for (i = 0; i < 14; i++) { pci_ranges[i] = cpu_to_be32(pci_ranges[i]); } + qemu_devtree_setprop_cell(fdt, pci, "fsl,msi", msi_ph); qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges)); qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32, MPC8544_PCI_REGS_BASE, 0, 0x1000); From 997505065dc92e533debf5cb23012ba4e673d387 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 8 Dec 2012 14:27:26 +0100 Subject: [PATCH 1977/2270] PPC: e500: Declare pci bridge as bridge The new PCI host bridge device needs to identify itself as PCI host bridge. Declare it as such. Signed-off-by: Alexander Graf --- hw/ppce500_pci.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 54c72b4fd2..e5343411be 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -330,9 +330,15 @@ static int e500_pcihost_bridge_initfn(PCIDevice *d) PPCE500CCSRState *ccsr = CCSR(container_get(qdev_get_machine(), "/e500-ccsr")); + pci_config_set_class(d->config, PCI_CLASS_BRIDGE_PCI); + d->config[PCI_HEADER_TYPE] = + (d->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) | + PCI_HEADER_TYPE_BRIDGE; + memory_region_init_alias(&b->bar0, "e500-pci-bar0", &ccsr->ccsr_space, 0, int128_get64(ccsr->ccsr_space.size)); pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &b->bar0); + return 0; } From 68d1e1f52d73ddcec4b0358f269d9a8c2ea216d9 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 6 Dec 2012 04:11:33 +0100 Subject: [PATCH 1978/2270] MSI-X: Fix endianness The MSI-X vector tables are usually stored in little endian in memory, so let's mark the accessors as such. This fixes MSI-X on e500 for me. Signed-off-by: Alexander Graf Acked-by: Michael S. Tsirkin --- hw/msix.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/msix.c b/hw/msix.c index 136ef09373..b57ae60491 100644 --- a/hw/msix.c +++ b/hw/msix.c @@ -180,8 +180,7 @@ static void msix_table_mmio_write(void *opaque, hwaddr addr, static const MemoryRegionOps msix_table_mmio_ops = { .read = msix_table_mmio_read, .write = msix_table_mmio_write, - /* TODO: MSIX should be LITTLE_ENDIAN. */ - .endianness = DEVICE_NATIVE_ENDIAN, + .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 4, .max_access_size = 4, @@ -198,8 +197,7 @@ static uint64_t msix_pba_mmio_read(void *opaque, hwaddr addr, static const MemoryRegionOps msix_pba_mmio_ops = { .read = msix_pba_mmio_read, - /* TODO: MSIX should be LITTLE_ENDIAN. */ - .endianness = DEVICE_NATIVE_ENDIAN, + .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 4, .max_access_size = 4, From dbe30e13e87a71e85e88ae3ffd3460173cbc8193 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 13 Dec 2012 00:44:22 +0100 Subject: [PATCH 1979/2270] openpic: fix minor coding style issues This patch removes all remaining occurences of spaces before function parameter indicating parenthesis. Signed-off-by: Alexander Graf --- hw/openpic.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index 4bea1e7b10..25d5cd7e26 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -140,17 +140,17 @@ #define BF_WIDTH(_bits_) \ (((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8)) -static inline void set_bit (uint32_t *field, int bit) +static inline void set_bit(uint32_t *field, int bit) { field[bit >> 5] |= 1 << (bit & 0x1F); } -static inline void reset_bit (uint32_t *field, int bit) +static inline void reset_bit(uint32_t *field, int bit) { field[bit >> 5] &= ~(1 << (bit & 0x1F)); } -static inline int test_bit (uint32_t *field, int bit) +static inline int test_bit(uint32_t *field, int bit) { return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0; } @@ -249,17 +249,17 @@ typedef struct OpenPICState { static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src); -static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ) +static inline void IRQ_setbit(IRQ_queue_t *q, int n_IRQ) { set_bit(q->queue, n_IRQ); } -static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ) +static inline void IRQ_resetbit(IRQ_queue_t *q, int n_IRQ) { reset_bit(q->queue, n_IRQ); } -static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ) +static inline int IRQ_testbit(IRQ_queue_t *q, int n_IRQ) { return test_bit(q->queue, n_IRQ); } From 76aec1f8b6549d14576a3eb739c731df8f678ffb Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 13 Dec 2012 12:48:14 +0100 Subject: [PATCH 1980/2270] openpic: Accelerate pending irq search When we're done with one interrupt, we need to search for the next pending interrupt in the queue. This search has grown quite big now that we have more than 256 possible irq lines. So let's memorize how many interrupts we have pending in our bitmaps, so that we can always bail out in the usual case - the one where we're all done. Signed-off-by: Alexander Graf --- hw/openpic.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/hw/openpic.c b/hw/openpic.c index 25d5cd7e26..3cbcea8eb3 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -169,6 +169,7 @@ typedef struct IRQ_queue_t { uint32_t queue[BF_WIDTH(MAX_IRQ)]; int next; int priority; + int pending; /* nr of pending bits in queue */ } IRQ_queue_t; typedef struct IRQ_src_t { @@ -251,11 +252,13 @@ static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src); static inline void IRQ_setbit(IRQ_queue_t *q, int n_IRQ) { + q->pending++; set_bit(q->queue, n_IRQ); } static inline void IRQ_resetbit(IRQ_queue_t *q, int n_IRQ) { + q->pending--; reset_bit(q->queue, n_IRQ); } @@ -271,6 +274,12 @@ static void IRQ_check(OpenPICState *opp, IRQ_queue_t *q) next = -1; priority = -1; + + if (!q->pending) { + /* IRQ bitmap is empty */ + goto out; + } + for (i = 0; i < opp->max_irq; i++) { if (IRQ_testbit(q, i)) { DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n", @@ -281,6 +290,8 @@ static void IRQ_check(OpenPICState *opp, IRQ_queue_t *q) } } } + +out: q->next = next; q->priority = priority; } From eafb325fb11af21ed9df3f5a310fd26e70954318 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 12 Dec 2012 12:56:40 +0100 Subject: [PATCH 1981/2270] PPC: E500: PCI: Make first slot qdev settable Today the first slot id in our e500 pci implementation is hardcoded to 0x11. Keep it there as default, but allow users to change the default to a different id. Signed-off-by: Alexander Graf --- hw/ppce500_pci.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index e5343411be..4cd4edc85b 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -87,6 +87,7 @@ struct PPCE500PCIState { struct pci_inbound pib[PPCE500_PCI_NR_PIBS]; uint32_t gasket_time; qemu_irq irq[4]; + uint32_t first_slot; /* mmio maps */ MemoryRegion container; MemoryRegion iomem; @@ -361,7 +362,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev) b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq, mpc85xx_pci_map_irq, s->irq, address_space_mem, - &s->pio, PCI_DEVFN(0x11, 0), 4); + &s->pio, PCI_DEVFN(s->first_slot, 0), 4); h->bus = b; pci_create_simple(b, 0, "e500-host-bridge"); @@ -401,12 +402,18 @@ static const TypeInfo e500_host_bridge_info = { .class_init = e500_host_bridge_class_init, }; +static Property pcihost_properties[] = { + DEFINE_PROP_UINT32("first_slot", PPCE500PCIState, first_slot, 0x11), + DEFINE_PROP_END_OF_LIST(), +}; + static void e500_pcihost_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); k->init = e500_pcihost_initfn; + dc->props = pcihost_properties; dc->vmsd = &vmstate_ppce500_pci; } From 05f57d9de8e99bf5f7ca762c6dc2f1e054c2074c Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 12 Dec 2012 12:58:12 +0100 Subject: [PATCH 1982/2270] PPC: E500: PCI: Make IRQ calculation more generic The IRQ line calculation is more or less hardcoded today. Instead, let's write it as an algorithmic function that theoretically allows an arbitrary number of PCI slots. Signed-off-by: Alexander Graf --- hw/ppce500_pci.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 4cd4edc85b..561a77661d 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -253,17 +253,10 @@ static const MemoryRegionOps e500_pci_reg_ops = { static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num) { - int devno = pci_dev->devfn >> 3, ret = 0; + int devno = pci_dev->devfn >> 3; + int ret; - switch (devno) { - /* Two PCI slot */ - case 0x11: - case 0x12: - ret = (irq_num + devno - 0x10) % 4; - break; - default: - printf("Error:%s:unknown dev number\n", __func__); - } + ret = (irq_num + devno) % 4; pci_debug("%s: devfn %x irq %d -> %d devno:%x\n", __func__, pci_dev->devfn, irq_num, ret, devno); From 347dd79dccf41a679115213da673dfd06c4c8cc8 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 12 Dec 2012 13:47:07 +0100 Subject: [PATCH 1983/2270] PPC: E500: Generate dt pci irq map dynamically Today we're hardcoding the PCI interrupt map in the e500 machine file. Instead, let's write it dynamically so that different machine types can have different slot properties. Signed-off-by: Alexander Graf --- hw/ppc/e500.c | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 1034f93963..ebb6d96689 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -66,25 +66,33 @@ struct boot_info uint32_t entry; }; -static void pci_map_create(void *fdt, uint32_t *pci_map, uint32_t mpic) +static uint32_t *pci_map_create(void *fdt, uint32_t mpic, int first_slot, + int nr_slots, int *len) { - int i; - const uint32_t tmp[] = { - /* IDSEL 0x11 J17 Slot 1 */ - 0x8800, 0x0, 0x0, 0x1, mpic, 0x2, 0x1, - 0x8800, 0x0, 0x0, 0x2, mpic, 0x3, 0x1, - 0x8800, 0x0, 0x0, 0x3, mpic, 0x4, 0x1, - 0x8800, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, + int i = 0; + int slot; + int pci_irq; + int last_slot = first_slot + nr_slots; + uint32_t *pci_map; - /* IDSEL 0x12 J16 Slot 2 */ - 0x9000, 0x0, 0x0, 0x1, mpic, 0x3, 0x1, - 0x9000, 0x0, 0x0, 0x2, mpic, 0x4, 0x1, - 0x9000, 0x0, 0x0, 0x3, mpic, 0x2, 0x1, - 0x9000, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, - }; - for (i = 0; i < (7 * 8); i++) { - pci_map[i] = cpu_to_be32(tmp[i]); + *len = nr_slots * 4 * 7 * sizeof(uint32_t); + pci_map = g_malloc(*len); + + for (slot = first_slot; slot < last_slot; slot++) { + for (pci_irq = 0; pci_irq < 4; pci_irq++) { + pci_map[i++] = cpu_to_be32(slot << 11); + pci_map[i++] = cpu_to_be32(0x0); + pci_map[i++] = cpu_to_be32(0x0); + pci_map[i++] = cpu_to_be32(pci_irq + 1); + pci_map[i++] = cpu_to_be32(mpic); + pci_map[i++] = cpu_to_be32(((pci_irq + slot) % 4) + 1); + pci_map[i++] = cpu_to_be32(0x1); + } } + + assert((i * sizeof(uint32_t)) == *len); + + return pci_map; } static void dt_serial_create(void *fdt, unsigned long long offset, @@ -132,7 +140,8 @@ static int ppce500_load_device_tree(CPUPPCState *env, char gutil[128]; char pci[128]; char msi[128]; - uint32_t pci_map[7 * 8]; + uint32_t *pci_map = NULL; + int len; uint32_t pci_ranges[14] = { 0x2000000, 0x0, 0xc0000000, @@ -329,8 +338,9 @@ static int ppce500_load_device_tree(CPUPPCState *env, qemu_devtree_setprop_string(fdt, pci, "device_type", "pci"); qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0, 0x0, 0x7); - pci_map_create(fdt, pci_map, qemu_devtree_get_phandle(fdt, mpic)); - qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, sizeof(pci_map)); + pci_map = pci_map_create(fdt, qemu_devtree_get_phandle(fdt, mpic), + 0x11, 2, &len); + qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, len); qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic); qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2); qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255); @@ -364,6 +374,7 @@ done: ret = fdt_size; out: + g_free(pci_map); return ret; } From 492ec48dc2d99ca13b24d554e1970af7e2581e23 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 12 Dec 2012 13:53:53 +0100 Subject: [PATCH 1984/2270] PPC: E500: Move PCI slot information into params We have a params struct that allows us to expose differences between e500 machine models. Include PCI slot information there, so we can have different machines with different PCI slot topology. Signed-off-by: Alexander Graf --- hw/ppc/e500.c | 4 +++- hw/ppc/e500.h | 2 ++ hw/ppc/e500plat.c | 2 ++ hw/ppc/mpc8544ds.c | 2 ++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index ebb6d96689..564f6548e4 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -339,7 +339,8 @@ static int ppce500_load_device_tree(CPUPPCState *env, qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0, 0x0, 0x7); pci_map = pci_map_create(fdt, qemu_devtree_get_phandle(fdt, mpic), - 0x11, 2, &len); + params->pci_first_slot, params->pci_nr_slots, + &len); qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, len); qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic); qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2); @@ -569,6 +570,7 @@ void ppce500_init(PPCE500Params *params) /* PCI */ dev = qdev_create(NULL, "e500-pcihost"); + qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); sysbus_connect_irq(s, 0, mpic[pci_irq_nrs[0]]); diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h index 7ae87f4e21..f5ff27385b 100644 --- a/hw/ppc/e500.h +++ b/hw/ppc/e500.h @@ -9,6 +9,8 @@ typedef struct PPCE500Params { const char *kernel_cmdline; const char *initrd_filename; const char *cpu_model; + int pci_first_slot; + int pci_nr_slots; /* e500-specific params */ diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c index 4cfb94061a..9365213aff 100644 --- a/hw/ppc/e500plat.c +++ b/hw/ppc/e500plat.c @@ -40,6 +40,8 @@ static void e500plat_init(QEMUMachineInitArgs *args) .kernel_cmdline = kernel_cmdline, .initrd_filename = initrd_filename, .cpu_model = cpu_model, + .pci_first_slot = 0x11, + .pci_nr_slots = 2, .fixup_devtree = e500plat_fixup_devtree, }; diff --git a/hw/ppc/mpc8544ds.c b/hw/ppc/mpc8544ds.c index e651661941..7e1761d20c 100644 --- a/hw/ppc/mpc8544ds.c +++ b/hw/ppc/mpc8544ds.c @@ -40,6 +40,8 @@ static void mpc8544ds_init(QEMUMachineInitArgs *args) .kernel_cmdline = kernel_cmdline, .initrd_filename = initrd_filename, .cpu_model = cpu_model, + .pci_first_slot = 0x11, + .pci_nr_slots = 2, .fixup_devtree = mpc8544ds_fixup_devtree, }; From 3bb7e02a9725a24e5bf915b35f914f82f5b07a1f Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 12 Dec 2012 14:58:30 +0100 Subject: [PATCH 1985/2270] PPC: E500plat: Make a lot of PCI slots available The ppce500 machine doesn't have to stick to hardware limitations, as it's defined as being fully device tree based. Thus we can change the initial PCI slot ID to 0x1 which gives us a whopping 31 PCI devices we can support with this machine now! Signed-off-by: Alexander Graf --- hw/ppc/e500plat.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c index 9365213aff..2992bd9794 100644 --- a/hw/ppc/e500plat.c +++ b/hw/ppc/e500plat.c @@ -14,6 +14,7 @@ #include "e500.h" #include "../boards.h" #include "device_tree.h" +#include "hw/pci.h" static void e500plat_fixup_devtree(PPCE500Params *params, void *fdt) { @@ -40,8 +41,8 @@ static void e500plat_init(QEMUMachineInitArgs *args) .kernel_cmdline = kernel_cmdline, .initrd_filename = initrd_filename, .cpu_model = cpu_model, - .pci_first_slot = 0x11, - .pci_nr_slots = 2, + .pci_first_slot = 0x1, + .pci_nr_slots = PCI_SLOT_MAX - 1, .fixup_devtree = e500plat_fixup_devtree, }; From 9e2c12988bebca7b99c0cd064b23fb7ea6643c86 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 13 Dec 2012 01:16:24 +0100 Subject: [PATCH 1986/2270] PPC: e500: pci: Export slot2irq calculation We need the calculation method to get from a PCI slot ID to its respective interrupt line twice. Once in the internal map function and once when assembling the device tree. So let's extract the calculation to a separate function that can be called by both users. Signed-off-by: Alexander Graf --- hw/ppc/e500.c | 5 ++++- hw/ppce500_pci.c | 3 ++- hw/ppce500_pci.h | 9 +++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 hw/ppce500_pci.h diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 564f6548e4..af6b67143a 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -34,6 +34,7 @@ #include "hw/sysbus.h" #include "exec-memory.h" #include "host-utils.h" +#include "hw/ppce500_pci.h" #define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb" #define UIMAGE_LOAD_BASE 0 @@ -72,6 +73,7 @@ static uint32_t *pci_map_create(void *fdt, uint32_t mpic, int first_slot, int i = 0; int slot; int pci_irq; + int host_irq; int last_slot = first_slot + nr_slots; uint32_t *pci_map; @@ -85,7 +87,8 @@ static uint32_t *pci_map_create(void *fdt, uint32_t mpic, int first_slot, pci_map[i++] = cpu_to_be32(0x0); pci_map[i++] = cpu_to_be32(pci_irq + 1); pci_map[i++] = cpu_to_be32(mpic); - pci_map[i++] = cpu_to_be32(((pci_irq + slot) % 4) + 1); + host_irq = ppce500_pci_map_irq_slot(slot, pci_irq); + pci_map[i++] = cpu_to_be32(host_irq + 1); pci_map[i++] = cpu_to_be32(0x1); } } diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 561a77661d..09e3507994 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -19,6 +19,7 @@ #include "pci.h" #include "pci_host.h" #include "bswap.h" +#include "ppce500_pci.h" #ifdef DEBUG_PCI #define pci_debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) @@ -256,7 +257,7 @@ static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num) int devno = pci_dev->devfn >> 3; int ret; - ret = (irq_num + devno) % 4; + ret = ppce500_pci_map_irq_slot(devno, irq_num); pci_debug("%s: devfn %x irq %d -> %d devno:%x\n", __func__, pci_dev->devfn, irq_num, ret, devno); diff --git a/hw/ppce500_pci.h b/hw/ppce500_pci.h new file mode 100644 index 0000000000..61f773ef30 --- /dev/null +++ b/hw/ppce500_pci.h @@ -0,0 +1,9 @@ +#ifndef PPCE500_PCI_H +#define PPCE500_PCI_H + +static inline int ppce500_pci_map_irq_slot(int devno, int irq_num) +{ + return (devno + irq_num) % 4; +} + +#endif From b162d02e9450201c656edce290f33994a6d2ad33 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 3 Dec 2012 16:42:14 +0000 Subject: [PATCH 1987/2270] target-ppc: Don't use hwaddr to represent hardware state The hwaddr type is somewhat vaguely defined as being able to contain bus addresses on the widest possible bus in the system. For that reason it's discouraged for representing specific pieces of persistent hardware state, which should instead use an explicit width type that matches the bits available in real hardware. In particular, because of the possibility that the size of hwaddr might change if different buses are added to the target in future, it's not suitable for use in vm state descriptions for savevm and migration. This patch purges such unwise uses of hwaddr from the ppc target code, which turns out to be just one. The ppcemb_tlb_t struct, used on a number of embedded ppc models to represent a TLB entry contains a hwaddr for the real address field. This patch changes it to be a fixed uint64_t which is suitable enough for all machine types which use this structure. Other uses of hwaddr in CPUPPCState turn out not to be problematic: htab_base and htab_mask are just used for the convenience of the TCG code; the underlying machine state is the SDR1 register, which is stored with a suitable type already. Likewise the mpic_cpu_base field is only used internally and does not represent fundamental hardware state which needs to be saved. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- target-ppc/cpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 5f1dc8b7d5..742d4f8ae3 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -355,7 +355,7 @@ struct ppc6xx_tlb_t { typedef struct ppcemb_tlb_t ppcemb_tlb_t; struct ppcemb_tlb_t { - hwaddr RPN; + uint64_t RPN; target_ulong EPN; target_ulong PID; target_ulong size; From a64ae610b978dfd8ccfb7f6c5d4cfe62d7542fbd Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 3 Dec 2012 16:42:16 +0000 Subject: [PATCH 1988/2270] pseries: Increase default NVRAM size If no image file for NVRAM is specified, the pseries machine currently creates a 16K non-persistent NVRAM by default. This basically works, but is not large enough for current firmware and guest kernels to create all the NVRAM partitions they would like to. Increasing the default size to 64K addresses this and stops the guest generating error messages. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_nvram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/spapr_nvram.c b/hw/spapr_nvram.c index 641de485f9..512bb8d5d1 100644 --- a/hw/spapr_nvram.c +++ b/hw/spapr_nvram.c @@ -37,7 +37,7 @@ typedef struct sPAPRNVRAM { } sPAPRNVRAM; #define MIN_NVRAM_SIZE 8192 -#define DEFAULT_NVRAM_SIZE 16384 +#define DEFAULT_NVRAM_SIZE 65536 #define MAX_NVRAM_SIZE (UINT16_MAX * 16) static void rtas_nvram_fetch(sPAPREnvironment *spapr, From f28558d3d37ad3bc4e35e8ac93f7bf81a0d5622c Mon Sep 17 00:00:00 2001 From: Will Auld Date: Mon, 26 Nov 2012 21:32:18 -0800 Subject: [PATCH 1989/2270] target-i386: Enabling IA32_TSC_ADJUST for QEMU KVM guest VMs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPUID.7.0.EBX[1]=1 indicates IA32_TSC_ADJUST MSR 0x3b is supported Basic design is to emulate the MSR by allowing reads and writes to the hypervisor vcpu specific locations to store the value of the emulated MSRs. In this way the IA32_TSC_ADJUST value will be included in all reads to the TSC MSR whether through rdmsr or rdtsc. As this is a new MSR that the guest may access and modify its value needs to be migrated along with the other MRSs. The changes here are specifically for recognizing when IA32_TSC_ADJUST is enabled in CPUID and code added for migrating its value. Signed-off-by: Will Auld Reviewed-by: Andreas Färber Signed-off-by: Marcelo Tosatti --- target-i386/cpu.h | 2 ++ target-i386/kvm.c | 14 ++++++++++++++ target-i386/machine.c | 21 +++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 386c4f6d98..477da33aa8 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -295,6 +295,7 @@ #define MSR_IA32_APICBASE_BSP (1<<8) #define MSR_IA32_APICBASE_ENABLE (1<<11) #define MSR_IA32_APICBASE_BASE (0xfffff<<12) +#define MSR_TSC_ADJUST 0x0000003b #define MSR_IA32_TSCDEADLINE 0x6e0 #define MSR_MTRRcap 0xfe @@ -774,6 +775,7 @@ typedef struct CPUX86State { uint64_t pv_eoi_en_msr; uint64_t tsc; + uint64_t tsc_adjust; uint64_t tsc_deadline; uint64_t mcg_status; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index f669281e13..ae6ce1ff3c 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -62,6 +62,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = { static bool has_msr_star; static bool has_msr_hsave_pa; +static bool has_msr_tsc_adjust; static bool has_msr_tsc_deadline; static bool has_msr_async_pf_en; static bool has_msr_pv_eoi_en; @@ -676,6 +677,10 @@ static int kvm_get_supported_msrs(KVMState *s) has_msr_hsave_pa = true; continue; } + if (kvm_msr_list->indices[i] == MSR_TSC_ADJUST) { + has_msr_tsc_adjust = true; + continue; + } if (kvm_msr_list->indices[i] == MSR_IA32_TSCDEADLINE) { has_msr_tsc_deadline = true; continue; @@ -1013,6 +1018,9 @@ static int kvm_put_msrs(CPUX86State *env, int level) if (has_msr_hsave_pa) { kvm_msr_entry_set(&msrs[n++], MSR_VM_HSAVE_PA, env->vm_hsave); } + if (has_msr_tsc_adjust) { + kvm_msr_entry_set(&msrs[n++], MSR_TSC_ADJUST, env->tsc_adjust); + } if (has_msr_tsc_deadline) { kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSCDEADLINE, env->tsc_deadline); } @@ -1273,6 +1281,9 @@ static int kvm_get_msrs(CPUX86State *env) if (has_msr_hsave_pa) { msrs[n++].index = MSR_VM_HSAVE_PA; } + if (has_msr_tsc_adjust) { + msrs[n++].index = MSR_TSC_ADJUST; + } if (has_msr_tsc_deadline) { msrs[n++].index = MSR_IA32_TSCDEADLINE; } @@ -1350,6 +1361,9 @@ static int kvm_get_msrs(CPUX86State *env) case MSR_IA32_TSC: env->tsc = msrs[i].data; break; + case MSR_TSC_ADJUST: + env->tsc_adjust = msrs[i].data; + break; case MSR_IA32_TSCDEADLINE: env->tsc_deadline = msrs[i].data; break; diff --git a/target-i386/machine.c b/target-i386/machine.c index 477150887b..4229ddeac8 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -328,6 +328,24 @@ static const VMStateDescription vmstate_fpop_ip_dp = { } }; +static bool tsc_adjust_needed(void *opaque) +{ + CPUX86State *env = opaque; + + return env->tsc_adjust != 0; +} + +static const VMStateDescription vmstate_msr_tsc_adjust = { + .name = "cpu/msr_tsc_adjust", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT64(tsc_adjust, CPUX86State), + VMSTATE_END_OF_LIST() + } +}; + static bool tscdeadline_needed(void *opaque) { CPUX86State *env = opaque; @@ -477,6 +495,9 @@ static const VMStateDescription vmstate_cpu = { } , { .vmsd = &vmstate_fpop_ip_dp, .needed = fpop_ip_dp_needed, + }, { + .vmsd = &vmstate_msr_tsc_adjust, + .needed = tsc_adjust_needed, }, { .vmsd = &vmstate_msr_tscdeadline, .needed = tscdeadline_needed, From fbddfc727bde692f009a269e8e628d8c152b537b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 14 Dec 2012 08:54:21 +0100 Subject: [PATCH 1990/2270] pixman: fix version check for PIXMAN_TYPE_BGRA Signed-off-by: Gerd Hoffmann Signed-off-by: Blue Swirl --- qemu-pixman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu-pixman.c b/qemu-pixman.c index e46e1804f6..79e175b8d0 100644 --- a/qemu-pixman.c +++ b/qemu-pixman.c @@ -21,7 +21,7 @@ int qemu_pixman_get_type(int rshift, int gshift, int bshift) if (rshift == 0) { type = PIXMAN_TYPE_ABGR; } else { -#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0, 21, 8) +#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0, 16, 0) type = PIXMAN_TYPE_BGRA; #endif } From cb1d40d7ccfc18ba1fcb9e064402d930349ee047 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 14 Dec 2012 08:54:22 +0100 Subject: [PATCH 1991/2270] Revert "pixman: require 0.18.4 or newer" This reverts commit 288fa40736e6eb63132d01aa6dc21ee831b796ae. The only reason old pixman versions didn't work was the missing PIXMAN_TYPE_BGRA, which is properly #ifdef'ed now. So we don't have to require a minimum pixman version. Signed-off-by: Gerd Hoffmann Signed-off-by: Blue Swirl --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 38b1cc6b35..ecdb33a58e 100755 --- a/configure +++ b/configure @@ -2127,7 +2127,7 @@ fi # pixman support probe if test "$pixman" = ""; then - if $pkg_config --atleast-version=0.18.4 pixman-1 > /dev/null 2>&1; then + if $pkg_config pixman-1 > /dev/null 2>&1; then pixman="system" else pixman="internal" @@ -2138,7 +2138,7 @@ if test "$pixman" = "system"; then pixman_libs=`$pkg_config --libs pixman-1 2>/dev/null` else if test ! -d ${source_path}/pixman/pixman; then - echo "ERROR: pixman not present (or older than 0.18.4). Your options:" + echo "ERROR: pixman not present. Your options:" echo " (1) Preferred: Install the pixman devel package (any recent" echo " distro should have packages as Xorg needs pixman too)." echo " (2) Fetch the pixman submodule, using:" From f27b2e1dfe79f993567652411d1ba16295b99719 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 14 Dec 2012 08:54:23 +0100 Subject: [PATCH 1992/2270] pixman: update internal copy to pixman-0.28.2 Some w64 fixes by Stefan Weil found their way into 0.28.2, so update the internal copy to that version to improve windows support. Signed-off-by: Gerd Hoffmann Signed-off-by: Blue Swirl --- pixman | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pixman b/pixman index 97336fad32..a5e5179b56 160000 --- a/pixman +++ b/pixman @@ -1 +1 @@ -Subproject commit 97336fad32acf802003855cd8bd6477fa49a12e3 +Subproject commit a5e5179b5624c99c812e9bf6e7b907e355a811e8 From bc210eb163b162ff2e94e5c8f4307715731257f8 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann <1087974@bugs.launchpad.net> Date: Fri, 14 Dec 2012 07:54:24 +0000 Subject: [PATCH 1993/2270] pixman: fix vnc tight png/jpeg support This patch adds an x argument to qemu_pixman_linebuf_fill so it can also be used to convert a partial scanline. Then fix tight + png/jpeg encoding by passing in the x+y offset, so the data is read from the correct screen location instead of the upper left corner. Cc: 1087974@bugs.launchpad.net Cc: qemu-stable@nongnu.org Reported-by: Tim Hardeneck Signed-off-by: Gerd Hoffmann Signed-off-by: Blue Swirl --- hw/vga.c | 2 +- qemu-pixman.c | 4 ++-- qemu-pixman.h | 2 +- ui/vnc-enc-tight.c | 4 ++-- ui/vnc.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/hw/vga.c b/hw/vga.c index 2b0200a164..c2661610e3 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -2413,7 +2413,7 @@ void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp) } linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width); for (y = 0; y < height; y++) { - qemu_pixman_linebuf_fill(linebuf, ds->image, width, y); + qemu_pixman_linebuf_fill(linebuf, ds->image, width, 0, y); clearerr(f); ret = fwrite(pixman_image_get_data(linebuf), 1, pixman_image_get_stride(linebuf), f); diff --git a/qemu-pixman.c b/qemu-pixman.c index 79e175b8d0..e7263fb2bf 100644 --- a/qemu-pixman.c +++ b/qemu-pixman.c @@ -52,10 +52,10 @@ pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format, } void qemu_pixman_linebuf_fill(pixman_image_t *linebuf, pixman_image_t *fb, - int width, int y) + int width, int x, int y) { pixman_image_composite(PIXMAN_OP_SRC, fb, NULL, linebuf, - 0, y, 0, 0, 0, 0, width, 1); + x, y, 0, 0, 0, 0, width, 1); } pixman_image_t *qemu_pixman_mirror_create(pixman_format_code_t format, diff --git a/qemu-pixman.h b/qemu-pixman.h index bee55eb7da..3c05c83a7c 100644 --- a/qemu-pixman.h +++ b/qemu-pixman.h @@ -31,7 +31,7 @@ pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf); pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format, int width); void qemu_pixman_linebuf_fill(pixman_image_t *linebuf, pixman_image_t *fb, - int width, int y); + int width, int x, int y); pixman_image_t *qemu_pixman_mirror_create(pixman_format_code_t format, pixman_image_t *image); void qemu_pixman_image_unref(pixman_image_t *image); diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c index 9ae4cabffc..62d0fde77f 100644 --- a/ui/vnc-enc-tight.c +++ b/ui/vnc-enc-tight.c @@ -1212,7 +1212,7 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality) buf = (uint8_t *)pixman_image_get_data(linebuf); row[0] = buf; for (dy = 0; dy < h; dy++) { - qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, dy); + qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, x, y + dy); jpeg_write_scanlines(&cinfo, row, 1); } qemu_pixman_image_unref(linebuf); @@ -1356,7 +1356,7 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h, if (color_type == PNG_COLOR_TYPE_PALETTE) { memcpy(buf, vs->tight.tight.buffer + (dy * w), w); } else { - qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, dy); + qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, x, y + dy); } png_write_row(png_ptr, buf); } diff --git a/ui/vnc.c b/ui/vnc.c index ba303626ad..04afcffc52 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -2569,7 +2569,7 @@ static int vnc_refresh_server_surface(VncDisplay *vd) uint8_t *server_ptr; if (vd->guest.format != VNC_SERVER_FB_FORMAT) { - qemu_pixman_linebuf_fill(tmpbuf, vd->guest.fb, width, y); + qemu_pixman_linebuf_fill(tmpbuf, vd->guest.fb, width, 0, y); guest_ptr = (uint8_t *)pixman_image_get_data(tmpbuf); } else { guest_ptr = guest_row; From 4b4496dbccc5f286f0ef411f0ff702d67cb95145 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 14 Dec 2012 08:54:25 +0100 Subject: [PATCH 1994/2270] console: clip update rectangle Signed-off-by: Gerd Hoffmann Signed-off-by: Blue Swirl --- console.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/console.h b/console.h index 50a0512f32..edb1950871 100644 --- a/console.h +++ b/console.h @@ -229,6 +229,16 @@ static inline void unregister_displaychangelistener(DisplayState *ds, static inline void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h) { struct DisplayChangeListener *dcl; + int width = pixman_image_get_width(s->surface->image); + int height = pixman_image_get_height(s->surface->image); + + x = MAX(x, 0); + y = MAX(y, 0); + x = MIN(x, width); + y = MIN(y, height); + w = MIN(w, width - x); + h = MIN(h, height - y); + QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->dpy_gfx_update) { dcl->dpy_gfx_update(s, x, y, w, h); From 659f807c0a700317a7a0fae7a6e6ebfe68bfbbc4 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 13 Dec 2012 04:13:41 +0400 Subject: [PATCH 1995/2270] target-xtensa: fix ITLB/DTLB page protection flags With MMU option xtensa architecture has two TLBs: ITLB and DTLB. ITLB is only used for code access, DTLB is only for data. However TLB entries in both TLBs have attribute field controlling write and exec access. These bits need to be properly masked off depending on TLB type before being used as tlb_set_page prot argument. Otherwise the following happens: (1) ITLB entry for some PFN gets invalidated (2) DTLB entry for the same PFN gets updated, attributes allow code execution (3) code at the page with that PFN is executed (possible due to step 2), entry for the TB is written into the jump cache (4) QEMU TLB entry for the PFN gets replaced with an entry for some other PFN (5) code in the TB from step 3 is executed (possible due to jump cache) and it accesses data, for which there's no DTLB entry, causing DTLB miss exception (6) re-translation of the TB from step 5 is attempted, but there's no QEMU TLB entry nor xtensa ITLB entry for that PFN, which causes ITLB miss exception at the TB start address (7) ITLB miss exception is handled by the guest, but execution is resumed from the beginning of the faulting TB (the point where ITLB miss occured), not from the point where DTLB miss occured, which is wrong. With that fix the above scenario causes ITLB miss exception (that used to be step 7) at step 3, right at the beginning of the TB. Signed-off-by: Max Filippov Cc: qemu-stable@nongnu.org Signed-off-by: Blue Swirl --- target-xtensa/helper.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c index 200fb43c28..bf05575eb5 100644 --- a/target-xtensa/helper.c +++ b/target-xtensa/helper.c @@ -522,7 +522,8 @@ static int get_physical_addr_mmu(CPUXtensaState *env, bool update_tlb, INST_FETCH_PRIVILEGE_CAUSE; } - *access = mmu_attr_to_access(entry->attr); + *access = mmu_attr_to_access(entry->attr) & + ~(dtlb ? PAGE_EXEC : PAGE_READ | PAGE_WRITE); if (!is_access_granted(*access, is_write)) { return dtlb ? (is_write ? From 44209fc4edfd92464eb0413acfd434b687be945a Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Dec 2012 17:25:06 +0000 Subject: [PATCH 1996/2270] exec: fix coding style Fix coding style in areas to be moved by later patches. Signed-off-by: Blue Swirl --- exec.c | 178 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 110 insertions(+), 68 deletions(-) diff --git a/exec.c b/exec.c index 0594b07057..2e56a8ab07 100644 --- a/exec.c +++ b/exec.c @@ -79,6 +79,7 @@ #define SMC_BITMAP_USE_THRESHOLD 10 +/* Code generation and translation blocks */ static TranslationBlock *tbs; static int code_gen_max_blocks; TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; @@ -207,21 +208,20 @@ static inline void map_exec(void *addr, long size) DWORD old_protect; VirtualProtect(addr, size, PAGE_EXECUTE_READWRITE, &old_protect); - } #else static inline void map_exec(void *addr, long size) { unsigned long start, end, page_size; - + page_size = getpagesize(); start = (unsigned long)addr; start &= ~(page_size - 1); - + end = (unsigned long)addr + size; end += page_size - 1; end &= ~(page_size - 1); - + mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC); } @@ -241,10 +241,12 @@ static void page_init(void) #else qemu_real_host_page_size = getpagesize(); #endif - if (qemu_host_page_size == 0) + if (qemu_host_page_size == 0) { qemu_host_page_size = qemu_real_host_page_size; - if (qemu_host_page_size < TARGET_PAGE_SIZE) + } + if (qemu_host_page_size < TARGET_PAGE_SIZE) { qemu_host_page_size = TARGET_PAGE_SIZE; + } qemu_host_page_mask = ~(qemu_host_page_size - 1); #if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY) @@ -291,7 +293,7 @@ static void page_init(void) unsigned long startaddr, endaddr; int n; - n = fscanf (f, "%lx-%lx %*[^\n]\n", &startaddr, &endaddr); + n = fscanf(f, "%lx-%lx %*[^\n]\n", &startaddr, &endaddr); if (n == 2 && h2g_valid(startaddr)) { startaddr = h2g(startaddr) & TARGET_PAGE_MASK; @@ -591,6 +593,7 @@ static inline void *alloc_code_gen_buffer(void) static inline void *alloc_code_gen_buffer(void) { void *buf = g_malloc(code_gen_buffer_size); + if (buf) { map_exec(buf, code_gen_buffer_size); } @@ -737,8 +740,9 @@ static TranslationBlock *tb_alloc(target_ulong pc) TranslationBlock *tb; if (nb_tbs >= code_gen_max_blocks || - (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size) + (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size) { return NULL; + } tb = &tbs[nb_tbs++]; tb->pc = pc; tb->cflags = 0; @@ -766,8 +770,7 @@ static inline void invalidate_page_bitmap(PageDesc *p) } /* Set to NULL all the 'first_tb' fields in all PageDescs. */ - -static void page_flush_tb_1 (int level, void **lp) +static void page_flush_tb_1(int level, void **lp) { int i; @@ -776,14 +779,16 @@ static void page_flush_tb_1 (int level, void **lp) } if (level == 0) { PageDesc *pd = *lp; + for (i = 0; i < L2_SIZE; ++i) { pd[i].first_tb = NULL; invalidate_page_bitmap(pd + i); } } else { void **pp = *lp; + for (i = 0; i < L2_SIZE; ++i) { - page_flush_tb_1 (level - 1, pp + i); + page_flush_tb_1(level - 1, pp + i); } } } @@ -791,6 +796,7 @@ static void page_flush_tb_1 (int level, void **lp) static void page_flush_tb(void) { int i; + for (i = 0; i < V_L1_SIZE; i++) { page_flush_tb_1(V_L1_SHIFT / L2_BITS - 1, l1_map + i); } @@ -801,22 +807,24 @@ static void page_flush_tb(void) void tb_flush(CPUArchState *env1) { CPUArchState *env; + #if defined(DEBUG_FLUSH) printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n", (unsigned long)(code_gen_ptr - code_gen_buffer), nb_tbs, nb_tbs > 0 ? ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0); #endif - if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size) + if ((unsigned long)(code_gen_ptr - code_gen_buffer) + > code_gen_buffer_size) { cpu_abort(env1, "Internal error: code buffer overflow\n"); - + } nb_tbs = 0; - for(env = first_cpu; env != NULL; env = env->next_cpu) { - memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *)); + for (env = first_cpu; env != NULL; env = env->next_cpu) { + memset(env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof(void *)); } - memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *)); + memset(tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof(void *)); page_flush_tb(); code_gen_ptr = code_gen_buffer; @@ -831,9 +839,10 @@ static void tb_invalidate_check(target_ulong address) { TranslationBlock *tb; int i; + address &= TARGET_PAGE_MASK; - for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) { - for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) { + for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) { + for (tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) { if (!(address + TARGET_PAGE_SIZE <= tb->pc || address >= tb->pc + tb->size)) { printf("ERROR invalidate: address=" TARGET_FMT_lx @@ -850,8 +859,8 @@ static void tb_page_check(void) TranslationBlock *tb; int i, flags1, flags2; - for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) { - for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) { + for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) { + for (tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) { flags1 = page_get_flags(tb->pc); flags2 = page_get_flags(tb->pc + tb->size - 1); if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) { @@ -864,12 +873,14 @@ static void tb_page_check(void) #endif + /* invalidate one TB */ static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb, int next_offset) { TranslationBlock *tb1; - for(;;) { + + for (;;) { tb1 = *ptb; if (tb1 == tb) { *ptb = *(TranslationBlock **)((char *)tb1 + next_offset); @@ -884,7 +895,7 @@ static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb) TranslationBlock *tb1; unsigned int n1; - for(;;) { + for (;;) { tb1 = *ptb; n1 = (uintptr_t)tb1 & 3; tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); @@ -905,12 +916,13 @@ static inline void tb_jmp_remove(TranslationBlock *tb, int n) tb1 = *ptb; if (tb1) { /* find tb(n) in circular list */ - for(;;) { + for (;;) { tb1 = *ptb; n1 = (uintptr_t)tb1 & 3; tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); - if (n1 == n && tb1 == tb) + if (n1 == n && tb1 == tb) { break; + } if (n1 == 2) { ptb = &tb1->jmp_first; } else { @@ -961,9 +973,10 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) /* remove the TB from the hash list */ h = tb_jmp_cache_hash_func(tb->pc); - for(env = first_cpu; env != NULL; env = env->next_cpu) { - if (env->tb_jmp_cache[h] == tb) + for (env = first_cpu; env != NULL; env = env->next_cpu) { + if (env->tb_jmp_cache[h] == tb) { env->tb_jmp_cache[h] = NULL; + } } /* suppress this TB from the two jump lists */ @@ -972,10 +985,11 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) /* suppress any remaining jumps to this TB */ tb1 = tb->jmp_first; - for(;;) { + for (;;) { n1 = (uintptr_t)tb1 & 3; - if (n1 == 2) + if (n1 == 2) { break; + } tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); tb2 = tb1->jmp_next[n1]; tb_reset_jump(tb1, n1); @@ -1031,8 +1045,9 @@ static void build_page_bitmap(PageDesc *p) it is not a problem */ tb_start = tb->pc & ~TARGET_PAGE_MASK; tb_end = tb_start + tb->size; - if (tb_end > TARGET_PAGE_SIZE) + if (tb_end > TARGET_PAGE_SIZE) { tb_end = TARGET_PAGE_SIZE; + } } else { tb_start = 0; tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK); @@ -1123,8 +1138,9 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, #endif /* TARGET_HAS_PRECISE_SMC */ p = page_find(start >> TARGET_PAGE_BITS); - if (!p) + if (!p) { return; + } if (!p->code_bitmap && ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD && is_cpu_write_access) { @@ -1133,7 +1149,8 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, } /* we remove all the TBs in the range [start, end[ */ - /* XXX: see if in some cases it could be faster to invalidate all the code */ + /* XXX: see if in some cases it could be faster to invalidate all + the code */ tb = p->first_tb; while (tb != NULL) { n = (uintptr_t)tb & 3; @@ -1183,8 +1200,9 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, tb_phys_invalidate(tb, -1); if (env) { env->current_tb = saved_tb; - if (env->interrupt_request && env->current_tb) + if (env->interrupt_request && env->current_tb) { cpu_interrupt(env, env->interrupt_request); + } } } tb = tb_next; @@ -1215,6 +1233,7 @@ static inline void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len) { PageDesc *p; int offset, b; + #if 0 if (1) { qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n", @@ -1225,13 +1244,15 @@ static inline void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len) } #endif p = page_find(start >> TARGET_PAGE_BITS); - if (!p) + if (!p) { return; + } if (p->code_bitmap) { offset = start & ~TARGET_PAGE_MASK; b = p->code_bitmap[offset >> 3] >> (offset & 7); - if (b & ((1 << len) - 1)) + if (b & ((1 << len) - 1)) { goto do_invalidate; + } } else { do_invalidate: tb_invalidate_phys_page_range(start, start + len, 1); @@ -1256,8 +1277,9 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr, addr &= TARGET_PAGE_MASK; p = page_find(addr >> TARGET_PAGE_BITS); - if (!p) + if (!p) { return; + } tb = p->first_tb; #ifdef TARGET_HAS_PRECISE_SMC if (tb && pc != 0) { @@ -1329,12 +1351,13 @@ static inline void tb_alloc_page(TranslationBlock *tb, page fault + mprotect overhead) */ page_addr &= qemu_host_page_mask; prot = 0; - for(addr = page_addr; addr < page_addr + qemu_host_page_size; + for (addr = page_addr; addr < page_addr + qemu_host_page_size; addr += TARGET_PAGE_SIZE) { - p2 = page_find (addr >> TARGET_PAGE_BITS); - if (!p2) + p2 = page_find(addr >> TARGET_PAGE_BITS); + if (!p2) { continue; + } prot |= p2->flags; p2->flags &= ~PAGE_WRITE; } @@ -1376,20 +1399,23 @@ static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, /* add in the page list */ tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK); - if (phys_page2 != -1) + if (phys_page2 != -1) { tb_alloc_page(tb, 1, phys_page2); - else + } else { tb->page_addr[1] = -1; + } tb->jmp_first = (TranslationBlock *)((uintptr_t)tb | 2); tb->jmp_next[0] = NULL; tb->jmp_next[1] = NULL; /* init original jump addresses */ - if (tb->tb_next_offset[0] != 0xffff) + if (tb->tb_next_offset[0] != 0xffff) { tb_reset_jump(tb, 0); - if (tb->tb_next_offset[1] != 0xffff) + } + if (tb->tb_next_offset[1] != 0xffff) { tb_reset_jump(tb, 1); + } #ifdef DEBUG_TB_CHECK tb_page_check(); @@ -1416,8 +1442,9 @@ TranslationBlock *tb_find_pc(uintptr_t tc_ptr) uintptr_t v; TranslationBlock *tb; - if (nb_tbs <= 0) + if (nb_tbs <= 0) { return NULL; + } if (tc_ptr < (uintptr_t)code_gen_buffer || tc_ptr >= (uintptr_t)code_gen_ptr) { return NULL; @@ -1429,9 +1456,9 @@ TranslationBlock *tb_find_pc(uintptr_t tc_ptr) m = (m_min + m_max) >> 1; tb = &tbs[m]; v = (uintptr_t)tb->tc_ptr; - if (v == tc_ptr) + if (v == tc_ptr) { return tb; - else if (tc_ptr < v) { + } else if (tc_ptr < v) { m_max = m - 1; } else { m_min = m + 1; @@ -1450,11 +1477,12 @@ static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n) tb1 = tb->jmp_next[n]; if (tb1 != NULL) { /* find head of list */ - for(;;) { + for (;;) { n1 = (uintptr_t)tb1 & 3; tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); - if (n1 == 2) + if (n1 == 2) { break; + } tb1 = tb1->jmp_next[n1]; } /* we are now sure now that tb jumps to tb1 */ @@ -1462,12 +1490,13 @@ static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n) /* remove tb from the jmp_first list */ ptb = &tb_next->jmp_first; - for(;;) { + for (;;) { tb1 = *ptb; n1 = (uintptr_t)tb1 & 3; tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); - if (n1 == n && tb1 == tb) + if (n1 == n && tb1 == tb) { break; + } ptb = &tb1->jmp_next[n1]; } *ptb = tb->jmp_next[n]; @@ -1499,7 +1528,8 @@ void tb_invalidate_phys_addr(hwaddr addr) ram_addr_t ram_addr; MemoryRegionSection *section; - section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); + 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))) { return; @@ -1939,9 +1969,7 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env, * Walks guest process memory "regions" one by one * and calls callback function 'fn' for each region. */ - -struct walk_memory_regions_data -{ +struct walk_memory_regions_data { walk_memory_regions_fn fn; void *priv; uintptr_t start; @@ -1976,6 +2004,7 @@ static int walk_memory_regions_1(struct walk_memory_regions_data *data, if (level == 0) { PageDesc *pd = *lp; + for (i = 0; i < L2_SIZE; ++i) { int prot = pd[i].flags; @@ -1989,6 +2018,7 @@ static int walk_memory_regions_1(struct walk_memory_regions_data *data, } } else { void **pp = *lp; + for (i = 0; i < L2_SIZE; ++i) { pa = base | ((abi_ulong)i << (TARGET_PAGE_BITS + L2_BITS * level)); @@ -2015,6 +2045,7 @@ int walk_memory_regions(void *priv, walk_memory_regions_fn fn) for (i = 0; i < V_L1_SIZE; i++) { int rc = walk_memory_regions_1(&data, (abi_ulong)i << V_L1_SHIFT, V_L1_SHIFT / L2_BITS - 1, l1_map + i); + if (rc != 0) { return rc; } @@ -2035,7 +2066,7 @@ static int dump_region(void *priv, abi_ulong start, ((prot & PAGE_WRITE) ? 'w' : '-'), ((prot & PAGE_EXEC) ? 'x' : '-')); - return (0); + return 0; } /* dump memory mappings */ @@ -2051,8 +2082,9 @@ int page_get_flags(target_ulong address) PageDesc *p; p = page_find(address >> TARGET_PAGE_BITS); - if (!p) + if (!p) { return 0; + } return p->flags; } @@ -2115,28 +2147,34 @@ int page_check_range(target_ulong start, target_ulong len, int flags) return -1; } - end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */ + /* must do before we loose bits in the next step */ + end = TARGET_PAGE_ALIGN(start + len); start = start & TARGET_PAGE_MASK; for (addr = start, len = end - start; len != 0; len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) { p = page_find(addr >> TARGET_PAGE_BITS); - if( !p ) + if (!p) { return -1; - if( !(p->flags & PAGE_VALID) ) + } + if (!(p->flags & PAGE_VALID)) { return -1; + } - if ((flags & PAGE_READ) && !(p->flags & PAGE_READ)) + if ((flags & PAGE_READ) && !(p->flags & PAGE_READ)) { return -1; + } if (flags & PAGE_WRITE) { - if (!(p->flags & PAGE_WRITE_ORG)) + if (!(p->flags & PAGE_WRITE_ORG)) { return -1; + } /* unprotect the page if it was put read-only because it contains translated code */ if (!(p->flags & PAGE_WRITE)) { - if (!page_unprotect(addr, 0, NULL)) + if (!page_unprotect(addr, 0, NULL)) { return -1; + } } return 0; } @@ -4101,7 +4139,7 @@ void cpu_io_recompile(CPUArchState *env, uintptr_t retaddr) tb = tb_find_pc(retaddr); if (!tb) { - cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p", + cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p", (void *)retaddr); } n = env->icount_decr.u16.low + tb->icount; @@ -4130,8 +4168,9 @@ void cpu_io_recompile(CPUArchState *env, uintptr_t retaddr) } #endif /* This should never happen. */ - if (n > CF_COUNT_MASK) + if (n > CF_COUNT_MASK) { cpu_abort(env, "TB too big during recompile"); + } cflags = n | CF_LAST_IO; pc = tb->pc; @@ -4162,13 +4201,15 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) cross_page = 0; direct_jmp_count = 0; direct_jmp2_count = 0; - for(i = 0; i < nb_tbs; i++) { + for (i = 0; i < nb_tbs; i++) { tb = &tbs[i]; target_code_size += tb->size; - if (tb->size > max_target_code_size) + if (tb->size > max_target_code_size) { max_target_code_size = tb->size; - if (tb->page_addr[1] != -1) + } + if (tb->page_addr[1] != -1) { cross_page++; + } if (tb->tb_next_offset[0] != 0xffff) { direct_jmp_count++; if (tb->tb_next_offset[1] != 0xffff) { @@ -4180,14 +4221,15 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) cpu_fprintf(f, "Translation buffer state:\n"); cpu_fprintf(f, "gen code size %td/%zd\n", code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size); - cpu_fprintf(f, "TB count %d/%d\n", + cpu_fprintf(f, "TB count %d/%d\n", nb_tbs, code_gen_max_blocks); cpu_fprintf(f, "TB avg target size %d max=%d bytes\n", nb_tbs ? target_code_size / nb_tbs : 0, max_target_code_size); cpu_fprintf(f, "TB avg host size %td bytes (expansion ratio: %0.1f)\n", nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0, - target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0); + target_code_size ? (double) (code_gen_ptr - code_gen_buffer) + / target_code_size : 0); cpu_fprintf(f, "cross page TB count %d (%d%%)\n", cross_page, nb_tbs ? (cross_page * 100) / nb_tbs : 0); From 5a3165263ae6782a7fe712a0a0c29c17468b9b68 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Dec 2012 21:28:09 +0000 Subject: [PATCH 1997/2270] exec: extract TB watchpoint check Will be moved by the next patch. Signed-off-by: Blue Swirl --- exec.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/exec.c b/exec.c index 2e56a8ab07..a1f617d0e1 100644 --- a/exec.c +++ b/exec.c @@ -2987,12 +2987,24 @@ static const MemoryRegionOps notdirty_mem_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; +static void tb_check_watchpoint(CPUArchState *env) +{ + TranslationBlock *tb; + + tb = tb_find_pc(env->mem_io_pc); + if (!tb) { + cpu_abort(env, "check_watchpoint: could not find TB for pc=%p", + (void *)env->mem_io_pc); + } + cpu_restore_state(tb, env, env->mem_io_pc); + tb_phys_invalidate(tb, -1); +} + /* Generate a debug exception if a watchpoint has been hit. */ static void check_watchpoint(int offset, int len_mask, int flags) { CPUArchState *env = cpu_single_env; target_ulong pc, cs_base; - TranslationBlock *tb; target_ulong vaddr; CPUWatchpoint *wp; int cpu_flags; @@ -3011,13 +3023,7 @@ static void check_watchpoint(int offset, int len_mask, int flags) wp->flags |= BP_WATCHPOINT_HIT; if (!env->watchpoint_hit) { env->watchpoint_hit = wp; - tb = tb_find_pc(env->mem_io_pc); - if (!tb) { - cpu_abort(env, "check_watchpoint: could not find TB for " - "pc=%p", (void *)env->mem_io_pc); - } - cpu_restore_state(tb, env, env->mem_io_pc); - tb_phys_invalidate(tb, -1); + tb_check_watchpoint(env); if (wp->flags & BP_STOP_BEFORE_ACCESS) { env->exception_index = EXCP_DEBUG; cpu_loop_exit(env); From 5b6dd8683dc30e8e0970db3dd9176732dc819410 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 2 Dec 2012 16:04:43 +0000 Subject: [PATCH 1998/2270] exec: move TB handling to translate-all.c Signed-off-by: Blue Swirl --- exec.c | 1713 +--------------------------------------------- translate-all.c | 1719 +++++++++++++++++++++++++++++++++++++++++++++++ translate-all.h | 34 + 3 files changed, 1755 insertions(+), 1711 deletions(-) create mode 100644 translate-all.h diff --git a/exec.c b/exec.c index a1f617d0e1..4c1246a9f9 100644 --- a/exec.c +++ b/exec.c @@ -1,5 +1,5 @@ /* - * virtual page mapping and translated block handling + * Virtual page mapping * * Copyright (c) 2003 Fabrice Bellard * @@ -38,62 +38,19 @@ #include "exec-memory.h" #if defined(CONFIG_USER_ONLY) #include -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -#include -#if __FreeBSD_version >= 700104 -#define HAVE_KINFO_GETVMMAP -#define sigqueue sigqueue_freebsd /* avoid redefinition */ -#include -#include -#include -#define _KERNEL -#include -#undef _KERNEL -#undef sigqueue -#include -#endif -#endif #else /* !CONFIG_USER_ONLY */ #include "xen-mapcache.h" #include "trace.h" #endif #include "cputlb.h" +#include "translate-all.h" #include "memory-internal.h" -//#define DEBUG_TB_INVALIDATE -//#define DEBUG_FLUSH //#define DEBUG_UNASSIGNED - -/* make various TB consistency checks */ -//#define DEBUG_TB_CHECK - -//#define DEBUG_IOPORT //#define DEBUG_SUBPAGE -#if !defined(CONFIG_USER_ONLY) -/* TB consistency checks only implemented for usermode emulation. */ -#undef DEBUG_TB_CHECK -#endif - -#define SMC_BITMAP_USE_THRESHOLD 10 - -/* Code generation and translation blocks */ -static TranslationBlock *tbs; -static int code_gen_max_blocks; -TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; -static int nb_tbs; -/* any access to the tbs or the page table must use this lock */ -spinlock_t tb_lock = SPIN_LOCK_UNLOCKED; - -uint8_t *code_gen_prologue; -static uint8_t *code_gen_buffer; -static size_t code_gen_buffer_size; -/* threshold to flush the translated code buffer */ -static size_t code_gen_buffer_max_size; -static uint8_t *code_gen_ptr; - #if !defined(CONFIG_USER_ONLY) int phys_ram_fd; static int in_migration; @@ -121,59 +78,6 @@ DEFINE_TLS(CPUArchState *,cpu_single_env); 2 = Adaptive rate instruction counting. */ int use_icount = 0; -typedef struct PageDesc { - /* list of TBs intersecting this ram page */ - TranslationBlock *first_tb; - /* in order to optimize self modifying code, we count the number - of lookups we do to a given page to use a bitmap */ - unsigned int code_write_count; - uint8_t *code_bitmap; -#if defined(CONFIG_USER_ONLY) - unsigned long flags; -#endif -} PageDesc; - -/* In system mode we want L1_MAP to be based on ram offsets, - while in user mode we want it to be based on virtual addresses. */ -#if !defined(CONFIG_USER_ONLY) -#if HOST_LONG_BITS < TARGET_PHYS_ADDR_SPACE_BITS -# define L1_MAP_ADDR_SPACE_BITS HOST_LONG_BITS -#else -# define L1_MAP_ADDR_SPACE_BITS TARGET_PHYS_ADDR_SPACE_BITS -#endif -#else -# define L1_MAP_ADDR_SPACE_BITS TARGET_VIRT_ADDR_SPACE_BITS -#endif - -/* Size of the L2 (and L3, etc) page tables. */ -#define L2_BITS 10 -#define L2_SIZE (1 << L2_BITS) - -#define P_L2_LEVELS \ - (((TARGET_PHYS_ADDR_SPACE_BITS - TARGET_PAGE_BITS - 1) / L2_BITS) + 1) - -/* The bits remaining after N lower levels of page tables. */ -#define V_L1_BITS_REM \ - ((L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS) % L2_BITS) - -#if V_L1_BITS_REM < 4 -#define V_L1_BITS (V_L1_BITS_REM + L2_BITS) -#else -#define V_L1_BITS V_L1_BITS_REM -#endif - -#define V_L1_SIZE ((target_ulong)1 << V_L1_BITS) - -#define V_L1_SHIFT (L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS - V_L1_BITS) - -uintptr_t qemu_real_host_page_size; -uintptr_t qemu_host_page_size; -uintptr_t qemu_host_page_mask; - -/* This is a multi-level map on the virtual address space. - The bottom level has pointers to PageDesc. */ -static void *l1_map[V_L1_SIZE]; - #if !defined(CONFIG_USER_ONLY) static MemoryRegionSection *phys_sections; @@ -195,180 +99,6 @@ static void *qemu_safe_ram_ptr(ram_addr_t addr); static MemoryRegion io_mem_watch; #endif -static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, - tb_page_addr_t phys_page2); - -/* statistics */ -static int tb_flush_count; -static int tb_phys_invalidate_count; - -#ifdef _WIN32 -static inline void map_exec(void *addr, long size) -{ - DWORD old_protect; - VirtualProtect(addr, size, - PAGE_EXECUTE_READWRITE, &old_protect); -} -#else -static inline void map_exec(void *addr, long size) -{ - unsigned long start, end, page_size; - - page_size = getpagesize(); - start = (unsigned long)addr; - start &= ~(page_size - 1); - - end = (unsigned long)addr + size; - end += page_size - 1; - end &= ~(page_size - 1); - - mprotect((void *)start, end - start, - PROT_READ | PROT_WRITE | PROT_EXEC); -} -#endif - -static void page_init(void) -{ - /* NOTE: we can always suppose that qemu_host_page_size >= - TARGET_PAGE_SIZE */ -#ifdef _WIN32 - { - SYSTEM_INFO system_info; - - GetSystemInfo(&system_info); - qemu_real_host_page_size = system_info.dwPageSize; - } -#else - qemu_real_host_page_size = getpagesize(); -#endif - if (qemu_host_page_size == 0) { - qemu_host_page_size = qemu_real_host_page_size; - } - if (qemu_host_page_size < TARGET_PAGE_SIZE) { - qemu_host_page_size = TARGET_PAGE_SIZE; - } - qemu_host_page_mask = ~(qemu_host_page_size - 1); - -#if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY) - { -#ifdef HAVE_KINFO_GETVMMAP - struct kinfo_vmentry *freep; - int i, cnt; - - freep = kinfo_getvmmap(getpid(), &cnt); - if (freep) { - mmap_lock(); - for (i = 0; i < cnt; i++) { - unsigned long startaddr, endaddr; - - startaddr = freep[i].kve_start; - endaddr = freep[i].kve_end; - if (h2g_valid(startaddr)) { - startaddr = h2g(startaddr) & TARGET_PAGE_MASK; - - if (h2g_valid(endaddr)) { - endaddr = h2g(endaddr); - page_set_flags(startaddr, endaddr, PAGE_RESERVED); - } else { -#if TARGET_ABI_BITS <= L1_MAP_ADDR_SPACE_BITS - endaddr = ~0ul; - page_set_flags(startaddr, endaddr, PAGE_RESERVED); -#endif - } - } - } - free(freep); - mmap_unlock(); - } -#else - FILE *f; - - last_brk = (unsigned long)sbrk(0); - - f = fopen("/compat/linux/proc/self/maps", "r"); - if (f) { - mmap_lock(); - - do { - unsigned long startaddr, endaddr; - int n; - - n = fscanf(f, "%lx-%lx %*[^\n]\n", &startaddr, &endaddr); - - if (n == 2 && h2g_valid(startaddr)) { - startaddr = h2g(startaddr) & TARGET_PAGE_MASK; - - if (h2g_valid(endaddr)) { - endaddr = h2g(endaddr); - } else { - endaddr = ~0ul; - } - page_set_flags(startaddr, endaddr, PAGE_RESERVED); - } - } while (!feof(f)); - - fclose(f); - mmap_unlock(); - } -#endif - } -#endif -} - -static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc) -{ - PageDesc *pd; - void **lp; - int i; - -#if defined(CONFIG_USER_ONLY) - /* We can't use g_malloc because it may recurse into a locked mutex. */ -# define ALLOC(P, SIZE) \ - do { \ - P = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, \ - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \ - } while (0) -#else -# define ALLOC(P, SIZE) \ - do { P = g_malloc0(SIZE); } while (0) -#endif - - /* Level 1. Always allocated. */ - lp = l1_map + ((index >> V_L1_SHIFT) & (V_L1_SIZE - 1)); - - /* Level 2..N-1. */ - for (i = V_L1_SHIFT / L2_BITS - 1; i > 0; i--) { - void **p = *lp; - - if (p == NULL) { - if (!alloc) { - return NULL; - } - ALLOC(p, sizeof(void *) * L2_SIZE); - *lp = p; - } - - lp = p + ((index >> (i * L2_BITS)) & (L2_SIZE - 1)); - } - - pd = *lp; - if (pd == NULL) { - if (!alloc) { - return NULL; - } - ALLOC(pd, sizeof(PageDesc) * L2_SIZE); - *lp = pd; - } - -#undef ALLOC - - return pd + (index & (L2_SIZE - 1)); -} - -static inline PageDesc *page_find(tb_page_addr_t index) -{ - return page_find_alloc(index, 0); -} #if !defined(CONFIG_USER_ONLY) @@ -476,178 +206,8 @@ bool memory_region_is_unassigned(MemoryRegion *mr) && mr != &io_mem_notdirty && !mr->rom_device && mr != &io_mem_watch; } - -#define mmap_lock() do { } while(0) -#define mmap_unlock() do { } while(0) #endif -#if defined(CONFIG_USER_ONLY) -/* Currently it is not recommended to allocate big chunks of data in - user mode. It will change when a dedicated libc will be used. */ -/* ??? 64-bit hosts ought to have no problem mmaping data outside the - region in which the guest needs to run. Revisit this. */ -#define USE_STATIC_CODE_GEN_BUFFER -#endif - -/* ??? Should configure for this, not list operating systems here. */ -#if (defined(__linux__) \ - || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \ - || defined(__DragonFly__) || defined(__OpenBSD__) \ - || defined(__NetBSD__)) -# define USE_MMAP -#endif - -/* Minimum size of the code gen buffer. This number is randomly chosen, - but not so small that we can't have a fair number of TB's live. */ -#define MIN_CODE_GEN_BUFFER_SIZE (1024u * 1024) - -/* Maximum size of the code gen buffer we'd like to use. Unless otherwise - indicated, this is constrained by the range of direct branches on the - host cpu, as used by the TCG implementation of goto_tb. */ -#if defined(__x86_64__) -# define MAX_CODE_GEN_BUFFER_SIZE (2ul * 1024 * 1024 * 1024) -#elif defined(__sparc__) -# define MAX_CODE_GEN_BUFFER_SIZE (2ul * 1024 * 1024 * 1024) -#elif defined(__arm__) -# define MAX_CODE_GEN_BUFFER_SIZE (16u * 1024 * 1024) -#elif defined(__s390x__) - /* We have a +- 4GB range on the branches; leave some slop. */ -# define MAX_CODE_GEN_BUFFER_SIZE (3ul * 1024 * 1024 * 1024) -#else -# define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1) -#endif - -#define DEFAULT_CODE_GEN_BUFFER_SIZE_1 (32u * 1024 * 1024) - -#define DEFAULT_CODE_GEN_BUFFER_SIZE \ - (DEFAULT_CODE_GEN_BUFFER_SIZE_1 < MAX_CODE_GEN_BUFFER_SIZE \ - ? DEFAULT_CODE_GEN_BUFFER_SIZE_1 : MAX_CODE_GEN_BUFFER_SIZE) - -static inline size_t size_code_gen_buffer(size_t tb_size) -{ - /* Size the buffer. */ - if (tb_size == 0) { -#ifdef USE_STATIC_CODE_GEN_BUFFER - tb_size = DEFAULT_CODE_GEN_BUFFER_SIZE; -#else - /* ??? Needs adjustments. */ - /* ??? If we relax the requirement that CONFIG_USER_ONLY use the - static buffer, we could size this on RESERVED_VA, on the text - segment size of the executable, or continue to use the default. */ - tb_size = (unsigned long)(ram_size / 4); -#endif - } - if (tb_size < MIN_CODE_GEN_BUFFER_SIZE) { - tb_size = MIN_CODE_GEN_BUFFER_SIZE; - } - if (tb_size > MAX_CODE_GEN_BUFFER_SIZE) { - tb_size = MAX_CODE_GEN_BUFFER_SIZE; - } - code_gen_buffer_size = tb_size; - return tb_size; -} - -#ifdef USE_STATIC_CODE_GEN_BUFFER -static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE] - __attribute__((aligned(CODE_GEN_ALIGN))); - -static inline void *alloc_code_gen_buffer(void) -{ - map_exec(static_code_gen_buffer, code_gen_buffer_size); - return static_code_gen_buffer; -} -#elif defined(USE_MMAP) -static inline void *alloc_code_gen_buffer(void) -{ - int flags = MAP_PRIVATE | MAP_ANONYMOUS; - uintptr_t start = 0; - void *buf; - - /* Constrain the position of the buffer based on the host cpu. - Note that these addresses are chosen in concert with the - addresses assigned in the relevant linker script file. */ -# if defined(__PIE__) || defined(__PIC__) - /* Don't bother setting a preferred location if we're building - a position-independent executable. We're more likely to get - an address near the main executable if we let the kernel - choose the address. */ -# elif defined(__x86_64__) && defined(MAP_32BIT) - /* Force the memory down into low memory with the executable. - Leave the choice of exact location with the kernel. */ - flags |= MAP_32BIT; - /* Cannot expect to map more than 800MB in low memory. */ - if (code_gen_buffer_size > 800u * 1024 * 1024) { - code_gen_buffer_size = 800u * 1024 * 1024; - } -# elif defined(__sparc__) - start = 0x40000000ul; -# elif defined(__s390x__) - start = 0x90000000ul; -# endif - - buf = mmap((void *)start, code_gen_buffer_size, - PROT_WRITE | PROT_READ | PROT_EXEC, flags, -1, 0); - return buf == MAP_FAILED ? NULL : buf; -} -#else -static inline void *alloc_code_gen_buffer(void) -{ - void *buf = g_malloc(code_gen_buffer_size); - - if (buf) { - map_exec(buf, code_gen_buffer_size); - } - return buf; -} -#endif /* USE_STATIC_CODE_GEN_BUFFER, USE_MMAP */ - -static inline void code_gen_alloc(size_t tb_size) -{ - code_gen_buffer_size = size_code_gen_buffer(tb_size); - code_gen_buffer = alloc_code_gen_buffer(); - if (code_gen_buffer == NULL) { - fprintf(stderr, "Could not allocate dynamic translator buffer\n"); - exit(1); - } - - qemu_madvise(code_gen_buffer, code_gen_buffer_size, QEMU_MADV_HUGEPAGE); - - /* Steal room for the prologue at the end of the buffer. This ensures - (via the MAX_CODE_GEN_BUFFER_SIZE limits above) that direct branches - from TB's to the prologue are going to be in range. It also means - that we don't need to mark (additional) portions of the data segment - as executable. */ - code_gen_prologue = code_gen_buffer + code_gen_buffer_size - 1024; - code_gen_buffer_size -= 1024; - - code_gen_buffer_max_size = code_gen_buffer_size - - (TCG_MAX_OP_SIZE * OPC_BUF_SIZE); - code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE; - tbs = g_malloc(code_gen_max_blocks * sizeof(TranslationBlock)); -} - -/* Must be called before using the QEMU cpus. 'tb_size' is the size - (in bytes) allocated to the translation buffer. Zero means default - size. */ -void tcg_exec_init(unsigned long tb_size) -{ - cpu_gen_init(); - code_gen_alloc(tb_size); - code_gen_ptr = code_gen_buffer; - tcg_register_jit(code_gen_buffer, code_gen_buffer_size); - page_init(); -#if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE) - /* There's no guest base to take into account, so go ahead and - initialize the prologue now. */ - tcg_prologue_init(&tcg_ctx); -#endif -} - -bool tcg_enabled(void) -{ - return code_gen_buffer != NULL; -} - void cpu_exec_init_all(void) { #if !defined(CONFIG_USER_ONLY) @@ -733,789 +293,6 @@ void cpu_exec_init(CPUArchState *env) #endif } -/* Allocate a new translation block. Flush the translation buffer if - too many translation blocks or too much generated code. */ -static TranslationBlock *tb_alloc(target_ulong pc) -{ - TranslationBlock *tb; - - if (nb_tbs >= code_gen_max_blocks || - (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size) { - return NULL; - } - tb = &tbs[nb_tbs++]; - tb->pc = pc; - tb->cflags = 0; - return tb; -} - -void tb_free(TranslationBlock *tb) -{ - /* In practice this is mostly used for single use temporary TB - Ignore the hard cases and just back up if this TB happens to - be the last one generated. */ - if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) { - code_gen_ptr = tb->tc_ptr; - nb_tbs--; - } -} - -static inline void invalidate_page_bitmap(PageDesc *p) -{ - if (p->code_bitmap) { - g_free(p->code_bitmap); - p->code_bitmap = NULL; - } - p->code_write_count = 0; -} - -/* Set to NULL all the 'first_tb' fields in all PageDescs. */ -static void page_flush_tb_1(int level, void **lp) -{ - int i; - - if (*lp == NULL) { - return; - } - if (level == 0) { - PageDesc *pd = *lp; - - for (i = 0; i < L2_SIZE; ++i) { - pd[i].first_tb = NULL; - invalidate_page_bitmap(pd + i); - } - } else { - void **pp = *lp; - - for (i = 0; i < L2_SIZE; ++i) { - page_flush_tb_1(level - 1, pp + i); - } - } -} - -static void page_flush_tb(void) -{ - int i; - - for (i = 0; i < V_L1_SIZE; i++) { - page_flush_tb_1(V_L1_SHIFT / L2_BITS - 1, l1_map + i); - } -} - -/* flush all the translation blocks */ -/* XXX: tb_flush is currently not thread safe */ -void tb_flush(CPUArchState *env1) -{ - CPUArchState *env; - -#if defined(DEBUG_FLUSH) - printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n", - (unsigned long)(code_gen_ptr - code_gen_buffer), - nb_tbs, nb_tbs > 0 ? - ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0); -#endif - if ((unsigned long)(code_gen_ptr - code_gen_buffer) - > code_gen_buffer_size) { - cpu_abort(env1, "Internal error: code buffer overflow\n"); - } - nb_tbs = 0; - - for (env = first_cpu; env != NULL; env = env->next_cpu) { - memset(env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof(void *)); - } - - memset(tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof(void *)); - page_flush_tb(); - - code_gen_ptr = code_gen_buffer; - /* XXX: flush processor icache at this point if cache flush is - expensive */ - tb_flush_count++; -} - -#ifdef DEBUG_TB_CHECK - -static void tb_invalidate_check(target_ulong address) -{ - TranslationBlock *tb; - int i; - - address &= TARGET_PAGE_MASK; - for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) { - for (tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) { - if (!(address + TARGET_PAGE_SIZE <= tb->pc || - address >= tb->pc + tb->size)) { - printf("ERROR invalidate: address=" TARGET_FMT_lx - " PC=%08lx size=%04x\n", - address, (long)tb->pc, tb->size); - } - } - } -} - -/* verify that all the pages have correct rights for code */ -static void tb_page_check(void) -{ - TranslationBlock *tb; - int i, flags1, flags2; - - for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) { - for (tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) { - flags1 = page_get_flags(tb->pc); - flags2 = page_get_flags(tb->pc + tb->size - 1); - if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) { - printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n", - (long)tb->pc, tb->size, flags1, flags2); - } - } - } -} - -#endif - - -/* invalidate one TB */ -static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb, - int next_offset) -{ - TranslationBlock *tb1; - - for (;;) { - tb1 = *ptb; - if (tb1 == tb) { - *ptb = *(TranslationBlock **)((char *)tb1 + next_offset); - break; - } - ptb = (TranslationBlock **)((char *)tb1 + next_offset); - } -} - -static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb) -{ - TranslationBlock *tb1; - unsigned int n1; - - for (;;) { - tb1 = *ptb; - n1 = (uintptr_t)tb1 & 3; - tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); - if (tb1 == tb) { - *ptb = tb1->page_next[n1]; - break; - } - ptb = &tb1->page_next[n1]; - } -} - -static inline void tb_jmp_remove(TranslationBlock *tb, int n) -{ - TranslationBlock *tb1, **ptb; - unsigned int n1; - - ptb = &tb->jmp_next[n]; - tb1 = *ptb; - if (tb1) { - /* find tb(n) in circular list */ - for (;;) { - tb1 = *ptb; - n1 = (uintptr_t)tb1 & 3; - tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); - if (n1 == n && tb1 == tb) { - break; - } - if (n1 == 2) { - ptb = &tb1->jmp_first; - } else { - ptb = &tb1->jmp_next[n1]; - } - } - /* now we can suppress tb(n) from the list */ - *ptb = tb->jmp_next[n]; - - tb->jmp_next[n] = NULL; - } -} - -/* reset the jump entry 'n' of a TB so that it is not chained to - another TB */ -static inline void tb_reset_jump(TranslationBlock *tb, int n) -{ - tb_set_jmp_target(tb, n, (uintptr_t)(tb->tc_ptr + tb->tb_next_offset[n])); -} - -void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) -{ - CPUArchState *env; - PageDesc *p; - unsigned int h, n1; - tb_page_addr_t phys_pc; - TranslationBlock *tb1, *tb2; - - /* remove the TB from the hash list */ - phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK); - h = tb_phys_hash_func(phys_pc); - tb_remove(&tb_phys_hash[h], tb, - offsetof(TranslationBlock, phys_hash_next)); - - /* remove the TB from the page list */ - if (tb->page_addr[0] != page_addr) { - p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS); - tb_page_remove(&p->first_tb, tb); - invalidate_page_bitmap(p); - } - if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) { - p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS); - tb_page_remove(&p->first_tb, tb); - invalidate_page_bitmap(p); - } - - tb_invalidated_flag = 1; - - /* remove the TB from the hash list */ - h = tb_jmp_cache_hash_func(tb->pc); - for (env = first_cpu; env != NULL; env = env->next_cpu) { - if (env->tb_jmp_cache[h] == tb) { - env->tb_jmp_cache[h] = NULL; - } - } - - /* suppress this TB from the two jump lists */ - tb_jmp_remove(tb, 0); - tb_jmp_remove(tb, 1); - - /* suppress any remaining jumps to this TB */ - tb1 = tb->jmp_first; - for (;;) { - n1 = (uintptr_t)tb1 & 3; - if (n1 == 2) { - break; - } - tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); - tb2 = tb1->jmp_next[n1]; - tb_reset_jump(tb1, n1); - tb1->jmp_next[n1] = NULL; - tb1 = tb2; - } - tb->jmp_first = (TranslationBlock *)((uintptr_t)tb | 2); /* fail safe */ - - tb_phys_invalidate_count++; -} - -static inline void set_bits(uint8_t *tab, int start, int len) -{ - int end, mask, end1; - - end = start + len; - tab += start >> 3; - mask = 0xff << (start & 7); - if ((start & ~7) == (end & ~7)) { - if (start < end) { - mask &= ~(0xff << (end & 7)); - *tab |= mask; - } - } else { - *tab++ |= mask; - start = (start + 8) & ~7; - end1 = end & ~7; - while (start < end1) { - *tab++ = 0xff; - start += 8; - } - if (start < end) { - mask = ~(0xff << (end & 7)); - *tab |= mask; - } - } -} - -static void build_page_bitmap(PageDesc *p) -{ - int n, tb_start, tb_end; - TranslationBlock *tb; - - p->code_bitmap = g_malloc0(TARGET_PAGE_SIZE / 8); - - tb = p->first_tb; - while (tb != NULL) { - n = (uintptr_t)tb & 3; - tb = (TranslationBlock *)((uintptr_t)tb & ~3); - /* NOTE: this is subtle as a TB may span two physical pages */ - if (n == 0) { - /* NOTE: tb_end may be after the end of the page, but - it is not a problem */ - tb_start = tb->pc & ~TARGET_PAGE_MASK; - tb_end = tb_start + tb->size; - if (tb_end > TARGET_PAGE_SIZE) { - tb_end = TARGET_PAGE_SIZE; - } - } else { - tb_start = 0; - tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK); - } - set_bits(p->code_bitmap, tb_start, tb_end - tb_start); - tb = tb->page_next[n]; - } -} - -TranslationBlock *tb_gen_code(CPUArchState *env, - target_ulong pc, target_ulong cs_base, - int flags, int cflags) -{ - TranslationBlock *tb; - uint8_t *tc_ptr; - tb_page_addr_t phys_pc, phys_page2; - target_ulong virt_page2; - int code_gen_size; - - phys_pc = get_page_addr_code(env, pc); - tb = tb_alloc(pc); - if (!tb) { - /* flush must be done */ - tb_flush(env); - /* cannot fail at this point */ - tb = tb_alloc(pc); - /* Don't forget to invalidate previous TB info. */ - tb_invalidated_flag = 1; - } - tc_ptr = code_gen_ptr; - tb->tc_ptr = tc_ptr; - tb->cs_base = cs_base; - tb->flags = flags; - tb->cflags = cflags; - cpu_gen_code(env, tb, &code_gen_size); - code_gen_ptr = (void *)(((uintptr_t)code_gen_ptr + code_gen_size + - CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); - - /* check next page if needed */ - virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK; - phys_page2 = -1; - if ((pc & TARGET_PAGE_MASK) != virt_page2) { - phys_page2 = get_page_addr_code(env, virt_page2); - } - tb_link_page(tb, phys_pc, phys_page2); - return tb; -} - -/* - * Invalidate all TBs which intersect with the target physical address range - * [start;end[. NOTE: start and end may refer to *different* physical pages. - * 'is_cpu_write_access' should be true if called from a real cpu write - * access: the virtual CPU will exit the current TB if code is modified inside - * this TB. - */ -void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end, - int is_cpu_write_access) -{ - while (start < end) { - tb_invalidate_phys_page_range(start, end, is_cpu_write_access); - start &= TARGET_PAGE_MASK; - start += TARGET_PAGE_SIZE; - } -} - -/* - * Invalidate all TBs which intersect with the target physical address range - * [start;end[. NOTE: start and end must refer to the *same* physical page. - * 'is_cpu_write_access' should be true if called from a real cpu write - * access: the virtual CPU will exit the current TB if code is modified inside - * this TB. - */ -void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, - int is_cpu_write_access) -{ - TranslationBlock *tb, *tb_next, *saved_tb; - CPUArchState *env = cpu_single_env; - tb_page_addr_t tb_start, tb_end; - PageDesc *p; - int n; -#ifdef TARGET_HAS_PRECISE_SMC - int current_tb_not_found = is_cpu_write_access; - TranslationBlock *current_tb = NULL; - int current_tb_modified = 0; - target_ulong current_pc = 0; - target_ulong current_cs_base = 0; - int current_flags = 0; -#endif /* TARGET_HAS_PRECISE_SMC */ - - p = page_find(start >> TARGET_PAGE_BITS); - if (!p) { - return; - } - if (!p->code_bitmap && - ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD && - is_cpu_write_access) { - /* build code bitmap */ - build_page_bitmap(p); - } - - /* we remove all the TBs in the range [start, end[ */ - /* XXX: see if in some cases it could be faster to invalidate all - the code */ - tb = p->first_tb; - while (tb != NULL) { - n = (uintptr_t)tb & 3; - tb = (TranslationBlock *)((uintptr_t)tb & ~3); - tb_next = tb->page_next[n]; - /* NOTE: this is subtle as a TB may span two physical pages */ - if (n == 0) { - /* NOTE: tb_end may be after the end of the page, but - it is not a problem */ - tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK); - tb_end = tb_start + tb->size; - } else { - tb_start = tb->page_addr[1]; - tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK); - } - if (!(tb_end <= start || tb_start >= end)) { -#ifdef TARGET_HAS_PRECISE_SMC - if (current_tb_not_found) { - current_tb_not_found = 0; - current_tb = NULL; - if (env->mem_io_pc) { - /* now we have a real cpu fault */ - current_tb = tb_find_pc(env->mem_io_pc); - } - } - if (current_tb == tb && - (current_tb->cflags & CF_COUNT_MASK) != 1) { - /* If we are modifying the current TB, we must stop - its execution. We could be more precise by checking - that the modification is after the current PC, but it - would require a specialized function to partially - restore the CPU state */ - - current_tb_modified = 1; - cpu_restore_state(current_tb, env, env->mem_io_pc); - cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base, - ¤t_flags); - } -#endif /* TARGET_HAS_PRECISE_SMC */ - /* we need to do that to handle the case where a signal - occurs while doing tb_phys_invalidate() */ - saved_tb = NULL; - if (env) { - saved_tb = env->current_tb; - env->current_tb = NULL; - } - tb_phys_invalidate(tb, -1); - if (env) { - env->current_tb = saved_tb; - if (env->interrupt_request && env->current_tb) { - cpu_interrupt(env, env->interrupt_request); - } - } - } - tb = tb_next; - } -#if !defined(CONFIG_USER_ONLY) - /* if no code remaining, no need to continue to use slow writes */ - if (!p->first_tb) { - invalidate_page_bitmap(p); - if (is_cpu_write_access) { - tlb_unprotect_code_phys(env, start, env->mem_io_vaddr); - } - } -#endif -#ifdef TARGET_HAS_PRECISE_SMC - if (current_tb_modified) { - /* we generate a block containing just the instruction - modifying the memory. It will ensure that it cannot modify - itself */ - env->current_tb = NULL; - tb_gen_code(env, current_pc, current_cs_base, current_flags, 1); - cpu_resume_from_signal(env, NULL); - } -#endif -} - -/* len must be <= 8 and start must be a multiple of len */ -static inline void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len) -{ - PageDesc *p; - int offset, b; - -#if 0 - if (1) { - qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n", - cpu_single_env->mem_io_vaddr, len, - cpu_single_env->eip, - cpu_single_env->eip + - (intptr_t)cpu_single_env->segs[R_CS].base); - } -#endif - p = page_find(start >> TARGET_PAGE_BITS); - if (!p) { - return; - } - if (p->code_bitmap) { - offset = start & ~TARGET_PAGE_MASK; - b = p->code_bitmap[offset >> 3] >> (offset & 7); - if (b & ((1 << len) - 1)) { - goto do_invalidate; - } - } else { - do_invalidate: - tb_invalidate_phys_page_range(start, start + len, 1); - } -} - -#if !defined(CONFIG_SOFTMMU) -static void tb_invalidate_phys_page(tb_page_addr_t addr, - uintptr_t pc, void *puc) -{ - TranslationBlock *tb; - PageDesc *p; - int n; -#ifdef TARGET_HAS_PRECISE_SMC - TranslationBlock *current_tb = NULL; - CPUArchState *env = cpu_single_env; - int current_tb_modified = 0; - target_ulong current_pc = 0; - target_ulong current_cs_base = 0; - int current_flags = 0; -#endif - - addr &= TARGET_PAGE_MASK; - p = page_find(addr >> TARGET_PAGE_BITS); - if (!p) { - return; - } - tb = p->first_tb; -#ifdef TARGET_HAS_PRECISE_SMC - if (tb && pc != 0) { - current_tb = tb_find_pc(pc); - } -#endif - while (tb != NULL) { - n = (uintptr_t)tb & 3; - tb = (TranslationBlock *)((uintptr_t)tb & ~3); -#ifdef TARGET_HAS_PRECISE_SMC - if (current_tb == tb && - (current_tb->cflags & CF_COUNT_MASK) != 1) { - /* If we are modifying the current TB, we must stop - its execution. We could be more precise by checking - that the modification is after the current PC, but it - would require a specialized function to partially - restore the CPU state */ - - current_tb_modified = 1; - cpu_restore_state(current_tb, env, pc); - cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base, - ¤t_flags); - } -#endif /* TARGET_HAS_PRECISE_SMC */ - tb_phys_invalidate(tb, addr); - tb = tb->page_next[n]; - } - p->first_tb = NULL; -#ifdef TARGET_HAS_PRECISE_SMC - if (current_tb_modified) { - /* we generate a block containing just the instruction - modifying the memory. It will ensure that it cannot modify - itself */ - env->current_tb = NULL; - tb_gen_code(env, current_pc, current_cs_base, current_flags, 1); - cpu_resume_from_signal(env, puc); - } -#endif -} -#endif - -/* add the tb in the target page and protect it if necessary */ -static inline void tb_alloc_page(TranslationBlock *tb, - unsigned int n, tb_page_addr_t page_addr) -{ - PageDesc *p; -#ifndef CONFIG_USER_ONLY - bool page_already_protected; -#endif - - tb->page_addr[n] = page_addr; - p = page_find_alloc(page_addr >> TARGET_PAGE_BITS, 1); - tb->page_next[n] = p->first_tb; -#ifndef CONFIG_USER_ONLY - page_already_protected = p->first_tb != NULL; -#endif - p->first_tb = (TranslationBlock *)((uintptr_t)tb | n); - invalidate_page_bitmap(p); - -#if defined(TARGET_HAS_SMC) || 1 - -#if defined(CONFIG_USER_ONLY) - if (p->flags & PAGE_WRITE) { - target_ulong addr; - PageDesc *p2; - int prot; - - /* force the host page as non writable (writes will have a - page fault + mprotect overhead) */ - page_addr &= qemu_host_page_mask; - prot = 0; - for (addr = page_addr; addr < page_addr + qemu_host_page_size; - addr += TARGET_PAGE_SIZE) { - - p2 = page_find(addr >> TARGET_PAGE_BITS); - if (!p2) { - continue; - } - prot |= p2->flags; - p2->flags &= ~PAGE_WRITE; - } - mprotect(g2h(page_addr), qemu_host_page_size, - (prot & PAGE_BITS) & ~PAGE_WRITE); -#ifdef DEBUG_TB_INVALIDATE - printf("protecting code page: 0x" TARGET_FMT_lx "\n", - page_addr); -#endif - } -#else - /* if some code is already present, then the pages are already - protected. So we handle the case where only the first TB is - allocated in a physical page */ - if (!page_already_protected) { - tlb_protect_code(page_addr); - } -#endif - -#endif /* TARGET_HAS_SMC */ -} - -/* add a new TB and link it to the physical page tables. phys_page2 is - (-1) to indicate that only one page contains the TB. */ -static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, - tb_page_addr_t phys_page2) -{ - unsigned int h; - TranslationBlock **ptb; - - /* Grab the mmap lock to stop another thread invalidating this TB - before we are done. */ - mmap_lock(); - /* add in the physical hash table */ - h = tb_phys_hash_func(phys_pc); - ptb = &tb_phys_hash[h]; - tb->phys_hash_next = *ptb; - *ptb = tb; - - /* add in the page list */ - tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK); - if (phys_page2 != -1) { - tb_alloc_page(tb, 1, phys_page2); - } else { - tb->page_addr[1] = -1; - } - - tb->jmp_first = (TranslationBlock *)((uintptr_t)tb | 2); - tb->jmp_next[0] = NULL; - tb->jmp_next[1] = NULL; - - /* init original jump addresses */ - if (tb->tb_next_offset[0] != 0xffff) { - tb_reset_jump(tb, 0); - } - if (tb->tb_next_offset[1] != 0xffff) { - tb_reset_jump(tb, 1); - } - -#ifdef DEBUG_TB_CHECK - tb_page_check(); -#endif - mmap_unlock(); -} - -#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU) -/* check whether the given addr is in TCG generated code buffer or not */ -bool is_tcg_gen_code(uintptr_t tc_ptr) -{ - /* This can be called during code generation, code_gen_buffer_max_size - is used instead of code_gen_ptr for upper boundary checking */ - return (tc_ptr >= (uintptr_t)code_gen_buffer && - tc_ptr < (uintptr_t)(code_gen_buffer + code_gen_buffer_max_size)); -} -#endif - -/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr < - tb[1].tc_ptr. Return NULL if not found */ -TranslationBlock *tb_find_pc(uintptr_t tc_ptr) -{ - int m_min, m_max, m; - uintptr_t v; - TranslationBlock *tb; - - if (nb_tbs <= 0) { - return NULL; - } - if (tc_ptr < (uintptr_t)code_gen_buffer || - tc_ptr >= (uintptr_t)code_gen_ptr) { - return NULL; - } - /* binary search (cf Knuth) */ - m_min = 0; - m_max = nb_tbs - 1; - while (m_min <= m_max) { - m = (m_min + m_max) >> 1; - tb = &tbs[m]; - v = (uintptr_t)tb->tc_ptr; - if (v == tc_ptr) { - return tb; - } else if (tc_ptr < v) { - m_max = m - 1; - } else { - m_min = m + 1; - } - } - return &tbs[m_max]; -} - -static void tb_reset_jump_recursive(TranslationBlock *tb); - -static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n) -{ - TranslationBlock *tb1, *tb_next, **ptb; - unsigned int n1; - - tb1 = tb->jmp_next[n]; - if (tb1 != NULL) { - /* find head of list */ - for (;;) { - n1 = (uintptr_t)tb1 & 3; - tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); - if (n1 == 2) { - break; - } - tb1 = tb1->jmp_next[n1]; - } - /* we are now sure now that tb jumps to tb1 */ - tb_next = tb1; - - /* remove tb from the jmp_first list */ - ptb = &tb_next->jmp_first; - for (;;) { - tb1 = *ptb; - n1 = (uintptr_t)tb1 & 3; - tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); - if (n1 == n && tb1 == tb) { - break; - } - ptb = &tb1->jmp_next[n1]; - } - *ptb = tb->jmp_next[n]; - tb->jmp_next[n] = NULL; - - /* suppress the jump to next tb in generated code */ - tb_reset_jump(tb, n); - - /* suppress jumps in the tb on which we could have jumped */ - tb_reset_jump_recursive(tb_next); - } -} - -static void tb_reset_jump_recursive(TranslationBlock *tb) -{ - tb_reset_jump_recursive2(tb, 0); - tb_reset_jump_recursive2(tb, 1); -} - #if defined(TARGET_HAS_ICE) #if defined(CONFIG_USER_ONLY) static void breakpoint_invalidate(CPUArchState *env, target_ulong pc) @@ -1523,22 +300,6 @@ static void breakpoint_invalidate(CPUArchState *env, target_ulong pc) tb_invalidate_phys_page_range(pc, pc + 1, 0); } #else -void tb_invalidate_phys_addr(hwaddr addr) -{ - ram_addr_t ram_addr; - MemoryRegionSection *section; - - 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))) { - return; - } - ram_addr = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK) - + memory_region_section_addr(section, addr); - tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0); -} - static void breakpoint_invalidate(CPUArchState *env, target_ulong pc) { tb_invalidate_phys_addr(cpu_get_phys_page_debug(env, pc) | @@ -1720,67 +481,6 @@ void cpu_single_step(CPUArchState *env, int enabled) #endif } -static void cpu_unlink_tb(CPUArchState *env) -{ - /* FIXME: TB unchaining isn't SMP safe. For now just ignore the - problem and hope the cpu will stop of its own accord. For userspace - emulation this often isn't actually as bad as it sounds. Often - signals are used primarily to interrupt blocking syscalls. */ - TranslationBlock *tb; - static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED; - - spin_lock(&interrupt_lock); - tb = env->current_tb; - /* if the cpu is currently executing code, we must unlink it and - all the potentially executing TB */ - if (tb) { - env->current_tb = NULL; - tb_reset_jump_recursive(tb); - } - spin_unlock(&interrupt_lock); -} - -#ifndef CONFIG_USER_ONLY -/* mask must never be zero, except for A20 change call */ -static void tcg_handle_interrupt(CPUArchState *env, int mask) -{ - CPUState *cpu = ENV_GET_CPU(env); - int old_mask; - - old_mask = env->interrupt_request; - env->interrupt_request |= mask; - - /* - * If called from iothread context, wake the target cpu in - * case its halted. - */ - if (!qemu_cpu_is_self(cpu)) { - qemu_cpu_kick(cpu); - return; - } - - if (use_icount) { - env->icount_decr.u16.high = 0xffff; - if (!can_do_io(env) - && (mask & ~old_mask) != 0) { - cpu_abort(env, "Raised interrupt while not in I/O function"); - } - } else { - cpu_unlink_tb(env); - } -} - -CPUInterruptHandler cpu_interrupt_handler = tcg_handle_interrupt; - -#else /* CONFIG_USER_ONLY */ - -void cpu_interrupt(CPUArchState *env, int mask) -{ - env->interrupt_request |= mask; - cpu_unlink_tb(env); -} -#endif /* CONFIG_USER_ONLY */ - void cpu_reset_interrupt(CPUArchState *env, int mask) { env->interrupt_request &= ~mask; @@ -1859,21 +559,6 @@ CPUArchState *cpu_copy(CPUArchState *env) } #if !defined(CONFIG_USER_ONLY) -void tb_flush_jmp_cache(CPUArchState *env, target_ulong addr) -{ - unsigned int i; - - /* Discard jump cache entries for any tb which might potentially - overlap the flushed page. */ - i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE); - memset (&env->tb_jmp_cache[i], 0, - TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *)); - - i = tb_jmp_cache_hash_page(addr); - memset (&env->tb_jmp_cache[i], 0, - TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *)); -} - static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t end, uintptr_t length) { @@ -1963,272 +648,6 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env, return iotlb; } - -#else -/* - * Walks guest process memory "regions" one by one - * and calls callback function 'fn' for each region. - */ -struct walk_memory_regions_data { - walk_memory_regions_fn fn; - void *priv; - uintptr_t start; - int prot; -}; - -static int walk_memory_regions_end(struct walk_memory_regions_data *data, - abi_ulong end, int new_prot) -{ - if (data->start != -1ul) { - int rc = data->fn(data->priv, data->start, end, data->prot); - if (rc != 0) { - return rc; - } - } - - data->start = (new_prot ? end : -1ul); - data->prot = new_prot; - - return 0; -} - -static int walk_memory_regions_1(struct walk_memory_regions_data *data, - abi_ulong base, int level, void **lp) -{ - abi_ulong pa; - int i, rc; - - if (*lp == NULL) { - return walk_memory_regions_end(data, base, 0); - } - - if (level == 0) { - PageDesc *pd = *lp; - - for (i = 0; i < L2_SIZE; ++i) { - int prot = pd[i].flags; - - pa = base | (i << TARGET_PAGE_BITS); - if (prot != data->prot) { - rc = walk_memory_regions_end(data, pa, prot); - if (rc != 0) { - return rc; - } - } - } - } else { - void **pp = *lp; - - for (i = 0; i < L2_SIZE; ++i) { - pa = base | ((abi_ulong)i << - (TARGET_PAGE_BITS + L2_BITS * level)); - rc = walk_memory_regions_1(data, pa, level - 1, pp + i); - if (rc != 0) { - return rc; - } - } - } - - return 0; -} - -int walk_memory_regions(void *priv, walk_memory_regions_fn fn) -{ - struct walk_memory_regions_data data; - uintptr_t i; - - data.fn = fn; - data.priv = priv; - data.start = -1ul; - data.prot = 0; - - for (i = 0; i < V_L1_SIZE; i++) { - int rc = walk_memory_regions_1(&data, (abi_ulong)i << V_L1_SHIFT, - V_L1_SHIFT / L2_BITS - 1, l1_map + i); - - if (rc != 0) { - return rc; - } - } - - return walk_memory_regions_end(&data, 0, 0); -} - -static int dump_region(void *priv, abi_ulong start, - abi_ulong end, unsigned long prot) -{ - FILE *f = (FILE *)priv; - - (void) fprintf(f, TARGET_ABI_FMT_lx"-"TARGET_ABI_FMT_lx - " "TARGET_ABI_FMT_lx" %c%c%c\n", - start, end, end - start, - ((prot & PAGE_READ) ? 'r' : '-'), - ((prot & PAGE_WRITE) ? 'w' : '-'), - ((prot & PAGE_EXEC) ? 'x' : '-')); - - return 0; -} - -/* dump memory mappings */ -void page_dump(FILE *f) -{ - (void) fprintf(f, "%-8s %-8s %-8s %s\n", - "start", "end", "size", "prot"); - walk_memory_regions(f, dump_region); -} - -int page_get_flags(target_ulong address) -{ - PageDesc *p; - - p = page_find(address >> TARGET_PAGE_BITS); - if (!p) { - return 0; - } - return p->flags; -} - -/* Modify the flags of a page and invalidate the code if necessary. - The flag PAGE_WRITE_ORG is positioned automatically depending - on PAGE_WRITE. The mmap_lock should already be held. */ -void page_set_flags(target_ulong start, target_ulong end, int flags) -{ - target_ulong addr, len; - - /* This function should never be called with addresses outside the - guest address space. If this assert fires, it probably indicates - a missing call to h2g_valid. */ -#if TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS - assert(end < ((abi_ulong)1 << L1_MAP_ADDR_SPACE_BITS)); -#endif - assert(start < end); - - start = start & TARGET_PAGE_MASK; - end = TARGET_PAGE_ALIGN(end); - - if (flags & PAGE_WRITE) { - flags |= PAGE_WRITE_ORG; - } - - for (addr = start, len = end - start; - len != 0; - len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) { - PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, 1); - - /* If the write protection bit is set, then we invalidate - the code inside. */ - if (!(p->flags & PAGE_WRITE) && - (flags & PAGE_WRITE) && - p->first_tb) { - tb_invalidate_phys_page(addr, 0, NULL); - } - p->flags = flags; - } -} - -int page_check_range(target_ulong start, target_ulong len, int flags) -{ - PageDesc *p; - target_ulong end; - target_ulong addr; - - /* This function should never be called with addresses outside the - guest address space. If this assert fires, it probably indicates - a missing call to h2g_valid. */ -#if TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS - assert(start < ((abi_ulong)1 << L1_MAP_ADDR_SPACE_BITS)); -#endif - - if (len == 0) { - return 0; - } - if (start + len - 1 < start) { - /* We've wrapped around. */ - return -1; - } - - /* must do before we loose bits in the next step */ - end = TARGET_PAGE_ALIGN(start + len); - start = start & TARGET_PAGE_MASK; - - for (addr = start, len = end - start; - len != 0; - len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) { - p = page_find(addr >> TARGET_PAGE_BITS); - if (!p) { - return -1; - } - if (!(p->flags & PAGE_VALID)) { - return -1; - } - - if ((flags & PAGE_READ) && !(p->flags & PAGE_READ)) { - return -1; - } - if (flags & PAGE_WRITE) { - if (!(p->flags & PAGE_WRITE_ORG)) { - return -1; - } - /* unprotect the page if it was put read-only because it - contains translated code */ - if (!(p->flags & PAGE_WRITE)) { - if (!page_unprotect(addr, 0, NULL)) { - return -1; - } - } - return 0; - } - } - return 0; -} - -/* called from signal handler: invalidate the code and unprotect the - page. Return TRUE if the fault was successfully handled. */ -int page_unprotect(target_ulong address, uintptr_t pc, void *puc) -{ - unsigned int prot; - PageDesc *p; - target_ulong host_start, host_end, addr; - - /* Technically this isn't safe inside a signal handler. However we - know this only ever happens in a synchronous SEGV handler, so in - practice it seems to be ok. */ - mmap_lock(); - - p = page_find(address >> TARGET_PAGE_BITS); - if (!p) { - mmap_unlock(); - return 0; - } - - /* if the page was really writable, then we change its - protection back to writable */ - if ((p->flags & PAGE_WRITE_ORG) && !(p->flags & PAGE_WRITE)) { - host_start = address & qemu_host_page_mask; - host_end = host_start + qemu_host_page_size; - - prot = 0; - for (addr = host_start ; addr < host_end ; addr += TARGET_PAGE_SIZE) { - p = page_find(addr >> TARGET_PAGE_BITS); - p->flags |= PAGE_WRITE; - prot |= p->flags; - - /* and since the content will be modified, we must invalidate - the corresponding translated code. */ - tb_invalidate_phys_page(addr, pc, puc); -#ifdef DEBUG_TB_CHECK - tb_invalidate_check(addr); -#endif - } - mprotect((void *)g2h(host_start), qemu_host_page_size, - prot & PAGE_BITS); - - mmap_unlock(); - return 1; - } - mmap_unlock(); - return 0; -} #endif /* defined(CONFIG_USER_ONLY) */ #if !defined(CONFIG_USER_ONLY) @@ -2987,19 +1406,6 @@ static const MemoryRegionOps notdirty_mem_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void tb_check_watchpoint(CPUArchState *env) -{ - TranslationBlock *tb; - - tb = tb_find_pc(env->mem_io_pc); - if (!tb) { - cpu_abort(env, "check_watchpoint: could not find TB for pc=%p", - (void *)env->mem_io_pc); - } - cpu_restore_state(tb, env, env->mem_io_pc); - tb_phys_invalidate(tb, -1); -} - /* Generate a debug exception if a watchpoint has been hit. */ static void check_watchpoint(int offset, int len_mask, int flags) { @@ -4134,123 +2540,8 @@ int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr, } #endif -/* in deterministic execution mode, instructions doing device I/Os - must be at the end of the TB */ -void cpu_io_recompile(CPUArchState *env, uintptr_t retaddr) -{ - TranslationBlock *tb; - uint32_t n, cflags; - target_ulong pc, cs_base; - uint64_t flags; - - tb = tb_find_pc(retaddr); - if (!tb) { - cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p", - (void *)retaddr); - } - n = env->icount_decr.u16.low + tb->icount; - cpu_restore_state(tb, env, retaddr); - /* Calculate how many instructions had been executed before the fault - occurred. */ - n = n - env->icount_decr.u16.low; - /* Generate a new TB ending on the I/O insn. */ - n++; - /* On MIPS and SH, delay slot instructions can only be restarted if - they were already the first instruction in the TB. If this is not - the first instruction in a TB then re-execute the preceding - branch. */ -#if defined(TARGET_MIPS) - if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) { - env->active_tc.PC -= 4; - env->icount_decr.u16.low++; - env->hflags &= ~MIPS_HFLAG_BMASK; - } -#elif defined(TARGET_SH4) - if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0 - && n > 1) { - env->pc -= 2; - env->icount_decr.u16.low++; - env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL); - } -#endif - /* This should never happen. */ - if (n > CF_COUNT_MASK) { - cpu_abort(env, "TB too big during recompile"); - } - - cflags = n | CF_LAST_IO; - pc = tb->pc; - cs_base = tb->cs_base; - flags = tb->flags; - tb_phys_invalidate(tb, -1); - /* FIXME: In theory this could raise an exception. In practice - we have already translated the block once so it's probably ok. */ - tb_gen_code(env, pc, cs_base, flags, cflags); - /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not - the first in the TB) then we end up generating a whole new TB and - repeating the fault, which is horribly inefficient. - Better would be to execute just this insn uncached, or generate a - second new TB. */ - cpu_resume_from_signal(env, NULL); -} - #if !defined(CONFIG_USER_ONLY) -void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) -{ - int i, target_code_size, max_target_code_size; - int direct_jmp_count, direct_jmp2_count, cross_page; - TranslationBlock *tb; - - target_code_size = 0; - max_target_code_size = 0; - cross_page = 0; - direct_jmp_count = 0; - direct_jmp2_count = 0; - for (i = 0; i < nb_tbs; i++) { - tb = &tbs[i]; - target_code_size += tb->size; - if (tb->size > max_target_code_size) { - max_target_code_size = tb->size; - } - if (tb->page_addr[1] != -1) { - cross_page++; - } - if (tb->tb_next_offset[0] != 0xffff) { - direct_jmp_count++; - if (tb->tb_next_offset[1] != 0xffff) { - direct_jmp2_count++; - } - } - } - /* XXX: avoid using doubles ? */ - cpu_fprintf(f, "Translation buffer state:\n"); - cpu_fprintf(f, "gen code size %td/%zd\n", - code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size); - cpu_fprintf(f, "TB count %d/%d\n", - nb_tbs, code_gen_max_blocks); - cpu_fprintf(f, "TB avg target size %d max=%d bytes\n", - nb_tbs ? target_code_size / nb_tbs : 0, - max_target_code_size); - cpu_fprintf(f, "TB avg host size %td bytes (expansion ratio: %0.1f)\n", - nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0, - target_code_size ? (double) (code_gen_ptr - code_gen_buffer) - / target_code_size : 0); - cpu_fprintf(f, "cross page TB count %d (%d%%)\n", - cross_page, - nb_tbs ? (cross_page * 100) / nb_tbs : 0); - cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n", - direct_jmp_count, - nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0, - direct_jmp2_count, - nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0); - cpu_fprintf(f, "\nStatistics:\n"); - cpu_fprintf(f, "TB flush count %d\n", tb_flush_count); - cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count); - cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count); - tcg_dump_info(f, cpu_fprintf); -} - /* * A helper function for the _utterly broken_ virtio device model to find out if * it's running on a big endian machine. Don't do this at home kids! diff --git a/translate-all.c b/translate-all.c index f22e3eedd2..b958342a99 100644 --- a/translate-all.c +++ b/translate-all.c @@ -16,6 +16,12 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ +#ifdef _WIN32 +#include +#else +#include +#include +#endif #include #include #include @@ -24,15 +30,119 @@ #include "config.h" +#include "qemu-common.h" #define NO_CPU_IO_DEFS #include "cpu.h" #include "disas.h" #include "tcg.h" #include "qemu-timer.h" +#include "memory.h" +#include "exec-memory.h" +#if defined(CONFIG_USER_ONLY) +#include "qemu.h" +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#include +#if __FreeBSD_version >= 700104 +#define HAVE_KINFO_GETVMMAP +#define sigqueue sigqueue_freebsd /* avoid redefinition */ +#include +#include +#include +#define _KERNEL +#include +#undef _KERNEL +#undef sigqueue +#include +#endif +#endif +#endif + +#include "cputlb.h" +#include "translate-all.h" + +//#define DEBUG_TB_INVALIDATE +//#define DEBUG_FLUSH +/* make various TB consistency checks */ +//#define DEBUG_TB_CHECK + +#if !defined(CONFIG_USER_ONLY) +/* TB consistency checks only implemented for usermode emulation. */ +#undef DEBUG_TB_CHECK +#endif + +#define SMC_BITMAP_USE_THRESHOLD 10 + +/* Code generation and translation blocks */ +static TranslationBlock *tbs; +static int code_gen_max_blocks; +TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; +static int nb_tbs; +/* any access to the tbs or the page table must use this lock */ +spinlock_t tb_lock = SPIN_LOCK_UNLOCKED; + +uint8_t *code_gen_prologue; +static uint8_t *code_gen_buffer; +static size_t code_gen_buffer_size; +/* threshold to flush the translated code buffer */ +static size_t code_gen_buffer_max_size; +static uint8_t *code_gen_ptr; + +typedef struct PageDesc { + /* list of TBs intersecting this ram page */ + TranslationBlock *first_tb; + /* in order to optimize self modifying code, we count the number + of lookups we do to a given page to use a bitmap */ + unsigned int code_write_count; + uint8_t *code_bitmap; +#if defined(CONFIG_USER_ONLY) + unsigned long flags; +#endif +} PageDesc; + +/* In system mode we want L1_MAP to be based on ram offsets, + while in user mode we want it to be based on virtual addresses. */ +#if !defined(CONFIG_USER_ONLY) +#if HOST_LONG_BITS < TARGET_PHYS_ADDR_SPACE_BITS +# define L1_MAP_ADDR_SPACE_BITS HOST_LONG_BITS +#else +# define L1_MAP_ADDR_SPACE_BITS TARGET_PHYS_ADDR_SPACE_BITS +#endif +#else +# define L1_MAP_ADDR_SPACE_BITS TARGET_VIRT_ADDR_SPACE_BITS +#endif + +/* The bits remaining after N lower levels of page tables. */ +#define V_L1_BITS_REM \ + ((L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS) % L2_BITS) + +#if V_L1_BITS_REM < 4 +#define V_L1_BITS (V_L1_BITS_REM + L2_BITS) +#else +#define V_L1_BITS V_L1_BITS_REM +#endif + +#define V_L1_SIZE ((target_ulong)1 << V_L1_BITS) + +#define V_L1_SHIFT (L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS - V_L1_BITS) + +uintptr_t qemu_real_host_page_size; +uintptr_t qemu_host_page_size; +uintptr_t qemu_host_page_mask; + +/* This is a multi-level map on the virtual address space. + The bottom level has pointers to PageDesc. */ +static void *l1_map[V_L1_SIZE]; + +/* statistics */ +static int tb_flush_count; +static int tb_phys_invalidate_count; /* code generation context */ TCGContext tcg_ctx; +static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, + tb_page_addr_t phys_page2); + void cpu_gen_init(void) { tcg_context_init(&tcg_ctx); @@ -155,3 +265,1612 @@ int cpu_restore_state(TranslationBlock *tb, #endif return 0; } + +#ifdef _WIN32 +static inline void map_exec(void *addr, long size) +{ + DWORD old_protect; + VirtualProtect(addr, size, + PAGE_EXECUTE_READWRITE, &old_protect); +} +#else +static inline void map_exec(void *addr, long size) +{ + unsigned long start, end, page_size; + + page_size = getpagesize(); + start = (unsigned long)addr; + start &= ~(page_size - 1); + + end = (unsigned long)addr + size; + end += page_size - 1; + end &= ~(page_size - 1); + + mprotect((void *)start, end - start, + PROT_READ | PROT_WRITE | PROT_EXEC); +} +#endif + +static void page_init(void) +{ + /* NOTE: we can always suppose that qemu_host_page_size >= + TARGET_PAGE_SIZE */ +#ifdef _WIN32 + { + SYSTEM_INFO system_info; + + GetSystemInfo(&system_info); + qemu_real_host_page_size = system_info.dwPageSize; + } +#else + qemu_real_host_page_size = getpagesize(); +#endif + if (qemu_host_page_size == 0) { + qemu_host_page_size = qemu_real_host_page_size; + } + if (qemu_host_page_size < TARGET_PAGE_SIZE) { + qemu_host_page_size = TARGET_PAGE_SIZE; + } + qemu_host_page_mask = ~(qemu_host_page_size - 1); + +#if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY) + { +#ifdef HAVE_KINFO_GETVMMAP + struct kinfo_vmentry *freep; + int i, cnt; + + freep = kinfo_getvmmap(getpid(), &cnt); + if (freep) { + mmap_lock(); + for (i = 0; i < cnt; i++) { + unsigned long startaddr, endaddr; + + startaddr = freep[i].kve_start; + endaddr = freep[i].kve_end; + if (h2g_valid(startaddr)) { + startaddr = h2g(startaddr) & TARGET_PAGE_MASK; + + if (h2g_valid(endaddr)) { + endaddr = h2g(endaddr); + page_set_flags(startaddr, endaddr, PAGE_RESERVED); + } else { +#if TARGET_ABI_BITS <= L1_MAP_ADDR_SPACE_BITS + endaddr = ~0ul; + page_set_flags(startaddr, endaddr, PAGE_RESERVED); +#endif + } + } + } + free(freep); + mmap_unlock(); + } +#else + FILE *f; + + last_brk = (unsigned long)sbrk(0); + + f = fopen("/compat/linux/proc/self/maps", "r"); + if (f) { + mmap_lock(); + + do { + unsigned long startaddr, endaddr; + int n; + + n = fscanf(f, "%lx-%lx %*[^\n]\n", &startaddr, &endaddr); + + if (n == 2 && h2g_valid(startaddr)) { + startaddr = h2g(startaddr) & TARGET_PAGE_MASK; + + if (h2g_valid(endaddr)) { + endaddr = h2g(endaddr); + } else { + endaddr = ~0ul; + } + page_set_flags(startaddr, endaddr, PAGE_RESERVED); + } + } while (!feof(f)); + + fclose(f); + mmap_unlock(); + } +#endif + } +#endif +} + +static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc) +{ + PageDesc *pd; + void **lp; + int i; + +#if defined(CONFIG_USER_ONLY) + /* We can't use g_malloc because it may recurse into a locked mutex. */ +# define ALLOC(P, SIZE) \ + do { \ + P = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, \ + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \ + } while (0) +#else +# define ALLOC(P, SIZE) \ + do { P = g_malloc0(SIZE); } while (0) +#endif + + /* Level 1. Always allocated. */ + lp = l1_map + ((index >> V_L1_SHIFT) & (V_L1_SIZE - 1)); + + /* Level 2..N-1. */ + for (i = V_L1_SHIFT / L2_BITS - 1; i > 0; i--) { + void **p = *lp; + + if (p == NULL) { + if (!alloc) { + return NULL; + } + ALLOC(p, sizeof(void *) * L2_SIZE); + *lp = p; + } + + lp = p + ((index >> (i * L2_BITS)) & (L2_SIZE - 1)); + } + + pd = *lp; + if (pd == NULL) { + if (!alloc) { + return NULL; + } + ALLOC(pd, sizeof(PageDesc) * L2_SIZE); + *lp = pd; + } + +#undef ALLOC + + return pd + (index & (L2_SIZE - 1)); +} + +static inline PageDesc *page_find(tb_page_addr_t index) +{ + return page_find_alloc(index, 0); +} + +#if !defined(CONFIG_USER_ONLY) +#define mmap_lock() do { } while (0) +#define mmap_unlock() do { } while (0) +#endif + +#if defined(CONFIG_USER_ONLY) +/* Currently it is not recommended to allocate big chunks of data in + user mode. It will change when a dedicated libc will be used. */ +/* ??? 64-bit hosts ought to have no problem mmaping data outside the + region in which the guest needs to run. Revisit this. */ +#define USE_STATIC_CODE_GEN_BUFFER +#endif + +/* ??? Should configure for this, not list operating systems here. */ +#if (defined(__linux__) \ + || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \ + || defined(__DragonFly__) || defined(__OpenBSD__) \ + || defined(__NetBSD__)) +# define USE_MMAP +#endif + +/* Minimum size of the code gen buffer. This number is randomly chosen, + but not so small that we can't have a fair number of TB's live. */ +#define MIN_CODE_GEN_BUFFER_SIZE (1024u * 1024) + +/* Maximum size of the code gen buffer we'd like to use. Unless otherwise + indicated, this is constrained by the range of direct branches on the + host cpu, as used by the TCG implementation of goto_tb. */ +#if defined(__x86_64__) +# define MAX_CODE_GEN_BUFFER_SIZE (2ul * 1024 * 1024 * 1024) +#elif defined(__sparc__) +# define MAX_CODE_GEN_BUFFER_SIZE (2ul * 1024 * 1024 * 1024) +#elif defined(__arm__) +# define MAX_CODE_GEN_BUFFER_SIZE (16u * 1024 * 1024) +#elif defined(__s390x__) + /* We have a +- 4GB range on the branches; leave some slop. */ +# define MAX_CODE_GEN_BUFFER_SIZE (3ul * 1024 * 1024 * 1024) +#else +# define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1) +#endif + +#define DEFAULT_CODE_GEN_BUFFER_SIZE_1 (32u * 1024 * 1024) + +#define DEFAULT_CODE_GEN_BUFFER_SIZE \ + (DEFAULT_CODE_GEN_BUFFER_SIZE_1 < MAX_CODE_GEN_BUFFER_SIZE \ + ? DEFAULT_CODE_GEN_BUFFER_SIZE_1 : MAX_CODE_GEN_BUFFER_SIZE) + +static inline size_t size_code_gen_buffer(size_t tb_size) +{ + /* Size the buffer. */ + if (tb_size == 0) { +#ifdef USE_STATIC_CODE_GEN_BUFFER + tb_size = DEFAULT_CODE_GEN_BUFFER_SIZE; +#else + /* ??? Needs adjustments. */ + /* ??? If we relax the requirement that CONFIG_USER_ONLY use the + static buffer, we could size this on RESERVED_VA, on the text + segment size of the executable, or continue to use the default. */ + tb_size = (unsigned long)(ram_size / 4); +#endif + } + if (tb_size < MIN_CODE_GEN_BUFFER_SIZE) { + tb_size = MIN_CODE_GEN_BUFFER_SIZE; + } + if (tb_size > MAX_CODE_GEN_BUFFER_SIZE) { + tb_size = MAX_CODE_GEN_BUFFER_SIZE; + } + code_gen_buffer_size = tb_size; + return tb_size; +} + +#ifdef USE_STATIC_CODE_GEN_BUFFER +static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE] + __attribute__((aligned(CODE_GEN_ALIGN))); + +static inline void *alloc_code_gen_buffer(void) +{ + map_exec(static_code_gen_buffer, code_gen_buffer_size); + return static_code_gen_buffer; +} +#elif defined(USE_MMAP) +static inline void *alloc_code_gen_buffer(void) +{ + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + uintptr_t start = 0; + void *buf; + + /* Constrain the position of the buffer based on the host cpu. + Note that these addresses are chosen in concert with the + addresses assigned in the relevant linker script file. */ +# if defined(__PIE__) || defined(__PIC__) + /* Don't bother setting a preferred location if we're building + a position-independent executable. We're more likely to get + an address near the main executable if we let the kernel + choose the address. */ +# elif defined(__x86_64__) && defined(MAP_32BIT) + /* Force the memory down into low memory with the executable. + Leave the choice of exact location with the kernel. */ + flags |= MAP_32BIT; + /* Cannot expect to map more than 800MB in low memory. */ + if (code_gen_buffer_size > 800u * 1024 * 1024) { + code_gen_buffer_size = 800u * 1024 * 1024; + } +# elif defined(__sparc__) + start = 0x40000000ul; +# elif defined(__s390x__) + start = 0x90000000ul; +# endif + + buf = mmap((void *)start, code_gen_buffer_size, + PROT_WRITE | PROT_READ | PROT_EXEC, flags, -1, 0); + return buf == MAP_FAILED ? NULL : buf; +} +#else +static inline void *alloc_code_gen_buffer(void) +{ + void *buf = g_malloc(code_gen_buffer_size); + + if (buf) { + map_exec(buf, code_gen_buffer_size); + } + return buf; +} +#endif /* USE_STATIC_CODE_GEN_BUFFER, USE_MMAP */ + +static inline void code_gen_alloc(size_t tb_size) +{ + code_gen_buffer_size = size_code_gen_buffer(tb_size); + code_gen_buffer = alloc_code_gen_buffer(); + if (code_gen_buffer == NULL) { + fprintf(stderr, "Could not allocate dynamic translator buffer\n"); + exit(1); + } + + qemu_madvise(code_gen_buffer, code_gen_buffer_size, QEMU_MADV_HUGEPAGE); + + /* Steal room for the prologue at the end of the buffer. This ensures + (via the MAX_CODE_GEN_BUFFER_SIZE limits above) that direct branches + from TB's to the prologue are going to be in range. It also means + that we don't need to mark (additional) portions of the data segment + as executable. */ + code_gen_prologue = code_gen_buffer + code_gen_buffer_size - 1024; + code_gen_buffer_size -= 1024; + + code_gen_buffer_max_size = code_gen_buffer_size - + (TCG_MAX_OP_SIZE * OPC_BUF_SIZE); + code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE; + tbs = g_malloc(code_gen_max_blocks * sizeof(TranslationBlock)); +} + +/* Must be called before using the QEMU cpus. 'tb_size' is the size + (in bytes) allocated to the translation buffer. Zero means default + size. */ +void tcg_exec_init(unsigned long tb_size) +{ + cpu_gen_init(); + code_gen_alloc(tb_size); + code_gen_ptr = code_gen_buffer; + tcg_register_jit(code_gen_buffer, code_gen_buffer_size); + page_init(); +#if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE) + /* There's no guest base to take into account, so go ahead and + initialize the prologue now. */ + tcg_prologue_init(&tcg_ctx); +#endif +} + +bool tcg_enabled(void) +{ + return code_gen_buffer != NULL; +} + +/* Allocate a new translation block. Flush the translation buffer if + too many translation blocks or too much generated code. */ +static TranslationBlock *tb_alloc(target_ulong pc) +{ + TranslationBlock *tb; + + if (nb_tbs >= code_gen_max_blocks || + (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size) { + return NULL; + } + tb = &tbs[nb_tbs++]; + tb->pc = pc; + tb->cflags = 0; + return tb; +} + +void tb_free(TranslationBlock *tb) +{ + /* In practice this is mostly used for single use temporary TB + Ignore the hard cases and just back up if this TB happens to + be the last one generated. */ + if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) { + code_gen_ptr = tb->tc_ptr; + nb_tbs--; + } +} + +static inline void invalidate_page_bitmap(PageDesc *p) +{ + if (p->code_bitmap) { + g_free(p->code_bitmap); + p->code_bitmap = NULL; + } + p->code_write_count = 0; +} + +/* Set to NULL all the 'first_tb' fields in all PageDescs. */ +static void page_flush_tb_1(int level, void **lp) +{ + int i; + + if (*lp == NULL) { + return; + } + if (level == 0) { + PageDesc *pd = *lp; + + for (i = 0; i < L2_SIZE; ++i) { + pd[i].first_tb = NULL; + invalidate_page_bitmap(pd + i); + } + } else { + void **pp = *lp; + + for (i = 0; i < L2_SIZE; ++i) { + page_flush_tb_1(level - 1, pp + i); + } + } +} + +static void page_flush_tb(void) +{ + int i; + + for (i = 0; i < V_L1_SIZE; i++) { + page_flush_tb_1(V_L1_SHIFT / L2_BITS - 1, l1_map + i); + } +} + +/* flush all the translation blocks */ +/* XXX: tb_flush is currently not thread safe */ +void tb_flush(CPUArchState *env1) +{ + CPUArchState *env; + +#if defined(DEBUG_FLUSH) + printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n", + (unsigned long)(code_gen_ptr - code_gen_buffer), + nb_tbs, nb_tbs > 0 ? + ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0); +#endif + if ((unsigned long)(code_gen_ptr - code_gen_buffer) + > code_gen_buffer_size) { + cpu_abort(env1, "Internal error: code buffer overflow\n"); + } + nb_tbs = 0; + + for (env = first_cpu; env != NULL; env = env->next_cpu) { + memset(env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof(void *)); + } + + memset(tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof(void *)); + page_flush_tb(); + + code_gen_ptr = code_gen_buffer; + /* XXX: flush processor icache at this point if cache flush is + expensive */ + tb_flush_count++; +} + +#ifdef DEBUG_TB_CHECK + +static void tb_invalidate_check(target_ulong address) +{ + TranslationBlock *tb; + int i; + + address &= TARGET_PAGE_MASK; + for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) { + for (tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) { + if (!(address + TARGET_PAGE_SIZE <= tb->pc || + address >= tb->pc + tb->size)) { + printf("ERROR invalidate: address=" TARGET_FMT_lx + " PC=%08lx size=%04x\n", + address, (long)tb->pc, tb->size); + } + } + } +} + +/* verify that all the pages have correct rights for code */ +static void tb_page_check(void) +{ + TranslationBlock *tb; + int i, flags1, flags2; + + for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) { + for (tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) { + flags1 = page_get_flags(tb->pc); + flags2 = page_get_flags(tb->pc + tb->size - 1); + if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) { + printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n", + (long)tb->pc, tb->size, flags1, flags2); + } + } + } +} + +#endif + +/* invalidate one TB */ +static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb, + int next_offset) +{ + TranslationBlock *tb1; + + for (;;) { + tb1 = *ptb; + if (tb1 == tb) { + *ptb = *(TranslationBlock **)((char *)tb1 + next_offset); + break; + } + ptb = (TranslationBlock **)((char *)tb1 + next_offset); + } +} + +static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb) +{ + TranslationBlock *tb1; + unsigned int n1; + + for (;;) { + tb1 = *ptb; + n1 = (uintptr_t)tb1 & 3; + tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); + if (tb1 == tb) { + *ptb = tb1->page_next[n1]; + break; + } + ptb = &tb1->page_next[n1]; + } +} + +static inline void tb_jmp_remove(TranslationBlock *tb, int n) +{ + TranslationBlock *tb1, **ptb; + unsigned int n1; + + ptb = &tb->jmp_next[n]; + tb1 = *ptb; + if (tb1) { + /* find tb(n) in circular list */ + for (;;) { + tb1 = *ptb; + n1 = (uintptr_t)tb1 & 3; + tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); + if (n1 == n && tb1 == tb) { + break; + } + if (n1 == 2) { + ptb = &tb1->jmp_first; + } else { + ptb = &tb1->jmp_next[n1]; + } + } + /* now we can suppress tb(n) from the list */ + *ptb = tb->jmp_next[n]; + + tb->jmp_next[n] = NULL; + } +} + +/* reset the jump entry 'n' of a TB so that it is not chained to + another TB */ +static inline void tb_reset_jump(TranslationBlock *tb, int n) +{ + tb_set_jmp_target(tb, n, (uintptr_t)(tb->tc_ptr + tb->tb_next_offset[n])); +} + +void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) +{ + CPUArchState *env; + PageDesc *p; + unsigned int h, n1; + tb_page_addr_t phys_pc; + TranslationBlock *tb1, *tb2; + + /* remove the TB from the hash list */ + phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK); + h = tb_phys_hash_func(phys_pc); + tb_remove(&tb_phys_hash[h], tb, + offsetof(TranslationBlock, phys_hash_next)); + + /* remove the TB from the page list */ + if (tb->page_addr[0] != page_addr) { + p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS); + tb_page_remove(&p->first_tb, tb); + invalidate_page_bitmap(p); + } + if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) { + p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS); + tb_page_remove(&p->first_tb, tb); + invalidate_page_bitmap(p); + } + + tb_invalidated_flag = 1; + + /* remove the TB from the hash list */ + h = tb_jmp_cache_hash_func(tb->pc); + for (env = first_cpu; env != NULL; env = env->next_cpu) { + if (env->tb_jmp_cache[h] == tb) { + env->tb_jmp_cache[h] = NULL; + } + } + + /* suppress this TB from the two jump lists */ + tb_jmp_remove(tb, 0); + tb_jmp_remove(tb, 1); + + /* suppress any remaining jumps to this TB */ + tb1 = tb->jmp_first; + for (;;) { + n1 = (uintptr_t)tb1 & 3; + if (n1 == 2) { + break; + } + tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); + tb2 = tb1->jmp_next[n1]; + tb_reset_jump(tb1, n1); + tb1->jmp_next[n1] = NULL; + tb1 = tb2; + } + tb->jmp_first = (TranslationBlock *)((uintptr_t)tb | 2); /* fail safe */ + + tb_phys_invalidate_count++; +} + +static inline void set_bits(uint8_t *tab, int start, int len) +{ + int end, mask, end1; + + end = start + len; + tab += start >> 3; + mask = 0xff << (start & 7); + if ((start & ~7) == (end & ~7)) { + if (start < end) { + mask &= ~(0xff << (end & 7)); + *tab |= mask; + } + } else { + *tab++ |= mask; + start = (start + 8) & ~7; + end1 = end & ~7; + while (start < end1) { + *tab++ = 0xff; + start += 8; + } + if (start < end) { + mask = ~(0xff << (end & 7)); + *tab |= mask; + } + } +} + +static void build_page_bitmap(PageDesc *p) +{ + int n, tb_start, tb_end; + TranslationBlock *tb; + + p->code_bitmap = g_malloc0(TARGET_PAGE_SIZE / 8); + + tb = p->first_tb; + while (tb != NULL) { + n = (uintptr_t)tb & 3; + tb = (TranslationBlock *)((uintptr_t)tb & ~3); + /* NOTE: this is subtle as a TB may span two physical pages */ + if (n == 0) { + /* NOTE: tb_end may be after the end of the page, but + it is not a problem */ + tb_start = tb->pc & ~TARGET_PAGE_MASK; + tb_end = tb_start + tb->size; + if (tb_end > TARGET_PAGE_SIZE) { + tb_end = TARGET_PAGE_SIZE; + } + } else { + tb_start = 0; + tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK); + } + set_bits(p->code_bitmap, tb_start, tb_end - tb_start); + tb = tb->page_next[n]; + } +} + +TranslationBlock *tb_gen_code(CPUArchState *env, + target_ulong pc, target_ulong cs_base, + int flags, int cflags) +{ + TranslationBlock *tb; + uint8_t *tc_ptr; + tb_page_addr_t phys_pc, phys_page2; + target_ulong virt_page2; + int code_gen_size; + + phys_pc = get_page_addr_code(env, pc); + tb = tb_alloc(pc); + if (!tb) { + /* flush must be done */ + tb_flush(env); + /* cannot fail at this point */ + tb = tb_alloc(pc); + /* Don't forget to invalidate previous TB info. */ + tb_invalidated_flag = 1; + } + tc_ptr = code_gen_ptr; + tb->tc_ptr = tc_ptr; + tb->cs_base = cs_base; + tb->flags = flags; + tb->cflags = cflags; + cpu_gen_code(env, tb, &code_gen_size); + code_gen_ptr = (void *)(((uintptr_t)code_gen_ptr + code_gen_size + + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); + + /* check next page if needed */ + virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK; + phys_page2 = -1; + if ((pc & TARGET_PAGE_MASK) != virt_page2) { + phys_page2 = get_page_addr_code(env, virt_page2); + } + tb_link_page(tb, phys_pc, phys_page2); + return tb; +} + +/* + * Invalidate all TBs which intersect with the target physical address range + * [start;end[. NOTE: start and end may refer to *different* physical pages. + * 'is_cpu_write_access' should be true if called from a real cpu write + * access: the virtual CPU will exit the current TB if code is modified inside + * this TB. + */ +void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end, + int is_cpu_write_access) +{ + while (start < end) { + tb_invalidate_phys_page_range(start, end, is_cpu_write_access); + start &= TARGET_PAGE_MASK; + start += TARGET_PAGE_SIZE; + } +} + +/* + * Invalidate all TBs which intersect with the target physical address range + * [start;end[. NOTE: start and end must refer to the *same* physical page. + * 'is_cpu_write_access' should be true if called from a real cpu write + * access: the virtual CPU will exit the current TB if code is modified inside + * this TB. + */ +void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, + int is_cpu_write_access) +{ + TranslationBlock *tb, *tb_next, *saved_tb; + CPUArchState *env = cpu_single_env; + tb_page_addr_t tb_start, tb_end; + PageDesc *p; + int n; +#ifdef TARGET_HAS_PRECISE_SMC + int current_tb_not_found = is_cpu_write_access; + TranslationBlock *current_tb = NULL; + int current_tb_modified = 0; + target_ulong current_pc = 0; + target_ulong current_cs_base = 0; + int current_flags = 0; +#endif /* TARGET_HAS_PRECISE_SMC */ + + p = page_find(start >> TARGET_PAGE_BITS); + if (!p) { + return; + } + if (!p->code_bitmap && + ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD && + is_cpu_write_access) { + /* build code bitmap */ + build_page_bitmap(p); + } + + /* we remove all the TBs in the range [start, end[ */ + /* XXX: see if in some cases it could be faster to invalidate all + the code */ + tb = p->first_tb; + while (tb != NULL) { + n = (uintptr_t)tb & 3; + tb = (TranslationBlock *)((uintptr_t)tb & ~3); + tb_next = tb->page_next[n]; + /* NOTE: this is subtle as a TB may span two physical pages */ + if (n == 0) { + /* NOTE: tb_end may be after the end of the page, but + it is not a problem */ + tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK); + tb_end = tb_start + tb->size; + } else { + tb_start = tb->page_addr[1]; + tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK); + } + if (!(tb_end <= start || tb_start >= end)) { +#ifdef TARGET_HAS_PRECISE_SMC + if (current_tb_not_found) { + current_tb_not_found = 0; + current_tb = NULL; + if (env->mem_io_pc) { + /* now we have a real cpu fault */ + current_tb = tb_find_pc(env->mem_io_pc); + } + } + if (current_tb == tb && + (current_tb->cflags & CF_COUNT_MASK) != 1) { + /* If we are modifying the current TB, we must stop + its execution. We could be more precise by checking + that the modification is after the current PC, but it + would require a specialized function to partially + restore the CPU state */ + + current_tb_modified = 1; + cpu_restore_state(current_tb, env, env->mem_io_pc); + cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base, + ¤t_flags); + } +#endif /* TARGET_HAS_PRECISE_SMC */ + /* we need to do that to handle the case where a signal + occurs while doing tb_phys_invalidate() */ + saved_tb = NULL; + if (env) { + saved_tb = env->current_tb; + env->current_tb = NULL; + } + tb_phys_invalidate(tb, -1); + if (env) { + env->current_tb = saved_tb; + if (env->interrupt_request && env->current_tb) { + cpu_interrupt(env, env->interrupt_request); + } + } + } + tb = tb_next; + } +#if !defined(CONFIG_USER_ONLY) + /* if no code remaining, no need to continue to use slow writes */ + if (!p->first_tb) { + invalidate_page_bitmap(p); + if (is_cpu_write_access) { + tlb_unprotect_code_phys(env, start, env->mem_io_vaddr); + } + } +#endif +#ifdef TARGET_HAS_PRECISE_SMC + if (current_tb_modified) { + /* we generate a block containing just the instruction + modifying the memory. It will ensure that it cannot modify + itself */ + env->current_tb = NULL; + tb_gen_code(env, current_pc, current_cs_base, current_flags, 1); + cpu_resume_from_signal(env, NULL); + } +#endif +} + +/* len must be <= 8 and start must be a multiple of len */ +void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len) +{ + PageDesc *p; + int offset, b; + +#if 0 + if (1) { + qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n", + cpu_single_env->mem_io_vaddr, len, + cpu_single_env->eip, + cpu_single_env->eip + + (intptr_t)cpu_single_env->segs[R_CS].base); + } +#endif + p = page_find(start >> TARGET_PAGE_BITS); + if (!p) { + return; + } + if (p->code_bitmap) { + offset = start & ~TARGET_PAGE_MASK; + b = p->code_bitmap[offset >> 3] >> (offset & 7); + if (b & ((1 << len) - 1)) { + goto do_invalidate; + } + } else { + do_invalidate: + tb_invalidate_phys_page_range(start, start + len, 1); + } +} + +#if !defined(CONFIG_SOFTMMU) +static void tb_invalidate_phys_page(tb_page_addr_t addr, + uintptr_t pc, void *puc) +{ + TranslationBlock *tb; + PageDesc *p; + int n; +#ifdef TARGET_HAS_PRECISE_SMC + TranslationBlock *current_tb = NULL; + CPUArchState *env = cpu_single_env; + int current_tb_modified = 0; + target_ulong current_pc = 0; + target_ulong current_cs_base = 0; + int current_flags = 0; +#endif + + addr &= TARGET_PAGE_MASK; + p = page_find(addr >> TARGET_PAGE_BITS); + if (!p) { + return; + } + tb = p->first_tb; +#ifdef TARGET_HAS_PRECISE_SMC + if (tb && pc != 0) { + current_tb = tb_find_pc(pc); + } +#endif + while (tb != NULL) { + n = (uintptr_t)tb & 3; + tb = (TranslationBlock *)((uintptr_t)tb & ~3); +#ifdef TARGET_HAS_PRECISE_SMC + if (current_tb == tb && + (current_tb->cflags & CF_COUNT_MASK) != 1) { + /* If we are modifying the current TB, we must stop + its execution. We could be more precise by checking + that the modification is after the current PC, but it + would require a specialized function to partially + restore the CPU state */ + + current_tb_modified = 1; + cpu_restore_state(current_tb, env, pc); + cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base, + ¤t_flags); + } +#endif /* TARGET_HAS_PRECISE_SMC */ + tb_phys_invalidate(tb, addr); + tb = tb->page_next[n]; + } + p->first_tb = NULL; +#ifdef TARGET_HAS_PRECISE_SMC + if (current_tb_modified) { + /* we generate a block containing just the instruction + modifying the memory. It will ensure that it cannot modify + itself */ + env->current_tb = NULL; + tb_gen_code(env, current_pc, current_cs_base, current_flags, 1); + cpu_resume_from_signal(env, puc); + } +#endif +} +#endif + +/* add the tb in the target page and protect it if necessary */ +static inline void tb_alloc_page(TranslationBlock *tb, + unsigned int n, tb_page_addr_t page_addr) +{ + PageDesc *p; +#ifndef CONFIG_USER_ONLY + bool page_already_protected; +#endif + + tb->page_addr[n] = page_addr; + p = page_find_alloc(page_addr >> TARGET_PAGE_BITS, 1); + tb->page_next[n] = p->first_tb; +#ifndef CONFIG_USER_ONLY + page_already_protected = p->first_tb != NULL; +#endif + p->first_tb = (TranslationBlock *)((uintptr_t)tb | n); + invalidate_page_bitmap(p); + +#if defined(TARGET_HAS_SMC) || 1 + +#if defined(CONFIG_USER_ONLY) + if (p->flags & PAGE_WRITE) { + target_ulong addr; + PageDesc *p2; + int prot; + + /* force the host page as non writable (writes will have a + page fault + mprotect overhead) */ + page_addr &= qemu_host_page_mask; + prot = 0; + for (addr = page_addr; addr < page_addr + qemu_host_page_size; + addr += TARGET_PAGE_SIZE) { + + p2 = page_find(addr >> TARGET_PAGE_BITS); + if (!p2) { + continue; + } + prot |= p2->flags; + p2->flags &= ~PAGE_WRITE; + } + mprotect(g2h(page_addr), qemu_host_page_size, + (prot & PAGE_BITS) & ~PAGE_WRITE); +#ifdef DEBUG_TB_INVALIDATE + printf("protecting code page: 0x" TARGET_FMT_lx "\n", + page_addr); +#endif + } +#else + /* if some code is already present, then the pages are already + protected. So we handle the case where only the first TB is + allocated in a physical page */ + if (!page_already_protected) { + tlb_protect_code(page_addr); + } +#endif + +#endif /* TARGET_HAS_SMC */ +} + +/* add a new TB and link it to the physical page tables. phys_page2 is + (-1) to indicate that only one page contains the TB. */ +static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, + tb_page_addr_t phys_page2) +{ + unsigned int h; + TranslationBlock **ptb; + + /* Grab the mmap lock to stop another thread invalidating this TB + before we are done. */ + mmap_lock(); + /* add in the physical hash table */ + h = tb_phys_hash_func(phys_pc); + ptb = &tb_phys_hash[h]; + tb->phys_hash_next = *ptb; + *ptb = tb; + + /* add in the page list */ + tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK); + if (phys_page2 != -1) { + tb_alloc_page(tb, 1, phys_page2); + } else { + tb->page_addr[1] = -1; + } + + tb->jmp_first = (TranslationBlock *)((uintptr_t)tb | 2); + tb->jmp_next[0] = NULL; + tb->jmp_next[1] = NULL; + + /* init original jump addresses */ + if (tb->tb_next_offset[0] != 0xffff) { + tb_reset_jump(tb, 0); + } + if (tb->tb_next_offset[1] != 0xffff) { + tb_reset_jump(tb, 1); + } + +#ifdef DEBUG_TB_CHECK + tb_page_check(); +#endif + mmap_unlock(); +} + +#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU) +/* check whether the given addr is in TCG generated code buffer or not */ +bool is_tcg_gen_code(uintptr_t tc_ptr) +{ + /* This can be called during code generation, code_gen_buffer_max_size + is used instead of code_gen_ptr for upper boundary checking */ + return (tc_ptr >= (uintptr_t)code_gen_buffer && + tc_ptr < (uintptr_t)(code_gen_buffer + code_gen_buffer_max_size)); +} +#endif + +/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr < + tb[1].tc_ptr. Return NULL if not found */ +TranslationBlock *tb_find_pc(uintptr_t tc_ptr) +{ + int m_min, m_max, m; + uintptr_t v; + TranslationBlock *tb; + + if (nb_tbs <= 0) { + return NULL; + } + if (tc_ptr < (uintptr_t)code_gen_buffer || + tc_ptr >= (uintptr_t)code_gen_ptr) { + return NULL; + } + /* binary search (cf Knuth) */ + m_min = 0; + m_max = nb_tbs - 1; + while (m_min <= m_max) { + m = (m_min + m_max) >> 1; + tb = &tbs[m]; + v = (uintptr_t)tb->tc_ptr; + if (v == tc_ptr) { + return tb; + } else if (tc_ptr < v) { + m_max = m - 1; + } else { + m_min = m + 1; + } + } + return &tbs[m_max]; +} + +static void tb_reset_jump_recursive(TranslationBlock *tb); + +static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n) +{ + TranslationBlock *tb1, *tb_next, **ptb; + unsigned int n1; + + tb1 = tb->jmp_next[n]; + if (tb1 != NULL) { + /* find head of list */ + for (;;) { + n1 = (uintptr_t)tb1 & 3; + tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); + if (n1 == 2) { + break; + } + tb1 = tb1->jmp_next[n1]; + } + /* we are now sure now that tb jumps to tb1 */ + tb_next = tb1; + + /* remove tb from the jmp_first list */ + ptb = &tb_next->jmp_first; + for (;;) { + tb1 = *ptb; + n1 = (uintptr_t)tb1 & 3; + tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); + if (n1 == n && tb1 == tb) { + break; + } + ptb = &tb1->jmp_next[n1]; + } + *ptb = tb->jmp_next[n]; + tb->jmp_next[n] = NULL; + + /* suppress the jump to next tb in generated code */ + tb_reset_jump(tb, n); + + /* suppress jumps in the tb on which we could have jumped */ + tb_reset_jump_recursive(tb_next); + } +} + +static void tb_reset_jump_recursive(TranslationBlock *tb) +{ + tb_reset_jump_recursive2(tb, 0); + tb_reset_jump_recursive2(tb, 1); +} + +#if defined(TARGET_HAS_ICE) && !defined(CONFIG_USER_ONLY) +void tb_invalidate_phys_addr(hwaddr addr) +{ + ram_addr_t ram_addr; + MemoryRegionSection *section; + + 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))) { + return; + } + ram_addr = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK) + + memory_region_section_addr(section, addr); + tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0); +} +#endif /* TARGET_HAS_ICE && !defined(CONFIG_USER_ONLY) */ + +void cpu_unlink_tb(CPUArchState *env) +{ + /* FIXME: TB unchaining isn't SMP safe. For now just ignore the + problem and hope the cpu will stop of its own accord. For userspace + emulation this often isn't actually as bad as it sounds. Often + signals are used primarily to interrupt blocking syscalls. */ + TranslationBlock *tb; + static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED; + + spin_lock(&interrupt_lock); + tb = env->current_tb; + /* if the cpu is currently executing code, we must unlink it and + all the potentially executing TB */ + if (tb) { + env->current_tb = NULL; + tb_reset_jump_recursive(tb); + } + spin_unlock(&interrupt_lock); +} + +void tb_check_watchpoint(CPUArchState *env) +{ + TranslationBlock *tb; + + tb = tb_find_pc(env->mem_io_pc); + if (!tb) { + cpu_abort(env, "check_watchpoint: could not find TB for pc=%p", + (void *)env->mem_io_pc); + } + cpu_restore_state(tb, env, env->mem_io_pc); + tb_phys_invalidate(tb, -1); +} + +#ifndef CONFIG_USER_ONLY +/* mask must never be zero, except for A20 change call */ +static void tcg_handle_interrupt(CPUArchState *env, int mask) +{ + CPUState *cpu = ENV_GET_CPU(env); + int old_mask; + + old_mask = env->interrupt_request; + env->interrupt_request |= mask; + + /* + * If called from iothread context, wake the target cpu in + * case its halted. + */ + if (!qemu_cpu_is_self(cpu)) { + qemu_cpu_kick(cpu); + return; + } + + if (use_icount) { + env->icount_decr.u16.high = 0xffff; + if (!can_do_io(env) + && (mask & ~old_mask) != 0) { + cpu_abort(env, "Raised interrupt while not in I/O function"); + } + } else { + cpu_unlink_tb(env); + } +} + +CPUInterruptHandler cpu_interrupt_handler = tcg_handle_interrupt; + +/* in deterministic execution mode, instructions doing device I/Os + must be at the end of the TB */ +void cpu_io_recompile(CPUArchState *env, uintptr_t retaddr) +{ + TranslationBlock *tb; + uint32_t n, cflags; + target_ulong pc, cs_base; + uint64_t flags; + + tb = tb_find_pc(retaddr); + if (!tb) { + cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p", + (void *)retaddr); + } + n = env->icount_decr.u16.low + tb->icount; + cpu_restore_state(tb, env, retaddr); + /* Calculate how many instructions had been executed before the fault + occurred. */ + n = n - env->icount_decr.u16.low; + /* Generate a new TB ending on the I/O insn. */ + n++; + /* On MIPS and SH, delay slot instructions can only be restarted if + they were already the first instruction in the TB. If this is not + the first instruction in a TB then re-execute the preceding + branch. */ +#if defined(TARGET_MIPS) + if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) { + env->active_tc.PC -= 4; + env->icount_decr.u16.low++; + env->hflags &= ~MIPS_HFLAG_BMASK; + } +#elif defined(TARGET_SH4) + if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0 + && n > 1) { + env->pc -= 2; + env->icount_decr.u16.low++; + env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL); + } +#endif + /* This should never happen. */ + if (n > CF_COUNT_MASK) { + cpu_abort(env, "TB too big during recompile"); + } + + cflags = n | CF_LAST_IO; + pc = tb->pc; + cs_base = tb->cs_base; + flags = tb->flags; + tb_phys_invalidate(tb, -1); + /* FIXME: In theory this could raise an exception. In practice + we have already translated the block once so it's probably ok. */ + tb_gen_code(env, pc, cs_base, flags, cflags); + /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not + the first in the TB) then we end up generating a whole new TB and + repeating the fault, which is horribly inefficient. + Better would be to execute just this insn uncached, or generate a + second new TB. */ + cpu_resume_from_signal(env, NULL); +} + +void tb_flush_jmp_cache(CPUArchState *env, target_ulong addr) +{ + unsigned int i; + + /* Discard jump cache entries for any tb which might potentially + overlap the flushed page. */ + i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE); + memset(&env->tb_jmp_cache[i], 0, + TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *)); + + i = tb_jmp_cache_hash_page(addr); + memset(&env->tb_jmp_cache[i], 0, + TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *)); +} + +void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) +{ + int i, target_code_size, max_target_code_size; + int direct_jmp_count, direct_jmp2_count, cross_page; + TranslationBlock *tb; + + target_code_size = 0; + max_target_code_size = 0; + cross_page = 0; + direct_jmp_count = 0; + direct_jmp2_count = 0; + for (i = 0; i < nb_tbs; i++) { + tb = &tbs[i]; + target_code_size += tb->size; + if (tb->size > max_target_code_size) { + max_target_code_size = tb->size; + } + if (tb->page_addr[1] != -1) { + cross_page++; + } + if (tb->tb_next_offset[0] != 0xffff) { + direct_jmp_count++; + if (tb->tb_next_offset[1] != 0xffff) { + direct_jmp2_count++; + } + } + } + /* XXX: avoid using doubles ? */ + cpu_fprintf(f, "Translation buffer state:\n"); + cpu_fprintf(f, "gen code size %td/%zd\n", + code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size); + cpu_fprintf(f, "TB count %d/%d\n", + nb_tbs, code_gen_max_blocks); + cpu_fprintf(f, "TB avg target size %d max=%d bytes\n", + nb_tbs ? target_code_size / nb_tbs : 0, + max_target_code_size); + cpu_fprintf(f, "TB avg host size %td bytes (expansion ratio: %0.1f)\n", + nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0, + target_code_size ? (double) (code_gen_ptr - code_gen_buffer) + / target_code_size : 0); + cpu_fprintf(f, "cross page TB count %d (%d%%)\n", + cross_page, + nb_tbs ? (cross_page * 100) / nb_tbs : 0); + cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n", + direct_jmp_count, + nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0, + direct_jmp2_count, + nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0); + cpu_fprintf(f, "\nStatistics:\n"); + cpu_fprintf(f, "TB flush count %d\n", tb_flush_count); + cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count); + cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count); + tcg_dump_info(f, cpu_fprintf); +} + +#else /* CONFIG_USER_ONLY */ + +void cpu_interrupt(CPUArchState *env, int mask) +{ + env->interrupt_request |= mask; + cpu_unlink_tb(env); +} + +/* + * Walks guest process memory "regions" one by one + * and calls callback function 'fn' for each region. + */ +struct walk_memory_regions_data { + walk_memory_regions_fn fn; + void *priv; + uintptr_t start; + int prot; +}; + +static int walk_memory_regions_end(struct walk_memory_regions_data *data, + abi_ulong end, int new_prot) +{ + if (data->start != -1ul) { + int rc = data->fn(data->priv, data->start, end, data->prot); + if (rc != 0) { + return rc; + } + } + + data->start = (new_prot ? end : -1ul); + data->prot = new_prot; + + return 0; +} + +static int walk_memory_regions_1(struct walk_memory_regions_data *data, + abi_ulong base, int level, void **lp) +{ + abi_ulong pa; + int i, rc; + + if (*lp == NULL) { + return walk_memory_regions_end(data, base, 0); + } + + if (level == 0) { + PageDesc *pd = *lp; + + for (i = 0; i < L2_SIZE; ++i) { + int prot = pd[i].flags; + + pa = base | (i << TARGET_PAGE_BITS); + if (prot != data->prot) { + rc = walk_memory_regions_end(data, pa, prot); + if (rc != 0) { + return rc; + } + } + } + } else { + void **pp = *lp; + + for (i = 0; i < L2_SIZE; ++i) { + pa = base | ((abi_ulong)i << + (TARGET_PAGE_BITS + L2_BITS * level)); + rc = walk_memory_regions_1(data, pa, level - 1, pp + i); + if (rc != 0) { + return rc; + } + } + } + + return 0; +} + +int walk_memory_regions(void *priv, walk_memory_regions_fn fn) +{ + struct walk_memory_regions_data data; + uintptr_t i; + + data.fn = fn; + data.priv = priv; + data.start = -1ul; + data.prot = 0; + + for (i = 0; i < V_L1_SIZE; i++) { + int rc = walk_memory_regions_1(&data, (abi_ulong)i << V_L1_SHIFT, + V_L1_SHIFT / L2_BITS - 1, l1_map + i); + + if (rc != 0) { + return rc; + } + } + + return walk_memory_regions_end(&data, 0, 0); +} + +static int dump_region(void *priv, abi_ulong start, + abi_ulong end, unsigned long prot) +{ + FILE *f = (FILE *)priv; + + (void) fprintf(f, TARGET_ABI_FMT_lx"-"TARGET_ABI_FMT_lx + " "TARGET_ABI_FMT_lx" %c%c%c\n", + start, end, end - start, + ((prot & PAGE_READ) ? 'r' : '-'), + ((prot & PAGE_WRITE) ? 'w' : '-'), + ((prot & PAGE_EXEC) ? 'x' : '-')); + + return 0; +} + +/* dump memory mappings */ +void page_dump(FILE *f) +{ + (void) fprintf(f, "%-8s %-8s %-8s %s\n", + "start", "end", "size", "prot"); + walk_memory_regions(f, dump_region); +} + +int page_get_flags(target_ulong address) +{ + PageDesc *p; + + p = page_find(address >> TARGET_PAGE_BITS); + if (!p) { + return 0; + } + return p->flags; +} + +/* Modify the flags of a page and invalidate the code if necessary. + The flag PAGE_WRITE_ORG is positioned automatically depending + on PAGE_WRITE. The mmap_lock should already be held. */ +void page_set_flags(target_ulong start, target_ulong end, int flags) +{ + target_ulong addr, len; + + /* This function should never be called with addresses outside the + guest address space. If this assert fires, it probably indicates + a missing call to h2g_valid. */ +#if TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS + assert(end < ((abi_ulong)1 << L1_MAP_ADDR_SPACE_BITS)); +#endif + assert(start < end); + + start = start & TARGET_PAGE_MASK; + end = TARGET_PAGE_ALIGN(end); + + if (flags & PAGE_WRITE) { + flags |= PAGE_WRITE_ORG; + } + + for (addr = start, len = end - start; + len != 0; + len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) { + PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, 1); + + /* If the write protection bit is set, then we invalidate + the code inside. */ + if (!(p->flags & PAGE_WRITE) && + (flags & PAGE_WRITE) && + p->first_tb) { + tb_invalidate_phys_page(addr, 0, NULL); + } + p->flags = flags; + } +} + +int page_check_range(target_ulong start, target_ulong len, int flags) +{ + PageDesc *p; + target_ulong end; + target_ulong addr; + + /* This function should never be called with addresses outside the + guest address space. If this assert fires, it probably indicates + a missing call to h2g_valid. */ +#if TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS + assert(start < ((abi_ulong)1 << L1_MAP_ADDR_SPACE_BITS)); +#endif + + if (len == 0) { + return 0; + } + if (start + len - 1 < start) { + /* We've wrapped around. */ + return -1; + } + + /* must do before we loose bits in the next step */ + end = TARGET_PAGE_ALIGN(start + len); + start = start & TARGET_PAGE_MASK; + + for (addr = start, len = end - start; + len != 0; + len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) { + p = page_find(addr >> TARGET_PAGE_BITS); + if (!p) { + return -1; + } + if (!(p->flags & PAGE_VALID)) { + return -1; + } + + if ((flags & PAGE_READ) && !(p->flags & PAGE_READ)) { + return -1; + } + if (flags & PAGE_WRITE) { + if (!(p->flags & PAGE_WRITE_ORG)) { + return -1; + } + /* unprotect the page if it was put read-only because it + contains translated code */ + if (!(p->flags & PAGE_WRITE)) { + if (!page_unprotect(addr, 0, NULL)) { + return -1; + } + } + return 0; + } + } + return 0; +} + +/* called from signal handler: invalidate the code and unprotect the + page. Return TRUE if the fault was successfully handled. */ +int page_unprotect(target_ulong address, uintptr_t pc, void *puc) +{ + unsigned int prot; + PageDesc *p; + target_ulong host_start, host_end, addr; + + /* Technically this isn't safe inside a signal handler. However we + know this only ever happens in a synchronous SEGV handler, so in + practice it seems to be ok. */ + mmap_lock(); + + p = page_find(address >> TARGET_PAGE_BITS); + if (!p) { + mmap_unlock(); + return 0; + } + + /* if the page was really writable, then we change its + protection back to writable */ + if ((p->flags & PAGE_WRITE_ORG) && !(p->flags & PAGE_WRITE)) { + host_start = address & qemu_host_page_mask; + host_end = host_start + qemu_host_page_size; + + prot = 0; + for (addr = host_start ; addr < host_end ; addr += TARGET_PAGE_SIZE) { + p = page_find(addr >> TARGET_PAGE_BITS); + p->flags |= PAGE_WRITE; + prot |= p->flags; + + /* and since the content will be modified, we must invalidate + the corresponding translated code. */ + tb_invalidate_phys_page(addr, pc, puc); +#ifdef DEBUG_TB_CHECK + tb_invalidate_check(addr); +#endif + } + mprotect((void *)g2h(host_start), qemu_host_page_size, + prot & PAGE_BITS); + + mmap_unlock(); + return 1; + } + mmap_unlock(); + return 0; +} +#endif /* CONFIG_USER_ONLY */ diff --git a/translate-all.h b/translate-all.h new file mode 100644 index 0000000000..b181fb48ad --- /dev/null +++ b/translate-all.h @@ -0,0 +1,34 @@ +/* + * Translated block handling + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#ifndef TRANSLATE_ALL_H +#define TRANSLATE_ALL_H + +/* Size of the L2 (and L3, etc) page tables. */ +#define L2_BITS 10 +#define L2_SIZE (1 << L2_BITS) + +#define P_L2_LEVELS \ + (((TARGET_PHYS_ADDR_SPACE_BITS - TARGET_PAGE_BITS - 1) / L2_BITS) + 1) + +/* translate-all.c */ +void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len); +void cpu_unlink_tb(CPUArchState *env); +void tb_check_watchpoint(CPUArchState *env); + +#endif /* TRANSLATE_ALL_H */ From a8a826a3c3b8c8a1c4def0e9e22b46e78e6163a0 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Tue, 4 Dec 2012 20:16:07 +0000 Subject: [PATCH 1999/2270] exec: refactor cpu_restore_state Refactor common code around calls to cpu_restore_state(). tb_find_pc() has now no external users, make it static. Signed-off-by: Blue Swirl --- exec-all.h | 6 ++---- hw/kvmvapic.c | 4 +--- target-alpha/helper.c | 14 +++----------- target-alpha/mem_helper.c | 8 ++++++-- target-arm/op_helper.c | 8 +------- target-cris/op_helper.c | 8 +------- target-i386/helper.c | 5 +---- target-i386/mem_helper.c | 8 +------- target-lm32/op_helper.c | 8 +------- target-m68k/op_helper.c | 8 +------- target-microblaze/op_helper.c | 8 +------- target-mips/op_helper.c | 8 +------- target-openrisc/mmu_helper.c | 10 +--------- target-ppc/mem_helper.c | 8 +------- target-s390x/mem_helper.c | 8 +------- target-sh4/op_helper.c | 23 ++++++----------------- target-sparc/cpu.h | 1 - target-sparc/helper.c | 12 ++++++------ target-sparc/ldst_helper.c | 24 ++++++------------------ target-unicore32/op_helper.c | 9 +-------- target-xtensa/op_helper.c | 14 ++------------ translate-all.c | 27 ++++++++++++++++++++------- user-exec.c | 8 +------- 23 files changed, 65 insertions(+), 172 deletions(-) diff --git a/exec-all.h b/exec-all.h index b18d4ca534..e9b07cd986 100644 --- a/exec-all.h +++ b/exec-all.h @@ -80,8 +80,8 @@ void restore_state_to_opc(CPUArchState *env, struct TranslationBlock *tb, void cpu_gen_init(void); int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb, int *gen_code_size_ptr); -int cpu_restore_state(struct TranslationBlock *tb, - CPUArchState *env, uintptr_t searched_pc); +bool cpu_restore_state(CPUArchState *env, uintptr_t searched_pc); + void QEMU_NORETURN cpu_resume_from_signal(CPUArchState *env1, void *puc); void QEMU_NORETURN cpu_io_recompile(CPUArchState *env, uintptr_t retaddr); TranslationBlock *tb_gen_code(CPUArchState *env, @@ -275,8 +275,6 @@ static inline void tb_add_jump(TranslationBlock *tb, int n, } } -TranslationBlock *tb_find_pc(uintptr_t pc_ptr); - #include "qemu-lock.h" extern spinlock_t tb_lock; diff --git a/hw/kvmvapic.c b/hw/kvmvapic.c index e04c4011d7..60c8fc46aa 100644 --- a/hw/kvmvapic.c +++ b/hw/kvmvapic.c @@ -387,7 +387,6 @@ static void patch_instruction(VAPICROMState *s, CPUX86State *env, target_ulong i VAPICHandlers *handlers; uint8_t opcode[2]; uint32_t imm32; - TranslationBlock *current_tb; target_ulong current_pc = 0; target_ulong current_cs_base = 0; int current_flags = 0; @@ -399,8 +398,7 @@ static void patch_instruction(VAPICROMState *s, CPUX86State *env, target_ulong i } if (!kvm_enabled()) { - current_tb = tb_find_pc(env->mem_io_pc); - cpu_restore_state(current_tb, env, env->mem_io_pc); + cpu_restore_state(env, env->mem_io_pc); cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base, ¤t_flags); } diff --git a/target-alpha/helper.c b/target-alpha/helper.c index d9d7f75b58..2430f70aca 100644 --- a/target-alpha/helper.c +++ b/target-alpha/helper.c @@ -494,16 +494,6 @@ void cpu_dump_state (CPUAlphaState *env, FILE *f, fprintf_function cpu_fprintf, cpu_fprintf(f, "\n"); } -void do_restore_state(CPUAlphaState *env, uintptr_t retaddr) -{ - if (retaddr) { - TranslationBlock *tb = tb_find_pc(retaddr); - if (tb) { - cpu_restore_state(tb, env, retaddr); - } - } -} - /* This should only be called from translate, via gen_excp. We expect that ENV->PC has already been updated. */ void QEMU_NORETURN helper_excp(CPUAlphaState *env, int excp, int error) @@ -519,7 +509,9 @@ void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, uintptr_t retaddr, { env->exception_index = excp; env->error_code = error; - do_restore_state(env, retaddr); + if (retaddr) { + cpu_restore_state(env, retaddr); + } cpu_loop_exit(env); } diff --git a/target-alpha/mem_helper.c b/target-alpha/mem_helper.c index 617836cc6c..64b33f6518 100644 --- a/target-alpha/mem_helper.c +++ b/target-alpha/mem_helper.c @@ -94,7 +94,9 @@ static void do_unaligned_access(CPUAlphaState *env, target_ulong addr, uint64_t pc; uint32_t insn; - do_restore_state(env, retaddr); + if (retaddr) { + cpu_restore_state(env, retaddr); + } pc = env->pc; insn = cpu_ldl_code(env, pc); @@ -143,7 +145,9 @@ void tlb_fill(CPUAlphaState *env, target_ulong addr, int is_write, ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret != 0)) { - do_restore_state(env, retaddr); + if (retaddr) { + cpu_restore_state(env, retaddr); + } /* Exception index and error code are already set */ cpu_loop_exit(env); } diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 6e3ab90e3b..1fcc975945 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -74,19 +74,13 @@ uint32_t HELPER(neon_tbl)(CPUARMState *env, uint32_t ireg, uint32_t def, void tlb_fill(CPUARMState *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { - TranslationBlock *tb; int ret; ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ - tb = tb_find_pc(retaddr); - if (tb) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, retaddr); - } + cpu_restore_state(env, retaddr); } raise_exception(env, env->exception_index); } diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c index a7468d41c6..31db42494d 100644 --- a/target-cris/op_helper.c +++ b/target-cris/op_helper.c @@ -57,7 +57,6 @@ void tlb_fill(CPUCRISState *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { - TranslationBlock *tb; int ret; D_LOG("%s pc=%x tpc=%x ra=%p\n", __func__, @@ -66,12 +65,7 @@ void tlb_fill(CPUCRISState *env, target_ulong addr, int is_write, int mmu_idx, if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ - tb = tb_find_pc(retaddr); - if (tb) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, retaddr); - + if (cpu_restore_state(env, retaddr)) { /* Evaluate flags after retranslation. */ helper_top_evaluate_flags(env); } diff --git a/target-i386/helper.c b/target-i386/helper.c index bf206cfa97..00341c5233 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1196,15 +1196,12 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank, void cpu_report_tpr_access(CPUX86State *env, TPRAccess access) { - TranslationBlock *tb; - if (kvm_enabled()) { env->tpr_access_type = access; cpu_interrupt(env, CPU_INTERRUPT_TPR); } else { - tb = tb_find_pc(env->mem_io_pc); - cpu_restore_state(tb, env, env->mem_io_pc); + cpu_restore_state(env, env->mem_io_pc); apic_handle_tpr_access_report(env->apic_state, env->eip, access); } diff --git a/target-i386/mem_helper.c b/target-i386/mem_helper.c index 7f99c7cfe3..d0be77b1ed 100644 --- a/target-i386/mem_helper.c +++ b/target-i386/mem_helper.c @@ -135,19 +135,13 @@ void helper_boundl(CPUX86State *env, target_ulong a0, int v) void tlb_fill(CPUX86State *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { - TranslationBlock *tb; int ret; ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx); if (ret) { if (retaddr) { /* now we have a real cpu fault */ - tb = tb_find_pc(retaddr); - if (tb) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, retaddr); - } + cpu_restore_state(env, retaddr); } raise_exception_err(env, env->exception_index, env->error_code); } diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c index 7b91d8c31e..97b9625c1a 100644 --- a/target-lm32/op_helper.c +++ b/target-lm32/op_helper.c @@ -76,19 +76,13 @@ uint32_t helper_rcsr_jrx(CPULM32State *env) void tlb_fill(CPULM32State *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { - TranslationBlock *tb; int ret; ret = cpu_lm32_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ - tb = tb_find_pc(retaddr); - if (tb) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, retaddr); - } + cpu_restore_state(env, retaddr); } cpu_loop_exit(env); } diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c index aa005048e1..b97ba5e28f 100644 --- a/target-m68k/op_helper.c +++ b/target-m68k/op_helper.c @@ -56,19 +56,13 @@ extern int semihosting_enabled; void tlb_fill(CPUM68KState *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { - TranslationBlock *tb; int ret; ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ - tb = tb_find_pc(retaddr); - if (tb) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, retaddr); - } + cpu_restore_state(env, retaddr); } cpu_loop_exit(env); } diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c index 210296b30b..7593517094 100644 --- a/target-microblaze/op_helper.c +++ b/target-microblaze/op_helper.c @@ -44,19 +44,13 @@ void tlb_fill(CPUMBState *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { - TranslationBlock *tb; int ret; ret = cpu_mb_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ - tb = tb_find_pc(retaddr); - if (tb) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, retaddr); - } + cpu_restore_state(env, retaddr); } cpu_loop_exit(env); } diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index f45d494b14..2972ae3f0a 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -38,7 +38,6 @@ static inline void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, int error_code, uintptr_t pc) { - TranslationBlock *tb; #if 1 if (exception < 0x100) qemu_log("%s: %d %d\n", __func__, exception, error_code); @@ -48,12 +47,7 @@ static inline void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, if (pc) { /* now we have a real cpu fault */ - tb = tb_find_pc(pc); - if (tb) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, pc); - } + cpu_restore_state(env, pc); } cpu_loop_exit(env); diff --git a/target-openrisc/mmu_helper.c b/target-openrisc/mmu_helper.c index 59ed371ae0..d2edebcb49 100644 --- a/target-openrisc/mmu_helper.c +++ b/target-openrisc/mmu_helper.c @@ -39,8 +39,6 @@ void tlb_fill(CPUOpenRISCState *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { - TranslationBlock *tb; - unsigned long pc; int ret; ret = cpu_openrisc_handle_mmu_fault(env, addr, is_write, mmu_idx); @@ -48,13 +46,7 @@ void tlb_fill(CPUOpenRISCState *env, target_ulong addr, int is_write, if (ret) { if (retaddr) { /* now we have a real cpu fault. */ - pc = (unsigned long)retaddr; - tb = tb_find_pc(pc); - if (tb) { - /* the PC is inside the translated code. It means that we - have a virtual CPU fault. */ - cpu_restore_state(tb, env, pc); - } + cpu_restore_state(env, retaddr); } /* Raise Exception. */ cpu_loop_exit(env); diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c index 5b5f1bdd23..04c01445f9 100644 --- a/target-ppc/mem_helper.c +++ b/target-ppc/mem_helper.c @@ -275,19 +275,13 @@ STVE(stvewx, cpu_stl_data, bswap32, u32) void tlb_fill(CPUPPCState *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { - TranslationBlock *tb; int ret; ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret != 0)) { if (likely(retaddr)) { /* now we have a real cpu fault */ - tb = tb_find_pc(retaddr); - if (likely(tb)) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, retaddr); - } + cpu_restore_state(env, retaddr); } helper_raise_exception_err(env, env->exception_index, env->error_code); } diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c index 6ebc22dd11..91b25e309d 100644 --- a/target-s390x/mem_helper.c +++ b/target-s390x/mem_helper.c @@ -47,19 +47,13 @@ void tlb_fill(CPUS390XState *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { - TranslationBlock *tb; int ret; ret = cpu_s390x_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret != 0)) { if (likely(retaddr)) { /* now we have a real cpu fault */ - tb = tb_find_pc(retaddr); - if (likely(tb)) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, retaddr); - } + cpu_restore_state(env, retaddr); } cpu_loop_exit(env); } diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c index 60ec4cbc4d..e8e87f5152 100644 --- a/target-sh4/op_helper.c +++ b/target-sh4/op_helper.c @@ -21,21 +21,6 @@ #include "cpu.h" #include "helper.h" -static inline void cpu_restore_state_from_retaddr(CPUSH4State *env, - uintptr_t retaddr) -{ - TranslationBlock *tb; - - if (retaddr) { - tb = tb_find_pc(retaddr); - if (tb) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, retaddr); - } - } -} - #ifndef CONFIG_USER_ONLY #include "softmmu_exec.h" @@ -61,7 +46,9 @@ void tlb_fill(CPUSH4State *env, target_ulong addr, int is_write, int mmu_idx, ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx); if (ret) { /* now we have a real cpu fault */ - cpu_restore_state_from_retaddr(env, retaddr); + if (retaddr) { + cpu_restore_state(env, retaddr); + } cpu_loop_exit(env); } } @@ -82,7 +69,9 @@ static inline void QEMU_NORETURN raise_exception(CPUSH4State *env, int index, uintptr_t retaddr) { env->exception_index = index; - cpu_restore_state_from_retaddr(env, retaddr); + if (retaddr) { + cpu_restore_state(env, retaddr); + } cpu_loop_exit(env); } diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 375f20a71e..013ecbd063 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -710,7 +710,6 @@ uint64_t cpu_tick_get_count(CPUTimer *timer); void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit); trap_state* cpu_tsptr(CPUSPARCState* env); #endif -void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr); #define TB_FLAG_FPU_ENABLED (1 << 4) #define TB_FLAG_AM_ENABLED (1 << 5) diff --git a/target-sparc/helper.c b/target-sparc/helper.c index 556ac286eb..3c8e865eef 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -75,7 +75,7 @@ static target_ulong helper_udiv_common(CPUSPARCState *env, target_ulong a, x1 = (b & 0xffffffff); if (x1 == 0) { - cpu_restore_state2(env, GETPC()); + cpu_restore_state(env, GETPC()); helper_raise_exception(env, TT_DIV_ZERO); } @@ -114,7 +114,7 @@ static target_ulong helper_sdiv_common(CPUSPARCState *env, target_ulong a, x1 = (b & 0xffffffff); if (x1 == 0) { - cpu_restore_state2(env, GETPC()); + cpu_restore_state(env, GETPC()); helper_raise_exception(env, TT_DIV_ZERO); } @@ -147,7 +147,7 @@ int64_t helper_sdivx(CPUSPARCState *env, int64_t a, int64_t b) { if (b == 0) { /* Raise divide by zero trap. */ - cpu_restore_state2(env, GETPC()); + cpu_restore_state(env, GETPC()); helper_raise_exception(env, TT_DIV_ZERO); } else if (b == -1) { /* Avoid overflow trap with i386 divide insn. */ @@ -161,7 +161,7 @@ uint64_t helper_udivx(CPUSPARCState *env, uint64_t a, uint64_t b) { if (b == 0) { /* Raise divide by zero trap. */ - cpu_restore_state2(env, GETPC()); + cpu_restore_state(env, GETPC()); helper_raise_exception(env, TT_DIV_ZERO); } return a / b; @@ -193,7 +193,7 @@ target_ulong helper_taddcctv(CPUSPARCState *env, target_ulong src1, return dst; tag_overflow: - cpu_restore_state2(env, GETPC()); + cpu_restore_state(env, GETPC()); helper_raise_exception(env, TT_TOVF); } @@ -222,6 +222,6 @@ target_ulong helper_tsubcctv(CPUSPARCState *env, target_ulong src1, return dst; tag_overflow: - cpu_restore_state2(env, GETPC()); + cpu_restore_state(env, GETPC()); helper_raise_exception(env, TT_TOVF); } diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c index f3e08fd6e6..8d815e5038 100644 --- a/target-sparc/ldst_helper.c +++ b/target-sparc/ldst_helper.c @@ -2393,22 +2393,6 @@ void cpu_unassigned_access(CPUSPARCState *env, hwaddr addr, #endif #endif -/* XXX: make it generic ? */ -void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr) -{ - TranslationBlock *tb; - - if (retaddr) { - /* now we have a real cpu fault */ - tb = tb_find_pc(retaddr); - if (tb) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, retaddr); - } - } -} - #if !defined(CONFIG_USER_ONLY) static void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write, @@ -2418,7 +2402,9 @@ static void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env, printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx "\n", addr, env->pc); #endif - cpu_restore_state2(env, retaddr); + if (retaddr) { + cpu_restore_state(env, retaddr); + } helper_raise_exception(env, TT_UNALIGNED); } @@ -2433,7 +2419,9 @@ void tlb_fill(CPUSPARCState *env, target_ulong addr, int is_write, int mmu_idx, ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx); if (ret) { - cpu_restore_state2(env, retaddr); + if (retaddr) { + cpu_restore_state(env, retaddr); + } cpu_loop_exit(env); } } diff --git a/target-unicore32/op_helper.c b/target-unicore32/op_helper.c index f474d1b59b..b8172ba682 100644 --- a/target-unicore32/op_helper.c +++ b/target-unicore32/op_helper.c @@ -256,20 +256,13 @@ uint32_t HELPER(ror_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i) void tlb_fill(CPUUniCore32State *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { - TranslationBlock *tb; - unsigned long pc; int ret; ret = uc32_cpu_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ - pc = (unsigned long)retaddr; - tb = tb_find_pc(pc); - if (tb) {/* the PC is inside the translated code. - It means that we have a virtual CPU fault */ - cpu_restore_state(tb, env, pc); - } + cpu_restore_state(env, retaddr); } cpu_loop_exit(env); } diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c index 0e0f21d1a2..84f0449f79 100644 --- a/target-xtensa/op_helper.c +++ b/target-xtensa/op_helper.c @@ -47,22 +47,12 @@ static void do_unaligned_access(CPUXtensaState *env, #define SHIFT 3 #include "softmmu_template.h" -static void do_restore_state(CPUXtensaState *env, uintptr_t pc) -{ - TranslationBlock *tb; - - tb = tb_find_pc(pc); - if (tb) { - cpu_restore_state(tb, env, pc); - } -} - static void do_unaligned_access(CPUXtensaState *env, target_ulong addr, int is_write, int is_user, uintptr_t retaddr) { if (xtensa_option_enabled(env->config, XTENSA_OPTION_UNALIGNED_EXCEPTION) && !xtensa_option_enabled(env->config, XTENSA_OPTION_HW_ALIGNMENT)) { - do_restore_state(env, retaddr); + cpu_restore_state(env, retaddr); HELPER(exception_cause_vaddr)(env, env->pc, LOAD_STORE_ALIGNMENT_CAUSE, addr); } @@ -86,7 +76,7 @@ void tlb_fill(CPUXtensaState *env, paddr & TARGET_PAGE_MASK, access, mmu_idx, page_size); } else { - do_restore_state(env, retaddr); + cpu_restore_state(env, retaddr); HELPER(exception_cause_vaddr)(env, env->pc, ret, vaddr); } } diff --git a/translate-all.c b/translate-all.c index b958342a99..164870a68c 100644 --- a/translate-all.c +++ b/translate-all.c @@ -142,6 +142,7 @@ TCGContext tcg_ctx; static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, tb_page_addr_t phys_page2); +static TranslationBlock *tb_find_pc(uintptr_t tc_ptr); void cpu_gen_init(void) { @@ -211,8 +212,8 @@ int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_size_ptr /* The cpu state corresponding to 'searched_pc' is restored. */ -int cpu_restore_state(TranslationBlock *tb, - CPUArchState *env, uintptr_t searched_pc) +static int cpu_restore_state_from_tb(TranslationBlock *tb, CPUArchState *env, + uintptr_t searched_pc) { TCGContext *s = &tcg_ctx; int j; @@ -266,6 +267,18 @@ int cpu_restore_state(TranslationBlock *tb, return 0; } +bool cpu_restore_state(CPUArchState *env, uintptr_t retaddr) +{ + TranslationBlock *tb; + + tb = tb_find_pc(retaddr); + if (tb) { + cpu_restore_state_from_tb(tb, env, retaddr); + return true; + } + return false; +} + #ifdef _WIN32 static inline void map_exec(void *addr, long size) { @@ -1057,7 +1070,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, restore the CPU state */ current_tb_modified = 1; - cpu_restore_state(current_tb, env, env->mem_io_pc); + cpu_restore_state_from_tb(current_tb, env, env->mem_io_pc); cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base, ¤t_flags); } @@ -1171,7 +1184,7 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr, restore the CPU state */ current_tb_modified = 1; - cpu_restore_state(current_tb, env, pc); + cpu_restore_state_from_tb(current_tb, env, pc); cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base, ¤t_flags); } @@ -1308,7 +1321,7 @@ bool is_tcg_gen_code(uintptr_t tc_ptr) /* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr < tb[1].tc_ptr. Return NULL if not found */ -TranslationBlock *tb_find_pc(uintptr_t tc_ptr) +static TranslationBlock *tb_find_pc(uintptr_t tc_ptr) { int m_min, m_max, m; uintptr_t v; @@ -1435,7 +1448,7 @@ void tb_check_watchpoint(CPUArchState *env) cpu_abort(env, "check_watchpoint: could not find TB for pc=%p", (void *)env->mem_io_pc); } - cpu_restore_state(tb, env, env->mem_io_pc); + cpu_restore_state_from_tb(tb, env, env->mem_io_pc); tb_phys_invalidate(tb, -1); } @@ -1486,7 +1499,7 @@ void cpu_io_recompile(CPUArchState *env, uintptr_t retaddr) (void *)retaddr); } n = env->icount_decr.u16.low + tb->icount; - cpu_restore_state(tb, env, retaddr); + cpu_restore_state_from_tb(tb, env, retaddr); /* Calculate how many instructions had been executed before the fault occurred. */ n = n - env->icount_decr.u16.low; diff --git a/user-exec.c b/user-exec.c index ef9b1727b3..1185cb03c8 100644 --- a/user-exec.c +++ b/user-exec.c @@ -81,7 +81,6 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address, int is_write, sigset_t *old_set, void *puc) { - TranslationBlock *tb; int ret; #if defined(DEBUG_SIGNAL) @@ -104,12 +103,7 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address, return 1; /* the MMU fault was handled without causing real CPU fault */ } /* now we have a real cpu fault */ - tb = tb_find_pc(pc); - if (tb) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, cpu_single_env, pc); - } + cpu_restore_state(cpu_single_env, pc); /* we restore the process signal mask as the sigreturn should do it (XXX: use sigsetjmp) */ From 315a1350c4a386065a73aad2ded1a11d77bf7771 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 12 Dec 2012 13:32:14 +0200 Subject: [PATCH 2000/2270] pci: move pci core code to hw/pci Move files and modify makefiles to pick them at the new location. Signed-off-by: Michael S. Tsirkin --- hw/Makefile.objs | 11 ++--------- hw/i386/Makefile.objs | 2 +- hw/pci/Makefile.objs | 7 +++++++ hw/{ => pci}/msi.c | 0 hw/{ => pci}/msi.h | 0 hw/{ => pci}/msix.c | 0 hw/{ => pci}/msix.h | 0 hw/{ => pci}/pci-hotplug.c | 0 hw/{ => pci}/pci-stub.c | 0 hw/{ => pci}/pci.c | 0 hw/{ => pci}/pci.h | 0 hw/{ => pci}/pci_bridge.c | 0 hw/{ => pci}/pci_bridge.h | 0 hw/{ => pci}/pci_host.c | 0 hw/{ => pci}/pci_host.h | 0 hw/{ => pci}/pci_ids.h | 0 hw/{ => pci}/pci_internals.h | 0 hw/{ => pci}/pci_regs.h | 0 hw/{ => pci}/pcie.c | 0 hw/{ => pci}/pcie.h | 0 hw/{ => pci}/pcie_aer.c | 0 hw/{ => pci}/pcie_aer.h | 0 hw/{ => pci}/pcie_host.c | 0 hw/{ => pci}/pcie_host.h | 0 hw/{ => pci}/pcie_port.c | 0 hw/{ => pci}/pcie_port.h | 0 hw/{ => pci}/pcie_regs.h | 0 hw/{ => pci}/shpc.c | 0 hw/{ => pci}/shpc.h | 0 hw/{ => pci}/slotid_cap.c | 0 hw/{ => pci}/slotid_cap.h | 0 hw/ppc/Makefile.objs | 2 +- 32 files changed, 11 insertions(+), 11 deletions(-) create mode 100644 hw/pci/Makefile.objs rename hw/{ => pci}/msi.c (100%) rename hw/{ => pci}/msi.h (100%) rename hw/{ => pci}/msix.c (100%) rename hw/{ => pci}/msix.h (100%) rename hw/{ => pci}/pci-hotplug.c (100%) rename hw/{ => pci}/pci-stub.c (100%) rename hw/{ => pci}/pci.c (100%) rename hw/{ => pci}/pci.h (100%) rename hw/{ => pci}/pci_bridge.c (100%) rename hw/{ => pci}/pci_bridge.h (100%) rename hw/{ => pci}/pci_host.c (100%) rename hw/{ => pci}/pci_host.h (100%) rename hw/{ => pci}/pci_ids.h (100%) rename hw/{ => pci}/pci_internals.h (100%) rename hw/{ => pci}/pci_regs.h (100%) rename hw/{ => pci}/pcie.c (100%) rename hw/{ => pci}/pcie.h (100%) rename hw/{ => pci}/pcie_aer.c (100%) rename hw/{ => pci}/pcie_aer.h (100%) rename hw/{ => pci}/pcie_host.c (100%) rename hw/{ => pci}/pcie_host.h (100%) rename hw/{ => pci}/pcie_port.c (100%) rename hw/{ => pci}/pcie_port.h (100%) rename hw/{ => pci}/pcie_regs.h (100%) rename hw/{ => pci}/shpc.c (100%) rename hw/{ => pci}/shpc.h (100%) rename hw/{ => pci}/slotid_cap.c (100%) rename hw/{ => pci}/slotid_cap.h (100%) diff --git a/hw/Makefile.objs b/hw/Makefile.objs index d581d8d6d6..9d33b189e6 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -1,14 +1,10 @@ -common-obj-y = usb/ ide/ +common-obj-y = usb/ ide/ pci/ common-obj-y += loader.o common-obj-$(CONFIG_VIRTIO) += virtio-console.o common-obj-$(CONFIG_VIRTIO) += virtio-rng.o common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o common-obj-y += fw_cfg.o -common-obj-$(CONFIG_PCI) += pci.o pci_bridge.o pci_bridge_dev.o -common-obj-$(CONFIG_PCI) += msix.o msi.o -common-obj-$(CONFIG_PCI) += shpc.o -common-obj-$(CONFIG_PCI) += slotid_cap.o -common-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o +common-obj-$(CONFIG_PCI) += pci_bridge_dev.o common-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o common-obj-$(CONFIG_PCI) += i82801b11.o common-obj-y += watchdog.o @@ -102,8 +98,6 @@ common-obj-$(CONFIG_XGMAC) += xgmac.o # PCI watchdog devices common-obj-$(CONFIG_PCI) += wdt_i6300esb.o -common-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o - # PCI network cards common-obj-$(CONFIG_NE2000_PCI) += ne2000.o common-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o @@ -199,7 +193,6 @@ obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o virtio-scsi.o obj-$(CONFIG_SOFTMMU) += vhost_net.o obj-$(CONFIG_VHOST_NET) += vhost.o obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/ -obj-$(CONFIG_NO_PCI) += pci-stub.o obj-$(CONFIG_VGA) += vga.o obj-$(CONFIG_SOFTMMU) += device-hotplug.o obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 0d3f6a8e84..257f3c1a91 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -2,7 +2,7 @@ obj-y += mc146818rtc.o pc.o obj-y += apic_common.o apic.o kvmvapic.o obj-y += sga.o ioapic_common.o ioapic.o piix_pci.o obj-y += vmport.o -obj-y += pci-hotplug.o smbios.o wdt_ib700.o +obj-y += pci/pci-hotplug.o smbios.o wdt_ib700.o obj-y += debugcon.o multiboot.o obj-y += pc_piix.o obj-y += pc_sysfw.o diff --git a/hw/pci/Makefile.objs b/hw/pci/Makefile.objs new file mode 100644 index 0000000000..aa7a0e84b5 --- /dev/null +++ b/hw/pci/Makefile.objs @@ -0,0 +1,7 @@ +common-obj-$(CONFIG_PCI) += pci.o pci_bridge.o +common-obj-$(CONFIG_PCI) += msix.o msi.o +common-obj-$(CONFIG_PCI) += shpc.o +common-obj-$(CONFIG_PCI) += slotid_cap.o +common-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o +common-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o +common-obj-$(CONFIG_NO_PCI) += pci-stub.o diff --git a/hw/msi.c b/hw/pci/msi.c similarity index 100% rename from hw/msi.c rename to hw/pci/msi.c diff --git a/hw/msi.h b/hw/pci/msi.h similarity index 100% rename from hw/msi.h rename to hw/pci/msi.h diff --git a/hw/msix.c b/hw/pci/msix.c similarity index 100% rename from hw/msix.c rename to hw/pci/msix.c diff --git a/hw/msix.h b/hw/pci/msix.h similarity index 100% rename from hw/msix.h rename to hw/pci/msix.h diff --git a/hw/pci-hotplug.c b/hw/pci/pci-hotplug.c similarity index 100% rename from hw/pci-hotplug.c rename to hw/pci/pci-hotplug.c diff --git a/hw/pci-stub.c b/hw/pci/pci-stub.c similarity index 100% rename from hw/pci-stub.c rename to hw/pci/pci-stub.c diff --git a/hw/pci.c b/hw/pci/pci.c similarity index 100% rename from hw/pci.c rename to hw/pci/pci.c diff --git a/hw/pci.h b/hw/pci/pci.h similarity index 100% rename from hw/pci.h rename to hw/pci/pci.h diff --git a/hw/pci_bridge.c b/hw/pci/pci_bridge.c similarity index 100% rename from hw/pci_bridge.c rename to hw/pci/pci_bridge.c diff --git a/hw/pci_bridge.h b/hw/pci/pci_bridge.h similarity index 100% rename from hw/pci_bridge.h rename to hw/pci/pci_bridge.h diff --git a/hw/pci_host.c b/hw/pci/pci_host.c similarity index 100% rename from hw/pci_host.c rename to hw/pci/pci_host.c diff --git a/hw/pci_host.h b/hw/pci/pci_host.h similarity index 100% rename from hw/pci_host.h rename to hw/pci/pci_host.h diff --git a/hw/pci_ids.h b/hw/pci/pci_ids.h similarity index 100% rename from hw/pci_ids.h rename to hw/pci/pci_ids.h diff --git a/hw/pci_internals.h b/hw/pci/pci_internals.h similarity index 100% rename from hw/pci_internals.h rename to hw/pci/pci_internals.h diff --git a/hw/pci_regs.h b/hw/pci/pci_regs.h similarity index 100% rename from hw/pci_regs.h rename to hw/pci/pci_regs.h diff --git a/hw/pcie.c b/hw/pci/pcie.c similarity index 100% rename from hw/pcie.c rename to hw/pci/pcie.c diff --git a/hw/pcie.h b/hw/pci/pcie.h similarity index 100% rename from hw/pcie.h rename to hw/pci/pcie.h diff --git a/hw/pcie_aer.c b/hw/pci/pcie_aer.c similarity index 100% rename from hw/pcie_aer.c rename to hw/pci/pcie_aer.c diff --git a/hw/pcie_aer.h b/hw/pci/pcie_aer.h similarity index 100% rename from hw/pcie_aer.h rename to hw/pci/pcie_aer.h diff --git a/hw/pcie_host.c b/hw/pci/pcie_host.c similarity index 100% rename from hw/pcie_host.c rename to hw/pci/pcie_host.c diff --git a/hw/pcie_host.h b/hw/pci/pcie_host.h similarity index 100% rename from hw/pcie_host.h rename to hw/pci/pcie_host.h diff --git a/hw/pcie_port.c b/hw/pci/pcie_port.c similarity index 100% rename from hw/pcie_port.c rename to hw/pci/pcie_port.c diff --git a/hw/pcie_port.h b/hw/pci/pcie_port.h similarity index 100% rename from hw/pcie_port.h rename to hw/pci/pcie_port.h diff --git a/hw/pcie_regs.h b/hw/pci/pcie_regs.h similarity index 100% rename from hw/pcie_regs.h rename to hw/pci/pcie_regs.h diff --git a/hw/shpc.c b/hw/pci/shpc.c similarity index 100% rename from hw/shpc.c rename to hw/pci/shpc.c diff --git a/hw/shpc.h b/hw/pci/shpc.h similarity index 100% rename from hw/shpc.h rename to hw/pci/shpc.h diff --git a/hw/slotid_cap.c b/hw/pci/slotid_cap.c similarity index 100% rename from hw/slotid_cap.c rename to hw/pci/slotid_cap.c diff --git a/hw/slotid_cap.h b/hw/pci/slotid_cap.h similarity index 100% rename from hw/slotid_cap.h rename to hw/pci/slotid_cap.h diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index 8fe21235f0..cb7cf8fba5 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -10,7 +10,7 @@ obj-y += ppc_newworld.o # IBM pSeries (sPAPR) obj-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o obj-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o -obj-$(CONFIG_PSERIES) += spapr_pci.o pci-hotplug.o spapr_iommu.o +obj-$(CONFIG_PSERIES) += spapr_pci.o pci/pci-hotplug.o spapr_iommu.o obj-$(CONFIG_PSERIES) += spapr_events.o # PowerPC 4xx boards obj-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o From a2cb15b0ddfa05f81a42d7b65dd0c7c50e420c33 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 12 Dec 2012 14:24:50 +0200 Subject: [PATCH 2001/2270] pci: update all users to look in pci/ update all users so we can remove the makefile hack. Signed-off-by: Michael S. Tsirkin --- arch_init.c | 2 +- hw/ac97.c | 2 +- hw/acpi_ich9.c | 2 +- hw/acpi_piix4.c | 2 +- hw/alpha_sys.h | 4 ++-- hw/apb_pci.c | 8 ++++---- hw/apic.c | 2 +- hw/apm.c | 2 +- hw/bonito.c | 4 ++-- hw/cirrus_vga.c | 2 +- hw/dec_pci.c | 8 ++++---- hw/e1000.c | 2 +- hw/eepro100.c | 2 +- hw/es1370.c | 2 +- hw/esp-pci.c | 2 +- hw/grackle_pci.c | 4 ++-- hw/gt64xxx.c | 4 ++-- hw/hda-audio.c | 2 +- hw/i82378.c | 2 +- hw/i82801b11.c | 2 +- hw/ich9.h | 8 ++++---- hw/ide.h | 2 +- hw/ide/ahci.c | 4 ++-- hw/ide/cmd646.c | 2 +- hw/ide/core.c | 2 +- hw/ide/ich.c | 4 ++-- hw/ide/pci.c | 2 +- hw/ide/piix.c | 2 +- hw/ide/via.c | 2 +- hw/intel-hda.c | 4 ++-- hw/ioh3420.c | 6 +++--- hw/ioh3420.h | 2 +- hw/ivshmem.c | 4 ++-- hw/kvm/apic.c | 2 +- hw/kvm/pci-assign.c | 4 ++-- hw/lpc_ich9.c | 8 ++++---- hw/lsi53c895a.c | 2 +- hw/macio.c | 2 +- hw/megasas.c | 4 ++-- hw/mips_fulong2e.c | 2 +- hw/mips_malta.c | 2 +- hw/ne2000.c | 2 +- hw/openpic.c | 2 +- hw/pc.c | 4 ++-- hw/pc_piix.c | 4 ++-- hw/pci_bridge_dev.c | 12 ++++++------ hw/pcnet-pci.c | 2 +- hw/piix4.c | 2 +- hw/piix_pci.c | 4 ++-- hw/ppc/e500.c | 2 +- hw/ppc440_bamboo.c | 2 +- hw/ppc4xx.h | 2 +- hw/ppc4xx_pci.c | 4 ++-- hw/ppc_newworld.c | 2 +- hw/ppc_oldworld.c | 2 +- hw/ppc_prep.c | 4 ++-- hw/ppce500_pci.c | 4 ++-- hw/prep_pci.c | 4 ++-- hw/q35.h | 4 ++-- hw/qxl.h | 2 +- hw/r2d.c | 2 +- hw/realview.c | 2 +- hw/rtl8139.c | 2 +- hw/serial-pci.c | 2 +- hw/sga.c | 2 +- hw/sh_pci.c | 4 ++-- hw/smbus_ich9.c | 2 +- hw/spapr.c | 4 ++-- hw/spapr_pci.c | 10 +++++----- hw/spapr_pci.h | 4 ++-- hw/sun4u.c | 2 +- hw/unin_pci.c | 4 ++-- hw/usb/hcd-ehci-pci.c | 2 +- hw/usb/hcd-ohci.c | 2 +- hw/usb/hcd-uhci.c | 2 +- hw/usb/hcd-xhci.c | 6 +++--- hw/versatile_pci.c | 4 ++-- hw/versatilepb.c | 2 +- hw/vfio_pci.c | 6 +++--- hw/vga-pci.c | 2 +- hw/vga.c | 2 +- hw/virtio-balloon.h | 2 +- hw/virtio-net.h | 2 +- hw/virtio-pci.c | 6 +++--- hw/virtio-scsi.h | 2 +- hw/vmware_vga.c | 2 +- hw/vt82c686.c | 4 ++-- hw/wdt_i6300esb.c | 2 +- hw/xen-host-pci-device.h | 2 +- hw/xen_apic.c | 2 +- hw/xen_platform.c | 2 +- hw/xen_pt.c | 2 +- hw/xen_pt.h | 2 +- hw/xio3130_downstream.c | 6 +++--- hw/xio3130_downstream.h | 2 +- hw/xio3130_upstream.c | 6 +++--- hw/xio3130_upstream.h | 2 +- kvm-all.c | 2 +- kvm-stub.c | 2 +- monitor.c | 2 +- target-i386/kvm.c | 2 +- xen-all.c | 2 +- 102 files changed, 159 insertions(+), 159 deletions(-) diff --git a/arch_init.c b/arch_init.c index e6effe809a..e307b23310 100644 --- a/arch_init.c +++ b/arch_init.c @@ -36,7 +36,7 @@ #include "arch_init.h" #include "audio/audio.h" #include "hw/pc.h" -#include "hw/pci.h" +#include "hw/pci/pci.h" #include "hw/audiodev.h" #include "kvm.h" #include "migration.h" diff --git a/hw/ac97.c b/hw/ac97.c index ce6a1dc609..3e659b38df 100644 --- a/hw/ac97.c +++ b/hw/ac97.c @@ -20,7 +20,7 @@ #include "hw.h" #include "audiodev.h" #include "audio/audio.h" -#include "pci.h" +#include "pci/pci.h" #include "dma.h" enum { diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c index 85d441c33c..755fa050f7 100644 --- a/hw/acpi_ich9.c +++ b/hw/acpi_ich9.c @@ -25,7 +25,7 @@ */ #include "hw.h" #include "pc.h" -#include "pci.h" +#include "pci/pci.h" #include "qemu-timer.h" #include "sysemu.h" #include "acpi.h" diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 0b5b0d3d3e..46f9843891 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -22,7 +22,7 @@ #include "pc.h" #include "apm.h" #include "pm_smbus.h" -#include "pci.h" +#include "pci/pci.h" #include "acpi.h" #include "sysemu.h" #include "range.h" diff --git a/hw/alpha_sys.h b/hw/alpha_sys.h index 7604d09c80..b1e52585b3 100644 --- a/hw/alpha_sys.h +++ b/hw/alpha_sys.h @@ -3,8 +3,8 @@ #ifndef HW_ALPHA_H #define HW_ALPHA_H 1 -#include "pci.h" -#include "pci_host.h" +#include "pci/pci.h" +#include "pci/pci_host.h" #include "ide.h" #include "net.h" #include "pc.h" diff --git a/hw/apb_pci.c b/hw/apb_pci.c index 054814fd4b..de594f8c0b 100644 --- a/hw/apb_pci.c +++ b/hw/apb_pci.c @@ -27,10 +27,10 @@ the secondary PCI bridge. */ #include "sysbus.h" -#include "pci.h" -#include "pci_host.h" -#include "pci_bridge.h" -#include "pci_internals.h" +#include "pci/pci.h" +#include "pci/pci_host.h" +#include "pci/pci_bridge.h" +#include "pci/pci_internals.h" #include "apb_pci.h" #include "sysemu.h" #include "exec-memory.h" diff --git a/hw/apic.c b/hw/apic.c index f73fc877aa..d66a476aac 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -20,7 +20,7 @@ #include "apic_internal.h" #include "apic.h" #include "ioapic.h" -#include "msi.h" +#include "pci/msi.h" #include "host-utils.h" #include "trace.h" #include "pc.h" diff --git a/hw/apm.c b/hw/apm.c index e988ad9939..2e1b1372d2 100644 --- a/hw/apm.c +++ b/hw/apm.c @@ -22,7 +22,7 @@ #include "apm.h" #include "hw.h" -#include "pci.h" +#include "pci/pci.h" //#define DEBUG diff --git a/hw/bonito.c b/hw/bonito.c index 0bf6d4aa5f..a1fc38c784 100644 --- a/hw/bonito.c +++ b/hw/bonito.c @@ -40,10 +40,10 @@ #include #include "hw.h" -#include "pci.h" +#include "pci/pci.h" #include "pc.h" #include "mips.h" -#include "pci_host.h" +#include "pci/pci_host.h" #include "sysemu.h" #include "exec-memory.h" diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index 40efa8a523..7d021f2e1d 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -27,7 +27,7 @@ * available at http://home.worldonline.dk/~finth/ */ #include "hw.h" -#include "pci.h" +#include "pci/pci.h" #include "console.h" #include "vga_int.h" #include "loader.h" diff --git a/hw/dec_pci.c b/hw/dec_pci.c index c30ade38bd..a6a7c846fd 100644 --- a/hw/dec_pci.c +++ b/hw/dec_pci.c @@ -25,10 +25,10 @@ #include "dec_pci.h" #include "sysbus.h" -#include "pci.h" -#include "pci_host.h" -#include "pci_bridge.h" -#include "pci_internals.h" +#include "pci/pci.h" +#include "pci/pci_host.h" +#include "pci/pci_bridge.h" +#include "pci/pci_internals.h" /* debug DEC */ //#define DEBUG_DEC diff --git a/hw/e1000.c b/hw/e1000.c index 5537ad2fc4..c89c8d22ab 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -26,7 +26,7 @@ #include "hw.h" -#include "pci.h" +#include "pci/pci.h" #include "net.h" #include "net/checksum.h" #include "loader.h" diff --git a/hw/eepro100.c b/hw/eepro100.c index a189474d31..992f03ace7 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -42,7 +42,7 @@ #include /* offsetof */ #include "hw.h" -#include "pci.h" +#include "pci/pci.h" #include "net.h" #include "eeprom93xx.h" #include "sysemu.h" diff --git a/hw/es1370.c b/hw/es1370.c index e0c9729dc9..65365788e1 100644 --- a/hw/es1370.c +++ b/hw/es1370.c @@ -29,7 +29,7 @@ #include "hw.h" #include "audiodev.h" #include "audio/audio.h" -#include "pci.h" +#include "pci/pci.h" #include "dma.h" /* Missing stuff: diff --git a/hw/esp-pci.c b/hw/esp-pci.c index d9a8e59c98..d433473d6a 100644 --- a/hw/esp-pci.c +++ b/hw/esp-pci.c @@ -23,7 +23,7 @@ * THE SOFTWARE. */ -#include "pci.h" +#include "pci/pci.h" #include "eeprom93xx.h" #include "esp.h" #include "trace.h" diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c index 67da307284..948416632a 100644 --- a/hw/grackle_pci.c +++ b/hw/grackle_pci.c @@ -23,9 +23,9 @@ * THE SOFTWARE. */ -#include "pci_host.h" +#include "pci/pci_host.h" #include "ppc_mac.h" -#include "pci.h" +#include "pci/pci.h" /* debug Grackle */ //#define DEBUG_GRACKLE diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c index 95d491d932..5aa49c6148 100644 --- a/hw/gt64xxx.c +++ b/hw/gt64xxx.c @@ -24,8 +24,8 @@ #include "hw.h" #include "mips.h" -#include "pci.h" -#include "pci_host.h" +#include "pci/pci.h" +#include "pci/pci_host.h" #include "pc.h" #include "exec-memory.h" diff --git a/hw/hda-audio.c b/hw/hda-audio.c index 36761dd2de..92a91b5ab1 100644 --- a/hw/hda-audio.c +++ b/hw/hda-audio.c @@ -18,7 +18,7 @@ */ #include "hw.h" -#include "pci.h" +#include "pci/pci.h" #include "intel-hda.h" #include "intel-hda-defs.h" #include "audio/audio.h" diff --git a/hw/i82378.c b/hw/i82378.c index 99f35d41ef..c6b0b5ec55 100644 --- a/hw/i82378.c +++ b/hw/i82378.c @@ -17,7 +17,7 @@ * License along with this library; if not, see . */ -#include "pci.h" +#include "pci/pci.h" #include "pc.h" #include "i8254.h" #include "pcspk.h" diff --git a/hw/i82801b11.c b/hw/i82801b11.c index 3d1f996b2f..3dc10000a4 100644 --- a/hw/i82801b11.c +++ b/hw/i82801b11.c @@ -41,7 +41,7 @@ * License along with this library; if not, see */ -#include "pci.h" +#include "pci/pci.h" #include "ich9.h" diff --git a/hw/ich9.h b/hw/ich9.h index 34e216f142..ddd12934d5 100644 --- a/hw/ich9.h +++ b/hw/ich9.h @@ -8,13 +8,13 @@ #include "pc.h" #include "apm.h" #include "ioapic.h" -#include "pci.h" -#include "pcie_host.h" -#include "pci_bridge.h" +#include "pci/pci.h" +#include "pci/pcie_host.h" +#include "pci/pci_bridge.h" #include "acpi.h" #include "acpi_ich9.h" #include "pam.h" -#include "pci_internals.h" +#include "pci/pci_internals.h" void ich9_lpc_set_irq(void *opaque, int irq_num, int level); int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx); diff --git a/hw/ide.h b/hw/ide.h index add742c4a8..081c710d56 100644 --- a/hw/ide.h +++ b/hw/ide.h @@ -2,7 +2,7 @@ #define HW_IDE_H #include "isa.h" -#include "pci.h" +#include "pci/pci.h" #include "memory.h" #define MAX_IDE_DEVS 2 diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 67562db041..2ea64bd316 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -22,9 +22,9 @@ */ #include -#include +#include #include -#include +#include #include #include "monitor.h" diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index 804db60ffe..88210eabc8 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -24,7 +24,7 @@ */ #include #include -#include +#include #include #include "block.h" #include "sysemu.h" diff --git a/hw/ide/core.c b/hw/ide/core.c index c4f93d0e47..adc4aa41b9 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -24,7 +24,7 @@ */ #include #include -#include +#include #include #include "qemu-error.h" #include "qemu-timer.h" diff --git a/hw/ide/ich.c b/hw/ide/ich.c index 272b7734b5..8e1a48e257 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -61,9 +61,9 @@ */ #include -#include +#include #include -#include +#include #include #include "block.h" #include "dma.h" diff --git a/hw/ide/pci.c b/hw/ide/pci.c index bcdd70e450..23a0e237fb 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -24,7 +24,7 @@ */ #include #include -#include +#include #include #include "block.h" #include "dma.h" diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 9431badadf..5cf39cf8f0 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include "blockdev.h" #include "sysemu.h" diff --git a/hw/ide/via.c b/hw/ide/via.c index efda1733d9..8b4a24e5c2 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -25,7 +25,7 @@ */ #include #include -#include +#include #include #include "block.h" #include "sysemu.h" diff --git a/hw/intel-hda.c b/hw/intel-hda.c index a68c3685e3..c21bf7204a 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -18,8 +18,8 @@ */ #include "hw.h" -#include "pci.h" -#include "msi.h" +#include "pci/pci.h" +#include "pci/msi.h" #include "qemu-timer.h" #include "audiodev.h" #include "intel-hda.h" diff --git a/hw/ioh3420.c b/hw/ioh3420.c index 4d314733b9..d706e195df 100644 --- a/hw/ioh3420.c +++ b/hw/ioh3420.c @@ -20,9 +20,9 @@ * with this program; if not, see . */ -#include "pci_ids.h" -#include "msi.h" -#include "pcie.h" +#include "pci/pci_ids.h" +#include "pci/msi.h" +#include "pci/pcie.h" #include "ioh3420.h" #define PCI_DEVICE_ID_IOH_EPORT 0x3420 /* D0:F0 express mode */ diff --git a/hw/ioh3420.h b/hw/ioh3420.h index 68c523ab46..046cf2c281 100644 --- a/hw/ioh3420.h +++ b/hw/ioh3420.h @@ -1,7 +1,7 @@ #ifndef QEMU_IOH3420_H #define QEMU_IOH3420_H -#include "pcie_port.h" +#include "pci/pcie_port.h" PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction, const char *bus_name, pci_map_irq_fn map_irq, diff --git a/hw/ivshmem.c b/hw/ivshmem.c index f6dbb212f2..cf64f32ac0 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -18,8 +18,8 @@ */ #include "hw.h" #include "pc.h" -#include "pci.h" -#include "msix.h" +#include "pci/pci.h" +#include "pci/msix.h" #include "kvm.h" #include "migration.h" #include "qerror.h" diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c index 8b65d513db..beb418de8d 100644 --- a/hw/kvm/apic.c +++ b/hw/kvm/apic.c @@ -10,7 +10,7 @@ * See the COPYING file in the top-level directory. */ #include "hw/apic_internal.h" -#include "hw/msi.h" +#include "hw/pci/msi.h" #include "kvm.h" static inline void kvm_apic_set_reg(struct kvm_lapic_state *kapic, diff --git a/hw/kvm/pci-assign.c b/hw/kvm/pci-assign.c index e80dad009c..42291592e3 100644 --- a/hw/kvm/pci-assign.c +++ b/hw/kvm/pci-assign.c @@ -34,8 +34,8 @@ #include "monitor.h" #include "range.h" #include "sysemu.h" -#include "hw/pci.h" -#include "hw/msi.h" +#include "hw/pci/pci.h" +#include "hw/pci/msi.h" #include "kvm_i386.h" #define MSIX_PAGE_SIZE 0x1000 diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c index 7a113633ed..811bf261c3 100644 --- a/hw/lpc_ich9.c +++ b/hw/lpc_ich9.c @@ -35,14 +35,14 @@ #include "pc.h" #include "apm.h" #include "ioapic.h" -#include "pci.h" -#include "pcie_host.h" -#include "pci_bridge.h" +#include "pci/pci.h" +#include "pci/pcie_host.h" +#include "pci/pci_bridge.h" #include "ich9.h" #include "acpi.h" #include "acpi_ich9.h" #include "pam.h" -#include "pci_internals.h" +#include "pci/pci_internals.h" #include "exec-memory.h" #include "sysemu.h" diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index 04f2faef42..4aac9a0cff 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -13,7 +13,7 @@ #include #include "hw.h" -#include "pci.h" +#include "pci/pci.h" #include "scsi.h" #include "dma.h" diff --git a/hw/macio.c b/hw/macio.c index eb15b890b1..362afdc7ec 100644 --- a/hw/macio.c +++ b/hw/macio.c @@ -24,7 +24,7 @@ */ #include "hw.h" #include "ppc_mac.h" -#include "pci.h" +#include "pci/pci.h" #include "escc.h" typedef struct MacIOState diff --git a/hw/megasas.c b/hw/megasas.c index 61b6527928..f4fbe9790a 100644 --- a/hw/megasas.c +++ b/hw/megasas.c @@ -19,9 +19,9 @@ */ #include "hw.h" -#include "pci.h" +#include "pci/pci.h" #include "dma.h" -#include "msix.h" +#include "pci/msix.h" #include "iov.h" #include "scsi.h" #include "scsi-defs.h" diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c index 5fcf900e04..d5cf33b4b6 100644 --- a/hw/mips_fulong2e.c +++ b/hw/mips_fulong2e.c @@ -29,7 +29,7 @@ #include "flash.h" #include "mips.h" #include "mips_cpudevs.h" -#include "pci.h" +#include "pci/pci.h" #include "qemu-char.h" #include "sysemu.h" #include "audio/audio.h" diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 4d2464a02c..571903dfc5 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -33,7 +33,7 @@ #include "flash.h" #include "mips.h" #include "mips_cpudevs.h" -#include "pci.h" +#include "pci/pci.h" #include "qemu-char.h" #include "sysemu.h" #include "arch_init.h" diff --git a/hw/ne2000.c b/hw/ne2000.c index d3dd9a6f26..fb78e5b252 100644 --- a/hw/ne2000.c +++ b/hw/ne2000.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "hw.h" -#include "pci.h" +#include "pci/pci.h" #include "net.h" #include "ne2000.h" #include "loader.h" diff --git a/hw/openpic.c b/hw/openpic.c index 8b3784a6bd..4791dc6eaf 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -35,7 +35,7 @@ */ #include "hw.h" #include "ppc_mac.h" -#include "pci.h" +#include "pci/pci.h" #include "openpic.h" //#define DEBUG_OPENPIC diff --git a/hw/pc.c b/hw/pc.c index b11e7c4adc..d1b102c879 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -27,7 +27,7 @@ #include "apic.h" #include "fdc.h" #include "ide.h" -#include "pci.h" +#include "pci/pci.h" #include "monitor.h" #include "fw_cfg.h" #include "hpet_emul.h" @@ -38,7 +38,7 @@ #include "mc146818rtc.h" #include "i8254.h" #include "pcspk.h" -#include "msi.h" +#include "pci/msi.h" #include "sysbus.h" #include "sysemu.h" #include "kvm.h" diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 19e342aeb4..c2b4cb07e5 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -27,8 +27,8 @@ #include "hw.h" #include "pc.h" #include "apic.h" -#include "pci.h" -#include "pci_ids.h" +#include "pci/pci.h" +#include "pci/pci_ids.h" #include "usb.h" #include "net.h" #include "boards.h" diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c index f7063961a0..5c9fc5036b 100644 --- a/hw/pci_bridge_dev.c +++ b/hw/pci_bridge_dev.c @@ -19,13 +19,13 @@ * with this program; if not, see . */ -#include "pci_bridge.h" -#include "pci_ids.h" -#include "msi.h" -#include "shpc.h" -#include "slotid_cap.h" +#include "pci/pci_bridge.h" +#include "pci/pci_ids.h" +#include "pci/msi.h" +#include "pci/shpc.h" +#include "pci/slotid_cap.h" #include "memory.h" -#include "pci_internals.h" +#include "pci/pci_internals.h" #define REDHAT_PCI_VENDOR_ID 0x1b36 #define PCI_BRIDGE_DEV_VENDOR_ID REDHAT_PCI_VENDOR_ID diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c index 0bf438ffee..c1abbf8d0d 100644 --- a/hw/pcnet-pci.c +++ b/hw/pcnet-pci.c @@ -27,7 +27,7 @@ * AMD Publication# 19436 Rev:E Amendment/0 Issue Date: June 2000 */ -#include "pci.h" +#include "pci/pci.h" #include "net.h" #include "loader.h" #include "qemu-timer.h" diff --git a/hw/piix4.c b/hw/piix4.c index ce4eb0d1ae..799ed1729c 100644 --- a/hw/piix4.c +++ b/hw/piix4.c @@ -24,7 +24,7 @@ #include "hw.h" #include "pc.h" -#include "pci.h" +#include "pci/pci.h" #include "isa.h" #include "sysbus.h" diff --git a/hw/piix_pci.c b/hw/piix_pci.c index ba1b3de749..b5ea68bc61 100644 --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@ -24,8 +24,8 @@ #include "hw.h" #include "pc.h" -#include "pci.h" -#include "pci_host.h" +#include "pci/pci.h" +#include "pci/pci_host.h" #include "isa.h" #include "sysbus.h" #include "range.h" diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 6749ffffb3..f77c488af7 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -20,7 +20,7 @@ #include "net.h" #include "hw/hw.h" #include "hw/serial.h" -#include "hw/pci.h" +#include "hw/pci/pci.h" #include "hw/boards.h" #include "sysemu.h" #include "kvm.h" diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c index cc85607cb7..0b39a81ec5 100644 --- a/hw/ppc440_bamboo.c +++ b/hw/ppc440_bamboo.c @@ -15,7 +15,7 @@ #include "qemu-common.h" #include "net.h" #include "hw.h" -#include "pci.h" +#include "pci/pci.h" #include "boards.h" #include "kvm.h" #include "kvm_ppc.h" diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h index d795ced57e..2b96d47f36 100644 --- a/hw/ppc4xx.h +++ b/hw/ppc4xx.h @@ -25,7 +25,7 @@ #if !defined(PPC_4XX_H) #define PPC_4XX_H -#include "pci.h" +#include "pci/pci.h" /* PowerPC 4xx core initialization */ CPUPPCState *ppc4xx_init (const char *cpu_model, diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c index d3ad6a0b79..3e8af11f08 100644 --- a/hw/ppc4xx_pci.c +++ b/hw/ppc4xx_pci.c @@ -22,8 +22,8 @@ #include "hw.h" #include "ppc.h" #include "ppc4xx.h" -#include "pci.h" -#include "pci_host.h" +#include "pci/pci.h" +#include "pci/pci_host.h" #include "exec-memory.h" #undef DEBUG diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index 664747ead3..c1ff9d7c31 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -52,7 +52,7 @@ #include "adb.h" #include "mac_dbdma.h" #include "nvram.h" -#include "pci.h" +#include "pci/pci.h" #include "net.h" #include "sysemu.h" #include "boards.h" diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index e8138c091e..3bc29c619c 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -32,7 +32,7 @@ #include "sysemu.h" #include "net.h" #include "isa.h" -#include "pci.h" +#include "pci/pci.h" #include "boards.h" #include "fw_cfg.h" #include "escc.h" diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index bf15730d8b..f6ffb593b7 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -29,8 +29,8 @@ #include "net.h" #include "sysemu.h" #include "isa.h" -#include "pci.h" -#include "pci_host.h" +#include "pci/pci.h" +#include "pci/pci_host.h" #include "ppc.h" #include "boards.h" #include "qemu-log.h" diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 2ff7438d09..39022aada0 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -15,8 +15,8 @@ */ #include "hw.h" -#include "pci.h" -#include "pci_host.h" +#include "pci/pci.h" +#include "pci/pci_host.h" #include "bswap.h" #ifdef DEBUG_PCI diff --git a/hw/prep_pci.c b/hw/prep_pci.c index 0bc479cd1f..5f22de647a 100644 --- a/hw/prep_pci.c +++ b/hw/prep_pci.c @@ -23,8 +23,8 @@ */ #include "hw.h" -#include "pci.h" -#include "pci_host.h" +#include "pci/pci.h" +#include "pci/pci_host.h" #include "pc.h" #include "exec-memory.h" diff --git a/hw/q35.h b/hw/q35.h index e34f7c165f..2f951c8a94 100644 --- a/hw/q35.h +++ b/hw/q35.h @@ -29,8 +29,8 @@ #include "pc.h" #include "apm.h" #include "apic.h" -#include "pci.h" -#include "pcie_host.h" +#include "pci/pci.h" +#include "pci/pcie_host.h" #include "acpi.h" #include "acpi_ich9.h" #include "pam.h" diff --git a/hw/qxl.h b/hw/qxl.h index e583cfb750..41246c7554 100644 --- a/hw/qxl.h +++ b/hw/qxl.h @@ -2,7 +2,7 @@ #include "console.h" #include "hw.h" -#include "pci.h" +#include "pci/pci.h" #include "vga_int.h" #include "qemu-thread.h" diff --git a/hw/r2d.c b/hw/r2d.c index 66212e9cda..e18c23b28b 100644 --- a/hw/r2d.c +++ b/hw/r2d.c @@ -29,7 +29,7 @@ #include "devices.h" #include "sysemu.h" #include "boards.h" -#include "pci.h" +#include "pci/pci.h" #include "net.h" #include "sh7750_regs.h" #include "ide.h" diff --git a/hw/realview.c b/hw/realview.c index e789c159a9..149bb562af 100644 --- a/hw/realview.c +++ b/hw/realview.c @@ -11,7 +11,7 @@ #include "arm-misc.h" #include "primecell.h" #include "devices.h" -#include "pci.h" +#include "pci/pci.h" #include "net.h" #include "sysemu.h" #include "boards.h" diff --git a/hw/rtl8139.c b/hw/rtl8139.c index e3aa8bfb11..e294a2a5e3 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -52,7 +52,7 @@ #include #include "hw.h" -#include "pci.h" +#include "pci/pci.h" #include "dma.h" #include "qemu-timer.h" #include "net.h" diff --git a/hw/serial-pci.c b/hw/serial-pci.c index 95dc5c8d2f..6a2548a515 100644 --- a/hw/serial-pci.c +++ b/hw/serial-pci.c @@ -26,7 +26,7 @@ /* see docs/specs/pci-serial.txt */ #include "serial.h" -#include "pci.h" +#include "pci/pci.h" #define PCI_SERIAL_MAX_PORTS 4 diff --git a/hw/sga.c b/hw/sga.c index a666349f82..5d80efd0c2 100644 --- a/hw/sga.c +++ b/hw/sga.c @@ -24,7 +24,7 @@ * sgabios code originally available at code.google.com/p/sgabios * */ -#include "pci.h" +#include "pci/pci.h" #include "pc.h" #include "loader.h" #include "sysemu.h" diff --git a/hw/sh_pci.c b/hw/sh_pci.c index fdec71b9e8..9ea08c8f8e 100644 --- a/hw/sh_pci.c +++ b/hw/sh_pci.c @@ -23,8 +23,8 @@ */ #include "sysbus.h" #include "sh.h" -#include "pci.h" -#include "pci_host.h" +#include "pci/pci.h" +#include "pci/pci_host.h" #include "bswap.h" #include "exec-memory.h" diff --git a/hw/smbus_ich9.c b/hw/smbus_ich9.c index d202664a36..b7bddc80d3 100644 --- a/hw/smbus_ich9.c +++ b/hw/smbus_ich9.c @@ -27,7 +27,7 @@ #include "hw.h" #include "pc.h" #include "pm_smbus.h" -#include "pci.h" +#include "pci/pci.h" #include "sysemu.h" #include "i2c.h" #include "smbus.h" diff --git a/hw/spapr.c b/hw/spapr.c index ad3f0ea7fc..b0125a892c 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -41,11 +41,11 @@ #include "hw/spapr_vio.h" #include "hw/spapr_pci.h" #include "hw/xics.h" -#include "hw/msi.h" +#include "hw/pci/msi.h" #include "kvm.h" #include "kvm_ppc.h" -#include "pci.h" +#include "pci/pci.h" #include "exec-memory.h" #include "hw/usb.h" diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 3c5b855bc0..2386164d5d 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -23,17 +23,17 @@ * THE SOFTWARE. */ #include "hw.h" -#include "pci.h" -#include "msi.h" -#include "msix.h" -#include "pci_host.h" +#include "pci/pci.h" +#include "pci/msi.h" +#include "pci/msix.h" +#include "pci/pci_host.h" #include "hw/spapr.h" #include "hw/spapr_pci.h" #include "exec-memory.h" #include #include "trace.h" -#include "hw/pci_internals.h" +#include "hw/pci/pci_internals.h" /* Copied from the kernel arch/powerpc/platforms/pseries/msi.c */ #define RTAS_QUERY_FN 0 diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index e307ac8035..7b26ba1561 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -23,8 +23,8 @@ #if !defined(__HW_SPAPR_PCI_H__) #define __HW_SPAPR_PCI_H__ -#include "hw/pci.h" -#include "hw/pci_host.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_host.h" #include "hw/xics.h" #define SPAPR_MSIX_MAX_DEVS 32 diff --git a/hw/sun4u.c b/hw/sun4u.c index b2b51e30c2..47bcf9382d 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "hw.h" -#include "pci.h" +#include "pci/pci.h" #include "apb_pci.h" #include "pc.h" #include "serial.h" diff --git a/hw/unin_pci.c b/hw/unin_pci.c index 9981d949d2..46757924b6 100644 --- a/hw/unin_pci.c +++ b/hw/unin_pci.c @@ -23,8 +23,8 @@ */ #include "hw.h" #include "ppc_mac.h" -#include "pci.h" -#include "pci_host.h" +#include "pci/pci.h" +#include "pci/pci_host.h" /* debug UniNorth */ //#define DEBUG_UNIN diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c index 41dbb539f2..8b043966f6 100644 --- a/hw/usb/hcd-ehci-pci.c +++ b/hw/usb/hcd-ehci-pci.c @@ -16,7 +16,7 @@ */ #include "hw/usb/hcd-ehci.h" -#include "hw/pci.h" +#include "hw/pci/pci.h" #include "range.h" typedef struct EHCIPCIState { diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index e16a2ecab4..4faf8e1aed 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -29,7 +29,7 @@ #include "hw/hw.h" #include "qemu-timer.h" #include "hw/usb.h" -#include "hw/pci.h" +#include "hw/pci/pci.h" #include "hw/sysbus.h" #include "hw/qdev-dma.h" diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index d053791de0..04c944613c 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -27,7 +27,7 @@ */ #include "hw/hw.h" #include "hw/usb.h" -#include "hw/pci.h" +#include "hw/pci/pci.h" #include "qemu-timer.h" #include "iov.h" #include "dma.h" diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index efb509e423..220c3b536a 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -21,9 +21,9 @@ #include "hw/hw.h" #include "qemu-timer.h" #include "hw/usb.h" -#include "hw/pci.h" -#include "hw/msi.h" -#include "hw/msix.h" +#include "hw/pci/pci.h" +#include "hw/pci/msi.h" +#include "hw/pci/msix.h" #include "trace.h" //#define DEBUG_XHCI diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c index e0c3ee36a5..7a543b47d0 100644 --- a/hw/versatile_pci.c +++ b/hw/versatile_pci.c @@ -8,8 +8,8 @@ */ #include "sysbus.h" -#include "pci.h" -#include "pci_host.h" +#include "pci/pci.h" +#include "pci/pci_host.h" #include "exec-memory.h" typedef struct { diff --git a/hw/versatilepb.c b/hw/versatilepb.c index 25e652b1aa..41e39d8fb9 100644 --- a/hw/versatilepb.c +++ b/hw/versatilepb.c @@ -12,7 +12,7 @@ #include "devices.h" #include "net.h" #include "sysemu.h" -#include "pci.h" +#include "pci/pci.h" #include "i2c.h" #include "boards.h" #include "blockdev.h" diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 7c27834e06..45d90ab490 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -31,9 +31,9 @@ #include "exec-memory.h" #include "kvm.h" #include "memory.h" -#include "msi.h" -#include "msix.h" -#include "pci.h" +#include "pci/msi.h" +#include "pci/msix.h" +#include "pci/pci.h" #include "qemu-common.h" #include "qemu-error.h" #include "qemu-queue.h" diff --git a/hw/vga-pci.c b/hw/vga-pci.c index 947e35c76f..0cb318eab6 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -25,7 +25,7 @@ */ #include "hw.h" #include "console.h" -#include "pci.h" +#include "pci/pci.h" #include "vga_int.h" #include "pixel_ops.h" #include "qemu-timer.h" diff --git a/hw/vga.c b/hw/vga.c index 2b0200a164..6d56f8a5d9 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -25,7 +25,7 @@ #include "vga.h" #include "console.h" #include "pc.h" -#include "pci.h" +#include "pci/pci.h" #include "vga_int.h" #include "pixel_ops.h" #include "qemu-timer.h" diff --git a/hw/virtio-balloon.h b/hw/virtio-balloon.h index 73300ddc86..b1828f4a48 100644 --- a/hw/virtio-balloon.h +++ b/hw/virtio-balloon.h @@ -16,7 +16,7 @@ #define _QEMU_VIRTIO_BALLOON_H #include "virtio.h" -#include "pci.h" +#include "pci/pci.h" /* from Linux's linux/virtio_balloon.h */ diff --git a/hw/virtio-net.h b/hw/virtio-net.h index 36aa463812..b13be7ccb5 100644 --- a/hw/virtio-net.h +++ b/hw/virtio-net.h @@ -16,7 +16,7 @@ #include "virtio.h" #include "net.h" -#include "pci.h" +#include "pci/pci.h" #define ETH_ALEN 6 diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 71f4fb5dc6..e9b722dd96 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -22,10 +22,10 @@ #include "virtio-net.h" #include "virtio-serial.h" #include "virtio-scsi.h" -#include "pci.h" +#include "pci/pci.h" #include "qemu-error.h" -#include "msi.h" -#include "msix.h" +#include "pci/msi.h" +#include "pci/msix.h" #include "net.h" #include "loader.h" #include "kvm.h" diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h index 91924f6dfc..7d7cba752d 100644 --- a/hw/virtio-scsi.h +++ b/hw/virtio-scsi.h @@ -16,7 +16,7 @@ #include "virtio.h" #include "net.h" -#include "pci.h" +#include "pci/pci.h" /* The ID for virtio_scsi */ #define VIRTIO_ID_SCSI 8 diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 834588daf6..333ec8cebe 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -24,7 +24,7 @@ #include "hw.h" #include "loader.h" #include "console.h" -#include "pci.h" +#include "pci/pci.h" #undef VERBOSE #define HW_RECT_ACCEL diff --git a/hw/vt82c686.c b/hw/vt82c686.c index 57d16c0134..f963912112 100644 --- a/hw/vt82c686.c +++ b/hw/vt82c686.c @@ -15,7 +15,7 @@ #include "vt82c686.h" #include "i2c.h" #include "smbus.h" -#include "pci.h" +#include "pci/pci.h" #include "isa.h" #include "sysbus.h" #include "mips.h" @@ -27,7 +27,7 @@ #include "exec-memory.h" typedef uint32_t pci_addr_t; -#include "pci_host.h" +#include "pci/pci_host.h" //#define DEBUG_VT82C686B #ifdef DEBUG_VT82C686B diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c index da15c73918..181774220d 100644 --- a/hw/wdt_i6300esb.c +++ b/hw/wdt_i6300esb.c @@ -25,7 +25,7 @@ #include "qemu-timer.h" #include "watchdog.h" #include "hw.h" -#include "pci.h" +#include "pci/pci.h" /*#define I6300ESB_DEBUG 1*/ diff --git a/hw/xen-host-pci-device.h b/hw/xen-host-pci-device.h index 0079daca51..942b24dccc 100644 --- a/hw/xen-host-pci-device.h +++ b/hw/xen-host-pci-device.h @@ -1,7 +1,7 @@ #ifndef XEN_HOST_PCI_DEVICE_H #define XEN_HOST_PCI_DEVICE_H -#include "pci.h" +#include "pci/pci.h" enum { XEN_HOST_PCI_REGION_TYPE_IO = 1 << 1, diff --git a/hw/xen_apic.c b/hw/xen_apic.c index fc4536651a..a6632fe798 100644 --- a/hw/xen_apic.c +++ b/hw/xen_apic.c @@ -10,7 +10,7 @@ * later. See the COPYING file in the top-level directory. */ #include "hw/apic_internal.h" -#include "hw/msi.h" +#include "hw/pci/msi.h" #include "xen.h" static uint64_t xen_apic_mem_read(void *opaque, hwaddr addr, diff --git a/hw/xen_platform.c b/hw/xen_platform.c index a54e7a2cdb..10bb560073 100644 --- a/hw/xen_platform.c +++ b/hw/xen_platform.c @@ -27,7 +27,7 @@ #include "hw.h" #include "pc.h" -#include "pci.h" +#include "pci/pci.h" #include "irq.h" #include "xen_common.h" #include "net.h" diff --git a/hw/xen_pt.c b/hw/xen_pt.c index 7a3846e649..c782cdb283 100644 --- a/hw/xen_pt.c +++ b/hw/xen_pt.c @@ -54,7 +54,7 @@ #include -#include "pci.h" +#include "pci/pci.h" #include "xen.h" #include "xen_backend.h" #include "xen_pt.h" diff --git a/hw/xen_pt.h b/hw/xen_pt.h index f15e69a290..e3497302cf 100644 --- a/hw/xen_pt.h +++ b/hw/xen_pt.h @@ -3,7 +3,7 @@ #include "qemu-common.h" #include "xen_common.h" -#include "pci.h" +#include "pci/pci.h" #include "xen-host-pci-device.h" void xen_pt_log(const PCIDevice *d, const char *f, ...) GCC_FMT_ATTR(2, 3); diff --git a/hw/xio3130_downstream.c b/hw/xio3130_downstream.c index 0d8a5e7020..2dcd46bff1 100644 --- a/hw/xio3130_downstream.c +++ b/hw/xio3130_downstream.c @@ -19,9 +19,9 @@ * with this program; if not, see . */ -#include "pci_ids.h" -#include "msi.h" -#include "pcie.h" +#include "pci/pci_ids.h" +#include "pci/msi.h" +#include "pci/pcie.h" #include "xio3130_downstream.h" #define PCI_DEVICE_ID_TI_XIO3130D 0x8233 /* downstream port */ diff --git a/hw/xio3130_downstream.h b/hw/xio3130_downstream.h index 010487f2d9..559dff6565 100644 --- a/hw/xio3130_downstream.h +++ b/hw/xio3130_downstream.h @@ -1,7 +1,7 @@ #ifndef QEMU_XIO3130_DOWNSTREAM_H #define QEMU_XIO3130_DOWNSTREAM_H -#include "pcie_port.h" +#include "pci/pcie_port.h" PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction, const char *bus_name, pci_map_irq_fn map_irq, diff --git a/hw/xio3130_upstream.c b/hw/xio3130_upstream.c index d46b86c74d..713caf2dda 100644 --- a/hw/xio3130_upstream.c +++ b/hw/xio3130_upstream.c @@ -19,9 +19,9 @@ * with this program; if not, see . */ -#include "pci_ids.h" -#include "msi.h" -#include "pcie.h" +#include "pci/pci_ids.h" +#include "pci/msi.h" +#include "pci/pcie.h" #include "xio3130_upstream.h" #define PCI_DEVICE_ID_TI_XIO3130U 0x8232 /* upstream port */ diff --git a/hw/xio3130_upstream.h b/hw/xio3130_upstream.h index e9969975ff..fa09656b35 100644 --- a/hw/xio3130_upstream.h +++ b/hw/xio3130_upstream.h @@ -1,7 +1,7 @@ #ifndef QEMU_XIO3130_UPSTREAM_H #define QEMU_XIO3130_UPSTREAM_H -#include "pcie_port.h" +#include "pci/pcie_port.h" PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction, const char *bus_name, pci_map_irq_fn map_irq, diff --git a/kvm-all.c b/kvm-all.c index 8e9a8d8fd2..bfa09ad05b 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -26,7 +26,7 @@ #include "qemu-config.h" #include "sysemu.h" #include "hw/hw.h" -#include "hw/msi.h" +#include "hw/pci/msi.h" #include "gdbstub.h" #include "kvm.h" #include "bswap.h" diff --git a/kvm-stub.c b/kvm-stub.c index a3455e2203..d65fd04507 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -12,7 +12,7 @@ #include "qemu-common.h" #include "hw/hw.h" -#include "hw/msi.h" +#include "hw/pci/msi.h" #include "cpu.h" #include "gdbstub.h" #include "kvm.h" diff --git a/monitor.c b/monitor.c index c0e32d60c3..a92ab44384 100644 --- a/monitor.c +++ b/monitor.c @@ -27,7 +27,7 @@ #include "hw/usb.h" #include "hw/pcmcia.h" #include "hw/pc.h" -#include "hw/pci.h" +#include "hw/pci/pci.h" #include "hw/watchdog.h" #include "hw/loader.h" #include "gdbstub.h" diff --git a/target-i386/kvm.c b/target-i386/kvm.c index f669281e13..0901589a88 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -31,7 +31,7 @@ #include "hw/apic.h" #include "ioport.h" #include "hyperv.h" -#include "hw/pci.h" +#include "hw/pci/pci.h" //#define DEBUG_KVM diff --git a/xen-all.c b/xen-all.c index 046cc2ac37..e3a51ccc81 100644 --- a/xen-all.c +++ b/xen-all.c @@ -10,7 +10,7 @@ #include -#include "hw/pci.h" +#include "hw/pci/pci.h" #include "hw/pc.h" #include "hw/xen_common.h" #include "hw/xen_backend.h" From c759b24fae08c6c333df03e1db48e13b7f5eda30 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 12 Dec 2012 23:05:42 +0200 Subject: [PATCH 2002/2270] pci: fix path for local includes Include dependencies from pci core using the correct path. This is required now that it's in the separate directory. Need to check whether they can be minimized, for now, keep the code as is. Signed-off-by: Michael S. Tsirkin --- hw/pci/msi.c | 2 +- hw/pci/msi.h | 2 +- hw/pci/msix.c | 8 ++++---- hw/pci/msix.h | 2 +- hw/pci/pci-hotplug.c | 12 ++++++------ hw/pci/pci-stub.c | 2 +- hw/pci/pci.c | 14 +++++++------- hw/pci/pci.h | 10 +++++----- hw/pci/pci_bridge.c | 4 ++-- hw/pci/pci_bridge.h | 2 +- hw/pci/pci_host.c | 4 ++-- hw/pci/pci_host.h | 2 +- hw/pci/pcie.c | 12 ++++++------ hw/pci/pcie.h | 8 ++++---- hw/pci/pcie_aer.c | 12 ++++++------ hw/pci/pcie_aer.h | 2 +- hw/pci/pcie_host.c | 6 +++--- hw/pci/pcie_host.h | 2 +- hw/pci/pcie_port.c | 2 +- hw/pci/pcie_port.h | 4 ++-- hw/pci/shpc.c | 8 ++++---- hw/pci/slotid_cap.c | 4 ++-- 22 files changed, 62 insertions(+), 62 deletions(-) diff --git a/hw/pci/msi.c b/hw/pci/msi.c index 33037a80e9..680e4637d7 100644 --- a/hw/pci/msi.c +++ b/hw/pci/msi.c @@ -18,7 +18,7 @@ * with this program; if not, see . */ -#include "msi.h" +#include "hw/pci/msi.h" #include "range.h" /* Eventually those constants should go to Linux pci_regs.h */ diff --git a/hw/pci/msi.h b/hw/pci/msi.h index 150b09a19d..81a3848a31 100644 --- a/hw/pci/msi.h +++ b/hw/pci/msi.h @@ -22,7 +22,7 @@ #define QEMU_MSI_H #include "qemu-common.h" -#include "pci.h" +#include "hw/pci/pci.h" struct MSIMessage { uint64_t address; diff --git a/hw/pci/msix.c b/hw/pci/msix.c index 136ef09373..917327bfe6 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -14,10 +14,10 @@ * GNU GPL, version 2 or (at your option) any later version. */ -#include "hw.h" -#include "msi.h" -#include "msix.h" -#include "pci.h" +#include "hw/hw.h" +#include "hw/pci/msi.h" +#include "hw/pci/msix.h" +#include "hw/pci/pci.h" #include "range.h" #define MSIX_CAP_LENGTH 12 diff --git a/hw/pci/msix.h b/hw/pci/msix.h index 15211cb592..ff07ae2e8f 100644 --- a/hw/pci/msix.h +++ b/hw/pci/msix.h @@ -2,7 +2,7 @@ #define QEMU_MSIX_H #include "qemu-common.h" -#include "pci.h" +#include "hw/pci/pci.h" void msix_set_message(PCIDevice *dev, int vector, MSIMessage msg); int msix_init(PCIDevice *dev, unsigned short nentries, diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug.c index 3bcfdcc1a6..4b4c931c74 100644 --- a/hw/pci/pci-hotplug.c +++ b/hw/pci/pci-hotplug.c @@ -22,14 +22,14 @@ * THE SOFTWARE. */ -#include "hw.h" -#include "boards.h" -#include "pci.h" +#include "hw/hw.h" +#include "hw/boards.h" +#include "hw/pci/pci.h" #include "net.h" -#include "pc.h" +#include "hw/pc.h" #include "monitor.h" -#include "scsi.h" -#include "virtio-blk.h" +#include "hw/scsi.h" +#include "hw/virtio-blk.h" #include "qemu-config.h" #include "blockdev.h" #include "error.h" diff --git a/hw/pci/pci-stub.c b/hw/pci/pci-stub.c index 134c4484b6..b5c43a935b 100644 --- a/hw/pci/pci-stub.c +++ b/hw/pci/pci-stub.c @@ -20,7 +20,7 @@ #include "sysemu.h" #include "monitor.h" -#include "pci.h" +#include "hw/pci/pci.h" #include "qmp-commands.h" PciInfoList *qmp_query_pci(Error **errp) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 97a0cd77c1..c107fe2232 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -21,18 +21,18 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "hw.h" -#include "pci.h" -#include "pci_bridge.h" -#include "pci_internals.h" +#include "hw/hw.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_bridge.h" +#include "hw/pci/pci_internals.h" #include "monitor.h" #include "net.h" #include "sysemu.h" -#include "loader.h" +#include "hw/loader.h" #include "range.h" #include "qmp-commands.h" -#include "msi.h" -#include "msix.h" +#include "hw/pci/msi.h" +#include "hw/pci/msix.h" #include "exec-memory.h" //#define DEBUG_PCI diff --git a/hw/pci/pci.h b/hw/pci/pci.h index 4da0c2a4c9..41e5ddd1c4 100644 --- a/hw/pci/pci.h +++ b/hw/pci/pci.h @@ -3,14 +3,14 @@ #include "qemu-common.h" -#include "qdev.h" +#include "hw/qdev.h" #include "memory.h" #include "dma.h" /* PCI includes legacy ISA access. */ -#include "isa.h" +#include "hw/isa.h" -#include "pcie.h" +#include "hw/pci/pcie.h" /* PCI bus */ @@ -21,7 +21,7 @@ #define PCI_FUNC_MAX 8 /* Class, Vendor and Device IDs from Linux's pci_ids.h */ -#include "pci_ids.h" +#include "hw/pci/pci_ids.h" /* QEMU-specific Vendor and Device ID definitions */ @@ -100,7 +100,7 @@ typedef struct PCIIORegion { #define PCI_ROM_SLOT 6 #define PCI_NUM_REGIONS 7 -#include "pci_regs.h" +#include "hw/pci/pci_regs.h" /* PCI HEADER_TYPE */ #define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80 diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c index 4680501e4e..eb6b70bb64 100644 --- a/hw/pci/pci_bridge.c +++ b/hw/pci/pci_bridge.c @@ -29,8 +29,8 @@ * VA Linux Systems Japan K.K. */ -#include "pci_bridge.h" -#include "pci_internals.h" +#include "hw/pci/pci_bridge.h" +#include "hw/pci/pci_internals.h" #include "range.h" /* PCI bridge subsystem vendor ID helper functions */ diff --git a/hw/pci/pci_bridge.h b/hw/pci/pci_bridge.h index a00accc172..455cb6677a 100644 --- a/hw/pci/pci_bridge.h +++ b/hw/pci/pci_bridge.h @@ -26,7 +26,7 @@ #ifndef QEMU_PCI_BRIDGE_H #define QEMU_PCI_BRIDGE_H -#include "pci.h" +#include "hw/pci/pci.h" int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset, uint16_t svid, uint16_t ssid); diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c index 68e328cd23..daca1c1ea0 100644 --- a/hw/pci/pci_host.c +++ b/hw/pci/pci_host.c @@ -18,8 +18,8 @@ * with this program; if not, see . */ -#include "pci.h" -#include "pci_host.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_host.h" /* debug PCI */ //#define DEBUG_PCI diff --git a/hw/pci/pci_host.h b/hw/pci/pci_host.h index 4b9c300fcf..1845d4dfd5 100644 --- a/hw/pci/pci_host.h +++ b/hw/pci/pci_host.h @@ -28,7 +28,7 @@ #ifndef PCI_HOST_H #define PCI_HOST_H -#include "sysbus.h" +#include "hw/sysbus.h" #define TYPE_PCI_HOST_BRIDGE "pci-host-bridge" #define PCI_HOST_BRIDGE(obj) \ diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 7c92f193e7..b98adbf87a 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -19,12 +19,12 @@ */ #include "qemu-common.h" -#include "pci_bridge.h" -#include "pcie.h" -#include "msix.h" -#include "msi.h" -#include "pci_internals.h" -#include "pcie_regs.h" +#include "hw/pci/pci_bridge.h" +#include "hw/pci/pcie.h" +#include "hw/pci/msix.h" +#include "hw/pci/msi.h" +#include "hw/pci/pci_internals.h" +#include "hw/pci/pcie_regs.h" #include "range.h" //#define DEBUG_PCIE diff --git a/hw/pci/pcie.h b/hw/pci/pcie.h index 4889194ae6..31604e2742 100644 --- a/hw/pci/pcie.h +++ b/hw/pci/pcie.h @@ -21,10 +21,10 @@ #ifndef QEMU_PCIE_H #define QEMU_PCIE_H -#include "hw.h" -#include "pci_regs.h" -#include "pcie_regs.h" -#include "pcie_aer.h" +#include "hw/hw.h" +#include "hw/pci/pci_regs.h" +#include "hw/pci/pcie_regs.h" +#include "hw/pci/pcie_aer.h" typedef enum { /* for attention and power indicator */ diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c index b04c164e22..3026b66916 100644 --- a/hw/pci/pcie_aer.c +++ b/hw/pci/pcie_aer.c @@ -21,12 +21,12 @@ #include "sysemu.h" #include "qemu-objects.h" #include "monitor.h" -#include "pci_bridge.h" -#include "pcie.h" -#include "msix.h" -#include "msi.h" -#include "pci_internals.h" -#include "pcie_regs.h" +#include "hw/pci/pci_bridge.h" +#include "hw/pci/pcie.h" +#include "hw/pci/msix.h" +#include "hw/pci/msi.h" +#include "hw/pci/pci_internals.h" +#include "hw/pci/pcie_regs.h" //#define DEBUG_PCIE #ifdef DEBUG_PCIE diff --git a/hw/pci/pcie_aer.h b/hw/pci/pcie_aer.h index 7539500cd8..bcac80a7b0 100644 --- a/hw/pci/pcie_aer.h +++ b/hw/pci/pcie_aer.h @@ -21,7 +21,7 @@ #ifndef QEMU_PCIE_AER_H #define QEMU_PCIE_AER_H -#include "hw.h" +#include "hw/hw.h" /* definitions which PCIExpressDevice uses */ diff --git a/hw/pci/pcie_host.c b/hw/pci/pcie_host.c index c257fb43ca..ab8d251de6 100644 --- a/hw/pci/pcie_host.c +++ b/hw/pci/pcie_host.c @@ -19,9 +19,9 @@ * with this program; if not, see . */ -#include "hw.h" -#include "pci.h" -#include "pcie_host.h" +#include "hw/hw.h" +#include "hw/pci/pci.h" +#include "hw/pci/pcie_host.h" #include "exec-memory.h" /* diff --git a/hw/pci/pcie_host.h b/hw/pci/pcie_host.h index 392193530d..150bef9736 100644 --- a/hw/pci/pcie_host.h +++ b/hw/pci/pcie_host.h @@ -21,7 +21,7 @@ #ifndef PCIE_HOST_H #define PCIE_HOST_H -#include "pci_host.h" +#include "hw/pci/pci_host.h" #include "memory.h" #define TYPE_PCIE_HOST_BRIDGE "pcie-host-bridge" diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c index d6350e5e73..33a6b0a08a 100644 --- a/hw/pci/pcie_port.c +++ b/hw/pci/pcie_port.c @@ -18,7 +18,7 @@ * with this program; if not, see . */ -#include "pcie_port.h" +#include "hw/pci/pcie_port.h" void pcie_port_init_reg(PCIDevice *d) { diff --git a/hw/pci/pcie_port.h b/hw/pci/pcie_port.h index 3709583cc0..3259e6a9b9 100644 --- a/hw/pci/pcie_port.h +++ b/hw/pci/pcie_port.h @@ -21,8 +21,8 @@ #ifndef QEMU_PCIE_PORT_H #define QEMU_PCIE_PORT_H -#include "pci_bridge.h" -#include "pci_internals.h" +#include "hw/pci/pci_bridge.h" +#include "hw/pci/pci_internals.h" struct PCIEPort { PCIBridge br; diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c index 4597bbde75..38693f759f 100644 --- a/hw/pci/shpc.c +++ b/hw/pci/shpc.c @@ -2,10 +2,10 @@ #include #include "range.h" #include "range.h" -#include "shpc.h" -#include "pci.h" -#include "pci_internals.h" -#include "msi.h" +#include "hw/pci/shpc.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_internals.h" +#include "hw/pci/msi.h" /* TODO: model power only and disabled slot states. */ /* TODO: handle SERR and wakeups */ diff --git a/hw/pci/slotid_cap.c b/hw/pci/slotid_cap.c index 01064521a9..99a30f429d 100644 --- a/hw/pci/slotid_cap.c +++ b/hw/pci/slotid_cap.c @@ -1,5 +1,5 @@ -#include "slotid_cap.h" -#include "pci.h" +#include "hw/pci/slotid_cap.h" +#include "hw/pci/pci.h" #define SLOTID_CAP_LENGTH 4 #define SLOTID_NSLOTS_SHIFT (ffs(PCI_SID_ESR_NSLOTS) - 1) From d9fb58054825ef141e6d03f455654b2e3e767bce Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 12 Dec 2012 14:39:01 +0200 Subject: [PATCH 2003/2270] Revert "pci: prepare makefiles for pci code reorganization" This reverts commit 475d67c3bcd6ba9fef917b6e59d96ae69eb1a9b4. Now that all users have been updated, we don't need the makefile hack or the softlink anymore. Signed-off-by: Michael S. Tsirkin --- Makefile | 1 - Makefile.target | 1 - Makefile.user | 1 - hw/pci/hw | 1 - 4 files changed, 4 deletions(-) delete mode 120000 hw/pci/hw diff --git a/Makefile b/Makefile index b9a81d18a2..9ecbcbb0a7 100644 --- a/Makefile +++ b/Makefile @@ -146,7 +146,6 @@ audio/audio.o audio/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS) QEMU_CFLAGS+=$(CURL_CFLAGS) QEMU_CFLAGS += -I$(SRC_PATH)/include -QEMU_CFLAGS+=-I$(SRC_PATH)/hw/pci -I$(SRC_PATH)/hw ui/cocoa.o: ui/cocoa.m diff --git a/Makefile.target b/Makefile.target index fe2cc0d8b0..927347bac2 100644 --- a/Makefile.target +++ b/Makefile.target @@ -12,7 +12,6 @@ endif QEMU_CFLAGS += -I.. -I$(SRC_PATH)/target-$(TARGET_BASE_ARCH) -DNEED_CPU_H QEMU_CFLAGS+=-I$(SRC_PATH)/include -QEMU_CFLAGS+=-I$(SRC_PATH)/hw/pci -I$(SRC_PATH)/hw ifdef CONFIG_USER_ONLY # user emulator name diff --git a/Makefile.user b/Makefile.user index 045ecd3bea..9302d33245 100644 --- a/Makefile.user +++ b/Makefile.user @@ -11,7 +11,6 @@ $(call set-vpath, $(SRC_PATH)) QEMU_CFLAGS+=-I.. QEMU_CFLAGS += -I$(SRC_PATH)/include QEMU_CFLAGS += -DCONFIG_USER_ONLY -QEMU_CFLAGS+=-I$(SRC_PATH)/hw/pci -I$(SRC_PATH)/hw include $(SRC_PATH)/Makefile.objs diff --git a/hw/pci/hw b/hw/pci/hw deleted file mode 120000 index 945c9b46d6..0000000000 --- a/hw/pci/hw +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file From 06aac7bd50cd934f416fe355633c045fee832905 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 12 Dec 2012 15:00:45 +0200 Subject: [PATCH 2004/2270] pci: rename pci_internals.h pci_bus.h There are lots of external users of pci_internals.h, apparently making it an internal interface only didn't work out. Let's stop pretending it's an internal header. Signed-off-by: Michael S. Tsirkin --- hw/apb_pci.c | 2 +- hw/dec_pci.c | 2 +- hw/ich9.h | 2 +- hw/lpc_ich9.c | 2 +- hw/pci/pci.c | 2 +- hw/pci/pci_bridge.c | 2 +- hw/pci/{pci_internals.h => pci_bus.h} | 0 hw/pci/pcie.c | 2 +- hw/pci/pcie_aer.c | 2 +- hw/pci/pcie_port.h | 2 +- hw/pci/shpc.c | 2 +- hw/pci_bridge_dev.c | 2 +- hw/spapr_pci.c | 2 +- 13 files changed, 12 insertions(+), 12 deletions(-) rename hw/pci/{pci_internals.h => pci_bus.h} (100%) diff --git a/hw/apb_pci.c b/hw/apb_pci.c index de594f8c0b..fb7a07de37 100644 --- a/hw/apb_pci.c +++ b/hw/apb_pci.c @@ -30,7 +30,7 @@ #include "pci/pci.h" #include "pci/pci_host.h" #include "pci/pci_bridge.h" -#include "pci/pci_internals.h" +#include "pci/pci_bus.h" #include "apb_pci.h" #include "sysemu.h" #include "exec-memory.h" diff --git a/hw/dec_pci.c b/hw/dec_pci.c index a6a7c846fd..ee3f4ca834 100644 --- a/hw/dec_pci.c +++ b/hw/dec_pci.c @@ -28,7 +28,7 @@ #include "pci/pci.h" #include "pci/pci_host.h" #include "pci/pci_bridge.h" -#include "pci/pci_internals.h" +#include "pci/pci_bus.h" /* debug DEC */ //#define DEBUG_DEC diff --git a/hw/ich9.h b/hw/ich9.h index ddd12934d5..5c73f94caf 100644 --- a/hw/ich9.h +++ b/hw/ich9.h @@ -14,7 +14,7 @@ #include "acpi.h" #include "acpi_ich9.h" #include "pam.h" -#include "pci/pci_internals.h" +#include "pci/pci_bus.h" void ich9_lpc_set_irq(void *opaque, int irq_num, int level); int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx); diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c index 811bf261c3..30505789f8 100644 --- a/hw/lpc_ich9.c +++ b/hw/lpc_ich9.c @@ -42,7 +42,7 @@ #include "acpi.h" #include "acpi_ich9.h" #include "pam.h" -#include "pci/pci_internals.h" +#include "pci/pci_bus.h" #include "exec-memory.h" #include "sysemu.h" diff --git a/hw/pci/pci.c b/hw/pci/pci.c index c107fe2232..2e455e22d2 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -24,7 +24,7 @@ #include "hw/hw.h" #include "hw/pci/pci.h" #include "hw/pci/pci_bridge.h" -#include "hw/pci/pci_internals.h" +#include "hw/pci/pci_bus.h" #include "monitor.h" #include "net.h" #include "sysemu.h" diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c index eb6b70bb64..131091408d 100644 --- a/hw/pci/pci_bridge.c +++ b/hw/pci/pci_bridge.c @@ -30,7 +30,7 @@ */ #include "hw/pci/pci_bridge.h" -#include "hw/pci/pci_internals.h" +#include "hw/pci/pci_bus.h" #include "range.h" /* PCI bridge subsystem vendor ID helper functions */ diff --git a/hw/pci/pci_internals.h b/hw/pci/pci_bus.h similarity index 100% rename from hw/pci/pci_internals.h rename to hw/pci/pci_bus.h diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index b98adbf87a..b60a6faaf3 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -23,7 +23,7 @@ #include "hw/pci/pcie.h" #include "hw/pci/msix.h" #include "hw/pci/msi.h" -#include "hw/pci/pci_internals.h" +#include "hw/pci/pci_bus.h" #include "hw/pci/pcie_regs.h" #include "range.h" diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c index 3026b66916..8a2032ca49 100644 --- a/hw/pci/pcie_aer.c +++ b/hw/pci/pcie_aer.c @@ -25,7 +25,7 @@ #include "hw/pci/pcie.h" #include "hw/pci/msix.h" #include "hw/pci/msi.h" -#include "hw/pci/pci_internals.h" +#include "hw/pci/pci_bus.h" #include "hw/pci/pcie_regs.h" //#define DEBUG_PCIE diff --git a/hw/pci/pcie_port.h b/hw/pci/pcie_port.h index 3259e6a9b9..d89aa615c5 100644 --- a/hw/pci/pcie_port.h +++ b/hw/pci/pcie_port.h @@ -22,7 +22,7 @@ #define QEMU_PCIE_PORT_H #include "hw/pci/pci_bridge.h" -#include "hw/pci/pci_internals.h" +#include "hw/pci/pci_bus.h" struct PCIEPort { PCIBridge br; diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c index 38693f759f..18b1512b43 100644 --- a/hw/pci/shpc.c +++ b/hw/pci/shpc.c @@ -4,7 +4,7 @@ #include "range.h" #include "hw/pci/shpc.h" #include "hw/pci/pci.h" -#include "hw/pci/pci_internals.h" +#include "hw/pci/pci_bus.h" #include "hw/pci/msi.h" /* TODO: model power only and disabled slot states. */ diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c index 5c9fc5036b..dbb4b3b433 100644 --- a/hw/pci_bridge_dev.c +++ b/hw/pci_bridge_dev.c @@ -25,7 +25,7 @@ #include "pci/shpc.h" #include "pci/slotid_cap.h" #include "memory.h" -#include "pci/pci_internals.h" +#include "pci/pci_bus.h" #define REDHAT_PCI_VENDOR_ID 0x1b36 #define PCI_BRIDGE_DEV_VENDOR_ID REDHAT_PCI_VENDOR_ID diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 2386164d5d..786f6f4222 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -33,7 +33,7 @@ #include #include "trace.h" -#include "hw/pci/pci_internals.h" +#include "hw/pci/pci_bus.h" /* Copied from the kernel arch/powerpc/platforms/pseries/msi.c */ #define RTAS_QUERY_FN 0 From 952deab6cff5d6d81ff7a63955e958894c07177c Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 12 Dec 2012 15:04:09 +0200 Subject: [PATCH 2005/2270] pci_bus: update comment Don't ask everyone to desist from including this header, simply recommend using accessors. Signed-off-by: Michael S. Tsirkin --- hw/pci/pci_bus.h | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/hw/pci/pci_bus.h b/hw/pci/pci_bus.h index 21d0ce6973..8217f61969 100644 --- a/hw/pci/pci_bus.h +++ b/hw/pci/pci_bus.h @@ -2,14 +2,10 @@ #define QEMU_PCI_INTERNALS_H /* - * This header files is private to pci.c and pci_bridge.c - * So following structures are opaque to others and shouldn't be - * accessed. + * PCI Bus and Bridge datastructures. * - * For pci-to-pci bridge needs to include this header file to embed - * PCIBridge in its structure or to get sizeof(PCIBridge), - * However, they shouldn't access those following members directly. - * Use accessor function in pci.h, pci_bridge.h + * Do not access the following members directly; + * use accessor functions in pci.h, pci_bridge.h */ #define TYPE_PCI_BUS "PCI" From 2059946358999da80be22494af2d5c3174142902 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 12 Dec 2012 23:11:16 +0200 Subject: [PATCH 2006/2270] pci_bus.h: tweak include guards Now that header has been renamed, tweak include guards to match. Signed-off-by: Michael S. Tsirkin --- hw/pci/pci_bus.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/pci/pci_bus.h b/hw/pci/pci_bus.h index 8217f61969..f905b9e11e 100644 --- a/hw/pci/pci_bus.h +++ b/hw/pci/pci_bus.h @@ -1,5 +1,5 @@ -#ifndef QEMU_PCI_INTERNALS_H -#define QEMU_PCI_INTERNALS_H +#ifndef QEMU_PCI_BUS_H +#define QEMU_PCI_BUS_H /* * PCI Bus and Bridge datastructures. @@ -71,4 +71,4 @@ struct PCIBridge { const char *bus_name; }; -#endif /* QEMU_PCI_INTERNALS_H */ +#endif /* QEMU_PCI_BUS_H */ From 1dd3a74d2ee2d873cde0b390b536e45420b3fe05 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 10 Dec 2012 13:00:45 +0200 Subject: [PATCH 2007/2270] kvm: do not flush after deleting gsi Deleting a GSI isn't necessary: it is enough to stop using it. Delay flush until an entry is used. Signed-off-by: Michael S. Tsirkin --- kvm-all.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index bfa09ad05b..759ef17ab0 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -991,8 +991,6 @@ void kvm_irqchip_release_virq(KVMState *s, int virq) } } clear_gsi(s, virq); - - kvm_irqchip_commit_routes(s); } static unsigned int kvm_hash_msi(uint32_t data) From 2c1d4d15f09cf95b8f832624e7aac2916f9d1865 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Mon, 17 Dec 2012 11:36:09 +0000 Subject: [PATCH 2008/2270] xen: implement support for secondary consoles in the console backend This patch corresponds to commit 840184a106bc24e745beda5c77e392f6cecd2bc9 from git://xenbits.xensource.com/qemu-xen-unstable.git. Signed-off-by: Stefano Stabellini --- hw/xen_console.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/hw/xen_console.c b/hw/xen_console.c index 9426d7374f..134988144b 100644 --- a/hw/xen_console.c +++ b/hw/xen_console.c @@ -184,7 +184,11 @@ static int con_init(struct XenDevice *xendev) /* setup */ dom = xs_get_domain_path(xenstore, con->xendev.dom); - snprintf(con->console, sizeof(con->console), "%s/console", dom); + if (!xendev->dev) { + snprintf(con->console, sizeof(con->console), "%s/console", dom); + } else { + snprintf(con->console, sizeof(con->console), "%s/device/console/%d", dom, xendev->dev); + } free(dom); type = xenstore_read_str(con->console, "type"); @@ -223,10 +227,16 @@ static int con_initialise(struct XenDevice *xendev) if (xenstore_read_int(con->console, "limit", &limit) == 0) con->buffer.max_capacity = limit; - con->sring = xc_map_foreign_range(xen_xc, con->xendev.dom, - XC_PAGE_SIZE, - PROT_READ|PROT_WRITE, - con->ring_ref); + if (!xendev->dev) { + con->sring = xc_map_foreign_range(xen_xc, con->xendev.dom, + XC_PAGE_SIZE, + PROT_READ|PROT_WRITE, + con->ring_ref); + } else { + con->sring = xc_gnttab_map_grant_ref(xendev->gnttabdev, con->xendev.dom, + con->ring_ref, + PROT_READ|PROT_WRITE); + } if (!con->sring) return -1; @@ -255,7 +265,11 @@ static void con_disconnect(struct XenDevice *xendev) xen_be_unbind_evtchn(&con->xendev); if (con->sring) { - munmap(con->sring, XC_PAGE_SIZE); + if (!xendev->gnttabdev) { + munmap(con->sring, XC_PAGE_SIZE); + } else { + xc_gnttab_munmap(xendev->gnttabdev, con->sring, 1); + } con->sring = NULL; } } @@ -273,7 +287,7 @@ static void con_event(struct XenDevice *xendev) struct XenDevOps xen_console_ops = { .size = sizeof(struct XenConsole), - .flags = DEVOPS_FLAG_IGNORE_STATE, + .flags = DEVOPS_FLAG_IGNORE_STATE|DEVOPS_FLAG_NEED_GNTDEV, .init = con_init, .initialise = con_initialise, .event = con_event, From 044b99c6555f562254ae70dc39f32190eecbc1f2 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Mon, 17 Dec 2012 11:36:58 +0000 Subject: [PATCH 2009/2270] xen: fix trivial PCI passthrough MSI-X bug We are currently passing entry->data as address parameter. Pass entry->addr instead. Signed-off-by: Stefano Stabellini Tested-by: Sander Eikelenboom Xen-devel: http://marc.info/?l=xen-devel&m=135515462613715 --- hw/xen_pt_msi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xen_pt_msi.c b/hw/xen_pt_msi.c index 680767229b..db757cd1f1 100644 --- a/hw/xen_pt_msi.c +++ b/hw/xen_pt_msi.c @@ -321,7 +321,7 @@ static int xen_pt_msix_update_one(XenPCIPassthroughState *s, int entry_nr) pirq = entry->pirq; - rc = msi_msix_setup(s, entry->data, entry->data, &pirq, true, entry_nr, + rc = msi_msix_setup(s, entry->addr, entry->data, &pirq, true, entry_nr, entry->pirq == XEN_PT_UNASSIGNED_PIRQ); if (rc) { return rc; From f1b8caf1d927f30f66054733a783651a24db4999 Mon Sep 17 00:00:00 2001 From: Sander Eikelenboom Date: Mon, 17 Dec 2012 11:37:43 +0000 Subject: [PATCH 2010/2270] Fix compile errors when enabling Xen debug logging. Signed-off-by: Sander Eikelenboom Acked-by: Stefano Stabellini --- hw/xen_pt.c | 5 +++-- xen-all.c | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/hw/xen_pt.c b/hw/xen_pt.c index 7a3846e649..7aae826d1f 100644 --- a/hw/xen_pt.c +++ b/hw/xen_pt.c @@ -671,7 +671,8 @@ static int xen_pt_initfn(PCIDevice *d) s->is_virtfn = s->real_device.is_virtfn; if (s->is_virtfn) { XEN_PT_LOG(d, "%04x:%02x:%02x.%d is a SR-IOV Virtual Function\n", - s->real_device.domain, bus, slot, func); + s->real_device.domain, s->real_device.bus, + s->real_device.dev, s->real_device.func); } /* Initialize virtualized PCI configuration (Extended 256 Bytes) */ @@ -752,7 +753,7 @@ out: memory_listener_register(&s->memory_listener, &address_space_memory); memory_listener_register(&s->io_listener, &address_space_io); XEN_PT_LOG(d, "Real physical device %02x:%02x.%d registered successfuly!\n", - bus, slot, func); + s->hostaddr.bus, s->hostaddr.slot, s->hostaddr.function); return 0; } diff --git a/xen-all.c b/xen-all.c index 046cc2ac37..d0142bdf60 100644 --- a/xen-all.c +++ b/xen-all.c @@ -292,7 +292,8 @@ static int xen_add_to_physmap(XenIOState *state, return -1; go_physmap: - DPRINTF("mapping vram to %llx - %llx\n", start_addr, start_addr + size); + DPRINTF("mapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx"\n", + start_addr, start_addr + size); pfn = phys_offset >> TARGET_PAGE_BITS; start_gpfn = start_addr >> TARGET_PAGE_BITS; @@ -365,8 +366,8 @@ static int xen_remove_from_physmap(XenIOState *state, phys_offset = physmap->phys_offset; size = physmap->size; - DPRINTF("unmapping vram to %llx - %llx, from %llx\n", - phys_offset, phys_offset + size, start_addr); + DPRINTF("unmapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx", from ", + "%"HWADDR_PRIx"\n", phys_offset, phys_offset + size, start_addr); size >>= TARGET_PAGE_BITS; start_addr >>= TARGET_PAGE_BITS; From a38648290ee277c7cb8a53eabdcdb08bb7a9f23f Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 17 Dec 2012 11:43:19 +0000 Subject: [PATCH 2011/2270] cpu_ioreq_pio, cpu_ioreq_move: introduce read_phys_req_item, write_phys_req_item Replace a lot of formulaic multiplications (containing casts, no less) with calls to a pair of functions. This encapsulates in a single place the operations which require care relating to integer overflow. Cc: Dongxiao Xu Signed-off-by: Ian Jackson Acked-by: Stefano Stabellini --- xen-all.c | 76 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/xen-all.c b/xen-all.c index d0142bdf60..ef430ca21e 100644 --- a/xen-all.c +++ b/xen-all.c @@ -683,11 +683,45 @@ static void do_outp(pio_addr_t addr, } } +/* + * Helper functions which read/write an object from/to physical guest + * memory, as part of the implementation of an ioreq. + * + * Equivalent to + * cpu_physical_memory_rw(addr + (req->df ? -1 : +1) * req->size * i, + * val, req->size, 0/1) + * except without the integer overflow problems. + */ +static void rw_phys_req_item(hwaddr addr, + ioreq_t *req, uint32_t i, void *val, int rw) +{ + /* Do everything unsigned so overflow just results in a truncated result + * and accesses to undesired parts of guest memory, which is up + * to the guest */ + hwaddr offset = (hwaddr)req->size * i; + if (req->df) { + addr -= offset; + } else { + addr += offset; + } + cpu_physical_memory_rw(addr, val, req->size, rw); +} + +static inline void read_phys_req_item(hwaddr addr, + ioreq_t *req, uint32_t i, void *val) +{ + rw_phys_req_item(addr, req, i, val, 0); +} +static inline void write_phys_req_item(hwaddr addr, + ioreq_t *req, uint32_t i, void *val) +{ + rw_phys_req_item(addr, req, i, val, 1); +} + + static void cpu_ioreq_pio(ioreq_t *req) { - int i, sign; - - sign = req->df ? -1 : 1; + int i; if (req->dir == IOREQ_READ) { if (!req->data_is_ptr) { @@ -697,9 +731,7 @@ static void cpu_ioreq_pio(ioreq_t *req) for (i = 0; i < req->count; i++) { tmp = do_inp(req->addr, req->size); - cpu_physical_memory_write( - req->data + (sign * i * (int64_t)req->size), - (uint8_t *) &tmp, req->size); + write_phys_req_item(req->data, req, i, &tmp); } } } else if (req->dir == IOREQ_WRITE) { @@ -709,9 +741,7 @@ static void cpu_ioreq_pio(ioreq_t *req) for (i = 0; i < req->count; i++) { uint32_t tmp = 0; - cpu_physical_memory_read( - req->data + (sign * i * (int64_t)req->size), - (uint8_t*) &tmp, req->size); + read_phys_req_item(req->data, req, i, &tmp); do_outp(req->addr, req->size, tmp); } } @@ -720,22 +750,16 @@ static void cpu_ioreq_pio(ioreq_t *req) static void cpu_ioreq_move(ioreq_t *req) { - int i, sign; - - sign = req->df ? -1 : 1; + int i; if (!req->data_is_ptr) { if (req->dir == IOREQ_READ) { for (i = 0; i < req->count; i++) { - cpu_physical_memory_read( - req->addr + (sign * i * (int64_t)req->size), - (uint8_t *) &req->data, req->size); + read_phys_req_item(req->addr, req, i, &req->data); } } else if (req->dir == IOREQ_WRITE) { for (i = 0; i < req->count; i++) { - cpu_physical_memory_write( - req->addr + (sign * i * (int64_t)req->size), - (uint8_t *) &req->data, req->size); + write_phys_req_item(req->addr, req, i, &req->data); } } } else { @@ -743,21 +767,13 @@ static void cpu_ioreq_move(ioreq_t *req) if (req->dir == IOREQ_READ) { for (i = 0; i < req->count; i++) { - cpu_physical_memory_read( - req->addr + (sign * i * (int64_t)req->size), - (uint8_t*) &tmp, req->size); - cpu_physical_memory_write( - req->data + (sign * i * (int64_t)req->size), - (uint8_t*) &tmp, req->size); + read_phys_req_item(req->addr, req, i, &tmp); + write_phys_req_item(req->data, req, i, &tmp); } } else if (req->dir == IOREQ_WRITE) { for (i = 0; i < req->count; i++) { - cpu_physical_memory_read( - req->data + (sign * i * (int64_t)req->size), - (uint8_t*) &tmp, req->size); - cpu_physical_memory_write( - req->addr + (sign * i * (int64_t)req->size), - (uint8_t*) &tmp, req->size); + read_phys_req_item(req->data, req, i, &tmp); + write_phys_req_item(req->addr, req, i, &tmp); } } } From 249e7e0fff080df0eff54730f3b6459d92d61e5a Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 17 Dec 2012 11:44:02 +0000 Subject: [PATCH 2012/2270] cpu_ioreq_pio, cpu_ioreq_move: i should be uint32_t rather than int The current code compare i (int) with req->count (uint32_t) in a for loop, risking an infinite loop if req->count is equal to UINT_MAX. Also i is only used in comparisons or multiplications with unsigned integers. Signed-off-by: Stefano Stabellini Cc: Dongxiao Xu Cc: Stefano Stabellini Signed-off-by: Ian Jackson --- xen-all.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xen-all.c b/xen-all.c index ef430ca21e..daf43b99d0 100644 --- a/xen-all.c +++ b/xen-all.c @@ -721,7 +721,7 @@ static inline void write_phys_req_item(hwaddr addr, static void cpu_ioreq_pio(ioreq_t *req) { - int i; + uint32_t i; if (req->dir == IOREQ_READ) { if (!req->data_is_ptr) { @@ -750,7 +750,7 @@ static void cpu_ioreq_pio(ioreq_t *req) static void cpu_ioreq_move(ioreq_t *req) { - int i; + uint32_t i; if (!req->data_is_ptr) { if (req->dir == IOREQ_READ) { From 2f464b5a32b414adb545acc6d94b5c35c7d258ba Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 10 Dec 2012 07:41:07 +0100 Subject: [PATCH 2013/2270] qxl: save qemu_create_displaysurface_from result Spotted by Coverity. https://bugzilla.redhat.com/show_bug.cgi?id=885644 Cc: qemu-stable@nongnu.org Reported-by: Markus Armbruster Signed-off-by: Gerd Hoffmann --- hw/qxl-render.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/hw/qxl-render.c b/hw/qxl-render.c index 98ecb21405..88e63f8085 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -113,11 +113,12 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) qxl->guest_primary.bits_pp); if (qxl->guest_primary.qxl_stride > 0) { qemu_free_displaysurface(vga->ds); - qemu_create_displaysurface_from(qxl->guest_primary.surface.width, - qxl->guest_primary.surface.height, - qxl->guest_primary.bits_pp, - qxl->guest_primary.abs_stride, - qxl->guest_primary.data); + vga->ds->surface = qemu_create_displaysurface_from + (qxl->guest_primary.surface.width, + qxl->guest_primary.surface.height, + qxl->guest_primary.bits_pp, + qxl->guest_primary.abs_stride, + qxl->guest_primary.data); } else { qemu_resize_displaysurface(vga->ds, qxl->guest_primary.surface.width, From 938b8a36b65e44c44ca29245437f8d7ac0f826e8 Mon Sep 17 00:00:00 2001 From: Uri Lublin Date: Wed, 12 Dec 2012 18:30:47 +0200 Subject: [PATCH 2014/2270] qxl+vnc: register a vm state change handler for dummy spice_server When qxl + vnc are used, a dummy spice_server is initialized. The spice_server has to be told when the VM runstate changes, which is what this patch does. Without it, from qxl_send_events(), the following error message is shown: qxl_send_events: spice-server bug: guest stopped, ignoring Cc: qemu-stable@nongnu.org Signed-off-by: Uri Lublin Signed-off-by: Gerd Hoffmann --- ui/spice-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/spice-core.c b/ui/spice-core.c index 261c6f2c11..59ce5f6370 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -732,6 +732,8 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin) */ spice_server = spice_server_new(); spice_server_init(spice_server, &core_interface); + qemu_add_vm_change_state_handler(vm_change_state_handler, + &spice_server); } return spice_server_add_interface(spice_server, sin); From 07a54d704e62e2515db0b085d53d13a2f1b1b06a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 5 Dec 2012 16:15:32 +0100 Subject: [PATCH 2015/2270] spice-qemu-char: write to chardev whatever amount it can read The current code waits until the chardev can read MIN(len, VMC_MAX) But some chardev may never reach than amount, in fact some of them will only ever accept write of 1. Fix the min computation and remove the VMC_MAX constant. Signed-off-by: Gerd Hoffmann --- spice-qemu-char.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/spice-qemu-char.c b/spice-qemu-char.c index 09aa22d566..665efd30ee 100644 --- a/spice-qemu-char.c +++ b/spice-qemu-char.c @@ -14,8 +14,6 @@ } \ } while (0) -#define VMC_MAX_HOST_WRITE 2048 - typedef struct SpiceCharDriver { CharDriverState* chr; SpiceCharDeviceInstance sin; @@ -35,8 +33,8 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) uint8_t* p = (uint8_t*)buf; while (len > 0) { - last_out = MIN(len, VMC_MAX_HOST_WRITE); - if (qemu_chr_be_can_write(scd->chr) < last_out) { + last_out = MIN(len, qemu_chr_be_can_write(scd->chr)); + if (last_out <= 0) { break; } qemu_chr_be_write(scd->chr, p, last_out); From 71b423f4b970de2622803a67a2bf39b1d1f5a12c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 5 Dec 2012 16:15:33 +0100 Subject: [PATCH 2016/2270] spice-qemu-char: factor out CharDriverState creation Make the CharDriverState creation code reusable by spicevmc port. Signed-off-by: Gerd Hoffmann --- spice-qemu-char.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/spice-qemu-char.c b/spice-qemu-char.c index 665efd30ee..b86e83ab8c 100644 --- a/spice-qemu-char.c +++ b/spice-qemu-char.c @@ -186,13 +186,32 @@ static void print_allowed_subtypes(void) fprintf(stderr, "\n"); } -CharDriverState *qemu_chr_open_spice(QemuOpts *opts) +static CharDriverState *chr_open(QemuOpts *opts, const char *subtype) { CharDriverState *chr; SpiceCharDriver *s; - const char* name = qemu_opt_get(opts, "name"); uint32_t debug = qemu_opt_get_number(opts, "debug", 0); - const char** psubtype = spice_server_char_device_recognized_subtypes(); + + chr = g_malloc0(sizeof(CharDriverState)); + s = g_malloc0(sizeof(SpiceCharDriver)); + s->chr = chr; + s->debug = debug; + s->active = false; + s->sin.subtype = subtype; + chr->opaque = s; + chr->chr_write = spice_chr_write; + chr->chr_close = spice_chr_close; + chr->chr_guest_open = spice_chr_guest_open; + chr->chr_guest_close = spice_chr_guest_close; + + return chr; +} + +CharDriverState *qemu_chr_open_spice(QemuOpts *opts) +{ + CharDriverState *chr; + const char *name = qemu_opt_get(opts, "name"); + const char **psubtype = spice_server_char_device_recognized_subtypes(); const char *subtype = NULL; if (name == NULL) { @@ -212,17 +231,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts) return NULL; } - chr = g_malloc0(sizeof(CharDriverState)); - s = g_malloc0(sizeof(SpiceCharDriver)); - s->chr = chr; - s->debug = debug; - s->active = false; - s->sin.subtype = subtype; - chr->opaque = s; - chr->chr_write = spice_chr_write; - chr->chr_close = spice_chr_close; - chr->chr_guest_open = spice_chr_guest_open; - chr->chr_guest_close = spice_chr_guest_close; + chr = chr_open(opts, subtype); #if SPICE_SERVER_VERSION < 0x000901 /* See comment in vmc_state() */ From 5a49d3e9a799b7e1bf87da7ae7f2a719e01da319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 5 Dec 2012 16:15:34 +0100 Subject: [PATCH 2017/2270] spice-qemu-char: add spiceport chardev Add a new spice chardev to allow arbitrary communication between the host and the Spice client via the spice server. Examples: This allows the Spice client to have a special port for the qemu monitor: ... -chardev spiceport,name=org.qemu.monitor,id=monitorport -mon chardev=monitorport v2: - remove support for chardev to chardev linking - conditionnaly compile with SPICE_SERVER_VERSION Signed-off-by: Gerd Hoffmann --- qemu-char.c | 3 +++ qemu-options.hx | 13 +++++++++++++ spice-qemu-char.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ trace-events | 1 + ui/qemu-spice.h | 3 +++ 5 files changed, 65 insertions(+) diff --git a/qemu-char.c b/qemu-char.c index 242b799909..9940701d6a 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2762,6 +2762,9 @@ static const struct { #endif #ifdef CONFIG_SPICE { .name = "spicevmc", .open = qemu_chr_open_spice }, +#if SPICE_SERVER_VERSION >= 0x000c02 + { .name = "spiceport", .open = qemu_chr_open_spice_port }, +#endif #endif }; diff --git a/qemu-options.hx b/qemu-options.hx index 231cc4f55f..9df0cde64c 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1749,6 +1749,7 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev, #endif #if defined(CONFIG_SPICE) "-chardev spicevmc,id=id,name=name[,debug=debug]\n" + "-chardev spiceport,id=id,name=name[,debug=debug]\n" #endif , QEMU_ARCH_ALL ) @@ -1776,6 +1777,7 @@ Backend is one of: @option{tty}, @option{parport}, @option{spicevmc}. +@option{spiceport}. The specific backend will determine the applicable options. All devices must have an id, which can be any string up to 127 characters long. @@ -1961,6 +1963,17 @@ required. Connect to a spice virtual machine channel, such as vdiport. +@item -chardev spiceport ,id=@var{id} ,debug=@var{debug}, name=@var{name} + +@option{spiceport} is only available when spice support is built in. + +@option{debug} debug level for spicevmc + +@option{name} name of spice port to connect to + +Connect to a spice port, allowing a Spice client to handle the traffic +identified by a name (preferably a fqdn). + @end table ETEXI diff --git a/spice-qemu-char.c b/spice-qemu-char.c index b86e83ab8c..4be75ba353 100644 --- a/spice-qemu-char.c +++ b/spice-qemu-char.c @@ -3,6 +3,7 @@ #include "ui/qemu-spice.h" #include #include +#include #include "osdep.h" @@ -67,6 +68,27 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) return bytes; } +#if SPICE_SERVER_VERSION >= 0x000c02 +static void vmc_event(SpiceCharDeviceInstance *sin, uint8_t event) +{ + SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); + int chr_event; + + switch (event) { + case SPICE_PORT_EVENT_BREAK: + chr_event = CHR_EVENT_BREAK; + break; + default: + dprintf(scd, 2, "%s: unknown %d\n", __func__, event); + return; + } + + dprintf(scd, 2, "%s: %d\n", __func__, event); + trace_spice_vmc_event(chr_event); + qemu_chr_be_event(scd->chr, chr_event); +} +#endif + static void vmc_state(SpiceCharDeviceInstance *sin, int connected) { SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); @@ -103,6 +125,9 @@ static SpiceCharDeviceInterface vmc_interface = { .state = vmc_state, .write = vmc_write, .read = vmc_read, +#if SPICE_SERVER_VERSION >= 0x000c02 + .event = vmc_event, +#endif }; @@ -242,3 +267,23 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts) return chr; } + +#if SPICE_SERVER_VERSION >= 0x000c02 +CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts) +{ + CharDriverState *chr; + SpiceCharDriver *s; + const char *name = qemu_opt_get(opts, "name"); + + if (name == NULL) { + fprintf(stderr, "spice-qemu-char: missing name parameter\n"); + return NULL; + } + + chr = chr_open(opts, "port"); + s = chr->opaque; + s->sin.portname = name; + + return chr; +} +#endif diff --git a/trace-events b/trace-events index 6cb450a993..bb7621eeb6 100644 --- a/trace-events +++ b/trace-events @@ -535,6 +535,7 @@ spice_vmc_write(ssize_t out, int len) "spice wrottn %zd of requested %d" spice_vmc_read(int bytes, int len) "spice read %d of requested %d" spice_vmc_register_interface(void *scd) "spice vmc registered interface %p" spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p" +spice_vmc_event(int event) "spice vmc event %d" # hw/lm32_pic.c lm32_pic_raise_irq(void) "Raise CPU interrupt" diff --git a/ui/qemu-spice.h b/ui/qemu-spice.h index 3299da87d6..5669767de0 100644 --- a/ui/qemu-spice.h +++ b/ui/qemu-spice.h @@ -46,6 +46,9 @@ void do_info_spice_print(Monitor *mon, const QObject *data); void do_info_spice(Monitor *mon, QObject **ret_data); CharDriverState *qemu_chr_open_spice(QemuOpts *opts); +#if SPICE_SERVER_VERSION >= 0x000c02 +CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts); +#endif #else /* CONFIG_SPICE */ #include "monitor.h" From 7a5448ce6ef140a20b1a090d50aeb4248d0a9ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 5 Dec 2012 16:15:35 +0100 Subject: [PATCH 2018/2270] spice-qemu-char: keep a list of spice chardev Signed-off-by: Gerd Hoffmann --- spice-qemu-char.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spice-qemu-char.c b/spice-qemu-char.c index 4be75ba353..4eb85ae798 100644 --- a/spice-qemu-char.c +++ b/spice-qemu-char.c @@ -24,8 +24,12 @@ typedef struct SpiceCharDriver { uint8_t *datapos; ssize_t bufsize, datalen; uint32_t debug; + QLIST_ENTRY(SpiceCharDriver) next; } SpiceCharDriver; +static QLIST_HEAD(, SpiceCharDriver) spice_chars = + QLIST_HEAD_INITIALIZER(spice_chars); + static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) { SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); @@ -179,6 +183,7 @@ static void spice_chr_close(struct CharDriverState *chr) printf("%s\n", __func__); vmc_unregister_interface(s); + QLIST_REMOVE(s, next); g_free(s); } @@ -229,6 +234,8 @@ static CharDriverState *chr_open(QemuOpts *opts, const char *subtype) chr->chr_guest_open = spice_chr_guest_open; chr->chr_guest_close = spice_chr_guest_close; + QLIST_INSERT_HEAD(&spice_chars, s, next); + return chr; } From afd0b4091fef7a1290cf76c6da8c9a24a3553d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 5 Dec 2012 16:15:36 +0100 Subject: [PATCH 2019/2270] spice-qemu-char: register spicevmc ports during qemu_spice_init() Do the delayed registration of spicevmc ports after Spice server is initialized. Signed-off-by: Gerd Hoffmann --- spice-qemu-char.c | 12 ++++++++++++ ui/qemu-spice.h | 1 + ui/spice-core.c | 4 ++++ 3 files changed, 17 insertions(+) diff --git a/spice-qemu-char.c b/spice-qemu-char.c index 4eb85ae798..b2586c263d 100644 --- a/spice-qemu-char.c +++ b/spice-qemu-char.c @@ -293,4 +293,16 @@ CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts) return chr; } + +void qemu_spice_register_ports(void) +{ + SpiceCharDriver *s; + + QLIST_FOREACH(s, &spice_chars, next) { + if (s->sin.portname == NULL) { + continue; + } + vmc_register_interface(s); + } +} #endif diff --git a/ui/qemu-spice.h b/ui/qemu-spice.h index 5669767de0..642f012690 100644 --- a/ui/qemu-spice.h +++ b/ui/qemu-spice.h @@ -48,6 +48,7 @@ void do_info_spice(Monitor *mon, QObject **ret_data); CharDriverState *qemu_chr_open_spice(QemuOpts *opts); #if SPICE_SERVER_VERSION >= 0x000c02 CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts); +void qemu_spice_register_ports(void); #endif #else /* CONFIG_SPICE */ diff --git a/ui/spice-core.c b/ui/spice-core.c index 59ce5f6370..ac46deb2be 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -714,6 +714,10 @@ void qemu_spice_init(void) g_free(x509_key_file); g_free(x509_cert_file); g_free(x509_cacert_file); + +#if SPICE_SERVER_VERSION >= 0x000c02 + qemu_spice_register_ports(); +#endif } int qemu_spice_add_interface(SpiceBaseInstance *sin) From 700f6b6a921861a8946377a9531b6d1e8b09bb51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 5 Dec 2012 16:15:37 +0100 Subject: [PATCH 2020/2270] docs: add spice-port-fqdn.txt Start a simple org.qemu.* registry of well known name. Signed-off-by: Gerd Hoffmann --- docs/spice-port-fqdn.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 docs/spice-port-fqdn.txt diff --git a/docs/spice-port-fqdn.txt b/docs/spice-port-fqdn.txt new file mode 100644 index 0000000000..50778952e5 --- /dev/null +++ b/docs/spice-port-fqdn.txt @@ -0,0 +1,19 @@ +A Spice port channel is an arbitrary communication between the Spice +server host side and the client side. + +Thanks to the associated reverse fully qualified domain name (fqdn), +a Spice client can handle the various ports appropriately. + +The following fqdn names are reserved by the QEMU project: + +org.qemu.monitor.hmp.0 + QEMU human monitor + +org.qemu.monitor.qmp.0: + QEMU control monitor + +org.qemu.console.serial.0 + QEMU virtual serial port + +org.qemu.console.debug.0 + QEMU debug console From 5f0cef1aa92b98610a99125d1d1d80e9339ac7c5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 27 Sep 2012 09:51:55 +0200 Subject: [PATCH 2021/2270] libcacard: simplify rules for recursive build Signed-off-by: Paolo Bonzini --- Makefile | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 9ecbcbb0a7..d06fbad6c9 100644 --- a/Makefile +++ b/Makefile @@ -169,19 +169,11 @@ libqemustub.a: $(stub-obj-y) # Support building shared library libcacard .PHONY: libcacard.la install-libcacard -ifeq ($(LIBTOOL),) -libcacard.la: - @echo "libtool is missing, please install and rerun configure"; exit 1 - -install-libcacard: - @echo "libtool is missing, please install and rerun configure"; exit 1 -else -libcacard.la: $(oslib-obj-y) qemu-timer-common.o $(addsuffix .lo, $(basename $(trace-obj-y))) +libcacard.la: $(oslib-obj-y) qemu-timer-common.o $(trace-obj-y) $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libcacard V="$(V)" TARGET_DIR="$*/" libcacard.la,) install-libcacard: libcacard.la $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libcacard V="$(V)" TARGET_DIR="$*/" install-libcacard,) -endif ###################################################################### From 4e28976e563ad54f6adc5ae00b1fb8224f1a82ca Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Wed, 12 Dec 2012 18:26:09 +0530 Subject: [PATCH 2022/2270] virtio-serial-bus: send_control_msg() should not deal with cpkts Stuff the cpkt before calling send_control_msg(). This function should not be concerned about contents of the buffer it receives. A few code refactorings recently have made making this change easier than earlier. Coverity and clang have flagged this code several times in the past (cpkt->id not set before send_control_event() passed it on to send_control_msg()). This will finally eliminate the false-positive. CC: Markus Armbruster Reviewed-by: Markus Armbruster Signed-off-by: Amit Shah --- hw/virtio-serial-bus.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index fc0166ca7f..3ea95b8b52 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -217,13 +217,12 @@ static void flush_queued_data(VirtIOSerialPort *port) do_flush_queued_data(port, port->ovq, &port->vser->vdev); } -static size_t send_control_msg(VirtIOSerialPort *port, void *buf, size_t len) +static size_t send_control_msg(VirtIOSerial *vser, void *buf, size_t len) { VirtQueueElement elem; VirtQueue *vq; - struct virtio_console_control *cpkt; - vq = port->vser->c_ivq; + vq = vser->c_ivq; if (!virtio_queue_ready(vq)) { return 0; } @@ -231,25 +230,24 @@ static size_t send_control_msg(VirtIOSerialPort *port, void *buf, size_t len) return 0; } - cpkt = (struct virtio_console_control *)buf; - stl_p(&cpkt->id, port->id); memcpy(elem.in_sg[0].iov_base, buf, len); virtqueue_push(vq, &elem, len); - virtio_notify(&port->vser->vdev, vq); + virtio_notify(&vser->vdev, vq); return len; } -static size_t send_control_event(VirtIOSerialPort *port, uint16_t event, - uint16_t value) +static size_t send_control_event(VirtIOSerial *vser, uint32_t port_id, + uint16_t event, uint16_t value) { struct virtio_console_control cpkt; + stl_p(&cpkt.id, port_id); stw_p(&cpkt.event, event); stw_p(&cpkt.value, value); - trace_virtio_serial_send_control_event(port->id, event, value); - return send_control_msg(port, &cpkt, sizeof(cpkt)); + trace_virtio_serial_send_control_event(port_id, event, value); + return send_control_msg(vser, &cpkt, sizeof(cpkt)); } /* Functions for use inside qemu to open and read from/write to ports */ @@ -261,7 +259,7 @@ int virtio_serial_open(VirtIOSerialPort *port) } /* Send port open notification to the guest */ port->host_connected = true; - send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 1); + send_control_event(port->vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 1); return 0; } @@ -276,7 +274,7 @@ int virtio_serial_close(VirtIOSerialPort *port) port->throttled = false; discard_vq_data(port->ovq, &port->vser->vdev); - send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 0); + send_control_event(port->vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 0); return 0; } @@ -365,7 +363,7 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len) * ports we have here. */ QTAILQ_FOREACH(port, &vser->ports, next) { - send_control_event(port, VIRTIO_CONSOLE_PORT_ADD, 1); + send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_ADD, 1); } return; } @@ -396,10 +394,11 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len) * up to hvc. */ if (vsc->is_console) { - send_control_event(port, VIRTIO_CONSOLE_CONSOLE_PORT, 1); + send_control_event(vser, port->id, VIRTIO_CONSOLE_CONSOLE_PORT, 1); } if (port->name) { + stl_p(&cpkt.id, port->id); stw_p(&cpkt.event, VIRTIO_CONSOLE_PORT_NAME); stw_p(&cpkt.value, 1); @@ -410,12 +409,12 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len) memcpy(buffer + sizeof(cpkt), port->name, strlen(port->name)); buffer[buffer_len - 1] = 0; - send_control_msg(port, buffer, buffer_len); + send_control_msg(vser, buffer, buffer_len); g_free(buffer); } if (port->host_connected) { - send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 1); + send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 1); } /* @@ -655,7 +654,7 @@ static void virtio_serial_post_load_timer_cb(void *opaque) * We have to let the guest know of the host connection * status change */ - send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, + send_control_event(s, port->id, VIRTIO_CONSOLE_PORT_OPEN, port->host_connected); } } @@ -841,9 +840,7 @@ static void mark_port_added(VirtIOSerial *vser, uint32_t port_id) static void add_port(VirtIOSerial *vser, uint32_t port_id) { mark_port_added(vser, port_id); - - send_control_event(find_port_by_id(vser, port_id), - VIRTIO_CONSOLE_PORT_ADD, 1); + send_control_event(vser, port_id, VIRTIO_CONSOLE_PORT_ADD, 1); } static void remove_port(VirtIOSerial *vser, uint32_t port_id) @@ -858,7 +855,7 @@ static void remove_port(VirtIOSerial *vser, uint32_t port_id) /* Flush out any unconsumed buffers first */ discard_vq_data(port->ovq, &port->vser->vdev); - send_control_event(port, VIRTIO_CONSOLE_PORT_REMOVE, 1); + send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_REMOVE, 1); } static int virtser_port_qdev_init(DeviceState *qdev) From 91bdd1cf08f65b7a127c22d4d65ff9d16dcac870 Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Tue, 18 Dec 2012 13:08:33 +0530 Subject: [PATCH 2023/2270] virtio-serial-bus: assert port is non-null in remove_port() remove_port() is called from qdev's unplug callback, and we're certain the port will be found in our list of ports. Adding an assert() documents this. This was flagged by Coverity, fix suggested by Markus. CC: Markus Armbruster Reviewed-by: Markus Armbruster Signed-off-by: Amit Shah --- hw/virtio-serial-bus.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index 3ea95b8b52..ce4556fc48 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -852,6 +852,12 @@ static void remove_port(VirtIOSerial *vser, uint32_t port_id) vser->ports_map[i] &= ~(1U << (port_id % 32)); port = find_port_by_id(vser, port_id); + /* + * This function is only called from qdev's unplug callback; if we + * get a NULL port here, we're in trouble. + */ + assert(port); + /* Flush out any unconsumed buffers first */ discard_vq_data(port->ovq, &port->vser->vdev); From e103129b1b5746f8388b37d18317e61d6b139b69 Mon Sep 17 00:00:00 2001 From: Zhi Yong Wu Date: Fri, 7 Dec 2012 09:43:18 +0800 Subject: [PATCH 2024/2270] net, hub: fix the indent in the comments Remove some redundant blanks in the comments of net_hub_id_for_client(). Signed-off-by: Zhi Yong Wu Signed-off-by: Stefan Hajnoczi --- net/hub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/hub.c b/net/hub.c index be413012bb..3b2d1ffcd2 100644 --- a/net/hub.c +++ b/net/hub.c @@ -256,7 +256,7 @@ void net_hub_info(Monitor *mon) /** * Get the hub id that a client is connected to * - * @id Pointer for hub id output, may be NULL + * @id: Pointer for hub id output, may be NULL */ int net_hub_id_for_client(NetClientState *nc, int *id) { From d96fc51cc6defcd80bdf932823dadd88be532a0b Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 4 Dec 2012 16:04:33 +1000 Subject: [PATCH 2025/2270] pflash_cfi01: qemu_log_mask "unimplemented" msg This printf is informing the user of unimplemented functionality. It should be re-directed to qemu_log(LOG_UNIMP, ...) accordingly. Signed-off-by: Peter Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Stefan Hajnoczi --- hw/pflash_cfi01.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index 7d040b508a..f9f8e5d03c 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -438,9 +438,9 @@ static void pflash_write(pflash_t *pfl, hwaddr offset, return; error_flash: - printf("%s: Unimplemented flash cmd sequence " - "(offset " TARGET_FMT_plx ", wcycle 0x%x cmd 0x%x value 0x%x)\n", - __func__, offset, pfl->wcycle, pfl->cmd, value); + qemu_log_mask(LOG_UNIMP, "%s: Unimplemented flash cmd sequence " + "(offset " TARGET_FMT_plx ", wcycle 0x%x cmd 0x%x value 0x%x)" + "\n", __func__, offset, pfl->wcycle, pfl->cmd, value); reset_flash: memory_region_rom_device_set_readable(&pfl->mem, true); From ec9ea4890cd06de1648cbbfb99fcb63e01f4000f Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 4 Dec 2012 16:04:34 +1000 Subject: [PATCH 2026/2270] pflash_cfi0x: Send debug messages to stderr These debug info messages should go to stderr rather than stdout. Signed-off-by: Peter Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Stefan Hajnoczi --- hw/pflash_cfi01.c | 8 ++++---- hw/pflash_cfi02.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index f9f8e5d03c..931264ff8c 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -46,15 +46,15 @@ #define PFLASH_BUG(fmt, ...) \ do { \ - printf("PFLASH: Possible BUG - " fmt, ## __VA_ARGS__); \ + fprintf(stderr, "PFLASH: Possible BUG - " fmt, ## __VA_ARGS__); \ exit(1); \ } while(0) /* #define PFLASH_DEBUG */ #ifdef PFLASH_DEBUG -#define DPRINTF(fmt, ...) \ -do { \ - printf("PFLASH: " fmt , ## __VA_ARGS__); \ +#define DPRINTF(fmt, ...) \ +do { \ + fprintf(stderr, "PFLASH: " fmt , ## __VA_ARGS__); \ } while (0) #else #define DPRINTF(fmt, ...) do { } while (0) diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c index f918e36580..c60ae831b4 100644 --- a/hw/pflash_cfi02.c +++ b/hw/pflash_cfi02.c @@ -45,9 +45,9 @@ //#define PFLASH_DEBUG #ifdef PFLASH_DEBUG -#define DPRINTF(fmt, ...) \ -do { \ - printf("PFLASH: " fmt , ## __VA_ARGS__); \ +#define DPRINTF(fmt, ...) \ +do { \ + fprintf(stderr "PFLASH: " fmt , ## __VA_ARGS__); \ } while (0) #else #define DPRINTF(fmt, ...) do { } while (0) From 8f6038009662b481fbd1e43cd69af80aa10a8223 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 4 Dec 2012 16:04:35 +1000 Subject: [PATCH 2027/2270] zynq_slcr: Compile time warning fixes. Few warnings when compiled with debug printfs enabled. Fixed all. Signed-off-by: Peter Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Stefan Hajnoczi --- hw/zynq_slcr.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/zynq_slcr.c b/hw/zynq_slcr.c index dde4306195..f55ab8d8a9 100644 --- a/hw/zynq_slcr.c +++ b/hw/zynq_slcr.c @@ -334,7 +334,7 @@ static uint64_t zynq_slcr_read(void *opaque, hwaddr offset, { uint32_t ret = zynq_slcr_read_imp(opaque, offset); - DB_PRINT("addr: %08x data: %08x\n", offset, ret); + DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, (unsigned)ret); return ret; } @@ -343,7 +343,7 @@ static void zynq_slcr_write(void *opaque, hwaddr offset, { ZynqSLCRState *s = (ZynqSLCRState *)opaque; - DB_PRINT("offset: %08x data: %08x\n", offset, (unsigned)val); + DB_PRINT("offset: %08x data: %08x\n", (unsigned)offset, (unsigned)val); switch (offset) { case 0x00: /* SCL */ @@ -476,7 +476,8 @@ static void zynq_slcr_write(void *opaque, hwaddr offset, break; default: bad_reg: - DB_PRINT("Bad register write %x <= %08x\n", (int)offset, val); + DB_PRINT("Bad register write %x <= %08x\n", (int)offset, + (unsigned)val); } } else { DB_PRINT("SCLR registers are locked. Unlock them first\n"); From 8c815fb30ed1940c66389be728b29d5ebdf05c0e Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 4 Dec 2012 16:04:36 +1000 Subject: [PATCH 2028/2270] arm_gic: Add cpu nr to Raised IRQ message Add the relevant CPU nr to this debug message to make IRQ debugging more informative. Signed-off-by: Peter Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Stefan Hajnoczi --- hw/arm_gic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/arm_gic.c b/hw/arm_gic.c index 8d769de4f5..b6062c4241 100644 --- a/hw/arm_gic.c +++ b/hw/arm_gic.c @@ -76,7 +76,7 @@ void gic_update(GICState *s) if (best_prio < s->priority_mask[cpu]) { s->current_pending[cpu] = best_irq; if (best_prio < s->running_priority[cpu]) { - DPRINTF("Raised pending IRQ %d\n", best_irq); + DPRINTF("Raised pending IRQ %d (cpu %d)\n", best_irq, cpu); level = 1; } } From 887eb29930a7b48e46d16916cb050d114016f143 Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Thu, 6 Dec 2012 20:03:26 -0500 Subject: [PATCH 2029/2270] gitignore: Add virtfs-proxy-helper Signed-off-by: Cole Robinson Signed-off-by: Stefan Hajnoczi --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index bd6ba1c71e..3ce57ccd58 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,7 @@ test-qmp-output-visitor test-string-input-visitor test-string-output-visitor test-visitor-serialization +fsdev/virtfs-proxy-helper fsdev/virtfs-proxy-helper.1 fsdev/virtfs-proxy-helper.pod .gdbinit From e12cdb1b4055530c61fe99683d256c42e9e62ac8 Mon Sep 17 00:00:00 2001 From: John Spencer Date: Mon, 10 Dec 2012 07:59:44 +0100 Subject: [PATCH 2030/2270] fix build error on ARM due to wrong glibc check the test for glibc < 2 "succeeds" wrongly for any non-glibc C library, and breaks the build on musl libc. we must first test if __GLIBC__ is defined at all, before using it unconditionally. Signed-off-by: John Spencer Reviewed-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- user-exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user-exec.c b/user-exec.c index 1185cb03c8..5863b9f362 100644 --- a/user-exec.c +++ b/user-exec.c @@ -436,7 +436,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, unsigned long pc; int is_write; -#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) +#if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) pc = uc->uc_mcontext.gregs[R15]; #else pc = uc->uc_mcontext.arm_pc; From c56dc774242f902e51e2343f4472e742ef2b7838 Mon Sep 17 00:00:00 2001 From: John Spencer Date: Mon, 10 Dec 2012 07:59:46 +0100 Subject: [PATCH 2031/2270] linux-user/syscall.c: remove wrong forward decl of setgroups() this declaration is wrong: the correct prototype on linux is: int setgroups(size_t size, const gid_t *list); since by default musl libc exposes this symbol in unistd.h additionally to grp.h, the wrong declaration causes a build error. the proper fix is to simply include the correct header. Signed-off-by: John Spencer Reviewed-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- linux-user/syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 31d5276465..275260a6ff 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -584,7 +585,6 @@ extern int personality(int); extern int flock(int, int); extern int setfsuid(int); extern int setfsgid(int); -extern int setgroups(int, gid_t *); /* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */ #ifdef TARGET_ARM From 5a6c7644b215060a43d94709307d86bc50e1b4b9 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Thu, 13 Dec 2012 15:01:49 +0100 Subject: [PATCH 2032/2270] vmmouse_reset(): remove minimal code duplication Commit 069ab0eb added a vmmouse_disable() call to vmmouse_reset(). vmmouse_disable() resets the status already. Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- hw/vmmouse.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/vmmouse.c b/hw/vmmouse.c index 6338efa1c3..578122c9f5 100644 --- a/hw/vmmouse.c +++ b/hw/vmmouse.c @@ -252,7 +252,6 @@ static void vmmouse_reset(DeviceState *d) { VMMouseState *s = container_of(d, VMMouseState, dev.qdev); - s->status = 0xffff; s->queue_size = VMMOUSE_QUEUE_SIZE; vmmouse_disable(s); From 779ab5e3ddb9ad903f9a0ec21e148ed7bfd2d255 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sun, 16 Dec 2012 11:29:45 +0100 Subject: [PATCH 2033/2270] configure: Earlier pkg-config probe Probe pkg-config before it is used for the first time (libseccomp check). Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- configure | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/configure b/configure index ecdb33a58e..728caca0d0 100755 --- a/configure +++ b/configure @@ -1359,6 +1359,14 @@ esac fi +########################################## +# pkg-config probe + +if ! has "$pkg_config_exe"; then + echo "Error: pkg-config binary '$pkg_config_exe' not found" + exit 1 +fi + ########################################## # NPTL probe @@ -1589,14 +1597,6 @@ if test "$xen_pci_passthrough" != "no"; then fi fi -########################################## -# pkg-config probe - -if ! has "$pkg_config_exe"; then - echo "Error: pkg-config binary '$pkg_config_exe' not found" - exit 1 -fi - ########################################## # libtool probe From 5f5e335088925cedc5b912fd8bb4e1e933094d56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 15 Oct 2012 17:52:00 +0200 Subject: [PATCH 2034/2270] target-alpha: Let cpu_alpha_init() return AlphaCPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace cpu_init() macro with inline function for backwards compatibility. Signed-off-by: Andreas Färber Acked-by: Richard Henderson --- target-alpha/cpu.h | 13 +++++++++++-- target-alpha/translate.c | 4 ++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 9939d61ca8..32e3777cdc 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -290,7 +290,6 @@ struct CPUAlphaState { int implver; }; -#define cpu_init cpu_alpha_init #define cpu_exec cpu_alpha_exec #define cpu_gen_code cpu_alpha_gen_code #define cpu_signal_handler cpu_alpha_signal_handler @@ -427,7 +426,17 @@ enum { IR_ZERO = 31, }; -CPUAlphaState * cpu_alpha_init (const char *cpu_model); +AlphaCPU *cpu_alpha_init(const char *cpu_model); + +static inline CPUAlphaState *cpu_init(const char *cpu_model) +{ + AlphaCPU *cpu = cpu_alpha_init(cpu_model); + if (cpu == NULL) { + return NULL; + } + return &cpu->env; +} + int cpu_alpha_exec(CPUAlphaState *s); /* you can call this signal handler from your SIGBUS and SIGSEGV signal handlers to inform the virtual CPU of exceptions. non zero diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 71fe1a1ab0..6f41ef7bfe 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -3517,7 +3517,7 @@ static const struct cpu_def_t cpu_defs[] = { | AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), } }; -CPUAlphaState * cpu_alpha_init (const char *cpu_model) +AlphaCPU *cpu_alpha_init(const char *cpu_model) { AlphaCPU *cpu; CPUAlphaState *env; @@ -3546,7 +3546,7 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model) env->cpu_model_str = cpu_model; qemu_init_vcpu(env); - return env; + return cpu; } void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, int pc_pos) From ad6011775a324d7c3e2a8bd824e03c5e576dda48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 16 Oct 2012 02:45:53 +0200 Subject: [PATCH 2035/2270] alpha: Pass AlphaCPU array to Typhoon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also store it in TyphoonCchip. Signed-off-by: Andreas Färber Acked-by: Richard Henderson --- hw/alpha_dp264.c | 18 +++++++++--------- hw/alpha_sys.h | 2 +- hw/alpha_typhoon.c | 29 ++++++++++++++++------------- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c index 76d8ae8a84..af24d1eaf4 100644 --- a/hw/alpha_dp264.c +++ b/hw/alpha_dp264.c @@ -50,7 +50,7 @@ static void clipper_init(QEMUMachineInitArgs *args) const char *kernel_filename = args->kernel_filename; const char *kernel_cmdline = args->kernel_cmdline; const char *initrd_filename = args->initrd_filename; - CPUAlphaState *cpus[4]; + AlphaCPU *cpus[4]; PCIBus *pci_bus; ISABus *isa_bus; qemu_irq rtc_irq; @@ -62,12 +62,12 @@ static void clipper_init(QEMUMachineInitArgs *args) /* Create up to 4 cpus. */ memset(cpus, 0, sizeof(cpus)); for (i = 0; i < smp_cpus; ++i) { - cpus[i] = cpu_init(cpu_model ? cpu_model : "ev67"); + cpus[i] = cpu_alpha_init(cpu_model ? cpu_model : "ev67"); } - cpus[0]->trap_arg0 = ram_size; - cpus[0]->trap_arg1 = 0; - cpus[0]->trap_arg2 = smp_cpus; + cpus[0]->env.trap_arg0 = ram_size; + cpus[0]->env.trap_arg1 = 0; + cpus[0]->env.trap_arg2 = smp_cpus; /* Init the chipset. */ pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus, @@ -119,9 +119,9 @@ static void clipper_init(QEMUMachineInitArgs *args) /* Start all cpus at the PALcode RESET entry point. */ for (i = 0; i < smp_cpus; ++i) { - cpus[i]->pal_mode = 1; - cpus[i]->pc = palcode_entry; - cpus[i]->palbr = palcode_entry; + cpus[i]->env.pal_mode = 1; + cpus[i]->env.pc = palcode_entry; + cpus[i]->env.palbr = palcode_entry; } /* Load a kernel. */ @@ -136,7 +136,7 @@ static void clipper_init(QEMUMachineInitArgs *args) exit(1); } - cpus[0]->trap_arg1 = kernel_entry; + cpus[0]->env.trap_arg1 = kernel_entry; param_offset = kernel_low - 0x6000; diff --git a/hw/alpha_sys.h b/hw/alpha_sys.h index 7604d09c80..69929ea815 100644 --- a/hw/alpha_sys.h +++ b/hw/alpha_sys.h @@ -11,7 +11,7 @@ #include "irq.h" -PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, CPUAlphaState *[4], +PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, AlphaCPU *[4], pci_map_irq_fn); /* alpha_pci.c. */ diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c index 9b16d96612..4cc810fb21 100644 --- a/hw/alpha_typhoon.c +++ b/hw/alpha_typhoon.c @@ -23,7 +23,7 @@ typedef struct TyphoonCchip { uint64_t drir; uint64_t dim[4]; uint32_t iic[4]; - CPUAlphaState *cpu[4]; + AlphaCPU *cpu[4]; } TyphoonCchip; typedef struct TyphoonWindow { @@ -58,10 +58,11 @@ typedef struct TyphoonState { } TyphoonState; /* Called when one of DRIR or DIM changes. */ -static void cpu_irq_change(CPUAlphaState *env, uint64_t req) +static void cpu_irq_change(AlphaCPU *cpu, uint64_t req) { /* If there are any non-masked interrupts, tell the cpu. */ - if (env) { + if (cpu != NULL) { + CPUAlphaState *env = &cpu->env; if (req) { cpu_interrupt(env, CPU_INTERRUPT_HARD); } else { @@ -353,8 +354,9 @@ static void cchip_write(void *opaque, hwaddr addr, if ((newval ^ oldval) & 0xff0) { int i; for (i = 0; i < 4; ++i) { - CPUAlphaState *env = s->cchip.cpu[i]; - if (env) { + AlphaCPU *cpu = s->cchip.cpu[i]; + if (cpu != NULL) { + CPUAlphaState *env = &cpu->env; /* IPI can be either cleared or set by the write. */ if (newval & (1 << (i + 8))) { cpu_interrupt(env, CPU_INTERRUPT_SMP); @@ -661,8 +663,8 @@ static void typhoon_set_timer_irq(void *opaque, int irq, int level) /* Deliver the interrupt to each CPU, considering each CPU's IIC. */ for (i = 0; i < 4; ++i) { - CPUAlphaState *env = s->cchip.cpu[i]; - if (env) { + AlphaCPU *cpu = s->cchip.cpu[i]; + if (cpu != NULL) { uint32_t iic = s->cchip.iic[i]; /* ??? The verbage in Section 10.2.2.10 isn't 100% clear. @@ -681,7 +683,7 @@ static void typhoon_set_timer_irq(void *opaque, int irq, int level) /* Set the ITI bit for this cpu. */ s->cchip.misc |= 1 << (i + 4); /* And signal the interrupt. */ - cpu_interrupt(env, CPU_INTERRUPT_TIMER); + cpu_interrupt(&cpu->env, CPU_INTERRUPT_TIMER); } } } @@ -694,12 +696,12 @@ static void typhoon_alarm_timer(void *opaque) /* Set the ITI bit for this cpu. */ s->cchip.misc |= 1 << (cpu + 4); - cpu_interrupt(s->cchip.cpu[cpu], CPU_INTERRUPT_TIMER); + cpu_interrupt(&s->cchip.cpu[cpu]->env, CPU_INTERRUPT_TIMER); } PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, qemu_irq *p_rtc_irq, - CPUAlphaState *cpus[4], pci_map_irq_fn sys_map_irq) + AlphaCPU *cpus[4], pci_map_irq_fn sys_map_irq) { const uint64_t MB = 1024 * 1024; const uint64_t GB = 1024 * MB; @@ -719,9 +721,10 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, /* Remember the CPUs so that we can deliver interrupts to them. */ for (i = 0; i < 4; i++) { - CPUAlphaState *env = cpus[i]; - s->cchip.cpu[i] = env; - if (env) { + AlphaCPU *cpu = cpus[i]; + s->cchip.cpu[i] = cpu; + if (cpu != NULL) { + CPUAlphaState *env = &cpu->env; env->alarm_timer = qemu_new_timer_ns(rtc_clock, typhoon_alarm_timer, (void *)((uintptr_t)s + i)); From c92458538f501eda585b4b774c50644aed391a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 31 Oct 2012 02:41:11 +0100 Subject: [PATCH 2036/2270] target-alpha: Avoid leaking the alarm timer over reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the timer from CPUAlphaState to AlphaCPU to avoid the pointer being zero'ed once we implement reset. Would cause a segfault in sys_helper.c:helper_set_alarm(). This also simplifies timer initialization in Typhoon. Signed-off-by: Andreas Färber Acked-by: Richard Henderson --- hw/alpha_typhoon.c | 3 +-- target-alpha/cpu-qom.h | 3 +++ target-alpha/cpu.h | 1 - target-alpha/sys_helper.c | 6 ++++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c index 4cc810fb21..40b3a47c7e 100644 --- a/hw/alpha_typhoon.c +++ b/hw/alpha_typhoon.c @@ -724,8 +724,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, AlphaCPU *cpu = cpus[i]; s->cchip.cpu[i] = cpu; if (cpu != NULL) { - CPUAlphaState *env = &cpu->env; - env->alarm_timer = qemu_new_timer_ns(rtc_clock, + cpu->alarm_timer = qemu_new_timer_ns(rtc_clock, typhoon_alarm_timer, (void *)((uintptr_t)s + i)); } diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h index 6b4ca6d1d1..98585d5023 100644 --- a/target-alpha/cpu-qom.h +++ b/target-alpha/cpu-qom.h @@ -58,6 +58,9 @@ typedef struct AlphaCPU { /*< public >*/ CPUAlphaState env; + + /* This alarm doesn't exist in real hardware; we wish it did. */ + struct QEMUTimer *alarm_timer; } AlphaCPU; static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env) diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 32e3777cdc..e1d771562a 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -277,7 +277,6 @@ struct CPUAlphaState { #endif /* This alarm doesn't exist in real hardware; we wish it did. */ - struct QEMUTimer *alarm_timer; uint64_t alarm_expire; /* Those resources are used only in QEMU core */ diff --git a/target-alpha/sys_helper.c b/target-alpha/sys_helper.c index 40ca49c883..d4f14efd86 100644 --- a/target-alpha/sys_helper.c +++ b/target-alpha/sys_helper.c @@ -77,11 +77,13 @@ uint64_t helper_get_time(void) void helper_set_alarm(CPUAlphaState *env, uint64_t expire) { + AlphaCPU *cpu = alpha_env_get_cpu(env); + if (expire) { env->alarm_expire = expire; - qemu_mod_timer(env->alarm_timer, expire); + qemu_mod_timer(cpu->alarm_timer, expire); } else { - qemu_del_timer(env->alarm_timer); + qemu_del_timer(cpu->alarm_timer); } } #endif /* CONFIG_USER_ONLY */ From 0c28246fcd5ea9ccb22aa93ef2e0af14463fec58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 15 Oct 2012 17:33:32 +0200 Subject: [PATCH 2037/2270] target-alpha: Turn CPU definitions into subclasses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make TYPE_ALPHA_CPU abstract and add types -alpha-cpu. Use type inheritence, and turn "2*" models into aliases. Move cpu_alpha_init() to cpu.c and split out CPU realization. Default to creating type "ev67-alpha-cpu" as before. Signed-off-by: Andreas Färber Acked-by: Richard Henderson --- target-alpha/cpu.c | 178 ++++++++++++++++++++++++++++++++++++++- target-alpha/cpu.h | 2 + target-alpha/translate.c | 58 +------------ 3 files changed, 180 insertions(+), 58 deletions(-) diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c index 11a19ebc87..a5a98d0fd5 100644 --- a/target-alpha/cpu.c +++ b/target-alpha/cpu.c @@ -21,8 +21,175 @@ #include "cpu.h" #include "qemu-common.h" +#include "error.h" +static void alpha_cpu_realize(Object *obj, Error **errp) +{ +#ifndef CONFIG_USER_ONLY + AlphaCPU *cpu = ALPHA_CPU(obj); + + qemu_init_vcpu(&cpu->env); +#endif +} + +/* Models */ + +#define TYPE(model) model "-" TYPE_ALPHA_CPU + +typedef struct AlphaCPUAlias { + const char *alias; + const char *typename; +} AlphaCPUAlias; + +static const AlphaCPUAlias alpha_cpu_aliases[] = { + { "21064", TYPE("ev4") }, + { "21164", TYPE("ev5") }, + { "21164a", TYPE("ev56") }, + { "21164pc", TYPE("pca56") }, + { "21264", TYPE("ev6") }, + { "21264a", TYPE("ev67") }, +}; + +static ObjectClass *alpha_cpu_class_by_name(const char *cpu_model) +{ + ObjectClass *oc = NULL; + char *typename; + int i; + + if (cpu_model == NULL) { + return NULL; + } + + oc = object_class_by_name(cpu_model); + if (oc != NULL) { + return oc; + } + + for (i = 0; i < ARRAY_SIZE(alpha_cpu_aliases); i++) { + if (strcmp(cpu_model, alpha_cpu_aliases[i].alias) == 0) { + oc = object_class_by_name(alpha_cpu_aliases[i].typename); + assert(oc != NULL); + return oc; + } + } + + typename = g_strdup_printf("%s-" TYPE_ALPHA_CPU, cpu_model); + oc = object_class_by_name(typename); + g_free(typename); + return oc; +} + +AlphaCPU *cpu_alpha_init(const char *cpu_model) +{ + AlphaCPU *cpu; + CPUAlphaState *env; + ObjectClass *cpu_class; + + cpu_class = alpha_cpu_class_by_name(cpu_model); + if (cpu_class == NULL) { + /* Default to ev67; no reason not to emulate insns by default. */ + cpu_class = object_class_by_name(TYPE("ev67")); + } + cpu = ALPHA_CPU(object_new(object_class_get_name(cpu_class))); + env = &cpu->env; + + env->cpu_model_str = cpu_model; + + alpha_cpu_realize(OBJECT(cpu), NULL); + return cpu; +} + +static void ev4_cpu_initfn(Object *obj) +{ + AlphaCPU *cpu = ALPHA_CPU(obj); + CPUAlphaState *env = &cpu->env; + + env->implver = IMPLVER_2106x; +} + +static const TypeInfo ev4_cpu_type_info = { + .name = TYPE("ev4"), + .parent = TYPE_ALPHA_CPU, + .instance_init = ev4_cpu_initfn, +}; + +static void ev5_cpu_initfn(Object *obj) +{ + AlphaCPU *cpu = ALPHA_CPU(obj); + CPUAlphaState *env = &cpu->env; + + env->implver = IMPLVER_21164; +} + +static const TypeInfo ev5_cpu_type_info = { + .name = TYPE("ev5"), + .parent = TYPE_ALPHA_CPU, + .instance_init = ev5_cpu_initfn, +}; + +static void ev56_cpu_initfn(Object *obj) +{ + AlphaCPU *cpu = ALPHA_CPU(obj); + CPUAlphaState *env = &cpu->env; + + env->amask |= AMASK_BWX; +} + +static const TypeInfo ev56_cpu_type_info = { + .name = TYPE("ev56"), + .parent = TYPE("ev5"), + .instance_init = ev56_cpu_initfn, +}; + +static void pca56_cpu_initfn(Object *obj) +{ + AlphaCPU *cpu = ALPHA_CPU(obj); + CPUAlphaState *env = &cpu->env; + + env->amask |= AMASK_MVI; +} + +static const TypeInfo pca56_cpu_type_info = { + .name = TYPE("pca56"), + .parent = TYPE("ev56"), + .instance_init = pca56_cpu_initfn, +}; + +static void ev6_cpu_initfn(Object *obj) +{ + AlphaCPU *cpu = ALPHA_CPU(obj); + CPUAlphaState *env = &cpu->env; + + env->implver = IMPLVER_21264; + env->amask = AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP; +} + +static const TypeInfo ev6_cpu_type_info = { + .name = TYPE("ev6"), + .parent = TYPE_ALPHA_CPU, + .instance_init = ev6_cpu_initfn, +}; + +static void ev67_cpu_initfn(Object *obj) +{ + AlphaCPU *cpu = ALPHA_CPU(obj); + CPUAlphaState *env = &cpu->env; + + env->amask |= AMASK_CIX | AMASK_PREFETCH; +} + +static const TypeInfo ev67_cpu_type_info = { + .name = TYPE("ev67"), + .parent = TYPE("ev6"), + .instance_init = ev67_cpu_initfn, +}; + +static const TypeInfo ev68_cpu_type_info = { + .name = TYPE("ev68"), + .parent = TYPE("ev67"), +}; + static void alpha_cpu_initfn(Object *obj) { AlphaCPU *cpu = ALPHA_CPU(obj); @@ -31,6 +198,8 @@ static void alpha_cpu_initfn(Object *obj) cpu_exec_init(env); tlb_flush(env, 1); + alpha_translate_init(); + #if defined(CONFIG_USER_ONLY) env->ps = PS_USER_MODE; cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD @@ -46,13 +215,20 @@ static const TypeInfo alpha_cpu_type_info = { .parent = TYPE_CPU, .instance_size = sizeof(AlphaCPU), .instance_init = alpha_cpu_initfn, - .abstract = false, + .abstract = true, .class_size = sizeof(AlphaCPUClass), }; static void alpha_cpu_register_types(void) { type_register_static(&alpha_cpu_type_info); + type_register_static(&ev4_cpu_type_info); + type_register_static(&ev5_cpu_type_info); + type_register_static(&ev56_cpu_type_info); + type_register_static(&pca56_cpu_type_info); + type_register_static(&ev6_cpu_type_info); + type_register_static(&ev67_cpu_type_info); + type_register_static(&ev68_cpu_type_info); } type_init(alpha_cpu_register_types) diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index e1d771562a..0d084586e1 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -425,6 +425,8 @@ enum { IR_ZERO = 31, }; +void alpha_translate_init(void); + AlphaCPU *cpu_alpha_init(const char *cpu_model); static inline CPUAlphaState *cpu_init(const char *cpu_model) diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 6f41ef7bfe..dc0c97c571 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -90,7 +90,7 @@ static char cpu_reg_names[10*4+21*5 + 10*5+21*6]; #include "gen-icount.h" -static void alpha_translate_init(void) +void alpha_translate_init(void) { int i; char *p; @@ -3493,62 +3493,6 @@ void gen_intermediate_code_pc (CPUAlphaState *env, struct TranslationBlock *tb) gen_intermediate_code_internal(env, tb, 1); } -struct cpu_def_t { - const char *name; - int implver, amask; -}; - -static const struct cpu_def_t cpu_defs[] = { - { "ev4", IMPLVER_2106x, 0 }, - { "ev5", IMPLVER_21164, 0 }, - { "ev56", IMPLVER_21164, AMASK_BWX }, - { "pca56", IMPLVER_21164, AMASK_BWX | AMASK_MVI }, - { "ev6", IMPLVER_21264, AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP }, - { "ev67", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX - | AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), }, - { "ev68", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX - | AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), }, - { "21064", IMPLVER_2106x, 0 }, - { "21164", IMPLVER_21164, 0 }, - { "21164a", IMPLVER_21164, AMASK_BWX }, - { "21164pc", IMPLVER_21164, AMASK_BWX | AMASK_MVI }, - { "21264", IMPLVER_21264, AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP }, - { "21264a", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX - | AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), } -}; - -AlphaCPU *cpu_alpha_init(const char *cpu_model) -{ - AlphaCPU *cpu; - CPUAlphaState *env; - int implver, amask, i, max; - - cpu = ALPHA_CPU(object_new(TYPE_ALPHA_CPU)); - env = &cpu->env; - - alpha_translate_init(); - - /* Default to ev67; no reason not to emulate insns by default. */ - implver = IMPLVER_21264; - amask = (AMASK_BWX | AMASK_FIX | AMASK_CIX | AMASK_MVI - | AMASK_TRAP | AMASK_PREFETCH); - - max = ARRAY_SIZE(cpu_defs); - for (i = 0; i < max; i++) { - if (strcmp (cpu_model, cpu_defs[i].name) == 0) { - implver = cpu_defs[i].implver; - amask = cpu_defs[i].amask; - break; - } - } - env->implver = implver; - env->amask = amask; - env->cpu_model_str = cpu_model; - - qemu_init_vcpu(env); - return cpu; -} - void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, int pc_pos) { env->pc = tcg_ctx.gen_opc_pc[pc_pos]; From 494342b35b55b3b126821141e15c8a49df122ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 15 Oct 2012 17:44:21 +0200 Subject: [PATCH 2038/2270] target-alpha: Add support for -cpu ? MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement alphabetical listing of CPU subclasses. Signed-off-by: Andreas Färber Acked-by: Richard Henderson --- target-alpha/cpu.c | 41 +++++++++++++++++++++++++++++++++++++++++ target-alpha/cpu.h | 2 ++ 2 files changed, 43 insertions(+) diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c index a5a98d0fd5..2deb3c1d7d 100644 --- a/target-alpha/cpu.c +++ b/target-alpha/cpu.c @@ -33,6 +33,47 @@ static void alpha_cpu_realize(Object *obj, Error **errp) #endif } +typedef struct AlphaCPUListState { + fprintf_function cpu_fprintf; + FILE *file; +} AlphaCPUListState; + +/* Sort alphabetically by type name. */ +static gint alpha_cpu_list_compare(gconstpointer a, gconstpointer b) +{ + ObjectClass *class_a = (ObjectClass *)a; + ObjectClass *class_b = (ObjectClass *)b; + const char *name_a, *name_b; + + name_a = object_class_get_name(class_a); + name_b = object_class_get_name(class_b); + return strcmp(name_a, name_b); +} + +static void alpha_cpu_list_entry(gpointer data, gpointer user_data) +{ + ObjectClass *oc = data; + AlphaCPUListState *s = user_data; + + (*s->cpu_fprintf)(s->file, " %s\n", + object_class_get_name(oc)); +} + +void alpha_cpu_list(FILE *f, fprintf_function cpu_fprintf) +{ + AlphaCPUListState s = { + .file = f, + .cpu_fprintf = cpu_fprintf, + }; + GSList *list; + + list = object_class_get_list(TYPE_ALPHA_CPU, false); + list = g_slist_sort(list, alpha_cpu_list_compare); + (*cpu_fprintf)(f, "Available CPUs:\n"); + g_slist_foreach(list, alpha_cpu_list_entry, &s); + g_slist_free(list); +} + /* Models */ #define TYPE(model) model "-" TYPE_ALPHA_CPU diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 0d084586e1..23f06c5a02 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -289,6 +289,7 @@ struct CPUAlphaState { int implver; }; +#define cpu_list alpha_cpu_list #define cpu_exec cpu_alpha_exec #define cpu_gen_code cpu_alpha_gen_code #define cpu_signal_handler cpu_alpha_signal_handler @@ -438,6 +439,7 @@ static inline CPUAlphaState *cpu_init(const char *cpu_model) return &cpu->env; } +void alpha_cpu_list(FILE *f, fprintf_function cpu_fprintf); int cpu_alpha_exec(CPUAlphaState *s); /* you can call this signal handler from your SIGBUS and SIGSEGV signal handlers to inform the virtual CPU of exceptions. non zero From 7937e75b1aba66cf24c93e58c48cbb4d59d1c19c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 24 Oct 2012 10:47:53 +0200 Subject: [PATCH 2039/2270] vscclient: use per-target variables Signed-off-by: Paolo Bonzini --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d06fbad6c9..7e381127e8 100644 --- a/Makefile +++ b/Makefile @@ -189,8 +189,9 @@ qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y) libqemustub.a qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o +vscclient$(EXESUF): LIBS += $(libcacard_libs) vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) libcacard/vscclient.o libqemustub.a - $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^ $(libcacard_libs) $(LIBS)," LINK $@") + $(call LINK, $^) fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o oslib-posix.o $(trace-obj-y) fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap From 9d9199a003b7531257836d5abb0b30c250303885 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Sep 2012 10:21:52 +0200 Subject: [PATCH 2040/2270] build: adjust setting of QEMU_INCLUDES Make it correct for nested directories, and move the static part from Makefile to configure. Signed-off-by: Paolo Bonzini --- Makefile | 2 -- configure | 3 +-- rules.mak | 3 +++ 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 7e381127e8..9ebd3cd24f 100644 --- a/Makefile +++ b/Makefile @@ -145,8 +145,6 @@ audio/audio.o audio/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS) QEMU_CFLAGS+=$(CURL_CFLAGS) -QEMU_CFLAGS += -I$(SRC_PATH)/include - ui/cocoa.o: ui/cocoa.m ui/sdl.o audio/sdlaudio.o ui/sdl_zoom.o hw/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS) diff --git a/configure b/configure index ecdb33a58e..e9ad1b1bd8 100755 --- a/configure +++ b/configure @@ -278,7 +278,7 @@ QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS" QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS" QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS" QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS" -QEMU_INCLUDES="-I. -I\$(SRC_PATH) -I\$(SRC_PATH)/fpu" +QEMU_INCLUDES="-I. -I\$(SRC_PATH) -I\$(SRC_PATH)/include -I\$(SRC_PATH)/fpu" if test "$debug_info" = "yes"; then CFLAGS="-g $CFLAGS" LDFLAGS="-g $LDFLAGS" @@ -3343,7 +3343,6 @@ fi if test "$slirp" = "yes" ; then echo "CONFIG_SLIRP=y" >> $config_host_mak echo "CONFIG_SMBD_COMMAND=\"$smbd\"" >> $config_host_mak - QEMU_INCLUDES="-I\$(SRC_PATH)/slirp $QEMU_INCLUDES" fi if test "$vde" = "yes" ; then echo "CONFIG_VDE=y" >> $config_host_mak diff --git a/rules.mak b/rules.mak index d0b04e44f5..77d23605bf 100644 --- a/rules.mak +++ b/rules.mak @@ -14,6 +14,9 @@ MAKEFLAGS += -rR # Flags for dependency generation QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d +# Same as -I$(SRC_PATH) -I., but for the nested source/object directories +QEMU_CFLAGS += -I$( Date: Mon, 17 Sep 2012 10:31:17 +0200 Subject: [PATCH 2041/2270] build: add $(TARGET_DIR) to "GEN config-target.h" lines Signed-off-by: Paolo Bonzini --- rules.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules.mak b/rules.mak index 77d23605bf..8448b94cdf 100644 --- a/rules.mak +++ b/rules.mak @@ -71,7 +71,7 @@ TRACETOOL=$(PYTHON) $(SRC_PATH)/scripts/tracetool.py @test -f $@ || cp $< $@ %.h-timestamp: %.mak - $(call quiet-command, sh $(SRC_PATH)/scripts/create_config < $< > $@, " GEN $*.h") + $(call quiet-command, sh $(SRC_PATH)/scripts/create_config < $< > $@, " GEN $(TARGET_DIR)$*.h") @cmp $@ $*.h >/dev/null 2>&1 || cp $@ $*.h # will delete the target of a rule if commands exit with a nonzero exit status From 525877c9992a07d424be4cfdd4ba13a69141a513 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Sep 2012 08:35:53 +0200 Subject: [PATCH 2042/2270] build: move rules from Makefile to */Makefile.objs Signed-off-by: Paolo Bonzini --- Makefile | 10 ---------- audio/Makefile.objs | 3 +++ block/Makefile.objs | 2 ++ hw/Makefile.objs | 2 ++ ui/Makefile.objs | 5 +++++ 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 9ebd3cd24f..58107180fb 100644 --- a/Makefile +++ b/Makefile @@ -141,16 +141,6 @@ ALL_SUBDIRS=$(TARGET_DIRS) $(patsubst %,pc-bios/%, $(ROMS)) recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES) -audio/audio.o audio/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS) - -QEMU_CFLAGS+=$(CURL_CFLAGS) - -ui/cocoa.o: ui/cocoa.m - -ui/sdl.o audio/sdlaudio.o ui/sdl_zoom.o hw/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS) - -ui/vnc.o: QEMU_CFLAGS += $(VNC_TLS_CFLAGS) - bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS) version.o: $(SRC_PATH)/version.rc config-host.h diff --git a/audio/Makefile.objs b/audio/Makefile.objs index 0f2932d1b3..d71a877249 100644 --- a/audio/Makefile.objs +++ b/audio/Makefile.objs @@ -12,3 +12,6 @@ common-obj-$(CONFIG_WINWAVE) += winwaveaudio.o common-obj-$(CONFIG_AUDIO_PT_INT) += audio_pt_int.o common-obj-$(CONFIG_AUDIO_WIN_INT) += audio_win_int.o common-obj-y += wavcapture.o + +$(obj)/audio.o $(obj)/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS) +$(obj)/sdlaudio.o: QEMU_CFLAGS += $(SDL_CFLAGS) diff --git a/block/Makefile.objs b/block/Makefile.objs index 7f015105b1..c067f38e1d 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -18,3 +18,5 @@ endif common-obj-y += stream.o common-obj-y += commit.o common-obj-y += mirror.o + +$(obj)/curl.o: QEMU_CFLAGS+=$(CURL_CFLAGS) diff --git a/hw/Makefile.objs b/hw/Makefile.objs index bcf278d4ec..2778035b1c 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -204,3 +204,5 @@ ifeq ($(CONFIG_PCI), y) obj-$(CONFIG_KVM) += ivshmem.o obj-$(CONFIG_LINUX) += vfio_pci.o endif + +$(obj)/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS) diff --git a/ui/Makefile.objs b/ui/Makefile.objs index adc07be761..fd339d247b 100644 --- a/ui/Makefile.objs +++ b/ui/Makefile.objs @@ -12,3 +12,8 @@ common-obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o common-obj-$(CONFIG_COCOA) += cocoa.o common-obj-$(CONFIG_CURSES) += curses.o common-obj-$(CONFIG_VNC) += $(vnc-obj-y) + +$(obj)/sdl.o $(obj)/sdl_zoom.o: QEMU_CFLAGS += $(SDL_CFLAGS) +$(obj)/vnc.o: QEMU_CFLAGS += $(VNC_TLS_CFLAGS) + +$(obj)/cocoa.o: $(SRC_PATH)/$(obj)/cocoa.m From c1c9367216c97ca93de79e90822045a425d7e76d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 14 Sep 2012 18:28:23 +0200 Subject: [PATCH 2043/2270] build: create ldscripts/ Signed-off-by: Paolo Bonzini --- configure | 2 +- alpha.ld => ldscripts/alpha.ld | 0 arm.ld => ldscripts/arm.ld | 0 hppa.ld => ldscripts/hppa.ld | 0 i386.ld => ldscripts/i386.ld | 0 ia64.ld => ldscripts/ia64.ld | 0 m68k.ld => ldscripts/m68k.ld | 0 mips.ld => ldscripts/mips.ld | 0 ppc.ld => ldscripts/ppc.ld | 0 ppc64.ld => ldscripts/ppc64.ld | 0 s390.ld => ldscripts/s390.ld | 0 sparc.ld => ldscripts/sparc.ld | 0 sparc64.ld => ldscripts/sparc64.ld | 0 x86_64.ld => ldscripts/x86_64.ld | 0 14 files changed, 1 insertion(+), 1 deletion(-) rename alpha.ld => ldscripts/alpha.ld (100%) rename arm.ld => ldscripts/arm.ld (100%) rename hppa.ld => ldscripts/hppa.ld (100%) rename i386.ld => ldscripts/i386.ld (100%) rename ia64.ld => ldscripts/ia64.ld (100%) rename m68k.ld => ldscripts/m68k.ld (100%) rename mips.ld => ldscripts/mips.ld (100%) rename ppc.ld => ldscripts/ppc.ld (100%) rename ppc64.ld => ldscripts/ppc64.ld (100%) rename s390.ld => ldscripts/s390.ld (100%) rename sparc.ld => ldscripts/sparc.ld (100%) rename sparc64.ld => ldscripts/sparc64.ld (100%) rename x86_64.ld => ldscripts/x86_64.ld (100%) diff --git a/configure b/configure index e9ad1b1bd8..d2ad1819d5 100755 --- a/configure +++ b/configure @@ -4158,7 +4158,7 @@ fi if test "$ARCH" = "tci"; then linker_script="" else - linker_script="-Wl,-T../config-host.ld -Wl,-T,\$(SRC_PATH)/\$(ARCH).ld" + linker_script="-Wl,-T../config-host.ld -Wl,-T,\$(SRC_PATH)/ldscripts/\$(ARCH).ld" fi if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then diff --git a/alpha.ld b/ldscripts/alpha.ld similarity index 100% rename from alpha.ld rename to ldscripts/alpha.ld diff --git a/arm.ld b/ldscripts/arm.ld similarity index 100% rename from arm.ld rename to ldscripts/arm.ld diff --git a/hppa.ld b/ldscripts/hppa.ld similarity index 100% rename from hppa.ld rename to ldscripts/hppa.ld diff --git a/i386.ld b/ldscripts/i386.ld similarity index 100% rename from i386.ld rename to ldscripts/i386.ld diff --git a/ia64.ld b/ldscripts/ia64.ld similarity index 100% rename from ia64.ld rename to ldscripts/ia64.ld diff --git a/m68k.ld b/ldscripts/m68k.ld similarity index 100% rename from m68k.ld rename to ldscripts/m68k.ld diff --git a/mips.ld b/ldscripts/mips.ld similarity index 100% rename from mips.ld rename to ldscripts/mips.ld diff --git a/ppc.ld b/ldscripts/ppc.ld similarity index 100% rename from ppc.ld rename to ldscripts/ppc.ld diff --git a/ppc64.ld b/ldscripts/ppc64.ld similarity index 100% rename from ppc64.ld rename to ldscripts/ppc64.ld diff --git a/s390.ld b/ldscripts/s390.ld similarity index 100% rename from s390.ld rename to ldscripts/s390.ld diff --git a/sparc.ld b/ldscripts/sparc.ld similarity index 100% rename from sparc.ld rename to ldscripts/sparc.ld diff --git a/sparc64.ld b/ldscripts/sparc64.ld similarity index 100% rename from sparc64.ld rename to ldscripts/sparc64.ld diff --git a/x86_64.ld b/ldscripts/x86_64.ld similarity index 100% rename from x86_64.ld rename to ldscripts/x86_64.ld From 76cad71136b7eb371cf2a2a4e1621cfe8d9c769a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 24 Oct 2012 11:12:21 +0200 Subject: [PATCH 2044/2270] build: kill libdis, move disassemblers to disas/ Signed-off-by: Paolo Bonzini --- .gitignore | 1 + Makefile | 9 +++--- Makefile.dis | 20 ------------ Makefile.objs | 19 ++--------- Makefile.target | 5 +-- bsd-user/elfload.c | 2 +- configure | 45 ++++++++++---------------- cpu-exec.c | 2 +- disas.c | 4 +-- disas/Makefile.objs | 16 +++++++++ alpha-dis.c => disas/alpha.c | 2 +- arm-dis.c => disas/arm.c | 2 +- cris-dis.c => disas/cris.c | 2 +- hppa-dis.c => disas/hppa.c | 2 +- i386-dis.c => disas/i386.c | 2 +- ia64-dis.c => disas/ia64.c | 2 +- lm32-dis.c => disas/lm32.c | 2 +- m68k-dis.c => disas/m68k.c | 2 +- microblaze-dis.c => disas/microblaze.c | 2 +- mips-dis.c => disas/mips.c | 2 +- ppc-dis.c => disas/ppc.c | 2 +- s390-dis.c => disas/s390.c | 2 +- sh4-dis.c => disas/sh4.c | 2 +- sparc-dis.c => disas/sparc.c | 2 +- tci-dis.c => disas/tci.c | 2 +- hw/loader.c | 2 +- dis-asm.h => include/disas/bfd.h | 0 disas.h => include/disas/disas.h | 0 linux-user/elfload.c | 2 +- monitor.c | 2 +- qemu-log.h | 2 +- target-alpha/translate.c | 2 +- target-arm/translate.c | 2 +- target-cris/translate.c | 2 +- target-i386/translate.c | 2 +- target-lm32/translate.c | 2 +- target-m68k/translate.c | 2 +- target-microblaze/helper.c | 2 +- target-microblaze/translate.c | 2 +- target-mips/translate.c | 2 +- target-openrisc/translate.c | 2 +- target-ppc/translate.c | 2 +- target-ppc/translate_init.c | 2 +- target-s390x/translate.c | 2 +- target-sh4/translate.c | 2 +- target-sparc/translate.c | 2 +- target-unicore32/translate.c | 2 +- target-xtensa/translate.c | 2 +- translate-all.c | 2 +- user-exec.c | 2 +- vl.c | 2 +- 51 files changed, 86 insertions(+), 115 deletions(-) delete mode 100644 Makefile.dis create mode 100644 disas/Makefile.objs rename alpha-dis.c => disas/alpha.c (99%) rename arm-dis.c => disas/arm.c (99%) rename cris-dis.c => disas/cris.c (99%) rename hppa-dis.c => disas/hppa.c (99%) rename i386-dis.c => disas/i386.c (99%) rename ia64-dis.c => disas/ia64.c (99%) rename lm32-dis.c => disas/lm32.c (99%) rename m68k-dis.c => disas/m68k.c (99%) rename microblaze-dis.c => disas/microblaze.c (99%) rename mips-dis.c => disas/mips.c (99%) rename ppc-dis.c => disas/ppc.c (99%) rename s390-dis.c => disas/s390.c (99%) rename sh4-dis.c => disas/sh4.c (99%) rename sparc-dis.c => disas/sparc.c (99%) rename tci-dis.c => disas/tci.c (98%) rename dis-asm.h => include/disas/bfd.h (100%) rename disas.h => include/disas/disas.h (100%) diff --git a/.gitignore b/.gitignore index bd6ba1c71e..ca52f01ab2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ config-devices.* config-all-devices.* +config-all-disas.* config-host.* config-target.* trace.h diff --git a/Makefile b/Makefile index 58107180fb..da47cb8572 100644 --- a/Makefile +++ b/Makefile @@ -99,6 +99,7 @@ defconfig: rm -f config-all-devices.mak $(SUBDIR_DEVICES_MAK) -include config-all-devices.mak +-include config-all-disas.mak all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all @@ -129,9 +130,9 @@ $(SRC_PATH)/pixman/configure: $(SUBDIR_RULES): libqemustub.a -$(filter %-softmmu,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) $(common-obj-y) $(extra-obj-y) subdir-libdis +$(filter %-softmmu,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) $(common-obj-y) $(extra-obj-y) -$(filter %-user,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) subdir-libdis-user subdir-libuser +$(filter %-user,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) subdir-libuser ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS)) romsubdir-%: @@ -223,7 +224,7 @@ $(qga-obj-y) qemu-ga.o: $(QGALIB_GEN) qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(oslib-obj-y) $(trace-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y) libqemustub.a -QEMULIBS=libuser libdis libdis-user +QEMULIBS=libuser clean: # avoid old build problems by removing potentially incorrect old files @@ -255,7 +256,7 @@ qemu-%.tar.bz2: distclean: clean rm -f config-host.mak config-host.h* config-host.ld $(DOCS) qemu-options.texi qemu-img-cmds.texi qemu-monitor.texi - rm -f config-all-devices.mak + rm -f config-all-devices.mak config-all-disas.mak rm -f roms/seabios/config.mak roms/vgabios/config.mak rm -f qemu-doc.info qemu-doc.aux qemu-doc.cp qemu-doc.cps qemu-doc.dvi rm -f qemu-doc.fn qemu-doc.fns qemu-doc.info qemu-doc.ky qemu-doc.kys diff --git a/Makefile.dis b/Makefile.dis deleted file mode 100644 index 2cfec6a358..0000000000 --- a/Makefile.dis +++ /dev/null @@ -1,20 +0,0 @@ -# Makefile for disassemblers. - -include ../config-host.mak -include config.mak -include $(SRC_PATH)/rules.mak - -.PHONY: all - -$(call set-vpath, $(SRC_PATH)) - -QEMU_CFLAGS+=-I.. - -include $(SRC_PATH)/Makefile.objs - -all: $(libdis-y) -# Dummy command so that make thinks it has done something - @true - -clean: - rm -f *.o *.d *.a *~ diff --git a/Makefile.objs b/Makefile.objs index 20fb2c54f0..3248eafe32 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -127,24 +127,10 @@ user-obj-y += $(trace-obj-y) user-obj-y += qom/ ###################################################################### -# libdis +# disassemblers # NOTE: the disassembler code is only needed for debugging -libdis-y = -libdis-$(CONFIG_ALPHA_DIS) += alpha-dis.o -libdis-$(CONFIG_ARM_DIS) += arm-dis.o -libdis-$(CONFIG_CRIS_DIS) += cris-dis.o -libdis-$(CONFIG_HPPA_DIS) += hppa-dis.o -libdis-$(CONFIG_I386_DIS) += i386-dis.o -libdis-$(CONFIG_IA64_DIS) += ia64-dis.o -libdis-$(CONFIG_M68K_DIS) += m68k-dis.o -libdis-$(CONFIG_MICROBLAZE_DIS) += microblaze-dis.o -libdis-$(CONFIG_MIPS_DIS) += mips-dis.o -libdis-$(CONFIG_PPC_DIS) += ppc-dis.o -libdis-$(CONFIG_S390_DIS) += s390-dis.o -libdis-$(CONFIG_SH4_DIS) += sh4-dis.o -libdis-$(CONFIG_SPARC_DIS) += sparc-dis.o -libdis-$(CONFIG_LM32_DIS) += lm32-dis.o +universal-obj-y += disas/ ###################################################################### # trace @@ -252,5 +238,6 @@ nested-vars += \ block-obj-y \ user-obj-y \ common-obj-y \ + universal-obj-y \ extra-obj-y dummy := $(call unnest-vars) diff --git a/Makefile.target b/Makefile.target index 927347bac2..f353651369 100644 --- a/Makefile.target +++ b/Makefile.target @@ -70,9 +70,8 @@ obj-y = exec.o translate-all.o cpu-exec.o obj-y += tcg/tcg.o tcg/optimize.o obj-$(CONFIG_TCG_INTERPRETER) += tci.o obj-y += fpu/softfloat.o -obj-y += disas.o -obj-$(CONFIG_TCI_DIS) += tci-dis.o obj-y += target-$(TARGET_BASE_ARCH)/ +obj-y += disas.o obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o tci-dis.o: QEMU_CFLAGS += -I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/tci @@ -156,11 +155,9 @@ all-obj-y += $(addprefix ../, $(universal-obj-y)) ifdef CONFIG_SOFTMMU all-obj-y += $(addprefix ../, $(common-obj-y)) -all-obj-y += $(addprefix ../libdis/, $(libdis-y)) all-obj-y += $(addprefix ../, $(trace-obj-y)) else all-obj-y += $(addprefix ../libuser/, $(user-obj-y)) -all-obj-y += $(addprefix ../libdis-user/, $(libdis-y)) endif #CONFIG_LINUX_USER ifdef QEMU_PROGW diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c index 55b213609e..a6cd3ab4f3 100644 --- a/bsd-user/elfload.c +++ b/bsd-user/elfload.c @@ -10,7 +10,7 @@ #include #include "qemu.h" -#include "disas.h" +#include "disas/disas.h" #ifdef _ARCH_PPC64 #undef ARCH_DLINFO diff --git a/configure b/configure index d2ad1819d5..f180e172a7 100755 --- a/configure +++ b/configure @@ -3697,11 +3697,6 @@ if test -f ${config_host_ld}~ ; then fi fi -for d in libdis libdis-user; do - symlink "$source_path/Makefile.dis" "$d/Makefile" - echo > $d/config.mak -done - # use included Linux headers if test "$linux" = "yes" ; then mkdir -p linux-headers @@ -4043,83 +4038,77 @@ if test "$linux" = "yes" ; then includes="-I\$(SRC_PATH)/linux-headers $includes" fi -if test "$target_user_only" = "yes" ; then - libdis_config_mak=libdis-user/config.mak -else - libdis_config_mak=libdis/config.mak -fi - for i in $ARCH $TARGET_BASE_ARCH ; do case "$i" in alpha) echo "CONFIG_ALPHA_DIS=y" >> $config_target_mak - echo "CONFIG_ALPHA_DIS=y" >> $libdis_config_mak + echo "CONFIG_ALPHA_DIS=y" >> config-all-disas.mak ;; arm) echo "CONFIG_ARM_DIS=y" >> $config_target_mak - echo "CONFIG_ARM_DIS=y" >> $libdis_config_mak + echo "CONFIG_ARM_DIS=y" >> config-all-disas.mak ;; cris) echo "CONFIG_CRIS_DIS=y" >> $config_target_mak - echo "CONFIG_CRIS_DIS=y" >> $libdis_config_mak + echo "CONFIG_CRIS_DIS=y" >> config-all-disas.mak ;; hppa) echo "CONFIG_HPPA_DIS=y" >> $config_target_mak - echo "CONFIG_HPPA_DIS=y" >> $libdis_config_mak + echo "CONFIG_HPPA_DIS=y" >> config-all-disas.mak ;; i386|x86_64) echo "CONFIG_I386_DIS=y" >> $config_target_mak - echo "CONFIG_I386_DIS=y" >> $libdis_config_mak + echo "CONFIG_I386_DIS=y" >> config-all-disas.mak ;; ia64*) echo "CONFIG_IA64_DIS=y" >> $config_target_mak - echo "CONFIG_IA64_DIS=y" >> $libdis_config_mak + echo "CONFIG_IA64_DIS=y" >> config-all-disas.mak ;; lm32) echo "CONFIG_LM32_DIS=y" >> $config_target_mak - echo "CONFIG_LM32_DIS=y" >> $libdis_config_mak + echo "CONFIG_LM32_DIS=y" >> config-all-disas.mak ;; m68k) echo "CONFIG_M68K_DIS=y" >> $config_target_mak - echo "CONFIG_M68K_DIS=y" >> $libdis_config_mak + echo "CONFIG_M68K_DIS=y" >> config-all-disas.mak ;; microblaze*) echo "CONFIG_MICROBLAZE_DIS=y" >> $config_target_mak - echo "CONFIG_MICROBLAZE_DIS=y" >> $libdis_config_mak + echo "CONFIG_MICROBLAZE_DIS=y" >> config-all-disas.mak ;; mips*) echo "CONFIG_MIPS_DIS=y" >> $config_target_mak - echo "CONFIG_MIPS_DIS=y" >> $libdis_config_mak + echo "CONFIG_MIPS_DIS=y" >> config-all-disas.mak ;; or32) echo "CONFIG_OPENRISC_DIS=y" >> $config_target_mak - echo "CONFIG_OPENRISC_DIS=y" >> $libdis_config_mak + echo "CONFIG_OPENRISC_DIS=y" >> config-all-disas.mak ;; ppc*) echo "CONFIG_PPC_DIS=y" >> $config_target_mak - echo "CONFIG_PPC_DIS=y" >> $libdis_config_mak + echo "CONFIG_PPC_DIS=y" >> config-all-disas.mak ;; s390*) echo "CONFIG_S390_DIS=y" >> $config_target_mak - echo "CONFIG_S390_DIS=y" >> $libdis_config_mak + echo "CONFIG_S390_DIS=y" >> config-all-disas.mak ;; sh4) echo "CONFIG_SH4_DIS=y" >> $config_target_mak - echo "CONFIG_SH4_DIS=y" >> $libdis_config_mak + echo "CONFIG_SH4_DIS=y" >> config-all-disas.mak ;; sparc*) echo "CONFIG_SPARC_DIS=y" >> $config_target_mak - echo "CONFIG_SPARC_DIS=y" >> $libdis_config_mak + echo "CONFIG_SPARC_DIS=y" >> config-all-disas.mak ;; xtensa*) echo "CONFIG_XTENSA_DIS=y" >> $config_target_mak - echo "CONFIG_XTENSA_DIS=y" >> $libdis_config_mak + echo "CONFIG_XTENSA_DIS=y" >> config-all-disas.mak ;; esac done if test "$tcg_interpreter" = "yes" ; then echo "CONFIG_TCI_DIS=y" >> $config_target_mak - echo "CONFIG_TCI_DIS=y" >> $libdis_config_mak + echo "CONFIG_TCI_DIS=y" >> config-all-disas.mak fi case "$ARCH" in diff --git a/cpu-exec.c b/cpu-exec.c index 904ee73c7b..b5a32b84e4 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -18,7 +18,7 @@ */ #include "config.h" #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" #include "tcg.h" #include "qemu-barrier.h" #include "qtest.h" diff --git a/disas.c b/disas.c index 6da1dd09f4..8157b96fc1 100644 --- a/disas.c +++ b/disas.c @@ -1,11 +1,11 @@ /* General "disassemble this chunk" code. Used for debugging. */ #include "config.h" -#include "dis-asm.h" +#include "disas/bfd.h" #include "elf.h" #include #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" typedef struct CPUDebug { struct disassemble_info info; diff --git a/disas/Makefile.objs b/disas/Makefile.objs new file mode 100644 index 0000000000..9134429845 --- /dev/null +++ b/disas/Makefile.objs @@ -0,0 +1,16 @@ +universal-obj-$(CONFIG_ALPHA_DIS) += alpha.o +universal-obj-$(CONFIG_ARM_DIS) += arm.o +universal-obj-$(CONFIG_CRIS_DIS) += cris.o +universal-obj-$(CONFIG_HPPA_DIS) += hppa.o +universal-obj-$(CONFIG_I386_DIS) += i386.o +universal-obj-$(CONFIG_IA64_DIS) += ia64.o +universal-obj-$(CONFIG_M68K_DIS) += m68k.o +universal-obj-$(CONFIG_MICROBLAZE_DIS) += microblaze.o +universal-obj-$(CONFIG_MIPS_DIS) += mips.o +universal-obj-$(CONFIG_PPC_DIS) += ppc.o +universal-obj-$(CONFIG_S390_DIS) += s390.o +universal-obj-$(CONFIG_SH4_DIS) += sh4.o +universal-obj-$(CONFIG_SPARC_DIS) += sparc.o +universal-obj-$(CONFIG_LM32_DIS) += lm32.o + +universal-obj-$(CONFIG_TCI_DIS) += tci.o diff --git a/alpha-dis.c b/disas/alpha.c similarity index 99% rename from alpha-dis.c rename to disas/alpha.c index ae331b35b8..a950b9cee0 100644 --- a/alpha-dis.c +++ b/disas/alpha.c @@ -20,7 +20,7 @@ along with this file; see the file COPYING. If not, see . */ #include -#include "dis-asm.h" +#include "disas/bfd.h" /* MAX is redefined below, so remove any previous definition. */ #undef MAX diff --git a/arm-dis.c b/disas/arm.c similarity index 99% rename from arm-dis.c rename to disas/arm.c index 6bc4d71698..4927d8ad7c 100644 --- a/arm-dis.c +++ b/disas/arm.c @@ -22,7 +22,7 @@ /* Start of qemu specific additions. Mostly this is stub definitions for things we don't care about. */ -#include "dis-asm.h" +#include "disas/bfd.h" #define ATTRIBUTE_UNUSED __attribute__((unused)) #define ISSPACE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n') diff --git a/cris-dis.c b/disas/cris.c similarity index 99% rename from cris-dis.c rename to disas/cris.c index 1d174ba8cc..9dfb4e3885 100644 --- a/cris-dis.c +++ b/disas/cris.c @@ -19,7 +19,7 @@ along with this program; if not, see . */ #include "qemu-common.h" -#include "dis-asm.h" +#include "disas/bfd.h" //#include "sysdep.h" #include "target-cris/opcode-cris.h" //#include "libiberty.h" diff --git a/hppa-dis.c b/disas/hppa.c similarity index 99% rename from hppa-dis.c rename to disas/hppa.c index 420a7d22d0..c7c8be66a2 100644 --- a/hppa-dis.c +++ b/disas/hppa.c @@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, see . */ -#include "dis-asm.h" +#include "disas/bfd.h" /* HP PA-RISC SOM object file format: definitions internal to BFD. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, diff --git a/i386-dis.c b/disas/i386.c similarity index 99% rename from i386-dis.c rename to disas/i386.c index c4a81c99ad..3b006b13e0 100644 --- a/i386-dis.c +++ b/disas/i386.c @@ -32,7 +32,7 @@ the Intel manual for details. */ #include -#include "dis-asm.h" +#include "disas/bfd.h" /* include/opcode/i386.h r1.78 */ /* opcode/i386.h -- Intel 80386 opcode macros diff --git a/ia64-dis.c b/disas/ia64.c similarity index 99% rename from ia64-dis.c rename to disas/ia64.c index 2a103e6b5c..a8fe26c413 100644 --- a/ia64-dis.c +++ b/disas/ia64.c @@ -21,7 +21,7 @@ #include #include -#include "dis-asm.h" +#include "disas/bfd.h" /* ia64.h -- Header file for ia64 opcode table Copyright (C) 1998, 1999, 2000, 2002, 2005, 2006 diff --git a/lm32-dis.c b/disas/lm32.c similarity index 99% rename from lm32-dis.c rename to disas/lm32.c index 709ed3215c..a8eefe05b1 100644 --- a/lm32-dis.c +++ b/disas/lm32.c @@ -19,7 +19,7 @@ */ #include -#include "dis-asm.h" +#include "disas/bfd.h" typedef enum { LM32_OP_SRUI = 0, LM32_OP_NORI, LM32_OP_MULI, LM32_OP_SH, LM32_OP_LB, diff --git a/m68k-dis.c b/disas/m68k.c similarity index 99% rename from m68k-dis.c rename to disas/m68k.c index 2b155de51c..c950241f79 100644 --- a/m68k-dis.c +++ b/disas/m68k.c @@ -5,7 +5,7 @@ #include #include -#include "dis-asm.h" +#include "disas/bfd.h" /* **** floatformat.h from sourceware.org CVS 2005-08-14. */ /* IEEE floating point support declarations, for GDB, the GNU Debugger. diff --git a/microblaze-dis.c b/disas/microblaze.c similarity index 99% rename from microblaze-dis.c rename to disas/microblaze.c index 16c312f2f5..ec91af386d 100644 --- a/microblaze-dis.c +++ b/disas/microblaze.c @@ -582,7 +582,7 @@ char pvr_register_prefix[] = "rpvr"; #endif /* MICROBLAZE_OPC */ -#include "dis-asm.h" +#include "disas/bfd.h" #include #define get_field_rd(instr) get_field(instr, RD_MASK, RD_LOW) diff --git a/mips-dis.c b/disas/mips.c similarity index 99% rename from mips-dis.c rename to disas/mips.c index e3a6e0b49e..2106b574cb 100644 --- a/mips-dis.c +++ b/disas/mips.c @@ -19,7 +19,7 @@ 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 . */ -#include "dis-asm.h" +#include "disas/bfd.h" /* mips.h. Mips opcode list for GDB, the GNU debugger. Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 diff --git a/ppc-dis.c b/disas/ppc.c similarity index 99% rename from ppc-dis.c rename to disas/ppc.c index bc98cbe655..c149506fd8 100644 --- a/ppc-dis.c +++ b/disas/ppc.c @@ -18,7 +18,7 @@ the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this file; see the file COPYING. If not, see . */ -#include "dis-asm.h" +#include "disas/bfd.h" #define BFD_DEFAULT_TARGET_SIZE 64 /* ppc.h -- Header file for PowerPC opcode table diff --git a/s390-dis.c b/disas/s390.c similarity index 99% rename from s390-dis.c rename to disas/s390.c index 8abcdf0128..0859dfa19f 100644 --- a/s390-dis.c +++ b/disas/s390.c @@ -21,7 +21,7 @@ 02110-1301, USA. */ #include "qemu-common.h" -#include "dis-asm.h" +#include "disas/bfd.h" /* include/opcode/s390.h revision 1.9 */ /* s390.h -- Header file for S390 opcode table diff --git a/sh4-dis.c b/disas/sh4.c similarity index 99% rename from sh4-dis.c rename to disas/sh4.c index 673bc78380..f6cadd55c0 100644 --- a/sh4-dis.c +++ b/disas/sh4.c @@ -16,7 +16,7 @@ along with this program; if not, see . */ #include -#include "dis-asm.h" +#include "disas/bfd.h" #define DEFINE_TABLE diff --git a/sparc-dis.c b/disas/sparc.c similarity index 99% rename from sparc-dis.c rename to disas/sparc.c index 1d017faaa3..8eb22e6fc3 100644 --- a/sparc-dis.c +++ b/disas/sparc.c @@ -27,7 +27,7 @@ see . */ #include -#include "dis-asm.h" +#include "disas/bfd.h" /* The SPARC opcode table (and other related data) is defined in the opcodes library in sparc-opc.c. If you change anything here, make diff --git a/tci-dis.c b/disas/tci.c similarity index 98% rename from tci-dis.c rename to disas/tci.c index 10c411be8c..a606b63a2a 100644 --- a/tci-dis.c +++ b/disas/tci.c @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -#include "dis-asm.h" +#include "disas/bfd.h" #include "tcg/tcg.h" /* Disassemble TCI bytecode. */ diff --git a/hw/loader.c b/hw/loader.c index ba01ca6638..52f0940778 100644 --- a/hw/loader.c +++ b/hw/loader.c @@ -43,7 +43,7 @@ */ #include "hw.h" -#include "disas.h" +#include "disas/disas.h" #include "monitor.h" #include "sysemu.h" #include "uboot_image.h" diff --git a/dis-asm.h b/include/disas/bfd.h similarity index 100% rename from dis-asm.h rename to include/disas/bfd.h diff --git a/disas.h b/include/disas/disas.h similarity index 100% rename from disas.h rename to include/disas/disas.h diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 1d8bcb4e79..89db49ccaa 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -14,7 +14,7 @@ #include #include "qemu.h" -#include "disas.h" +#include "disas/disas.h" #ifdef _ARCH_PPC64 #undef ARCH_DLINFO diff --git a/monitor.c b/monitor.c index a92ab44384..bd63768c27 100644 --- a/monitor.c +++ b/monitor.c @@ -41,7 +41,7 @@ #include "console.h" #include "blockdev.h" #include "audio/audio.h" -#include "disas.h" +#include "disas/disas.h" #include "balloon.h" #include "qemu-timer.h" #include "migration.h" diff --git a/qemu-log.h b/qemu-log.h index 344eca3f1b..58f69cb494 100644 --- a/qemu-log.h +++ b/qemu-log.h @@ -3,7 +3,7 @@ #include #ifdef NEED_CPU_H -#include "disas.h" +#include "disas/disas.h" #endif /* Private global variables, don't use */ diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 71fe1a1ab0..f57c8fd91f 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -18,7 +18,7 @@ */ #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" #include "host-utils.h" #include "tcg-op.h" diff --git a/target-arm/translate.c b/target-arm/translate.c index 3cf3604517..10c548d5ba 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -25,7 +25,7 @@ #include #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" #include "tcg-op.h" #include "qemu-log.h" diff --git a/target-cris/translate.c b/target-cris/translate.c index 60bdc241ef..2a92727843 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -24,7 +24,7 @@ */ #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" #include "tcg-op.h" #include "helper.h" #include "mmu.h" diff --git a/target-i386/translate.c b/target-i386/translate.c index f394ea69a5..026201e98e 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -24,7 +24,7 @@ #include #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" #include "tcg-op.h" #include "helper.h" diff --git a/target-lm32/translate.c b/target-lm32/translate.c index e131ad1b5f..9683b9a4b5 100644 --- a/target-lm32/translate.c +++ b/target-lm32/translate.c @@ -18,7 +18,7 @@ */ #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" #include "helper.h" #include "tcg-op.h" diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 11defc6e04..d955c7a409 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -19,7 +19,7 @@ */ #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" #include "tcg-op.h" #include "qemu-log.h" diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c index efaa123a14..530e0b5fb0 100644 --- a/target-microblaze/helper.c +++ b/target-microblaze/helper.c @@ -198,7 +198,7 @@ void do_interrupt(CPUMBState *env) t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1; #if 0 -#include "disas.h" +#include "disas/disas.h" /* Useful instrumentation when debugging interrupt issues in either the models or in sw. */ diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index 6ceff02a12..5946a5ba5c 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -19,7 +19,7 @@ */ #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" #include "tcg-op.h" #include "helper.h" #include "microblaze-decode.h" diff --git a/target-mips/translate.c b/target-mips/translate.c index 65e6725cc9..44e7617395 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -22,7 +22,7 @@ */ #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" #include "tcg-op.h" #include "helper.h" diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index 9ac999a9c8..2cb9d69826 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -20,7 +20,7 @@ #include "cpu.h" #include "exec-all.h" -#include "disas.h" +#include "disas/disas.h" #include "tcg-op.h" #include "qemu-common.h" #include "qemu-log.h" diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 653c2fdb1f..8a53105f89 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -19,7 +19,7 @@ */ #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" #include "tcg-op.h" #include "host-utils.h" diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index e63627cac1..984ca9fc63 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -23,7 +23,7 @@ * inside "#if defined(TODO) ... #endif" statements to make tests easier. */ -#include "dis-asm.h" +#include "disas/bfd.h" #include "gdbstub.h" #include #include "kvm_ppc.h" diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 787e3c6963..6e144a67a2 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -30,7 +30,7 @@ #endif #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" #include "tcg-op.h" #include "qemu-log.h" diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 86493e1b03..41d53e5c51 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -21,7 +21,7 @@ //#define SH4_SINGLE_STEP #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" #include "tcg-op.h" #include "helper.h" diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 5859f2e801..88802b8486 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -25,7 +25,7 @@ #include #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" #include "helper.h" #include "tcg-op.h" diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index 3951758fc8..8c49f4d701 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -15,7 +15,7 @@ #include #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" #include "tcg-op.h" #include "qemu-log.h" diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 5d8762c0ca..4e81cbd9ec 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -32,7 +32,7 @@ #include "cpu.h" #include "exec-all.h" -#include "disas.h" +#include "disas/disas.h" #include "tcg-op.h" #include "qemu-log.h" #include "sysemu.h" diff --git a/translate-all.c b/translate-all.c index 164870a68c..bbe06db6eb 100644 --- a/translate-all.c +++ b/translate-all.c @@ -33,7 +33,7 @@ #include "qemu-common.h" #define NO_CPU_IO_DEFS #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" #include "tcg.h" #include "qemu-timer.h" #include "memory.h" diff --git a/user-exec.c b/user-exec.c index 1185cb03c8..63fb05384f 100644 --- a/user-exec.c +++ b/user-exec.c @@ -18,7 +18,7 @@ */ #include "config.h" #include "cpu.h" -#include "disas.h" +#include "disas/disas.h" #include "tcg.h" #undef EAX diff --git a/vl.c b/vl.c index 3ebf01f8f1..571a49b931 100644 --- a/vl.c +++ b/vl.c @@ -154,7 +154,7 @@ int main(int argc, char **argv) #endif #include "qtest.h" -#include "disas.h" +#include "disas/disas.h" #include "qemu_socket.h" From 8e98e2e80b92e08e79e27a0c20a172906cfa12d2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 24 Oct 2012 11:16:01 +0200 Subject: [PATCH 2045/2270] build: kill libuser Signed-off-by: Paolo Bonzini --- Makefile | 8 +++----- Makefile.objs | 3 ++- Makefile.target | 3 +-- Makefile.user | 24 ------------------------ configure | 3 --- 5 files changed, 6 insertions(+), 35 deletions(-) delete mode 100644 Makefile.user diff --git a/Makefile b/Makefile index da47cb8572..0c6ad1efe6 100644 --- a/Makefile +++ b/Makefile @@ -132,7 +132,7 @@ $(SUBDIR_RULES): libqemustub.a $(filter %-softmmu,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) $(common-obj-y) $(extra-obj-y) -$(filter %-user,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) subdir-libuser +$(filter %-user,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) $(user-obj-y) ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS)) romsubdir-%: @@ -224,8 +224,6 @@ $(qga-obj-y) qemu-ga.o: $(QGALIB_GEN) qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(oslib-obj-y) $(trace-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y) libqemustub.a -QEMULIBS=libuser - clean: # avoid old build problems by removing potentially incorrect old files rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h @@ -242,7 +240,7 @@ clean: rm -rf qapi-generated rm -rf qga/qapi-generated $(MAKE) -C tests/tcg clean - for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard; do \ + for d in $(ALL_SUBDIRS) libcacard; do \ if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \ rm -f $$d/qemu-options.def; \ done @@ -265,7 +263,7 @@ distclean: clean rm -f config.log rm -f linux-headers/asm rm -f qemu-tech.info qemu-tech.aux qemu-tech.cp qemu-tech.dvi qemu-tech.fn qemu-tech.info qemu-tech.ky qemu-tech.log qemu-tech.pdf qemu-tech.pg qemu-tech.toc qemu-tech.tp qemu-tech.vr - for d in $(TARGET_DIRS) $(QEMULIBS); do \ + for d in $(TARGET_DIRS); do \ rm -rf $$d || exit 1 ; \ done if test -f pixman/config.log; then make -C pixman distclean; fi diff --git a/Makefile.objs b/Makefile.objs index 3248eafe32..986f085c85 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -123,7 +123,6 @@ user-obj-y += tcg-runtime.o host-utils.o user-obj-y += cache-utils.o user-obj-y += module.o user-obj-y += qemu-user.o -user-obj-y += $(trace-obj-y) user-obj-y += qom/ ###################################################################### @@ -196,6 +195,8 @@ trace-obj-y += trace/control.o $(trace-obj-y): $(GENERATED_HEADERS) +universal-obj-y += $(trace-obj-y) + ###################################################################### # smartcard diff --git a/Makefile.target b/Makefile.target index f353651369..8bbad380c2 100644 --- a/Makefile.target +++ b/Makefile.target @@ -155,9 +155,8 @@ all-obj-y += $(addprefix ../, $(universal-obj-y)) ifdef CONFIG_SOFTMMU all-obj-y += $(addprefix ../, $(common-obj-y)) -all-obj-y += $(addprefix ../, $(trace-obj-y)) else -all-obj-y += $(addprefix ../libuser/, $(user-obj-y)) +all-obj-y += $(addprefix ../, $(user-obj-y)) endif #CONFIG_LINUX_USER ifdef QEMU_PROGW diff --git a/Makefile.user b/Makefile.user deleted file mode 100644 index 9302d33245..0000000000 --- a/Makefile.user +++ /dev/null @@ -1,24 +0,0 @@ -# Makefile for qemu target independent user files. - -include ../config-host.mak -include $(SRC_PATH)/rules.mak --include config.mak - -.PHONY: all - -$(call set-vpath, $(SRC_PATH)) - -QEMU_CFLAGS+=-I.. -QEMU_CFLAGS += -I$(SRC_PATH)/include -QEMU_CFLAGS += -DCONFIG_USER_ONLY - -include $(SRC_PATH)/Makefile.objs - -all: $(user-obj-y) -# Dummy command so that make thinks it has done something - @true - -clean: - for d in . trace; do \ - rm -f $$d/*.o $$d/*.d $$d/*.a $$d/*~; \ - done diff --git a/configure b/configure index f180e172a7..4d0e1163a2 100755 --- a/configure +++ b/configure @@ -4212,9 +4212,6 @@ for rom in seabios vgabios ; do echo "LD=$ld" >> $config_mak done -d=libuser -symlink "$source_path/Makefile.user" "$d/Makefile" - if test "$docs" = "yes" ; then mkdir -p QMP fi From 077805fa92b9089137c6b6b196d449ee05cc342f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 25 Sep 2012 10:04:17 +0200 Subject: [PATCH 2046/2270] janitor: do not rely on indirect inclusions of or from qemu-char.h Various header files rely on qemu-char.h including qemu-config.h or main-loop.h, but they really do not need qemu-char.h at all (particularly interesting is the case of the block layer!). Clean this up, and also add missing inclusions of qemu-char.h itself. Signed-off-by: Paolo Bonzini --- arch_init.c | 1 + audio/alsaaudio.c | 1 + audio/ossaudio.c | 1 + block/blkdebug.c | 1 + block/iscsi.c | 1 + bt-host.c | 1 + bt-vhci.c | 1 + event_notifier-posix.c | 1 + exec.c | 1 + hw/arm_boot.c | 1 + hw/dma.c | 1 + hw/fw_cfg.c | 1 + hw/jazz_led.c | 1 + hw/mac_dbdma.c | 1 + hw/ppc/e500.c | 1 + hw/puv3.c | 2 ++ hw/qdev-monitor.c | 1 + hw/qdev-properties.c | 1 + hw/s390x/sclpconsole.c | 1 + hw/spapr.c | 1 + hw/tcx.c | 1 + hw/usb/dev-network.c | 1 + net.c | 1 + qemu-config.h | 1 + spice-qemu-char.c | 1 + target-i386/kvm.c | 1 + 26 files changed, 27 insertions(+) diff --git a/arch_init.c b/arch_init.c index 1645f3079a..ef866cdea4 100644 --- a/arch_init.c +++ b/arch_init.c @@ -46,6 +46,7 @@ #include "exec-memory.h" #include "hw/pcspk.h" #include "qemu/page_cache.h" +#include "qemu-config.h" #include "qmp-commands.h" #include "trace.h" diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index cb45b49c2a..564d632d0c 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -23,6 +23,7 @@ */ #include #include "qemu-common.h" +#include "main-loop.h" #include "qemu-char.h" #include "audio.h" diff --git a/audio/ossaudio.c b/audio/ossaudio.c index df51b7cc58..45abe39a6d 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -31,6 +31,7 @@ #include #endif #include "qemu-common.h" +#include "main-loop.h" #include "host-utils.h" #include "qemu-char.h" #include "audio.h" diff --git a/block/blkdebug.c b/block/blkdebug.c index 294e983306..65556e73e5 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -23,6 +23,7 @@ */ #include "qemu-common.h" +#include "qemu-config.h" #include "block_int.h" #include "module.h" diff --git a/block/iscsi.c b/block/iscsi.c index c0b70b3d32..33b93d8000 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -27,6 +27,7 @@ #include #include #include "qemu-common.h" +#include "qemu-config.h" #include "qemu-error.h" #include "block_int.h" #include "trace.h" diff --git a/bt-host.c b/bt-host.c index 0d3ad28e8c..8b47370b26 100644 --- a/bt-host.c +++ b/bt-host.c @@ -21,6 +21,7 @@ #include "qemu-char.h" #include "net.h" #include "bt-host.h" +#include "main-loop.h" #ifndef _WIN32 # include diff --git a/bt-vhci.c b/bt-vhci.c index bbc1029854..878460aeb5 100644 --- a/bt-vhci.c +++ b/bt-vhci.c @@ -21,6 +21,7 @@ #include "qemu-char.h" #include "net.h" #include "hw/bt.h" +#include "main-loop.h" #define VHCI_DEV "/dev/vhci" #define VHCI_UDEV "/dev/hci_vhci" diff --git a/event_notifier-posix.c b/event_notifier-posix.c index 6f3239a3fc..f0bd839acd 100644 --- a/event_notifier-posix.c +++ b/event_notifier-posix.c @@ -13,6 +13,7 @@ #include "qemu-common.h" #include "event_notifier.h" #include "qemu-char.h" +#include "main-loop.h" #ifdef CONFIG_EVENTFD #include diff --git a/exec.c b/exec.c index 4c1246a9f9..986084146c 100644 --- a/exec.c +++ b/exec.c @@ -33,6 +33,7 @@ #include "kvm.h" #include "hw/xen.h" #include "qemu-timer.h" +#include "qemu-config.h" #include "memory.h" #include "dma.h" #include "exec-memory.h" diff --git a/hw/arm_boot.c b/hw/arm_boot.c index ec3b8d5d12..63ff559cf7 100644 --- a/hw/arm_boot.c +++ b/hw/arm_boot.c @@ -15,6 +15,7 @@ #include "loader.h" #include "elf.h" #include "device_tree.h" +#include "qemu-config.h" #define KERNEL_ARGS_ADDR 0x100 #define KERNEL_LOAD_ADDR 0x00010000 diff --git a/hw/dma.c b/hw/dma.c index c2d7b21562..364f54d2d7 100644 --- a/hw/dma.c +++ b/hw/dma.c @@ -23,6 +23,7 @@ */ #include "hw.h" #include "isa.h" +#include "main-loop.h" /* #define DEBUG_DMA */ diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c index 2b92cda98a..7b0e50f70d 100644 --- a/hw/fw_cfg.c +++ b/hw/fw_cfg.c @@ -27,6 +27,7 @@ #include "fw_cfg.h" #include "sysbus.h" #include "qemu-error.h" +#include "qemu-config.h" /* debug firmware config */ //#define DEBUG_FW_CFG diff --git a/hw/jazz_led.c b/hw/jazz_led.c index 640e75ef2f..09c77429e8 100644 --- a/hw/jazz_led.c +++ b/hw/jazz_led.c @@ -22,6 +22,7 @@ * THE SOFTWARE. */ +#include "qemu-common.h" #include "console.h" #include "pixel_ops.h" #include "trace.h" diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c index e551156af9..41eee50a35 100644 --- a/hw/mac_dbdma.c +++ b/hw/mac_dbdma.c @@ -39,6 +39,7 @@ #include "hw.h" #include "isa.h" #include "mac_dbdma.h" +#include "main-loop.h" /* debug DBDMA */ //#define DEBUG_DBDMA diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 8fab508c07..2b1558b16e 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -19,6 +19,7 @@ #include "e500.h" #include "e500-ccsr.h" #include "net.h" +#include "qemu-config.h" #include "hw/hw.h" #include "hw/serial.h" #include "hw/pci/pci.h" diff --git a/hw/puv3.c b/hw/puv3.c index 3d7734936b..6f89c44e32 100644 --- a/hw/puv3.c +++ b/hw/puv3.c @@ -8,6 +8,8 @@ * published by the Free Software Foundation, or any later version. * See the COPYING file in the top-level directory. */ + +#include "qemu-common.h" #include "console.h" #include "elf.h" #include "exec-memory.h" diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c index a1b4d6ae5f..5aaf74b98a 100644 --- a/hw/qdev-monitor.c +++ b/hw/qdev-monitor.c @@ -21,6 +21,7 @@ #include "monitor.h" #include "qmp-commands.h" #include "arch_init.h" +#include "qemu-config.h" /* * Aliases were a bad idea from the start. Let's keep them diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 81d901c6c4..b9cd3c0077 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -5,6 +5,7 @@ #include "hw/block-common.h" #include "net/hub.h" #include "qapi/qapi-visit-core.h" +#include "qemu-char.h" void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) { diff --git a/hw/s390x/sclpconsole.c b/hw/s390x/sclpconsole.c index fece878e88..9ad297c999 100644 --- a/hw/s390x/sclpconsole.c +++ b/hw/s390x/sclpconsole.c @@ -17,6 +17,7 @@ #include "sclp.h" #include "event-facility.h" +#include "qemu-char.h" typedef struct ASCIIConsoleData { EventBufferHeader ebh; diff --git a/hw/spapr.c b/hw/spapr.c index 9bd2fd5c8c..7306ab368a 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -49,6 +49,7 @@ #include "exec-memory.h" #include "hw/usb.h" +#include "qemu-config.h" #include diff --git a/hw/tcx.c b/hw/tcx.c index 7aee2a9bd3..a66fbeefdb 100644 --- a/hw/tcx.c +++ b/hw/tcx.c @@ -22,6 +22,7 @@ * THE SOFTWARE. */ +#include "qemu-common.h" #include "console.h" #include "pixel_ops.h" #include "sysbus.h" diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 30cb03373e..0552e6f438 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -28,6 +28,7 @@ #include "hw/usb/desc.h" #include "net.h" #include "qemu-queue.h" +#include "qemu-config.h" #include "sysemu.h" #include "iov.h" diff --git a/net.c b/net.c index e8ae13e283..4f3d642468 100644 --- a/net.c +++ b/net.c @@ -32,6 +32,7 @@ #include "monitor.h" #include "qemu-common.h" #include "qemu_socket.h" +#include "qemu-config.h" #include "qmp-commands.h" #include "hw/qdev.h" #include "iov.h" diff --git a/qemu-config.h b/qemu-config.h index 812c4c5b10..eb50eca838 100644 --- a/qemu-config.h +++ b/qemu-config.h @@ -4,6 +4,7 @@ #include #include "qemu-option.h" #include "error.h" +#include "qemu-option.h" extern QemuOptsList qemu_fsdev_opts; extern QemuOptsList qemu_virtfs_opts; diff --git a/spice-qemu-char.c b/spice-qemu-char.c index 09aa22d566..5f95c937f3 100644 --- a/spice-qemu-char.c +++ b/spice-qemu-char.c @@ -1,6 +1,7 @@ #include "config-host.h" #include "trace.h" #include "ui/qemu-spice.h" +#include "qemu-char.h" #include #include diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 0901589a88..824930c749 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -27,6 +27,7 @@ #include "cpu.h" #include "gdbstub.h" #include "host-utils.h" +#include "qemu-config.h" #include "hw/pc.h" #include "hw/apic.h" #include "ioport.h" From f8fe796407d8b340def61a6b57991e47aee3cfc4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 24 Oct 2012 08:49:51 +0200 Subject: [PATCH 2047/2270] janitor: do not include qemu-char everywhere Touching char/char.h basically causes the whole of QEMU to be rebuilt. Avoid this, it is usually unnecessary. Signed-off-by: Paolo Bonzini --- audio/alsaaudio.c | 1 - audio/ossaudio.c | 1 - block/raw-posix.c | 1 - bt-host.c | 1 - bt-vhci.c | 1 - buffered_file.c | 1 - console.c | 1 + console.h | 1 - hmp.c | 1 + hw/9pfs/virtio-9p-coth.c | 1 - hw/ivshmem.c | 1 + hw/spapr_hcall.c | 2 -- hw/strongarm.c | 1 + hw/xen_disk.c | 1 - hw/xen_nic.c | 1 - hw/xilinx_axidma.c | 1 - hw/xilinx_axienet.c | 1 - hw/xtensa_lx60.c | 1 + iohandler.c | 1 - migration-exec.c | 1 - migration-fd.c | 1 - migration-tcp.c | 1 - migration-unix.c | 1 - monitor.h | 1 - net/slirp.c | 1 + net/socket.c | 1 - net/tap.c | 1 - net/vde.c | 1 - qmp.c | 1 + savevm.c | 1 - ui/qemu-spice.h | 1 - 31 files changed, 7 insertions(+), 25 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 564d632d0c..cd553c2a7b 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -24,7 +24,6 @@ #include #include "qemu-common.h" #include "main-loop.h" -#include "qemu-char.h" #include "audio.h" #if QEMU_GNUC_PREREQ(4, 3) diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 45abe39a6d..8249a00449 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -33,7 +33,6 @@ #include "qemu-common.h" #include "main-loop.h" #include "host-utils.h" -#include "qemu-char.h" #include "audio.h" #define AUDIO_CAP "oss" diff --git a/block/raw-posix.c b/block/raw-posix.c index abfedbea73..48eff2fd83 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -23,7 +23,6 @@ */ #include "qemu-common.h" #include "qemu-timer.h" -#include "qemu-char.h" #include "qemu-log.h" #include "block_int.h" #include "module.h" diff --git a/bt-host.c b/bt-host.c index 8b47370b26..311864517d 100644 --- a/bt-host.c +++ b/bt-host.c @@ -18,7 +18,6 @@ */ #include "qemu-common.h" -#include "qemu-char.h" #include "net.h" #include "bt-host.h" #include "main-loop.h" diff --git a/bt-vhci.c b/bt-vhci.c index 878460aeb5..6fecb66716 100644 --- a/bt-vhci.c +++ b/bt-vhci.c @@ -18,7 +18,6 @@ */ #include "qemu-common.h" -#include "qemu-char.h" #include "net.h" #include "hw/bt.h" #include "main-loop.h" diff --git a/buffered_file.c b/buffered_file.c index bd0f61d8c9..f13443ee91 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -16,7 +16,6 @@ #include "qemu-common.h" #include "hw/hw.h" #include "qemu-timer.h" -#include "qemu-char.h" #include "buffered_file.h" //#define DEBUG_BUFFERED_FILE diff --git a/console.c b/console.c index 048b48e721..9ac7b28742 100644 --- a/console.c +++ b/console.c @@ -25,6 +25,7 @@ #include "console.h" #include "qemu-timer.h" #include "qmp-commands.h" +#include "qemu-char.h" //#define DEBUG_CONSOLE #define DEFAULT_BACKSCROLL 512 diff --git a/console.h b/console.h index edb1950871..33354e437a 100644 --- a/console.h +++ b/console.h @@ -1,7 +1,6 @@ #ifndef CONSOLE_H #define CONSOLE_H -#include "qemu-char.h" #include "qemu-pixman.h" #include "qdict.h" #include "notify.h" diff --git a/hmp.c b/hmp.c index 180ba2bfd9..873962f710 100644 --- a/hmp.c +++ b/hmp.c @@ -15,6 +15,7 @@ #include "hmp.h" #include "net.h" +#include "qemu-char.h" #include "qemu-option.h" #include "qemu-timer.h" #include "qmp-commands.h" diff --git a/hw/9pfs/virtio-9p-coth.c b/hw/9pfs/virtio-9p-coth.c index 25556cc6a7..9368df7610 100644 --- a/hw/9pfs/virtio-9p-coth.c +++ b/hw/9pfs/virtio-9p-coth.c @@ -12,7 +12,6 @@ * */ -#include "qemu-char.h" #include "fsdev/qemu-fsdev.h" #include "qemu-thread.h" #include "qemu-coroutine.h" diff --git a/hw/ivshmem.c b/hw/ivshmem.c index cf64f32ac0..5c648d98d3 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -24,6 +24,7 @@ #include "migration.h" #include "qerror.h" #include "event_notifier.h" +#include "qemu-char.h" #include #include diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c index 63cadb8d92..1fac362329 100644 --- a/hw/spapr_hcall.c +++ b/hw/spapr_hcall.c @@ -1,8 +1,6 @@ #include "sysemu.h" #include "cpu.h" -#include "qemu-char.h" #include "sysemu.h" -#include "qemu-char.h" #include "helper_regs.h" #include "hw/spapr.h" diff --git a/hw/strongarm.c b/hw/strongarm.c index 43855151ce..44bec34e07 100644 --- a/hw/strongarm.c +++ b/hw/strongarm.c @@ -30,6 +30,7 @@ #include "strongarm.h" #include "qemu-error.h" #include "arm-misc.h" +#include "qemu-char.h" #include "sysemu.h" #include "ssi.h" diff --git a/hw/xen_disk.c b/hw/xen_disk.c index e6bb2f20b9..423b580cff 100644 --- a/hw/xen_disk.c +++ b/hw/xen_disk.c @@ -36,7 +36,6 @@ #include #include "hw.h" -#include "qemu-char.h" #include "xen_backend.h" #include "xen_blkif.h" #include "blockdev.h" diff --git a/hw/xen_nic.c b/hw/xen_nic.c index cf7d5591b3..dadacb1fb5 100644 --- a/hw/xen_nic.c +++ b/hw/xen_nic.c @@ -39,7 +39,6 @@ #include "net.h" #include "net/checksum.h" #include "net/util.h" -#include "qemu-char.h" #include "xen_backend.h" #include diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c index 4575da1765..2fd6068428 100644 --- a/hw/xilinx_axidma.c +++ b/hw/xilinx_axidma.c @@ -23,7 +23,6 @@ */ #include "sysbus.h" -#include "qemu-char.h" #include "qemu-timer.h" #include "ptimer.h" #include "qemu-log.h" diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c index f2e3bf1274..c859fde09e 100644 --- a/hw/xilinx_axienet.c +++ b/hw/xilinx_axienet.c @@ -23,7 +23,6 @@ */ #include "sysbus.h" -#include "qemu-char.h" #include "qemu-log.h" #include "net.h" #include "net/checksum.h" diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c index 4c42edc4ea..bc10d3161f 100644 --- a/hw/xtensa_lx60.c +++ b/hw/xtensa_lx60.c @@ -36,6 +36,7 @@ #include "sysbus.h" #include "flash.h" #include "blockdev.h" +#include "qemu-char.h" #include "xtensa_bootparam.h" typedef struct LxBoardDesc { diff --git a/iohandler.c b/iohandler.c index 60460a6f88..258f42d8d2 100644 --- a/iohandler.c +++ b/iohandler.c @@ -24,7 +24,6 @@ #include "config-host.h" #include "qemu-common.h" -#include "qemu-char.h" #include "qemu-queue.h" #include "qemu-aio.h" #include "main-loop.h" diff --git a/migration-exec.c b/migration-exec.c index 2b6fcb4262..b4a3ca3921 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -18,7 +18,6 @@ #include "qemu-common.h" #include "qemu_socket.h" #include "migration.h" -#include "qemu-char.h" #include "buffered_file.h" #include "block.h" #include diff --git a/migration-fd.c b/migration-fd.c index 5fe28e09fd..6d42287913 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -17,7 +17,6 @@ #include "qemu_socket.h" #include "migration.h" #include "monitor.h" -#include "qemu-char.h" #include "buffered_file.h" #include "block.h" #include "qemu_socket.h" diff --git a/migration-tcp.c b/migration-tcp.c index 5e855fe72f..a9bb817d99 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -16,7 +16,6 @@ #include "qemu-common.h" #include "qemu_socket.h" #include "migration.h" -#include "qemu-char.h" #include "buffered_file.h" #include "block.h" diff --git a/migration-unix.c b/migration-unix.c index dba72b4a54..e58e8bc15b 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -16,7 +16,6 @@ #include "qemu-common.h" #include "qemu_socket.h" #include "migration.h" -#include "qemu-char.h" #include "buffered_file.h" #include "block.h" diff --git a/monitor.h b/monitor.h index b4ef9559dc..4595c217ed 100644 --- a/monitor.h +++ b/monitor.h @@ -2,7 +2,6 @@ #define MONITOR_H #include "qemu-common.h" -#include "qemu-char.h" #include "qerror.h" #include "qdict.h" #include "block.h" diff --git a/net/slirp.c b/net/slirp.c index afb52c3af1..f117412bad 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -35,6 +35,7 @@ #include "monitor.h" #include "qemu_socket.h" #include "slirp/libslirp.h" +#include "qemu-char.h" static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) { diff --git a/net/socket.c b/net/socket.c index c01323d4b0..cf309cd5b9 100644 --- a/net/socket.c +++ b/net/socket.c @@ -26,7 +26,6 @@ #include "net.h" #include "clients.h" #include "monitor.h" -#include "qemu-char.h" #include "qemu-common.h" #include "qemu-error.h" #include "qemu-option.h" diff --git a/net/tap.c b/net/tap.c index 1abfd44bd9..5ff78934dc 100644 --- a/net/tap.c +++ b/net/tap.c @@ -37,7 +37,6 @@ #include "clients.h" #include "monitor.h" #include "sysemu.h" -#include "qemu-char.h" #include "qemu-common.h" #include "qemu-error.h" diff --git a/net/vde.c b/net/vde.c index 275bda92c3..cc5a07d65e 100644 --- a/net/vde.c +++ b/net/vde.c @@ -27,7 +27,6 @@ #include "net.h" #include "clients.h" -#include "qemu-char.h" #include "qemu-common.h" #include "qemu-option.h" diff --git a/qmp.c b/qmp.c index e3a7f0b217..e873f0a0dc 100644 --- a/qmp.c +++ b/qmp.c @@ -16,6 +16,7 @@ #include "qemu-common.h" #include "sysemu.h" #include "qmp-commands.h" +#include "qemu-char.h" #include "ui/qemu-spice.h" #include "ui/vnc.h" #include "kvm.h" diff --git a/savevm.c b/savevm.c index 5d04d59688..f5886ce772 100644 --- a/savevm.c +++ b/savevm.c @@ -76,7 +76,6 @@ #include "monitor.h" #include "sysemu.h" #include "qemu-timer.h" -#include "qemu-char.h" #include "audio/audio.h" #include "migration.h" #include "qemu_socket.h" diff --git a/ui/qemu-spice.h b/ui/qemu-spice.h index 3299da87d6..5857b8a92e 100644 --- a/ui/qemu-spice.h +++ b/ui/qemu-spice.h @@ -24,7 +24,6 @@ #include "qemu-option.h" #include "qemu-config.h" -#include "qemu-char.h" #include "monitor.h" extern int using_spice; From 090f7ac5ba433ef9de7004b8e8304d06bd9ffd7d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 24 Oct 2012 09:36:16 +0200 Subject: [PATCH 2048/2270] net: move Bluetooth stuff out of net.h Signed-off-by: Paolo Bonzini --- bt-host.c | 1 - bt-host.h | 13 ++++++++++++- bt-vhci.c | 2 +- hw/bt-hci-csr.c | 2 +- hw/bt-hci.c | 2 +- hw/bt.c | 2 +- hw/usb/dev-bluetooth.c | 2 +- net.h | 14 -------------- 8 files changed, 17 insertions(+), 21 deletions(-) diff --git a/bt-host.c b/bt-host.c index 311864517d..65aaca337c 100644 --- a/bt-host.c +++ b/bt-host.c @@ -18,7 +18,6 @@ */ #include "qemu-common.h" -#include "net.h" #include "bt-host.h" #include "main-loop.h" diff --git a/bt-host.h b/bt-host.h index f1eff65f45..2bc6d53cca 100644 --- a/bt-host.h +++ b/bt-host.h @@ -1,9 +1,20 @@ #ifndef BT_HOST_H #define BT_HOST_H -struct HCIInfo; +/* BT HCI info */ + +struct HCIInfo { + int (*bdaddr_set)(struct HCIInfo *hci, const uint8_t *bd_addr); + void (*cmd_send)(struct HCIInfo *hci, const uint8_t *data, int len); + void (*sco_send)(struct HCIInfo *hci, const uint8_t *data, int len); + void (*acl_send)(struct HCIInfo *hci, const uint8_t *data, int len); + void *opaque; + void (*evt_recv)(void *opaque, const uint8_t *data, int len); + void (*acl_recv)(void *opaque, const uint8_t *data, int len); +}; /* bt-host.c */ struct HCIInfo *bt_host_hci(const char *id); +struct HCIInfo *qemu_next_hci(void); #endif diff --git a/bt-vhci.c b/bt-vhci.c index 6fecb66716..13c0e53729 100644 --- a/bt-vhci.c +++ b/bt-vhci.c @@ -18,7 +18,7 @@ */ #include "qemu-common.h" -#include "net.h" +#include "bt-host.h" #include "hw/bt.h" #include "main-loop.h" diff --git a/hw/bt-hci-csr.c b/hw/bt-hci-csr.c index 772b677ba1..0faabbb585 100644 --- a/hw/bt-hci-csr.c +++ b/hw/bt-hci-csr.c @@ -22,7 +22,7 @@ #include "qemu-char.h" #include "qemu-timer.h" #include "irq.h" -#include "net.h" +#include "bt-host.h" #include "bt.h" struct csrhci_s { diff --git a/hw/bt-hci.c b/hw/bt-hci.c index e54cfd7815..d2ad57faa9 100644 --- a/hw/bt-hci.c +++ b/hw/bt-hci.c @@ -21,7 +21,7 @@ #include "qemu-common.h" #include "qemu-timer.h" #include "usb.h" -#include "net.h" +#include "bt-host.h" #include "bt.h" struct bt_hci_s { diff --git a/hw/bt.c b/hw/bt.c index dc99fc28fa..3fea0983d4 100644 --- a/hw/bt.c +++ b/hw/bt.c @@ -18,7 +18,7 @@ */ #include "qemu-common.h" -#include "net.h" +#include "bt-host.h" #include "bt.h" /* Slave implementations can ignore this */ diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c index 39984f53eb..4a37442288 100644 --- a/hw/usb/dev-bluetooth.c +++ b/hw/usb/dev-bluetooth.c @@ -21,7 +21,7 @@ #include "qemu-common.h" #include "hw/usb.h" #include "hw/usb/desc.h" -#include "net.h" +#include "bt-host.h" #include "hw/bt.h" struct USBBtState { diff --git a/net.h b/net.h index 04fda1d6c8..1d0816bc0a 100644 --- a/net.h +++ b/net.h @@ -133,20 +133,6 @@ extern int nb_nics; extern NICInfo nd_table[MAX_NICS]; extern int default_net; -/* BT HCI info */ - -struct HCIInfo { - int (*bdaddr_set)(struct HCIInfo *hci, const uint8_t *bd_addr); - void (*cmd_send)(struct HCIInfo *hci, const uint8_t *data, int len); - void (*sco_send)(struct HCIInfo *hci, const uint8_t *data, int len); - void (*acl_send)(struct HCIInfo *hci, const uint8_t *data, int len); - void *opaque; - void (*evt_recv)(void *opaque, const uint8_t *data, int len); - void (*acl_recv)(void *opaque, const uint8_t *data, int len); -}; - -struct HCIInfo *qemu_next_hci(void); - /* from net.c */ extern const char *legacy_tftp_prefix; extern const char *legacy_bootp_filename; From 7fa22f2bf7a06d5345283a00a7c6d86b8a345228 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 24 Oct 2012 09:36:33 +0200 Subject: [PATCH 2049/2270] net: do not include net.h everywhere Signed-off-by: Paolo Bonzini --- arch_init.c | 1 - hw/alpha_sys.h | 1 - hw/device-hotplug.c | 1 - hw/lm32_boards.c | 1 - hw/milkymist-hw.h | 1 + hw/milkymist.c | 1 - hw/s390-virtio-bus.c | 1 - hw/spapr_vscsi.c | 1 - hw/virtex_ml507.c | 1 - hw/virtio-net.h | 1 - hw/virtio-pci.c | 1 - hw/virtio-scsi.h | 1 - hw/xen_backend.h | 1 - hw/xen_platform.c | 1 - input.c | 1 - qemu-char.c | 1 - qemu-timer.c | 1 - 17 files changed, 1 insertion(+), 16 deletions(-) diff --git a/arch_init.c b/arch_init.c index ef866cdea4..e479a2566c 100644 --- a/arch_init.c +++ b/arch_init.c @@ -40,7 +40,6 @@ #include "hw/audiodev.h" #include "kvm.h" #include "migration.h" -#include "net.h" #include "gdbstub.h" #include "hw/smbios.h" #include "exec-memory.h" diff --git a/hw/alpha_sys.h b/hw/alpha_sys.h index b1e52585b3..348f55c27e 100644 --- a/hw/alpha_sys.h +++ b/hw/alpha_sys.h @@ -6,7 +6,6 @@ #include "pci/pci.h" #include "pci/pci_host.h" #include "ide.h" -#include "net.h" #include "pc.h" #include "irq.h" diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c index 839b9ea1d4..336ffc2274 100644 --- a/hw/device-hotplug.c +++ b/hw/device-hotplug.c @@ -24,7 +24,6 @@ #include "hw.h" #include "boards.h" -#include "net.h" #include "blockdev.h" #include "qemu-config.h" #include "sysemu.h" diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c index 772cb8b053..f59d3bfef8 100644 --- a/hw/lm32_boards.c +++ b/hw/lm32_boards.c @@ -19,7 +19,6 @@ #include "sysbus.h" #include "hw.h" -#include "net.h" #include "flash.h" #include "devices.h" #include "boards.h" diff --git a/hw/milkymist-hw.h b/hw/milkymist-hw.h index 96b2a7f863..0253b7ab26 100644 --- a/hw/milkymist-hw.h +++ b/hw/milkymist-hw.h @@ -3,6 +3,7 @@ #include "qdev.h" #include "qdev-addr.h" +#include "net.h" static inline DeviceState *milkymist_uart_create(hwaddr base, qemu_irq irq) diff --git a/hw/milkymist.c b/hw/milkymist.c index 4c8111a74d..c26ea4aed2 100644 --- a/hw/milkymist.c +++ b/hw/milkymist.c @@ -19,7 +19,6 @@ #include "sysbus.h" #include "hw.h" -#include "net.h" #include "flash.h" #include "sysemu.h" #include "devices.h" diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index e0ac2d1ec2..169dd4683d 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -20,7 +20,6 @@ #include "hw.h" #include "block.h" #include "sysemu.h" -#include "net.h" #include "boards.h" #include "monitor.h" #include "loader.h" diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c index e3d4b237f1..2d811320ca 100644 --- a/hw/spapr_vscsi.c +++ b/hw/spapr_vscsi.c @@ -34,7 +34,6 @@ #include "hw.h" #include "scsi.h" #include "scsi-defs.h" -#include "net.h" /* Remove that when we can */ #include "srp.h" #include "hw/qdev.h" #include "hw/spapr.h" diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c index 6ab8fee0c1..1fdbc497cc 100644 --- a/hw/virtex_ml507.c +++ b/hw/virtex_ml507.c @@ -25,7 +25,6 @@ #include "sysbus.h" #include "hw.h" #include "serial.h" -#include "net.h" #include "flash.h" #include "sysemu.h" #include "devices.h" diff --git a/hw/virtio-net.h b/hw/virtio-net.h index b13be7ccb5..2566ea13ec 100644 --- a/hw/virtio-net.h +++ b/hw/virtio-net.h @@ -15,7 +15,6 @@ #define _QEMU_VIRTIO_NET_H #include "virtio.h" -#include "net.h" #include "pci/pci.h" #define ETH_ALEN 6 diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index d0d6a5e816..a2355dc867 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -26,7 +26,6 @@ #include "qemu-error.h" #include "pci/msi.h" #include "pci/msix.h" -#include "net.h" #include "loader.h" #include "kvm.h" #include "blockdev.h" diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h index 7d7cba752d..8d9d15f093 100644 --- a/hw/virtio-scsi.h +++ b/hw/virtio-scsi.h @@ -15,7 +15,6 @@ #define _QEMU_VIRTIO_SCSI_H #include "virtio.h" -#include "net.h" #include "pci/pci.h" /* The ID for virtio_scsi */ diff --git a/hw/xen_backend.h b/hw/xen_backend.h index fea86dd78b..3305630903 100644 --- a/hw/xen_backend.h +++ b/hw/xen_backend.h @@ -4,7 +4,6 @@ #include "xen_common.h" #include "sysemu.h" #include "net.h" -#include "net/hub.h" /* ------------------------------------------------------------- */ diff --git a/hw/xen_platform.c b/hw/xen_platform.c index 10bb560073..023499eb55 100644 --- a/hw/xen_platform.c +++ b/hw/xen_platform.c @@ -30,7 +30,6 @@ #include "pci/pci.h" #include "irq.h" #include "xen_common.h" -#include "net.h" #include "xen_backend.h" #include "trace.h" #include "exec-memory.h" diff --git a/input.c b/input.c index 25d3973e21..123bb237d4 100644 --- a/input.c +++ b/input.c @@ -23,7 +23,6 @@ */ #include "sysemu.h" -#include "net.h" #include "monitor.h" #include "console.h" #include "error.h" diff --git a/qemu-char.c b/qemu-char.c index 242b799909..f066ad0654 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -22,7 +22,6 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "net.h" #include "monitor.h" #include "console.h" #include "sysemu.h" diff --git a/qemu-timer.c b/qemu-timer.c index 0d2bb94289..9b9585b259 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -23,7 +23,6 @@ */ #include "sysemu.h" -#include "net.h" #include "monitor.h" #include "console.h" From fd9400b302ef582c3ae8a8d5288338ea5f0f4c9a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 24 Oct 2012 11:27:28 +0200 Subject: [PATCH 2050/2270] net: move net.c to net/ Signed-off-by: Paolo Bonzini --- Makefile.objs | 2 +- net/Makefile.objs | 2 +- net.c => net/net.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) rename net.c => net/net.c (99%) diff --git a/Makefile.objs b/Makefile.objs index 986f085c85..83092dc74b 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -66,7 +66,7 @@ endif # single QEMU executable should support all CPUs and machines. common-obj-y = $(block-obj-y) blockdev.o blockdev-nbd.o block/ -common-obj-y += net.o net/ +common-obj-y += net/ common-obj-y += qom/ common-obj-y += readline.o console.o cursor.o common-obj-y += qemu-pixman.o diff --git a/net/Makefile.objs b/net/Makefile.objs index cf04187717..a08cd14e2e 100644 --- a/net/Makefile.objs +++ b/net/Makefile.objs @@ -1,4 +1,4 @@ -common-obj-y = queue.o checksum.o util.o hub.o +common-obj-y = net.o queue.o checksum.o util.o hub.o common-obj-y += socket.o common-obj-y += dump.o common-obj-$(CONFIG_POSIX) += tap.o diff --git a/net.c b/net/net.c similarity index 99% rename from net.c rename to net/net.c index 4f3d642468..7b1600f17c 100644 --- a/net.c +++ b/net/net.c @@ -24,10 +24,10 @@ #include "config-host.h" #include "net.h" -#include "net/clients.h" -#include "net/hub.h" -#include "net/slirp.h" -#include "net/util.h" +#include "clients.h" +#include "hub.h" +#include "slirp.h" +#include "util.h" #include "monitor.h" #include "qemu-common.h" From 1422e32db51ff2b1194fb24a6201c4310be5667d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 24 Oct 2012 08:43:34 +0200 Subject: [PATCH 2051/2270] net: reorganize headers Move public headers to include/net, and leave private headers in net/. Put the virtio headers in include/net/tap.h, removing the multiple copies that existed. Leave include/net/tap.h as the interface for NICs, and net/tap_int.h as the interface for OS-specific parts of the tap backend. Signed-off-by: Paolo Bonzini --- hmp.c | 2 +- hw/axis_dev88.c | 2 +- hw/cadence_gem.c | 2 +- hw/dp8393x.c | 2 +- hw/e1000.c | 2 +- hw/eepro100.c | 2 +- hw/etraxfs.h | 2 +- hw/etraxfs_eth.c | 2 +- hw/exynos4_boards.c | 2 +- hw/gumstix.c | 2 +- hw/highbank.c | 2 +- hw/integratorcp.c | 2 +- hw/kzm.c | 2 +- hw/lan9118.c | 2 +- hw/lance.c | 2 +- hw/mainstone.c | 2 +- hw/mcf5208.c | 2 +- hw/mcf_fec.c | 2 +- hw/milkymist-hw.h | 2 +- hw/milkymist-minimac2.c | 2 +- hw/mips_fulong2e.c | 2 +- hw/mips_jazz.c | 2 +- hw/mips_malta.c | 2 +- hw/mips_mipssim.c | 2 +- hw/mips_r4k.c | 2 +- hw/mipsnet.c | 2 +- hw/musicpal.c | 2 +- hw/ne2000-isa.c | 2 +- hw/ne2000.c | 2 +- hw/opencores_eth.c | 2 +- hw/openrisc_sim.c | 2 +- hw/pc.h | 2 +- hw/pc_piix.c | 2 +- hw/pci/pci-hotplug.c | 2 +- hw/pci/pci.c | 2 +- hw/pcnet-pci.c | 2 +- hw/pcnet.c | 2 +- hw/petalogix_ml605_mmu.c | 2 +- hw/petalogix_s3adsp1800_mmu.c | 2 +- hw/ppc/e500.c | 2 +- hw/ppc440_bamboo.c | 2 +- hw/ppc_newworld.c | 2 +- hw/ppc_oldworld.c | 2 +- hw/ppc_prep.c | 2 +- hw/qdev-properties.c | 2 +- hw/qdev.c | 2 +- hw/r2d.c | 2 +- hw/realview.c | 2 +- hw/rtl8139.c | 2 +- hw/s390-virtio.c | 2 +- hw/smc91c111.c | 2 +- hw/spapr.c | 2 +- hw/spapr_llan.c | 2 +- hw/stellaris.c | 2 +- hw/stellaris_enet.c | 2 +- hw/sun4m.c | 2 +- hw/sun4u.c | 2 +- hw/usb/dev-network.c | 2 +- hw/versatilepb.c | 2 +- hw/vexpress.c | 2 +- hw/vhost_net.c | 2 +- hw/vhost_net.h | 2 +- hw/virtio-net.c | 2 +- hw/virtio-net.h | 27 ------------- hw/virtio.h | 2 +- hw/xen_backend.h | 2 +- hw/xen_nic.c | 2 +- hw/xgmac.c | 2 +- hw/xilinx.h | 2 +- hw/xilinx_axienet.c | 2 +- hw/xilinx_ethlite.c | 2 +- hw/xilinx_zynq.c | 2 +- hw/xtensa_lx60.c | 2 +- {net => include/net}/checksum.h | 0 net.h => include/net/net.h | 3 ++ {net => include/net}/queue.h | 0 {net => include/net}/slirp.h | 0 include/net/tap.h | 67 +++++++++++++++++++++++++++++++++ monitor.c | 2 +- net/clients.h | 2 +- net/hub.c | 2 +- net/hub.h | 2 - net/net.c | 4 +- net/queue.c | 2 +- net/slirp.c | 2 +- net/socket.c | 2 +- net/tap-aix.c | 2 +- net/tap-bsd.c | 2 +- net/tap-haiku.c | 2 +- net/tap-linux.c | 3 +- net/tap-linux.h | 20 +--------- net/tap-solaris.c | 2 +- net/tap-win32.c | 4 +- net/tap.c | 6 +-- net/{tap.h => tap_int.h} | 18 ++------- net/util.c | 2 +- net/vde.c | 2 +- savevm.c | 2 +- vl.c | 2 +- 99 files changed, 170 insertions(+), 156 deletions(-) rename {net => include/net}/checksum.h (100%) rename net.h => include/net/net.h (98%) rename {net => include/net}/queue.h (100%) rename {net => include/net}/slirp.h (100%) create mode 100644 include/net/tap.h rename net/{tap.h => tap_int.h} (77%) diff --git a/hmp.c b/hmp.c index 873962f710..9b31e9f8a7 100644 --- a/hmp.c +++ b/hmp.c @@ -14,7 +14,7 @@ */ #include "hmp.h" -#include "net.h" +#include "net/net.h" #include "qemu-char.h" #include "qemu-option.h" #include "qemu-timer.h" diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c index aa1ac9e479..50ddbc920d 100644 --- a/hw/axis_dev88.c +++ b/hw/axis_dev88.c @@ -23,7 +23,7 @@ */ #include "sysbus.h" -#include "net.h" +#include "net/net.h" #include "flash.h" #include "boards.h" #include "etraxfs.h" diff --git a/hw/cadence_gem.c b/hw/cadence_gem.c index 0c037a2993..40a239973c 100644 --- a/hw/cadence_gem.c +++ b/hw/cadence_gem.c @@ -25,7 +25,7 @@ #include /* For crc32 */ #include "sysbus.h" -#include "net.h" +#include "net/net.h" #include "net/checksum.h" #ifdef CADENCE_GEM_ERR_DEBUG diff --git a/hw/dp8393x.c b/hw/dp8393x.c index 3f6386eee8..d59b6118ad 100644 --- a/hw/dp8393x.c +++ b/hw/dp8393x.c @@ -19,7 +19,7 @@ #include "hw.h" #include "qemu-timer.h" -#include "net.h" +#include "net/net.h" #include "mips.h" //#define DEBUG_SONIC diff --git a/hw/e1000.c b/hw/e1000.c index c89c8d22ab..aeee3e61f4 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -27,7 +27,7 @@ #include "hw.h" #include "pci/pci.h" -#include "net.h" +#include "net/net.h" #include "net/checksum.h" #include "loader.h" #include "sysemu.h" diff --git a/hw/eepro100.c b/hw/eepro100.c index 992f03ace7..9e2be4ea0d 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -43,7 +43,7 @@ #include /* offsetof */ #include "hw.h" #include "pci/pci.h" -#include "net.h" +#include "net/net.h" #include "eeprom93xx.h" #include "sysemu.h" #include "dma.h" diff --git a/hw/etraxfs.h b/hw/etraxfs.h index 725bb9e142..bc60713633 100644 --- a/hw/etraxfs.h +++ b/hw/etraxfs.h @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "net.h" +#include "net/net.h" #include "etraxfs_dma.h" qemu_irq *cris_pic_init_cpu(CPUCRISState *env); diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c index 3d42426823..289a810edc 100644 --- a/hw/etraxfs_eth.c +++ b/hw/etraxfs_eth.c @@ -24,7 +24,7 @@ #include #include "sysbus.h" -#include "net.h" +#include "net/net.h" #include "etraxfs.h" #define D(x) diff --git a/hw/exynos4_boards.c b/hw/exynos4_boards.c index bc815bbae3..c375f16479 100644 --- a/hw/exynos4_boards.c +++ b/hw/exynos4_boards.c @@ -23,7 +23,7 @@ #include "sysemu.h" #include "sysbus.h" -#include "net.h" +#include "net/net.h" #include "arm-misc.h" #include "exec-memory.h" #include "exynos4210.h" diff --git a/hw/gumstix.c b/hw/gumstix.c index 4103a88b80..545b92fd95 100644 --- a/hw/gumstix.c +++ b/hw/gumstix.c @@ -36,7 +36,7 @@ #include "hw.h" #include "pxa.h" -#include "net.h" +#include "net/net.h" #include "flash.h" #include "devices.h" #include "boards.h" diff --git a/hw/highbank.c b/hw/highbank.c index 8e35127c8a..90f7cb5ef2 100644 --- a/hw/highbank.c +++ b/hw/highbank.c @@ -21,7 +21,7 @@ #include "arm-misc.h" #include "devices.h" #include "loader.h" -#include "net.h" +#include "net/net.h" #include "sysemu.h" #include "boards.h" #include "sysbus.h" diff --git a/hw/integratorcp.c b/hw/integratorcp.c index 77807c39e3..2b59fea9f1 100644 --- a/hw/integratorcp.c +++ b/hw/integratorcp.c @@ -11,7 +11,7 @@ #include "devices.h" #include "boards.h" #include "arm-misc.h" -#include "net.h" +#include "net/net.h" #include "exec-memory.h" #include "sysemu.h" diff --git a/hw/kzm.c b/hw/kzm.c index 687daf3b2c..a27ecbba84 100644 --- a/hw/kzm.c +++ b/hw/kzm.c @@ -18,7 +18,7 @@ #include "hw.h" #include "arm-misc.h" #include "devices.h" -#include "net.h" +#include "net/net.h" #include "sysemu.h" #include "boards.h" #include "serial.h" diff --git a/hw/lan9118.c b/hw/lan9118.c index f724e1c301..4c72d0d98e 100644 --- a/hw/lan9118.c +++ b/hw/lan9118.c @@ -11,7 +11,7 @@ */ #include "sysbus.h" -#include "net.h" +#include "net/net.h" #include "devices.h" #include "sysemu.h" #include "ptimer.h" diff --git a/hw/lance.c b/hw/lance.c index a3e6dd91d5..a384676158 100644 --- a/hw/lance.c +++ b/hw/lance.c @@ -36,7 +36,7 @@ */ #include "sysbus.h" -#include "net.h" +#include "net/net.h" #include "qemu-timer.h" #include "qemu_socket.h" #include "sun4m.h" diff --git a/hw/mainstone.c b/hw/mainstone.c index 5bbecb7304..58c8b0748e 100644 --- a/hw/mainstone.c +++ b/hw/mainstone.c @@ -14,7 +14,7 @@ #include "hw.h" #include "pxa.h" #include "arm-misc.h" -#include "net.h" +#include "net/net.h" #include "devices.h" #include "boards.h" #include "flash.h" diff --git a/hw/mcf5208.c b/hw/mcf5208.c index b1db54937e..6326624111 100644 --- a/hw/mcf5208.c +++ b/hw/mcf5208.c @@ -10,7 +10,7 @@ #include "qemu-timer.h" #include "ptimer.h" #include "sysemu.h" -#include "net.h" +#include "net/net.h" #include "boards.h" #include "loader.h" #include "elf.h" diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c index 1ed193c5db..b5fb18f67f 100644 --- a/hw/mcf_fec.c +++ b/hw/mcf_fec.c @@ -6,7 +6,7 @@ * This code is licensed under the GPL */ #include "hw.h" -#include "net.h" +#include "net/net.h" #include "mcf.h" /* For crc32 */ #include diff --git a/hw/milkymist-hw.h b/hw/milkymist-hw.h index 0253b7ab26..812ddd2bd1 100644 --- a/hw/milkymist-hw.h +++ b/hw/milkymist-hw.h @@ -3,7 +3,7 @@ #include "qdev.h" #include "qdev-addr.h" -#include "net.h" +#include "net/net.h" static inline DeviceState *milkymist_uart_create(hwaddr base, qemu_irq irq) diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c index b204e5f890..926f7f9a8b 100644 --- a/hw/milkymist-minimac2.c +++ b/hw/milkymist-minimac2.c @@ -25,7 +25,7 @@ #include "hw.h" #include "sysbus.h" #include "trace.h" -#include "net.h" +#include "net/net.h" #include "qemu-error.h" #include "qdev-addr.h" diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c index d5cf33b4b6..bab96b27c1 100644 --- a/hw/mips_fulong2e.c +++ b/hw/mips_fulong2e.c @@ -22,7 +22,7 @@ #include "pc.h" #include "serial.h" #include "fdc.h" -#include "net.h" +#include "net/net.h" #include "boards.h" #include "smbus.h" #include "block.h" diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c index ea1416ae2f..8e5e8ef1af 100644 --- a/hw/mips_jazz.c +++ b/hw/mips_jazz.c @@ -32,7 +32,7 @@ #include "sysemu.h" #include "arch_init.h" #include "boards.h" -#include "net.h" +#include "net/net.h" #include "esp.h" #include "mips-bios.h" #include "loader.h" diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 571903dfc5..3f9f171385 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -26,7 +26,7 @@ #include "pc.h" #include "serial.h" #include "fdc.h" -#include "net.h" +#include "net/net.h" #include "boards.h" #include "smbus.h" #include "block.h" diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c index 20b5f1a58c..78317426a7 100644 --- a/hw/mips_mipssim.c +++ b/hw/mips_mipssim.c @@ -29,7 +29,7 @@ #include "mips_cpudevs.h" #include "serial.h" #include "isa.h" -#include "net.h" +#include "net/net.h" #include "sysemu.h" #include "boards.h" #include "mips-bios.h" diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index 325098a43a..ec99d7d6a6 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -13,7 +13,7 @@ #include "pc.h" #include "serial.h" #include "isa.h" -#include "net.h" +#include "net/net.h" #include "sysemu.h" #include "boards.h" #include "flash.h" diff --git a/hw/mipsnet.c b/hw/mipsnet.c index bece332c4e..bb752d3950 100644 --- a/hw/mipsnet.c +++ b/hw/mipsnet.c @@ -1,5 +1,5 @@ #include "hw.h" -#include "net.h" +#include "net/net.h" #include "trace.h" #include "sysbus.h" diff --git a/hw/musicpal.c b/hw/musicpal.c index e0c57c84eb..4e8399ab63 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -12,7 +12,7 @@ #include "sysbus.h" #include "arm-misc.h" #include "devices.h" -#include "net.h" +#include "net/net.h" #include "sysemu.h" #include "boards.h" #include "serial.h" diff --git a/hw/ne2000-isa.c b/hw/ne2000-isa.c index 69982a9abb..99477a412a 100644 --- a/hw/ne2000-isa.c +++ b/hw/ne2000-isa.c @@ -25,7 +25,7 @@ #include "pc.h" #include "isa.h" #include "qdev.h" -#include "net.h" +#include "net/net.h" #include "ne2000.h" #include "exec-memory.h" diff --git a/hw/ne2000.c b/hw/ne2000.c index fb78e5b252..2001264e14 100644 --- a/hw/ne2000.c +++ b/hw/ne2000.c @@ -23,7 +23,7 @@ */ #include "hw.h" #include "pci/pci.h" -#include "net.h" +#include "net/net.h" #include "ne2000.h" #include "loader.h" #include "sysemu.h" diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c index b2780b9334..fd2f0f61c3 100644 --- a/hw/opencores_eth.c +++ b/hw/opencores_eth.c @@ -33,7 +33,7 @@ #include "hw.h" #include "sysbus.h" -#include "net.h" +#include "net/net.h" #include "sysemu.h" #include "trace.h" diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c index 23c66df1fb..a879fb0dd0 100644 --- a/hw/openrisc_sim.c +++ b/hw/openrisc_sim.c @@ -22,7 +22,7 @@ #include "boards.h" #include "elf.h" #include "serial.h" -#include "net.h" +#include "net/net.h" #include "loader.h" #include "exec-memory.h" #include "sysemu.h" diff --git a/hw/pc.h b/hw/pc.h index 2237e86446..5e4d103813 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -6,7 +6,7 @@ #include "ioport.h" #include "isa.h" #include "fdc.h" -#include "net.h" +#include "net/net.h" #include "memory.h" #include "ioapic.h" diff --git a/hw/pc_piix.c b/hw/pc_piix.c index c2b4cb07e5..7268dcd944 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -30,7 +30,7 @@ #include "pci/pci.h" #include "pci/pci_ids.h" #include "usb.h" -#include "net.h" +#include "net/net.h" #include "boards.h" #include "ide.h" #include "kvm.h" diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug.c index 4b4c931c74..b850400252 100644 --- a/hw/pci/pci-hotplug.c +++ b/hw/pci/pci-hotplug.c @@ -25,7 +25,7 @@ #include "hw/hw.h" #include "hw/boards.h" #include "hw/pci/pci.h" -#include "net.h" +#include "net/net.h" #include "hw/pc.h" #include "monitor.h" #include "hw/scsi.h" diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 2e455e22d2..105fe9560e 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -26,7 +26,7 @@ #include "hw/pci/pci_bridge.h" #include "hw/pci/pci_bus.h" #include "monitor.h" -#include "net.h" +#include "net/net.h" #include "sysemu.h" #include "hw/loader.h" #include "range.h" diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c index c1abbf8d0d..c6768bcbdc 100644 --- a/hw/pcnet-pci.c +++ b/hw/pcnet-pci.c @@ -28,7 +28,7 @@ */ #include "pci/pci.h" -#include "net.h" +#include "net/net.h" #include "loader.h" #include "qemu-timer.h" #include "dma.h" diff --git a/hw/pcnet.c b/hw/pcnet.c index 54eecd01d3..5b03edecdd 100644 --- a/hw/pcnet.c +++ b/hw/pcnet.c @@ -36,7 +36,7 @@ */ #include "qdev.h" -#include "net.h" +#include "net/net.h" #include "qemu-timer.h" #include "qemu_socket.h" #include "sysemu.h" diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c index 3589a4bc7f..df51a74450 100644 --- a/hw/petalogix_ml605_mmu.c +++ b/hw/petalogix_ml605_mmu.c @@ -27,7 +27,7 @@ #include "sysbus.h" #include "hw.h" -#include "net.h" +#include "net/net.h" #include "flash.h" #include "sysemu.h" #include "devices.h" diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c index c5fd5e793a..37b0d5595a 100644 --- a/hw/petalogix_s3adsp1800_mmu.c +++ b/hw/petalogix_s3adsp1800_mmu.c @@ -25,7 +25,7 @@ #include "sysbus.h" #include "hw.h" -#include "net.h" +#include "net/net.h" #include "flash.h" #include "sysemu.h" #include "devices.h" diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 2b1558b16e..4690bd8b00 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -18,7 +18,7 @@ #include "qemu-common.h" #include "e500.h" #include "e500-ccsr.h" -#include "net.h" +#include "net/net.h" #include "qemu-config.h" #include "hw/hw.h" #include "hw/serial.h" diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c index 0b39a81ec5..5193a0c4be 100644 --- a/hw/ppc440_bamboo.c +++ b/hw/ppc440_bamboo.c @@ -13,7 +13,7 @@ #include "config.h" #include "qemu-common.h" -#include "net.h" +#include "net/net.h" #include "hw.h" #include "pci/pci.h" #include "boards.h" diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index 2bf3094e9f..657f405f1b 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -53,7 +53,7 @@ #include "mac_dbdma.h" #include "nvram.h" #include "pci/pci.h" -#include "net.h" +#include "net/net.h" #include "sysemu.h" #include "boards.h" #include "fw_cfg.h" diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index 3bc29c619c..a149306cc9 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -30,7 +30,7 @@ #include "mac_dbdma.h" #include "nvram.h" #include "sysemu.h" -#include "net.h" +#include "net/net.h" #include "isa.h" #include "pci/pci.h" #include "boards.h" diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index f6ffb593b7..25cc0490f9 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -26,7 +26,7 @@ #include "pc.h" #include "serial.h" #include "fdc.h" -#include "net.h" +#include "net/net.h" #include "sysemu.h" #include "isa.h" #include "pci/pci.h" diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index b9cd3c0077..7ab55efe43 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -1,4 +1,4 @@ -#include "net.h" +#include "net/net.h" #include "qdev.h" #include "qerror.h" #include "blockdev.h" diff --git a/hw/qdev.c b/hw/qdev.c index 599382cab2..6b91fb987b 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -25,7 +25,7 @@ inherit from a particular bus (e.g. PCI or I2C) rather than this API directly. */ -#include "net.h" +#include "net/net.h" #include "qdev.h" #include "sysemu.h" #include "error.h" diff --git a/hw/r2d.c b/hw/r2d.c index e18c23b28b..b1c278f73f 100644 --- a/hw/r2d.c +++ b/hw/r2d.c @@ -30,7 +30,7 @@ #include "sysemu.h" #include "boards.h" #include "pci/pci.h" -#include "net.h" +#include "net/net.h" #include "sh7750_regs.h" #include "ide.h" #include "loader.h" diff --git a/hw/realview.c b/hw/realview.c index 5fbdcbf2b0..17d1ba2266 100644 --- a/hw/realview.c +++ b/hw/realview.c @@ -12,7 +12,7 @@ #include "primecell.h" #include "devices.h" #include "pci/pci.h" -#include "net.h" +#include "net/net.h" #include "sysemu.h" #include "boards.h" #include "i2c.h" diff --git a/hw/rtl8139.c b/hw/rtl8139.c index e294a2a5e3..e024520b8b 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -55,7 +55,7 @@ #include "pci/pci.h" #include "dma.h" #include "qemu-timer.h" -#include "net.h" +#include "net/net.h" #include "loader.h" #include "sysemu.h" #include "iov.h" diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index 7aca0c4aad..8c724b942c 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -21,7 +21,7 @@ #include "block.h" #include "blockdev.h" #include "sysemu.h" -#include "net.h" +#include "net/net.h" #include "boards.h" #include "monitor.h" #include "loader.h" diff --git a/hw/smc91c111.c b/hw/smc91c111.c index 4ceed01a1a..2161b4af7a 100644 --- a/hw/smc91c111.c +++ b/hw/smc91c111.c @@ -8,7 +8,7 @@ */ #include "sysbus.h" -#include "net.h" +#include "net/net.h" #include "devices.h" /* For crc32 */ #include diff --git a/hw/spapr.c b/hw/spapr.c index 7306ab368a..395c4ac69b 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -27,7 +27,7 @@ #include "sysemu.h" #include "hw.h" #include "elf.h" -#include "net.h" +#include "net/net.h" #include "blockdev.h" #include "cpus.h" #include "kvm.h" diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c index 09ad69f6b5..8077eb94bc 100644 --- a/hw/spapr_llan.c +++ b/hw/spapr_llan.c @@ -25,7 +25,7 @@ * */ #include "hw.h" -#include "net.h" +#include "net/net.h" #include "hw/qdev.h" #include "hw/spapr.h" #include "hw/spapr_vio.h" diff --git a/hw/stellaris.c b/hw/stellaris.c index b038f10f3a..f3eb4bbc01 100644 --- a/hw/stellaris.c +++ b/hw/stellaris.c @@ -13,7 +13,7 @@ #include "devices.h" #include "qemu-timer.h" #include "i2c.h" -#include "net.h" +#include "net/net.h" #include "boards.h" #include "exec-memory.h" diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c index a530b10598..d7e1e21ff9 100644 --- a/hw/stellaris_enet.c +++ b/hw/stellaris_enet.c @@ -7,7 +7,7 @@ * This code is licensed under the GPL. */ #include "sysbus.h" -#include "net.h" +#include "net/net.h" #include //#define DEBUG_STELLARIS_ENET 1 diff --git a/hw/sun4m.c b/hw/sun4m.c index 52cf82b681..9a784dfd04 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -28,7 +28,7 @@ #include "sparc32_dma.h" #include "fdc.h" #include "sysemu.h" -#include "net.h" +#include "net/net.h" #include "boards.h" #include "firmware_abi.h" #include "esp.h" diff --git a/hw/sun4u.c b/hw/sun4u.c index 47bcf9382d..d9e752fe83 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -28,7 +28,7 @@ #include "serial.h" #include "nvram.h" #include "fdc.h" -#include "net.h" +#include "net/net.h" #include "qemu-timer.h" #include "sysemu.h" #include "boards.h" diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 0552e6f438..bf289ff5a6 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -26,7 +26,7 @@ #include "qemu-common.h" #include "hw/usb.h" #include "hw/usb/desc.h" -#include "net.h" +#include "net/net.h" #include "qemu-queue.h" #include "qemu-config.h" #include "sysemu.h" diff --git a/hw/versatilepb.c b/hw/versatilepb.c index f5a742b37f..af398d9cca 100644 --- a/hw/versatilepb.c +++ b/hw/versatilepb.c @@ -10,7 +10,7 @@ #include "sysbus.h" #include "arm-misc.h" #include "devices.h" -#include "net.h" +#include "net/net.h" #include "sysemu.h" #include "pci/pci.h" #include "i2c.h" diff --git a/hw/vexpress.c b/hw/vexpress.c index e89694c86e..5c9c08b991 100644 --- a/hw/vexpress.c +++ b/hw/vexpress.c @@ -25,7 +25,7 @@ #include "arm-misc.h" #include "primecell.h" #include "devices.h" -#include "net.h" +#include "net/net.h" #include "sysemu.h" #include "boards.h" #include "exec-memory.h" diff --git a/hw/vhost_net.c b/hw/vhost_net.c index 8241601539..93ad89a11c 100644 --- a/hw/vhost_net.c +++ b/hw/vhost_net.c @@ -13,7 +13,7 @@ * GNU GPL, version 2 or (at your option) any later version. */ -#include "net.h" +#include "net/net.h" #include "net/tap.h" #include "virtio-net.h" diff --git a/hw/vhost_net.h b/hw/vhost_net.h index a9db23423c..012aba4148 100644 --- a/hw/vhost_net.h +++ b/hw/vhost_net.h @@ -1,7 +1,7 @@ #ifndef VHOST_NET_H #define VHOST_NET_H -#include "net.h" +#include "net/net.h" struct vhost_net; typedef struct vhost_net VHostNetState; diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 108ce07cfc..dc7c6d6b56 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -13,7 +13,7 @@ #include "iov.h" #include "virtio.h" -#include "net.h" +#include "net/net.h" #include "net/checksum.h" #include "net/tap.h" #include "qemu-error.h" diff --git a/hw/virtio-net.h b/hw/virtio-net.h index 2566ea13ec..d46fb9840f 100644 --- a/hw/virtio-net.h +++ b/hw/virtio-net.h @@ -73,33 +73,6 @@ struct virtio_net_config uint16_t status; } QEMU_PACKED; -/* This is the first element of the scatter-gather list. If you don't - * specify GSO or CSUM features, you can simply ignore the header. */ -struct virtio_net_hdr -{ -#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 // Use csum_start, csum_offset -#define VIRTIO_NET_HDR_F_DATA_VALID 2 // Csum is valid - uint8_t flags; -#define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame -#define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO) -#define VIRTIO_NET_HDR_GSO_UDP 3 // GSO frame, IPv4 UDP (UFO) -#define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP -#define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set - uint8_t gso_type; - uint16_t hdr_len; - uint16_t gso_size; - uint16_t csum_start; - uint16_t csum_offset; -}; - -/* This is the version of the header to use when the MRG_RXBUF - * feature has been negotiated. */ -struct virtio_net_hdr_mrg_rxbuf -{ - struct virtio_net_hdr hdr; - uint16_t num_buffers; /* Number of merged rx buffers */ -}; - /* * Control virtqueue data structures * diff --git a/hw/virtio.h b/hw/virtio.h index 7c17f7ba0b..cdcb490733 100644 --- a/hw/virtio.h +++ b/hw/virtio.h @@ -15,7 +15,7 @@ #define _QEMU_VIRTIO_H #include "hw.h" -#include "net.h" +#include "net/net.h" #include "qdev.h" #include "sysemu.h" #include "event_notifier.h" diff --git a/hw/xen_backend.h b/hw/xen_backend.h index 3305630903..92ab501d37 100644 --- a/hw/xen_backend.h +++ b/hw/xen_backend.h @@ -3,7 +3,7 @@ #include "xen_common.h" #include "sysemu.h" -#include "net.h" +#include "net/net.h" /* ------------------------------------------------------------- */ diff --git a/hw/xen_nic.c b/hw/xen_nic.c index dadacb1fb5..dc12110dba 100644 --- a/hw/xen_nic.c +++ b/hw/xen_nic.c @@ -36,7 +36,7 @@ #include #include "hw.h" -#include "net.h" +#include "net/net.h" #include "net/checksum.h" #include "net/util.h" #include "xen_backend.h" diff --git a/hw/xgmac.c b/hw/xgmac.c index ec50c745d0..d0d510ed6a 100644 --- a/hw/xgmac.c +++ b/hw/xgmac.c @@ -27,7 +27,7 @@ #include "sysbus.h" #include "qemu-char.h" #include "qemu-log.h" -#include "net.h" +#include "net/net.h" #include "net/checksum.h" #ifdef DEBUG_XGMAC diff --git a/hw/xilinx.h b/hw/xilinx.h index 9323fd07c6..735f8e257d 100644 --- a/hw/xilinx.h +++ b/hw/xilinx.h @@ -1,6 +1,6 @@ #include "stream.h" #include "qemu-common.h" -#include "net.h" +#include "net/net.h" static inline DeviceState * xilinx_intc_create(hwaddr base, qemu_irq irq, int kind_of_intr) diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c index c859fde09e..35979e65c9 100644 --- a/hw/xilinx_axienet.c +++ b/hw/xilinx_axienet.c @@ -24,7 +24,7 @@ #include "sysbus.h" #include "qemu-log.h" -#include "net.h" +#include "net/net.h" #include "net/checksum.h" #include "stream.h" diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c index 13bd45613d..4de4a53a0b 100644 --- a/hw/xilinx_ethlite.c +++ b/hw/xilinx_ethlite.c @@ -24,7 +24,7 @@ #include "sysbus.h" #include "hw.h" -#include "net.h" +#include "net/net.h" #define D(x) #define R_TX_BUF0 0 diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c index 9ca22a4e7d..67adc52725 100644 --- a/hw/xilinx_zynq.c +++ b/hw/xilinx_zynq.c @@ -17,7 +17,7 @@ #include "sysbus.h" #include "arm-misc.h" -#include "net.h" +#include "net/net.h" #include "exec-memory.h" #include "sysemu.h" #include "boards.h" diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c index bc10d3161f..0399de777e 100644 --- a/hw/xtensa_lx60.c +++ b/hw/xtensa_lx60.c @@ -32,7 +32,7 @@ #include "memory.h" #include "exec-memory.h" #include "serial.h" -#include "net.h" +#include "net/net.h" #include "sysbus.h" #include "flash.h" #include "blockdev.h" diff --git a/net/checksum.h b/include/net/checksum.h similarity index 100% rename from net/checksum.h rename to include/net/checksum.h diff --git a/net.h b/include/net/net.h similarity index 98% rename from net.h rename to include/net/net.h index 1d0816bc0a..9ff9305d7a 100644 --- a/net.h +++ b/include/net/net.h @@ -147,6 +147,9 @@ void net_host_device_remove(Monitor *mon, const QDict *qdict); void netdev_add(QemuOpts *opts, Error **errp); int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret); +int net_hub_id_for_client(NetClientState *nc, int *id); +NetClientState *net_hub_port_find(int hub_id); + #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" #define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown" #define DEFAULT_BRIDGE_HELPER CONFIG_QEMU_HELPERDIR "/qemu-bridge-helper" diff --git a/net/queue.h b/include/net/queue.h similarity index 100% rename from net/queue.h rename to include/net/queue.h diff --git a/net/slirp.h b/include/net/slirp.h similarity index 100% rename from net/slirp.h rename to include/net/slirp.h diff --git a/include/net/tap.h b/include/net/tap.h new file mode 100644 index 0000000000..bb7efb5439 --- /dev/null +++ b/include/net/tap.h @@ -0,0 +1,67 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2009 Red Hat, Inc. + * + * 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. + */ + +#ifndef QEMU_NET_TAP_H +#define QEMU_NET_TAP_H + +#include "qemu-common.h" +#include "qapi-types.h" + +int tap_has_ufo(NetClientState *nc); +int tap_has_vnet_hdr(NetClientState *nc); +int tap_has_vnet_hdr_len(NetClientState *nc, int len); +void tap_using_vnet_hdr(NetClientState *nc, int using_vnet_hdr); +void tap_set_offload(NetClientState *nc, int csum, int tso4, int tso6, int ecn, int ufo); +void tap_set_vnet_hdr_len(NetClientState *nc, int len); + +int tap_get_fd(NetClientState *nc); + +struct vhost_net; +struct vhost_net *tap_get_vhost_net(NetClientState *nc); + +struct virtio_net_hdr +{ +#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 // Use csum_start, csum_offset +#define VIRTIO_NET_HDR_F_DATA_VALID 2 // Csum is valid + uint8_t flags; +#define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame +#define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO) +#define VIRTIO_NET_HDR_GSO_UDP 3 // GSO frame, IPv4 UDP (UFO) +#define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP +#define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set + uint8_t gso_type; + uint16_t hdr_len; + uint16_t gso_size; + uint16_t csum_start; + uint16_t csum_offset; +}; + +struct virtio_net_hdr_mrg_rxbuf +{ + struct virtio_net_hdr hdr; + uint16_t num_buffers; /* Number of merged rx buffers */ +}; + +#endif /* QEMU_NET_TAP_H */ diff --git a/monitor.c b/monitor.c index bd63768c27..37b9d20299 100644 --- a/monitor.c +++ b/monitor.c @@ -31,7 +31,7 @@ #include "hw/watchdog.h" #include "hw/loader.h" #include "gdbstub.h" -#include "net.h" +#include "net/net.h" #include "net/slirp.h" #include "qemu-char.h" #include "ui/qemu-spice.h" diff --git a/net/clients.h b/net/clients.h index c58cc6087c..77932942bd 100644 --- a/net/clients.h +++ b/net/clients.h @@ -24,7 +24,7 @@ #ifndef QEMU_NET_CLIENTS_H #define QEMU_NET_CLIENTS_H -#include "net.h" +#include "net/net.h" #include "qapi-types.h" int net_init_dump(const NetClientOptions *opts, const char *name, diff --git a/net/hub.c b/net/hub.c index be413012bb..8508ecf380 100644 --- a/net/hub.c +++ b/net/hub.c @@ -13,7 +13,7 @@ */ #include "monitor.h" -#include "net.h" +#include "net/net.h" #include "clients.h" #include "hub.h" #include "iov.h" diff --git a/net/hub.h b/net/hub.h index 4cbfdb128b..583ada89d8 100644 --- a/net/hub.h +++ b/net/hub.h @@ -20,8 +20,6 @@ NetClientState *net_hub_add_port(int hub_id, const char *name); NetClientState *net_hub_find_client_by_name(int hub_id, const char *name); void net_hub_info(Monitor *mon); -int net_hub_id_for_client(NetClientState *nc, int *id); void net_hub_check_clients(void); -NetClientState *net_hub_port_find(int hub_id); #endif /* NET_HUB_H */ diff --git a/net/net.c b/net/net.c index 7b1600f17c..a4395be140 100644 --- a/net/net.c +++ b/net/net.c @@ -23,10 +23,10 @@ */ #include "config-host.h" -#include "net.h" +#include "net/net.h" #include "clients.h" #include "hub.h" -#include "slirp.h" +#include "net/slirp.h" #include "util.h" #include "monitor.h" diff --git a/net/queue.c b/net/queue.c index 254f28013a..542c549b1a 100644 --- a/net/queue.c +++ b/net/queue.c @@ -23,7 +23,7 @@ #include "net/queue.h" #include "qemu-queue.h" -#include "net.h" +#include "net/net.h" /* The delivery handler may only return zero if it will call * qemu_net_queue_flush() when it determines that it is once again able diff --git a/net/slirp.c b/net/slirp.c index f117412bad..5a11ac5859 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -29,7 +29,7 @@ #include #include #endif -#include "net.h" +#include "net/net.h" #include "clients.h" #include "hub.h" #include "monitor.h" diff --git a/net/socket.c b/net/socket.c index cf309cd5b9..8430f1a161 100644 --- a/net/socket.c +++ b/net/socket.c @@ -23,7 +23,7 @@ */ #include "config-host.h" -#include "net.h" +#include "net/net.h" #include "clients.h" #include "monitor.h" #include "qemu-common.h" diff --git a/net/tap-aix.c b/net/tap-aix.c index f27c17729e..aff6c527e9 100644 --- a/net/tap-aix.c +++ b/net/tap-aix.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "net/tap.h" +#include "tap_int.h" #include int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required) diff --git a/net/tap-bsd.c b/net/tap-bsd.c index a3b717dd1c..a1c55ad3de 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "net/tap.h" +#include "tap_int.h" #include "qemu-common.h" #include "sysemu.h" #include "qemu-error.h" diff --git a/net/tap-haiku.c b/net/tap-haiku.c index 34739d1562..08cc034cee 100644 --- a/net/tap-haiku.c +++ b/net/tap-haiku.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "net/tap.h" +#include "tap_int.h" #include int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required) diff --git a/net/tap-linux.c b/net/tap-linux.c index 3eaedc40ad..3de7b3b6ce 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -23,8 +23,9 @@ * THE SOFTWARE. */ +#include "tap_int.h" +#include "tap-linux.h" #include "net/tap.h" -#include "net/tap-linux.h" #include #include diff --git a/net/tap-linux.h b/net/tap-linux.h index 659e98122b..cb2a6d480a 100644 --- a/net/tap-linux.h +++ b/net/tap-linux.h @@ -13,8 +13,8 @@ * GNU General Public License for more details. */ -#ifndef QEMU_TAP_H -#define QEMU_TAP_H +#ifndef QEMU_TAP_LINUX_H +#define QEMU_TAP_LINUX_H #include #ifdef __linux__ @@ -44,20 +44,4 @@ #define TUN_F_TSO_ECN 0x08 /* I can handle TSO with ECN bits. */ #define TUN_F_UFO 0x10 /* I can handle UFO packets */ -struct virtio_net_hdr -{ - uint8_t flags; - uint8_t gso_type; - uint16_t hdr_len; - uint16_t gso_size; - uint16_t csum_start; - uint16_t csum_offset; -}; - -struct virtio_net_hdr_mrg_rxbuf -{ - struct virtio_net_hdr hdr; - uint16_t num_buffers; /* Number of merged rx buffers */ -}; - #endif /* QEMU_TAP_H */ diff --git a/net/tap-solaris.c b/net/tap-solaris.c index 5d6ac42f24..f228fffb6d 100644 --- a/net/tap-solaris.c +++ b/net/tap-solaris.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "net/tap.h" +#include "tap_int.h" #include "sysemu.h" #include diff --git a/net/tap-win32.c b/net/tap-win32.c index f9bd74109c..e37d8ee458 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -26,11 +26,11 @@ * distribution); if not, see . */ -#include "tap.h" +#include "tap_int.h" #include "qemu-common.h" #include "clients.h" /* net_init_tap */ -#include "net.h" +#include "net/net.h" #include "sysemu.h" #include "qemu-error.h" #include diff --git a/net/tap.c b/net/tap.c index 5ff78934dc..f8cabc4f86 100644 --- a/net/tap.c +++ b/net/tap.c @@ -23,7 +23,7 @@ * THE SOFTWARE. */ -#include "tap.h" +#include "tap_int.h" #include "config-host.h" @@ -33,14 +33,14 @@ #include #include -#include "net.h" +#include "net/net.h" #include "clients.h" #include "monitor.h" #include "sysemu.h" #include "qemu-common.h" #include "qemu-error.h" -#include "net/tap-linux.h" +#include "net/tap.h" #include "hw/vhost_net.h" diff --git a/net/tap.h b/net/tap_int.h similarity index 77% rename from net/tap.h rename to net/tap_int.h index d44d83ae73..1dffe12a45 100644 --- a/net/tap.h +++ b/net/tap_int.h @@ -23,8 +23,8 @@ * THE SOFTWARE. */ -#ifndef QEMU_NET_TAP_H -#define QEMU_NET_TAP_H +#ifndef QEMU_TAP_H +#define QEMU_TAP_H #include "qemu-common.h" #include "qapi-types.h" @@ -36,13 +36,6 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen); -int tap_has_ufo(NetClientState *nc); -int tap_has_vnet_hdr(NetClientState *nc); -int tap_has_vnet_hdr_len(NetClientState *nc, int len); -void tap_using_vnet_hdr(NetClientState *nc, int using_vnet_hdr); -void tap_set_offload(NetClientState *nc, int csum, int tso4, int tso6, int ecn, int ufo); -void tap_set_vnet_hdr_len(NetClientState *nc, int len); - int tap_set_sndbuf(int fd, const NetdevTapOptions *tap); int tap_probe_vnet_hdr(int fd); int tap_probe_vnet_hdr_len(int fd, int len); @@ -50,9 +43,4 @@ int tap_probe_has_ufo(int fd); void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo); void tap_fd_set_vnet_hdr_len(int fd, int len); -int tap_get_fd(NetClientState *nc); - -struct vhost_net; -struct vhost_net *tap_get_vhost_net(NetClientState *nc); - -#endif /* QEMU_NET_TAP_H */ +#endif /* QEMU_TAP_H */ diff --git a/net/util.c b/net/util.c index 1e9afbc1ae..7e9507679d 100644 --- a/net/util.c +++ b/net/util.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "net/util.h" +#include "util.h" #include #include diff --git a/net/vde.c b/net/vde.c index cc5a07d65e..52d4f19fba 100644 --- a/net/vde.c +++ b/net/vde.c @@ -25,7 +25,7 @@ #include -#include "net.h" +#include "net/net.h" #include "clients.h" #include "qemu-common.h" #include "qemu-option.h" diff --git a/savevm.c b/savevm.c index f5886ce772..ae8787868f 100644 --- a/savevm.c +++ b/savevm.c @@ -72,7 +72,7 @@ #include "qemu-common.h" #include "hw/hw.h" #include "hw/qdev.h" -#include "net.h" +#include "net/net.h" #include "monitor.h" #include "sysemu.h" #include "qemu-timer.h" diff --git a/vl.c b/vl.c index 571a49b931..a7eeafc26e 100644 --- a/vl.c +++ b/vl.c @@ -127,7 +127,7 @@ int main(int argc, char **argv) #include "hw/qdev.h" #include "hw/loader.h" #include "bt-host.h" -#include "net.h" +#include "net/net.h" #include "net/slirp.h" #include "monitor.h" #include "console.h" From 2870dc3456c9c02debb63b0a99b3dcbbf74a1048 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 24 Oct 2012 11:26:49 +0200 Subject: [PATCH 2052/2270] qemu-ga: move qemu-ga files to qga/ Signed-off-by: Paolo Bonzini --- Makefile | 9 +++++---- Makefile.objs | 2 +- qga/Makefile.objs | 2 +- qemu-ga.c => qga/main.c | 0 qapi-schema-guest.json => qga/qapi-schema.json | 0 5 files changed, 7 insertions(+), 6 deletions(-) rename qemu-ga.c => qga/main.c (100%) rename qapi-schema-guest.json => qga/qapi-schema.json (100%) diff --git a/Makefile b/Makefile index 0c6ad1efe6..a0321dd7f0 100644 --- a/Makefile +++ b/Makefile @@ -200,13 +200,13 @@ endif qapi-py = $(SRC_PATH)/scripts/qapi.py $(SRC_PATH)/scripts/ordereddict.py qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h :\ -$(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) +$(SRC_PATH)/qga/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 qga/qapi-generated -p "qga-" < $<, " GEN $@") qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h :\ -$(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py) +$(SRC_PATH)/qga/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 qga/qapi-generated -p "qga-" < $<, " GEN $@") qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c :\ -$(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) +$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o qga/qapi-generated -p "qga-" < $<, " GEN $@") qapi-types.c qapi-types.h :\ @@ -222,7 +222,8 @@ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h) $(qga-obj-y) qemu-ga.o: $(QGALIB_GEN) -qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(oslib-obj-y) $(trace-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y) libqemustub.a +qemu-ga$(EXESUF): $(qga-obj-y) $(oslib-obj-y) $(trace-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y) libqemustub.a + $(call LINK, $^) clean: # avoid old build problems by removing potentially incorrect old files diff --git a/Makefile.objs b/Makefile.objs index 83092dc74b..fe78836fcb 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -222,7 +222,7 @@ universal-obj-y += $(qapi-obj-y) ###################################################################### # guest agent -qga-obj-y = qga/ qemu-ga.o module.o qemu-tool.o +qga-obj-y = qga/ module.o qemu-tool.o qga-obj-$(CONFIG_POSIX) += qemu-sockets.o qemu-option.o vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS) diff --git a/qga/Makefile.objs b/qga/Makefile.objs index cd3e13516c..b8d7cd0a43 100644 --- a/qga/Makefile.objs +++ b/qga/Makefile.objs @@ -1,4 +1,4 @@ -qga-obj-y = commands.o guest-agent-command-state.o +qga-obj-y = commands.o guest-agent-command-state.o main.o qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o diff --git a/qemu-ga.c b/qga/main.c similarity index 100% rename from qemu-ga.c rename to qga/main.c diff --git a/qapi-schema-guest.json b/qga/qapi-schema.json similarity index 100% rename from qapi-schema-guest.json rename to qga/qapi-schema.json From 28ecbaeecb139a214f019207402a35d7b58aec0f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Nov 2012 12:06:30 +0100 Subject: [PATCH 2053/2270] ui: move files to ui/ and include/ui/ Signed-off-by: Paolo Bonzini --- Makefile.objs | 4 +--- hmp.c | 2 +- hw/adb.c | 2 +- hw/ads7846.c | 2 +- hw/applesmc.c | 2 +- hw/blizzard.c | 4 ++-- hw/bt-hid.c | 2 +- hw/cirrus_vga.c | 2 +- hw/escc.c | 2 +- hw/exynos4210_fimd.c | 4 ++-- hw/framebuffer.c | 2 +- hw/g364fb.c | 4 ++-- hw/hid.c | 2 +- hw/hpet.c | 2 +- hw/jazz_led.c | 4 ++-- hw/kvm/pci-assign.c | 2 +- hw/lm832x.c | 2 +- hw/milkymist-softusb.c | 2 +- hw/milkymist-vgafb.c | 4 ++-- hw/msmouse.c | 6 +++--- hw/musicpal.c | 5 ++--- hw/nseries.c | 2 +- hw/omap_dss.c | 2 +- hw/omap_lcdc.c | 5 ++--- hw/omap_sx1.c | 2 +- hw/palm.c | 2 +- hw/pl110.c | 5 ++--- hw/ps2.c | 2 +- hw/puv3.c | 2 +- hw/pxa2xx_keypad.c | 2 +- hw/pxa2xx_lcd.c | 4 ++-- hw/qxl.h | 2 +- hw/sm501.c | 5 ++--- hw/spitz.c | 2 +- hw/ssd0303.c | 2 +- hw/ssd0323.c | 2 +- hw/stellaris_input.c | 2 +- hw/tc6393xb.c | 4 ++-- hw/tcx.c | 4 ++-- hw/tsc2005.c | 2 +- hw/tsc210x.c | 2 +- hw/twl92230.c | 2 +- hw/usb/dev-hid.c | 2 +- hw/usb/dev-storage.c | 2 +- hw/usb/dev-wacom.c | 2 +- hw/usb/host-stub.c | 2 +- hw/vga-isa-mm.c | 4 ++-- hw/vga-isa.c | 4 ++-- hw/vga-pci.c | 4 ++-- hw/vga.c | 4 ++-- hw/vmmouse.c | 2 +- hw/vmware_vga.c | 2 +- hw/xenfb.c | 2 +- hw/z2.c | 2 +- console.h => include/ui/console.h | 2 +- {hw => include/ui}/pixel_ops.h | 0 qemu-pixman.h => include/ui/qemu-pixman.h | 0 {ui => include/ui}/qemu-spice.h | 0 {ui => include/ui}/spice-display.h | 2 +- monitor.c | 2 +- qemu-char.c | 2 +- qemu-timer.c | 2 +- target-unicore32/helper.c | 2 +- ui/Makefile.objs | 2 +- ui/cocoa.m | 2 +- console.c => ui/console.c | 2 +- ui/curses.c | 2 +- cursor.c => ui/cursor.c | 2 +- cursor_hidden.xpm => ui/cursor_hidden.xpm | 0 cursor_left_ptr.xpm => ui/cursor_left_ptr.xpm | 0 input.c => ui/input.c | 2 +- qemu-pixman.c => ui/qemu-pixman.c | 2 +- qemu-x509.h => ui/qemu-x509.h | 0 ui/sdl.c | 2 +- ui/spice-core.c | 4 ++-- ui/spice-display.c | 6 +++--- ui/spice-input.c | 4 ++-- vgafont.h => ui/vgafont.h | 0 ui/vnc.h | 2 +- vl.c | 2 +- 80 files changed, 95 insertions(+), 101 deletions(-) rename console.h => include/ui/console.h (99%) rename {hw => include/ui}/pixel_ops.h (100%) rename qemu-pixman.h => include/ui/qemu-pixman.h (100%) rename {ui => include/ui}/qemu-spice.h (100%) rename {ui => include/ui}/spice-display.h (99%) rename console.c => ui/console.c (99%) rename cursor.c => ui/cursor.c (99%) rename cursor_hidden.xpm => ui/cursor_hidden.xpm (100%) rename cursor_left_ptr.xpm => ui/cursor_left_ptr.xpm (100%) rename input.c => ui/input.c (99%) rename qemu-pixman.c => ui/qemu-pixman.c (98%) rename qemu-x509.h => ui/qemu-x509.h (100%) rename vgafont.h => ui/vgafont.h (100%) diff --git a/Makefile.objs b/Makefile.objs index fe78836fcb..a637a4a8f0 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -68,8 +68,7 @@ endif common-obj-y = $(block-obj-y) blockdev.o blockdev-nbd.o block/ common-obj-y += net/ common-obj-y += qom/ -common-obj-y += readline.o console.o cursor.o -common-obj-y += qemu-pixman.o +common-obj-y += readline.o common-obj-y += $(oslib-obj-y) common-obj-$(CONFIG_WIN32) += os-win32.o common-obj-$(CONFIG_POSIX) += os-posix.o @@ -78,7 +77,6 @@ common-obj-$(CONFIG_LINUX) += fsdev/ extra-obj-$(CONFIG_LINUX) += fsdev/ common-obj-y += tcg-runtime.o host-utils.o main-loop.o -common-obj-y += input.o common-obj-y += buffered_file.o migration.o migration-tcp.o common-obj-y += qemu-char.o #aio.o common-obj-y += block-migration.o iohandler.o diff --git a/hmp.c b/hmp.c index 9b31e9f8a7..f235134bb6 100644 --- a/hmp.c +++ b/hmp.c @@ -21,7 +21,7 @@ #include "qmp-commands.h" #include "qemu_socket.h" #include "monitor.h" -#include "console.h" +#include "ui/console.h" static void hmp_handle_error(Monitor *mon, Error **errp) { diff --git a/hw/adb.c b/hw/adb.c index 3b547f0af7..cc8ad8e057 100644 --- a/hw/adb.c +++ b/hw/adb.c @@ -23,7 +23,7 @@ */ #include "hw.h" #include "adb.h" -#include "console.h" +#include "ui/console.h" /* debug ADB */ //#define DEBUG_ADB diff --git a/hw/ads7846.c b/hw/ads7846.c index 2ea9e55bb5..fa137e628e 100644 --- a/hw/ads7846.c +++ b/hw/ads7846.c @@ -11,7 +11,7 @@ */ #include "ssi.h" -#include "console.h" +#include "ui/console.h" typedef struct { SSISlave ssidev; diff --git a/hw/applesmc.c b/hw/applesmc.c index 8bedaad310..91e7cb3d5c 100644 --- a/hw/applesmc.c +++ b/hw/applesmc.c @@ -32,7 +32,7 @@ #include "hw.h" #include "isa.h" -#include "console.h" +#include "ui/console.h" #include "qemu-timer.h" /* #define DEBUG_SMC */ diff --git a/hw/blizzard.c b/hw/blizzard.c index 1b57eb5396..24bde32e5a 100644 --- a/hw/blizzard.c +++ b/hw/blizzard.c @@ -19,10 +19,10 @@ */ #include "qemu-common.h" -#include "console.h" +#include "ui/console.h" #include "devices.h" #include "vga_int.h" -#include "pixel_ops.h" +#include "ui/pixel_ops.h" typedef void (*blizzard_fn_t)(uint8_t *, const uint8_t *, unsigned int); diff --git a/hw/bt-hid.c b/hw/bt-hid.c index 8d7a3dae21..0ec0c013b0 100644 --- a/hw/bt-hid.c +++ b/hw/bt-hid.c @@ -20,7 +20,7 @@ #include "qemu-common.h" #include "qemu-timer.h" -#include "console.h" +#include "ui/console.h" #include "hid.h" #include "bt.h" diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index 7d021f2e1d..80510bc9af 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -28,7 +28,7 @@ */ #include "hw.h" #include "pci/pci.h" -#include "console.h" +#include "ui/console.h" #include "vga_int.h" #include "loader.h" diff --git a/hw/escc.c b/hw/escc.c index a356613b06..38e8164e44 100644 --- a/hw/escc.c +++ b/hw/escc.c @@ -26,7 +26,7 @@ #include "sysbus.h" #include "escc.h" #include "qemu-char.h" -#include "console.h" +#include "ui/console.h" #include "trace.h" /* diff --git a/hw/exynos4210_fimd.c b/hw/exynos4210_fimd.c index f2443ca4af..3ef0847271 100644 --- a/hw/exynos4210_fimd.c +++ b/hw/exynos4210_fimd.c @@ -25,8 +25,8 @@ #include "qemu-common.h" #include "cpu-all.h" #include "sysbus.h" -#include "console.h" -#include "pixel_ops.h" +#include "ui/console.h" +#include "ui/pixel_ops.h" #include "bswap.h" /* Debug messages configuration */ diff --git a/hw/framebuffer.c b/hw/framebuffer.c index fa0f7863c4..2a870961bc 100644 --- a/hw/framebuffer.c +++ b/hw/framebuffer.c @@ -18,7 +18,7 @@ */ #include "hw.h" -#include "console.h" +#include "ui/console.h" #include "framebuffer.h" /* Render an image from a shared memory framebuffer. */ diff --git a/hw/g364fb.c b/hw/g364fb.c index 8192baf1c8..b46a044607 100644 --- a/hw/g364fb.c +++ b/hw/g364fb.c @@ -18,8 +18,8 @@ */ #include "hw.h" -#include "console.h" -#include "pixel_ops.h" +#include "ui/console.h" +#include "ui/pixel_ops.h" #include "trace.h" #include "sysbus.h" diff --git a/hw/hid.c b/hw/hid.c index 03761ab8b8..7935998e83 100644 --- a/hw/hid.c +++ b/hw/hid.c @@ -23,7 +23,7 @@ * THE SOFTWARE. */ #include "hw.h" -#include "console.h" +#include "ui/console.h" #include "qemu-timer.h" #include "hid.h" diff --git a/hw/hpet.c b/hw/hpet.c index 50ac067ece..49e1b631b5 100644 --- a/hw/hpet.c +++ b/hw/hpet.c @@ -26,7 +26,7 @@ #include "hw.h" #include "pc.h" -#include "console.h" +#include "ui/console.h" #include "qemu-timer.h" #include "hpet_emul.h" #include "sysbus.h" diff --git a/hw/jazz_led.c b/hw/jazz_led.c index 09c77429e8..f4a040631e 100644 --- a/hw/jazz_led.c +++ b/hw/jazz_led.c @@ -23,8 +23,8 @@ */ #include "qemu-common.h" -#include "console.h" -#include "pixel_ops.h" +#include "ui/console.h" +#include "ui/pixel_ops.h" #include "trace.h" #include "sysbus.h" diff --git a/hw/kvm/pci-assign.c b/hw/kvm/pci-assign.c index 42291592e3..2629775589 100644 --- a/hw/kvm/pci-assign.c +++ b/hw/kvm/pci-assign.c @@ -29,7 +29,7 @@ #include "hw/hw.h" #include "hw/pc.h" #include "qemu-error.h" -#include "console.h" +#include "ui/console.h" #include "hw/loader.h" #include "monitor.h" #include "range.h" diff --git a/hw/lm832x.c b/hw/lm832x.c index 8e09f9bcc9..b14a089b32 100644 --- a/hw/lm832x.c +++ b/hw/lm832x.c @@ -21,7 +21,7 @@ #include "hw.h" #include "i2c.h" #include "qemu-timer.h" -#include "console.h" +#include "ui/console.h" typedef struct { I2CSlave i2c; diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c index b162b88db7..0743668d18 100644 --- a/hw/milkymist-softusb.c +++ b/hw/milkymist-softusb.c @@ -24,7 +24,7 @@ #include "hw.h" #include "sysbus.h" #include "trace.h" -#include "console.h" +#include "ui/console.h" #include "hid.h" #include "qemu-error.h" diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c index 833881cc6a..c3471315d3 100644 --- a/hw/milkymist-vgafb.c +++ b/hw/milkymist-vgafb.c @@ -25,9 +25,9 @@ #include "hw.h" #include "sysbus.h" #include "trace.h" -#include "console.h" +#include "ui/console.h" #include "framebuffer.h" -#include "pixel_ops.h" +#include "ui/pixel_ops.h" #include "qemu-error.h" #define BITS 8 diff --git a/hw/msmouse.c b/hw/msmouse.c index 9c492a4637..decb1a3b5d 100644 --- a/hw/msmouse.c +++ b/hw/msmouse.c @@ -22,9 +22,9 @@ * THE SOFTWARE. */ #include -#include "../qemu-common.h" -#include "../qemu-char.h" -#include "../console.h" +#include "qemu-common.h" +#include "qemu-char.h" +#include "ui/console.h" #include "msmouse.h" #define MSMOUSE_LO6(n) ((n) & 0x3f) diff --git a/hw/musicpal.c b/hw/musicpal.c index 4e8399ab63..d16cd141a2 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -20,10 +20,11 @@ #include "ptimer.h" #include "block.h" #include "flash.h" -#include "console.h" +#include "ui/console.h" #include "i2c.h" #include "blockdev.h" #include "exec-memory.h" +#include "ui/pixel_ops.h" #define MP_MISC_BASE 0x80002000 #define MP_MISC_SIZE 0x00001000 @@ -492,8 +493,6 @@ SET_LCD_PIXEL(8, uint8_t) SET_LCD_PIXEL(16, uint16_t) SET_LCD_PIXEL(32, uint32_t) -#include "pixel_ops.h" - static void lcd_refresh(void *opaque) { musicpal_lcd_state *s = opaque; diff --git a/hw/nseries.c b/hw/nseries.c index 2de8d21f08..dcd3dc97d0 100644 --- a/hw/nseries.c +++ b/hw/nseries.c @@ -23,7 +23,7 @@ #include "omap.h" #include "arm-misc.h" #include "irq.h" -#include "console.h" +#include "ui/console.h" #include "boards.h" #include "i2c.h" #include "devices.h" diff --git a/hw/omap_dss.c b/hw/omap_dss.c index 1e83726d3b..ae51bdfe41 100644 --- a/hw/omap_dss.c +++ b/hw/omap_dss.c @@ -18,7 +18,7 @@ * with this program; if not, see . */ #include "hw.h" -#include "console.h" +#include "ui/console.h" #include "omap.h" struct omap_dss_s { diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c index d7ae3032be..936850a621 100644 --- a/hw/omap_lcdc.c +++ b/hw/omap_lcdc.c @@ -17,9 +17,10 @@ * with this program; if not, see . */ #include "hw.h" -#include "console.h" +#include "ui/console.h" #include "omap.h" #include "framebuffer.h" +#include "ui/pixel_ops.h" struct omap_lcd_panel_s { MemoryRegion *sysmem; @@ -66,8 +67,6 @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s) qemu_irq_lower(s->irq); } -#include "pixel_ops.h" - #define draw_line_func drawfn #define DEPTH 8 diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c index 21a5bbb006..918a6f6a04 100644 --- a/hw/omap_sx1.c +++ b/hw/omap_sx1.c @@ -26,7 +26,7 @@ * with this program; if not, see . */ #include "hw.h" -#include "console.h" +#include "ui/console.h" #include "omap.h" #include "boards.h" #include "arm-misc.h" diff --git a/hw/palm.c b/hw/palm.c index 6f6f414e6e..5aaeb07460 100644 --- a/hw/palm.c +++ b/hw/palm.c @@ -19,7 +19,7 @@ #include "hw.h" #include "audio/audio.h" #include "sysemu.h" -#include "console.h" +#include "ui/console.h" #include "omap.h" #include "boards.h" #include "arm-misc.h" diff --git a/hw/pl110.c b/hw/pl110.c index f869ba60d7..098e335aea 100644 --- a/hw/pl110.c +++ b/hw/pl110.c @@ -8,8 +8,9 @@ */ #include "sysbus.h" -#include "console.h" +#include "ui/console.h" #include "framebuffer.h" +#include "ui/pixel_ops.h" #define PL110_CR_EN 0x001 #define PL110_CR_BGR 0x100 @@ -109,8 +110,6 @@ static const unsigned char *idregs[] = { pl111_id }; -#include "pixel_ops.h" - #define BITS 8 #include "pl110_template.h" #define BITS 15 diff --git a/hw/ps2.c b/hw/ps2.c index f93cd24d94..ba80089aba 100644 --- a/hw/ps2.c +++ b/hw/ps2.c @@ -23,7 +23,7 @@ */ #include "hw.h" #include "ps2.h" -#include "console.h" +#include "ui/console.h" #include "sysemu.h" /* debug PC keyboard */ diff --git a/hw/puv3.c b/hw/puv3.c index 6f89c44e32..9f8e294ad5 100644 --- a/hw/puv3.c +++ b/hw/puv3.c @@ -10,7 +10,7 @@ */ #include "qemu-common.h" -#include "console.h" +#include "ui/console.h" #include "elf.h" #include "exec-memory.h" #include "sysbus.h" diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c index 257984c427..4ff04ad63b 100644 --- a/hw/pxa2xx_keypad.c +++ b/hw/pxa2xx_keypad.c @@ -13,7 +13,7 @@ #include "hw.h" #include "pxa.h" -#include "console.h" +#include "ui/console.h" /* * Keypad diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c index b53dfaf3cf..b5efd4d426 100644 --- a/hw/pxa2xx_lcd.c +++ b/hw/pxa2xx_lcd.c @@ -11,9 +11,9 @@ */ #include "hw.h" -#include "console.h" +#include "ui/console.h" #include "pxa.h" -#include "pixel_ops.h" +#include "ui/pixel_ops.h" /* FIXME: For graphic_rotate. Should probably be done in common code. */ #include "sysemu.h" #include "framebuffer.h" diff --git a/hw/qxl.h b/hw/qxl.h index 41246c7554..8433d1aeea 100644 --- a/hw/qxl.h +++ b/hw/qxl.h @@ -1,6 +1,6 @@ #include "qemu-common.h" -#include "console.h" +#include "ui/console.h" #include "hw.h" #include "pci/pci.h" #include "vga_int.h" diff --git a/hw/sm501.c b/hw/sm501.c index 50324cda53..714aca0492 100644 --- a/hw/sm501.c +++ b/hw/sm501.c @@ -25,11 +25,12 @@ #include #include "hw.h" #include "serial.h" -#include "console.h" +#include "ui/console.h" #include "devices.h" #include "sysbus.h" #include "qdev-addr.h" #include "range.h" +#include "ui/pixel_ops.h" /* * Status: 2010/05/07 @@ -1163,8 +1164,6 @@ static const MemoryRegionOps sm501_2d_engine_ops = { /* draw line functions for all console modes */ -#include "pixel_ops.h" - typedef void draw_line_func(uint8_t *d, const uint8_t *s, int width, const uint32_t *pal); diff --git a/hw/spitz.c b/hw/spitz.c index 12e2815221..d4575d20bf 100644 --- a/hw/spitz.c +++ b/hw/spitz.c @@ -21,7 +21,7 @@ #include "qemu-timer.h" #include "devices.h" #include "sharpsl.h" -#include "console.h" +#include "ui/console.h" #include "block.h" #include "audio/audio.h" #include "boards.h" diff --git a/hw/ssd0303.c b/hw/ssd0303.c index d7fd828c65..cbdf49af57 100644 --- a/hw/ssd0303.c +++ b/hw/ssd0303.c @@ -11,7 +11,7 @@ implement one. Most of the commends relating to brightness and geometry setup are ignored. */ #include "i2c.h" -#include "console.h" +#include "ui/console.h" //#define DEBUG_SSD0303 1 diff --git a/hw/ssd0323.c b/hw/ssd0323.c index 4098830c2b..fe6f801ae7 100644 --- a/hw/ssd0323.c +++ b/hw/ssd0323.c @@ -11,7 +11,7 @@ implement one. Most of the commends relating to brightness and geometry setup are ignored. */ #include "ssi.h" -#include "console.h" +#include "ui/console.h" //#define DEBUG_SSD0323 1 diff --git a/hw/stellaris_input.c b/hw/stellaris_input.c index 68c600c04c..7a95c3fc88 100644 --- a/hw/stellaris_input.c +++ b/hw/stellaris_input.c @@ -8,7 +8,7 @@ */ #include "hw.h" #include "devices.h" -#include "console.h" +#include "ui/console.h" typedef struct { qemu_irq irq; diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c index f0320271d4..edf76817b5 100644 --- a/hw/tc6393xb.c +++ b/hw/tc6393xb.c @@ -13,8 +13,8 @@ #include "hw.h" #include "devices.h" #include "flash.h" -#include "console.h" -#include "pixel_ops.h" +#include "ui/console.h" +#include "ui/pixel_ops.h" #include "blockdev.h" #define IRQ_TC6393_NAND 0 diff --git a/hw/tcx.c b/hw/tcx.c index a66fbeefdb..185588b49c 100644 --- a/hw/tcx.c +++ b/hw/tcx.c @@ -23,8 +23,8 @@ */ #include "qemu-common.h" -#include "console.h" -#include "pixel_ops.h" +#include "ui/console.h" +#include "ui/pixel_ops.h" #include "sysbus.h" #include "qdev-addr.h" diff --git a/hw/tsc2005.c b/hw/tsc2005.c index 9a500ebb3d..e2326283c0 100644 --- a/hw/tsc2005.c +++ b/hw/tsc2005.c @@ -20,7 +20,7 @@ #include "hw.h" #include "qemu-timer.h" -#include "console.h" +#include "ui/console.h" #include "devices.h" #define TSC_CUT_RESOLUTION(value, p) ((value) >> (16 - (p ? 12 : 10))) diff --git a/hw/tsc210x.c b/hw/tsc210x.c index 3c448a6f0f..2b3535d4fc 100644 --- a/hw/tsc210x.c +++ b/hw/tsc210x.c @@ -22,7 +22,7 @@ #include "hw.h" #include "audio/audio.h" #include "qemu-timer.h" -#include "console.h" +#include "ui/console.h" #include "omap.h" /* For I2SCodec and uWireSlave */ #include "devices.h" diff --git a/hw/twl92230.c b/hw/twl92230.c index 0d70d8498d..ce699bdbdd 100644 --- a/hw/twl92230.c +++ b/hw/twl92230.c @@ -23,7 +23,7 @@ #include "qemu-timer.h" #include "i2c.h" #include "sysemu.h" -#include "console.h" +#include "ui/console.h" #define VERBOSE 1 diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c index 87491284a8..6953f2e710 100644 --- a/hw/usb/dev-hid.c +++ b/hw/usb/dev-hid.c @@ -23,7 +23,7 @@ * THE SOFTWARE. */ #include "hw/hw.h" -#include "console.h" +#include "ui/console.h" #include "hw/usb.h" #include "hw/usb/desc.h" #include "qemu-timer.h" diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 50af97109b..de56fea610 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -13,7 +13,7 @@ #include "hw/usb.h" #include "hw/usb/desc.h" #include "hw/scsi.h" -#include "console.h" +#include "ui/console.h" #include "monitor.h" #include "sysemu.h" #include "blockdev.h" diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c index f7342b08c3..9ab368a6c5 100644 --- a/hw/usb/dev-wacom.c +++ b/hw/usb/dev-wacom.c @@ -26,7 +26,7 @@ * THE SOFTWARE. */ #include "hw/hw.h" -#include "console.h" +#include "ui/console.h" #include "hw/usb.h" #include "hw/usb/desc.h" diff --git a/hw/usb/host-stub.c b/hw/usb/host-stub.c index b4e10c12ca..e8da3221f6 100644 --- a/hw/usb/host-stub.c +++ b/hw/usb/host-stub.c @@ -31,7 +31,7 @@ */ #include "qemu-common.h" -#include "console.h" +#include "ui/console.h" #include "hw/usb.h" #include "monitor.h" diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c index 8ef4320d05..008703ff57 100644 --- a/hw/vga-isa-mm.c +++ b/hw/vga-isa-mm.c @@ -22,10 +22,10 @@ * THE SOFTWARE. */ #include "hw.h" -#include "console.h" +#include "ui/console.h" #include "pc.h" #include "vga_int.h" -#include "pixel_ops.h" +#include "ui/pixel_ops.h" #include "qemu-timer.h" #define VGA_RAM_SIZE (8192 * 1024) diff --git a/hw/vga-isa.c b/hw/vga-isa.c index 046602b3d2..d1d5b11828 100644 --- a/hw/vga-isa.c +++ b/hw/vga-isa.c @@ -24,10 +24,10 @@ * THE SOFTWARE. */ #include "hw.h" -#include "console.h" +#include "ui/console.h" #include "pc.h" #include "vga_int.h" -#include "pixel_ops.h" +#include "ui/pixel_ops.h" #include "qemu-timer.h" #include "loader.h" diff --git a/hw/vga-pci.c b/hw/vga-pci.c index 0cb318eab6..fe3a3d4899 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -24,10 +24,10 @@ * THE SOFTWARE. */ #include "hw.h" -#include "console.h" +#include "ui/console.h" #include "pci/pci.h" #include "vga_int.h" -#include "pixel_ops.h" +#include "ui/pixel_ops.h" #include "qemu-timer.h" #include "loader.h" diff --git a/hw/vga.c b/hw/vga.c index ab40d73100..4007116859 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -23,11 +23,11 @@ */ #include "hw.h" #include "vga.h" -#include "console.h" +#include "ui/console.h" #include "pc.h" #include "pci/pci.h" #include "vga_int.h" -#include "pixel_ops.h" +#include "ui/pixel_ops.h" #include "qemu-timer.h" #include "xen.h" #include "trace.h" diff --git a/hw/vmmouse.c b/hw/vmmouse.c index 6338efa1c3..d052f33f56 100644 --- a/hw/vmmouse.c +++ b/hw/vmmouse.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "hw.h" -#include "console.h" +#include "ui/console.h" #include "ps2.h" #include "pc.h" #include "qdev.h" diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 333ec8cebe..b0e772f863 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -23,7 +23,7 @@ */ #include "hw.h" #include "loader.h" -#include "console.h" +#include "ui/console.h" #include "pci/pci.h" #undef VERBOSE diff --git a/hw/xenfb.c b/hw/xenfb.c index 442a63a320..b1122bd933 100644 --- a/hw/xenfb.c +++ b/hw/xenfb.c @@ -36,7 +36,7 @@ #include #include "hw.h" -#include "console.h" +#include "ui/console.h" #include "qemu-char.h" #include "xen_backend.h" diff --git a/hw/z2.c b/hw/z2.c index f62b8067bf..d46186430f 100644 --- a/hw/z2.c +++ b/hw/z2.c @@ -21,7 +21,7 @@ #include "sysemu.h" #include "flash.h" #include "blockdev.h" -#include "console.h" +#include "ui/console.h" #include "audio/audio.h" #include "exec-memory.h" diff --git a/console.h b/include/ui/console.h similarity index 99% rename from console.h rename to include/ui/console.h index 33354e437a..777881d4a3 100644 --- a/console.h +++ b/include/ui/console.h @@ -1,7 +1,7 @@ #ifndef CONSOLE_H #define CONSOLE_H -#include "qemu-pixman.h" +#include "ui/qemu-pixman.h" #include "qdict.h" #include "notify.h" #include "monitor.h" diff --git a/hw/pixel_ops.h b/include/ui/pixel_ops.h similarity index 100% rename from hw/pixel_ops.h rename to include/ui/pixel_ops.h diff --git a/qemu-pixman.h b/include/ui/qemu-pixman.h similarity index 100% rename from qemu-pixman.h rename to include/ui/qemu-pixman.h diff --git a/ui/qemu-spice.h b/include/ui/qemu-spice.h similarity index 100% rename from ui/qemu-spice.h rename to include/ui/qemu-spice.h diff --git a/ui/spice-display.h b/include/ui/spice-display.h similarity index 99% rename from ui/spice-display.h rename to include/ui/spice-display.h index 38b6ea98b3..928e0a1bae 100644 --- a/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -20,7 +20,7 @@ #include #include "qemu-thread.h" -#include "qemu-pixman.h" +#include "ui/qemu-pixman.h" #include "sysemu.h" #define NUM_MEMSLOTS 8 diff --git a/monitor.c b/monitor.c index 37b9d20299..6546f8c30b 100644 --- a/monitor.c +++ b/monitor.c @@ -38,7 +38,7 @@ #include "sysemu.h" #include "monitor.h" #include "readline.h" -#include "console.h" +#include "ui/console.h" #include "blockdev.h" #include "audio/audio.h" #include "disas/disas.h" diff --git a/qemu-char.c b/qemu-char.c index f066ad0654..bc53d09a9b 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -23,7 +23,7 @@ */ #include "qemu-common.h" #include "monitor.h" -#include "console.h" +#include "ui/console.h" #include "sysemu.h" #include "qemu-timer.h" #include "qemu-char.h" diff --git a/qemu-timer.c b/qemu-timer.c index 9b9585b259..5a99403fda 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -24,7 +24,7 @@ #include "sysemu.h" #include "monitor.h" -#include "console.h" +#include "ui/console.h" #include "hw/hw.h" diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c index a9e226bde4..4b6856137d 100644 --- a/target-unicore32/helper.c +++ b/target-unicore32/helper.c @@ -13,7 +13,7 @@ #include "gdbstub.h" #include "helper.h" #include "host-utils.h" -#include "console.h" +#include "ui/console.h" #undef DEBUG_UC32 diff --git a/ui/Makefile.objs b/ui/Makefile.objs index fd339d247b..dc8f0e46ad 100644 --- a/ui/Makefile.objs +++ b/ui/Makefile.objs @@ -6,7 +6,7 @@ vnc-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o vnc-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o vnc-obj-y += vnc-jobs.o -common-obj-y += keymaps.o +common-obj-y += keymaps.o console.o cursor.o input.o qemu-pixman.o common-obj-$(CONFIG_SPICE) += spice-core.o spice-input.o spice-display.o common-obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o common-obj-$(CONFIG_COCOA) += cocoa.o diff --git a/ui/cocoa.m b/ui/cocoa.m index 87d2e44c69..0afa6f86dd 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -26,7 +26,7 @@ #include #include "qemu-common.h" -#include "console.h" +#include "ui/console.h" #include "sysemu.h" #ifndef MAC_OS_X_VERSION_10_4 diff --git a/console.c b/ui/console.c similarity index 99% rename from console.c rename to ui/console.c index 9ac7b28742..60bfb72ac2 100644 --- a/console.c +++ b/ui/console.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "console.h" +#include "ui/console.h" #include "qemu-timer.h" #include "qmp-commands.h" #include "qemu-char.h" diff --git a/ui/curses.c b/ui/curses.c index 5dc0b2c95f..5d15e9e16e 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -29,7 +29,7 @@ #endif #include "qemu-common.h" -#include "console.h" +#include "ui/console.h" #include "sysemu.h" #define FONT_HEIGHT 16 diff --git a/cursor.c b/ui/cursor.c similarity index 99% rename from cursor.c rename to ui/cursor.c index 76e262caf7..2b8dd3fa50 100644 --- a/cursor.c +++ b/ui/cursor.c @@ -1,5 +1,5 @@ #include "qemu-common.h" -#include "console.h" +#include "ui/console.h" #include "cursor_hidden.xpm" #include "cursor_left_ptr.xpm" diff --git a/cursor_hidden.xpm b/ui/cursor_hidden.xpm similarity index 100% rename from cursor_hidden.xpm rename to ui/cursor_hidden.xpm diff --git a/cursor_left_ptr.xpm b/ui/cursor_left_ptr.xpm similarity index 100% rename from cursor_left_ptr.xpm rename to ui/cursor_left_ptr.xpm diff --git a/input.c b/ui/input.c similarity index 99% rename from input.c rename to ui/input.c index 123bb237d4..58d3b4709c 100644 --- a/input.c +++ b/ui/input.c @@ -24,7 +24,7 @@ #include "sysemu.h" #include "monitor.h" -#include "console.h" +#include "ui/console.h" #include "error.h" #include "qmp-commands.h" #include "qapi-types.h" diff --git a/qemu-pixman.c b/ui/qemu-pixman.c similarity index 98% rename from qemu-pixman.c rename to ui/qemu-pixman.c index e7263fb2bf..609335ab11 100644 --- a/qemu-pixman.c +++ b/ui/qemu-pixman.c @@ -3,7 +3,7 @@ * See the COPYING file in the top-level directory. */ -#include "qemu-pixman.h" +#include "ui/qemu-pixman.h" int qemu_pixman_get_type(int rshift, int gshift, int bshift) { diff --git a/qemu-x509.h b/ui/qemu-x509.h similarity index 100% rename from qemu-x509.h rename to ui/qemu-x509.h diff --git a/ui/sdl.c b/ui/sdl.c index 37f01b217d..bcbf89daeb 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -29,7 +29,7 @@ #include #include "qemu-common.h" -#include "console.h" +#include "ui/console.h" #include "sysemu.h" #include "x_keymap.h" #include "sdl_zoom.h" diff --git a/ui/spice-core.c b/ui/spice-core.c index 261c6f2c11..ec925ecbb0 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -22,7 +22,7 @@ #include "sysemu.h" #include "qemu-common.h" -#include "qemu-spice.h" +#include "ui/qemu-spice.h" #include "qemu-thread.h" #include "qemu-timer.h" #include "qemu-queue.h" @@ -37,7 +37,7 @@ #include "migration.h" #include "monitor.h" #include "hw/hw.h" -#include "spice-display.h" +#include "ui/spice-display.h" /* core bits */ diff --git a/ui/spice-display.c b/ui/spice-display.c index 6aff3368ca..681fe32fed 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -16,15 +16,15 @@ */ #include "qemu-common.h" -#include "qemu-spice.h" +#include "ui/qemu-spice.h" #include "qemu-timer.h" #include "qemu-queue.h" #include "monitor.h" -#include "console.h" +#include "ui/console.h" #include "sysemu.h" #include "trace.h" -#include "spice-display.h" +#include "ui/spice-display.h" static int debug = 0; diff --git a/ui/spice-input.c b/ui/spice-input.c index af4223d442..3beb8deadb 100644 --- a/ui/spice-input.c +++ b/ui/spice-input.c @@ -24,8 +24,8 @@ #include #include "qemu-common.h" -#include "qemu-spice.h" -#include "console.h" +#include "ui/qemu-spice.h" +#include "ui/console.h" /* keyboard bits */ diff --git a/vgafont.h b/ui/vgafont.h similarity index 100% rename from vgafont.h rename to ui/vgafont.h diff --git a/ui/vnc.h b/ui/vnc.h index 6141e88b4e..7ec183372a 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -30,7 +30,7 @@ #include "qemu-common.h" #include "qemu-queue.h" #include "qemu-thread.h" -#include "console.h" +#include "ui/console.h" #include "monitor.h" #include "audio/audio.h" #include "bitmap.h" diff --git a/vl.c b/vl.c index a7eeafc26e..6713220905 100644 --- a/vl.c +++ b/vl.c @@ -130,7 +130,7 @@ int main(int argc, char **argv) #include "net/net.h" #include "net/slirp.h" #include "monitor.h" -#include "console.h" +#include "ui/console.h" #include "sysemu.h" #include "gdbstub.h" #include "qemu-timer.h" From 79ee7df8853c5d7085d87036420b6b388dda2595 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Dec 2012 11:22:34 +0100 Subject: [PATCH 2054/2270] qapi: move inclusions of qemu-common.h from headers to .c files Signed-off-by: Paolo Bonzini --- qapi/opts-visitor.c | 1 + qapi/qapi-types-core.h | 1 - qapi/qapi-visit-core.c | 1 + qemu-error.h | 2 ++ scripts/qapi-commands.py | 1 + scripts/qapi-visit.py | 1 + tests/test-qmp-commands.c | 1 + tests/test-qmp-input-strict.c | 1 + tests/test-qmp-input-visitor.c | 1 + tests/test-qmp-output-visitor.c | 1 + tests/test-string-input-visitor.c | 1 + tests/test-string-output-visitor.c | 1 + tests/test-visitor-serialization.c | 2 ++ 13 files changed, 14 insertions(+), 1 deletion(-) diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index e048b6c863..e3fd25446d 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -10,6 +10,7 @@ * */ +#include "qemu-common.h" #include "opts-visitor.h" #include "qemu-queue.h" #include "qemu-option-internal.h" diff --git a/qapi/qapi-types-core.h b/qapi/qapi-types-core.h index f781fc3ab7..831df21ea7 100644 --- a/qapi/qapi-types-core.h +++ b/qapi/qapi-types-core.h @@ -14,7 +14,6 @@ #ifndef QAPI_TYPES_CORE_H #define QAPI_TYPES_CORE_H -#include "qemu-common.h" #include "error.h" #include "qerror.h" diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index 7a82b63766..300293999d 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -11,6 +11,7 @@ * */ +#include "qemu-common.h" #include "qapi/qapi-visit-core.h" #include "qapi/qapi-visit-impl.h" diff --git a/qemu-error.h b/qemu-error.h index 93d74b4a30..c902cc10de 100644 --- a/qemu-error.h +++ b/qemu-error.h @@ -13,6 +13,8 @@ #ifndef QEMU_ERROR_H #define QEMU_ERROR_H +#include + typedef struct Location { /* all members are private to qemu-error.c */ enum { LOC_NONE, LOC_CMDLINE, LOC_FILE } kind; diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index 3c4678dbf1..2db0bf1e56 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -366,6 +366,7 @@ def gen_command_def_prologue(prefix="", proxy=False): * */ +#include "qemu-common.h" #include "qemu-objects.h" #include "qapi/qmp-core.h" #include "qapi/qapi-visit-core.h" diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index a360de719f..f1aabb3813 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -298,6 +298,7 @@ fdef.write(mcgen(''' * */ +#include "qemu-common.h" #include "%(header)s" ''', header=basename(h_file))) diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c index dc3c507f2b..bf41034c62 100644 --- a/tests/test-qmp-commands.c +++ b/tests/test-qmp-commands.c @@ -1,4 +1,5 @@ #include +#include "qemu-common.h" #include "qemu-objects.h" #include "test-qmp-commands.h" #include "qapi/qmp-core.h" diff --git a/tests/test-qmp-input-strict.c b/tests/test-qmp-input-strict.c index f6df8cbe1e..86f24d821c 100644 --- a/tests/test-qmp-input-strict.c +++ b/tests/test-qmp-input-strict.c @@ -14,6 +14,7 @@ #include #include +#include "qemu-common.h" #include "qapi/qmp-input-visitor.h" #include "test-qapi-types.h" #include "test-qapi-visit.h" diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c index 8f5a509582..6568c9907c 100644 --- a/tests/test-qmp-input-visitor.c +++ b/tests/test-qmp-input-visitor.c @@ -13,6 +13,7 @@ #include #include +#include "qemu-common.h" #include "qapi/qmp-input-visitor.h" #include "test-qapi-types.h" #include "test-qapi-visit.h" diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c index 24a6359504..84b1f41894 100644 --- a/tests/test-qmp-output-visitor.c +++ b/tests/test-qmp-output-visitor.c @@ -12,6 +12,7 @@ #include +#include "qemu-common.h" #include "qapi/qmp-output-visitor.h" #include "test-qapi-types.h" #include "test-qapi-visit.h" diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-visitor.c index 5370e32041..36b3792980 100644 --- a/tests/test-string-input-visitor.c +++ b/tests/test-string-input-visitor.c @@ -13,6 +13,7 @@ #include #include +#include "qemu-common.h" #include "qapi/string-input-visitor.h" #include "test-qapi-types.h" #include "test-qapi-visit.h" diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c index 608f14a5de..afb557a00f 100644 --- a/tests/test-string-output-visitor.c +++ b/tests/test-string-output-visitor.c @@ -12,6 +12,7 @@ #include +#include "qemu-common.h" #include "qapi/string-output-visitor.h" #include "test-qapi-types.h" #include "test-qapi-visit.h" diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c index b8ad16fc9e..a251f878e1 100644 --- a/tests/test-visitor-serialization.c +++ b/tests/test-visitor-serialization.c @@ -14,6 +14,8 @@ #include #include #include + +#include "qemu-common.h" #include "test-qapi-types.h" #include "test-qapi-visit.h" #include "qemu-objects.h" From 4167c42c5eb79add9252547efe92df7e5c2d1abd Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Dec 2012 11:51:59 +0100 Subject: [PATCH 2055/2270] qapi: remove qapi/qapi-types-core.h The file is only including error.h and qerror.h. Prefer explicit inclusion of whatever files are needed. Signed-off-by: Paolo Bonzini --- qapi/opts-visitor.c | 1 + qapi/qapi-dealloc-visitor.c | 1 + qapi/qapi-types-core.h | 20 -------------------- qapi/qapi-visit-core.c | 1 + qapi/qapi-visit-core.h | 2 +- qapi/qapi-visit-impl.h | 2 +- qemu-option-internal.h | 1 + qom/object.c | 1 + scripts/qapi-commands.py | 2 ++ target-i386/cpu.c | 1 + 10 files changed, 10 insertions(+), 22 deletions(-) delete mode 100644 qapi/qapi-types-core.h diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index e3fd25446d..6ccb8a1c33 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -11,6 +11,7 @@ */ #include "qemu-common.h" +#include "qerror.h" #include "opts-visitor.h" #include "qemu-queue.h" #include "qemu-option-internal.h" diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c index 75214e7daa..7c44042619 100644 --- a/qapi/qapi-dealloc-visitor.c +++ b/qapi/qapi-dealloc-visitor.c @@ -15,6 +15,7 @@ #include "qemu-queue.h" #include "qemu-common.h" #include "qemu-objects.h" +#include "qapi-visit-impl.h" typedef struct StackEntry { diff --git a/qapi/qapi-types-core.h b/qapi/qapi-types-core.h deleted file mode 100644 index 831df21ea7..0000000000 --- a/qapi/qapi-types-core.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Core Definitions for QAPI-generated Types - * - * Copyright IBM, Corp. 2011 - * - * Authors: - * Anthony Liguori - * - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. - * See the COPYING.LIB file in the top-level directory. - * - */ - -#ifndef QAPI_TYPES_CORE_H -#define QAPI_TYPES_CORE_H - -#include "error.h" -#include "qerror.h" - -#endif diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index 300293999d..4649fb71b7 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -12,6 +12,7 @@ */ #include "qemu-common.h" +#include "qerror.h" #include "qapi/qapi-visit-core.h" #include "qapi/qapi-visit-impl.h" diff --git a/qapi/qapi-visit-core.h b/qapi/qapi-visit-core.h index 60acedac77..00ce678d0a 100644 --- a/qapi/qapi-visit-core.h +++ b/qapi/qapi-visit-core.h @@ -13,7 +13,7 @@ #ifndef QAPI_VISITOR_CORE_H #define QAPI_VISITOR_CORE_H -#include "qapi/qapi-types-core.h" +#include "error.h" #include typedef struct GenericList diff --git a/qapi/qapi-visit-impl.h b/qapi/qapi-visit-impl.h index 0f3a1898fe..efd4271d40 100644 --- a/qapi/qapi-visit-impl.h +++ b/qapi/qapi-visit-impl.h @@ -12,7 +12,7 @@ #ifndef QAPI_VISITOR_IMPL_H #define QAPI_VISITOR_IMPL_H -#include "qapi/qapi-types-core.h" +#include "error.h" #include "qapi/qapi-visit-core.h" void input_type_enum(Visitor *v, int *obj, const char *strings[], diff --git a/qemu-option-internal.h b/qemu-option-internal.h index 19fdc1ca85..77899b082d 100644 --- a/qemu-option-internal.h +++ b/qemu-option-internal.h @@ -27,6 +27,7 @@ #define QEMU_OPTIONS_INTERNAL_H #include "qemu-option.h" +#include "qemu-error.h" struct QemuOpt { const char *name; diff --git a/qom/object.c b/qom/object.c index 0739aa2943..8d3036dcf4 100644 --- a/qom/object.c +++ b/qom/object.c @@ -15,6 +15,7 @@ #include "qapi/qapi-visit-core.h" #include "qapi/string-input-visitor.h" #include "qapi/string-output-visitor.h" +#include "qerror.h" /* TODO: replace QObject with a simpler visitor to avoid a dependency * of the QOM core on QObject? */ diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index 2db0bf1e56..5d034c2c21 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -367,6 +367,8 @@ def gen_command_def_prologue(prefix="", proxy=False): */ #include "qemu-common.h" +#include "module.h" +#include "qerror.h" #include "qemu-objects.h" #include "qapi/qmp-core.h" #include "qapi/qapi-visit-core.h" diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 7be3ad82cb..e968006ed0 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -26,6 +26,7 @@ #include "qemu-option.h" #include "qemu-config.h" +#include "qerror.h" #include "qapi/qapi-visit-core.h" #include "arch_init.h" From 7edd63f1b179c18f0f1a4664ddbabe4fe5b2be2f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Dec 2012 11:28:04 +0100 Subject: [PATCH 2056/2270] qapi: make struct Visitor opaque Move its definition from qapi-visit-core.h to qapi-visit-impl.h. Signed-off-by: Paolo Bonzini --- qapi/qapi-visit-core.h | 40 ---------------------------------------- qapi/qapi-visit-impl.h | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/qapi/qapi-visit-core.h b/qapi/qapi-visit-core.h index 00ce678d0a..602debe753 100644 --- a/qapi/qapi-visit-core.h +++ b/qapi/qapi-visit-core.h @@ -24,46 +24,6 @@ typedef struct GenericList typedef struct Visitor Visitor; -struct Visitor -{ - /* Must be set */ - void (*start_struct)(Visitor *v, void **obj, const char *kind, - const char *name, size_t size, Error **errp); - void (*end_struct)(Visitor *v, Error **errp); - - void (*start_list)(Visitor *v, const char *name, Error **errp); - GenericList *(*next_list)(Visitor *v, GenericList **list, Error **errp); - void (*end_list)(Visitor *v, Error **errp); - - void (*type_enum)(Visitor *v, int *obj, const char *strings[], - const char *kind, const char *name, Error **errp); - - void (*type_int)(Visitor *v, int64_t *obj, const char *name, Error **errp); - void (*type_bool)(Visitor *v, bool *obj, const char *name, Error **errp); - void (*type_str)(Visitor *v, char **obj, const char *name, Error **errp); - void (*type_number)(Visitor *v, double *obj, const char *name, - Error **errp); - - /* May be NULL */ - void (*start_optional)(Visitor *v, bool *present, const char *name, - Error **errp); - void (*end_optional)(Visitor *v, Error **errp); - - void (*start_handle)(Visitor *v, void **obj, const char *kind, - const char *name, Error **errp); - void (*end_handle)(Visitor *v, Error **errp); - void (*type_uint8)(Visitor *v, uint8_t *obj, const char *name, Error **errp); - void (*type_uint16)(Visitor *v, uint16_t *obj, const char *name, Error **errp); - void (*type_uint32)(Visitor *v, uint32_t *obj, const char *name, Error **errp); - void (*type_uint64)(Visitor *v, uint64_t *obj, const char *name, Error **errp); - void (*type_int8)(Visitor *v, int8_t *obj, const char *name, Error **errp); - void (*type_int16)(Visitor *v, int16_t *obj, const char *name, Error **errp); - void (*type_int32)(Visitor *v, int32_t *obj, const char *name, Error **errp); - void (*type_int64)(Visitor *v, int64_t *obj, const char *name, Error **errp); - /* visit_type_size() falls back to (*type_uint64)() if type_size is unset */ - void (*type_size)(Visitor *v, uint64_t *obj, const char *name, Error **errp); -}; - void visit_start_handle(Visitor *v, void **obj, const char *kind, const char *name, Error **errp); void visit_end_handle(Visitor *v, Error **errp); diff --git a/qapi/qapi-visit-impl.h b/qapi/qapi-visit-impl.h index efd4271d40..9337d62e75 100644 --- a/qapi/qapi-visit-impl.h +++ b/qapi/qapi-visit-impl.h @@ -15,6 +15,46 @@ #include "error.h" #include "qapi/qapi-visit-core.h" +struct Visitor +{ + /* Must be set */ + void (*start_struct)(Visitor *v, void **obj, const char *kind, + const char *name, size_t size, Error **errp); + void (*end_struct)(Visitor *v, Error **errp); + + void (*start_list)(Visitor *v, const char *name, Error **errp); + GenericList *(*next_list)(Visitor *v, GenericList **list, Error **errp); + void (*end_list)(Visitor *v, Error **errp); + + void (*type_enum)(Visitor *v, int *obj, const char *strings[], + const char *kind, const char *name, Error **errp); + + void (*type_int)(Visitor *v, int64_t *obj, const char *name, Error **errp); + void (*type_bool)(Visitor *v, bool *obj, const char *name, Error **errp); + void (*type_str)(Visitor *v, char **obj, const char *name, Error **errp); + void (*type_number)(Visitor *v, double *obj, const char *name, + Error **errp); + + /* May be NULL */ + void (*start_optional)(Visitor *v, bool *present, const char *name, + Error **errp); + void (*end_optional)(Visitor *v, Error **errp); + + void (*start_handle)(Visitor *v, void **obj, const char *kind, + const char *name, Error **errp); + void (*end_handle)(Visitor *v, Error **errp); + void (*type_uint8)(Visitor *v, uint8_t *obj, const char *name, Error **errp); + void (*type_uint16)(Visitor *v, uint16_t *obj, const char *name, Error **errp); + void (*type_uint32)(Visitor *v, uint32_t *obj, const char *name, Error **errp); + void (*type_uint64)(Visitor *v, uint64_t *obj, const char *name, Error **errp); + void (*type_int8)(Visitor *v, int8_t *obj, const char *name, Error **errp); + void (*type_int16)(Visitor *v, int16_t *obj, const char *name, Error **errp); + void (*type_int32)(Visitor *v, int32_t *obj, const char *name, Error **errp); + void (*type_int64)(Visitor *v, int64_t *obj, const char *name, Error **errp); + /* visit_type_size() falls back to (*type_uint64)() if type_size is unset */ + void (*type_size)(Visitor *v, uint64_t *obj, const char *name, Error **errp); +}; + void input_type_enum(Visitor *v, int *obj, const char *strings[], const char *kind, const char *name, Error **errp); void output_type_enum(Visitor *v, int *obj, const char *strings[], From cb9c377f54a756b04ef92c1c2e0453613ee863cf Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Dec 2012 12:15:58 +0100 Subject: [PATCH 2057/2270] janitor: add guards to headers Signed-off-by: Paolo Bonzini --- gen-icount.h | 5 +++++ host-utils.h | 4 ++++ hw/9pfs/virtio-9p-synth.h | 4 ++++ hw/audiodev.h | 5 +++++ hw/baum.h | 4 ++++ hw/bt.h | 5 +++++ hw/cris-boot.h | 4 ++++ hw/empty_slot.h | 5 +++++ hw/escc.h | 5 +++++ hw/etraxfs.h | 5 +++++ hw/etraxfs_dma.h | 5 +++++ hw/flash.h | 5 +++++ hw/lm32.h | 5 +++++ hw/mac_dbdma.h | 4 ++++ hw/msmouse.h | 5 +++++ hw/ne2000.h | 5 +++++ hw/pci/pci_ids.h | 4 ++++ hw/pcmcia.h | 5 +++++ hw/pcnet.h | 5 +++++ hw/ppc.h | 5 +++++ hw/qdev-addr.h | 5 +++++ hw/qxl.h | 5 +++++ hw/s390-virtio-bus.h | 4 ++++ hw/scsi-defs.h | 4 ++++ hw/serial.h | 4 ++++ hw/soc_dma.h | 6 ++++++ hw/usb/hcd-ehci.h | 4 ++++ hw/vga_int.h | 4 ++++ hw/xilinx.h | 6 ++++++ iov.h | 5 +++++ linux-user/cris/syscall.h | 5 +++++ linux-user/microblaze/syscall.h | 6 ++++++ linux-user/syscall_defs.h | 6 ++++++ slirp/bootp.h | 4 ++++ slirp/main.h | 4 ++++ slirp/tftp.h | 4 ++++ softmmu-semi.h | 4 ++++ target-cris/crisv32-decode.h | 4 ++++ tcg/arm/tcg-target.h | 3 +++ tcg/hppa/tcg-target.h | 3 +++ tcg/i386/tcg-target.h | 3 +++ tcg/ia64/tcg-target.h | 3 +++ tcg/mips/tcg-target.h | 3 +++ tcg/ppc/tcg-target.h | 3 +++ tcg/ppc64/tcg-target.h | 3 +++ tcg/s390/tcg-target.h | 3 +++ tcg/sparc/tcg-target.h | 3 +++ tests/tcg/cris/crisutils.h | 5 +++++ ui/curses_keys.h | 5 +++++ ui/d3des.h | 4 ++++ 50 files changed, 219 insertions(+) diff --git a/gen-icount.h b/gen-icount.h index 248cf5b16d..1541f0b1e4 100644 --- a/gen-icount.h +++ b/gen-icount.h @@ -1,3 +1,6 @@ +#ifndef GEN_ICOUNT_H +#define GEN_ICOUNT_H 1 + #include "qemu-timer.h" /* Helpers for instruction counting code generation. */ @@ -46,3 +49,5 @@ static inline void gen_io_end(void) tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUArchState, can_do_io)); tcg_temp_free_i32(tmp); } + +#endif diff --git a/host-utils.h b/host-utils.h index 821db93671..a5f8464fb2 100644 --- a/host-utils.h +++ b/host-utils.h @@ -22,6 +22,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef HOST_UTILS_H +#define HOST_UTILS_H 1 #include "compiler.h" /* QEMU_GNUC_PREREQ */ @@ -234,3 +236,5 @@ static inline int ctpop64(uint64_t val) return val; #endif } + +#endif diff --git a/hw/9pfs/virtio-9p-synth.h b/hw/9pfs/virtio-9p-synth.h index e03f434633..ab05a8e78c 100644 --- a/hw/9pfs/virtio-9p-synth.h +++ b/hw/9pfs/virtio-9p-synth.h @@ -10,6 +10,8 @@ * the COPYING file in the top-level directory. * */ +#ifndef HW_9PFS_VIRTIO9P_SYNTH_H +#define HW_9PFS_VIRTIO9P_SYNTH_H 1 #include #include @@ -48,3 +50,5 @@ extern int qemu_v9fs_synth_mkdir(V9fsSynthNode *parent, int mode, extern int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode, const char *name, v9fs_synth_read read, v9fs_synth_write write, void *arg); + +#endif diff --git a/hw/audiodev.h b/hw/audiodev.h index ed2790f5f6..428274f929 100644 --- a/hw/audiodev.h +++ b/hw/audiodev.h @@ -1,3 +1,6 @@ +#ifndef HW_AUDIODEV_H +#define HW_AUDIODEV_H 1 + /* es1370.c */ int es1370_init(PCIBus *bus); @@ -18,3 +21,5 @@ int cs4231a_init(ISABus *bus); /* intel-hda.c + hda-audio.c */ int intel_hda_and_codec_init(PCIBus *bus); + +#endif diff --git a/hw/baum.h b/hw/baum.h index 8af710fa21..763588422a 100644 --- a/hw/baum.h +++ b/hw/baum.h @@ -21,6 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef HW_BAUM_H +#define HW_BAUM_H 1 /* char device */ CharDriverState *chr_baum_init(QemuOpts *opts); + +#endif diff --git a/hw/bt.h b/hw/bt.h index ebf6a370a1..830af94735 100644 --- a/hw/bt.h +++ b/hw/bt.h @@ -23,6 +23,9 @@ * along with this program; if not, see . */ +#ifndef HW_BT_H +#define HW_BT_H 1 + #include "hw/irq.h" /* BD Address */ @@ -2183,3 +2186,5 @@ enum bt_sdp_attribute_id { SDP_ATTR_NORMALLY_CONNECTABLE = 0x020d, SDP_ATTR_BOOT_DEVICE = 0x020e, }; + +#endif diff --git a/hw/cris-boot.h b/hw/cris-boot.h index 5b17d83cbb..c4d3fa6f6f 100644 --- a/hw/cris-boot.h +++ b/hw/cris-boot.h @@ -1,3 +1,5 @@ +#ifndef _CRIS_BOOT_H +#define HW_CRIS_BOOT_H 1 struct cris_load_info { @@ -9,3 +11,5 @@ struct cris_load_info }; void cris_load_image(CRISCPU *cpu, struct cris_load_info *li); + +#endif diff --git a/hw/empty_slot.h b/hw/empty_slot.h index 4e9e460485..6079602cdf 100644 --- a/hw/empty_slot.h +++ b/hw/empty_slot.h @@ -1,2 +1,7 @@ +#ifndef HW_EMPTY_SLOT_H +#define HW_EMPTY_SLOT_H 1 + /* empty_slot.c */ void empty_slot_init(hwaddr addr, uint64_t slot_size); + +#endif diff --git a/hw/escc.h b/hw/escc.h index def28947a0..bda3213317 100644 --- a/hw/escc.h +++ b/hw/escc.h @@ -1,3 +1,6 @@ +#ifndef HW_ESCC_H +#define HW_ESCC_H 1 + /* escc.c */ #define ESCC_SIZE 4 MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB, @@ -6,3 +9,5 @@ MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB, void slavio_serial_ms_kbd_init(hwaddr base, qemu_irq irq, int disabled, int clock, int it_shift); + +#endif diff --git a/hw/etraxfs.h b/hw/etraxfs.h index bc60713633..cc1d7a17a0 100644 --- a/hw/etraxfs.h +++ b/hw/etraxfs.h @@ -22,6 +22,9 @@ * THE SOFTWARE. */ +#ifndef HW_EXTRAXFS_H +#define HW_EXTRAXFS_H 1 + #include "net/net.h" #include "etraxfs_dma.h" @@ -44,3 +47,5 @@ etraxfs_eth_init(NICInfo *nd, hwaddr base, int phyaddr, sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); return dev; } + +#endif diff --git a/hw/etraxfs_dma.h b/hw/etraxfs_dma.h index 3fef80fae1..38104a67b5 100644 --- a/hw/etraxfs_dma.h +++ b/hw/etraxfs_dma.h @@ -1,3 +1,6 @@ +#ifndef HW_ETRAXFS_DMA_H +#define HW_ETRAXFS_DMA_H 1 + struct dma_context_metadata { /* data descriptor md */ uint16_t metadata; @@ -27,3 +30,5 @@ void etraxfs_dmac_connect_client(void *opaque, int c, struct etraxfs_dma_client *cl); int etraxfs_dmac_input(struct etraxfs_dma_client *client, void *buf, int len, int eop); + +#endif diff --git a/hw/flash.h b/hw/flash.h index d790f3c92d..bda2158c13 100644 --- a/hw/flash.h +++ b/hw/flash.h @@ -1,3 +1,6 @@ +#ifndef HW_FLASH_H +#define HW_FLASH_H 1 + /* NOR flash devices */ #include "memory.h" @@ -57,3 +60,5 @@ typedef struct { uint8_t ecc_digest(ECCState *s, uint8_t sample); void ecc_reset(ECCState *s); extern VMStateDescription vmstate_ecc_state; + +#endif diff --git a/hw/lm32.h b/hw/lm32.h index 0a676329fd..4194c9a813 100644 --- a/hw/lm32.h +++ b/hw/lm32.h @@ -1,3 +1,6 @@ +#ifndef HW_LM32_H +#define HW_LM32_H 1 + #include "qemu-common.h" @@ -23,3 +26,5 @@ static inline DeviceState *lm32_juart_init(void) return dev; } + +#endif diff --git a/hw/mac_dbdma.h b/hw/mac_dbdma.h index bfdb0ddc68..e596837f46 100644 --- a/hw/mac_dbdma.h +++ b/hw/mac_dbdma.h @@ -19,6 +19,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef HW_MAC_DBDMA_H +#define HW_MAC_DBDMA_H 1 #include "memory.h" @@ -42,3 +44,5 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, DBDMA_rw rw, DBDMA_flush flush, void *opaque); void* DBDMA_init (MemoryRegion **dbdma_mem); + +#endif diff --git a/hw/msmouse.h b/hw/msmouse.h index 456cb21424..8cff3a71c3 100644 --- a/hw/msmouse.h +++ b/hw/msmouse.h @@ -1,2 +1,7 @@ +#ifndef HW_MSMOUSE_H +#define HW_MSMOUSE_H 1 + /* msmouse.c */ CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts); + +#endif diff --git a/hw/ne2000.h b/hw/ne2000.h index 1e7ab073e3..b31ae030f9 100644 --- a/hw/ne2000.h +++ b/hw/ne2000.h @@ -1,3 +1,6 @@ +#ifndef HW_NE2000_H +#define HW_NE2000_H 1 + #define NE2000_PMEM_SIZE (32*1024) #define NE2000_PMEM_START (16*1024) #define NE2000_PMEM_END (NE2000_PMEM_SIZE+NE2000_PMEM_START) @@ -33,3 +36,5 @@ extern const VMStateDescription vmstate_ne2000; void ne2000_reset(NE2000State *s); int ne2000_can_receive(NetClientState *nc); ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_); + +#endif diff --git a/hw/pci/pci_ids.h b/hw/pci/pci_ids.h index 5df7245349..271d935bc7 100644 --- a/hw/pci/pci_ids.h +++ b/hw/pci/pci_ids.h @@ -7,6 +7,8 @@ * * QEMU-specific definitions belong in pci.h */ +#ifndef HW_PCI_IDS_H +#define HW_PCI_IDS_H 1 /* Device classes and subclasses */ @@ -145,3 +147,5 @@ #define PCI_VENDOR_ID_NEC 0x1033 #define PCI_DEVICE_ID_NEC_UPD720200 0x0194 + +#endif diff --git a/hw/pcmcia.h b/hw/pcmcia.h index 50648c973f..aac1d77cc7 100644 --- a/hw/pcmcia.h +++ b/hw/pcmcia.h @@ -1,3 +1,6 @@ +#ifndef HW_PCMCIA_H +#define HW_PCMCIA_H 1 + /* PCMCIA/Cardbus */ #include "qemu-common.h" @@ -49,3 +52,5 @@ struct PCMCIACardState { /* dscm1xxxx.c */ PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv); + +#endif diff --git a/hw/pcnet.h b/hw/pcnet.h index da8c3bde7b..96643117a0 100644 --- a/hw/pcnet.h +++ b/hw/pcnet.h @@ -1,3 +1,6 @@ +#ifndef HW_PCNET_H +#define HW_PCNET_H 1 + #define PCNET_IOPORT_SIZE 0x20 #define PCNET_PNPMMIO_SIZE 0x20 @@ -63,3 +66,5 @@ void pcnet_set_link_status(NetClientState *nc); void pcnet_common_cleanup(PCNetState *d); int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info); extern const VMStateDescription vmstate_pcnet; + +#endif diff --git a/hw/ppc.h b/hw/ppc.h index 2f3ea277bc..17005c795a 100644 --- a/hw/ppc.h +++ b/hw/ppc.h @@ -1,3 +1,6 @@ +#ifndef HW_PPC_H +#define HW_PPC_H 1 + void ppc_set_irq (CPUPPCState *env, int n_IRQ, int level); /* PowerPC hardware exceptions management helpers */ @@ -90,3 +93,5 @@ enum { /* ppc_booke.c */ void ppc_booke_timers_init(CPUPPCState *env, uint32_t freq, uint32_t flags); + +#endif diff --git a/hw/qdev-addr.h b/hw/qdev-addr.h index ea5ecb4d78..79708e6751 100644 --- a/hw/qdev-addr.h +++ b/hw/qdev-addr.h @@ -1,5 +1,10 @@ +#ifndef HW_QDEV_ADDR_H +#define HW_QDEV_ADDR_H 1 + #define DEFINE_PROP_TADDR(_n, _s, _f, _d) \ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_taddr, hwaddr) extern PropertyInfo qdev_prop_taddr; void qdev_prop_set_taddr(DeviceState *dev, const char *name, hwaddr value); + +#endif diff --git a/hw/qxl.h b/hw/qxl.h index 8433d1aeea..9130261524 100644 --- a/hw/qxl.h +++ b/hw/qxl.h @@ -1,3 +1,6 @@ +#ifndef HW_QXL_H +#define HW_QXL_H 1 + #include "qemu-common.h" #include "ui/console.h" @@ -158,3 +161,5 @@ void qxl_render_update(PCIQXLDevice *qxl); int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext); void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie); void qxl_render_update_area_bh(void *opaque); + +#endif diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h index a83afe785f..23fedd5be8 100644 --- a/hw/s390-virtio-bus.h +++ b/hw/s390-virtio-bus.h @@ -16,6 +16,8 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ +#ifndef HW_S390_VIRTIO_BUS_H +#define HW_S390_VIRTIO_BUS_H 1 #include "virtio-blk.h" #include "virtio-net.h" @@ -100,3 +102,5 @@ VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem); void s390_virtio_device_sync(VirtIOS390Device *dev); void s390_virtio_reset_idx(VirtIOS390Device *dev); + +#endif diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h index d7a401912b..9ab045b613 100644 --- a/hw/scsi-defs.h +++ b/hw/scsi-defs.h @@ -19,6 +19,8 @@ * This header file contains public constants and structures used by * the scsi code for linux. */ +#ifndef HW_SCSI_DEFS_H +#define HW_SCSI_DEFS_H 1 /* * SCSI opcodes @@ -301,3 +303,5 @@ #define MMC_PROFILE_HDDVD_R_DL 0x0058 #define MMC_PROFILE_HDDVD_RW_DL 0x005A #define MMC_PROFILE_INVALID 0xFFFF + +#endif diff --git a/hw/serial.h b/hw/serial.h index ed1a5cd43e..2d7d614e09 100644 --- a/hw/serial.h +++ b/hw/serial.h @@ -22,6 +22,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef HW_SERIAL_H +#define HW_SERIAL_H 1 #include "hw.h" #include "sysemu.h" @@ -97,3 +99,5 @@ SerialState *serial_mm_init(MemoryRegion *address_space, /* serial-isa.c */ bool serial_isa_init(ISABus *bus, int index, CharDriverState *chr); + +#endif diff --git a/hw/soc_dma.h b/hw/soc_dma.h index 5948489eae..6ca4166184 100644 --- a/hw/soc_dma.h +++ b/hw/soc_dma.h @@ -18,6 +18,10 @@ * with this program; if not, see . */ +#ifndef HW_SOC_DMA_H +#define HW_SOC_DMA_H 1 + + #include "memory.h" #include "hw/irq.h" @@ -108,3 +112,5 @@ static inline void soc_dma_port_add_fifo_out(struct soc_dma_s *dma, { return soc_dma_port_add_fifo(dma, virt_base, fn, opaque, 1); } + +#endif diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index 772870b727..837c63be85 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -14,6 +14,8 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ +#ifndef HW_USB_EHCI_H +#define HW_USB_EHCI_H 1 #include "hw/hw.h" #include "qemu-timer.h" @@ -318,3 +320,5 @@ struct EHCIState { extern const VMStateDescription vmstate_ehci; void usb_ehci_initfn(EHCIState *s, DeviceState *dev); + +#endif diff --git a/hw/vga_int.h b/hw/vga_int.h index bcb738d8c9..ad02404b3c 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -21,6 +21,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef HW_VGA_INT_H +#define HW_VGA_INT_H 1 #include #include "error.h" @@ -212,3 +214,5 @@ extern const uint8_t gr_mask[16]; #define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin" extern const MemoryRegionOps vga_mem_ops; + +#endif diff --git a/hw/xilinx.h b/hw/xilinx.h index 735f8e257d..a12eccbe3c 100644 --- a/hw/xilinx.h +++ b/hw/xilinx.h @@ -1,3 +1,7 @@ +#ifndef HW_XILINX_H +#define HW_XILINX_H 1 + + #include "stream.h" #include "qemu-common.h" #include "net/net.h" @@ -90,3 +94,5 @@ xilinx_axiethernetdma_init(DeviceState *dev, StreamSlave *peer, sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq); sysbus_connect_irq(sysbus_from_qdev(dev), 1, irq2); } + +#endif diff --git a/iov.h b/iov.h index 34c8ec9faa..d06f8b9ce3 100644 --- a/iov.h +++ b/iov.h @@ -11,6 +11,9 @@ * the COPYING file in the top-level directory. */ +#ifndef IOV_H +#define IOV_H + #include "qemu-common.h" /** @@ -95,3 +98,5 @@ void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt, unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt, const struct iovec *iov, unsigned int iov_cnt, size_t offset, size_t bytes); + +#endif diff --git a/linux-user/cris/syscall.h b/linux-user/cris/syscall.h index 24f92ba421..50e50b4f3f 100644 --- a/linux-user/cris/syscall.h +++ b/linux-user/cris/syscall.h @@ -1,3 +1,6 @@ +#ifndef CRIS_SYSCALL_H +#define CRIS_SYSCALL_H 1 + #define UNAME_MACHINE "cris" @@ -34,3 +37,5 @@ struct target_pt_regs { unsigned long exs; unsigned long eda; }; + +#endif diff --git a/linux-user/microblaze/syscall.h b/linux-user/microblaze/syscall.h index db1f98ae69..c3e5c55b3d 100644 --- a/linux-user/microblaze/syscall.h +++ b/linux-user/microblaze/syscall.h @@ -1,3 +1,7 @@ +#ifndef MICROBLAZE_SYSCALLS_H +#define MICROBLAZE_SYSCALLS_H 1 + + #define UNAME_MACHINE "microblaze" /* We use microblaze_reg_t to keep things similar to the kernel sources. */ @@ -43,3 +47,5 @@ struct target_pt_regs { microblaze_reg_t fsr; uint32_t kernel_mode; }; + +#endif diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index a98cbf7b80..d4589e7906 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -4,6 +4,10 @@ most of them stay the same, so we handle it by putting ifdefs if necessary */ +#ifndef SYSCALL_DEFS_H +#define SYSCALL_DEFS_H 1 + + #include "syscall_nr.h" #define SOCKOP_socket 1 @@ -2425,3 +2429,5 @@ struct target_ucred { uint32_t uid; uint32_t gid; }; + +#endif diff --git a/slirp/bootp.h b/slirp/bootp.h index 30c30ab863..ec3b68704c 100644 --- a/slirp/bootp.h +++ b/slirp/bootp.h @@ -1,4 +1,6 @@ /* bootp/dhcp defines */ +#ifndef SLIRP_BOOTP_H +#define SLIRP_BOOTP_H 1 #define BOOTP_SERVER 67 #define BOOTP_CLIENT 68 @@ -120,3 +122,5 @@ typedef struct { #define NB_BOOTP_CLIENTS 16 void bootp_input(struct mbuf *m); + +#endif diff --git a/slirp/main.h b/slirp/main.h index 1f3b84de92..66e4f9252f 100644 --- a/slirp/main.h +++ b/slirp/main.h @@ -4,6 +4,8 @@ * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */ +#ifndef SLIRP_MAIN_H +#define SLIRP_MAIN_H 1 #ifdef HAVE_SYS_SELECT_H #include @@ -45,3 +47,5 @@ extern int tcp_keepintvl; int if_encap(Slirp *slirp, struct mbuf *ifm); ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags); + +#endif diff --git a/slirp/tftp.h b/slirp/tftp.h index 51704e4874..87adeb5333 100644 --- a/slirp/tftp.h +++ b/slirp/tftp.h @@ -1,4 +1,6 @@ /* tftp defines */ +#ifndef SLIRP_TFTP_H +#define SLIRP_TFTP_H 1 #define TFTP_SESSIONS_MAX 3 @@ -43,3 +45,5 @@ struct tftp_session { }; void tftp_input(struct mbuf *m); + +#endif diff --git a/softmmu-semi.h b/softmmu-semi.h index bcb979a5b0..93798b9614 100644 --- a/softmmu-semi.h +++ b/softmmu-semi.h @@ -6,6 +6,8 @@ * * This code is licensed under the GPL */ +#ifndef SOFTMMU_SEMI_H +#define SOFTMMU_SEMI_H 1 static inline uint32_t softmmu_tget32(CPUArchState *env, uint32_t addr) { @@ -71,3 +73,5 @@ static void softmmu_unlock_user(CPUArchState *env, void *p, target_ulong addr, free(p); } #define unlock_user(s, args, len) softmmu_unlock_user(env, s, args, len) + +#endif diff --git a/target-cris/crisv32-decode.h b/target-cris/crisv32-decode.h index ed141de0b7..cdba377817 100644 --- a/target-cris/crisv32-decode.h +++ b/target-cris/crisv32-decode.h @@ -17,6 +17,8 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ +#ifndef CRISV32_DECODE_H +#define CRISV32_DECODE_H 1 /* Convenient binary macros. */ #define HEX__(n) 0x##n##LU @@ -126,3 +128,5 @@ #define DEC_FTAG_FIDX_D_M {B8(10101011), B8(11111111)} #define DEC_FTAG_FIDX_I_M {B8(11010011), B8(11111111)} + +#endif diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index 98fa11b286..7083f3a700 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef TCG_TARGET_ARM #define TCG_TARGET_ARM 1 #undef TCG_TARGET_WORDS_BIGENDIAN @@ -91,3 +92,5 @@ static inline void flush_icache_range(tcg_target_ulong start, __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg)); #endif } + +#endif diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h index f43fb419ae..e2754fe970 100644 --- a/tcg/hppa/tcg-target.h +++ b/tcg/hppa/tcg-target.h @@ -22,6 +22,7 @@ * THE SOFTWARE. */ +#ifndef TCG_TARGET_HPPA #define TCG_TARGET_HPPA 1 #if TCG_TARGET_REG_BITS != 32 @@ -119,3 +120,5 @@ static inline void flush_icache_range(tcg_target_ulong start, start += 32; } } + +#endif diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index dbc6756414..5352ac0254 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef TCG_TARGET_I386 #define TCG_TARGET_I386 1 //#define TCG_TARGET_WORDS_BIGENDIAN @@ -135,3 +136,5 @@ static inline void flush_icache_range(tcg_target_ulong start, tcg_target_ulong stop) { } + +#endif diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index 91fe7a3b06..7f3401ecdd 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef TCG_TARGET_IA64 #define TCG_TARGET_IA64 1 /* We only map the first 64 registers */ @@ -158,3 +159,5 @@ static inline void flush_icache_range(tcg_target_ulong start, } asm volatile (";;sync.i;;srlz.i;;"); } + +#endif diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index 65b5c59e89..78af664cca 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -23,6 +23,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef TCG_TARGET_MIPS #define TCG_TARGET_MIPS 1 #ifdef __MIPSEB__ @@ -127,3 +128,5 @@ static inline void flush_icache_range(tcg_target_ulong start, { cacheflush ((void *)start, stop-start, ICACHE); } + +#endif diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h index ad433ae5bb..ea26769581 100644 --- a/tcg/ppc/tcg-target.h +++ b/tcg/ppc/tcg-target.h @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef TCG_TARGET_PPC #define TCG_TARGET_PPC 1 #define TCG_TARGET_WORDS_BIGENDIAN @@ -99,3 +100,5 @@ typedef enum { #define tcg_qemu_tb_exec(env, tb_ptr) \ ((long __attribute__ ((longcall)) \ (*)(void *, void *))code_gen_prologue)(env, tb_ptr) + +#endif diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h index 97fc5c9885..9b8e9a07b8 100644 --- a/tcg/ppc64/tcg-target.h +++ b/tcg/ppc64/tcg-target.h @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef TCG_TARGET_PPC64 #define TCG_TARGET_PPC64 1 #define TCG_TARGET_WORDS_BIGENDIAN @@ -109,3 +110,5 @@ typedef enum { #define TCG_AREG0 TCG_REG_R27 #define TCG_TARGET_EXTEND_ARGS 1 + +#endif diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h index a0181aef74..c87b4138b5 100644 --- a/tcg/s390/tcg-target.h +++ b/tcg/s390/tcg-target.h @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef TCG_TARGET_S390 #define TCG_TARGET_S390 1 #define TCG_TARGET_WORDS_BIGENDIAN @@ -103,3 +104,5 @@ static inline void flush_icache_range(tcg_target_ulong start, tcg_target_ulong stop) { } + +#endif diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index 0e7d398a41..256f973c6d 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef TCG_TARGET_SPARC #define TCG_TARGET_SPARC 1 #define TCG_TARGET_WORDS_BIGENDIAN @@ -138,3 +139,5 @@ static inline void flush_icache_range(tcg_target_ulong start, for (; p < stop; p += 8) __asm__ __volatile__("flush\t%0" : : "r" (p)); } + +#endif diff --git a/tests/tcg/cris/crisutils.h b/tests/tcg/cris/crisutils.h index 29b71cd7b9..3456b9d50d 100644 --- a/tests/tcg/cris/crisutils.h +++ b/tests/tcg/cris/crisutils.h @@ -1,3 +1,6 @@ +#ifndef CRISUTILS_H +#define CRISUTILS_H 1 + static char *tst_cc_loc = NULL; #define cris_tst_cc_init() \ @@ -69,3 +72,5 @@ static inline void cris_tst_cc(const int n, const int z, if (c) cris_tst_cc_c1(); else cris_tst_cc_c0(); asm volatile ("" : : "g" (_err)); } + +#endif diff --git a/ui/curses_keys.h b/ui/curses_keys.h index c0d5eb452f..18ce6dceee 100644 --- a/ui/curses_keys.h +++ b/ui/curses_keys.h @@ -22,6 +22,9 @@ * THE SOFTWARE. */ +#ifndef QEMU_CURSES_KEYS_H +#define QEMU_CURSES_KEYS_H 1 + #include #include "keymaps.h" @@ -507,3 +510,5 @@ static const name2keysym_t name2keysym[] = { { NULL, 0 }, }; + +#endif diff --git a/ui/d3des.h b/ui/d3des.h index 78d546f7d8..70cb6b57ea 100644 --- a/ui/d3des.h +++ b/ui/d3des.h @@ -9,6 +9,8 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ +#ifndef D3DES_H +#define D3DES_H 1 /* d3des.h - * @@ -49,3 +51,5 @@ void des(unsigned char *, unsigned char *); /* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery ********************************************************************/ + +#endif From 7b1b5d191385ca52e96caae2a05c64f3a63855d9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Dec 2012 18:19:43 +0100 Subject: [PATCH 2058/2270] qapi: move include files to include/qobject/ Signed-off-by: Paolo Bonzini --- backends/rng-egd.c | 2 +- backends/rng-random.c | 2 +- backends/rng.c | 2 +- balloon.c | 2 +- block.c | 2 +- block.h | 2 +- block/qcow2.c | 2 +- block/qed.c | 2 +- block_int.h | 2 +- blockdev-nbd.c | 2 +- blockdev.c | 4 ++-- blockdev.h | 2 +- blockjob.c | 2 +- dump-stub.c | 2 +- dump.c | 2 +- error.c | 8 ++++---- hmp.h | 2 +- hw/ivshmem.c | 2 +- hw/mc146818rtc.c | 2 +- hw/pci/pci-hotplug.c | 2 +- hw/pci/pcie_aer.c | 2 +- hw/qdev-addr.c | 2 +- hw/qdev-core.h | 2 +- hw/qdev-properties.c | 4 ++-- hw/qdev.c | 4 ++-- hw/vga_int.h | 2 +- hw/watchdog.c | 2 +- include/net/net.h | 2 +- include/net/slirp.h | 2 +- .../qapi/dealloc-visitor.h | 2 +- error.h => include/qapi/error.h | 0 {qapi => include/qapi}/opts-visitor.h | 2 +- {qapi => include/qapi}/qmp-input-visitor.h | 4 ++-- {qapi => include/qapi}/qmp-output-visitor.h | 4 ++-- qapi/qmp-core.h => include/qapi/qmp/dispatch.h | 6 +++--- json-lexer.h => include/qapi/qmp/json-lexer.h | 4 ++-- .../qapi/qmp/json-parser.h | 4 ++-- .../qapi/qmp/json-streamer.h | 4 ++-- qbool.h => include/qapi/qmp/qbool.h | 2 +- qdict.h => include/qapi/qmp/qdict.h | 4 ++-- qerror.h => include/qapi/qmp/qerror.h | 6 +++--- qfloat.h => include/qapi/qmp/qfloat.h | 2 +- qint.h => include/qapi/qmp/qint.h | 2 +- qjson.h => include/qapi/qmp/qjson.h | 4 ++-- qlist.h => include/qapi/qmp/qlist.h | 2 +- qobject.h => include/qapi/qmp/qobject.h | 0 qstring.h => include/qapi/qmp/qstring.h | 2 +- qemu-objects.h => include/qapi/qmp/types.h | 16 ++++++++-------- {qapi => include/qapi}/string-input-visitor.h | 2 +- {qapi => include/qapi}/string-output-visitor.h | 2 +- .../qapi/visitor-impl.h | 4 ++-- .../qapi/visitor.h | 2 +- include/qemu/rng.h | 2 +- include/ui/console.h | 4 ++-- json-lexer.c | 10 +++++----- json-parser.c | 18 +++++++++--------- json-streamer.c | 10 +++++----- migration.h | 4 ++-- monitor.c | 16 ++++++++-------- monitor.h | 4 ++-- net/net.c | 2 +- pixman | 2 +- qapi/opts-visitor.c | 6 +++--- qapi/qapi-dealloc-visitor.c | 6 +++--- qapi/qapi-visit-core.c | 6 +++--- qapi/qmp-dispatch.c | 10 +++++----- qapi/qmp-input-visitor.c | 8 ++++---- qapi/qmp-output-visitor.c | 8 ++++---- qapi/qmp-registry.c | 2 +- qapi/string-input-visitor.c | 6 +++--- qapi/string-output-visitor.c | 6 +++--- qbool.c | 4 ++-- qdict.c | 12 ++++++------ qemu-char.h | 4 ++-- qemu-config.c | 2 +- qemu-config.h | 2 +- qemu-img.c | 2 +- qemu-option.c | 6 +++--- qemu-option.h | 4 ++-- qemu_socket.h | 4 ++-- qerror.c | 4 ++-- qfloat.c | 4 ++-- qga/commands-posix.c | 2 +- qga/commands-win32.c | 2 +- qga/commands.c | 2 +- qga/guest-agent-core.h | 2 +- qga/main.c | 12 ++++++------ qint.c | 4 ++-- qjson.c | 18 +++++++++--------- qlist.c | 4 ++-- qom/object.c | 12 ++++++------ qom/qom-qobject.c | 2 +- qstring.c | 4 ++-- scripts/qapi-commands.py | 14 +++++++------- scripts/qapi-types.py | 2 +- scripts/qapi-visit.py | 2 +- stubs/arch-query-cpu-def.c | 2 +- target-i386/cpu-qom.h | 2 +- target-i386/cpu.c | 4 ++-- target-openrisc/cpu.h | 2 +- tests/check-qdict.c | 6 +++--- tests/check-qfloat.c | 2 +- tests/check-qint.c | 2 +- tests/check-qjson.c | 14 +++++++------- tests/check-qlist.c | 4 ++-- tests/check-qstring.c | 2 +- tests/test-qmp-commands.c | 4 ++-- tests/test-qmp-input-strict.c | 2 +- tests/test-qmp-input-visitor.c | 2 +- tests/test-qmp-output-visitor.c | 2 +- tests/test-string-input-visitor.c | 2 +- tests/test-string-output-visitor.c | 2 +- tests/test-visitor-serialization.c | 2 +- ui/input.c | 2 +- ui/spice-core.c | 8 ++++---- ui/vnc-enc-tight.c | 2 +- ui/vnc-palette.h | 2 +- ui/vnc.c | 2 +- vl.c | 2 +- 119 files changed, 242 insertions(+), 242 deletions(-) rename qapi/qapi-dealloc-visitor.h => include/qapi/dealloc-visitor.h (95%) rename error.h => include/qapi/error.h (100%) rename {qapi => include/qapi}/opts-visitor.h (96%) rename {qapi => include/qapi}/qmp-input-visitor.h (91%) rename {qapi => include/qapi}/qmp-output-visitor.h (91%) rename qapi/qmp-core.h => include/qapi/qmp/dispatch.h (93%) rename json-lexer.h => include/qapi/qmp/json-lexer.h (94%) rename json-parser.h => include/qapi/qmp/json-parser.h (90%) rename json-streamer.h => include/qapi/qmp/json-streamer.h (93%) rename qbool.h => include/qapi/qmp/qbool.h (94%) rename qdict.h => include/qapi/qmp/qdict.h (97%) rename qerror.h => include/qapi/qmp/qerror.h (99%) rename qfloat.h => include/qapi/qmp/qfloat.h (94%) rename qint.h => include/qapi/qmp/qint.h (94%) rename qjson.h => include/qapi/qmp/qjson.h (91%) rename qlist.h => include/qapi/qmp/qlist.h (98%) rename qobject.h => include/qapi/qmp/qobject.h (100%) rename qstring.h => include/qapi/qmp/qstring.h (96%) rename qemu-objects.h => include/qapi/qmp/types.h (60%) rename {qapi => include/qapi}/string-input-visitor.h (95%) rename {qapi => include/qapi}/string-output-visitor.h (95%) rename qapi/qapi-visit-impl.h => include/qapi/visitor-impl.h (98%) rename qapi/qapi-visit-core.h => include/qapi/visitor.h (99%) diff --git a/backends/rng-egd.c b/backends/rng-egd.c index ad8473777c..3a7d1ecbe0 100644 --- a/backends/rng-egd.c +++ b/backends/rng-egd.c @@ -12,7 +12,7 @@ #include "qemu/rng.h" #include "qemu-char.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" #include "hw/qdev.h" /* just for DEFINE_PROP_CHR */ #define TYPE_RNG_EGD "rng-egd" diff --git a/backends/rng-random.c b/backends/rng-random.c index 9c9923b2ac..c201953f29 100644 --- a/backends/rng-random.c +++ b/backends/rng-random.c @@ -12,7 +12,7 @@ #include "qemu/rng-random.h" #include "qemu/rng.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" #include "main-loop.h" struct RndRandom diff --git a/backends/rng.c b/backends/rng.c index 06f261180c..48a5840cd5 100644 --- a/backends/rng.c +++ b/backends/rng.c @@ -11,7 +11,7 @@ */ #include "qemu/rng.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" void rng_backend_request_entropy(RngBackend *s, size_t size, EntropyReceiveFunc *receive_entropy, diff --git a/balloon.c b/balloon.c index e02ab1c884..610fe6d626 100644 --- a/balloon.c +++ b/balloon.c @@ -30,7 +30,7 @@ #include "balloon.h" #include "trace.h" #include "qmp-commands.h" -#include "qjson.h" +#include "qapi/qmp/qjson.h" static QEMUBalloonEvent *balloon_event_fn; static QEMUBalloonStatus *balloon_stat_fn; diff --git a/block.c b/block.c index 0668c4be17..e962a5afe9 100644 --- a/block.c +++ b/block.c @@ -28,7 +28,7 @@ #include "block_int.h" #include "blockjob.h" #include "module.h" -#include "qjson.h" +#include "qapi/qmp/qjson.h" #include "sysemu.h" #include "notify.h" #include "qemu-coroutine.h" diff --git a/block.h b/block.h index 893448a5fc..0b22892d61 100644 --- a/block.h +++ b/block.h @@ -5,7 +5,7 @@ #include "qemu-common.h" #include "qemu-option.h" #include "qemu-coroutine.h" -#include "qobject.h" +#include "qapi/qmp/qobject.h" #include "qapi-types.h" /* block.c */ diff --git a/block/qcow2.c b/block/qcow2.c index 8520bda21a..217b4e422f 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -28,7 +28,7 @@ #include "aes.h" #include "block/qcow2.h" #include "qemu-error.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" #include "trace.h" /* diff --git a/block/qed.c b/block/qed.c index 0b5374a202..ca1fafb47e 100644 --- a/block/qed.c +++ b/block/qed.c @@ -15,7 +15,7 @@ #include "qemu-timer.h" #include "trace.h" #include "qed.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" #include "migration.h" static void qed_aio_cancel(BlockDriverAIOCB *blockacb) diff --git a/block_int.h b/block_int.h index bf3f79b3db..a748b6c571 100644 --- a/block_int.h +++ b/block_int.h @@ -30,7 +30,7 @@ #include "qemu-coroutine.h" #include "qemu-timer.h" #include "qapi-types.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" #include "monitor.h" #define BLOCK_FLAG_ENCRYPT 1 diff --git a/blockdev-nbd.c b/blockdev-nbd.c index 6b26bbf8c5..a194ecd392 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -12,7 +12,7 @@ #include "blockdev.h" #include "hw/block-common.h" #include "monitor.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" #include "sysemu.h" #include "qmp-commands.h" #include "trace.h" diff --git a/blockdev.c b/blockdev.c index 9a05e57009..c85c614577 100644 --- a/blockdev.c +++ b/blockdev.c @@ -11,10 +11,10 @@ #include "hw/block-common.h" #include "blockjob.h" #include "monitor.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" #include "qemu-option.h" #include "qemu-config.h" -#include "qemu-objects.h" +#include "qapi/qmp/types.h" #include "sysemu.h" #include "block_int.h" #include "qmp-commands.h" diff --git a/blockdev.h b/blockdev.h index d73d552a98..6e36d9f2c2 100644 --- a/blockdev.h +++ b/blockdev.h @@ -11,7 +11,7 @@ #define BLOCKDEV_H #include "block.h" -#include "error.h" +#include "qapi/error.h" #include "qemu-queue.h" void blockdev_mark_auto_del(BlockDriverState *bs); diff --git a/blockjob.c b/blockjob.c index cda12c6933..8c0a286a77 100644 --- a/blockjob.c +++ b/blockjob.c @@ -30,7 +30,7 @@ #include "block.h" #include "blockjob.h" #include "block_int.h" -#include "qjson.h" +#include "qapi/qmp/qjson.h" #include "qemu-coroutine.h" #include "qmp-commands.h" #include "qemu-timer.h" diff --git a/dump-stub.c b/dump-stub.c index 56d4564f0f..0842e6f916 100644 --- a/dump-stub.c +++ b/dump-stub.c @@ -13,7 +13,7 @@ #include "qemu-common.h" #include "dump.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" #include "qmp-commands.h" /* we need this function in hmp.c */ diff --git a/dump.c b/dump.c index 5640c2c2ff..7b45b53a8f 100644 --- a/dump.c +++ b/dump.c @@ -21,7 +21,7 @@ #include "dump.h" #include "sysemu.h" #include "memory_mapping.h" -#include "error.h" +#include "qapi/error.h" #include "qmp-commands.h" #include "gdbstub.h" diff --git a/error.c b/error.c index 128d88cd91..519f6b6ce0 100644 --- a/error.c +++ b/error.c @@ -11,11 +11,11 @@ */ #include "qemu-common.h" -#include "error.h" -#include "qjson.h" -#include "qdict.h" +#include "qapi/error.h" +#include "qapi/qmp/qjson.h" +#include "qapi/qmp/qdict.h" #include "qapi-types.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" struct Error { diff --git a/hmp.h b/hmp.h index 0ab03be982..21f3e05d09 100644 --- a/hmp.h +++ b/hmp.h @@ -16,7 +16,7 @@ #include "qemu-common.h" #include "qapi-types.h" -#include "qdict.h" +#include "qapi/qmp/qdict.h" void hmp_info_name(Monitor *mon); void hmp_info_version(Monitor *mon); diff --git a/hw/ivshmem.c b/hw/ivshmem.c index 5c648d98d3..d15760b314 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -22,7 +22,7 @@ #include "pci/msix.h" #include "kvm.h" #include "migration.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" #include "event_notifier.h" #include "qemu-char.h" diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index c79fca7d68..2a1278f393 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -25,7 +25,7 @@ #include "qemu-timer.h" #include "sysemu.h" #include "mc146818rtc.h" -#include "qapi/qapi-visit-core.h" +#include "qapi/visitor.h" #ifdef TARGET_I386 #include "apic.h" diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug.c index b850400252..5ba7558ecd 100644 --- a/hw/pci/pci-hotplug.c +++ b/hw/pci/pci-hotplug.c @@ -32,7 +32,7 @@ #include "hw/virtio-blk.h" #include "qemu-config.h" #include "blockdev.h" -#include "error.h" +#include "qapi/error.h" #if defined(TARGET_I386) static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon, diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c index 8a2032ca49..b6f4f8510f 100644 --- a/hw/pci/pcie_aer.c +++ b/hw/pci/pcie_aer.c @@ -19,7 +19,7 @@ */ #include "sysemu.h" -#include "qemu-objects.h" +#include "qapi/qmp/types.h" #include "monitor.h" #include "hw/pci/pci_bridge.h" #include "hw/pci/pcie.h" diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c index ea32c31ab6..552ee21f82 100644 --- a/hw/qdev-addr.c +++ b/hw/qdev-addr.c @@ -1,7 +1,7 @@ #include "qdev.h" #include "qdev-addr.h" #include "hwaddr.h" -#include "qapi/qapi-visit-core.h" +#include "qapi/visitor.h" /* --- target physical address --- */ diff --git a/hw/qdev-core.h b/hw/qdev-core.h index d672ccafe6..506977c109 100644 --- a/hw/qdev-core.h +++ b/hw/qdev-core.h @@ -6,7 +6,7 @@ #include "qemu-types.h" #include "qemu/object.h" #include "hw/irq.h" -#include "error.h" +#include "qapi/error.h" enum DevState { DEV_STATE_CREATED = 1, diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 7ab55efe43..ba6c648fed 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -1,10 +1,10 @@ #include "net/net.h" #include "qdev.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" #include "blockdev.h" #include "hw/block-common.h" #include "net/hub.h" -#include "qapi/qapi-visit-core.h" +#include "qapi/visitor.h" #include "qemu-char.h" void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) diff --git a/hw/qdev.c b/hw/qdev.c index 6b91fb987b..0a2a32d5d3 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -28,8 +28,8 @@ #include "net/net.h" #include "qdev.h" #include "sysemu.h" -#include "error.h" -#include "qapi/qapi-visit-core.h" +#include "qapi/error.h" +#include "qapi/visitor.h" int qdev_hotplug = 0; static bool qdev_hot_added = false; diff --git a/hw/vga_int.h b/hw/vga_int.h index ad02404b3c..5efaee81d9 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -25,7 +25,7 @@ #define HW_VGA_INT_H 1 #include -#include "error.h" +#include "qapi/error.h" #include "memory.h" #define ST01_V_RETRACE 0x08 diff --git a/hw/watchdog.c b/hw/watchdog.c index 5c82c17d09..f878bec860 100644 --- a/hw/watchdog.c +++ b/hw/watchdog.c @@ -23,7 +23,7 @@ #include "qemu-option.h" #include "qemu-config.h" #include "qemu-queue.h" -#include "qemu-objects.h" +#include "qapi/qmp/types.h" #include "monitor.h" #include "sysemu.h" #include "hw/watchdog.h" diff --git a/include/net/net.h b/include/net/net.h index 9ff9305d7a..26dd0cf29c 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -3,7 +3,7 @@ #include "qemu-queue.h" #include "qemu-common.h" -#include "qdict.h" +#include "qapi/qmp/qdict.h" #include "qemu-option.h" #include "net/queue.h" #include "vmstate.h" diff --git a/include/net/slirp.h b/include/net/slirp.h index 2ca09b65b7..ac9d44964f 100644 --- a/include/net/slirp.h +++ b/include/net/slirp.h @@ -25,7 +25,7 @@ #define QEMU_NET_SLIRP_H #include "qemu-common.h" -#include "qdict.h" +#include "qapi/qmp/qdict.h" #include "qemu-option.h" #include "qapi-types.h" diff --git a/qapi/qapi-dealloc-visitor.h b/include/qapi/dealloc-visitor.h similarity index 95% rename from qapi/qapi-dealloc-visitor.h rename to include/qapi/dealloc-visitor.h index 5842bc79bd..cf4c36d2d3 100644 --- a/qapi/qapi-dealloc-visitor.h +++ b/include/qapi/dealloc-visitor.h @@ -14,7 +14,7 @@ #ifndef QAPI_DEALLOC_VISITOR_H #define QAPI_DEALLOC_VISITOR_H -#include "qapi-visit-core.h" +#include "qapi/visitor.h" typedef struct QapiDeallocVisitor QapiDeallocVisitor; diff --git a/error.h b/include/qapi/error.h similarity index 100% rename from error.h rename to include/qapi/error.h diff --git a/qapi/opts-visitor.h b/include/qapi/opts-visitor.h similarity index 96% rename from qapi/opts-visitor.h rename to include/qapi/opts-visitor.h index ea1a395573..31fa4c5628 100644 --- a/qapi/opts-visitor.h +++ b/include/qapi/opts-visitor.h @@ -13,7 +13,7 @@ #ifndef OPTS_VISITOR_H #define OPTS_VISITOR_H -#include "qapi-visit-core.h" +#include "qapi/visitor.h" #include "qemu-option.h" typedef struct OptsVisitor OptsVisitor; diff --git a/qapi/qmp-input-visitor.h b/include/qapi/qmp-input-visitor.h similarity index 91% rename from qapi/qmp-input-visitor.h rename to include/qapi/qmp-input-visitor.h index e0a48a5f3b..3ed499cc42 100644 --- a/qapi/qmp-input-visitor.h +++ b/include/qapi/qmp-input-visitor.h @@ -14,8 +14,8 @@ #ifndef QMP_INPUT_VISITOR_H #define QMP_INPUT_VISITOR_H -#include "qapi-visit-core.h" -#include "qobject.h" +#include "qapi/visitor.h" +#include "qapi/qmp/qobject.h" typedef struct QmpInputVisitor QmpInputVisitor; diff --git a/qapi/qmp-output-visitor.h b/include/qapi/qmp-output-visitor.h similarity index 91% rename from qapi/qmp-output-visitor.h rename to include/qapi/qmp-output-visitor.h index 4a649c2504..22667706ab 100644 --- a/qapi/qmp-output-visitor.h +++ b/include/qapi/qmp-output-visitor.h @@ -14,8 +14,8 @@ #ifndef QMP_OUTPUT_VISITOR_H #define QMP_OUTPUT_VISITOR_H -#include "qapi-visit-core.h" -#include "qobject.h" +#include "qapi/visitor.h" +#include "qapi/qmp/qobject.h" typedef struct QmpOutputVisitor QmpOutputVisitor; diff --git a/qapi/qmp-core.h b/include/qapi/qmp/dispatch.h similarity index 93% rename from qapi/qmp-core.h rename to include/qapi/qmp/dispatch.h index 00446cff9b..1ce11f5df0 100644 --- a/qapi/qmp-core.h +++ b/include/qapi/qmp/dispatch.h @@ -14,9 +14,9 @@ #ifndef QMP_CORE_H #define QMP_CORE_H -#include "qobject.h" -#include "qdict.h" -#include "error.h" +#include "qapi/qmp/qobject.h" +#include "qapi/qmp/qdict.h" +#include "qapi/error.h" typedef void (QmpCommandFunc)(QDict *, QObject **, Error **); diff --git a/json-lexer.h b/include/qapi/qmp/json-lexer.h similarity index 94% rename from json-lexer.h rename to include/qapi/qmp/json-lexer.h index 10bc0a7798..cdff0460a8 100644 --- a/json-lexer.h +++ b/include/qapi/qmp/json-lexer.h @@ -14,8 +14,8 @@ #ifndef QEMU_JSON_LEXER_H #define QEMU_JSON_LEXER_H -#include "qstring.h" -#include "qlist.h" +#include "qapi/qmp/qstring.h" +#include "qapi/qmp/qlist.h" typedef enum json_token_type { JSON_OPERATOR = 100, diff --git a/json-parser.h b/include/qapi/qmp/json-parser.h similarity index 90% rename from json-parser.h rename to include/qapi/qmp/json-parser.h index 8f2b5ec4bc..44d88f3468 100644 --- a/json-parser.h +++ b/include/qapi/qmp/json-parser.h @@ -15,8 +15,8 @@ #define QEMU_JSON_PARSER_H #include "qemu-common.h" -#include "qlist.h" -#include "error.h" +#include "qapi/qmp/qlist.h" +#include "qapi/error.h" QObject *json_parser_parse(QList *tokens, va_list *ap); QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp); diff --git a/json-streamer.h b/include/qapi/qmp/json-streamer.h similarity index 93% rename from json-streamer.h rename to include/qapi/qmp/json-streamer.h index f09bc4daec..823f7d7fa4 100644 --- a/json-streamer.h +++ b/include/qapi/qmp/json-streamer.h @@ -14,8 +14,8 @@ #ifndef QEMU_JSON_STREAMER_H #define QEMU_JSON_STREAMER_H -#include "qlist.h" -#include "json-lexer.h" +#include "qapi/qmp/qlist.h" +#include "qapi/qmp/json-lexer.h" typedef struct JSONMessageParser { diff --git a/qbool.h b/include/qapi/qmp/qbool.h similarity index 94% rename from qbool.h rename to include/qapi/qmp/qbool.h index fe66fcd455..c4eaab9bb9 100644 --- a/qbool.h +++ b/include/qapi/qmp/qbool.h @@ -15,7 +15,7 @@ #define QBOOL_H #include -#include "qobject.h" +#include "qapi/qmp/qobject.h" typedef struct QBool { QObject_HEAD; diff --git a/qdict.h b/include/qapi/qmp/qdict.h similarity index 97% rename from qdict.h rename to include/qapi/qmp/qdict.h index 929d8d22f5..c815981d30 100644 --- a/qdict.h +++ b/include/qapi/qmp/qdict.h @@ -13,8 +13,8 @@ #ifndef QDICT_H #define QDICT_H -#include "qobject.h" -#include "qlist.h" +#include "qapi/qmp/qobject.h" +#include "qapi/qmp/qlist.h" #include "qemu-queue.h" #include diff --git a/qerror.h b/include/qapi/qmp/qerror.h similarity index 99% rename from qerror.h rename to include/qapi/qmp/qerror.h index 8db4309aef..d912297590 100644 --- a/qerror.h +++ b/include/qapi/qmp/qerror.h @@ -12,10 +12,10 @@ #ifndef QERROR_H #define QERROR_H -#include "qdict.h" -#include "qstring.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qstring.h" #include "qemu-error.h" -#include "error.h" +#include "qapi/error.h" #include "qapi-types.h" #include diff --git a/qfloat.h b/include/qapi/qmp/qfloat.h similarity index 94% rename from qfloat.h rename to include/qapi/qmp/qfloat.h index 9d6787659c..a8658443dc 100644 --- a/qfloat.h +++ b/include/qapi/qmp/qfloat.h @@ -15,7 +15,7 @@ #define QFLOAT_H #include -#include "qobject.h" +#include "qapi/qmp/qobject.h" typedef struct QFloat { QObject_HEAD; diff --git a/qint.h b/include/qapi/qmp/qint.h similarity index 94% rename from qint.h rename to include/qapi/qmp/qint.h index 6b1a15c088..48a41b0f2a 100644 --- a/qint.h +++ b/include/qapi/qmp/qint.h @@ -14,7 +14,7 @@ #define QINT_H #include -#include "qobject.h" +#include "qapi/qmp/qobject.h" typedef struct QInt { QObject_HEAD; diff --git a/qjson.h b/include/qapi/qmp/qjson.h similarity index 91% rename from qjson.h rename to include/qapi/qmp/qjson.h index 1190d8a86c..0473374bf2 100644 --- a/qjson.h +++ b/include/qapi/qmp/qjson.h @@ -16,8 +16,8 @@ #include #include "compiler.h" -#include "qobject.h" -#include "qstring.h" +#include "qapi/qmp/qobject.h" +#include "qapi/qmp/qstring.h" QObject *qobject_from_json(const char *string) GCC_FMT_ATTR(1, 0); QObject *qobject_from_jsonf(const char *string, ...) GCC_FMT_ATTR(1, 2); diff --git a/qlist.h b/include/qapi/qmp/qlist.h similarity index 98% rename from qlist.h rename to include/qapi/qmp/qlist.h index 74089471df..ffa0846d48 100644 --- a/qlist.h +++ b/include/qapi/qmp/qlist.h @@ -13,7 +13,7 @@ #ifndef QLIST_H #define QLIST_H -#include "qobject.h" +#include "qapi/qmp/qobject.h" #include "qemu-queue.h" #include "qemu-queue.h" diff --git a/qobject.h b/include/qapi/qmp/qobject.h similarity index 100% rename from qobject.h rename to include/qapi/qmp/qobject.h diff --git a/qstring.h b/include/qapi/qmp/qstring.h similarity index 96% rename from qstring.h rename to include/qapi/qmp/qstring.h index 84ccd96d61..0e690f4849 100644 --- a/qstring.h +++ b/include/qapi/qmp/qstring.h @@ -14,7 +14,7 @@ #define QSTRING_H #include -#include "qobject.h" +#include "qapi/qmp/qobject.h" typedef struct QString { QObject_HEAD; diff --git a/qemu-objects.h b/include/qapi/qmp/types.h similarity index 60% rename from qemu-objects.h rename to include/qapi/qmp/types.h index c53fbaa217..7782ec5a60 100644 --- a/qemu-objects.h +++ b/include/qapi/qmp/types.h @@ -13,13 +13,13 @@ #ifndef QEMU_OBJECTS_H #define QEMU_OBJECTS_H -#include "qobject.h" -#include "qint.h" -#include "qfloat.h" -#include "qbool.h" -#include "qstring.h" -#include "qdict.h" -#include "qlist.h" -#include "qjson.h" +#include "qapi/qmp/qobject.h" +#include "qapi/qmp/qint.h" +#include "qapi/qmp/qfloat.h" +#include "qapi/qmp/qbool.h" +#include "qapi/qmp/qstring.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qlist.h" +#include "qapi/qmp/qjson.h" #endif /* QEMU_OBJECTS_H */ diff --git a/qapi/string-input-visitor.h b/include/qapi/string-input-visitor.h similarity index 95% rename from qapi/string-input-visitor.h rename to include/qapi/string-input-visitor.h index d269d42cef..089243c09e 100644 --- a/qapi/string-input-visitor.h +++ b/include/qapi/string-input-visitor.h @@ -13,7 +13,7 @@ #ifndef STRING_INPUT_VISITOR_H #define STRING_INPUT_VISITOR_H -#include "qapi-visit-core.h" +#include "qapi/visitor.h" typedef struct StringInputVisitor StringInputVisitor; diff --git a/qapi/string-output-visitor.h b/include/qapi/string-output-visitor.h similarity index 95% rename from qapi/string-output-visitor.h rename to include/qapi/string-output-visitor.h index 8868454110..ec81e42b60 100644 --- a/qapi/string-output-visitor.h +++ b/include/qapi/string-output-visitor.h @@ -13,7 +13,7 @@ #ifndef STRING_OUTPUT_VISITOR_H #define STRING_OUTPUT_VISITOR_H -#include "qapi-visit-core.h" +#include "qapi/visitor.h" typedef struct StringOutputVisitor StringOutputVisitor; diff --git a/qapi/qapi-visit-impl.h b/include/qapi/visitor-impl.h similarity index 98% rename from qapi/qapi-visit-impl.h rename to include/qapi/visitor-impl.h index 9337d62e75..5159964863 100644 --- a/qapi/qapi-visit-impl.h +++ b/include/qapi/visitor-impl.h @@ -12,8 +12,8 @@ #ifndef QAPI_VISITOR_IMPL_H #define QAPI_VISITOR_IMPL_H -#include "error.h" -#include "qapi/qapi-visit-core.h" +#include "qapi/error.h" +#include "qapi/visitor.h" struct Visitor { diff --git a/qapi/qapi-visit-core.h b/include/qapi/visitor.h similarity index 99% rename from qapi/qapi-visit-core.h rename to include/qapi/visitor.h index 602debe753..1fef18c08f 100644 --- a/qapi/qapi-visit-core.h +++ b/include/qapi/visitor.h @@ -13,7 +13,7 @@ #ifndef QAPI_VISITOR_CORE_H #define QAPI_VISITOR_CORE_H -#include "error.h" +#include "qapi/error.h" #include typedef struct GenericList diff --git a/include/qemu/rng.h b/include/qemu/rng.h index d094bf8d4c..37912971e0 100644 --- a/include/qemu/rng.h +++ b/include/qemu/rng.h @@ -15,7 +15,7 @@ #include "qemu/object.h" #include "qemu-common.h" -#include "error.h" +#include "qapi/error.h" #define TYPE_RNG_BACKEND "rng-backend" #define RNG_BACKEND(obj) \ diff --git a/include/ui/console.h b/include/ui/console.h index 777881d4a3..eff5cc92d6 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -2,12 +2,12 @@ #define CONSOLE_H #include "ui/qemu-pixman.h" -#include "qdict.h" +#include "qapi/qmp/qdict.h" #include "notify.h" #include "monitor.h" #include "trace.h" #include "qapi-types.h" -#include "error.h" +#include "qapi/error.h" /* keyboard/mouse support */ diff --git a/json-lexer.c b/json-lexer.c index 3cd3285825..440df60392 100644 --- a/json-lexer.c +++ b/json-lexer.c @@ -11,12 +11,12 @@ * */ -#include "qstring.h" -#include "qlist.h" -#include "qdict.h" -#include "qint.h" +#include "qapi/qmp/qstring.h" +#include "qapi/qmp/qlist.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qint.h" #include "qemu-common.h" -#include "json-lexer.h" +#include "qapi/qmp/json-lexer.h" #define MAX_TOKEN_SIZE (64ULL << 20) diff --git a/json-parser.c b/json-parser.c index 457291b161..05279c11eb 100644 --- a/json-parser.c +++ b/json-parser.c @@ -14,15 +14,15 @@ #include #include "qemu-common.h" -#include "qstring.h" -#include "qint.h" -#include "qdict.h" -#include "qlist.h" -#include "qfloat.h" -#include "qbool.h" -#include "json-parser.h" -#include "json-lexer.h" -#include "qerror.h" +#include "qapi/qmp/qstring.h" +#include "qapi/qmp/qint.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qlist.h" +#include "qapi/qmp/qfloat.h" +#include "qapi/qmp/qbool.h" +#include "qapi/qmp/json-parser.h" +#include "qapi/qmp/json-lexer.h" +#include "qapi/qmp/qerror.h" typedef struct JSONParserContext { diff --git a/json-streamer.c b/json-streamer.c index c255c7818f..1b2f9b1d10 100644 --- a/json-streamer.c +++ b/json-streamer.c @@ -11,12 +11,12 @@ * */ -#include "qlist.h" -#include "qint.h" -#include "qdict.h" +#include "qapi/qmp/qlist.h" +#include "qapi/qmp/qint.h" +#include "qapi/qmp/qdict.h" #include "qemu-common.h" -#include "json-lexer.h" -#include "json-streamer.h" +#include "qapi/qmp/json-lexer.h" +#include "qapi/qmp/json-streamer.h" #define MAX_TOKEN_SIZE (64ULL << 20) #define MAX_NESTING (1ULL << 10) diff --git a/migration.h b/migration.h index c3a23cc6c8..af444d444b 100644 --- a/migration.h +++ b/migration.h @@ -14,10 +14,10 @@ #ifndef QEMU_MIGRATION_H #define QEMU_MIGRATION_H -#include "qdict.h" +#include "qapi/qmp/qdict.h" #include "qemu-common.h" #include "notify.h" -#include "error.h" +#include "qapi/error.h" #include "vmstate.h" #include "qapi-types.h" diff --git a/monitor.c b/monitor.c index 6546f8c30b..7d5c8a622c 100644 --- a/monitor.c +++ b/monitor.c @@ -47,14 +47,14 @@ #include "migration.h" #include "kvm.h" #include "acl.h" -#include "qint.h" -#include "qfloat.h" -#include "qlist.h" -#include "qbool.h" -#include "qstring.h" -#include "qjson.h" -#include "json-streamer.h" -#include "json-parser.h" +#include "qapi/qmp/qint.h" +#include "qapi/qmp/qfloat.h" +#include "qapi/qmp/qlist.h" +#include "qapi/qmp/qbool.h" +#include "qapi/qmp/qstring.h" +#include "qapi/qmp/qjson.h" +#include "qapi/qmp/json-streamer.h" +#include "qapi/qmp/json-parser.h" #include "osdep.h" #include "cpu.h" #include "trace.h" diff --git a/monitor.h b/monitor.h index 4595c217ed..7c29d9db34 100644 --- a/monitor.h +++ b/monitor.h @@ -2,8 +2,8 @@ #define MONITOR_H #include "qemu-common.h" -#include "qerror.h" -#include "qdict.h" +#include "qapi/qmp/qerror.h" +#include "qapi/qmp/qdict.h" #include "block.h" #include "readline.h" diff --git a/net/net.c b/net/net.c index a4395be140..ead7e96fe1 100644 --- a/net/net.c +++ b/net/net.c @@ -38,7 +38,7 @@ #include "iov.h" #include "qapi-visit.h" #include "qapi/opts-visitor.h" -#include "qapi/qapi-dealloc-visitor.h" +#include "qapi/dealloc-visitor.h" /* Net bridge is currently not supported for W32. */ #if !defined(_WIN32) diff --git a/pixman b/pixman index a5e5179b56..97336fad32 160000 --- a/pixman +++ b/pixman @@ -1 +1 @@ -Subproject commit a5e5179b5624c99c812e9bf6e7b907e355a811e8 +Subproject commit 97336fad32acf802003855cd8bd6477fa49a12e3 diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index 6ccb8a1c33..f8149ce455 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -11,11 +11,11 @@ */ #include "qemu-common.h" -#include "qerror.h" -#include "opts-visitor.h" +#include "qapi/qmp/qerror.h" +#include "qapi/opts-visitor.h" #include "qemu-queue.h" #include "qemu-option-internal.h" -#include "qapi-visit-impl.h" +#include "qapi/visitor-impl.h" struct OptsVisitor diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c index 7c44042619..98f2a58efd 100644 --- a/qapi/qapi-dealloc-visitor.c +++ b/qapi/qapi-dealloc-visitor.c @@ -11,11 +11,11 @@ * */ -#include "qapi-dealloc-visitor.h" +#include "qapi/dealloc-visitor.h" #include "qemu-queue.h" #include "qemu-common.h" -#include "qemu-objects.h" -#include "qapi-visit-impl.h" +#include "qapi/qmp/types.h" +#include "qapi/visitor-impl.h" typedef struct StackEntry { diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index 4649fb71b7..401ee6e597 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -12,9 +12,9 @@ */ #include "qemu-common.h" -#include "qerror.h" -#include "qapi/qapi-visit-core.h" -#include "qapi/qapi-visit-impl.h" +#include "qapi/qmp/qerror.h" +#include "qapi/visitor.h" +#include "qapi/visitor-impl.h" void visit_start_handle(Visitor *v, void **obj, const char *kind, const char *name, Error **errp) diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 4085994686..921de33bce 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -11,12 +11,12 @@ * */ -#include "qemu-objects.h" -#include "qapi/qmp-core.h" -#include "json-parser.h" +#include "qapi/qmp/types.h" +#include "qapi/qmp/dispatch.h" +#include "qapi/qmp/json-parser.h" #include "qapi-types.h" -#include "error.h" -#include "qerror.h" +#include "qapi/error.h" +#include "qapi/qmp/qerror.h" static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp) { diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c index 107d8d361b..8087909036 100644 --- a/qapi/qmp-input-visitor.c +++ b/qapi/qmp-input-visitor.c @@ -11,12 +11,12 @@ * */ -#include "qmp-input-visitor.h" -#include "qapi/qapi-visit-impl.h" +#include "qapi/qmp-input-visitor.h" +#include "qapi/visitor-impl.h" #include "qemu-queue.h" #include "qemu-common.h" -#include "qemu-objects.h" -#include "qerror.h" +#include "qapi/qmp/types.h" +#include "qapi/qmp/qerror.h" #define QIV_STACK_SIZE 1024 diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c index 2bce9d5db1..8015e3f88d 100644 --- a/qapi/qmp-output-visitor.c +++ b/qapi/qmp-output-visitor.c @@ -11,12 +11,12 @@ * */ -#include "qmp-output-visitor.h" -#include "qapi/qapi-visit-impl.h" +#include "qapi/qmp-output-visitor.h" +#include "qapi/visitor-impl.h" #include "qemu-queue.h" #include "qemu-common.h" -#include "qemu-objects.h" -#include "qerror.h" +#include "qapi/qmp/types.h" +#include "qapi/qmp/qerror.h" typedef struct QStackEntry { diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c index c2c31b420d..70cdbca470 100644 --- a/qapi/qmp-registry.c +++ b/qapi/qmp-registry.c @@ -14,7 +14,7 @@ #include #include -#include "qapi/qmp-core.h" +#include "qapi/qmp/dispatch.h" static QTAILQ_HEAD(QmpCommandList, QmpCommand) qmp_commands = QTAILQ_HEAD_INITIALIZER(qmp_commands); diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c index 497eb9a60a..8f1bc41333 100644 --- a/qapi/string-input-visitor.c +++ b/qapi/string-input-visitor.c @@ -11,9 +11,9 @@ */ #include "qemu-common.h" -#include "string-input-visitor.h" -#include "qapi/qapi-visit-impl.h" -#include "qerror.h" +#include "qapi/string-input-visitor.h" +#include "qapi/visitor-impl.h" +#include "qapi/qmp/qerror.h" struct StringInputVisitor { diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c index 34e525eadd..921653d425 100644 --- a/qapi/string-output-visitor.c +++ b/qapi/string-output-visitor.c @@ -11,9 +11,9 @@ */ #include "qemu-common.h" -#include "string-output-visitor.h" -#include "qapi/qapi-visit-impl.h" -#include "qerror.h" +#include "qapi/string-output-visitor.h" +#include "qapi/visitor-impl.h" +#include "qapi/qmp/qerror.h" struct StringOutputVisitor { diff --git a/qbool.c b/qbool.c index 590cd716ea..a3d2afa827 100644 --- a/qbool.c +++ b/qbool.c @@ -11,8 +11,8 @@ * */ -#include "qbool.h" -#include "qobject.h" +#include "qapi/qmp/qbool.h" +#include "qapi/qmp/qobject.h" #include "qemu-common.h" static void qbool_destroy_obj(QObject *obj); diff --git a/qdict.c b/qdict.c index 4bf308b61c..fa7a62cff4 100644 --- a/qdict.c +++ b/qdict.c @@ -10,12 +10,12 @@ * See the COPYING.LIB file in the top-level directory. */ -#include "qint.h" -#include "qfloat.h" -#include "qdict.h" -#include "qbool.h" -#include "qstring.h" -#include "qobject.h" +#include "qapi/qmp/qint.h" +#include "qapi/qmp/qfloat.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qbool.h" +#include "qapi/qmp/qstring.h" +#include "qapi/qmp/qobject.h" #include "qemu-queue.h" #include "qemu-common.h" diff --git a/qemu-char.h b/qemu-char.h index a121e04cdc..3e230a1319 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -6,8 +6,8 @@ #include "qemu-option.h" #include "qemu-config.h" #include "qemu-aio.h" -#include "qobject.h" -#include "qstring.h" +#include "qapi/qmp/qobject.h" +#include "qapi/qmp/qstring.h" #include "main-loop.h" /* character device */ diff --git a/qemu-config.c b/qemu-config.c index b4ce0d8034..ceec6bd155 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -3,7 +3,7 @@ #include "qemu-option.h" #include "qemu-config.h" #include "hw/qdev.h" -#include "error.h" +#include "qapi/error.h" static QemuOptsList qemu_drive_opts = { .name = "drive", diff --git a/qemu-config.h b/qemu-config.h index eb50eca838..584491a29b 100644 --- a/qemu-config.h +++ b/qemu-config.h @@ -3,7 +3,7 @@ #include #include "qemu-option.h" -#include "error.h" +#include "qapi/error.h" #include "qemu-option.h" extern QemuOptsList qemu_fsdev_opts; diff --git a/qemu-img.c b/qemu-img.c index c989a52564..a13bc788cf 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -23,7 +23,7 @@ */ #include "qapi-visit.h" #include "qapi/qmp-output-visitor.h" -#include "qjson.h" +#include "qapi/qmp/qjson.h" #include "qemu-common.h" #include "qemu-option.h" #include "qemu-error.h" diff --git a/qemu-option.c b/qemu-option.c index 94557cfde7..ebd3537063 100644 --- a/qemu-option.c +++ b/qemu-option.c @@ -28,9 +28,9 @@ #include "qemu-common.h" #include "qemu-error.h" -#include "qemu-objects.h" -#include "error.h" -#include "qerror.h" +#include "qapi/qmp/types.h" +#include "qapi/error.h" +#include "qapi/qmp/qerror.h" #include "qemu-option-internal.h" /* diff --git a/qemu-option.h b/qemu-option.h index 002dd07ee5..ca0dc041dd 100644 --- a/qemu-option.h +++ b/qemu-option.h @@ -28,8 +28,8 @@ #include #include "qemu-queue.h" -#include "error.h" -#include "qdict.h" +#include "qapi/error.h" +#include "qapi/qmp/qdict.h" enum QEMUOptionParType { OPT_FLAG, diff --git a/qemu_socket.h b/qemu_socket.h index 02490ad06c..42899fe138 100644 --- a/qemu_socket.h +++ b/qemu_socket.h @@ -27,8 +27,8 @@ int inet_aton(const char *cp, struct in_addr *ia); #endif /* !_WIN32 */ #include "qemu-option.h" -#include "error.h" -#include "qerror.h" +#include "qapi/error.h" +#include "qapi/qmp/qerror.h" /* misc helpers */ int qemu_socket(int domain, int type, int protocol); diff --git a/qerror.c b/qerror.c index 08185047b4..8c78104277 100644 --- a/qerror.c +++ b/qerror.c @@ -11,8 +11,8 @@ */ #include "monitor.h" -#include "qjson.h" -#include "qerror.h" +#include "qapi/qmp/qjson.h" +#include "qapi/qmp/qerror.h" #include "qemu-common.h" static void qerror_destroy_obj(QObject *obj); diff --git a/qfloat.c b/qfloat.c index 98338f3b71..7de0992dba 100644 --- a/qfloat.c +++ b/qfloat.c @@ -11,8 +11,8 @@ * */ -#include "qfloat.h" -#include "qobject.h" +#include "qapi/qmp/qfloat.h" +#include "qapi/qmp/qobject.h" #include "qemu-common.h" static void qfloat_destroy_obj(QObject *obj); diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 726930a909..cedf2ccf28 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -17,7 +17,7 @@ #include #include "qga/guest-agent-core.h" #include "qga-qmp-commands.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" #include "qemu-queue.h" #include "host-utils.h" diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 5bd8fb27f2..7e8ecb3b40 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -16,7 +16,7 @@ #include #include "qga/guest-agent-core.h" #include "qga-qmp-commands.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" #ifndef SHTDN_REASON_FLAG_PLANNED #define SHTDN_REASON_FLAG_PLANNED 0x80000000 diff --git a/qga/commands.c b/qga/commands.c index 46b0b083bc..7ffb35e4af 100644 --- a/qga/commands.c +++ b/qga/commands.c @@ -13,7 +13,7 @@ #include #include "qga/guest-agent-core.h" #include "qga-qmp-commands.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" /* Note: in some situations, like with the fsfreeze, logging may be * temporarilly disabled. if it is necessary that a command be able diff --git a/qga/guest-agent-core.h b/qga/guest-agent-core.h index 49a7abee95..8934163375 100644 --- a/qga/guest-agent-core.h +++ b/qga/guest-agent-core.h @@ -10,7 +10,7 @@ * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. */ -#include "qapi/qmp-core.h" +#include "qapi/qmp/dispatch.h" #include "qemu-common.h" #define QGA_READ_COUNT_DEFAULT 4096 diff --git a/qga/main.c b/qga/main.c index 9b59a52461..ead58cc11f 100644 --- a/qga/main.c +++ b/qga/main.c @@ -20,15 +20,15 @@ #include #include #endif -#include "json-streamer.h" -#include "json-parser.h" -#include "qint.h" -#include "qjson.h" +#include "qapi/qmp/json-streamer.h" +#include "qapi/qmp/json-parser.h" +#include "qapi/qmp/qint.h" +#include "qapi/qmp/qjson.h" #include "qga/guest-agent-core.h" #include "module.h" #include "signal.h" -#include "qerror.h" -#include "qapi/qmp-core.h" +#include "qapi/qmp/qerror.h" +#include "qapi/qmp/dispatch.h" #include "qga/channel.h" #ifdef _WIN32 #include "qga/service-win32.h" diff --git a/qint.c b/qint.c index ee51804fbe..86b9b04f0b 100644 --- a/qint.c +++ b/qint.c @@ -10,8 +10,8 @@ * See the COPYING.LIB file in the top-level directory. */ -#include "qint.h" -#include "qobject.h" +#include "qapi/qmp/qint.h" +#include "qapi/qmp/qobject.h" #include "qemu-common.h" static void qint_destroy_obj(QObject *obj); diff --git a/qjson.c b/qjson.c index f9c8e77516..83a6b4f7c1 100644 --- a/qjson.c +++ b/qjson.c @@ -11,15 +11,15 @@ * */ -#include "json-lexer.h" -#include "json-parser.h" -#include "json-streamer.h" -#include "qjson.h" -#include "qint.h" -#include "qlist.h" -#include "qbool.h" -#include "qfloat.h" -#include "qdict.h" +#include "qapi/qmp/json-lexer.h" +#include "qapi/qmp/json-parser.h" +#include "qapi/qmp/json-streamer.h" +#include "qapi/qmp/qjson.h" +#include "qapi/qmp/qint.h" +#include "qapi/qmp/qlist.h" +#include "qapi/qmp/qbool.h" +#include "qapi/qmp/qfloat.h" +#include "qapi/qmp/qdict.h" typedef struct JSONParsingState { diff --git a/qlist.c b/qlist.c index b48ec5b914..c5ac2115af 100644 --- a/qlist.c +++ b/qlist.c @@ -10,8 +10,8 @@ * See the COPYING.LIB file in the top-level directory. */ -#include "qlist.h" -#include "qobject.h" +#include "qapi/qmp/qlist.h" +#include "qapi/qmp/qobject.h" #include "qemu-queue.h" #include "qemu-common.h" diff --git a/qom/object.c b/qom/object.c index 8d3036dcf4..932f8b30de 100644 --- a/qom/object.c +++ b/qom/object.c @@ -12,18 +12,18 @@ #include "qemu/object.h" #include "qemu-common.h" -#include "qapi/qapi-visit-core.h" +#include "qapi/visitor.h" #include "qapi/string-input-visitor.h" #include "qapi/string-output-visitor.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" /* TODO: replace QObject with a simpler visitor to avoid a dependency * of the QOM core on QObject? */ #include "qemu/qom-qobject.h" -#include "qobject.h" -#include "qbool.h" -#include "qint.h" -#include "qstring.h" +#include "qapi/qmp/qobject.h" +#include "qapi/qmp/qbool.h" +#include "qapi/qmp/qint.h" +#include "qapi/qmp/qstring.h" #define MAX_INTERFACES 32 diff --git a/qom/qom-qobject.c b/qom/qom-qobject.c index 0689914e15..f0fa652157 100644 --- a/qom/qom-qobject.c +++ b/qom/qom-qobject.c @@ -12,7 +12,7 @@ #include "qemu-common.h" #include "qemu/object.h" #include "qemu/qom-qobject.h" -#include "qapi/qapi-visit-core.h" +#include "qapi/visitor.h" #include "qapi/qmp-input-visitor.h" #include "qapi/qmp-output-visitor.h" diff --git a/qstring.c b/qstring.c index b7e12e4015..5f7376c336 100644 --- a/qstring.c +++ b/qstring.c @@ -10,8 +10,8 @@ * See the COPYING.LIB file in the top-level directory. */ -#include "qobject.h" -#include "qstring.h" +#include "qapi/qmp/qobject.h" +#include "qapi/qmp/qstring.h" #include "qemu-common.h" static void qstring_destroy_obj(QObject *obj); diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index 5d034c2c21..eccc28daee 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -342,8 +342,8 @@ def gen_command_decl_prologue(header, guard, prefix=""): #define %(guard)s #include "%(prefix)sqapi-types.h" -#include "qdict.h" -#include "error.h" +#include "qapi/qmp/qdict.h" +#include "qapi/error.h" ''', header=basename(header), guard=guardname(header), prefix=prefix) @@ -368,13 +368,13 @@ def gen_command_def_prologue(prefix="", proxy=False): #include "qemu-common.h" #include "module.h" -#include "qerror.h" -#include "qemu-objects.h" -#include "qapi/qmp-core.h" -#include "qapi/qapi-visit-core.h" +#include "qapi/qmp/qerror.h" +#include "qapi/qmp/types.h" +#include "qapi/qmp/dispatch.h" +#include "qapi/visitor.h" #include "qapi/qmp-output-visitor.h" #include "qapi/qmp-input-visitor.h" -#include "qapi/qapi-dealloc-visitor.h" +#include "qapi/dealloc-visitor.h" #include "%(prefix)sqapi-types.h" #include "%(prefix)sqapi-visit.h" diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index 6bc2391874..9e19920970 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -248,7 +248,7 @@ fdef.write(mcgen(''' * */ -#include "qapi/qapi-dealloc-visitor.h" +#include "qapi/dealloc-visitor.h" #include "%(prefix)sqapi-types.h" #include "%(prefix)sqapi-visit.h" diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index f1aabb3813..a276540a18 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -322,7 +322,7 @@ fdecl.write(mcgen(''' #ifndef %(guard)s #define %(guard)s -#include "qapi/qapi-visit-core.h" +#include "qapi/visitor.h" #include "%(prefix)sqapi-types.h" ''', prefix=prefix, guard=guardname(h_file))) diff --git a/stubs/arch-query-cpu-def.c b/stubs/arch-query-cpu-def.c index 47b524628d..6eca8527d2 100644 --- a/stubs/arch-query-cpu-def.c +++ b/stubs/arch-query-cpu-def.c @@ -1,6 +1,6 @@ #include "qemu-common.h" #include "arch_init.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) { diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h index 5901140480..3a7bc6aef4 100644 --- a/target-i386/cpu-qom.h +++ b/target-i386/cpu-qom.h @@ -22,7 +22,7 @@ #include "qemu/cpu.h" #include "cpu.h" -#include "error.h" +#include "qapi/error.h" #ifdef TARGET_X86_64 #define TYPE_X86_CPU "x86_64-cpu" diff --git a/target-i386/cpu.c b/target-i386/cpu.c index e968006ed0..150c4dfb0c 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -26,9 +26,9 @@ #include "qemu-option.h" #include "qemu-config.h" -#include "qerror.h" +#include "qapi/qmp/qerror.h" -#include "qapi/qapi-visit-core.h" +#include "qapi/visitor.h" #include "arch_init.h" #include "hyperv.h" diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h index ebb5ad3124..c7b1750153 100644 --- a/target-openrisc/cpu.h +++ b/target-openrisc/cpu.h @@ -33,7 +33,7 @@ struct OpenRISCCPU; #include "cpu-defs.h" #include "softfloat.h" #include "qemu/cpu.h" -#include "error.h" +#include "qapi/error.h" #define TYPE_OPENRISC_CPU "or32-cpu" diff --git a/tests/check-qdict.c b/tests/check-qdict.c index fc0d276538..dc5f05a85f 100644 --- a/tests/check-qdict.c +++ b/tests/check-qdict.c @@ -11,9 +11,9 @@ */ #include -#include "qint.h" -#include "qdict.h" -#include "qstring.h" +#include "qapi/qmp/qint.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qstring.h" #include "qemu-common.h" /* diff --git a/tests/check-qfloat.c b/tests/check-qfloat.c index cdc66ea10b..6404ac8df6 100644 --- a/tests/check-qfloat.c +++ b/tests/check-qfloat.c @@ -12,7 +12,7 @@ */ #include -#include "qfloat.h" +#include "qapi/qmp/qfloat.h" #include "qemu-common.h" /* diff --git a/tests/check-qint.c b/tests/check-qint.c index 5a27119ae2..86868844ab 100644 --- a/tests/check-qint.c +++ b/tests/check-qint.c @@ -11,7 +11,7 @@ */ #include -#include "qint.h" +#include "qapi/qmp/qint.h" #include "qemu-common.h" /* diff --git a/tests/check-qjson.c b/tests/check-qjson.c index 3b896f5f9c..32ffb436df 100644 --- a/tests/check-qjson.c +++ b/tests/check-qjson.c @@ -10,13 +10,13 @@ */ #include -#include "qstring.h" -#include "qint.h" -#include "qdict.h" -#include "qlist.h" -#include "qfloat.h" -#include "qbool.h" -#include "qjson.h" +#include "qapi/qmp/qstring.h" +#include "qapi/qmp/qint.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qlist.h" +#include "qapi/qmp/qfloat.h" +#include "qapi/qmp/qbool.h" +#include "qapi/qmp/qjson.h" #include "qemu-common.h" diff --git a/tests/check-qlist.c b/tests/check-qlist.c index 501ba262da..b9c05d43fd 100644 --- a/tests/check-qlist.c +++ b/tests/check-qlist.c @@ -11,8 +11,8 @@ */ #include -#include "qint.h" -#include "qlist.h" +#include "qapi/qmp/qint.h" +#include "qapi/qmp/qlist.h" /* * Public Interface test-cases diff --git a/tests/check-qstring.c b/tests/check-qstring.c index addad6c673..95dc9e3e7b 100644 --- a/tests/check-qstring.c +++ b/tests/check-qstring.c @@ -11,7 +11,7 @@ */ #include -#include "qstring.h" +#include "qapi/qmp/qstring.h" #include "qemu-common.h" /* diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c index bf41034c62..61b533a071 100644 --- a/tests/test-qmp-commands.c +++ b/tests/test-qmp-commands.c @@ -1,8 +1,8 @@ #include #include "qemu-common.h" -#include "qemu-objects.h" +#include "qapi/qmp/types.h" #include "test-qmp-commands.h" -#include "qapi/qmp-core.h" +#include "qapi/qmp/dispatch.h" #include "module.h" #include "qapi/qmp-input-visitor.h" #include "tests/test-qapi-types.h" diff --git a/tests/test-qmp-input-strict.c b/tests/test-qmp-input-strict.c index 86f24d821c..6f68963a3d 100644 --- a/tests/test-qmp-input-strict.c +++ b/tests/test-qmp-input-strict.c @@ -18,7 +18,7 @@ #include "qapi/qmp-input-visitor.h" #include "test-qapi-types.h" #include "test-qapi-visit.h" -#include "qemu-objects.h" +#include "qapi/qmp/types.h" typedef struct TestInputVisitorData { QObject *obj; diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c index 6568c9907c..955a4c0b0a 100644 --- a/tests/test-qmp-input-visitor.c +++ b/tests/test-qmp-input-visitor.c @@ -17,7 +17,7 @@ #include "qapi/qmp-input-visitor.h" #include "test-qapi-types.h" #include "test-qapi-visit.h" -#include "qemu-objects.h" +#include "qapi/qmp/types.h" typedef struct TestInputVisitorData { QObject *obj; diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c index 84b1f41894..71367e6efa 100644 --- a/tests/test-qmp-output-visitor.c +++ b/tests/test-qmp-output-visitor.c @@ -16,7 +16,7 @@ #include "qapi/qmp-output-visitor.h" #include "test-qapi-types.h" #include "test-qapi-visit.h" -#include "qemu-objects.h" +#include "qapi/qmp/types.h" typedef struct TestOutputVisitorData { QmpOutputVisitor *qov; diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-visitor.c index 36b3792980..899feda579 100644 --- a/tests/test-string-input-visitor.c +++ b/tests/test-string-input-visitor.c @@ -17,7 +17,7 @@ #include "qapi/string-input-visitor.h" #include "test-qapi-types.h" #include "test-qapi-visit.h" -#include "qemu-objects.h" +#include "qapi/qmp/types.h" typedef struct TestInputVisitorData { StringInputVisitor *siv; diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c index afb557a00f..79d815f888 100644 --- a/tests/test-string-output-visitor.c +++ b/tests/test-string-output-visitor.c @@ -16,7 +16,7 @@ #include "qapi/string-output-visitor.h" #include "test-qapi-types.h" #include "test-qapi-visit.h" -#include "qemu-objects.h" +#include "qapi/qmp/types.h" typedef struct TestOutputVisitorData { StringOutputVisitor *sov; diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c index a251f878e1..3c6b8df607 100644 --- a/tests/test-visitor-serialization.c +++ b/tests/test-visitor-serialization.c @@ -18,7 +18,7 @@ #include "qemu-common.h" #include "test-qapi-types.h" #include "test-qapi-visit.h" -#include "qemu-objects.h" +#include "qapi/qmp/types.h" #include "qapi/qmp-input-visitor.h" #include "qapi/qmp-output-visitor.h" #include "qapi/string-input-visitor.h" diff --git a/ui/input.c b/ui/input.c index 58d3b4709c..65950af9af 100644 --- a/ui/input.c +++ b/ui/input.c @@ -25,7 +25,7 @@ #include "sysemu.h" #include "monitor.h" #include "ui/console.h" -#include "error.h" +#include "qapi/error.h" #include "qmp-commands.h" #include "qapi-types.h" diff --git a/ui/spice-core.c b/ui/spice-core.c index ec925ecbb0..0550805b38 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -29,10 +29,10 @@ #include "qemu-x509.h" #include "qemu_socket.h" #include "qmp-commands.h" -#include "qint.h" -#include "qbool.h" -#include "qstring.h" -#include "qjson.h" +#include "qapi/qmp/qint.h" +#include "qapi/qmp/qbool.h" +#include "qapi/qmp/qstring.h" +#include "qapi/qmp/qjson.h" #include "notify.h" #include "migration.h" #include "monitor.h" diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c index 62d0fde77f..09199ef584 100644 --- a/ui/vnc-enc-tight.c +++ b/ui/vnc-enc-tight.c @@ -45,7 +45,7 @@ #endif #include "bswap.h" -#include "qint.h" +#include "qapi/qmp/qint.h" #include "vnc.h" #include "vnc-enc-tight.h" #include "vnc-palette.h" diff --git a/ui/vnc-palette.h b/ui/vnc-palette.h index b82dc5db91..bfc7fe642e 100644 --- a/ui/vnc-palette.h +++ b/ui/vnc-palette.h @@ -29,7 +29,7 @@ #ifndef VNC_PALETTE_H #define VNC_PALETTE_H -#include "qlist.h" +#include "qapi/qmp/qlist.h" #include "qemu-queue.h" #include #include diff --git a/ui/vnc.c b/ui/vnc.c index 04afcffc52..dad2ddee29 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -30,7 +30,7 @@ #include "qemu_socket.h" #include "qemu-timer.h" #include "acl.h" -#include "qemu-objects.h" +#include "qapi/qmp/types.h" #include "qmp-commands.h" #include "osdep.h" diff --git a/vl.c b/vl.c index 6713220905..975767a44b 100644 --- a/vl.c +++ b/vl.c @@ -143,7 +143,7 @@ int main(int argc, char **argv) #include "audio/audio.h" #include "migration.h" #include "kvm.h" -#include "qjson.h" +#include "qapi/qmp/qjson.h" #include "qemu-option.h" #include "qemu-config.h" #include "qemu-options.h" From 737e150e89c44c6b33691a627e24bac7fb58f349 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Dec 2012 18:19:44 +0100 Subject: [PATCH 2059/2270] block: move include files to include/block/ Signed-off-by: Paolo Bonzini --- aes.c | 2 +- aio-posix.c | 2 +- aio-win32.c | 2 +- async.c | 2 +- block-migration.c | 2 +- block.c | 6 +++--- block/blkdebug.c | 2 +- block/blkverify.c | 2 +- block/bochs.c | 2 +- block/cloop.c | 2 +- block/commit.c | 4 ++-- block/cow.c | 2 +- block/curl.c | 2 +- block/dmg.c | 2 +- block/gluster.c | 2 +- block/iscsi.c | 2 +- block/linux-aio.c | 2 +- block/mirror.c | 4 ++-- block/nbd.c | 4 ++-- block/parallels.c | 2 +- block/qcow.c | 4 ++-- block/qcow2-cache.c | 2 +- block/qcow2-cluster.c | 2 +- block/qcow2-refcount.c | 2 +- block/qcow2-snapshot.c | 2 +- block/qcow2.c | 4 ++-- block/qcow2.h | 4 ++-- block/qed.h | 2 +- block/raw-posix.c | 4 ++-- block/raw-win32.c | 4 ++-- block/raw.c | 2 +- block/rbd.c | 2 +- block/sheepdog.c | 2 +- block/stream.c | 4 ++-- block/vdi.c | 2 +- block/vmdk.c | 2 +- block/vpc.c | 2 +- block/vvfat.c | 2 +- block/win32-aio.c | 4 ++-- blockdev-nbd.c | 2 +- blockdev.c | 4 ++-- blockdev.h | 2 +- blockjob.c | 8 ++++---- cmd.c | 2 +- coroutine-gthread.c | 2 +- coroutine-sigaltstack.c | 2 +- coroutine-ucontext.c | 2 +- coroutine-win32.c | 2 +- dma.h | 2 +- hw/9pfs/codir.c | 2 +- hw/9pfs/cofile.c | 2 +- hw/9pfs/cofs.c | 2 +- hw/9pfs/coxattr.c | 2 +- hw/9pfs/virtio-9p-coth.c | 2 +- hw/9pfs/virtio-9p-coth.h | 2 +- hw/9pfs/virtio-9p.h | 2 +- hw/hd-geometry.c | 2 +- hw/hw.h | 2 +- hw/ide/cmd646.c | 2 +- hw/ide/ich.c | 2 +- hw/ide/isa.c | 2 +- hw/ide/macio.c | 2 +- hw/ide/microdrive.c | 2 +- hw/ide/mmio.c | 2 +- hw/ide/pci.c | 2 +- hw/ide/via.c | 2 +- hw/mips_fulong2e.c | 2 +- hw/mips_malta.c | 2 +- hw/musicpal.c | 2 +- hw/pflash_cfi01.c | 2 +- hw/pflash_cfi02.c | 2 +- hw/ppc405_boards.c | 2 +- hw/s390-virtio-bus.c | 2 +- hw/s390-virtio.c | 2 +- hw/scsi.h | 2 +- hw/sd.c | 2 +- hw/spitz.c | 2 +- hw/tosa.c | 2 +- aes.h => include/block/aes.h | 0 qemu-aio.h => include/block/aio.h | 0 block.h => include/block/block.h | 4 ++-- block_int.h => include/block/block_int.h | 4 ++-- blockjob.h => include/block/blockjob.h | 2 +- qemu-coroutine.h => include/block/coroutine.h | 0 qemu-coroutine-int.h => include/block/coroutine_int.h | 2 +- nbd.h => include/block/nbd.h | 0 thread-pool.h => include/block/thread-pool.h | 4 ++-- iohandler.c | 2 +- main-loop.c | 2 +- main-loop.h | 2 +- migration-exec.c | 2 +- migration-fd.c | 2 +- migration-tcp.c | 2 +- migration-unix.c | 2 +- migration.c | 2 +- monitor.h | 2 +- nbd.c | 6 +++--- qemu-char.h | 2 +- qemu-coroutine-io.c | 2 +- qemu-coroutine-lock.c | 6 +++--- qemu-coroutine-sleep.c | 2 +- qemu-coroutine.c | 4 ++-- qemu-img.c | 2 +- qemu-io.c | 2 +- qemu-nbd.c | 4 ++-- tests/test-aio.c | 2 +- tests/test-coroutine.c | 2 +- tests/test-thread-pool.c | 6 +++--- thread-pool.c | 6 +++--- 109 files changed, 134 insertions(+), 134 deletions(-) rename aes.h => include/block/aes.h (100%) rename qemu-aio.h => include/block/aio.h (100%) rename block.h => include/block/block.h (99%) rename block_int.h => include/block/block_int.h (99%) rename blockjob.h => include/block/blockjob.h (99%) rename qemu-coroutine.h => include/block/coroutine.h (100%) rename qemu-coroutine-int.h => include/block/coroutine_int.h (98%) rename nbd.h => include/block/nbd.h (100%) rename thread-pool.h => include/block/thread-pool.h (93%) diff --git a/aes.c b/aes.c index eb37adbed8..1da7bff1c9 100644 --- a/aes.c +++ b/aes.c @@ -28,7 +28,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "qemu-common.h" -#include "aes.h" +#include "block/aes.h" #ifndef NDEBUG #define NDEBUG diff --git a/aio-posix.c b/aio-posix.c index 05cc84e121..d1e1bc2c75 100644 --- a/aio-posix.c +++ b/aio-posix.c @@ -14,7 +14,7 @@ */ #include "qemu-common.h" -#include "block.h" +#include "block/block.h" #include "qemu-queue.h" #include "qemu_socket.h" diff --git a/aio-win32.c b/aio-win32.c index cec4646635..9a26f9c3d9 100644 --- a/aio-win32.c +++ b/aio-win32.c @@ -16,7 +16,7 @@ */ #include "qemu-common.h" -#include "block.h" +#include "block/block.h" #include "qemu-queue.h" #include "qemu_socket.h" diff --git a/async.c b/async.c index 41ae0c1195..6df4caf68a 100644 --- a/async.c +++ b/async.c @@ -23,7 +23,7 @@ */ #include "qemu-common.h" -#include "qemu-aio.h" +#include "block/aio.h" #include "main-loop.h" /***********************************************************/ diff --git a/block-migration.c b/block-migration.c index 71b9601e00..c15de9f750 100644 --- a/block-migration.c +++ b/block-migration.c @@ -14,7 +14,7 @@ */ #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include "hw/hw.h" #include "qemu-queue.h" #include "qemu-timer.h" diff --git a/block.c b/block.c index e962a5afe9..5eab9e2519 100644 --- a/block.c +++ b/block.c @@ -25,13 +25,13 @@ #include "qemu-common.h" #include "trace.h" #include "monitor.h" -#include "block_int.h" -#include "blockjob.h" +#include "block/block_int.h" +#include "block/blockjob.h" #include "module.h" #include "qapi/qmp/qjson.h" #include "sysemu.h" #include "notify.h" -#include "qemu-coroutine.h" +#include "block/coroutine.h" #include "qmp-commands.h" #include "qemu-timer.h" diff --git a/block/blkdebug.c b/block/blkdebug.c index 65556e73e5..cd2866e7bd 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -24,7 +24,7 @@ #include "qemu-common.h" #include "qemu-config.h" -#include "block_int.h" +#include "block/block_int.h" #include "module.h" typedef struct BDRVBlkdebugState { diff --git a/block/blkverify.c b/block/blkverify.c index 4beede77ab..cde5098e5a 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -9,7 +9,7 @@ #include #include "qemu_socket.h" /* for EINPROGRESS on Windows */ -#include "block_int.h" +#include "block/block_int.h" typedef struct { BlockDriverState *test_file; diff --git a/block/bochs.c b/block/bochs.c index ab7944dc43..2cc7524782 100644 --- a/block/bochs.c +++ b/block/bochs.c @@ -23,7 +23,7 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include "module.h" /**************************************************************/ diff --git a/block/cloop.c b/block/cloop.c index 7570eb8e74..da29ff379c 100644 --- a/block/cloop.c +++ b/block/cloop.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include "module.h" #include diff --git a/block/commit.c b/block/commit.c index e2bb1e241b..61ebdba54f 100644 --- a/block/commit.c +++ b/block/commit.c @@ -13,8 +13,8 @@ */ #include "trace.h" -#include "block_int.h" -#include "blockjob.h" +#include "block/block_int.h" +#include "block/blockjob.h" #include "qemu/ratelimit.h" enum { diff --git a/block/cow.c b/block/cow.c index a5a00eb9ca..1438ae1e3b 100644 --- a/block/cow.c +++ b/block/cow.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include "module.h" /**************************************************************/ diff --git a/block/curl.c b/block/curl.c index 1179484de0..47df9524ea 100644 --- a/block/curl.c +++ b/block/curl.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include // #define DEBUG diff --git a/block/dmg.c b/block/dmg.c index 37902a4347..6ee505a9f5 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include "bswap.h" #include "module.h" #include diff --git a/block/gluster.c b/block/gluster.c index 1c90174b13..4cb4e60227 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -16,7 +16,7 @@ * GNU GPL, version 2 or (at your option) any later version. */ #include -#include "block_int.h" +#include "block/block_int.h" #include "qemu_socket.h" #include "uri.h" diff --git a/block/iscsi.c b/block/iscsi.c index 33b93d8000..77e619a1fd 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -29,7 +29,7 @@ #include "qemu-common.h" #include "qemu-config.h" #include "qemu-error.h" -#include "block_int.h" +#include "block/block_int.h" #include "trace.h" #include "hw/scsi-defs.h" diff --git a/block/linux-aio.c b/block/linux-aio.c index 91ef863241..28e5a04e12 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -8,7 +8,7 @@ * See the COPYING file in the top-level directory. */ #include "qemu-common.h" -#include "qemu-aio.h" +#include "block/aio.h" #include "qemu-queue.h" #include "block/raw-aio.h" #include "event_notifier.h" diff --git a/block/mirror.c b/block/mirror.c index b1f5d4fa22..8aeacbf12c 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -12,8 +12,8 @@ */ #include "trace.h" -#include "blockjob.h" -#include "block_int.h" +#include "block/blockjob.h" +#include "block/block_int.h" #include "qemu/ratelimit.h" enum { diff --git a/block/nbd.c b/block/nbd.c index e87c248175..38d6b90ab2 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -27,9 +27,9 @@ */ #include "qemu-common.h" -#include "nbd.h" +#include "block/nbd.h" #include "uri.h" -#include "block_int.h" +#include "block/block_int.h" #include "module.h" #include "qemu_socket.h" diff --git a/block/parallels.c b/block/parallels.c index d30f0ecf77..ae88cd6359 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -24,7 +24,7 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include "module.h" /**************************************************************/ diff --git a/block/qcow.c b/block/qcow.c index b239c82ae0..d13bd400f0 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -22,10 +22,10 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include "module.h" #include -#include "aes.h" +#include "block/aes.h" #include "migration.h" /**************************************************************/ diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c index 2d4322a8dd..2f3114ecc2 100644 --- a/block/qcow2-cache.c +++ b/block/qcow2-cache.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "block_int.h" +#include "block/block_int.h" #include "qemu-common.h" #include "qcow2.h" #include "trace.h" diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 468ef1be56..56fccf9487 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -25,7 +25,7 @@ #include #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include "block/qcow2.h" #include "trace.h" diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 96224d1af2..6a95aa6c92 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -23,7 +23,7 @@ */ #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include "block/qcow2.h" static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size); diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 4e7c93b8b3..eb8fcd5549 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -23,7 +23,7 @@ */ #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include "block/qcow2.h" typedef struct QEMU_PACKED QCowSnapshotHeader { diff --git a/block/qcow2.c b/block/qcow2.c index 217b4e422f..205d910a52 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -22,10 +22,10 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include "module.h" #include -#include "aes.h" +#include "block/aes.h" #include "block/qcow2.h" #include "qemu-error.h" #include "qapi/qmp/qerror.h" diff --git a/block/qcow2.h b/block/qcow2.h index a60fcb429a..718b52baca 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -25,8 +25,8 @@ #ifndef BLOCK_QCOW2_H #define BLOCK_QCOW2_H -#include "aes.h" -#include "qemu-coroutine.h" +#include "block/aes.h" +#include "block/coroutine.h" //#define DEBUG_ALLOC //#define DEBUG_ALLOC2 diff --git a/block/qed.h b/block/qed.h index a063bf70af..2b4ddedf31 100644 --- a/block/qed.h +++ b/block/qed.h @@ -15,7 +15,7 @@ #ifndef BLOCK_QED_H #define BLOCK_QED_H -#include "block_int.h" +#include "block/block_int.h" /* The layout of a QED file is as follows: * diff --git a/block/raw-posix.c b/block/raw-posix.c index 48eff2fd83..4e73885269 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -24,10 +24,10 @@ #include "qemu-common.h" #include "qemu-timer.h" #include "qemu-log.h" -#include "block_int.h" +#include "block/block_int.h" #include "module.h" #include "trace.h" -#include "thread-pool.h" +#include "block/thread-pool.h" #include "iov.h" #include "raw-aio.h" diff --git a/block/raw-win32.c b/block/raw-win32.c index ce207a3109..9269fe84c0 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -23,11 +23,11 @@ */ #include "qemu-common.h" #include "qemu-timer.h" -#include "block_int.h" +#include "block/block_int.h" #include "module.h" #include "raw-aio.h" #include "trace.h" -#include "thread-pool.h" +#include "block/thread-pool.h" #include "iov.h" #include #include diff --git a/block/raw.c b/block/raw.c index 253e949b8c..6aec93dadb 100644 --- a/block/raw.c +++ b/block/raw.c @@ -1,6 +1,6 @@ #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include "module.h" static int raw_open(BlockDriverState *bs, int flags) diff --git a/block/rbd.c b/block/rbd.c index 737bab16cc..8def2f174c 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -15,7 +15,7 @@ #include "qemu-common.h" #include "qemu-error.h" -#include "block_int.h" +#include "block/block_int.h" #include diff --git a/block/sheepdog.c b/block/sheepdog.c index a48f58cfe8..da70df2d00 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -15,7 +15,7 @@ #include "qemu-common.h" #include "qemu-error.h" #include "qemu_socket.h" -#include "block_int.h" +#include "block/block_int.h" #include "bitops.h" #define SD_PROTO_VER 0x01 diff --git a/block/stream.c b/block/stream.c index 0dcd286035..d6df06f35a 100644 --- a/block/stream.c +++ b/block/stream.c @@ -12,8 +12,8 @@ */ #include "trace.h" -#include "block_int.h" -#include "blockjob.h" +#include "block/block_int.h" +#include "block/blockjob.h" #include "qemu/ratelimit.h" enum { diff --git a/block/vdi.c b/block/vdi.c index c8330b7eae..dab9cac76e 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -50,7 +50,7 @@ */ #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include "module.h" #include "migration.h" diff --git a/block/vmdk.c b/block/vmdk.c index 51398c0c08..68e50e1a3e 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -24,7 +24,7 @@ */ #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include "module.h" #include "migration.h" #include diff --git a/block/vpc.c b/block/vpc.c index 566e9a3b37..aabd71201c 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -23,7 +23,7 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include "module.h" #include "migration.h" #if defined(CONFIG_UUID) diff --git a/block/vvfat.c b/block/vvfat.c index 59d3c5b8ac..fbabafca76 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -25,7 +25,7 @@ #include #include #include "qemu-common.h" -#include "block_int.h" +#include "block/block_int.h" #include "module.h" #include "migration.h" diff --git a/block/win32-aio.c b/block/win32-aio.c index 4704ee06c2..606e4d6925 100644 --- a/block/win32-aio.c +++ b/block/win32-aio.c @@ -23,10 +23,10 @@ */ #include "qemu-common.h" #include "qemu-timer.h" -#include "block_int.h" +#include "block/block_int.h" #include "module.h" #include "qemu-common.h" -#include "qemu-aio.h" +#include "block/aio.h" #include "raw-aio.h" #include "event_notifier.h" #include diff --git a/blockdev-nbd.c b/blockdev-nbd.c index a194ecd392..81aa1d34ef 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -16,7 +16,7 @@ #include "sysemu.h" #include "qmp-commands.h" #include "trace.h" -#include "nbd.h" +#include "block/nbd.h" #include "qemu_socket.h" static int server_fd = -1; diff --git a/blockdev.c b/blockdev.c index c85c614577..ff6b333f69 100644 --- a/blockdev.c +++ b/blockdev.c @@ -9,14 +9,14 @@ #include "blockdev.h" #include "hw/block-common.h" -#include "blockjob.h" +#include "block/blockjob.h" #include "monitor.h" #include "qapi/qmp/qerror.h" #include "qemu-option.h" #include "qemu-config.h" #include "qapi/qmp/types.h" #include "sysemu.h" -#include "block_int.h" +#include "block/block_int.h" #include "qmp-commands.h" #include "trace.h" #include "arch_init.h" diff --git a/blockdev.h b/blockdev.h index 6e36d9f2c2..4134864758 100644 --- a/blockdev.h +++ b/blockdev.h @@ -10,7 +10,7 @@ #ifndef BLOCKDEV_H #define BLOCKDEV_H -#include "block.h" +#include "block/block.h" #include "qapi/error.h" #include "qemu-queue.h" diff --git a/blockjob.c b/blockjob.c index 8c0a286a77..004480d714 100644 --- a/blockjob.c +++ b/blockjob.c @@ -27,11 +27,11 @@ #include "qemu-common.h" #include "trace.h" #include "monitor.h" -#include "block.h" -#include "blockjob.h" -#include "block_int.h" +#include "block/block.h" +#include "block/blockjob.h" +#include "block/block_int.h" #include "qapi/qmp/qjson.h" -#include "qemu-coroutine.h" +#include "block/coroutine.h" #include "qmp-commands.h" #include "qemu-timer.h" diff --git a/cmd.c b/cmd.c index f40f09bbb7..01a8c3a299 100644 --- a/cmd.c +++ b/cmd.c @@ -24,7 +24,7 @@ #include #include "cmd.h" -#include "qemu-aio.h" +#include "block/aio.h" #include "main-loop.h" #define _(x) x /* not gettext support yet */ diff --git a/coroutine-gthread.c b/coroutine-gthread.c index 30c24c94b8..d3e5b991f7 100644 --- a/coroutine-gthread.c +++ b/coroutine-gthread.c @@ -20,7 +20,7 @@ #include #include "qemu-common.h" -#include "qemu-coroutine-int.h" +#include "block/coroutine_int.h" typedef struct { Coroutine base; diff --git a/coroutine-sigaltstack.c b/coroutine-sigaltstack.c index 39dbaa5da1..e37ebac9c4 100644 --- a/coroutine-sigaltstack.c +++ b/coroutine-sigaltstack.c @@ -31,7 +31,7 @@ #include #include #include "qemu-common.h" -#include "qemu-coroutine-int.h" +#include "block/coroutine_int.h" enum { /* Maximum free pool size prevents holding too many freed coroutines */ diff --git a/coroutine-ucontext.c b/coroutine-ucontext.c index 784081ab18..2ed703a3ed 100644 --- a/coroutine-ucontext.c +++ b/coroutine-ucontext.c @@ -28,7 +28,7 @@ #include #include #include "qemu-common.h" -#include "qemu-coroutine-int.h" +#include "block/coroutine_int.h" #ifdef CONFIG_VALGRIND_H #include diff --git a/coroutine-win32.c b/coroutine-win32.c index 4179609eec..edc1f72c18 100644 --- a/coroutine-win32.c +++ b/coroutine-win32.c @@ -23,7 +23,7 @@ */ #include "qemu-common.h" -#include "qemu-coroutine-int.h" +#include "block/coroutine_int.h" typedef struct { diff --git a/dma.h b/dma.h index eedf878383..40280365ce 100644 --- a/dma.h +++ b/dma.h @@ -13,7 +13,7 @@ #include #include "memory.h" #include "hw/hw.h" -#include "block.h" +#include "block/block.h" #include "kvm.h" typedef struct DMAContext DMAContext; diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c index 3d188284ba..cd137330b9 100644 --- a/hw/9pfs/codir.c +++ b/hw/9pfs/codir.c @@ -14,7 +14,7 @@ #include "fsdev/qemu-fsdev.h" #include "qemu-thread.h" -#include "qemu-coroutine.h" +#include "block/coroutine.h" #include "virtio-9p-coth.h" int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *dent, diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c index 9345aaeb2e..6d6dac7abf 100644 --- a/hw/9pfs/cofile.c +++ b/hw/9pfs/cofile.c @@ -14,7 +14,7 @@ #include "fsdev/qemu-fsdev.h" #include "qemu-thread.h" -#include "qemu-coroutine.h" +#include "block/coroutine.h" #include "virtio-9p-coth.h" int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode, diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c index 83f125bd47..4b9ba30157 100644 --- a/hw/9pfs/cofs.c +++ b/hw/9pfs/cofs.c @@ -14,7 +14,7 @@ #include "fsdev/qemu-fsdev.h" #include "qemu-thread.h" -#include "qemu-coroutine.h" +#include "block/coroutine.h" #include "virtio-9p-coth.h" int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, V9fsString *buf) diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c index 8a48228702..08365a697e 100644 --- a/hw/9pfs/coxattr.c +++ b/hw/9pfs/coxattr.c @@ -14,7 +14,7 @@ #include "fsdev/qemu-fsdev.h" #include "qemu-thread.h" -#include "qemu-coroutine.h" +#include "block/coroutine.h" #include "virtio-9p-coth.h" int v9fs_co_llistxattr(V9fsPDU *pdu, V9fsPath *path, void *value, size_t size) diff --git a/hw/9pfs/virtio-9p-coth.c b/hw/9pfs/virtio-9p-coth.c index 9368df7610..958725e5cc 100644 --- a/hw/9pfs/virtio-9p-coth.c +++ b/hw/9pfs/virtio-9p-coth.c @@ -14,7 +14,7 @@ #include "fsdev/qemu-fsdev.h" #include "qemu-thread.h" -#include "qemu-coroutine.h" +#include "block/coroutine.h" #include "virtio-9p-coth.h" /* v9fs glib thread pool */ diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index c31c96578b..8c48a16c10 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -16,7 +16,7 @@ #define _QEMU_VIRTIO_9P_COTH_H #include "qemu-thread.h" -#include "qemu-coroutine.h" +#include "block/coroutine.h" #include "virtio-9p.h" #include diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 579794404b..2c0c3baad4 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -10,7 +10,7 @@ #include "fsdev/file-op-9p.h" #include "fsdev/virtio-9p-marshal.h" #include "qemu-thread.h" -#include "qemu-coroutine.h" +#include "block/coroutine.h" /* The feature bitmap for virtio 9P */ diff --git a/hw/hd-geometry.c b/hw/hd-geometry.c index 1cdb9fb753..c30514364f 100644 --- a/hw/hd-geometry.c +++ b/hw/hd-geometry.c @@ -30,7 +30,7 @@ * THE SOFTWARE. */ -#include "block.h" +#include "block/block.h" #include "hw/block-common.h" #include "trace.h" diff --git a/hw/hw.h b/hw/hw.h index f530f6f41a..003d974866 100644 --- a/hw/hw.h +++ b/hw/hw.h @@ -10,7 +10,7 @@ #include "ioport.h" #include "irq.h" -#include "qemu-aio.h" +#include "block/aio.h" #include "qemu-file.h" #include "vmstate.h" #include "qemu-log.h" diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index 88210eabc8..f6d15b9f2a 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -26,7 +26,7 @@ #include #include #include -#include "block.h" +#include "block/block.h" #include "sysemu.h" #include "dma.h" diff --git a/hw/ide/ich.c b/hw/ide/ich.c index 8e1a48e257..3457b98cc1 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -65,7 +65,7 @@ #include #include #include -#include "block.h" +#include "block/block.h" #include "dma.h" #include diff --git a/hw/ide/isa.c b/hw/ide/isa.c index 8ab2718eea..39df87c608 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -25,7 +25,7 @@ #include #include #include -#include "block.h" +#include "block/block.h" #include "dma.h" #include diff --git a/hw/ide/macio.c b/hw/ide/macio.c index d2edcc0850..87cbb0c31e 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -25,7 +25,7 @@ #include #include #include -#include "block.h" +#include "block/block.h" #include "dma.h" #include diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c index 9eee5b50ba..6cce5230c5 100644 --- a/hw/ide/microdrive.c +++ b/hw/ide/microdrive.c @@ -25,7 +25,7 @@ #include #include #include -#include "block.h" +#include "block/block.h" #include "dma.h" #include diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c index bcb26c8b64..40443513be 100644 --- a/hw/ide/mmio.c +++ b/hw/ide/mmio.c @@ -23,7 +23,7 @@ * THE SOFTWARE. */ #include -#include "block.h" +#include "block/block.h" #include "dma.h" #include diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 23a0e237fb..8821d5cceb 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -26,7 +26,7 @@ #include #include #include -#include "block.h" +#include "block/block.h" #include "dma.h" #include diff --git a/hw/ide/via.c b/hw/ide/via.c index 8b4a24e5c2..880f61cc8e 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -27,7 +27,7 @@ #include #include #include -#include "block.h" +#include "block/block.h" #include "sysemu.h" #include "dma.h" diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c index bab96b27c1..b46f7fdcb1 100644 --- a/hw/mips_fulong2e.c +++ b/hw/mips_fulong2e.c @@ -25,7 +25,7 @@ #include "net/net.h" #include "boards.h" #include "smbus.h" -#include "block.h" +#include "block/block.h" #include "flash.h" #include "mips.h" #include "mips_cpudevs.h" diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 3f9f171385..60f237987f 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -29,7 +29,7 @@ #include "net/net.h" #include "boards.h" #include "smbus.h" -#include "block.h" +#include "block/block.h" #include "flash.h" #include "mips.h" #include "mips_cpudevs.h" diff --git a/hw/musicpal.c b/hw/musicpal.c index d16cd141a2..d7672e92a5 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -18,7 +18,7 @@ #include "serial.h" #include "qemu-timer.h" #include "ptimer.h" -#include "block.h" +#include "block/block.h" #include "flash.h" #include "ui/console.h" #include "i2c.h" diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index 7d040b508a..a2f6360838 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -38,7 +38,7 @@ #include "hw.h" #include "flash.h" -#include "block.h" +#include "block/block.h" #include "qemu-timer.h" #include "exec-memory.h" #include "host-utils.h" diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c index f918e36580..beab67fc87 100644 --- a/hw/pflash_cfi02.c +++ b/hw/pflash_cfi02.c @@ -38,7 +38,7 @@ #include "hw.h" #include "flash.h" #include "qemu-timer.h" -#include "block.h" +#include "block/block.h" #include "exec-memory.h" #include "host-utils.h" #include "sysbus.h" diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c index 8dc693f050..b875e3b615 100644 --- a/hw/ppc405_boards.c +++ b/hw/ppc405_boards.c @@ -27,7 +27,7 @@ #include "nvram.h" #include "flash.h" #include "sysemu.h" -#include "block.h" +#include "block/block.h" #include "boards.h" #include "qemu-log.h" #include "loader.h" diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index 169dd4683d..f7e1939288 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -18,7 +18,7 @@ */ #include "hw.h" -#include "block.h" +#include "block/block.h" #include "sysemu.h" #include "boards.h" #include "monitor.h" diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index 8c724b942c..b732bccef8 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -18,7 +18,7 @@ */ #include "hw.h" -#include "block.h" +#include "block/block.h" #include "blockdev.h" #include "sysemu.h" #include "net/net.h" diff --git a/hw/scsi.h b/hw/scsi.h index b8f73577d3..24ed522722 100644 --- a/hw/scsi.h +++ b/hw/scsi.h @@ -2,7 +2,7 @@ #define QEMU_HW_SCSI_H #include "qdev.h" -#include "block.h" +#include "block/block.h" #include "hw/block-common.h" #include "sysemu.h" diff --git a/hw/sd.c b/hw/sd.c index 607edba9c8..2e54eea981 100644 --- a/hw/sd.c +++ b/hw/sd.c @@ -30,7 +30,7 @@ */ #include "hw.h" -#include "block.h" +#include "block/block.h" #include "sd.h" #include "bitmap.h" diff --git a/hw/spitz.c b/hw/spitz.c index d4575d20bf..1500161d44 100644 --- a/hw/spitz.c +++ b/hw/spitz.c @@ -22,7 +22,7 @@ #include "devices.h" #include "sharpsl.h" #include "ui/console.h" -#include "block.h" +#include "block/block.h" #include "audio/audio.h" #include "boards.h" #include "blockdev.h" diff --git a/hw/tosa.c b/hw/tosa.c index 512278c241..3991a909b5 100644 --- a/hw/tosa.c +++ b/hw/tosa.c @@ -17,7 +17,7 @@ #include "devices.h" #include "sharpsl.h" #include "pcmcia.h" -#include "block.h" +#include "block/block.h" #include "boards.h" #include "i2c.h" #include "ssi.h" diff --git a/aes.h b/include/block/aes.h similarity index 100% rename from aes.h rename to include/block/aes.h diff --git a/qemu-aio.h b/include/block/aio.h similarity index 100% rename from qemu-aio.h rename to include/block/aio.h diff --git a/block.h b/include/block/block.h similarity index 99% rename from block.h rename to include/block/block.h index 0b22892d61..d49ce4dbc5 100644 --- a/block.h +++ b/include/block/block.h @@ -1,10 +1,10 @@ #ifndef BLOCK_H #define BLOCK_H -#include "qemu-aio.h" +#include "block/aio.h" #include "qemu-common.h" #include "qemu-option.h" -#include "qemu-coroutine.h" +#include "block/coroutine.h" #include "qapi/qmp/qobject.h" #include "qapi-types.h" diff --git a/block_int.h b/include/block/block_int.h similarity index 99% rename from block_int.h rename to include/block/block_int.h index a748b6c571..d06de2637b 100644 --- a/block_int.h +++ b/include/block/block_int.h @@ -24,10 +24,10 @@ #ifndef BLOCK_INT_H #define BLOCK_INT_H -#include "block.h" +#include "block/block.h" #include "qemu-option.h" #include "qemu-queue.h" -#include "qemu-coroutine.h" +#include "block/coroutine.h" #include "qemu-timer.h" #include "qapi-types.h" #include "qapi/qmp/qerror.h" diff --git a/blockjob.h b/include/block/blockjob.h similarity index 99% rename from blockjob.h rename to include/block/blockjob.h index 3792b73e52..c290d07bba 100644 --- a/blockjob.h +++ b/include/block/blockjob.h @@ -25,7 +25,7 @@ #ifndef BLOCKJOB_H #define BLOCKJOB_H 1 -#include "block.h" +#include "block/block.h" /** * BlockJobType: diff --git a/qemu-coroutine.h b/include/block/coroutine.h similarity index 100% rename from qemu-coroutine.h rename to include/block/coroutine.h diff --git a/qemu-coroutine-int.h b/include/block/coroutine_int.h similarity index 98% rename from qemu-coroutine-int.h rename to include/block/coroutine_int.h index 0f1bd80a8d..282a3ceda6 100644 --- a/qemu-coroutine-int.h +++ b/include/block/coroutine_int.h @@ -26,7 +26,7 @@ #define QEMU_COROUTINE_INT_H #include "qemu-queue.h" -#include "qemu-coroutine.h" +#include "block/coroutine.h" typedef enum { COROUTINE_YIELD = 1, diff --git a/nbd.h b/include/block/nbd.h similarity index 100% rename from nbd.h rename to include/block/nbd.h diff --git a/thread-pool.h b/include/block/thread-pool.h similarity index 93% rename from thread-pool.h rename to include/block/thread-pool.h index 378a4ac9f9..a87b287081 100644 --- a/thread-pool.h +++ b/include/block/thread-pool.h @@ -21,8 +21,8 @@ #include "qemu-common.h" #include "qemu-queue.h" #include "qemu-thread.h" -#include "qemu-coroutine.h" -#include "block_int.h" +#include "block/coroutine.h" +#include "block/block_int.h" typedef int ThreadPoolFunc(void *opaque); diff --git a/iohandler.c b/iohandler.c index 258f42d8d2..cf8276dffc 100644 --- a/iohandler.c +++ b/iohandler.c @@ -25,7 +25,7 @@ #include "config-host.h" #include "qemu-common.h" #include "qemu-queue.h" -#include "qemu-aio.h" +#include "block/aio.h" #include "main-loop.h" #ifndef _WIN32 diff --git a/main-loop.c b/main-loop.c index 7dba6f6e35..f9006118ad 100644 --- a/main-loop.c +++ b/main-loop.c @@ -26,7 +26,7 @@ #include "qemu-timer.h" #include "slirp/slirp.h" #include "main-loop.h" -#include "qemu-aio.h" +#include "block/aio.h" #ifndef _WIN32 diff --git a/main-loop.h b/main-loop.h index 326c74269c..e8059c3d0a 100644 --- a/main-loop.h +++ b/main-loop.h @@ -25,7 +25,7 @@ #ifndef QEMU_MAIN_LOOP_H #define QEMU_MAIN_LOOP_H 1 -#include "qemu-aio.h" +#include "block/aio.h" #define SIG_IPI SIGUSR1 diff --git a/migration-exec.c b/migration-exec.c index b4a3ca3921..3e55b7792d 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -19,7 +19,7 @@ #include "qemu_socket.h" #include "migration.h" #include "buffered_file.h" -#include "block.h" +#include "block/block.h" #include #include diff --git a/migration-fd.c b/migration-fd.c index 6d42287913..e86228823f 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -18,7 +18,7 @@ #include "migration.h" #include "monitor.h" #include "buffered_file.h" -#include "block.h" +#include "block/block.h" #include "qemu_socket.h" //#define DEBUG_MIGRATION_FD diff --git a/migration-tcp.c b/migration-tcp.c index a9bb817d99..07f51f2aef 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -17,7 +17,7 @@ #include "qemu_socket.h" #include "migration.h" #include "buffered_file.h" -#include "block.h" +#include "block/block.h" //#define DEBUG_MIGRATION_TCP diff --git a/migration-unix.c b/migration-unix.c index e58e8bc15b..1b9c461083 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -17,7 +17,7 @@ #include "qemu_socket.h" #include "migration.h" #include "buffered_file.h" -#include "block.h" +#include "block/block.h" //#define DEBUG_MIGRATION_UNIX diff --git a/migration.c b/migration.c index 73ce170ddf..1fce152548 100644 --- a/migration.c +++ b/migration.c @@ -18,7 +18,7 @@ #include "monitor.h" #include "buffered_file.h" #include "sysemu.h" -#include "block.h" +#include "block/block.h" #include "qemu_socket.h" #include "block-migration.h" #include "qmp-commands.h" diff --git a/monitor.h b/monitor.h index 7c29d9db34..9e96e83f5f 100644 --- a/monitor.h +++ b/monitor.h @@ -4,7 +4,7 @@ #include "qemu-common.h" #include "qapi/qmp/qerror.h" #include "qapi/qmp/qdict.h" -#include "block.h" +#include "block/block.h" #include "readline.h" extern Monitor *cur_mon; diff --git a/nbd.c b/nbd.c index 01976e8e33..04ff0a1d44 100644 --- a/nbd.c +++ b/nbd.c @@ -16,10 +16,10 @@ * along with this program; if not, see . */ -#include "nbd.h" -#include "block.h" +#include "block/nbd.h" +#include "block/block.h" -#include "qemu-coroutine.h" +#include "block/coroutine.h" #include #include diff --git a/qemu-char.h b/qemu-char.h index 3e230a1319..5ff1b2ba91 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -5,7 +5,7 @@ #include "qemu-queue.h" #include "qemu-option.h" #include "qemu-config.h" -#include "qemu-aio.h" +#include "block/aio.h" #include "qapi/qmp/qobject.h" #include "qapi/qmp/qstring.h" #include "main-loop.h" diff --git a/qemu-coroutine-io.c b/qemu-coroutine-io.c index 5734965003..5fae9c7d47 100644 --- a/qemu-coroutine-io.c +++ b/qemu-coroutine-io.c @@ -24,7 +24,7 @@ */ #include "qemu-common.h" #include "qemu_socket.h" -#include "qemu-coroutine.h" +#include "block/coroutine.h" #include "iov.h" ssize_t coroutine_fn diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c index 9dda3f86c9..c3939ac6ef 100644 --- a/qemu-coroutine-lock.c +++ b/qemu-coroutine-lock.c @@ -23,10 +23,10 @@ */ #include "qemu-common.h" -#include "qemu-coroutine.h" -#include "qemu-coroutine-int.h" +#include "block/coroutine.h" +#include "block/coroutine_int.h" #include "qemu-queue.h" -#include "qemu-aio.h" +#include "block/aio.h" #include "trace.h" static QTAILQ_HEAD(, Coroutine) unlock_bh_queue = diff --git a/qemu-coroutine-sleep.c b/qemu-coroutine-sleep.c index d7083ee41a..26e6dac2eb 100644 --- a/qemu-coroutine-sleep.c +++ b/qemu-coroutine-sleep.c @@ -11,7 +11,7 @@ * */ -#include "qemu-coroutine.h" +#include "block/coroutine.h" #include "qemu-timer.h" typedef struct CoSleepCB { diff --git a/qemu-coroutine.c b/qemu-coroutine.c index 600be2643c..0f6e268574 100644 --- a/qemu-coroutine.c +++ b/qemu-coroutine.c @@ -14,8 +14,8 @@ #include "trace.h" #include "qemu-common.h" -#include "qemu-coroutine.h" -#include "qemu-coroutine-int.h" +#include "block/coroutine.h" +#include "block/coroutine_int.h" Coroutine *qemu_coroutine_create(CoroutineEntry *entry) { diff --git a/qemu-img.c b/qemu-img.c index a13bc788cf..2e5ca5c964 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -29,7 +29,7 @@ #include "qemu-error.h" #include "osdep.h" #include "sysemu.h" -#include "block_int.h" +#include "block/block_int.h" #include #include diff --git a/qemu-io.c b/qemu-io.c index 1637773302..e0e47423d7 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -16,7 +16,7 @@ #include "qemu-common.h" #include "main-loop.h" -#include "block_int.h" +#include "block/block_int.h" #include "cmd.h" #include "trace/control.h" diff --git a/qemu-nbd.c b/qemu-nbd.c index 80f08d8464..0a6091b6a8 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -17,8 +17,8 @@ */ #include "qemu-common.h" -#include "block.h" -#include "nbd.h" +#include "block/block.h" +#include "block/nbd.h" #include #include diff --git a/tests/test-aio.c b/tests/test-aio.c index a8a4f0c6a5..e4ebef76b9 100644 --- a/tests/test-aio.c +++ b/tests/test-aio.c @@ -11,7 +11,7 @@ */ #include -#include "qemu-aio.h" +#include "block/aio.h" AioContext *ctx; diff --git a/tests/test-coroutine.c b/tests/test-coroutine.c index e5d14eb696..4c6cc81fb9 100644 --- a/tests/test-coroutine.c +++ b/tests/test-coroutine.c @@ -12,7 +12,7 @@ */ #include -#include "qemu-coroutine.h" +#include "block/coroutine.h" /* * Check that qemu_in_coroutine() works diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c index ea8e676b0c..9998e031f2 100644 --- a/tests/test-thread-pool.c +++ b/tests/test-thread-pool.c @@ -1,8 +1,8 @@ #include #include "qemu-common.h" -#include "qemu-aio.h" -#include "thread-pool.h" -#include "block.h" +#include "block/aio.h" +#include "block/thread-pool.h" +#include "block/block.h" static int active; diff --git a/thread-pool.c b/thread-pool.c index 204f70b7b5..4c73a7db97 100644 --- a/thread-pool.c +++ b/thread-pool.c @@ -18,11 +18,11 @@ #include "qemu-queue.h" #include "qemu-thread.h" #include "osdep.h" -#include "qemu-coroutine.h" +#include "block/coroutine.h" #include "trace.h" -#include "block_int.h" +#include "block/block_int.h" #include "event_notifier.h" -#include "thread-pool.h" +#include "block/thread-pool.h" static void do_spawn_thread(void); From 022c62cbbcf1ff40b23c92874f8670cddfec2414 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Dec 2012 18:19:49 +0100 Subject: [PATCH 2060/2270] exec: move include files to include/exec/ Signed-off-by: Paolo Bonzini --- arch_init.c | 4 +- balloon.c | 2 +- bsd-user/qemu.h | 4 +- cpus.c | 2 +- cputlb.c | 18 +++--- dma.h | 2 +- dump.c | 6 +- exec.c | 8 +-- gdbstub.c | 2 +- hw/acpi_ich9.c | 2 +- hw/acpi_piix4.c | 4 +- hw/alpha_typhoon.c | 4 +- hw/an5206.c | 2 +- hw/apb_pci.c | 2 +- hw/apic_internal.h | 2 +- hw/apm.h | 2 +- hw/arm-misc.h | 2 +- hw/armv7m_nvic.c | 2 +- hw/axis_dev88.c | 2 +- hw/bonito.c | 2 +- hw/collie.c | 2 +- hw/dummy_m68k.c | 2 +- hw/etraxfs_dma.c | 2 +- hw/exynos4210.h | 2 +- hw/exynos4210_fimd.c | 2 +- hw/exynos4_boards.c | 2 +- hw/flash.h | 2 +- hw/framebuffer.h | 2 +- hw/gt64xxx.c | 2 +- hw/gumstix.c | 2 +- hw/highbank.c | 2 +- hw/hw.h | 4 +- hw/ide.h | 2 +- hw/ide/ahci.c | 2 +- hw/ide/internal.h | 2 +- hw/integratorcp.c | 2 +- hw/ioapic_internal.h | 2 +- hw/isa-bus.c | 2 +- hw/isa.h | 4 +- hw/isa_mmio.c | 2 +- hw/kzm.c | 2 +- hw/leon3.c | 2 +- hw/lm32_boards.c | 2 +- hw/loader.c | 4 +- hw/lpc_ich9.c | 2 +- hw/m48t59.c | 2 +- hw/mac_dbdma.h | 2 +- hw/mainstone.c | 2 +- hw/mcf5206.c | 2 +- hw/mcf5208.c | 2 +- hw/mcf_fec.c | 2 +- hw/mcf_intc.c | 2 +- hw/mcf_uart.c | 2 +- hw/milkymist.c | 2 +- hw/mips.h | 2 +- hw/mips_fulong2e.c | 2 +- hw/mips_jazz.c | 2 +- hw/mips_malta.c | 2 +- hw/mips_mipssim.c | 2 +- hw/mips_r4k.c | 2 +- hw/musicpal.c | 2 +- hw/ne2000-isa.c | 2 +- hw/nseries.c | 2 +- hw/omap.h | 2 +- hw/omap_gpmc.c | 4 +- hw/omap_sx1.c | 2 +- hw/omap_uart.c | 2 +- hw/onenand.c | 4 +- hw/openrisc_sim.c | 2 +- hw/palm.c | 2 +- hw/pam.h | 2 +- hw/pc.c | 4 +- hw/pc.h | 6 +- hw/pc_piix.c | 4 +- hw/pc_q35.c | 2 +- hw/pci/pci.c | 2 +- hw/pci/pci.h | 2 +- hw/pci/pcie_host.c | 2 +- hw/pci/pcie_host.h | 2 +- hw/pci/shpc.h | 2 +- hw/pci_bridge_dev.c | 2 +- hw/pcnet.h | 2 +- hw/petalogix_ml605_mmu.c | 2 +- hw/petalogix_s3adsp1800_mmu.c | 2 +- hw/pflash_cfi01.c | 2 +- hw/pflash_cfi02.c | 2 +- hw/ppc/e500.c | 2 +- hw/ppc405_boards.c | 2 +- hw/ppc405_uc.c | 2 +- hw/ppc440_bamboo.c | 2 +- hw/ppc4xx_devs.c | 2 +- hw/ppc4xx_pci.c | 2 +- hw/ppc_mac.h | 2 +- hw/ppc_newworld.c | 2 +- hw/ppc_oldworld.c | 2 +- hw/ppc_prep.c | 2 +- hw/ppce500_pci.c | 2 +- hw/prep_pci.c | 2 +- hw/puv3.c | 2 +- hw/pxa.h | 2 +- hw/qdev-addr.c | 2 +- hw/r2d.c | 2 +- hw/realview.c | 2 +- hw/s390-virtio.c | 2 +- hw/s390x/sclp.c | 2 +- hw/serial.c | 2 +- hw/serial.h | 2 +- hw/sh7750.c | 2 +- hw/sh_intc.h | 2 +- hw/sh_pci.c | 2 +- hw/sh_serial.c | 2 +- hw/sh_timer.c | 2 +- hw/shix.c | 2 +- hw/soc_dma.h | 2 +- hw/spapr.c | 2 +- hw/spapr_iommu.c | 2 +- hw/spapr_pci.c | 2 +- hw/spitz.c | 2 +- hw/stellaris.c | 2 +- hw/strongarm.h | 2 +- hw/sun4u.c | 2 +- hw/sysbus.c | 2 +- hw/sysbus.h | 2 +- hw/tosa.c | 2 +- hw/usb/libhw.c | 2 +- hw/versatile_pci.c | 2 +- hw/versatilepb.c | 2 +- hw/vexpress.c | 2 +- hw/vfio_pci.c | 4 +- hw/vga_int.h | 2 +- hw/vhost.c | 2 +- hw/vhost.h | 2 +- hw/virtex_ml507.c | 2 +- hw/virtio-balloon.c | 2 +- hw/vt82c686.c | 2 +- hw/xen_platform.c | 2 +- hw/xen_pt.c | 2 +- hw/xilinx_zynq.c | 2 +- hw/xtensa_lx60.c | 4 +- hw/xtensa_sim.c | 4 +- hw/z2.c | 2 +- .../exec/address-spaces.h | 2 +- cpu-all.h => include/exec/cpu-all.h | 4 +- cpu-common.h => include/exec/cpu-common.h | 4 +- cpu-defs.h => include/exec/cpu-defs.h | 2 +- cputlb.h => include/exec/cputlb.h | 0 def-helper.h => include/exec/def-helper.h | 0 exec-all.h => include/exec/exec-all.h | 12 ++-- gdbstub.h => include/exec/gdbstub.h | 0 gen-icount.h => include/exec/gen-icount.h | 0 hwaddr.h => include/exec/hwaddr.h | 0 ioport.h => include/exec/ioport.h | 2 +- iorange.h => include/exec/iorange.h | 0 .../exec/memory-internal.h | 0 memory.h => include/exec/memory.h | 8 +-- poison.h => include/exec/poison.h | 0 softmmu-semi.h => include/exec/softmmu-semi.h | 0 softmmu_defs.h => include/exec/softmmu_defs.h | 0 softmmu_exec.h => include/exec/softmmu_exec.h | 58 +++++++++---------- .../exec/softmmu_header.h | 0 .../exec/softmmu_template.h | 2 +- qemu-lock.h => include/exec/spinlock.h | 0 .../exec/user/abitypes.h | 0 thunk.h => include/exec/user/thunk.h | 0 ioport.c | 4 +- kvm-all.c | 6 +- kvm-stub.c | 2 +- linux-user/qemu.h | 6 +- memory.c | 8 +-- memory_mapping-stub.c | 2 +- memory_mapping.c | 2 +- monitor.c | 4 +- qtest.c | 4 +- savevm.c | 2 +- scripts/feature_to_c.sh | 2 +- target-alpha/cpu.h | 6 +- target-alpha/helper.h | 4 +- target-alpha/mem_helper.c | 10 ++-- target-alpha/translate.c | 2 +- target-arm/arm-semi.c | 4 +- target-arm/cpu.h | 6 +- target-arm/helper.c | 2 +- target-arm/helper.h | 4 +- target-arm/iwmmxt_helper.c | 2 +- target-arm/neon_helper.c | 2 +- target-arm/op_helper.c | 10 ++-- target-arm/translate.c | 2 +- target-cris/cpu.h | 6 +- target-cris/helper.h | 4 +- target-cris/op_helper.c | 10 ++-- target-cris/translate.c | 2 +- target-i386/arch_dump.c | 2 +- target-i386/arch_memory_mapping.c | 2 +- target-i386/cpu.h | 6 +- target-i386/fpu_helper.c | 2 +- target-i386/helper.h | 4 +- target-i386/ioport-user.c | 2 +- target-i386/kvm.c | 4 +- target-i386/mem_helper.c | 10 ++-- target-i386/misc_helper.c | 4 +- target-i386/seg_helper.c | 2 +- target-i386/svm_helper.c | 4 +- target-i386/translate.c | 2 +- target-lm32/cpu.h | 6 +- target-lm32/helper.h | 4 +- target-lm32/op_helper.c | 8 +-- target-lm32/translate.c | 2 +- target-m68k/cpu.h | 6 +- target-m68k/helper.c | 2 +- target-m68k/helpers.h | 4 +- target-m68k/m68k-semi.c | 4 +- target-m68k/op_helper.c | 10 ++-- target-m68k/translate.c | 2 +- target-microblaze/cpu.h | 6 +- target-microblaze/helper.h | 4 +- target-microblaze/op_helper.c | 10 ++-- target-microblaze/translate.c | 2 +- target-mips/cpu.h | 6 +- target-mips/helper.h | 4 +- target-mips/op_helper.c | 10 ++-- target-mips/translate.c | 2 +- target-openrisc/cpu.h | 6 +- target-openrisc/helper.h | 4 +- target-openrisc/interrupt.c | 2 +- target-openrisc/mmu.c | 2 +- target-openrisc/mmu_helper.c | 10 ++-- target-openrisc/translate.c | 4 +- target-ppc/cpu.h | 6 +- target-ppc/helper.h | 4 +- target-ppc/kvm_ppc.h | 2 +- target-ppc/mem_helper.c | 10 ++-- target-ppc/translate.c | 2 +- target-ppc/translate_init.c | 2 +- target-s390x/cpu.h | 6 +- target-s390x/fpu_helper.c | 2 +- target-s390x/helper.c | 2 +- target-s390x/helper.h | 4 +- target-s390x/mem_helper.c | 10 ++-- target-s390x/misc_helper.c | 4 +- target-s390x/translate.c | 2 +- target-sh4/cpu.h | 6 +- target-sh4/helper.h | 4 +- target-sh4/op_helper.c | 10 ++-- target-sh4/translate.c | 2 +- target-sparc/cpu.h | 6 +- target-sparc/helper.h | 4 +- target-sparc/ldst_helper.c | 10 ++-- target-sparc/mmu_helper.c | 2 +- target-sparc/translate.c | 2 +- target-unicore32/cpu.h | 6 +- target-unicore32/helper.c | 2 +- target-unicore32/helper.h | 4 +- target-unicore32/op_helper.c | 8 +-- target-unicore32/translate.c | 2 +- target-xtensa/core-dc232b.c | 4 +- target-xtensa/core-dc233c.c | 4 +- target-xtensa/core-fsf.c | 4 +- target-xtensa/cpu.h | 6 +- target-xtensa/helper.c | 4 +- target-xtensa/helper.h | 4 +- target-xtensa/op_helper.c | 8 +-- target-xtensa/translate.c | 4 +- tcg/arm/tcg-target.c | 2 +- tcg/hppa/tcg-target.c | 2 +- tcg/i386/tcg-target.c | 2 +- tcg/ia64/tcg-target.c | 2 +- tcg/mips/tcg-target.c | 2 +- tcg/ppc/tcg-target.c | 2 +- tcg/ppc64/tcg-target.c | 2 +- tcg/s390/tcg-target.c | 2 +- tcg/sparc/tcg-target.c | 2 +- tci.c | 2 +- thunk.c | 2 +- translate-all.c | 6 +- vl.c | 2 +- xen-all.c | 2 +- xen-stub.c | 2 +- 277 files changed, 456 insertions(+), 456 deletions(-) rename exec-memory.h => include/exec/address-spaces.h (97%) rename cpu-all.h => include/exec/cpu-all.h (99%) rename cpu-common.h => include/exec/cpu-common.h (98%) rename cpu-defs.h => include/exec/cpu-defs.h (99%) rename cputlb.h => include/exec/cputlb.h (100%) rename def-helper.h => include/exec/def-helper.h (100%) rename exec-all.h => include/exec/exec-all.h (98%) rename gdbstub.h => include/exec/gdbstub.h (100%) rename gen-icount.h => include/exec/gen-icount.h (100%) rename hwaddr.h => include/exec/hwaddr.h (100%) rename ioport.h => include/exec/ioport.h (99%) rename iorange.h => include/exec/iorange.h (100%) rename memory-internal.h => include/exec/memory-internal.h (100%) rename memory.h => include/exec/memory.h (99%) rename poison.h => include/exec/poison.h (100%) rename softmmu-semi.h => include/exec/softmmu-semi.h (100%) rename softmmu_defs.h => include/exec/softmmu_defs.h (100%) rename softmmu_exec.h => include/exec/softmmu_exec.h (72%) rename softmmu_header.h => include/exec/softmmu_header.h (100%) rename softmmu_template.h => include/exec/softmmu_template.h (99%) rename qemu-lock.h => include/exec/spinlock.h (100%) rename qemu-user-types.h => include/exec/user/abitypes.h (100%) rename thunk.h => include/exec/user/thunk.h (100%) diff --git a/arch_init.c b/arch_init.c index e479a2566c..e15cedad04 100644 --- a/arch_init.c +++ b/arch_init.c @@ -40,9 +40,9 @@ #include "hw/audiodev.h" #include "kvm.h" #include "migration.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #include "hw/smbios.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "hw/pcspk.h" #include "qemu/page_cache.h" #include "qemu-config.h" diff --git a/balloon.c b/balloon.c index 610fe6d626..c24458b5f9 100644 --- a/balloon.c +++ b/balloon.c @@ -25,7 +25,7 @@ */ #include "monitor.h" -#include "cpu-common.h" +#include "exec/cpu-common.h" #include "kvm.h" #include "balloon.h" #include "trace.h" diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h index d2688995bd..c64c3ccca3 100644 --- a/bsd-user/qemu.h +++ b/bsd-user/qemu.h @@ -11,7 +11,7 @@ #include #endif /* DEBUG_REMAP */ -#include "qemu-user-types.h" +#include "exec/user/abitypes.h" enum BSDType { target_freebsd, @@ -23,7 +23,7 @@ extern enum BSDType bsd_type; #include "syscall_defs.h" #include "syscall.h" #include "target_signal.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #if defined(CONFIG_USE_NPTL) #define THREAD __thread diff --git a/cpus.c b/cpus.c index d9c332fcb8..8926873ad1 100644 --- a/cpus.c +++ b/cpus.c @@ -27,7 +27,7 @@ #include "monitor.h" #include "sysemu.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #include "dma.h" #include "kvm.h" #include "qmp-commands.h" diff --git a/cputlb.c b/cputlb.c index d6d0372615..88239c494a 100644 --- a/cputlb.c +++ b/cputlb.c @@ -19,13 +19,13 @@ #include "config.h" #include "cpu.h" -#include "exec-all.h" -#include "memory.h" -#include "exec-memory.h" +#include "exec/exec-all.h" +#include "exec/memory.h" +#include "exec/address-spaces.h" -#include "cputlb.h" +#include "exec/cputlb.h" -#include "memory-internal.h" +#include "exec/memory-internal.h" //#define DEBUG_TLB //#define DEBUG_TLB_CHECK @@ -347,15 +347,15 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr) #define SOFTMMU_CODE_ACCESS #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #undef env diff --git a/dma.h b/dma.h index 40280365ce..fd68f74c5b 100644 --- a/dma.h +++ b/dma.h @@ -11,7 +11,7 @@ #define DMA_H #include -#include "memory.h" +#include "exec/memory.h" #include "hw/hw.h" #include "block/block.h" #include "kvm.h" diff --git a/dump.c b/dump.c index 7b45b53a8f..e70e0f3b21 100644 --- a/dump.c +++ b/dump.c @@ -14,8 +14,8 @@ #include "qemu-common.h" #include "elf.h" #include "cpu.h" -#include "cpu-all.h" -#include "hwaddr.h" +#include "exec/cpu-all.h" +#include "exec/hwaddr.h" #include "monitor.h" #include "kvm.h" #include "dump.h" @@ -23,7 +23,7 @@ #include "memory_mapping.h" #include "qapi/error.h" #include "qmp-commands.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" static uint16_t cpu_convert_to_target16(uint16_t val, int endian) { diff --git a/exec.c b/exec.c index 986084146c..17fc7cf854 100644 --- a/exec.c +++ b/exec.c @@ -34,9 +34,9 @@ #include "hw/xen.h" #include "qemu-timer.h" #include "qemu-config.h" -#include "memory.h" +#include "exec/memory.h" #include "dma.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #if defined(CONFIG_USER_ONLY) #include #else /* !CONFIG_USER_ONLY */ @@ -44,10 +44,10 @@ #include "trace.h" #endif -#include "cputlb.h" +#include "exec/cputlb.h" #include "translate-all.h" -#include "memory-internal.h" +#include "exec/memory-internal.h" //#define DEBUG_UNASSIGNED //#define DEBUG_SUBPAGE diff --git a/gdbstub.c b/gdbstub.c index d02ec75384..70ad79a748 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -32,7 +32,7 @@ #include "monitor.h" #include "qemu-char.h" #include "sysemu.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #endif #define MAX_PACKET_LENGTH 4096 diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c index 755fa050f7..92af3a554c 100644 --- a/hw/acpi_ich9.c +++ b/hw/acpi_ich9.c @@ -30,7 +30,7 @@ #include "sysemu.h" #include "acpi.h" #include "kvm.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "ich9.h" diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 46f9843891..4f43f6e070 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -26,9 +26,9 @@ #include "acpi.h" #include "sysemu.h" #include "range.h" -#include "ioport.h" +#include "exec/ioport.h" #include "fw_cfg.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" //#define DEBUG diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c index 9b16d96612..d61b2f483c 100644 --- a/hw/alpha_typhoon.c +++ b/hw/alpha_typhoon.c @@ -7,12 +7,12 @@ */ #include "cpu.h" -#include "exec-all.h" +#include "exec/exec-all.h" #include "hw.h" #include "devices.h" #include "sysemu.h" #include "alpha_sys.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost" diff --git a/hw/an5206.c b/hw/an5206.c index d887c0e7eb..dcfe34b3ae 100644 --- a/hw/an5206.c +++ b/hw/an5206.c @@ -11,7 +11,7 @@ #include "boards.h" #include "loader.h" #include "elf.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define KERNEL_LOAD_ADDR 0x10000 #define AN5206_MBAR_ADDR 0x10000000 diff --git a/hw/apb_pci.c b/hw/apb_pci.c index fb7a07de37..144a7cc8d3 100644 --- a/hw/apb_pci.c +++ b/hw/apb_pci.c @@ -33,7 +33,7 @@ #include "pci/pci_bus.h" #include "apb_pci.h" #include "sysemu.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" /* debug APB */ //#define DEBUG_APB diff --git a/hw/apic_internal.h b/hw/apic_internal.h index 79e2de2243..fea95654ca 100644 --- a/hw/apic_internal.h +++ b/hw/apic_internal.h @@ -20,7 +20,7 @@ #ifndef QEMU_APIC_INTERNAL_H #define QEMU_APIC_INTERNAL_H -#include "memory.h" +#include "exec/memory.h" #include "sysbus.h" #include "qemu-timer.h" diff --git a/hw/apm.h b/hw/apm.h index 5431b6d7c8..9abb47f99f 100644 --- a/hw/apm.h +++ b/hw/apm.h @@ -4,7 +4,7 @@ #include #include "qemu-common.h" #include "hw.h" -#include "memory.h" +#include "exec/memory.h" typedef void (*apm_ctrl_changed_t)(uint32_t val, void *arg); diff --git a/hw/arm-misc.h b/hw/arm-misc.h index d129678b26..cba7553039 100644 --- a/hw/arm-misc.h +++ b/hw/arm-misc.h @@ -11,7 +11,7 @@ #ifndef ARM_MISC_H #define ARM_MISC_H 1 -#include "memory.h" +#include "exec/memory.h" #include "hw/irq.h" /* The CPU is also modeled as an interrupt controller. */ diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c index 4963678bf1..270c307717 100644 --- a/hw/armv7m_nvic.c +++ b/hw/armv7m_nvic.c @@ -13,7 +13,7 @@ #include "sysbus.h" #include "qemu-timer.h" #include "arm-misc.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "arm_gic_internal.h" typedef struct { diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c index 50ddbc920d..e537aecc78 100644 --- a/hw/axis_dev88.c +++ b/hw/axis_dev88.c @@ -31,7 +31,7 @@ #include "elf.h" #include "cris-boot.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define D(x) #define DNAND(x) diff --git a/hw/bonito.c b/hw/bonito.c index a1fc38c784..78e264ccc0 100644 --- a/hw/bonito.c +++ b/hw/bonito.c @@ -45,7 +45,7 @@ #include "mips.h" #include "pci/pci_host.h" #include "sysemu.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" //#define DEBUG_BONITO diff --git a/hw/collie.c b/hw/collie.c index 695982a99f..faf5ac9ac7 100644 --- a/hw/collie.c +++ b/hw/collie.c @@ -16,7 +16,7 @@ #include "arm-misc.h" #include "flash.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" static struct arm_boot_info collie_binfo = { .loader_start = SA_SDCS0, diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c index 20f790b1a6..7878cc3e15 100644 --- a/hw/dummy_m68k.c +++ b/hw/dummy_m68k.c @@ -10,7 +10,7 @@ #include "boards.h" #include "loader.h" #include "elf.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define KERNEL_LOAD_ADDR 0x10000 diff --git a/hw/etraxfs_dma.c b/hw/etraxfs_dma.c index 49221abc1a..089267fcc1 100644 --- a/hw/etraxfs_dma.c +++ b/hw/etraxfs_dma.c @@ -24,7 +24,7 @@ #include #include #include "hw.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "qemu-common.h" #include "sysemu.h" diff --git a/hw/exynos4210.h b/hw/exynos4210.h index 777f0f5b2f..bb9a1dddc8 100644 --- a/hw/exynos4210.h +++ b/hw/exynos4210.h @@ -27,7 +27,7 @@ #define EXYNOS4210_H_ #include "qemu-common.h" -#include "memory.h" +#include "exec/memory.h" #define EXYNOS4210_NCPUS 2 diff --git a/hw/exynos4210_fimd.c b/hw/exynos4210_fimd.c index 3ef0847271..cfca72ab67 100644 --- a/hw/exynos4210_fimd.c +++ b/hw/exynos4210_fimd.c @@ -23,7 +23,7 @@ */ #include "qemu-common.h" -#include "cpu-all.h" +#include "exec/cpu-all.h" #include "sysbus.h" #include "ui/console.h" #include "ui/pixel_ops.h" diff --git a/hw/exynos4_boards.c b/hw/exynos4_boards.c index c375f16479..5dd2961459 100644 --- a/hw/exynos4_boards.c +++ b/hw/exynos4_boards.c @@ -25,7 +25,7 @@ #include "sysbus.h" #include "net/net.h" #include "arm-misc.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "exynos4210.h" #include "boards.h" diff --git a/hw/flash.h b/hw/flash.h index bda2158c13..920d7596e3 100644 --- a/hw/flash.h +++ b/hw/flash.h @@ -3,7 +3,7 @@ /* NOR flash devices */ -#include "memory.h" +#include "exec/memory.h" typedef struct pflash_t pflash_t; diff --git a/hw/framebuffer.h b/hw/framebuffer.h index 46e375b5ec..11f53edec0 100644 --- a/hw/framebuffer.h +++ b/hw/framebuffer.h @@ -1,7 +1,7 @@ #ifndef QEMU_FRAMEBUFFER_H #define QEMU_FRAMEBUFFER_H -#include "memory.h" +#include "exec/memory.h" /* Framebuffer device helper routines. */ diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c index 5aa49c6148..977a2c5e69 100644 --- a/hw/gt64xxx.c +++ b/hw/gt64xxx.c @@ -27,7 +27,7 @@ #include "pci/pci.h" #include "pci/pci_host.h" #include "pc.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" //#define DEBUG diff --git a/hw/gumstix.c b/hw/gumstix.c index 545b92fd95..4acb32c2a9 100644 --- a/hw/gumstix.c +++ b/hw/gumstix.c @@ -41,7 +41,7 @@ #include "devices.h" #include "boards.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" static const int sector_len = 128 * 1024; diff --git a/hw/highbank.c b/hw/highbank.c index 90f7cb5ef2..6f5f2a9d9d 100644 --- a/hw/highbank.c +++ b/hw/highbank.c @@ -26,7 +26,7 @@ #include "boards.h" #include "sysbus.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define SMP_BOOT_ADDR 0x100 #define SMP_BOOT_REG 0x40 diff --git a/hw/hw.h b/hw/hw.h index 003d974866..7368470bb1 100644 --- a/hw/hw.h +++ b/hw/hw.h @@ -5,10 +5,10 @@ #include "qemu-common.h" #if !defined(CONFIG_USER_ONLY) && !defined(NEED_CPU_H) -#include "cpu-common.h" +#include "exec/cpu-common.h" #endif -#include "ioport.h" +#include "exec/ioport.h" #include "irq.h" #include "block/aio.h" #include "qemu-file.h" diff --git a/hw/ide.h b/hw/ide.h index 081c710d56..7e23cda8e0 100644 --- a/hw/ide.h +++ b/hw/ide.h @@ -3,7 +3,7 @@ #include "isa.h" #include "pci/pci.h" -#include "memory.h" +#include "exec/memory.h" #define MAX_IDE_DEVS 2 diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 2ea64bd316..f32a84761d 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -29,7 +29,7 @@ #include "monitor.h" #include "dma.h" -#include "cpu-common.h" +#include "exec/cpu-common.h" #include "internal.h" #include #include diff --git a/hw/ide/internal.h b/hw/ide/internal.h index bf7d313cf4..c5016f0cea 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -8,7 +8,7 @@ */ #include #include -#include "iorange.h" +#include "exec/iorange.h" #include "dma.h" #include "sysemu.h" #include "hw/block-common.h" diff --git a/hw/integratorcp.c b/hw/integratorcp.c index 2b59fea9f1..c995dc724f 100644 --- a/hw/integratorcp.c +++ b/hw/integratorcp.c @@ -12,7 +12,7 @@ #include "boards.h" #include "arm-misc.h" #include "net/net.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "sysemu.h" typedef struct { diff --git a/hw/ioapic_internal.h b/hw/ioapic_internal.h index e04c9f3c12..c8447d7f3b 100644 --- a/hw/ioapic_internal.h +++ b/hw/ioapic_internal.h @@ -23,7 +23,7 @@ #define QEMU_IOAPIC_INTERNAL_H #include "hw.h" -#include "memory.h" +#include "exec/memory.h" #include "sysbus.h" #define MAX_IOAPICS 1 diff --git a/hw/isa-bus.c b/hw/isa-bus.c index 144a88e272..8f40974166 100644 --- a/hw/isa-bus.c +++ b/hw/isa-bus.c @@ -21,7 +21,7 @@ #include "sysbus.h" #include "sysemu.h" #include "isa.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" static ISABus *isabus; hwaddr isa_mem_base = 0; diff --git a/hw/isa.h b/hw/isa.h index 9d719fa3c8..62e89d3bcd 100644 --- a/hw/isa.h +++ b/hw/isa.h @@ -3,8 +3,8 @@ /* ISA bus */ -#include "ioport.h" -#include "memory.h" +#include "exec/ioport.h" +#include "exec/memory.h" #include "qdev.h" #define ISA_NUM_IRQS 16 diff --git a/hw/isa_mmio.c b/hw/isa_mmio.c index 14053960cb..487cf6a8fb 100644 --- a/hw/isa_mmio.c +++ b/hw/isa_mmio.c @@ -24,7 +24,7 @@ #include "hw.h" #include "isa.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" static void isa_mmio_writeb (void *opaque, hwaddr addr, uint32_t val) diff --git a/hw/kzm.c b/hw/kzm.c index a27ecbba84..9f92d30928 100644 --- a/hw/kzm.c +++ b/hw/kzm.c @@ -14,7 +14,7 @@ */ #include "sysbus.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "hw.h" #include "arm-misc.h" #include "devices.h" diff --git a/hw/leon3.c b/hw/leon3.c index ef83dffd85..e8d54e5d06 100644 --- a/hw/leon3.c +++ b/hw/leon3.c @@ -30,7 +30,7 @@ #include "loader.h" #include "elf.h" #include "trace.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "grlib.h" diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c index f59d3bfef8..81afdf675c 100644 --- a/hw/lm32_boards.c +++ b/hw/lm32_boards.c @@ -27,7 +27,7 @@ #include "elf.h" #include "lm32_hwsetup.h" #include "lm32.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" typedef struct { LM32CPU *cpu; diff --git a/hw/loader.c b/hw/loader.c index 52f0940778..03f0318d91 100644 --- a/hw/loader.c +++ b/hw/loader.c @@ -49,8 +49,8 @@ #include "uboot_image.h" #include "loader.h" #include "fw_cfg.h" -#include "memory.h" -#include "exec-memory.h" +#include "exec/memory.h" +#include "exec/address-spaces.h" #include diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c index 30505789f8..e225693721 100644 --- a/hw/lpc_ich9.c +++ b/hw/lpc_ich9.c @@ -43,7 +43,7 @@ #include "acpi_ich9.h" #include "pam.h" #include "pci/pci_bus.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "sysemu.h" static int ich9_lpc_sci_irq(ICH9LPCState *lpc); diff --git a/hw/m48t59.c b/hw/m48t59.c index 7da7e7c822..491d433ae7 100644 --- a/hw/m48t59.c +++ b/hw/m48t59.c @@ -27,7 +27,7 @@ #include "sysemu.h" #include "sysbus.h" #include "isa.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" //#define DEBUG_NVRAM diff --git a/hw/mac_dbdma.h b/hw/mac_dbdma.h index e596837f46..691263eede 100644 --- a/hw/mac_dbdma.h +++ b/hw/mac_dbdma.h @@ -22,7 +22,7 @@ #ifndef HW_MAC_DBDMA_H #define HW_MAC_DBDMA_H 1 -#include "memory.h" +#include "exec/memory.h" typedef struct DBDMA_io DBDMA_io; diff --git a/hw/mainstone.c b/hw/mainstone.c index 58c8b0748e..80d6a9d54d 100644 --- a/hw/mainstone.c +++ b/hw/mainstone.c @@ -20,7 +20,7 @@ #include "flash.h" #include "blockdev.h" #include "sysbus.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" /* Device addresses */ #define MST_FPGA_PHYS 0x08000000 diff --git a/hw/mcf5206.c b/hw/mcf5206.c index 510d77047e..5edc931abd 100644 --- a/hw/mcf5206.c +++ b/hw/mcf5206.c @@ -10,7 +10,7 @@ #include "qemu-timer.h" #include "ptimer.h" #include "sysemu.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" /* General purpose timer module. */ typedef struct { diff --git a/hw/mcf5208.c b/hw/mcf5208.c index 6326624111..997b34847c 100644 --- a/hw/mcf5208.c +++ b/hw/mcf5208.c @@ -14,7 +14,7 @@ #include "boards.h" #include "loader.h" #include "elf.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define SYS_FREQ 66000000 diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c index b5fb18f67f..2423f64bf6 100644 --- a/hw/mcf_fec.c +++ b/hw/mcf_fec.c @@ -10,7 +10,7 @@ #include "mcf.h" /* For crc32 */ #include -#include "exec-memory.h" +#include "exec/address-spaces.h" //#define DEBUG_FEC 1 diff --git a/hw/mcf_intc.c b/hw/mcf_intc.c index 6ef6dac931..3bed3a2e4c 100644 --- a/hw/mcf_intc.c +++ b/hw/mcf_intc.c @@ -7,7 +7,7 @@ */ #include "hw.h" #include "mcf.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" typedef struct { MemoryRegion iomem; diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c index d1655f8f2c..2eca2c6ae9 100644 --- a/hw/mcf_uart.c +++ b/hw/mcf_uart.c @@ -8,7 +8,7 @@ #include "hw.h" #include "mcf.h" #include "qemu-char.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" typedef struct { MemoryRegion iomem; diff --git a/hw/milkymist.c b/hw/milkymist.c index c26ea4aed2..588522260b 100644 --- a/hw/milkymist.c +++ b/hw/milkymist.c @@ -28,7 +28,7 @@ #include "blockdev.h" #include "milkymist-hw.h" #include "lm32.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define BIOS_FILENAME "mmone-bios.bin" #define BIOS_OFFSET 0x00860000 diff --git a/hw/mips.h b/hw/mips.h index f7e9b7e2c1..291e85f6b9 100644 --- a/hw/mips.h +++ b/hw/mips.h @@ -2,7 +2,7 @@ #define HW_MIPS_H /* Definitions for mips board emulation. */ -#include "memory.h" +#include "exec/memory.h" /* gt64xxx.c */ PCIBus *gt64120_register(qemu_irq *pic); diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c index b46f7fdcb1..34619b7e3e 100644 --- a/hw/mips_fulong2e.c +++ b/hw/mips_fulong2e.c @@ -42,7 +42,7 @@ #include "mc146818rtc.h" #include "i8254.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define DEBUG_FULONG2E_INIT diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c index 8e5e8ef1af..0befc99210 100644 --- a/hw/mips_jazz.c +++ b/hw/mips_jazz.c @@ -41,7 +41,7 @@ #include "pcspk.h" #include "blockdev.h" #include "sysbus.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" enum jazz_model_e { diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 60f237987f..d65d1256fd 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -46,7 +46,7 @@ #include "mc146818rtc.h" #include "i8254.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "sysbus.h" /* SysBusDevice */ //#define DEBUG_BOARD_INIT diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c index 78317426a7..ac7dfa9b74 100644 --- a/hw/mips_mipssim.c +++ b/hw/mips_mipssim.c @@ -36,7 +36,7 @@ #include "loader.h" #include "elf.h" #include "sysbus.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" static struct _loaderparams { int ram_size; diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index ec99d7d6a6..05494b9b40 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -25,7 +25,7 @@ #include "mc146818rtc.h" #include "i8254.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define MAX_IDE_BUS 2 diff --git a/hw/musicpal.c b/hw/musicpal.c index d7672e92a5..436b3f7c37 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -23,7 +23,7 @@ #include "ui/console.h" #include "i2c.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "ui/pixel_ops.h" #define MP_MISC_BASE 0x80002000 diff --git a/hw/ne2000-isa.c b/hw/ne2000-isa.c index 99477a412a..c2c00c215f 100644 --- a/hw/ne2000-isa.c +++ b/hw/ne2000-isa.c @@ -27,7 +27,7 @@ #include "qdev.h" #include "net/net.h" #include "ne2000.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" typedef struct ISANE2000State { ISADevice dev; diff --git a/hw/nseries.c b/hw/nseries.c index dcd3dc97d0..83adb97211 100644 --- a/hw/nseries.c +++ b/hw/nseries.c @@ -33,7 +33,7 @@ #include "loader.h" #include "blockdev.h" #include "sysbus.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" /* Nokia N8x0 support */ struct n800_s { diff --git a/hw/omap.h b/hw/omap.h index 2b383ffc44..188cda8771 100644 --- a/hw/omap.h +++ b/hw/omap.h @@ -17,7 +17,7 @@ * with this program; if not, see . */ #ifndef hw_omap_h -#include "memory.h" +#include "exec/memory.h" # define hw_omap_h "omap.h" #include "hw/irq.h" diff --git a/hw/omap_gpmc.c b/hw/omap_gpmc.c index 1f7c5bc5f3..02ab0ab568 100644 --- a/hw/omap_gpmc.c +++ b/hw/omap_gpmc.c @@ -21,8 +21,8 @@ #include "hw.h" #include "flash.h" #include "omap.h" -#include "memory.h" -#include "exec-memory.h" +#include "exec/memory.h" +#include "exec/address-spaces.h" /* General-Purpose Memory Controller */ struct omap_gpmc_s { diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c index 918a6f6a04..ca6eb9ddeb 100644 --- a/hw/omap_sx1.c +++ b/hw/omap_sx1.c @@ -32,7 +32,7 @@ #include "arm-misc.h" #include "flash.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" /*****************************************************************************/ /* Siemens SX1 Cellphone V1 */ diff --git a/hw/omap_uart.c b/hw/omap_uart.c index 92f27021bb..159b2d1cdd 100644 --- a/hw/omap_uart.c +++ b/hw/omap_uart.c @@ -21,7 +21,7 @@ #include "hw.h" #include "omap.h" #include "serial.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" /* UARTs */ struct omap_uart_s { diff --git a/hw/onenand.c b/hw/onenand.c index 1803e4c264..7d255c563f 100644 --- a/hw/onenand.c +++ b/hw/onenand.c @@ -23,8 +23,8 @@ #include "flash.h" #include "irq.h" #include "blockdev.h" -#include "memory.h" -#include "exec-memory.h" +#include "exec/memory.h" +#include "exec/address-spaces.h" #include "sysbus.h" #include "qemu-error.h" diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c index a879fb0dd0..c12097e12b 100644 --- a/hw/openrisc_sim.c +++ b/hw/openrisc_sim.c @@ -24,7 +24,7 @@ #include "serial.h" #include "net/net.h" #include "loader.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "sysemu.h" #include "sysbus.h" #include "qtest.h" diff --git a/hw/palm.c b/hw/palm.c index 5aaeb07460..e091bbcfc1 100644 --- a/hw/palm.c +++ b/hw/palm.c @@ -25,7 +25,7 @@ #include "arm-misc.h" #include "devices.h" #include "loader.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" static uint32_t static_readb(void *opaque, hwaddr offset) { diff --git a/hw/pam.h b/hw/pam.h index 2d77ebe0d9..8e9e349b1d 100644 --- a/hw/pam.h +++ b/hw/pam.h @@ -51,7 +51,7 @@ */ #include "qemu-common.h" -#include "memory.h" +#include "exec/memory.h" #define SMRAM_C_BASE 0xa0000 #define SMRAM_C_END 0xc0000 diff --git a/hw/pc.c b/hw/pc.c index d1b102c879..2452fd4214 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -47,8 +47,8 @@ #include "blockdev.h" #include "hw/block-common.h" #include "ui/qemu-spice.h" -#include "memory.h" -#include "exec-memory.h" +#include "exec/memory.h" +#include "exec/address-spaces.h" #include "arch_init.h" #include "bitmap.h" diff --git a/hw/pc.h b/hw/pc.h index 5e4d103813..a73e3e7b5b 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -2,12 +2,12 @@ #define HW_PC_H #include "qemu-common.h" -#include "memory.h" -#include "ioport.h" +#include "exec/memory.h" +#include "exec/ioport.h" #include "isa.h" #include "fdc.h" #include "net/net.h" -#include "memory.h" +#include "exec/memory.h" #include "ioapic.h" /* PC-style peripherals (also used by other machines). */ diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 7268dcd944..0d011348f2 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -41,8 +41,8 @@ #include "blockdev.h" #include "smbus.h" #include "xen.h" -#include "memory.h" -#include "exec-memory.h" +#include "exec/memory.h" +#include "exec/address-spaces.h" #include "cpu.h" #ifdef CONFIG_XEN # include diff --git a/hw/pc_q35.c b/hw/pc_q35.c index 3429a9ae8f..2580d5ff34 100644 --- a/hw/pc_q35.c +++ b/hw/pc_q35.c @@ -36,7 +36,7 @@ #include "kvm.h" #include "kvm/clock.h" #include "q35.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "ich9.h" #include "hw/ide/pci.h" #include "hw/ide/ahci.h" diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 105fe9560e..fa0f08eb0a 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -33,7 +33,7 @@ #include "qmp-commands.h" #include "hw/pci/msi.h" #include "hw/pci/msix.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" //#define DEBUG_PCI #ifdef DEBUG_PCI diff --git a/hw/pci/pci.h b/hw/pci/pci.h index 41e5ddd1c4..d6ef4f6574 100644 --- a/hw/pci/pci.h +++ b/hw/pci/pci.h @@ -4,7 +4,7 @@ #include "qemu-common.h" #include "hw/qdev.h" -#include "memory.h" +#include "exec/memory.h" #include "dma.h" /* PCI includes legacy ISA access. */ diff --git a/hw/pci/pcie_host.c b/hw/pci/pcie_host.c index ab8d251de6..b2d942bce1 100644 --- a/hw/pci/pcie_host.c +++ b/hw/pci/pcie_host.c @@ -22,7 +22,7 @@ #include "hw/hw.h" #include "hw/pci/pci.h" #include "hw/pci/pcie_host.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" /* * PCI express mmcfig address diff --git a/hw/pci/pcie_host.h b/hw/pci/pcie_host.h index 150bef9736..1228e36cb2 100644 --- a/hw/pci/pcie_host.h +++ b/hw/pci/pcie_host.h @@ -22,7 +22,7 @@ #define PCIE_HOST_H #include "hw/pci/pci_host.h" -#include "memory.h" +#include "exec/memory.h" #define TYPE_PCIE_HOST_BRIDGE "pcie-host-bridge" #define PCIE_HOST_BRIDGE(obj) \ diff --git a/hw/pci/shpc.h b/hw/pci/shpc.h index 130b71df30..6374e68bdb 100644 --- a/hw/pci/shpc.h +++ b/hw/pci/shpc.h @@ -2,7 +2,7 @@ #define SHPC_H #include "qemu-common.h" -#include "memory.h" +#include "exec/memory.h" #include "vmstate.h" struct SHPCDevice { diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c index dbb4b3b433..7818dcc350 100644 --- a/hw/pci_bridge_dev.c +++ b/hw/pci_bridge_dev.c @@ -24,7 +24,7 @@ #include "pci/msi.h" #include "pci/shpc.h" #include "pci/slotid_cap.h" -#include "memory.h" +#include "exec/memory.h" #include "pci/pci_bus.h" #define REDHAT_PCI_VENDOR_ID 0x1b36 diff --git a/hw/pcnet.h b/hw/pcnet.h index 96643117a0..9dee6f3e2c 100644 --- a/hw/pcnet.h +++ b/hw/pcnet.h @@ -7,7 +7,7 @@ #define PCNET_LOOPTEST_CRC 1 #define PCNET_LOOPTEST_NOCRC 2 -#include "memory.h" +#include "exec/memory.h" /* BUS CONFIGURATION REGISTERS */ #define BCR_MSRDA 0 diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c index df51a74450..4eab0f2d8b 100644 --- a/hw/petalogix_ml605_mmu.c +++ b/hw/petalogix_ml605_mmu.c @@ -35,7 +35,7 @@ #include "xilinx.h" #include "blockdev.h" #include "serial.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "ssi.h" #include "microblaze_boot.h" diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c index 37b0d5595a..124a88eeda 100644 --- a/hw/petalogix_s3adsp1800_mmu.c +++ b/hw/petalogix_s3adsp1800_mmu.c @@ -32,7 +32,7 @@ #include "boards.h" #include "xilinx.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "microblaze_boot.h" #include "microblaze_pic_cpu.h" diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index a2f6360838..36af4647df 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -40,7 +40,7 @@ #include "flash.h" #include "block/block.h" #include "qemu-timer.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "host-utils.h" #include "sysbus.h" diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c index beab67fc87..c689cc9f42 100644 --- a/hw/pflash_cfi02.c +++ b/hw/pflash_cfi02.c @@ -39,7 +39,7 @@ #include "flash.h" #include "qemu-timer.h" #include "block/block.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "host-utils.h" #include "sysbus.h" diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 4690bd8b00..798e67cedf 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -33,7 +33,7 @@ #include "hw/loader.h" #include "elf.h" #include "hw/sysbus.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "host-utils.h" #include "hw/ppce500_pci.h" diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c index b875e3b615..5a0e0260e6 100644 --- a/hw/ppc405_boards.c +++ b/hw/ppc405_boards.c @@ -32,7 +32,7 @@ #include "qemu-log.h" #include "loader.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define BIOS_FILENAME "ppc405_rom.bin" #define BIOS_SIZE (2048 * 1024) diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c index 0f458ef772..aabb2efb48 100644 --- a/hw/ppc405_uc.c +++ b/hw/ppc405_uc.c @@ -28,7 +28,7 @@ #include "qemu-timer.h" #include "sysemu.h" #include "qemu-log.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define DEBUG_OPBA #define DEBUG_SDRAM diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c index 5193a0c4be..591d7b0088 100644 --- a/hw/ppc440_bamboo.c +++ b/hw/ppc440_bamboo.c @@ -22,7 +22,7 @@ #include "device_tree.h" #include "loader.h" #include "elf.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "serial.h" #include "ppc.h" #include "ppc405.h" diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c index bac8d8769a..3b9dc06716 100644 --- a/hw/ppc4xx_devs.c +++ b/hw/ppc4xx_devs.c @@ -25,7 +25,7 @@ #include "ppc.h" #include "ppc4xx.h" #include "qemu-log.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" //#define DEBUG_MMIO //#define DEBUG_UNASSIGNED diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c index 3e8af11f08..ba2d669b83 100644 --- a/hw/ppc4xx_pci.c +++ b/hw/ppc4xx_pci.c @@ -24,7 +24,7 @@ #include "ppc4xx.h" #include "pci/pci.h" #include "pci/pci_host.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #undef DEBUG #ifdef DEBUG diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h index 524b2368a4..89c7d66386 100644 --- a/hw/ppc_mac.h +++ b/hw/ppc_mac.h @@ -25,7 +25,7 @@ #if !defined(__PPC_MAC_H__) #define __PPC_MAC_H__ -#include "memory.h" +#include "exec/memory.h" /* SMP is not enabled, for now */ #define MAX_CPUS 1 diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index 657f405f1b..b2d02eaff2 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -66,7 +66,7 @@ #include "kvm_ppc.h" #include "hw/usb.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "sysbus.h" #define MAX_IDE_BUS 2 diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index a149306cc9..7a8a039d7e 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -42,7 +42,7 @@ #include "kvm.h" #include "kvm_ppc.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define MAX_IDE_BUS 2 #define CFG_ADDR 0xf0000510 diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index 25cc0490f9..aa46cc6f55 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -39,7 +39,7 @@ #include "mc146818rtc.h" #include "blockdev.h" #include "arch_init.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" //#define HARD_DEBUG_PPC_IO //#define DEBUG_PPC_IO diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 9bffbb9f87..feefc6596b 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -317,7 +317,7 @@ static const VMStateDescription vmstate_ppce500_pci = { } }; -#include "exec-memory.h" +#include "exec/address-spaces.h" static int e500_pcihost_bridge_initfn(PCIDevice *d) { diff --git a/hw/prep_pci.c b/hw/prep_pci.c index 5f22de647a..212a2ac4f1 100644 --- a/hw/prep_pci.c +++ b/hw/prep_pci.c @@ -26,7 +26,7 @@ #include "pci/pci.h" #include "pci/pci_host.h" #include "pc.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost" diff --git a/hw/puv3.c b/hw/puv3.c index 9f8e294ad5..7814bc5051 100644 --- a/hw/puv3.c +++ b/hw/puv3.c @@ -12,7 +12,7 @@ #include "qemu-common.h" #include "ui/console.h" #include "elf.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "sysbus.h" #include "boards.h" #include "loader.h" diff --git a/hw/pxa.h b/hw/pxa.h index 49ac820ea2..c2577d1d94 100644 --- a/hw/pxa.h +++ b/hw/pxa.h @@ -9,7 +9,7 @@ #ifndef PXA_H # define PXA_H "pxa.h" -#include "memory.h" +#include "exec/memory.h" /* Interrupt numbers */ # define PXA2XX_PIC_SSP3 0 diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c index 552ee21f82..3bfe101d79 100644 --- a/hw/qdev-addr.c +++ b/hw/qdev-addr.c @@ -1,6 +1,6 @@ #include "qdev.h" #include "qdev-addr.h" -#include "hwaddr.h" +#include "exec/hwaddr.h" #include "qapi/visitor.h" /* --- target physical address --- */ diff --git a/hw/r2d.c b/hw/r2d.c index b1c278f73f..d7a26bf398 100644 --- a/hw/r2d.c +++ b/hw/r2d.c @@ -37,7 +37,7 @@ #include "usb.h" #include "flash.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define FLASH_BASE 0x00000000 #define FLASH_SIZE 0x02000000 diff --git a/hw/realview.c b/hw/realview.c index 17d1ba2266..9c55bf29b7 100644 --- a/hw/realview.c +++ b/hw/realview.c @@ -17,7 +17,7 @@ #include "boards.h" #include "i2c.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define SMP_BOOT_ADDR 0xe0000000 #define SMP_BOOTREG_ADDR 0x10000030 diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index b732bccef8..0a15625b73 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -29,7 +29,7 @@ #include "hw/virtio.h" #include "hw/sysbus.h" #include "kvm.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "hw/s390-virtio-bus.h" #include "hw/s390x/sclp.h" diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c index 5c274fa03d..bc9b0aeb00 100644 --- a/hw/s390x/sclp.c +++ b/hw/s390x/sclp.c @@ -14,7 +14,7 @@ #include "cpu.h" #include "kvm.h" -#include "memory.h" +#include "exec/memory.h" #include "sclp.h" diff --git a/hw/serial.c b/hw/serial.c index 07a2a11931..3968c4fc46 100644 --- a/hw/serial.c +++ b/hw/serial.c @@ -26,7 +26,7 @@ #include "serial.h" #include "qemu-char.h" #include "qemu-timer.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" //#define DEBUG_SERIAL diff --git a/hw/serial.h b/hw/serial.h index 2d7d614e09..5722f8a353 100644 --- a/hw/serial.h +++ b/hw/serial.h @@ -27,7 +27,7 @@ #include "hw.h" #include "sysemu.h" -#include "memory.h" +#include "exec/memory.h" #define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */ diff --git a/hw/sh7750.c b/hw/sh7750.c index 8bcf0df96f..08945750c4 100644 --- a/hw/sh7750.c +++ b/hw/sh7750.c @@ -30,7 +30,7 @@ #include "sh7750_regnames.h" #include "sh_intc.h" #include "cpu.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define NB_DEVICES 4 diff --git a/hw/sh_intc.h b/hw/sh_intc.h index 80c9430577..6f11beeddd 100644 --- a/hw/sh_intc.h +++ b/hw/sh_intc.h @@ -3,7 +3,7 @@ #include "qemu-common.h" #include "irq.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" typedef unsigned char intc_enum; diff --git a/hw/sh_pci.c b/hw/sh_pci.c index 9ea08c8f8e..d5218420a3 100644 --- a/hw/sh_pci.c +++ b/hw/sh_pci.c @@ -26,7 +26,7 @@ #include "pci/pci.h" #include "pci/pci_host.h" #include "bswap.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" typedef struct SHPCIState { SysBusDevice busdev; diff --git a/hw/sh_serial.c b/hw/sh_serial.c index 9da5d08fee..63723496f1 100644 --- a/hw/sh_serial.c +++ b/hw/sh_serial.c @@ -27,7 +27,7 @@ #include "hw.h" #include "sh.h" #include "qemu-char.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" //#define DEBUG_SERIAL diff --git a/hw/sh_timer.c b/hw/sh_timer.c index c0365b1142..da6689f369 100644 --- a/hw/sh_timer.c +++ b/hw/sh_timer.c @@ -11,7 +11,7 @@ #include "hw.h" #include "sh.h" #include "qemu-timer.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "ptimer.h" //#define DEBUG_TIMER diff --git a/hw/shix.c b/hw/shix.c index b56dd54f75..821196e84c 100644 --- a/hw/shix.c +++ b/hw/shix.c @@ -32,7 +32,7 @@ #include "sysemu.h" #include "boards.h" #include "loader.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define BIOS_FILENAME "shix_bios.bin" #define BIOS_ADDRESS 0xA0000000 diff --git a/hw/soc_dma.h b/hw/soc_dma.h index 6ca4166184..7379731afd 100644 --- a/hw/soc_dma.h +++ b/hw/soc_dma.h @@ -22,7 +22,7 @@ #define HW_SOC_DMA_H 1 -#include "memory.h" +#include "exec/memory.h" #include "hw/irq.h" struct soc_dma_s; diff --git a/hw/spapr.c b/hw/spapr.c index 395c4ac69b..d1252fc68c 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -47,7 +47,7 @@ #include "kvm_ppc.h" #include "pci/pci.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "hw/usb.h" #include "qemu-config.h" diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c index 3011b251d3..fb968b250b 100644 --- a/hw/spapr_iommu.c +++ b/hw/spapr_iommu.c @@ -21,7 +21,7 @@ #include "qdev.h" #include "kvm_ppc.h" #include "dma.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "hw/spapr.h" diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 786f6f4222..27b3ad3d60 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -29,7 +29,7 @@ #include "pci/pci_host.h" #include "hw/spapr.h" #include "hw/spapr_pci.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include #include "trace.h" diff --git a/hw/spitz.c b/hw/spitz.c index 1500161d44..48668a0f10 100644 --- a/hw/spitz.c +++ b/hw/spitz.c @@ -27,7 +27,7 @@ #include "boards.h" #include "blockdev.h" #include "sysbus.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #undef REG_FMT #define REG_FMT "0x%02lx" diff --git a/hw/stellaris.c b/hw/stellaris.c index f3eb4bbc01..368f8a5e73 100644 --- a/hw/stellaris.c +++ b/hw/stellaris.c @@ -15,7 +15,7 @@ #include "i2c.h" #include "net/net.h" #include "boards.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define GPIO_A 0 #define GPIO_B 1 diff --git a/hw/strongarm.h b/hw/strongarm.h index d30dd6ac5e..2893f94445 100644 --- a/hw/strongarm.h +++ b/hw/strongarm.h @@ -1,7 +1,7 @@ #ifndef _STRONGARM_H #define _STRONGARM_H -#include "memory.h" +#include "exec/memory.h" #define SA_CS0 0x00000000 #define SA_CS1 0x08000000 diff --git a/hw/sun4u.c b/hw/sun4u.c index d9e752fe83..000f6118e1 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -39,7 +39,7 @@ #include "loader.h" #include "elf.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" //#define DEBUG_IRQ //#define DEBUG_EBUS diff --git a/hw/sysbus.c b/hw/sysbus.c index ef8ffb6603..7ab250463c 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -19,7 +19,7 @@ #include "sysbus.h" #include "monitor.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent); static char *sysbus_get_fw_dev_path(DeviceState *dev); diff --git a/hw/sysbus.h b/hw/sysbus.h index e58baaae36..669cf87ae9 100644 --- a/hw/sysbus.h +++ b/hw/sysbus.h @@ -4,7 +4,7 @@ /* Devices attached directly to the main system bus. */ #include "qdev.h" -#include "memory.h" +#include "exec/memory.h" #define QDEV_MAX_MMIO 32 #define QDEV_MAX_PIO 32 diff --git a/hw/tosa.c b/hw/tosa.c index 3991a909b5..6fdbec53ee 100644 --- a/hw/tosa.c +++ b/hw/tosa.c @@ -23,7 +23,7 @@ #include "ssi.h" #include "blockdev.h" #include "sysbus.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define TOSA_RAM 0x04000000 #define TOSA_ROM 0x00800000 diff --git a/hw/usb/libhw.c b/hw/usb/libhw.c index 24d3cad3a2..672d7a5598 100644 --- a/hw/usb/libhw.c +++ b/hw/usb/libhw.c @@ -20,7 +20,7 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "cpu-common.h" +#include "exec/cpu-common.h" #include "hw/usb.h" #include "dma.h" diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c index 7a543b47d0..1f4d66934c 100644 --- a/hw/versatile_pci.c +++ b/hw/versatile_pci.c @@ -10,7 +10,7 @@ #include "sysbus.h" #include "pci/pci.h" #include "pci/pci_host.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" typedef struct { SysBusDevice busdev; diff --git a/hw/versatilepb.c b/hw/versatilepb.c index af398d9cca..bd9c01564a 100644 --- a/hw/versatilepb.c +++ b/hw/versatilepb.c @@ -16,7 +16,7 @@ #include "i2c.h" #include "boards.h" #include "blockdev.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "flash.h" #define VERSATILE_FLASH_ADDR 0x34000000 diff --git a/hw/vexpress.c b/hw/vexpress.c index 5c9c08b991..e7b9e93852 100644 --- a/hw/vexpress.c +++ b/hw/vexpress.c @@ -28,7 +28,7 @@ #include "net/net.h" #include "sysemu.h" #include "boards.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "blockdev.h" #include "flash.h" diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 264e58a68b..096621cdbd 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -28,9 +28,9 @@ #include "config.h" #include "event_notifier.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "kvm.h" -#include "memory.h" +#include "exec/memory.h" #include "pci/msi.h" #include "pci/msix.h" #include "pci/pci.h" diff --git a/hw/vga_int.h b/hw/vga_int.h index 5efaee81d9..8d496ea9bf 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -26,7 +26,7 @@ #include #include "qapi/error.h" -#include "memory.h" +#include "exec/memory.h" #define ST01_V_RETRACE 0x08 #define ST01_DISP_ENABLE 0x01 diff --git a/hw/vhost.c b/hw/vhost.c index 16322a14f4..feaff64c15 100644 --- a/hw/vhost.c +++ b/hw/vhost.c @@ -18,7 +18,7 @@ #include "hw/hw.h" #include "range.h" #include -#include "exec-memory.h" +#include "exec/address-spaces.h" static void vhost_dev_sync_region(struct vhost_dev *dev, MemoryRegionSection *section, diff --git a/hw/vhost.h b/hw/vhost.h index 0c47229f91..6f6a906f4f 100644 --- a/hw/vhost.h +++ b/hw/vhost.h @@ -3,7 +3,7 @@ #include "hw/hw.h" #include "hw/virtio.h" -#include "memory.h" +#include "exec/memory.h" /* Generic structures common for any vhost based device. */ struct vhost_virtqueue { diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c index 1fdbc497cc..0f27c2b414 100644 --- a/hw/virtex_ml507.c +++ b/hw/virtex_ml507.c @@ -33,7 +33,7 @@ #include "loader.h" #include "elf.h" #include "qemu-log.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "ppc.h" #include "ppc4xx.h" diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c index dd1a6506cf..97d3a932d9 100644 --- a/hw/virtio-balloon.c +++ b/hw/virtio-balloon.c @@ -21,7 +21,7 @@ #include "balloon.h" #include "virtio-balloon.h" #include "kvm.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #if defined(__linux__) #include diff --git a/hw/vt82c686.c b/hw/vt82c686.c index f963912112..edceb5a01d 100644 --- a/hw/vt82c686.c +++ b/hw/vt82c686.c @@ -24,7 +24,7 @@ #include "pm_smbus.h" #include "sysemu.h" #include "qemu-timer.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" typedef uint32_t pci_addr_t; #include "pci/pci_host.h" diff --git a/hw/xen_platform.c b/hw/xen_platform.c index 023499eb55..e7611bb353 100644 --- a/hw/xen_platform.c +++ b/hw/xen_platform.c @@ -32,7 +32,7 @@ #include "xen_common.h" #include "xen_backend.h" #include "trace.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include diff --git a/hw/xen_pt.c b/hw/xen_pt.c index c782cdb283..5c50d562d9 100644 --- a/hw/xen_pt.c +++ b/hw/xen_pt.c @@ -59,7 +59,7 @@ #include "xen_backend.h" #include "xen_pt.h" #include "range.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #define XEN_PT_NR_IRQS (256) static uint8_t xen_pt_mapped_machine_irq[XEN_PT_NR_IRQS] = {0}; diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c index 67adc52725..156648a5d1 100644 --- a/hw/xilinx_zynq.c +++ b/hw/xilinx_zynq.c @@ -18,7 +18,7 @@ #include "sysbus.h" #include "arm-misc.h" #include "net/net.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include "sysemu.h" #include "boards.h" #include "flash.h" diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c index 0399de777e..c6c880eba5 100644 --- a/hw/xtensa_lx60.c +++ b/hw/xtensa_lx60.c @@ -29,8 +29,8 @@ #include "boards.h" #include "loader.h" #include "elf.h" -#include "memory.h" -#include "exec-memory.h" +#include "exec/memory.h" +#include "exec/address-spaces.h" #include "serial.h" #include "net/net.h" #include "sysbus.h" diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c index 0d633e4724..29b5f22a18 100644 --- a/hw/xtensa_sim.c +++ b/hw/xtensa_sim.c @@ -29,8 +29,8 @@ #include "boards.h" #include "loader.h" #include "elf.h" -#include "memory.h" -#include "exec-memory.h" +#include "exec/memory.h" +#include "exec/address-spaces.h" static uint64_t translate_phys_addr(void *env, uint64_t addr) { diff --git a/hw/z2.c b/hw/z2.c index d46186430f..ec35f3e444 100644 --- a/hw/z2.c +++ b/hw/z2.c @@ -23,7 +23,7 @@ #include "blockdev.h" #include "ui/console.h" #include "audio/audio.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #ifdef DEBUG_Z2 #define DPRINTF(fmt, ...) \ diff --git a/exec-memory.h b/include/exec/address-spaces.h similarity index 97% rename from exec-memory.h rename to include/exec/address-spaces.h index ac1d07dfe4..3d12cddeec 100644 --- a/exec-memory.h +++ b/include/exec/address-spaces.h @@ -19,7 +19,7 @@ * you're one of them. */ -#include "memory.h" +#include "exec/memory.h" #ifndef CONFIG_USER_ONLY diff --git a/cpu-all.h b/include/exec/cpu-all.h similarity index 99% rename from cpu-all.h rename to include/exec/cpu-all.h index d6b2b19743..bec04e2008 100644 --- a/cpu-all.h +++ b/include/exec/cpu-all.h @@ -21,7 +21,7 @@ #include "qemu-common.h" #include "qemu-tls.h" -#include "cpu-common.h" +#include "exec/cpu-common.h" /* some important defines: * @@ -180,7 +180,7 @@ static inline void tswap64s(uint64_t *s) #if defined(CONFIG_USER_ONLY) #include -#include "qemu-user-types.h" +#include "exec/user/abitypes.h" /* On some host systems the guest address space is reserved on the host. * This allows the guest address space to be offset to a convenient location. diff --git a/cpu-common.h b/include/exec/cpu-common.h similarity index 98% rename from cpu-common.h rename to include/exec/cpu-common.h index d2fbafac9c..f83d6180f3 100644 --- a/cpu-common.h +++ b/include/exec/cpu-common.h @@ -3,10 +3,10 @@ /* CPU interfaces that are target independent. */ -#include "hwaddr.h" +#include "exec/hwaddr.h" #ifndef NEED_CPU_H -#include "poison.h" +#include "exec/poison.h" #endif #include "bswap.h" diff --git a/cpu-defs.h b/include/exec/cpu-defs.h similarity index 99% rename from cpu-defs.h rename to include/exec/cpu-defs.h index 3669241faf..8d2230e50e 100644 --- a/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -29,7 +29,7 @@ #include #include "osdep.h" #include "qemu-queue.h" -#include "hwaddr.h" +#include "exec/hwaddr.h" #ifndef TARGET_LONG_BITS #error TARGET_LONG_BITS must be defined before including this header diff --git a/cputlb.h b/include/exec/cputlb.h similarity index 100% rename from cputlb.h rename to include/exec/cputlb.h diff --git a/def-helper.h b/include/exec/def-helper.h similarity index 100% rename from def-helper.h rename to include/exec/def-helper.h diff --git a/exec-all.h b/include/exec/exec-all.h similarity index 98% rename from exec-all.h rename to include/exec/exec-all.h index e9b07cd986..2ae8aae3d6 100644 --- a/exec-all.h +++ b/include/exec/exec-all.h @@ -275,7 +275,7 @@ static inline void tb_add_jump(TranslationBlock *tb, int n, } } -#include "qemu-lock.h" +#include "exec/spinlock.h" extern spinlock_t tb_lock; @@ -353,22 +353,22 @@ void io_mem_write(struct MemoryRegion *mr, hwaddr addr, void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr); -#include "softmmu_defs.h" +#include "exec/softmmu_defs.h" #define ACCESS_TYPE (NB_MMU_MODES + 1) #define MEMSUFFIX _code #define DATA_SIZE 1 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 2 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 4 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 8 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #undef ACCESS_TYPE #undef MEMSUFFIX diff --git a/gdbstub.h b/include/exec/gdbstub.h similarity index 100% rename from gdbstub.h rename to include/exec/gdbstub.h diff --git a/gen-icount.h b/include/exec/gen-icount.h similarity index 100% rename from gen-icount.h rename to include/exec/gen-icount.h diff --git a/hwaddr.h b/include/exec/hwaddr.h similarity index 100% rename from hwaddr.h rename to include/exec/hwaddr.h diff --git a/ioport.h b/include/exec/ioport.h similarity index 99% rename from ioport.h rename to include/exec/ioport.h index 23441cba08..fc28350a3c 100644 --- a/ioport.h +++ b/include/exec/ioport.h @@ -25,7 +25,7 @@ #define IOPORT_H #include "qemu-common.h" -#include "iorange.h" +#include "exec/iorange.h" typedef uint32_t pio_addr_t; #define FMT_pioaddr PRIx32 diff --git a/iorange.h b/include/exec/iorange.h similarity index 100% rename from iorange.h rename to include/exec/iorange.h diff --git a/memory-internal.h b/include/exec/memory-internal.h similarity index 100% rename from memory-internal.h rename to include/exec/memory-internal.h diff --git a/memory.h b/include/exec/memory.h similarity index 99% rename from memory.h rename to include/exec/memory.h index 9462bfd3ad..b0c474584f 100644 --- a/memory.h +++ b/include/exec/memory.h @@ -19,11 +19,11 @@ #include #include #include "qemu-common.h" -#include "cpu-common.h" -#include "hwaddr.h" +#include "exec/cpu-common.h" +#include "exec/hwaddr.h" #include "qemu-queue.h" -#include "iorange.h" -#include "ioport.h" +#include "exec/iorange.h" +#include "exec/ioport.h" #include "int128.h" typedef struct MemoryRegionOps MemoryRegionOps; diff --git a/poison.h b/include/exec/poison.h similarity index 100% rename from poison.h rename to include/exec/poison.h diff --git a/softmmu-semi.h b/include/exec/softmmu-semi.h similarity index 100% rename from softmmu-semi.h rename to include/exec/softmmu-semi.h diff --git a/softmmu_defs.h b/include/exec/softmmu_defs.h similarity index 100% rename from softmmu_defs.h rename to include/exec/softmmu_defs.h diff --git a/softmmu_exec.h b/include/exec/softmmu_exec.h similarity index 72% rename from softmmu_exec.h rename to include/exec/softmmu_exec.h index 8c73985599..3e4e886a30 100644 --- a/softmmu_exec.h +++ b/include/exec/softmmu_exec.h @@ -19,37 +19,37 @@ #define ldul_executive ldl_executive #define ldul_supervisor ldl_supervisor -#include "softmmu_defs.h" +#include "exec/softmmu_defs.h" #define ACCESS_TYPE 0 #define MEMSUFFIX MMU_MODE0_SUFFIX #define DATA_SIZE 1 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 2 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 4 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 8 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #undef ACCESS_TYPE #undef MEMSUFFIX #define ACCESS_TYPE 1 #define MEMSUFFIX MMU_MODE1_SUFFIX #define DATA_SIZE 1 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 2 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 4 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 8 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #undef ACCESS_TYPE #undef MEMSUFFIX @@ -58,16 +58,16 @@ #define ACCESS_TYPE 2 #define MEMSUFFIX MMU_MODE2_SUFFIX #define DATA_SIZE 1 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 2 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 4 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 8 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #undef ACCESS_TYPE #undef MEMSUFFIX #endif /* (NB_MMU_MODES >= 3) */ @@ -77,16 +77,16 @@ #define ACCESS_TYPE 3 #define MEMSUFFIX MMU_MODE3_SUFFIX #define DATA_SIZE 1 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 2 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 4 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 8 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #undef ACCESS_TYPE #undef MEMSUFFIX #endif /* (NB_MMU_MODES >= 4) */ @@ -96,16 +96,16 @@ #define ACCESS_TYPE 4 #define MEMSUFFIX MMU_MODE4_SUFFIX #define DATA_SIZE 1 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 2 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 4 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 8 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #undef ACCESS_TYPE #undef MEMSUFFIX #endif /* (NB_MMU_MODES >= 5) */ @@ -115,16 +115,16 @@ #define ACCESS_TYPE 5 #define MEMSUFFIX MMU_MODE5_SUFFIX #define DATA_SIZE 1 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 2 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 4 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 8 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #undef ACCESS_TYPE #undef MEMSUFFIX #endif /* (NB_MMU_MODES >= 6) */ @@ -137,16 +137,16 @@ #define ACCESS_TYPE (NB_MMU_MODES) #define MEMSUFFIX _data #define DATA_SIZE 1 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 2 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 4 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #define DATA_SIZE 8 -#include "softmmu_header.h" +#include "exec/softmmu_header.h" #undef ACCESS_TYPE #undef MEMSUFFIX diff --git a/softmmu_header.h b/include/exec/softmmu_header.h similarity index 100% rename from softmmu_header.h rename to include/exec/softmmu_header.h diff --git a/softmmu_template.h b/include/exec/softmmu_template.h similarity index 99% rename from softmmu_template.h rename to include/exec/softmmu_template.h index ce30d8bddc..15d4c519ee 100644 --- a/softmmu_template.h +++ b/include/exec/softmmu_template.h @@ -22,7 +22,7 @@ * License along with this library; if not, see . */ #include "qemu-timer.h" -#include "memory.h" +#include "exec/memory.h" #define DATA_SIZE (1 << SHIFT) diff --git a/qemu-lock.h b/include/exec/spinlock.h similarity index 100% rename from qemu-lock.h rename to include/exec/spinlock.h diff --git a/qemu-user-types.h b/include/exec/user/abitypes.h similarity index 100% rename from qemu-user-types.h rename to include/exec/user/abitypes.h diff --git a/thunk.h b/include/exec/user/thunk.h similarity index 100% rename from thunk.h rename to include/exec/user/thunk.h diff --git a/ioport.c b/ioport.c index 6e4ca0dd91..a0ac2a0a41 100644 --- a/ioport.c +++ b/ioport.c @@ -25,9 +25,9 @@ * splitted out ioport related stuffs from vl.c. */ -#include "ioport.h" +#include "exec/ioport.h" #include "trace.h" -#include "memory.h" +#include "exec/memory.h" /***********************************************************/ /* IO Port */ diff --git a/kvm-all.c b/kvm-all.c index 759ef17ab0..c2588594e1 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -27,11 +27,11 @@ #include "sysemu.h" #include "hw/hw.h" #include "hw/pci/msi.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #include "kvm.h" #include "bswap.h" -#include "memory.h" -#include "exec-memory.h" +#include "exec/memory.h" +#include "exec/address-spaces.h" #include "event_notifier.h" /* This check must be after config-host.h is included */ diff --git a/kvm-stub.c b/kvm-stub.c index d65fd04507..8de8ebd3d2 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -14,7 +14,7 @@ #include "hw/hw.h" #include "hw/pci/msi.h" #include "cpu.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #include "kvm.h" KVMState *kvm_state; diff --git a/linux-user/qemu.h b/linux-user/qemu.h index ceddb3ce72..2af883bf74 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -11,13 +11,13 @@ #include #endif /* DEBUG_REMAP */ -#include "qemu-user-types.h" +#include "exec/user/abitypes.h" -#include "thunk.h" +#include "exec/user/thunk.h" #include "syscall_defs.h" #include "syscall.h" #include "target_signal.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #include "qemu-queue.h" #if defined(CONFIG_USE_NPTL) diff --git a/memory.c b/memory.c index 741985385c..d40193d474 100644 --- a/memory.c +++ b/memory.c @@ -13,14 +13,14 @@ * GNU GPL, version 2 or (at your option) any later version. */ -#include "memory.h" -#include "exec-memory.h" -#include "ioport.h" +#include "exec/memory.h" +#include "exec/address-spaces.h" +#include "exec/ioport.h" #include "bitops.h" #include "kvm.h" #include -#include "memory-internal.h" +#include "exec/memory-internal.h" static unsigned memory_region_transaction_depth; static bool memory_region_update_pending; diff --git a/memory_mapping-stub.c b/memory_mapping-stub.c index 76be34d89f..5f5fb99c58 100644 --- a/memory_mapping-stub.c +++ b/memory_mapping-stub.c @@ -12,7 +12,7 @@ */ #include "cpu.h" -#include "cpu-all.h" +#include "exec/cpu-all.h" #include "memory_mapping.h" int qemu_get_guest_memory_mapping(MemoryMappingList *list) diff --git a/memory_mapping.c b/memory_mapping.c index a82e190cab..c829a9fa34 100644 --- a/memory_mapping.c +++ b/memory_mapping.c @@ -12,7 +12,7 @@ */ #include "cpu.h" -#include "cpu-all.h" +#include "exec/cpu-all.h" #include "memory_mapping.h" static void memory_mapping_list_add_mapping_sorted(MemoryMappingList *list, diff --git a/monitor.c b/monitor.c index 7d5c8a622c..a3e010968e 100644 --- a/monitor.c +++ b/monitor.c @@ -30,7 +30,7 @@ #include "hw/pci/pci.h" #include "hw/watchdog.h" #include "hw/loader.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #include "net/net.h" #include "net/slirp.h" #include "qemu-char.h" @@ -63,7 +63,7 @@ #include "trace/simple.h" #endif #include "ui/qemu-spice.h" -#include "memory.h" +#include "exec/memory.h" #include "qmp-commands.h" #include "hmp.h" #include "qemu-thread.h" diff --git a/qtest.c b/qtest.c index fbfab4e1a7..ebe3963167 100644 --- a/qtest.c +++ b/qtest.c @@ -14,8 +14,8 @@ #include "qtest.h" #include "hw/qdev.h" #include "qemu-char.h" -#include "ioport.h" -#include "memory.h" +#include "exec/ioport.h" +#include "exec/memory.h" #include "hw/irq.h" #include "sysemu.h" #include "cpus.h" diff --git a/savevm.c b/savevm.c index ae8787868f..cb33501ecc 100644 --- a/savevm.c +++ b/savevm.c @@ -82,7 +82,7 @@ #include "qemu-queue.h" #include "qemu-timer.h" #include "cpus.h" -#include "memory.h" +#include "exec/memory.h" #include "qmp-commands.h" #include "trace.h" #include "bitops.h" diff --git a/scripts/feature_to_c.sh b/scripts/feature_to_c.sh index b62da8a0bd..888548e58b 100644 --- a/scripts/feature_to_c.sh +++ b/scripts/feature_to_c.sh @@ -38,7 +38,7 @@ for input; do ${AWK:-awk} 'BEGIN { n = 0 printf "#include \"config.h\"\n" printf "#include \"qemu-common.h\"\n" - printf "#include \"gdbstub.h\"\n" + printf "#include \"exec/gdbstub.h\"\n" print "static const char '$arrayname'[] = {" for (i = 0; i < 255; i++) _ord_[sprintf("%c", i)] = i diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 9939d61ca8..137703f6d7 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -27,7 +27,7 @@ #define CPUArchState struct CPUAlphaState -#include "cpu-defs.h" +#include "exec/cpu-defs.h" #include "softfloat.h" @@ -295,7 +295,7 @@ struct CPUAlphaState { #define cpu_gen_code cpu_alpha_gen_code #define cpu_signal_handler cpu_alpha_signal_handler -#include "cpu-all.h" +#include "exec/cpu-all.h" #include "cpu-qom.h" enum { @@ -520,7 +520,7 @@ static inline bool cpu_has_work(CPUState *cpu) | CPU_INTERRUPT_MCHK); } -#include "exec-all.h" +#include "exec/exec-all.h" static inline void cpu_pc_from_tb(CPUAlphaState *env, TranslationBlock *tb) { diff --git a/target-alpha/helper.h b/target-alpha/helper.h index dd55f89aad..eac3041b87 100644 --- a/target-alpha/helper.h +++ b/target-alpha/helper.h @@ -1,4 +1,4 @@ -#include "def-helper.h" +#include "exec/def-helper.h" DEF_HELPER_3(excp, noreturn, env, int, int) DEF_HELPER_FLAGS_1(load_pcc, TCG_CALL_NO_RWG_SE, i64, env) @@ -119,4 +119,4 @@ DEF_HELPER_FLAGS_0(get_time, TCG_CALL_NO_RWG, i64) DEF_HELPER_FLAGS_2(set_alarm, TCG_CALL_NO_RWG, void, env, i64) #endif -#include "def-helper.h" +#include "exec/def-helper.h" diff --git a/target-alpha/mem_helper.c b/target-alpha/mem_helper.c index 64b33f6518..3d2cd61358 100644 --- a/target-alpha/mem_helper.c +++ b/target-alpha/mem_helper.c @@ -117,22 +117,22 @@ void cpu_unassigned_access(CPUAlphaState *env, hwaddr addr, dynamic_excp(env, 0, EXCP_MCHK, 0); } -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #define MMUSUFFIX _mmu #define ALIGNED_ONLY #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" /* try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not diff --git a/target-alpha/translate.c b/target-alpha/translate.c index f57c8fd91f..2d0d891128 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -88,7 +88,7 @@ static TCGv cpu_usp; /* register names */ static char cpu_reg_names[10*4+21*5 + 10*5+21*6]; -#include "gen-icount.h" +#include "exec/gen-icount.h" static void alpha_translate_init(void) { diff --git a/target-arm/arm-semi.c b/target-arm/arm-semi.c index 7743d67010..847318d1f4 100644 --- a/target-arm/arm-semi.c +++ b/target-arm/arm-semi.c @@ -33,7 +33,7 @@ #define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024) #else #include "qemu-common.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #include "hw/arm-misc.h" #endif @@ -113,7 +113,7 @@ static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code) return code; } -#include "softmmu-semi.h" +#include "exec/softmmu-semi.h" #endif static target_ulong arm_semi_syscall_len; diff --git a/target-arm/cpu.h b/target-arm/cpu.h index e4ff918fa4..7f87efa7d9 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -27,7 +27,7 @@ #include "config.h" #include "qemu-common.h" -#include "cpu-defs.h" +#include "exec/cpu-defs.h" #include "softfloat.h" @@ -659,7 +659,7 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp) } #endif -#include "cpu-all.h" +#include "exec/cpu-all.h" /* Bit usage in the TB flags field: */ #define ARM_TBFLAG_THUMB_SHIFT 0 @@ -726,7 +726,7 @@ static inline bool cpu_has_work(CPUState *cpu) (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB); } -#include "exec-all.h" +#include "exec/exec-all.h" static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb) { diff --git a/target-arm/helper.c b/target-arm/helper.c index ab8b734933..1f7a3c04c3 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1,5 +1,5 @@ #include "cpu.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #include "helper.h" #include "host-utils.h" #include "sysemu.h" diff --git a/target-arm/helper.h b/target-arm/helper.h index 3d23ceb257..8544f82a94 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -1,4 +1,4 @@ -#include "def-helper.h" +#include "exec/def-helper.h" DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, i32, i32) DEF_HELPER_FLAGS_1(sxtb16, TCG_CALL_NO_RWG_SE, i32, i32) @@ -463,4 +463,4 @@ DEF_HELPER_3(neon_qzip8, void, env, i32, i32) DEF_HELPER_3(neon_qzip16, void, env, i32, i32) DEF_HELPER_3(neon_qzip32, void, env, i32, i32) -#include "def-helper.h" +#include "exec/def-helper.h" diff --git a/target-arm/iwmmxt_helper.c b/target-arm/iwmmxt_helper.c index 1dd8d1a3af..7953b53f7e 100644 --- a/target-arm/iwmmxt_helper.c +++ b/target-arm/iwmmxt_helper.c @@ -23,7 +23,7 @@ #include #include "cpu.h" -#include "exec-all.h" +#include "exec/exec-all.h" #include "helper.h" /* iwMMXt macros extracted from GNU gdb. */ diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c index 89280b6eeb..b028cc2c93 100644 --- a/target-arm/neon_helper.c +++ b/target-arm/neon_helper.c @@ -10,7 +10,7 @@ #include #include "cpu.h" -#include "exec-all.h" +#include "exec/exec-all.h" #include "helper.h" #define SIGNBIT (uint32_t)0x80000000 diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 1fcc975945..99610d7734 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -52,21 +52,21 @@ uint32_t HELPER(neon_tbl)(CPUARMState *env, uint32_t ireg, uint32_t def, #if !defined(CONFIG_USER_ONLY) -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #define MMUSUFFIX _mmu #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" /* try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not diff --git a/target-arm/translate.c b/target-arm/translate.c index 10c548d5ba..988b5428d4 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -98,7 +98,7 @@ static TCGv_i32 cpu_exclusive_info; static TCGv cpu_F0s, cpu_F1s; static TCGv_i64 cpu_F0d, cpu_F1d; -#include "gen-icount.h" +#include "exec/gen-icount.h" static const char *regnames[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", diff --git a/target-cris/cpu.h b/target-cris/cpu.h index 2c27506d0d..63e6234f11 100644 --- a/target-cris/cpu.h +++ b/target-cris/cpu.h @@ -27,7 +27,7 @@ #define CPUArchState struct CPUCRISState -#include "cpu-defs.h" +#include "exec/cpu-defs.h" #define TARGET_HAS_ICE 1 @@ -270,7 +270,7 @@ static inline void cpu_set_tls(CPUCRISState *env, target_ulong newtls) #define SFR_RW_MM_TLB_LO env->pregs[PR_SRS]][5 #define SFR_RW_MM_TLB_HI env->pregs[PR_SRS]][6 -#include "cpu-all.h" +#include "exec/cpu-all.h" static inline void cpu_get_tb_cpu_state(CPUCRISState *env, target_ulong *pc, target_ulong *cs_base, int *flags) @@ -292,7 +292,7 @@ static inline bool cpu_has_work(CPUState *cpu) return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI); } -#include "exec-all.h" +#include "exec/exec-all.h" static inline void cpu_pc_from_tb(CPUCRISState *env, TranslationBlock *tb) { diff --git a/target-cris/helper.h b/target-cris/helper.h index fe12083a16..8e8365cf69 100644 --- a/target-cris/helper.h +++ b/target-cris/helper.h @@ -1,4 +1,4 @@ -#include "def-helper.h" +#include "exec/def-helper.h" DEF_HELPER_2(raise_exception, void, env, i32) DEF_HELPER_2(tlb_flush_pid, void, env, i32) @@ -26,4 +26,4 @@ DEF_HELPER_FLAGS_3(evaluate_flags_move_2, TCG_CALL_NO_SE, i32, env, i32, i32) DEF_HELPER_1(evaluate_flags, void, env) DEF_HELPER_1(top_evaluate_flags, void, env) -#include "def-helper.h" +#include "exec/def-helper.h" diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c index 31db42494d..cd0e17e099 100644 --- a/target-cris/op_helper.c +++ b/target-cris/op_helper.c @@ -35,21 +35,21 @@ #endif #if !defined(CONFIG_USER_ONLY) -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #define MMUSUFFIX _mmu #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" /* Try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not diff --git a/target-cris/translate.c b/target-cris/translate.c index 2a92727843..09e6011ea4 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -70,7 +70,7 @@ static TCGv env_btaken; static TCGv env_btarget; static TCGv env_pc; -#include "gen-icount.h" +#include "exec/gen-icount.h" /* This is the state at translation time. */ typedef struct DisasContext { diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c index 4240278edd..50d866f4c6 100644 --- a/target-i386/arch_dump.c +++ b/target-i386/arch_dump.c @@ -12,7 +12,7 @@ */ #include "cpu.h" -#include "cpu-all.h" +#include "exec/cpu-all.h" #include "dump.h" #include "elf.h" diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c index 41f9d1c3e3..6dfb0f3f56 100644 --- a/target-i386/arch_memory_mapping.c +++ b/target-i386/arch_memory_mapping.c @@ -12,7 +12,7 @@ */ #include "cpu.h" -#include "cpu-all.h" +#include "exec/cpu-all.h" #include "memory_mapping.h" /* PAE Paging or IA-32e Paging */ diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 386c4f6d98..f3f50a0499 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -44,7 +44,7 @@ #define CPUArchState struct CPUX86State -#include "cpu-defs.h" +#include "exec/cpu-defs.h" #include "softfloat.h" @@ -1117,7 +1117,7 @@ static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp) } #endif -#include "cpu-all.h" +#include "exec/cpu-all.h" #include "svm.h" #if !defined(CONFIG_USER_ONLY) @@ -1137,7 +1137,7 @@ static inline bool cpu_has_work(CPUState *cpu) CPU_INTERRUPT_MCE)); } -#include "exec-all.h" +#include "exec/exec-all.h" static inline void cpu_pc_from_tb(CPUX86State *env, TranslationBlock *tb) { diff --git a/target-i386/fpu_helper.c b/target-i386/fpu_helper.c index dfc34a6253..44f3d27944 100644 --- a/target-i386/fpu_helper.c +++ b/target-i386/fpu_helper.c @@ -22,7 +22,7 @@ #include "helper.h" #if !defined(CONFIG_USER_ONLY) -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #endif /* !defined(CONFIG_USER_ONLY) */ #define FPU_RC_MASK 0xc00 diff --git a/target-i386/helper.h b/target-i386/helper.h index 970fcd98ff..9ed720d0ed 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -1,4 +1,4 @@ -#include "def-helper.h" +#include "exec/def-helper.h" DEF_HELPER_FLAGS_2(cc_compute_all, TCG_CALL_NO_SE, i32, env, int) DEF_HELPER_FLAGS_2(cc_compute_c, TCG_CALL_NO_SE, i32, env, int) @@ -220,4 +220,4 @@ DEF_HELPER_3(rclq, tl, env, tl, tl) DEF_HELPER_3(rcrq, tl, env, tl, tl) #endif -#include "def-helper.h" +#include "exec/def-helper.h" diff --git a/target-i386/ioport-user.c b/target-i386/ioport-user.c index 03fac22d22..f7636e0a87 100644 --- a/target-i386/ioport-user.c +++ b/target-i386/ioport-user.c @@ -21,7 +21,7 @@ #include "qemu.h" #include "qemu-common.h" -#include "ioport.h" +#include "exec/ioport.h" void cpu_outb(pio_addr_t addr, uint8_t val) { diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 824930c749..f7c95d5424 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -25,12 +25,12 @@ #include "kvm.h" #include "kvm_i386.h" #include "cpu.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #include "host-utils.h" #include "qemu-config.h" #include "hw/pc.h" #include "hw/apic.h" -#include "ioport.h" +#include "exec/ioport.h" #include "hyperv.h" #include "hw/pci/pci.h" diff --git a/target-i386/mem_helper.c b/target-i386/mem_helper.c index d0be77b1ed..6cf9ba076e 100644 --- a/target-i386/mem_helper.c +++ b/target-i386/mem_helper.c @@ -21,7 +21,7 @@ #include "helper.h" #if !defined(CONFIG_USER_ONLY) -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #endif /* !defined(CONFIG_USER_ONLY) */ /* broken thread support */ @@ -114,16 +114,16 @@ void helper_boundl(CPUX86State *env, target_ulong a0, int v) #define MMUSUFFIX _mmu #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #endif diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c index a02037963f..db3126b79b 100644 --- a/target-i386/misc_helper.c +++ b/target-i386/misc_helper.c @@ -18,11 +18,11 @@ */ #include "cpu.h" -#include "ioport.h" +#include "exec/ioport.h" #include "helper.h" #if !defined(CONFIG_USER_ONLY) -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #endif /* !defined(CONFIG_USER_ONLY) */ /* check if Port I/O is allowed in TSS */ diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c index ff9337441b..be795d71eb 100644 --- a/target-i386/seg_helper.c +++ b/target-i386/seg_helper.c @@ -25,7 +25,7 @@ //#define DEBUG_PCALL #if !defined(CONFIG_USER_ONLY) -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #endif /* !defined(CONFIG_USER_ONLY) */ #ifdef DEBUG_PCALL diff --git a/target-i386/svm_helper.c b/target-i386/svm_helper.c index a238d95a55..3f246e9073 100644 --- a/target-i386/svm_helper.c +++ b/target-i386/svm_helper.c @@ -18,11 +18,11 @@ */ #include "cpu.h" -#include "cpu-all.h" +#include "exec/cpu-all.h" #include "helper.h" #if !defined(CONFIG_USER_ONLY) -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #endif /* !defined(CONFIG_USER_ONLY) */ /* Secure Virtual Machine helpers */ diff --git a/target-i386/translate.c b/target-i386/translate.c index 026201e98e..32d21f52d0 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -65,7 +65,7 @@ static TCGv cpu_tmp5; static uint8_t gen_opc_cc_op[OPC_BUF_SIZE]; -#include "gen-icount.h" +#include "exec/gen-icount.h" #ifdef TARGET_X86_64 static int x86_64_hregs; diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h index 7243b4f7c7..4e202db32c 100644 --- a/target-lm32/cpu.h +++ b/target-lm32/cpu.h @@ -26,7 +26,7 @@ #include "config.h" #include "qemu-common.h" -#include "cpu-defs.h" +#include "exec/cpu-defs.h" struct CPULM32State; typedef struct CPULM32State CPULM32State; @@ -238,7 +238,7 @@ static inline int cpu_interrupts_enabled(CPULM32State *env) return env->ie & IE_IE; } -#include "cpu-all.h" +#include "exec/cpu-all.h" static inline target_ulong cpu_get_pc(CPULM32State *env) { @@ -260,7 +260,7 @@ static inline bool cpu_has_work(CPUState *cpu) return env->interrupt_request & CPU_INTERRUPT_HARD; } -#include "exec-all.h" +#include "exec/exec-all.h" static inline void cpu_pc_from_tb(CPULM32State *env, TranslationBlock *tb) { diff --git a/target-lm32/helper.h b/target-lm32/helper.h index 07f5670172..3ea15a6e80 100644 --- a/target-lm32/helper.h +++ b/target-lm32/helper.h @@ -1,4 +1,4 @@ -#include "def-helper.h" +#include "exec/def-helper.h" DEF_HELPER_2(raise_exception, void, env, i32) DEF_HELPER_1(hlt, void, env) @@ -11,4 +11,4 @@ DEF_HELPER_1(rcsr_ip, i32, env) DEF_HELPER_1(rcsr_jtx, i32, env) DEF_HELPER_1(rcsr_jrx, i32, env) -#include "def-helper.h" +#include "exec/def-helper.h" diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c index 97b9625c1a..27b3cef25c 100644 --- a/target-lm32/op_helper.c +++ b/target-lm32/op_helper.c @@ -9,13 +9,13 @@ #if !defined(CONFIG_USER_ONLY) #define MMUSUFFIX _mmu #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" void helper_raise_exception(CPULM32State *env, uint32_t index) { diff --git a/target-lm32/translate.c b/target-lm32/translate.c index 9683b9a4b5..6b87340174 100644 --- a/target-lm32/translate.c +++ b/target-lm32/translate.c @@ -53,7 +53,7 @@ static TCGv cpu_deba; static TCGv cpu_bp[4]; static TCGv cpu_wp[4]; -#include "gen-icount.h" +#include "exec/gen-icount.h" enum { OP_FMT_RI, diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index f4fcdeee7a..b37af1fffd 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -26,7 +26,7 @@ #include "config.h" #include "qemu-common.h" -#include "cpu-defs.h" +#include "exec/cpu-defs.h" #include "softfloat.h" @@ -242,7 +242,7 @@ static inline void cpu_clone_regs(CPUM68KState *env, target_ulong newsp) } #endif -#include "cpu-all.h" +#include "exec/cpu-all.h" static inline void cpu_get_tb_cpu_state(CPUM68KState *env, target_ulong *pc, target_ulong *cs_base, int *flags) @@ -261,7 +261,7 @@ static inline bool cpu_has_work(CPUState *cpu) return env->interrupt_request & CPU_INTERRUPT_HARD; } -#include "exec-all.h" +#include "exec/exec-all.h" static inline void cpu_pc_from_tb(CPUM68KState *env, TranslationBlock *tb) { diff --git a/target-m68k/helper.c b/target-m68k/helper.c index a5d0100473..a9a277865f 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -19,7 +19,7 @@ */ #include "cpu.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #include "helpers.h" diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h index 8112b44a58..2b024502ba 100644 --- a/target-m68k/helpers.h +++ b/target-m68k/helpers.h @@ -1,4 +1,4 @@ -#include "def-helper.h" +#include "exec/def-helper.h" DEF_HELPER_1(bitrev, i32, i32) DEF_HELPER_1(ff1, i32, i32) @@ -51,4 +51,4 @@ DEF_HELPER_3(set_mac_extu, void, env, i32, i32) DEF_HELPER_2(flush_flags, void, env, i32) DEF_HELPER_2(raise_exception, void, env, i32) -#include "def-helper.h" +#include "exec/def-helper.h" diff --git a/target-m68k/m68k-semi.c b/target-m68k/m68k-semi.c index 9f7a24cdb4..e6c7dd2f9b 100644 --- a/target-m68k/m68k-semi.c +++ b/target-m68k/m68k-semi.c @@ -33,8 +33,8 @@ #define SEMIHOSTING_HEAP_SIZE (128 * 1024 * 1024) #else #include "qemu-common.h" -#include "gdbstub.h" -#include "softmmu-semi.h" +#include "exec/gdbstub.h" +#include "exec/softmmu-semi.h" #endif #include "sysemu.h" diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c index b97ba5e28f..16df24c0ca 100644 --- a/target-m68k/op_helper.c +++ b/target-m68k/op_helper.c @@ -34,21 +34,21 @@ void do_interrupt_m68k_hardirq(CPUM68KState *env) extern int semihosting_enabled; -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #define MMUSUFFIX _mmu #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" /* Try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not diff --git a/target-m68k/translate.c b/target-m68k/translate.c index d955c7a409..1c9b5ec8d4 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -61,7 +61,7 @@ static TCGv NULL_QREG; /* Used to distinguish stores from bad addressing modes. */ static TCGv store_dummy; -#include "gen-icount.h" +#include "exec/gen-icount.h" void m68k_tcg_init(void) { diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h index 585bbd6dbc..5358941ae4 100644 --- a/target-microblaze/cpu.h +++ b/target-microblaze/cpu.h @@ -26,7 +26,7 @@ #define CPUArchState struct CPUMBState -#include "cpu-defs.h" +#include "exec/cpu-defs.h" #include "softfloat.h" struct CPUMBState; typedef struct CPUMBState CPUMBState; @@ -353,7 +353,7 @@ static inline int cpu_interrupts_enabled(CPUMBState *env) return env->sregs[SR_MSR] & MSR_IE; } -#include "cpu-all.h" +#include "exec/cpu-all.h" static inline target_ulong cpu_get_pc(CPUMBState *env) { @@ -381,7 +381,7 @@ static inline bool cpu_has_work(CPUState *cpu) return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI); } -#include "exec-all.h" +#include "exec/exec-all.h" static inline void cpu_pc_from_tb(CPUMBState *env, TranslationBlock *tb) { diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h index a667122e91..4e51429498 100644 --- a/target-microblaze/helper.h +++ b/target-microblaze/helper.h @@ -1,4 +1,4 @@ -#include "def-helper.h" +#include "exec/def-helper.h" DEF_HELPER_2(raise_exception, void, env, i32) DEF_HELPER_1(debug, void, env) @@ -38,4 +38,4 @@ DEF_HELPER_2(stackprot, void, env, i32) DEF_HELPER_2(get, i32, i32, i32) DEF_HELPER_3(put, void, i32, i32, i32) -#include "def-helper.h" +#include "exec/def-helper.h" diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c index 7593517094..343dcc15e7 100644 --- a/target-microblaze/op_helper.c +++ b/target-microblaze/op_helper.c @@ -26,17 +26,17 @@ #define D(x) #if !defined(CONFIG_USER_ONLY) -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #define MMUSUFFIX _mmu #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" /* Try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index 5946a5ba5c..58ce71267d 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -50,7 +50,7 @@ static TCGv env_btaken; static TCGv env_btarget; static TCGv env_iflags; -#include "gen-icount.h" +#include "exec/gen-icount.h" /* This is the state at translation time. */ typedef struct DisasContext { diff --git a/target-mips/cpu.h b/target-mips/cpu.h index aebb2d5b79..183ba9fbd8 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -12,7 +12,7 @@ #include "config.h" #include "qemu-common.h" #include "mips-defs.h" -#include "cpu-defs.h" +#include "exec/cpu-defs.h" #include "softfloat.h" struct CPUMIPSState; @@ -560,7 +560,7 @@ static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env) return r; } -#include "cpu-all.h" +#include "exec/cpu-all.h" /* Memory access type : * may be needed for precise access rights control and precise exceptions. @@ -738,7 +738,7 @@ static inline bool cpu_has_work(CPUState *cpu) return has_work; } -#include "exec-all.h" +#include "exec/exec-all.h" static inline void cpu_pc_from_tb(CPUMIPSState *env, TranslationBlock *tb) { diff --git a/target-mips/helper.h b/target-mips/helper.h index acf9ebd759..9ea60ec1bb 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -1,4 +1,4 @@ -#include "def-helper.h" +#include "exec/def-helper.h" DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int) DEF_HELPER_2(raise_exception, noreturn, env, i32) @@ -707,4 +707,4 @@ DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env) -#include "def-helper.h" +#include "exec/def-helper.h" diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 2972ae3f0a..157f59e6bf 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -23,7 +23,7 @@ #include "helper.h" #if !defined(CONFIG_USER_ONLY) -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #endif /* !defined(CONFIG_USER_ONLY) */ #ifndef CONFIG_USER_ONLY @@ -2116,16 +2116,16 @@ static void QEMU_NORETURN do_unaligned_access(CPUMIPSState *env, #define ALIGNED_ONLY #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" static void do_unaligned_access(CPUMIPSState *env, target_ulong addr, int is_write, int is_user, uintptr_t retaddr) diff --git a/target-mips/translate.c b/target-mips/translate.c index 44e7617395..e81ff38476 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1017,7 +1017,7 @@ static TCGv_i64 fpu_f64[32]; static uint32_t gen_opc_hflags[OPC_BUF_SIZE]; static target_ulong gen_opc_btarget[OPC_BUF_SIZE]; -#include "gen-icount.h" +#include "exec/gen-icount.h" #define gen_helper_0e0i(name, arg) do { \ TCGv_i32 helper_tmp = tcg_const_i32(arg); \ diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h index c7b1750153..8dc56c2873 100644 --- a/target-openrisc/cpu.h +++ b/target-openrisc/cpu.h @@ -30,7 +30,7 @@ struct OpenRISCCPU; #include "config.h" #include "qemu-common.h" -#include "cpu-defs.h" +#include "exec/cpu-defs.h" #include "softfloat.h" #include "qemu/cpu.h" #include "qapi/error.h" @@ -398,7 +398,7 @@ static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp) } #endif -#include "cpu-all.h" +#include "exec/cpu-all.h" static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env, target_ulong *pc, @@ -427,7 +427,7 @@ static inline bool cpu_has_work(CPUState *cpu) CPU_INTERRUPT_TIMER); } -#include "exec-all.h" +#include "exec/exec-all.h" static inline target_ulong cpu_get_pc(CPUOpenRISCState *env) { diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h index 404d46447f..2af97901ce 100644 --- a/target-openrisc/helper.h +++ b/target-openrisc/helper.h @@ -17,7 +17,7 @@ * License along with this library; if not, see . */ -#include "def-helper.h" +#include "exec/def-helper.h" /* exception */ DEF_HELPER_FLAGS_2(exception, 0, void, env, i32) @@ -67,4 +67,4 @@ DEF_HELPER_FLAGS_1(rfe, 0, void, env) DEF_HELPER_FLAGS_4(mtspr, 0, void, env, tl, tl, tl) DEF_HELPER_FLAGS_4(mfspr, 0, tl, env, tl, tl, tl) -#include "def-helper.h" +#include "exec/def-helper.h" diff --git a/target-openrisc/interrupt.c b/target-openrisc/interrupt.c index 642da7de49..226ce43513 100644 --- a/target-openrisc/interrupt.c +++ b/target-openrisc/interrupt.c @@ -19,7 +19,7 @@ #include "cpu.h" #include "qemu-common.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #include "host-utils.h" #ifndef CONFIG_USER_ONLY #include "hw/loader.h" diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c index f2a6523cfb..4eee44434f 100644 --- a/target-openrisc/mmu.c +++ b/target-openrisc/mmu.c @@ -20,7 +20,7 @@ #include "cpu.h" #include "qemu-common.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #include "host-utils.h" #ifndef CONFIG_USER_ONLY #include "hw/loader.h" diff --git a/target-openrisc/mmu_helper.c b/target-openrisc/mmu_helper.c index d2edebcb49..e46b092984 100644 --- a/target-openrisc/mmu_helper.c +++ b/target-openrisc/mmu_helper.c @@ -21,20 +21,20 @@ #include "cpu.h" #ifndef CONFIG_USER_ONLY -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #define MMUSUFFIX _mmu #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" void tlb_fill(CPUOpenRISCState *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index 2cb9d69826..5883347fa7 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -19,7 +19,7 @@ */ #include "cpu.h" -#include "exec-all.h" +#include "exec/exec-all.h" #include "disas/disas.h" #include "tcg-op.h" #include "qemu-common.h" @@ -61,7 +61,7 @@ static TCGv_i32 fpcsr; static TCGv machi, maclo; static TCGv fpmaddhi, fpmaddlo; static TCGv_i32 env_flags; -#include "gen-icount.h" +#include "exec/gen-icount.h" void openrisc_translate_init(void) { diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 742d4f8ae3..610bcd544b 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -73,7 +73,7 @@ #define CPUArchState struct CPUPPCState -#include "cpu-defs.h" +#include "exec/cpu-defs.h" #include "softfloat.h" @@ -1251,7 +1251,7 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp) } #endif -#include "cpu-all.h" +#include "exec/cpu-all.h" /*****************************************************************************/ /* CRF definitions */ @@ -2224,7 +2224,7 @@ static inline bool cpu_has_work(CPUState *cpu) return msr_ee && (env->interrupt_request & CPU_INTERRUPT_HARD); } -#include "exec-all.h" +#include "exec/exec-all.h" static inline void cpu_pc_from_tb(CPUPPCState *env, TranslationBlock *tb) { diff --git a/target-ppc/helper.h b/target-ppc/helper.h index e588370e29..d2e9a55f28 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -1,4 +1,4 @@ -#include "def-helper.h" +#include "exec/def-helper.h" DEF_HELPER_3(raise_exception_err, void, env, i32, i32) DEF_HELPER_2(raise_exception, void, env, i32) @@ -414,4 +414,4 @@ DEF_HELPER_3(store_601_batl, void, env, i32, tl) DEF_HELPER_3(store_601_batu, void, env, i32, tl) #endif -#include "def-helper.h" +#include "exec/def-helper.h" diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h index baad6eb75b..83f98729a2 100644 --- a/target-ppc/kvm_ppc.h +++ b/target-ppc/kvm_ppc.h @@ -9,7 +9,7 @@ #ifndef __KVM_PPC_H__ #define __KVM_PPC_H__ -#include "memory.h" +#include "exec/memory.h" void kvmppc_init(void); diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c index 04c01445f9..2d7a349c32 100644 --- a/target-ppc/mem_helper.c +++ b/target-ppc/mem_helper.c @@ -23,7 +23,7 @@ #include "helper_regs.h" #if !defined(CONFIG_USER_ONLY) -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #endif /* !defined(CONFIG_USER_ONLY) */ //#define DEBUG_OP @@ -257,16 +257,16 @@ STVE(stvewx, cpu_stl_data, bswap32, u32) #define MMUSUFFIX _mmu #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" /* try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 8a53105f89..a74d76b5a6 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -71,7 +71,7 @@ static TCGv cpu_reserve; static TCGv cpu_fpscr; static TCGv_i32 cpu_access_type; -#include "gen-icount.h" +#include "exec/gen-icount.h" void ppc_translate_init(void) { diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 984ca9fc63..cca63abf5d 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -24,7 +24,7 @@ */ #include "disas/bfd.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #include #include "kvm_ppc.h" #include "arch_init.h" diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 0f9a1f7340..acb8c73174 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -28,13 +28,13 @@ #define CPUArchState struct CPUS390XState -#include "cpu-defs.h" +#include "exec/cpu-defs.h" #define TARGET_PAGE_BITS 12 #define TARGET_PHYS_ADDR_SPACE_BITS 64 #define TARGET_VIRT_ADDR_SPACE_BITS 64 -#include "cpu-all.h" +#include "exec/cpu-all.h" #include "softfloat.h" @@ -350,7 +350,7 @@ static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls) #define cpu_gen_code cpu_s390x_gen_code #define cpu_signal_handler cpu_s390x_signal_handler -#include "exec-all.h" +#include "exec/exec-all.h" #ifdef CONFIG_USER_ONLY diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c index ee9420d446..173f820428 100644 --- a/target-s390x/fpu_helper.c +++ b/target-s390x/fpu_helper.c @@ -22,7 +22,7 @@ #include "helper.h" #if !defined(CONFIG_USER_ONLY) -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #endif /* #define DEBUG_HELPER */ diff --git a/target-s390x/helper.c b/target-s390x/helper.c index b7b812a7e6..6e9b209713 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -19,7 +19,7 @@ */ #include "cpu.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #include "qemu-timer.h" #ifndef CONFIG_USER_ONLY #include "sysemu.h" diff --git a/target-s390x/helper.h b/target-s390x/helper.h index ac44eabd53..c4926c52ad 100644 --- a/target-s390x/helper.h +++ b/target-s390x/helper.h @@ -1,4 +1,4 @@ -#include "def-helper.h" +#include "exec/def-helper.h" DEF_HELPER_2(exception, void, env, i32) DEF_HELPER_4(nc, i32, env, i32, i64, i64) @@ -149,4 +149,4 @@ DEF_HELPER_3(cksm, void, env, i32, i32) DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64) -#include "def-helper.h" +#include "exec/def-helper.h" diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c index 91b25e309d..bed21e6e1c 100644 --- a/target-s390x/mem_helper.c +++ b/target-s390x/mem_helper.c @@ -24,21 +24,21 @@ /*****************************************************************************/ /* Softmmu support */ #if !defined(CONFIG_USER_ONLY) -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #define MMUSUFFIX _mmu #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" /* try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index 38d8f2a627..a3336e16b0 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -19,7 +19,7 @@ */ #include "cpu.h" -#include "memory.h" +#include "exec/memory.h" #include "host-utils.h" #include "helper.h" #include @@ -30,7 +30,7 @@ #endif #if !defined(CONFIG_USER_ONLY) -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #include "sysemu.h" #endif diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 6e144a67a2..28e61c54b8 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -37,7 +37,7 @@ /* global register indexes */ static TCGv_ptr cpu_env; -#include "gen-icount.h" +#include "exec/gen-icount.h" #include "helper.h" #define GEN_HELPER 1 #include "helper.h" diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index 9a0e72b1fb..7c50c798b8 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -39,7 +39,7 @@ #define CPUArchState struct CPUSH4State -#include "cpu-defs.h" +#include "exec/cpu-defs.h" #include "softfloat.h" @@ -264,7 +264,7 @@ static inline void cpu_clone_regs(CPUSH4State *env, target_ulong newsp) } #endif -#include "cpu-all.h" +#include "exec/cpu-all.h" /* Memory access type */ enum { @@ -378,7 +378,7 @@ static inline bool cpu_has_work(CPUState *cpu) return env->interrupt_request & CPU_INTERRUPT_HARD; } -#include "exec-all.h" +#include "exec/exec-all.h" static inline void cpu_pc_from_tb(CPUSH4State *env, TranslationBlock *tb) { diff --git a/target-sh4/helper.h b/target-sh4/helper.h index 304b77ba3f..7162448497 100644 --- a/target-sh4/helper.h +++ b/target-sh4/helper.h @@ -1,4 +1,4 @@ -#include "def-helper.h" +#include "exec/def-helper.h" DEF_HELPER_1(ldtlb, void, env) DEF_HELPER_1(raise_illegal_instruction, noreturn, env) @@ -47,4 +47,4 @@ DEF_HELPER_2(ftrc_DT, i32, env, f64) DEF_HELPER_3(fipr, void, env, i32, i32) DEF_HELPER_2(ftrv, void, env, i32) -#include "def-helper.h" +#include "exec/def-helper.h" diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c index e8e87f5152..09e3d23aff 100644 --- a/target-sh4/op_helper.c +++ b/target-sh4/op_helper.c @@ -22,21 +22,21 @@ #include "helper.h" #ifndef CONFIG_USER_ONLY -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #define MMUSUFFIX _mmu #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" void tlb_fill(CPUSH4State *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 41d53e5c51..260aaab559 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -69,7 +69,7 @@ static TCGv cpu_flags, cpu_delayed_pc; static uint32_t gen_opc_hflags[OPC_BUF_SIZE]; -#include "gen-icount.h" +#include "exec/gen-icount.h" static void sh4_translate_init(void) { diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 013ecbd063..0ed511a399 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -25,7 +25,7 @@ #define CPUArchState struct CPUSPARCState -#include "cpu-defs.h" +#include "exec/cpu-defs.h" #include "softfloat.h" @@ -701,7 +701,7 @@ static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp) } #endif -#include "cpu-all.h" +#include "exec/cpu-all.h" #ifdef TARGET_SPARC64 /* sun4u.c */ @@ -767,7 +767,7 @@ static inline bool cpu_has_work(CPUState *cpu) cpu_interrupts_enabled(env1); } -#include "exec-all.h" +#include "exec/exec-all.h" static inline void cpu_pc_from_tb(CPUSPARCState *env, TranslationBlock *tb) { diff --git a/target-sparc/helper.h b/target-sparc/helper.h index 098c482216..cfcdab1ea4 100644 --- a/target-sparc/helper.h +++ b/target-sparc/helper.h @@ -1,4 +1,4 @@ -#include "def-helper.h" +#include "exec/def-helper.h" #ifndef TARGET_SPARC64 DEF_HELPER_1(rett, void, env) @@ -173,4 +173,4 @@ VIS_CMPHELPER(cmpne); DEF_HELPER_1(compute_psr, void, env); DEF_HELPER_1(compute_C_icc, i32, env); -#include "def-helper.h" +#include "exec/def-helper.h" diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c index 8d815e5038..cf1bddf2db 100644 --- a/target-sparc/ldst_helper.c +++ b/target-sparc/ldst_helper.c @@ -68,21 +68,21 @@ static void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write, int is_user, uintptr_t retaddr); -#include "softmmu_exec.h" +#include "exec/softmmu_exec.h" #define MMUSUFFIX _mmu #define ALIGNED_ONLY #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #endif #if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) diff --git a/target-sparc/mmu_helper.c b/target-sparc/mmu_helper.c index 2c89b20b68..a9649ae064 100644 --- a/target-sparc/mmu_helper.c +++ b/target-sparc/mmu_helper.c @@ -19,7 +19,7 @@ #include "cpu.h" #include "trace.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" /* Sparc MMU emulation */ diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 88802b8486..ca75e1aa48 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -64,7 +64,7 @@ static TCGv_i64 cpu_fpr[TARGET_DPREGS]; static target_ulong gen_opc_npc[OPC_BUF_SIZE]; static target_ulong gen_opc_jump_pc[2]; -#include "gen-icount.h" +#include "exec/gen-icount.h" typedef struct DisasContext { target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */ diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h index 676c5d9d99..cd8f730756 100644 --- a/target-unicore32/cpu.h +++ b/target-unicore32/cpu.h @@ -23,7 +23,7 @@ #include "config.h" #include "qemu-common.h" -#include "cpu-defs.h" +#include "exec/cpu-defs.h" #include "softfloat.h" #define NB_MMU_MODES 2 @@ -157,9 +157,9 @@ static inline void cpu_set_tls(CPUUniCore32State *env, target_ulong newtls) env->regs[16] = newtls; } -#include "cpu-all.h" +#include "exec/cpu-all.h" #include "cpu-qom.h" -#include "exec-all.h" +#include "exec/exec-all.h" static inline void cpu_pc_from_tb(CPUUniCore32State *env, TranslationBlock *tb) { diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c index 4b6856137d..2adbd1675d 100644 --- a/target-unicore32/helper.c +++ b/target-unicore32/helper.c @@ -10,7 +10,7 @@ */ #include "cpu.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #include "helper.h" #include "host-utils.h" #include "ui/console.h" diff --git a/target-unicore32/helper.h b/target-unicore32/helper.h index a4b81494aa..e85ce6c201 100644 --- a/target-unicore32/helper.h +++ b/target-unicore32/helper.h @@ -6,7 +6,7 @@ * published by the Free Software Foundation, or (at your option) any * later version. See the COPYING file in the top-level directory. */ -#include "def-helper.h" +#include "exec/def-helper.h" #ifndef CONFIG_USER_ONLY DEF_HELPER_4(cp0_set, void, env, i32, i32, i32) @@ -65,4 +65,4 @@ DEF_HELPER_2(ucf64_si2df, f64, f32, env) DEF_HELPER_2(ucf64_sf2si, f32, f32, env) DEF_HELPER_2(ucf64_df2si, f32, f64, env) -#include "def-helper.h" +#include "exec/def-helper.h" diff --git a/target-unicore32/op_helper.c b/target-unicore32/op_helper.c index b8172ba682..6443ffec1c 100644 --- a/target-unicore32/op_helper.c +++ b/target-unicore32/op_helper.c @@ -242,16 +242,16 @@ uint32_t HELPER(ror_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i) #define MMUSUFFIX _mmu #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" void tlb_fill(CPUUniCore32State *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index 8c49f4d701..218e95eaca 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -55,7 +55,7 @@ static TCGv_i32 cpu_R[32]; static TCGv cpu_F0s, cpu_F1s; static TCGv_i64 cpu_F0d, cpu_F1d; -#include "gen-icount.h" +#include "exec/gen-icount.h" static const char *regnames[] = { "r00", "r01", "r02", "r03", "r04", "r05", "r06", "r07", diff --git a/target-xtensa/core-dc232b.c b/target-xtensa/core-dc232b.c index 804fdef56a..d1a594cda2 100644 --- a/target-xtensa/core-dc232b.c +++ b/target-xtensa/core-dc232b.c @@ -26,8 +26,8 @@ */ #include "cpu.h" -#include "exec-all.h" -#include "gdbstub.h" +#include "exec/exec-all.h" +#include "exec/gdbstub.h" #include "host-utils.h" #include "core-dc232b/core-isa.h" diff --git a/target-xtensa/core-dc233c.c b/target-xtensa/core-dc233c.c index d643f41d37..ead6b3b128 100644 --- a/target-xtensa/core-dc233c.c +++ b/target-xtensa/core-dc233c.c @@ -26,8 +26,8 @@ */ #include "cpu.h" -#include "exec-all.h" -#include "gdbstub.h" +#include "exec/exec-all.h" +#include "exec/gdbstub.h" #include "qemu-common.h" #include "host-utils.h" diff --git a/target-xtensa/core-fsf.c b/target-xtensa/core-fsf.c index e36b0de9d5..a387aeeca5 100644 --- a/target-xtensa/core-fsf.c +++ b/target-xtensa/core-fsf.c @@ -26,8 +26,8 @@ */ #include "cpu.h" -#include "exec-all.h" -#include "gdbstub.h" +#include "exec/exec-all.h" +#include "exec/gdbstub.h" #include "host-utils.h" #include "core-fsf/core-isa.h" diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h index 08fd5bc395..5acf78c692 100644 --- a/target-xtensa/cpu.h +++ b/target-xtensa/cpu.h @@ -35,7 +35,7 @@ #include "config.h" #include "qemu-common.h" -#include "cpu-defs.h" +#include "exec/cpu-defs.h" #include "fpu/softfloat.h" #define TARGET_HAS_ICE 1 @@ -512,8 +512,8 @@ static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc, } } -#include "cpu-all.h" -#include "exec-all.h" +#include "exec/cpu-all.h" +#include "exec/exec-all.h" static inline int cpu_has_work(CPUState *cpu) { diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c index bf05575eb5..3d7a399008 100644 --- a/target-xtensa/helper.c +++ b/target-xtensa/helper.c @@ -26,8 +26,8 @@ */ #include "cpu.h" -#include "exec-all.h" -#include "gdbstub.h" +#include "exec/exec-all.h" +#include "exec/gdbstub.h" #include "host-utils.h" #if !defined(CONFIG_USER_ONLY) #include "hw/loader.h" diff --git a/target-xtensa/helper.h b/target-xtensa/helper.h index 5b4cd2700f..38d7157f34 100644 --- a/target-xtensa/helper.h +++ b/target-xtensa/helper.h @@ -1,4 +1,4 @@ -#include "def-helper.h" +#include "exec/def-helper.h" DEF_HELPER_2(exception, noreturn, env, i32) DEF_HELPER_3(exception_cause, noreturn, env, i32, i32) @@ -58,4 +58,4 @@ DEF_HELPER_4(ult_s, void, env, i32, f32, f32) DEF_HELPER_4(ole_s, void, env, i32, f32, f32) DEF_HELPER_4(ule_s, void, env, i32, f32, f32) -#include "def-helper.h" +#include "exec/def-helper.h" diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c index 84f0449f79..a93abcb1dd 100644 --- a/target-xtensa/op_helper.c +++ b/target-xtensa/op_helper.c @@ -36,16 +36,16 @@ static void do_unaligned_access(CPUXtensaState *env, #define MMUSUFFIX _mmu #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" static void do_unaligned_access(CPUXtensaState *env, target_ulong addr, int is_write, int is_user, uintptr_t retaddr) diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 4e81cbd9ec..3c2d1853d6 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -31,7 +31,7 @@ #include #include "cpu.h" -#include "exec-all.h" +#include "exec/exec-all.h" #include "disas/disas.h" #include "tcg-op.h" #include "qemu-log.h" @@ -76,7 +76,7 @@ static TCGv_i32 cpu_FR[16]; static TCGv_i32 cpu_SR[256]; static TCGv_i32 cpu_UR[256]; -#include "gen-icount.h" +#include "exec/gen-icount.h" typedef struct XtensaReg { const char *name; diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index 47612fe260..c3ac85e054 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -992,7 +992,7 @@ static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index) #ifdef CONFIG_SOFTMMU -#include "../../softmmu_defs.h" +#include "exec/softmmu_defs.h" /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c index de500ae181..5b27cf6f12 100644 --- a/tcg/hppa/tcg-target.c +++ b/tcg/hppa/tcg-target.c @@ -906,7 +906,7 @@ static void tcg_out_movcond(TCGContext *s, int cond, TCGArg ret, } #if defined(CONFIG_SOFTMMU) -#include "../../softmmu_defs.h" +#include "exec/softmmu_defs.h" /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 6f3ad3ceab..ae8274652a 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -982,7 +982,7 @@ static void tcg_out_jmp(TCGContext *s, tcg_target_long dest) #if defined(CONFIG_SOFTMMU) -#include "../../softmmu_defs.h" +#include "exec/softmmu_defs.h" /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 06570bea38..2373d9ef79 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -1491,7 +1491,7 @@ static inline void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGArg ret, #if defined(CONFIG_SOFTMMU) -#include "../../softmmu_defs.h" +#include "exec/softmmu_defs.h" /* Load and compare a TLB entry, and return the result in (p6, p7). R2 is loaded with the address of the addend TLB entry. diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index ae2b274d85..bd8c858989 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -920,7 +920,7 @@ static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret, #if defined(CONFIG_SOFTMMU) -#include "../../softmmu_defs.h" +#include "exec/softmmu_defs.h" /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index d72d396270..29ca934e66 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -549,7 +549,7 @@ static void add_qemu_ldst_label (TCGContext *s, label->label_ptr[0] = label_ptr; } -#include "../../softmmu_defs.h" +#include "exec/softmmu_defs.h" /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c index 5403fc1f91..833fe0c10b 100644 --- a/tcg/ppc64/tcg-target.c +++ b/tcg/ppc64/tcg-target.c @@ -546,7 +546,7 @@ static void tcg_out_ldsta (TCGContext *s, int ret, int addr, #if defined (CONFIG_SOFTMMU) -#include "../../softmmu_defs.h" +#include "exec/softmmu_defs.h" /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c index fd9286f52d..e12a15221a 100644 --- a/tcg/s390/tcg-target.c +++ b/tcg/s390/tcg-target.c @@ -299,7 +299,7 @@ static const uint8_t tcg_cond_to_ltr_cond[] = { #ifdef CONFIG_SOFTMMU -#include "../../softmmu_defs.h" +#include "exec/softmmu_defs.h" /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index f146647874..03db514a1d 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -831,7 +831,7 @@ static void tcg_target_qemu_prologue(TCGContext *s) #if defined(CONFIG_SOFTMMU) -#include "../../softmmu_defs.h" +#include "exec/softmmu_defs.h" /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ diff --git a/tci.c b/tci.c index 54cf1d9524..2b2c11f259 100644 --- a/tci.c +++ b/tci.c @@ -25,7 +25,7 @@ #endif #include "qemu-common.h" -#include "exec-all.h" /* MAX_OPC_PARAM_IARGS */ +#include "exec/exec-all.h" /* MAX_OPC_PARAM_IARGS */ #include "tcg-op.h" /* Marker for missing code. */ diff --git a/thunk.c b/thunk.c index 8ebbbb46b6..3cca047509 100644 --- a/thunk.c +++ b/thunk.c @@ -21,7 +21,7 @@ #include #include "qemu.h" -#include "thunk.h" +#include "exec/user/thunk.h" //#define DEBUG diff --git a/translate-all.c b/translate-all.c index bbe06db6eb..e0cdad38c7 100644 --- a/translate-all.c +++ b/translate-all.c @@ -36,8 +36,8 @@ #include "disas/disas.h" #include "tcg.h" #include "qemu-timer.h" -#include "memory.h" -#include "exec-memory.h" +#include "exec/memory.h" +#include "exec/address-spaces.h" #if defined(CONFIG_USER_ONLY) #include "qemu.h" #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) @@ -57,7 +57,7 @@ #endif #endif -#include "cputlb.h" +#include "exec/cputlb.h" #include "translate-all.h" //#define DEBUG_TB_INVALIDATE diff --git a/vl.c b/vl.c index 975767a44b..015f0a4757 100644 --- a/vl.c +++ b/vl.c @@ -132,7 +132,7 @@ int main(int argc, char **argv) #include "monitor.h" #include "ui/console.h" #include "sysemu.h" -#include "gdbstub.h" +#include "exec/gdbstub.h" #include "qemu-timer.h" #include "qemu-char.h" #include "cache-utils.h" diff --git a/xen-all.c b/xen-all.c index e3a51ccc81..95d383f41f 100644 --- a/xen-all.c +++ b/xen-all.c @@ -19,7 +19,7 @@ #include "range.h" #include "xen-mapcache.h" #include "trace.h" -#include "exec-memory.h" +#include "exec/address-spaces.h" #include #include diff --git a/xen-stub.c b/xen-stub.c index 921439263a..1ee841137e 100644 --- a/xen-stub.c +++ b/xen-stub.c @@ -10,7 +10,7 @@ #include "qemu-common.h" #include "hw/xen.h" -#include "memory.h" +#include "exec/memory.h" #include "qmp-commands.h" void xenstore_store_pv_console_info(int i, CharDriverState *chr) From 83c9089e73b81c69dc1ecdf859fa84d2c500fb5f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Dec 2012 18:19:49 +0100 Subject: [PATCH 2061/2270] monitor: move include files to include/monitor/ Signed-off-by: Paolo Bonzini --- arch_init.c | 2 +- audio/audio.c | 2 +- audio/wavcapture.c | 2 +- balloon.c | 2 +- balloon.h | 2 +- block.c | 2 +- blockdev-nbd.c | 2 +- blockdev.c | 2 +- blockjob.c | 2 +- cpus.c | 2 +- disas.c | 2 +- dump.c | 2 +- gdbstub.c | 2 +- hmp.c | 2 +- hw/acpi.c | 2 +- hw/ccid-card-emulated.c | 2 +- hw/ccid-card-passthru.c | 2 +- hw/device-hotplug.c | 2 +- hw/i8259.c | 2 +- hw/ide/ahci.c | 2 +- hw/isa-bus.c | 2 +- hw/kvm/pci-assign.c | 2 +- hw/lm32_pic.c | 2 +- hw/loader.c | 2 +- hw/pc.c | 2 +- hw/pci/pci-hotplug.c | 2 +- hw/pci/pci-stub.c | 2 +- hw/pci/pci.c | 2 +- hw/pci/pcie_aer.c | 2 +- hw/qdev-monitor.c | 2 +- hw/qdev-monitor.h | 2 +- hw/qxl.c | 2 +- hw/s390-virtio-bus.c | 2 +- hw/s390-virtio.c | 2 +- hw/s390x/event-facility.c | 2 +- hw/slavio_intctl.c | 2 +- hw/spapr_vio.c | 2 +- hw/sun4c_intctl.c | 2 +- hw/sysbus.c | 2 +- hw/usb/bus.c | 2 +- hw/usb/dev-smartcard-reader.c | 2 +- hw/usb/dev-storage.c | 2 +- hw/usb/hcd-ehci.h | 2 +- hw/usb/host-bsd.c | 2 +- hw/usb/host-linux.c | 2 +- hw/usb/host-stub.c | 2 +- hw/usb/redirect.c | 2 +- hw/virtio-serial-bus.c | 2 +- hw/watchdog.c | 2 +- include/block/block_int.h | 2 +- monitor.h => include/monitor/monitor.h | 2 +- readline.h => include/monitor/readline.h | 0 include/ui/console.h | 2 +- include/ui/qemu-spice.h | 4 ++-- migration-fd.c | 2 +- migration.c | 2 +- monitor.c | 4 ++-- net/hub.c | 2 +- net/net.c | 2 +- net/slirp.c | 2 +- net/socket.c | 2 +- net/tap.c | 2 +- osdep.c | 2 +- qemu-char.c | 2 +- qemu-error.c | 2 +- qemu-sockets.c | 2 +- qemu-timer.c | 2 +- qemu-tool.c | 2 +- qemu-user.c | 2 +- qerror.c | 2 +- readline.c | 4 ++-- savevm.c | 2 +- slirp/misc.c | 4 ++-- stubs/fdset-add-fd.c | 2 +- stubs/fdset-find-fd.c | 2 +- stubs/fdset-get-fd.c | 2 +- stubs/fdset-remove-fd.c | 2 +- stubs/get-fd.c | 2 +- target-i386/helper.c | 2 +- ui/input.c | 2 +- ui/spice-core.c | 2 +- ui/spice-display.c | 2 +- ui/vnc.h | 2 +- vl.c | 2 +- 84 files changed, 87 insertions(+), 87 deletions(-) rename monitor.h => include/monitor/monitor.h (99%) rename readline.h => include/monitor/readline.h (100%) diff --git a/arch_init.c b/arch_init.c index e15cedad04..93d1e52f4a 100644 --- a/arch_init.c +++ b/arch_init.c @@ -29,7 +29,7 @@ #include #endif #include "config.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "sysemu.h" #include "bitops.h" #include "bitmap.h" diff --git a/audio/audio.c b/audio/audio.c index 1c7738930b..a0cc727020 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -23,7 +23,7 @@ */ #include "hw/hw.h" #include "audio.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "qemu-timer.h" #include "sysemu.h" diff --git a/audio/wavcapture.c b/audio/wavcapture.c index 4f785f5f49..9d94623225 100644 --- a/audio/wavcapture.c +++ b/audio/wavcapture.c @@ -1,5 +1,5 @@ #include "hw/hw.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "audio.h" typedef struct { diff --git a/balloon.c b/balloon.c index c24458b5f9..d1de4352b4 100644 --- a/balloon.c +++ b/balloon.c @@ -24,7 +24,7 @@ * THE SOFTWARE. */ -#include "monitor.h" +#include "monitor/monitor.h" #include "exec/cpu-common.h" #include "kvm.h" #include "balloon.h" diff --git a/balloon.h b/balloon.h index b803a00741..bd9d39505d 100644 --- a/balloon.h +++ b/balloon.h @@ -14,7 +14,7 @@ #ifndef _QEMU_BALLOON_H #define _QEMU_BALLOON_H -#include "monitor.h" +#include "monitor/monitor.h" #include "qapi-types.h" typedef void (QEMUBalloonEvent)(void *opaque, ram_addr_t target); diff --git a/block.c b/block.c index 5eab9e2519..0e7f18c6d3 100644 --- a/block.c +++ b/block.c @@ -24,7 +24,7 @@ #include "config-host.h" #include "qemu-common.h" #include "trace.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "block/block_int.h" #include "block/blockjob.h" #include "module.h" diff --git a/blockdev-nbd.c b/blockdev-nbd.c index 81aa1d34ef..596b47499d 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -11,7 +11,7 @@ #include "blockdev.h" #include "hw/block-common.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "qapi/qmp/qerror.h" #include "sysemu.h" #include "qmp-commands.h" diff --git a/blockdev.c b/blockdev.c index ff6b333f69..a2308fa718 100644 --- a/blockdev.c +++ b/blockdev.c @@ -10,7 +10,7 @@ #include "blockdev.h" #include "hw/block-common.h" #include "block/blockjob.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "qapi/qmp/qerror.h" #include "qemu-option.h" #include "qemu-config.h" diff --git a/blockjob.c b/blockjob.c index 004480d714..4bc60c7378 100644 --- a/blockjob.c +++ b/blockjob.c @@ -26,7 +26,7 @@ #include "config-host.h" #include "qemu-common.h" #include "trace.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "block/block.h" #include "block/blockjob.h" #include "block/block_int.h" diff --git a/cpus.c b/cpus.c index 8926873ad1..3a66401e0d 100644 --- a/cpus.c +++ b/cpus.c @@ -25,7 +25,7 @@ /* Needed early for CONFIG_BSD etc. */ #include "config-host.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "sysemu.h" #include "exec/gdbstub.h" #include "dma.h" diff --git a/disas.c b/disas.c index 8157b96fc1..a46faeed80 100644 --- a/disas.c +++ b/disas.c @@ -374,7 +374,7 @@ const char *lookup_symbol(target_ulong orig_addr) #if !defined(CONFIG_USER_ONLY) -#include "monitor.h" +#include "monitor/monitor.h" static int monitor_disas_is_physical; diff --git a/dump.c b/dump.c index e70e0f3b21..871ee1727a 100644 --- a/dump.c +++ b/dump.c @@ -16,7 +16,7 @@ #include "cpu.h" #include "exec/cpu-all.h" #include "exec/hwaddr.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "kvm.h" #include "dump.h" #include "sysemu.h" diff --git a/gdbstub.c b/gdbstub.c index 70ad79a748..9395c829a2 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -29,7 +29,7 @@ #include "qemu.h" #else -#include "monitor.h" +#include "monitor/monitor.h" #include "qemu-char.h" #include "sysemu.h" #include "exec/gdbstub.h" diff --git a/hmp.c b/hmp.c index f235134bb6..a76a8f06ea 100644 --- a/hmp.c +++ b/hmp.c @@ -20,7 +20,7 @@ #include "qemu-timer.h" #include "qmp-commands.h" #include "qemu_socket.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "ui/console.h" static void hmp_handle_error(Monitor *mon, Error **errp) diff --git a/hw/acpi.c b/hw/acpi.c index ae29a59077..fe9b76a9b0 100644 --- a/hw/acpi.c +++ b/hw/acpi.c @@ -22,7 +22,7 @@ #include "hw.h" #include "pc.h" #include "acpi.h" -#include "monitor.h" +#include "monitor/monitor.h" struct acpi_table_header { uint16_t _length; /* our length, not actual part of the hdr */ diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c index f4a6da4283..845a764446 100644 --- a/hw/ccid-card-emulated.c +++ b/hw/ccid-card-emulated.c @@ -33,7 +33,7 @@ #include "qemu-thread.h" #include "qemu-char.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "hw/ccid.h" #define DPRINTF(card, lvl, fmt, ...) \ diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c index bd6c77777d..f5b4794e90 100644 --- a/hw/ccid-card-passthru.c +++ b/hw/ccid-card-passthru.c @@ -10,7 +10,7 @@ #include "qemu-char.h" #include "qemu_socket.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "hw/ccid.h" #include "libcacard/vscard_common.h" diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c index 336ffc2274..809a598e3a 100644 --- a/hw/device-hotplug.c +++ b/hw/device-hotplug.c @@ -27,7 +27,7 @@ #include "blockdev.h" #include "qemu-config.h" #include "sysemu.h" -#include "monitor.h" +#include "monitor/monitor.h" DriveInfo *add_init_drive(const char *optstr) { diff --git a/hw/i8259.c b/hw/i8259.c index af0ba4d7c6..5e935e7f99 100644 --- a/hw/i8259.c +++ b/hw/i8259.c @@ -24,7 +24,7 @@ #include "hw.h" #include "pc.h" #include "isa.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "qemu-timer.h" #include "i8259_internal.h" diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index f32a84761d..d38c6e4574 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -27,7 +27,7 @@ #include #include -#include "monitor.h" +#include "monitor/monitor.h" #include "dma.h" #include "exec/cpu-common.h" #include "internal.h" diff --git a/hw/isa-bus.c b/hw/isa-bus.c index 8f40974166..a2be67df56 100644 --- a/hw/isa-bus.c +++ b/hw/isa-bus.c @@ -17,7 +17,7 @@ * License along with this library; if not, see . */ #include "hw.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "sysbus.h" #include "sysemu.h" #include "isa.h" diff --git a/hw/kvm/pci-assign.c b/hw/kvm/pci-assign.c index 2629775589..ff0dc0dfd4 100644 --- a/hw/kvm/pci-assign.c +++ b/hw/kvm/pci-assign.c @@ -31,7 +31,7 @@ #include "qemu-error.h" #include "ui/console.h" #include "hw/loader.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "range.h" #include "sysemu.h" #include "hw/pci/pci.h" diff --git a/hw/lm32_pic.c b/hw/lm32_pic.c index 32f65db7f1..42d5602cf0 100644 --- a/hw/lm32_pic.c +++ b/hw/lm32_pic.c @@ -21,7 +21,7 @@ #include "hw.h" #include "pc.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "sysbus.h" #include "trace.h" #include "lm32_pic.h" diff --git a/hw/loader.c b/hw/loader.c index 03f0318d91..f5ef575b52 100644 --- a/hw/loader.c +++ b/hw/loader.c @@ -44,7 +44,7 @@ #include "hw.h" #include "disas/disas.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "sysemu.h" #include "uboot_image.h" #include "loader.h" diff --git a/hw/pc.c b/hw/pc.c index 2452fd4214..7aaff0f2fd 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -28,7 +28,7 @@ #include "fdc.h" #include "ide.h" #include "pci/pci.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "fw_cfg.h" #include "hpet_emul.h" #include "smbios.h" diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug.c index 5ba7558ecd..e5e8a7ab58 100644 --- a/hw/pci/pci-hotplug.c +++ b/hw/pci/pci-hotplug.c @@ -27,7 +27,7 @@ #include "hw/pci/pci.h" #include "net/net.h" #include "hw/pc.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "hw/scsi.h" #include "hw/virtio-blk.h" #include "qemu-config.h" diff --git a/hw/pci/pci-stub.c b/hw/pci/pci-stub.c index b5c43a935b..5891dc959d 100644 --- a/hw/pci/pci-stub.c +++ b/hw/pci/pci-stub.c @@ -19,7 +19,7 @@ */ #include "sysemu.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "hw/pci/pci.h" #include "qmp-commands.h" diff --git a/hw/pci/pci.c b/hw/pci/pci.c index fa0f08eb0a..e062f66088 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -25,7 +25,7 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_bridge.h" #include "hw/pci/pci_bus.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "net/net.h" #include "sysemu.h" #include "hw/loader.h" diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c index b6f4f8510f..f7f3633f5b 100644 --- a/hw/pci/pcie_aer.c +++ b/hw/pci/pcie_aer.c @@ -20,7 +20,7 @@ #include "sysemu.h" #include "qapi/qmp/types.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "hw/pci/pci_bridge.h" #include "hw/pci/pcie.h" #include "hw/pci/msix.h" diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c index 5aaf74b98a..207282c4a4 100644 --- a/hw/qdev-monitor.c +++ b/hw/qdev-monitor.c @@ -18,7 +18,7 @@ */ #include "qdev.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "qmp-commands.h" #include "arch_init.h" #include "qemu-config.h" diff --git a/hw/qdev-monitor.h b/hw/qdev-monitor.h index 220ceba4c5..fae1b1ec84 100644 --- a/hw/qdev-monitor.h +++ b/hw/qdev-monitor.h @@ -2,7 +2,7 @@ #define QEMU_QDEV_MONITOR_H #include "qdev-core.h" -#include "monitor.h" +#include "monitor/monitor.h" /*** monitor commands ***/ diff --git a/hw/qxl.c b/hw/qxl.c index 96887c4aad..ad0214827e 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -23,7 +23,7 @@ #include "qemu-common.h" #include "qemu-timer.h" #include "qemu-queue.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "sysemu.h" #include "trace.h" diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index f7e1939288..769015c136 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -21,7 +21,7 @@ #include "block/block.h" #include "sysemu.h" #include "boards.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "loader.h" #include "elf.h" #include "hw/virtio.h" diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index 0a15625b73..7dfe87ade3 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -23,7 +23,7 @@ #include "sysemu.h" #include "net/net.h" #include "boards.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "loader.h" #include "elf.h" #include "hw/virtio.h" diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c index bc9cea9e1b..748118d0f0 100644 --- a/hw/s390x/event-facility.c +++ b/hw/s390x/event-facility.c @@ -15,7 +15,7 @@ * */ -#include "monitor.h" +#include "monitor/monitor.h" #include "sysemu.h" #include "sclp.h" diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c index 6aafa8b233..a44ce95c1f 100644 --- a/hw/slavio_intctl.c +++ b/hw/slavio_intctl.c @@ -23,7 +23,7 @@ */ #include "sun4m.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "sysbus.h" #include "trace.h" diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index 1f19fedd0e..fdf8db9158 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -22,7 +22,7 @@ #include "hw.h" #include "sysemu.h" #include "boards.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "loader.h" #include "elf.h" #include "hw/sysbus.h" diff --git a/hw/sun4c_intctl.c b/hw/sun4c_intctl.c index 702e9f5444..b78d54f232 100644 --- a/hw/sun4c_intctl.c +++ b/hw/sun4c_intctl.c @@ -24,7 +24,7 @@ #include "hw.h" #include "sun4m.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "sysbus.h" //#define DEBUG_IRQ_COUNT diff --git a/hw/sysbus.c b/hw/sysbus.c index 7ab250463c..49a41775f8 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -18,7 +18,7 @@ */ #include "sysbus.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "exec/address-spaces.h" static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent); diff --git a/hw/usb/bus.c b/hw/usb/bus.c index 8264c240ee..74728c94e5 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -2,7 +2,7 @@ #include "hw/usb.h" #include "hw/qdev.h" #include "sysemu.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "trace.h" static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent); diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index de955b709f..3862c9b6c9 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -38,7 +38,7 @@ #include "qemu-error.h" #include "hw/usb.h" #include "hw/usb/desc.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "hw/ccid.h" diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index de56fea610..0d7597b4d1 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -14,7 +14,7 @@ #include "hw/usb/desc.h" #include "hw/scsi.h" #include "ui/console.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "sysemu.h" #include "blockdev.h" diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index 837c63be85..740f7309fb 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -20,7 +20,7 @@ #include "hw/hw.h" #include "qemu-timer.h" #include "hw/usb.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "trace.h" #include "dma.h" #include "sysemu.h" diff --git a/hw/usb/host-bsd.c b/hw/usb/host-bsd.c index dae0009378..340c21aeb4 100644 --- a/hw/usb/host-bsd.c +++ b/hw/usb/host-bsd.c @@ -25,7 +25,7 @@ */ #include "qemu-common.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "hw/usb.h" /* usb.h declares these */ diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c index bdafb6bc87..5a56e99891 100644 --- a/hw/usb/host-linux.c +++ b/hw/usb/host-linux.c @@ -32,7 +32,7 @@ #include "qemu-common.h" #include "qemu-timer.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "sysemu.h" #include "trace.h" diff --git a/hw/usb/host-stub.c b/hw/usb/host-stub.c index e8da3221f6..58423a0f5c 100644 --- a/hw/usb/host-stub.c +++ b/hw/usb/host-stub.c @@ -33,7 +33,7 @@ #include "qemu-common.h" #include "ui/console.h" #include "hw/usb.h" -#include "monitor.h" +#include "monitor/monitor.h" void usb_host_info(Monitor *mon) { diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 9e7f6453f7..3621076020 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -27,7 +27,7 @@ #include "qemu-common.h" #include "qemu-timer.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "sysemu.h" #include "iov.h" diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index 155da58dcd..5559518a93 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -19,7 +19,7 @@ */ #include "iov.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "qemu-queue.h" #include "sysbus.h" #include "trace.h" diff --git a/hw/watchdog.c b/hw/watchdog.c index f878bec860..623b299f71 100644 --- a/hw/watchdog.c +++ b/hw/watchdog.c @@ -24,7 +24,7 @@ #include "qemu-config.h" #include "qemu-queue.h" #include "qapi/qmp/types.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "sysemu.h" #include "hw/watchdog.h" diff --git a/include/block/block_int.h b/include/block/block_int.h index d06de2637b..14c57afd54 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -31,7 +31,7 @@ #include "qemu-timer.h" #include "qapi-types.h" #include "qapi/qmp/qerror.h" -#include "monitor.h" +#include "monitor/monitor.h" #define BLOCK_FLAG_ENCRYPT 1 #define BLOCK_FLAG_COMPAT6 4 diff --git a/monitor.h b/include/monitor/monitor.h similarity index 99% rename from monitor.h rename to include/monitor/monitor.h index 9e96e83f5f..87fb49c092 100644 --- a/monitor.h +++ b/include/monitor/monitor.h @@ -5,7 +5,7 @@ #include "qapi/qmp/qerror.h" #include "qapi/qmp/qdict.h" #include "block/block.h" -#include "readline.h" +#include "monitor/readline.h" extern Monitor *cur_mon; extern Monitor *default_mon; diff --git a/readline.h b/include/monitor/readline.h similarity index 100% rename from readline.h rename to include/monitor/readline.h diff --git a/include/ui/console.h b/include/ui/console.h index eff5cc92d6..3db6635b0a 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -4,7 +4,7 @@ #include "ui/qemu-pixman.h" #include "qapi/qmp/qdict.h" #include "notify.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "trace.h" #include "qapi-types.h" #include "qapi/error.h" diff --git a/include/ui/qemu-spice.h b/include/ui/qemu-spice.h index 5857b8a92e..3e08be06bf 100644 --- a/include/ui/qemu-spice.h +++ b/include/ui/qemu-spice.h @@ -24,7 +24,7 @@ #include "qemu-option.h" #include "qemu-config.h" -#include "monitor.h" +#include "monitor/monitor.h" extern int using_spice; @@ -47,7 +47,7 @@ void do_info_spice(Monitor *mon, QObject **ret_data); CharDriverState *qemu_chr_open_spice(QemuOpts *opts); #else /* CONFIG_SPICE */ -#include "monitor.h" +#include "monitor/monitor.h" #define using_spice 0 static inline int qemu_spice_set_passwd(const char *passwd, diff --git a/migration-fd.c b/migration-fd.c index e86228823f..73a1dfcc93 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -16,7 +16,7 @@ #include "qemu-common.h" #include "qemu_socket.h" #include "migration.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "buffered_file.h" #include "block/block.h" #include "qemu_socket.h" diff --git a/migration.c b/migration.c index 1fce152548..27a272eace 100644 --- a/migration.c +++ b/migration.c @@ -15,7 +15,7 @@ #include "qemu-common.h" #include "migration.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "buffered_file.h" #include "sysemu.h" #include "block/block.h" diff --git a/monitor.c b/monitor.c index a3e010968e..94c6bb6672 100644 --- a/monitor.c +++ b/monitor.c @@ -36,8 +36,8 @@ #include "qemu-char.h" #include "ui/qemu-spice.h" #include "sysemu.h" -#include "monitor.h" -#include "readline.h" +#include "monitor/monitor.h" +#include "monitor/readline.h" #include "ui/console.h" #include "blockdev.h" #include "audio/audio.h" diff --git a/net/hub.c b/net/hub.c index 8508ecf380..81a73b54a7 100644 --- a/net/hub.c +++ b/net/hub.c @@ -12,7 +12,7 @@ * */ -#include "monitor.h" +#include "monitor/monitor.h" #include "net/net.h" #include "clients.h" #include "hub.h" diff --git a/net/net.c b/net/net.c index ead7e96fe1..e4d85a9cfa 100644 --- a/net/net.c +++ b/net/net.c @@ -29,7 +29,7 @@ #include "net/slirp.h" #include "util.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "qemu-common.h" #include "qemu_socket.h" #include "qemu-config.h" diff --git a/net/slirp.c b/net/slirp.c index 5a11ac5859..c37a5ef959 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -32,7 +32,7 @@ #include "net/net.h" #include "clients.h" #include "hub.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "qemu_socket.h" #include "slirp/libslirp.h" #include "qemu-char.h" diff --git a/net/socket.c b/net/socket.c index 8430f1a161..bc2b951832 100644 --- a/net/socket.c +++ b/net/socket.c @@ -25,7 +25,7 @@ #include "net/net.h" #include "clients.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "qemu-common.h" #include "qemu-error.h" #include "qemu-option.h" diff --git a/net/tap.c b/net/tap.c index f8cabc4f86..9a677e9864 100644 --- a/net/tap.c +++ b/net/tap.c @@ -35,7 +35,7 @@ #include "net/net.h" #include "clients.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "sysemu.h" #include "qemu-common.h" #include "qemu-error.h" diff --git a/osdep.c b/osdep.c index 3a63d26e75..807e90cf97 100644 --- a/osdep.c +++ b/osdep.c @@ -48,7 +48,7 @@ extern int madvise(caddr_t, size_t, int); #include "qemu-common.h" #include "trace.h" #include "qemu_socket.h" -#include "monitor.h" +#include "monitor/monitor.h" static bool fips_enabled = false; diff --git a/qemu-char.c b/qemu-char.c index bc53d09a9b..16021c5a43 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "ui/console.h" #include "sysemu.h" #include "qemu-timer.h" diff --git a/qemu-error.c b/qemu-error.c index 7cd5ffe1e9..08a36f480c 100644 --- a/qemu-error.c +++ b/qemu-error.c @@ -11,7 +11,7 @@ */ #include -#include "monitor.h" +#include "monitor/monitor.h" /* * Print to current monitor if we have one, else to stderr. diff --git a/qemu-sockets.c b/qemu-sockets.c index c52a40a411..cea0a4b8ac 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -22,7 +22,7 @@ #include #include -#include "monitor.h" +#include "monitor/monitor.h" #include "qemu_socket.h" #include "qemu-common.h" /* for qemu_isdigit */ #include "main-loop.h" diff --git a/qemu-timer.c b/qemu-timer.c index 5a99403fda..8e0dccc087 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -23,7 +23,7 @@ */ #include "sysemu.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "ui/console.h" #include "hw/hw.h" diff --git a/qemu-tool.c b/qemu-tool.c index b46631e422..40453fdd99 100644 --- a/qemu-tool.c +++ b/qemu-tool.c @@ -14,7 +14,7 @@ */ #include "qemu-common.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "qemu-timer.h" #include "qemu-log.h" #include "migration.h" diff --git a/qemu-user.c b/qemu-user.c index 08ccb0fe8e..f8b450c03d 100644 --- a/qemu-user.c +++ b/qemu-user.c @@ -19,7 +19,7 @@ */ #include "qemu-common.h" -#include "monitor.h" +#include "monitor/monitor.h" Monitor *cur_mon; diff --git a/qerror.c b/qerror.c index 8c78104277..3aee1cf6a6 100644 --- a/qerror.c +++ b/qerror.c @@ -10,7 +10,7 @@ * See the COPYING.LIB file in the top-level directory. */ -#include "monitor.h" +#include "monitor/monitor.h" #include "qapi/qmp/qjson.h" #include "qapi/qmp/qerror.h" #include "qemu-common.h" diff --git a/readline.c b/readline.c index 540cd8a025..5fc9643c2b 100644 --- a/readline.c +++ b/readline.c @@ -21,8 +21,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "readline.h" -#include "monitor.h" +#include "monitor/readline.h" +#include "monitor/monitor.h" #define IS_NORM 0 #define IS_ESC 1 diff --git a/savevm.c b/savevm.c index cb33501ecc..bf341bb25f 100644 --- a/savevm.c +++ b/savevm.c @@ -73,7 +73,7 @@ #include "hw/hw.h" #include "hw/qdev.h" #include "net/net.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "sysemu.h" #include "qemu-timer.h" #include "audio/audio.h" diff --git a/slirp/misc.c b/slirp/misc.c index 664532a663..d4df972d13 100644 --- a/slirp/misc.c +++ b/slirp/misc.c @@ -8,7 +8,7 @@ #include #include -#include "monitor.h" +#include "monitor/monitor.h" #ifdef DEBUG int slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR; @@ -242,7 +242,7 @@ strdup(str) } #endif -#include "monitor.h" +#include "monitor/monitor.h" void lprint(const char *format, ...) { diff --git a/stubs/fdset-add-fd.c b/stubs/fdset-add-fd.c index 09fe2a839a..ee1643708c 100644 --- a/stubs/fdset-add-fd.c +++ b/stubs/fdset-add-fd.c @@ -1,5 +1,5 @@ #include "qemu-common.h" -#include "monitor.h" +#include "monitor/monitor.h" int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd) { diff --git a/stubs/fdset-find-fd.c b/stubs/fdset-find-fd.c index f82baa066c..4f18344bad 100644 --- a/stubs/fdset-find-fd.c +++ b/stubs/fdset-find-fd.c @@ -1,5 +1,5 @@ #include "qemu-common.h" -#include "monitor.h" +#include "monitor/monitor.h" int monitor_fdset_dup_fd_find(int dup_fd) { diff --git a/stubs/fdset-get-fd.c b/stubs/fdset-get-fd.c index 4106cf90f0..7112c155e3 100644 --- a/stubs/fdset-get-fd.c +++ b/stubs/fdset-get-fd.c @@ -1,5 +1,5 @@ #include "qemu-common.h" -#include "monitor.h" +#include "monitor/monitor.h" int monitor_fdset_get_fd(int64_t fdset_id, int flags) { diff --git a/stubs/fdset-remove-fd.c b/stubs/fdset-remove-fd.c index 861b31247e..b3886d9f45 100644 --- a/stubs/fdset-remove-fd.c +++ b/stubs/fdset-remove-fd.c @@ -1,5 +1,5 @@ #include "qemu-common.h" -#include "monitor.h" +#include "monitor/monitor.h" int monitor_fdset_dup_fd_remove(int dupfd) { diff --git a/stubs/get-fd.c b/stubs/get-fd.c index 3561ab60e2..9f2c65cf0a 100644 --- a/stubs/get-fd.c +++ b/stubs/get-fd.c @@ -1,5 +1,5 @@ #include "qemu-common.h" -#include "monitor.h" +#include "monitor/monitor.h" int monitor_get_fd(Monitor *mon, const char *name, Error **errp) { diff --git a/target-i386/helper.c b/target-i386/helper.c index 00341c5233..bd47b8e58e 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -21,7 +21,7 @@ #include "kvm.h" #ifndef CONFIG_USER_ONLY #include "sysemu.h" -#include "monitor.h" +#include "monitor/monitor.h" #endif //#define DEBUG_MMU diff --git a/ui/input.c b/ui/input.c index 65950af9af..05f6c0c849 100644 --- a/ui/input.c +++ b/ui/input.c @@ -23,7 +23,7 @@ */ #include "sysemu.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "ui/console.h" #include "qapi/error.h" #include "qmp-commands.h" diff --git a/ui/spice-core.c b/ui/spice-core.c index 0550805b38..379677554e 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -35,7 +35,7 @@ #include "qapi/qmp/qjson.h" #include "notify.h" #include "migration.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "hw/hw.h" #include "ui/spice-display.h" diff --git a/ui/spice-display.c b/ui/spice-display.c index 681fe32fed..56ebf80805 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -19,7 +19,7 @@ #include "ui/qemu-spice.h" #include "qemu-timer.h" #include "qemu-queue.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "ui/console.h" #include "sysemu.h" #include "trace.h" diff --git a/ui/vnc.h b/ui/vnc.h index 7ec183372a..e5c043ff45 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -31,7 +31,7 @@ #include "qemu-queue.h" #include "qemu-thread.h" #include "ui/console.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "audio/audio.h" #include "bitmap.h" #include diff --git a/vl.c b/vl.c index 015f0a4757..9adaf28e64 100644 --- a/vl.c +++ b/vl.c @@ -129,7 +129,7 @@ int main(int argc, char **argv) #include "bt-host.h" #include "net/net.h" #include "net/slirp.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "ui/console.h" #include "sysemu.h" #include "exec/gdbstub.h" From caf71f86a3de97394bcc5b06549012b7dc65fe60 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Dec 2012 18:19:50 +0100 Subject: [PATCH 2062/2270] migration: move include files to include/migration/ Signed-off-by: Paolo Bonzini --- arch_init.c | 4 ++-- block-migration.c | 4 ++-- block/qcow.c | 2 +- block/qed.c | 2 +- block/vdi.c | 2 +- block/vmdk.c | 2 +- block/vpc.c | 2 +- block/vvfat.c | 2 +- buffered_file.h | 2 +- hw/9pfs/virtio-9p.c | 2 +- hw/hid.h | 2 +- hw/hw.h | 4 ++-- hw/ivshmem.c | 2 +- hw/pci/shpc.h | 2 +- hw/ptimer.h | 2 +- block-migration.h => include/migration/block.h | 0 migration.h => include/migration/migration.h | 2 +- include/{qemu => migration}/page_cache.h | 0 qemu-file.h => include/migration/qemu-file.h | 0 vmstate.h => include/migration/vmstate.h | 0 include/net/net.h | 2 +- migration-exec.c | 2 +- migration-fd.c | 2 +- migration-tcp.c | 2 +- migration-unix.c | 2 +- migration.c | 4 ++-- monitor.c | 2 +- page_cache.c | 2 +- qemu-tool.c | 2 +- savevm.c | 2 +- ui/spice-core.c | 2 +- vl.c | 4 ++-- 32 files changed, 33 insertions(+), 33 deletions(-) rename block-migration.h => include/migration/block.h (100%) rename migration.h => include/migration/migration.h (99%) rename include/{qemu => migration}/page_cache.h (100%) rename qemu-file.h => include/migration/qemu-file.h (100%) rename vmstate.h => include/migration/vmstate.h (100%) diff --git a/arch_init.c b/arch_init.c index 93d1e52f4a..f627253a20 100644 --- a/arch_init.c +++ b/arch_init.c @@ -39,12 +39,12 @@ #include "hw/pci/pci.h" #include "hw/audiodev.h" #include "kvm.h" -#include "migration.h" +#include "migration/migration.h" #include "exec/gdbstub.h" #include "hw/smbios.h" #include "exec/address-spaces.h" #include "hw/pcspk.h" -#include "qemu/page_cache.h" +#include "migration/page_cache.h" #include "qemu-config.h" #include "qmp-commands.h" #include "trace.h" diff --git a/block-migration.c b/block-migration.c index c15de9f750..2d2dcbda94 100644 --- a/block-migration.c +++ b/block-migration.c @@ -18,8 +18,8 @@ #include "hw/hw.h" #include "qemu-queue.h" #include "qemu-timer.h" -#include "block-migration.h" -#include "migration.h" +#include "migration/block.h" +#include "migration/migration.h" #include "blockdev.h" #include diff --git a/block/qcow.c b/block/qcow.c index d13bd400f0..f36671196e 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -26,7 +26,7 @@ #include "module.h" #include #include "block/aes.h" -#include "migration.h" +#include "migration/migration.h" /**************************************************************/ /* QEMU COW block driver with compression and encryption support */ diff --git a/block/qed.c b/block/qed.c index ca1fafb47e..10d0827482 100644 --- a/block/qed.c +++ b/block/qed.c @@ -16,7 +16,7 @@ #include "trace.h" #include "qed.h" #include "qapi/qmp/qerror.h" -#include "migration.h" +#include "migration/migration.h" static void qed_aio_cancel(BlockDriverAIOCB *blockacb) { diff --git a/block/vdi.c b/block/vdi.c index dab9cac76e..b1d199a2e5 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -52,7 +52,7 @@ #include "qemu-common.h" #include "block/block_int.h" #include "module.h" -#include "migration.h" +#include "migration/migration.h" #if defined(CONFIG_UUID) #include diff --git a/block/vmdk.c b/block/vmdk.c index 68e50e1a3e..77a1a67c61 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -26,7 +26,7 @@ #include "qemu-common.h" #include "block/block_int.h" #include "module.h" -#include "migration.h" +#include "migration/migration.h" #include #define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D') diff --git a/block/vpc.c b/block/vpc.c index aabd71201c..47b5518aee 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -25,7 +25,7 @@ #include "qemu-common.h" #include "block/block_int.h" #include "module.h" -#include "migration.h" +#include "migration/migration.h" #if defined(CONFIG_UUID) #include #endif diff --git a/block/vvfat.c b/block/vvfat.c index fbabafca76..a63c3ea7cd 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -27,7 +27,7 @@ #include "qemu-common.h" #include "block/block_int.h" #include "module.h" -#include "migration.h" +#include "migration/migration.h" #ifndef S_IWGRP #define S_IWGRP 0 diff --git a/buffered_file.h b/buffered_file.h index ef010febfe..86a7075246 100644 --- a/buffered_file.h +++ b/buffered_file.h @@ -15,7 +15,7 @@ #define QEMU_BUFFERED_FILE_H #include "hw/hw.h" -#include "migration.h" +#include "migration/migration.h" QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state); diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 8b9cdc96ed..ede20ce80e 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -20,7 +20,7 @@ #include "virtio-9p-xattr.h" #include "virtio-9p-coth.h" #include "trace.h" -#include "migration.h" +#include "migration/migration.h" int open_fd_hw; int total_open_fd; diff --git a/hw/hid.h b/hw/hid.h index 5315cf7a31..100b121663 100644 --- a/hw/hid.h +++ b/hw/hid.h @@ -1,7 +1,7 @@ #ifndef QEMU_HID_H #define QEMU_HID_H -#include "vmstate.h" +#include "migration/vmstate.h" #define HID_MOUSE 1 #define HID_TABLET 2 diff --git a/hw/hw.h b/hw/hw.h index 7368470bb1..883ddb60f9 100644 --- a/hw/hw.h +++ b/hw/hw.h @@ -11,8 +11,8 @@ #include "exec/ioport.h" #include "irq.h" #include "block/aio.h" -#include "qemu-file.h" -#include "vmstate.h" +#include "migration/qemu-file.h" +#include "migration/vmstate.h" #include "qemu-log.h" #ifdef NEED_CPU_H diff --git a/hw/ivshmem.c b/hw/ivshmem.c index d15760b314..d5b91dd24e 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -21,7 +21,7 @@ #include "pci/pci.h" #include "pci/msix.h" #include "kvm.h" -#include "migration.h" +#include "migration/migration.h" #include "qapi/qmp/qerror.h" #include "event_notifier.h" #include "qemu-char.h" diff --git a/hw/pci/shpc.h b/hw/pci/shpc.h index 6374e68bdb..467911a558 100644 --- a/hw/pci/shpc.h +++ b/hw/pci/shpc.h @@ -3,7 +3,7 @@ #include "qemu-common.h" #include "exec/memory.h" -#include "vmstate.h" +#include "migration/vmstate.h" struct SHPCDevice { /* Capability offset in device's config space */ diff --git a/hw/ptimer.h b/hw/ptimer.h index 6638f61322..9d172f7764 100644 --- a/hw/ptimer.h +++ b/hw/ptimer.h @@ -10,7 +10,7 @@ #include "qemu-common.h" #include "qemu-timer.h" -#include "vmstate.h" +#include "migration/vmstate.h" /* ptimer.c */ typedef struct ptimer_state ptimer_state; diff --git a/block-migration.h b/include/migration/block.h similarity index 100% rename from block-migration.h rename to include/migration/block.h diff --git a/migration.h b/include/migration/migration.h similarity index 99% rename from migration.h rename to include/migration/migration.h index af444d444b..a95f761e4c 100644 --- a/migration.h +++ b/include/migration/migration.h @@ -18,7 +18,7 @@ #include "qemu-common.h" #include "notify.h" #include "qapi/error.h" -#include "vmstate.h" +#include "migration/vmstate.h" #include "qapi-types.h" struct MigrationParams { diff --git a/include/qemu/page_cache.h b/include/migration/page_cache.h similarity index 100% rename from include/qemu/page_cache.h rename to include/migration/page_cache.h diff --git a/qemu-file.h b/include/migration/qemu-file.h similarity index 100% rename from qemu-file.h rename to include/migration/qemu-file.h diff --git a/vmstate.h b/include/migration/vmstate.h similarity index 100% rename from vmstate.h rename to include/migration/vmstate.h diff --git a/include/net/net.h b/include/net/net.h index 26dd0cf29c..41d3729867 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -6,7 +6,7 @@ #include "qapi/qmp/qdict.h" #include "qemu-option.h" #include "net/queue.h" -#include "vmstate.h" +#include "migration/vmstate.h" #include "qapi-types.h" struct MACAddr { diff --git a/migration-exec.c b/migration-exec.c index 3e55b7792d..784486d2fc 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -17,7 +17,7 @@ #include "qemu-common.h" #include "qemu_socket.h" -#include "migration.h" +#include "migration/migration.h" #include "buffered_file.h" #include "block/block.h" #include diff --git a/migration-fd.c b/migration-fd.c index 73a1dfcc93..ab5abe2aa5 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -15,7 +15,7 @@ #include "qemu-common.h" #include "qemu_socket.h" -#include "migration.h" +#include "migration/migration.h" #include "monitor/monitor.h" #include "buffered_file.h" #include "block/block.h" diff --git a/migration-tcp.c b/migration-tcp.c index 07f51f2aef..a36e637ffd 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -15,7 +15,7 @@ #include "qemu-common.h" #include "qemu_socket.h" -#include "migration.h" +#include "migration/migration.h" #include "buffered_file.h" #include "block/block.h" diff --git a/migration-unix.c b/migration-unix.c index 1b9c461083..9debc952da 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -15,7 +15,7 @@ #include "qemu-common.h" #include "qemu_socket.h" -#include "migration.h" +#include "migration/migration.h" #include "buffered_file.h" #include "block/block.h" diff --git a/migration.c b/migration.c index 27a272eace..0456983bad 100644 --- a/migration.c +++ b/migration.c @@ -14,13 +14,13 @@ */ #include "qemu-common.h" -#include "migration.h" +#include "migration/migration.h" #include "monitor/monitor.h" #include "buffered_file.h" #include "sysemu.h" #include "block/block.h" #include "qemu_socket.h" -#include "block-migration.h" +#include "migration/block.h" #include "qmp-commands.h" //#define DEBUG_MIGRATION diff --git a/monitor.c b/monitor.c index 94c6bb6672..46fdc008f4 100644 --- a/monitor.c +++ b/monitor.c @@ -44,7 +44,7 @@ #include "disas/disas.h" #include "balloon.h" #include "qemu-timer.h" -#include "migration.h" +#include "migration/migration.h" #include "kvm.h" #include "acl.h" #include "qapi/qmp/qint.h" diff --git a/page_cache.c b/page_cache.c index 0294f7e9f6..ba5640bd73 100644 --- a/page_cache.c +++ b/page_cache.c @@ -24,7 +24,7 @@ #include #include "qemu-common.h" -#include "qemu/page_cache.h" +#include "migration/page_cache.h" #ifdef DEBUG_CACHE #define DPRINTF(fmt, ...) \ diff --git a/qemu-tool.c b/qemu-tool.c index 40453fdd99..d1f46222ee 100644 --- a/qemu-tool.c +++ b/qemu-tool.c @@ -17,7 +17,7 @@ #include "monitor/monitor.h" #include "qemu-timer.h" #include "qemu-log.h" -#include "migration.h" +#include "migration/migration.h" #include "main-loop.h" #include "sysemu.h" #include "qemu_socket.h" diff --git a/savevm.c b/savevm.c index bf341bb25f..a5205a09c3 100644 --- a/savevm.c +++ b/savevm.c @@ -77,7 +77,7 @@ #include "sysemu.h" #include "qemu-timer.h" #include "audio/audio.h" -#include "migration.h" +#include "migration/migration.h" #include "qemu_socket.h" #include "qemu-queue.h" #include "qemu-timer.h" diff --git a/ui/spice-core.c b/ui/spice-core.c index 379677554e..962475de6b 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -34,7 +34,7 @@ #include "qapi/qmp/qstring.h" #include "qapi/qmp/qjson.h" #include "notify.h" -#include "migration.h" +#include "migration/migration.h" #include "monitor/monitor.h" #include "hw/hw.h" #include "ui/spice-display.h" diff --git a/vl.c b/vl.c index 9adaf28e64..2debde0a4a 100644 --- a/vl.c +++ b/vl.c @@ -138,10 +138,10 @@ int main(int argc, char **argv) #include "cache-utils.h" #include "blockdev.h" #include "hw/block-common.h" -#include "block-migration.h" +#include "migration/block.h" #include "dma.h" #include "audio/audio.h" -#include "migration.h" +#include "migration/migration.h" #include "kvm.h" #include "qapi/qmp/qjson.h" #include "qemu-option.h" From 14cccb618508a0aa70eb9ccf366703a019a45ff0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Dec 2012 18:19:50 +0100 Subject: [PATCH 2063/2270] qom: move include files to include/qom/ Signed-off-by: Paolo Bonzini --- hw/qdev-core.h | 2 +- hw/stream.h | 2 +- include/qemu/rng-random.h | 2 +- include/qemu/rng.h | 2 +- include/{qemu => qom}/cpu.h | 2 +- include/{qemu => qom}/object.h | 0 include/{qemu => qom}/qom-qobject.h | 2 +- qmp.c | 2 +- qom/container.c | 2 +- qom/cpu.c | 2 +- qom/object.c | 4 ++-- qom/qom-qobject.c | 4 ++-- target-alpha/cpu-qom.h | 2 +- target-arm/cpu-qom.h | 2 +- target-cris/cpu-qom.h | 2 +- target-i386/cpu-qom.h | 2 +- target-lm32/cpu-qom.h | 2 +- target-m68k/cpu-qom.h | 2 +- target-microblaze/cpu-qom.h | 2 +- target-mips/cpu-qom.h | 2 +- target-openrisc/cpu.h | 2 +- target-ppc/cpu-qom.h | 2 +- target-s390x/cpu-qom.h | 2 +- target-sh4/cpu-qom.h | 2 +- target-sparc/cpu-qom.h | 2 +- target-unicore32/cpu-qom.h | 2 +- target-xtensa/cpu-qom.h | 2 +- 27 files changed, 28 insertions(+), 28 deletions(-) rename include/{qemu => qom}/cpu.h (99%) rename include/{qemu => qom}/object.h (100%) rename include/{qemu => qom}/qom-qobject.h (97%) diff --git a/hw/qdev-core.h b/hw/qdev-core.h index 506977c109..93a3a2a7bc 100644 --- a/hw/qdev-core.h +++ b/hw/qdev-core.h @@ -4,7 +4,7 @@ #include "qemu-queue.h" #include "qemu-option.h" #include "qemu-types.h" -#include "qemu/object.h" +#include "qom/object.h" #include "hw/irq.h" #include "qapi/error.h" diff --git a/hw/stream.h b/hw/stream.h index 21123a9089..f6137d6e25 100644 --- a/hw/stream.h +++ b/hw/stream.h @@ -2,7 +2,7 @@ #define STREAM_H 1 #include "qemu-common.h" -#include "qemu/object.h" +#include "qom/object.h" /* stream slave. Used until qdev provides a generic way. */ #define TYPE_STREAM_SLAVE "stream-slave" diff --git a/include/qemu/rng-random.h b/include/qemu/rng-random.h index 6249290cc4..4332772a24 100644 --- a/include/qemu/rng-random.h +++ b/include/qemu/rng-random.h @@ -12,7 +12,7 @@ #ifndef QEMU_RNG_RANDOM_H #define QEMU_RNG_RANDOM_H -#include "qemu/object.h" +#include "qom/object.h" #define TYPE_RNG_RANDOM "rng-random" #define RNG_RANDOM(obj) OBJECT_CHECK(RndRandom, (obj), TYPE_RNG_RANDOM) diff --git a/include/qemu/rng.h b/include/qemu/rng.h index 37912971e0..509abd023d 100644 --- a/include/qemu/rng.h +++ b/include/qemu/rng.h @@ -13,7 +13,7 @@ #ifndef QEMU_RNG_H #define QEMU_RNG_H -#include "qemu/object.h" +#include "qom/object.h" #include "qemu-common.h" #include "qapi/error.h" diff --git a/include/qemu/cpu.h b/include/qom/cpu.h similarity index 99% rename from include/qemu/cpu.h rename to include/qom/cpu.h index 61b76982f1..9682dd59ed 100644 --- a/include/qemu/cpu.h +++ b/include/qom/cpu.h @@ -20,7 +20,7 @@ #ifndef QEMU_CPU_H #define QEMU_CPU_H -#include "qemu/object.h" +#include "qom/object.h" #include "qemu-thread.h" /** diff --git a/include/qemu/object.h b/include/qom/object.h similarity index 100% rename from include/qemu/object.h rename to include/qom/object.h diff --git a/include/qemu/qom-qobject.h b/include/qom/qom-qobject.h similarity index 97% rename from include/qemu/qom-qobject.h rename to include/qom/qom-qobject.h index f9dff12f11..77cd717e3f 100644 --- a/include/qemu/qom-qobject.h +++ b/include/qom/qom-qobject.h @@ -13,7 +13,7 @@ #ifndef QEMU_QOM_QOBJECT_H #define QEMU_QOM_QOBJECT_H -#include "qemu/object.h" +#include "qom/object.h" /* * object_property_get_qobject: diff --git a/qmp.c b/qmp.c index e873f0a0dc..5b3a5d7d03 100644 --- a/qmp.c +++ b/qmp.c @@ -23,7 +23,7 @@ #include "arch_init.h" #include "hw/qdev.h" #include "blockdev.h" -#include "qemu/qom-qobject.h" +#include "qom/qom-qobject.h" NameInfo *qmp_query_name(Error **errp) { diff --git a/qom/container.c b/qom/container.c index 4ca8b5cba3..ceb0f0186d 100644 --- a/qom/container.c +++ b/qom/container.c @@ -10,7 +10,7 @@ * See the COPYING file in the top-level directory. */ -#include "qemu/object.h" +#include "qom/object.h" #include "module.h" #include diff --git a/qom/cpu.c b/qom/cpu.c index 5b360469c5..d4d436f80a 100644 --- a/qom/cpu.c +++ b/qom/cpu.c @@ -18,7 +18,7 @@ * */ -#include "qemu/cpu.h" +#include "qom/cpu.h" #include "qemu-common.h" void cpu_reset(CPUState *cpu) diff --git a/qom/object.c b/qom/object.c index 932f8b30de..351b88c817 100644 --- a/qom/object.c +++ b/qom/object.c @@ -10,7 +10,7 @@ * See the COPYING file in the top-level directory. */ -#include "qemu/object.h" +#include "qom/object.h" #include "qemu-common.h" #include "qapi/visitor.h" #include "qapi/string-input-visitor.h" @@ -19,7 +19,7 @@ /* TODO: replace QObject with a simpler visitor to avoid a dependency * of the QOM core on QObject? */ -#include "qemu/qom-qobject.h" +#include "qom/qom-qobject.h" #include "qapi/qmp/qobject.h" #include "qapi/qmp/qbool.h" #include "qapi/qmp/qint.h" diff --git a/qom/qom-qobject.c b/qom/qom-qobject.c index f0fa652157..6384b8e98c 100644 --- a/qom/qom-qobject.c +++ b/qom/qom-qobject.c @@ -10,8 +10,8 @@ */ #include "qemu-common.h" -#include "qemu/object.h" -#include "qemu/qom-qobject.h" +#include "qom/object.h" +#include "qom/qom-qobject.h" #include "qapi/visitor.h" #include "qapi/qmp-input-visitor.h" #include "qapi/qmp-output-visitor.h" diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h index 6b4ca6d1d1..f2414f7e4f 100644 --- a/target-alpha/cpu-qom.h +++ b/target-alpha/cpu-qom.h @@ -20,7 +20,7 @@ #ifndef QEMU_ALPHA_CPU_QOM_H #define QEMU_ALPHA_CPU_QOM_H -#include "qemu/cpu.h" +#include "qom/cpu.h" #include "cpu.h" #define TYPE_ALPHA_CPU "alpha-cpu" diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h index beabf9a0a9..0f455c40ff 100644 --- a/target-arm/cpu-qom.h +++ b/target-arm/cpu-qom.h @@ -20,7 +20,7 @@ #ifndef QEMU_ARM_CPU_QOM_H #define QEMU_ARM_CPU_QOM_H -#include "qemu/cpu.h" +#include "qom/cpu.h" #define TYPE_ARM_CPU "arm-cpu" diff --git a/target-cris/cpu-qom.h b/target-cris/cpu-qom.h index d0e5f04f78..41ab9b2fa5 100644 --- a/target-cris/cpu-qom.h +++ b/target-cris/cpu-qom.h @@ -20,7 +20,7 @@ #ifndef QEMU_CRIS_CPU_QOM_H #define QEMU_CRIS_CPU_QOM_H -#include "qemu/cpu.h" +#include "qom/cpu.h" #define TYPE_CRIS_CPU "cris-cpu" diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h index 3a7bc6aef4..332916a185 100644 --- a/target-i386/cpu-qom.h +++ b/target-i386/cpu-qom.h @@ -20,7 +20,7 @@ #ifndef QEMU_I386_CPU_QOM_H #define QEMU_I386_CPU_QOM_H -#include "qemu/cpu.h" +#include "qom/cpu.h" #include "cpu.h" #include "qapi/error.h" diff --git a/target-lm32/cpu-qom.h b/target-lm32/cpu-qom.h index 4ae2eddafb..400cdbd554 100644 --- a/target-lm32/cpu-qom.h +++ b/target-lm32/cpu-qom.h @@ -20,7 +20,7 @@ #ifndef QEMU_LM32_CPU_QOM_H #define QEMU_LM32_CPU_QOM_H -#include "qemu/cpu.h" +#include "qom/cpu.h" #include "cpu.h" #define TYPE_LM32_CPU "lm32-cpu" diff --git a/target-m68k/cpu-qom.h b/target-m68k/cpu-qom.h index 805786b04d..170daa7c96 100644 --- a/target-m68k/cpu-qom.h +++ b/target-m68k/cpu-qom.h @@ -20,7 +20,7 @@ #ifndef QEMU_M68K_CPU_QOM_H #define QEMU_M68K_CPU_QOM_H -#include "qemu/cpu.h" +#include "qom/cpu.h" #define TYPE_M68K_CPU "m68k-cpu" diff --git a/target-microblaze/cpu-qom.h b/target-microblaze/cpu-qom.h index 4b23303b6d..f75549dc22 100644 --- a/target-microblaze/cpu-qom.h +++ b/target-microblaze/cpu-qom.h @@ -20,7 +20,7 @@ #ifndef QEMU_MICROBLAZE_CPU_QOM_H #define QEMU_MICROBLAZE_CPU_QOM_H -#include "qemu/cpu.h" +#include "qom/cpu.h" #define TYPE_MICROBLAZE_CPU "microblaze-cpu" diff --git a/target-mips/cpu-qom.h b/target-mips/cpu-qom.h index 6e2237123a..2a4b812402 100644 --- a/target-mips/cpu-qom.h +++ b/target-mips/cpu-qom.h @@ -20,7 +20,7 @@ #ifndef QEMU_MIPS_CPU_QOM_H #define QEMU_MIPS_CPU_QOM_H -#include "qemu/cpu.h" +#include "qom/cpu.h" #ifdef TARGET_MIPS64 #define TYPE_MIPS_CPU "mips64-cpu" diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h index 8dc56c2873..876b386a3c 100644 --- a/target-openrisc/cpu.h +++ b/target-openrisc/cpu.h @@ -32,7 +32,7 @@ struct OpenRISCCPU; #include "qemu-common.h" #include "exec/cpu-defs.h" #include "softfloat.h" -#include "qemu/cpu.h" +#include "qom/cpu.h" #include "qapi/error.h" #define TYPE_OPENRISC_CPU "or32-cpu" diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h index fef6f95a04..fb6b5a4119 100644 --- a/target-ppc/cpu-qom.h +++ b/target-ppc/cpu-qom.h @@ -20,7 +20,7 @@ #ifndef QEMU_PPC_CPU_QOM_H #define QEMU_PPC_CPU_QOM_H -#include "qemu/cpu.h" +#include "qom/cpu.h" #include "cpu.h" #ifdef TARGET_PPC64 diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h index 6fa55a80a5..d54e4a2ee2 100644 --- a/target-s390x/cpu-qom.h +++ b/target-s390x/cpu-qom.h @@ -20,7 +20,7 @@ #ifndef QEMU_S390_CPU_QOM_H #define QEMU_S390_CPU_QOM_H -#include "qemu/cpu.h" +#include "qom/cpu.h" #include "cpu.h" #define TYPE_S390_CPU "s390-cpu" diff --git a/target-sh4/cpu-qom.h b/target-sh4/cpu-qom.h index c41164aa22..09573c9c34 100644 --- a/target-sh4/cpu-qom.h +++ b/target-sh4/cpu-qom.h @@ -20,7 +20,7 @@ #ifndef QEMU_SUPERH_CPU_QOM_H #define QEMU_SUPERH_CPU_QOM_H -#include "qemu/cpu.h" +#include "qom/cpu.h" #define TYPE_SUPERH_CPU "superh-cpu" diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h index 3d3ac0fcef..2a738ae360 100644 --- a/target-sparc/cpu-qom.h +++ b/target-sparc/cpu-qom.h @@ -20,7 +20,7 @@ #ifndef QEMU_SPARC_CPU_QOM_H #define QEMU_SPARC_CPU_QOM_H -#include "qemu/cpu.h" +#include "qom/cpu.h" #include "cpu.h" #ifdef TARGET_SPARC64 diff --git a/target-unicore32/cpu-qom.h b/target-unicore32/cpu-qom.h index 342d85e39b..fe40b2d6a8 100644 --- a/target-unicore32/cpu-qom.h +++ b/target-unicore32/cpu-qom.h @@ -11,7 +11,7 @@ #ifndef QEMU_UC32_CPU_QOM_H #define QEMU_UC32_CPU_QOM_H -#include "qemu/cpu.h" +#include "qom/cpu.h" #include "cpu.h" #define TYPE_UNICORE32_CPU "unicore32-cpu" diff --git a/target-xtensa/cpu-qom.h b/target-xtensa/cpu-qom.h index 1fd2f274a1..e344a9aa79 100644 --- a/target-xtensa/cpu-qom.h +++ b/target-xtensa/cpu-qom.h @@ -29,7 +29,7 @@ #ifndef QEMU_XTENSA_CPU_QOM_H #define QEMU_XTENSA_CPU_QOM_H -#include "qemu/cpu.h" +#include "qom/cpu.h" #include "cpu.h" #define TYPE_XTENSA_CPU "xtensa-cpu" From 1de7afc984b49af164e2619e6850b9732b173b34 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Dec 2012 18:20:00 +0100 Subject: [PATCH 2064/2270] misc: move include files to include/qemu/ Signed-off-by: Paolo Bonzini --- acl.c | 2 +- aio-posix.c | 4 ++-- aio-win32.c | 4 ++-- arch_init.c | 6 +++--- async.c | 2 +- audio/alsaaudio.c | 2 +- audio/audio.c | 2 +- audio/audio.h | 2 +- audio/noaudio.c | 2 +- audio/ossaudio.c | 4 ++-- audio/spiceaudio.c | 2 +- audio/wavaudio.c | 2 +- backends/rng-random.c | 2 +- bitmap.c | 4 ++-- bitops.c | 2 +- block-migration.c | 4 ++-- block.c | 6 +++--- block/blkdebug.c | 4 ++-- block/blkverify.c | 2 +- block/bochs.c | 2 +- block/cloop.c | 2 +- block/cow.c | 2 +- block/dmg.c | 4 ++-- block/gluster.c | 4 ++-- block/iscsi.c | 4 ++-- block/linux-aio.c | 4 ++-- block/nbd.c | 6 +++--- block/parallels.c | 2 +- block/qcow.c | 2 +- block/qcow2.c | 4 ++-- block/qed-table.c | 2 +- block/qed.c | 2 +- block/raw-posix.c | 8 ++++---- block/raw-win32.c | 6 +++--- block/raw.c | 2 +- block/rbd.c | 2 +- block/sheepdog.c | 6 +++--- block/vdi.c | 2 +- block/vmdk.c | 2 +- block/vpc.c | 2 +- block/vvfat.c | 2 +- block/win32-aio.c | 6 +++--- blockdev-nbd.c | 2 +- blockdev.c | 4 ++-- blockdev.h | 2 +- blockjob.c | 2 +- bsd-user/main.c | 4 ++-- bsd-user/qemu.h | 2 +- bt-host.c | 2 +- bt-vhci.c | 2 +- buffered_file.c | 2 +- cache-utils.c | 2 +- cmd.c | 2 +- compatfd.c | 2 +- cpu-exec.c | 2 +- cpus.c | 8 ++++---- cutils.c | 6 +++--- device_tree.c | 4 ++-- dma-helpers.c | 4 ++-- envlist.c | 4 ++-- event_notifier-posix.c | 4 ++-- event_notifier-win32.c | 4 ++-- exec.c | 6 +++--- fpu/softfloat.h | 2 +- fsdev/qemu-fsdev-dummy.c | 4 ++-- fsdev/qemu-fsdev.c | 6 +++--- fsdev/qemu-fsdev.h | 2 +- fsdev/virtfs-proxy-helper.c | 4 ++-- fsdev/virtio-9p-marshal.c | 4 ++-- gdbstub.c | 2 +- hmp.c | 6 +++--- host-utils.c | 2 +- hw/9pfs/codir.c | 2 +- hw/9pfs/cofile.c | 2 +- hw/9pfs/cofs.c | 2 +- hw/9pfs/coxattr.c | 2 +- hw/9pfs/virtio-9p-coth.c | 2 +- hw/9pfs/virtio-9p-coth.h | 2 +- hw/9pfs/virtio-9p-device.c | 2 +- hw/9pfs/virtio-9p-handle.c | 2 +- hw/9pfs/virtio-9p-local.c | 2 +- hw/9pfs/virtio-9p-posix-acl.c | 2 +- hw/9pfs/virtio-9p-xattr.h | 2 +- hw/9pfs/virtio-9p.c | 2 +- hw/9pfs/virtio-9p.h | 2 +- hw/acpi.h | 2 +- hw/acpi_ich9.c | 2 +- hw/acpi_piix4.c | 2 +- hw/adlib.c | 2 +- hw/alpha_pci.c | 2 +- hw/apic.c | 4 ++-- hw/apic_internal.h | 2 +- hw/applesmc.c | 2 +- hw/arm11mpcore.c | 2 +- hw/arm_boot.c | 2 +- hw/arm_mptimer.c | 2 +- hw/arm_sysctl.c | 2 +- hw/arm_timer.c | 2 +- hw/armv7m_nvic.c | 2 +- hw/baum.c | 2 +- hw/block-common.c | 2 +- hw/bt-hci-csr.c | 2 +- hw/bt-hci.c | 2 +- hw/bt-hid.c | 2 +- hw/bt-l2cap.c | 2 +- hw/cadence_ttc.c | 2 +- hw/cadence_uart.c | 2 +- hw/ccid-card-emulated.c | 2 +- hw/ccid-card-passthru.c | 2 +- hw/cs4231a.c | 2 +- hw/cuda.c | 2 +- hw/device-hotplug.c | 2 +- hw/dma.c | 2 +- hw/dp8393x.c | 2 +- hw/esp-pci.c | 2 +- hw/esp.c | 2 +- hw/etraxfs_ser.c | 2 +- hw/etraxfs_timer.c | 2 +- hw/exynos4210_fimd.c | 2 +- hw/exynos4210_i2c.c | 2 +- hw/exynos4210_mct.c | 2 +- hw/exynos4210_pwm.c | 2 +- hw/exynos4210_rtc.c | 4 ++-- hw/fdc.c | 6 +++--- hw/fw_cfg.c | 4 ++-- hw/grlib_gptimer.c | 2 +- hw/hid.c | 2 +- hw/hpet.c | 2 +- hw/hw.h | 2 +- hw/i8254.c | 2 +- hw/i8254_common.c | 2 +- hw/i8259.c | 2 +- hw/ich9.h | 2 +- hw/ide/core.c | 4 ++-- hw/ide/qdev.c | 2 +- hw/imx_avic.c | 2 +- hw/imx_timer.c | 2 +- hw/intel-hda.c | 2 +- hw/ivshmem.c | 2 +- hw/kvm/i8254.c | 2 +- hw/kvm/pci-assign.c | 4 ++-- hw/lance.c | 4 ++-- hw/leon3.c | 2 +- hw/lm32_sys.c | 6 +++--- hw/lm32_timer.c | 4 ++-- hw/lm32_uart.c | 2 +- hw/lm832x.c | 2 +- hw/lpc_ich9.c | 2 +- hw/m48t59.c | 2 +- hw/mac_dbdma.c | 2 +- hw/mc146818rtc.c | 2 +- hw/mcf5206.c | 2 +- hw/mcf5208.c | 2 +- hw/megasas.c | 2 +- hw/microblaze_boot.c | 4 ++-- hw/milkymist-ac97.c | 2 +- hw/milkymist-hpdmc.c | 2 +- hw/milkymist-memcard.c | 2 +- hw/milkymist-minimac2.c | 2 +- hw/milkymist-pfpu.c | 4 ++-- hw/milkymist-softusb.c | 2 +- hw/milkymist-sysctl.c | 4 ++-- hw/milkymist-tmu2.c | 2 +- hw/milkymist-uart.c | 2 +- hw/milkymist-vgafb.c | 2 +- hw/mips_fulong2e.c | 2 +- hw/mips_malta.c | 2 +- hw/mips_r4k.c | 2 +- hw/mips_timer.c | 2 +- hw/musicpal.c | 2 +- hw/nand.c | 2 +- hw/omap1.c | 2 +- hw/omap2.c | 2 +- hw/omap_dma.c | 2 +- hw/omap_gptimer.c | 2 +- hw/omap_synctimer.c | 2 +- hw/onenand.c | 2 +- hw/openrisc_timer.c | 2 +- hw/pc.c | 2 +- hw/pci/msi.c | 2 +- hw/pci/msix.c | 2 +- hw/pci/pci-hotplug.c | 2 +- hw/pci/pci.c | 2 +- hw/pci/pci_bridge.c | 2 +- hw/pci/pcie.c | 2 +- hw/pci/shpc.c | 4 ++-- hw/pcnet-pci.c | 2 +- hw/pcnet.c | 4 ++-- hw/pcspk.c | 2 +- hw/pflash_cfi01.c | 4 ++-- hw/pflash_cfi02.c | 4 ++-- hw/piix_pci.c | 2 +- hw/pl031.c | 2 +- hw/ppc.c | 4 ++-- hw/ppc/e500.c | 4 ++-- hw/ppc405_boards.c | 2 +- hw/ppc405_uc.c | 4 ++-- hw/ppc4xx_devs.c | 2 +- hw/ppc_booke.c | 4 ++-- hw/ppc_prep.c | 2 +- hw/ppce500_pci.c | 2 +- hw/ptimer.c | 4 ++-- hw/ptimer.h | 2 +- hw/pxa2xx_timer.c | 2 +- hw/q35.h | 2 +- hw/qdev-core.h | 6 +++--- hw/qdev-monitor.c | 2 +- hw/qxl-logger.c | 2 +- hw/qxl.c | 4 ++-- hw/qxl.h | 2 +- hw/rc4030.c | 2 +- hw/rtl8139.c | 4 ++-- hw/s390x/event-facility.h | 2 +- hw/s390x/sclpconsole.c | 2 +- hw/sb16.c | 4 ++-- hw/scsi-bus.c | 2 +- hw/scsi-disk.c | 2 +- hw/scsi-generic.c | 2 +- hw/sd.c | 2 +- hw/serial.c | 2 +- hw/sh_pci.c | 2 +- hw/sh_timer.c | 2 +- hw/slavio_timer.c | 2 +- hw/sm501.c | 2 +- hw/soc_dma.c | 2 +- hw/spapr.c | 2 +- hw/spitz.c | 2 +- hw/stellaris.c | 2 +- hw/strongarm.c | 2 +- hw/sun4m.c | 2 +- hw/sun4u.c | 2 +- hw/tsc2005.c | 2 +- hw/tsc210x.c | 2 +- hw/tusb6010.c | 2 +- hw/twl92230.c | 2 +- hw/usb.h | 2 +- hw/usb/combined-packet.c | 2 +- hw/usb/core.c | 2 +- hw/usb/dev-hid.c | 2 +- hw/usb/dev-network.c | 6 +++--- hw/usb/dev-serial.c | 2 +- hw/usb/dev-smartcard-reader.c | 2 +- hw/usb/dev-storage.c | 4 ++-- hw/usb/dev-uas.c | 4 ++-- hw/usb/hcd-ehci-pci.c | 2 +- hw/usb/hcd-ehci.h | 2 +- hw/usb/hcd-musb.c | 2 +- hw/usb/hcd-ohci.c | 2 +- hw/usb/hcd-uhci.c | 4 ++-- hw/usb/hcd-xhci.c | 2 +- hw/usb/host-linux.c | 2 +- hw/usb/redirect.c | 4 ++-- hw/vfio_pci.c | 8 ++++---- hw/vga-isa-mm.c | 2 +- hw/vga-isa.c | 2 +- hw/vga-pci.c | 2 +- hw/vga.c | 2 +- hw/vhost.c | 2 +- hw/vhost_net.c | 2 +- hw/virtex_ml507.c | 2 +- hw/virtio-balloon.c | 2 +- hw/virtio-blk.c | 2 +- hw/virtio-console.c | 2 +- hw/virtio-net.c | 6 +++--- hw/virtio-pci.c | 4 ++-- hw/virtio-rng.c | 2 +- hw/virtio-serial-bus.c | 4 ++-- hw/virtio.c | 4 ++-- hw/virtio.h | 2 +- hw/vt82c686.c | 2 +- hw/watchdog.c | 6 +++--- hw/watchdog.h | 2 +- hw/wdt_i6300esb.c | 2 +- hw/wdt_ib700.c | 2 +- hw/xen_backend.c | 2 +- hw/xen_common.h | 2 +- hw/xen_domainbuild.c | 4 ++-- hw/xen_pt.c | 2 +- hw/xen_pt_config_init.c | 2 +- hw/xgmac.c | 2 +- hw/xilinx_axidma.c | 4 ++-- hw/xilinx_axienet.c | 2 +- hw/xilinx_spi.c | 2 +- hw/xilinx_spips.c | 4 ++-- hw/xilinx_timer.c | 2 +- hw/xtensa_pic.c | 4 ++-- hw/zynq_slcr.c | 2 +- include/block/aio.h | 4 ++-- include/block/block.h | 2 +- include/block/block_int.h | 6 +++--- include/block/coroutine.h | 4 ++-- include/block/coroutine_int.h | 2 +- include/block/thread-pool.h | 4 ++-- include/exec/cpu-all.h | 2 +- include/exec/cpu-common.h | 4 ++-- include/exec/cpu-defs.h | 4 ++-- include/exec/exec-all.h | 2 +- include/exec/gen-icount.h | 2 +- include/exec/memory.h | 4 ++-- include/exec/softmmu_template.h | 2 +- include/migration/migration.h | 2 +- include/net/net.h | 4 ++-- include/net/slirp.h | 2 +- include/qapi/error.h | 2 +- include/qapi/opts-visitor.h | 2 +- include/qapi/qmp/qdict.h | 2 +- include/qapi/qmp/qerror.h | 2 +- include/qapi/qmp/qjson.h | 2 +- include/qapi/qmp/qlist.h | 4 ++-- acl.h => include/qemu/acl.h | 2 +- qemu-barrier.h => include/qemu/atomic.h | 2 +- bitmap.h => include/qemu/bitmap.h | 2 +- bitops.h => include/qemu/bitops.h | 0 bswap.h => include/qemu/bswap.h | 0 cache-utils.h => include/qemu/cache-utils.h | 0 compatfd.h => include/qemu/compatfd.h | 0 compiler.h => include/qemu/compiler.h | 0 qemu-config.h => include/qemu/config-file.h | 4 ++-- envlist.h => include/qemu/envlist.h | 0 qemu-error.h => include/qemu/error-report.h | 0 .../qemu/event_notifier.h | 0 host-utils.h => include/qemu/host-utils.h | 2 +- int128.h => include/qemu/int128.h | 0 iov.h => include/qemu/iov.h | 0 qemu-log.h => include/qemu/log.h | 0 main-loop.h => include/qemu/main-loop.h | 0 module.h => include/qemu/module.h | 0 notify.h => include/qemu/notify.h | 2 +- qemu-option.h => include/qemu/option.h | 2 +- .../qemu/option_int.h | 4 ++-- osdep.h => include/qemu/osdep.h | 0 qemu-queue.h => include/qemu/queue.h | 2 +- range.h => include/qemu/range.h | 0 qemu_socket.h => include/qemu/sockets.h | 2 +- .../qemu/thread-posix.h | 0 .../qemu/thread-win32.h | 0 qemu-thread.h => include/qemu/thread.h | 4 ++-- qemu-timer.h => include/qemu/timer.h | 4 ++-- qemu-tls.h => include/qemu/tls.h | 0 qemu-types.h => include/qemu/typedefs.h | 0 uri.h => include/qemu/uri.h | 0 qemu-xattr.h => include/qemu/xattr.h | 0 include/qom/cpu.h | 2 +- include/qom/object.h | 2 +- include/ui/console.h | 2 +- include/ui/qemu-spice.h | 4 ++-- include/ui/spice-display.h | 2 +- iohandler.c | 4 ++-- iov.c | 2 +- kvm-all.c | 10 +++++----- kvm.h | 2 +- libcacard/event.c | 2 +- libcacard/vreader.c | 2 +- libcacard/vscclient.c | 4 ++-- libfdt_env.h | 2 +- linux-user/main.c | 6 +++--- linux-user/qemu.h | 4 ++-- linux-user/syscall.c | 2 +- main-loop.c | 6 +++--- memory.c | 2 +- memory_mapping.h | 2 +- migration-exec.c | 2 +- migration-fd.c | 4 ++-- migration-tcp.c | 2 +- migration-unix.c | 2 +- migration.c | 2 +- module.c | 4 ++-- monitor.c | 8 ++++---- nbd.c | 4 ++-- net/dump.c | 6 +++--- net/hub.c | 2 +- net/net.c | 6 +++--- net/queue.c | 2 +- net/slirp.c | 2 +- net/socket.c | 8 ++++---- net/tap-bsd.c | 2 +- net/tap-linux.c | 2 +- net/tap-solaris.c | 2 +- net/tap-win32.c | 2 +- net/tap.c | 2 +- net/vde.c | 2 +- notify.c | 2 +- osdep.c | 2 +- oslib-posix.c | 2 +- oslib-win32.c | 4 ++-- qapi/opts-visitor.c | 4 ++-- qapi/qapi-dealloc-visitor.c | 2 +- qapi/qmp-input-visitor.c | 2 +- qapi/qmp-output-visitor.c | 2 +- qdict.c | 2 +- qemu-bridge-helper.c | 2 +- qemu-char.c | 4 ++-- qemu-char.h | 8 ++++---- qemu-common.h | 10 +++++----- qemu-config.c | 6 +++--- qemu-coroutine-io.c | 4 ++-- qemu-coroutine-lock.c | 2 +- qemu-coroutine-sleep.c | 2 +- qemu-img.c | 6 +++--- qemu-io.c | 2 +- qemu-log.c | 2 +- qemu-option.c | 4 ++-- qemu-progress.c | 2 +- qemu-seccomp.h | 2 +- qemu-sockets.c | 4 ++-- qemu-thread-posix.c | 2 +- qemu-thread-win32.c | 2 +- qemu-timer-common.c | 2 +- qemu-timer.c | 4 ++-- qemu-tool.c | 8 ++++---- qga/channel-posix.c | 4 ++-- qga/commands-posix.c | 4 ++-- qga/main.c | 2 +- qlist.c | 2 +- qom/container.c | 2 +- savevm.c | 10 +++++----- scripts/qapi-commands.py | 2 +- slirp/if.c | 2 +- slirp/ip_input.c | 2 +- slirp/sbuf.c | 2 +- slirp/slirp.c | 2 +- slirp/slirp.h | 4 ++-- spice-qemu-char.c | 2 +- stubs/fd-register.c | 2 +- stubs/set-fd-handler.c | 2 +- sysemu.h | 12 ++++++------ target-alpha/int_helper.c | 2 +- target-alpha/sys_helper.c | 2 +- target-alpha/translate.c | 2 +- target-arm/helper.c | 4 ++-- target-arm/translate.c | 2 +- target-cris/helper.c | 2 +- target-cris/op_helper.c | 2 +- target-i386/cpu.c | 4 ++-- target-i386/excp_helper.c | 2 +- target-i386/int_helper.c | 2 +- target-i386/kvm.c | 4 ++-- target-i386/seg_helper.c | 2 +- target-lm32/helper.c | 2 +- target-lm32/op_helper.c | 2 +- target-m68k/translate.c | 2 +- target-microblaze/helper.c | 2 +- target-microblaze/op_helper.c | 2 +- target-mips/op_helper.c | 2 +- target-openrisc/int_helper.c | 2 +- target-openrisc/interrupt.c | 2 +- target-openrisc/mmu.c | 2 +- target-openrisc/translate.c | 4 ++-- target-ppc/int_helper.c | 2 +- target-ppc/kvm.c | 2 +- target-ppc/kvm_ppc.c | 2 +- target-ppc/mem_helper.c | 2 +- target-ppc/translate.c | 2 +- target-s390x/cpu.c | 2 +- target-s390x/helper.c | 2 +- target-s390x/int_helper.c | 2 +- target-s390x/kvm.c | 2 +- target-s390x/misc_helper.c | 4 ++-- target-s390x/translate.c | 2 +- target-sparc/cpu.h | 2 +- target-sparc/helper.c | 2 +- target-sparc/machine.c | 2 +- target-unicore32/helper.c | 2 +- target-unicore32/translate.c | 2 +- target-xtensa/core-dc232b.c | 2 +- target-xtensa/core-dc233c.c | 2 +- target-xtensa/core-fsf.c | 2 +- target-xtensa/helper.c | 2 +- target-xtensa/op_helper.c | 2 +- target-xtensa/translate.c | 2 +- target-xtensa/xtensa-semi.c | 2 +- tcg/tcg.c | 6 +++--- tests/libqtest.c | 4 ++-- tests/tcg/test-i386-fprem.c | 4 ++-- tests/tcg/test-i386.c | 2 +- tests/test-iov.c | 4 ++-- tests/test-qmp-commands.c | 2 +- thread-pool.c | 8 ++++---- trace/simple.c | 2 +- translate-all.c | 2 +- ui/console.c | 2 +- ui/sdl_zoom.c | 2 +- ui/spice-core.c | 10 +++++----- ui/spice-display.c | 4 ++-- ui/vnc-auth-sasl.h | 2 +- ui/vnc-enc-tight.c | 2 +- ui/vnc-jobs.c | 2 +- ui/vnc-palette.h | 2 +- ui/vnc-tls.c | 2 +- ui/vnc-tls.h | 2 +- ui/vnc.c | 8 ++++---- ui/vnc.h | 6 +++--- uri.c | 2 +- vl.c | 18 +++++++++--------- xen-all.c | 2 +- xen-mapcache.c | 2 +- 496 files changed, 673 insertions(+), 673 deletions(-) rename acl.h => include/qemu/acl.h (98%) rename qemu-barrier.h => include/qemu/atomic.h (96%) rename bitmap.h => include/qemu/bitmap.h (99%) rename bitops.h => include/qemu/bitops.h (100%) rename bswap.h => include/qemu/bswap.h (100%) rename cache-utils.h => include/qemu/cache-utils.h (100%) rename compatfd.h => include/qemu/compatfd.h (100%) rename compiler.h => include/qemu/compiler.h (100%) rename qemu-config.h => include/qemu/config-file.h (94%) rename envlist.h => include/qemu/envlist.h (100%) rename qemu-error.h => include/qemu/error-report.h (100%) rename event_notifier.h => include/qemu/event_notifier.h (100%) rename host-utils.h => include/qemu/host-utils.h (99%) rename int128.h => include/qemu/int128.h (100%) rename iov.h => include/qemu/iov.h (100%) rename qemu-log.h => include/qemu/log.h (100%) rename main-loop.h => include/qemu/main-loop.h (100%) rename module.h => include/qemu/module.h (100%) rename notify.h => include/qemu/notify.h (97%) rename qemu-option.h => include/qemu/option.h (99%) rename qemu-option-internal.h => include/qemu/option_int.h (96%) rename osdep.h => include/qemu/osdep.h (100%) rename qemu-queue.h => include/qemu/queue.h (99%) rename range.h => include/qemu/range.h (100%) rename qemu_socket.h => include/qemu/sockets.h (99%) rename qemu-thread-posix.h => include/qemu/thread-posix.h (100%) rename qemu-thread-win32.h => include/qemu/thread-win32.h (100%) rename qemu-thread.h => include/qemu/thread.h (96%) rename qemu-timer.h => include/qemu/timer.h (99%) rename qemu-tls.h => include/qemu/tls.h (100%) rename qemu-types.h => include/qemu/typedefs.h (100%) rename uri.h => include/qemu/uri.h (100%) rename qemu-xattr.h => include/qemu/xattr.h (100%) diff --git a/acl.c b/acl.c index e840b9b633..81ac25599b 100644 --- a/acl.c +++ b/acl.c @@ -24,7 +24,7 @@ #include "qemu-common.h" -#include "acl.h" +#include "qemu/acl.h" #ifdef CONFIG_FNMATCH #include diff --git a/aio-posix.c b/aio-posix.c index d1e1bc2c75..88d09e1cfb 100644 --- a/aio-posix.c +++ b/aio-posix.c @@ -15,8 +15,8 @@ #include "qemu-common.h" #include "block/block.h" -#include "qemu-queue.h" -#include "qemu_socket.h" +#include "qemu/queue.h" +#include "qemu/sockets.h" struct AioHandler { diff --git a/aio-win32.c b/aio-win32.c index 9a26f9c3d9..f5ea027f8c 100644 --- a/aio-win32.c +++ b/aio-win32.c @@ -17,8 +17,8 @@ #include "qemu-common.h" #include "block/block.h" -#include "qemu-queue.h" -#include "qemu_socket.h" +#include "qemu/queue.h" +#include "qemu/sockets.h" struct AioHandler { EventNotifier *e; diff --git a/arch_init.c b/arch_init.c index f627253a20..9dacf5689b 100644 --- a/arch_init.c +++ b/arch_init.c @@ -31,8 +31,8 @@ #include "config.h" #include "monitor/monitor.h" #include "sysemu.h" -#include "bitops.h" -#include "bitmap.h" +#include "qemu/bitops.h" +#include "qemu/bitmap.h" #include "arch_init.h" #include "audio/audio.h" #include "hw/pc.h" @@ -45,7 +45,7 @@ #include "exec/address-spaces.h" #include "hw/pcspk.h" #include "migration/page_cache.h" -#include "qemu-config.h" +#include "qemu/config-file.h" #include "qmp-commands.h" #include "trace.h" diff --git a/async.c b/async.c index 6df4caf68a..72d268ae35 100644 --- a/async.c +++ b/async.c @@ -24,7 +24,7 @@ #include "qemu-common.h" #include "block/aio.h" -#include "main-loop.h" +#include "qemu/main-loop.h" /***********************************************************/ /* bottom halves (can be seen as timers which expire ASAP) */ diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index cd553c2a7b..e4e5442631 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -23,7 +23,7 @@ */ #include #include "qemu-common.h" -#include "main-loop.h" +#include "qemu/main-loop.h" #include "audio.h" #if QEMU_GNUC_PREREQ(4, 3) diff --git a/audio/audio.c b/audio/audio.c index a0cc727020..eb2222c10f 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -24,7 +24,7 @@ #include "hw/hw.h" #include "audio.h" #include "monitor/monitor.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysemu.h" #define AUDIO_CAP "audio" diff --git a/audio/audio.h b/audio/audio.h index a70fda97e3..e7ea39777e 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -25,7 +25,7 @@ #define QEMU_AUDIO_H #include "config-host.h" -#include "qemu-queue.h" +#include "qemu/queue.h" typedef void (*audio_callback_fn) (void *opaque, int avail); diff --git a/audio/noaudio.c b/audio/noaudio.c index 54958f8623..9f23aa2cb3 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -23,7 +23,7 @@ */ #include "qemu-common.h" #include "audio.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #define AUDIO_CAP "noaudio" #include "audio_int.h" diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 8249a00449..00be9c91e3 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -31,8 +31,8 @@ #include #endif #include "qemu-common.h" -#include "main-loop.h" -#include "host-utils.h" +#include "qemu/main-loop.h" +#include "qemu/host-utils.h" #include "audio.h" #define AUDIO_CAP "oss" diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index 6f15591a74..bc24557de4 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -18,7 +18,7 @@ */ #include "hw/hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ui/qemu-spice.h" #define AUDIO_CAP "spice" diff --git a/audio/wavaudio.c b/audio/wavaudio.c index a449b5127e..950fa8f19c 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "hw/hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "audio.h" #define AUDIO_CAP "wav" diff --git a/backends/rng-random.c b/backends/rng-random.c index c201953f29..d479ce8c56 100644 --- a/backends/rng-random.c +++ b/backends/rng-random.c @@ -13,7 +13,7 @@ #include "qemu/rng-random.h" #include "qemu/rng.h" #include "qapi/qmp/qerror.h" -#include "main-loop.h" +#include "qemu/main-loop.h" struct RndRandom { diff --git a/bitmap.c b/bitmap.c index a62c8ba681..687841dcec 100644 --- a/bitmap.c +++ b/bitmap.c @@ -9,8 +9,8 @@ * Version 2. */ -#include "bitops.h" -#include "bitmap.h" +#include "qemu/bitops.h" +#include "qemu/bitmap.h" /* * bitmaps provide an array of bits, implemented using an an diff --git a/bitops.c b/bitops.c index d9de71f7e8..4c3a836a01 100644 --- a/bitops.c +++ b/bitops.c @@ -11,7 +11,7 @@ * 2 of the License, or (at your option) any later version. */ -#include "bitops.h" +#include "qemu/bitops.h" #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) diff --git a/block-migration.c b/block-migration.c index 2d2dcbda94..4e865a6781 100644 --- a/block-migration.c +++ b/block-migration.c @@ -16,8 +16,8 @@ #include "qemu-common.h" #include "block/block_int.h" #include "hw/hw.h" -#include "qemu-queue.h" -#include "qemu-timer.h" +#include "qemu/queue.h" +#include "qemu/timer.h" #include "migration/block.h" #include "migration/migration.h" #include "blockdev.h" diff --git a/block.c b/block.c index 0e7f18c6d3..1af4b99ee8 100644 --- a/block.c +++ b/block.c @@ -27,13 +27,13 @@ #include "monitor/monitor.h" #include "block/block_int.h" #include "block/blockjob.h" -#include "module.h" +#include "qemu/module.h" #include "qapi/qmp/qjson.h" #include "sysemu.h" -#include "notify.h" +#include "qemu/notify.h" #include "block/coroutine.h" #include "qmp-commands.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #ifdef CONFIG_BSD #include diff --git a/block/blkdebug.c b/block/blkdebug.c index cd2866e7bd..6f7463772b 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -23,9 +23,9 @@ */ #include "qemu-common.h" -#include "qemu-config.h" +#include "qemu/config-file.h" #include "block/block_int.h" -#include "module.h" +#include "qemu/module.h" typedef struct BDRVBlkdebugState { int state; diff --git a/block/blkverify.c b/block/blkverify.c index cde5098e5a..a7dd45909b 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -8,7 +8,7 @@ */ #include -#include "qemu_socket.h" /* for EINPROGRESS on Windows */ +#include "qemu/sockets.h" /* for EINPROGRESS on Windows */ #include "block/block_int.h" typedef struct { diff --git a/block/bochs.c b/block/bochs.c index 2cc7524782..1b1d9cdbe5 100644 --- a/block/bochs.c +++ b/block/bochs.c @@ -24,7 +24,7 @@ */ #include "qemu-common.h" #include "block/block_int.h" -#include "module.h" +#include "qemu/module.h" /**************************************************************/ diff --git a/block/cloop.c b/block/cloop.c index da29ff379c..5a0d0d805f 100644 --- a/block/cloop.c +++ b/block/cloop.c @@ -23,7 +23,7 @@ */ #include "qemu-common.h" #include "block/block_int.h" -#include "module.h" +#include "qemu/module.h" #include typedef struct BDRVCloopState { diff --git a/block/cow.c b/block/cow.c index 1438ae1e3b..a33ce950d4 100644 --- a/block/cow.c +++ b/block/cow.c @@ -23,7 +23,7 @@ */ #include "qemu-common.h" #include "block/block_int.h" -#include "module.h" +#include "qemu/module.h" /**************************************************************/ /* COW block driver using file system holes */ diff --git a/block/dmg.c b/block/dmg.c index 6ee505a9f5..ac397dc8f7 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -23,8 +23,8 @@ */ #include "qemu-common.h" #include "block/block_int.h" -#include "bswap.h" -#include "module.h" +#include "qemu/bswap.h" +#include "qemu/module.h" #include typedef struct BDRVDMGState { diff --git a/block/gluster.c b/block/gluster.c index 4cb4e60227..0f2c32a3fa 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -17,8 +17,8 @@ */ #include #include "block/block_int.h" -#include "qemu_socket.h" -#include "uri.h" +#include "qemu/sockets.h" +#include "qemu/uri.h" typedef struct GlusterAIOCB { BlockDriverAIOCB common; diff --git a/block/iscsi.c b/block/iscsi.c index 77e619a1fd..041ee07de3 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -27,8 +27,8 @@ #include #include #include "qemu-common.h" -#include "qemu-config.h" -#include "qemu-error.h" +#include "qemu/config-file.h" +#include "qemu/error-report.h" #include "block/block_int.h" #include "trace.h" #include "hw/scsi-defs.h" diff --git a/block/linux-aio.c b/block/linux-aio.c index 28e5a04e12..ee0f8d10c9 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -9,9 +9,9 @@ */ #include "qemu-common.h" #include "block/aio.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #include "block/raw-aio.h" -#include "event_notifier.h" +#include "qemu/event_notifier.h" #include diff --git a/block/nbd.c b/block/nbd.c index 38d6b90ab2..a5812948d2 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -28,10 +28,10 @@ #include "qemu-common.h" #include "block/nbd.h" -#include "uri.h" +#include "qemu/uri.h" #include "block/block_int.h" -#include "module.h" -#include "qemu_socket.h" +#include "qemu/module.h" +#include "qemu/sockets.h" #include #include diff --git a/block/parallels.c b/block/parallels.c index ae88cd6359..377375046f 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -25,7 +25,7 @@ */ #include "qemu-common.h" #include "block/block_int.h" -#include "module.h" +#include "qemu/module.h" /**************************************************************/ diff --git a/block/qcow.c b/block/qcow.c index f36671196e..4276610afd 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -23,7 +23,7 @@ */ #include "qemu-common.h" #include "block/block_int.h" -#include "module.h" +#include "qemu/module.h" #include #include "block/aes.h" #include "migration/migration.h" diff --git a/block/qcow2.c b/block/qcow2.c index 205d910a52..d603f98a9c 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -23,11 +23,11 @@ */ #include "qemu-common.h" #include "block/block_int.h" -#include "module.h" +#include "qemu/module.h" #include #include "block/aes.h" #include "block/qcow2.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "qapi/qmp/qerror.h" #include "trace.h" diff --git a/block/qed-table.c b/block/qed-table.c index de845ec3d0..76d2dcccf8 100644 --- a/block/qed-table.c +++ b/block/qed-table.c @@ -13,7 +13,7 @@ */ #include "trace.h" -#include "qemu_socket.h" /* for EINPROGRESS on Windows */ +#include "qemu/sockets.h" /* for EINPROGRESS on Windows */ #include "qed.h" typedef struct { diff --git a/block/qed.c b/block/qed.c index 10d0827482..cf85d8f2b4 100644 --- a/block/qed.c +++ b/block/qed.c @@ -12,7 +12,7 @@ * */ -#include "qemu-timer.h" +#include "qemu/timer.h" #include "trace.h" #include "qed.h" #include "qapi/qmp/qerror.h" diff --git a/block/raw-posix.c b/block/raw-posix.c index 4e73885269..91159c7887 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -22,13 +22,13 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "qemu-timer.h" -#include "qemu-log.h" +#include "qemu/timer.h" +#include "qemu/log.h" #include "block/block_int.h" -#include "module.h" +#include "qemu/module.h" #include "trace.h" #include "block/thread-pool.h" -#include "iov.h" +#include "qemu/iov.h" #include "raw-aio.h" #if defined(__APPLE__) && (__MACH__) diff --git a/block/raw-win32.c b/block/raw-win32.c index 9269fe84c0..f58334be08 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -22,13 +22,13 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "block/block_int.h" -#include "module.h" +#include "qemu/module.h" #include "raw-aio.h" #include "trace.h" #include "block/thread-pool.h" -#include "iov.h" +#include "qemu/iov.h" #include #include diff --git a/block/raw.c b/block/raw.c index 6aec93dadb..75812db3c2 100644 --- a/block/raw.c +++ b/block/raw.c @@ -1,7 +1,7 @@ #include "qemu-common.h" #include "block/block_int.h" -#include "module.h" +#include "qemu/module.h" static int raw_open(BlockDriverState *bs, int flags) { diff --git a/block/rbd.c b/block/rbd.c index 8def2f174c..8cd10a7b59 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -14,7 +14,7 @@ #include #include "qemu-common.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "block/block_int.h" #include diff --git a/block/sheepdog.c b/block/sheepdog.c index da70df2d00..13dc023fdb 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -13,10 +13,10 @@ */ #include "qemu-common.h" -#include "qemu-error.h" -#include "qemu_socket.h" +#include "qemu/error-report.h" +#include "qemu/sockets.h" #include "block/block_int.h" -#include "bitops.h" +#include "qemu/bitops.h" #define SD_PROTO_VER 0x01 diff --git a/block/vdi.c b/block/vdi.c index b1d199a2e5..7b6231941b 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -51,7 +51,7 @@ #include "qemu-common.h" #include "block/block_int.h" -#include "module.h" +#include "qemu/module.h" #include "migration/migration.h" #if defined(CONFIG_UUID) diff --git a/block/vmdk.c b/block/vmdk.c index 77a1a67c61..19298c2a3e 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -25,7 +25,7 @@ #include "qemu-common.h" #include "block/block_int.h" -#include "module.h" +#include "qemu/module.h" #include "migration/migration.h" #include diff --git a/block/vpc.c b/block/vpc.c index 47b5518aee..7948609e50 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -24,7 +24,7 @@ */ #include "qemu-common.h" #include "block/block_int.h" -#include "module.h" +#include "qemu/module.h" #include "migration/migration.h" #if defined(CONFIG_UUID) #include diff --git a/block/vvfat.c b/block/vvfat.c index a63c3ea7cd..83706ce556 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -26,7 +26,7 @@ #include #include "qemu-common.h" #include "block/block_int.h" -#include "module.h" +#include "qemu/module.h" #include "migration/migration.h" #ifndef S_IWGRP diff --git a/block/win32-aio.c b/block/win32-aio.c index 606e4d6925..46a5db78cc 100644 --- a/block/win32-aio.c +++ b/block/win32-aio.c @@ -22,13 +22,13 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "block/block_int.h" -#include "module.h" +#include "qemu/module.h" #include "qemu-common.h" #include "block/aio.h" #include "raw-aio.h" -#include "event_notifier.h" +#include "qemu/event_notifier.h" #include #include diff --git a/blockdev-nbd.c b/blockdev-nbd.c index 596b47499d..95b621699a 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -17,7 +17,7 @@ #include "qmp-commands.h" #include "trace.h" #include "block/nbd.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" static int server_fd = -1; diff --git a/blockdev.c b/blockdev.c index a2308fa718..3ebff44310 100644 --- a/blockdev.c +++ b/blockdev.c @@ -12,8 +12,8 @@ #include "block/blockjob.h" #include "monitor/monitor.h" #include "qapi/qmp/qerror.h" -#include "qemu-option.h" -#include "qemu-config.h" +#include "qemu/option.h" +#include "qemu/config-file.h" #include "qapi/qmp/types.h" #include "sysemu.h" #include "block/block_int.h" diff --git a/blockdev.h b/blockdev.h index 4134864758..1fe533299e 100644 --- a/blockdev.h +++ b/blockdev.h @@ -12,7 +12,7 @@ #include "block/block.h" #include "qapi/error.h" -#include "qemu-queue.h" +#include "qemu/queue.h" void blockdev_mark_auto_del(BlockDriverState *bs); void blockdev_auto_del(BlockDriverState *bs); diff --git a/blockjob.c b/blockjob.c index 4bc60c7378..ca80df1d0e 100644 --- a/blockjob.c +++ b/blockjob.c @@ -33,7 +33,7 @@ #include "qapi/qmp/qjson.h" #include "block/coroutine.h" #include "qmp-commands.h" -#include "qemu-timer.h" +#include "qemu/timer.h" void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs, int64_t speed, BlockDriverCompletionFunc *cb, diff --git a/bsd-user/main.c b/bsd-user/main.c index 095ae8eaaa..1dc033046b 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -31,8 +31,8 @@ /* For tb_lock */ #include "cpu.h" #include "tcg.h" -#include "qemu-timer.h" -#include "envlist.h" +#include "qemu/timer.h" +#include "qemu/envlist.h" #define DEBUG_LOGFILE "/tmp/qemu.log" diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h index c64c3ccca3..a826086dab 100644 --- a/bsd-user/qemu.h +++ b/bsd-user/qemu.h @@ -146,7 +146,7 @@ int get_osversion(void); void fork_start(void); void fork_end(int child); -#include "qemu-log.h" +#include "qemu/log.h" /* strace.c */ void diff --git a/bt-host.c b/bt-host.c index 65aaca337c..4f5f9f93c5 100644 --- a/bt-host.c +++ b/bt-host.c @@ -19,7 +19,7 @@ #include "qemu-common.h" #include "bt-host.h" -#include "main-loop.h" +#include "qemu/main-loop.h" #ifndef _WIN32 # include diff --git a/bt-vhci.c b/bt-vhci.c index 13c0e53729..f5d856a809 100644 --- a/bt-vhci.c +++ b/bt-vhci.c @@ -20,7 +20,7 @@ #include "qemu-common.h" #include "bt-host.h" #include "hw/bt.h" -#include "main-loop.h" +#include "qemu/main-loop.h" #define VHCI_DEV "/dev/vhci" #define VHCI_UDEV "/dev/hci_vhci" diff --git a/buffered_file.c b/buffered_file.c index f13443ee91..27627a1b71 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -15,7 +15,7 @@ #include "qemu-common.h" #include "hw/hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "buffered_file.h" //#define DEBUG_BUFFERED_FILE diff --git a/cache-utils.c b/cache-utils.c index 2db5af2db1..b94013a8cb 100644 --- a/cache-utils.c +++ b/cache-utils.c @@ -1,4 +1,4 @@ -#include "cache-utils.h" +#include "qemu/cache-utils.h" #if defined(_ARCH_PPC) struct qemu_cache_conf qemu_cache_conf = { diff --git a/cmd.c b/cmd.c index 01a8c3a299..10a8688b2d 100644 --- a/cmd.c +++ b/cmd.c @@ -25,7 +25,7 @@ #include "cmd.h" #include "block/aio.h" -#include "main-loop.h" +#include "qemu/main-loop.h" #define _(x) x /* not gettext support yet */ diff --git a/compatfd.c b/compatfd.c index 42f81cafe4..9cf3f2834d 100644 --- a/compatfd.c +++ b/compatfd.c @@ -14,7 +14,7 @@ */ #include "qemu-common.h" -#include "compatfd.h" +#include "qemu/compatfd.h" #include #include diff --git a/cpu-exec.c b/cpu-exec.c index b5a32b84e4..54e62ed551 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -20,7 +20,7 @@ #include "cpu.h" #include "disas/disas.h" #include "tcg.h" -#include "qemu-barrier.h" +#include "qemu/atomic.h" #include "qtest.h" int tb_invalidated_flag; diff --git a/cpus.c b/cpus.c index 3a66401e0d..036418d62c 100644 --- a/cpus.c +++ b/cpus.c @@ -32,14 +32,14 @@ #include "kvm.h" #include "qmp-commands.h" -#include "qemu-thread.h" +#include "qemu/thread.h" #include "cpus.h" #include "qtest.h" -#include "main-loop.h" -#include "bitmap.h" +#include "qemu/main-loop.h" +#include "qemu/bitmap.h" #ifndef _WIN32 -#include "compatfd.h" +#include "qemu/compatfd.h" #endif #ifdef CONFIG_LINUX diff --git a/cutils.c b/cutils.c index 4f0692f78e..d06590b330 100644 --- a/cutils.c +++ b/cutils.c @@ -22,11 +22,11 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include -#include "qemu_socket.h" -#include "iov.h" +#include "qemu/sockets.h" +#include "qemu/iov.h" void strpadcpy(char *buf, int buf_size, const char *str, char pad) { diff --git a/device_tree.c b/device_tree.c index a9236133c7..c3e1ba4904 100644 --- a/device_tree.c +++ b/device_tree.c @@ -22,8 +22,8 @@ #include "qemu-common.h" #include "device_tree.h" #include "hw/loader.h" -#include "qemu-option.h" -#include "qemu-config.h" +#include "qemu/option.h" +#include "qemu/config-file.h" #include diff --git a/dma-helpers.c b/dma-helpers.c index 4f5fb649e7..e6a6dd82fd 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -9,8 +9,8 @@ #include "dma.h" #include "trace.h" -#include "range.h" -#include "qemu-thread.h" +#include "qemu/range.h" +#include "qemu/thread.h" /* #define DEBUG_IOMMU */ diff --git a/envlist.c b/envlist.c index f2303cdd79..ff99fc44e9 100644 --- a/envlist.c +++ b/envlist.c @@ -4,8 +4,8 @@ #include #include -#include "qemu-queue.h" -#include "envlist.h" +#include "qemu/queue.h" +#include "qemu/envlist.h" struct envlist_entry { const char *ev_var; /* actual env value */ diff --git a/event_notifier-posix.c b/event_notifier-posix.c index f0bd839acd..a53b95688d 100644 --- a/event_notifier-posix.c +++ b/event_notifier-posix.c @@ -11,9 +11,9 @@ */ #include "qemu-common.h" -#include "event_notifier.h" +#include "qemu/event_notifier.h" #include "qemu-char.h" -#include "main-loop.h" +#include "qemu/main-loop.h" #ifdef CONFIG_EVENTFD #include diff --git a/event_notifier-win32.c b/event_notifier-win32.c index 4ed21c2a7c..6dbb530cfa 100644 --- a/event_notifier-win32.c +++ b/event_notifier-win32.c @@ -11,8 +11,8 @@ */ #include "qemu-common.h" -#include "event_notifier.h" -#include "main-loop.h" +#include "qemu/event_notifier.h" +#include "qemu/main-loop.h" int event_notifier_init(EventNotifier *e, int active) { diff --git a/exec.c b/exec.c index 17fc7cf854..917bec0ecd 100644 --- a/exec.c +++ b/exec.c @@ -29,11 +29,11 @@ #include "tcg.h" #include "hw/hw.h" #include "hw/qdev.h" -#include "osdep.h" +#include "qemu/osdep.h" #include "kvm.h" #include "hw/xen.h" -#include "qemu-timer.h" -#include "qemu-config.h" +#include "qemu/timer.h" +#include "qemu/config-file.h" #include "exec/memory.h" #include "dma.h" #include "exec/address-spaces.h" diff --git a/fpu/softfloat.h b/fpu/softfloat.h index d8999b311a..0946f0739d 100644 --- a/fpu/softfloat.h +++ b/fpu/softfloat.h @@ -44,7 +44,7 @@ these four paragraphs for those parts of this code that are retained. #include #include "config-host.h" -#include "osdep.h" +#include "qemu/osdep.h" /*---------------------------------------------------------------------------- | Each of the following `typedef's defines the most convenient type that holds diff --git a/fsdev/qemu-fsdev-dummy.c b/fsdev/qemu-fsdev-dummy.c index 300f2758be..4bcf38fe4b 100644 --- a/fsdev/qemu-fsdev-dummy.c +++ b/fsdev/qemu-fsdev-dummy.c @@ -13,8 +13,8 @@ #include #include #include "qemu-fsdev.h" -#include "qemu-config.h" -#include "module.h" +#include "qemu/config-file.h" +#include "qemu/module.h" int qemu_fsdev_add(QemuOpts *opts) { diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c index e20202a4bf..4cc04d4fde 100644 --- a/fsdev/qemu-fsdev.c +++ b/fsdev/qemu-fsdev.c @@ -13,10 +13,10 @@ #include #include #include "qemu-fsdev.h" -#include "qemu-queue.h" -#include "osdep.h" +#include "qemu/queue.h" +#include "qemu/osdep.h" #include "qemu-common.h" -#include "qemu-config.h" +#include "qemu/config-file.h" static QTAILQ_HEAD(FsDriverEntry_head, FsDriverListEntry) fsdriver_entries = QTAILQ_HEAD_INITIALIZER(fsdriver_entries); diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h index 1af1f545d8..9fa45bf510 100644 --- a/fsdev/qemu-fsdev.h +++ b/fsdev/qemu-fsdev.h @@ -12,7 +12,7 @@ */ #ifndef QEMU_FSDEV_H #define QEMU_FSDEV_H -#include "qemu-option.h" +#include "qemu/option.h" #include "file-op-9p.h" diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c index df2a9392b1..6b9afd32d5 100644 --- a/fsdev/virtfs-proxy-helper.c +++ b/fsdev/virtfs-proxy-helper.c @@ -21,8 +21,8 @@ #include #endif #include "qemu-common.h" -#include "qemu_socket.h" -#include "qemu-xattr.h" +#include "qemu/sockets.h" +#include "qemu/xattr.h" #include "virtio-9p-marshal.h" #include "hw/9pfs/virtio-9p-proxy.h" #include "fsdev/virtio-9p-marshal.h" diff --git a/fsdev/virtio-9p-marshal.c b/fsdev/virtio-9p-marshal.c index bf980bfa38..20f308b760 100644 --- a/fsdev/virtio-9p-marshal.c +++ b/fsdev/virtio-9p-marshal.c @@ -22,9 +22,9 @@ #include #include -#include "compiler.h" +#include "qemu/compiler.h" #include "virtio-9p-marshal.h" -#include "bswap.h" +#include "qemu/bswap.h" void v9fs_string_free(V9fsString *str) { diff --git a/gdbstub.c b/gdbstub.c index 9395c829a2..4b178a608f 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -38,7 +38,7 @@ #define MAX_PACKET_LENGTH 4096 #include "cpu.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "kvm.h" #ifndef TARGET_CPU_MEMORY_RW_DEBUG diff --git a/hmp.c b/hmp.c index a76a8f06ea..3d056b0e38 100644 --- a/hmp.c +++ b/hmp.c @@ -16,10 +16,10 @@ #include "hmp.h" #include "net/net.h" #include "qemu-char.h" -#include "qemu-option.h" -#include "qemu-timer.h" +#include "qemu/option.h" +#include "qemu/timer.h" #include "qmp-commands.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "monitor/monitor.h" #include "ui/console.h" diff --git a/host-utils.c b/host-utils.c index dc9612387b..5e3915abba 100644 --- a/host-utils.c +++ b/host-utils.c @@ -25,7 +25,7 @@ #include #include -#include "host-utils.h" +#include "qemu/host-utils.h" //#define DEBUG_MULDIV diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c index cd137330b9..65ad3298be 100644 --- a/hw/9pfs/codir.c +++ b/hw/9pfs/codir.c @@ -13,7 +13,7 @@ */ #include "fsdev/qemu-fsdev.h" -#include "qemu-thread.h" +#include "qemu/thread.h" #include "block/coroutine.h" #include "virtio-9p-coth.h" diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c index 6d6dac7abf..2efebf3571 100644 --- a/hw/9pfs/cofile.c +++ b/hw/9pfs/cofile.c @@ -13,7 +13,7 @@ */ #include "fsdev/qemu-fsdev.h" -#include "qemu-thread.h" +#include "qemu/thread.h" #include "block/coroutine.h" #include "virtio-9p-coth.h" diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c index 4b9ba30157..3891050748 100644 --- a/hw/9pfs/cofs.c +++ b/hw/9pfs/cofs.c @@ -13,7 +13,7 @@ */ #include "fsdev/qemu-fsdev.h" -#include "qemu-thread.h" +#include "qemu/thread.h" #include "block/coroutine.h" #include "virtio-9p-coth.h" diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c index 08365a697e..18ee08df0f 100644 --- a/hw/9pfs/coxattr.c +++ b/hw/9pfs/coxattr.c @@ -13,7 +13,7 @@ */ #include "fsdev/qemu-fsdev.h" -#include "qemu-thread.h" +#include "qemu/thread.h" #include "block/coroutine.h" #include "virtio-9p-coth.h" diff --git a/hw/9pfs/virtio-9p-coth.c b/hw/9pfs/virtio-9p-coth.c index 958725e5cc..ae6cde8005 100644 --- a/hw/9pfs/virtio-9p-coth.c +++ b/hw/9pfs/virtio-9p-coth.c @@ -13,7 +13,7 @@ */ #include "fsdev/qemu-fsdev.h" -#include "qemu-thread.h" +#include "qemu/thread.h" #include "block/coroutine.h" #include "virtio-9p-coth.h" diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index 8c48a16c10..86d5ed4169 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -15,7 +15,7 @@ #ifndef _QEMU_VIRTIO_9P_COTH_H #define _QEMU_VIRTIO_9P_COTH_H -#include "qemu-thread.h" +#include "qemu/thread.h" #include "block/coroutine.h" #include "virtio-9p.h" #include diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index b8220abae7..6761bce9dc 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -13,7 +13,7 @@ #include "hw/virtio.h" #include "hw/pc.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "hw/virtio-pci.h" #include "virtio-9p.h" #include "fsdev/qemu-fsdev.h" diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c index f96d17a974..e30fdb6730 100644 --- a/hw/9pfs/virtio-9p-handle.c +++ b/hw/9pfs/virtio-9p-handle.c @@ -19,7 +19,7 @@ #include #include #include -#include "qemu-xattr.h" +#include "qemu/xattr.h" #include #include #ifdef CONFIG_LINUX_MAGIC_H diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index 33a41d2e18..113602144c 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -19,7 +19,7 @@ #include #include #include -#include "qemu-xattr.h" +#include "qemu/xattr.h" #include #include #ifdef CONFIG_LINUX_MAGIC_H diff --git a/hw/9pfs/virtio-9p-posix-acl.c b/hw/9pfs/virtio-9p-posix-acl.c index c064017b1f..08bb0e8bca 100644 --- a/hw/9pfs/virtio-9p-posix-acl.c +++ b/hw/9pfs/virtio-9p-posix-acl.c @@ -12,7 +12,7 @@ */ #include -#include "qemu-xattr.h" +#include "qemu/xattr.h" #include "hw/virtio.h" #include "virtio-9p.h" #include "fsdev/file-op-9p.h" diff --git a/hw/9pfs/virtio-9p-xattr.h b/hw/9pfs/virtio-9p-xattr.h index 9437280c99..41cc6cbc7b 100644 --- a/hw/9pfs/virtio-9p-xattr.h +++ b/hw/9pfs/virtio-9p-xattr.h @@ -13,7 +13,7 @@ #ifndef _QEMU_VIRTIO_9P_XATTR_H #define _QEMU_VIRTIO_9P_XATTR_H -#include "qemu-xattr.h" +#include "qemu/xattr.h" typedef struct xattr_operations { diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index ede20ce80e..0aaf0d2de0 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -13,7 +13,7 @@ #include "hw/virtio.h" #include "hw/pc.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "hw/virtio-pci.h" #include "virtio-9p.h" #include "fsdev/qemu-fsdev.h" diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 2c0c3baad4..406fe522db 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -9,7 +9,7 @@ #include "hw/virtio.h" #include "fsdev/file-op-9p.h" #include "fsdev/virtio-9p-marshal.h" -#include "qemu-thread.h" +#include "qemu/thread.h" #include "block/coroutine.h" diff --git a/hw/acpi.h b/hw/acpi.h index afda153d09..c3628d070d 100644 --- a/hw/acpi.h +++ b/hw/acpi.h @@ -127,7 +127,7 @@ void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, MemoryRegion *parent); void acpi_pm_tmr_reset(ACPIREGS *ar); -#include "qemu-timer.h" +#include "qemu/timer.h" static inline int64_t acpi_pm_tmr_get_clock(void) { return muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY, diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c index 92af3a554c..8d1a689a36 100644 --- a/hw/acpi_ich9.c +++ b/hw/acpi_ich9.c @@ -26,7 +26,7 @@ #include "hw.h" #include "pc.h" #include "pci/pci.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysemu.h" #include "acpi.h" #include "kvm.h" diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 4f43f6e070..ebd015dc02 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -25,7 +25,7 @@ #include "pci/pci.h" #include "acpi.h" #include "sysemu.h" -#include "range.h" +#include "qemu/range.h" #include "exec/ioport.h" #include "fw_cfg.h" #include "exec/address-spaces.h" diff --git a/hw/adlib.c b/hw/adlib.c index d39cd97384..07c69fc967 100644 --- a/hw/adlib.c +++ b/hw/adlib.c @@ -32,7 +32,7 @@ #define ADLIB_KILL_TIMERS 1 #ifdef DEBUG -#include "qemu-timer.h" +#include "qemu/timer.h" #endif #define dolog(...) AUD_log ("adlib", __VA_ARGS__) diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c index 7e7b1d27d2..78d93e55ec 100644 --- a/hw/alpha_pci.c +++ b/hw/alpha_pci.c @@ -8,7 +8,7 @@ #include "config.h" #include "alpha_sys.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "sysemu.h" diff --git a/hw/apic.c b/hw/apic.c index d66a476aac..81b82f694c 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -16,12 +16,12 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see */ -#include "qemu-thread.h" +#include "qemu/thread.h" #include "apic_internal.h" #include "apic.h" #include "ioapic.h" #include "pci/msi.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "trace.h" #include "pc.h" #include "apic-msidef.h" diff --git a/hw/apic_internal.h b/hw/apic_internal.h index fea95654ca..dcbbfd41cb 100644 --- a/hw/apic_internal.h +++ b/hw/apic_internal.h @@ -22,7 +22,7 @@ #include "exec/memory.h" #include "sysbus.h" -#include "qemu-timer.h" +#include "qemu/timer.h" /* APIC Local Vector Table */ #define APIC_LVT_TIMER 0 diff --git a/hw/applesmc.c b/hw/applesmc.c index 91e7cb3d5c..c564b60c0a 100644 --- a/hw/applesmc.c +++ b/hw/applesmc.c @@ -33,7 +33,7 @@ #include "hw.h" #include "isa.h" #include "ui/console.h" -#include "qemu-timer.h" +#include "qemu/timer.h" /* #define DEBUG_SMC */ diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c index 640ed20a61..093331124a 100644 --- a/hw/arm11mpcore.c +++ b/hw/arm11mpcore.c @@ -8,7 +8,7 @@ */ #include "sysbus.h" -#include "qemu-timer.h" +#include "qemu/timer.h" /* MPCore private memory region. */ diff --git a/hw/arm_boot.c b/hw/arm_boot.c index 63ff559cf7..bb9889fbef 100644 --- a/hw/arm_boot.c +++ b/hw/arm_boot.c @@ -15,7 +15,7 @@ #include "loader.h" #include "elf.h" #include "device_tree.h" -#include "qemu-config.h" +#include "qemu/config-file.h" #define KERNEL_ARGS_ADDR 0x100 #define KERNEL_LOAD_ADDR 0x00010000 diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c index 6790832236..1febaeb7b1 100644 --- a/hw/arm_mptimer.c +++ b/hw/arm_mptimer.c @@ -20,7 +20,7 @@ */ #include "sysbus.h" -#include "qemu-timer.h" +#include "qemu/timer.h" /* This device implements the per-cpu private timer and watchdog block * which is used in both the ARM11MPCore and Cortex-A9MP. diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c index 58eb98216d..0884f6275c 100644 --- a/hw/arm_sysctl.c +++ b/hw/arm_sysctl.c @@ -8,7 +8,7 @@ */ #include "hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysbus.h" #include "primecell.h" #include "sysemu.h" diff --git a/hw/arm_timer.c b/hw/arm_timer.c index af339d3d19..37e28e993c 100644 --- a/hw/arm_timer.c +++ b/hw/arm_timer.c @@ -8,7 +8,7 @@ */ #include "sysbus.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "qemu-common.h" #include "qdev.h" #include "ptimer.h" diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c index 270c307717..0907e42c0c 100644 --- a/hw/armv7m_nvic.c +++ b/hw/armv7m_nvic.c @@ -11,7 +11,7 @@ */ #include "sysbus.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "arm-misc.h" #include "exec/address-spaces.h" #include "arm_gic_internal.h" diff --git a/hw/baum.c b/hw/baum.c index 3e94f84e51..97d13ea344 100644 --- a/hw/baum.c +++ b/hw/baum.c @@ -23,7 +23,7 @@ */ #include "qemu-common.h" #include "qemu-char.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "usb.h" #include "baum.h" #include diff --git a/hw/block-common.c b/hw/block-common.c index f0196d78dc..c24208e560 100644 --- a/hw/block-common.c +++ b/hw/block-common.c @@ -9,7 +9,7 @@ #include "blockdev.h" #include "hw/block-common.h" -#include "qemu-error.h" +#include "qemu/error-report.h" void blkconf_serial(BlockConf *conf, char **serial) { diff --git a/hw/bt-hci-csr.c b/hw/bt-hci-csr.c index 0faabbb585..e1dcb6d099 100644 --- a/hw/bt-hci-csr.c +++ b/hw/bt-hci-csr.c @@ -20,7 +20,7 @@ #include "qemu-common.h" #include "qemu-char.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "irq.h" #include "bt-host.h" #include "bt.h" diff --git a/hw/bt-hci.c b/hw/bt-hci.c index d2ad57faa9..da096d8c37 100644 --- a/hw/bt-hci.c +++ b/hw/bt-hci.c @@ -19,7 +19,7 @@ */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "usb.h" #include "bt-host.h" #include "bt.h" diff --git a/hw/bt-hid.c b/hw/bt-hid.c index 0ec0c013b0..cfa7c145b8 100644 --- a/hw/bt-hid.c +++ b/hw/bt-hid.c @@ -19,7 +19,7 @@ */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ui/console.h" #include "hid.h" #include "bt.h" diff --git a/hw/bt-l2cap.c b/hw/bt-l2cap.c index cb43ee7733..ba061c0da3 100644 --- a/hw/bt-l2cap.c +++ b/hw/bt-l2cap.c @@ -18,7 +18,7 @@ */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "bt.h" #define L2CAP_CID_MAX 0x100 /* Between 0x40 and 0x10000 */ diff --git a/hw/cadence_ttc.c b/hw/cadence_ttc.c index ec78a52180..9e1cb1f152 100644 --- a/hw/cadence_ttc.c +++ b/hw/cadence_ttc.c @@ -17,7 +17,7 @@ */ #include "sysbus.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #ifdef CADENCE_TTC_ERR_DEBUG #define DB_PRINT(...) do { \ diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c index 686e6172d0..f34acc8c46 100644 --- a/hw/cadence_uart.c +++ b/hw/cadence_uart.c @@ -18,7 +18,7 @@ #include "sysbus.h" #include "qemu-char.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #ifdef CADENCE_UART_ERR_DEBUG #define DB_PRINT(...) do { \ diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c index 845a764446..e508380482 100644 --- a/hw/ccid-card-emulated.c +++ b/hw/ccid-card-emulated.c @@ -31,7 +31,7 @@ #include #include -#include "qemu-thread.h" +#include "qemu/thread.h" #include "qemu-char.h" #include "monitor/monitor.h" #include "hw/ccid.h" diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c index f5b4794e90..48e4228b9d 100644 --- a/hw/ccid-card-passthru.c +++ b/hw/ccid-card-passthru.c @@ -9,7 +9,7 @@ */ #include "qemu-char.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "monitor/monitor.h" #include "hw/ccid.h" #include "libcacard/vscard_common.h" diff --git a/hw/cs4231a.c b/hw/cs4231a.c index 0257fd8d2a..9d528c43b0 100644 --- a/hw/cs4231a.c +++ b/hw/cs4231a.c @@ -26,7 +26,7 @@ #include "audio/audio.h" #include "isa.h" #include "qdev.h" -#include "qemu-timer.h" +#include "qemu/timer.h" /* Missing features: diff --git a/hw/cuda.c b/hw/cuda.c index f1f408b839..cf83956e1a 100644 --- a/hw/cuda.c +++ b/hw/cuda.c @@ -25,7 +25,7 @@ #include "hw.h" #include "ppc_mac.h" #include "adb.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysemu.h" /* XXX: implement all timer modes */ diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c index 809a598e3a..34543786e5 100644 --- a/hw/device-hotplug.c +++ b/hw/device-hotplug.c @@ -25,7 +25,7 @@ #include "hw.h" #include "boards.h" #include "blockdev.h" -#include "qemu-config.h" +#include "qemu/config-file.h" #include "sysemu.h" #include "monitor/monitor.h" diff --git a/hw/dma.c b/hw/dma.c index 364f54d2d7..0634baa552 100644 --- a/hw/dma.c +++ b/hw/dma.c @@ -23,7 +23,7 @@ */ #include "hw.h" #include "isa.h" -#include "main-loop.h" +#include "qemu/main-loop.h" /* #define DEBUG_DMA */ diff --git a/hw/dp8393x.c b/hw/dp8393x.c index d59b6118ad..b5014501df 100644 --- a/hw/dp8393x.c +++ b/hw/dp8393x.c @@ -18,7 +18,7 @@ */ #include "hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "net/net.h" #include "mips.h" diff --git a/hw/esp-pci.c b/hw/esp-pci.c index d433473d6a..c949e6e0d9 100644 --- a/hw/esp-pci.c +++ b/hw/esp-pci.c @@ -27,7 +27,7 @@ #include "eeprom93xx.h" #include "esp.h" #include "trace.h" -#include "qemu-log.h" +#include "qemu/log.h" #define TYPE_AM53C974_DEVICE "am53c974" diff --git a/hw/esp.c b/hw/esp.c index 6d01624a49..0e4e430880 100644 --- a/hw/esp.c +++ b/hw/esp.c @@ -26,7 +26,7 @@ #include "sysbus.h" #include "esp.h" #include "trace.h" -#include "qemu-log.h" +#include "qemu/log.h" /* * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O), diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c index ee0d72bf87..59cb7d2172 100644 --- a/hw/etraxfs_ser.c +++ b/hw/etraxfs_ser.c @@ -24,7 +24,7 @@ #include "sysbus.h" #include "qemu-char.h" -#include "qemu-log.h" +#include "qemu/log.h" #define D(x) diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c index f5601dc7a5..cc8b327715 100644 --- a/hw/etraxfs_timer.c +++ b/hw/etraxfs_timer.c @@ -23,7 +23,7 @@ */ #include "sysbus.h" #include "sysemu.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ptimer.h" #define D(x) diff --git a/hw/exynos4210_fimd.c b/hw/exynos4210_fimd.c index cfca72ab67..5c29b5d01d 100644 --- a/hw/exynos4210_fimd.c +++ b/hw/exynos4210_fimd.c @@ -27,7 +27,7 @@ #include "sysbus.h" #include "ui/console.h" #include "ui/pixel_ops.h" -#include "bswap.h" +#include "qemu/bswap.h" /* Debug messages configuration */ #define EXYNOS4210_FIMD_DEBUG 0 diff --git a/hw/exynos4210_i2c.c b/hw/exynos4210_i2c.c index 1e11d9b48c..cefd736092 100644 --- a/hw/exynos4210_i2c.c +++ b/hw/exynos4210_i2c.c @@ -20,7 +20,7 @@ * */ -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysbus.h" #include "i2c.h" diff --git a/hw/exynos4210_mct.c b/hw/exynos4210_mct.c index 37dbda92df..41cd142227 100644 --- a/hw/exynos4210_mct.c +++ b/hw/exynos4210_mct.c @@ -53,7 +53,7 @@ */ #include "sysbus.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "qemu-common.h" #include "ptimer.h" diff --git a/hw/exynos4210_pwm.c b/hw/exynos4210_pwm.c index 5e2872f8f7..3a3eb8c27a 100644 --- a/hw/exynos4210_pwm.c +++ b/hw/exynos4210_pwm.c @@ -21,7 +21,7 @@ */ #include "sysbus.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "qemu-common.h" #include "ptimer.h" diff --git a/hw/exynos4210_rtc.c b/hw/exynos4210_rtc.c index c4fbd49461..6ebc9b1790 100644 --- a/hw/exynos4210_rtc.c +++ b/hw/exynos4210_rtc.c @@ -26,12 +26,12 @@ */ #include "sysbus.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "qemu-common.h" #include "ptimer.h" #include "hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysemu.h" #include "exynos4210.h" diff --git a/hw/fdc.c b/hw/fdc.c index 29b5449ff8..b67d3a574b 100644 --- a/hw/fdc.c +++ b/hw/fdc.c @@ -29,14 +29,14 @@ #include "hw.h" #include "fdc.h" -#include "qemu-error.h" -#include "qemu-timer.h" +#include "qemu/error-report.h" +#include "qemu/timer.h" #include "isa.h" #include "sysbus.h" #include "qdev-addr.h" #include "blockdev.h" #include "sysemu.h" -#include "qemu-log.h" +#include "qemu/log.h" /********************************************************/ /* debug Floppy devices */ diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c index 7b0e50f70d..2a00163a04 100644 --- a/hw/fw_cfg.c +++ b/hw/fw_cfg.c @@ -26,8 +26,8 @@ #include "isa.h" #include "fw_cfg.h" #include "sysbus.h" -#include "qemu-error.h" -#include "qemu-config.h" +#include "qemu/error-report.h" +#include "qemu/config-file.h" /* debug firmware config */ //#define DEBUG_FW_CFG diff --git a/hw/grlib_gptimer.c b/hw/grlib_gptimer.c index 2fdccfba06..252ba893e3 100644 --- a/hw/grlib_gptimer.c +++ b/hw/grlib_gptimer.c @@ -23,7 +23,7 @@ */ #include "sysbus.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ptimer.h" #include "trace.h" diff --git a/hw/hid.c b/hw/hid.c index 7935998e83..0fee3b6ddd 100644 --- a/hw/hid.c +++ b/hw/hid.c @@ -24,7 +24,7 @@ */ #include "hw.h" #include "ui/console.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "hid.h" #define HID_USAGE_ERROR_ROLLOVER 0x01 diff --git a/hw/hpet.c b/hw/hpet.c index 49e1b631b5..78c0662dfc 100644 --- a/hw/hpet.c +++ b/hw/hpet.c @@ -27,7 +27,7 @@ #include "hw.h" #include "pc.h" #include "ui/console.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "hpet_emul.h" #include "sysbus.h" #include "mc146818rtc.h" diff --git a/hw/hw.h b/hw/hw.h index 883ddb60f9..dfced97bbc 100644 --- a/hw/hw.h +++ b/hw/hw.h @@ -13,7 +13,7 @@ #include "block/aio.h" #include "migration/qemu-file.h" #include "migration/vmstate.h" -#include "qemu-log.h" +#include "qemu/log.h" #ifdef NEED_CPU_H #if TARGET_LONG_BITS == 64 diff --git a/hw/i8254.c b/hw/i8254.c index bea5f92fd2..7c2aa6238d 100644 --- a/hw/i8254.c +++ b/hw/i8254.c @@ -24,7 +24,7 @@ #include "hw.h" #include "pc.h" #include "isa.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "i8254.h" #include "i8254_internal.h" diff --git a/hw/i8254_common.c b/hw/i8254_common.c index a03d7cd458..08ab8d14bd 100644 --- a/hw/i8254_common.c +++ b/hw/i8254_common.c @@ -25,7 +25,7 @@ #include "hw.h" #include "pc.h" #include "isa.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "i8254.h" #include "i8254_internal.h" diff --git a/hw/i8259.c b/hw/i8259.c index 5e935e7f99..8fc6339250 100644 --- a/hw/i8259.c +++ b/hw/i8259.c @@ -25,7 +25,7 @@ #include "pc.h" #include "isa.h" #include "monitor/monitor.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "i8259_internal.h" /* debug PIC */ diff --git a/hw/ich9.h b/hw/ich9.h index 5c73f94caf..b8d8e6d3df 100644 --- a/hw/ich9.h +++ b/hw/ich9.h @@ -2,7 +2,7 @@ #define HW_ICH9_H #include "hw.h" -#include "range.h" +#include "qemu/range.h" #include "isa.h" #include "sysbus.h" #include "pc.h" diff --git a/hw/ide/core.c b/hw/ide/core.c index 0e5bc7fe3b..bf65cb407e 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -26,8 +26,8 @@ #include #include #include -#include "qemu-error.h" -#include "qemu-timer.h" +#include "qemu/error-report.h" +#include "qemu/timer.h" #include "sysemu.h" #include "dma.h" #include "hw/block-common.h" diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index f2e4ea4207..c85e1ac018 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -18,7 +18,7 @@ */ #include #include "dma.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include #include "blockdev.h" #include "hw/block-common.h" diff --git a/hw/imx_avic.c b/hw/imx_avic.c index 810979366d..f1f066cf9c 100644 --- a/hw/imx_avic.c +++ b/hw/imx_avic.c @@ -16,7 +16,7 @@ #include "hw.h" #include "sysbus.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #define DEBUG_INT 1 #undef DEBUG_INT /* comment out for debugging */ diff --git a/hw/imx_timer.c b/hw/imx_timer.c index 33f33fb41e..e924c747c5 100644 --- a/hw/imx_timer.c +++ b/hw/imx_timer.c @@ -12,7 +12,7 @@ */ #include "hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ptimer.h" #include "sysbus.h" #include "imx.h" diff --git a/hw/intel-hda.c b/hw/intel-hda.c index c21bf7204a..7ef3a15e08 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -20,7 +20,7 @@ #include "hw.h" #include "pci/pci.h" #include "pci/msi.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "audiodev.h" #include "intel-hda.h" #include "intel-hda-defs.h" diff --git a/hw/ivshmem.c b/hw/ivshmem.c index d5b91dd24e..af34f3b582 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -23,7 +23,7 @@ #include "kvm.h" #include "migration/migration.h" #include "qapi/qmp/qerror.h" -#include "event_notifier.h" +#include "qemu/event_notifier.h" #include "qemu-char.h" #include diff --git a/hw/kvm/i8254.c b/hw/kvm/i8254.c index 53d13e3123..8ee1c352cf 100644 --- a/hw/kvm/i8254.c +++ b/hw/kvm/i8254.c @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysemu.h" #include "hw/i8254.h" #include "hw/i8254_internal.h" diff --git a/hw/kvm/pci-assign.c b/hw/kvm/pci-assign.c index ff0dc0dfd4..2f06c27e83 100644 --- a/hw/kvm/pci-assign.c +++ b/hw/kvm/pci-assign.c @@ -28,11 +28,11 @@ #include #include "hw/hw.h" #include "hw/pc.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "ui/console.h" #include "hw/loader.h" #include "monitor/monitor.h" -#include "range.h" +#include "qemu/range.h" #include "sysemu.h" #include "hw/pci/pci.h" #include "hw/pci/msi.h" diff --git a/hw/lance.c b/hw/lance.c index a384676158..b7265c0fed 100644 --- a/hw/lance.c +++ b/hw/lance.c @@ -37,8 +37,8 @@ #include "sysbus.h" #include "net/net.h" -#include "qemu-timer.h" -#include "qemu_socket.h" +#include "qemu/timer.h" +#include "qemu/sockets.h" #include "sun4m.h" #include "pcnet.h" #include "trace.h" diff --git a/hw/leon3.c b/hw/leon3.c index e8d54e5d06..776ab97a78 100644 --- a/hw/leon3.c +++ b/hw/leon3.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ptimer.h" #include "qemu-char.h" #include "sysemu.h" diff --git a/hw/lm32_sys.c b/hw/lm32_sys.c index a7887d14f6..b3350890cb 100644 --- a/hw/lm32_sys.c +++ b/hw/lm32_sys.c @@ -31,10 +31,10 @@ #include "hw.h" #include "sysbus.h" #include "trace.h" -#include "qemu-log.h" -#include "qemu-error.h" +#include "qemu/log.h" +#include "qemu/error-report.h" #include "sysemu.h" -#include "qemu-log.h" +#include "qemu/log.h" enum { R_CTRL = 0, diff --git a/hw/lm32_timer.c b/hw/lm32_timer.c index a8be9cc168..bd4c346386 100644 --- a/hw/lm32_timer.c +++ b/hw/lm32_timer.c @@ -24,9 +24,9 @@ #include "hw.h" #include "sysbus.h" #include "trace.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ptimer.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #define DEFAULT_FREQUENCY (50*1000000) diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c index adb9287568..bf2f507523 100644 --- a/hw/lm32_uart.c +++ b/hw/lm32_uart.c @@ -26,7 +26,7 @@ #include "sysbus.h" #include "trace.h" #include "qemu-char.h" -#include "qemu-error.h" +#include "qemu/error-report.h" enum { R_RXTX = 0, diff --git a/hw/lm832x.c b/hw/lm832x.c index b14a089b32..3649e3d249 100644 --- a/hw/lm832x.c +++ b/hw/lm832x.c @@ -20,7 +20,7 @@ #include "hw.h" #include "i2c.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ui/console.h" typedef struct { diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c index e225693721..76217a74fc 100644 --- a/hw/lpc_ich9.c +++ b/hw/lpc_ich9.c @@ -29,7 +29,7 @@ */ #include "qemu-common.h" #include "hw.h" -#include "range.h" +#include "qemu/range.h" #include "isa.h" #include "sysbus.h" #include "pc.h" diff --git a/hw/m48t59.c b/hw/m48t59.c index 491d433ae7..301b10ce79 100644 --- a/hw/m48t59.c +++ b/hw/m48t59.c @@ -23,7 +23,7 @@ */ #include "hw.h" #include "nvram.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysemu.h" #include "sysbus.h" #include "isa.h" diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c index 41eee50a35..b894ab21aa 100644 --- a/hw/mac_dbdma.c +++ b/hw/mac_dbdma.c @@ -39,7 +39,7 @@ #include "hw.h" #include "isa.h" #include "mac_dbdma.h" -#include "main-loop.h" +#include "qemu/main-loop.h" /* debug DBDMA */ //#define DEBUG_DBDMA diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index 2a1278f393..fba75029df 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysemu.h" #include "mc146818rtc.h" #include "qapi/visitor.h" diff --git a/hw/mcf5206.c b/hw/mcf5206.c index 5edc931abd..fbc806ac18 100644 --- a/hw/mcf5206.c +++ b/hw/mcf5206.c @@ -7,7 +7,7 @@ */ #include "hw.h" #include "mcf.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ptimer.h" #include "sysemu.h" #include "exec/address-spaces.h" diff --git a/hw/mcf5208.c b/hw/mcf5208.c index 997b34847c..fea8a69262 100644 --- a/hw/mcf5208.c +++ b/hw/mcf5208.c @@ -7,7 +7,7 @@ */ #include "hw.h" #include "mcf.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ptimer.h" #include "sysemu.h" #include "net/net.h" diff --git a/hw/megasas.c b/hw/megasas.c index f4fbe9790a..e80c0d1c25 100644 --- a/hw/megasas.c +++ b/hw/megasas.c @@ -22,7 +22,7 @@ #include "pci/pci.h" #include "dma.h" #include "pci/msix.h" -#include "iov.h" +#include "qemu/iov.h" #include "scsi.h" #include "scsi-defs.h" #include "trace.h" diff --git a/hw/microblaze_boot.c b/hw/microblaze_boot.c index 02c349c189..76d33021c0 100644 --- a/hw/microblaze_boot.c +++ b/hw/microblaze_boot.c @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#include "qemu-option.h" -#include "qemu-config.h" +#include "qemu/option.h" +#include "qemu/config-file.h" #include "qemu-common.h" #include "device_tree.h" #include "loader.h" diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c index d87656c9ac..f46af1c509 100644 --- a/hw/milkymist-ac97.c +++ b/hw/milkymist-ac97.c @@ -25,7 +25,7 @@ #include "sysbus.h" #include "trace.h" #include "audio/audio.h" -#include "qemu-error.h" +#include "qemu/error-report.h" enum { R_AC97_CTRL = 0, diff --git a/hw/milkymist-hpdmc.c b/hw/milkymist-hpdmc.c index 5d120a497f..fd54d3129a 100644 --- a/hw/milkymist-hpdmc.c +++ b/hw/milkymist-hpdmc.c @@ -24,7 +24,7 @@ #include "hw.h" #include "sysbus.h" #include "trace.h" -#include "qemu-error.h" +#include "qemu/error-report.h" enum { R_SYSTEM = 0, diff --git a/hw/milkymist-memcard.c b/hw/milkymist-memcard.c index ca5df56290..5dc30ace60 100644 --- a/hw/milkymist-memcard.c +++ b/hw/milkymist-memcard.c @@ -25,7 +25,7 @@ #include "sysbus.h" #include "sysemu.h" #include "trace.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "blockdev.h" #include "sd.h" diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c index 926f7f9a8b..4e92ac3dcb 100644 --- a/hw/milkymist-minimac2.c +++ b/hw/milkymist-minimac2.c @@ -26,7 +26,7 @@ #include "sysbus.h" #include "trace.h" #include "net/net.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "qdev-addr.h" #include diff --git a/hw/milkymist-pfpu.c b/hw/milkymist-pfpu.c index 450bab921f..0521829202 100644 --- a/hw/milkymist-pfpu.c +++ b/hw/milkymist-pfpu.c @@ -25,8 +25,8 @@ #include "hw.h" #include "sysbus.h" #include "trace.h" -#include "qemu-log.h" -#include "qemu-error.h" +#include "qemu/log.h" +#include "qemu/error-report.h" #include /* #define TRACE_EXEC */ diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c index 0743668d18..b7beb4bedb 100644 --- a/hw/milkymist-softusb.c +++ b/hw/milkymist-softusb.c @@ -26,7 +26,7 @@ #include "trace.h" #include "ui/console.h" #include "hid.h" -#include "qemu-error.h" +#include "qemu/error-report.h" enum { R_CTRL = 0, diff --git a/hw/milkymist-sysctl.c b/hw/milkymist-sysctl.c index f951ef9ca8..519462afcc 100644 --- a/hw/milkymist-sysctl.c +++ b/hw/milkymist-sysctl.c @@ -25,9 +25,9 @@ #include "sysbus.h" #include "sysemu.h" #include "trace.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ptimer.h" -#include "qemu-error.h" +#include "qemu/error-report.h" enum { CTRL_ENABLE = (1<<0), diff --git a/hw/milkymist-tmu2.c b/hw/milkymist-tmu2.c index 3f9a684eda..a11772aebe 100644 --- a/hw/milkymist-tmu2.c +++ b/hw/milkymist-tmu2.c @@ -27,7 +27,7 @@ #include "hw.h" #include "sysbus.h" #include "trace.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include #include diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c index aefa8c7f1c..ef5518e5c2 100644 --- a/hw/milkymist-uart.c +++ b/hw/milkymist-uart.c @@ -25,7 +25,7 @@ #include "sysbus.h" #include "trace.h" #include "qemu-char.h" -#include "qemu-error.h" +#include "qemu/error-report.h" enum { R_RXTX = 0, diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c index c3471315d3..561285154f 100644 --- a/hw/milkymist-vgafb.c +++ b/hw/milkymist-vgafb.c @@ -28,7 +28,7 @@ #include "ui/console.h" #include "framebuffer.h" #include "ui/pixel_ops.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #define BITS 8 #include "milkymist-vgafb_template.h" diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c index 34619b7e3e..60dd8c69bb 100644 --- a/hw/mips_fulong2e.c +++ b/hw/mips_fulong2e.c @@ -33,7 +33,7 @@ #include "qemu-char.h" #include "sysemu.h" #include "audio/audio.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "loader.h" #include "mips-bios.h" #include "ide.h" diff --git a/hw/mips_malta.c b/hw/mips_malta.c index d65d1256fd..04c7a2612c 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -38,7 +38,7 @@ #include "sysemu.h" #include "arch_init.h" #include "boards.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "mips-bios.h" #include "ide.h" #include "loader.h" diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index 05494b9b40..511e1e41c0 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -17,7 +17,7 @@ #include "sysemu.h" #include "boards.h" #include "flash.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "mips-bios.h" #include "ide.h" #include "loader.h" diff --git a/hw/mips_timer.c b/hw/mips_timer.c index 7aa9004a0e..83c400c158 100644 --- a/hw/mips_timer.c +++ b/hw/mips_timer.c @@ -22,7 +22,7 @@ #include "hw.h" #include "mips_cpudevs.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #define TIMER_FREQ 100 * 1000 * 1000 diff --git a/hw/musicpal.c b/hw/musicpal.c index 436b3f7c37..5a7bf8bee1 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -16,7 +16,7 @@ #include "sysemu.h" #include "boards.h" #include "serial.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ptimer.h" #include "block/block.h" #include "flash.h" diff --git a/hw/nand.c b/hw/nand.c index 01f3adaee1..a73205d866 100644 --- a/hw/nand.c +++ b/hw/nand.c @@ -22,7 +22,7 @@ # include "flash.h" # include "blockdev.h" # include "sysbus.h" -#include "qemu-error.h" +#include "qemu/error-report.h" # define NAND_CMD_READ0 0x00 # define NAND_CMD_READ1 0x01 diff --git a/hw/omap1.c b/hw/omap1.c index 4d5815eb08..50c4570f31 100644 --- a/hw/omap1.c +++ b/hw/omap1.c @@ -22,7 +22,7 @@ #include "sysemu.h" #include "soc_dma.h" #include "blockdev.h" -#include "range.h" +#include "qemu/range.h" #include "sysbus.h" /* Should signal the TCMI/GPMC */ diff --git a/hw/omap2.c b/hw/omap2.c index 96aba71052..7ccee69661 100644 --- a/hw/omap2.c +++ b/hw/omap2.c @@ -23,7 +23,7 @@ #include "arm-misc.h" #include "omap.h" #include "sysemu.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "qemu-char.h" #include "flash.h" #include "soc_dma.h" diff --git a/hw/omap_dma.c b/hw/omap_dma.c index e619c7b7de..aec5874311 100644 --- a/hw/omap_dma.c +++ b/hw/omap_dma.c @@ -18,7 +18,7 @@ * with this program; if not, see . */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "omap.h" #include "irq.h" #include "soc_dma.h" diff --git a/hw/omap_gptimer.c b/hw/omap_gptimer.c index e39da74067..a5db710dcb 100644 --- a/hw/omap_gptimer.c +++ b/hw/omap_gptimer.c @@ -18,7 +18,7 @@ * with this program; if not, see . */ #include "hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "omap.h" /* GP timers */ diff --git a/hw/omap_synctimer.c b/hw/omap_synctimer.c index 7031a88531..945711eff5 100644 --- a/hw/omap_synctimer.c +++ b/hw/omap_synctimer.c @@ -18,7 +18,7 @@ * with this program; if not, see . */ #include "hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "omap.h" struct omap_synctimer_s { MemoryRegion iomem; diff --git a/hw/onenand.c b/hw/onenand.c index 7d255c563f..2e26e3a05d 100644 --- a/hw/onenand.c +++ b/hw/onenand.c @@ -26,7 +26,7 @@ #include "exec/memory.h" #include "exec/address-spaces.h" #include "sysbus.h" -#include "qemu-error.h" +#include "qemu/error-report.h" /* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */ #define PAGE_SHIFT 11 diff --git a/hw/openrisc_timer.c b/hw/openrisc_timer.c index 7916e61d24..d965be77de 100644 --- a/hw/openrisc_timer.c +++ b/hw/openrisc_timer.c @@ -20,7 +20,7 @@ #include "cpu.h" #include "hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #define TIMER_FREQ (20 * 1000 * 1000) /* 20MHz */ diff --git a/hw/pc.c b/hw/pc.c index 7aaff0f2fd..0a92ea6bed 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -50,7 +50,7 @@ #include "exec/memory.h" #include "exec/address-spaces.h" #include "arch_init.h" -#include "bitmap.h" +#include "qemu/bitmap.h" /* debug PC/ISA interrupts */ //#define DEBUG_IRQ diff --git a/hw/pci/msi.c b/hw/pci/msi.c index 680e4637d7..2a04d18884 100644 --- a/hw/pci/msi.c +++ b/hw/pci/msi.c @@ -19,7 +19,7 @@ */ #include "hw/pci/msi.h" -#include "range.h" +#include "qemu/range.h" /* Eventually those constants should go to Linux pci_regs.h */ #define PCI_MSI_PENDING_32 0x10 diff --git a/hw/pci/msix.c b/hw/pci/msix.c index a6a401e286..073e22c315 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -18,7 +18,7 @@ #include "hw/pci/msi.h" #include "hw/pci/msix.h" #include "hw/pci/pci.h" -#include "range.h" +#include "qemu/range.h" #define MSIX_CAP_LENGTH 12 diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug.c index e5e8a7ab58..2bc02e344f 100644 --- a/hw/pci/pci-hotplug.c +++ b/hw/pci/pci-hotplug.c @@ -30,7 +30,7 @@ #include "monitor/monitor.h" #include "hw/scsi.h" #include "hw/virtio-blk.h" -#include "qemu-config.h" +#include "qemu/config-file.h" #include "blockdev.h" #include "qapi/error.h" diff --git a/hw/pci/pci.c b/hw/pci/pci.c index e062f66088..c9ed95be89 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -29,7 +29,7 @@ #include "net/net.h" #include "sysemu.h" #include "hw/loader.h" -#include "range.h" +#include "qemu/range.h" #include "qmp-commands.h" #include "hw/pci/msi.h" #include "hw/pci/msix.h" diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c index 131091408d..995842a72d 100644 --- a/hw/pci/pci_bridge.c +++ b/hw/pci/pci_bridge.c @@ -31,7 +31,7 @@ #include "hw/pci/pci_bridge.h" #include "hw/pci/pci_bus.h" -#include "range.h" +#include "qemu/range.h" /* PCI bridge subsystem vendor ID helper functions */ #define PCI_SSVID_SIZEOF 8 diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index b60a6faaf3..6c916d15ec 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -25,7 +25,7 @@ #include "hw/pci/msi.h" #include "hw/pci/pci_bus.h" #include "hw/pci/pcie_regs.h" -#include "range.h" +#include "qemu/range.h" //#define DEBUG_PCIE #ifdef DEBUG_PCIE diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c index 18b1512b43..f07266da66 100644 --- a/hw/pci/shpc.c +++ b/hw/pci/shpc.c @@ -1,7 +1,7 @@ #include #include -#include "range.h" -#include "range.h" +#include "qemu/range.h" +#include "qemu/range.h" #include "hw/pci/shpc.h" #include "hw/pci/pci.h" #include "hw/pci/pci_bus.h" diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c index c6768bcbdc..5e8eed3af8 100644 --- a/hw/pcnet-pci.c +++ b/hw/pcnet-pci.c @@ -30,7 +30,7 @@ #include "pci/pci.h" #include "net/net.h" #include "loader.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "dma.h" #include "pcnet.h" diff --git a/hw/pcnet.c b/hw/pcnet.c index 5b03edecdd..87736542e4 100644 --- a/hw/pcnet.c +++ b/hw/pcnet.c @@ -37,8 +37,8 @@ #include "qdev.h" #include "net/net.h" -#include "qemu-timer.h" -#include "qemu_socket.h" +#include "qemu/timer.h" +#include "qemu/sockets.h" #include "sysemu.h" #include "pcnet.h" diff --git a/hw/pcspk.c b/hw/pcspk.c index ad6491b0f4..6d55ebe82f 100644 --- a/hw/pcspk.c +++ b/hw/pcspk.c @@ -26,7 +26,7 @@ #include "pc.h" #include "isa.h" #include "audio/audio.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "i8254.h" #include "pcspk.h" diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index 36af4647df..59982dcd6f 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -39,9 +39,9 @@ #include "hw.h" #include "flash.h" #include "block/block.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "exec/address-spaces.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "sysbus.h" #define PFLASH_BUG(fmt, ...) \ diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c index c689cc9f42..6924f064c2 100644 --- a/hw/pflash_cfi02.c +++ b/hw/pflash_cfi02.c @@ -37,10 +37,10 @@ #include "hw.h" #include "flash.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "block/block.h" #include "exec/address-spaces.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "sysbus.h" //#define PFLASH_DEBUG diff --git a/hw/piix_pci.c b/hw/piix_pci.c index b5ea68bc61..3d79c73fda 100644 --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@ -28,7 +28,7 @@ #include "pci/pci_host.h" #include "isa.h" #include "sysbus.h" -#include "range.h" +#include "qemu/range.h" #include "xen.h" #include "pam.h" diff --git a/hw/pl031.c b/hw/pl031.c index 8bf0183289..834a20c917 100644 --- a/hw/pl031.c +++ b/hw/pl031.c @@ -12,7 +12,7 @@ */ #include "sysbus.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysemu.h" //#define DEBUG_PL031 diff --git a/hw/ppc.c b/hw/ppc.c index 11fd199eaa..f066367609 100644 --- a/hw/ppc.c +++ b/hw/ppc.c @@ -23,10 +23,10 @@ */ #include "hw.h" #include "ppc.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysemu.h" #include "nvram.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "loader.h" #include "kvm.h" #include "kvm_ppc.h" diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 798e67cedf..3593f7c0e2 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -19,7 +19,7 @@ #include "e500.h" #include "e500-ccsr.h" #include "net/net.h" -#include "qemu-config.h" +#include "qemu/config-file.h" #include "hw/hw.h" #include "hw/serial.h" #include "hw/pci/pci.h" @@ -34,7 +34,7 @@ #include "elf.h" #include "hw/sysbus.h" #include "exec/address-spaces.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "hw/ppce500_pci.h" #define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb" diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c index 5a0e0260e6..31bcc4bb95 100644 --- a/hw/ppc405_boards.c +++ b/hw/ppc405_boards.c @@ -29,7 +29,7 @@ #include "sysemu.h" #include "block/block.h" #include "boards.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "loader.h" #include "blockdev.h" #include "exec/address-spaces.h" diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c index aabb2efb48..b1ed8837d6 100644 --- a/hw/ppc405_uc.c +++ b/hw/ppc405_uc.c @@ -25,9 +25,9 @@ #include "ppc.h" #include "ppc405.h" #include "serial.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysemu.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "exec/address-spaces.h" #define DEBUG_OPBA diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c index 3b9dc06716..d1fb1576b0 100644 --- a/hw/ppc4xx_devs.c +++ b/hw/ppc4xx_devs.c @@ -24,7 +24,7 @@ #include "hw.h" #include "ppc.h" #include "ppc4xx.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "exec/address-spaces.h" //#define DEBUG_MMIO diff --git a/hw/ppc_booke.c b/hw/ppc_booke.c index d51e7fad67..a7182be0d3 100644 --- a/hw/ppc_booke.c +++ b/hw/ppc_booke.c @@ -23,10 +23,10 @@ */ #include "hw.h" #include "ppc.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysemu.h" #include "nvram.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "loader.h" diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index aa46cc6f55..072535294e 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -33,7 +33,7 @@ #include "pci/pci_host.h" #include "ppc.h" #include "boards.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "ide.h" #include "loader.h" #include "mc146818rtc.h" diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index feefc6596b..1e1ade3d2e 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -18,7 +18,7 @@ #include "hw/ppc/e500-ccsr.h" #include "pci/pci.h" #include "pci/pci_host.h" -#include "bswap.h" +#include "qemu/bswap.h" #include "ppce500_pci.h" #ifdef DEBUG_PCI diff --git a/hw/ptimer.c b/hw/ptimer.c index bc0b3f802f..24af6a2afe 100644 --- a/hw/ptimer.c +++ b/hw/ptimer.c @@ -6,9 +6,9 @@ * This code is licensed under the GNU LGPL. */ #include "hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ptimer.h" -#include "host-utils.h" +#include "qemu/host-utils.h" struct ptimer_state { diff --git a/hw/ptimer.h b/hw/ptimer.h index 9d172f7764..28fcaf17f8 100644 --- a/hw/ptimer.h +++ b/hw/ptimer.h @@ -9,7 +9,7 @@ #define PTIMER_H #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "migration/vmstate.h" /* ptimer.c */ diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c index 8242d26c37..1481c6d3e1 100644 --- a/hw/pxa2xx_timer.c +++ b/hw/pxa2xx_timer.c @@ -8,7 +8,7 @@ */ #include "hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysemu.h" #include "pxa.h" #include "sysbus.h" diff --git a/hw/q35.h b/hw/q35.h index 2f951c8a94..246c12cb04 100644 --- a/hw/q35.h +++ b/hw/q35.h @@ -23,7 +23,7 @@ #define HW_Q35_H #include "hw.h" -#include "range.h" +#include "qemu/range.h" #include "isa.h" #include "sysbus.h" #include "pc.h" diff --git a/hw/qdev-core.h b/hw/qdev-core.h index 93a3a2a7bc..fdf14ec4a6 100644 --- a/hw/qdev-core.h +++ b/hw/qdev-core.h @@ -1,9 +1,9 @@ #ifndef QDEV_CORE_H #define QDEV_CORE_H -#include "qemu-queue.h" -#include "qemu-option.h" -#include "qemu-types.h" +#include "qemu/queue.h" +#include "qemu/option.h" +#include "qemu/typedefs.h" #include "qom/object.h" #include "hw/irq.h" #include "qapi/error.h" diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c index 207282c4a4..1c6712e6de 100644 --- a/hw/qdev-monitor.c +++ b/hw/qdev-monitor.c @@ -21,7 +21,7 @@ #include "monitor/monitor.h" #include "qmp-commands.h" #include "arch_init.h" -#include "qemu-config.h" +#include "qemu/config-file.h" /* * Aliases were a bad idea from the start. Let's keep them diff --git a/hw/qxl-logger.c b/hw/qxl-logger.c index fe2878c836..3cd85d9b97 100644 --- a/hw/qxl-logger.c +++ b/hw/qxl-logger.c @@ -19,7 +19,7 @@ * along with this program; if not, see . */ -#include "qemu-timer.h" +#include "qemu/timer.h" #include "qxl.h" static const char *qxl_type[] = { diff --git a/hw/qxl.c b/hw/qxl.c index ad0214827e..b88a39cc93 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -21,8 +21,8 @@ #include #include "qemu-common.h" -#include "qemu-timer.h" -#include "qemu-queue.h" +#include "qemu/timer.h" +#include "qemu/queue.h" #include "monitor/monitor.h" #include "sysemu.h" #include "trace.h" diff --git a/hw/qxl.h b/hw/qxl.h index 9130261524..f867a1d0ac 100644 --- a/hw/qxl.h +++ b/hw/qxl.h @@ -7,7 +7,7 @@ #include "hw.h" #include "pci/pci.h" #include "vga_int.h" -#include "qemu-thread.h" +#include "qemu/thread.h" #include "ui/qemu-spice.h" #include "ui/spice-display.h" diff --git a/hw/rc4030.c b/hw/rc4030.c index e0024c87e8..a0358a319c 100644 --- a/hw/rc4030.c +++ b/hw/rc4030.c @@ -24,7 +24,7 @@ #include "hw.h" #include "mips.h" -#include "qemu-timer.h" +#include "qemu/timer.h" /********************************************************/ /* debug rc4030 */ diff --git a/hw/rtl8139.c b/hw/rtl8139.c index e024520b8b..19c31a02c6 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -54,11 +54,11 @@ #include "hw.h" #include "pci/pci.h" #include "dma.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "net/net.h" #include "loader.h" #include "sysemu.h" -#include "iov.h" +#include "qemu/iov.h" /* debug RTL8139 card */ //#define DEBUG_RTL8139 1 diff --git a/hw/s390x/event-facility.h b/hw/s390x/event-facility.h index 30af0a76a7..791ab2a6de 100644 --- a/hw/s390x/event-facility.h +++ b/hw/s390x/event-facility.h @@ -16,7 +16,7 @@ #define HW_S390_SCLP_EVENT_FACILITY_H #include -#include "qemu-thread.h" +#include "qemu/thread.h" /* SCLP event types */ #define SCLP_EVENT_ASCII_CONSOLE_DATA 0x1a diff --git a/hw/s390x/sclpconsole.c b/hw/s390x/sclpconsole.c index 9ad297c999..ca78d6796a 100644 --- a/hw/s390x/sclpconsole.c +++ b/hw/s390x/sclpconsole.c @@ -13,7 +13,7 @@ */ #include -#include "qemu-thread.h" +#include "qemu/thread.h" #include "sclp.h" #include "event-facility.h" diff --git a/hw/sb16.c b/hw/sb16.c index 523ab0d5fd..bb460ccb60 100644 --- a/hw/sb16.c +++ b/hw/sb16.c @@ -26,8 +26,8 @@ #include "audio/audio.h" #include "isa.h" #include "qdev.h" -#include "qemu-timer.h" -#include "host-utils.h" +#include "qemu/timer.h" +#include "qemu/host-utils.h" #define dolog(...) AUD_log ("sb16", __VA_ARGS__) diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index dfb2631210..5dc9f512b5 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -1,5 +1,5 @@ #include "hw.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "scsi.h" #include "scsi-defs.h" #include "qdev.h" diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 49b5686a92..c65da4a9c9 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -29,7 +29,7 @@ do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0) #endif #include "qemu-common.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "scsi.h" #include "scsi-defs.h" #include "sysemu.h" diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index d9045341ba..faeb61ee2c 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -12,7 +12,7 @@ */ #include "qemu-common.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "scsi.h" #include "blockdev.h" diff --git a/hw/sd.c b/hw/sd.c index 2e54eea981..428bd78e32 100644 --- a/hw/sd.c +++ b/hw/sd.c @@ -32,7 +32,7 @@ #include "hw.h" #include "block/block.h" #include "sd.h" -#include "bitmap.h" +#include "qemu/bitmap.h" //#define DEBUG_SD 1 diff --git a/hw/serial.c b/hw/serial.c index 3968c4fc46..2cbb5447a7 100644 --- a/hw/serial.c +++ b/hw/serial.c @@ -25,7 +25,7 @@ #include "serial.h" #include "qemu-char.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "exec/address-spaces.h" //#define DEBUG_SERIAL diff --git a/hw/sh_pci.c b/hw/sh_pci.c index d5218420a3..018b1c198b 100644 --- a/hw/sh_pci.c +++ b/hw/sh_pci.c @@ -25,7 +25,7 @@ #include "sh.h" #include "pci/pci.h" #include "pci/pci_host.h" -#include "bswap.h" +#include "qemu/bswap.h" #include "exec/address-spaces.h" typedef struct SHPCIState { diff --git a/hw/sh_timer.c b/hw/sh_timer.c index da6689f369..64ea23fce6 100644 --- a/hw/sh_timer.c +++ b/hw/sh_timer.c @@ -10,7 +10,7 @@ #include "hw.h" #include "sh.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "exec/address-spaces.h" #include "ptimer.h" diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c index c07ceb1de0..584629f1a5 100644 --- a/hw/slavio_timer.c +++ b/hw/slavio_timer.c @@ -23,7 +23,7 @@ */ #include "sun4m.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ptimer.h" #include "sysbus.h" #include "trace.h" diff --git a/hw/sm501.c b/hw/sm501.c index 714aca0492..dd186aa7f2 100644 --- a/hw/sm501.c +++ b/hw/sm501.c @@ -29,7 +29,7 @@ #include "devices.h" #include "sysbus.h" #include "qdev-addr.h" -#include "range.h" +#include "qemu/range.h" #include "ui/pixel_ops.h" /* diff --git a/hw/soc_dma.c b/hw/soc_dma.c index 50d5f84b4e..64e8ee1d13 100644 --- a/hw/soc_dma.c +++ b/hw/soc_dma.c @@ -18,7 +18,7 @@ * with this program; if not, see . */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "soc_dma.h" static void transfer_mem2mem(struct soc_dma_ch_s *ch) diff --git a/hw/spapr.c b/hw/spapr.c index d1252fc68c..1abfde2a05 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -49,7 +49,7 @@ #include "exec/address-spaces.h" #include "hw/usb.h" -#include "qemu-config.h" +#include "qemu/config-file.h" #include diff --git a/hw/spitz.c b/hw/spitz.c index 48668a0f10..1259e32974 100644 --- a/hw/spitz.c +++ b/hw/spitz.c @@ -18,7 +18,7 @@ #include "i2c.h" #include "ssi.h" #include "flash.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "devices.h" #include "sharpsl.h" #include "ui/console.h" diff --git a/hw/stellaris.c b/hw/stellaris.c index 368f8a5e73..26da3c7f60 100644 --- a/hw/stellaris.c +++ b/hw/stellaris.c @@ -11,7 +11,7 @@ #include "ssi.h" #include "arm-misc.h" #include "devices.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "i2c.h" #include "net/net.h" #include "boards.h" diff --git a/hw/strongarm.c b/hw/strongarm.c index 44bec34e07..f776fee3bc 100644 --- a/hw/strongarm.c +++ b/hw/strongarm.c @@ -28,7 +28,7 @@ */ #include "sysbus.h" #include "strongarm.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "arm-misc.h" #include "qemu-char.h" #include "sysemu.h" diff --git a/hw/sun4m.c b/hw/sun4m.c index 9a784dfd04..4245854949 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "sysbus.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sun4m.h" #include "nvram.h" #include "sparc32_dma.h" diff --git a/hw/sun4u.c b/hw/sun4u.c index 000f6118e1..8bca4fdff9 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -29,7 +29,7 @@ #include "nvram.h" #include "fdc.h" #include "net/net.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysemu.h" #include "boards.h" #include "firmware_abi.h" diff --git a/hw/tsc2005.c b/hw/tsc2005.c index e2326283c0..740ff86aa8 100644 --- a/hw/tsc2005.c +++ b/hw/tsc2005.c @@ -19,7 +19,7 @@ */ #include "hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ui/console.h" #include "devices.h" diff --git a/hw/tsc210x.c b/hw/tsc210x.c index 2b3535d4fc..2076c355d2 100644 --- a/hw/tsc210x.c +++ b/hw/tsc210x.c @@ -21,7 +21,7 @@ #include "hw.h" #include "audio/audio.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ui/console.h" #include "omap.h" /* For I2SCodec and uWireSlave */ #include "devices.h" diff --git a/hw/tusb6010.c b/hw/tusb6010.c index 325200bd34..990d50619d 100644 --- a/hw/tusb6010.c +++ b/hw/tusb6010.c @@ -19,7 +19,7 @@ * with this program; if not, see . */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "usb.h" #include "omap.h" #include "irq.h" diff --git a/hw/twl92230.c b/hw/twl92230.c index ce699bdbdd..3210b9ef4e 100644 --- a/hw/twl92230.c +++ b/hw/twl92230.c @@ -20,7 +20,7 @@ */ #include "hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "i2c.h" #include "sysemu.h" #include "ui/console.h" diff --git a/hw/usb.h b/hw/usb.h index efae65dcad..81e265c4fd 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -26,7 +26,7 @@ */ #include "qdev.h" -#include "qemu-queue.h" +#include "qemu/queue.h" /* Constants related to the USB / PCI interaction */ #define USB_SBRN 0x60 /* Serial Bus Release Number Register */ diff --git a/hw/usb/combined-packet.c b/hw/usb/combined-packet.c index 4a0c299457..13f6602ad2 100644 --- a/hw/usb/combined-packet.c +++ b/hw/usb/combined-packet.c @@ -21,7 +21,7 @@ */ #include "qemu-common.h" #include "hw/usb.h" -#include "iov.h" +#include "qemu/iov.h" #include "trace.h" static void usb_combined_packet_add(USBCombinedPacket *combined, USBPacket *p) diff --git a/hw/usb/core.c b/hw/usb/core.c index 8e360d3ec0..e315fc1021 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -25,7 +25,7 @@ */ #include "qemu-common.h" #include "hw/usb.h" -#include "iov.h" +#include "qemu/iov.h" #include "trace.h" void usb_attach(USBPort *port) diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c index 6953f2e710..ce38fef9f6 100644 --- a/hw/usb/dev-hid.c +++ b/hw/usb/dev-hid.c @@ -26,7 +26,7 @@ #include "ui/console.h" #include "hw/usb.h" #include "hw/usb/desc.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "hw/hid.h" /* HID interface requests */ diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index bf289ff5a6..e8ada9f02c 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -27,10 +27,10 @@ #include "hw/usb.h" #include "hw/usb/desc.h" #include "net/net.h" -#include "qemu-queue.h" -#include "qemu-config.h" +#include "qemu/queue.h" +#include "qemu/config-file.h" #include "sysemu.h" -#include "iov.h" +#include "qemu/iov.h" /*#define TRAFFIC_DEBUG*/ /* Thanks to NetChip Technologies for donating this product ID. diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 99b19df1d1..2ff4fe247a 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -9,7 +9,7 @@ */ #include "qemu-common.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "hw/usb.h" #include "hw/usb/desc.h" #include "qemu-char.h" diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index 3862c9b6c9..f26bb341f7 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -35,7 +35,7 @@ */ #include "qemu-common.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "hw/usb.h" #include "hw/usb/desc.h" #include "monitor/monitor.h" diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 0d7597b4d1..6d27bac94f 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -8,8 +8,8 @@ */ #include "qemu-common.h" -#include "qemu-option.h" -#include "qemu-config.h" +#include "qemu/option.h" +#include "qemu/config-file.h" #include "hw/usb.h" #include "hw/usb/desc.h" #include "hw/scsi.h" diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index a21b2ba627..9a0088928f 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -10,8 +10,8 @@ */ #include "qemu-common.h" -#include "qemu-option.h" -#include "qemu-config.h" +#include "qemu/option.h" +#include "qemu/config-file.h" #include "trace.h" #include "hw/usb.h" diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c index 8b043966f6..ee77d41db5 100644 --- a/hw/usb/hcd-ehci-pci.c +++ b/hw/usb/hcd-ehci-pci.c @@ -17,7 +17,7 @@ #include "hw/usb/hcd-ehci.h" #include "hw/pci/pci.h" -#include "range.h" +#include "qemu/range.h" typedef struct EHCIPCIState { PCIDevice pcidev; diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index 740f7309fb..5bc80031bf 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -18,7 +18,7 @@ #define HW_USB_EHCI_H 1 #include "hw/hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "hw/usb.h" #include "monitor/monitor.h" #include "trace.h" diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c index c707f7a2bb..64e9e834bf 100644 --- a/hw/usb/hcd-musb.c +++ b/hw/usb/hcd-musb.c @@ -21,7 +21,7 @@ * Only host-mode and non-DMA accesses are currently supported. */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "hw/usb.h" #include "hw/irq.h" #include "hw/hw.h" diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 4faf8e1aed..052c4a3037 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -27,7 +27,7 @@ */ #include "hw/hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "hw/usb.h" #include "hw/pci/pci.h" #include "hw/sysbus.h" diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 04c944613c..c9b8a31465 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -28,8 +28,8 @@ #include "hw/hw.h" #include "hw/usb.h" #include "hw/pci/pci.h" -#include "qemu-timer.h" -#include "iov.h" +#include "qemu/timer.h" +#include "qemu/iov.h" #include "dma.h" #include "trace.h" diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 220c3b536a..e2de71ef1a 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -19,7 +19,7 @@ * License along with this library; if not, see . */ #include "hw/hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "hw/usb.h" #include "hw/pci/pci.h" #include "hw/pci/msi.h" diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c index 5a56e99891..9a8c26ceaf 100644 --- a/hw/usb/host-linux.c +++ b/hw/usb/host-linux.c @@ -31,7 +31,7 @@ */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "monitor/monitor.h" #include "sysemu.h" #include "trace.h" diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 3621076020..31e5f27595 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -26,10 +26,10 @@ */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "monitor/monitor.h" #include "sysemu.h" -#include "iov.h" +#include "qemu/iov.h" #include #include diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 096621cdbd..9f204bc113 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -27,7 +27,7 @@ #include #include "config.h" -#include "event_notifier.h" +#include "qemu/event_notifier.h" #include "exec/address-spaces.h" #include "kvm.h" #include "exec/memory.h" @@ -35,9 +35,9 @@ #include "pci/msix.h" #include "pci/pci.h" #include "qemu-common.h" -#include "qemu-error.h" -#include "qemu-queue.h" -#include "range.h" +#include "qemu/error-report.h" +#include "qemu/queue.h" +#include "qemu/range.h" /* #define DEBUG_VFIO */ #ifdef DEBUG_VFIO diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c index 008703ff57..311c966f77 100644 --- a/hw/vga-isa-mm.c +++ b/hw/vga-isa-mm.c @@ -26,7 +26,7 @@ #include "pc.h" #include "vga_int.h" #include "ui/pixel_ops.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #define VGA_RAM_SIZE (8192 * 1024) diff --git a/hw/vga-isa.c b/hw/vga-isa.c index d1d5b11828..cbe7b05a7e 100644 --- a/hw/vga-isa.c +++ b/hw/vga-isa.c @@ -28,7 +28,7 @@ #include "pc.h" #include "vga_int.h" #include "ui/pixel_ops.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "loader.h" typedef struct ISAVGAState { diff --git a/hw/vga-pci.c b/hw/vga-pci.c index fe3a3d4899..87c7c0648d 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -28,7 +28,7 @@ #include "pci/pci.h" #include "vga_int.h" #include "ui/pixel_ops.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "loader.h" #define PCI_VGA_IOPORT_OFFSET 0x400 diff --git a/hw/vga.c b/hw/vga.c index 4007116859..e2ba7f208c 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -28,7 +28,7 @@ #include "pci/pci.h" #include "vga_int.h" #include "ui/pixel_ops.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "xen.h" #include "trace.h" diff --git a/hw/vhost.c b/hw/vhost.c index feaff64c15..4e1cb47418 100644 --- a/hw/vhost.c +++ b/hw/vhost.c @@ -16,7 +16,7 @@ #include #include "vhost.h" #include "hw/hw.h" -#include "range.h" +#include "qemu/range.h" #include #include "exec/address-spaces.h" diff --git a/hw/vhost_net.c b/hw/vhost_net.c index 93ad89a11c..ae2785d83f 100644 --- a/hw/vhost_net.c +++ b/hw/vhost_net.c @@ -18,7 +18,7 @@ #include "virtio-net.h" #include "vhost_net.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "config.h" diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c index 0f27c2b414..5134e2f477 100644 --- a/hw/virtex_ml507.c +++ b/hw/virtex_ml507.c @@ -32,7 +32,7 @@ #include "device_tree.h" #include "loader.h" #include "elf.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "exec/address-spaces.h" #include "ppc.h" diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c index 97d3a932d9..2eb709b422 100644 --- a/hw/virtio-balloon.c +++ b/hw/virtio-balloon.c @@ -13,7 +13,7 @@ * */ -#include "iov.h" +#include "qemu/iov.h" #include "qemu-common.h" #include "virtio.h" #include "pc.h" diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index e25cc96477..208caa2642 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -12,7 +12,7 @@ */ #include "qemu-common.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "trace.h" #include "hw/block-common.h" #include "blockdev.h" diff --git a/hw/virtio-console.c b/hw/virtio-console.c index cffee3d470..df0951e973 100644 --- a/hw/virtio-console.c +++ b/hw/virtio-console.c @@ -11,7 +11,7 @@ */ #include "qemu-char.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "trace.h" #include "virtio-serial.h" diff --git a/hw/virtio-net.c b/hw/virtio-net.c index dc7c6d6b56..5d03b31c1b 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -11,13 +11,13 @@ * */ -#include "iov.h" +#include "qemu/iov.h" #include "virtio.h" #include "net/net.h" #include "net/checksum.h" #include "net/tap.h" -#include "qemu-error.h" -#include "qemu-timer.h" +#include "qemu/error-report.h" +#include "qemu/timer.h" #include "virtio-net.h" #include "vhost_net.h" diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index a2355dc867..f58917f75f 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -23,14 +23,14 @@ #include "virtio-serial.h" #include "virtio-scsi.h" #include "pci/pci.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "pci/msi.h" #include "pci/msix.h" #include "loader.h" #include "kvm.h" #include "blockdev.h" #include "virtio-pci.h" -#include "range.h" +#include "qemu/range.h" /* from Linux's linux/virtio_pci.h */ diff --git a/hw/virtio-rng.c b/hw/virtio-rng.c index a73ef8e334..e063127df6 100644 --- a/hw/virtio-rng.c +++ b/hw/virtio-rng.c @@ -9,7 +9,7 @@ * top-level directory. */ -#include "iov.h" +#include "qemu/iov.h" #include "qdev.h" #include "virtio.h" #include "virtio-rng.h" diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index 5559518a93..fc5cb32277 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -18,9 +18,9 @@ * GNU GPL, version 2 or (at your option) any later version. */ -#include "iov.h" +#include "qemu/iov.h" #include "monitor/monitor.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #include "sysbus.h" #include "trace.h" #include "virtio-serial.h" diff --git a/hw/virtio.c b/hw/virtio.c index f40a8c5571..0455a9e8f3 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -14,9 +14,9 @@ #include #include "trace.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "virtio.h" -#include "qemu-barrier.h" +#include "qemu/atomic.h" /* The alignment to use between consumer and producer parts of vring. * x86 pagesize again. */ diff --git a/hw/virtio.h b/hw/virtio.h index cdcb490733..511a16992e 100644 --- a/hw/virtio.h +++ b/hw/virtio.h @@ -18,7 +18,7 @@ #include "net/net.h" #include "qdev.h" #include "sysemu.h" -#include "event_notifier.h" +#include "qemu/event_notifier.h" #ifdef CONFIG_LINUX #include "9p.h" #endif diff --git a/hw/vt82c686.c b/hw/vt82c686.c index edceb5a01d..a18aaed217 100644 --- a/hw/vt82c686.c +++ b/hw/vt82c686.c @@ -23,7 +23,7 @@ #include "acpi.h" #include "pm_smbus.h" #include "sysemu.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "exec/address-spaces.h" typedef uint32_t pci_addr_t; diff --git a/hw/watchdog.c b/hw/watchdog.c index 623b299f71..5b04215374 100644 --- a/hw/watchdog.c +++ b/hw/watchdog.c @@ -20,9 +20,9 @@ */ #include "qemu-common.h" -#include "qemu-option.h" -#include "qemu-config.h" -#include "qemu-queue.h" +#include "qemu/option.h" +#include "qemu/config-file.h" +#include "qemu/queue.h" #include "qapi/qmp/types.h" #include "monitor/monitor.h" #include "sysemu.h" diff --git a/hw/watchdog.h b/hw/watchdog.h index c12a29311a..3e9a970686 100644 --- a/hw/watchdog.h +++ b/hw/watchdog.h @@ -22,7 +22,7 @@ #ifndef QEMU_WATCHDOG_H #define QEMU_WATCHDOG_H -#include "qemu-queue.h" +#include "qemu/queue.h" struct WatchdogTimerModel { QLIST_ENTRY(WatchdogTimerModel) entry; diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c index 181774220d..54f0665135 100644 --- a/hw/wdt_i6300esb.c +++ b/hw/wdt_i6300esb.c @@ -22,7 +22,7 @@ #include #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "watchdog.h" #include "hw.h" #include "pci/pci.h" diff --git a/hw/wdt_ib700.c b/hw/wdt_ib700.c index 7f6c21d809..4475f7b862 100644 --- a/hw/wdt_ib700.c +++ b/hw/wdt_ib700.c @@ -20,7 +20,7 @@ */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "watchdog.h" #include "hw.h" #include "isa.h" diff --git a/hw/xen_backend.c b/hw/xen_backend.c index f83a1e1d09..270584fc10 100644 --- a/hw/xen_backend.c +++ b/hw/xen_backend.c @@ -36,7 +36,7 @@ #include "hw.h" #include "qemu-char.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "xen_backend.h" #include diff --git a/hw/xen_common.h b/hw/xen_common.h index 727757afb4..95bc9a7825 100644 --- a/hw/xen_common.h +++ b/hw/xen_common.h @@ -16,7 +16,7 @@ #include "hw.h" #include "xen.h" -#include "qemu-queue.h" +#include "qemu/queue.h" /* * We don't support Xen prior to 3.3.0. diff --git a/hw/xen_domainbuild.c b/hw/xen_domainbuild.c index db1497469a..a4272f0680 100644 --- a/hw/xen_domainbuild.c +++ b/hw/xen_domainbuild.c @@ -1,8 +1,8 @@ #include #include "xen_backend.h" #include "xen_domainbuild.h" -#include "qemu-timer.h" -#include "qemu-log.h" +#include "qemu/timer.h" +#include "qemu/log.h" #include diff --git a/hw/xen_pt.c b/hw/xen_pt.c index 5c50d562d9..9ebd028f2e 100644 --- a/hw/xen_pt.c +++ b/hw/xen_pt.c @@ -58,7 +58,7 @@ #include "xen.h" #include "xen_backend.h" #include "xen_pt.h" -#include "range.h" +#include "qemu/range.h" #include "exec/address-spaces.h" #define XEN_PT_NR_IRQS (256) diff --git a/hw/xen_pt_config_init.c b/hw/xen_pt_config_init.c index 0a5f82cb80..54a179af90 100644 --- a/hw/xen_pt_config_init.c +++ b/hw/xen_pt_config_init.c @@ -12,7 +12,7 @@ * This file implements direct PCI assignment to a HVM guest */ -#include "qemu-timer.h" +#include "qemu/timer.h" #include "xen_backend.h" #include "xen_pt.h" diff --git a/hw/xgmac.c b/hw/xgmac.c index d0d510ed6a..acc3d37648 100644 --- a/hw/xgmac.c +++ b/hw/xgmac.c @@ -26,7 +26,7 @@ #include "sysbus.h" #include "qemu-char.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "net/net.h" #include "net/checksum.h" diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c index 2fd6068428..ce02764b3f 100644 --- a/hw/xilinx_axidma.c +++ b/hw/xilinx_axidma.c @@ -23,9 +23,9 @@ */ #include "sysbus.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "ptimer.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "qdev-addr.h" #include "stream.h" diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c index 35979e65c9..09e49b0aee 100644 --- a/hw/xilinx_axienet.c +++ b/hw/xilinx_axienet.c @@ -23,7 +23,7 @@ */ #include "sysbus.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "net/net.h" #include "net/checksum.h" diff --git a/hw/xilinx_spi.c b/hw/xilinx_spi.c index 039027442c..4eed1828e3 100644 --- a/hw/xilinx_spi.c +++ b/hw/xilinx_spi.c @@ -26,7 +26,7 @@ #include "sysbus.h" #include "sysemu.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "fifo.h" #include "ssi.h" diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c index ee7656d7d8..ebe375e56f 100644 --- a/hw/xilinx_spips.c +++ b/hw/xilinx_spips.c @@ -25,10 +25,10 @@ #include "sysbus.h" #include "sysemu.h" #include "ptimer.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "fifo.h" #include "ssi.h" -#include "bitops.h" +#include "qemu/bitops.h" #ifdef XILINX_SPIPS_ERR_DEBUG #define DB_PRINT(...) do { \ diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c index 2b01dc2869..69294bb83c 100644 --- a/hw/xilinx_timer.c +++ b/hw/xilinx_timer.c @@ -24,7 +24,7 @@ #include "sysbus.h" #include "ptimer.h" -#include "qemu-log.h" +#include "qemu/log.h" #define D(x) diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c index 1ec70cd969..97d36be272 100644 --- a/hw/xtensa_pic.c +++ b/hw/xtensa_pic.c @@ -26,8 +26,8 @@ */ #include "hw.h" -#include "qemu-log.h" -#include "qemu-timer.h" +#include "qemu/log.h" +#include "qemu/timer.h" void xtensa_advance_ccount(CPUXtensaState *env, uint32_t d) { diff --git a/hw/zynq_slcr.c b/hw/zynq_slcr.c index dde4306195..c7ce51f4a6 100644 --- a/hw/zynq_slcr.c +++ b/hw/zynq_slcr.c @@ -15,7 +15,7 @@ */ #include "hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysbus.h" #include "sysemu.h" diff --git a/include/block/aio.h b/include/block/aio.h index 31884a8f16..0933f05878 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -15,8 +15,8 @@ #define QEMU_AIO_H #include "qemu-common.h" -#include "qemu-queue.h" -#include "event_notifier.h" +#include "qemu/queue.h" +#include "qemu/event_notifier.h" typedef struct BlockDriverAIOCB BlockDriverAIOCB; typedef void BlockDriverCompletionFunc(void *opaque, int ret); diff --git a/include/block/block.h b/include/block/block.h index d49ce4dbc5..b81d200b03 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -3,7 +3,7 @@ #include "block/aio.h" #include "qemu-common.h" -#include "qemu-option.h" +#include "qemu/option.h" #include "block/coroutine.h" #include "qapi/qmp/qobject.h" #include "qapi-types.h" diff --git a/include/block/block_int.h b/include/block/block_int.h index 14c57afd54..f83ffb8a08 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -25,10 +25,10 @@ #define BLOCK_INT_H #include "block/block.h" -#include "qemu-option.h" -#include "qemu-queue.h" +#include "qemu/option.h" +#include "qemu/queue.h" #include "block/coroutine.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "qapi-types.h" #include "qapi/qmp/qerror.h" #include "monitor/monitor.h" diff --git a/include/block/coroutine.h b/include/block/coroutine.h index 34c15d4116..c31fae3f3c 100644 --- a/include/block/coroutine.h +++ b/include/block/coroutine.h @@ -16,8 +16,8 @@ #define QEMU_COROUTINE_H #include -#include "qemu-queue.h" -#include "qemu-timer.h" +#include "qemu/queue.h" +#include "qemu/timer.h" /** * Coroutines are a mechanism for stack switching and can be used for diff --git a/include/block/coroutine_int.h b/include/block/coroutine_int.h index 282a3ceda6..17eb71e723 100644 --- a/include/block/coroutine_int.h +++ b/include/block/coroutine_int.h @@ -25,7 +25,7 @@ #ifndef QEMU_COROUTINE_INT_H #define QEMU_COROUTINE_INT_H -#include "qemu-queue.h" +#include "qemu/queue.h" #include "block/coroutine.h" typedef enum { diff --git a/include/block/thread-pool.h b/include/block/thread-pool.h index a87b287081..200703e35f 100644 --- a/include/block/thread-pool.h +++ b/include/block/thread-pool.h @@ -19,8 +19,8 @@ #define QEMU_THREAD_POOL_H 1 #include "qemu-common.h" -#include "qemu-queue.h" -#include "qemu-thread.h" +#include "qemu/queue.h" +#include "qemu/thread.h" #include "block/coroutine.h" #include "block/block_int.h" diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index bec04e2008..c12e35f54d 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -20,7 +20,7 @@ #define CPU_ALL_H #include "qemu-common.h" -#include "qemu-tls.h" +#include "qemu/tls.h" #include "exec/cpu-common.h" /* some important defines: diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index f83d6180f3..4d4f8d4e98 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -9,8 +9,8 @@ #include "exec/poison.h" #endif -#include "bswap.h" -#include "qemu-queue.h" +#include "qemu/bswap.h" +#include "qemu/queue.h" #if !defined(CONFIG_USER_ONLY) diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index 8d2230e50e..aea0ece051 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -27,8 +27,8 @@ #include #include #include -#include "osdep.h" -#include "qemu-queue.h" +#include "qemu/osdep.h" +#include "qemu/queue.h" #include "exec/hwaddr.h" #ifndef TARGET_LONG_BITS diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 2ae8aae3d6..46dca74fda 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -70,7 +70,7 @@ typedef struct TranslationBlock TranslationBlock; #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * MAX_OPC_PARAM) -#include "qemu-log.h" +#include "qemu/log.h" void gen_intermediate_code(CPUArchState *env, struct TranslationBlock *tb); void gen_intermediate_code_pc(CPUArchState *env, struct TranslationBlock *tb); diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h index 1541f0b1e4..8043b3ba26 100644 --- a/include/exec/gen-icount.h +++ b/include/exec/gen-icount.h @@ -1,7 +1,7 @@ #ifndef GEN_ICOUNT_H #define GEN_ICOUNT_H 1 -#include "qemu-timer.h" +#include "qemu/timer.h" /* Helpers for instruction counting code generation. */ diff --git a/include/exec/memory.h b/include/exec/memory.h index b0c474584f..aada969628 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -21,10 +21,10 @@ #include "qemu-common.h" #include "exec/cpu-common.h" #include "exec/hwaddr.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #include "exec/iorange.h" #include "exec/ioport.h" -#include "int128.h" +#include "qemu/int128.h" typedef struct MemoryRegionOps MemoryRegionOps; typedef struct MemoryRegion MemoryRegion; diff --git a/include/exec/softmmu_template.h b/include/exec/softmmu_template.h index 15d4c519ee..b219191abd 100644 --- a/include/exec/softmmu_template.h +++ b/include/exec/softmmu_template.h @@ -21,7 +21,7 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ -#include "qemu-timer.h" +#include "qemu/timer.h" #include "exec/memory.h" #define DATA_SIZE (1 << SHIFT) diff --git a/include/migration/migration.h b/include/migration/migration.h index a95f761e4c..8b7af61e7e 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -16,7 +16,7 @@ #include "qapi/qmp/qdict.h" #include "qemu-common.h" -#include "notify.h" +#include "qemu/notify.h" #include "qapi/error.h" #include "migration/vmstate.h" #include "qapi-types.h" diff --git a/include/net/net.h b/include/net/net.h index 41d3729867..de42dd76da 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -1,10 +1,10 @@ #ifndef QEMU_NET_H #define QEMU_NET_H -#include "qemu-queue.h" +#include "qemu/queue.h" #include "qemu-common.h" #include "qapi/qmp/qdict.h" -#include "qemu-option.h" +#include "qemu/option.h" #include "net/queue.h" #include "migration/vmstate.h" #include "qapi-types.h" diff --git a/include/net/slirp.h b/include/net/slirp.h index ac9d44964f..54b655c272 100644 --- a/include/net/slirp.h +++ b/include/net/slirp.h @@ -26,7 +26,7 @@ #include "qemu-common.h" #include "qapi/qmp/qdict.h" -#include "qemu-option.h" +#include "qemu/option.h" #include "qapi-types.h" #ifdef CONFIG_SLIRP diff --git a/include/qapi/error.h b/include/qapi/error.h index 4d52e7369e..5cd2f0c302 100644 --- a/include/qapi/error.h +++ b/include/qapi/error.h @@ -12,7 +12,7 @@ #ifndef ERROR_H #define ERROR_H -#include "compiler.h" +#include "qemu/compiler.h" #include "qapi-types.h" #include diff --git a/include/qapi/opts-visitor.h b/include/qapi/opts-visitor.h index 31fa4c5628..5939eeebc7 100644 --- a/include/qapi/opts-visitor.h +++ b/include/qapi/opts-visitor.h @@ -14,7 +14,7 @@ #define OPTS_VISITOR_H #include "qapi/visitor.h" -#include "qemu-option.h" +#include "qemu/option.h" typedef struct OptsVisitor OptsVisitor; diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h index c815981d30..6d9a4be3a5 100644 --- a/include/qapi/qmp/qdict.h +++ b/include/qapi/qmp/qdict.h @@ -15,7 +15,7 @@ #include "qapi/qmp/qobject.h" #include "qapi/qmp/qlist.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #include #define QDICT_BUCKET_MAX 512 diff --git a/include/qapi/qmp/qerror.h b/include/qapi/qmp/qerror.h index d912297590..6c0a18dfc4 100644 --- a/include/qapi/qmp/qerror.h +++ b/include/qapi/qmp/qerror.h @@ -14,7 +14,7 @@ #include "qapi/qmp/qdict.h" #include "qapi/qmp/qstring.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "qapi/error.h" #include "qapi-types.h" #include diff --git a/include/qapi/qmp/qjson.h b/include/qapi/qmp/qjson.h index 0473374bf2..73351ed6d6 100644 --- a/include/qapi/qmp/qjson.h +++ b/include/qapi/qmp/qjson.h @@ -15,7 +15,7 @@ #define QJSON_H #include -#include "compiler.h" +#include "qemu/compiler.h" #include "qapi/qmp/qobject.h" #include "qapi/qmp/qstring.h" diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h index ffa0846d48..382f04c3c4 100644 --- a/include/qapi/qmp/qlist.h +++ b/include/qapi/qmp/qlist.h @@ -14,8 +14,8 @@ #define QLIST_H #include "qapi/qmp/qobject.h" -#include "qemu-queue.h" -#include "qemu-queue.h" +#include "qemu/queue.h" +#include "qemu/queue.h" typedef struct QListEntry { QObject *value; diff --git a/acl.h b/include/qemu/acl.h similarity index 98% rename from acl.h rename to include/qemu/acl.h index 0ef780401f..116487e282 100644 --- a/acl.h +++ b/include/qemu/acl.h @@ -25,7 +25,7 @@ #ifndef __QEMU_ACL_H__ #define __QEMU_ACL_H__ -#include "qemu-queue.h" +#include "qemu/queue.h" typedef struct qemu_acl_entry qemu_acl_entry; typedef struct qemu_acl qemu_acl; diff --git a/qemu-barrier.h b/include/qemu/atomic.h similarity index 96% rename from qemu-barrier.h rename to include/qemu/atomic.h index faa83d265e..96a194bbee 100644 --- a/qemu-barrier.h +++ b/include/qemu/atomic.h @@ -6,7 +6,7 @@ #if defined(__i386__) -#include "compiler.h" /* QEMU_GNUC_PREREQ */ +#include "qemu/compiler.h" /* QEMU_GNUC_PREREQ */ /* * Because of the strongly ordered x86 storage model, wmb() and rmb() are nops diff --git a/bitmap.h b/include/qemu/bitmap.h similarity index 99% rename from bitmap.h rename to include/qemu/bitmap.h index 08755eba11..308bbb71e9 100644 --- a/bitmap.h +++ b/include/qemu/bitmap.h @@ -13,7 +13,7 @@ #define BITMAP_H #include "qemu-common.h" -#include "bitops.h" +#include "qemu/bitops.h" /* * The available bitmap operations and their rough meaning in the diff --git a/bitops.h b/include/qemu/bitops.h similarity index 100% rename from bitops.h rename to include/qemu/bitops.h diff --git a/bswap.h b/include/qemu/bswap.h similarity index 100% rename from bswap.h rename to include/qemu/bswap.h diff --git a/cache-utils.h b/include/qemu/cache-utils.h similarity index 100% rename from cache-utils.h rename to include/qemu/cache-utils.h diff --git a/compatfd.h b/include/qemu/compatfd.h similarity index 100% rename from compatfd.h rename to include/qemu/compatfd.h diff --git a/compiler.h b/include/qemu/compiler.h similarity index 100% rename from compiler.h rename to include/qemu/compiler.h diff --git a/qemu-config.h b/include/qemu/config-file.h similarity index 94% rename from qemu-config.h rename to include/qemu/config-file.h index 584491a29b..486c77cad4 100644 --- a/qemu-config.h +++ b/include/qemu/config-file.h @@ -2,9 +2,9 @@ #define QEMU_CONFIG_H #include -#include "qemu-option.h" +#include "qemu/option.h" #include "qapi/error.h" -#include "qemu-option.h" +#include "qemu/option.h" extern QemuOptsList qemu_fsdev_opts; extern QemuOptsList qemu_virtfs_opts; diff --git a/envlist.h b/include/qemu/envlist.h similarity index 100% rename from envlist.h rename to include/qemu/envlist.h diff --git a/qemu-error.h b/include/qemu/error-report.h similarity index 100% rename from qemu-error.h rename to include/qemu/error-report.h diff --git a/event_notifier.h b/include/qemu/event_notifier.h similarity index 100% rename from event_notifier.h rename to include/qemu/event_notifier.h diff --git a/host-utils.h b/include/qemu/host-utils.h similarity index 99% rename from host-utils.h rename to include/qemu/host-utils.h index a5f8464fb2..81c9a754ae 100644 --- a/host-utils.h +++ b/include/qemu/host-utils.h @@ -25,7 +25,7 @@ #ifndef HOST_UTILS_H #define HOST_UTILS_H 1 -#include "compiler.h" /* QEMU_GNUC_PREREQ */ +#include "qemu/compiler.h" /* QEMU_GNUC_PREREQ */ #if defined(__x86_64__) #define __HAVE_FAST_MULU64__ diff --git a/int128.h b/include/qemu/int128.h similarity index 100% rename from int128.h rename to include/qemu/int128.h diff --git a/iov.h b/include/qemu/iov.h similarity index 100% rename from iov.h rename to include/qemu/iov.h diff --git a/qemu-log.h b/include/qemu/log.h similarity index 100% rename from qemu-log.h rename to include/qemu/log.h diff --git a/main-loop.h b/include/qemu/main-loop.h similarity index 100% rename from main-loop.h rename to include/qemu/main-loop.h diff --git a/module.h b/include/qemu/module.h similarity index 100% rename from module.h rename to include/qemu/module.h diff --git a/notify.h b/include/qemu/notify.h similarity index 97% rename from notify.h rename to include/qemu/notify.h index 03cf26c0b6..4e2e7f0ec4 100644 --- a/notify.h +++ b/include/qemu/notify.h @@ -14,7 +14,7 @@ #ifndef QEMU_NOTIFY_H #define QEMU_NOTIFY_H -#include "qemu-queue.h" +#include "qemu/queue.h" typedef struct Notifier Notifier; diff --git a/qemu-option.h b/include/qemu/option.h similarity index 99% rename from qemu-option.h rename to include/qemu/option.h index ca0dc041dd..ba197cddcf 100644 --- a/qemu-option.h +++ b/include/qemu/option.h @@ -27,7 +27,7 @@ #define QEMU_OPTIONS_H #include -#include "qemu-queue.h" +#include "qemu/queue.h" #include "qapi/error.h" #include "qapi/qmp/qdict.h" diff --git a/qemu-option-internal.h b/include/qemu/option_int.h similarity index 96% rename from qemu-option-internal.h rename to include/qemu/option_int.h index 77899b082d..8212fa4a48 100644 --- a/qemu-option-internal.h +++ b/include/qemu/option_int.h @@ -26,8 +26,8 @@ #ifndef QEMU_OPTIONS_INTERNAL_H #define QEMU_OPTIONS_INTERNAL_H -#include "qemu-option.h" -#include "qemu-error.h" +#include "qemu/option.h" +#include "qemu/error-report.h" struct QemuOpt { const char *name; diff --git a/osdep.h b/include/qemu/osdep.h similarity index 100% rename from osdep.h rename to include/qemu/osdep.h diff --git a/qemu-queue.h b/include/qemu/queue.h similarity index 99% rename from qemu-queue.h rename to include/qemu/queue.h index 9288cd8e82..d433b9017c 100644 --- a/qemu-queue.h +++ b/include/qemu/queue.h @@ -78,7 +78,7 @@ * For details on the use of these macros, see the queue(3) manual page. */ -#include "qemu-barrier.h" /* for smp_wmb() */ +#include "qemu/atomic.h" /* for smp_wmb() */ /* * List definitions. diff --git a/range.h b/include/qemu/range.h similarity index 100% rename from range.h rename to include/qemu/range.h diff --git a/qemu_socket.h b/include/qemu/sockets.h similarity index 99% rename from qemu_socket.h rename to include/qemu/sockets.h index 42899fe138..803ae1798c 100644 --- a/qemu_socket.h +++ b/include/qemu/sockets.h @@ -26,7 +26,7 @@ int inet_aton(const char *cp, struct in_addr *ia); #endif /* !_WIN32 */ -#include "qemu-option.h" +#include "qemu/option.h" #include "qapi/error.h" #include "qapi/qmp/qerror.h" diff --git a/qemu-thread-posix.h b/include/qemu/thread-posix.h similarity index 100% rename from qemu-thread-posix.h rename to include/qemu/thread-posix.h diff --git a/qemu-thread-win32.h b/include/qemu/thread-win32.h similarity index 100% rename from qemu-thread-win32.h rename to include/qemu/thread-win32.h diff --git a/qemu-thread.h b/include/qemu/thread.h similarity index 96% rename from qemu-thread.h rename to include/qemu/thread.h index 3ee2f6b1f9..c02404b9fb 100644 --- a/qemu-thread.h +++ b/include/qemu/thread.h @@ -10,9 +10,9 @@ typedef struct QemuSemaphore QemuSemaphore; typedef struct QemuThread QemuThread; #ifdef _WIN32 -#include "qemu-thread-win32.h" +#include "qemu/thread-win32.h" #else -#include "qemu-thread-posix.h" +#include "qemu/thread-posix.h" #endif #define QEMU_THREAD_JOINABLE 0 diff --git a/qemu-timer.h b/include/qemu/timer.h similarity index 99% rename from qemu-timer.h rename to include/qemu/timer.h index da7e97cd5a..1766b2d6c7 100644 --- a/qemu-timer.h +++ b/include/qemu/timer.h @@ -2,8 +2,8 @@ #define QEMU_TIMER_H #include "qemu-common.h" -#include "main-loop.h" -#include "notify.h" +#include "qemu/main-loop.h" +#include "qemu/notify.h" #ifdef __FreeBSD__ #include diff --git a/qemu-tls.h b/include/qemu/tls.h similarity index 100% rename from qemu-tls.h rename to include/qemu/tls.h diff --git a/qemu-types.h b/include/qemu/typedefs.h similarity index 100% rename from qemu-types.h rename to include/qemu/typedefs.h diff --git a/uri.h b/include/qemu/uri.h similarity index 100% rename from uri.h rename to include/qemu/uri.h diff --git a/qemu-xattr.h b/include/qemu/xattr.h similarity index 100% rename from qemu-xattr.h rename to include/qemu/xattr.h diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 9682dd59ed..9e9d044bdf 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -21,7 +21,7 @@ #define QEMU_CPU_H #include "qom/object.h" -#include "qemu-thread.h" +#include "qemu/thread.h" /** * SECTION:cpu diff --git a/include/qom/object.h b/include/qom/object.h index ed1f47f050..abe9691cb7 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -17,7 +17,7 @@ #include #include #include -#include "qemu-queue.h" +#include "qemu/queue.h" struct Visitor; struct Error; diff --git a/include/ui/console.h b/include/ui/console.h index 3db6635b0a..fc23baa06b 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -3,7 +3,7 @@ #include "ui/qemu-pixman.h" #include "qapi/qmp/qdict.h" -#include "notify.h" +#include "qemu/notify.h" #include "monitor/monitor.h" #include "trace.h" #include "qapi-types.h" diff --git a/include/ui/qemu-spice.h b/include/ui/qemu-spice.h index 3e08be06bf..73422adeee 100644 --- a/include/ui/qemu-spice.h +++ b/include/ui/qemu-spice.h @@ -22,8 +22,8 @@ #include -#include "qemu-option.h" -#include "qemu-config.h" +#include "qemu/option.h" +#include "qemu/config-file.h" #include "monitor/monitor.h" extern int using_spice; diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h index 928e0a1bae..a0d1a50487 100644 --- a/include/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -19,7 +19,7 @@ #include #include -#include "qemu-thread.h" +#include "qemu/thread.h" #include "ui/qemu-pixman.h" #include "sysemu.h" diff --git a/iohandler.c b/iohandler.c index cf8276dffc..2523adc11d 100644 --- a/iohandler.c +++ b/iohandler.c @@ -24,9 +24,9 @@ #include "config-host.h" #include "qemu-common.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #include "block/aio.h" -#include "main-loop.h" +#include "qemu/main-loop.h" #ifndef _WIN32 #include diff --git a/iov.c b/iov.c index a81eedcedb..419e419969 100644 --- a/iov.c +++ b/iov.c @@ -16,7 +16,7 @@ * GNU GPL, version 2 or (at your option) any later version. */ -#include "iov.h" +#include "qemu/iov.h" #ifdef _WIN32 # include diff --git a/kvm-all.c b/kvm-all.c index c2588594e1..41ea3aa6ee 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -21,18 +21,18 @@ #include #include "qemu-common.h" -#include "qemu-barrier.h" -#include "qemu-option.h" -#include "qemu-config.h" +#include "qemu/atomic.h" +#include "qemu/option.h" +#include "qemu/config-file.h" #include "sysemu.h" #include "hw/hw.h" #include "hw/pci/msi.h" #include "exec/gdbstub.h" #include "kvm.h" -#include "bswap.h" +#include "qemu/bswap.h" #include "exec/memory.h" #include "exec/address-spaces.h" -#include "event_notifier.h" +#include "qemu/event_notifier.h" /* This check must be after config-host.h is included */ #ifdef CONFIG_EVENTFD diff --git a/kvm.h b/kvm.h index 72d866a966..131d2bdc15 100644 --- a/kvm.h +++ b/kvm.h @@ -16,7 +16,7 @@ #include #include "config-host.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #ifdef CONFIG_KVM #include diff --git a/libcacard/event.c b/libcacard/event.c index 61923761c9..2d7500fac0 100644 --- a/libcacard/event.c +++ b/libcacard/event.c @@ -6,7 +6,7 @@ */ #include "qemu-common.h" -#include "qemu-thread.h" +#include "qemu/thread.h" #include "vcard.h" #include "vreader.h" diff --git a/libcacard/vreader.c b/libcacard/vreader.c index 96d2407e78..313349b656 100644 --- a/libcacard/vreader.c +++ b/libcacard/vreader.c @@ -6,7 +6,7 @@ */ #include "qemu-common.h" -#include "qemu-thread.h" +#include "qemu/thread.h" #include "vcard.h" #include "vcard_emul.h" diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c index b64c93dd69..2fce52bed5 100644 --- a/libcacard/vscclient.c +++ b/libcacard/vscclient.c @@ -13,8 +13,8 @@ #include #include "qemu-common.h" -#include "qemu-thread.h" -#include "qemu_socket.h" +#include "qemu/thread.h" +#include "qemu/sockets.h" #include "vscard_common.h" diff --git a/libfdt_env.h b/libfdt_env.h index 90d7f3b162..7938d73fae 100644 --- a/libfdt_env.h +++ b/libfdt_env.h @@ -19,7 +19,7 @@ #ifndef _LIBFDT_ENV_H #define _LIBFDT_ENV_H -#include "bswap.h" +#include "qemu/bswap.h" #ifdef HOST_WORDS_BIGENDIAN #define fdt32_to_cpu(x) (x) diff --git a/linux-user/main.c b/linux-user/main.c index 25e35cd3dc..f6c4c8d7a3 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -28,11 +28,11 @@ #include "qemu.h" #include "qemu-common.h" -#include "cache-utils.h" +#include "qemu/cache-utils.h" #include "cpu.h" #include "tcg.h" -#include "qemu-timer.h" -#include "envlist.h" +#include "qemu/timer.h" +#include "qemu/envlist.h" #include "elf.h" #define DEBUG_LOGFILE "/tmp/qemu.log" diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 2af883bf74..8a3538c631 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -18,7 +18,7 @@ #include "syscall.h" #include "target_signal.h" #include "exec/gdbstub.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #if defined(CONFIG_USE_NPTL) #define THREAD __thread @@ -217,7 +217,7 @@ unsigned long init_guest_space(unsigned long host_start, unsigned long guest_start, bool fixed); -#include "qemu-log.h" +#include "qemu/log.h" /* syscall.c */ int host_to_target_waitstatus(int status); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 31d5276465..7c304e92de 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -72,7 +72,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include #endif #ifdef CONFIG_ATTR -#include "qemu-xattr.h" +#include "qemu/xattr.h" #endif #define termios host_termios diff --git a/main-loop.c b/main-loop.c index f9006118ad..54f38ae1ae 100644 --- a/main-loop.c +++ b/main-loop.c @@ -23,14 +23,14 @@ */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "slirp/slirp.h" -#include "main-loop.h" +#include "qemu/main-loop.h" #include "block/aio.h" #ifndef _WIN32 -#include "compatfd.h" +#include "qemu/compatfd.h" /* If we have signalfd, we mask out the signals we want to handle and then * use signalfd to listen for them. We rely on whatever the current signal diff --git a/memory.c b/memory.c index d40193d474..d44200335b 100644 --- a/memory.c +++ b/memory.c @@ -16,7 +16,7 @@ #include "exec/memory.h" #include "exec/address-spaces.h" #include "exec/ioport.h" -#include "bitops.h" +#include "qemu/bitops.h" #include "kvm.h" #include diff --git a/memory_mapping.h b/memory_mapping.h index d5ba46c7e7..1256125963 100644 --- a/memory_mapping.h +++ b/memory_mapping.h @@ -14,7 +14,7 @@ #ifndef MEMORY_MAPPING_H #define MEMORY_MAPPING_H -#include "qemu-queue.h" +#include "qemu/queue.h" /* The physical and virtual address in the memory mapping are contiguous. */ typedef struct MemoryMapping { diff --git a/migration-exec.c b/migration-exec.c index 784486d2fc..68f36f41f1 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -16,7 +16,7 @@ */ #include "qemu-common.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "migration/migration.h" #include "buffered_file.h" #include "block/block.h" diff --git a/migration-fd.c b/migration-fd.c index ab5abe2aa5..ea121bc0d6 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -14,12 +14,12 @@ */ #include "qemu-common.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "migration/migration.h" #include "monitor/monitor.h" #include "buffered_file.h" #include "block/block.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" //#define DEBUG_MIGRATION_FD diff --git a/migration-tcp.c b/migration-tcp.c index a36e637ffd..3c4c315052 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -14,7 +14,7 @@ */ #include "qemu-common.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "migration/migration.h" #include "buffered_file.h" #include "block/block.h" diff --git a/migration-unix.c b/migration-unix.c index 9debc952da..d5f986853f 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -14,7 +14,7 @@ */ #include "qemu-common.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "migration/migration.h" #include "buffered_file.h" #include "block/block.h" diff --git a/migration.c b/migration.c index 0456983bad..8c5c5670d8 100644 --- a/migration.c +++ b/migration.c @@ -19,7 +19,7 @@ #include "buffered_file.h" #include "sysemu.h" #include "block/block.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "migration/block.h" #include "qmp-commands.h" diff --git a/module.c b/module.c index c3a6da7a86..7acc33d076 100644 --- a/module.c +++ b/module.c @@ -14,8 +14,8 @@ */ #include "qemu-common.h" -#include "qemu-queue.h" -#include "module.h" +#include "qemu/queue.h" +#include "qemu/module.h" typedef struct ModuleEntry { diff --git a/monitor.c b/monitor.c index 46fdc008f4..878b2317af 100644 --- a/monitor.c +++ b/monitor.c @@ -43,10 +43,10 @@ #include "audio/audio.h" #include "disas/disas.h" #include "balloon.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "migration/migration.h" #include "kvm.h" -#include "acl.h" +#include "qemu/acl.h" #include "qapi/qmp/qint.h" #include "qapi/qmp/qfloat.h" #include "qapi/qmp/qlist.h" @@ -55,7 +55,7 @@ #include "qapi/qmp/qjson.h" #include "qapi/qmp/json-streamer.h" #include "qapi/qmp/json-parser.h" -#include "osdep.h" +#include "qemu/osdep.h" #include "cpu.h" #include "trace.h" #include "trace/control.h" @@ -66,7 +66,7 @@ #include "exec/memory.h" #include "qmp-commands.h" #include "hmp.h" -#include "qemu-thread.h" +#include "qemu/thread.h" /* for pic/irq_info */ #if defined(TARGET_SPARC) diff --git a/nbd.c b/nbd.c index 04ff0a1d44..0698a023ad 100644 --- a/nbd.c +++ b/nbd.c @@ -36,8 +36,8 @@ #include #endif -#include "qemu_socket.h" -#include "qemu-queue.h" +#include "qemu/sockets.h" +#include "qemu/queue.h" //#define DEBUG_NBD diff --git a/net/dump.c b/net/dump.c index e0a5d74644..4119721720 100644 --- a/net/dump.c +++ b/net/dump.c @@ -24,9 +24,9 @@ #include "clients.h" #include "qemu-common.h" -#include "qemu-error.h" -#include "qemu-log.h" -#include "qemu-timer.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qemu/timer.h" #include "hub.h" typedef struct DumpState { diff --git a/net/hub.c b/net/hub.c index 81a73b54a7..5adfce444b 100644 --- a/net/hub.c +++ b/net/hub.c @@ -16,7 +16,7 @@ #include "net/net.h" #include "clients.h" #include "hub.h" -#include "iov.h" +#include "qemu/iov.h" /* * A hub broadcasts incoming packets to all its ports except the source port. diff --git a/net/net.c b/net/net.c index e4d85a9cfa..dbf3e1b003 100644 --- a/net/net.c +++ b/net/net.c @@ -31,11 +31,11 @@ #include "monitor/monitor.h" #include "qemu-common.h" -#include "qemu_socket.h" -#include "qemu-config.h" +#include "qemu/sockets.h" +#include "qemu/config-file.h" #include "qmp-commands.h" #include "hw/qdev.h" -#include "iov.h" +#include "qemu/iov.h" #include "qapi-visit.h" #include "qapi/opts-visitor.h" #include "qapi/dealloc-visitor.h" diff --git a/net/queue.c b/net/queue.c index 542c549b1a..6eaf5b63c0 100644 --- a/net/queue.c +++ b/net/queue.c @@ -22,7 +22,7 @@ */ #include "net/queue.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #include "net/net.h" /* The delivery handler may only return zero if it will call diff --git a/net/slirp.c b/net/slirp.c index c37a5ef959..87bdc9d031 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -33,7 +33,7 @@ #include "clients.h" #include "hub.h" #include "monitor/monitor.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "slirp/libslirp.h" #include "qemu-char.h" diff --git a/net/socket.c b/net/socket.c index bc2b951832..396dc8c0b1 100644 --- a/net/socket.c +++ b/net/socket.c @@ -27,10 +27,10 @@ #include "clients.h" #include "monitor/monitor.h" #include "qemu-common.h" -#include "qemu-error.h" -#include "qemu-option.h" -#include "qemu_socket.h" -#include "iov.h" +#include "qemu/error-report.h" +#include "qemu/option.h" +#include "qemu/sockets.h" +#include "qemu/iov.h" typedef struct NetSocketState { NetClientState nc; diff --git a/net/tap-bsd.c b/net/tap-bsd.c index a1c55ad3de..b48182f678 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -25,7 +25,7 @@ #include "tap_int.h" #include "qemu-common.h" #include "sysemu.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #ifdef __NetBSD__ #include diff --git a/net/tap-linux.c b/net/tap-linux.c index 3de7b3b6ce..dd4b915243 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -32,7 +32,7 @@ #include "sysemu.h" #include "qemu-common.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #define PATH_NET_TUN "/dev/net/tun" diff --git a/net/tap-solaris.c b/net/tap-solaris.c index f228fffb6d..3d5fee5542 100644 --- a/net/tap-solaris.c +++ b/net/tap-solaris.c @@ -38,7 +38,7 @@ #include #include #include -#include "qemu-error.h" +#include "qemu/error-report.h" ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen) { diff --git a/net/tap-win32.c b/net/tap-win32.c index e37d8ee458..1ddd6fa6e6 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -32,7 +32,7 @@ #include "clients.h" /* net_init_tap */ #include "net/net.h" #include "sysemu.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include #include #include diff --git a/net/tap.c b/net/tap.c index 9a677e9864..d34ff13398 100644 --- a/net/tap.c +++ b/net/tap.c @@ -38,7 +38,7 @@ #include "monitor/monitor.h" #include "sysemu.h" #include "qemu-common.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "net/tap.h" diff --git a/net/vde.c b/net/vde.c index 52d4f19fba..754a141543 100644 --- a/net/vde.c +++ b/net/vde.c @@ -28,7 +28,7 @@ #include "net/net.h" #include "clients.h" #include "qemu-common.h" -#include "qemu-option.h" +#include "qemu/option.h" typedef struct VDEState { NetClientState nc; diff --git a/notify.c b/notify.c index 12282a6745..7b7692acb2 100644 --- a/notify.c +++ b/notify.c @@ -14,7 +14,7 @@ */ #include "qemu-common.h" -#include "notify.h" +#include "qemu/notify.h" void notifier_list_init(NotifierList *list) { diff --git a/osdep.c b/osdep.c index 807e90cf97..5b51a0322e 100644 --- a/osdep.c +++ b/osdep.c @@ -47,7 +47,7 @@ extern int madvise(caddr_t, size_t, int); #include "qemu-common.h" #include "trace.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "monitor/monitor.h" static bool fips_enabled = false; diff --git a/oslib-posix.c b/oslib-posix.c index 9db9c3d8af..a737d6e0e3 100644 --- a/oslib-posix.c +++ b/oslib-posix.c @@ -51,7 +51,7 @@ extern int daemon(int, int); #include "config-host.h" #include "sysemu.h" #include "trace.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #if defined(CONFIG_VALGRIND) static int running_on_valgrind = -1; diff --git a/oslib-win32.c b/oslib-win32.c index 51b33e8b20..7f0dd07e5f 100644 --- a/oslib-win32.c +++ b/oslib-win32.c @@ -28,9 +28,9 @@ #include #include "config-host.h" #include "sysemu.h" -#include "main-loop.h" +#include "qemu/main-loop.h" #include "trace.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" void *qemu_oom_check(void *ptr) { diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index f8149ce455..174bd8bdb0 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -13,8 +13,8 @@ #include "qemu-common.h" #include "qapi/qmp/qerror.h" #include "qapi/opts-visitor.h" -#include "qemu-queue.h" -#include "qemu-option-internal.h" +#include "qemu/queue.h" +#include "qemu/option_int.h" #include "qapi/visitor-impl.h" diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c index 98f2a58efd..1334de33cc 100644 --- a/qapi/qapi-dealloc-visitor.c +++ b/qapi/qapi-dealloc-visitor.c @@ -12,7 +12,7 @@ */ #include "qapi/dealloc-visitor.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #include "qemu-common.h" #include "qapi/qmp/types.h" #include "qapi/visitor-impl.h" diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c index 8087909036..67fb127050 100644 --- a/qapi/qmp-input-visitor.c +++ b/qapi/qmp-input-visitor.c @@ -13,7 +13,7 @@ #include "qapi/qmp-input-visitor.h" #include "qapi/visitor-impl.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #include "qemu-common.h" #include "qapi/qmp/types.h" #include "qapi/qmp/qerror.h" diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c index 8015e3f88d..74a5684ed3 100644 --- a/qapi/qmp-output-visitor.c +++ b/qapi/qmp-output-visitor.c @@ -13,7 +13,7 @@ #include "qapi/qmp-output-visitor.h" #include "qapi/visitor-impl.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #include "qemu-common.h" #include "qapi/qmp/types.h" #include "qapi/qmp/qerror.h" diff --git a/qdict.c b/qdict.c index fa7a62cff4..7543ccc10f 100644 --- a/qdict.c +++ b/qdict.c @@ -16,7 +16,7 @@ #include "qapi/qmp/qbool.h" #include "qapi/qmp/qstring.h" #include "qapi/qmp/qobject.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #include "qemu-common.h" static void qdict_destroy_obj(QObject *obj); diff --git a/qemu-bridge-helper.c b/qemu-bridge-helper.c index 652eec99fd..287bfd5e38 100644 --- a/qemu-bridge-helper.c +++ b/qemu-bridge-helper.c @@ -39,7 +39,7 @@ #include #endif -#include "qemu-queue.h" +#include "qemu/queue.h" #include "net/tap-linux.h" diff --git a/qemu-char.c b/qemu-char.c index 16021c5a43..5a8d8f75a4 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -25,7 +25,7 @@ #include "monitor/monitor.h" #include "ui/console.h" #include "sysemu.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "qemu-char.h" #include "hw/usb.h" #include "hw/baum.h" @@ -94,7 +94,7 @@ #endif #endif -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "ui/qemu-spice.h" #define READ_BUF_LEN 4096 diff --git a/qemu-char.h b/qemu-char.h index 5ff1b2ba91..baa5d035fd 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -2,13 +2,13 @@ #define QEMU_CHAR_H #include "qemu-common.h" -#include "qemu-queue.h" -#include "qemu-option.h" -#include "qemu-config.h" +#include "qemu/queue.h" +#include "qemu/option.h" +#include "qemu/config-file.h" #include "block/aio.h" #include "qapi/qmp/qobject.h" #include "qapi/qmp/qstring.h" -#include "main-loop.h" +#include "qemu/main-loop.h" /* character device */ diff --git a/qemu-common.h b/qemu-common.h index e67478607b..40cd198fc1 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -12,9 +12,9 @@ #ifndef QEMU_COMMON_H #define QEMU_COMMON_H -#include "compiler.h" +#include "qemu/compiler.h" #include "config-host.h" -#include "qemu-types.h" +#include "qemu/typedefs.h" #if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__) || defined(__ia64__) #define WORDS_ALIGNED @@ -122,8 +122,8 @@ extern int use_icount; /* FIXME: Remove NEED_CPU_H. */ #ifndef NEED_CPU_H -#include "osdep.h" -#include "bswap.h" +#include "qemu/osdep.h" +#include "qemu/bswap.h" #else @@ -408,7 +408,7 @@ static inline bool is_power_of_2(uint64_t value) /* round down to the nearest power of 2*/ int64_t pow2floor(int64_t value); -#include "module.h" +#include "qemu/module.h" /* * Implementation of ULEB128 (http://en.wikipedia.org/wiki/LEB128) diff --git a/qemu-config.c b/qemu-config.c index ceec6bd155..2188c3e5ec 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -1,7 +1,7 @@ #include "qemu-common.h" -#include "qemu-error.h" -#include "qemu-option.h" -#include "qemu-config.h" +#include "qemu/error-report.h" +#include "qemu/option.h" +#include "qemu/config-file.h" #include "hw/qdev.h" #include "qapi/error.h" diff --git a/qemu-coroutine-io.c b/qemu-coroutine-io.c index 5fae9c7d47..e8ad1a4011 100644 --- a/qemu-coroutine-io.c +++ b/qemu-coroutine-io.c @@ -23,9 +23,9 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "block/coroutine.h" -#include "iov.h" +#include "qemu/iov.h" ssize_t coroutine_fn qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt, diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c index c3939ac6ef..97ef01c796 100644 --- a/qemu-coroutine-lock.c +++ b/qemu-coroutine-lock.c @@ -25,7 +25,7 @@ #include "qemu-common.h" #include "block/coroutine.h" #include "block/coroutine_int.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #include "block/aio.h" #include "trace.h" diff --git a/qemu-coroutine-sleep.c b/qemu-coroutine-sleep.c index 26e6dac2eb..169ce5ccc9 100644 --- a/qemu-coroutine-sleep.c +++ b/qemu-coroutine-sleep.c @@ -12,7 +12,7 @@ */ #include "block/coroutine.h" -#include "qemu-timer.h" +#include "qemu/timer.h" typedef struct CoSleepCB { QEMUTimer *ts; diff --git a/qemu-img.c b/qemu-img.c index 2e5ca5c964..4c8e2f3849 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -25,9 +25,9 @@ #include "qapi/qmp-output-visitor.h" #include "qapi/qmp/qjson.h" #include "qemu-common.h" -#include "qemu-option.h" -#include "qemu-error.h" -#include "osdep.h" +#include "qemu/option.h" +#include "qemu/error-report.h" +#include "qemu/osdep.h" #include "sysemu.h" #include "block/block_int.h" #include diff --git a/qemu-io.c b/qemu-io.c index e0e47423d7..61880932b3 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -15,7 +15,7 @@ #include #include "qemu-common.h" -#include "main-loop.h" +#include "qemu/main-loop.h" #include "block/block_int.h" #include "cmd.h" #include "trace/control.h" diff --git a/qemu-log.c b/qemu-log.c index a4c3d1f2e3..b655b305ea 100644 --- a/qemu-log.c +++ b/qemu-log.c @@ -18,7 +18,7 @@ */ #include "qemu-common.h" -#include "qemu-log.h" +#include "qemu/log.h" #ifdef WIN32 static const char *logfilename = "qemu.log"; diff --git a/qemu-option.c b/qemu-option.c index ebd3537063..f532b765a0 100644 --- a/qemu-option.c +++ b/qemu-option.c @@ -27,11 +27,11 @@ #include #include "qemu-common.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "qapi/qmp/types.h" #include "qapi/error.h" #include "qapi/qmp/qerror.h" -#include "qemu-option-internal.h" +#include "qemu/option_int.h" /* * Extracts the name of an option from the parameter string (p points at the diff --git a/qemu-progress.c b/qemu-progress.c index 5f1b8dfb97..08d67949a1 100644 --- a/qemu-progress.c +++ b/qemu-progress.c @@ -23,7 +23,7 @@ */ #include "qemu-common.h" -#include "osdep.h" +#include "qemu/osdep.h" #include "sysemu.h" #include diff --git a/qemu-seccomp.h b/qemu-seccomp.h index b2fc3f8c3c..1189fa241d 100644 --- a/qemu-seccomp.h +++ b/qemu-seccomp.h @@ -16,7 +16,7 @@ #define QEMU_SECCOMP_H #include -#include "osdep.h" +#include "qemu/osdep.h" int seccomp_start(void); #endif diff --git a/qemu-sockets.c b/qemu-sockets.c index cea0a4b8ac..3537bf3d45 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -23,9 +23,9 @@ #include #include "monitor/monitor.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "qemu-common.h" /* for qemu_isdigit */ -#include "main-loop.h" +#include "qemu/main-loop.h" #ifndef AI_ADDRCONFIG # define AI_ADDRCONFIG 0 diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c index 4ef9c7b3f8..7be292ed68 100644 --- a/qemu-thread-posix.c +++ b/qemu-thread-posix.c @@ -20,7 +20,7 @@ #include #include #include -#include "qemu-thread.h" +#include "qemu/thread.h" static void error_exit(int err, const char *msg) { diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c index 4b3db60f5c..8037b39045 100644 --- a/qemu-thread-win32.c +++ b/qemu-thread-win32.c @@ -11,7 +11,7 @@ * */ #include "qemu-common.h" -#include "qemu-thread.h" +#include "qemu/thread.h" #include #include #include diff --git a/qemu-timer-common.c b/qemu-timer-common.c index 755e300bc9..16f5e758b2 100644 --- a/qemu-timer-common.c +++ b/qemu-timer-common.c @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "qemu-timer.h" +#include "qemu/timer.h" /***********************************************************/ /* real time host monotonic timer */ diff --git a/qemu-timer.c b/qemu-timer.c index 8e0dccc087..80b3f2eb31 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -28,7 +28,7 @@ #include "hw/hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #ifdef CONFIG_POSIX #include #endif @@ -477,7 +477,7 @@ static void host_alarm_handler(int host_signum) #if defined(__linux__) -#include "compatfd.h" +#include "qemu/compatfd.h" static int dynticks_start_timer(struct qemu_alarm_timer *t) { diff --git a/qemu-tool.c b/qemu-tool.c index d1f46222ee..8ac45ff39b 100644 --- a/qemu-tool.c +++ b/qemu-tool.c @@ -15,12 +15,12 @@ #include "qemu-common.h" #include "monitor/monitor.h" -#include "qemu-timer.h" -#include "qemu-log.h" +#include "qemu/timer.h" +#include "qemu/log.h" #include "migration/migration.h" -#include "main-loop.h" +#include "qemu/main-loop.h" #include "sysemu.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "slirp/libslirp.h" #include diff --git a/qga/channel-posix.c b/qga/channel-posix.c index 769a559456..d4fd628907 100644 --- a/qga/channel-posix.c +++ b/qga/channel-posix.c @@ -4,8 +4,8 @@ #include #include #include -#include "osdep.h" -#include "qemu_socket.h" +#include "qemu/osdep.h" +#include "qemu/sockets.h" #include "qga/channel.h" #ifdef CONFIG_SOLARIS diff --git a/qga/commands-posix.c b/qga/commands-posix.c index cedf2ccf28..a657201e7a 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -18,8 +18,8 @@ #include "qga/guest-agent-core.h" #include "qga-qmp-commands.h" #include "qapi/qmp/qerror.h" -#include "qemu-queue.h" -#include "host-utils.h" +#include "qemu/queue.h" +#include "qemu/host-utils.h" #ifndef CONFIG_HAS_ENVIRON #ifdef __APPLE__ diff --git a/qga/main.c b/qga/main.c index ead58cc11f..ba5fa1c778 100644 --- a/qga/main.c +++ b/qga/main.c @@ -25,7 +25,7 @@ #include "qapi/qmp/qint.h" #include "qapi/qmp/qjson.h" #include "qga/guest-agent-core.h" -#include "module.h" +#include "qemu/module.h" #include "signal.h" #include "qapi/qmp/qerror.h" #include "qapi/qmp/dispatch.h" diff --git a/qlist.c b/qlist.c index c5ac2115af..1ced0de58e 100644 --- a/qlist.c +++ b/qlist.c @@ -12,7 +12,7 @@ #include "qapi/qmp/qlist.h" #include "qapi/qmp/qobject.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #include "qemu-common.h" static void qlist_destroy_obj(QObject *obj); diff --git a/qom/container.c b/qom/container.c index ceb0f0186d..5270a5ee9c 100644 --- a/qom/container.c +++ b/qom/container.c @@ -11,7 +11,7 @@ */ #include "qom/object.h" -#include "module.h" +#include "qemu/module.h" #include static TypeInfo container_info = { diff --git a/savevm.c b/savevm.c index a5205a09c3..ea01e9baf6 100644 --- a/savevm.c +++ b/savevm.c @@ -75,17 +75,17 @@ #include "net/net.h" #include "monitor/monitor.h" #include "sysemu.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "audio/audio.h" #include "migration/migration.h" -#include "qemu_socket.h" -#include "qemu-queue.h" -#include "qemu-timer.h" +#include "qemu/sockets.h" +#include "qemu/queue.h" +#include "qemu/timer.h" #include "cpus.h" #include "exec/memory.h" #include "qmp-commands.h" #include "trace.h" -#include "bitops.h" +#include "qemu/bitops.h" #define SELF_ANNOUNCE_ROUNDS 5 diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index eccc28daee..e06332bd55 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -367,7 +367,7 @@ def gen_command_def_prologue(prefix="", proxy=False): */ #include "qemu-common.h" -#include "module.h" +#include "qemu/module.h" #include "qapi/qmp/qerror.h" #include "qapi/qmp/types.h" #include "qapi/qmp/dispatch.h" diff --git a/slirp/if.c b/slirp/if.c index 533295dd07..dcd5fafe5d 100644 --- a/slirp/if.c +++ b/slirp/if.c @@ -6,7 +6,7 @@ */ #include -#include "qemu-timer.h" +#include "qemu/timer.h" static void ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead) diff --git a/slirp/ip_input.c b/slirp/ip_input.c index 6f4cff8fdd..880bdfd3cc 100644 --- a/slirp/ip_input.c +++ b/slirp/ip_input.c @@ -39,7 +39,7 @@ */ #include -#include +#include #include "ip_icmp.h" static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp); diff --git a/slirp/sbuf.c b/slirp/sbuf.c index 637f8fea3d..08ec2b4f44 100644 --- a/slirp/sbuf.c +++ b/slirp/sbuf.c @@ -6,7 +6,7 @@ */ #include -#include +#include static void sbappendsb(struct sbuf *sb, struct mbuf *m); diff --git a/slirp/slirp.c b/slirp/slirp.c index 3395d509a2..4b51a67e7d 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "qemu-char.h" #include "slirp.h" #include "hw/hw.h" diff --git a/slirp/slirp.h b/slirp/slirp.h index 0107b07e66..dfc3e3a2b8 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -133,8 +133,8 @@ void free(void *ptr); #include "debug.h" -#include "qemu-queue.h" -#include "qemu_socket.h" +#include "qemu/queue.h" +#include "qemu/sockets.h" #include "libslirp.h" #include "ip.h" diff --git a/spice-qemu-char.c b/spice-qemu-char.c index 5f95c937f3..41b1657ccd 100644 --- a/spice-qemu-char.c +++ b/spice-qemu-char.c @@ -5,7 +5,7 @@ #include #include -#include "osdep.h" +#include "qemu/osdep.h" #define dprintf(_scd, _level, _fmt, ...) \ do { \ diff --git a/stubs/fd-register.c b/stubs/fd-register.c index 813b6dd7c0..d0c34fd2a3 100644 --- a/stubs/fd-register.c +++ b/stubs/fd-register.c @@ -1,5 +1,5 @@ #include "qemu-common.h" -#include "main-loop.h" +#include "qemu/main-loop.h" void qemu_fd_register(int fd) { diff --git a/stubs/set-fd-handler.c b/stubs/set-fd-handler.c index 4807b5dc22..fc874d33fe 100644 --- a/stubs/set-fd-handler.c +++ b/stubs/set-fd-handler.c @@ -1,5 +1,5 @@ #include "qemu-common.h" -#include "main-loop.h" +#include "qemu/main-loop.h" int qemu_set_fd_handler2(int fd, IOCanReadHandler *fd_read_poll, diff --git a/sysemu.h b/sysemu.h index 1b6add2dc3..8eaa4707a0 100644 --- a/sysemu.h +++ b/sysemu.h @@ -2,13 +2,13 @@ #define SYSEMU_H /* Misc. things related to the system emulator. */ -#include "qemu-types.h" -#include "qemu-option.h" -#include "qemu-queue.h" -#include "qemu-timer.h" +#include "qemu/typedefs.h" +#include "qemu/option.h" +#include "qemu/queue.h" +#include "qemu/timer.h" #include "qapi-types.h" -#include "notify.h" -#include "main-loop.h" +#include "qemu/notify.h" +#include "qemu/main-loop.h" /* vl.c */ diff --git a/target-alpha/int_helper.c b/target-alpha/int_helper.c index 1d832f0b57..c9b42b6ed4 100644 --- a/target-alpha/int_helper.c +++ b/target-alpha/int_helper.c @@ -19,7 +19,7 @@ #include "cpu.h" #include "helper.h" -#include "host-utils.h" +#include "qemu/host-utils.h" uint64_t helper_umulh(uint64_t op1, uint64_t op2) diff --git a/target-alpha/sys_helper.c b/target-alpha/sys_helper.c index 40ca49c883..2bc2b02815 100644 --- a/target-alpha/sys_helper.c +++ b/target-alpha/sys_helper.c @@ -20,7 +20,7 @@ #include "cpu.h" #include "helper.h" #include "sysemu.h" -#include "qemu-timer.h" +#include "qemu/timer.h" uint64_t helper_load_pcc(CPUAlphaState *env) diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 2d0d891128..c94126737f 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -19,7 +19,7 @@ #include "cpu.h" #include "disas/disas.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "tcg-op.h" #include "helper.h" diff --git a/target-arm/helper.c b/target-arm/helper.c index 1f7a3c04c3..eef2acd18a 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1,9 +1,9 @@ #include "cpu.h" #include "exec/gdbstub.h" #include "helper.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "sysemu.h" -#include "bitops.h" +#include "qemu/bitops.h" #ifndef CONFIG_USER_ONLY static inline int get_phys_addr(CPUARMState *env, uint32_t address, diff --git a/target-arm/translate.c b/target-arm/translate.c index 988b5428d4..724e00f7cf 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -27,7 +27,7 @@ #include "cpu.h" #include "disas/disas.h" #include "tcg-op.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "helper.h" #define GEN_HELPER 1 diff --git a/target-cris/helper.c b/target-cris/helper.c index 324fe052f5..8407a6d880 100644 --- a/target-cris/helper.c +++ b/target-cris/helper.c @@ -20,7 +20,7 @@ #include "cpu.h" #include "mmu.h" -#include "host-utils.h" +#include "qemu/host-utils.h" //#define CRIS_HELPER_DEBUG diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c index cd0e17e099..79bff38663 100644 --- a/target-cris/op_helper.c +++ b/target-cris/op_helper.c @@ -21,7 +21,7 @@ #include "cpu.h" #include "mmu.h" #include "helper.h" -#include "host-utils.h" +#include "qemu/host-utils.h" //#define CRIS_OP_HELPER_DEBUG diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 150c4dfb0c..8abc5561e9 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -24,8 +24,8 @@ #include "cpu.h" #include "kvm.h" -#include "qemu-option.h" -#include "qemu-config.h" +#include "qemu/option.h" +#include "qemu/config-file.h" #include "qapi/qmp/qerror.h" #include "qapi/visitor.h" diff --git a/target-i386/excp_helper.c b/target-i386/excp_helper.c index aaa5ca2090..64c8346d3b 100644 --- a/target-i386/excp_helper.c +++ b/target-i386/excp_helper.c @@ -18,7 +18,7 @@ */ #include "cpu.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "sysemu.h" #include "helper.h" diff --git a/target-i386/int_helper.c b/target-i386/int_helper.c index f39747e806..84b812dcca 100644 --- a/target-i386/int_helper.c +++ b/target-i386/int_helper.c @@ -18,7 +18,7 @@ */ #include "cpu.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "helper.h" //#define DEBUG_MULDIV diff --git a/target-i386/kvm.c b/target-i386/kvm.c index f7c95d5424..340ed3f33e 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -26,8 +26,8 @@ #include "kvm_i386.h" #include "cpu.h" #include "exec/gdbstub.h" -#include "host-utils.h" -#include "qemu-config.h" +#include "qemu/host-utils.h" +#include "qemu/config-file.h" #include "hw/pc.h" #include "hw/apic.h" #include "exec/ioport.h" diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c index be795d71eb..c2a99ee9bc 100644 --- a/target-i386/seg_helper.c +++ b/target-i386/seg_helper.c @@ -19,7 +19,7 @@ */ #include "cpu.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "helper.h" //#define DEBUG_PCALL diff --git a/target-lm32/helper.c b/target-lm32/helper.c index 0ed7cfda18..d76ea3fe09 100644 --- a/target-lm32/helper.c +++ b/target-lm32/helper.c @@ -18,7 +18,7 @@ */ #include "cpu.h" -#include "host-utils.h" +#include "qemu/host-utils.h" int cpu_lm32_handle_mmu_fault(CPULM32State *env, target_ulong address, int rw, int mmu_idx) diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c index 27b3cef25c..53410b176e 100644 --- a/target-lm32/op_helper.c +++ b/target-lm32/op_helper.c @@ -1,7 +1,7 @@ #include #include "cpu.h" #include "helper.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "hw/lm32_pic.h" #include "hw/lm32_juart.h" diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 1c9b5ec8d4..e763195f86 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -21,7 +21,7 @@ #include "cpu.h" #include "disas/disas.h" #include "tcg-op.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "helpers.h" #define GEN_HELPER 1 diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c index 530e0b5fb0..97aedc52bb 100644 --- a/target-microblaze/helper.c +++ b/target-microblaze/helper.c @@ -19,7 +19,7 @@ */ #include "cpu.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #define D(x) #define DMMU(x) diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c index 343dcc15e7..1c62f3c68f 100644 --- a/target-microblaze/op_helper.c +++ b/target-microblaze/op_helper.c @@ -21,7 +21,7 @@ #include #include "cpu.h" #include "helper.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #define D(x) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 157f59e6bf..e85edce6fa 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -18,7 +18,7 @@ */ #include #include "cpu.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "helper.h" diff --git a/target-openrisc/int_helper.c b/target-openrisc/int_helper.c index 2fdfd27712..20f9837e6a 100644 --- a/target-openrisc/int_helper.c +++ b/target-openrisc/int_helper.c @@ -21,7 +21,7 @@ #include "cpu.h" #include "helper.h" #include "exception.h" -#include "host-utils.h" +#include "qemu/host-utils.h" target_ulong HELPER(ff1)(target_ulong x) { diff --git a/target-openrisc/interrupt.c b/target-openrisc/interrupt.c index 226ce43513..7f2c025da2 100644 --- a/target-openrisc/interrupt.c +++ b/target-openrisc/interrupt.c @@ -20,7 +20,7 @@ #include "cpu.h" #include "qemu-common.h" #include "exec/gdbstub.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #ifndef CONFIG_USER_ONLY #include "hw/loader.h" #endif diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c index 4eee44434f..836465259a 100644 --- a/target-openrisc/mmu.c +++ b/target-openrisc/mmu.c @@ -21,7 +21,7 @@ #include "cpu.h" #include "qemu-common.h" #include "exec/gdbstub.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #ifndef CONFIG_USER_ONLY #include "hw/loader.h" #endif diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index 5883347fa7..1e1b30cdcb 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -23,9 +23,9 @@ #include "disas/disas.h" #include "tcg-op.h" #include "qemu-common.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "config.h" -#include "bitops.h" +#include "qemu/bitops.h" #include "helper.h" #define GEN_HELPER 1 diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c index f39b4f682a..783079d995 100644 --- a/target-ppc/int_helper.c +++ b/target-ppc/int_helper.c @@ -17,7 +17,7 @@ * License along with this library; if not, see . */ #include "cpu.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "helper.h" #include "helper_regs.h" diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 3f5df5772f..2546c577f6 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -23,7 +23,7 @@ #include #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysemu.h" #include "kvm.h" #include "kvm_ppc.h" diff --git a/target-ppc/kvm_ppc.c b/target-ppc/kvm_ppc.c index a2e49cd423..2de59fd43b 100644 --- a/target-ppc/kvm_ppc.c +++ b/target-ppc/kvm_ppc.c @@ -12,7 +12,7 @@ */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "kvm_ppc.h" #include "device_tree.h" diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c index 2d7a349c32..902b1cd823 100644 --- a/target-ppc/mem_helper.c +++ b/target-ppc/mem_helper.c @@ -17,7 +17,7 @@ * License along with this library; if not, see . */ #include "cpu.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "helper.h" #include "helper_regs.h" diff --git a/target-ppc/translate.c b/target-ppc/translate.c index a74d76b5a6..798b7acfc9 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -21,7 +21,7 @@ #include "cpu.h" #include "disas/disas.h" #include "tcg-op.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "helper.h" #define GEN_HELPER 1 diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c index 619b202b92..249f063d94 100644 --- a/target-s390x/cpu.c +++ b/target-s390x/cpu.c @@ -22,7 +22,7 @@ #include "cpu.h" #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" /* CPUClass::reset() */ diff --git a/target-s390x/helper.c b/target-s390x/helper.c index 6e9b209713..8e135457a3 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -20,7 +20,7 @@ #include "cpu.h" #include "exec/gdbstub.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #ifndef CONFIG_USER_ONLY #include "sysemu.h" #endif diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c index f202a7e1da..b683709860 100644 --- a/target-s390x/int_helper.c +++ b/target-s390x/int_helper.c @@ -19,7 +19,7 @@ */ #include "cpu.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "helper.h" /* #define DEBUG_HELPER */ diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 94de764264..dc70699919 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -25,7 +25,7 @@ #include #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "sysemu.h" #include "kvm.h" #include "cpu.h" diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index a3336e16b0..2e73d30756 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -20,11 +20,11 @@ #include "cpu.h" #include "exec/memory.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "helper.h" #include #include "kvm.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #ifdef CONFIG_KVM #include #endif diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 28e61c54b8..9e34741311 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -32,7 +32,7 @@ #include "cpu.h" #include "disas/disas.h" #include "tcg-op.h" -#include "qemu-log.h" +#include "qemu/log.h" /* global register indexes */ static TCGv_ptr cpu_env; diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 0ed511a399..04b6659909 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -3,7 +3,7 @@ #include "config.h" #include "qemu-common.h" -#include "bswap.h" +#include "qemu/bswap.h" #if !defined(TARGET_SPARC64) #define TARGET_LONG_BITS 32 diff --git a/target-sparc/helper.c b/target-sparc/helper.c index 3c8e865eef..e0d78f3852 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -18,7 +18,7 @@ */ #include "cpu.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "helper.h" #include "sysemu.h" diff --git a/target-sparc/machine.c b/target-sparc/machine.c index eb4d87f158..a353dabdd9 100644 --- a/target-sparc/machine.c +++ b/target-sparc/machine.c @@ -1,6 +1,6 @@ #include "hw/hw.h" #include "hw/boards.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "cpu.h" diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c index 2adbd1675d..ff4f628404 100644 --- a/target-unicore32/helper.c +++ b/target-unicore32/helper.c @@ -12,7 +12,7 @@ #include "cpu.h" #include "exec/gdbstub.h" #include "helper.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "ui/console.h" #undef DEBUG_UC32 diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index 218e95eaca..f4498bcb14 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -17,7 +17,7 @@ #include "cpu.h" #include "disas/disas.h" #include "tcg-op.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "helper.h" #define GEN_HELPER 1 diff --git a/target-xtensa/core-dc232b.c b/target-xtensa/core-dc232b.c index d1a594cda2..0bfcf2414c 100644 --- a/target-xtensa/core-dc232b.c +++ b/target-xtensa/core-dc232b.c @@ -28,7 +28,7 @@ #include "cpu.h" #include "exec/exec-all.h" #include "exec/gdbstub.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "core-dc232b/core-isa.h" #include "overlay_tool.h" diff --git a/target-xtensa/core-dc233c.c b/target-xtensa/core-dc233c.c index ead6b3b128..11acbf3580 100644 --- a/target-xtensa/core-dc233c.c +++ b/target-xtensa/core-dc233c.c @@ -29,7 +29,7 @@ #include "exec/exec-all.h" #include "exec/gdbstub.h" #include "qemu-common.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "core-dc233c/core-isa.h" #include "overlay_tool.h" diff --git a/target-xtensa/core-fsf.c b/target-xtensa/core-fsf.c index a387aeeca5..d4660edde9 100644 --- a/target-xtensa/core-fsf.c +++ b/target-xtensa/core-fsf.c @@ -28,7 +28,7 @@ #include "cpu.h" #include "exec/exec-all.h" #include "exec/gdbstub.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #include "core-fsf/core-isa.h" #include "overlay_tool.h" diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c index 3d7a399008..94c03a1d3c 100644 --- a/target-xtensa/helper.c +++ b/target-xtensa/helper.c @@ -28,7 +28,7 @@ #include "cpu.h" #include "exec/exec-all.h" #include "exec/gdbstub.h" -#include "host-utils.h" +#include "qemu/host-utils.h" #if !defined(CONFIG_USER_ONLY) #include "hw/loader.h" #endif diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c index a93abcb1dd..3813a72626 100644 --- a/target-xtensa/op_helper.c +++ b/target-xtensa/op_helper.c @@ -27,7 +27,7 @@ #include "cpu.h" #include "helper.h" -#include "host-utils.h" +#include "qemu/host-utils.h" static void do_unaligned_access(CPUXtensaState *env, target_ulong addr, int is_write, int is_user, uintptr_t retaddr); diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 3c2d1853d6..f61a497d21 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -34,7 +34,7 @@ #include "exec/exec-all.h" #include "disas/disas.h" #include "tcg-op.h" -#include "qemu-log.h" +#include "qemu/log.h" #include "sysemu.h" #include "helper.h" diff --git a/target-xtensa/xtensa-semi.c b/target-xtensa/xtensa-semi.c index 851ff546f0..5fe0361c02 100644 --- a/target-xtensa/xtensa-semi.c +++ b/target-xtensa/xtensa-semi.c @@ -31,7 +31,7 @@ #include #include "cpu.h" #include "helper.h" -#include "qemu-log.h" +#include "qemu/log.h" enum { TARGET_SYS_exit = 1, diff --git a/tcg/tcg.c b/tcg/tcg.c index cb193f2683..ede51a3960 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -37,9 +37,9 @@ #endif #include "qemu-common.h" -#include "cache-utils.h" -#include "host-utils.h" -#include "qemu-timer.h" +#include "qemu/cache-utils.h" +#include "qemu/host-utils.h" +#include "qemu/timer.h" /* Note: the long term plan is to reduce the dependancies on the QEMU CPU definitions. Currently they are used for qemu_ld/st diff --git a/tests/libqtest.c b/tests/libqtest.c index 71b84c12dd..913fa0535c 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -26,8 +26,8 @@ #include #include -#include "compiler.h" -#include "osdep.h" +#include "qemu/compiler.h" +#include "qemu/osdep.h" #define MAX_IRQ 256 diff --git a/tests/tcg/test-i386-fprem.c b/tests/tcg/test-i386-fprem.c index 8c7a4d1ff4..e91fb1ae93 100644 --- a/tests/tcg/test-i386-fprem.c +++ b/tests/tcg/test-i386-fprem.c @@ -22,8 +22,8 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ -#include "compiler.h" -#include "osdep.h" +#include "qemu/compiler.h" +#include "qemu/osdep.h" #include #include diff --git a/tests/tcg/test-i386.c b/tests/tcg/test-i386.c index 40392ac51d..6dc730d882 100644 --- a/tests/tcg/test-i386.c +++ b/tests/tcg/test-i386.c @@ -17,7 +17,7 @@ * along with this program; if not, see . */ #define _GNU_SOURCE -#include "compiler.h" +#include "qemu/compiler.h" #include #include #include diff --git a/tests/test-iov.c b/tests/test-iov.c index cbe7a8955c..a480bc8725 100644 --- a/tests/test-iov.c +++ b/tests/test-iov.c @@ -1,7 +1,7 @@ #include #include "qemu-common.h" -#include "iov.h" -#include "qemu_socket.h" +#include "qemu/iov.h" +#include "qemu/sockets.h" /* create a randomly-sized iovec with random vectors */ static void iov_random(struct iovec **iovp, unsigned *iov_cntp) diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c index 61b533a071..5a3e82a854 100644 --- a/tests/test-qmp-commands.c +++ b/tests/test-qmp-commands.c @@ -3,7 +3,7 @@ #include "qapi/qmp/types.h" #include "test-qmp-commands.h" #include "qapi/qmp/dispatch.h" -#include "module.h" +#include "qemu/module.h" #include "qapi/qmp-input-visitor.h" #include "tests/test-qapi-types.h" #include "tests/test-qapi-visit.h" diff --git a/thread-pool.c b/thread-pool.c index 4c73a7db97..e3ca64d790 100644 --- a/thread-pool.c +++ b/thread-pool.c @@ -15,13 +15,13 @@ * GNU GPL, version 2 or (at your option) any later version. */ #include "qemu-common.h" -#include "qemu-queue.h" -#include "qemu-thread.h" -#include "osdep.h" +#include "qemu/queue.h" +#include "qemu/thread.h" +#include "qemu/osdep.h" #include "block/coroutine.h" #include "trace.h" #include "block/block_int.h" -#include "event_notifier.h" +#include "qemu/event_notifier.h" #include "block/thread-pool.h" static void do_spawn_thread(void); diff --git a/trace/simple.c b/trace/simple.c index d83681b227..ce17d64bd7 100644 --- a/trace/simple.c +++ b/trace/simple.c @@ -16,7 +16,7 @@ #include #include #endif -#include "qemu-timer.h" +#include "qemu/timer.h" #include "trace.h" #include "trace/control.h" diff --git a/translate-all.c b/translate-all.c index e0cdad38c7..b621748ec0 100644 --- a/translate-all.c +++ b/translate-all.c @@ -35,7 +35,7 @@ #include "cpu.h" #include "disas/disas.h" #include "tcg.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "exec/memory.h" #include "exec/address-spaces.h" #if defined(CONFIG_USER_ONLY) diff --git a/ui/console.c b/ui/console.c index 60bfb72ac2..a4bff8ce8a 100644 --- a/ui/console.c +++ b/ui/console.c @@ -23,7 +23,7 @@ */ #include "qemu-common.h" #include "ui/console.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "qmp-commands.h" #include "qemu-char.h" diff --git a/ui/sdl_zoom.c b/ui/sdl_zoom.c index a986c7c14c..122027cb36 100644 --- a/ui/sdl_zoom.c +++ b/ui/sdl_zoom.c @@ -12,7 +12,7 @@ */ #include "sdl_zoom.h" -#include "osdep.h" +#include "qemu/osdep.h" #include #include diff --git a/ui/spice-core.c b/ui/spice-core.c index 962475de6b..8727bf49ca 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -23,17 +23,17 @@ #include "qemu-common.h" #include "ui/qemu-spice.h" -#include "qemu-thread.h" -#include "qemu-timer.h" -#include "qemu-queue.h" +#include "qemu/thread.h" +#include "qemu/timer.h" +#include "qemu/queue.h" #include "qemu-x509.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "qmp-commands.h" #include "qapi/qmp/qint.h" #include "qapi/qmp/qbool.h" #include "qapi/qmp/qstring.h" #include "qapi/qmp/qjson.h" -#include "notify.h" +#include "qemu/notify.h" #include "migration/migration.h" #include "monitor/monitor.h" #include "hw/hw.h" diff --git a/ui/spice-display.c b/ui/spice-display.c index 56ebf80805..a19b3d95fb 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -17,8 +17,8 @@ #include "qemu-common.h" #include "ui/qemu-spice.h" -#include "qemu-timer.h" -#include "qemu-queue.h" +#include "qemu/timer.h" +#include "qemu/queue.h" #include "monitor/monitor.h" #include "ui/console.h" #include "sysemu.h" diff --git a/ui/vnc-auth-sasl.h b/ui/vnc-auth-sasl.h index ee243a9d64..8091d689cb 100644 --- a/ui/vnc-auth-sasl.h +++ b/ui/vnc-auth-sasl.h @@ -32,7 +32,7 @@ typedef struct VncStateSASL VncStateSASL; typedef struct VncDisplaySASL VncDisplaySASL; -#include "acl.h" +#include "qemu/acl.h" struct VncStateSASL { sasl_conn_t *conn; diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c index 09199ef584..4ddea7d4f5 100644 --- a/ui/vnc-enc-tight.c +++ b/ui/vnc-enc-tight.c @@ -44,7 +44,7 @@ #include #endif -#include "bswap.h" +#include "qemu/bswap.h" #include "qapi/qmp/qint.h" #include "vnc.h" #include "vnc-enc-tight.h" diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c index 57c091683b..0bfc0c5485 100644 --- a/ui/vnc-jobs.c +++ b/ui/vnc-jobs.c @@ -28,7 +28,7 @@ #include "vnc.h" #include "vnc-jobs.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" /* * Locking: diff --git a/ui/vnc-palette.h b/ui/vnc-palette.h index bfc7fe642e..d02f0236c1 100644 --- a/ui/vnc-palette.h +++ b/ui/vnc-palette.h @@ -30,7 +30,7 @@ #define VNC_PALETTE_H #include "qapi/qmp/qlist.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #include #include diff --git a/ui/vnc-tls.c b/ui/vnc-tls.c index a7f7d07ac8..56292636d7 100644 --- a/ui/vnc-tls.c +++ b/ui/vnc-tls.c @@ -26,7 +26,7 @@ #include "qemu-x509.h" #include "vnc.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #if defined(_VNC_DEBUG) && _VNC_DEBUG >= 2 /* Very verbose, so only enabled for _VNC_DEBUG >= 2 */ diff --git a/ui/vnc-tls.h b/ui/vnc-tls.h index 2b93633896..36a2227fec 100644 --- a/ui/vnc-tls.h +++ b/ui/vnc-tls.h @@ -31,7 +31,7 @@ #include #include -#include "acl.h" +#include "qemu/acl.h" enum { VNC_WIREMODE_CLEAR, diff --git a/ui/vnc.c b/ui/vnc.c index dad2ddee29..d9e5315e79 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -27,12 +27,12 @@ #include "vnc.h" #include "vnc-jobs.h" #include "sysemu.h" -#include "qemu_socket.h" -#include "qemu-timer.h" -#include "acl.h" +#include "qemu/sockets.h" +#include "qemu/timer.h" +#include "qemu/acl.h" #include "qapi/qmp/types.h" #include "qmp-commands.h" -#include "osdep.h" +#include "qemu/osdep.h" #define VNC_REFRESH_INTERVAL_BASE 30 #define VNC_REFRESH_INTERVAL_INC 50 diff --git a/ui/vnc.h b/ui/vnc.h index e5c043ff45..8b40f09117 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -28,12 +28,12 @@ #define __QEMU_VNC_H #include "qemu-common.h" -#include "qemu-queue.h" -#include "qemu-thread.h" +#include "qemu/queue.h" +#include "qemu/thread.h" #include "ui/console.h" #include "monitor/monitor.h" #include "audio/audio.h" -#include "bitmap.h" +#include "qemu/bitmap.h" #include #include diff --git a/uri.c b/uri.c index 138547b821..4238729b83 100644 --- a/uri.c +++ b/uri.c @@ -55,7 +55,7 @@ #include #include -#include "uri.h" +#include "qemu/uri.h" static void uri_clean(URI *uri); diff --git a/vl.c b/vl.c index 2debde0a4a..9b80e7abc4 100644 --- a/vl.c +++ b/vl.c @@ -28,7 +28,7 @@ #include #include #include -#include "bitmap.h" +#include "qemu/bitmap.h" /* Needed early for CONFIG_BSD etc. */ #include "config-host.h" @@ -133,9 +133,9 @@ int main(int argc, char **argv) #include "ui/console.h" #include "sysemu.h" #include "exec/gdbstub.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "qemu-char.h" -#include "cache-utils.h" +#include "qemu/cache-utils.h" #include "blockdev.h" #include "hw/block-common.h" #include "migration/block.h" @@ -144,11 +144,11 @@ int main(int argc, char **argv) #include "migration/migration.h" #include "kvm.h" #include "qapi/qmp/qjson.h" -#include "qemu-option.h" -#include "qemu-config.h" +#include "qemu/option.h" +#include "qemu/config-file.h" #include "qemu-options.h" #include "qmp-commands.h" -#include "main-loop.h" +#include "qemu/main-loop.h" #ifdef CONFIG_VIRTFS #include "fsdev/qemu-fsdev.h" #endif @@ -156,16 +156,16 @@ int main(int argc, char **argv) #include "disas/disas.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "slirp/libslirp.h" #include "trace.h" #include "trace/control.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #include "cpus.h" #include "arch_init.h" -#include "osdep.h" +#include "qemu/osdep.h" #include "ui/qemu-spice.h" #include "qapi/string-input-visitor.h" diff --git a/xen-all.c b/xen-all.c index 95d383f41f..6965626db8 100644 --- a/xen-all.c +++ b/xen-all.c @@ -16,7 +16,7 @@ #include "hw/xen_backend.h" #include "qmp-commands.h" -#include "range.h" +#include "qemu/range.h" #include "xen-mapcache.h" #include "trace.h" #include "exec/address-spaces.h" diff --git a/xen-mapcache.c b/xen-mapcache.c index 31c06dc950..8f4648cc32 100644 --- a/xen-mapcache.c +++ b/xen-mapcache.c @@ -14,7 +14,7 @@ #include "hw/xen_backend.h" #include "blockdev.h" -#include "bitmap.h" +#include "qemu/bitmap.h" #include #include From 9c17d615a66ebd655871bf891ec0fe901ad8b332 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Dec 2012 18:20:04 +0100 Subject: [PATCH 2065/2270] softmmu: move include files to include/sysemu/ Signed-off-by: Paolo Bonzini --- arch_init.c | 6 +++--- audio/audio.c | 2 +- audio/winwaveaudio.c | 2 +- balloon.c | 4 ++-- block-migration.c | 2 +- block.c | 2 +- block/vdi.c | 2 +- blockdev-nbd.c | 4 ++-- blockdev.c | 6 +++--- cpu-exec.c | 2 +- cpus.c | 10 +++++----- device_tree.c | 2 +- dma-helpers.c | 2 +- dump-stub.c | 2 +- dump.c | 8 ++++---- exec.c | 6 +++--- gdbstub.c | 4 ++-- hw/ac97.c | 2 +- hw/acpi.c | 2 +- hw/acpi_ich9.c | 4 ++-- hw/acpi_piix4.c | 2 +- hw/alpha_dp264.c | 2 +- hw/alpha_pci.c | 2 +- hw/alpha_typhoon.c | 2 +- hw/apb_pci.c | 2 +- hw/apic_common.c | 2 +- hw/arm_boot.c | 4 ++-- hw/arm_sysctl.c | 2 +- hw/axis_dev88.c | 2 +- hw/block-common.c | 2 +- hw/boards.h | 2 +- hw/bonito.c | 2 +- hw/cbus.c | 2 +- hw/collie.c | 2 +- hw/cuda.c | 2 +- hw/device-hotplug.c | 4 ++-- hw/e1000.c | 4 ++-- hw/eepro100.c | 4 ++-- hw/es1370.c | 2 +- hw/etraxfs_dma.c | 2 +- hw/etraxfs_timer.c | 2 +- hw/exynos4210.c | 2 +- hw/exynos4210_rtc.c | 2 +- hw/exynos4210_uart.c | 2 +- hw/exynos4_boards.c | 2 +- hw/fdc.c | 4 ++-- hw/fw_cfg.c | 2 +- hw/gumstix.c | 2 +- hw/highbank.c | 4 ++-- hw/ide/ahci.c | 2 +- hw/ide/cmd646.c | 4 ++-- hw/ide/core.c | 6 +++--- hw/ide/ich.c | 2 +- hw/ide/internal.h | 4 ++-- hw/ide/isa.c | 2 +- hw/ide/macio.c | 2 +- hw/ide/microdrive.c | 2 +- hw/ide/mmio.c | 2 +- hw/ide/pci.c | 2 +- hw/ide/piix.c | 6 +++--- hw/ide/qdev.c | 6 +++--- hw/ide/via.c | 4 ++-- hw/imx_ccm.c | 2 +- hw/imx_serial.c | 2 +- hw/integratorcp.c | 2 +- hw/intel-hda.c | 2 +- hw/isa-bus.c | 2 +- hw/ivshmem.c | 2 +- hw/kvm/apic.c | 2 +- hw/kvm/clock.c | 4 ++-- hw/kvm/i8254.c | 4 ++-- hw/kvm/i8259.c | 2 +- hw/kvm/ioapic.c | 2 +- hw/kvm/pci-assign.c | 2 +- hw/kvmvapic.c | 6 +++--- hw/kzm.c | 2 +- hw/lan9118.c | 2 +- hw/leon3.c | 2 +- hw/lm32_boards.c | 2 +- hw/lm32_sys.c | 2 +- hw/loader.c | 2 +- hw/lpc_ich9.c | 2 +- hw/lsi53c895a.c | 2 +- hw/m25p80.c | 2 +- hw/m48t59.c | 2 +- hw/mac_nvram.c | 2 +- hw/mainstone.c | 2 +- hw/mc146818rtc.c | 2 +- hw/mcf5206.c | 2 +- hw/mcf5208.c | 2 +- hw/megasas.c | 2 +- hw/microblaze_boot.c | 2 +- hw/milkymist-memcard.c | 4 ++-- hw/milkymist-sysctl.c | 2 +- hw/milkymist.c | 4 ++-- hw/mips_fulong2e.c | 4 ++-- hw/mips_jazz.c | 6 +++--- hw/mips_malta.c | 6 +++--- hw/mips_mipssim.c | 2 +- hw/mips_r4k.c | 4 ++-- hw/mpc8544_guts.c | 2 +- hw/multiboot.c | 2 +- hw/musicpal.c | 4 ++-- hw/nand.c | 2 +- hw/ne2000.c | 2 +- hw/nseries.c | 4 ++-- hw/omap1.c | 4 ++-- hw/omap2.c | 4 ++-- hw/omap_sx1.c | 2 +- hw/onenand.c | 2 +- hw/opencores_eth.c | 2 +- hw/openrisc_sim.c | 4 ++-- hw/palm.c | 2 +- hw/pam.c | 2 +- hw/parallel.c | 2 +- hw/pc.c | 8 ++++---- hw/pc_piix.c | 8 ++++---- hw/pc_q35.c | 4 ++-- hw/pc_sysfw.c | 6 +++--- hw/pci/pci-hotplug.c | 2 +- hw/pci/pci-stub.c | 2 +- hw/pci/pci.c | 2 +- hw/pci/pci.h | 2 +- hw/pci/pcie_aer.c | 2 +- hw/pckbd.c | 2 +- hw/pcnet-pci.c | 2 +- hw/pcnet.c | 2 +- hw/petalogix_ml605_mmu.c | 4 ++-- hw/petalogix_s3adsp1800_mmu.c | 4 ++-- hw/pl031.c | 2 +- hw/pl181.c | 2 +- hw/ppc.c | 4 ++-- hw/ppc/e500.c | 6 +++--- hw/ppc/e500plat.c | 4 ++-- hw/ppc/mpc8544ds.c | 2 +- hw/ppc405_boards.c | 4 ++-- hw/ppc405_uc.c | 2 +- hw/ppc440_bamboo.c | 6 +++--- hw/ppc_booke.c | 2 +- hw/ppc_newworld.c | 6 +++--- hw/ppc_oldworld.c | 6 +++--- hw/ppc_prep.c | 6 +++--- hw/ppce500_spin.c | 4 ++-- hw/ps2.c | 2 +- hw/pxa2xx.c | 4 ++-- hw/pxa2xx_lcd.c | 2 +- hw/pxa2xx_timer.c | 2 +- hw/qdev-monitor.c | 2 +- hw/qdev-properties.c | 2 +- hw/qdev.c | 2 +- hw/qxl.c | 2 +- hw/r2d.c | 4 ++-- hw/realview.c | 4 ++-- hw/rtl8139.c | 4 ++-- hw/s390-virtio-bus.c | 4 ++-- hw/s390-virtio.c | 6 +++--- hw/s390x/event-facility.c | 2 +- hw/s390x/sclp.c | 2 +- hw/s390x/sclpquiesce.c | 2 +- hw/scsi-bus.c | 4 ++-- hw/scsi-disk.c | 6 +++--- hw/scsi-generic.c | 2 +- hw/scsi.h | 2 +- hw/serial.h | 2 +- hw/sga.c | 2 +- hw/sh7750.c | 2 +- hw/shix.c | 2 +- hw/slavio_misc.c | 2 +- hw/smbios.c | 2 +- hw/smbus_ich9.c | 2 +- hw/spapr.c | 10 +++++----- hw/spapr.h | 2 +- hw/spapr_events.c | 4 ++-- hw/spapr_hcall.c | 4 ++-- hw/spapr_iommu.c | 4 ++-- hw/spapr_nvram.c | 2 +- hw/spapr_rtas.c | 4 ++-- hw/spapr_vio.c | 6 +++--- hw/spapr_vio.h | 2 +- hw/spitz.c | 4 ++-- hw/ssi-sd.c | 2 +- hw/strongarm.c | 2 +- hw/sun4m.c | 4 ++-- hw/sun4u.c | 4 ++-- hw/tc6393xb.c | 2 +- hw/tosa.c | 2 +- hw/twl92230.c | 2 +- hw/usb/bus.c | 2 +- hw/usb/dev-network.c | 2 +- hw/usb/dev-storage.c | 4 ++-- hw/usb/hcd-ehci.h | 4 ++-- hw/usb/hcd-uhci.c | 2 +- hw/usb/host-linux.c | 2 +- hw/usb/libhw.c | 2 +- hw/usb/redirect.c | 2 +- hw/versatilepb.c | 4 ++-- hw/vexpress.c | 4 ++-- hw/vfio_pci.c | 2 +- hw/virtex_ml507.c | 6 +++--- hw/virtio-balloon.c | 4 ++-- hw/virtio-blk.c | 2 +- hw/virtio-pci.c | 4 ++-- hw/virtio.h | 2 +- hw/vmport.c | 2 +- hw/vt82c686.c | 2 +- hw/watchdog.c | 2 +- hw/xen_backend.h | 2 +- hw/xen_devconfig.c | 2 +- hw/xen_disk.c | 2 +- hw/xen_machine_pv.c | 2 +- hw/xilinx_spi.c | 2 +- hw/xilinx_spips.c | 2 +- hw/xilinx_zynq.c | 4 ++-- hw/xtensa_lx60.c | 4 ++-- hw/xtensa_sim.c | 2 +- hw/z2.c | 4 ++-- hw/zynq_slcr.c | 2 +- arch_init.h => include/sysemu/arch_init.h | 0 balloon.h => include/sysemu/balloon.h | 0 blockdev.h => include/sysemu/blockdev.h | 0 cpus.h => include/sysemu/cpus.h | 0 device_tree.h => include/sysemu/device_tree.h | 0 dma.h => include/sysemu/dma.h | 2 +- dump.h => include/sysemu/dump.h | 0 kvm.h => include/sysemu/kvm.h | 0 .../sysemu/memory_mapping.h | 0 qemu-os-posix.h => include/sysemu/os-posix.h | 0 qemu-os-win32.h => include/sysemu/os-win32.h | 0 qtest.h => include/sysemu/qtest.h | 0 qemu-seccomp.h => include/sysemu/seccomp.h | 0 sysemu.h => include/sysemu/sysemu.h | 0 xen-mapcache.h => include/sysemu/xen-mapcache.h | 0 include/ui/spice-display.h | 2 +- kvm-all.c | 4 ++-- kvm-stub.c | 2 +- memory.c | 2 +- memory_mapping-stub.c | 2 +- memory_mapping.c | 2 +- migration.c | 2 +- monitor.c | 8 ++++---- net/tap-bsd.c | 2 +- net/tap-linux.c | 2 +- net/tap-solaris.c | 2 +- net/tap-win32.c | 2 +- net/tap.c | 2 +- os-posix.c | 2 +- os-win32.c | 2 +- oslib-posix.c | 2 +- oslib-win32.c | 2 +- qemu-char.c | 2 +- qemu-common.h | 4 ++-- qemu-img.c | 2 +- qemu-progress.c | 2 +- qemu-seccomp.c | 2 +- qemu-timer.c | 2 +- qemu-tool.c | 2 +- qmp.c | 8 ++++---- qtest.c | 6 +++--- savevm.c | 4 ++-- stubs/arch-query-cpu-def.c | 2 +- target-alpha/sys_helper.c | 2 +- target-arm/cpu.c | 2 +- target-arm/helper.c | 2 +- target-i386/arch_dump.c | 2 +- target-i386/arch_memory_mapping.c | 2 +- target-i386/cpu.c | 6 +++--- target-i386/excp_helper.c | 2 +- target-i386/helper.c | 4 ++-- target-i386/kvm.c | 4 ++-- target-i386/kvm_i386.h | 2 +- target-i386/machine.c | 2 +- target-m68k/m68k-semi.c | 2 +- target-ppc/helper.c | 4 ++-- target-ppc/kvm.c | 8 ++++---- target-ppc/kvm_ppc.c | 2 +- target-ppc/machine.c | 2 +- target-ppc/mmu_helper.c | 2 +- target-ppc/translate_init.c | 4 ++-- target-s390x/helper.c | 2 +- target-s390x/interrupt.c | 2 +- target-s390x/kvm.c | 6 +++--- target-s390x/misc_helper.c | 4 ++-- target-sparc/helper.c | 2 +- target-sparc/int32_helper.c | 2 +- target-xtensa/translate.c | 2 +- ui/cocoa.m | 2 +- ui/curses.c | 2 +- ui/input.c | 2 +- ui/keymaps.c | 2 +- ui/sdl.c | 2 +- ui/spice-core.c | 2 +- ui/spice-display.c | 2 +- ui/vnc.c | 2 +- vl.c | 16 ++++++++-------- xen-all.c | 2 +- xen-mapcache.c | 4 ++-- 296 files changed, 421 insertions(+), 421 deletions(-) rename arch_init.h => include/sysemu/arch_init.h (100%) rename balloon.h => include/sysemu/balloon.h (100%) rename blockdev.h => include/sysemu/blockdev.h (100%) rename cpus.h => include/sysemu/cpus.h (100%) rename device_tree.h => include/sysemu/device_tree.h (100%) rename dma.h => include/sysemu/dma.h (99%) rename dump.h => include/sysemu/dump.h (100%) rename kvm.h => include/sysemu/kvm.h (100%) rename memory_mapping.h => include/sysemu/memory_mapping.h (100%) rename qemu-os-posix.h => include/sysemu/os-posix.h (100%) rename qemu-os-win32.h => include/sysemu/os-win32.h (100%) rename qtest.h => include/sysemu/qtest.h (100%) rename qemu-seccomp.h => include/sysemu/seccomp.h (100%) rename sysemu.h => include/sysemu/sysemu.h (100%) rename xen-mapcache.h => include/sysemu/xen-mapcache.h (100%) diff --git a/arch_init.c b/arch_init.c index 9dacf5689b..a8b65416da 100644 --- a/arch_init.c +++ b/arch_init.c @@ -30,15 +30,15 @@ #endif #include "config.h" #include "monitor/monitor.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/bitops.h" #include "qemu/bitmap.h" -#include "arch_init.h" +#include "sysemu/arch_init.h" #include "audio/audio.h" #include "hw/pc.h" #include "hw/pci/pci.h" #include "hw/audiodev.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "migration/migration.h" #include "exec/gdbstub.h" #include "hw/smbios.h" diff --git a/audio/audio.c b/audio/audio.c index eb2222c10f..1510b598a6 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -25,7 +25,7 @@ #include "audio.h" #include "monitor/monitor.h" #include "qemu/timer.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #define AUDIO_CAP "audio" #include "audio_int.h" diff --git a/audio/winwaveaudio.c b/audio/winwaveaudio.c index 72babbf184..8dbd145ca1 100644 --- a/audio/winwaveaudio.c +++ b/audio/winwaveaudio.c @@ -1,7 +1,7 @@ /* public domain */ #include "qemu-common.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "audio.h" #define AUDIO_CAP "winwave" diff --git a/balloon.c b/balloon.c index d1de4352b4..e321f2c688 100644 --- a/balloon.c +++ b/balloon.c @@ -26,8 +26,8 @@ #include "monitor/monitor.h" #include "exec/cpu-common.h" -#include "kvm.h" -#include "balloon.h" +#include "sysemu/kvm.h" +#include "sysemu/balloon.h" #include "trace.h" #include "qmp-commands.h" #include "qapi/qmp/qjson.h" diff --git a/block-migration.c b/block-migration.c index 4e865a6781..ca4ba3fffb 100644 --- a/block-migration.c +++ b/block-migration.c @@ -20,7 +20,7 @@ #include "qemu/timer.h" #include "migration/block.h" #include "migration/migration.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include #define BLOCK_SIZE (BDRV_SECTORS_PER_DIRTY_CHUNK << BDRV_SECTOR_BITS) diff --git a/block.c b/block.c index 1af4b99ee8..4e28c55bc7 100644 --- a/block.c +++ b/block.c @@ -29,7 +29,7 @@ #include "block/blockjob.h" #include "qemu/module.h" #include "qapi/qmp/qjson.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/notify.h" #include "block/coroutine.h" #include "qmp-commands.h" diff --git a/block/vdi.c b/block/vdi.c index 7b6231941b..021abaa227 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -58,7 +58,7 @@ #include #else /* TODO: move uuid emulation to some central place in QEMU. */ -#include "sysemu.h" /* UUID_FMT */ +#include "sysemu/sysemu.h" /* UUID_FMT */ typedef unsigned char uuid_t[16]; #endif diff --git a/blockdev-nbd.c b/blockdev-nbd.c index 95b621699a..dc4e9a2462 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -9,11 +9,11 @@ * later. See the COPYING file in the top-level directory. */ -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "hw/block-common.h" #include "monitor/monitor.h" #include "qapi/qmp/qerror.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qmp-commands.h" #include "trace.h" #include "block/nbd.h" diff --git a/blockdev.c b/blockdev.c index 3ebff44310..d724e2dc5b 100644 --- a/blockdev.c +++ b/blockdev.c @@ -7,7 +7,7 @@ * later. See the COPYING file in the top-level directory. */ -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "hw/block-common.h" #include "block/blockjob.h" #include "monitor/monitor.h" @@ -15,11 +15,11 @@ #include "qemu/option.h" #include "qemu/config-file.h" #include "qapi/qmp/types.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "block/block_int.h" #include "qmp-commands.h" #include "trace.h" -#include "arch_init.h" +#include "sysemu/arch_init.h" static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives); diff --git a/cpu-exec.c b/cpu-exec.c index 54e62ed551..19ebb4a924 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -21,7 +21,7 @@ #include "disas/disas.h" #include "tcg.h" #include "qemu/atomic.h" -#include "qtest.h" +#include "sysemu/qtest.h" int tb_invalidated_flag; diff --git a/cpus.c b/cpus.c index 036418d62c..4a7782a541 100644 --- a/cpus.c +++ b/cpus.c @@ -26,15 +26,15 @@ #include "config-host.h" #include "monitor/monitor.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "exec/gdbstub.h" -#include "dma.h" -#include "kvm.h" +#include "sysemu/dma.h" +#include "sysemu/kvm.h" #include "qmp-commands.h" #include "qemu/thread.h" -#include "cpus.h" -#include "qtest.h" +#include "sysemu/cpus.h" +#include "sysemu/qtest.h" #include "qemu/main-loop.h" #include "qemu/bitmap.h" diff --git a/device_tree.c b/device_tree.c index c3e1ba4904..56af24b397 100644 --- a/device_tree.c +++ b/device_tree.c @@ -20,7 +20,7 @@ #include "config.h" #include "qemu-common.h" -#include "device_tree.h" +#include "sysemu/device_tree.h" #include "hw/loader.h" #include "qemu/option.h" #include "qemu/config-file.h" diff --git a/dma-helpers.c b/dma-helpers.c index e6a6dd82fd..272632f367 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -7,7 +7,7 @@ * (GNU GPL), version 2 or later. */ -#include "dma.h" +#include "sysemu/dma.h" #include "trace.h" #include "qemu/range.h" #include "qemu/thread.h" diff --git a/dump-stub.c b/dump-stub.c index 0842e6f916..a9d0b3c67b 100644 --- a/dump-stub.c +++ b/dump-stub.c @@ -12,7 +12,7 @@ */ #include "qemu-common.h" -#include "dump.h" +#include "sysemu/dump.h" #include "qapi/qmp/qerror.h" #include "qmp-commands.h" diff --git a/dump.c b/dump.c index 871ee1727a..a26b1a5e1a 100644 --- a/dump.c +++ b/dump.c @@ -17,10 +17,10 @@ #include "exec/cpu-all.h" #include "exec/hwaddr.h" #include "monitor/monitor.h" -#include "kvm.h" -#include "dump.h" -#include "sysemu.h" -#include "memory_mapping.h" +#include "sysemu/kvm.h" +#include "sysemu/dump.h" +#include "sysemu/sysemu.h" +#include "sysemu/memory_mapping.h" #include "qapi/error.h" #include "qmp-commands.h" #include "exec/gdbstub.h" diff --git a/exec.c b/exec.c index 917bec0ecd..28abd7e710 100644 --- a/exec.c +++ b/exec.c @@ -30,17 +30,17 @@ #include "hw/hw.h" #include "hw/qdev.h" #include "qemu/osdep.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "hw/xen.h" #include "qemu/timer.h" #include "qemu/config-file.h" #include "exec/memory.h" -#include "dma.h" +#include "sysemu/dma.h" #include "exec/address-spaces.h" #if defined(CONFIG_USER_ONLY) #include #else /* !CONFIG_USER_ONLY */ -#include "xen-mapcache.h" +#include "sysemu/xen-mapcache.h" #include "trace.h" #endif diff --git a/gdbstub.c b/gdbstub.c index 4b178a608f..2fca1a7ebf 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -31,7 +31,7 @@ #else #include "monitor/monitor.h" #include "qemu-char.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "exec/gdbstub.h" #endif @@ -39,7 +39,7 @@ #include "cpu.h" #include "qemu/sockets.h" -#include "kvm.h" +#include "sysemu/kvm.h" #ifndef TARGET_CPU_MEMORY_RW_DEBUG static inline int target_memory_rw_debug(CPUArchState *env, target_ulong addr, diff --git a/hw/ac97.c b/hw/ac97.c index 3e659b38df..5cd19c1d02 100644 --- a/hw/ac97.c +++ b/hw/ac97.c @@ -21,7 +21,7 @@ #include "audiodev.h" #include "audio/audio.h" #include "pci/pci.h" -#include "dma.h" +#include "sysemu/dma.h" enum { AC97_Reset = 0x00, diff --git a/hw/acpi.c b/hw/acpi.c index fe9b76a9b0..97617c4ef5 100644 --- a/hw/acpi.c +++ b/hw/acpi.c @@ -18,7 +18,7 @@ * Contributions after 2012-01-13 are licensed under the terms of the * GNU GPL, version 2 or (at your option) any later version. */ -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "hw.h" #include "pc.h" #include "acpi.h" diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c index 8d1a689a36..37a50e6d7b 100644 --- a/hw/acpi_ich9.c +++ b/hw/acpi_ich9.c @@ -27,9 +27,9 @@ #include "pc.h" #include "pci/pci.h" #include "qemu/timer.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "acpi.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "exec/address-spaces.h" #include "ich9.h" diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index ebd015dc02..f53b969aa6 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -24,7 +24,7 @@ #include "pm_smbus.h" #include "pci/pci.h" #include "acpi.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/range.h" #include "exec/ioport.h" #include "fw_cfg.h" diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c index 76d8ae8a84..e7e52c1f1c 100644 --- a/hw/alpha_dp264.c +++ b/hw/alpha_dp264.c @@ -11,7 +11,7 @@ #include "loader.h" #include "boards.h" #include "alpha_sys.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "mc146818rtc.h" #include "ide.h" #include "i8254.h" diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c index 78d93e55ec..7327d488fd 100644 --- a/hw/alpha_pci.c +++ b/hw/alpha_pci.c @@ -9,7 +9,7 @@ #include "config.h" #include "alpha_sys.h" #include "qemu/log.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" /* PCI IO reads/writes, to byte-word addressable memory. */ diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c index d61b2f483c..9f233d99f5 100644 --- a/hw/alpha_typhoon.c +++ b/hw/alpha_typhoon.c @@ -10,7 +10,7 @@ #include "exec/exec-all.h" #include "hw.h" #include "devices.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "alpha_sys.h" #include "exec/address-spaces.h" diff --git a/hw/apb_pci.c b/hw/apb_pci.c index 144a7cc8d3..c22e2b0fc3 100644 --- a/hw/apb_pci.c +++ b/hw/apb_pci.c @@ -32,7 +32,7 @@ #include "pci/pci_bridge.h" #include "pci/pci_bus.h" #include "apb_pci.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "exec/address-spaces.h" /* debug APB */ diff --git a/hw/apic_common.c b/hw/apic_common.c index 5f542764eb..0658be93c1 100644 --- a/hw/apic_common.c +++ b/hw/apic_common.c @@ -20,7 +20,7 @@ #include "apic.h" #include "apic_internal.h" #include "trace.h" -#include "kvm.h" +#include "sysemu/kvm.h" static int apic_irq_delivered; bool apic_report_tpr_access; diff --git a/hw/arm_boot.c b/hw/arm_boot.c index bb9889fbef..115f583876 100644 --- a/hw/arm_boot.c +++ b/hw/arm_boot.c @@ -10,11 +10,11 @@ #include "config.h" #include "hw.h" #include "arm-misc.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "loader.h" #include "elf.h" -#include "device_tree.h" +#include "sysemu/device_tree.h" #include "qemu/config-file.h" #define KERNEL_ARGS_ADDR 0x100 diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c index 0884f6275c..b733617aa0 100644 --- a/hw/arm_sysctl.c +++ b/hw/arm_sysctl.c @@ -11,7 +11,7 @@ #include "qemu/timer.h" #include "sysbus.h" #include "primecell.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #define LOCK_VALUE 0xa05f diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c index e537aecc78..2ca606b835 100644 --- a/hw/axis_dev88.c +++ b/hw/axis_dev88.c @@ -30,7 +30,7 @@ #include "loader.h" #include "elf.h" #include "cris-boot.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" #define D(x) diff --git a/hw/block-common.c b/hw/block-common.c index c24208e560..0f1b64ec95 100644 --- a/hw/block-common.c +++ b/hw/block-common.c @@ -7,7 +7,7 @@ * later. See the COPYING file in the top-level directory. */ -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "hw/block-common.h" #include "qemu/error-report.h" diff --git a/hw/boards.h b/hw/boards.h index c66fa16a9d..4540e952f7 100644 --- a/hw/boards.h +++ b/hw/boards.h @@ -3,7 +3,7 @@ #ifndef HW_BOARDS_H #define HW_BOARDS_H -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "qdev.h" typedef struct QEMUMachineInitArgs { diff --git a/hw/bonito.c b/hw/bonito.c index 78e264ccc0..0498c9be79 100644 --- a/hw/bonito.c +++ b/hw/bonito.c @@ -44,7 +44,7 @@ #include "pc.h" #include "mips.h" #include "pci/pci_host.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "exec/address-spaces.h" //#define DEBUG_BONITO diff --git a/hw/cbus.c b/hw/cbus.c index 7216899a09..6fd3905448 100644 --- a/hw/cbus.c +++ b/hw/cbus.c @@ -23,7 +23,7 @@ #include "qemu-common.h" #include "irq.h" #include "devices.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" //#define DEBUG diff --git a/hw/collie.c b/hw/collie.c index faf5ac9ac7..804d61a421 100644 --- a/hw/collie.c +++ b/hw/collie.c @@ -15,7 +15,7 @@ #include "strongarm.h" #include "arm-misc.h" #include "flash.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" static struct arm_boot_info collie_binfo = { diff --git a/hw/cuda.c b/hw/cuda.c index cf83956e1a..d59e0aeaa9 100644 --- a/hw/cuda.c +++ b/hw/cuda.c @@ -26,7 +26,7 @@ #include "ppc_mac.h" #include "adb.h" #include "qemu/timer.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" /* XXX: implement all timer modes */ diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c index 34543786e5..88da145a89 100644 --- a/hw/device-hotplug.c +++ b/hw/device-hotplug.c @@ -24,9 +24,9 @@ #include "hw.h" #include "boards.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "qemu/config-file.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "monitor/monitor.h" DriveInfo *add_init_drive(const char *optstr) diff --git a/hw/e1000.c b/hw/e1000.c index aeee3e61f4..92fb00a89f 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -30,8 +30,8 @@ #include "net/net.h" #include "net/checksum.h" #include "loader.h" -#include "sysemu.h" -#include "dma.h" +#include "sysemu/sysemu.h" +#include "sysemu/dma.h" #include "e1000_hw.h" diff --git a/hw/eepro100.c b/hw/eepro100.c index 9e2be4ea0d..6bbefb505f 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -45,8 +45,8 @@ #include "pci/pci.h" #include "net/net.h" #include "eeprom93xx.h" -#include "sysemu.h" -#include "dma.h" +#include "sysemu/sysemu.h" +#include "sysemu/dma.h" /* QEMU sends frames smaller than 60 bytes to ethernet nics. * Such frames are rejected by real nics and their emulations. diff --git a/hw/es1370.c b/hw/es1370.c index 65365788e1..59c3f2329e 100644 --- a/hw/es1370.c +++ b/hw/es1370.c @@ -30,7 +30,7 @@ #include "audiodev.h" #include "audio/audio.h" #include "pci/pci.h" -#include "dma.h" +#include "sysemu/dma.h" /* Missing stuff: SCTRL_P[12](END|ST)INC diff --git a/hw/etraxfs_dma.c b/hw/etraxfs_dma.c index 089267fcc1..d41500316f 100644 --- a/hw/etraxfs_dma.c +++ b/hw/etraxfs_dma.c @@ -26,7 +26,7 @@ #include "hw.h" #include "exec/address-spaces.h" #include "qemu-common.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "etraxfs_dma.h" diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c index cc8b327715..e9273cd95d 100644 --- a/hw/etraxfs_timer.c +++ b/hw/etraxfs_timer.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "sysbus.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/timer.h" #include "ptimer.h" diff --git a/hw/exynos4210.c b/hw/exynos4210.c index 22148cd946..a7b84d61a0 100644 --- a/hw/exynos4210.c +++ b/hw/exynos4210.c @@ -22,7 +22,7 @@ */ #include "boards.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "sysbus.h" #include "arm-misc.h" #include "loader.h" diff --git a/hw/exynos4210_rtc.c b/hw/exynos4210_rtc.c index 6ebc9b1790..5694a6207b 100644 --- a/hw/exynos4210_rtc.c +++ b/hw/exynos4210_rtc.c @@ -32,7 +32,7 @@ #include "hw.h" #include "qemu/timer.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "exynos4210.h" diff --git a/hw/exynos4210_uart.c b/hw/exynos4210_uart.c index 20dcd9fb57..8950891a00 100644 --- a/hw/exynos4210_uart.c +++ b/hw/exynos4210_uart.c @@ -20,7 +20,7 @@ */ #include "sysbus.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu-char.h" #include "exynos4210.h" diff --git a/hw/exynos4_boards.c b/hw/exynos4_boards.c index 5dd2961459..b26796847b 100644 --- a/hw/exynos4_boards.c +++ b/hw/exynos4_boards.c @@ -21,7 +21,7 @@ * */ -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "sysbus.h" #include "net/net.h" #include "arm-misc.h" diff --git a/hw/fdc.c b/hw/fdc.c index b67d3a574b..ddc0cc3819 100644 --- a/hw/fdc.c +++ b/hw/fdc.c @@ -34,8 +34,8 @@ #include "isa.h" #include "sysbus.h" #include "qdev-addr.h" -#include "blockdev.h" -#include "sysemu.h" +#include "sysemu/blockdev.h" +#include "sysemu/sysemu.h" #include "qemu/log.h" /********************************************************/ diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c index 2a00163a04..26f7125fe2 100644 --- a/hw/fw_cfg.c +++ b/hw/fw_cfg.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "hw.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "isa.h" #include "fw_cfg.h" #include "sysbus.h" diff --git a/hw/gumstix.c b/hw/gumstix.c index 4acb32c2a9..6fb068386c 100644 --- a/hw/gumstix.c +++ b/hw/gumstix.c @@ -40,7 +40,7 @@ #include "flash.h" #include "devices.h" #include "boards.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" static const int sector_len = 128 * 1024; diff --git a/hw/highbank.c b/hw/highbank.c index 6f5f2a9d9d..6005622f3a 100644 --- a/hw/highbank.c +++ b/hw/highbank.c @@ -22,10 +22,10 @@ #include "devices.h" #include "loader.h" #include "net/net.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "sysbus.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" #define SMP_BOOT_ADDR 0x100 diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index d38c6e4574..d0724499c7 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -28,7 +28,7 @@ #include #include "monitor/monitor.h" -#include "dma.h" +#include "sysemu/dma.h" #include "exec/cpu-common.h" #include "internal.h" #include diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index f6d15b9f2a..ee855b670f 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -27,8 +27,8 @@ #include #include #include "block/block.h" -#include "sysemu.h" -#include "dma.h" +#include "sysemu/sysemu.h" +#include "sysemu/dma.h" #include diff --git a/hw/ide/core.c b/hw/ide/core.c index bf65cb407e..6f1938a0a8 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -28,10 +28,10 @@ #include #include "qemu/error-report.h" #include "qemu/timer.h" -#include "sysemu.h" -#include "dma.h" +#include "sysemu/sysemu.h" +#include "sysemu/dma.h" #include "hw/block-common.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include diff --git a/hw/ide/ich.c b/hw/ide/ich.c index 3457b98cc1..de39b3067a 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -66,7 +66,7 @@ #include #include #include "block/block.h" -#include "dma.h" +#include "sysemu/dma.h" #include #include diff --git a/hw/ide/internal.h b/hw/ide/internal.h index c5016f0cea..d80360e85b 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -9,8 +9,8 @@ #include #include #include "exec/iorange.h" -#include "dma.h" -#include "sysemu.h" +#include "sysemu/dma.h" +#include "sysemu/sysemu.h" #include "hw/block-common.h" #include "hw/scsi-defs.h" diff --git a/hw/ide/isa.c b/hw/ide/isa.c index 39df87c608..aa0e7fa22d 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -26,7 +26,7 @@ #include #include #include "block/block.h" -#include "dma.h" +#include "sysemu/dma.h" #include diff --git a/hw/ide/macio.c b/hw/ide/macio.c index 87cbb0c31e..d8f9b4bce1 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -26,7 +26,7 @@ #include #include #include "block/block.h" -#include "dma.h" +#include "sysemu/dma.h" #include diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c index 6cce5230c5..642774ef98 100644 --- a/hw/ide/microdrive.c +++ b/hw/ide/microdrive.c @@ -26,7 +26,7 @@ #include #include #include "block/block.h" -#include "dma.h" +#include "sysemu/dma.h" #include diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c index 40443513be..eb59976eda 100644 --- a/hw/ide/mmio.c +++ b/hw/ide/mmio.c @@ -24,7 +24,7 @@ */ #include #include "block/block.h" -#include "dma.h" +#include "sysemu/dma.h" #include diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 8821d5cceb..e6226e3197 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -27,7 +27,7 @@ #include #include #include "block/block.h" -#include "dma.h" +#include "sysemu/dma.h" #include diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 5cf39cf8f0..df95aec195 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -27,9 +27,9 @@ #include #include #include -#include "blockdev.h" -#include "sysemu.h" -#include "dma.h" +#include "sysemu/blockdev.h" +#include "sysemu/sysemu.h" +#include "sysemu/dma.h" #include diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index c85e1ac018..d2fe77398f 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -17,12 +17,12 @@ * License along with this library; if not, see . */ #include -#include "dma.h" +#include "sysemu/dma.h" #include "qemu/error-report.h" #include -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "hw/block-common.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" /* --------------------------------- */ diff --git a/hw/ide/via.c b/hw/ide/via.c index 880f61cc8e..14acb3ac04 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -28,8 +28,8 @@ #include #include #include "block/block.h" -#include "sysemu.h" -#include "dma.h" +#include "sysemu/sysemu.h" +#include "sysemu/dma.h" #include diff --git a/hw/imx_ccm.c b/hw/imx_ccm.c index f2e623cd29..46962e4df9 100644 --- a/hw/imx_ccm.c +++ b/hw/imx_ccm.c @@ -12,7 +12,7 @@ #include "hw.h" #include "sysbus.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "imx.h" #define CKIH_FREQ 26000000 /* 26MHz crystal input */ diff --git a/hw/imx_serial.c b/hw/imx_serial.c index dcd125fd25..e56e3ea726 100644 --- a/hw/imx_serial.c +++ b/hw/imx_serial.c @@ -19,7 +19,7 @@ #include "hw.h" #include "sysbus.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu-char.h" #include "imx.h" diff --git a/hw/integratorcp.c b/hw/integratorcp.c index c995dc724f..47fc9cb944 100644 --- a/hw/integratorcp.c +++ b/hw/integratorcp.c @@ -13,7 +13,7 @@ #include "arm-misc.h" #include "net/net.h" #include "exec/address-spaces.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" typedef struct { SysBusDevice busdev; diff --git a/hw/intel-hda.c b/hw/intel-hda.c index 7ef3a15e08..98ff93679d 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -24,7 +24,7 @@ #include "audiodev.h" #include "intel-hda.h" #include "intel-hda-defs.h" -#include "dma.h" +#include "sysemu/dma.h" /* --------------------------------------------------------------------- */ /* hda bus */ diff --git a/hw/isa-bus.c b/hw/isa-bus.c index a2be67df56..86b0bbd3d1 100644 --- a/hw/isa-bus.c +++ b/hw/isa-bus.c @@ -19,7 +19,7 @@ #include "hw.h" #include "monitor/monitor.h" #include "sysbus.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "isa.h" #include "exec/address-spaces.h" diff --git a/hw/ivshmem.c b/hw/ivshmem.c index af34f3b582..567c9a76a7 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -20,7 +20,7 @@ #include "pc.h" #include "pci/pci.h" #include "pci/msix.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "migration/migration.h" #include "qapi/qmp/qerror.h" #include "qemu/event_notifier.h" diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c index beb418de8d..dad2f21c18 100644 --- a/hw/kvm/apic.c +++ b/hw/kvm/apic.c @@ -11,7 +11,7 @@ */ #include "hw/apic_internal.h" #include "hw/pci/msi.h" -#include "kvm.h" +#include "sysemu/kvm.h" static inline void kvm_apic_set_reg(struct kvm_lapic_state *kapic, int reg_id, uint32_t val) diff --git a/hw/kvm/clock.c b/hw/kvm/clock.c index 824b978397..6fcca95ada 100644 --- a/hw/kvm/clock.c +++ b/hw/kvm/clock.c @@ -14,8 +14,8 @@ */ #include "qemu-common.h" -#include "sysemu.h" -#include "kvm.h" +#include "sysemu/sysemu.h" +#include "sysemu/kvm.h" #include "hw/sysbus.h" #include "hw/kvm/clock.h" diff --git a/hw/kvm/i8254.c b/hw/kvm/i8254.c index 8ee1c352cf..57faf64ab2 100644 --- a/hw/kvm/i8254.c +++ b/hw/kvm/i8254.c @@ -23,10 +23,10 @@ * THE SOFTWARE. */ #include "qemu/timer.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "hw/i8254.h" #include "hw/i8254_internal.h" -#include "kvm.h" +#include "sysemu/kvm.h" #define KVM_PIT_REINJECT_BIT 0 diff --git a/hw/kvm/i8259.c b/hw/kvm/i8259.c index 1e24cd4f36..70e1d185de 100644 --- a/hw/kvm/i8259.c +++ b/hw/kvm/i8259.c @@ -11,7 +11,7 @@ */ #include "hw/i8259_internal.h" #include "hw/apic_internal.h" -#include "kvm.h" +#include "sysemu/kvm.h" static void kvm_pic_get(PICCommonState *s) { diff --git a/hw/kvm/ioapic.c b/hw/kvm/ioapic.c index f95c157591..30db6230b4 100644 --- a/hw/kvm/ioapic.c +++ b/hw/kvm/ioapic.c @@ -13,7 +13,7 @@ #include "hw/pc.h" #include "hw/ioapic_internal.h" #include "hw/apic_internal.h" -#include "kvm.h" +#include "sysemu/kvm.h" /* PC Utility function */ void kvm_pc_setup_irq_routing(bool pci_enabled) diff --git a/hw/kvm/pci-assign.c b/hw/kvm/pci-assign.c index 2f06c27e83..410b6c6eeb 100644 --- a/hw/kvm/pci-assign.c +++ b/hw/kvm/pci-assign.c @@ -33,7 +33,7 @@ #include "hw/loader.h" #include "monitor/monitor.h" #include "qemu/range.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "hw/pci/pci.h" #include "hw/pci/msi.h" #include "kvm_i386.h" diff --git a/hw/kvmvapic.c b/hw/kvmvapic.c index 60c8fc46aa..81f4bcfdf6 100644 --- a/hw/kvmvapic.c +++ b/hw/kvmvapic.c @@ -8,9 +8,9 @@ * (at your option) any later version. See the COPYING file in the * top-level directory. */ -#include "sysemu.h" -#include "cpus.h" -#include "kvm.h" +#include "sysemu/sysemu.h" +#include "sysemu/cpus.h" +#include "sysemu/kvm.h" #include "apic_internal.h" #define APIC_DEFAULT_ADDRESS 0xfee00000 diff --git a/hw/kzm.c b/hw/kzm.c index 9f92d30928..fd00af921e 100644 --- a/hw/kzm.c +++ b/hw/kzm.c @@ -19,7 +19,7 @@ #include "arm-misc.h" #include "devices.h" #include "net/net.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "serial.h" #include "imx.h" diff --git a/hw/lan9118.c b/hw/lan9118.c index 4c72d0d98e..5adf91199b 100644 --- a/hw/lan9118.c +++ b/hw/lan9118.c @@ -13,7 +13,7 @@ #include "sysbus.h" #include "net/net.h" #include "devices.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "ptimer.h" /* For crc32 */ #include diff --git a/hw/leon3.c b/hw/leon3.c index 776ab97a78..d1d4541867 100644 --- a/hw/leon3.c +++ b/hw/leon3.c @@ -25,7 +25,7 @@ #include "qemu/timer.h" #include "ptimer.h" #include "qemu-char.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "loader.h" #include "elf.h" diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c index 81afdf675c..42e8b6b52a 100644 --- a/hw/lm32_boards.c +++ b/hw/lm32_boards.c @@ -23,7 +23,7 @@ #include "devices.h" #include "boards.h" #include "loader.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "elf.h" #include "lm32_hwsetup.h" #include "lm32.h" diff --git a/hw/lm32_sys.c b/hw/lm32_sys.c index b3350890cb..e3a9db9748 100644 --- a/hw/lm32_sys.c +++ b/hw/lm32_sys.c @@ -33,7 +33,7 @@ #include "trace.h" #include "qemu/log.h" #include "qemu/error-report.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/log.h" enum { diff --git a/hw/loader.c b/hw/loader.c index f5ef575b52..3f59fcd14a 100644 --- a/hw/loader.c +++ b/hw/loader.c @@ -45,7 +45,7 @@ #include "hw.h" #include "disas/disas.h" #include "monitor/monitor.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "uboot_image.h" #include "loader.h" #include "fw_cfg.h" diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c index 76217a74fc..a068715c04 100644 --- a/hw/lpc_ich9.c +++ b/hw/lpc_ich9.c @@ -44,7 +44,7 @@ #include "pam.h" #include "pci/pci_bus.h" #include "exec/address-spaces.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" static int ich9_lpc_sci_irq(ICH9LPCState *lpc); diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index 4aac9a0cff..0aafb00b58 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -15,7 +15,7 @@ #include "hw.h" #include "pci/pci.h" #include "scsi.h" -#include "dma.h" +#include "sysemu/dma.h" //#define DEBUG_LSI //#define DEBUG_LSI_REG diff --git a/hw/m25p80.c b/hw/m25p80.c index 3895e73957..d39265632b 100644 --- a/hw/m25p80.c +++ b/hw/m25p80.c @@ -22,7 +22,7 @@ */ #include "hw.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "ssi.h" #include "devices.h" diff --git a/hw/m48t59.c b/hw/m48t59.c index 301b10ce79..393c5c049a 100644 --- a/hw/m48t59.c +++ b/hw/m48t59.c @@ -24,7 +24,7 @@ #include "hw.h" #include "nvram.h" #include "qemu/timer.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "sysbus.h" #include "isa.h" #include "exec/address-spaces.h" diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c index a0d14dd3c5..71093c2b10 100644 --- a/hw/mac_nvram.c +++ b/hw/mac_nvram.c @@ -24,7 +24,7 @@ */ #include "hw.h" #include "firmware_abi.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "ppc_mac.h" /* debug NVR */ diff --git a/hw/mainstone.c b/hw/mainstone.c index 80d6a9d54d..a5ddbeff9d 100644 --- a/hw/mainstone.c +++ b/hw/mainstone.c @@ -18,7 +18,7 @@ #include "devices.h" #include "boards.h" #include "flash.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "sysbus.h" #include "exec/address-spaces.h" diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index fba75029df..2ddd7de09e 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -23,7 +23,7 @@ */ #include "hw.h" #include "qemu/timer.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "mc146818rtc.h" #include "qapi/visitor.h" diff --git a/hw/mcf5206.c b/hw/mcf5206.c index fbc806ac18..fe7a48864f 100644 --- a/hw/mcf5206.c +++ b/hw/mcf5206.c @@ -9,7 +9,7 @@ #include "mcf.h" #include "qemu/timer.h" #include "ptimer.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "exec/address-spaces.h" /* General purpose timer module. */ diff --git a/hw/mcf5208.c b/hw/mcf5208.c index fea8a69262..c1816cc9d1 100644 --- a/hw/mcf5208.c +++ b/hw/mcf5208.c @@ -9,7 +9,7 @@ #include "mcf.h" #include "qemu/timer.h" #include "ptimer.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "net/net.h" #include "boards.h" #include "loader.h" diff --git a/hw/megasas.c b/hw/megasas.c index e80c0d1c25..eb191f5e12 100644 --- a/hw/megasas.c +++ b/hw/megasas.c @@ -20,7 +20,7 @@ #include "hw.h" #include "pci/pci.h" -#include "dma.h" +#include "sysemu/dma.h" #include "pci/msix.h" #include "qemu/iov.h" #include "scsi.h" diff --git a/hw/microblaze_boot.c b/hw/microblaze_boot.c index 76d33021c0..3ec5c0f7dd 100644 --- a/hw/microblaze_boot.c +++ b/hw/microblaze_boot.c @@ -27,7 +27,7 @@ #include "qemu/option.h" #include "qemu/config-file.h" #include "qemu-common.h" -#include "device_tree.h" +#include "sysemu/device_tree.h" #include "loader.h" #include "elf.h" diff --git a/hw/milkymist-memcard.c b/hw/milkymist-memcard.c index 5dc30ace60..f80befc53a 100644 --- a/hw/milkymist-memcard.c +++ b/hw/milkymist-memcard.c @@ -23,10 +23,10 @@ #include "hw.h" #include "sysbus.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "trace.h" #include "qemu/error-report.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "sd.h" enum { diff --git a/hw/milkymist-sysctl.c b/hw/milkymist-sysctl.c index 519462afcc..796e795f04 100644 --- a/hw/milkymist-sysctl.c +++ b/hw/milkymist-sysctl.c @@ -23,7 +23,7 @@ #include "hw.h" #include "sysbus.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "trace.h" #include "qemu/timer.h" #include "ptimer.h" diff --git a/hw/milkymist.c b/hw/milkymist.c index 588522260b..0c23b672f3 100644 --- a/hw/milkymist.c +++ b/hw/milkymist.c @@ -20,12 +20,12 @@ #include "sysbus.h" #include "hw.h" #include "flash.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "devices.h" #include "boards.h" #include "loader.h" #include "elf.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "milkymist-hw.h" #include "lm32.h" #include "exec/address-spaces.h" diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c index 60dd8c69bb..e7eeda319e 100644 --- a/hw/mips_fulong2e.c +++ b/hw/mips_fulong2e.c @@ -31,7 +31,7 @@ #include "mips_cpudevs.h" #include "pci/pci.h" #include "qemu-char.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "audio/audio.h" #include "qemu/log.h" #include "loader.h" @@ -41,7 +41,7 @@ #include "vt82c686.h" #include "mc146818rtc.h" #include "i8254.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" #define DEBUG_FULONG2E_INIT diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c index 0befc99210..63df2a734b 100644 --- a/hw/mips_jazz.c +++ b/hw/mips_jazz.c @@ -29,8 +29,8 @@ #include "serial.h" #include "isa.h" #include "fdc.h" -#include "sysemu.h" -#include "arch_init.h" +#include "sysemu/sysemu.h" +#include "sysemu/arch_init.h" #include "boards.h" #include "net/net.h" #include "esp.h" @@ -39,7 +39,7 @@ #include "mc146818rtc.h" #include "i8254.h" #include "pcspk.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "sysbus.h" #include "exec/address-spaces.h" diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 04c7a2612c..bd31ced29d 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -35,8 +35,8 @@ #include "mips_cpudevs.h" #include "pci/pci.h" #include "qemu-char.h" -#include "sysemu.h" -#include "arch_init.h" +#include "sysemu/sysemu.h" +#include "sysemu/arch_init.h" #include "boards.h" #include "qemu/log.h" #include "mips-bios.h" @@ -45,7 +45,7 @@ #include "elf.h" #include "mc146818rtc.h" #include "i8254.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" #include "sysbus.h" /* SysBusDevice */ diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c index ac7dfa9b74..67066c0ca1 100644 --- a/hw/mips_mipssim.c +++ b/hw/mips_mipssim.c @@ -30,7 +30,7 @@ #include "serial.h" #include "isa.h" #include "net/net.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "mips-bios.h" #include "loader.h" diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index 511e1e41c0..59c43e591c 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -14,7 +14,7 @@ #include "serial.h" #include "isa.h" #include "net/net.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "flash.h" #include "qemu/log.h" @@ -24,7 +24,7 @@ #include "elf.h" #include "mc146818rtc.h" #include "i8254.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" #define MAX_IDE_BUS 2 diff --git a/hw/mpc8544_guts.c b/hw/mpc8544_guts.c index 873cb8cbfc..84522e9722 100644 --- a/hw/mpc8544_guts.c +++ b/hw/mpc8544_guts.c @@ -18,7 +18,7 @@ */ #include "hw.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "sysbus.h" #define MPC8544_GUTS_MMIO_SIZE 0x1000 diff --git a/hw/multiboot.c b/hw/multiboot.c index 09ec5b2539..c4ec2e34a7 100644 --- a/hw/multiboot.c +++ b/hw/multiboot.c @@ -27,7 +27,7 @@ #include "multiboot.h" #include "loader.h" #include "elf.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" /* Show multiboot debug output */ //#define DEBUG_MULTIBOOT diff --git a/hw/musicpal.c b/hw/musicpal.c index 5a7bf8bee1..77a585eee6 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -13,7 +13,7 @@ #include "arm-misc.h" #include "devices.h" #include "net/net.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "serial.h" #include "qemu/timer.h" @@ -22,7 +22,7 @@ #include "flash.h" #include "ui/console.h" #include "i2c.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" #include "ui/pixel_ops.h" diff --git a/hw/nand.c b/hw/nand.c index a73205d866..16950c5ec4 100644 --- a/hw/nand.c +++ b/hw/nand.c @@ -20,7 +20,7 @@ # include "hw.h" # include "flash.h" -# include "blockdev.h" +# include "sysemu/blockdev.h" # include "sysbus.h" #include "qemu/error-report.h" diff --git a/hw/ne2000.c b/hw/ne2000.c index 2001264e14..00efa74a0f 100644 --- a/hw/ne2000.c +++ b/hw/ne2000.c @@ -26,7 +26,7 @@ #include "net/net.h" #include "ne2000.h" #include "loader.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" /* debug NE2000 card */ //#define DEBUG_NE2000 diff --git a/hw/nseries.c b/hw/nseries.c index 83adb97211..d96b750ccd 100644 --- a/hw/nseries.c +++ b/hw/nseries.c @@ -19,7 +19,7 @@ */ #include "qemu-common.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "omap.h" #include "arm-misc.h" #include "irq.h" @@ -31,7 +31,7 @@ #include "hw.h" #include "bt.h" #include "loader.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "sysbus.h" #include "exec/address-spaces.h" diff --git a/hw/omap1.c b/hw/omap1.c index 50c4570f31..8536e96687 100644 --- a/hw/omap1.c +++ b/hw/omap1.c @@ -19,9 +19,9 @@ #include "hw.h" #include "arm-misc.h" #include "omap.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "soc_dma.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "qemu/range.h" #include "sysbus.h" diff --git a/hw/omap2.c b/hw/omap2.c index 7ccee69661..dc6867c962 100644 --- a/hw/omap2.c +++ b/hw/omap2.c @@ -18,11 +18,11 @@ * with this program; if not, see . */ -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "hw.h" #include "arm-misc.h" #include "omap.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/timer.h" #include "qemu-char.h" #include "flash.h" diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c index ca6eb9ddeb..0f03121505 100644 --- a/hw/omap_sx1.c +++ b/hw/omap_sx1.c @@ -31,7 +31,7 @@ #include "boards.h" #include "arm-misc.h" #include "flash.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" /*****************************************************************************/ diff --git a/hw/onenand.c b/hw/onenand.c index 2e26e3a05d..26bf991d6d 100644 --- a/hw/onenand.c +++ b/hw/onenand.c @@ -22,7 +22,7 @@ #include "hw.h" #include "flash.h" #include "irq.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/memory.h" #include "exec/address-spaces.h" #include "sysbus.h" diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c index fd2f0f61c3..a0dfdce1f9 100644 --- a/hw/opencores_eth.c +++ b/hw/opencores_eth.c @@ -34,7 +34,7 @@ #include "hw.h" #include "sysbus.h" #include "net/net.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "trace.h" /* RECSMALL is not used because it breaks tap networking in linux: diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c index c12097e12b..d2b2379ae2 100644 --- a/hw/openrisc_sim.c +++ b/hw/openrisc_sim.c @@ -25,9 +25,9 @@ #include "net/net.h" #include "loader.h" #include "exec/address-spaces.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "sysbus.h" -#include "qtest.h" +#include "sysemu/qtest.h" #define KERNEL_LOAD_ADDR 0x100 diff --git a/hw/palm.c b/hw/palm.c index e091bbcfc1..5219e37394 100644 --- a/hw/palm.c +++ b/hw/palm.c @@ -18,7 +18,7 @@ */ #include "hw.h" #include "audio/audio.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "ui/console.h" #include "omap.h" #include "boards.h" diff --git a/hw/pam.c b/hw/pam.c index a95e2cfb07..1d72e88e62 100644 --- a/hw/pam.c +++ b/hw/pam.c @@ -26,7 +26,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "pam.h" void smram_update(MemoryRegion *smram_region, uint8_t smram, diff --git a/hw/parallel.c b/hw/parallel.c index c4705bc89d..56b3760e8c 100644 --- a/hw/parallel.c +++ b/hw/parallel.c @@ -26,7 +26,7 @@ #include "qemu-char.h" #include "isa.h" #include "pc.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" //#define DEBUG_PARALLEL diff --git a/hw/pc.c b/hw/pc.c index 0a92ea6bed..71902e210b 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -40,16 +40,16 @@ #include "pcspk.h" #include "pci/msi.h" #include "sysbus.h" -#include "sysemu.h" -#include "kvm.h" +#include "sysemu/sysemu.h" +#include "sysemu/kvm.h" #include "kvm_i386.h" #include "xen.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "hw/block-common.h" #include "ui/qemu-spice.h" #include "exec/memory.h" #include "exec/address-spaces.h" -#include "arch_init.h" +#include "sysemu/arch_init.h" #include "qemu/bitmap.h" /* debug PC/ISA interrupts */ diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 0d011348f2..99747a774c 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -33,12 +33,12 @@ #include "net/net.h" #include "boards.h" #include "ide.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "kvm/clock.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "sysbus.h" -#include "arch_init.h" -#include "blockdev.h" +#include "sysemu/arch_init.h" +#include "sysemu/blockdev.h" #include "smbus.h" #include "xen.h" #include "exec/memory.h" diff --git a/hw/pc_q35.c b/hw/pc_q35.c index 2580d5ff34..c7262d6315 100644 --- a/hw/pc_q35.c +++ b/hw/pc_q35.c @@ -28,12 +28,12 @@ * THE SOFTWARE. */ #include "hw.h" -#include "arch_init.h" +#include "sysemu/arch_init.h" #include "smbus.h" #include "boards.h" #include "mc146818rtc.h" #include "xen.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "kvm/clock.h" #include "q35.h" #include "exec/address-spaces.h" diff --git a/hw/pc_sysfw.c b/hw/pc_sysfw.c index d7ea3a5595..87e1fa961b 100644 --- a/hw/pc_sysfw.c +++ b/hw/pc_sysfw.c @@ -23,15 +23,15 @@ * THE SOFTWARE. */ -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "sysbus.h" #include "hw.h" #include "pc.h" #include "hw/boards.h" #include "loader.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "flash.h" -#include "kvm.h" +#include "sysemu/kvm.h" #define BIOS_FILENAME "bios.bin" diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug.c index 2bc02e344f..f38df30540 100644 --- a/hw/pci/pci-hotplug.c +++ b/hw/pci/pci-hotplug.c @@ -31,7 +31,7 @@ #include "hw/scsi.h" #include "hw/virtio-blk.h" #include "qemu/config-file.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "qapi/error.h" #if defined(TARGET_I386) diff --git a/hw/pci/pci-stub.c b/hw/pci/pci-stub.c index 5891dc959d..1dda89b593 100644 --- a/hw/pci/pci-stub.c +++ b/hw/pci/pci-stub.c @@ -18,7 +18,7 @@ * with this program; if not, see . */ -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "monitor/monitor.h" #include "hw/pci/pci.h" #include "qmp-commands.h" diff --git a/hw/pci/pci.c b/hw/pci/pci.c index c9ed95be89..94840c4af7 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -27,7 +27,7 @@ #include "hw/pci/pci_bus.h" #include "monitor/monitor.h" #include "net/net.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "hw/loader.h" #include "qemu/range.h" #include "qmp-commands.h" diff --git a/hw/pci/pci.h b/hw/pci/pci.h index d6ef4f6574..3152050856 100644 --- a/hw/pci/pci.h +++ b/hw/pci/pci.h @@ -5,7 +5,7 @@ #include "hw/qdev.h" #include "exec/memory.h" -#include "dma.h" +#include "sysemu/dma.h" /* PCI includes legacy ISA access. */ #include "hw/isa.h" diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c index f7f3633f5b..1ce72ce944 100644 --- a/hw/pci/pcie_aer.c +++ b/hw/pci/pcie_aer.c @@ -18,7 +18,7 @@ * with this program; if not, see . */ -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qapi/qmp/types.h" #include "monitor/monitor.h" #include "hw/pci/pci_bridge.h" diff --git a/hw/pckbd.c b/hw/pckbd.c index 5bb3e0abf3..6db7bbcc06 100644 --- a/hw/pckbd.c +++ b/hw/pckbd.c @@ -25,7 +25,7 @@ #include "isa.h" #include "pc.h" #include "ps2.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" /* debug PC keyboard */ //#define DEBUG_KBD diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c index 5e8eed3af8..40a0e6eda4 100644 --- a/hw/pcnet-pci.c +++ b/hw/pcnet-pci.c @@ -31,7 +31,7 @@ #include "net/net.h" #include "loader.h" #include "qemu/timer.h" -#include "dma.h" +#include "sysemu/dma.h" #include "pcnet.h" diff --git a/hw/pcnet.c b/hw/pcnet.c index 87736542e4..30f100007a 100644 --- a/hw/pcnet.c +++ b/hw/pcnet.c @@ -39,7 +39,7 @@ #include "net/net.h" #include "qemu/timer.h" #include "qemu/sockets.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "pcnet.h" diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c index 4eab0f2d8b..1cfdb2f302 100644 --- a/hw/petalogix_ml605_mmu.c +++ b/hw/petalogix_ml605_mmu.c @@ -29,11 +29,11 @@ #include "hw.h" #include "net/net.h" #include "flash.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "devices.h" #include "boards.h" #include "xilinx.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "serial.h" #include "exec/address-spaces.h" #include "ssi.h" diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c index 124a88eeda..27ecfe7752 100644 --- a/hw/petalogix_s3adsp1800_mmu.c +++ b/hw/petalogix_s3adsp1800_mmu.c @@ -27,11 +27,11 @@ #include "hw.h" #include "net/net.h" #include "flash.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "devices.h" #include "boards.h" #include "xilinx.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" #include "microblaze_boot.h" diff --git a/hw/pl031.c b/hw/pl031.c index 834a20c917..3a23ecde48 100644 --- a/hw/pl031.c +++ b/hw/pl031.c @@ -13,7 +13,7 @@ #include "sysbus.h" #include "qemu/timer.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" //#define DEBUG_PL031 diff --git a/hw/pl181.c b/hw/pl181.c index 8a2895ce1b..cbddb741ce 100644 --- a/hw/pl181.c +++ b/hw/pl181.c @@ -7,7 +7,7 @@ * This code is licensed under the GPL. */ -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "sysbus.h" #include "sd.h" diff --git a/hw/ppc.c b/hw/ppc.c index f066367609..1559982625 100644 --- a/hw/ppc.c +++ b/hw/ppc.c @@ -24,11 +24,11 @@ #include "hw.h" #include "ppc.h" #include "qemu/timer.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "nvram.h" #include "qemu/log.h" #include "loader.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "kvm_ppc.h" //#define PPC_DEBUG_IRQ diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 3593f7c0e2..aa54fd84d7 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -24,10 +24,10 @@ #include "hw/serial.h" #include "hw/pci/pci.h" #include "hw/boards.h" -#include "sysemu.h" -#include "kvm.h" +#include "sysemu/sysemu.h" +#include "sysemu/kvm.h" #include "kvm_ppc.h" -#include "device_tree.h" +#include "sysemu/device_tree.h" #include "hw/openpic.h" #include "hw/ppc.h" #include "hw/loader.h" diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c index 2992bd9794..4deb02ac38 100644 --- a/hw/ppc/e500plat.c +++ b/hw/ppc/e500plat.c @@ -13,8 +13,8 @@ #include "qemu-common.h" #include "e500.h" #include "../boards.h" -#include "device_tree.h" -#include "hw/pci.h" +#include "sysemu/device_tree.h" +#include "hw/pci/pci.h" static void e500plat_fixup_devtree(PPCE500Params *params, void *fdt) { diff --git a/hw/ppc/mpc8544ds.c b/hw/ppc/mpc8544ds.c index 7e1761d20c..f9ae20f5a3 100644 --- a/hw/ppc/mpc8544ds.c +++ b/hw/ppc/mpc8544ds.c @@ -13,7 +13,7 @@ #include "qemu-common.h" #include "e500.h" #include "../boards.h" -#include "device_tree.h" +#include "sysemu/device_tree.h" static void mpc8544ds_fixup_devtree(PPCE500Params *params, void *fdt) { diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c index 31bcc4bb95..8f7f0d07d1 100644 --- a/hw/ppc405_boards.c +++ b/hw/ppc405_boards.c @@ -26,12 +26,12 @@ #include "ppc405.h" #include "nvram.h" #include "flash.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "block/block.h" #include "boards.h" #include "qemu/log.h" #include "loader.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" #define BIOS_FILENAME "ppc405_rom.bin" diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c index b1ed8837d6..7e56ecb4af 100644 --- a/hw/ppc405_uc.c +++ b/hw/ppc405_uc.c @@ -26,7 +26,7 @@ #include "ppc405.h" #include "serial.h" #include "qemu/timer.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/log.h" #include "exec/address-spaces.h" diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c index 591d7b0088..4f1b734c22 100644 --- a/hw/ppc440_bamboo.c +++ b/hw/ppc440_bamboo.c @@ -17,16 +17,16 @@ #include "hw.h" #include "pci/pci.h" #include "boards.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "kvm_ppc.h" -#include "device_tree.h" +#include "sysemu/device_tree.h" #include "loader.h" #include "elf.h" #include "exec/address-spaces.h" #include "serial.h" #include "ppc.h" #include "ppc405.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "sysbus.h" #define BINARY_DEVICE_TREE_FILE "bamboo.dtb" diff --git a/hw/ppc_booke.c b/hw/ppc_booke.c index a7182be0d3..5c89fc313d 100644 --- a/hw/ppc_booke.c +++ b/hw/ppc_booke.c @@ -24,7 +24,7 @@ #include "hw.h" #include "ppc.h" #include "qemu/timer.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "nvram.h" #include "qemu/log.h" #include "loader.h" diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index b2d02eaff2..fabcc08b40 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -54,7 +54,7 @@ #include "nvram.h" #include "pci/pci.h" #include "net/net.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "fw_cfg.h" #include "escc.h" @@ -62,10 +62,10 @@ #include "ide.h" #include "loader.h" #include "elf.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "kvm_ppc.h" #include "hw/usb.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" #include "sysbus.h" diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index 7a8a039d7e..fff5129ca9 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -29,7 +29,7 @@ #include "adb.h" #include "mac_dbdma.h" #include "nvram.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "net/net.h" #include "isa.h" #include "pci/pci.h" @@ -39,9 +39,9 @@ #include "ide.h" #include "loader.h" #include "elf.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "kvm_ppc.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" #define MAX_IDE_BUS 2 diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index 072535294e..9c78c863e8 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -27,7 +27,7 @@ #include "serial.h" #include "fdc.h" #include "net/net.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "isa.h" #include "pci/pci.h" #include "pci/pci_host.h" @@ -37,8 +37,8 @@ #include "ide.h" #include "loader.h" #include "mc146818rtc.h" -#include "blockdev.h" -#include "arch_init.h" +#include "sysemu/blockdev.h" +#include "sysemu/arch_init.h" #include "exec/address-spaces.h" //#define HARD_DEBUG_PPC_IO diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c index c1a155bd31..177aa2d122 100644 --- a/hw/ppce500_spin.c +++ b/hw/ppce500_spin.c @@ -28,9 +28,9 @@ */ #include "hw.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "sysbus.h" -#include "kvm.h" +#include "sysemu/kvm.h" #define MAX_CPUS 32 diff --git a/hw/ps2.c b/hw/ps2.c index ba80089aba..15cfd5bb76 100644 --- a/hw/ps2.c +++ b/hw/ps2.c @@ -24,7 +24,7 @@ #include "hw.h" #include "ps2.h" #include "ui/console.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" /* debug PC keyboard */ //#define DEBUG_KBD diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c index e616979207..936e9f87cd 100644 --- a/hw/pxa2xx.c +++ b/hw/pxa2xx.c @@ -9,12 +9,12 @@ #include "sysbus.h" #include "pxa.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "serial.h" #include "i2c.h" #include "ssi.h" #include "qemu-char.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" static struct { hwaddr io_base; diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c index b5efd4d426..512a27e702 100644 --- a/hw/pxa2xx_lcd.c +++ b/hw/pxa2xx_lcd.c @@ -15,7 +15,7 @@ #include "pxa.h" #include "ui/pixel_ops.h" /* FIXME: For graphic_rotate. Should probably be done in common code. */ -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "framebuffer.h" struct DMAChannel { diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c index 1481c6d3e1..e4ffb15bb2 100644 --- a/hw/pxa2xx_timer.c +++ b/hw/pxa2xx_timer.c @@ -9,7 +9,7 @@ #include "hw.h" #include "qemu/timer.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "pxa.h" #include "sysbus.h" diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c index 1c6712e6de..b73986759b 100644 --- a/hw/qdev-monitor.c +++ b/hw/qdev-monitor.c @@ -20,7 +20,7 @@ #include "qdev.h" #include "monitor/monitor.h" #include "qmp-commands.h" -#include "arch_init.h" +#include "sysemu/arch_init.h" #include "qemu/config-file.h" /* diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index ba6c648fed..1cb97ea594 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -1,7 +1,7 @@ #include "net/net.h" #include "qdev.h" #include "qapi/qmp/qerror.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "hw/block-common.h" #include "net/hub.h" #include "qapi/visitor.h" diff --git a/hw/qdev.c b/hw/qdev.c index 0a2a32d5d3..c4a9857a05 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -27,7 +27,7 @@ #include "net/net.h" #include "qdev.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qapi/error.h" #include "qapi/visitor.h" diff --git a/hw/qxl.c b/hw/qxl.c index b88a39cc93..d08b9bd3c1 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -24,7 +24,7 @@ #include "qemu/timer.h" #include "qemu/queue.h" #include "monitor/monitor.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "trace.h" #include "qxl.h" diff --git a/hw/r2d.c b/hw/r2d.c index d7a26bf398..7cf1893d19 100644 --- a/hw/r2d.c +++ b/hw/r2d.c @@ -27,7 +27,7 @@ #include "hw.h" #include "sh.h" #include "devices.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "pci/pci.h" #include "net/net.h" @@ -36,7 +36,7 @@ #include "loader.h" #include "usb.h" #include "flash.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" #define FLASH_BASE 0x00000000 diff --git a/hw/realview.c b/hw/realview.c index 9c55bf29b7..872b3b468a 100644 --- a/hw/realview.c +++ b/hw/realview.c @@ -13,10 +13,10 @@ #include "devices.h" #include "pci/pci.h" #include "net/net.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "i2c.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" #define SMP_BOOT_ADDR 0xe0000000 diff --git a/hw/rtl8139.c b/hw/rtl8139.c index 19c31a02c6..c59ec6b6df 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -53,11 +53,11 @@ #include "hw.h" #include "pci/pci.h" -#include "dma.h" +#include "sysemu/dma.h" #include "qemu/timer.h" #include "net/net.h" #include "loader.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/iov.h" /* debug RTL8139 card */ diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index 769015c136..963b4f0dc2 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -19,7 +19,7 @@ #include "hw.h" #include "block/block.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "monitor/monitor.h" #include "loader.h" @@ -29,7 +29,7 @@ #include "hw/virtio-serial.h" #include "hw/virtio-net.h" #include "hw/sysbus.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "hw/s390-virtio-bus.h" diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index 7dfe87ade3..20827761d0 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -19,8 +19,8 @@ #include "hw.h" #include "block/block.h" -#include "blockdev.h" -#include "sysemu.h" +#include "sysemu/blockdev.h" +#include "sysemu/sysemu.h" #include "net/net.h" #include "boards.h" #include "monitor/monitor.h" @@ -28,7 +28,7 @@ #include "elf.h" #include "hw/virtio.h" #include "hw/sysbus.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "exec/address-spaces.h" #include "hw/s390-virtio-bus.h" diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c index 748118d0f0..89b1b66bd2 100644 --- a/hw/s390x/event-facility.c +++ b/hw/s390x/event-facility.c @@ -16,7 +16,7 @@ */ #include "monitor/monitor.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "sclp.h" #include "event-facility.h" diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c index bc9b0aeb00..7ad791d5e3 100644 --- a/hw/s390x/sclp.c +++ b/hw/s390x/sclp.c @@ -13,7 +13,7 @@ */ #include "cpu.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "exec/memory.h" #include "sclp.h" diff --git a/hw/s390x/sclpquiesce.c b/hw/s390x/sclpquiesce.c index 9a773b87ff..6e6f5624df 100644 --- a/hw/s390x/sclpquiesce.c +++ b/hw/s390x/sclpquiesce.c @@ -12,7 +12,7 @@ * */ #include -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "sclp.h" #include "event-facility.h" diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 5dc9f512b5..970c1fc01b 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -3,9 +3,9 @@ #include "scsi.h" #include "scsi-defs.h" #include "qdev.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "trace.h" -#include "dma.h" +#include "sysemu/dma.h" static char *scsibus_get_dev_path(DeviceState *dev); static char *scsibus_get_fw_dev_path(DeviceState *dev); diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index c65da4a9c9..a69735b0a6 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -32,10 +32,10 @@ do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0) #include "qemu/error-report.h" #include "scsi.h" #include "scsi-defs.h" -#include "sysemu.h" -#include "blockdev.h" +#include "sysemu/sysemu.h" +#include "sysemu/blockdev.h" #include "hw/block-common.h" -#include "dma.h" +#include "sysemu/dma.h" #ifdef __linux #include diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index faeb61ee2c..4c702be19f 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -14,7 +14,7 @@ #include "qemu-common.h" #include "qemu/error-report.h" #include "scsi.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #ifdef __linux__ diff --git a/hw/scsi.h b/hw/scsi.h index 24ed522722..a5b5b2ec0d 100644 --- a/hw/scsi.h +++ b/hw/scsi.h @@ -4,7 +4,7 @@ #include "qdev.h" #include "block/block.h" #include "hw/block-common.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #define MAX_SCSI_DEVS 255 diff --git a/hw/serial.h b/hw/serial.h index 5722f8a353..98ee4241be 100644 --- a/hw/serial.h +++ b/hw/serial.h @@ -26,7 +26,7 @@ #define HW_SERIAL_H 1 #include "hw.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "exec/memory.h" #define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */ diff --git a/hw/sga.c b/hw/sga.c index 5d80efd0c2..d5c91ed98e 100644 --- a/hw/sga.c +++ b/hw/sga.c @@ -27,7 +27,7 @@ #include "pci/pci.h" #include "pc.h" #include "loader.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #define SGABIOS_FILENAME "sgabios.bin" diff --git a/hw/sh7750.c b/hw/sh7750.c index 08945750c4..666f8655ed 100644 --- a/hw/sh7750.c +++ b/hw/sh7750.c @@ -25,7 +25,7 @@ #include #include "hw.h" #include "sh.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "sh7750_regs.h" #include "sh7750_regnames.h" #include "sh_intc.h" diff --git a/hw/shix.c b/hw/shix.c index 821196e84c..86d703ad70 100644 --- a/hw/shix.c +++ b/hw/shix.c @@ -29,7 +29,7 @@ */ #include "hw.h" #include "sh.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "loader.h" #include "exec/address-spaces.h" diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c index 682fb457f5..704f2b173b 100644 --- a/hw/slavio_misc.c +++ b/hw/slavio_misc.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "sysbus.h" #include "trace.h" diff --git a/hw/smbios.c b/hw/smbios.c index c57237d279..a7b8bfc383 100644 --- a/hw/smbios.c +++ b/hw/smbios.c @@ -13,7 +13,7 @@ * GNU GPL, version 2 or (at your option) any later version. */ -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "smbios.h" #include "loader.h" diff --git a/hw/smbus_ich9.c b/hw/smbus_ich9.c index b7bddc80d3..16db3a743c 100644 --- a/hw/smbus_ich9.c +++ b/hw/smbus_ich9.c @@ -28,7 +28,7 @@ #include "pc.h" #include "pm_smbus.h" #include "pci/pci.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "i2c.h" #include "smbus.h" diff --git a/hw/spapr.c b/hw/spapr.c index 1abfde2a05..fdd1eb6925 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -24,13 +24,13 @@ * THE SOFTWARE. * */ -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "hw.h" #include "elf.h" #include "net/net.h" -#include "blockdev.h" -#include "cpus.h" -#include "kvm.h" +#include "sysemu/blockdev.h" +#include "sysemu/cpus.h" +#include "sysemu/kvm.h" #include "kvm_ppc.h" #include "hw/boards.h" @@ -43,7 +43,7 @@ #include "hw/xics.h" #include "hw/pci/msi.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "kvm_ppc.h" #include "pci/pci.h" diff --git a/hw/spapr.h b/hw/spapr.h index 600722f132..3a1f69f2a9 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -1,7 +1,7 @@ #if !defined(__HW_SPAPR_H__) #define __HW_SPAPR_H__ -#include "dma.h" +#include "sysemu/dma.h" #include "hw/xics.h" struct VIOsPAPRBus; diff --git a/hw/spapr_events.c b/hw/spapr_events.c index 18ccd4a9e0..7956601466 100644 --- a/hw/spapr_events.c +++ b/hw/spapr_events.c @@ -25,10 +25,10 @@ * */ #include "cpu.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu-char.h" #include "hw/qdev.h" -#include "device_tree.h" +#include "sysemu/device_tree.h" #include "hw/spapr.h" #include "hw/spapr_vio.h" diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c index 1fac362329..afb12973f2 100644 --- a/hw/spapr_hcall.c +++ b/hw/spapr_hcall.c @@ -1,6 +1,6 @@ -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "cpu.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "helper_regs.h" #include "hw/spapr.h" diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c index fb968b250b..d8a098cb1b 100644 --- a/hw/spapr_iommu.c +++ b/hw/spapr_iommu.c @@ -17,10 +17,10 @@ * License along with this library; if not, see . */ #include "hw.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "qdev.h" #include "kvm_ppc.h" -#include "dma.h" +#include "sysemu/dma.h" #include "exec/address-spaces.h" #include "hw/spapr.h" diff --git a/hw/spapr_nvram.c b/hw/spapr_nvram.c index 512bb8d5d1..f20f6b4fdd 100644 --- a/hw/spapr_nvram.c +++ b/hw/spapr_nvram.c @@ -24,7 +24,7 @@ #include #include -#include "device_tree.h" +#include "sysemu/device_tree.h" #include "hw/sysbus.h" #include "hw/spapr.h" #include "hw/spapr_vio.h" diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c index e618c2db53..d29736285c 100644 --- a/hw/spapr_rtas.c +++ b/hw/spapr_rtas.c @@ -25,10 +25,10 @@ * */ #include "cpu.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu-char.h" #include "hw/qdev.h" -#include "device_tree.h" +#include "sysemu/device_tree.h" #include "hw/spapr.h" #include "hw/spapr_vio.h" diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index fdf8db9158..a58621d17e 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -20,14 +20,14 @@ */ #include "hw.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "monitor/monitor.h" #include "loader.h" #include "elf.h" #include "hw/sysbus.h" -#include "kvm.h" -#include "device_tree.h" +#include "sysemu/kvm.h" +#include "sysemu/device_tree.h" #include "kvm_ppc.h" #include "hw/spapr.h" diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h index cc85d26101..f98ec0a2e5 100644 --- a/hw/spapr_vio.h +++ b/hw/spapr_vio.h @@ -21,7 +21,7 @@ * License along with this library; if not, see . */ -#include "dma.h" +#include "sysemu/dma.h" #define TYPE_VIO_SPAPR_DEVICE "vio-spapr-device" #define VIO_SPAPR_DEVICE(obj) \ diff --git a/hw/spitz.c b/hw/spitz.c index 1259e32974..8e1be7fb21 100644 --- a/hw/spitz.c +++ b/hw/spitz.c @@ -13,7 +13,7 @@ #include "hw.h" #include "pxa.h" #include "arm-misc.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "pcmcia.h" #include "i2c.h" #include "ssi.h" @@ -25,7 +25,7 @@ #include "block/block.h" #include "audio/audio.h" #include "boards.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "sysbus.h" #include "exec/address-spaces.h" diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c index c5505ee24f..d61c3328d9 100644 --- a/hw/ssi-sd.c +++ b/hw/ssi-sd.c @@ -10,7 +10,7 @@ * GNU GPL, version 2 or (at your option) any later version. */ -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "ssi.h" #include "sd.h" diff --git a/hw/strongarm.c b/hw/strongarm.c index f776fee3bc..5d5f454b1d 100644 --- a/hw/strongarm.c +++ b/hw/strongarm.c @@ -31,7 +31,7 @@ #include "qemu/error-report.h" #include "arm-misc.h" #include "qemu-char.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "ssi.h" //#define DEBUG diff --git a/hw/sun4m.c b/hw/sun4m.c index 4245854949..0d84b373b1 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -27,7 +27,7 @@ #include "nvram.h" #include "sparc32_dma.h" #include "fdc.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "net/net.h" #include "boards.h" #include "firmware_abi.h" @@ -40,7 +40,7 @@ #include "qdev-addr.h" #include "loader.h" #include "elf.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "trace.h" /* diff --git a/hw/sun4u.c b/hw/sun4u.c index 8bca4fdff9..cbfd217587 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -30,7 +30,7 @@ #include "fdc.h" #include "net/net.h" #include "qemu/timer.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "firmware_abi.h" #include "fw_cfg.h" @@ -38,7 +38,7 @@ #include "ide.h" #include "loader.h" #include "elf.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" //#define DEBUG_IRQ diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c index edf76817b5..e815f83198 100644 --- a/hw/tc6393xb.c +++ b/hw/tc6393xb.c @@ -15,7 +15,7 @@ #include "flash.h" #include "ui/console.h" #include "ui/pixel_ops.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #define IRQ_TC6393_NAND 0 #define IRQ_TC6393_MMC 1 diff --git a/hw/tosa.c b/hw/tosa.c index 6fdbec53ee..6ee4693840 100644 --- a/hw/tosa.c +++ b/hw/tosa.c @@ -21,7 +21,7 @@ #include "boards.h" #include "i2c.h" #include "ssi.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "sysbus.h" #include "exec/address-spaces.h" diff --git a/hw/twl92230.c b/hw/twl92230.c index 3210b9ef4e..c71e4a2af0 100644 --- a/hw/twl92230.c +++ b/hw/twl92230.c @@ -22,7 +22,7 @@ #include "hw.h" #include "qemu/timer.h" #include "i2c.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "ui/console.h" #define VERBOSE 1 diff --git a/hw/usb/bus.c b/hw/usb/bus.c index 74728c94e5..10260a13ac 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -1,7 +1,7 @@ #include "hw/hw.h" #include "hw/usb.h" #include "hw/qdev.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "monitor/monitor.h" #include "trace.h" diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index e8ada9f02c..1c54863452 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -29,7 +29,7 @@ #include "net/net.h" #include "qemu/queue.h" #include "qemu/config-file.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/iov.h" /*#define TRAFFIC_DEBUG*/ diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 6d27bac94f..5025597673 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -15,8 +15,8 @@ #include "hw/scsi.h" #include "ui/console.h" #include "monitor/monitor.h" -#include "sysemu.h" -#include "blockdev.h" +#include "sysemu/sysemu.h" +#include "sysemu/blockdev.h" //#define DEBUG_MSD diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index 5bc80031bf..e35144d386 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -22,8 +22,8 @@ #include "hw/usb.h" #include "monitor/monitor.h" #include "trace.h" -#include "dma.h" -#include "sysemu.h" +#include "sysemu/dma.h" +#include "sysemu/sysemu.h" #ifndef EHCI_DEBUG #define EHCI_DEBUG 0 diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index c9b8a31465..2af754b5cf 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -30,7 +30,7 @@ #include "hw/pci/pci.h" #include "qemu/timer.h" #include "qemu/iov.h" -#include "dma.h" +#include "sysemu/dma.h" #include "trace.h" //#define DEBUG diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c index 9a8c26ceaf..669fbd245c 100644 --- a/hw/usb/host-linux.c +++ b/hw/usb/host-linux.c @@ -33,7 +33,7 @@ #include "qemu-common.h" #include "qemu/timer.h" #include "monitor/monitor.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "trace.h" #include diff --git a/hw/usb/libhw.c b/hw/usb/libhw.c index 672d7a5598..75f022f4ec 100644 --- a/hw/usb/libhw.c +++ b/hw/usb/libhw.c @@ -22,7 +22,7 @@ #include "qemu-common.h" #include "exec/cpu-common.h" #include "hw/usb.h" -#include "dma.h" +#include "sysemu/dma.h" int usb_packet_map(USBPacket *p, QEMUSGList *sgl) { diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 31e5f27595..b65e8682b6 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -28,7 +28,7 @@ #include "qemu-common.h" #include "qemu/timer.h" #include "monitor/monitor.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/iov.h" #include diff --git a/hw/versatilepb.c b/hw/versatilepb.c index bd9c01564a..5e89e747a2 100644 --- a/hw/versatilepb.c +++ b/hw/versatilepb.c @@ -11,11 +11,11 @@ #include "arm-misc.h" #include "devices.h" #include "net/net.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "pci/pci.h" #include "i2c.h" #include "boards.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "exec/address-spaces.h" #include "flash.h" diff --git a/hw/vexpress.c b/hw/vexpress.c index e7b9e93852..93c3176667 100644 --- a/hw/vexpress.c +++ b/hw/vexpress.c @@ -26,10 +26,10 @@ #include "primecell.h" #include "devices.h" #include "net/net.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "exec/address-spaces.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "flash.h" #define VEXPRESS_BOARD_ID 0x8e0 diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 9f204bc113..41fb7ad1de 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -29,7 +29,7 @@ #include "config.h" #include "qemu/event_notifier.h" #include "exec/address-spaces.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "exec/memory.h" #include "pci/msi.h" #include "pci/msix.h" diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c index 5134e2f477..5238c7cbd6 100644 --- a/hw/virtex_ml507.c +++ b/hw/virtex_ml507.c @@ -26,10 +26,10 @@ #include "hw.h" #include "serial.h" #include "flash.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "devices.h" #include "boards.h" -#include "device_tree.h" +#include "sysemu/device_tree.h" #include "loader.h" #include "elf.h" #include "qemu/log.h" @@ -39,7 +39,7 @@ #include "ppc4xx.h" #include "ppc405.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "xilinx.h" #define EPAPR_MAGIC (0x45504150) diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c index 2eb709b422..3040bc63ab 100644 --- a/hw/virtio-balloon.c +++ b/hw/virtio-balloon.c @@ -18,9 +18,9 @@ #include "virtio.h" #include "pc.h" #include "cpu.h" -#include "balloon.h" +#include "sysemu/balloon.h" #include "virtio-balloon.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "exec/address-spaces.h" #if defined(__linux__) diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 208caa2642..90cfa246db 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -15,7 +15,7 @@ #include "qemu/error-report.h" #include "trace.h" #include "hw/block-common.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "virtio-blk.h" #include "scsi-defs.h" #ifdef __linux__ diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index f58917f75f..d2d2454493 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -27,8 +27,8 @@ #include "pci/msi.h" #include "pci/msix.h" #include "loader.h" -#include "kvm.h" -#include "blockdev.h" +#include "sysemu/kvm.h" +#include "sysemu/blockdev.h" #include "virtio-pci.h" #include "qemu/range.h" diff --git a/hw/virtio.h b/hw/virtio.h index 511a16992e..541600484e 100644 --- a/hw/virtio.h +++ b/hw/virtio.h @@ -17,7 +17,7 @@ #include "hw.h" #include "net/net.h" #include "qdev.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/event_notifier.h" #ifdef CONFIG_LINUX #include "9p.h" diff --git a/hw/vmport.c b/hw/vmport.c index 3ab3a1405c..7d425237ac 100644 --- a/hw/vmport.c +++ b/hw/vmport.c @@ -24,7 +24,7 @@ #include "hw.h" #include "isa.h" #include "pc.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "qdev.h" //#define VMPORT_DEBUG diff --git a/hw/vt82c686.c b/hw/vt82c686.c index a18aaed217..d3469d49f1 100644 --- a/hw/vt82c686.c +++ b/hw/vt82c686.c @@ -22,7 +22,7 @@ #include "apm.h" #include "acpi.h" #include "pm_smbus.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/timer.h" #include "exec/address-spaces.h" diff --git a/hw/watchdog.c b/hw/watchdog.c index 5b04215374..072d256882 100644 --- a/hw/watchdog.c +++ b/hw/watchdog.c @@ -25,7 +25,7 @@ #include "qemu/queue.h" #include "qapi/qmp/types.h" #include "monitor/monitor.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "hw/watchdog.h" /* Possible values for action parameter. */ diff --git a/hw/xen_backend.h b/hw/xen_backend.h index 92ab501d37..f37afb1f05 100644 --- a/hw/xen_backend.h +++ b/hw/xen_backend.h @@ -2,7 +2,7 @@ #define QEMU_HW_XEN_BACKEND_H 1 #include "xen_common.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "net/net.h" /* ------------------------------------------------------------- */ diff --git a/hw/xen_devconfig.c b/hw/xen_devconfig.c index d83e8d0f64..e2ba741d54 100644 --- a/hw/xen_devconfig.c +++ b/hw/xen_devconfig.c @@ -1,5 +1,5 @@ #include "xen_backend.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" /* ------------------------------------------------------------- */ diff --git a/hw/xen_disk.c b/hw/xen_disk.c index 423b580cff..a6a64a2455 100644 --- a/hw/xen_disk.c +++ b/hw/xen_disk.c @@ -38,7 +38,7 @@ #include "hw.h" #include "xen_backend.h" #include "xen_blkif.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" /* ------------------------------------------------------------- */ diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c index 426470351e..9feecd5a27 100644 --- a/hw/xen_machine_pv.c +++ b/hw/xen_machine_pv.c @@ -27,7 +27,7 @@ #include "boards.h" #include "xen_backend.h" #include "xen_domainbuild.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" static void xen_init_pv(QEMUMachineInitArgs *args) { diff --git a/hw/xilinx_spi.c b/hw/xilinx_spi.c index 4eed1828e3..77f9178008 100644 --- a/hw/xilinx_spi.c +++ b/hw/xilinx_spi.c @@ -25,7 +25,7 @@ */ #include "sysbus.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/log.h" #include "fifo.h" diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c index ebe375e56f..42e019dc05 100644 --- a/hw/xilinx_spips.c +++ b/hw/xilinx_spips.c @@ -23,7 +23,7 @@ */ #include "sysbus.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "ptimer.h" #include "qemu/log.h" #include "fifo.h" diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c index 156648a5d1..da0a7d0aa1 100644 --- a/hw/xilinx_zynq.c +++ b/hw/xilinx_zynq.c @@ -19,10 +19,10 @@ #include "arm-misc.h" #include "net/net.h" #include "exec/address-spaces.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "flash.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "loader.h" #include "ssi.h" diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c index c6c880eba5..9c7bb75f81 100644 --- a/hw/xtensa_lx60.c +++ b/hw/xtensa_lx60.c @@ -25,7 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "loader.h" #include "elf.h" @@ -35,7 +35,7 @@ #include "net/net.h" #include "sysbus.h" #include "flash.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "qemu-char.h" #include "xtensa_bootparam.h" diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c index 29b5f22a18..14fe85b2fc 100644 --- a/hw/xtensa_sim.c +++ b/hw/xtensa_sim.c @@ -25,7 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "boards.h" #include "loader.h" #include "elf.h" diff --git a/hw/z2.c b/hw/z2.c index ec35f3e444..09b03687d1 100644 --- a/hw/z2.c +++ b/hw/z2.c @@ -18,9 +18,9 @@ #include "i2c.h" #include "ssi.h" #include "boards.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "flash.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "ui/console.h" #include "audio/audio.h" #include "exec/address-spaces.h" diff --git a/hw/zynq_slcr.c b/hw/zynq_slcr.c index c7ce51f4a6..97ec578262 100644 --- a/hw/zynq_slcr.c +++ b/hw/zynq_slcr.c @@ -17,7 +17,7 @@ #include "hw.h" #include "qemu/timer.h" #include "sysbus.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #ifdef ZYNQ_ARM_SLCR_ERR_DEBUG #define DB_PRINT(...) do { \ diff --git a/arch_init.h b/include/sysemu/arch_init.h similarity index 100% rename from arch_init.h rename to include/sysemu/arch_init.h diff --git a/balloon.h b/include/sysemu/balloon.h similarity index 100% rename from balloon.h rename to include/sysemu/balloon.h diff --git a/blockdev.h b/include/sysemu/blockdev.h similarity index 100% rename from blockdev.h rename to include/sysemu/blockdev.h diff --git a/cpus.h b/include/sysemu/cpus.h similarity index 100% rename from cpus.h rename to include/sysemu/cpus.h diff --git a/device_tree.h b/include/sysemu/device_tree.h similarity index 100% rename from device_tree.h rename to include/sysemu/device_tree.h diff --git a/dma.h b/include/sysemu/dma.h similarity index 99% rename from dma.h rename to include/sysemu/dma.h index fd68f74c5b..a52c93a553 100644 --- a/dma.h +++ b/include/sysemu/dma.h @@ -14,7 +14,7 @@ #include "exec/memory.h" #include "hw/hw.h" #include "block/block.h" -#include "kvm.h" +#include "sysemu/kvm.h" typedef struct DMAContext DMAContext; typedef struct ScatterGatherEntry ScatterGatherEntry; diff --git a/dump.h b/include/sysemu/dump.h similarity index 100% rename from dump.h rename to include/sysemu/dump.h diff --git a/kvm.h b/include/sysemu/kvm.h similarity index 100% rename from kvm.h rename to include/sysemu/kvm.h diff --git a/memory_mapping.h b/include/sysemu/memory_mapping.h similarity index 100% rename from memory_mapping.h rename to include/sysemu/memory_mapping.h diff --git a/qemu-os-posix.h b/include/sysemu/os-posix.h similarity index 100% rename from qemu-os-posix.h rename to include/sysemu/os-posix.h diff --git a/qemu-os-win32.h b/include/sysemu/os-win32.h similarity index 100% rename from qemu-os-win32.h rename to include/sysemu/os-win32.h diff --git a/qtest.h b/include/sysemu/qtest.h similarity index 100% rename from qtest.h rename to include/sysemu/qtest.h diff --git a/qemu-seccomp.h b/include/sysemu/seccomp.h similarity index 100% rename from qemu-seccomp.h rename to include/sysemu/seccomp.h diff --git a/sysemu.h b/include/sysemu/sysemu.h similarity index 100% rename from sysemu.h rename to include/sysemu/sysemu.h diff --git a/xen-mapcache.h b/include/sysemu/xen-mapcache.h similarity index 100% rename from xen-mapcache.h rename to include/sysemu/xen-mapcache.h diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h index a0d1a50487..8b192e9613 100644 --- a/include/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -21,7 +21,7 @@ #include "qemu/thread.h" #include "ui/qemu-pixman.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #define NUM_MEMSLOTS 8 #define MEMSLOT_GENERATION_BITS 8 diff --git a/kvm-all.c b/kvm-all.c index 41ea3aa6ee..5aa65c4c15 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -24,11 +24,11 @@ #include "qemu/atomic.h" #include "qemu/option.h" #include "qemu/config-file.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "hw/hw.h" #include "hw/pci/msi.h" #include "exec/gdbstub.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "qemu/bswap.h" #include "exec/memory.h" #include "exec/address-spaces.h" diff --git a/kvm-stub.c b/kvm-stub.c index 8de8ebd3d2..5b971521cd 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -15,7 +15,7 @@ #include "hw/pci/msi.h" #include "cpu.h" #include "exec/gdbstub.h" -#include "kvm.h" +#include "sysemu/kvm.h" KVMState *kvm_state; bool kvm_kernel_irqchip; diff --git a/memory.c b/memory.c index d44200335b..35e6122dd7 100644 --- a/memory.c +++ b/memory.c @@ -17,7 +17,7 @@ #include "exec/address-spaces.h" #include "exec/ioport.h" #include "qemu/bitops.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include #include "exec/memory-internal.h" diff --git a/memory_mapping-stub.c b/memory_mapping-stub.c index 5f5fb99c58..24d5d67371 100644 --- a/memory_mapping-stub.c +++ b/memory_mapping-stub.c @@ -13,7 +13,7 @@ #include "cpu.h" #include "exec/cpu-all.h" -#include "memory_mapping.h" +#include "sysemu/memory_mapping.h" int qemu_get_guest_memory_mapping(MemoryMappingList *list) { diff --git a/memory_mapping.c b/memory_mapping.c index c829a9fa34..530f1d6793 100644 --- a/memory_mapping.c +++ b/memory_mapping.c @@ -13,7 +13,7 @@ #include "cpu.h" #include "exec/cpu-all.h" -#include "memory_mapping.h" +#include "sysemu/memory_mapping.h" static void memory_mapping_list_add_mapping_sorted(MemoryMappingList *list, MemoryMapping *mapping) diff --git a/migration.c b/migration.c index 8c5c5670d8..810f25e7eb 100644 --- a/migration.c +++ b/migration.c @@ -17,7 +17,7 @@ #include "migration/migration.h" #include "monitor/monitor.h" #include "buffered_file.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "block/block.h" #include "qemu/sockets.h" #include "migration/block.h" diff --git a/monitor.c b/monitor.c index 878b2317af..200bef452f 100644 --- a/monitor.c +++ b/monitor.c @@ -35,17 +35,17 @@ #include "net/slirp.h" #include "qemu-char.h" #include "ui/qemu-spice.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "monitor/monitor.h" #include "monitor/readline.h" #include "ui/console.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "audio/audio.h" #include "disas/disas.h" -#include "balloon.h" +#include "sysemu/balloon.h" #include "qemu/timer.h" #include "migration/migration.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "qemu/acl.h" #include "qapi/qmp/qint.h" #include "qapi/qmp/qfloat.h" diff --git a/net/tap-bsd.c b/net/tap-bsd.c index b48182f678..01c705b4c0 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -24,7 +24,7 @@ #include "tap_int.h" #include "qemu-common.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/error-report.h" #ifdef __NetBSD__ diff --git a/net/tap-linux.c b/net/tap-linux.c index dd4b915243..059f5f34ab 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -30,7 +30,7 @@ #include #include -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu-common.h" #include "qemu/error-report.h" diff --git a/net/tap-solaris.c b/net/tap-solaris.c index 3d5fee5542..486a7ea838 100644 --- a/net/tap-solaris.c +++ b/net/tap-solaris.c @@ -23,7 +23,7 @@ */ #include "tap_int.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include #include diff --git a/net/tap-win32.c b/net/tap-win32.c index 1ddd6fa6e6..0c63cbd203 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -31,7 +31,7 @@ #include "qemu-common.h" #include "clients.h" /* net_init_tap */ #include "net/net.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/error-report.h" #include #include diff --git a/net/tap.c b/net/tap.c index d34ff13398..eb40c42d7d 100644 --- a/net/tap.c +++ b/net/tap.c @@ -36,7 +36,7 @@ #include "net/net.h" #include "clients.h" #include "monitor/monitor.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu-common.h" #include "qemu/error-report.h" diff --git a/os-posix.c b/os-posix.c index 488e48005f..5c64518902 100644 --- a/os-posix.c +++ b/os-posix.c @@ -36,7 +36,7 @@ /* Needed early for CONFIG_BSD etc. */ #include "config-host.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "net/slirp.h" #include "qemu-options.h" diff --git a/os-win32.c b/os-win32.c index 13892ba320..9673a81c7d 100644 --- a/os-win32.c +++ b/os-win32.c @@ -30,7 +30,7 @@ #include #include #include "config-host.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu-options.h" /***********************************************************/ diff --git a/oslib-posix.c b/oslib-posix.c index a737d6e0e3..4f5ec6788b 100644 --- a/oslib-posix.c +++ b/oslib-posix.c @@ -49,7 +49,7 @@ extern int daemon(int, int); #endif #include "config-host.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "trace.h" #include "qemu/sockets.h" diff --git a/oslib-win32.c b/oslib-win32.c index 7f0dd07e5f..e7e283e875 100644 --- a/oslib-win32.c +++ b/oslib-win32.c @@ -27,7 +27,7 @@ */ #include #include "config-host.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/main-loop.h" #include "trace.h" #include "qemu/sockets.h" diff --git a/qemu-char.c b/qemu-char.c index 5a8d8f75a4..0cbe85318e 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -24,7 +24,7 @@ #include "qemu-common.h" #include "monitor/monitor.h" #include "ui/console.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/timer.h" #include "qemu-char.h" #include "hw/usb.h" diff --git a/qemu-common.h b/qemu-common.h index 40cd198fc1..6871cab371 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -43,11 +43,11 @@ #include #ifdef _WIN32 -#include "qemu-os-win32.h" +#include "sysemu/os-win32.h" #endif #ifdef CONFIG_POSIX -#include "qemu-os-posix.h" +#include "sysemu/os-posix.h" #endif #ifndef O_LARGEFILE diff --git a/qemu-img.c b/qemu-img.c index 4c8e2f3849..69cc02871b 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -28,7 +28,7 @@ #include "qemu/option.h" #include "qemu/error-report.h" #include "qemu/osdep.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "block/block_int.h" #include #include diff --git a/qemu-progress.c b/qemu-progress.c index 08d67949a1..9a3f96cd47 100644 --- a/qemu-progress.c +++ b/qemu-progress.c @@ -24,7 +24,7 @@ #include "qemu-common.h" #include "qemu/osdep.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include struct progress_state { diff --git a/qemu-seccomp.c b/qemu-seccomp.c index 2a71d6fee9..031da1dfee 100644 --- a/qemu-seccomp.c +++ b/qemu-seccomp.c @@ -14,7 +14,7 @@ */ #include #include -#include "qemu-seccomp.h" +#include "sysemu/seccomp.h" struct QemuSeccompSyscall { int32_t num; diff --git a/qemu-timer.c b/qemu-timer.c index 80b3f2eb31..8fb5c75df7 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "monitor/monitor.h" #include "ui/console.h" diff --git a/qemu-tool.c b/qemu-tool.c index 8ac45ff39b..1a474c45bc 100644 --- a/qemu-tool.c +++ b/qemu-tool.c @@ -19,7 +19,7 @@ #include "qemu/log.h" #include "migration/migration.h" #include "qemu/main-loop.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/sockets.h" #include "slirp/libslirp.h" diff --git a/qmp.c b/qmp.c index 5b3a5d7d03..be63fe1029 100644 --- a/qmp.c +++ b/qmp.c @@ -14,15 +14,15 @@ */ #include "qemu-common.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qmp-commands.h" #include "qemu-char.h" #include "ui/qemu-spice.h" #include "ui/vnc.h" -#include "kvm.h" -#include "arch_init.h" +#include "sysemu/kvm.h" +#include "sysemu/arch_init.h" #include "hw/qdev.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "qom/qom-qobject.h" NameInfo *qmp_query_name(Error **errp) diff --git a/qtest.c b/qtest.c index ebe3963167..468c921310 100644 --- a/qtest.c +++ b/qtest.c @@ -11,14 +11,14 @@ * */ -#include "qtest.h" +#include "sysemu/qtest.h" #include "hw/qdev.h" #include "qemu-char.h" #include "exec/ioport.h" #include "exec/memory.h" #include "hw/irq.h" -#include "sysemu.h" -#include "cpus.h" +#include "sysemu/sysemu.h" +#include "sysemu/cpus.h" #define MAX_IRQ 256 diff --git a/savevm.c b/savevm.c index ea01e9baf6..b2a844f2b1 100644 --- a/savevm.c +++ b/savevm.c @@ -74,14 +74,14 @@ #include "hw/qdev.h" #include "net/net.h" #include "monitor/monitor.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/timer.h" #include "audio/audio.h" #include "migration/migration.h" #include "qemu/sockets.h" #include "qemu/queue.h" #include "qemu/timer.h" -#include "cpus.h" +#include "sysemu/cpus.h" #include "exec/memory.h" #include "qmp-commands.h" #include "trace.h" diff --git a/stubs/arch-query-cpu-def.c b/stubs/arch-query-cpu-def.c index 6eca8527d2..fa6789598a 100644 --- a/stubs/arch-query-cpu-def.c +++ b/stubs/arch-query-cpu-def.c @@ -1,5 +1,5 @@ #include "qemu-common.h" -#include "arch_init.h" +#include "sysemu/arch_init.h" #include "qapi/qmp/qerror.h" CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) diff --git a/target-alpha/sys_helper.c b/target-alpha/sys_helper.c index 2bc2b02815..434a63a97d 100644 --- a/target-alpha/sys_helper.c +++ b/target-alpha/sys_helper.c @@ -19,7 +19,7 @@ #include "cpu.h" #include "helper.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/timer.h" diff --git a/target-arm/cpu.c b/target-arm/cpu.c index b00f5fa547..17875ed0f0 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -23,7 +23,7 @@ #if !defined(CONFIG_USER_ONLY) #include "hw/loader.h" #endif -#include "sysemu.h" +#include "sysemu/sysemu.h" static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque) { diff --git a/target-arm/helper.c b/target-arm/helper.c index eef2acd18a..e343fac853 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2,7 +2,7 @@ #include "exec/gdbstub.h" #include "helper.h" #include "qemu/host-utils.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/bitops.h" #ifndef CONFIG_USER_ONLY diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c index 50d866f4c6..8209ce9ee2 100644 --- a/target-i386/arch_dump.c +++ b/target-i386/arch_dump.c @@ -13,7 +13,7 @@ #include "cpu.h" #include "exec/cpu-all.h" -#include "dump.h" +#include "sysemu/dump.h" #include "elf.h" #ifdef TARGET_X86_64 diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c index 6dfb0f3f56..c6c7874474 100644 --- a/target-i386/arch_memory_mapping.c +++ b/target-i386/arch_memory_mapping.c @@ -13,7 +13,7 @@ #include "cpu.h" #include "exec/cpu-all.h" -#include "memory_mapping.h" +#include "sysemu/memory_mapping.h" /* PAE Paging or IA-32e Paging */ static void walk_pte(MemoryMappingList *list, hwaddr pte_start_addr, diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 8abc5561e9..1837f5af04 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -22,14 +22,14 @@ #include #include "cpu.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "qemu/option.h" #include "qemu/config-file.h" #include "qapi/qmp/qerror.h" #include "qapi/visitor.h" -#include "arch_init.h" +#include "sysemu/arch_init.h" #include "hyperv.h" @@ -38,7 +38,7 @@ #include #endif -#include "sysemu.h" +#include "sysemu/sysemu.h" #ifndef CONFIG_USER_ONLY #include "hw/xen.h" #include "hw/sysbus.h" diff --git a/target-i386/excp_helper.c b/target-i386/excp_helper.c index 64c8346d3b..179ea82f0f 100644 --- a/target-i386/excp_helper.c +++ b/target-i386/excp_helper.c @@ -19,7 +19,7 @@ #include "cpu.h" #include "qemu/log.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "helper.h" #if 0 diff --git a/target-i386/helper.c b/target-i386/helper.c index bd47b8e58e..dca1360962 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -18,9 +18,9 @@ */ #include "cpu.h" -#include "kvm.h" +#include "sysemu/kvm.h" #ifndef CONFIG_USER_ONLY -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "monitor/monitor.h" #endif diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 340ed3f33e..f63b1fbfda 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -21,8 +21,8 @@ #include #include "qemu-common.h" -#include "sysemu.h" -#include "kvm.h" +#include "sysemu/sysemu.h" +#include "sysemu/kvm.h" #include "kvm_i386.h" #include "cpu.h" #include "exec/gdbstub.h" diff --git a/target-i386/kvm_i386.h b/target-i386/kvm_i386.h index f6ab82f93c..4392ab4359 100644 --- a/target-i386/kvm_i386.h +++ b/target-i386/kvm_i386.h @@ -11,7 +11,7 @@ #ifndef QEMU_KVM_I386_H #define QEMU_KVM_I386_H -#include "kvm.h" +#include "sysemu/kvm.h" bool kvm_allows_irq0_override(void); diff --git a/target-i386/machine.c b/target-i386/machine.c index 477150887b..8c1fed1005 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -4,7 +4,7 @@ #include "hw/isa.h" #include "cpu.h" -#include "kvm.h" +#include "sysemu/kvm.h" static const VMStateDescription vmstate_segment = { .name = "segment", diff --git a/target-m68k/m68k-semi.c b/target-m68k/m68k-semi.c index e6c7dd2f9b..239fadbad5 100644 --- a/target-m68k/m68k-semi.c +++ b/target-m68k/m68k-semi.c @@ -36,7 +36,7 @@ #include "exec/gdbstub.h" #include "exec/softmmu-semi.h" #endif -#include "sysemu.h" +#include "sysemu/sysemu.h" #define HOSTED_EXIT 0 #define HOSTED_INIT_SIM 1 diff --git a/target-ppc/helper.c b/target-ppc/helper.c index 48b19a7e1d..103855afe0 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -19,9 +19,9 @@ #include "cpu.h" #include "helper_regs.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "kvm_ppc.h" -#include "cpus.h" +#include "sysemu/cpus.h" PowerPCCPU *cpu_ppc_init(const char *cpu_model) { diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 2546c577f6..88650d4ae4 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -24,12 +24,12 @@ #include "qemu-common.h" #include "qemu/timer.h" -#include "sysemu.h" -#include "kvm.h" +#include "sysemu/sysemu.h" +#include "sysemu/kvm.h" #include "kvm_ppc.h" #include "cpu.h" -#include "cpus.h" -#include "device_tree.h" +#include "sysemu/cpus.h" +#include "sysemu/device_tree.h" #include "hw/sysbus.h" #include "hw/spapr.h" diff --git a/target-ppc/kvm_ppc.c b/target-ppc/kvm_ppc.c index 2de59fd43b..1b192a8038 100644 --- a/target-ppc/kvm_ppc.c +++ b/target-ppc/kvm_ppc.c @@ -14,7 +14,7 @@ #include "qemu-common.h" #include "qemu/timer.h" #include "kvm_ppc.h" -#include "device_tree.h" +#include "sysemu/device_tree.h" #define PROC_DEVTREE_PATH "/proc/device-tree" diff --git a/target-ppc/machine.c b/target-ppc/machine.c index 5e7bc00e26..e014c0c1af 100644 --- a/target-ppc/machine.c +++ b/target-ppc/machine.c @@ -1,6 +1,6 @@ #include "hw/hw.h" #include "hw/boards.h" -#include "kvm.h" +#include "sysemu/kvm.h" void cpu_save(QEMUFile *f, void *opaque) { diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c index 318ce92adb..0aee7a9063 100644 --- a/target-ppc/mmu_helper.c +++ b/target-ppc/mmu_helper.c @@ -18,7 +18,7 @@ */ #include "cpu.h" #include "helper.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "kvm_ppc.h" //#define DEBUG_MMU diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index cca63abf5d..42ed748b59 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -25,9 +25,9 @@ #include "disas/bfd.h" #include "exec/gdbstub.h" -#include +#include #include "kvm_ppc.h" -#include "arch_init.h" +#include "sysemu/arch_init.h" //#define PPC_DUMP_CPU //#define PPC_DEBUG_SPR diff --git a/target-s390x/helper.c b/target-s390x/helper.c index 8e135457a3..42e06eb85e 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -22,7 +22,7 @@ #include "exec/gdbstub.h" #include "qemu/timer.h" #ifndef CONFIG_USER_ONLY -#include "sysemu.h" +#include "sysemu/sysemu.h" #endif //#define DEBUG_S390 diff --git a/target-s390x/interrupt.c b/target-s390x/interrupt.c index c1b034f775..6c0024b426 100644 --- a/target-s390x/interrupt.c +++ b/target-s390x/interrupt.c @@ -8,7 +8,7 @@ */ #include "cpu.h" -#include "kvm.h" +#include "sysemu/kvm.h" #if !defined(CONFIG_USER_ONLY) /* service interrupts are floating therefore we must not pass an cpustate */ diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index dc70699919..762231d845 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -26,10 +26,10 @@ #include "qemu-common.h" #include "qemu/timer.h" -#include "sysemu.h" -#include "kvm.h" +#include "sysemu/sysemu.h" +#include "sysemu/kvm.h" #include "cpu.h" -#include "device_tree.h" +#include "sysemu/device_tree.h" /* #define DEBUG_KVM */ diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index 2e73d30756..e521ed55cc 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -23,7 +23,7 @@ #include "qemu/host-utils.h" #include "helper.h" #include -#include "kvm.h" +#include "sysemu/kvm.h" #include "qemu/timer.h" #ifdef CONFIG_KVM #include @@ -31,7 +31,7 @@ #if !defined(CONFIG_USER_ONLY) #include "exec/softmmu_exec.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #endif /* #define DEBUG_HELPER */ diff --git a/target-sparc/helper.c b/target-sparc/helper.c index e0d78f3852..91ecfc7aa8 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -20,7 +20,7 @@ #include "cpu.h" #include "qemu/host-utils.h" #include "helper.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" void helper_raise_exception(CPUSPARCState *env, int tt) { diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c index 507c355cac..c35f522e0f 100644 --- a/target-sparc/int32_helper.c +++ b/target-sparc/int32_helper.c @@ -19,7 +19,7 @@ #include "cpu.h" #include "trace.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #define DEBUG_PCALL diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index f61a497d21..0a037291ef 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -35,7 +35,7 @@ #include "disas/disas.h" #include "tcg-op.h" #include "qemu/log.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "helper.h" #define GEN_HELPER 1 diff --git a/ui/cocoa.m b/ui/cocoa.m index 0afa6f86dd..3bf1c6e890 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -27,7 +27,7 @@ #include "qemu-common.h" #include "ui/console.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #ifndef MAC_OS_X_VERSION_10_4 #define MAC_OS_X_VERSION_10_4 1040 diff --git a/ui/curses.c b/ui/curses.c index 5d15e9e16e..d78e378440 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -30,7 +30,7 @@ #include "qemu-common.h" #include "ui/console.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #define FONT_HEIGHT 16 #define FONT_WIDTH 8 diff --git a/ui/input.c b/ui/input.c index 05f6c0c849..259fd1808d 100644 --- a/ui/input.c +++ b/ui/input.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "monitor/monitor.h" #include "ui/console.h" #include "qapi/error.h" diff --git a/ui/keymaps.c b/ui/keymaps.c index f55a2aa464..9625d82fa1 100644 --- a/ui/keymaps.c +++ b/ui/keymaps.c @@ -23,7 +23,7 @@ */ #include "keymaps.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" static int get_keysym(const name2keysym_t *table, const char *name) diff --git a/ui/sdl.c b/ui/sdl.c index bcbf89daeb..1657848e9f 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -30,7 +30,7 @@ #include "qemu-common.h" #include "ui/console.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "x_keymap.h" #include "sdl_zoom.h" diff --git a/ui/spice-core.c b/ui/spice-core.c index 8727bf49ca..5fe3e0e4cf 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -19,7 +19,7 @@ #include #include -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu-common.h" #include "ui/qemu-spice.h" diff --git a/ui/spice-display.c b/ui/spice-display.c index a19b3d95fb..dc7e58d0ed 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -21,7 +21,7 @@ #include "qemu/queue.h" #include "monitor/monitor.h" #include "ui/console.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "trace.h" #include "ui/spice-display.h" diff --git a/ui/vnc.c b/ui/vnc.c index d9e5315e79..8912b78945 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -26,7 +26,7 @@ #include "vnc.h" #include "vnc-jobs.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/sockets.h" #include "qemu/timer.h" #include "qemu/acl.h" diff --git a/vl.c b/vl.c index 9b80e7abc4..75a30a1720 100644 --- a/vl.c +++ b/vl.c @@ -65,7 +65,7 @@ #endif #ifdef CONFIG_SECCOMP -#include "qemu-seccomp.h" +#include "sysemu/seccomp.h" #endif #ifdef __sun__ @@ -131,18 +131,18 @@ int main(int argc, char **argv) #include "net/slirp.h" #include "monitor/monitor.h" #include "ui/console.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "exec/gdbstub.h" #include "qemu/timer.h" #include "qemu-char.h" #include "qemu/cache-utils.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "hw/block-common.h" #include "migration/block.h" -#include "dma.h" +#include "sysemu/dma.h" #include "audio/audio.h" #include "migration/migration.h" -#include "kvm.h" +#include "sysemu/kvm.h" #include "qapi/qmp/qjson.h" #include "qemu/option.h" #include "qemu/config-file.h" @@ -152,7 +152,7 @@ int main(int argc, char **argv) #ifdef CONFIG_VIRTFS #include "fsdev/qemu-fsdev.h" #endif -#include "qtest.h" +#include "sysemu/qtest.h" #include "disas/disas.h" @@ -163,8 +163,8 @@ int main(int argc, char **argv) #include "trace.h" #include "trace/control.h" #include "qemu/queue.h" -#include "cpus.h" -#include "arch_init.h" +#include "sysemu/cpus.h" +#include "sysemu/arch_init.h" #include "qemu/osdep.h" #include "ui/qemu-spice.h" diff --git a/xen-all.c b/xen-all.c index 6965626db8..b659321184 100644 --- a/xen-all.c +++ b/xen-all.c @@ -17,7 +17,7 @@ #include "qmp-commands.h" #include "qemu/range.h" -#include "xen-mapcache.h" +#include "sysemu/xen-mapcache.h" #include "trace.h" #include "exec/address-spaces.h" diff --git a/xen-mapcache.c b/xen-mapcache.c index 8f4648cc32..dc6d1fadb7 100644 --- a/xen-mapcache.c +++ b/xen-mapcache.c @@ -13,13 +13,13 @@ #include #include "hw/xen_backend.h" -#include "blockdev.h" +#include "sysemu/blockdev.h" #include "qemu/bitmap.h" #include #include -#include "xen-mapcache.h" +#include "sysemu/xen-mapcache.h" #include "trace.h" From 927d4878b0ff319ed87fed9363f314613b0a5ed9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Dec 2012 18:20:05 +0100 Subject: [PATCH 2066/2270] softmmu: move remaining include files to include/ subdirectories Signed-off-by: Paolo Bonzini --- backends/rng-egd.c | 2 +- bt-host.c | 2 +- bt-vhci.c | 2 +- event_notifier-posix.c | 2 +- gdbstub.c | 2 +- hmp.c | 2 +- hw/baum.c | 2 +- hw/bt-hci-csr.c | 4 ++-- hw/bt-hci.c | 2 +- hw/bt.c | 2 +- hw/cadence_uart.c | 2 +- hw/ccid-card-emulated.c | 2 +- hw/ccid-card-passthru.c | 2 +- hw/debugcon.c | 2 +- hw/escc.c | 2 +- hw/etraxfs_ser.c | 2 +- hw/exynos4210_uart.c | 2 +- hw/grlib_apbuart.c | 2 +- hw/imx_serial.c | 2 +- hw/ivshmem.c | 2 +- hw/leon3.c | 2 +- hw/lm32_juart.c | 2 +- hw/lm32_uart.c | 2 +- hw/mcf_uart.c | 2 +- hw/milkymist-uart.c | 2 +- hw/mips_fulong2e.c | 2 +- hw/mips_malta.c | 2 +- hw/msmouse.c | 2 +- hw/omap2.c | 2 +- hw/omap_uart.c | 2 +- hw/parallel.c | 2 +- hw/pl011.c | 2 +- hw/pxa2xx.c | 2 +- hw/qdev-properties.c | 2 +- hw/s390x/sclpconsole.c | 2 +- hw/serial.c | 2 +- hw/sh_serial.c | 2 +- hw/spapr_events.c | 2 +- hw/spapr_rtas.c | 2 +- hw/spapr_vty.c | 2 +- hw/strongarm.c | 2 +- hw/usb/dev-bluetooth.c | 2 +- hw/usb/dev-serial.c | 2 +- hw/virtio-console.c | 2 +- hw/xen_backend.c | 2 +- hw/xen_console.c | 2 +- hw/xenfb.c | 2 +- hw/xgmac.c | 2 +- hw/xilinx_uartlite.c | 2 +- hw/xtensa_lx60.c | 2 +- bt-host.h => include/bt/bt.h | 0 qemu-char.h => include/char/char.h | 0 monitor.c | 2 +- net/slirp.c | 2 +- qemu-char.c | 2 +- qmp.c | 2 +- qtest.c | 2 +- slirp/slirp.c | 2 +- spice-qemu-char.c | 2 +- ui/console.c | 2 +- vl.c | 4 ++-- 61 files changed, 61 insertions(+), 61 deletions(-) rename bt-host.h => include/bt/bt.h (100%) rename qemu-char.h => include/char/char.h (100%) diff --git a/backends/rng-egd.c b/backends/rng-egd.c index 3a7d1ecbe0..fd41b53188 100644 --- a/backends/rng-egd.c +++ b/backends/rng-egd.c @@ -11,7 +11,7 @@ */ #include "qemu/rng.h" -#include "qemu-char.h" +#include "char/char.h" #include "qapi/qmp/qerror.h" #include "hw/qdev.h" /* just for DEFINE_PROP_CHR */ diff --git a/bt-host.c b/bt-host.c index 4f5f9f93c5..2092754530 100644 --- a/bt-host.c +++ b/bt-host.c @@ -18,7 +18,7 @@ */ #include "qemu-common.h" -#include "bt-host.h" +#include "bt/bt.h" #include "qemu/main-loop.h" #ifndef _WIN32 diff --git a/bt-vhci.c b/bt-vhci.c index f5d856a809..a6a7ab0329 100644 --- a/bt-vhci.c +++ b/bt-vhci.c @@ -18,7 +18,7 @@ */ #include "qemu-common.h" -#include "bt-host.h" +#include "bt/bt.h" #include "hw/bt.h" #include "qemu/main-loop.h" diff --git a/event_notifier-posix.c b/event_notifier-posix.c index a53b95688d..713d7560d0 100644 --- a/event_notifier-posix.c +++ b/event_notifier-posix.c @@ -12,7 +12,7 @@ #include "qemu-common.h" #include "qemu/event_notifier.h" -#include "qemu-char.h" +#include "char/char.h" #include "qemu/main-loop.h" #ifdef CONFIG_EVENTFD diff --git a/gdbstub.c b/gdbstub.c index 2fca1a7ebf..a8dd437ec0 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -30,7 +30,7 @@ #include "qemu.h" #else #include "monitor/monitor.h" -#include "qemu-char.h" +#include "char/char.h" #include "sysemu/sysemu.h" #include "exec/gdbstub.h" #endif diff --git a/hmp.c b/hmp.c index 3d056b0e38..9e9e62450e 100644 --- a/hmp.c +++ b/hmp.c @@ -15,7 +15,7 @@ #include "hmp.h" #include "net/net.h" -#include "qemu-char.h" +#include "char/char.h" #include "qemu/option.h" #include "qemu/timer.h" #include "qmp-commands.h" diff --git a/hw/baum.c b/hw/baum.c index 97d13ea344..09dcb9cc74 100644 --- a/hw/baum.c +++ b/hw/baum.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "qemu-char.h" +#include "char/char.h" #include "qemu/timer.h" #include "usb.h" #include "baum.h" diff --git a/hw/bt-hci-csr.c b/hw/bt-hci-csr.c index e1dcb6d099..2070bb940c 100644 --- a/hw/bt-hci-csr.c +++ b/hw/bt-hci-csr.c @@ -19,10 +19,10 @@ */ #include "qemu-common.h" -#include "qemu-char.h" +#include "char/char.h" #include "qemu/timer.h" #include "irq.h" -#include "bt-host.h" +#include "bt/bt.h" #include "bt.h" struct csrhci_s { diff --git a/hw/bt-hci.c b/hw/bt-hci.c index da096d8c37..69d2c73862 100644 --- a/hw/bt-hci.c +++ b/hw/bt-hci.c @@ -21,7 +21,7 @@ #include "qemu-common.h" #include "qemu/timer.h" #include "usb.h" -#include "bt-host.h" +#include "bt/bt.h" #include "bt.h" struct bt_hci_s { diff --git a/hw/bt.c b/hw/bt.c index 3fea0983d4..4f2372d794 100644 --- a/hw/bt.c +++ b/hw/bt.c @@ -18,7 +18,7 @@ */ #include "qemu-common.h" -#include "bt-host.h" +#include "bt/bt.h" #include "bt.h" /* Slave implementations can ignore this */ diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c index f34acc8c46..7dd2fe54ed 100644 --- a/hw/cadence_uart.c +++ b/hw/cadence_uart.c @@ -17,7 +17,7 @@ */ #include "sysbus.h" -#include "qemu-char.h" +#include "char/char.h" #include "qemu/timer.h" #ifdef CADENCE_UART_ERR_DEBUG diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c index e508380482..6fd44695ae 100644 --- a/hw/ccid-card-emulated.c +++ b/hw/ccid-card-emulated.c @@ -32,7 +32,7 @@ #include #include "qemu/thread.h" -#include "qemu-char.h" +#include "char/char.h" #include "monitor/monitor.h" #include "hw/ccid.h" diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c index 48e4228b9d..4be05471a9 100644 --- a/hw/ccid-card-passthru.c +++ b/hw/ccid-card-passthru.c @@ -8,7 +8,7 @@ * See the COPYING file in the top-level directory. */ -#include "qemu-char.h" +#include "char/char.h" #include "qemu/sockets.h" #include "monitor/monitor.h" #include "hw/ccid.h" diff --git a/hw/debugcon.c b/hw/debugcon.c index 14ab326be3..14f83f1962 100644 --- a/hw/debugcon.c +++ b/hw/debugcon.c @@ -25,7 +25,7 @@ */ #include "hw.h" -#include "qemu-char.h" +#include "char/char.h" #include "isa.h" #include "pc.h" diff --git a/hw/escc.c b/hw/escc.c index 38e8164e44..f09904aae4 100644 --- a/hw/escc.c +++ b/hw/escc.c @@ -25,7 +25,7 @@ #include "hw.h" #include "sysbus.h" #include "escc.h" -#include "qemu-char.h" +#include "char/char.h" #include "ui/console.h" #include "trace.h" diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c index 59cb7d2172..7bde8004d0 100644 --- a/hw/etraxfs_ser.c +++ b/hw/etraxfs_ser.c @@ -23,7 +23,7 @@ */ #include "sysbus.h" -#include "qemu-char.h" +#include "char/char.h" #include "qemu/log.h" #define D(x) diff --git a/hw/exynos4210_uart.c b/hw/exynos4210_uart.c index 8950891a00..4f23079095 100644 --- a/hw/exynos4210_uart.c +++ b/hw/exynos4210_uart.c @@ -21,7 +21,7 @@ #include "sysbus.h" #include "sysemu/sysemu.h" -#include "qemu-char.h" +#include "char/char.h" #include "exynos4210.h" diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c index 0865764deb..88c46780d1 100644 --- a/hw/grlib_apbuart.c +++ b/hw/grlib_apbuart.c @@ -23,7 +23,7 @@ */ #include "sysbus.h" -#include "qemu-char.h" +#include "char/char.h" #include "trace.h" diff --git a/hw/imx_serial.c b/hw/imx_serial.c index e56e3ea726..124dbb2860 100644 --- a/hw/imx_serial.c +++ b/hw/imx_serial.c @@ -20,7 +20,7 @@ #include "hw.h" #include "sysbus.h" #include "sysemu/sysemu.h" -#include "qemu-char.h" +#include "char/char.h" #include "imx.h" //#define DEBUG_SERIAL 1 diff --git a/hw/ivshmem.c b/hw/ivshmem.c index 567c9a76a7..fcf5d05bae 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -24,7 +24,7 @@ #include "migration/migration.h" #include "qapi/qmp/qerror.h" #include "qemu/event_notifier.h" -#include "qemu-char.h" +#include "char/char.h" #include #include diff --git a/hw/leon3.c b/hw/leon3.c index d1d4541867..79b3a41def 100644 --- a/hw/leon3.c +++ b/hw/leon3.c @@ -24,7 +24,7 @@ #include "hw.h" #include "qemu/timer.h" #include "ptimer.h" -#include "qemu-char.h" +#include "char/char.h" #include "sysemu/sysemu.h" #include "boards.h" #include "loader.h" diff --git a/hw/lm32_juart.c b/hw/lm32_juart.c index f07ed3977f..7c2d202d6a 100644 --- a/hw/lm32_juart.c +++ b/hw/lm32_juart.c @@ -20,7 +20,7 @@ #include "hw.h" #include "sysbus.h" #include "trace.h" -#include "qemu-char.h" +#include "char/char.h" #include "lm32_juart.h" diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c index bf2f507523..89605b8e77 100644 --- a/hw/lm32_uart.c +++ b/hw/lm32_uart.c @@ -25,7 +25,7 @@ #include "hw.h" #include "sysbus.h" #include "trace.h" -#include "qemu-char.h" +#include "char/char.h" #include "qemu/error-report.h" enum { diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c index 2eca2c6ae9..c44344317a 100644 --- a/hw/mcf_uart.c +++ b/hw/mcf_uart.c @@ -7,7 +7,7 @@ */ #include "hw.h" #include "mcf.h" -#include "qemu-char.h" +#include "char/char.h" #include "exec/address-spaces.h" typedef struct { diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c index ef5518e5c2..19e9dbdc75 100644 --- a/hw/milkymist-uart.c +++ b/hw/milkymist-uart.c @@ -24,7 +24,7 @@ #include "hw.h" #include "sysbus.h" #include "trace.h" -#include "qemu-char.h" +#include "char/char.h" #include "qemu/error-report.h" enum { diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c index e7eeda319e..4d8ee8c09c 100644 --- a/hw/mips_fulong2e.c +++ b/hw/mips_fulong2e.c @@ -30,7 +30,7 @@ #include "mips.h" #include "mips_cpudevs.h" #include "pci/pci.h" -#include "qemu-char.h" +#include "char/char.h" #include "sysemu/sysemu.h" #include "audio/audio.h" #include "qemu/log.h" diff --git a/hw/mips_malta.c b/hw/mips_malta.c index bd31ced29d..635143d20c 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -34,7 +34,7 @@ #include "mips.h" #include "mips_cpudevs.h" #include "pci/pci.h" -#include "qemu-char.h" +#include "char/char.h" #include "sysemu/sysemu.h" #include "sysemu/arch_init.h" #include "boards.h" diff --git a/hw/msmouse.c b/hw/msmouse.c index decb1a3b5d..ef47aed4e9 100644 --- a/hw/msmouse.c +++ b/hw/msmouse.c @@ -23,7 +23,7 @@ */ #include #include "qemu-common.h" -#include "qemu-char.h" +#include "char/char.h" #include "ui/console.h" #include "msmouse.h" diff --git a/hw/omap2.c b/hw/omap2.c index dc6867c962..c8358500bc 100644 --- a/hw/omap2.c +++ b/hw/omap2.c @@ -24,7 +24,7 @@ #include "omap.h" #include "sysemu/sysemu.h" #include "qemu/timer.h" -#include "qemu-char.h" +#include "char/char.h" #include "flash.h" #include "soc_dma.h" #include "sysbus.h" diff --git a/hw/omap_uart.c b/hw/omap_uart.c index 159b2d1cdd..0ebfbf8cae 100644 --- a/hw/omap_uart.c +++ b/hw/omap_uart.c @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ -#include "qemu-char.h" +#include "char/char.h" #include "hw.h" #include "omap.h" #include "serial.h" diff --git a/hw/parallel.c b/hw/parallel.c index 56b3760e8c..64a46c6055 100644 --- a/hw/parallel.c +++ b/hw/parallel.c @@ -23,7 +23,7 @@ * THE SOFTWARE. */ #include "hw.h" -#include "qemu-char.h" +#include "char/char.h" #include "isa.h" #include "pc.h" #include "sysemu/sysemu.h" diff --git a/hw/pl011.c b/hw/pl011.c index 1f7ce2f94c..35835f36c0 100644 --- a/hw/pl011.c +++ b/hw/pl011.c @@ -8,7 +8,7 @@ */ #include "sysbus.h" -#include "qemu-char.h" +#include "char/char.h" typedef struct { SysBusDevice busdev; diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c index 936e9f87cd..3c51bc82aa 100644 --- a/hw/pxa2xx.c +++ b/hw/pxa2xx.c @@ -13,7 +13,7 @@ #include "serial.h" #include "i2c.h" #include "ssi.h" -#include "qemu-char.h" +#include "char/char.h" #include "sysemu/blockdev.h" static struct { diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 1cb97ea594..04d605dd37 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -5,7 +5,7 @@ #include "hw/block-common.h" #include "net/hub.h" #include "qapi/visitor.h" -#include "qemu-char.h" +#include "char/char.h" void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) { diff --git a/hw/s390x/sclpconsole.c b/hw/s390x/sclpconsole.c index ca78d6796a..aa70e16665 100644 --- a/hw/s390x/sclpconsole.c +++ b/hw/s390x/sclpconsole.c @@ -17,7 +17,7 @@ #include "sclp.h" #include "event-facility.h" -#include "qemu-char.h" +#include "char/char.h" typedef struct ASCIIConsoleData { EventBufferHeader ebh; diff --git a/hw/serial.c b/hw/serial.c index 2cbb5447a7..a5b2a0c609 100644 --- a/hw/serial.c +++ b/hw/serial.c @@ -24,7 +24,7 @@ */ #include "serial.h" -#include "qemu-char.h" +#include "char/char.h" #include "qemu/timer.h" #include "exec/address-spaces.h" diff --git a/hw/sh_serial.c b/hw/sh_serial.c index 63723496f1..21c5b1362d 100644 --- a/hw/sh_serial.c +++ b/hw/sh_serial.c @@ -26,7 +26,7 @@ */ #include "hw.h" #include "sh.h" -#include "qemu-char.h" +#include "char/char.h" #include "exec/address-spaces.h" //#define DEBUG_SERIAL diff --git a/hw/spapr_events.c b/hw/spapr_events.c index 7956601466..ce78f0922e 100644 --- a/hw/spapr_events.c +++ b/hw/spapr_events.c @@ -26,7 +26,7 @@ */ #include "cpu.h" #include "sysemu/sysemu.h" -#include "qemu-char.h" +#include "char/char.h" #include "hw/qdev.h" #include "sysemu/device_tree.h" diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c index d29736285c..81eecd0940 100644 --- a/hw/spapr_rtas.c +++ b/hw/spapr_rtas.c @@ -26,7 +26,7 @@ */ #include "cpu.h" #include "sysemu/sysemu.h" -#include "qemu-char.h" +#include "char/char.h" #include "hw/qdev.h" #include "sysemu/device_tree.h" diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c index 14f862fba1..ec81a7e6e8 100644 --- a/hw/spapr_vty.c +++ b/hw/spapr_vty.c @@ -1,5 +1,5 @@ #include "qdev.h" -#include "qemu-char.h" +#include "char/char.h" #include "hw/spapr.h" #include "hw/spapr_vio.h" diff --git a/hw/strongarm.c b/hw/strongarm.c index 5d5f454b1d..804c1a37a6 100644 --- a/hw/strongarm.c +++ b/hw/strongarm.c @@ -30,7 +30,7 @@ #include "strongarm.h" #include "qemu/error-report.h" #include "arm-misc.h" -#include "qemu-char.h" +#include "char/char.h" #include "sysemu/sysemu.h" #include "ssi.h" diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c index 4a37442288..a0d7a88d91 100644 --- a/hw/usb/dev-bluetooth.c +++ b/hw/usb/dev-bluetooth.c @@ -21,7 +21,7 @@ #include "qemu-common.h" #include "hw/usb.h" #include "hw/usb/desc.h" -#include "bt-host.h" +#include "bt/bt.h" #include "hw/bt.h" struct USBBtState { diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 2ff4fe247a..20cf5337b7 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -12,7 +12,7 @@ #include "qemu/error-report.h" #include "hw/usb.h" #include "hw/usb/desc.h" -#include "qemu-char.h" +#include "char/char.h" //#define DEBUG_Serial diff --git a/hw/virtio-console.c b/hw/virtio-console.c index df0951e973..002b028b99 100644 --- a/hw/virtio-console.c +++ b/hw/virtio-console.c @@ -10,7 +10,7 @@ * the COPYING file in the top-level directory. */ -#include "qemu-char.h" +#include "char/char.h" #include "qemu/error-report.h" #include "trace.h" #include "virtio-serial.h" diff --git a/hw/xen_backend.c b/hw/xen_backend.c index 270584fc10..3fa30098ca 100644 --- a/hw/xen_backend.c +++ b/hw/xen_backend.c @@ -35,7 +35,7 @@ #include #include "hw.h" -#include "qemu-char.h" +#include "char/char.h" #include "qemu/log.h" #include "xen_backend.h" diff --git a/hw/xen_console.c b/hw/xen_console.c index 9426d7374f..ac36ceb47c 100644 --- a/hw/xen_console.c +++ b/hw/xen_console.c @@ -30,7 +30,7 @@ #include #include "hw.h" -#include "qemu-char.h" +#include "char/char.h" #include "xen_backend.h" #include diff --git a/hw/xenfb.c b/hw/xenfb.c index b1122bd933..903efd3073 100644 --- a/hw/xenfb.c +++ b/hw/xenfb.c @@ -37,7 +37,7 @@ #include "hw.h" #include "ui/console.h" -#include "qemu-char.h" +#include "char/char.h" #include "xen_backend.h" #include diff --git a/hw/xgmac.c b/hw/xgmac.c index acc3d37648..9639b6141b 100644 --- a/hw/xgmac.c +++ b/hw/xgmac.c @@ -25,7 +25,7 @@ */ #include "sysbus.h" -#include "qemu-char.h" +#include "char/char.h" #include "qemu/log.h" #include "net/net.h" #include "net/checksum.h" diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c index 02c5850331..abd256ae00 100644 --- a/hw/xilinx_uartlite.c +++ b/hw/xilinx_uartlite.c @@ -23,7 +23,7 @@ */ #include "sysbus.h" -#include "qemu-char.h" +#include "char/char.h" #define DUART(x) diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c index 9c7bb75f81..0b9a52851a 100644 --- a/hw/xtensa_lx60.c +++ b/hw/xtensa_lx60.c @@ -36,7 +36,7 @@ #include "sysbus.h" #include "flash.h" #include "sysemu/blockdev.h" -#include "qemu-char.h" +#include "char/char.h" #include "xtensa_bootparam.h" typedef struct LxBoardDesc { diff --git a/bt-host.h b/include/bt/bt.h similarity index 100% rename from bt-host.h rename to include/bt/bt.h diff --git a/qemu-char.h b/include/char/char.h similarity index 100% rename from qemu-char.h rename to include/char/char.h diff --git a/monitor.c b/monitor.c index 200bef452f..9cf419bb1d 100644 --- a/monitor.c +++ b/monitor.c @@ -33,7 +33,7 @@ #include "exec/gdbstub.h" #include "net/net.h" #include "net/slirp.h" -#include "qemu-char.h" +#include "char/char.h" #include "ui/qemu-spice.h" #include "sysemu/sysemu.h" #include "monitor/monitor.h" diff --git a/net/slirp.c b/net/slirp.c index 87bdc9d031..c14259f004 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -35,7 +35,7 @@ #include "monitor/monitor.h" #include "qemu/sockets.h" #include "slirp/libslirp.h" -#include "qemu-char.h" +#include "char/char.h" static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) { diff --git a/qemu-char.c b/qemu-char.c index 0cbe85318e..e39e6f168c 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -26,7 +26,7 @@ #include "ui/console.h" #include "sysemu/sysemu.h" #include "qemu/timer.h" -#include "qemu-char.h" +#include "char/char.h" #include "hw/usb.h" #include "hw/baum.h" #include "hw/msmouse.h" diff --git a/qmp.c b/qmp.c index be63fe1029..55b056b558 100644 --- a/qmp.c +++ b/qmp.c @@ -16,7 +16,7 @@ #include "qemu-common.h" #include "sysemu/sysemu.h" #include "qmp-commands.h" -#include "qemu-char.h" +#include "char/char.h" #include "ui/qemu-spice.h" #include "ui/vnc.h" #include "sysemu/kvm.h" diff --git a/qtest.c b/qtest.c index 468c921310..c9b58ceb8b 100644 --- a/qtest.c +++ b/qtest.c @@ -13,7 +13,7 @@ #include "sysemu/qtest.h" #include "hw/qdev.h" -#include "qemu-char.h" +#include "char/char.h" #include "exec/ioport.h" #include "exec/memory.h" #include "hw/irq.h" diff --git a/slirp/slirp.c b/slirp/slirp.c index 4b51a67e7d..e93b578832 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -23,7 +23,7 @@ */ #include "qemu-common.h" #include "qemu/timer.h" -#include "qemu-char.h" +#include "char/char.h" #include "slirp.h" #include "hw/hw.h" diff --git a/spice-qemu-char.c b/spice-qemu-char.c index 41b1657ccd..4b03143f68 100644 --- a/spice-qemu-char.c +++ b/spice-qemu-char.c @@ -1,7 +1,7 @@ #include "config-host.h" #include "trace.h" #include "ui/qemu-spice.h" -#include "qemu-char.h" +#include "char/char.h" #include #include diff --git a/ui/console.c b/ui/console.c index a4bff8ce8a..d880ebff07 100644 --- a/ui/console.c +++ b/ui/console.c @@ -25,7 +25,7 @@ #include "ui/console.h" #include "qemu/timer.h" #include "qmp-commands.h" -#include "qemu-char.h" +#include "char/char.h" //#define DEBUG_CONSOLE #define DEFAULT_BACKSCROLL 512 diff --git a/vl.c b/vl.c index 75a30a1720..e6a8d89acc 100644 --- a/vl.c +++ b/vl.c @@ -126,7 +126,7 @@ int main(int argc, char **argv) #include "hw/xen.h" #include "hw/qdev.h" #include "hw/loader.h" -#include "bt-host.h" +#include "bt/bt.h" #include "net/net.h" #include "net/slirp.h" #include "monitor/monitor.h" @@ -134,7 +134,7 @@ int main(int argc, char **argv) #include "sysemu/sysemu.h" #include "exec/gdbstub.h" #include "qemu/timer.h" -#include "qemu-char.h" +#include "char/char.h" #include "qemu/cache-utils.h" #include "sysemu/blockdev.h" #include "hw/block-common.h" From 6b4c305cbd549e9d12a6b0192fdb8d6519a9664c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 24 Oct 2012 13:12:00 +0200 Subject: [PATCH 2067/2270] fpu: move public header file to include/fpu Signed-off-by: Paolo Bonzini --- configure | 2 +- fpu/softfloat.c | 2 +- {fpu => include/fpu}/softfloat.h | 0 include/qemu/bswap.h | 2 +- linux-user/arm/nwfpe/double_cpdo.c | 2 +- linux-user/arm/nwfpe/extended_cpdo.c | 2 +- linux-user/arm/nwfpe/fpa11.h | 2 +- linux-user/arm/nwfpe/fpa11_cpdt.c | 2 +- linux-user/arm/nwfpe/fpa11_cprt.c | 2 +- linux-user/arm/nwfpe/fpopcode.c | 2 +- linux-user/arm/nwfpe/single_cpdo.c | 2 +- target-alpha/cpu.h | 2 +- target-alpha/fpu_helper.c | 2 +- target-alpha/helper.c | 2 +- target-alpha/translate.c | 2 +- target-arm/cpu.h | 2 +- target-i386/cpu.h | 2 +- target-m68k/cpu.h | 2 +- target-microblaze/cpu.h | 2 +- target-mips/cpu.h | 2 +- target-openrisc/cpu.h | 2 +- target-ppc/cpu.h | 2 +- target-s390x/cpu.h | 2 +- target-sh4/cpu.h | 4 +--- target-sparc/cpu.h | 2 +- target-unicore32/cpu.h | 2 +- 26 files changed, 25 insertions(+), 27 deletions(-) rename {fpu => include/fpu}/softfloat.h (100%) diff --git a/configure b/configure index 4d0e1163a2..c989fece9a 100755 --- a/configure +++ b/configure @@ -278,7 +278,7 @@ QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS" QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS" QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS" QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS" -QEMU_INCLUDES="-I. -I\$(SRC_PATH) -I\$(SRC_PATH)/include -I\$(SRC_PATH)/fpu" +QEMU_INCLUDES="-I. -I\$(SRC_PATH) -I\$(SRC_PATH)/include" if test "$debug_info" = "yes"; then CFLAGS="-g $CFLAGS" LDFLAGS="-g $LDFLAGS" diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 841314686b..0cfa6b4831 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -40,7 +40,7 @@ these four paragraphs for those parts of this code that are retained. */ #include "config.h" -#include "softfloat.h" +#include "fpu/softfloat.h" /*---------------------------------------------------------------------------- | Primitive arithmetic functions, including multi-word arithmetic, and diff --git a/fpu/softfloat.h b/include/fpu/softfloat.h similarity index 100% rename from fpu/softfloat.h rename to include/fpu/softfloat.h diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h index cc7f84d30f..2006fcd621 100644 --- a/include/qemu/bswap.h +++ b/include/qemu/bswap.h @@ -4,7 +4,7 @@ #include "config-host.h" #include -#include "softfloat.h" +#include "fpu/softfloat.h" #ifdef CONFIG_MACHINE_BSWAP_H #include diff --git a/linux-user/arm/nwfpe/double_cpdo.c b/linux-user/arm/nwfpe/double_cpdo.c index 8e9b28fa68..41c28f3096 100644 --- a/linux-user/arm/nwfpe/double_cpdo.c +++ b/linux-user/arm/nwfpe/double_cpdo.c @@ -19,7 +19,7 @@ */ #include "fpa11.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #include "fpopcode.h" float64 float64_exp(float64 Fm); diff --git a/linux-user/arm/nwfpe/extended_cpdo.c b/linux-user/arm/nwfpe/extended_cpdo.c index 880ce030a5..48eca3b4a6 100644 --- a/linux-user/arm/nwfpe/extended_cpdo.c +++ b/linux-user/arm/nwfpe/extended_cpdo.c @@ -19,7 +19,7 @@ */ #include "fpa11.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #include "fpopcode.h" floatx80 floatx80_exp(floatx80 Fm); diff --git a/linux-user/arm/nwfpe/fpa11.h b/linux-user/arm/nwfpe/fpa11.h index 002b3cbb82..bb9ac6554e 100644 --- a/linux-user/arm/nwfpe/fpa11.h +++ b/linux-user/arm/nwfpe/fpa11.h @@ -43,7 +43,7 @@ extern CPUARMState *user_registers; /* includes */ #include "fpsr.h" /* FP control and status register definitions */ -#include "softfloat.h" +#include "fpu/softfloat.h" #define typeNone 0x00 #define typeSingle 0x01 diff --git a/linux-user/arm/nwfpe/fpa11_cpdt.c b/linux-user/arm/nwfpe/fpa11_cpdt.c index 3e7a938253..007a3d6505 100644 --- a/linux-user/arm/nwfpe/fpa11_cpdt.c +++ b/linux-user/arm/nwfpe/fpa11_cpdt.c @@ -20,7 +20,7 @@ */ #include "fpa11.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #include "fpopcode.h" //#include "fpmodule.h" //#include "fpmodule.inl" diff --git a/linux-user/arm/nwfpe/fpa11_cprt.c b/linux-user/arm/nwfpe/fpa11_cprt.c index 801189798b..7be93fa54f 100644 --- a/linux-user/arm/nwfpe/fpa11_cprt.c +++ b/linux-user/arm/nwfpe/fpa11_cprt.c @@ -20,7 +20,7 @@ */ #include "fpa11.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #include "fpopcode.h" #include "fpa11.inl" //#include "fpmodule.h" diff --git a/linux-user/arm/nwfpe/fpopcode.c b/linux-user/arm/nwfpe/fpopcode.c index 82ac92f0ce..0dc5c9cd5d 100644 --- a/linux-user/arm/nwfpe/fpopcode.c +++ b/linux-user/arm/nwfpe/fpopcode.c @@ -19,7 +19,7 @@ */ #include "fpa11.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #include "fpopcode.h" #include "fpsr.h" //#include "fpmodule.h" diff --git a/linux-user/arm/nwfpe/single_cpdo.c b/linux-user/arm/nwfpe/single_cpdo.c index 26168e2201..2bfb359eb6 100644 --- a/linux-user/arm/nwfpe/single_cpdo.c +++ b/linux-user/arm/nwfpe/single_cpdo.c @@ -19,7 +19,7 @@ */ #include "fpa11.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #include "fpopcode.h" float32 float32_exp(float32 Fm); diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 137703f6d7..b75c856f97 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -29,7 +29,7 @@ #include "exec/cpu-defs.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #define TARGET_HAS_ICE 1 diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c index fe988ec459..fad3575549 100644 --- a/target-alpha/fpu_helper.c +++ b/target-alpha/fpu_helper.c @@ -19,7 +19,7 @@ #include "cpu.h" #include "helper.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #define FP_STATUS (env->fp_status) diff --git a/target-alpha/helper.c b/target-alpha/helper.c index 2430f70aca..22c9c6ec8c 100644 --- a/target-alpha/helper.c +++ b/target-alpha/helper.c @@ -22,7 +22,7 @@ #include #include "cpu.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #include "helper.h" uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env) diff --git a/target-alpha/translate.c b/target-alpha/translate.c index c94126737f..3afc3c63f9 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -611,7 +611,7 @@ static void gen_qual_roundmode(DisasContext *ctx, int fn11) } #if defined(CONFIG_SOFTFLOAT_INLINE) - /* ??? The "softfloat.h" interface is to call set_float_rounding_mode. + /* ??? The "fpu/softfloat.h" interface is to call set_float_rounding_mode. With CONFIG_SOFTFLOAT that expands to an out-of-line call that just sets the one field. */ tcg_gen_st8_i32(tmp, cpu_env, diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 7f87efa7d9..ffddfcbc0d 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -29,7 +29,7 @@ #include "qemu-common.h" #include "exec/cpu-defs.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #define TARGET_HAS_ICE 1 diff --git a/target-i386/cpu.h b/target-i386/cpu.h index f3f50a0499..0709780356 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -46,7 +46,7 @@ #include "exec/cpu-defs.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #define R_EAX 0 #define R_ECX 1 diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index b37af1fffd..adaf56c471 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -28,7 +28,7 @@ #include "qemu-common.h" #include "exec/cpu-defs.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #define MAX_QREGS 32 diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h index 5358941ae4..4de22266ef 100644 --- a/target-microblaze/cpu.h +++ b/target-microblaze/cpu.h @@ -27,7 +27,7 @@ #define CPUArchState struct CPUMBState #include "exec/cpu-defs.h" -#include "softfloat.h" +#include "fpu/softfloat.h" struct CPUMBState; typedef struct CPUMBState CPUMBState; #if !defined(CONFIG_USER_ONLY) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 183ba9fbd8..31602ac8ed 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -13,7 +13,7 @@ #include "qemu-common.h" #include "mips-defs.h" #include "exec/cpu-defs.h" -#include "softfloat.h" +#include "fpu/softfloat.h" struct CPUMIPSState; diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h index 876b386a3c..3beab45c3c 100644 --- a/target-openrisc/cpu.h +++ b/target-openrisc/cpu.h @@ -31,7 +31,7 @@ struct OpenRISCCPU; #include "config.h" #include "qemu-common.h" #include "exec/cpu-defs.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #include "qom/cpu.h" #include "qapi/error.h" diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 610bcd544b..e88ebe00d4 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -75,7 +75,7 @@ #include "exec/cpu-defs.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #define TARGET_HAS_ICE 1 diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index acb8c73174..dda0b9af66 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -36,7 +36,7 @@ #include "exec/cpu-all.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #define NB_MMU_MODES 3 diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index 7c50c798b8..34e9b0acf7 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -41,7 +41,7 @@ #include "exec/cpu-defs.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #define TARGET_PAGE_BITS 12 /* 4k XXXXX */ @@ -230,8 +230,6 @@ static inline void cpu_set_tls(CPUSH4State *env, target_ulong newtls) void cpu_load_tlb(CPUSH4State * env); -#include "softfloat.h" - static inline CPUSH4State *cpu_init(const char *cpu_model) { SuperHCPU *cpu = cpu_sh4_init(cpu_model); diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 04b6659909..7389b03514 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -27,7 +27,7 @@ #include "exec/cpu-defs.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #define TARGET_HAS_ICE 1 diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h index cd8f730756..509ce7c69d 100644 --- a/target-unicore32/cpu.h +++ b/target-unicore32/cpu.h @@ -24,7 +24,7 @@ #include "config.h" #include "qemu-common.h" #include "exec/cpu-defs.h" -#include "softfloat.h" +#include "fpu/softfloat.h" #define NB_MMU_MODES 2 From 42dc882ff850cde22ae7d501d1dd452837fc4103 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 14 Sep 2012 18:19:15 +0200 Subject: [PATCH 2068/2270] hw: move executable format header files to hw/ Or delete a.out.h which is unused. Signed-off-by: Paolo Bonzini --- a.out.h | 430 ------------------------------ uboot_image.h => hw/uboot_image.h | 0 2 files changed, 430 deletions(-) delete mode 100644 a.out.h rename uboot_image.h => hw/uboot_image.h (100%) diff --git a/a.out.h b/a.out.h deleted file mode 100644 index 33ca7f77ea..0000000000 --- a/a.out.h +++ /dev/null @@ -1,430 +0,0 @@ -/* a.out.h - - Copyright 1997, 1998, 1999, 2001 Red Hat, Inc. - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#ifndef _A_OUT_H_ -#define _A_OUT_H_ - -#ifdef __cplusplus -extern "C" { -#endif -#define COFF_IMAGE_WITH_PE -#define COFF_LONG_SECTION_NAMES - -/*** coff information for Intel 386/486. */ - - -/********************** FILE HEADER **********************/ - -struct external_filehdr { - short f_magic; /* magic number */ - short f_nscns; /* number of sections */ - host_ulong f_timdat; /* time & date stamp */ - host_ulong f_symptr; /* file pointer to symtab */ - host_ulong f_nsyms; /* number of symtab entries */ - short f_opthdr; /* sizeof(optional hdr) */ - short f_flags; /* flags */ -}; - -/* Bits for f_flags: - * F_RELFLG relocation info stripped from file - * F_EXEC file is executable (no unresolved external references) - * F_LNNO line numbers stripped from file - * F_LSYMS local symbols stripped from file - * F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax) - */ - -#define F_RELFLG (0x0001) -#define F_EXEC (0x0002) -#define F_LNNO (0x0004) -#define F_LSYMS (0x0008) - - - -#define I386MAGIC 0x14c -#define I386PTXMAGIC 0x154 -#define I386AIXMAGIC 0x175 - -/* This is Lynx's all-platform magic number for executables. */ - -#define LYNXCOFFMAGIC 0415 - -#define I386BADMAG(x) (((x).f_magic != I386MAGIC) \ - && (x).f_magic != I386AIXMAGIC \ - && (x).f_magic != I386PTXMAGIC \ - && (x).f_magic != LYNXCOFFMAGIC) - -#define FILHDR struct external_filehdr -#define FILHSZ 20 - - -/********************** AOUT "OPTIONAL HEADER"= - **********************/ - - -typedef struct -{ - unsigned short magic; /* type of file */ - unsigned short vstamp; /* version stamp */ - host_ulong tsize; /* text size in bytes, padded to FW bdry*/ - host_ulong dsize; /* initialized data " " */ - host_ulong bsize; /* uninitialized data " " */ - host_ulong entry; /* entry pt. */ - host_ulong text_start; /* base of text used for this file */ - host_ulong data_start; /* base of data used for this file= - */ -} -AOUTHDR; - -#define AOUTSZ 28 -#define AOUTHDRSZ 28 - -#define OMAGIC 0404 /* object files, eg as output */ -#define ZMAGIC 0413 /* demand load format, eg normal ld output */ -#define STMAGIC 0401 /* target shlib */ -#define SHMAGIC 0443 /* host shlib */ - - -/* define some NT default values */ -/* #define NT_IMAGE_BASE 0x400000 moved to internal.h */ -#define NT_SECTION_ALIGNMENT 0x1000 -#define NT_FILE_ALIGNMENT 0x200 -#define NT_DEF_RESERVE 0x100000 -#define NT_DEF_COMMIT 0x1000 - -/********************** SECTION HEADER **********************/ - - -struct external_scnhdr { - char s_name[8]; /* section name */ - host_ulong s_paddr; /* physical address, offset - of last addr in scn */ - host_ulong s_vaddr; /* virtual address */ - host_ulong s_size; /* section size */ - host_ulong s_scnptr; /* file ptr to raw data for section */ - host_ulong s_relptr; /* file ptr to relocation */ - host_ulong s_lnnoptr; /* file ptr to line numbers */ - unsigned short s_nreloc; /* number of relocation entries */ - unsigned short s_nlnno; /* number of line number entries*/ - host_ulong s_flags; /* flags */ -}; - -#define SCNHDR struct external_scnhdr -#define SCNHSZ 40 - -/* - * names of "special" sections - */ -#define _TEXT ".text" -#define _DATA ".data" -#define _BSS ".bss" -#define _COMMENT ".comment" -#define _LIB ".lib" - -/********************** LINE NUMBERS **********************/ - -/* 1 line number entry for every "breakpointable" source line in a section. - * Line numbers are grouped on a per function basis; first entry in a function - * grouping will have l_lnno = 0 and in place of physical address will be the - * symbol table index of the function name. - */ -struct external_lineno { - union { - host_ulong l_symndx; /* function name symbol index, iff l_lnno 0 */ - host_ulong l_paddr; /* (physical) address of line number */ - } l_addr; - unsigned short l_lnno; /* line number */ -}; - -#define LINENO struct external_lineno -#define LINESZ 6 - -/********************** SYMBOLS **********************/ - -#define E_SYMNMLEN 8 /* # characters in a symbol name */ -#define E_FILNMLEN 14 /* # characters in a file name */ -#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ - -struct QEMU_PACKED external_syment -{ - union { - char e_name[E_SYMNMLEN]; - struct { - host_ulong e_zeroes; - host_ulong e_offset; - } e; - } e; - host_ulong e_value; - unsigned short e_scnum; - unsigned short e_type; - char e_sclass[1]; - char e_numaux[1]; -}; - -#define N_BTMASK (0xf) -#define N_TMASK (0x30) -#define N_BTSHFT (4) -#define N_TSHIFT (2) - -union external_auxent { - struct { - host_ulong x_tagndx; /* str, un, or enum tag indx */ - union { - struct { - unsigned short x_lnno; /* declaration line number */ - unsigned short x_size; /* str/union/array size */ - } x_lnsz; - host_ulong x_fsize; /* size of function */ - } x_misc; - union { - struct { /* if ISFCN, tag, or .bb */ - host_ulong x_lnnoptr;/* ptr to fcn line # */ - host_ulong x_endndx; /* entry ndx past block end */ - } x_fcn; - struct { /* if ISARY, up to 4 dimen. */ - char x_dimen[E_DIMNUM][2]; - } x_ary; - } x_fcnary; - unsigned short x_tvndx; /* tv index */ - } x_sym; - - union { - char x_fname[E_FILNMLEN]; - struct { - host_ulong x_zeroes; - host_ulong x_offset; - } x_n; - } x_file; - - struct { - host_ulong x_scnlen; /* section length */ - unsigned short x_nreloc; /* # relocation entries */ - unsigned short x_nlinno; /* # line numbers */ - host_ulong x_checksum; /* section COMDAT checksum */ - unsigned short x_associated;/* COMDAT associated section index */ - char x_comdat[1]; /* COMDAT selection number */ - } x_scn; - - struct { - host_ulong x_tvfill; /* tv fill value */ - unsigned short x_tvlen; /* length of .tv */ - char x_tvran[2][2]; /* tv range */ - } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ - -}; - -#define SYMENT struct external_syment -#define SYMESZ 18 -#define AUXENT union external_auxent -#define AUXESZ 18 - -#define _ETEXT "etext" - -/********************** RELOCATION DIRECTIVES **********************/ - -struct external_reloc { - char r_vaddr[4]; - char r_symndx[4]; - char r_type[2]; -}; - -#define RELOC struct external_reloc -#define RELSZ 10 - -/* end of coff/i386.h */ - -/* PE COFF header information */ - -#ifndef _PE_H -#define _PE_H - -/* NT specific file attributes */ -#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 -#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 -#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 -#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 -#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 -#define IMAGE_FILE_32BIT_MACHINE 0x0100 -#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 -#define IMAGE_FILE_SYSTEM 0x1000 -#define IMAGE_FILE_DLL 0x2000 -#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 - -/* additional flags to be set for section headers to allow the NT loader to - read and write to the section data (to replace the addresses of data in - dlls for one thing); also to execute the section in .text's case= - */ -#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 -#define IMAGE_SCN_MEM_EXECUTE 0x20000000 -#define IMAGE_SCN_MEM_READ 0x40000000 -#define IMAGE_SCN_MEM_WRITE 0x80000000 - -/* - * Section characteristics added for ppc-nt - */ - -#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Reserved. */ - -#define IMAGE_SCN_CNT_CODE 0x00000020 /* Section contains code. */ -#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* Section contains initialized data. */ -#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* Section contains uninitialized data. */ - -#define IMAGE_SCN_LNK_OTHER 0x00000100 /* Reserved. */ -#define IMAGE_SCN_LNK_INFO 0x00000200 /* Section contains comments or some other type of information. */ -#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* Section contents will not become part of image. */ -#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* Section contents comdat. */ - -#define IMAGE_SCN_MEM_FARDATA 0x00008000 - -#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 -#define IMAGE_SCN_MEM_16BIT 0x00020000 -#define IMAGE_SCN_MEM_LOCKED 0x00040000 -#define IMAGE_SCN_MEM_PRELOAD 0x00080000 - -#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 -#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 -#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 -#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 -#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 /* Default alignment if no others are specified. */ -#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 -#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 - - -#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* Section contains extended relocations. */ -#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* Section is not cachable. */ -#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* Section is not pageable. */ -#define IMAGE_SCN_MEM_SHARED 0x10000000 /* Section is shareable. */ - -/* COMDAT selection codes. */ - -#define IMAGE_COMDAT_SELECT_NODUPLICATES (1) /* Warn if duplicates. */ -#define IMAGE_COMDAT_SELECT_ANY (2) /* No warning. */ -#define IMAGE_COMDAT_SELECT_SAME_SIZE (3) /* Warn if different size. */ -#define IMAGE_COMDAT_SELECT_EXACT_MATCH (4) /* Warn if different. */ -#define IMAGE_COMDAT_SELECT_ASSOCIATIVE (5) /* Base on other section. */ - -/* Magic values that are true for all dos/nt implementations */ -#define DOSMAGIC 0x5a4d -#define NT_SIGNATURE 0x00004550 - -/* NT allows long filenames, we want to accommodate this. This may break - some of the bfd functions */ -#undef FILNMLEN -#define FILNMLEN 18 /* # characters in a file name */ - - -#ifdef COFF_IMAGE_WITH_PE -/* The filehdr is only weired in images */ - -#undef FILHDR -struct external_PE_filehdr -{ - /* DOS header fields */ - unsigned short e_magic; /* Magic number, 0x5a4d */ - unsigned short e_cblp; /* Bytes on last page of file, 0x90 */ - unsigned short e_cp; /* Pages in file, 0x3 */ - unsigned short e_crlc; /* Relocations, 0x0 */ - unsigned short e_cparhdr; /* Size of header in paragraphs, 0x4 */ - unsigned short e_minalloc; /* Minimum extra paragraphs needed, 0x0 */ - unsigned short e_maxalloc; /* Maximum extra paragraphs needed, 0xFFFF */ - unsigned short e_ss; /* Initial (relative) SS value, 0x0 */ - unsigned short e_sp; /* Initial SP value, 0xb8 */ - unsigned short e_csum; /* Checksum, 0x0 */ - unsigned short e_ip; /* Initial IP value, 0x0 */ - unsigned short e_cs; /* Initial (relative) CS value, 0x0 */ - unsigned short e_lfarlc; /* File address of relocation table, 0x40 */ - unsigned short e_ovno; /* Overlay number, 0x0 */ - char e_res[4][2]; /* Reserved words, all 0x0 */ - unsigned short e_oemid; /* OEM identifier (for e_oeminfo), 0x0 */ - unsigned short e_oeminfo; /* OEM information; e_oemid specific, 0x0 */ - char e_res2[10][2]; /* Reserved words, all 0x0 */ - host_ulong e_lfanew; /* File address of new exe header, 0x80 */ - char dos_message[16][4]; /* other stuff, always follow DOS header */ - unsigned int nt_signature; /* required NT signature, 0x4550 */ - - /* From standard header */ - - unsigned short f_magic; /* magic number */ - unsigned short f_nscns; /* number of sections */ - host_ulong f_timdat; /* time & date stamp */ - host_ulong f_symptr; /* file pointer to symtab */ - host_ulong f_nsyms; /* number of symtab entries */ - unsigned short f_opthdr; /* sizeof(optional hdr) */ - unsigned short f_flags; /* flags */ -}; - - -#define FILHDR struct external_PE_filehdr -#undef FILHSZ -#define FILHSZ 152 - -#endif - -typedef struct -{ - unsigned short magic; /* type of file */ - unsigned short vstamp; /* version stamp */ - host_ulong tsize; /* text size in bytes, padded to FW bdry*/ - host_ulong dsize; /* initialized data " " */ - host_ulong bsize; /* uninitialized data " " */ - host_ulong entry; /* entry pt. */ - host_ulong text_start; /* base of text used for this file */ - host_ulong data_start; /* base of all data used for this file */ - - /* NT extra fields; see internal.h for descriptions */ - host_ulong ImageBase; - host_ulong SectionAlignment; - host_ulong FileAlignment; - unsigned short MajorOperatingSystemVersion; - unsigned short MinorOperatingSystemVersion; - unsigned short MajorImageVersion; - unsigned short MinorImageVersion; - unsigned short MajorSubsystemVersion; - unsigned short MinorSubsystemVersion; - char Reserved1[4]; - host_ulong SizeOfImage; - host_ulong SizeOfHeaders; - host_ulong CheckSum; - unsigned short Subsystem; - unsigned short DllCharacteristics; - host_ulong SizeOfStackReserve; - host_ulong SizeOfStackCommit; - host_ulong SizeOfHeapReserve; - host_ulong SizeOfHeapCommit; - host_ulong LoaderFlags; - host_ulong NumberOfRvaAndSizes; - /* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */ - char DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars */ - -} PEAOUTHDR; - - -#undef AOUTSZ -#define AOUTSZ (AOUTHDRSZ + 196) - -#undef E_FILNMLEN -#define E_FILNMLEN 18 /* # characters in a file name */ -#endif - -/* end of coff/pe.h */ - -#define DT_NON (0) /* no derived type */ -#define DT_PTR (1) /* pointer */ -#define DT_FCN (2) /* function */ -#define DT_ARY (3) /* array */ - -#define ISPTR(x) (((x) & N_TMASK) == (DT_PTR << N_BTSHFT)) -#define ISFCN(x) (((x) & N_TMASK) == (DT_FCN << N_BTSHFT)) -#define ISARY(x) (((x) & N_TMASK) == (DT_ARY << N_BTSHFT)) - -#ifdef __cplusplus -} -#endif - -#endif /* _A_OUT_H_ */ diff --git a/uboot_image.h b/hw/uboot_image.h similarity index 100% rename from uboot_image.h rename to hw/uboot_image.h From ec5e016c9a68588bd01be387416923c7dcafb951 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 24 Oct 2012 13:09:17 +0200 Subject: [PATCH 2069/2270] janitor: move remaining public headers to include/ Headers in the root directory are now used only from within that directory. Signed-off-by: Paolo Bonzini --- config.h => include/config.h | 0 elf.h => include/elf.h | 0 libfdt_env.h => include/libfdt_env.h | 0 qemu-common.h => include/qemu-common.h | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename config.h => include/config.h (100%) rename elf.h => include/elf.h (100%) rename libfdt_env.h => include/libfdt_env.h (100%) rename qemu-common.h => include/qemu-common.h (100%) diff --git a/config.h b/include/config.h similarity index 100% rename from config.h rename to include/config.h diff --git a/elf.h b/include/elf.h similarity index 100% rename from elf.h rename to include/elf.h diff --git a/libfdt_env.h b/include/libfdt_env.h similarity index 100% rename from libfdt_env.h rename to include/libfdt_env.h diff --git a/qemu-common.h b/include/qemu-common.h similarity index 100% rename from qemu-common.h rename to include/qemu-common.h From 92a3136174f60ee45b113296cb2c2a5225b00369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 16 Dec 2012 02:17:02 +0100 Subject: [PATCH 2070/2270] cpu: Introduce CPUListState struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This generalizes {ARM,M68k,Alpha}CPUListState to avoid declaring it for each target. Place it in cpu-common.h to avoid circular dependencies. Signed-off-by: Andreas Färber Reviewed-by: Igor Mammedov Reviewed-by: Eduardo Habkost --- cpu-common.h | 12 ++++++++++++ target-alpha/cpu.c | 9 ++------- target-arm/helper.c | 9 ++------- target-m68k/helper.c | 9 ++------- 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/cpu-common.h b/cpu-common.h index d2fbafac9c..a62b6ea3f9 100644 --- a/cpu-common.h +++ b/cpu-common.h @@ -12,6 +12,18 @@ #include "bswap.h" #include "qemu-queue.h" +/** + * CPUListState: + * @cpu_fprintf: Print function. + * @file: File to print to using @cpu_fprint. + * + * State commonly used for iterating over CPU models. + */ +typedef struct CPUListState { + fprintf_function cpu_fprintf; + FILE *file; +} CPUListState; + #if !defined(CONFIG_USER_ONLY) enum device_endian { diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c index 2deb3c1d7d..59d8669ab0 100644 --- a/target-alpha/cpu.c +++ b/target-alpha/cpu.c @@ -33,11 +33,6 @@ static void alpha_cpu_realize(Object *obj, Error **errp) #endif } -typedef struct AlphaCPUListState { - fprintf_function cpu_fprintf; - FILE *file; -} AlphaCPUListState; - /* Sort alphabetically by type name. */ static gint alpha_cpu_list_compare(gconstpointer a, gconstpointer b) { @@ -53,7 +48,7 @@ static gint alpha_cpu_list_compare(gconstpointer a, gconstpointer b) static void alpha_cpu_list_entry(gpointer data, gpointer user_data) { ObjectClass *oc = data; - AlphaCPUListState *s = user_data; + CPUListState *s = user_data; (*s->cpu_fprintf)(s->file, " %s\n", object_class_get_name(oc)); @@ -61,7 +56,7 @@ static void alpha_cpu_list_entry(gpointer data, gpointer user_data) void alpha_cpu_list(FILE *f, fprintf_function cpu_fprintf) { - AlphaCPUListState s = { + CPUListState s = { .file = f, .cpu_fprintf = cpu_fprintf, }; diff --git a/target-arm/helper.c b/target-arm/helper.c index ab8b734933..d2f2fb4820 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1291,11 +1291,6 @@ ARMCPU *cpu_arm_init(const char *cpu_model) return cpu; } -typedef struct ARMCPUListState { - fprintf_function cpu_fprintf; - FILE *file; -} ARMCPUListState; - /* Sort alphabetically by type name, except for "any". */ static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b) { @@ -1317,7 +1312,7 @@ static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b) static void arm_cpu_list_entry(gpointer data, gpointer user_data) { ObjectClass *oc = data; - ARMCPUListState *s = user_data; + CPUListState *s = user_data; (*s->cpu_fprintf)(s->file, " %s\n", object_class_get_name(oc)); @@ -1325,7 +1320,7 @@ static void arm_cpu_list_entry(gpointer data, gpointer user_data) void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf) { - ARMCPUListState s = { + CPUListState s = { .file = f, .cpu_fprintf = cpu_fprintf, }; diff --git a/target-m68k/helper.c b/target-m68k/helper.c index a5d0100473..875a71af21 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -25,11 +25,6 @@ #define SIGNBIT (1u << 31) -typedef struct M68kCPUListState { - fprintf_function cpu_fprintf; - FILE *file; -} M68kCPUListState; - /* Sort alphabetically, except for "any". */ static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b) { @@ -51,7 +46,7 @@ static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b) static void m68k_cpu_list_entry(gpointer data, gpointer user_data) { ObjectClass *c = data; - M68kCPUListState *s = user_data; + CPUListState *s = user_data; (*s->cpu_fprintf)(s->file, "%s\n", object_class_get_name(c)); @@ -59,7 +54,7 @@ static void m68k_cpu_list_entry(gpointer data, gpointer user_data) void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf) { - M68kCPUListState s = { + CPUListState s = { .file = f, .cpu_fprintf = cpu_fprintf, }; From 04a2d61e494532260214736ebb0f975822771643 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 5 Dec 2012 14:49:10 -0200 Subject: [PATCH 2071/2270] qdev: Coding style fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing braces and break lines larger than 80 chars. Signed-off-by: Eduardo Habkost Signed-off-by: Andreas Färber --- hw/qdev-properties.c | 53 +++++++++++++++++++++++++++++--------------- hw/qdev.c | 3 ++- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 81d901c6c4..67543fd76f 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -95,10 +95,11 @@ static void bit_prop_set(DeviceState *dev, Property *props, bool val) { uint32_t *p = qdev_get_prop_ptr(dev, props); uint32_t mask = qdev_get_prop_mask(props); - if (val) + if (val) { *p |= mask; - else + } else { *p &= ~mask; + } } static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len) @@ -420,11 +421,13 @@ static void release_string(Object *obj, const char *name, void *opaque) g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop)); } -static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len) +static int print_string(DeviceState *dev, Property *prop, char *dest, + size_t len) { char **ptr = qdev_get_prop_ptr(dev, prop); - if (!*ptr) + if (!*ptr) { return snprintf(dest, len, ""); + } return snprintf(dest, len, "\"%s\"", *ptr); } @@ -483,10 +486,12 @@ static int parse_drive(DeviceState *dev, const char *str, void **ptr) BlockDriverState *bs; bs = bdrv_find(str); - if (bs == NULL) + if (bs == NULL) { return -ENOENT; - if (bdrv_attach_dev(bs, dev) < 0) + } + if (bdrv_attach_dev(bs, dev) < 0) { return -EEXIST; + } *ptr = bs; return 0; } @@ -749,16 +754,20 @@ static void set_mac(Object *obj, Visitor *v, void *opaque, } for (i = 0, pos = 0; i < 6; i++, pos += 3) { - if (!qemu_isxdigit(str[pos])) + if (!qemu_isxdigit(str[pos])) { goto inval; - if (!qemu_isxdigit(str[pos+1])) + } + if (!qemu_isxdigit(str[pos+1])) { goto inval; + } if (i == 5) { - if (str[pos+2] != '\0') + if (str[pos+2] != '\0') { goto inval; + } } else { - if (str[pos+2] != ':' && str[pos+2] != '-') + if (str[pos+2] != ':' && str[pos+2] != '-') { goto inval; + } } mac->a[i] = strtol(str+pos, &p, 16); } @@ -864,7 +873,8 @@ invalid: g_free(str); } -static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len) +static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, + size_t len) { int32_t *ptr = qdev_get_prop_ptr(dev, prop); @@ -1038,11 +1048,13 @@ PropertyInfo qdev_prop_pci_host_devaddr = { static Property *qdev_prop_walk(Property *props, const char *name) { - if (!props) + if (!props) { return NULL; + } while (props->name) { - if (strcmp(props->name, name) == 0) + if (strcmp(props->name, name) == 0) { return props; + } props++; } return NULL; @@ -1158,7 +1170,8 @@ void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value) assert_no_error(errp); } -int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) +int qdev_prop_set_drive(DeviceState *dev, const char *name, + BlockDriverState *value) { Error *errp = NULL; const char *bdrv_name = value ? bdrv_get_device_name(value) : ""; @@ -1172,13 +1185,15 @@ int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *va return 0; } -void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value) +void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, + BlockDriverState *value) { if (qdev_prop_set_drive(dev, name, value) < 0) { exit(1); } } -void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value) +void qdev_prop_set_chr(DeviceState *dev, const char *name, + CharDriverState *value) { Error *errp = NULL; assert(!value || value->label); @@ -1187,7 +1202,8 @@ void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *valu assert_no_error(errp); } -void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value) +void qdev_prop_set_netdev(DeviceState *dev, const char *name, + NetClientState *value) { Error *errp = NULL; assert(!value || value->name); @@ -1229,7 +1245,8 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value) *ptr = value; } -static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props); +static QTAILQ_HEAD(, GlobalProperty) global_props = + QTAILQ_HEAD_INITIALIZER(global_props); static void qdev_prop_register_global(GlobalProperty *prop) { diff --git a/hw/qdev.c b/hw/qdev.c index 599382cab2..0f8b87843a 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -315,8 +315,9 @@ void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) { qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a); - if (nd->netdev) + if (nd->netdev) { qdev_prop_set_netdev(dev, "netdev", nd->netdev); + } if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED && object_property_find(OBJECT(dev), "vectors", NULL)) { qdev_prop_set_uint32(dev, "vectors", nd->nvectors); From a404b61244ff555ace0a1360fc22275fbeda503e Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 5 Dec 2012 14:49:11 -0200 Subject: [PATCH 2072/2270] qdev-properties.c: Separate core from the code used only by qemu-system-* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This separates the qdev properties code in two parts: - qdev-properties.c, that contains most of the qdev properties code; - qdev-properties-system.c for code specific for qemu-system-*, containing: - Property types: drive, chr, netdev, vlan, that depend on code that won't be included on *-user - qemu_add_globals(), that depends on qemu-config.o. This change should help on two things: - Allowing DeviceState to be used by *-user without pulling dependencies that are specific for qemu-system-*; - Writing qdev unit tests without pulling too many dependencies. The copyright/license of qdev-properties.c isn't explicitly stated at the file, so add a simple copyright/license header pointing to the commit ID of the original file. Signed-off-by: Eduardo Habkost Signed-off-by: Andreas Färber --- hw/Makefile.objs | 1 + hw/qdev-properties-system.c | 357 ++++++++++++++++++++++++++++++++++++ hw/qdev-properties.c | 327 +-------------------------------- hw/qdev-properties.h | 1 + hw/qdev.c | 14 -- 5 files changed, 360 insertions(+), 340 deletions(-) create mode 100644 hw/qdev-properties-system.c diff --git a/hw/Makefile.objs b/hw/Makefile.objs index d581d8d6d6..96a8365349 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -185,6 +185,7 @@ common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o common-obj-y += bt-hci-csr.o common-obj-y += msmouse.o ps2.o common-obj-y += qdev.o qdev-properties.o qdev-monitor.o +common-obj-y += qdev-properties-system.o common-obj-$(CONFIG_BRLAPI) += baum.o # xen backend driver support diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c new file mode 100644 index 0000000000..86b4cf6e99 --- /dev/null +++ b/hw/qdev-properties-system.c @@ -0,0 +1,357 @@ +/* + * qdev property parsing and global properties + * (parts specific for qemu-system-*) + * + * This file is based on code from hw/qdev-properties.c from + * commit 074a86fccd185616469dfcdc0e157f438aebba18, + * Copyright (c) Gerd Hoffmann and other contributors. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "net.h" +#include "qdev.h" +#include "qerror.h" +#include "blockdev.h" +#include "hw/block-common.h" +#include "net/hub.h" +#include "qapi/qapi-visit-core.h" + +static void get_pointer(Object *obj, Visitor *v, Property *prop, + const char *(*print)(void *ptr), + const char *name, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + void **ptr = qdev_get_prop_ptr(dev, prop); + char *p; + + p = (char *) (*ptr ? print(*ptr) : ""); + visit_type_str(v, &p, name, errp); +} + +static void set_pointer(Object *obj, Visitor *v, Property *prop, + int (*parse)(DeviceState *dev, const char *str, + void **ptr), + const char *name, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Error *local_err = NULL; + void **ptr = qdev_get_prop_ptr(dev, prop); + char *str; + int ret; + + if (dev->state != DEV_STATE_CREATED) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + + visit_type_str(v, &str, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + if (!*str) { + g_free(str); + *ptr = NULL; + return; + } + ret = parse(dev, str, ptr); + error_set_from_qdev_prop_error(errp, ret, dev, prop, str); + g_free(str); +} + +/* --- drive --- */ + +static int parse_drive(DeviceState *dev, const char *str, void **ptr) +{ + BlockDriverState *bs; + + bs = bdrv_find(str); + if (bs == NULL) { + return -ENOENT; + } + if (bdrv_attach_dev(bs, dev) < 0) { + return -EEXIST; + } + *ptr = bs; + return 0; +} + +static void release_drive(Object *obj, const char *name, void *opaque) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop); + + if (*ptr) { + bdrv_detach_dev(*ptr, dev); + blockdev_auto_del(*ptr); + } +} + +static const char *print_drive(void *ptr) +{ + return bdrv_get_device_name(ptr); +} + +static void get_drive(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + get_pointer(obj, v, opaque, print_drive, name, errp); +} + +static void set_drive(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + set_pointer(obj, v, opaque, parse_drive, name, errp); +} + +PropertyInfo qdev_prop_drive = { + .name = "drive", + .get = get_drive, + .set = set_drive, + .release = release_drive, +}; + +/* --- character device --- */ + +static int parse_chr(DeviceState *dev, const char *str, void **ptr) +{ + CharDriverState *chr = qemu_chr_find(str); + if (chr == NULL) { + return -ENOENT; + } + if (chr->avail_connections < 1) { + return -EEXIST; + } + *ptr = chr; + --chr->avail_connections; + return 0; +} + +static void release_chr(Object *obj, const char *name, void *opaque) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); + + if (*ptr) { + qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL); + } +} + + +static const char *print_chr(void *ptr) +{ + CharDriverState *chr = ptr; + + return chr->label ? chr->label : ""; +} + +static void get_chr(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + get_pointer(obj, v, opaque, print_chr, name, errp); +} + +static void set_chr(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + set_pointer(obj, v, opaque, parse_chr, name, errp); +} + +PropertyInfo qdev_prop_chr = { + .name = "chr", + .get = get_chr, + .set = set_chr, + .release = release_chr, +}; + +/* --- netdev device --- */ + +static int parse_netdev(DeviceState *dev, const char *str, void **ptr) +{ + NetClientState *netdev = qemu_find_netdev(str); + + if (netdev == NULL) { + return -ENOENT; + } + if (netdev->peer) { + return -EEXIST; + } + *ptr = netdev; + return 0; +} + +static const char *print_netdev(void *ptr) +{ + NetClientState *netdev = ptr; + + return netdev->name ? netdev->name : ""; +} + +static void get_netdev(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + get_pointer(obj, v, opaque, print_netdev, name, errp); +} + +static void set_netdev(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + set_pointer(obj, v, opaque, parse_netdev, name, errp); +} + +PropertyInfo qdev_prop_netdev = { + .name = "netdev", + .get = get_netdev, + .set = set_netdev, +}; + +/* --- vlan --- */ + +static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len) +{ + NetClientState **ptr = qdev_get_prop_ptr(dev, prop); + + if (*ptr) { + int id; + if (!net_hub_id_for_client(*ptr, &id)) { + return snprintf(dest, len, "%d", id); + } + } + + return snprintf(dest, len, ""); +} + +static void get_vlan(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + NetClientState **ptr = qdev_get_prop_ptr(dev, prop); + int32_t id = -1; + + if (*ptr) { + int hub_id; + if (!net_hub_id_for_client(*ptr, &hub_id)) { + id = hub_id; + } + } + + visit_type_int32(v, &id, name, errp); +} + +static void set_vlan(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + NetClientState **ptr = qdev_get_prop_ptr(dev, prop); + Error *local_err = NULL; + int32_t id; + NetClientState *hubport; + + if (dev->state != DEV_STATE_CREATED) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + + visit_type_int32(v, &id, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + if (id == -1) { + *ptr = NULL; + return; + } + + hubport = net_hub_port_find(id); + if (!hubport) { + error_set(errp, QERR_INVALID_PARAMETER_VALUE, + name, prop->info->name); + return; + } + *ptr = hubport; +} + +PropertyInfo qdev_prop_vlan = { + .name = "vlan", + .print = print_vlan, + .get = get_vlan, + .set = set_vlan, +}; + +int qdev_prop_set_drive(DeviceState *dev, const char *name, + BlockDriverState *value) +{ + Error *errp = NULL; + const char *bdrv_name = value ? bdrv_get_device_name(value) : ""; + object_property_set_str(OBJECT(dev), bdrv_name, + name, &errp); + if (errp) { + qerror_report_err(errp); + error_free(errp); + return -1; + } + return 0; +} + +void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, + BlockDriverState *value) +{ + if (qdev_prop_set_drive(dev, name, value) < 0) { + exit(1); + } +} +void qdev_prop_set_chr(DeviceState *dev, const char *name, + CharDriverState *value) +{ + Error *errp = NULL; + assert(!value || value->label); + object_property_set_str(OBJECT(dev), + value ? value->label : "", name, &errp); + assert_no_error(errp); +} + +void qdev_prop_set_netdev(DeviceState *dev, const char *name, + NetClientState *value) +{ + Error *errp = NULL; + assert(!value || value->name); + object_property_set_str(OBJECT(dev), + value ? value->name : "", name, &errp); + assert_no_error(errp); +} + +void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) +{ + qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a); + if (nd->netdev) { + qdev_prop_set_netdev(dev, "netdev", nd->netdev); + } + if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED && + object_property_find(OBJECT(dev), "vectors", NULL)) { + qdev_prop_set_uint32(dev, "vectors", nd->nvectors); + } + nd->instantiated = 1; +} + +static int qdev_add_one_global(QemuOpts *opts, void *opaque) +{ + GlobalProperty *g; + + g = g_malloc0(sizeof(*g)); + g->driver = qemu_opt_get(opts, "driver"); + g->property = qemu_opt_get(opts, "property"); + g->value = qemu_opt_get(opts, "value"); + qdev_prop_register_global(g); + return 0; +} + +void qemu_add_globals(void) +{ + qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0); +} diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 67543fd76f..bbab2a95af 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -13,49 +13,6 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) return ptr; } -static void get_pointer(Object *obj, Visitor *v, Property *prop, - const char *(*print)(void *ptr), - const char *name, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - void **ptr = qdev_get_prop_ptr(dev, prop); - char *p; - - p = (char *) (*ptr ? print(*ptr) : ""); - visit_type_str(v, &p, name, errp); -} - -static void set_pointer(Object *obj, Visitor *v, Property *prop, - int (*parse)(DeviceState *dev, const char *str, - void **ptr), - const char *name, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Error *local_err = NULL; - void **ptr = qdev_get_prop_ptr(dev, prop); - char *str; - int ret; - - if (dev->state != DEV_STATE_CREATED) { - error_set(errp, QERR_PERMISSION_DENIED); - return; - } - - visit_type_str(v, &str, name, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - if (!*str) { - g_free(str); - *ptr = NULL; - return; - } - ret = parse(dev, str, ptr); - error_set_from_qdev_prop_error(errp, ret, dev, prop, str); - g_free(str); -} - static void get_enum(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { @@ -479,229 +436,6 @@ PropertyInfo qdev_prop_string = { .set = set_string, }; -/* --- drive --- */ - -static int parse_drive(DeviceState *dev, const char *str, void **ptr) -{ - BlockDriverState *bs; - - bs = bdrv_find(str); - if (bs == NULL) { - return -ENOENT; - } - if (bdrv_attach_dev(bs, dev) < 0) { - return -EEXIST; - } - *ptr = bs; - return 0; -} - -static void release_drive(Object *obj, const char *name, void *opaque) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop); - - if (*ptr) { - bdrv_detach_dev(*ptr, dev); - blockdev_auto_del(*ptr); - } -} - -static const char *print_drive(void *ptr) -{ - return bdrv_get_device_name(ptr); -} - -static void get_drive(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - get_pointer(obj, v, opaque, print_drive, name, errp); -} - -static void set_drive(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - set_pointer(obj, v, opaque, parse_drive, name, errp); -} - -PropertyInfo qdev_prop_drive = { - .name = "drive", - .get = get_drive, - .set = set_drive, - .release = release_drive, -}; - -/* --- character device --- */ - -static int parse_chr(DeviceState *dev, const char *str, void **ptr) -{ - CharDriverState *chr = qemu_chr_find(str); - if (chr == NULL) { - return -ENOENT; - } - if (chr->avail_connections < 1) { - return -EEXIST; - } - *ptr = chr; - --chr->avail_connections; - return 0; -} - -static void release_chr(Object *obj, const char *name, void *opaque) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); - - if (*ptr) { - qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL); - } -} - - -static const char *print_chr(void *ptr) -{ - CharDriverState *chr = ptr; - - return chr->label ? chr->label : ""; -} - -static void get_chr(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - get_pointer(obj, v, opaque, print_chr, name, errp); -} - -static void set_chr(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - set_pointer(obj, v, opaque, parse_chr, name, errp); -} - -PropertyInfo qdev_prop_chr = { - .name = "chr", - .get = get_chr, - .set = set_chr, - .release = release_chr, -}; - -/* --- netdev device --- */ - -static int parse_netdev(DeviceState *dev, const char *str, void **ptr) -{ - NetClientState *netdev = qemu_find_netdev(str); - - if (netdev == NULL) { - return -ENOENT; - } - if (netdev->peer) { - return -EEXIST; - } - *ptr = netdev; - return 0; -} - -static const char *print_netdev(void *ptr) -{ - NetClientState *netdev = ptr; - - return netdev->name ? netdev->name : ""; -} - -static void get_netdev(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - get_pointer(obj, v, opaque, print_netdev, name, errp); -} - -static void set_netdev(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - set_pointer(obj, v, opaque, parse_netdev, name, errp); -} - -PropertyInfo qdev_prop_netdev = { - .name = "netdev", - .get = get_netdev, - .set = set_netdev, -}; - -/* --- vlan --- */ - -static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len) -{ - NetClientState **ptr = qdev_get_prop_ptr(dev, prop); - - if (*ptr) { - int id; - if (!net_hub_id_for_client(*ptr, &id)) { - return snprintf(dest, len, "%d", id); - } - } - - return snprintf(dest, len, ""); -} - -static void get_vlan(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - NetClientState **ptr = qdev_get_prop_ptr(dev, prop); - int32_t id = -1; - - if (*ptr) { - int hub_id; - if (!net_hub_id_for_client(*ptr, &hub_id)) { - id = hub_id; - } - } - - visit_type_int32(v, &id, name, errp); -} - -static void set_vlan(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - NetClientState **ptr = qdev_get_prop_ptr(dev, prop); - Error *local_err = NULL; - int32_t id; - NetClientState *hubport; - - if (dev->state != DEV_STATE_CREATED) { - error_set(errp, QERR_PERMISSION_DENIED); - return; - } - - visit_type_int32(v, &id, name, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - if (id == -1) { - *ptr = NULL; - return; - } - - hubport = net_hub_port_find(id); - if (!hubport) { - error_set(errp, QERR_INVALID_PARAMETER_VALUE, - name, prop->info->name); - return; - } - *ptr = hubport; -} - -PropertyInfo qdev_prop_vlan = { - .name = "vlan", - .print = print_vlan, - .get = get_vlan, - .set = set_vlan, -}; - /* --- pointer --- */ /* Not a proper property, just for dirty hacks. TODO Remove it! */ @@ -1170,48 +904,6 @@ void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value) assert_no_error(errp); } -int qdev_prop_set_drive(DeviceState *dev, const char *name, - BlockDriverState *value) -{ - Error *errp = NULL; - const char *bdrv_name = value ? bdrv_get_device_name(value) : ""; - object_property_set_str(OBJECT(dev), bdrv_name, - name, &errp); - if (errp) { - qerror_report_err(errp); - error_free(errp); - return -1; - } - return 0; -} - -void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, - BlockDriverState *value) -{ - if (qdev_prop_set_drive(dev, name, value) < 0) { - exit(1); - } -} -void qdev_prop_set_chr(DeviceState *dev, const char *name, - CharDriverState *value) -{ - Error *errp = NULL; - assert(!value || value->label); - object_property_set_str(OBJECT(dev), - value ? value->label : "", name, &errp); - assert_no_error(errp); -} - -void qdev_prop_set_netdev(DeviceState *dev, const char *name, - NetClientState *value) -{ - Error *errp = NULL; - assert(!value || value->name); - object_property_set_str(OBJECT(dev), - value ? value->name : "", name, &errp); - assert_no_error(errp); -} - void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value) { Error *errp = NULL; @@ -1248,7 +940,7 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value) static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props); -static void qdev_prop_register_global(GlobalProperty *prop) +void qdev_prop_register_global(GlobalProperty *prop) { QTAILQ_INSERT_TAIL(&global_props, prop, next); } @@ -1279,20 +971,3 @@ void qdev_prop_set_globals(DeviceState *dev) class = object_class_get_parent(class); } while (class); } - -static int qdev_add_one_global(QemuOpts *opts, void *opaque) -{ - GlobalProperty *g; - - g = g_malloc0(sizeof(*g)); - g->driver = qemu_opt_get(opts, "driver"); - g->property = qemu_opt_get(opts, "property"); - g->value = qemu_opt_get(opts, "value"); - qdev_prop_register_global(g); - return 0; -} - -void qemu_add_globals(void) -{ - qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0); -} diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h index 5b046abb28..ddcf774506 100644 --- a/hw/qdev-properties.h +++ b/hw/qdev-properties.h @@ -116,6 +116,7 @@ void qdev_prop_set_enum(DeviceState *dev, const char *name, int value); /* FIXME: Remove opaque pointer properties. */ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value); +void qdev_prop_register_global(GlobalProperty *prop); void qdev_prop_register_global_list(GlobalProperty *props); void qdev_prop_set_globals(DeviceState *dev); void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, diff --git a/hw/qdev.c b/hw/qdev.c index 0f8b87843a..fa0af21b58 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -25,7 +25,6 @@ inherit from a particular bus (e.g. PCI or I2C) rather than this API directly. */ -#include "net.h" #include "qdev.h" #include "sysemu.h" #include "error.h" @@ -312,19 +311,6 @@ void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) dev->gpio_out[n] = pin; } -void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) -{ - qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a); - if (nd->netdev) { - qdev_prop_set_netdev(dev, "netdev", nd->netdev); - } - if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED && - object_property_find(OBJECT(dev), "vectors", NULL)) { - qdev_prop_set_uint32(dev, "vectors", nd->nvectors); - } - nd->instantiated = 1; -} - BusState *qdev_get_child_bus(DeviceState *dev, const char *name) { BusState *bus; From 8737c51c0444f832c4e97d7eb7540eae457e08e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 31 Oct 2012 05:29:00 +0100 Subject: [PATCH 2073/2270] cpu: Move kvm_fd into CPUState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- cpu-defs.h | 1 - include/qemu/cpu.h | 5 +++++ kvm-all.c | 8 +++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/cpu-defs.h b/cpu-defs.h index 3669241faf..6373a808f9 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -207,7 +207,6 @@ typedef struct CPUWatchpoint { const char *cpu_model_str; \ struct KVMState *kvm_state; \ struct kvm_run *kvm_run; \ - int kvm_fd; \ int kvm_vcpu_dirty; #endif diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h index 61b76982f1..6049a20a4d 100644 --- a/include/qemu/cpu.h +++ b/include/qemu/cpu.h @@ -57,6 +57,7 @@ typedef struct CPUClass { * @created: Indicates whether the CPU thread has been successfully created. * @stop: Indicates a pending stop request. * @stopped: Indicates the CPU has been artificially stopped. + * @kvm_fd: vCPU file descriptor for KVM. * * State of one CPU core or thread. */ @@ -77,6 +78,10 @@ struct CPUState { bool stop; bool stopped; +#if !defined(CONFIG_USER_ONLY) + int kvm_fd; +#endif + /* TODO Move common fields from CPUArchState here. */ }; diff --git a/kvm-all.c b/kvm-all.c index 8e9a8d8fd2..8a00df72c3 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -216,6 +216,7 @@ static void kvm_reset_vcpu(void *opaque) int kvm_init_vcpu(CPUArchState *env) { + CPUState *cpu = ENV_GET_CPU(env); KVMState *s = kvm_state; long mmap_size; int ret; @@ -228,7 +229,7 @@ int kvm_init_vcpu(CPUArchState *env) goto err; } - env->kvm_fd = ret; + cpu->kvm_fd = ret; env->kvm_state = s; env->kvm_vcpu_dirty = 1; @@ -240,7 +241,7 @@ int kvm_init_vcpu(CPUArchState *env) } env->kvm_run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, - env->kvm_fd, 0); + cpu->kvm_fd, 0); if (env->kvm_run == MAP_FAILED) { ret = -errno; DPRINTF("mmap'ing vcpu state failed\n"); @@ -1652,6 +1653,7 @@ int kvm_vm_ioctl(KVMState *s, int type, ...) int kvm_vcpu_ioctl(CPUArchState *env, int type, ...) { + CPUState *cpu = ENV_GET_CPU(env); int ret; void *arg; va_list ap; @@ -1660,7 +1662,7 @@ int kvm_vcpu_ioctl(CPUArchState *env, int type, ...) arg = va_arg(ap, void *); va_end(ap); - ret = ioctl(env->kvm_fd, type, arg); + ret = ioctl(cpu->kvm_fd, type, arg); if (ret == -1) { ret = -errno; } From 20d695a9254c1b086a456d3b79a3c311236643ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 31 Oct 2012 06:57:49 +0100 Subject: [PATCH 2074/2270] kvm: Pass CPUState to kvm_arch_* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move kvm_vcpu_dirty field into CPUState to simplify things and change its type to bool while at it. Signed-off-by: Andreas Färber --- cpu-defs.h | 3 +- include/qemu/cpu.h | 1 + kvm-all.c | 75 +++++++++++++++++++++++++++------------------- kvm.h | 26 ++++++++-------- target-i386/kvm.c | 59 +++++++++++++++++++++++------------- target-ppc/kvm.c | 36 ++++++++++++++-------- target-s390x/kvm.c | 38 +++++++++++++++-------- 7 files changed, 146 insertions(+), 92 deletions(-) diff --git a/cpu-defs.h b/cpu-defs.h index 6373a808f9..a382e35248 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -206,7 +206,6 @@ typedef struct CPUWatchpoint { \ const char *cpu_model_str; \ struct KVMState *kvm_state; \ - struct kvm_run *kvm_run; \ - int kvm_vcpu_dirty; + struct kvm_run *kvm_run; #endif diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h index 6049a20a4d..b8f8dd1d13 100644 --- a/include/qemu/cpu.h +++ b/include/qemu/cpu.h @@ -80,6 +80,7 @@ struct CPUState { #if !defined(CONFIG_USER_ONLY) int kvm_fd; + bool kvm_vcpu_dirty; #endif /* TODO Move common fields from CPUArchState here. */ diff --git a/kvm-all.c b/kvm-all.c index 8a00df72c3..792cdf1d66 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -209,9 +209,9 @@ static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot) static void kvm_reset_vcpu(void *opaque) { - CPUArchState *env = opaque; + CPUState *cpu = opaque; - kvm_arch_reset_vcpu(env); + kvm_arch_reset_vcpu(cpu); } int kvm_init_vcpu(CPUArchState *env) @@ -231,7 +231,7 @@ int kvm_init_vcpu(CPUArchState *env) cpu->kvm_fd = ret; env->kvm_state = s; - env->kvm_vcpu_dirty = 1; + cpu->kvm_vcpu_dirty = true; mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0); if (mmap_size < 0) { @@ -253,10 +253,10 @@ int kvm_init_vcpu(CPUArchState *env) (void *)env->kvm_run + s->coalesced_mmio * PAGE_SIZE; } - ret = kvm_arch_init_vcpu(env); + ret = kvm_arch_init_vcpu(cpu); if (ret == 0) { - qemu_register_reset(kvm_reset_vcpu, env); - kvm_arch_reset_vcpu(env); + qemu_register_reset(kvm_reset_vcpu, cpu); + kvm_arch_reset_vcpu(cpu); } err: return ret; @@ -1438,6 +1438,8 @@ static void kvm_handle_io(uint16_t port, void *data, int direction, int size, static int kvm_handle_internal_error(CPUArchState *env, struct kvm_run *run) { + CPUState *cpu = ENV_GET_CPU(env); + fprintf(stderr, "KVM internal error."); if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) { int i; @@ -1452,7 +1454,7 @@ static int kvm_handle_internal_error(CPUArchState *env, struct kvm_run *run) } if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) { fprintf(stderr, "emulation failure\n"); - if (!kvm_arch_stop_on_emulation_error(env)) { + if (!kvm_arch_stop_on_emulation_error(cpu)) { cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE); return EXCP_INTERRUPT; } @@ -1489,13 +1491,13 @@ void kvm_flush_coalesced_mmio_buffer(void) s->coalesced_flush_in_progress = false; } -static void do_kvm_cpu_synchronize_state(void *_env) +static void do_kvm_cpu_synchronize_state(void *arg) { - CPUArchState *env = _env; + CPUState *cpu = arg; - if (!env->kvm_vcpu_dirty) { - kvm_arch_get_registers(env); - env->kvm_vcpu_dirty = 1; + if (!cpu->kvm_vcpu_dirty) { + kvm_arch_get_registers(cpu); + cpu->kvm_vcpu_dirty = true; } } @@ -1503,42 +1505,47 @@ void kvm_cpu_synchronize_state(CPUArchState *env) { CPUState *cpu = ENV_GET_CPU(env); - if (!env->kvm_vcpu_dirty) { - run_on_cpu(cpu, do_kvm_cpu_synchronize_state, env); + if (!cpu->kvm_vcpu_dirty) { + run_on_cpu(cpu, do_kvm_cpu_synchronize_state, cpu); } } void kvm_cpu_synchronize_post_reset(CPUArchState *env) { - kvm_arch_put_registers(env, KVM_PUT_RESET_STATE); - env->kvm_vcpu_dirty = 0; + CPUState *cpu = ENV_GET_CPU(env); + + kvm_arch_put_registers(cpu, KVM_PUT_RESET_STATE); + cpu->kvm_vcpu_dirty = false; } void kvm_cpu_synchronize_post_init(CPUArchState *env) { - kvm_arch_put_registers(env, KVM_PUT_FULL_STATE); - env->kvm_vcpu_dirty = 0; + CPUState *cpu = ENV_GET_CPU(env); + + kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE); + cpu->kvm_vcpu_dirty = false; } int kvm_cpu_exec(CPUArchState *env) { + CPUState *cpu = ENV_GET_CPU(env); struct kvm_run *run = env->kvm_run; int ret, run_ret; DPRINTF("kvm_cpu_exec()\n"); - if (kvm_arch_process_async_events(env)) { + if (kvm_arch_process_async_events(cpu)) { env->exit_request = 0; return EXCP_HLT; } do { - if (env->kvm_vcpu_dirty) { - kvm_arch_put_registers(env, KVM_PUT_RUNTIME_STATE); - env->kvm_vcpu_dirty = 0; + if (cpu->kvm_vcpu_dirty) { + kvm_arch_put_registers(cpu, KVM_PUT_RUNTIME_STATE); + cpu->kvm_vcpu_dirty = false; } - kvm_arch_pre_run(env, run); + kvm_arch_pre_run(cpu, run); if (env->exit_request) { DPRINTF("interrupt exit requested\n"); /* @@ -1553,7 +1560,7 @@ int kvm_cpu_exec(CPUArchState *env) run_ret = kvm_vcpu_ioctl(env, KVM_RUN, 0); qemu_mutex_lock_iothread(); - kvm_arch_post_run(env, run); + kvm_arch_post_run(cpu, run); if (run_ret < 0) { if (run_ret == -EINTR || run_ret == -EAGAIN) { @@ -1603,7 +1610,7 @@ int kvm_cpu_exec(CPUArchState *env) break; default: DPRINTF("kvm_arch_handle_exit\n"); - ret = kvm_arch_handle_exit(env, run); + ret = kvm_arch_handle_exit(cpu, run); break; } } while (ret == 0); @@ -1799,7 +1806,7 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap) if (env->singlestep_enabled) { data.dbg.control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP; } - kvm_arch_update_guest_debug(env, &data.dbg); + kvm_arch_update_guest_debug(cpu, &data.dbg); data.env = env; run_on_cpu(cpu, kvm_invoke_set_guest_debug, &data); @@ -1809,6 +1816,7 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap) int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, target_ulong len, int type) { + CPUState *current_cpu = ENV_GET_CPU(current_env); struct kvm_sw_breakpoint *bp; CPUArchState *env; int err; @@ -1827,7 +1835,7 @@ int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, bp->pc = addr; bp->use_count = 1; - err = kvm_arch_insert_sw_breakpoint(current_env, bp); + err = kvm_arch_insert_sw_breakpoint(current_cpu, bp); if (err) { g_free(bp); return err; @@ -1854,6 +1862,7 @@ int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, target_ulong len, int type) { + CPUState *current_cpu = ENV_GET_CPU(current_env); struct kvm_sw_breakpoint *bp; CPUArchState *env; int err; @@ -1869,7 +1878,7 @@ int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, return 0; } - err = kvm_arch_remove_sw_breakpoint(current_env, bp); + err = kvm_arch_remove_sw_breakpoint(current_cpu, bp); if (err) { return err; } @@ -1894,15 +1903,18 @@ int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, void kvm_remove_all_breakpoints(CPUArchState *current_env) { + CPUState *current_cpu = ENV_GET_CPU(current_env); struct kvm_sw_breakpoint *bp, *next; KVMState *s = current_env->kvm_state; CPUArchState *env; + CPUState *cpu; QTAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) { - if (kvm_arch_remove_sw_breakpoint(current_env, bp) != 0) { + if (kvm_arch_remove_sw_breakpoint(current_cpu, bp) != 0) { /* Try harder to find a CPU that currently sees the breakpoint. */ for (env = first_cpu; env != NULL; env = env->next_cpu) { - if (kvm_arch_remove_sw_breakpoint(env, bp) == 0) { + cpu = ENV_GET_CPU(env); + if (kvm_arch_remove_sw_breakpoint(cpu, bp) == 0) { break; } } @@ -2014,7 +2026,8 @@ int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign) int kvm_on_sigbus_vcpu(CPUArchState *env, int code, void *addr) { - return kvm_arch_on_sigbus_vcpu(env, code, addr); + CPUState *cpu = ENV_GET_CPU(env); + return kvm_arch_on_sigbus_vcpu(cpu, code, addr); } int kvm_on_sigbus(int code, void *addr) diff --git a/kvm.h b/kvm.h index 72d866a966..61f00b7456 100644 --- a/kvm.h +++ b/kvm.h @@ -158,14 +158,14 @@ int kvm_vcpu_ioctl(CPUArchState *env, int type, ...); extern const KVMCapabilityInfo kvm_arch_required_capabilities[]; -void kvm_arch_pre_run(CPUArchState *env, struct kvm_run *run); -void kvm_arch_post_run(CPUArchState *env, struct kvm_run *run); +void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run); +void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run); -int kvm_arch_handle_exit(CPUArchState *env, struct kvm_run *run); +int kvm_arch_handle_exit(CPUState *cpu, struct kvm_run *run); -int kvm_arch_process_async_events(CPUArchState *env); +int kvm_arch_process_async_events(CPUState *cpu); -int kvm_arch_get_registers(CPUArchState *env); +int kvm_arch_get_registers(CPUState *cpu); /* state subset only touched by the VCPU itself during runtime */ #define KVM_PUT_RUNTIME_STATE 1 @@ -174,15 +174,15 @@ int kvm_arch_get_registers(CPUArchState *env); /* full state set, modified during initialization or on vmload */ #define KVM_PUT_FULL_STATE 3 -int kvm_arch_put_registers(CPUArchState *env, int level); +int kvm_arch_put_registers(CPUState *cpu, int level); int kvm_arch_init(KVMState *s); -int kvm_arch_init_vcpu(CPUArchState *env); +int kvm_arch_init_vcpu(CPUState *cpu); -void kvm_arch_reset_vcpu(CPUArchState *env); +void kvm_arch_reset_vcpu(CPUState *cpu); -int kvm_arch_on_sigbus_vcpu(CPUArchState *env, int code, void *addr); +int kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr); int kvm_arch_on_sigbus(int code, void *addr); void kvm_arch_init_irq_routing(KVMState *s); @@ -212,9 +212,9 @@ struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUArchState *env, int kvm_sw_breakpoints_active(CPUArchState *env); -int kvm_arch_insert_sw_breakpoint(CPUArchState *current_env, +int kvm_arch_insert_sw_breakpoint(CPUState *current_cpu, struct kvm_sw_breakpoint *bp); -int kvm_arch_remove_sw_breakpoint(CPUArchState *current_env, +int kvm_arch_remove_sw_breakpoint(CPUState *current_cpu, struct kvm_sw_breakpoint *bp); int kvm_arch_insert_hw_breakpoint(target_ulong addr, target_ulong len, int type); @@ -222,9 +222,9 @@ int kvm_arch_remove_hw_breakpoint(target_ulong addr, target_ulong len, int type); void kvm_arch_remove_all_hw_breakpoints(void); -void kvm_arch_update_guest_debug(CPUArchState *env, struct kvm_guest_debug *dbg); +void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg); -bool kvm_arch_stop_on_emulation_error(CPUArchState *env); +bool kvm_arch_stop_on_emulation_error(CPUState *cpu); int kvm_check_extension(KVMState *s, unsigned int extension); diff --git a/target-i386/kvm.c b/target-i386/kvm.c index f669281e13..80cacf3764 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -306,9 +306,10 @@ static void hardware_memory_error(void) exit(1); } -int kvm_arch_on_sigbus_vcpu(CPUX86State *env, int code, void *addr) +int kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) { - X86CPU *cpu = x86_env_get_cpu(env); + X86CPU *cpu = X86_CPU(c); + CPUX86State *env = &cpu->env; ram_addr_t ram_addr; hwaddr paddr; @@ -406,12 +407,14 @@ static void cpu_update_state(void *opaque, int running, RunState state) } } -int kvm_arch_init_vcpu(CPUX86State *env) +int kvm_arch_init_vcpu(CPUState *cs) { struct { struct kvm_cpuid2 cpuid; struct kvm_cpuid_entry2 entries[100]; } QEMU_PACKED cpuid_data; + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; uint32_t limit, i, j, cpuid_i; uint32_t unused; struct kvm_cpuid_entry2 *c; @@ -623,9 +626,10 @@ int kvm_arch_init_vcpu(CPUX86State *env) return 0; } -void kvm_arch_reset_vcpu(CPUX86State *env) +void kvm_arch_reset_vcpu(CPUState *cs) { - X86CPU *cpu = x86_env_get_cpu(env); + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; env->exception_injected = -1; env->interrupt_injected = -1; @@ -1582,9 +1586,10 @@ static int kvm_get_debugregs(CPUX86State *env) return 0; } -int kvm_arch_put_registers(CPUX86State *env, int level) +int kvm_arch_put_registers(CPUState *cpu, int level) { - CPUState *cpu = ENV_GET_CPU(env); + X86CPU *x86_cpu = X86_CPU(cpu); + CPUX86State *env = &x86_cpu->env; int ret; assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); @@ -1640,12 +1645,13 @@ int kvm_arch_put_registers(CPUX86State *env, int level) return 0; } -int kvm_arch_get_registers(CPUX86State *env) +int kvm_arch_get_registers(CPUState *cs) { - X86CPU *cpu = x86_env_get_cpu(env); + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; int ret; - assert(cpu_is_stopped(CPU(cpu)) || qemu_cpu_is_self(CPU(cpu))); + assert(cpu_is_stopped(cs) || qemu_cpu_is_self(cs)); ret = kvm_getput_regs(env, 0); if (ret < 0) { @@ -1686,8 +1692,10 @@ int kvm_arch_get_registers(CPUX86State *env) return 0; } -void kvm_arch_pre_run(CPUX86State *env, struct kvm_run *run) +void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run) { + X86CPU *x86_cpu = X86_CPU(cpu); + CPUX86State *env = &x86_cpu->env; int ret; /* Inject NMI */ @@ -1746,8 +1754,11 @@ void kvm_arch_pre_run(CPUX86State *env, struct kvm_run *run) } } -void kvm_arch_post_run(CPUX86State *env, struct kvm_run *run) +void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run) { + X86CPU *x86_cpu = X86_CPU(cpu); + CPUX86State *env = &x86_cpu->env; + if (run->if_flag) { env->eflags |= IF_MASK; } else { @@ -1757,9 +1768,10 @@ void kvm_arch_post_run(CPUX86State *env, struct kvm_run *run) cpu_set_apic_base(env->apic_state, run->apic_base); } -int kvm_arch_process_async_events(CPUX86State *env) +int kvm_arch_process_async_events(CPUState *cs) { - X86CPU *cpu = x86_env_get_cpu(env); + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; if (env->interrupt_request & CPU_INTERRUPT_MCE) { /* We must not raise CPU_INTERRUPT_MCE if it's not supported. */ @@ -1839,8 +1851,9 @@ static int kvm_handle_tpr_access(CPUX86State *env) return 1; } -int kvm_arch_insert_sw_breakpoint(CPUX86State *env, struct kvm_sw_breakpoint *bp) +int kvm_arch_insert_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp) { + CPUX86State *env = &X86_CPU(cpu)->env; static const uint8_t int3 = 0xcc; if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 0) || @@ -1850,8 +1863,9 @@ int kvm_arch_insert_sw_breakpoint(CPUX86State *env, struct kvm_sw_breakpoint *bp return 0; } -int kvm_arch_remove_sw_breakpoint(CPUX86State *env, struct kvm_sw_breakpoint *bp) +int kvm_arch_remove_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp) { + CPUX86State *env = &X86_CPU(cpu)->env; uint8_t int3; if (cpu_memory_rw_debug(env, bp->pc, &int3, 1, 0) || int3 != 0xcc || @@ -1994,8 +2008,9 @@ static int kvm_handle_debug(CPUX86State *env, return ret; } -void kvm_arch_update_guest_debug(CPUX86State *env, struct kvm_guest_debug *dbg) +void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg) { + CPUX86State *env = &X86_CPU(cpu)->env; const uint8_t type_code[] = { [GDB_BREAKPOINT_HW] = 0x0, [GDB_WATCHPOINT_WRITE] = 0x1, @@ -2031,9 +2046,10 @@ static bool host_supports_vmx(void) #define VMX_INVALID_GUEST_STATE 0x80000021 -int kvm_arch_handle_exit(CPUX86State *env, struct kvm_run *run) +int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) { - X86CPU *cpu = x86_env_get_cpu(env); + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; uint64_t code; int ret; @@ -2083,8 +2099,11 @@ int kvm_arch_handle_exit(CPUX86State *env, struct kvm_run *run) return ret; } -bool kvm_arch_stop_on_emulation_error(CPUX86State *env) +bool kvm_arch_stop_on_emulation_error(CPUState *cs) { + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; + kvm_cpu_synchronize_state(env); return !(env->cr[0] & CR0_PE_MASK) || ((env->segs[R_CS].selector & 3) != 3); diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 3f5df5772f..8a59b706da 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -375,9 +375,10 @@ static inline void kvm_fixup_page_sizes(CPUPPCState *env) #endif /* !defined (TARGET_PPC64) */ -int kvm_arch_init_vcpu(CPUPPCState *cenv) +int kvm_arch_init_vcpu(CPUState *cs) { - PowerPCCPU *cpu = ppc_env_get_cpu(cenv); + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *cenv = &cpu->env; int ret; /* Gather server mmu info from KVM and update the CPU state */ @@ -403,7 +404,7 @@ int kvm_arch_init_vcpu(CPUPPCState *cenv) return ret; } -void kvm_arch_reset_vcpu(CPUPPCState *env) +void kvm_arch_reset_vcpu(CPUState *cpu) { } @@ -432,8 +433,10 @@ static void kvm_sw_tlb_put(CPUPPCState *env) g_free(bitmap); } -int kvm_arch_put_registers(CPUPPCState *env, int level) +int kvm_arch_put_registers(CPUState *cs, int level) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; struct kvm_regs regs; int ret; int i; @@ -525,8 +528,10 @@ int kvm_arch_put_registers(CPUPPCState *env, int level) return ret; } -int kvm_arch_get_registers(CPUPPCState *env) +int kvm_arch_get_registers(CPUState *cs) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; struct kvm_regs regs; struct kvm_sregs sregs; uint32_t cr; @@ -727,8 +732,10 @@ int kvmppc_set_interrupt(CPUPPCState *env, int irq, int level) #define PPC_INPUT_INT PPC6xx_INPUT_INT #endif -void kvm_arch_pre_run(CPUPPCState *env, struct kvm_run *run) +void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; int r; unsigned irq; @@ -760,13 +767,14 @@ void kvm_arch_pre_run(CPUPPCState *env, struct kvm_run *run) * anyways, so we will get a chance to deliver the rest. */ } -void kvm_arch_post_run(CPUPPCState *env, struct kvm_run *run) +void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run) { } -int kvm_arch_process_async_events(CPUPPCState *env) +int kvm_arch_process_async_events(CPUState *cs) { - return env->halted; + PowerPCCPU *cpu = POWERPC_CPU(cs); + return cpu->env.halted; } static int kvmppc_handle_halt(CPUPPCState *env) @@ -796,8 +804,10 @@ static int kvmppc_handle_dcr_write(CPUPPCState *env, uint32_t dcrn, uint32_t dat return 0; } -int kvm_arch_handle_exit(CPUPPCState *env, struct kvm_run *run) +int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; int ret; switch (run->exit_reason) { @@ -817,7 +827,7 @@ int kvm_arch_handle_exit(CPUPPCState *env, struct kvm_run *run) #ifdef CONFIG_PSERIES case KVM_EXIT_PAPR_HCALL: dprintf("handle PAPR hypercall\n"); - run->papr_hcall.ret = spapr_hypercall(ppc_env_get_cpu(env), + run->papr_hcall.ret = spapr_hypercall(cpu, run->papr_hcall.nr, run->papr_hcall.args); ret = 0; @@ -1225,12 +1235,12 @@ int kvmppc_fixup_cpu(CPUPPCState *env) } -bool kvm_arch_stop_on_emulation_error(CPUPPCState *env) +bool kvm_arch_stop_on_emulation_error(CPUState *cpu) { return true; } -int kvm_arch_on_sigbus_vcpu(CPUPPCState *env, int code, void *addr) +int kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr) { return 1; } diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 94de764264..d4e6ab2db8 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -72,8 +72,9 @@ int kvm_arch_init(KVMState *s) return 0; } -int kvm_arch_init_vcpu(CPUS390XState *env) +int kvm_arch_init_vcpu(CPUState *cpu) { + CPUS390XState *env = &S390_CPU(cpu)->env; int ret = 0; if (kvm_vcpu_ioctl(env, KVM_S390_INITIAL_RESET, NULL) < 0) { @@ -83,13 +84,15 @@ int kvm_arch_init_vcpu(CPUS390XState *env) return ret; } -void kvm_arch_reset_vcpu(CPUS390XState *env) +void kvm_arch_reset_vcpu(CPUState *cpu) { /* FIXME: add code to reset vcpu. */ } -int kvm_arch_put_registers(CPUS390XState *env, int level) +int kvm_arch_put_registers(CPUState *cs, int level) { + S390CPU *cpu = S390_CPU(cs); + CPUS390XState *env = &cpu->env; struct kvm_sregs sregs; struct kvm_regs regs; int ret; @@ -149,8 +152,10 @@ int kvm_arch_put_registers(CPUS390XState *env, int level) return 0; } -int kvm_arch_get_registers(CPUS390XState *env) +int kvm_arch_get_registers(CPUState *cs) { + S390CPU *cpu = S390_CPU(cs); + CPUS390XState *env = &cpu->env; struct kvm_sregs sregs; struct kvm_regs regs; int ret; @@ -239,8 +244,10 @@ void *kvm_arch_vmalloc(ram_addr_t size) } } -int kvm_arch_insert_sw_breakpoint(CPUS390XState *env, struct kvm_sw_breakpoint *bp) +int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) { + S390CPU *cpu = S390_CPU(cs); + CPUS390XState *env = &cpu->env; static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01}; if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 4, 0) || @@ -250,8 +257,10 @@ int kvm_arch_insert_sw_breakpoint(CPUS390XState *env, struct kvm_sw_breakpoint * return 0; } -int kvm_arch_remove_sw_breakpoint(CPUS390XState *env, struct kvm_sw_breakpoint *bp) +int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) { + S390CPU *cpu = S390_CPU(cs); + CPUS390XState *env = &cpu->env; uint8_t t[4]; static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01}; @@ -266,17 +275,18 @@ int kvm_arch_remove_sw_breakpoint(CPUS390XState *env, struct kvm_sw_breakpoint * return 0; } -void kvm_arch_pre_run(CPUS390XState *env, struct kvm_run *run) +void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run) { } -void kvm_arch_post_run(CPUS390XState *env, struct kvm_run *run) +void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run) { } -int kvm_arch_process_async_events(CPUS390XState *env) +int kvm_arch_process_async_events(CPUState *cs) { - return env->halted; + S390CPU *cpu = S390_CPU(cs); + return cpu->env.halted; } void kvm_s390_interrupt_internal(CPUS390XState *env, int type, uint32_t parm, @@ -565,8 +575,10 @@ static int handle_intercept(CPUS390XState *env) return r; } -int kvm_arch_handle_exit(CPUS390XState *env, struct kvm_run *run) +int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) { + S390CPU *cpu = S390_CPU(cs); + CPUS390XState *env = &cpu->env; int ret = 0; switch (run->exit_reason) { @@ -587,12 +599,12 @@ int kvm_arch_handle_exit(CPUS390XState *env, struct kvm_run *run) return ret; } -bool kvm_arch_stop_on_emulation_error(CPUS390XState *env) +bool kvm_arch_stop_on_emulation_error(CPUState *cpu) { return true; } -int kvm_arch_on_sigbus_vcpu(CPUS390XState *env, int code, void *addr) +int kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr) { return 1; } From 1bc22652d62f862a5def54f939e87fdb7a5593ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 31 Oct 2012 06:06:49 +0100 Subject: [PATCH 2075/2270] kvm: Pass CPUState to kvm_vcpu_ioctl() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adapt helper functions to pass X86CPU / PowerPCCPU / S390CPU. Signed-off-by: Andreas Färber --- hw/kvm/apic.c | 10 +-- hw/kvm/clock.c | 2 +- hw/ppc.c | 2 +- hw/s390-virtio-bus.c | 12 +-- hw/spapr.c | 2 +- kvm-all.c | 14 ++-- kvm.h | 2 +- target-i386/kvm.c | 158 +++++++++++++++++++++---------------- target-ppc/kvm.c | 55 +++++++------ target-ppc/kvm_ppc.h | 8 +- target-s390x/cpu.h | 12 +-- target-s390x/interrupt.c | 3 +- target-s390x/kvm.c | 62 ++++++++------- target-s390x/misc_helper.c | 2 +- 14 files changed, 188 insertions(+), 156 deletions(-) diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c index 8b65d513db..c4d74ee1aa 100644 --- a/hw/kvm/apic.c +++ b/hw/kvm/apic.c @@ -104,7 +104,7 @@ static void kvm_apic_enable_tpr_reporting(APICCommonState *s, bool enable) .enabled = enable }; - kvm_vcpu_ioctl(&s->cpu->env, KVM_TPR_ACCESS_REPORTING, &ctl); + kvm_vcpu_ioctl(CPU(s->cpu), KVM_TPR_ACCESS_REPORTING, &ctl); } static void kvm_apic_vapic_base_update(APICCommonState *s) @@ -114,7 +114,7 @@ static void kvm_apic_vapic_base_update(APICCommonState *s) }; int ret; - ret = kvm_vcpu_ioctl(&s->cpu->env, KVM_SET_VAPIC_ADDR, &vapid_addr); + ret = kvm_vcpu_ioctl(CPU(s->cpu), KVM_SET_VAPIC_ADDR, &vapid_addr); if (ret < 0) { fprintf(stderr, "KVM: setting VAPIC address failed (%s)\n", strerror(-ret)); @@ -125,15 +125,15 @@ static void kvm_apic_vapic_base_update(APICCommonState *s) static void do_inject_external_nmi(void *data) { APICCommonState *s = data; - CPUX86State *env = &s->cpu->env; + CPUState *cpu = CPU(s->cpu); uint32_t lvt; int ret; - cpu_synchronize_state(env); + cpu_synchronize_state(&s->cpu->env); lvt = s->lvt[APIC_LVT_LINT1]; if (!(lvt & APIC_LVT_MASKED) && ((lvt >> 8) & 7) == APIC_DM_NMI) { - ret = kvm_vcpu_ioctl(env, KVM_NMI); + ret = kvm_vcpu_ioctl(cpu, KVM_NMI); if (ret < 0) { fprintf(stderr, "KVM: injection failed, NMI lost (%s)\n", strerror(-ret)); diff --git a/hw/kvm/clock.c b/hw/kvm/clock.c index 824b978397..4cf62f696a 100644 --- a/hw/kvm/clock.c +++ b/hw/kvm/clock.c @@ -76,7 +76,7 @@ static void kvmclock_vm_state_change(void *opaque, int running, return; } for (penv = first_cpu; penv != NULL; penv = penv->next_cpu) { - ret = kvm_vcpu_ioctl(penv, KVM_KVMCLOCK_CTRL, 0); + ret = kvm_vcpu_ioctl(ENV_GET_CPU(penv), KVM_KVMCLOCK_CTRL, 0); if (ret) { if (ret != -EINVAL) { fprintf(stderr, "%s: %s\n", __func__, strerror(-ret)); diff --git a/hw/ppc.c b/hw/ppc.c index 11fd199eaa..e99a93db96 100644 --- a/hw/ppc.c +++ b/hw/ppc.c @@ -65,7 +65,7 @@ void ppc_set_irq(CPUPPCState *env, int n_IRQ, int level) if (old_pending != env->pending_interrupts) { #ifdef CONFIG_KVM - kvmppc_set_interrupt(env, n_IRQ, level); + kvmppc_set_interrupt(ppc_env_get_cpu(env), n_IRQ, level); #endif } diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index e0ac2d1ec2..716028d3a2 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -111,10 +111,12 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size) return bus; } -static void s390_virtio_irq(CPUS390XState *env, int config_change, uint64_t token) +static void s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token) { + CPUS390XState *env = &cpu->env; + if (kvm_enabled()) { - kvm_s390_virtio_irq(env, config_change, token); + kvm_s390_virtio_irq(cpu, config_change, token); } else { cpu_inject_ext(env, VIRTIO_EXT_CODE, config_change, token); } @@ -143,8 +145,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev) s390_virtio_reset_idx(dev); if (dev->qdev.hotplugged) { S390CPU *cpu = s390_cpu_addr2state(0); - CPUS390XState *env = &cpu->env; - s390_virtio_irq(env, VIRTIO_PARAM_DEV_ADD, dev->dev_offs); + s390_virtio_irq(cpu, VIRTIO_PARAM_DEV_ADD, dev->dev_offs); } return 0; @@ -369,9 +370,8 @@ static void virtio_s390_notify(void *opaque, uint16_t vector) VirtIOS390Device *dev = (VirtIOS390Device*)opaque; uint64_t token = s390_virtio_device_vq_token(dev, vector); S390CPU *cpu = s390_cpu_addr2state(0); - CPUS390XState *env = &cpu->env; - s390_virtio_irq(env, 0, token); + s390_virtio_irq(cpu, 0, token); } static unsigned virtio_s390_get_features(void *opaque) diff --git a/hw/spapr.c b/hw/spapr.c index 504d0fca5e..341f0b91ca 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -797,7 +797,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args) /* Tell KVM that we're in PAPR mode */ if (kvm_enabled()) { - kvmppc_set_papr(env); + kvmppc_set_papr(cpu); } qemu_register_reset(spapr_cpu_reset, cpu); diff --git a/kvm-all.c b/kvm-all.c index 792cdf1d66..5f1d1fed2c 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1557,7 +1557,7 @@ int kvm_cpu_exec(CPUArchState *env) } qemu_mutex_unlock_iothread(); - run_ret = kvm_vcpu_ioctl(env, KVM_RUN, 0); + run_ret = kvm_vcpu_ioctl(cpu, KVM_RUN, 0); qemu_mutex_lock_iothread(); kvm_arch_post_run(cpu, run); @@ -1658,9 +1658,8 @@ int kvm_vm_ioctl(KVMState *s, int type, ...) return ret; } -int kvm_vcpu_ioctl(CPUArchState *env, int type, ...) +int kvm_vcpu_ioctl(CPUState *cpu, int type, ...) { - CPUState *cpu = ENV_GET_CPU(env); int ret; void *arg; va_list ap; @@ -1791,9 +1790,9 @@ struct kvm_set_guest_debug_data { static void kvm_invoke_set_guest_debug(void *data) { struct kvm_set_guest_debug_data *dbg_data = data; - CPUArchState *env = dbg_data->env; + CPUState *cpu = ENV_GET_CPU(dbg_data->env); - dbg_data->err = kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &dbg_data->dbg); + dbg_data->err = kvm_vcpu_ioctl(cpu, KVM_SET_GUEST_DEBUG, &dbg_data->dbg); } int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap) @@ -1955,18 +1954,19 @@ void kvm_remove_all_breakpoints(CPUArchState *current_env) int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset) { + CPUState *cpu = ENV_GET_CPU(env); struct kvm_signal_mask *sigmask; int r; if (!sigset) { - return kvm_vcpu_ioctl(env, KVM_SET_SIGNAL_MASK, NULL); + return kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, NULL); } sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset)); sigmask->len = 8; memcpy(sigmask->sigset, sigset, sizeof(*sigset)); - r = kvm_vcpu_ioctl(env, KVM_SET_SIGNAL_MASK, sigmask); + r = kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, sigmask); g_free(sigmask); return r; diff --git a/kvm.h b/kvm.h index 61f00b7456..a2375ff469 100644 --- a/kvm.h +++ b/kvm.h @@ -152,7 +152,7 @@ int kvm_ioctl(KVMState *s, int type, ...); int kvm_vm_ioctl(KVMState *s, int type, ...); -int kvm_vcpu_ioctl(CPUArchState *env, int type, ...); +int kvm_vcpu_ioctl(CPUState *cpu, int type, ...); /* Arch specific hooks */ diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 80cacf3764..b2efa1e928 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -368,8 +368,10 @@ int kvm_arch_on_sigbus(int code, void *addr) return 0; } -static int kvm_inject_mce_oldstyle(CPUX86State *env) +static int kvm_inject_mce_oldstyle(X86CPU *cpu) { + CPUX86State *env = &cpu->env; + if (!kvm_has_vcpu_events() && env->exception_injected == EXCP12_MCHK) { unsigned int bank, bank_num = env->mcg_cap & 0xff; struct kvm_x86_mce mce; @@ -393,7 +395,7 @@ static int kvm_inject_mce_oldstyle(CPUX86State *env) mce.addr = env->mce_banks[bank * 4 + 2]; mce.misc = env->mce_banks[bank * 4 + 3]; - return kvm_vcpu_ioctl(env, KVM_X86_SET_MCE, &mce); + return kvm_vcpu_ioctl(CPU(cpu), KVM_X86_SET_MCE, &mce); } return 0; } @@ -593,7 +595,7 @@ int kvm_arch_init_vcpu(CPUState *cs) } mcg_cap &= MCE_CAP_DEF; mcg_cap |= banks; - ret = kvm_vcpu_ioctl(env, KVM_X86_SETUP_MCE, &mcg_cap); + ret = kvm_vcpu_ioctl(cs, KVM_X86_SETUP_MCE, &mcg_cap); if (ret < 0) { fprintf(stderr, "KVM_X86_SETUP_MCE: %s", strerror(-ret)); return ret; @@ -605,14 +607,14 @@ int kvm_arch_init_vcpu(CPUState *cs) qemu_add_vm_change_state_handler(cpu_update_state, env); cpuid_data.cpuid.padding = 0; - r = kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data); + r = kvm_vcpu_ioctl(cs, KVM_SET_CPUID2, &cpuid_data); if (r) { return r; } r = kvm_check_extension(env->kvm_state, KVM_CAP_TSC_CONTROL); if (r && env->tsc_khz) { - r = kvm_vcpu_ioctl(env, KVM_SET_TSC_KHZ, env->tsc_khz); + r = kvm_vcpu_ioctl(cs, KVM_SET_TSC_KHZ, env->tsc_khz); if (r < 0) { fprintf(stderr, "KVM_SET_TSC_KHZ failed\n"); return r; @@ -820,13 +822,14 @@ static void kvm_getput_reg(__u64 *kvm_reg, target_ulong *qemu_reg, int set) } } -static int kvm_getput_regs(CPUX86State *env, int set) +static int kvm_getput_regs(X86CPU *cpu, int set) { + CPUX86State *env = &cpu->env; struct kvm_regs regs; int ret = 0; if (!set) { - ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_REGS, ®s); if (ret < 0) { return ret; } @@ -855,14 +858,15 @@ static int kvm_getput_regs(CPUX86State *env, int set) kvm_getput_reg(®s.rip, &env->eip, set); if (set) { - ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s); + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_REGS, ®s); } return ret; } -static int kvm_put_fpu(CPUX86State *env) +static int kvm_put_fpu(X86CPU *cpu) { + CPUX86State *env = &cpu->env; struct kvm_fpu fpu; int i; @@ -880,7 +884,7 @@ static int kvm_put_fpu(CPUX86State *env) memcpy(fpu.xmm, env->xmm_regs, sizeof env->xmm_regs); fpu.mxcsr = env->mxcsr; - return kvm_vcpu_ioctl(env, KVM_SET_FPU, &fpu); + return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_FPU, &fpu); } #define XSAVE_FCW_FSW 0 @@ -893,14 +897,15 @@ static int kvm_put_fpu(CPUX86State *env) #define XSAVE_XSTATE_BV 128 #define XSAVE_YMMH_SPACE 144 -static int kvm_put_xsave(CPUX86State *env) +static int kvm_put_xsave(X86CPU *cpu) { + CPUX86State *env = &cpu->env; struct kvm_xsave* xsave = env->kvm_xsave_buf; uint16_t cwd, swd, twd; int i, r; if (!kvm_has_xsave()) { - return kvm_put_fpu(env); + return kvm_put_fpu(cpu); } memset(xsave, 0, sizeof(struct kvm_xsave)); @@ -923,12 +928,13 @@ static int kvm_put_xsave(CPUX86State *env) *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV] = env->xstate_bv; memcpy(&xsave->region[XSAVE_YMMH_SPACE], env->ymmh_regs, sizeof env->ymmh_regs); - r = kvm_vcpu_ioctl(env, KVM_SET_XSAVE, xsave); + r = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XSAVE, xsave); return r; } -static int kvm_put_xcrs(CPUX86State *env) +static int kvm_put_xcrs(X86CPU *cpu) { + CPUX86State *env = &cpu->env; struct kvm_xcrs xcrs; if (!kvm_has_xcrs()) { @@ -939,11 +945,12 @@ static int kvm_put_xcrs(CPUX86State *env) xcrs.flags = 0; xcrs.xcrs[0].xcr = 0; xcrs.xcrs[0].value = env->xcr0; - return kvm_vcpu_ioctl(env, KVM_SET_XCRS, &xcrs); + return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XCRS, &xcrs); } -static int kvm_put_sregs(CPUX86State *env) +static int kvm_put_sregs(X86CPU *cpu) { + CPUX86State *env = &cpu->env; struct kvm_sregs sregs; memset(sregs.interrupt_bitmap, 0, sizeof(sregs.interrupt_bitmap)); @@ -988,7 +995,7 @@ static int kvm_put_sregs(CPUX86State *env) sregs.efer = env->efer; - return kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs); + return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_SREGS, &sregs); } static void kvm_msr_entry_set(struct kvm_msr_entry *entry, @@ -998,8 +1005,9 @@ static void kvm_msr_entry_set(struct kvm_msr_entry *entry, entry->data = value; } -static int kvm_put_msrs(CPUX86State *env, int level) +static int kvm_put_msrs(X86CPU *cpu, int level) { + CPUX86State *env = &cpu->env; struct { struct kvm_msrs info; struct kvm_msr_entry entries[100]; @@ -1080,17 +1088,18 @@ static int kvm_put_msrs(CPUX86State *env, int level) msr_data.info.nmsrs = n; - return kvm_vcpu_ioctl(env, KVM_SET_MSRS, &msr_data); + return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, &msr_data); } -static int kvm_get_fpu(CPUX86State *env) +static int kvm_get_fpu(X86CPU *cpu) { + CPUX86State *env = &cpu->env; struct kvm_fpu fpu; int i, ret; - ret = kvm_vcpu_ioctl(env, KVM_GET_FPU, &fpu); + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_FPU, &fpu); if (ret < 0) { return ret; } @@ -1111,17 +1120,18 @@ static int kvm_get_fpu(CPUX86State *env) return 0; } -static int kvm_get_xsave(CPUX86State *env) +static int kvm_get_xsave(X86CPU *cpu) { + CPUX86State *env = &cpu->env; struct kvm_xsave* xsave = env->kvm_xsave_buf; int ret, i; uint16_t cwd, swd, twd; if (!kvm_has_xsave()) { - return kvm_get_fpu(env); + return kvm_get_fpu(cpu); } - ret = kvm_vcpu_ioctl(env, KVM_GET_XSAVE, xsave); + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_XSAVE, xsave); if (ret < 0) { return ret; } @@ -1149,8 +1159,9 @@ static int kvm_get_xsave(CPUX86State *env) return 0; } -static int kvm_get_xcrs(CPUX86State *env) +static int kvm_get_xcrs(X86CPU *cpu) { + CPUX86State *env = &cpu->env; int i, ret; struct kvm_xcrs xcrs; @@ -1158,7 +1169,7 @@ static int kvm_get_xcrs(CPUX86State *env) return 0; } - ret = kvm_vcpu_ioctl(env, KVM_GET_XCRS, &xcrs); + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_XCRS, &xcrs); if (ret < 0) { return ret; } @@ -1173,13 +1184,14 @@ static int kvm_get_xcrs(CPUX86State *env) return 0; } -static int kvm_get_sregs(CPUX86State *env) +static int kvm_get_sregs(X86CPU *cpu) { + CPUX86State *env = &cpu->env; struct kvm_sregs sregs; uint32_t hflags; int bit, i, ret; - ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs); + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS, &sregs); if (ret < 0) { return ret; } @@ -1257,8 +1269,9 @@ static int kvm_get_sregs(CPUX86State *env) return 0; } -static int kvm_get_msrs(CPUX86State *env) +static int kvm_get_msrs(X86CPU *cpu) { + CPUX86State *env = &cpu->env; struct { struct kvm_msrs info; struct kvm_msr_entry entries[100]; @@ -1315,7 +1328,7 @@ static int kvm_get_msrs(CPUX86State *env) } msr_data.info.nmsrs = n; - ret = kvm_vcpu_ioctl(env, KVM_GET_MSRS, &msr_data); + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data); if (ret < 0) { return ret; } @@ -1393,11 +1406,11 @@ static int kvm_get_msrs(CPUX86State *env) return 0; } -static int kvm_put_mp_state(CPUX86State *env) +static int kvm_put_mp_state(X86CPU *cpu) { - struct kvm_mp_state mp_state = { .mp_state = env->mp_state }; + struct kvm_mp_state mp_state = { .mp_state = cpu->env.mp_state }; - return kvm_vcpu_ioctl(env, KVM_SET_MP_STATE, &mp_state); + return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MP_STATE, &mp_state); } static int kvm_get_mp_state(X86CPU *cpu) @@ -1406,7 +1419,7 @@ static int kvm_get_mp_state(X86CPU *cpu) struct kvm_mp_state mp_state; int ret; - ret = kvm_vcpu_ioctl(env, KVM_GET_MP_STATE, &mp_state); + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MP_STATE, &mp_state); if (ret < 0) { return ret; } @@ -1417,14 +1430,15 @@ static int kvm_get_mp_state(X86CPU *cpu) return 0; } -static int kvm_get_apic(CPUX86State *env) +static int kvm_get_apic(X86CPU *cpu) { + CPUX86State *env = &cpu->env; DeviceState *apic = env->apic_state; struct kvm_lapic_state kapic; int ret; if (apic && kvm_irqchip_in_kernel()) { - ret = kvm_vcpu_ioctl(env, KVM_GET_LAPIC, &kapic); + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_LAPIC, &kapic); if (ret < 0) { return ret; } @@ -1434,21 +1448,23 @@ static int kvm_get_apic(CPUX86State *env) return 0; } -static int kvm_put_apic(CPUX86State *env) +static int kvm_put_apic(X86CPU *cpu) { + CPUX86State *env = &cpu->env; DeviceState *apic = env->apic_state; struct kvm_lapic_state kapic; if (apic && kvm_irqchip_in_kernel()) { kvm_put_apic_state(apic, &kapic); - return kvm_vcpu_ioctl(env, KVM_SET_LAPIC, &kapic); + return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_LAPIC, &kapic); } return 0; } -static int kvm_put_vcpu_events(CPUX86State *env, int level) +static int kvm_put_vcpu_events(X86CPU *cpu, int level) { + CPUX86State *env = &cpu->env; struct kvm_vcpu_events events; if (!kvm_has_vcpu_events()) { @@ -1478,11 +1494,12 @@ static int kvm_put_vcpu_events(CPUX86State *env, int level) KVM_VCPUEVENT_VALID_NMI_PENDING | KVM_VCPUEVENT_VALID_SIPI_VECTOR; } - return kvm_vcpu_ioctl(env, KVM_SET_VCPU_EVENTS, &events); + return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_VCPU_EVENTS, &events); } -static int kvm_get_vcpu_events(CPUX86State *env) +static int kvm_get_vcpu_events(X86CPU *cpu) { + CPUX86State *env = &cpu->env; struct kvm_vcpu_events events; int ret; @@ -1490,7 +1507,7 @@ static int kvm_get_vcpu_events(CPUX86State *env) return 0; } - ret = kvm_vcpu_ioctl(env, KVM_GET_VCPU_EVENTS, &events); + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_VCPU_EVENTS, &events); if (ret < 0) { return ret; } @@ -1516,8 +1533,9 @@ static int kvm_get_vcpu_events(CPUX86State *env) return 0; } -static int kvm_guest_debug_workarounds(CPUX86State *env) +static int kvm_guest_debug_workarounds(X86CPU *cpu) { + CPUX86State *env = &cpu->env; int ret = 0; unsigned long reinject_trap = 0; @@ -1545,8 +1563,9 @@ static int kvm_guest_debug_workarounds(CPUX86State *env) return ret; } -static int kvm_put_debugregs(CPUX86State *env) +static int kvm_put_debugregs(X86CPU *cpu) { + CPUX86State *env = &cpu->env; struct kvm_debugregs dbgregs; int i; @@ -1561,11 +1580,12 @@ static int kvm_put_debugregs(CPUX86State *env) dbgregs.dr7 = env->dr[7]; dbgregs.flags = 0; - return kvm_vcpu_ioctl(env, KVM_SET_DEBUGREGS, &dbgregs); + return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_DEBUGREGS, &dbgregs); } -static int kvm_get_debugregs(CPUX86State *env) +static int kvm_get_debugregs(X86CPU *cpu) { + CPUX86State *env = &cpu->env; struct kvm_debugregs dbgregs; int i, ret; @@ -1573,7 +1593,7 @@ static int kvm_get_debugregs(CPUX86State *env) return 0; } - ret = kvm_vcpu_ioctl(env, KVM_GET_DEBUGREGS, &dbgregs); + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_DEBUGREGS, &dbgregs); if (ret < 0) { return ret; } @@ -1589,56 +1609,55 @@ static int kvm_get_debugregs(CPUX86State *env) int kvm_arch_put_registers(CPUState *cpu, int level) { X86CPU *x86_cpu = X86_CPU(cpu); - CPUX86State *env = &x86_cpu->env; int ret; assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); - ret = kvm_getput_regs(env, 1); + ret = kvm_getput_regs(x86_cpu, 1); if (ret < 0) { return ret; } - ret = kvm_put_xsave(env); + ret = kvm_put_xsave(x86_cpu); if (ret < 0) { return ret; } - ret = kvm_put_xcrs(env); + ret = kvm_put_xcrs(x86_cpu); if (ret < 0) { return ret; } - ret = kvm_put_sregs(env); + ret = kvm_put_sregs(x86_cpu); if (ret < 0) { return ret; } /* must be before kvm_put_msrs */ - ret = kvm_inject_mce_oldstyle(env); + ret = kvm_inject_mce_oldstyle(x86_cpu); if (ret < 0) { return ret; } - ret = kvm_put_msrs(env, level); + ret = kvm_put_msrs(x86_cpu, level); if (ret < 0) { return ret; } if (level >= KVM_PUT_RESET_STATE) { - ret = kvm_put_mp_state(env); + ret = kvm_put_mp_state(x86_cpu); if (ret < 0) { return ret; } - ret = kvm_put_apic(env); + ret = kvm_put_apic(x86_cpu); if (ret < 0) { return ret; } } - ret = kvm_put_vcpu_events(env, level); + ret = kvm_put_vcpu_events(x86_cpu, level); if (ret < 0) { return ret; } - ret = kvm_put_debugregs(env); + ret = kvm_put_debugregs(x86_cpu); if (ret < 0) { return ret; } /* must be last */ - ret = kvm_guest_debug_workarounds(env); + ret = kvm_guest_debug_workarounds(x86_cpu); if (ret < 0) { return ret; } @@ -1648,28 +1667,27 @@ int kvm_arch_put_registers(CPUState *cpu, int level) int kvm_arch_get_registers(CPUState *cs) { X86CPU *cpu = X86_CPU(cs); - CPUX86State *env = &cpu->env; int ret; assert(cpu_is_stopped(cs) || qemu_cpu_is_self(cs)); - ret = kvm_getput_regs(env, 0); + ret = kvm_getput_regs(cpu, 0); if (ret < 0) { return ret; } - ret = kvm_get_xsave(env); + ret = kvm_get_xsave(cpu); if (ret < 0) { return ret; } - ret = kvm_get_xcrs(env); + ret = kvm_get_xcrs(cpu); if (ret < 0) { return ret; } - ret = kvm_get_sregs(env); + ret = kvm_get_sregs(cpu); if (ret < 0) { return ret; } - ret = kvm_get_msrs(env); + ret = kvm_get_msrs(cpu); if (ret < 0) { return ret; } @@ -1677,15 +1695,15 @@ int kvm_arch_get_registers(CPUState *cs) if (ret < 0) { return ret; } - ret = kvm_get_apic(env); + ret = kvm_get_apic(cpu); if (ret < 0) { return ret; } - ret = kvm_get_vcpu_events(env); + ret = kvm_get_vcpu_events(cpu); if (ret < 0) { return ret; } - ret = kvm_get_debugregs(env); + ret = kvm_get_debugregs(cpu); if (ret < 0) { return ret; } @@ -1702,7 +1720,7 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run) if (env->interrupt_request & CPU_INTERRUPT_NMI) { env->interrupt_request &= ~CPU_INTERRUPT_NMI; DPRINTF("injected NMI\n"); - ret = kvm_vcpu_ioctl(env, KVM_NMI); + ret = kvm_vcpu_ioctl(cpu, KVM_NMI); if (ret < 0) { fprintf(stderr, "KVM: injection failed, NMI lost (%s)\n", strerror(-ret)); @@ -1730,7 +1748,7 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run) intr.irq = irq; DPRINTF("injected interrupt %d\n", irq); - ret = kvm_vcpu_ioctl(env, KVM_INTERRUPT, &intr); + ret = kvm_vcpu_ioctl(cpu, KVM_INTERRUPT, &intr); if (ret < 0) { fprintf(stderr, "KVM: injection failed, interrupt lost (%s)\n", diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 8a59b706da..ad5bc66396 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -99,8 +99,10 @@ int kvm_arch_init(KVMState *s) return 0; } -static int kvm_arch_sync_sregs(CPUPPCState *cenv) +static int kvm_arch_sync_sregs(PowerPCCPU *cpu) { + CPUPPCState *cenv = &cpu->env; + CPUState *cs = CPU(cpu); struct kvm_sregs sregs; int ret; @@ -117,18 +119,20 @@ static int kvm_arch_sync_sregs(CPUPPCState *cenv) } } - ret = kvm_vcpu_ioctl(cenv, KVM_GET_SREGS, &sregs); + ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs); if (ret) { return ret; } sregs.pvr = cenv->spr[SPR_PVR]; - return kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs); + return kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs); } /* Set up a shared TLB array with KVM */ -static int kvm_booke206_tlb_init(CPUPPCState *env) +static int kvm_booke206_tlb_init(PowerPCCPU *cpu) { + CPUPPCState *env = &cpu->env; + CPUState *cs = CPU(cpu); struct kvm_book3e_206_tlb_params params = {}; struct kvm_config_tlb cfg = {}; struct kvm_enable_cap encap = {}; @@ -161,7 +165,7 @@ static int kvm_booke206_tlb_init(CPUPPCState *env) encap.cap = KVM_CAP_SW_TLB; encap.args[0] = (uintptr_t)&cfg; - ret = kvm_vcpu_ioctl(env, KVM_ENABLE_CAP, &encap); + ret = kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap); if (ret < 0) { fprintf(stderr, "%s: couldn't enable KVM_CAP_SW_TLB: %s\n", __func__, strerror(-ret)); @@ -385,7 +389,7 @@ int kvm_arch_init_vcpu(CPUState *cs) kvm_fixup_page_sizes(cenv); /* Synchronize sregs with kvm */ - ret = kvm_arch_sync_sregs(cenv); + ret = kvm_arch_sync_sregs(cpu); if (ret) { return ret; } @@ -395,7 +399,7 @@ int kvm_arch_init_vcpu(CPUState *cs) /* Some targets support access to KVM's guest TLB. */ switch (cenv->mmu_model) { case POWERPC_MMU_BOOKE206: - ret = kvm_booke206_tlb_init(cenv); + ret = kvm_booke206_tlb_init(cpu); break; default: break; @@ -408,8 +412,10 @@ void kvm_arch_reset_vcpu(CPUState *cpu) { } -static void kvm_sw_tlb_put(CPUPPCState *env) +static void kvm_sw_tlb_put(PowerPCCPU *cpu) { + CPUPPCState *env = &cpu->env; + CPUState *cs = CPU(cpu); struct kvm_dirty_tlb dirty_tlb; unsigned char *bitmap; int ret; @@ -424,7 +430,7 @@ static void kvm_sw_tlb_put(CPUPPCState *env) dirty_tlb.bitmap = (uintptr_t)bitmap; dirty_tlb.num_dirty = env->nb_tlb; - ret = kvm_vcpu_ioctl(env, KVM_DIRTY_TLB, &dirty_tlb); + ret = kvm_vcpu_ioctl(cs, KVM_DIRTY_TLB, &dirty_tlb); if (ret) { fprintf(stderr, "%s: KVM_DIRTY_TLB: %s\n", __func__, strerror(-ret)); @@ -441,9 +447,10 @@ int kvm_arch_put_registers(CPUState *cs, int level) int ret; int i; - ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); - if (ret < 0) + ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); + if (ret < 0) { return ret; + } regs.ctr = env->ctr; regs.lr = env->lr; @@ -468,12 +475,12 @@ int kvm_arch_put_registers(CPUState *cs, int level) for (i = 0;i < 32; i++) regs.gpr[i] = env->gpr[i]; - ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s); + ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); if (ret < 0) return ret; if (env->tlb_dirty) { - kvm_sw_tlb_put(env); + kvm_sw_tlb_put(cpu); env->tlb_dirty = false; } @@ -506,7 +513,7 @@ int kvm_arch_put_registers(CPUState *cs, int level) | env->IBAT[1][i]; } - ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs); + ret = kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs); if (ret) { return ret; } @@ -519,7 +526,7 @@ int kvm_arch_put_registers(CPUState *cs, int level) .addr = (uintptr_t) &hior, }; - ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, ®); + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); if (ret) { return ret; } @@ -537,7 +544,7 @@ int kvm_arch_get_registers(CPUState *cs) uint32_t cr; int i, ret; - ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); + ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); if (ret < 0) return ret; @@ -571,7 +578,7 @@ int kvm_arch_get_registers(CPUState *cs) env->gpr[i] = regs.gpr[i]; if (cap_booke_sregs) { - ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs); + ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs); if (ret < 0) { return ret; } @@ -675,7 +682,7 @@ int kvm_arch_get_registers(CPUState *cs) } if (cap_segstate) { - ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs); + ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs); if (ret < 0) { return ret; } @@ -707,7 +714,7 @@ int kvm_arch_get_registers(CPUState *cs) return 0; } -int kvmppc_set_interrupt(CPUPPCState *env, int irq, int level) +int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level) { unsigned virq = level ? KVM_INTERRUPT_SET_LEVEL : KVM_INTERRUPT_UNSET; @@ -719,7 +726,7 @@ int kvmppc_set_interrupt(CPUPPCState *env, int irq, int level) return 0; } - kvm_vcpu_ioctl(env, KVM_INTERRUPT, &virq); + kvm_vcpu_ioctl(CPU(cpu), KVM_INTERRUPT, &virq); return 0; } @@ -753,7 +760,7 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) irq = KVM_INTERRUPT_SET; dprintf("injected interrupt %d\n", irq); - r = kvm_vcpu_ioctl(env, KVM_INTERRUPT, &irq); + r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &irq); if (r < 0) printf("cpu %d fail inject %x\n", env->cpu_index, irq); @@ -1007,13 +1014,15 @@ int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len) return 0; } -void kvmppc_set_papr(CPUPPCState *env) +void kvmppc_set_papr(PowerPCCPU *cpu) { + CPUPPCState *env = &cpu->env; + CPUState *cs = CPU(cpu); struct kvm_enable_cap cap = {}; int ret; cap.cap = KVM_CAP_PPC_PAPR; - ret = kvm_vcpu_ioctl(env, KVM_ENABLE_CAP, &cap); + ret = kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &cap); if (ret) { cpu_abort(env, "This KVM version does not support PAPR\n"); diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h index baad6eb75b..369c7fe12c 100644 --- a/target-ppc/kvm_ppc.h +++ b/target-ppc/kvm_ppc.h @@ -20,8 +20,8 @@ uint64_t kvmppc_get_clockfreq(void); uint32_t kvmppc_get_vmx(void); uint32_t kvmppc_get_dfp(void); int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len); -int kvmppc_set_interrupt(CPUPPCState *env, int irq, int level); -void kvmppc_set_papr(CPUPPCState *env); +int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level); +void kvmppc_set_papr(PowerPCCPU *cpu); int kvmppc_smt_threads(void); #ifndef CONFIG_USER_ONLY off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem); @@ -65,12 +65,12 @@ static inline int kvmppc_read_segment_page_sizes(uint32_t *prop, int maxcells) return -1; } -static inline int kvmppc_set_interrupt(CPUPPCState *env, int irq, int level) +static inline int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level) { return -1; } -static inline void kvmppc_set_papr(CPUPPCState *env) +static inline void kvmppc_set_papr(PowerPCCPU *cpu) { } diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 0f9a1f7340..7e7e3b7199 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -296,21 +296,21 @@ void s390x_cpu_timer(void *opaque); int s390_virtio_hypercall(CPUS390XState *env, uint64_t mem, uint64_t hypercall); #ifdef CONFIG_KVM -void kvm_s390_interrupt(CPUS390XState *env, int type, uint32_t code); -void kvm_s390_virtio_irq(CPUS390XState *env, int config_change, uint64_t token); -void kvm_s390_interrupt_internal(CPUS390XState *env, int type, uint32_t parm, +void kvm_s390_interrupt(S390CPU *cpu, int type, uint32_t code); +void kvm_s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token); +void kvm_s390_interrupt_internal(S390CPU *cpu, int type, uint32_t parm, uint64_t parm64, int vm); #else -static inline void kvm_s390_interrupt(CPUS390XState *env, int type, uint32_t code) +static inline void kvm_s390_interrupt(S390CPU *cpu, int type, uint32_t code) { } -static inline void kvm_s390_virtio_irq(CPUS390XState *env, int config_change, +static inline void kvm_s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token) { } -static inline void kvm_s390_interrupt_internal(CPUS390XState *env, int type, +static inline void kvm_s390_interrupt_internal(S390CPU *cpu, int type, uint32_t parm, uint64_t parm64, int vm) { diff --git a/target-s390x/interrupt.c b/target-s390x/interrupt.c index c1b034f775..97487bd631 100644 --- a/target-s390x/interrupt.c +++ b/target-s390x/interrupt.c @@ -19,7 +19,8 @@ void s390_sclp_extint(uint32_t parm) if (kvm_enabled()) { #ifdef CONFIG_KVM - kvm_s390_interrupt_internal(env, KVM_S390_INT_SERVICE, parm, 0, 1); + kvm_s390_interrupt_internal(dummy_cpu, KVM_S390_INT_SERVICE, parm, + 0, 1); #endif } else { env->psw.addr += 4; diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index d4e6ab2db8..5422678330 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -74,10 +74,9 @@ int kvm_arch_init(KVMState *s) int kvm_arch_init_vcpu(CPUState *cpu) { - CPUS390XState *env = &S390_CPU(cpu)->env; int ret = 0; - if (kvm_vcpu_ioctl(env, KVM_S390_INITIAL_RESET, NULL) < 0) { + if (kvm_vcpu_ioctl(cpu, KVM_S390_INITIAL_RESET, NULL) < 0) { perror("cannot init reset vcpu"); } @@ -111,7 +110,7 @@ int kvm_arch_put_registers(CPUState *cs, int level) for (i = 0; i < 16; i++) { regs.gprs[i] = env->regs[i]; } - ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s); + ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); if (ret < 0) { return ret; } @@ -136,7 +135,7 @@ int kvm_arch_put_registers(CPUState *cs, int level) sregs.acrs[i] = env->aregs[i]; sregs.crs[i] = env->cregs[i]; } - ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs); + ret = kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs); if (ret < 0) { return ret; } @@ -171,7 +170,7 @@ int kvm_arch_get_registers(CPUState *cs) env->regs[i] = env->kvm_run->s.regs.gprs[i]; } } else { - ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); + ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); if (ret < 0) { return ret; } @@ -189,7 +188,7 @@ int kvm_arch_get_registers(CPUState *cs) env->cregs[i] = env->kvm_run->s.regs.crs[i]; } } else { - ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs); + ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs); if (ret < 0) { return ret; } @@ -289,9 +288,11 @@ int kvm_arch_process_async_events(CPUState *cs) return cpu->env.halted; } -void kvm_s390_interrupt_internal(CPUS390XState *env, int type, uint32_t parm, +void kvm_s390_interrupt_internal(S390CPU *cpu, int type, uint32_t parm, uint64_t parm64, int vm) { + CPUS390XState *env = &cpu->env; + CPUState *cs = CPU(cpu); struct kvm_s390_interrupt kvmint; int r; @@ -306,7 +307,7 @@ void kvm_s390_interrupt_internal(CPUS390XState *env, int type, uint32_t parm, if (vm) { r = kvm_vm_ioctl(env->kvm_state, KVM_S390_INTERRUPT, &kvmint); } else { - r = kvm_vcpu_ioctl(env, KVM_S390_INTERRUPT, &kvmint); + r = kvm_vcpu_ioctl(cs, KVM_S390_INTERRUPT, &kvmint); } if (r < 0) { @@ -315,20 +316,20 @@ void kvm_s390_interrupt_internal(CPUS390XState *env, int type, uint32_t parm, } } -void kvm_s390_virtio_irq(CPUS390XState *env, int config_change, uint64_t token) +void kvm_s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token) { - kvm_s390_interrupt_internal(env, KVM_S390_INT_VIRTIO, config_change, + kvm_s390_interrupt_internal(cpu, KVM_S390_INT_VIRTIO, config_change, token, 1); } -void kvm_s390_interrupt(CPUS390XState *env, int type, uint32_t code) +void kvm_s390_interrupt(S390CPU *cpu, int type, uint32_t code) { - kvm_s390_interrupt_internal(env, type, code, 0, 0); + kvm_s390_interrupt_internal(cpu, type, code, 0, 0); } -static void enter_pgmcheck(CPUS390XState *env, uint16_t code) +static void enter_pgmcheck(S390CPU *cpu, uint16_t code) { - kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code); + kvm_s390_interrupt(cpu, KVM_S390_PROGRAM_INT, code); } static inline void setcc(CPUS390XState *env, uint64_t cc) @@ -340,9 +341,10 @@ static inline void setcc(CPUS390XState *env, uint64_t cc) env->psw.mask |= (cc & 3) << 44; } -static int kvm_sclp_service_call(CPUS390XState *env, struct kvm_run *run, +static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run, uint16_t ipbh0) { + CPUS390XState *env = &cpu->env; uint32_t sccb; uint64_t code; int r = 0; @@ -353,14 +355,14 @@ static int kvm_sclp_service_call(CPUS390XState *env, struct kvm_run *run, r = sclp_service_call(sccb, code); if (r < 0) { - enter_pgmcheck(env, -r); + enter_pgmcheck(cpu, -r); } setcc(env, r); return 0; } -static int handle_priv(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1) +static int handle_priv(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) { int r = 0; uint16_t ipbh0 = (run->s390_sieic.ipb & 0xffff0000) >> 16; @@ -368,7 +370,7 @@ static int handle_priv(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1) dprintf("KVM: PRIV: %d\n", ipa1); switch (ipa1) { case PRIV_SCLP_CALL: - r = kvm_sclp_service_call(env, run, ipbh0); + r = kvm_sclp_service_call(cpu, run, ipbh0); break; default: dprintf("KVM: unknown PRIV: 0x%x\n", ipa1); @@ -411,7 +413,7 @@ static int s390_cpu_restart(S390CPU *cpu) { CPUS390XState *env = &cpu->env; - kvm_s390_interrupt(env, KVM_S390_RESTART, 0); + kvm_s390_interrupt(cpu, KVM_S390_RESTART, 0); s390_add_running_cpu(env); qemu_cpu_kick(CPU(cpu)); dprintf("DONE: SIGP cpu restart: %p\n", env); @@ -425,12 +427,13 @@ static int s390_store_status(CPUS390XState *env, uint32_t parameter) return -1; } -static int s390_cpu_initial_reset(CPUS390XState *env) +static int s390_cpu_initial_reset(S390CPU *cpu) { + CPUS390XState *env = &cpu->env; int i; s390_del_running_cpu(env); - if (kvm_vcpu_ioctl(env, KVM_S390_INITIAL_RESET, NULL) < 0) { + if (kvm_vcpu_ioctl(CPU(cpu), KVM_S390_INITIAL_RESET, NULL) < 0) { perror("cannot init reset vcpu"); } @@ -489,7 +492,7 @@ static int handle_sigp(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1) /* make the caller panic */ return -1; case SIGP_INITIAL_CPU_RESET: - r = s390_cpu_initial_reset(target_env); + r = s390_cpu_initial_reset(target_cpu); break; default: fprintf(stderr, "KVM: unknown SIGP: 0x%x\n", order_code); @@ -501,8 +504,9 @@ out: return 0; } -static int handle_instruction(CPUS390XState *env, struct kvm_run *run) +static int handle_instruction(S390CPU *cpu, struct kvm_run *run) { + CPUS390XState *env = &cpu->env; unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00); uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff; int ipb_code = (run->s390_sieic.ipb & 0x0fff0000) >> 16; @@ -511,7 +515,7 @@ static int handle_instruction(CPUS390XState *env, struct kvm_run *run) dprintf("handle_instruction 0x%x 0x%x\n", run->s390_sieic.ipa, run->s390_sieic.ipb); switch (ipa0) { case IPA0_PRIV: - r = handle_priv(env, run, ipa1); + r = handle_priv(cpu, run, ipa1); break; case IPA0_DIAG: r = handle_diag(env, run, ipb_code); @@ -522,7 +526,7 @@ static int handle_instruction(CPUS390XState *env, struct kvm_run *run) } if (r < 0) { - enter_pgmcheck(env, 0x0001); + enter_pgmcheck(cpu, 0x0001); } return 0; } @@ -533,8 +537,9 @@ static bool is_special_wait_psw(CPUS390XState *env) return env->kvm_run->psw_addr == 0xfffUL; } -static int handle_intercept(CPUS390XState *env) +static int handle_intercept(S390CPU *cpu) { + CPUS390XState *env = &cpu->env; struct kvm_run *run = env->kvm_run; int icpt_code = run->s390_sieic.icptcode; int r = 0; @@ -543,7 +548,7 @@ static int handle_intercept(CPUS390XState *env) (long)env->kvm_run->psw_addr); switch (icpt_code) { case ICPT_INSTRUCTION: - r = handle_instruction(env, run); + r = handle_instruction(cpu, run); break; case ICPT_WAITPSW: if (s390_del_running_cpu(env) == 0 && @@ -578,12 +583,11 @@ static int handle_intercept(CPUS390XState *env) int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) { S390CPU *cpu = S390_CPU(cs); - CPUS390XState *env = &cpu->env; int ret = 0; switch (run->exit_reason) { case KVM_EXIT_S390_SIEIC: - ret = handle_intercept(env); + ret = handle_intercept(cpu); break; case KVM_EXIT_S390_RESET: qemu_system_reset_request(); diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index 38d8f2a627..0834a1992b 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -57,7 +57,7 @@ void program_interrupt(CPUS390XState *env, uint32_t code, int ilc) if (kvm_enabled()) { #ifdef CONFIG_KVM - kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code); + kvm_s390_interrupt(s390_env_get_cpu(env), KVM_S390_PROGRAM_INT, code); #endif } else { env->int_pgm_code = code; From 7058581a26f4299e0b7e05677c64c1b5a50d0e75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sat, 1 Dec 2012 03:55:58 +0100 Subject: [PATCH 2076/2270] ppc: Pass PowerPCCPU to ppc_set_irq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adapt static caller functions. This cleans up after passing PowerPCCPU to kvmppc_set_interrupt(). Signed-off-by: Andreas Färber --- hw/ppc.c | 66 ++++++++++++++++++++++++++++++-------------------- hw/ppc.h | 2 +- hw/ppc_booke.c | 28 ++++++++++++++------- 3 files changed, 60 insertions(+), 36 deletions(-) diff --git a/hw/ppc.c b/hw/ppc.c index e99a93db96..6db595f4e6 100644 --- a/hw/ppc.c +++ b/hw/ppc.c @@ -50,8 +50,9 @@ static void cpu_ppc_tb_stop (CPUPPCState *env); static void cpu_ppc_tb_start (CPUPPCState *env); -void ppc_set_irq(CPUPPCState *env, int n_IRQ, int level) +void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level) { + CPUPPCState *env = &cpu->env; unsigned int old_pending = env->pending_interrupts; if (level) { @@ -65,7 +66,7 @@ void ppc_set_irq(CPUPPCState *env, int n_IRQ, int level) if (old_pending != env->pending_interrupts) { #ifdef CONFIG_KVM - kvmppc_set_interrupt(ppc_env_get_cpu(env), n_IRQ, level); + kvmppc_set_interrupt(cpu, n_IRQ, level); #endif } @@ -100,13 +101,13 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level) /* Level sensitive - active high */ LOG_IRQ("%s: set the external IRQ state to %d\n", __func__, level); - ppc_set_irq(env, PPC_INTERRUPT_EXT, level); + ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level); break; case PPC6xx_INPUT_SMI: /* Level sensitive - active high */ LOG_IRQ("%s: set the SMI IRQ state to %d\n", __func__, level); - ppc_set_irq(env, PPC_INTERRUPT_SMI, level); + ppc_set_irq(cpu, PPC_INTERRUPT_SMI, level); break; case PPC6xx_INPUT_MCP: /* Negative edge sensitive */ @@ -116,7 +117,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level) if (cur_level == 1 && level == 0) { LOG_IRQ("%s: raise machine check state\n", __func__); - ppc_set_irq(env, PPC_INTERRUPT_MCK, 1); + ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1); } break; case PPC6xx_INPUT_CKSTP_IN: @@ -138,7 +139,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level) case PPC6xx_INPUT_SRESET: LOG_IRQ("%s: set the RESET IRQ state to %d\n", __func__, level); - ppc_set_irq(env, PPC_INTERRUPT_RESET, level); + ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level); break; default: /* Unknown pin - do nothing */ @@ -178,13 +179,13 @@ static void ppc970_set_irq(void *opaque, int pin, int level) /* Level sensitive - active high */ LOG_IRQ("%s: set the external IRQ state to %d\n", __func__, level); - ppc_set_irq(env, PPC_INTERRUPT_EXT, level); + ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level); break; case PPC970_INPUT_THINT: /* Level sensitive - active high */ LOG_IRQ("%s: set the SMI IRQ state to %d\n", __func__, level); - ppc_set_irq(env, PPC_INTERRUPT_THERM, level); + ppc_set_irq(cpu, PPC_INTERRUPT_THERM, level); break; case PPC970_INPUT_MCP: /* Negative edge sensitive */ @@ -194,7 +195,7 @@ static void ppc970_set_irq(void *opaque, int pin, int level) if (cur_level == 1 && level == 0) { LOG_IRQ("%s: raise machine check state\n", __func__); - ppc_set_irq(env, PPC_INTERRUPT_MCK, 1); + ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1); } break; case PPC970_INPUT_CKSTP: @@ -218,7 +219,7 @@ static void ppc970_set_irq(void *opaque, int pin, int level) case PPC970_INPUT_SRESET: LOG_IRQ("%s: set the RESET IRQ state to %d\n", __func__, level); - ppc_set_irq(env, PPC_INTERRUPT_RESET, level); + ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level); break; case PPC970_INPUT_TBEN: LOG_IRQ("%s: set the TBEN state to %d\n", __func__, @@ -259,7 +260,7 @@ static void power7_set_irq(void *opaque, int pin, int level) /* Level sensitive - active high */ LOG_IRQ("%s: set the external IRQ state to %d\n", __func__, level); - ppc_set_irq(env, PPC_INTERRUPT_EXT, level); + ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level); break; default: /* Unknown pin - do nothing */ @@ -319,13 +320,13 @@ static void ppc40x_set_irq(void *opaque, int pin, int level) /* Level sensitive - active high */ LOG_IRQ("%s: set the critical IRQ state to %d\n", __func__, level); - ppc_set_irq(env, PPC_INTERRUPT_CEXT, level); + ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level); break; case PPC40x_INPUT_INT: /* Level sensitive - active high */ LOG_IRQ("%s: set the external IRQ state to %d\n", __func__, level); - ppc_set_irq(env, PPC_INTERRUPT_EXT, level); + ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level); break; case PPC40x_INPUT_HALT: /* Level sensitive - active low */ @@ -342,7 +343,7 @@ static void ppc40x_set_irq(void *opaque, int pin, int level) /* Level sensitive - active high */ LOG_IRQ("%s: set the debug pin state to %d\n", __func__, level); - ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level); + ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, level); break; default: /* Unknown pin - do nothing */ @@ -387,26 +388,26 @@ static void ppce500_set_irq(void *opaque, int pin, int level) case PPCE500_INPUT_RESET_CORE: if (level) { LOG_IRQ("%s: reset the PowerPC core\n", __func__); - ppc_set_irq(env, PPC_INTERRUPT_MCK, level); + ppc_set_irq(cpu, PPC_INTERRUPT_MCK, level); } break; case PPCE500_INPUT_CINT: /* Level sensitive - active high */ LOG_IRQ("%s: set the critical IRQ state to %d\n", __func__, level); - ppc_set_irq(env, PPC_INTERRUPT_CEXT, level); + ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level); break; case PPCE500_INPUT_INT: /* Level sensitive - active high */ LOG_IRQ("%s: set the core IRQ state to %d\n", __func__, level); - ppc_set_irq(env, PPC_INTERRUPT_EXT, level); + ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level); break; case PPCE500_INPUT_DEBUG: /* Level sensitive - active high */ LOG_IRQ("%s: set the debug pin state to %d\n", __func__, level); - ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level); + ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, level); break; default: /* Unknown pin - do nothing */ @@ -645,16 +646,20 @@ uint64_t cpu_ppc_load_purr (CPUPPCState *env) */ static inline void cpu_ppc_decr_excp(CPUPPCState *env) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); + /* Raise it */ LOG_TB("raise decrementer exception\n"); - ppc_set_irq(env, PPC_INTERRUPT_DECR, 1); + ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 1); } static inline void cpu_ppc_hdecr_excp(CPUPPCState *env) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); + /* Raise it */ LOG_TB("raise decrementer exception\n"); - ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1); + ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1); } static void __cpu_ppc_store_decr (CPUPPCState *env, uint64_t *nextp, @@ -829,12 +834,14 @@ struct ppc40x_timer_t { /* Fixed interval timer */ static void cpu_4xx_fit_cb (void *opaque) { + PowerPCCPU *cpu; CPUPPCState *env; ppc_tb_t *tb_env; ppc40x_timer_t *ppc40x_timer; uint64_t now, next; env = opaque; + cpu = ppc_env_get_cpu(env); tb_env = env->tb_env; ppc40x_timer = tb_env->opaque; now = qemu_get_clock_ns(vm_clock); @@ -860,8 +867,9 @@ static void cpu_4xx_fit_cb (void *opaque) next++; qemu_mod_timer(ppc40x_timer->fit_timer, next); env->spr[SPR_40x_TSR] |= 1 << 26; - if ((env->spr[SPR_40x_TCR] >> 23) & 0x1) - ppc_set_irq(env, PPC_INTERRUPT_FIT, 1); + if ((env->spr[SPR_40x_TCR] >> 23) & 0x1) { + ppc_set_irq(cpu, PPC_INTERRUPT_FIT, 1); + } LOG_TB("%s: ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__, (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1), env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]); @@ -897,16 +905,19 @@ static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp) static void cpu_4xx_pit_cb (void *opaque) { + PowerPCCPU *cpu; CPUPPCState *env; ppc_tb_t *tb_env; ppc40x_timer_t *ppc40x_timer; env = opaque; + cpu = ppc_env_get_cpu(env); tb_env = env->tb_env; ppc40x_timer = tb_env->opaque; env->spr[SPR_40x_TSR] |= 1 << 27; - if ((env->spr[SPR_40x_TCR] >> 26) & 0x1) - ppc_set_irq(env, ppc40x_timer->decr_excp, 1); + if ((env->spr[SPR_40x_TCR] >> 26) & 0x1) { + ppc_set_irq(cpu, ppc40x_timer->decr_excp, 1); + } start_stop_pit(env, tb_env, 1); LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " " "%016" PRIx64 "\n", __func__, @@ -919,12 +930,14 @@ static void cpu_4xx_pit_cb (void *opaque) /* Watchdog timer */ static void cpu_4xx_wdt_cb (void *opaque) { + PowerPCCPU *cpu; CPUPPCState *env; ppc_tb_t *tb_env; ppc40x_timer_t *ppc40x_timer; uint64_t now, next; env = opaque; + cpu = ppc_env_get_cpu(env); tb_env = env->tb_env; ppc40x_timer = tb_env->opaque; now = qemu_get_clock_ns(vm_clock); @@ -961,8 +974,9 @@ static void cpu_4xx_wdt_cb (void *opaque) qemu_mod_timer(ppc40x_timer->wdt_timer, next); ppc40x_timer->wdt_next = next; env->spr[SPR_40x_TSR] |= 1 << 30; - if ((env->spr[SPR_40x_TCR] >> 27) & 0x1) - ppc_set_irq(env, PPC_INTERRUPT_WDT, 1); + if ((env->spr[SPR_40x_TCR] >> 27) & 0x1) { + ppc_set_irq(cpu, PPC_INTERRUPT_WDT, 1); + } break; case 0x3: env->spr[SPR_40x_TSR] &= ~0x30000000; diff --git a/hw/ppc.h b/hw/ppc.h index 2f3ea277bc..64463ad388 100644 --- a/hw/ppc.h +++ b/hw/ppc.h @@ -1,4 +1,4 @@ -void ppc_set_irq (CPUPPCState *env, int n_IRQ, int level); +void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level); /* PowerPC hardware exceptions management helpers */ typedef void (*clk_setup_cb)(void *opaque, uint32_t freq); diff --git a/hw/ppc_booke.c b/hw/ppc_booke.c index d51e7fad67..da6bc4a283 100644 --- a/hw/ppc_booke.c +++ b/hw/ppc_booke.c @@ -71,17 +71,19 @@ struct booke_timer_t { uint32_t flags; }; -static void booke_update_irq(CPUPPCState *env) +static void booke_update_irq(PowerPCCPU *cpu) { - ppc_set_irq(env, PPC_INTERRUPT_DECR, + CPUPPCState *env = &cpu->env; + + ppc_set_irq(cpu, PPC_INTERRUPT_DECR, (env->spr[SPR_BOOKE_TSR] & TSR_DIS && env->spr[SPR_BOOKE_TCR] & TCR_DIE)); - ppc_set_irq(env, PPC_INTERRUPT_WDT, + ppc_set_irq(cpu, PPC_INTERRUPT_WDT, (env->spr[SPR_BOOKE_TSR] & TSR_WIS && env->spr[SPR_BOOKE_TCR] & TCR_WIE)); - ppc_set_irq(env, PPC_INTERRUPT_FIT, + ppc_set_irq(cpu, PPC_INTERRUPT_FIT, (env->spr[SPR_BOOKE_TSR] & TSR_FIS && env->spr[SPR_BOOKE_TCR] & TCR_FIE)); } @@ -154,9 +156,10 @@ static void booke_update_fixed_timer(CPUPPCState *env, static void booke_decr_cb(void *opaque) { CPUPPCState *env = opaque; + PowerPCCPU *cpu = ppc_env_get_cpu(env); env->spr[SPR_BOOKE_TSR] |= TSR_DIS; - booke_update_irq(env); + booke_update_irq(cpu); if (env->spr[SPR_BOOKE_TCR] & TCR_ARE) { /* Auto Reload */ @@ -166,16 +169,18 @@ static void booke_decr_cb(void *opaque) static void booke_fit_cb(void *opaque) { + PowerPCCPU *cpu; CPUPPCState *env; ppc_tb_t *tb_env; booke_timer_t *booke_timer; env = opaque; + cpu = ppc_env_get_cpu(env); tb_env = env->tb_env; booke_timer = tb_env->opaque; env->spr[SPR_BOOKE_TSR] |= TSR_FIS; - booke_update_irq(env); + booke_update_irq(cpu); booke_update_fixed_timer(env, booke_get_fit_target(env, tb_env), @@ -185,17 +190,19 @@ static void booke_fit_cb(void *opaque) static void booke_wdt_cb(void *opaque) { + PowerPCCPU *cpu; CPUPPCState *env; ppc_tb_t *tb_env; booke_timer_t *booke_timer; env = opaque; + cpu = ppc_env_get_cpu(env); tb_env = env->tb_env; booke_timer = tb_env->opaque; /* TODO: There's lots of complicated stuff to do here */ - booke_update_irq(env); + booke_update_irq(cpu); booke_update_fixed_timer(env, booke_get_wdt_target(env, tb_env), @@ -205,19 +212,22 @@ static void booke_wdt_cb(void *opaque) void store_booke_tsr(CPUPPCState *env, target_ulong val) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); + env->spr[SPR_BOOKE_TSR] &= ~val; - booke_update_irq(env); + booke_update_irq(cpu); } void store_booke_tcr(CPUPPCState *env, target_ulong val) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); ppc_tb_t *tb_env = env->tb_env; booke_timer_t *booke_timer = tb_env->opaque; tb_env = env->tb_env; env->spr[SPR_BOOKE_TCR] = val; - booke_update_irq(env); + booke_update_irq(cpu); booke_update_fixed_timer(env, booke_get_fit_target(env, tb_env), From 7e0a924734e7bfad7568bf57fec68bfecd5c2575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sat, 1 Dec 2012 04:18:02 +0100 Subject: [PATCH 2077/2270] ppc: Pass PowerPCCPU to [h]decr callbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleans up after passing PowerPCCPU to ppc_set_irq(). Signed-off-by: Andreas Färber --- hw/ppc.c | 60 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/hw/ppc.c b/hw/ppc.c index 6db595f4e6..b1b93a1e7d 100644 --- a/hw/ppc.c +++ b/hw/ppc.c @@ -644,30 +644,27 @@ uint64_t cpu_ppc_load_purr (CPUPPCState *env) /* When decrementer expires, * all we need to do is generate or queue a CPU exception */ -static inline void cpu_ppc_decr_excp(CPUPPCState *env) +static inline void cpu_ppc_decr_excp(PowerPCCPU *cpu) { - PowerPCCPU *cpu = ppc_env_get_cpu(env); - /* Raise it */ LOG_TB("raise decrementer exception\n"); ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 1); } -static inline void cpu_ppc_hdecr_excp(CPUPPCState *env) +static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu) { - PowerPCCPU *cpu = ppc_env_get_cpu(env); - /* Raise it */ LOG_TB("raise decrementer exception\n"); ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1); } -static void __cpu_ppc_store_decr (CPUPPCState *env, uint64_t *nextp, - struct QEMUTimer *timer, - void (*raise_excp)(CPUPPCState *), - uint32_t decr, uint32_t value, - int is_excp) +static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp, + struct QEMUTimer *timer, + void (*raise_excp)(PowerPCCPU *), + uint32_t decr, uint32_t value, + int is_excp) { + CPUPPCState *env = &cpu->env; ppc_tb_t *tb_env = env->tb_env; uint64_t now, next; @@ -697,53 +694,61 @@ static void __cpu_ppc_store_decr (CPUPPCState *env, uint64_t *nextp, if ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && (value & 0x80000000) && !(decr & 0x80000000)) { - (*raise_excp)(env); + (*raise_excp)(cpu); } } -static inline void _cpu_ppc_store_decr(CPUPPCState *env, uint32_t decr, +static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, uint32_t decr, uint32_t value, int is_excp) { - ppc_tb_t *tb_env = env->tb_env; + ppc_tb_t *tb_env = cpu->env.tb_env; - __cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer, + __cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer, &cpu_ppc_decr_excp, decr, value, is_excp); } void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value) { - _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0); + PowerPCCPU *cpu = ppc_env_get_cpu(env); + + _cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value, 0); } static void cpu_ppc_decr_cb (void *opaque) { - _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1); + CPUPPCState *env = opaque; + + _cpu_ppc_store_decr(ppc_env_get_cpu(env), 0x00000000, 0xFFFFFFFF, 1); } -static inline void _cpu_ppc_store_hdecr(CPUPPCState *env, uint32_t hdecr, +static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, uint32_t hdecr, uint32_t value, int is_excp) { - ppc_tb_t *tb_env = env->tb_env; + ppc_tb_t *tb_env = cpu->env.tb_env; if (tb_env->hdecr_timer != NULL) { - __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer, + __cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer, &cpu_ppc_hdecr_excp, hdecr, value, is_excp); } } void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value) { - _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0); + PowerPCCPU *cpu = ppc_env_get_cpu(env); + + _cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value, 0); } static void cpu_ppc_hdecr_cb (void *opaque) { - _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1); + CPUPPCState *env = opaque; + + _cpu_ppc_store_hdecr(ppc_env_get_cpu(env), 0x00000000, 0xFFFFFFFF, 1); } -static void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value) +static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value) { - ppc_tb_t *tb_env = env->tb_env; + ppc_tb_t *tb_env = cpu->env.tb_env; tb_env->purr_load = value; tb_env->purr_start = qemu_get_clock_ns(vm_clock); @@ -752,6 +757,7 @@ static void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value) static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq) { CPUPPCState *env = opaque; + PowerPCCPU *cpu = ppc_env_get_cpu(env); ppc_tb_t *tb_env = env->tb_env; tb_env->tb_freq = freq; @@ -760,9 +766,9 @@ static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq) * if a decrementer exception is pending when it enables msr_ee at startup, * it's not ready to handle it... */ - _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0); - _cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0); - cpu_ppc_store_purr(env, 0x0000000000000000ULL); + _cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0); + _cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0); + cpu_ppc_store_purr(cpu, 0x0000000000000000ULL); } /* Set up (once) timebase frequency (in Hz) */ From 50c680f06ca81aebc91ac4a325f194b2d8396721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sat, 1 Dec 2012 04:26:55 +0100 Subject: [PATCH 2078/2270] ppc: Pass PowerPCCPU to [h]decr timer callbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleans up after passing PowerPCCPU to [h]decr exception callbacks. Signed-off-by: Andreas Färber --- hw/ppc.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/hw/ppc.c b/hw/ppc.c index b1b93a1e7d..8c05eb308d 100644 --- a/hw/ppc.c +++ b/hw/ppc.c @@ -714,11 +714,11 @@ void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value) _cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value, 0); } -static void cpu_ppc_decr_cb (void *opaque) +static void cpu_ppc_decr_cb(void *opaque) { - CPUPPCState *env = opaque; + PowerPCCPU *cpu = opaque; - _cpu_ppc_store_decr(ppc_env_get_cpu(env), 0x00000000, 0xFFFFFFFF, 1); + _cpu_ppc_store_decr(cpu, 0x00000000, 0xFFFFFFFF, 1); } static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, uint32_t hdecr, @@ -739,11 +739,11 @@ void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value) _cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value, 0); } -static void cpu_ppc_hdecr_cb (void *opaque) +static void cpu_ppc_hdecr_cb(void *opaque) { - CPUPPCState *env = opaque; + PowerPCCPU *cpu = opaque; - _cpu_ppc_store_hdecr(ppc_env_get_cpu(env), 0x00000000, 0xFFFFFFFF, 1); + _cpu_ppc_store_hdecr(cpu, 0x00000000, 0xFFFFFFFF, 1); } static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value) @@ -774,17 +774,19 @@ static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq) /* Set up (once) timebase frequency (in Hz) */ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); ppc_tb_t *tb_env; tb_env = g_malloc0(sizeof(ppc_tb_t)); env->tb_env = tb_env; tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED; /* Create new timer */ - tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_decr_cb, env); + tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_decr_cb, cpu); if (0) { /* XXX: find a suitable condition to enable the hypervisor decrementer */ - tb_env->hdecr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_hdecr_cb, env); + tb_env->hdecr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_hdecr_cb, + cpu); } else { tb_env->hdecr_timer = NULL; } From ee0c98e650da0ce1e4e17dc1e2bbb946cde2c45c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sat, 1 Dec 2012 04:35:15 +0100 Subject: [PATCH 2079/2270] ppc_booke: Pass PowerPCCPU to {decr,fit,wdt} timer callbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleans up after passing PowerPCCPU to booke_update_irq(). Signed-off-by: Andreas Färber --- hw/ppc_booke.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/hw/ppc_booke.c b/hw/ppc_booke.c index da6bc4a283..5748063f45 100644 --- a/hw/ppc_booke.c +++ b/hw/ppc_booke.c @@ -155,8 +155,8 @@ static void booke_update_fixed_timer(CPUPPCState *env, static void booke_decr_cb(void *opaque) { - CPUPPCState *env = opaque; - PowerPCCPU *cpu = ppc_env_get_cpu(env); + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; env->spr[SPR_BOOKE_TSR] |= TSR_DIS; booke_update_irq(cpu); @@ -169,13 +169,11 @@ static void booke_decr_cb(void *opaque) static void booke_fit_cb(void *opaque) { - PowerPCCPU *cpu; - CPUPPCState *env; + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; ppc_tb_t *tb_env; booke_timer_t *booke_timer; - env = opaque; - cpu = ppc_env_get_cpu(env); tb_env = env->tb_env; booke_timer = tb_env->opaque; env->spr[SPR_BOOKE_TSR] |= TSR_FIS; @@ -190,13 +188,11 @@ static void booke_fit_cb(void *opaque) static void booke_wdt_cb(void *opaque) { - PowerPCCPU *cpu; - CPUPPCState *env; + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; ppc_tb_t *tb_env; booke_timer_t *booke_timer; - env = opaque; - cpu = ppc_env_get_cpu(env); tb_env = env->tb_env; booke_timer = tb_env->opaque; @@ -243,6 +239,7 @@ void store_booke_tcr(CPUPPCState *env, target_ulong val) void ppc_booke_timers_init(CPUPPCState *env, uint32_t freq, uint32_t flags) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); ppc_tb_t *tb_env; booke_timer_t *booke_timer; @@ -255,10 +252,10 @@ void ppc_booke_timers_init(CPUPPCState *env, uint32_t freq, uint32_t flags) tb_env->tb_freq = freq; tb_env->decr_freq = freq; tb_env->opaque = booke_timer; - tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &booke_decr_cb, env); + tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &booke_decr_cb, cpu); booke_timer->fit_timer = - qemu_new_timer_ns(vm_clock, &booke_fit_cb, env); + qemu_new_timer_ns(vm_clock, &booke_fit_cb, cpu); booke_timer->wdt_timer = - qemu_new_timer_ns(vm_clock, &booke_wdt_cb, env); + qemu_new_timer_ns(vm_clock, &booke_wdt_cb, cpu); } From 2f9859fb49cb3c6ec876bc0bf709f28afcdd2384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sat, 1 Dec 2012 04:47:33 +0100 Subject: [PATCH 2080/2270] ppc4xx_devs: Return PowerPCCPU from ppc4xx_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepares for passing PowerPCCPU to ppc_booke_timers_init(). Signed-off-by: Andreas Färber --- hw/ppc405_uc.c | 8 ++++++-- hw/ppc4xx.h | 6 +++--- hw/ppc4xx_devs.c | 8 ++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c index 0f458ef772..373b8f3324 100644 --- a/hw/ppc405_uc.c +++ b/hw/ppc405_uc.c @@ -2111,12 +2111,14 @@ CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem, { clk_setup_t clk_setup[PPC405CR_CLK_NB]; qemu_irq dma_irqs[4]; + PowerPCCPU *cpu; CPUPPCState *env; qemu_irq *pic, *irqs; memset(clk_setup, 0, sizeof(clk_setup)); - env = ppc4xx_init("405cr", &clk_setup[PPC405CR_CPU_CLK], + cpu = ppc4xx_init("405cr", &clk_setup[PPC405CR_CPU_CLK], &clk_setup[PPC405CR_TMR_CLK], sysclk); + env = &cpu->env; /* Memory mapped devices registers */ /* PLB arbitrer */ ppc4xx_plb_init(env); @@ -2460,13 +2462,15 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem, { clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup; qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4]; + PowerPCCPU *cpu; CPUPPCState *env; qemu_irq *pic, *irqs; memset(clk_setup, 0, sizeof(clk_setup)); /* init CPUs */ - env = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK], + cpu = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK], &tlb_clk_setup, sysclk); + env = &cpu->env; clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb; clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque; /* Internal devices init */ diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h index d795ced57e..5d891aeae6 100644 --- a/hw/ppc4xx.h +++ b/hw/ppc4xx.h @@ -28,9 +28,9 @@ #include "pci.h" /* PowerPC 4xx core initialization */ -CPUPPCState *ppc4xx_init (const char *cpu_model, - clk_setup_t *cpu_clk, clk_setup_t *tb_clk, - uint32_t sysclk); +PowerPCCPU *ppc4xx_init(const char *cpu_model, + clk_setup_t *cpu_clk, clk_setup_t *tb_clk, + uint32_t sysclk); /* PowerPC 4xx universal interrupt controller */ enum { diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c index bac8d8769a..761cb595ae 100644 --- a/hw/ppc4xx_devs.c +++ b/hw/ppc4xx_devs.c @@ -47,9 +47,9 @@ static void ppc4xx_reset(void *opaque) /*****************************************************************************/ /* Generic PowerPC 4xx processor instantiation */ -CPUPPCState *ppc4xx_init (const char *cpu_model, - clk_setup_t *cpu_clk, clk_setup_t *tb_clk, - uint32_t sysclk) +PowerPCCPU *ppc4xx_init(const char *cpu_model, + clk_setup_t *cpu_clk, clk_setup_t *tb_clk, + uint32_t sysclk) { PowerPCCPU *cpu; CPUPPCState *env; @@ -72,7 +72,7 @@ CPUPPCState *ppc4xx_init (const char *cpu_model, /* Register qemu callbacks */ qemu_register_reset(ppc4xx_reset, cpu); - return env; + return cpu; } /*****************************************************************************/ From a34a92b9ecd8d25bd1de9df601ed31ccd8ebcae7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sat, 1 Dec 2012 04:43:18 +0100 Subject: [PATCH 2081/2270] ppc_booke: Pass PowerPCCPU to ppc_booke_timers_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleans up after passing PowerPCCPU to timer callbacks. Signed-off-by: Andreas Färber --- hw/ppc.h | 2 +- hw/ppc/e500.c | 2 +- hw/ppc405_uc.c | 2 +- hw/ppc440_bamboo.c | 2 +- hw/ppc_booke.c | 5 ++--- hw/virtex_ml507.c | 2 +- 6 files changed, 7 insertions(+), 8 deletions(-) diff --git a/hw/ppc.h b/hw/ppc.h index 64463ad388..ec33f9c6b9 100644 --- a/hw/ppc.h +++ b/hw/ppc.h @@ -89,4 +89,4 @@ enum { #define PPC_SERIAL_MM_BAUDBASE 399193 /* ppc_booke.c */ -void ppc_booke_timers_init(CPUPPCState *env, uint32_t freq, uint32_t flags); +void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags); diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index af6b67143a..55923595ca 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -495,7 +495,7 @@ void ppce500_init(PPCE500Params *params) env->mpic_cpu_base = MPC8544_CCSRBAR_BASE + MPC8544_MPIC_REGS_OFFSET + 0x20000; - ppc_booke_timers_init(env, 400000000, PPC_TIMER_E500); + ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500); /* Register reset handler */ if (!i) { diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c index 373b8f3324..fe71784cdc 100644 --- a/hw/ppc405_uc.c +++ b/hw/ppc405_uc.c @@ -2482,7 +2482,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem, /* OBP arbitrer */ ppc4xx_opba_init(0xef600600); /* Initialize timers */ - ppc_booke_timers_init(env, sysclk, 0); + ppc_booke_timers_init(cpu, sysclk, 0); /* Universal interrupt controller */ irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB); irqs[PPCUIC_OUTPUT_INT] = diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c index cc85607cb7..d9f0f81d62 100644 --- a/hw/ppc440_bamboo.c +++ b/hw/ppc440_bamboo.c @@ -195,7 +195,7 @@ static void bamboo_init(QEMUMachineInitArgs *args) env = &cpu->env; qemu_register_reset(main_cpu_reset, cpu); - ppc_booke_timers_init(env, 400000000, 0); + ppc_booke_timers_init(cpu, 400000000, 0); ppc_dcr_init(env, NULL, NULL); /* interrupt controller */ diff --git a/hw/ppc_booke.c b/hw/ppc_booke.c index 5748063f45..f2c0409f94 100644 --- a/hw/ppc_booke.c +++ b/hw/ppc_booke.c @@ -237,16 +237,15 @@ void store_booke_tcr(CPUPPCState *env, target_ulong val) } -void ppc_booke_timers_init(CPUPPCState *env, uint32_t freq, uint32_t flags) +void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags) { - PowerPCCPU *cpu = ppc_env_get_cpu(env); ppc_tb_t *tb_env; booke_timer_t *booke_timer; tb_env = g_malloc0(sizeof(ppc_tb_t)); booke_timer = g_malloc0(sizeof(booke_timer_t)); - env->tb_env = tb_env; + cpu->env.tb_env = tb_env; tb_env->flags = flags | PPC_TIMER_BOOKE | PPC_DECR_ZERO_TRIGGERED; tb_env->tb_freq = freq; diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c index 6ab8fee0c1..1a19cd2d08 100644 --- a/hw/virtex_ml507.c +++ b/hw/virtex_ml507.c @@ -94,7 +94,7 @@ static PowerPCCPU *ppc440_init_xilinx(ram_addr_t *ram_size, } env = &cpu->env; - ppc_booke_timers_init(env, sysclk, 0/* no flags */); + ppc_booke_timers_init(cpu, sysclk, 0/* no flags */); ppc_dcr_init(env, NULL, NULL); From a60f24b56b07f46453424263b276b0879c25c4e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sat, 1 Dec 2012 05:35:08 +0100 Subject: [PATCH 2082/2270] cpu: Move kvm_state field into CPUState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adapt some functions to take CPUState / {PowerPC,S390}CPU argument. Signed-off-by: Andreas Färber --- cpu-defs.h | 2 -- include/qemu/cpu.h | 3 +++ kvm-all.c | 28 ++++++++++++++-------------- kvm.h | 4 ++-- target-i386/cpu.c | 7 +++++-- target-i386/kvm.c | 22 +++++++++++----------- target-ppc/kvm.c | 33 ++++++++++++++++++++------------- target-s390x/kvm.c | 5 ++--- 8 files changed, 57 insertions(+), 47 deletions(-) diff --git a/cpu-defs.h b/cpu-defs.h index a382e35248..9ed54cf444 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -135,7 +135,6 @@ typedef struct icount_decr_u16 { #endif struct kvm_run; -struct KVMState; struct qemu_work_item; typedef struct CPUBreakpoint { @@ -205,7 +204,6 @@ typedef struct CPUWatchpoint { void *opaque; \ \ const char *cpu_model_str; \ - struct KVMState *kvm_state; \ struct kvm_run *kvm_run; #endif diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h index b8f8dd1d13..03962eff69 100644 --- a/include/qemu/cpu.h +++ b/include/qemu/cpu.h @@ -52,6 +52,8 @@ typedef struct CPUClass { void (*reset)(CPUState *cpu); } CPUClass; +struct KVMState; + /** * CPUState: * @created: Indicates whether the CPU thread has been successfully created. @@ -82,6 +84,7 @@ struct CPUState { int kvm_fd; bool kvm_vcpu_dirty; #endif + struct KVMState *kvm_state; /* TODO Move common fields from CPUArchState here. */ }; diff --git a/kvm-all.c b/kvm-all.c index 5f1d1fed2c..ba139ab13c 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -230,7 +230,7 @@ int kvm_init_vcpu(CPUArchState *env) } cpu->kvm_fd = ret; - env->kvm_state = s; + cpu->kvm_state = s; cpu->kvm_vcpu_dirty = true; mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0); @@ -1763,12 +1763,12 @@ void kvm_setup_guest_memory(void *start, size_t size) } #ifdef KVM_CAP_SET_GUEST_DEBUG -struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUArchState *env, +struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu, target_ulong pc) { struct kvm_sw_breakpoint *bp; - QTAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) { + QTAILQ_FOREACH(bp, &cpu->kvm_state->kvm_sw_breakpoints, entry) { if (bp->pc == pc) { return bp; } @@ -1776,23 +1776,23 @@ struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUArchState *env, return NULL; } -int kvm_sw_breakpoints_active(CPUArchState *env) +int kvm_sw_breakpoints_active(CPUState *cpu) { - return !QTAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints); + return !QTAILQ_EMPTY(&cpu->kvm_state->kvm_sw_breakpoints); } struct kvm_set_guest_debug_data { struct kvm_guest_debug dbg; - CPUArchState *env; + CPUState *cpu; int err; }; static void kvm_invoke_set_guest_debug(void *data) { struct kvm_set_guest_debug_data *dbg_data = data; - CPUState *cpu = ENV_GET_CPU(dbg_data->env); - dbg_data->err = kvm_vcpu_ioctl(cpu, KVM_SET_GUEST_DEBUG, &dbg_data->dbg); + dbg_data->err = kvm_vcpu_ioctl(dbg_data->cpu, KVM_SET_GUEST_DEBUG, + &dbg_data->dbg); } int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap) @@ -1806,7 +1806,7 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap) data.dbg.control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP; } kvm_arch_update_guest_debug(cpu, &data.dbg); - data.env = env; + data.cpu = cpu; run_on_cpu(cpu, kvm_invoke_set_guest_debug, &data); return data.err; @@ -1821,7 +1821,7 @@ int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, int err; if (type == GDB_BREAKPOINT_SW) { - bp = kvm_find_sw_breakpoint(current_env, addr); + bp = kvm_find_sw_breakpoint(current_cpu, addr); if (bp) { bp->use_count++; return 0; @@ -1840,7 +1840,7 @@ int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, return err; } - QTAILQ_INSERT_HEAD(¤t_env->kvm_state->kvm_sw_breakpoints, + QTAILQ_INSERT_HEAD(¤t_cpu->kvm_state->kvm_sw_breakpoints, bp, entry); } else { err = kvm_arch_insert_hw_breakpoint(addr, len, type); @@ -1867,7 +1867,7 @@ int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, int err; if (type == GDB_BREAKPOINT_SW) { - bp = kvm_find_sw_breakpoint(current_env, addr); + bp = kvm_find_sw_breakpoint(current_cpu, addr); if (!bp) { return -ENOENT; } @@ -1882,7 +1882,7 @@ int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, return err; } - QTAILQ_REMOVE(¤t_env->kvm_state->kvm_sw_breakpoints, bp, entry); + QTAILQ_REMOVE(¤t_cpu->kvm_state->kvm_sw_breakpoints, bp, entry); g_free(bp); } else { err = kvm_arch_remove_hw_breakpoint(addr, len, type); @@ -1904,7 +1904,7 @@ void kvm_remove_all_breakpoints(CPUArchState *current_env) { CPUState *current_cpu = ENV_GET_CPU(current_env); struct kvm_sw_breakpoint *bp, *next; - KVMState *s = current_env->kvm_state; + KVMState *s = current_cpu->kvm_state; CPUArchState *env; CPUState *cpu; diff --git a/kvm.h b/kvm.h index a2375ff469..6ddcdc5e8b 100644 --- a/kvm.h +++ b/kvm.h @@ -207,10 +207,10 @@ struct kvm_sw_breakpoint { QTAILQ_HEAD(kvm_sw_breakpoint_head, kvm_sw_breakpoint); -struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUArchState *env, +struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu, target_ulong pc); -int kvm_sw_breakpoints_active(CPUArchState *env); +int kvm_sw_breakpoints_active(CPUState *cpu); int kvm_arch_insert_sw_breakpoint(CPUState *current_cpu, struct kvm_sw_breakpoint *bp); diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 7be3ad82cb..04a90c5e21 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1636,6 +1636,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { + X86CPU *cpu = x86_env_get_cpu(env); + CPUState *cs = CPU(cpu); + /* test if maximum index reached */ if (index & 0x80000000) { if (index > env->cpuid_xlevel) { @@ -1752,7 +1755,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, case 0xA: /* Architectural Performance Monitoring Leaf */ if (kvm_enabled()) { - KVMState *s = env->kvm_state; + KVMState *s = cs->kvm_state; *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX); *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX); @@ -1775,7 +1778,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; } if (kvm_enabled()) { - KVMState *s = env->kvm_state; + KVMState *s = cs->kvm_state; *eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX); *ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX); diff --git a/target-i386/kvm.c b/target-i386/kvm.c index b2efa1e928..ff5c9cd1cd 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -316,7 +316,7 @@ int kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) if ((env->mcg_cap & MCG_SER_P) && addr && (code == BUS_MCEERR_AR || code == BUS_MCEERR_AO)) { if (qemu_ram_addr_from_host(addr, &ram_addr) || - !kvm_physical_memory_addr_from_host(env->kvm_state, addr, &paddr)) { + !kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) { fprintf(stderr, "Hardware memory error for memory used by " "QEMU itself instead of guest system!\n"); /* Hope we are lucky for AO MCE */ @@ -348,8 +348,8 @@ int kvm_arch_on_sigbus(int code, void *addr) /* Hope we are lucky for AO MCE */ if (qemu_ram_addr_from_host(addr, &ram_addr) || - !kvm_physical_memory_addr_from_host(first_cpu->kvm_state, addr, - &paddr)) { + !kvm_physical_memory_addr_from_host(CPU(first_cpu)->kvm_state, + addr, &paddr)) { fprintf(stderr, "Hardware memory error for memory used by " "QEMU itself instead of guest system!: %p\n", addr); return 0; @@ -579,12 +579,12 @@ int kvm_arch_init_vcpu(CPUState *cs) if (((env->cpuid_version >> 8)&0xF) >= 6 && (env->cpuid_features&(CPUID_MCE|CPUID_MCA)) == (CPUID_MCE|CPUID_MCA) - && kvm_check_extension(env->kvm_state, KVM_CAP_MCE) > 0) { + && kvm_check_extension(cs->kvm_state, KVM_CAP_MCE) > 0) { uint64_t mcg_cap; int banks; int ret; - ret = kvm_get_mce_cap_supported(env->kvm_state, &mcg_cap, &banks); + ret = kvm_get_mce_cap_supported(cs->kvm_state, &mcg_cap, &banks); if (ret < 0) { fprintf(stderr, "kvm_get_mce_cap_supported: %s", strerror(-ret)); return ret; @@ -612,7 +612,7 @@ int kvm_arch_init_vcpu(CPUState *cs) return r; } - r = kvm_check_extension(env->kvm_state, KVM_CAP_TSC_CONTROL); + r = kvm_check_extension(cs->kvm_state, KVM_CAP_TSC_CONTROL); if (r && env->tsc_khz) { r = kvm_vcpu_ioctl(cs, KVM_SET_TSC_KHZ, env->tsc_khz); if (r < 0) { @@ -1977,9 +1977,10 @@ void kvm_arch_remove_all_hw_breakpoints(void) static CPUWatchpoint hw_watchpoint; -static int kvm_handle_debug(CPUX86State *env, +static int kvm_handle_debug(X86CPU *cpu, struct kvm_debug_exit_arch *arch_info) { + CPUX86State *env = &cpu->env; int ret = 0; int n; @@ -2011,7 +2012,7 @@ static int kvm_handle_debug(CPUX86State *env, } } } - } else if (kvm_find_sw_breakpoint(env, arch_info->pc)) { + } else if (kvm_find_sw_breakpoint(CPU(cpu), arch_info->pc)) { ret = EXCP_DEBUG; } if (ret == 0) { @@ -2028,7 +2029,6 @@ static int kvm_handle_debug(CPUX86State *env, void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg) { - CPUX86State *env = &X86_CPU(cpu)->env; const uint8_t type_code[] = { [GDB_BREAKPOINT_HW] = 0x0, [GDB_WATCHPOINT_WRITE] = 0x1, @@ -2039,7 +2039,7 @@ void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg) }; int n; - if (kvm_sw_breakpoints_active(env)) { + if (kvm_sw_breakpoints_active(cpu)) { dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; } if (nb_hw_breakpoint > 0) { @@ -2106,7 +2106,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) break; case KVM_EXIT_DEBUG: DPRINTF("kvm_exit_debug\n"); - ret = kvm_handle_debug(env, &run->debug.arch); + ret = kvm_handle_debug(cpu, &run->debug.arch); break; default: fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason); diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index ad5bc66396..eb52b76bdc 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -140,7 +140,7 @@ static int kvm_booke206_tlb_init(PowerPCCPU *cpu) int ret, i; if (!kvm_enabled() || - !kvm_check_extension(env->kvm_state, KVM_CAP_SW_TLB)) { + !kvm_check_extension(cs->kvm_state, KVM_CAP_SW_TLB)) { return 0; } @@ -178,9 +178,12 @@ static int kvm_booke206_tlb_init(PowerPCCPU *cpu) #if defined(TARGET_PPC64) -static void kvm_get_fallback_smmu_info(CPUPPCState *env, +static void kvm_get_fallback_smmu_info(PowerPCCPU *cpu, struct kvm_ppc_smmu_info *info) { + CPUPPCState *env = &cpu->env; + CPUState *cs = CPU(cpu); + memset(info, 0, sizeof(*info)); /* We don't have the new KVM_PPC_GET_SMMU_INFO ioctl, so @@ -206,7 +209,7 @@ static void kvm_get_fallback_smmu_info(CPUPPCState *env, * implements KVM_CAP_PPC_GET_SMMU_INFO and thus doesn't hit * this fallback. */ - if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_GET_PVINFO)) { + if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO)) { /* No flags */ info->flags = 0; info->slb_size = 64; @@ -262,18 +265,19 @@ static void kvm_get_fallback_smmu_info(CPUPPCState *env, } } -static void kvm_get_smmu_info(CPUPPCState *env, struct kvm_ppc_smmu_info *info) +static void kvm_get_smmu_info(PowerPCCPU *cpu, struct kvm_ppc_smmu_info *info) { + CPUState *cs = CPU(cpu); int ret; - if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_GET_SMMU_INFO)) { - ret = kvm_vm_ioctl(env->kvm_state, KVM_PPC_GET_SMMU_INFO, info); + if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_SMMU_INFO)) { + ret = kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_SMMU_INFO, info); if (ret == 0) { return; } } - kvm_get_fallback_smmu_info(env, info); + kvm_get_fallback_smmu_info(cpu, info); } static long getrampagesize(void) @@ -316,10 +320,11 @@ static bool kvm_valid_page_size(uint32_t flags, long rampgsize, uint32_t shift) return (1ul << shift) <= rampgsize; } -static void kvm_fixup_page_sizes(CPUPPCState *env) +static void kvm_fixup_page_sizes(PowerPCCPU *cpu) { static struct kvm_ppc_smmu_info smmu_info; static bool has_smmu_info; + CPUPPCState *env = &cpu->env; long rampagesize; int iq, ik, jq, jk; @@ -330,7 +335,7 @@ static void kvm_fixup_page_sizes(CPUPPCState *env) /* Collect MMU info from kernel if not already */ if (!has_smmu_info) { - kvm_get_smmu_info(env, &smmu_info); + kvm_get_smmu_info(cpu, &smmu_info); has_smmu_info = true; } @@ -373,7 +378,7 @@ static void kvm_fixup_page_sizes(CPUPPCState *env) } #else /* defined (TARGET_PPC64) */ -static inline void kvm_fixup_page_sizes(CPUPPCState *env) +static inline void kvm_fixup_page_sizes(PowerPCCPU *cpu) { } @@ -386,7 +391,7 @@ int kvm_arch_init_vcpu(CPUState *cs) int ret; /* Gather server mmu info from KVM and update the CPU state */ - kvm_fixup_page_sizes(cenv); + kvm_fixup_page_sizes(cpu); /* Synchronize sregs with kvm */ ret = kvm_arch_sync_sregs(cpu); @@ -986,12 +991,14 @@ uint32_t kvmppc_get_dfp(void) int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); + CPUState *cs = CPU(cpu); uint32_t *hc = (uint32_t*)buf; struct kvm_ppc_pvinfo pvinfo; - if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_GET_PVINFO) && - !kvm_vm_ioctl(env->kvm_state, KVM_PPC_GET_PVINFO, &pvinfo)) { + if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO) && + !kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_PVINFO, &pvinfo)) { memcpy(buf, pvinfo.hcall, buf_len); return 0; diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 5422678330..4e343041fa 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -291,12 +291,11 @@ int kvm_arch_process_async_events(CPUState *cs) void kvm_s390_interrupt_internal(S390CPU *cpu, int type, uint32_t parm, uint64_t parm64, int vm) { - CPUS390XState *env = &cpu->env; CPUState *cs = CPU(cpu); struct kvm_s390_interrupt kvmint; int r; - if (!env->kvm_state) { + if (!cs->kvm_state) { return; } @@ -305,7 +304,7 @@ void kvm_s390_interrupt_internal(S390CPU *cpu, int type, uint32_t parm, kvmint.parm64 = parm64; if (vm) { - r = kvm_vm_ioctl(env->kvm_state, KVM_S390_INTERRUPT, &kvmint); + r = kvm_vm_ioctl(cs->kvm_state, KVM_S390_INTERRUPT, &kvmint); } else { r = kvm_vcpu_ioctl(cs, KVM_S390_INTERRUPT, &kvmint); } From f7575c96c6058763fe3bd8dd26f3d09473f2df36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sat, 1 Dec 2012 06:18:14 +0100 Subject: [PATCH 2083/2270] cpu: Move kvm_run into CPUState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass CPUState / {X86,S390}CPU to helper functions. Signed-off-by: Andreas Färber --- cpu-defs.h | 4 +-- include/qemu/cpu.h | 2 ++ kvm-all.c | 8 ++--- target-i386/kvm.c | 9 +++--- target-s390x/kvm.c | 77 ++++++++++++++++++++++++---------------------- 5 files changed, 53 insertions(+), 47 deletions(-) diff --git a/cpu-defs.h b/cpu-defs.h index 9ed54cf444..caea72b5be 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -134,7 +134,6 @@ typedef struct icount_decr_u16 { } icount_decr_u16; #endif -struct kvm_run; struct qemu_work_item; typedef struct CPUBreakpoint { @@ -203,7 +202,6 @@ typedef struct CPUWatchpoint { /* user data */ \ void *opaque; \ \ - const char *cpu_model_str; \ - struct kvm_run *kvm_run; + const char *cpu_model_str; #endif diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h index 03962eff69..fa3ffdbc2a 100644 --- a/include/qemu/cpu.h +++ b/include/qemu/cpu.h @@ -53,6 +53,7 @@ typedef struct CPUClass { } CPUClass; struct KVMState; +struct kvm_run; /** * CPUState: @@ -85,6 +86,7 @@ struct CPUState { bool kvm_vcpu_dirty; #endif struct KVMState *kvm_state; + struct kvm_run *kvm_run; /* TODO Move common fields from CPUArchState here. */ }; diff --git a/kvm-all.c b/kvm-all.c index ba139ab13c..f687229da8 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -240,9 +240,9 @@ int kvm_init_vcpu(CPUArchState *env) goto err; } - env->kvm_run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, + cpu->kvm_run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, cpu->kvm_fd, 0); - if (env->kvm_run == MAP_FAILED) { + if (cpu->kvm_run == MAP_FAILED) { ret = -errno; DPRINTF("mmap'ing vcpu state failed\n"); goto err; @@ -250,7 +250,7 @@ int kvm_init_vcpu(CPUArchState *env) if (s->coalesced_mmio && !s->coalesced_mmio_ring) { s->coalesced_mmio_ring = - (void *)env->kvm_run + s->coalesced_mmio * PAGE_SIZE; + (void *)cpu->kvm_run + s->coalesced_mmio * PAGE_SIZE; } ret = kvm_arch_init_vcpu(cpu); @@ -1529,7 +1529,7 @@ void kvm_cpu_synchronize_post_init(CPUArchState *env) int kvm_cpu_exec(CPUArchState *env) { CPUState *cpu = ENV_GET_CPU(env); - struct kvm_run *run = env->kvm_run; + struct kvm_run *run = cpu->kvm_run; int ret, run_ret; DPRINTF("kvm_cpu_exec()\n"); diff --git a/target-i386/kvm.c b/target-i386/kvm.c index ff5c9cd1cd..53096c97b4 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1859,9 +1859,11 @@ static int kvm_handle_halt(X86CPU *cpu) return 0; } -static int kvm_handle_tpr_access(CPUX86State *env) +static int kvm_handle_tpr_access(X86CPU *cpu) { - struct kvm_run *run = env->kvm_run; + CPUX86State *env = &cpu->env; + CPUState *cs = CPU(cpu); + struct kvm_run *run = cs->kvm_run; apic_handle_tpr_access_report(env->apic_state, run->tpr_access.rip, run->tpr_access.is_write ? TPR_ACCESS_WRITE @@ -2067,7 +2069,6 @@ static bool host_supports_vmx(void) int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) { X86CPU *cpu = X86_CPU(cs); - CPUX86State *env = &cpu->env; uint64_t code; int ret; @@ -2080,7 +2081,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) ret = 0; break; case KVM_EXIT_TPR_ACCESS: - ret = kvm_handle_tpr_access(env); + ret = kvm_handle_tpr_access(cpu); break; case KVM_EXIT_FAIL_ENTRY: code = run->fail_entry.hardware_entry_failure_reason; diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 4e343041fa..0b640928fc 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -98,13 +98,13 @@ int kvm_arch_put_registers(CPUState *cs, int level) int i; /* always save the PSW and the GPRS*/ - env->kvm_run->psw_addr = env->psw.addr; - env->kvm_run->psw_mask = env->psw.mask; + cs->kvm_run->psw_addr = env->psw.addr; + cs->kvm_run->psw_mask = env->psw.mask; - if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_GPRS) { + if (cap_sync_regs && cs->kvm_run->kvm_valid_regs & KVM_SYNC_GPRS) { for (i = 0; i < 16; i++) { - env->kvm_run->s.regs.gprs[i] = env->regs[i]; - env->kvm_run->kvm_dirty_regs |= KVM_SYNC_GPRS; + cs->kvm_run->s.regs.gprs[i] = env->regs[i]; + cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_GPRS; } } else { for (i = 0; i < 16; i++) { @@ -122,14 +122,14 @@ int kvm_arch_put_registers(CPUState *cs, int level) } if (cap_sync_regs && - env->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS && - env->kvm_run->kvm_valid_regs & KVM_SYNC_CRS) { + cs->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS && + cs->kvm_run->kvm_valid_regs & KVM_SYNC_CRS) { for (i = 0; i < 16; i++) { - env->kvm_run->s.regs.acrs[i] = env->aregs[i]; - env->kvm_run->s.regs.crs[i] = env->cregs[i]; + cs->kvm_run->s.regs.acrs[i] = env->aregs[i]; + cs->kvm_run->s.regs.crs[i] = env->cregs[i]; } - env->kvm_run->kvm_dirty_regs |= KVM_SYNC_ACRS; - env->kvm_run->kvm_dirty_regs |= KVM_SYNC_CRS; + cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_ACRS; + cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_CRS; } else { for (i = 0; i < 16; i++) { sregs.acrs[i] = env->aregs[i]; @@ -142,9 +142,9 @@ int kvm_arch_put_registers(CPUState *cs, int level) } /* Finally the prefix */ - if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) { - env->kvm_run->s.regs.prefix = env->psa; - env->kvm_run->kvm_dirty_regs |= KVM_SYNC_PREFIX; + if (cap_sync_regs && cs->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) { + cs->kvm_run->s.regs.prefix = env->psa; + cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_PREFIX; } else { /* prefix is only supported via sync regs */ } @@ -161,13 +161,13 @@ int kvm_arch_get_registers(CPUState *cs) int i; /* get the PSW */ - env->psw.addr = env->kvm_run->psw_addr; - env->psw.mask = env->kvm_run->psw_mask; + env->psw.addr = cs->kvm_run->psw_addr; + env->psw.mask = cs->kvm_run->psw_mask; /* the GPRS */ - if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_GPRS) { + if (cap_sync_regs && cs->kvm_run->kvm_valid_regs & KVM_SYNC_GPRS) { for (i = 0; i < 16; i++) { - env->regs[i] = env->kvm_run->s.regs.gprs[i]; + env->regs[i] = cs->kvm_run->s.regs.gprs[i]; } } else { ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); @@ -181,11 +181,11 @@ int kvm_arch_get_registers(CPUState *cs) /* The ACRS and CRS */ if (cap_sync_regs && - env->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS && - env->kvm_run->kvm_valid_regs & KVM_SYNC_CRS) { + cs->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS && + cs->kvm_run->kvm_valid_regs & KVM_SYNC_CRS) { for (i = 0; i < 16; i++) { - env->aregs[i] = env->kvm_run->s.regs.acrs[i]; - env->cregs[i] = env->kvm_run->s.regs.crs[i]; + env->aregs[i] = cs->kvm_run->s.regs.acrs[i]; + env->cregs[i] = cs->kvm_run->s.regs.crs[i]; } } else { ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs); @@ -199,8 +199,8 @@ int kvm_arch_get_registers(CPUState *cs) } /* Finally the prefix */ - if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) { - env->psa = env->kvm_run->s.regs.prefix; + if (cap_sync_regs && cs->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) { + env->psa = cs->kvm_run->s.regs.prefix; } else { /* no prefix without sync regs */ } @@ -331,10 +331,13 @@ static void enter_pgmcheck(S390CPU *cpu, uint16_t code) kvm_s390_interrupt(cpu, KVM_S390_PROGRAM_INT, code); } -static inline void setcc(CPUS390XState *env, uint64_t cc) +static inline void setcc(S390CPU *cpu, uint64_t cc) { - env->kvm_run->psw_mask &= ~(3ull << 44); - env->kvm_run->psw_mask |= (cc & 3) << 44; + CPUS390XState *env = &cpu->env; + CPUState *cs = CPU(cpu); + + cs->kvm_run->psw_mask &= ~(3ull << 44); + cs->kvm_run->psw_mask |= (cc & 3) << 44; env->psw.mask &= ~(3ul << 44); env->psw.mask |= (cc & 3) << 44; @@ -356,7 +359,7 @@ static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run, if (r < 0) { enter_pgmcheck(cpu, -r); } - setcc(env, r); + setcc(cpu, r); return 0; } @@ -446,8 +449,9 @@ static int s390_cpu_initial_reset(S390CPU *cpu) return 0; } -static int handle_sigp(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1) +static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) { + CPUS390XState *env = &cpu->env; uint8_t order_code; uint32_t parameter; uint16_t cpu_addr; @@ -499,7 +503,7 @@ static int handle_sigp(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1) } out: - setcc(env, r ? 3 : 0); + setcc(cpu, r ? 3 : 0); return 0; } @@ -520,7 +524,7 @@ static int handle_instruction(S390CPU *cpu, struct kvm_run *run) r = handle_diag(env, run, ipb_code); break; case IPA0_SIGP: - r = handle_sigp(env, run, ipa1); + r = handle_sigp(cpu, run, ipa1); break; } @@ -530,28 +534,29 @@ static int handle_instruction(S390CPU *cpu, struct kvm_run *run) return 0; } -static bool is_special_wait_psw(CPUS390XState *env) +static bool is_special_wait_psw(CPUState *cs) { /* signal quiesce */ - return env->kvm_run->psw_addr == 0xfffUL; + return cs->kvm_run->psw_addr == 0xfffUL; } static int handle_intercept(S390CPU *cpu) { CPUS390XState *env = &cpu->env; - struct kvm_run *run = env->kvm_run; + CPUState *cs = CPU(cpu); + struct kvm_run *run = cs->kvm_run; int icpt_code = run->s390_sieic.icptcode; int r = 0; dprintf("intercept: 0x%x (at 0x%lx)\n", icpt_code, - (long)env->kvm_run->psw_addr); + (long)cs->kvm_run->psw_addr); switch (icpt_code) { case ICPT_INSTRUCTION: r = handle_instruction(cpu, run); break; case ICPT_WAITPSW: if (s390_del_running_cpu(env) == 0 && - is_special_wait_psw(env)) { + is_special_wait_psw(cs)) { qemu_system_shutdown_request(); } r = EXCP_HALTED; From 62e0c095450f6a7eb37914991f3f7966aa4da7a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 9 Dec 2012 20:15:31 +0100 Subject: [PATCH 2084/2270] MAINTAINERS: Include X86CPU in CPU maintenance area MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document that the x86 CPU refactorings are going through the qom-cpu tree. This does not contradict the established practice that patches adding KVM features to the x86 CPU go through the KVM maintainers, it merely takes it out of target-i386 TCG's Odd Fixes status. Signed-off-by: Andreas Färber Cc: Marcello Tosatti --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 2ede20d60b..61d5a4b009 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -599,6 +599,7 @@ M: Andreas Färber S: Supported F: qom/cpu.c F: include/qemu/cpu.h +F: target-i386/cpu.c Device Tree M: Peter Crosthwaite From 15faf946f7a17a5fab0d05a2312d43249d81af3c Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 20 Dec 2012 08:19:16 +0100 Subject: [PATCH 2085/2270] Update seabios to a810e4e72a0d42c7bc04eda57382f8e019add901 git shortlog: Kevin O'Connor (6): floppy: Minor - reduce handle_0e code size when CONFIG_FLOPPY is disabled. vga: Minor comment spelling fix. Don't recursively evaluate CFLAGS variables. Don't use gcc's -combine option. Add compile checking phase to build. acpi: Use prt_slot() macro to describe irq pins of first PCI device. Laszlo Ersek (1): maininit(): print machine UUID under seabios version message Paolo Bonzini (1): acpi: reintroduce LNKS Paolo's patch fixes the FreeBSD boot failure. Cc: qemu-stable@nongnu.org Signed-off-by: Gerd Hoffmann --- pc-bios/acpi-dsdt.aml | Bin 4438 -> 4521 bytes pc-bios/bios.bin | Bin 262144 -> 131072 bytes pc-bios/q35-acpi-dsdt.aml | Bin 7458 -> 7458 bytes roms/seabios | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pc-bios/acpi-dsdt.aml b/pc-bios/acpi-dsdt.aml index 18b4dc1aa53859593604abe598b05784b116a360..00224eabb7b92de601edc5cc41b444c4ca8cb9da 100644 GIT binary patch delta 175 zcmcbnv{G5wCDSOQWD P6bcRsX54(9znu{PZH*~z delta 91 zcmZ3fd`(H&CD*ruv5H% qYe|5!rvXQNKv0N~=VTo=Q*Le+p8x+rs<}8f=dmSoZdMX#X9NHb#TIb@ diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin index 3eefff4cf81a37e0cbd20d3cf0da7b2dd11c34d5..3910875311ceaed814f902e9e4e7e29cdf340fc6 100644 GIT binary patch delta 44263 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

TuRymwO&F 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 diff --git a/pc-bios/q35-acpi-dsdt.aml b/pc-bios/q35-acpi-dsdt.aml index 8a5055951485d7b14ba44e6c99ecd32bf1ad446e..e50641cc53416c14133bfc7ae48f35fb14116781 100644 GIT binary patch delta 44 xcmZ2vwa7}@CDu{v{CuL3;^NE3DN)n diff --git a/roms/seabios b/roms/seabios index e8a76b0f22..a810e4e72a 160000 --- a/roms/seabios +++ b/roms/seabios @@ -1 +1 @@ -Subproject commit e8a76b0f225bba5ba9d63ab227e0a37b3beb1059 +Subproject commit a810e4e72a0d42c7bc04eda57382f8e019add901 From d2a0ccc613ccc48c7240f99e1ce05e0acce6e2a1 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 17 Dec 2012 13:01:07 +0200 Subject: [PATCH 2086/2270] virtio: make bindings typesafe Move bindings from opaque to DeviceState. This gives us better type safety with no performance cost. Add macros to make future QOM work easier. Signed-off-by: Michael S. Tsirkin --- hw/s390-virtio-bus.c | 24 ++++++++++++---- hw/virtio-pci.c | 67 ++++++++++++++++++++++++++------------------ hw/virtio.c | 2 +- hw/virtio.h | 26 ++++++++--------- 4 files changed, 73 insertions(+), 46 deletions(-) diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index 963b4f0dc2..84fba9674c 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -136,7 +136,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev) bus->dev_offs += dev_len; - virtio_bind_device(vdev, &virtio_s390_bindings, dev); + virtio_bind_device(vdev, &virtio_s390_bindings, DEVICE(dev)); dev->host_features = vdev->get_features(vdev, dev->host_features); s390_virtio_device_sync(dev); s390_virtio_reset_idx(dev); @@ -363,9 +363,23 @@ VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem) return NULL; } -static void virtio_s390_notify(void *opaque, uint16_t vector) +/* DeviceState to VirtIOS390Device. Note: used on datapath, + * be careful and test performance if you change this. + */ +static inline VirtIOS390Device *to_virtio_s390_device_fast(DeviceState *d) { - VirtIOS390Device *dev = (VirtIOS390Device*)opaque; + return container_of(d, VirtIOS390Device, qdev); +} + +/* DeviceState to VirtIOS390Device. TODO: use QOM. */ +static inline VirtIOS390Device *to_virtio_s390_device(DeviceState *d) +{ + return container_of(d, VirtIOS390Device, qdev); +} + +static void virtio_s390_notify(DeviceState *d, uint16_t vector) +{ + VirtIOS390Device *dev = to_virtio_s390_device_fast(d); uint64_t token = s390_virtio_device_vq_token(dev, vector); S390CPU *cpu = s390_cpu_addr2state(0); CPUS390XState *env = &cpu->env; @@ -373,9 +387,9 @@ static void virtio_s390_notify(void *opaque, uint16_t vector) s390_virtio_irq(env, 0, token); } -static unsigned virtio_s390_get_features(void *opaque) +static unsigned virtio_s390_get_features(DeviceState *d) { - VirtIOS390Device *dev = (VirtIOS390Device*)opaque; + VirtIOS390Device *dev = to_virtio_s390_device(d); return dev->host_features; } diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index d2d2454493..1f1a285ce8 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -96,35 +96,48 @@ bool virtio_is_big_endian(void); /* virtio device */ - -static void virtio_pci_notify(void *opaque, uint16_t vector) +/* DeviceState to VirtIOPCIProxy. For use off data-path. TODO: use QOM. */ +static inline VirtIOPCIProxy *to_virtio_pci_proxy(DeviceState *d) { - VirtIOPCIProxy *proxy = opaque; + return container_of(d, VirtIOPCIProxy, pci_dev.qdev); +} + +/* DeviceState to VirtIOPCIProxy. Note: used on datapath, + * be careful and test performance if you change this. + */ +static inline VirtIOPCIProxy *to_virtio_pci_proxy_fast(DeviceState *d) +{ + return container_of(d, VirtIOPCIProxy, pci_dev.qdev); +} + +static void virtio_pci_notify(DeviceState *d, uint16_t vector) +{ + VirtIOPCIProxy *proxy = to_virtio_pci_proxy_fast(d); if (msix_enabled(&proxy->pci_dev)) msix_notify(&proxy->pci_dev, vector); else qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1); } -static void virtio_pci_save_config(void * opaque, QEMUFile *f) +static void virtio_pci_save_config(DeviceState *d, QEMUFile *f) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); pci_device_save(&proxy->pci_dev, f); msix_save(&proxy->pci_dev, f); if (msix_present(&proxy->pci_dev)) qemu_put_be16(f, proxy->vdev->config_vector); } -static void virtio_pci_save_queue(void * opaque, int n, QEMUFile *f) +static void virtio_pci_save_queue(DeviceState *d, int n, QEMUFile *f) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); if (msix_present(&proxy->pci_dev)) qemu_put_be16(f, virtio_queue_vector(proxy->vdev, n)); } -static int virtio_pci_load_config(void * opaque, QEMUFile *f) +static int virtio_pci_load_config(DeviceState *d, QEMUFile *f) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); int ret; ret = pci_device_load(&proxy->pci_dev, f); if (ret) { @@ -143,9 +156,9 @@ static int virtio_pci_load_config(void * opaque, QEMUFile *f) return 0; } -static int virtio_pci_load_queue(void * opaque, int n, QEMUFile *f) +static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); uint16_t vector; if (msix_present(&proxy->pci_dev)) { qemu_get_be16s(f, &vector); @@ -243,7 +256,7 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy) void virtio_pci_reset(DeviceState *d) { - VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev); + VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); virtio_pci_stop_ioeventfd(proxy); virtio_reset(proxy->vdev); msix_unuse_all_vectors(&proxy->pci_dev); @@ -463,9 +476,9 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address, } } -static unsigned virtio_pci_get_features(void *opaque) +static unsigned virtio_pci_get_features(DeviceState *d) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); return proxy->host_features; } @@ -567,9 +580,9 @@ static void kvm_virtio_pci_vector_release(PCIDevice *dev, unsigned vector) } } -static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign) +static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); VirtQueue *vq = virtio_get_queue(proxy->vdev, n); EventNotifier *notifier = virtio_queue_get_guest_notifier(vq); @@ -587,15 +600,15 @@ static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign) return 0; } -static bool virtio_pci_query_guest_notifiers(void *opaque) +static bool virtio_pci_query_guest_notifiers(DeviceState *d) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); return msix_enabled(&proxy->pci_dev); } -static int virtio_pci_set_guest_notifiers(void *opaque, bool assign) +static int virtio_pci_set_guest_notifiers(DeviceState *d, bool assign) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); VirtIODevice *vdev = proxy->vdev; int r, n; @@ -611,7 +624,7 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign) break; } - r = virtio_pci_set_guest_notifier(opaque, n, assign); + r = virtio_pci_set_guest_notifier(d, n, assign); if (r < 0) { goto assign_error; } @@ -636,14 +649,14 @@ assign_error: /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */ assert(assign); while (--n >= 0) { - virtio_pci_set_guest_notifier(opaque, n, !assign); + virtio_pci_set_guest_notifier(d, n, !assign); } return r; } -static int virtio_pci_set_host_notifier(void *opaque, int n, bool assign) +static int virtio_pci_set_host_notifier(DeviceState *d, int n, bool assign) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); /* Stop using ioeventfd for virtqueue kick if the device starts using host * notifiers. This makes it easy to avoid stepping on each others' toes. @@ -659,9 +672,9 @@ static int virtio_pci_set_host_notifier(void *opaque, int n, bool assign) return virtio_pci_set_host_notifier_internal(proxy, n, assign, false); } -static void virtio_pci_vmstate_change(void *opaque, bool running) +static void virtio_pci_vmstate_change(DeviceState *d, bool running) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); if (running) { /* Try to find out if the guest has bus master disabled, but is @@ -726,7 +739,7 @@ void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev) proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD; } - virtio_bind_device(vdev, &virtio_pci_bindings, proxy); + virtio_bind_device(vdev, &virtio_pci_bindings, DEVICE(proxy)); proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY; proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE; proxy->host_features = vdev->get_features(vdev, proxy->host_features); diff --git a/hw/virtio.c b/hw/virtio.c index 0455a9e8f3..77b53a9c21 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -935,7 +935,7 @@ VirtIODevice *virtio_common_init(const char *name, uint16_t device_id, } void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding, - void *opaque) + DeviceState *opaque) { vdev->binding = binding; vdev->binding_opaque = opaque; diff --git a/hw/virtio.h b/hw/virtio.h index 541600484e..1dec9dce07 100644 --- a/hw/virtio.h +++ b/hw/virtio.h @@ -91,17 +91,17 @@ typedef struct VirtQueueElement } VirtQueueElement; typedef struct { - void (*notify)(void * opaque, uint16_t vector); - void (*save_config)(void * opaque, QEMUFile *f); - void (*save_queue)(void * opaque, int n, QEMUFile *f); - int (*load_config)(void * opaque, QEMUFile *f); - int (*load_queue)(void * opaque, int n, QEMUFile *f); - int (*load_done)(void * opaque, QEMUFile *f); - unsigned (*get_features)(void * opaque); - bool (*query_guest_notifiers)(void * opaque); - int (*set_guest_notifiers)(void * opaque, bool assigned); - int (*set_host_notifier)(void * opaque, int n, bool assigned); - void (*vmstate_change)(void * opaque, bool running); + void (*notify)(DeviceState *d, uint16_t vector); + void (*save_config)(DeviceState *d, QEMUFile *f); + void (*save_queue)(DeviceState *d, int n, QEMUFile *f); + int (*load_config)(DeviceState *d, QEMUFile *f); + int (*load_queue)(DeviceState *d, int n, QEMUFile *f); + int (*load_done)(DeviceState *d, QEMUFile *f); + unsigned (*get_features)(DeviceState *d); + bool (*query_guest_notifiers)(DeviceState *d); + int (*set_guest_notifiers)(DeviceState *d, bool assigned); + int (*set_host_notifier)(DeviceState *d, int n, bool assigned); + void (*vmstate_change)(DeviceState *d, bool running); } VirtIOBindings; #define VIRTIO_PCI_QUEUE_MAX 64 @@ -128,7 +128,7 @@ struct VirtIODevice void (*set_status)(VirtIODevice *vdev, uint8_t val); VirtQueue *vq; const VirtIOBindings *binding; - void *binding_opaque; + DeviceState *binding_opaque; uint16_t device_id; bool vm_running; VMChangeStateEntry *vmstate; @@ -191,7 +191,7 @@ void virtio_update_irq(VirtIODevice *vdev); int virtio_set_features(VirtIODevice *vdev, uint32_t val); void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding, - void *opaque); + DeviceState *opaque); /* Base devices. */ typedef struct VirtIOBlkConf VirtIOBlkConf; From 244eaa7514a944b36273eb8428f32da8e9124fcf Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 12 Dec 2012 12:54:43 +0100 Subject: [PATCH 2087/2270] migration: fix migration_bitmap leak Cc: qemu-stable@nongnu.org Signed-off-by: Paolo Bonzini Signed-off-by: Juan Quintela --- arch_init.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/arch_init.c b/arch_init.c index a8b65416da..e01f0e5ea1 100644 --- a/arch_init.c +++ b/arch_init.c @@ -535,9 +535,13 @@ static void sort_ram_list(void) static void migration_end(void) { - memory_global_dirty_log_stop(); + if (migration_bitmap) { + memory_global_dirty_log_stop(); + g_free(migration_bitmap); + migration_bitmap = NULL; + } - if (migrate_use_xbzrle()) { + if (XBZRLE.cache) { cache_fini(XBZRLE.cache); g_free(XBZRLE.cache); g_free(XBZRLE.encoded_buf); @@ -689,13 +693,10 @@ static int ram_save_complete(QEMUFile *f, void *opaque) } bytes_transferred += bytes_sent; } - memory_global_dirty_log_stop(); + migration_end(); qemu_put_be64(f, RAM_SAVE_FLAG_EOS); - g_free(migration_bitmap); - migration_bitmap = NULL; - return 0; } From bde54c08b4854aceee3dee25121a2b835cb81166 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 20 Nov 2012 12:48:19 +0100 Subject: [PATCH 2088/2270] buffered_file: do not send more than s->bytes_xfer bytes per tick Sending more was possible if the buffer was large. Cc: qemu-stable@nongnu.org Signed-off-by: Paolo Bonzini Signed-off-by: Juan Quintela --- buffered_file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 27627a1b71..1de47e04a8 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -65,9 +65,9 @@ static ssize_t buffered_flush(QEMUFileBuffered *s) DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size); while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) { - + size_t to_send = MIN(s->buffer_size - offset, s->xfer_limit - s->bytes_xfer); ret = migrate_fd_put_buffer(s->migration_state, s->buffer + offset, - s->buffer_size - offset); + to_send); if (ret == -EAGAIN) { DPRINTF("backend not ready, freezing\n"); ret = 0; From 24ea1e4b4b79cef2bac6f8e0f0a212f42ef420a9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 10 Nov 2012 18:58:40 +0100 Subject: [PATCH 2089/2270] migration: remove double call to migrate_fd_close The call in buffered_close is enough, because buffered_close is called already by migrate_fd_cleanup. Signed-off-by: Paolo Bonzini Signed-off-by: Juan Quintela --- migration.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migration.c b/migration.c index 810f25e7eb..e560930977 100644 --- a/migration.c +++ b/migration.c @@ -272,7 +272,7 @@ static int migrate_fd_cleanup(MigrationState *s) s->file = NULL; } - migrate_fd_close(s); + assert(s->fd == -1); return ret; } From 557ec5a001740d234e2b9604f0697a0d52ae90ca Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 3 Oct 2012 14:07:31 +0200 Subject: [PATCH 2090/2270] migration: include qemu-file.h They don't use/know anything about buffered-file. Signed-off-by: Juan Quintela --- migration-exec.c | 2 +- migration-fd.c | 2 +- migration-tcp.c | 2 +- migration-unix.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/migration-exec.c b/migration-exec.c index 68f36f41f1..b7b760b1d4 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -18,7 +18,7 @@ #include "qemu-common.h" #include "qemu/sockets.h" #include "migration/migration.h" -#include "buffered_file.h" +#include "migration/qemu-file.h" #include "block/block.h" #include #include diff --git a/migration-fd.c b/migration-fd.c index ea121bc0d6..c45c42e9d3 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -17,7 +17,7 @@ #include "qemu/sockets.h" #include "migration/migration.h" #include "monitor/monitor.h" -#include "buffered_file.h" +#include "migration/qemu-file.h" #include "block/block.h" #include "qemu/sockets.h" diff --git a/migration-tcp.c b/migration-tcp.c index 3c4c315052..1fca42843e 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -16,7 +16,7 @@ #include "qemu-common.h" #include "qemu/sockets.h" #include "migration/migration.h" -#include "buffered_file.h" +#include "migration/qemu-file.h" #include "block/block.h" //#define DEBUG_MIGRATION_TCP diff --git a/migration-unix.c b/migration-unix.c index d5f986853f..f2f368c528 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -16,7 +16,7 @@ #include "qemu-common.h" #include "qemu/sockets.h" #include "migration/migration.h" -#include "buffered_file.h" +#include "migration/qemu-file.h" #include "block/block.h" //#define DEBUG_MIGRATION_UNIX From 803ef03257a9ee375f08ca7a89e009ea12bc17a4 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 3 Oct 2012 14:08:05 +0200 Subject: [PATCH 2091/2270] migration-fd: remove duplicate include Signed-off-by: Juan Quintela --- migration-fd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/migration-fd.c b/migration-fd.c index c45c42e9d3..5086a9038a 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -19,7 +19,6 @@ #include "monitor/monitor.h" #include "migration/qemu-file.h" #include "block/block.h" -#include "qemu/sockets.h" //#define DEBUG_MIGRATION_FD From 0d6d3c87a232cc27641dde3491d75c8021745d02 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 14 Nov 2012 15:45:02 +0100 Subject: [PATCH 2092/2270] exec: change ramlist from MRU order to a 1-item cache Most of the time, only 2 items will be active (from/to for a string operation, or code/data). But TCG guests likely won't have gigabytes of memory, so this actually goes down to 1 item. Signed-off-by: Paolo Bonzini Signed-off-by: Juan Quintela --- arch_init.c | 1 + exec.c | 49 ++++++++++++++++++++++++------------------ include/exec/cpu-all.h | 1 + 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/arch_init.c b/arch_init.c index e01f0e5ea1..6695ccfdc5 100644 --- a/arch_init.c +++ b/arch_init.c @@ -48,6 +48,7 @@ #include "qemu/config-file.h" #include "qmp-commands.h" #include "trace.h" +#include "exec/cpu-all.h" #ifdef DEBUG_ARCH_INIT #define DPRINTF(fmt, ...) \ diff --git a/exec.c b/exec.c index 28abd7e710..78bae1c7ac 100644 --- a/exec.c +++ b/exec.c @@ -43,6 +43,7 @@ #include "sysemu/xen-mapcache.h" #include "trace.h" #endif +#include "exec/cpu-all.h" #include "exec/cputlb.h" #include "translate-all.h" @@ -1043,6 +1044,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, new_block->length = size; QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next); + ram_list.mru_block = NULL; ram_list.phys_dirty = g_realloc(ram_list.phys_dirty, last_ram_offset() >> TARGET_PAGE_BITS); @@ -1071,6 +1073,7 @@ void qemu_ram_free_from_ptr(ram_addr_t addr) QLIST_FOREACH(block, &ram_list.blocks, next) { if (addr == block->offset) { QLIST_REMOVE(block, next); + ram_list.mru_block = NULL; g_free(block); return; } @@ -1084,6 +1087,7 @@ void qemu_ram_free(ram_addr_t addr) QLIST_FOREACH(block, &ram_list.blocks, next) { if (addr == block->offset) { QLIST_REMOVE(block, next); + ram_list.mru_block = NULL; if (block->flags & RAM_PREALLOC_MASK) { ; } else if (mem_path) { @@ -1189,37 +1193,40 @@ void *qemu_get_ram_ptr(ram_addr_t addr) { RAMBlock *block; + block = ram_list.mru_block; + if (block && addr - block->offset < block->length) { + goto found; + } QLIST_FOREACH(block, &ram_list.blocks, next) { if (addr - block->offset < block->length) { - /* Move this entry to to start of the list. */ - if (block != QLIST_FIRST(&ram_list.blocks)) { - QLIST_REMOVE(block, next); - QLIST_INSERT_HEAD(&ram_list.blocks, block, next); - } - if (xen_enabled()) { - /* We need to check if the requested address is in the RAM - * because we don't want to map the entire memory in QEMU. - * In that case just map until the end of the page. - */ - if (block->offset == 0) { - return xen_map_cache(addr, 0, 0); - } else if (block->host == NULL) { - block->host = - xen_map_cache(block->offset, block->length, 1); - } - } - return block->host + (addr - block->offset); + goto found; } } fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr); abort(); - return NULL; +found: + ram_list.mru_block = block; + if (xen_enabled()) { + /* We need to check if the requested address is in the RAM + * because we don't want to map the entire memory in QEMU. + * In that case just map until the end of the page. + */ + if (block->offset == 0) { + return xen_map_cache(addr, 0, 0); + } else if (block->host == NULL) { + block->host = + xen_map_cache(block->offset, block->length, 1); + } + } + return block->host + (addr - block->offset); } -/* Return a host pointer to ram allocated with qemu_ram_alloc. - * Same as qemu_get_ram_ptr but avoid reordering ramblocks. +/* Return a host pointer to ram allocated with qemu_ram_alloc. Same as + * qemu_get_ram_ptr but do not touch ram_list.mru_block. + * + * ??? Is this still necessary? */ static void *qemu_safe_ram_ptr(ram_addr_t addr) { diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index c12e35f54d..9fe6fc0751 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -495,6 +495,7 @@ typedef struct RAMBlock { typedef struct RAMList { uint8_t *phys_dirty; + RAMBlock *mru_block; QLIST_HEAD(, RAMBlock) blocks; } RAMList; extern RAMList ram_list; From a3161038a1fd17a638a0c606f71e1f799f65f41b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 14 Nov 2012 15:54:48 +0100 Subject: [PATCH 2093/2270] exec: change RAM list to a TAILQ Signed-off-by: Paolo Bonzini Signed-off-by: Juan Quintela --- arch_init.c | 24 ++++++++++++------------ dump.c | 8 ++++---- exec.c | 34 +++++++++++++++++----------------- include/exec/cpu-all.h | 4 ++-- memory_mapping.c | 4 ++-- target-i386/arch_dump.c | 2 +- 6 files changed, 38 insertions(+), 38 deletions(-) diff --git a/arch_init.c b/arch_init.c index 6695ccfdc5..67b14d24c1 100644 --- a/arch_init.c +++ b/arch_init.c @@ -382,7 +382,7 @@ static void migration_bitmap_sync(void) trace_migration_bitmap_sync_start(); memory_global_sync_dirty_bitmap(get_system_memory()); - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) { if (memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE, DIRTY_MEMORY_MIGRATION)) { @@ -424,7 +424,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage) ram_addr_t current_addr; if (!block) - block = QLIST_FIRST(&ram_list.blocks); + block = QTAILQ_FIRST(&ram_list.blocks); do { mr = block->mr; @@ -465,9 +465,9 @@ static int ram_save_block(QEMUFile *f, bool last_stage) offset += TARGET_PAGE_SIZE; if (offset >= block->length) { offset = 0; - block = QLIST_NEXT(block, next); + block = QTAILQ_NEXT(block, next); if (!block) - block = QLIST_FIRST(&ram_list.blocks); + block = QTAILQ_FIRST(&ram_list.blocks); } } while (block != last_block || offset != last_offset); @@ -499,7 +499,7 @@ uint64_t ram_bytes_total(void) RAMBlock *block; uint64_t total = 0; - QLIST_FOREACH(block, &ram_list.blocks, next) + QTAILQ_FOREACH(block, &ram_list.blocks, next) total += block->length; return total; @@ -518,18 +518,18 @@ static void sort_ram_list(void) RAMBlock *block, *nblock, **blocks; int n; n = 0; - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { ++n; } blocks = g_malloc(n * sizeof *blocks); n = 0; - QLIST_FOREACH_SAFE(block, &ram_list.blocks, next, nblock) { + QTAILQ_FOREACH_SAFE(block, &ram_list.blocks, next, nblock) { blocks[n++] = block; - QLIST_REMOVE(block, next); + QTAILQ_REMOVE(&ram_list.blocks, block, next); } qsort(blocks, n, sizeof *blocks, block_compar); while (--n >= 0) { - QLIST_INSERT_HEAD(&ram_list.blocks, blocks[n], next); + QTAILQ_INSERT_HEAD(&ram_list.blocks, blocks[n], next); } g_free(blocks); } @@ -597,7 +597,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE); - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { qemu_put_byte(f, strlen(block->idstr)); qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr)); qemu_put_be64(f, block->length); @@ -763,7 +763,7 @@ static inline void *host_from_stream_offset(QEMUFile *f, qemu_get_buffer(f, (uint8_t *)id, len); id[len] = 0; - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (!strncmp(id, block->idstr, sizeof(id))) return memory_region_get_ram_ptr(block->mr) + offset; } @@ -807,7 +807,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) id[len] = 0; length = qemu_get_be64(f); - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (!strncmp(id, block->idstr, sizeof(id))) { if (block->length != length) { ret = -EINVAL; diff --git a/dump.c b/dump.c index a26b1a5e1a..4ed1fa8622 100644 --- a/dump.c +++ b/dump.c @@ -427,7 +427,7 @@ static hwaddr get_offset(hwaddr phys_addr, } } - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (s->has_filter) { if (block->offset >= s->begin + s->length || block->offset + block->length <= s->begin) { @@ -594,7 +594,7 @@ static int dump_completed(DumpState *s) static int get_next_block(DumpState *s, RAMBlock *block) { while (1) { - block = QLIST_NEXT(block, next); + block = QTAILQ_NEXT(block, next); if (!block) { /* no more block */ return 1; @@ -670,11 +670,11 @@ static ram_addr_t get_start_block(DumpState *s) RAMBlock *block; if (!s->has_filter) { - s->block = QLIST_FIRST(&ram_list.blocks); + s->block = QTAILQ_FIRST(&ram_list.blocks); return 0; } - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (block->offset >= s->begin + s->length || block->offset + block->length <= s->begin) { /* This block is out of the range */ diff --git a/exec.c b/exec.c index 78bae1c7ac..584279a2e3 100644 --- a/exec.c +++ b/exec.c @@ -57,7 +57,7 @@ int phys_ram_fd; static int in_migration; -RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks) }; +RAMList ram_list = { .blocks = QTAILQ_HEAD_INITIALIZER(ram_list.blocks) }; static MemoryRegion *system_memory; static MemoryRegion *system_io; @@ -902,15 +902,15 @@ static ram_addr_t find_ram_offset(ram_addr_t size) RAMBlock *block, *next_block; ram_addr_t offset = RAM_ADDR_MAX, mingap = RAM_ADDR_MAX; - if (QLIST_EMPTY(&ram_list.blocks)) + if (QTAILQ_EMPTY(&ram_list.blocks)) return 0; - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { ram_addr_t end, next = RAM_ADDR_MAX; end = block->offset + block->length; - QLIST_FOREACH(next_block, &ram_list.blocks, next) { + QTAILQ_FOREACH(next_block, &ram_list.blocks, next) { if (next_block->offset >= end) { next = MIN(next, next_block->offset); } @@ -935,7 +935,7 @@ ram_addr_t last_ram_offset(void) RAMBlock *block; ram_addr_t last = 0; - QLIST_FOREACH(block, &ram_list.blocks, next) + QTAILQ_FOREACH(block, &ram_list.blocks, next) last = MAX(last, block->offset + block->length); return last; @@ -964,7 +964,7 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) RAMBlock *new_block, *block; new_block = NULL; - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (block->offset == addr) { new_block = block; break; @@ -982,7 +982,7 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) } pstrcat(new_block->idstr, sizeof(new_block->idstr), name); - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (block != new_block && !strcmp(block->idstr, new_block->idstr)) { fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n", new_block->idstr); @@ -1043,7 +1043,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, } new_block->length = size; - QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next); + QTAILQ_INSERT_HEAD(&ram_list.blocks, new_block, next); ram_list.mru_block = NULL; ram_list.phys_dirty = g_realloc(ram_list.phys_dirty, @@ -1070,9 +1070,9 @@ void qemu_ram_free_from_ptr(ram_addr_t addr) { RAMBlock *block; - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (addr == block->offset) { - QLIST_REMOVE(block, next); + QTAILQ_REMOVE(&ram_list.blocks, block, next); ram_list.mru_block = NULL; g_free(block); return; @@ -1084,9 +1084,9 @@ void qemu_ram_free(ram_addr_t addr) { RAMBlock *block; - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (addr == block->offset) { - QLIST_REMOVE(block, next); + QTAILQ_REMOVE(&ram_list.blocks, block, next); ram_list.mru_block = NULL; if (block->flags & RAM_PREALLOC_MASK) { ; @@ -1127,7 +1127,7 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) int flags; void *area, *vaddr; - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { offset = addr - block->offset; if (offset < block->length) { vaddr = block->host + offset; @@ -1197,7 +1197,7 @@ void *qemu_get_ram_ptr(ram_addr_t addr) if (block && addr - block->offset < block->length) { goto found; } - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (addr - block->offset < block->length) { goto found; } @@ -1232,7 +1232,7 @@ static void *qemu_safe_ram_ptr(ram_addr_t addr) { RAMBlock *block; - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (addr - block->offset < block->length) { if (xen_enabled()) { /* We need to check if the requested address is in the RAM @@ -1268,7 +1268,7 @@ static void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size) } else { RAMBlock *block; - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (addr - block->offset < block->length) { if (addr - block->offset + *size > block->length) *size = block->length - addr + block->offset; @@ -1296,7 +1296,7 @@ int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr) return 0; } - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { /* This case append when the block is not mapped. */ if (block->host == NULL) { continue; diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 9fe6fc0751..612e95005b 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -487,7 +487,7 @@ typedef struct RAMBlock { ram_addr_t length; uint32_t flags; char idstr[256]; - QLIST_ENTRY(RAMBlock) next; + QTAILQ_ENTRY(RAMBlock) next; #if defined(__linux__) && !defined(TARGET_S390X) int fd; #endif @@ -496,7 +496,7 @@ typedef struct RAMBlock { typedef struct RAMList { uint8_t *phys_dirty; RAMBlock *mru_block; - QLIST_HEAD(, RAMBlock) blocks; + QTAILQ_HEAD(, RAMBlock) blocks; } RAMList; extern RAMList ram_list; diff --git a/memory_mapping.c b/memory_mapping.c index 530f1d6793..ff45b3a239 100644 --- a/memory_mapping.c +++ b/memory_mapping.c @@ -200,7 +200,7 @@ int qemu_get_guest_memory_mapping(MemoryMappingList *list) * If the guest doesn't use paging, the virtual address is equal to physical * address. */ - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { offset = block->offset; length = block->length; create_new_memory_mapping(list, offset, offset, length); @@ -213,7 +213,7 @@ void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list) { RAMBlock *block; - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { create_new_memory_mapping(list, block->offset, 0, block->length); } } diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c index 8209ce9ee2..2cd2f7f09e 100644 --- a/target-i386/arch_dump.c +++ b/target-i386/arch_dump.c @@ -403,7 +403,7 @@ int cpu_get_dump_info(ArchDumpInfo *info) } else { info->d_class = ELFCLASS32; - QLIST_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (block->offset + block->length > UINT_MAX) { /* The memory size is greater than 4G */ info->d_class = ELFCLASS64; From abb26d63e7e4492d306c13b7e0e799d4c11a067c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 14 Nov 2012 16:00:51 +0100 Subject: [PATCH 2094/2270] exec: sort the memory from biggest to smallest Signed-off-by: Paolo Bonzini Signed-off-by: Juan Quintela --- arch_init.c | 30 ------------------------------ exec.c | 14 ++++++++++++-- 2 files changed, 12 insertions(+), 32 deletions(-) diff --git a/arch_init.c b/arch_init.c index 67b14d24c1..5c8df3af41 100644 --- a/arch_init.c +++ b/arch_init.c @@ -505,35 +505,6 @@ uint64_t ram_bytes_total(void) return total; } -static int block_compar(const void *a, const void *b) -{ - RAMBlock * const *ablock = a; - RAMBlock * const *bblock = b; - - return strcmp((*ablock)->idstr, (*bblock)->idstr); -} - -static void sort_ram_list(void) -{ - RAMBlock *block, *nblock, **blocks; - int n; - n = 0; - QTAILQ_FOREACH(block, &ram_list.blocks, next) { - ++n; - } - blocks = g_malloc(n * sizeof *blocks); - n = 0; - QTAILQ_FOREACH_SAFE(block, &ram_list.blocks, next, nblock) { - blocks[n++] = block; - QTAILQ_REMOVE(&ram_list.blocks, block, next); - } - qsort(blocks, n, sizeof *blocks, block_compar); - while (--n >= 0) { - QTAILQ_INSERT_HEAD(&ram_list.blocks, blocks[n], next); - } - g_free(blocks); -} - static void migration_end(void) { if (migration_bitmap) { @@ -562,7 +533,6 @@ static void reset_ram_globals(void) { last_block = NULL; last_offset = 0; - sort_ram_list(); } #define MAX_WAIT 50 /* ms, half buffered_file limit */ diff --git a/exec.c b/exec.c index 584279a2e3..1ee4fa649d 100644 --- a/exec.c +++ b/exec.c @@ -1007,7 +1007,7 @@ static int memory_try_enable_merging(void *addr, size_t len) ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, MemoryRegion *mr) { - RAMBlock *new_block; + RAMBlock *block, *new_block; size = TARGET_PAGE_ALIGN(size); new_block = g_malloc0(sizeof(*new_block)); @@ -1043,7 +1043,17 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, } new_block->length = size; - QTAILQ_INSERT_HEAD(&ram_list.blocks, new_block, next); + /* Keep the list sorted from biggest to smallest block. */ + QTAILQ_FOREACH(block, &ram_list.blocks, next) { + if (block->length < new_block->length) { + break; + } + } + if (block) { + QTAILQ_INSERT_BEFORE(block, new_block, next); + } else { + QTAILQ_INSERT_TAIL(&ram_list.blocks, new_block, next); + } ram_list.mru_block = NULL; ram_list.phys_dirty = g_realloc(ram_list.phys_dirty, From f798b07f517143df3a1e38bccc3f72ade2f080dc Mon Sep 17 00:00:00 2001 From: Umesh Deshpande Date: Thu, 18 Aug 2011 11:41:17 -0700 Subject: [PATCH 2095/2270] add a version number to ram_list This will be used to detect if last_block might have become invalid across different calls to ram_save_live. Signed-off-by: Paolo Bonzini Signed-off-by: Umesh Deshpande Signed-off-by: Juan Quintela Reviewed-by: Orit Wasserman --- arch_init.c | 7 ++++++- exec.c | 4 ++++ include/exec/cpu-all.h | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch_init.c b/arch_init.c index 5c8df3af41..1f737dc1eb 100644 --- a/arch_init.c +++ b/arch_init.c @@ -336,6 +336,7 @@ static RAMBlock *last_block; static ram_addr_t last_offset; static unsigned long *migration_bitmap; static uint64_t migration_dirty_pages; +static uint32_t last_version; static inline bool migration_bitmap_test_and_reset_dirty(MemoryRegion *mr, ram_addr_t offset) @@ -406,7 +407,6 @@ static void migration_bitmap_sync(void) } } - /* * ram_save_block: Writes a page of memory to the stream f * @@ -533,6 +533,7 @@ static void reset_ram_globals(void) { last_block = NULL; last_offset = 0; + last_version = ram_list.version; } #define MAX_WAIT 50 /* ms, half buffered_file limit */ @@ -587,6 +588,10 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) uint64_t expected_downtime; MigrationState *s = migrate_get_current(); + if (ram_list.version != last_version) { + reset_ram_globals(); + } + bytes_transferred_last = bytes_transferred; bwidth = qemu_get_clock_ns(rt_clock); diff --git a/exec.c b/exec.c index 1ee4fa649d..8478bef548 100644 --- a/exec.c +++ b/exec.c @@ -1056,6 +1056,8 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, } ram_list.mru_block = NULL; + ram_list.version++; + ram_list.phys_dirty = g_realloc(ram_list.phys_dirty, last_ram_offset() >> TARGET_PAGE_BITS); memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS), @@ -1084,6 +1086,7 @@ void qemu_ram_free_from_ptr(ram_addr_t addr) if (addr == block->offset) { QTAILQ_REMOVE(&ram_list.blocks, block, next); ram_list.mru_block = NULL; + ram_list.version++; g_free(block); return; } @@ -1098,6 +1101,7 @@ void qemu_ram_free(ram_addr_t addr) if (addr == block->offset) { QTAILQ_REMOVE(&ram_list.blocks, block, next); ram_list.mru_block = NULL; + ram_list.version++; if (block->flags & RAM_PREALLOC_MASK) { ; } else if (mem_path) { diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 612e95005b..f052b38974 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -497,6 +497,7 @@ typedef struct RAMList { uint8_t *phys_dirty; RAMBlock *mru_block; QTAILQ_HEAD(, RAMBlock) blocks; + uint32_t version; } RAMList; extern RAMList ram_list; From b2a8658ef5dc57ea9e7a45091724a719dd4bdcd3 Mon Sep 17 00:00:00 2001 From: Umesh Deshpande Date: Wed, 17 Aug 2011 00:01:33 -0700 Subject: [PATCH 2096/2270] protect the ramlist with a separate mutex Add the new mutex that protects shared state between ram_save_live and the iothread. If the iothread mutex has to be taken together with the ramlist mutex, the iothread shall always be _outside_. Signed-off-by: Paolo Bonzini Signed-off-by: Umesh Deshpande Signed-off-by: Juan Quintela Reviewed-by: Orit Wasserman --- arch_init.c | 9 ++++++++- exec.c | 29 +++++++++++++++++++++++++++-- include/exec/cpu-all.h | 9 +++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/arch_init.c b/arch_init.c index 1f737dc1eb..fad1c4099a 100644 --- a/arch_init.c +++ b/arch_init.c @@ -528,7 +528,6 @@ static void ram_migration_cancel(void *opaque) migration_end(); } - static void reset_ram_globals(void) { last_block = NULL; @@ -547,6 +546,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) bitmap_set(migration_bitmap, 0, ram_pages); migration_dirty_pages = ram_pages; + qemu_mutex_lock_ramlist(); bytes_transferred = 0; reset_ram_globals(); @@ -574,6 +574,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) qemu_put_be64(f, block->length); } + qemu_mutex_unlock_ramlist(); qemu_put_be64(f, RAM_SAVE_FLAG_EOS); return 0; @@ -588,6 +589,8 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) uint64_t expected_downtime; MigrationState *s = migrate_get_current(); + qemu_mutex_lock_ramlist(); + if (ram_list.version != last_version) { reset_ram_globals(); } @@ -636,6 +639,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) bwidth = 0.000001; } + qemu_mutex_unlock_ramlist(); qemu_put_be64(f, RAM_SAVE_FLAG_EOS); expected_downtime = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth; @@ -656,6 +660,8 @@ static int ram_save_complete(QEMUFile *f, void *opaque) { migration_bitmap_sync(); + qemu_mutex_lock_ramlist(); + /* try transferring iterative blocks of memory */ /* flush all remaining blocks regardless of rate limiting */ @@ -671,6 +677,7 @@ static int ram_save_complete(QEMUFile *f, void *opaque) } migration_end(); + qemu_mutex_unlock_ramlist(); qemu_put_be64(f, RAM_SAVE_FLAG_EOS); return 0; diff --git a/exec.c b/exec.c index 8478bef548..a6923addd4 100644 --- a/exec.c +++ b/exec.c @@ -213,6 +213,7 @@ bool memory_region_is_unassigned(MemoryRegion *mr) void cpu_exec_init_all(void) { #if !defined(CONFIG_USER_ONLY) + qemu_mutex_init(&ram_list.mutex); memory_map_init(); io_mem_init(); #endif @@ -801,6 +802,16 @@ void qemu_flush_coalesced_mmio_buffer(void) kvm_flush_coalesced_mmio_buffer(); } +void qemu_mutex_lock_ramlist(void) +{ + qemu_mutex_lock(&ram_list.mutex); +} + +void qemu_mutex_unlock_ramlist(void) +{ + qemu_mutex_unlock(&ram_list.mutex); +} + #if defined(__linux__) && !defined(TARGET_S390X) #include @@ -982,6 +993,8 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) } pstrcat(new_block->idstr, sizeof(new_block->idstr), name); + /* This assumes the iothread lock is taken here too. */ + qemu_mutex_lock_ramlist(); QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (block != new_block && !strcmp(block->idstr, new_block->idstr)) { fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n", @@ -989,6 +1002,7 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) abort(); } } + qemu_mutex_unlock_ramlist(); } static int memory_try_enable_merging(void *addr, size_t len) @@ -1012,6 +1026,8 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, size = TARGET_PAGE_ALIGN(size); new_block = g_malloc0(sizeof(*new_block)); + /* This assumes the iothread lock is taken here too. */ + qemu_mutex_lock_ramlist(); new_block->mr = mr; new_block->offset = find_ram_offset(size); if (host) { @@ -1057,6 +1073,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, ram_list.mru_block = NULL; ram_list.version++; + qemu_mutex_unlock_ramlist(); ram_list.phys_dirty = g_realloc(ram_list.phys_dirty, last_ram_offset() >> TARGET_PAGE_BITS); @@ -1082,21 +1099,26 @@ void qemu_ram_free_from_ptr(ram_addr_t addr) { RAMBlock *block; + /* This assumes the iothread lock is taken here too. */ + qemu_mutex_lock_ramlist(); QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (addr == block->offset) { QTAILQ_REMOVE(&ram_list.blocks, block, next); ram_list.mru_block = NULL; ram_list.version++; g_free(block); - return; + break; } } + qemu_mutex_unlock_ramlist(); } void qemu_ram_free(ram_addr_t addr) { RAMBlock *block; + /* This assumes the iothread lock is taken here too. */ + qemu_mutex_lock_ramlist(); QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (addr == block->offset) { QTAILQ_REMOVE(&ram_list.blocks, block, next); @@ -1127,9 +1149,10 @@ void qemu_ram_free(ram_addr_t addr) #endif } g_free(block); - return; + break; } } + qemu_mutex_unlock_ramlist(); } @@ -1207,6 +1230,7 @@ void *qemu_get_ram_ptr(ram_addr_t addr) { RAMBlock *block; + /* The list is protected by the iothread lock here. */ block = ram_list.mru_block; if (block && addr - block->offset < block->length) { goto found; @@ -1246,6 +1270,7 @@ static void *qemu_safe_ram_ptr(ram_addr_t addr) { RAMBlock *block; + /* The list is protected by the iothread lock here. */ QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (addr - block->offset < block->length) { if (xen_enabled()) { diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index f052b38974..439e88deb4 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -22,6 +22,7 @@ #include "qemu-common.h" #include "qemu/tls.h" #include "exec/cpu-common.h" +#include "qemu/thread.h" /* some important defines: * @@ -487,6 +488,9 @@ typedef struct RAMBlock { ram_addr_t length; uint32_t flags; char idstr[256]; + /* Reads can take either the iothread or the ramlist lock. + * Writes must take both locks. + */ QTAILQ_ENTRY(RAMBlock) next; #if defined(__linux__) && !defined(TARGET_S390X) int fd; @@ -494,8 +498,11 @@ typedef struct RAMBlock { } RAMBlock; typedef struct RAMList { + QemuMutex mutex; + /* Protected by the iothread lock. */ uint8_t *phys_dirty; RAMBlock *mru_block; + /* Protected by the ramlist lock. */ QTAILQ_HEAD(, RAMBlock) blocks; uint32_t version; } RAMList; @@ -516,6 +523,8 @@ extern int mem_prealloc; void dump_exec_info(FILE *f, fprintf_function cpu_fprintf); ram_addr_t last_ram_offset(void); +void qemu_mutex_lock_ramlist(void); +void qemu_mutex_unlock_ramlist(void); #endif /* !CONFIG_USER_ONLY */ int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr, From c09f4cb2b3243085a86aee3c7ed4f31c77e4db87 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 23 Jul 2012 01:56:50 +0200 Subject: [PATCH 2097/2270] buffered_file: Move from using a timer to use a thread We still protect everything except the wait with the iothread lock. But we moved from a timer to a thread. Steps one by one. We also need to detect when we have finished with a variable "complete". Signed-off-by: Juan Quintela --- buffered_file.c | 58 ++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 1de47e04a8..70590997d5 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -17,6 +17,7 @@ #include "hw/hw.h" #include "qemu/timer.h" #include "buffered_file.h" +#include "qemu/thread.h" //#define DEBUG_BUFFERED_FILE @@ -30,7 +31,8 @@ typedef struct QEMUFileBuffered uint8_t *buffer; size_t buffer_size; size_t buffer_capacity; - QEMUTimer *timer; + QemuThread thread; + bool complete; } QEMUFileBuffered; #ifdef DEBUG_BUFFERED_FILE @@ -159,11 +161,8 @@ static int buffered_close(void *opaque) if (ret >= 0) { ret = ret2; } - qemu_del_timer(s->timer); - qemu_free_timer(s->timer); - g_free(s->buffer); - g_free(s); - + ret = migrate_fd_close(s->migration_state); + s->complete = true; return ret; } @@ -221,23 +220,38 @@ static int64_t buffered_get_rate_limit(void *opaque) return s->xfer_limit; } -static void buffered_rate_tick(void *opaque) +/* 10ms xfer_limit is the limit that we should write each 10ms */ +#define BUFFER_DELAY 100 + +static void *buffered_file_thread(void *opaque) { QEMUFileBuffered *s = opaque; + int64_t expire_time = qemu_get_clock_ms(rt_clock) + BUFFER_DELAY; - if (qemu_file_get_error(s->file)) { - buffered_close(s); - return; + while (true) { + int64_t current_time = qemu_get_clock_ms(rt_clock); + + if (s->complete) { + break; + } + if (s->freeze_output) { + continue; + } + if (current_time >= expire_time) { + s->bytes_xfer = 0; + expire_time = current_time + BUFFER_DELAY; + } + if (s->bytes_xfer >= s->xfer_limit) { + /* usleep expects microseconds */ + g_usleep((expire_time - current_time)*1000); + } + qemu_mutex_lock_iothread(); + buffered_put_buffer(s, NULL, 0, 0); + qemu_mutex_unlock_iothread(); } - - qemu_mod_timer(s->timer, qemu_get_clock_ms(rt_clock) + 100); - - if (s->freeze_output) - return; - - s->bytes_xfer = 0; - - buffered_put_buffer(s, NULL, 0, 0); + g_free(s->buffer); + g_free(s); + return NULL; } static const QEMUFileOps buffered_file_ops = { @@ -257,12 +271,12 @@ QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state) s->migration_state = migration_state; s->xfer_limit = migration_state->bandwidth_limit / 10; + s->complete = false; s->file = qemu_fopen_ops(s, &buffered_file_ops); - s->timer = qemu_new_timer_ms(rt_clock, buffered_rate_tick, s); - - qemu_mod_timer(s->timer, qemu_get_clock_ms(rt_clock) + 100); + qemu_thread_create(&s->thread, buffered_file_thread, s, + QEMU_THREAD_DETACHED); return s->file; } From edfa1af52f4c69264c5a0c38da10eb372077fba3 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 23 Jul 2012 02:13:23 +0200 Subject: [PATCH 2098/2270] migration: make qemu_fopen_ops_buffered() return void We want the file assignment to happen before the thread is created to avoid locking, so we just do it before creating the thread. Signed-off-by: Juan Quintela Reviewed-by: Orit Wasserman --- buffered_file.c | 13 ++++++------- buffered_file.h | 2 +- include/migration/migration.h | 1 + migration.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 70590997d5..d61892b9e8 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -32,7 +32,6 @@ typedef struct QEMUFileBuffered size_t buffer_size; size_t buffer_capacity; QemuThread thread; - bool complete; } QEMUFileBuffered; #ifdef DEBUG_BUFFERED_FILE @@ -162,7 +161,7 @@ static int buffered_close(void *opaque) ret = ret2; } ret = migrate_fd_close(s->migration_state); - s->complete = true; + s->migration_state->complete = true; return ret; } @@ -231,7 +230,7 @@ static void *buffered_file_thread(void *opaque) while (true) { int64_t current_time = qemu_get_clock_ms(rt_clock); - if (s->complete) { + if (s->migration_state->complete) { break; } if (s->freeze_output) { @@ -263,7 +262,7 @@ static const QEMUFileOps buffered_file_ops = { .set_rate_limit = buffered_set_rate_limit, }; -QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state) +void qemu_fopen_ops_buffered(MigrationState *migration_state) { QEMUFileBuffered *s; @@ -271,12 +270,12 @@ QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state) s->migration_state = migration_state; s->xfer_limit = migration_state->bandwidth_limit / 10; - s->complete = false; + s->migration_state->complete = false; s->file = qemu_fopen_ops(s, &buffered_file_ops); + migration_state->file = s->file; + qemu_thread_create(&s->thread, buffered_file_thread, s, QEMU_THREAD_DETACHED); - - return s->file; } diff --git a/buffered_file.h b/buffered_file.h index 86a7075246..d278f3d951 100644 --- a/buffered_file.h +++ b/buffered_file.h @@ -17,6 +17,6 @@ #include "hw/hw.h" #include "migration/migration.h" -QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state); +void qemu_fopen_ops_buffered(MigrationState *migration_state); #endif diff --git a/include/migration/migration.h b/include/migration/migration.h index 8b7af61e7e..fa1fb8f4cd 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -45,6 +45,7 @@ struct MigrationState int64_t dirty_pages_rate; bool enabled_capabilities[MIGRATION_CAPABILITY_MAX]; int64_t xbzrle_cache_size; + bool complete; }; void process_incoming_migration(QEMUFile *f); diff --git a/migration.c b/migration.c index e560930977..5450c3b3e7 100644 --- a/migration.c +++ b/migration.c @@ -448,7 +448,7 @@ void migrate_fd_connect(MigrationState *s) int ret; s->state = MIG_STATE_ACTIVE; - s->file = qemu_fopen_ops_buffered(s); + qemu_fopen_ops_buffered(s); DPRINTF("beginning savevm\n"); ret = qemu_savevm_state_begin(s->file, &s->params); From 766bd1769e70835e0cc25f3f057f101619494b59 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 23 Jul 2012 05:45:29 +0200 Subject: [PATCH 2099/2270] migration: move migration thread init code to migrate_fd_put_ready This way everything related with migration is run on the migration thread and no locking is needed. Signed-off-by: Juan Quintela --- include/migration/migration.h | 1 + migration.c | 29 +++++++++++++++++------------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/include/migration/migration.h b/include/migration/migration.h index fa1fb8f4cd..0ce3720112 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -46,6 +46,7 @@ struct MigrationState bool enabled_capabilities[MIGRATION_CAPABILITY_MAX]; int64_t xbzrle_cache_size; bool complete; + bool first_time; }; void process_incoming_migration(QEMUFile *f); diff --git a/migration.c b/migration.c index 5450c3b3e7..249eea389d 100644 --- a/migration.c +++ b/migration.c @@ -21,6 +21,7 @@ #include "block/block.h" #include "qemu/sockets.h" #include "migration/block.h" +#include "qemu/thread.h" #include "qmp-commands.h" //#define DEBUG_MIGRATION @@ -339,6 +340,16 @@ void migrate_fd_put_ready(MigrationState *s) DPRINTF("put_ready returning because of non-active state\n"); return; } + if (s->first_time) { + s->first_time = false; + DPRINTF("beginning savevm\n"); + ret = qemu_savevm_state_begin(s->file, &s->params); + if (ret < 0) { + DPRINTF("failed, %d\n", ret); + migrate_fd_error(s); + return; + } + } DPRINTF("iterate\n"); ret = qemu_savevm_state_iterate(s->file); @@ -351,7 +362,11 @@ void migrate_fd_put_ready(MigrationState *s) DPRINTF("done iterating\n"); start_time = qemu_get_clock_ms(rt_clock); qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); - vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); + if (old_vm_running) { + vm_stop(RUN_STATE_FINISH_MIGRATE); + } else { + vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); + } if (qemu_savevm_state_complete(s->file) < 0) { migrate_fd_error(s); @@ -445,19 +460,9 @@ bool migration_has_failed(MigrationState *s) void migrate_fd_connect(MigrationState *s) { - int ret; - s->state = MIG_STATE_ACTIVE; + s->first_time = true; qemu_fopen_ops_buffered(s); - - DPRINTF("beginning savevm\n"); - ret = qemu_savevm_state_begin(s->file, &s->params); - if (ret < 0) { - DPRINTF("failed, %d\n", ret); - migrate_fd_error(s); - return; - } - migrate_fd_put_ready(s); } static MigrationState *migrate_init(const MigrationParams *params) From dd217b8732b93d97c22fa70dc15a72d92a2b2380 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 23 Jul 2012 06:15:02 +0200 Subject: [PATCH 2100/2270] migration: make writes blocking Move all the writes to the migration_thread, and make writings blocking. Notice that are still using the iothread for everything that we do. Signed-off-by: Juan Quintela --- include/migration/qemu-file.h | 5 ----- migration-exec.c | 1 - migration-fd.c | 1 - migration-tcp.c | 1 + migration-unix.c | 1 + migration.c | 17 ----------------- savevm.c | 5 ----- 7 files changed, 2 insertions(+), 29 deletions(-) diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h index d64bdbb19b..68deefbcfb 100644 --- a/include/migration/qemu-file.h +++ b/include/migration/qemu-file.h @@ -113,11 +113,6 @@ int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate); int64_t qemu_file_get_rate_limit(QEMUFile *f); int qemu_file_get_error(QEMUFile *f); -/* Try to send any outstanding data. This function is useful when output is - * halted due to rate limiting or EAGAIN errors occur as it can be used to - * resume output. */ -int qemu_file_put_notify(QEMUFile *f); - static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv) { qemu_put_be64(f, *pv); diff --git a/migration-exec.c b/migration-exec.c index b7b760b1d4..a051a6e668 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -69,7 +69,6 @@ void exec_start_outgoing_migration(MigrationState *s, const char *command, Error s->fd = fileno(f); assert(s->fd != -1); - socket_set_nonblock(s->fd); s->opaque = qemu_popen(f, "w"); diff --git a/migration-fd.c b/migration-fd.c index 5086a9038a..a99e0e3971 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -75,7 +75,6 @@ void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error ** return; } - fcntl(s->fd, F_SETFL, O_NONBLOCK); s->get_error = fd_errno; s->write = fd_write; s->close = fd_close; diff --git a/migration-tcp.c b/migration-tcp.c index 1fca42843e..e78a296137 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -60,6 +60,7 @@ static void tcp_wait_for_connect(int fd, void *opaque) } else { DPRINTF("migrate connect success\n"); s->fd = fd; + socket_set_block(s->fd); migrate_fd_connect(s); } } diff --git a/migration-unix.c b/migration-unix.c index f2f368c528..218835a7a4 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -60,6 +60,7 @@ static void unix_wait_for_connect(int fd, void *opaque) } else { DPRINTF("migrate connect success\n"); s->fd = fd; + socket_set_block(s->fd); migrate_fd_connect(s); } } diff --git a/migration.c b/migration.c index 249eea389d..207c754e52 100644 --- a/migration.c +++ b/migration.c @@ -297,18 +297,6 @@ static void migrate_fd_completed(MigrationState *s) notifier_list_notify(&migration_state_notifiers, s); } -static void migrate_fd_put_notify(void *opaque) -{ - MigrationState *s = opaque; - int ret; - - qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); - ret = qemu_file_put_notify(s->file); - if (ret) { - migrate_fd_error(s); - } -} - ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data, size_t size) { @@ -325,10 +313,6 @@ ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data, if (ret == -1) ret = -(s->get_error(s)); - if (ret == -EAGAIN) { - qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s); - } - return ret; } @@ -425,7 +409,6 @@ int migrate_fd_close(MigrationState *s) { int rc = 0; if (s->fd != -1) { - qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); rc = s->close(s); s->fd = -1; } diff --git a/savevm.c b/savevm.c index b2a844f2b1..c93d0b4fde 100644 --- a/savevm.c +++ b/savevm.c @@ -555,11 +555,6 @@ int qemu_fclose(QEMUFile *f) return ret; } -int qemu_file_put_notify(QEMUFile *f) -{ - return f->ops->put_buffer(f->opaque, NULL, 0, 0); -} - void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) { int l; From 188a428559f0cd0bde884d28b42e449abd744c2f Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 23 Jul 2012 06:24:03 +0200 Subject: [PATCH 2101/2270] migration: remove unfreeze logic Now that we have a thread, and blocking writes, we don't need it. Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- buffered_file.c | 24 +----------------------- include/migration/migration.h | 1 - migration.c | 23 ----------------------- 3 files changed, 1 insertion(+), 47 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index d61892b9e8..14e3a6fb73 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -25,7 +25,6 @@ typedef struct QEMUFileBuffered { MigrationState *migration_state; QEMUFile *file; - int freeze_output; size_t bytes_xfer; size_t xfer_limit; uint8_t *buffer; @@ -69,13 +68,6 @@ static ssize_t buffered_flush(QEMUFileBuffered *s) size_t to_send = MIN(s->buffer_size - offset, s->xfer_limit - s->bytes_xfer); ret = migrate_fd_put_buffer(s->migration_state, s->buffer + offset, to_send); - if (ret == -EAGAIN) { - DPRINTF("backend not ready, freezing\n"); - ret = 0; - s->freeze_output = 1; - break; - } - if (ret <= 0) { DPRINTF("error flushing data, %zd\n", ret); break; @@ -109,9 +101,6 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in return error; } - DPRINTF("unfreezing output\n"); - s->freeze_output = 0; - if (size > 0) { DPRINTF("buffering %d bytes\n", size - offset); buffered_append(s, buf, size); @@ -125,7 +114,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in if (pos == 0 && size == 0) { DPRINTF("file is ready\n"); - if (!s->freeze_output && s->bytes_xfer < s->xfer_limit) { + if (s->bytes_xfer < s->xfer_limit) { DPRINTF("notifying client\n"); migrate_fd_put_ready(s->migration_state); } @@ -148,12 +137,6 @@ static int buffered_close(void *opaque) if (ret < 0) { break; } - if (s->freeze_output) { - ret = migrate_fd_wait_for_unfreeze(s->migration_state); - if (ret < 0) { - break; - } - } } ret2 = migrate_fd_close(s->migration_state); @@ -187,8 +170,6 @@ static int buffered_rate_limit(void *opaque) if (ret) { return ret; } - if (s->freeze_output) - return 1; if (s->bytes_xfer > s->xfer_limit) return 1; @@ -233,9 +214,6 @@ static void *buffered_file_thread(void *opaque) if (s->migration_state->complete) { break; } - if (s->freeze_output) { - continue; - } if (current_time >= expire_time) { s->bytes_xfer = 0; expire_time = current_time + BUFFER_DELAY; diff --git a/include/migration/migration.h b/include/migration/migration.h index 0ce3720112..92190f2afd 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -82,7 +82,6 @@ void migrate_fd_connect(MigrationState *s); ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data, size_t size); void migrate_fd_put_ready(MigrationState *s); -int migrate_fd_wait_for_unfreeze(MigrationState *s); int migrate_fd_close(MigrationState *s); void add_migration_state_change_notifier(Notifier *notify); diff --git a/migration.c b/migration.c index 207c754e52..032c9c254f 100644 --- a/migration.c +++ b/migration.c @@ -382,29 +382,6 @@ static void migrate_fd_cancel(MigrationState *s) migrate_fd_cleanup(s); } -int migrate_fd_wait_for_unfreeze(MigrationState *s) -{ - int ret; - - DPRINTF("wait for unfreeze\n"); - if (s->state != MIG_STATE_ACTIVE) - return -EINVAL; - - do { - fd_set wfds; - - FD_ZERO(&wfds); - FD_SET(s->fd, &wfds); - - ret = select(s->fd + 1, NULL, &wfds, NULL, NULL); - } while (ret == -1 && (s->get_error(s)) == EINTR); - - if (ret == -1) { - return -s->get_error(s); - } - return 0; -} - int migrate_fd_close(MigrationState *s) { int rc = 0; From e76274824defce54a124e5104be3880044c698e1 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 23 Jul 2012 06:31:30 +0200 Subject: [PATCH 2102/2270] migration: just lock migrate_fd_put_ready Signed-off-by: Juan Quintela --- buffered_file.c | 2 -- migration.c | 5 +++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 14e3a6fb73..7743fbdbca 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -222,9 +222,7 @@ static void *buffered_file_thread(void *opaque) /* usleep expects microseconds */ g_usleep((expire_time - current_time)*1000); } - qemu_mutex_lock_iothread(); buffered_put_buffer(s, NULL, 0, 0); - qemu_mutex_unlock_iothread(); } g_free(s->buffer); g_free(s); diff --git a/migration.c b/migration.c index 032c9c254f..11123bcea0 100644 --- a/migration.c +++ b/migration.c @@ -320,8 +320,10 @@ void migrate_fd_put_ready(MigrationState *s) { int ret; + qemu_mutex_lock_iothread(); if (s->state != MIG_STATE_ACTIVE) { DPRINTF("put_ready returning because of non-active state\n"); + qemu_mutex_unlock_iothread(); return; } if (s->first_time) { @@ -331,6 +333,7 @@ void migrate_fd_put_ready(MigrationState *s) if (ret < 0) { DPRINTF("failed, %d\n", ret); migrate_fd_error(s); + qemu_mutex_unlock_iothread(); return; } } @@ -366,6 +369,8 @@ void migrate_fd_put_ready(MigrationState *s) } } } + qemu_mutex_unlock_iothread(); + } static void migrate_fd_cancel(MigrationState *s) From 78d1d231f889f7eae3835ddaec4373011792e46f Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 24 Jul 2012 13:22:18 +0200 Subject: [PATCH 2103/2270] buffered_file: Unfold the trick to restart generating migration data This was needed before due to the way that the callbacks worked. Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- buffered_file.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 7743fbdbca..d61d805de7 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -112,14 +112,6 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in return error; } - if (pos == 0 && size == 0) { - DPRINTF("file is ready\n"); - if (s->bytes_xfer < s->xfer_limit) { - DPRINTF("notifying client\n"); - migrate_fd_put_ready(s->migration_state); - } - } - return size; } @@ -222,8 +214,17 @@ static void *buffered_file_thread(void *opaque) /* usleep expects microseconds */ g_usleep((expire_time - current_time)*1000); } - buffered_put_buffer(s, NULL, 0, 0); + if (buffered_flush(s) < 0) { + break; + } + + DPRINTF("file is ready\n"); + if (s->bytes_xfer < s->xfer_limit) { + DPRINTF("notifying client\n"); + migrate_fd_put_ready(s->migration_state); + } } + g_free(s->buffer); g_free(s); return NULL; From c518dd841deb85b3ccf77ff93e1142b27b06af32 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 24 Jul 2012 14:00:13 +0200 Subject: [PATCH 2104/2270] buffered_file: don't flush on put buffer We call buffered_put_buffer with iothread held, and buffered_flush() does synchronous writes. We only want to do the synchronous writes outside. Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- buffered_file.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index d61d805de7..1d7fa2443d 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -106,12 +106,6 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in buffered_append(s, buf, size); } - error = buffered_flush(s); - if (error < 0) { - DPRINTF("buffered flush error. bailing: %s\n", strerror(-error)); - return error; - } - return size; } From f50b4986b261fc10065289d2a03deba24d824988 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 24 Jul 2012 14:24:08 +0200 Subject: [PATCH 2105/2270] buffered_file: unfold buffered_append in buffered_put_buffer It was the only user, and now buffered_put_buffer just do the append Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- buffered_file.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 1d7fa2443d..be9424b543 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -41,22 +41,6 @@ typedef struct QEMUFileBuffered do { } while (0) #endif -static void buffered_append(QEMUFileBuffered *s, - const uint8_t *buf, size_t size) -{ - if (size > (s->buffer_capacity - s->buffer_size)) { - DPRINTF("increasing buffer capacity from %zu by %zu\n", - s->buffer_capacity, size + 1024); - - s->buffer_capacity += size + 1024; - - s->buffer = g_realloc(s->buffer, s->buffer_capacity); - } - - memcpy(s->buffer + s->buffer_size, buf, size); - s->buffer_size += size; -} - static ssize_t buffered_flush(QEMUFileBuffered *s) { size_t offset = 0; @@ -101,11 +85,22 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in return error; } - if (size > 0) { - DPRINTF("buffering %d bytes\n", size - offset); - buffered_append(s, buf, size); + if (size <= 0) { + return size; } + if (size > (s->buffer_capacity - s->buffer_size)) { + DPRINTF("increasing buffer capacity from %zu by %zu\n", + s->buffer_capacity, size + 1024); + + s->buffer_capacity += size + 1024; + + s->buffer = g_realloc(s->buffer, s->buffer_capacity); + } + + memcpy(s->buffer + s->buffer_size, buf, size); + s->buffer_size += size; + return size; } From e4ed1541ac9413eac494a03532e34beaf8a7d1c5 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 21 Sep 2012 11:18:18 +0200 Subject: [PATCH 2106/2270] savevm: New save live migration method: pending Code just now does (simplified for clarity) if (qemu_savevm_state_iterate(s->file) == 1) { vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); qemu_savevm_state_complete(s->file); } Problem here is that qemu_savevm_state_iterate() returns 1 when it knows that remaining memory to sent takes less than max downtime. But this means that we could end spending 2x max_downtime, one downtime in qemu_savevm_iterate, and the other in qemu_savevm_state_complete. Changed code to: pending_size = qemu_savevm_state_pending(s->file, max_size); DPRINTF("pending size %lu max %lu\n", pending_size, max_size); if (pending_size >= max_size) { ret = qemu_savevm_state_iterate(s->file); } else { vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); qemu_savevm_state_complete(s->file); } So what we do is: at current network speed, we calculate the maximum number of bytes we can sent: max_size. Then we ask every save_live section how much they have pending. If they are less than max_size, we move to complete phase, otherwise we do an iterate one. This makes things much simpler, because now individual sections don't have to caluclate the bandwidth (it was implossible to do right from there). Signed-off-by: Juan Quintela Reviewed-by: Paolo Bonzini --- arch_init.c | 48 +++++++++++++--------------------- block-migration.c | 49 +++++++---------------------------- buffered_file.c | 25 +++++++++++++----- include/migration/migration.h | 2 +- include/migration/vmstate.h | 1 + include/sysemu/sysemu.h | 1 + migration.c | 22 +++++++++++----- savevm.c | 19 ++++++++++++++ 8 files changed, 83 insertions(+), 84 deletions(-) diff --git a/arch_init.c b/arch_init.c index fad1c4099a..af1ae9f72a 100644 --- a/arch_init.c +++ b/arch_init.c @@ -582,12 +582,9 @@ static int ram_save_setup(QEMUFile *f, void *opaque) static int ram_save_iterate(QEMUFile *f, void *opaque) { - uint64_t bytes_transferred_last; - double bwidth = 0; int ret; int i; - uint64_t expected_downtime; - MigrationState *s = migrate_get_current(); + int64_t t0; qemu_mutex_lock_ramlist(); @@ -595,9 +592,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) reset_ram_globals(); } - bytes_transferred_last = bytes_transferred; - bwidth = qemu_get_clock_ns(rt_clock); - + t0 = qemu_get_clock_ns(rt_clock); i = 0; while ((ret = qemu_file_rate_limit(f)) == 0) { int bytes_sent; @@ -615,7 +610,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) iterations */ if ((i & 63) == 0) { - uint64_t t1 = (qemu_get_clock_ns(rt_clock) - bwidth) / 1000000; + uint64_t t1 = (qemu_get_clock_ns(rt_clock) - t0) / 1000000; if (t1 > MAX_WAIT) { DPRINTF("big wait: %" PRIu64 " milliseconds, %d iterations\n", t1, i); @@ -629,31 +624,10 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) return ret; } - bwidth = qemu_get_clock_ns(rt_clock) - bwidth; - bwidth = (bytes_transferred - bytes_transferred_last) / bwidth; - - /* if we haven't transferred anything this round, force - * expected_downtime to a very high value, but without - * crashing */ - if (bwidth == 0) { - bwidth = 0.000001; - } - qemu_mutex_unlock_ramlist(); qemu_put_be64(f, RAM_SAVE_FLAG_EOS); - expected_downtime = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth; - DPRINTF("ram_save_live: expected(%" PRIu64 ") <= max(" PRIu64 ")?\n", - expected_downtime, migrate_max_downtime()); - - if (expected_downtime <= migrate_max_downtime()) { - migration_bitmap_sync(); - expected_downtime = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth; - s->expected_downtime = expected_downtime / 1000000; /* ns -> ms */ - - return expected_downtime <= migrate_max_downtime(); - } - return 0; + return i; } static int ram_save_complete(QEMUFile *f, void *opaque) @@ -683,6 +657,19 @@ static int ram_save_complete(QEMUFile *f, void *opaque) return 0; } +static uint64_t ram_save_pending(QEMUFile *f, void *opaque, uint64_t max_size) +{ + uint64_t remaining_size; + + remaining_size = ram_save_remaining() * TARGET_PAGE_SIZE; + + if (remaining_size < max_size) { + migration_bitmap_sync(); + remaining_size = ram_save_remaining() * TARGET_PAGE_SIZE; + } + return remaining_size; +} + static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host) { int ret, rc = 0; @@ -869,6 +856,7 @@ SaveVMHandlers savevm_ram_handlers = { .save_live_setup = ram_save_setup, .save_live_iterate = ram_save_iterate, .save_live_complete = ram_save_complete, + .save_live_pending = ram_save_pending, .load_state = ram_load, .cancel = ram_migration_cancel, }; diff --git a/block-migration.c b/block-migration.c index ca4ba3fffb..6acf3e1682 100644 --- a/block-migration.c +++ b/block-migration.c @@ -77,9 +77,7 @@ typedef struct BlkMigState { int64_t total_sector_sum; int prev_progress; int bulk_completed; - long double total_time; long double prev_time_offset; - int reads; } BlkMigState; static BlkMigState block_mig_state; @@ -132,12 +130,6 @@ uint64_t blk_mig_bytes_total(void) return sum << BDRV_SECTOR_BITS; } -static inline long double compute_read_bwidth(void) -{ - assert(block_mig_state.total_time != 0); - return (block_mig_state.reads / block_mig_state.total_time) * BLOCK_SIZE; -} - static int bmds_aio_inflight(BlkMigDevState *bmds, int64_t sector) { int64_t chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK; @@ -191,8 +183,6 @@ static void blk_mig_read_cb(void *opaque, int ret) blk->ret = ret; - block_mig_state.reads++; - block_mig_state.total_time += (curr_time - block_mig_state.prev_time_offset); block_mig_state.prev_time_offset = curr_time; QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry); @@ -310,8 +300,6 @@ static void init_blk_migration(QEMUFile *f) block_mig_state.total_sector_sum = 0; block_mig_state.prev_progress = -1; block_mig_state.bulk_completed = 0; - block_mig_state.total_time = 0; - block_mig_state.reads = 0; bdrv_iterate(init_blk_migration_it, NULL); } @@ -493,32 +481,6 @@ static int64_t get_remaining_dirty(void) return dirty * BLOCK_SIZE; } -static int is_stage2_completed(void) -{ - int64_t remaining_dirty; - long double bwidth; - - if (block_mig_state.bulk_completed == 1) { - - remaining_dirty = get_remaining_dirty(); - if (remaining_dirty == 0) { - return 1; - } - - bwidth = compute_read_bwidth(); - - if ((remaining_dirty / bwidth) <= - migrate_max_downtime()) { - /* finish stage2 because we think that we can finish remaining work - below max_downtime */ - - return 1; - } - } - - return 0; -} - static void blk_mig_cleanup(void) { BlkMigDevState *bmds; @@ -619,7 +581,7 @@ static int block_save_iterate(QEMUFile *f, void *opaque) qemu_put_be64(f, BLK_MIG_FLAG_EOS); - return is_stage2_completed(); + return 0; } static int block_save_complete(QEMUFile *f, void *opaque) @@ -659,6 +621,14 @@ static int block_save_complete(QEMUFile *f, void *opaque) return 0; } +static uint64_t block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size) +{ + + DPRINTF("Enter save live pending %ld\n", get_remaining_dirty()); + + return get_remaining_dirty(); +} + static int block_load(QEMUFile *f, void *opaque, int version_id) { static int banner_printed; @@ -755,6 +725,7 @@ SaveVMHandlers savevm_block_handlers = { .save_live_setup = block_save_setup, .save_live_iterate = block_save_iterate, .save_live_complete = block_save_complete, + .save_live_pending = block_save_pending, .load_state = block_load, .cancel = block_migration_cancel, .is_active = block_is_active, diff --git a/buffered_file.c b/buffered_file.c index be9424b543..fdf7efa964 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -181,13 +181,15 @@ static int64_t buffered_get_rate_limit(void *opaque) return s->xfer_limit; } -/* 10ms xfer_limit is the limit that we should write each 10ms */ +/* 100ms xfer_limit is the limit that we should write each 100ms */ #define BUFFER_DELAY 100 static void *buffered_file_thread(void *opaque) { QEMUFileBuffered *s = opaque; - int64_t expire_time = qemu_get_clock_ms(rt_clock) + BUFFER_DELAY; + int64_t initial_time = qemu_get_clock_ms(rt_clock); + int64_t max_size = 0; + bool last_round = false; while (true) { int64_t current_time = qemu_get_clock_ms(rt_clock); @@ -195,13 +197,22 @@ static void *buffered_file_thread(void *opaque) if (s->migration_state->complete) { break; } - if (current_time >= expire_time) { + if (current_time >= initial_time + BUFFER_DELAY) { + uint64_t transferred_bytes = s->bytes_xfer; + uint64_t time_spent = current_time - initial_time; + double bandwidth = transferred_bytes / time_spent; + max_size = bandwidth * migrate_max_downtime() / 1000000; + + DPRINTF("transferred %" PRIu64 " time_spent %" PRIu64 + " bandwidth %g max_size %" PRId64 "\n", + transferred_bytes, time_spent, bandwidth, max_size); + s->bytes_xfer = 0; - expire_time = current_time + BUFFER_DELAY; + initial_time = current_time; } - if (s->bytes_xfer >= s->xfer_limit) { + if (!last_round && (s->bytes_xfer >= s->xfer_limit)) { /* usleep expects microseconds */ - g_usleep((expire_time - current_time)*1000); + g_usleep((initial_time + BUFFER_DELAY - current_time)*1000); } if (buffered_flush(s) < 0) { break; @@ -210,7 +221,7 @@ static void *buffered_file_thread(void *opaque) DPRINTF("file is ready\n"); if (s->bytes_xfer < s->xfer_limit) { DPRINTF("notifying client\n"); - migrate_fd_put_ready(s->migration_state); + last_round = migrate_fd_put_ready(s->migration_state, max_size); } } diff --git a/include/migration/migration.h b/include/migration/migration.h index 92190f2afd..9571ec532c 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -81,7 +81,7 @@ void migrate_fd_connect(MigrationState *s); ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data, size_t size); -void migrate_fd_put_ready(MigrationState *s); +bool migrate_fd_put_ready(MigrationState *s, uint64_t max_size); int migrate_fd_close(MigrationState *s); void add_migration_state_change_notifier(Notifier *notify); diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index 623af0a29a..f27276c2d8 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -35,6 +35,7 @@ typedef struct SaveVMHandlers { int (*save_live_setup)(QEMUFile *f, void *opaque); int (*save_live_iterate)(QEMUFile *f, void *opaque); int (*save_live_complete)(QEMUFile *f, void *opaque); + uint64_t (*save_live_pending)(QEMUFile *f, void *opaque, uint64_t max_size); void (*cancel)(void *opaque); LoadStateHandler *load_state; bool (*is_active)(void *opaque); diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 8eaa4707a0..28a783e2be 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -78,6 +78,7 @@ int qemu_savevm_state_begin(QEMUFile *f, int qemu_savevm_state_iterate(QEMUFile *f); int qemu_savevm_state_complete(QEMUFile *f); void qemu_savevm_state_cancel(QEMUFile *f); +uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size); int qemu_loadvm_state(QEMUFile *f); /* SLIRP */ diff --git a/migration.c b/migration.c index 11123bcea0..b6374ae072 100644 --- a/migration.c +++ b/migration.c @@ -316,15 +316,17 @@ ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data, return ret; } -void migrate_fd_put_ready(MigrationState *s) +bool migrate_fd_put_ready(MigrationState *s, uint64_t max_size) { int ret; + uint64_t pending_size; + bool last_round = false; qemu_mutex_lock_iothread(); if (s->state != MIG_STATE_ACTIVE) { DPRINTF("put_ready returning because of non-active state\n"); qemu_mutex_unlock_iothread(); - return; + return false; } if (s->first_time) { s->first_time = false; @@ -334,15 +336,19 @@ void migrate_fd_put_ready(MigrationState *s) DPRINTF("failed, %d\n", ret); migrate_fd_error(s); qemu_mutex_unlock_iothread(); - return; + return false; } } DPRINTF("iterate\n"); - ret = qemu_savevm_state_iterate(s->file); - if (ret < 0) { - migrate_fd_error(s); - } else if (ret == 1) { + pending_size = qemu_savevm_state_pending(s->file, max_size); + DPRINTF("pending size %lu max %lu\n", pending_size, max_size); + if (pending_size >= max_size) { + ret = qemu_savevm_state_iterate(s->file); + if (ret < 0) { + migrate_fd_error(s); + } + } else { int old_vm_running = runstate_is_running(); int64_t start_time, end_time; @@ -368,9 +374,11 @@ void migrate_fd_put_ready(MigrationState *s) vm_start(); } } + last_round = true; } qemu_mutex_unlock_iothread(); + return last_round; } static void migrate_fd_cancel(MigrationState *s) diff --git a/savevm.c b/savevm.c index c93d0b4fde..bcdb92ee81 100644 --- a/savevm.c +++ b/savevm.c @@ -1753,6 +1753,25 @@ int qemu_savevm_state_complete(QEMUFile *f) return qemu_file_get_error(f); } +uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size) +{ + SaveStateEntry *se; + uint64_t ret = 0; + + QTAILQ_FOREACH(se, &savevm_handlers, entry) { + if (!se->ops || !se->ops->save_live_pending) { + continue; + } + if (se->ops && se->ops->is_active) { + if (!se->ops->is_active(se->opaque)) { + continue; + } + } + ret += se->ops->save_live_pending(f, se->opaque, max_size); + } + return ret; +} + void qemu_savevm_state_cancel(QEMUFile *f) { SaveStateEntry *se; From 0d82d0e8b98cf0ea03a45f8542d835ebd3a84cd3 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 3 Oct 2012 14:18:33 +0200 Subject: [PATCH 2107/2270] migration: move buffered_file.c code into migration.c This only moves the code (also from buffered_file.h to migration.h). Fix whitespace until checkpatch is happy. Signed-off-by: Juan Quintela --- Makefile.objs | 3 +- buffered_file.c | 258 ---------------------------------- buffered_file.h | 22 --- include/migration/migration.h | 1 + migration.c | 233 +++++++++++++++++++++++++++++- 5 files changed, 235 insertions(+), 282 deletions(-) delete mode 100644 buffered_file.c delete mode 100644 buffered_file.h diff --git a/Makefile.objs b/Makefile.objs index a637a4a8f0..4ef0a718d2 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -77,7 +77,8 @@ common-obj-$(CONFIG_LINUX) += fsdev/ extra-obj-$(CONFIG_LINUX) += fsdev/ common-obj-y += tcg-runtime.o host-utils.o main-loop.o -common-obj-y += buffered_file.o migration.o migration-tcp.o +common-obj-y += migration.o migration-tcp.o +common-obj-y += migration.o migration-tcp.o common-obj-y += qemu-char.o #aio.o common-obj-y += block-migration.o iohandler.o common-obj-y += bitmap.o bitops.o diff --git a/buffered_file.c b/buffered_file.c deleted file mode 100644 index fdf7efa964..0000000000 --- a/buffered_file.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * QEMU buffered QEMUFile - * - * Copyright IBM, Corp. 2008 - * - * Authors: - * Anthony Liguori - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ - -#include "qemu-common.h" -#include "hw/hw.h" -#include "qemu/timer.h" -#include "buffered_file.h" -#include "qemu/thread.h" - -//#define DEBUG_BUFFERED_FILE - -typedef struct QEMUFileBuffered -{ - MigrationState *migration_state; - QEMUFile *file; - size_t bytes_xfer; - size_t xfer_limit; - uint8_t *buffer; - size_t buffer_size; - size_t buffer_capacity; - QemuThread thread; -} QEMUFileBuffered; - -#ifdef DEBUG_BUFFERED_FILE -#define DPRINTF(fmt, ...) \ - do { printf("buffered-file: " fmt, ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) \ - do { } while (0) -#endif - -static ssize_t buffered_flush(QEMUFileBuffered *s) -{ - size_t offset = 0; - ssize_t ret = 0; - - DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size); - - while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) { - size_t to_send = MIN(s->buffer_size - offset, s->xfer_limit - s->bytes_xfer); - ret = migrate_fd_put_buffer(s->migration_state, s->buffer + offset, - to_send); - if (ret <= 0) { - DPRINTF("error flushing data, %zd\n", ret); - break; - } else { - DPRINTF("flushed %zd byte(s)\n", ret); - offset += ret; - s->bytes_xfer += ret; - } - } - - DPRINTF("flushed %zu of %zu byte(s)\n", offset, s->buffer_size); - memmove(s->buffer, s->buffer + offset, s->buffer_size - offset); - s->buffer_size -= offset; - - if (ret < 0) { - return ret; - } - return offset; -} - -static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size) -{ - QEMUFileBuffered *s = opaque; - ssize_t error; - - DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos); - - error = qemu_file_get_error(s->file); - if (error) { - DPRINTF("flush when error, bailing: %s\n", strerror(-error)); - return error; - } - - if (size <= 0) { - return size; - } - - if (size > (s->buffer_capacity - s->buffer_size)) { - DPRINTF("increasing buffer capacity from %zu by %zu\n", - s->buffer_capacity, size + 1024); - - s->buffer_capacity += size + 1024; - - s->buffer = g_realloc(s->buffer, s->buffer_capacity); - } - - memcpy(s->buffer + s->buffer_size, buf, size); - s->buffer_size += size; - - return size; -} - -static int buffered_close(void *opaque) -{ - QEMUFileBuffered *s = opaque; - ssize_t ret = 0; - int ret2; - - DPRINTF("closing\n"); - - s->xfer_limit = INT_MAX; - while (!qemu_file_get_error(s->file) && s->buffer_size) { - ret = buffered_flush(s); - if (ret < 0) { - break; - } - } - - ret2 = migrate_fd_close(s->migration_state); - if (ret >= 0) { - ret = ret2; - } - ret = migrate_fd_close(s->migration_state); - s->migration_state->complete = true; - return ret; -} - -/* - * The meaning of the return values is: - * 0: We can continue sending - * 1: Time to stop - * negative: There has been an error - */ -static int buffered_get_fd(void *opaque) -{ - QEMUFileBuffered *s = opaque; - - return qemu_get_fd(s->file); -} - -static int buffered_rate_limit(void *opaque) -{ - QEMUFileBuffered *s = opaque; - int ret; - - ret = qemu_file_get_error(s->file); - if (ret) { - return ret; - } - - if (s->bytes_xfer > s->xfer_limit) - return 1; - - return 0; -} - -static int64_t buffered_set_rate_limit(void *opaque, int64_t new_rate) -{ - QEMUFileBuffered *s = opaque; - if (qemu_file_get_error(s->file)) { - goto out; - } - if (new_rate > SIZE_MAX) { - new_rate = SIZE_MAX; - } - - s->xfer_limit = new_rate / 10; - -out: - return s->xfer_limit; -} - -static int64_t buffered_get_rate_limit(void *opaque) -{ - QEMUFileBuffered *s = opaque; - - return s->xfer_limit; -} - -/* 100ms xfer_limit is the limit that we should write each 100ms */ -#define BUFFER_DELAY 100 - -static void *buffered_file_thread(void *opaque) -{ - QEMUFileBuffered *s = opaque; - int64_t initial_time = qemu_get_clock_ms(rt_clock); - int64_t max_size = 0; - bool last_round = false; - - while (true) { - int64_t current_time = qemu_get_clock_ms(rt_clock); - - if (s->migration_state->complete) { - break; - } - if (current_time >= initial_time + BUFFER_DELAY) { - uint64_t transferred_bytes = s->bytes_xfer; - uint64_t time_spent = current_time - initial_time; - double bandwidth = transferred_bytes / time_spent; - max_size = bandwidth * migrate_max_downtime() / 1000000; - - DPRINTF("transferred %" PRIu64 " time_spent %" PRIu64 - " bandwidth %g max_size %" PRId64 "\n", - transferred_bytes, time_spent, bandwidth, max_size); - - s->bytes_xfer = 0; - initial_time = current_time; - } - if (!last_round && (s->bytes_xfer >= s->xfer_limit)) { - /* usleep expects microseconds */ - g_usleep((initial_time + BUFFER_DELAY - current_time)*1000); - } - if (buffered_flush(s) < 0) { - break; - } - - DPRINTF("file is ready\n"); - if (s->bytes_xfer < s->xfer_limit) { - DPRINTF("notifying client\n"); - last_round = migrate_fd_put_ready(s->migration_state, max_size); - } - } - - g_free(s->buffer); - g_free(s); - return NULL; -} - -static const QEMUFileOps buffered_file_ops = { - .get_fd = buffered_get_fd, - .put_buffer = buffered_put_buffer, - .close = buffered_close, - .rate_limit = buffered_rate_limit, - .get_rate_limit = buffered_get_rate_limit, - .set_rate_limit = buffered_set_rate_limit, -}; - -void qemu_fopen_ops_buffered(MigrationState *migration_state) -{ - QEMUFileBuffered *s; - - s = g_malloc0(sizeof(*s)); - - s->migration_state = migration_state; - s->xfer_limit = migration_state->bandwidth_limit / 10; - s->migration_state->complete = false; - - s->file = qemu_fopen_ops(s, &buffered_file_ops); - - migration_state->file = s->file; - - qemu_thread_create(&s->thread, buffered_file_thread, s, - QEMU_THREAD_DETACHED); -} diff --git a/buffered_file.h b/buffered_file.h deleted file mode 100644 index d278f3d951..0000000000 --- a/buffered_file.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * QEMU buffered QEMUFile - * - * Copyright IBM, Corp. 2008 - * - * Authors: - * Anthony Liguori - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - */ - -#ifndef QEMU_BUFFERED_FILE_H -#define QEMU_BUFFERED_FILE_H - -#include "hw/hw.h" -#include "migration/migration.h" - -void qemu_fopen_ops_buffered(MigrationState *migration_state); - -#endif diff --git a/include/migration/migration.h b/include/migration/migration.h index 9571ec532c..af7de038a9 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -129,4 +129,5 @@ int64_t migrate_xbzrle_cache_size(void); int64_t xbzrle_cache_resize(int64_t new_size); +void qemu_fopen_ops_buffered(MigrationState *migration_state); #endif diff --git a/migration.c b/migration.c index b6374ae072..2937c87f9a 100644 --- a/migration.c +++ b/migration.c @@ -16,7 +16,7 @@ #include "qemu-common.h" #include "migration/migration.h" #include "monitor/monitor.h" -#include "buffered_file.h" +#include "migration/qemu-file.h" #include "sysemu/sysemu.h" #include "block/block.h" #include "qemu/sockets.h" @@ -587,3 +587,234 @@ int64_t migrate_xbzrle_cache_size(void) return s->xbzrle_cache_size; } + +/* migration thread support */ + +typedef struct QEMUFileBuffered { + MigrationState *migration_state; + QEMUFile *file; + size_t bytes_xfer; + size_t xfer_limit; + uint8_t *buffer; + size_t buffer_size; + size_t buffer_capacity; + QemuThread thread; +} QEMUFileBuffered; + +static ssize_t buffered_flush(QEMUFileBuffered *s) +{ + size_t offset = 0; + ssize_t ret = 0; + + DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size); + + while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) { + size_t to_send = MIN(s->buffer_size - offset, s->xfer_limit - s->bytes_xfer); + ret = migrate_fd_put_buffer(s->migration_state, s->buffer + offset, + to_send); + if (ret <= 0) { + DPRINTF("error flushing data, %zd\n", ret); + break; + } else { + DPRINTF("flushed %zd byte(s)\n", ret); + offset += ret; + s->bytes_xfer += ret; + } + } + + DPRINTF("flushed %zu of %zu byte(s)\n", offset, s->buffer_size); + memmove(s->buffer, s->buffer + offset, s->buffer_size - offset); + s->buffer_size -= offset; + + if (ret < 0) { + return ret; + } + return offset; +} + +static int buffered_put_buffer(void *opaque, const uint8_t *buf, + int64_t pos, int size) +{ + QEMUFileBuffered *s = opaque; + ssize_t error; + + DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos); + + error = qemu_file_get_error(s->file); + if (error) { + DPRINTF("flush when error, bailing: %s\n", strerror(-error)); + return error; + } + + if (size <= 0) { + return size; + } + + if (size > (s->buffer_capacity - s->buffer_size)) { + DPRINTF("increasing buffer capacity from %zu by %zu\n", + s->buffer_capacity, size + 1024); + + s->buffer_capacity += size + 1024; + + s->buffer = g_realloc(s->buffer, s->buffer_capacity); + } + + memcpy(s->buffer + s->buffer_size, buf, size); + s->buffer_size += size; + + return size; +} + +static int buffered_close(void *opaque) +{ + QEMUFileBuffered *s = opaque; + ssize_t ret = 0; + int ret2; + + DPRINTF("closing\n"); + + s->xfer_limit = INT_MAX; + while (!qemu_file_get_error(s->file) && s->buffer_size) { + ret = buffered_flush(s); + if (ret < 0) { + break; + } + } + + ret2 = migrate_fd_close(s->migration_state); + if (ret >= 0) { + ret = ret2; + } + ret = migrate_fd_close(s->migration_state); + s->migration_state->complete = true; + return ret; +} + +static int buffered_get_fd(void *opaque) +{ + QEMUFileBuffered *s = opaque; + + return qemu_get_fd(s->file); +} + +/* + * The meaning of the return values is: + * 0: We can continue sending + * 1: Time to stop + * negative: There has been an error + */ +static int buffered_rate_limit(void *opaque) +{ + QEMUFileBuffered *s = opaque; + int ret; + + ret = qemu_file_get_error(s->file); + if (ret) { + return ret; + } + + if (s->bytes_xfer > s->xfer_limit) { + return 1; + } + + return 0; +} + +static int64_t buffered_set_rate_limit(void *opaque, int64_t new_rate) +{ + QEMUFileBuffered *s = opaque; + if (qemu_file_get_error(s->file)) { + goto out; + } + if (new_rate > SIZE_MAX) { + new_rate = SIZE_MAX; + } + + s->xfer_limit = new_rate / 10; + +out: + return s->xfer_limit; +} + +static int64_t buffered_get_rate_limit(void *opaque) +{ + QEMUFileBuffered *s = opaque; + + return s->xfer_limit; +} + +/* 100ms xfer_limit is the limit that we should write each 100ms */ +#define BUFFER_DELAY 100 + +static void *buffered_file_thread(void *opaque) +{ + QEMUFileBuffered *s = opaque; + int64_t initial_time = qemu_get_clock_ms(rt_clock); + int64_t max_size = 0; + bool last_round = false; + + while (true) { + int64_t current_time = qemu_get_clock_ms(rt_clock); + + if (s->migration_state->complete) { + break; + } + if (current_time >= initial_time + BUFFER_DELAY) { + uint64_t transferred_bytes = s->bytes_xfer; + uint64_t time_spent = current_time - initial_time; + double bandwidth = transferred_bytes / time_spent; + max_size = bandwidth * migrate_max_downtime() / 1000000; + + DPRINTF("transferred %" PRIu64 " time_spent %" PRIu64 + " bandwidth %g max_size %" PRId64 "\n", + transferred_bytes, time_spent, bandwidth, max_size); + + s->bytes_xfer = 0; + initial_time = current_time; + } + if (!last_round && (s->bytes_xfer >= s->xfer_limit)) { + /* usleep expects microseconds */ + g_usleep((initial_time + BUFFER_DELAY - current_time)*1000); + } + if (buffered_flush(s) < 0) { + break; + } + + DPRINTF("file is ready\n"); + if (s->bytes_xfer < s->xfer_limit) { + DPRINTF("notifying client\n"); + last_round = migrate_fd_put_ready(s->migration_state, max_size); + } + } + + g_free(s->buffer); + g_free(s); + return NULL; +} + +static const QEMUFileOps buffered_file_ops = { + .get_fd = buffered_get_fd, + .put_buffer = buffered_put_buffer, + .close = buffered_close, + .rate_limit = buffered_rate_limit, + .get_rate_limit = buffered_get_rate_limit, + .set_rate_limit = buffered_set_rate_limit, +}; + +void qemu_fopen_ops_buffered(MigrationState *migration_state) +{ + QEMUFileBuffered *s; + + s = g_malloc0(sizeof(*s)); + + s->migration_state = migration_state; + s->xfer_limit = migration_state->bandwidth_limit / 10; + s->migration_state->complete = false; + + s->file = qemu_fopen_ops(s, &buffered_file_ops); + + migration_state->file = s->file; + + qemu_thread_create(&s->thread, buffered_file_thread, s, + QEMU_THREAD_DETACHED); +} From 5b4e1eb769eee892b44d3f6b2369b05196442f59 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 19 Dec 2012 10:40:48 +0100 Subject: [PATCH 2108/2270] migration: add XFER_LIMIT_RATIO The "magic" divisions by 10 are there because of the value of BUFFER_DELAY. Introduce a constant to explain them better. Signed-off-by: Paolo Bonzini Signed-off-by: Juan Quintela --- migration.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/migration.c b/migration.c index 2937c87f9a..15f22eac40 100644 --- a/migration.c +++ b/migration.c @@ -44,6 +44,11 @@ enum { #define MAX_THROTTLE (32 << 20) /* Migration speed throttling */ +/* Amount of time to allocate to each "chunk" of bandwidth-throttled + * data. */ +#define BUFFER_DELAY 100 +#define XFER_LIMIT_RATIO (1000 / BUFFER_DELAY) + /* Migration XBZRLE default cache size */ #define DEFAULT_MIGRATE_CACHE_SIZE (64 * 1024 * 1024) @@ -743,9 +748,6 @@ static int64_t buffered_get_rate_limit(void *opaque) return s->xfer_limit; } -/* 100ms xfer_limit is the limit that we should write each 100ms */ -#define BUFFER_DELAY 100 - static void *buffered_file_thread(void *opaque) { QEMUFileBuffered *s = opaque; @@ -808,7 +810,7 @@ void qemu_fopen_ops_buffered(MigrationState *migration_state) s = g_malloc0(sizeof(*s)); s->migration_state = migration_state; - s->xfer_limit = migration_state->bandwidth_limit / 10; + s->xfer_limit = s->migration_state->bandwidth_limit / XFER_LIMIT_RATIO; s->migration_state->complete = false; s->file = qemu_fopen_ops(s, &buffered_file_ops); From 0e288fa369c02df1731dc59ffbf158f5e5f2d80f Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 3 Oct 2012 17:23:59 +0200 Subject: [PATCH 2109/2270] migration: move migration_fd_put_ready() Put it near its use and un-export it. Signed-off-by: Juan Quintela --- include/migration/migration.h | 1 - migration.c | 130 +++++++++++++++++----------------- 2 files changed, 65 insertions(+), 66 deletions(-) diff --git a/include/migration/migration.h b/include/migration/migration.h index af7de038a9..2998dcc3b8 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -81,7 +81,6 @@ void migrate_fd_connect(MigrationState *s); ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data, size_t size); -bool migrate_fd_put_ready(MigrationState *s, uint64_t max_size); int migrate_fd_close(MigrationState *s); void add_migration_state_change_notifier(Notifier *notify); diff --git a/migration.c b/migration.c index 15f22eac40..a38720112c 100644 --- a/migration.c +++ b/migration.c @@ -321,71 +321,6 @@ ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data, return ret; } -bool migrate_fd_put_ready(MigrationState *s, uint64_t max_size) -{ - int ret; - uint64_t pending_size; - bool last_round = false; - - qemu_mutex_lock_iothread(); - if (s->state != MIG_STATE_ACTIVE) { - DPRINTF("put_ready returning because of non-active state\n"); - qemu_mutex_unlock_iothread(); - return false; - } - if (s->first_time) { - s->first_time = false; - DPRINTF("beginning savevm\n"); - ret = qemu_savevm_state_begin(s->file, &s->params); - if (ret < 0) { - DPRINTF("failed, %d\n", ret); - migrate_fd_error(s); - qemu_mutex_unlock_iothread(); - return false; - } - } - - DPRINTF("iterate\n"); - pending_size = qemu_savevm_state_pending(s->file, max_size); - DPRINTF("pending size %lu max %lu\n", pending_size, max_size); - if (pending_size >= max_size) { - ret = qemu_savevm_state_iterate(s->file); - if (ret < 0) { - migrate_fd_error(s); - } - } else { - int old_vm_running = runstate_is_running(); - int64_t start_time, end_time; - - DPRINTF("done iterating\n"); - start_time = qemu_get_clock_ms(rt_clock); - qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); - if (old_vm_running) { - vm_stop(RUN_STATE_FINISH_MIGRATE); - } else { - vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); - } - - if (qemu_savevm_state_complete(s->file) < 0) { - migrate_fd_error(s); - } else { - migrate_fd_completed(s); - } - end_time = qemu_get_clock_ms(rt_clock); - s->total_time = end_time - s->total_time; - s->downtime = end_time - start_time; - if (s->state != MIG_STATE_COMPLETED) { - if (old_vm_running) { - vm_start(); - } - } - last_round = true; - } - qemu_mutex_unlock_iothread(); - - return last_round; -} - static void migrate_fd_cancel(MigrationState *s) { if (s->state != MIG_STATE_ACTIVE) @@ -748,6 +683,71 @@ static int64_t buffered_get_rate_limit(void *opaque) return s->xfer_limit; } +static bool migrate_fd_put_ready(MigrationState *s, uint64_t max_size) +{ + int ret; + uint64_t pending_size; + bool last_round = false; + + qemu_mutex_lock_iothread(); + if (s->state != MIG_STATE_ACTIVE) { + DPRINTF("put_ready returning because of non-active state\n"); + qemu_mutex_unlock_iothread(); + return false; + } + if (s->first_time) { + s->first_time = false; + DPRINTF("beginning savevm\n"); + ret = qemu_savevm_state_begin(s->file, &s->params); + if (ret < 0) { + DPRINTF("failed, %d\n", ret); + migrate_fd_error(s); + qemu_mutex_unlock_iothread(); + return false; + } + } + + DPRINTF("iterate\n"); + pending_size = qemu_savevm_state_pending(s->file, max_size); + DPRINTF("pending size %lu max %lu\n", pending_size, max_size); + if (pending_size >= max_size) { + ret = qemu_savevm_state_iterate(s->file); + if (ret < 0) { + migrate_fd_error(s); + } + } else { + int old_vm_running = runstate_is_running(); + int64_t start_time, end_time; + + DPRINTF("done iterating\n"); + start_time = qemu_get_clock_ms(rt_clock); + qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); + if (old_vm_running) { + vm_stop(RUN_STATE_FINISH_MIGRATE); + } else { + vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); + } + + if (qemu_savevm_state_complete(s->file) < 0) { + migrate_fd_error(s); + } else { + migrate_fd_completed(s); + } + end_time = qemu_get_clock_ms(rt_clock); + s->total_time = end_time - s->total_time; + s->downtime = end_time - start_time; + if (s->state != MIG_STATE_COMPLETED) { + if (old_vm_running) { + vm_start(); + } + } + last_round = true; + } + qemu_mutex_unlock_iothread(); + + return last_round; +} + static void *buffered_file_thread(void *opaque) { QEMUFileBuffered *s = opaque; From 2e450865338738300e529457879d81332939f064 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 3 Oct 2012 18:23:03 +0200 Subject: [PATCH 2110/2270] migration: Inline qemu_fopen_ops_buffered into migrate_fd_connect Signed-off-by: Juan Quintela --- include/migration/migration.h | 2 -- migration.c | 11 +++-------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/include/migration/migration.h b/include/migration/migration.h index 2998dcc3b8..0c9bf8b482 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -127,6 +127,4 @@ int migrate_use_xbzrle(void); int64_t migrate_xbzrle_cache_size(void); int64_t xbzrle_cache_resize(int64_t new_size); - -void qemu_fopen_ops_buffered(MigrationState *migration_state); #endif diff --git a/migration.c b/migration.c index a38720112c..4a9f0b5041 100644 --- a/migration.c +++ b/migration.c @@ -371,13 +371,6 @@ bool migration_has_failed(MigrationState *s) s->state == MIG_STATE_ERROR); } -void migrate_fd_connect(MigrationState *s) -{ - s->state = MIG_STATE_ACTIVE; - s->first_time = true; - qemu_fopen_ops_buffered(s); -} - static MigrationState *migrate_init(const MigrationParams *params) { MigrationState *s = migrate_get_current(); @@ -803,10 +796,12 @@ static const QEMUFileOps buffered_file_ops = { .set_rate_limit = buffered_set_rate_limit, }; -void qemu_fopen_ops_buffered(MigrationState *migration_state) +void migrate_fd_connect(MigrationState *migration_state) { QEMUFileBuffered *s; + migration_state->state = MIG_STATE_ACTIVE; + migration_state->first_time = true; s = g_malloc0(sizeof(*s)); s->migration_state = migration_state; From 0d3b26f5488e04c01667dd12c9bd7eed54dda258 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 3 Oct 2012 20:04:41 +0200 Subject: [PATCH 2111/2270] migration: move migration notifier At this point, it is waranteed that state is ACTIVE. Old position didn't assured hat. Signed-off-by: Juan Quintela --- migration.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/migration.c b/migration.c index 4a9f0b5041..596aca7276 100644 --- a/migration.c +++ b/migration.c @@ -455,8 +455,6 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, error_propagate(errp, local_err); return; } - - notifier_list_notify(&migration_state_notifiers, s); } void qmp_migrate_cancel(Error **errp) @@ -814,4 +812,5 @@ void migrate_fd_connect(MigrationState *migration_state) qemu_thread_create(&s->thread, buffered_file_thread, s, QEMU_THREAD_DETACHED); + notifier_list_notify(&migration_state_notifiers, s); } From b23a9a5cad356cdc8e25d4be72e53096a27ea722 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 17 Oct 2012 20:08:04 +0200 Subject: [PATCH 2112/2270] ram: rename last_block to last_seen_block Signed-off-by: Juan Quintela --- arch_init.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/arch_init.c b/arch_init.c index af1ae9f72a..4351d304a8 100644 --- a/arch_init.c +++ b/arch_init.c @@ -332,7 +332,10 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data, return bytes_sent; } -static RAMBlock *last_block; + +/* This is the last block that we have visited serching for dirty pages + */ +static RAMBlock *last_seen_block; static ram_addr_t last_offset; static unsigned long *migration_bitmap; static uint64_t migration_dirty_pages; @@ -417,7 +420,7 @@ static void migration_bitmap_sync(void) static int ram_save_block(QEMUFile *f, bool last_stage) { - RAMBlock *block = last_block; + RAMBlock *block = last_seen_block; ram_addr_t offset = last_offset; int bytes_sent = -1; MemoryRegion *mr; @@ -430,7 +433,8 @@ static int ram_save_block(QEMUFile *f, bool last_stage) mr = block->mr; if (migration_bitmap_test_and_reset_dirty(mr, offset)) { uint8_t *p; - int cont = (block == last_block) ? RAM_SAVE_FLAG_CONTINUE : 0; + int cont = (block == last_seen_block) ? + RAM_SAVE_FLAG_CONTINUE : 0; p = memory_region_get_ram_ptr(mr) + offset; @@ -469,9 +473,9 @@ static int ram_save_block(QEMUFile *f, bool last_stage) if (!block) block = QTAILQ_FIRST(&ram_list.blocks); } - } while (block != last_block || offset != last_offset); + } while (block != last_seen_block || offset != last_offset); - last_block = block; + last_seen_block = block; last_offset = offset; return bytes_sent; @@ -530,7 +534,7 @@ static void ram_migration_cancel(void *opaque) static void reset_ram_globals(void) { - last_block = NULL; + last_seen_block = NULL; last_offset = 0; last_version = ram_list.version; } From 5f718a15d0db3775bbcf2755a35dd6b019bcff8b Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 17 Oct 2012 20:10:55 +0200 Subject: [PATCH 2113/2270] ram: Add last_sent_block This is the last block from where we have sent data. Signed-off-by: Orit Wasserman Signed-off-by: Juan Quintela --- arch_init.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch_init.c b/arch_init.c index 4351d304a8..caac526f2f 100644 --- a/arch_init.c +++ b/arch_init.c @@ -336,6 +336,8 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data, /* This is the last block that we have visited serching for dirty pages */ static RAMBlock *last_seen_block; +/* This is the last block from where we have sent data */ +static RAMBlock *last_sent_block; static ram_addr_t last_offset; static unsigned long *migration_bitmap; static uint64_t migration_dirty_pages; @@ -433,7 +435,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage) mr = block->mr; if (migration_bitmap_test_and_reset_dirty(mr, offset)) { uint8_t *p; - int cont = (block == last_seen_block) ? + int cont = (block == last_sent_block) ? RAM_SAVE_FLAG_CONTINUE : 0; p = memory_region_get_ram_ptr(mr) + offset; @@ -462,6 +464,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage) /* if page is unmodified, continue to the next */ if (bytes_sent != 0) { + last_sent_block = block; break; } } @@ -535,6 +538,7 @@ static void ram_migration_cancel(void *opaque) static void reset_ram_globals(void) { last_seen_block = NULL; + last_sent_block = NULL; last_offset = 0; last_version = ram_list.version; } From 6c279db8ee99e64e498447c67c16e987150be96b Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 17 Oct 2012 20:24:28 +0200 Subject: [PATCH 2114/2270] memory: introduce memory_region_test_and_clear_dirty This function avoids having to do two calls, one to test the dirty bit, and other to reset it. Signed-off-by: Juan Quintela --- include/exec/memory.h | 16 ++++++++++++++++ memory.c | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/exec/memory.h b/include/exec/memory.h index aada969628..2322732dce 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -453,6 +453,22 @@ bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr, void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr, hwaddr size); +/** + * memory_region_test_and_clear_dirty: Check whether a range of bytes is dirty + * for a specified client. It clears them. + * + * Checks whether a range of bytes has been written to since the last + * call to memory_region_reset_dirty() with the same @client. Dirty logging + * must be enabled. + * + * @mr: the memory region being queried. + * @addr: the address (relative to the start of the region) being queried. + * @size: the size of the range being queried. + * @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or + * %DIRTY_MEMORY_VGA. + */ +bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr, + hwaddr size, unsigned client); /** * memory_region_sync_dirty_bitmap: Synchronize a region's dirty bitmap with * any external TLBs (e.g. kvm) diff --git a/memory.c b/memory.c index 35e6122dd7..410c5f80b4 100644 --- a/memory.c +++ b/memory.c @@ -1081,6 +1081,22 @@ void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr, return cpu_physical_memory_set_dirty_range(mr->ram_addr + addr, size, -1); } +bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr, + hwaddr size, unsigned client) +{ + bool ret; + assert(mr->terminates); + ret = cpu_physical_memory_get_dirty(mr->ram_addr + addr, size, + 1 << client); + if (ret) { + cpu_physical_memory_reset_dirty(mr->ram_addr + addr, + mr->ram_addr + addr + size, + 1 << client); + } + return ret; +} + + void memory_region_sync_dirty_bitmap(MemoryRegion *mr) { AddressSpace *as; From ece7931817e03a4d946c15716fab5e4f781663c9 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 17 Oct 2012 20:27:15 +0200 Subject: [PATCH 2115/2270] ram: Use memory_region_test_and_clear_dirty This avoids having to do two walks over the dirty bitmap, once reading the dirty bits, and anthoer cleaning them. Signed-off-by: Juan Quintela --- arch_init.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch_init.c b/arch_init.c index caac526f2f..9f32ee0124 100644 --- a/arch_init.c +++ b/arch_init.c @@ -390,13 +390,12 @@ static void migration_bitmap_sync(void) QTAILQ_FOREACH(block, &ram_list.blocks, next) { for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) { - if (memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE, - DIRTY_MEMORY_MIGRATION)) { + if (memory_region_test_and_clear_dirty(block->mr, + addr, TARGET_PAGE_SIZE, + DIRTY_MEMORY_MIGRATION)) { migration_bitmap_set_dirty(block->mr, addr); } } - memory_region_reset_dirty(block->mr, 0, block->length, - DIRTY_MEMORY_MIGRATION); } trace_migration_bitmap_sync_end(migration_dirty_pages - num_dirty_pages_init); From 4c8ae0f60e63478aea0a1741cca95474b68fb949 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Thu, 18 Oct 2012 00:00:59 +0200 Subject: [PATCH 2116/2270] ram: optimize migration bitmap walking Instead of testing each page individually, we search what is the next dirty page with a bitmap operation. We have to reorganize the code to move from a "for" loop, to a while(dirty) loop. Signed-off-by: Juan Quintela --- arch_init.c | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/arch_init.c b/arch_init.c index 9f32ee0124..74dc9c8c51 100644 --- a/arch_init.c +++ b/arch_init.c @@ -343,18 +343,21 @@ static unsigned long *migration_bitmap; static uint64_t migration_dirty_pages; static uint32_t last_version; -static inline bool migration_bitmap_test_and_reset_dirty(MemoryRegion *mr, - ram_addr_t offset) +static inline +ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr, + ram_addr_t start) { - bool ret; - int nr = (mr->ram_addr + offset) >> TARGET_PAGE_BITS; + unsigned long base = mr->ram_addr >> TARGET_PAGE_BITS; + unsigned long nr = base + (start >> TARGET_PAGE_BITS); + unsigned long size = base + (int128_get64(mr->size) >> TARGET_PAGE_BITS); - ret = test_and_clear_bit(nr, migration_bitmap); + unsigned long next = find_next_bit(migration_bitmap, size, nr); - if (ret) { + if (next < size) { + clear_bit(next, migration_bitmap); migration_dirty_pages--; } - return ret; + return (next - base) << TARGET_PAGE_BITS; } static inline bool migration_bitmap_set_dirty(MemoryRegion *mr, @@ -423,6 +426,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage) { RAMBlock *block = last_seen_block; ram_addr_t offset = last_offset; + bool complete_round = false; int bytes_sent = -1; MemoryRegion *mr; ram_addr_t current_addr; @@ -430,9 +434,21 @@ static int ram_save_block(QEMUFile *f, bool last_stage) if (!block) block = QTAILQ_FIRST(&ram_list.blocks); - do { + while (true) { mr = block->mr; - if (migration_bitmap_test_and_reset_dirty(mr, offset)) { + offset = migration_bitmap_find_and_reset_dirty(mr, offset); + if (complete_round && block == last_seen_block && + offset >= last_offset) { + break; + } + if (offset >= block->length) { + offset = 0; + block = QTAILQ_NEXT(block, next); + if (!block) { + block = QTAILQ_FIRST(&ram_list.blocks); + complete_round = true; + } + } else { uint8_t *p; int cont = (block == last_sent_block) ? RAM_SAVE_FLAG_CONTINUE : 0; @@ -467,16 +483,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage) break; } } - - offset += TARGET_PAGE_SIZE; - if (offset >= block->length) { - offset = 0; - block = QTAILQ_NEXT(block, next); - if (!block) - block = QTAILQ_FIRST(&ram_list.blocks); - } - } while (block != last_seen_block || offset != last_offset); - + } last_seen_block = block; last_offset = offset; From 3f7d7b098194ec893efa037491f6231687ff043a Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Thu, 18 Oct 2012 13:56:35 +0200 Subject: [PATCH 2117/2270] ram: account the amount of transferred ram better Signed-off-by: Juan Quintela --- arch_init.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/arch_init.c b/arch_init.c index 74dc9c8c51..4015bfd8c5 100644 --- a/arch_init.c +++ b/arch_init.c @@ -265,16 +265,21 @@ uint64_t xbzrle_mig_pages_overflow(void) return acct_info.xbzrle_overflows; } -static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset, - int cont, int flag) +static size_t save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset, + int cont, int flag) { - qemu_put_be64(f, offset | cont | flag); - if (!cont) { - qemu_put_byte(f, strlen(block->idstr)); - qemu_put_buffer(f, (uint8_t *)block->idstr, - strlen(block->idstr)); - } + size_t size; + qemu_put_be64(f, offset | cont | flag); + size = 8; + + if (!cont) { + qemu_put_byte(f, strlen(block->idstr)); + qemu_put_buffer(f, (uint8_t *)block->idstr, + strlen(block->idstr)); + size += 1 + strlen(block->idstr); + } + return size; } #define ENCODING_FLAG_XBZRLE 0x1 @@ -321,11 +326,11 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data, } /* Send XBZRLE based compressed page */ - save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_XBZRLE); + bytes_sent = save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_XBZRLE); qemu_put_byte(f, ENCODING_FLAG_XBZRLE); qemu_put_be16(f, encoded_len); qemu_put_buffer(f, XBZRLE.encoded_buf, encoded_len); - bytes_sent = encoded_len + 1 + 2; + bytes_sent += encoded_len + 1 + 2; acct_info.xbzrle_pages++; acct_info.xbzrle_bytes += bytes_sent; @@ -457,9 +462,10 @@ static int ram_save_block(QEMUFile *f, bool last_stage) if (is_dup_page(p)) { acct_info.dup_pages++; - save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_COMPRESS); + bytes_sent = save_block_hdr(f, block, offset, cont, + RAM_SAVE_FLAG_COMPRESS); qemu_put_byte(f, *p); - bytes_sent = 1; + bytes_sent += 1; } else if (migrate_use_xbzrle()) { current_addr = block->offset + offset; bytes_sent = save_xbzrle_page(f, p, current_addr, block, @@ -471,9 +477,9 @@ static int ram_save_block(QEMUFile *f, bool last_stage) /* either we didn't send yet (we may have had XBZRLE overflow) */ if (bytes_sent == -1) { - save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE); + bytes_sent = save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE); qemu_put_buffer(f, p, TARGET_PAGE_SIZE); - bytes_sent = TARGET_PAGE_SIZE; + bytes_sent += TARGET_PAGE_SIZE; acct_info.norm_pages++; } From b823ceaadfaad65f3a034ada394b33ca1bf1a914 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 10 Dec 2012 13:27:50 +0100 Subject: [PATCH 2118/2270] ram: refactor ram_save_block() return value It could only return 0 if we only found dirty xbzrle pages that hadn't changed (i.e. they were written with the same content). We don't care about that case, it is the same than nothing dirty. So now the return of the function is how much have it written, nothing else. Adjust callers. And we also made ram_save_iterate() return the number of transferred bytes, not the number of transferred pages. Signed-off-by: Juan Quintela --- arch_init.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/arch_init.c b/arch_init.c index 4015bfd8c5..86f85443d7 100644 --- a/arch_init.c +++ b/arch_init.c @@ -422,9 +422,8 @@ static void migration_bitmap_sync(void) /* * ram_save_block: Writes a page of memory to the stream f * - * Returns: 0: if the page hasn't changed - * -1: if there are no more dirty pages - * n: the amount of bytes written in other case + * Returns: The number of bytes written. + * 0 means no dirty pages */ static int ram_save_block(QEMUFile *f, bool last_stage) @@ -432,7 +431,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage) RAMBlock *block = last_seen_block; ram_addr_t offset = last_offset; bool complete_round = false; - int bytes_sent = -1; + int bytes_sent = 0; MemoryRegion *mr; ram_addr_t current_addr; @@ -460,6 +459,8 @@ static int ram_save_block(QEMUFile *f, bool last_stage) p = memory_region_get_ram_ptr(mr) + offset; + /* In doubt sent page as normal */ + bytes_sent = -1; if (is_dup_page(p)) { acct_info.dup_pages++; bytes_sent = save_block_hdr(f, block, offset, cont, @@ -475,7 +476,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage) } } - /* either we didn't send yet (we may have had XBZRLE overflow) */ + /* XBZRLE overflow or normal page */ if (bytes_sent == -1) { bytes_sent = save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE); qemu_put_buffer(f, p, TARGET_PAGE_SIZE); @@ -484,7 +485,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage) } /* if page is unmodified, continue to the next */ - if (bytes_sent != 0) { + if (bytes_sent > 0) { last_sent_block = block; break; } @@ -605,6 +606,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) int ret; int i; int64_t t0; + int total_sent = 0; qemu_mutex_lock_ramlist(); @@ -619,10 +621,10 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) bytes_sent = ram_save_block(f, false); /* no more blocks to sent */ - if (bytes_sent < 0) { + if (bytes_sent == 0) { break; } - bytes_transferred += bytes_sent; + total_sent += bytes_sent; acct_info.iterations++; /* we want to check in the 1st loop, just in case it was the 1st time and we had to sync the dirty bitmap. @@ -641,13 +643,16 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) } if (ret < 0) { + bytes_transferred += total_sent; return ret; } qemu_mutex_unlock_ramlist(); qemu_put_be64(f, RAM_SAVE_FLAG_EOS); + total_sent += 8; + bytes_transferred += total_sent; - return i; + return total_sent; } static int ram_save_complete(QEMUFile *f, void *opaque) @@ -664,7 +669,7 @@ static int ram_save_complete(QEMUFile *f, void *opaque) bytes_sent = ram_save_block(f, true); /* no more blocks to sent */ - if (bytes_sent < 0) { + if (bytes_sent == 0) { break; } bytes_transferred += bytes_sent; From e659586e63793a8a61efc4a658e2908ac8a2e935 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 8 Nov 2012 00:42:50 +0100 Subject: [PATCH 2119/2270] migration: fix qemu_get_fd for BufferedFile Not really used, but nice to have it correct. :) Signed-off-by: Paolo Bonzini Signed-off-by: Juan Quintela --- migration.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migration.c b/migration.c index 596aca7276..3fcc1c8616 100644 --- a/migration.c +++ b/migration.c @@ -625,7 +625,7 @@ static int buffered_get_fd(void *opaque) { QEMUFileBuffered *s = opaque; - return qemu_get_fd(s->file); + return s->migration_state->fd; } /* From 9848a40427cd76628d04d918fa4751c542527915 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 19 Dec 2012 09:55:50 +0100 Subject: [PATCH 2120/2270] migration: merge QEMUFileBuffered into MigrationState Avoid splitting the state of outgoing migration, more or less arbitrarily, between two data structures. QEMUFileBuffered anyway is used only during migration. Signed-off-by: Paolo Bonzini Signed-off-by: Juan Quintela --- include/migration/migration.h | 8 +++++ migration.c | 61 ++++++++++++++--------------------- 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/include/migration/migration.h b/include/migration/migration.h index 0c9bf8b482..2d5b630cce 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -16,6 +16,7 @@ #include "qapi/qmp/qdict.h" #include "qemu-common.h" +#include "qemu/thread.h" #include "qemu/notify.h" #include "qapi/error.h" #include "migration/vmstate.h" @@ -31,6 +32,13 @@ typedef struct MigrationState MigrationState; struct MigrationState { int64_t bandwidth_limit; + size_t bytes_xfer; + size_t xfer_limit; + uint8_t *buffer; + size_t buffer_size; + size_t buffer_capacity; + QemuThread thread; + QEMUFile *file; int fd; int state; diff --git a/migration.c b/migration.c index 3fcc1c8616..c69e864fcd 100644 --- a/migration.c +++ b/migration.c @@ -521,18 +521,8 @@ int64_t migrate_xbzrle_cache_size(void) /* migration thread support */ -typedef struct QEMUFileBuffered { - MigrationState *migration_state; - QEMUFile *file; - size_t bytes_xfer; - size_t xfer_limit; - uint8_t *buffer; - size_t buffer_size; - size_t buffer_capacity; - QemuThread thread; -} QEMUFileBuffered; -static ssize_t buffered_flush(QEMUFileBuffered *s) +static ssize_t buffered_flush(MigrationState *s) { size_t offset = 0; ssize_t ret = 0; @@ -541,8 +531,7 @@ static ssize_t buffered_flush(QEMUFileBuffered *s) while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) { size_t to_send = MIN(s->buffer_size - offset, s->xfer_limit - s->bytes_xfer); - ret = migrate_fd_put_buffer(s->migration_state, s->buffer + offset, - to_send); + ret = migrate_fd_put_buffer(s, s->buffer + offset, to_send); if (ret <= 0) { DPRINTF("error flushing data, %zd\n", ret); break; @@ -566,7 +555,7 @@ static ssize_t buffered_flush(QEMUFileBuffered *s) static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size) { - QEMUFileBuffered *s = opaque; + MigrationState *s = opaque; ssize_t error; DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos); @@ -598,7 +587,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, static int buffered_close(void *opaque) { - QEMUFileBuffered *s = opaque; + MigrationState *s = opaque; ssize_t ret = 0; int ret2; @@ -612,20 +601,20 @@ static int buffered_close(void *opaque) } } - ret2 = migrate_fd_close(s->migration_state); + ret2 = migrate_fd_close(s); if (ret >= 0) { ret = ret2; } - ret = migrate_fd_close(s->migration_state); - s->migration_state->complete = true; + ret = migrate_fd_close(s); + s->complete = true; return ret; } static int buffered_get_fd(void *opaque) { - QEMUFileBuffered *s = opaque; + MigrationState *s = opaque; - return s->migration_state->fd; + return s->fd; } /* @@ -636,7 +625,7 @@ static int buffered_get_fd(void *opaque) */ static int buffered_rate_limit(void *opaque) { - QEMUFileBuffered *s = opaque; + MigrationState *s = opaque; int ret; ret = qemu_file_get_error(s->file); @@ -653,7 +642,7 @@ static int buffered_rate_limit(void *opaque) static int64_t buffered_set_rate_limit(void *opaque, int64_t new_rate) { - QEMUFileBuffered *s = opaque; + MigrationState *s = opaque; if (qemu_file_get_error(s->file)) { goto out; } @@ -669,7 +658,7 @@ out: static int64_t buffered_get_rate_limit(void *opaque) { - QEMUFileBuffered *s = opaque; + MigrationState *s = opaque; return s->xfer_limit; } @@ -741,7 +730,7 @@ static bool migrate_fd_put_ready(MigrationState *s, uint64_t max_size) static void *buffered_file_thread(void *opaque) { - QEMUFileBuffered *s = opaque; + MigrationState *s = opaque; int64_t initial_time = qemu_get_clock_ms(rt_clock); int64_t max_size = 0; bool last_round = false; @@ -749,7 +738,7 @@ static void *buffered_file_thread(void *opaque) while (true) { int64_t current_time = qemu_get_clock_ms(rt_clock); - if (s->migration_state->complete) { + if (s->complete) { break; } if (current_time >= initial_time + BUFFER_DELAY) { @@ -776,12 +765,11 @@ static void *buffered_file_thread(void *opaque) DPRINTF("file is ready\n"); if (s->bytes_xfer < s->xfer_limit) { DPRINTF("notifying client\n"); - last_round = migrate_fd_put_ready(s->migration_state, max_size); + last_round = migrate_fd_put_ready(s, max_size); } } g_free(s->buffer); - g_free(s); return NULL; } @@ -794,22 +782,21 @@ static const QEMUFileOps buffered_file_ops = { .set_rate_limit = buffered_set_rate_limit, }; -void migrate_fd_connect(MigrationState *migration_state) +void migrate_fd_connect(MigrationState *s) { - QEMUFileBuffered *s; + s->state = MIG_STATE_ACTIVE; + s->bytes_xfer = 0; + s->buffer = NULL; + s->buffer_size = 0; + s->buffer_capacity = 0; - migration_state->state = MIG_STATE_ACTIVE; - migration_state->first_time = true; - s = g_malloc0(sizeof(*s)); + s->first_time = true; - s->migration_state = migration_state; - s->xfer_limit = s->migration_state->bandwidth_limit / XFER_LIMIT_RATIO; - s->migration_state->complete = false; + s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO; + s->complete = false; s->file = qemu_fopen_ops(s, &buffered_file_ops); - migration_state->file = s->file; - qemu_thread_create(&s->thread, buffered_file_thread, s, QEMU_THREAD_DETACHED); notifier_list_notify(&migration_state_notifiers, s); From ca273d58d8a77d5cc9d42440bcdf9d7cad2054bc Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 20 Dec 2012 12:29:19 +0100 Subject: [PATCH 2121/2270] build: fix includes for VNC vnc-tls.h is included by vnc.h, and it includes gnutls/gnutls.h. Hence, GnuTLS header files are needed by all files that include vnc.h, most notably qmp.c. Move these flags to QEMU_CFLAGS for simplicity. Reported-by: Peter Maydell Signed-off-by: Paolo Bonzini Signed-off-by: Blue Swirl --- Makefile.target | 5 ----- configure | 7 +++---- ui/Makefile.objs | 1 - 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/Makefile.target b/Makefile.target index 8bbad380c2..be8b8b86a5 100644 --- a/Makefile.target +++ b/Makefile.target @@ -120,11 +120,6 @@ obj-$(CONFIG_NO_GET_MEMORY_MAPPING) += memory_mapping-stub.o obj-$(CONFIG_NO_CORE_DUMP) += dump-stub.o LIBS+=-lz -QEMU_CFLAGS += $(VNC_TLS_CFLAGS) -QEMU_CFLAGS += $(VNC_SASL_CFLAGS) -QEMU_CFLAGS += $(VNC_JPEG_CFLAGS) -QEMU_CFLAGS += $(VNC_PNG_CFLAGS) - # xen support obj-$(CONFIG_XEN) += xen-all.o xen-mapcache.o obj-$(CONFIG_NO_XEN) += xen-stub.o diff --git a/configure b/configure index b101d5c1b7..14f05c7b90 100755 --- a/configure +++ b/configure @@ -1712,6 +1712,7 @@ EOF if compile_prog "$vnc_tls_cflags" "$vnc_tls_libs" ; then vnc_tls=yes libs_softmmu="$vnc_tls_libs $libs_softmmu" + QEMU_CFLAGS="$QEMU_CFLAGS $vnc_tls_cflags" else if test "$vnc_tls" = "yes" ; then feature_not_found "vnc-tls" @@ -1734,6 +1735,7 @@ EOF if compile_prog "$vnc_sasl_cflags" "$vnc_sasl_libs" ; then vnc_sasl=yes libs_softmmu="$vnc_sasl_libs $libs_softmmu" + QEMU_CFLAGS="$QEMU_CFLAGS $vnc_sasl_cflags" else if test "$vnc_sasl" = "yes" ; then feature_not_found "vnc-sasl" @@ -1755,6 +1757,7 @@ EOF if compile_prog "$vnc_jpeg_cflags" "$vnc_jpeg_libs" ; then vnc_jpeg=yes libs_softmmu="$vnc_jpeg_libs $libs_softmmu" + QEMU_CFLAGS="$QEMU_CFLAGS $vnc_jpeg_cflags" else if test "$vnc_jpeg" = "yes" ; then feature_not_found "vnc-jpeg" @@ -3377,19 +3380,15 @@ if test "$vnc" = "yes" ; then fi if test "$vnc_tls" = "yes" ; then echo "CONFIG_VNC_TLS=y" >> $config_host_mak - echo "VNC_TLS_CFLAGS=$vnc_tls_cflags" >> $config_host_mak fi if test "$vnc_sasl" = "yes" ; then echo "CONFIG_VNC_SASL=y" >> $config_host_mak - echo "VNC_SASL_CFLAGS=$vnc_sasl_cflags" >> $config_host_mak fi if test "$vnc_jpeg" = "yes" ; then echo "CONFIG_VNC_JPEG=y" >> $config_host_mak - echo "VNC_JPEG_CFLAGS=$vnc_jpeg_cflags" >> $config_host_mak fi if test "$vnc_png" = "yes" ; then echo "CONFIG_VNC_PNG=y" >> $config_host_mak - echo "VNC_PNG_CFLAGS=$vnc_png_cflags" >> $config_host_mak fi if test "$fnmatch" = "yes" ; then echo "CONFIG_FNMATCH=y" >> $config_host_mak diff --git a/ui/Makefile.objs b/ui/Makefile.objs index dc8f0e46ad..6768bb7f7e 100644 --- a/ui/Makefile.objs +++ b/ui/Makefile.objs @@ -14,6 +14,5 @@ common-obj-$(CONFIG_CURSES) += curses.o common-obj-$(CONFIG_VNC) += $(vnc-obj-y) $(obj)/sdl.o $(obj)/sdl_zoom.o: QEMU_CFLAGS += $(SDL_CFLAGS) -$(obj)/vnc.o: QEMU_CFLAGS += $(VNC_TLS_CFLAGS) $(obj)/cocoa.o: $(SRC_PATH)/$(obj)/cocoa.m From 4ad549e89e55fb48eb6feb783ee4a9ede1dea52e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 20 Dec 2012 12:29:20 +0100 Subject: [PATCH 2122/2270] xen: add missing include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit xen-all needs to access CharDeviceState's filename field, so it needs to include char/char.h. Signed-off-by: Paolo Bonzini Tested-by: Andreas Färber Signed-off-by: Blue Swirl --- xen-all.c | 1 + 1 file changed, 1 insertion(+) diff --git a/xen-all.c b/xen-all.c index 50edaecbf1..19bcfd1510 100644 --- a/xen-all.c +++ b/xen-all.c @@ -16,6 +16,7 @@ #include "hw/xen_backend.h" #include "qmp-commands.h" +#include "char/char.h" #include "qemu/range.h" #include "sysemu/xen-mapcache.h" #include "trace.h" From b2136140f68ce05122f611eb9cde4f0365ab6a00 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 20 Dec 2012 23:09:53 +0100 Subject: [PATCH 2123/2270] net: Add missing include statement (fix compiler warnings for MinGW) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These and some more compiler warnings were caused by a recent commit: net/tap-win32.c:724: warning: no previous prototype for ‘tap_has_ufo’ net/tap-win32.c:729: warning: no previous prototype for ‘tap_has_vnet_hdr’ ... Signed-off-by: Stefan Weil Signed-off-by: Blue Swirl --- net/tap-win32.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/tap-win32.c b/net/tap-win32.c index 0c63cbd203..265369c3c5 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -31,6 +31,7 @@ #include "qemu-common.h" #include "clients.h" /* net_init_tap */ #include "net/net.h" +#include "net/tap.h" /* tap_has_ufo, ... */ #include "sysemu/sysemu.h" #include "qemu/error-report.h" #include From 0c884d1659f02b4a0c704c2344f42e3fabb1f193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B3=E9=9F=8B=E4=BB=BB=20=28Wei-Ren=20Chen=29?= Date: Thu, 20 Dec 2012 09:39:16 +0800 Subject: [PATCH 2124/2270] translate-all.c: Use tb1->phys_hash_next directly in tb_remove When tb_remove was first commited at fd6ce8f6, there were three different calls pass different names to offsetof. In current codebase, the other two calls are replaced with tb_page_remove. There is no need to have a general tb_remove. Omit passing the third parameter and using tb1->phys_hash_next directly. Signed-off-by: Chen Wei-Ren Signed-off-by: Blue Swirl --- translate-all.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/translate-all.c b/translate-all.c index b621748ec0..d367fc4d11 100644 --- a/translate-all.c +++ b/translate-all.c @@ -759,19 +759,17 @@ static void tb_page_check(void) #endif -/* invalidate one TB */ -static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb, - int next_offset) +static inline void tb_hash_remove(TranslationBlock **ptb, TranslationBlock *tb) { TranslationBlock *tb1; for (;;) { tb1 = *ptb; if (tb1 == tb) { - *ptb = *(TranslationBlock **)((char *)tb1 + next_offset); + *ptb = tb1->phys_hash_next; break; } - ptb = (TranslationBlock **)((char *)tb1 + next_offset); + ptb = &tb1->phys_hash_next; } } @@ -828,6 +826,7 @@ static inline void tb_reset_jump(TranslationBlock *tb, int n) tb_set_jmp_target(tb, n, (uintptr_t)(tb->tc_ptr + tb->tb_next_offset[n])); } +/* invalidate one TB */ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) { CPUArchState *env; @@ -839,8 +838,7 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) /* remove the TB from the hash list */ phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK); h = tb_phys_hash_func(phys_pc); - tb_remove(&tb_phys_hash[h], tb, - offsetof(TranslationBlock, phys_hash_next)); + tb_hash_remove(&tb_phys_hash[h], tb); /* remove the TB from the page list */ if (tb->page_addr[0] != page_addr) { From 3f124b687462ce3140d963a024705a89cdc8cee8 Mon Sep 17 00:00:00 2001 From: Liming Wang Date: Fri, 21 Dec 2012 16:56:58 +0800 Subject: [PATCH 2125/2270] net: add missing include file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To fix building error: CC net/vde.o net/vde.c: In function ‘vde_cleanup’: net/vde.c:65:5: error: implicit declaration of function ‘qemu_set_fd_handler’ [-Werror=implicit-function-declaration] net/vde.c:65:5: error: nested extern declaration of ‘qemu_set_fd_handler’ [-Werror=nested-externs] cc1: all warnings being treated as errors Signed-off-by: Liming Wang Signed-off-by: Blue Swirl --- net/vde.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/vde.c b/net/vde.c index 754a141543..4dea32d07a 100644 --- a/net/vde.c +++ b/net/vde.c @@ -29,6 +29,7 @@ #include "clients.h" #include "qemu-common.h" #include "qemu/option.h" +#include "qemu/main-loop.h" typedef struct VDEState { NetClientState nc; From 36f25d2537c40c6c47f4abee5d31a24863d1adf7 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 20 Dec 2012 00:04:09 +0400 Subject: [PATCH 2126/2270] target-xtensa: fix search_pc for the last TB opcode Zero out tcg_ctx.gen_opc_instr_start for instructions representing the last guest opcode in the TB. Cc: qemu-stable@nongnu.org Signed-off-by: Max Filippov Signed-off-by: Blue Swirl --- target-xtensa/translate.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 0a037291ef..7029ac4814 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -3005,7 +3005,11 @@ static void gen_intermediate_code_internal( gen_icount_end(tb, insn_count); *tcg_ctx.gen_opc_ptr = INDEX_op_end; - if (!search_pc) { + if (search_pc) { + j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; + memset(tcg_ctx.gen_opc_instr_start + lj + 1, 0, + (j - lj) * sizeof(tcg_ctx.gen_opc_instr_start[0])); + } else { tb->size = dc.pc - pc_start; tb->icount = insn_count; } From 586502189edf9fd0f89a83de96717a2ea826fdb0 Mon Sep 17 00:00:00 2001 From: Lei Li Date: Fri, 21 Dec 2012 12:26:38 +0800 Subject: [PATCH 2127/2270] qemu-char: Inherit ptys and improve output from -serial pty Changes since V1: - Avoid crashing since qemu_opts_id() may return null on some systems according to Markus's suggestion. When controlling a qemu instance from another program, it's hard to know which serial port or monitor device is redirected to which pty. With more than one device using "pty" a lot of guesswork is involved. $ ./x86_64-softmmu/qemu-system-x86_64 -serial pty -serial pty -monitor pty char device redirected to /dev/pts/5 char device redirected to /dev/pts/6 char device redirected to /dev/pts/7 Although we can find out what everything else is connected to by the "info chardev" with "-monitor stdio" in the command line, It'd be very useful to be able to have qemu inherit pseudo-tty file descriptors so they could just be specified on the command line like: $ ./x86_64-softmmu/qemu-system-x86_64 -serial pty -serial pty -monitor pty char device compat_monitor0 redirected to /dev/pts/5 char device serial0 redirected to /dev/pts/6 char device serial1 redirected to /dev/pts/7 Referred link: https://bugs.launchpad.net/qemu/+bug/938552 Signed-off-by: Lei Li Signed-off-by: Anthony Liguori --- qemu-char.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/qemu-char.c b/qemu-char.c index 6113d0ab60..c6382a93f5 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -980,6 +980,7 @@ static CharDriverState *qemu_chr_open_pty(QemuOpts *opts) CharDriverState *chr; PtyCharDriver *s; struct termios tty; + const char *label; int master_fd, slave_fd, len; #if defined(__OpenBSD__) || defined(__DragonFly__) char pty_name[PATH_MAX]; @@ -1005,7 +1006,12 @@ static CharDriverState *qemu_chr_open_pty(QemuOpts *opts) chr->filename = g_malloc(len); snprintf(chr->filename, len, "pty:%s", q_ptsname(master_fd)); qemu_opt_set(opts, "path", q_ptsname(master_fd)); - fprintf(stderr, "char device redirected to %s\n", q_ptsname(master_fd)); + + label = qemu_opts_id(opts); + fprintf(stderr, "char device%s%s redirected to %s\n", + label ? " " : "", + label ?: "", + q_ptsname(master_fd)); s = g_malloc0(sizeof(PtyCharDriver)); chr->opaque = s; From 57f26ae72983095d0258e391041dfb8864f769e5 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 20 Dec 2012 16:43:48 -0200 Subject: [PATCH 2128/2270] target-i386: CPUID: return highest basic leaf if eax > cpuid_xlevel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a subtle bug. A bug that probably won't cause trouble for any existing OS, but a bug anyway: Intel SDM Volume 2, CPUID Instruction states: > Two types of information are returned: basic and extended function > information. If a value entered for CPUID.EAX is higher than the maximum > input value for basic or extended function for that processor then the > data for the highest basic information leaf is returned. For example, > using the Intel Core i7 processor, the following is true: > > CPUID.EAX = 05H (* Returns MONITOR/MWAIT leaf. *) > CPUID.EAX = 0AH (* Returns Architectural Performance Monitoring leaf. *) > CPUID.EAX = 0BH (* Returns Extended Topology Enumeration leaf. *) > CPUID.EAX = 0CH (* INVALID: Returns the same information as CPUID.EAX = 0BH. *) > CPUID.EAX = 80000008H (* Returns linear/physical address size data. *) > CPUID.EAX = 8000000AH (* INVALID: Returns same information as CPUID.EAX = 0BH. *) AMD's CPUID Specification, on the other hand, is less specific: > The CPUID instruction supports two sets or ranges of functions, > standard and extended. > > • The smallest function number of the standard function range is > Fn0000_0000. The largest function num- ber of the standard function > range, for a particular implementation, is returned in CPUID > Fn0000_0000_EAX. > > • The smallest function number of the extended function range is > Fn8000_0000. The largest function num- ber of the extended function > range, for a particular implementation, is returned in CPUID > Fn8000_0000_EAX. > > Functions that are neither standard nor extended are undefined and > should not be relied upon. QEMU's behavior matched Intel's specification before, but this was changed by commit b3baa152aaef1905876670590275c2dd0bbb088c. This patch restores the behavior documented by Intel when cpuid_xlevel2 is 0. The existing behavior when cpuid_xlevel2 is set (falling back to level=cpuid_xlevel) is being kept, as I couldn't find any public documentation on the CPUID 0xC0000000 function range on Centaur CPUs. Signed-off-by: Eduardo Habkost Signed-off-by: Anthony Liguori --- target-i386/cpu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 1837f5af04..3cd1cee540 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1648,7 +1648,11 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, index = env->cpuid_xlevel; } } else { - index = env->cpuid_xlevel; + /* Intel documentation states that invalid EAX input will + * return the same information as EAX=cpuid_level + * (Intel SDM Vol. 2A - Instruction Set Reference - CPUID) + */ + index = env->cpuid_level; } } } else { From 6265e4ff327763b6362cba472e2b46f2dcf18762 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 23 Nov 2012 12:12:01 +0100 Subject: [PATCH 2129/2270] win32: Switch thread abstraction to us TLS variable internally We already depend on working __thread support for coroutines, so this complication here is no longer needed. Reviewed-by: Paolo Bonzini Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- qemu-thread-win32.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c index 8037b39045..517878dcc1 100644 --- a/qemu-thread-win32.c +++ b/qemu-thread-win32.c @@ -239,7 +239,7 @@ struct QemuThreadData { CRITICAL_SECTION cs; }; -static int qemu_thread_tls_index = TLS_OUT_OF_INDEXES; +static __thread QemuThreadData *qemu_thread_data; static unsigned __stdcall win32_start_routine(void *arg) { @@ -251,14 +251,15 @@ static unsigned __stdcall win32_start_routine(void *arg) g_free(data); data = NULL; } - TlsSetValue(qemu_thread_tls_index, data); + qemu_thread_data = data; qemu_thread_exit(start_routine(thread_arg)); abort(); } void qemu_thread_exit(void *arg) { - QemuThreadData *data = TlsGetValue(qemu_thread_tls_index); + QemuThreadData *data = qemu_thread_data; + if (data) { assert(data->mode != QEMU_THREAD_DETACHED); data->ret = arg; @@ -298,25 +299,13 @@ void *qemu_thread_join(QemuThread *thread) return ret; } -static inline void qemu_thread_init(void) -{ - if (qemu_thread_tls_index == TLS_OUT_OF_INDEXES) { - qemu_thread_tls_index = TlsAlloc(); - if (qemu_thread_tls_index == TLS_OUT_OF_INDEXES) { - error_exit(ERROR_NO_SYSTEM_RESOURCES, __func__); - } - } -} - - void qemu_thread_create(QemuThread *thread, void *(*start_routine)(void *), void *arg, int mode) { HANDLE hThread; - struct QemuThreadData *data; - qemu_thread_init(); + data = g_malloc(sizeof *data); data->start_routine = start_routine; data->arg = arg; @@ -338,8 +327,7 @@ void qemu_thread_create(QemuThread *thread, void qemu_thread_get_self(QemuThread *thread) { - qemu_thread_init(); - thread->data = TlsGetValue(qemu_thread_tls_index); + thread->data = qemu_thread_data; thread->tid = GetCurrentThreadId(); } From eac236ea7bfc1902126be70459e320591078df5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Llu=C3=ADs=20Vilanova?= Date: Fri, 14 Dec 2012 20:13:09 +0100 Subject: [PATCH 2130/2270] build: Use separate makefile for "trace/" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Paolo Bonzini Signed-off-by: Lluís Vilanova -- Changes in v2: * Do not depend on "qemu-timer-common.o". * Use "$(obj)" in rules to refer to the build sub-directory. * Remove dependencies against "$(GENERATED_HEADERS)". Cc: Paolo Bonzini Signed-off-by: Anthony Liguori --- .gitignore | 8 ++-- Makefile | 17 ++++--- Makefile.objs | 64 ++------------------------ scripts/tracetool/backend/dtrace.py | 2 +- scripts/tracetool/format/h.py | 6 +-- trace.h | 6 +++ trace/Makefile.objs | 70 +++++++++++++++++++++++++++++ 7 files changed, 97 insertions(+), 76 deletions(-) create mode 100644 trace.h create mode 100644 trace/Makefile.objs diff --git a/.gitignore b/.gitignore index 3a417656e2..0e3816918c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,10 +3,10 @@ config-all-devices.* config-all-disas.* config-host.* config-target.* -trace.h -trace.c -trace-dtrace.h -trace-dtrace.dtrace +trace/generated-tracers.h +trace/generated-tracers.c +trace/generated-tracers-dtrace.h +trace/generated-tracers-dtrace.dtrace *-timestamp *-softmmu *-darwin-user diff --git a/Makefile b/Makefile index a0321dd7f0..a7ac04b9ae 100644 --- a/Makefile +++ b/Makefile @@ -31,12 +31,15 @@ ifneq ($(filter-out %clean,$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail)) endif endif -GENERATED_HEADERS = config-host.h trace.h qemu-options.def -ifeq ($(TRACE_BACKEND),dtrace) -GENERATED_HEADERS += trace-dtrace.h -endif +GENERATED_HEADERS = config-host.h qemu-options.def GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h -GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c trace.c +GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c + +GENERATED_HEADERS += trace/generated-tracers.h +ifeq ($(TRACE_BACKEND),dtrace) +GENERATED_HEADERS += trace/generated-tracers-dtrace.h +endif +GENERATED_SOURCES += trace/generated-tracers.c # Don't try to regenerate Makefile or configure # We don't generate any of them @@ -233,9 +236,9 @@ clean: rm -f *.a *.lo $(TOOLS) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~ rm -Rf .libs rm -f qemu-img-cmds.h - rm -f trace-dtrace.dtrace trace-dtrace.dtrace-timestamp @# May not be present in GENERATED_HEADERS - rm -f trace-dtrace.h trace-dtrace.h-timestamp + rm -f trace/generated-tracers-dtrace.dtrace* + rm -f trace/generated-tracers-dtrace.h* rm -f $(foreach f,$(GENERATED_HEADERS),$(f) $(f)-timestamp) rm -f $(foreach f,$(GENERATED_SOURCES),$(f) $(f)-timestamp) rm -rf qapi-generated diff --git a/Makefile.objs b/Makefile.objs index 4ef0a718d2..3a3a4028c5 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -133,66 +133,7 @@ universal-obj-y += disas/ ###################################################################### # trace -ifeq ($(TRACE_BACKEND),dtrace) -TRACE_H_EXTRA_DEPS=trace-dtrace.h -endif -trace.h: trace.h-timestamp $(TRACE_H_EXTRA_DEPS) -trace.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(TRACETOOL) \ - --format=h \ - --backend=$(TRACE_BACKEND) \ - < $< > $@," GEN trace.h") - @cmp -s $@ trace.h || cp $@ trace.h - -trace.c: trace.c-timestamp -trace.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(TRACETOOL) \ - --format=c \ - --backend=$(TRACE_BACKEND) \ - < $< > $@," GEN trace.c") - @cmp -s $@ trace.c || cp $@ trace.c - -trace.o: trace.c $(GENERATED_HEADERS) - -trace-dtrace.h: trace-dtrace.dtrace - $(call quiet-command,dtrace -o $@ -h -s $<, " GEN trace-dtrace.h") - -# Normal practice is to name DTrace probe file with a '.d' extension -# but that gets picked up by QEMU's Makefile as an external dependency -# rule file. So we use '.dtrace' instead -trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp -trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(TRACETOOL) \ - --format=d \ - --backend=$(TRACE_BACKEND) \ - < $< > $@," GEN trace-dtrace.dtrace") - @cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace - -trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS) - $(call quiet-command,dtrace -o $@ -G -s $<, " GEN trace-dtrace.o") - -ifeq ($(LIBTOOL),) -trace-dtrace.lo: trace-dtrace.dtrace - @echo "missing libtool. please install and rerun configure."; exit 1 -else -trace-dtrace.lo: trace-dtrace.dtrace - $(call quiet-command,$(LIBTOOL) --mode=compile --tag=CC dtrace -o $@ -G -s $<, " lt GEN trace-dtrace.o") -endif - -trace/simple.o: trace/simple.c $(GENERATED_HEADERS) - -trace-obj-$(CONFIG_TRACE_DTRACE) += trace-dtrace.o -ifneq ($(TRACE_BACKEND),dtrace) -trace-obj-y = trace.o -endif - -trace-obj-$(CONFIG_TRACE_DEFAULT) += trace/default.o -trace-obj-$(CONFIG_TRACE_SIMPLE) += trace/simple.o -trace-obj-$(CONFIG_TRACE_SIMPLE) += qemu-timer-common.o -trace-obj-$(CONFIG_TRACE_STDERR) += trace/stderr.o -trace-obj-y += trace/control.o - -$(trace-obj-y): $(GENERATED_HEADERS) +trace-obj-y += trace/ universal-obj-y += $(trace-obj-y) @@ -239,5 +180,6 @@ nested-vars += \ user-obj-y \ common-obj-y \ universal-obj-y \ - extra-obj-y + extra-obj-y \ + trace-obj-y dummy := $(call unnest-vars) diff --git a/scripts/tracetool/backend/dtrace.py b/scripts/tracetool/backend/dtrace.py index 23c43e2772..ad5eb3b0ab 100644 --- a/scripts/tracetool/backend/dtrace.py +++ b/scripts/tracetool/backend/dtrace.py @@ -37,7 +37,7 @@ def c(events): def h(events): - out('#include "trace-dtrace.h"', + out('#include "trace/generated-tracers-dtrace.h"', '') for e in events: diff --git a/scripts/tracetool/format/h.py b/scripts/tracetool/format/h.py index 6ffb3c2f4e..9a58de1331 100644 --- a/scripts/tracetool/format/h.py +++ b/scripts/tracetool/format/h.py @@ -19,8 +19,8 @@ from tracetool import out def begin(events): out('/* This file is autogenerated by tracetool, do not edit. */', '', - '#ifndef TRACE_H', - '#define TRACE_H', + '#ifndef TRACE__GENERATED_TRACERS_H', + '#define TRACE__GENERATED_TRACERS_H', '', '#include "qemu-common.h"') @@ -32,7 +32,7 @@ def end(events): enabled = 1 out('#define TRACE_%s_ENABLED %d' % (e.name.upper(), enabled)) out('', - '#endif /* TRACE_H */') + '#endif /* TRACE__GENERATED_TRACERS_H */') def nop(events): for e in events: diff --git a/trace.h b/trace.h new file mode 100644 index 0000000000..c15f498128 --- /dev/null +++ b/trace.h @@ -0,0 +1,6 @@ +#ifndef TRACE_H +#define TRACE_H + +#include "trace/generated-tracers.h" + +#endif /* TRACE_H */ diff --git a/trace/Makefile.objs b/trace/Makefile.objs new file mode 100644 index 0000000000..b791723696 --- /dev/null +++ b/trace/Makefile.objs @@ -0,0 +1,70 @@ +# -*- mode: makefile -*- + +###################################################################### +# Auto-generated tracing routines + +ifeq ($(TRACE_BACKEND),dtrace) +TRACE_H_EXTRA_DEPS=$(obj)/generated-tracers-dtrace.h +endif +$(obj)/generated-tracers.h: $(obj)/generated-tracers.h-timestamp $(TRACE_H_EXTRA_DEPS) +$(obj)/generated-tracers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak + $(call quiet-command,$(TRACETOOL) \ + --format=h \ + --backend=$(TRACE_BACKEND) \ + < $< > $@," GEN $(patsubst %-timestamp,%,$@)") + @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@) + +$(obj)/generated-tracers.c: $(obj)/generated-tracers.c-timestamp +$(obj)/generated-tracers.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak + $(call quiet-command,$(TRACETOOL) \ + --format=c \ + --backend=$(TRACE_BACKEND) \ + < $< > $@," GEN $(patsubst %-timestamp,%,$@)") + @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@) + +$(obj)/generated-tracers.o: $(obj)/generated-tracers.c $(obj)/generated-tracers.h + +ifneq ($(TRACE_BACKEND),dtrace) +trace-obj-y += generated-tracers.o +endif + + +###################################################################### +# Auto-generated DTrace code + +# Normal practice is to name DTrace probe file with a '.d' extension +# but that gets picked up by QEMU's Makefile as an external dependency +# rule file. So we use '.dtrace' instead +$(obj)/generated-tracers-dtrace.dtrace: $(obj)/generated-tracers-dtrace.dtrace-timestamp +$(obj)/generated-tracers-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak + $(call quiet-command,$(TRACETOOL) \ + --format=d \ + --backend=$(TRACE_BACKEND) \ + < $< > $@," GEN $(patsubst %-timestamp,%,$@)") + @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@) + +$(obj)/generated-tracers-dtrace.h: trace/generated-tracers-dtrace.dtrace + $(call quiet-command,dtrace -o $@ -h -s $<, " GEN $@") + +$(obj)/generated-tracers-dtrace.o: trace/generated-tracers-dtrace.dtrace + $(call quiet-command,dtrace -o $@ -G -s $<, " GEN $@") + +trace-obj-$(CONFIG_TRACE_DTRACE) += generated-tracers-dtrace.o + + +ifeq ($(LIBTOOL),) +$(obj)/generated-tracers-dtrace.lo: $(obj)/generated-tracers-dtrace.dtrace + @echo "missing libtool. please install and rerun configure."; exit 1 +else +$(obj)/generated-tracers-dtrace.lo: $(obj)/generated-tracers-dtrace.dtrace + $(call quiet-command,$(LIBTOOL) --mode=compile --tag=CC dtrace -o $@ -G -s $<, " lt GEN $@") +endif + + +###################################################################### +# Backend code + +trace-obj-$(CONFIG_TRACE_DEFAULT) += default.o +trace-obj-$(CONFIG_TRACE_SIMPLE) += simple.o +trace-obj-$(CONFIG_TRACE_STDERR) += stderr.o +trace-obj-y += control.o From 2915efbfa8efadaa2806e827ba92b8dba4f7cd52 Mon Sep 17 00:00:00 2001 From: Alex Horn Date: Wed, 5 Dec 2012 12:34:06 +0000 Subject: [PATCH 2131/2270] tmp105: Create API for TMP105 temperature sensor. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Define enum for TMP105 registers * Move tmp105_set() from I2C to TMP105 header * Document units and range of temperature as preconditions Reviewed-by: Andreas Färber Signed-off-by: Alex Horn Signed-off-by: Anthony Liguori --- hw/i2c.h | 3 --- hw/tmp105.c | 17 +++++++------- hw/tmp105.h | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 hw/tmp105.h diff --git a/hw/i2c.h b/hw/i2c.h index 0f5682b4b0..883b5c588d 100644 --- a/hw/i2c.h +++ b/hw/i2c.h @@ -73,9 +73,6 @@ void *wm8750_dac_buffer(void *opaque, int samples); void wm8750_dac_commit(void *opaque); void wm8750_set_bclk_in(void *opaque, int new_hz); -/* tmp105.c */ -void tmp105_set(I2CSlave *i2c, int temp); - /* lm832x.c */ void lm832x_key_event(DeviceState *dev, int key, int state); diff --git a/hw/tmp105.c b/hw/tmp105.c index 8e8dbd94eb..9c67e644dd 100644 --- a/hw/tmp105.c +++ b/hw/tmp105.c @@ -20,6 +20,7 @@ #include "hw.h" #include "i2c.h" +#include "tmp105.h" typedef struct { I2CSlave i2c; @@ -92,22 +93,22 @@ static void tmp105_read(TMP105State *s) } switch (s->pointer & 3) { - case 0: /* Temperature */ + case TMP105_REG_TEMPERATURE: s->buf[s->len ++] = (((uint16_t) s->temperature) >> 8); s->buf[s->len ++] = (((uint16_t) s->temperature) >> 0) & (0xf0 << ((~s->config >> 5) & 3)); /* R */ break; - case 1: /* Configuration */ + case TMP105_REG_CONFIG: s->buf[s->len ++] = s->config; break; - case 2: /* T_LOW */ + case TMP105_REG_T_LOW: s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 8; s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 0; break; - case 3: /* T_HIGH */ + case TMP105_REG_T_HIGH: s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 8; s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 0; break; @@ -117,10 +118,10 @@ static void tmp105_read(TMP105State *s) static void tmp105_write(TMP105State *s) { switch (s->pointer & 3) { - case 0: /* Temperature */ + case TMP105_REG_TEMPERATURE: break; - case 1: /* Configuration */ + case TMP105_REG_CONFIG: if (s->buf[0] & ~s->config & (1 << 0)) /* SD */ printf("%s: TMP105 shutdown\n", __FUNCTION__); s->config = s->buf[0]; @@ -128,8 +129,8 @@ static void tmp105_write(TMP105State *s) tmp105_alarm_update(s); break; - case 2: /* T_LOW */ - case 3: /* T_HIGH */ + case TMP105_REG_T_LOW: + case TMP105_REG_T_HIGH: if (s->len >= 3) s->limit[s->pointer & 1] = (int16_t) ((((uint16_t) s->buf[0]) << 8) | s->buf[1]); diff --git a/hw/tmp105.h b/hw/tmp105.h new file mode 100644 index 0000000000..51eff4be1c --- /dev/null +++ b/hw/tmp105.h @@ -0,0 +1,67 @@ +/* + * Texas Instruments TMP105 Temperature Sensor + * + * Browse the data sheet: + * + * http://www.ti.com/lit/gpn/tmp105 + * + * Copyright (C) 2012 Alex Horn + * Copyright (C) 2008-2012 Andrzej Zaborowski + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later. See the COPYING file in the top-level directory. + */ +#ifndef QEMU_TMP105_H +#define QEMU_TMP105_H + +#include "i2c.h" + +/** + * TMP105Reg: + * @TMP105_REG_TEMPERATURE: Temperature register + * @TMP105_REG_CONFIG: Configuration register + * @TMP105_REG_T_LOW: Low temperature register (also known as T_hyst) + * @TMP105_REG_T_HIGH: High temperature register (also known as T_OS) + * + * The following temperature sensors are + * compatible with the TMP105 registers: + * - adt75 + * - ds1775 + * - ds75 + * - lm75 + * - lm75a + * - max6625 + * - max6626 + * - mcp980x + * - stds75 + * - tcn75 + * - tmp100 + * - tmp101 + * - tmp105 + * - tmp175 + * - tmp275 + * - tmp75 + **/ +typedef enum TMP105Reg { + TMP105_REG_TEMPERATURE = 0, + TMP105_REG_CONFIG, + TMP105_REG_T_LOW, + TMP105_REG_T_HIGH, +} TMP105Reg; + +/** + * tmp105_set: + * @i2c: dispatcher to TMP105 hardware model + * @temp: temperature with 0.001 centigrades units in the range -40 C to +125 C + * + * Sets the temperature of the TMP105 hardware model. + * + * Bits 5 and 6 (value 32 and 64) in the register indexed by TMP105_REG_CONFIG + * determine the precision of the temperature. See Table 8 in the data sheet. + * + * @see_also: I2C_SLAVE macro + * @see_also: http://www.ti.com/lit/gpn/tmp105 + */ +void tmp105_set(I2CSlave *i2c, int temp); + +#endif From 74880fe27d2120ab3861dc857ecd025db1a67038 Mon Sep 17 00:00:00 2001 From: Robert Schiele Date: Tue, 4 Dec 2012 16:58:08 +0100 Subject: [PATCH 2132/2270] configure: allow disabling pixman if not needed When we build neither any system emulation targets nor the tools there is actually no need for pixman library. In that case do not enforce presence of that library on the system. Reviewed-by: Andreas F=E4rber Signed-off-by: Robert Schiele Signed-off-by: Anthony Liguori --- configure | 18 ++++++++++++++++-- target-unicore32/helper.c | 2 ++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 14f05c7b90..99c1ec3467 100755 --- a/configure +++ b/configure @@ -656,6 +656,8 @@ for opt do ;; --without-system-pixman) pixman="internal" ;; + --without-pixman) pixman="none" + ;; --disable-sdl) sdl="no" ;; --enable-sdl) sdl="yes" @@ -2130,13 +2132,25 @@ fi # pixman support probe if test "$pixman" = ""; then - if $pkg_config pixman-1 > /dev/null 2>&1; then + if test "$want_tools" = "no" -a "$softmmu" = "no"; then + pixman="none" + elif $pkg_config pixman-1 > /dev/null 2>&1; then pixman="system" else pixman="internal" fi fi -if test "$pixman" = "system"; then +if test "$pixman" = "none"; then + if test "$want_tools" != "no" -o "$softmmu" != "no"; then + echo "ERROR: pixman disabled but system emulation or tools build" + echo " enabled. You can turn off pixman only if you also" + echo " disable all system emulation targets and the tools" + echo " build with '--disable-tools --disable-system'." + exit 1 + fi + pixman_cflags= + pixman_libs= +elif test "$pixman" = "system"; then pixman_cflags=`$pkg_config --cflags pixman-1 2>/dev/null` pixman_libs=`$pkg_config --libs pixman-1 2>/dev/null` else diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c index ff4f628404..5359538ea5 100644 --- a/target-unicore32/helper.c +++ b/target-unicore32/helper.c @@ -13,7 +13,9 @@ #include "exec/gdbstub.h" #include "helper.h" #include "qemu/host-utils.h" +#ifndef CONFIG_USER_ONLY #include "ui/console.h" +#endif #undef DEBUG_UC32 From a2685bcc80f61aa612e0d8cfd91086857ae2942e Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Wed, 19 Dec 2012 17:46:15 +0200 Subject: [PATCH 2133/2270] MAINTAINERS: Take over kvm maintenance Replace Avi with myself as kvm maintainer. Signed-off-by: Gleb Natapov Signed-off-by: Anthony Liguori --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index c1b16c5fe4..3e9dbc271d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -132,7 +132,7 @@ Guest CPU Cores (KVM): ---------------------- Overall -M: Avi Kivity +M: Gleb Natapov M: Marcelo Tosatti L: kvm@vger.kernel.org S: Supported @@ -150,7 +150,7 @@ S: Maintained F: target-s390x/kvm.c X86 -M: Avi Kivity +M: Gleb Natapov M: Marcelo Tosatti L: kvm@vger.kernel.org S: Supported From 0a2a59d35cbabf63c91340a1c62038e3e60538c1 Mon Sep 17 00:00:00 2001 From: Xudong Hao Date: Thu, 20 Dec 2012 11:07:23 +0800 Subject: [PATCH 2134/2270] qemu-kvm/pci-assign: 64 bits bar emulation Enable 64 bits bar emulation. Test pass with the current seabios which already support 64bit pci bars. Signed-off-by: Xudong Hao Reviewed-by: Alex Williamson Signed-off-by: Gleb Natapov --- hw/kvm/pci-assign.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/hw/kvm/pci-assign.c b/hw/kvm/pci-assign.c index e80dad009c..addc205596 100644 --- a/hw/kvm/pci-assign.c +++ b/hw/kvm/pci-assign.c @@ -46,6 +46,7 @@ #define IORESOURCE_IRQ 0x00000400 #define IORESOURCE_DMA 0x00000800 #define IORESOURCE_PREFETCH 0x00002000 /* No side effects */ +#define IORESOURCE_MEM_64 0x00100000 //#define DEVICE_ASSIGNMENT_DEBUG @@ -442,9 +443,13 @@ static int assigned_dev_register_regions(PCIRegion *io_regions, /* handle memory io regions */ if (cur_region->type & IORESOURCE_MEM) { - int t = cur_region->type & IORESOURCE_PREFETCH - ? PCI_BASE_ADDRESS_MEM_PREFETCH - : PCI_BASE_ADDRESS_SPACE_MEMORY; + int t = PCI_BASE_ADDRESS_SPACE_MEMORY; + if (cur_region->type & IORESOURCE_PREFETCH) { + t |= PCI_BASE_ADDRESS_MEM_PREFETCH; + } + if (cur_region->type & IORESOURCE_MEM_64) { + t |= PCI_BASE_ADDRESS_MEM_TYPE_64; + } /* map physical memory */ pci_dev->v_addrs[i].u.r_virtbase = mmap(NULL, cur_region->size, @@ -632,7 +637,8 @@ again: rp->valid = 0; rp->resource_fd = -1; size = end - start + 1; - flags &= IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH; + flags &= IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH + | IORESOURCE_MEM_64; if (size == 0 || (flags & ~IORESOURCE_PREFETCH) == 0) { continue; } From 812d2594d558f7c4f95c99c8fc58adc47ab68eb3 Mon Sep 17 00:00:00 2001 From: Knut Omang Date: Tue, 18 Dec 2012 22:36:29 +0100 Subject: [PATCH 2135/2270] pcie: Fix bug in pcie_ext_cap_set_next Upper 16 bits of the PCIe Extended Capability Header was truncated during update, also breaking pcie_add_capability. Signed-off-by: Knut Omang Signed-off-by: Michael S. Tsirkin --- hw/pci/pcie.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 6c916d15ec..485c94c1b2 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -494,7 +494,7 @@ uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id) static void pcie_ext_cap_set_next(PCIDevice *dev, uint16_t pos, uint16_t next) { - uint16_t header = pci_get_long(dev->config + pos); + uint32_t header = pci_get_long(dev->config + pos); assert(!(next & (PCI_EXT_CAP_ALIGN - 1))); header = (header & ~PCI_EXT_CAP_NEXT_MASK) | ((next << PCI_EXT_CAP_NEXT_SHIFT) & PCI_EXT_CAP_NEXT_MASK); From bbef882cc1938fa5a6e1b36a50d79ce5c0cefb81 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 12 Dec 2012 16:10:02 +0200 Subject: [PATCH 2136/2270] msi: add API to get notified about pending bit poll Update all users. Signed-off-by: Michael S. Tsirkin --- hw/pci/msix.c | 13 ++++++++++++- hw/pci/msix.h | 3 ++- hw/pci/pci.h | 4 ++++ hw/vfio_pci.c | 2 +- hw/virtio-pci.c | 3 ++- 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/hw/pci/msix.c b/hw/pci/msix.c index 073e22c315..a285d18197 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -191,6 +191,11 @@ static uint64_t msix_pba_mmio_read(void *opaque, hwaddr addr, unsigned size) { PCIDevice *dev = opaque; + if (dev->msix_vector_poll_notifier) { + unsigned vector_start = addr * 8; + unsigned vector_end = MIN(addr + size * 8, dev->msix_entries_nr); + dev->msix_vector_poll_notifier(dev, vector_start, vector_end); + } return pci_get_long(dev->msix_pba + addr); } @@ -513,7 +518,8 @@ static void msix_unset_notifier_for_vector(PCIDevice *dev, unsigned int vector) int msix_set_vector_notifiers(PCIDevice *dev, MSIVectorUseNotifier use_notifier, - MSIVectorReleaseNotifier release_notifier) + MSIVectorReleaseNotifier release_notifier, + MSIVectorPollNotifier poll_notifier) { int vector, ret; @@ -521,6 +527,7 @@ int msix_set_vector_notifiers(PCIDevice *dev, dev->msix_vector_use_notifier = use_notifier; dev->msix_vector_release_notifier = release_notifier; + dev->msix_vector_poll_notifier = poll_notifier; if ((dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & (MSIX_ENABLE_MASK | MSIX_MASKALL_MASK)) == MSIX_ENABLE_MASK) { @@ -531,6 +538,9 @@ int msix_set_vector_notifiers(PCIDevice *dev, } } } + if (dev->msix_vector_poll_notifier) { + dev->msix_vector_poll_notifier(dev, 0, dev->msix_entries_nr); + } return 0; undo: @@ -557,4 +567,5 @@ void msix_unset_vector_notifiers(PCIDevice *dev) } dev->msix_vector_use_notifier = NULL; dev->msix_vector_release_notifier = NULL; + dev->msix_vector_poll_notifier = NULL; } diff --git a/hw/pci/msix.h b/hw/pci/msix.h index ff07ae2e8f..ea85d02264 100644 --- a/hw/pci/msix.h +++ b/hw/pci/msix.h @@ -36,6 +36,7 @@ void msix_reset(PCIDevice *dev); int msix_set_vector_notifiers(PCIDevice *dev, MSIVectorUseNotifier use_notifier, - MSIVectorReleaseNotifier release_notifier); + MSIVectorReleaseNotifier release_notifier, + MSIVectorPollNotifier poll_notifier); void msix_unset_vector_notifiers(PCIDevice *dev); #endif diff --git a/hw/pci/pci.h b/hw/pci/pci.h index 3152050856..72927e3149 100644 --- a/hw/pci/pci.h +++ b/hw/pci/pci.h @@ -187,6 +187,9 @@ typedef void (*PCIINTxRoutingNotifier)(PCIDevice *dev); typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector, MSIMessage msg); typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector); +typedef void (*MSIVectorPollNotifier)(PCIDevice *dev, + unsigned int vector_start, + unsigned int vector_end); struct PCIDevice { DeviceState qdev; @@ -271,6 +274,7 @@ struct PCIDevice { /* MSI-X notifiers */ MSIVectorUseNotifier msix_vector_use_notifier; MSIVectorReleaseNotifier msix_vector_release_notifier; + MSIVectorPollNotifier msix_vector_poll_notifier; }; void pci_register_bar(PCIDevice *pci_dev, int region_num, diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 41fb7ad1de..28c83031d0 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -698,7 +698,7 @@ static void vfio_enable_msix(VFIODevice *vdev) vdev->interrupt = VFIO_INT_MSIX; if (msix_set_vector_notifiers(&vdev->pdev, vfio_msix_vector_use, - vfio_msix_vector_release)) { + vfio_msix_vector_release, NULL)) { error_report("vfio: msix_set_vector_notifiers failed\n"); } diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 1f1a285ce8..37e8b2d255 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -637,7 +637,8 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, bool assign) msix_nr_vectors_allocated(&proxy->pci_dev)); r = msix_set_vector_notifiers(&proxy->pci_dev, kvm_virtio_pci_vector_use, - kvm_virtio_pci_vector_release); + kvm_virtio_pci_vector_release, + NULL); if (r < 0) { goto assign_error; } From 70f8ee395afda6d96b15cb9a5b311af7720dded0 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 18 Dec 2012 13:54:32 +0200 Subject: [PATCH 2137/2270] msix: expose access to masked/pending state For use by poll handler. Signed-off-by: Michael S. Tsirkin --- hw/pci/msix.c | 6 +++--- hw/pci/msix.h | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/pci/msix.c b/hw/pci/msix.c index a285d18197..9eee6570c2 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -65,7 +65,7 @@ static int msix_is_pending(PCIDevice *dev, int vector) return *msix_pending_byte(dev, vector) & msix_pending_mask(vector); } -static void msix_set_pending(PCIDevice *dev, int vector) +void msix_set_pending(PCIDevice *dev, unsigned int vector) { *msix_pending_byte(dev, vector) |= msix_pending_mask(vector); } @@ -75,13 +75,13 @@ static void msix_clr_pending(PCIDevice *dev, int vector) *msix_pending_byte(dev, vector) &= ~msix_pending_mask(vector); } -static bool msix_vector_masked(PCIDevice *dev, int vector, bool fmask) +static bool msix_vector_masked(PCIDevice *dev, unsigned int vector, bool fmask) { unsigned offset = vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL; return fmask || dev->msix_table[offset] & PCI_MSIX_ENTRY_CTRL_MASKBIT; } -static bool msix_is_masked(PCIDevice *dev, int vector) +bool msix_is_masked(PCIDevice *dev, unsigned int vector) { return msix_vector_masked(dev, vector, dev->msix_function_masked); } diff --git a/hw/pci/msix.h b/hw/pci/msix.h index ea85d02264..d0c4429843 100644 --- a/hw/pci/msix.h +++ b/hw/pci/msix.h @@ -26,6 +26,9 @@ void msix_load(PCIDevice *dev, QEMUFile *f); int msix_enabled(PCIDevice *dev); int msix_present(PCIDevice *dev); +bool msix_is_masked(PCIDevice *dev, unsigned vector); +void msix_set_pending(PCIDevice *dev, unsigned vector); + int msix_vector_use(PCIDevice *dev, unsigned vector); void msix_vector_unuse(PCIDevice *dev, unsigned vector); void msix_unuse_all_vectors(PCIDevice *dev); From 89d62be9f4fb538db7f919a2be7df2544ffc02c5 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 18 Dec 2012 14:02:46 +0200 Subject: [PATCH 2138/2270] virtio-pci: don't poll masked vectors At the moment, when irqfd is in use but a vector is masked, qemu will poll it and handle vector masks in userspace. Since almost no one ever looks at the pending bits, it is better to defer this until pending bits are actually read. Implement this optimization using the new poll notifier. Signed-off-by: Michael S. Tsirkin --- hw/virtio-pci.c | 52 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 37e8b2d255..af9a56c757 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -508,8 +508,6 @@ static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy, } return ret; } - - virtio_queue_set_guest_notifier_fd_handler(vq, true, true); return 0; } @@ -528,8 +526,6 @@ static void kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy, if (--irqfd->users == 0) { kvm_irqchip_release_virq(kvm_state, irqfd->virq); } - - virtio_queue_set_guest_notifier_fd_handler(vq, true, false); } static int kvm_virtio_pci_vector_use(PCIDevice *dev, unsigned vector, @@ -580,7 +576,36 @@ static void kvm_virtio_pci_vector_release(PCIDevice *dev, unsigned vector) } } -static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign) +static void kvm_virtio_pci_vector_poll(PCIDevice *dev, + unsigned int vector_start, + unsigned int vector_end) +{ + VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); + VirtIODevice *vdev = proxy->vdev; + int queue_no; + unsigned int vector; + EventNotifier *notifier; + VirtQueue *vq; + + for (queue_no = 0; queue_no < VIRTIO_PCI_QUEUE_MAX; queue_no++) { + if (!virtio_queue_get_num(vdev, queue_no)) { + break; + } + vector = virtio_queue_vector(vdev, queue_no); + if (vector < vector_start || vector >= vector_end || + !msix_is_masked(dev, vector)) { + continue; + } + vq = virtio_get_queue(vdev, queue_no); + notifier = virtio_queue_get_guest_notifier(vq); + if (event_notifier_test_and_clear(notifier)) { + msix_set_pending(dev, vector); + } + } +} + +static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign, + bool with_irqfd) { VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); VirtQueue *vq = virtio_get_queue(proxy->vdev, n); @@ -591,9 +616,9 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign) if (r < 0) { return r; } - virtio_queue_set_guest_notifier_fd_handler(vq, true, false); + virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd); } else { - virtio_queue_set_guest_notifier_fd_handler(vq, false, false); + virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd); event_notifier_cleanup(notifier); } @@ -611,9 +636,11 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, bool assign) VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); VirtIODevice *vdev = proxy->vdev; int r, n; + bool with_irqfd = msix_enabled(&proxy->pci_dev) && + kvm_msi_via_irqfd_enabled(); /* Must unset vector notifier while guest notifier is still assigned */ - if (kvm_msi_via_irqfd_enabled() && !assign) { + if (proxy->vector_irqfd && !assign) { msix_unset_vector_notifiers(&proxy->pci_dev); g_free(proxy->vector_irqfd); proxy->vector_irqfd = NULL; @@ -624,21 +651,22 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, bool assign) break; } - r = virtio_pci_set_guest_notifier(d, n, assign); + r = virtio_pci_set_guest_notifier(d, n, assign, + kvm_msi_via_irqfd_enabled()); if (r < 0) { goto assign_error; } } /* Must set vector notifier after guest notifier has been assigned */ - if (kvm_msi_via_irqfd_enabled() && assign) { + if (with_irqfd && assign) { proxy->vector_irqfd = g_malloc0(sizeof(*proxy->vector_irqfd) * msix_nr_vectors_allocated(&proxy->pci_dev)); r = msix_set_vector_notifiers(&proxy->pci_dev, kvm_virtio_pci_vector_use, kvm_virtio_pci_vector_release, - NULL); + kvm_virtio_pci_vector_poll); if (r < 0) { goto assign_error; } @@ -650,7 +678,7 @@ assign_error: /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */ assert(assign); while (--n >= 0) { - virtio_pci_set_guest_notifier(d, n, !assign); + virtio_pci_set_guest_notifier(d, n, !assign, with_irqfd); } return r; } From 62054c06d4d1d0d54ef87c2d9154efec00ad170c Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Sun, 23 Dec 2012 23:25:09 +0200 Subject: [PATCH 2139/2270] usb/redirect.c: unbreak compilation due to include/char/char.h Broken since: commit 927d4878b0ff319ed87fed9363f314613b0a5ed9 Author: Paolo Bonzini Date: Mon Dec 17 18:20:05 2012 +0100 softmmu: move remaining include files to include/ subdirectories Signed-off-by: Alon Levy Signed-off-by: Blue Swirl --- hw/usb/redirect.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index b65e8682b6..0abe1ff4d1 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -30,6 +30,7 @@ #include "monitor/monitor.h" #include "sysemu/sysemu.h" #include "qemu/iov.h" +#include "char/char.h" #include #include From 927fa909d5d5cf8c07673cd16a6d3bdc81250bc0 Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Fri, 28 Dec 2012 01:38:11 -0500 Subject: [PATCH 2140/2270] Disable semaphores fallback code for OpenBSD Disable the semaphores fallback code for OpenBSD as modern OpenBSD releases now have sem_timedwait(). Signed-off-by: Brad Smith Signed-off-by: Blue Swirl --- include/qemu/thread-posix.h | 2 +- qemu-thread-posix.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/qemu/thread-posix.h b/include/qemu/thread-posix.h index 380bae209b..0f30dccb53 100644 --- a/include/qemu/thread-posix.h +++ b/include/qemu/thread-posix.h @@ -12,7 +12,7 @@ struct QemuCond { }; struct QemuSemaphore { -#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__NetBSD__) pthread_mutex_t lock; pthread_cond_t cond; int count; diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c index 7be292ed68..6374df3328 100644 --- a/qemu-thread-posix.c +++ b/qemu-thread-posix.c @@ -122,7 +122,7 @@ void qemu_sem_init(QemuSemaphore *sem, int init) { int rc; -#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__NetBSD__) rc = pthread_mutex_init(&sem->lock, NULL); if (rc != 0) { error_exit(rc, __func__); @@ -147,7 +147,7 @@ void qemu_sem_destroy(QemuSemaphore *sem) { int rc; -#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__NetBSD__) rc = pthread_cond_destroy(&sem->cond); if (rc < 0) { error_exit(rc, __func__); @@ -168,7 +168,7 @@ void qemu_sem_post(QemuSemaphore *sem) { int rc; -#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__NetBSD__) pthread_mutex_lock(&sem->lock); if (sem->count == INT_MAX) { rc = EINVAL; @@ -206,7 +206,7 @@ int qemu_sem_timedwait(QemuSemaphore *sem, int ms) int rc; struct timespec ts; -#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__NetBSD__) compute_abs_deadline(&ts, ms); pthread_mutex_lock(&sem->lock); --sem->count; @@ -248,7 +248,7 @@ int qemu_sem_timedwait(QemuSemaphore *sem, int ms) void qemu_sem_wait(QemuSemaphore *sem) { -#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__NetBSD__) pthread_mutex_lock(&sem->lock); --sem->count; while (sem->count < 0) { From afcb92beac9e477e5ae5c36bf38830e225e2235f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Dec 2012 15:07:17 -0600 Subject: [PATCH 2141/2270] tcg: Add TCGV_IS_UNUSED_* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Aurelien Jarno Signed-off-by: Richard Henderson Reviewed-by: Andreas Färber Signed-off-by: Blue Swirl --- tcg/tcg-op.h | 2 ++ tcg/tcg.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 0b3cb0be3a..91c9d80dd5 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -2329,6 +2329,7 @@ static inline void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, #define tcg_gen_qemu_ldst_op tcg_gen_op3i_i32 #define tcg_gen_qemu_ldst_op_i64 tcg_gen_qemu_ldst_op_i64_i32 #define TCGV_UNUSED(x) TCGV_UNUSED_I32(x) +#define TCGV_IS_UNUSED(x) TCGV_IS_UNUSED_I32(x) #define TCGV_EQUAL(a, b) TCGV_EQUAL_I32(a, b) #else #define TCGv TCGv_i64 @@ -2340,6 +2341,7 @@ static inline void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, #define tcg_gen_qemu_ldst_op tcg_gen_op3i_i64 #define tcg_gen_qemu_ldst_op_i64 tcg_gen_qemu_ldst_op_i64_i64 #define TCGV_UNUSED(x) TCGV_UNUSED_I64(x) +#define TCGV_IS_UNUSED(x) TCGV_IS_UNUSED_I64(x) #define TCGV_EQUAL(a, b) TCGV_EQUAL_I64(a, b) #endif diff --git a/tcg/tcg.h b/tcg/tcg.h index b2e2a25653..a4279725a6 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -270,6 +270,9 @@ typedef int TCGv_i64; #define TCGV_UNUSED_I32(x) x = MAKE_TCGV_I32(-1) #define TCGV_UNUSED_I64(x) x = MAKE_TCGV_I64(-1) +#define TCGV_IS_UNUSED_I32(x) (GET_TCGV_I32(x) == -1) +#define TCGV_IS_UNUSED_I64(x) (GET_TCGV_I64(x) == -1) + /* call flags */ /* Helper does not read globals (either directly or through an exception). It implies TCG_CALL_NO_WRITE_GLOBALS. */ From 76a347e1cd0c2d6959461c89dda15ef5c4140da6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 28 Dec 2012 14:17:02 -0800 Subject: [PATCH 2142/2270] tcg-i386: Perform cmov detection at runtime for 32-bit. Existing compile-time detection is spotty at best. Convert it all to runtime detection instead. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- configure | 19 +++++++++++++++++++ tcg/i386/tcg-target.c | 31 ++++++++++++++++++++++++++++++- tcg/i386/tcg-target.h | 5 ----- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/configure b/configure index 99c1ec3467..b0c7e542c6 100755 --- a/configure +++ b/configure @@ -3086,6 +3086,21 @@ if compile_prog "" "" ; then has_environ=yes fi +######################################## +# check if cpuid.h is usable. + +cpuid_h=no +cat > $TMPC << EOF +#include +int main(void) { + return 0; +} +EOF +if compile_prog "" "" ; then + cpuid_h=yes +fi + + ########################################## # End of CC checks # After here, no more $cc or $ld runs @@ -3611,6 +3626,10 @@ if test "$has_environ" = "yes" ; then echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak fi +if test "$cpuid_h" = "yes" ; then + echo "CONFIG_CPUID_H=y" >> $config_host_mak +fi + if test "$glusterfs" = "yes" ; then echo "CONFIG_GLUSTERFS=y" >> $config_host_mak fi diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index ae8274652a..e0838748a9 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -97,6 +97,18 @@ static const int tcg_target_call_oarg_regs[] = { # define TCG_REG_L1 TCG_REG_EDX #endif +/* For 32-bit, we are going to attempt to determine at runtime whether cmov + is available. However, the host compiler must supply , as we're + not going to go so far as our own inline assembly. */ +#if TCG_TARGET_REG_BITS == 64 +# define have_cmov 1 +#elif defined(CONFIG_CPUID_H) +#include +static bool have_cmov; +#else +# define have_cmov 0 +#endif + static uint8_t *tb_ret_addr; static void patch_reloc(uint8_t *code_ptr, int type, @@ -943,7 +955,14 @@ static void tcg_out_movcond32(TCGContext *s, TCGCond cond, TCGArg dest, TCGArg v1) { tcg_out_cmp(s, c1, c2, const_c2, 0); - tcg_out_modrm(s, OPC_CMOVCC | tcg_cond_to_jcc[cond], dest, v1); + if (have_cmov) { + tcg_out_modrm(s, OPC_CMOVCC | tcg_cond_to_jcc[cond], dest, v1); + } else { + int over = gen_new_label(); + tcg_out_jxx(s, tcg_cond_to_jcc[tcg_invert_cond(cond)], over, 1); + tcg_out_mov(s, TCG_TYPE_I32, dest, v1); + tcg_out_label(s, over, s->code_ptr); + } } #if TCG_TARGET_REG_BITS == 64 @@ -2243,6 +2262,16 @@ static void tcg_target_qemu_prologue(TCGContext *s) static void tcg_target_init(TCGContext *s) { + /* For 32-bit, 99% certainty that we're running on hardware that supports + cmov, but we still need to check. In case cmov is not available, we'll + use a small forward branch. */ +#ifndef have_cmov + { + unsigned a, b, c, d; + have_cmov = (__get_cpuid(1, &a, &b, &c, &d) && (d & bit_CMOV)); + } +#endif + #if !defined(CONFIG_USER_ONLY) /* fail safe */ if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry)) diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index 5352ac0254..e63db9cfe9 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -91,12 +91,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 1 -#if defined(__x86_64__) || defined(__i686__) -/* Use cmov only if the compiler is already doing so. */ #define TCG_TARGET_HAS_movcond_i32 1 -#else -#define TCG_TARGET_HAS_movcond_i32 0 -#endif #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_div2_i64 1 From 753d99d38b5877440dde2705e30ca60e2ec62965 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 28 Dec 2012 14:19:35 -0800 Subject: [PATCH 2143/2270] tcg-hppa: Fix typo in brcond2 Reported-by: Stuart Brady Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- tcg/hppa/tcg-target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c index 5b27cf6f12..656e73621a 100644 --- a/tcg/hppa/tcg-target.c +++ b/tcg/hppa/tcg-target.c @@ -824,7 +824,7 @@ static void tcg_out_brcond2(TCGContext *s, int cond, TCGArg al, TCGArg ah, tcg_out_brcond(s, TCG_COND_EQ, ah, bh, bhconst, label_index); break; case TCG_COND_NE: - tcg_out_brcond(s, TCG_COND_NE, al, bl, bhconst, label_index); + tcg_out_brcond(s, TCG_COND_NE, al, bl, blconst, label_index); tcg_out_brcond(s, TCG_COND_NE, ah, bh, bhconst, label_index); break; default: From a795ef8dcb8cbadffc996c41ff38927a97645234 Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Fri, 28 Dec 2012 01:00:26 -0500 Subject: [PATCH 2144/2270] Fix semaphores fallback code As reported in bug 1087114 the semaphores fallback code is broken which results in QEMU crashing and making QEMU unusable. This patch is from Paolo. This needs to be back ported to the 1.3 stable tree as well. Signed-off-by: Paolo Bonzini Signed-off-by: Brad Smith Signed-off-by: Blue Swirl --- qemu-thread-posix.c | 1 + 1 file changed, 1 insertion(+) diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c index 6374df3328..4489abf1d8 100644 --- a/qemu-thread-posix.c +++ b/qemu-thread-posix.c @@ -213,6 +213,7 @@ int qemu_sem_timedwait(QemuSemaphore *sem, int ms) while (sem->count < 0) { rc = pthread_cond_timedwait(&sem->cond, &sem->lock, &ts); if (rc == ETIMEDOUT) { + ++sem->count; break; } if (rc != 0) { From eec8972a5bc744eda695a86a984d746c240dff90 Mon Sep 17 00:00:00 2001 From: Petar Jovanovic Date: Thu, 6 Dec 2012 20:30:35 +0100 Subject: [PATCH 2145/2270] target-mips: Fix incorrect reads and writes to DSPControl register Upper 4 bits of ccond (bits 31..28 ) of DSPControl register are not used in the MIPS32 architecture. They are used in the MIPS64 architecture. For MIPS32 these bits must be written as zero, and return zero on read. The change fixes writes (WRDSP) and reads (RDDSP) to the register. It also fixes the tests that use these instructions, and makes them smaller and simpler. Signed-off-by: Petar Jovanovic Signed-off-by: Aurelien Jarno --- target-mips/dsp_helper.c | 8 ++++++++ tests/tcg/mips/mips32-dsp/rddsp.c | 32 ++++++++++++------------------- tests/tcg/mips/mips32-dsp/wrdsp.c | 32 ++++++++++++------------------- 3 files changed, 32 insertions(+), 40 deletions(-) diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index 14daf91950..acf7ceb1d1 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -3948,7 +3948,11 @@ void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env) if (mask[4] == 1) { overwrite &= 0x00FFFFFF; newbits &= 0x00FFFFFF; +#if defined(TARGET_MIPS64) newbits |= 0xFF000000 & rs; +#else + newbits |= 0x0F000000 & rs; +#endif } if (mask[5] == 1) { @@ -3999,7 +4003,11 @@ target_ulong helper_rddsp(target_ulong masknum, CPUMIPSState *env) } if (mask[4] == 1) { +#if defined(TARGET_MIPS64) temp |= dsp & 0xFF000000; +#else + temp |= dsp & 0x0F000000; +#endif } if (mask[5] == 1) { diff --git a/tests/tcg/mips/mips32-dsp/rddsp.c b/tests/tcg/mips/mips32-dsp/rddsp.c index e8948ec1d9..2f30285033 100644 --- a/tests/tcg/mips/mips32-dsp/rddsp.c +++ b/tests/tcg/mips/mips32-dsp/rddsp.c @@ -6,14 +6,13 @@ int main() int dsp_i, dsp_o; int ccond_i, outflag_i, efi_i, c_i, scount_i, pos_i; int ccond_o, outflag_o, efi_o, c_o, scount_o, pos_o; - int ccond_r, outflag_r, efi_r, c_r, scount_r, pos_r; - ccond_i = 0x000000BC;/* 4 */ - outflag_i = 0x0000001B;/* 3 */ - efi_i = 0x00000001;/* 5 */ - c_i = 0x00000001;/* 2 */ - scount_i = 0x0000000F;/* 1 */ - pos_i = 0x0000000C;/* 0 */ + ccond_i = 0x0000000C; /* 4 */ + outflag_i = 0x0000001B; /* 3 */ + efi_i = 0x00000001; /* 5 */ + c_i = 0x00000001; /* 2 */ + scount_i = 0x0000000F; /* 1 */ + pos_i = 0x0000000C; /* 0 */ dsp_i = (ccond_i << 24) | \ (outflag_i << 16) | \ @@ -22,13 +21,6 @@ int main() (scount_i << 7) | \ pos_i; - ccond_r = ccond_i; - outflag_r = outflag_i; - efi_r = efi_i; - c_r = c_i; - scount_r = scount_i; - pos_r = pos_i; - __asm ("wrdsp %1, 0x3F\n\t" "rddsp %0, 0x3F\n\t" @@ -43,12 +35,12 @@ int main() scount_o = (dsp_o >> 7) & 0x3F; pos_o = dsp_o & 0x1F; - assert(ccond_o == ccond_r); - assert(outflag_o == outflag_r); - assert(efi_o == efi_r); - assert(c_o == c_r); - assert(scount_o == scount_r); - assert(pos_o == pos_r); + assert(ccond_o == ccond_i); + assert(outflag_o == outflag_i); + assert(efi_o == efi_i); + assert(c_o == c_i); + assert(scount_o == scount_i); + assert(pos_o == pos_i); return 0; } diff --git a/tests/tcg/mips/mips32-dsp/wrdsp.c b/tests/tcg/mips/mips32-dsp/wrdsp.c index e8948ec1d9..dc54943a99 100644 --- a/tests/tcg/mips/mips32-dsp/wrdsp.c +++ b/tests/tcg/mips/mips32-dsp/wrdsp.c @@ -6,14 +6,13 @@ int main() int dsp_i, dsp_o; int ccond_i, outflag_i, efi_i, c_i, scount_i, pos_i; int ccond_o, outflag_o, efi_o, c_o, scount_o, pos_o; - int ccond_r, outflag_r, efi_r, c_r, scount_r, pos_r; - ccond_i = 0x000000BC;/* 4 */ - outflag_i = 0x0000001B;/* 3 */ - efi_i = 0x00000001;/* 5 */ - c_i = 0x00000001;/* 2 */ - scount_i = 0x0000000F;/* 1 */ - pos_i = 0x0000000C;/* 0 */ + ccond_i = 0x000000BC; /* 4 */ + outflag_i = 0x0000001B; /* 3 */ + efi_i = 0x00000001; /* 5 */ + c_i = 0x00000001; /* 2 */ + scount_i = 0x0000000F; /* 1 */ + pos_i = 0x0000000C; /* 0 */ dsp_i = (ccond_i << 24) | \ (outflag_i << 16) | \ @@ -22,13 +21,6 @@ int main() (scount_i << 7) | \ pos_i; - ccond_r = ccond_i; - outflag_r = outflag_i; - efi_r = efi_i; - c_r = c_i; - scount_r = scount_i; - pos_r = pos_i; - __asm ("wrdsp %1, 0x3F\n\t" "rddsp %0, 0x3F\n\t" @@ -43,12 +35,12 @@ int main() scount_o = (dsp_o >> 7) & 0x3F; pos_o = dsp_o & 0x1F; - assert(ccond_o == ccond_r); - assert(outflag_o == outflag_r); - assert(efi_o == efi_r); - assert(c_o == c_r); - assert(scount_o == scount_r); - assert(pos_o == pos_r); + assert(ccond_o == (ccond_i & 0x0F)); + assert(outflag_o == outflag_i); + assert(efi_o == efi_i); + assert(c_o == c_i); + assert(scount_o == scount_i); + assert(pos_o == pos_i); return 0; } From b8abbbe8df5e04085f4b85fc4f7cf85efbcd492c Mon Sep 17 00:00:00 2001 From: Petar Jovanovic Date: Mon, 10 Dec 2012 16:28:17 +0100 Subject: [PATCH 2146/2270] target-mips: Fix for helpers for EXTR_* instructions The change removes some unnecessary and incorrect code for EXTR_S.H. Further, it corrects the mask for shift value in the EXTR_ instructions. It also extends the existing tests so they trigger the issues corrected with the change. Signed-off-by: Petar Jovanovic Signed-off-by: Aurelien Jarno --- target-mips/dsp_helper.c | 45 ++++++-------------------- tests/tcg/mips/mips32-dsp/extr_r_w.c | 23 +++++++++++++ tests/tcg/mips/mips32-dsp/extr_rs_w.c | 23 +++++++++++++ tests/tcg/mips/mips32-dsp/extr_s_h.c | 23 +++++++++++++ tests/tcg/mips/mips32-dsp/extr_w.c | 23 +++++++++++++ tests/tcg/mips/mips32-dsp/extrv_r_w.c | 25 ++++++++++++++ tests/tcg/mips/mips32-dsp/extrv_rs_w.c | 25 ++++++++++++++ tests/tcg/mips/mips32-dsp/extrv_s_h.c | 17 ++++++++++ tests/tcg/mips/mips32-dsp/extrv_w.c | 26 +++++++++++++++ 9 files changed, 195 insertions(+), 35 deletions(-) diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index acf7ceb1d1..ee0c8724c7 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -484,35 +484,6 @@ static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b) return (temp >> 1) & 0x00FF; } -static inline int64_t mipsdsp_rashift_short_acc(int32_t ac, - int32_t shift, - CPUMIPSState *env) -{ - int32_t sign, temp31; - int64_t temp, acc; - - sign = (env->active_tc.HI[ac] >> 31) & 0x01; - acc = ((int64_t)env->active_tc.HI[ac] << 32) | - ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF); - if (shift == 0) { - temp = acc; - } else { - if (sign == 0) { - temp = (((int64_t)0x01 << (32 - shift + 1)) - 1) & (acc >> shift); - } else { - temp = ((((int64_t)0x01 << (shift + 1)) - 1) << (32 - shift)) | - (acc >> shift); - } - } - - temp31 = (temp >> 31) & 0x01; - if (sign != temp31) { - set_DSPControl_overflow_flag(1, 23, env); - } - - return temp; -} - /* 128 bits long. p[0] is LO, p[1] is HI. */ static inline void mipsdsp_rndrashift_short_acc(int64_t *p, int32_t ac, @@ -3407,7 +3378,7 @@ target_ulong helper_extr_w(target_ulong ac, target_ulong shift, int32_t tempI; int64_t tempDL[2]; - shift = shift & 0x0F; + shift = shift & 0x1F; mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env); if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && @@ -3435,7 +3406,7 @@ target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift, { int64_t tempDL[2]; - shift = shift & 0x0F; + shift = shift & 0x1F; mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env); if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && @@ -3462,7 +3433,7 @@ target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift, int32_t tempI, temp64; int64_t tempDL[2]; - shift = shift & 0x0F; + shift = shift & 0x1F; mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env); if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && @@ -3645,11 +3616,15 @@ target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift, target_ulong helper_extr_s_h(target_ulong ac, target_ulong shift, CPUMIPSState *env) { - int64_t temp; + int64_t temp, acc; - shift = shift & 0x0F; + shift = shift & 0x1F; + + acc = ((int64_t)env->active_tc.HI[ac] << 32) | + ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF); + + temp = acc >> shift; - temp = mipsdsp_rashift_short_acc(ac, shift, env); if (temp > (int64_t)0x7FFF) { temp = 0x00007FFF; set_DSPControl_overflow_flag(1, 23, env); diff --git a/tests/tcg/mips/mips32-dsp/extr_r_w.c b/tests/tcg/mips/mips32-dsp/extr_r_w.c index 0beeefd366..02e022427a 100644 --- a/tests/tcg/mips/mips32-dsp/extr_r_w.c +++ b/tests/tcg/mips/mips32-dsp/extr_r_w.c @@ -44,5 +44,28 @@ int main() assert(dsp == 0); assert(result == rt); + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + ach = 0x3fffffff; + acl = 0x2bcdef01; + result = 0x7ffffffe; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_r.w %0, $ac1, 0x1F\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + return 0; } diff --git a/tests/tcg/mips/mips32-dsp/extr_rs_w.c b/tests/tcg/mips/mips32-dsp/extr_rs_w.c index 24c748db20..c3a22ee704 100644 --- a/tests/tcg/mips/mips32-dsp/extr_rs_w.c +++ b/tests/tcg/mips/mips32-dsp/extr_rs_w.c @@ -44,5 +44,28 @@ int main() assert(dsp == 0); assert(result == rt); + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + ach = 0x3fffffff; + acl = 0x2bcdef01; + result = 0x7ffffffe; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_rs.w %0, $ac1, 0x1F\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + return 0; } diff --git a/tests/tcg/mips/mips32-dsp/extr_s_h.c b/tests/tcg/mips/mips32-dsp/extr_s_h.c index b2129134c8..9bc2a63cc2 100644 --- a/tests/tcg/mips/mips32-dsp/extr_s_h.c +++ b/tests/tcg/mips/mips32-dsp/extr_s_h.c @@ -59,5 +59,28 @@ int main() assert(dsp == 0); assert(result == rt); + /* Clear dsp */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + ach = 0x123; + acl = 0x87654321; + result = 0x1238; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_s.h %0, $ac1, 28\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + return 0; } diff --git a/tests/tcg/mips/mips32-dsp/extr_w.c b/tests/tcg/mips/mips32-dsp/extr_w.c index 02ab9ecaae..bd6b0b95c2 100644 --- a/tests/tcg/mips/mips32-dsp/extr_w.c +++ b/tests/tcg/mips/mips32-dsp/extr_w.c @@ -44,5 +44,28 @@ int main() assert(dsp == 0); assert(result == rt); + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + ach = 0x3fffffff; + acl = 0x2bcdef01; + result = 0x7ffffffe; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr.w %0, $ac1, 0x1F\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + return 0; } diff --git a/tests/tcg/mips/mips32-dsp/extrv_r_w.c b/tests/tcg/mips/mips32-dsp/extrv_r_w.c index 005807b142..2403b3afe4 100644 --- a/tests/tcg/mips/mips32-dsp/extrv_r_w.c +++ b/tests/tcg/mips/mips32-dsp/extrv_r_w.c @@ -50,5 +50,30 @@ int main() assert(dsp == 0); assert(result == rt); + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + rs = 31; + ach = 0x3fffffff; + acl = 0x2bcdef01; + result = 0x7ffffffe; + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_r.w %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + return 0; } diff --git a/tests/tcg/mips/mips32-dsp/extrv_rs_w.c b/tests/tcg/mips/mips32-dsp/extrv_rs_w.c index c2d8513bb6..ccceeb9f4c 100644 --- a/tests/tcg/mips/mips32-dsp/extrv_rs_w.c +++ b/tests/tcg/mips/mips32-dsp/extrv_rs_w.c @@ -48,5 +48,30 @@ int main() assert(dsp == 0); assert(result == rt); + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + rs = 0x1F; + ach = 0x3fffffff; + acl = 0x2bcdef01; + result = 0x7ffffffe; + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_rs.w %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + return 0; } diff --git a/tests/tcg/mips/mips32-dsp/extrv_s_h.c b/tests/tcg/mips/mips32-dsp/extrv_s_h.c index 8c13b5eda5..feac3e2e33 100644 --- a/tests/tcg/mips/mips32-dsp/extrv_s_h.c +++ b/tests/tcg/mips/mips32-dsp/extrv_s_h.c @@ -67,5 +67,22 @@ int main() assert(dsp == 0); assert(result == rt); + rs = 0x1C; + ach = 0x123; + acl = 0x87654321; + result = 0x1238; + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv_s.h %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + return 0; } diff --git a/tests/tcg/mips/mips32-dsp/extrv_w.c b/tests/tcg/mips/mips32-dsp/extrv_w.c index 9cb493df39..9e8b238a04 100644 --- a/tests/tcg/mips/mips32-dsp/extrv_w.c +++ b/tests/tcg/mips/mips32-dsp/extrv_w.c @@ -50,5 +50,31 @@ int main() assert(dsp == 0); assert(result == rt); + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + rs = 31; + ach = 0x3fffffff; + acl = 0x2bcdef01; + result = 0x7ffffffe; + __asm + ("wrdsp %1, 0x01\n\t" + "mthi %3, $ac1\n\t" + "mtlo %4, $ac1\n\t" + "extrv.w %0, $ac1, %2\n\t" + "rddsp %1\n\t" + : "=r"(rt), "+r"(dsp) + : "r"(rs), "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + + return 0; } From 79eb8392db19a916f6a3277f7cd36fb22c2bdbaf Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 22 Dec 2012 13:38:19 +0100 Subject: [PATCH 2147/2270] target-mips: Remove semicolon from macro definition Macro RESTORE_FLUSH_MODE is similar to RESTORE_ROUNDING_MODE but included a semicolon. The code which uses that macro also includes a semicolon, so the result was an empty statement. Remove the superfluous semicolon from the macro definition. Signed-off-by: Stefan Weil Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index e85edce6fa..e3ab05cbb0 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2175,7 +2175,7 @@ static unsigned int ieee_rm[] = { set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], &env->active_fpu.fp_status) #define RESTORE_FLUSH_MODE \ - set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0, &env->active_fpu.fp_status); + set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0, &env->active_fpu.fp_status) target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg) { From fe65a1fad6aa140769ffda31c34a109f7d2df101 Mon Sep 17 00:00:00 2001 From: Dongxue Zhang Date: Tue, 11 Dec 2012 22:28:28 +0800 Subject: [PATCH 2148/2270] Fix my email address Fix my email address, last time it's wrong. Signed-off-by: Dongxue Zhang Signed-off-by: Aurelien Jarno --- target-mips/dsp_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index ee0c8724c7..a33e2bf9fd 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -2,7 +2,7 @@ * MIPS ASE DSP Instruction emulation helpers for QEMU. * * Copyright (c) 2012 Jia Liu - * Dongxue Zhang + * Dongxue Zhang * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either From c4aaba92e516ad061dff7ac2ae3c2b2b7058c404 Mon Sep 17 00:00:00 2001 From: "Jovanovic, Petar" Date: Tue, 11 Dec 2012 15:06:35 +0000 Subject: [PATCH 2149/2270] target-mips: Make repl_ph to sign extend to target-long The immediate value is 9bits, should sign-extend to 16bits. The return value to register should sign-extend to target_long, as Richard says, removing an unnecessary cast works fun. Signed-off-by: Dongxue Zhang Signed-off-by: Aurelien Jarno --- target-mips/translate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index e81ff38476..6281e70471 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -13769,9 +13769,10 @@ static void gen_mipsdsp_bitinsn(CPUMIPSState *env, DisasContext *ctx, check_dsp(ctx); { imm = (ctx->opcode >> 16) & 0x03FF; + imm = (int16_t)(imm << 6) >> 6; tcg_gen_movi_tl(cpu_gpr[ret], \ (target_long)((int32_t)imm << 16 | \ - (uint32_t)(uint16_t)imm)); + (uint16_t)imm)); } break; case OPC_REPLV_PH: From 0f0b93980572726e69e32ff13e2d7fb72b936157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B3=E9=9F=8B=E4=BB=BB=20=28Wei-Ren=20Chen=29?= Date: Tue, 11 Dec 2012 00:15:55 +0800 Subject: [PATCH 2150/2270] target-mips: Use EXCP_SC rather than a magic number From the discussion on the ML [1], the exception limit defined by magic number 0x100 is actually EXCP_SC defined in cpu.h. Replace the magic number with EXCP_SC. Remove "#if 1 .. #endif" as well. [1] http://lists.gnu.org/archive/html/qemu-devel/2012-11/msg03080.html Signed-off-by: Chen Wei-Ren Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index e3ab05cbb0..d833d78b4f 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -38,10 +38,9 @@ static inline void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, int error_code, uintptr_t pc) { -#if 1 - if (exception < 0x100) + if (exception < EXCP_SC) { qemu_log("%s: %d %d\n", __func__, exception, error_code); -#endif + } env->exception_index = exception; env->error_code = error_code; From 5928023cef87847a295035487397b9ec701fdd6b Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 24 Nov 2012 23:03:13 +0100 Subject: [PATCH 2151/2270] pflash_cfi01: Suppress warning when Linux probes for AMD flash There are several ARM and MIPS boards which are manufactured with either Intel (pflash_cfi01.c) or AMD (pflash_cfi02.c) flash memory. The Linux kernel supports both and first probes for AMD flash which resulted in one or two warnings from the Intel flash emulation: pflash_write: Unimplemented flash cmd sequence (offset 0000000000000000, wcycle 0x0 cmd 0x0 value 0xf000f0) pflash_write: Unimplemented flash cmd sequence (offset 0000000000000000, wcycle 0x0 cmd 0x0 value 0xf0) These warnings confuse users, so suppress them. Signed-off-by: Stefan Weil Signed-off-by: Aurelien Jarno --- hw/pflash_cfi01.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index 95e07e7cdb..aadedefb25 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -319,6 +319,9 @@ static void pflash_write(pflash_t *pfl, hwaddr offset, DPRINTF("%s: Write to buffer\n", __func__); pfl->status |= 0x80; /* Ready! */ break; + case 0xf0: /* Probe for AMD flash */ + DPRINTF("%s: Probe for AMD flash\n", __func__); + goto reset_flash; case 0xff: /* Read array mode */ DPRINTF("%s: Read array mode\n", __func__); goto reset_flash; From 4065742ac0f3c84abdd8d718b44a88f3ac56015a Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 14 Nov 2012 11:43:23 +0100 Subject: [PATCH 2152/2270] raw-posix: add raw_get_aio_fd() for virtio-blk-data-plane The raw_get_aio_fd() function allows virtio-blk-data-plane to get the file descriptor of a raw image file with Linux AIO enabled. This interface is really a layering violation that can be resolved once the block layer is able to run outside the global mutex - at that point virtio-blk-data-plane will switch from custom Linux AIO code to using the block layer. Signed-off-by: Stefan Hajnoczi --- block/raw-posix.c | 34 ++++++++++++++++++++++++++++++++++ include/block/block.h | 9 +++++++++ 2 files changed, 43 insertions(+) diff --git a/block/raw-posix.c b/block/raw-posix.c index 91159c7887..87d888ed01 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -1776,6 +1776,40 @@ static BlockDriver bdrv_host_cdrom = { }; #endif /* __FreeBSD__ */ +#ifdef CONFIG_LINUX_AIO +/** + * Return the file descriptor for Linux AIO + * + * This function is a layering violation and should be removed when it becomes + * possible to call the block layer outside the global mutex. It allows the + * caller to hijack the file descriptor so I/O can be performed outside the + * block layer. + */ +int raw_get_aio_fd(BlockDriverState *bs) +{ + BDRVRawState *s; + + if (!bs->drv) { + return -ENOMEDIUM; + } + + if (bs->drv == bdrv_find_format("raw")) { + bs = bs->file; + } + + /* raw-posix has several protocols so just check for raw_aio_readv */ + if (bs->drv->bdrv_aio_readv != raw_aio_readv) { + return -ENOTSUP; + } + + s = bs->opaque; + if (!s->use_aio) { + return -ENOTSUP; + } + return s->fd; +} +#endif /* CONFIG_LINUX_AIO */ + static void bdrv_file_init(void) { /* diff --git a/include/block/block.h b/include/block/block.h index b81d200b03..0719339231 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -365,6 +365,15 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs); void bdrv_set_in_use(BlockDriverState *bs, int in_use); int bdrv_in_use(BlockDriverState *bs); +#ifdef CONFIG_LINUX_AIO +int raw_get_aio_fd(BlockDriverState *bs); +#else +static inline int raw_get_aio_fd(BlockDriverState *bs) +{ + return -ENOTSUP; +} +#endif + enum BlockAcctType { BDRV_ACCT_READ, BDRV_ACCT_WRITE, From 583f6e7bbd24b31f7eecd5c21ba0a5a5a77f52f1 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 14 Nov 2012 15:04:15 +0100 Subject: [PATCH 2153/2270] configure: add CONFIG_VIRTIO_BLK_DATA_PLANE The virtio-blk-data-plane feature only works with Linux AIO. Therefore add a ./configure option and necessary checks to implement this dependency. Signed-off-by: Stefan Hajnoczi --- configure | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/configure b/configure index b0c7e542c6..cc1e20ac54 100755 --- a/configure +++ b/configure @@ -223,6 +223,7 @@ libiscsi="" coroutine="" seccomp="" glusterfs="" +virtio_blk_data_plane="" # parse CC options first for opt do @@ -882,6 +883,10 @@ for opt do ;; --enable-glusterfs) glusterfs="yes" ;; + --disable-virtio-blk-data-plane) virtio_blk_data_plane="no" + ;; + --enable-virtio-blk-data-plane) virtio_blk_data_plane="yes" + ;; *) echo "ERROR: unknown option $opt"; show_help="yes" ;; esac @@ -2273,6 +2278,17 @@ EOF fi fi +########################################## +# adjust virtio-blk-data-plane based on linux-aio + +if test "$virtio_blk_data_plane" = "yes" -a \ + "$linux_aio" != "yes" ; then + echo "Error: virtio-blk-data-plane requires Linux AIO, please try --enable-linux-aio" + exit 1 +elif test -z "$virtio_blk_data_plane" ; then + virtio_blk_data_plane=$linux_aio +fi + ########################################## # attr probe @@ -3289,6 +3305,7 @@ echo "build guest agent $guest_agent" echo "seccomp support $seccomp" echo "coroutine backend $coroutine_backend" echo "GlusterFS support $glusterfs" +echo "virtio-blk-data-plane $virtio_blk_data_plane" if test "$sdl_too_old" = "yes"; then echo "-> Your SDL version is too old - please upgrade to have SDL support" @@ -3634,6 +3651,10 @@ if test "$glusterfs" = "yes" ; then echo "CONFIG_GLUSTERFS=y" >> $config_host_mak fi +if test "$virtio_blk_data_plane" = "yes" ; then + echo "CONFIG_VIRTIO_BLK_DATA_PLANE=y" >> $config_host_mak +fi + # USB host support case "$usb" in linux) From 185ecf40e3589fc2717b0856ee1df05dd63a46dd Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 20 Nov 2012 10:30:08 +0100 Subject: [PATCH 2154/2270] dataplane: add host memory mapping code The data plane thread needs to map guest physical addresses to host pointers. Normally this is done with cpu_physical_memory_map() but the function assumes the global mutex is held. The data plane thread does not touch the global mutex and therefore needs a thread-safe memory mapping mechanism. Hostmem registers a MemoryListener similar to how vhost collects and pushes memory region information into the kernel. There is a fine-grained lock on the regions list which is held during lookup and when installing a new regions list. When the physical memory map changes the MemoryListener callbacks are invoked. They build up a new list of memory regions which is finally installed when the list has been completed. Signed-off-by: Stefan Hajnoczi --- hw/Makefile.objs | 2 +- hw/dataplane/Makefile.objs | 3 + hw/dataplane/hostmem.c | 176 +++++++++++++++++++++++++++++++++++++ hw/dataplane/hostmem.h | 57 ++++++++++++ 4 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 hw/dataplane/Makefile.objs create mode 100644 hw/dataplane/hostmem.c create mode 100644 hw/dataplane/hostmem.h diff --git a/hw/Makefile.objs b/hw/Makefile.objs index d75f2f0bd7..5ac49134bd 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -1,4 +1,4 @@ -common-obj-y = usb/ ide/ pci/ +common-obj-y = usb/ ide/ pci/ dataplane/ common-obj-y += loader.o common-obj-$(CONFIG_VIRTIO) += virtio-console.o common-obj-$(CONFIG_VIRTIO) += virtio-rng.o diff --git a/hw/dataplane/Makefile.objs b/hw/dataplane/Makefile.objs new file mode 100644 index 0000000000..8c8dea1b21 --- /dev/null +++ b/hw/dataplane/Makefile.objs @@ -0,0 +1,3 @@ +ifeq ($(CONFIG_VIRTIO), y) +common-obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += hostmem.o +endif diff --git a/hw/dataplane/hostmem.c b/hw/dataplane/hostmem.c new file mode 100644 index 0000000000..380537e06d --- /dev/null +++ b/hw/dataplane/hostmem.c @@ -0,0 +1,176 @@ +/* + * Thread-safe guest to host memory mapping + * + * Copyright 2012 Red Hat, Inc. and/or its affiliates + * + * Authors: + * Stefan Hajnoczi + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "exec/address-spaces.h" +#include "hostmem.h" + +static int hostmem_lookup_cmp(const void *phys_, const void *region_) +{ + hwaddr phys = *(const hwaddr *)phys_; + const HostMemRegion *region = region_; + + if (phys < region->guest_addr) { + return -1; + } else if (phys >= region->guest_addr + region->size) { + return 1; + } else { + return 0; + } +} + +/** + * Map guest physical address to host pointer + */ +void *hostmem_lookup(HostMem *hostmem, hwaddr phys, hwaddr len, bool is_write) +{ + HostMemRegion *region; + void *host_addr = NULL; + hwaddr offset_within_region; + + qemu_mutex_lock(&hostmem->current_regions_lock); + region = bsearch(&phys, hostmem->current_regions, + hostmem->num_current_regions, + sizeof(hostmem->current_regions[0]), + hostmem_lookup_cmp); + if (!region) { + goto out; + } + if (is_write && region->readonly) { + goto out; + } + offset_within_region = phys - region->guest_addr; + if (len <= region->size - offset_within_region) { + host_addr = region->host_addr + offset_within_region; + } +out: + qemu_mutex_unlock(&hostmem->current_regions_lock); + + return host_addr; +} + +/** + * Install new regions list + */ +static void hostmem_listener_commit(MemoryListener *listener) +{ + HostMem *hostmem = container_of(listener, HostMem, listener); + + qemu_mutex_lock(&hostmem->current_regions_lock); + g_free(hostmem->current_regions); + hostmem->current_regions = hostmem->new_regions; + hostmem->num_current_regions = hostmem->num_new_regions; + qemu_mutex_unlock(&hostmem->current_regions_lock); + + /* Reset new regions list */ + hostmem->new_regions = NULL; + hostmem->num_new_regions = 0; +} + +/** + * Add a MemoryRegionSection to the new regions list + */ +static void hostmem_append_new_region(HostMem *hostmem, + MemoryRegionSection *section) +{ + void *ram_ptr = memory_region_get_ram_ptr(section->mr); + size_t num = hostmem->num_new_regions; + size_t new_size = (num + 1) * sizeof(hostmem->new_regions[0]); + + hostmem->new_regions = g_realloc(hostmem->new_regions, new_size); + hostmem->new_regions[num] = (HostMemRegion){ + .host_addr = ram_ptr + section->offset_within_region, + .guest_addr = section->offset_within_address_space, + .size = section->size, + .readonly = section->readonly, + }; + hostmem->num_new_regions++; +} + +static void hostmem_listener_append_region(MemoryListener *listener, + MemoryRegionSection *section) +{ + HostMem *hostmem = container_of(listener, HostMem, listener); + + /* Ignore non-RAM regions, we may not be able to map them */ + if (!memory_region_is_ram(section->mr)) { + return; + } + + /* Ignore regions with dirty logging, we cannot mark them dirty */ + if (memory_region_is_logging(section->mr)) { + return; + } + + hostmem_append_new_region(hostmem, section); +} + +/* We don't implement most MemoryListener callbacks, use these nop stubs */ +static void hostmem_listener_dummy(MemoryListener *listener) +{ +} + +static void hostmem_listener_section_dummy(MemoryListener *listener, + MemoryRegionSection *section) +{ +} + +static void hostmem_listener_eventfd_dummy(MemoryListener *listener, + MemoryRegionSection *section, + bool match_data, uint64_t data, + EventNotifier *e) +{ +} + +static void hostmem_listener_coalesced_mmio_dummy(MemoryListener *listener, + MemoryRegionSection *section, + hwaddr addr, hwaddr len) +{ +} + +void hostmem_init(HostMem *hostmem) +{ + memset(hostmem, 0, sizeof(*hostmem)); + + qemu_mutex_init(&hostmem->current_regions_lock); + + hostmem->listener = (MemoryListener){ + .begin = hostmem_listener_dummy, + .commit = hostmem_listener_commit, + .region_add = hostmem_listener_append_region, + .region_del = hostmem_listener_section_dummy, + .region_nop = hostmem_listener_append_region, + .log_start = hostmem_listener_section_dummy, + .log_stop = hostmem_listener_section_dummy, + .log_sync = hostmem_listener_section_dummy, + .log_global_start = hostmem_listener_dummy, + .log_global_stop = hostmem_listener_dummy, + .eventfd_add = hostmem_listener_eventfd_dummy, + .eventfd_del = hostmem_listener_eventfd_dummy, + .coalesced_mmio_add = hostmem_listener_coalesced_mmio_dummy, + .coalesced_mmio_del = hostmem_listener_coalesced_mmio_dummy, + .priority = 10, + }; + + memory_listener_register(&hostmem->listener, &address_space_memory); + if (hostmem->num_new_regions > 0) { + hostmem_listener_commit(&hostmem->listener); + } +} + +void hostmem_finalize(HostMem *hostmem) +{ + memory_listener_unregister(&hostmem->listener); + g_free(hostmem->new_regions); + g_free(hostmem->current_regions); + qemu_mutex_destroy(&hostmem->current_regions_lock); +} diff --git a/hw/dataplane/hostmem.h b/hw/dataplane/hostmem.h new file mode 100644 index 0000000000..b2cf09333f --- /dev/null +++ b/hw/dataplane/hostmem.h @@ -0,0 +1,57 @@ +/* + * Thread-safe guest to host memory mapping + * + * Copyright 2012 Red Hat, Inc. and/or its affiliates + * + * Authors: + * Stefan Hajnoczi + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef HOSTMEM_H +#define HOSTMEM_H + +#include "exec/memory.h" +#include "qemu/thread.h" + +typedef struct { + void *host_addr; + hwaddr guest_addr; + uint64_t size; + bool readonly; +} HostMemRegion; + +typedef struct { + /* The listener is invoked when regions change and a new list of regions is + * built up completely before they are installed. + */ + MemoryListener listener; + HostMemRegion *new_regions; + size_t num_new_regions; + + /* Current regions are accessed from multiple threads either to lookup + * addresses or to install a new list of regions. The lock protects the + * pointer and the regions. + */ + QemuMutex current_regions_lock; + HostMemRegion *current_regions; + size_t num_current_regions; +} HostMem; + +void hostmem_init(HostMem *hostmem); +void hostmem_finalize(HostMem *hostmem); + +/** + * Map a guest physical address to a pointer + * + * Note that there is map/unmap mechanism here. The caller must ensure that + * mapped memory is no longer used across events like hot memory unplug. This + * can be done with other mechanisms like bdrv_drain_all() that quiesce + * in-flight I/O. + */ +void *hostmem_lookup(HostMem *hostmem, hwaddr phys, hwaddr len, bool is_write); + +#endif /* HOSTMEM_H */ From 88807f89d945acad54c8365ff7b6ef0f0d0ddd56 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 14 Nov 2012 15:15:50 +0100 Subject: [PATCH 2155/2270] dataplane: add virtqueue vring code The virtio-blk-data-plane cannot access memory using the usual QEMU functions since it executes outside the global mutex and the memory APIs are this time are not thread-safe. This patch introduces a virtqueue module based on the kernel's vhost vring code. The trick is that we map guest memory ahead of time and access it cheaply outside the global mutex. Once the hardware emulation code can execute outside the global mutex it will be possible to drop this code. Signed-off-by: Stefan Hajnoczi --- hw/dataplane/Makefile.objs | 2 +- hw/dataplane/vring.c | 362 +++++++++++++++++++++++++++++++++++++ hw/dataplane/vring.h | 62 +++++++ trace-events | 3 + 4 files changed, 428 insertions(+), 1 deletion(-) create mode 100644 hw/dataplane/vring.c create mode 100644 hw/dataplane/vring.h diff --git a/hw/dataplane/Makefile.objs b/hw/dataplane/Makefile.objs index 8c8dea1b21..34e6d579ec 100644 --- a/hw/dataplane/Makefile.objs +++ b/hw/dataplane/Makefile.objs @@ -1,3 +1,3 @@ ifeq ($(CONFIG_VIRTIO), y) -common-obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += hostmem.o +common-obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += hostmem.o vring.o endif diff --git a/hw/dataplane/vring.c b/hw/dataplane/vring.c new file mode 100644 index 0000000000..d5d4ef45d1 --- /dev/null +++ b/hw/dataplane/vring.c @@ -0,0 +1,362 @@ +/* Copyright 2012 Red Hat, Inc. + * Copyright IBM, Corp. 2012 + * + * Based on Linux 2.6.39 vhost code: + * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2006 Rusty Russell IBM Corporation + * + * Author: Michael S. Tsirkin + * Stefan Hajnoczi + * + * Inspiration, some code, and most witty comments come from + * Documentation/virtual/lguest/lguest.c, by Rusty Russell + * + * This work is licensed under the terms of the GNU GPL, version 2. + */ + +#include "trace.h" +#include "hw/dataplane/vring.h" + +/* Map the guest's vring to host memory */ +bool vring_setup(Vring *vring, VirtIODevice *vdev, int n) +{ + hwaddr vring_addr = virtio_queue_get_ring_addr(vdev, n); + hwaddr vring_size = virtio_queue_get_ring_size(vdev, n); + void *vring_ptr; + + vring->broken = false; + + hostmem_init(&vring->hostmem); + vring_ptr = hostmem_lookup(&vring->hostmem, vring_addr, vring_size, true); + if (!vring_ptr) { + error_report("Failed to map vring " + "addr %#" HWADDR_PRIx " size %" HWADDR_PRIu, + vring_addr, vring_size); + vring->broken = true; + return false; + } + + vring_init(&vring->vr, virtio_queue_get_num(vdev, n), vring_ptr, 4096); + + vring->last_avail_idx = 0; + vring->last_used_idx = 0; + vring->signalled_used = 0; + vring->signalled_used_valid = false; + + trace_vring_setup(virtio_queue_get_ring_addr(vdev, n), + vring->vr.desc, vring->vr.avail, vring->vr.used); + return true; +} + +void vring_teardown(Vring *vring) +{ + hostmem_finalize(&vring->hostmem); +} + +/* Disable guest->host notifies */ +void vring_disable_notification(VirtIODevice *vdev, Vring *vring) +{ + if (!(vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX))) { + vring->vr.used->flags |= VRING_USED_F_NO_NOTIFY; + } +} + +/* Enable guest->host notifies + * + * Return true if the vring is empty, false if there are more requests. + */ +bool vring_enable_notification(VirtIODevice *vdev, Vring *vring) +{ + if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { + vring_avail_event(&vring->vr) = vring->vr.avail->idx; + } else { + vring->vr.used->flags &= ~VRING_USED_F_NO_NOTIFY; + } + smp_mb(); /* ensure update is seen before reading avail_idx */ + return !vring_more_avail(vring); +} + +/* This is stolen from linux/drivers/vhost/vhost.c:vhost_notify() */ +bool vring_should_notify(VirtIODevice *vdev, Vring *vring) +{ + uint16_t old, new; + bool v; + /* Flush out used index updates. This is paired + * with the barrier that the Guest executes when enabling + * interrupts. */ + smp_mb(); + + if ((vdev->guest_features & VIRTIO_F_NOTIFY_ON_EMPTY) && + unlikely(vring->vr.avail->idx == vring->last_avail_idx)) { + return true; + } + + if (!(vdev->guest_features & VIRTIO_RING_F_EVENT_IDX)) { + return !(vring->vr.avail->flags & VRING_AVAIL_F_NO_INTERRUPT); + } + old = vring->signalled_used; + v = vring->signalled_used_valid; + new = vring->signalled_used = vring->last_used_idx; + vring->signalled_used_valid = true; + + if (unlikely(!v)) { + return true; + } + + return vring_need_event(vring_used_event(&vring->vr), new, old); +} + +/* This is stolen from linux/drivers/vhost/vhost.c. */ +static int get_indirect(Vring *vring, + struct iovec iov[], struct iovec *iov_end, + unsigned int *out_num, unsigned int *in_num, + struct vring_desc *indirect) +{ + struct vring_desc desc; + unsigned int i = 0, count, found = 0; + + /* Sanity check */ + if (unlikely(indirect->len % sizeof(desc))) { + error_report("Invalid length in indirect descriptor: " + "len %#x not multiple of %#zx", + indirect->len, sizeof(desc)); + vring->broken = true; + return -EFAULT; + } + + count = indirect->len / sizeof(desc); + /* Buffers are chained via a 16 bit next field, so + * we can have at most 2^16 of these. */ + if (unlikely(count > USHRT_MAX + 1)) { + error_report("Indirect buffer length too big: %d", indirect->len); + vring->broken = true; + return -EFAULT; + } + + do { + struct vring_desc *desc_ptr; + + /* Translate indirect descriptor */ + desc_ptr = hostmem_lookup(&vring->hostmem, + indirect->addr + found * sizeof(desc), + sizeof(desc), false); + if (!desc_ptr) { + error_report("Failed to map indirect descriptor " + "addr %#" PRIx64 " len %zu", + (uint64_t)indirect->addr + found * sizeof(desc), + sizeof(desc)); + vring->broken = true; + return -EFAULT; + } + desc = *desc_ptr; + + /* Ensure descriptor has been loaded before accessing fields */ + barrier(); /* read_barrier_depends(); */ + + if (unlikely(++found > count)) { + error_report("Loop detected: last one at %u " + "indirect size %u", i, count); + vring->broken = true; + return -EFAULT; + } + + if (unlikely(desc.flags & VRING_DESC_F_INDIRECT)) { + error_report("Nested indirect descriptor"); + vring->broken = true; + return -EFAULT; + } + + /* Stop for now if there are not enough iovecs available. */ + if (iov >= iov_end) { + return -ENOBUFS; + } + + iov->iov_base = hostmem_lookup(&vring->hostmem, desc.addr, desc.len, + desc.flags & VRING_DESC_F_WRITE); + if (!iov->iov_base) { + error_report("Failed to map indirect descriptor" + "addr %#" PRIx64 " len %u", + (uint64_t)desc.addr, desc.len); + vring->broken = true; + return -EFAULT; + } + iov->iov_len = desc.len; + iov++; + + /* If this is an input descriptor, increment that count. */ + if (desc.flags & VRING_DESC_F_WRITE) { + *in_num += 1; + } else { + /* If it's an output descriptor, they're all supposed + * to come before any input descriptors. */ + if (unlikely(*in_num)) { + error_report("Indirect descriptor " + "has out after in: idx %u", i); + vring->broken = true; + return -EFAULT; + } + *out_num += 1; + } + i = desc.next; + } while (desc.flags & VRING_DESC_F_NEXT); + return 0; +} + +/* This looks in the virtqueue and for the first available buffer, and converts + * it to an iovec for convenient access. Since descriptors consist of some + * number of output then some number of input descriptors, it's actually two + * iovecs, but we pack them into one and note how many of each there were. + * + * This function returns the descriptor number found, or vq->num (which is + * never a valid descriptor number) if none was found. A negative code is + * returned on error. + * + * Stolen from linux/drivers/vhost/vhost.c. + */ +int vring_pop(VirtIODevice *vdev, Vring *vring, + struct iovec iov[], struct iovec *iov_end, + unsigned int *out_num, unsigned int *in_num) +{ + struct vring_desc desc; + unsigned int i, head, found = 0, num = vring->vr.num; + uint16_t avail_idx, last_avail_idx; + + /* If there was a fatal error then refuse operation */ + if (vring->broken) { + return -EFAULT; + } + + /* Check it isn't doing very strange things with descriptor numbers. */ + last_avail_idx = vring->last_avail_idx; + avail_idx = vring->vr.avail->idx; + barrier(); /* load indices now and not again later */ + + if (unlikely((uint16_t)(avail_idx - last_avail_idx) > num)) { + error_report("Guest moved used index from %u to %u", + last_avail_idx, avail_idx); + vring->broken = true; + return -EFAULT; + } + + /* If there's nothing new since last we looked. */ + if (avail_idx == last_avail_idx) { + return -EAGAIN; + } + + /* Only get avail ring entries after they have been exposed by guest. */ + smp_rmb(); + + /* Grab the next descriptor number they're advertising, and increment + * the index we've seen. */ + head = vring->vr.avail->ring[last_avail_idx % num]; + + /* If their number is silly, that's an error. */ + if (unlikely(head >= num)) { + error_report("Guest says index %u > %u is available", head, num); + vring->broken = true; + return -EFAULT; + } + + if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { + vring_avail_event(&vring->vr) = vring->vr.avail->idx; + } + + /* When we start there are none of either input nor output. */ + *out_num = *in_num = 0; + + i = head; + do { + if (unlikely(i >= num)) { + error_report("Desc index is %u > %u, head = %u", i, num, head); + vring->broken = true; + return -EFAULT; + } + if (unlikely(++found > num)) { + error_report("Loop detected: last one at %u vq size %u head %u", + i, num, head); + vring->broken = true; + return -EFAULT; + } + desc = vring->vr.desc[i]; + + /* Ensure descriptor is loaded before accessing fields */ + barrier(); + + if (desc.flags & VRING_DESC_F_INDIRECT) { + int ret = get_indirect(vring, iov, iov_end, out_num, in_num, &desc); + if (ret < 0) { + return ret; + } + continue; + } + + /* If there are not enough iovecs left, stop for now. The caller + * should check if there are more descs available once they have dealt + * with the current set. + */ + if (iov >= iov_end) { + return -ENOBUFS; + } + + /* TODO handle non-contiguous memory across region boundaries */ + iov->iov_base = hostmem_lookup(&vring->hostmem, desc.addr, desc.len, + desc.flags & VRING_DESC_F_WRITE); + if (!iov->iov_base) { + error_report("Failed to map vring desc addr %#" PRIx64 " len %u", + (uint64_t)desc.addr, desc.len); + vring->broken = true; + return -EFAULT; + } + iov->iov_len = desc.len; + iov++; + + if (desc.flags & VRING_DESC_F_WRITE) { + /* If this is an input descriptor, + * increment that count. */ + *in_num += 1; + } else { + /* If it's an output descriptor, they're all supposed + * to come before any input descriptors. */ + if (unlikely(*in_num)) { + error_report("Descriptor has out after in: idx %d", i); + vring->broken = true; + return -EFAULT; + } + *out_num += 1; + } + i = desc.next; + } while (desc.flags & VRING_DESC_F_NEXT); + + /* On success, increment avail index. */ + vring->last_avail_idx++; + return head; +} + +/* After we've used one of their buffers, we tell them about it. + * + * Stolen from linux/drivers/vhost/vhost.c. + */ +void vring_push(Vring *vring, unsigned int head, int len) +{ + struct vring_used_elem *used; + uint16_t new; + + /* Don't touch vring if a fatal error occurred */ + if (vring->broken) { + return; + } + + /* The virtqueue contains a ring of used buffers. Get a pointer to the + * next entry in that used ring. */ + used = &vring->vr.used->ring[vring->last_used_idx % vring->vr.num]; + used->id = head; + used->len = len; + + /* Make sure buffer is written before we update index. */ + smp_wmb(); + + new = vring->vr.used->idx = ++vring->last_used_idx; + if (unlikely((int16_t)(new - vring->signalled_used) < (uint16_t)1)) { + vring->signalled_used_valid = false; + } +} diff --git a/hw/dataplane/vring.h b/hw/dataplane/vring.h new file mode 100644 index 0000000000..3274f623f5 --- /dev/null +++ b/hw/dataplane/vring.h @@ -0,0 +1,62 @@ +/* Copyright 2012 Red Hat, Inc. and/or its affiliates + * Copyright IBM, Corp. 2012 + * + * Based on Linux 2.6.39 vhost code: + * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2006 Rusty Russell IBM Corporation + * + * Author: Michael S. Tsirkin + * Stefan Hajnoczi + * + * Inspiration, some code, and most witty comments come from + * Documentation/virtual/lguest/lguest.c, by Rusty Russell + * + * This work is licensed under the terms of the GNU GPL, version 2. + */ + +#ifndef VRING_H +#define VRING_H + +#include +#include "qemu-common.h" +#include "hw/dataplane/hostmem.h" +#include "hw/virtio.h" + +typedef struct { + HostMem hostmem; /* guest memory mapper */ + struct vring vr; /* virtqueue vring mapped to host memory */ + uint16_t last_avail_idx; /* last processed avail ring index */ + uint16_t last_used_idx; /* last processed used ring index */ + uint16_t signalled_used; /* EVENT_IDX state */ + bool signalled_used_valid; + bool broken; /* was there a fatal error? */ +} Vring; + +static inline unsigned int vring_get_num(Vring *vring) +{ + return vring->vr.num; +} + +/* Are there more descriptors available? */ +static inline bool vring_more_avail(Vring *vring) +{ + return vring->vr.avail->idx != vring->last_avail_idx; +} + +/* Fail future vring_pop() and vring_push() calls until reset */ +static inline void vring_set_broken(Vring *vring) +{ + vring->broken = true; +} + +bool vring_setup(Vring *vring, VirtIODevice *vdev, int n); +void vring_teardown(Vring *vring); +void vring_disable_notification(VirtIODevice *vdev, Vring *vring); +bool vring_enable_notification(VirtIODevice *vdev, Vring *vring); +bool vring_should_notify(VirtIODevice *vdev, Vring *vring); +int vring_pop(VirtIODevice *vdev, Vring *vring, + struct iovec iov[], struct iovec *iov_end, + unsigned int *out_num, unsigned int *in_num); +void vring_push(Vring *vring, unsigned int head, int len); + +#endif /* VRING_H */ diff --git a/trace-events b/trace-events index bb7621eeb6..167d776eff 100644 --- a/trace-events +++ b/trace-events @@ -98,6 +98,9 @@ virtio_blk_rw_complete(void *req, int ret) "req %p ret %d" virtio_blk_handle_write(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu" virtio_blk_handle_read(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu" +# hw/dataplane/vring.c +vring_setup(uint64_t physical, void *desc, void *avail, void *used) "vring physical %#"PRIx64" desc %p avail %p used %p" + # thread-pool.c thread_pool_submit(void *req, void *opaque) "req %p opaque %p" thread_pool_complete(void *req, void *opaque, int ret) "req %p opaque %p ret %d" From 71973b046120a13df4eaa9143bed5ba8a67abc7f Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 14 Nov 2012 15:23:00 +0100 Subject: [PATCH 2156/2270] dataplane: add event loop Outside the safety of the global mutex we need to poll on file descriptors. I found epoll(2) is a convenient way to do that, although other options could replace this module in the future (such as an AioContext-based loop or glib's GMainLoop). One important feature of this small event loop implementation is that the loop can be terminated in a thread-safe way. This allows QEMU to stop the data plane thread cleanly. Signed-off-by: Stefan Hajnoczi --- hw/dataplane/Makefile.objs | 2 +- hw/dataplane/event-poll.c | 100 +++++++++++++++++++++++++++++++++++++ hw/dataplane/event-poll.h | 40 +++++++++++++++ 3 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 hw/dataplane/event-poll.c create mode 100644 hw/dataplane/event-poll.h diff --git a/hw/dataplane/Makefile.objs b/hw/dataplane/Makefile.objs index 34e6d579ec..e26bd7d89a 100644 --- a/hw/dataplane/Makefile.objs +++ b/hw/dataplane/Makefile.objs @@ -1,3 +1,3 @@ ifeq ($(CONFIG_VIRTIO), y) -common-obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += hostmem.o vring.o +common-obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += hostmem.o vring.o event-poll.o endif diff --git a/hw/dataplane/event-poll.c b/hw/dataplane/event-poll.c new file mode 100644 index 0000000000..2b55c6e255 --- /dev/null +++ b/hw/dataplane/event-poll.c @@ -0,0 +1,100 @@ +/* + * Event loop with file descriptor polling + * + * Copyright 2012 IBM, Corp. + * Copyright 2012 Red Hat, Inc. and/or its affiliates + * + * Authors: + * Stefan Hajnoczi + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include +#include "hw/dataplane/event-poll.h" + +/* Add an event notifier and its callback for polling */ +void event_poll_add(EventPoll *poll, EventHandler *handler, + EventNotifier *notifier, EventCallback *callback) +{ + struct epoll_event event = { + .events = EPOLLIN, + .data.ptr = handler, + }; + handler->notifier = notifier; + handler->callback = callback; + if (epoll_ctl(poll->epoll_fd, EPOLL_CTL_ADD, + event_notifier_get_fd(notifier), &event) != 0) { + fprintf(stderr, "failed to add event handler to epoll: %m\n"); + exit(1); + } +} + +/* Event callback for stopping event_poll() */ +static void handle_stop(EventHandler *handler) +{ + /* Do nothing */ +} + +void event_poll_init(EventPoll *poll) +{ + /* Create epoll file descriptor */ + poll->epoll_fd = epoll_create1(EPOLL_CLOEXEC); + if (poll->epoll_fd < 0) { + fprintf(stderr, "epoll_create1 failed: %m\n"); + exit(1); + } + + /* Set up stop notifier */ + if (event_notifier_init(&poll->stop_notifier, 0) < 0) { + fprintf(stderr, "failed to init stop notifier\n"); + exit(1); + } + event_poll_add(poll, &poll->stop_handler, + &poll->stop_notifier, handle_stop); +} + +void event_poll_cleanup(EventPoll *poll) +{ + event_notifier_cleanup(&poll->stop_notifier); + close(poll->epoll_fd); + poll->epoll_fd = -1; +} + +/* Block until the next event and invoke its callback */ +void event_poll(EventPoll *poll) +{ + EventHandler *handler; + struct epoll_event event; + int nevents; + + /* Wait for the next event. Only do one event per call to keep the + * function simple, this could be changed later. */ + do { + nevents = epoll_wait(poll->epoll_fd, &event, 1, -1); + } while (nevents < 0 && errno == EINTR); + if (unlikely(nevents != 1)) { + fprintf(stderr, "epoll_wait failed: %m\n"); + exit(1); /* should never happen */ + } + + /* Find out which event handler has become active */ + handler = event.data.ptr; + + /* Clear the eventfd */ + event_notifier_test_and_clear(handler->notifier); + + /* Handle the event */ + handler->callback(handler); +} + +/* Stop event_poll() + * + * This function can be used from another thread. + */ +void event_poll_notify(EventPoll *poll) +{ + event_notifier_set(&poll->stop_notifier); +} diff --git a/hw/dataplane/event-poll.h b/hw/dataplane/event-poll.h new file mode 100644 index 0000000000..3e8d3ec7d5 --- /dev/null +++ b/hw/dataplane/event-poll.h @@ -0,0 +1,40 @@ +/* + * Event loop with file descriptor polling + * + * Copyright 2012 IBM, Corp. + * Copyright 2012 Red Hat, Inc. and/or its affiliates + * + * Authors: + * Stefan Hajnoczi + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef EVENT_POLL_H +#define EVENT_POLL_H + +#include "qemu/event_notifier.h" + +typedef struct EventHandler EventHandler; +typedef void EventCallback(EventHandler *handler); +struct EventHandler { + EventNotifier *notifier; /* eventfd */ + EventCallback *callback; /* callback function */ +}; + +typedef struct { + int epoll_fd; /* epoll(2) file descriptor */ + EventNotifier stop_notifier; /* stop poll notifier */ + EventHandler stop_handler; /* stop poll handler */ +} EventPoll; + +void event_poll_add(EventPoll *poll, EventHandler *handler, + EventNotifier *notifier, EventCallback *callback); +void event_poll_init(EventPoll *poll); +void event_poll_cleanup(EventPoll *poll); +void event_poll(EventPoll *poll); +void event_poll_notify(EventPoll *poll); + +#endif /* EVENT_POLL_H */ From 3e9ec521711ed033476098cfc7f23c992cc606a2 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 14 Nov 2012 15:30:09 +0100 Subject: [PATCH 2157/2270] dataplane: add Linux AIO request queue The IOQueue has a pool of iocb structs and a function to add new read/write requests. Multiple requests can be added before calling the submit function to actually tell the host kernel to begin I/O. This allows callers to batch requests and submit them in one go. The actual I/O is performed using Linux AIO. Signed-off-by: Stefan Hajnoczi --- hw/dataplane/Makefile.objs | 2 +- hw/dataplane/ioq.c | 117 +++++++++++++++++++++++++++++++++++++ hw/dataplane/ioq.h | 57 ++++++++++++++++++ 3 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 hw/dataplane/ioq.c create mode 100644 hw/dataplane/ioq.h diff --git a/hw/dataplane/Makefile.objs b/hw/dataplane/Makefile.objs index e26bd7d89a..abd408f1da 100644 --- a/hw/dataplane/Makefile.objs +++ b/hw/dataplane/Makefile.objs @@ -1,3 +1,3 @@ ifeq ($(CONFIG_VIRTIO), y) -common-obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += hostmem.o vring.o event-poll.o +common-obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += hostmem.o vring.o event-poll.o ioq.o endif diff --git a/hw/dataplane/ioq.c b/hw/dataplane/ioq.c new file mode 100644 index 0000000000..0c9f5c4d60 --- /dev/null +++ b/hw/dataplane/ioq.c @@ -0,0 +1,117 @@ +/* + * Linux AIO request queue + * + * Copyright 2012 IBM, Corp. + * Copyright 2012 Red Hat, Inc. and/or its affiliates + * + * Authors: + * Stefan Hajnoczi + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "hw/dataplane/ioq.h" + +void ioq_init(IOQueue *ioq, int fd, unsigned int max_reqs) +{ + int rc; + + ioq->fd = fd; + ioq->max_reqs = max_reqs; + + memset(&ioq->io_ctx, 0, sizeof ioq->io_ctx); + rc = io_setup(max_reqs, &ioq->io_ctx); + if (rc != 0) { + fprintf(stderr, "ioq io_setup failed %d\n", rc); + exit(1); + } + + rc = event_notifier_init(&ioq->io_notifier, 0); + if (rc != 0) { + fprintf(stderr, "ioq io event notifier creation failed %d\n", rc); + exit(1); + } + + ioq->freelist = g_malloc0(sizeof ioq->freelist[0] * max_reqs); + ioq->freelist_idx = 0; + + ioq->queue = g_malloc0(sizeof ioq->queue[0] * max_reqs); + ioq->queue_idx = 0; +} + +void ioq_cleanup(IOQueue *ioq) +{ + g_free(ioq->freelist); + g_free(ioq->queue); + + event_notifier_cleanup(&ioq->io_notifier); + io_destroy(ioq->io_ctx); +} + +EventNotifier *ioq_get_notifier(IOQueue *ioq) +{ + return &ioq->io_notifier; +} + +struct iocb *ioq_get_iocb(IOQueue *ioq) +{ + /* Underflow cannot happen since ioq is sized for max_reqs */ + assert(ioq->freelist_idx != 0); + + struct iocb *iocb = ioq->freelist[--ioq->freelist_idx]; + ioq->queue[ioq->queue_idx++] = iocb; + return iocb; +} + +void ioq_put_iocb(IOQueue *ioq, struct iocb *iocb) +{ + /* Overflow cannot happen since ioq is sized for max_reqs */ + assert(ioq->freelist_idx != ioq->max_reqs); + + ioq->freelist[ioq->freelist_idx++] = iocb; +} + +struct iocb *ioq_rdwr(IOQueue *ioq, bool read, struct iovec *iov, + unsigned int count, long long offset) +{ + struct iocb *iocb = ioq_get_iocb(ioq); + + if (read) { + io_prep_preadv(iocb, ioq->fd, iov, count, offset); + } else { + io_prep_pwritev(iocb, ioq->fd, iov, count, offset); + } + io_set_eventfd(iocb, event_notifier_get_fd(&ioq->io_notifier)); + return iocb; +} + +int ioq_submit(IOQueue *ioq) +{ + int rc = io_submit(ioq->io_ctx, ioq->queue_idx, ioq->queue); + ioq->queue_idx = 0; /* reset */ + return rc; +} + +int ioq_run_completion(IOQueue *ioq, IOQueueCompletion *completion, + void *opaque) +{ + struct io_event events[ioq->max_reqs]; + int nevents, i; + + do { + nevents = io_getevents(ioq->io_ctx, 0, ioq->max_reqs, events, NULL); + } while (nevents < 0 && errno == EINTR); + if (nevents < 0) { + return nevents; + } + + for (i = 0; i < nevents; i++) { + ssize_t ret = ((uint64_t)events[i].res2 << 32) | events[i].res; + + completion(events[i].obj, ret, opaque); + ioq_put_iocb(ioq, events[i].obj); + } + return nevents; +} diff --git a/hw/dataplane/ioq.h b/hw/dataplane/ioq.h new file mode 100644 index 0000000000..b49b5de7f4 --- /dev/null +++ b/hw/dataplane/ioq.h @@ -0,0 +1,57 @@ +/* + * Linux AIO request queue + * + * Copyright 2012 IBM, Corp. + * Copyright 2012 Red Hat, Inc. and/or its affiliates + * + * Authors: + * Stefan Hajnoczi + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef IOQ_H +#define IOQ_H + +#include +#include "qemu/event_notifier.h" + +typedef struct { + int fd; /* file descriptor */ + unsigned int max_reqs; /* max length of freelist and queue */ + + io_context_t io_ctx; /* Linux AIO context */ + EventNotifier io_notifier; /* Linux AIO eventfd */ + + /* Requests can complete in any order so a free list is necessary to manage + * available iocbs. + */ + struct iocb **freelist; /* free iocbs */ + unsigned int freelist_idx; + + /* Multiple requests are queued up before submitting them all in one go */ + struct iocb **queue; /* queued iocbs */ + unsigned int queue_idx; +} IOQueue; + +void ioq_init(IOQueue *ioq, int fd, unsigned int max_reqs); +void ioq_cleanup(IOQueue *ioq); +EventNotifier *ioq_get_notifier(IOQueue *ioq); +struct iocb *ioq_get_iocb(IOQueue *ioq); +void ioq_put_iocb(IOQueue *ioq, struct iocb *iocb); +struct iocb *ioq_rdwr(IOQueue *ioq, bool read, struct iovec *iov, + unsigned int count, long long offset); +int ioq_submit(IOQueue *ioq); + +static inline unsigned int ioq_num_queued(IOQueue *ioq) +{ + return ioq->queue_idx; +} + +typedef void IOQueueCompletion(struct iocb *iocb, ssize_t ret, void *opaque); +int ioq_run_completion(IOQueue *ioq, IOQueueCompletion *completion, + void *opaque); + +#endif /* IOQ_H */ From d02776350d9c76348988fc9e58a64a4f6b1a9f61 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 21 Nov 2012 17:41:10 +0100 Subject: [PATCH 2158/2270] iov: add iov_discard_front/back() to remove data The iov_discard_front/back() functions remove data from the front or back of the vector. This is useful when peeling off header/footer structs. Signed-off-by: Stefan Hajnoczi --- include/qemu/iov.h | 13 ++++++++++++ iov.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/include/qemu/iov.h b/include/qemu/iov.h index d06f8b9ce3..68d25f29b7 100644 --- a/include/qemu/iov.h +++ b/include/qemu/iov.h @@ -99,4 +99,17 @@ unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt, const struct iovec *iov, unsigned int iov_cnt, size_t offset, size_t bytes); +/* + * Remove a given number of bytes from the front or back of a vector. + * This may update iov and/or iov_cnt to exclude iovec elements that are + * no longer required. + * + * The number of bytes actually discarded is returned. This number may be + * smaller than requested if the vector is too small. + */ +size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt, + size_t bytes); +size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt, + size_t bytes); + #endif diff --git a/iov.c b/iov.c index 419e419969..92ad77b162 100644 --- a/iov.c +++ b/iov.c @@ -354,3 +354,54 @@ size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset, { return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes); } + +size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt, + size_t bytes) +{ + size_t total = 0; + struct iovec *cur; + + for (cur = *iov; *iov_cnt > 0; cur++) { + if (cur->iov_len > bytes) { + cur->iov_base += bytes; + cur->iov_len -= bytes; + total += bytes; + break; + } + + bytes -= cur->iov_len; + total += cur->iov_len; + *iov_cnt -= 1; + } + + *iov = cur; + return total; +} + +size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt, + size_t bytes) +{ + size_t total = 0; + struct iovec *cur; + + if (*iov_cnt == 0) { + return 0; + } + + cur = iov + (*iov_cnt - 1); + + while (*iov_cnt > 0) { + if (cur->iov_len > bytes) { + cur->iov_len -= bytes; + total += bytes; + break; + } + + bytes -= cur->iov_len; + total += cur->iov_len; + cur--; + *iov_cnt -= 1; + } + + return total; +} From 8962e44fe438a051aff9f43209363f599be33624 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 21 Nov 2012 19:18:26 +0100 Subject: [PATCH 2159/2270] test-iov: add iov_discard_front/back() testcases Signed-off-by: Stefan Hajnoczi --- tests/test-iov.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/tests/test-iov.c b/tests/test-iov.c index a480bc8725..46e4dddc55 100644 --- a/tests/test-iov.c +++ b/tests/test-iov.c @@ -250,11 +250,161 @@ static void test_io(void) #endif } +static void test_discard_front(void) +{ + struct iovec *iov; + struct iovec *iov_tmp; + unsigned int iov_cnt; + unsigned int iov_cnt_tmp; + void *old_base; + size_t size; + size_t ret; + + /* Discard zero bytes */ + iov_random(&iov, &iov_cnt); + iov_tmp = iov; + iov_cnt_tmp = iov_cnt; + ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, 0); + g_assert(ret == 0); + g_assert(iov_tmp == iov); + g_assert(iov_cnt_tmp == iov_cnt); + iov_free(iov, iov_cnt); + + /* Discard more bytes than vector size */ + iov_random(&iov, &iov_cnt); + iov_tmp = iov; + iov_cnt_tmp = iov_cnt; + size = iov_size(iov, iov_cnt); + ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size + 1); + g_assert(ret == size); + g_assert(iov_cnt_tmp == 0); + iov_free(iov, iov_cnt); + + /* Discard entire vector */ + iov_random(&iov, &iov_cnt); + iov_tmp = iov; + iov_cnt_tmp = iov_cnt; + size = iov_size(iov, iov_cnt); + ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size); + g_assert(ret == size); + g_assert(iov_cnt_tmp == 0); + iov_free(iov, iov_cnt); + + /* Discard within first element */ + iov_random(&iov, &iov_cnt); + iov_tmp = iov; + iov_cnt_tmp = iov_cnt; + old_base = iov->iov_base; + size = g_test_rand_int_range(1, iov->iov_len); + ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size); + g_assert(ret == size); + g_assert(iov_tmp == iov); + g_assert(iov_cnt_tmp == iov_cnt); + g_assert(iov_tmp->iov_base == old_base + size); + iov_tmp->iov_base = old_base; /* undo before g_free() */ + iov_free(iov, iov_cnt); + + /* Discard entire first element */ + iov_random(&iov, &iov_cnt); + iov_tmp = iov; + iov_cnt_tmp = iov_cnt; + ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, iov->iov_len); + g_assert(ret == iov->iov_len); + g_assert(iov_tmp == iov + 1); + g_assert(iov_cnt_tmp == iov_cnt - 1); + iov_free(iov, iov_cnt); + + /* Discard within second element */ + iov_random(&iov, &iov_cnt); + iov_tmp = iov; + iov_cnt_tmp = iov_cnt; + old_base = iov[1].iov_base; + size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len); + ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size); + g_assert(ret == size); + g_assert(iov_tmp == iov + 1); + g_assert(iov_cnt_tmp == iov_cnt - 1); + g_assert(iov_tmp->iov_base == old_base + (size - iov->iov_len)); + iov_tmp->iov_base = old_base; /* undo before g_free() */ + iov_free(iov, iov_cnt); +} + +static void test_discard_back(void) +{ + struct iovec *iov; + unsigned int iov_cnt; + unsigned int iov_cnt_tmp; + void *old_base; + size_t size; + size_t ret; + + /* Discard zero bytes */ + iov_random(&iov, &iov_cnt); + iov_cnt_tmp = iov_cnt; + ret = iov_discard_back(iov, &iov_cnt_tmp, 0); + g_assert(ret == 0); + g_assert(iov_cnt_tmp == iov_cnt); + iov_free(iov, iov_cnt); + + /* Discard more bytes than vector size */ + iov_random(&iov, &iov_cnt); + iov_cnt_tmp = iov_cnt; + size = iov_size(iov, iov_cnt); + ret = iov_discard_back(iov, &iov_cnt_tmp, size + 1); + g_assert(ret == size); + g_assert(iov_cnt_tmp == 0); + iov_free(iov, iov_cnt); + + /* Discard entire vector */ + iov_random(&iov, &iov_cnt); + iov_cnt_tmp = iov_cnt; + size = iov_size(iov, iov_cnt); + ret = iov_discard_back(iov, &iov_cnt_tmp, size); + g_assert(ret == size); + g_assert(iov_cnt_tmp == 0); + iov_free(iov, iov_cnt); + + /* Discard within last element */ + iov_random(&iov, &iov_cnt); + iov_cnt_tmp = iov_cnt; + old_base = iov[iov_cnt - 1].iov_base; + size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len); + ret = iov_discard_back(iov, &iov_cnt_tmp, size); + g_assert(ret == size); + g_assert(iov_cnt_tmp == iov_cnt); + g_assert(iov[iov_cnt - 1].iov_base == old_base); + iov_free(iov, iov_cnt); + + /* Discard entire last element */ + iov_random(&iov, &iov_cnt); + iov_cnt_tmp = iov_cnt; + old_base = iov[iov_cnt - 1].iov_base; + size = iov[iov_cnt - 1].iov_len; + ret = iov_discard_back(iov, &iov_cnt_tmp, size); + g_assert(ret == size); + g_assert(iov_cnt_tmp == iov_cnt - 1); + iov_free(iov, iov_cnt); + + /* Discard within second-to-last element */ + iov_random(&iov, &iov_cnt); + iov_cnt_tmp = iov_cnt; + old_base = iov[iov_cnt - 2].iov_base; + size = iov[iov_cnt - 1].iov_len + + g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len); + ret = iov_discard_back(iov, &iov_cnt_tmp, size); + g_assert(ret == size); + g_assert(iov_cnt_tmp == iov_cnt - 1); + g_assert(iov[iov_cnt - 2].iov_base == old_base); + iov_free(iov, iov_cnt); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); g_test_rand_int(); g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf); g_test_add_func("/basic/iov/io", test_io); + g_test_add_func("/basic/iov/discard-front", test_discard_front); + g_test_add_func("/basic/iov/discard-back", test_discard_back); return g_test_run(); } From 530c0bbd73e1b658c9266582072847de1fbdff10 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 22 Nov 2012 16:06:06 +0100 Subject: [PATCH 2160/2270] iov: add qemu_iovec_concat_iov() The qemu_iovec_concat() function copies a subset of a QEMUIOVector. The new qemu_iovec_concat_iov() function does the same for a iov/cnt pair. It is easy to define qemu_iovec_concat() in terms of qemu_iovec_concat_iov(). The existing code is mostly unchanged, except for the assertion src->size >= soffset, which cannot be efficiently checked upfront on a iov/cnt pair. Instead we assert upon hitting the end of src with an unsatisfied soffset. Signed-off-by: Stefan Hajnoczi --- include/qemu-common.h | 3 +++ iov.c | 47 ++++++++++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/include/qemu-common.h b/include/qemu-common.h index 6871cab371..2b83de395c 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -329,6 +329,9 @@ void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov); void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len); void qemu_iovec_concat(QEMUIOVector *dst, QEMUIOVector *src, size_t soffset, size_t sbytes); +void qemu_iovec_concat_iov(QEMUIOVector *dst, + struct iovec *src_iov, unsigned int src_cnt, + size_t soffset, size_t sbytes); void qemu_iovec_destroy(QEMUIOVector *qiov); void qemu_iovec_reset(QEMUIOVector *qiov); size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset, diff --git a/iov.c b/iov.c index 92ad77b162..c0f5c56618 100644 --- a/iov.c +++ b/iov.c @@ -288,6 +288,36 @@ void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len) ++qiov->niov; } +/* + * Concatenates (partial) iovecs from src_iov to the end of dst. + * It starts copying after skipping `soffset' bytes at the + * beginning of src and adds individual vectors from src to + * dst copies up to `sbytes' bytes total, or up to the end + * of src_iov if it comes first. This way, it is okay to specify + * very large value for `sbytes' to indicate "up to the end + * of src". + * Only vector pointers are processed, not the actual data buffers. + */ +void qemu_iovec_concat_iov(QEMUIOVector *dst, + struct iovec *src_iov, unsigned int src_cnt, + size_t soffset, size_t sbytes) +{ + int i; + size_t done; + assert(dst->nalloc != -1); + for (i = 0, done = 0; done < sbytes && i < src_cnt; i++) { + if (soffset < src_iov[i].iov_len) { + size_t len = MIN(src_iov[i].iov_len - soffset, sbytes - done); + qemu_iovec_add(dst, src_iov[i].iov_base + soffset, len); + done += len; + soffset = 0; + } else { + soffset -= src_iov[i].iov_len; + } + } + assert(soffset == 0); /* offset beyond end of src */ +} + /* * Concatenates (partial) iovecs from src to the end of dst. * It starts copying after skipping `soffset' bytes at the @@ -301,22 +331,7 @@ void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len) void qemu_iovec_concat(QEMUIOVector *dst, QEMUIOVector *src, size_t soffset, size_t sbytes) { - int i; - size_t done; - struct iovec *siov = src->iov; - assert(dst->nalloc != -1); - assert(src->size >= soffset); - for (i = 0, done = 0; done < sbytes && i < src->niov; i++) { - if (soffset < siov[i].iov_len) { - size_t len = MIN(siov[i].iov_len - soffset, sbytes - done); - qemu_iovec_add(dst, siov[i].iov_base + soffset, len); - done += len; - soffset = 0; - } else { - soffset -= siov[i].iov_len; - } - } - /* return done; */ + qemu_iovec_concat_iov(dst, src->iov, src->niov, soffset, sbytes); } void qemu_iovec_destroy(QEMUIOVector *qiov) From 8a873ba78069ef81c4ef073a0bd703172c8b3312 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 10 Dec 2012 13:14:39 +0100 Subject: [PATCH 2161/2270] virtio-blk: restore VirtIOBlkConf->config_wce flag Two slightly different versions of a patch to conditionally set VIRTIO_BLK_F_CONFIG_WCE through the "config-wce" qdev property have been applied (ea776abca and eec7f96c2). David Gibson noticed that the "config-wce" property is broken as a result and fixed it recently. The fix sets the host_features VIRTIO_BLK_F_CONFIG_WCE bit from a qdev property. Unfortunately, the virtio device then has no chance to test for the presence of the feature bit during virtio_blk_init(). Therefore, reinstate the VirtIOBlkConf->config_wce flag. Drop the duplicate qdev property to set the host_features bit. The VirtIOBlkConf->config_wce flag will be used by virtio-blk-data-plane in a later patch. Signed-off-by: Stefan Hajnoczi --- hw/virtio-blk.c | 3 +++ hw/virtio-blk.h | 4 ++-- hw/virtio-pci.c | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 90cfa246db..f004148e3e 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -524,6 +524,9 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features) features |= (1 << VIRTIO_BLK_F_BLK_SIZE); features |= (1 << VIRTIO_BLK_F_SCSI); + if (s->blk->config_wce) { + features |= (1 << VIRTIO_BLK_F_CONFIG_WCE); + } if (bdrv_enable_write_cache(s->bs)) features |= (1 << VIRTIO_BLK_F_WCE); diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h index 651a000b9f..454f445d61 100644 --- a/hw/virtio-blk.h +++ b/hw/virtio-blk.h @@ -104,10 +104,10 @@ struct VirtIOBlkConf BlockConf conf; char *serial; uint32_t scsi; + uint32_t config_wce; }; #define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \ - DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \ - DEFINE_PROP_BIT("config-wce", _state, _field, VIRTIO_BLK_F_CONFIG_WCE, true) + DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) #endif diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index d2d2454493..3cab783804 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -894,6 +894,7 @@ static Property virtio_blk_properties[] = { #ifdef __linux__ DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true), #endif + DEFINE_PROP_BIT("config-wce", VirtIOPCIProxy, blk.config_wce, 0, true), DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features), From e72f66a0a20f38d0c7576f6c0aec0ca644976e35 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 14 Nov 2012 15:39:30 +0100 Subject: [PATCH 2162/2270] dataplane: add virtio-blk data plane code virtio-blk-data-plane is a subset implementation of virtio-blk. It only handles read, write, and flush requests. It does this using a dedicated thread that executes an epoll(2)-based event loop and processes I/O using Linux AIO. This approach performs very well but can be used for raw image files only. The number of IOPS achieved has been reported to be several times higher than the existing virtio-blk implementation. Eventually it should be possible to unify virtio-blk-data-plane with the main body of QEMU code once the block layer and hardware emulation is able to run outside the global mutex. Signed-off-by: Stefan Hajnoczi --- hw/dataplane/Makefile.objs | 2 +- hw/dataplane/virtio-blk.c | 465 +++++++++++++++++++++++++++++++++++++ hw/dataplane/virtio-blk.h | 29 +++ hw/virtio-blk.h | 1 + trace-events | 6 + 5 files changed, 502 insertions(+), 1 deletion(-) create mode 100644 hw/dataplane/virtio-blk.c create mode 100644 hw/dataplane/virtio-blk.h diff --git a/hw/dataplane/Makefile.objs b/hw/dataplane/Makefile.objs index abd408f1da..682aa9e7ee 100644 --- a/hw/dataplane/Makefile.objs +++ b/hw/dataplane/Makefile.objs @@ -1,3 +1,3 @@ ifeq ($(CONFIG_VIRTIO), y) -common-obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += hostmem.o vring.o event-poll.o ioq.o +common-obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += hostmem.o vring.o event-poll.o ioq.o virtio-blk.o endif diff --git a/hw/dataplane/virtio-blk.c b/hw/dataplane/virtio-blk.c new file mode 100644 index 0000000000..4c4ad8422a --- /dev/null +++ b/hw/dataplane/virtio-blk.c @@ -0,0 +1,465 @@ +/* + * Dedicated thread for virtio-blk I/O processing + * + * Copyright 2012 IBM, Corp. + * Copyright 2012 Red Hat, Inc. and/or its affiliates + * + * Authors: + * Stefan Hajnoczi + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "trace.h" +#include "qemu/iov.h" +#include "event-poll.h" +#include "qemu/thread.h" +#include "vring.h" +#include "ioq.h" +#include "migration/migration.h" +#include "hw/virtio-blk.h" +#include "hw/dataplane/virtio-blk.h" + +enum { + SEG_MAX = 126, /* maximum number of I/O segments */ + VRING_MAX = SEG_MAX + 2, /* maximum number of vring descriptors */ + REQ_MAX = VRING_MAX, /* maximum number of requests in the vring, + * is VRING_MAX / 2 with traditional and + * VRING_MAX with indirect descriptors */ +}; + +typedef struct { + struct iocb iocb; /* Linux AIO control block */ + QEMUIOVector *inhdr; /* iovecs for virtio_blk_inhdr */ + unsigned int head; /* vring descriptor index */ +} VirtIOBlockRequest; + +struct VirtIOBlockDataPlane { + bool started; + QEMUBH *start_bh; + QemuThread thread; + + VirtIOBlkConf *blk; + int fd; /* image file descriptor */ + + VirtIODevice *vdev; + Vring vring; /* virtqueue vring */ + EventNotifier *guest_notifier; /* irq */ + + EventPoll event_poll; /* event poller */ + EventHandler io_handler; /* Linux AIO completion handler */ + EventHandler notify_handler; /* virtqueue notify handler */ + + IOQueue ioqueue; /* Linux AIO queue (should really be per + dataplane thread) */ + VirtIOBlockRequest requests[REQ_MAX]; /* pool of requests, managed by the + queue */ + + unsigned int num_reqs; + + Error *migration_blocker; +}; + +/* Raise an interrupt to signal guest, if necessary */ +static void notify_guest(VirtIOBlockDataPlane *s) +{ + if (!vring_should_notify(s->vdev, &s->vring)) { + return; + } + + event_notifier_set(s->guest_notifier); +} + +static void complete_request(struct iocb *iocb, ssize_t ret, void *opaque) +{ + VirtIOBlockDataPlane *s = opaque; + VirtIOBlockRequest *req = container_of(iocb, VirtIOBlockRequest, iocb); + struct virtio_blk_inhdr hdr; + int len; + + if (likely(ret >= 0)) { + hdr.status = VIRTIO_BLK_S_OK; + len = ret; + } else { + hdr.status = VIRTIO_BLK_S_IOERR; + len = 0; + } + + trace_virtio_blk_data_plane_complete_request(s, req->head, ret); + + qemu_iovec_from_buf(req->inhdr, 0, &hdr, sizeof(hdr)); + qemu_iovec_destroy(req->inhdr); + g_slice_free(QEMUIOVector, req->inhdr); + + /* According to the virtio specification len should be the number of bytes + * written to, but for virtio-blk it seems to be the number of bytes + * transferred plus the status bytes. + */ + vring_push(&s->vring, req->head, len + sizeof(hdr)); + + s->num_reqs--; +} + +static void complete_request_early(VirtIOBlockDataPlane *s, unsigned int head, + QEMUIOVector *inhdr, unsigned char status) +{ + struct virtio_blk_inhdr hdr = { + .status = status, + }; + + qemu_iovec_from_buf(inhdr, 0, &hdr, sizeof(hdr)); + qemu_iovec_destroy(inhdr); + g_slice_free(QEMUIOVector, inhdr); + + vring_push(&s->vring, head, sizeof(hdr)); + notify_guest(s); +} + +/* Get disk serial number */ +static void do_get_id_cmd(VirtIOBlockDataPlane *s, + struct iovec *iov, unsigned int iov_cnt, + unsigned int head, QEMUIOVector *inhdr) +{ + char id[VIRTIO_BLK_ID_BYTES]; + + /* Serial number not NUL-terminated when shorter than buffer */ + strncpy(id, s->blk->serial ? s->blk->serial : "", sizeof(id)); + iov_from_buf(iov, iov_cnt, 0, id, sizeof(id)); + complete_request_early(s, head, inhdr, VIRTIO_BLK_S_OK); +} + +static int process_request(IOQueue *ioq, struct iovec iov[], + unsigned int out_num, unsigned int in_num, + unsigned int head) +{ + VirtIOBlockDataPlane *s = container_of(ioq, VirtIOBlockDataPlane, ioqueue); + struct iovec *in_iov = &iov[out_num]; + struct virtio_blk_outhdr outhdr; + QEMUIOVector *inhdr; + size_t in_size; + struct iocb *iocb; + + /* Copy in outhdr */ + if (unlikely(iov_to_buf(iov, out_num, 0, &outhdr, + sizeof(outhdr)) != sizeof(outhdr))) { + error_report("virtio-blk request outhdr too short"); + return -EFAULT; + } + iov_discard_front(&iov, &out_num, sizeof(outhdr)); + + /* Grab inhdr for later */ + in_size = iov_size(in_iov, in_num); + if (in_size < sizeof(struct virtio_blk_inhdr)) { + error_report("virtio_blk request inhdr too short"); + return -EFAULT; + } + inhdr = g_slice_new(QEMUIOVector); + qemu_iovec_init(inhdr, 1); + qemu_iovec_concat_iov(inhdr, in_iov, in_num, + in_size - sizeof(struct virtio_blk_inhdr), + sizeof(struct virtio_blk_inhdr)); + iov_discard_back(in_iov, &in_num, sizeof(struct virtio_blk_inhdr)); + + /* TODO Linux sets the barrier bit even when not advertised! */ + outhdr.type &= ~VIRTIO_BLK_T_BARRIER; + + switch (outhdr.type) { + case VIRTIO_BLK_T_IN: + iocb = ioq_rdwr(ioq, true, in_iov, in_num, outhdr.sector * 512); + break; + + case VIRTIO_BLK_T_OUT: + iocb = ioq_rdwr(ioq, false, iov, out_num, outhdr.sector * 512); + break; + + case VIRTIO_BLK_T_SCSI_CMD: + /* TODO support SCSI commands */ + complete_request_early(s, head, inhdr, VIRTIO_BLK_S_UNSUPP); + return 0; + + case VIRTIO_BLK_T_FLUSH: + /* TODO fdsync not supported by Linux AIO, do it synchronously here! */ + if (qemu_fdatasync(s->fd) < 0) { + complete_request_early(s, head, inhdr, VIRTIO_BLK_S_IOERR); + } else { + complete_request_early(s, head, inhdr, VIRTIO_BLK_S_OK); + } + return 0; + + case VIRTIO_BLK_T_GET_ID: + do_get_id_cmd(s, in_iov, in_num, head, inhdr); + return 0; + + default: + error_report("virtio-blk unsupported request type %#x", outhdr.type); + qemu_iovec_destroy(inhdr); + g_slice_free(QEMUIOVector, inhdr); + return -EFAULT; + } + + /* Fill in virtio block metadata needed for completion */ + VirtIOBlockRequest *req = container_of(iocb, VirtIOBlockRequest, iocb); + req->head = head; + req->inhdr = inhdr; + return 0; +} + +static void handle_notify(EventHandler *handler) +{ + VirtIOBlockDataPlane *s = container_of(handler, VirtIOBlockDataPlane, + notify_handler); + + /* There is one array of iovecs into which all new requests are extracted + * from the vring. Requests are read from the vring and the translated + * descriptors are written to the iovecs array. The iovecs do not have to + * persist across handle_notify() calls because the kernel copies the + * iovecs on io_submit(). + * + * Handling io_submit() EAGAIN may require storing the requests across + * handle_notify() calls until the kernel has sufficient resources to + * accept more I/O. This is not implemented yet. + */ + struct iovec iovec[VRING_MAX]; + struct iovec *end = &iovec[VRING_MAX]; + struct iovec *iov = iovec; + + /* When a request is read from the vring, the index of the first descriptor + * (aka head) is returned so that the completed request can be pushed onto + * the vring later. + * + * The number of hypervisor read-only iovecs is out_num. The number of + * hypervisor write-only iovecs is in_num. + */ + int head; + unsigned int out_num = 0, in_num = 0; + unsigned int num_queued; + + for (;;) { + /* Disable guest->host notifies to avoid unnecessary vmexits */ + vring_disable_notification(s->vdev, &s->vring); + + for (;;) { + head = vring_pop(s->vdev, &s->vring, iov, end, &out_num, &in_num); + if (head < 0) { + break; /* no more requests */ + } + + trace_virtio_blk_data_plane_process_request(s, out_num, in_num, + head); + + if (process_request(&s->ioqueue, iov, out_num, in_num, head) < 0) { + vring_set_broken(&s->vring); + break; + } + iov += out_num + in_num; + } + + if (likely(head == -EAGAIN)) { /* vring emptied */ + /* Re-enable guest->host notifies and stop processing the vring. + * But if the guest has snuck in more descriptors, keep processing. + */ + if (vring_enable_notification(s->vdev, &s->vring)) { + break; + } + } else { /* head == -ENOBUFS or fatal error, iovecs[] is depleted */ + /* Since there are no iovecs[] left, stop processing for now. Do + * not re-enable guest->host notifies since the I/O completion + * handler knows to check for more vring descriptors anyway. + */ + break; + } + } + + num_queued = ioq_num_queued(&s->ioqueue); + if (num_queued > 0) { + s->num_reqs += num_queued; + + int rc = ioq_submit(&s->ioqueue); + if (unlikely(rc < 0)) { + fprintf(stderr, "ioq_submit failed %d\n", rc); + exit(1); + } + } +} + +static void handle_io(EventHandler *handler) +{ + VirtIOBlockDataPlane *s = container_of(handler, VirtIOBlockDataPlane, + io_handler); + + if (ioq_run_completion(&s->ioqueue, complete_request, s) > 0) { + notify_guest(s); + } + + /* If there were more requests than iovecs, the vring will not be empty yet + * so check again. There should now be enough resources to process more + * requests. + */ + if (unlikely(vring_more_avail(&s->vring))) { + handle_notify(&s->notify_handler); + } +} + +static void *data_plane_thread(void *opaque) +{ + VirtIOBlockDataPlane *s = opaque; + + do { + event_poll(&s->event_poll); + } while (s->started || s->num_reqs > 0); + return NULL; +} + +static void start_data_plane_bh(void *opaque) +{ + VirtIOBlockDataPlane *s = opaque; + + qemu_bh_delete(s->start_bh); + s->start_bh = NULL; + qemu_thread_create(&s->thread, data_plane_thread, + s, QEMU_THREAD_JOINABLE); +} + +bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, + VirtIOBlockDataPlane **dataplane) +{ + VirtIOBlockDataPlane *s; + int fd; + + *dataplane = NULL; + + if (!blk->data_plane) { + return true; + } + + if (blk->scsi) { + error_report("device is incompatible with x-data-plane, use scsi=off"); + return false; + } + + if (blk->config_wce) { + error_report("device is incompatible with x-data-plane, " + "use config-wce=off"); + return false; + } + + fd = raw_get_aio_fd(blk->conf.bs); + if (fd < 0) { + error_report("drive is incompatible with x-data-plane, " + "use format=raw,cache=none,aio=native"); + return false; + } + + s = g_new0(VirtIOBlockDataPlane, 1); + s->vdev = vdev; + s->fd = fd; + s->blk = blk; + + /* Prevent block operations that conflict with data plane thread */ + bdrv_set_in_use(blk->conf.bs, 1); + + error_setg(&s->migration_blocker, + "x-data-plane does not support migration"); + migrate_add_blocker(s->migration_blocker); + + *dataplane = s; + return true; +} + +void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s) +{ + if (!s) { + return; + } + + virtio_blk_data_plane_stop(s); + migrate_del_blocker(s->migration_blocker); + error_free(s->migration_blocker); + bdrv_set_in_use(s->blk->conf.bs, 0); + g_free(s); +} + +void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) +{ + VirtQueue *vq; + int i; + + if (s->started) { + return; + } + + vq = virtio_get_queue(s->vdev, 0); + if (!vring_setup(&s->vring, s->vdev, 0)) { + return; + } + + event_poll_init(&s->event_poll); + + /* Set up guest notifier (irq) */ + if (s->vdev->binding->set_guest_notifiers(s->vdev->binding_opaque, + true) != 0) { + fprintf(stderr, "virtio-blk failed to set guest notifier, " + "ensure -enable-kvm is set\n"); + exit(1); + } + s->guest_notifier = virtio_queue_get_guest_notifier(vq); + + /* Set up virtqueue notify */ + if (s->vdev->binding->set_host_notifier(s->vdev->binding_opaque, + 0, true) != 0) { + fprintf(stderr, "virtio-blk failed to set host notifier\n"); + exit(1); + } + event_poll_add(&s->event_poll, &s->notify_handler, + virtio_queue_get_host_notifier(vq), + handle_notify); + + /* Set up ioqueue */ + ioq_init(&s->ioqueue, s->fd, REQ_MAX); + for (i = 0; i < ARRAY_SIZE(s->requests); i++) { + ioq_put_iocb(&s->ioqueue, &s->requests[i].iocb); + } + event_poll_add(&s->event_poll, &s->io_handler, + ioq_get_notifier(&s->ioqueue), handle_io); + + s->started = true; + trace_virtio_blk_data_plane_start(s); + + /* Kick right away to begin processing requests already in vring */ + event_notifier_set(virtio_queue_get_host_notifier(vq)); + + /* Spawn thread in BH so it inherits iothread cpusets */ + s->start_bh = qemu_bh_new(start_data_plane_bh, s); + qemu_bh_schedule(s->start_bh); +} + +void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s) +{ + if (!s->started) { + return; + } + s->started = false; + trace_virtio_blk_data_plane_stop(s); + + /* Stop thread or cancel pending thread creation BH */ + if (s->start_bh) { + qemu_bh_delete(s->start_bh); + s->start_bh = NULL; + } else { + event_poll_notify(&s->event_poll); + qemu_thread_join(&s->thread); + } + + ioq_cleanup(&s->ioqueue); + + s->vdev->binding->set_host_notifier(s->vdev->binding_opaque, 0, false); + + event_poll_cleanup(&s->event_poll); + + /* Clean up guest notifier (irq) */ + s->vdev->binding->set_guest_notifiers(s->vdev->binding_opaque, false); + + vring_teardown(&s->vring); +} diff --git a/hw/dataplane/virtio-blk.h b/hw/dataplane/virtio-blk.h new file mode 100644 index 0000000000..1e8fdfe418 --- /dev/null +++ b/hw/dataplane/virtio-blk.h @@ -0,0 +1,29 @@ +/* + * Dedicated thread for virtio-blk I/O processing + * + * Copyright 2012 IBM, Corp. + * Copyright 2012 Red Hat, Inc. and/or its affiliates + * + * Authors: + * Stefan Hajnoczi + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef HW_DATAPLANE_VIRTIO_BLK_H +#define HW_DATAPLANE_VIRTIO_BLK_H + +#include "hw/virtio.h" + +typedef struct VirtIOBlockDataPlane VirtIOBlockDataPlane; + +bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, + VirtIOBlockDataPlane **dataplane); +void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s); +void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s); +void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s); +void virtio_blk_data_plane_drain(VirtIOBlockDataPlane *s); + +#endif /* HW_DATAPLANE_VIRTIO_BLK_H */ diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h index 454f445d61..43ca492080 100644 --- a/hw/virtio-blk.h +++ b/hw/virtio-blk.h @@ -105,6 +105,7 @@ struct VirtIOBlkConf char *serial; uint32_t scsi; uint32_t config_wce; + uint32_t data_plane; }; #define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \ diff --git a/trace-events b/trace-events index 167d776eff..4023a4c094 100644 --- a/trace-events +++ b/trace-events @@ -98,6 +98,12 @@ virtio_blk_rw_complete(void *req, int ret) "req %p ret %d" virtio_blk_handle_write(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu" virtio_blk_handle_read(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu" +# hw/dataplane/virtio-blk.c +virtio_blk_data_plane_start(void *s) "dataplane %p" +virtio_blk_data_plane_stop(void *s) "dataplane %p" +virtio_blk_data_plane_process_request(void *s, unsigned int out_num, unsigned int in_num, unsigned int head) "dataplane %p out_num %u in_num %u head %u" +virtio_blk_data_plane_complete_request(void *s, unsigned int head, int ret) "dataplane %p head %u ret %d" + # hw/dataplane/vring.c vring_setup(uint64_t physical, void *desc, void *avail, void *used) "vring physical %#"PRIx64" desc %p avail %p used %p" From 392808b49b6aee066d0c1d200e72fc3dc11c9d0f Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 14 Nov 2012 15:45:38 +0100 Subject: [PATCH 2163/2270] virtio-blk: add x-data-plane=on|off performance feature The virtio-blk-data-plane feature is easy to integrate into hw/virtio-blk.c. The data plane can be started and stopped similar to vhost-net. Users can take advantage of the virtio-blk-data-plane feature using the new -device virtio-blk-pci,x-data-plane=on property. The x-data-plane name was chosen because at this stage the feature is experimental and likely to see changes in the future. If the VM configuration does not support virtio-blk-data-plane an error message is printed. Although we could fall back to regular virtio-blk, I prefer the explicit approach since it prompts the user to fix their configuration if they want the performance benefit of virtio-blk-data-plane. Limitations: * Only format=raw is supported * Live migration is not supported * Block jobs, hot unplug, and other operations fail with -EBUSY * I/O throttling limits are ignored * Only Linux hosts are supported due to Linux AIO usage Signed-off-by: Stefan Hajnoczi --- hw/virtio-blk.c | 44 +++++++++++++++++++++++++++++++++++++++++++- hw/virtio-pci.c | 3 +++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index f004148e3e..92c745a316 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -17,6 +17,9 @@ #include "hw/block-common.h" #include "sysemu/blockdev.h" #include "virtio-blk.h" +#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE +#include "hw/dataplane/virtio-blk.h" +#endif #include "scsi-defs.h" #ifdef __linux__ # include @@ -33,6 +36,9 @@ typedef struct VirtIOBlock VirtIOBlkConf *blk; unsigned short sector_mask; DeviceState *qdev; +#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE + VirtIOBlockDataPlane *dataplane; +#endif } VirtIOBlock; static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev) @@ -407,6 +413,16 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) .num_writes = 0, }; +#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE + /* Some guests kick before setting VIRTIO_CONFIG_S_DRIVER_OK so start + * dataplane here instead of waiting for .set_status(). + */ + if (s->dataplane) { + virtio_blk_data_plane_start(s->dataplane); + return; + } +#endif + while ((req = virtio_blk_get_request(s))) { virtio_blk_handle_request(req, &mrb); } @@ -446,8 +462,9 @@ static void virtio_blk_dma_restart_cb(void *opaque, int running, { VirtIOBlock *s = opaque; - if (!running) + if (!running) { return; + } if (!s->bh) { s->bh = qemu_bh_new(virtio_blk_dma_restart_bh, s); @@ -457,6 +474,14 @@ static void virtio_blk_dma_restart_cb(void *opaque, int running, static void virtio_blk_reset(VirtIODevice *vdev) { +#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE + VirtIOBlock *s = to_virtio_blk(vdev); + + if (s->dataplane) { + virtio_blk_data_plane_stop(s->dataplane); + } +#endif + /* * This should cancel pending requests, but can't do nicely until there * are per-device request lists. @@ -541,6 +566,12 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status) VirtIOBlock *s = to_virtio_blk(vdev); uint32_t features; +#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE + if (s->dataplane && !(status & VIRTIO_CONFIG_S_DRIVER)) { + virtio_blk_data_plane_stop(s->dataplane); + } +#endif + if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) { return; } @@ -638,6 +669,12 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk) s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1; s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output); +#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE + if (!virtio_blk_data_plane_create(&s->vdev, blk, &s->dataplane)) { + virtio_cleanup(&s->vdev); + return NULL; + } +#endif qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s); s->qdev = dev; @@ -655,6 +692,11 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk) void virtio_blk_exit(VirtIODevice *vdev) { VirtIOBlock *s = to_virtio_blk(vdev); + +#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE + virtio_blk_data_plane_destroy(s->dataplane); + s->dataplane = NULL; +#endif unregister_savevm(s->qdev, "virtio-blk", s); blockdev_mark_auto_del(s->bs); virtio_cleanup(vdev); diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 3cab783804..82761cf7f7 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -896,6 +896,9 @@ static Property virtio_blk_properties[] = { #endif DEFINE_PROP_BIT("config-wce", VirtIOPCIProxy, blk.config_wce, 0, true), DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), +#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE + DEFINE_PROP_BIT("x-data-plane", VirtIOPCIProxy, blk.data_plane, 0, false), +#endif DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features), DEFINE_PROP_END_OF_LIST(), From 9e72c45033770b81b536ac6091e91807247cc25a Mon Sep 17 00:00:00 2001 From: Alexey Zaytsev Date: Thu, 13 Dec 2012 09:03:43 +0200 Subject: [PATCH 2164/2270] virtio-blk: Return UNSUPP for unknown request types Currently, all unknown requests are treated as VIRTIO_BLK_T_IN Signed-off-by: Alexey Zaytsev Signed-off-by: Stefan Hajnoczi --- hw/virtio-blk.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 92c745a316..df57b35f1b 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -398,10 +398,14 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req, qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1], req->elem.out_num - 1); virtio_blk_handle_write(req, mrb); - } else { + } else if (type == VIRTIO_BLK_T_IN || type == VIRTIO_BLK_T_BARRIER) { + /* VIRTIO_BLK_T_IN is 0, so we can't just & it. */ qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0], req->elem.in_num - 1); virtio_blk_handle_read(req); + } else { + virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP); + g_free(req); } } From 37edbf7ea8067262a5c3d8bbe4786139348c8311 Mon Sep 17 00:00:00 2001 From: liguang Date: Mon, 17 Dec 2012 09:49:22 +0800 Subject: [PATCH 2165/2270] cutils: change strtosz_suffix_unit function if value to be translated is larger than INT64_MAX, this function will not be convenient for caller to be aware of it, so change a little for this. Signed-off-by: liguang Signed-off-by: Stefan Hajnoczi --- cutils.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cutils.c b/cutils.c index d06590b330..80bb1dcbf7 100644 --- a/cutils.c +++ b/cutils.c @@ -214,12 +214,13 @@ static int64_t suffix_mul(char suffix, int64_t unit) /* * Convert string to bytes, allowing either B/b for bytes, K/k for KB, * M/m for MB, G/g for GB or T/t for TB. End pointer will be returned - * in *end, if not NULL. Return -1 on error. + * in *end, if not NULL. Return -ERANGE on overflow, Return -EINVAL on + * other error. */ int64_t strtosz_suffix_unit(const char *nptr, char **end, const char default_suffix, int64_t unit) { - int64_t retval = -1; + int64_t retval = -EINVAL; char *endptr; unsigned char c; int mul_required = 0; @@ -246,6 +247,7 @@ int64_t strtosz_suffix_unit(const char *nptr, char **end, goto fail; } if ((val * mul >= INT64_MAX) || val < 0) { + retval = -ERANGE; goto fail; } retval = val * mul; From 7944339726b4582b67fd94085c21c33636e8f973 Mon Sep 17 00:00:00 2001 From: liguang Date: Mon, 17 Dec 2012 09:49:23 +0800 Subject: [PATCH 2166/2270] qemu-img: report size overflow error message qemu-img will complain when qcow or qcow2 size overflow for 64 bits, report the right message in this condition. $./qemu-img create -f qcow2 /tmp/foo 0x10000000000000000 before change: qemu-img: Invalid image size specified! You may use k, M, G or T suffixes for qemu-img: kilobytes, megabytes, gigabytes and terabytes. after change: qemu-img: Image size must be less than 8 EiB! [Resolved conflict with a9300911 goto removal -- Stefan] Signed-off-by: liguang Signed-off-by: Stefan Hajnoczi --- qemu-img.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index 69cc02871b..85d3740b9c 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -348,9 +348,13 @@ static int img_create(int argc, char **argv) char *end; sval = strtosz_suffix(argv[optind++], &end, STRTOSZ_DEFSUFFIX_B); if (sval < 0 || *end) { - error_report("Invalid image size specified! You may use k, M, G or " - "T suffixes for "); - error_report("kilobytes, megabytes, gigabytes and terabytes."); + if (sval == -ERANGE) { + error_report("Image size must be less than 8 EiB!"); + } else { + error_report("Invalid image size specified! You may use k, M, " + "G or T suffixes for "); + error_report("kilobytes, megabytes, gigabytes and terabytes."); + } return 1; } img_size = (uint64_t)sval; From fccedc624c425e3acb1557f9f9b13104427ec5ce Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Mon, 17 Dec 2012 20:40:01 +0100 Subject: [PATCH 2167/2270] block/raw-win32: Fix compiler warnings (wrong format specifiers) Commit fbcad04d6bfdff937536eb23088a01a280a1a3af added fprintf statements with wrong format specifiers. GetLastError() returns a DWORD which is unsigned long, so %lu must be used. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- block/raw-win32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block/raw-win32.c b/block/raw-win32.c index f58334be08..b89ac19ffa 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -314,11 +314,11 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset) */ dwPtrLow = SetFilePointer(s->hfile, low, &high, FILE_BEGIN); if (dwPtrLow == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) { - fprintf(stderr, "SetFilePointer error: %d\n", GetLastError()); + fprintf(stderr, "SetFilePointer error: %lu\n", GetLastError()); return -EIO; } if (SetEndOfFile(s->hfile) == 0) { - fprintf(stderr, "SetEndOfFile error: %d\n", GetLastError()); + fprintf(stderr, "SetEndOfFile error: %lu\n", GetLastError()); return -EIO; } return 0; From bd751f2204a03d6fcd47a4b4b12ac534d2ecbea7 Mon Sep 17 00:00:00 2001 From: Liu Yuan Date: Mon, 17 Dec 2012 14:17:26 +0800 Subject: [PATCH 2168/2270] sheepdog: don't update inode when create_and_write fails For the error case such as SD_RES_NO_SPACE, we shouldn't update the inode bitmap to avoid the scenario that the object is allocated but wasn't created at the server side. This will result in VM's IO error on the failed object. Cc: MORITA Kazutaka Cc: Kevin Wolf Signed-off-by: Liu Yuan Reviewed-by: MORITA Kazutaka Signed-off-by: Stefan Hajnoczi --- block/sheepdog.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/block/sheepdog.c b/block/sheepdog.c index 13dc023fdb..b9186fb92b 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -714,10 +714,11 @@ static void coroutine_fn aio_read_response(void *opaque) * and max_dirty_data_idx are changed to include updated * index between them. */ - s->inode.data_vdi_id[idx] = s->inode.vdi_id; - s->max_dirty_data_idx = MAX(idx, s->max_dirty_data_idx); - s->min_dirty_data_idx = MIN(idx, s->min_dirty_data_idx); - + if (rsp.result == SD_RES_SUCCESS) { + s->inode.data_vdi_id[idx] = s->inode.vdi_id; + s->max_dirty_data_idx = MAX(idx, s->max_dirty_data_idx); + s->min_dirty_data_idx = MIN(idx, s->min_dirty_data_idx); + } /* * Some requests may be blocked because simultaneous * create requests are not allowed, so we search the From d6b1ef89a1ede41334e4d0fa27e600e0b4d4f209 Mon Sep 17 00:00:00 2001 From: Liu Yuan Date: Mon, 17 Dec 2012 14:17:27 +0800 Subject: [PATCH 2169/2270] sheepdog: pass oid directly to send_pending_req() Cc: MORITA Kazutaka Cc: Kevin Wolf Signed-off-by: Liu Yuan Reviewed-by: MORITA Kazutaka Signed-off-by: Stefan Hajnoczi --- block/sheepdog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/sheepdog.c b/block/sheepdog.c index b9186fb92b..e821746116 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -724,7 +724,7 @@ static void coroutine_fn aio_read_response(void *opaque) * create requests are not allowed, so we search the * pending requests here. */ - send_pending_req(s, vid_to_data_oid(s->inode.vdi_id, idx)); + send_pending_req(s, aio_req->oid); } break; case AIOCB_READ_UDATA: From 9a8a5ae69d3a436e51a7eb2edafe254572f60823 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sun, 30 Dec 2012 08:20:13 +0100 Subject: [PATCH 2170/2270] tcg: Remove unneeded assertion Commit 7f6f0ae5b95adfa76e10eabe2c34424a955fd10c added two assertions. One of these assertions is not needed: The pointer ts is never NULL because it is initialized with the address of an array element. Reviewed-by: Richard Henderson Signed-off-by: Stefan Weil Signed-off-by: Anthony Liguori --- tcg/tcg.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index ede51a3960..9275e372ff 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -800,7 +800,6 @@ static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size, assert(idx >= 0 && idx < s->nb_temps); ts = &s->temps[idx]; - assert(ts); if (idx < s->nb_globals) { pstrcpy(buf, buf_size, ts->name); } else { From ab51b1d568e02c80b1abf9016bda3a86dc1db389 Mon Sep 17 00:00:00 2001 From: Michael Tokarev Date: Sun, 30 Dec 2012 12:48:14 +0400 Subject: [PATCH 2171/2270] disallow -daemonize usage of stdio (curses display, -nographic, -serial stdio etc) Curses display requires stdin/out to stay on the terminal, so -daemonize makes no sense in this case. Instead of leaving display uninitialized like is done since 995ee2bf469de6bb, explicitly detect this case earlier and error out. -nographic can actually be used with -daemonize, by redirecting everything to a null device, but the problem is that according to documentation and historical behavour, -nographic redirects guest ports to stdin/out, which, again, makes no sense in case of -daemonize. Since -nographic is a legacy option, don't bother fixing this case (to allow -nographic and -daemonize by redirecting guest ports to null instead of stdin/out in this case), but disallow it completely instead, to stop garbling host terminal. If no display display needed and user wants to use -nographic, the right way to go is to use -serial null -parallel null -monitor none -display none -vga none instead of -nographic. Also prevent the same issue -- it was possible to get garbled host tty after -nographic -daemonize and it is still possible to have it by using -serial stdio -daemonize Fix this by disallowing opening stdio chardev when -daemonize is specified. Signed-off-by: Michael Tokarev Signed-off-by: Anthony Liguori --- qemu-char.c | 4 ++++ vl.c | 28 +++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index c6382a93f5..331ad5c087 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -772,6 +772,10 @@ static CharDriverState *qemu_chr_open_stdio(QemuOpts *opts) if (stdio_nb_clients >= STDIO_MAX_CLIENTS) { return NULL; } + if (is_daemonized()) { + error_report("cannot use stdio with -daemonize"); + return NULL; + } if (stdio_nb_clients == 0) { old_fd0_flags = fcntl(0, F_GETFL); tcgetattr (0, &oldtty); diff --git a/vl.c b/vl.c index e6a8d89acc..f056c95807 100644 --- a/vl.c +++ b/vl.c @@ -3637,6 +3637,30 @@ int main(int argc, char **argv, char **envp) default_sdcard = 0; } + if (is_daemonized()) { + /* According to documentation and historically, -nographic redirects + * serial port, parallel port and monitor to stdio, which does not work + * with -daemonize. We can redirect these to null instead, but since + * -nographic is legacy, let's just error out. + * We disallow -nographic only if all other ports are not redirected + * explicitly, to not break existing legacy setups which uses + * -nographic _and_ redirects all ports explicitly - this is valid + * usage, -nographic is just a no-op in this case. + */ + if (display_type == DT_NOGRAPHIC + && (default_parallel || default_serial + || default_monitor || default_virtcon)) { + fprintf(stderr, "-nographic can not be used with -daemonize\n"); + exit(1); + } +#ifdef CONFIG_CURSES + if (display_type == DT_CURSES) { + fprintf(stderr, "curses display can not be used with -daemonize\n"); + exit(1); + } +#endif + } + if (display_type == DT_NOGRAPHIC) { if (default_parallel) add_device_config(DEV_PARALLEL, "null"); @@ -3903,9 +3927,7 @@ int main(int argc, char **argv, char **envp) break; #if defined(CONFIG_CURSES) case DT_CURSES: - if (!is_daemonized()) { - curses_display_init(ds, full_screen); - } + curses_display_init(ds, full_screen); break; #endif #if defined(CONFIG_SDL) From 74e91370beb3fabda515623b4491a8b7a024304a Mon Sep 17 00:00:00 2001 From: Michael Tokarev Date: Mon, 31 Dec 2012 15:30:31 +0400 Subject: [PATCH 2172/2270] savevm.c: cleanup system includes savevm.c suffers from the same problem as some other files. Some years ago savevm.c was created from vl.c, moving some code from there into a separate file. At that time, all includes were just copied from vl.c to savevm.c, without checking which ones are needed and which are not. But actually most of that stuff is _not_ needed. More, some stuff is wrong, for example, *BSD #ifdef'ery around vs - for one, it fails to build on Debian/kFreebsd. Just remove all this. Maybe there's a possibility to clean it up further - like removing (and maybe including winsock.h for htons etc), and maybe it's possible to remove some internal #includes too, but I didn't check this. While at it, remove duplicate #include of qemu/timer.h. Signed-off-by: Michael Tokarev Signed-off-by: Anthony Liguori --- savevm.c | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/savevm.c b/savevm.c index bcdb92ee81..529d60ec1f 100644 --- a/savevm.c +++ b/savevm.c @@ -21,52 +21,15 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include -#include -#include -#include -#include -#include -/* Needed early for CONFIG_BSD etc. */ #include "config-host.h" #ifndef _WIN32 -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#ifdef CONFIG_BSD -#include -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) -#include -#else -#include -#endif -#ifdef __linux__ -#include -#include -#include -#endif -#endif #endif #ifdef _WIN32 #include -#include -#include -#include -#define getopt_long_only getopt_long -#define memalign(align, size) malloc(size) #endif #include "qemu-common.h" @@ -80,7 +43,6 @@ #include "migration/migration.h" #include "qemu/sockets.h" #include "qemu/queue.h" -#include "qemu/timer.h" #include "sysemu/cpus.h" #include "exec/memory.h" #include "qmp-commands.h" From 503483336039a8b2b182535f87f4820d259fca82 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Tue, 1 Jan 2013 18:43:56 +0100 Subject: [PATCH 2173/2270] tci: Fix broken builds with TCG interpreter TCI no longer compiled after commit 76cad71136b7eb371cf2a2a4e1621cfe8d9c769a. The TCI disassembler depends on data structures which are different for each QEMU target, so it cannot be compiled as a universal-obj today. Signed-off-by: Stefan Weil Signed-off-by: Anthony Liguori --- Makefile.target | 3 +-- disas/Makefile.objs | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile.target b/Makefile.target index be8b8b86a5..5bfa496080 100644 --- a/Makefile.target +++ b/Makefile.target @@ -69,13 +69,12 @@ all: $(PROGS) stap obj-y = exec.o translate-all.o cpu-exec.o obj-y += tcg/tcg.o tcg/optimize.o obj-$(CONFIG_TCG_INTERPRETER) += tci.o +obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o obj-y += fpu/softfloat.o obj-y += target-$(TARGET_BASE_ARCH)/ obj-y += disas.o obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o -tci-dis.o: QEMU_CFLAGS += -I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/tci - ######################################################### # Linux user emulator target diff --git a/disas/Makefile.objs b/disas/Makefile.objs index 9134429845..3f5c5b9a21 100644 --- a/disas/Makefile.objs +++ b/disas/Makefile.objs @@ -13,4 +13,6 @@ universal-obj-$(CONFIG_SH4_DIS) += sh4.o universal-obj-$(CONFIG_SPARC_DIS) += sparc.o universal-obj-$(CONFIG_LM32_DIS) += lm32.o -universal-obj-$(CONFIG_TCI_DIS) += tci.o +# TODO: As long as the TCG interpreter and its generated code depend +# on the QEMU target, we cannot compile the disassembler here. +#universal-obj-$(CONFIG_TCI_DIS) += tci.o From dbd99ae302be8f51b547fb6283c91d0c9859b7d5 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Tue, 1 Jan 2013 18:33:44 +0100 Subject: [PATCH 2174/2270] configure: Write new file "config-all-disas.mak" when running configure Incremental builds added new lines to that file each time when configure was run. Now a new file with a comment line is written. Signed-off-by: Stefan Weil Signed-off-by: Anthony Liguori --- configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure b/configure index cc1e20ac54..9538041d05 100755 --- a/configure +++ b/configure @@ -3314,6 +3314,8 @@ fi config_host_mak="config-host.mak" config_host_ld="config-host.ld" +echo "# Automatically generated by configure - do not modify" >config-all-disas.mak + echo "# Automatically generated by configure - do not modify" > $config_host_mak printf "# Configured with:" >> $config_host_mak printf " '%s'" "$0" "$@" >> $config_host_mak From ef4929fb3c25e03deca76c7f5d22fba08edf864f Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 3 Jan 2013 11:56:16 +0100 Subject: [PATCH 2175/2270] dataplane: use linux-headers/ for virtio includes The hw/dataplane/vring.c code includes linux/virtio_ring.h. Ensure that we use linux-headers/ instead of the system-wide headers, which may be out-of-date on older distros. This resolves the following build error on Debian 6: CC hw/dataplane/vring.o cc1: warnings being treated as errors hw/dataplane/vring.c: In function 'vring_enable_notification': hw/dataplane/vring.c:71: error: implicit declaration of function 'vring_avail_event' hw/dataplane/vring.c:71: error: nested extern declaration of 'vring_avail_event' hw/dataplane/vring.c:71: error: lvalue required as left operand of assignment Note that we now build dataplane/ for each target instead of only once. There is no way around this since linux-headers/ is only available for per-target objects - and it's how virtio, vfio, kvm, and friends are built. Signed-off-by: Stefan Hajnoczi Signed-off-by: Anthony Liguori --- hw/Makefile.objs | 3 ++- hw/dataplane/Makefile.objs | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 5ac49134bd..b8bbed39c1 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -1,4 +1,4 @@ -common-obj-y = usb/ ide/ pci/ dataplane/ +common-obj-y = usb/ ide/ pci/ common-obj-y += loader.o common-obj-$(CONFIG_VIRTIO) += virtio-console.o common-obj-$(CONFIG_VIRTIO) += virtio-rng.o @@ -191,6 +191,7 @@ common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o xenfb.o xen_disk.o xen_nic.o # Per-target files # virtio has to be here due to weird dependency between PCI and virtio-net. # need to fix this properly +obj-$(CONFIG_VIRTIO) += dataplane/ obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o virtio-scsi.o obj-$(CONFIG_SOFTMMU) += vhost_net.o diff --git a/hw/dataplane/Makefile.objs b/hw/dataplane/Makefile.objs index 682aa9e7ee..3e47d0537e 100644 --- a/hw/dataplane/Makefile.objs +++ b/hw/dataplane/Makefile.objs @@ -1,3 +1 @@ -ifeq ($(CONFIG_VIRTIO), y) -common-obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += hostmem.o vring.o event-poll.o ioq.o virtio-blk.o -endif +obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += hostmem.o vring.o event-poll.o ioq.o virtio-blk.o From 25bbf61e4bacd1e4fa4115ffcf151051b9d6608e Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 3 Jan 2013 14:23:03 +0100 Subject: [PATCH 2176/2270] pty: unbreak libvirt Commit 586502189edf9fd0f89a83de96717a2ea826fdb0 breaks libvirt pty support because it tried to figure the pts name from stderr output. Fix this by moving the label to the end of the line, this way the libvirt parser does still recognise the message. libvirt looks for "char device redirected to ${ptsname}". Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- qemu-char.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 331ad5c087..f41788c9ef 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -1012,10 +1012,11 @@ static CharDriverState *qemu_chr_open_pty(QemuOpts *opts) qemu_opt_set(opts, "path", q_ptsname(master_fd)); label = qemu_opts_id(opts); - fprintf(stderr, "char device%s%s redirected to %s\n", - label ? " " : "", - label ?: "", - q_ptsname(master_fd)); + fprintf(stderr, "char device redirected to %s%s%s%s\n", + q_ptsname(master_fd), + label ? " (label " : "", + label ? label : "", + label ? ")" : ""); s = g_malloc0(sizeof(PtyCharDriver)); chr->opaque = s; From 5acc2ec041b2fd5c9a85d9d12362c08d3b3bf339 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 3 Dec 2012 10:45:49 +0100 Subject: [PATCH 2177/2270] configure: also symlink *.aml files Signed-off-by: Gerd Hoffmann --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 9538041d05..1e9fd868af 100755 --- a/configure +++ b/configure @@ -4240,6 +4240,7 @@ FILES="$FILES pc-bios/spapr-rtas/Makefile" FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile" for bios_file in \ $source_path/pc-bios/*.bin \ + $source_path/pc-bios/*.aml \ $source_path/pc-bios/*.rom \ $source_path/pc-bios/*.dtb \ $source_path/pc-bios/openbios-* \ From f7e4dd6c18ccfbaf6cd2f5eaaed2b77cabc8a406 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 3 Dec 2012 10:47:27 +0100 Subject: [PATCH 2178/2270] acpi: autoload dsdt Signed-off-by: Gerd Hoffmann --- hw/pc.c | 23 +++++++++++++++++++++++ hw/pc.h | 1 + hw/pc_piix.c | 1 + hw/pc_q35.c | 1 + 4 files changed, 26 insertions(+) diff --git a/hw/pc.c b/hw/pc.c index 71902e210b..5ec3bd5aff 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -886,6 +886,29 @@ void pc_cpus_init(const char *cpu_model) } } +void pc_acpi_init(const char *default_dsdt) +{ + char *filename = NULL, *arg = NULL; + + if (acpi_tables != NULL) { + /* manually set via -acpitable, leave it alone */ + return; + } + + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, default_dsdt); + if (filename == NULL) { + fprintf(stderr, "WARNING: failed to find %s\n", default_dsdt); + return; + } + + arg = g_strdup_printf("file=%s", filename); + if (acpi_table_add(arg) != 0) { + fprintf(stderr, "WARNING: failed to load %s\n", filename); + } + g_free(arg); + g_free(filename); +} + void *pc_memory_init(MemoryRegion *system_memory, const char *kernel_filename, const char *kernel_cmdline, diff --git a/hw/pc.h b/hw/pc.h index a73e3e7b5b..4134aa94e5 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -79,6 +79,7 @@ void pc_register_ferr_irq(qemu_irq irq); void pc_acpi_smi_interrupt(void *opaque, int irq, int level); void pc_cpus_init(const char *cpu_model); +void pc_acpi_init(const char *default_dsdt); void *pc_memory_init(MemoryRegion *system_memory, const char *kernel_filename, const char *kernel_cmdline, diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 99747a774c..2b3d58b852 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -87,6 +87,7 @@ static void pc_init1(MemoryRegion *system_memory, void *fw_cfg = NULL; pc_cpus_init(cpu_model); + pc_acpi_init("acpi-dsdt.aml"); if (kvmclock_enabled) { kvmclock_create(); diff --git a/hw/pc_q35.c b/hw/pc_q35.c index c7262d6315..ef540b6a71 100644 --- a/hw/pc_q35.c +++ b/hw/pc_q35.c @@ -87,6 +87,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) qemu_irq *cmos_s3; pc_cpus_init(cpu_model); + pc_acpi_init("q35-acpi-dsdt.aml"); kvmclock_create(); From 56e5b2a1a655b9158c0d274a6f630927c9a5fb4b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 11 Dec 2012 09:40:45 +0100 Subject: [PATCH 2179/2270] apci: assign memory regions to piix4 acpi device Get rid of get_system_io() usage. Signed-off-by: Gerd Hoffmann --- hw/acpi_piix4.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index f53b969aa6..06a8aca9cb 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -57,6 +57,7 @@ struct pci_status { typedef struct PIIX4PMState { PCIDevice dev; + MemoryRegion io; MemoryRegion io_gpe; MemoryRegion io_pci; @@ -83,7 +84,8 @@ typedef struct PIIX4PMState { uint8_t s4_val; } PIIX4PMState; -static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s); +static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, + PCIBus *bus, PIIX4PMState *s); #define ACPI_ENABLE 0xf1 #define ACPI_DISABLE 0xf0 @@ -406,11 +408,13 @@ static int piix4_pm_initfn(PCIDevice *dev) pci_conf[0xd2] = 0x09; pm_smbus_init(&s->dev.qdev, &s->smb); memory_region_set_enabled(&s->smb.io, pci_conf[0xd2] & 1); - memory_region_add_subregion(get_system_io(), s->smb_io_base, &s->smb.io); + memory_region_add_subregion(pci_address_space_io(dev), + s->smb_io_base, &s->smb.io); memory_region_init(&s->io, "piix4-pm", 64); memory_region_set_enabled(&s->io, false); - memory_region_add_subregion(get_system_io(), 0, &s->io); + memory_region_add_subregion(pci_address_space_io(dev), + 0, &s->io); acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io); acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io); @@ -423,7 +427,8 @@ static int piix4_pm_initfn(PCIDevice *dev) s->machine_ready.notify = piix4_pm_machine_ready; qemu_add_machine_init_done_notifier(&s->machine_ready); qemu_register_reset(piix4_reset, s); - piix4_acpi_system_hot_add_init(dev->bus, s); + + piix4_acpi_system_hot_add_init(pci_address_space_io(dev), dev->bus, s); return 0; } @@ -593,15 +598,16 @@ static const MemoryRegionOps piix4_pci_ops = { static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, PCIHotplugState state); -static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s) +static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, + PCIBus *bus, PIIX4PMState *s) { memory_region_init_io(&s->io_gpe, &piix4_gpe_ops, s, "apci-gpe0", GPE_LEN); - memory_region_add_subregion(get_system_io(), GPE_BASE, &s->io_gpe); + memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe); memory_region_init_io(&s->io_pci, &piix4_pci_ops, s, "apci-pci-hotplug", PCI_HOTPLUG_SIZE); - memory_region_add_subregion(get_system_io(), PCI_HOTPLUG_ADDR, + memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR, &s->io_pci); pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev); } From 503b19fc5d018f4edc60fb771cf97f47cea71be2 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 11 Dec 2012 09:42:18 +0100 Subject: [PATCH 2180/2270] apci: assign memory regions to ich9 lpc device Get rid of get_system_io() usage. Signed-off-by: Gerd Hoffmann --- hw/acpi_ich9.c | 6 ++++-- hw/acpi_ich9.h | 4 +++- hw/lpc_ich9.c | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c index 37a50e6d7b..d2f9808242 100644 --- a/hw/acpi_ich9.c +++ b/hw/acpi_ich9.c @@ -202,11 +202,13 @@ static void pm_powerdown_req(Notifier *n, void *opaque) acpi_pm1_evt_power_down(&pm->acpi_regs); } -void ich9_pm_init(ICH9LPCPMRegs *pm, qemu_irq sci_irq, qemu_irq cmos_s3) +void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, + qemu_irq sci_irq, qemu_irq cmos_s3) { memory_region_init(&pm->io, "ich9-pm", ICH9_PMIO_SIZE); memory_region_set_enabled(&pm->io, false); - memory_region_add_subregion(get_system_io(), 0, &pm->io); + memory_region_add_subregion(pci_address_space_io(lpc_pci), + 0, &pm->io); acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io); acpi_pm1_evt_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io); diff --git a/hw/acpi_ich9.h b/hw/acpi_ich9.h index bc221d3cbc..ecb82abc65 100644 --- a/hw/acpi_ich9.h +++ b/hw/acpi_ich9.h @@ -30,9 +30,11 @@ typedef struct ICH9LPCPMRegs { * PM1a_CNT_BLK = 2 in FADT so it is defined as uint16_t. */ ACPIREGS acpi_regs; + MemoryRegion io; MemoryRegion io_gpe; MemoryRegion io_smi; + uint32_t smi_en; uint32_t smi_sts; @@ -42,7 +44,7 @@ typedef struct ICH9LPCPMRegs { Notifier powerdown_notifier; } ICH9LPCPMRegs; -void ich9_pm_init(ICH9LPCPMRegs *pm, +void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, qemu_irq sci_irq, qemu_irq cmos_s3_resume); void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base); extern const VMStateDescription vmstate_ich9_pm; diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c index a068715c04..16843d76bc 100644 --- a/hw/lpc_ich9.c +++ b/hw/lpc_ich9.c @@ -336,7 +336,7 @@ void ich9_lpc_pm_init(PCIDevice *lpc_pci, qemu_irq cmos_s3) qemu_irq *sci_irq; sci_irq = qemu_allocate_irqs(ich9_set_sci, lpc, 1); - ich9_pm_init(&lpc->pm, sci_irq[0], cmos_s3); + ich9_pm_init(lpc_pci, &lpc->pm, sci_irq[0], cmos_s3); ich9_lpc_reset(&lpc->d.qdev); } From e8ba1ce92d8cbc4e77efcaf040077d3901098e5f Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 12 Dec 2012 15:43:35 +0100 Subject: [PATCH 2181/2270] switch debugcon to memory api Also some QOM glue while being at it. Signed-off-by: Gerd Hoffmann --- hw/debugcon.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/hw/debugcon.c b/hw/debugcon.c index 14f83f1962..e8a855e33a 100644 --- a/hw/debugcon.c +++ b/hw/debugcon.c @@ -29,20 +29,27 @@ #include "isa.h" #include "pc.h" +#define TYPE_ISA_DEBUGCON_DEVICE "isa-debugcon" +#define ISA_DEBUGCON_DEVICE(obj) \ + OBJECT_CHECK(ISADebugconState, (obj), TYPE_ISA_DEBUGCON_DEVICE) + //#define DEBUG_DEBUGCON typedef struct DebugconState { + MemoryRegion io; CharDriverState *chr; uint32_t readback; } DebugconState; typedef struct ISADebugconState { - ISADevice dev; + ISADevice parent_obj; + uint32_t iobase; DebugconState state; } ISADebugconState; -static void debugcon_ioport_write(void *opaque, uint32_t addr, uint32_t val) +static void debugcon_ioport_write(void *opaque, hwaddr addr, uint64_t val, + unsigned width) { DebugconState *s = opaque; unsigned char ch = val; @@ -55,7 +62,7 @@ static void debugcon_ioport_write(void *opaque, uint32_t addr, uint32_t val) } -static uint32_t debugcon_ioport_read(void *opaque, uint32_t addr) +static uint64_t debugcon_ioport_read(void *opaque, hwaddr addr, unsigned width) { DebugconState *s = opaque; @@ -66,6 +73,14 @@ static uint32_t debugcon_ioport_read(void *opaque, uint32_t addr) return s->readback; } +static const MemoryRegionOps debugcon_ops = { + .read = debugcon_ioport_read, + .write = debugcon_ioport_write, + .valid.min_access_size = 1, + .valid.max_access_size = 1, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + static void debugcon_init_core(DebugconState *s) { if (!s->chr) { @@ -78,12 +93,14 @@ static void debugcon_init_core(DebugconState *s) static int debugcon_isa_initfn(ISADevice *dev) { - ISADebugconState *isa = DO_UPCAST(ISADebugconState, dev, dev); + ISADebugconState *isa = ISA_DEBUGCON_DEVICE(dev); DebugconState *s = &isa->state; debugcon_init_core(s); - register_ioport_write(isa->iobase, 1, 1, debugcon_ioport_write, s); - register_ioport_read(isa->iobase, 1, 1, debugcon_ioport_read, s); + memory_region_init_io(&s->io, &debugcon_ops, s, + TYPE_ISA_DEBUGCON_DEVICE, 1); + memory_region_add_subregion(isa_address_space_io(dev), + isa->iobase, &s->io); return 0; } @@ -103,7 +120,7 @@ static void debugcon_isa_class_initfn(ObjectClass *klass, void *data) } static TypeInfo debugcon_isa_info = { - .name = "isa-debugcon", + .name = TYPE_ISA_DEBUGCON_DEVICE, .parent = TYPE_ISA_DEVICE, .instance_size = sizeof(ISADebugconState), .class_init = debugcon_isa_class_initfn, From bb355b1859dde19fbb4f856c6d0b8f46733142d7 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 12 Dec 2012 15:54:59 +0100 Subject: [PATCH 2182/2270] add isa-debug-exit device. When present it makes qemu exit on any write. Mapped to port 0x501 by default. Without this patch Anthony doesn't allow me to remove the bochs bios debug ports because his test suite uses this. Signed-off-by: Gerd Hoffmann --- hw/debugexit.c | 75 +++++++++++++++++++++++++++++++++++++++++++ hw/i386/Makefile.objs | 2 +- 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 hw/debugexit.c diff --git a/hw/debugexit.c b/hw/debugexit.c new file mode 100644 index 0000000000..90642eb37f --- /dev/null +++ b/hw/debugexit.c @@ -0,0 +1,75 @@ +/* + * debug exit port emulation + * + * 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 or + * (at your option) any later version. + */ + +#include "hw.h" +#include "isa.h" + +#define TYPE_ISA_DEBUG_EXIT_DEVICE "isa-debug-exit" +#define ISA_DEBUG_EXIT_DEVICE(obj) \ + OBJECT_CHECK(ISADebugExitState, (obj), TYPE_ISA_DEBUG_EXIT_DEVICE) + +typedef struct ISADebugExitState { + ISADevice parent_obj; + + uint32_t iobase; + uint32_t iosize; + MemoryRegion io; +} ISADebugExitState; + +static void debug_exit_write(void *opaque, hwaddr addr, uint64_t val, + unsigned width) +{ + exit((val << 1) | 1); +} + +static const MemoryRegionOps debug_exit_ops = { + .write = debug_exit_write, + .valid.min_access_size = 1, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static int debug_exit_initfn(ISADevice *dev) +{ + ISADebugExitState *isa = ISA_DEBUG_EXIT_DEVICE(dev); + + memory_region_init_io(&isa->io, &debug_exit_ops, isa, + TYPE_ISA_DEBUG_EXIT_DEVICE, isa->iosize); + memory_region_add_subregion(isa_address_space_io(dev), + isa->iobase, &isa->io); + return 0; +} + +static Property debug_exit_properties[] = { + DEFINE_PROP_HEX32("iobase", ISADebugExitState, iobase, 0x501), + DEFINE_PROP_HEX32("iosize", ISADebugExitState, iosize, 0x02), + DEFINE_PROP_END_OF_LIST(), +}; + +static void debug_exit_class_initfn(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = debug_exit_initfn; + dc->props = debug_exit_properties; +} + +static TypeInfo debug_exit_info = { + .name = TYPE_ISA_DEBUG_EXIT_DEVICE, + .parent = TYPE_ISA_DEVICE, + .instance_size = sizeof(ISADebugExitState), + .class_init = debug_exit_class_initfn, +}; + +static void debug_exit_register_types(void) +{ + type_register_static(&debug_exit_info); +} + +type_init(debug_exit_register_types) diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 257f3c1a91..2ba04db0a8 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -3,7 +3,7 @@ obj-y += apic_common.o apic.o kvmvapic.o obj-y += sga.o ioapic_common.o ioapic.o piix_pci.o obj-y += vmport.o obj-y += pci/pci-hotplug.o smbios.o wdt_ib700.o -obj-y += debugcon.o multiboot.o +obj-y += debugcon.o debugexit.o multiboot.o obj-y += pc_piix.o obj-y += pc_sysfw.o obj-y += lpc_ich9.o q35.o pc_q35.o From ee0cc5415e6edc043bd84e855f7d0bf85bd97547 Mon Sep 17 00:00:00 2001 From: Lucas Meneghel Rodrigues Date: Thu, 13 Dec 2012 12:48:53 -0200 Subject: [PATCH 2183/2270] hw: Add test device for unittests execution Add a test device which supports the kvmctl ioports, so one can run the KVM unittest suite. Intended Usage: qemu-system-x86_64 -nographic \ -device pc-testdev \ -device isa-debug-exit,iobase=0xf4,iosize=0x04 \ -kernel /path/to/kvm/unittests/msr.flat Where msr.flat is one of the KVM unittests, present on a separate repo, git://git.kernel.org/pub/scm/virt/kvm/kvm-unit-tests.git [ kraxel: more memory api + qom fixes ] CC: Paolo Bonzini Signed-off-by: Alexander Graf Signed-off-by: Marcelo Tosatti Signed-off-by: Lucas Meneghel Rodrigues Signed-off-by: Gerd Hoffmann --- hw/i386/Makefile.objs | 1 + hw/pc-testdev.c | 182 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 183 insertions(+) create mode 100644 hw/pc-testdev.c diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 2ba04db0a8..025803aa66 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -12,5 +12,6 @@ obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o obj-y += kvm/ obj-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o +obj-y += pc-testdev.o obj-y := $(addprefix ../,$(obj-y)) diff --git a/hw/pc-testdev.c b/hw/pc-testdev.c new file mode 100644 index 0000000000..620c86c92a --- /dev/null +++ b/hw/pc-testdev.c @@ -0,0 +1,182 @@ +/* + * QEMU x86 ISA testdev + * + * Copyright (c) 2012 Avi Kivity, Gerd Hoffmann, Marcelo Tosatti + * + * 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. + */ + +/* + * This device is used to test KVM features specific to the x86 port, such + * as emulation, power management, interrupt routing, among others. It's meant + * to be used like: + * + * qemu-system-x86_64 -device pc-testdev -serial stdio \ + * -device isa-debug-exit,iobase=0xf4,iosize=0x4 \ + * -kernel /home/lmr/Code/virt-test.git/kvm/unittests/msr.flat + * + * Where msr.flat is one of the KVM unittests, present on a separate repo, + * git://git.kernel.org/pub/scm/virt/kvm/kvm-unit-tests.git +*/ + +#include +#include "hw.h" +#include "qdev.h" +#include "isa.h" + +#define IOMEM_LEN 0x10000 + +typedef struct PCTestdev { + ISADevice parent_obj; + + MemoryRegion ioport; + MemoryRegion flush; + MemoryRegion irq; + MemoryRegion iomem; + uint32_t ioport_data; + char iomem_buf[IOMEM_LEN]; +} PCTestdev; + +#define TYPE_TESTDEV "pc-testdev" +#define TESTDEV(obj) \ + OBJECT_CHECK(struct PCTestdev, (obj), TYPE_TESTDEV) + +static void test_irq_line(void *opaque, hwaddr addr, uint64_t data, + unsigned len) +{ + struct PCTestdev *dev = opaque; + struct ISADevice *isa = ISA_DEVICE(dev); + + qemu_set_irq(isa_get_irq(isa, addr), !!data); +} + +static const MemoryRegionOps test_irq_ops = { + .write = test_irq_line, + .valid.min_access_size = 1, + .valid.max_access_size = 1, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void test_ioport_write(void *opaque, hwaddr addr, uint64_t data, + unsigned len) +{ + struct PCTestdev *dev = opaque; + dev->ioport_data = data; +} + +static uint64_t test_ioport_read(void *opaque, hwaddr addr, unsigned len) +{ + struct PCTestdev *dev = opaque; + return dev->ioport_data; +} + +static const MemoryRegionOps test_ioport_ops = { + .read = test_ioport_read, + .write = test_ioport_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void test_flush_page(void *opaque, hwaddr addr, uint64_t data, + unsigned len) +{ + hwaddr page = 4096; + void *a = cpu_physical_memory_map(data & ~0xffful, &page, 0); + + /* We might not be able to get the full page, only mprotect what we actually + have mapped */ + mprotect(a, page, PROT_NONE); + mprotect(a, page, PROT_READ|PROT_WRITE); + cpu_physical_memory_unmap(a, page, 0, 0); +} + +static const MemoryRegionOps test_flush_ops = { + .write = test_flush_page, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static uint64_t test_iomem_read(void *opaque, hwaddr addr, unsigned len) +{ + struct PCTestdev *dev = opaque; + uint64_t ret = 0; + memcpy(&ret, &dev->iomem_buf[addr], len); + ret = le64_to_cpu(ret); + + return ret; +} + +static void test_iomem_write(void *opaque, hwaddr addr, uint64_t val, + unsigned len) +{ + struct PCTestdev *dev = opaque; + val = cpu_to_le64(val); + memcpy(&dev->iomem_buf[addr], &val, len); + dev->iomem_buf[addr] = val; +} + +static const MemoryRegionOps test_iomem_ops = { + .read = test_iomem_read, + .write = test_iomem_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static int init_test_device(ISADevice *isa) +{ + struct PCTestdev *dev = TESTDEV(isa); + MemoryRegion *mem = isa_address_space(isa); + MemoryRegion *io = isa_address_space_io(isa); + + memory_region_init_io(&dev->ioport, &test_ioport_ops, dev, + "pc-testdev-ioport", 4); + memory_region_init_io(&dev->flush, &test_flush_ops, dev, + "pc-testdev-flush-page", 4); + memory_region_init_io(&dev->irq, &test_irq_ops, dev, + "pc-testdev-irq-line", 24); + memory_region_init_io(&dev->iomem, &test_iomem_ops, dev, + "pc-testdev-iomem", IOMEM_LEN); + + memory_region_add_subregion(io, 0xe0, &dev->ioport); + memory_region_add_subregion(io, 0xe4, &dev->flush); + memory_region_add_subregion(io, 0x2000, &dev->irq); + memory_region_add_subregion(mem, 0xff000000, &dev->iomem); + + return 0; +} + +static void testdev_class_init(ObjectClass *klass, void *data) +{ + ISADeviceClass *k = ISA_DEVICE_CLASS(klass); + + k->init = init_test_device; +} + +static TypeInfo testdev_info = { + .name = TYPE_TESTDEV, + .parent = TYPE_ISA_DEVICE, + .instance_size = sizeof(struct PCTestdev), + .class_init = testdev_class_init, +}; + +static void testdev_register_types(void) +{ + type_register_static(&testdev_info); +} + +type_init(testdev_register_types) From 9ee59f341f9d7a95b3a87b7cac3f74bcdda395fb Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 11 Dec 2012 09:59:55 +0100 Subject: [PATCH 2184/2270] pc: remove bochs bios debug ports Prehistoric leftover, zap it. We poweroff via acpi these days. And having a port (0x501,0x502) where any random guest write will make qemu exit -- with no way to turn it off -- is a bad joke anyway. Signed-off-by: Gerd Hoffmann --- hw/pc.c | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/hw/pc.c b/hw/pc.c index 71902e210b..4879e4f4fb 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -524,34 +524,6 @@ static void handle_a20_line_change(void *opaque, int irq, int level) cpu_x86_set_a20(cpu, level); } -/***********************************************************/ -/* Bochs BIOS debug ports */ - -static void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val) -{ - static const char shutdown_str[8] = "Shutdown"; - static int shutdown_index = 0; - - switch(addr) { - case 0x8900: - /* same as Bochs power off */ - if (val == shutdown_str[shutdown_index]) { - shutdown_index++; - if (shutdown_index == 8) { - shutdown_index = 0; - qemu_system_shutdown_request(); - } - } else { - shutdown_index = 0; - } - break; - - case 0x501: - case 0x502: - exit((val << 1) | 1); - } -} - int e820_add_entry(uint64_t address, uint64_t length, uint32_t type) { int index = le32_to_cpu(e820_table.count); @@ -569,14 +541,6 @@ int e820_add_entry(uint64_t address, uint64_t length, uint32_t type) return index; } -static const MemoryRegionPortio bochs_bios_portio_list[] = { - { 0x500, 1, 1, .write = bochs_bios_write, }, /* 0x500 */ - { 0x501, 1, 1, .write = bochs_bios_write, }, /* 0x501 */ - { 0x501, 2, 2, .write = bochs_bios_write, }, /* 0x501 */ - { 0x8900, 1, 1, .write = bochs_bios_write, }, /* 0x8900 */ - PORTIO_END_OF_LIST(), -}; - static void *bochs_bios_init(void) { void *fw_cfg; @@ -584,11 +548,6 @@ static void *bochs_bios_init(void) size_t smbios_len; uint64_t *numa_fw_cfg; int i, j; - PortioList *bochs_bios_port_list = g_new(PortioList, 1); - - portio_list_init(bochs_bios_port_list, bochs_bios_portio_list, - NULL, "bochs-bios"); - portio_list_add(bochs_bios_port_list, get_system_io(), 0x0); fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0); From e7b1d0ea950fc760371c9580ba6b34c912369a38 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 5 Dec 2012 15:28:05 +0100 Subject: [PATCH 2185/2270] pc_sysfw: Check for qemu_find_file() failure pc_fw_add_pflash_drv() ignores qemu_find_file() failure, and happily creates a drive without a medium. When pc_system_flash_init() asks for its size, bdrv_getlength() fails with -ENOMEDIUM, which isn't checked either. It fails relatively cleanly only because -ENOMEDIUM isn't a multiple of 4096: $ qemu-system-x86_64 -S -vnc :0 -bios nonexistant qemu: PC system firmware (pflash) must be a multiple of 0x1000 [Exit 1 ] Fix by handling the qemu_find_file() failure. Signed-off-by: Markus Armbruster Signed-off-by: Stefan Hajnoczi --- hw/pc_sysfw.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/pc_sysfw.c b/hw/pc_sysfw.c index 87e1fa961b..7567593a63 100644 --- a/hw/pc_sysfw.c +++ b/hw/pc_sysfw.c @@ -84,6 +84,10 @@ static void pc_fw_add_pflash_drv(void) bios_name = BIOS_FILENAME; } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + if (!filename) { + error_report("Can't open BIOS image %s", bios_name); + exit(1); + } opts = drive_add(IF_PFLASH, -1, filename, "readonly=on"); From e2af7a4dc8d218c5fb5b41dd1d008fa111d0636e Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 20 Dec 2012 07:50:41 +0100 Subject: [PATCH 2186/2270] pseries: Remove unneeded include statement (fixes MinGW builds) sys/mman.h is not needed (tested on Linux) and unavailable for MinGW, so remove it. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- hw/spapr_nvram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/spapr_nvram.c b/hw/spapr_nvram.c index f20f6b4fdd..680cdba928 100644 --- a/hw/spapr_nvram.c +++ b/hw/spapr_nvram.c @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include + #include #include "sysemu/device_tree.h" From c242222c978d2c09411f2560915708c364ca2ce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B3=E9=9F=8B=E4=BB=BB=20=28Wei-Ren=20Chen=29?= Date: Thu, 20 Dec 2012 16:41:34 +0800 Subject: [PATCH 2187/2270] Remove --sparc_cpu option from the configure list commit 9b9c37c36439ee0452632253dac7a31897f27f70 always assume sparcv9, the others are no longer supported. Remove --sparc_cpu option from the configure list. Signed-off-by: Chen Wei-Ren Signed-off-by: Stefan Hajnoczi --- configure | 1 - 1 file changed, 1 deletion(-) diff --git a/configure b/configure index 9538041d05..db11e511f0 100755 --- a/configure +++ b/configure @@ -1096,7 +1096,6 @@ echo " --fmod-inc path to FMOD includes" echo " --oss-lib path to OSS library" echo " --enable-uname-release=R Return R for uname -r in usermode emulation" echo " --cpu=CPU Build for host CPU [$cpu]" -echo " --sparc_cpu=V Build qemu for Sparc architecture v7, v8, v8plus, v8plusa, v9" echo " --disable-uuid disable uuid support" echo " --enable-uuid enable uuid support" echo " --disable-vde disable support for vde network" From 715857cbbabc8740792b608f9bc4cd9fad6ecb1d Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 22 Dec 2012 13:59:22 +0100 Subject: [PATCH 2188/2270] hw/mcf5206: Reduce size of lookup table This typically reduces the size from 512 bytes to 128 bytes. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- hw/mcf5206.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/mcf5206.c b/hw/mcf5206.c index fe7a48864f..d8c0059ed6 100644 --- a/hw/mcf5206.c +++ b/hw/mcf5206.c @@ -359,7 +359,7 @@ static void m5206_mbar_write(m5206_mbar_state *s, uint32_t offset, /* Internal peripherals use a variety of register widths. This lookup table allows a single routine to handle all of them. */ -static const int m5206_mbar_width[] = +static const uint8_t m5206_mbar_width[] = { /* 000-040 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, /* 040-080 */ 1, 2, 2, 2, 4, 1, 2, 4, 1, 2, 4, 2, 2, 4, 2, 2, From 586b0bef84c202bb2256a35eb71bfd6670262bd7 Mon Sep 17 00:00:00 2001 From: John Spencer Date: Wed, 26 Dec 2012 00:49:49 +0100 Subject: [PATCH 2189/2270] linux-user/syscall.c: remove forward declarations instead use the correct headers that define these functions. Requested-by: Stefan Weil Signed-off-by: John Spencer Reviewed-by: Amos Kong Reviewed-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- linux-user/syscall.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index e99adab492..3167a87549 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -36,6 +36,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -581,11 +584,6 @@ _syscall4(int, sys_prlimit64, pid_t, pid, int, resource, struct host_rlimit64 *, old_limit) #endif -extern int personality(int); -extern int flock(int, int); -extern int setfsuid(int); -extern int setfsgid(int); - /* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */ #ifdef TARGET_ARM static inline int regpairs_aligned(void *cpu_env) { From bfb82a28752d29291adf932c3a9941e8383203af Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 19 Dec 2012 14:07:16 +0100 Subject: [PATCH 2190/2270] spice: drop incorrect vm_change_state_handler() opaque The spice_server pointer is a global variable and vm_change_state_handler() therefore does not use its opaque parameter. The vm change state handler is added with a pointer to the spice_server pointer. This is useless and we probably would not want 2 levels of pointers. Signed-off-by: Stefan Hajnoczi Reviewed-by: Uri Lublin --- ui/spice-core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ui/spice-core.c b/ui/spice-core.c index 3e44779107..d83de2a46e 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -709,7 +709,7 @@ void qemu_spice_init(void) qemu_spice_input_init(); qemu_spice_audio_init(); - qemu_add_vm_change_state_handler(vm_change_state_handler, &spice_server); + qemu_add_vm_change_state_handler(vm_change_state_handler, NULL); g_free(x509_key_file); g_free(x509_cert_file); @@ -736,8 +736,7 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin) */ spice_server = spice_server_new(); spice_server_init(spice_server, &core_interface); - qemu_add_vm_change_state_handler(vm_change_state_handler, - &spice_server); + qemu_add_vm_change_state_handler(vm_change_state_handler, NULL); } return spice_server_add_interface(spice_server, sin); From 17ed229379d971ae117245b353324115a62b0014 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 31 Dec 2012 10:09:03 -0800 Subject: [PATCH 2191/2270] softfloat: Fix uint64_to_float64 The interface to normalizeRoundAndPackFloat64 requires that the high bit be clear. Perform one shift-right-and-jam if needed. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- fpu/softfloat.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 0cfa6b4831..20b05d4392 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1271,11 +1271,18 @@ float64 int64_to_float64( int64 a STATUS_PARAM ) } -float64 uint64_to_float64( uint64 a STATUS_PARAM ) +float64 uint64_to_float64(uint64 a STATUS_PARAM) { - if ( a == 0 ) return float64_zero; - return normalizeRoundAndPackFloat64( 0, 0x43C, a STATUS_VAR ); + int exp = 0x43C; + if (a == 0) { + return float64_zero; + } + if ((int64_t)a < 0) { + shift64RightJamming(a, 1, &a); + exp += 1; + } + return normalizeRoundAndPackFloat64(0, exp, a STATUS_VAR); } /*---------------------------------------------------------------------------- From 1e397eadf1cf54920c45a2fdc204b1ade1b72d38 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 31 Dec 2012 10:09:04 -0800 Subject: [PATCH 2192/2270] softfloat: Implement uint64_to_float128 Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- fpu/softfloat.c | 8 ++++++++ include/fpu/softfloat.h | 3 +++ 2 files changed, 11 insertions(+) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 20b05d4392..ac3d150015 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1339,6 +1339,14 @@ float128 int64_to_float128( int64 a STATUS_PARAM ) } +float128 uint64_to_float128(uint64 a STATUS_PARAM) +{ + if (a == 0) { + return float128_zero; + } + return normalizeRoundAndPackFloat128(0, 0x406E, a, 0 STATUS_VAR); +} + /*---------------------------------------------------------------------------- | Returns the result of converting the single-precision floating-point value | `a' to the 32-bit two's complement integer format. The conversion is diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 0946f0739d..f3927e2419 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -237,6 +237,7 @@ float64 int64_to_float64( int64 STATUS_PARAM ); float64 uint64_to_float64( uint64 STATUS_PARAM ); floatx80 int64_to_floatx80( int64 STATUS_PARAM ); float128 int64_to_float128( int64 STATUS_PARAM ); +float128 uint64_to_float128( uint64 STATUS_PARAM ); /*---------------------------------------------------------------------------- | Software half-precision conversion routines. @@ -630,6 +631,8 @@ INLINE int float128_is_any_nan(float128 a) ((a.low != 0) || ((a.high & 0xffffffffffffLL) != 0)); } +#define float128_zero make_float128(0, 0) + /*---------------------------------------------------------------------------- | The pattern for a default generated quadruple-precision NaN. *----------------------------------------------------------------------------*/ From 549db5c32bb025501e2eeb23d2e5cc669061eb71 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 5 Jan 2013 09:33:43 +0100 Subject: [PATCH 2193/2270] hw/i386: Fix broken build for non POSIX hosts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pc-testdev.c cannot be compiled with MinGW (and other non POSIX hosts): CC i386-softmmu/hw/i386/../pc-testdev.o qemu/hw/i386/../pc-testdev.c:38:22: warning: sys/mman.h: file not found qemu/hw/i386/../pc-testdev.c: In function ‘test_flush_page’: qemu/hw/i386/../pc-testdev.c:103: warning: implicit declaration of function ‘mprotect’ ... Signed-off-by: Stefan Weil Signed-off-by: Blue Swirl --- hw/pc-testdev.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/pc-testdev.c b/hw/pc-testdev.c index 620c86c92a..192848998c 100644 --- a/hw/pc-testdev.c +++ b/hw/pc-testdev.c @@ -35,7 +35,10 @@ * git://git.kernel.org/pub/scm/virt/kvm/kvm-unit-tests.git */ +#include "config-host.h" +#if defined(CONFIG_POSIX) #include +#endif #include "hw.h" #include "qdev.h" #include "isa.h" @@ -100,8 +103,10 @@ static void test_flush_page(void *opaque, hwaddr addr, uint64_t data, /* We might not be able to get the full page, only mprotect what we actually have mapped */ +#if defined(CONFIG_POSIX) mprotect(a, page, PROT_NONE); mprotect(a, page, PROT_READ|PROT_WRITE); +#endif cpu_physical_memory_unmap(a, page, 0, 0); } From 1d728c394652d40a9065668606d62f28bc544949 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Tue, 1 May 2012 18:45:39 +0000 Subject: [PATCH 2194/2270] tests: add gcov support Add support for compiling for GCOV test coverage, enabled with '--enable-gcov' during configure. Test coverage will be reported after each test. Signed-off-by: Blue Swirl --- Makefile.objs | 2 ++ configure | 20 +++++++++++++++++++- tests/Makefile | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/Makefile.objs b/Makefile.objs index 3a3a4028c5..a3eab4b410 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -31,6 +31,8 @@ oslib-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o # coroutines coroutine-obj-y = qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o coroutine-obj-y += qemu-coroutine-sleep.o + +# If you change this logic, please also check tests/Makefile ifeq ($(CONFIG_UCONTEXT_COROUTINE),y) coroutine-obj-$(CONFIG_POSIX) += coroutine-ucontext.o else diff --git a/configure b/configure index 837a84aff0..fe18ed2b25 100755 --- a/configure +++ b/configure @@ -176,6 +176,8 @@ strip_opt="yes" tcg_interpreter="no" bigendian="no" mingw32="no" +gcov="no" +gcov_tool="gcov" EXESUF="" prefix="/usr/local" mandir="\${prefix}/share/man" @@ -600,6 +602,8 @@ for opt do ;; --python=*) python="$optarg" ;; + --gcov=*) gcov_tool="$optarg" + ;; --smbd=*) smbd="$optarg" ;; --extra-cflags=*) @@ -620,6 +624,8 @@ for opt do ;; --enable-gprof) gprof="yes" ;; + --enable-gcov) gcov="yes" + ;; --static) static="yes" LDFLAGS="-static $LDFLAGS" @@ -1134,6 +1140,8 @@ echo " --with-coroutine=BACKEND coroutine backend. Supported options:" echo " gthread, ucontext, sigaltstack, windows" echo " --enable-glusterfs enable GlusterFS backend" echo " --disable-glusterfs disable GlusterFS backend" +echo " --enable-gcov enable test coverage analysis with gcov" +echo " --gcov=GCOV use specified gcov [$gcov_tool]" echo "" echo "NOTE: The object files are built at the place where configure is launched" exit 1 @@ -3120,10 +3128,14 @@ fi # End of CC checks # After here, no more $cc or $ld runs -if test "$debug" = "no" ; then +if test "$gcov" = "yes" ; then + CFLAGS="-fprofile-arcs -ftest-coverage -g $CFLAGS" + LDFLAGS="-fprofile-arcs -ftest-coverage $LDFLAGS" +elif test "$debug" = "no" ; then CFLAGS="-O2 -D_FORTIFY_SOURCE=2 $CFLAGS" fi + # Disable zero malloc errors for official releases unless explicitly told to # enable/disable if test -z "$zero_malloc" ; then @@ -3305,6 +3317,8 @@ echo "seccomp support $seccomp" echo "coroutine backend $coroutine_backend" echo "GlusterFS support $glusterfs" echo "virtio-blk-data-plane $virtio_blk_data_plane" +echo "gcov $gcov_tool" +echo "gcov enabled $gcov" if test "$sdl_too_old" = "yes"; then echo "-> Your SDL version is too old - please upgrade to have SDL support" @@ -3738,6 +3752,10 @@ echo "EXESUF=$EXESUF" >> $config_host_mak echo "LIBS_QGA+=$libs_qga" >> $config_host_mak echo "POD2MAN=$POD2MAN" >> $config_host_mak echo "TRANSLATE_OPT_CFLAGS=$TRANSLATE_OPT_CFLAGS" >> $config_host_mak +if test "$gcov" = "yes" ; then + echo "CONFIG_GCOV=y" >> $config_host_mak + echo "GCOV=$gcov_tool" >> $config_host_mak +fi # generate list of library paths for linker script diff --git a/tests/Makefile b/tests/Makefile index b60f0fb8f0..b09a3437cd 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,33 +1,65 @@ export SRC_PATH check-unit-y = tests/check-qdict$(EXESUF) +gcov-files-check-qdict-y = qdict.c check-unit-y += tests/check-qfloat$(EXESUF) +gcov-files-check-qfloat-y = qfloat.c check-unit-y += tests/check-qint$(EXESUF) +gcov-files-check-qint-y = qint.c check-unit-y += tests/check-qstring$(EXESUF) +gcov-files-check-qstring-y = qstring.c check-unit-y += tests/check-qlist$(EXESUF) +gcov-files-check-qlist-y = qlist.c check-unit-y += tests/check-qjson$(EXESUF) +gcov-files-check-qjson-y = qjson.c check-unit-y += tests/test-qmp-output-visitor$(EXESUF) +gcov-files-test-qmp-output-visitor-y = qapi/qmp-output-visitor.c check-unit-y += tests/test-qmp-input-visitor$(EXESUF) +gcov-files-test-qmp-input-visitor-y = qapi/qmp-input-visitor.c check-unit-y += tests/test-qmp-input-strict$(EXESUF) check-unit-y += tests/test-qmp-commands$(EXESUF) +gcov-files-test-qmp-commands-y = qapi/qmp-dispatch.c check-unit-y += tests/test-string-input-visitor$(EXESUF) +gcov-files-test-string-input-visitor-y = qapi/string-input-visitor.c check-unit-y += tests/test-string-output-visitor$(EXESUF) +gcov-files-test-string-output-visitor-y = qapi/string-output-visitor.c check-unit-y += tests/test-coroutine$(EXESUF) +ifeq ($(CONFIG_WIN32),y) +gcov-files-test-coroutine-y = coroutine-win32.c +else +ifeq ($(CONFIG_UCONTEXT_COROUTINE),y) +gcov-files-test-coroutine-y = coroutine-ucontext.c +else +ifeq ($(CONFIG_SIGALTSTACK_COROUTINE),y) +gcov-files-test-coroutine-y = coroutine-sigaltstack.c +else +gcov-files-test-coroutine-y = coroutine-gthread.c +endif +endif +endif check-unit-y += tests/test-visitor-serialization$(EXESUF) check-unit-y += tests/test-iov$(EXESUF) +gcov-files-test-iov-y = iov.c check-unit-y += tests/test-aio$(EXESUF) +gcov-files-test-aio-$(CONFIG_WIN32) = aio-win32.c +gcov-files-test-aio-$(CONFIG_POSIX) = aio-posix.c check-unit-y += tests/test-thread-pool$(EXESUF) +gcov-files-test-thread-pool-y = thread-pool.c check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh # All QTests for now are POSIX-only, but the dependencies are # really in libqtest, not in the testcases themselves. check-qtest-i386-y = tests/fdc-test$(EXESUF) +gcov-files-i386-y = hw/fdc.c check-qtest-i386-y += tests/hd-geo-test$(EXESUF) +gcov-files-i386-y += hw/hd-geometry.c check-qtest-i386-y += tests/rtc-test$(EXESUF) check-qtest-x86_64-y = $(check-qtest-i386-y) +gcov-files-i386-y += i386-softmmu/hw/mc146818rtc.c check-qtest-sparc-y = tests/m48t59-test$(EXESUF) check-qtest-sparc64-y = tests/m48t59-test$(EXESUF) +gcov-files-sparc-y += hw/m48t59.c GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h tests/test-qmp-commands.h @@ -108,17 +140,28 @@ check-help: SPEED = quick GTESTER_OPTIONS = -k $(if $(V),--verbose,-q) +GCOV_OPTIONS = -n $(if $(V),-f,) # gtester tests, possibly with verbose output .PHONY: $(patsubst %, check-qtest-%, $(QTEST_TARGETS)) $(patsubst %, check-qtest-%, $(QTEST_TARGETS)): check-qtest-%: $(check-qtest-y) + $(if $(CONFIG_GCOV),@rm -f *.gcda */*.gcda */*/*.gcda */*/*/*.gcda,) $(call quiet-command,QTEST_QEMU_BINARY=$*-softmmu/qemu-system-$* \ gtester $(GTESTER_OPTIONS) -m=$(SPEED) $(check-qtest-$*-y),"GTESTER $@") + $(if $(CONFIG_GCOV),@for f in $(gcov-files-$*-y); do \ + echo Gcov report for $$f:;\ + $(GCOV) $(GCOV_OPTIONS) $$f -o `dirname $$f`; \ + done,) .PHONY: $(patsubst %, check-%, $(check-unit-y)) $(patsubst %, check-%, $(check-unit-y)): check-%: % + $(if $(CONFIG_GCOV),@rm -f *.gcda */*.gcda */*/*.gcda */*/*/*.gcda,) $(call quiet-command,gtester $(GTESTER_OPTIONS) -m=$(SPEED) $*,"GTESTER $*") + $(if $(CONFIG_GCOV),@for f in $(gcov-files-$(subst tests/,,$*)-y); do \ + echo Gcov report for $$f:;\ + $(GCOV) $(GCOV_OPTIONS) $$f -o `dirname $$f`; \ + done,) # gtester tests with XML output From 9807caccd605d09a72495637959568d690e10175 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sat, 14 Apr 2012 20:39:14 +0000 Subject: [PATCH 2195/2270] virtio-pci: replace byte swap hack Remove byte swaps by declaring the config space as native endian. Signed-off-by: Blue Swirl --- exec.c | 18 ------------------ hw/virtio-pci.c | 17 +---------------- 2 files changed, 1 insertion(+), 34 deletions(-) diff --git a/exec.c b/exec.c index a6923addd4..140eb5668f 100644 --- a/exec.c +++ b/exec.c @@ -2587,24 +2587,6 @@ int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr, } #endif -#if !defined(CONFIG_USER_ONLY) - -/* - * A helper function for the _utterly broken_ virtio device model to find out if - * it's running on a big endian machine. Don't do this at home kids! - */ -bool virtio_is_big_endian(void); -bool virtio_is_big_endian(void) -{ -#if defined(TARGET_WORDS_BIGENDIAN) - return true; -#else - return false; -#endif -} - -#endif - #ifndef CONFIG_USER_ONLY bool cpu_physical_memory_is_io(hwaddr phys_addr) { diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index c7f0c4d4ed..e714bcac72 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -92,9 +92,6 @@ */ #define wmb() do { } while (0) -/* HACK for virtio to determine if it's running a big endian guest */ -bool virtio_is_big_endian(void); - /* virtio device */ /* DeviceState to VirtIOPCIProxy. For use off data-path. TODO: use QOM. */ static inline VirtIOPCIProxy *to_virtio_pci_proxy(DeviceState *d) @@ -403,15 +400,9 @@ static uint64_t virtio_pci_config_read(void *opaque, hwaddr addr, break; case 2: val = virtio_config_readw(proxy->vdev, addr); - if (virtio_is_big_endian()) { - val = bswap16(val); - } break; case 4: val = virtio_config_readl(proxy->vdev, addr); - if (virtio_is_big_endian()) { - val = bswap32(val); - } break; } return val; @@ -436,15 +427,9 @@ static void virtio_pci_config_write(void *opaque, hwaddr addr, virtio_config_writeb(proxy->vdev, addr, val); break; case 2: - if (virtio_is_big_endian()) { - val = bswap16(val); - } virtio_config_writew(proxy->vdev, addr, val); break; case 4: - if (virtio_is_big_endian()) { - val = bswap32(val); - } virtio_config_writel(proxy->vdev, addr, val); break; } @@ -457,7 +442,7 @@ static const MemoryRegionOps virtio_pci_config_ops = { .min_access_size = 1, .max_access_size = 4, }, - .endianness = DEVICE_LITTLE_ENDIAN, + .endianness = DEVICE_NATIVE_ENDIAN, }; static void virtio_write_config(PCIDevice *pci_dev, uint32_t address, From 8e4a424b305e29dc0e454f52df3b35577f342975 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 6 Jan 2013 18:30:17 +0000 Subject: [PATCH 2196/2270] Revert "virtio-pci: replace byte swap hack" This reverts commit 9807caccd605d09a72495637959568d690e10175. Signed-off-by: Blue Swirl --- exec.c | 18 ++++++++++++++++++ hw/virtio-pci.c | 17 ++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/exec.c b/exec.c index 140eb5668f..a6923addd4 100644 --- a/exec.c +++ b/exec.c @@ -2587,6 +2587,24 @@ int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr, } #endif +#if !defined(CONFIG_USER_ONLY) + +/* + * A helper function for the _utterly broken_ virtio device model to find out if + * it's running on a big endian machine. Don't do this at home kids! + */ +bool virtio_is_big_endian(void); +bool virtio_is_big_endian(void) +{ +#if defined(TARGET_WORDS_BIGENDIAN) + return true; +#else + return false; +#endif +} + +#endif + #ifndef CONFIG_USER_ONLY bool cpu_physical_memory_is_io(hwaddr phys_addr) { diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index e714bcac72..c7f0c4d4ed 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -92,6 +92,9 @@ */ #define wmb() do { } while (0) +/* HACK for virtio to determine if it's running a big endian guest */ +bool virtio_is_big_endian(void); + /* virtio device */ /* DeviceState to VirtIOPCIProxy. For use off data-path. TODO: use QOM. */ static inline VirtIOPCIProxy *to_virtio_pci_proxy(DeviceState *d) @@ -400,9 +403,15 @@ static uint64_t virtio_pci_config_read(void *opaque, hwaddr addr, break; case 2: val = virtio_config_readw(proxy->vdev, addr); + if (virtio_is_big_endian()) { + val = bswap16(val); + } break; case 4: val = virtio_config_readl(proxy->vdev, addr); + if (virtio_is_big_endian()) { + val = bswap32(val); + } break; } return val; @@ -427,9 +436,15 @@ static void virtio_pci_config_write(void *opaque, hwaddr addr, virtio_config_writeb(proxy->vdev, addr, val); break; case 2: + if (virtio_is_big_endian()) { + val = bswap16(val); + } virtio_config_writew(proxy->vdev, addr, val); break; case 4: + if (virtio_is_big_endian()) { + val = bswap32(val); + } virtio_config_writel(proxy->vdev, addr, val); break; } @@ -442,7 +457,7 @@ static const MemoryRegionOps virtio_pci_config_ops = { .min_access_size = 1, .max_access_size = 4, }, - .endianness = DEVICE_NATIVE_ENDIAN, + .endianness = DEVICE_LITTLE_ENDIAN, }; static void virtio_write_config(PCIDevice *pci_dev, uint32_t address, From 2c0331f4f7d241995452b99afaf0aab00493334a Mon Sep 17 00:00:00 2001 From: Michael Contreras Date: Wed, 5 Dec 2012 13:31:30 -0500 Subject: [PATCH 2197/2270] e1000: Discard oversized packets based on SBP|LPE Discard packets longer than 16384 when !SBP to match the hardware behavior. Signed-off-by: Michael Contreras Signed-off-by: Stefan Hajnoczi --- hw/e1000.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hw/e1000.c b/hw/e1000.c index 92fb00a89f..8fd165456a 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -61,6 +61,8 @@ static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL); /* this is the size past which hardware will drop packets when setting LPE=0 */ #define MAXIMUM_ETHERNET_VLAN_SIZE 1522 +/* this is the size past which hardware will drop packets when setting LPE=1 */ +#define MAXIMUM_ETHERNET_LPE_SIZE 16384 /* * HW models: @@ -809,8 +811,9 @@ e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size) } /* Discard oversized packets if !LPE and !SBP. */ - if (size > MAXIMUM_ETHERNET_VLAN_SIZE - && !(s->mac_reg[RCTL] & E1000_RCTL_LPE) + if ((size > MAXIMUM_ETHERNET_LPE_SIZE || + (size > MAXIMUM_ETHERNET_VLAN_SIZE + && !(s->mac_reg[RCTL] & E1000_RCTL_LPE))) && !(s->mac_reg[RCTL] & E1000_RCTL_SBP)) { return size; } From f30dbae63a46f23116715dff8d130c7d01ff02be Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Tue, 11 Dec 2012 22:20:15 +0800 Subject: [PATCH 2198/2270] net: clean up network at qemu process termination We don't clean up network if fails to parse "-device" parameters without calling net_cleanup(). I touch a problem, the tap device which is created by qemu-ifup script could not be removed by qemu-ifdown script. Some similar problems also exist in vl.c In this patch, if network initialization successes, a cleanup function will be registered to be called at qemu process termination. Signed-off-by: Amos Kong Acked-by: Michael S. Tsirkin Signed-off-by: Stefan Hajnoczi --- vl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vl.c b/vl.c index f056c95807..79e5122393 100644 --- a/vl.c +++ b/vl.c @@ -3762,6 +3762,9 @@ int main(int argc, char **argv, char **envp) } configure_icount(icount_option); + /* clean up network at qemu process termination */ + atexit(&net_cleanup); + if (net_init_clients() < 0) { exit(1); } @@ -4014,7 +4017,6 @@ int main(int argc, char **argv, char **envp) main_loop(); bdrv_close_all(); pause_all_vcpus(); - net_cleanup(); res_free(); return 0; From 84dd2120247a7d25ff1bb337de21c0e76816ad2d Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Fri, 28 Dec 2012 17:29:10 +0800 Subject: [PATCH 2199/2270] e1000: no need auto-negotiation if link was down Commit b9d03e352cb6b31a66545763f6a1e20c9abf0c2c added link auto-negotiation emulation, it would always set link up by callback function. Problem exists if original link status was down, link status should not be changed in auto-negotiation. Signed-off-by: Jason Wang Signed-off-by: Amos Kong Signed-off-by: Stefan Hajnoczi --- hw/e1000.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/e1000.c b/hw/e1000.c index 8fd165456a..0f177ff844 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -166,6 +166,11 @@ static void set_phy_ctrl(E1000State *s, int index, uint16_t val) { if ((val & MII_CR_AUTO_NEG_EN) && (val & MII_CR_RESTART_AUTO_NEG)) { + /* no need auto-negotiation if link was down */ + if (s->nic->nc.link_down) { + s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE; + return; + } s->nic->nc.link_down = true; e1000_link_down(s); s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE; From 83f58e570f21c3e7227e7fbef1fc0e18b5ed7ea9 Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Fri, 28 Dec 2012 17:29:11 +0800 Subject: [PATCH 2200/2270] rtl8139: preserve link state across device reset A device reset does not affect the link state, only set_link does. Signed-off-by: Amos Kong Signed-off-by: Stefan Hajnoczi --- hw/rtl8139.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/rtl8139.c b/hw/rtl8139.c index c59ec6b6df..3e080621f6 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -1258,7 +1258,8 @@ static void rtl8139_reset(DeviceState *d) s->BasicModeStatus = 0x7809; //s->BasicModeStatus |= 0x0040; /* UTP medium */ s->BasicModeStatus |= 0x0020; /* autonegotiation completed */ - s->BasicModeStatus |= 0x0004; /* link is up */ + /* preserve link state */ + s->BasicModeStatus |= s->nic->nc.link_down ? 0 : 0x04; s->NWayAdvert = 0x05e1; /* all modes, full duplex */ s->NWayLPAR = 0x05e1; /* all modes, full duplex */ From f881c8d36b5c524348bc337b46baf34636079cf6 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:22 +0100 Subject: [PATCH 2201/2270] ehci: Add a ehci_writeback_async_complete_packet helper function Also drop the warning printf, which was there mainly because this was an untested code path (as the previous bug fixes to it show), but that no longer is the case now :) Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 7536837fb2..218b1d7efe 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -438,6 +438,22 @@ static inline bool ehci_periodic_enabled(EHCIState *s) return ehci_enabled(s) && (s->usbcmd & USBCMD_PSE); } +/* Finish executing and writeback a packet outside of the regular + fetchqh -> fetchqtd -> execute -> writeback cycle */ +static void ehci_writeback_async_complete_packet(EHCIPacket *p) +{ + EHCIQueue *q = p->queue; + int state; + + state = ehci_get_state(q->ehci, q->async); + ehci_state_executing(q); + ehci_state_writeback(q); /* Frees the packet! */ + if (!(q->qh.token & QTD_TOKEN_HALT)) { + ehci_state_advqueue(q); + } + ehci_set_state(q->ehci, q->async, state); +} + /* packet management */ static EHCIPacket *ehci_alloc_packet(EHCIQueue *q) @@ -455,17 +471,7 @@ static EHCIPacket *ehci_alloc_packet(EHCIQueue *q) static void ehci_free_packet(EHCIPacket *p) { if (p->async == EHCI_ASYNC_FINISHED) { - EHCIQueue *q = p->queue; - int state = ehci_get_state(q->ehci, q->async); - /* This is a normal, but rare condition (cancel racing completion) */ - fprintf(stderr, "EHCI: Warning packet completed but not processed\n"); - ehci_state_executing(q); - ehci_state_writeback(q); - if (!(q->qh.token & QTD_TOKEN_HALT)) { - ehci_state_advqueue(q); - } - ehci_set_state(q->ehci, q->async, state); - /* state_writeback recurses into us with async == EHCI_ASYNC_NONE!! */ + ehci_writeback_async_complete_packet(p); return; } trace_usb_ehci_packet_action(p->queue, p, "free"); From c643263409b42a31fd9b1458cd5158280b9c62e1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:23 +0100 Subject: [PATCH 2202/2270] ehci: Add ehci_verify_qh and ehci_verify_qtd helper functions Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 51 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 218b1d7efe..0d315971a9 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -438,6 +438,36 @@ static inline bool ehci_periodic_enabled(EHCIState *s) return ehci_enabled(s) && (s->usbcmd & USBCMD_PSE); } +static bool ehci_verify_qh(EHCIQueue *q, EHCIqh *qh) +{ + uint32_t devaddr = get_field(qh->epchar, QH_EPCHAR_DEVADDR); + uint32_t endp = get_field(qh->epchar, QH_EPCHAR_EP); + if ((devaddr != get_field(q->qh.epchar, QH_EPCHAR_DEVADDR)) || + (endp != get_field(q->qh.epchar, QH_EPCHAR_EP)) || + (qh->current_qtd != q->qh.current_qtd) || + (q->async && qh->next_qtd != q->qh.next_qtd) || + (memcmp(&qh->altnext_qtd, &q->qh.altnext_qtd, + 7 * sizeof(uint32_t)) != 0) || + (q->dev != NULL && q->dev->addr != devaddr)) { + return false; + } else { + return true; + } +} + +static bool ehci_verify_qtd(EHCIPacket *p, EHCIqtd *qtd) +{ + if (p->qtdaddr != p->queue->qtdaddr || + (p->queue->async && !NLPTR_TBIT(p->qtd.next) && + (p->qtd.next != qtd->next)) || + (!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd->altnext)) || + p->qtd.bufptr[0] != qtd->bufptr[0]) { + return false; + } else { + return true; + } +} + /* Finish executing and writeback a packet outside of the regular fetchqh -> fetchqtd -> execute -> writeback cycle */ static void ehci_writeback_async_complete_packet(EHCIPacket *p) @@ -1557,8 +1587,8 @@ out: static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) { + uint32_t entry; EHCIPacket *p; - uint32_t entry, devaddr, endp; EHCIQueue *q; EHCIqh qh; @@ -1588,15 +1618,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) * The overlay area of the qh should never be changed by the guest, * except when idle, in which case the reset is a nop. */ - devaddr = get_field(qh.epchar, QH_EPCHAR_DEVADDR); - endp = get_field(qh.epchar, QH_EPCHAR_EP); - if ((devaddr != get_field(q->qh.epchar, QH_EPCHAR_DEVADDR)) || - (endp != get_field(q->qh.epchar, QH_EPCHAR_EP)) || - (qh.current_qtd != q->qh.current_qtd) || - (q->async && qh.next_qtd != q->qh.next_qtd) || - (memcmp(&qh.altnext_qtd, &q->qh.altnext_qtd, - 7 * sizeof(uint32_t)) != 0) || - (q->dev != NULL && q->dev->addr != devaddr)) { + if (!ehci_verify_qh(q, &qh)) { if (ehci_reset_queue(q) > 0) { ehci_trace_guest_bug(ehci, "guest updated active QH"); } @@ -1610,7 +1632,8 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) } if (q->dev == NULL) { - q->dev = ehci_find_device(q->ehci, devaddr); + q->dev = ehci_find_device(q->ehci, + get_field(q->qh.epchar, QH_EPCHAR_DEVADDR)); } if (p && p->async == EHCI_ASYNC_FINISHED) { @@ -1768,11 +1791,7 @@ static int ehci_state_fetchqtd(EHCIQueue *q) p = QTAILQ_FIRST(&q->packets); if (p != NULL) { - if (p->qtdaddr != q->qtdaddr || - (q->async && !NLPTR_TBIT(p->qtd.next) && - (p->qtd.next != qtd.next)) || - (!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd.altnext)) || - p->qtd.bufptr[0] != qtd.bufptr[0]) { + if (!ehci_verify_qtd(p, &qtd)) { ehci_cancel_queue(q); ehci_trace_guest_bug(q->ehci, "guest updated active QH or qTD"); p = NULL; From d066c57b1c97a1967c949aba643bba35329b32ee Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:24 +0100 Subject: [PATCH 2203/2270] ehci: Verify guest does not change the token of inflight qtd-s This is not allowed, except for clearing active on cancellation, so don't warn when the new token does not have its active bit set. This unifies the cancellation path for modified qtd-s, and prepares ehci_verify_qtd to be used ad an extra check inside ehci_writeback_async_complete_packet(). Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 0d315971a9..04301ce173 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -461,6 +461,7 @@ static bool ehci_verify_qtd(EHCIPacket *p, EHCIqtd *qtd) (p->queue->async && !NLPTR_TBIT(p->qtd.next) && (p->qtd.next != qtd->next)) || (!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd->altnext)) || + p->qtd.token != qtd->token || p->qtd.bufptr[0] != qtd->bufptr[0]) { return false; } else { @@ -1793,7 +1794,9 @@ static int ehci_state_fetchqtd(EHCIQueue *q) if (p != NULL) { if (!ehci_verify_qtd(p, &qtd)) { ehci_cancel_queue(q); - ehci_trace_guest_bug(q->ehci, "guest updated active QH or qTD"); + if (qtd.token & QTD_TOKEN_ACTIVE) { + ehci_trace_guest_bug(q->ehci, "guest updated active qTD"); + } p = NULL; } else { p->qtd = qtd; @@ -1802,11 +1805,6 @@ static int ehci_state_fetchqtd(EHCIQueue *q) } if (!(qtd.token & QTD_TOKEN_ACTIVE)) { - if (p != NULL) { - /* transfer canceled by guest (clear active) */ - ehci_cancel_queue(q); - p = NULL; - } ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); } else if (p != NULL) { switch (p->async) { From 190d849249fd7fecbc75ec38f348197c152f4e87 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:25 +0100 Subject: [PATCH 2204/2270] ehci: Move get / put_dwords upwards No other changes. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 84 +++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 04301ce173..934af55dc6 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -438,6 +438,48 @@ static inline bool ehci_periodic_enabled(EHCIState *s) return ehci_enabled(s) && (s->usbcmd & USBCMD_PSE); } +/* Get an array of dwords from main memory */ +static inline int get_dwords(EHCIState *ehci, uint32_t addr, + uint32_t *buf, int num) +{ + int i; + + if (!ehci->dma) { + ehci_raise_irq(ehci, USBSTS_HSE); + ehci->usbcmd &= ~USBCMD_RUNSTOP; + trace_usb_ehci_dma_error(); + return -1; + } + + for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { + dma_memory_read(ehci->dma, addr, buf, sizeof(*buf)); + *buf = le32_to_cpu(*buf); + } + + return num; +} + +/* Put an array of dwords in to main memory */ +static inline int put_dwords(EHCIState *ehci, uint32_t addr, + uint32_t *buf, int num) +{ + int i; + + if (!ehci->dma) { + ehci_raise_irq(ehci, USBSTS_HSE); + ehci->usbcmd &= ~USBCMD_RUNSTOP; + trace_usb_ehci_dma_error(); + return -1; + } + + for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { + uint32_t tmp = cpu_to_le32(*buf); + dma_memory_write(ehci->dma, addr, &tmp, sizeof(tmp)); + } + + return num; +} + static bool ehci_verify_qh(EHCIQueue *q, EHCIqh *qh) { uint32_t devaddr = get_field(qh->epchar, QH_EPCHAR_DEVADDR); @@ -1054,48 +1096,6 @@ static void ehci_opreg_write(void *ptr, hwaddr addr, *mmio, old); } -/* Get an array of dwords from main memory */ -static inline int get_dwords(EHCIState *ehci, uint32_t addr, - uint32_t *buf, int num) -{ - int i; - - if (!ehci->dma) { - ehci_raise_irq(ehci, USBSTS_HSE); - ehci->usbcmd &= ~USBCMD_RUNSTOP; - trace_usb_ehci_dma_error(); - return -1; - } - - for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { - dma_memory_read(ehci->dma, addr, buf, sizeof(*buf)); - *buf = le32_to_cpu(*buf); - } - - return num; -} - -/* Put an array of dwords in to main memory */ -static inline int put_dwords(EHCIState *ehci, uint32_t addr, - uint32_t *buf, int num) -{ - int i; - - if (!ehci->dma) { - ehci_raise_irq(ehci, USBSTS_HSE); - ehci->usbcmd &= ~USBCMD_RUNSTOP; - trace_usb_ehci_dma_error(); - return -1; - } - - for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { - uint32_t tmp = cpu_to_le32(*buf); - dma_memory_write(ehci->dma, addr, &tmp, sizeof(tmp)); - } - - return num; -} - /* * Write the qh back to guest physical memory. This step isn't * in the EHCI spec but we need to do it since we don't share From 2b3de6ada5d180130ba083d5b45ed51ce8e4def2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:26 +0100 Subject: [PATCH 2205/2270] ehci: writeback_async_complete_packet: verify qh and qtd Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 934af55dc6..96a014442c 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -192,6 +192,7 @@ static int ehci_state_executing(EHCIQueue *q); static int ehci_state_writeback(EHCIQueue *q); static int ehci_state_advqueue(EHCIQueue *q); static int ehci_fill_queue(EHCIPacket *p); +static void ehci_free_packet(EHCIPacket *p); static const char *nr2str(const char **n, size_t len, uint32_t nr) { @@ -516,8 +517,21 @@ static bool ehci_verify_qtd(EHCIPacket *p, EHCIqtd *qtd) static void ehci_writeback_async_complete_packet(EHCIPacket *p) { EHCIQueue *q = p->queue; + EHCIqtd qtd; + EHCIqh qh; int state; + /* Verify the qh + qtd, like we do when going through fetchqh & fetchqtd */ + get_dwords(q->ehci, NLPTR_GET(q->qhaddr), + (uint32_t *) &qh, sizeof(EHCIqh) >> 2); + get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), + (uint32_t *) &qtd, sizeof(EHCIqtd) >> 2); + if (!ehci_verify_qh(q, &qh) || !ehci_verify_qtd(p, &qtd)) { + p->async = EHCI_ASYNC_INITIALIZED; + ehci_free_packet(p); + return; + } + state = ehci_get_state(q->ehci, q->async); ehci_state_executing(q); ehci_state_writeback(q); /* Frees the packet! */ From e3fdfd488c47c2d6920e0964364f1238fb5bf0e2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:27 +0100 Subject: [PATCH 2206/2270] ehci: Verify qtd for async completed packets Remove the short-circuiting of fetchqtd in fetchqh, so that the qtd gets properly verified before completing the transaction. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 96a014442c..dde2ff3130 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1603,7 +1603,6 @@ out: static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) { uint32_t entry; - EHCIPacket *p; EHCIQueue *q; EHCIqh qh; @@ -1612,7 +1611,6 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) if (NULL == q) { q = ehci_alloc_queue(ehci, entry, async); } - p = QTAILQ_FIRST(&q->packets); q->seen++; if (q->seen > 1) { @@ -1637,7 +1635,6 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) if (ehci_reset_queue(q) > 0) { ehci_trace_guest_bug(ehci, "guest updated active QH"); } - p = NULL; } q->qh = qh; @@ -1651,13 +1648,6 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) get_field(q->qh.epchar, QH_EPCHAR_DEVADDR)); } - if (p && p->async == EHCI_ASYNC_FINISHED) { - /* I/O finished -- continue processing queue */ - trace_usb_ehci_packet_action(p->queue, p, "complete"); - ehci_set_state(ehci, async, EST_EXECUTING); - goto out; - } - if (async && (q->qh.epchar & QH_EPCHAR_H)) { /* EHCI spec version 1.0 Section 4.8.3 & 4.10.1 */ @@ -1834,10 +1824,7 @@ static int ehci_state_fetchqtd(EHCIQueue *q) ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); break; case EHCI_ASYNC_FINISHED: - /* - * We get here when advqueue moves to a packet which is already - * finished, which can happen with packets queued up by fill_queue - */ + /* Complete executing of the packet */ ehci_set_state(q->ehci, q->async, EST_EXECUTING); break; } From 51e0c5d02951ee5bd653132e46123f6e963ff23f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:28 +0100 Subject: [PATCH 2207/2270] ehci: Add an ehci_get_pid helper function Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index dde2ff3130..dae414abb9 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -481,6 +481,21 @@ static inline int put_dwords(EHCIState *ehci, uint32_t addr, return num; } +static int ehci_get_pid(EHCIqtd *qtd) +{ + switch (get_field(qtd->token, QTD_TOKEN_PID)) { + case 0: + return USB_TOKEN_OUT; + case 1: + return USB_TOKEN_IN; + case 2: + return USB_TOKEN_SETUP; + default: + fprintf(stderr, "bad token\n"); + return 0; + } +} + static bool ehci_verify_qh(EHCIQueue *q, EHCIqh *qh) { uint32_t devaddr = get_field(qh->epchar, QH_EPCHAR_DEVADDR); @@ -1352,22 +1367,7 @@ static int ehci_execute(EHCIPacket *p, const char *action) return -1; } - p->pid = (p->qtd.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH; - switch (p->pid) { - case 0: - p->pid = USB_TOKEN_OUT; - break; - case 1: - p->pid = USB_TOKEN_IN; - break; - case 2: - p->pid = USB_TOKEN_SETUP; - break; - default: - fprintf(stderr, "bad token\n"); - break; - } - + p->pid = ehci_get_pid(&p->qtd); endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP); ep = usb_ep_get(p->queue->dev, p->pid, endp); From bbbc39ccacf66ef58261c155f9eed503947c3023 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:29 +0100 Subject: [PATCH 2208/2270] ehci: Verify a queue's ep direction does not change ehci_fill_queue assumes that there is a one on one relationship between an ep and a qh, this patch adds a check to ensure this. Note I don't expect this to ever trigger, this is just something I noticed the guest might do while working on other stuff. The only way this check can trigger is if a guest mixes in and out qtd-s in a single qh for a non control ep. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 19 +++++++++++++++++++ hw/usb/hcd-ehci.h | 1 + 2 files changed, 20 insertions(+) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index dae414abb9..5d314a09f1 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -527,6 +527,19 @@ static bool ehci_verify_qtd(EHCIPacket *p, EHCIqtd *qtd) } } +static bool ehci_verify_pid(EHCIQueue *q, EHCIqtd *qtd) +{ + int ep = get_field(q->qh.epchar, QH_EPCHAR_EP); + int pid = ehci_get_pid(qtd); + + /* Note the pid changing is normal for ep 0 (the control ep) */ + if (q->last_pid && ep != 0 && pid != q->last_pid) { + return false; + } else { + return true; + } +} + /* Finish executing and writeback a packet outside of the regular fetchqh -> fetchqtd -> execute -> writeback cycle */ static void ehci_writeback_async_complete_packet(EHCIPacket *p) @@ -634,6 +647,7 @@ static int ehci_reset_queue(EHCIQueue *q) packets = ehci_cancel_queue(q); q->dev = NULL; q->qtdaddr = 0; + q->last_pid = 0; return packets; } @@ -1368,6 +1382,7 @@ static int ehci_execute(EHCIPacket *p, const char *action) } p->pid = ehci_get_pid(&p->qtd); + p->queue->last_pid = p->pid; endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP); ep = usb_ep_get(p->queue->dev, p->pid, endp); @@ -1883,6 +1898,10 @@ static int ehci_fill_queue(EHCIPacket *p) if (!(qtd.token & QTD_TOKEN_ACTIVE)) { break; } + if (!ehci_verify_pid(q, &qtd)) { + ehci_trace_guest_bug(q->ehci, "guest queued token with wrong pid"); + break; + } p = ehci_alloc_packet(q); p->qtdaddr = qtdaddr; p->qtd = qtd; diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index e35144d386..14ee3bea5a 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -248,6 +248,7 @@ struct EHCIQueue { EHCIqh qh; /* copy of current QH (being worked on) */ uint32_t qhaddr; /* address QH read from */ uint32_t qtdaddr; /* address QTD read from */ + int last_pid; /* pid of last packet executed */ USBDevice *dev; QTAILQ_HEAD(pkts_head, EHCIPacket) packets; }; From 9359a58b122187964d7465d48165680eadbf69d3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 18 Dec 2012 14:17:02 +0100 Subject: [PATCH 2209/2270] ehci: Use uframe precision for interrupt threshold checking (v2) Before this patch, the following could happen: 1) Transfer completes, raises interrupt 2) .5 ms later we check if the guest has queued up any new transfers 3) We find and execute a new transfer 4) .2 ms later the new transfer completes 5) We re-run our frame_timer to write back the completion, but less then 1 ms has passed since our last run, so frindex is not changed, so the interrupt threshold code delays the interrupt 6) 1 ms from the re-run our frame-timer runs again and finally delivers the interrupt This leads to unnecessary large delays of interrupts, this code fixes this by changing frindex to uframe precision and using that for interrupt threshold control, making the interrupt fire at step 5 for guest which have low interrupt threshold settings (like Linux). Note that the guest still sees the frindex move in steps of 8 for migration compatibility. This boosts Linux read speed of a simple cheap USB thumb drive by 6 %. Changes in v2: -Make the guest see frindex move in steps of 8 by modifying ehci_opreg_read, rather then using a shadow variable Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 70 +++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 5d314a09f1..efa1d778e3 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -109,12 +109,13 @@ #define FRAME_TIMER_FREQ 1000 #define FRAME_TIMER_NS (1000000000 / FRAME_TIMER_FREQ) +#define UFRAME_TIMER_NS (FRAME_TIMER_NS / 8) #define NB_MAXINTRATE 8 // Max rate at which controller issues ints #define BUFF_SIZE 5*4096 // Max bytes to transfer per transaction #define MAX_QH 100 // Max allowable queue heads in a chain -#define MIN_FR_PER_TICK 3 // Min frames to process when catching up -#define PERIODIC_ACTIVE 64 +#define MIN_UFR_PER_TICK 24 /* Min frames to process when catching up */ +#define PERIODIC_ACTIVE 512 /* Micro-frames */ /* Internal periodic / asynchronous schedule state machine states */ @@ -955,7 +956,15 @@ static uint64_t ehci_opreg_read(void *ptr, hwaddr addr, EHCIState *s = ptr; uint32_t val; - val = s->opreg[addr >> 2]; + switch (addr) { + case FRINDEX: + /* Round down to mult of 8, else it can go backwards on migration */ + val = s->frindex & ~7; + break; + default: + val = s->opreg[addr >> 2]; + } + trace_usb_ehci_opreg_read(addr + s->opregbase, addr2str(addr), val); return val; } @@ -1106,7 +1115,8 @@ static void ehci_opreg_write(void *ptr, hwaddr addr, break; case FRINDEX: - val &= 0x00003ff8; /* frindex is 14bits and always a multiple of 8 */ + val &= 0x00003fff; /* frindex is 14bits */ + s->usbsts_frindex = val; break; case CONFIGFLAG: @@ -2219,16 +2229,16 @@ static void ehci_advance_periodic_state(EHCIState *ehci) } } -static void ehci_update_frindex(EHCIState *ehci, int frames) +static void ehci_update_frindex(EHCIState *ehci, int uframes) { int i; - if (!ehci_enabled(ehci)) { + if (!ehci_enabled(ehci) && ehci->pstate == EST_INACTIVE) { return; } - for (i = 0; i < frames; i++) { - ehci->frindex += 8; + for (i = 0; i < uframes; i++) { + ehci->frindex++; if (ehci->frindex == 0x00002000) { ehci_raise_irq(ehci, USBSTS_FLR); @@ -2252,33 +2262,33 @@ static void ehci_frame_timer(void *opaque) int need_timer = 0; int64_t expire_time, t_now; uint64_t ns_elapsed; - int frames, skipped_frames; + int uframes, skipped_uframes; int i; t_now = qemu_get_clock_ns(vm_clock); ns_elapsed = t_now - ehci->last_run_ns; - frames = ns_elapsed / FRAME_TIMER_NS; + uframes = ns_elapsed / UFRAME_TIMER_NS; if (ehci_periodic_enabled(ehci) || ehci->pstate != EST_INACTIVE) { need_timer++; - if (frames > ehci->maxframes) { - skipped_frames = frames - ehci->maxframes; - ehci_update_frindex(ehci, skipped_frames); - ehci->last_run_ns += FRAME_TIMER_NS * skipped_frames; - frames -= skipped_frames; - DPRINTF("WARNING - EHCI skipped %d frames\n", skipped_frames); + if (uframes > (ehci->maxframes * 8)) { + skipped_uframes = uframes - (ehci->maxframes * 8); + ehci_update_frindex(ehci, skipped_uframes); + ehci->last_run_ns += UFRAME_TIMER_NS * skipped_uframes; + uframes -= skipped_uframes; + DPRINTF("WARNING - EHCI skipped %d uframes\n", skipped_uframes); } - for (i = 0; i < frames; i++) { + for (i = 0; i < uframes; i++) { /* * If we're running behind schedule, we should not catch up * too fast, as that will make some guests unhappy: - * 1) We must process a minimum of MIN_FR_PER_TICK frames, + * 1) We must process a minimum of MIN_UFR_PER_TICK frames, * otherwise we will never catch up * 2) Process frames until the guest has requested an irq (IOC) */ - if (i >= MIN_FR_PER_TICK) { + if (i >= MIN_UFR_PER_TICK) { ehci_commit_irq(ehci); if ((ehci->usbsts & USBINTR_MASK) & ehci->usbintr) { break; @@ -2288,13 +2298,15 @@ static void ehci_frame_timer(void *opaque) ehci->periodic_sched_active--; } ehci_update_frindex(ehci, 1); - ehci_advance_periodic_state(ehci); - ehci->last_run_ns += FRAME_TIMER_NS; + if ((ehci->frindex & 7) == 0) { + ehci_advance_periodic_state(ehci); + } + ehci->last_run_ns += UFRAME_TIMER_NS; } } else { ehci->periodic_sched_active = 0; - ehci_update_frindex(ehci, frames); - ehci->last_run_ns += FRAME_TIMER_NS * frames; + ehci_update_frindex(ehci, uframes); + ehci->last_run_ns += UFRAME_TIMER_NS * uframes; } if (ehci->periodic_sched_active) { @@ -2373,6 +2385,17 @@ static USBBusOps ehci_bus_ops = { .wakeup_endpoint = ehci_wakeup_endpoint, }; +static void usb_ehci_pre_save(void *opaque) +{ + EHCIState *ehci = opaque; + uint32_t new_frindex; + + /* Round down frindex to a multiple of 8 for migration compatibility */ + new_frindex = ehci->frindex & ~7; + ehci->last_run_ns -= (ehci->frindex - new_frindex) * UFRAME_TIMER_NS; + ehci->frindex = new_frindex; +} + static int usb_ehci_post_load(void *opaque, int version_id) { EHCIState *s = opaque; @@ -2423,6 +2446,7 @@ const VMStateDescription vmstate_ehci = { .name = "ehci-core", .version_id = 2, .minimum_version_id = 1, + .pre_save = usb_ehci_pre_save, .post_load = usb_ehci_post_load, .fields = (VMStateField[]) { /* mmio registers */ From 52c15e5986cd0f6531a2989a81a964f77b4ed9c2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:31 +0100 Subject: [PATCH 2210/2270] ehci: Further speedup rescanning if async schedule after raising an interrupt I tried lowering the time between raising an interrupt and rescanning the async schedule to see if the guest has queued a new transfer before, but that did not have any positive effect. I now believe the cause for this is that lowering this time made it more likely to hit the 1 ms interrupt threshold penalty for the next packet, as described in my "ehci: Use uframe precision for interrupt threshold checking" commit. Now that we do interrupt threshold handling with uframe precision, futher lowering this time from .5 to .25 ms gives an extra 15% improvement in speed (MB/s) reading from a simple USB-2.0 thumb-drive. While at it also properly set the int_req_by_async flag for short packet completions. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index efa1d778e3..8da4b6a6d2 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1347,6 +1347,9 @@ static void ehci_execute_complete(EHCIQueue *q) if (tbytes) { /* 4.15.1.2 must raise int on a short input packet */ ehci_raise_irq(q->ehci, USBSTS_INT); + if (q->async) { + q->ehci->int_req_by_async = true; + } } } else { tbytes = 0; @@ -2337,7 +2340,7 @@ static void ehci_frame_timer(void *opaque) /* If we've raised int, we speed up the timer, so that we quickly * notice any new packets queued up in response */ if (ehci->int_req_by_async && (ehci->usbsts & USBSTS_INT)) { - expire_time = t_now + get_ticks_per_sec() / (FRAME_TIMER_FREQ * 2); + expire_time = t_now + get_ticks_per_sec() / (FRAME_TIMER_FREQ * 4); ehci->int_req_by_async = false; } else { expire_time = t_now + (get_ticks_per_sec() From 4a9ef2c042207e4eddbd010ccf2e1c8264d8f0d6 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:32 +0100 Subject: [PATCH 2211/2270] ehci: Don't call commit_irq after raising PCD ehci_raise_irq(s, USBSTS_PCD), gets applied immediately so there is no need to call commit_irq after it. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 8da4b6a6d2..1713394c65 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -757,7 +757,6 @@ static void ehci_attach(USBPort *port) *portsc |= PORTSC_CSC; ehci_raise_irq(s, USBSTS_PCD); - ehci_commit_irq(s); } static void ehci_detach(USBPort *port) @@ -787,7 +786,6 @@ static void ehci_detach(USBPort *port) *portsc |= PORTSC_CSC; ehci_raise_irq(s, USBSTS_PCD); - ehci_commit_irq(s); } static void ehci_child_detach(USBPort *port, USBDevice *child) From 719c130dcaa3b1269beed71ca9cf6c43a0219b30 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:33 +0100 Subject: [PATCH 2212/2270] uhci: Fix 1 ms delay in interrupt reporting to the guest Re-arrange how we process frames / increase frnum / report pending interrupts, to avoid a 1 ms delay in interrupt reporting to the guest. This increases the packet throughput for cases where the guest submits a single packet, then waits for its completion then re-submits from 500 pkts / sec to 1000 pkts / sec. This impacts for example the use of redirected / virtual usb to serial convertors. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 2af754b5cf..5685b9f3a9 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -1191,17 +1191,7 @@ static void uhci_frame_timer(void *opaque) return; } - /* Complete the previous frame */ - if (s->pending_int_mask) { - s->status2 |= s->pending_int_mask; - s->status |= UHCI_STS_USBINT; - uhci_update_irq(s); - } - s->pending_int_mask = 0; - - /* Start new frame */ - s->frnum = (s->frnum + 1) & 0x7ff; - + /* Process the current frame */ trace_usb_uhci_frame_start(s->frnum); uhci_async_validate_begin(s); @@ -1210,6 +1200,18 @@ static void uhci_frame_timer(void *opaque) uhci_async_validate_end(s); + /* The uhci spec says frnum reflects the frame currently being processed, + * and the guest must look at frnum - 1 on interrupt, so inc frnum now */ + s->frnum = (s->frnum + 1) & 0x7ff; + + /* Complete the previous frame */ + if (s->pending_int_mask) { + s->status2 |= s->pending_int_mask; + s->status |= UHCI_STS_USBINT; + uhci_update_irq(s); + } + s->pending_int_mask = 0; + qemu_mod_timer(s->frame_timer, s->expire_time); } From ecfdc15f4351a17989d446f4f1e6d1931d9c1677 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:34 +0100 Subject: [PATCH 2213/2270] uhci: Fix pending interrupts getting lost on migration Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 5685b9f3a9..e82e5cc809 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -433,7 +433,7 @@ static int uhci_post_load(void *opaque, int version_id) static const VMStateDescription vmstate_uhci = { .name = "uhci", - .version_id = 2, + .version_id = 3, .minimum_version_id = 1, .minimum_version_id_old = 1, .post_load = uhci_post_load, @@ -451,6 +451,7 @@ static const VMStateDescription vmstate_uhci = { VMSTATE_UINT8(status2, UHCIState), VMSTATE_TIMER(frame_timer, UHCIState), VMSTATE_INT64_V(expire_time, UHCIState, 2), + VMSTATE_UINT32_V(pending_int_mask, UHCIState, 3), VMSTATE_END_OF_LIST() } }; From 475443cf14d7ef01b9ea56eed8657804f7bdf664 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:35 +0100 Subject: [PATCH 2214/2270] uhci: Add a QH_VALID define Rather then using the magic 32 value in various places. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index e82e5cc809..d61d879c1c 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -75,6 +75,9 @@ #define FRAME_MAX_LOOPS 256 +/* Must be large enough to handle 10 frame delay for initial isoc requests */ +#define QH_VALID 32 + #define NB_PORTS 2 enum { @@ -206,9 +209,7 @@ static UHCIQueue *uhci_queue_new(UHCIState *s, uint32_t qh_addr, UHCI_TD *td, queue->ep = ep; QTAILQ_INIT(&queue->asyncs); QTAILQ_INSERT_HEAD(&s->queues, queue, next); - /* valid needs to be large enough to handle 10 frame delay - * for initial isochronous requests */ - queue->valid = 32; + queue->valid = QH_VALID; trace_usb_uhci_queue_add(queue->token); return queue; } @@ -854,7 +855,7 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr, } if (q) { - q->valid = 32; + q->valid = QH_VALID; } /* Is active ? */ From f8f48b6957bf182339495e6be429f7bdc7ef1981 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:36 +0100 Subject: [PATCH 2215/2270] uhci: Limit amount of frames processed in one go Before this patch uhci would process an unlimited amount of frames when behind on schedule, by setting the timer to a time already past, causing the timer subsys to immediately recall the frame_timer function gain. This would cause invalid cancellations of bulk queues when the catching up processed more then 32 frames at a moment when the bulk qh was temporarily unlinked (which the Linux uhci driver does). This patch fixes this by processing maximum 16 frames in one go, and always setting the timer one ms later, making the code behave more like the ehci code. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index d61d879c1c..e5c3e595f1 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -78,6 +78,8 @@ /* Must be large enough to handle 10 frame delay for initial isoc requests */ #define QH_VALID 32 +#define MAX_FRAMES_PER_TICK (QH_VALID / 2) + #define NB_PORTS 2 enum { @@ -500,7 +502,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val) trace_usb_uhci_schedule_start(); s->expire_time = qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() / FRAME_TIMER_FREQ); - qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock)); + qemu_mod_timer(s->frame_timer, s->expire_time); s->status &= ~UHCI_STS_HCHALTED; } else if (!(val & UHCI_CMD_RS)) { s->status |= UHCI_STS_HCHALTED; @@ -1176,10 +1178,10 @@ static void uhci_bh(void *opaque) static void uhci_frame_timer(void *opaque) { UHCIState *s = opaque; + uint64_t t_now, t_last_run; + int i, frames; + const uint64_t frame_t = get_ticks_per_sec() / FRAME_TIMER_FREQ; - /* prepare the timer for the next frame */ - s->expire_time += (get_ticks_per_sec() / FRAME_TIMER_FREQ); - s->frame_bytes = 0; s->completions_only = false; qemu_bh_cancel(s->bh); @@ -1193,20 +1195,29 @@ static void uhci_frame_timer(void *opaque) return; } - /* Process the current frame */ - trace_usb_uhci_frame_start(s->frnum); + /* We still store expire_time in our state, for migration */ + t_last_run = s->expire_time - frame_t; + t_now = qemu_get_clock_ns(vm_clock); - uhci_async_validate_begin(s); + /* Process up to MAX_FRAMES_PER_TICK frames */ + frames = (t_now - t_last_run) / frame_t; + if (frames > MAX_FRAMES_PER_TICK) { + frames = MAX_FRAMES_PER_TICK; + } - uhci_process_frame(s); + for (i = 0; i < frames; i++) { + s->frame_bytes = 0; + trace_usb_uhci_frame_start(s->frnum); + uhci_async_validate_begin(s); + uhci_process_frame(s); + uhci_async_validate_end(s); + /* The spec says frnum is the frame currently being processed, and + * the guest must look at frnum - 1 on interrupt, so inc frnum now */ + s->frnum = (s->frnum + 1) & 0x7ff; + s->expire_time += frame_t; + } - uhci_async_validate_end(s); - - /* The uhci spec says frnum reflects the frame currently being processed, - * and the guest must look at frnum - 1 on interrupt, so inc frnum now */ - s->frnum = (s->frnum + 1) & 0x7ff; - - /* Complete the previous frame */ + /* Complete the previous frame(s) */ if (s->pending_int_mask) { s->status2 |= s->pending_int_mask; s->status |= UHCI_STS_USBINT; @@ -1214,7 +1225,7 @@ static void uhci_frame_timer(void *opaque) } s->pending_int_mask = 0; - qemu_mod_timer(s->frame_timer, s->expire_time); + qemu_mod_timer(s->frame_timer, t_now + frame_t); } static const MemoryRegionPortio uhci_portio[] = { From 9fdf70272702095f57efc51a80c79493fd0829b8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:37 +0100 Subject: [PATCH 2216/2270] uhci: Maximize how many frames we catch up when behind If somehow we've gotten behind a lot, simply skip ahead, like the ehci code does. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index e5c3e595f1..bd3377e36a 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -171,6 +171,7 @@ struct UHCIState { /* Properties */ char *masterbus; uint32_t firstport; + uint32_t maxframes; }; typedef struct UHCI_TD { @@ -1201,6 +1202,12 @@ static void uhci_frame_timer(void *opaque) /* Process up to MAX_FRAMES_PER_TICK frames */ frames = (t_now - t_last_run) / frame_t; + if (frames > s->maxframes) { + int skipped = frames - s->maxframes; + s->expire_time += skipped * frame_t; + s->frnum = (s->frnum + skipped) & 0x7ff; + frames -= skipped; + } if (frames > MAX_FRAMES_PER_TICK) { frames = MAX_FRAMES_PER_TICK; } @@ -1326,6 +1333,7 @@ static Property uhci_properties[] = { DEFINE_PROP_STRING("masterbus", UHCIState, masterbus), DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0), DEFINE_PROP_UINT32("bandwidth", UHCIState, frame_bandwidth, 1280), + DEFINE_PROP_UINT32("maxframes", UHCIState, maxframes, 128), DEFINE_PROP_END_OF_LIST(), }; From 027c03f7327faa696e1d876954a18b5214c18583 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:38 +0100 Subject: [PATCH 2217/2270] hid: Change idle handling to use a timer This leads to cleaner code in usb-hid, and removes up to a 1000 calls / sec to qemu_get_clock_ns(vm_clock) if idle-time is set to its default value of 0. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/hid.c | 43 +++++++++++++++++++++++++++++++++++++------ hw/hid.h | 5 +++-- hw/usb/dev-hid.c | 8 +++----- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/hw/hid.c b/hw/hid.c index 0fee3b6ddd..89b5415c0f 100644 --- a/hw/hid.c +++ b/hw/hid.c @@ -71,12 +71,38 @@ static const uint8_t hid_usage_keys[0x100] = { bool hid_has_events(HIDState *hs) { - return hs->n > 0; + return hs->n > 0 || hs->idle_pending; } -void hid_set_next_idle(HIDState *hs, int64_t curtime) +static void hid_idle_timer(void *opaque) { - hs->next_idle_clock = curtime + (get_ticks_per_sec() * hs->idle * 4) / 1000; + HIDState *hs = opaque; + + hs->idle_pending = true; + hs->event(hs); +} + +static void hid_del_idle_timer(HIDState *hs) +{ + if (hs->idle_timer) { + qemu_del_timer(hs->idle_timer); + qemu_free_timer(hs->idle_timer); + hs->idle_timer = NULL; + } +} + +void hid_set_next_idle(HIDState *hs) +{ + if (hs->idle) { + uint64_t expire_time = qemu_get_clock_ns(vm_clock) + + get_ticks_per_sec() * hs->idle * 4 / 1000; + if (!hs->idle_timer) { + hs->idle_timer = qemu_new_timer_ns(vm_clock, hid_idle_timer, hs); + } + qemu_mod_timer_ns(hs->idle_timer, expire_time); + } else { + hid_del_idle_timer(hs); + } } static void hid_pointer_event_clear(HIDPointerEvent *e, int buttons) @@ -232,6 +258,8 @@ int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len) int index; HIDPointerEvent *e; + hs->idle_pending = false; + hid_pointer_activate(hs); /* When the buffer is empty, return the last event. Relative @@ -319,6 +347,8 @@ int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len) int hid_keyboard_poll(HIDState *hs, uint8_t *buf, int len) { + hs->idle_pending = false; + if (len < 2) { return 0; } @@ -377,6 +407,8 @@ void hid_reset(HIDState *hs) hs->n = 0; hs->protocol = 1; hs->idle = 0; + hs->idle_pending = false; + hid_del_idle_timer(hs); } void hid_free(HIDState *hs) @@ -390,6 +422,7 @@ void hid_free(HIDState *hs) qemu_remove_mouse_event_handler(hs->ptr.eh_entry); break; } + hid_del_idle_timer(hs); } void hid_init(HIDState *hs, int kind, HIDEventFunc event) @@ -412,9 +445,7 @@ static int hid_post_load(void *opaque, int version_id) { HIDState *s = opaque; - if (s->idle) { - hid_set_next_idle(s, qemu_get_clock_ns(vm_clock)); - } + hid_set_next_idle(s); return 0; } diff --git a/hw/hid.h b/hw/hid.h index 100b121663..56c71ed5ae 100644 --- a/hw/hid.h +++ b/hw/hid.h @@ -43,7 +43,8 @@ struct HIDState { int kind; int32_t protocol; uint8_t idle; - int64_t next_idle_clock; + bool idle_pending; + QEMUTimer *idle_timer; HIDEventFunc event; }; @@ -52,7 +53,7 @@ void hid_reset(HIDState *hs); void hid_free(HIDState *hs); bool hid_has_events(HIDState *hs); -void hid_set_next_idle(HIDState *hs, int64_t curtime); +void hid_set_next_idle(HIDState *hs); void hid_pointer_activate(HIDState *hs); int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len); int hid_keyboard_poll(HIDState *hs, uint8_t *buf, int len); diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c index ce38fef9f6..b4ace04eef 100644 --- a/hw/usb/dev-hid.c +++ b/hw/usb/dev-hid.c @@ -501,7 +501,7 @@ static void usb_hid_handle_control(USBDevice *dev, USBPacket *p, break; case SET_IDLE: hs->idle = (uint8_t) (value >> 8); - hid_set_next_idle(hs, qemu_get_clock_ns(vm_clock)); + hid_set_next_idle(hs); if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) { hid_pointer_activate(hs); } @@ -523,16 +523,14 @@ static void usb_hid_handle_data(USBDevice *dev, USBPacket *p) switch (p->pid) { case USB_TOKEN_IN: if (p->ep->nr == 1) { - int64_t curtime = qemu_get_clock_ns(vm_clock); if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) { hid_pointer_activate(hs); } - if (!hid_has_events(hs) && - (!hs->idle || hs->next_idle_clock - curtime > 0)) { + if (!hid_has_events(hs)) { p->status = USB_RET_NAK; return; } - hid_set_next_idle(hs, curtime); + hid_set_next_idle(hs); if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) { len = hid_pointer_poll(hs, buf, p->iov.size); } else if (hs->kind == HID_KEYBOARD) { From 6735d433729f80fab80c0a1f70ae131398645613 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:39 +0100 Subject: [PATCH 2218/2270] usb: Fix usb_ep_find_packet_by_id usb_ep_find_packet_by_id mistakenly only checks the first packet and if that is not a match, keeps trying the first packet! This patch fixes this. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb/core.c b/hw/usb/core.c index e315fc1021..d057aab900 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -761,7 +761,7 @@ USBPacket *usb_ep_find_packet_by_id(USBDevice *dev, int pid, int ep, struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); USBPacket *p; - while ((p = QTAILQ_FIRST(&uep->queue)) != NULL) { + QTAILQ_FOREACH(p, &uep->queue, queue) { if (p->id == id) { return p; } From f79738b03ba55a5c9733c6dc2455964a6f8fdac9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:40 +0100 Subject: [PATCH 2219/2270] usb: Add an usb_device_ep_stopped USBDevice method Some usb devices (host or network redirection) can benefit from knowing when the guest stops using an endpoint. Redirection may involve submitting packets independently from the guest (in combination with a fifo buffer between the redirection code and the guest), to ensure that buffers of the real usb device are timely emptied. This is done for example for isoc traffic and for interrupt input endpoints. But when the (re)submission of packets is done by the device code, then how does it know when to stop this? For isoc endpoints this is handled by detecting a set interface (change alt setting) command, which works well for isoc endpoints. But for interrupt endpoints currently the redirection code never stops receiving data from the device, which is less then ideal. However the controller emulation is aware when a guest looses interest, as then the qh for the endpoint gets unlinked (ehci, ohci, uhci) or the endpoint is explicitly stopped (xhci). This patch adds a new ep_stopped USBDevice method and modifies the hcd code to call this on queue unlink / ep stop. This makes it possible for the redirection code to properly stop receiving interrupt input (*) data when the guest no longer has interest in it. *) And in the future also buffered bulk input. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb.h | 8 ++++++++ hw/usb/bus.c | 8 ++++++++ hw/usb/hcd-ehci.c | 19 ++++++++++++++++++- hw/usb/hcd-ohci.c | 30 ++++++++++++++++++++++++++---- hw/usb/hcd-uhci.c | 1 + hw/usb/hcd-xhci.c | 7 +++++++ 6 files changed, 68 insertions(+), 5 deletions(-) diff --git a/hw/usb.h b/hw/usb.h index 81e265c4fd..aca8ff6950 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -307,6 +307,12 @@ typedef struct USBDeviceClass { */ void (*flush_ep_queue)(USBDevice *dev, USBEndpoint *ep); + /* + * Called by the hcd to let the device know the queue for an endpoint + * has been unlinked / stopped. Optional may be NULL. + */ + void (*ep_stopped)(USBDevice *dev, USBEndpoint *ep); + const char *product_desc; const USBDesc *usb_desc; } USBDeviceClass; @@ -539,6 +545,8 @@ void usb_device_set_interface(USBDevice *dev, int interface, void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep); +void usb_device_ep_stopped(USBDevice *dev, USBEndpoint *ep); + const char *usb_device_get_product_desc(USBDevice *dev); const USBDesc *usb_device_get_usb_desc(USBDevice *dev); diff --git a/hw/usb/bus.c b/hw/usb/bus.c index 10260a13ac..180d1d739b 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -189,6 +189,14 @@ void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep) } } +void usb_device_ep_stopped(USBDevice *dev, USBEndpoint *ep) +{ + USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); + if (klass->ep_stopped) { + klass->ep_stopped(dev, ep); + } +} + static int usb_qdev_init(DeviceState *qdev) { USBDevice *dev = USB_DEVICE(qdev); diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 1713394c65..320b7e7239 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -622,6 +622,17 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint32_t addr, int async) return q; } +static void ehci_queue_stopped(EHCIQueue *q) +{ + int endp = get_field(q->qh.epchar, QH_EPCHAR_EP); + + if (!q->last_pid || !q->dev) { + return; + } + + usb_device_ep_stopped(q->dev, usb_ep_get(q->dev, q->last_pid, endp)); +} + static int ehci_cancel_queue(EHCIQueue *q) { EHCIPacket *p; @@ -629,7 +640,7 @@ static int ehci_cancel_queue(EHCIQueue *q) p = QTAILQ_FIRST(&q->packets); if (p == NULL) { - return 0; + goto leave; } trace_usb_ehci_queue_action(q, "cancel"); @@ -637,6 +648,9 @@ static int ehci_cancel_queue(EHCIQueue *q) ehci_free_packet(p); packets++; } while ((p = QTAILQ_FIRST(&q->packets)) != NULL); + +leave: + ehci_queue_stopped(q); return packets; } @@ -1392,6 +1406,9 @@ static int ehci_execute(EHCIPacket *p, const char *action) return -1; } + if (!ehci_verify_pid(p->queue, &p->qtd)) { + ehci_queue_stopped(p->queue); /* Mark the ep in the prev dir stopped */ + } p->pid = ehci_get_pid(&p->qtd); p->queue->last_pid = p->pid; endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP); diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 052c4a3037..29bafa6da9 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -430,6 +430,23 @@ static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr) return NULL; } +static void ohci_stop_endpoints(OHCIState *ohci) +{ + USBDevice *dev; + int i, j; + + for (i = 0; i < ohci->num_ports; i++) { + dev = ohci->rhport[i].port.dev; + if (dev && dev->attached) { + usb_device_ep_stopped(dev, &dev->ep_ctl); + for (j = 0; j < USB_MAX_ENDPOINTS; j++) { + usb_device_ep_stopped(dev, &dev->ep_in[j]); + usb_device_ep_stopped(dev, &dev->ep_out[j]); + } + } + } +} + /* Reset the controller */ static void ohci_reset(void *opaque) { @@ -478,6 +495,7 @@ static void ohci_reset(void *opaque) usb_cancel_packet(&ohci->usb_packet); ohci->async_td = 0; } + ohci_stop_endpoints(ohci); DPRINTF("usb-ohci: Reset %s\n", ohci->name); } @@ -1147,6 +1165,8 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion) if (ohci->async_td && addr == ohci->async_td) { usb_cancel_packet(&ohci->usb_packet); ohci->async_td = 0; + usb_device_ep_stopped(ohci->usb_packet.ep->dev, + ohci->usb_packet.ep); } continue; } @@ -1227,10 +1247,12 @@ static void ohci_frame_boundary(void *opaque) } /* Cancel all pending packets if either of the lists has been disabled. */ - if (ohci->async_td && - ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) { - usb_cancel_packet(&ohci->usb_packet); - ohci->async_td = 0; + if (ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) { + if (ohci->async_td) { + usb_cancel_packet(&ohci->usb_packet); + ohci->async_td = 0; + } + ohci_stop_endpoints(ohci); } ohci->old_ctl = ohci->ctl; ohci_process_lists(ohci, 0); diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index bd3377e36a..0cd68cf355 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -226,6 +226,7 @@ static void uhci_queue_free(UHCIQueue *queue, const char *reason) async = QTAILQ_FIRST(&queue->asyncs); uhci_async_cancel(async); } + usb_device_ep_stopped(queue->ep->dev, queue->ep); trace_usb_uhci_queue_del(queue->token, reason); QTAILQ_REMOVE(&s->queues, queue, next); diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index e2de71ef1a..40542b8d05 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1177,6 +1177,7 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid, XHCISlot *slot; XHCIEPContext *epctx; int i, xferi, killed = 0; + USBEndpoint *ep = NULL; assert(slotid >= 1 && slotid <= xhci->numslots); assert(epid >= 1 && epid <= 31); @@ -1192,9 +1193,15 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid, xferi = epctx->next_xfer; for (i = 0; i < TD_QUEUE; i++) { + if (epctx->transfers[xferi].packet.ep) { + ep = epctx->transfers[xferi].packet.ep; + } killed += xhci_ep_nuke_one_xfer(&epctx->transfers[xferi]); xferi = (xferi + 1) % TD_QUEUE; } + if (ep) { + usb_device_ep_stopped(ep->dev, ep); + } return killed; } From f8c126f329892ec8941e5bbe6ba411d78cfc66cb Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:41 +0100 Subject: [PATCH 2220/2270] usbredir: Add an usbredir_stop_ep helper function Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 0abe1ff4d1..c5704c176a 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -752,6 +752,23 @@ static void usbredir_flush_ep_queue(USBDevice *dev, USBEndpoint *ep) } } +static void usbredir_stop_ep(USBRedirDevice *dev, int i) +{ + uint8_t ep = I2EP(i); + + switch (dev->endpoint[i].type) { + case USB_ENDPOINT_XFER_ISOC: + usbredir_stop_iso_stream(dev, ep); + break; + case USB_ENDPOINT_XFER_INT: + if (ep & USB_DIR_IN) { + usbredir_stop_interrupt_receiving(dev, ep); + } + break; + } + usbredir_free_bufpq(dev, ep); +} + static void usbredir_set_config(USBRedirDevice *dev, USBPacket *p, int config) { @@ -761,17 +778,7 @@ static void usbredir_set_config(USBRedirDevice *dev, USBPacket *p, DPRINTF("set config %d id %"PRIu64"\n", config, p->id); for (i = 0; i < MAX_ENDPOINTS; i++) { - switch (dev->endpoint[i].type) { - case USB_ENDPOINT_XFER_ISOC: - usbredir_stop_iso_stream(dev, I2EP(i)); - break; - case USB_ENDPOINT_XFER_INT: - if (i & 0x10) { - usbredir_stop_interrupt_receiving(dev, I2EP(i)); - } - break; - } - usbredir_free_bufpq(dev, I2EP(i)); + usbredir_stop_ep(dev, i); } set_config.configuration = config; @@ -799,17 +806,7 @@ static void usbredir_set_interface(USBRedirDevice *dev, USBPacket *p, for (i = 0; i < MAX_ENDPOINTS; i++) { if (dev->endpoint[i].interface == interface) { - switch (dev->endpoint[i].type) { - case USB_ENDPOINT_XFER_ISOC: - usbredir_stop_iso_stream(dev, I2EP(i)); - break; - case USB_ENDPOINT_XFER_INT: - if (i & 0x10) { - usbredir_stop_interrupt_receiving(dev, I2EP(i)); - } - break; - } - usbredir_free_bufpq(dev, I2EP(i)); + usbredir_stop_ep(dev, i); } } From 7e9638d3eb5c0b4c5920dac72bb2e6885652c029 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:42 +0100 Subject: [PATCH 2221/2270] usbredir: Add USBEP2I and I2USBEP helper macros Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index c5704c176a..0ffcc7db48 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -44,6 +44,11 @@ #define NO_INTERFACE_INFO 255 /* Valid interface_count always <= 32 */ #define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f)) #define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f)) +#define USBEP2I(usb_ep) (((usb_ep)->pid == USB_TOKEN_IN) ? \ + ((usb_ep)->nr | 0x10) : ((usb_ep)->nr)) +#define I2USBEP(d, i) (usb_ep_get(&(d)->dev, \ + ((i) & 0x10) ? USB_TOKEN_IN : USB_TOKEN_OUT, \ + (i) & 0x0f)) typedef struct USBRedirDevice USBRedirDevice; @@ -1351,11 +1356,10 @@ static void usbredir_set_pipeline(USBRedirDevice *dev, struct USBEndpoint *uep) static void usbredir_setup_usb_eps(USBRedirDevice *dev) { struct USBEndpoint *usb_ep; - int i, pid; + int i; for (i = 0; i < MAX_ENDPOINTS; i++) { - pid = (i & 0x10) ? USB_TOKEN_IN : USB_TOKEN_OUT; - usb_ep = usb_ep_get(&dev->dev, pid, i & 0x0f); + usb_ep = I2USBEP(dev, i); usb_ep->type = dev->endpoint[i].type; usb_ep->ifnum = dev->endpoint[i].interface; usb_ep->max_packet_size = dev->endpoint[i].max_packet_size; From d8553dd0475a967042193cdcf4d02c8ce5e73730 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:43 +0100 Subject: [PATCH 2222/2270] usbredir: Add ep_stopped USBDevice method To ensure that interrupt receiving is properly stopped when the guest is no longer interested in an interrupt endpoint. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 0ffcc7db48..855c76563a 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -774,6 +774,14 @@ static void usbredir_stop_ep(USBRedirDevice *dev, int i) usbredir_free_bufpq(dev, ep); } +static void usbredir_ep_stopped(USBDevice *udev, USBEndpoint *uep) +{ + USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + + usbredir_stop_ep(dev, USBEP2I(uep)); + usbredirparser_do_write(dev->parser); +} + static void usbredir_set_config(USBRedirDevice *dev, USBPacket *p, int config) { @@ -1995,6 +2003,7 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data) uc->handle_data = usbredir_handle_data; uc->handle_control = usbredir_handle_control; uc->flush_ep_queue = usbredir_flush_ep_queue; + uc->ep_stopped = usbredir_ep_stopped; dc->vmsd = &usbredir_vmstate; dc->props = usbredir_properties; } From d3aea641a4002e0abe940c65d318ef38eda245df Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:44 +0100 Subject: [PATCH 2223/2270] usbredir: Verify we have 32 bits bulk length cap when redirecting to xhci The xhci-hcd may submit bulk transfers > 65535 bytes even when not using bulk-in pipeling, so usbredir can only be used in combination with an xhci hcd if the client has the 32 bits bulk length capability. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 855c76563a..566737d8f5 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -979,6 +979,8 @@ static void usbredir_do_attach(void *opaque) if ((dev->dev.port->speedmask & USB_SPEED_MASK_SUPER) && !( usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_ep_info_max_packet_size) && + usbredirparser_peer_has_cap(dev->parser, + usb_redir_cap_32bits_bulk_length) && usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_64bits_ids))) { ERROR("usb-redir-host lacks capabilities needed for use with XHCI\n"); From bd019b735ac422bf9a40e1865e3d59f2e128604f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:45 +0100 Subject: [PATCH 2224/2270] usbredir: Add usbredir_init_endpoints() helper Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 566737d8f5..ad22491f2c 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1063,6 +1063,17 @@ static void usbredir_vm_state_change(void *priv, int running, RunState state) } } +static void usbredir_init_endpoints(USBRedirDevice *dev) +{ + int i; + + usb_ep_init(&dev->dev); + memset(dev->endpoint, 0, sizeof(dev->endpoint)); + for (i = 0; i < MAX_ENDPOINTS; i++) { + QTAILQ_INIT(&dev->endpoint[i].bufpq); + } +} + static int usbredir_initfn(USBDevice *udev) { USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); @@ -1089,9 +1100,7 @@ static int usbredir_initfn(USBDevice *udev) packet_id_queue_init(&dev->cancelled, dev, "cancelled"); packet_id_queue_init(&dev->already_in_flight, dev, "already-in-flight"); - for (i = 0; i < MAX_ENDPOINTS; i++) { - QTAILQ_INIT(&dev->endpoint[i].bufpq); - } + usbredir_init_endpoints(dev); /* We'll do the attach once we receive the speed from the usb-host */ udev->auto_attach = 0; @@ -1295,7 +1304,6 @@ static void usbredir_device_connect(void *priv, static void usbredir_device_disconnect(void *priv) { USBRedirDevice *dev = priv; - int i; /* Stop any pending attaches */ qemu_del_timer(dev->attach_timer); @@ -1312,11 +1320,7 @@ static void usbredir_device_disconnect(void *priv) /* Reset state so that the next dev connected starts with a clean slate */ usbredir_cleanup_device_queues(dev); - memset(dev->endpoint, 0, sizeof(dev->endpoint)); - for (i = 0; i < MAX_ENDPOINTS; i++) { - QTAILQ_INIT(&dev->endpoint[i].bufpq); - } - usb_ep_init(&dev->dev); + usbredir_init_endpoints(dev); dev->interface_info.interface_count = NO_INTERFACE_INFO; dev->dev.addr = 0; dev->dev.speed = 0; From e97f0aca796fb949f9d34c50603511048a52b39b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Dec 2012 14:35:46 +0100 Subject: [PATCH 2225/2270] usb-redir: Add debugging to bufpq save / restore Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index ad22491f2c..f15dc914ab 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -61,6 +61,7 @@ struct buf_packet { }; struct endp_data { + USBRedirDevice *dev; uint8_t type; uint8_t interval; uint8_t interface; /* bInterfaceNumber this ep belongs to */ @@ -1070,6 +1071,7 @@ static void usbredir_init_endpoints(USBRedirDevice *dev) usb_ep_init(&dev->dev); memset(dev->endpoint, 0, sizeof(dev->endpoint)); for (i = 0; i < MAX_ENDPOINTS; i++) { + dev->endpoint[i].dev = dev; QTAILQ_INIT(&dev->endpoint[i].bufpq); } } @@ -1783,22 +1785,26 @@ static const VMStateInfo usbredir_parser_vmstate_info = { static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused) { struct endp_data *endp = priv; + USBRedirDevice *dev = endp->dev; struct buf_packet *bufp; - int remain = endp->bufpq_size; + int i = 0; qemu_put_be32(f, endp->bufpq_size); QTAILQ_FOREACH(bufp, &endp->bufpq, next) { + DPRINTF("put_bufpq %d/%d len %d status %d\n", i + 1, endp->bufpq_size, + bufp->len, bufp->status); qemu_put_be32(f, bufp->len); qemu_put_be32(f, bufp->status); qemu_put_buffer(f, bufp->data, bufp->len); - remain--; + i++; } - assert(remain == 0); + assert(i == endp->bufpq_size); } static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused) { struct endp_data *endp = priv; + USBRedirDevice *dev = endp->dev; struct buf_packet *bufp; int i; @@ -1810,6 +1816,8 @@ static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused) bufp->data = qemu_oom_check(malloc(bufp->len)); /* regular malloc! */ qemu_get_buffer(f, bufp->data, bufp->len); QTAILQ_INSERT_TAIL(&endp->bufpq, bufp, next); + DPRINTF("get_bufpq %d/%d len %d status %d\n", i + 1, endp->bufpq_size, + bufp->len, bufp->status); } return 0; } From a820b575787ac0b6b274b6a89aa6ef9813b4c782 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 14 Dec 2012 13:10:39 +0100 Subject: [PATCH 2226/2270] xhci: call set-address with dummy usbpacket Due to the way devices are addressed with xhci (done by hardware, not the guest os) there is no packet when invoking the set-address control request. Create a dummy packet in that case to avoid null pointer dereferences. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 40542b8d05..9132920932 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1970,13 +1970,18 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, if (bsr) { slot_ctx[3] = SLOT_DEFAULT << SLOT_STATE_SHIFT; } else { + USBPacket p; slot->devaddr = xhci->devaddr++; slot_ctx[3] = (SLOT_ADDRESSED << SLOT_STATE_SHIFT) | slot->devaddr; DPRINTF("xhci: device address is %d\n", slot->devaddr); usb_device_reset(dev); - usb_device_handle_control(dev, NULL, + usb_packet_setup(&p, USB_TOKEN_OUT, + usb_ep_get(dev, USB_TOKEN_OUT, 0), + 0, false, false); + usb_device_handle_control(dev, &p, DeviceOutRequest | USB_REQ_SET_ADDRESS, slot->devaddr, 0, 0, NULL); + assert(p.status != USB_RET_ASYNC); } res = xhci_enable_ep(xhci, slotid, 1, octx+32, ep0_ctx); From 5aa3ca9f53cc7a1bf76b7583c46937a73914394a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 16 Dec 2012 04:49:43 +0100 Subject: [PATCH 2227/2270] usb/ehci: Clean up SysBus and PCI EHCI split MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SysBus EHCI was introduced in a hurry before 1.3 Soft Freeze. To use QOM casts in place of DO_UPCAST() / FROM_SYSBUS(), we need an identifying type. Introduce generic abstract base types for PCI and SysBus EHCI to allow multiple types to access the shared fields. While at it, move the state structs being amended with macros to the header file so that they can be embedded. The VMSTATE_PCI_DEVICE() macro does not play nice with the QOM parent_obj naming convention, so defer that cleanup. Signed-off-by: Andreas Färber Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci-pci.c | 39 ++++++++++++++++++++++++--------------- hw/usb/hcd-ehci-sysbus.c | 19 ++++++++++--------- hw/usb/hcd-ehci.h | 26 ++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 24 deletions(-) diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c index ee77d41db5..0eb78269f7 100644 --- a/hw/usb/hcd-ehci-pci.c +++ b/hw/usb/hcd-ehci-pci.c @@ -16,14 +16,8 @@ */ #include "hw/usb/hcd-ehci.h" -#include "hw/pci/pci.h" #include "qemu/range.h" -typedef struct EHCIPCIState { - PCIDevice pcidev; - EHCIState ehci; -} EHCIPCIState; - typedef struct EHCIPCIInfo { const char *name; uint16_t vendor_id; @@ -33,7 +27,7 @@ typedef struct EHCIPCIInfo { static int usb_ehci_pci_initfn(PCIDevice *dev) { - EHCIPCIState *i = DO_UPCAST(EHCIPCIState, pcidev, dev); + EHCIPCIState *i = PCI_EHCI(dev); EHCIState *s = &i->ehci; uint8_t *pci_conf = dev->config; @@ -83,7 +77,7 @@ static int usb_ehci_pci_initfn(PCIDevice *dev) static void usb_ehci_pci_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int l) { - EHCIPCIState *i = DO_UPCAST(EHCIPCIState, pcidev, dev); + EHCIPCIState *i = PCI_EHCI(dev); bool busmaster; pci_default_write_config(dev, addr, val, l); @@ -115,12 +109,8 @@ static void ehci_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - EHCIPCIInfo *i = data; k->init = usb_ehci_pci_initfn; - k->vendor_id = i->vendor_id; - k->device_id = i->device_id; - k->revision = i->revision; k->class_id = PCI_CLASS_SERIAL_USB; k->config_write = usb_ehci_pci_write_config; k->no_hotplug = 1; @@ -128,6 +118,24 @@ static void ehci_class_init(ObjectClass *klass, void *data) dc->props = ehci_pci_properties; } +static const TypeInfo ehci_pci_type_info = { + .name = TYPE_PCI_EHCI, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(EHCIPCIState), + .abstract = true, + .class_init = ehci_class_init, +}; + +static void ehci_data_class_init(ObjectClass *klass, void *data) +{ + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + EHCIPCIInfo *i = data; + + k->vendor_id = i->vendor_id; + k->device_id = i->device_id; + k->revision = i->revision; +} + static struct EHCIPCIInfo ehci_pci_info[] = { { .name = "usb-ehci", @@ -150,12 +158,13 @@ static struct EHCIPCIInfo ehci_pci_info[] = { static void ehci_pci_register_types(void) { TypeInfo ehci_type_info = { - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(EHCIPCIState), - .class_init = ehci_class_init, + .parent = TYPE_PCI_EHCI, + .class_init = ehci_data_class_init, }; int i; + type_register_static(&ehci_pci_type_info); + for (i = 0; i < ARRAY_SIZE(ehci_pci_info); i++) { ehci_type_info.name = ehci_pci_info[i].name; ehci_type_info.class_data = ehci_pci_info + i; diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c index 803df92f31..d4311936ba 100644 --- a/hw/usb/hcd-ehci-sysbus.c +++ b/hw/usb/hcd-ehci-sysbus.c @@ -16,12 +16,6 @@ */ #include "hw/usb/hcd-ehci.h" -#include "hw/sysbus.h" - -typedef struct EHCISysBusState { - SysBusDevice busdev; - EHCIState ehci; -} EHCISysBusState; static const VMStateDescription vmstate_ehci_sysbus = { .name = "ehci-sysbus", @@ -40,7 +34,7 @@ static Property ehci_sysbus_properties[] = { static int usb_ehci_sysbus_initfn(SysBusDevice *dev) { - EHCISysBusState *i = FROM_SYSBUS(EHCISysBusState, dev); + EHCISysBusState *i = SYS_BUS_EHCI(dev); EHCIState *s = &i->ehci; s->capsbase = 0x100; @@ -63,15 +57,22 @@ static void ehci_sysbus_class_init(ObjectClass *klass, void *data) dc->props = ehci_sysbus_properties; } -TypeInfo ehci_xlnx_type_info = { - .name = "xlnx,ps7-usb", +static const TypeInfo ehci_type_info = { + .name = TYPE_SYS_BUS_EHCI, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(EHCISysBusState), + .abstract = true, .class_init = ehci_sysbus_class_init, }; +static const TypeInfo ehci_xlnx_type_info = { + .name = "xlnx,ps7-usb", + .parent = TYPE_SYS_BUS_EHCI, +}; + static void ehci_sysbus_register_types(void) { + type_register_static(&ehci_type_info); type_register_static(&ehci_xlnx_type_info); } diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index 14ee3bea5a..5ba3faf2b8 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -24,6 +24,8 @@ #include "trace.h" #include "sysemu/dma.h" #include "sysemu/sysemu.h" +#include "hw/pci/pci.h" +#include "hw/sysbus.h" #ifndef EHCI_DEBUG #define EHCI_DEBUG 0 @@ -322,4 +324,28 @@ extern const VMStateDescription vmstate_ehci; void usb_ehci_initfn(EHCIState *s, DeviceState *dev); +#define TYPE_PCI_EHCI "pci-ehci-usb" +#define PCI_EHCI(obj) OBJECT_CHECK(EHCIPCIState, (obj), TYPE_PCI_EHCI) + +typedef struct EHCIPCIState { + /*< private >*/ + PCIDevice pcidev; + /*< public >*/ + + EHCIState ehci; +} EHCIPCIState; + + +#define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb" +#define SYS_BUS_EHCI(obj) \ + OBJECT_CHECK(EHCISysBusState, (obj), TYPE_SYS_BUS_EHCI) + +typedef struct EHCISysBusState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + EHCIState ehci; +} EHCISysBusState; + #endif From 4a4343671e183824a3f5db76ad561ce01e6c6e0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 16 Dec 2012 04:49:44 +0100 Subject: [PATCH 2228/2270] usb/ehci: Move capsbase and opregbase into SysBus EHCI class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows specific derived models to use different values. Signed-off-by: Andreas Färber Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci-sysbus.c | 15 +++++++++++++-- hw/usb/hcd-ehci.h | 13 +++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c index d4311936ba..5a94ce31ef 100644 --- a/hw/usb/hcd-ehci-sysbus.c +++ b/hw/usb/hcd-ehci-sysbus.c @@ -35,10 +35,11 @@ static Property ehci_sysbus_properties[] = { static int usb_ehci_sysbus_initfn(SysBusDevice *dev) { EHCISysBusState *i = SYS_BUS_EHCI(dev); + SysBusEHCIClass *sec = SYS_BUS_EHCI_GET_CLASS(dev); EHCIState *s = &i->ehci; - s->capsbase = 0x100; - s->opregbase = 0x140; + s->capsbase = sec->capsbase; + s->opregbase = sec->opregbase; s->dma = &dma_context_memory; usb_ehci_initfn(s, DEVICE(dev)); @@ -63,11 +64,21 @@ static const TypeInfo ehci_type_info = { .instance_size = sizeof(EHCISysBusState), .abstract = true, .class_init = ehci_sysbus_class_init, + .class_size = sizeof(SysBusEHCIClass), }; +static void ehci_xlnx_class_init(ObjectClass *oc, void *data) +{ + SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc); + + sec->capsbase = 0x100; + sec->opregbase = 0x140; +} + static const TypeInfo ehci_xlnx_type_info = { .name = "xlnx,ps7-usb", .parent = TYPE_SYS_BUS_EHCI, + .class_init = ehci_xlnx_class_init, }; static void ehci_sysbus_register_types(void) diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index 5ba3faf2b8..2b0b5a17ab 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -339,6 +339,10 @@ typedef struct EHCIPCIState { #define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb" #define SYS_BUS_EHCI(obj) \ OBJECT_CHECK(EHCISysBusState, (obj), TYPE_SYS_BUS_EHCI) +#define SYS_BUS_EHCI_CLASS(class) \ + OBJECT_CLASS_CHECK(SysBusEHCIClass, (class), TYPE_SYS_BUS_EHCI) +#define SYS_BUS_EHCI_GET_CLASS(obj) \ + OBJECT_GET_CLASS(SysBusEHCIClass, (obj), TYPE_SYS_BUS_EHCI) typedef struct EHCISysBusState { /*< private >*/ @@ -348,4 +352,13 @@ typedef struct EHCISysBusState { EHCIState ehci; } EHCISysBusState; +typedef struct SysBusEHCIClass { + /*< private >*/ + SysBusDeviceClass parent_class; + /*< public >*/ + + uint16_t capsbase; + uint16_t opregbase; +} SysBusEHCIClass; + #endif From aee7499a59d6778c10b018da41db4a22655ef8a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 16 Dec 2012 04:49:45 +0100 Subject: [PATCH 2229/2270] usb/ehci: Add SysBus EHCI device for Exynos4210 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It uses a different capsbase and opregbase than the Xilinx device. Signed-off-by: Liming Wang Signed-off-by: Andreas Färber Cc: Igor Mitsyanko Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci-sysbus.c | 15 +++++++++++++++ hw/usb/hcd-ehci.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c index 5a94ce31ef..b68a66a63b 100644 --- a/hw/usb/hcd-ehci-sysbus.c +++ b/hw/usb/hcd-ehci-sysbus.c @@ -81,10 +81,25 @@ static const TypeInfo ehci_xlnx_type_info = { .class_init = ehci_xlnx_class_init, }; +static void ehci_exynos4210_class_init(ObjectClass *oc, void *data) +{ + SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc); + + sec->capsbase = 0x0; + sec->opregbase = 0x10; +} + +static const TypeInfo ehci_exynos4210_type_info = { + .name = TYPE_EXYNOS4210_EHCI, + .parent = TYPE_SYS_BUS_EHCI, + .class_init = ehci_exynos4210_class_init, +}; + static void ehci_sysbus_register_types(void) { type_register_static(&ehci_type_info); type_register_static(&ehci_xlnx_type_info); + type_register_static(&ehci_exynos4210_type_info); } type_init(ehci_sysbus_register_types) diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index 2b0b5a17ab..e95bb7ec46 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -337,6 +337,8 @@ typedef struct EHCIPCIState { #define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb" +#define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb" + #define SYS_BUS_EHCI(obj) \ OBJECT_CHECK(EHCISysBusState, (obj), TYPE_SYS_BUS_EHCI) #define SYS_BUS_EHCI_CLASS(class) \ From 358d615b6908b4916c74819ffad823cb4a74314e Mon Sep 17 00:00:00 2001 From: Liming Wang Date: Sun, 16 Dec 2012 04:49:46 +0100 Subject: [PATCH 2230/2270] exynos4210: Add EHCI support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add EHCI USB host controller to exynos4210. Signed-off-by: Liming Wang Signed-off-by: Andreas Färber Reviewed-by: Igor Mitsyanko Signed-off-by: Gerd Hoffmann --- hw/exynos4210.c | 7 +++++++ hw/exynos4210_gic.c | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/hw/exynos4210.c b/hw/exynos4210.c index a7b84d61a0..246a0fc1c3 100644 --- a/hw/exynos4210.c +++ b/hw/exynos4210.c @@ -27,6 +27,7 @@ #include "arm-misc.h" #include "loader.h" #include "exynos4210.h" +#include "usb/hcd-ehci.h" #define EXYNOS4210_CHIPID_ADDR 0x10000000 @@ -72,6 +73,9 @@ /* Display controllers (FIMD) */ #define EXYNOS4210_FIMD0_BASE_ADDR 0x11C00000 +/* EHCI */ +#define EXYNOS4210_EHCI_BASE_ADDR 0x12580000 + static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43, 0x09, 0x00, 0x00, 0x00 }; @@ -338,5 +342,8 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem, s->irq_table[exynos4210_get_irq(11, 2)], NULL); + sysbus_create_simple(TYPE_EXYNOS4210_EHCI, EXYNOS4210_EHCI_BASE_ADDR, + s->irq_table[exynos4210_get_irq(28, 3)]); + return s; } diff --git a/hw/exynos4210_gic.c b/hw/exynos4210_gic.c index 4fea09873a..959de5679d 100644 --- a/hw/exynos4210_gic.c +++ b/hw/exynos4210_gic.c @@ -140,7 +140,7 @@ combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = { EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6, EXT_GIC_ID_I2C7 }, /* int combiner group 28 */ - { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 }, + { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST}, /* int combiner group 29 */ { EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2, EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC }, From b2d1fe67d09d2b6c7da647fbcea6ca0148c206d3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 19 Dec 2012 15:08:33 +0100 Subject: [PATCH 2231/2270] usbredir: Add support for buffered bulk input (v2) Buffered bulk mode is intended for bulk *input* endpoints, where the data is of a streaming nature (not part of a command-response protocol). These endpoints' input buffer may overflow if data is not read quickly enough. So in buffered bulk mode the usb-host takes care of the submitting and re-submitting of bulk transfers. Buffered bulk mode is necessary for reliable operation with the bulk in endpoints of usb to serial convertors. Unfortunatelty buffered bulk input mode will only work with certain devices, therefor this patch also adds a usb-id table to enable it for devices which need it, while leaving the bulk ep handling for other devices unmodified. Note that the bumping of the required usbredir from 0.5.3 to 0.6 does not mean that we will now need a newer usbredir release then qemu-1.3, .pc files reporting 0.5.3 have only ever existed in usbredir builds directly from git, so qemu-1.3 needs the 0.6 release too. Changes in v2: -Split of quirk handling into quirks.c Signed-off-by: Hans de Goede --- configure | 2 +- hw/usb.h | 12 +- hw/usb/Makefile.objs | 2 +- hw/usb/quirks-ftdi-ids.h | 1255 ++++++++++++++++++++++++++++++++++++ hw/usb/quirks-pl2303-ids.h | 150 +++++ hw/usb/quirks.c | 53 ++ hw/usb/quirks.h | 910 ++++++++++++++++++++++++++ hw/usb/redirect.c | 355 +++++++++- 8 files changed, 2718 insertions(+), 21 deletions(-) create mode 100644 hw/usb/quirks-ftdi-ids.h create mode 100644 hw/usb/quirks-pl2303-ids.h create mode 100644 hw/usb/quirks.c create mode 100644 hw/usb/quirks.h diff --git a/configure b/configure index fe18ed2b25..82f6e71700 100755 --- a/configure +++ b/configure @@ -2851,7 +2851,7 @@ fi # check for usbredirparser for usb network redirection support if test "$usb_redir" != "no" ; then - if $pkg_config --atleast-version=0.5.3 libusbredirparser-0.5 >/dev/null 2>&1 ; then + if $pkg_config --atleast-version=0.6 libusbredirparser-0.5 >/dev/null 2>&1 ; then usb_redir="yes" usb_redir_cflags=$($pkg_config --cflags libusbredirparser-0.5 2>/dev/null) usb_redir_libs=$($pkg_config --libs libusbredirparser-0.5 2>/dev/null) diff --git a/hw/usb.h b/hw/usb.h index aca8ff6950..50c297f341 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -553,5 +553,15 @@ const USBDesc *usb_device_get_usb_desc(USBDevice *dev); int ehci_create_ich9_with_companions(PCIBus *bus, int slot); -#endif +/* quirks.c */ +/* In bulk endpoints are streaming data sources (iow behave like isoc eps) */ +#define USB_QUIRK_BUFFER_BULK_IN 0x01 +/* Bulk pkts in FTDI format, need special handling when combining packets */ +#define USB_QUIRK_IS_FTDI 0x02 + +int usb_get_quirks(uint16_t vendor_id, uint16_t product_id, + uint8_t interface_class, uint8_t interface_subclass, + uint8_t interface_protocol); + +#endif diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs index 5a4eeb6d13..dad4cb9f3c 100644 --- a/hw/usb/Makefile.objs +++ b/hw/usb/Makefile.objs @@ -5,7 +5,7 @@ common-obj-$(CONFIG_USB_XHCI) += hcd-xhci.o common-obj-y += libhw.o common-obj-$(CONFIG_SMARTCARD) += dev-smartcard-reader.o -common-obj-$(CONFIG_USB_REDIR) += redirect.o +common-obj-$(CONFIG_USB_REDIR) += redirect.o quirks.o common-obj-y += core.o combined-packet.o bus.o desc.o dev-hub.o common-obj-y += host-$(HOST_USB).o dev-bluetooth.o diff --git a/hw/usb/quirks-ftdi-ids.h b/hw/usb/quirks-ftdi-ids.h new file mode 100644 index 0000000000..57c12ef662 --- /dev/null +++ b/hw/usb/quirks-ftdi-ids.h @@ -0,0 +1,1255 @@ +/* + * vendor/product IDs (VID/PID) of devices using FTDI USB serial converters. + * Please keep numerically sorted within individual areas, thanks! + * + * Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais + * from Rudolf Gugler + * + */ + + +/**********************************/ +/***** devices using FTDI VID *****/ +/**********************************/ + + +#define FTDI_VID 0x0403 /* Vendor Id */ + + +/*** "original" FTDI device PIDs ***/ + +#define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */ +#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */ +#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */ +#define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */ +#define FTDI_232H_PID 0x6014 /* Single channel hi-speed device */ +#define FTDI_FTX_PID 0x6015 /* FT-X series (FT201X, FT230X, FT231X, etc) */ +#define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */ +#define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */ + + +/*** third-party PIDs (using FTDI_VID) ***/ + +#define FTDI_LUMEL_PD12_PID 0x6002 + +/* + * Marvell OpenRD Base, Client + * http://www.open-rd.org + * OpenRD Base, Client use VID 0x0403 + */ +#define MARVELL_OPENRD_PID 0x9e90 + +/* www.candapter.com Ewert Energy Systems CANdapter device */ +#define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */ + +/* + * Texas Instruments XDS100v2 JTAG / BeagleBone A3 + * http://processors.wiki.ti.com/index.php/XDS100 + * http://beagleboard.org/bone + */ +#define TI_XDS100V2_PID 0xa6d0 + +#define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */ + +/* US Interface Navigator (http://www.usinterface.com/) */ +#define FTDI_USINT_CAT_PID 0xb810 /* Navigator CAT and 2nd PTT lines */ +#define FTDI_USINT_WKEY_PID 0xb811 /* Navigator WKEY and FSK lines */ +#define FTDI_USINT_RS232_PID 0xb812 /* Navigator RS232 and CONFIG lines */ + +/* OOCDlink by Joern Kaipf + * (http://www.joernonline.de/) */ +#define FTDI_OOCDLINK_PID 0xbaf8 /* Amontec JTAGkey */ + +/* Luminary Micro Stellaris Boards, VID = FTDI_VID */ +/* FTDI 2332C Dual channel device, side A=245 FIFO (JTAG), Side B=RS232 UART */ +#define LMI_LM3S_DEVEL_BOARD_PID 0xbcd8 +#define LMI_LM3S_EVAL_BOARD_PID 0xbcd9 +#define LMI_LM3S_ICDI_BOARD_PID 0xbcda + +#define FTDI_TURTELIZER_PID 0xBDC8 /* JTAG/RS-232 adapter by egnite GmbH */ + +/* OpenDCC (www.opendcc.de) product id */ +#define FTDI_OPENDCC_PID 0xBFD8 +#define FTDI_OPENDCC_SNIFFER_PID 0xBFD9 +#define FTDI_OPENDCC_THROTTLE_PID 0xBFDA +#define FTDI_OPENDCC_GATEWAY_PID 0xBFDB +#define FTDI_OPENDCC_GBM_PID 0xBFDC + +/* NZR SEM 16+ USB (http://www.nzr.de) */ +#define FTDI_NZR_SEM_USB_PID 0xC1E0 /* NZR SEM-LOG16+ */ + +/* + * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com) + */ +#define FTDI_RRCIRKITS_LOCOBUFFER_PID 0xc7d0 /* LocoBuffer USB */ + +/* DMX4ALL DMX Interfaces */ +#define FTDI_DMX4ALL 0xC850 + +/* + * ASK.fr devices + */ +#define FTDI_ASK_RDR400_PID 0xC991 /* ASK RDR 400 series card reader */ + +/* www.starting-point-systems.com µChameleon device */ +#define FTDI_MICRO_CHAMELEON_PID 0xCAA0 /* Product Id */ + +/* + * Tactrix OpenPort (ECU) devices. + * OpenPort 1.3M submitted by Donour Sizemore. + * OpenPort 1.3S and 1.3U submitted by Ian Abbott. + */ +#define FTDI_TACTRIX_OPENPORT_13M_PID 0xCC48 /* OpenPort 1.3 Mitsubishi */ +#define FTDI_TACTRIX_OPENPORT_13S_PID 0xCC49 /* OpenPort 1.3 Subaru */ +#define FTDI_TACTRIX_OPENPORT_13U_PID 0xCC4A /* OpenPort 1.3 Universal */ + +#define FTDI_DISTORTEC_JTAG_LOCK_PICK_PID 0xCFF8 + +/* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */ +/* the VID is the standard ftdi vid (FTDI_VID) */ +#define FTDI_SCS_DEVICE_0_PID 0xD010 /* SCS PTC-IIusb */ +#define FTDI_SCS_DEVICE_1_PID 0xD011 /* SCS Tracker / DSP TNC */ +#define FTDI_SCS_DEVICE_2_PID 0xD012 +#define FTDI_SCS_DEVICE_3_PID 0xD013 +#define FTDI_SCS_DEVICE_4_PID 0xD014 +#define FTDI_SCS_DEVICE_5_PID 0xD015 +#define FTDI_SCS_DEVICE_6_PID 0xD016 +#define FTDI_SCS_DEVICE_7_PID 0xD017 + +/* iPlus device */ +#define FTDI_IPLUS_PID 0xD070 /* Product Id */ +#define FTDI_IPLUS2_PID 0xD071 /* Product Id */ + +/* + * Gamma Scout (http://gamma-scout.com/). Submitted by rsc@runtux.com. + */ +#define FTDI_GAMMA_SCOUT_PID 0xD678 /* Gamma Scout online */ + +/* Propox devices */ +#define FTDI_PROPOX_JTAGCABLEII_PID 0xD738 +#define FTDI_PROPOX_ISPCABLEIII_PID 0xD739 + +/* Lenz LI-USB Computer Interface. */ +#define FTDI_LENZ_LIUSB_PID 0xD780 + +/* Vardaan Enterprises Serial Interface VEUSB422R3 */ +#define FTDI_VARDAAN_PID 0xF070 + +/* + * Xsens Technologies BV products (http://www.xsens.com). + */ +#define XSENS_CONVERTER_0_PID 0xD388 +#define XSENS_CONVERTER_1_PID 0xD389 +#define XSENS_CONVERTER_2_PID 0xD38A +#define XSENS_CONVERTER_3_PID 0xD38B +#define XSENS_CONVERTER_4_PID 0xD38C +#define XSENS_CONVERTER_5_PID 0xD38D +#define XSENS_CONVERTER_6_PID 0xD38E +#define XSENS_CONVERTER_7_PID 0xD38F + +/* + * NDI (www.ndigital.com) product ids + */ +#define FTDI_NDI_HUC_PID 0xDA70 /* NDI Host USB Converter */ +#define FTDI_NDI_SPECTRA_SCU_PID 0xDA71 /* NDI Spectra SCU */ +#define FTDI_NDI_FUTURE_2_PID 0xDA72 /* NDI future device #2 */ +#define FTDI_NDI_FUTURE_3_PID 0xDA73 /* NDI future device #3 */ +#define FTDI_NDI_AURORA_SCU_PID 0xDA74 /* NDI Aurora SCU */ + +/* + * ChamSys Limited (www.chamsys.co.uk) USB wing/interface product IDs + */ +#define FTDI_CHAMSYS_24_MASTER_WING_PID 0xDAF8 +#define FTDI_CHAMSYS_PC_WING_PID 0xDAF9 +#define FTDI_CHAMSYS_USB_DMX_PID 0xDAFA +#define FTDI_CHAMSYS_MIDI_TIMECODE_PID 0xDAFB +#define FTDI_CHAMSYS_MINI_WING_PID 0xDAFC +#define FTDI_CHAMSYS_MAXI_WING_PID 0xDAFD +#define FTDI_CHAMSYS_MEDIA_WING_PID 0xDAFE +#define FTDI_CHAMSYS_WING_PID 0xDAFF + +/* + * Westrex International devices submitted by Cory Lee + */ +#define FTDI_WESTREX_MODEL_777_PID 0xDC00 /* Model 777 */ +#define FTDI_WESTREX_MODEL_8900F_PID 0xDC01 /* Model 8900F */ + +/* + * ACG Identification Technologies GmbH products (http://www.acg.de/). + * Submitted by anton -at- goto10 -dot- org. + */ +#define FTDI_ACG_HFDUAL_PID 0xDD20 /* HF Dual ISO Reader (RFID) */ + +/* + * Definitions for Artemis astronomical USB based cameras + * Check it at http://www.artemisccd.co.uk/ + */ +#define FTDI_ARTEMIS_PID 0xDF28 /* All Artemis Cameras */ + +/* + * Definitions for ATIK Instruments astronomical USB based cameras + * Check it at http://www.atik-instruments.com/ + */ +#define FTDI_ATIK_ATK16_PID 0xDF30 /* ATIK ATK-16 Grayscale Camera */ +#define FTDI_ATIK_ATK16C_PID 0xDF32 /* ATIK ATK-16C Colour Camera */ +#define FTDI_ATIK_ATK16HR_PID 0xDF31 /* ATIK ATK-16HR Grayscale Camera */ +#define FTDI_ATIK_ATK16HRC_PID 0xDF33 /* ATIK ATK-16HRC Colour Camera */ +#define FTDI_ATIK_ATK16IC_PID 0xDF35 /* ATIK ATK-16IC Grayscale Camera */ + +/* + * Yost Engineering, Inc. products (www.yostengineering.com). + * PID 0xE050 submitted by Aaron Prose. + */ +#define FTDI_YEI_SERVOCENTER31_PID 0xE050 /* YEI ServoCenter3.1 USB */ + +/* + * ELV USB devices submitted by Christian Abt of ELV (www.elv.de). + * All of these devices use FTDI's vendor ID (0x0403). + * Further IDs taken from ELV Windows .inf file. + * + * The previously included PID for the UO 100 module was incorrect. + * In fact, that PID was for ELV's UR 100 USB-RS232 converter (0xFB58). + * + * Armin Laeuger originally sent the PID for the UM 100 module. + */ +#define FTDI_ELV_USR_PID 0xE000 /* ELV Universal-Sound-Recorder */ +#define FTDI_ELV_MSM1_PID 0xE001 /* ELV Mini-Sound-Modul */ +#define FTDI_ELV_KL100_PID 0xE002 /* ELV Kfz-Leistungsmesser KL 100 */ +#define FTDI_ELV_WS550_PID 0xE004 /* WS 550 */ +#define FTDI_ELV_EC3000_PID 0xE006 /* ENERGY CONTROL 3000 USB */ +#define FTDI_ELV_WS888_PID 0xE008 /* WS 888 */ +#define FTDI_ELV_TWS550_PID 0xE009 /* Technoline WS 550 */ +#define FTDI_ELV_FEM_PID 0xE00A /* Funk Energie Monitor */ +#define FTDI_ELV_FHZ1300PC_PID 0xE0E8 /* FHZ 1300 PC */ +#define FTDI_ELV_WS500_PID 0xE0E9 /* PC-Wetterstation (WS 500) */ +#define FTDI_ELV_HS485_PID 0xE0EA /* USB to RS-485 adapter */ +#define FTDI_ELV_UMS100_PID 0xE0EB /* ELV USB Master-Slave Schaltsteckdose UMS 100 */ +#define FTDI_ELV_TFD128_PID 0xE0EC /* ELV Temperatur-Feuchte-Datenlogger TFD 128 */ +#define FTDI_ELV_FM3RX_PID 0xE0ED /* ELV Messwertuebertragung FM3 RX */ +#define FTDI_ELV_WS777_PID 0xE0EE /* Conrad WS 777 */ +#define FTDI_ELV_EM1010PC_PID 0xE0EF /* Energy monitor EM 1010 PC */ +#define FTDI_ELV_CSI8_PID 0xE0F0 /* Computer-Schalt-Interface (CSI 8) */ +#define FTDI_ELV_EM1000DL_PID 0xE0F1 /* PC-Datenlogger fuer Energiemonitor (EM 1000 DL) */ +#define FTDI_ELV_PCK100_PID 0xE0F2 /* PC-Kabeltester (PCK 100) */ +#define FTDI_ELV_RFP500_PID 0xE0F3 /* HF-Leistungsmesser (RFP 500) */ +#define FTDI_ELV_FS20SIG_PID 0xE0F4 /* Signalgeber (FS 20 SIG) */ +#define FTDI_ELV_UTP8_PID 0xE0F5 /* ELV UTP 8 */ +#define FTDI_ELV_WS300PC_PID 0xE0F6 /* PC-Wetterstation (WS 300 PC) */ +#define FTDI_ELV_WS444PC_PID 0xE0F7 /* Conrad WS 444 PC */ +#define FTDI_PHI_FISCO_PID 0xE40B /* PHI Fisco USB to Serial cable */ +#define FTDI_ELV_UAD8_PID 0xF068 /* USB-AD-Wandler (UAD 8) */ +#define FTDI_ELV_UDA7_PID 0xF069 /* USB-DA-Wandler (UDA 7) */ +#define FTDI_ELV_USI2_PID 0xF06A /* USB-Schrittmotoren-Interface (USI 2) */ +#define FTDI_ELV_T1100_PID 0xF06B /* Thermometer (T 1100) */ +#define FTDI_ELV_PCD200_PID 0xF06C /* PC-Datenlogger (PCD 200) */ +#define FTDI_ELV_ULA200_PID 0xF06D /* USB-LCD-Ansteuerung (ULA 200) */ +#define FTDI_ELV_ALC8500_PID 0xF06E /* ALC 8500 Expert */ +#define FTDI_ELV_FHZ1000PC_PID 0xF06F /* FHZ 1000 PC */ +#define FTDI_ELV_UR100_PID 0xFB58 /* USB-RS232-Umsetzer (UR 100) */ +#define FTDI_ELV_UM100_PID 0xFB5A /* USB-Modul UM 100 */ +#define FTDI_ELV_UO100_PID 0xFB5B /* USB-Modul UO 100 */ +/* Additional ELV PIDs that default to using the FTDI D2XX drivers on + * MS Windows, rather than the FTDI Virtual Com Port drivers. + * Maybe these will be easier to use with the libftdi/libusb user-space + * drivers, or possibly the Comedi drivers in some cases. */ +#define FTDI_ELV_CLI7000_PID 0xFB59 /* Computer-Light-Interface (CLI 7000) */ +#define FTDI_ELV_PPS7330_PID 0xFB5C /* Processor-Power-Supply (PPS 7330) */ +#define FTDI_ELV_TFM100_PID 0xFB5D /* Temperatur-Feuchte-Messgeraet (TFM 100) */ +#define FTDI_ELV_UDF77_PID 0xFB5E /* USB DCF Funkuhr (UDF 77) */ +#define FTDI_ELV_UIO88_PID 0xFB5F /* USB-I/O Interface (UIO 88) */ + +/* + * EVER Eco Pro UPS (http://www.ever.com.pl/) + */ + +#define EVER_ECO_PRO_CDS 0xe520 /* RS-232 converter */ + +/* + * Active Robots product ids. + */ +#define FTDI_ACTIVE_ROBOTS_PID 0xE548 /* USB comms board */ + +/* Pyramid Computer GmbH */ +#define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */ + +/* www.elsterelectricity.com Elster Unicom III Optical Probe */ +#define FTDI_ELSTER_UNICOM_PID 0xE700 /* Product Id */ + +/* + * Gude Analog- und Digitalsysteme GmbH + */ +#define FTDI_GUDEADS_E808_PID 0xE808 +#define FTDI_GUDEADS_E809_PID 0xE809 +#define FTDI_GUDEADS_E80A_PID 0xE80A +#define FTDI_GUDEADS_E80B_PID 0xE80B +#define FTDI_GUDEADS_E80C_PID 0xE80C +#define FTDI_GUDEADS_E80D_PID 0xE80D +#define FTDI_GUDEADS_E80E_PID 0xE80E +#define FTDI_GUDEADS_E80F_PID 0xE80F +#define FTDI_GUDEADS_E888_PID 0xE888 /* Expert ISDN Control USB */ +#define FTDI_GUDEADS_E889_PID 0xE889 /* USB RS-232 OptoBridge */ +#define FTDI_GUDEADS_E88A_PID 0xE88A +#define FTDI_GUDEADS_E88B_PID 0xE88B +#define FTDI_GUDEADS_E88C_PID 0xE88C +#define FTDI_GUDEADS_E88D_PID 0xE88D +#define FTDI_GUDEADS_E88E_PID 0xE88E +#define FTDI_GUDEADS_E88F_PID 0xE88F + +/* + * Eclo (http://www.eclo.pt/) product IDs. + * PID 0xEA90 submitted by Martin Grill. + */ +#define FTDI_ECLO_COM_1WIRE_PID 0xEA90 /* COM to 1-Wire USB adaptor */ + +/* TNC-X USB-to-packet-radio adapter, versions prior to 3.0 (DLP module) */ +#define FTDI_TNC_X_PID 0xEBE0 + +/* + * Teratronik product ids. + * Submitted by O. Wölfelschneider. + */ +#define FTDI_TERATRONIK_VCP_PID 0xEC88 /* Teratronik device (preferring VCP driver on windows) */ +#define FTDI_TERATRONIK_D2XX_PID 0xEC89 /* Teratronik device (preferring D2XX driver on windows) */ + +/* Rig Expert Ukraine devices */ +#define FTDI_REU_TINY_PID 0xED22 /* RigExpert Tiny */ + +/* + * Hameg HO820 and HO870 interface (using VID 0x0403) + */ +#define HAMEG_HO820_PID 0xed74 +#define HAMEG_HO730_PID 0xed73 +#define HAMEG_HO720_PID 0xed72 +#define HAMEG_HO870_PID 0xed71 + +/* + * MaxStream devices www.maxstream.net + */ +#define FTDI_MAXSTREAM_PID 0xEE18 /* Xbee PKG-U Module */ + +/* + * microHAM product IDs (http://www.microham.com). + * Submitted by Justin Burket (KL1RL) + * and Mike Studer (K6EEP) . + * Ian Abbott added a few more from the driver INF file. + */ +#define FTDI_MHAM_KW_PID 0xEEE8 /* USB-KW interface */ +#define FTDI_MHAM_YS_PID 0xEEE9 /* USB-YS interface */ +#define FTDI_MHAM_Y6_PID 0xEEEA /* USB-Y6 interface */ +#define FTDI_MHAM_Y8_PID 0xEEEB /* USB-Y8 interface */ +#define FTDI_MHAM_IC_PID 0xEEEC /* USB-IC interface */ +#define FTDI_MHAM_DB9_PID 0xEEED /* USB-DB9 interface */ +#define FTDI_MHAM_RS232_PID 0xEEEE /* USB-RS232 interface */ +#define FTDI_MHAM_Y9_PID 0xEEEF /* USB-Y9 interface */ + +/* Domintell products http://www.domintell.com */ +#define FTDI_DOMINTELL_DGQG_PID 0xEF50 /* Master */ +#define FTDI_DOMINTELL_DUSB_PID 0xEF51 /* DUSB01 module */ + +/* + * The following are the values for the Perle Systems + * UltraPort USB serial converters + */ +#define FTDI_PERLE_ULTRAPORT_PID 0xF0C0 /* Perle UltraPort Product Id */ + +/* Sprog II (Andrew Crosland's SprogII DCC interface) */ +#define FTDI_SPROG_II 0xF0C8 + +/* an infrared receiver for user access control with IR tags */ +#define FTDI_PIEGROUP_PID 0xF208 /* Product Id */ + +/* ACT Solutions HomePro ZWave interface + (http://www.act-solutions.com/HomePro-Product-Matrix.html) */ +#define FTDI_ACTZWAVE_PID 0xF2D0 + +/* + * 4N-GALAXY.DE PIDs for CAN-USB, USB-RS232, USB-RS422, USB-RS485, + * USB-TTY aktiv, USB-TTY passiv. Some PIDs are used by several devices + * and I'm not entirely sure which are used by which. + */ +#define FTDI_4N_GALAXY_DE_1_PID 0xF3C0 +#define FTDI_4N_GALAXY_DE_2_PID 0xF3C1 +#define FTDI_4N_GALAXY_DE_3_PID 0xF3C2 + +/* + * Linx Technologies product ids + */ +#define LINX_SDMUSBQSS_PID 0xF448 /* Linx SDM-USB-QS-S */ +#define LINX_MASTERDEVEL2_PID 0xF449 /* Linx Master Development 2.0 */ +#define LINX_FUTURE_0_PID 0xF44A /* Linx future device */ +#define LINX_FUTURE_1_PID 0xF44B /* Linx future device */ +#define LINX_FUTURE_2_PID 0xF44C /* Linx future device */ + +/* + * Oceanic product ids + */ +#define FTDI_OCEANIC_PID 0xF460 /* Oceanic dive instrument */ + +/* + * SUUNTO product ids + */ +#define FTDI_SUUNTO_SPORTS_PID 0xF680 /* Suunto Sports instrument */ + +/* USB-UIRT - An infrared receiver and transmitter using the 8U232AM chip */ +/* http://www.usbuirt.com/ */ +#define FTDI_USB_UIRT_PID 0xF850 /* Product Id */ + +/* CCS Inc. ICDU/ICDU40 product ID - + * the FT232BM is used in an in-circuit-debugger unit for PIC16's/PIC18's */ +#define FTDI_CCSICDU20_0_PID 0xF9D0 +#define FTDI_CCSICDU40_1_PID 0xF9D1 +#define FTDI_CCSMACHX_2_PID 0xF9D2 +#define FTDI_CCSLOAD_N_GO_3_PID 0xF9D3 +#define FTDI_CCSICDU64_4_PID 0xF9D4 +#define FTDI_CCSPRIME8_5_PID 0xF9D5 + +/* + * The following are the values for the Matrix Orbital LCD displays, + * which are the FT232BM ( similar to the 8U232AM ) + */ +#define FTDI_MTXORB_0_PID 0xFA00 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_1_PID 0xFA01 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_2_PID 0xFA02 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_3_PID 0xFA03 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_4_PID 0xFA04 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_5_PID 0xFA05 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_6_PID 0xFA06 /* Matrix Orbital Product Id */ + +/* + * Home Electronics (www.home-electro.com) USB gadgets + */ +#define FTDI_HE_TIRA1_PID 0xFA78 /* Tira-1 IR transceiver */ + +/* Inside Accesso contactless reader (http://www.insidecontactless.com/) */ +#define INSIDE_ACCESSO 0xFAD0 + +/* + * ThorLabs USB motor drivers + */ +#define FTDI_THORLABS_PID 0xfaf0 /* ThorLabs USB motor drivers */ + +/* + * Protego product ids + */ +#define PROTEGO_SPECIAL_1 0xFC70 /* special/unknown device */ +#define PROTEGO_R2X0 0xFC71 /* R200-USB TRNG unit (R210, R220, and R230) */ +#define PROTEGO_SPECIAL_3 0xFC72 /* special/unknown device */ +#define PROTEGO_SPECIAL_4 0xFC73 /* special/unknown device */ + +/* + * Sony Ericsson product ids + */ +#define FTDI_DSS20_PID 0xFC82 /* DSS-20 Sync Station for Sony Ericsson P800 */ +#define FTDI_URBAN_0_PID 0xFC8A /* Sony Ericsson Urban, uart #0 */ +#define FTDI_URBAN_1_PID 0xFC8B /* Sony Ericsson Urban, uart #1 */ + +/* www.irtrans.de device */ +#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */ + +/* + * RM Michaelides CANview USB (http://www.rmcan.com) (FTDI_VID) + * CAN fieldbus interface adapter, added by port GmbH www.port.de) + * Ian Abbott changed the macro names for consistency. + */ +#define FTDI_RM_CANVIEW_PID 0xfd60 /* Product Id */ +/* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */ +#define FTDI_TTUSB_PID 0xFF20 /* Product Id */ + +#define FTDI_USBX_707_PID 0xF857 /* ADSTech IR Blaster USBX-707 (FTDI_VID) */ + +#define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */ + +/* + * PCDJ use ftdi based dj-controllers. The following PID is + * for their DAC-2 device http://www.pcdjhardware.com/DAC2.asp + * (the VID is the standard ftdi vid (FTDI_VID), PID sent by Wouter Paesen) + */ +#define FTDI_PCDJ_DAC2_PID 0xFA88 + +#define FTDI_R2000KU_TRUE_RNG 0xFB80 /* R2000KU TRUE RNG (FTDI_VID) */ + +/* + * DIEBOLD BCS SE923 (FTDI_VID) + */ +#define DIEBOLD_BCS_SE923_PID 0xfb99 + +/* www.crystalfontz.com devices + * - thanx for providing free devices for evaluation ! + * they use the ftdi chipset for the USB interface + * and the vendor id is the same + */ +#define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */ +#define FTDI_XF_634_PID 0xFC09 /* 634: 20x4 Character Display */ +#define FTDI_XF_547_PID 0xFC0A /* 547: Two line Display */ +#define FTDI_XF_633_PID 0xFC0B /* 633: 16x2 Character Display with Keys */ +#define FTDI_XF_631_PID 0xFC0C /* 631: 20x2 Character Display */ +#define FTDI_XF_635_PID 0xFC0D /* 635: 20x4 Character Display */ +#define FTDI_XF_640_PID 0xFC0E /* 640: Two line Display */ +#define FTDI_XF_642_PID 0xFC0F /* 642: Two line Display */ + +/* + * Video Networks Limited / Homechoice in the UK use an ftdi-based device + * for their 1Mb broadband internet service. The following PID is exhibited + * by the usb device supplied (the VID is the standard ftdi vid (FTDI_VID) + */ +#define FTDI_VNHCPCUSB_D_PID 0xfe38 /* Product Id */ + +/* AlphaMicro Components AMC-232USB01 device (FTDI_VID) */ +#define FTDI_AMC232_PID 0xFF00 /* Product Id */ + +/* + * IBS elektronik product ids (FTDI_VID) + * Submitted by Thomas Schleusener + */ +#define FTDI_IBS_US485_PID 0xff38 /* IBS US485 (USB<-->RS422/485 interface) */ +#define FTDI_IBS_PICPRO_PID 0xff39 /* IBS PIC-Programmer */ +#define FTDI_IBS_PCMCIA_PID 0xff3a /* IBS Card reader for PCMCIA SRAM-cards */ +#define FTDI_IBS_PK1_PID 0xff3b /* IBS PK1 - Particel counter */ +#define FTDI_IBS_RS232MON_PID 0xff3c /* IBS RS232 - Monitor */ +#define FTDI_IBS_APP70_PID 0xff3d /* APP 70 (dust monitoring system) */ +#define FTDI_IBS_PEDO_PID 0xff3e /* IBS PEDO-Modem (RF modem 868.35 MHz) */ +#define FTDI_IBS_PROD_PID 0xff3f /* future device */ +/* www.canusb.com Lawicel CANUSB device (FTDI_VID) */ +#define FTDI_CANUSB_PID 0xFFA8 /* Product Id */ + +/* + * TavIR AVR product ids (FTDI_VID) + */ +#define FTDI_TAVIR_STK500_PID 0xFA33 /* STK500 AVR programmer */ + +/* + * TIAO product ids (FTDI_VID) + * http://www.tiaowiki.com/w/Main_Page + */ +#define FTDI_TIAO_UMPA_PID 0x8a98 /* TIAO/DIYGADGET USB Multi-Protocol Adapter */ + + +/********************************/ +/** third-party VID/PID combos **/ +/********************************/ + + + +/* + * Atmel STK541 + */ +#define ATMEL_VID 0x03eb /* Vendor ID */ +#define STK541_PID 0x2109 /* Zigbee Controller */ + +/* + * Blackfin gnICE JTAG + * http://docs.blackfin.uclinux.org/doku.php?id=hw:jtag:gnice + */ +#define ADI_VID 0x0456 +#define ADI_GNICE_PID 0xF000 +#define ADI_GNICEPLUS_PID 0xF001 + +/* + * Microchip Technology, Inc. + * + * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are + * used by single function CDC ACM class based firmware demo + * applications. The VID/PID has also been used in firmware + * emulating FTDI serial chips by: + * Hornby Elite - Digital Command Control Console + * http://www.hornby.com/hornby-dcc/controllers/ + */ +#define MICROCHIP_VID 0x04D8 +#define MICROCHIP_USB_BOARD_PID 0x000A /* CDC RS-232 Emulation Demo */ + +/* + * RATOC REX-USB60F + */ +#define RATOC_VENDOR_ID 0x0584 +#define RATOC_PRODUCT_ID_USB60F 0xb020 + +/* + * Acton Research Corp. + */ +#define ACTON_VID 0x0647 /* Vendor ID */ +#define ACTON_SPECTRAPRO_PID 0x0100 + +/* + * Contec products (http://www.contec.com) + * Submitted by Daniel Sangorrin + */ +#define CONTEC_VID 0x06CE /* Vendor ID */ +#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */ + +/* + * Definitions for B&B Electronics products. + */ +#define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */ +#define BANDB_USOTL4_PID 0xAC01 /* USOTL4 Isolated RS-485 Converter */ +#define BANDB_USTL4_PID 0xAC02 /* USTL4 RS-485 Converter */ +#define BANDB_USO9ML2_PID 0xAC03 /* USO9ML2 Isolated RS-232 Converter */ +#define BANDB_USOPTL4_PID 0xAC11 +#define BANDB_USPTL4_PID 0xAC12 +#define BANDB_USO9ML2DR_2_PID 0xAC16 +#define BANDB_USO9ML2DR_PID 0xAC17 +#define BANDB_USOPTL4DR2_PID 0xAC18 /* USOPTL4R-2 2-port Isolated RS-232 Converter */ +#define BANDB_USOPTL4DR_PID 0xAC19 +#define BANDB_485USB9F_2W_PID 0xAC25 +#define BANDB_485USB9F_4W_PID 0xAC26 +#define BANDB_232USB9M_PID 0xAC27 +#define BANDB_485USBTB_2W_PID 0xAC33 +#define BANDB_485USBTB_4W_PID 0xAC34 +#define BANDB_TTL5USB9M_PID 0xAC49 +#define BANDB_TTL3USB9M_PID 0xAC50 +#define BANDB_ZZ_PROG1_USB_PID 0xBA02 + +/* + * Intrepid Control Systems (http://www.intrepidcs.com/) ValueCAN and NeoVI + */ +#define INTREPID_VID 0x093C +#define INTREPID_VALUECAN_PID 0x0601 +#define INTREPID_NEOVI_PID 0x0701 + +/* + * Definitions for ID TECH (www.idt-net.com) devices + */ +#define IDTECH_VID 0x0ACD /* ID TECH Vendor ID */ +#define IDTECH_IDT1221U_PID 0x0300 /* IDT1221U USB to RS-232 adapter */ + +/* + * Definitions for Omnidirectional Control Technology, Inc. devices + */ +#define OCT_VID 0x0B39 /* OCT vendor ID */ +/* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */ +/* Also rebadged as Dick Smith Electronics (Aus) XH6451 */ +/* Also rebadged as SIIG Inc. model US2308 hardware version 1 */ +#define OCT_DK201_PID 0x0103 /* OCT DK201 USB docking station */ +#define OCT_US101_PID 0x0421 /* OCT US101 USB to RS-232 */ + +/* + * Definitions for Icom Inc. devices + */ +#define ICOM_VID 0x0C26 /* Icom vendor ID */ +/* Note: ID-1 is a communications tranceiver for HAM-radio operators */ +#define ICOM_ID_1_PID 0x0004 /* ID-1 USB to RS-232 */ +/* Note: OPC is an Optional cable to connect an Icom Tranceiver */ +#define ICOM_OPC_U_UC_PID 0x0018 /* OPC-478UC, OPC-1122U cloning cable */ +/* Note: ID-RP* devices are Icom Repeater Devices for HAM-radio */ +#define ICOM_ID_RP2C1_PID 0x0009 /* ID-RP2C Asset 1 to RS-232 */ +#define ICOM_ID_RP2C2_PID 0x000A /* ID-RP2C Asset 2 to RS-232 */ +#define ICOM_ID_RP2D_PID 0x000B /* ID-RP2D configuration port*/ +#define ICOM_ID_RP2VT_PID 0x000C /* ID-RP2V Transmit config port */ +#define ICOM_ID_RP2VR_PID 0x000D /* ID-RP2V Receive config port */ +#define ICOM_ID_RP4KVT_PID 0x0010 /* ID-RP4000V Transmit config port */ +#define ICOM_ID_RP4KVR_PID 0x0011 /* ID-RP4000V Receive config port */ +#define ICOM_ID_RP2KVT_PID 0x0012 /* ID-RP2000V Transmit config port */ +#define ICOM_ID_RP2KVR_PID 0x0013 /* ID-RP2000V Receive config port */ + +/* + * GN Otometrics (http://www.otometrics.com) + * Submitted by Ville Sundberg. + */ +#define GN_OTOMETRICS_VID 0x0c33 /* Vendor ID */ +#define AURICAL_USB_PID 0x0010 /* Aurical USB Audiometer */ + +/* + * The following are the values for the Sealevel SeaLINK+ adapters. + * (Original list sent by Tuan Hoang. Ian Abbott renamed the macros and + * removed some PIDs that don't seem to match any existing products.) + */ +#define SEALEVEL_VID 0x0c52 /* Sealevel Vendor ID */ +#define SEALEVEL_2101_PID 0x2101 /* SeaLINK+232 (2101/2105) */ +#define SEALEVEL_2102_PID 0x2102 /* SeaLINK+485 (2102) */ +#define SEALEVEL_2103_PID 0x2103 /* SeaLINK+232I (2103) */ +#define SEALEVEL_2104_PID 0x2104 /* SeaLINK+485I (2104) */ +#define SEALEVEL_2106_PID 0x9020 /* SeaLINK+422 (2106) */ +#define SEALEVEL_2201_1_PID 0x2211 /* SeaPORT+2/232 (2201) Port 1 */ +#define SEALEVEL_2201_2_PID 0x2221 /* SeaPORT+2/232 (2201) Port 2 */ +#define SEALEVEL_2202_1_PID 0x2212 /* SeaPORT+2/485 (2202) Port 1 */ +#define SEALEVEL_2202_2_PID 0x2222 /* SeaPORT+2/485 (2202) Port 2 */ +#define SEALEVEL_2203_1_PID 0x2213 /* SeaPORT+2 (2203) Port 1 */ +#define SEALEVEL_2203_2_PID 0x2223 /* SeaPORT+2 (2203) Port 2 */ +#define SEALEVEL_2401_1_PID 0x2411 /* SeaPORT+4/232 (2401) Port 1 */ +#define SEALEVEL_2401_2_PID 0x2421 /* SeaPORT+4/232 (2401) Port 2 */ +#define SEALEVEL_2401_3_PID 0x2431 /* SeaPORT+4/232 (2401) Port 3 */ +#define SEALEVEL_2401_4_PID 0x2441 /* SeaPORT+4/232 (2401) Port 4 */ +#define SEALEVEL_2402_1_PID 0x2412 /* SeaPORT+4/485 (2402) Port 1 */ +#define SEALEVEL_2402_2_PID 0x2422 /* SeaPORT+4/485 (2402) Port 2 */ +#define SEALEVEL_2402_3_PID 0x2432 /* SeaPORT+4/485 (2402) Port 3 */ +#define SEALEVEL_2402_4_PID 0x2442 /* SeaPORT+4/485 (2402) Port 4 */ +#define SEALEVEL_2403_1_PID 0x2413 /* SeaPORT+4 (2403) Port 1 */ +#define SEALEVEL_2403_2_PID 0x2423 /* SeaPORT+4 (2403) Port 2 */ +#define SEALEVEL_2403_3_PID 0x2433 /* SeaPORT+4 (2403) Port 3 */ +#define SEALEVEL_2403_4_PID 0x2443 /* SeaPORT+4 (2403) Port 4 */ +#define SEALEVEL_2801_1_PID 0X2811 /* SeaLINK+8/232 (2801) Port 1 */ +#define SEALEVEL_2801_2_PID 0X2821 /* SeaLINK+8/232 (2801) Port 2 */ +#define SEALEVEL_2801_3_PID 0X2831 /* SeaLINK+8/232 (2801) Port 3 */ +#define SEALEVEL_2801_4_PID 0X2841 /* SeaLINK+8/232 (2801) Port 4 */ +#define SEALEVEL_2801_5_PID 0X2851 /* SeaLINK+8/232 (2801) Port 5 */ +#define SEALEVEL_2801_6_PID 0X2861 /* SeaLINK+8/232 (2801) Port 6 */ +#define SEALEVEL_2801_7_PID 0X2871 /* SeaLINK+8/232 (2801) Port 7 */ +#define SEALEVEL_2801_8_PID 0X2881 /* SeaLINK+8/232 (2801) Port 8 */ +#define SEALEVEL_2802_1_PID 0X2812 /* SeaLINK+8/485 (2802) Port 1 */ +#define SEALEVEL_2802_2_PID 0X2822 /* SeaLINK+8/485 (2802) Port 2 */ +#define SEALEVEL_2802_3_PID 0X2832 /* SeaLINK+8/485 (2802) Port 3 */ +#define SEALEVEL_2802_4_PID 0X2842 /* SeaLINK+8/485 (2802) Port 4 */ +#define SEALEVEL_2802_5_PID 0X2852 /* SeaLINK+8/485 (2802) Port 5 */ +#define SEALEVEL_2802_6_PID 0X2862 /* SeaLINK+8/485 (2802) Port 6 */ +#define SEALEVEL_2802_7_PID 0X2872 /* SeaLINK+8/485 (2802) Port 7 */ +#define SEALEVEL_2802_8_PID 0X2882 /* SeaLINK+8/485 (2802) Port 8 */ +#define SEALEVEL_2803_1_PID 0X2813 /* SeaLINK+8 (2803) Port 1 */ +#define SEALEVEL_2803_2_PID 0X2823 /* SeaLINK+8 (2803) Port 2 */ +#define SEALEVEL_2803_3_PID 0X2833 /* SeaLINK+8 (2803) Port 3 */ +#define SEALEVEL_2803_4_PID 0X2843 /* SeaLINK+8 (2803) Port 4 */ +#define SEALEVEL_2803_5_PID 0X2853 /* SeaLINK+8 (2803) Port 5 */ +#define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */ +#define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */ +#define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */ +#define SEALEVEL_2803R_1_PID 0Xa02a /* SeaLINK+8 (2803-ROHS) Port 1+2 */ +#define SEALEVEL_2803R_2_PID 0Xa02b /* SeaLINK+8 (2803-ROHS) Port 3+4 */ +#define SEALEVEL_2803R_3_PID 0Xa02c /* SeaLINK+8 (2803-ROHS) Port 5+6 */ +#define SEALEVEL_2803R_4_PID 0Xa02d /* SeaLINK+8 (2803-ROHS) Port 7+8 */ + +/* + * JETI SPECTROMETER SPECBOS 1201 + * http://www.jeti.com/cms/index.php/instruments/other-instruments/specbos-2101 + */ +#define JETI_VID 0x0c6c +#define JETI_SPC1201_PID 0x04b2 + +/* + * FTDI USB UART chips used in construction projects from the + * Elektor Electronics magazine (http://www.elektor.com/) + */ +#define ELEKTOR_VID 0x0C7D +#define ELEKTOR_FT323R_PID 0x0005 /* RFID-Reader, issue 09-2006 */ + +/* + * Posiflex inc retail equipment (http://www.posiflex.com.tw) + */ +#define POSIFLEX_VID 0x0d3a /* Vendor ID */ +#define POSIFLEX_PP7000_PID 0x0300 /* PP-7000II thermal printer */ + +/* + * The following are the values for two KOBIL chipcard terminals. + */ +#define KOBIL_VID 0x0d46 /* KOBIL Vendor ID */ +#define KOBIL_CONV_B1_PID 0x2020 /* KOBIL Konverter for B1 */ +#define KOBIL_CONV_KAAN_PID 0x2021 /* KOBIL_Konverter for KAAN */ + +#define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ +#define FTDI_NF_RIC_PID 0x0001 /* Product Id */ + +/* + * Falcom Wireless Communications GmbH + */ +#define FALCOM_VID 0x0F94 /* Vendor Id */ +#define FALCOM_TWIST_PID 0x0001 /* Falcom Twist USB GPRS modem */ +#define FALCOM_SAMBA_PID 0x0005 /* Falcom Samba USB GPRS modem */ + +/* Larsen and Brusgaard AltiTrack/USBtrack */ +#define LARSENBRUSGAARD_VID 0x0FD8 +#define LB_ALTITRACK_PID 0x0001 + +/* + * TTi (Thurlby Thandar Instruments) + */ +#define TTI_VID 0x103E /* Vendor Id */ +#define TTI_QL355P_PID 0x03E8 /* TTi QL355P power supply */ + +/* Interbiometrics USB I/O Board */ +/* Developed for Interbiometrics by Rudolf Gugler */ +#define INTERBIOMETRICS_VID 0x1209 +#define INTERBIOMETRICS_IOBOARD_PID 0x1002 +#define INTERBIOMETRICS_MINI_IOBOARD_PID 0x1006 + +/* + * Testo products (http://www.testo.com/) + * Submitted by Colin Leroy + */ +#define TESTO_VID 0x128D +#define TESTO_USB_INTERFACE_PID 0x0001 + +/* + * Mobility Electronics products. + */ +#define MOBILITY_VID 0x1342 +#define MOBILITY_USB_SERIAL_PID 0x0202 /* EasiDock USB 200 serial */ + +/* + * FIC / OpenMoko, Inc. http://wiki.openmoko.org/wiki/Neo1973_Debug_Board_v3 + * Submitted by Harald Welte + */ +#define FIC_VID 0x1457 +#define FIC_NEO1973_DEBUG_PID 0x5118 + +/* Olimex */ +#define OLIMEX_VID 0x15BA +#define OLIMEX_ARM_USB_OCD_PID 0x0003 +#define OLIMEX_ARM_USB_OCD_H_PID 0x002b + +/* + * Telldus Technologies + */ +#define TELLDUS_VID 0x1781 /* Vendor ID */ +#define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */ + +/* + * RT Systems programming cables for various ham radios + */ +#define RTSYSTEMS_VID 0x2100 /* Vendor ID */ +#define RTSYSTEMS_SERIAL_VX7_PID 0x9e52 /* Serial converter for VX-7 Radios using FT232RL */ +#define RTSYSTEMS_CT29B_PID 0x9e54 /* CT29B Radio Cable */ +#define RTSYSTEMS_RTS01_PID 0x9e57 /* USB-RTS01 Radio Cable */ + + +/* + * Physik Instrumente + * http://www.physikinstrumente.com/en/products/ + */ +/* These two devices use the VID of FTDI */ +#define PI_C865_PID 0xe0a0 /* PI C-865 Piezomotor Controller */ +#define PI_C857_PID 0xe0a1 /* PI Encoder Trigger Box */ + +#define PI_VID 0x1a72 /* Vendor ID */ +#define PI_C866_PID 0x1000 /* PI C-866 Piezomotor Controller */ +#define PI_C663_PID 0x1001 /* PI C-663 Mercury-Step */ +#define PI_C725_PID 0x1002 /* PI C-725 Piezomotor Controller */ +#define PI_E517_PID 0x1005 /* PI E-517 Digital Piezo Controller Operation Module */ +#define PI_C863_PID 0x1007 /* PI C-863 */ +#define PI_E861_PID 0x1008 /* PI E-861 Piezomotor Controller */ +#define PI_C867_PID 0x1009 /* PI C-867 Piezomotor Controller */ +#define PI_E609_PID 0x100D /* PI E-609 Digital Piezo Controller */ +#define PI_E709_PID 0x100E /* PI E-709 Digital Piezo Controller */ +#define PI_100F_PID 0x100F /* PI Digital Piezo Controller */ +#define PI_1011_PID 0x1011 /* PI Digital Piezo Controller */ +#define PI_1012_PID 0x1012 /* PI Motion Controller */ +#define PI_1013_PID 0x1013 /* PI Motion Controller */ +#define PI_1014_PID 0x1014 /* PI Device */ +#define PI_1015_PID 0x1015 /* PI Device */ +#define PI_1016_PID 0x1016 /* PI Digital Servo Module */ + +/* + * Kondo Kagaku Co.Ltd. + * http://www.kondo-robot.com/EN + */ +#define KONDO_VID 0x165c +#define KONDO_USB_SERIAL_PID 0x0002 + +/* + * Bayer Ascensia Contour blood glucose meter USB-converter cable. + * http://winglucofacts.com/cables/ + */ +#define BAYER_VID 0x1A79 +#define BAYER_CONTOUR_CABLE_PID 0x6001 + +/* + * The following are the values for the Matrix Orbital FTDI Range + * Anything in this range will use an FT232RL. + */ +#define MTXORB_VID 0x1B3D +#define MTXORB_FTDI_RANGE_0100_PID 0x0100 +#define MTXORB_FTDI_RANGE_0101_PID 0x0101 +#define MTXORB_FTDI_RANGE_0102_PID 0x0102 +#define MTXORB_FTDI_RANGE_0103_PID 0x0103 +#define MTXORB_FTDI_RANGE_0104_PID 0x0104 +#define MTXORB_FTDI_RANGE_0105_PID 0x0105 +#define MTXORB_FTDI_RANGE_0106_PID 0x0106 +#define MTXORB_FTDI_RANGE_0107_PID 0x0107 +#define MTXORB_FTDI_RANGE_0108_PID 0x0108 +#define MTXORB_FTDI_RANGE_0109_PID 0x0109 +#define MTXORB_FTDI_RANGE_010A_PID 0x010A +#define MTXORB_FTDI_RANGE_010B_PID 0x010B +#define MTXORB_FTDI_RANGE_010C_PID 0x010C +#define MTXORB_FTDI_RANGE_010D_PID 0x010D +#define MTXORB_FTDI_RANGE_010E_PID 0x010E +#define MTXORB_FTDI_RANGE_010F_PID 0x010F +#define MTXORB_FTDI_RANGE_0110_PID 0x0110 +#define MTXORB_FTDI_RANGE_0111_PID 0x0111 +#define MTXORB_FTDI_RANGE_0112_PID 0x0112 +#define MTXORB_FTDI_RANGE_0113_PID 0x0113 +#define MTXORB_FTDI_RANGE_0114_PID 0x0114 +#define MTXORB_FTDI_RANGE_0115_PID 0x0115 +#define MTXORB_FTDI_RANGE_0116_PID 0x0116 +#define MTXORB_FTDI_RANGE_0117_PID 0x0117 +#define MTXORB_FTDI_RANGE_0118_PID 0x0118 +#define MTXORB_FTDI_RANGE_0119_PID 0x0119 +#define MTXORB_FTDI_RANGE_011A_PID 0x011A +#define MTXORB_FTDI_RANGE_011B_PID 0x011B +#define MTXORB_FTDI_RANGE_011C_PID 0x011C +#define MTXORB_FTDI_RANGE_011D_PID 0x011D +#define MTXORB_FTDI_RANGE_011E_PID 0x011E +#define MTXORB_FTDI_RANGE_011F_PID 0x011F +#define MTXORB_FTDI_RANGE_0120_PID 0x0120 +#define MTXORB_FTDI_RANGE_0121_PID 0x0121 +#define MTXORB_FTDI_RANGE_0122_PID 0x0122 +#define MTXORB_FTDI_RANGE_0123_PID 0x0123 +#define MTXORB_FTDI_RANGE_0124_PID 0x0124 +#define MTXORB_FTDI_RANGE_0125_PID 0x0125 +#define MTXORB_FTDI_RANGE_0126_PID 0x0126 +#define MTXORB_FTDI_RANGE_0127_PID 0x0127 +#define MTXORB_FTDI_RANGE_0128_PID 0x0128 +#define MTXORB_FTDI_RANGE_0129_PID 0x0129 +#define MTXORB_FTDI_RANGE_012A_PID 0x012A +#define MTXORB_FTDI_RANGE_012B_PID 0x012B +#define MTXORB_FTDI_RANGE_012C_PID 0x012C +#define MTXORB_FTDI_RANGE_012D_PID 0x012D +#define MTXORB_FTDI_RANGE_012E_PID 0x012E +#define MTXORB_FTDI_RANGE_012F_PID 0x012F +#define MTXORB_FTDI_RANGE_0130_PID 0x0130 +#define MTXORB_FTDI_RANGE_0131_PID 0x0131 +#define MTXORB_FTDI_RANGE_0132_PID 0x0132 +#define MTXORB_FTDI_RANGE_0133_PID 0x0133 +#define MTXORB_FTDI_RANGE_0134_PID 0x0134 +#define MTXORB_FTDI_RANGE_0135_PID 0x0135 +#define MTXORB_FTDI_RANGE_0136_PID 0x0136 +#define MTXORB_FTDI_RANGE_0137_PID 0x0137 +#define MTXORB_FTDI_RANGE_0138_PID 0x0138 +#define MTXORB_FTDI_RANGE_0139_PID 0x0139 +#define MTXORB_FTDI_RANGE_013A_PID 0x013A +#define MTXORB_FTDI_RANGE_013B_PID 0x013B +#define MTXORB_FTDI_RANGE_013C_PID 0x013C +#define MTXORB_FTDI_RANGE_013D_PID 0x013D +#define MTXORB_FTDI_RANGE_013E_PID 0x013E +#define MTXORB_FTDI_RANGE_013F_PID 0x013F +#define MTXORB_FTDI_RANGE_0140_PID 0x0140 +#define MTXORB_FTDI_RANGE_0141_PID 0x0141 +#define MTXORB_FTDI_RANGE_0142_PID 0x0142 +#define MTXORB_FTDI_RANGE_0143_PID 0x0143 +#define MTXORB_FTDI_RANGE_0144_PID 0x0144 +#define MTXORB_FTDI_RANGE_0145_PID 0x0145 +#define MTXORB_FTDI_RANGE_0146_PID 0x0146 +#define MTXORB_FTDI_RANGE_0147_PID 0x0147 +#define MTXORB_FTDI_RANGE_0148_PID 0x0148 +#define MTXORB_FTDI_RANGE_0149_PID 0x0149 +#define MTXORB_FTDI_RANGE_014A_PID 0x014A +#define MTXORB_FTDI_RANGE_014B_PID 0x014B +#define MTXORB_FTDI_RANGE_014C_PID 0x014C +#define MTXORB_FTDI_RANGE_014D_PID 0x014D +#define MTXORB_FTDI_RANGE_014E_PID 0x014E +#define MTXORB_FTDI_RANGE_014F_PID 0x014F +#define MTXORB_FTDI_RANGE_0150_PID 0x0150 +#define MTXORB_FTDI_RANGE_0151_PID 0x0151 +#define MTXORB_FTDI_RANGE_0152_PID 0x0152 +#define MTXORB_FTDI_RANGE_0153_PID 0x0153 +#define MTXORB_FTDI_RANGE_0154_PID 0x0154 +#define MTXORB_FTDI_RANGE_0155_PID 0x0155 +#define MTXORB_FTDI_RANGE_0156_PID 0x0156 +#define MTXORB_FTDI_RANGE_0157_PID 0x0157 +#define MTXORB_FTDI_RANGE_0158_PID 0x0158 +#define MTXORB_FTDI_RANGE_0159_PID 0x0159 +#define MTXORB_FTDI_RANGE_015A_PID 0x015A +#define MTXORB_FTDI_RANGE_015B_PID 0x015B +#define MTXORB_FTDI_RANGE_015C_PID 0x015C +#define MTXORB_FTDI_RANGE_015D_PID 0x015D +#define MTXORB_FTDI_RANGE_015E_PID 0x015E +#define MTXORB_FTDI_RANGE_015F_PID 0x015F +#define MTXORB_FTDI_RANGE_0160_PID 0x0160 +#define MTXORB_FTDI_RANGE_0161_PID 0x0161 +#define MTXORB_FTDI_RANGE_0162_PID 0x0162 +#define MTXORB_FTDI_RANGE_0163_PID 0x0163 +#define MTXORB_FTDI_RANGE_0164_PID 0x0164 +#define MTXORB_FTDI_RANGE_0165_PID 0x0165 +#define MTXORB_FTDI_RANGE_0166_PID 0x0166 +#define MTXORB_FTDI_RANGE_0167_PID 0x0167 +#define MTXORB_FTDI_RANGE_0168_PID 0x0168 +#define MTXORB_FTDI_RANGE_0169_PID 0x0169 +#define MTXORB_FTDI_RANGE_016A_PID 0x016A +#define MTXORB_FTDI_RANGE_016B_PID 0x016B +#define MTXORB_FTDI_RANGE_016C_PID 0x016C +#define MTXORB_FTDI_RANGE_016D_PID 0x016D +#define MTXORB_FTDI_RANGE_016E_PID 0x016E +#define MTXORB_FTDI_RANGE_016F_PID 0x016F +#define MTXORB_FTDI_RANGE_0170_PID 0x0170 +#define MTXORB_FTDI_RANGE_0171_PID 0x0171 +#define MTXORB_FTDI_RANGE_0172_PID 0x0172 +#define MTXORB_FTDI_RANGE_0173_PID 0x0173 +#define MTXORB_FTDI_RANGE_0174_PID 0x0174 +#define MTXORB_FTDI_RANGE_0175_PID 0x0175 +#define MTXORB_FTDI_RANGE_0176_PID 0x0176 +#define MTXORB_FTDI_RANGE_0177_PID 0x0177 +#define MTXORB_FTDI_RANGE_0178_PID 0x0178 +#define MTXORB_FTDI_RANGE_0179_PID 0x0179 +#define MTXORB_FTDI_RANGE_017A_PID 0x017A +#define MTXORB_FTDI_RANGE_017B_PID 0x017B +#define MTXORB_FTDI_RANGE_017C_PID 0x017C +#define MTXORB_FTDI_RANGE_017D_PID 0x017D +#define MTXORB_FTDI_RANGE_017E_PID 0x017E +#define MTXORB_FTDI_RANGE_017F_PID 0x017F +#define MTXORB_FTDI_RANGE_0180_PID 0x0180 +#define MTXORB_FTDI_RANGE_0181_PID 0x0181 +#define MTXORB_FTDI_RANGE_0182_PID 0x0182 +#define MTXORB_FTDI_RANGE_0183_PID 0x0183 +#define MTXORB_FTDI_RANGE_0184_PID 0x0184 +#define MTXORB_FTDI_RANGE_0185_PID 0x0185 +#define MTXORB_FTDI_RANGE_0186_PID 0x0186 +#define MTXORB_FTDI_RANGE_0187_PID 0x0187 +#define MTXORB_FTDI_RANGE_0188_PID 0x0188 +#define MTXORB_FTDI_RANGE_0189_PID 0x0189 +#define MTXORB_FTDI_RANGE_018A_PID 0x018A +#define MTXORB_FTDI_RANGE_018B_PID 0x018B +#define MTXORB_FTDI_RANGE_018C_PID 0x018C +#define MTXORB_FTDI_RANGE_018D_PID 0x018D +#define MTXORB_FTDI_RANGE_018E_PID 0x018E +#define MTXORB_FTDI_RANGE_018F_PID 0x018F +#define MTXORB_FTDI_RANGE_0190_PID 0x0190 +#define MTXORB_FTDI_RANGE_0191_PID 0x0191 +#define MTXORB_FTDI_RANGE_0192_PID 0x0192 +#define MTXORB_FTDI_RANGE_0193_PID 0x0193 +#define MTXORB_FTDI_RANGE_0194_PID 0x0194 +#define MTXORB_FTDI_RANGE_0195_PID 0x0195 +#define MTXORB_FTDI_RANGE_0196_PID 0x0196 +#define MTXORB_FTDI_RANGE_0197_PID 0x0197 +#define MTXORB_FTDI_RANGE_0198_PID 0x0198 +#define MTXORB_FTDI_RANGE_0199_PID 0x0199 +#define MTXORB_FTDI_RANGE_019A_PID 0x019A +#define MTXORB_FTDI_RANGE_019B_PID 0x019B +#define MTXORB_FTDI_RANGE_019C_PID 0x019C +#define MTXORB_FTDI_RANGE_019D_PID 0x019D +#define MTXORB_FTDI_RANGE_019E_PID 0x019E +#define MTXORB_FTDI_RANGE_019F_PID 0x019F +#define MTXORB_FTDI_RANGE_01A0_PID 0x01A0 +#define MTXORB_FTDI_RANGE_01A1_PID 0x01A1 +#define MTXORB_FTDI_RANGE_01A2_PID 0x01A2 +#define MTXORB_FTDI_RANGE_01A3_PID 0x01A3 +#define MTXORB_FTDI_RANGE_01A4_PID 0x01A4 +#define MTXORB_FTDI_RANGE_01A5_PID 0x01A5 +#define MTXORB_FTDI_RANGE_01A6_PID 0x01A6 +#define MTXORB_FTDI_RANGE_01A7_PID 0x01A7 +#define MTXORB_FTDI_RANGE_01A8_PID 0x01A8 +#define MTXORB_FTDI_RANGE_01A9_PID 0x01A9 +#define MTXORB_FTDI_RANGE_01AA_PID 0x01AA +#define MTXORB_FTDI_RANGE_01AB_PID 0x01AB +#define MTXORB_FTDI_RANGE_01AC_PID 0x01AC +#define MTXORB_FTDI_RANGE_01AD_PID 0x01AD +#define MTXORB_FTDI_RANGE_01AE_PID 0x01AE +#define MTXORB_FTDI_RANGE_01AF_PID 0x01AF +#define MTXORB_FTDI_RANGE_01B0_PID 0x01B0 +#define MTXORB_FTDI_RANGE_01B1_PID 0x01B1 +#define MTXORB_FTDI_RANGE_01B2_PID 0x01B2 +#define MTXORB_FTDI_RANGE_01B3_PID 0x01B3 +#define MTXORB_FTDI_RANGE_01B4_PID 0x01B4 +#define MTXORB_FTDI_RANGE_01B5_PID 0x01B5 +#define MTXORB_FTDI_RANGE_01B6_PID 0x01B6 +#define MTXORB_FTDI_RANGE_01B7_PID 0x01B7 +#define MTXORB_FTDI_RANGE_01B8_PID 0x01B8 +#define MTXORB_FTDI_RANGE_01B9_PID 0x01B9 +#define MTXORB_FTDI_RANGE_01BA_PID 0x01BA +#define MTXORB_FTDI_RANGE_01BB_PID 0x01BB +#define MTXORB_FTDI_RANGE_01BC_PID 0x01BC +#define MTXORB_FTDI_RANGE_01BD_PID 0x01BD +#define MTXORB_FTDI_RANGE_01BE_PID 0x01BE +#define MTXORB_FTDI_RANGE_01BF_PID 0x01BF +#define MTXORB_FTDI_RANGE_01C0_PID 0x01C0 +#define MTXORB_FTDI_RANGE_01C1_PID 0x01C1 +#define MTXORB_FTDI_RANGE_01C2_PID 0x01C2 +#define MTXORB_FTDI_RANGE_01C3_PID 0x01C3 +#define MTXORB_FTDI_RANGE_01C4_PID 0x01C4 +#define MTXORB_FTDI_RANGE_01C5_PID 0x01C5 +#define MTXORB_FTDI_RANGE_01C6_PID 0x01C6 +#define MTXORB_FTDI_RANGE_01C7_PID 0x01C7 +#define MTXORB_FTDI_RANGE_01C8_PID 0x01C8 +#define MTXORB_FTDI_RANGE_01C9_PID 0x01C9 +#define MTXORB_FTDI_RANGE_01CA_PID 0x01CA +#define MTXORB_FTDI_RANGE_01CB_PID 0x01CB +#define MTXORB_FTDI_RANGE_01CC_PID 0x01CC +#define MTXORB_FTDI_RANGE_01CD_PID 0x01CD +#define MTXORB_FTDI_RANGE_01CE_PID 0x01CE +#define MTXORB_FTDI_RANGE_01CF_PID 0x01CF +#define MTXORB_FTDI_RANGE_01D0_PID 0x01D0 +#define MTXORB_FTDI_RANGE_01D1_PID 0x01D1 +#define MTXORB_FTDI_RANGE_01D2_PID 0x01D2 +#define MTXORB_FTDI_RANGE_01D3_PID 0x01D3 +#define MTXORB_FTDI_RANGE_01D4_PID 0x01D4 +#define MTXORB_FTDI_RANGE_01D5_PID 0x01D5 +#define MTXORB_FTDI_RANGE_01D6_PID 0x01D6 +#define MTXORB_FTDI_RANGE_01D7_PID 0x01D7 +#define MTXORB_FTDI_RANGE_01D8_PID 0x01D8 +#define MTXORB_FTDI_RANGE_01D9_PID 0x01D9 +#define MTXORB_FTDI_RANGE_01DA_PID 0x01DA +#define MTXORB_FTDI_RANGE_01DB_PID 0x01DB +#define MTXORB_FTDI_RANGE_01DC_PID 0x01DC +#define MTXORB_FTDI_RANGE_01DD_PID 0x01DD +#define MTXORB_FTDI_RANGE_01DE_PID 0x01DE +#define MTXORB_FTDI_RANGE_01DF_PID 0x01DF +#define MTXORB_FTDI_RANGE_01E0_PID 0x01E0 +#define MTXORB_FTDI_RANGE_01E1_PID 0x01E1 +#define MTXORB_FTDI_RANGE_01E2_PID 0x01E2 +#define MTXORB_FTDI_RANGE_01E3_PID 0x01E3 +#define MTXORB_FTDI_RANGE_01E4_PID 0x01E4 +#define MTXORB_FTDI_RANGE_01E5_PID 0x01E5 +#define MTXORB_FTDI_RANGE_01E6_PID 0x01E6 +#define MTXORB_FTDI_RANGE_01E7_PID 0x01E7 +#define MTXORB_FTDI_RANGE_01E8_PID 0x01E8 +#define MTXORB_FTDI_RANGE_01E9_PID 0x01E9 +#define MTXORB_FTDI_RANGE_01EA_PID 0x01EA +#define MTXORB_FTDI_RANGE_01EB_PID 0x01EB +#define MTXORB_FTDI_RANGE_01EC_PID 0x01EC +#define MTXORB_FTDI_RANGE_01ED_PID 0x01ED +#define MTXORB_FTDI_RANGE_01EE_PID 0x01EE +#define MTXORB_FTDI_RANGE_01EF_PID 0x01EF +#define MTXORB_FTDI_RANGE_01F0_PID 0x01F0 +#define MTXORB_FTDI_RANGE_01F1_PID 0x01F1 +#define MTXORB_FTDI_RANGE_01F2_PID 0x01F2 +#define MTXORB_FTDI_RANGE_01F3_PID 0x01F3 +#define MTXORB_FTDI_RANGE_01F4_PID 0x01F4 +#define MTXORB_FTDI_RANGE_01F5_PID 0x01F5 +#define MTXORB_FTDI_RANGE_01F6_PID 0x01F6 +#define MTXORB_FTDI_RANGE_01F7_PID 0x01F7 +#define MTXORB_FTDI_RANGE_01F8_PID 0x01F8 +#define MTXORB_FTDI_RANGE_01F9_PID 0x01F9 +#define MTXORB_FTDI_RANGE_01FA_PID 0x01FA +#define MTXORB_FTDI_RANGE_01FB_PID 0x01FB +#define MTXORB_FTDI_RANGE_01FC_PID 0x01FC +#define MTXORB_FTDI_RANGE_01FD_PID 0x01FD +#define MTXORB_FTDI_RANGE_01FE_PID 0x01FE +#define MTXORB_FTDI_RANGE_01FF_PID 0x01FF + + + +/* + * The Mobility Lab (TML) + * Submitted by Pierre Castella + */ +#define TML_VID 0x1B91 /* Vendor ID */ +#define TML_USB_SERIAL_PID 0x0064 /* USB - Serial Converter */ + +/* Alti-2 products http://www.alti-2.com */ +#define ALTI2_VID 0x1BC9 +#define ALTI2_N3_PID 0x6001 /* Neptune 3 */ + +/* + * Ionics PlugComputer + */ +#define IONICS_VID 0x1c0c +#define IONICS_PLUGCOMPUTER_PID 0x0102 + +/* + * Dresden Elektronik Sensor Terminal Board + */ +#define DE_VID 0x1cf1 /* Vendor ID */ +#define STB_PID 0x0001 /* Sensor Terminal Board */ +#define WHT_PID 0x0004 /* Wireless Handheld Terminal */ + +/* + * STMicroelectonics + */ +#define ST_VID 0x0483 +#define ST_STMCLT1030_PID 0x3747 /* ST Micro Connect Lite STMCLT1030 */ + +/* + * Papouch products (http://www.papouch.com/) + * Submitted by Folkert van Heusden + */ + +#define PAPOUCH_VID 0x5050 /* Vendor ID */ +#define PAPOUCH_SB485_PID 0x0100 /* Papouch SB485 USB-485/422 Converter */ +#define PAPOUCH_AP485_PID 0x0101 /* AP485 USB-RS485 Converter */ +#define PAPOUCH_SB422_PID 0x0102 /* Papouch SB422 USB-RS422 Converter */ +#define PAPOUCH_SB485_2_PID 0x0103 /* Papouch SB485 USB-485/422 Converter */ +#define PAPOUCH_AP485_2_PID 0x0104 /* AP485 USB-RS485 Converter */ +#define PAPOUCH_SB422_2_PID 0x0105 /* Papouch SB422 USB-RS422 Converter */ +#define PAPOUCH_SB485S_PID 0x0106 /* Papouch SB485S USB-485/422 Converter */ +#define PAPOUCH_SB485C_PID 0x0107 /* Papouch SB485C USB-485/422 Converter */ +#define PAPOUCH_LEC_PID 0x0300 /* LEC USB Converter */ +#define PAPOUCH_SB232_PID 0x0301 /* Papouch SB232 USB-RS232 Converter */ +#define PAPOUCH_TMU_PID 0x0400 /* TMU USB Thermometer */ +#define PAPOUCH_IRAMP_PID 0x0500 /* Papouch IRAmp Duplex */ +#define PAPOUCH_DRAK5_PID 0x0700 /* Papouch DRAK5 */ +#define PAPOUCH_QUIDO8x8_PID 0x0800 /* Papouch Quido 8/8 Module */ +#define PAPOUCH_QUIDO4x4_PID 0x0900 /* Papouch Quido 4/4 Module */ +#define PAPOUCH_QUIDO2x2_PID 0x0a00 /* Papouch Quido 2/2 Module */ +#define PAPOUCH_QUIDO10x1_PID 0x0b00 /* Papouch Quido 10/1 Module */ +#define PAPOUCH_QUIDO30x3_PID 0x0c00 /* Papouch Quido 30/3 Module */ +#define PAPOUCH_QUIDO60x3_PID 0x0d00 /* Papouch Quido 60(100)/3 Module */ +#define PAPOUCH_QUIDO2x16_PID 0x0e00 /* Papouch Quido 2/16 Module */ +#define PAPOUCH_QUIDO3x32_PID 0x0f00 /* Papouch Quido 3/32 Module */ +#define PAPOUCH_DRAK6_PID 0x1000 /* Papouch DRAK6 */ +#define PAPOUCH_UPSUSB_PID 0x8000 /* Papouch UPS-USB adapter */ +#define PAPOUCH_MU_PID 0x8001 /* MU controller */ +#define PAPOUCH_SIMUKEY_PID 0x8002 /* Papouch SimuKey */ +#define PAPOUCH_AD4USB_PID 0x8003 /* AD4USB Measurement Module */ +#define PAPOUCH_GMUX_PID 0x8004 /* Papouch GOLIATH MUX */ +#define PAPOUCH_GMSR_PID 0x8005 /* Papouch GOLIATH MSR */ + +/* + * Marvell SheevaPlug + */ +#define MARVELL_VID 0x9e88 +#define MARVELL_SHEEVAPLUG_PID 0x9e8f + +/* + * Evolution Robotics products (http://www.evolution.com/). + * Submitted by Shawn M. Lavelle. + */ +#define EVOLUTION_VID 0xDEEE /* Vendor ID */ +#define EVOLUTION_ER1_PID 0x0300 /* ER1 Control Module */ +#define EVO_8U232AM_PID 0x02FF /* Evolution robotics RCM2 (FT232AM)*/ +#define EVO_HYBRID_PID 0x0302 /* Evolution robotics RCM4 PID (FT232BM)*/ +#define EVO_RCM4_PID 0x0303 /* Evolution robotics RCM4 PID */ + +/* + * MJS Gadgets HD Radio / XM Radio / Sirius Radio interfaces (using VID 0x0403) + */ +#define MJSG_GENERIC_PID 0x9378 +#define MJSG_SR_RADIO_PID 0x9379 +#define MJSG_XM_RADIO_PID 0x937A +#define MJSG_HD_RADIO_PID 0x937C + +/* + * D.O.Tec products (http://www.directout.eu) + */ +#define FTDI_DOTEC_PID 0x9868 + +/* + * Xverve Signalyzer tools (http://www.signalyzer.com/) + */ +#define XVERVE_SIGNALYZER_ST_PID 0xBCA0 +#define XVERVE_SIGNALYZER_SLITE_PID 0xBCA1 +#define XVERVE_SIGNALYZER_SH2_PID 0xBCA2 +#define XVERVE_SIGNALYZER_SH4_PID 0xBCA4 + +/* + * Segway Robotic Mobility Platform USB interface (using VID 0x0403) + * Submitted by John G. Rogers + */ +#define SEGWAY_RMP200_PID 0xe729 + + +/* + * Accesio USB Data Acquisition products (http://www.accesio.com/) + */ +#define ACCESIO_COM4SM_PID 0xD578 + +/* www.sciencescope.co.uk educational dataloggers */ +#define FTDI_SCIENCESCOPE_LOGBOOKML_PID 0xFF18 +#define FTDI_SCIENCESCOPE_LS_LOGBOOK_PID 0xFF1C +#define FTDI_SCIENCESCOPE_HS_LOGBOOK_PID 0xFF1D + +/* + * Milkymist One JTAG/Serial + */ +#define QIHARDWARE_VID 0x20B7 +#define MILKYMISTONE_JTAGSERIAL_PID 0x0713 + +/* + * CTI GmbH RS485 Converter http://www.cti-lean.com/ + */ +/* USB-485-Mini*/ +#define FTDI_CTI_MINI_PID 0xF608 +/* USB-Nano-485*/ +#define FTDI_CTI_NANO_PID 0xF60B + +/* + * ZeitControl cardsystems GmbH rfid-readers http://zeitconrol.de + */ +/* TagTracer MIFARE*/ +#define FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID 0xF7C0 + +/* + * Rainforest Automation + */ +/* ZigBee controller */ +#define FTDI_RF_R106 0x8A28 + +/* + * Product: HCP HIT GPRS modem + * Manufacturer: HCP d.o.o. + * ATI command output: Cinterion MC55i + */ +#define FTDI_CINTERION_MC55I_PID 0xA951 diff --git a/hw/usb/quirks-pl2303-ids.h b/hw/usb/quirks-pl2303-ids.h new file mode 100644 index 0000000000..8dbdb46ffe --- /dev/null +++ b/hw/usb/quirks-pl2303-ids.h @@ -0,0 +1,150 @@ +/* + * Prolific PL2303 USB to serial adaptor driver header file + * + * 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. + * + */ + +#define BENQ_VENDOR_ID 0x04a5 +#define BENQ_PRODUCT_ID_S81 0x4027 + +#define PL2303_VENDOR_ID 0x067b +#define PL2303_PRODUCT_ID 0x2303 +#define PL2303_PRODUCT_ID_RSAQ2 0x04bb +#define PL2303_PRODUCT_ID_DCU11 0x1234 +#define PL2303_PRODUCT_ID_PHAROS 0xaaa0 +#define PL2303_PRODUCT_ID_RSAQ3 0xaaa2 +#define PL2303_PRODUCT_ID_ALDIGA 0x0611 +#define PL2303_PRODUCT_ID_MMX 0x0612 +#define PL2303_PRODUCT_ID_GPRS 0x0609 +#define PL2303_PRODUCT_ID_HCR331 0x331a +#define PL2303_PRODUCT_ID_MOTOROLA 0x0307 + +#define ATEN_VENDOR_ID 0x0557 +#define ATEN_VENDOR_ID2 0x0547 +#define ATEN_PRODUCT_ID 0x2008 + +#define IODATA_VENDOR_ID 0x04bb +#define IODATA_PRODUCT_ID 0x0a03 +#define IODATA_PRODUCT_ID_RSAQ5 0x0a0e + +#define ELCOM_VENDOR_ID 0x056e +#define ELCOM_PRODUCT_ID 0x5003 +#define ELCOM_PRODUCT_ID_UCSGT 0x5004 + +#define ITEGNO_VENDOR_ID 0x0eba +#define ITEGNO_PRODUCT_ID 0x1080 +#define ITEGNO_PRODUCT_ID_2080 0x2080 + +#define MA620_VENDOR_ID 0x0df7 +#define MA620_PRODUCT_ID 0x0620 + +#define RATOC_VENDOR_ID 0x0584 +#define RATOC_PRODUCT_ID 0xb000 + +#define TRIPP_VENDOR_ID 0x2478 +#define TRIPP_PRODUCT_ID 0x2008 + +#define RADIOSHACK_VENDOR_ID 0x1453 +#define RADIOSHACK_PRODUCT_ID 0x4026 + +#define DCU10_VENDOR_ID 0x0731 +#define DCU10_PRODUCT_ID 0x0528 + +#define SITECOM_VENDOR_ID 0x6189 +#define SITECOM_PRODUCT_ID 0x2068 + +/* Alcatel OT535/735 USB cable */ +#define ALCATEL_VENDOR_ID 0x11f7 +#define ALCATEL_PRODUCT_ID 0x02df + +/* Samsung I330 phone cradle */ +#define SAMSUNG_VENDOR_ID 0x04e8 +#define SAMSUNG_PRODUCT_ID 0x8001 + +#define SIEMENS_VENDOR_ID 0x11f5 +#define SIEMENS_PRODUCT_ID_SX1 0x0001 +#define SIEMENS_PRODUCT_ID_X65 0x0003 +#define SIEMENS_PRODUCT_ID_X75 0x0004 +#define SIEMENS_PRODUCT_ID_EF81 0x0005 + +#define SYNTECH_VENDOR_ID 0x0745 +#define SYNTECH_PRODUCT_ID 0x0001 + +/* Nokia CA-42 Cable */ +#define NOKIA_CA42_VENDOR_ID 0x078b +#define NOKIA_CA42_PRODUCT_ID 0x1234 + +/* CA-42 CLONE Cable www.ca-42.com chipset: Prolific Technology Inc */ +#define CA_42_CA42_VENDOR_ID 0x10b5 +#define CA_42_CA42_PRODUCT_ID 0xac70 + +#define SAGEM_VENDOR_ID 0x079b +#define SAGEM_PRODUCT_ID 0x0027 + +/* Leadtek GPS 9531 (ID 0413:2101) */ +#define LEADTEK_VENDOR_ID 0x0413 +#define LEADTEK_9531_PRODUCT_ID 0x2101 + +/* USB GSM cable from Speed Dragon Multimedia, Ltd */ +#define SPEEDDRAGON_VENDOR_ID 0x0e55 +#define SPEEDDRAGON_PRODUCT_ID 0x110b + +/* DATAPILOT Universal-2 Phone Cable */ +#define DATAPILOT_U2_VENDOR_ID 0x0731 +#define DATAPILOT_U2_PRODUCT_ID 0x2003 + +/* Belkin "F5U257" Serial Adapter */ +#define BELKIN_VENDOR_ID 0x050d +#define BELKIN_PRODUCT_ID 0x0257 + +/* Alcor Micro Corp. USB 2.0 TO RS-232 */ +#define ALCOR_VENDOR_ID 0x058F +#define ALCOR_PRODUCT_ID 0x9720 + +/* Willcom WS002IN Data Driver (by NetIndex Inc.) */ +#define WS002IN_VENDOR_ID 0x11f6 +#define WS002IN_PRODUCT_ID 0x2001 + +/* Corega CG-USBRS232R Serial Adapter */ +#define COREGA_VENDOR_ID 0x07aa +#define COREGA_PRODUCT_ID 0x002a + +/* Y.C. Cable U.S.A., Inc - USB to RS-232 */ +#define YCCABLE_VENDOR_ID 0x05ad +#define YCCABLE_PRODUCT_ID 0x0fba + +/* "Superial" USB - Serial */ +#define SUPERIAL_VENDOR_ID 0x5372 +#define SUPERIAL_PRODUCT_ID 0x2303 + +/* Hewlett-Packard LD220-HP POS Pole Display */ +#define HP_VENDOR_ID 0x03f0 +#define HP_LD220_PRODUCT_ID 0x3524 + +/* Cressi Edy (diving computer) PC interface */ +#define CRESSI_VENDOR_ID 0x04b8 +#define CRESSI_EDY_PRODUCT_ID 0x0521 + +/* Zeagle dive computer interface */ +#define ZEAGLE_VENDOR_ID 0x04b8 +#define ZEAGLE_N2ITION3_PRODUCT_ID 0x0522 + +/* Sony, USB data cable for CMD-Jxx mobile phones */ +#define SONY_VENDOR_ID 0x054c +#define SONY_QN3USB_PRODUCT_ID 0x0437 + +/* Sanwa KB-USB2 multimeter cable (ID: 11ad:0001) */ +#define SANWA_VENDOR_ID 0x11ad +#define SANWA_PRODUCT_ID 0x0001 + +/* ADLINK ND-6530 RS232,RS485 and RS422 adapter */ +#define ADLINK_VENDOR_ID 0x0b63 +#define ADLINK_ND6530_PRODUCT_ID 0x6530 + +/* SMART USB Serial Adapter */ +#define SMART_VENDOR_ID 0x0b8c +#define SMART_PRODUCT_ID 0x2303 diff --git a/hw/usb/quirks.c b/hw/usb/quirks.c new file mode 100644 index 0000000000..a761a96032 --- /dev/null +++ b/hw/usb/quirks.c @@ -0,0 +1,53 @@ +/* + * USB quirk handling + * + * Copyright (c) 2012 Red Hat, Inc. + * + * Red Hat Authors: + * Hans de Goede + * + * 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. + */ + +#include "quirks.h" +#include "hw/usb.h" + +static bool usb_id_match(const struct usb_device_id *ids, + uint16_t vendor_id, uint16_t product_id, + uint8_t interface_class, uint8_t interface_subclass, + uint8_t interface_protocol) { + int i; + + for (i = 0; ids[i].vendor_id != -1; i++) { + if (ids[i].vendor_id == vendor_id && + ids[i].product_id == product_id && + (ids[i].interface_class == -1 || + (ids[i].interface_class == interface_class && + ids[i].interface_subclass == interface_subclass && + ids[i].interface_protocol == interface_protocol))) { + return true; + } + } + return false; +} + +int usb_get_quirks(uint16_t vendor_id, uint16_t product_id, + uint8_t interface_class, uint8_t interface_subclass, + uint8_t interface_protocol) +{ + int quirks = 0; + + if (usb_id_match(usbredir_raw_serial_ids, vendor_id, product_id, + interface_class, interface_subclass, interface_protocol)) { + quirks |= USB_QUIRK_BUFFER_BULK_IN; + } + if (usb_id_match(usbredir_ftdi_serial_ids, vendor_id, product_id, + interface_class, interface_subclass, interface_protocol)) { + quirks |= USB_QUIRK_BUFFER_BULK_IN | USB_QUIRK_IS_FTDI; + } + + return quirks; +} diff --git a/hw/usb/quirks.h b/hw/usb/quirks.h new file mode 100644 index 0000000000..8dc6065527 --- /dev/null +++ b/hw/usb/quirks.h @@ -0,0 +1,910 @@ +/* + * USB quirk handling + * + * Copyright (c) 2012 Red Hat, Inc. + * + * Red Hat Authors: + * Hans de Goede + * + * 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. + */ + +/* 1 on 1 copy of linux/drivers/usb/serial/ftdi_sio_ids.h */ +#include "quirks-ftdi-ids.h" +/* 1 on 1 copy of linux/drivers/usb/serial/pl2303.h */ +#include "quirks-pl2303-ids.h" + +struct usb_device_id { + int vendor_id; + int product_id; + int interface_class; + int interface_subclass; + int interface_protocol; +}; + +#define USB_DEVICE(vendor, product) \ + .vendor_id = vendor, .product_id = product, .interface_class = -1, + +#define USB_DEVICE_AND_INTERFACE_INFO(vend, prod, iclass, isubclass, iproto) \ + .vendor_id = vend, .product_id = prod, .interface_class = iclass, \ + .interface_subclass = isubclass, .interface_protocol = iproto + +static const struct usb_device_id usbredir_raw_serial_ids[] = { + /* + * Silicon Laboratories CP210x USB to RS232 serial adapter ids + * copied from linux/drivers/usb/serial/cp210x.c + * + * Copyright (C) 2005 Craig Shelley (craig@microtron.org.uk) + */ + { USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */ + { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ + { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ + { USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ + { USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */ + { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ + { USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */ + { USB_DEVICE(0x0BED, 0x1100) }, /* MEI (TM) Cashflow-SC Bill/Voucher Acceptor */ + { USB_DEVICE(0x0BED, 0x1101) }, /* MEI series 2000 Combo Acceptor */ + { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ + { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */ + { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */ + { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ + { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ + { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ + { USB_DEVICE(0x10C4, 0x0F91) }, /* Vstabi */ + { USB_DEVICE(0x10C4, 0x1101) }, /* Arkham Technology DS101 Bus Monitor */ + { USB_DEVICE(0x10C4, 0x1601) }, /* Arkham Technology DS101 Adapter */ + { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */ + { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ + { USB_DEVICE(0x10C4, 0x8044) }, /* Cygnal Debug Adapter */ + { USB_DEVICE(0x10C4, 0x804E) }, /* Software Bisque Paramount ME build-in converter */ + { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */ + { USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */ + { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */ + { USB_DEVICE(0x10C4, 0x806F) }, /* IMS USB to RS422 Converter Cable */ + { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ + { USB_DEVICE(0x10C4, 0x80C4) }, /* Cygnal Integrated Products, Inc., Optris infrared thermometer */ + { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ + { USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */ + { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ + { USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */ + { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ + { USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */ + { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ + { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ + { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */ + { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ + { USB_DEVICE(0x10C4, 0x815F) }, /* Timewave HamLinkUSB */ + { USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */ + { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ + { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */ + { USB_DEVICE(0x10C4, 0x81A9) }, /* Multiplex RC Interface */ + { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */ + { USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */ + { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ + { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ + { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ + { USB_DEVICE(0x10C4, 0x81E8) }, /* Zephyr Bioharness */ + { USB_DEVICE(0x10C4, 0x81F2) }, /* C1007 HF band RFID controller */ + { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ + { USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */ + { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demonstration module */ + { USB_DEVICE(0x10C4, 0x8293) }, /* Telegesis ETRX2USB */ + { USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */ + { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ + { USB_DEVICE(0x10C4, 0x8382) }, /* Cygnal Integrated Products, Inc. */ + { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ + { USB_DEVICE(0x10C4, 0x83D8) }, /* DekTec DTA Plus VHF/UHF Booster/Attenuator */ + { USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */ + { USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */ + { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ + { USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */ + { USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */ + { USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */ + { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */ + { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ + { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */ + { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ + { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */ + { USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */ + { USB_DEVICE(0x10C4, 0xF004) }, /* Elan Digital Systems USBcount50 */ + { USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */ + { USB_DEVICE(0x10CE, 0xEA6A) }, /* Silicon Labs MobiData GPRS USB Modem 100EU */ + { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */ + { USB_DEVICE(0x1555, 0x0004) }, /* Owen AC4 USB-RS485 Converter */ + { USB_DEVICE(0x166A, 0x0201) }, /* Clipsal 5500PACA C-Bus Pascal Automation Controller */ + { USB_DEVICE(0x166A, 0x0301) }, /* Clipsal 5800PC C-Bus Wireless PC Interface */ + { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */ + { USB_DEVICE(0x166A, 0x0304) }, /* Clipsal 5000CT2 C-Bus Black and White Touchscreen */ + { USB_DEVICE(0x166A, 0x0305) }, /* Clipsal C-5000CT2 C-Bus Spectrum Colour Touchscreen */ + { USB_DEVICE(0x166A, 0x0401) }, /* Clipsal L51xx C-Bus Architectural Dimmer */ + { USB_DEVICE(0x166A, 0x0101) }, /* Clipsal 5560884 C-Bus Multi-room Audio Matrix Switcher */ + { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ + { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */ + { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ + { USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */ + { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ + { USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */ + { USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */ + { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ + { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ + { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ + { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ + { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */ + { USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */ + { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */ + { USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */ + { USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */ + { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ + + /* + * Prolific pl2303 USB to RS232 serial adapter ids + * copied from linux/drivers/usb/serial/pl2303.c + * + * Copyright (C) 2001-2007 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2003 IBM Corp. + */ + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) }, + { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, + { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, + { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, + { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) }, + { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, + { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) }, + { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) }, + { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) }, + { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) }, + { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) }, + { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) }, + { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) }, + { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) }, + { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) }, + { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) }, + { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1) }, + { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) }, + { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) }, + { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81) }, + { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_ID_S81) }, /* Benq/Siemens S81 */ + { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, + { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) }, + { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) }, + { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) }, + { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) }, + { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) }, + { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, + { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, + { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, + { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, + { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, + { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, + { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, + { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, + { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) }, + { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, + { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) }, + { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) }, + { USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) }, + + { USB_DEVICE(-1, -1) } /* Terminating Entry */ +}; + +static const struct usb_device_id usbredir_ftdi_serial_ids[] = { + /* + * FTDI USB to RS232 serial adapter ids + * copied from linux/drivers/usb/serial/ftdi_sio.c + * + * Copyright (C) 2009 - 2010 + * Johan Hovold (jhovold@gmail.com) + * Copyright (C) 1999 - 2001 + * Greg Kroah-Hartman (greg@kroah.com) + * Bill Ryder (bryder@sgi.com) + * Copyright (C) 2002 + * Kuba Ober (kuba@mareimbrium.org) + */ + { USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_NXTCAM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_3_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_4_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_5_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_6_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_7_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_USINT_CAT_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_USINT_WKEY_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_USINT_RS232_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IPLUS2_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_DMX4ALL) }, + { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_4232H_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_232H_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_FTX_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_SNIFFER_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) }, + { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, + { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, + { USB_DEVICE(FTDI_VID, FTDI_LENZ_LIUSB_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_XF_633_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_XF_631_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_XF_635_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_XF_640_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_XF_642_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_DSS20_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_URBAN_0_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_URBAN_1_PID) }, + { USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MTXORB_0_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MTXORB_1_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MTXORB_2_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MTXORB_3_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) }, + { USB_DEVICE(FTDI_VID, FTDI_VARDAAN_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0103_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0104_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0105_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0106_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0107_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0108_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0109_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0110_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0111_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0112_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0113_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0114_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0115_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0116_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0117_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0118_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0119_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0120_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0121_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0122_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0123_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0124_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0125_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0126_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0127_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0128_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0129_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0130_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0131_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0132_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0133_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0134_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0135_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0136_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0137_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0138_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0139_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0140_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0141_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0142_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0143_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0144_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0145_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0146_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0147_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0148_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0149_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0150_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0151_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0152_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0153_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0154_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0155_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0156_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0157_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0158_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0159_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0160_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0161_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0162_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0163_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0164_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0165_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0166_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0167_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0168_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0169_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0170_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0171_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0172_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0173_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0174_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0175_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0176_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0177_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0178_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0179_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0180_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0181_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0182_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0183_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0184_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0185_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0186_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0187_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0188_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0189_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0190_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0191_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0192_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0193_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0194_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0195_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0196_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0197_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0198_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0199_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019A_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019B_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019C_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019D_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019E_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019F_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A0_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A1_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A2_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A3_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A4_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A5_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A6_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A7_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A8_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A9_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AA_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AB_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AC_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AD_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AE_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AF_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B0_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B1_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B2_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B3_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B4_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B5_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B6_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B7_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B8_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B9_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BA_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BB_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BC_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BD_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BE_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BF_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C0_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C1_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C2_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C3_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C4_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C5_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C6_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C7_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C8_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C9_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CA_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CB_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CC_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CD_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CE_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CF_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D0_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D1_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D2_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D3_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D4_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D5_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D6_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D7_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D8_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D9_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DA_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DB_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DC_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DD_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DE_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DF_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E0_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E1_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E2_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E3_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E4_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E5_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E6_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E7_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E8_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E9_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EA_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EB_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EC_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01ED_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EE_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EF_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F0_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F1_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F2_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F3_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F4_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F5_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F6_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F7_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F8_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F9_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FA_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FB_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FC_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FD_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FE_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FF_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_USBX_707_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2106_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_3_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_4_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_3_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_4_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_3_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_4_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_3_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_4_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_5_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_6_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_7_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_8_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_3_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_4_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_5_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_6_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_7_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_8_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_3_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_4_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_5_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_3_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_4_PID) }, + { USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) }, + { USB_DEVICE(OCT_VID, OCT_US101_PID) }, + { USB_DEVICE(OCT_VID, OCT_DK201_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_HE_TIRA1_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) }, + { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_1) }, + { USB_DEVICE(FTDI_VID, PROTEGO_R2X0) }, + { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_3) }, + { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_4) }, + { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E808_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E809_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80A_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80B_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80C_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80D_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80E_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80F_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E888_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E889_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88A_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88B_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88C_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88D_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88E_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88F_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_UR100_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IBS_US485_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IBS_PICPRO_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IBS_PCMCIA_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IBS_PK1_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IBS_RS232MON_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IBS_APP70_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID) }, + /* + * ELV devices: + */ + { USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_WS550_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_EC3000_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_WS888_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_TWS550_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_FEM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_CLI7000_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_PPS7330_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_TFM100_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_UDF77_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_UIO88_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_UAD8_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_UDA7_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_USI2_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_T1100_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_PCD200_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_ULA200_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_CSI8_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1000DL_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_RFP500_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_FS20SIG_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_UTP8_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_WS444PC_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1010PC_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_HS485_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_UMS100_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_TFD128_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_FM3RX_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_WS777_PID) }, + { USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) }, + { USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) }, + { USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) }, + { USB_DEVICE(FTDI_VID, LINX_FUTURE_1_PID) }, + { USB_DEVICE(FTDI_VID, LINX_FUTURE_2_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CCSMACHX_2_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CCSLOAD_N_GO_3_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CCSICDU64_4_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CCSPRIME8_5_PID) }, + { USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) }, + { USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) }, + { USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) }, + { USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) }, + { USB_DEVICE(FALCOM_VID, FALCOM_SAMBA_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OCEANIC_PID) }, + { USB_DEVICE(TTI_VID, TTI_QL355P_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, + { USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) }, + { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USOPTL4_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USPTL4_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USO9ML2DR_2_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USO9ML2DR_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USOPTL4DR2_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USOPTL4DR_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_485USB9F_2W_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_485USB9F_4W_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_232USB9M_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_485USBTB_2W_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_485USBTB_4W_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_TTL5USB9M_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_TTL3USB9M_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_ZZ_PROG1_USB_PID) }, + { USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) }, + { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_3_PID) }, + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_0_PID) }, + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_1_PID) }, + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_2_PID) }, + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_3_PID) }, + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_4_PID) }, + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) }, + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) }, + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) }, + { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MHAM_YS_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MHAM_IC_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MHAM_DB9_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MHAM_RS232_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y9_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_VCP_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_D2XX_PID) }, + { USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) }, + { USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) }, + { USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HRC_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16IC_PID) }, + { USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) }, + { USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) }, + { USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TTUSB_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ECLO_COM_1WIRE_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_777_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_8900F_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_NZR_SEM_USB_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C2_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2D_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2VT_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2VR_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVT_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVR_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVT_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVR_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) }, + { USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_GAMMA_SCOUT_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13M_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) }, + { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_NDI_SPECTRA_SCU_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_2_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_3_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID) }, + { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_SERIAL_VX7_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_CT29B_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_RTS01_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) }, + { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) }, + { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID) }, + { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID) }, + { USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID) }, + { USB_DEVICE(FTDI_VID, LMI_LM3S_DEVEL_BOARD_PID) }, + { USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID) }, + { USB_DEVICE(FTDI_VID, LMI_LM3S_ICDI_BOARD_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID) }, + { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, + { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) }, + + /* Papouch devices based on FTDI chip */ + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_AP485_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB422_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485_2_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_AP485_2_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB422_2_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485S_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485C_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_LEC_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB232_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_IRAMP_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_DRAK5_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO8x8_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO2x2_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO10x1_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO30x3_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO60x3_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO2x16_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO3x32_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_DRAK6_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_UPSUSB_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_MU_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SIMUKEY_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_AD4USB_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_GMUX_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_GMSR_PID) }, + + { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DGQG_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) }, + { USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) }, + { USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) }, + { USB_DEVICE(ATMEL_VID, STK541_PID) }, + { USB_DEVICE(DE_VID, STB_PID) }, + { USB_DEVICE(DE_VID, WHT_PID) }, + { USB_DEVICE(ADI_VID, ADI_GNICE_PID) }, + { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID) }, + { USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID, + 0xff, 0xff, 0x00) }, + { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, + { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID) }, + { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) }, + { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) }, + { USB_DEVICE(FTDI_VID, PI_C865_PID) }, + { USB_DEVICE(FTDI_VID, PI_C857_PID) }, + { USB_DEVICE(PI_VID, PI_C866_PID) }, + { USB_DEVICE(PI_VID, PI_C663_PID) }, + { USB_DEVICE(PI_VID, PI_C725_PID) }, + { USB_DEVICE(PI_VID, PI_E517_PID) }, + { USB_DEVICE(PI_VID, PI_C863_PID) }, + { USB_DEVICE(PI_VID, PI_E861_PID) }, + { USB_DEVICE(PI_VID, PI_C867_PID) }, + { USB_DEVICE(PI_VID, PI_E609_PID) }, + { USB_DEVICE(PI_VID, PI_E709_PID) }, + { USB_DEVICE(PI_VID, PI_100F_PID) }, + { USB_DEVICE(PI_VID, PI_1011_PID) }, + { USB_DEVICE(PI_VID, PI_1012_PID) }, + { USB_DEVICE(PI_VID, PI_1013_PID) }, + { USB_DEVICE(PI_VID, PI_1014_PID) }, + { USB_DEVICE(PI_VID, PI_1015_PID) }, + { USB_DEVICE(PI_VID, PI_1016_PID) }, + { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) }, + { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, + { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID) }, + { USB_DEVICE(FTDI_VID, TI_XDS100V2_PID) }, + { USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) }, + { USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) }, + { USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) }, + { USB_DEVICE(FTDI_VID, HAMEG_HO870_PID) }, + { USB_DEVICE(FTDI_VID, MJSG_GENERIC_PID) }, + { USB_DEVICE(FTDI_VID, MJSG_SR_RADIO_PID) }, + { USB_DEVICE(FTDI_VID, MJSG_HD_RADIO_PID) }, + { USB_DEVICE(FTDI_VID, MJSG_XM_RADIO_PID) }, + { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_ST_PID) }, + { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SLITE_PID) }, + { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH2_PID) }, + { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID) }, + { USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) }, + { USB_DEVICE(FTDI_VID, ACCESIO_COM4SM_PID) }, + { USB_DEVICE(IONICS_VID, IONICS_PLUGCOMPUTER_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_24_MASTER_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_PC_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_USB_DMX_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MIDI_TIMECODE_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MINI_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MAXI_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MEDIA_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CINTERION_MC55I_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) }, + { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID) }, + { USB_DEVICE(ST_VID, ST_STMCLT1030_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_RF_R106) }, + { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, + + { USB_DEVICE(-1, -1) } /* Terminating Entry */ +}; + +#undef USB_DEVICE +#undef USB_DEVICE_AND_INTERFACE_INFO diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index f15dc914ab..f1bf84c987 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -52,11 +52,13 @@ typedef struct USBRedirDevice USBRedirDevice; -/* Struct to hold buffered packets (iso or int input packets) */ +/* Struct to hold buffered packets */ struct buf_packet { uint8_t *data; - int len; - int status; + void *free_on_destroy; + uint16_t len; + uint16_t offset; + uint8_t status; QTAILQ_ENTRY(buf_packet)next; }; @@ -70,11 +72,14 @@ struct endp_data { uint8_t iso_error; /* For reporting iso errors to the HC */ uint8_t interrupt_started; uint8_t interrupt_error; + uint8_t bulk_receiving_enabled; + uint8_t bulk_receiving_started; uint8_t bufpq_prefilled; uint8_t bufpq_dropping_packets; QTAILQ_HEAD(, buf_packet) bufpq; int32_t bufpq_size; int32_t bufpq_target_size; + USBPacket *pending_async_packet; }; struct PacketIdQueueEntry { @@ -108,6 +113,7 @@ struct USBRedirDevice { struct endp_data endpoint[MAX_ENDPOINTS]; struct PacketIdQueue cancelled; struct PacketIdQueue already_in_flight; + void (*buffered_bulk_in_complete)(USBRedirDevice *, USBPacket *, uint8_t); /* Data for device filtering */ struct usb_redir_device_connect_header device_info; struct usb_redir_interface_info_header interface_info; @@ -135,6 +141,8 @@ static void usbredir_interrupt_receiving_status(void *priv, uint64_t id, *interrupt_receiving_status); static void usbredir_bulk_streams_status(void *priv, uint64_t id, struct usb_redir_bulk_streams_status_header *bulk_streams_status); +static void usbredir_bulk_receiving_status(void *priv, uint64_t id, + struct usb_redir_bulk_receiving_status_header *bulk_receiving_status); static void usbredir_control_packet(void *priv, uint64_t id, struct usb_redir_control_packet_header *control_packet, uint8_t *data, int data_len); @@ -147,6 +155,9 @@ static void usbredir_iso_packet(void *priv, uint64_t id, static void usbredir_interrupt_packet(void *priv, uint64_t id, struct usb_redir_interrupt_packet_header *interrupt_header, uint8_t *data, int data_len); +static void usbredir_buffered_bulk_packet(void *priv, uint64_t id, + struct usb_redir_buffered_bulk_packet_header *buffered_bulk_packet, + uint8_t *data, int data_len); static void usbredir_handle_status(USBRedirDevice *dev, USBPacket *p, int status); @@ -320,12 +331,19 @@ static void packet_id_queue_empty(struct PacketIdQueue *q) static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p) { USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + int i = USBEP2I(p->ep); if (p->combined) { usb_combined_packet_cancel(udev, p); return; } + if (dev->endpoint[i].pending_async_packet) { + assert(dev->endpoint[i].pending_async_packet == p); + dev->endpoint[i].pending_async_packet = NULL; + return; + } + packet_id_queue_add(&dev->cancelled, p->id); usbredirparser_send_cancel_data_packet(dev->parser, p->id); usbredirparser_do_write(dev->parser); @@ -344,6 +362,11 @@ static void usbredir_fill_already_in_flight_from_ep(USBRedirDevice *dev, { static USBPacket *p; + /* async handled packets for bulk receiving eps do not count as inflight */ + if (dev->endpoint[USBEP2I(ep)].bulk_receiving_started) { + return; + } + QTAILQ_FOREACH(p, &ep->queue, queue) { /* Skip combined packets, except for the first */ if (p->combined && p != p->combined->first) { @@ -391,8 +414,8 @@ static USBPacket *usbredir_find_packet_by_id(USBRedirDevice *dev, return p; } -static void bufp_alloc(USBRedirDevice *dev, - uint8_t *data, int len, int status, uint8_t ep) +static void bufp_alloc(USBRedirDevice *dev, uint8_t *data, uint16_t len, + uint8_t status, uint8_t ep, void *free_on_destroy) { struct buf_packet *bufp; @@ -416,7 +439,9 @@ static void bufp_alloc(USBRedirDevice *dev, bufp = g_malloc(sizeof(struct buf_packet)); bufp->data = data; bufp->len = len; + bufp->offset = 0; bufp->status = status; + bufp->free_on_destroy = free_on_destroy; QTAILQ_INSERT_TAIL(&dev->endpoint[EP2I(ep)].bufpq, bufp, next); dev->endpoint[EP2I(ep)].bufpq_size++; } @@ -426,7 +451,7 @@ static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp, { QTAILQ_REMOVE(&dev->endpoint[EP2I(ep)].bufpq, bufp, next); dev->endpoint[EP2I(ep)].bufpq_size--; - free(bufp->data); + free(bufp->free_on_destroy); g_free(bufp); } @@ -577,19 +602,162 @@ static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep) usbredir_free_bufpq(dev, ep); } +/* + * The usb-host may poll the endpoint faster then our guest, resulting in lots + * of smaller bulkp-s. The below buffered_bulk_in_complete* functions combine + * data from multiple bulkp-s into a single packet, avoiding bufpq overflows. + */ +static void usbredir_buffered_bulk_add_data_to_packet(USBRedirDevice *dev, + struct buf_packet *bulkp, int count, USBPacket *p, uint8_t ep) +{ + usb_packet_copy(p, bulkp->data + bulkp->offset, count); + bulkp->offset += count; + if (bulkp->offset == bulkp->len) { + /* Store status in the last packet with data from this bulkp */ + usbredir_handle_status(dev, p, bulkp->status); + bufp_free(dev, bulkp, ep); + } +} + +static void usbredir_buffered_bulk_in_complete_raw(USBRedirDevice *dev, + USBPacket *p, uint8_t ep) +{ + struct buf_packet *bulkp; + int count; + + while ((bulkp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq)) && + p->actual_length < p->iov.size && p->status == USB_RET_SUCCESS) { + count = bulkp->len - bulkp->offset; + if (count > (p->iov.size - p->actual_length)) { + count = p->iov.size - p->actual_length; + } + usbredir_buffered_bulk_add_data_to_packet(dev, bulkp, count, p, ep); + } +} + +static void usbredir_buffered_bulk_in_complete_ftdi(USBRedirDevice *dev, + USBPacket *p, uint8_t ep) +{ + const int maxp = dev->endpoint[EP2I(ep)].max_packet_size; + uint8_t header[2] = { 0, 0 }; + struct buf_packet *bulkp; + int count; + + while ((bulkp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq)) && + p->actual_length < p->iov.size && p->status == USB_RET_SUCCESS) { + if (bulkp->len < 2) { + WARNING("malformed ftdi bulk in packet\n"); + bufp_free(dev, bulkp, ep); + continue; + } + + if ((p->actual_length % maxp) == 0) { + usb_packet_copy(p, bulkp->data, 2); + memcpy(header, bulkp->data, 2); + } else { + if (bulkp->data[0] != header[0] || bulkp->data[1] != header[1]) { + break; /* Different header, add to next packet */ + } + } + + if (bulkp->offset == 0) { + bulkp->offset = 2; /* Skip header */ + } + count = bulkp->len - bulkp->offset; + /* Must repeat the header at maxp interval */ + if (count > (maxp - (p->actual_length % maxp))) { + count = maxp - (p->actual_length % maxp); + } + usbredir_buffered_bulk_add_data_to_packet(dev, bulkp, count, p, ep); + } +} + +static void usbredir_buffered_bulk_in_complete(USBRedirDevice *dev, + USBPacket *p, uint8_t ep) +{ + p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */ + dev->buffered_bulk_in_complete(dev, p, ep); + DPRINTF("bulk-token-in ep %02X status %d len %d id %"PRIu64"\n", + ep, p->status, p->actual_length, p->id); +} + +static void usbredir_handle_buffered_bulk_in_data(USBRedirDevice *dev, + USBPacket *p, uint8_t ep) +{ + /* Input bulk endpoint, buffered packet input */ + if (!dev->endpoint[EP2I(ep)].bulk_receiving_started) { + int bpt; + struct usb_redir_start_bulk_receiving_header start = { + .endpoint = ep, + .stream_id = 0, + .no_transfers = 5, + }; + /* Round bytes_per_transfer up to a multiple of max_packet_size */ + bpt = 512 + dev->endpoint[EP2I(ep)].max_packet_size - 1; + bpt /= dev->endpoint[EP2I(ep)].max_packet_size; + bpt *= dev->endpoint[EP2I(ep)].max_packet_size; + start.bytes_per_transfer = bpt; + /* No id, we look at the ep when receiving a status back */ + usbredirparser_send_start_bulk_receiving(dev->parser, 0, &start); + usbredirparser_do_write(dev->parser); + DPRINTF("bulk receiving started bytes/transfer %u count %d ep %02X\n", + start.bytes_per_transfer, start.no_transfers, ep); + dev->endpoint[EP2I(ep)].bulk_receiving_started = 1; + /* We don't really want to drop bulk packets ever, but + having some upper limit to how much we buffer is good. */ + dev->endpoint[EP2I(ep)].bufpq_target_size = 5000; + dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0; + } + + if (QTAILQ_EMPTY(&dev->endpoint[EP2I(ep)].bufpq)) { + DPRINTF("bulk-token-in ep %02X, no bulkp\n", ep); + assert(dev->endpoint[EP2I(ep)].pending_async_packet == NULL); + dev->endpoint[EP2I(ep)].pending_async_packet = p; + p->status = USB_RET_ASYNC; + return; + } + usbredir_buffered_bulk_in_complete(dev, p, ep); +} + +static void usbredir_stop_bulk_receiving(USBRedirDevice *dev, uint8_t ep) +{ + struct usb_redir_stop_bulk_receiving_header stop_bulk = { + .endpoint = ep, + .stream_id = 0, + }; + if (dev->endpoint[EP2I(ep)].bulk_receiving_started) { + usbredirparser_send_stop_bulk_receiving(dev->parser, 0, &stop_bulk); + DPRINTF("bulk receiving stopped ep %02X\n", ep); + dev->endpoint[EP2I(ep)].bulk_receiving_started = 0; + } + usbredir_free_bufpq(dev, ep); +} + static void usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p, uint8_t ep) { struct usb_redir_bulk_packet_header bulk_packet; size_t size = (p->combined) ? p->combined->iov.size : p->iov.size; - - DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, size, p->id); + const int maxp = dev->endpoint[EP2I(ep)].max_packet_size; if (usbredir_already_in_flight(dev, p->id)) { p->status = USB_RET_ASYNC; return; } + if (dev->endpoint[EP2I(ep)].bulk_receiving_enabled) { + if (size != 0 && (size % maxp) == 0) { + usbredir_handle_buffered_bulk_in_data(dev, p, ep); + return; + } + WARNING("bulk recv invalid size %zd ep %02x, disabling\n", size, ep); + assert(dev->endpoint[EP2I(ep)].pending_async_packet == NULL); + usbredir_stop_bulk_receiving(dev, ep); + dev->endpoint[EP2I(ep)].bulk_receiving_enabled = 0; + } + + DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, size, p->id); + bulk_packet.endpoint = ep; bulk_packet.length = size; bulk_packet.stream_id = 0; @@ -726,9 +894,6 @@ static void usbredir_handle_data(USBDevice *udev, USBPacket *p) ERROR("handle_data called for control transfer on ep %02X\n", ep); p->status = USB_RET_NAK; break; - case USB_ENDPOINT_XFER_ISOC: - usbredir_handle_iso_data(dev, p, ep); - break; case USB_ENDPOINT_XFER_BULK: if (p->state == USB_PACKET_SETUP && p->pid == USB_TOKEN_IN && p->ep->pipeline) { @@ -737,6 +902,9 @@ static void usbredir_handle_data(USBDevice *udev, USBPacket *p) } usbredir_handle_bulk_data(dev, p, ep); break; + case USB_ENDPOINT_XFER_ISOC: + usbredir_handle_iso_data(dev, p, ep); + break; case USB_ENDPOINT_XFER_INT: if (ep & USB_DIR_IN) { usbredir_handle_interrupt_in_data(dev, p, ep); @@ -763,6 +931,11 @@ static void usbredir_stop_ep(USBRedirDevice *dev, int i) uint8_t ep = I2EP(i); switch (dev->endpoint[i].type) { + case USB_ENDPOINT_XFER_BULK: + if (ep & USB_DIR_IN) { + usbredir_stop_bulk_receiving(dev, ep); + } + break; case USB_ENDPOINT_XFER_ISOC: usbredir_stop_iso_stream(dev, ep); break; @@ -942,10 +1115,12 @@ static void usbredir_create_parser(USBRedirDevice *dev) dev->parser->interrupt_receiving_status_func = usbredir_interrupt_receiving_status; dev->parser->bulk_streams_status_func = usbredir_bulk_streams_status; + dev->parser->bulk_receiving_status_func = usbredir_bulk_receiving_status; dev->parser->control_packet_func = usbredir_control_packet; dev->parser->bulk_packet_func = usbredir_bulk_packet; dev->parser->iso_packet_func = usbredir_iso_packet; dev->parser->interrupt_packet_func = usbredir_interrupt_packet; + dev->parser->buffered_bulk_packet_func = usbredir_buffered_bulk_packet; dev->read_buf = NULL; dev->read_buf_size = 0; @@ -954,6 +1129,7 @@ static void usbredir_create_parser(USBRedirDevice *dev) usbredirparser_caps_set_cap(caps, usb_redir_cap_ep_info_max_packet_size); usbredirparser_caps_set_cap(caps, usb_redir_cap_64bits_ids); usbredirparser_caps_set_cap(caps, usb_redir_cap_32bits_bulk_length); + usbredirparser_caps_set_cap(caps, usb_redir_cap_bulk_receiving); if (runstate_check(RUN_STATE_INMIGRATE)) { flags |= usbredirparser_fl_no_hello; @@ -1192,6 +1368,52 @@ error: return -1; } +static void usbredir_check_bulk_receiving(USBRedirDevice *dev) +{ + int i, j, quirks; + + if (!usbredirparser_peer_has_cap(dev->parser, + usb_redir_cap_bulk_receiving)) { + return; + } + + for (i = EP2I(USB_DIR_IN); i < MAX_ENDPOINTS; i++) { + dev->endpoint[i].bulk_receiving_enabled = 0; + } + for (i = 0; i < dev->interface_info.interface_count; i++) { + quirks = usb_get_quirks(dev->device_info.vendor_id, + dev->device_info.product_id, + dev->interface_info.interface_class[i], + dev->interface_info.interface_subclass[i], + dev->interface_info.interface_protocol[i]); + if (!(quirks & USB_QUIRK_BUFFER_BULK_IN)) { + continue; + } + if (quirks & USB_QUIRK_IS_FTDI) { + dev->buffered_bulk_in_complete = + usbredir_buffered_bulk_in_complete_ftdi; + } else { + dev->buffered_bulk_in_complete = + usbredir_buffered_bulk_in_complete_raw; + } + + for (j = EP2I(USB_DIR_IN); j < MAX_ENDPOINTS; j++) { + if (dev->endpoint[j].interface == + dev->interface_info.interface[i] && + dev->endpoint[j].type == USB_ENDPOINT_XFER_BULK && + dev->endpoint[j].max_packet_size != 0) { + dev->endpoint[j].bulk_receiving_enabled = 1; + /* + * With buffering pipelining is not necessary. Also packet + * combining and bulk in buffering don't play nice together! + */ + I2USBEP(dev, j)->pipeline = false; + break; /* Only buffer for the first ep of each intf */ + } + } + } +} + /* * usbredirparser packet complete callbacks */ @@ -1300,6 +1522,7 @@ static void usbredir_device_connect(void *priv, return; } + usbredir_check_bulk_receiving(dev); qemu_mod_timer(dev->attach_timer, dev->next_attach_time); } @@ -1338,9 +1561,10 @@ static void usbredir_interface_info(void *priv, /* * If we receive interface info after the device has already been - * connected (ie on a set_config), re-check the filter. + * connected (ie on a set_config), re-check interface dependent things. */ if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) { + usbredir_check_bulk_receiving(dev); if (usbredir_check_filter(dev)) { ERROR("Device no longer matches filter after interface info " "change, disconnecting!\n"); @@ -1441,6 +1665,7 @@ static void usbredir_ep_info(void *priv, return; } usbredir_setup_usb_eps(dev); + usbredir_check_bulk_receiving(dev); } static void usbredir_configuration_status(void *priv, uint64_t id, @@ -1531,6 +1756,25 @@ static void usbredir_bulk_streams_status(void *priv, uint64_t id, { } +static void usbredir_bulk_receiving_status(void *priv, uint64_t id, + struct usb_redir_bulk_receiving_status_header *bulk_receiving_status) +{ + USBRedirDevice *dev = priv; + uint8_t ep = bulk_receiving_status->endpoint; + + DPRINTF("bulk recv status %d ep %02X id %"PRIu64"\n", + bulk_receiving_status->status, ep, id); + + if (!dev->dev.attached || !dev->endpoint[EP2I(ep)].bulk_receiving_started) { + return; + } + + if (bulk_receiving_status->status == usb_redir_stall) { + DPRINTF("bulk receiving stopped by peer ep %02X\n", ep); + dev->endpoint[EP2I(ep)].bulk_receiving_started = 0; + } +} + static void usbredir_control_packet(void *priv, uint64_t id, struct usb_redir_control_packet_header *control_packet, uint8_t *data, int data_len) @@ -1636,7 +1880,7 @@ static void usbredir_iso_packet(void *priv, uint64_t id, } /* bufp_alloc also adds the packet to the ep queue */ - bufp_alloc(dev, data, data_len, iso_packet->status, ep); + bufp_alloc(dev, data, data_len, iso_packet->status, ep, data); } static void usbredir_interrupt_packet(void *priv, uint64_t id, @@ -1667,7 +1911,7 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id, } /* bufp_alloc also adds the packet to the ep queue */ - bufp_alloc(dev, data, data_len, interrupt_packet->status, ep); + bufp_alloc(dev, data, data_len, interrupt_packet->status, ep, data); } else { /* * We report output interrupt packets as completed directly upon @@ -1680,6 +1924,52 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id, } } +static void usbredir_buffered_bulk_packet(void *priv, uint64_t id, + struct usb_redir_buffered_bulk_packet_header *buffered_bulk_packet, + uint8_t *data, int data_len) +{ + USBRedirDevice *dev = priv; + uint8_t status, ep = buffered_bulk_packet->endpoint; + void *free_on_destroy; + int i, len; + + DPRINTF("buffered-bulk-in status %d ep %02X len %d id %"PRIu64"\n", + buffered_bulk_packet->status, ep, data_len, id); + + if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_BULK) { + ERROR("received buffered-bulk packet for non bulk ep %02X\n", ep); + free(data); + return; + } + + if (dev->endpoint[EP2I(ep)].bulk_receiving_started == 0) { + DPRINTF("received buffered-bulk packet on not started ep %02X\n", ep); + free(data); + return; + } + + /* Data must be in maxp chunks for buffered_bulk_add_*_data_to_packet */ + len = dev->endpoint[EP2I(ep)].max_packet_size; + status = usb_redir_success; + free_on_destroy = NULL; + for (i = 0; i < data_len; i += len) { + if (len >= (data_len - i)) { + len = data_len - i; + status = buffered_bulk_packet->status; + free_on_destroy = data; + } + /* bufp_alloc also adds the packet to the ep queue */ + bufp_alloc(dev, data + i, len, status, ep, free_on_destroy); + } + + if (dev->endpoint[EP2I(ep)].pending_async_packet) { + USBPacket *p = dev->endpoint[EP2I(ep)].pending_async_packet; + dev->endpoint[EP2I(ep)].pending_async_packet = NULL; + usbredir_buffered_bulk_in_complete(dev, p, ep); + usb_packet_complete(&dev->dev, p); + } +} + /* * Migration code */ @@ -1714,6 +2004,7 @@ static int usbredir_post_load(void *priv, int version_id) dev->dev.speedmask = (1 << dev->dev.speed); usbredir_setup_usb_eps(dev); + usbredir_check_bulk_receiving(dev); return 0; } @@ -1787,15 +2078,16 @@ static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused) struct endp_data *endp = priv; USBRedirDevice *dev = endp->dev; struct buf_packet *bufp; - int i = 0; + int len, i = 0; qemu_put_be32(f, endp->bufpq_size); QTAILQ_FOREACH(bufp, &endp->bufpq, next) { + len = bufp->len - bufp->offset; DPRINTF("put_bufpq %d/%d len %d status %d\n", i + 1, endp->bufpq_size, - bufp->len, bufp->status); - qemu_put_be32(f, bufp->len); + len, bufp->status); + qemu_put_be32(f, len); qemu_put_be32(f, bufp->status); - qemu_put_buffer(f, bufp->data, bufp->len); + qemu_put_buffer(f, bufp->data + bufp->offset, len); i++; } assert(i == endp->bufpq_size); @@ -1813,7 +2105,9 @@ static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused) bufp = g_malloc(sizeof(struct buf_packet)); bufp->len = qemu_get_be32(f); bufp->status = qemu_get_be32(f); + bufp->offset = 0; bufp->data = qemu_oom_check(malloc(bufp->len)); /* regular malloc! */ + bufp->free_on_destroy = bufp->data; qemu_get_buffer(f, bufp->data, bufp->len); QTAILQ_INSERT_TAIL(&endp->bufpq, bufp, next); DPRINTF("get_bufpq %d/%d len %d status %d\n", i + 1, endp->bufpq_size, @@ -1830,6 +2124,23 @@ static const VMStateInfo usbredir_ep_bufpq_vmstate_info = { /* For endp_data migration */ +static const VMStateDescription usbredir_bulk_receiving_vmstate = { + .name = "usb-redir-ep/bulk-receiving", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(bulk_receiving_started, struct endp_data), + VMSTATE_END_OF_LIST() + } +}; + +static bool usbredir_bulk_receiving_needed(void *priv) +{ + struct endp_data *endp = priv; + + return endp->bulk_receiving_started; +} + static const VMStateDescription usbredir_ep_vmstate = { .name = "usb-redir-ep", .version_id = 1, @@ -1856,6 +2167,14 @@ static const VMStateDescription usbredir_ep_vmstate = { }, VMSTATE_INT32(bufpq_target_size, struct endp_data), VMSTATE_END_OF_LIST() + }, + .subsections = (VMStateSubsection[]) { + { + .vmsd = &usbredir_bulk_receiving_vmstate, + .needed = usbredir_bulk_receiving_needed, + }, { + /* empty */ + } } }; From 89eb147c2cfd2c797d3662aa2f55254441f0595a Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 3 Jan 2013 12:29:41 +0100 Subject: [PATCH 2232/2270] uhci: stop using portio lists Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-uhci.c | 106 +++++++++++++--------------------------------- trace-events | 2 - 2 files changed, 30 insertions(+), 78 deletions(-) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 0cd68cf355..60645aa21f 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -461,40 +461,11 @@ static const VMStateDescription vmstate_uhci = { } }; -static void uhci_ioport_writeb(void *opaque, uint32_t addr, uint32_t val) +static void uhci_port_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) { UHCIState *s = opaque; - addr &= 0x1f; - switch(addr) { - case 0x0c: - s->sof_timing = val; - break; - } -} - -static uint32_t uhci_ioport_readb(void *opaque, uint32_t addr) -{ - UHCIState *s = opaque; - uint32_t val; - - addr &= 0x1f; - switch(addr) { - case 0x0c: - val = s->sof_timing; - break; - default: - val = 0xff; - break; - } - return val; -} - -static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val) -{ - UHCIState *s = opaque; - - addr &= 0x1f; trace_usb_uhci_mmio_writew(addr, val); switch(addr) { @@ -543,6 +514,17 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val) if (s->status & UHCI_STS_HCHALTED) s->frnum = val & 0x7ff; break; + case 0x08: + s->fl_base_addr &= 0xffff0000; + s->fl_base_addr |= val & ~0xfff; + break; + case 0x0a: + s->fl_base_addr &= 0x0000ffff; + s->fl_base_addr |= (val << 16); + break; + case 0x0c: + s->sof_timing = val & 0xff; + break; case 0x10 ... 0x1f: { UHCIPort *port; @@ -574,12 +556,11 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val) } } -static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr) +static uint64_t uhci_port_read(void *opaque, hwaddr addr, unsigned size) { UHCIState *s = opaque; uint32_t val; - addr &= 0x1f; switch(addr) { case 0x00: val = s->cmd; @@ -593,6 +574,15 @@ static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr) case 0x06: val = s->frnum; break; + case 0x08: + val = s->fl_base_addr & 0xffff; + break; + case 0x0a: + val = (s->fl_base_addr >> 16) & 0xffff; + break; + case 0x0c: + val = s->sof_timing; + break; case 0x10 ... 0x1f: { UHCIPort *port; @@ -615,38 +605,6 @@ static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr) return val; } -static void uhci_ioport_writel(void *opaque, uint32_t addr, uint32_t val) -{ - UHCIState *s = opaque; - - addr &= 0x1f; - trace_usb_uhci_mmio_writel(addr, val); - - switch(addr) { - case 0x08: - s->fl_base_addr = val & ~0xfff; - break; - } -} - -static uint32_t uhci_ioport_readl(void *opaque, uint32_t addr) -{ - UHCIState *s = opaque; - uint32_t val; - - addr &= 0x1f; - switch(addr) { - case 0x08: - val = s->fl_base_addr; - break; - default: - val = 0xffffffff; - break; - } - trace_usb_uhci_mmio_readl(addr, val); - return val; -} - /* signal resume if controller suspended */ static void uhci_resume (void *opaque) { @@ -1236,18 +1194,14 @@ static void uhci_frame_timer(void *opaque) qemu_mod_timer(s->frame_timer, t_now + frame_t); } -static const MemoryRegionPortio uhci_portio[] = { - { 0, 32, 2, .write = uhci_ioport_writew, }, - { 0, 32, 2, .read = uhci_ioport_readw, }, - { 0, 32, 4, .write = uhci_ioport_writel, }, - { 0, 32, 4, .read = uhci_ioport_readl, }, - { 0, 32, 1, .write = uhci_ioport_writeb, }, - { 0, 32, 1, .read = uhci_ioport_readb, }, - PORTIO_END_OF_LIST() -}; - static const MemoryRegionOps uhci_ioport_ops = { - .old_portio = uhci_portio, + .read = uhci_port_read, + .write = uhci_port_write, + .valid.min_access_size = 1, + .valid.max_access_size = 4, + .impl.min_access_size = 2, + .impl.max_access_size = 2, + .endianness = DEVICE_LITTLE_ENDIAN, }; static USBPortOps uhci_port_ops = { diff --git a/trace-events b/trace-events index 4023a4c094..2183183214 100644 --- a/trace-events +++ b/trace-events @@ -307,8 +307,6 @@ usb_uhci_frame_loop_stop_idle(void) "" usb_uhci_frame_loop_continue(void) "" usb_uhci_mmio_readw(uint32_t addr, uint32_t val) "addr 0x%04x, ret 0x%04x" usb_uhci_mmio_writew(uint32_t addr, uint32_t val) "addr 0x%04x, val 0x%04x" -usb_uhci_mmio_readl(uint32_t addr, uint32_t val) "addr 0x%04x, ret 0x%08x" -usb_uhci_mmio_writel(uint32_t addr, uint32_t val) "addr 0x%04x, val 0x%08x" usb_uhci_queue_add(uint32_t token) "token 0x%x" usb_uhci_queue_del(uint32_t token, const char *reason) "token 0x%x: %s" usb_uhci_packet_add(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x" From 314992b1a48a5a2a0f2b14195f959ad2c3f5b3ff Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 3 Jan 2013 14:17:18 +0100 Subject: [PATCH 2233/2270] linux-user: fix mips 32-on-64 prealloc case MIPS only supports 31 bits of virtual address space for user space, so let's make sure we stay within that limit with our preallocated memory block. This fixes the MIPS user space targets when executed without command line option. Signed-off-by: Alexander Graf Signed-off-by: Aurelien Jarno --- linux-user/main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/linux-user/main.c b/linux-user/main.c index f6c4c8d7a3..9ade1bfabd 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -57,7 +57,12 @@ int have_guest_base; * This way we will never overlap with our own libraries or binaries or stack * or anything else that QEMU maps. */ +# ifdef TARGET_MIPS +/* MIPS only supports 31 bits of virtual address space for user space */ +unsigned long reserved_va = 0x77000000; +# else unsigned long reserved_va = 0xf7000000; +# endif #else unsigned long reserved_va; #endif From e1a4019cf13ddf2441496c2e613faba3a891cddf Mon Sep 17 00:00:00 2001 From: Eric Johnson Date: Mon, 7 Jan 2013 22:26:44 -0800 Subject: [PATCH 2234/2270] target-mips: Allow DSP access to be disabled once enabled. Clear the DSP hflags at the start of compute_hflags. Otherwise access is not properly disabled once enabled. Signed-off-by: Eric Johnson Signed-off-by: Aurelien Jarno --- target-mips/cpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 31602ac8ed..5963d62973 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -751,7 +751,7 @@ static inline void compute_hflags(CPUMIPSState *env) { env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU | - MIPS_HFLAG_UX); + MIPS_HFLAG_UX | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2); if (!(env->CP0_Status & (1 << CP0St_EXL)) && !(env->CP0_Status & (1 << CP0St_ERL)) && !(env->hflags & MIPS_HFLAG_DM)) { From e320d05a531ed4991a87cfe0a4c280563fb88788 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Tue, 1 Jan 2013 19:44:31 +0100 Subject: [PATCH 2235/2270] target-mips: Replace macros by inline functions The macros RESTORE_ROUNDING_MODE and RESTORE_FLUSH_MODE silently used variable env from their callers. Using inline functions with env passed as a function argument is more transparent. This modification was proposed by Peter Maydell. Cc: Peter Maydell Signed-off-by: Stefan Weil Reviewed-by: Eric Johnson Signed-off-by: Aurelien Jarno --- target-mips/op_helper.c | 42 +++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index d833d78b4f..d5c61e8a84 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2170,11 +2170,17 @@ static unsigned int ieee_rm[] = { float_round_down }; -#define RESTORE_ROUNDING_MODE \ - set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], &env->active_fpu.fp_status) +static inline void restore_rounding_mode(CPUMIPSState *env) +{ + set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], + &env->active_fpu.fp_status); +} -#define RESTORE_FLUSH_MODE \ - set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0, &env->active_fpu.fp_status) +static inline void restore_flush_mode(CPUMIPSState *env) +{ + set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0, + &env->active_fpu.fp_status); +} target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg) { @@ -2230,9 +2236,9 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t reg) return; } /* set rounding mode */ - RESTORE_ROUNDING_MODE; + restore_rounding_mode(env); /* set flush-to-zero mode */ - RESTORE_FLUSH_MODE; + restore_flush_mode(env); set_float_exception_flags(0, &env->active_fpu.fp_status); if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31)) do_raise_exception(env, EXCP_FPE, GETPC()); @@ -2464,7 +2470,7 @@ uint64_t helper_float_roundl_d(CPUMIPSState *env, uint64_t fdt0) set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status); dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); - RESTORE_ROUNDING_MODE; + restore_rounding_mode(env); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { dt2 = FP_TO_INT64_OVERFLOW; @@ -2479,7 +2485,7 @@ uint64_t helper_float_roundl_s(CPUMIPSState *env, uint32_t fst0) set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status); dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); - RESTORE_ROUNDING_MODE; + restore_rounding_mode(env); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { dt2 = FP_TO_INT64_OVERFLOW; @@ -2494,7 +2500,7 @@ uint32_t helper_float_roundw_d(CPUMIPSState *env, uint64_t fdt0) set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status); wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); - RESTORE_ROUNDING_MODE; + restore_rounding_mode(env); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { wt2 = FP_TO_INT32_OVERFLOW; @@ -2509,7 +2515,7 @@ uint32_t helper_float_roundw_s(CPUMIPSState *env, uint32_t fst0) set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status); wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); - RESTORE_ROUNDING_MODE; + restore_rounding_mode(env); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { wt2 = FP_TO_INT32_OVERFLOW; @@ -2576,7 +2582,7 @@ uint64_t helper_float_ceill_d(CPUMIPSState *env, uint64_t fdt0) set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); - RESTORE_ROUNDING_MODE; + restore_rounding_mode(env); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { dt2 = FP_TO_INT64_OVERFLOW; @@ -2591,7 +2597,7 @@ uint64_t helper_float_ceill_s(CPUMIPSState *env, uint32_t fst0) set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); - RESTORE_ROUNDING_MODE; + restore_rounding_mode(env); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { dt2 = FP_TO_INT64_OVERFLOW; @@ -2606,7 +2612,7 @@ uint32_t helper_float_ceilw_d(CPUMIPSState *env, uint64_t fdt0) set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); - RESTORE_ROUNDING_MODE; + restore_rounding_mode(env); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { wt2 = FP_TO_INT32_OVERFLOW; @@ -2621,7 +2627,7 @@ uint32_t helper_float_ceilw_s(CPUMIPSState *env, uint32_t fst0) set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); - RESTORE_ROUNDING_MODE; + restore_rounding_mode(env); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { wt2 = FP_TO_INT32_OVERFLOW; @@ -2636,7 +2642,7 @@ uint64_t helper_float_floorl_d(CPUMIPSState *env, uint64_t fdt0) set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); - RESTORE_ROUNDING_MODE; + restore_rounding_mode(env); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { dt2 = FP_TO_INT64_OVERFLOW; @@ -2651,7 +2657,7 @@ uint64_t helper_float_floorl_s(CPUMIPSState *env, uint32_t fst0) set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); - RESTORE_ROUNDING_MODE; + restore_rounding_mode(env); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { dt2 = FP_TO_INT64_OVERFLOW; @@ -2666,7 +2672,7 @@ uint32_t helper_float_floorw_d(CPUMIPSState *env, uint64_t fdt0) set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); - RESTORE_ROUNDING_MODE; + restore_rounding_mode(env); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { wt2 = FP_TO_INT32_OVERFLOW; @@ -2681,7 +2687,7 @@ uint32_t helper_float_floorw_s(CPUMIPSState *env, uint32_t fst0) set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); - RESTORE_ROUNDING_MODE; + restore_rounding_mode(env); if (get_float_exception_flags(&env->active_fpu.fp_status) & (float_flag_invalid | float_flag_overflow)) { wt2 = FP_TO_INT32_OVERFLOW; From da1a4cef9e125a866f4ef9a39b342c2913727f70 Mon Sep 17 00:00:00 2001 From: Petar Jovanovic Date: Wed, 2 Jan 2013 05:08:48 +0100 Subject: [PATCH 2236/2270] target-mips: Fix helper and tests for dot/cross-dot product instructions Helper function for dpa_w_ph, dpax_w_ph, dps_w_ph and dpsx_w_ph incorrectly defines halfword vector elements as unsigned values. This results in wrong output which is not triggered in the tests as they also follow this logic. Signed-off-by: Petar Jovanovic Reviewed-by: Eric Johnson Signed-off-by: Aurelien Jarno --- target-mips/dsp_helper.c | 2 +- tests/tcg/mips/mips32-dspr2/dpa_w_ph.c | 4 ++-- tests/tcg/mips/mips32-dspr2/dpax_w_ph.c | 17 +++++++++++++++++ tests/tcg/mips/mips32-dspr2/dps_w_ph.c | 17 +++++++++++++++++ tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c | 4 ++-- 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index a33e2bf9fd..4870e3dbbc 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -2473,7 +2473,7 @@ DP_OB(dpsu_h_obr, 0, 24, 16, 8, 0, 24, 16, 8, 0); void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ CPUMIPSState *env) \ { \ - uint16_t rsB, rsA, rtB, rtA; \ + int16_t rsB, rsA, rtB, rtA; \ int32_t tempA, tempB; \ int64_t acc; \ \ diff --git a/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c index 1cfbdb080f..fae49f10eb 100644 --- a/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c +++ b/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c @@ -26,8 +26,8 @@ int main() ach = 6, acl = 7; rs = 0xFFFF00FF; rt = 0xFFFF0002; - resulth = 0x05; - resultl = 0xfffe0206; + resulth = 0x06; + resultl = 0x206; __asm ("mthi %0, $ac1\n\t" "mtlo %1, $ac1\n\t" diff --git a/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c index f75699755c..514797cfd1 100644 --- a/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c +++ b/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c @@ -23,5 +23,22 @@ int main() assert(ach == resulth); assert(acl == resultl); + ach = 6, acl = 7; + rs = 0xFFFF00FF; + rt = 0xFFFF0002; + resulth = 0x05; + resultl = 0xFFFFFF06; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dpax.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + return 0; } diff --git a/tests/tcg/mips/mips32-dspr2/dps_w_ph.c b/tests/tcg/mips/mips32-dspr2/dps_w_ph.c index 8303643d18..f51f9b9d13 100644 --- a/tests/tcg/mips/mips32-dspr2/dps_w_ph.c +++ b/tests/tcg/mips/mips32-dspr2/dps_w_ph.c @@ -23,5 +23,22 @@ int main() assert(ach == resulth); assert(acl == resultl); + ach = 6, acl = 7; + rs = 0xFFFF00FF; + rt = 0xFFFF0002; + resulth = 0x05; + resultl = 0xFFFFFE08; + __asm + ("mthi %0, $ac1\n\t" + "mtlo %1, $ac1\n\t" + "dps.w.ph $ac1, %2, %3\n\t" + "mfhi %0, $ac1\n\t" + "mflo %1, $ac1\n\t" + : "+r"(ach), "+r"(acl) + : "r"(rs), "r"(rt) + ); + assert(ach == resulth); + assert(acl == resultl); + return 0; } diff --git a/tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c index 6db59a4ccd..bb49a4031d 100644 --- a/tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c +++ b/tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c @@ -9,8 +9,8 @@ int main() rs = 0xBC0123AD; rt = 0x01643721; - resulth = 0x04; - resultl = 0xD751F050; + resulth = 0x05; + resultl = 0xE72F050; __asm ("mthi %0, $ac1\n\t" "mtlo %1, $ac1\n\t" From 41c6bcd912d1a2461313040566077b86e48eea31 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 5 Dec 2012 14:49:07 -0200 Subject: [PATCH 2237/2270] libqemustub: Add qemu_[un]register_reset() stubs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will be useful for code that don't call qemu_devices_reset() (e.g. *-user). If qemu_devices_reset() is never called, it means we don't need to keep track of the reset handler list. Signed-off-by: Eduardo Habkost Signed-off-by: Andreas Färber --- stubs/Makefile.objs | 1 + stubs/reset.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 stubs/reset.c diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index 035b29a1f3..00f0b641d6 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -5,4 +5,5 @@ stub-obj-y += fdset-get-fd.o stub-obj-y += fdset-remove-fd.o stub-obj-y += get-fd.o stub-obj-y += set-fd-handler.o +stub-obj-y += reset.o stub-obj-$(CONFIG_WIN32) += fd-register.o diff --git a/stubs/reset.c b/stubs/reset.c new file mode 100644 index 0000000000..ad287251ed --- /dev/null +++ b/stubs/reset.c @@ -0,0 +1,13 @@ +#include "hw/hw.h" + +/* Stub functions for binaries that never call qemu_devices_reset(), + * and don't need to keep track of the reset handler list. + */ + +void qemu_register_reset(QEMUResetHandler *func, void *opaque) +{ +} + +void qemu_unregister_reset(QEMUResetHandler *func, void *opaque) +{ +} From 083a5f8731bb3c7e0eae99dcdb1209027d770aaf Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 5 Dec 2012 14:49:08 -0200 Subject: [PATCH 2238/2270] libqemustub: vmstate register/unregister stubs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add vmstate stub functions, so that qdev.o can be used without savevm.o when vmstate support is not necessary (i.e. by *-user). Signed-off-by: Eduardo Habkost Signed-off-by: Andreas Färber --- stubs/Makefile.objs | 1 + stubs/vmstate.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 stubs/vmstate.c diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index 00f0b641d6..ca2197e6fb 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -6,4 +6,5 @@ stub-obj-y += fdset-remove-fd.o stub-obj-y += get-fd.o stub-obj-y += set-fd-handler.o stub-obj-y += reset.o +stub-obj-y += vmstate.o stub-obj-$(CONFIG_WIN32) += fd-register.o diff --git a/stubs/vmstate.c b/stubs/vmstate.c new file mode 100644 index 0000000000..3682af599e --- /dev/null +++ b/stubs/vmstate.c @@ -0,0 +1,17 @@ +#include "qemu-common.h" +#include "migration/vmstate.h" + +int vmstate_register_with_alias_id(DeviceState *dev, + int instance_id, + const VMStateDescription *vmsd, + void *base, int alias_id, + int required_for_version) +{ + return 0; +} + +void vmstate_unregister(DeviceState *dev, + const VMStateDescription *vmsd, + void *opaque) +{ +} From 906709a151344805df4ff493a7d3a81fbce46fbe Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 5 Dec 2012 14:49:09 -0200 Subject: [PATCH 2239/2270] libqemustub: sysbus_get_default() stub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The stub will be used on cases where sysbus.c is not compiled in (e.g. *-user). Note that code that uses NULL as the bus with qdev{_try,}_create() implicitly uses sysbus_get_default() as the bus, and will still require sysbus.c to be compiled in. Signed-off-by: Eduardo Habkost Signed-off-by: Andreas Färber --- stubs/Makefile.objs | 1 + stubs/sysbus.c | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 stubs/sysbus.c diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index ca2197e6fb..7672c69a29 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -7,4 +7,5 @@ stub-obj-y += get-fd.o stub-obj-y += set-fd-handler.o stub-obj-y += reset.o stub-obj-y += vmstate.o +stub-obj-y += sysbus.o stub-obj-$(CONFIG_WIN32) += fd-register.o diff --git a/stubs/sysbus.c b/stubs/sysbus.c new file mode 100644 index 0000000000..e13496582b --- /dev/null +++ b/stubs/sysbus.c @@ -0,0 +1,6 @@ +#include "hw/qdev-core.h" + +BusState *sysbus_get_default(void) +{ + return NULL; +} From 507066f8a9610c0088df19ce7b3e436f43165ec1 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 5 Dec 2012 14:49:12 -0200 Subject: [PATCH 2240/2270] qdev: Include qdev code into *-user, too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code depends on some functions from qemu-option.o, so add qemu-option.o to universal-obj-y to make sure it's included. Signed-off-by: Eduardo Habkost Signed-off-by: Andreas Färber --- Makefile.objs | 8 ++++++++ hw/Makefile.objs | 9 +++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Makefile.objs b/Makefile.objs index a3eab4b410..12a314e3fb 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -21,6 +21,13 @@ qom-obj-y = qom/ universal-obj-y += $(qom-obj-y) +####################################################################### +# Core hw code (qdev core) +hw-core-obj-y += hw/ +hw-core-obj-y += qemu-option.o + +universal-obj-y += $(hw-core-obj-y) + ####################################################################### # oslib-obj-y is code depending on the OS (win32 vs posix) oslib-obj-y = osdep.o cutils.o qemu-timer-common.o @@ -182,6 +189,7 @@ nested-vars += \ user-obj-y \ common-obj-y \ universal-obj-y \ + hw-core-obj-y \ extra-obj-y \ trace-obj-y dummy := $(call unnest-vars) diff --git a/hw/Makefile.objs b/hw/Makefile.objs index b8bbed39c1..6b8a68c504 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -1,3 +1,9 @@ +# core qdev-related obj files, also used by *-user: +hw-core-obj-y += qdev.o qdev-properties.o +# irq.o needed for qdev GPIO handling: +hw-core-obj-y += irq.o + + common-obj-y = usb/ ide/ pci/ common-obj-y += loader.o common-obj-$(CONFIG_VIRTIO) += virtio-console.o @@ -154,7 +160,6 @@ common-obj-$(CONFIG_SOUND) += $(sound-obj-y) common-obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/ common-obj-y += usb/ -common-obj-y += irq.o common-obj-$(CONFIG_PTIMER) += ptimer.o common-obj-$(CONFIG_MAX7310) += max7310.o common-obj-$(CONFIG_WM8750) += wm8750.o @@ -180,7 +185,7 @@ common-obj-$(CONFIG_SD) += sd.o common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o common-obj-y += bt-hci-csr.o common-obj-y += msmouse.o ps2.o -common-obj-y += qdev.o qdev-properties.o qdev-monitor.o +common-obj-y += qdev-monitor.o common-obj-y += qdev-properties-system.o common-obj-$(CONFIG_BRLAPI) += baum.o From 5d5b24d042072fb4d13e7027f6e52e44390a9896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 4 Jan 2013 18:13:00 +0100 Subject: [PATCH 2241/2270] qdev: Don't assume existence of parent bus on unparenting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 667d22d1ae59da46b4c1fbd094ca61145f19b8c3 (qdev: move bus removal to object_unparent) made the assumption that at unparenting time parent_bus is not NULL. This assumption is unjustified since object_unparent() may well be called directly after object_initialize(), without any qdev_set_parent_bus(). This did not cause any issues yet because qdev_[try_]create() does call qdev_set_parent_bus(), falling back to SysBus if unsupplied. While at it, ensure that this new function uses the device_ prefix and make the name more neutral in light of this semantic change. Reported-by: Eduardo Habkost Signed-off-by: Andreas Färber Tested-by: Igor Mammedov --- hw/qdev.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/qdev.c b/hw/qdev.c index f2c248451c..e2a5c5735b 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -698,16 +698,18 @@ static void device_class_base_init(ObjectClass *class, void *data) klass->props = NULL; } -static void qdev_remove_from_bus(Object *obj) +static void device_unparent(Object *obj) { DeviceState *dev = DEVICE(obj); - bus_remove_child(dev->parent_bus, dev); + if (dev->parent_bus != NULL) { + bus_remove_child(dev->parent_bus, dev); + } } static void device_class_init(ObjectClass *class, void *data) { - class->unparent = qdev_remove_from_bus; + class->unparent = device_unparent; } void device_reset(DeviceState *dev) From 961f839570f01d60a0b224248e6e56fc1d675793 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 5 Dec 2012 14:49:13 -0200 Subject: [PATCH 2242/2270] cpu: Change parent type to Device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This finally makes the CPU class a subclass of the Device class, allowing us to start using DeviceState properties on CPU subclasses. It has no_user=1, as creating CPUs using -device doesn't work yet. Signed-off-by: Igor Mammedov Signed-off-by: Eduardo Habkost Signed-off-by: Andreas Färber --- include/qom/cpu.h | 6 +++--- qom/cpu.c | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 3e9fc3aca5..fbacb2756b 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -20,7 +20,7 @@ #ifndef QEMU_CPU_H #define QEMU_CPU_H -#include "qom/object.h" +#include "hw/qdev-core.h" #include "qemu/thread.h" /** @@ -46,7 +46,7 @@ typedef struct CPUState CPUState; */ typedef struct CPUClass { /*< private >*/ - ObjectClass parent_class; + DeviceClass parent_class; /*< public >*/ void (*reset)(CPUState *cpu); @@ -66,7 +66,7 @@ struct kvm_run; */ struct CPUState { /*< private >*/ - Object parent_obj; + DeviceState parent_obj; /*< public >*/ struct QemuThread *thread; diff --git a/qom/cpu.c b/qom/cpu.c index d4d436f80a..49e5134ea1 100644 --- a/qom/cpu.c +++ b/qom/cpu.c @@ -36,14 +36,16 @@ static void cpu_common_reset(CPUState *cpu) static void cpu_class_init(ObjectClass *klass, void *data) { + DeviceClass *dc = DEVICE_CLASS(klass); CPUClass *k = CPU_CLASS(klass); k->reset = cpu_common_reset; + dc->no_user = 1; } -static TypeInfo cpu_type_info = { +static const TypeInfo cpu_type_info = { .name = TYPE_CPU, - .parent = TYPE_OBJECT, + .parent = TYPE_DEVICE, .instance_size = sizeof(CPUState), .abstract = true, .class_size = sizeof(CPUClass), From fcb93c036053ca8a5cfc02ca72b1b80dd2062423 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Fri, 4 Jan 2013 20:01:04 -0200 Subject: [PATCH 2243/2270] target-i386: kvm: -cpu host: Use GET_SUPPORTED_CPUID for SVM features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The existing -cpu host code simply sets every bit inside svm_features (initializing it to -1), and that makes it impossible to make the enforce/check options work properly when the user asks for SVM features explicitly in the command-line. So, instead of initializing svm_features to -1, use GET_SUPPORTED_CPUID to fill only the bits that are supported by the host (just like we do for all other CPUID feature words inside kvm_cpu_fill_host()). This will keep the existing behavior (as filter_features_for_kvm() already uses GET_SUPPORTED_CPUID to filter svm_features), but will allow us to properly check for KVM features inside kvm_check_features_against_host() later. For example, we will be able to make this: $ qemu-system-x86_64 -cpu ...,+pfthreshold,enforce refuse to start if the SVM "pfthreshold" feature is not supported by the host (after we fix kvm_check_features_against_host() to check SVM flags as well). Signed-off-by: Eduardo Habkost Reviewed-by: Gleb Natapov Signed-off-by: Andreas Färber --- target-i386/cpu.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 82685dc3f5..1e30015be9 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -897,13 +897,10 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) } } - /* - * Every SVM feature requires emulation support in KVM - so we can't just - * read the host features here. KVM might even support SVM features not - * available on the host hardware. Just set all bits and mask out the - * unsupported ones later. - */ - x86_cpu_def->svm_features = -1; + /* Other KVM-specific feature fields: */ + x86_cpu_def->svm_features = + kvm_arch_get_supported_cpuid(s, 0x8000000A, 0, R_EDX); + #endif /* CONFIG_KVM */ } From bd004beff8db09b5790b1bb19fad3974e112f007 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Fri, 4 Jan 2013 20:01:05 -0200 Subject: [PATCH 2244/2270] target-i386: kvm: Enable all supported KVM features for -cpu host MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using -cpu host, we don't need to use the kvm_default_features variable, as the user is explicitly asking QEMU to enable all feature supported by the host. This changes the kvm_cpu_fill_host() code to use GET_SUPPORTED_CPUID to initialize the kvm_features field, so we get all host KVM features enabled. This will also allow us to properly check/enforce KVM features inside kvm_check_features_against_host() later. For example, we will be able to make this: $ qemu-system-x86_64 -cpu ...,+kvm_pv_eoi,enforce refuse to start if kvm_pv_eoi is not supported by the host (after we fix kvm_check_features_against_host() to check KVM flags as well). Signed-off-by: Eduardo Habkost Reviewed-by: Gleb Natapov Signed-off-by: Andreas Färber --- target-i386/cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 1e30015be9..2547bfabf1 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -900,6 +900,8 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) /* Other KVM-specific feature fields: */ x86_cpu_def->svm_features = kvm_arch_get_supported_cpuid(s, 0x8000000A, 0, R_EDX); + x86_cpu_def->kvm_features = + kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); #endif /* CONFIG_KVM */ } From 8b4beddc6bead9d7c85fe690b62f2621574eb195 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Fri, 4 Jan 2013 20:01:06 -0200 Subject: [PATCH 2245/2270] target-i386: check/enforce: Fix CPUID leaf numbers on error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The -cpu check/enforce warnings are printing incorrect information about the missing flags. There are no feature flags on CPUID leaves 0 and 0x80000000, but there were references to 0 and 0x80000000 in the table at kvm_check_features_against_host(). This changes the model_features_t struct to contain the register number as well, so the error messages print the correct CPUID leaf+register information, instead of wrong CPUID leaf numbers. This also changes the format of the error messages, so they follow the "CPUID... [bit ]" convention used in Intel documentation. Example output: $ qemu-system-x86_64 -machine pc-1.0,accel=kvm -cpu Opteron_G4,+ia64,enforce warning: host doesn't support requested feature: CPUID.01H:EDX.ia64 [bit 30] warning: host doesn't support requested feature: CPUID.01H:ECX.xsave [bit 26] warning: host doesn't support requested feature: CPUID.01H:ECX.avx [bit 28] warning: host doesn't support requested feature: CPUID.80000001H:ECX.abm [bit 5] warning: host doesn't support requested feature: CPUID.80000001H:ECX.sse4a [bit 6] warning: host doesn't support requested feature: CPUID.80000001H:ECX.misalignsse [bit 7] warning: host doesn't support requested feature: CPUID.80000001H:ECX.3dnowprefetch [bit 8] warning: host doesn't support requested feature: CPUID.80000001H:ECX.xop [bit 11] warning: host doesn't support requested feature: CPUID.80000001H:ECX.fma4 [bit 16] Unable to find x86 CPU definition $ Signed-off-by: Eduardo Habkost Reviewed-by: Gleb Natapov Signed-off-by: Andreas Färber --- target-i386/cpu.c | 42 +++++++++++++++++++++++++++++++++--------- target-i386/cpu.h | 3 +++ 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 2547bfabf1..ddf70248a0 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -124,6 +124,25 @@ static const char *cpuid_7_0_ebx_feature_name[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; +const char *get_register_name_32(unsigned int reg) +{ + static const char *reg_names[CPU_NB_REGS32] = { + [R_EAX] = "EAX", + [R_ECX] = "ECX", + [R_EDX] = "EDX", + [R_EBX] = "EBX", + [R_ESP] = "ESP", + [R_EBP] = "EBP", + [R_ESI] = "ESI", + [R_EDI] = "EDI", + }; + + if (reg > CPU_NB_REGS32) { + return NULL; + } + return reg_names[reg]; +} + /* collects per-function cpuid data */ typedef struct model_features_t { @@ -132,7 +151,8 @@ typedef struct model_features_t { uint32_t check_feat; const char **flag_names; uint32_t cpuid; - } model_features_t; + int reg; +} model_features_t; int check_cpuid = 0; int enforce_cpuid = 0; @@ -912,10 +932,13 @@ static int unavailable_host_feature(struct model_features_t *f, uint32_t mask) for (i = 0; i < 32; ++i) if (1 << i & mask) { - fprintf(stderr, "warning: host cpuid %04x_%04x lacks requested" - " flag '%s' [0x%08x]\n", - f->cpuid >> 16, f->cpuid & 0xffff, - f->flag_names[i] ? f->flag_names[i] : "[reserved]", mask); + const char *reg = get_register_name_32(f->reg); + assert(reg); + fprintf(stderr, "warning: host doesn't support requested feature: " + "CPUID.%02XH:%s%s%s [bit %d]\n", + f->cpuid, reg, + f->flag_names[i] ? "." : "", + f->flag_names[i] ? f->flag_names[i] : "", i); break; } return 0; @@ -934,13 +957,14 @@ static int kvm_check_features_against_host(x86_def_t *guest_def) int rv, i; struct model_features_t ft[] = { {&guest_def->features, &host_def.features, - ~0, feature_name, 0x00000000}, + ~0, feature_name, 0x00000001, R_EDX}, {&guest_def->ext_features, &host_def.ext_features, - ~CPUID_EXT_HYPERVISOR, ext_feature_name, 0x00000001}, + ~CPUID_EXT_HYPERVISOR, ext_feature_name, 0x00000001, R_ECX}, {&guest_def->ext2_features, &host_def.ext2_features, - ~PPRO_FEATURES, ext2_feature_name, 0x80000000}, + ~PPRO_FEATURES, ext2_feature_name, 0x80000001, R_EDX}, {&guest_def->ext3_features, &host_def.ext3_features, - ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}}; + ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001, R_ECX} + }; assert(kvm_enabled()); diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 1283537108..e56921bbe3 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1220,4 +1220,7 @@ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access); void enable_kvm_pv_eoi(void); +/* Return name of 32-bit register, from a R_* constant */ +const char *get_register_name_32(unsigned int reg); + #endif /* CPU_I386_H */ From 54830ff84df5d1fb182e91bf40e3d7c66c2559a4 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Fri, 4 Jan 2013 20:01:07 -0200 Subject: [PATCH 2246/2270] target-i386: check/enforce: Do not ignore "hypervisor" flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't need any hack to ignore CPUID_EXT_HYPERVISOR anymore, because kvm_arch_get_supported_cpuid() now sets CPUID_EXT_HYPERVISOR properly. So, this shouldn't introduce any behavior change, but it makes the code simpler. Signed-off-by: Eduardo Habkost Reviewed-by: Gleb Natapov Signed-off-by: Andreas Färber --- target-i386/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index ddf70248a0..a3d104d7dc 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -959,7 +959,7 @@ static int kvm_check_features_against_host(x86_def_t *guest_def) {&guest_def->features, &host_def.features, ~0, feature_name, 0x00000001, R_EDX}, {&guest_def->ext_features, &host_def.ext_features, - ~CPUID_EXT_HYPERVISOR, ext_feature_name, 0x00000001, R_ECX}, + ~0, ext_feature_name, 0x00000001, R_ECX}, {&guest_def->ext2_features, &host_def.ext2_features, ~PPRO_FEATURES, ext2_feature_name, 0x80000001, R_EDX}, {&guest_def->ext3_features, &host_def.ext3_features, From 227146259e8deb14b7b30e7718e61512e0f524a9 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Fri, 4 Jan 2013 20:01:08 -0200 Subject: [PATCH 2247/2270] target-i386: check/enforce: Check all CPUID.80000001H.EDX bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I have no idea why PPRO_FEATURES was being ignored on the check of the CPUID.80000001H.EDX bits. I believe it was a mistake, and it was supposed to be ~(PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) or just ~CPUID_EXT2_AMD_ALIASES, because some time ago kvm_cpu_fill_host() used the CPUID instruction directly (instead of kvm_arch_get_supported_cpuid()). But now kvm_cpu_fill_host() uses kvm_arch_get_supported_cpuid(), and kvm_arch_get_supported_cpuid() returns all supported bits for CPUID.80000001H.EDX, even the AMD aliases (that are explicitly copied from CPUID.01H.EDX), so we can make the code check/enforce all the CPUID.80000001H.EDX bits. Signed-off-by: Eduardo Habkost Reviewed-by: Gleb Natapov Signed-off-by: Andreas Färber --- target-i386/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index a3d104d7dc..a2971d27eb 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -961,7 +961,7 @@ static int kvm_check_features_against_host(x86_def_t *guest_def) {&guest_def->ext_features, &host_def.ext_features, ~0, ext_feature_name, 0x00000001, R_ECX}, {&guest_def->ext2_features, &host_def.ext2_features, - ~PPRO_FEATURES, ext2_feature_name, 0x80000001, R_EDX}, + ~0, ext2_feature_name, 0x80000001, R_EDX}, {&guest_def->ext3_features, &host_def.ext3_features, ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001, R_ECX} }; From 396d2cfccdc1a46a8c66d9d9baaa59071a553b1c Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Fri, 4 Jan 2013 20:01:09 -0200 Subject: [PATCH 2248/2270] target-i386: check/enforce: Check SVM flag support as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When nested SVM is supported, the kernel returns the SVM flag on GET_SUPPORTED_CPUID[1], so we can check the SVM flag safely in kvm_check_features_against_host(). I don't know why the original code ignored the SVM flag. Maybe it was because kvm_cpu_fill_host() used the CPUID instruction directly instead of GET_SUPPORTED_CPUID [1] Older kernels (before v2.6.37) returned the SVM flag even if nested SVM was _not_ supported. So the only cases where this patch should change behavior is when SVM is being requested by the user or the CPU model, but not supported by the host. And on these cases we really want QEMU to abort if the "enforce" option is set. Signed-off-by: Eduardo Habkost Reviewed-by: Gleb Natapov Signed-off-by: Andreas Färber --- target-i386/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index a2971d27eb..535cd52d17 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -963,7 +963,7 @@ static int kvm_check_features_against_host(x86_def_t *guest_def) {&guest_def->ext2_features, &host_def.ext2_features, ~0, ext2_feature_name, 0x80000001, R_EDX}, {&guest_def->ext3_features, &host_def.ext3_features, - ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001, R_ECX} + ~0, ext3_feature_name, 0x80000001, R_ECX} }; assert(kvm_enabled()); From e8beac00bd26a60e788ab336f38bc12a95b20f0d Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Fri, 4 Jan 2013 20:01:10 -0200 Subject: [PATCH 2249/2270] target-i386: check/enforce: Eliminate check_feat field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that all entries have check_feat=~0 in kvm_check_features_against_host(), we can eliminate check_feat entirely and make the code check all bits. This patch shouldn't introduce any behavior change, as check_feat is set to ~0 on all entries. Signed-off-by: Eduardo Habkost Reviewed-by: Gleb Natapov Signed-off-by: Andreas Färber --- target-i386/cpu.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 535cd52d17..951e206779 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -148,7 +148,6 @@ const char *get_register_name_32(unsigned int reg) typedef struct model_features_t { uint32_t *guest_feat; uint32_t *host_feat; - uint32_t check_feat; const char **flag_names; uint32_t cpuid; int reg; @@ -945,8 +944,7 @@ static int unavailable_host_feature(struct model_features_t *f, uint32_t mask) } /* best effort attempt to inform user requested cpu flags aren't making - * their way to the guest. Note: ft[].check_feat ideally should be - * specified via a guest_def field to suppress report of extraneous flags. + * their way to the guest. * * This function may be called only if KVM is enabled. */ @@ -957,13 +955,13 @@ static int kvm_check_features_against_host(x86_def_t *guest_def) int rv, i; struct model_features_t ft[] = { {&guest_def->features, &host_def.features, - ~0, feature_name, 0x00000001, R_EDX}, + feature_name, 0x00000001, R_EDX}, {&guest_def->ext_features, &host_def.ext_features, - ~0, ext_feature_name, 0x00000001, R_ECX}, + ext_feature_name, 0x00000001, R_ECX}, {&guest_def->ext2_features, &host_def.ext2_features, - ~0, ext2_feature_name, 0x80000001, R_EDX}, + ext2_feature_name, 0x80000001, R_EDX}, {&guest_def->ext3_features, &host_def.ext3_features, - ~0, ext3_feature_name, 0x80000001, R_ECX} + ext3_feature_name, 0x80000001, R_ECX} }; assert(kvm_enabled()); @@ -971,7 +969,7 @@ static int kvm_check_features_against_host(x86_def_t *guest_def) kvm_cpu_fill_host(&host_def); for (rv = 0, i = 0; i < ARRAY_SIZE(ft); ++i) for (mask = 1; mask; mask <<= 1) - if (ft[i].check_feat & mask && *ft[i].guest_feat & mask && + if (*ft[i].guest_feat & mask && !(*ft[i].host_feat & mask)) { unavailable_host_feature(&ft[i], mask); rv = 1; From 75a192aa68e7801ab8465b3345ac74d6d3cdceca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sat, 5 Jan 2013 14:44:08 +0100 Subject: [PATCH 2250/2270] qemu-common.h: Make qemu_init_vcpu() stub static inline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turn the *-user macro into a no-op inline function to avoid unused-variable warnings and band-aiding #ifdef'ery. This allows to drop an #ifdef for alpha and avoids more for unicore32 and other upcoming trivial realizefn implementations. Suggested-by: Lluís Vilanova Signed-off-by: Eduardo Habkost Signed-off-by: Andreas Färber Reviewed-by: Eduardo Habkost --- include/qemu-common.h | 4 +++- target-alpha/cpu.c | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/qemu-common.h b/include/qemu-common.h index 2b83de395c..ca464bb367 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -288,7 +288,9 @@ struct qemu_work_item { }; #ifdef CONFIG_USER_ONLY -#define qemu_init_vcpu(env) do { } while (0) +static inline void qemu_init_vcpu(void *env) +{ +} #else void qemu_init_vcpu(void *env); #endif diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c index 212a6250ba..40e980933f 100644 --- a/target-alpha/cpu.c +++ b/target-alpha/cpu.c @@ -26,11 +26,9 @@ static void alpha_cpu_realize(Object *obj, Error **errp) { -#ifndef CONFIG_USER_ONLY AlphaCPU *cpu = ALPHA_CPU(obj); qemu_init_vcpu(&cpu->env); -#endif } /* Sort alphabetically by type name. */ From 4586f157757acc5c8edcc954289c7aa51661235c Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 28 Dec 2012 21:01:16 +0100 Subject: [PATCH 2251/2270] target-i386: Filter out unsupported features at realize time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Eduardo Habkost Signed-off-by: Igor Mammedov Reviewed-by: Eduardo Habkost Signed-off-by: Andreas Färber --- target-i386/cpu.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 951e206779..a776e1118d 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1571,21 +1571,6 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) env->cpuid_ext2_features |= (def->features & CPUID_EXT2_AMD_ALIASES); } - if (!kvm_enabled()) { - env->cpuid_features &= TCG_FEATURES; - env->cpuid_ext_features &= TCG_EXT_FEATURES; - env->cpuid_ext2_features &= (TCG_EXT2_FEATURES -#ifdef TARGET_X86_64 - | CPUID_EXT2_SYSCALL | CPUID_EXT2_LM -#endif - ); - env->cpuid_ext3_features &= TCG_EXT3_FEATURES; - env->cpuid_svm_features &= TCG_SVM_FEATURES; - } else { -#ifdef CONFIG_KVM - filter_features_for_kvm(cpu); -#endif - } object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error); if (error) { fprintf(stderr, "%s\n", error_get_pretty(error)); @@ -2106,6 +2091,22 @@ void x86_cpu_realize(Object *obj, Error **errp) env->cpuid_level = 7; } + if (!kvm_enabled()) { + env->cpuid_features &= TCG_FEATURES; + env->cpuid_ext_features &= TCG_EXT_FEATURES; + env->cpuid_ext2_features &= (TCG_EXT2_FEATURES +#ifdef TARGET_X86_64 + | CPUID_EXT2_SYSCALL | CPUID_EXT2_LM +#endif + ); + env->cpuid_ext3_features &= TCG_EXT3_FEATURES; + env->cpuid_svm_features &= TCG_SVM_FEATURES; + } else { +#ifdef CONFIG_KVM + filter_features_for_kvm(cpu); +#endif + } + #ifndef CONFIG_USER_ONLY qemu_register_reset(x86_cpu_machine_reset_cb, cpu); From 9b15cd9e7a1ab0827f4d01c4be77eb41f195073f Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 28 Dec 2012 21:01:17 +0100 Subject: [PATCH 2252/2270] target-i386: Sanitize AMD's ext2_features at realize time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When CPU properties are implemented, ext2_features may change between object_new(CPU) and cpu_realize_fn(). Sanitizing ext2_features for AMD based CPU at realize() time will keep current behavior after CPU features are converted to properties. Signed-off-by: Igor Mammedov Reviewed-by: Eduardo Habkost Signed-off-by: Andreas Färber --- target-i386/cpu.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index a776e1118d..b40cc37bac 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1561,16 +1561,6 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000, "tsc-frequency", &error); - /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on - * CPUID[1].EDX. - */ - if (env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && - env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && - env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) { - env->cpuid_ext2_features &= ~CPUID_EXT2_AMD_ALIASES; - env->cpuid_ext2_features |= (def->features & CPUID_EXT2_AMD_ALIASES); - } - object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error); if (error) { fprintf(stderr, "%s\n", error_get_pretty(error)); @@ -2091,6 +2081,17 @@ void x86_cpu_realize(Object *obj, Error **errp) env->cpuid_level = 7; } + /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on + * CPUID[1].EDX. + */ + if (env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && + env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && + env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) { + env->cpuid_ext2_features &= ~CPUID_EXT2_AMD_ALIASES; + env->cpuid_ext2_features |= (env->cpuid_features + & CPUID_EXT2_AMD_ALIASES); + } + if (!kvm_enabled()) { env->cpuid_features &= TCG_FEATURES; env->cpuid_ext_features &= TCG_EXT_FEATURES; From ebe8b9c6eb6e425d44805288b6b5dabd69368f46 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 28 Dec 2012 21:01:18 +0100 Subject: [PATCH 2253/2270] target-i386: Explicitly set vendor for each built-in cpudef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since cpudef config is not supported anymore and all remaining sources now always set x86_def_t.vendor[123] fields, remove setting default vendor to simplify future re-factoring. Signed-off-by: Igor Mammedov Reviewed-by: Eduardo Habkost Signed-off-by: Andreas Färber --- target-i386/cpu.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index b40cc37bac..78bd61e18f 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -407,6 +407,9 @@ static x86_def_t builtin_x86_defs[] = { { .name = "core2duo", .level = 10, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, .family = 6, .model = 15, .stepping = 11, @@ -451,6 +454,9 @@ static x86_def_t builtin_x86_defs[] = { { .name = "qemu32", .level = 4, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, .family = 6, .model = 3, .stepping = 3, @@ -461,6 +467,9 @@ static x86_def_t builtin_x86_defs[] = { { .name = "kvm32", .level = 5, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, .family = 15, .model = 6, .stepping = 1, @@ -475,6 +484,9 @@ static x86_def_t builtin_x86_defs[] = { { .name = "coreduo", .level = 10, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, .family = 6, .model = 14, .stepping = 8, @@ -490,6 +502,9 @@ static x86_def_t builtin_x86_defs[] = { { .name = "486", .level = 1, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, .family = 4, .model = 0, .stepping = 0, @@ -499,6 +514,9 @@ static x86_def_t builtin_x86_defs[] = { { .name = "pentium", .level = 1, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, .family = 5, .model = 4, .stepping = 3, @@ -508,6 +526,9 @@ static x86_def_t builtin_x86_defs[] = { { .name = "pentium2", .level = 2, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, .family = 6, .model = 5, .stepping = 2, @@ -517,6 +538,9 @@ static x86_def_t builtin_x86_defs[] = { { .name = "pentium3", .level = 2, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, .family = 6, .model = 7, .stepping = 3, @@ -542,6 +566,9 @@ static x86_def_t builtin_x86_defs[] = { .name = "n270", /* original is on level 10 */ .level = 5, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, .family = 6, .model = 28, .stepping = 2, @@ -1534,15 +1561,10 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) if (cpu_x86_parse_featurestr(def, features) < 0) { goto error; } - if (def->vendor1) { - env->cpuid_vendor1 = def->vendor1; - env->cpuid_vendor2 = def->vendor2; - env->cpuid_vendor3 = def->vendor3; - } else { - env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1; - env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2; - env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3; - } + assert(def->vendor1); + env->cpuid_vendor1 = def->vendor1; + env->cpuid_vendor2 = def->vendor2; + env->cpuid_vendor3 = def->vendor3; env->cpuid_vendor_override = def->vendor_override; object_property_set_int(OBJECT(cpu), def->level, "level", &error); object_property_set_int(OBJECT(cpu), def->family, "family", &error); From b0223e29afdc88cc262a764026296414396cd129 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 8 Jan 2013 14:09:03 -0700 Subject: [PATCH 2254/2270] vfio-pci: Make host MSI-X enable track guest Guests typically enable MSI-X with all of the vectors in the MSI-X vector table masked. Only when the vector is enabled does the vector get unmasked, resulting in a vector_use callback. These two points, enable and unmask, correspond to pci_enable_msix() and request_irq() for Linux guests. Some drivers rely on VF/PF or PF/fw communication channels that expect the physical state of the device to match the guest visible state of the device. They don't appreciate lazily enabling MSI-X on the physical device. To solve this, enable MSI-X with a single vector when the MSI-X capability is enabled and immediate disable the vector. This leaves the physical device in exactly the same state between host and guest. Furthermore, the brief gap where we enable vector 0, it fires into userspace, not KVM, so the guest doesn't get spurious interrupts. Ideally we could call VFIO_DEVICE_SET_IRQS with the right parameters to enable MSI-X with zero vectors, but this will currently return an error as the Linux MSI-X interfaces do not allow it. Signed-off-by: Alex Williamson Cc: qemu-stable@nongnu.org --- hw/vfio_pci.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 28c83031d0..8ec1faf27e 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -562,8 +562,8 @@ static int vfio_enable_vectors(VFIODevice *vdev, bool msix) return ret; } -static int vfio_msix_vector_use(PCIDevice *pdev, - unsigned int nr, MSIMessage msg) +static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr, + MSIMessage *msg, IOHandler *handler) { VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev); VFIOMSIVector *vector; @@ -587,7 +587,7 @@ static int vfio_msix_vector_use(PCIDevice *pdev, * Attempt to enable route through KVM irqchip, * default to userspace handling if unavailable. */ - vector->virq = kvm_irqchip_add_msi_route(kvm_state, msg); + vector->virq = msg ? kvm_irqchip_add_msi_route(kvm_state, *msg) : -1; if (vector->virq < 0 || kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt, vector->virq) < 0) { @@ -596,7 +596,7 @@ static int vfio_msix_vector_use(PCIDevice *pdev, vector->virq = -1; } qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), - vfio_msi_interrupt, NULL, vector); + handler, NULL, vector); } /* @@ -639,6 +639,12 @@ static int vfio_msix_vector_use(PCIDevice *pdev, return 0; } +static int vfio_msix_vector_use(PCIDevice *pdev, + unsigned int nr, MSIMessage msg) +{ + return vfio_msix_vector_do_use(pdev, nr, &msg, vfio_msi_interrupt); +} + static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr) { VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev); @@ -697,6 +703,22 @@ static void vfio_enable_msix(VFIODevice *vdev) vdev->interrupt = VFIO_INT_MSIX; + /* + * Some communication channels between VF & PF or PF & fw rely on the + * physical state of the device and expect that enabling MSI-X from the + * guest enables the same on the host. When our guest is Linux, the + * guest driver call to pci_enable_msix() sets the enabling bit in the + * MSI-X capability, but leaves the vector table masked. We therefore + * can't rely on a vector_use callback (from request_irq() in the guest) + * to switch the physical device into MSI-X mode because that may come a + * long time after pci_enable_msix(). This code enables vector 0 with + * triggering to userspace, then immediately release the vector, leaving + * the physical device with no vectors enabled, but MSI-X enabled, just + * like the guest view. + */ + vfio_msix_vector_do_use(&vdev->pdev, 0, NULL, NULL); + vfio_msix_vector_release(&vdev->pdev, 0); + if (msix_set_vector_notifiers(&vdev->pdev, vfio_msix_vector_use, vfio_msix_vector_release, NULL)) { error_report("vfio: msix_set_vector_notifiers failed\n"); From 8fc94e5a8046e349e07976f9bcaffbcd5833f3a2 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 8 Jan 2013 14:10:03 -0700 Subject: [PATCH 2255/2270] vfio-pci: Loosen sanity checks to allow future features VFIO_PCI_NUM_REGIONS and VFIO_PCI_NUM_IRQS should never have been used in this manner as it locks a specific kernel implementation. Future features may introduce new regions or interrupt entries (VGA may add legacy ranges, AER might add an IRQ for error signalling). Fix this before it gets us into trouble. Signed-off-by: Alex Williamson Cc: qemu-stable@nongnu.org --- hw/vfio_pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 8ec1faf27e..c51ae6761b 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -1837,13 +1837,13 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev) error_report("Warning, device %s does not support reset\n", name); } - if (dev_info.num_regions != VFIO_PCI_NUM_REGIONS) { + if (dev_info.num_regions < VFIO_PCI_CONFIG_REGION_INDEX + 1) { error_report("vfio: unexpected number of io regions %u\n", dev_info.num_regions); goto error; } - if (dev_info.num_irqs != VFIO_PCI_NUM_IRQS) { + if (dev_info.num_irqs < VFIO_PCI_MSIX_IRQ_INDEX + 1) { error_report("vfio: unexpected number of irqs %u\n", dev_info.num_irqs); goto error; } From a9de6d01df3153b2ac0cade11e26a66d596d7166 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Tue, 27 Nov 2012 11:01:55 -0200 Subject: [PATCH 2256/2270] qemu-ga: guest_file_handle_find(): take an Error argument Signed-off-by: Luiz Capitulino Reviewed-by: Michael Roth *Fixed missing space character in error message Signed-off-by: Michael Roth --- qga/commands-posix.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index a657201e7a..bbef66dc6a 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -111,7 +111,7 @@ static void guest_file_handle_add(FILE *fh) QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next); } -static GuestFileHandle *guest_file_handle_find(int64_t id) +static GuestFileHandle *guest_file_handle_find(int64_t id, Error **err) { GuestFileHandle *gfh; @@ -122,6 +122,7 @@ static GuestFileHandle *guest_file_handle_find(int64_t id) } } + error_setg(err, "handle '%" PRId64 "' has not been found", id); return NULL; } @@ -160,12 +161,11 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, E void qmp_guest_file_close(int64_t handle, Error **err) { - GuestFileHandle *gfh = guest_file_handle_find(handle); + GuestFileHandle *gfh = guest_file_handle_find(handle, err); int ret; slog("guest-file-close called, handle: %ld", handle); if (!gfh) { - error_set(err, QERR_FD_NOT_FOUND, "handle"); return; } @@ -182,14 +182,13 @@ void qmp_guest_file_close(int64_t handle, Error **err) struct GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count, int64_t count, Error **err) { - GuestFileHandle *gfh = guest_file_handle_find(handle); + GuestFileHandle *gfh = guest_file_handle_find(handle, err); GuestFileRead *read_data = NULL; guchar *buf; FILE *fh; size_t read_count; if (!gfh) { - error_set(err, QERR_FD_NOT_FOUND, "handle"); return NULL; } @@ -228,11 +227,10 @@ GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64, guchar *buf; gsize buf_len; int write_count; - GuestFileHandle *gfh = guest_file_handle_find(handle); + GuestFileHandle *gfh = guest_file_handle_find(handle, err); FILE *fh; if (!gfh) { - error_set(err, QERR_FD_NOT_FOUND, "handle"); return NULL; } @@ -265,13 +263,12 @@ GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64, struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset, int64_t whence, Error **err) { - GuestFileHandle *gfh = guest_file_handle_find(handle); + GuestFileHandle *gfh = guest_file_handle_find(handle, err); GuestFileSeek *seek_data = NULL; FILE *fh; int ret; if (!gfh) { - error_set(err, QERR_FD_NOT_FOUND, "handle"); return NULL; } @@ -291,12 +288,11 @@ struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset, void qmp_guest_file_flush(int64_t handle, Error **err) { - GuestFileHandle *gfh = guest_file_handle_find(handle); + GuestFileHandle *gfh = guest_file_handle_find(handle, err); FILE *fh; int ret; if (!gfh) { - error_set(err, QERR_FD_NOT_FOUND, "handle"); return; } From 3ac4b7c51e3ba181a86983ba2601a595ed8f3b1d Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Tue, 27 Nov 2012 11:01:56 -0200 Subject: [PATCH 2257/2270] qemu-ga: qmp_guest_file_close(): fix fclose() error check fclose() returns EOF on error. Signed-off-by: Luiz Capitulino Reviewed-by: Michael Roth Signed-off-by: Michael Roth --- qga/commands-posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index bbef66dc6a..ebb58be22e 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -170,7 +170,7 @@ void qmp_guest_file_close(int64_t handle, Error **err) } ret = fclose(gfh->fh); - if (ret == -1) { + if (ret == EOF) { error_set(err, QERR_QGA_COMMAND_FAILED, "fclose() failed"); return; } From db3edb665549979b44e0376ab9e859f58b89b503 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Tue, 27 Nov 2012 11:01:57 -0200 Subject: [PATCH 2258/2270] qemu-ga: qmp_guest_file_*: improve error reporting Use error_setg_errno() when possible with an improved error description. Signed-off-by: Luiz Capitulino Signed-off-by: Michael Roth --- qga/commands-posix.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index ebb58be22e..d5f2dcdc09 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -138,7 +138,8 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, E slog("guest-file-open called, filepath: %s, mode: %s", path, mode); fh = fopen(path, mode); if (!fh) { - error_set(err, QERR_OPEN_FILE_FAILED, path); + error_setg_errno(err, errno, "failed to open file '%s' (mode: '%s')", + path, mode); return -1; } @@ -149,7 +150,8 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, E ret = fcntl(fd, F_GETFL); ret = fcntl(fd, F_SETFL, ret | O_NONBLOCK); if (ret == -1) { - error_set(err, QERR_QGA_COMMAND_FAILED, "fcntl() failed"); + error_setg_errno(err, errno, "failed to make file '%s' non-blocking", + path); fclose(fh); return -1; } @@ -171,7 +173,7 @@ void qmp_guest_file_close(int64_t handle, Error **err) ret = fclose(gfh->fh); if (ret == EOF) { - error_set(err, QERR_QGA_COMMAND_FAILED, "fclose() failed"); + error_setg_errno(err, errno, "failed to close handle"); return; } @@ -195,7 +197,8 @@ struct GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count, if (!has_count) { count = QGA_READ_COUNT_DEFAULT; } else if (count < 0) { - error_set(err, QERR_INVALID_PARAMETER, "count"); + error_setg(err, "value '%" PRId64 "' is invalid for argument count", + count); return NULL; } @@ -203,8 +206,8 @@ struct GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count, buf = g_malloc0(count+1); 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); - error_set(err, QERR_QGA_COMMAND_FAILED, "fread() failed"); } else { buf[read_count] = 0; read_data = g_malloc0(sizeof(GuestFileRead)); @@ -240,15 +243,16 @@ GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64, if (!has_count) { count = buf_len; } else if (count < 0 || count > buf_len) { + error_setg(err, "value '%" PRId64 "' is invalid for argument count", + count); g_free(buf); - error_set(err, QERR_INVALID_PARAMETER, "count"); return NULL; } 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); - error_set(err, QERR_QGA_COMMAND_FAILED, "fwrite() error"); } else { write_data = g_malloc0(sizeof(GuestFileWrite)); write_data->count = write_count; @@ -275,7 +279,7 @@ struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset, fh = gfh->fh; ret = fseek(fh, offset, whence); if (ret == -1) { - error_set(err, QERR_QGA_COMMAND_FAILED, strerror(errno)); + error_setg_errno(err, errno, "failed to seek file"); } else { seek_data = g_malloc0(sizeof(GuestFileRead)); seek_data->position = ftell(fh); @@ -299,7 +303,7 @@ void qmp_guest_file_flush(int64_t handle, Error **err) fh = gfh->fh; ret = fflush(fh); if (ret == EOF) { - error_set(err, QERR_QGA_COMMAND_FAILED, strerror(errno)); + error_setg_errno(err, errno, "failed to flush file"); } } From d220a6dfea10655efe70d37748a3c23cf0a00647 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Tue, 27 Nov 2012 11:01:58 -0200 Subject: [PATCH 2259/2270] qemu-ga: qmp_guest_shutdown(): improve error reporting Most errors are QERR_UNDEFINED_ERROR. Also, adds ga_wait_child() as a future commit will use it too. Signed-off-by: Luiz Capitulino Reviewed-by: Michael Roth Signed-off-by: Michael Roth --- qga/commands-posix.c | 52 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index d5f2dcdc09..247e8dc855 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -46,10 +46,29 @@ extern char **environ; #endif #endif +static void ga_wait_child(pid_t pid, int *status, Error **err) +{ + pid_t rpid; + + *status = 0; + + do { + rpid = waitpid(pid, status, 0); + } while (rpid == -1 && errno == EINTR); + + if (rpid == -1) { + error_setg_errno(err, errno, "failed to wait for child (pid: %d)", pid); + return; + } + + g_assert(rpid == pid); +} + void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err) { const char *shutdown_flag; - pid_t rpid, pid; + Error *local_err = NULL; + pid_t pid; int status; slog("guest-shutdown called, mode: %s", mode); @@ -60,8 +79,8 @@ void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err) } else if (strcmp(mode, "reboot") == 0) { shutdown_flag = "-r"; } else { - error_set(err, QERR_INVALID_PARAMETER_VALUE, "mode", - "halt|powerdown|reboot"); + error_setg(err, + "mode is invalid (valid values are: halt|powerdown|reboot"); return; } @@ -77,18 +96,27 @@ void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err) "hypervisor initiated shutdown", (char*)NULL, environ); _exit(EXIT_FAILURE); } else if (pid < 0) { - goto exit_err; - } - - do { - rpid = waitpid(pid, &status, 0); - } while (rpid == -1 && errno == EINTR); - if (rpid == pid && WIFEXITED(status) && !WEXITSTATUS(status)) { + error_setg_errno(err, errno, "failed to create child process"); return; } -exit_err: - error_set(err, QERR_UNDEFINED_ERROR); + ga_wait_child(pid, &status, &local_err); + if (error_is_set(&local_err)) { + error_propagate(err, local_err); + return; + } + + if (!WIFEXITED(status)) { + error_setg(err, "child process has terminated abnormally"); + return; + } + + if (WEXITSTATUS(status)) { + error_setg(err, "child process has failed to shutdown"); + return; + } + + /* succeded */ } typedef struct GuestFileHandle { From 261551d1cc3a830e9623971dffa8033b216f1d63 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 29 Nov 2012 15:29:11 -0200 Subject: [PATCH 2260/2270] qemu-ga: build_fs_mount_list(): take an Error argument Signed-off-by: Luiz Capitulino Signed-off-by: Michael Roth --- qga/commands-posix.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 247e8dc855..f7b85b284c 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -371,7 +371,7 @@ static void free_fs_mount_list(FsMountList *mounts) /* * Walk the mount table and build a list of local file systems */ -static int build_fs_mount_list(FsMountList *mounts) +static void build_fs_mount_list(FsMountList *mounts, Error **err) { struct mntent *ment; FsMount *mount; @@ -380,8 +380,8 @@ static int build_fs_mount_list(FsMountList *mounts) fp = setmntent(mtab, "r"); if (!fp) { - g_warning("fsfreeze: unable to read mtab"); - return -1; + error_setg(err, "failed to open mtab file: '%s'", mtab); + return; } while ((ment = getmntent(fp))) { @@ -405,8 +405,6 @@ static int build_fs_mount_list(FsMountList *mounts) } endmntent(fp); - - return 0; } #endif @@ -433,15 +431,17 @@ int64_t qmp_guest_fsfreeze_freeze(Error **err) int ret = 0, i = 0; FsMountList mounts; struct FsMount *mount; + Error *local_err = NULL; int fd; char err_msg[512]; slog("guest-fsfreeze called"); QTAILQ_INIT(&mounts); - ret = build_fs_mount_list(&mounts); - if (ret < 0) { - return ret; + build_fs_mount_list(&mounts, &local_err); + if (error_is_set(&local_err)) { + error_propagate(err, local_err); + return -1; } /* cannot risk guest agent blocking itself on a write in this state */ @@ -498,12 +498,12 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err) FsMountList mounts; FsMount *mount; int fd, i = 0, logged; + Error *local_err = NULL; QTAILQ_INIT(&mounts); - ret = build_fs_mount_list(&mounts); - if (ret) { - error_set(err, QERR_QGA_COMMAND_FAILED, - "failed to enumerate filesystems"); + build_fs_mount_list(&mounts, &local_err); + if (error_is_set(&local_err)) { + error_propagate(err, local_err); return 0; } @@ -568,6 +568,7 @@ void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err) FsMountList mounts; struct FsMount *mount; int fd; + Error *local_err = NULL; char err_msg[512]; struct fstrim_range r = { .start = 0, @@ -578,8 +579,9 @@ void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err) slog("guest-fstrim called"); QTAILQ_INIT(&mounts); - ret = build_fs_mount_list(&mounts); - if (ret < 0) { + build_fs_mount_list(&mounts, &local_err); + if (error_is_set(&local_err)) { + error_propagate(err, local_err); return; } From 617fbbc13219d26dd71d100d83d617ec8acf5e2d Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Tue, 27 Nov 2012 11:02:00 -0200 Subject: [PATCH 2261/2270] qemu-ga: qmp_guest_fsfreeze_*(): get rid of sprintf() + error_set() Convert them to error_setg_errno(). Signed-off-by: Luiz Capitulino Reviewed-by: Michael Roth Signed-off-by: Michael Roth --- qga/commands-posix.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index f7b85b284c..9ad2891d77 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -433,7 +433,6 @@ int64_t qmp_guest_fsfreeze_freeze(Error **err) struct FsMount *mount; Error *local_err = NULL; int fd; - char err_msg[512]; slog("guest-fsfreeze called"); @@ -450,9 +449,7 @@ int64_t qmp_guest_fsfreeze_freeze(Error **err) QTAILQ_FOREACH(mount, &mounts, next) { fd = qemu_open(mount->dirname, O_RDONLY); if (fd == -1) { - sprintf(err_msg, "failed to open %s, %s", mount->dirname, - strerror(errno)); - error_set(err, QERR_QGA_COMMAND_FAILED, err_msg); + error_setg_errno(err, errno, "failed to open %s", mount->dirname); goto error; } @@ -468,9 +465,8 @@ int64_t qmp_guest_fsfreeze_freeze(Error **err) ret = ioctl(fd, FIFREEZE); if (ret == -1) { if (errno != EOPNOTSUPP) { - sprintf(err_msg, "failed to freeze %s, %s", - mount->dirname, strerror(errno)); - error_set(err, QERR_QGA_COMMAND_FAILED, err_msg); + error_setg_errno(err, errno, "failed to freeze %s", + mount->dirname); close(fd); goto error; } From 071673b09021b60eab268653c6bcfba92eea7603 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Tue, 27 Nov 2012 11:02:01 -0200 Subject: [PATCH 2262/2270] qemu-ga: qmp_guest_fstrim(): get rid of sprintf() + error_set() Convert them to error_setg_errno(). Signed-off-by: Luiz Capitulino Reviewed-by: Michael Roth Signed-off-by: Michael Roth --- qga/commands-posix.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 9ad2891d77..fa786e53e9 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -565,7 +565,6 @@ void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err) struct FsMount *mount; int fd; Error *local_err = NULL; - char err_msg[512]; struct fstrim_range r = { .start = 0, .len = -1, @@ -584,9 +583,7 @@ void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err) QTAILQ_FOREACH(mount, &mounts, next) { fd = qemu_open(mount->dirname, O_RDONLY); if (fd == -1) { - sprintf(err_msg, "failed to open %s, %s", mount->dirname, - strerror(errno)); - error_set(err, QERR_QGA_COMMAND_FAILED, err_msg); + error_setg_errno(err, errno, "failed to open %s", mount->dirname); goto error; } @@ -599,9 +596,8 @@ void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err) ret = ioctl(fd, FITRIM, &r); if (ret == -1) { if (errno != ENOTTY && errno != EOPNOTSUPP) { - sprintf(err_msg, "failed to trim %s, %s", - mount->dirname, strerror(errno)); - error_set(err, QERR_QGA_COMMAND_FAILED, err_msg); + error_setg_errno(err, errno, "failed to trim %s", + mount->dirname); close(fd); goto error; } From 878a0ae0ab3eb8428626e67995c9efad8eb1ba80 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Tue, 27 Nov 2012 11:02:02 -0200 Subject: [PATCH 2263/2270] qemu-ga: qmp_guest_network_get_interfaces(): get rid of snprintf() + error_set() Convert them to error_setg_errno(). Signed-off-by: Luiz Capitulino Reviewed-by: Michael Roth Signed-off-by: Michael Roth --- qga/commands-posix.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index fa786e53e9..9b6ef17260 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -802,12 +802,9 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) { GuestNetworkInterfaceList *head = NULL, *cur_item = NULL; struct ifaddrs *ifap, *ifa; - char err_msg[512]; if (getifaddrs(&ifap) < 0) { - snprintf(err_msg, sizeof(err_msg), - "getifaddrs failed: %s", strerror(errno)); - error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); + error_setg_errno(errp, errno, "getifaddrs failed"); goto error; } @@ -843,20 +840,16 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) /* we haven't obtained HW address yet */ sock = socket(PF_INET, SOCK_STREAM, 0); if (sock == -1) { - snprintf(err_msg, sizeof(err_msg), - "failed to create socket: %s", strerror(errno)); - error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); + error_setg_errno(errp, errno, "failed to create socket"); goto error; } memset(&ifr, 0, sizeof(ifr)); pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->value->name); if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) { - snprintf(err_msg, sizeof(err_msg), - "failed to get MAC address of %s: %s", - ifa->ifa_name, - strerror(errno)); - error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); + error_setg_errno(errp, errno, + "failed to get MAC address of %s", + ifa->ifa_name); goto error; } @@ -867,9 +860,7 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) (int) mac_addr[0], (int) mac_addr[1], (int) mac_addr[2], (int) mac_addr[3], (int) mac_addr[4], (int) mac_addr[5]) == -1) { - snprintf(err_msg, sizeof(err_msg), - "failed to format MAC: %s", strerror(errno)); - error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); + error_setg_errno(errp, errno, "failed to format MAC"); goto error; } @@ -884,9 +875,7 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) address_item->value = g_malloc0(sizeof(*address_item->value)); p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) { - snprintf(err_msg, sizeof(err_msg), - "inet_ntop failed : %s", strerror(errno)); - error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); + error_setg_errno(errp, errno, "inet_ntop failed"); goto error; } @@ -906,9 +895,7 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) address_item->value = g_malloc0(sizeof(*address_item->value)); p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) { - snprintf(err_msg, sizeof(err_msg), - "inet_ntop failed : %s", strerror(errno)); - error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); + error_setg_errno(errp, errno, "inet_ntop failed"); goto error; } From 6b26e837a40a7bed14080fb9029ad6c22409f8b3 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Tue, 27 Nov 2012 11:02:03 -0200 Subject: [PATCH 2264/2270] qemu-ga: bios_supports_mode(): improve error reporting Most errors are QERR_UNDEFINED_ERROR today. Signed-off-by: Luiz Capitulino Reviewed-by: Michael Roth Signed-off-by: Michael Roth --- qga/commands-posix.c | 54 +++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 9b6ef17260..f3ee492633 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -618,8 +618,9 @@ error: static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg, const char *sysfile_str, Error **err) { + Error *local_err = NULL; char *pmutils_path; - pid_t pid, rpid; + pid_t pid; int status; pmutils_path = g_find_program_in_path(pmutils_bin); @@ -664,31 +665,38 @@ static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg, } _exit(SUSPEND_NOT_SUPPORTED); + } else if (pid < 0) { + error_setg_errno(err, errno, "failed to create child process"); + goto out; } + ga_wait_child(pid, &status, &local_err); + if (error_is_set(&local_err)) { + error_propagate(err, local_err); + goto out; + } + + if (!WIFEXITED(status)) { + error_setg(err, "child process has terminated abnormally"); + goto out; + } + + switch (WEXITSTATUS(status)) { + case SUSPEND_SUPPORTED: + goto out; + case SUSPEND_NOT_SUPPORTED: + error_setg(err, + "the requested suspend mode is not supported by the guest"); + goto out; + default: + error_setg(err, + "the helper program '%s' returned an unexpected exit status" + " code (%d)", pmutils_path, WEXITSTATUS(status)); + goto out; + } + +out: g_free(pmutils_path); - - if (pid < 0) { - goto undef_err; - } - - do { - rpid = waitpid(pid, &status, 0); - } while (rpid == -1 && errno == EINTR); - if (rpid == pid && WIFEXITED(status)) { - switch (WEXITSTATUS(status)) { - case SUSPEND_SUPPORTED: - return; - case SUSPEND_NOT_SUPPORTED: - error_set(err, QERR_UNSUPPORTED); - return; - default: - goto undef_err; - } - } - -undef_err: - error_set(err, QERR_UNDEFINED_ERROR); } static void guest_suspend(const char *pmutils_bin, const char *sysfile_str, From 7b3760879bf323a0d9654a5158d5b3ed51882505 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Tue, 27 Nov 2012 11:02:04 -0200 Subject: [PATCH 2265/2270] qemu-ga: guest_suspend(): improve error reporting Most errors are QERR_UNDEFINED_ERROR today. Signed-off-by: Luiz Capitulino Reviewed-by: Michael Roth Signed-off-by: Michael Roth --- qga/commands-posix.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index f3ee492633..614a421ffd 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -702,8 +702,9 @@ out: static void guest_suspend(const char *pmutils_bin, const char *sysfile_str, Error **err) { + Error *local_err = NULL; char *pmutils_path; - pid_t rpid, pid; + pid_t pid; int status; pmutils_path = g_find_program_in_path(pmutils_bin); @@ -741,23 +742,29 @@ static void guest_suspend(const char *pmutils_bin, const char *sysfile_str, } _exit(EXIT_SUCCESS); + } else if (pid < 0) { + error_setg_errno(err, errno, "failed to create child process"); + goto out; } + ga_wait_child(pid, &status, &local_err); + if (error_is_set(&local_err)) { + error_propagate(err, local_err); + goto out; + } + + if (!WIFEXITED(status)) { + error_setg(err, "child process has terminated abnormally"); + goto out; + } + + if (WEXITSTATUS(status)) { + error_setg(err, "child process has failed to suspend"); + goto out; + } + +out: g_free(pmutils_path); - - if (pid < 0) { - goto exit_err; - } - - do { - rpid = waitpid(pid, &status, 0); - } while (rpid == -1 && errno == EINTR); - if (rpid == pid && WIFEXITED(status) && !WEXITSTATUS(status)) { - return; - } - -exit_err: - error_set(err, QERR_UNDEFINED_ERROR); } void qmp_guest_suspend_disk(Error **err) From ec0f694c11e8e0958d727e40e0759ab99e5908d6 Mon Sep 17 00:00:00 2001 From: Tomoki Sekiyama Date: Wed, 12 Dec 2012 12:55:55 +0900 Subject: [PATCH 2266/2270] qemu-ga: execute hook to quiesce the guest on fsfreeze-freeze/thaw To use the online disk snapshot for online-backup, application-level consistency of the snapshot image is required. However, currently the guest agent can provide only filesystem-level consistency, and the snapshot may contain dirty data, for example, incomplete transactions. This patch provides the opportunity to quiesce applications before snapshot is taken. If --fsfreeze-hook option is specified, the hook is executed with "freeze" argument before the filesystem is frozen by fsfreeze-freeze command. As for fsfreeze-thaw command, the hook is executed with "thaw" argument after the filesystem is thawed. This patch depends on patchset to improve error reporting by Luiz Capitulino: http://lists.gnu.org/archive/html/qemu-devel/2012-11/msg03016.html Signed-off-by: Tomoki Sekiyama Reviewed-by: Luiz Capitulino *clarified usage in help output Signed-off-by: Michael Roth --- qga/commands-posix.c | 69 ++++++++++++++++++++++++++++++++++++++++++ qga/guest-agent-core.h | 1 + qga/main.c | 48 ++++++++++++++++++++++++++++- 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 614a421ffd..77f6ee7d5f 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -410,6 +410,66 @@ static void build_fs_mount_list(FsMountList *mounts, Error **err) #if defined(CONFIG_FSFREEZE) +typedef enum { + FSFREEZE_HOOK_THAW = 0, + FSFREEZE_HOOK_FREEZE, +} FsfreezeHookArg; + +const char *fsfreeze_hook_arg_string[] = { + "thaw", + "freeze", +}; + +static void execute_fsfreeze_hook(FsfreezeHookArg arg, Error **err) +{ + int status; + pid_t pid; + const char *hook; + const char *arg_str = fsfreeze_hook_arg_string[arg]; + Error *local_err = NULL; + + hook = ga_fsfreeze_hook(ga_state); + if (!hook) { + return; + } + if (access(hook, X_OK) != 0) { + error_setg_errno(err, errno, "can't access fsfreeze hook '%s'", hook); + return; + } + + slog("executing fsfreeze hook with arg '%s'", arg_str); + pid = fork(); + if (pid == 0) { + setsid(); + reopen_fd_to_null(0); + reopen_fd_to_null(1); + reopen_fd_to_null(2); + + execle(hook, hook, arg_str, NULL, environ); + _exit(EXIT_FAILURE); + } else if (pid < 0) { + error_setg_errno(err, errno, "failed to create child process"); + return; + } + + ga_wait_child(pid, &status, &local_err); + if (error_is_set(&local_err)) { + error_propagate(err, local_err); + return; + } + + if (!WIFEXITED(status)) { + error_setg(err, "fsfreeze hook has terminated abnormally"); + return; + } + + status = WEXITSTATUS(status); + if (status) { + error_setg(err, "fsfreeze hook has failed with status %d", status); + return; + } +} + /* * Return status of freeze/thaw */ @@ -436,6 +496,12 @@ int64_t qmp_guest_fsfreeze_freeze(Error **err) slog("guest-fsfreeze called"); + execute_fsfreeze_hook(FSFREEZE_HOOK_FREEZE, &local_err); + if (error_is_set(&local_err)) { + error_propagate(err, local_err); + return -1; + } + QTAILQ_INIT(&mounts); build_fs_mount_list(&mounts, &local_err); if (error_is_set(&local_err)) { @@ -537,6 +603,9 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err) ga_unset_frozen(ga_state); free_fs_mount_list(&mounts); + + execute_fsfreeze_hook(FSFREEZE_HOOK_THAW, err); + return i; } diff --git a/qga/guest-agent-core.h b/qga/guest-agent-core.h index 8934163375..3354598362 100644 --- a/qga/guest-agent-core.h +++ b/qga/guest-agent-core.h @@ -34,6 +34,7 @@ void ga_set_response_delimited(GAState *s); bool ga_is_frozen(GAState *s); void ga_set_frozen(GAState *s); void ga_unset_frozen(GAState *s); +const char *ga_fsfreeze_hook(GAState *s); #ifndef _WIN32 void reopen_fd_to_null(int fd); diff --git a/qga/main.c b/qga/main.c index ba5fa1c778..a9b968c507 100644 --- a/qga/main.c +++ b/qga/main.c @@ -34,6 +34,12 @@ #include "qga/service-win32.h" #include #endif +#ifdef __linux__ +#include +#ifdef FIFREEZE +#define CONFIG_FSFREEZE +#endif +#endif #ifndef _WIN32 #define QGA_VIRTIO_PATH_DEFAULT "/dev/virtio-ports/org.qemu.guest_agent.0" @@ -42,6 +48,9 @@ #endif #define QGA_STATEDIR_DEFAULT CONFIG_QEMU_LOCALSTATEDIR "/run" #define QGA_PIDFILE_DEFAULT QGA_STATEDIR_DEFAULT "/qemu-ga.pid" +#ifdef CONFIG_FSFREEZE +#define QGA_FSFREEZE_HOOK_DEFAULT CONFIG_QEMU_CONFDIR "/fsfreeze-hook" +#endif #define QGA_SENTINEL_BYTE 0xFF struct GAState { @@ -64,6 +73,9 @@ struct GAState { const char *log_filepath; const char *pid_filepath; } deferred_options; +#ifdef CONFIG_FSFREEZE + const char *fsfreeze_hook; +#endif }; struct GAState *ga_state; @@ -153,6 +165,16 @@ static void usage(const char *cmd) " %s)\n" " -l, --logfile set logfile path, logs to stderr by default\n" " -f, --pidfile specify pidfile (default is %s)\n" +#ifdef CONFIG_FSFREEZE +" -F, --fsfreeze-hook\n" +" enable fsfreeze hook. Accepts an optional argument that\n" +" specifies script to run on freeze/thaw. Script will be\n" +" called with 'freeze'/'thaw' arguments accordingly.\n" +" (default is %s)\n" +" If using -F with an argument, do not follow -F with a\n" +" space.\n" +" (for example: -F/var/run/fsfreezehook.sh)\n" +#endif " -t, --statedir specify dir to store state information (absolute paths\n" " only, default is %s)\n" " -v, --verbose log extra debugging information\n" @@ -167,6 +189,9 @@ static void usage(const char *cmd) "\n" "Report bugs to \n" , cmd, QEMU_VERSION, QGA_VIRTIO_PATH_DEFAULT, QGA_PIDFILE_DEFAULT, +#ifdef CONFIG_FSFREEZE + QGA_FSFREEZE_HOOK_DEFAULT, +#endif QGA_STATEDIR_DEFAULT); } @@ -401,6 +426,13 @@ void ga_unset_frozen(GAState *s) } } +#ifdef CONFIG_FSFREEZE +const char *ga_fsfreeze_hook(GAState *s) +{ + return s->fsfreeze_hook; +} +#endif + static void become_daemon(const char *pidfile) { #ifndef _WIN32 @@ -678,10 +710,13 @@ VOID WINAPI service_main(DWORD argc, TCHAR *argv[]) int main(int argc, char **argv) { - const char *sopt = "hVvdm:p:l:f:b:s:t:"; + const char *sopt = "hVvdm:p:l:f:F::b:s:t:"; const char *method = NULL, *path = NULL; const char *log_filepath = NULL; const char *pid_filepath = QGA_PIDFILE_DEFAULT; +#ifdef CONFIG_FSFREEZE + const char *fsfreeze_hook = NULL; +#endif const char *state_dir = QGA_STATEDIR_DEFAULT; #ifdef _WIN32 const char *service = NULL; @@ -691,6 +726,9 @@ int main(int argc, char **argv) { "version", 0, NULL, 'V' }, { "logfile", 1, NULL, 'l' }, { "pidfile", 1, NULL, 'f' }, +#ifdef CONFIG_FSFREEZE + { "fsfreeze-hook", 2, NULL, 'F' }, +#endif { "verbose", 0, NULL, 'v' }, { "method", 1, NULL, 'm' }, { "path", 1, NULL, 'p' }, @@ -723,6 +761,11 @@ int main(int argc, char **argv) case 'f': pid_filepath = optarg; break; +#ifdef CONFIG_FSFREEZE + case 'F': + fsfreeze_hook = optarg ? optarg : QGA_FSFREEZE_HOOK_DEFAULT; + break; +#endif case 't': state_dir = optarg; break; @@ -786,6 +829,9 @@ int main(int argc, char **argv) s = g_malloc0(sizeof(GAState)); s->log_level = log_level; s->log_file = stderr; +#ifdef CONFIG_FSFREEZE + s->fsfreeze_hook = fsfreeze_hook; +#endif g_log_set_default_handler(ga_log, s); g_log_set_fatal_mask(NULL, G_LOG_LEVEL_ERROR); ga_enable_logging(s); From 96610da210697a1f33669d8bec0cb7b944d3a516 Mon Sep 17 00:00:00 2001 From: Tomoki Sekiyama Date: Wed, 12 Dec 2012 12:55:57 +0900 Subject: [PATCH 2267/2270] qemu-ga: sample fsfreeze hooks Adds sample hook scripts for --fsfreeze-hook option of qemu-ga. - fsfreeze-hook : execute scripts in fsfreeze-hook.d/ - fsfreeze-hook.d/mysql-flush.sh.sample : quiesce MySQL before snapshot Signed-off-by: Tomoki Sekiyama Reviewed-by: Michael Roth Signed-off-by: Michael Roth --- .gitignore | 1 + Makefile | 2 +- scripts/qemu-guest-agent/fsfreeze-hook | 33 +++++++++++ .../fsfreeze-hook.d/mysql-flush.sh.sample | 56 +++++++++++++++++++ 4 files changed, 91 insertions(+), 1 deletion(-) create mode 100755 scripts/qemu-guest-agent/fsfreeze-hook create mode 100755 scripts/qemu-guest-agent/fsfreeze-hook.d/mysql-flush.sh.sample diff --git a/.gitignore b/.gitignore index 0e3816918c..5fea65dc14 100644 --- a/.gitignore +++ b/.gitignore @@ -70,6 +70,7 @@ fsdev/virtfs-proxy-helper.pod *.tp *.vr *.d +!scripts/qemu-guest-agent/fsfreeze-hook.d *.o *.lo *.la diff --git a/Makefile b/Makefile index a7ac04b9ae..ee06448e28 100644 --- a/Makefile +++ b/Makefile @@ -232,7 +232,7 @@ clean: # avoid old build problems by removing potentially incorrect old files rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h rm -f qemu-options.def - find . -name '*.[od]' -exec rm -f {} + + find . -name '*.[od]' -type f -exec rm -f {} + rm -f *.a *.lo $(TOOLS) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~ rm -Rf .libs rm -f qemu-img-cmds.h diff --git a/scripts/qemu-guest-agent/fsfreeze-hook b/scripts/qemu-guest-agent/fsfreeze-hook new file mode 100755 index 0000000000..c27b29f282 --- /dev/null +++ b/scripts/qemu-guest-agent/fsfreeze-hook @@ -0,0 +1,33 @@ +#!/bin/sh + +# This script is executed when a guest agent receives fsfreeze-freeze and +# fsfreeze-thaw command, if it is specified in --fsfreeze-hook (-F) +# option of qemu-ga or placed in default path (/etc/qemu/fsfreeze-hook). +# When the agent receives fsfreeze-freeze request, this script is issued with +# "freeze" argument before the filesystem is frozen. And for fsfreeze-thaw +# request, it is issued with "thaw" argument after filesystem is thawed. + +LOGFILE=/var/log/qga-fsfreeze-hook.log +FSFREEZE_D=$(dirname -- "$0")/fsfreeze-hook.d + +# Check whether file $1 is a backup or rpm-generated file and should be ignored +is_ignored_file() { + case "$1" in + *~ | *.bak | *.orig | *.rpmnew | *.rpmorig | *.rpmsave | *.sample) + return 0 ;; + esac + return 1 +} + +# Iterate executables in directory "fsfreeze-hook.d" with the specified args +[ ! -d "$FSFREEZE_D" ] && exit 0 +for file in "$FSFREEZE_D"/* ; do + is_ignored_file "$file" && continue + [ -x "$file" ] || continue + printf "$(date): execute $file $@\n" >>$LOGFILE + "$file" "$@" >>$LOGFILE 2>&1 + STATUS=$? + printf "$(date): $file finished with status=$STATUS\n" >>$LOGFILE +done + +exit 0 diff --git a/scripts/qemu-guest-agent/fsfreeze-hook.d/mysql-flush.sh.sample b/scripts/qemu-guest-agent/fsfreeze-hook.d/mysql-flush.sh.sample new file mode 100755 index 0000000000..2b4fa3aeb1 --- /dev/null +++ b/scripts/qemu-guest-agent/fsfreeze-hook.d/mysql-flush.sh.sample @@ -0,0 +1,56 @@ +#!/bin/sh + +# Flush MySQL tables to the disk before the filesystem is frozen. +# At the same time, this keeps a read lock in order to avoid write accesses +# from the other clients until the filesystem is thawed. + +MYSQL="/usr/bin/mysql" +MYSQL_OPTS="-uroot" #"-prootpassword" +FIFO=/var/run/mysql-flush.fifo + +# Check mysql is installed and the server running +[ -x "$MYSQL" ] && "$MYSQL" $MYSQL_OPTS < /dev/null || exit 0 + +flush_and_wait() { + printf "FLUSH TABLES WITH READ LOCK \\G\n" + trap 'printf "$(date): $0 is killed\n">&2' HUP INT QUIT ALRM TERM + read < $FIFO + printf "UNLOCK TABLES \\G\n" + rm -f $FIFO +} + +case "$1" in + freeze) + mkfifo $FIFO || exit 1 + flush_and_wait | "$MYSQL" $MYSQL_OPTS & + # wait until every block is flushed + while [ "$(echo 'SHOW STATUS LIKE "Key_blocks_not_flushed"' |\ + "$MYSQL" $MYSQL_OPTS | tail -1 | cut -f 2)" -gt 0 ]; do + sleep 1 + done + # for InnoDB, wait until every log is flushed + INNODB_STATUS=$(mktemp /tmp/mysql-flush.XXXXXX) + [ $? -ne 0 ] && exit 2 + trap "rm -f $INNODB_STATUS; exit 1" HUP INT QUIT ALRM TERM + while :; do + printf "SHOW ENGINE INNODB STATUS \\G" |\ + "$MYSQL" $MYSQL_OPTS > $INNODB_STATUS + LOG_CURRENT=$(grep 'Log sequence number' $INNODB_STATUS |\ + tr -s ' ' | cut -d' ' -f4) + LOG_FLUSHED=$(grep 'Log flushed up to' $INNODB_STATUS |\ + tr -s ' ' | cut -d' ' -f5) + [ "$LOG_CURRENT" = "$LOG_FLUSHED" ] && break + sleep 1 + done + rm -f $INNODB_STATUS + ;; + + thaw) + [ ! -p $FIFO ] && exit 1 + echo > $FIFO + ;; + + *) + exit 1 + ;; +esac From 5e3bc735d93dd23f074b5116fd11e1ad8cd4962f Mon Sep 17 00:00:00 2001 From: Fabien Chouteau Date: Tue, 8 Jan 2013 16:30:56 +0100 Subject: [PATCH 2268/2270] Check return values from g_poll and select The current implementation of os_host_main_loop_wait() on Windows, returns 1 only when a g_poll() event occurs because the return value of select() is overridden. This is wrong as we may skip a socket event, as shown in this example: 1. select() returns 0 2. g_poll() returns 1 (socket event occurs) 3. os_host_main_loop_wait() returns 1 4. qemu_iohandler_poll() sees no socket event because select() has return before the event occurs 5. select() returns 1 6. g_poll() returns 0 (g_poll overrides select's return value) 7. os_host_main_loop_wait() returns 0 8. qemu_iohandler_poll() doesn't check for socket events because the return value of os_host_main_loop_wait() is zero. 9. goto 5 This patch use one variable for each of these return values, so we don't miss a select() event anymore. Also move the call to select() after g_poll(), this will improve latency as we don't have to go through two os_host_main_loop_wait() calls to detect a socket event. Reviewed-by: Paolo Bonzini Signed-off-by: Fabien Chouteau Signed-off-by: Anthony Liguori --- main-loop.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/main-loop.c b/main-loop.c index 54f38ae1ae..6f52ac39bc 100644 --- a/main-loop.c +++ b/main-loop.c @@ -330,7 +330,7 @@ void qemu_fd_register(int fd) static int os_host_main_loop_wait(uint32_t timeout) { GMainContext *context = g_main_context_default(); - int ret, i; + int select_ret, g_poll_ret, ret, i; PollingEntry *pe; WaitObjects *w = &wait_objects; gint poll_timeout; @@ -345,13 +345,6 @@ static int os_host_main_loop_wait(uint32_t timeout) return ret; } - if (nfds >= 0) { - ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0); - if (ret != 0) { - timeout = 0; - } - } - g_main_context_prepare(context, &max_priority); n_poll_fds = g_main_context_query(context, max_priority, &poll_timeout, poll_fds, ARRAY_SIZE(poll_fds)); @@ -367,9 +360,9 @@ static int os_host_main_loop_wait(uint32_t timeout) } qemu_mutex_unlock_iothread(); - ret = g_poll(poll_fds, n_poll_fds + w->num, poll_timeout); + g_poll_ret = g_poll(poll_fds, n_poll_fds + w->num, poll_timeout); qemu_mutex_lock_iothread(); - if (ret > 0) { + if (g_poll_ret > 0) { for (i = 0; i < w->num; i++) { w->revents[i] = poll_fds[n_poll_fds + i].revents; } @@ -384,12 +377,18 @@ static int os_host_main_loop_wait(uint32_t timeout) g_main_context_dispatch(context); } - /* If an edge-triggered socket event occurred, select will return a - * positive result on the next iteration. We do not need to do anything - * here. + /* Call select after g_poll to avoid a useless iteration and therefore + * improve socket latency. */ - return ret; + if (nfds >= 0) { + select_ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0); + if (select_ret != 0) { + timeout = 0; + } + } + + return select_ret || g_poll_ret; } #endif From 4e45deedf57c6cc7113b588282d0c16f89298aff Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 4 Jan 2013 10:37:50 +0100 Subject: [PATCH 2269/2270] rtc-test: skip year-2038 overflow check in case time_t is 32bit only Signed-off-by: Gerd Hoffmann --- tests/rtc-test.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/rtc-test.c b/tests/rtc-test.c index 02edbf5727..e7123cafbc 100644 --- a/tests/rtc-test.c +++ b/tests/rtc-test.c @@ -201,6 +201,10 @@ static void set_year_20xx(void) g_assert_cmpint(cmos_read(RTC_YEAR), ==, 0x11); g_assert_cmpint(cmos_read(RTC_CENTURY), ==, 0x20); + if (sizeof(time_t) == 4) { + return; + } + /* Set a date in 2080 to ensure there is no year-2038 overflow. */ cmos_write(RTC_REG_A, 0x76); cmos_write(RTC_YEAR, 0x80); From 067f0691277325dcce8401534d2ffc6164305021 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 4 Jan 2013 17:12:18 +0100 Subject: [PATCH 2270/2270] m48t59-test: don't touch watchdog Signed-off-by: Gerd Hoffmann --- tests/m48t59-test.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/m48t59-test.c b/tests/m48t59-test.c index 5179681ca5..d79f55472d 100644 --- a/tests/m48t59-test.c +++ b/tests/m48t59-test.c @@ -233,6 +233,11 @@ static void fuzz_registers(void) reg = (uint8_t)g_test_rand_int_range(0, 16); val = (uint8_t)g_test_rand_int_range(0, 256); + if (reg == 7) { + /* watchdog setup register, may trigger system reset, skip */ + continue; + } + cmos_write(reg, val); cmos_read(reg); }